Hello Florian, When working with a Zynq I wonder why you use the 8250 driver for RS485. Using software to time RS485 changeovers is asking for trouble IMHO. Have you seen my patch for the uartlite to support RS485 in hardware? https://forums.xilinx.com/t5/Embedded-Development-Tools/Feature-Request-UARTlite-with-RS485-Driver-Enable-output-signal/m-p/689335 Maarten On 2017-08-23 10:20, Florian Reitz wrote:
Dear kernel community, I am working on an embedded Linux device that that is using the Linux 4.7 Kernel on the Xilinx Zynq platform. I am having trouble getting the RS485 part of the 8250 serial driver to work. All the functions needed for switching the RS485 transceiver using the RTS pin are already present in the 8250_port.c file, but I had to add a rs485_config() function to the 8250_of.c file to support configuration using TIOCSRS485 ioctl() calls. My problem was that at first, that the functions responsible for setting the RTS pin was only called at the beginning of transmission, leaving the transceiver in send mode. I found out that there may be a bug in the __stop_tx() function from 8250_port.c static inline void __stop_tx(struct uart_8250_port *p) { struct uart_8250_em485 *em485 = p->em485; if (em485) { unsigned char lsr = serial_in(p, UART_LSR); /* * To provide required timeing and allow FIFO transfer, * __stop_tx_rs485 must be called only when both FIFO and * shift register are empty. It is for device driver to enable * interrupt on TEMT. */ if ((lsr & BOTH_EMPTY) != BOTH_EMPTY) { return; } del_timer(&em485->start_tx_timer); em485->active_timer = NULL; } __do_stop_tx(p); __stop_tx_rs485(p); } BOTH_EMPTY translates to THRE and TEMT bits in the LSR register. THRE is set when tx data has been transferred from the holding register to the shift register, indicating, that the cpu may write a new byte to the UART. TEMT is set when the data has been shifted out of the shift register, ie. has actually been sent over the line. Therefore, TEMT will always be set AFTER THRE was set, with the delay of the time it takes to shift the byte on the line, including start-, stop- and parity-bits. I believe the problem is, that THRE and TEMT are tested together but they may not have been set when the function is called, especially when a low baudrate is used (19200 Bd in my case). I verified that the return in the middle was always taken, even after the last byte, when it was supposed to call __stop_tx_rs485(). That is why the transceiver was never switched back to receive. I simply commented the return out and it's working now, kind of. But that is another question/problem I will ask later. I'd like to hear your opinion on this topic first. This code is still present in the 4.12 kernel files. Greetings, Florian PS: Please CC your answers to my email address.
-- To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html