serial: 8250_pci: add RS485 for F81504/508/512
PATCH v2 1/1 serial: 8250_pci: add RS485 for F81504/508/512
Add RS485 control for Fintek F81504/508/512
F81504/508/512 can control their RTS with H/W mode. PCI configuration space for each port is 0x40 + idx * 8 + 7.
When it set with 0x01, it's configured with RS232 mode. RTS is controlled by MCR.
When it set with 0x11, it's configured with RS485 mode. RTS is controlled by H/W, RTS low with idle & RX, high with TX.
When it set with 0x31, it's configured with RS485 mode. RTS is controlled by H/W, RTS high with idle & RX, low with TX.
We will force 0x01 on pci_fintek_setup().
Changelog:
V2
1. change direct bit operation with meaningful define name.
2. due to F81504 series only support SER_RS485_ENABLED & SER_RS485_RTS_ON_SEND. We'll clean non-support area of struct serial_rs485.
3. change control method of SER_RS485_RTS_ON_SEND. In our reference circuit, the transceiver default mode needed in rx mode with RTS logic high, tx mode with RTS logic low.
If user set to SER_RS485_ENABLED(default), we should set reg with 0x31. if SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND will set reg to 0x11.
--- drivers/tty/serial/8250/8250_pci.c | 61 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+)
drivers/tty/serial/8250/8250_pci.c +61 -0
@@ -1685,11 +1685,60 @@ pci_brcm_trumanage_setup(struct serial_private *priv,return ret; } +/* RTS will control by MCR if this bit is 0 */ +#define FINTEK_RTS_CONTROL_BY_HW BIT(4) +/* only worked with FINTEK_RTS_CONTROL_BY_HW on */ +#define FINTEK_RTS_INVERT BIT(5) + +/* We should do proper H/W transceiver setting before change to RS485 mode */ +static int pci_fintek_rs485_config (struct uart_port *port, +struct serial_rs485 *rs485) +{ +u8 setting; +u8 *index = (u8 *) port->private_data; + struct pci_dev *pci_dev = container_of(port->dev, struct pci_dev, + dev); + +pci_read_config_byte (pci_dev,0x40 +8 * *index +7 , &setting); + +if (rs485->flags &SER_RS485_ENABLED ) +memset (rs485->padding,0 ,sizeof (rs485->padding)); +else +memset (rs485,0 ,sizeof (*rs485)); + +/* F81504/508/512 not support RTS delay before or after send */ + rs485->flags &=SER_RS485_ENABLED |SER_RS485_RTS_ON_SEND ; + +if (rs485->flags &SER_RS485_ENABLED ) { +/* Enable RTS H/W control mode */ + setting |=FINTEK_RTS_CONTROL_BY_HW ; + +if (rs485->flags &SER_RS485_RTS_ON_SEND ) { +/* RTS driving high on TX */ + setting &= ~FINTEK_RTS_INVERT ; + }else { +/* RTS driving low on TX */ + setting |=FINTEK_RTS_INVERT ; + } + + rs485->delay_rts_after_send =0 ; + rs485->delay_rts_before_send =0 ; + }else { +/* Disable RTS H/W control mode */ + setting &= ~(FINTEK_RTS_CONTROL_BY_HW |FINTEK_RTS_INVERT ); + } + +pci_write_config_byte (pci_dev,0x40 +8 * *index +7 , setting); + port->rs485 = *rs485; +return 0 ; +} +static int pci_fintek_setup (struct serial_private *priv,const struct pciserial_board *board,struct uart_8250_port *port,int idx) {struct pci_dev *pdev = priv->dev; +u8 *data;u8 config_base;u16 iobase;
@@ -1702,6 +1751,15 @@ static int pci_fintek_setup(struct serial_private *priv, port->port.iotype =UPIO_PORT ; port->port.iobase = iobase; + port->port.rs485_config = pci_fintek_rs485_config; + + data =devm_kzalloc (&pdev->dev,sizeof (u8),GFP_KERNEL ); +if (!data) +return -ENOMEM ; + +/* preserve index in PCI configuration space */ + *data = idx; + port->port.private_data = data;return 0 ; }
@@ -1752,6 +1810,9 @@ static int pci_fintek_init(struct pci_dev *dev) (u8)((iobase & 0xff00) >> 8));pci_write_config_byte (dev, config_base +0x06 , dev->irq); + +/* force init to RS232 Mode */ +pci_write_config_byte (dev, config_base +0x07 ,0x01 ); }return max_port;
Signature · 1 line
1.9.1
Quoted 26 lines · Peter Hung
Add RS485 control for Fintek F81504/508/512
F81504/508/512 can control their RTS with H/W mode. PCI configuration space for each port is
0x40+ idx * 8 + 7.When it set with
0x01, it's configured with RS232 mode. RTS is controlled by MCR.When it set with
0x11, it's configured with RS485 mode. RTS is controlled by H/W, RTS low with idle & RX, high with TX.When it set with
0x31, it's configured with RS485 mode. RTS is controlled by H/W, RTS high with idle & RX, low with TX.We will force
0x01onpci_fintek_setup().Changelog:
V2
1. change direct bit operation with meaningful define name.
2. due to F81504 series only supportSER_RS485_ENABLED&SER_RS485_RTS_ON_SEND. We'll clean non-support area of structserial_rs485.
3. change control method ofSER_RS485_RTS_ON_SEND. In our reference circuit, the transceiver default mode needed in rx mode with RTS logic high, tx mode with RTS logic low.
Quoted 5 lines
If user set to SER_RS485_ENABLED(default), we should set reg with 0x31. if SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND will set reg to 0x11.Signed-off-by Peter Hung <[email protected]>
Looks better, thanks. For future postings please put the changelog below the ---, we don't need it in the logs.