blob: bb63da373900276174bc82e032cb66c0944a99c7 [file] [log] [blame]
Vikas Manocha94d53082017-02-12 10:25:49 -08001#include <common.h>
Vikas Manocha94d53082017-02-12 10:25:49 -08002#include <dm.h>
3#include <dm/pinctrl.h>
Benjamin Gaignard075b0182018-11-27 13:49:53 +01004#include <hwspinlock.h>
Vikas Manocha77417102017-04-10 15:02:57 -07005#include <asm/arch/gpio.h>
6#include <asm/gpio.h>
7#include <asm/io.h>
Vikas Manocha94d53082017-02-12 10:25:49 -08008
9DECLARE_GLOBAL_DATA_PTR;
10
Vikas Manocha58fb3c82017-04-10 15:03:04 -070011#define MAX_PINS_ONE_IP 70
Vikas Manocha77417102017-04-10 15:02:57 -070012#define MODE_BITS_MASK 3
13#define OSPEED_MASK 3
14#define PUPD_MASK 3
15#define OTYPE_MSK 1
16#define AFR_MASK 0xF
17
Patrice Chotard8f651ca2018-10-24 14:10:18 +020018struct stm32_pinctrl_priv {
Benjamin Gaignard075b0182018-11-27 13:49:53 +010019 struct hwspinlock hws;
Patrice Chotard8f651ca2018-10-24 14:10:18 +020020 int pinctrl_ngpios;
21 struct list_head gpio_dev;
22};
23
24struct stm32_gpio_bank {
25 struct udevice *gpio_dev;
26 struct list_head list;
27};
28
Benjamin Gaignard075b0182018-11-27 13:49:53 +010029#ifndef CONFIG_SPL_BUILD
30
Patrice Chotard4ff1c202018-10-24 14:10:19 +020031#define MAX_PIN_PER_BANK 16
32
33static char pin_name[PINNAME_SIZE];
Patrice Chotardb42d9382018-10-24 14:10:20 +020034#define PINMUX_MODE_COUNT 5
35static const char * const pinmux_mode[PINMUX_MODE_COUNT] = {
36 "gpio input",
37 "gpio output",
38 "analog",
39 "unknown",
40 "alt function",
41};
42
43static int stm32_pinctrl_get_af(struct udevice *dev, unsigned int offset)
44{
45 struct stm32_gpio_priv *priv = dev_get_priv(dev);
46 struct stm32_gpio_regs *regs = priv->regs;
47 u32 af;
48 u32 alt_shift = (offset % 8) * 4;
49 u32 alt_index = offset / 8;
50
51 af = (readl(&regs->afr[alt_index]) &
52 GENMASK(alt_shift + 3, alt_shift)) >> alt_shift;
53
54 return af;
55}
56
Patrice Chotard8f651ca2018-10-24 14:10:18 +020057static int stm32_pinctrl_get_pins_count(struct udevice *dev)
58{
59 struct stm32_pinctrl_priv *priv = dev_get_priv(dev);
60 struct gpio_dev_priv *uc_priv;
61 struct stm32_gpio_bank *gpio_bank;
62
63 /*
64 * if get_pins_count has already been executed once on this
65 * pin-controller, no need to run it again
66 */
67 if (priv->pinctrl_ngpios)
68 return priv->pinctrl_ngpios;
69
70 /*
71 * walk through all banks to retrieve the pin-controller
72 * pins number
73 */
74 list_for_each_entry(gpio_bank, &priv->gpio_dev, list) {
75 uc_priv = dev_get_uclass_priv(gpio_bank->gpio_dev);
76
77 priv->pinctrl_ngpios += uc_priv->gpio_count;
78 }
79
80 return priv->pinctrl_ngpios;
81}
82
Patrice Chotard4ff1c202018-10-24 14:10:19 +020083static struct udevice *stm32_pinctrl_get_gpio_dev(struct udevice *dev,
84 unsigned int selector)
85{
86 struct stm32_pinctrl_priv *priv = dev_get_priv(dev);
87 struct stm32_gpio_bank *gpio_bank;
88 struct gpio_dev_priv *uc_priv;
89 int first_pin = 0;
90
91 /* look up for the bank which owns the requested pin */
92 list_for_each_entry(gpio_bank, &priv->gpio_dev, list) {
93 uc_priv = dev_get_uclass_priv(gpio_bank->gpio_dev);
94
95 if (selector < (first_pin + uc_priv->gpio_count))
96 /* we found the bank */
97 return gpio_bank->gpio_dev;
98
99 first_pin += uc_priv->gpio_count;
100 }
101
102 return NULL;
103}
104
105static const char *stm32_pinctrl_get_pin_name(struct udevice *dev,
106 unsigned int selector)
107{
108 struct gpio_dev_priv *uc_priv;
109 struct udevice *gpio_dev;
110
111 /* look up for the bank which owns the requested pin */
112 gpio_dev = stm32_pinctrl_get_gpio_dev(dev, selector);
113 if (!gpio_dev) {
114 snprintf(pin_name, PINNAME_SIZE, "Error");
115 } else {
116 uc_priv = dev_get_uclass_priv(gpio_dev);
117
118 snprintf(pin_name, PINNAME_SIZE, "%s%d",
119 uc_priv->bank_name,
120 selector % MAX_PIN_PER_BANK);
121 }
122
123 return pin_name;
124}
Patrice Chotardb42d9382018-10-24 14:10:20 +0200125
126static int stm32_pinctrl_get_pin_muxing(struct udevice *dev,
127 unsigned int selector,
128 char *buf,
129 int size)
130{
131 struct udevice *gpio_dev;
132 const char *label;
133 int gpio_pin;
134 int mode;
135 int af_num;
136
137 /* look up for the bank which owns the requested pin */
138 gpio_dev = stm32_pinctrl_get_gpio_dev(dev, selector);
139
140 if (!gpio_dev)
141 return -ENODEV;
142
143 /* translate pin-controller pin number to gpio pin number */
144 gpio_pin = selector % MAX_PIN_PER_BANK;
145
146 mode = gpio_get_raw_function(gpio_dev, gpio_pin, &label);
147
148 dev_dbg(dev, "selector = %d gpio_pin = %d mode = %d\n",
149 selector, gpio_pin, mode);
150
151 switch (mode) {
152 case GPIOF_UNKNOWN:
153 /* should never happen */
154 return -EINVAL;
155 case GPIOF_UNUSED:
156 snprintf(buf, size, "%s", pinmux_mode[mode]);
157 break;
158 case GPIOF_FUNC:
159 af_num = stm32_pinctrl_get_af(gpio_dev, gpio_pin);
160 snprintf(buf, size, "%s %d", pinmux_mode[mode], af_num);
161 break;
162 case GPIOF_OUTPUT:
163 case GPIOF_INPUT:
164 snprintf(buf, size, "%s %s",
165 pinmux_mode[mode], label ? label : "");
166 break;
167 }
168
169 return 0;
170}
171
Benjamin Gaignard075b0182018-11-27 13:49:53 +0100172#endif
173
Patrice Chotard8f651ca2018-10-24 14:10:18 +0200174int stm32_pinctrl_probe(struct udevice *dev)
175{
176 struct stm32_pinctrl_priv *priv = dev_get_priv(dev);
177 struct udevice *gpio_dev;
178 struct udevice *child;
179 struct stm32_gpio_bank *gpio_bank;
180 int ret;
181
182 INIT_LIST_HEAD(&priv->gpio_dev);
183
184 /*
185 * parse pin-controller sub-nodes (ie gpio bank nodes) and fill
186 * a list with all gpio device reference which belongs to the
187 * current pin-controller. This list is used to find pin_name and
188 * pin muxing
189 */
190 list_for_each_entry(child, &dev->child_head, sibling_node) {
191 ret = uclass_get_device_by_name(UCLASS_GPIO, child->name,
192 &gpio_dev);
193 if (ret < 0)
194 continue;
195
196 gpio_bank = malloc(sizeof(*gpio_bank));
197 if (!gpio_bank) {
198 dev_err(dev, "Not enough memory\n");
199 return -ENOMEM;
200 }
201
202 gpio_bank->gpio_dev = gpio_dev;
203 list_add_tail(&gpio_bank->list, &priv->gpio_dev);
204 }
205
Benjamin Gaignard075b0182018-11-27 13:49:53 +0100206 /* hwspinlock property is optional, just log the error */
207 ret = hwspinlock_get_by_index(dev, 0, &priv->hws);
208 if (ret)
209 debug("%s: hwspinlock_get_by_index may have failed (%d)\n",
210 __func__, ret);
211
Patrice Chotard8f651ca2018-10-24 14:10:18 +0200212 return 0;
213}
Patrice Chotard8f651ca2018-10-24 14:10:18 +0200214
Vikas Manocha77417102017-04-10 15:02:57 -0700215static int stm32_gpio_config(struct gpio_desc *desc,
216 const struct stm32_gpio_ctl *ctl)
217{
218 struct stm32_gpio_priv *priv = dev_get_priv(desc->dev);
219 struct stm32_gpio_regs *regs = priv->regs;
Benjamin Gaignard075b0182018-11-27 13:49:53 +0100220 struct stm32_pinctrl_priv *ctrl_priv;
221 int ret;
Vikas Manocha77417102017-04-10 15:02:57 -0700222 u32 index;
223
224 if (!ctl || ctl->af > 15 || ctl->mode > 3 || ctl->otype > 1 ||
225 ctl->pupd > 2 || ctl->speed > 3)
226 return -EINVAL;
227
Benjamin Gaignard075b0182018-11-27 13:49:53 +0100228 ctrl_priv = dev_get_priv(dev_get_parent(desc->dev));
229 ret = hwspinlock_lock_timeout(&ctrl_priv->hws, 10);
230 if (ret == -ETIME) {
231 dev_err(desc->dev, "HWSpinlock timeout\n");
232 return ret;
233 }
234
Vikas Manocha77417102017-04-10 15:02:57 -0700235 index = (desc->offset & 0x07) * 4;
236 clrsetbits_le32(&regs->afr[desc->offset >> 3], AFR_MASK << index,
237 ctl->af << index);
238
239 index = desc->offset * 2;
240 clrsetbits_le32(&regs->moder, MODE_BITS_MASK << index,
241 ctl->mode << index);
242 clrsetbits_le32(&regs->ospeedr, OSPEED_MASK << index,
243 ctl->speed << index);
244 clrsetbits_le32(&regs->pupdr, PUPD_MASK << index, ctl->pupd << index);
245
246 index = desc->offset;
247 clrsetbits_le32(&regs->otyper, OTYPE_MSK << index, ctl->otype << index);
248
Benjamin Gaignard075b0182018-11-27 13:49:53 +0100249 hwspinlock_unlock(&ctrl_priv->hws);
250
Vikas Manocha77417102017-04-10 15:02:57 -0700251 return 0;
252}
Patrick Delaunay8aeba622018-03-12 10:46:13 +0100253
Vikas Manocha94d53082017-02-12 10:25:49 -0800254static int prep_gpio_dsc(struct stm32_gpio_dsc *gpio_dsc, u32 port_pin)
255{
Patrick Delaunay8aeba622018-03-12 10:46:13 +0100256 gpio_dsc->port = (port_pin & 0x1F000) >> 12;
Vikas Manocha94d53082017-02-12 10:25:49 -0800257 gpio_dsc->pin = (port_pin & 0x0F00) >> 8;
258 debug("%s: GPIO:port= %d, pin= %d\n", __func__, gpio_dsc->port,
259 gpio_dsc->pin);
260
261 return 0;
262}
263
264static int prep_gpio_ctl(struct stm32_gpio_ctl *gpio_ctl, u32 gpio_fn, int node)
265{
266 gpio_fn &= 0x00FF;
Vikas Manocha77417102017-04-10 15:02:57 -0700267 gpio_ctl->af = 0;
Vikas Manocha94d53082017-02-12 10:25:49 -0800268
269 switch (gpio_fn) {
270 case 0:
271 gpio_ctl->mode = STM32_GPIO_MODE_IN;
272 break;
273 case 1 ... 16:
274 gpio_ctl->mode = STM32_GPIO_MODE_AF;
275 gpio_ctl->af = gpio_fn - 1;
276 break;
277 case 17:
278 gpio_ctl->mode = STM32_GPIO_MODE_AN;
279 break;
280 default:
281 gpio_ctl->mode = STM32_GPIO_MODE_OUT;
282 break;
283 }
284
285 gpio_ctl->speed = fdtdec_get_int(gd->fdt_blob, node, "slew-rate", 0);
286
287 if (fdtdec_get_bool(gd->fdt_blob, node, "drive-open-drain"))
288 gpio_ctl->otype = STM32_GPIO_OTYPE_OD;
289 else
290 gpio_ctl->otype = STM32_GPIO_OTYPE_PP;
291
292 if (fdtdec_get_bool(gd->fdt_blob, node, "bias-pull-up"))
293 gpio_ctl->pupd = STM32_GPIO_PUPD_UP;
294 else if (fdtdec_get_bool(gd->fdt_blob, node, "bias-pull-down"))
295 gpio_ctl->pupd = STM32_GPIO_PUPD_DOWN;
296 else
297 gpio_ctl->pupd = STM32_GPIO_PUPD_NO;
298
299 debug("%s: gpio fn= %d, slew-rate= %x, op type= %x, pull-upd is = %x\n",
300 __func__, gpio_fn, gpio_ctl->speed, gpio_ctl->otype,
301 gpio_ctl->pupd);
302
303 return 0;
304}
305
Christophe Kerelload0376e2017-06-20 17:04:18 +0200306static int stm32_pinctrl_config(int offset)
Vikas Manocha94d53082017-02-12 10:25:49 -0800307{
Vikas Manocha58fb3c82017-04-10 15:03:04 -0700308 u32 pin_mux[MAX_PINS_ONE_IP];
Vikas Manocha94d53082017-02-12 10:25:49 -0800309 int rv, len;
310
Vikas Manocha94d53082017-02-12 10:25:49 -0800311 /*
312 * check for "pinmux" property in each subnode (e.g. pins1 and pins2 for
313 * usart1) of pin controller phandle "pinctrl-0"
314 * */
Christophe Kerelload0376e2017-06-20 17:04:18 +0200315 fdt_for_each_subnode(offset, gd->fdt_blob, offset) {
Vikas Manocha94d53082017-02-12 10:25:49 -0800316 struct stm32_gpio_dsc gpio_dsc;
317 struct stm32_gpio_ctl gpio_ctl;
318 int i;
319
Christophe Kerelload0376e2017-06-20 17:04:18 +0200320 len = fdtdec_get_int_array_count(gd->fdt_blob, offset,
Vikas Manocha94d53082017-02-12 10:25:49 -0800321 "pinmux", pin_mux,
322 ARRAY_SIZE(pin_mux));
Christophe Kerelload0376e2017-06-20 17:04:18 +0200323 debug("%s: no of pinmux entries= %d\n", __func__, len);
Vikas Manocha94d53082017-02-12 10:25:49 -0800324 if (len < 0)
325 return -EINVAL;
326 for (i = 0; i < len; i++) {
Vikas Manocha280057b2017-04-10 15:02:59 -0700327 struct gpio_desc desc;
Patrick Delaunay8aeba622018-03-12 10:46:13 +0100328
Vikas Manocha94d53082017-02-12 10:25:49 -0800329 debug("%s: pinmux = %x\n", __func__, *(pin_mux + i));
330 prep_gpio_dsc(&gpio_dsc, *(pin_mux + i));
Christophe Kerelload0376e2017-06-20 17:04:18 +0200331 prep_gpio_ctl(&gpio_ctl, *(pin_mux + i), offset);
Vikas Manocha280057b2017-04-10 15:02:59 -0700332 rv = uclass_get_device_by_seq(UCLASS_GPIO,
Patrick Delaunay8aeba622018-03-12 10:46:13 +0100333 gpio_dsc.port,
334 &desc.dev);
Vikas Manocha280057b2017-04-10 15:02:59 -0700335 if (rv)
336 return rv;
337 desc.offset = gpio_dsc.pin;
338 rv = stm32_gpio_config(&desc, &gpio_ctl);
Vikas Manocha94d53082017-02-12 10:25:49 -0800339 debug("%s: rv = %d\n\n", __func__, rv);
340 if (rv)
341 return rv;
342 }
343 }
344
345 return 0;
346}
347
Christophe Kerellobb44b962017-06-20 17:04:19 +0200348#if CONFIG_IS_ENABLED(PINCTRL_FULL)
349static int stm32_pinctrl_set_state(struct udevice *dev, struct udevice *config)
350{
351 return stm32_pinctrl_config(dev_of_offset(config));
352}
353#else /* PINCTRL_FULL */
Christophe Kerelload0376e2017-06-20 17:04:18 +0200354static int stm32_pinctrl_set_state_simple(struct udevice *dev,
355 struct udevice *periph)
356{
357 const void *fdt = gd->fdt_blob;
358 const fdt32_t *list;
359 uint32_t phandle;
360 int config_node;
361 int size, i, ret;
362
363 list = fdt_getprop(fdt, dev_of_offset(periph), "pinctrl-0", &size);
364 if (!list)
365 return -EINVAL;
366
367 debug("%s: periph->name = %s\n", __func__, periph->name);
368
369 size /= sizeof(*list);
370 for (i = 0; i < size; i++) {
371 phandle = fdt32_to_cpu(*list++);
372
373 config_node = fdt_node_offset_by_phandle(fdt, phandle);
374 if (config_node < 0) {
Masahiro Yamada9b643e32017-09-16 14:10:41 +0900375 pr_err("prop pinctrl-0 index %d invalid phandle\n", i);
Christophe Kerelload0376e2017-06-20 17:04:18 +0200376 return -EINVAL;
377 }
378
379 ret = stm32_pinctrl_config(config_node);
380 if (ret)
381 return ret;
382 }
383
384 return 0;
385}
Christophe Kerellobb44b962017-06-20 17:04:19 +0200386#endif /* PINCTRL_FULL */
Christophe Kerelload0376e2017-06-20 17:04:18 +0200387
Vikas Manocha94d53082017-02-12 10:25:49 -0800388static struct pinctrl_ops stm32_pinctrl_ops = {
Christophe Kerellobb44b962017-06-20 17:04:19 +0200389#if CONFIG_IS_ENABLED(PINCTRL_FULL)
390 .set_state = stm32_pinctrl_set_state,
391#else /* PINCTRL_FULL */
Vikas Manocha94d53082017-02-12 10:25:49 -0800392 .set_state_simple = stm32_pinctrl_set_state_simple,
Christophe Kerellobb44b962017-06-20 17:04:19 +0200393#endif /* PINCTRL_FULL */
Patrice Chotard8f651ca2018-10-24 14:10:18 +0200394#ifndef CONFIG_SPL_BUILD
Patrice Chotard4ff1c202018-10-24 14:10:19 +0200395 .get_pin_name = stm32_pinctrl_get_pin_name,
Patrice Chotard8f651ca2018-10-24 14:10:18 +0200396 .get_pins_count = stm32_pinctrl_get_pins_count,
Patrice Chotardb42d9382018-10-24 14:10:20 +0200397 .get_pin_muxing = stm32_pinctrl_get_pin_muxing,
Patrice Chotard8f651ca2018-10-24 14:10:18 +0200398#endif
Vikas Manocha94d53082017-02-12 10:25:49 -0800399};
400
401static const struct udevice_id stm32_pinctrl_ids[] = {
Patrice Chotard98693c22017-12-12 09:49:35 +0100402 { .compatible = "st,stm32f429-pinctrl" },
403 { .compatible = "st,stm32f469-pinctrl" },
Vikas Manocha94d53082017-02-12 10:25:49 -0800404 { .compatible = "st,stm32f746-pinctrl" },
Patrice Chotard092e72c2017-09-13 18:00:04 +0200405 { .compatible = "st,stm32h743-pinctrl" },
Patrick Delaunay8aeba622018-03-12 10:46:13 +0100406 { .compatible = "st,stm32mp157-pinctrl" },
407 { .compatible = "st,stm32mp157-z-pinctrl" },
Vikas Manocha94d53082017-02-12 10:25:49 -0800408 { }
409};
410
411U_BOOT_DRIVER(pinctrl_stm32) = {
Patrice Chotard8f651ca2018-10-24 14:10:18 +0200412 .name = "pinctrl_stm32",
413 .id = UCLASS_PINCTRL,
414 .of_match = stm32_pinctrl_ids,
415 .ops = &stm32_pinctrl_ops,
416 .bind = dm_scan_fdt_dev,
Patrice Chotard8f651ca2018-10-24 14:10:18 +0200417 .probe = stm32_pinctrl_probe,
418 .priv_auto_alloc_size = sizeof(struct stm32_pinctrl_priv),
Vikas Manocha94d53082017-02-12 10:25:49 -0800419};