xref: /openbmc/u-boot/drivers/gpio/s5p_gpio.c (revision 1ace4022)
1 /*
2  * (C) Copyright 2009 Samsung Electronics
3  * Minkyu Kang <mk7.kang@samsung.com>
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <common.h>
9 #include <asm/io.h>
10 #include <asm/gpio.h>
11 
12 #define S5P_GPIO_GET_BANK(x)	((x >> S5P_GPIO_BANK_SHIFT) \
13 				& S5P_GPIO_BANK_MASK)
14 
15 #define S5P_GPIO_GET_PIN(x)	(x & S5P_GPIO_PIN_MASK)
16 
17 #define CON_MASK(x)		(0xf << ((x) << 2))
18 #define CON_SFR(x, v)		((v) << ((x) << 2))
19 
20 #define DAT_MASK(x)		(0x1 << (x))
21 #define DAT_SET(x)		(0x1 << (x))
22 
23 #define PULL_MASK(x)		(0x3 << ((x) << 1))
24 #define PULL_MODE(x, v)		((v) << ((x) << 1))
25 
26 #define DRV_MASK(x)		(0x3 << ((x) << 1))
27 #define DRV_SET(x, m)		((m) << ((x) << 1))
28 #define RATE_MASK(x)		(0x1 << (x + 16))
29 #define RATE_SET(x)		(0x1 << (x + 16))
30 
31 void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg)
32 {
33 	unsigned int value;
34 
35 	value = readl(&bank->con);
36 	value &= ~CON_MASK(gpio);
37 	value |= CON_SFR(gpio, cfg);
38 	writel(value, &bank->con);
39 }
40 
41 void s5p_gpio_direction_output(struct s5p_gpio_bank *bank, int gpio, int en)
42 {
43 	s5p_gpio_cfg_pin(bank, gpio, GPIO_OUTPUT);
44 	s5p_gpio_set_value(bank, gpio, en);
45 }
46 
47 void s5p_gpio_direction_input(struct s5p_gpio_bank *bank, int gpio)
48 {
49 	s5p_gpio_cfg_pin(bank, gpio, GPIO_INPUT);
50 }
51 
52 void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en)
53 {
54 	unsigned int value;
55 
56 	value = readl(&bank->dat);
57 	value &= ~DAT_MASK(gpio);
58 	if (en)
59 		value |= DAT_SET(gpio);
60 	writel(value, &bank->dat);
61 }
62 
63 unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio)
64 {
65 	unsigned int value;
66 
67 	value = readl(&bank->dat);
68 	return !!(value & DAT_MASK(gpio));
69 }
70 
71 void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode)
72 {
73 	unsigned int value;
74 
75 	value = readl(&bank->pull);
76 	value &= ~PULL_MASK(gpio);
77 
78 	switch (mode) {
79 	case GPIO_PULL_DOWN:
80 	case GPIO_PULL_UP:
81 		value |= PULL_MODE(gpio, mode);
82 		break;
83 	default:
84 		break;
85 	}
86 
87 	writel(value, &bank->pull);
88 }
89 
90 void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode)
91 {
92 	unsigned int value;
93 
94 	value = readl(&bank->drv);
95 	value &= ~DRV_MASK(gpio);
96 
97 	switch (mode) {
98 	case GPIO_DRV_1X:
99 	case GPIO_DRV_2X:
100 	case GPIO_DRV_3X:
101 	case GPIO_DRV_4X:
102 		value |= DRV_SET(gpio, mode);
103 		break;
104 	default:
105 		return;
106 	}
107 
108 	writel(value, &bank->drv);
109 }
110 
111 void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode)
112 {
113 	unsigned int value;
114 
115 	value = readl(&bank->drv);
116 	value &= ~RATE_MASK(gpio);
117 
118 	switch (mode) {
119 	case GPIO_DRV_FAST:
120 	case GPIO_DRV_SLOW:
121 		value |= RATE_SET(gpio);
122 		break;
123 	default:
124 		return;
125 	}
126 
127 	writel(value, &bank->drv);
128 }
129 
130 struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned gpio)
131 {
132 	unsigned bank = S5P_GPIO_GET_BANK(gpio);
133 	unsigned base = s5p_gpio_base(gpio);
134 
135 	return (struct s5p_gpio_bank *)(base + bank);
136 }
137 
138 int s5p_gpio_get_pin(unsigned gpio)
139 {
140 	return S5P_GPIO_GET_PIN(gpio);
141 }
142 
143 /* Common GPIO API */
144 
145 int gpio_request(unsigned gpio, const char *label)
146 {
147 	return 0;
148 }
149 
150 int gpio_free(unsigned gpio)
151 {
152 	return 0;
153 }
154 
155 int gpio_direction_input(unsigned gpio)
156 {
157 	s5p_gpio_direction_input(s5p_gpio_get_bank(gpio),
158 				s5p_gpio_get_pin(gpio));
159 	return 0;
160 }
161 
162 int gpio_direction_output(unsigned gpio, int value)
163 {
164 	s5p_gpio_direction_output(s5p_gpio_get_bank(gpio),
165 				 s5p_gpio_get_pin(gpio), value);
166 	return 0;
167 }
168 
169 int gpio_get_value(unsigned gpio)
170 {
171 	return (int) s5p_gpio_get_value(s5p_gpio_get_bank(gpio),
172 				       s5p_gpio_get_pin(gpio));
173 }
174 
175 int gpio_set_value(unsigned gpio, int value)
176 {
177 	s5p_gpio_set_value(s5p_gpio_get_bank(gpio),
178 			  s5p_gpio_get_pin(gpio), value);
179 
180 	return 0;
181 }
182