1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright 2020 NXP.
4*4882a593Smuzhiyun * NXP PCA9450 pmic driver
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <linux/err.h>
8*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
9*4882a593Smuzhiyun #include <linux/i2c.h>
10*4882a593Smuzhiyun #include <linux/interrupt.h>
11*4882a593Smuzhiyun #include <linux/kernel.h>
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun #include <linux/of.h>
14*4882a593Smuzhiyun #include <linux/of_device.h>
15*4882a593Smuzhiyun #include <linux/platform_device.h>
16*4882a593Smuzhiyun #include <linux/regulator/driver.h>
17*4882a593Smuzhiyun #include <linux/regulator/machine.h>
18*4882a593Smuzhiyun #include <linux/regulator/of_regulator.h>
19*4882a593Smuzhiyun #include <linux/regulator/pca9450.h>
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun struct pc9450_dvs_config {
22*4882a593Smuzhiyun unsigned int run_reg; /* dvs0 */
23*4882a593Smuzhiyun unsigned int run_mask;
24*4882a593Smuzhiyun unsigned int standby_reg; /* dvs1 */
25*4882a593Smuzhiyun unsigned int standby_mask;
26*4882a593Smuzhiyun };
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun struct pca9450_regulator_desc {
29*4882a593Smuzhiyun struct regulator_desc desc;
30*4882a593Smuzhiyun const struct pc9450_dvs_config dvs;
31*4882a593Smuzhiyun };
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun struct pca9450 {
34*4882a593Smuzhiyun struct device *dev;
35*4882a593Smuzhiyun struct regmap *regmap;
36*4882a593Smuzhiyun struct gpio_desc *sd_vsel_gpio;
37*4882a593Smuzhiyun enum pca9450_chip_type type;
38*4882a593Smuzhiyun unsigned int rcnt;
39*4882a593Smuzhiyun int irq;
40*4882a593Smuzhiyun };
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun static const struct regmap_range pca9450_status_range = {
43*4882a593Smuzhiyun .range_min = PCA9450_REG_INT1,
44*4882a593Smuzhiyun .range_max = PCA9450_REG_PWRON_STAT,
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun static const struct regmap_access_table pca9450_volatile_regs = {
48*4882a593Smuzhiyun .yes_ranges = &pca9450_status_range,
49*4882a593Smuzhiyun .n_yes_ranges = 1,
50*4882a593Smuzhiyun };
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun static const struct regmap_config pca9450_regmap_config = {
53*4882a593Smuzhiyun .reg_bits = 8,
54*4882a593Smuzhiyun .val_bits = 8,
55*4882a593Smuzhiyun .volatile_table = &pca9450_volatile_regs,
56*4882a593Smuzhiyun .max_register = PCA9450_MAX_REGISTER - 1,
57*4882a593Smuzhiyun .cache_type = REGCACHE_RBTREE,
58*4882a593Smuzhiyun };
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun /*
61*4882a593Smuzhiyun * BUCK1/2/3
62*4882a593Smuzhiyun * BUCK1RAM[1:0] BUCK1 DVS ramp rate setting
63*4882a593Smuzhiyun * 00: 25mV/1usec
64*4882a593Smuzhiyun * 01: 25mV/2usec
65*4882a593Smuzhiyun * 10: 25mV/4usec
66*4882a593Smuzhiyun * 11: 25mV/8usec
67*4882a593Smuzhiyun */
pca9450_dvs_set_ramp_delay(struct regulator_dev * rdev,int ramp_delay)68*4882a593Smuzhiyun static int pca9450_dvs_set_ramp_delay(struct regulator_dev *rdev,
69*4882a593Smuzhiyun int ramp_delay)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun int id = rdev_get_id(rdev);
72*4882a593Smuzhiyun unsigned int ramp_value;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun switch (ramp_delay) {
75*4882a593Smuzhiyun case 1 ... 3125:
76*4882a593Smuzhiyun ramp_value = BUCK1_RAMP_3P125MV;
77*4882a593Smuzhiyun break;
78*4882a593Smuzhiyun case 3126 ... 6250:
79*4882a593Smuzhiyun ramp_value = BUCK1_RAMP_6P25MV;
80*4882a593Smuzhiyun break;
81*4882a593Smuzhiyun case 6251 ... 12500:
82*4882a593Smuzhiyun ramp_value = BUCK1_RAMP_12P5MV;
83*4882a593Smuzhiyun break;
84*4882a593Smuzhiyun case 12501 ... 25000:
85*4882a593Smuzhiyun ramp_value = BUCK1_RAMP_25MV;
86*4882a593Smuzhiyun break;
87*4882a593Smuzhiyun default:
88*4882a593Smuzhiyun ramp_value = BUCK1_RAMP_25MV;
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun return regmap_update_bits(rdev->regmap, PCA9450_REG_BUCK1CTRL + id * 3,
92*4882a593Smuzhiyun BUCK1_RAMP_MASK, ramp_value << 6);
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun static const struct regulator_ops pca9450_dvs_buck_regulator_ops = {
96*4882a593Smuzhiyun .enable = regulator_enable_regmap,
97*4882a593Smuzhiyun .disable = regulator_disable_regmap,
98*4882a593Smuzhiyun .is_enabled = regulator_is_enabled_regmap,
99*4882a593Smuzhiyun .list_voltage = regulator_list_voltage_linear_range,
100*4882a593Smuzhiyun .set_voltage_sel = regulator_set_voltage_sel_regmap,
101*4882a593Smuzhiyun .get_voltage_sel = regulator_get_voltage_sel_regmap,
102*4882a593Smuzhiyun .set_voltage_time_sel = regulator_set_voltage_time_sel,
103*4882a593Smuzhiyun .set_ramp_delay = pca9450_dvs_set_ramp_delay,
104*4882a593Smuzhiyun };
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun static const struct regulator_ops pca9450_buck_regulator_ops = {
107*4882a593Smuzhiyun .enable = regulator_enable_regmap,
108*4882a593Smuzhiyun .disable = regulator_disable_regmap,
109*4882a593Smuzhiyun .is_enabled = regulator_is_enabled_regmap,
110*4882a593Smuzhiyun .list_voltage = regulator_list_voltage_linear_range,
111*4882a593Smuzhiyun .set_voltage_sel = regulator_set_voltage_sel_regmap,
112*4882a593Smuzhiyun .get_voltage_sel = regulator_get_voltage_sel_regmap,
113*4882a593Smuzhiyun .set_voltage_time_sel = regulator_set_voltage_time_sel,
114*4882a593Smuzhiyun };
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun static const struct regulator_ops pca9450_ldo_regulator_ops = {
117*4882a593Smuzhiyun .enable = regulator_enable_regmap,
118*4882a593Smuzhiyun .disable = regulator_disable_regmap,
119*4882a593Smuzhiyun .is_enabled = regulator_is_enabled_regmap,
120*4882a593Smuzhiyun .list_voltage = regulator_list_voltage_linear_range,
121*4882a593Smuzhiyun .set_voltage_sel = regulator_set_voltage_sel_regmap,
122*4882a593Smuzhiyun .get_voltage_sel = regulator_get_voltage_sel_regmap,
123*4882a593Smuzhiyun };
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun /*
126*4882a593Smuzhiyun * BUCK1/2/3
127*4882a593Smuzhiyun * 0.60 to 2.1875V (12.5mV step)
128*4882a593Smuzhiyun */
129*4882a593Smuzhiyun static const struct linear_range pca9450_dvs_buck_volts[] = {
130*4882a593Smuzhiyun REGULATOR_LINEAR_RANGE(600000, 0x00, 0x7F, 12500),
131*4882a593Smuzhiyun };
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun /*
134*4882a593Smuzhiyun * BUCK4/5/6
135*4882a593Smuzhiyun * 0.6V to 3.4V (25mV step)
136*4882a593Smuzhiyun */
137*4882a593Smuzhiyun static const struct linear_range pca9450_buck_volts[] = {
138*4882a593Smuzhiyun REGULATOR_LINEAR_RANGE(600000, 0x00, 0x70, 25000),
139*4882a593Smuzhiyun REGULATOR_LINEAR_RANGE(3400000, 0x71, 0x7F, 0),
140*4882a593Smuzhiyun };
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun /*
143*4882a593Smuzhiyun * LDO1
144*4882a593Smuzhiyun * 1.6 to 3.3V ()
145*4882a593Smuzhiyun */
146*4882a593Smuzhiyun static const struct linear_range pca9450_ldo1_volts[] = {
147*4882a593Smuzhiyun REGULATOR_LINEAR_RANGE(1600000, 0x00, 0x03, 100000),
148*4882a593Smuzhiyun REGULATOR_LINEAR_RANGE(3000000, 0x04, 0x07, 100000),
149*4882a593Smuzhiyun };
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun /*
152*4882a593Smuzhiyun * LDO2
153*4882a593Smuzhiyun * 0.8 to 1.15V (50mV step)
154*4882a593Smuzhiyun */
155*4882a593Smuzhiyun static const struct linear_range pca9450_ldo2_volts[] = {
156*4882a593Smuzhiyun REGULATOR_LINEAR_RANGE(800000, 0x00, 0x07, 50000),
157*4882a593Smuzhiyun };
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun /*
160*4882a593Smuzhiyun * LDO3/4
161*4882a593Smuzhiyun * 0.8 to 3.3V (100mV step)
162*4882a593Smuzhiyun */
163*4882a593Smuzhiyun static const struct linear_range pca9450_ldo34_volts[] = {
164*4882a593Smuzhiyun REGULATOR_LINEAR_RANGE(800000, 0x00, 0x19, 100000),
165*4882a593Smuzhiyun REGULATOR_LINEAR_RANGE(3300000, 0x1A, 0x1F, 0),
166*4882a593Smuzhiyun };
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun /*
169*4882a593Smuzhiyun * LDO5
170*4882a593Smuzhiyun * 1.8 to 3.3V (100mV step)
171*4882a593Smuzhiyun */
172*4882a593Smuzhiyun static const struct linear_range pca9450_ldo5_volts[] = {
173*4882a593Smuzhiyun REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000),
174*4882a593Smuzhiyun };
175*4882a593Smuzhiyun
buck_set_dvs(const struct regulator_desc * desc,struct device_node * np,struct regmap * regmap,char * prop,unsigned int reg,unsigned int mask)176*4882a593Smuzhiyun static int buck_set_dvs(const struct regulator_desc *desc,
177*4882a593Smuzhiyun struct device_node *np, struct regmap *regmap,
178*4882a593Smuzhiyun char *prop, unsigned int reg, unsigned int mask)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun int ret, i;
181*4882a593Smuzhiyun uint32_t uv;
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun ret = of_property_read_u32(np, prop, &uv);
184*4882a593Smuzhiyun if (ret == -EINVAL)
185*4882a593Smuzhiyun return 0;
186*4882a593Smuzhiyun else if (ret)
187*4882a593Smuzhiyun return ret;
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun for (i = 0; i < desc->n_voltages; i++) {
190*4882a593Smuzhiyun ret = regulator_desc_list_voltage_linear_range(desc, i);
191*4882a593Smuzhiyun if (ret < 0)
192*4882a593Smuzhiyun continue;
193*4882a593Smuzhiyun if (ret == uv) {
194*4882a593Smuzhiyun i <<= ffs(desc->vsel_mask) - 1;
195*4882a593Smuzhiyun ret = regmap_update_bits(regmap, reg, mask, i);
196*4882a593Smuzhiyun break;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun return ret;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
pca9450_set_dvs_levels(struct device_node * np,const struct regulator_desc * desc,struct regulator_config * cfg)203*4882a593Smuzhiyun static int pca9450_set_dvs_levels(struct device_node *np,
204*4882a593Smuzhiyun const struct regulator_desc *desc,
205*4882a593Smuzhiyun struct regulator_config *cfg)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun struct pca9450_regulator_desc *data = container_of(desc,
208*4882a593Smuzhiyun struct pca9450_regulator_desc, desc);
209*4882a593Smuzhiyun const struct pc9450_dvs_config *dvs = &data->dvs;
210*4882a593Smuzhiyun unsigned int reg, mask;
211*4882a593Smuzhiyun char *prop;
212*4882a593Smuzhiyun int i, ret = 0;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun for (i = 0; i < PCA9450_DVS_LEVEL_MAX; i++) {
215*4882a593Smuzhiyun switch (i) {
216*4882a593Smuzhiyun case PCA9450_DVS_LEVEL_RUN:
217*4882a593Smuzhiyun prop = "nxp,dvs-run-voltage";
218*4882a593Smuzhiyun reg = dvs->run_reg;
219*4882a593Smuzhiyun mask = dvs->run_mask;
220*4882a593Smuzhiyun break;
221*4882a593Smuzhiyun case PCA9450_DVS_LEVEL_STANDBY:
222*4882a593Smuzhiyun prop = "nxp,dvs-standby-voltage";
223*4882a593Smuzhiyun reg = dvs->standby_reg;
224*4882a593Smuzhiyun mask = dvs->standby_mask;
225*4882a593Smuzhiyun break;
226*4882a593Smuzhiyun default:
227*4882a593Smuzhiyun return -EINVAL;
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun ret = buck_set_dvs(desc, np, cfg->regmap, prop, reg, mask);
231*4882a593Smuzhiyun if (ret)
232*4882a593Smuzhiyun break;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun return ret;
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun static const struct pca9450_regulator_desc pca9450a_regulators[] = {
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun .desc = {
241*4882a593Smuzhiyun .name = "buck1",
242*4882a593Smuzhiyun .of_match = of_match_ptr("BUCK1"),
243*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
244*4882a593Smuzhiyun .id = PCA9450_BUCK1,
245*4882a593Smuzhiyun .ops = &pca9450_dvs_buck_regulator_ops,
246*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
247*4882a593Smuzhiyun .n_voltages = PCA9450_BUCK1_VOLTAGE_NUM,
248*4882a593Smuzhiyun .linear_ranges = pca9450_dvs_buck_volts,
249*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts),
250*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_BUCK1OUT_DVS0,
251*4882a593Smuzhiyun .vsel_mask = BUCK1OUT_DVS0_MASK,
252*4882a593Smuzhiyun .enable_reg = PCA9450_REG_BUCK1CTRL,
253*4882a593Smuzhiyun .enable_mask = BUCK1_ENMODE_MASK,
254*4882a593Smuzhiyun .owner = THIS_MODULE,
255*4882a593Smuzhiyun .of_parse_cb = pca9450_set_dvs_levels,
256*4882a593Smuzhiyun },
257*4882a593Smuzhiyun .dvs = {
258*4882a593Smuzhiyun .run_reg = PCA9450_REG_BUCK1OUT_DVS0,
259*4882a593Smuzhiyun .run_mask = BUCK1OUT_DVS0_MASK,
260*4882a593Smuzhiyun .standby_reg = PCA9450_REG_BUCK1OUT_DVS1,
261*4882a593Smuzhiyun .standby_mask = BUCK1OUT_DVS1_MASK,
262*4882a593Smuzhiyun },
263*4882a593Smuzhiyun },
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun .desc = {
266*4882a593Smuzhiyun .name = "buck2",
267*4882a593Smuzhiyun .of_match = of_match_ptr("BUCK2"),
268*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
269*4882a593Smuzhiyun .id = PCA9450_BUCK2,
270*4882a593Smuzhiyun .ops = &pca9450_dvs_buck_regulator_ops,
271*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
272*4882a593Smuzhiyun .n_voltages = PCA9450_BUCK2_VOLTAGE_NUM,
273*4882a593Smuzhiyun .linear_ranges = pca9450_dvs_buck_volts,
274*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts),
275*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_BUCK2OUT_DVS0,
276*4882a593Smuzhiyun .vsel_mask = BUCK2OUT_DVS0_MASK,
277*4882a593Smuzhiyun .enable_reg = PCA9450_REG_BUCK2CTRL,
278*4882a593Smuzhiyun .enable_mask = BUCK1_ENMODE_MASK,
279*4882a593Smuzhiyun .owner = THIS_MODULE,
280*4882a593Smuzhiyun .of_parse_cb = pca9450_set_dvs_levels,
281*4882a593Smuzhiyun },
282*4882a593Smuzhiyun .dvs = {
283*4882a593Smuzhiyun .run_reg = PCA9450_REG_BUCK2OUT_DVS0,
284*4882a593Smuzhiyun .run_mask = BUCK2OUT_DVS0_MASK,
285*4882a593Smuzhiyun .standby_reg = PCA9450_REG_BUCK2OUT_DVS1,
286*4882a593Smuzhiyun .standby_mask = BUCK2OUT_DVS1_MASK,
287*4882a593Smuzhiyun },
288*4882a593Smuzhiyun },
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun .desc = {
291*4882a593Smuzhiyun .name = "buck3",
292*4882a593Smuzhiyun .of_match = of_match_ptr("BUCK3"),
293*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
294*4882a593Smuzhiyun .id = PCA9450_BUCK3,
295*4882a593Smuzhiyun .ops = &pca9450_dvs_buck_regulator_ops,
296*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
297*4882a593Smuzhiyun .n_voltages = PCA9450_BUCK3_VOLTAGE_NUM,
298*4882a593Smuzhiyun .linear_ranges = pca9450_dvs_buck_volts,
299*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts),
300*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_BUCK3OUT_DVS0,
301*4882a593Smuzhiyun .vsel_mask = BUCK3OUT_DVS0_MASK,
302*4882a593Smuzhiyun .enable_reg = PCA9450_REG_BUCK3CTRL,
303*4882a593Smuzhiyun .enable_mask = BUCK3_ENMODE_MASK,
304*4882a593Smuzhiyun .owner = THIS_MODULE,
305*4882a593Smuzhiyun .of_parse_cb = pca9450_set_dvs_levels,
306*4882a593Smuzhiyun },
307*4882a593Smuzhiyun .dvs = {
308*4882a593Smuzhiyun .run_reg = PCA9450_REG_BUCK3OUT_DVS0,
309*4882a593Smuzhiyun .run_mask = BUCK3OUT_DVS0_MASK,
310*4882a593Smuzhiyun .standby_reg = PCA9450_REG_BUCK3OUT_DVS1,
311*4882a593Smuzhiyun .standby_mask = BUCK3OUT_DVS1_MASK,
312*4882a593Smuzhiyun },
313*4882a593Smuzhiyun },
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun .desc = {
316*4882a593Smuzhiyun .name = "buck4",
317*4882a593Smuzhiyun .of_match = of_match_ptr("BUCK4"),
318*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
319*4882a593Smuzhiyun .id = PCA9450_BUCK4,
320*4882a593Smuzhiyun .ops = &pca9450_buck_regulator_ops,
321*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
322*4882a593Smuzhiyun .n_voltages = PCA9450_BUCK4_VOLTAGE_NUM,
323*4882a593Smuzhiyun .linear_ranges = pca9450_buck_volts,
324*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
325*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_BUCK4OUT,
326*4882a593Smuzhiyun .vsel_mask = BUCK4OUT_MASK,
327*4882a593Smuzhiyun .enable_reg = PCA9450_REG_BUCK4CTRL,
328*4882a593Smuzhiyun .enable_mask = BUCK4_ENMODE_MASK,
329*4882a593Smuzhiyun .owner = THIS_MODULE,
330*4882a593Smuzhiyun },
331*4882a593Smuzhiyun },
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun .desc = {
334*4882a593Smuzhiyun .name = "buck5",
335*4882a593Smuzhiyun .of_match = of_match_ptr("BUCK5"),
336*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
337*4882a593Smuzhiyun .id = PCA9450_BUCK5,
338*4882a593Smuzhiyun .ops = &pca9450_buck_regulator_ops,
339*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
340*4882a593Smuzhiyun .n_voltages = PCA9450_BUCK5_VOLTAGE_NUM,
341*4882a593Smuzhiyun .linear_ranges = pca9450_buck_volts,
342*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
343*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_BUCK5OUT,
344*4882a593Smuzhiyun .vsel_mask = BUCK5OUT_MASK,
345*4882a593Smuzhiyun .enable_reg = PCA9450_REG_BUCK5CTRL,
346*4882a593Smuzhiyun .enable_mask = BUCK5_ENMODE_MASK,
347*4882a593Smuzhiyun .owner = THIS_MODULE,
348*4882a593Smuzhiyun },
349*4882a593Smuzhiyun },
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun .desc = {
352*4882a593Smuzhiyun .name = "buck6",
353*4882a593Smuzhiyun .of_match = of_match_ptr("BUCK6"),
354*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
355*4882a593Smuzhiyun .id = PCA9450_BUCK6,
356*4882a593Smuzhiyun .ops = &pca9450_buck_regulator_ops,
357*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
358*4882a593Smuzhiyun .n_voltages = PCA9450_BUCK6_VOLTAGE_NUM,
359*4882a593Smuzhiyun .linear_ranges = pca9450_buck_volts,
360*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
361*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_BUCK6OUT,
362*4882a593Smuzhiyun .vsel_mask = BUCK6OUT_MASK,
363*4882a593Smuzhiyun .enable_reg = PCA9450_REG_BUCK6CTRL,
364*4882a593Smuzhiyun .enable_mask = BUCK6_ENMODE_MASK,
365*4882a593Smuzhiyun .owner = THIS_MODULE,
366*4882a593Smuzhiyun },
367*4882a593Smuzhiyun },
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun .desc = {
370*4882a593Smuzhiyun .name = "ldo1",
371*4882a593Smuzhiyun .of_match = of_match_ptr("LDO1"),
372*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
373*4882a593Smuzhiyun .id = PCA9450_LDO1,
374*4882a593Smuzhiyun .ops = &pca9450_ldo_regulator_ops,
375*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
376*4882a593Smuzhiyun .n_voltages = PCA9450_LDO1_VOLTAGE_NUM,
377*4882a593Smuzhiyun .linear_ranges = pca9450_ldo1_volts,
378*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_ldo1_volts),
379*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_LDO1CTRL,
380*4882a593Smuzhiyun .vsel_mask = LDO1OUT_MASK,
381*4882a593Smuzhiyun .enable_reg = PCA9450_REG_LDO1CTRL,
382*4882a593Smuzhiyun .enable_mask = LDO1_EN_MASK,
383*4882a593Smuzhiyun .owner = THIS_MODULE,
384*4882a593Smuzhiyun },
385*4882a593Smuzhiyun },
386*4882a593Smuzhiyun {
387*4882a593Smuzhiyun .desc = {
388*4882a593Smuzhiyun .name = "ldo2",
389*4882a593Smuzhiyun .of_match = of_match_ptr("LDO2"),
390*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
391*4882a593Smuzhiyun .id = PCA9450_LDO2,
392*4882a593Smuzhiyun .ops = &pca9450_ldo_regulator_ops,
393*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
394*4882a593Smuzhiyun .n_voltages = PCA9450_LDO2_VOLTAGE_NUM,
395*4882a593Smuzhiyun .linear_ranges = pca9450_ldo2_volts,
396*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_ldo2_volts),
397*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_LDO2CTRL,
398*4882a593Smuzhiyun .vsel_mask = LDO2OUT_MASK,
399*4882a593Smuzhiyun .enable_reg = PCA9450_REG_LDO2CTRL,
400*4882a593Smuzhiyun .enable_mask = LDO2_EN_MASK,
401*4882a593Smuzhiyun .owner = THIS_MODULE,
402*4882a593Smuzhiyun },
403*4882a593Smuzhiyun },
404*4882a593Smuzhiyun {
405*4882a593Smuzhiyun .desc = {
406*4882a593Smuzhiyun .name = "ldo3",
407*4882a593Smuzhiyun .of_match = of_match_ptr("LDO3"),
408*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
409*4882a593Smuzhiyun .id = PCA9450_LDO3,
410*4882a593Smuzhiyun .ops = &pca9450_ldo_regulator_ops,
411*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
412*4882a593Smuzhiyun .n_voltages = PCA9450_LDO3_VOLTAGE_NUM,
413*4882a593Smuzhiyun .linear_ranges = pca9450_ldo34_volts,
414*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts),
415*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_LDO3CTRL,
416*4882a593Smuzhiyun .vsel_mask = LDO3OUT_MASK,
417*4882a593Smuzhiyun .enable_reg = PCA9450_REG_LDO3CTRL,
418*4882a593Smuzhiyun .enable_mask = LDO3_EN_MASK,
419*4882a593Smuzhiyun .owner = THIS_MODULE,
420*4882a593Smuzhiyun },
421*4882a593Smuzhiyun },
422*4882a593Smuzhiyun {
423*4882a593Smuzhiyun .desc = {
424*4882a593Smuzhiyun .name = "ldo4",
425*4882a593Smuzhiyun .of_match = of_match_ptr("LDO4"),
426*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
427*4882a593Smuzhiyun .id = PCA9450_LDO4,
428*4882a593Smuzhiyun .ops = &pca9450_ldo_regulator_ops,
429*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
430*4882a593Smuzhiyun .n_voltages = PCA9450_LDO4_VOLTAGE_NUM,
431*4882a593Smuzhiyun .linear_ranges = pca9450_ldo34_volts,
432*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts),
433*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_LDO4CTRL,
434*4882a593Smuzhiyun .vsel_mask = LDO4OUT_MASK,
435*4882a593Smuzhiyun .enable_reg = PCA9450_REG_LDO4CTRL,
436*4882a593Smuzhiyun .enable_mask = LDO4_EN_MASK,
437*4882a593Smuzhiyun .owner = THIS_MODULE,
438*4882a593Smuzhiyun },
439*4882a593Smuzhiyun },
440*4882a593Smuzhiyun {
441*4882a593Smuzhiyun .desc = {
442*4882a593Smuzhiyun .name = "ldo5",
443*4882a593Smuzhiyun .of_match = of_match_ptr("LDO5"),
444*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
445*4882a593Smuzhiyun .id = PCA9450_LDO5,
446*4882a593Smuzhiyun .ops = &pca9450_ldo_regulator_ops,
447*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
448*4882a593Smuzhiyun .n_voltages = PCA9450_LDO5_VOLTAGE_NUM,
449*4882a593Smuzhiyun .linear_ranges = pca9450_ldo5_volts,
450*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_ldo5_volts),
451*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_LDO5CTRL_H,
452*4882a593Smuzhiyun .vsel_mask = LDO5HOUT_MASK,
453*4882a593Smuzhiyun .enable_reg = PCA9450_REG_LDO5CTRL_H,
454*4882a593Smuzhiyun .enable_mask = LDO5H_EN_MASK,
455*4882a593Smuzhiyun .owner = THIS_MODULE,
456*4882a593Smuzhiyun },
457*4882a593Smuzhiyun },
458*4882a593Smuzhiyun };
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun /*
461*4882a593Smuzhiyun * Buck3 removed on PCA9450B and connected with Buck1 internal for dual phase
462*4882a593Smuzhiyun * on PCA9450C as no Buck3.
463*4882a593Smuzhiyun */
464*4882a593Smuzhiyun static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
465*4882a593Smuzhiyun {
466*4882a593Smuzhiyun .desc = {
467*4882a593Smuzhiyun .name = "buck1",
468*4882a593Smuzhiyun .of_match = of_match_ptr("BUCK1"),
469*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
470*4882a593Smuzhiyun .id = PCA9450_BUCK1,
471*4882a593Smuzhiyun .ops = &pca9450_dvs_buck_regulator_ops,
472*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
473*4882a593Smuzhiyun .n_voltages = PCA9450_BUCK1_VOLTAGE_NUM,
474*4882a593Smuzhiyun .linear_ranges = pca9450_dvs_buck_volts,
475*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts),
476*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_BUCK1OUT_DVS0,
477*4882a593Smuzhiyun .vsel_mask = BUCK1OUT_DVS0_MASK,
478*4882a593Smuzhiyun .enable_reg = PCA9450_REG_BUCK1CTRL,
479*4882a593Smuzhiyun .enable_mask = BUCK1_ENMODE_MASK,
480*4882a593Smuzhiyun .owner = THIS_MODULE,
481*4882a593Smuzhiyun .of_parse_cb = pca9450_set_dvs_levels,
482*4882a593Smuzhiyun },
483*4882a593Smuzhiyun .dvs = {
484*4882a593Smuzhiyun .run_reg = PCA9450_REG_BUCK1OUT_DVS0,
485*4882a593Smuzhiyun .run_mask = BUCK1OUT_DVS0_MASK,
486*4882a593Smuzhiyun .standby_reg = PCA9450_REG_BUCK1OUT_DVS1,
487*4882a593Smuzhiyun .standby_mask = BUCK1OUT_DVS1_MASK,
488*4882a593Smuzhiyun },
489*4882a593Smuzhiyun },
490*4882a593Smuzhiyun {
491*4882a593Smuzhiyun .desc = {
492*4882a593Smuzhiyun .name = "buck2",
493*4882a593Smuzhiyun .of_match = of_match_ptr("BUCK2"),
494*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
495*4882a593Smuzhiyun .id = PCA9450_BUCK2,
496*4882a593Smuzhiyun .ops = &pca9450_dvs_buck_regulator_ops,
497*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
498*4882a593Smuzhiyun .n_voltages = PCA9450_BUCK2_VOLTAGE_NUM,
499*4882a593Smuzhiyun .linear_ranges = pca9450_dvs_buck_volts,
500*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts),
501*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_BUCK2OUT_DVS0,
502*4882a593Smuzhiyun .vsel_mask = BUCK2OUT_DVS0_MASK,
503*4882a593Smuzhiyun .enable_reg = PCA9450_REG_BUCK2CTRL,
504*4882a593Smuzhiyun .enable_mask = BUCK1_ENMODE_MASK,
505*4882a593Smuzhiyun .owner = THIS_MODULE,
506*4882a593Smuzhiyun .of_parse_cb = pca9450_set_dvs_levels,
507*4882a593Smuzhiyun },
508*4882a593Smuzhiyun .dvs = {
509*4882a593Smuzhiyun .run_reg = PCA9450_REG_BUCK2OUT_DVS0,
510*4882a593Smuzhiyun .run_mask = BUCK2OUT_DVS0_MASK,
511*4882a593Smuzhiyun .standby_reg = PCA9450_REG_BUCK2OUT_DVS1,
512*4882a593Smuzhiyun .standby_mask = BUCK2OUT_DVS1_MASK,
513*4882a593Smuzhiyun },
514*4882a593Smuzhiyun },
515*4882a593Smuzhiyun {
516*4882a593Smuzhiyun .desc = {
517*4882a593Smuzhiyun .name = "buck4",
518*4882a593Smuzhiyun .of_match = of_match_ptr("BUCK4"),
519*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
520*4882a593Smuzhiyun .id = PCA9450_BUCK4,
521*4882a593Smuzhiyun .ops = &pca9450_buck_regulator_ops,
522*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
523*4882a593Smuzhiyun .n_voltages = PCA9450_BUCK4_VOLTAGE_NUM,
524*4882a593Smuzhiyun .linear_ranges = pca9450_buck_volts,
525*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
526*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_BUCK4OUT,
527*4882a593Smuzhiyun .vsel_mask = BUCK4OUT_MASK,
528*4882a593Smuzhiyun .enable_reg = PCA9450_REG_BUCK4CTRL,
529*4882a593Smuzhiyun .enable_mask = BUCK4_ENMODE_MASK,
530*4882a593Smuzhiyun .owner = THIS_MODULE,
531*4882a593Smuzhiyun },
532*4882a593Smuzhiyun },
533*4882a593Smuzhiyun {
534*4882a593Smuzhiyun .desc = {
535*4882a593Smuzhiyun .name = "buck5",
536*4882a593Smuzhiyun .of_match = of_match_ptr("BUCK5"),
537*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
538*4882a593Smuzhiyun .id = PCA9450_BUCK5,
539*4882a593Smuzhiyun .ops = &pca9450_buck_regulator_ops,
540*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
541*4882a593Smuzhiyun .n_voltages = PCA9450_BUCK5_VOLTAGE_NUM,
542*4882a593Smuzhiyun .linear_ranges = pca9450_buck_volts,
543*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
544*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_BUCK5OUT,
545*4882a593Smuzhiyun .vsel_mask = BUCK5OUT_MASK,
546*4882a593Smuzhiyun .enable_reg = PCA9450_REG_BUCK5CTRL,
547*4882a593Smuzhiyun .enable_mask = BUCK5_ENMODE_MASK,
548*4882a593Smuzhiyun .owner = THIS_MODULE,
549*4882a593Smuzhiyun },
550*4882a593Smuzhiyun },
551*4882a593Smuzhiyun {
552*4882a593Smuzhiyun .desc = {
553*4882a593Smuzhiyun .name = "buck6",
554*4882a593Smuzhiyun .of_match = of_match_ptr("BUCK6"),
555*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
556*4882a593Smuzhiyun .id = PCA9450_BUCK6,
557*4882a593Smuzhiyun .ops = &pca9450_buck_regulator_ops,
558*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
559*4882a593Smuzhiyun .n_voltages = PCA9450_BUCK6_VOLTAGE_NUM,
560*4882a593Smuzhiyun .linear_ranges = pca9450_buck_volts,
561*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts),
562*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_BUCK6OUT,
563*4882a593Smuzhiyun .vsel_mask = BUCK6OUT_MASK,
564*4882a593Smuzhiyun .enable_reg = PCA9450_REG_BUCK6CTRL,
565*4882a593Smuzhiyun .enable_mask = BUCK6_ENMODE_MASK,
566*4882a593Smuzhiyun .owner = THIS_MODULE,
567*4882a593Smuzhiyun },
568*4882a593Smuzhiyun },
569*4882a593Smuzhiyun {
570*4882a593Smuzhiyun .desc = {
571*4882a593Smuzhiyun .name = "ldo1",
572*4882a593Smuzhiyun .of_match = of_match_ptr("LDO1"),
573*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
574*4882a593Smuzhiyun .id = PCA9450_LDO1,
575*4882a593Smuzhiyun .ops = &pca9450_ldo_regulator_ops,
576*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
577*4882a593Smuzhiyun .n_voltages = PCA9450_LDO1_VOLTAGE_NUM,
578*4882a593Smuzhiyun .linear_ranges = pca9450_ldo1_volts,
579*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_ldo1_volts),
580*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_LDO1CTRL,
581*4882a593Smuzhiyun .vsel_mask = LDO1OUT_MASK,
582*4882a593Smuzhiyun .enable_reg = PCA9450_REG_LDO1CTRL,
583*4882a593Smuzhiyun .enable_mask = LDO1_EN_MASK,
584*4882a593Smuzhiyun .owner = THIS_MODULE,
585*4882a593Smuzhiyun },
586*4882a593Smuzhiyun },
587*4882a593Smuzhiyun {
588*4882a593Smuzhiyun .desc = {
589*4882a593Smuzhiyun .name = "ldo2",
590*4882a593Smuzhiyun .of_match = of_match_ptr("LDO2"),
591*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
592*4882a593Smuzhiyun .id = PCA9450_LDO2,
593*4882a593Smuzhiyun .ops = &pca9450_ldo_regulator_ops,
594*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
595*4882a593Smuzhiyun .n_voltages = PCA9450_LDO2_VOLTAGE_NUM,
596*4882a593Smuzhiyun .linear_ranges = pca9450_ldo2_volts,
597*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_ldo2_volts),
598*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_LDO2CTRL,
599*4882a593Smuzhiyun .vsel_mask = LDO2OUT_MASK,
600*4882a593Smuzhiyun .enable_reg = PCA9450_REG_LDO2CTRL,
601*4882a593Smuzhiyun .enable_mask = LDO2_EN_MASK,
602*4882a593Smuzhiyun .owner = THIS_MODULE,
603*4882a593Smuzhiyun },
604*4882a593Smuzhiyun },
605*4882a593Smuzhiyun {
606*4882a593Smuzhiyun .desc = {
607*4882a593Smuzhiyun .name = "ldo3",
608*4882a593Smuzhiyun .of_match = of_match_ptr("LDO3"),
609*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
610*4882a593Smuzhiyun .id = PCA9450_LDO3,
611*4882a593Smuzhiyun .ops = &pca9450_ldo_regulator_ops,
612*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
613*4882a593Smuzhiyun .n_voltages = PCA9450_LDO3_VOLTAGE_NUM,
614*4882a593Smuzhiyun .linear_ranges = pca9450_ldo34_volts,
615*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts),
616*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_LDO3CTRL,
617*4882a593Smuzhiyun .vsel_mask = LDO3OUT_MASK,
618*4882a593Smuzhiyun .enable_reg = PCA9450_REG_LDO3CTRL,
619*4882a593Smuzhiyun .enable_mask = LDO3_EN_MASK,
620*4882a593Smuzhiyun .owner = THIS_MODULE,
621*4882a593Smuzhiyun },
622*4882a593Smuzhiyun },
623*4882a593Smuzhiyun {
624*4882a593Smuzhiyun .desc = {
625*4882a593Smuzhiyun .name = "ldo4",
626*4882a593Smuzhiyun .of_match = of_match_ptr("LDO4"),
627*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
628*4882a593Smuzhiyun .id = PCA9450_LDO4,
629*4882a593Smuzhiyun .ops = &pca9450_ldo_regulator_ops,
630*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
631*4882a593Smuzhiyun .n_voltages = PCA9450_LDO4_VOLTAGE_NUM,
632*4882a593Smuzhiyun .linear_ranges = pca9450_ldo34_volts,
633*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts),
634*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_LDO4CTRL,
635*4882a593Smuzhiyun .vsel_mask = LDO4OUT_MASK,
636*4882a593Smuzhiyun .enable_reg = PCA9450_REG_LDO4CTRL,
637*4882a593Smuzhiyun .enable_mask = LDO4_EN_MASK,
638*4882a593Smuzhiyun .owner = THIS_MODULE,
639*4882a593Smuzhiyun },
640*4882a593Smuzhiyun },
641*4882a593Smuzhiyun {
642*4882a593Smuzhiyun .desc = {
643*4882a593Smuzhiyun .name = "ldo5",
644*4882a593Smuzhiyun .of_match = of_match_ptr("LDO5"),
645*4882a593Smuzhiyun .regulators_node = of_match_ptr("regulators"),
646*4882a593Smuzhiyun .id = PCA9450_LDO5,
647*4882a593Smuzhiyun .ops = &pca9450_ldo_regulator_ops,
648*4882a593Smuzhiyun .type = REGULATOR_VOLTAGE,
649*4882a593Smuzhiyun .n_voltages = PCA9450_LDO5_VOLTAGE_NUM,
650*4882a593Smuzhiyun .linear_ranges = pca9450_ldo5_volts,
651*4882a593Smuzhiyun .n_linear_ranges = ARRAY_SIZE(pca9450_ldo5_volts),
652*4882a593Smuzhiyun .vsel_reg = PCA9450_REG_LDO5CTRL_H,
653*4882a593Smuzhiyun .vsel_mask = LDO5HOUT_MASK,
654*4882a593Smuzhiyun .enable_reg = PCA9450_REG_LDO5CTRL_H,
655*4882a593Smuzhiyun .enable_mask = LDO5H_EN_MASK,
656*4882a593Smuzhiyun .owner = THIS_MODULE,
657*4882a593Smuzhiyun },
658*4882a593Smuzhiyun },
659*4882a593Smuzhiyun };
660*4882a593Smuzhiyun
pca9450_irq_handler(int irq,void * data)661*4882a593Smuzhiyun static irqreturn_t pca9450_irq_handler(int irq, void *data)
662*4882a593Smuzhiyun {
663*4882a593Smuzhiyun struct pca9450 *pca9450 = data;
664*4882a593Smuzhiyun struct regmap *regmap = pca9450->regmap;
665*4882a593Smuzhiyun unsigned int status;
666*4882a593Smuzhiyun int ret;
667*4882a593Smuzhiyun
668*4882a593Smuzhiyun ret = regmap_read(regmap, PCA9450_REG_INT1, &status);
669*4882a593Smuzhiyun if (ret < 0) {
670*4882a593Smuzhiyun dev_err(pca9450->dev,
671*4882a593Smuzhiyun "Failed to read INT1(%d)\n", ret);
672*4882a593Smuzhiyun return IRQ_NONE;
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun if (status & IRQ_PWRON)
676*4882a593Smuzhiyun dev_warn(pca9450->dev, "PWRON interrupt.\n");
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun if (status & IRQ_WDOGB)
679*4882a593Smuzhiyun dev_warn(pca9450->dev, "WDOGB interrupt.\n");
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun if (status & IRQ_VR_FLT1)
682*4882a593Smuzhiyun dev_warn(pca9450->dev, "VRFLT1 interrupt.\n");
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun if (status & IRQ_VR_FLT2)
685*4882a593Smuzhiyun dev_warn(pca9450->dev, "VRFLT2 interrupt.\n");
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun if (status & IRQ_LOWVSYS)
688*4882a593Smuzhiyun dev_warn(pca9450->dev, "LOWVSYS interrupt.\n");
689*4882a593Smuzhiyun
690*4882a593Smuzhiyun if (status & IRQ_THERM_105)
691*4882a593Smuzhiyun dev_warn(pca9450->dev, "IRQ_THERM_105 interrupt.\n");
692*4882a593Smuzhiyun
693*4882a593Smuzhiyun if (status & IRQ_THERM_125)
694*4882a593Smuzhiyun dev_warn(pca9450->dev, "IRQ_THERM_125 interrupt.\n");
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun return IRQ_HANDLED;
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun
pca9450_i2c_probe(struct i2c_client * i2c,const struct i2c_device_id * id)699*4882a593Smuzhiyun static int pca9450_i2c_probe(struct i2c_client *i2c,
700*4882a593Smuzhiyun const struct i2c_device_id *id)
701*4882a593Smuzhiyun {
702*4882a593Smuzhiyun enum pca9450_chip_type type = (unsigned int)(uintptr_t)
703*4882a593Smuzhiyun of_device_get_match_data(&i2c->dev);
704*4882a593Smuzhiyun const struct pca9450_regulator_desc *regulator_desc;
705*4882a593Smuzhiyun struct regulator_config config = { };
706*4882a593Smuzhiyun struct pca9450 *pca9450;
707*4882a593Smuzhiyun unsigned int device_id, i;
708*4882a593Smuzhiyun int ret;
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun if (!i2c->irq) {
711*4882a593Smuzhiyun dev_err(&i2c->dev, "No IRQ configured?\n");
712*4882a593Smuzhiyun return -EINVAL;
713*4882a593Smuzhiyun }
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun pca9450 = devm_kzalloc(&i2c->dev, sizeof(struct pca9450), GFP_KERNEL);
716*4882a593Smuzhiyun if (!pca9450)
717*4882a593Smuzhiyun return -ENOMEM;
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun switch (type) {
720*4882a593Smuzhiyun case PCA9450_TYPE_PCA9450A:
721*4882a593Smuzhiyun regulator_desc = pca9450a_regulators;
722*4882a593Smuzhiyun pca9450->rcnt = ARRAY_SIZE(pca9450a_regulators);
723*4882a593Smuzhiyun break;
724*4882a593Smuzhiyun case PCA9450_TYPE_PCA9450BC:
725*4882a593Smuzhiyun regulator_desc = pca9450bc_regulators;
726*4882a593Smuzhiyun pca9450->rcnt = ARRAY_SIZE(pca9450bc_regulators);
727*4882a593Smuzhiyun break;
728*4882a593Smuzhiyun default:
729*4882a593Smuzhiyun dev_err(&i2c->dev, "Unknown device type");
730*4882a593Smuzhiyun return -EINVAL;
731*4882a593Smuzhiyun }
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun pca9450->irq = i2c->irq;
734*4882a593Smuzhiyun pca9450->type = type;
735*4882a593Smuzhiyun pca9450->dev = &i2c->dev;
736*4882a593Smuzhiyun
737*4882a593Smuzhiyun dev_set_drvdata(&i2c->dev, pca9450);
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun pca9450->regmap = devm_regmap_init_i2c(i2c,
740*4882a593Smuzhiyun &pca9450_regmap_config);
741*4882a593Smuzhiyun if (IS_ERR(pca9450->regmap)) {
742*4882a593Smuzhiyun dev_err(&i2c->dev, "regmap initialization failed\n");
743*4882a593Smuzhiyun return PTR_ERR(pca9450->regmap);
744*4882a593Smuzhiyun }
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun ret = regmap_read(pca9450->regmap, PCA9450_REG_DEV_ID, &device_id);
747*4882a593Smuzhiyun if (ret) {
748*4882a593Smuzhiyun dev_err(&i2c->dev, "Read device id error\n");
749*4882a593Smuzhiyun return ret;
750*4882a593Smuzhiyun }
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun /* Check your board and dts for match the right pmic */
753*4882a593Smuzhiyun if (((device_id >> 4) != 0x1 && type == PCA9450_TYPE_PCA9450A) ||
754*4882a593Smuzhiyun ((device_id >> 4) != 0x3 && type == PCA9450_TYPE_PCA9450BC)) {
755*4882a593Smuzhiyun dev_err(&i2c->dev, "Device id(%x) mismatched\n",
756*4882a593Smuzhiyun device_id >> 4);
757*4882a593Smuzhiyun return -EINVAL;
758*4882a593Smuzhiyun }
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun for (i = 0; i < pca9450->rcnt; i++) {
761*4882a593Smuzhiyun const struct regulator_desc *desc;
762*4882a593Smuzhiyun struct regulator_dev *rdev;
763*4882a593Smuzhiyun const struct pca9450_regulator_desc *r;
764*4882a593Smuzhiyun
765*4882a593Smuzhiyun r = ®ulator_desc[i];
766*4882a593Smuzhiyun desc = &r->desc;
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun config.regmap = pca9450->regmap;
769*4882a593Smuzhiyun config.dev = pca9450->dev;
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun rdev = devm_regulator_register(pca9450->dev, desc, &config);
772*4882a593Smuzhiyun if (IS_ERR(rdev)) {
773*4882a593Smuzhiyun ret = PTR_ERR(rdev);
774*4882a593Smuzhiyun dev_err(pca9450->dev,
775*4882a593Smuzhiyun "Failed to register regulator(%s): %d\n",
776*4882a593Smuzhiyun desc->name, ret);
777*4882a593Smuzhiyun return ret;
778*4882a593Smuzhiyun }
779*4882a593Smuzhiyun }
780*4882a593Smuzhiyun
781*4882a593Smuzhiyun ret = devm_request_threaded_irq(pca9450->dev, pca9450->irq, NULL,
782*4882a593Smuzhiyun pca9450_irq_handler,
783*4882a593Smuzhiyun (IRQF_TRIGGER_FALLING | IRQF_ONESHOT),
784*4882a593Smuzhiyun "pca9450-irq", pca9450);
785*4882a593Smuzhiyun if (ret != 0) {
786*4882a593Smuzhiyun dev_err(pca9450->dev, "Failed to request IRQ: %d\n",
787*4882a593Smuzhiyun pca9450->irq);
788*4882a593Smuzhiyun return ret;
789*4882a593Smuzhiyun }
790*4882a593Smuzhiyun /* Unmask all interrupt except PWRON/WDOG/RSVD */
791*4882a593Smuzhiyun ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_INT1_MSK,
792*4882a593Smuzhiyun IRQ_VR_FLT1 | IRQ_VR_FLT2 | IRQ_LOWVSYS |
793*4882a593Smuzhiyun IRQ_THERM_105 | IRQ_THERM_125,
794*4882a593Smuzhiyun IRQ_PWRON | IRQ_WDOGB | IRQ_RSVD);
795*4882a593Smuzhiyun if (ret) {
796*4882a593Smuzhiyun dev_err(&i2c->dev, "Unmask irq error\n");
797*4882a593Smuzhiyun return ret;
798*4882a593Smuzhiyun }
799*4882a593Smuzhiyun
800*4882a593Smuzhiyun /* Clear PRESET_EN bit in BUCK123_DVS to use DVS registers */
801*4882a593Smuzhiyun ret = regmap_clear_bits(pca9450->regmap, PCA9450_REG_BUCK123_DVS,
802*4882a593Smuzhiyun BUCK123_PRESET_EN);
803*4882a593Smuzhiyun if (ret) {
804*4882a593Smuzhiyun dev_err(&i2c->dev, "Failed to clear PRESET_EN bit: %d\n", ret);
805*4882a593Smuzhiyun return ret;
806*4882a593Smuzhiyun }
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun /* Set reset behavior on assertion of WDOG_B signal */
809*4882a593Smuzhiyun ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_RESET_CTRL,
810*4882a593Smuzhiyun WDOG_B_CFG_MASK, WDOG_B_CFG_COLD_LDO12);
811*4882a593Smuzhiyun if (ret) {
812*4882a593Smuzhiyun dev_err(&i2c->dev, "Failed to set WDOG_B reset behavior\n");
813*4882a593Smuzhiyun return ret;
814*4882a593Smuzhiyun }
815*4882a593Smuzhiyun
816*4882a593Smuzhiyun /*
817*4882a593Smuzhiyun * The driver uses the LDO5CTRL_H register to control the LDO5 regulator.
818*4882a593Smuzhiyun * This is only valid if the SD_VSEL input of the PMIC is high. Let's
819*4882a593Smuzhiyun * check if the pin is available as GPIO and set it to high.
820*4882a593Smuzhiyun */
821*4882a593Smuzhiyun pca9450->sd_vsel_gpio = gpiod_get_optional(pca9450->dev, "sd-vsel", GPIOD_OUT_HIGH);
822*4882a593Smuzhiyun
823*4882a593Smuzhiyun if (IS_ERR(pca9450->sd_vsel_gpio)) {
824*4882a593Smuzhiyun dev_err(&i2c->dev, "Failed to get SD_VSEL GPIO\n");
825*4882a593Smuzhiyun return ret;
826*4882a593Smuzhiyun }
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun dev_info(&i2c->dev, "%s probed.\n",
829*4882a593Smuzhiyun type == PCA9450_TYPE_PCA9450A ? "pca9450a" : "pca9450bc");
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun return 0;
832*4882a593Smuzhiyun }
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun static const struct of_device_id pca9450_of_match[] = {
835*4882a593Smuzhiyun {
836*4882a593Smuzhiyun .compatible = "nxp,pca9450a",
837*4882a593Smuzhiyun .data = (void *)PCA9450_TYPE_PCA9450A,
838*4882a593Smuzhiyun },
839*4882a593Smuzhiyun {
840*4882a593Smuzhiyun .compatible = "nxp,pca9450b",
841*4882a593Smuzhiyun .data = (void *)PCA9450_TYPE_PCA9450BC,
842*4882a593Smuzhiyun },
843*4882a593Smuzhiyun {
844*4882a593Smuzhiyun .compatible = "nxp,pca9450c",
845*4882a593Smuzhiyun .data = (void *)PCA9450_TYPE_PCA9450BC,
846*4882a593Smuzhiyun },
847*4882a593Smuzhiyun { }
848*4882a593Smuzhiyun };
849*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, pca9450_of_match);
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun static struct i2c_driver pca9450_i2c_driver = {
852*4882a593Smuzhiyun .driver = {
853*4882a593Smuzhiyun .name = "nxp-pca9450",
854*4882a593Smuzhiyun .of_match_table = pca9450_of_match,
855*4882a593Smuzhiyun },
856*4882a593Smuzhiyun .probe = pca9450_i2c_probe,
857*4882a593Smuzhiyun };
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun module_i2c_driver(pca9450_i2c_driver);
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun MODULE_AUTHOR("Robin Gong <yibin.gong@nxp.com>");
862*4882a593Smuzhiyun MODULE_DESCRIPTION("NXP PCA9450 Power Management IC driver");
863*4882a593Smuzhiyun MODULE_LICENSE("GPL");
864