Prepare v2023.10
[platform/kernel/u-boot.git] / drivers / pinctrl / meson / pinctrl-meson.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2016 - Beniamino Galvani <b.galvani@gmail.com>
4  */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <log.h>
9 #include <malloc.h>
10 #include <asm/global_data.h>
11 #include <dm/device-internal.h>
12 #include <dm/device_compat.h>
13 #include <dm/lists.h>
14 #include <dm/pinctrl.h>
15 #include <fdt_support.h>
16 #include <linux/bitops.h>
17 #include <linux/err.h>
18 #include <linux/io.h>
19 #include <linux/libfdt.h>
20 #include <linux/sizes.h>
21 #include <asm/gpio.h>
22
23 #include "pinctrl-meson.h"
24
25 DECLARE_GLOBAL_DATA_PTR;
26
27 static const char *meson_pinctrl_dummy_name = "_dummy";
28
29 static char pin_name[PINNAME_SIZE];
30
31 int meson_pinctrl_get_groups_count(struct udevice *dev)
32 {
33         struct meson_pinctrl *priv = dev_get_priv(dev);
34
35         return priv->data->num_groups;
36 }
37
38 const char *meson_pinctrl_get_group_name(struct udevice *dev,
39                                          unsigned int selector)
40 {
41         struct meson_pinctrl *priv = dev_get_priv(dev);
42
43         if (!priv->data->groups[selector].name)
44                 return meson_pinctrl_dummy_name;
45
46         return priv->data->groups[selector].name;
47 }
48
49 int meson_pinctrl_get_pins_count(struct udevice *dev)
50 {
51         struct meson_pinctrl *priv = dev_get_priv(dev);
52
53         return priv->data->num_pins;
54 }
55
56 const char *meson_pinctrl_get_pin_name(struct udevice *dev,
57                                        unsigned int selector)
58 {
59         struct meson_pinctrl *priv = dev_get_priv(dev);
60
61         if (selector > priv->data->num_pins ||
62             selector > priv->data->funcs[0].num_groups)
63                 snprintf(pin_name, PINNAME_SIZE, "Error");
64         else
65                 snprintf(pin_name, PINNAME_SIZE, "%s",
66                          priv->data->funcs[0].groups[selector]);
67
68         return pin_name;
69 }
70
71 int meson_pinmux_get_functions_count(struct udevice *dev)
72 {
73         struct meson_pinctrl *priv = dev_get_priv(dev);
74
75         return priv->data->num_funcs;
76 }
77
78 const char *meson_pinmux_get_function_name(struct udevice *dev,
79                                            unsigned int selector)
80 {
81         struct meson_pinctrl *priv = dev_get_priv(dev);
82
83         return priv->data->funcs[selector].name;
84 }
85
86 static int meson_gpio_calc_reg_and_bit(struct udevice *dev, unsigned int offset,
87                                        enum meson_reg_type reg_type,
88                                        unsigned int *reg, unsigned int *bit)
89 {
90         struct meson_pinctrl *priv = dev_get_priv(dev);
91         struct meson_bank *bank = NULL;
92         struct meson_reg_desc *desc;
93         unsigned int pin;
94         int i;
95
96         pin = priv->data->pin_base + offset;
97
98         for (i = 0; i < priv->data->num_banks; i++) {
99                 if (pin >= priv->data->banks[i].first &&
100                     pin <= priv->data->banks[i].last) {
101                         bank = &priv->data->banks[i];
102                         break;
103                 }
104         }
105
106         if (!bank)
107                 return -EINVAL;
108
109         desc = &bank->regs[reg_type];
110         *reg = desc->reg * 4;
111         *bit = desc->bit + pin - bank->first;
112
113         return 0;
114 }
115
116 int meson_gpio_get(struct udevice *dev, unsigned int offset)
117 {
118         struct meson_pinctrl *priv = dev_get_priv(dev->parent);
119         unsigned int reg, bit;
120         int ret;
121
122         ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_IN, &reg,
123                                           &bit);
124         if (ret)
125                 return ret;
126
127         return !!(readl(priv->reg_gpio + reg) & BIT(bit));
128 }
129
130 int meson_gpio_set(struct udevice *dev, unsigned int offset, int value)
131 {
132         struct meson_pinctrl *priv = dev_get_priv(dev->parent);
133         unsigned int reg, bit;
134         int ret;
135
136         ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_OUT, &reg,
137                                           &bit);
138         if (ret)
139                 return ret;
140
141         clrsetbits_le32(priv->reg_gpio + reg, BIT(bit), value ? BIT(bit) : 0);
142
143         return 0;
144 }
145
146 int meson_gpio_get_direction(struct udevice *dev, unsigned int offset)
147 {
148         struct meson_pinctrl *priv = dev_get_priv(dev->parent);
149         unsigned int reg, bit, val;
150         int ret;
151
152         ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_DIR, &reg,
153                                           &bit);
154         if (ret)
155                 return ret;
156
157         val = readl(priv->reg_gpio + reg);
158
159         return (val & BIT(bit)) ? GPIOF_INPUT : GPIOF_OUTPUT;
160 }
161
162 int meson_gpio_direction_input(struct udevice *dev, unsigned int offset)
163 {
164         struct meson_pinctrl *priv = dev_get_priv(dev->parent);
165         unsigned int reg, bit;
166         int ret;
167
168         ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_DIR, &reg,
169                                           &bit);
170         if (ret)
171                 return ret;
172
173         setbits_le32(priv->reg_gpio + reg, BIT(bit));
174
175         return 0;
176 }
177
178 int meson_gpio_direction_output(struct udevice *dev,
179                                 unsigned int offset, int value)
180 {
181         struct meson_pinctrl *priv = dev_get_priv(dev->parent);
182         unsigned int reg, bit;
183         int ret;
184
185         ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_DIR, &reg,
186                                           &bit);
187         if (ret)
188                 return ret;
189
190         clrbits_le32(priv->reg_gpio + reg, BIT(bit));
191
192         ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_OUT, &reg,
193                                           &bit);
194         if (ret)
195                 return ret;
196
197         clrsetbits_le32(priv->reg_gpio + reg, BIT(bit), value ? BIT(bit) : 0);
198
199         return 0;
200 }
201
202 static int meson_pinconf_bias_set(struct udevice *dev, unsigned int pin,
203                                   unsigned int param)
204 {
205         struct meson_pinctrl *priv = dev_get_priv(dev);
206         unsigned int offset = pin - priv->data->pin_base;
207         unsigned int reg, bit;
208         int ret;
209
210         ret = meson_gpio_calc_reg_and_bit(dev, offset, REG_PULLEN, &reg, &bit);
211         if (ret)
212                 return ret;
213
214         if (param == PIN_CONFIG_BIAS_DISABLE) {
215                 clrsetbits_le32(priv->reg_pullen + reg, BIT(bit), 0);
216                 return 0;
217         }
218
219         /* othewise, enable the bias and select level */
220         clrsetbits_le32(priv->reg_pullen + reg, BIT(bit), BIT(bit));
221         ret = meson_gpio_calc_reg_and_bit(dev, offset, REG_PULL, &reg, &bit);
222         if (ret)
223                 return ret;
224
225         clrsetbits_le32(priv->reg_pull + reg, BIT(bit),
226                         (param == PIN_CONFIG_BIAS_PULL_UP ? BIT(bit) : 0));
227
228         return 0;
229 }
230
231 static int meson_pinconf_drive_strength_set(struct udevice *dev,
232                                             unsigned int pin,
233                                             unsigned int drive_strength_ua)
234 {
235         struct meson_pinctrl *priv = dev_get_priv(dev);
236         unsigned int offset = pin - priv->data->pin_base;
237         unsigned int reg, bit;
238         unsigned int ds_val;
239         int ret;
240
241         if (!priv->reg_ds) {
242                 dev_err(dev, "drive-strength-microamp not supported\n");
243                 return -ENOTSUPP;
244         }
245
246         ret = meson_gpio_calc_reg_and_bit(dev, offset, REG_DS, &reg, &bit);
247         if (ret)
248                 return ret;
249
250         bit = bit << 1;
251
252         if (drive_strength_ua <= 500) {
253                 ds_val = MESON_PINCONF_DRV_500UA;
254         } else if (drive_strength_ua <= 2500) {
255                 ds_val = MESON_PINCONF_DRV_2500UA;
256         } else if (drive_strength_ua <= 3000) {
257                 ds_val = MESON_PINCONF_DRV_3000UA;
258         } else if (drive_strength_ua <= 4000) {
259                 ds_val = MESON_PINCONF_DRV_4000UA;
260         } else {
261                 dev_warn(dev,
262                          "pin %u: invalid drive-strength-microamp : %d , default to 4mA\n",
263                          pin, drive_strength_ua);
264                 ds_val = MESON_PINCONF_DRV_4000UA;
265         }
266
267         clrsetbits_le32(priv->reg_ds + reg, 0x3 << bit, ds_val << bit);
268
269         return 0;
270 }
271
272 int meson_pinconf_set(struct udevice *dev, unsigned int pin,
273                       unsigned int param, unsigned int arg)
274 {
275         int ret;
276
277         switch (param) {
278         case PIN_CONFIG_BIAS_DISABLE:
279         case PIN_CONFIG_BIAS_PULL_UP:
280         case PIN_CONFIG_BIAS_PULL_DOWN:
281                 ret = meson_pinconf_bias_set(dev, pin, param);
282                 break;
283         case PIN_CONFIG_DRIVE_STRENGTH_UA:
284                 ret = meson_pinconf_drive_strength_set(dev, pin, arg);
285                 break;
286         default:
287                 dev_err(dev, "unsupported configuration parameter %u\n", param);
288                 return -EINVAL;
289         }
290
291         return ret;
292 }
293
294 int meson_pinconf_group_set(struct udevice *dev,
295                             unsigned int group_selector,
296                             unsigned int param, unsigned int arg)
297 {
298         struct meson_pinctrl *priv = dev_get_priv(dev);
299         struct meson_pmx_group *grp = &priv->data->groups[group_selector];
300         int i, ret;
301
302         for (i = 0; i < grp->num_pins; i++) {
303                 ret = meson_pinconf_set(dev, grp->pins[i], param, arg);
304                 if (ret)
305                         return ret;
306         }
307
308         return 0;
309 }
310
311 int meson_gpio_probe(struct udevice *dev)
312 {
313         struct meson_pinctrl *priv = dev_get_priv(dev->parent);
314         struct gpio_dev_priv *uc_priv;
315
316         uc_priv = dev_get_uclass_priv(dev);
317         uc_priv->bank_name = priv->data->name;
318         uc_priv->gpio_count = priv->data->num_pins;
319
320         return 0;
321 }
322
323 static fdt_addr_t parse_address(int offset, const char *name, int na, int ns)
324 {
325         int index, len = 0;
326         const fdt32_t *reg;
327
328         index = fdt_stringlist_search(gd->fdt_blob, offset, "reg-names", name);
329         if (index < 0)
330                 return FDT_ADDR_T_NONE;
331
332         reg = fdt_getprop(gd->fdt_blob, offset, "reg", &len);
333         if (!reg || (len <= (index * sizeof(fdt32_t) * (na + ns))))
334                 return FDT_ADDR_T_NONE;
335
336         reg += index * (na + ns);
337
338         return fdt_translate_address((void *)gd->fdt_blob, offset, reg);
339 }
340
341 int meson_pinctrl_probe(struct udevice *dev)
342 {
343         struct meson_pinctrl *priv = dev_get_priv(dev);
344         struct uclass_driver *drv;
345         struct udevice *gpio_dev;
346         fdt_addr_t addr;
347         int node, gpio = -1, len;
348         int na, ns;
349         char *name;
350
351         /* FIXME: Should use livetree */
352         na = fdt_address_cells(gd->fdt_blob, dev_of_offset(dev->parent));
353         if (na < 1) {
354                 debug("bad #address-cells\n");
355                 return -EINVAL;
356         }
357
358         ns = fdt_size_cells(gd->fdt_blob, dev_of_offset(dev->parent));
359         if (ns < 1) {
360                 debug("bad #size-cells\n");
361                 return -EINVAL;
362         }
363
364         fdt_for_each_subnode(node, gd->fdt_blob, dev_of_offset(dev)) {
365                 if (fdt_getprop(gd->fdt_blob, node, "gpio-controller", &len)) {
366                         gpio = node;
367                         break;
368                 }
369         }
370
371         if (!gpio) {
372                 debug("gpio node not found\n");
373                 return -EINVAL;
374         }
375
376         addr = parse_address(gpio, "mux", na, ns);
377         if (addr == FDT_ADDR_T_NONE) {
378                 debug("mux address not found\n");
379                 return -EINVAL;
380         }
381         priv->reg_mux = (void __iomem *)addr;
382
383         addr = parse_address(gpio, "gpio", na, ns);
384         if (addr == FDT_ADDR_T_NONE) {
385                 debug("gpio address not found\n");
386                 return -EINVAL;
387         }
388         priv->reg_gpio = (void __iomem *)addr;
389
390         addr = parse_address(gpio, "pull", na, ns);
391         /* Use gpio region if pull one is not present */
392         if (addr == FDT_ADDR_T_NONE)
393                 priv->reg_pull = priv->reg_gpio;
394         else
395                 priv->reg_pull = (void __iomem *)addr;
396
397         addr = parse_address(gpio, "pull-enable", na, ns);
398         /* Use pull region if pull-enable one is not present */
399         if (addr == FDT_ADDR_T_NONE)
400                 priv->reg_pullen = priv->reg_pull;
401         else
402                 priv->reg_pullen = (void __iomem *)addr;
403
404         addr = parse_address(gpio, "ds", na, ns);
405         /* Drive strength region is optional */
406         if (addr == FDT_ADDR_T_NONE)
407                 priv->reg_ds = NULL;
408         else
409                 priv->reg_ds = (void __iomem *)addr;
410
411         priv->data = (struct meson_pinctrl_data *)dev_get_driver_data(dev);
412
413         /* Lookup GPIO driver */
414         drv = lists_uclass_lookup(UCLASS_GPIO);
415         if (!drv) {
416                 puts("Cannot find GPIO driver\n");
417                 return -ENOENT;
418         }
419
420         name = calloc(1, 32);
421         sprintf(name, "meson-gpio");
422
423         /* Create child device UCLASS_GPIO and bind it */
424         device_bind(dev, priv->data->gpio_driver, name, NULL,
425                     offset_to_ofnode(gpio), &gpio_dev);
426
427         return 0;
428 }