xref: /OK3568_Linux_fs/u-boot/drivers/gpio/kw_gpio.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * arch/arm/plat-orion/gpio.c
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Marvell Orion SoC GPIO handling.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun /*
10*4882a593Smuzhiyun  * Based on (mostly copied from) plat-orion based Linux 2.6 kernel driver.
11*4882a593Smuzhiyun  * Removed orion_gpiochip struct and kernel level irq handling.
12*4882a593Smuzhiyun  *
13*4882a593Smuzhiyun  * Dieter Kiermaier dk-arm-linux@gmx.de
14*4882a593Smuzhiyun  */
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include <common.h>
17*4882a593Smuzhiyun #include <linux/bitops.h>
18*4882a593Smuzhiyun #include <asm/io.h>
19*4882a593Smuzhiyun #include <asm/arch/soc.h>
20*4882a593Smuzhiyun #include <asm/arch/gpio.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun static unsigned long gpio_valid_input[BITS_TO_LONGS(GPIO_MAX)];
23*4882a593Smuzhiyun static unsigned long gpio_valid_output[BITS_TO_LONGS(GPIO_MAX)];
24*4882a593Smuzhiyun 
__set_direction(unsigned pin,int input)25*4882a593Smuzhiyun void __set_direction(unsigned pin, int input)
26*4882a593Smuzhiyun {
27*4882a593Smuzhiyun 	u32 u;
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun 	u = readl(GPIO_IO_CONF(pin));
30*4882a593Smuzhiyun 	if (input)
31*4882a593Smuzhiyun 		u |= 1 << (pin & 31);
32*4882a593Smuzhiyun 	else
33*4882a593Smuzhiyun 		u &= ~(1 << (pin & 31));
34*4882a593Smuzhiyun 	writel(u, GPIO_IO_CONF(pin));
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun 	u = readl(GPIO_IO_CONF(pin));
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun 
__set_level(unsigned pin,int high)39*4882a593Smuzhiyun static void __set_level(unsigned pin, int high)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun 	u32 u;
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun 	u = readl(GPIO_OUT(pin));
44*4882a593Smuzhiyun 	if (high)
45*4882a593Smuzhiyun 		u |= 1 << (pin & 31);
46*4882a593Smuzhiyun 	else
47*4882a593Smuzhiyun 		u &= ~(1 << (pin & 31));
48*4882a593Smuzhiyun 	writel(u, GPIO_OUT(pin));
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun 
__set_blinking(unsigned pin,int blink)51*4882a593Smuzhiyun static void __set_blinking(unsigned pin, int blink)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun 	u32 u;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	u = readl(GPIO_BLINK_EN(pin));
56*4882a593Smuzhiyun 	if (blink)
57*4882a593Smuzhiyun 		u |= 1 << (pin & 31);
58*4882a593Smuzhiyun 	else
59*4882a593Smuzhiyun 		u &= ~(1 << (pin & 31));
60*4882a593Smuzhiyun 	writel(u, GPIO_BLINK_EN(pin));
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun 
kw_gpio_is_valid(unsigned pin,int mode)63*4882a593Smuzhiyun int kw_gpio_is_valid(unsigned pin, int mode)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun 	if (pin < GPIO_MAX) {
66*4882a593Smuzhiyun 		if ((mode & GPIO_INPUT_OK) && !test_bit(pin, gpio_valid_input))
67*4882a593Smuzhiyun 			goto err_out;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 		if ((mode & GPIO_OUTPUT_OK) && !test_bit(pin, gpio_valid_output))
70*4882a593Smuzhiyun 			goto err_out;
71*4882a593Smuzhiyun 		return 0;
72*4882a593Smuzhiyun 	}
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun err_out:
75*4882a593Smuzhiyun 		printf("%s: invalid GPIO %d\n", __func__, pin);
76*4882a593Smuzhiyun 	return 1;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun 
kw_gpio_set_valid(unsigned pin,int mode)79*4882a593Smuzhiyun void kw_gpio_set_valid(unsigned pin, int mode)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun 	if (mode == 1)
82*4882a593Smuzhiyun 		mode = GPIO_INPUT_OK | GPIO_OUTPUT_OK;
83*4882a593Smuzhiyun 	if (mode & GPIO_INPUT_OK)
84*4882a593Smuzhiyun 		__set_bit(pin, gpio_valid_input);
85*4882a593Smuzhiyun 	else
86*4882a593Smuzhiyun 		__clear_bit(pin, gpio_valid_input);
87*4882a593Smuzhiyun 	if (mode & GPIO_OUTPUT_OK)
88*4882a593Smuzhiyun 		__set_bit(pin, gpio_valid_output);
89*4882a593Smuzhiyun 	else
90*4882a593Smuzhiyun 		__clear_bit(pin, gpio_valid_output);
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun /*
93*4882a593Smuzhiyun  * GENERIC_GPIO primitives.
94*4882a593Smuzhiyun  */
kw_gpio_direction_input(unsigned pin)95*4882a593Smuzhiyun int kw_gpio_direction_input(unsigned pin)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun 	if (kw_gpio_is_valid(pin, GPIO_INPUT_OK) != 0)
98*4882a593Smuzhiyun 		return 1;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 	/* Configure GPIO direction. */
101*4882a593Smuzhiyun 	__set_direction(pin, 1);
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	return 0;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
kw_gpio_direction_output(unsigned pin,int value)106*4882a593Smuzhiyun int kw_gpio_direction_output(unsigned pin, int value)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun 	if (kw_gpio_is_valid(pin, GPIO_OUTPUT_OK) != 0)
109*4882a593Smuzhiyun 	{
110*4882a593Smuzhiyun 		printf("%s: invalid GPIO %d\n", __func__, pin);
111*4882a593Smuzhiyun 		return 1;
112*4882a593Smuzhiyun 	}
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	__set_blinking(pin, 0);
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	/* Configure GPIO output value. */
117*4882a593Smuzhiyun 	__set_level(pin, value);
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	/* Configure GPIO direction. */
120*4882a593Smuzhiyun 	__set_direction(pin, 0);
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	return 0;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun 
kw_gpio_get_value(unsigned pin)125*4882a593Smuzhiyun int kw_gpio_get_value(unsigned pin)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun 	int val;
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	if (readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31)))
130*4882a593Smuzhiyun 		val = readl(GPIO_DATA_IN(pin)) ^ readl(GPIO_IN_POL(pin));
131*4882a593Smuzhiyun 	else
132*4882a593Smuzhiyun 		val = readl(GPIO_OUT(pin));
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	return (val >> (pin & 31)) & 1;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun 
kw_gpio_set_value(unsigned pin,int value)137*4882a593Smuzhiyun void kw_gpio_set_value(unsigned pin, int value)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun 	/* Configure GPIO output value. */
140*4882a593Smuzhiyun 	__set_level(pin, value);
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun 
kw_gpio_set_blink(unsigned pin,int blink)143*4882a593Smuzhiyun void kw_gpio_set_blink(unsigned pin, int blink)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun 	/* Set output value to zero. */
146*4882a593Smuzhiyun 	__set_level(pin, 0);
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	/* Set blinking. */
149*4882a593Smuzhiyun 	__set_blinking(pin, blink);
150*4882a593Smuzhiyun }
151