[PATCH] tty: sc16is7xx: Fix per-channel rx/tx buffer access

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Register access must encode the channel of this multi-channel device
in the lowest nibble of the register address.

This is done correctly most of the time, but not when reading/writing
the fifo in handle_tx/rx. It worked by fortune for channel 0, because
the address happens to be 0x0, but not for any other channel.

Fix this bug, and add a macro to encapsulate the address encoding, and use
it everywhere.

Signed-off-by: Florian Achleitner <achleitner.florian@xxxxxxxxxxx>
---
 drivers/tty/serial/sc16is7xx.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index d1c046d..954001c 100644
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -295,6 +295,9 @@
 #define SC16IS7XX_FIFO_SIZE		(64)
 #define SC16IS7XX_REG_SHIFT		2
 
+/* Build the address of a per-channel register */
+#define SC16IS7XX_LINE_REG_ADDR(reg, line) ((reg << SC16IS7XX_REG_SHIFT) | (line))
+
 struct sc16is7xx_devtype {
 	char	name[10];
 	int	nr_gpio;
@@ -327,8 +330,7 @@ static u8 sc16is7xx_port_read(struct uart_port *port, u8 reg)
 	struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
 	unsigned int val = 0;
 
-	regmap_read(s->regmap,
-		    (reg << SC16IS7XX_REG_SHIFT) | port->line, &val);
+	regmap_read(s->regmap, SC16IS7XX_LINE_REG_ADDR(reg, port->line), &val);
 
 	return val;
 }
@@ -337,8 +339,7 @@ static void sc16is7xx_port_write(struct uart_port *port, u8 reg, u8 val)
 {
 	struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
 
-	regmap_write(s->regmap,
-		     (reg << SC16IS7XX_REG_SHIFT) | port->line, val);
+	regmap_write(s->regmap, SC16IS7XX_LINE_REG_ADDR(reg, port->line), val);
 }
 
 static void sc16is7xx_port_update(struct uart_port *port, u8 reg,
@@ -346,8 +347,7 @@ static void sc16is7xx_port_update(struct uart_port *port, u8 reg,
 {
 	struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
 
-	regmap_update_bits(s->regmap,
-			   (reg << SC16IS7XX_REG_SHIFT) | port->line,
+	regmap_update_bits(s->regmap, SC16IS7XX_LINE_REG_ADDR(reg, port->line),
 			   mask, val);
 }
 
@@ -496,7 +496,8 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
 			bytes_read = 1;
 		} else {
 			regcache_cache_bypass(s->regmap, true);
-			regmap_raw_read(s->regmap, SC16IS7XX_RHR_REG,
+			regmap_raw_read(s->regmap,
+					SC16IS7XX_LINE_REG_ADDR(SC16IS7XX_RHR_REG, port->line),
 					s->buf, rxlen);
 			regcache_cache_bypass(s->regmap, false);
 			bytes_read = rxlen;
@@ -579,7 +580,9 @@ static void sc16is7xx_handle_tx(struct uart_port *port)
 			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 		}
 		regcache_cache_bypass(s->regmap, true);
-		regmap_raw_write(s->regmap, SC16IS7XX_THR_REG, s->buf, to_send);
+		regmap_raw_write(s->regmap,
+				SC16IS7XX_LINE_REG_ADDR(SC16IS7XX_THR_REG, port->line),
+				s->buf, to_send);
 		regcache_cache_bypass(s->regmap, false);
 	}
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux