Skip to content

Commit c052fb7

Browse files
[sg toup] drivers: serial: si32: Support UART line control API
Implementing this API allows PPP to (temporally) prevent its peer (Linux in our case) from sending more bytes. Without this, Linux may send data too fast, causing messages to be lost on the radio module side. This commit should be part of our (future) SiM3U upstreaming efforts. (cherry picked from commit 46ecdd1)
1 parent a171f29 commit c052fb7

File tree

1 file changed

+37
-1
lines changed

1 file changed

+37
-1
lines changed

drivers/serial/uart_si32_usart.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,28 @@ static void usart_si32_irq_handler(const struct device *dev)
209209
}
210210
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
211211

212+
#ifdef CONFIG_UART_LINE_CTRL
213+
214+
static int usart_si32_line_ctrl_set(const struct device *dev, uint32_t ctrl, uint32_t val)
215+
{
216+
const struct usart_si32_config *config = dev->config;
217+
218+
switch (ctrl) {
219+
case UART_LINE_CTRL_RTS:
220+
/* When inversion is not enabled, clear the RTS bit to signal readyness */
221+
if (val) {
222+
SI32_USART_A_clear_rts(config->usart);
223+
} else {
224+
SI32_USART_A_set_rts(config->usart);
225+
}
226+
return 0;
227+
}
228+
229+
return -ENOTSUP;
230+
}
231+
232+
#endif /* CONFIG_UART_LINE_CTRL */
233+
212234
static const struct uart_driver_api usart_si32_driver_api = {
213235
.poll_in = usart_si32_poll_in,
214236
.poll_out = usart_si32_poll_out,
@@ -229,6 +251,10 @@ static const struct uart_driver_api usart_si32_driver_api = {
229251
.irq_update = usart_si32_irq_update,
230252
.irq_callback_set = usart_si32_irq_callback_set,
231253
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
254+
255+
#ifdef CONFIG_UART_LINE_CTRL
256+
.line_ctrl_set = usart_si32_line_ctrl_set,
257+
#endif
232258
};
233259

234260
static int usart_si32_init(const struct device *dev)
@@ -286,10 +312,17 @@ static int usart_si32_init(const struct device *dev)
286312

287313
SI32_USART_A_exit_loopback_mode(config->usart);
288314

315+
/* Configure RTS to be pulled low when we are ready to receive data */
316+
SI32_USART_A_disable_rts_inversion(config->usart);
317+
318+
/* Hardware flow control can only be enabled (or disabled) for both, RTS and CTS in the
319+
* device tree. As a workaround, when CONFIG_UART_LINE_CTRL is enabled, configure CTS only.
320+
*/
289321
if (config->hw_flow_control) {
322+
#if !defined(CONFIG_UART_LINE_CTRL)
290323
SI32_USART_A_enable_rts(config->usart);
291324
SI32_USART_A_select_rts_deassert_on_byte_free(config->usart);
292-
SI32_USART_A_disable_rts_inversion(config->usart);
325+
#endif
293326

294327
SI32_USART_A_enable_cts(config->usart);
295328
SI32_USART_A_disable_cts_inversion(config->usart);
@@ -328,6 +361,9 @@ static int usart_si32_init(const struct device *dev)
328361
SI32_USART_A_disable_rx_signal_inversion(config->usart);
329362
SI32_USART_A_select_rx_fifo_threshold_1(config->usart);
330363
SI32_USART_A_enable_rx(config->usart);
364+
#if defined(CONFIG_UART_LINE_CTRL)
365+
SI32_USART_A_clear_rts(config->usart);
366+
#endif
331367

332368
SI32_USART_A_flush_tx_fifo(config->usart);
333369
SI32_USART_A_flush_rx_fifo(config->usart);

0 commit comments

Comments
 (0)