pinctrl: uniphier: support per-pin configuration via DT
[oweals/u-boot.git] / drivers / pinctrl / uniphier / pinctrl-uniphier-core.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2015-2016 Socionext Inc.
4  *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
5  */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <linux/io.h>
10 #include <linux/err.h>
11 #include <linux/kernel.h>
12 #include <linux/sizes.h>
13 #include <dm/pinctrl.h>
14
15 #include "pinctrl-uniphier.h"
16
17 #define UNIPHIER_PINCTRL_PINMUX_BASE    0x1000
18 #define UNIPHIER_PINCTRL_LOAD_PINMUX    0x1700
19 #define UNIPHIER_PINCTRL_PUPDCTRL_BASE  0x1a00
20 #define UNIPHIER_PINCTRL_IECTRL         0x1d00
21
22 static const char *uniphier_pinctrl_dummy_name = "_dummy";
23
24 static int uniphier_pinctrl_get_pins_count(struct udevice *dev)
25 {
26         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
27         const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
28         int pins_count = priv->socdata->pins_count;
29
30         /*
31          * We do not list all pins in the pin table to save memory footprint.
32          * Report the max pin number + 1 to fake the framework.
33          */
34         return pins[pins_count - 1].number + 1;
35 }
36
37 static const char *uniphier_pinctrl_get_pin_name(struct udevice *dev,
38                                                  unsigned int selector)
39 {
40         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
41         const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
42         int pins_count = priv->socdata->pins_count;
43         int i;
44
45         for (i = 0; i < pins_count; i++)
46                 if (pins[i].number == selector)
47                         return pins[i].name;
48
49         return uniphier_pinctrl_dummy_name;
50 }
51
52 static int uniphier_pinctrl_get_groups_count(struct udevice *dev)
53 {
54         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
55
56         return priv->socdata->groups_count;
57 }
58
59 static const char *uniphier_pinctrl_get_group_name(struct udevice *dev,
60                                                    unsigned selector)
61 {
62         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
63
64         if (!priv->socdata->groups[selector].name)
65                 return uniphier_pinctrl_dummy_name;
66
67         return priv->socdata->groups[selector].name;
68 }
69
70 static int uniphier_pinmux_get_functions_count(struct udevice *dev)
71 {
72         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
73
74         return priv->socdata->functions_count;
75 }
76
77 static const char *uniphier_pinmux_get_function_name(struct udevice *dev,
78                                                      unsigned selector)
79 {
80         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
81
82         if (!priv->socdata->functions[selector])
83                 return uniphier_pinctrl_dummy_name;
84
85         return priv->socdata->functions[selector];
86 }
87
88 static int uniphier_pinconf_input_enable_perpin(struct udevice *dev,
89                                                 unsigned int pin, int enable)
90 {
91         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
92         unsigned reg;
93         u32 mask, tmp;
94
95         reg = UNIPHIER_PINCTRL_IECTRL + pin / 32 * 4;
96         mask = BIT(pin % 32);
97
98         tmp = readl(priv->base + reg);
99         if (enable)
100                 tmp |= mask;
101         else
102                 tmp &= ~mask;
103         writel(tmp, priv->base + reg);
104
105         return 0;
106 }
107
108 static int uniphier_pinconf_input_enable_legacy(struct udevice *dev,
109                                                 unsigned int pin, int enable)
110 {
111         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
112
113         /*
114          * Multiple pins share one input enable, per-pin disabling is
115          * impossible.
116          */
117         if (!enable)
118                 return -EINVAL;
119
120         /* Set all bits instead of having a bunch of pin data */
121         writel(U32_MAX, priv->base + UNIPHIER_PINCTRL_IECTRL);
122
123         return 0;
124 }
125
126 static int uniphier_pinconf_input_enable(struct udevice *dev,
127                                          unsigned int pin, int enable)
128 {
129         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
130
131         if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL)
132                 return uniphier_pinconf_input_enable_perpin(dev, pin, enable);
133         else
134                 return uniphier_pinconf_input_enable_legacy(dev, pin, enable);
135 }
136
137 #if CONFIG_IS_ENABLED(PINCONF)
138
139 static const struct pinconf_param uniphier_pinconf_params[] = {
140         { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
141         { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
142         { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
143         { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
144         { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
145         { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
146 };
147
148 static int uniphier_pinconf_bias_set(struct udevice *dev, unsigned int pin,
149                                      unsigned int param, unsigned int arg)
150 {
151         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
152         unsigned int enable = 1;
153         unsigned int reg;
154         u32 mask, tmp;
155
156         if (!(priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PUPD_SIMPLE))
157                 return -ENOTSUPP;
158
159         switch (param) {
160         case PIN_CONFIG_BIAS_DISABLE:
161                 enable = 0;
162                 break;
163         case PIN_CONFIG_BIAS_PULL_UP:
164         case PIN_CONFIG_BIAS_PULL_DOWN:
165                 if (arg == 0)   /* total bias is not supported */
166                         return -EINVAL;
167                 break;
168         case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
169                 if (arg == 0)   /* configuration ignored */
170                         return 0;
171         default:
172                 BUG();
173         }
174
175         reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pin / 32 * 4;
176         mask = BIT(pin % 32);
177
178         tmp = readl(priv->base + reg);
179         if (enable)
180                 tmp |= mask;
181         else
182                 tmp &= ~mask;
183         writel(tmp, priv->base + reg);
184
185         return 0;
186 }
187
188 static int uniphier_pinconf_set(struct udevice *dev, unsigned int pin,
189                                 unsigned int param, unsigned int arg)
190 {
191         int ret;
192
193         switch (param) {
194         case PIN_CONFIG_BIAS_DISABLE:
195         case PIN_CONFIG_BIAS_PULL_UP:
196         case PIN_CONFIG_BIAS_PULL_DOWN:
197         case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
198                 ret = uniphier_pinconf_bias_set(dev, pin, param, arg);
199                 break;
200         case PIN_CONFIG_INPUT_ENABLE:
201                 ret = uniphier_pinconf_input_enable(dev, pin, arg);
202                 break;
203         default:
204                 dev_err(dev, "unsupported configuration parameter %u\n", param);
205                 return -EINVAL;
206         }
207
208         return ret;
209 }
210
211 static int uniphier_pinconf_group_set(struct udevice *dev,
212                                       unsigned int group_selector,
213                                       unsigned int param, unsigned int arg)
214 {
215         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
216         const struct uniphier_pinctrl_group *grp =
217                                         &priv->socdata->groups[group_selector];
218         int i, ret;
219
220         for (i = 0; i < grp->num_pins; i++) {
221                 ret = uniphier_pinconf_set(dev, grp->pins[i], param, arg);
222                 if (ret)
223                         return ret;
224         }
225
226         return 0;
227 }
228
229 #endif /* CONFIG_IS_ENABLED(PINCONF) */
230
231 static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin,
232                                     int muxval)
233 {
234         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
235         unsigned reg, reg_end, shift, mask;
236         unsigned mux_bits = 8;
237         unsigned reg_stride = 4;
238         bool load_pinctrl = false;
239         u32 tmp;
240
241         /* some pins need input-enabling */
242         uniphier_pinconf_input_enable(dev, pin, 1);
243
244         if (muxval < 0)
245                 return;         /* dedicated pin; nothing to do for pin-mux */
246
247         if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_MUX_4BIT)
248                 mux_bits = 4;
249
250         if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) {
251                 /*
252                  *  Mode       offset        bit
253                  *  Normal     4 * n     shift+3:shift
254                  *  Debug      4 * n     shift+7:shift+4
255                  */
256                 mux_bits /= 2;
257                 reg_stride = 8;
258                 load_pinctrl = true;
259         }
260
261         reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
262         reg_end = reg + reg_stride;
263         shift = pin * mux_bits % 32;
264         mask = (1U << mux_bits) - 1;
265
266         /*
267          * If reg_stride is greater than 4, the MSB of each pinsel shall be
268          * stored in the offset+4.
269          */
270         for (; reg < reg_end; reg += 4) {
271                 tmp = readl(priv->base + reg);
272                 tmp &= ~(mask << shift);
273                 tmp |= (mask & muxval) << shift;
274                 writel(tmp, priv->base + reg);
275
276                 muxval >>= mux_bits;
277         }
278
279         if (load_pinctrl)
280                 writel(1, priv->base + UNIPHIER_PINCTRL_LOAD_PINMUX);
281 }
282
283 static int uniphier_pinmux_group_set(struct udevice *dev,
284                                      unsigned group_selector,
285                                      unsigned func_selector)
286 {
287         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
288         const struct uniphier_pinctrl_group *grp =
289                                         &priv->socdata->groups[group_selector];
290         int i;
291
292         for (i = 0; i < grp->num_pins; i++)
293                 uniphier_pinmux_set_one(dev, grp->pins[i], grp->muxvals[i]);
294
295         return 0;
296 }
297
298 const struct pinctrl_ops uniphier_pinctrl_ops = {
299         .get_pins_count = uniphier_pinctrl_get_pins_count,
300         .get_pin_name = uniphier_pinctrl_get_pin_name,
301         .get_groups_count = uniphier_pinctrl_get_groups_count,
302         .get_group_name = uniphier_pinctrl_get_group_name,
303         .get_functions_count = uniphier_pinmux_get_functions_count,
304         .get_function_name = uniphier_pinmux_get_function_name,
305         .pinmux_group_set = uniphier_pinmux_group_set,
306 #if CONFIG_IS_ENABLED(PINCONF)
307         .pinconf_num_params = ARRAY_SIZE(uniphier_pinconf_params),
308         .pinconf_params = uniphier_pinconf_params,
309         .pinconf_set = uniphier_pinconf_set,
310         .pinconf_group_set = uniphier_pinconf_group_set,
311 #endif
312         .set_state = pinctrl_generic_set_state,
313 };
314
315 int uniphier_pinctrl_probe(struct udevice *dev,
316                            struct uniphier_pinctrl_socdata *socdata)
317 {
318         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
319         fdt_addr_t addr;
320
321         addr = devfdt_get_addr(dev->parent);
322         if (addr == FDT_ADDR_T_NONE)
323                 return -EINVAL;
324
325         priv->base = devm_ioremap(dev, addr, SZ_4K);
326         if (!priv->base)
327                 return -ENOMEM;
328
329         priv->socdata = socdata;
330
331         return 0;
332 }