From: Sasha Levin Date: Sun, 10 Sep 2023 14:39:23 +0000 (-0400) Subject: Fixes for 6.1 X-Git-Tag: v6.1.53~39 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=de8a1dd3c3075fbf42dffdf2dba4dcc02240ee43;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.1 Signed-off-by: Sasha Levin --- 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 index 00000000000..53807c73f0f --- /dev/null +++ b/queue-6.1/serial-sc16is7xx-fix-regression-with-gpio-configurat.patch @@ -0,0 +1,287 @@ +From b9bf3cbfbc48c29b0b82590222a25e12f999e39d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Aug 2023 17:45:54 -0400 +Subject: serial: sc16is7xx: fix regression with GPIO configuration + +From: Hugo Villeneuve + +[ 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 +Reviewed-by: Andy Shevchenko +Reviewed-by: Lech Perczak +Tested-by: Lech Perczak +Acked-by: Rob Herring +Link: https://lore.kernel.org/r/20230807214556.540627-5-hugo@hugovil.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..2c264c6f7a2 --- /dev/null +++ b/queue-6.1/serial-sc16is7xx-remove-obsolete-out_thread-label.patch @@ -0,0 +1,57 @@ +From eceb02f48cb689761cdee323722e1f748c9f37e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Aug 2023 17:45:52 -0400 +Subject: serial: sc16is7xx: remove obsolete out_thread label + +From: Hugo Villeneuve + +[ 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 +Reviewed-by: Lech Perczak +Tested-by: Lech Perczak +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20230807214556.540627-3-hugo@hugovil.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 049994292834 ("serial: sc16is7xx: fix regression with GPIO configuration") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/series b/queue-6.1/series index eba1b617ab3..e5f1cd443ab 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -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