]>
Commit | Line | Data |
---|---|---|
94d53084 | 1 | #include <common.h> |
94d53084 VM |
2 | #include <dm.h> |
3 | #include <dm/pinctrl.h> | |
77417102 VM |
4 | #include <asm/arch/gpio.h> |
5 | #include <asm/gpio.h> | |
6 | #include <asm/io.h> | |
94d53084 VM |
7 | |
8 | DECLARE_GLOBAL_DATA_PTR; | |
9 | ||
58fb3c8d | 10 | #define MAX_PINS_ONE_IP 70 |
77417102 VM |
11 | #define MODE_BITS_MASK 3 |
12 | #define OSPEED_MASK 3 | |
13 | #define PUPD_MASK 3 | |
14 | #define OTYPE_MSK 1 | |
15 | #define AFR_MASK 0xF | |
16 | ||
17 | static int stm32_gpio_config(struct gpio_desc *desc, | |
18 | const struct stm32_gpio_ctl *ctl) | |
19 | { | |
20 | struct stm32_gpio_priv *priv = dev_get_priv(desc->dev); | |
21 | struct stm32_gpio_regs *regs = priv->regs; | |
22 | u32 index; | |
23 | ||
24 | if (!ctl || ctl->af > 15 || ctl->mode > 3 || ctl->otype > 1 || | |
25 | ctl->pupd > 2 || ctl->speed > 3) | |
26 | return -EINVAL; | |
27 | ||
28 | index = (desc->offset & 0x07) * 4; | |
29 | clrsetbits_le32(®s->afr[desc->offset >> 3], AFR_MASK << index, | |
30 | ctl->af << index); | |
31 | ||
32 | index = desc->offset * 2; | |
33 | clrsetbits_le32(®s->moder, MODE_BITS_MASK << index, | |
34 | ctl->mode << index); | |
35 | clrsetbits_le32(®s->ospeedr, OSPEED_MASK << index, | |
36 | ctl->speed << index); | |
37 | clrsetbits_le32(®s->pupdr, PUPD_MASK << index, ctl->pupd << index); | |
38 | ||
39 | index = desc->offset; | |
40 | clrsetbits_le32(®s->otyper, OTYPE_MSK << index, ctl->otype << index); | |
41 | ||
42 | return 0; | |
43 | } | |
94d53084 VM |
44 | static int prep_gpio_dsc(struct stm32_gpio_dsc *gpio_dsc, u32 port_pin) |
45 | { | |
46 | gpio_dsc->port = (port_pin & 0xF000) >> 12; | |
47 | gpio_dsc->pin = (port_pin & 0x0F00) >> 8; | |
48 | debug("%s: GPIO:port= %d, pin= %d\n", __func__, gpio_dsc->port, | |
49 | gpio_dsc->pin); | |
50 | ||
51 | return 0; | |
52 | } | |
53 | ||
54 | static int prep_gpio_ctl(struct stm32_gpio_ctl *gpio_ctl, u32 gpio_fn, int node) | |
55 | { | |
56 | gpio_fn &= 0x00FF; | |
77417102 | 57 | gpio_ctl->af = 0; |
94d53084 VM |
58 | |
59 | switch (gpio_fn) { | |
60 | case 0: | |
61 | gpio_ctl->mode = STM32_GPIO_MODE_IN; | |
62 | break; | |
63 | case 1 ... 16: | |
64 | gpio_ctl->mode = STM32_GPIO_MODE_AF; | |
65 | gpio_ctl->af = gpio_fn - 1; | |
66 | break; | |
67 | case 17: | |
68 | gpio_ctl->mode = STM32_GPIO_MODE_AN; | |
69 | break; | |
70 | default: | |
71 | gpio_ctl->mode = STM32_GPIO_MODE_OUT; | |
72 | break; | |
73 | } | |
74 | ||
75 | gpio_ctl->speed = fdtdec_get_int(gd->fdt_blob, node, "slew-rate", 0); | |
76 | ||
77 | if (fdtdec_get_bool(gd->fdt_blob, node, "drive-open-drain")) | |
78 | gpio_ctl->otype = STM32_GPIO_OTYPE_OD; | |
79 | else | |
80 | gpio_ctl->otype = STM32_GPIO_OTYPE_PP; | |
81 | ||
82 | if (fdtdec_get_bool(gd->fdt_blob, node, "bias-pull-up")) | |
83 | gpio_ctl->pupd = STM32_GPIO_PUPD_UP; | |
84 | else if (fdtdec_get_bool(gd->fdt_blob, node, "bias-pull-down")) | |
85 | gpio_ctl->pupd = STM32_GPIO_PUPD_DOWN; | |
86 | else | |
87 | gpio_ctl->pupd = STM32_GPIO_PUPD_NO; | |
88 | ||
89 | debug("%s: gpio fn= %d, slew-rate= %x, op type= %x, pull-upd is = %x\n", | |
90 | __func__, gpio_fn, gpio_ctl->speed, gpio_ctl->otype, | |
91 | gpio_ctl->pupd); | |
92 | ||
93 | return 0; | |
94 | } | |
95 | ||
ad0376e0 | 96 | static int stm32_pinctrl_config(int offset) |
94d53084 | 97 | { |
58fb3c8d | 98 | u32 pin_mux[MAX_PINS_ONE_IP]; |
94d53084 VM |
99 | int rv, len; |
100 | ||
94d53084 VM |
101 | /* |
102 | * check for "pinmux" property in each subnode (e.g. pins1 and pins2 for | |
103 | * usart1) of pin controller phandle "pinctrl-0" | |
104 | * */ | |
ad0376e0 | 105 | fdt_for_each_subnode(offset, gd->fdt_blob, offset) { |
94d53084 VM |
106 | struct stm32_gpio_dsc gpio_dsc; |
107 | struct stm32_gpio_ctl gpio_ctl; | |
108 | int i; | |
109 | ||
ad0376e0 | 110 | len = fdtdec_get_int_array_count(gd->fdt_blob, offset, |
94d53084 VM |
111 | "pinmux", pin_mux, |
112 | ARRAY_SIZE(pin_mux)); | |
ad0376e0 | 113 | debug("%s: no of pinmux entries= %d\n", __func__, len); |
94d53084 VM |
114 | if (len < 0) |
115 | return -EINVAL; | |
116 | for (i = 0; i < len; i++) { | |
280057bd | 117 | struct gpio_desc desc; |
94d53084 VM |
118 | debug("%s: pinmux = %x\n", __func__, *(pin_mux + i)); |
119 | prep_gpio_dsc(&gpio_dsc, *(pin_mux + i)); | |
ad0376e0 | 120 | prep_gpio_ctl(&gpio_ctl, *(pin_mux + i), offset); |
280057bd VM |
121 | rv = uclass_get_device_by_seq(UCLASS_GPIO, |
122 | gpio_dsc.port, &desc.dev); | |
123 | if (rv) | |
124 | return rv; | |
125 | desc.offset = gpio_dsc.pin; | |
126 | rv = stm32_gpio_config(&desc, &gpio_ctl); | |
94d53084 VM |
127 | debug("%s: rv = %d\n\n", __func__, rv); |
128 | if (rv) | |
129 | return rv; | |
130 | } | |
131 | } | |
132 | ||
133 | return 0; | |
134 | } | |
135 | ||
bb44b968 CK |
136 | #if CONFIG_IS_ENABLED(PINCTRL_FULL) |
137 | static int stm32_pinctrl_set_state(struct udevice *dev, struct udevice *config) | |
138 | { | |
139 | return stm32_pinctrl_config(dev_of_offset(config)); | |
140 | } | |
141 | #else /* PINCTRL_FULL */ | |
ad0376e0 CK |
142 | static int stm32_pinctrl_set_state_simple(struct udevice *dev, |
143 | struct udevice *periph) | |
144 | { | |
145 | const void *fdt = gd->fdt_blob; | |
146 | const fdt32_t *list; | |
147 | uint32_t phandle; | |
148 | int config_node; | |
149 | int size, i, ret; | |
150 | ||
151 | list = fdt_getprop(fdt, dev_of_offset(periph), "pinctrl-0", &size); | |
152 | if (!list) | |
153 | return -EINVAL; | |
154 | ||
155 | debug("%s: periph->name = %s\n", __func__, periph->name); | |
156 | ||
157 | size /= sizeof(*list); | |
158 | for (i = 0; i < size; i++) { | |
159 | phandle = fdt32_to_cpu(*list++); | |
160 | ||
161 | config_node = fdt_node_offset_by_phandle(fdt, phandle); | |
162 | if (config_node < 0) { | |
9b643e31 | 163 | pr_err("prop pinctrl-0 index %d invalid phandle\n", i); |
ad0376e0 CK |
164 | return -EINVAL; |
165 | } | |
166 | ||
167 | ret = stm32_pinctrl_config(config_node); | |
168 | if (ret) | |
169 | return ret; | |
170 | } | |
171 | ||
172 | return 0; | |
173 | } | |
bb44b968 | 174 | #endif /* PINCTRL_FULL */ |
ad0376e0 | 175 | |
94d53084 | 176 | static struct pinctrl_ops stm32_pinctrl_ops = { |
bb44b968 CK |
177 | #if CONFIG_IS_ENABLED(PINCTRL_FULL) |
178 | .set_state = stm32_pinctrl_set_state, | |
179 | #else /* PINCTRL_FULL */ | |
94d53084 | 180 | .set_state_simple = stm32_pinctrl_set_state_simple, |
bb44b968 | 181 | #endif /* PINCTRL_FULL */ |
94d53084 VM |
182 | }; |
183 | ||
184 | static const struct udevice_id stm32_pinctrl_ids[] = { | |
185 | { .compatible = "st,stm32f746-pinctrl" }, | |
092e72cb | 186 | { .compatible = "st,stm32h743-pinctrl" }, |
94d53084 VM |
187 | { } |
188 | }; | |
189 | ||
190 | U_BOOT_DRIVER(pinctrl_stm32) = { | |
191 | .name = "pinctrl_stm32", | |
192 | .id = UCLASS_PINCTRL, | |
193 | .of_match = stm32_pinctrl_ids, | |
194 | .ops = &stm32_pinctrl_ops, | |
195 | .bind = dm_scan_fdt_dev, | |
196 | }; |