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