summaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/sc16is7xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/sc16is7xx.c')
-rw-r--r--drivers/tty/serial/sc16is7xx.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index edb5305b9d4d..025a4264430e 100644
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -196,14 +196,14 @@
* or (IO6)
* - only on 75x/76x
*/
-#define SC16IS7XX_MSR_CTS_BIT (1 << 0) /* CTS */
-#define SC16IS7XX_MSR_DSR_BIT (1 << 1) /* DSR (IO4)
+#define SC16IS7XX_MSR_CTS_BIT (1 << 4) /* CTS */
+#define SC16IS7XX_MSR_DSR_BIT (1 << 5) /* DSR (IO4)
* - only on 75x/76x
*/
-#define SC16IS7XX_MSR_RI_BIT (1 << 2) /* RI (IO7)
+#define SC16IS7XX_MSR_RI_BIT (1 << 6) /* RI (IO7)
* - only on 75x/76x
*/
-#define SC16IS7XX_MSR_CD_BIT (1 << 3) /* CD (IO6)
+#define SC16IS7XX_MSR_CD_BIT (1 << 7) /* CD (IO6)
* - only on 75x/76x
*/
#define SC16IS7XX_MSR_DELTA_MASK 0x0F /* Any of the delta bits! */
@@ -240,7 +240,7 @@
/* IOControl register bits (Only 750/760) */
#define SC16IS7XX_IOCONTROL_LATCH_BIT (1 << 0) /* Enable input latching */
-#define SC16IS7XX_IOCONTROL_GPIO_BIT (1 << 1) /* Enable GPIO[7:4] */
+#define SC16IS7XX_IOCONTROL_MODEM_BIT (1 << 1) /* Enable GPIO[7:4] as modem pins */
#define SC16IS7XX_IOCONTROL_SRESET_BIT (1 << 3) /* Software Reset */
/* EFCR register bits */
@@ -389,6 +389,13 @@ static void sc16is7xx_fifo_write(struct uart_port *port, u8 to_send)
const u8 line = sc16is7xx_line(port);
u8 addr = (SC16IS7XX_THR_REG << SC16IS7XX_REG_SHIFT) | line;
+ /*
+ * Don't send zero-length data, at least on SPI it confuses the chip
+ * delivering wrong TXLVL data.
+ */
+ if (unlikely(!to_send))
+ return;
+
regcache_cache_bypass(s->regmap, true);
regmap_raw_write(s->regmap, addr, s->buf, to_send);
regcache_cache_bypass(s->regmap, false);
@@ -630,6 +637,12 @@ static void sc16is7xx_handle_tx(struct uart_port *port)
if (likely(to_send)) {
/* Limit to size of TX FIFO */
txlen = sc16is7xx_port_read(port, SC16IS7XX_TXLVL_REG);
+ if (txlen > SC16IS7XX_FIFO_SIZE) {
+ dev_err_ratelimited(port->dev,
+ "chip reports %d free bytes in TX fifo, but it only has %d",
+ txlen, SC16IS7XX_FIFO_SIZE);
+ txlen = 0;
+ }
to_send = (to_send > txlen) ? txlen : to_send;
/* Add data to send */
@@ -674,7 +687,7 @@ static void sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno)
case SC16IS7XX_IIR_CTSRTS_SRC:
msr = sc16is7xx_port_read(port, SC16IS7XX_MSR_REG);
uart_handle_cts_change(port,
- !!(msr & SC16IS7XX_MSR_CTS_BIT));
+ !!(msr & SC16IS7XX_MSR_DCTS_BIT));
break;
case SC16IS7XX_IIR_THRI_SRC:
sc16is7xx_handle_tx(port);
@@ -748,12 +761,20 @@ static void sc16is7xx_reg_proc(struct kthread_work *ws)
memset(&one->config, 0, sizeof(one->config));
spin_unlock_irqrestore(&one->port.lock, irqflags);
- if (config.flags & SC16IS7XX_RECONF_MD)
+ if (config.flags & SC16IS7XX_RECONF_MD) {
sc16is7xx_port_update(&one->port, SC16IS7XX_MCR_REG,
SC16IS7XX_MCR_LOOP_BIT,
(one->port.mctrl & TIOCM_LOOP) ?
SC16IS7XX_MCR_LOOP_BIT : 0);
-
+ sc16is7xx_port_update(&one->port, SC16IS7XX_MCR_REG,
+ SC16IS7XX_MCR_RTS_BIT,
+ (one->port.mctrl & TIOCM_RTS) ?
+ SC16IS7XX_MCR_RTS_BIT : 0);
+ sc16is7xx_port_update(&one->port, SC16IS7XX_MCR_REG,
+ SC16IS7XX_MCR_DTR_BIT,
+ (one->port.mctrl & TIOCM_DTR) ?
+ SC16IS7XX_MCR_DTR_BIT : 0);
+ }
if (config.flags & SC16IS7XX_RECONF_IER)
sc16is7xx_port_update(&one->port, SC16IS7XX_IER_REG,
config.ier_clear, 0);
@@ -1180,7 +1201,7 @@ static int sc16is7xx_probe(struct device *dev,
if (devtype->nr_gpio) {
/* Setup GPIO cotroller */
s->gpio.owner = THIS_MODULE;
- s->gpio.dev = dev;
+ s->gpio.parent = dev;
s->gpio.label = dev_name(dev);
s->gpio.direction_input = sc16is7xx_gpio_direction_input;
s->gpio.get = sc16is7xx_gpio_get;
OpenPOWER on IntegriCloud