Merge branch 'topic/error' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator into regulator-fixed

This commit is contained in:
Mark Brown
2016-11-04 12:16:38 -06:00
17972 changed files with 1243253 additions and 621219 deletions

View File

@@ -323,7 +323,7 @@ config REGULATOR_LP872X
config REGULATOR_LP873X
tristate "TI LP873X Power regulators"
depends on MFD_LP873X && OF
depends on MFD_TI_LP873X && OF
help
This driver supports LP873X voltage regulator chips. LP873X
provides two step-down converters and two general-purpose LDO
@@ -353,6 +353,14 @@ config REGULATOR_LTC3589
This enables support for the LTC3589, LTC3589-1, and LTC3589-2
8-output regulators controlled via I2C.
config REGULATOR_LTC3676
tristate "LTC3676 8-output voltage regulator"
depends on I2C
select REGMAP_I2C
help
This enables support for the LTC3676
8-output regulators controlled via I2C.
config REGULATOR_MAX14577
tristate "Maxim 14577/77836 regulator"
depends on MFD_MAX14577
@@ -498,6 +506,15 @@ config REGULATOR_MT6311
This driver supports the control of different power rails of device
through regulator interface.
config REGULATOR_MT6323
tristate "MediaTek MT6323 PMIC"
depends on MFD_MT6397
help
Say y here to select this option to enable the power regulator of
MediaTek MT6323 PMIC.
This driver supports the control of different power rails of device
through regulator interface.
config REGULATOR_MT6397
tristate "MediaTek MT6397 PMIC"
depends on MFD_MT6397
@@ -543,12 +560,12 @@ config REGULATOR_PCF50633
on PCF50633
config REGULATOR_PFUZE100
tristate "Freescale PFUZE100/PFUZE200 regulator driver"
tristate "Freescale PFUZE100/200/3000 regulator driver"
depends on I2C
select REGMAP_I2C
help
Say y here to support the regulators found on the Freescale
PFUZE100/PFUZE200 PMIC.
PFUZE100/200/3000 PMIC.
config REGULATOR_PV88060
tristate "Powerventure Semiconductor PV88060 regulator"
@@ -626,20 +643,21 @@ config REGULATOR_RC5T583
outputs which can be controlled by i2c communication.
config REGULATOR_RK808
tristate "Rockchip RK808 Power regulators"
tristate "Rockchip RK808/RK818 Power regulators"
depends on MFD_RK808
help
Select this option to enable the power regulator of ROCKCHIP
PMIC RK808.
PMIC RK808 and RK818.
This driver supports the control of different power rails of device
through regulator interface. The device supports multiple DCDC/LDO
outputs which can be controlled by i2c communication.
config REGULATOR_RN5T618
tristate "Ricoh RN5T618 voltage regulators"
tristate "Ricoh RN5T567/618 voltage regulators"
depends on MFD_RN5T618
help
Say y here to support the regulators found on Ricoh RN5T618 PMIC.
Say y here to support the regulators found on Ricoh RN5T567 or
RN5T618 PMIC.
config REGULATOR_RT5033
tristate "Richtek RT5033 Regulators"
@@ -810,7 +828,7 @@ config REGULATOR_TPS65912
This driver supports TPS65912 voltage regulator chip.
config REGULATOR_TPS80031
tristate "TI TPS80031/TPS80032 power regualtor driver"
tristate "TI TPS80031/TPS80032 power regulator driver"
depends on MFD_TPS80031
help
TPS80031/ TPS80032 Fully Integrated Power Management with Power

View File

@@ -47,6 +47,7 @@ obj-$(CONFIG_REGULATOR_LP8788) += lp8788-buck.o
obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o
obj-$(CONFIG_REGULATOR_LP8755) += lp8755.o
obj-$(CONFIG_REGULATOR_LTC3589) += ltc3589.o
obj-$(CONFIG_REGULATOR_LTC3676) += ltc3676.o
obj-$(CONFIG_REGULATOR_MAX14577) += max14577-regulator.o
obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o
@@ -65,6 +66,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o
obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o
obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_SMD_RPM) += qcom_smd-regulator.o

View File

