xref: /linux/drivers/regulator/pf9453-regulator.c (revision 1260ed77798502de9c98020040d2995008de10cc)
1*0959b670SJoy Zou // SPDX-License-Identifier: GPL-2.0
2*0959b670SJoy Zou /*
3*0959b670SJoy Zou  * Copyright 2024 NXP.
4*0959b670SJoy Zou  * NXP PF9453 pmic driver
5*0959b670SJoy Zou  */
6*0959b670SJoy Zou 
7*0959b670SJoy Zou #include <linux/bits.h>
8*0959b670SJoy Zou #include <linux/err.h>
9*0959b670SJoy Zou #include <linux/gpio/consumer.h>
10*0959b670SJoy Zou #include <linux/i2c.h>
11*0959b670SJoy Zou #include <linux/interrupt.h>
12*0959b670SJoy Zou #include <linux/kernel.h>
13*0959b670SJoy Zou #include <linux/module.h>
14*0959b670SJoy Zou #include <linux/of.h>
15*0959b670SJoy Zou #include <linux/platform_device.h>
16*0959b670SJoy Zou #include <linux/regmap.h>
17*0959b670SJoy Zou #include <linux/regulator/driver.h>
18*0959b670SJoy Zou #include <linux/regulator/machine.h>
19*0959b670SJoy Zou #include <linux/regulator/of_regulator.h>
20*0959b670SJoy Zou 
21*0959b670SJoy Zou struct pf9453_dvs_config {
22*0959b670SJoy Zou 	unsigned int run_reg; /* dvs0 */
23*0959b670SJoy Zou 	unsigned int run_mask;
24*0959b670SJoy Zou 	unsigned int standby_reg; /* dvs1 */
25*0959b670SJoy Zou 	unsigned int standby_mask;
26*0959b670SJoy Zou };
27*0959b670SJoy Zou 
28*0959b670SJoy Zou struct pf9453_regulator_desc {
29*0959b670SJoy Zou 	struct regulator_desc desc;
30*0959b670SJoy Zou 	const struct pf9453_dvs_config dvs;
31*0959b670SJoy Zou };
32*0959b670SJoy Zou 
33*0959b670SJoy Zou struct pf9453 {
34*0959b670SJoy Zou 	struct device *dev;
35*0959b670SJoy Zou 	struct regmap *regmap;
36*0959b670SJoy Zou 	struct gpio_desc *sd_vsel_gpio;
37*0959b670SJoy Zou 	int irq;
38*0959b670SJoy Zou };
39*0959b670SJoy Zou 
40*0959b670SJoy Zou enum {
41*0959b670SJoy Zou 	PF9453_BUCK1 = 0,
42*0959b670SJoy Zou 	PF9453_BUCK2,
43*0959b670SJoy Zou 	PF9453_BUCK3,
44*0959b670SJoy Zou 	PF9453_BUCK4,
45*0959b670SJoy Zou 	PF9453_LDO1,
46*0959b670SJoy Zou 	PF9453_LDO2,
47*0959b670SJoy Zou 	PF9453_LDOSNVS,
48*0959b670SJoy Zou 	PF9453_REGULATOR_CNT
49*0959b670SJoy Zou };
50*0959b670SJoy Zou 
51*0959b670SJoy Zou enum {
52*0959b670SJoy Zou 	PF9453_DVS_LEVEL_RUN = 0,
53*0959b670SJoy Zou 	PF9453_DVS_LEVEL_STANDBY,
54*0959b670SJoy Zou 	PF9453_DVS_LEVEL_DPSTANDBY,
55*0959b670SJoy Zou 	PF9453_DVS_LEVEL_MAX
56*0959b670SJoy Zou };
57*0959b670SJoy Zou 
58*0959b670SJoy Zou #define PF9453_BUCK1_VOLTAGE_NUM	0x80
59*0959b670SJoy Zou #define PF9453_BUCK2_VOLTAGE_NUM	0x80
60*0959b670SJoy Zou #define PF9453_BUCK3_VOLTAGE_NUM	0x80
61*0959b670SJoy Zou #define PF9453_BUCK4_VOLTAGE_NUM	0x80
62*0959b670SJoy Zou 
63*0959b670SJoy Zou #define PF9453_LDO1_VOLTAGE_NUM		0x65
64*0959b670SJoy Zou #define PF9453_LDO2_VOLTAGE_NUM		0x3b
65*0959b670SJoy Zou #define PF9453_LDOSNVS_VOLTAGE_NUM	0x59
66*0959b670SJoy Zou 
67*0959b670SJoy Zou enum {
68*0959b670SJoy Zou 	PF9453_REG_DEV_ID		= 0x00,
69*0959b670SJoy Zou 	PF9453_REG_OTP_VER		= 0x01,
70*0959b670SJoy Zou 	PF9453_REG_INT1			= 0x02,
71*0959b670SJoy Zou 	PF9453_REG_INT1_MASK		= 0x03,
72*0959b670SJoy Zou 	PF9453_REG_INT1_STATUS		= 0x04,
73*0959b670SJoy Zou 	PF9453_REG_VRFLT1_INT		= 0x05,
74*0959b670SJoy Zou 	PF9453_REG_VRFLT1_MASK		= 0x06,
75*0959b670SJoy Zou 	PF9453_REG_PWRON_STAT		= 0x07,
76*0959b670SJoy Zou 	PF9453_REG_RESET_CTRL		= 0x08,
77*0959b670SJoy Zou 	PF9453_REG_SW_RST		= 0x09,
78*0959b670SJoy Zou 	PF9453_REG_PWR_CTRL		= 0x0a,
79*0959b670SJoy Zou 	PF9453_REG_CONFIG1		= 0x0b,
80*0959b670SJoy Zou 	PF9453_REG_CONFIG2		= 0x0c,
81*0959b670SJoy Zou 	PF9453_REG_32K_CONFIG		= 0x0d,
82*0959b670SJoy Zou 	PF9453_REG_BUCK1CTRL		= 0x10,
83*0959b670SJoy Zou 	PF9453_REG_BUCK1OUT		= 0x11,
84*0959b670SJoy Zou 	PF9453_REG_BUCK2CTRL		= 0x14,
85*0959b670SJoy Zou 	PF9453_REG_BUCK2OUT		= 0x15,
86*0959b670SJoy Zou 	PF9453_REG_BUCK2OUT_STBY	= 0x1d,
87*0959b670SJoy Zou 	PF9453_REG_BUCK2OUT_MAX_LIMIT	= 0x1f,
88*0959b670SJoy Zou 	PF9453_REG_BUCK2OUT_MIN_LIMIT	= 0x20,
89*0959b670SJoy Zou 	PF9453_REG_BUCK3CTRL		= 0x21,
90*0959b670SJoy Zou 	PF9453_REG_BUCK3OUT		= 0x22,
91*0959b670SJoy Zou 	PF9453_REG_BUCK4CTRL		= 0x2e,
92*0959b670SJoy Zou 	PF9453_REG_BUCK4OUT		= 0x2f,
93*0959b670SJoy Zou 	PF9453_REG_LDO1OUT_L		= 0x36,
94*0959b670SJoy Zou 	PF9453_REG_LDO1CFG		= 0x37,
95*0959b670SJoy Zou 	PF9453_REG_LDO1OUT_H		= 0x38,
96*0959b670SJoy Zou 	PF9453_REG_LDOSNVS_CFG1		= 0x39,
97*0959b670SJoy Zou 	PF9453_REG_LDOSNVS_CFG2		= 0x3a,
98*0959b670SJoy Zou 	PF9453_REG_LDO2CFG		= 0x3b,
99*0959b670SJoy Zou 	PF9453_REG_LDO2OUT		= 0x3c,
100*0959b670SJoy Zou 	PF9453_REG_BUCK_POK		= 0x3d,
101*0959b670SJoy Zou 	PF9453_REG_LSW_CTRL1		= 0x40,
102*0959b670SJoy Zou 	PF9453_REG_LSW_CTRL2		= 0x41,
103*0959b670SJoy Zou 	PF9453_REG_LOCK			= 0x4e,
104*0959b670SJoy Zou 	PF9453_MAX_REG
105*0959b670SJoy Zou };
106*0959b670SJoy Zou 
107*0959b670SJoy Zou #define PF9453_UNLOCK_KEY		0x5c
108*0959b670SJoy Zou #define PF9453_LOCK_KEY			0x0
109*0959b670SJoy Zou 
110*0959b670SJoy Zou /* PF9453 BUCK ENMODE bits */
111*0959b670SJoy Zou #define BUCK_ENMODE_OFF			0x00
112*0959b670SJoy Zou #define BUCK_ENMODE_ONREQ		0x01
113*0959b670SJoy Zou #define BUCK_ENMODE_ONREQ_STBY		0x02
114*0959b670SJoy Zou #define BUCK_ENMODE_ONREQ_STBY_DPSTBY	0x03
115*0959b670SJoy Zou 
116*0959b670SJoy Zou /* PF9453 BUCK ENMODE bits */
117*0959b670SJoy Zou #define LDO_ENMODE_OFF			0x00
118*0959b670SJoy Zou #define LDO_ENMODE_ONREQ		0x01
119*0959b670SJoy Zou #define LDO_ENMODE_ONREQ_STBY		0x02
120*0959b670SJoy Zou #define LDO_ENMODE_ONREQ_STBY_DPSTBY	0x03
121*0959b670SJoy Zou 
122*0959b670SJoy Zou /* PF9453_REG_BUCK1_CTRL bits */
123*0959b670SJoy Zou #define BUCK1_LPMODE			0x30
124*0959b670SJoy Zou #define BUCK1_AD			0x08
125*0959b670SJoy Zou #define BUCK1_FPWM			0x04
126*0959b670SJoy Zou #define BUCK1_ENMODE_MASK		GENMASK(1, 0)
127*0959b670SJoy Zou 
128*0959b670SJoy Zou /* PF9453_REG_BUCK2_CTRL bits */
129*0959b670SJoy Zou #define BUCK2_RAMP_MASK			GENMASK(7, 6)
130*0959b670SJoy Zou #define BUCK2_RAMP_25MV			0x0
131*0959b670SJoy Zou #define BUCK2_RAMP_12P5MV		0x1
132*0959b670SJoy Zou #define BUCK2_RAMP_6P25MV		0x2
133*0959b670SJoy Zou #define BUCK2_RAMP_3P125MV		0x3
134*0959b670SJoy Zou #define BUCK2_LPMODE			0x30
135*0959b670SJoy Zou #define BUCK2_AD			0x08
136*0959b670SJoy Zou #define BUCK2_FPWM			0x04
137*0959b670SJoy Zou #define BUCK2_ENMODE_MASK		GENMASK(1, 0)
138*0959b670SJoy Zou 
139*0959b670SJoy Zou /* PF9453_REG_BUCK3_CTRL bits */
140*0959b670SJoy Zou #define BUCK3_LPMODE			0x30
141*0959b670SJoy Zou #define BUCK3_AD			0x08
142*0959b670SJoy Zou #define BUCK3_FPWM			0x04
143*0959b670SJoy Zou #define BUCK3_ENMODE_MASK		GENMASK(1, 0)
144*0959b670SJoy Zou 
145*0959b670SJoy Zou /* PF9453_REG_BUCK4_CTRL bits */
146*0959b670SJoy Zou #define BUCK4_LPMODE			0x30
147*0959b670SJoy Zou #define BUCK4_AD			0x08
148*0959b670SJoy Zou #define BUCK4_FPWM			0x04
149*0959b670SJoy Zou #define BUCK4_ENMODE_MASK		GENMASK(1, 0)
150*0959b670SJoy Zou 
151*0959b670SJoy Zou /* PF9453_REG_BUCK123_PRESET_EN bit */
152*0959b670SJoy Zou #define BUCK123_PRESET_EN		0x80
153*0959b670SJoy Zou 
154*0959b670SJoy Zou /* PF9453_BUCK1OUT bits */
155*0959b670SJoy Zou #define BUCK1OUT_MASK			GENMASK(6, 0)
156*0959b670SJoy Zou 
157*0959b670SJoy Zou /* PF9453_BUCK2OUT bits */
158*0959b670SJoy Zou #define BUCK2OUT_MASK			GENMASK(6, 0)
159*0959b670SJoy Zou #define BUCK2OUT_STBY_MASK		GENMASK(6, 0)
160*0959b670SJoy Zou 
161*0959b670SJoy Zou /* PF9453_REG_BUCK3OUT bits */
162*0959b670SJoy Zou #define BUCK3OUT_MASK			GENMASK(6, 0)
163*0959b670SJoy Zou 
164*0959b670SJoy Zou /* PF9453_REG_BUCK4OUT bits */
165*0959b670SJoy Zou #define BUCK4OUT_MASK			GENMASK(6, 0)
166*0959b670SJoy Zou 
167*0959b670SJoy Zou /* PF9453_REG_LDO1_VOLT bits */
168*0959b670SJoy Zou #define LDO1_EN_MASK			GENMASK(1, 0)
169*0959b670SJoy Zou #define LDO1OUT_MASK			GENMASK(6, 0)
170*0959b670SJoy Zou 
171*0959b670SJoy Zou /* PF9453_REG_LDO2_VOLT bits */
172*0959b670SJoy Zou #define LDO2_EN_MASK			GENMASK(1, 0)
173*0959b670SJoy Zou #define LDO2OUT_MASK			GENMASK(6, 0)
174*0959b670SJoy Zou 
175*0959b670SJoy Zou /* PF9453_REG_LDOSNVS_VOLT bits */
176*0959b670SJoy Zou #define LDOSNVS_EN_MASK			GENMASK(0, 0)
177*0959b670SJoy Zou #define LDOSNVSCFG1_MASK		GENMASK(6, 0)
178*0959b670SJoy Zou 
179*0959b670SJoy Zou /* PF9453_REG_IRQ bits */
180*0959b670SJoy Zou #define IRQ_RSVD			0x80
181*0959b670SJoy Zou #define IRQ_RSTB			0x40
182*0959b670SJoy Zou #define IRQ_ONKEY			0x20
183*0959b670SJoy Zou #define IRQ_RESETKEY			0x10
184*0959b670SJoy Zou #define IRQ_VR_FLT1			0x08
185*0959b670SJoy Zou #define IRQ_LOWVSYS			0x04
186*0959b670SJoy Zou #define IRQ_THERM_100			0x02
187*0959b670SJoy Zou #define IRQ_THERM_80			0x01
188*0959b670SJoy Zou 
189*0959b670SJoy Zou /* PF9453_REG_RESET_CTRL bits */
190*0959b670SJoy Zou #define WDOG_B_CFG_MASK			GENMASK(7, 6)
191*0959b670SJoy Zou #define WDOG_B_CFG_NONE			0x00
192*0959b670SJoy Zou #define WDOG_B_CFG_WARM			0x40
193*0959b670SJoy Zou #define WDOG_B_CFG_COLD			0x80
194*0959b670SJoy Zou 
195*0959b670SJoy Zou /* PF9453_REG_CONFIG2 bits */
196*0959b670SJoy Zou #define I2C_LT_MASK			GENMASK(1, 0)
197*0959b670SJoy Zou #define I2C_LT_FORCE_DISABLE		0x00
198*0959b670SJoy Zou #define I2C_LT_ON_STANDBY_RUN		0x01
199*0959b670SJoy Zou #define I2C_LT_ON_RUN			0x02
200*0959b670SJoy Zou #define I2C_LT_FORCE_ENABLE		0x03
201*0959b670SJoy Zou 
202*0959b670SJoy Zou static const struct regmap_range pf9453_status_range = {
203*0959b670SJoy Zou 	.range_min = PF9453_REG_INT1,
204*0959b670SJoy Zou 	.range_max = PF9453_REG_PWRON_STAT,
205*0959b670SJoy Zou };
206*0959b670SJoy Zou 
207*0959b670SJoy Zou static const struct regmap_access_table pf9453_volatile_regs = {
208*0959b670SJoy Zou 	.yes_ranges = &pf9453_status_range,
209*0959b670SJoy Zou 	.n_yes_ranges = 1,
210*0959b670SJoy Zou };
211*0959b670SJoy Zou 
212*0959b670SJoy Zou static const struct regmap_config pf9453_regmap_config = {
213*0959b670SJoy Zou 	.reg_bits = 8,
214*0959b670SJoy Zou 	.val_bits = 8,
215*0959b670SJoy Zou 	.volatile_table = &pf9453_volatile_regs,
216*0959b670SJoy Zou 	.max_register = PF9453_MAX_REG - 1,
217*0959b670SJoy Zou 	.cache_type = REGCACHE_RBTREE,
218*0959b670SJoy Zou };
219*0959b670SJoy Zou 
220*0959b670SJoy Zou /*
221*0959b670SJoy Zou  * BUCK2
222*0959b670SJoy Zou  * BUCK2RAM[1:0] BUCK2 DVS ramp rate setting
223*0959b670SJoy Zou  * 00: 25mV/1usec
224*0959b670SJoy Zou  * 01: 25mV/2usec
225*0959b670SJoy Zou  * 10: 25mV/4usec
226*0959b670SJoy Zou  * 11: 25mV/8usec
227*0959b670SJoy Zou  */
228*0959b670SJoy Zou static const unsigned int pf9453_dvs_buck_ramp_table[] = {
229*0959b670SJoy Zou 	25000, 12500, 6250, 3125
230*0959b670SJoy Zou };
231*0959b670SJoy Zou 
232*0959b670SJoy Zou static bool is_reg_protect(uint reg)
233*0959b670SJoy Zou {
234*0959b670SJoy Zou 	switch (reg) {
235*0959b670SJoy Zou 	case PF9453_REG_BUCK1OUT:
236*0959b670SJoy Zou 	case PF9453_REG_BUCK2OUT:
237*0959b670SJoy Zou 	case PF9453_REG_BUCK3OUT:
238*0959b670SJoy Zou 	case PF9453_REG_BUCK4OUT:
239*0959b670SJoy Zou 	case PF9453_REG_LDO1OUT_L:
240*0959b670SJoy Zou 	case PF9453_REG_LDO1OUT_H:
241*0959b670SJoy Zou 	case PF9453_REG_LDO2OUT:
242*0959b670SJoy Zou 	case PF9453_REG_LDOSNVS_CFG1:
243*0959b670SJoy Zou 	case PF9453_REG_BUCK2OUT_MAX_LIMIT:
244*0959b670SJoy Zou 	case PF9453_REG_BUCK2OUT_MIN_LIMIT:
245*0959b670SJoy Zou 		return true;
246*0959b670SJoy Zou 	default:
247*0959b670SJoy Zou 		return false;
248*0959b670SJoy Zou 	}
249*0959b670SJoy Zou }
250*0959b670SJoy Zou 
251*0959b670SJoy Zou static int pf9453_pmic_write(struct pf9453 *pf9453, unsigned int reg, u8 mask, unsigned int val)
252*0959b670SJoy Zou {
253*0959b670SJoy Zou 	int ret = -EINVAL;
254*0959b670SJoy Zou 	u8 data, key;
255*0959b670SJoy Zou 	u32 rxBuf;
256*0959b670SJoy Zou 
257*0959b670SJoy Zou 	/* If not updating entire register, perform a read-mod-write */
258*0959b670SJoy Zou 	data = val;
259*0959b670SJoy Zou 	key = PF9453_UNLOCK_KEY;
260*0959b670SJoy Zou 
261*0959b670SJoy Zou 	if (mask != 0xffU) {
262*0959b670SJoy Zou 		/* Read data */
263*0959b670SJoy Zou 		ret = regmap_read(pf9453->regmap, reg, &rxBuf);
264*0959b670SJoy Zou 		if (ret) {
265*0959b670SJoy Zou 			dev_err(pf9453->dev, "Read reg=%0x error!\n", reg);
266*0959b670SJoy Zou 			return ret;
267*0959b670SJoy Zou 		}
268*0959b670SJoy Zou 		data = (val & mask) | (rxBuf & (~mask));
269*0959b670SJoy Zou 	}
270*0959b670SJoy Zou 
271*0959b670SJoy Zou 	if (reg < PF9453_MAX_REG) {
272*0959b670SJoy Zou 		if (is_reg_protect(reg)) {
273*0959b670SJoy Zou 			ret = regmap_raw_write(pf9453->regmap, PF9453_REG_LOCK, &key, 1U);
274*0959b670SJoy Zou 			if (ret) {
275*0959b670SJoy Zou 				dev_err(pf9453->dev, "Write reg=%0x error!\n", reg);
276*0959b670SJoy Zou 				return ret;
277*0959b670SJoy Zou 			}
278*0959b670SJoy Zou 
279*0959b670SJoy Zou 			ret = regmap_raw_write(pf9453->regmap, reg, &data, 1U);
280*0959b670SJoy Zou 			if (ret) {
281*0959b670SJoy Zou 				dev_err(pf9453->dev, "Write reg=%0x error!\n", reg);
282*0959b670SJoy Zou 				return ret;
283*0959b670SJoy Zou 			}
284*0959b670SJoy Zou 
285*0959b670SJoy Zou 			key = PF9453_LOCK_KEY;
286*0959b670SJoy Zou 			ret = regmap_raw_write(pf9453->regmap, PF9453_REG_LOCK, &key, 1U);
287*0959b670SJoy Zou 			if (ret) {
288*0959b670SJoy Zou 				dev_err(pf9453->dev, "Write reg=%0x error!\n", reg);
289*0959b670SJoy Zou 				return ret;
290*0959b670SJoy Zou 			}
291*0959b670SJoy Zou 		} else {
292*0959b670SJoy Zou 			ret = regmap_raw_write(pf9453->regmap, reg, &data, 1U);
293*0959b670SJoy Zou 			if (ret) {
294*0959b670SJoy Zou 				dev_err(pf9453->dev, "Write reg=%0x error!\n", reg);
295*0959b670SJoy Zou 				return ret;
296*0959b670SJoy Zou 			}
297*0959b670SJoy Zou 		}
298*0959b670SJoy Zou 	}
299*0959b670SJoy Zou 
300*0959b670SJoy Zou 	return ret;
301*0959b670SJoy Zou }
302*0959b670SJoy Zou 
303*0959b670SJoy Zou /**
304*0959b670SJoy Zou  * pf9453_regulator_enable_regmap for regmap users
305*0959b670SJoy Zou  *
306*0959b670SJoy Zou  * @rdev: regulator to operate on
307*0959b670SJoy Zou  *
308*0959b670SJoy Zou  * Regulators that use regmap for their register I/O can set the
309*0959b670SJoy Zou  * enable_reg and enable_mask fields in their descriptor and then use
310*0959b670SJoy Zou  * this as their enable() operation, saving some code.
311*0959b670SJoy Zou  */
312*0959b670SJoy Zou static int pf9453_regulator_enable_regmap(struct regulator_dev *rdev)
313*0959b670SJoy Zou {
314*0959b670SJoy Zou 	struct pf9453 *pf9453 = dev_get_drvdata(rdev->dev.parent);
315*0959b670SJoy Zou 	unsigned int val;
316*0959b670SJoy Zou 
317*0959b670SJoy Zou 	if (rdev->desc->enable_is_inverted) {
318*0959b670SJoy Zou 		val = rdev->desc->disable_val;
319*0959b670SJoy Zou 	} else {
320*0959b670SJoy Zou 		val = rdev->desc->enable_val;
321*0959b670SJoy Zou 		if (!val)
322*0959b670SJoy Zou 			val = rdev->desc->enable_mask;
323*0959b670SJoy Zou 	}
324*0959b670SJoy Zou 
325*0959b670SJoy Zou 	return pf9453_pmic_write(pf9453, rdev->desc->enable_reg, rdev->desc->enable_mask, val);
326*0959b670SJoy Zou }
327*0959b670SJoy Zou 
328*0959b670SJoy Zou /**
329*0959b670SJoy Zou  * pf9453_regulator_disable_regmap for regmap users
330*0959b670SJoy Zou  *
331*0959b670SJoy Zou  * @rdev: regulator to operate on
332*0959b670SJoy Zou  *
333*0959b670SJoy Zou  * Regulators that use regmap for their register I/O can set the
334*0959b670SJoy Zou  * enable_reg and enable_mask fields in their descriptor and then use
335*0959b670SJoy Zou  * this as their disable() operation, saving some code.
336*0959b670SJoy Zou  */
337*0959b670SJoy Zou static int pf9453_regulator_disable_regmap(struct regulator_dev *rdev)
338*0959b670SJoy Zou {
339*0959b670SJoy Zou 	struct pf9453 *pf9453 = dev_get_drvdata(rdev->dev.parent);
340*0959b670SJoy Zou 	unsigned int val;
341*0959b670SJoy Zou 
342*0959b670SJoy Zou 	if (rdev->desc->enable_is_inverted) {
343*0959b670SJoy Zou 		val = rdev->desc->enable_val;
344*0959b670SJoy Zou 		if (!val)
345*0959b670SJoy Zou 			val = rdev->desc->enable_mask;
346*0959b670SJoy Zou 	} else {
347*0959b670SJoy Zou 		val = rdev->desc->disable_val;
348*0959b670SJoy Zou 	}
349*0959b670SJoy Zou 
350*0959b670SJoy Zou 	return pf9453_pmic_write(pf9453, rdev->desc->enable_reg, rdev->desc->enable_mask, val);
351*0959b670SJoy Zou }
352*0959b670SJoy Zou 
353*0959b670SJoy Zou /**
354*0959b670SJoy Zou  * pf9453_regulator_set_voltage_sel_regmap for regmap users
355*0959b670SJoy Zou  *
356*0959b670SJoy Zou  * @rdev: regulator to operate on
357*0959b670SJoy Zou  * @sel: Selector to set
358*0959b670SJoy Zou  *
359*0959b670SJoy Zou  * Regulators that use regmap for their register I/O can set the
360*0959b670SJoy Zou  * vsel_reg and vsel_mask fields in their descriptor and then use this
361*0959b670SJoy Zou  * as their set_voltage_vsel operation, saving some code.
362*0959b670SJoy Zou  */
363*0959b670SJoy Zou static int pf9453_regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned int sel)
364*0959b670SJoy Zou {
365*0959b670SJoy Zou 	struct pf9453 *pf9453 = dev_get_drvdata(rdev->dev.parent);
366*0959b670SJoy Zou 	int ret;
367*0959b670SJoy Zou 
368*0959b670SJoy Zou 	sel <<= ffs(rdev->desc->vsel_mask) - 1;
369*0959b670SJoy Zou 	ret = pf9453_pmic_write(pf9453, rdev->desc->vsel_reg, rdev->desc->vsel_mask, sel);
370*0959b670SJoy Zou 	if (ret)
371*0959b670SJoy Zou 		return ret;
372*0959b670SJoy Zou 
373*0959b670SJoy Zou 	if (rdev->desc->apply_bit)
374*0959b670SJoy Zou 		ret = pf9453_pmic_write(pf9453, rdev->desc->apply_reg,
375*0959b670SJoy Zou 					rdev->desc->apply_bit, rdev->desc->apply_bit);
376*0959b670SJoy Zou 	return ret;
377*0959b670SJoy Zou }
378*0959b670SJoy Zou 
379*0959b670SJoy Zou static int find_closest_bigger(unsigned int target, const unsigned int *table,
380*0959b670SJoy Zou 			       unsigned int num_sel, unsigned int *sel)
381*0959b670SJoy Zou {
382*0959b670SJoy Zou 	unsigned int s, tmp, max, maxsel = 0;
383*0959b670SJoy Zou 	bool found = false;
384*0959b670SJoy Zou 
385*0959b670SJoy Zou 	max = table[0];
386*0959b670SJoy Zou 
387*0959b670SJoy Zou 	for (s = 0; s < num_sel; s++) {
388*0959b670SJoy Zou 		if (table[s] > max) {
389*0959b670SJoy Zou 			max = table[s];
390*0959b670SJoy Zou 			maxsel = s;
391*0959b670SJoy Zou 		}
392*0959b670SJoy Zou 		if (table[s] >= target) {
393*0959b670SJoy Zou 			if (!found || table[s] - target < tmp - target) {
394*0959b670SJoy Zou 				tmp = table[s];
395*0959b670SJoy Zou 				*sel = s;
396*0959b670SJoy Zou 				found = true;
397*0959b670SJoy Zou 				if (tmp == target)
398*0959b670SJoy Zou 					break;
399*0959b670SJoy Zou 			}
400*0959b670SJoy Zou 		}
401*0959b670SJoy Zou 	}
402*0959b670SJoy Zou 
403*0959b670SJoy Zou 	if (!found) {
404*0959b670SJoy Zou 		*sel = maxsel;
405*0959b670SJoy Zou 		return -EINVAL;
406*0959b670SJoy Zou 	}
407*0959b670SJoy Zou 
408*0959b670SJoy Zou 	return 0;
409*0959b670SJoy Zou }
410*0959b670SJoy Zou 
411*0959b670SJoy Zou /**
412*0959b670SJoy Zou  * pf9453_regulator_set_ramp_delay_regmap
413*0959b670SJoy Zou  *
414*0959b670SJoy Zou  * @rdev: regulator to operate on
415*0959b670SJoy Zou  *
416*0959b670SJoy Zou  * Regulators that use regmap for their register I/O can set the ramp_reg
417*0959b670SJoy Zou  * and ramp_mask fields in their descriptor and then use this as their
418*0959b670SJoy Zou  * set_ramp_delay operation, saving some code.
419*0959b670SJoy Zou  */
420*0959b670SJoy Zou static int pf9453_regulator_set_ramp_delay_regmap(struct regulator_dev *rdev, int ramp_delay)
421*0959b670SJoy Zou {
422*0959b670SJoy Zou 	struct pf9453 *pf9453 = dev_get_drvdata(rdev->dev.parent);
423*0959b670SJoy Zou 	unsigned int sel;
424*0959b670SJoy Zou 	int ret;
425*0959b670SJoy Zou 
426*0959b670SJoy Zou 	if (WARN_ON(!rdev->desc->n_ramp_values || !rdev->desc->ramp_delay_table))
427*0959b670SJoy Zou 		return -EINVAL;
428*0959b670SJoy Zou 
429*0959b670SJoy Zou 	ret = find_closest_bigger(ramp_delay, rdev->desc->ramp_delay_table,
430*0959b670SJoy Zou 				  rdev->desc->n_ramp_values, &sel);
431*0959b670SJoy Zou 
432*0959b670SJoy Zou 	if (ret) {
433*0959b670SJoy Zou 		dev_warn(rdev_get_dev(rdev),
434*0959b670SJoy Zou 			 "Can't set ramp-delay %u, setting %u\n", ramp_delay,
435*0959b670SJoy Zou 			 rdev->desc->ramp_delay_table[sel]);
436*0959b670SJoy Zou 	}
437*0959b670SJoy Zou 
438*0959b670SJoy Zou 	sel <<= ffs(rdev->desc->ramp_mask) - 1;
439*0959b670SJoy Zou 
440*0959b670SJoy Zou 	return pf9453_pmic_write(pf9453, rdev->desc->ramp_reg,
441*0959b670SJoy Zou 				 rdev->desc->ramp_mask, sel);
442*0959b670SJoy Zou }
443*0959b670SJoy Zou 
444*0959b670SJoy Zou static const struct regulator_ops pf9453_dvs_buck_regulator_ops = {
445*0959b670SJoy Zou 	.enable = pf9453_regulator_enable_regmap,
446*0959b670SJoy Zou 	.disable = pf9453_regulator_disable_regmap,
447*0959b670SJoy Zou 	.is_enabled = regulator_is_enabled_regmap,
448*0959b670SJoy Zou 	.list_voltage = regulator_list_voltage_linear_range,
449*0959b670SJoy Zou 	.set_voltage_sel = pf9453_regulator_set_voltage_sel_regmap,
450*0959b670SJoy Zou 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
451*0959b670SJoy Zou 	.set_voltage_time_sel = regulator_set_voltage_time_sel,
452*0959b670SJoy Zou 	.set_ramp_delay	= pf9453_regulator_set_ramp_delay_regmap,
453*0959b670SJoy Zou };
454*0959b670SJoy Zou 
455*0959b670SJoy Zou static const struct regulator_ops pf9453_buck_regulator_ops = {
456*0959b670SJoy Zou 	.enable = pf9453_regulator_enable_regmap,
457*0959b670SJoy Zou 	.disable = pf9453_regulator_disable_regmap,
458*0959b670SJoy Zou 	.is_enabled = regulator_is_enabled_regmap,
459*0959b670SJoy Zou 	.list_voltage = regulator_list_voltage_linear_range,
460*0959b670SJoy Zou 	.set_voltage_sel = pf9453_regulator_set_voltage_sel_regmap,
461*0959b670SJoy Zou 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
462*0959b670SJoy Zou 	.set_voltage_time_sel = regulator_set_voltage_time_sel,
463*0959b670SJoy Zou };
464*0959b670SJoy Zou 
465*0959b670SJoy Zou static const struct regulator_ops pf9453_ldo_regulator_ops = {
466*0959b670SJoy Zou 	.enable = pf9453_regulator_enable_regmap,
467*0959b670SJoy Zou 	.disable = pf9453_regulator_disable_regmap,
468*0959b670SJoy Zou 	.is_enabled = regulator_is_enabled_regmap,
469*0959b670SJoy Zou 	.list_voltage = regulator_list_voltage_linear_range,
470*0959b670SJoy Zou 	.set_voltage_sel = pf9453_regulator_set_voltage_sel_regmap,
471*0959b670SJoy Zou 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
472*0959b670SJoy Zou };
473*0959b670SJoy Zou 
474*0959b670SJoy Zou /*
475*0959b670SJoy Zou  * BUCK1/3/4
476*0959b670SJoy Zou  * 0.60 to 3.775V (25mV step)
477*0959b670SJoy Zou  */
478*0959b670SJoy Zou static const struct linear_range pf9453_buck134_volts[] = {
479*0959b670SJoy Zou 	REGULATOR_LINEAR_RANGE(600000, 0x00, 0x7F, 25000),
480*0959b670SJoy Zou };
481*0959b670SJoy Zou 
482*0959b670SJoy Zou /*
483*0959b670SJoy Zou  * BUCK2
484*0959b670SJoy Zou  * 0.60 to 2.1875V (12.5mV step)
485*0959b670SJoy Zou  */
486*0959b670SJoy Zou static const struct linear_range pf9453_buck2_volts[] = {
487*0959b670SJoy Zou 	REGULATOR_LINEAR_RANGE(600000, 0x00, 0x7F, 12500),
488*0959b670SJoy Zou };
489*0959b670SJoy Zou 
490*0959b670SJoy Zou /*
491*0959b670SJoy Zou  * LDO1
492*0959b670SJoy Zou  * 0.8 to 3.3V (25mV step)
493*0959b670SJoy Zou  */
494*0959b670SJoy Zou static const struct linear_range pf9453_ldo1_volts[] = {
495*0959b670SJoy Zou 	REGULATOR_LINEAR_RANGE(800000, 0x00, 0x64, 25000),
496*0959b670SJoy Zou };
497*0959b670SJoy Zou 
498*0959b670SJoy Zou /*
499*0959b670SJoy Zou  * LDO2
500*0959b670SJoy Zou  * 0.5 to 1.95V (25mV step)
501*0959b670SJoy Zou  */
502*0959b670SJoy Zou static const struct linear_range pf9453_ldo2_volts[] = {
503*0959b670SJoy Zou 	REGULATOR_LINEAR_RANGE(500000, 0x00, 0x3A, 25000),
504*0959b670SJoy Zou };
505*0959b670SJoy Zou 
506*0959b670SJoy Zou /*
507*0959b670SJoy Zou  * LDOSNVS
508*0959b670SJoy Zou  * 1.2 to 3.4V (25mV step)
509*0959b670SJoy Zou  */
510*0959b670SJoy Zou static const struct linear_range pf9453_ldosnvs_volts[] = {
511*0959b670SJoy Zou 	REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x58, 25000),
512*0959b670SJoy Zou };
513*0959b670SJoy Zou 
514*0959b670SJoy Zou static int buck_set_dvs(const struct regulator_desc *desc,
515*0959b670SJoy Zou 			struct device_node *np, struct pf9453 *pf9453,
516*0959b670SJoy Zou 			char *prop, unsigned int reg, unsigned int mask)
517*0959b670SJoy Zou {
518*0959b670SJoy Zou 	int ret, i;
519*0959b670SJoy Zou 	u32 uv;
520*0959b670SJoy Zou 
521*0959b670SJoy Zou 	ret = of_property_read_u32(np, prop, &uv);
522*0959b670SJoy Zou 	if (ret == -EINVAL)
523*0959b670SJoy Zou 		return 0;
524*0959b670SJoy Zou 	else if (ret)
525*0959b670SJoy Zou 		return ret;
526*0959b670SJoy Zou 
527*0959b670SJoy Zou 	for (i = 0; i < desc->n_voltages; i++) {
528*0959b670SJoy Zou 		ret = regulator_desc_list_voltage_linear_range(desc, i);
529*0959b670SJoy Zou 		if (ret < 0)
530*0959b670SJoy Zou 			continue;
531*0959b670SJoy Zou 		if (ret == uv) {
532*0959b670SJoy Zou 			i <<= ffs(desc->vsel_mask) - 1;
533*0959b670SJoy Zou 			ret = pf9453_pmic_write(pf9453, reg, mask, i);
534*0959b670SJoy Zou 			break;
535*0959b670SJoy Zou 		}
536*0959b670SJoy Zou 	}
537*0959b670SJoy Zou 
538*0959b670SJoy Zou 	if (ret == 0) {
539*0959b670SJoy Zou 		struct pf9453_regulator_desc *regulator = container_of(desc,
540*0959b670SJoy Zou 					struct pf9453_regulator_desc, desc);
541*0959b670SJoy Zou 
542*0959b670SJoy Zou 		/* Enable DVS control through PMIC_STBY_REQ for this BUCK */
543*0959b670SJoy Zou 		ret = pf9453_pmic_write(pf9453, regulator->desc.enable_reg,
544*0959b670SJoy Zou 					BUCK2_LPMODE, BUCK2_LPMODE);
545*0959b670SJoy Zou 	}
546*0959b670SJoy Zou 	return ret;
547*0959b670SJoy Zou }
548*0959b670SJoy Zou 
549*0959b670SJoy Zou static int pf9453_set_dvs_levels(struct device_node *np, const struct regulator_desc *desc,
550*0959b670SJoy Zou 				 struct regulator_config *cfg)
551*0959b670SJoy Zou {
552*0959b670SJoy Zou 	struct pf9453_regulator_desc *data = container_of(desc, struct pf9453_regulator_desc, desc);
553*0959b670SJoy Zou 	struct pf9453 *pf9453 = dev_get_drvdata(cfg->dev);
554*0959b670SJoy Zou 	const struct pf9453_dvs_config *dvs = &data->dvs;
555*0959b670SJoy Zou 	unsigned int reg, mask;
556*0959b670SJoy Zou 	int i, ret = 0;
557*0959b670SJoy Zou 	char *prop;
558*0959b670SJoy Zou 
559*0959b670SJoy Zou 	for (i = 0; i < PF9453_DVS_LEVEL_MAX; i++) {
560*0959b670SJoy Zou 		switch (i) {
561*0959b670SJoy Zou 		case PF9453_DVS_LEVEL_RUN:
562*0959b670SJoy Zou 			prop = "nxp,dvs-run-voltage";
563*0959b670SJoy Zou 			reg = dvs->run_reg;
564*0959b670SJoy Zou 			mask = dvs->run_mask;
565*0959b670SJoy Zou 			break;
566*0959b670SJoy Zou 		case PF9453_DVS_LEVEL_DPSTANDBY:
567*0959b670SJoy Zou 		case PF9453_DVS_LEVEL_STANDBY:
568*0959b670SJoy Zou 			prop = "nxp,dvs-standby-voltage";
569*0959b670SJoy Zou 			reg = dvs->standby_reg;
570*0959b670SJoy Zou 			mask = dvs->standby_mask;
571*0959b670SJoy Zou 			break;
572*0959b670SJoy Zou 		default:
573*0959b670SJoy Zou 			return -EINVAL;
574*0959b670SJoy Zou 		}
575*0959b670SJoy Zou 
576*0959b670SJoy Zou 		ret = buck_set_dvs(desc, np, pf9453, prop, reg, mask);
577*0959b670SJoy Zou 		if (ret)
578*0959b670SJoy Zou 			break;
579*0959b670SJoy Zou 	}
580*0959b670SJoy Zou 
581*0959b670SJoy Zou 	return ret;
582*0959b670SJoy Zou }
583*0959b670SJoy Zou 
584*0959b670SJoy Zou static const struct pf9453_regulator_desc pf9453_regulators[] = {
585*0959b670SJoy Zou 	{
586*0959b670SJoy Zou 		.desc = {
587*0959b670SJoy Zou 			.name = "buck1",
588*0959b670SJoy Zou 			.of_match = of_match_ptr("BUCK1"),
589*0959b670SJoy Zou 			.regulators_node = of_match_ptr("regulators"),
590*0959b670SJoy Zou 			.id = PF9453_BUCK1,
591*0959b670SJoy Zou 			.ops = &pf9453_buck_regulator_ops,
592*0959b670SJoy Zou 			.type = REGULATOR_VOLTAGE,
593*0959b670SJoy Zou 			.n_voltages = PF9453_BUCK1_VOLTAGE_NUM,
594*0959b670SJoy Zou 			.linear_ranges = pf9453_buck134_volts,
595*0959b670SJoy Zou 			.n_linear_ranges = ARRAY_SIZE(pf9453_buck134_volts),
596*0959b670SJoy Zou 			.vsel_reg = PF9453_REG_BUCK1OUT,
597*0959b670SJoy Zou 			.vsel_mask = BUCK1OUT_MASK,
598*0959b670SJoy Zou 			.enable_reg = PF9453_REG_BUCK1CTRL,
599*0959b670SJoy Zou 			.enable_mask = BUCK1_ENMODE_MASK,
600*0959b670SJoy Zou 			.enable_val = BUCK_ENMODE_ONREQ,
601*0959b670SJoy Zou 			.owner = THIS_MODULE,
602*0959b670SJoy Zou 		},
603*0959b670SJoy Zou 	},
604*0959b670SJoy Zou 	{
605*0959b670SJoy Zou 		.desc = {
606*0959b670SJoy Zou 			.name = "buck2",
607*0959b670SJoy Zou 			.of_match = of_match_ptr("BUCK2"),
608*0959b670SJoy Zou 			.regulators_node = of_match_ptr("regulators"),
609*0959b670SJoy Zou 			.id = PF9453_BUCK2,
610*0959b670SJoy Zou 			.ops = &pf9453_dvs_buck_regulator_ops,
611*0959b670SJoy Zou 			.type = REGULATOR_VOLTAGE,
612*0959b670SJoy Zou 			.n_voltages = PF9453_BUCK2_VOLTAGE_NUM,
613*0959b670SJoy Zou 			.linear_ranges = pf9453_buck2_volts,
614*0959b670SJoy Zou 			.n_linear_ranges = ARRAY_SIZE(pf9453_buck2_volts),
615*0959b670SJoy Zou 			.vsel_reg = PF9453_REG_BUCK2OUT,
616*0959b670SJoy Zou 			.vsel_mask = BUCK2OUT_MASK,
617*0959b670SJoy Zou 			.enable_reg = PF9453_REG_BUCK2CTRL,
618*0959b670SJoy Zou 			.enable_mask = BUCK2_ENMODE_MASK,
619*0959b670SJoy Zou 			.enable_val = BUCK_ENMODE_ONREQ,
620*0959b670SJoy Zou 			.ramp_reg = PF9453_REG_BUCK2CTRL,
621*0959b670SJoy Zou 			.ramp_mask = BUCK2_RAMP_MASK,
622*0959b670SJoy Zou 			.ramp_delay_table = pf9453_dvs_buck_ramp_table,
623*0959b670SJoy Zou 			.n_ramp_values = ARRAY_SIZE(pf9453_dvs_buck_ramp_table),
624*0959b670SJoy Zou 			.owner = THIS_MODULE,
625*0959b670SJoy Zou 			.of_parse_cb = pf9453_set_dvs_levels,
626*0959b670SJoy Zou 		},
627*0959b670SJoy Zou 		.dvs = {
628*0959b670SJoy Zou 			.run_reg = PF9453_REG_BUCK2OUT,
629*0959b670SJoy Zou 			.run_mask = BUCK2OUT_MASK,
630*0959b670SJoy Zou 			.standby_reg = PF9453_REG_BUCK2OUT_STBY,
631*0959b670SJoy Zou 			.standby_mask = BUCK2OUT_STBY_MASK,
632*0959b670SJoy Zou 		},
633*0959b670SJoy Zou 	},
634*0959b670SJoy Zou 	{
635*0959b670SJoy Zou 		.desc = {
636*0959b670SJoy Zou 			.name = "buck3",
637*0959b670SJoy Zou 			.of_match = of_match_ptr("BUCK3"),
638*0959b670SJoy Zou 			.regulators_node = of_match_ptr("regulators"),
639*0959b670SJoy Zou 			.id = PF9453_BUCK3,
640*0959b670SJoy Zou 			.ops = &pf9453_buck_regulator_ops,
641*0959b670SJoy Zou 			.type = REGULATOR_VOLTAGE,
642*0959b670SJoy Zou 			.n_voltages = PF9453_BUCK3_VOLTAGE_NUM,
643*0959b670SJoy Zou 			.linear_ranges = pf9453_buck134_volts,
644*0959b670SJoy Zou 			.n_linear_ranges = ARRAY_SIZE(pf9453_buck134_volts),
645*0959b670SJoy Zou 			.vsel_reg = PF9453_REG_BUCK3OUT,
646*0959b670SJoy Zou 			.vsel_mask = BUCK3OUT_MASK,
647*0959b670SJoy Zou 			.enable_reg = PF9453_REG_BUCK3CTRL,
648*0959b670SJoy Zou 			.enable_mask = BUCK3_ENMODE_MASK,
649*0959b670SJoy Zou 			.enable_val = BUCK_ENMODE_ONREQ,
650*0959b670SJoy Zou 			.owner = THIS_MODULE,
651*0959b670SJoy Zou 		},
652*0959b670SJoy Zou 	},
653*0959b670SJoy Zou 	{
654*0959b670SJoy Zou 		.desc = {
655*0959b670SJoy Zou 			.name = "buck4",
656*0959b670SJoy Zou 			.of_match = of_match_ptr("BUCK4"),
657*0959b670SJoy Zou 			.regulators_node = of_match_ptr("regulators"),
658*0959b670SJoy Zou 			.id = PF9453_BUCK4,
659*0959b670SJoy Zou 			.ops = &pf9453_buck_regulator_ops,
660*0959b670SJoy Zou 			.type = REGULATOR_VOLTAGE,
661*0959b670SJoy Zou 			.n_voltages = PF9453_BUCK4_VOLTAGE_NUM,
662*0959b670SJoy Zou 			.linear_ranges = pf9453_buck134_volts,
663*0959b670SJoy Zou 			.n_linear_ranges = ARRAY_SIZE(pf9453_buck134_volts),
664*0959b670SJoy Zou 			.vsel_reg = PF9453_REG_BUCK4OUT,
665*0959b670SJoy Zou 			.vsel_mask = BUCK4OUT_MASK,
666*0959b670SJoy Zou 			.enable_reg = PF9453_REG_BUCK4CTRL,
667*0959b670SJoy Zou 			.enable_mask = BUCK4_ENMODE_MASK,
668*0959b670SJoy Zou 			.enable_val = BUCK_ENMODE_ONREQ,
669*0959b670SJoy Zou 			.owner = THIS_MODULE,
670*0959b670SJoy Zou 		},
671*0959b670SJoy Zou 	},
672*0959b670SJoy Zou 	{
673*0959b670SJoy Zou 		.desc = {
674*0959b670SJoy Zou 			.name = "ldo1",
675*0959b670SJoy Zou 			.of_match = of_match_ptr("LDO1"),
676*0959b670SJoy Zou 			.regulators_node = of_match_ptr("regulators"),
677*0959b670SJoy Zou 			.id = PF9453_LDO1,
678*0959b670SJoy Zou 			.ops = &pf9453_ldo_regulator_ops,
679*0959b670SJoy Zou 			.type = REGULATOR_VOLTAGE,
680*0959b670SJoy Zou 			.n_voltages = PF9453_LDO1_VOLTAGE_NUM,
681*0959b670SJoy Zou 			.linear_ranges = pf9453_ldo1_volts,
682*0959b670SJoy Zou 			.n_linear_ranges = ARRAY_SIZE(pf9453_ldo1_volts),
683*0959b670SJoy Zou 			.vsel_reg = PF9453_REG_LDO1OUT_H,
684*0959b670SJoy Zou 			.vsel_mask = LDO1OUT_MASK,
685*0959b670SJoy Zou 			.enable_reg = PF9453_REG_LDO1CFG,
686*0959b670SJoy Zou 			.enable_mask = LDO1_EN_MASK,
687*0959b670SJoy Zou 			.enable_val = LDO_ENMODE_ONREQ,
688*0959b670SJoy Zou 			.owner = THIS_MODULE,
689*0959b670SJoy Zou 		},
690*0959b670SJoy Zou 	},
691*0959b670SJoy Zou 	{
692*0959b670SJoy Zou 		.desc = {
693*0959b670SJoy Zou 			.name = "ldo2",
694*0959b670SJoy Zou 			.of_match = of_match_ptr("LDO2"),
695*0959b670SJoy Zou 			.regulators_node = of_match_ptr("regulators"),
696*0959b670SJoy Zou 			.id = PF9453_LDO2,
697*0959b670SJoy Zou 			.ops = &pf9453_ldo_regulator_ops,
698*0959b670SJoy Zou 			.type = REGULATOR_VOLTAGE,
699*0959b670SJoy Zou 			.n_voltages = PF9453_LDO2_VOLTAGE_NUM,
700*0959b670SJoy Zou 			.linear_ranges = pf9453_ldo2_volts,
701*0959b670SJoy Zou 			.n_linear_ranges = ARRAY_SIZE(pf9453_ldo2_volts),
702*0959b670SJoy Zou 			.vsel_reg = PF9453_REG_LDO2OUT,
703*0959b670SJoy Zou 			.vsel_mask = LDO2OUT_MASK,
704*0959b670SJoy Zou 			.enable_reg = PF9453_REG_LDO2CFG,
705*0959b670SJoy Zou 			.enable_mask = LDO2_EN_MASK,
706*0959b670SJoy Zou 			.enable_val = LDO_ENMODE_ONREQ,
707*0959b670SJoy Zou 			.owner = THIS_MODULE,
708*0959b670SJoy Zou 		},
709*0959b670SJoy Zou 	},
710*0959b670SJoy Zou 	{
711*0959b670SJoy Zou 		.desc = {
712*0959b670SJoy Zou 			.name = "ldosnvs",
713*0959b670SJoy Zou 			.of_match = of_match_ptr("LDO-SNVS"),
714*0959b670SJoy Zou 			.regulators_node = of_match_ptr("regulators"),
715*0959b670SJoy Zou 			.id = PF9453_LDOSNVS,
716*0959b670SJoy Zou 			.ops = &pf9453_ldo_regulator_ops,
717*0959b670SJoy Zou 			.type = REGULATOR_VOLTAGE,
718*0959b670SJoy Zou 			.n_voltages = PF9453_LDOSNVS_VOLTAGE_NUM,
719*0959b670SJoy Zou 			.linear_ranges = pf9453_ldosnvs_volts,
720*0959b670SJoy Zou 			.n_linear_ranges = ARRAY_SIZE(pf9453_ldosnvs_volts),
721*0959b670SJoy Zou 			.vsel_reg = PF9453_REG_LDOSNVS_CFG1,
722*0959b670SJoy Zou 			.vsel_mask = LDOSNVSCFG1_MASK,
723*0959b670SJoy Zou 			.enable_reg = PF9453_REG_LDOSNVS_CFG2,
724*0959b670SJoy Zou 			.enable_mask = LDOSNVS_EN_MASK,
725*0959b670SJoy Zou 			.owner = THIS_MODULE,
726*0959b670SJoy Zou 		},
727*0959b670SJoy Zou 	},
728*0959b670SJoy Zou 	{ }
729*0959b670SJoy Zou };
730*0959b670SJoy Zou 
731*0959b670SJoy Zou static irqreturn_t pf9453_irq_handler(int irq, void *data)
732*0959b670SJoy Zou {
733*0959b670SJoy Zou 	struct pf9453 *pf9453 = data;
734*0959b670SJoy Zou 	struct regmap *regmap = pf9453->regmap;
735*0959b670SJoy Zou 	unsigned int status;
736*0959b670SJoy Zou 	int ret;
737*0959b670SJoy Zou 
738*0959b670SJoy Zou 	ret = regmap_read(regmap, PF9453_REG_INT1, &status);
739*0959b670SJoy Zou 	if (ret < 0) {
740*0959b670SJoy Zou 		dev_err(pf9453->dev, "Failed to read INT1(%d)\n", ret);
741*0959b670SJoy Zou 		return IRQ_NONE;
742*0959b670SJoy Zou 	}
743*0959b670SJoy Zou 
744*0959b670SJoy Zou 	if (status & IRQ_RSTB)
745*0959b670SJoy Zou 		dev_warn(pf9453->dev, "IRQ_RSTB interrupt.\n");
746*0959b670SJoy Zou 
747*0959b670SJoy Zou 	if (status & IRQ_ONKEY)
748*0959b670SJoy Zou 		dev_warn(pf9453->dev, "IRQ_ONKEY interrupt.\n");
749*0959b670SJoy Zou 
750*0959b670SJoy Zou 	if (status & IRQ_VR_FLT1)
751*0959b670SJoy Zou 		dev_warn(pf9453->dev, "VRFLT1 interrupt.\n");
752*0959b670SJoy Zou 
753*0959b670SJoy Zou 	if (status & IRQ_RESETKEY)
754*0959b670SJoy Zou 		dev_warn(pf9453->dev, "IRQ_RESETKEY interrupt.\n");
755*0959b670SJoy Zou 
756*0959b670SJoy Zou 	if (status & IRQ_LOWVSYS)
757*0959b670SJoy Zou 		dev_warn(pf9453->dev, "LOWVSYS interrupt.\n");
758*0959b670SJoy Zou 
759*0959b670SJoy Zou 	if (status & IRQ_THERM_100)
760*0959b670SJoy Zou 		dev_warn(pf9453->dev, "IRQ_THERM_100 interrupt.\n");
761*0959b670SJoy Zou 
762*0959b670SJoy Zou 	if (status & IRQ_THERM_80)
763*0959b670SJoy Zou 		dev_warn(pf9453->dev, "IRQ_THERM_80 interrupt.\n");
764*0959b670SJoy Zou 
765*0959b670SJoy Zou 	return IRQ_HANDLED;
766*0959b670SJoy Zou }
767*0959b670SJoy Zou 
768*0959b670SJoy Zou static int pf9453_i2c_probe(struct i2c_client *i2c)
769*0959b670SJoy Zou {
770*0959b670SJoy Zou 	const struct pf9453_regulator_desc *regulator_desc = of_device_get_match_data(&i2c->dev);
771*0959b670SJoy Zou 	struct regulator_config config = { };
772*0959b670SJoy Zou 	unsigned int reset_ctrl;
773*0959b670SJoy Zou 	unsigned int device_id;
774*0959b670SJoy Zou 	struct pf9453 *pf9453;
775*0959b670SJoy Zou 	int ret;
776*0959b670SJoy Zou 
777*0959b670SJoy Zou 	if (!i2c->irq)
778*0959b670SJoy Zou 		return dev_err_probe(&i2c->dev, -EINVAL, "No IRQ configured?\n");
779*0959b670SJoy Zou 
780*0959b670SJoy Zou 	pf9453 = devm_kzalloc(&i2c->dev, sizeof(struct pf9453), GFP_KERNEL);
781*0959b670SJoy Zou 	if (!pf9453)
782*0959b670SJoy Zou 		return -ENOMEM;
783*0959b670SJoy Zou 
784*0959b670SJoy Zou 	pf9453->regmap = devm_regmap_init_i2c(i2c, &pf9453_regmap_config);
785*0959b670SJoy Zou 	if (IS_ERR(pf9453->regmap))
786*0959b670SJoy Zou 		return dev_err_probe(&i2c->dev, PTR_ERR(pf9453->regmap),
787*0959b670SJoy Zou 				     "regmap initialization failed\n");
788*0959b670SJoy Zou 
789*0959b670SJoy Zou 	pf9453->irq = i2c->irq;
790*0959b670SJoy Zou 	pf9453->dev = &i2c->dev;
791*0959b670SJoy Zou 
792*0959b670SJoy Zou 	dev_set_drvdata(&i2c->dev, pf9453);
793*0959b670SJoy Zou 
794*0959b670SJoy Zou 	ret = regmap_read(pf9453->regmap, PF9453_REG_DEV_ID, &device_id);
795*0959b670SJoy Zou 	if (ret)
796*0959b670SJoy Zou 		return dev_err_probe(&i2c->dev, ret, "Read device id error\n");
797*0959b670SJoy Zou 
798*0959b670SJoy Zou 	/* Check your board and dts for match the right pmic */
799*0959b670SJoy Zou 	if ((device_id >> 4) != 0xb)
800*0959b670SJoy Zou 		return dev_err_probe(&i2c->dev, -EINVAL, "Device id(%x) mismatched\n",
801*0959b670SJoy Zou 				     device_id >> 4);
802*0959b670SJoy Zou 
803*0959b670SJoy Zou 	while (regulator_desc->desc.name) {
804*0959b670SJoy Zou 		const struct regulator_desc *desc;
805*0959b670SJoy Zou 		struct regulator_dev *rdev;
806*0959b670SJoy Zou 
807*0959b670SJoy Zou 		desc = &regulator_desc->desc;
808*0959b670SJoy Zou 
809*0959b670SJoy Zou 		config.regmap = pf9453->regmap;
810*0959b670SJoy Zou 		config.dev = pf9453->dev;
811*0959b670SJoy Zou 
812*0959b670SJoy Zou 		rdev = devm_regulator_register(pf9453->dev, desc, &config);
813*0959b670SJoy Zou 		if (IS_ERR(rdev))
814*0959b670SJoy Zou 			return dev_err_probe(pf9453->dev, PTR_ERR(rdev),
815*0959b670SJoy Zou 					     "Failed to register regulator(%s)\n", desc->name);
816*0959b670SJoy Zou 
817*0959b670SJoy Zou 		regulator_desc++;
818*0959b670SJoy Zou 	}
819*0959b670SJoy Zou 
820*0959b670SJoy Zou 	ret = devm_request_threaded_irq(pf9453->dev, pf9453->irq, NULL, pf9453_irq_handler,
821*0959b670SJoy Zou 					(IRQF_TRIGGER_FALLING | IRQF_ONESHOT),
822*0959b670SJoy Zou 					"pf9453-irq", pf9453);
823*0959b670SJoy Zou 	if (ret)
824*0959b670SJoy Zou 		return dev_err_probe(pf9453->dev, ret, "Failed to request IRQ: %d\n", pf9453->irq);
825*0959b670SJoy Zou 
826*0959b670SJoy Zou 	/* Unmask all interrupt except PWRON/WDOG/RSVD */
827*0959b670SJoy Zou 	ret = pf9453_pmic_write(pf9453, PF9453_REG_INT1_MASK,
828*0959b670SJoy Zou 				IRQ_ONKEY | IRQ_RESETKEY | IRQ_RSTB | IRQ_VR_FLT1
829*0959b670SJoy Zou 				| IRQ_LOWVSYS | IRQ_THERM_100 | IRQ_THERM_80, IRQ_RSVD);
830*0959b670SJoy Zou 	if (ret)
831*0959b670SJoy Zou 		return dev_err_probe(&i2c->dev, ret, "Unmask irq error\n");
832*0959b670SJoy Zou 
833*0959b670SJoy Zou 	if (of_property_read_bool(i2c->dev.of_node, "nxp,wdog_b-warm-reset"))
834*0959b670SJoy Zou 		reset_ctrl = WDOG_B_CFG_WARM;
835*0959b670SJoy Zou 	else
836*0959b670SJoy Zou 		reset_ctrl = WDOG_B_CFG_COLD;
837*0959b670SJoy Zou 
838*0959b670SJoy Zou 	/* Set reset behavior on assertion of WDOG_B signal */
839*0959b670SJoy Zou 	ret = pf9453_pmic_write(pf9453, PF9453_REG_RESET_CTRL, WDOG_B_CFG_MASK, reset_ctrl);
840*0959b670SJoy Zou 	if (ret)
841*0959b670SJoy Zou 		return dev_err_probe(&i2c->dev, ret, "Failed to set WDOG_B reset behavior\n");
842*0959b670SJoy Zou 
843*0959b670SJoy Zou 	/*
844*0959b670SJoy Zou 	 * The driver uses the LDO1OUT_H register to control the LDO1 regulator.
845*0959b670SJoy Zou 	 * This is only valid if the SD_VSEL input of the PMIC is high. Let's
846*0959b670SJoy Zou 	 * check if the pin is available as GPIO and set it to high.
847*0959b670SJoy Zou 	 */
848*0959b670SJoy Zou 	pf9453->sd_vsel_gpio = gpiod_get_optional(pf9453->dev, "sd-vsel", GPIOD_OUT_HIGH);
849*0959b670SJoy Zou 
850*0959b670SJoy Zou 	if (IS_ERR(pf9453->sd_vsel_gpio))
851*0959b670SJoy Zou 		return dev_err_probe(&i2c->dev, PTR_ERR(pf9453->sd_vsel_gpio),
852*0959b670SJoy Zou 				     "Failed to get SD_VSEL GPIO\n");
853*0959b670SJoy Zou 
854*0959b670SJoy Zou 	return 0;
855*0959b670SJoy Zou }
856*0959b670SJoy Zou 
857*0959b670SJoy Zou static const struct of_device_id pf9453_of_match[] = {
858*0959b670SJoy Zou 	{
859*0959b670SJoy Zou 		.compatible = "nxp,pf9453",
860*0959b670SJoy Zou 		.data = pf9453_regulators,
861*0959b670SJoy Zou 	},
862*0959b670SJoy Zou 	{ }
863*0959b670SJoy Zou };
864*0959b670SJoy Zou MODULE_DEVICE_TABLE(of, pf9453_of_match);
865*0959b670SJoy Zou 
866*0959b670SJoy Zou static struct i2c_driver pf9453_i2c_driver = {
867*0959b670SJoy Zou 	.driver = {
868*0959b670SJoy Zou 		.name = "nxp-pf9453",
869*0959b670SJoy Zou 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
870*0959b670SJoy Zou 		.of_match_table = pf9453_of_match,
871*0959b670SJoy Zou 	},
872*0959b670SJoy Zou 	.probe = pf9453_i2c_probe,
873*0959b670SJoy Zou };
874*0959b670SJoy Zou 
875*0959b670SJoy Zou module_i2c_driver(pf9453_i2c_driver);
876*0959b670SJoy Zou 
877*0959b670SJoy Zou MODULE_AUTHOR("Joy Zou <joy.zou@nxp.com>");
878*0959b670SJoy Zou MODULE_DESCRIPTION("NXP PF9453 Power Management IC driver");
879*0959b670SJoy Zou MODULE_LICENSE("GPL");
880