1
2
3
4
5
6
7#include <common.h>
8#include <mapmem.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
17static const char *uniphier_pinctrl_dummy_name = "_dummy";
18
19static int uniphier_pinctrl_get_groups_count(struct udevice *dev)
20{
21 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
22
23 return priv->socdata->groups_count;
24}
25
26static const char *uniphier_pinctrl_get_group_name(struct udevice *dev,
27 unsigned selector)
28{
29 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
30
31 if (!priv->socdata->groups[selector].name)
32 return uniphier_pinctrl_dummy_name;
33
34 return priv->socdata->groups[selector].name;
35}
36
37static int uniphier_pinmux_get_functions_count(struct udevice *dev)
38{
39 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
40
41 return priv->socdata->functions_count;
42}
43
44static const char *uniphier_pinmux_get_function_name(struct udevice *dev,
45 unsigned selector)
46{
47 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
48
49 if (!priv->socdata->functions[selector])
50 return uniphier_pinctrl_dummy_name;
51
52 return priv->socdata->functions[selector];
53}
54
55static void uniphier_pinconf_input_enable_perpin(struct udevice *dev,
56 unsigned pin)
57{
58 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
59 unsigned reg;
60 u32 mask, tmp;
61
62 reg = UNIPHIER_PINCTRL_IECTRL + pin / 32 * 4;
63 mask = BIT(pin % 32);
64
65 tmp = readl(priv->base + reg);
66 tmp |= mask;
67 writel(tmp, priv->base + reg);
68}
69
70static void uniphier_pinconf_input_enable_legacy(struct udevice *dev,
71 unsigned pin)
72{
73 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
74 int pins_count = priv->socdata->pins_count;
75 const struct uniphier_pinctrl_pin *pins = priv->socdata->pins;
76 int i;
77
78 for (i = 0; i < pins_count; i++) {
79 if (pins[i].number == pin) {
80 unsigned int iectrl;
81 u32 tmp;
82
83 iectrl = uniphier_pin_get_iectrl(pins[i].data);
84 tmp = readl(priv->base + UNIPHIER_PINCTRL_IECTRL);
85 tmp |= 1 << iectrl;
86 writel(tmp, priv->base + UNIPHIER_PINCTRL_IECTRL);
87 }
88 }
89}
90
91static void uniphier_pinconf_input_enable(struct udevice *dev, unsigned pin)
92{
93 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
94
95 if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_PERPIN_IECTRL)
96 uniphier_pinconf_input_enable_perpin(dev, pin);
97 else
98 uniphier_pinconf_input_enable_legacy(dev, pin);
99}
100
101static void uniphier_pinmux_set_one(struct udevice *dev, unsigned pin,
102 int muxval)
103{
104 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
105 unsigned mux_bits, reg_stride, reg, reg_end, shift, mask;
106 bool load_pinctrl;
107 u32 tmp;
108
109
110 uniphier_pinconf_input_enable(dev, pin);
111
112 if (muxval < 0)
113 return;
114
115 if (priv->socdata->caps & UNIPHIER_PINCTRL_CAPS_DBGMUX_SEPARATE) {
116
117
118
119
120
121 mux_bits = 4;
122 reg_stride = 8;
123 load_pinctrl = true;
124 } else {
125
126
127
128
129
130 mux_bits = 8;
131 reg_stride = 4;
132 load_pinctrl = false;
133 }
134
135 reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
136 reg_end = reg + reg_stride;
137 shift = pin * mux_bits % 32;
138 mask = (1U << mux_bits) - 1;
139
140
141
142
143
144 for (; reg < reg_end; reg += 4) {
145 tmp = readl(priv->base + reg);
146 tmp &= ~(mask << shift);
147 tmp |= (mask & muxval) << shift;
148 writel(tmp, priv->base + reg);
149
150 muxval >>= mux_bits;
151 }
152
153 if (load_pinctrl)
154 writel(1, priv->base + UNIPHIER_PINCTRL_LOAD_PINMUX);
155}
156
157static int uniphier_pinmux_group_set(struct udevice *dev,
158 unsigned group_selector,
159 unsigned func_selector)
160{
161 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
162 const struct uniphier_pinctrl_group *grp =
163 &priv->socdata->groups[group_selector];
164 int i;
165
166 for (i = 0; i < grp->num_pins; i++)
167 uniphier_pinmux_set_one(dev, grp->pins[i], grp->muxvals[i]);
168
169 return 0;
170}
171
172const struct pinctrl_ops uniphier_pinctrl_ops = {
173 .get_groups_count = uniphier_pinctrl_get_groups_count,
174 .get_group_name = uniphier_pinctrl_get_group_name,
175 .get_functions_count = uniphier_pinmux_get_functions_count,
176 .get_function_name = uniphier_pinmux_get_function_name,
177 .pinmux_group_set = uniphier_pinmux_group_set,
178 .set_state = pinctrl_generic_set_state,
179};
180
181int uniphier_pinctrl_probe(struct udevice *dev,
182 struct uniphier_pinctrl_socdata *socdata)
183{
184 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
185 fdt_addr_t addr;
186
187 addr = dev_get_addr(dev->parent);
188 if (addr == FDT_ADDR_T_NONE)
189 return -EINVAL;
190
191 priv->base = map_sysmem(addr, SZ_4K);
192 if (!priv->base)
193 return -ENOMEM;
194
195 priv->socdata = socdata;
196
197 return 0;
198}
199
200int uniphier_pinctrl_remove(struct udevice *dev)
201{
202 struct uniphier_pinctrl_priv *priv = dev_get_priv(dev);
203
204 unmap_sysmem(priv->base);
205
206 return 0;
207}
208