Hello Fabio,
I was trying to use 4.12.4 and 4.14.39.
The failure is that when Linux disables the UART peripheral, control
over CTS_B is lost and it defaults to high voltage state. That makes
sense for eg. RS232, but not for using this signal as positive logic
"driver enable", which should default to low voltage state.
I had a look at how it is done in the latest kernels, I think it's the
same thing in principle.
I am going to fix this, just I would like to find out which of the
suggested solutions is better suited for Linux. Personally, I opt for
solution 1 - keep UART enabled all the time - but maybe there is a good
reason not to do that.
Best regards,
Adam
W dniu 2018-09-10 o 19:56, Fabio Estevam pisze:
Hi Adam,
On Mon, Sep 10, 2018 at 1:54 PM, Adam Rudziński
<adam.rudzinski@xxxxxxxxxx> wrote:
Hi,
I'm preparing Linux for a device based on i.MX6UL by Freescale, now NXP. The
device uses RS485 interface, and I have noticed, that the current driver
SERIAL_IMX (driver/tty/serial/imx.c) doesn't do that correctly. Thus, I have
a question to you (four paragraphs below).
Which kernel version are you using and what is the exact failure?
According to my understanding, at least for the i.MX family, the general
agreement is that CTS_B signal of the processor, which is an output, should
be used as "driver enable" (DE) signal of transmitter in the RS485
transceiver chip. Typically this DE signal is "normal logic", ie. high
voltage == '1', while CTS_B is inverted logic signal, ie. low voltage ==
'1'. UART peripheral of i.MX processor has bit field CTS in register UCR2,
and this bit field can be used for "manual" control of the CTS_B signal.
That is what the driver SERIAL_IMX does for ports defined in device tree as
dedicated for RS485.
Yes, this commit from Baruch helps to clarify about it:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v4.19-rc3&id=e51e597d9f692cd7d205e3b44bb35ea3b97e7329
However, Linux can, and does, disable serial port, here, by putting '0' into
UCR1 register of the UART peripheral. But then, CTS bit field is ignored and
CTS_B a.k.a. DE signal line is high. For RS485 this ends up in having
wrestling match of connected transmitters.
The correct state should be that for unused or disabled UART assigned for
RS485 the DE signal line is low. That is something I want to implement. I
can see two ways of doing that in software (described below), and my
question is: which is preferred?
1) Prevent disabling UART peripheral. For that function imx_shutdown or
imx_uart_shutdown could check if RS485 is enabled (in rs485.flags) and if
yes, keep the enable bit in UCR1 asserted. This will not require engaging
other things, but will not allow to fully disable the port. I don't know why
Linux tries to do so, and I can't tell whether or not that is a potential
problem.
2) Use GPIO to define the state of the signal when UART peripheral is
disabled. That might be done by defining the GPIO muxed with CTS_B as output
in low state, and muxing the processor pin to CTS_B when enabling the UART,
and to GPIO when disabling it. This would allow to fully disable UART, but
will require undisclosed control of an additional feature (GPIO channel)
which somebody might want to use for another purpose.
I would appreciate letting me know your opinion on that.
Added a few folks who has worked with RS485 on i.MX in case they can help.