Merge tag 'pci-v6.4-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci
[linux.git] / drivers / regulator / mt6370-regulator.c
1 // SPDX-License-Identifier: GPL-2.0+
2
3 #include <linux/bits.h>
4 #include <linux/gpio/consumer.h>
5 #include <linux/interrupt.h>
6 #include <linux/kernel.h>
7 #include <linux/mod_devicetable.h>
8 #include <linux/module.h>
9 #include <linux/of.h>
10 #include <linux/platform_device.h>
11 #include <linux/regmap.h>
12 #include <linux/regulator/driver.h>
13 #include <linux/regulator/machine.h>
14
15 enum {
16         MT6370_IDX_DSVBOOST = 0,
17         MT6370_IDX_DSVPOS,
18         MT6370_IDX_DSVNEG,
19         MT6370_IDX_VIBLDO,
20         MT6370_MAX_IDX
21 };
22
23 #define MT6370_REG_LDO_CFG      0x180
24 #define MT6370_REG_LDO_VOUT     0x181
25 #define MT6370_REG_DB_CTRL1     0x1B0
26 #define MT6370_REG_DB_CTRL2     0x1B1
27 #define MT6370_REG_DB_VBST      0x1B2
28 #define MT6370_REG_DB_VPOS      0x1B3
29 #define MT6370_REG_DB_VNEG      0x1B4
30 #define MT6370_REG_LDO_STAT     0x1DC
31 #define MT6370_REG_DB_STAT      0x1DF
32
33 #define MT6370_LDOOMS_MASK      BIT(7)
34 #define MT6370_LDOEN_MASK       BIT(7)
35 #define MT6370_LDOVOUT_MASK     GENMASK(3, 0)
36 #define MT6370_DBPERD_MASK      (BIT(7) | BIT(4))
37 #define MT6370_DBEXTEN_MASK     BIT(0)
38 #define MT6370_DBVPOSEN_MASK    BIT(6)
39 #define MT6370_DBVPOSDISG_MASK  BIT(5)
40 #define MT6370_DBVNEGEN_MASK    BIT(3)
41 #define MT6370_DBVNEGDISG_MASK  BIT(2)
42 #define MT6370_DBALLON_MASK     (MT6370_DBVPOSEN_MASK | MT6370_DBVNEGEN_MASK)
43 #define MT6370_DBSLEW_MASK      GENMASK(7, 6)
44 #define MT6370_DBVOUT_MASK      GENMASK(5, 0)
45 #define MT6370_LDOOC_EVT_MASK   BIT(7)
46 #define MT6370_POSSCP_EVT_MASK  BIT(7)
47 #define MT6370_NEGSCP_EVT_MASK  BIT(6)
48 #define MT6370_BSTOCP_EVT_MASK  BIT(5)
49 #define MT6370_POSOCP_EVT_MASK  BIT(4)
50 #define MT6370_NEGOCP_EVT_MASK  BIT(3)
51
52 #define MT6370_LDO_MINUV        1600000
53 #define MT6370_LDO_STPUV        200000
54 #define MT6370_LDO_N_VOLT       13
55 #define MT6370_DBVBOOST_MINUV   4000000
56 #define MT6370_DBVBOOST_STPUV   50000
57 #define MT6370_DBVBOOST_N_VOLT  45
58 #define MT6370_DBVOUT_MINUV     4000000
59 #define MT6370_DBVOUT_STPUV     50000
60 #define MT6370_DBVOUT_N_VOLT    41
61
62 struct mt6370_priv {
63         struct device *dev;
64         struct regmap *regmap;
65         struct regulator_dev *rdev[MT6370_MAX_IDX];
66         bool use_external_ctrl;
67 };
68
69 static const unsigned int mt6370_vpos_ramp_tbl[] = { 8540, 5840, 4830, 3000 };
70 static const unsigned int mt6370_vneg_ramp_tbl[] = { 10090, 6310, 5050, 3150 };
71
72 static int mt6370_get_error_flags(struct regulator_dev *rdev,
73                                   unsigned int *flags)
74 {
75         struct regmap *regmap = rdev_get_regmap(rdev);
76         unsigned int stat_reg, stat, rpt_flags = 0;
77         int rid = rdev_get_id(rdev), ret;
78
79         if (rid == MT6370_IDX_VIBLDO)
80                 stat_reg = MT6370_REG_LDO_STAT;
81         else
82                 stat_reg = MT6370_REG_DB_STAT;
83
84         ret = regmap_read(regmap, stat_reg, &stat);
85         if (ret)
86                 return ret;
87
88         switch (rid) {
89         case MT6370_IDX_DSVBOOST:
90                 if (stat & MT6370_BSTOCP_EVT_MASK)
91                         rpt_flags |= REGULATOR_ERROR_OVER_CURRENT;
92                 break;
93         case MT6370_IDX_DSVPOS:
94                 if (stat & MT6370_POSSCP_EVT_MASK)
95                         rpt_flags |= REGULATOR_ERROR_UNDER_VOLTAGE;
96
97                 if (stat & MT6370_POSOCP_EVT_MASK)
98                         rpt_flags |= REGULATOR_ERROR_OVER_CURRENT;
99                 break;
100         case MT6370_IDX_DSVNEG:
101                 if (stat & MT6370_NEGSCP_EVT_MASK)
102                         rpt_flags |= REGULATOR_ERROR_UNDER_VOLTAGE;
103
104                 if (stat & MT6370_NEGOCP_EVT_MASK)
105                         rpt_flags |= REGULATOR_ERROR_OVER_CURRENT;
106                 break;
107         default:
108                 if (stat & MT6370_LDOOC_EVT_MASK)
109                         rpt_flags |= REGULATOR_ERROR_OVER_CURRENT;
110                 break;
111         }
112
113         *flags = rpt_flags;
114         return 0;
115 }
116
117 static const struct regulator_ops mt6370_dbvboost_ops = {
118         .get_voltage_sel = regulator_get_voltage_sel_regmap,
119         .set_voltage_sel = regulator_set_voltage_sel_regmap,
120         .list_voltage = regulator_list_voltage_linear,
121         .get_bypass = regulator_get_bypass_regmap,
122         .set_bypass = regulator_set_bypass_regmap,
123         .get_error_flags = mt6370_get_error_flags,
124 };
125
126 static const struct regulator_ops mt6370_dbvout_ops = {
127         .get_voltage_sel = regulator_get_voltage_sel_regmap,
128         .set_voltage_sel = regulator_set_voltage_sel_regmap,
129         .list_voltage = regulator_list_voltage_linear,
130         .is_enabled = regulator_is_enabled_regmap,
131         .enable = regulator_enable_regmap,
132         .disable = regulator_disable_regmap,
133         .set_active_discharge = regulator_set_active_discharge_regmap,
134         .set_ramp_delay = regulator_set_ramp_delay_regmap,
135         .get_error_flags = mt6370_get_error_flags,
136 };
137
138 static const struct regulator_ops mt6370_ldo_ops = {
139         .get_voltage_sel = regulator_get_voltage_sel_regmap,
140         .set_voltage_sel = regulator_set_voltage_sel_regmap,
141         .list_voltage = regulator_list_voltage_linear,
142         .is_enabled = regulator_is_enabled_regmap,
143         .enable = regulator_enable_regmap,
144         .disable = regulator_disable_regmap,
145         .set_active_discharge = regulator_set_active_discharge_regmap,
146         .get_error_flags = mt6370_get_error_flags,
147 };
148
149 static int mt6370_of_parse_cb(struct device_node *np,
150                               const struct regulator_desc *desc,
151                               struct regulator_config *config)
152 {
153         struct mt6370_priv *priv = config->driver_data;
154         struct gpio_desc *enable_gpio;
155         int ret;
156
157         enable_gpio = fwnode_gpiod_get_index(of_fwnode_handle(np), "enable", 0,
158                                              GPIOD_OUT_HIGH |
159                                              GPIOD_FLAGS_BIT_NONEXCLUSIVE,
160                                              desc->name);
161         if (IS_ERR(enable_gpio)) {
162                 config->ena_gpiod = NULL;
163                 return 0;
164         }
165
166         /*
167          * RG control by default
168          * Only if all are using external pin, change all by external control
169          */
170         if (priv->use_external_ctrl) {
171                 ret = regmap_update_bits(priv->regmap, MT6370_REG_DB_CTRL1,
172                                          MT6370_DBEXTEN_MASK,
173                                          MT6370_DBEXTEN_MASK);
174                 if (ret)
175                         return ret;
176         }
177
178         config->ena_gpiod = enable_gpio;
179         priv->use_external_ctrl = true;
180         return 0;
181 }
182
183 static const struct regulator_desc mt6370_regulator_descs[] = {
184         {
185                 .name = "mt6370-dsv-vbst",
186                 .of_match = of_match_ptr("dsvbst"),
187                 .regulators_node = of_match_ptr("regulators"),
188                 .id = MT6370_IDX_DSVBOOST,
189                 .type = REGULATOR_VOLTAGE,
190                 .owner = THIS_MODULE,
191                 .ops = &mt6370_dbvboost_ops,
192                 .min_uV = MT6370_DBVBOOST_MINUV,
193                 .uV_step = MT6370_DBVBOOST_STPUV,
194                 .n_voltages = MT6370_DBVBOOST_N_VOLT,
195                 .vsel_reg = MT6370_REG_DB_VBST,
196                 .vsel_mask = MT6370_DBVOUT_MASK,
197                 .bypass_reg = MT6370_REG_DB_CTRL1,
198                 .bypass_mask = MT6370_DBPERD_MASK,
199                 .bypass_val_on = MT6370_DBPERD_MASK,
200         },
201         {
202                 .name = "mt6370-dsv-vpos",
203                 .of_match = of_match_ptr("dsvpos"),
204                 .regulators_node = of_match_ptr("regulators"),
205                 .id = MT6370_IDX_DSVPOS,
206                 .type = REGULATOR_VOLTAGE,
207                 .owner = THIS_MODULE,
208                 .of_parse_cb = mt6370_of_parse_cb,
209                 .ops = &mt6370_dbvout_ops,
210                 .min_uV = MT6370_DBVOUT_MINUV,
211                 .uV_step = MT6370_DBVOUT_STPUV,
212                 .n_voltages = MT6370_DBVOUT_N_VOLT,
213                 .vsel_reg = MT6370_REG_DB_VPOS,
214                 .vsel_mask = MT6370_DBVOUT_MASK,
215                 .enable_reg = MT6370_REG_DB_CTRL2,
216                 .enable_mask = MT6370_DBVPOSEN_MASK,
217                 .ramp_reg = MT6370_REG_DB_VPOS,
218                 .ramp_mask = MT6370_DBSLEW_MASK,
219                 .ramp_delay_table = mt6370_vpos_ramp_tbl,
220                 .n_ramp_values = ARRAY_SIZE(mt6370_vpos_ramp_tbl),
221                 .active_discharge_reg = MT6370_REG_DB_CTRL2,
222                 .active_discharge_mask = MT6370_DBVPOSDISG_MASK,
223                 .active_discharge_on = MT6370_DBVPOSDISG_MASK,
224         },
225         {
226                 .name = "mt6370-dsv-vneg",
227                 .of_match = of_match_ptr("dsvneg"),
228                 .regulators_node = of_match_ptr("regulators"),
229                 .id = MT6370_IDX_DSVNEG,
230                 .type = REGULATOR_VOLTAGE,
231                 .owner = THIS_MODULE,
232                 .of_parse_cb = mt6370_of_parse_cb,
233                 .ops = &mt6370_dbvout_ops,
234                 .min_uV = MT6370_DBVOUT_MINUV,
235                 .uV_step = MT6370_DBVOUT_STPUV,
236                 .n_voltages = MT6370_DBVOUT_N_VOLT,
237                 .vsel_reg = MT6370_REG_DB_VNEG,
238                 .vsel_mask = MT6370_DBVOUT_MASK,
239                 .enable_reg = MT6370_REG_DB_CTRL2,
240                 .enable_mask = MT6370_DBVNEGEN_MASK,
241                 .ramp_reg = MT6370_REG_DB_VNEG,
242                 .ramp_mask = MT6370_DBSLEW_MASK,
243                 .ramp_delay_table = mt6370_vneg_ramp_tbl,
244                 .n_ramp_values = ARRAY_SIZE(mt6370_vneg_ramp_tbl),
245                 .active_discharge_reg = MT6370_REG_DB_CTRL2,
246                 .active_discharge_mask = MT6370_DBVNEGDISG_MASK,
247                 .active_discharge_on = MT6370_DBVNEGDISG_MASK,
248         },
249         {
250                 .name = "mt6370-vib-ldo",
251                 .of_match = of_match_ptr("vibldo"),
252                 .regulators_node = of_match_ptr("regulators"),
253                 .id = MT6370_IDX_VIBLDO,
254                 .type = REGULATOR_VOLTAGE,
255                 .owner = THIS_MODULE,
256                 .ops = &mt6370_ldo_ops,
257                 .min_uV = MT6370_LDO_MINUV,
258                 .uV_step = MT6370_LDO_STPUV,
259                 .n_voltages = MT6370_LDO_N_VOLT,
260                 .vsel_reg = MT6370_REG_LDO_VOUT,
261                 .vsel_mask = MT6370_LDOVOUT_MASK,
262                 .enable_reg = MT6370_REG_LDO_VOUT,
263                 .enable_mask = MT6370_LDOEN_MASK,
264                 .active_discharge_reg = MT6370_REG_LDO_CFG,
265                 .active_discharge_mask = MT6370_LDOOMS_MASK,
266                 .active_discharge_on = MT6370_LDOOMS_MASK,
267         }
268 };
269
270 static irqreturn_t mt6370_scp_handler(int irq, void *data)
271 {
272         struct regulator_dev *rdev = data;
273
274         regulator_notifier_call_chain(rdev, REGULATOR_EVENT_UNDER_VOLTAGE,
275                                       NULL);
276         return IRQ_HANDLED;
277 }
278
279 static irqreturn_t mt6370_ocp_handler(int irq, void *data)
280 {
281         struct regulator_dev *rdev = data;
282
283         regulator_notifier_call_chain(rdev, REGULATOR_EVENT_OVER_CURRENT, NULL);
284         return IRQ_HANDLED;
285 }
286
287 static int mt6370_regulator_irq_register(struct mt6370_priv *priv)
288 {
289         struct platform_device *pdev = to_platform_device(priv->dev);
290         static const struct {
291                 const char *name;
292                 int rid;
293                 irq_handler_t handler;
294         } mt6370_irqs[] = {
295                 { "db_vpos_scp", MT6370_IDX_DSVPOS, mt6370_scp_handler },
296                 { "db_vneg_scp", MT6370_IDX_DSVNEG, mt6370_scp_handler },
297                 { "db_vbst_ocp", MT6370_IDX_DSVBOOST, mt6370_ocp_handler },
298                 { "db_vpos_ocp", MT6370_IDX_DSVPOS,  mt6370_ocp_handler },
299                 { "db_vneg_ocp", MT6370_IDX_DSVNEG, mt6370_ocp_handler },
300                 { "ldo_oc", MT6370_IDX_VIBLDO, mt6370_ocp_handler }
301         };
302         struct regulator_dev *rdev;
303         int i, irq, ret;
304
305         for (i = 0; i < ARRAY_SIZE(mt6370_irqs); i++) {
306                 irq = platform_get_irq_byname(pdev, mt6370_irqs[i].name);
307
308                 rdev = priv->rdev[mt6370_irqs[i].rid];
309
310                 ret = devm_request_threaded_irq(priv->dev, irq, NULL,
311                                                 mt6370_irqs[i].handler, 0,
312                                                 mt6370_irqs[i].name, rdev);
313                 if (ret) {
314                         dev_err(priv->dev,
315                                 "Failed to register (%d) interrupt\n", i);
316                         return ret;
317                 }
318         }
319
320         return 0;
321 }
322
323 static int mt6370_regualtor_register(struct mt6370_priv *priv)
324 {
325         struct regulator_dev *rdev;
326         struct regulator_config cfg = {};
327         struct device *parent = priv->dev->parent;
328         int i;
329
330         cfg.dev = parent;
331         cfg.driver_data = priv;
332
333         for (i = 0; i < MT6370_MAX_IDX; i++) {
334                 rdev = devm_regulator_register(priv->dev,
335                                                mt6370_regulator_descs + i,
336                                                &cfg);
337                 if (IS_ERR(rdev)) {
338                         dev_err(priv->dev,
339                                 "Failed to register (%d) regulator\n", i);
340                         return PTR_ERR(rdev);
341                 }
342
343                 priv->rdev[i] = rdev;
344         }
345
346         return 0;
347 }
348
349 static int mt6370_regulator_probe(struct platform_device *pdev)
350 {
351         struct mt6370_priv *priv;
352         int ret;
353
354         priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
355         if (!priv)
356                 return -ENOMEM;
357
358         priv->dev = &pdev->dev;
359
360         priv->regmap = dev_get_regmap(pdev->dev.parent, NULL);
361         if (!priv->regmap) {
362                 dev_err(&pdev->dev, "Failed to init regmap\n");
363                 return -ENODEV;
364         }
365
366         ret = mt6370_regualtor_register(priv);
367         if (ret)
368                 return ret;
369
370         return mt6370_regulator_irq_register(priv);
371 }
372
373 static const struct platform_device_id mt6370_devid_table[] = {
374         { "mt6370-regulator", 0},
375         {}
376 };
377 MODULE_DEVICE_TABLE(platform, mt6370_devid_table);
378
379 static struct platform_driver mt6370_regulator_driver = {
380         .driver = {
381                 .name = "mt6370-regulator",
382                 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
383         },
384         .id_table = mt6370_devid_table,
385         .probe = mt6370_regulator_probe,
386 };
387 module_platform_driver(mt6370_regulator_driver);
388
389 MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
390 MODULE_DESCRIPTION("Mediatek MT6370 Regulator Driver");
391 MODULE_LICENSE("GPL v2");