1 // SPDX-License-Identifier: GPL-2.0+
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>
10 #include <linux/platform_device.h>
11 #include <linux/regmap.h>
12 #include <linux/regulator/driver.h>
13 #include <linux/regulator/machine.h>
16 MT6370_IDX_DSVBOOST
= 0,
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
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)
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
64 struct regmap
*regmap
;
65 struct regulator_dev
*rdev
[MT6370_MAX_IDX
];
66 bool use_external_ctrl
;
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 };
72 static int mt6370_get_error_flags(struct regulator_dev
*rdev
,
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
;
79 if (rid
== MT6370_IDX_VIBLDO
)
80 stat_reg
= MT6370_REG_LDO_STAT
;
82 stat_reg
= MT6370_REG_DB_STAT
;
84 ret
= regmap_read(regmap
, stat_reg
, &stat
);
89 case MT6370_IDX_DSVBOOST
:
90 if (stat
& MT6370_BSTOCP_EVT_MASK
)
91 rpt_flags
|= REGULATOR_ERROR_OVER_CURRENT
;
93 case MT6370_IDX_DSVPOS
:
94 if (stat
& MT6370_POSSCP_EVT_MASK
)
95 rpt_flags
|= REGULATOR_ERROR_UNDER_VOLTAGE
;
97 if (stat
& MT6370_POSOCP_EVT_MASK
)
98 rpt_flags
|= REGULATOR_ERROR_OVER_CURRENT
;
100 case MT6370_IDX_DSVNEG
:
101 if (stat
& MT6370_NEGSCP_EVT_MASK
)
102 rpt_flags
|= REGULATOR_ERROR_UNDER_VOLTAGE
;
104 if (stat
& MT6370_NEGOCP_EVT_MASK
)
105 rpt_flags
|= REGULATOR_ERROR_OVER_CURRENT
;
108 if (stat
& MT6370_LDOOC_EVT_MASK
)
109 rpt_flags
|= REGULATOR_ERROR_OVER_CURRENT
;
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
,
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
,
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
,
149 static int mt6370_of_parse_cb(struct device_node
*np
,
150 const struct regulator_desc
*desc
,
151 struct regulator_config
*config
)
153 struct mt6370_priv
*priv
= config
->driver_data
;
154 struct gpio_desc
*enable_gpio
;
157 enable_gpio
= fwnode_gpiod_get_index(of_fwnode_handle(np
), "enable", 0,
159 GPIOD_FLAGS_BIT_NONEXCLUSIVE
,
161 if (IS_ERR(enable_gpio
)) {
162 config
->ena_gpiod
= NULL
;
167 * RG control by default
168 * Only if all are using external pin, change all by external control
170 if (priv
->use_external_ctrl
) {
171 ret
= regmap_update_bits(priv
->regmap
, MT6370_REG_DB_CTRL1
,
173 MT6370_DBEXTEN_MASK
);
178 config
->ena_gpiod
= enable_gpio
;
179 priv
->use_external_ctrl
= true;
183 static const struct regulator_desc mt6370_regulator_descs
[] = {
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
,
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
,
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
,
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
,
270 static irqreturn_t
mt6370_scp_handler(int irq
, void *data
)
272 struct regulator_dev
*rdev
= data
;
274 regulator_notifier_call_chain(rdev
, REGULATOR_EVENT_UNDER_VOLTAGE
,
279 static irqreturn_t
mt6370_ocp_handler(int irq
, void *data
)
281 struct regulator_dev
*rdev
= data
;
283 regulator_notifier_call_chain(rdev
, REGULATOR_EVENT_OVER_CURRENT
, NULL
);
287 static int mt6370_regulator_irq_register(struct mt6370_priv
*priv
)
289 struct platform_device
*pdev
= to_platform_device(priv
->dev
);
290 static const struct {
293 irq_handler_t handler
;
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
}
302 struct regulator_dev
*rdev
;
305 for (i
= 0; i
< ARRAY_SIZE(mt6370_irqs
); i
++) {
306 irq
= platform_get_irq_byname(pdev
, mt6370_irqs
[i
].name
);
308 rdev
= priv
->rdev
[mt6370_irqs
[i
].rid
];
310 ret
= devm_request_threaded_irq(priv
->dev
, irq
, NULL
,
311 mt6370_irqs
[i
].handler
, 0,
312 mt6370_irqs
[i
].name
, rdev
);
315 "Failed to register (%d) interrupt\n", i
);
323 static int mt6370_regualtor_register(struct mt6370_priv
*priv
)
325 struct regulator_dev
*rdev
;
326 struct regulator_config cfg
= {};
327 struct device
*parent
= priv
->dev
->parent
;
331 cfg
.driver_data
= priv
;
333 for (i
= 0; i
< MT6370_MAX_IDX
; i
++) {
334 rdev
= devm_regulator_register(priv
->dev
,
335 mt6370_regulator_descs
+ i
,
339 "Failed to register (%d) regulator\n", i
);
340 return PTR_ERR(rdev
);
343 priv
->rdev
[i
] = rdev
;
349 static int mt6370_regulator_probe(struct platform_device
*pdev
)
351 struct mt6370_priv
*priv
;
354 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
358 priv
->dev
= &pdev
->dev
;
360 priv
->regmap
= dev_get_regmap(pdev
->dev
.parent
, NULL
);
362 dev_err(&pdev
->dev
, "Failed to init regmap\n");
366 ret
= mt6370_regualtor_register(priv
);
370 return mt6370_regulator_irq_register(priv
);
373 static const struct platform_device_id mt6370_devid_table
[] = {
374 { "mt6370-regulator", 0},
377 MODULE_DEVICE_TABLE(platform
, mt6370_devid_table
);
379 static struct platform_driver mt6370_regulator_driver
= {
381 .name
= "mt6370-regulator",
382 .probe_type
= PROBE_PREFER_ASYNCHRONOUS
,
384 .id_table
= mt6370_devid_table
,
385 .probe
= mt6370_regulator_probe
,
387 module_platform_driver(mt6370_regulator_driver
);
389 MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
390 MODULE_DESCRIPTION("Mediatek MT6370 Regulator Driver");
391 MODULE_LICENSE("GPL v2");