1
1
/*
2
2
* Copyright (c) Core Devices LLC
3
+ * Copyright (c) Qingsong Gou <gouqs@hotmail.com>
3
4
* SPDX-License-Identifier: Apache-2.0
4
5
*/
5
6
11
12
#include <zephyr/drivers/clock_control/sf32lb.h>
12
13
#include <zephyr/drivers/pinctrl.h>
13
14
#include <zephyr/drivers/uart.h>
15
+ #include <zephyr/irq.h>
14
16
15
17
#include <register.h>
16
18
19
+ #define UART_REG (reg ) ((config->base) + (reg))
20
+
17
21
#define UART_CR1 offsetof(USART_TypeDef, CR1)
18
22
#define UART_CR2 offsetof(USART_TypeDef, CR2)
19
23
#define UART_CR3 offsetof(USART_TypeDef, CR3)
32
36
#define UART_CR2_STOP_1B FIELD_PREP(USART_CR2_STOP_Msk, 0U)
33
37
#define UART_CR2_STOP_2B FIELD_PREP(USART_CR2_STOP_Msk, 1U)
34
38
39
+ #define UART_FLAG_IS_SET (flag ) \
40
+ sys_test_bit(UART_REG(UART_ISR), flag)
41
+
42
+ #define UART_FLAG_CLEAR (flag ) \
43
+ sys_clear_bit(UART_REG(UART_ICR), flag)
44
+
35
45
/* minimal BRR: INT=1, FRAC=0 (0x10) */
36
46
#define UART_BRR_MIN 0x10U
37
47
48
+ struct uart_sf32lb_data {
49
+ #ifdef CONFIG_UART_INTERRUPT_DRIVEN
50
+ uart_irq_callback_user_data_t irq_callback ;
51
+ void * cb_data ;
52
+ #endif
53
+ };
54
+
38
55
struct uart_sf32lb_config {
39
56
uintptr_t base ;
40
57
const struct pinctrl_dev_config * pcfg ;
41
58
struct sf32lb_clock_dt_spec clock ;
42
59
struct uart_config uart_cfg ;
60
+ #if CONFIG_UART_INTERRUPT_DRIVEN
61
+ void (* irq_config_func )(const struct device * dev );
62
+ #endif
43
63
};
44
64
65
+ #if defined(CONFIG_UART_INTERRUPT_DRIVEN )
66
+ static void uart_sf32lb_isr (const struct device * dev )
67
+ {
68
+ const struct uart_sf32lb_config * config = dev -> config ;
69
+ struct uart_sf32lb_data * data = dev -> data ;
70
+
71
+ #ifdef CONFIG_UART_INTERRUPT_DRIVEN
72
+ if (data -> irq_callback ) {
73
+ data -> irq_callback (dev , data -> cb_data );
74
+ }
75
+ #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
76
+ if (UART_FLAG_IS_SET (USART_ISR_ORE_Pos )) {
77
+ UART_FLAG_CLEAR (USART_ICR_ORECF_Pos );
78
+ }
79
+ if (UART_FLAG_IS_SET (USART_ISR_NF_Pos )) {
80
+ UART_FLAG_CLEAR (USART_ICR_NCF_Pos );
81
+ }
82
+ if (UART_FLAG_IS_SET (USART_ISR_FE_Pos )) {
83
+ UART_FLAG_CLEAR (USART_ICR_FECF_Pos );
84
+ }
85
+ if (UART_FLAG_IS_SET (USART_ISR_PE_Pos )) {
86
+ UART_FLAG_CLEAR (USART_ICR_PECF_Pos );
87
+ }
88
+
89
+ if (UART_FLAG_IS_SET (USART_ISR_CTS_Pos )) {
90
+ UART_FLAG_CLEAR (USART_ISR_CTS_Pos );
91
+ }
92
+ if (UART_FLAG_IS_SET (USART_ISR_TXE_Pos )) {
93
+ UART_FLAG_CLEAR (USART_ISR_TXE_Pos );
94
+ }
95
+ if (UART_FLAG_IS_SET (USART_ISR_TC_Pos )) {
96
+ UART_FLAG_CLEAR (USART_ISR_TC_Pos );
97
+ }
98
+ if (UART_FLAG_IS_SET (USART_ISR_RXNE_Pos )) {
99
+ UART_FLAG_CLEAR (USART_ISR_RXNE_Pos );
100
+ }
101
+ }
102
+ #endif
103
+
45
104
static int uart_sf32lb_configure (const struct device * dev , const struct uart_config * cfg )
46
105
{
47
106
const struct uart_sf32lb_config * config = dev -> config ;
@@ -177,9 +236,137 @@ static void uart_sf32lb_poll_out(const struct device *dev, uint8_t c)
177
236
}
178
237
}
179
238
239
+ #ifdef CONFIG_UART_INTERRUPT_DRIVEN
240
+ static int uart_sf32lb_fifo_fill (const struct device * dev , const uint8_t * tx_data , int len )
241
+ {
242
+ const struct uart_sf32lb_config * config = dev -> config ;
243
+ int i ;
244
+
245
+ for (i = 0 ; i < len ; i ++ ) {
246
+ if ((sys_read32 (config -> base + UART_ISR ) & USART_ISR_TXE ) == 0U ) {
247
+ break ;
248
+ }
249
+ sys_write8 (tx_data [i ], config -> base + UART_TDR );
250
+ }
251
+
252
+ return i ;
253
+ }
254
+
255
+ static int uart_sf32lb_fifo_read (const struct device * dev , uint8_t * rx_data , const int size )
256
+ {
257
+ const struct uart_sf32lb_config * config = dev -> config ;
258
+ int i ;
259
+
260
+ for (i = 0 ; i < size ; i ++ ) {
261
+ if ((sys_read32 (config -> base + UART_ISR ) & USART_ISR_RXNE ) == 0U ) {
262
+ break ;
263
+ }
264
+ rx_data [i ] = sys_read32 (config -> base + UART_RDR ) & 0xFF ;
265
+ }
266
+
267
+ return i ;
268
+ }
269
+
270
+ static void uart_sf32lb_irq_tx_enable (const struct device * dev )
271
+ {
272
+ const struct uart_sf32lb_config * config = dev -> config ;
273
+
274
+ sys_set_bit (config -> base + UART_CR1 , USART_CR1_TE_Pos );
275
+ }
276
+
277
+ static void uart_sf32lb_irq_tx_disable (const struct device * dev )
278
+ {
279
+ const struct uart_sf32lb_config * config = dev -> config ;
280
+
281
+ sys_clear_bit (config -> base + UART_CR1 , USART_CR1_TE_Pos );
282
+ }
283
+
284
+ static int uart_sf32lb_irq_tx_ready (const struct device * dev )
285
+ {
286
+ const struct uart_sf32lb_config * config = dev -> config ;
287
+
288
+ return sys_test_bit (config -> base + UART_ISR , USART_ISR_TXE_Pos );
289
+ }
290
+
291
+ static int uart_sf32lb_irq_tx_complete (const struct device * dev )
292
+ {
293
+ const struct uart_sf32lb_config * config = dev -> config ;
294
+
295
+ return sys_test_bit (config -> base + UART_ISR , USART_ISR_TC_Pos );
296
+ }
297
+
298
+ static int uart_sf32lb_irq_rx_ready (const struct device * dev )
299
+ {
300
+ const struct uart_sf32lb_config * config = dev -> config ;
301
+
302
+ return sys_test_bit (config -> base + UART_ISR , USART_ISR_RXNE_Pos );
303
+ }
304
+
305
+ static void uart_sf32lb_irq_err_enable (const struct device * dev )
306
+ {
307
+ const struct uart_sf32lb_config * config = dev -> config ;
308
+
309
+ sys_set_bit (config -> base + UART_CR1 , USART_CR1_PEIE_Pos );
310
+ sys_set_bit (config -> base + UART_CR3 , USART_CR3_EIE_Pos );
311
+ }
312
+
313
+ static void uart_sf32lb_irq_err_disable (const struct device * dev )
314
+ {
315
+ const struct uart_sf32lb_config * config = dev -> config ;
316
+
317
+ sys_clear_bit (config -> base + UART_CR1 , USART_CR1_PEIE_Pos );
318
+ sys_clear_bit (config -> base + UART_CR3 , USART_CR3_EIE_Pos );
319
+ }
320
+
321
+ static int uart_sf32lb_irq_is_pending (const struct device * dev )
322
+ {
323
+ const struct uart_sf32lb_config * config = dev -> config ;
324
+
325
+ return sys_read32 (config -> base + UART_ISR ) == 0U ? 0 : 1 ;
326
+ }
327
+
328
+ static void uart_sf32lb_irq_callback_set (const struct device * dev , uart_irq_callback_user_data_t cb ,
329
+ void * user_data )
330
+ {
331
+ struct uart_sf32lb_data * data = dev -> data ;
332
+
333
+ data -> irq_callback = cb ;
334
+ data -> cb_data = user_data ;
335
+ }
336
+
337
+ static void uart_sf32lb_irq_rx_enable (const struct device * dev )
338
+ {
339
+ const struct uart_sf32lb_config * config = dev -> config ;
340
+
341
+ sys_set_bit (config -> base + UART_CR3 , USART_ISR_RXNE );
342
+ }
343
+
344
+ static void uart_sf32lb_irq_rx_disable (const struct device * dev )
345
+ {
346
+ const struct uart_sf32lb_config * config = dev -> config ;
347
+
348
+ sys_clear_bit (config -> base + UART_CR3 , USART_ISR_RXNE );
349
+ }
350
+ #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
351
+
180
352
static const struct uart_driver_api uart_sf32lb_api = {
181
353
.poll_in = uart_sf32lb_poll_in ,
182
354
.poll_out = uart_sf32lb_poll_out ,
355
+ #ifdef CONFIG_UART_INTERRUPT_DRIVEN
356
+ .fifo_fill = uart_sf32lb_fifo_fill ,
357
+ .fifo_read = uart_sf32lb_fifo_read ,
358
+ .irq_tx_enable = uart_sf32lb_irq_tx_enable ,
359
+ .irq_tx_disable = uart_sf32lb_irq_tx_disable ,
360
+ .irq_tx_complete = uart_sf32lb_irq_tx_complete ,
361
+ .irq_tx_ready = uart_sf32lb_irq_tx_ready ,
362
+ .irq_rx_enable = uart_sf32lb_irq_rx_enable ,
363
+ .irq_rx_disable = uart_sf32lb_irq_rx_disable ,
364
+ .irq_rx_ready = uart_sf32lb_irq_rx_ready ,
365
+ .irq_err_enable = uart_sf32lb_irq_err_enable ,
366
+ .irq_err_disable = uart_sf32lb_irq_err_disable ,
367
+ .irq_is_pending = uart_sf32lb_irq_is_pending ,
368
+ .irq_callback_set = uart_sf32lb_irq_callback_set ,
369
+ #endif
183
370
};
184
371
185
372
static int uart_sf32lb_init (const struct device * dev )
@@ -208,11 +395,22 @@ static int uart_sf32lb_init(const struct device *dev)
208
395
return ret ;
209
396
}
210
397
398
+ #if CONFIG_UART_INTERRUPT_DRIVEN
399
+ config -> irq_config_func (dev );
400
+ #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
401
+
211
402
return 0 ;
212
403
}
213
404
214
405
#define SF32LB_UART_DEFINE (index ) \
215
406
PINCTRL_DT_INST_DEFINE(index); \
407
+ IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \
408
+ (static void uart_sf32lb_irq_config_func_##index(const struct device *dev) \
409
+ { \
410
+ IRQ_CONNECT(DT_INST_IRQN(index), DT_INST_IRQ(index, priority), uart_sf32lb_isr, \
411
+ DEVICE_DT_INST_GET(index), 0); \
412
+ irq_enable(DT_INST_IRQN(index)); \
413
+ })); \
216
414
\
217
415
static const struct uart_sf32lb_config uart_sf32lb_cfg_##index = { \
218
416
.base = DT_INST_REG_ADDR(index), \
@@ -231,9 +429,14 @@ static int uart_sf32lb_init(const struct device *dev)
231
429
? UART_CFG_FLOW_CTRL_RTS_CTS \
232
430
: UART_CFG_FLOW_CTRL_NONE, \
233
431
}, \
432
+ IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \
433
+ (.irq_config_func = uart_sf32lb_irq_config_func_##index,)) \
234
434
}; \
235
435
\
236
- DEVICE_DT_INST_DEFINE(index, uart_sf32lb_init, NULL, NULL, &uart_sf32lb_cfg_##index, \
237
- PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, &uart_sf32lb_api);
436
+ static struct uart_sf32lb_data uart_sf32lb_data_##index; \
437
+ \
438
+ DEVICE_DT_INST_DEFINE(index, uart_sf32lb_init, NULL, \
439
+ &uart_sf32lb_data_##index, &uart_sf32lb_cfg_##index, PRE_KERNEL_1, \
440
+ CONFIG_SERIAL_INIT_PRIORITY, &uart_sf32lb_api);
238
441
239
442
DT_INST_FOREACH_STATUS_OKAY (SF32LB_UART_DEFINE )
0 commit comments