GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / regulator / stm32-vrefbuf.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) STMicroelectronics 2017
4  *
5  * Author: Fabrice Gasnier <fabrice.gasnier@st.com>
6  */
7
8 #include <linux/bitfield.h>
9 #include <linux/clk.h>
10 #include <linux/io.h>
11 #include <linux/iopoll.h>
12 #include <linux/module.h>
13 #include <linux/of.h>
14 #include <linux/platform_device.h>
15 #include <linux/regulator/driver.h>
16 #include <linux/regulator/of_regulator.h>
17 #include <linux/pm_runtime.h>
18
19 /* STM32 VREFBUF registers */
20 #define STM32_VREFBUF_CSR               0x00
21
22 /* STM32 VREFBUF CSR bitfields */
23 #define STM32_VRS                       GENMASK(6, 4)
24 #define STM32_VRR                       BIT(3)
25 #define STM32_HIZ                       BIT(1)
26 #define STM32_ENVR                      BIT(0)
27
28 #define STM32_VREFBUF_AUTO_SUSPEND_DELAY_MS     10
29
30 struct stm32_vrefbuf {
31         void __iomem *base;
32         struct clk *clk;
33         struct device *dev;
34 };
35
36 static const unsigned int stm32_vrefbuf_voltages[] = {
37         /* Matches resp. VRS = 000b, 001b, 010b, 011b */
38         2500000, 2048000, 1800000, 1500000,
39 };
40
41 static int stm32_vrefbuf_enable(struct regulator_dev *rdev)
42 {
43         struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
44         u32 val;
45         int ret;
46
47         ret = pm_runtime_resume_and_get(priv->dev);
48         if (ret < 0)
49                 return ret;
50
51         val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
52         val = (val & ~STM32_HIZ) | STM32_ENVR;
53         writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
54
55         /*
56          * Vrefbuf startup time depends on external capacitor: wait here for
57          * VRR to be set. That means output has reached expected value.
58          * ~650us sleep should be enough for caps up to 1.5uF. Use 10ms as
59          * arbitrary timeout.
60          */
61         ret = readl_poll_timeout(priv->base + STM32_VREFBUF_CSR, val,
62                                  val & STM32_VRR, 650, 10000);
63         if (ret) {
64                 dev_err(&rdev->dev, "stm32 vrefbuf timed out!\n");
65                 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
66                 val = (val & ~STM32_ENVR) | STM32_HIZ;
67                 writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
68         }
69
70         pm_runtime_mark_last_busy(priv->dev);
71         pm_runtime_put_autosuspend(priv->dev);
72
73         return ret;
74 }
75
76 static int stm32_vrefbuf_disable(struct regulator_dev *rdev)
77 {
78         struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
79         u32 val;
80         int ret;
81
82         ret = pm_runtime_resume_and_get(priv->dev);
83         if (ret < 0)
84                 return ret;
85
86         val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
87         val &= ~STM32_ENVR;
88         writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
89
90         pm_runtime_mark_last_busy(priv->dev);
91         pm_runtime_put_autosuspend(priv->dev);
92
93         return 0;
94 }
95
96 static int stm32_vrefbuf_is_enabled(struct regulator_dev *rdev)
97 {
98         struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
99         int ret;
100
101         ret = pm_runtime_resume_and_get(priv->dev);
102         if (ret < 0)
103                 return ret;
104
105         ret = readl_relaxed(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR;
106
107         pm_runtime_mark_last_busy(priv->dev);
108         pm_runtime_put_autosuspend(priv->dev);
109
110         return ret;
111 }
112
113 static int stm32_vrefbuf_set_voltage_sel(struct regulator_dev *rdev,
114                                          unsigned sel)
115 {
116         struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
117         u32 val;
118         int ret;
119
120         ret = pm_runtime_resume_and_get(priv->dev);
121         if (ret < 0)
122                 return ret;
123
124         val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
125         val = (val & ~STM32_VRS) | FIELD_PREP(STM32_VRS, sel);
126         writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
127
128         pm_runtime_mark_last_busy(priv->dev);
129         pm_runtime_put_autosuspend(priv->dev);
130
131         return 0;
132 }
133
134 static int stm32_vrefbuf_get_voltage_sel(struct regulator_dev *rdev)
135 {
136         struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
137         u32 val;
138         int ret;
139
140         ret = pm_runtime_resume_and_get(priv->dev);
141         if (ret < 0)
142                 return ret;
143
144         val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
145         ret = FIELD_GET(STM32_VRS, val);
146
147         pm_runtime_mark_last_busy(priv->dev);
148         pm_runtime_put_autosuspend(priv->dev);
149
150         return ret;
151 }
152
153 static const struct regulator_ops stm32_vrefbuf_volt_ops = {
154         .enable         = stm32_vrefbuf_enable,
155         .disable        = stm32_vrefbuf_disable,
156         .is_enabled     = stm32_vrefbuf_is_enabled,
157         .get_voltage_sel = stm32_vrefbuf_get_voltage_sel,
158         .set_voltage_sel = stm32_vrefbuf_set_voltage_sel,
159         .list_voltage   = regulator_list_voltage_table,
160 };
161
162 static const struct regulator_desc stm32_vrefbuf_regu = {
163         .name = "vref",
164         .supply_name = "vdda",
165         .volt_table = stm32_vrefbuf_voltages,
166         .n_voltages = ARRAY_SIZE(stm32_vrefbuf_voltages),
167         .ops = &stm32_vrefbuf_volt_ops,
168         .off_on_delay = 1000,
169         .type = REGULATOR_VOLTAGE,
170         .owner = THIS_MODULE,
171 };
172
173 static int stm32_vrefbuf_probe(struct platform_device *pdev)
174 {
175         struct stm32_vrefbuf *priv;
176         struct regulator_config config = { };
177         struct regulator_dev *rdev;
178         int ret;
179
180         priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
181         if (!priv)
182                 return -ENOMEM;
183         priv->dev = &pdev->dev;
184
185         priv->base = devm_platform_ioremap_resource(pdev, 0);
186         if (IS_ERR(priv->base))
187                 return PTR_ERR(priv->base);
188
189         priv->clk = devm_clk_get(&pdev->dev, NULL);
190         if (IS_ERR(priv->clk))
191                 return PTR_ERR(priv->clk);
192
193         pm_runtime_get_noresume(&pdev->dev);
194         pm_runtime_set_active(&pdev->dev);
195         pm_runtime_set_autosuspend_delay(&pdev->dev,
196                                          STM32_VREFBUF_AUTO_SUSPEND_DELAY_MS);
197         pm_runtime_use_autosuspend(&pdev->dev);
198         pm_runtime_enable(&pdev->dev);
199
200         ret = clk_prepare_enable(priv->clk);
201         if (ret) {
202                 dev_err(&pdev->dev, "clk prepare failed with error %d\n", ret);
203                 goto err_pm_stop;
204         }
205
206         config.dev = &pdev->dev;
207         config.driver_data = priv;
208         config.of_node = pdev->dev.of_node;
209         config.init_data = of_get_regulator_init_data(&pdev->dev,
210                                                       pdev->dev.of_node,
211                                                       &stm32_vrefbuf_regu);
212
213         rdev = regulator_register(&pdev->dev, &stm32_vrefbuf_regu, &config);
214         if (IS_ERR(rdev)) {
215                 ret = PTR_ERR(rdev);
216                 dev_err(&pdev->dev, "register failed with error %d\n", ret);
217                 goto err_clk_dis;
218         }
219         platform_set_drvdata(pdev, rdev);
220
221         pm_runtime_mark_last_busy(&pdev->dev);
222         pm_runtime_put_autosuspend(&pdev->dev);
223
224         return 0;
225
226 err_clk_dis:
227         clk_disable_unprepare(priv->clk);
228 err_pm_stop:
229         pm_runtime_disable(&pdev->dev);
230         pm_runtime_set_suspended(&pdev->dev);
231         pm_runtime_put_noidle(&pdev->dev);
232
233         return ret;
234 }
235
236 static int stm32_vrefbuf_remove(struct platform_device *pdev)
237 {
238         struct regulator_dev *rdev = platform_get_drvdata(pdev);
239         struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
240
241         pm_runtime_get_sync(&pdev->dev);
242         regulator_unregister(rdev);
243         clk_disable_unprepare(priv->clk);
244         pm_runtime_disable(&pdev->dev);
245         pm_runtime_set_suspended(&pdev->dev);
246         pm_runtime_put_noidle(&pdev->dev);
247
248         return 0;
249 };
250
251 static int __maybe_unused stm32_vrefbuf_runtime_suspend(struct device *dev)
252 {
253         struct regulator_dev *rdev = dev_get_drvdata(dev);
254         struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
255
256         clk_disable_unprepare(priv->clk);
257
258         return 0;
259 }
260
261 static int __maybe_unused stm32_vrefbuf_runtime_resume(struct device *dev)
262 {
263         struct regulator_dev *rdev = dev_get_drvdata(dev);
264         struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
265
266         return clk_prepare_enable(priv->clk);
267 }
268
269 static const struct dev_pm_ops stm32_vrefbuf_pm_ops = {
270         SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
271                                 pm_runtime_force_resume)
272         SET_RUNTIME_PM_OPS(stm32_vrefbuf_runtime_suspend,
273                            stm32_vrefbuf_runtime_resume,
274                            NULL)
275 };
276
277 static const struct of_device_id __maybe_unused stm32_vrefbuf_of_match[] = {
278         { .compatible = "st,stm32-vrefbuf", },
279         {},
280 };
281 MODULE_DEVICE_TABLE(of, stm32_vrefbuf_of_match);
282
283 static struct platform_driver stm32_vrefbuf_driver = {
284         .probe = stm32_vrefbuf_probe,
285         .remove = stm32_vrefbuf_remove,
286         .driver = {
287                 .name  = "stm32-vrefbuf",
288                 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
289                 .of_match_table = of_match_ptr(stm32_vrefbuf_of_match),
290                 .pm = &stm32_vrefbuf_pm_ops,
291         },
292 };
293 module_platform_driver(stm32_vrefbuf_driver);
294
295 MODULE_LICENSE("GPL v2");
296 MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
297 MODULE_DESCRIPTION("STMicroelectronics STM32 VREFBUF driver");
298 MODULE_ALIAS("platform:stm32-vrefbuf");