@@ -25,6 +25,456 @@
#include <linux/mfd/abx500/ab8500.h>
#include <linux/regulator/ab8500.h>
static struct regulator_consumer_supply ab8500_vaux1_consumers[] = {
/* Main display, u8500 R3 uib */
REGULATOR_SUPPLY("vddi", "mcde_disp_sony_acx424akp.0"),
/* Main display, u8500 uib and ST uib */
REGULATOR_SUPPLY("vdd1", "samsung_s6d16d0.0"),
/* Secondary display, ST uib */
REGULATOR_SUPPLY("vdd1", "samsung_s6d16d0.1"),
/* SFH7741 proximity sensor */
REGULATOR_SUPPLY("vcc", "gpio-keys.0"),
/* BH1780GLS ambient light sensor */
REGULATOR_SUPPLY("vcc", "2-0029"),
/* lsm303dlh accelerometer */
REGULATOR_SUPPLY("vdd", "2-0018"),
/* lsm303dlhc accelerometer */
REGULATOR_SUPPLY("vdd", "2-0019"),
/* lsm303dlh magnetometer */
REGULATOR_SUPPLY("vdd", "2-001e"),
/* Rohm BU21013 Touchscreen devices */
REGULATOR_SUPPLY("avdd", "3-005c"),
REGULATOR_SUPPLY("avdd", "3-005d"),
/* Synaptics RMI4 Touchscreen device */
REGULATOR_SUPPLY("vdd", "3-004b"),
/* L3G4200D Gyroscope device */
REGULATOR_SUPPLY("vdd", "2-0068"),
/* Ambient light sensor device */
REGULATOR_SUPPLY("vdd", "3-0029"),
/* Pressure sensor device */
REGULATOR_SUPPLY("vdd", "2-005c"),
/* Cypress TrueTouch Touchscreen device */
REGULATOR_SUPPLY("vcpin", "spi8.0"),
/* Camera device */
REGULATOR_SUPPLY("vaux12v5", "mmio_camera"),
};
static struct regulator_consumer_supply ab8500_vaux2_consumers[] = {
/* On-board eMMC power */
REGULATOR_SUPPLY("vmmc", "sdi4"),
/* AB8500 audio codec */
REGULATOR_SUPPLY("vcc-N2158", "ab8500-codec.0"),
/* AB8500 accessory detect 1 */
REGULATOR_SUPPLY("vcc-N2158", "ab8500-acc-det.0"),
/* AB8500 Tv-out device */
REGULATOR_SUPPLY("vcc-N2158", "mcde_tv_ab8500.4"),
/* AV8100 HDMI device */
REGULATOR_SUPPLY("vcc-N2158", "av8100_hdmi.3"),
};
static struct regulator_consumer_supply ab8500_vaux3_consumers[] = {
REGULATOR_SUPPLY("v-SD-STM", "stm"),
/* External MMC slot power */
REGULATOR_SUPPLY("vmmc", "sdi0"),
};
static struct regulator_consumer_supply ab8500_vtvout_consumers[] = {
/* TV-out DENC supply */
REGULATOR_SUPPLY("vtvout", "ab8500-denc.0"),
/* Internal general-purpose ADC */
REGULATOR_SUPPLY("vddadc", "ab8500-gpadc.0"),
/* ADC for charger */
REGULATOR_SUPPLY("vddadc", "ab8500-charger.0"),
/* AB8500 Tv-out device */
REGULATOR_SUPPLY("vtvout", "mcde_tv_ab8500.4"),
};
static struct regulator_consumer_supply ab8500_vaud_consumers[] = {
/* AB8500 audio-codec main supply */
REGULATOR_SUPPLY("vaud", "ab8500-codec.0"),
};
static struct regulator_consumer_supply ab8500_vamic1_consumers[] = {
/* AB8500 audio-codec Mic1 supply */
REGULATOR_SUPPLY("vamic1", "ab8500-codec.0"),
};
static struct regulator_consumer_supply ab8500_vamic2_consumers[] = {
/* AB8500 audio-codec Mic2 supply */
REGULATOR_SUPPLY("vamic2", "ab8500-codec.0"),
};
static struct regulator_consumer_supply ab8500_vdmic_consumers[] = {
/* AB8500 audio-codec DMic supply */
REGULATOR_SUPPLY("vdmic", "ab8500-codec.0"),
};
static struct regulator_consumer_supply ab8500_vintcore_consumers[] = {
/* SoC core supply, no device */
REGULATOR_SUPPLY("v-intcore", NULL),
/* USB Transceiver */
REGULATOR_SUPPLY("vddulpivio18", "ab8500-usb.0"),
/* Handled by abx500 clk driver */
REGULATOR_SUPPLY("v-intcore", "abx500-clk.0"),
};
static struct regulator_consumer_supply ab8500_vana_consumers[] = {
/* DB8500 DSI */
REGULATOR_SUPPLY("vdddsi1v2", "mcde"),
REGULATOR_SUPPLY("vdddsi1v2", "b2r2_core"),
REGULATOR_SUPPLY("vdddsi1v2", "b2r2_1_core"),
REGULATOR_SUPPLY("vdddsi1v2", "dsilink.0"),
REGULATOR_SUPPLY("vdddsi1v2", "dsilink.1"),
REGULATOR_SUPPLY("vdddsi1v2", "dsilink.2"),
/* DB8500 CSI */
REGULATOR_SUPPLY("vddcsi1v2", "mmio_camera"),
};
/* ab8500 regulator register initialization */
static struct ab8500_regulator_reg_init ab8500_reg_init[] = {
/*
* VanaRequestCtrl = HP/LP depending on VxRequest
* VextSupply1RequestCtrl = HP/LP depending on VxRequest
*/
INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL2, 0xf0, 0x00),
/*
* VextSupply2RequestCtrl = HP/LP depending on VxRequest
* VextSupply3RequestCtrl = HP/LP depending on VxRequest
* Vaux1RequestCtrl = HP/LP depending on VxRequest
* Vaux2RequestCtrl = HP/LP depending on VxRequest
*/
INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL3, 0xff, 0x00),
/*
* Vaux3RequestCtrl = HP/LP depending on VxRequest
* SwHPReq = Control through SWValid disabled
*/
INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL4, 0x07, 0x00),
/*
* VanaSysClkReq1HPValid = disabled
* Vaux1SysClkReq1HPValid = disabled
* Vaux2SysClkReq1HPValid = disabled
* Vaux3SysClkReq1HPValid = disabled
*/
INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID1, 0xe8, 0x00),
/*
* VextSupply1SysClkReq1HPValid = disabled
* VextSupply2SysClkReq1HPValid = disabled
* VextSupply3SysClkReq1HPValid = SysClkReq1 controlled
*/
INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID2, 0x70, 0x40),
/*
* VanaHwHPReq1Valid = disabled
* Vaux1HwHPreq1Valid = disabled
* Vaux2HwHPReq1Valid = disabled
* Vaux3HwHPReqValid = disabled
*/
INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID1, 0xe8, 0x00),
/*
* VextSupply1HwHPReq1Valid = disabled
* VextSupply2HwHPReq1Valid = disabled
* VextSupply3HwHPReq1Valid = disabled
*/
INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID2, 0x07, 0x00),
/*
* VanaHwHPReq2Valid = disabled
* Vaux1HwHPReq2Valid = disabled
* Vaux2HwHPReq2Valid = disabled
* Vaux3HwHPReq2Valid = disabled
*/
INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID1, 0xe8, 0x00),
/*
* VextSupply1HwHPReq2Valid = disabled
* VextSupply2HwHPReq2Valid = disabled
* VextSupply3HwHPReq2Valid = HWReq2 controlled
*/
INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID2, 0x07, 0x04),
/*
* VanaSwHPReqValid = disabled
* Vaux1SwHPReqValid = disabled
*/
INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID1, 0xa0, 0x00),
/*
* Vaux2SwHPReqValid = disabled
* Vaux3SwHPReqValid = disabled
* VextSupply1SwHPReqValid = disabled
* VextSupply2SwHPReqValid = disabled
* VextSupply3SwHPReqValid = disabled
*/
INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID2, 0x1f, 0x00),
/*
* SysClkReq2Valid1 = SysClkReq2 controlled
* SysClkReq3Valid1 = disabled
* SysClkReq4Valid1 = SysClkReq4 controlled
* SysClkReq5Valid1 = disabled
* SysClkReq6Valid1 = SysClkReq6 controlled
* SysClkReq7Valid1 = disabled
* SysClkReq8Valid1 = disabled
*/
INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID1, 0xfe, 0x2a),
/*
* SysClkReq2Valid2 = disabled
* SysClkReq3Valid2 = disabled
* SysClkReq4Valid2 = disabled
* SysClkReq5Valid2 = disabled
* SysClkReq6Valid2 = SysClkReq6 controlled
* SysClkReq7Valid2 = disabled
* SysClkReq8Valid2 = disabled
*/
INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID2, 0xfe, 0x20),
/*
* VTVoutEna = disabled
* Vintcore12Ena = disabled
* Vintcore12Sel = 1.25 V
* Vintcore12LP = inactive (HP)
* VTVoutLP = inactive (HP)
*/
INIT_REGULATOR_REGISTER(AB8500_REGUMISC1, 0xfe, 0x10),
/*
* VaudioEna = disabled
* VdmicEna = disabled
* Vamic1Ena = disabled
* Vamic2Ena = disabled
*/
INIT_REGULATOR_REGISTER(AB8500_VAUDIOSUPPLY, 0x1e, 0x00),
/*
* Vamic1_dzout = high-Z when Vamic1 is disabled
* Vamic2_dzout = high-Z when Vamic2 is disabled
*/
INIT_REGULATOR_REGISTER(AB8500_REGUCTRL1VAMIC, 0x03, 0x00),
/*
* VPll = Hw controlled (NOTE! PRCMU bits)
* VanaRegu = force off
*/
INIT_REGULATOR_REGISTER(AB8500_VPLLVANAREGU, 0x0f, 0x02),
/*
* VrefDDREna = disabled
* VrefDDRSleepMode = inactive (no pulldown)
*/
INIT_REGULATOR_REGISTER(AB8500_VREFDDR, 0x03, 0x00),
/*
* VextSupply1Regu = force LP
* VextSupply2Regu = force OFF
* VextSupply3Regu = force HP (-> STBB2=LP and TPS=LP)
* ExtSupply2Bypass = ExtSupply12LPn ball is 0 when Ena is 0
* ExtSupply3Bypass = ExtSupply3LPn ball is 0 when Ena is 0
*/
INIT_REGULATOR_REGISTER(AB8500_EXTSUPPLYREGU, 0xff, 0x13),
/*
* Vaux1Regu = force HP
* Vaux2Regu = force off
*/
INIT_REGULATOR_REGISTER(AB8500_VAUX12REGU, 0x0f, 0x01),
/*
* Vaux3Regu = force off
*/
INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3REGU, 0x03, 0x00),
/*
* Vaux1Sel = 2.8 V
*/
INIT_REGULATOR_REGISTER(AB8500_VAUX1SEL, 0x0f, 0x0C),
/*
* Vaux2Sel = 2.9 V
*/
INIT_REGULATOR_REGISTER(AB8500_VAUX2SEL, 0x0f, 0x0d),
/*
* Vaux3Sel = 2.91 V
*/
INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3SEL, 0x07, 0x07),
/*
* VextSupply12LP = disabled (no LP)
*/
INIT_REGULATOR_REGISTER(AB8500_REGUCTRL2SPARE, 0x01, 0x00),
/*
* Vaux1Disch = short discharge time
* Vaux2Disch = short discharge time
* Vaux3Disch = short discharge time
* Vintcore12Disch = short discharge time
* VTVoutDisch = short discharge time
* VaudioDisch = short discharge time
*/
INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH, 0xfc, 0x00),
/*
* VanaDisch = short discharge time
* VdmicPullDownEna = pulldown disabled when Vdmic is disabled
* VdmicDisch = short discharge time
*/
INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH2, 0x16, 0x00),
};
/* AB8500 regulators */
static struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
/* supplies to the display/camera */
[AB8500_LDO_AUX1] = {
.supply_regulator = "ab8500-ext-supply3",
.constraints = {
.name = "V-DISPLAY",
.min_uV = 2800000,
.max_uV = 3300000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
REGULATOR_CHANGE_STATUS,
.boot_on = 1, /* display is on at boot */
},
.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux1_consumers),
.consumer_supplies = ab8500_vaux1_consumers,
},
/* supplies to the on-board eMMC */
[AB8500_LDO_AUX2] = {
.supply_regulator = "ab8500-ext-supply3",
.constraints = {
.name = "V-eMMC1",
.min_uV = 1100000,
.max_uV = 3300000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
REGULATOR_CHANGE_STATUS |
REGULATOR_CHANGE_MODE,
.valid_modes_mask = REGULATOR_MODE_NORMAL |
REGULATOR_MODE_IDLE,
},
.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux2_consumers),
.consumer_supplies = ab8500_vaux2_consumers,
},
/* supply for VAUX3, supplies to SDcard slots */
[AB8500_LDO_AUX3] = {
.supply_regulator = "ab8500-ext-supply3",
.constraints = {
.name = "V-MMC-SD",
.min_uV = 1100000,
.max_uV = 3300000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
REGULATOR_CHANGE_STATUS |
REGULATOR_CHANGE_MODE,
.valid_modes_mask = REGULATOR_MODE_NORMAL |
REGULATOR_MODE_IDLE,
},
.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux3_consumers),
.consumer_supplies = ab8500_vaux3_consumers,
},
/* supply for tvout, gpadc, TVOUT LDO */
[AB8500_LDO_TVOUT] = {
.constraints = {
.name = "V-TVOUT",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = ARRAY_SIZE(ab8500_vtvout_consumers),
.consumer_supplies = ab8500_vtvout_consumers,
},
/* supply for ab8500-vaudio, VAUDIO LDO */
[AB8500_LDO_AUDIO] = {
.constraints = {
.name = "V-AUD",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = ARRAY_SIZE(ab8500_vaud_consumers),
.consumer_supplies = ab8500_vaud_consumers,
},
/* supply for v-anamic1 VAMic1-LDO */
[AB8500_LDO_ANAMIC1] = {
.constraints = {
.name = "V-AMIC1",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = ARRAY_SIZE(ab8500_vamic1_consumers),
.consumer_supplies = ab8500_vamic1_consumers,
},
/* supply for v-amic2, VAMIC2 LDO, reuse constants for AMIC1 */
[AB8500_LDO_ANAMIC2] = {
.constraints = {
.name = "V-AMIC2",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = ARRAY_SIZE(ab8500_vamic2_consumers),
.consumer_supplies = ab8500_vamic2_consumers,
},
/* supply for v-dmic, VDMIC LDO */
[AB8500_LDO_DMIC] = {
.constraints = {
.name = "V-DMIC",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = ARRAY_SIZE(ab8500_vdmic_consumers),
.consumer_supplies = ab8500_vdmic_consumers,
},
/* supply for v-intcore12, VINTCORE12 LDO */
[AB8500_LDO_INTCORE] = {
.constraints = {
.name = "V-INTCORE",
.min_uV = 1250000,
.max_uV = 1350000,
.input_uV = 1800000,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
REGULATOR_CHANGE_STATUS |
REGULATOR_CHANGE_MODE |
REGULATOR_CHANGE_DRMS,
.valid_modes_mask = REGULATOR_MODE_NORMAL |
REGULATOR_MODE_IDLE,
},
.num_consumer_supplies = ARRAY_SIZE(ab8500_vintcore_consumers),
.consumer_supplies = ab8500_vintcore_consumers,
},
/* supply for U8500 CSI-DSI, VANA LDO */
[AB8500_LDO_ANA] = {
.constraints = {
.name = "V-CSI-DSI",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = ARRAY_SIZE(ab8500_vana_consumers),
.consumer_supplies = ab8500_vana_consumers,
},
};
/* supply for VextSupply3 */
static struct regulator_consumer_supply ab8500_ext_supply3_consumers[] = {
/* SIM supply for 3 V SIM cards */
REGULATOR_SUPPLY("vinvsim", "sim-detect.0"),
};
/*
* AB8500 external regulators
*/
static struct regulator_init_data ab8500_ext_regulators[] = {
/* fixed Vbat supplies VSMPS1_EXT_1V8 */
[AB8500_EXT_SUPPLY1] = {
.constraints = {
.name = "ab8500-ext-supply1",
.min_uV = 1800000,
.max_uV = 1800000,
.initial_mode = REGULATOR_MODE_IDLE,
.boot_on = 1,
.always_on = 1,
},
},
/* fixed Vbat supplies VSMPS2_EXT_1V36 and VSMPS5_EXT_1V15 */
[AB8500_EXT_SUPPLY2] = {
.constraints = {
.name = "ab8500-ext-supply2",
.min_uV = 1360000,
.max_uV = 1360000,
},
},
/* fixed Vbat supplies VSMPS3_EXT_3V4 and VSMPS4_EXT_3V4 */
[AB8500_EXT_SUPPLY3] = {
.constraints = {
.name = "ab8500-ext-supply3",
.min_uV = 3400000,
.max_uV = 3400000,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
.boot_on = 1,
},
.num_consumer_supplies =
ARRAY_SIZE(ab8500_ext_supply3_consumers),
.consumer_supplies = ab8500_ext_supply3_consumers,
},
};
static struct ab8500_regulator_platform_data ab8500_regulator_plat_data = {
.reg_init = ab8500_reg_init,
.num_reg_init = ARRAY_SIZE(ab8500_reg_init),
.regulator = ab8500_regulators,
.num_regulator = ARRAY_SIZE(ab8500_regulators),
.ext_regulator = ab8500_ext_regulators,
.num_ext_regulator = ARRAY_SIZE(ab8500_ext_regulators),
};
/**
* struct ab8500_ext_regulator_info - ab8500 regulator information
* @dev: device pointer
@@ -344,8 +794,7 @@ static struct of_regulator_match ab8500_ext_regulator_match[] = {
static int ab8500_ext_regulator_probe(struct platform_device *pdev)
{
struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
struct ab8500_platform_data *ppdata;
struct ab8500_regulator_platform_data *pdata;
struct ab8500_regulator_platform_data *pdata = &ab8500_regulator_plat_data;
struct device_node *np = pdev->dev.of_node;
struct regulator_config config = { };
int i, err;
@@ -366,18 +815,6 @@ static int ab8500_ext_regulator_probe(struct platform_device *pdev)
return -EINVAL;
}
ppdata = dev_get_platdata(ab8500->dev);
if (!ppdata) {
dev_err(&pdev->dev, "null parent pdata\n");
return -EINVAL;
}
pdata = ppdata->regulator;
if (!pdata) {
dev_err(&pdev->dev, "null pdata\n");
return -EINVAL;
}
/* make sure the platform data has the correct size */
if (pdata->num_ext_regulator != ARRAY_SIZE(ab8500_ext_regulator_info)) {
dev_err(&pdev->dev, "Configuration error: size mismatch.\n");

View File

@@ -395,12 +395,6 @@ static int act8865_pdata_from_dt(struct device *dev,
struct act8865_regulator_data *regulator;
struct of_regulator_match *matches;
np = of_get_child_by_name(dev->of_node, "regulators");
if (!np) {
dev_err(dev, "missing 'regulators' subnode in DT\n");
return -EINVAL;
}
switch (type) {
case ACT8600:
matches = act8600_matches;
@@ -419,6 +413,12 @@ static int act8865_pdata_from_dt(struct device *dev,
return -EINVAL;
}
np = of_get_child_by_name(dev->of_node, "regulators");
if (!np) {
dev_err(dev, "missing 'regulators' subnode in DT\n");
return -EINVAL;
}
matched = of_regulator_match(dev, np, matches, num_matches);
of_node_put(np);
if (matched <= 0)

View File

@@ -296,7 +296,7 @@ static int anatop_regulator_probe(struct platform_device *pdev)
if (!sreg->sel && !strcmp(sreg->name, "vddpu"))
sreg->sel = 22;
if (!sreg->sel) {
if (!sreg->bypass && !sreg->sel) {
dev_err(&pdev->dev, "Failed to read a valid default voltage selector.\n");
return -EINVAL;
}

View File

@@ -36,6 +36,8 @@
#define AXP20X_FREQ_DCDC_MASK 0x0f
#define AXP22X_MISC_N_VBUSEN_FUNC BIT(4)
#define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
_vmask, _ereg, _emask, _enable_val, _disable_val) \
[_family##_##_id] = { \
@@ -230,9 +232,125 @@ static const struct regulator_desc axp22x_regulators[] = {
AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000),
};
static const struct regulator_desc axp22x_drivevbus_regulator = {
.name = "drivevbus",
.supply_name = "drivevbus",
.of_match = of_match_ptr("drivevbus"),
.regulators_node = of_match_ptr("regulators"),
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.enable_reg = AXP20X_VBUS_IPSOUT_MGMT,
.enable_mask = BIT(2),
.ops = &axp20x_ops_sw,
};
static const struct regulator_linear_range axp806_dcdca_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0x0, 0x32, 10000),
REGULATOR_LINEAR_RANGE(1120000, 0x33, 0x47, 20000),
};
static const struct regulator_linear_range axp806_dcdcd_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0x0, 0x2d, 20000),
REGULATOR_LINEAR_RANGE(1600000, 0x2e, 0x3f, 100000),
};
static const struct regulator_linear_range axp806_cldo2_ranges[] = {
REGULATOR_LINEAR_RANGE(700000, 0x0, 0x1a, 100000),
REGULATOR_LINEAR_RANGE(3400000, 0x1b, 0x1f, 200000),
};
static const struct regulator_desc axp806_regulators[] = {
AXP_DESC_RANGES(AXP806, DCDCA, "dcdca", "vina", axp806_dcdca_ranges,
72, AXP806_DCDCA_V_CTRL, 0x7f, AXP806_PWR_OUT_CTRL1,
BIT(0)),
AXP_DESC(AXP806, DCDCB, "dcdcb", "vinb", 1000, 2550, 50,
AXP806_DCDCB_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(1)),
AXP_DESC_RANGES(AXP806, DCDCC, "dcdcc", "vinc", axp806_dcdca_ranges,
72, AXP806_DCDCC_V_CTRL, 0x7f, AXP806_PWR_OUT_CTRL1,
BIT(2)),
AXP_DESC_RANGES(AXP806, DCDCD, "dcdcd", "vind", axp806_dcdcd_ranges,
64, AXP806_DCDCD_V_CTRL, 0x3f, AXP806_PWR_OUT_CTRL1,
BIT(3)),
AXP_DESC(AXP806, DCDCE, "dcdce", "vine", 1100, 3400, 100,
AXP806_DCDCB_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(4)),
AXP_DESC(AXP806, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
AXP806_ALDO1_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(5)),
AXP_DESC(AXP806, ALDO2, "aldo2", "aldoin", 700, 3400, 100,
AXP806_ALDO2_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(6)),
AXP_DESC(AXP806, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
AXP806_ALDO3_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(7)),
AXP_DESC(AXP806, BLDO1, "bldo1", "bldoin", 700, 1900, 100,
AXP806_BLDO1_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(0)),
AXP_DESC(AXP806, BLDO2, "bldo2", "bldoin", 700, 1900, 100,
AXP806_BLDO2_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(1)),
AXP_DESC(AXP806, BLDO3, "bldo3", "bldoin", 700, 1900, 100,
AXP806_BLDO3_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(2)),
AXP_DESC(AXP806, BLDO4, "bldo4", "bldoin", 700, 1900, 100,
AXP806_BLDO4_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(3)),
AXP_DESC(AXP806, CLDO1, "cldo1", "cldoin", 700, 3300, 100,
AXP806_CLDO1_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2, BIT(4)),
AXP_DESC_RANGES(AXP806, CLDO2, "cldo2", "cldoin", axp806_cldo2_ranges,
32, AXP806_CLDO2_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2,
BIT(5)),
AXP_DESC(AXP806, CLDO3, "cldo3", "cldoin", 700, 3300, 100,
AXP806_CLDO3_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2, BIT(6)),
AXP_DESC_SW(AXP806, SW, "sw", "swin", AXP806_PWR_OUT_CTRL2, BIT(7)),
};
static const struct regulator_linear_range axp809_dcdc4_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0x0, 0x2f, 20000),
REGULATOR_LINEAR_RANGE(1800000, 0x30, 0x38, 100000),
};
static const struct regulator_desc axp809_regulators[] = {
AXP_DESC(AXP809, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(1)),
AXP_DESC(AXP809, DCDC2, "dcdc2", "vin2", 600, 1540, 20,
AXP22X_DCDC2_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(2)),
AXP_DESC(AXP809, DCDC3, "dcdc3", "vin3", 600, 1860, 20,
AXP22X_DCDC3_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(3)),
AXP_DESC_RANGES(AXP809, DCDC4, "dcdc4", "vin4", axp809_dcdc4_ranges,
57, AXP22X_DCDC4_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1,
BIT(4)),
AXP_DESC(AXP809, DCDC5, "dcdc5", "vin5", 1000, 2550, 50,
AXP22X_DCDC5_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(5)),
/* secondary switchable output of DCDC1 */
AXP_DESC_SW(AXP809, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
BIT(7)),
/* LDO regulator internally chained to DCDC5 */
AXP_DESC(AXP809, DC5LDO, "dc5ldo", NULL, 700, 1400, 100,
AXP22X_DC5LDO_V_OUT, 0x7, AXP22X_PWR_OUT_CTRL1, BIT(0)),
AXP_DESC(AXP809, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(6)),
AXP_DESC(AXP809, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(7)),
AXP_DESC(AXP809, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
AXP_DESC_RANGES(AXP809, DLDO1, "dldo1", "dldoin", axp806_cldo2_ranges,
32, AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
BIT(3)),
AXP_DESC(AXP809, DLDO2, "dldo2", "dldoin", 700, 3300, 100,
AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(4)),
AXP_DESC(AXP809, ELDO1, "eldo1", "eldoin", 700, 3300, 100,
AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
AXP_DESC(AXP809, ELDO2, "eldo2", "eldoin", 700, 3300, 100,
AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
AXP_DESC(AXP809, ELDO3, "eldo3", "eldoin", 700, 3300, 100,
AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
AXP_DESC_IO(AXP809, LDO_IO0, "ldo_io0", "ips", 700, 3300, 100,
AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
AXP_DESC_IO(AXP809, LDO_IO1, "ldo_io1", "ips", 700, 3300, 100,
AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
AXP_DESC_FIXED(AXP809, RTC_LDO, "rtc_ldo", "ips", 1800),
AXP_DESC_SW(AXP809, SW, "sw", "swin", AXP22X_PWR_OUT_CTRL2, BIT(6)),
};
static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
{
struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
unsigned int reg = AXP20X_DCDC_FREQ;
u32 min, max, def, step;
switch (axp20x->variant) {
@@ -243,8 +361,17 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
def = 1500;
step = 75;
break;
case AXP806_ID:
/*
* AXP806 DCDC work frequency setting has the same range and
* step as AXP22X, but at a different register.
* Fall through to the check below.
* (See include/linux/mfd/axp20x.h)
*/
reg = AXP806_DCDC_FREQ_CTRL;
case AXP221_ID:
case AXP223_ID:
case AXP809_ID:
min = 1800;
max = 4050;
def = 3000;
@@ -273,7 +400,7 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
dcdcfreq = (dcdcfreq - min) / step;
return regmap_update_bits(axp20x->regmap, AXP20X_DCDC_FREQ,
return regmap_update_bits(axp20x->regmap, reg,
AXP20X_FREQ_DCDC_MASK, dcdcfreq);
}
@@ -307,6 +434,7 @@ static int axp20x_regulator_parse_dt(struct platform_device *pdev)
static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode)
{
struct axp20x_dev *axp20x = rdev_get_drvdata(rdev);
unsigned int reg = AXP20X_DCDC_MODE;
unsigned int mask;
switch (axp20x->variant) {
@@ -322,8 +450,16 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work
workmode <<= ffs(mask) - 1;
break;
case AXP806_ID:
reg = AXP806_DCDC_MODE_CTRL2;
/*
* AXP806 DCDC regulator IDs have the same range as AXP22X.
* Fall through to the check below.
* (See include/linux/mfd/axp20x.h)
*/
case AXP221_ID:
case AXP223_ID:
case AXP809_ID:
if (id < AXP22X_DCDC1 || id > AXP22X_DCDC5)
return -EINVAL;
@@ -337,7 +473,34 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work
return -EINVAL;
}
return regmap_update_bits(rdev->regmap, AXP20X_DCDC_MODE, mask, workmode);
return regmap_update_bits(rdev->regmap, reg, mask, workmode);
}
/*
* This function checks whether a regulator is part of a poly-phase
* output setup based on the registers settings. Returns true if it is.
*/
static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id)
{
u32 reg = 0;
/* Only AXP806 has poly-phase outputs */
if (axp20x->variant != AXP806_ID)
return false;
regmap_read(axp20x->regmap, AXP806_DCDC_MODE_CTRL2, &reg);
switch (id) {
case AXP806_DCDCB:
return (((reg & GENMASK(7, 6)) == BIT(6)) ||
((reg & GENMASK(7, 6)) == BIT(7)));
case AXP806_DCDCC:
return ((reg & GENMASK(7, 6)) == BIT(7));
case AXP806_DCDCE:
return !!(reg & BIT(5));
}
return false;
}
static int axp20x_regulator_probe(struct platform_device *pdev)
@@ -352,8 +515,9 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
};
int ret, i, nregulators;
u32 workmode;
const char *axp22x_dc1_name = axp22x_regulators[AXP22X_DCDC1].name;
const char *axp22x_dc5_name = axp22x_regulators[AXP22X_DCDC5].name;
const char *dcdc1_name = axp22x_regulators[AXP22X_DCDC1].name;
const char *dcdc5_name = axp22x_regulators[AXP22X_DCDC5].name;
bool drivevbus = false;
switch (axp20x->variant) {
case AXP202_ID:
@@ -365,6 +529,16 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
case AXP223_ID:
regulators = axp22x_regulators;
nregulators = AXP22X_REG_ID_MAX;
drivevbus = of_property_read_bool(pdev->dev.parent->of_node,
"x-powers,drive-vbus-en");
break;
case AXP806_ID:
regulators = axp806_regulators;
nregulators = AXP806_REG_ID_MAX;
break;
case AXP809_ID:
regulators = axp809_regulators;
nregulators = AXP809_REG_ID_MAX;
break;
default:
dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
@@ -379,6 +553,14 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
const struct regulator_desc *desc = &regulators[i];
struct regulator_desc *new_desc;
/*
* If this regulator is a slave in a poly-phase setup,
* skip it, as its controls are bound to the master
* regulator and won't work.
*/
if (axp20x_is_polyphase_slave(axp20x, i))
continue;
/*
* Regulators DC1SW and DC5LDO are connected internally,
* so we have to handle their supply names separately.
@@ -388,22 +570,22 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
* part of this loop to see where we save the DT defined
* name.
*/
if (regulators == axp22x_regulators) {
if (i == AXP22X_DC1SW) {
new_desc = devm_kzalloc(&pdev->dev,
sizeof(*desc),
GFP_KERNEL);
*new_desc = regulators[i];
new_desc->supply_name = axp22x_dc1_name;
desc = new_desc;
} else if (i == AXP22X_DC5LDO) {
new_desc = devm_kzalloc(&pdev->dev,
sizeof(*desc),
GFP_KERNEL);
*new_desc = regulators[i];
new_desc->supply_name = axp22x_dc5_name;
desc = new_desc;
}
if ((regulators == axp22x_regulators && i == AXP22X_DC1SW) ||
(regulators == axp809_regulators && i == AXP809_DC1SW)) {
new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
GFP_KERNEL);
*new_desc = regulators[i];
new_desc->supply_name = dcdc1_name;
desc = new_desc;
}
if ((regulators == axp22x_regulators && i == AXP22X_DC5LDO) ||
(regulators == axp809_regulators && i == AXP809_DC5LDO)) {
new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
GFP_KERNEL);
*new_desc = regulators[i];
new_desc->supply_name = dcdc5_name;
desc = new_desc;
}
rdev = devm_regulator_register(&pdev->dev, desc, &config);
@@ -426,16 +608,29 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
/*
* Save AXP22X DCDC1 / DCDC5 regulator names for later.
*/
if (regulators == axp22x_regulators) {
/* Can we use rdev->constraints->name instead? */
if (i == AXP22X_DCDC1)
of_property_read_string(rdev->dev.of_node,
"regulator-name",
&axp22x_dc1_name);
else if (i == AXP22X_DCDC5)
of_property_read_string(rdev->dev.of_node,
"regulator-name",
&axp22x_dc5_name);
if ((regulators == axp22x_regulators && i == AXP22X_DCDC1) ||
(regulators == axp809_regulators && i == AXP809_DCDC1))
of_property_read_string(rdev->dev.of_node,
"regulator-name",
&dcdc1_name);
if ((regulators == axp22x_regulators && i == AXP22X_DCDC5) ||
(regulators == axp809_regulators && i == AXP809_DCDC5))
of_property_read_string(rdev->dev.of_node,
"regulator-name",
&dcdc5_name);
}
if (drivevbus) {
/* Change N_VBUSEN sense pin to DRIVEVBUS output pin */
regmap_update_bits(axp20x->regmap, AXP20X_OVER_TMP,
AXP22X_MISC_N_VBUSEN_FUNC, 0);
rdev = devm_regulator_register(&pdev->dev,
&axp22x_drivevbus_regulator,
&config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "Failed to register drivevbus\n");
return PTR_ERR(rdev);
}
}

View File

@@ -679,24 +679,6 @@ static int drms_uA_update(struct regulator_dev *rdev)
!rdev->desc->ops->set_load)
return -EINVAL;
/* get output voltage */
output_uV = _regulator_get_voltage(rdev);
if (output_uV <= 0) {
rdev_err(rdev, "invalid output voltage found\n");
return -EINVAL;
}
/* get input voltage */
input_uV = 0;
if (rdev->supply)
input_uV = regulator_get_voltage(rdev->supply);
if (input_uV <= 0)
input_uV = rdev->constraints->input_uV;
if (input_uV <= 0) {
rdev_err(rdev, "invalid input voltage found\n");
return -EINVAL;
}
/* calc total requested load */
list_for_each_entry(sibling, &rdev->consumer_list, list)
current_uA += sibling->uA_load;
@@ -709,6 +691,24 @@ static int drms_uA_update(struct regulator_dev *rdev)
if (err < 0)
rdev_err(rdev, "failed to set load %d\n", current_uA);
} else {
/* get output voltage */
output_uV = _regulator_get_voltage(rdev);
if (output_uV <= 0) {
rdev_err(rdev, "invalid output voltage found\n");
return -EINVAL;
}
/* get input voltage */
input_uV = 0;
if (rdev->supply)
input_uV = regulator_get_voltage(rdev->supply);
if (input_uV <= 0)
input_uV = rdev->constraints->input_uV;
if (input_uV <= 0) {
rdev_err(rdev, "invalid input voltage found\n");
return -EINVAL;
}
/* now get the optimum mode for our new total regulator load */
mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV,
output_uV, current_uA);
@@ -2508,33 +2508,6 @@ int regulator_is_enabled(struct regulator *regulator)
}
EXPORT_SYMBOL_GPL(regulator_is_enabled);
/**
* regulator_can_change_voltage - check if regulator can change voltage
* @regulator: regulator source
*
* Returns positive if the regulator driver backing the source/client
* can change its voltage, false otherwise. Useful for detecting fixed
* or dummy regulators and disabling voltage change logic in the client
* driver.
*/
int regulator_can_change_voltage(struct regulator *regulator)
{
struct regulator_dev *rdev = regulator->rdev;
if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) {
if (rdev->desc->n_voltages - rdev->desc->linear_min_sel > 1)
return 1;
if (rdev->desc->continuous_voltage_range &&
rdev->constraints->min_uV && rdev->constraints->max_uV &&
rdev->constraints->min_uV != rdev->constraints->max_uV)
return 1;
}
return 0;
}
EXPORT_SYMBOL_GPL(regulator_can_change_voltage);
/**
* regulator_count_voltages - count regulator_list_voltage() selectors
* @regulator: regulator source
@@ -2770,6 +2743,24 @@ static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev,
return ret;
}
static int _regulator_set_voltage_time(struct regulator_dev *rdev,
int old_uV, int new_uV)
{
unsigned int ramp_delay = 0;
if (rdev->constraints->ramp_delay)
ramp_delay = rdev->constraints->ramp_delay;
else if (rdev->desc->ramp_delay)
ramp_delay = rdev->desc->ramp_delay;
if (ramp_delay == 0) {
rdev_warn(rdev, "ramp_delay not set\n");
return 0;
}
return DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay);
}
static int _regulator_do_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
@@ -2778,6 +2769,8 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
int best_val = 0;
unsigned int selector;
int old_selector = -1;
const struct regulator_ops *ops = rdev->desc->ops;
int old_uV = _regulator_get_voltage(rdev);
trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
@@ -2789,29 +2782,28 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
* info to call set_voltage_time_sel().
*/
if (_regulator_is_enabled(rdev) &&
rdev->desc->ops->set_voltage_time_sel &&
rdev->desc->ops->get_voltage_sel) {
old_selector = rdev->desc->ops->get_voltage_sel(rdev);
ops->set_voltage_time_sel && ops->get_voltage_sel) {
old_selector = ops->get_voltage_sel(rdev);
if (old_selector < 0)
return old_selector;
}
if (rdev->desc->ops->set_voltage) {
if (ops->set_voltage) {
ret = _regulator_call_set_voltage(rdev, min_uV, max_uV,
&selector);
if (ret >= 0) {
if (rdev->desc->ops->list_voltage)
best_val = rdev->desc->ops->list_voltage(rdev,
selector);
if (ops->list_voltage)
best_val = ops->list_voltage(rdev,
selector);
else
best_val = _regulator_get_voltage(rdev);
}
} else if (rdev->desc->ops->set_voltage_sel) {
} else if (ops->set_voltage_sel) {
ret = regulator_map_voltage(rdev, min_uV, max_uV);
if (ret >= 0) {
best_val = rdev->desc->ops->list_voltage(rdev, ret);
best_val = ops->list_voltage(rdev, ret);
if (min_uV <= best_val && max_uV >= best_val) {
selector = ret;
if (old_selector == selector)
@@ -2827,34 +2819,50 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
ret = -EINVAL;
}
/* Call set_voltage_time_sel if successfully obtained old_selector */
if (ret == 0 && !rdev->constraints->ramp_disable && old_selector >= 0
&& old_selector != selector) {
if (ret)
goto out;
delay = rdev->desc->ops->set_voltage_time_sel(rdev,
old_selector, selector);
if (delay < 0) {
rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n",
delay);
delay = 0;
}
/* Insert any necessary delays */
if (delay >= 1000) {
mdelay(delay / 1000);
udelay(delay % 1000);
} else if (delay) {
udelay(delay);
if (ops->set_voltage_time_sel) {
/*
* Call set_voltage_time_sel if successfully obtained
* old_selector
*/
if (old_selector >= 0 && old_selector != selector)
delay = ops->set_voltage_time_sel(rdev, old_selector,
selector);
} else {
if (old_uV != best_val) {
if (ops->set_voltage_time)
delay = ops->set_voltage_time(rdev, old_uV,
best_val);
else
delay = _regulator_set_voltage_time(rdev,
old_uV,
best_val);
}
}
if (ret == 0 && best_val >= 0) {
if (delay < 0) {
rdev_warn(rdev, "failed to get delay: %d\n", delay);
delay = 0;
}
/* Insert any necessary delays */
if (delay >= 1000) {
mdelay(delay / 1000);
udelay(delay % 1000);
} else if (delay) {
udelay(delay);
}
if (best_val >= 0) {
unsigned long data = best_val;
_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
(void *)data);
}
out:
trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val);
return ret;
@@ -3025,9 +3033,13 @@ int regulator_set_voltage_time(struct regulator *regulator,
int voltage;
int i;
if (ops->set_voltage_time)
return ops->set_voltage_time(rdev, old_uV, new_uV);
else if (!ops->set_voltage_time_sel)
return _regulator_set_voltage_time(rdev, old_uV, new_uV);
/* Currently requires operations to do this */
if (!ops->list_voltage || !ops->set_voltage_time_sel
|| !rdev->desc->n_voltages)
if (!ops->list_voltage || !rdev->desc->n_voltages)
return -EINVAL;
for (i = 0; i < rdev->desc->n_voltages; i++) {
@@ -3066,19 +3078,8 @@ int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
unsigned int old_selector,
unsigned int new_selector)
{
unsigned int ramp_delay = 0;
int old_volt, new_volt;
if (rdev->constraints->ramp_delay)
ramp_delay = rdev->constraints->ramp_delay;
else if (rdev->desc->ramp_delay)
ramp_delay = rdev->desc->ramp_delay;
if (ramp_delay == 0) {
rdev_warn(rdev, "ramp_delay not set\n");
return 0;
}
/* sanity check */
if (!rdev->desc->ops->list_voltage)
return -EINVAL;
@@ -3086,7 +3087,11 @@ int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
old_volt = rdev->desc->ops->list_voltage(rdev, old_selector);
new_volt = rdev->desc->ops->list_voltage(rdev, new_selector);
return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay);
if (rdev->desc->ops->set_voltage_time)
return rdev->desc->ops->set_voltage_time(rdev, old_volt,
new_volt);
else
return _regulator_set_voltage_time(rdev, old_volt, new_volt);
}
EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel);
@@ -3354,6 +3359,39 @@ unsigned int regulator_get_mode(struct regulator *regulator)
}
EXPORT_SYMBOL_GPL(regulator_get_mode);
static int _regulator_get_error_flags(struct regulator_dev *rdev,
unsigned int *flags)
{
int ret;
mutex_lock(&rdev->mutex);
/* sanity check */
if (!rdev->desc->ops->get_error_flags) {
ret = -EINVAL;
goto out;
}
ret = rdev->desc->ops->get_error_flags(rdev, flags);
out:
mutex_unlock(&rdev->mutex);
return ret;
}
/**
* regulator_get_error_flags - get regulator error information
* @regulator: regulator source
* @flags: pointer to store error flags
*
* Get the current regulator error information.
*/
int regulator_get_error_flags(struct regulator *regulator,
unsigned int *flags)
{
return _regulator_get_error_flags(regulator->rdev, flags);
}
EXPORT_SYMBOL_GPL(regulator_get_error_flags);
/**
* regulator_set_load - set regulator load
* @regulator: regulator source
@@ -3510,10 +3548,8 @@ int regulator_bulk_get(struct device *dev, int num_consumers,
consumers[i].consumer = NULL;
for (i = 0; i < num_consumers; i++) {
consumers[i].consumer = _regulator_get(dev,
consumers[i].supply,
false,
!consumers[i].optional);
consumers[i].consumer = regulator_get(dev,
consumers[i].supply);
if (IS_ERR(consumers[i].consumer)) {
ret = PTR_ERR(consumers[i].consumer);
dev_err(dev, "Failed to get supply '%s': %d\n",

View File

@@ -333,7 +333,7 @@ static const struct regulator_ops da9052_ldo_ops = {
static struct da9052_regulator_info da9052_regulator_info[] = {
DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
DA9052_DCDC(BUCK3, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO),
DA9052_DCDC(BUCK3, 25, 950, 2525, 6, 6, DA9052_SUPPLY_VBMEMGO),
DA9052_DCDC(BUCK4, 50, 1800, 3600, 5, 6, 0),
DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0),
DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
@@ -350,8 +350,8 @@ static struct da9052_regulator_info da9052_regulator_info[] = {
static struct da9052_regulator_info da9053_regulator_info[] = {
DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
DA9052_DCDC(BUCK3, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO),
DA9052_DCDC(BUCK4, 25, 925, 2500, 6, 6, 0),
DA9052_DCDC(BUCK3, 25, 950, 2525, 6, 6, DA9052_SUPPLY_VBMEMGO),
DA9052_DCDC(BUCK4, 25, 950, 2525, 6, 6, 0),
DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0),
DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),

View File

@@ -21,12 +21,11 @@
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/of_device.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regmap.h>
@@ -179,6 +178,13 @@ error_i2c:
/*
* I2C driver interface functions
*/
static const struct of_device_id da9210_dt_ids[] = {
{ .compatible = "dlg,da9210", },
{ }
};
MODULE_DEVICE_TABLE(of, da9210_dt_ids);
static int da9210_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -188,6 +194,16 @@ static int da9210_i2c_probe(struct i2c_client *i2c,
struct regulator_dev *rdev = NULL;
struct regulator_config config = { };
int error;
const struct of_device_id *match;
if (i2c->dev.of_node && !pdata) {
match = of_match_device(of_match_ptr(da9210_dt_ids),
&i2c->dev);
if (!match) {
dev_err(&i2c->dev, "Error: No device match found\n");
return -ENODEV;
}
}
chip = devm_kzalloc(&i2c->dev, sizeof(struct da9210), GFP_KERNEL);
if (!chip)
@@ -264,6 +280,7 @@ MODULE_DEVICE_TABLE(i2c, da9210_i2c_id);
static struct i2c_driver da9210_regulator_driver = {
.driver = {
.name = "da9210",
.of_match_table = of_match_ptr(da9210_dt_ids),
},
.probe = da9210_i2c_probe,
.id_table = da9210_i2c_id,

View File

@@ -1,5 +1,6 @@
/*
* da9211-regulator.c - Regulator device driver for DA9211/DA9213/DA9215
* da9211-regulator.c - Regulator device driver for DA9211/DA9212
* /DA9213/DA9214/DA9215
* Copyright (C) 2015 Dialog Semiconductor Ltd.
*
* This library is free software; you can redistribute it and/or
@@ -493,7 +494,9 @@ static int da9211_i2c_probe(struct i2c_client *i2c,
static const struct i2c_device_id da9211_i2c_id[] = {
{"da9211", DA9211},
{"da9212", DA9212},
{"da9213", DA9213},
{"da9214", DA9214},
{"da9215", DA9215},
{},
};
@@ -502,8 +505,10 @@ MODULE_DEVICE_TABLE(i2c, da9211_i2c_id);
#ifdef CONFIG_OF
static const struct of_device_id da9211_dt_ids[] = {
{ .compatible = "dlg,da9211", .data = &da9211_i2c_id[0] },
{ .compatible = "dlg,da9213", .data = &da9211_i2c_id[1] },
{ .compatible = "dlg,da9215", .data = &da9211_i2c_id[2] },
{ .compatible = "dlg,da9212", .data = &da9211_i2c_id[1] },
{ .compatible = "dlg,da9213", .data = &da9211_i2c_id[2] },
{ .compatible = "dlg,da9214", .data = &da9211_i2c_id[3] },
{ .compatible = "dlg,da9215", .data = &da9211_i2c_id[4] },
{},
};
MODULE_DEVICE_TABLE(of, da9211_dt_ids);
@@ -521,5 +526,5 @@ static struct i2c_driver da9211_regulator_driver = {
module_i2c_driver(da9211_regulator_driver);
MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>");
MODULE_DESCRIPTION("Regulator device driver for Dialog DA9211/DA9213/DA9215");
MODULE_DESCRIPTION("DA9211/DA9212/DA9213/DA9214/DA9215 regulator driver");
MODULE_LICENSE("GPL");

View File

@@ -1,5 +1,6 @@
/*
* da9211-regulator.h - Regulator definitions for DA9211/DA9213/DA9215
* da9211-regulator.h - Regulator definitions for DA9211/DA9212
* /DA9213/DA9214/DA9215
* Copyright (C) 2015 Dialog Semiconductor Ltd.
*
* This program is free software; you can redistribute it and/or

View File

@@ -75,24 +75,6 @@ static struct ux500_regulator_debug {
u8 *state_after_suspend;
} rdebug;
void ux500_regulator_suspend_debug(void)
{
int i;
for (i = 0; i < rdebug.num_regulators; i++)
rdebug.state_before_suspend[i] =
rdebug.regulator_array[i].is_enabled;
}
void ux500_regulator_resume_debug(void)
{
int i;
for (i = 0; i < rdebug.num_regulators; i++)
rdebug.state_after_suspend[i] =
rdebug.regulator_array[i].is_enabled;
}
static int ux500_regulator_power_state_cnt_print(struct seq_file *s, void *p)
{
/* print power state count */

View File

@@ -164,11 +164,8 @@ int devm_regulator_bulk_get(struct device *dev, int num_consumers,
consumers[i].consumer = NULL;
for (i = 0; i < num_consumers; i++) {
consumers[i].consumer = _devm_regulator_get(dev,
consumers[i].supply,
consumers[i].optional ?
OPTIONAL_GET :
NORMAL_GET);
consumers[i].consumer = devm_regulator_get(dev,
consumers[i].supply);
if (IS_ERR(consumers[i].consumer)) {
ret = PTR_ERR(consumers[i].consumer);
dev_err(dev, "Failed to get supply '%s': %d\n",

View File

@@ -477,7 +477,8 @@ static int hi6421_regulator_buck_set_mode(struct regulator_dev *rdev,
return 0;
}
unsigned int hi6421_regulator_ldo_get_optimum_mode(struct regulator_dev *rdev,
static unsigned int
hi6421_regulator_ldo_get_optimum_mode(struct regulator_dev *rdev,
int input_uV, int output_uV, int load_uA)
{
struct hi6421_regulator_info *info = rdev_get_drvdata(rdev);

View File

@@ -20,7 +20,7 @@
#include <linux/mfd/lp873x.h>
#define LP873X_REGULATOR(_name, _id, _of, _ops, _n, _vr, _vm, _er, _em, \
_delay, _lr, _nlr, _cr) \
_delay, _lr, _cr) \
[_id] = { \
.desc = { \
.name = _name, \
@@ -37,7 +37,7 @@
.enable_mask = _em, \
.ramp_delay = _delay, \
.linear_ranges = _lr, \
.n_linear_ranges = _nlr, \
.n_linear_ranges = ARRAY_SIZE(_lr), \
}, \
.ctrl2_reg = _cr, \
}
@@ -175,22 +175,20 @@ static const struct lp873x_regulator regulators[] = {
256, LP873X_REG_BUCK0_VOUT,
LP873X_BUCK0_VOUT_BUCK0_VSET, LP873X_REG_BUCK0_CTRL_1,
LP873X_BUCK0_CTRL_1_BUCK0_EN, 10000,
buck0_buck1_ranges, 4, LP873X_REG_BUCK0_CTRL_2),
buck0_buck1_ranges, LP873X_REG_BUCK0_CTRL_2),
LP873X_REGULATOR("BUCK1", LP873X_BUCK_1, "buck1", lp873x_buck01_ops,
256, LP873X_REG_BUCK1_VOUT,
LP873X_BUCK1_VOUT_BUCK1_VSET, LP873X_REG_BUCK1_CTRL_1,
LP873X_BUCK1_CTRL_1_BUCK1_EN, 10000,
buck0_buck1_ranges, 4, LP873X_REG_BUCK1_CTRL_2),
buck0_buck1_ranges, LP873X_REG_BUCK1_CTRL_2),
LP873X_REGULATOR("LDO0", LP873X_LDO_0, "ldo0", lp873x_ldo01_ops, 26,
LP873X_REG_LDO0_VOUT, LP873X_LDO0_VOUT_LDO0_VSET,
LP873X_REG_LDO0_CTRL,
LP873X_LDO0_CTRL_LDO0_EN, 0, ldo0_ldo1_ranges, 1,
0xFF),
LP873X_LDO0_CTRL_LDO0_EN, 0, ldo0_ldo1_ranges, 0xFF),
LP873X_REGULATOR("LDO1", LP873X_LDO_1, "ldo1", lp873x_ldo01_ops, 26,
LP873X_REG_LDO1_VOUT, LP873X_LDO1_VOUT_LDO1_VSET,
LP873X_REG_LDO1_CTRL,
LP873X_LDO1_CTRL_LDO1_EN, 0, ldo0_ldo1_ranges, 1,
0xFF),
LP873X_LDO1_CTRL_LDO1_EN, 0, ldo0_ldo1_ranges, 0xFF),
};
static int lp873x_regulator_probe(struct platform_device *pdev)

420
drivers/regulator/ltc3676.c Normal file
View File

@@ -0,0 +1,420 @@
/*
* Copyright (C) 2016 Gateworks Corporation, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#define DRIVER_NAME "ltc3676"
/* LTC3676 Registers */
#define LTC3676_BUCK1 0x01
#define LTC3676_BUCK2 0x02
#define LTC3676_BUCK3 0x03
#define LTC3676_BUCK4 0x04
#define LTC3676_LDOA 0x05
#define LTC3676_LDOB 0x06
#define LTC3676_SQD1 0x07
#define LTC3676_SQD2 0x08
#define LTC3676_CNTRL 0x09
#define LTC3676_DVB1A 0x0A
#define LTC3676_DVB1B 0x0B
#define LTC3676_DVB2A 0x0C
#define LTC3676_DVB2B 0x0D
#define LTC3676_DVB3A 0x0E
#define LTC3676_DVB3B 0x0F
#define LTC3676_DVB4A 0x10
#define LTC3676_DVB4B 0x11
#define LTC3676_MSKIRQ 0x12
#define LTC3676_MSKPG 0x13
#define LTC3676_USER 0x14
#define LTC3676_IRQSTAT 0x15
#define LTC3676_PGSTATL 0x16
#define LTC3676_PGSTATRT 0x17
#define LTC3676_HRST 0x1E
#define LTC3676_CLIRQ 0x1F
#define LTC3676_DVBxA_REF_SELECT BIT(5)
#define LTC3676_IRQSTAT_PGOOD_TIMEOUT BIT(3)
#define LTC3676_IRQSTAT_UNDERVOLT_WARN BIT(4)
#define LTC3676_IRQSTAT_UNDERVOLT_FAULT BIT(5)
#define LTC3676_IRQSTAT_THERMAL_WARN BIT(6)
#define LTC3676_IRQSTAT_THERMAL_FAULT BIT(7)
enum ltc3676_reg {
LTC3676_SW1,
LTC3676_SW2,
LTC3676_SW3,
LTC3676_SW4,
LTC3676_LDO1,
LTC3676_LDO2,
LTC3676_LDO3,
LTC3676_LDO4,
LTC3676_NUM_REGULATORS,
};
struct ltc3676 {
struct regmap *regmap;
struct device *dev;
struct regulator_desc regulator_descs[LTC3676_NUM_REGULATORS];
struct regulator_dev *regulators[LTC3676_NUM_REGULATORS];
};
static int ltc3676_set_suspend_voltage(struct regulator_dev *rdev, int uV)
{
struct ltc3676 *ltc3676 = rdev_get_drvdata(rdev);
struct device *dev = ltc3676->dev;
int dcdc = rdev_get_id(rdev);
int sel;
dev_dbg(dev, "%s id=%d uV=%d\n", __func__, dcdc, uV);
sel = regulator_map_voltage_linear(rdev, uV, uV);
if (sel < 0)
return sel;
/* DVBB register follows right after the corresponding DVBA register */
return regmap_update_bits(ltc3676->regmap, rdev->desc->vsel_reg + 1,
rdev->desc->vsel_mask, sel);
}
static int ltc3676_set_suspend_mode(struct regulator_dev *rdev,
unsigned int mode)
{
struct ltc3676 *ltc3676= rdev_get_drvdata(rdev);
struct device *dev = ltc3676->dev;
int mask, val;
int dcdc = rdev_get_id(rdev);
dev_dbg(dev, "%s id=%d mode=%d\n", __func__, dcdc, mode);
mask = LTC3676_DVBxA_REF_SELECT;
switch (mode) {
case REGULATOR_MODE_STANDBY:
val = 0; /* select DVBxA */
break;
case REGULATOR_MODE_NORMAL:
val = LTC3676_DVBxA_REF_SELECT; /* select DVBxB */
break;
default:
dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n",
rdev->desc->name, mode);
return -EINVAL;
}
return regmap_update_bits(ltc3676->regmap, rdev->desc->vsel_reg,
mask, val);
}
static inline unsigned int ltc3676_scale(unsigned int uV, u32 r1, u32 r2)
{
uint64_t tmp;
if (uV == 0)
return 0;
tmp = (uint64_t)uV * r1;
do_div(tmp, r2);
return uV + (unsigned int)tmp;
}
static int ltc3676_of_parse_cb(struct device_node *np,
const struct regulator_desc *desc,
struct regulator_config *config)
{
struct ltc3676 *ltc3676 = config->driver_data;
struct regulator_desc *rdesc = &ltc3676->regulator_descs[desc->id];
u32 r[2];
int ret;
/* LDO3 has a fixed output */
if (desc->id == LTC3676_LDO3)
return 0;
ret = of_property_read_u32_array(np, "lltc,fb-voltage-divider", r, 2);
if (ret) {
dev_err(ltc3676->dev, "Failed to parse voltage divider: %d\n",
ret);
return ret;
}
rdesc->min_uV = ltc3676_scale(desc->min_uV, r[0], r[1]);
rdesc->uV_step = ltc3676_scale(desc->uV_step, r[0], r[1]);
rdesc->fixed_uV = ltc3676_scale(desc->fixed_uV, r[0], r[1]);
return 0;
}
/* SW1, SW2, SW3, SW4 linear 0.8V-3.3V with scalar via R1/R2 feeback res */
static struct regulator_ops ltc3676_linear_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.list_voltage = regulator_list_voltage_linear,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_suspend_voltage = ltc3676_set_suspend_voltage,
.set_suspend_mode = ltc3676_set_suspend_mode,
};
/* LDO1 always on fixed 0.8V-3.3V via scalar via R1/R2 feeback res */
static struct regulator_ops ltc3676_fixed_standby_regulator_ops = {
};
/* LDO2, LDO3 fixed (LDO2 has external scalar via R1/R2 feedback res) */
static struct regulator_ops ltc3676_fixed_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
};
#define LTC3676_REG(_id, _name, _ops, en_reg, en_bit, dvba_reg, dvb_mask) \
[LTC3676_ ## _id] = { \
.name = #_name, \
.of_match = of_match_ptr(#_name), \
.regulators_node = of_match_ptr("regulators"), \
.of_parse_cb = ltc3676_of_parse_cb, \
.n_voltages = (dvb_mask) + 1, \
.min_uV = (dvba_reg) ? 412500 : 0, \
.uV_step = (dvba_reg) ? 12500 : 0, \
.ramp_delay = (dvba_reg) ? 800 : 0, \
.fixed_uV = (dvb_mask) ? 0 : 725000, \
.ops = &ltc3676_ ## _ops ## _regulator_ops, \
.type = REGULATOR_VOLTAGE, \
.id = LTC3676_ ## _id, \
.owner = THIS_MODULE, \
.vsel_reg = (dvba_reg), \
.vsel_mask = (dvb_mask), \
.enable_reg = (en_reg), \
.enable_mask = (1 << en_bit), \
}
#define LTC3676_LINEAR_REG(_id, _name, _en, _dvba) \
LTC3676_REG(_id, _name, linear, \
LTC3676_ ## _en, 7, \
LTC3676_ ## _dvba, 0x1f)
#define LTC3676_FIXED_REG(_id, _name, _en_reg, _en_bit) \
LTC3676_REG(_id, _name, fixed, LTC3676_ ## _en_reg, _en_bit, 0, 0)
static struct regulator_desc ltc3676_regulators[LTC3676_NUM_REGULATORS] = {
LTC3676_LINEAR_REG(SW1, sw1, BUCK1, DVB1A),
LTC3676_LINEAR_REG(SW2, sw2, BUCK2, DVB2A),
LTC3676_LINEAR_REG(SW3, sw3, BUCK3, DVB3A),
LTC3676_LINEAR_REG(SW4, sw4, BUCK4, DVB4A),
LTC3676_REG(LDO1, ldo1, fixed_standby, 0, 0, 0, 0),
LTC3676_FIXED_REG(LDO2, ldo2, LDOA, 2),
LTC3676_FIXED_REG(LDO3, ldo3, LDOA, 5),
LTC3676_FIXED_REG(LDO4, ldo4, LDOB, 2),
};
static bool ltc3676_writeable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case LTC3676_IRQSTAT:
case LTC3676_BUCK1:
case LTC3676_BUCK2:
case LTC3676_BUCK3:
case LTC3676_BUCK4:
case LTC3676_LDOA:
case LTC3676_LDOB:
case LTC3676_SQD1:
case LTC3676_SQD2:
case LTC3676_CNTRL:
case LTC3676_DVB1A:
case LTC3676_DVB1B:
case LTC3676_DVB2A:
case LTC3676_DVB2B:
case LTC3676_DVB3A:
case LTC3676_DVB3B:
case LTC3676_DVB4A:
case LTC3676_DVB4B:
case LTC3676_MSKIRQ:
case LTC3676_MSKPG:
case LTC3676_USER:
case LTC3676_HRST:
case LTC3676_CLIRQ:
return true;
}
return false;
}
static bool ltc3676_readable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case LTC3676_IRQSTAT:
case LTC3676_BUCK1:
case LTC3676_BUCK2:
case LTC3676_BUCK3:
case LTC3676_BUCK4:
case LTC3676_LDOA:
case LTC3676_LDOB:
case LTC3676_SQD1:
case LTC3676_SQD2:
case LTC3676_CNTRL:
case LTC3676_DVB1A:
case LTC3676_DVB1B:
case LTC3676_DVB2A:
case LTC3676_DVB2B:
case LTC3676_DVB3A:
case LTC3676_DVB3B:
case LTC3676_DVB4A:
case LTC3676_DVB4B:
case LTC3676_MSKIRQ:
case LTC3676_MSKPG:
case LTC3676_USER:
case LTC3676_HRST:
case LTC3676_CLIRQ:
return true;
}
return false;
}
static bool ltc3676_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case LTC3676_IRQSTAT:
case LTC3676_PGSTATL:
case LTC3676_PGSTATRT:
return true;
}
return false;
}
static const struct regmap_config ltc3676_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.writeable_reg = ltc3676_writeable_reg,
.readable_reg = ltc3676_readable_reg,
.volatile_reg = ltc3676_volatile_reg,
.max_register = LTC3676_CLIRQ,
.use_single_rw = true,
.cache_type = REGCACHE_RBTREE,
};
static irqreturn_t ltc3676_isr(int irq, void *dev_id)
{
struct ltc3676 *ltc3676 = dev_id;
struct device *dev = ltc3676->dev;
unsigned int i, irqstat, event;
regmap_read(ltc3676->regmap, LTC3676_IRQSTAT, &irqstat);
dev_dbg(dev, "irq%d irqstat=0x%02x\n", irq, irqstat);
if (irqstat & LTC3676_IRQSTAT_THERMAL_WARN) {
dev_warn(dev, "Over-temperature Warning\n");
event = REGULATOR_EVENT_OVER_TEMP;
for (i = 0; i < LTC3676_NUM_REGULATORS; i++)
regulator_notifier_call_chain(ltc3676->regulators[i],
event, NULL);
}
if (irqstat & LTC3676_IRQSTAT_UNDERVOLT_WARN) {
dev_info(dev, "Undervoltage Warning\n");
event = REGULATOR_EVENT_UNDER_VOLTAGE;
for (i = 0; i < LTC3676_NUM_REGULATORS; i++)
regulator_notifier_call_chain(ltc3676->regulators[i],
event, NULL);
}
/* Clear warning condition */
regmap_write(ltc3676->regmap, LTC3676_CLIRQ, 0);
return IRQ_HANDLED;
}
static int ltc3676_regulator_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct regulator_init_data *init_data = dev_get_platdata(dev);
struct regulator_desc *descs;
struct ltc3676 *ltc3676;
int i, ret;
ltc3676 = devm_kzalloc(dev, sizeof(*ltc3676), GFP_KERNEL);
if (!ltc3676)
return -ENOMEM;
i2c_set_clientdata(client, ltc3676);
ltc3676->dev = dev;
descs = ltc3676->regulator_descs;
memcpy(descs, ltc3676_regulators, sizeof(ltc3676_regulators));
descs[LTC3676_LDO3].fixed_uV = 1800000; /* LDO3 is fixed 1.8V */
ltc3676->regmap = devm_regmap_init_i2c(client, &ltc3676_regmap_config);
if (IS_ERR(ltc3676->regmap)) {
ret = PTR_ERR(ltc3676->regmap);
dev_err(dev, "failed to initialize regmap: %d\n", ret);
return ret;
}
for (i = 0; i < LTC3676_NUM_REGULATORS; i++) {
struct regulator_desc *desc = &ltc3676->regulator_descs[i];
struct regulator_config config = { };
if (init_data)
config.init_data = &init_data[i];
config.dev = dev;
config.driver_data = ltc3676;
ltc3676->regulators[i] = devm_regulator_register(dev, desc,
&config);
if (IS_ERR(ltc3676->regulators[i])) {
ret = PTR_ERR(ltc3676->regulators[i]);
dev_err(dev, "failed to register regulator %s: %d\n",
desc->name, ret);
return ret;
}
}
regmap_write(ltc3676->regmap, LTC3676_CLIRQ, 0);
if (client->irq) {
ret = devm_request_threaded_irq(dev, client->irq, NULL,
ltc3676_isr,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
client->name, ltc3676);
if (ret) {
dev_err(dev, "Failed to request IRQ: %d\n", ret);
return ret;
}
}
return 0;
}
static const struct i2c_device_id ltc3676_i2c_id[] = {
{ "ltc3676" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ltc3676_i2c_id);
static struct i2c_driver ltc3676_driver = {
.driver = {
.name = DRIVER_NAME,
},
.probe = ltc3676_regulator_probe,
.id_table = ltc3676_i2c_id,
};
module_i2c_driver(ltc3676_driver);
MODULE_AUTHOR("Tim Harvey <tharvey@gateworks.com>");
MODULE_DESCRIPTION("Regulator driver for Linear Technology LTC1376");
MODULE_LICENSE("GPL v2");

View File

@@ -2,7 +2,7 @@
* max14577.c - Regulator driver for the Maxim 14577/77836
*
* Copyright (C) 2013,2014 Samsung Electronics
* Krzysztof Kozlowski <k.kozlowski@samsung.com>
* Krzysztof Kozlowski <krzk@kernel.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -331,7 +331,7 @@ static void __exit max14577_regulator_exit(void)
}
module_exit(max14577_regulator_exit);
MODULE_AUTHOR("Krzysztof Kozlowski <k.kozlowski@samsung.com>");
MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
MODULE_DESCRIPTION("Maxim 14577/77836 regulator driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:max14577-regulator");

