diff options
author | Marek Vasut <marek.vasut@gmail.com> | 2017-04-24 11:21:30 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2017-04-25 11:38:21 -0400 |
commit | e85c5a153fe237f261838fc9638c28f19e0f27c1 (patch) | |
tree | 0b8293762c3b43c8fdb017ee02eaa7c257bd36ec | |
parent | c1ae3cfa0e89fa1a7ecc4c99031f5e9ae99d9201 (diff) |
regulator: Add ROHM BD9571MWV-M PMIC regulator driver
Add driver for the regulator block in the ROHM BD9571MWV-W MFD PMIC.
This block supports three voltage monitors, VD18, VD25, VD33 for the
1V8, 2V5, 3V3 voltage rails and a single voltage regulator for the
DVFS rail.
Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | drivers/regulator/Kconfig | 11 | ||||
-rw-r--r-- | drivers/regulator/Makefile | 1 | ||||
-rw-r--r-- | drivers/regulator/bd9571mwv-regulator.c | 178 |
3 files changed, 190 insertions, 0 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index be06eb29c681..a27b97c5695b 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
@@ -163,6 +163,17 @@ config REGULATOR_BCM590XX | |||
163 | BCM590xx PMUs. This will enable support for the software | 163 | BCM590xx PMUs. This will enable support for the software |
164 | controllable LDO/Switching regulators. | 164 | controllable LDO/Switching regulators. |
165 | 165 | ||
166 | config REGULATOR_BD9571MWV | ||
167 | tristate "ROHM BD9571MWV Regulators" | ||
168 | depends on MFD_BD9571MWV | ||
169 | help | ||
170 | This driver provides support for the voltage regulators on the | ||
171 | ROHM BD9571MWV PMIC. This will enable support for the software | ||
172 | controllable regulator and voltage sampling units. | ||
173 | |||
174 | This driver can also be built as a module. If so, the module | ||
175 | will be called bd9571mwv-regulator. | ||
176 | |||
166 | config REGULATOR_CPCAP | 177 | config REGULATOR_CPCAP |
167 | tristate "Motorola CPCAP regulator" | 178 | tristate "Motorola CPCAP regulator" |
168 | depends on MFD_CPCAP | 179 | depends on MFD_CPCAP |
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index ef7725e2592a..439b9b21f2fe 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
@@ -24,6 +24,7 @@ obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o | |||
24 | obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o | 24 | obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o |
25 | obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o | 25 | obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o |
26 | obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o | 26 | obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o |
27 | obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o | ||
27 | obj-$(CONFIG_REGULATOR_DA903X) += da903x.o | 28 | obj-$(CONFIG_REGULATOR_DA903X) += da903x.o |
28 | obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o | 29 | obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o |
29 | obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o | 30 | obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o |
diff --git a/drivers/regulator/bd9571mwv-regulator.c b/drivers/regulator/bd9571mwv-regulator.c new file mode 100644 index 000000000000..8ba206fec31e --- /dev/null +++ b/drivers/regulator/bd9571mwv-regulator.c | |||
@@ -0,0 +1,178 @@ | |||
1 | /* | ||
2 | * ROHM BD9571MWV-M regulator driver | ||
3 | * | ||
4 | * Copyright (C) 2017 Marek Vasut <marek.vasut+renesas@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
11 | * kind, whether expressed or implied; without even the implied warranty | ||
12 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License version 2 for more details. | ||
14 | * | ||
15 | * Based on the TPS65086 driver | ||
16 | * | ||
17 | * NOTE: VD09 is missing | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/of.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/regulator/driver.h> | ||
24 | |||
25 | #include <linux/mfd/bd9571mwv.h> | ||
26 | |||
27 | enum bd9571mwv_regulators { VD09, VD18, VD25, VD33, DVFS }; | ||
28 | |||
29 | #define BD9571MWV_REG(_name, _of, _id, _ops, _vr, _vm, _nv, _min, _step, _lmin)\ | ||
30 | { \ | ||
31 | .name = _name, \ | ||
32 | .of_match = of_match_ptr(_of), \ | ||
33 | .regulators_node = "regulators", \ | ||
34 | .id = _id, \ | ||
35 | .ops = &_ops, \ | ||
36 | .n_voltages = _nv, \ | ||
37 | .type = REGULATOR_VOLTAGE, \ | ||
38 | .owner = THIS_MODULE, \ | ||
39 | .vsel_reg = _vr, \ | ||
40 | .vsel_mask = _vm, \ | ||
41 | .min_uV = _min, \ | ||
42 | .uV_step = _step, \ | ||
43 | .linear_min_sel = _lmin, \ | ||
44 | } | ||
45 | |||
46 | int bd9571mwv_avs_get_moni_state(struct regulator_dev *rdev) | ||
47 | { | ||
48 | unsigned int val; | ||
49 | int ret; | ||
50 | |||
51 | ret = regmap_read(rdev->regmap, BD9571MWV_AVS_SET_MONI, &val); | ||
52 | if (ret != 0) | ||
53 | return ret; | ||
54 | |||
55 | return val & BD9571MWV_AVS_SET_MONI_MASK; | ||
56 | } | ||
57 | |||
58 | int bd9571mwv_avs_set_voltage_sel_regmap(struct regulator_dev *rdev, | ||
59 | unsigned int sel) | ||
60 | { | ||
61 | int ret; | ||
62 | |||
63 | ret = bd9571mwv_avs_get_moni_state(rdev); | ||
64 | if (ret < 0) | ||
65 | return ret; | ||
66 | |||
67 | return regmap_write_bits(rdev->regmap, BD9571MWV_AVS_VD09_VID(ret), | ||
68 | rdev->desc->vsel_mask, sel); | ||
69 | } | ||
70 | |||
71 | int bd9571mwv_avs_get_voltage_sel_regmap(struct regulator_dev *rdev) | ||
72 | { | ||
73 | unsigned int val; | ||
74 | int ret; | ||
75 | |||
76 | ret = bd9571mwv_avs_get_moni_state(rdev); | ||
77 | if (ret < 0) | ||
78 | return ret; | ||
79 | |||
80 | ret = regmap_read(rdev->regmap, BD9571MWV_AVS_VD09_VID(ret), &val); | ||
81 | if (ret != 0) | ||
82 | return ret; | ||
83 | |||
84 | val &= rdev->desc->vsel_mask; | ||
85 | val >>= ffs(rdev->desc->vsel_mask) - 1; | ||
86 | |||
87 | return val; | ||
88 | } | ||
89 | |||
90 | int bd9571mwv_reg_set_voltage_sel_regmap(struct regulator_dev *rdev, | ||
91 | unsigned int sel) | ||
92 | { | ||
93 | return regmap_write_bits(rdev->regmap, BD9571MWV_DVFS_SETVID, | ||
94 | rdev->desc->vsel_mask, sel); | ||
95 | } | ||
96 | |||
97 | /* Operations permitted on AVS voltage regulator */ | ||
98 | static struct regulator_ops avs_ops = { | ||
99 | .set_voltage_sel = bd9571mwv_avs_set_voltage_sel_regmap, | ||
100 | .map_voltage = regulator_map_voltage_linear, | ||
101 | .get_voltage_sel = bd9571mwv_avs_get_voltage_sel_regmap, | ||
102 | .list_voltage = regulator_list_voltage_linear, | ||
103 | }; | ||
104 | |||
105 | /* Operations permitted on voltage regulators */ | ||
106 | static struct regulator_ops reg_ops = { | ||
107 | .set_voltage_sel = bd9571mwv_reg_set_voltage_sel_regmap, | ||
108 | .map_voltage = regulator_map_voltage_linear, | ||
109 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
110 | .list_voltage = regulator_list_voltage_linear, | ||
111 | }; | ||
112 | |||
113 | /* Operations permitted on voltage monitors */ | ||
114 | static struct regulator_ops vid_ops = { | ||
115 | .map_voltage = regulator_map_voltage_linear, | ||
116 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
117 | .list_voltage = regulator_list_voltage_linear, | ||
118 | }; | ||
119 | |||
120 | static struct regulator_desc regulators[] = { | ||
121 | BD9571MWV_REG("VD09", "vd09", VD09, avs_ops, 0, 0x7f, | ||
122 | 0x80, 600000, 10000, 0x3c), | ||
123 | BD9571MWV_REG("VD18", "vd18", VD18, vid_ops, BD9571MWV_VD18_VID, 0xf, | ||
124 | 16, 1625000, 25000, 0), | ||
125 | BD9571MWV_REG("VD25", "vd25", VD25, vid_ops, BD9571MWV_VD25_VID, 0xf, | ||
126 | 16, 2150000, 50000, 0), | ||
127 | BD9571MWV_REG("VD33", "vd33", VD33, vid_ops, BD9571MWV_VD33_VID, 0xf, | ||
128 | 11, 2800000, 100000, 0), | ||
129 | BD9571MWV_REG("DVFS", "dvfs", DVFS, reg_ops, | ||
130 | BD9571MWV_DVFS_MONIVDAC, 0x7f, | ||
131 | 0x80, 600000, 10000, 0x3c), | ||
132 | }; | ||
133 | |||
134 | static int bd9571mwv_regulator_probe(struct platform_device *pdev) | ||
135 | { | ||
136 | struct bd9571mwv *bd = dev_get_drvdata(pdev->dev.parent); | ||
137 | struct regulator_config config = { }; | ||
138 | struct regulator_dev *rdev; | ||
139 | int i; | ||
140 | |||
141 | platform_set_drvdata(pdev, bd); | ||
142 | |||
143 | config.dev = &pdev->dev; | ||
144 | config.dev->of_node = bd->dev->of_node; | ||
145 | config.driver_data = bd; | ||
146 | config.regmap = bd->regmap; | ||
147 | |||
148 | for (i = 0; i < ARRAY_SIZE(regulators); i++) { | ||
149 | rdev = devm_regulator_register(&pdev->dev, ®ulators[i], | ||
150 | &config); | ||
151 | if (IS_ERR(rdev)) { | ||
152 | dev_err(bd->dev, "failed to register %s regulator\n", | ||
153 | pdev->name); | ||
154 | return PTR_ERR(rdev); | ||
155 | } | ||
156 | } | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static const struct platform_device_id bd9571mwv_regulator_id_table[] = { | ||
162 | { "bd9571mwv-regulator", }, | ||
163 | { /* sentinel */ } | ||
164 | }; | ||
165 | MODULE_DEVICE_TABLE(platform, bd9571mwv_regulator_id_table); | ||
166 | |||
167 | static struct platform_driver bd9571mwv_regulator_driver = { | ||
168 | .driver = { | ||
169 | .name = "bd9571mwv-regulator", | ||
170 | }, | ||
171 | .probe = bd9571mwv_regulator_probe, | ||
172 | .id_table = bd9571mwv_regulator_id_table, | ||
173 | }; | ||
174 | module_platform_driver(bd9571mwv_regulator_driver); | ||
175 | |||
176 | MODULE_AUTHOR("Marek Vasut <marek.vasut+renesas@gmail.com>"); | ||
177 | MODULE_DESCRIPTION("BD9571MWV Regulator driver"); | ||
178 | MODULE_LICENSE("GPL v2"); | ||