1
1
/*
2
2
* Copyright (c) 2018 Diego Sueiro <[email protected] >
3
+ * Copyright (c) 2022 Antonio Tessarolo <[email protected] >
3
4
*
4
5
* SPDX-License-Identifier: Apache-2.0
5
6
*/
23
24
#include <zephyr/drivers/pinctrl.h>
24
25
#include <zephyr/irq.h>
25
26
26
- #define UART_STRUCT (dev ) \
27
- ((UART_Type *)((const struct imx_uart_config *const)(dev)->config)->base)
27
+ #define UART_STRUCT (dev ) ((UART_Type *)((const struct imx_uart_config *const)(dev)->config)->base)
28
+
29
+ /* FIFO real size is 32 but irq may rise when there are 2 bytes in the queue */
30
+ #define UART_FIFO_SIZE 30u
28
31
29
32
struct imx_uart_config {
30
33
UART_Type * base ;
@@ -33,16 +36,27 @@ struct imx_uart_config {
33
36
const struct pinctrl_dev_config * pincfg ;
34
37
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
35
38
void (* irq_config_func )(const struct device * dev );
39
+ bool rs485_enabled ;
40
+ bool rs485_de_active_low ;
41
+ uint32_t rs485_de_timeout ;
36
42
#endif
37
43
};
38
44
39
45
struct imx_uart_data {
40
46
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
41
47
uart_irq_callback_user_data_t callback ;
42
48
void * cb_data ;
49
+ struct k_timer rs485_timer ;
43
50
#endif
44
51
};
45
52
53
+ static void rs485_de_time_expire_callback (struct k_timer * timer )
54
+ {
55
+ UART_Type * uart = k_timer_user_data_get (timer );
56
+
57
+ UART_SetIntCmd (uart , uartIntTxReady , true);
58
+ }
59
+
46
60
/**
47
61
* @brief Initialize UART channel
48
62
*
@@ -57,28 +71,27 @@ static int uart_imx_init(const struct device *dev)
57
71
{
58
72
UART_Type * uart = UART_STRUCT (dev );
59
73
const struct imx_uart_config * config = dev -> config ;
74
+ struct imx_uart_data * data = dev -> data ;
60
75
unsigned int old_level ;
61
76
int err ;
62
77
63
78
/* disable interrupts */
64
79
old_level = irq_lock ();
65
80
66
81
/* Setup UART init structure */
67
- uart_init_config_t initConfig = {
68
- .baudRate = config -> baud_rate ,
69
- .wordLength = uartWordLength8Bits ,
70
- .stopBitNum = uartStopBitNumOne ,
71
- .parity = uartParityDisable ,
72
- .direction = uartDirectionTxRx
73
- };
82
+ uart_init_config_t initConfig = {.baudRate = config -> baud_rate ,
83
+ .wordLength = uartWordLength8Bits ,
84
+ .stopBitNum = uartStopBitNumOne ,
85
+ .parity = uartParityDisable ,
86
+ .direction = uartDirectionTxRx };
74
87
75
88
err = pinctrl_apply_state (config -> pincfg , PINCTRL_STATE_DEFAULT );
76
89
if (err ) {
77
90
return err ;
78
91
}
79
92
80
93
/* Get current module clock frequency */
81
- initConfig .clockRate = get_uart_clock_freq (uart );
94
+ initConfig .clockRate = get_uart_clock_freq (uart );
82
95
83
96
UART_Init (uart , & initConfig );
84
97
@@ -93,6 +106,12 @@ static int uart_imx_init(const struct device *dev)
93
106
config -> irq_config_func (dev );
94
107
#endif
95
108
109
+ if (config -> rs485_enabled ) {
110
+ UART_SetCtsPinLevel (uart , !config -> rs485_de_active_low );
111
+ k_timer_init (& data -> rs485_timer , rs485_de_time_expire_callback , NULL );
112
+ k_timer_user_data_set (& data -> rs485_timer , uart );
113
+ }
114
+
96
115
/* Set UART modem mode */
97
116
UART_SetModemMode (uart , config -> modem_mode );
98
117
@@ -130,31 +149,28 @@ static int uart_imx_poll_in(const struct device *dev, unsigned char *c)
130
149
131
150
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
132
151
133
- static int uart_imx_fifo_fill (const struct device * dev ,
134
- const uint8_t * tx_data ,
135
- int size )
152
+ static int uart_imx_fifo_fill (const struct device * dev , const uint8_t * tx_data , int size )
136
153
{
137
154
UART_Type * uart = UART_STRUCT (dev );
138
155
unsigned int num_tx = 0U ;
139
156
140
- while (((size - num_tx ) > 0 ) &&
141
- UART_GetStatusFlag (uart , uartStatusTxReady )) {
142
- /* Send a character */
143
- UART_Putchar (uart , tx_data [num_tx ]);
144
- num_tx ++ ;
157
+ if (UART_GetStatusFlag (uart , uartStatusTxReady )) {
158
+ while (((size - num_tx ) > 0 ) && (num_tx < UART_FIFO_SIZE )) {
159
+ /* Send a character */
160
+ UART_Putchar (uart , tx_data [num_tx ]);
161
+ num_tx ++ ;
162
+ }
145
163
}
146
164
147
165
return (int )num_tx ;
148
166
}
149
167
150
- static int uart_imx_fifo_read (const struct device * dev , uint8_t * rx_data ,
151
- const int size )
168
+ static int uart_imx_fifo_read (const struct device * dev , uint8_t * rx_data , const int size )
152
169
{
153
170
UART_Type * uart = UART_STRUCT (dev );
154
171
unsigned int num_rx = 0U ;
155
172
156
- while (((size - num_rx ) > 0 ) &&
157
- UART_GetStatusFlag (uart , uartStatusRxReady )) {
173
+ while (((size - num_rx ) > 0 ) && UART_GetStatusFlag (uart , uartStatusRxReady )) {
158
174
/* Receive a character */
159
175
rx_data [num_rx ++ ] = UART_Getchar (uart );
160
176
}
@@ -163,19 +179,36 @@ static int uart_imx_fifo_read(const struct device *dev, uint8_t *rx_data,
163
179
UART_ClearStatusFlag (uart , uartStatusRxOverrun );
164
180
}
165
181
166
- return num_rx ;
182
+ return ( int ) num_rx ;
167
183
}
168
184
169
185
static void uart_imx_irq_tx_enable (const struct device * dev )
170
186
{
171
187
UART_Type * uart = UART_STRUCT (dev );
188
+ const struct imx_uart_config * config = dev -> config ;
189
+ struct imx_uart_data * data = dev -> data ;
172
190
173
- UART_SetIntCmd (uart , uartIntTxReady , true);
191
+ if (config -> rs485_enabled ) {
192
+ UART_SetCtsPinLevel (uart , config -> rs485_de_active_low );
193
+ if (config -> rs485_de_timeout ) {
194
+ k_timer_start (& data -> rs485_timer , K_USEC (config -> rs485_de_timeout ),
195
+ K_NO_WAIT );
196
+ } else {
197
+ UART_SetIntCmd (uart , uartIntTxReady , true);
198
+ }
199
+ } else {
200
+ UART_SetIntCmd (uart , uartIntTxReady , true);
201
+ }
174
202
}
175
203
176
204
static void uart_imx_irq_tx_disable (const struct device * dev )
177
205
{
178
206
UART_Type * uart = UART_STRUCT (dev );
207
+ const struct imx_uart_config * config = dev -> config ;
208
+
209
+ if (config -> rs485_enabled ) {
210
+ UART_SetIntCmd (uart , uartIntTxComplete , true);
211
+ }
179
212
180
213
UART_SetIntCmd (uart , uartIntTxReady , false);
181
214
}
@@ -187,9 +220,27 @@ static int uart_imx_irq_tx_ready(const struct device *dev)
187
220
return UART_GetStatusFlag (uart , uartStatusTxReady );
188
221
}
189
222
223
+ static int uart_imx_irq_tx_complete (const struct device * dev )
224
+ {
225
+ UART_Type * uart = UART_STRUCT (dev );
226
+ const struct imx_uart_config * config = dev -> config ;
227
+ bool complete = UART_GetStatusFlag (uart , uartStatusTxComplete );
228
+
229
+ if (config -> rs485_enabled && complete ) {
230
+ UART_SetIntCmd (uart , uartIntTxComplete , false);
231
+ }
232
+
233
+ return complete ;
234
+ }
235
+
190
236
static void uart_imx_irq_rx_enable (const struct device * dev )
191
237
{
192
238
UART_Type * uart = UART_STRUCT (dev );
239
+ const struct imx_uart_config * config = dev -> config ;
240
+
241
+ if (config -> rs485_enabled ) {
242
+ UART_SetCtsPinLevel (uart , !config -> rs485_de_active_low );
243
+ }
193
244
194
245
UART_SetIntCmd (uart , uartIntRxReady , true);
195
246
}
@@ -229,16 +280,15 @@ static int uart_imx_irq_is_pending(const struct device *dev)
229
280
UART_Type * uart = UART_STRUCT (dev );
230
281
231
282
return UART_GetStatusFlag (uart , uartStatusRxReady ) ||
232
- UART_GetStatusFlag (uart , uartStatusTxReady );
283
+ UART_GetStatusFlag (uart , uartStatusTxReady );
233
284
}
234
285
235
286
static int uart_imx_irq_update (const struct device * dev )
236
287
{
237
288
return 1 ;
238
289
}
239
290
240
- static void uart_imx_irq_callback_set (const struct device * dev ,
241
- uart_irq_callback_user_data_t cb ,
291
+ static void uart_imx_irq_callback_set (const struct device * dev , uart_irq_callback_user_data_t cb ,
242
292
void * cb_data )
243
293
{
244
294
struct imx_uart_data * data = dev -> data ;
@@ -272,68 +322,64 @@ static DEVICE_API(uart, uart_imx_driver_api) = {
272
322
.poll_out = uart_imx_poll_out ,
273
323
274
324
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
275
- .fifo_fill = uart_imx_fifo_fill ,
276
- .fifo_read = uart_imx_fifo_read ,
277
- .irq_tx_enable = uart_imx_irq_tx_enable ,
278
- .irq_tx_disable = uart_imx_irq_tx_disable ,
279
- .irq_tx_ready = uart_imx_irq_tx_ready ,
280
- .irq_rx_enable = uart_imx_irq_rx_enable ,
281
- .irq_rx_disable = uart_imx_irq_rx_disable ,
282
- .irq_rx_ready = uart_imx_irq_rx_ready ,
283
- .irq_err_enable = uart_imx_irq_err_enable ,
284
- .irq_err_disable = uart_imx_irq_err_disable ,
285
- .irq_is_pending = uart_imx_irq_is_pending ,
286
- .irq_update = uart_imx_irq_update ,
325
+ .fifo_fill = uart_imx_fifo_fill ,
326
+ .fifo_read = uart_imx_fifo_read ,
327
+ .irq_tx_enable = uart_imx_irq_tx_enable ,
328
+ .irq_tx_disable = uart_imx_irq_tx_disable ,
329
+ .irq_tx_ready = uart_imx_irq_tx_ready ,
330
+ .irq_tx_complete = uart_imx_irq_tx_complete ,
331
+ .irq_rx_enable = uart_imx_irq_rx_enable ,
332
+ .irq_rx_disable = uart_imx_irq_rx_disable ,
333
+ .irq_rx_ready = uart_imx_irq_rx_ready ,
334
+ .irq_err_enable = uart_imx_irq_err_enable ,
335
+ .irq_err_disable = uart_imx_irq_err_disable ,
336
+ .irq_is_pending = uart_imx_irq_is_pending ,
337
+ .irq_update = uart_imx_irq_update ,
287
338
.irq_callback_set = uart_imx_irq_callback_set ,
288
- #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
339
+ #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
289
340
290
341
};
291
342
292
- #define UART_IMX_DECLARE_CFG (n , IRQ_FUNC_INIT ) \
293
- static const struct imx_uart_config imx_uart_##n##_config = { \
294
- .base = (UART_Type *) DT_INST_REG_ADDR(n), \
295
- .baud_rate = DT_INST_PROP(n, current_speed), \
296
- .modem_mode = DT_INST_PROP(n, modem_mode), \
297
- .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
298
- IRQ_FUNC_INIT \
299
- }
343
+ #define UART_IMX_DECLARE_CFG (n , IRQ_FUNC_INIT ) \
344
+ static const struct imx_uart_config imx_uart_##n##_config = { \
345
+ .base = (UART_Type *)DT_INST_REG_ADDR(n), \
346
+ .baud_rate = DT_INST_PROP(n, current_speed), \
347
+ .modem_mode = DT_INST_PROP(n, modem_mode), \
348
+ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
349
+ IRQ_FUNC_INIT}
300
350
301
351
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
302
- #define UART_IMX_CONFIG_FUNC (n ) \
303
- static void irq_config_func_##n(const struct device *dev) \
304
- { \
305
- IRQ_CONNECT(DT_INST_IRQN(n), \
306
- DT_INST_IRQ(n, priority), \
307
- uart_imx_isr, \
308
- DEVICE_DT_INST_GET(n), 0); \
309
- irq_enable(DT_INST_IRQN(n)); \
352
+ #define UART_IMX_CONFIG_FUNC (n ) \
353
+ static void irq_config_func_##n(const struct device *dev) \
354
+ { \
355
+ IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), uart_imx_isr, \
356
+ DEVICE_DT_INST_GET(n), 0); \
357
+ irq_enable(DT_INST_IRQN(n)); \
310
358
}
311
- #define UART_IMX_IRQ_CFG_FUNC_INIT (n ) \
312
- .irq_config_func = irq_config_func_##n
313
- #define UART_IMX_INIT_CFG (n ) \
314
- UART_IMX_DECLARE_CFG(n, UART_IMX_IRQ_CFG_FUNC_INIT(n))
359
+ #define UART_IMX_IRQ_CFG_FUNC_INIT (n ) \
360
+ .irq_config_func = irq_config_func_##n, .rs485_enabled = DT_INST_PROP(n, rs485_enabled), \
361
+ .rs485_de_active_low = DT_INST_PROP(n, rs485_de_active_low), \
362
+ .rs485_de_timeout = DT_INST_PROP(n, rs485_assertion_time_de_us),
363
+ #define UART_IMX_INIT_CFG (n ) UART_IMX_DECLARE_CFG(n, UART_IMX_IRQ_CFG_FUNC_INIT(n))
315
364
#else
316
365
#define UART_IMX_CONFIG_FUNC (n )
317
366
#define UART_IMX_IRQ_CFG_FUNC_INIT
318
- #define UART_IMX_INIT_CFG (n ) \
319
- UART_IMX_DECLARE_CFG(n, UART_IMX_IRQ_CFG_FUNC_INIT)
367
+ #define UART_IMX_INIT_CFG (n ) UART_IMX_DECLARE_CFG(n, UART_IMX_IRQ_CFG_FUNC_INIT)
320
368
#endif
321
369
322
- #define UART_IMX_INIT (n ) \
323
- static struct imx_uart_data imx_uart_##n##_data; \
324
- \
325
- static const struct imx_uart_config imx_uart_##n##_config; \
326
- \
327
- PINCTRL_DT_INST_DEFINE(n); \
328
- \
329
- DEVICE_DT_INST_DEFINE(n, uart_imx_init, NULL, \
330
- &imx_uart_##n##_data, &imx_uart_##n##_config, \
331
- PRE_KERNEL_1, \
332
- CONFIG_SERIAL_INIT_PRIORITY, \
333
- &uart_imx_driver_api); \
334
- \
335
- UART_IMX_CONFIG_FUNC(n) \
336
- \
370
+ #define UART_IMX_INIT (n ) \
371
+ static struct imx_uart_data imx_uart_##n##_data; \
372
+ \
373
+ static const struct imx_uart_config imx_uart_##n##_config; \
374
+ \
375
+ PINCTRL_DT_INST_DEFINE(n); \
376
+ \
377
+ DEVICE_DT_INST_DEFINE(n, uart_imx_init, NULL, &imx_uart_##n##_data, \
378
+ &imx_uart_##n##_config, PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \
379
+ &uart_imx_driver_api); \
380
+ \
381
+ UART_IMX_CONFIG_FUNC(n) \
382
+ \
337
383
UART_IMX_INIT_CFG(n);
338
384
339
385
DT_INST_FOREACH_STATUS_OKAY (UART_IMX_INIT )
0 commit comments