]>
Commit | Line | Data |
---|---|---|
d439a46e KY |
1 | /* |
2 | * (C) Copyright 2016 Rockchip Electronics Co., Ltd | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
6 | ||
7 | #include <common.h> | |
8 | #include <dm.h> | |
9 | #include <errno.h> | |
10 | #include <syscon.h> | |
11 | #include <asm/arch/clock.h> | |
12 | #include <asm/arch/hardware.h> | |
13 | #include <asm/arch/grf_rk3328.h> | |
14 | #include <asm/arch/periph.h> | |
15 | #include <asm/io.h> | |
16 | #include <dm/pinctrl.h> | |
17 | ||
18 | DECLARE_GLOBAL_DATA_PTR; | |
19 | ||
20 | struct rk3328_pinctrl_priv { | |
21 | struct rk3328_grf_regs *grf; | |
22 | }; | |
23 | ||
d439a46e KY |
24 | static void pinctrl_rk3328_pwm_config(struct rk3328_grf_regs *grf, int pwm_id) |
25 | { | |
26 | switch (pwm_id) { | |
27 | case PERIPH_ID_PWM0: | |
28 | rk_clrsetreg(&grf->gpio2a_iomux, | |
6f0c1237 KY |
29 | GPIO2A4_SEL_MASK, |
30 | GPIO2A4_PWM_0 << GPIO2A4_SEL_SHIFT); | |
d439a46e KY |
31 | break; |
32 | case PERIPH_ID_PWM1: | |
33 | rk_clrsetreg(&grf->gpio2a_iomux, | |
6f0c1237 KY |
34 | GPIO2A5_SEL_MASK, |
35 | GPIO2A5_PWM_1 << GPIO2A5_SEL_SHIFT); | |
d439a46e KY |
36 | break; |
37 | case PERIPH_ID_PWM2: | |
38 | rk_clrsetreg(&grf->gpio2a_iomux, | |
6f0c1237 KY |
39 | GPIO2A6_SEL_MASK, |
40 | GPIO2A6_PWM_2 << GPIO2A6_SEL_SHIFT); | |
d439a46e KY |
41 | break; |
42 | case PERIPH_ID_PWM3: | |
43 | rk_clrsetreg(&grf->gpio2a_iomux, | |
6f0c1237 KY |
44 | GPIO2A2_SEL_MASK, |
45 | GPIO2A2_PWM_IR << GPIO2A2_SEL_SHIFT); | |
d439a46e KY |
46 | break; |
47 | default: | |
48 | debug("pwm id = %d iomux error!\n", pwm_id); | |
49 | break; | |
50 | } | |
51 | } | |
52 | ||
53 | static void pinctrl_rk3328_i2c_config(struct rk3328_grf_regs *grf, int i2c_id) | |
54 | { | |
55 | switch (i2c_id) { | |
56 | case PERIPH_ID_I2C0: | |
57 | rk_clrsetreg(&grf->gpio2d_iomux, | |
6f0c1237 KY |
58 | GPIO2D0_SEL_MASK | GPIO2D1_SEL_MASK, |
59 | GPIO2D0_I2C0_SCL << GPIO2D0_SEL_SHIFT | | |
60 | GPIO2D1_I2C0_SDA << GPIO2D1_SEL_SHIFT); | |
d439a46e KY |
61 | break; |
62 | case PERIPH_ID_I2C1: | |
63 | rk_clrsetreg(&grf->gpio2a_iomux, | |
6f0c1237 KY |
64 | GPIO2A4_SEL_MASK | GPIO2A5_SEL_MASK, |
65 | GPIO2A5_I2C1_SCL << GPIO2A5_SEL_SHIFT | | |
66 | GPIO2A4_I2C1_SDA << GPIO2A4_SEL_SHIFT); | |
d439a46e KY |
67 | break; |
68 | case PERIPH_ID_I2C2: | |
69 | rk_clrsetreg(&grf->gpio2bl_iomux, | |
6f0c1237 KY |
70 | GPIO2BL5_SEL_MASK | GPIO2BL6_SEL_MASK, |
71 | GPIO2BL6_I2C2_SCL << GPIO2BL6_SEL_SHIFT | | |
72 | GPIO2BL5_I2C2_SDA << GPIO2BL5_SEL_SHIFT); | |
d439a46e KY |
73 | break; |
74 | case PERIPH_ID_I2C3: | |
75 | rk_clrsetreg(&grf->gpio0a_iomux, | |
6f0c1237 KY |
76 | GPIO0A5_SEL_MASK | GPIO0A6_SEL_MASK, |
77 | GPIO0A5_I2C3_SCL << GPIO0A5_SEL_SHIFT | | |
78 | GPIO0A6_I2C3_SDA << GPIO0A6_SEL_SHIFT); | |
d439a46e KY |
79 | break; |
80 | default: | |
81 | debug("i2c id = %d iomux error!\n", i2c_id); | |
82 | break; | |
83 | } | |
84 | } | |
85 | ||
86 | static void pinctrl_rk3328_lcdc_config(struct rk3328_grf_regs *grf, int lcd_id) | |
87 | { | |
88 | switch (lcd_id) { | |
89 | case PERIPH_ID_LCDC0: | |
90 | break; | |
91 | default: | |
92 | debug("lcdc id = %d iomux error!\n", lcd_id); | |
93 | break; | |
94 | } | |
95 | } | |
96 | ||
97 | static int pinctrl_rk3328_spi_config(struct rk3328_grf_regs *grf, | |
98 | enum periph_id spi_id, int cs) | |
99 | { | |
077eb315 KY |
100 | u32 com_iomux = readl(&grf->com_iomux); |
101 | ||
102 | if ((com_iomux & IOMUX_SEL_SPI_MASK) != | |
103 | IOMUX_SEL_SPI_M0 << IOMUX_SEL_SPI_SHIFT) { | |
104 | debug("driver do not support iomux other than m0\n"); | |
105 | goto err; | |
106 | } | |
d439a46e KY |
107 | |
108 | switch (spi_id) { | |
109 | case PERIPH_ID_SPI0: | |
110 | switch (cs) { | |
111 | case 0: | |
112 | rk_clrsetreg(&grf->gpio2bl_iomux, | |
6f0c1237 KY |
113 | GPIO2BL3_SEL_MASK, |
114 | GPIO2BL3_SPI_CSN0_M0 | |
115 | << GPIO2BL3_SEL_SHIFT); | |
d439a46e KY |
116 | break; |
117 | case 1: | |
118 | rk_clrsetreg(&grf->gpio2bl_iomux, | |
6f0c1237 KY |
119 | GPIO2BL4_SEL_MASK, |
120 | GPIO2BL4_SPI_CSN1_M0 | |
121 | << GPIO2BL4_SEL_SHIFT); | |
d439a46e KY |
122 | break; |
123 | default: | |
124 | goto err; | |
125 | } | |
126 | rk_clrsetreg(&grf->gpio2bl_iomux, | |
6f0c1237 KY |
127 | GPIO2BL0_SEL_MASK, |
128 | GPIO2BL0_SPI_CLK_TX_RX_M0 << GPIO2BL0_SEL_SHIFT); | |
d439a46e KY |
129 | break; |
130 | default: | |
131 | goto err; | |
132 | } | |
133 | ||
134 | return 0; | |
135 | err: | |
136 | debug("rkspi: periph%d cs=%d not supported", spi_id, cs); | |
137 | return -ENOENT; | |
138 | } | |
139 | ||
140 | static void pinctrl_rk3328_uart_config(struct rk3328_grf_regs *grf, int uart_id) | |
141 | { | |
077eb315 KY |
142 | u32 com_iomux = readl(&grf->com_iomux); |
143 | ||
d439a46e KY |
144 | switch (uart_id) { |
145 | case PERIPH_ID_UART2: | |
146 | break; | |
077eb315 KY |
147 | if (com_iomux & IOMUX_SEL_UART2_MASK) |
148 | rk_clrsetreg(&grf->gpio2a_iomux, | |
149 | GPIO2A0_SEL_MASK | GPIO2A1_SEL_MASK, | |
150 | GPIO2A0_UART2_TX_M1 << GPIO2A0_SEL_SHIFT | | |
151 | GPIO2A1_UART2_RX_M1 << GPIO2A1_SEL_SHIFT); | |
152 | ||
d439a46e KY |
153 | break; |
154 | case PERIPH_ID_UART0: | |
155 | case PERIPH_ID_UART1: | |
156 | case PERIPH_ID_UART3: | |
157 | case PERIPH_ID_UART4: | |
158 | default: | |
159 | debug("uart id = %d iomux error!\n", uart_id); | |
160 | break; | |
161 | } | |
162 | } | |
163 | ||
164 | static void pinctrl_rk3328_sdmmc_config(struct rk3328_grf_regs *grf, | |
165 | int mmc_id) | |
166 | { | |
077eb315 KY |
167 | u32 com_iomux = readl(&grf->com_iomux); |
168 | ||
d439a46e KY |
169 | switch (mmc_id) { |
170 | case PERIPH_ID_EMMC: | |
171 | rk_clrsetreg(&grf->gpio0a_iomux, | |
6f0c1237 KY |
172 | GPIO0A7_SEL_MASK, |
173 | GPIO0A7_EMMC_DATA0 << GPIO0A7_SEL_SHIFT); | |
d439a46e | 174 | rk_clrsetreg(&grf->gpio2d_iomux, |
6f0c1237 KY |
175 | GPIO2D4_SEL_MASK, |
176 | GPIO2D4_EMMC_DATA1234 << GPIO2D4_SEL_SHIFT); | |
d439a46e | 177 | rk_clrsetreg(&grf->gpio3c_iomux, |
6f0c1237 KY |
178 | GPIO3C0_SEL_MASK, |
179 | GPIO3C0_EMMC_DATA567_PWR_CLK_RSTN_CMD | |
180 | << GPIO3C0_SEL_SHIFT); | |
d439a46e KY |
181 | break; |
182 | case PERIPH_ID_SDCARD: | |
077eb315 KY |
183 | /* SDMMC_PWREN use GPIO and init as regulator-fiexed */ |
184 | if (com_iomux & IOMUX_SEL_SDMMC_MASK) | |
185 | rk_clrsetreg(&grf->gpio0d_iomux, | |
186 | GPIO0D6_SEL_MASK, | |
fe450895 | 187 | GPIO0D6_GPIO << GPIO0D6_SEL_SHIFT); |
077eb315 KY |
188 | else |
189 | rk_clrsetreg(&grf->gpio2a_iomux, | |
190 | GPIO2A7_SEL_MASK, | |
fe450895 | 191 | GPIO2A7_GPIO << GPIO2A7_SEL_SHIFT); |
d439a46e | 192 | rk_clrsetreg(&grf->gpio1a_iomux, |
6f0c1237 KY |
193 | GPIO1A0_SEL_MASK, |
194 | GPIO1A0_CARD_DATA_CLK_CMD_DETN | |
195 | << GPIO1A0_SEL_SHIFT); | |
d439a46e KY |
196 | break; |
197 | default: | |
198 | debug("mmc id = %d iomux error!\n", mmc_id); | |
199 | break; | |
200 | } | |
201 | } | |
202 | ||
203 | static int rk3328_pinctrl_request(struct udevice *dev, int func, int flags) | |
204 | { | |
205 | struct rk3328_pinctrl_priv *priv = dev_get_priv(dev); | |
206 | ||
207 | debug("%s: func=%x, flags=%x\n", __func__, func, flags); | |
208 | switch (func) { | |
209 | case PERIPH_ID_PWM0: | |
210 | case PERIPH_ID_PWM1: | |
211 | case PERIPH_ID_PWM2: | |
212 | case PERIPH_ID_PWM3: | |
213 | pinctrl_rk3328_pwm_config(priv->grf, func); | |
214 | break; | |
215 | case PERIPH_ID_I2C0: | |
216 | case PERIPH_ID_I2C1: | |
217 | case PERIPH_ID_I2C2: | |
218 | case PERIPH_ID_I2C3: | |
219 | pinctrl_rk3328_i2c_config(priv->grf, func); | |
220 | break; | |
221 | case PERIPH_ID_SPI0: | |
222 | pinctrl_rk3328_spi_config(priv->grf, func, flags); | |
223 | break; | |
224 | case PERIPH_ID_UART0: | |
225 | case PERIPH_ID_UART1: | |
226 | case PERIPH_ID_UART2: | |
227 | case PERIPH_ID_UART3: | |
228 | case PERIPH_ID_UART4: | |
229 | pinctrl_rk3328_uart_config(priv->grf, func); | |
230 | break; | |
231 | case PERIPH_ID_LCDC0: | |
232 | case PERIPH_ID_LCDC1: | |
233 | pinctrl_rk3328_lcdc_config(priv->grf, func); | |
234 | break; | |
235 | case PERIPH_ID_SDMMC0: | |
236 | case PERIPH_ID_SDMMC1: | |
237 | pinctrl_rk3328_sdmmc_config(priv->grf, func); | |
238 | break; | |
239 | default: | |
240 | return -EINVAL; | |
241 | } | |
242 | ||
243 | return 0; | |
244 | } | |
245 | ||
246 | static int rk3328_pinctrl_get_periph_id(struct udevice *dev, | |
247 | struct udevice *periph) | |
248 | { | |
249 | u32 cell[3]; | |
250 | int ret; | |
251 | ||
9f4f914d | 252 | ret = dev_read_u32_array(periph, "interrupts", cell, ARRAY_SIZE(cell)); |
d439a46e KY |
253 | if (ret < 0) |
254 | return -EINVAL; | |
255 | ||
256 | switch (cell[1]) { | |
257 | case 49: | |
258 | return PERIPH_ID_SPI0; | |
259 | case 50: | |
260 | return PERIPH_ID_PWM0; | |
261 | case 36: | |
262 | return PERIPH_ID_I2C0; | |
263 | case 37: /* Note strange order */ | |
264 | return PERIPH_ID_I2C1; | |
265 | case 38: | |
266 | return PERIPH_ID_I2C2; | |
267 | case 39: | |
268 | return PERIPH_ID_I2C3; | |
269 | case 12: | |
270 | return PERIPH_ID_SDCARD; | |
271 | case 14: | |
272 | return PERIPH_ID_EMMC; | |
273 | } | |
274 | ||
275 | return -ENOENT; | |
276 | } | |
277 | ||
278 | static int rk3328_pinctrl_set_state_simple(struct udevice *dev, | |
279 | struct udevice *periph) | |
280 | { | |
281 | int func; | |
282 | ||
283 | func = rk3328_pinctrl_get_periph_id(dev, periph); | |
284 | if (func < 0) | |
285 | return func; | |
286 | ||
287 | return rk3328_pinctrl_request(dev, func, 0); | |
288 | } | |
289 | ||
290 | static struct pinctrl_ops rk3328_pinctrl_ops = { | |
291 | .set_state_simple = rk3328_pinctrl_set_state_simple, | |
292 | .request = rk3328_pinctrl_request, | |
293 | .get_periph_id = rk3328_pinctrl_get_periph_id, | |
294 | }; | |
295 | ||
296 | static int rk3328_pinctrl_probe(struct udevice *dev) | |
297 | { | |
298 | struct rk3328_pinctrl_priv *priv = dev_get_priv(dev); | |
299 | int ret = 0; | |
300 | ||
301 | priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); | |
302 | debug("%s: grf=%p\n", __func__, priv->grf); | |
303 | ||
304 | return ret; | |
305 | } | |
306 | ||
307 | static const struct udevice_id rk3328_pinctrl_ids[] = { | |
308 | { .compatible = "rockchip,rk3328-pinctrl" }, | |
309 | { } | |
310 | }; | |
311 | ||
312 | U_BOOT_DRIVER(pinctrl_rk3328) = { | |
313 | .name = "rockchip_rk3328_pinctrl", | |
314 | .id = UCLASS_PINCTRL, | |
315 | .of_match = rk3328_pinctrl_ids, | |
316 | .priv_auto_alloc_size = sizeof(struct rk3328_pinctrl_priv), | |
317 | .ops = &rk3328_pinctrl_ops, | |
318 | .bind = dm_scan_fdt_dev, | |
319 | .probe = rk3328_pinctrl_probe, | |
320 | }; |