|
78 | 78 | #define UART_TX_BYTE_FIFO 0x00
|
79 | 79 | #define UART_FIFO_CTL 0x02
|
80 | 80 |
|
| 81 | +#define UART_MODEM_CTL_REG 0x04 |
| 82 | +#define UART_MODEM_CTL_RTS_SET BIT(1) |
| 83 | + |
| 84 | +#define UART_LINE_STAT_REG 0x05 |
| 85 | +#define UART_LINE_XMIT_CHECK_MASK GENMASK(6, 5) |
| 86 | + |
81 | 87 | #define UART_ACTV_REG 0x11
|
82 | 88 | #define UART_BLOCK_SET_ACTIVE BIT(0)
|
83 | 89 |
|
|
94 | 100 | #define UART_BIT_SAMPLE_CNT_16 16
|
95 | 101 | #define BAUD_CLOCK_DIV_INT_MSK GENMASK(31, 8)
|
96 | 102 | #define ADCL_CFG_RTS_DELAY_MASK GENMASK(11, 8)
|
| 103 | +#define FRAC_DIV_TX_END_POINT_MASK GENMASK(23, 20) |
97 | 104 |
|
98 | 105 | #define UART_WAKE_REG 0x8C
|
99 | 106 | #define UART_WAKE_MASK_REG 0x90
|
|
134 | 141 | #define UART_BST_STAT_LSR_FRAME_ERR 0x8000000
|
135 | 142 | #define UART_BST_STAT_LSR_THRE 0x20000000
|
136 | 143 |
|
| 144 | +#define GET_MODEM_CTL_RTS_STATUS(reg) ((reg) & UART_MODEM_CTL_RTS_SET) |
| 145 | +#define GET_RTS_PIN_STATUS(val) (((val) & TIOCM_RTS) >> 1) |
| 146 | +#define RTS_TOGGLE_STATUS_MASK(val, reg) (GET_MODEM_CTL_RTS_STATUS(reg) \ |
| 147 | + != GET_RTS_PIN_STATUS(val)) |
| 148 | + |
137 | 149 | struct pci1xxxx_8250 {
|
138 | 150 | unsigned int nr;
|
139 | 151 | u8 dev_rev;
|
@@ -254,6 +266,47 @@ static void pci1xxxx_set_divisor(struct uart_port *port, unsigned int baud,
|
254 | 266 | port->membase + UART_BAUD_CLK_DIVISOR_REG);
|
255 | 267 | }
|
256 | 268 |
|
| 269 | +static void pci1xxxx_set_mctrl(struct uart_port *port, unsigned int mctrl) |
| 270 | +{ |
| 271 | + u32 fract_div_cfg_reg; |
| 272 | + u32 line_stat_reg; |
| 273 | + u32 modem_ctl_reg; |
| 274 | + u32 adcl_cfg_reg; |
| 275 | + |
| 276 | + adcl_cfg_reg = readl(port->membase + ADCL_CFG_REG); |
| 277 | + |
| 278 | + /* HW is responsible in ADCL_EN case */ |
| 279 | + if ((adcl_cfg_reg & (ADCL_CFG_EN | ADCL_CFG_PIN_SEL))) |
| 280 | + return; |
| 281 | + |
| 282 | + modem_ctl_reg = readl(port->membase + UART_MODEM_CTL_REG); |
| 283 | + |
| 284 | + serial8250_do_set_mctrl(port, mctrl); |
| 285 | + |
| 286 | + if (RTS_TOGGLE_STATUS_MASK(mctrl, modem_ctl_reg)) { |
| 287 | + line_stat_reg = readl(port->membase + UART_LINE_STAT_REG); |
| 288 | + if (line_stat_reg & UART_LINE_XMIT_CHECK_MASK) { |
| 289 | + fract_div_cfg_reg = readl(port->membase + |
| 290 | + FRAC_DIV_CFG_REG); |
| 291 | + |
| 292 | + writel((fract_div_cfg_reg & |
| 293 | + ~(FRAC_DIV_TX_END_POINT_MASK)), |
| 294 | + port->membase + FRAC_DIV_CFG_REG); |
| 295 | + |
| 296 | + /* Enable ADC and set the nRTS pin */ |
| 297 | + writel((adcl_cfg_reg | (ADCL_CFG_EN | |
| 298 | + ADCL_CFG_PIN_SEL)), |
| 299 | + port->membase + ADCL_CFG_REG); |
| 300 | + |
| 301 | + /* Revert to the original settings */ |
| 302 | + writel(adcl_cfg_reg, port->membase + ADCL_CFG_REG); |
| 303 | + |
| 304 | + writel(fract_div_cfg_reg, port->membase + |
| 305 | + FRAC_DIV_CFG_REG); |
| 306 | + } |
| 307 | + } |
| 308 | +} |
| 309 | + |
257 | 310 | static int pci1xxxx_rs485_config(struct uart_port *port,
|
258 | 311 | struct ktermios *termios,
|
259 | 312 | struct serial_rs485 *rs485)
|
@@ -631,9 +684,14 @@ static int pci1xxxx_setup(struct pci_dev *pdev,
|
631 | 684 | port->port.rs485_config = pci1xxxx_rs485_config;
|
632 | 685 | port->port.rs485_supported = pci1xxxx_rs485_supported;
|
633 | 686 |
|
634 |
| - /* From C0 rev Burst operation is supported */ |
| 687 | + /* |
| 688 | + * C0 and later revisions support Burst operation. |
| 689 | + * RTS workaround in mctrl is applicable only to B0. |
| 690 | + */ |
635 | 691 | if (rev >= 0xC0)
|
636 | 692 | port->port.handle_irq = pci1xxxx_handle_irq;
|
| 693 | + else if (rev == 0xB0) |
| 694 | + port->port.set_mctrl = pci1xxxx_set_mctrl; |
637 | 695 |
|
638 | 696 | ret = serial8250_pci_setup_port(pdev, port, 0, PORT_OFFSET * port_idx, 0);
|
639 | 697 | if (ret < 0)
|
|
0 commit comments