Message ID | 20231120151056.148450-2-linux@rasmusvillemoes.dk |
---|---|
State | New |
Headers | show |
Series | serial: add rs485-mux-gpio dt binding and support | expand |
On 21/11/2023 10:28, Rasmus Villemoes wrote: > On 21/11/2023 09.34, Krzysztof Kozlowski wrote: >> On 21/11/2023 09:27, Rasmus Villemoes wrote: >>> On 21/11/2023 08.52, Krzysztof Kozlowski wrote: > >>>> Anyway, similar comments: this does not look like generic RS485 >>>> property. Are you saying that standard defines such GPIO? >>> >>> No, I'm saying that several boards that exist in the wild have the >>> RX/TX/CTS etc. pins routed to a multiplexer, which in turn routes those >>> signals to either a rs485 transceiver or an rs232 driver (and those in >>> turn are connected to different screw terminals). So no, it's not a >>> property of the rs485 protocol itself, but very much related to making >>> use of rs485 (and rs232, though of course not simultaneously) on such >>> boards. >> >> Which upstream boards use it? > > None, because the binding doesn't exist. > >> To me it looks like specific to each controller, not to RS485. > > What do you mean "controller"? It's not specific to one particular > SOC/IP, any uart IP capable of both rs232 and rs485 could be wired to > circuitry like this. > >>> Would a link to a schematic help? >> >> Yes, always :) > > https://ibb.co/B3gzySt > > The UART1.* signals on the right are from the SOC (in this case an > imx8mp, but I know of other boards e.g. based on powerpc that use a > similar scheme), and the COM1_Sel is just some gpio. The multiplexer is > roughly in the middle (U2103). > > As you can see, if one wants to talk rs485, one must set COM1_Sel low > (and that works just fine by describing the rs485-mux-gpio as > ACTIVE_LOW), and if one wants to talk rs232, it must be set high. While > userspace could be tasked with knowing about and handling that gpio on > top of the ioctl() for switching mode, this really seems like the kind > of thing that DT is supposed to describe and the kernel is supposed to > handle. Yep, the trouble is only the placement. This GPIO mux is neither part of the UART controller nor connector. Usually such pins in static configuration are described either as GPIO hogs or as pinctrl. I guess this matches other GPIOs in that binding, so I think it is fine. You still though should answer to comments from other folks, including multiple-GPIO case and mux. Best regards, Krzysztof
On 22/11/2023 15.53, Lukas Wunner wrote: > On Mon, Nov 20, 2023 at 04:10:54PM +0100, Rasmus Villemoes wrote: >> Some boards are capable of both rs232 and rs485, and control which >> external terminals are active via a gpio-controlled mux. Allow >> describing that gpio in DT so that the kernel can transparently handle >> the proper setting when the uart is switched between rs232 and rs485 >> modes. > > Crescent CY Hsieh (+cc) is in parallel trying to add an RS-422 mode bit > to struct serial_rs485: > > https://lore.kernel.org/all/20231121095122.15948-1-crescentcy.hsieh@moxa.com/ > > I don't know whether that makes sense at all (I had thought RS-422 is > the same as RS-485 with full-duplex, i.e. SER_RS485_ENABLED plus > SER_RS485_RX_DURING_TX). No, that latter case is as I understand it usually called "4-wire rs485", while rs-422 is an entirely different animal, and the wiring is in some sense actually closer to rs-232. rs-422 is full-duplex, with all the slave device's tx-lines connected to the master's rx, and the master's tx connected to the slaves' rx (ok, it uses differential signalling, so there are four wires involved and not two as in rs-232). But I'm no expert, and there doesn't seem to be entirely consistent terminology. > > But if that patch gets accepted, we'd have *three* different modes: > RS-232, RS-485, RS-422. A single GPIO seems insufficient to handle that. > You'd need at least two GPIOs. I don't see Crescent introducing any new gpio that needs to be handled. In fact, I can't even see why from the perspective of the software that rs422 isn't just rs232; there's no transmit enable pin that needs to be handled. But maybe the uart driver does something different in rs422 mode; I assume he must have some update of some driver, since otherwise the new rs422 bit should be rejected by the core. So I can't really see the whole picture of that rs422 story. >> --- a/Documentation/devicetree/bindings/serial/rs485.yaml >> +++ b/Documentation/devicetree/bindings/serial/rs485.yaml >> @@ -61,6 +61,11 @@ properties: >> the active state enables RX during TX. >> maxItems: 1 >> >> + rs485-mux-gpios: >> + description: GPIO pin to control muxing of the SOC signals to the RS485 >> + transceiver. >> + maxItems: 1 > > The description doesn't really add much to the name "rs485-mux-gpios". > > Suggestion: > > description: selects whether the UART is connect to an RS-232 driver (low) > or an RS-485 transceiver (high) Indeed, I wasn't really able to come up with a good description. Thanks, that's much better. Rasmus
On 23/11/2023 11.38, Lukas Wunner wrote: > On Thu, Nov 23, 2023 at 11:07:16AM +0100, Rasmus Villemoes wrote: >> On 22/11/2023 15.53, Lukas Wunner wrote: >>> But if that patch gets accepted, we'd have *three* different modes: >>> RS-232, RS-485, RS-422. A single GPIO seems insufficient to handle that. >>> You'd need at least two GPIOs. >> >> I don't see Crescent introducing any new gpio that needs to be handled. >> In fact, I can't even see why from the perspective of the software that >> rs422 isn't just rs232; there's no transmit enable pin that needs to be >> handled. But maybe the uart driver does something different in rs422 >> mode; I assume he must have some update of some driver, since otherwise >> the new rs422 bit should be rejected by the core. So I can't really see >> the whole picture of that rs422 story. > > The question is, could we conceivably have the need to support > switching between the three modes RS-232, RS-485, RS-422. > If yes, then the GPIO mux interface should probably allow for that. > > As a case in point, the Siemens IOT 2040 has two serial ports > which can be set to either of those three modes. The signals > are routed to the same D-sub socket, but the pins used are > different. See page 46 and 47 of this document: > > https://cache.industry.siemens.com/dl/files/658/109741658/att_899623/v1/iot2000_operating_instructions_enUS_en-US.pdf > > The driver for this product is 8250_exar.c. It's an Intel-based > product, so no devicetree, but it shows that such use cases exist. OK. I did look at the mux-controller/mux-consumer bindings, but couldn't really make heads or tails of it, and there aren't a whole lot of examples in-tree. Also, the C API seems ... not quite what is needed here. I realize that's not really anything to do with the best way to describe the hardware, but that, plus the fact that the serial core already handles a number of gpios controlling circuitry related to rs485, was what made me go for one extra gpio. How would a mux-consumer description look? mux-states = <&mux 0>, <&mux 1>; mux-state-names = "rs485", "rs232"; or should that be mux-controls? Would that be enough so that we're sure that if and when a rs422 state is needed that could easily be represented here? Now implementation-wise, there's the complication that switching the mux to/from rs485 mode must be done after/before the driver's ->rs485_config is called, to avoid the transceiver temporarily being activated (thus blocking/disturbing other traffic). That plus the need to mux_*_deselect the old mode means the consumer (serial core in this case) ends up with quite a lot of bookkeeping, and even more so taking error path into consideration. Rasmus
Hi, On 22.11.23 at 15:53, Lukas Wunner wrote: > On Mon, Nov 20, 2023 at 04:10:54PM +0100, Rasmus Villemoes wrote: >> Some boards are capable of both rs232 and rs485, and control which >> external terminals are active via a gpio-controlled mux. Allow >> describing that gpio in DT so that the kernel can transparently handle >> the proper setting when the uart is switched between rs232 and rs485 >> modes. > > Crescent CY Hsieh (+cc) is in parallel trying to add an RS-422 mode bit > to struct serial_rs485: > > https://lore.kernel.org/all/20231121095122.15948-1-crescentcy.hsieh@moxa.com/ > That new flag was suggested by me instead of using SER_RS422_ENABLED, which would mostly be redundant to SER_RS485_ENABLED. I dont know if it is a good choice in the long term to handle both modes within the RS485 configuration. It would be cleaner to have an own RS422 structure with its own flags and properties. And until now the only flag that seems to make sense for both RS422 and RS485 is AFAICS SER_RS485_TERMINATE_BUS. On the other hand the bus termination is at least a property that both modes have in common. And handling RS422 in its own structure would require another ioctl to set and get the the RS422 settings. But maybe there are more or better possibilities to handle RS4822 support. I would like to hear other ideas. > I don't know whether that makes sense at all (I had thought RS-422 is > the same as RS-485 with full-duplex, i.e. SER_RS485_ENABLED plus > SER_RS485_RX_DURING_TX) > > But if that patch gets accepted, we'd have *three* different modes: > RS-232, RS-485, RS-422. Actually we would have four (as Brenda already wrote, see https://lore.kernel.org/all/c6ea912f-d5ab-4761-813d-3b6b6be141cb@ni.com/), and with the propose SER_RS485_MODE_RS422 flag these modes would be used like RS-232: rs485->flags = 0 RS-422: rs485->flags = SER_RS485_ENABLED|SER_RS485_MODE_RS422 RS-485 (2-wire half-duplex): rs485->flags = SER_RS485_ENABLED RS-485 (4-wire full-duplex): rs485->flags = SER_RS485_ENABLED|SER_RS485_RX_DURING_TX > A single GPIO seems insufficient to handle that. GPIOs for RS485 is another thing. I mean, currently we have a GPIO for RS485 termination (I introduced it with commit 44b27aec9d9680875). Christoph introduced support for a rx-during-tx GPIO (see commit 163f080eb717). Tomas intends to add a GPIO which enables RS485 if asserted (see https://lore.kernel.org/all/3Za.ZZs%7D.ndXI8CMee4.1bN6eQ@seznam.cz/) and with Rasmus patches we are about to add a MUX-GPIO which is to be asserted if RS485 is enabled. I wonder where this will end and if we really have to support every possible GPIO in the serial core. Regards, Lino
From: Lino Sanfilippo [mailto:LinoSanfilippo@gmx.de] Sent: Sunday, November 26, 2023 12:40 AM Hi, > On 22.11.23 at 15:53, Lukas Wunner wrote: >> On Mon, Nov 20, 2023 at 04:10:54PM +0100, Rasmus Villemoes wrote: >>> Some boards are capable of both rs232 and rs485, and control which >>> external terminals are active via a gpio-controlled mux. Allow >>> describing that gpio in DT so that the kernel can transparently handle >>> the proper setting when the uart is switched between rs232 and rs485 >>> modes. >> >> Crescent CY Hsieh (+cc) is in parallel trying to add an RS-422 mode bit >> to struct serial_rs485: >> >> https://lore.kernel.org/all/20231121095122.15948-1-crescentcy.hsieh@moxa.com/ >> > > That new flag was suggested by me instead of using SER_RS422_ENABLED, which > would mostly be redundant to SER_RS485_ENABLED. > I dont know if it is a good choice in the long term to handle both modes within > the RS485 configuration. It would be cleaner to have an own RS422 structure with > its own flags and properties. And until now the only flag that seems to make sense > for both RS422 and RS485 is AFAICS SER_RS485_TERMINATE_BUS. > > On the other hand the bus termination is at least a property that both modes have > in common. And handling RS422 in its own structure would require another ioctl > to set and get the the RS422 settings. > > But maybe there are more or better possibilities to handle RS4822 support. I would like to > hear other ideas. > > > >> I don't know whether that makes sense at all (I had thought RS-422 is >> the same as RS-485 with full-duplex, i.e. SER_RS485_ENABLED plus >> SER_RS485_RX_DURING_TX) With RS-485 full duplex, SER_RS485_RX_DURING_TX makes no sense to me. See below. >> >> But if that patch gets accepted, we'd have *three* different modes: >> RS-232, RS-485, RS-422. > > Actually we would have four (as Brenda already wrote, > see https://lore.kernel.org/all/c6ea912f-d5ab-4761-813d-3b6b6be141cb@ni.com/), > and with the propose SER_RS485_MODE_RS422 flag these modes would be used like > > RS-232: rs485->flags = 0 > RS-422: rs485->flags = SER_RS485_ENABLED|SER_RS485_MODE_RS422 > RS-485 (2-wire half-duplex): rs485->flags = SER_RS485_ENABLED > RS-485 (4-wire full-duplex): rs485->flags = SER_RS485_ENABLED|SER_RS485_RX_DURING_TX In my point of view there are also two different modes for the RS-485 2-wire half-duplex bus depending on the flag SER_RS485_RX_DURING_TX. - SER_RS485_RX_DURING_TX is not set: The device doesn't see the bus during sending (RX is off during sending). - SER_RS485_RX_DURING_TX is set: The device see want is on bus during sending (RX is also on during sending), so you can see your transmission and also if another bus device is transmitting at the same time. On RS-485 4-wire TX and RX are separated by wires. So the definition of SER_RS485_RX_DURING_TX above makes no sense, because you can receive all the time without worrying about TX. On the software side RS-485 4-wire full duplex it behaves like RS-232. So we don't need transceiver controlling by the RTS pin. Basically for me the SER_RS485_ENABLED flag is to enable the RTS control for the transceiver. Maybe on software side we can distinguish between half and full duplex mode and whether RX is enabled during sending by the flag SER_RS485_RX_DURING_TX: RS-232: rs485->flags = 0 RS-422 / RS-485 (4-wire): rs485->flags = SER_RS485_ENABLED|SER_RS485_MODE_FULL_DUPLEX RS-485 (2-wire NO RX_DURING_TX): rs485->flags = SER_RS485_ENABLED|SER_RS485_MODE_HALF_DUPLEX RS-485 (2-wire RX_DURING_TX): rs485->flags = SER_RS485_ENABLED|SER_RS485_MODE_HALF_DUPLEX|SER_RS485_RX_DURING_TX SER_RS485_MODE_FULL_DUPLEX and SER_RS485_MODE_HALF_DUPLEX can be defined at the same bit. If SER_RS485_MODE_HALF_DUPLEX will be defined as 0 it breaks nothing. With SER_RS485_MODE_FULL_DUPLEX, the RTS pin does not need to be controlled. > >> A single GPIO seems insufficient to handle that. > > GPIOs for RS485 is another thing. > > I mean, currently we have a GPIO for RS485 termination (I introduced it with commit > 44b27aec9d9680875). > Christoph introduced support for a rx-during-tx GPIO (see commit 163f080eb717). Tomas > intends > to add a GPIO which enables RS485 if asserted > (see https://lore.kernel.org/all/3Za.ZZs%7D.ndXI8CMee4.1bN6eQ@seznam.cz/) and with Rasmus > patches > we are about to add a MUX-GPIO which is to be asserted if RS485 is enabled. > > I wonder where this will end and if we really have to support every possible GPIO > in the serial core. I think the GPIOs reflect the flag states and are meaningful: - SER_RS485_TERMINATE_BUS: Switch bus termination on/off by GPIO - SER_RS485_RX_DURING_TX: Used to stop RX during TX in hardware by GPIO (for 2-wire) - SER_RS485_ENABLED: Muxing between RS-232 and RS-485 by GPIO Switching RS-485 on during boot could also be handled by a devicetree overlay. Evaluate the GPIO and load a DTO accordingly before booting. Regards Christoph
Hi, On 27.11.23 13:14, Christoph Niedermaier wrote: > From: Lino Sanfilippo [mailto:LinoSanfilippo@gmx.de] > Sent: Sunday, November 26, 2023 12:40 AM > > Hi, > >> On 22.11.23 at 15:53, Lukas Wunner wrote: >>> On Mon, Nov 20, 2023 at 04:10:54PM +0100, Rasmus Villemoes wrote: >>>> Some boards are capable of both rs232 and rs485, and control which >>>> external terminals are active via a gpio-controlled mux. Allow >>>> describing that gpio in DT so that the kernel can transparently handle >>>> the proper setting when the uart is switched between rs232 and rs485 >>>> modes. >>> >>> Crescent CY Hsieh (+cc) is in parallel trying to add an RS-422 mode bit >>> to struct serial_rs485: >>> >>> https://lore.kernel.org/all/20231121095122.15948-1-crescentcy.hsieh@moxa.com/ >>> >> >> That new flag was suggested by me instead of using SER_RS422_ENABLED, which >> would mostly be redundant to SER_RS485_ENABLED. >> I dont know if it is a good choice in the long term to handle both modes within >> the RS485 configuration. It would be cleaner to have an own RS422 structure with >> its own flags and properties. And until now the only flag that seems to make sense >> for both RS422 and RS485 is AFAICS SER_RS485_TERMINATE_BUS. >> >> On the other hand the bus termination is at least a property that both modes have >> in common. And handling RS422 in its own structure would require another ioctl >> to set and get the the RS422 settings. >> >> But maybe there are more or better possibilities to handle RS4822 support. I would like to >> hear other ideas. >> >> >> >>> I don't know whether that makes sense at all (I had thought RS-422 is >>> the same as RS-485 with full-duplex, i.e. SER_RS485_ENABLED plus >>> SER_RS485_RX_DURING_TX) > > With RS-485 full duplex, SER_RS485_RX_DURING_TX makes no sense to me. > See below. > >>> >>> But if that patch gets accepted, we'd have *three* different modes: >>> RS-232, RS-485, RS-422. >> >> Actually we would have four (as Brenda already wrote, >> see https://lore.kernel.org/all/c6ea912f-d5ab-4761-813d-3b6b6be141cb@ni.com/), >> and with the propose SER_RS485_MODE_RS422 flag these modes would be used like >> >> RS-232: rs485->flags = 0 >> RS-422: rs485->flags = SER_RS485_ENABLED|SER_RS485_MODE_RS422 >> RS-485 (2-wire half-duplex): rs485->flags = SER_RS485_ENABLED >> RS-485 (4-wire full-duplex): rs485->flags = SER_RS485_ENABLED|SER_RS485_RX_DURING_TX > > In my point of view there are also two different modes for the RS-485 2-wire > half-duplex bus depending on the flag SER_RS485_RX_DURING_TX. > - SER_RS485_RX_DURING_TX is not set: The device doesn't see the bus during sending > (RX is off during sending). > - SER_RS485_RX_DURING_TX is set: The device see want is on bus during sending > (RX is also on during sending), so you can > see your transmission and also if another bus > device is transmitting at the same time. > > On RS-485 4-wire TX and RX are separated by wires. So the definition of > SER_RS485_RX_DURING_TX above makes no sense, because you can receive all the time > without worrying about TX. On the software side RS-485 4-wire full duplex it behaves > like RS-232. So we don't need transceiver controlling by the RTS pin. >> Basically for me the SER_RS485_ENABLED flag is to enable the RTS control for the > transceiver. Maybe on software side we can distinguish between half and full duplex > mode and whether RX is enabled during sending by the flag SER_RS485_RX_DURING_TX: > RS-232: rs485->flags = 0 > RS-422 / RS-485 (4-wire): rs485->flags = SER_RS485_ENABLED|SER_RS485_MODE_FULL_DUPLEX How can we switch between RS485 (4-wire) and RS422 then? AFAIU they are not the same. And even if a driver behaves the same in both modes it needs to know when to switch from one mode to the other. > RS-485 (2-wire NO RX_DURING_TX): rs485->flags = SER_RS485_ENABLED|SER_RS485_MODE_HALF_DUPLEX > RS-485 (2-wire RX_DURING_TX): rs485->flags = SER_RS485_ENABLED|SER_RS485_MODE_HALF_DUPLEX|SER_RS485_RX_DURING_TX I think we can omit the SER_RS485_MODE_HALF_DUPLEX flag if we assume that a missing SER_RS485_MODE_FULL_DUPLEX means half duplex (i.e. controlling the RTS line). > SER_RS485_MODE_FULL_DUPLEX and SER_RS485_MODE_HALF_DUPLEX can be defined at the > same bit. If SER_RS485_MODE_HALF_DUPLEX will be defined as 0 it breaks nothing. > With SER_RS485_MODE_FULL_DUPLEX, the RTS pin does not need to be controlled > >> >>> A single GPIO seems insufficient to handle that. >> >> GPIOs for RS485 is another thing. >> >> I mean, currently we have a GPIO for RS485 termination (I introduced it with commit >> 44b27aec9d9680875). >> Christoph introduced support for a rx-during-tx GPIO (see commit 163f080eb717). Tomas >> intends >> to add a GPIO which enables RS485 if asserted >> (see https://lore.kernel.org/all/3Za.ZZs%7D.ndXI8CMee4.1bN6eQ@seznam.cz/) and with Rasmus >> patches >> we are about to add a MUX-GPIO which is to be asserted if RS485 is enabled. >> >> I wonder where this will end and if we really have to support every possible GPIO >> in the serial core. > > I think the GPIOs reflect the flag states and are meaningful: > - SER_RS485_TERMINATE_BUS: Switch bus termination on/off by GPIO > - SER_RS485_RX_DURING_TX: Used to stop RX during TX in hardware by GPIO (for 2-wire) > - SER_RS485_ENABLED: Muxing between RS-232 and RS-485 by GPIO > > Switching RS-485 on during boot could also be handled by a devicetree overlay. Evaluate the > GPIO and load a DTO accordingly before booting. > Regards, Lino
On Wed, Dec 06, 2023 at 04:42:53PM +0100, Lino Sanfilippo wrote: > On 27.11.23 13:14, Christoph Niedermaier wrote: > > From: Lino Sanfilippo [mailto:LinoSanfilippo@gmx.de] > > Sent: Sunday, November 26, 2023 12:40 AM ... > > RS-485 (2-wire NO RX_DURING_TX): rs485->flags = SER_RS485_ENABLED|SER_RS485_MODE_HALF_DUPLEX > > RS-485 (2-wire RX_DURING_TX): rs485->flags = SER_RS485_ENABLED|SER_RS485_MODE_HALF_DUPLEX|SER_RS485_RX_DURING_TX > > I think we can omit the SER_RS485_MODE_HALF_DUPLEX flag if we assume that > a missing SER_RS485_MODE_FULL_DUPLEX means half duplex (i.e. controlling > the RTS line). You should be very careful on these assumptions, i.e. one must to check _all_ existing user space tools (at least that are in use / supplied by main distros) on how they behave.
Hi Andy, On 07.12.23 13:35, Andy Shevchenko wrote: > On Wed, Dec 06, 2023 at 04:42:53PM +0100, Lino Sanfilippo wrote: >> On 27.11.23 13:14, Christoph Niedermaier wrote: >>> From: Lino Sanfilippo [mailto:LinoSanfilippo@gmx.de] >>> Sent: Sunday, November 26, 2023 12:40 AM > > ... > >>> RS-485 (2-wire NO RX_DURING_TX): rs485->flags = SER_RS485_ENABLED|SER_RS485_MODE_HALF_DUPLEX >>> RS-485 (2-wire RX_DURING_TX): rs485->flags = SER_RS485_ENABLED|SER_RS485_MODE_HALF_DUPLEX|SER_RS485_RX_DURING_TX >> >> I think we can omit the SER_RS485_MODE_HALF_DUPLEX flag if we assume that >> a missing SER_RS485_MODE_FULL_DUPLEX means half duplex (i.e. controlling >> the RTS line). > > You should be very careful on these assumptions, i.e. one must to check _all_ > existing user space tools (at least that are in use / supplied by main distros) > on how they behave. > Until now the DUPLEX flags do not yet exist, so existing userspace applications are not concerned. Christoph suggested to introduce two flags to distinguish between a FULL duplex and a half duplex RS485 mode. My point was that we do not need the flag for half duplex, since this would be the default. BR, Lino
On Sat, Dec 09, 2023 at 12:47:47PM +0100, Lino Sanfilippo wrote: > On 06.12.23 16:42, Lino Sanfilippo wrote: > >>>> Crescent CY Hsieh (+cc) is in parallel trying to add an RS-422 mode bit > >>>> to struct serial_rs485: > >>>> > >>>> https://lore.kernel.org/all/20231121095122.15948-1-crescentcy.hsieh@moxa.com/ > >>>> > >>> > >>> That new flag was suggested by me instead of using SER_RS422_ENABLED, which > >>> would mostly be redundant to SER_RS485_ENABLED. > > A cleaner solution would probably be to not handle RS422 with the RS485 settings at > all, but to introduce another set of ioctls to set and read it. > > An own RS422 structure like > > struct serial_rs422 { > __u32 flags; > #define SER_RS422_ENABLED (1 << 0) > #define SER_RS422_TERMINATE_BUS (1 << 1) > }; > > > could be used as the parameter for these new ioctls. > > Any comments on this? I have (maybe not so constructive) a comment. Please, at all means try to not extend the existing serial data structures, we have too many ones with too many fields already. For user space, though, one may use unions and flags, but for internal ones it might be better ways, I think.
Hi, On 11.12.23 14:07, Andy Shevchenko wrote: > On Sat, Dec 09, 2023 at 12:47:47PM +0100, Lino Sanfilippo wrote: >> On 06.12.23 16:42, Lino Sanfilippo wrote: > >>>>>> Crescent CY Hsieh (+cc) is in parallel trying to add an RS-422 mode bit >>>>>> to struct serial_rs485: >>>>>> >>>>>> https://lore.kernel.org/all/20231121095122.15948-1-crescentcy.hsieh@moxa.com/ >>>>>> >>>>> >>>>> That new flag was suggested by me instead of using SER_RS422_ENABLED, which >>>>> would mostly be redundant to SER_RS485_ENABLED. >> >> A cleaner solution would probably be to not handle RS422 with the RS485 settings at >> all, but to introduce another set of ioctls to set and read it. >> >> An own RS422 structure like >> >> struct serial_rs422 { >> __u32 flags; >> #define SER_RS422_ENABLED (1 << 0) >> #define SER_RS422_TERMINATE_BUS (1 << 1) >> }; >> >> >> could be used as the parameter for these new ioctls. >> >> Any comments on this? > > I have (maybe not so constructive) a comment. Please, at all means try to not > extend the existing serial data structures, we have too many ones with too many > fields already. For user space, though, one may use unions and flags, but for > internal ones it might be better ways, I think. > Ok, thanks. This is still a valuable information. So what if the above structure (serial_rs422) is only used as a parameter of a new TIOCSRS422 ioctl and only internally we set a SER_RS485_MODE_RS422 flag in the serial_rs485 struct? So we do not have to add something new to uart_port but also do not expose the mixture of RS485 and RS422 settings within the serial_rs485 structure to userspace. Regards, Lino
On Mon, Dec 11, 2023 at 03:07:59PM +0200, Andy Shevchenko wrote: > On Sat, Dec 09, 2023 at 12:47:47PM +0100, Lino Sanfilippo wrote: > > On 06.12.23 16:42, Lino Sanfilippo wrote: > > > >>>> Crescent CY Hsieh (+cc) is in parallel trying to add an RS-422 mode bit > > >>>> to struct serial_rs485: > > >>>> > > >>>> https://lore.kernel.org/all/20231121095122.15948-1-crescentcy.hsieh@moxa.com/ > > >>>> > > >>> > > >>> That new flag was suggested by me instead of using SER_RS422_ENABLED, which > > >>> would mostly be redundant to SER_RS485_ENABLED. > > > > A cleaner solution would probably be to not handle RS422 with the RS485 settings at > > all, but to introduce another set of ioctls to set and read it. > > > > An own RS422 structure like > > > > struct serial_rs422 { > > __u32 flags; > > #define SER_RS422_ENABLED (1 << 0) > > #define SER_RS422_TERMINATE_BUS (1 << 1) > > }; > > > > > > could be used as the parameter for these new ioctls. > > > > Any comments on this? > > I have (maybe not so constructive) a comment. Please, at all means try to not > extend the existing serial data structures, we have too many ones with too many > fields already. For user space, though, one may use unions and flags, but for > internal ones it might be better ways, I think. How about revising the name of 'TIOCSRS485' and 'serial_rs485' to a general one, and put RS422 and RS485 configuration flags into that structure? So that in userspace it could set RS422 or RS485 configurations using a single ioctl command and one structure. In this way, it won't be confused in userspace and won't add new data structure internally as well. --- Sincerely, Crescent Hsieh.
From: Crescent CY Hsieh <crescentcy.hsieh@moxa.com> Sent: Thursday, December 14, 2023 11:25 AM > On Mon, Dec 11, 2023 at 03:07:59PM +0200, Andy Shevchenko wrote: >> On Sat, Dec 09, 2023 at 12:47:47PM +0100, Lino Sanfilippo wrote: >>> On 06.12.23 16:42, Lino Sanfilippo wrote: >> >>>>>>> Crescent CY Hsieh (+cc) is in parallel trying to add an RS-422 mode bit >>>>>>> to struct serial_rs485: >>>>>>> >>>>>>> https://lore.kernel.org/all/20231121095122.15948-1-crescentcy.hsieh@moxa.com/ >>>>>>> >>>>>> >>>>>> That new flag was suggested by me instead of using SER_RS422_ENABLED, which >>>>>> would mostly be redundant to SER_RS485_ENABLED. >>> >>> A cleaner solution would probably be to not handle RS422 with the RS485 settings at >>> all, but to introduce another set of ioctls to set and read it. >>> >>> An own RS422 structure like >>> >>> struct serial_rs422 { >>> __u32 flags; >>> #define SER_RS422_ENABLED (1 << 0) >>> #define SER_RS422_TERMINATE_BUS (1 << 1) >>> }; >>> >>> >>> could be used as the parameter for these new ioctls. >>> >>> Any comments on this? >> >> I have (maybe not so constructive) a comment. Please, at all means try to not >> extend the existing serial data structures, we have too many ones with too many >> fields already. For user space, though, one may use unions and flags, but for >> internal ones it might be better ways, I think. > > How about revising the name of 'TIOCSRS485' and 'serial_rs485' to a > general one, and put RS422 and RS485 configuration flags into that > structure? > > So that in userspace it could set RS422 or RS485 configurations using a > single ioctl command and one structure. > > In this way, it won't be confused in userspace and won't add new data > structure internally as well. > I will summarize the current situation from my point of view, maybe it helps: RS-232: - Full Duplex Point-to-Point connection - No transceiver control with RTS - No termination - No extra struct in use RS-422: - Full Duplex Point-to-Point connection - No transceiver control with RTS needed - Termination possible - Extra struct serial_rs485 needed if termination is used => RS-422 can be used in RS-232 operation, but if a termination should be switchable the RS485 flag has to be enabled. But then also transceiver control will be enabled. Not a very satisfying situation. RS-485 (2-wire) very common: - Half Duplex RS-485 bus - Transceiver control with RTS is needed - Termination possible - Extra struct serial_rs485 is needed => RS-485 has to be enabled and configured: - Set SER_RS485_ENABLED - Set SER_RS485_RTS_ON_SEND or SER_RS485_RTS_AFTER_SEND - Set/clear SER_RS485_RX_DURING_TX depending on whether the receiver path should be on or off during sending. If it's set it allows to monitor the sending on the bus and detect whether another bus device is transmitting at the same time. - Set/clear SER_RS485_TERMINATE_BUS for bus termination. RS-485 (4-wire) little used: - Full Duplex RS-485 bus - Transceiver control with RTS is needed - Termination possible - Extra struct serial_rs485 is needed => RS-485 has to be enabled and configured: - Set SER_RS485_ENABLED - Set SER_RS485_RTS_ON_SEND or SER_RS485_RTS_AFTER_SEND - Set SER_RS485_RX_DURING_TX, as the receiver should always be enabled independently of TX, because TX and RX are separated from each other by their own wires. - Set/clear SER_RS485_TERMINATE_BUS for bus termination. I think the GPIOs reflect the flag states and are meaningful: - SER_RS485_TERMINATE_BUS: Switch bus termination on/off by GPIO - SER_RS485_RX_DURING_TX: Used to enable/disable RX during TX in hardware by GPIO (for 2-wire) - SER_RS485_ENABLED: Muxing between RS-232 and RS-485 by GPIO Switching RS-485 on during boot could also be handled by a devicetree overlay. Evaluate the GPIO and load a DTO accordingly before booting. Please correct me if I have misrepresented something... If I looked at it in this new way, I would discard my idea with the FULL_DUPLEX and HALF_DUPLEX. For a better use of RS-422 it would be good to disable transceiver control via RTS. It can be done by clearing the existing flags SER_RS485_RTS_ON_SEND and SER_RS485_RTS_AFTER_SEND at the same time, but I think it is confusing. Better would be a flag for RS-422: RS-422: Set SER_RS422_MODE for disabling transceiver control via RTS. RS-485 (2-wire and 4-wire): Clear SER_RS422_MODE for enabling transceiver control via RTS. Finally, at present it is also not possible to distinguish between RS485 2-wire and 4-wire operation. I think it isn't necessary, as different hardware has to be used anyway. The hardware then determines the configuration, see above. Regards Christoph
Hi, On 14.12.23 14:41, Christoph Niedermaier wrote: > From: Crescent CY Hsieh <crescentcy.hsieh@moxa.com> > Sent: Thursday, December 14, 2023 11:25 AM >> On Mon, Dec 11, 2023 at 03:07:59PM +0200, Andy Shevchenko wrote: >>> On Sat, Dec 09, 2023 at 12:47:47PM +0100, Lino Sanfilippo wrote: >>>> On 06.12.23 16:42, Lino Sanfilippo wrote: >>> >>>>>>>> Crescent CY Hsieh (+cc) is in parallel trying to add an RS-422 mode bit >>>>>>>> to struct serial_rs485: >>>>>>>> >>>>>>>> https://lore.kernel.org/all/20231121095122.15948-1-crescentcy.hsieh@moxa.com/ >>>>>>>> >>>>>>> >>>>>>> That new flag was suggested by me instead of using SER_RS422_ENABLED, which >>>>>>> would mostly be redundant to SER_RS485_ENABLED. >>>> >>>> A cleaner solution would probably be to not handle RS422 with the RS485 settings at >>>> all, but to introduce another set of ioctls to set and read it. >>>> >>>> An own RS422 structure like >>>> >>>> struct serial_rs422 { >>>> __u32 flags; >>>> #define SER_RS422_ENABLED (1 << 0) >>>> #define SER_RS422_TERMINATE_BUS (1 << 1) >>>> }; >>>> >>>> >>>> could be used as the parameter for these new ioctls. >>>> >>>> Any comments on this? >>> >>> I have (maybe not so constructive) a comment. Please, at all means try to not >>> extend the existing serial data structures, we have too many ones with too many >>> fields already. For user space, though, one may use unions and flags, but for >>> internal ones it might be better ways, I think. >> >> How about revising the name of 'TIOCSRS485' and 'serial_rs485' to a >> general one, and put RS422 and RS485 configuration flags into that >> structure? >> >> So that in userspace it could set RS422 or RS485 configurations using a >> single ioctl command and one structure. >> >> In this way, it won't be confused in userspace and won't add new data >> structure internally as well. >> > > I will summarize the current situation from my point of view, maybe it helps: > > RS-232: > - Full Duplex Point-to-Point connection > - No transceiver control with RTS > - No termination > - No extra struct in use > > RS-422: > - Full Duplex Point-to-Point connection > - No transceiver control with RTS needed > - Termination possible > - Extra struct serial_rs485 needed if termination is used > => RS-422 can be used in RS-232 operation, but if a termination should be > switchable the RS485 flag has to be enabled. But then also transceiver > control will be enabled. Not a very satisfying situation. > Thats why I vote for a RS422 mode. > RS-485 (2-wire) very common: > - Half Duplex RS-485 bus > - Transceiver control with RTS is needed > - Termination possible > - Extra struct serial_rs485 is needed > => RS-485 has to be enabled and configured: > - Set SER_RS485_ENABLED > - Set SER_RS485_RTS_ON_SEND or SER_RS485_RTS_AFTER_SEND > - Set/clear SER_RS485_RX_DURING_TX depending on whether > the receiver path should be on or off during sending. > If it's set it allows to monitor the sending on the bus > and detect whether another bus device is transmitting > at the same time. > - Set/clear SER_RS485_TERMINATE_BUS for bus termination. > > RS-485 (4-wire) little used: > - Full Duplex RS-485 bus > - Transceiver control with RTS is needed > - Termination possible > - Extra struct serial_rs485 is needed > => RS-485 has to be enabled and configured: > - Set SER_RS485_ENABLED > - Set SER_RS485_RTS_ON_SEND or SER_RS485_RTS_AFTER_SEND > - Set SER_RS485_RX_DURING_TX, as the receiver should always > be enabled independently of TX, because TX and RX are > separated from each other by their own wires. > - Set/clear SER_RS485_TERMINATE_BUS for bus termination. How can the driver distinguish between RS485 full duplex and half duplex then? In full duplex RTS control is not needed AFAIU. > > I think the GPIOs reflect the flag states and are meaningful: > - SER_RS485_TERMINATE_BUS: Switch bus termination on/off by GPIO > - SER_RS485_RX_DURING_TX: Used to enable/disable RX during TX > in hardware by GPIO (for 2-wire) > - SER_RS485_ENABLED: Muxing between RS-232 and RS-485 by GPIO > > Switching RS-485 on during boot could also be handled by a devicetree > overlay. Evaluate the GPIO and load a DTO accordingly before booting. > > Please correct me if I have misrepresented something... > > If I looked at it in this new way, I would discard my idea with the > FULL_DUPLEX and HALF_DUPLEX. For a better use of RS-422 it would be > good to disable transceiver control via RTS. It can be done by clearing > the existing flags SER_RS485_RTS_ON_SEND and SER_RS485_RTS_AFTER_SEND > at the same time, but I think it is confusing. Better would be a flag > for RS-422: > > RS-422: Set SER_RS422_MODE for disabling > transceiver control via RTS. > RS-485 (2-wire and 4-wire): Clear SER_RS422_MODE for enabling > transceiver control via RTS. > > Finally, at present it is also not possible to distinguish between RS485 > 2-wire and 4-wire operation. I think it isn't necessary, as different > hardware has to be used anyway. The hardware then determines the > configuration, see above. But the driver should somehow be informed that there exists a full duplex hardware setup, so that it does not need to control the RTS line. Maybe by means of a device tree property? Regards, Lino > > > Regards > Christoph
From: Lino Sanfilippo <LinoSanfilippo@gmx.de> Sent: Thursday, December 14, 2023 3:04 PM > > Hi, > > On 14.12.23 14:41, Christoph Niedermaier wrote: >> From: Crescent CY Hsieh <crescentcy.hsieh@moxa.com> >> Sent: Thursday, December 14, 2023 11:25 AM >>> On Mon, Dec 11, 2023 at 03:07:59PM +0200, Andy Shevchenko wrote: >>>> On Sat, Dec 09, 2023 at 12:47:47PM +0100, Lino Sanfilippo wrote: >>>>> On 06.12.23 16:42, Lino Sanfilippo wrote: >>>> >>>>>>>>> Crescent CY Hsieh (+cc) is in parallel trying to add an RS-422 mode bit >>>>>>>>> to struct serial_rs485: >>>>>>>>> >>>>>>>>> https://lore.kernel.org/all/20231121095122.15948-1-crescentcy.hsieh@moxa.com/ >>>>>>>>> >>>>>>>> >>>>>>>> That new flag was suggested by me instead of using SER_RS422_ENABLED, which >>>>>>>> would mostly be redundant to SER_RS485_ENABLED. >>>>> >>>>> A cleaner solution would probably be to not handle RS422 with the RS485 settings at >>>>> all, but to introduce another set of ioctls to set and read it. >>>>> >>>>> An own RS422 structure like >>>>> >>>>> struct serial_rs422 { >>>>> __u32 flags; >>>>> #define SER_RS422_ENABLED (1 << 0) >>>>> #define SER_RS422_TERMINATE_BUS (1 << 1) >>>>> }; >>>>> >>>>> >>>>> could be used as the parameter for these new ioctls. >>>>> >>>>> Any comments on this? >>>> >>>> I have (maybe not so constructive) a comment. Please, at all means try to not >>>> extend the existing serial data structures, we have too many ones with too many >>>> fields already. For user space, though, one may use unions and flags, but for >>>> internal ones it might be better ways, I think. >>> >>> How about revising the name of 'TIOCSRS485' and 'serial_rs485' to a >>> general one, and put RS422 and RS485 configuration flags into that >>> structure? >>> >>> So that in userspace it could set RS422 or RS485 configurations using a >>> single ioctl command and one structure. >>> >>> In this way, it won't be confused in userspace and won't add new data >>> structure internally as well. >>> >> >> I will summarize the current situation from my point of view, maybe it helps: >> >> RS-232: >> - Full Duplex Point-to-Point connection >> - No transceiver control with RTS >> - No termination >> - No extra struct in use >> >> RS-422: >> - Full Duplex Point-to-Point connection >> - No transceiver control with RTS needed >> - Termination possible >> - Extra struct serial_rs485 needed if termination is used >> => RS-422 can be used in RS-232 operation, but if a termination should be >> switchable the RS485 flag has to be enabled. But then also transceiver >> control will be enabled. Not a very satisfying situation. >> > > Thats why I vote for a RS422 mode. > >> RS-485 (2-wire) very common: >> - Half Duplex RS-485 bus >> - Transceiver control with RTS is needed >> - Termination possible >> - Extra struct serial_rs485 is needed >> => RS-485 has to be enabled and configured: >> - Set SER_RS485_ENABLED >> - Set SER_RS485_RTS_ON_SEND or SER_RS485_RTS_AFTER_SEND >> - Set/clear SER_RS485_RX_DURING_TX depending on whether >> the receiver path should be on or off during sending. >> If it's set it allows to monitor the sending on the bus >> and detect whether another bus device is transmitting >> at the same time. >> - Set/clear SER_RS485_TERMINATE_BUS for bus termination. >> >> RS-485 (4-wire) little used: >> - Full Duplex RS-485 bus >> - Transceiver control with RTS is needed >> - Termination possible >> - Extra struct serial_rs485 is needed >> => RS-485 has to be enabled and configured: >> - Set SER_RS485_ENABLED >> - Set SER_RS485_RTS_ON_SEND or SER_RS485_RTS_AFTER_SEND >> - Set SER_RS485_RX_DURING_TX, as the receiver should always >> be enabled independently of TX, because TX and RX are >> separated from each other by their own wires. >> - Set/clear SER_RS485_TERMINATE_BUS for bus termination. > > How can the driver distinguish between RS485 full duplex and half duplex then? > In full duplex RTS control is not needed AFAIU. I think we don't need to distinguish, because for a full duplex RS-485 transceiver also needs RTS control. For example look at the full duplex RS-485 transceiver ADM3491E [1]. It's a full duplex transceiver (A/B and Z/Y) that has DE (Driver enable) and DI (Driver Input) pins for controlling TX. I think the RS-485 master doesn't need it. The DE pin could also be set permanently high. But if we have more than one RS-485 slaves it's needed to avoid blocking of each other on the receiving wires of the RS-485 master. [1] https://www.analog.com/en/products/adm3491e.html >> I think the GPIOs reflect the flag states and are meaningful: >> - SER_RS485_TERMINATE_BUS: Switch bus termination on/off by GPIO >> - SER_RS485_RX_DURING_TX: Used to enable/disable RX during TX >> in hardware by GPIO (for 2-wire) >> - SER_RS485_ENABLED: Muxing between RS-232 and RS-485 by GPIO >> >> Switching RS-485 on during boot could also be handled by a devicetree >> overlay. Evaluate the GPIO and load a DTO accordingly before booting. >> >> Please correct me if I have misrepresented something... >> >> If I looked at it in this new way, I would discard my idea with the >> FULL_DUPLEX and HALF_DUPLEX. For a better use of RS-422 it would be >> good to disable transceiver control via RTS. It can be done by clearing >> the existing flags SER_RS485_RTS_ON_SEND and SER_RS485_RTS_AFTER_SEND >> at the same time, but I think it is confusing. Better would be a flag >> for RS-422: >> >> RS-422: Set SER_RS422_MODE for disabling >> transceiver control via RTS. >> RS-485 (2-wire and 4-wire): Clear SER_RS422_MODE for enabling >> transceiver control via RTS. >> >> Finally, at present it is also not possible to distinguish between RS485 >> 2-wire and 4-wire operation. I think it isn't necessary, as different >> hardware has to be used anyway. The hardware then determines the >> configuration, see above. > > But the driver should somehow be informed that there exists a full > duplex hardware setup, so that it does not need to control the RTS line. > Maybe by means of a device tree property? See above. Regards Christoph
Hi Christoph, On 14.12.23 15:50, Christoph Niedermaier wrote: > > I think we don't need to distinguish, because for a full duplex RS-485 > transceiver also needs RTS control. For example look at the full duplex > RS-485 transceiver ADM3491E [1]. It's a full duplex transceiver (A/B and Z/Y) > that has DE (Driver enable) and DI (Driver Input) pins for controlling TX. I > think the RS-485 master doesn't need it. The DE pin could also be set > permanently high. But if we have more than one RS-485 slaves it's needed to > avoid blocking of each other on the receiving wires of the RS-485 master. > Thanks for the explanation. So while still needed for the slaves, in case of the RS485 master the RTS control is not needed, right? Is this something that userspace should be able to configure? It could be set by clearing both the RTS_ON_SEND and RTS_AFTER_SEND flag (only if the driver supports this special RS485 mode, of course). Regards, Lino
From: Lino Sanfilippo [mailto:LinoSanfilippo@gmx.de] Sent: Friday, December 15, 2023 11:14 PM > > Hi Christoph, > Hi Lino, > On 14.12.23 15:50, Christoph Niedermaier wrote: > >> >> I think we don't need to distinguish, because for a full duplex RS-485 >> transceiver also needs RTS control. For example look at the full duplex >> RS-485 transceiver ADM3491E [1]. It's a full duplex transceiver (A/B and Z/Y) >> that has DE (Driver enable) and DI (Driver Input) pins for controlling TX. I >> think the RS-485 master doesn't need it. The DE pin could also be set >> permanently high. But if we have more than one RS-485 slaves it's needed to >> avoid blocking of each other on the receiving wires of the RS-485 master. >> > > Thanks for the explanation. So while still needed for the slaves, in case of the > RS485 master the RTS control is not needed, right? Yes, for the RS-485 (4-wire) master it isn't needed, but I think on the driver level it is better not to distinguish between master and salve. So use also RTS control for enabling sending on a RS-485 (4-wire) master device. > Is this something that userspace should be able to configure? It could be set > by clearing both the RTS_ON_SEND and RTS_AFTER_SEND flag (only if the driver > supports this special RS485 mode, of course). No, I think it shouldn't configure in userspace. Treating a RS-485 (4-wire) master device in the driver as a slave (with RTS control) has the following advantages: - Less confusion in user space (no additional setting available). - Only bus topology determines who is master and salve. - Save energy, because DE is only driven during sending. Regards Christoph
On Thu, Dec 14, 2023 at 01:41:47PM +0000, Christoph Niedermaier wrote: > I will summarize the current situation from my point of view, maybe it helps: > > RS-232: > - Full Duplex Point-to-Point connection > - No transceiver control with RTS > - No termination > - No extra struct in use > > RS-422: > - Full Duplex Point-to-Point connection > - No transceiver control with RTS needed > - Termination possible > - Extra struct serial_rs485 needed if termination is used > => RS-422 can be used in RS-232 operation, but if a termination should be > switchable the RS485 flag has to be enabled. But then also transceiver > control will be enabled. Not a very satisfying situation. Well why don't we just allow enabling or disabling RS-485 termination independently from the SER_RS485_ENABLED bit in struct serial_rs485? Just let the user issue a TIOCSRS485 ioctl to toggle termination even if in RS-232 mode and use that mode for RS-422. Looks like the simplest solution to me. > RS-485 (2-wire) very common: > - Half Duplex RS-485 bus > - Transceiver control with RTS is needed > - Termination possible > - Extra struct serial_rs485 is needed > => RS-485 has to be enabled and configured: > - Set SER_RS485_ENABLED > - Set SER_RS485_RTS_ON_SEND or SER_RS485_RTS_AFTER_SEND > - Set/clear SER_RS485_RX_DURING_TX depending on whether > the receiver path should be on or off during sending. > If it's set it allows to monitor the sending on the bus > and detect whether another bus device is transmitting > at the same time. > - Set/clear SER_RS485_TERMINATE_BUS for bus termination. > > RS-485 (4-wire) little used: > - Full Duplex RS-485 bus > - Transceiver control with RTS is needed > - Termination possible > - Extra struct serial_rs485 is needed > => RS-485 has to be enabled and configured: > - Set SER_RS485_ENABLED > - Set SER_RS485_RTS_ON_SEND or SER_RS485_RTS_AFTER_SEND > - Set SER_RS485_RX_DURING_TX, as the receiver should always > be enabled independently of TX, because TX and RX are > separated from each other by their own wires. > - Set/clear SER_RS485_TERMINATE_BUS for bus termination. Thanks for that overview, I found it very helpful. One small addendum: Hardware flow control. Only possible with RS-232. Doesn't work in any of the other modes, right? Thanks, Lukas
From: Lukas Wunner [mailto:lukas@wunner.de] Sent: Thursday, December 21, 2023 4:53 PM > > On Thu, Dec 14, 2023 at 01:41:47PM +0000, Christoph Niedermaier wrote: >> I will summarize the current situation from my point of view, maybe it helps: >> >> RS-232: >> - Full Duplex Point-to-Point connection >> - No transceiver control with RTS >> - No termination >> - No extra struct in use >> >> RS-422: >> - Full Duplex Point-to-Point connection >> - No transceiver control with RTS needed >> - Termination possible >> - Extra struct serial_rs485 needed if termination is used >> => RS-422 can be used in RS-232 operation, but if a termination should be >> switchable the RS485 flag has to be enabled. But then also transceiver >> control will be enabled. Not a very satisfying situation. > > Well why don't we just allow enabling or disabling RS-485 termination > independently from the SER_RS485_ENABLED bit in struct serial_rs485? > > Just let the user issue a TIOCSRS485 ioctl to toggle termination even > if in RS-232 mode and use that mode for RS-422. > > Looks like the simplest solution to me. Sounds not bad. The termination should only depend on whether the GPIO is given or not. Irrespective of this, I think the Linos idea of an RS-422 mode is not bad. This allows you to take care of special features that were previously overlooked. For example, hardware flow control can be switched off so that this does not cause any problems. >> RS-485 (2-wire) very common: >> - Half Duplex RS-485 bus >> - Transceiver control with RTS is needed >> - Termination possible >> - Extra struct serial_rs485 is needed >> => RS-485 has to be enabled and configured: >> - Set SER_RS485_ENABLED >> - Set SER_RS485_RTS_ON_SEND or SER_RS485_RTS_AFTER_SEND >> - Set/clear SER_RS485_RX_DURING_TX depending on whether >> the receiver path should be on or off during sending. >> If it's set it allows to monitor the sending on the bus >> and detect whether another bus device is transmitting >> at the same time. >> - Set/clear SER_RS485_TERMINATE_BUS for bus termination. >> >> RS-485 (4-wire) little used: >> - Full Duplex RS-485 bus >> - Transceiver control with RTS is needed >> - Termination possible >> - Extra struct serial_rs485 is needed >> => RS-485 has to be enabled and configured: >> - Set SER_RS485_ENABLED >> - Set SER_RS485_RTS_ON_SEND or SER_RS485_RTS_AFTER_SEND >> - Set SER_RS485_RX_DURING_TX, as the receiver should always >> be enabled independently of TX, because TX and RX are >> separated from each other by their own wires. >> - Set/clear SER_RS485_TERMINATE_BUS for bus termination. > > Thanks for that overview, I found it very helpful. > > One small addendum: Hardware flow control. Only possible with > RS-232. Doesn't work in any of the other modes, right? You are right I forgot to mention it. Regards and Merry Christmas Christoph
On 23.12.23 13:49, Christoph Niedermaier wrote: > From: Lukas Wunner [mailto:lukas@wunner.de] > Sent: Thursday, December 21, 2023 4:53 PM >> >> On Thu, Dec 14, 2023 at 01:41:47PM +0000, Christoph Niedermaier wrote: >>> I will summarize the current situation from my point of view, maybe it helps: >>> >>> RS-232: >>> - Full Duplex Point-to-Point connection >>> - No transceiver control with RTS >>> - No termination >>> - No extra struct in use >>> >>> RS-422: >>> - Full Duplex Point-to-Point connection >>> - No transceiver control with RTS needed >>> - Termination possible >>> - Extra struct serial_rs485 needed if termination is used >>> => RS-422 can be used in RS-232 operation, but if a termination should be >>> switchable the RS485 flag has to be enabled. But then also transceiver >>> control will be enabled. Not a very satisfying situation. >> >> Well why don't we just allow enabling or disabling RS-485 termination >> independently from the SER_RS485_ENABLED bit in struct serial_rs485? >> >> Just let the user issue a TIOCSRS485 ioctl to toggle termination even >> if in RS-232 mode and use that mode for RS-422. >> >> Looks like the simplest solution to me. > > Sounds not bad. The termination should only depend on whether the GPIO is > given or not. > > Irrespective of this, I think the Linos idea of an RS-422 mode is not bad. > This allows you to take care of special features that were previously > overlooked. For example, hardware flow control can be switched off so that > this does not cause any problems. > Also note, that RS232 and RS422 may NOT always be the same from driver perspective. Take a look at 8250_excar.c for example. That driver has to configure the hardware accordingly when switching from RS232 to RS422 (see iot2040_rs485_config()). While a SER_RS485_MODE_RS422 flag set by userspace could work to switch to RS422, I still think that the cleanest solution would be another ioctl TIOCSRS422 with a parameter like struct serial_rs422 { __u32 flags; #define SER_RS422_ENABLED (1 << 0) #define SER_RS422_TERMINATE_BUS (1 << 1) __u32 padding[7] }; The SER_RS485_MODE_RS422 flag could still be used internally as a hint to the driver. That solution would also be expandable if needed. I planned to send a patch that implements this as a RFC to the mailing list (maybe in the next few days). Regards, Lino
From: Lino Sanfilippo [mailto:LinoSanfilippo@gmx.de] Sent: Saturday, December 23, 2023 2:41 PM > On 23.12.23 13:49, Christoph Niedermaier wrote: >> From: Lukas Wunner [mailto:lukas@wunner.de] >> Sent: Thursday, December 21, 2023 4:53 PM >>> >>> On Thu, Dec 14, 2023 at 01:41:47PM +0000, Christoph Niedermaier wrote: >>>> I will summarize the current situation from my point of view, maybe it helps: >>>> >>>> RS-232: >>>> - Full Duplex Point-to-Point connection >>>> - No transceiver control with RTS >>>> - No termination >>>> - No extra struct in use >>>> >>>> RS-422: >>>> - Full Duplex Point-to-Point connection >>>> - No transceiver control with RTS needed >>>> - Termination possible >>>> - Extra struct serial_rs485 needed if termination is used >>>> => RS-422 can be used in RS-232 operation, but if a termination should be >>>> switchable the RS485 flag has to be enabled. But then also transceiver >>>> control will be enabled. Not a very satisfying situation. >>> >>> Well why don't we just allow enabling or disabling RS-485 termination >>> independently from the SER_RS485_ENABLED bit in struct serial_rs485? >>> >>> Just let the user issue a TIOCSRS485 ioctl to toggle termination even >>> if in RS-232 mode and use that mode for RS-422. >>> >>> Looks like the simplest solution to me. >> >> Sounds not bad. The termination should only depend on whether the GPIO is >> given or not. >> >> Irrespective of this, I think the Linos idea of an RS-422 mode is not bad. >> This allows you to take care of special features that were previously >> overlooked. For example, hardware flow control can be switched off so that >> this does not cause any problems. >> > > Also note, that RS232 and RS422 may NOT always be the same from driver perspective. > Take a look at 8250_excar.c for example. That driver has to configure the hardware > accordingly when switching from RS232 to RS422 (see iot2040_rs485_config()). > > While a SER_RS485_MODE_RS422 flag set by userspace could work to switch to RS422, I > still think that the cleanest solution would be another ioctl TIOCSRS422 with a > parameter like > > struct serial_rs422 { > __u32 flags; > #define SER_RS422_ENABLED (1 << 0) > #define SER_RS422_TERMINATE_BUS (1 << 1) > __u32 padding[7] > }; > > The SER_RS485_MODE_RS422 flag could still be used internally as a hint to the driver. > That solution would also be expandable if needed. I planned to send a patch that > implements this > as a RFC to the mailing list (maybe in the next few days). Having your own ioctl is a nice distinction, but when I think about it for a moment, questions come to mind: From userspace perspective then there are two termination flags SER_RS485_TERMINATE_BUS and SER_RS422_TERMINATE_BUS? How will they interact internally? What about the devicetree property? Will there be rs422-term-gpios as well? Could the user enable RS422 and RS485 at the same time? Regards and Merry Christmas Christoph
On Sat, Dec 23, 2023 at 02:40:58PM +0100, Lino Sanfilippo wrote: > On 23.12.23 13:49, Christoph Niedermaier wrote: > > From: Lukas Wunner [mailto:lukas@wunner.de] > > Sent: Thursday, December 21, 2023 4:53 PM > > > Well why don't we just allow enabling or disabling RS-485 termination > > > independently from the SER_RS485_ENABLED bit in struct serial_rs485? > > > > > > Just let the user issue a TIOCSRS485 ioctl to toggle termination even > > > if in RS-232 mode and use that mode for RS-422. > > > > Sounds not bad. The termination should only depend on whether the GPIO is > > given or not. > > > > Irrespective of this, I think the Linos idea of an RS-422 mode is not bad. > > This allows you to take care of special features that were previously > > overlooked. For example, hardware flow control can be switched off so that > > this does not cause any problems. > > Also note, that RS232 and RS422 may NOT always be the same from driver > perspective. > Take a look at 8250_excar.c for example. That driver has to configure > the hardware accordingly when switching from RS232 to RS422 > (see iot2040_rs485_config()). Actually it seems there are a bunch of GPIOs on the IOT2040 board (called MPIO instead of GPIO by the driver). See the documentation of the wiring at line 87 in drivers/tty/serial/8250/8250_exar.c. So "configure the hardware" seems to just boil down to toggling the right GPIO (aka MPIO) pins to mux the UART signals to the right (RS232/RS485/RS422) transceiver. IOT2040 is an ACPI-based platform, so no devicetree to describe the RS232/RS485/RS422 mux GPIOs, but the underlying concept is the same. Thanks, Lukas
diff --git a/Documentation/devicetree/bindings/serial/rs485.yaml b/Documentation/devicetree/bindings/serial/rs485.yaml index 9418fd66a8e9..e8136c7d22ed 100644 --- a/Documentation/devicetree/bindings/serial/rs485.yaml +++ b/Documentation/devicetree/bindings/serial/rs485.yaml @@ -61,6 +61,11 @@ properties: the active state enables RX during TX. maxItems: 1 + rs485-mux-gpios: + description: GPIO pin to control muxing of the SOC signals to the RS485 + transceiver. + maxItems: 1 + additionalProperties: true ...
Some boards are capable of both rs232 and rs485, and control which external terminals are active via a gpio-controlled mux. Allow describing that gpio in DT so that the kernel can transparently handle the proper setting when the uart is switched between rs232 and rs485 modes. Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> --- Documentation/devicetree/bindings/serial/rs485.yaml | 5 +++++ 1 file changed, 5 insertions(+)