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 }