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,6 +71,7 @@ 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
@@ -93,6 +108,12 @@ static int uart_imx_init(const struct device *dev)
93
108
config -> irq_config_func (dev );
94
109
#endif
95
110
111
+ if (config -> rs485_enabled ) {
112
+ UART_SetCtsPinLevel (uart , !config -> rs485_de_active_low );
113
+ k_timer_init (& data -> rs485_timer , rs485_de_time_expire_callback , NULL );
114
+ k_timer_user_data_set (& data -> rs485_timer , uart );
115
+ }
116
+
96
117
/* Set UART modem mode */
97
118
UART_SetModemMode (uart , config -> modem_mode );
98
119
@@ -137,11 +158,12 @@ static int uart_imx_fifo_fill(const struct device *dev,
137
158
UART_Type * uart = UART_STRUCT (dev );
138
159
unsigned int num_tx = 0U ;
139
160
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 ++ ;
161
+ if (UART_GetStatusFlag (uart , uartStatusTxReady )) {
162
+ while (((size - num_tx ) > 0 ) && (num_tx < UART_FIFO_SIZE )) {
163
+ /* Send a character */
164
+ UART_Putchar (uart , tx_data [num_tx ]);
165
+ num_tx ++ ;
166
+ }
145
167
}
146
168
147
169
return (int )num_tx ;
@@ -169,13 +191,30 @@ static int uart_imx_fifo_read(const struct device *dev, uint8_t *rx_data,
169
191
static void uart_imx_irq_tx_enable (const struct device * dev )
170
192
{
171
193
UART_Type * uart = UART_STRUCT (dev );
194
+ const struct imx_uart_config * config = dev -> config ;
195
+ struct imx_uart_data * data = dev -> data ;
172
196
173
- UART_SetIntCmd (uart , uartIntTxReady , true);
197
+ if (config -> rs485_enabled ) {
198
+ UART_SetCtsPinLevel (uart , config -> rs485_de_active_low );
199
+ if (config -> rs485_de_timeout ) {
200
+ k_timer_start (& data -> rs485_timer , K_USEC (config -> rs485_de_timeout ),
201
+ K_NO_WAIT );
202
+ } else {
203
+ UART_SetIntCmd (uart , uartIntTxReady , true);
204
+ }
205
+ } else {
206
+ UART_SetIntCmd (uart , uartIntTxReady , true);
207
+ }
174
208
}
175
209
176
210
static void uart_imx_irq_tx_disable (const struct device * dev )
177
211
{
178
212
UART_Type * uart = UART_STRUCT (dev );
213
+ const struct imx_uart_config * config = dev -> config ;
214
+
215
+ if (config -> rs485_enabled ) {
216
+ UART_SetIntCmd (uart , uartIntTxComplete , true);
217
+ }
179
218
180
219
UART_SetIntCmd (uart , uartIntTxReady , false);
181
220
}
@@ -187,9 +226,27 @@ static int uart_imx_irq_tx_ready(const struct device *dev)
187
226
return UART_GetStatusFlag (uart , uartStatusTxReady );
188
227
}
189
228
229
+ static int uart_imx_irq_tx_complete (const struct device * dev )
230
+ {
231
+ UART_Type * uart = UART_STRUCT (dev );
232
+ const struct imx_uart_config * config = dev -> config ;
233
+ bool complete = UART_GetStatusFlag (uart , uartStatusTxComplete );
234
+
235
+ if (config -> rs485_enabled && complete ) {
236
+ UART_SetIntCmd (uart , uartIntTxComplete , false);
237
+ }
238
+
239
+ return complete ;
240
+ }
241
+
190
242
static void uart_imx_irq_rx_enable (const struct device * dev )
191
243
{
192
244
UART_Type * uart = UART_STRUCT (dev );
245
+ const struct imx_uart_config * config = dev -> config ;
246
+
247
+ if (config -> rs485_enabled ) {
248
+ UART_SetCtsPinLevel (uart , !config -> rs485_de_active_low );
249
+ }
193
250
194
251
UART_SetIntCmd (uart , uartIntRxReady , true);
195
252
}
@@ -272,68 +329,64 @@ static DEVICE_API(uart, uart_imx_driver_api) = {
272
329
.poll_out = uart_imx_poll_out ,
273
330
274
331
#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 ,
332
+ .fifo_fill = uart_imx_fifo_fill ,
333
+ .fifo_read = uart_imx_fifo_read ,
334
+ .irq_tx_enable = uart_imx_irq_tx_enable ,
335
+ .irq_tx_disable = uart_imx_irq_tx_disable ,
336
+ .irq_tx_ready = uart_imx_irq_tx_ready ,
337
+ .irq_tx_complete = uart_imx_irq_tx_complete ,
338
+ .irq_rx_enable = uart_imx_irq_rx_enable ,
339
+ .irq_rx_disable = uart_imx_irq_rx_disable ,
340
+ .irq_rx_ready = uart_imx_irq_rx_ready ,
341
+ .irq_err_enable = uart_imx_irq_err_enable ,
342
+ .irq_err_disable = uart_imx_irq_err_disable ,
343
+ .irq_is_pending = uart_imx_irq_is_pending ,
344
+ .irq_update = uart_imx_irq_update ,
287
345
.irq_callback_set = uart_imx_irq_callback_set ,
288
346
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
289
347
290
348
};
291
349
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
- }
350
+ #define UART_IMX_DECLARE_CFG (n , IRQ_FUNC_INIT ) \
351
+ static const struct imx_uart_config imx_uart_##n##_config = { \
352
+ .base = (UART_Type *)DT_INST_REG_ADDR(n), \
353
+ .baud_rate = DT_INST_PROP(n, current_speed), \
354
+ .modem_mode = DT_INST_PROP(n, modem_mode), \
355
+ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
356
+ IRQ_FUNC_INIT}
300
357
301
358
#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)); \
359
+ #define UART_IMX_CONFIG_FUNC (n ) \
360
+ static void irq_config_func_##n(const struct device *dev) \
361
+ { \
362
+ IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), uart_imx_isr, \
363
+ DEVICE_DT_INST_GET(n), 0); \
364
+ irq_enable(DT_INST_IRQN(n)); \
310
365
}
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))
366
+ #define UART_IMX_IRQ_CFG_FUNC_INIT (n ) \
367
+ .irq_config_func = irq_config_func_##n, .rs485_enabled = DT_INST_PROP(n, rs485_enabled), \
368
+ .rs485_de_active_low = DT_INST_PROP(n, rs485_de_active_low), \
369
+ .rs485_de_timeout = DT_INST_PROP(n, rs485_assertion_time_de_us),
370
+ #define UART_IMX_INIT_CFG (n ) UART_IMX_DECLARE_CFG(n, UART_IMX_IRQ_CFG_FUNC_INIT(n))
315
371
#else
316
372
#define UART_IMX_CONFIG_FUNC (n )
317
373
#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)
374
+ #define UART_IMX_INIT_CFG (n ) UART_IMX_DECLARE_CFG(n, UART_IMX_IRQ_CFG_FUNC_INIT)
320
375
#endif
321
376
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
- \
377
+ #define UART_IMX_INIT (n ) \
378
+ static struct imx_uart_data imx_uart_##n##_data; \
379
+ \
380
+ static const struct imx_uart_config imx_uart_##n##_config; \
381
+ \
382
+ PINCTRL_DT_INST_DEFINE(n); \
383
+ \
384
+ DEVICE_DT_INST_DEFINE(n, uart_imx_init, NULL, &imx_uart_##n##_data, \
385
+ &imx_uart_##n##_config, PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \
386
+ &uart_imx_driver_api); \
387
+ \
388
+ UART_IMX_CONFIG_FUNC(n) \
389
+ \
337
390
UART_IMX_INIT_CFG(n);
338
391
339
392
DT_INST_FOREACH_STATUS_OKAY (UART_IMX_INIT )
0 commit comments