1 // SPDX-License-Identifier: GPL-2.0
3 * ROHM BD9571MWV-M regulator driver
5 * Copyright (C) 2017 Marek Vasut <marek.vasut+renesas@gmail.com>
7 * Based on the TPS65086 driver
9 * NOTE: VD09 is missing
12 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 #include <linux/regulator/driver.h>
17 #include <linux/mfd/bd9571mwv.h>
19 struct bd9571mwv_reg
{
22 /* DDR Backup Power */
23 u8 bkup_mode_cnt_keepon
; /* from "rohm,ddr-backup-power" */
24 u8 bkup_mode_cnt_saved
;
25 bool bkup_mode_enabled
;
27 /* Power switch type */
32 enum bd9571mwv_regulators
{ VD09
, VD18
, VD25
, VD33
, DVFS
};
34 #define BD9571MWV_REG(_name, _of, _id, _ops, _vr, _vm, _nv, _min, _step, _lmin)\
37 .of_match = of_match_ptr(_of), \
38 .regulators_node = "regulators", \
42 .type = REGULATOR_VOLTAGE, \
43 .owner = THIS_MODULE, \
48 .linear_min_sel = _lmin, \
51 static int bd9571mwv_avs_get_moni_state(struct regulator_dev
*rdev
)
56 ret
= regmap_read(rdev
->regmap
, BD9571MWV_AVS_SET_MONI
, &val
);
60 return val
& BD9571MWV_AVS_SET_MONI_MASK
;
63 static int bd9571mwv_avs_set_voltage_sel_regmap(struct regulator_dev
*rdev
,
68 ret
= bd9571mwv_avs_get_moni_state(rdev
);
72 return regmap_write_bits(rdev
->regmap
, BD9571MWV_AVS_VD09_VID(ret
),
73 rdev
->desc
->vsel_mask
, sel
);
76 static int bd9571mwv_avs_get_voltage_sel_regmap(struct regulator_dev
*rdev
)
81 ret
= bd9571mwv_avs_get_moni_state(rdev
);
85 ret
= regmap_read(rdev
->regmap
, BD9571MWV_AVS_VD09_VID(ret
), &val
);
89 val
&= rdev
->desc
->vsel_mask
;
90 val
>>= ffs(rdev
->desc
->vsel_mask
) - 1;
95 static int bd9571mwv_reg_set_voltage_sel_regmap(struct regulator_dev
*rdev
,
98 return regmap_write_bits(rdev
->regmap
, BD9571MWV_DVFS_SETVID
,
99 rdev
->desc
->vsel_mask
, sel
);
102 /* Operations permitted on AVS voltage regulator */
103 static const struct regulator_ops avs_ops
= {
104 .set_voltage_sel
= bd9571mwv_avs_set_voltage_sel_regmap
,
105 .map_voltage
= regulator_map_voltage_linear
,
106 .get_voltage_sel
= bd9571mwv_avs_get_voltage_sel_regmap
,
107 .list_voltage
= regulator_list_voltage_linear
,
110 /* Operations permitted on voltage regulators */
111 static const struct regulator_ops reg_ops
= {
112 .set_voltage_sel
= bd9571mwv_reg_set_voltage_sel_regmap
,
113 .map_voltage
= regulator_map_voltage_linear
,
114 .get_voltage_sel
= regulator_get_voltage_sel_regmap
,
115 .list_voltage
= regulator_list_voltage_linear
,
118 /* Operations permitted on voltage monitors */
119 static const struct regulator_ops vid_ops
= {
120 .map_voltage
= regulator_map_voltage_linear
,
121 .get_voltage_sel
= regulator_get_voltage_sel_regmap
,
122 .list_voltage
= regulator_list_voltage_linear
,
125 static const struct regulator_desc regulators
[] = {
126 BD9571MWV_REG("VD09", "vd09", VD09
, avs_ops
, 0, 0x7f,
127 0x80, 600000, 10000, 0x3c),
128 BD9571MWV_REG("VD18", "vd18", VD18
, vid_ops
, BD9571MWV_VD18_VID
, 0xf,
129 16, 1625000, 25000, 0),
130 BD9571MWV_REG("VD25", "vd25", VD25
, vid_ops
, BD9571MWV_VD25_VID
, 0xf,
131 16, 2150000, 50000, 0),
132 BD9571MWV_REG("VD33", "vd33", VD33
, vid_ops
, BD9571MWV_VD33_VID
, 0xf,
133 11, 2800000, 100000, 0),
134 BD9571MWV_REG("DVFS", "dvfs", DVFS
, reg_ops
,
135 BD9571MWV_DVFS_MONIVDAC
, 0x7f,
136 0x80, 600000, 10000, 0x3c),
139 #ifdef CONFIG_PM_SLEEP
140 static int bd9571mwv_bkup_mode_read(struct bd9571mwv
*bd
, unsigned int *mode
)
144 ret
= regmap_read(bd
->regmap
, BD9571MWV_BKUP_MODE_CNT
, mode
);
146 dev_err(bd
->dev
, "failed to read backup mode (%d)\n", ret
);
153 static int bd9571mwv_bkup_mode_write(struct bd9571mwv
*bd
, unsigned int mode
)
157 ret
= regmap_write(bd
->regmap
, BD9571MWV_BKUP_MODE_CNT
, mode
);
159 dev_err(bd
->dev
, "failed to configure backup mode 0x%x (%d)\n",
167 static ssize_t
backup_mode_show(struct device
*dev
,
168 struct device_attribute
*attr
, char *buf
)
170 struct bd9571mwv_reg
*bdreg
= dev_get_drvdata(dev
);
172 return sprintf(buf
, "%s\n", bdreg
->bkup_mode_enabled
? "on" : "off");
175 static ssize_t
backup_mode_store(struct device
*dev
,
176 struct device_attribute
*attr
,
177 const char *buf
, size_t count
)
179 struct bd9571mwv_reg
*bdreg
= dev_get_drvdata(dev
);
186 ret
= kstrtobool(buf
, &bdreg
->bkup_mode_enabled
);
190 if (!bdreg
->rstbmode_level
)
194 * Configure DDR Backup Mode, to change the role of the accessory power
195 * switch from a power switch to a wake-up switch, or vice versa
197 ret
= bd9571mwv_bkup_mode_read(bdreg
->bd
, &mode
);
201 mode
&= ~BD9571MWV_BKUP_MODE_CNT_KEEPON_MASK
;
202 if (bdreg
->bkup_mode_enabled
)
203 mode
|= bdreg
->bkup_mode_cnt_keepon
;
205 ret
= bd9571mwv_bkup_mode_write(bdreg
->bd
, mode
);
212 static DEVICE_ATTR_RW(backup_mode
);
214 static int bd9571mwv_suspend(struct device
*dev
)
216 struct bd9571mwv_reg
*bdreg
= dev_get_drvdata(dev
);
220 if (!bdreg
->bkup_mode_enabled
)
223 /* Save DDR Backup Mode */
224 ret
= bd9571mwv_bkup_mode_read(bdreg
->bd
, &mode
);
228 bdreg
->bkup_mode_cnt_saved
= mode
;
230 if (!bdreg
->rstbmode_pulse
)
233 /* Enable DDR Backup Mode */
234 mode
&= ~BD9571MWV_BKUP_MODE_CNT_KEEPON_MASK
;
235 mode
|= bdreg
->bkup_mode_cnt_keepon
;
237 if (mode
!= bdreg
->bkup_mode_cnt_saved
)
238 return bd9571mwv_bkup_mode_write(bdreg
->bd
, mode
);
243 static int bd9571mwv_resume(struct device
*dev
)
245 struct bd9571mwv_reg
*bdreg
= dev_get_drvdata(dev
);
247 if (!bdreg
->bkup_mode_enabled
)
250 /* Restore DDR Backup Mode */
251 return bd9571mwv_bkup_mode_write(bdreg
->bd
, bdreg
->bkup_mode_cnt_saved
);
254 static const struct dev_pm_ops bd9571mwv_pm
= {
255 SET_SYSTEM_SLEEP_PM_OPS(bd9571mwv_suspend
, bd9571mwv_resume
)
258 static int bd9571mwv_regulator_remove(struct platform_device
*pdev
)
260 device_remove_file(&pdev
->dev
, &dev_attr_backup_mode
);
263 #define DEV_PM_OPS &bd9571mwv_pm
265 #define DEV_PM_OPS NULL
266 #define bd9571mwv_regulator_remove NULL
267 #endif /* CONFIG_PM_SLEEP */
269 static int bd9571mwv_regulator_probe(struct platform_device
*pdev
)
271 struct bd9571mwv
*bd
= dev_get_drvdata(pdev
->dev
.parent
);
272 struct regulator_config config
= { };
273 struct bd9571mwv_reg
*bdreg
;
274 struct regulator_dev
*rdev
;
278 bdreg
= devm_kzalloc(&pdev
->dev
, sizeof(*bdreg
), GFP_KERNEL
);
284 platform_set_drvdata(pdev
, bdreg
);
286 config
.dev
= &pdev
->dev
;
287 config
.dev
->of_node
= bd
->dev
->of_node
;
288 config
.driver_data
= bd
;
289 config
.regmap
= bd
->regmap
;
291 for (i
= 0; i
< ARRAY_SIZE(regulators
); i
++) {
292 rdev
= devm_regulator_register(&pdev
->dev
, ®ulators
[i
],
295 dev_err(bd
->dev
, "failed to register %s regulator\n",
297 return PTR_ERR(rdev
);
302 of_property_read_u32(bd
->dev
->of_node
, "rohm,ddr-backup-power", &val
);
303 if (val
& ~BD9571MWV_BKUP_MODE_CNT_KEEPON_MASK
) {
304 dev_err(bd
->dev
, "invalid %s mode %u\n",
305 "rohm,ddr-backup-power", val
);
308 bdreg
->bkup_mode_cnt_keepon
= val
;
310 bdreg
->rstbmode_level
= of_property_read_bool(bd
->dev
->of_node
,
311 "rohm,rstbmode-level");
312 bdreg
->rstbmode_pulse
= of_property_read_bool(bd
->dev
->of_node
,
313 "rohm,rstbmode-pulse");
314 if (bdreg
->rstbmode_level
&& bdreg
->rstbmode_pulse
) {
315 dev_err(bd
->dev
, "only one rohm,rstbmode-* may be specified");
319 #ifdef CONFIG_PM_SLEEP
320 if (bdreg
->bkup_mode_cnt_keepon
) {
324 * Backup mode is enabled by default in pulse mode, but needs
325 * explicit user setup in level mode.
327 bdreg
->bkup_mode_enabled
= bdreg
->rstbmode_pulse
;
329 ret
= device_create_file(&pdev
->dev
, &dev_attr_backup_mode
);
333 #endif /* CONFIG_PM_SLEEP */
338 static const struct platform_device_id bd9571mwv_regulator_id_table
[] = {
339 { "bd9571mwv-regulator", },
342 MODULE_DEVICE_TABLE(platform
, bd9571mwv_regulator_id_table
);
344 static struct platform_driver bd9571mwv_regulator_driver
= {
346 .name
= "bd9571mwv-regulator",
349 .probe
= bd9571mwv_regulator_probe
,
350 .remove
= bd9571mwv_regulator_remove
,
351 .id_table
= bd9571mwv_regulator_id_table
,
353 module_platform_driver(bd9571mwv_regulator_driver
);
355 MODULE_AUTHOR("Marek Vasut <marek.vasut+renesas@gmail.com>");
356 MODULE_DESCRIPTION("BD9571MWV Regulator driver");
357 MODULE_LICENSE("GPL v2");