1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /*
3 * Microsemi SoCs pinctrl driver
4 *
5 * Author: <alexandre.belloni@free-electrons.com>
6 * Author: <gregory.clement@bootlin.com>
7 * License: Dual MIT/GPL
8 * Copyright (c) 2017 Microsemi Corporation
9 */
10
11 #include <asm/gpio.h>
12 #include <asm/system.h>
13 #include <common.h>
14 #include <config.h>
15 #include <dm.h>
16 #include <dm/device-internal.h>
17 #include <dm/device_compat.h>
18 #include <dm/devres.h>
19 #include <dm/lists.h>
20 #include <dm/pinctrl.h>
21 #include <dm/root.h>
22 #include <errno.h>
23 #include <fdtdec.h>
24 #include <linux/bitops.h>
25 #include <linux/io.h>
26 #include "mscc-common.h"
27
mscc_writel(unsigned int offset,void * addr)28 static void mscc_writel(unsigned int offset, void *addr)
29 {
30 if (offset < 32)
31 writel(BIT(offset), addr);
32 else
33 writel(BIT(offset % 32), addr + 4);
34 }
35
mscc_readl(unsigned int offset,void * addr)36 static unsigned int mscc_readl(unsigned int offset, void *addr)
37 {
38 if (offset < 32)
39 return readl(addr);
40 else
41 return readl(addr + 4);
42 }
43
mscc_setbits(unsigned int offset,void * addr)44 static void mscc_setbits(unsigned int offset, void *addr)
45 {
46 if (offset < 32)
47 writel(readl(addr) | BIT(offset), addr);
48 else
49 writel(readl(addr + 4) | BIT(offset % 32), addr + 4);
50 }
51
mscc_clrbits(unsigned int offset,void * addr)52 static void mscc_clrbits(unsigned int offset, void *addr)
53 {
54 if (offset < 32)
55 writel(readl(addr) & ~BIT(offset), addr);
56 else
57 writel(readl(addr + 4) & ~BIT(offset % 32), addr + 4);
58 }
59
mscc_get_functions_count(struct udevice * dev)60 static int mscc_get_functions_count(struct udevice *dev)
61 {
62 struct mscc_pinctrl *info = dev_get_priv(dev);
63
64 return info->num_func;
65 }
66
mscc_get_function_name(struct udevice * dev,unsigned int function)67 static const char *mscc_get_function_name(struct udevice *dev,
68 unsigned int function)
69 {
70 struct mscc_pinctrl *info = dev_get_priv(dev);
71
72 return info->function_names[function];
73 }
74
mscc_pin_function_idx(unsigned int pin,unsigned int function,const struct mscc_pin_data * mscc_pins)75 static int mscc_pin_function_idx(unsigned int pin, unsigned int function,
76 const struct mscc_pin_data *mscc_pins)
77 {
78 struct mscc_pin_caps *p = mscc_pins[pin].drv_data;
79 int i;
80
81 for (i = 0; i < MSCC_FUNC_PER_PIN; i++) {
82 if (function == p->functions[i])
83 return i;
84 }
85
86 return -1;
87 }
88
mscc_pinmux_set_mux(struct udevice * dev,unsigned int pin_selector,unsigned int selector)89 static int mscc_pinmux_set_mux(struct udevice *dev,
90 unsigned int pin_selector, unsigned int selector)
91 {
92 struct mscc_pinctrl *info = dev_get_priv(dev);
93 struct mscc_pin_caps *pin = info->mscc_pins[pin_selector].drv_data;
94 int f, offset, regoff;
95
96 f = mscc_pin_function_idx(pin_selector, selector, info->mscc_pins);
97 if (f < 0)
98 return -EINVAL;
99 /*
100 * f is encoded on two bits.
101 * bit 0 of f goes in BIT(pin) of ALT0, bit 1 of f goes in BIT(pin) of
102 * ALT1
103 * This is racy because both registers can't be updated at the same time
104 * but it doesn't matter much for now.
105 */
106 offset = pin->pin;
107 regoff = info->mscc_gpios[MSCC_GPIO_ALT0];
108 if (offset >= 32) {
109 offset = offset % 32;
110 regoff = info->mscc_gpios[MSCC_GPIO_ALT1];
111 }
112
113 if (f & BIT(0))
114 mscc_setbits(offset, info->regs + regoff);
115 else
116 mscc_clrbits(offset, info->regs + regoff);
117
118 if (f & BIT(1))
119 mscc_setbits(offset, info->regs + regoff + 4);
120 else
121 mscc_clrbits(offset, info->regs + regoff + 4);
122
123 return 0;
124 }
125
mscc_pctl_get_groups_count(struct udevice * dev)126 static int mscc_pctl_get_groups_count(struct udevice *dev)
127 {
128 struct mscc_pinctrl *info = dev_get_priv(dev);
129
130 return info->num_pins;
131 }
132
mscc_pctl_get_group_name(struct udevice * dev,unsigned int group)133 static const char *mscc_pctl_get_group_name(struct udevice *dev,
134 unsigned int group)
135 {
136 struct mscc_pinctrl *info = dev_get_priv(dev);
137
138 return info->mscc_pins[group].name;
139 }
140
mscc_create_group_func_map(struct udevice * dev,struct mscc_pinctrl * info)141 static int mscc_create_group_func_map(struct udevice *dev,
142 struct mscc_pinctrl *info)
143 {
144 u16 pins[info->num_pins];
145 int f, npins, i;
146
147 for (f = 0; f < info->num_func; f++) {
148 for (npins = 0, i = 0; i < info->num_pins; i++) {
149 if (mscc_pin_function_idx(i, f, info->mscc_pins) >= 0)
150 pins[npins++] = i;
151 }
152
153 info->func[f].ngroups = npins;
154 info->func[f].groups = devm_kzalloc(dev, npins * sizeof(char *),
155 GFP_KERNEL);
156 if (!info->func[f].groups)
157 return -ENOMEM;
158
159 for (i = 0; i < npins; i++)
160 info->func[f].groups[i] = info->mscc_pins[pins[i]].name;
161 }
162
163 return 0;
164 }
165
mscc_pinctrl_register(struct udevice * dev,struct mscc_pinctrl * info)166 static int mscc_pinctrl_register(struct udevice *dev, struct mscc_pinctrl *info)
167 {
168 int ret;
169
170 ret = mscc_create_group_func_map(dev, info);
171 if (ret) {
172 dev_err(dev, "Unable to create group func map.\n");
173 return ret;
174 }
175
176 return 0;
177 }
178
mscc_gpio_get(struct udevice * dev,unsigned int offset)179 static int mscc_gpio_get(struct udevice *dev, unsigned int offset)
180 {
181 struct mscc_pinctrl *info = dev_get_priv(dev->parent);
182 unsigned int val;
183
184 if (mscc_readl(offset, info->regs + info->mscc_gpios[MSCC_GPIO_OE]) &
185 BIT(offset % 32))
186 val = mscc_readl(offset,
187 info->regs + info->mscc_gpios[MSCC_GPIO_OUT]);
188 else
189 val = mscc_readl(offset,
190 info->regs + info->mscc_gpios[MSCC_GPIO_IN]);
191
192 return !!(val & BIT(offset % 32));
193 }
194
mscc_gpio_set(struct udevice * dev,unsigned int offset,int value)195 static int mscc_gpio_set(struct udevice *dev, unsigned int offset, int value)
196 {
197 struct mscc_pinctrl *info = dev_get_priv(dev->parent);
198
199 if (value)
200 mscc_writel(offset,
201 info->regs + info->mscc_gpios[MSCC_GPIO_OUT_SET]);
202 else
203 mscc_writel(offset,
204 info->regs + info->mscc_gpios[MSCC_GPIO_OUT_CLR]);
205
206 return 0;
207 }
208
mscc_gpio_get_direction(struct udevice * dev,unsigned int offset)209 static int mscc_gpio_get_direction(struct udevice *dev, unsigned int offset)
210 {
211 struct mscc_pinctrl *info = dev_get_priv(dev->parent);
212 unsigned int val;
213
214 val = mscc_readl(offset, info->regs + info->mscc_gpios[MSCC_GPIO_OE]);
215
216 return (val & BIT(offset % 32)) ? GPIOF_OUTPUT : GPIOF_INPUT;
217 }
218
mscc_gpio_direction_input(struct udevice * dev,unsigned int offset)219 static int mscc_gpio_direction_input(struct udevice *dev, unsigned int offset)
220 {
221 struct mscc_pinctrl *info = dev_get_priv(dev->parent);
222
223 mscc_clrbits(offset, info->regs + info->mscc_gpios[MSCC_GPIO_OE]);
224
225 return 0;
226 }
227
mscc_gpio_direction_output(struct udevice * dev,unsigned int offset,int value)228 static int mscc_gpio_direction_output(struct udevice *dev,
229 unsigned int offset, int value)
230 {
231 struct mscc_pinctrl *info = dev_get_priv(dev->parent);
232
233 mscc_setbits(offset, info->regs + info->mscc_gpios[MSCC_GPIO_OE]);
234
235 return mscc_gpio_set(dev, offset, value);
236 }
237
238 const struct dm_gpio_ops mscc_gpio_ops = {
239 .set_value = mscc_gpio_set,
240 .get_value = mscc_gpio_get,
241 .get_function = mscc_gpio_get_direction,
242 .direction_input = mscc_gpio_direction_input,
243 .direction_output = mscc_gpio_direction_output,
244 };
245
246 const struct pinctrl_ops mscc_pinctrl_ops = {
247 .get_pins_count = mscc_pctl_get_groups_count,
248 .get_pin_name = mscc_pctl_get_group_name,
249 .get_functions_count = mscc_get_functions_count,
250 .get_function_name = mscc_get_function_name,
251 .pinmux_set = mscc_pinmux_set_mux,
252 .set_state = pinctrl_generic_set_state,
253 };
254
mscc_pinctrl_probe(struct udevice * dev,int num_func,const struct mscc_pin_data * mscc_pins,int num_pins,char * const * function_names,const unsigned long * mscc_gpios)255 int mscc_pinctrl_probe(struct udevice *dev, int num_func,
256 const struct mscc_pin_data *mscc_pins, int num_pins,
257 char * const *function_names,
258 const unsigned long *mscc_gpios)
259 {
260 struct mscc_pinctrl *priv = dev_get_priv(dev);
261 int ret;
262
263 priv->regs = dev_remap_addr(dev);
264 if (!priv->regs)
265 return -EINVAL;
266
267 priv->func = devm_kzalloc(dev, num_func * sizeof(struct mscc_pmx_func),
268 GFP_KERNEL);
269 priv->num_func = num_func;
270 priv->mscc_pins = mscc_pins;
271 priv->num_pins = num_pins;
272 priv->function_names = function_names;
273 priv->mscc_gpios = mscc_gpios;
274 ret = mscc_pinctrl_register(dev, priv);
275
276 return ret;
277 }
278