1 #include "bflb_uart.h"
2 #include "bflb_clock.h"
3 #include "hardware/uart_reg.h"
4 
bflb_uart_init(struct bflb_device_s * dev,const struct bflb_uart_config_s * config)5 void bflb_uart_init(struct bflb_device_s *dev, const struct bflb_uart_config_s *config)
6 {
7     uint32_t div = 0;
8     uint32_t tx_cfg;
9     uint32_t rx_cfg;
10     uint32_t reg_base;
11     uint32_t regval;
12 
13     reg_base = dev->reg_base;
14     /* Cal the baud rate divisor */
15     div = (bflb_clk_get_peripheral_clock(BFLB_DEVICE_TYPE_UART, dev->idx) * 10 / config->baudrate + 5) / 10;
16 
17     tx_cfg = getreg32(reg_base + UART_UTX_CONFIG_OFFSET);
18     rx_cfg = getreg32(reg_base + UART_URX_CONFIG_OFFSET);
19     tx_cfg &= ~UART_CR_UTX_EN;
20     rx_cfg &= ~UART_CR_URX_EN;
21     putreg32(tx_cfg, reg_base + UART_UTX_CONFIG_OFFSET);
22     putreg32(rx_cfg, reg_base + UART_URX_CONFIG_OFFSET);
23 
24     putreg32(((div - 1) << 0x10) | ((div - 1) & 0xFFFF), reg_base + UART_BIT_PRD_OFFSET);
25 
26     /* configure parity type */
27 
28     tx_cfg = getreg32(reg_base + UART_UTX_CONFIG_OFFSET);
29     rx_cfg = getreg32(reg_base + UART_URX_CONFIG_OFFSET);
30 
31     switch (config->parity) {
32         case UART_PARITY_NONE:
33             tx_cfg &= ~UART_CR_UTX_PRT_EN;
34             rx_cfg &= ~UART_CR_URX_PRT_EN;
35             break;
36         case UART_PARITY_ODD:
37             tx_cfg |= UART_CR_UTX_PRT_EN;
38             tx_cfg |= UART_CR_UTX_PRT_SEL;
39             rx_cfg |= UART_CR_URX_PRT_EN;
40             rx_cfg |= UART_CR_URX_PRT_SEL;
41             break;
42         case UART_PARITY_EVEN:
43             tx_cfg |= UART_CR_UTX_PRT_EN;
44             tx_cfg &= ~UART_CR_UTX_PRT_SEL;
45             rx_cfg |= UART_CR_URX_PRT_EN;
46             rx_cfg &= ~UART_CR_URX_PRT_SEL;
47             break;
48         default:
49             break;
50     }
51 
52     /* Configure data bits */
53     tx_cfg &= ~UART_CR_UTX_BIT_CNT_D_MASK;
54     tx_cfg |= (config->data_bits + 4) << UART_CR_UTX_BIT_CNT_D_SHIFT;
55     rx_cfg &= ~UART_CR_URX_BIT_CNT_D_MASK;
56     rx_cfg |= (config->data_bits + 4) << UART_CR_URX_BIT_CNT_D_SHIFT;
57 
58     /* Configure tx stop bits */
59     tx_cfg &= ~UART_CR_UTX_BIT_CNT_P_MASK;
60     tx_cfg |= config->stop_bits << UART_CR_UTX_BIT_CNT_P_SHIFT;
61 
62     /* Configure tx cts flow control function */
63     if (config->flow_ctrl & UART_FLOWCTRL_CTS) {
64         tx_cfg |= UART_CR_UTX_CTS_EN;
65     } else {
66         tx_cfg &= ~UART_CR_UTX_CTS_EN;
67     }
68 
69     rx_cfg &= ~UART_CR_URX_DEG_EN;
70 
71     /* Write back */
72     putreg32(tx_cfg, reg_base + UART_UTX_CONFIG_OFFSET);
73     putreg32(rx_cfg, reg_base + UART_URX_CONFIG_OFFSET);
74 #if defined(BL602)
75     regval = getreg32(reg_base + UART_URX_CONFIG_OFFSET);
76     regval &= ~UART_CR_URX_RTS_SW_MODE;
77     putreg32(regval, reg_base + UART_URX_CONFIG_OFFSET);
78 
79 #else
80     regval = getreg32(reg_base + UART_SW_MODE_OFFSET);
81     regval &= ~UART_CR_URX_RTS_SW_MODE;
82     putreg32(regval, reg_base + UART_SW_MODE_OFFSET);
83 #endif
84     regval = getreg32(reg_base + UART_DATA_CONFIG_OFFSET);
85     regval &= ~UART_CR_UART_BIT_INV;
86     putreg32(regval, reg_base + UART_DATA_CONFIG_OFFSET);
87 
88     /* Enable tx free run mode */
89     regval = getreg32(reg_base + UART_UTX_CONFIG_OFFSET);
90     regval |= UART_CR_UTX_FRM_EN;
91     putreg32(regval, reg_base + UART_UTX_CONFIG_OFFSET);
92 
93     /* Configure FIFO thresholds */
94     regval = getreg32(reg_base + UART_FIFO_CONFIG_1_OFFSET);
95     regval &= ~UART_TX_FIFO_TH_MASK;
96     regval &= ~UART_RX_FIFO_TH_MASK;
97     regval |= (config->tx_fifo_threshold << UART_TX_FIFO_TH_SHIFT) & UART_TX_FIFO_TH_MASK;
98     regval |= (config->rx_fifo_threshold << UART_RX_FIFO_TH_SHIFT) & UART_RX_FIFO_TH_MASK;
99     putreg32(regval, reg_base + UART_FIFO_CONFIG_1_OFFSET);
100 
101     /* Clear FIFO */
102     regval = getreg32(reg_base + UART_FIFO_CONFIG_0_OFFSET);
103     regval |= UART_TX_FIFO_CLR;
104     regval |= UART_RX_FIFO_CLR;
105     regval &= ~UART_DMA_TX_EN;
106     regval &= ~UART_DMA_RX_EN;
107     putreg32(regval, reg_base + UART_FIFO_CONFIG_0_OFFSET);
108 
109     putreg32(0xFFFFFFFF, reg_base + UART_INT_MASK_OFFSET);
110 
111     /* Enable UART tx rx unit */
112     tx_cfg = getreg32(reg_base + UART_UTX_CONFIG_OFFSET);
113     rx_cfg = getreg32(reg_base + UART_URX_CONFIG_OFFSET);
114     tx_cfg |= UART_CR_UTX_EN;
115     rx_cfg |= UART_CR_URX_EN;
116     putreg32(tx_cfg, reg_base + UART_UTX_CONFIG_OFFSET);
117     putreg32(rx_cfg, reg_base + UART_URX_CONFIG_OFFSET);
118 }
119 
bflb_uart_deinit(struct bflb_device_s * dev)120 void bflb_uart_deinit(struct bflb_device_s *dev)
121 {
122     uint32_t reg_base;
123     uint32_t tx_cfg;
124     uint32_t rx_cfg;
125 
126     reg_base = dev->reg_base;
127     tx_cfg = getreg32(reg_base + UART_UTX_CONFIG_OFFSET);
128     rx_cfg = getreg32(reg_base + UART_URX_CONFIG_OFFSET);
129     tx_cfg &= ~UART_CR_UTX_EN;
130     rx_cfg &= ~UART_CR_URX_EN;
131     putreg32(tx_cfg, reg_base + UART_UTX_CONFIG_OFFSET);
132     putreg32(rx_cfg, reg_base + UART_URX_CONFIG_OFFSET);
133 }
134 
bflb_uart_enable(struct bflb_device_s * dev)135 void bflb_uart_enable(struct bflb_device_s *dev)
136 {
137     uint32_t reg_base;
138     uint32_t tx_cfg;
139     uint32_t rx_cfg;
140 
141     reg_base = dev->reg_base;
142     tx_cfg = getreg32(reg_base + UART_UTX_CONFIG_OFFSET);
143     rx_cfg = getreg32(reg_base + UART_URX_CONFIG_OFFSET);
144     tx_cfg |= UART_CR_UTX_EN;
145     rx_cfg |= UART_CR_URX_EN;
146     putreg32(tx_cfg, reg_base + UART_UTX_CONFIG_OFFSET);
147     putreg32(rx_cfg, reg_base + UART_URX_CONFIG_OFFSET);
148 }
149 
bflb_uart_disable(struct bflb_device_s * dev)150 void bflb_uart_disable(struct bflb_device_s *dev)
151 {
152     uint32_t reg_base;
153     uint32_t tx_cfg;
154     uint32_t rx_cfg;
155 
156     reg_base = dev->reg_base;
157     tx_cfg = getreg32(reg_base + UART_UTX_CONFIG_OFFSET);
158     rx_cfg = getreg32(reg_base + UART_URX_CONFIG_OFFSET);
159     tx_cfg &= ~UART_CR_UTX_EN;
160     rx_cfg &= ~UART_CR_URX_EN;
161     putreg32(tx_cfg, reg_base + UART_UTX_CONFIG_OFFSET);
162     putreg32(rx_cfg, reg_base + UART_URX_CONFIG_OFFSET);
163 }
164 
bflb_uart_link_txdma(struct bflb_device_s * dev,bool enable)165 void bflb_uart_link_txdma(struct bflb_device_s *dev, bool enable)
166 {
167     uint32_t reg_base;
168     uint32_t regval;
169 
170     reg_base = dev->reg_base;
171     regval = getreg32(reg_base + UART_FIFO_CONFIG_0_OFFSET);
172     if (enable) {
173         regval |= UART_DMA_TX_EN;
174     } else {
175         regval &= ~UART_DMA_TX_EN;
176     }
177     putreg32(regval, reg_base + UART_FIFO_CONFIG_0_OFFSET);
178 }
179 
bflb_uart_link_rxdma(struct bflb_device_s * dev,bool enable)180 void bflb_uart_link_rxdma(struct bflb_device_s *dev, bool enable)
181 {
182     uint32_t reg_base;
183     uint32_t regval;
184 
185     reg_base = dev->reg_base;
186     regval = getreg32(reg_base + UART_FIFO_CONFIG_0_OFFSET);
187     if (enable) {
188         regval |= UART_DMA_RX_EN;
189     } else {
190         regval &= ~UART_DMA_RX_EN;
191     }
192     putreg32(regval, reg_base + UART_FIFO_CONFIG_0_OFFSET);
193 }
194 
bflb_uart_putchar(struct bflb_device_s * dev,int ch)195 ATTR_TCM_SECTION int bflb_uart_putchar(struct bflb_device_s *dev, int ch)
196 {
197     uint64_t start_time;
198     uint32_t reg_base;
199 
200     reg_base = dev->reg_base;
201     // start_time = bflb_mtimer_get_time_ms();
202     while ((getreg32(reg_base + UART_FIFO_CONFIG_1_OFFSET) & UART_TX_FIFO_CNT_MASK) == 0) {
203         // if ((bflb_mtimer_get_time_ms() - start_time) > 100) {
204         //     return -ETIMEDOUT;
205         // }
206     }
207     putreg8(ch, reg_base + UART_FIFO_WDATA_OFFSET);
208     return 0;
209 }
210 
bflb_uart_getchar(struct bflb_device_s * dev)211 ATTR_TCM_SECTION int bflb_uart_getchar(struct bflb_device_s *dev)
212 {
213     int ch = -1;
214     uint32_t reg_base;
215 
216     reg_base = dev->reg_base;
217     if ((getreg32(reg_base + UART_FIFO_CONFIG_1_OFFSET) & UART_RX_FIFO_CNT_MASK) != 0) {
218         ch = getreg8(reg_base + UART_FIFO_RDATA_OFFSET);
219     }
220 
221     return ch;
222 }
223 
bflb_uart_put(struct bflb_device_s * dev,uint8_t * data,uint32_t len)224 ATTR_TCM_SECTION int bflb_uart_put(struct bflb_device_s *dev, uint8_t *data, uint32_t len)
225 {
226     int ret;
227     for (uint32_t i = 0; i < len; i++) {
228         ret = bflb_uart_putchar(dev, data[i]);
229         if (ret < 0) {
230             return ret;
231         }
232     }
233     return 0;
234 }
235 
bflb_uart_get(struct bflb_device_s * dev,uint8_t * data,uint32_t len)236 ATTR_TCM_SECTION int bflb_uart_get(struct bflb_device_s *dev, uint8_t *data, uint32_t len)
237 {
238     int ch = -1;
239     uint32_t count = 0;
240 
241     while (count < len) {
242         if ((ch = bflb_uart_getchar(dev)) < 0) {
243             break;
244         }
245         data[count] = ch;
246         count++;
247     }
248     return count;
249 }
250 
bflb_uart_txready(struct bflb_device_s * dev)251 bool bflb_uart_txready(struct bflb_device_s *dev)
252 {
253     uint32_t reg_base;
254 
255     reg_base = dev->reg_base;
256     if ((getreg32(reg_base + UART_FIFO_CONFIG_1_OFFSET) & UART_TX_FIFO_CNT_MASK) != 0) {
257         return true;
258     } else {
259         return false;
260     }
261 }
262 
bflb_uart_txempty(struct bflb_device_s * dev)263 bool bflb_uart_txempty(struct bflb_device_s *dev)
264 {
265     uint32_t reg_base;
266 
267     reg_base = dev->reg_base;
268     if ((getreg32(reg_base + UART_FIFO_CONFIG_1_OFFSET) & UART_TX_FIFO_CNT_MASK) == (UART_TX_FIFO_CNT_MASK >> 1) + 1) {
269         return true;
270     } else {
271         return false;
272     }
273 }
274 
bflb_uart_rxavailable(struct bflb_device_s * dev)275 bool bflb_uart_rxavailable(struct bflb_device_s *dev)
276 {
277     uint32_t reg_base;
278 
279     reg_base = dev->reg_base;
280     return ((getreg32(reg_base + UART_FIFO_CONFIG_1_OFFSET) & UART_RX_FIFO_CNT_MASK) != 0);
281 }
282 
bflb_uart_txint_mask(struct bflb_device_s * dev,bool mask)283 void bflb_uart_txint_mask(struct bflb_device_s *dev, bool mask)
284 {
285     uint32_t reg_base;
286     uint32_t int_mask;
287 
288     reg_base = dev->reg_base;
289     int_mask = getreg32(reg_base + UART_INT_MASK_OFFSET);
290     if (mask) {
291         int_mask |= UART_CR_UTX_FIFO_MASK;
292     } else {
293         int_mask &= ~UART_CR_UTX_FIFO_MASK;
294     }
295     putreg32(int_mask, reg_base + UART_INT_MASK_OFFSET);
296 }
297 
bflb_uart_rxint_mask(struct bflb_device_s * dev,bool mask)298 void bflb_uart_rxint_mask(struct bflb_device_s *dev, bool mask)
299 {
300     uint32_t reg_base;
301     uint32_t int_mask;
302 
303     reg_base = dev->reg_base;
304     int_mask = getreg32(reg_base + UART_INT_MASK_OFFSET);
305     if (mask) {
306         int_mask |= UART_CR_URX_FIFO_MASK;
307         int_mask |= UART_CR_URX_RTO_MASK;
308     } else {
309         int_mask &= ~UART_CR_URX_FIFO_MASK;
310         int_mask &= ~UART_CR_URX_RTO_MASK;
311     }
312     putreg32(int_mask, reg_base + UART_INT_MASK_OFFSET);
313 }
314 
bflb_uart_errint_mask(struct bflb_device_s * dev,bool mask)315 void bflb_uart_errint_mask(struct bflb_device_s *dev, bool mask)
316 {
317     uint32_t reg_base;
318     uint32_t int_mask;
319 
320     reg_base = dev->reg_base;
321     int_mask = getreg32(reg_base + UART_INT_MASK_OFFSET);
322     if (mask) {
323         int_mask |= UART_CR_URX_PCE_MASK;
324         int_mask |= UART_CR_UTX_FER_MASK;
325         int_mask |= UART_CR_URX_FER_MASK;
326 #if !defined(BL602)
327         int_mask |= UART_CR_URX_LSE_MASK;
328 #endif
329     } else {
330         int_mask &= ~UART_CR_URX_PCE_MASK;
331         int_mask &= ~UART_CR_UTX_FER_MASK;
332         int_mask &= ~UART_CR_URX_FER_MASK;
333 #if !defined(BL602)
334         int_mask &= ~UART_CR_URX_LSE_MASK;
335 #endif
336     }
337     putreg32(int_mask, reg_base + UART_INT_MASK_OFFSET);
338 }
339 
bflb_uart_get_intstatus(struct bflb_device_s * dev)340 uint32_t bflb_uart_get_intstatus(struct bflb_device_s *dev)
341 {
342     uint32_t reg_base;
343     uint32_t int_status;
344     uint32_t int_mask;
345 
346     reg_base = dev->reg_base;
347     int_status = getreg32(reg_base + UART_INT_STS_OFFSET);
348     int_mask = getreg32(reg_base + UART_INT_MASK_OFFSET);
349     return (int_status & ~int_mask);
350 }
351 
bflb_uart_int_clear(struct bflb_device_s * dev,uint32_t int_clear)352 void bflb_uart_int_clear(struct bflb_device_s *dev, uint32_t int_clear)
353 {
354     uint32_t reg_base;
355 
356     reg_base = dev->reg_base;
357     putreg32(int_clear, reg_base + UART_INT_CLEAR_OFFSET);
358 }
359 
bflb_uart_feature_control(struct bflb_device_s * dev,int cmd,size_t arg)360 int bflb_uart_feature_control(struct bflb_device_s *dev, int cmd, size_t arg)
361 {
362     int ret = 0;
363     uint32_t reg_base;
364     uint32_t tmp;
365     uint32_t tx_tmp;
366     uint32_t rx_tmp;
367     uint32_t int_mask;
368 
369     reg_base = dev->reg_base;
370 
371     switch (cmd) {
372         case UART_CMD_SET_BAUD_RATE:
373             /* Cal the baud rate divisor */
374             tmp = (bflb_clk_get_peripheral_clock(BFLB_DEVICE_TYPE_UART, dev->idx) * 10 / arg + 5) / 10;
375 
376             putreg32(((tmp - 1) << 0x10) | ((tmp - 1) & 0xFFFF), reg_base + UART_BIT_PRD_OFFSET);
377             break;
378 
379         case UART_CMD_SET_DATA_BITS:
380             /* Set data bits */
381             tx_tmp = getreg32(reg_base + UART_UTX_CONFIG_OFFSET);
382             rx_tmp = getreg32(reg_base + UART_URX_CONFIG_OFFSET);
383 
384             tx_tmp &= ~UART_CR_UTX_BIT_CNT_D_MASK;
385             tx_tmp |= (arg + 4) << UART_CR_UTX_BIT_CNT_D_SHIFT;
386 
387             rx_tmp &= ~UART_CR_URX_BIT_CNT_D_MASK;
388             rx_tmp |= (arg + 4) << UART_CR_URX_BIT_CNT_D_SHIFT;
389 
390             putreg32(tx_tmp, reg_base + UART_UTX_CONFIG_OFFSET);
391             putreg32(rx_tmp, reg_base + UART_URX_CONFIG_OFFSET);
392             break;
393 
394         case UART_CMD_SET_STOP_BITS:
395             /* Set stop bits */
396             tx_tmp = getreg32(reg_base + UART_UTX_CONFIG_OFFSET);
397 
398             tx_tmp &= ~UART_CR_UTX_BIT_CNT_P_MASK;
399             tx_tmp |= arg << UART_CR_UTX_BIT_CNT_P_SHIFT;
400 
401             putreg32(tx_tmp, reg_base + UART_UTX_CONFIG_OFFSET);
402             break;
403 
404         case UART_CMD_SET_PARITY_BITS:
405             /* Set parity mode */
406             tx_tmp = getreg32(reg_base + UART_UTX_CONFIG_OFFSET);
407             rx_tmp = getreg32(reg_base + UART_URX_CONFIG_OFFSET);
408 
409             if (arg == UART_PARITY_NONE) {
410                 tx_tmp &= ~UART_CR_UTX_PRT_EN;
411                 rx_tmp &= ~UART_CR_URX_PRT_EN;
412             } else if (arg == UART_PARITY_ODD) {
413                 tx_tmp |= UART_CR_UTX_PRT_EN;
414                 tx_tmp |= UART_CR_UTX_PRT_SEL;
415                 rx_tmp |= UART_CR_URX_PRT_EN;
416                 rx_tmp |= UART_CR_URX_PRT_SEL;
417             } else if (arg == UART_PARITY_EVEN) {
418                 tx_tmp |= UART_CR_UTX_PRT_EN;
419                 tx_tmp &= ~UART_CR_UTX_PRT_SEL;
420                 rx_tmp |= UART_CR_URX_PRT_EN;
421                 rx_tmp &= ~UART_CR_URX_PRT_SEL;
422             }
423 
424             putreg32(tx_tmp, reg_base + UART_UTX_CONFIG_OFFSET);
425             putreg32(rx_tmp, reg_base + UART_URX_CONFIG_OFFSET);
426             break;
427 
428         case UART_CMD_CLR_TX_FIFO:
429             /* Clear tx fifo */
430             tmp = getreg32(reg_base + UART_FIFO_CONFIG_0_OFFSET);
431             tmp |= UART_TX_FIFO_CLR;
432             putreg32(tmp, reg_base + UART_FIFO_CONFIG_0_OFFSET);
433             break;
434 
435         case UART_CMD_CLR_RX_FIFO:
436             /* Clear rx fifo */
437             tmp = getreg32(reg_base + UART_FIFO_CONFIG_0_OFFSET);
438             tmp |= UART_RX_FIFO_CLR;
439             putreg32(tmp, reg_base + UART_FIFO_CONFIG_0_OFFSET);
440             break;
441 
442         case UART_CMD_SET_RTO_VALUE:
443             /* Set rx time-out value */
444             putreg32(arg, reg_base + UART_URX_RTO_TIMER_OFFSET);
445             break;
446 
447         case UART_CMD_SET_RTS_VALUE:
448 #if defined(BL602)
449 #else
450             /* Set rx rts output software control value */
451             tmp = getreg32(reg_base + UART_SW_MODE_OFFSET);
452             tmp &= ~UART_CR_URX_RTS_SW_VAL;
453             if (arg) {
454                 tmp |= UART_CR_URX_RTS_SW_VAL;
455             }
456             putreg32(tmp, reg_base + UART_SW_MODE_OFFSET);
457 #endif
458             break;
459 
460         case UART_CMD_GET_TX_FIFO_CNT:
461             /* Get tx fifo count */
462             return (getreg32(reg_base + UART_FIFO_CONFIG_1_OFFSET) & UART_TX_FIFO_CNT_MASK) >> UART_TX_FIFO_CNT_SHIFT;
463 
464         case UART_CMD_GET_RX_FIFO_CNT:
465             /* Get rx fifo count */
466             return (getreg32(reg_base + UART_FIFO_CONFIG_1_OFFSET) & UART_RX_FIFO_CNT_MASK) >> UART_RX_FIFO_CNT_SHIFT;
467 
468         case UART_CMD_SET_AUTO_BAUD:
469             /* Set auto baudrate detection  */
470             tmp = getreg32(reg_base + UART_URX_CONFIG_OFFSET);
471             rx_tmp = getreg32(reg_base + UART_INT_MASK_OFFSET);
472             tmp &= ~UART_CR_URX_ABR_EN;
473             if (arg == UART_AUTO_BAUD_0X55) {
474                 tmp |= UART_CR_URX_ABR_EN;
475 #if !defined(BL602) && !defined(BL702)
476                 rx_tmp &= ~UART_CR_URX_AD5_MASK;
477 #endif
478             } else {
479                 tmp |= UART_CR_URX_ABR_EN;
480 #if !defined(BL602) && !defined(BL702)
481                 rx_tmp &= ~UART_CR_URX_ADS_MASK;
482 #endif
483             }
484 
485             putreg32(tmp, reg_base + UART_URX_CONFIG_OFFSET);
486             putreg32(rx_tmp, reg_base + UART_INT_MASK_OFFSET);
487             break;
488 
489         case UART_CMD_GET_AUTO_BAUD:
490             /* Get auto baudrate detection count value */
491             tmp = getreg32(reg_base + UART_STS_URX_ABR_PRD_OFFSET);
492             if (arg == UART_AUTO_BAUD_START) {
493                 return (tmp & UART_STS_URX_ABR_PRD_START_MASK);
494             } else {
495                 return ((tmp & UART_STS_URX_ABR_PRD_0X55_MASK) >> UART_STS_URX_ABR_PRD_0X55_SHIFT);
496             }
497 #if !defined(BL602)
498         case UART_CMD_SET_BREAK_VALUE:
499             /* Set lin mode break value */
500             tx_tmp = getreg32(reg_base + UART_UTX_CONFIG_OFFSET);
501 
502             tx_tmp &= ~UART_CR_UTX_BIT_CNT_B_MASK;
503             tx_tmp |= arg << UART_CR_UTX_BIT_CNT_B_SHIFT;
504 
505             putreg32(tx_tmp, reg_base + UART_UTX_CONFIG_OFFSET);
506             break;
507 
508         case UART_CMD_SET_TX_LIN_VALUE:
509             /* Set tx lin mode */
510             tx_tmp = getreg32(reg_base + UART_UTX_CONFIG_OFFSET);
511             tx_tmp &= ~UART_CR_UTX_LIN_EN;
512             if (arg) {
513                 tx_tmp |= UART_CR_UTX_LIN_EN;
514             }
515 
516             putreg32(tx_tmp, reg_base + UART_UTX_CONFIG_OFFSET);
517             break;
518 
519         case UART_CMD_SET_RX_LIN_VALUE:
520             /* Set rx lin mode */
521             rx_tmp = getreg32(reg_base + UART_URX_CONFIG_OFFSET);
522             rx_tmp &= ~UART_CR_URX_LIN_EN;
523             if (arg) {
524                 rx_tmp |= UART_CR_URX_LIN_EN;
525             }
526 
527             putreg32(rx_tmp, reg_base + UART_URX_CONFIG_OFFSET);
528             break;
529 #endif
530         case UART_CMD_SET_GLITCH_VALUE:
531             rx_tmp = getreg32(reg_base + UART_URX_CONFIG_OFFSET);
532             rx_tmp &= ~UART_CR_URX_DEG_CNT_MASK;
533             rx_tmp &= ~UART_CR_URX_DEG_EN;
534             if (arg) {
535                 rx_tmp |= (arg << UART_CR_URX_DEG_CNT_SHIFT) & UART_CR_URX_DEG_CNT_MASK;
536                 rx_tmp |= UART_CR_URX_DEG_EN;
537             }
538             putreg32(rx_tmp, reg_base + UART_URX_CONFIG_OFFSET);
539             break;
540 #if !defined(BL602) && !defined(BL702)
541         case UART_CMD_SET_TX_RS485_EN:
542             /* Set tx rs485 transceiver enable */
543             tx_tmp = getreg32(reg_base + UART_UTX_RS485_CFG_OFFSET);
544             tx_tmp &= ~UART_CR_UTX_RS485_EN;
545 
546             if (arg) {
547                 tx_tmp |= UART_CR_UTX_RS485_EN;
548             }
549 
550             putreg32(tx_tmp, reg_base + UART_UTX_RS485_CFG_OFFSET);
551             break;
552 
553         case UART_CMD_SET_TX_RS485_POLARITY:
554             /* Set tx rs485 de pin polarity */
555             tx_tmp = getreg32(reg_base + UART_UTX_RS485_CFG_OFFSET);
556             tx_tmp &= ~UART_CR_UTX_RS485_POL;
557 
558             if (arg) {
559                 tx_tmp |= UART_CR_UTX_RS485_POL;
560             }
561 
562             putreg32(tx_tmp, reg_base + UART_UTX_RS485_CFG_OFFSET);
563             break;
564 
565         case UART_CMD_SET_ABR_ALLOWABLE_ERROR:
566             /* Set auto baudrate detection mode pulse-width tolerance value for codeword 0x55 */
567             rx_tmp = getreg32(reg_base + UART_URX_ABR_PW_TOL_OFFSET);
568             rx_tmp &= ~UART_CR_URX_ABR_PW_TOL_MASK;
569             rx_tmp |= arg << UART_CR_URX_ABR_PW_TOL_SHIFT;
570 
571             putreg32(rx_tmp, reg_base + UART_URX_ABR_PW_TOL_OFFSET);
572             break;
573 #endif
574         case UART_CMD_SET_SW_RTS_CONTROL:
575 #if defined(BL602)
576             if (arg) {
577                 rx_tmp = getreg32(reg_base + UART_URX_CONFIG_OFFSET);
578                 rx_tmp |= UART_CR_URX_RTS_SW_MODE;
579                 putreg32(rx_tmp, reg_base + UART_URX_CONFIG_OFFSET);
580             } else {
581                 rx_tmp = getreg32(reg_base + UART_URX_CONFIG_OFFSET);
582                 rx_tmp &= ~UART_CR_URX_RTS_SW_MODE;
583                 putreg32(rx_tmp, reg_base + UART_URX_CONFIG_OFFSET);
584             }
585 #else
586             if (arg) {
587                 rx_tmp = getreg32(reg_base + UART_SW_MODE_OFFSET);
588                 rx_tmp |= UART_CR_URX_RTS_SW_MODE;
589                 putreg32(rx_tmp, reg_base + UART_SW_MODE_OFFSET);
590 
591             } else {
592                 rx_tmp = getreg32(reg_base + UART_SW_MODE_OFFSET);
593                 rx_tmp &= ~UART_CR_URX_RTS_SW_MODE;
594                 putreg32(rx_tmp, reg_base + UART_SW_MODE_OFFSET);
595             }
596 #endif
597             break;
598 #if !defined(BL702L)
599         case UART_CMD_IR_CONFIG: {
600             struct bflb_uart_ir_config_s *ir_config = (struct bflb_uart_ir_config_s *)arg;
601             tx_tmp = getreg32(reg_base + UART_UTX_CONFIG_OFFSET);
602             if (ir_config->tx_en) {
603                 tx_tmp |= UART_CR_UTX_IR_EN;
604             } else {
605                 tx_tmp &= ~UART_CR_UTX_IR_EN;
606             }
607             if (ir_config->tx_inverse) {
608                 tx_tmp |= UART_CR_UTX_IR_INV;
609             } else {
610                 tx_tmp &= ~UART_CR_UTX_IR_INV;
611             }
612             putreg32(tx_tmp, reg_base + UART_UTX_CONFIG_OFFSET);
613 
614             rx_tmp = getreg32(reg_base + UART_URX_CONFIG_OFFSET);
615             if (ir_config->rx_en) {
616                 rx_tmp |= UART_CR_URX_IR_EN;
617             } else {
618                 rx_tmp &= ~UART_CR_URX_IR_EN;
619             }
620             if (ir_config->rx_inverse) {
621                 rx_tmp |= UART_CR_URX_IR_INV;
622             } else {
623                 rx_tmp &= ~UART_CR_URX_IR_INV;
624             }
625             putreg32(rx_tmp, reg_base + UART_URX_CONFIG_OFFSET);
626             /* Configure tx ir pulse start and stop position */
627             putreg32((ir_config->tx_pluse_stop << 16) | ir_config->tx_pluse_start, reg_base + UART_UTX_IR_POSITION_OFFSET);
628             /* Configure rx ir pulse start position */
629             putreg32(ir_config->rx_pluse_start, reg_base + UART_URX_IR_POSITION_OFFSET);
630         } break;
631 #endif
632         case UART_CMD_SET_TX_FREERUN:
633             /* Set tx freerun */
634             tx_tmp = getreg32(reg_base + UART_UTX_CONFIG_OFFSET);
635 
636             if (arg) {
637                 tx_tmp |= UART_CR_UTX_FRM_EN;
638             } else {
639                 tx_tmp &= ~UART_CR_UTX_FRM_EN;
640             }
641 
642             putreg32(tx_tmp, reg_base + UART_UTX_CONFIG_OFFSET);
643             break;
644         case UART_CMD_SET_TX_END_INTERRUPT:
645             /* Set tx end interrupt */
646             int_mask = getreg32(reg_base + UART_INT_MASK_OFFSET);
647             if (arg) {
648                 int_mask &= ~UART_CR_UTX_END_MASK;
649             } else {
650                 int_mask |= UART_CR_UTX_END_MASK;
651             }
652             putreg32(int_mask, reg_base + UART_INT_MASK_OFFSET);
653             break;
654         case UART_CMD_SET_RX_END_INTERRUPT:
655             /* Set rx end interrupt */
656             int_mask = getreg32(reg_base + UART_INT_MASK_OFFSET);
657             if (arg) {
658                 int_mask &= ~UART_CR_URX_END_MASK;
659             } else {
660                 int_mask |= UART_CR_URX_END_MASK;
661             }
662             putreg32(int_mask, reg_base + UART_INT_MASK_OFFSET);
663             break;
664         case UART_CMD_SET_TX_TRANSFER_LEN:
665             /* Set tx transfer length */
666             tx_tmp = getreg32(reg_base + UART_UTX_CONFIG_OFFSET);
667             tx_tmp &= ~UART_CR_UTX_LEN_MASK;
668             tx_tmp |= ((arg - 1) << UART_CR_UTX_LEN_SHIFT);
669             putreg32(tx_tmp, reg_base + UART_UTX_CONFIG_OFFSET);
670             break;
671         case UART_CMD_SET_RX_TRANSFER_LEN:
672             /* Set rx transfer length */
673             rx_tmp = getreg32(reg_base + UART_URX_CONFIG_OFFSET);
674             rx_tmp &= ~UART_CR_URX_LEN_MASK;
675             rx_tmp |= ((arg - 1) << UART_CR_URX_LEN_SHIFT);
676             putreg32(rx_tmp, reg_base + UART_URX_CONFIG_OFFSET);
677             break;
678         case UART_CMD_SET_TX_EN:
679             /* Set tx enable */
680             tx_tmp = getreg32(reg_base + UART_UTX_CONFIG_OFFSET);
681 
682             if (arg) {
683                 tx_tmp |= UART_CR_UTX_EN;
684             } else {
685                 tx_tmp &= ~UART_CR_UTX_EN;
686             }
687 
688             putreg32(tx_tmp, reg_base + UART_UTX_CONFIG_OFFSET);
689             break;
690 #if !defined(BL602) && !defined(BL702)
691         case UART_CMD_SET_BCR_END_INTERRUPT:
692             /* Set bcr value */
693             int_mask = getreg32(reg_base + UART_INT_MASK_OFFSET);
694             int_mask &= ~UART_CR_URX_BCR_MASK;
695             putreg32(int_mask, reg_base + UART_INT_MASK_OFFSET);
696 
697             rx_tmp = getreg32(reg_base + UART_URX_BCR_INT_CFG_OFFSET);
698             rx_tmp &= ~UART_CR_URX_BCR_VALUE_MASK;
699             rx_tmp |= (arg << UART_CR_URX_BCR_VALUE_SHIFT);
700             putreg32(rx_tmp, reg_base + UART_URX_BCR_INT_CFG_OFFSET);
701             break;
702         case UART_CMD_GET_BCR_COUNT:
703             /* Get bcr value */
704             rx_tmp = getreg32(reg_base + UART_URX_BCR_INT_CFG_OFFSET);
705             return ((rx_tmp & UART_STS_URX_BCR_COUNT_MASK) >> UART_STS_URX_BCR_COUNT_SHIFT);
706             break;
707 #endif
708         case UART_CMD_SET_CTS_EN:
709             tx_tmp = getreg32(reg_base + UART_UTX_CONFIG_OFFSET);
710             if (arg) {
711                 tx_tmp |= UART_CR_UTX_CTS_EN;
712             } else {
713                 tx_tmp &= ~UART_CR_UTX_CTS_EN;
714             }
715             putreg32(tx_tmp, reg_base + UART_UTX_CONFIG_OFFSET);
716         case UART_CMD_SET_TX_FIFO_THREHOLD:
717             tx_tmp = getreg32(reg_base + UART_FIFO_CONFIG_1_OFFSET);
718             tx_tmp &= ~UART_TX_FIFO_TH_MASK;
719             tx_tmp |= (arg << UART_TX_FIFO_TH_SHIFT) & UART_TX_FIFO_TH_MASK;
720             putreg32(tx_tmp, reg_base + UART_FIFO_CONFIG_1_OFFSET);
721         case UART_CMD_SET_RX_FIFO_THREHOLD:
722             rx_tmp = getreg32(reg_base + UART_FIFO_CONFIG_1_OFFSET);
723             rx_tmp &= ~UART_RX_FIFO_TH_MASK;
724             rx_tmp |= (arg << UART_RX_FIFO_TH_SHIFT) & UART_RX_FIFO_TH_MASK;
725             putreg32(rx_tmp, reg_base + UART_FIFO_CONFIG_1_OFFSET);
726         default:
727             ret = -EPERM;
728             break;
729     }
730     return ret;
731 }
732