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