+++ /dev/null
-From 4409df5866b7ff7686ba27e449ca97a92ee063c9 Mon Sep 17 00:00:00 2001
-From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
-Date: Mon, 11 Dec 2023 12:13:51 -0500
-Subject: serial: sc16is7xx: change EFR lock to operate on each channels
-
-From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
-
-commit 4409df5866b7ff7686ba27e449ca97a92ee063c9 upstream.
-
-Now that the driver has been converted to use one regmap per port, change
-efr locking to operate on a channel basis instead of on the whole IC.
-
-Fixes: 3837a0379533 ("serial: sc16is7xx: improve regmap debugfs by using one regmap per port")
-Cc: <stable@vger.kernel.org> # 6.1.x: 3837a03 serial: sc16is7xx: improve regmap debugfs by using one regmap per port
-Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
-Link: https://lore.kernel.org/r/20231211171353.2901416-5-hugo@hugovil.com
-[Hui: fixed some conflict when backporting to 5.15.y]
-Signed-off-by: Hui Wang <hui.wang@canonical.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/tty/serial/sc16is7xx.c | 41 +++++++++++++++++++++++------------------
- 1 file changed, 23 insertions(+), 18 deletions(-)
-
---- a/drivers/tty/serial/sc16is7xx.c
-+++ b/drivers/tty/serial/sc16is7xx.c
-@@ -314,6 +314,7 @@ struct sc16is7xx_one_config {
- struct sc16is7xx_one {
- struct uart_port port;
- struct regmap *regmap;
-+ struct mutex efr_lock; /* EFR registers access */
- struct kthread_work tx_work;
- struct kthread_work reg_work;
- struct sc16is7xx_one_config config;
-@@ -329,7 +330,6 @@ struct sc16is7xx_port {
- unsigned char buf[SC16IS7XX_FIFO_SIZE];
- struct kthread_worker kworker;
- struct task_struct *kworker_task;
-- struct mutex efr_lock;
- struct sc16is7xx_one p[];
- };
-
-@@ -491,7 +491,6 @@ static bool sc16is7xx_regmap_noinc(struc
- */
- static int sc16is7xx_set_baud(struct uart_port *port, int baud)
- {
-- struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
- struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
- u8 lcr;
- unsigned int prescaler = 1;
-@@ -515,7 +514,7 @@ static int sc16is7xx_set_baud(struct uar
- * because the bulk of the interrupt processing is run as a workqueue
- * job in thread context.
- */
-- mutex_lock(&s->efr_lock);
-+ mutex_lock(&one->efr_lock);
-
- lcr = sc16is7xx_port_read(port, SC16IS7XX_LCR_REG);
-
-@@ -532,7 +531,7 @@ static int sc16is7xx_set_baud(struct uar
- /* Put LCR back to the normal mode */
- sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
-
-- mutex_unlock(&s->efr_lock);
-+ mutex_unlock(&one->efr_lock);
-
- /* If bit MCR_CLKSEL is set, the divide by 4 prescaler is activated. */
- sc16is7xx_port_update(port, SC16IS7XX_MCR_REG,
-@@ -680,14 +679,20 @@ static void sc16is7xx_handle_tx(struct u
-
- static bool sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno)
- {
-+ bool rc = true;
- struct uart_port *port = &s->p[portno].port;
-+ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
-+
-+ mutex_lock(&one->efr_lock);
-
- do {
- unsigned int iir, rxlen;
-
- iir = sc16is7xx_port_read(port, SC16IS7XX_IIR_REG);
-- if (iir & SC16IS7XX_IIR_NO_INT_BIT)
-- return false;
-+ if (iir & SC16IS7XX_IIR_NO_INT_BIT) {
-+ rc = false;
-+ goto out_port_irq;
-+ }
-
- iir &= SC16IS7XX_IIR_ID_MASK;
-
-@@ -722,15 +727,17 @@ static bool sc16is7xx_port_irq(struct sc
- break;
- }
- } while (0);
-- return true;
-+
-+out_port_irq:
-+ mutex_unlock(&one->efr_lock);
-+
-+ return rc;
- }
-
- static irqreturn_t sc16is7xx_irq(int irq, void *dev_id)
- {
- struct sc16is7xx_port *s = (struct sc16is7xx_port *)dev_id;
-
-- mutex_lock(&s->efr_lock);
--
- while (1) {
- bool keep_polling = false;
- int i;
-@@ -741,23 +748,21 @@ static irqreturn_t sc16is7xx_irq(int irq
- break;
- }
-
-- mutex_unlock(&s->efr_lock);
--
- return IRQ_HANDLED;
- }
-
- static void sc16is7xx_tx_proc(struct kthread_work *ws)
- {
- struct uart_port *port = &(to_sc16is7xx_one(ws, tx_work)->port);
-- struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
-+ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
-
- if ((port->rs485.flags & SER_RS485_ENABLED) &&
- (port->rs485.delay_rts_before_send > 0))
- msleep(port->rs485.delay_rts_before_send);
-
-- mutex_lock(&s->efr_lock);
-+ mutex_lock(&one->efr_lock);
- sc16is7xx_handle_tx(port);
-- mutex_unlock(&s->efr_lock);
-+ mutex_unlock(&one->efr_lock);
- }
-
- static void sc16is7xx_reconf_rs485(struct uart_port *port)
-@@ -878,7 +883,6 @@ static void sc16is7xx_set_termios(struct
- struct ktermios *termios,
- struct ktermios *old)
- {
-- struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
- struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
- unsigned int lcr, flow = 0;
- int baud;
-@@ -934,7 +938,7 @@ static void sc16is7xx_set_termios(struct
- port->ignore_status_mask |= SC16IS7XX_LSR_BRK_ERROR_MASK;
-
- /* As above, claim the mutex while accessing the EFR. */
-- mutex_lock(&s->efr_lock);
-+ mutex_lock(&one->efr_lock);
-
- sc16is7xx_port_write(port, SC16IS7XX_LCR_REG,
- SC16IS7XX_LCR_CONF_MODE_B);
-@@ -957,7 +961,7 @@ static void sc16is7xx_set_termios(struct
- /* Update LCR register */
- sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
-
-- mutex_unlock(&s->efr_lock);
-+ mutex_unlock(&one->efr_lock);
-
- /* Get baud rate generator configuration */
- baud = uart_get_baud_rate(port, termios, old,
-@@ -1261,7 +1265,6 @@ static int sc16is7xx_probe(struct device
-
- s->devtype = devtype;
- dev_set_drvdata(dev, s);
-- mutex_init(&s->efr_lock);
-
- kthread_init_worker(&s->kworker);
- s->kworker_task = kthread_run(kthread_worker_fn, &s->kworker,
-@@ -1302,6 +1305,8 @@ static int sc16is7xx_probe(struct device
- goto out_ports;
- }
-
-+ mutex_init(&s->p[i].efr_lock);
-+
- /* Disable all interrupts */
- sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_IER_REG, 0);
- /* Disable TX/RX */
+++ /dev/null
-From 3837a0379533aabb9e4483677077479f7c6aa910 Mon Sep 17 00:00:00 2001
-From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
-Date: Mon, 30 Oct 2023 17:14:47 -0400
-Subject: serial: sc16is7xx: improve regmap debugfs by using one regmap per port
-
-From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
-
-commit 3837a0379533aabb9e4483677077479f7c6aa910 upstream.
-
-With this current driver regmap implementation, it is hard to make sense
-of the register addresses displayed using the regmap debugfs interface,
-because they do not correspond to the actual register addresses documented
-in the datasheet. For example, register 1 is displayed as registers 04 thru
-07:
-
-$ cat /sys/kernel/debug/regmap/spi0.0/registers
- 04: 10 -> Port 0, register offset 1
- 05: 10 -> Port 1, register offset 1
- 06: 00 -> Port 2, register offset 1 -> invalid
- 07: 00 -> port 3, register offset 1 -> invalid
- ...
-
-The reason is that bits 0 and 1 of the register address correspond to the
-channel (port) bits, so the register address itself starts at bit 2, and we
-must 'mentally' shift each register address by 2 bits to get its real
-address/offset.
-
-Also, only channels 0 and 1 are supported by the chip, so channel mask
-combinations of 10b and 11b are invalid, and the display of these
-registers is useless.
-
-This patch adds a separate regmap configuration for each port, similar to
-what is done in the max310x driver, so that register addresses displayed
-match the register addresses in the chip datasheet. Also, each port now has
-its own debugfs entry.
-
-Example with new regmap implementation:
-
-$ cat /sys/kernel/debug/regmap/spi0.0-port0/registers
-1: 10
-2: 01
-3: 00
-...
-
-$ cat /sys/kernel/debug/regmap/spi0.0-port1/registers
-1: 10
-2: 01
-3: 00
-
-As an added bonus, this also simplifies some operations (read/write/modify)
-because it is no longer necessary to manually shift register addresses.
-
-Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
-Link: https://lore.kernel.org/r/20231030211447.974779-1-hugo@hugovil.com
-[Hui: Fixed some conflict when backporting to 5.15.y]
-Signed-off-by: Hui Wang <hui.wang@canonical.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/tty/serial/sc16is7xx.c | 136 +++++++++++++++++++++++------------------
- 1 file changed, 79 insertions(+), 57 deletions(-)
-
---- a/drivers/tty/serial/sc16is7xx.c
-+++ b/drivers/tty/serial/sc16is7xx.c
-@@ -292,8 +292,9 @@
- */
-
- /* Misc definitions */
-+#define SC16IS7XX_SPI_READ_BIT BIT(7)
- #define SC16IS7XX_FIFO_SIZE (64)
--#define SC16IS7XX_REG_SHIFT 2
-+#define SC16IS7XX_GPIOS_PER_BANK 4
-
- struct sc16is7xx_devtype {
- char name[10];
-@@ -313,6 +314,7 @@ struct sc16is7xx_one_config {
- struct sc16is7xx_one {
- struct uart_port port;
- u8 line;
-+ struct regmap *regmap;
- struct kthread_work tx_work;
- struct kthread_work reg_work;
- struct sc16is7xx_one_config config;
-@@ -344,46 +346,35 @@ static struct uart_driver sc16is7xx_uart
- #define to_sc16is7xx_port(p,e) ((container_of((p), struct sc16is7xx_port, e)))
- #define to_sc16is7xx_one(p,e) ((container_of((p), struct sc16is7xx_one, e)))
-
--static int sc16is7xx_line(struct uart_port *port)
--{
-- struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
--
-- return one->line;
--}
--
- static u8 sc16is7xx_port_read(struct uart_port *port, u8 reg)
- {
-- struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
-+ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
- unsigned int val = 0;
-- const u8 line = sc16is7xx_line(port);
-
-- regmap_read(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line, &val);
-+ regmap_read(one->regmap, reg, &val);
-
- return val;
- }
-
- static void sc16is7xx_port_write(struct uart_port *port, u8 reg, u8 val)
- {
-- struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
-- const u8 line = sc16is7xx_line(port);
-+ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
-
-- regmap_write(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line, val);
-+ regmap_write(one->regmap, reg, val);
- }
-
- static void sc16is7xx_fifo_read(struct uart_port *port, unsigned int rxlen)
- {
- struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
-- const u8 line = sc16is7xx_line(port);
-- u8 addr = (SC16IS7XX_RHR_REG << SC16IS7XX_REG_SHIFT) | line;
-+ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
-
-- regmap_noinc_read(s->regmap, addr, s->buf, rxlen);
-+ regmap_noinc_read(one->regmap, SC16IS7XX_RHR_REG, s->buf, rxlen);
- }
-
- static void sc16is7xx_fifo_write(struct uart_port *port, u8 to_send)
- {
- struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
-- const u8 line = sc16is7xx_line(port);
-- u8 addr = (SC16IS7XX_THR_REG << SC16IS7XX_REG_SHIFT) | line;
-+ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
-
- /*
- * Don't send zero-length data, at least on SPI it confuses the chip
-@@ -392,17 +383,15 @@ static void sc16is7xx_fifo_write(struct
- if (unlikely(!to_send))
- return;
-
-- regmap_noinc_write(s->regmap, addr, s->buf, to_send);
-+ regmap_noinc_write(one->regmap, SC16IS7XX_THR_REG, s->buf, to_send);
- }
-
- static void sc16is7xx_port_update(struct uart_port *port, u8 reg,
- u8 mask, u8 val)
- {
-- struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
-- const u8 line = sc16is7xx_line(port);
-+ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
-
-- regmap_update_bits(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line,
-- mask, val);
-+ regmap_update_bits(one->regmap, reg, mask, val);
- }
-
- static int sc16is7xx_alloc_line(void)
-@@ -457,7 +446,7 @@ static const struct sc16is7xx_devtype sc
-
- static bool sc16is7xx_regmap_volatile(struct device *dev, unsigned int reg)
- {
-- switch (reg >> SC16IS7XX_REG_SHIFT) {
-+ switch (reg) {
- case SC16IS7XX_RHR_REG:
- case SC16IS7XX_IIR_REG:
- case SC16IS7XX_LSR_REG:
-@@ -475,7 +464,7 @@ static bool sc16is7xx_regmap_volatile(st
-
- static bool sc16is7xx_regmap_precious(struct device *dev, unsigned int reg)
- {
-- switch (reg >> SC16IS7XX_REG_SHIFT) {
-+ switch (reg) {
- case SC16IS7XX_RHR_REG:
- return true;
- default:
-@@ -505,6 +494,7 @@ static bool sc16is7xx_regmap_noinc(struc
- static int sc16is7xx_set_baud(struct uart_port *port, int baud)
- {
- struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
-+ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
- u8 lcr;
- unsigned int prescaler = 1;
- unsigned long clk = port->uartclk, div = clk / 16 / baud;
-@@ -536,10 +526,10 @@ static int sc16is7xx_set_baud(struct uar
- SC16IS7XX_LCR_CONF_MODE_B);
-
- /* Enable enhanced features */
-- regcache_cache_bypass(s->regmap, true);
-+ regcache_cache_bypass(one->regmap, true);
- sc16is7xx_port_write(port, SC16IS7XX_EFR_REG,
- SC16IS7XX_EFR_ENABLE_BIT);
-- regcache_cache_bypass(s->regmap, false);
-+ regcache_cache_bypass(one->regmap, false);
-
- /* Put LCR back to the normal mode */
- sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
-@@ -556,10 +546,10 @@ static int sc16is7xx_set_baud(struct uar
- SC16IS7XX_LCR_CONF_MODE_A);
-
- /* Write the new divisor */
-- regcache_cache_bypass(s->regmap, true);
-+ regcache_cache_bypass(one->regmap, true);
- sc16is7xx_port_write(port, SC16IS7XX_DLH_REG, div / 256);
- sc16is7xx_port_write(port, SC16IS7XX_DLL_REG, div % 256);
-- regcache_cache_bypass(s->regmap, false);
-+ regcache_cache_bypass(one->regmap, false);
-
- /* Put LCR back to the normal mode */
- sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
-@@ -891,6 +881,7 @@ static void sc16is7xx_set_termios(struct
- struct ktermios *old)
- {
- struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
-+ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
- unsigned int lcr, flow = 0;
- int baud;
-
-@@ -951,7 +942,7 @@ static void sc16is7xx_set_termios(struct
- SC16IS7XX_LCR_CONF_MODE_B);
-
- /* Configure flow control */
-- regcache_cache_bypass(s->regmap, true);
-+ regcache_cache_bypass(one->regmap, true);
- sc16is7xx_port_write(port, SC16IS7XX_XON1_REG, termios->c_cc[VSTART]);
- sc16is7xx_port_write(port, SC16IS7XX_XOFF1_REG, termios->c_cc[VSTOP]);
- if (termios->c_cflag & CRTSCTS)
-@@ -963,7 +954,7 @@ static void sc16is7xx_set_termios(struct
- flow |= SC16IS7XX_EFR_SWFLOW1_BIT;
-
- sc16is7xx_port_write(port, SC16IS7XX_EFR_REG, flow);
-- regcache_cache_bypass(s->regmap, false);
-+ regcache_cache_bypass(one->regmap, false);
-
- /* Update LCR register */
- sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
-@@ -1018,7 +1009,6 @@ static int sc16is7xx_config_rs485(struct
- static int sc16is7xx_startup(struct uart_port *port)
- {
- struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
-- struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
- unsigned int val;
-
- sc16is7xx_power(port, 1);
-@@ -1034,7 +1024,7 @@ static int sc16is7xx_startup(struct uart
- sc16is7xx_port_write(port, SC16IS7XX_LCR_REG,
- SC16IS7XX_LCR_CONF_MODE_B);
-
-- regcache_cache_bypass(s->regmap, true);
-+ regcache_cache_bypass(one->regmap, true);
-
- /* Enable write access to enhanced features and internal clock div */
- sc16is7xx_port_write(port, SC16IS7XX_EFR_REG,
-@@ -1051,7 +1041,7 @@ static int sc16is7xx_startup(struct uart
- SC16IS7XX_TCR_RX_RESUME(24) |
- SC16IS7XX_TCR_RX_HALT(48));
-
-- regcache_cache_bypass(s->regmap, false);
-+ regcache_cache_bypass(one->regmap, false);
-
- /* Now, initialize the UART */
- sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, SC16IS7XX_LCR_WORD_LEN_8);
-@@ -1216,7 +1206,7 @@ static int sc16is7xx_gpio_direction_outp
-
- static int sc16is7xx_probe(struct device *dev,
- const struct sc16is7xx_devtype *devtype,
-- struct regmap *regmap, int irq)
-+ struct regmap *regmaps[], int irq)
- {
- unsigned long freq = 0, *pfreq = dev_get_platdata(dev);
- unsigned int val;
-@@ -1224,16 +1214,16 @@ static int sc16is7xx_probe(struct device
- int i, ret;
- struct sc16is7xx_port *s;
-
-- if (IS_ERR(regmap))
-- return PTR_ERR(regmap);
-+ for (i = 0; i < devtype->nr_uart; i++)
-+ if (IS_ERR(regmaps[i]))
-+ return PTR_ERR(regmaps[i]);
-
- /*
- * This device does not have an identification register that would
- * tell us if we are really connected to the correct device.
- * The best we can do is to check if communication is at all possible.
- */
-- ret = regmap_read(regmap,
-- SC16IS7XX_LSR_REG << SC16IS7XX_REG_SHIFT, &val);
-+ ret = regmap_read(regmaps[0], SC16IS7XX_LSR_REG, &val);
- if (ret < 0)
- return -EPROBE_DEFER;
-
-@@ -1267,7 +1257,7 @@ static int sc16is7xx_probe(struct device
- return -EINVAL;
- }
-
-- s->regmap = regmap;
-+ s->regmap = regmaps[0];
- s->devtype = devtype;
- dev_set_drvdata(dev, s);
- mutex_init(&s->efr_lock);
-@@ -1282,8 +1272,8 @@ static int sc16is7xx_probe(struct device
- sched_set_fifo(s->kworker_task);
-
- /* reset device, purging any pending irq / data */
-- regmap_write(s->regmap, SC16IS7XX_IOCONTROL_REG << SC16IS7XX_REG_SHIFT,
-- SC16IS7XX_IOCONTROL_SRESET_BIT);
-+ regmap_write(s->regmap, SC16IS7XX_IOCONTROL_REG,
-+ SC16IS7XX_IOCONTROL_SRESET_BIT);
-
- for (i = 0; i < devtype->nr_uart; ++i) {
- s->p[i].line = i;
-@@ -1305,6 +1295,8 @@ static int sc16is7xx_probe(struct device
- s->p[i].port.rs485_config = sc16is7xx_config_rs485;
- s->p[i].port.ops = &sc16is7xx_ops;
- s->p[i].port.line = sc16is7xx_alloc_line();
-+ s->p[i].regmap = regmaps[i];
-+
- if (s->p[i].port.line >= SC16IS7XX_MAX_DEVS) {
- ret = -ENOMEM;
- goto out_ports;
-@@ -1326,13 +1318,13 @@ static int sc16is7xx_probe(struct device
- sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_LCR_REG,
- SC16IS7XX_LCR_CONF_MODE_B);
-
-- regcache_cache_bypass(s->regmap, true);
-+ regcache_cache_bypass(regmaps[i], true);
-
- /* Enable write access to enhanced features */
- sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_EFR_REG,
- SC16IS7XX_EFR_ENABLE_BIT);
-
-- regcache_cache_bypass(s->regmap, false);
-+ regcache_cache_bypass(regmaps[i], false);
-
- /* Restore access to general registers */
- sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_LCR_REG, 0x00);
-@@ -1447,21 +1439,38 @@ static const struct of_device_id __maybe
- MODULE_DEVICE_TABLE(of, sc16is7xx_dt_ids);
-
- static struct regmap_config regcfg = {
-- .reg_bits = 7,
-- .pad_bits = 1,
-+ .reg_bits = 5,
-+ .pad_bits = 3,
- .val_bits = 8,
- .cache_type = REGCACHE_RBTREE,
- .volatile_reg = sc16is7xx_regmap_volatile,
- .precious_reg = sc16is7xx_regmap_precious,
- .writeable_noinc_reg = sc16is7xx_regmap_noinc,
- .readable_noinc_reg = sc16is7xx_regmap_noinc,
-+ .max_register = SC16IS7XX_EFCR_REG,
- };
-
-+static const char *sc16is7xx_regmap_name(unsigned int port_id)
-+{
-+ static char buf[6];
-+
-+ snprintf(buf, sizeof(buf), "port%d", port_id);
-+
-+ return buf;
-+}
-+
-+static unsigned int sc16is7xx_regmap_port_mask(unsigned int port_id)
-+{
-+ /* CH1,CH0 are at bits 2:1. */
-+ return port_id << 1;
-+}
-+
- #ifdef CONFIG_SERIAL_SC16IS7XX_SPI
- static int sc16is7xx_spi_probe(struct spi_device *spi)
- {
- const struct sc16is7xx_devtype *devtype;
-- struct regmap *regmap;
-+ struct regmap *regmaps[2];
-+ unsigned int i;
- int ret;
-
- /* Setup SPI bus */
-@@ -1486,11 +1495,20 @@ static int sc16is7xx_spi_probe(struct sp
- devtype = (struct sc16is7xx_devtype *)id_entry->driver_data;
- }
-
-- regcfg.max_register = (0xf << SC16IS7XX_REG_SHIFT) |
-- (devtype->nr_uart - 1);
-- regmap = devm_regmap_init_spi(spi, ®cfg);
-+ for (i = 0; i < devtype->nr_uart; i++) {
-+ regcfg.name = sc16is7xx_regmap_name(i);
-+ /*
-+ * If read_flag_mask is 0, the regmap code sets it to a default
-+ * of 0x80. Since we specify our own mask, we must add the READ
-+ * bit ourselves:
-+ */
-+ regcfg.read_flag_mask = sc16is7xx_regmap_port_mask(i) |
-+ SC16IS7XX_SPI_READ_BIT;
-+ regcfg.write_flag_mask = sc16is7xx_regmap_port_mask(i);
-+ regmaps[i] = devm_regmap_init_spi(spi, ®cfg);
-+ }
-
-- return sc16is7xx_probe(&spi->dev, devtype, regmap, spi->irq);
-+ return sc16is7xx_probe(&spi->dev, devtype, regmaps, spi->irq);
- }
-
- static int sc16is7xx_spi_remove(struct spi_device *spi)
-@@ -1529,7 +1547,8 @@ static int sc16is7xx_i2c_probe(struct i2
- const struct i2c_device_id *id)
- {
- const struct sc16is7xx_devtype *devtype;
-- struct regmap *regmap;
-+ struct regmap *regmaps[2];
-+ unsigned int i;
-
- if (i2c->dev.of_node) {
- devtype = device_get_match_data(&i2c->dev);
-@@ -1539,11 +1558,14 @@ static int sc16is7xx_i2c_probe(struct i2
- devtype = (struct sc16is7xx_devtype *)id->driver_data;
- }
-
-- regcfg.max_register = (0xf << SC16IS7XX_REG_SHIFT) |
-- (devtype->nr_uart - 1);
-- regmap = devm_regmap_init_i2c(i2c, ®cfg);
-+ for (i = 0; i < devtype->nr_uart; i++) {
-+ regcfg.name = sc16is7xx_regmap_name(i);
-+ regcfg.read_flag_mask = sc16is7xx_regmap_port_mask(i);
-+ regcfg.write_flag_mask = sc16is7xx_regmap_port_mask(i);
-+ regmaps[i] = devm_regmap_init_i2c(i2c, ®cfg);
-+ }
-
-- return sc16is7xx_probe(&i2c->dev, devtype, regmap, i2c->irq);
-+ return sc16is7xx_probe(&i2c->dev, devtype, regmaps, i2c->irq);
- }
-
- static int sc16is7xx_i2c_remove(struct i2c_client *client)