1 #include "bflb_gpio.h"
2 #include "hardware/gpio_reg.h"
3
bflb_gpio_init(struct bflb_device_s * dev,uint8_t pin,uint32_t cfgset)4 void bflb_gpio_init(struct bflb_device_s *dev, uint8_t pin, uint32_t cfgset)
5 {
6 uint32_t cfg = 0;
7 uint32_t reg_base;
8 uint32_t cfg_address;
9 uint8_t drive;
10 uint8_t function;
11 uint16_t mode;
12
13 reg_base = dev->reg_base;
14
15 function = (cfgset & GPIO_FUNC_MASK) >> GPIO_FUNC_SHIFT;
16 mode = (cfgset & GPIO_MODE_MASK);
17 drive = (cfgset & GPIO_DRV_MASK) >> GPIO_DRV_SHIFT;
18
19 #if defined(BL616)
20 /* disable muxed to be xtal32k */
21 if (pin == GPIO_PIN_16) {
22 *(volatile uint32_t *)(0x2000f000 + 0x38) &= ~(1 << 20);
23 } else if (pin == GPIO_PIN_17) {
24 *(volatile uint32_t *)(0x2000f000 + 0x38) &= ~(1 << 21);
25 }
26 #endif
27
28 #if defined(BL702) || defined(BL602) || defined(BL702L)
29 uint32_t regval;
30 uint8_t is_odd = 0;
31
32 regval = getreg32(reg_base + GLB_GPIO_CFGCTL34_OFFSET + ((pin >> 5) << 2));
33 regval &= ~(1 << (pin & 0x1f));
34 putreg32(regval, reg_base + GLB_GPIO_CFGCTL34_OFFSET + ((pin >> 5) << 2));
35
36 is_odd = (pin % 2);
37
38 cfg_address = reg_base + GLB_GPIO_CFGCTL0_OFFSET + (pin / 2 * 4);
39 cfg = getreg32(cfg_address);
40 cfg &= ~(0xffff << (16 * is_odd));
41
42 regval = getreg32(reg_base + GLB_GPIO_CFGCTL34_OFFSET + ((pin >> 5) << 2));
43 if (mode == GPIO_INPUT) {
44 cfg |= (1 << (is_odd * 16 + 0));
45 regval &= ~(1 << (pin & 0x1f));
46 function = 11;
47 } else if (mode == GPIO_OUTPUT) {
48 regval |= (1 << (pin & 0x1f));
49 function = 11;
50 #if defined(BL702L)
51 if (function == 22) {
52 regval &= ~(1 << (pin & 0x1f));
53 }
54 #endif
55 } else if (mode == GPIO_ANALOG) {
56 regval &= ~(1 << (pin & 0x1f));
57 function = 10;
58 } else if (mode == GPIO_ALTERNATE) {
59 cfg |= (1 << (is_odd * 16 + 0));
60 #if defined(BL702L)
61 if (function == 22) {
62 cfg &= ~(1 << (is_odd * 16 + 0));
63 }
64 #endif
65 regval &= ~(1 << (pin & 0x1f));
66 } else {
67 }
68 putreg32(regval, reg_base + GLB_GPIO_CFGCTL34_OFFSET + ((pin >> 5) << 2));
69
70 if (cfgset & GPIO_PULLUP) {
71 cfg |= (1 << (is_odd * 16 + 4));
72 } else if (cfgset & GPIO_PULLDOWN) {
73 cfg |= (1 << (is_odd * 16 + 5));
74 } else {
75 }
76
77 if (cfgset & GPIO_SMT_EN) {
78 cfg |= (1 << (is_odd * 16 + 1));
79 }
80
81 cfg |= (drive << (is_odd * 16 + 2));
82 cfg |= (function << (is_odd * 16 + 8));
83 #if defined(BL702L)
84 /* configure output mode:set and clr mode */
85 if ((function != 22) || (function != 21)) {
86 cfg |= (1 << (is_odd * 16 + 15));
87 }
88 #endif
89 #elif defined(BL616) || defined(BL808) || defined(BL606P) || defined(BL628)
90 cfg_address = reg_base + GLB_GPIO_CFG0_OFFSET + (pin << 2);
91 cfg = 0;
92 cfg |= GLB_REG_GPIO_0_INT_MASK;
93
94 if (mode == GPIO_INPUT) {
95 cfg |= GLB_REG_GPIO_0_IE;
96 function = 11;
97 } else if (mode == GPIO_OUTPUT) {
98 cfg |= GLB_REG_GPIO_0_OE;
99 function = 11;
100 } else if (mode == GPIO_ANALOG) {
101 function = 10;
102 } else if (mode == GPIO_ALTERNATE) {
103 cfg |= GLB_REG_GPIO_0_IE;
104 } else {
105 }
106
107 if (cfgset & GPIO_PULLUP) {
108 cfg |= GLB_REG_GPIO_0_PU;
109 } else if (cfgset & GPIO_PULLDOWN) {
110 cfg |= GLB_REG_GPIO_0_PD;
111 } else {
112 }
113
114 if (cfgset & GPIO_SMT_EN) {
115 cfg |= GLB_REG_GPIO_0_SMT;
116 }
117
118 cfg |= (drive << GLB_REG_GPIO_0_DRV_SHIFT);
119 cfg |= (function << GLB_REG_GPIO_0_FUNC_SEL_SHIFT);
120
121 /* configure output mode:set and clr mode */
122 cfg |= 0x1 << GLB_REG_GPIO_0_MODE_SHIFT;
123 #endif
124 putreg32(cfg, cfg_address);
125 }
126
bflb_gpio_deinit(struct bflb_device_s * dev,uint8_t pin)127 void bflb_gpio_deinit(struct bflb_device_s *dev, uint8_t pin)
128 {
129 bflb_gpio_init(dev, pin, GPIO_INPUT | GPIO_FLOAT);
130 }
131
bflb_gpio_set(struct bflb_device_s * dev,uint8_t pin)132 void bflb_gpio_set(struct bflb_device_s *dev, uint8_t pin)
133 {
134 #if defined(BL702) || defined(BL602)
135 uint32_t regval = getreg32(dev->reg_base + GLB_GPIO_CFGCTL32_OFFSET);
136 putreg32(regval | 1 << (pin & 0x1f), dev->reg_base + GLB_GPIO_CFGCTL32_OFFSET);
137 #elif defined(BL702L)
138 uint32_t regval = getreg32(dev->reg_base + GLB_GPIO_CFGCTL35_OFFSET);
139 putreg32(regval | 1 << (pin & 0x1f), dev->reg_base + GLB_GPIO_CFGCTL35_OFFSET);
140 #elif defined(BL616) || defined(BL808) || defined(BL606P) || defined(BL628)
141 putreg32(1 << (pin & 0x1f), dev->reg_base + GLB_GPIO_CFG138_OFFSET + ((pin >> 5) << 2));
142 #endif
143 }
144
bflb_gpio_reset(struct bflb_device_s * dev,uint8_t pin)145 void bflb_gpio_reset(struct bflb_device_s *dev, uint8_t pin)
146 {
147 #if defined(BL702) || defined(BL602)
148 uint32_t regval = getreg32(dev->reg_base + GLB_GPIO_CFGCTL32_OFFSET);
149 putreg32(regval & ~(1 << (pin & 0x1f)), dev->reg_base + GLB_GPIO_CFGCTL32_OFFSET);
150 #elif defined(BL702L)
151 uint32_t regval = getreg32(dev->reg_base + GLB_GPIO_CFGCTL36_OFFSET);
152 putreg32(regval & ~(1 << (pin & 0x1f)), dev->reg_base + GLB_GPIO_CFGCTL36_OFFSET);
153 #elif defined(BL616) || defined(BL808) || defined(BL606P) || defined(BL628)
154 putreg32(1 << (pin & 0x1f), dev->reg_base + GLB_GPIO_CFG140_OFFSET + ((pin >> 5) << 2));
155 #endif
156 }
157
bflb_gpio_read(struct bflb_device_s * dev,uint8_t pin)158 bool bflb_gpio_read(struct bflb_device_s *dev, uint8_t pin)
159 {
160 #if defined(BL702) || defined(BL602) || defined(BL702L)
161 return (getreg32(dev->reg_base + GLB_GPIO_CFGCTL30_OFFSET) & (1 << pin));
162 #elif defined(BL616) || defined(BL808) || defined(BL606P) || defined(BL628)
163 return (getreg32(dev->reg_base + GLB_GPIO_CFG0_OFFSET + (pin << 2)) & GLB_REG_GPIO_0_I);
164 #endif
165 }
166
bflb_gpio_pin0_31_write(struct bflb_device_s * dev,uint32_t val)167 void bflb_gpio_pin0_31_write(struct bflb_device_s *dev, uint32_t val)
168 {
169 #if defined(BL702) || defined(BL602) || defined(BL702L)
170 putreg32(val, dev->reg_base + GLB_GPIO_CFGCTL32_OFFSET);
171 #elif defined(BL616) || defined(BL808) || defined(BL606P) || defined(BL628)
172 putreg32(val, dev->reg_base + GLB_GPIO_CFG136_OFFSET);
173 #endif
174 }
175
bflb_gpio_pin32_63_write(struct bflb_device_s * dev,uint32_t val)176 void bflb_gpio_pin32_63_write(struct bflb_device_s *dev, uint32_t val)
177 {
178 #if defined(BL702) || defined(BL602) || defined(BL702L)
179 putreg32(val, dev->reg_base + GLB_GPIO_CFGCTL33_OFFSET);
180 #elif defined(BL616) || defined(BL808) || defined(BL606P) || defined(BL628)
181 putreg32(val, dev->reg_base + GLB_GPIO_CFG137_OFFSET);
182 #endif
183 }
184
bflb_gpio_pin0_31_read(struct bflb_device_s * dev)185 uint32_t bflb_gpio_pin0_31_read(struct bflb_device_s *dev)
186 {
187 #if defined(BL702) || defined(BL602) || defined(BL702L)
188 return (getreg32(dev->reg_base + GLB_GPIO_CFGCTL30_OFFSET));
189 #elif defined(BL616) || defined(BL808) || defined(BL606P) || defined(BL628)
190 return (getreg32(dev->reg_base + GLB_GPIO_CFG128_OFFSET));
191 #endif
192 }
193
bflb_gpio_pin32_63_read(struct bflb_device_s * dev)194 uint32_t bflb_gpio_pin32_63_read(struct bflb_device_s *dev)
195 {
196 #if defined(BL702) || defined(BL602) || defined(BL702L)
197 return (getreg32(dev->reg_base + GLB_GPIO_CFGCTL31_OFFSET));
198 #elif defined(BL616) || defined(BL808) || defined(BL606P) || defined(BL628)
199 return (getreg32(dev->reg_base + GLB_GPIO_CFG129_OFFSET));
200 #endif
201 }
202
bflb_gpio_int_init(struct bflb_device_s * dev,uint8_t pin,uint8_t trig_mode)203 void bflb_gpio_int_init(struct bflb_device_s *dev, uint8_t pin, uint8_t trig_mode)
204 {
205 uint32_t reg_base;
206 uint32_t cfg_address;
207 uint32_t regval;
208
209 reg_base = dev->reg_base;
210
211 bflb_gpio_init(dev, pin, GPIO_INPUT | GPIO_FLOAT);
212
213 bflb_gpio_int_mask(dev, pin, true);
214 bflb_gpio_int_clear(dev, pin);
215
216 #if defined(BL702) || defined(BL602)
217 cfg_address = reg_base + GLB_GPIO_INT_MODE_SET1_OFFSET + ((pin / 10) << 2);
218 regval = getreg32(cfg_address);
219 regval &= ~(0x07 << ((pin % 10) * 3));
220 regval |= (trig_mode << ((pin % 10) * 3));
221 #elif defined(BL702L)
222 cfg_address = reg_base + GLB_GPIO_INT_MODE_SET1_OFFSET + ((pin / 8) << 2);
223 regval = getreg32(cfg_address);
224 regval &= ~(0x0f << ((pin % 8) * 4));
225 regval |= (trig_mode << ((pin % 8) * 4));
226 #elif defined(BL616) || defined(BL808) || defined(BL606P) || defined(BL628)
227 cfg_address = reg_base + GLB_GPIO_CFG0_OFFSET + (pin << 2);
228 regval = getreg32(cfg_address);
229 regval &= ~GLB_REG_GPIO_0_INT_MODE_SET_MASK;
230 regval |= (trig_mode << GLB_REG_GPIO_0_INT_MODE_SET_SHIFT);
231 #endif
232 putreg32(regval, cfg_address);
233 }
234
bflb_gpio_int_mask(struct bflb_device_s * dev,uint8_t pin,bool mask)235 void bflb_gpio_int_mask(struct bflb_device_s *dev, uint8_t pin, bool mask)
236 {
237 uint32_t reg_base;
238 uint32_t cfg_address;
239 uint32_t regval;
240
241 reg_base = dev->reg_base;
242 #if defined(BL702) || defined(BL602) || defined(BL702L)
243 cfg_address = reg_base + GLB_GPIO_INT_MASK1_OFFSET;
244
245 regval = getreg32(cfg_address);
246 if (mask) {
247 regval |= (1 << pin);
248 } else {
249 regval &= ~(1 << pin);
250 }
251 #elif defined(BL616) || defined(BL808) || defined(BL606P) || defined(BL628)
252 cfg_address = reg_base + GLB_GPIO_CFG0_OFFSET + (pin << 2);
253
254 regval = getreg32(cfg_address);
255 if (mask) {
256 regval |= GLB_REG_GPIO_0_INT_MASK;
257 } else {
258 regval &= ~GLB_REG_GPIO_0_INT_MASK;
259 }
260 #endif
261 putreg32(regval, cfg_address);
262 }
263
bflb_gpio_get_intstatus(struct bflb_device_s * dev,uint8_t pin)264 bool bflb_gpio_get_intstatus(struct bflb_device_s *dev, uint8_t pin)
265 {
266 #if defined(BL702) || defined(BL602) || defined(BL702L)
267 return (getreg32(dev->reg_base + GLB_GPIO_INT_STAT1_OFFSET) & (1 << pin));
268 #elif defined(BL616) || defined(BL808) || defined(BL606P) || defined(BL628)
269 return (getreg32(dev->reg_base + GLB_GPIO_CFG0_OFFSET + (pin << 2)) & GLB_GPIO_0_INT_STAT);
270 #endif
271 }
272
bflb_gpio_int_clear(struct bflb_device_s * dev,uint8_t pin)273 void bflb_gpio_int_clear(struct bflb_device_s *dev, uint8_t pin)
274 {
275 uint32_t reg_base;
276 uint32_t cfg_address;
277 uint32_t regval;
278
279 reg_base = dev->reg_base;
280 #if defined(BL702) || defined(BL602) || defined(BL702L)
281 cfg_address = reg_base + GLB_GPIO_INT_CLR1_OFFSET;
282
283 regval = getreg32(cfg_address);
284 regval |= (1 << pin);
285 putreg32(regval, cfg_address);
286 regval &= ~(1 << pin);
287 putreg32(regval, cfg_address);
288 #elif defined(BL616) || defined(BL808) || defined(BL606P) || defined(BL628)
289 cfg_address = reg_base + GLB_GPIO_CFG0_OFFSET + (pin << 2);
290
291 regval = getreg32(cfg_address);
292 regval |= GLB_REG_GPIO_0_INT_CLR;
293 putreg32(regval, cfg_address);
294 regval &= ~GLB_REG_GPIO_0_INT_CLR;
295 putreg32(regval, cfg_address);
296 #endif
297 }
298
bflb_gpio_uart_init(struct bflb_device_s * dev,uint8_t pin,uint8_t uart_func)299 void bflb_gpio_uart_init(struct bflb_device_s *dev, uint8_t pin, uint8_t uart_func)
300 {
301 uint32_t reg_base;
302 uint32_t regval;
303 uint8_t sig;
304 uint8_t sig_pos;
305
306 reg_base = dev->reg_base;
307 #if defined(BL702) || defined(BL602)
308 #define GLB_UART_SIG_SEL_0_OFFSET (0xC0)
309 regval = getreg32(reg_base + GLB_UART_SIG_SEL_0_OFFSET);
310
311 sig = pin % 8;
312 sig_pos = sig << 2;
313
314 regval &= (~(0x0f << sig_pos));
315 regval |= (uart_func << sig_pos);
316
317 for (uint8_t i = 0; i < 8; i++) {
318 /* reset other sigs which are the same with uart_func */
319 sig_pos = i << 2;
320 if (((regval & (0x0f << sig_pos)) == (uart_func << sig_pos)) && (i != sig) && (uart_func != 0x0f)) {
321 regval &= (~(0x0f << sig_pos));
322 regval |= (0x0f << sig_pos);
323 }
324 }
325
326 putreg32(regval, reg_base + GLB_UART_SIG_SEL_0_OFFSET);
327 #elif defined(BL702L)
328 #define GLB_UART_SIG_SEL_0_OFFSET (0xC0)
329 regval = getreg32(reg_base + GLB_UART_SIG_SEL_0_OFFSET);
330
331 sig = pin % 4;
332 sig_pos = sig << 2;
333
334 regval &= (~(0x0f << sig_pos));
335 regval |= (uart_func << sig_pos);
336
337 for (uint8_t i = 0; i < 4; i++) {
338 /* reset other sigs which are the same with uart_func */
339 sig_pos = i << 2;
340 if (((regval & (0x0f << sig_pos)) == (uart_func << sig_pos)) && (i != sig) && (uart_func != 0x0f)) {
341 regval &= (~(0x0f << sig_pos));
342 regval |= (0x0f << sig_pos);
343 }
344 }
345
346 putreg32(regval, reg_base + GLB_UART_SIG_SEL_0_OFFSET);
347 #elif defined(BL616) || defined(BL808) || defined(BL606P) || defined(BL628)
348 #define GLB_UART_CFG1_OFFSET (0x154)
349 #define GLB_UART_CFG2_OFFSET (0x158)
350 uint32_t regval2;
351 sig = pin % 12;
352
353 if (sig < 8) {
354 sig_pos = sig << 2;
355
356 regval = getreg32(reg_base + GLB_UART_CFG1_OFFSET);
357 regval &= (~(0x0f << sig_pos));
358 regval |= (uart_func << sig_pos);
359
360 for (uint8_t i = 0; i < 8; i++) {
361 /* reset other sigs which are the same with uart_func */
362 sig_pos = i << 2;
363 if (((regval & (0x0f << sig_pos)) == (uart_func << sig_pos)) && (i != sig) && (uart_func != 0x0f)) {
364 regval &= (~(0x0f << sig_pos));
365 regval |= (0x0f << sig_pos);
366 }
367 }
368 regval2 = getreg32(reg_base + GLB_UART_CFG2_OFFSET);
369
370 for (uint8_t i = 8; i < 12; i++) {
371 /* reset other sigs which are the same with uart_func */
372 sig_pos = (i - 8) << 2;
373 if (((regval2 & (0x0f << sig_pos)) == (uart_func << sig_pos)) && (i != sig) && (uart_func != 0x0f)) {
374 regval2 &= (~(0x0f << sig_pos));
375 regval2 |= (0x0f << sig_pos);
376 }
377 }
378 putreg32(regval, reg_base + GLB_UART_CFG1_OFFSET);
379 putreg32(regval2, reg_base + GLB_UART_CFG2_OFFSET);
380 } else {
381 sig_pos = (sig - 8) << 2;
382
383 regval = getreg32(reg_base + GLB_UART_CFG2_OFFSET);
384 regval &= (~(0x0f << sig_pos));
385 regval |= (uart_func << sig_pos);
386
387 for (uint8_t i = 8; i < 12; i++) {
388 /* reset other sigs which are the same with uart_func */
389 sig_pos = (i - 8) << 2;
390 if (((regval & (0x0f << sig_pos)) == (uart_func << sig_pos)) && (i != sig) && (uart_func != 0x0f)) {
391 regval &= (~(0x0f << sig_pos));
392 regval |= (0x0f << sig_pos);
393 }
394 }
395 regval2 = getreg32(reg_base + GLB_UART_CFG1_OFFSET);
396
397 for (uint8_t i = 0; i < 8; i++) {
398 /* reset other sigs which are the same with uart_func */
399 sig_pos = i << 2;
400 if (((regval2 & (0x0f << sig_pos)) == (uart_func << sig_pos)) && (i != sig) && (uart_func != 0x0f)) {
401 regval2 &= (~(0x0f << sig_pos));
402 regval2 |= (0x0f << sig_pos);
403 }
404 }
405 putreg32(regval, reg_base + GLB_UART_CFG2_OFFSET);
406 putreg32(regval2, reg_base + GLB_UART_CFG1_OFFSET);
407 }
408 #endif
409 bflb_gpio_init(dev, pin, (7 << GPIO_FUNC_SHIFT) | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
410 }
411
bflb_gpio_feature_control(struct bflb_device_s * dev,int cmd,size_t arg)412 int bflb_gpio_feature_control(struct bflb_device_s *dev, int cmd, size_t arg)
413 {
414 int ret = 0;
415 uint32_t reg_base;
416 uint32_t regval;
417 uint8_t pin = arg;
418
419 reg_base = dev->reg_base;
420 switch (cmd) {
421 case GPIO_CMD_GET_GPIO_FUN:
422 #if defined(BL702) || defined(BL602) || defined(BL702L)
423 if ((pin % 2)) {
424 regval = getreg32(reg_base + GLB_GPIO_CFGCTL0_OFFSET + (pin / 2 * 4)) & GLB_REG_GPIO_0_FUNC_SEL_MASK;
425 regval >>= GLB_REG_GPIO_0_FUNC_SEL_SHIFT;
426 } else {
427 regval = getreg32(reg_base + GLB_GPIO_CFGCTL0_OFFSET + (pin / 2 * 4)) & GLB_REG_GPIO_1_FUNC_SEL_MASK;
428 regval >>= GLB_REG_GPIO_1_FUNC_SEL_SHIFT;
429 }
430 #elif defined(BL616) || defined(BL808) || defined(BL606P) || defined(BL628)
431 regval = getreg32(reg_base + GLB_GPIO_CFG0_OFFSET + (pin << 2)) & GLB_REG_GPIO_0_FUNC_SEL_MASK;
432 regval >>= GLB_REG_GPIO_0_FUNC_SEL_SHIFT;
433 #endif
434 return regval;
435 default:
436 ret = -EPERM;
437 break;
438 }
439 return ret;
440 }