1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3 * Copyright (c) 2021 Rockchip Electronics Co. Ltd.
4 *
5 * Author: Wyon Bi <bivvy.bi@rock-chips.com>
6 */
7
8 #include "rk628.h"
9
rk628_calc_mux_offset(struct rk628 * rk628,int mux,int reg,int offset)10 static int rk628_calc_mux_offset(struct rk628 *rk628, int mux, int reg, int offset)
11 {
12 int val = 0, orig;
13
14 switch (reg) {
15 case GRF_SYSTEM_CON3:
16 rk628_i2c_read(rk628, reg, &orig);
17 if (mux)
18 val = BIT(offset) | orig;
19 else
20 val = ~BIT(offset) & orig;
21 break;
22 case GRF_GPIO0AB_SEL_CON:
23 if (offset >= 4 && offset < 8) {
24 offset += offset - 4;
25 val = 0x3 << (offset + 16) | (mux << offset);
26 } else if (offset > 7) {
27 offset += 4;
28 val = BIT(offset + 16) | (mux << offset);
29 } else {
30 val = BIT(offset + 16) | (mux << offset);
31 }
32 break;
33 case GRF_GPIO1AB_SEL_CON:
34 if (offset == 13)
35 offset++;
36 if (offset > 11)
37 val = 0x3 << (offset + 16) | (mux << offset);
38 else
39 val = BIT(offset + 16) | (mux << offset);
40 break;
41 case GRF_GPIO2AB_SEL_CON:
42 val = BIT(offset + 16) | (mux << offset);
43 break;
44 case GRF_GPIO2C_SEL_CON:
45 offset -= 16;
46 val = 0x3 << ((offset*2) + 16) | (mux << (offset*2));
47 break;
48 case GRF_GPIO3AB_SEL_CON:
49 if (offset > 11)
50 val = 0x3 << (offset + 16) | (mux << offset);
51 else
52 val = BIT(offset + 16) | (mux << offset);
53 break;
54 default:
55 break;
56 }
57
58 return val;
59 }
60
rk628_misc_pinctrl_set_mux(struct rk628 * rk628,int gpio,int mux)61 int rk628_misc_pinctrl_set_mux(struct rk628 *rk628, int gpio, int mux)
62 {
63 int i, iomux_base, offset, val;
64
65 mux &= 0x3;
66
67 for (i = 0; i < ARRAY_SIZE(rk628_pin_iomux_groups); i++) {
68 if (rk628_pin_iomux_groups[i].pins == gpio) {
69 iomux_base = rk628_pin_iomux_groups[i].iomux_base;
70 offset = rk628_pin_iomux_groups[i].pins % BANK_OFFSET;
71 break;
72 }
73 }
74
75 if ((i == ARRAY_SIZE(rk628_pin_iomux_groups)) || (!iomux_base)) {
76 pr_info("%s invalid gpio or iomux_base\n", __func__);
77 return -1;
78 }
79
80 val = rk628_calc_mux_offset(rk628, mux, iomux_base, offset);
81
82 rk628_i2c_write(rk628, iomux_base, val);
83
84 return 0;
85
86 }
87
88
89 /* generic gpio chip */
rk628_misc_gpio_get_value(struct rk628 * rk628,int gpio)90 int rk628_misc_gpio_get_value(struct rk628 *rk628, int gpio)
91 {
92 int i, data_reg, offset, val;
93
94 for (i = 0; i < ARRAY_SIZE(rk628_pin_iomux_groups); i++) {
95 if (rk628_pin_iomux_groups[i].pins == gpio) {
96 data_reg = rk628_pin_iomux_groups[i].gpio_base + GPIO_EXT_PORT;
97 offset = rk628_pin_iomux_groups[i].pins % BANK_OFFSET;
98 break;
99 }
100 }
101
102 if ((i == ARRAY_SIZE(rk628_pin_iomux_groups)) || (!data_reg)) {
103 pr_info("%s invalid gpio or data_reg\n", __func__);
104 return -1;
105 }
106
107 rk628_i2c_read(rk628, data_reg, &val);
108
109 val >>= offset;
110 val &= 1;
111
112 return val;
113 }
114
rk628_misc_gpio_set_value(struct rk628 * rk628,int gpio,int value)115 int rk628_misc_gpio_set_value(struct rk628 *rk628, int gpio, int value)
116 {
117 int i, data_reg, offset, val;
118
119 for (i = 0; i < ARRAY_SIZE(rk628_pin_iomux_groups); i++) {
120 if (rk628_pin_iomux_groups[i].pins == gpio) {
121 offset = rk628_pin_iomux_groups[i].pins % BANK_OFFSET;
122 if (offset >= 16) {
123 data_reg = rk628_pin_iomux_groups[i].gpio_base + GPIO_SWPORT_DR_H;
124 offset -= 16;
125 } else {
126 data_reg = rk628_pin_iomux_groups[i].gpio_base + GPIO_SWPORT_DR_L;
127 }
128 break;
129 }
130 }
131
132 if ((i == ARRAY_SIZE(rk628_pin_iomux_groups)) || (!data_reg)) {
133 pr_info("%s invalid gpio or data_reg\n", __func__);
134 return -1;
135 }
136
137 if (value)
138 val = BIT(offset + 16) | BIT(offset);
139 else
140 val = BIT(offset + 16) | (0xffff & ~BIT(offset));
141
142 rk628_i2c_write(rk628, data_reg, val);
143
144 return 0;
145 }
146
147
148
rk628_misc_gpio_set_direction(struct rk628 * rk628,int gpio,int direction)149 int rk628_misc_gpio_set_direction(struct rk628 *rk628, int gpio, int direction)
150 {
151 int i, dir_reg, offset, val;
152
153 for (i = 0; i < ARRAY_SIZE(rk628_pin_iomux_groups); i++) {
154 if (rk628_pin_iomux_groups[i].pins == gpio) {
155 offset = rk628_pin_iomux_groups[i].pins % BANK_OFFSET;
156 if (offset >= 16) {
157 dir_reg = rk628_pin_iomux_groups[i].gpio_base + GPIO_SWPORT_DDR_H;
158 offset -= 16;
159 } else {
160 dir_reg = rk628_pin_iomux_groups[i].gpio_base + GPIO_SWPORT_DDR_L;
161 }
162 break;
163 }
164 }
165
166 if ((i == ARRAY_SIZE(rk628_pin_iomux_groups)) || (!dir_reg)) {
167 pr_info("%s invalid gpio or dir_reg\n", __func__);
168 return -1;
169 }
170
171 if (!direction)
172 val = BIT(offset + 16) | (0xffff & ~BIT(offset));
173 else
174 val = BIT(offset + 16) | BIT(offset);
175
176 rk628_i2c_write(rk628, dir_reg, val);
177
178 return 0;
179 }
180
181
rk628_misc_iomux_init(struct rk628 * rk628)182 int rk628_misc_iomux_init(struct rk628 *rk628)
183 {
184 int i, iomux_base, offset, val, mux;
185
186 for (i = 0; i < ARRAY_SIZE(rk628_pin_iomux_groups); i++) {
187 mux = rk628_pin_iomux_groups[i].mux;
188 iomux_base = rk628_pin_iomux_groups[i].iomux_base;
189 offset = rk628_pin_iomux_groups[i].pins % BANK_OFFSET;
190 if (iomux_base) {
191 val = rk628_calc_mux_offset(rk628, mux, iomux_base, offset);
192 rk628_i2c_write(rk628, iomux_base, val);
193 }
194 }
195
196 return 0;
197 }
198
199
rk628_misc_gpio_direction_input(struct rk628 * rk628,int gpio)200 int rk628_misc_gpio_direction_input(struct rk628 *rk628, int gpio)
201 {
202 rk628_misc_pinctrl_set_mux(rk628, gpio, GPIO_FUNC);
203
204 rk628_misc_gpio_set_direction(rk628, gpio, GPIO_DIRECTION_IN);
205
206 return 0;
207 }
208
209
rk628_misc_gpio_direction_output(struct rk628 * rk628,int gpio,int value)210 int rk628_misc_gpio_direction_output(struct rk628 *rk628, int gpio, int value)
211 {
212
213 rk628_misc_pinctrl_set_mux(rk628, gpio, GPIO_FUNC);
214 rk628_misc_gpio_set_value(rk628, gpio, value);
215 rk628_misc_gpio_set_direction(rk628, gpio, GPIO_DIRECTION_OUT);
216 return 0;
217 }
218
219
rk628_misc_gpio_set_pull_highz_up_down(struct rk628 * rk628,int gpio,int pull)220 int rk628_misc_gpio_set_pull_highz_up_down(struct rk628 *rk628, int gpio, int pull)
221 {
222 int i, bank, pull_reg = 0, offset, val = 0;
223 int valid_pinnum[] = { 8, 8, 24, 13 };
224
225 for (i = 0; i < ARRAY_SIZE(rk628_pin_iomux_groups); i++) {
226 if (rk628_pin_iomux_groups[i].pins == gpio) {
227 bank = rk628_pin_iomux_groups[i].bank;
228 pull_reg = rk628_pin_iomux_groups[i].pull_reg;
229 offset = rk628_pin_iomux_groups[i].pins % BANK_OFFSET;
230 break;
231 }
232 }
233
234 if ((i == ARRAY_SIZE(rk628_pin_iomux_groups)) || (!pull_reg)) {
235 pr_info("rk628_gpio_pull_highz_up_down invalid gpio or pull_reg\n");
236 return -1;
237 }
238
239 switch (bank) {
240 case GPIO_BANK0:
241 if (pull == GPIO_PULL_UP)
242 return -1;
243
244 if (offset == 2)
245 return -1;
246
247 if (offset < valid_pinnum[bank])
248 val = 0x3 << (2 * offset + 16) | pull << (2 * offset);
249 break;
250 case GPIO_BANK1:
251 if (pull == GPIO_PULL_UP)
252 return -1;
253
254 if (offset == 2)
255 return -1;
256
257 if (offset < valid_pinnum[bank])
258 val = 0x3 << (2 * offset + 16) | pull << (2 * offset);
259 break;
260 case GPIO_BANK2:
261 if (pull == GPIO_PULL_UP)
262 pull = GPIO_PULL_DOWN;
263 else if (pull == GPIO_PULL_DOWN)
264 pull = GPIO_PULL_UP;
265
266 if (offset < valid_pinnum[bank]) {
267 offset = offset % 8;
268 val = 0x3 << (2 * offset + 16) | pull << (2 * offset);
269 }
270 break;
271 case GPIO_BANK3:
272 if (pull == GPIO_PULL_UP && (offset == 2 || offset == 11 || offset == 12))
273 return -1;
274 else if (pull == GPIO_PULL_DOWN && (offset == 9 || offset == 10))
275 return -1;
276
277 if (offset == 0 || offset == 1 || offset == 3 || offset == 8) {
278 if (pull == GPIO_PULL_UP)
279 pull = GPIO_PULL_DOWN;
280 else if (pull == GPIO_PULL_DOWN)
281 pull = GPIO_PULL_UP;
282 }
283
284 if ((offset > 7 && offset < valid_pinnum[bank]) || offset < 4) {
285 offset = offset % 8;
286 val = 0x3 << (2 * offset + 16) | pull << (2 * offset);
287 }
288 break;
289 default:
290 break;
291 }
292
293 rk628_i2c_write(rk628, pull_reg, val);
294
295 return 0;
296 }
297
298
299
rk628_misc_gpio_test_all(struct rk628 * rk628)300 int rk628_misc_gpio_test_all(struct rk628 *rk628)
301 {
302 int i;
303
304 for (i = 0; i < ARRAY_SIZE(rk628_pin_iomux_groups); i++) {
305 if (rk628_pin_iomux_groups[i].pins && (rk628_pin_iomux_groups[i].pins != GPIO1_A1)
306 && (rk628_pin_iomux_groups[i].pins != GPIO2_C0)
307 && (rk628_pin_iomux_groups[i].pins != GPIO2_C1)
308 && (rk628_pin_iomux_groups[i].pins != GPIO2_C2)
309 && (rk628_pin_iomux_groups[i].pins != GPIO2_C3)
310 && (rk628_pin_iomux_groups[i].pins != GPIO2_C4))
311 rk628_misc_gpio_direction_output(rk628, rk628_pin_iomux_groups[i].pins, 1);
312 }
313
314 for (i = 0; i < ARRAY_SIZE(rk628_pin_iomux_groups); i++) {
315 if (rk628_pin_iomux_groups[i].pins && (rk628_pin_iomux_groups[i].pins != GPIO1_A1)
316 && (rk628_pin_iomux_groups[i].pins != GPIO2_C0)
317 && (rk628_pin_iomux_groups[i].pins != GPIO2_C1)
318 && (rk628_pin_iomux_groups[i].pins != GPIO2_C2)
319 && (rk628_pin_iomux_groups[i].pins != GPIO2_C3)
320 && (rk628_pin_iomux_groups[i].pins != GPIO2_C4))
321 rk628_misc_gpio_direction_output(rk628, rk628_pin_iomux_groups[i].pins, 0);
322 }
323
324 return 0;
325 }
326
327