View File

@@ -123,6 +123,9 @@ static int max77620_regulator_set_fps_src(struct max77620_regulator *pmic,
unsigned int val;
int ret;
if (!rinfo)
return 0;
switch (fps_src) {
case MAX77620_FPS_SRC_0:
case MAX77620_FPS_SRC_1:
@@ -171,6 +174,9 @@ static int max77620_regulator_set_fps_slots(struct max77620_regulator *pmic,
int pd = rpdata->active_fps_pd_slot;
int ret = 0;
if (!rinfo)
return 0;
if (is_suspend) {
pu = rpdata->suspend_fps_pu_slot;
pd = rpdata->suspend_fps_pd_slot;
@@ -680,7 +686,6 @@ static struct max77620_regulator_info max77620_regs_info[MAX77620_NUM_REGS] = {
RAIL_SD(SD1, sd1, "in-sd1", SD1, 600000, 1550000, 12500, 0x22, SD1),
RAIL_SD(SD2, sd2, "in-sd2", SDX, 600000, 3787500, 12500, 0xFF, NONE),
RAIL_SD(SD3, sd3, "in-sd3", SDX, 600000, 3787500, 12500, 0xFF, NONE),
RAIL_SD(SD4, sd4, "in-sd4", SDX, 600000, 3787500, 12500, 0xFF, NONE),
RAIL_LDO(LDO0, ldo0, "in-ldo0-1", N, 800000, 2375000, 25000),
RAIL_LDO(LDO1, ldo1, "in-ldo0-1", N, 800000, 2375000, 25000),

View File

@@ -3,7 +3,7 @@
*
* Copyright (C) 2013-2015 Samsung Electronics
* Jonghwa Lee <jonghwa3.lee@samsung.com>
* Krzysztof Kozlowski <k.kozlowski.k@gmail.com>
* Krzysztof Kozlowski <krzk@kernel.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -314,5 +314,5 @@ module_exit(max77693_pmic_cleanup);
MODULE_DESCRIPTION("MAXIM 77693/77843 regulator driver");
MODULE_AUTHOR("Jonghwa Lee <jonghwa3.lee@samsung.com>");
MODULE_AUTHOR("Krzysztof Kozlowski <k.kozlowski.k@gmail.com>");
MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
MODULE_LICENSE("GPL");

View File

@@ -271,22 +271,18 @@ static int max8973_set_ramp_delay(struct regulator_dev *rdev,
struct max8973_chip *max = rdev_get_drvdata(rdev);
unsigned int control;
int ret;
int ret_val;
/* Set ramp delay */
if (ramp_delay < 25000) {
if (ramp_delay <= 12000)
control = MAX8973_RAMP_12mV_PER_US;
ret_val = 12000;
} else if (ramp_delay < 50000) {
else if (ramp_delay <= 25000)
control = MAX8973_RAMP_25mV_PER_US;
ret_val = 25000;
} else if (ramp_delay < 200000) {
else if (ramp_delay <= 50000)
control = MAX8973_RAMP_50mV_PER_US;
ret_val = 50000;
} else {
else if (ramp_delay <= 200000)
control = MAX8973_RAMP_200mV_PER_US;
ret_val = 200000;
}
else
return -EINVAL;
ret = regmap_update_bits(max->regmap, MAX8973_CONTROL1,
MAX8973_RAMP_MASK, control);
@@ -499,7 +495,8 @@ static irqreturn_t max8973_thermal_irq(int irq, void *data)
{
struct max8973_chip *mchip = data;
thermal_zone_device_update(mchip->tz_device);
thermal_zone_device_update(mchip->tz_device,
THERMAL_EVENT_UNSPECIFIED);
return IRQ_HANDLED;
}

View File

@@ -0,0 +1,425 @@
/*
* Copyright (c) 2016 MediaTek Inc.
* Author: Chen Zhong <chen.zhong@mediatek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6323/registers.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/mt6323-regulator.h>
#include <linux/regulator/of_regulator.h>
#define MT6323_LDO_MODE_NORMAL 0
#define MT6323_LDO_MODE_LP 1
/*
* MT6323 regulators' information
*
* @desc: standard fields of regulator description.
* @qi: Mask for query enable signal status of regulators
* @vselon_reg: Register sections for hardware control mode of bucks
* @vselctrl_reg: Register for controlling the buck control mode.
* @vselctrl_mask: Mask for query buck's voltage control mode.
*/
struct mt6323_regulator_info {
struct regulator_desc desc;
u32 qi;
u32 vselon_reg;
u32 vselctrl_reg;
u32 vselctrl_mask;
u32 modeset_reg;
u32 modeset_mask;
};
#define MT6323_BUCK(match, vreg, min, max, step, volt_ranges, enreg, \
vosel, vosel_mask, voselon, vosel_ctrl) \
[MT6323_ID_##vreg] = { \
.desc = { \
.name = #vreg, \
.of_match = of_match_ptr(match), \
.ops = &mt6323_volt_range_ops, \
.type = REGULATOR_VOLTAGE, \
.id = MT6323_ID_##vreg, \
.owner = THIS_MODULE, \
.n_voltages = (max - min)/step + 1, \
.linear_ranges = volt_ranges, \
.n_linear_ranges = ARRAY_SIZE(volt_ranges), \
.vsel_reg = vosel, \
.vsel_mask = vosel_mask, \
.enable_reg = enreg, \
.enable_mask = BIT(0), \
}, \
.qi = BIT(13), \
.vselon_reg = voselon, \
.vselctrl_reg = vosel_ctrl, \
.vselctrl_mask = BIT(1), \
}
#define MT6323_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel, \
vosel_mask, _modeset_reg, _modeset_mask) \
[MT6323_ID_##vreg] = { \
.desc = { \
.name = #vreg, \
.of_match = of_match_ptr(match), \
.ops = &mt6323_volt_table_ops, \
.type = REGULATOR_VOLTAGE, \
.id = MT6323_ID_##vreg, \
.owner = THIS_MODULE, \
.n_voltages = ARRAY_SIZE(ldo_volt_table), \
.volt_table = ldo_volt_table, \
.vsel_reg = vosel, \
.vsel_mask = vosel_mask, \
.enable_reg = enreg, \
.enable_mask = BIT(enbit), \
}, \
.qi = BIT(15), \
.modeset_reg = _modeset_reg, \
.modeset_mask = _modeset_mask, \
}
#define MT6323_REG_FIXED(match, vreg, enreg, enbit, volt, \
_modeset_reg, _modeset_mask) \
[MT6323_ID_##vreg] = { \
.desc = { \
.name = #vreg, \
.of_match = of_match_ptr(match), \
.ops = &mt6323_volt_fixed_ops, \
.type = REGULATOR_VOLTAGE, \
.id = MT6323_ID_##vreg, \
.owner = THIS_MODULE, \
.n_voltages = 1, \
.enable_reg = enreg, \
.enable_mask = BIT(enbit), \
.min_uV = volt, \
}, \
.qi = BIT(15), \
.modeset_reg = _modeset_reg, \
.modeset_mask = _modeset_mask, \
}
static const struct regulator_linear_range buck_volt_range1[] = {
REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250),
};
static const struct regulator_linear_range buck_volt_range2[] = {
REGULATOR_LINEAR_RANGE(1400000, 0, 0x7f, 12500),
};
static const struct regulator_linear_range buck_volt_range3[] = {
REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000),
};
static const u32 ldo_volt_table1[] = {
3300000, 3400000, 3500000, 3600000,
};
static const u32 ldo_volt_table2[] = {
1500000, 1800000, 2500000, 2800000,
};
static const u32 ldo_volt_table3[] = {
1800000, 3300000,
};
static const u32 ldo_volt_table4[] = {
3000000, 3300000,
};
static const u32 ldo_volt_table5[] = {
1200000, 1300000, 1500000, 1800000, 2000000, 2800000, 3000000, 3300000,
};
static const u32 ldo_volt_table6[] = {
1200000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 2000000,
};
static const u32 ldo_volt_table7[] = {
1200000, 1300000, 1500000, 1800000,
};
static const u32 ldo_volt_table8[] = {
1800000, 3000000,
};
static const u32 ldo_volt_table9[] = {
1200000, 1350000, 1500000, 1800000,
};
static const u32 ldo_volt_table10[] = {
1200000, 1300000, 1500000, 1800000,
};
static int mt6323_get_status(struct regulator_dev *rdev)
{
int ret;
u32 regval;
struct mt6323_regulator_info *info = rdev_get_drvdata(rdev);
ret = regmap_read(rdev->regmap, info->desc.enable_reg, &regval);
if (ret != 0) {
dev_err(&rdev->dev, "Failed to get enable reg: %d\n", ret);
return ret;
}
return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;
}
static int mt6323_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
int ret, val = 0;
struct mt6323_regulator_info *info = rdev_get_drvdata(rdev);
if (!info->modeset_mask) {
dev_err(&rdev->dev, "regulator %s doesn't support set_mode\n",
info->desc.name);
return -EINVAL;
}
switch (mode) {
case REGULATOR_MODE_STANDBY:
val = MT6323_LDO_MODE_LP;
break;
case REGULATOR_MODE_NORMAL:
val = MT6323_LDO_MODE_NORMAL;
break;
default:
return -EINVAL;
}
val <<= ffs(info->modeset_mask) - 1;
ret = regmap_update_bits(rdev->regmap, info->modeset_reg,
info->modeset_mask, val);
return ret;
}
static unsigned int mt6323_ldo_get_mode(struct regulator_dev *rdev)
{
unsigned int val;
unsigned int mode;
int ret;
struct mt6323_regulator_info *info = rdev_get_drvdata(rdev);
if (!info->modeset_mask) {
dev_err(&rdev->dev, "regulator %s doesn't support get_mode\n",
info->desc.name);
return -EINVAL;
}
ret = regmap_read(rdev->regmap, info->modeset_reg, &val);
if (ret < 0)
return ret;
val &= info->modeset_mask;
val >>= ffs(info->modeset_mask) - 1;
if (val & 0x1)
mode = REGULATOR_MODE_STANDBY;
else
mode = REGULATOR_MODE_NORMAL;
return mode;
}
static const struct regulator_ops mt6323_volt_range_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.get_status = mt6323_get_status,
};
static const struct regulator_ops mt6323_volt_table_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_iterate,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.get_status = mt6323_get_status,
.set_mode = mt6323_ldo_set_mode,
.get_mode = mt6323_ldo_get_mode,
};
static const struct regulator_ops mt6323_volt_fixed_ops = {
.list_voltage = regulator_list_voltage_linear,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.get_status = mt6323_get_status,
.set_mode = mt6323_ldo_set_mode,
.get_mode = mt6323_ldo_get_mode,
};
/* The array is indexed by id(MT6323_ID_XXX) */
static struct mt6323_regulator_info mt6323_regulators[] = {
MT6323_BUCK("buck_vproc", VPROC, 700000, 1493750, 6250,
buck_volt_range1, MT6323_VPROC_CON7, MT6323_VPROC_CON9, 0x7f,
MT6323_VPROC_CON10, MT6323_VPROC_CON5),
MT6323_BUCK("buck_vsys", VSYS, 1400000, 2987500, 12500,
buck_volt_range2, MT6323_VSYS_CON7, MT6323_VSYS_CON9, 0x7f,
MT6323_VSYS_CON10, MT6323_VSYS_CON5),
MT6323_BUCK("buck_vpa", VPA, 500000, 3650000, 50000,
buck_volt_range3, MT6323_VPA_CON7, MT6323_VPA_CON9,
0x3f, MT6323_VPA_CON10, MT6323_VPA_CON5),
MT6323_REG_FIXED("ldo_vtcxo", VTCXO, MT6323_ANALDO_CON1, 10, 2800000,
MT6323_ANALDO_CON1, 0x2),
MT6323_REG_FIXED("ldo_vcn28", VCN28, MT6323_ANALDO_CON19, 12, 2800000,
MT6323_ANALDO_CON20, 0x2),
MT6323_LDO("ldo_vcn33_bt", VCN33_BT, ldo_volt_table1,
MT6323_ANALDO_CON16, 7, MT6323_ANALDO_CON16, 0xC,
MT6323_ANALDO_CON21, 0x2),
MT6323_LDO("ldo_vcn33_wifi", VCN33_WIFI, ldo_volt_table1,
MT6323_ANALDO_CON17, 12, MT6323_ANALDO_CON16, 0xC,
MT6323_ANALDO_CON21, 0x2),
MT6323_REG_FIXED("ldo_va", VA, MT6323_ANALDO_CON2, 14, 2800000,
MT6323_ANALDO_CON2, 0x2),
MT6323_LDO("ldo_vcama", VCAMA, ldo_volt_table2,
MT6323_ANALDO_CON4, 15, MT6323_ANALDO_CON10, 0x60, -1, 0),
MT6323_REG_FIXED("ldo_vio28", VIO28, MT6323_DIGLDO_CON0, 14, 2800000,
MT6323_DIGLDO_CON0, 0x2),
MT6323_REG_FIXED("ldo_vusb", VUSB, MT6323_DIGLDO_CON2, 14, 3300000,
MT6323_DIGLDO_CON2, 0x2),
MT6323_LDO("ldo_vmc", VMC, ldo_volt_table3,
MT6323_DIGLDO_CON3, 12, MT6323_DIGLDO_CON24, 0x10,
MT6323_DIGLDO_CON3, 0x2),
MT6323_LDO("ldo_vmch", VMCH, ldo_volt_table4,
MT6323_DIGLDO_CON5, 14, MT6323_DIGLDO_CON26, 0x80,
MT6323_DIGLDO_CON5, 0x2),
MT6323_LDO("ldo_vemc3v3", VEMC3V3, ldo_volt_table4,
MT6323_DIGLDO_CON6, 14, MT6323_DIGLDO_CON27, 0x80,
MT6323_DIGLDO_CON6, 0x2),
MT6323_LDO("ldo_vgp1", VGP1, ldo_volt_table5,
MT6323_DIGLDO_CON7, 15, MT6323_DIGLDO_CON28, 0xE0,
MT6323_DIGLDO_CON7, 0x2),
MT6323_LDO("ldo_vgp2", VGP2, ldo_volt_table6,
MT6323_DIGLDO_CON8, 15, MT6323_DIGLDO_CON29, 0xE0,
MT6323_DIGLDO_CON8, 0x2),
MT6323_LDO("ldo_vgp3", VGP3, ldo_volt_table7,
MT6323_DIGLDO_CON9, 15, MT6323_DIGLDO_CON30, 0x60,
MT6323_DIGLDO_CON9, 0x2),
MT6323_REG_FIXED("ldo_vcn18", VCN18, MT6323_DIGLDO_CON11, 14, 1800000,
MT6323_DIGLDO_CON11, 0x2),
MT6323_LDO("ldo_vsim1", VSIM1, ldo_volt_table8,
MT6323_DIGLDO_CON13, 15, MT6323_DIGLDO_CON34, 0x20,
MT6323_DIGLDO_CON13, 0x2),
MT6323_LDO("ldo_vsim2", VSIM2, ldo_volt_table8,
MT6323_DIGLDO_CON14, 15, MT6323_DIGLDO_CON35, 0x20,
MT6323_DIGLDO_CON14, 0x2),
MT6323_REG_FIXED("ldo_vrtc", VRTC, MT6323_DIGLDO_CON15, 8, 2800000,
-1, 0),
MT6323_LDO("ldo_vcamaf", VCAMAF, ldo_volt_table5,
MT6323_DIGLDO_CON31, 15, MT6323_DIGLDO_CON32, 0xE0,
MT6323_DIGLDO_CON31, 0x2),
MT6323_LDO("ldo_vibr", VIBR, ldo_volt_table5,
MT6323_DIGLDO_CON39, 15, MT6323_DIGLDO_CON40, 0xE0,
MT6323_DIGLDO_CON39, 0x2),
MT6323_REG_FIXED("ldo_vrf18", VRF18, MT6323_DIGLDO_CON45, 15, 1825000,
MT6323_DIGLDO_CON45, 0x2),
MT6323_LDO("ldo_vm", VM, ldo_volt_table9,
MT6323_DIGLDO_CON47, 14, MT6323_DIGLDO_CON48, 0x30,
MT6323_DIGLDO_CON47, 0x2),
MT6323_REG_FIXED("ldo_vio18", VIO18, MT6323_DIGLDO_CON49, 14, 1800000,
MT6323_DIGLDO_CON49, 0x2),
MT6323_LDO("ldo_vcamd", VCAMD, ldo_volt_table10,
MT6323_DIGLDO_CON51, 14, MT6323_DIGLDO_CON52, 0x60,
MT6323_DIGLDO_CON51, 0x2),
MT6323_REG_FIXED("ldo_vcamio", VCAMIO, MT6323_DIGLDO_CON53, 14, 1800000,
MT6323_DIGLDO_CON53, 0x2),
};
static int mt6323_set_buck_vosel_reg(struct platform_device *pdev)
{
struct mt6397_chip *mt6323 = dev_get_drvdata(pdev->dev.parent);
int i;
u32 regval;
for (i = 0; i < MT6323_MAX_REGULATOR; i++) {
if (mt6323_regulators[i].vselctrl_reg) {
if (regmap_read(mt6323->regmap,
mt6323_regulators[i].vselctrl_reg,
&regval) < 0) {
dev_err(&pdev->dev,
"Failed to read buck ctrl\n");
return -EIO;
}
if (regval & mt6323_regulators[i].vselctrl_mask) {
mt6323_regulators[i].desc.vsel_reg =
mt6323_regulators[i].vselon_reg;
}
}
}
return 0;
}
static int mt6323_regulator_probe(struct platform_device *pdev)
{
struct mt6397_chip *mt6323 = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = {};
struct regulator_dev *rdev;
int i;
u32 reg_value;
/* Query buck controller to select activated voltage register part */
if (mt6323_set_buck_vosel_reg(pdev))
return -EIO;
/* Read PMIC chip revision to update constraints and voltage table */
if (regmap_read(mt6323->regmap, MT6323_CID, &reg_value) < 0) {
dev_err(&pdev->dev, "Failed to read Chip ID\n");
return -EIO;
}
dev_info(&pdev->dev, "Chip ID = 0x%x\n", reg_value);
for (i = 0; i < MT6323_MAX_REGULATOR; i++) {
config.dev = &pdev->dev;
config.driver_data = &mt6323_regulators[i];
config.regmap = mt6323->regmap;
rdev = devm_regulator_register(&pdev->dev,
&mt6323_regulators[i].desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register %s\n",
mt6323_regulators[i].desc.name);
return PTR_ERR(rdev);
}
}
return 0;
}
static const struct platform_device_id mt6323_platform_ids[] = {
{"mt6323-regulator", 0},
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(platform, mt6323_platform_ids);
static struct platform_driver mt6323_regulator_driver = {
.driver = {
.name = "mt6323-regulator",
},
.probe = mt6323_regulator_probe,
.id_table = mt6323_platform_ids,
};
module_platform_driver(mt6323_regulator_driver);
MODULE_AUTHOR("Chen Zhong <chen.zhong@mediatek.com>");
MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6323 PMIC");
MODULE_LICENSE("GPL v2");

View File

@@ -23,6 +23,9 @@
#include <linux/regulator/mt6397-regulator.h>
#include <linux/regulator/of_regulator.h>
#define MT6397_BUCK_MODE_AUTO 0
#define MT6397_BUCK_MODE_FORCE_PWM 1
/*
* MT6397 regulators' information
*
@@ -38,10 +41,14 @@ struct mt6397_regulator_info {
u32 vselon_reg;
u32 vselctrl_reg;
u32 vselctrl_mask;
u32 modeset_reg;
u32 modeset_mask;
u32 modeset_shift;
};
#define MT6397_BUCK(match, vreg, min, max, step, volt_ranges, enreg, \
vosel, vosel_mask, voselon, vosel_ctrl) \
vosel, vosel_mask, voselon, vosel_ctrl, _modeset_reg, \
_modeset_shift) \
[MT6397_ID_##vreg] = { \
.desc = { \
.name = #vreg, \
@@ -62,6 +69,9 @@ struct mt6397_regulator_info {
.vselon_reg = voselon, \
.vselctrl_reg = vosel_ctrl, \
.vselctrl_mask = BIT(1), \
.modeset_reg = _modeset_reg, \
.modeset_mask = BIT(_modeset_shift), \
.modeset_shift = _modeset_shift \
}
#define MT6397_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel, \
@@ -145,6 +155,63 @@ static const u32 ldo_volt_table7[] = {
1300000, 1500000, 1800000, 2000000, 2500000, 2800000, 3000000, 3300000,
};
static int mt6397_regulator_set_mode(struct regulator_dev *rdev,
unsigned int mode)
{
struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
int ret, val;
switch (mode) {
case REGULATOR_MODE_FAST:
val = MT6397_BUCK_MODE_FORCE_PWM;
break;
case REGULATOR_MODE_NORMAL:
val = MT6397_BUCK_MODE_AUTO;
break;
default:
ret = -EINVAL;
goto err_mode;
}
dev_dbg(&rdev->dev, "mt6397 buck set_mode %#x, %#x, %#x, %#x\n",
info->modeset_reg, info->modeset_mask,
info->modeset_shift, val);
val <<= info->modeset_shift;
ret = regmap_update_bits(rdev->regmap, info->modeset_reg,
info->modeset_mask, val);
err_mode:
if (ret != 0) {
dev_err(&rdev->dev,
"Failed to set mt6397 buck mode: %d\n", ret);
return ret;
}
return 0;
}
static unsigned int mt6397_regulator_get_mode(struct regulator_dev *rdev)
{
struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
int ret, regval;
ret = regmap_read(rdev->regmap, info->modeset_reg, &regval);
if (ret != 0) {
dev_err(&rdev->dev,
"Failed to get mt6397 buck mode: %d\n", ret);
return ret;
}
switch ((regval & info->modeset_mask) >> info->modeset_shift) {
case MT6397_BUCK_MODE_AUTO:
return REGULATOR_MODE_NORMAL;
case MT6397_BUCK_MODE_FORCE_PWM:
return REGULATOR_MODE_FAST;
default:
return -EINVAL;
}
}
static int mt6397_get_status(struct regulator_dev *rdev)
{
int ret;
@@ -160,7 +227,7 @@ static int mt6397_get_status(struct regulator_dev *rdev)
return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;
}
static struct regulator_ops mt6397_volt_range_ops = {
static const struct regulator_ops mt6397_volt_range_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -170,9 +237,11 @@ static struct regulator_ops mt6397_volt_range_ops = {
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.get_status = mt6397_get_status,
.set_mode = mt6397_regulator_set_mode,
.get_mode = mt6397_regulator_get_mode,
};
static struct regulator_ops mt6397_volt_table_ops = {
static const struct regulator_ops mt6397_volt_table_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_iterate,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -184,7 +253,7 @@ static struct regulator_ops mt6397_volt_table_ops = {
.get_status = mt6397_get_status,
};
static struct regulator_ops mt6397_volt_fixed_ops = {
static const struct regulator_ops mt6397_volt_fixed_ops = {
.list_voltage = regulator_list_voltage_linear,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
@@ -196,28 +265,30 @@ static struct regulator_ops mt6397_volt_fixed_ops = {
static struct mt6397_regulator_info mt6397_regulators[] = {
MT6397_BUCK("buck_vpca15", VPCA15, 700000, 1493750, 6250,
buck_volt_range1, MT6397_VCA15_CON7, MT6397_VCA15_CON9, 0x7f,
MT6397_VCA15_CON10, MT6397_VCA15_CON5),
MT6397_VCA15_CON10, MT6397_VCA15_CON5, MT6397_VCA15_CON2, 11),
MT6397_BUCK("buck_vpca7", VPCA7, 700000, 1493750, 6250,
buck_volt_range1, MT6397_VPCA7_CON7, MT6397_VPCA7_CON9, 0x7f,
MT6397_VPCA7_CON10, MT6397_VPCA7_CON5),
MT6397_VPCA7_CON10, MT6397_VPCA7_CON5, MT6397_VPCA7_CON2, 8),
MT6397_BUCK("buck_vsramca15", VSRAMCA15, 700000, 1493750, 6250,
buck_volt_range1, MT6397_VSRMCA15_CON7, MT6397_VSRMCA15_CON9,
0x7f, MT6397_VSRMCA15_CON10, MT6397_VSRMCA15_CON5),
0x7f, MT6397_VSRMCA15_CON10, MT6397_VSRMCA15_CON5,
MT6397_VSRMCA15_CON2, 8),
MT6397_BUCK("buck_vsramca7", VSRAMCA7, 700000, 1493750, 6250,
buck_volt_range1, MT6397_VSRMCA7_CON7, MT6397_VSRMCA7_CON9,
0x7f, MT6397_VSRMCA7_CON10, MT6397_VSRMCA7_CON5),
0x7f, MT6397_VSRMCA7_CON10, MT6397_VSRMCA7_CON5,
MT6397_VSRMCA7_CON2, 8),
MT6397_BUCK("buck_vcore", VCORE, 700000, 1493750, 6250,
buck_volt_range1, MT6397_VCORE_CON7, MT6397_VCORE_CON9, 0x7f,
MT6397_VCORE_CON10, MT6397_VCORE_CON5),
MT6397_VCORE_CON10, MT6397_VCORE_CON5, MT6397_VCORE_CON2, 8),
MT6397_BUCK("buck_vgpu", VGPU, 700000, 1493750, 6250, buck_volt_range1,
MT6397_VGPU_CON7, MT6397_VGPU_CON9, 0x7f,
MT6397_VGPU_CON10, MT6397_VGPU_CON5),
MT6397_VGPU_CON10, MT6397_VGPU_CON5, MT6397_VGPU_CON2, 8),
MT6397_BUCK("buck_vdrm", VDRM, 800000, 1593750, 6250, buck_volt_range2,
MT6397_VDRM_CON7, MT6397_VDRM_CON9, 0x7f,
MT6397_VDRM_CON10, MT6397_VDRM_CON5),
MT6397_VDRM_CON10, MT6397_VDRM_CON5, MT6397_VDRM_CON2, 8),
MT6397_BUCK("buck_vio18", VIO18, 1500000, 2120000, 20000,
buck_volt_range3, MT6397_VIO18_CON7, MT6397_VIO18_CON9, 0x1f,
MT6397_VIO18_CON10, MT6397_VIO18_CON5),
MT6397_VIO18_CON10, MT6397_VIO18_CON5, MT6397_VIO18_CON2, 8),
MT6397_REG_FIXED("ldo_vtcxo", VTCXO, MT6397_ANALDO_CON0, 10, 2800000),
MT6397_REG_FIXED("ldo_va28", VA28, MT6397_ANALDO_CON1, 14, 2800000),
MT6397_LDO("ldo_vcama", VCAMA, ldo_volt_table1,

View File

@@ -163,6 +163,9 @@ static void of_get_regulation_constraints(struct device_node *np,
"regulator-suspend-microvolt", &pval))
suspend_state->uV = pval;
if (i == PM_SUSPEND_MEM)
constraints->initial_state = PM_SUSPEND_MEM;
of_node_put(suspend_np);
suspend_state = NULL;
suspend_np = NULL;

View File

@@ -70,6 +70,7 @@ struct pfuze_chip {
struct device *dev;
struct pfuze_regulator regulator_descs[PFUZE100_MAX_REGULATOR];
struct regulator_dev *regulators[PFUZE100_MAX_REGULATOR];
struct pfuze_regulator *pfuze_regulators;
};
static const int pfuze100_swbst[] = {
@@ -334,8 +335,6 @@ static struct pfuze_regulator pfuze3000_regulators[] = {
PFUZE100_VGEN_REG(PFUZE3000, VLDO4, PFUZE100_VGEN6VOL, 1800000, 3300000, 100000),
};
static struct pfuze_regulator *pfuze_regulators;
#ifdef CONFIG_OF
/* PFUZE100 */
static struct of_regulator_match pfuze100_matches[] = {
@@ -563,21 +562,21 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
/* use the right regulators after identify the right device */
switch (pfuze_chip->chip_id) {
case PFUZE3000:
pfuze_regulators = pfuze3000_regulators;
pfuze_chip->pfuze_regulators = pfuze3000_regulators;
regulator_num = ARRAY_SIZE(pfuze3000_regulators);
sw_check_start = PFUZE3000_SW2;
sw_check_end = PFUZE3000_SW2;
sw_hi = 1 << 3;
break;
case PFUZE200:
pfuze_regulators = pfuze200_regulators;
pfuze_chip->pfuze_regulators = pfuze200_regulators;
regulator_num = ARRAY_SIZE(pfuze200_regulators);
sw_check_start = PFUZE200_SW2;
sw_check_end = PFUZE200_SW3B;
break;
case PFUZE100:
default:
pfuze_regulators = pfuze100_regulators;
pfuze_chip->pfuze_regulators = pfuze100_regulators;
regulator_num = ARRAY_SIZE(pfuze100_regulators);
sw_check_start = PFUZE100_SW2;
sw_check_end = PFUZE100_SW4;
@@ -587,7 +586,7 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
(pfuze_chip->chip_id == PFUZE100) ? "100" :
((pfuze_chip->chip_id == PFUZE200) ? "200" : "3000"));
memcpy(pfuze_chip->regulator_descs, pfuze_regulators,
memcpy(pfuze_chip->regulator_descs, pfuze_chip->pfuze_regulators,
sizeof(pfuze_chip->regulator_descs));
ret = pfuze_parse_regulators_dt(pfuze_chip);
@@ -631,7 +630,7 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
devm_regulator_register(&client->dev, desc, &config);
if (IS_ERR(pfuze_chip->regulators[i])) {
dev_err(&client->dev, "register regulator%s failed\n",
pfuze_regulators[i].desc.name);
pfuze_chip->pfuze_regulators[i].desc.name);
return PTR_ERR(pfuze_chip->regulators[i]);
}
}
@@ -650,5 +649,5 @@ static struct i2c_driver pfuze_driver = {
module_i2c_driver(pfuze_driver);
MODULE_AUTHOR("Robin Gong <b38343@freescale.com>");
MODULE_DESCRIPTION("Regulator Driver for Freescale PFUZE100/PFUZE200 PMIC");
MODULE_DESCRIPTION("Regulator Driver for Freescale PFUZE100/200/3000 PMIC");
MODULE_LICENSE("GPL v2");

View File

@@ -14,7 +14,6 @@
*/
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -25,8 +24,6 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/regulator/of_regulator.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include "pv88060-regulator.h"
#define PV88060_MAX_REGULATORS 14

View File

@@ -14,9 +14,9 @@
*/
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/regulator/driver.h>
@@ -25,11 +25,9 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/regulator/of_regulator.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include "pv88080-regulator.h"
#define PV88080_MAX_REGULATORS 3
#define PV88080_MAX_REGULATORS 4
/* PV88080 REGULATOR IDs */
enum {
@@ -37,6 +35,12 @@ enum {
PV88080_ID_BUCK1,
PV88080_ID_BUCK2,
PV88080_ID_BUCK3,
PV88080_ID_HVBUCK,
};
enum pv88080_types {
TYPE_PV88080_AA,
TYPE_PV88080_BA,
};
struct pv88080_regulator {
@@ -45,7 +49,8 @@ struct pv88080_regulator {
unsigned int n_current_limits;
const int *current_limits;
unsigned int limit_mask;
unsigned int conf;
unsigned int mode_reg;
unsigned int limit_reg;
unsigned int conf2;
unsigned int conf5;
};
@@ -54,6 +59,8 @@ struct pv88080 {
struct device *dev;
struct regmap *regmap;
struct regulator_dev *rdev[PV88080_MAX_REGULATORS];
unsigned long type;
const struct pv88080_compatible_regmap *regmap_config;
};
struct pv88080_buck_voltage {
@@ -62,6 +69,30 @@ struct pv88080_buck_voltage {
int uV_step;
};
struct pv88080_buck_regmap {
/* REGS */
int buck_enable_reg;
int buck_vsel_reg;
int buck_mode_reg;
int buck_limit_reg;
int buck_vdac_range_reg;
int buck_vrange_gain_reg;
/* MASKS */
int buck_enable_mask;
int buck_vsel_mask;
int buck_limit_mask;
};
struct pv88080_compatible_regmap {
/* BUCK1, 2, 3 */
struct pv88080_buck_regmap buck_regmap[PV88080_MAX_REGULATORS-1];
/* HVBUCK */
int hvbuck_enable_reg;
int hvbuck_vsel_reg;
int hvbuck_enable_mask;
int hvbuck_vsel_mask;
};
static const struct regmap_config pv88080_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -92,13 +123,111 @@ static const struct pv88080_buck_voltage pv88080_buck_vol[2] = {
},
};
static const struct pv88080_compatible_regmap pv88080_aa_regs = {
/* BUCK1 */
.buck_regmap[0] = {
.buck_enable_reg = PV88080AA_REG_BUCK1_CONF0,
.buck_vsel_reg = PV88080AA_REG_BUCK1_CONF0,
.buck_mode_reg = PV88080AA_REG_BUCK1_CONF1,
.buck_limit_reg = PV88080AA_REG_BUCK1_CONF1,
.buck_vdac_range_reg = PV88080AA_REG_BUCK1_CONF2,
.buck_vrange_gain_reg = PV88080AA_REG_BUCK1_CONF5,
.buck_enable_mask = PV88080_BUCK1_EN,
.buck_vsel_mask = PV88080_VBUCK1_MASK,
.buck_limit_mask = PV88080_BUCK1_ILIM_MASK,
},
/* BUCK2 */
.buck_regmap[1] = {
.buck_enable_reg = PV88080AA_REG_BUCK2_CONF0,
.buck_vsel_reg = PV88080AA_REG_BUCK2_CONF0,
.buck_mode_reg = PV88080AA_REG_BUCK2_CONF1,
.buck_limit_reg = PV88080AA_REG_BUCK2_CONF1,
.buck_vdac_range_reg = PV88080AA_REG_BUCK2_CONF2,
.buck_vrange_gain_reg = PV88080AA_REG_BUCK2_CONF5,
.buck_enable_mask = PV88080_BUCK2_EN,
.buck_vsel_mask = PV88080_VBUCK2_MASK,
.buck_limit_mask = PV88080_BUCK2_ILIM_MASK,
},
/* BUCK3 */
.buck_regmap[2] = {
.buck_enable_reg = PV88080AA_REG_BUCK3_CONF0,
.buck_vsel_reg = PV88080AA_REG_BUCK3_CONF0,
.buck_mode_reg = PV88080AA_REG_BUCK3_CONF1,
.buck_limit_reg = PV88080AA_REG_BUCK3_CONF1,
.buck_vdac_range_reg = PV88080AA_REG_BUCK3_CONF2,
.buck_vrange_gain_reg = PV88080AA_REG_BUCK3_CONF5,
.buck_enable_mask = PV88080_BUCK3_EN,
.buck_vsel_mask = PV88080_VBUCK3_MASK,
.buck_limit_mask = PV88080_BUCK3_ILIM_MASK,
},
/* HVBUCK */
.hvbuck_enable_reg = PV88080AA_REG_HVBUCK_CONF2,
.hvbuck_vsel_reg = PV88080AA_REG_HVBUCK_CONF1,
.hvbuck_enable_mask = PV88080_HVBUCK_EN,
.hvbuck_vsel_mask = PV88080_VHVBUCK_MASK,
};
static const struct pv88080_compatible_regmap pv88080_ba_regs = {
/* BUCK1 */
.buck_regmap[0] = {
.buck_enable_reg = PV88080BA_REG_BUCK1_CONF0,
.buck_vsel_reg = PV88080BA_REG_BUCK1_CONF0,
.buck_mode_reg = PV88080BA_REG_BUCK1_CONF1,
.buck_limit_reg = PV88080BA_REG_BUCK1_CONF1,
.buck_vdac_range_reg = PV88080BA_REG_BUCK1_CONF2,
.buck_vrange_gain_reg = PV88080BA_REG_BUCK1_CONF5,
.buck_enable_mask = PV88080_BUCK1_EN,
.buck_vsel_mask = PV88080_VBUCK1_MASK,
.buck_limit_mask = PV88080_BUCK1_ILIM_MASK,
},
/* BUCK2 */
.buck_regmap[1] = {
.buck_enable_reg = PV88080BA_REG_BUCK2_CONF0,
.buck_vsel_reg = PV88080BA_REG_BUCK2_CONF0,
.buck_mode_reg = PV88080BA_REG_BUCK2_CONF1,
.buck_limit_reg = PV88080BA_REG_BUCK2_CONF1,
.buck_vdac_range_reg = PV88080BA_REG_BUCK2_CONF2,
.buck_vrange_gain_reg = PV88080BA_REG_BUCK2_CONF5,
.buck_enable_mask = PV88080_BUCK2_EN,
.buck_vsel_mask = PV88080_VBUCK2_MASK,
.buck_limit_mask = PV88080_BUCK2_ILIM_MASK,
},
/* BUCK3 */
.buck_regmap[2] = {
.buck_enable_reg = PV88080BA_REG_BUCK3_CONF0,
.buck_vsel_reg = PV88080BA_REG_BUCK3_CONF0,
.buck_mode_reg = PV88080BA_REG_BUCK3_CONF1,
.buck_limit_reg = PV88080BA_REG_BUCK3_CONF1,
.buck_vdac_range_reg = PV88080BA_REG_BUCK3_CONF2,
.buck_vrange_gain_reg = PV88080BA_REG_BUCK3_CONF5,
.buck_enable_mask = PV88080_BUCK3_EN,
.buck_vsel_mask = PV88080_VBUCK3_MASK,
.buck_limit_mask = PV88080_BUCK3_ILIM_MASK,
},
/* HVBUCK */
.hvbuck_enable_reg = PV88080BA_REG_HVBUCK_CONF2,
.hvbuck_vsel_reg = PV88080BA_REG_HVBUCK_CONF1,
.hvbuck_enable_mask = PV88080_HVBUCK_EN,
.hvbuck_vsel_mask = PV88080_VHVBUCK_MASK,
};
#ifdef CONFIG_OF
static const struct of_device_id pv88080_dt_ids[] = {
{ .compatible = "pvs,pv88080", .data = (void *)TYPE_PV88080_AA },
{ .compatible = "pvs,pv88080-aa", .data = (void *)TYPE_PV88080_AA },
{ .compatible = "pvs,pv88080-ba", .data = (void *)TYPE_PV88080_BA },
{},
};
MODULE_DEVICE_TABLE(of, pv88080_dt_ids);
#endif
static unsigned int pv88080_buck_get_mode(struct regulator_dev *rdev)
{
struct pv88080_regulator *info = rdev_get_drvdata(rdev);
unsigned int data;
int ret, mode = 0;
ret = regmap_read(rdev->regmap, info->conf, &data);
ret = regmap_read(rdev->regmap, info->mode_reg, &data);
if (ret < 0)
return ret;
@@ -139,7 +268,7 @@ static int pv88080_buck_set_mode(struct regulator_dev *rdev,
return -EINVAL;
}
return regmap_update_bits(rdev->regmap, info->conf,
return regmap_update_bits(rdev->regmap, info->mode_reg,
PV88080_BUCK1_MODE_MASK, val);
}
@@ -154,7 +283,7 @@ static int pv88080_set_current_limit(struct regulator_dev *rdev, int min,
if (min <= info->current_limits[i]
&& max >= info->current_limits[i]) {
return regmap_update_bits(rdev->regmap,
info->conf,
info->limit_reg,
info->limit_mask,
i << PV88080_BUCK1_ILIM_SHIFT);
}
@@ -169,7 +298,7 @@ static int pv88080_get_current_limit(struct regulator_dev *rdev)
unsigned int data;
int ret;
ret = regmap_read(rdev->regmap, info->conf, &data);
ret = regmap_read(rdev->regmap, info->limit_reg, &data);
if (ret < 0)
return ret;
@@ -190,6 +319,15 @@ static struct regulator_ops pv88080_buck_ops = {
.get_current_limit = pv88080_get_current_limit,
};
static struct regulator_ops pv88080_hvbuck_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
};
#define PV88080_BUCK(chip, regl_name, min, step, max, limits_array) \
{\
.desc = {\
@@ -203,17 +341,25 @@ static struct regulator_ops pv88080_buck_ops = {
.min_uV = min, \
.uV_step = step, \
.n_voltages = ((max) - (min))/(step) + 1, \
.enable_reg = PV88080_REG_##regl_name##_CONF0, \
.enable_mask = PV88080_##regl_name##_EN, \
.vsel_reg = PV88080_REG_##regl_name##_CONF0, \
.vsel_mask = PV88080_V##regl_name##_MASK, \
},\
.current_limits = limits_array, \
.n_current_limits = ARRAY_SIZE(limits_array), \
.limit_mask = PV88080_##regl_name##_ILIM_MASK, \
.conf = PV88080_REG_##regl_name##_CONF1, \
.conf2 = PV88080_REG_##regl_name##_CONF2, \
.conf5 = PV88080_REG_##regl_name##_CONF5, \
}
#define PV88080_HVBUCK(chip, regl_name, min, step, max) \
{\
.desc = {\
.id = chip##_ID_##regl_name,\
.name = __stringify(chip##_##regl_name),\
.of_match = of_match_ptr(#regl_name),\
.regulators_node = of_match_ptr("regulators"),\
.type = REGULATOR_VOLTAGE,\
.owner = THIS_MODULE,\
.ops = &pv88080_hvbuck_ops,\
.min_uV = min, \
.uV_step = step, \
.n_voltages = ((max) - (min))/(step) + 1, \
},\
}
static struct pv88080_regulator pv88080_regulator_info[] = {
@@ -223,6 +369,7 @@ static struct pv88080_regulator pv88080_regulator_info[] = {
pv88080_buck23_limits),
PV88080_BUCK(PV88080, BUCK3, 600000, 6250, 1393750,
pv88080_buck23_limits),
PV88080_HVBUCK(PV88080, HVBUCK, 0, 5000, 1275000),
};
static irqreturn_t pv88080_irq_handler(int irq, void *data)
@@ -283,6 +430,8 @@ static int pv88080_i2c_probe(struct i2c_client *i2c,
{
struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev);
struct pv88080 *chip;
const struct pv88080_compatible_regmap *regmap_config;
const struct of_device_id *match;
struct regulator_config config = { };
int i, error, ret;
unsigned int conf2, conf5;
@@ -300,6 +449,17 @@ static int pv88080_i2c_probe(struct i2c_client *i2c,
return error;
}
if (i2c->dev.of_node) {
match = of_match_node(pv88080_dt_ids, i2c->dev.of_node);
if (!match) {
dev_err(chip->dev, "Failed to get of_match_node\n");
return -EINVAL;
}
chip->type = (unsigned long)match->data;
} else {
chip->type = id->driver_data;
}
i2c_set_clientdata(i2c, chip);
if (i2c->irq != 0) {
@@ -339,31 +499,58 @@ static int pv88080_i2c_probe(struct i2c_client *i2c,
"Failed to update mask reg: %d\n", ret);
return ret;
}
} else {
dev_warn(chip->dev, "No IRQ configured\n");
}
switch (chip->type) {
case TYPE_PV88080_AA:
chip->regmap_config = &pv88080_aa_regs;
break;
case TYPE_PV88080_BA:
chip->regmap_config = &pv88080_ba_regs;
break;
}
regmap_config = chip->regmap_config;
config.dev = chip->dev;
config.regmap = chip->regmap;
for (i = 0; i < PV88080_MAX_REGULATORS; i++) {
/* Registeration for BUCK1, 2, 3 */
for (i = 0; i < PV88080_MAX_REGULATORS-1; i++) {
if (init_data)
config.init_data = &init_data[i];
pv88080_regulator_info[i].limit_reg
= regmap_config->buck_regmap[i].buck_limit_reg;
pv88080_regulator_info[i].limit_mask
= regmap_config->buck_regmap[i].buck_limit_mask;
pv88080_regulator_info[i].mode_reg
= regmap_config->buck_regmap[i].buck_mode_reg;
pv88080_regulator_info[i].conf2
= regmap_config->buck_regmap[i].buck_vdac_range_reg;
pv88080_regulator_info[i].conf5
= regmap_config->buck_regmap[i].buck_vrange_gain_reg;
pv88080_regulator_info[i].desc.enable_reg
= regmap_config->buck_regmap[i].buck_enable_reg;
pv88080_regulator_info[i].desc.enable_mask
= regmap_config->buck_regmap[i].buck_enable_mask;
pv88080_regulator_info[i].desc.vsel_reg
= regmap_config->buck_regmap[i].buck_vsel_reg;
pv88080_regulator_info[i].desc.vsel_mask
= regmap_config->buck_regmap[i].buck_vsel_mask;
ret = regmap_read(chip->regmap,
pv88080_regulator_info[i].conf2, &conf2);
pv88080_regulator_info[i].conf2, &conf2);
if (ret < 0)
return ret;
conf2 = ((conf2 >> PV88080_BUCK_VDAC_RANGE_SHIFT) &
PV88080_BUCK_VDAC_RANGE_MASK);
ret = regmap_read(chip->regmap,
pv88080_regulator_info[i].conf5, &conf5);
pv88080_regulator_info[i].conf5, &conf5);
if (ret < 0)
return ret;
conf5 = ((conf5 >> PV88080_BUCK_VRANGE_GAIN_SHIFT) &
PV88080_BUCK_VRANGE_GAIN_MASK);
@@ -386,23 +573,38 @@ static int pv88080_i2c_probe(struct i2c_client *i2c,
}
}
pv88080_regulator_info[PV88080_ID_HVBUCK].desc.enable_reg
= regmap_config->hvbuck_enable_reg;
pv88080_regulator_info[PV88080_ID_HVBUCK].desc.enable_mask
= regmap_config->hvbuck_enable_mask;
pv88080_regulator_info[PV88080_ID_HVBUCK].desc.vsel_reg
= regmap_config->hvbuck_vsel_reg;
pv88080_regulator_info[PV88080_ID_HVBUCK].desc.vsel_mask
= regmap_config->hvbuck_vsel_mask;
/* Registeration for HVBUCK */
if (init_data)
config.init_data = &init_data[PV88080_ID_HVBUCK];
config.driver_data = (void *)&pv88080_regulator_info[PV88080_ID_HVBUCK];
chip->rdev[PV88080_ID_HVBUCK] = devm_regulator_register(chip->dev,
&pv88080_regulator_info[PV88080_ID_HVBUCK].desc, &config);
if (IS_ERR(chip->rdev[PV88080_ID_HVBUCK])) {
dev_err(chip->dev, "Failed to register PV88080 regulator\n");
return PTR_ERR(chip->rdev[PV88080_ID_HVBUCK]);
}
return 0;
}
static const struct i2c_device_id pv88080_i2c_id[] = {
{"pv88080", 0},
{ "pv88080", TYPE_PV88080_AA },
{ "pv88080-aa", TYPE_PV88080_AA },
{ "pv88080-ba", TYPE_PV88080_BA },
{},
};
MODULE_DEVICE_TABLE(i2c, pv88080_i2c_id);
#ifdef CONFIG_OF
static const struct of_device_id pv88080_dt_ids[] = {
{ .compatible = "pvs,pv88080", .data = &pv88080_i2c_id[0] },
{},
};
MODULE_DEVICE_TABLE(of, pv88080_dt_ids);
#endif
static struct i2c_driver pv88080_regulator_driver = {
.driver = {
.name = "pv88080",

View File

@@ -17,55 +17,75 @@
#define __PV88080_REGISTERS_H__
/* System Control and Event Registers */
#define PV88080_REG_EVENT_A 0x04
#define PV88080_REG_MASK_A 0x09
#define PV88080_REG_MASK_B 0x0a
#define PV88080_REG_MASK_C 0x0b
#define PV88080_REG_EVENT_A 0x04
#define PV88080_REG_MASK_A 0x09
#define PV88080_REG_MASK_B 0x0A
#define PV88080_REG_MASK_C 0x0B
/* Regulator Registers */
#define PV88080_REG_BUCK1_CONF0 0x27
#define PV88080_REG_BUCK1_CONF1 0x28
#define PV88080_REG_BUCK1_CONF2 0x59
#define PV88080_REG_BUCK1_CONF5 0x5c
#define PV88080_REG_BUCK2_CONF0 0x29
#define PV88080_REG_BUCK2_CONF1 0x2a
#define PV88080_REG_BUCK2_CONF2 0x61
#define PV88080_REG_BUCK2_CONF5 0x64
#define PV88080_REG_BUCK3_CONF0 0x2b
#define PV88080_REG_BUCK3_CONF1 0x2c
#define PV88080_REG_BUCK3_CONF2 0x69
#define PV88080_REG_BUCK3_CONF5 0x6c
/* Regulator Registers - rev. AA */
#define PV88080AA_REG_HVBUCK_CONF1 0x2D
#define PV88080AA_REG_HVBUCK_CONF2 0x2E
#define PV88080AA_REG_BUCK1_CONF0 0x27
#define PV88080AA_REG_BUCK1_CONF1 0x28
#define PV88080AA_REG_BUCK1_CONF2 0x59
#define PV88080AA_REG_BUCK1_CONF5 0x5C
#define PV88080AA_REG_BUCK2_CONF0 0x29
#define PV88080AA_REG_BUCK2_CONF1 0x2A
#define PV88080AA_REG_BUCK2_CONF2 0x61
#define PV88080AA_REG_BUCK2_CONF5 0x64
#define PV88080AA_REG_BUCK3_CONF0 0x2B
#define PV88080AA_REG_BUCK3_CONF1 0x2C
#define PV88080AA_REG_BUCK3_CONF2 0x69
#define PV88080AA_REG_BUCK3_CONF5 0x6C
/* Regulator Registers - rev. BA */
#define PV88080BA_REG_HVBUCK_CONF1 0x33
#define PV88080BA_REG_HVBUCK_CONF2 0x34
#define PV88080BA_REG_BUCK1_CONF0 0x2A
#define PV88080BA_REG_BUCK1_CONF1 0x2C
#define PV88080BA_REG_BUCK1_CONF2 0x5A
#define PV88080BA_REG_BUCK1_CONF5 0x5D
#define PV88080BA_REG_BUCK2_CONF0 0x2D
#define PV88080BA_REG_BUCK2_CONF1 0x2F
#define PV88080BA_REG_BUCK2_CONF2 0x63
#define PV88080BA_REG_BUCK2_CONF5 0x66
#define PV88080BA_REG_BUCK3_CONF0 0x30
#define PV88080BA_REG_BUCK3_CONF1 0x32
#define PV88080BA_REG_BUCK3_CONF2 0x6C
#define PV88080BA_REG_BUCK3_CONF5 0x6F
/* PV88080_REG_EVENT_A (addr=0x04) */
#define PV88080_E_VDD_FLT 0x01
#define PV88080_E_OVER_TEMP 0x02
#define PV88080_E_OVER_TEMP 0x02
/* PV88080_REG_MASK_A (addr=0x09) */
#define PV88080_M_VDD_FLT 0x01
#define PV88080_M_OVER_TEMP 0x02
#define PV88080_M_OVER_TEMP 0x02
/* PV88080_REG_BUCK1_CONF0 (addr=0x27) */
/* PV88080_REG_BUCK1_CONF0 (addr=0x27|0x2A) */
#define PV88080_BUCK1_EN 0x80
#define PV88080_VBUCK1_MASK 0x7F
/* PV88080_REG_BUCK2_CONF0 (addr=0x29) */
#define PV88080_BUCK2_EN 0x80
#define PV88080_VBUCK2_MASK 0x7F
/* PV88080_REG_BUCK3_CONF0 (addr=0x2b) */
#define PV88080_BUCK3_EN 0x80
#define PV88080_VBUCK3_MASK 0x7F
#define PV88080_VBUCK1_MASK 0x7F
/* PV88080_REG_BUCK1_CONF1 (addr=0x28) */
#define PV88080_BUCK1_ILIM_SHIFT 2
/* PV88080_REG_BUCK2_CONF0 (addr=0x29|0x2D) */
#define PV88080_BUCK2_EN 0x80
#define PV88080_VBUCK2_MASK 0x7F
/* PV88080_REG_BUCK3_CONF0 (addr=0x2B|0x30) */
#define PV88080_BUCK3_EN 0x80
#define PV88080_VBUCK3_MASK 0x7F
/* PV88080_REG_BUCK1_CONF1 (addr=0x28|0x2C) */
#define PV88080_BUCK1_ILIM_SHIFT 2
#define PV88080_BUCK1_ILIM_MASK 0x0C
#define PV88080_BUCK1_MODE_MASK 0x03
/* PV88080_REG_BUCK2_CONF1 (addr=0x2a) */
#define PV88080_BUCK2_ILIM_SHIFT 2
/* PV88080_REG_BUCK2_CONF1 (addr=0x2A|0x2F) */
#define PV88080_BUCK2_ILIM_SHIFT 2
#define PV88080_BUCK2_ILIM_MASK 0x0C
#define PV88080_BUCK2_MODE_MASK 0x03
/* PV88080_REG_BUCK3_CONF1 (addr=0x2c) */
#define PV88080_BUCK3_ILIM_SHIFT 2
/* PV88080_REG_BUCK3_CONF1 (addr=0x2C|0x32) */
#define PV88080_BUCK3_ILIM_SHIFT 2
#define PV88080_BUCK3_ILIM_MASK 0x0C
#define PV88080_BUCK3_MODE_MASK 0x03
@@ -73,20 +93,26 @@
#define PV88080_BUCK_MODE_AUTO 0x01
#define PV88080_BUCK_MODE_SYNC 0x02
/* PV88080_REG_BUCK2_CONF2 (addr=0x61) */
/* PV88080_REG_BUCK3_CONF2 (addr=0x69) */
#define PV88080_BUCK_VDAC_RANGE_SHIFT 7
#define PV88080_BUCK_VDAC_RANGE_MASK 0x01
/* PV88080_REG_HVBUCK_CONF1 (addr=0x2D|0x33) */
#define PV88080_VHVBUCK_MASK 0xFF
#define PV88080_BUCK_VDAC_RANGE_1 0x00
#define PV88080_BUCK_VDAC_RANGE_2 0x01
/* PV88080_REG_HVBUCK_CONF1 (addr=0x2E|0x34) */
#define PV88080_HVBUCK_EN 0x01
/* PV88080_REG_BUCK2_CONF5 (addr=0x64) */
/* PV88080_REG_BUCK3_CONF5 (addr=0x6c) */
#define PV88080_BUCK_VRANGE_GAIN_SHIFT 0
#define PV88080_BUCK_VRANGE_GAIN_MASK 0x01
/* PV88080_REG_BUCK2_CONF2 (addr=0x61|0x63) */
/* PV88080_REG_BUCK3_CONF2 (addr=0x69|0x6C) */
#define PV88080_BUCK_VDAC_RANGE_SHIFT 7
#define PV88080_BUCK_VDAC_RANGE_MASK 0x01
#define PV88080_BUCK_VRANGE_GAIN_1 0x00
#define PV88080_BUCK_VRANGE_GAIN_2 0x01
#define PV88080_BUCK_VDAC_RANGE_1 0x00
#define PV88080_BUCK_VDAC_RANGE_2 0x01
/* PV88080_REG_BUCK2_CONF5 (addr=0x64|0x66) */
/* PV88080_REG_BUCK3_CONF5 (addr=0x6C|0x6F) */
#define PV88080_BUCK_VRANGE_GAIN_SHIFT 0
#define PV88080_BUCK_VRANGE_GAIN_MASK 0x01
#define PV88080_BUCK_VRANGE_GAIN_1 0x00
#define PV88080_BUCK_VRANGE_GAIN_2 0x01
#endif /* __PV88080_REGISTERS_H__ */

View File

@@ -14,7 +14,6 @@
*/
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -25,8 +24,6 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/regulator/of_regulator.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include "pv88090-regulator.h"
#define PV88090_MAX_REGULATORS 5

View File

@@ -10,7 +10,6 @@
* published by the Free Software Foundation.
*/
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
@@ -20,6 +19,13 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pwm.h>
#include <linux/gpio/consumer.h>
struct pwm_continuous_reg_data {
unsigned int min_uV_dutycycle;
unsigned int max_uV_dutycycle;
unsigned int dutycycle_unit;
};
struct pwm_regulator_data {
/* Shared */
@@ -28,6 +34,9 @@ struct pwm_regulator_data {
/* Voltage table */
struct pwm_voltages *duty_cycle_table;
/* Continuous mode info */
struct pwm_continuous_reg_data continuous;
/* regulator descriptor */
struct regulator_desc desc;
@@ -36,8 +45,8 @@ struct pwm_regulator_data {
int state;
/* Continuous voltage */
int volt_uV;
/* Enable GPIO */
struct gpio_desc *enb_gpio;
};
struct pwm_voltages {
@@ -48,10 +57,31 @@ struct pwm_voltages {
/**
* Voltage table call-backs
*/
static void pwm_regulator_init_state(struct regulator_dev *rdev)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
struct pwm_state pwm_state;
unsigned int dutycycle;
int i;
pwm_get_state(drvdata->pwm, &pwm_state);
dutycycle = pwm_get_relative_duty_cycle(&pwm_state, 100);
for (i = 0; i < rdev->desc->n_voltages; i++) {
if (dutycycle == drvdata->duty_cycle_table[i].dutycycle) {
drvdata->state = i;
return;
}
}
}
static int pwm_regulator_get_voltage_sel(struct regulator_dev *rdev)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
if (drvdata->state < 0)
pwm_regulator_init_state(rdev);
return drvdata->state;
}
@@ -59,16 +89,14 @@ static int pwm_regulator_set_voltage_sel(struct regulator_dev *rdev,
unsigned selector)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
struct pwm_args pargs;
int dutycycle;
struct pwm_state pstate;
int ret;
pwm_get_args(drvdata->pwm, &pargs);
pwm_init_state(drvdata->pwm, &pstate);
pwm_set_relative_duty_cycle(&pstate,
drvdata->duty_cycle_table[selector].dutycycle, 100);
dutycycle = (pargs.period *
drvdata->duty_cycle_table[selector].dutycycle) / 100;
ret = pwm_config(drvdata->pwm, dutycycle, pargs.period);
ret = pwm_apply_state(drvdata->pwm, &pstate);
if (ret) {
dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret);
return ret;
@@ -94,6 +122,9 @@ static int pwm_regulator_enable(struct regulator_dev *dev)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
if (drvdata->enb_gpio)
gpiod_set_value_cansleep(drvdata->enb_gpio, 1);
return pwm_enable(drvdata->pwm);
}
@@ -103,6 +134,9 @@ static int pwm_regulator_disable(struct regulator_dev *dev)
pwm_disable(drvdata->pwm);
if (drvdata->enb_gpio)
gpiod_set_value_cansleep(drvdata->enb_gpio, 0);
return 0;
}
@@ -110,65 +144,92 @@ static int pwm_regulator_is_enabled(struct regulator_dev *dev)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
if (drvdata->enb_gpio && !gpiod_get_value_cansleep(drvdata->enb_gpio))
return false;
return pwm_is_enabled(drvdata->pwm);
}
static int pwm_regulator_get_voltage(struct regulator_dev *rdev)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
unsigned int min_uV_duty = drvdata->continuous.min_uV_dutycycle;
unsigned int max_uV_duty = drvdata->continuous.max_uV_dutycycle;
unsigned int duty_unit = drvdata->continuous.dutycycle_unit;
int min_uV = rdev->constraints->min_uV;
int max_uV = rdev->constraints->max_uV;
int diff_uV = max_uV - min_uV;
struct pwm_state pstate;
unsigned int diff_duty;
unsigned int voltage;
return drvdata->volt_uV;
pwm_get_state(drvdata->pwm, &pstate);
voltage = pwm_get_relative_duty_cycle(&pstate, duty_unit);
/*
* The dutycycle for min_uV might be greater than the one for max_uV.
* This is happening when the user needs an inversed polarity, but the
* PWM device does not support inversing it in hardware.
*/
if (max_uV_duty < min_uV_duty) {
voltage = min_uV_duty - voltage;
diff_duty = min_uV_duty - max_uV_duty;
} else {
voltage = voltage - min_uV_duty;
diff_duty = max_uV_duty - min_uV_duty;
}
voltage = DIV_ROUND_CLOSEST_ULL((u64)voltage * diff_uV, diff_duty);
return voltage + min_uV;
}
static int pwm_regulator_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV,
unsigned *selector)
int req_min_uV, int req_max_uV,
unsigned int *selector)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
unsigned int ramp_delay = rdev->constraints->ramp_delay;
struct pwm_args pargs;
unsigned int req_diff = min_uV - rdev->constraints->min_uV;
unsigned int diff;
unsigned int duty_pulse;
u64 req_period;
u32 rem;
unsigned int min_uV_duty = drvdata->continuous.min_uV_dutycycle;
unsigned int max_uV_duty = drvdata->continuous.max_uV_dutycycle;
unsigned int duty_unit = drvdata->continuous.dutycycle_unit;
int min_uV = rdev->constraints->min_uV;
int max_uV = rdev->constraints->max_uV;
int diff_uV = max_uV - min_uV;
struct pwm_state pstate;
unsigned int diff_duty;
unsigned int dutycycle;
int ret;
pwm_get_args(drvdata->pwm, &pargs);
diff = rdev->constraints->max_uV - rdev->constraints->min_uV;
pwm_init_state(drvdata->pwm, &pstate);
/* First try to find out if we get the iduty cycle time which is
* factor of PWM period time. If (request_diff_to_min * pwm_period)
* is perfect divided by voltage_range_diff then it is possible to
* get duty cycle time which is factor of PWM period. This will help
* to get output voltage nearer to requested value as there is no
* calculation loss.
/*
* The dutycycle for min_uV might be greater than the one for max_uV.
* This is happening when the user needs an inversed polarity, but the
* PWM device does not support inversing it in hardware.
*/
req_period = req_diff * pargs.period;
div_u64_rem(req_period, diff, &rem);
if (!rem) {
do_div(req_period, diff);
duty_pulse = (unsigned int)req_period;
} else {
duty_pulse = (pargs.period / 100) * ((req_diff * 100) / diff);
}
if (max_uV_duty < min_uV_duty)
diff_duty = min_uV_duty - max_uV_duty;
else
diff_duty = max_uV_duty - min_uV_duty;
ret = pwm_config(drvdata->pwm, duty_pulse, pargs.period);
dutycycle = DIV_ROUND_CLOSEST_ULL((u64)(req_min_uV - min_uV) *
diff_duty,
diff_uV);
if (max_uV_duty < min_uV_duty)
dutycycle = min_uV_duty - dutycycle;
else
dutycycle = min_uV_duty + dutycycle;
pwm_set_relative_duty_cycle(&pstate, dutycycle, duty_unit);
ret = pwm_apply_state(drvdata->pwm, &pstate);
if (ret) {
dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret);
return ret;
}
ret = pwm_enable(drvdata->pwm);
if (ret) {
dev_err(&rdev->dev, "Failed to enable PWM: %d\n", ret);
return ret;
}
drvdata->volt_uV = min_uV;
/* Delay required by PWM regulator to settle to the new voltage */
usleep_range(ramp_delay, ramp_delay + 1000);
return 0;
}
@@ -226,6 +287,7 @@ static int pwm_regulator_init_table(struct platform_device *pdev,
return ret;
}
drvdata->state = -EINVAL;
drvdata->duty_cycle_table = duty_cycle_table;
memcpy(&drvdata->ops, &pwm_regulator_voltage_table_ops,
sizeof(drvdata->ops));
@@ -238,11 +300,28 @@ static int pwm_regulator_init_table(struct platform_device *pdev,
static int pwm_regulator_init_continuous(struct platform_device *pdev,
struct pwm_regulator_data *drvdata)
{
u32 dutycycle_range[2] = { 0, 100 };
u32 dutycycle_unit = 100;
memcpy(&drvdata->ops, &pwm_regulator_voltage_continuous_ops,
sizeof(drvdata->ops));
drvdata->desc.ops = &drvdata->ops;
drvdata->desc.continuous_voltage_range = true;
of_property_read_u32_array(pdev->dev.of_node,
"pwm-dutycycle-range",
dutycycle_range, 2);
of_property_read_u32(pdev->dev.of_node, "pwm-dutycycle-unit",
&dutycycle_unit);
if (dutycycle_range[0] > dutycycle_unit ||
dutycycle_range[1] > dutycycle_unit)
return -EINVAL;
drvdata->continuous.dutycycle_unit = dutycycle_unit;
drvdata->continuous.min_uV_dutycycle = dutycycle_range[0];
drvdata->continuous.max_uV_dutycycle = dutycycle_range[1];
return 0;
}
@@ -253,6 +332,7 @@ static int pwm_regulator_probe(struct platform_device *pdev)
struct regulator_dev *regulator;
struct regulator_config config = { };
struct device_node *np = pdev->dev.of_node;
enum gpiod_flags gpio_flags;
int ret;
if (!np) {
@@ -290,11 +370,21 @@ static int pwm_regulator_probe(struct platform_device *pdev)
return ret;
}
/*
* FIXME: pwm_apply_args() should be removed when switching to the
* atomic PWM API.
*/
pwm_apply_args(drvdata->pwm);
if (init_data->constraints.boot_on || init_data->constraints.always_on)
gpio_flags = GPIOD_OUT_HIGH;
else
gpio_flags = GPIOD_OUT_LOW;
drvdata->enb_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
gpio_flags);
if (IS_ERR(drvdata->enb_gpio)) {
ret = PTR_ERR(drvdata->enb_gpio);
dev_err(&pdev->dev, "Failed to get enable GPIO: %d\n", ret);
return ret;
}
ret = pwm_adjust_config(drvdata->pwm);
if (ret)
return ret;
regulator = devm_regulator_register(&pdev->dev,
&drvdata->desc, &config);

View File

@@ -447,6 +447,44 @@ static struct regulator_ops switch_ops = {
.is_enabled = rpm_reg_is_enabled,
};
/*
* PM8018 regulators
*/
static const struct qcom_rpm_reg pm8018_pldo = {
.desc.linear_ranges = pldo_ranges,
.desc.n_linear_ranges = ARRAY_SIZE(pldo_ranges),
.desc.n_voltages = 161,
.desc.ops = &uV_ops,
.parts = &rpm8960_ldo_parts,
.supports_force_mode_auto = false,
.supports_force_mode_bypass = false,
};
static const struct qcom_rpm_reg pm8018_nldo = {
.desc.linear_ranges = nldo_ranges,
.desc.n_linear_ranges = ARRAY_SIZE(nldo_ranges),
.desc.n_voltages = 64,
.desc.ops = &uV_ops,
.parts = &rpm8960_ldo_parts,
.supports_force_mode_auto = false,
.supports_force_mode_bypass = false,
};
static const struct qcom_rpm_reg pm8018_smps = {
.desc.linear_ranges = smps_ranges,
.desc.n_linear_ranges = ARRAY_SIZE(smps_ranges),
.desc.n_voltages = 154,
.desc.ops = &uV_ops,
.parts = &rpm8960_smps_parts,
.supports_force_mode_auto = false,
.supports_force_mode_bypass = false,
};
static const struct qcom_rpm_reg pm8018_switch = {
.desc.ops = &switch_ops,
.parts = &rpm8960_switch_parts,
};
/*
* PM8058 regulators
*/
@@ -755,6 +793,32 @@ struct rpm_regulator_data {
const char *supply;
};
static const struct rpm_regulator_data rpm_pm8018_regulators[] = {
{ "s1", QCOM_RPM_PM8018_SMPS1, &pm8018_smps, "vdd_s1" },
{ "s2", QCOM_RPM_PM8018_SMPS2, &pm8018_smps, "vdd_s2" },
{ "s3", QCOM_RPM_PM8018_SMPS3, &pm8018_smps, "vdd_s3" },
{ "s4", QCOM_RPM_PM8018_SMPS4, &pm8018_smps, "vdd_s4" },
{ "s5", QCOM_RPM_PM8018_SMPS5, &pm8018_smps, "vdd_s5" },
{ "l2", QCOM_RPM_PM8018_LDO2, &pm8018_pldo, "vdd_l2" },
{ "l3", QCOM_RPM_PM8018_LDO3, &pm8018_pldo, "vdd_l3" },
{ "l4", QCOM_RPM_PM8018_LDO4, &pm8018_pldo, "vdd_l4" },
{ "l5", QCOM_RPM_PM8018_LDO5, &pm8018_pldo, "vdd_l5" },
{ "l6", QCOM_RPM_PM8018_LDO6, &pm8018_pldo, "vdd_l7" },
{ "l7", QCOM_RPM_PM8018_LDO7, &pm8018_pldo, "vdd_l7" },
{ "l8", QCOM_RPM_PM8018_LDO8, &pm8018_nldo, "vdd_l8" },
{ "l9", QCOM_RPM_PM8018_LDO9, &pm8921_nldo1200,
"vdd_l9_l10_l11_l12" },
{ "l10", QCOM_RPM_PM8018_LDO10, &pm8018_nldo, "vdd_l9_l10_l11_l12" },
{ "l11", QCOM_RPM_PM8018_LDO11, &pm8018_nldo, "vdd_l9_l10_l11_l12" },
{ "l12", QCOM_RPM_PM8018_LDO12, &pm8018_nldo, "vdd_l9_l10_l11_l12" },
{ "l14", QCOM_RPM_PM8018_LDO14, &pm8018_pldo, "vdd_l14" },
{ "lvs1", QCOM_RPM_PM8018_LVS1, &pm8018_switch, "lvs1_in" },
{ }
};
static const struct rpm_regulator_data rpm_pm8058_regulators[] = {
{ "l0", QCOM_RPM_PM8058_LDO0, &pm8058_nldo, "vdd_l0_l1_lvs" },
{ "l1", QCOM_RPM_PM8058_LDO1, &pm8058_nldo, "vdd_l0_l1_lvs" },
@@ -870,6 +934,8 @@ static const struct rpm_regulator_data rpm_pm8921_regulators[] = {
};
static const struct of_device_id rpm_of_match[] = {
{ .compatible = "qcom,rpm-pm8018-regulators",
.data = &rpm_pm8018_regulators },
{ .compatible = "qcom,rpm-pm8058-regulators", .data = &rpm_pm8058_regulators },
{ .compatible = "qcom,rpm-pm8901-regulators", .data = &rpm_pm8901_regulators },
{ .compatible = "qcom,rpm-pm8921-regulators", .data = &rpm_pm8921_regulators },

View File

@@ -140,6 +140,18 @@ static const struct regulator_ops rpm_smps_ldo_ops = {
.enable = rpm_reg_enable,
.disable = rpm_reg_disable,
.is_enabled = rpm_reg_is_enabled,
.list_voltage = regulator_list_voltage_linear_range,
.get_voltage = rpm_reg_get_voltage,
.set_voltage = rpm_reg_set_voltage,
.set_load = rpm_reg_set_load,
};
static const struct regulator_ops rpm_smps_ldo_ops_fixed = {
.enable = rpm_reg_enable,
.disable = rpm_reg_disable,
.is_enabled = rpm_reg_is_enabled,
.get_voltage = rpm_reg_get_voltage,
.set_voltage = rpm_reg_set_voltage,
@@ -166,20 +178,21 @@ static const struct regulator_desc pma8084_hfsmps = {
static const struct regulator_desc pma8084_ftsmps = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(350000, 0, 184, 5000),
REGULATOR_LINEAR_RANGE(700000, 185, 339, 10000),
REGULATOR_LINEAR_RANGE(1280000, 185, 261, 10000),
},
.n_linear_ranges = 2,
.n_voltages = 340,
.n_voltages = 262,
.ops = &rpm_smps_ldo_ops,
};
static const struct regulator_desc pma8084_pldo = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(750000, 0, 30, 25000),
REGULATOR_LINEAR_RANGE(1500000, 31, 99, 50000),
REGULATOR_LINEAR_RANGE( 750000, 0, 63, 12500),
REGULATOR_LINEAR_RANGE(1550000, 64, 126, 25000),
REGULATOR_LINEAR_RANGE(3100000, 127, 163, 50000),
},
.n_linear_ranges = 2,
.n_voltages = 100,
.n_linear_ranges = 3,
.n_voltages = 164,
.ops = &rpm_smps_ldo_ops,
};
@@ -199,7 +212,7 @@ static const struct regulator_desc pma8084_switch = {
static const struct regulator_desc pm8x41_hfsmps = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE( 375000, 0, 95, 12500),
REGULATOR_LINEAR_RANGE(1550000, 96, 158, 25000),
REGULATOR_LINEAR_RANGE(1575000, 96, 158, 25000),
},
.n_linear_ranges = 2,
.n_voltages = 159,
@@ -209,29 +222,30 @@ static const struct regulator_desc pm8x41_hfsmps = {
static const struct regulator_desc pm8841_ftsmps = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(350000, 0, 184, 5000),
REGULATOR_LINEAR_RANGE(700000, 185, 339, 10000),
REGULATOR_LINEAR_RANGE(1280000, 185, 261, 10000),
},
.n_linear_ranges = 2,
.n_voltages = 340,
.n_voltages = 262,
.ops = &rpm_smps_ldo_ops,
};
static const struct regulator_desc pm8941_boost = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(4000000, 0, 15, 100000),
REGULATOR_LINEAR_RANGE(4000000, 0, 30, 50000),
},
.n_linear_ranges = 1,
.n_voltages = 16,
.n_voltages = 31,
.ops = &rpm_smps_ldo_ops,
};
static const struct regulator_desc pm8941_pldo = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE( 750000, 0, 30, 25000),
REGULATOR_LINEAR_RANGE(1500000, 31, 99, 50000),
REGULATOR_LINEAR_RANGE( 750000, 0, 63, 12500),
REGULATOR_LINEAR_RANGE(1550000, 64, 126, 25000),
REGULATOR_LINEAR_RANGE(3100000, 127, 163, 50000),
},
.n_linear_ranges = 2,
.n_voltages = 100,
.n_linear_ranges = 3,
.n_voltages = 164,
.ops = &rpm_smps_ldo_ops,
};
@@ -247,7 +261,7 @@ static const struct regulator_desc pm8941_nldo = {
static const struct regulator_desc pm8941_lnldo = {
.fixed_uV = 1740000,
.n_voltages = 1,
.ops = &rpm_smps_ldo_ops,
.ops = &rpm_smps_ldo_ops_fixed,
};
static const struct regulator_desc pm8941_switch = {

View File

@@ -1085,6 +1085,8 @@ static struct regulator_ops spmi_vs_ops = {
.set_pull_down = spmi_regulator_common_set_pull_down,
.set_soft_start = spmi_regulator_common_set_soft_start,
.set_over_current_protection = spmi_regulator_vs_ocp,
.set_mode = spmi_regulator_common_set_mode,
.get_mode = spmi_regulator_common_get_mode,
};
static struct regulator_ops spmi_boost_ops = {
@@ -1496,6 +1498,7 @@ static const struct spmi_regulator_data pm8941_regulators[] = {
{ "s1", 0x1400, "vdd_s1", },
{ "s2", 0x1700, "vdd_s2", },
{ "s3", 0x1a00, "vdd_s3", },
{ "s4", 0xa000, },
{ "l1", 0x4000, "vdd_l1_l3", },
{ "l2", 0x4100, "vdd_l2_lvs_1_2_3", },
{ "l3", 0x4200, "vdd_l1_l3", },
@@ -1523,8 +1526,8 @@ static const struct spmi_regulator_data pm8941_regulators[] = {
{ "lvs1", 0x8000, "vdd_l2_lvs_1_2_3", },
{ "lvs2", 0x8100, "vdd_l2_lvs_1_2_3", },
{ "lvs3", 0x8200, "vdd_l2_lvs_1_2_3", },
{ "mvs1", 0x8300, "vin_5vs", },
{ "mvs2", 0x8400, "vin_5vs", },
{ "5vs1", 0x8300, "vin_5vs", "ocp-5vs1", },
{ "5vs2", 0x8400, "vin_5vs", "ocp-5vs2", },
{ }
};

View File

@@ -1,11 +1,15 @@
/*
* Regulator driver for Rockchip RK808
* Regulator driver for Rockchip RK808/RK818
*
* Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
*
* Author: Chris Zhong <zyw@rock-chips.com>
* Author: Zhang Qing <zhangqing@rock-chips.com>
*
* Copyright (C) 2016 PHYTEC Messtechnik GmbH
*
* Author: Wadim Egorov <w.egorov@phytec.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
@@ -32,6 +36,12 @@
#define RK808_BUCK4_VSEL_MASK 0xf
#define RK808_LDO_VSEL_MASK 0x1f
#define RK818_BUCK_VSEL_MASK 0x3f
#define RK818_BUCK4_VSEL_MASK 0x1f
#define RK818_LDO_VSEL_MASK 0x1f
#define RK818_LDO3_ON_VSEL_MASK 0xf
#define RK818_BOOST_ON_VSEL_MASK 0xe0
/* Ramp rate definitions for buck1 / buck2 only */
#define RK808_RAMP_RATE_OFFSET 3
#define RK808_RAMP_RATE_MASK (3 << RK808_RAMP_RATE_OFFSET)
@@ -454,6 +464,108 @@ static const struct regulator_desc rk808_reg[] = {
RK808_DCDC_EN_REG, BIT(6)),
};
static const struct regulator_desc rk818_reg[] = {
{
.name = "DCDC_REG1",
.supply_name = "vcc1",
.of_match = of_match_ptr("DCDC_REG1"),
.regulators_node = of_match_ptr("regulators"),
.id = RK818_ID_DCDC1,
.ops = &rk808_reg_ops,
.type = REGULATOR_VOLTAGE,
.min_uV = 712500,
.uV_step = 12500,
.n_voltages = 64,
.vsel_reg = RK818_BUCK1_ON_VSEL_REG,
.vsel_mask = RK818_BUCK_VSEL_MASK,
.enable_reg = RK818_DCDC_EN_REG,
.enable_mask = BIT(0),
.owner = THIS_MODULE,
}, {
.name = "DCDC_REG2",
.supply_name = "vcc2",
.of_match = of_match_ptr("DCDC_REG2"),
.regulators_node = of_match_ptr("regulators"),
.id = RK818_ID_DCDC2,
.ops = &rk808_reg_ops,
.type = REGULATOR_VOLTAGE,
.min_uV = 712500,
.uV_step = 12500,
.n_voltages = 64,
.vsel_reg = RK818_BUCK2_ON_VSEL_REG,
.vsel_mask = RK818_BUCK_VSEL_MASK,
.enable_reg = RK818_DCDC_EN_REG,
.enable_mask = BIT(1),
.owner = THIS_MODULE,
}, {
.name = "DCDC_REG3",
.supply_name = "vcc3",
.of_match = of_match_ptr("DCDC_REG3"),
.regulators_node = of_match_ptr("regulators"),
.id = RK818_ID_DCDC3,
.ops = &rk808_switch_ops,
.type = REGULATOR_VOLTAGE,
.n_voltages = 1,
.enable_reg = RK818_DCDC_EN_REG,
.enable_mask = BIT(2),
.owner = THIS_MODULE,
},
RK8XX_DESC(RK818_ID_DCDC4, "DCDC_REG4", "vcc4", 1800, 3600, 100,
RK818_BUCK4_ON_VSEL_REG, RK818_BUCK4_VSEL_MASK,
RK818_DCDC_EN_REG, BIT(3), 0),
RK8XX_DESC(RK818_ID_BOOST, "DCDC_BOOST", "boost", 4700, 5400, 100,
RK818_BOOST_LDO9_ON_VSEL_REG, RK818_BOOST_ON_VSEL_MASK,
RK818_DCDC_EN_REG, BIT(4), 0),
RK8XX_DESC(RK818_ID_LDO1, "LDO_REG1", "vcc6", 1800, 3400, 100,
RK818_LDO1_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
BIT(0), 400),
RK8XX_DESC(RK818_ID_LDO2, "LDO_REG2", "vcc6", 1800, 3400, 100,
RK818_LDO1_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
BIT(1), 400),
{
.name = "LDO_REG3",
.supply_name = "vcc7",
.of_match = of_match_ptr("LDO_REG3"),
.regulators_node = of_match_ptr("regulators"),
.id = RK818_ID_LDO3,
.ops = &rk808_reg_ops_ranges,
.type = REGULATOR_VOLTAGE,
.n_voltages = 16,
.linear_ranges = rk808_ldo3_voltage_ranges,
.n_linear_ranges = ARRAY_SIZE(rk808_ldo3_voltage_ranges),
.vsel_reg = RK818_LDO3_ON_VSEL_REG,
.vsel_mask = RK818_LDO3_ON_VSEL_MASK,
.enable_reg = RK818_LDO_EN_REG,
.enable_mask = BIT(2),
.enable_time = 400,
.owner = THIS_MODULE,
},
RK8XX_DESC(RK818_ID_LDO4, "LDO_REG4", "vcc8", 1800, 3400, 100,
RK818_LDO4_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
BIT(3), 400),
RK8XX_DESC(RK818_ID_LDO5, "LDO_REG5", "vcc7", 1800, 3400, 100,
RK818_LDO5_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
BIT(4), 400),
RK8XX_DESC(RK818_ID_LDO6, "LDO_REG6", "vcc8", 800, 2500, 100,
RK818_LDO6_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
BIT(5), 400),
RK8XX_DESC(RK818_ID_LDO7, "LDO_REG7", "vcc7", 800, 2500, 100,
RK818_LDO7_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
BIT(6), 400),
RK8XX_DESC(RK818_ID_LDO8, "LDO_REG8", "vcc8", 1800, 3400, 100,
RK818_LDO8_ON_VSEL_REG, RK818_LDO_VSEL_MASK, RK818_LDO_EN_REG,
BIT(7), 400),
RK8XX_DESC(RK818_ID_LDO9, "LDO_REG9", "vcc9", 1800, 3400, 100,
RK818_BOOST_LDO9_ON_VSEL_REG, RK818_LDO_VSEL_MASK,
RK818_DCDC_EN_REG, BIT(5), 400),
RK8XX_DESC_SWITCH(RK818_ID_SWITCH, "SWITCH_REG", "vcc9",
RK818_DCDC_EN_REG, BIT(6)),
RK8XX_DESC_SWITCH(RK818_ID_HDMI_SWITCH, "HDMI_SWITCH", "h_5v",
RK818_H5V_EN_REG, BIT(0)),
RK8XX_DESC_SWITCH(RK818_ID_OTG_SWITCH, "OTG_SWITCH", "usb",
RK818_DCDC_EN_REG, BIT(7)),
};
static int rk808_regulator_dt_parse_pdata(struct device *dev,
struct device *client_dev,
struct regmap *map,
@@ -499,7 +611,8 @@ static int rk808_regulator_probe(struct platform_device *pdev)
struct regulator_config config = {};
struct regulator_dev *rk808_rdev;
struct rk808_regulator_data *pdata;
int ret, i;
const struct regulator_desc *regulators;
int ret, i, nregulators;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
@@ -512,14 +625,29 @@ static int rk808_regulator_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, pdata);
switch (rk808->variant) {
case RK808_ID:
regulators = rk808_reg;
nregulators = RK808_NUM_REGULATORS;
break;
case RK818_ID:
regulators = rk818_reg;
nregulators = RK818_NUM_REGULATORS;
break;
default:
dev_err(&client->dev, "unsupported RK8XX ID %lu\n",
rk808->variant);
return -EINVAL;
}
config.dev = &client->dev;
config.driver_data = pdata;
config.regmap = rk808->regmap;
/* Instantiate the regulators */
for (i = 0; i < RK808_NUM_REGULATORS; i++) {
for (i = 0; i < nregulators; i++) {
rk808_rdev = devm_regulator_register(&pdev->dev,
&rk808_reg[i], &config);
&regulators[i], &config);
if (IS_ERR(rk808_rdev)) {
dev_err(&client->dev,
"failed to register %d regulator\n", i);
@@ -533,15 +661,15 @@ static int rk808_regulator_probe(struct platform_device *pdev)
static struct platform_driver rk808_regulator_driver = {
.probe = rk808_regulator_probe,
.driver = {
.name = "rk808-regulator",
.owner = THIS_MODULE,
.name = "rk808-regulator"
},
};
module_platform_driver(rk808_regulator_driver);
MODULE_DESCRIPTION("regulator driver for the rk808 series PMICs");
MODULE_AUTHOR("Chris Zhong<zyw@rock-chips.com>");
MODULE_AUTHOR("Zhang Qing<zhangqing@rock-chips.com>");
MODULE_DESCRIPTION("regulator driver for the RK808/RK818 series PMICs");
MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
MODULE_AUTHOR("Wadim Egorov <w.egorov@phytec.de>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:rk808-regulator");

View File

@@ -46,6 +46,23 @@ static struct regulator_ops rn5t618_reg_ops = {
.vsel_mask = (vmask), \
}
static struct regulator_desc rn5t567_regulators[] = {
/* DCDC */
REG(DCDC1, DC1CTL, BIT(0), DC1DAC, 0xff, 600000, 3500000, 12500),
REG(DCDC2, DC2CTL, BIT(0), DC2DAC, 0xff, 600000, 3500000, 12500),
REG(DCDC3, DC3CTL, BIT(0), DC3DAC, 0xff, 600000, 3500000, 12500),
REG(DCDC4, DC4CTL, BIT(0), DC4DAC, 0xff, 600000, 3500000, 12500),
/* LDO */
REG(LDO1, LDOEN1, BIT(0), LDO1DAC, 0x7f, 900000, 3500000, 25000),
REG(LDO2, LDOEN1, BIT(1), LDO2DAC, 0x7f, 900000, 3500000, 25000),
REG(LDO3, LDOEN1, BIT(2), LDO3DAC, 0x7f, 600000, 3500000, 25000),
REG(LDO4, LDOEN1, BIT(3), LDO4DAC, 0x7f, 900000, 3500000, 25000),
REG(LDO5, LDOEN1, BIT(4), LDO5DAC, 0x7f, 900000, 3500000, 25000),
/* LDO RTC */
REG(LDORTC1, LDOEN2, BIT(4), LDORTCDAC, 0x7f, 1200000, 3500000, 25000),
REG(LDORTC2, LDOEN2, BIT(5), LDORTC2DAC, 0x7f, 900000, 3500000, 25000),
};
static struct regulator_desc rn5t618_regulators[] = {
/* DCDC */
REG(DCDC1, DC1CTL, BIT(0), DC1DAC, 0xff, 600000, 3500000, 12500),
@@ -67,18 +84,33 @@ static int rn5t618_regulator_probe(struct platform_device *pdev)
struct rn5t618 *rn5t618 = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = { };
struct regulator_dev *rdev;
struct regulator_desc *regulators;
int i;
switch (rn5t618->variant) {
case RN5T567:
regulators = rn5t567_regulators;
break;
case RN5T618:
regulators = rn5t618_regulators;
break;
default:
return -EINVAL;
}
config.dev = pdev->dev.parent;
config.regmap = rn5t618->regmap;
for (i = 0; i < RN5T618_REG_NUM; i++) {
config.dev = pdev->dev.parent;
config.regmap = rn5t618->regmap;
if (!regulators[i].name)
continue;
rdev = devm_regulator_register(&pdev->dev,
&rn5t618_regulators[i],
&regulators[i],
&config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register %s regulator\n",
rn5t618_regulators[i].name);
regulators[i].name);
return PTR_ERR(rdev);
}
}

View File

@@ -750,7 +750,7 @@ static const struct regulator_linear_range s2mps15_ldo_voltage_ranges3[] = {
/* voltage range for s2mps15 LDO 7, 8, 9 and 10 */
static const struct regulator_linear_range s2mps15_ldo_voltage_ranges4[] = {
REGULATOR_LINEAR_RANGE(700000, 0xc, 0x18, 25000),
REGULATOR_LINEAR_RANGE(700000, 0x10, 0x20, 25000),
};
/* voltage range for s2mps15 LDO 1 */
@@ -760,12 +760,12 @@ static const struct regulator_linear_range s2mps15_ldo_voltage_ranges5[] = {
/* voltage range for s2mps15 BUCK 1, 2, 3, 4, 5, 6 and 7 */
static const struct regulator_linear_range s2mps15_buck_voltage_ranges1[] = {
REGULATOR_LINEAR_RANGE(500000, 0x20, 0xb0, 6250),
REGULATOR_LINEAR_RANGE(500000, 0x20, 0xc0, 6250),
};
/* voltage range for s2mps15 BUCK 8, 9 and 10 */
static const struct regulator_linear_range s2mps15_buck_voltage_ranges2[] = {
REGULATOR_LINEAR_RANGE(1000000, 0x20, 0xc0, 12500),
REGULATOR_LINEAR_RANGE(1000000, 0x20, 0x78, 12500),
};
static const struct regulator_desc s2mps15_regulators[] = {

View File

@@ -94,11 +94,14 @@ static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev,
int ramp_delay)
{
struct tps51632_chip *tps = rdev_get_drvdata(rdev);
int bit = ramp_delay/6000;
int bit;
int ret;
if (bit)
bit--;
if (ramp_delay == 0)
bit = 0;
else
bit = DIV_ROUND_UP(ramp_delay, 6000) - 1;
ret = regmap_write(tps->regmap, TPS51632_SLEW_REGS, BIT(bit));
if (ret < 0)
dev_err(tps->dev, "SLEW reg write failed, err %d\n", ret);

View File

@@ -28,7 +28,7 @@
#include <linux/mfd/tps65217.h>
#define TPS65217_REGULATOR(_name, _id, _of_match, _ops, _n, _vr, _vm, _em, \
_t, _lr, _nlr) \
_t, _lr, _nlr, _sr, _sm) \
{ \
.name = _name, \
.id = _id, \
@@ -45,6 +45,8 @@
.volt_table = _t, \
.linear_ranges = _lr, \
.n_linear_ranges = _nlr, \
.bypass_reg = _sr, \
.bypass_mask = _sm, \
} \
static const unsigned int LDO1_VSEL_table[] = {
@@ -118,6 +120,35 @@ static int tps65217_pmic_set_voltage_sel(struct regulator_dev *dev,
return ret;
}
static int tps65217_pmic_set_suspend_enable(struct regulator_dev *dev)
{
struct tps65217 *tps = rdev_get_drvdata(dev);
unsigned int rid = rdev_get_id(dev);
if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
return -EINVAL;
return tps65217_clear_bits(tps, dev->desc->bypass_reg,
dev->desc->bypass_mask,
TPS65217_PROTECT_L1);
}
static int tps65217_pmic_set_suspend_disable(struct regulator_dev *dev)
{
struct tps65217 *tps = rdev_get_drvdata(dev);
unsigned int rid = rdev_get_id(dev);
if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
return -EINVAL;
if (!tps->strobes[rid])
return -EINVAL;
return tps65217_set_bits(tps, dev->desc->bypass_reg,
dev->desc->bypass_mask,
tps->strobes[rid], TPS65217_PROTECT_L1);
}
/* Operations permitted on DCDCx, LDO2, LDO3 and LDO4 */
static struct regulator_ops tps65217_pmic_ops = {
.is_enabled = regulator_is_enabled_regmap,
@@ -127,6 +158,8 @@ static struct regulator_ops tps65217_pmic_ops = {
.set_voltage_sel = tps65217_pmic_set_voltage_sel,
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.set_suspend_enable = tps65217_pmic_set_suspend_enable,
.set_suspend_disable = tps65217_pmic_set_suspend_disable,
};
/* Operations permitted on LDO1 */
@@ -138,41 +171,50 @@ static struct regulator_ops tps65217_pmic_ldo1_ops = {
.set_voltage_sel = tps65217_pmic_set_voltage_sel,
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.set_suspend_enable = tps65217_pmic_set_suspend_enable,
.set_suspend_disable = tps65217_pmic_set_suspend_disable,
};
static const struct regulator_desc regulators[] = {
TPS65217_REGULATOR("DCDC1", TPS65217_DCDC_1, "dcdc1",
tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC1,
TPS65217_DEFDCDCX_DCDC_MASK, TPS65217_ENABLE_DC1_EN,
NULL, tps65217_uv1_ranges, 2),
NULL, tps65217_uv1_ranges, 2, TPS65217_REG_SEQ1,
TPS65217_SEQ1_DC1_SEQ_MASK),
TPS65217_REGULATOR("DCDC2", TPS65217_DCDC_2, "dcdc2",
tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC2,
TPS65217_DEFDCDCX_DCDC_MASK, TPS65217_ENABLE_DC2_EN,
NULL, tps65217_uv1_ranges,
ARRAY_SIZE(tps65217_uv1_ranges)),
ARRAY_SIZE(tps65217_uv1_ranges), TPS65217_REG_SEQ1,
TPS65217_SEQ1_DC2_SEQ_MASK),
TPS65217_REGULATOR("DCDC3", TPS65217_DCDC_3, "dcdc3",
tps65217_pmic_ops, 64, TPS65217_REG_DEFDCDC3,
TPS65217_DEFDCDCX_DCDC_MASK, TPS65217_ENABLE_DC3_EN,
NULL, tps65217_uv1_ranges, 1),
NULL, tps65217_uv1_ranges, 1, TPS65217_REG_SEQ2,
TPS65217_SEQ2_DC3_SEQ_MASK),
TPS65217_REGULATOR("LDO1", TPS65217_LDO_1, "ldo1",
tps65217_pmic_ldo1_ops, 16, TPS65217_REG_DEFLDO1,
TPS65217_DEFLDO1_LDO1_MASK, TPS65217_ENABLE_LDO1_EN,
LDO1_VSEL_table, NULL, 0),
LDO1_VSEL_table, NULL, 0, TPS65217_REG_SEQ2,
TPS65217_SEQ2_LDO1_SEQ_MASK),
TPS65217_REGULATOR("LDO2", TPS65217_LDO_2, "ldo2", tps65217_pmic_ops,
64, TPS65217_REG_DEFLDO2,
TPS65217_DEFLDO2_LDO2_MASK, TPS65217_ENABLE_LDO2_EN,
NULL, tps65217_uv1_ranges,
ARRAY_SIZE(tps65217_uv1_ranges)),
ARRAY_SIZE(tps65217_uv1_ranges), TPS65217_REG_SEQ3,
TPS65217_SEQ3_LDO2_SEQ_MASK),
TPS65217_REGULATOR("LDO3", TPS65217_LDO_3, "ldo3", tps65217_pmic_ops,
32, TPS65217_REG_DEFLS1, TPS65217_DEFLDO3_LDO3_MASK,
TPS65217_ENABLE_LS1_EN | TPS65217_DEFLDO3_LDO3_EN,
NULL, tps65217_uv2_ranges,
ARRAY_SIZE(tps65217_uv2_ranges)),
ARRAY_SIZE(tps65217_uv2_ranges), TPS65217_REG_SEQ3,
TPS65217_SEQ3_LDO3_SEQ_MASK),
TPS65217_REGULATOR("LDO4", TPS65217_LDO_4, "ldo4", tps65217_pmic_ops,
32, TPS65217_REG_DEFLS2, TPS65217_DEFLDO4_LDO4_MASK,
TPS65217_ENABLE_LS2_EN | TPS65217_DEFLDO4_LDO4_EN,
NULL, tps65217_uv2_ranges,
ARRAY_SIZE(tps65217_uv2_ranges)),
ARRAY_SIZE(tps65217_uv2_ranges), TPS65217_REG_SEQ4,
TPS65217_SEQ4_LDO4_SEQ_MASK),
};
static int tps65217_regulator_probe(struct platform_device *pdev)
@@ -181,13 +223,18 @@ static int tps65217_regulator_probe(struct platform_device *pdev)
struct tps65217_board *pdata = dev_get_platdata(tps->dev);
struct regulator_dev *rdev;
struct regulator_config config = { };
int i;
int i, ret;
unsigned int val;
if (tps65217_chip_id(tps) != TPS65217) {
dev_err(&pdev->dev, "Invalid tps chip version\n");
return -ENODEV;
}
/* Allocate memory for strobes */
tps->strobes = devm_kzalloc(&pdev->dev, sizeof(u8) *
TPS65217_NUM_REGULATOR, GFP_KERNEL);
platform_set_drvdata(pdev, tps);
for (i = 0; i < TPS65217_NUM_REGULATOR; i++) {
@@ -205,6 +252,10 @@ static int tps65217_regulator_probe(struct platform_device *pdev)
pdev->name);
return PTR_ERR(rdev);
}
/* Store default strobe info */
ret = tps65217_reg_read(tps, regulators[i].bypass_reg, &val);
tps->strobes[i] = val & regulators[i].bypass_mask;
}
return 0;

