• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include <assert.h>
7 #include <debug.h>
8 #include <delay_timer.h>
9 #include <errno.h>
10 #include <gpio.h>
11 #include <mmio.h>
12 #include <plat_private.h>
13 #include <platform.h>
14 #include <platform_def.h>
15 #include <soc.h>
16 
17 uint32_t gpio_port[] = {
18 	GPIO0_BASE,
19 	GPIO1_BASE,
20 	GPIO2_BASE,
21 	GPIO3_BASE,
22 	GPIO4_BASE,
23 };
24 
25 struct {
26 	uint32_t swporta_dr;
27 	uint32_t swporta_ddr;
28 	uint32_t inten;
29 	uint32_t intmask;
30 	uint32_t inttype_level;
31 	uint32_t int_polarity;
32 	uint32_t debounce;
33 	uint32_t ls_sync;
34 } store_gpio[3];
35 
36 static uint32_t store_grf_gpio[(GRF_GPIO2D_HE - GRF_GPIO2A_IOMUX) / 4 + 1];
37 
38 #define SWPORTA_DR	0x00
39 #define SWPORTA_DDR	0x04
40 #define INTEN		0x30
41 #define INTMASK		0x34
42 #define INTTYPE_LEVEL	0x38
43 #define INT_POLARITY	0x3c
44 #define DEBOUNCE	0x48
45 #define LS_SYNC		0x60
46 
47 #define EXT_PORTA	0x50
48 #define PMU_GPIO_PORT0	0
49 #define PMU_GPIO_PORT1	1
50 #define GPIO_PORT2	2
51 #define GPIO_PORT3	3
52 #define GPIO_PORT4	4
53 
54 #define PMU_GRF_GPIO0A_P	0x40
55 #define GRF_GPIO2A_P		0xe040
56 #define GPIO_P_MASK		0x03
57 
58 #define GET_GPIO_PORT(pin)	(pin / 32)
59 #define GET_GPIO_NUM(pin)	(pin % 32)
60 #define GET_GPIO_BANK(pin)	((pin % 32) / 8)
61 #define GET_GPIO_ID(pin)	((pin % 32) % 8)
62 
63 /* returns old clock state, enables clock, in order to do GPIO access */
gpio_get_clock(uint32_t gpio_number)64 static int gpio_get_clock(uint32_t gpio_number)
65 {
66 	uint32_t port = GET_GPIO_PORT(gpio_number);
67 	uint32_t clock_state = 0;
68 
69 	assert(port < 5);
70 
71 	switch (port) {
72 	case PMU_GPIO_PORT0:
73 		clock_state = (mmio_read_32(PMUCRU_BASE +
74 					    CRU_PMU_CLKGATE_CON(1)) >>
75 					    PCLK_GPIO0_GATE_SHIFT) & 0x01;
76 		mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1),
77 			      BITS_WITH_WMASK(0, CLK_GATE_MASK,
78 					      PCLK_GPIO0_GATE_SHIFT));
79 		break;
80 	case PMU_GPIO_PORT1:
81 		clock_state = (mmio_read_32(PMUCRU_BASE +
82 					    CRU_PMU_CLKGATE_CON(1)) >>
83 					    PCLK_GPIO1_GATE_SHIFT) & 0x01;
84 		mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1),
85 			      BITS_WITH_WMASK(0, CLK_GATE_MASK,
86 					      PCLK_GPIO1_GATE_SHIFT));
87 		break;
88 	case GPIO_PORT2:
89 		clock_state = (mmio_read_32(CRU_BASE +
90 					    CRU_CLKGATE_CON(31)) >>
91 					    PCLK_GPIO2_GATE_SHIFT) & 0x01;
92 		mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
93 			      BITS_WITH_WMASK(0, CLK_GATE_MASK,
94 					      PCLK_GPIO2_GATE_SHIFT));
95 		break;
96 	case GPIO_PORT3:
97 		clock_state = (mmio_read_32(CRU_BASE +
98 					    CRU_CLKGATE_CON(31)) >>
99 					    PCLK_GPIO3_GATE_SHIFT) & 0x01;
100 		mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
101 			      BITS_WITH_WMASK(0, CLK_GATE_MASK,
102 					      PCLK_GPIO3_GATE_SHIFT));
103 		break;
104 	case GPIO_PORT4:
105 		clock_state = (mmio_read_32(CRU_BASE +
106 					    CRU_CLKGATE_CON(31)) >>
107 					    PCLK_GPIO4_GATE_SHIFT) & 0x01;
108 		mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
109 			      BITS_WITH_WMASK(0, CLK_GATE_MASK,
110 					      PCLK_GPIO4_GATE_SHIFT));
111 		break;
112 	default:
113 		break;
114 	}
115 
116 	return clock_state;
117 }
118 
119 /* restores old state of gpio clock */
gpio_put_clock(uint32_t gpio_number,uint32_t clock_state)120 void gpio_put_clock(uint32_t gpio_number, uint32_t clock_state)
121 {
122 	uint32_t port = GET_GPIO_PORT(gpio_number);
123 
124 	switch (port) {
125 	case PMU_GPIO_PORT0:
126 		mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1),
127 			      BITS_WITH_WMASK(clock_state, CLK_GATE_MASK,
128 					      PCLK_GPIO0_GATE_SHIFT));
129 		break;
130 	case PMU_GPIO_PORT1:
131 		mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATE_CON(1),
132 			      BITS_WITH_WMASK(clock_state, CLK_GATE_MASK,
133 					      PCLK_GPIO1_GATE_SHIFT));
134 		break;
135 	case GPIO_PORT2:
136 		mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
137 			      BITS_WITH_WMASK(clock_state, CLK_GATE_MASK,
138 					      PCLK_GPIO2_GATE_SHIFT));
139 		break;
140 	case GPIO_PORT3:
141 		mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
142 			      BITS_WITH_WMASK(clock_state, CLK_GATE_MASK,
143 					      PCLK_GPIO3_GATE_SHIFT));
144 
145 		break;
146 	case GPIO_PORT4:
147 		mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
148 			      BITS_WITH_WMASK(clock_state, CLK_GATE_MASK,
149 					      PCLK_GPIO4_GATE_SHIFT));
150 		break;
151 	default:
152 		break;
153 	}
154 }
155 
get_pull(int gpio)156 static int get_pull(int gpio)
157 {
158 	uint32_t port = GET_GPIO_PORT(gpio);
159 	uint32_t bank = GET_GPIO_BANK(gpio);
160 	uint32_t id = GET_GPIO_ID(gpio);
161 	uint32_t val, clock_state;
162 
163 	assert((port < 5) && (bank < 4));
164 
165 	clock_state = gpio_get_clock(gpio);
166 
167 	if (port == PMU_GPIO_PORT0 || port == PMU_GPIO_PORT1) {
168 		val = mmio_read_32(PMUGRF_BASE + PMU_GRF_GPIO0A_P +
169 				   port * 16 + bank * 4);
170 		val = (val >> (id * 2)) & GPIO_P_MASK;
171 	} else {
172 		val = mmio_read_32(GRF_BASE + GRF_GPIO2A_P +
173 				   (port - 2) * 16 + bank * 4);
174 		val = (val >> (id * 2)) & GPIO_P_MASK;
175 	}
176 	gpio_put_clock(gpio, clock_state);
177 
178 	/*
179 	 * in gpio0a, gpio0b, gpio2c, gpio2d,
180 	 * 00: Z
181 	 * 01: pull down
182 	 * 10: Z
183 	 * 11: pull up
184 	 * different with other gpio, so need to correct it
185 	 */
186 	if (((port == 0) && (bank < 2)) || ((port == 2) && (bank > 1))) {
187 		if (val == 3)
188 			val = GPIO_PULL_UP;
189 		else if (val == 1)
190 			val = GPIO_PULL_DOWN;
191 		else
192 			val = 0;
193 	}
194 
195 	return val;
196 }
197 
set_pull(int gpio,int pull)198 static void set_pull(int gpio, int pull)
199 {
200 	uint32_t port = GET_GPIO_PORT(gpio);
201 	uint32_t bank = GET_GPIO_BANK(gpio);
202 	uint32_t id = GET_GPIO_ID(gpio);
203 	uint32_t clock_state;
204 
205 	assert((port < 5) && (bank < 4));
206 
207 	clock_state = gpio_get_clock(gpio);
208 
209 	/*
210 	 * in gpio0a, gpio0b, gpio2c, gpio2d,
211 	 * 00: Z
212 	 * 01: pull down
213 	 * 10: Z
214 	 * 11: pull up
215 	 * different with other gpio, so need to correct it
216 	 */
217 	if (((port == 0) && (bank < 2)) || ((port == 2) && (bank > 1))) {
218 		if (pull == GPIO_PULL_UP)
219 			pull = 3;
220 		else if (pull == GPIO_PULL_DOWN)
221 			pull = 1;
222 		else
223 			pull = 0;
224 	}
225 
226 	if (port == PMU_GPIO_PORT0 || port == PMU_GPIO_PORT1) {
227 		mmio_write_32(PMUGRF_BASE + PMU_GRF_GPIO0A_P +
228 			      port * 16 + bank * 4,
229 			      BITS_WITH_WMASK(pull, GPIO_P_MASK, id * 2));
230 	} else {
231 		mmio_write_32(GRF_BASE + GRF_GPIO2A_P +
232 			      (port - 2) * 16 + bank * 4,
233 			      BITS_WITH_WMASK(pull, GPIO_P_MASK, id * 2));
234 	}
235 	gpio_put_clock(gpio, clock_state);
236 }
237 
set_direction(int gpio,int direction)238 static void set_direction(int gpio, int direction)
239 {
240 	uint32_t port = GET_GPIO_PORT(gpio);
241 	uint32_t num = GET_GPIO_NUM(gpio);
242 	uint32_t clock_state;
243 
244 	assert((port < 5) && (num < 32));
245 
246 	clock_state = gpio_get_clock(gpio);
247 
248 	/*
249 	 * in gpio.h
250 	 * #define GPIO_DIR_OUT	0
251 	 * #define GPIO_DIR_IN	1
252 	 * but rk3399 gpio direction 1: output, 0: input
253 	 * so need to revert direction value
254 	 */
255 	mmio_setbits_32(gpio_port[port] + SWPORTA_DDR, !direction << num);
256 	gpio_put_clock(gpio, clock_state);
257 }
258 
get_direction(int gpio)259 static int get_direction(int gpio)
260 {
261 	uint32_t port = GET_GPIO_PORT(gpio);
262 	uint32_t num = GET_GPIO_NUM(gpio);
263 	int direction, clock_state;
264 
265 	assert((port < 5) && (num < 32));
266 
267 	clock_state = gpio_get_clock(gpio);
268 
269 	/*
270 	 * in gpio.h
271 	 * #define GPIO_DIR_OUT	0
272 	 * #define GPIO_DIR_IN	1
273 	 * but rk3399 gpio direction 1: output, 0: input
274 	 * so need to revert direction value
275 	 */
276 	direction = !((mmio_read_32(gpio_port[port] +
277 				    SWPORTA_DDR) >> num) & 0x1);
278 	gpio_put_clock(gpio, clock_state);
279 
280 	return direction;
281 }
282 
get_value(int gpio)283 static int get_value(int gpio)
284 {
285 	uint32_t port = GET_GPIO_PORT(gpio);
286 	uint32_t num = GET_GPIO_NUM(gpio);
287 	int value, clock_state;
288 
289 	assert((port < 5) && (num < 32));
290 
291 	clock_state = gpio_get_clock(gpio);
292 	value = (mmio_read_32(gpio_port[port] + EXT_PORTA) >> num) & 0x1;
293 	gpio_put_clock(gpio, clock_state);
294 
295 	return value;
296 }
297 
set_value(int gpio,int value)298 static void set_value(int gpio, int value)
299 {
300 	uint32_t port = GET_GPIO_PORT(gpio);
301 	uint32_t num = GET_GPIO_NUM(gpio);
302 	uint32_t clock_state;
303 
304 	assert((port < 5) && (num < 32));
305 
306 	clock_state = gpio_get_clock(gpio);
307 	mmio_clrsetbits_32(gpio_port[port] + SWPORTA_DR, 1 << num,
308 							 !!value << num);
309 	gpio_put_clock(gpio, clock_state);
310 }
311 
plat_rockchip_save_gpio(void)312 void plat_rockchip_save_gpio(void)
313 {
314 	int i;
315 	uint32_t cru_gate_save;
316 
317 	cru_gate_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(31));
318 
319 	/*
320 	 * when shutdown logic, we need to save gpio2 ~ gpio4 register,
321 	 * we need to enable gpio2 ~ gpio4 clock here, since it may be gating,
322 	 * and we do not care gpio0 and gpio1 clock gate, since we never
323 	 * gating them
324 	 */
325 	mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
326 		      BITS_WITH_WMASK(0, 0x07, PCLK_GPIO2_GATE_SHIFT));
327 
328 	/*
329 	 * since gpio0, gpio1 are pmugpio, they will keep ther value
330 	 * when shutdown logic power rail, so only need to save gpio2 ~ gpio4
331 	 * register value
332 	 */
333 	for (i = 2; i < 5; i++) {
334 		store_gpio[i - 2].swporta_dr =
335 			mmio_read_32(gpio_port[i] + SWPORTA_DR);
336 		store_gpio[i - 2].swporta_ddr =
337 			mmio_read_32(gpio_port[i] + SWPORTA_DDR);
338 		store_gpio[i - 2].inten =
339 			mmio_read_32(gpio_port[i] + INTEN);
340 		store_gpio[i - 2].intmask =
341 			mmio_read_32(gpio_port[i] + INTMASK);
342 		store_gpio[i - 2].inttype_level =
343 			mmio_read_32(gpio_port[i] + INTTYPE_LEVEL);
344 		store_gpio[i - 2].int_polarity =
345 			mmio_read_32(gpio_port[i] + INT_POLARITY);
346 		store_gpio[i - 2].debounce =
347 			mmio_read_32(gpio_port[i] + DEBOUNCE);
348 		store_gpio[i - 2].ls_sync =
349 			mmio_read_32(gpio_port[i] + LS_SYNC);
350 	}
351 	mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
352 			cru_gate_save | REG_SOC_WMSK);
353 
354 	/*
355 	 * gpio0, gpio1 in pmuiomux, they will keep ther value
356 	 * when shutdown logic power rail, so only need to save gpio2 ~ gpio4
357 	 * iomux register value
358 	 */
359 	for (i = 0; i < ARRAY_SIZE(store_grf_gpio); i++)
360 		store_grf_gpio[i] =
361 			mmio_read_32(GRF_BASE + GRF_GPIO2A_IOMUX + i * 4);
362 }
363 
plat_rockchip_restore_gpio(void)364 void plat_rockchip_restore_gpio(void)
365 {
366 	int i;
367 	uint32_t cru_gate_save;
368 
369 	for (i = 0; i < ARRAY_SIZE(store_grf_gpio); i++)
370 		mmio_write_32(GRF_BASE + GRF_GPIO2A_IOMUX + i * 4,
371 		      REG_SOC_WMSK | store_grf_gpio[i]);
372 
373 	cru_gate_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(31));
374 
375 	/*
376 	 * when shutdown logic, we need to save gpio2 ~ gpio4 register,
377 	 * we need to enable gpio2 ~ gpio4 clock here, since it may be gating,
378 	 * and we do not care gpio0 and gpio1 clock gate, since we never
379 	 * gating them
380 	 */
381 	mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
382 		      BITS_WITH_WMASK(0, 0x07, PCLK_GPIO2_GATE_SHIFT));
383 
384 	for (i = 2; i < 5; i++) {
385 		mmio_write_32(gpio_port[i] + SWPORTA_DR,
386 				store_gpio[i - 2].swporta_dr);
387 		mmio_write_32(gpio_port[i] + SWPORTA_DDR,
388 				store_gpio[i - 2].swporta_ddr);
389 		mmio_write_32(gpio_port[i] + INTEN, store_gpio[i - 2].inten);
390 		mmio_write_32(gpio_port[i] + INTMASK,
391 				store_gpio[i - 2].intmask);
392 		mmio_write_32(gpio_port[i] + INTTYPE_LEVEL,
393 				store_gpio[i - 2].inttype_level);
394 		mmio_write_32(gpio_port[i] + INT_POLARITY,
395 				store_gpio[i - 2].int_polarity);
396 		mmio_write_32(gpio_port[i] + DEBOUNCE,
397 				store_gpio[i - 2].debounce);
398 		mmio_write_32(gpio_port[i] + LS_SYNC,
399 				store_gpio[i - 2].ls_sync);
400 	}
401 	mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31),
402 			cru_gate_save | REG_SOC_WMSK);
403 }
404 
405 const gpio_ops_t rk3399_gpio_ops = {
406 	.get_direction = get_direction,
407 	.set_direction = set_direction,
408 	.get_value = get_value,
409 	.set_value = set_value,
410 	.set_pull = set_pull,
411 	.get_pull = get_pull,
412 };
413 
plat_rockchip_gpio_init(void)414 void plat_rockchip_gpio_init(void)
415 {
416 	gpio_init(&rk3399_gpio_ops);
417 }
418