]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.1
authorSasha Levin <sashal@kernel.org>
Sun, 10 Sep 2023 14:39:23 +0000 (10:39 -0400)
committerSasha Levin <sashal@kernel.org>
Sun, 10 Sep 2023 14:39:23 +0000 (10:39 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-6.1/serial-sc16is7xx-fix-regression-with-gpio-configurat.patch [new file with mode: 0644]
queue-6.1/serial-sc16is7xx-remove-obsolete-out_thread-label.patch [new file with mode: 0644]
queue-6.1/series

diff --git a/queue-6.1/serial-sc16is7xx-fix-regression-with-gpio-configurat.patch b/queue-6.1/serial-sc16is7xx-fix-regression-with-gpio-configurat.patch
new file mode 100644 (file)
index 0000000..53807c7
--- /dev/null
@@ -0,0 +1,287 @@
+From b9bf3cbfbc48c29b0b82590222a25e12f999e39d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Aug 2023 17:45:54 -0400
+Subject: serial: sc16is7xx: fix regression with GPIO configuration
+
+From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+
+[ Upstream commit 0499942928341d572a42199580433c2b0725211e ]
+
+Commit 679875d1d880 ("sc16is7xx: Separate GPIOs from modem control lines")
+and commit 21144bab4f11 ("sc16is7xx: Handle modem status lines")
+changed the function of the GPIOs pins to act as modem control
+lines without any possibility of selecting GPIO function.
+
+As a consequence, applications that depends on GPIO lines configured
+by default as GPIO pins no longer work as expected.
+
+Also, the change to select modem control lines function was done only
+for channel A of dual UART variants (752/762). This was not documented
+in the log message.
+
+Allow to specify GPIO or modem control line function in the device
+tree, and for each of the ports (A or B).
+
+Do so by using the new device-tree property named
+"nxp,modem-control-line-ports" (property added in separate patch).
+
+When registering GPIO chip controller, mask-out GPIO pins declared as
+modem control lines according to this new DT property.
+
+Fixes: 679875d1d880 ("sc16is7xx: Separate GPIOs from modem control lines")
+Fixes: 21144bab4f11 ("sc16is7xx: Handle modem status lines")
+Cc: stable@vger.kernel.org
+Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Reviewed-by: Lech Perczak <lech.perczak@camlingroup.com>
+Tested-by: Lech Perczak <lech.perczak@camlingroup.com>
+Acked-by: Rob Herring <robh@kernel.org>
+Link: https://lore.kernel.org/r/20230807214556.540627-5-hugo@hugovil.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/sc16is7xx.c | 143 +++++++++++++++++++++++++--------
+ 1 file changed, 108 insertions(+), 35 deletions(-)
+
+diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
+index c481c84019f4a..21145eb8f2a9c 100644
+--- a/drivers/tty/serial/sc16is7xx.c
++++ b/drivers/tty/serial/sc16is7xx.c
+@@ -236,7 +236,8 @@
+ /* IOControl register bits (Only 750/760) */
+ #define SC16IS7XX_IOCONTROL_LATCH_BIT (1 << 0) /* Enable input latching */
+-#define SC16IS7XX_IOCONTROL_MODEM_BIT (1 << 1) /* Enable GPIO[7:4] as modem pins */
++#define SC16IS7XX_IOCONTROL_MODEM_A_BIT       (1 << 1) /* Enable GPIO[7:4] as modem A pins */
++#define SC16IS7XX_IOCONTROL_MODEM_B_BIT       (1 << 2) /* Enable GPIO[3:0] as modem B pins */
+ #define SC16IS7XX_IOCONTROL_SRESET_BIT        (1 << 3) /* Software Reset */
+ /* EFCR register bits */
+@@ -301,12 +302,12 @@
+ /* Misc definitions */
+ #define SC16IS7XX_FIFO_SIZE           (64)
+ #define SC16IS7XX_REG_SHIFT           2
++#define SC16IS7XX_GPIOS_PER_BANK      4
+ struct sc16is7xx_devtype {
+       char    name[10];
+       int     nr_gpio;
+       int     nr_uart;
+-      int     has_mctrl;
+ };
+ #define SC16IS7XX_RECONF_MD           (1 << 0)
+@@ -336,7 +337,9 @@ struct sc16is7xx_port {
+       struct clk                      *clk;
+ #ifdef CONFIG_GPIOLIB
+       struct gpio_chip                gpio;
++      unsigned long                   gpio_valid_mask;
+ #endif
++      u8                              mctrl_mask;
+       unsigned char                   buf[SC16IS7XX_FIFO_SIZE];
+       struct kthread_worker           kworker;
+       struct task_struct              *kworker_task;
+@@ -447,35 +450,30 @@ static const struct sc16is7xx_devtype sc16is74x_devtype = {
+       .name           = "SC16IS74X",
+       .nr_gpio        = 0,
+       .nr_uart        = 1,
+-      .has_mctrl      = 0,
+ };
+ static const struct sc16is7xx_devtype sc16is750_devtype = {
+       .name           = "SC16IS750",
+-      .nr_gpio        = 4,
++      .nr_gpio        = 8,
+       .nr_uart        = 1,
+-      .has_mctrl      = 1,
+ };
+ static const struct sc16is7xx_devtype sc16is752_devtype = {
+       .name           = "SC16IS752",
+-      .nr_gpio        = 0,
++      .nr_gpio        = 8,
+       .nr_uart        = 2,
+-      .has_mctrl      = 1,
+ };
+ static const struct sc16is7xx_devtype sc16is760_devtype = {
+       .name           = "SC16IS760",
+-      .nr_gpio        = 4,
++      .nr_gpio        = 8,
+       .nr_uart        = 1,
+-      .has_mctrl      = 1,
+ };
+ static const struct sc16is7xx_devtype sc16is762_devtype = {
+       .name           = "SC16IS762",
+-      .nr_gpio        = 0,
++      .nr_gpio        = 8,
+       .nr_uart        = 2,
+-      .has_mctrl      = 1,
+ };
+ static bool sc16is7xx_regmap_volatile(struct device *dev, unsigned int reg)
+@@ -1360,8 +1358,98 @@ static int sc16is7xx_gpio_direction_output(struct gpio_chip *chip,
+       return 0;
+ }
++
++static int sc16is7xx_gpio_init_valid_mask(struct gpio_chip *chip,
++                                        unsigned long *valid_mask,
++                                        unsigned int ngpios)
++{
++      struct sc16is7xx_port *s = gpiochip_get_data(chip);
++
++      *valid_mask = s->gpio_valid_mask;
++
++      return 0;
++}
++
++static int sc16is7xx_setup_gpio_chip(struct sc16is7xx_port *s)
++{
++      struct device *dev = s->p[0].port.dev;
++
++      if (!s->devtype->nr_gpio)
++              return 0;
++
++      switch (s->mctrl_mask) {
++      case 0:
++              s->gpio_valid_mask = GENMASK(7, 0);
++              break;
++      case SC16IS7XX_IOCONTROL_MODEM_A_BIT:
++              s->gpio_valid_mask = GENMASK(3, 0);
++              break;
++      case SC16IS7XX_IOCONTROL_MODEM_B_BIT:
++              s->gpio_valid_mask = GENMASK(7, 4);
++              break;
++      default:
++              break;
++      }
++
++      if (s->gpio_valid_mask == 0)
++              return 0;
++
++      s->gpio.owner            = THIS_MODULE;
++      s->gpio.parent           = dev;
++      s->gpio.label            = dev_name(dev);
++      s->gpio.init_valid_mask  = sc16is7xx_gpio_init_valid_mask;
++      s->gpio.direction_input  = sc16is7xx_gpio_direction_input;
++      s->gpio.get              = sc16is7xx_gpio_get;
++      s->gpio.direction_output = sc16is7xx_gpio_direction_output;
++      s->gpio.set              = sc16is7xx_gpio_set;
++      s->gpio.base             = -1;
++      s->gpio.ngpio            = s->devtype->nr_gpio;
++      s->gpio.can_sleep        = 1;
++
++      return gpiochip_add_data(&s->gpio, s);
++}
+ #endif
++/*
++ * Configure ports designated to operate as modem control lines.
++ */
++static int sc16is7xx_setup_mctrl_ports(struct sc16is7xx_port *s)
++{
++      int i;
++      int ret;
++      int count;
++      u32 mctrl_port[2];
++      struct device *dev = s->p[0].port.dev;
++
++      count = device_property_count_u32(dev, "nxp,modem-control-line-ports");
++      if (count < 0 || count > ARRAY_SIZE(mctrl_port))
++              return 0;
++
++      ret = device_property_read_u32_array(dev, "nxp,modem-control-line-ports",
++                                           mctrl_port, count);
++      if (ret)
++              return ret;
++
++      s->mctrl_mask = 0;
++
++      for (i = 0; i < count; i++) {
++              /* Use GPIO lines as modem control lines */
++              if (mctrl_port[i] == 0)
++                      s->mctrl_mask |= SC16IS7XX_IOCONTROL_MODEM_A_BIT;
++              else if (mctrl_port[i] == 1)
++                      s->mctrl_mask |= SC16IS7XX_IOCONTROL_MODEM_B_BIT;
++      }
++
++      if (s->mctrl_mask)
++              regmap_update_bits(
++                      s->regmap,
++                      SC16IS7XX_IOCONTROL_REG << SC16IS7XX_REG_SHIFT,
++                      SC16IS7XX_IOCONTROL_MODEM_A_BIT |
++                      SC16IS7XX_IOCONTROL_MODEM_B_BIT, s->mctrl_mask);
++
++      return 0;
++}
++
+ static const struct serial_rs485 sc16is7xx_rs485_supported = {
+       .flags = SER_RS485_ENABLED | SER_RS485_RTS_AFTER_SEND,
+       .delay_rts_before_send = 1,
+@@ -1474,12 +1562,6 @@ static int sc16is7xx_probe(struct device *dev,
+                                    SC16IS7XX_EFCR_RXDISABLE_BIT |
+                                    SC16IS7XX_EFCR_TXDISABLE_BIT);
+-              /* Use GPIO lines as modem status registers */
+-              if (devtype->has_mctrl)
+-                      sc16is7xx_port_write(&s->p[i].port,
+-                                           SC16IS7XX_IOCONTROL_REG,
+-                                           SC16IS7XX_IOCONTROL_MODEM_BIT);
+-
+               /* Initialize kthread work structs */
+               kthread_init_work(&s->p[i].tx_work, sc16is7xx_tx_proc);
+               kthread_init_work(&s->p[i].reg_work, sc16is7xx_reg_proc);
+@@ -1517,23 +1599,14 @@ static int sc16is7xx_probe(struct device *dev,
+                               s->p[u].irda_mode = true;
+       }
++      ret = sc16is7xx_setup_mctrl_ports(s);
++      if (ret)
++              goto out_ports;
++
+ #ifdef CONFIG_GPIOLIB
+-      if (devtype->nr_gpio) {
+-              /* Setup GPIO cotroller */
+-              s->gpio.owner            = THIS_MODULE;
+-              s->gpio.parent           = dev;
+-              s->gpio.label            = dev_name(dev);
+-              s->gpio.direction_input  = sc16is7xx_gpio_direction_input;
+-              s->gpio.get              = sc16is7xx_gpio_get;
+-              s->gpio.direction_output = sc16is7xx_gpio_direction_output;
+-              s->gpio.set              = sc16is7xx_gpio_set;
+-              s->gpio.base             = -1;
+-              s->gpio.ngpio            = devtype->nr_gpio;
+-              s->gpio.can_sleep        = 1;
+-              ret = gpiochip_add_data(&s->gpio, s);
+-              if (ret)
+-                      goto out_ports;
+-      }
++      ret = sc16is7xx_setup_gpio_chip(s);
++      if (ret)
++              goto out_ports;
+ #endif
+       /*
+@@ -1556,7 +1629,7 @@ static int sc16is7xx_probe(struct device *dev,
+               return 0;
+ #ifdef CONFIG_GPIOLIB
+-      if (devtype->nr_gpio)
++      if (s->gpio_valid_mask)
+               gpiochip_remove(&s->gpio);
+ #endif
+@@ -1580,7 +1653,7 @@ static void sc16is7xx_remove(struct device *dev)
+       int i;
+ #ifdef CONFIG_GPIOLIB
+-      if (s->devtype->nr_gpio)
++      if (s->gpio_valid_mask)
+               gpiochip_remove(&s->gpio);
+ #endif
+-- 
+2.40.1
+
diff --git a/queue-6.1/serial-sc16is7xx-remove-obsolete-out_thread-label.patch b/queue-6.1/serial-sc16is7xx-remove-obsolete-out_thread-label.patch
new file mode 100644 (file)
index 0000000..2c264c6
--- /dev/null
@@ -0,0 +1,57 @@
+From eceb02f48cb689761cdee323722e1f748c9f37e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Aug 2023 17:45:52 -0400
+Subject: serial: sc16is7xx: remove obsolete out_thread label
+
+From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+
+[ Upstream commit dabc54a45711fe77674a6c0348231e00e66bd567 ]
+
+Commit c8f71b49ee4d ("serial: sc16is7xx: setup GPIO controller later
+in probe") moved GPIO setup code later in probe function. Doing so
+also required to move ports cleanup code (out_ports label) after the
+GPIO cleanup code.
+
+After these moves, the out_thread label becomes misplaced and makes
+part of the cleanup code illogical.
+
+This patch remove the now obsolete out_thread label and make GPIO
+setup code jump to out_ports label if it fails.
+
+Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+Reviewed-by: Lech Perczak <lech.perczak@camlingroup.com>
+Tested-by: Lech Perczak <lech.perczak@camlingroup.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Link: https://lore.kernel.org/r/20230807214556.540627-3-hugo@hugovil.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 049994292834 ("serial: sc16is7xx: fix regression with GPIO configuration")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/sc16is7xx.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
+index 8411a0f312db0..c481c84019f4a 100644
+--- a/drivers/tty/serial/sc16is7xx.c
++++ b/drivers/tty/serial/sc16is7xx.c
+@@ -1532,7 +1532,7 @@ static int sc16is7xx_probe(struct device *dev,
+               s->gpio.can_sleep        = 1;
+               ret = gpiochip_add_data(&s->gpio, s);
+               if (ret)
+-                      goto out_thread;
++                      goto out_ports;
+       }
+ #endif
+@@ -1558,8 +1558,6 @@ static int sc16is7xx_probe(struct device *dev,
+ #ifdef CONFIG_GPIOLIB
+       if (devtype->nr_gpio)
+               gpiochip_remove(&s->gpio);
+-
+-out_thread:
+ #endif
+ out_ports:
+-- 
+2.40.1
+
index eba1b617ab30f4a9638d1b64e35a93694ec1f6e5..e5f1cd443ab9694c216c5b4ffa77b3ece6ec7427 100644 (file)
@@ -583,3 +583,5 @@ usb-typec-bus-verify-partner-exists-in-typec_altmode_attention.patch
 usb-core-unite-old-scheme-and-new-scheme-descriptor-reads.patch
 usb-core-change-usb_get_device_descriptor-api.patch
 usb-core-fix-race-by-not-overwriting-udev-descriptor-in-hub_port_init.patch
+serial-sc16is7xx-remove-obsolete-out_thread-label.patch
+serial-sc16is7xx-fix-regression-with-gpio-configurat.patch