View File

@@ -31,7 +31,7 @@ enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4,
DCDC5, DCDC6, LDO1, LS3 };
#define TPS65218_REGULATOR(_name, _id, _type, _ops, _n, _vr, _vm, _er, _em, \
_cr, _cm, _lr, _nlr, _delay, _fuv) \
_cr, _cm, _lr, _nlr, _delay, _fuv, _sr, _sm) \
{ \
.name = _name, \
.id = _id, \
@@ -49,7 +49,9 @@ enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4,
.linear_ranges = _lr, \
.n_linear_ranges = _nlr, \
.ramp_delay = _delay, \
.fixed_uV = _fuv \
.fixed_uV = _fuv, \
.bypass_reg = _sr, \
.bypass_mask = _sm, \
} \
#define TPS65218_INFO(_id, _nm, _min, _max) \
@@ -157,6 +159,48 @@ static int tps65218_pmic_disable(struct regulator_dev *dev)
dev->desc->enable_mask, TPS65218_PROTECT_L1);
}
static int tps65218_pmic_set_suspend_enable(struct regulator_dev *dev)
{
struct tps65218 *tps = rdev_get_drvdata(dev);
unsigned int rid = rdev_get_id(dev);
if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1)
return -EINVAL;
return tps65218_clear_bits(tps, dev->desc->bypass_reg,
dev->desc->bypass_mask,
TPS65218_PROTECT_L1);
}
static int tps65218_pmic_set_suspend_disable(struct regulator_dev *dev)
{
struct tps65218 *tps = rdev_get_drvdata(dev);
unsigned int rid = rdev_get_id(dev);
if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1)
return -EINVAL;
/*
* Certain revisions of TPS65218 will need to have DCDC3 regulator
* enabled always, otherwise an immediate system reboot will occur
* during poweroff.
*/
if (rid == TPS65218_DCDC_3 && tps->rev == TPS65218_REV_2_1)
return 0;
if (!tps->info[rid]->strobe) {
if (rid == TPS65218_DCDC_3)
tps->info[rid]->strobe = 3;
else
return -EINVAL;
}
return tps65218_set_bits(tps, dev->desc->bypass_reg,
dev->desc->bypass_mask,
tps->info[rid]->strobe,
TPS65218_PROTECT_L1);
}
/* Operations permitted on DCDC1, DCDC2 */
static struct regulator_ops tps65218_dcdc12_ops = {
.is_enabled = regulator_is_enabled_regmap,
@@ -167,6 +211,8 @@ static struct regulator_ops tps65218_dcdc12_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_suspend_enable = tps65218_pmic_set_suspend_enable,
.set_suspend_disable = tps65218_pmic_set_suspend_disable,
};
/* Operations permitted on DCDC3, DCDC4 and LDO1 */
@@ -178,6 +224,8 @@ static struct regulator_ops tps65218_ldo1_dcdc34_ops = {
.set_voltage_sel = tps65218_pmic_set_voltage_sel,
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.set_suspend_enable = tps65218_pmic_set_suspend_enable,
.set_suspend_disable = tps65218_pmic_set_suspend_disable,
};
static const int ls3_currents[] = { 100, 200, 500, 1000 };
@@ -247,6 +295,8 @@ static struct regulator_ops tps65218_dcdc56_pmic_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = tps65218_pmic_enable,
.disable = tps65218_pmic_disable,
.set_suspend_enable = tps65218_pmic_set_suspend_enable,
.set_suspend_disable = tps65218_pmic_set_suspend_disable,
};
static const struct regulator_desc regulators[] = {
@@ -254,42 +304,47 @@ static const struct regulator_desc regulators[] = {
tps65218_dcdc12_ops, 64, TPS65218_REG_CONTROL_DCDC1,
TPS65218_CONTROL_DCDC1_MASK, TPS65218_REG_ENABLE1,
TPS65218_ENABLE1_DC1_EN, 0, 0, dcdc1_dcdc2_ranges,
2, 4000, 0),
2, 4000, 0, TPS65218_REG_SEQ3,
TPS65218_SEQ3_DC1_SEQ_MASK),
TPS65218_REGULATOR("DCDC2", TPS65218_DCDC_2, REGULATOR_VOLTAGE,
tps65218_dcdc12_ops, 64, TPS65218_REG_CONTROL_DCDC2,
TPS65218_CONTROL_DCDC2_MASK, TPS65218_REG_ENABLE1,
TPS65218_ENABLE1_DC2_EN, 0, 0, dcdc1_dcdc2_ranges,
2, 4000, 0),
2, 4000, 0, TPS65218_REG_SEQ3,
TPS65218_SEQ3_DC2_SEQ_MASK),
TPS65218_REGULATOR("DCDC3", TPS65218_DCDC_3, REGULATOR_VOLTAGE,
tps65218_ldo1_dcdc34_ops, 64,
TPS65218_REG_CONTROL_DCDC3,
TPS65218_CONTROL_DCDC3_MASK, TPS65218_REG_ENABLE1,
TPS65218_ENABLE1_DC3_EN, 0, 0, ldo1_dcdc3_ranges, 2,
0, 0),
0, 0, TPS65218_REG_SEQ4, TPS65218_SEQ4_DC3_SEQ_MASK),
TPS65218_REGULATOR("DCDC4", TPS65218_DCDC_4, REGULATOR_VOLTAGE,
tps65218_ldo1_dcdc34_ops, 53,
TPS65218_REG_CONTROL_DCDC4,
TPS65218_CONTROL_DCDC4_MASK, TPS65218_REG_ENABLE1,
TPS65218_ENABLE1_DC4_EN, 0, 0, dcdc4_ranges, 2,
0, 0),
0, 0, TPS65218_REG_SEQ4, TPS65218_SEQ4_DC4_SEQ_MASK),
TPS65218_REGULATOR("DCDC5", TPS65218_DCDC_5, REGULATOR_VOLTAGE,
tps65218_dcdc56_pmic_ops, 1, -1, -1,
TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC5_EN, 0, 0,
NULL, 0, 0, 1000000),
NULL, 0, 0, 1000000, TPS65218_REG_SEQ5,
TPS65218_SEQ5_DC5_SEQ_MASK),
TPS65218_REGULATOR("DCDC6", TPS65218_DCDC_6, REGULATOR_VOLTAGE,
tps65218_dcdc56_pmic_ops, 1, -1, -1,
TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC6_EN, 0, 0,
NULL, 0, 0, 1800000),
NULL, 0, 0, 1800000, TPS65218_REG_SEQ5,
TPS65218_SEQ5_DC6_SEQ_MASK),
TPS65218_REGULATOR("LDO1", TPS65218_LDO_1, REGULATOR_VOLTAGE,
tps65218_ldo1_dcdc34_ops, 64,
TPS65218_REG_CONTROL_LDO1,
TPS65218_CONTROL_LDO1_MASK, TPS65218_REG_ENABLE2,
TPS65218_ENABLE2_LDO1_EN, 0, 0, ldo1_dcdc3_ranges,
2, 0, 0),
2, 0, 0, TPS65218_REG_SEQ6,
TPS65218_SEQ6_LDO1_SEQ_MASK),
TPS65218_REGULATOR("LS3", TPS65218_LS_3, REGULATOR_CURRENT,
tps65218_ls3_ops, 0, 0, 0, TPS65218_REG_ENABLE2,
TPS65218_ENABLE2_LS3_EN, TPS65218_REG_CONFIG2,
TPS65218_CONFIG2_LS3ILIM_MASK, NULL, 0, 0, 0),
TPS65218_CONFIG2_LS3ILIM_MASK, NULL, 0, 0, 0, 0, 0),
};
static int tps65218_regulator_probe(struct platform_device *pdev)
@@ -300,7 +355,8 @@ static int tps65218_regulator_probe(struct platform_device *pdev)
struct regulator_dev *rdev;
const struct of_device_id *match;
struct regulator_config config = { };
int id;
int id, ret;
unsigned int val;
match = of_match_device(tps65218_of_match, &pdev->dev);
if (!match)
@@ -327,6 +383,12 @@ static int tps65218_regulator_probe(struct platform_device *pdev)
return PTR_ERR(rdev);
}
ret = tps65218_reg_read(tps, regulators[id].bypass_reg, &val);
if (ret)
return ret;
tps->info[id]->strobe = val & regulators[id].bypass_mask;
return 0;
}

View File

@@ -1111,6 +1111,12 @@ static int tps65910_probe(struct platform_device *pdev)
pmic->num_regulators = ARRAY_SIZE(tps65910_regs);
pmic->ext_sleep_control = tps65910_ext_sleep_control;
info = tps65910_regs;
/* Work around silicon erratum SWCZ010: output programmed
* voltage level can go higher than expected or crash
* Workaround: use no synchronization of DCDC clocks
*/
tps65910_reg_clear_bits(pmic->mfd, TPS65910_DCDCCTRL,
DCDCCTRL_DCDCCKSYNC_MASK);
break;
case TPS65911:
pmic->get_ctrl_reg = &tps65911_get_ctrl_register;

View File

@@ -905,7 +905,7 @@ static struct regulator_ops twlsmps_ops = {
twl4030reg_map_mode)
#define TWL6030_FIXED_LDO(label, offset, mVolts, turnon_delay) \
TWL_FIXED_LDO(label, offset, mVolts, 0x0, turnon_delay, \
0x0, TWL6030, twl6030fixed_ops, 0x0)
0x0, TWL6030, twl6030fixed_ops, NULL)
#define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) \
static const struct twlreg_info TWL4030_INFO_##label = { \