Merge branch 'topic/error' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator into regulator-fixed
This commit is contained in:
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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");
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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, ®);
|
||||
|
||||
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 = ®ulators[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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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",
|
||||
|
@@ -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),
|
||||
|
@@ -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,
|
||||
|
@@ -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");
|
||||
|
@@ -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
|
||||
|
@@ -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 */
|
||||
|
@@ -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",
|
||||
|
@@ -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);
|
||||
|
@@ -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
420
drivers/regulator/ltc3676.c
Normal 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 = <c3676->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 = <c3676_ ## _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, <c3676_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 = <c3676->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");
|
@@ -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");
|
||||
|
@@ -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),
|
||||
|
@@ -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");
|
||||
|
@@ -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;
|
||||
}
|
||||
|
425
drivers/regulator/mt6323-regulator.c
Normal file
425
drivers/regulator/mt6323-regulator.c
Normal 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, ®val);
|
||||
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,
|
||||
®val) < 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, ®_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");
|
@@ -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, ®val);
|
||||
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,
|
||||
|
@@ -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;
|
||||
|
@@ -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");
|
||||
|
@@ -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
|
||||
|
@@ -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",
|
||||
|
@@ -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__ */
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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 },
|
||||
|
@@ -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 = {
|
||||
|
@@ -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", },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@@ -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);
|
||||
®ulators[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");
|
||||
|
@@ -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],
|
||||
®ulators[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);
|
||||
}
|
||||
}
|
||||
|
@@ -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[] = {
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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 = { \
|
||||
|
Reference in New Issue
Block a user