1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2023-09-23     GuEe-GUI     first version
9  */
10 
11 #include <dt-bindings/pin/state.h>
12 
13 #include "regulator_dm.h"
14 
15 struct regulator_gpio_state
16 {
17     rt_uint32_t value;
18     rt_uint32_t gpios;
19 };
20 
21 struct regulator_gpio_desc
22 {
23     rt_base_t pin;
24     rt_uint32_t flags;
25 };
26 
27 struct regulator_gpio
28 {
29     struct rt_regulator_node parent;
30 
31     rt_base_t enable_pin;
32 
33     rt_size_t pins_nr;
34     struct regulator_gpio_desc *pins_desc;
35 
36     int state;
37     rt_size_t states_nr;
38     struct regulator_gpio_state *states;
39 
40     const char *input_supply;
41     rt_uint32_t startup_delay;
42     rt_uint32_t off_on_delay;
43     rt_bool_t enabled_at_boot;
44     struct rt_regulator_param param;
45 };
46 
47 #define raw_to_regulator_gpio(raw) rt_container_of(raw, struct regulator_gpio, parent)
48 
regulator_gpio_enable(struct rt_regulator_node * reg_np)49 static rt_err_t regulator_gpio_enable(struct rt_regulator_node *reg_np)
50 {
51     struct regulator_gpio *rg = raw_to_regulator_gpio(reg_np);
52     struct rt_regulator_param *param = &rg->param;
53 
54     if (param->always_on)
55     {
56         return RT_EOK;
57     }
58 
59     if (rg->enable_pin >= 0)
60     {
61         rt_pin_mode(rg->enable_pin, PIN_MODE_OUTPUT);
62         rt_pin_write(rg->enable_pin, param->enable_active_high ? PIN_HIGH : PIN_LOW);
63     }
64 
65     return RT_EOK;
66 }
67 
regulator_gpio_disable(struct rt_regulator_node * reg_np)68 static rt_err_t regulator_gpio_disable(struct rt_regulator_node *reg_np)
69 {
70     struct regulator_gpio *rg = raw_to_regulator_gpio(reg_np);
71     struct rt_regulator_param *param = &rg->param;
72 
73     if (param->always_on)
74     {
75         return RT_EOK;
76     }
77 
78     if (rg->enable_pin >= 0)
79     {
80         rt_pin_mode(rg->enable_pin, PIN_MODE_OUTPUT);
81         rt_pin_write(rg->enable_pin, param->enable_active_high ? PIN_LOW : PIN_HIGH);
82     }
83 
84     return RT_EOK;
85 }
86 
regulator_gpio_is_enabled(struct rt_regulator_node * reg_np)87 static rt_bool_t regulator_gpio_is_enabled(struct rt_regulator_node *reg_np)
88 {
89     struct regulator_gpio *rg = raw_to_regulator_gpio(reg_np);
90     struct rt_regulator_param *param = &rg->param;
91 
92     if (param->always_on)
93     {
94         return RT_TRUE;
95     }
96 
97     if (rg->enable_pin >= 0)
98     {
99         rt_uint8_t active_val = param->enable_active_high ? PIN_LOW : PIN_HIGH;
100 
101         rt_pin_mode(rg->enable_pin, PIN_MODE_INPUT);
102         return rt_pin_read(rg->enable_pin) == active_val;
103     }
104 
105     return RT_TRUE;
106 }
107 
regulator_gpio_set_voltage(struct rt_regulator_node * reg_np,int min_uvolt,int max_uvolt)108 static rt_err_t regulator_gpio_set_voltage(struct rt_regulator_node *reg_np,
109         int min_uvolt, int max_uvolt)
110 {
111     int target = 0, best_val = RT_REGULATOR_UVOLT_INVALID;
112     struct regulator_gpio *rg = raw_to_regulator_gpio(reg_np);
113 
114     for (int i = 0; i < rg->states_nr; ++i)
115     {
116         struct regulator_gpio_state *state = &rg->states[i];
117 
118         if (state->value < best_val &&
119             state->value >= min_uvolt &&
120             state->value <= max_uvolt)
121         {
122             target = state->gpios;
123             best_val = state->value;
124         }
125     }
126 
127     if (best_val == RT_REGULATOR_UVOLT_INVALID)
128     {
129         return -RT_EINVAL;
130     }
131 
132     for (int i = 0; i < rg->pins_nr; ++i)
133     {
134         int state = (target >> i) & 1;
135         struct regulator_gpio_desc *gpiod = &rg->pins_desc[i];
136 
137         rt_pin_mode(gpiod->pin, PIN_MODE_OUTPUT);
138         rt_pin_write(gpiod->pin, gpiod->flags == PIND_OUT_HIGH ? state : !state);
139     }
140 
141     rg->state = target;
142 
143     return RT_EOK;
144 }
145 
regulator_gpio_get_voltage(struct rt_regulator_node * reg_np)146 static int regulator_gpio_get_voltage(struct rt_regulator_node *reg_np)
147 {
148     struct regulator_gpio *rg = raw_to_regulator_gpio(reg_np);
149 
150     for (int i = 0; i < rg->states_nr; ++i)
151     {
152         if (rg->states[i].gpios == rg->state)
153         {
154             return rg->states[i].value;
155         }
156     }
157 
158     return -RT_EINVAL;
159 }
160 
161 static const struct rt_regulator_ops regulator_gpio_ops =
162 {
163     .enable = regulator_gpio_enable,
164     .disable = regulator_gpio_disable,
165     .is_enabled = regulator_gpio_is_enabled,
166     .set_voltage = regulator_gpio_set_voltage,
167     .get_voltage = regulator_gpio_get_voltage,
168 };
169 
regulator_gpio_probe(struct rt_platform_device * pdev)170 static rt_err_t regulator_gpio_probe(struct rt_platform_device *pdev)
171 {
172     rt_err_t err;
173     struct rt_device *dev = &pdev->parent;
174     struct regulator_gpio *rg = rt_calloc(1, sizeof(*rg));
175     struct rt_regulator_node *rgp;
176 
177     if (!rg)
178     {
179         return -RT_ENOMEM;
180     }
181 
182     regulator_ofw_parse(dev->ofw_node, &rg->param);
183 
184     rgp = &rg->parent;
185     rgp->supply_name = rg->param.name;
186     rgp->ops = &regulator_gpio_ops;
187     rgp->param = &rg->param;
188     rgp->dev = &pdev->parent;
189 
190     rt_dm_dev_prop_read_u32(dev, "startup-delay-us", &rg->startup_delay);
191     rt_dm_dev_prop_read_u32(dev, "off-on-delay-us", &rg->off_on_delay);
192 
193     /* GPIO flags are ignored, we check by enable-active-high */
194     rg->enable_pin = rt_pin_get_named_pin(dev, "enable", 0, RT_NULL, RT_NULL);
195 
196     if (rg->enable_pin < 0 && rg->enable_pin != PIN_NONE)
197     {
198         err = rg->enable_pin;
199         goto _fail;
200     }
201 
202     rg->pins_nr = rt_pin_get_named_pin_count(dev, "gpios");
203 
204     if (rg->pins_nr > 0)
205     {
206         rg->pins_desc = rt_malloc(sizeof(*rg->pins_desc) * rg->pins_nr);
207 
208         if (!rg->pins_desc)
209         {
210             err = -RT_ENOMEM;
211 
212             goto _fail;
213         }
214 
215         for (int i = 0; i < rg->pins_nr; ++i)
216         {
217             rt_uint32_t val;
218             struct regulator_gpio_desc *gpiod = &rg->pins_desc[i];
219 
220             gpiod->pin = rt_pin_get_named_pin(dev, RT_NULL, i, RT_NULL, RT_NULL);
221 
222             if (gpiod->pin < 0)
223             {
224                 err = gpiod->pin;
225                 goto _fail;
226             }
227 
228             if (rt_dm_dev_prop_read_u32_index(dev, "gpios-states", i, &val) < 0)
229             {
230                 gpiod->flags = PIND_OUT_HIGH;
231             }
232             else
233             {
234                 gpiod->flags = val ? PIND_OUT_HIGH : PIND_OUT_LOW;
235             }
236 
237             if (gpiod->flags == PIND_OUT_HIGH)
238             {
239                 rg->state |= 1 << i;
240             }
241         }
242     }
243 
244     rg->states_nr = rt_dm_dev_prop_count_of_u32(dev, "states") / 2;
245 
246     if (rg->states_nr < 0)
247     {
248         err = -RT_EIO;
249 
250         goto _fail;
251     }
252 
253     rg->states = rt_malloc(sizeof(*rg->states) * rg->states_nr);
254 
255     if (!rg->states)
256     {
257         err = -RT_ENOMEM;
258 
259         goto _fail;
260     }
261 
262     for (int i = 0; i < rg->states_nr; ++i)
263     {
264         rt_dm_dev_prop_read_u32_index(dev, "states", i * 2, &rg->states[i].value);
265         rt_dm_dev_prop_read_u32_index(dev, "states", i * 2 + 1, &rg->states[i].gpios);
266     }
267 
268     if ((err = rt_regulator_register(rgp)))
269     {
270         goto _fail;
271     }
272 
273     return RT_EOK;
274 
275 _fail:
276     if (rg->pins_desc)
277     {
278         rt_free(rg->pins_desc);
279     }
280     if (rg->states)
281     {
282         rt_free(rg->states);
283     }
284     rt_free(rg);
285 
286     return err;
287 }
288 
289 static const struct rt_ofw_node_id regulator_gpio_ofw_ids[] =
290 {
291     { .compatible = "regulator-gpio" },
292     { /* sentinel */ }
293 };
294 
295 static struct rt_platform_driver regulator_gpio_driver =
296 {
297     .name = "regulator-gpio",
298     .ids = regulator_gpio_ofw_ids,
299 
300     .probe = regulator_gpio_probe,
301 };
302 
regulator_gpio_register(void)303 static int regulator_gpio_register(void)
304 {
305     rt_platform_driver_register(&regulator_gpio_driver);
306 
307     return 0;
308 }
309 INIT_SUBSYS_EXPORT(regulator_gpio_register);
310