Trying to hold RTS low (turn off RS485 transmitter controlled by RTS) during Linux boot. Can modify gpios emphasized textin board_init() in colibri_vf.c, but not the RTS pin. Tried treating it like a gpio but gpio_request returns failure. Is there a device tree setting or someway to hold RTS low until the app starts?
Trying to hold RTS low (turn off RS485 transmitter controlled by RTS) during Linux boot. Can modify gpios emphasized textin board_init() in colibri_vf.c, but not the RTS pin. Tried treating it like a gpio but gpio_request returns failure. Is there a device tree setting or someway to hold RTS low until the app starts?
Vybrid’s LPUART has auto RTS functionality, when RS485 support is enabled in device tree, the default configuration is done assuming UART active state as logic low. Accordingly the h/w configuration is done on our Colibri Eval board, please have a look at Colibri Evaluation board schematics. If you need UART active state as high this can be achieved by setting the RS485 flags accordingly, please have a look at the following diff:
diff --git a/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi b/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
index dc703043d3ac..7f04dd1b083b 100644
--- a/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
+++ b/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
@@ -189,6 +189,7 @@
&uart2 {
status = "okay";
+ linux,rs485-enabled-at-boot-time;
};
&usbdev0 {
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 2c72ed5071f1..8ab223183b22 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -2068,8 +2068,9 @@ static int lpuart_probe(struct platform_device *pdev)
if (of_property_read_bool(np, "linux,rs485-enabled-at-boot-time")) {
sport->port.rs485.flags |= SER_RS485_ENABLED;
- sport->port.rs485.flags |= SER_RS485_RTS_ON_SEND;
- writeb(UARTMODEM_TXRTSE, sport->port.membase + UARTMODEM);
+ sport->port.rs485.flags &= ~SER_RS485_RTS_ON_SEND;
+ sport->port.rs485.flags |= SER_RS485_RTS_AFTER_SEND;
+ writeb(UARTMODEM_TXRTSE | UARTMODEM_TXRTSPOL, sport->port.membase + UARTMODEM);
}
return 0;
Thank you for the answer. This does work, but leaves ~2.5-3 seconds of time when U-boot is starting before the RTS goes low at the start of loading drivers in Linux. Can the device tree be done differently to define this (and maybe CTS) as gpio at the start and then used in the Linux fsl_lpuart code?
Even changing the device tree won’t help during U-Boot phase. Probably your best bet is to modify U-Boot to mux the pin as GPIO temporarily.
I see how to separate them out, can you to instructions to associate them again with the UART for RS485 transmit and receive?
Thanks,
Paul
Further attempt -
If I remove NEW_PAD_CTRL(VF610_PAD_PTD2__UART2_RTS, UART_PAD_CTRL) from the structure in setup_iomux_uart, the RS485 can’t work as transmit never turns on.
Added code to vf_colibri.c to turn it off which appears to report okay but doesn’t turn it off.
Result during boot:
81 request ok
gpio 81 output set
gpio 81 return = 0
Code is:
/* set the RS485 direction bit */
/*
81 is the numeric representation
34 is the actual pin number on the SOM
*/
if ( gpio_request(81, "SODIMM_PIN_34")==0 ) {
printf("*** 81 request ok\n");
} else printf("*** 81 FAILED for request****************\n");
if ( gpio_direction_output(81, 1) == 0 ) {
printf("*** gpio 81 output set\n");
}
else printf("gpio 81 failed on output*******************\n");
return_value = gpio_set_value(81, 0);
printf("*** gpio 81 return = %d\n", return_value);
FYI - vf_colbri.dtsi modified like this:
/* BACnet RS485 port */
pinctrl_uart2: uart2grp {
fsl,pins = <
VF610_PAD_PTD0__UART2_TX 0x21a2
VF610_PAD_PTD1__UART2_RX 0x21a1
/* VF610_PAD_PTD2__UART2_RTS 0x21a2 */
/* VF610_PAD_PTD3__UART2_CTS 0x21a1 */
>;
};
Removing these from the group did not stop RS485 comm.s
Suggestions?
You have to mux the pin as GPIO. Unfortunately there is no macro/enum predefined, so you have to add it in arch/arm/include/asm/arch-vf610/iomux-vf610.h
:
--- a/arch/arm/include/asm/arch-vf610/iomux-vf610.h
+++ b/arch/arm/include/asm/arch-vf610/iomux-vf610.h
@@ -136,7 +136,9 @@ enum {
VF610_PAD_PTD0__QSPI0_A_QSCK = IOMUX_PAD(0x013c, 0x013c, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
VF610_PAD_PTD1__QSPI0_A_CS0 = IOMUX_PAD(0x0140, 0x0140, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
VF610_PAD_PTD2__QSPI0_A_DATA3 = IOMUX_PAD(0x0144, 0x0144, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+ VF610_PAD_PTD2__GPIO_81 = IOMUX_PAD(0x0144, 0x0144, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
VF610_PAD_PTD3__QSPI0_A_DATA2 = IOMUX_PAD(0x0148, 0x0148, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+ VF610_PAD_PTD3__GPIO_82 = IOMUX_PAD(0x0148, 0x0148, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
VF610_PAD_PTD4__GPIO_83 = IOMUX_PAD(0x014C, 0x014C, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
VF610_PAD_PTD4__QSPI0_A_DATA1 = IOMUX_PAD(0x014c, 0x014c, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
VF610_PAD_PTD5__QSPI0_A_DATA0 = IOMUX_PAD(0x0150, 0x0150, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
Then mux it as a GPIO, e.g. by adding the pin to the gpio_pads
array:
--- a/board/toradex/colibri_vf/colibri_vf.c
+++ b/board/toradex/colibri_vf/colibri_vf.c
@@ -238,6 +238,7 @@ static void setup_iomux_dspi(void)
static void setup_iomux_gpio(void)
{
static const iomux_v3_cfg_t gpio_pads[] = {
+ VF610_PAD_PTD2__GPIO_81,
VF610_PAD_PTA17__GPIO_7,
VF610_PAD_PTA20__GPIO_10,
VF610_PAD_PTA21__GPIO_11,
With that requesting and setting the pad as a GPIO should work.
Thanks - got to work on this today and got it working. Brief blip going high on power up and then low until app is running. My biggest mistake was the ‘0x144, 2’ instead of ‘0x144, 0’.
I also modified fsl_lpuart.c to reverse polarity until a protocol driver re-did it and start ‘talking’:
1888,1889c1888,1892
< sport->port.rs485.flags |= SER_RS485_RTS_ON_SEND;
< writeb(UARTMODEM_TXRTSE, sport->port.membase + UARTMODEM);
// sport->port.rs485.flags |= SER_RS485_RTS_ON_SEND;
// writeb(UARTMODEM_TXRTSE, sport->port.membase + UARTMODEM);
sport->port.rs485.flags &= ~SER_RS485_RTS_ON_SEND;
sport->port.rs485.flags |= SER_RS485_RTS_AFTER_SEND;
writeb(UARTMODEM_TXRTSE | UARTMODEM_TXRTSPOL, sport->port.membase + UARTMODEM);