]> git.sur5r.net Git - u-boot/blob - drivers/pinctrl/uniphier/pinctrl-uniphier-core.c
Merge branch 'master' of git://git.denx.de/u-boot-video
[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 <linux/io.h>
9 #include <linux/err.h>
10 #include <linux/sizes.h>
11 #include <dm/device.h>
12 #include <dm/pinctrl.h>
13
14 #include "pinctrl-uniphier.h"
15
16 static const char *uniphier_pinctrl_dummy_name = "_dummy";
17
18 static int uniphier_pinctrl_get_groups_count(struct udevice *dev)
19 {
20         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
21
22         return priv->socdata->groups_count;
23 }
24
25 static const char *uniphier_pinctrl_get_group_name(struct udevice *dev,
26                                                    unsigned selector)
27 {
28         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
29
30         if (!priv->socdata->groups[selector].name)
31                 return uniphier_pinctrl_dummy_name;
32
33         return priv->socdata->groups[selector].name;
34 }
35
36 static int uniphier_pinmux_get_functions_count(struct udevice *dev)
37 {
38         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
39
40         return priv->socdata->functions_count;
41 }
42
43 static const char *uniphier_pinmux_get_function_name(struct udevice *dev,
44                                                      unsigned selector)
45 {
46         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
47
48         if (!priv->socdata->functions[selector])
49                 return uniphier_pinctrl_dummy_name;
50
51         return priv->socdata->functions[selector];
52 }
53
54 static void uniphier_pinconf_input_enable_perpin(struct udevice *dev,
55                                                  unsigned pin)
56 {
57         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
58         unsigned reg;
59         u32 mask, tmp;
60
61         reg = UNIPHIER_PINCTRL_IECTRL + pin / 32 * 4;
62         mask = BIT(pin % 32);
63
64         tmp = readl(priv->base + reg);
65         tmp |= mask;
66         writel(tmp, priv->base + reg);
67 }
68
69 static void uniphier_pinconf_input_enable_legacy(struct udevice *dev,
70                                                  unsigned pin)
71 {
72         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
73         int pins_count = priv->socdata->pins_count;
74         const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
75         int i;
76
77         for (i = 0; i < pins_count; i++) {
78                 if (pins[i].number == pin) {
79                         unsigned int iectrl;
80                         u32 tmp;
81
82                         iectrl = uniphier_pin_get_iectrl(pins[i].data);
83                         tmp = readl(priv->base + UNIPHIER_PINCTRL_IECTRL);
84                         tmp |= 1 << iectrl;
85                         writel(tmp, priv->base + UNIPHIER_PINCTRL_IECTRL);
86                 }
87         }
88 }
89
90 static void uniphier_pinconf_input_enable(struct udevice *dev, unsigned pin)
91 {
92         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
93
94         if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL)
95                 uniphier_pinconf_input_enable_perpin(dev, pin);
96         else
97                 uniphier_pinconf_input_enable_legacy(dev, pin);
98 }
99
100 static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin,
101                                     int muxval)
102 {
103         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
104         unsigned mux_bits, reg_stride, reg, reg_end, shift, mask;
105         bool load_pinctrl;
106         u32 tmp;
107
108         /* some pins need input-enabling */
109         uniphier_pinconf_input_enable(dev, pin);
110
111         if (muxval < 0)
112                 return;         /* dedicated pin; nothing to do for pin-mux */
113
114         if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) {
115                 /*
116                  *  Mode       offset        bit
117                  *  Normal     4 * n     shift+3:shift
118                  *  Debug      4 * n     shift+7:shift+4
119                  */
120                 mux_bits = 4;
121                 reg_stride = 8;
122                 load_pinctrl = true;
123         } else {
124                 /*
125                  *  Mode       offset           bit
126                  *  Normal     8 * n        shift+3:shift
127                  *  Debug      8 * n + 4    shift+3:shift
128                  */
129                 mux_bits = 8;
130                 reg_stride = 4;
131                 load_pinctrl = false;
132         }
133
134         reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
135         reg_end = reg + reg_stride;
136         shift = pin * mux_bits % 32;
137         mask = (1U << mux_bits) - 1;
138
139         /*
140          * If reg_stride is greater than 4, the MSB of each pinsel shall be
141          * stored in the offset+4.
142          */
143         for (; reg < reg_end; reg += 4) {
144                 tmp = readl(priv->base + reg);
145                 tmp &= ~(mask << shift);
146                 tmp |= (mask & muxval) << shift;
147                 writel(tmp, priv->base + reg);
148
149                 muxval >>= mux_bits;
150         }
151
152         if (load_pinctrl)
153                 writel(1, priv->base + UNIPHIER_PINCTRL_LOAD_PINMUX);
154 }
155
156 static int uniphier_pinmux_group_set(struct udevice *dev,
157                                      unsigned group_selector,
158                                      unsigned func_selector)
159 {
160         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
161         const struct uniphier_pinctrl_group *grp =
162                                         &priv->socdata->groups[group_selector];
163         int i;
164
165         for (i = 0; i < grp->num_pins; i++)
166                 uniphier_pinmux_set_one(dev, grp->pins[i], grp->muxvals[i]);
167
168         return 0;
169 }
170
171 const struct pinctrl_ops uniphier_pinctrl_ops = {
172         .get_groups_count = uniphier_pinctrl_get_groups_count,
173         .get_group_name = uniphier_pinctrl_get_group_name,
174         .get_functions_count = uniphier_pinmux_get_functions_count,
175         .get_function_name = uniphier_pinmux_get_function_name,
176         .pinmux_group_set = uniphier_pinmux_group_set,
177         .set_state = pinctrl_generic_set_state,
178 };
179
180 int uniphier_pinctrl_probe(struct udevice *dev,
181                            struct uniphier_pinctrl_socdata *socdata)
182 {
183         struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
184         fdt_addr_t addr;
185
186         addr = dev_get_addr(dev->parent);
187         if (addr == FDT_ADDR_T_NONE)
188                 return -EINVAL;
189
190         priv->base = devm_ioremap(dev, addr, SZ_4K);
191         if (!priv->base)
192                 return -ENOMEM;
193
194         priv->socdata = socdata;
195
196         return 0;
197 }