From d93e612d13baabe76a8f414aa5dfc5726d4845da Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:10:33 +0200 Subject: serial: tegra: fix typos in comments Spelling mistakes (triple letters) in comments. Detected with the help of Coccinelle. Signed-off-by: Julia Lawall Link: https://lore.kernel.org/r/20220521111145.81697-23-Julia.Lawall@inria.fr Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial-tegra.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c index d942ab152f5a..101fb585e6f9 100644 --- a/drivers/tty/serial/serial-tegra.c +++ b/drivers/tty/serial/serial-tegra.c @@ -441,7 +441,7 @@ static char tegra_uart_decode_rx_error(struct tegra_uart_port *tup, if (unlikely(lsr & TEGRA_UART_LSR_ANY)) { if (lsr & UART_LSR_OE) { - /* Overrrun error */ + /* Overrun error */ flag = TTY_OVERRUN; tup->uport.icount.overrun++; dev_dbg(tup->uport.dev, "Got overrun errors\n"); @@ -1080,7 +1080,7 @@ static int tegra_uart_hw_init(struct tegra_uart_port *tup) tup->rx_in_progress = 1; /* - * Enable IE_RXS for the receive status interrupts like line errros. + * Enable IE_RXS for the receive status interrupts like line errors. * Enable IE_RX_TIMEOUT to get the bytes which cannot be DMA'd. * * EORD is different interrupt than RX_TIMEOUT - RX_TIMEOUT occurs when -- cgit v1.2.3 From 6f3cdf2bf1ba9b70de6c2921a415951a0d59873b Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Wed, 25 May 2022 10:12:04 +0800 Subject: serial: pic32: fix missing clk_disable_unprepare() on error in pic32_uart_startup() Fix the missing clk_disable_unprepare() before return from pic32_uart_startup() in the error handling case. Fixes: 157b9394709e ("serial: pic32_uart: Add PIC32 UART driver") Reported-by: Hulk Robot Reviewed-by: Jiri Slaby Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20220525021204.2407631-1-yangyingliang@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pic32_uart.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/pic32_uart.c b/drivers/tty/serial/pic32_uart.c index b399aac530fe..f418f1de66b3 100644 --- a/drivers/tty/serial/pic32_uart.c +++ b/drivers/tty/serial/pic32_uart.c @@ -503,7 +503,7 @@ static int pic32_uart_startup(struct uart_port *port) if (!sport->irq_fault_name) { dev_err(port->dev, "%s: kasprintf err!", __func__); ret = -ENOMEM; - goto out_done; + goto out_disable_clk; } irq_set_status_flags(sport->irq_fault, IRQ_NOAUTOEN); ret = request_irq(sport->irq_fault, pic32_uart_fault_interrupt, @@ -579,6 +579,8 @@ out_r: out_f: free_irq(sport->irq_fault, port); kfree(sport->irq_fault_name); +out_disable_clk: + clk_disable_unprepare(sport->clk); out_done: return ret; } -- cgit v1.2.3 From 7fd6c24bae8fff0c12c61bc69388d9f3c045ce21 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 2 Jun 2022 10:31:20 +0200 Subject: serial: pmac_zilog: remove unused header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After commit a5ddc498e792 (serial: pmac_zilog: remove unfinished DBDMA support), the header is unused and can be removed. So do so. Cc: Michael Ellerman Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Suggested-by: "Ilpo Järvinen" Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20220602083120.22519-1-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pmac_zilog.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index 3133446e806c..f63257b8e872 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -52,7 +52,6 @@ #ifdef CONFIG_PPC_PMAC #include #include -#include #include #else #include -- cgit v1.2.3 From 285e76fc049c4d32c772eea9460a7ef28a193802 Mon Sep 17 00:00:00 2001 From: Cosmin Tanislav Date: Sun, 5 Jun 2022 17:46:56 +0300 Subject: serial: max310x: use regmap methods for SPI batch operations The SPI batch read/write operations can be implemented as simple regmap raw read and write, which will also try to do a gather write just as it is done here. Use the regmap raw read and write methods. Reviewed-by: Andy Shevchenko Signed-off-by: Cosmin Tanislav Link: https://lore.kernel.org/r/20220605144659.4169853-2-demonsingur@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/max310x.c | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index a0b6ea52d133..46887a4ffea4 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -259,8 +259,6 @@ struct max310x_one { struct work_struct md_work; struct work_struct rs_work; - u8 wr_header; - u8 rd_header; u8 rx_buf[MAX310X_FIFO_SIZE]; }; #define to_max310x_port(_port) \ @@ -623,32 +621,18 @@ static u32 max310x_set_ref_clk(struct device *dev, struct max310x_port *s, static void max310x_batch_write(struct uart_port *port, u8 *txbuf, unsigned int len) { - struct max310x_one *one = to_max310x_port(port); - struct spi_transfer xfer[] = { - { - .tx_buf = &one->wr_header, - .len = sizeof(one->wr_header), - }, { - .tx_buf = txbuf, - .len = len, - } - }; - spi_sync_transfer(to_spi_device(port->dev), xfer, ARRAY_SIZE(xfer)); + struct max310x_port *s = dev_get_drvdata(port->dev); + u8 reg = port->iobase + MAX310X_THR_REG; + + regmap_raw_write(s->regmap, reg, txbuf, len); } static void max310x_batch_read(struct uart_port *port, u8 *rxbuf, unsigned int len) { - struct max310x_one *one = to_max310x_port(port); - struct spi_transfer xfer[] = { - { - .tx_buf = &one->rd_header, - .len = sizeof(one->rd_header), - }, { - .rx_buf = rxbuf, - .len = len, - } - }; - spi_sync_transfer(to_spi_device(port->dev), xfer, ARRAY_SIZE(xfer)); + struct max310x_port *s = dev_get_drvdata(port->dev); + u8 reg = port->iobase + MAX310X_RHR_REG; + + regmap_raw_read(s->regmap, reg, rxbuf, len); } static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen) @@ -1368,10 +1352,6 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty INIT_WORK(&s->p[i].md_work, max310x_md_proc); /* Initialize queue for changing RS485 mode */ INIT_WORK(&s->p[i].rs_work, max310x_rs_proc); - /* Initialize SPI-transfer buffers */ - s->p[i].wr_header = (s->p[i].port.iobase + MAX310X_THR_REG) | - MAX310X_WRITE_BIT; - s->p[i].rd_header = (s->p[i].port.iobase + MAX310X_RHR_REG); /* Register port */ ret = uart_add_one_port(&max310x_uart, &s->p[i].port); -- cgit v1.2.3 From 6ef281daf020592c219fa91780abc381c6c20db5 Mon Sep 17 00:00:00 2001 From: Cosmin Tanislav Date: Sun, 5 Jun 2022 17:46:57 +0300 Subject: serial: max310x: use a separate regmap for each port The driver currently does manual register manipulation in multiple places to talk to a specific UART port. In order to talk to a specific UART port over SPI, the bits U1 and U0 of the register address can be set, as explained in the Command byte configuration section of the datasheet. Make this more elegant by creating regmaps for each UART port and setting the read_flag_mask and write_flag_mask accordingly. All communcations regarding global registers are done on UART port 0, so replace the global regmap entirely with the port 0 regmap. Also, remove the 0x1f masks from reg_writeable(), reg_volatile() and reg_precious() methods, since setting the U1 and U0 bits of the register address happens inside the regmap core now. Reviewed-by: Andy Shevchenko Signed-off-by: Cosmin Tanislav Link: https://lore.kernel.org/r/20220605144659.4169853-3-demonsingur@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/max310x.c | 68 +++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 32 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 46887a4ffea4..6fd133c177a3 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -258,6 +258,7 @@ struct max310x_one { struct work_struct tx_work; struct work_struct md_work; struct work_struct rs_work; + struct regmap *regmap; u8 rx_buf[MAX310X_FIFO_SIZE]; }; @@ -287,26 +288,26 @@ static DECLARE_BITMAP(max310x_lines, MAX310X_UART_NRMAX); static u8 max310x_port_read(struct uart_port *port, u8 reg) { - struct max310x_port *s = dev_get_drvdata(port->dev); + struct max310x_one *one = to_max310x_port(port); unsigned int val = 0; - regmap_read(s->regmap, port->iobase + reg, &val); + regmap_read(one->regmap, reg, &val); return val; } static void max310x_port_write(struct uart_port *port, u8 reg, u8 val) { - struct max310x_port *s = dev_get_drvdata(port->dev); + struct max310x_one *one = to_max310x_port(port); - regmap_write(s->regmap, port->iobase + reg, val); + regmap_write(one->regmap, reg, val); } static void max310x_port_update(struct uart_port *port, u8 reg, u8 mask, u8 val) { - struct max310x_port *s = dev_get_drvdata(port->dev); + struct max310x_one *one = to_max310x_port(port); - regmap_update_bits(s->regmap, port->iobase + reg, mask, val); + regmap_update_bits(one->regmap, reg, mask, val); } static int max3107_detect(struct device *dev) @@ -445,7 +446,7 @@ static const struct max310x_devtype max14830_devtype = { static bool max310x_reg_writeable(struct device *dev, unsigned int reg) { - switch (reg & 0x1f) { + switch (reg) { case MAX310X_IRQSTS_REG: case MAX310X_LSR_IRQSTS_REG: case MAX310X_SPCHR_IRQSTS_REG: @@ -462,7 +463,7 @@ static bool max310x_reg_writeable(struct device *dev, unsigned int reg) static bool max310x_reg_volatile(struct device *dev, unsigned int reg) { - switch (reg & 0x1f) { + switch (reg) { case MAX310X_RHR_REG: case MAX310X_IRQSTS_REG: case MAX310X_LSR_IRQSTS_REG: @@ -484,7 +485,7 @@ static bool max310x_reg_volatile(struct device *dev, unsigned int reg) static bool max310x_reg_precious(struct device *dev, unsigned int reg) { - switch (reg & 0x1f) { + switch (reg) { case MAX310X_RHR_REG: case MAX310X_IRQSTS_REG: case MAX310X_SPCHR_IRQSTS_REG: @@ -621,18 +622,16 @@ static u32 max310x_set_ref_clk(struct device *dev, struct max310x_port *s, static void max310x_batch_write(struct uart_port *port, u8 *txbuf, unsigned int len) { - struct max310x_port *s = dev_get_drvdata(port->dev); - u8 reg = port->iobase + MAX310X_THR_REG; + struct max310x_one *one = to_max310x_port(port); - regmap_raw_write(s->regmap, reg, txbuf, len); + regmap_raw_write(one->regmap, MAX310X_THR_REG, txbuf, len); } static void max310x_batch_read(struct uart_port *port, u8 *rxbuf, unsigned int len) { - struct max310x_port *s = dev_get_drvdata(port->dev); - u8 reg = port->iobase + MAX310X_RHR_REG; + struct max310x_one *one = to_max310x_port(port); - regmap_raw_read(s->regmap, reg, rxbuf, len); + regmap_raw_read(one->regmap, MAX310X_RHR_REG, rxbuf, len); } static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen) @@ -1234,15 +1233,16 @@ static int max310x_gpio_set_config(struct gpio_chip *chip, unsigned int offset, #endif static int max310x_probe(struct device *dev, const struct max310x_devtype *devtype, - struct regmap *regmap, int irq) + struct regmap *regmaps[], int irq) { int i, ret, fmin, fmax, freq; struct max310x_port *s; u32 uartclk = 0; bool xtal; - if (IS_ERR(regmap)) - return PTR_ERR(regmap); + for (i = 0; i < devtype->nr; i++) + if (IS_ERR(regmaps[i])) + return PTR_ERR(regmaps[i]); /* Alloc port structure */ s = devm_kzalloc(dev, struct_size(s, p, devtype->nr), GFP_KERNEL); @@ -1289,7 +1289,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty goto out_clk; } - s->regmap = regmap; + s->regmap = regmaps[0]; s->devtype = devtype; dev_set_drvdata(dev, s); @@ -1299,22 +1299,18 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty goto out_clk; for (i = 0; i < devtype->nr; i++) { - unsigned int offs = i << 5; - /* Reset port */ - regmap_write(s->regmap, MAX310X_MODE2_REG + offs, + regmap_write(regmaps[i], MAX310X_MODE2_REG, MAX310X_MODE2_RST_BIT); /* Clear port reset */ - regmap_write(s->regmap, MAX310X_MODE2_REG + offs, 0); + regmap_write(regmaps[i], MAX310X_MODE2_REG, 0); /* Wait for port startup */ do { - regmap_read(s->regmap, - MAX310X_BRGDIVLSB_REG + offs, &ret); + regmap_read(regmaps[i], MAX310X_BRGDIVLSB_REG, &ret); } while (ret != 0x01); - regmap_write(s->regmap, MAX310X_MODE1_REG + offs, - devtype->mode1); + regmap_write(regmaps[i], MAX310X_MODE1_REG, devtype->mode1); } uartclk = max310x_set_ref_clk(dev, s, freq, xtal); @@ -1337,11 +1333,13 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty s->p[i].port.fifosize = MAX310X_FIFO_SIZE; s->p[i].port.flags = UPF_FIXED_TYPE | UPF_LOW_LATENCY; s->p[i].port.iotype = UPIO_PORT; - s->p[i].port.iobase = i * 0x20; + s->p[i].port.iobase = i; s->p[i].port.membase = (void __iomem *)~0; s->p[i].port.uartclk = uartclk; s->p[i].port.rs485_config = max310x_rs485_config; s->p[i].port.ops = &max310x_ops; + s->p[i].regmap = regmaps[i]; + /* Disable all interrupts */ max310x_port_write(&s->p[i].port, MAX310X_IRQEN_REG, 0); /* Clear IRQ status register */ @@ -1436,6 +1434,7 @@ static struct regmap_config regcfg = { .val_bits = 8, .write_flag_mask = MAX310X_WRITE_BIT, .cache_type = REGCACHE_RBTREE, + .max_register = MAX310X_REG_1F, .writeable_reg = max310x_reg_writeable, .volatile_reg = max310x_reg_volatile, .precious_reg = max310x_reg_precious, @@ -1445,7 +1444,8 @@ static struct regmap_config regcfg = { static int max310x_spi_probe(struct spi_device *spi) { const struct max310x_devtype *devtype; - struct regmap *regmap; + struct regmap *regmaps[4]; + unsigned int i; int ret; /* Setup SPI bus */ @@ -1460,10 +1460,14 @@ static int max310x_spi_probe(struct spi_device *spi) if (!devtype) devtype = (struct max310x_devtype *)spi_get_device_id(spi)->driver_data; - regcfg.max_register = devtype->nr * 0x20 - 1; - regmap = devm_regmap_init_spi(spi, ®cfg); + for (i = 0; i < devtype->nr; i++) { + u8 port_mask = i * 0x20; + regcfg.read_flag_mask = port_mask; + regcfg.write_flag_mask = port_mask | MAX310X_WRITE_BIT; + regmaps[i] = devm_regmap_init_spi(spi, ®cfg); + } - return max310x_probe(&spi->dev, devtype, regmap, spi->irq); + return max310x_probe(&spi->dev, devtype, regmaps, spi->irq); } static void max310x_spi_remove(struct spi_device *spi) -- cgit v1.2.3 From b3883ab5e95713e479f774ea68be275413e8e5b2 Mon Sep 17 00:00:00 2001 From: Cosmin Tanislav Date: Sun, 5 Jun 2022 17:46:58 +0300 Subject: serial: max310x: make accessing revision id interface-agnostic SPI can only use 5 address bits, since one bit is reserved for specifying R/W and 2 bits are used to specify the UART port. To access registers that have addresses past 0x1F, an extended register space can be enabled by writing to the GlobalCommand register (address 0x1F). I2C uses 8 address bits. The R/W bit is placed in the slave address, and so is the UART port. Because of this, registers that have addresses higher than 0x1F can be accessed normally. To access the RevID register, on SPI, 0xCE must be written to the 0x1F address to enable the extended register space, after which the RevID register is accessible at address 0x5. 0xCD must be written to the 0x1F address to disable the extended register space. On I2C, the RevID register is accessible at address 0x25. Create an interface config struct, and add a method for toggling the extended register space and a member for the RevId register address. Implement these for SPI. Reviewed-by: Andy Shevchenko Signed-off-by: Cosmin Tanislav Link: https://lore.kernel.org/r/20220605144659.4169853-4-demonsingur@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/max310x.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 6fd133c177a3..ef6b91242524 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -72,7 +72,7 @@ #define MAX310X_GLOBALCMD_REG MAX310X_REG_1F /* Global Command (WO) */ /* Extended registers */ -#define MAX310X_REVID_EXTREG MAX310X_REG_05 /* Revision ID */ +#define MAX310X_SPI_REVID_EXTREG MAX310X_REG_05 /* Revision ID */ /* IRQ register bits */ #define MAX310X_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */ @@ -245,6 +245,12 @@ #define MAX14830_BRGCFG_CLKDIS_BIT (1 << 6) /* Clock Disable */ #define MAX14830_REV_ID (0xb0) +struct max310x_if_cfg { + int (*extended_reg_enable)(struct device *dev, bool enable); + + unsigned int rev_id_reg; +}; + struct max310x_devtype { char name[9]; int nr; @@ -267,6 +273,7 @@ struct max310x_one { struct max310x_port { const struct max310x_devtype *devtype; + const struct max310x_if_cfg *if_cfg; struct regmap *regmap; struct clk *clk; #ifdef CONFIG_GPIOLIB @@ -356,13 +363,12 @@ static int max3109_detect(struct device *dev) unsigned int val = 0; int ret; - ret = regmap_write(s->regmap, MAX310X_GLOBALCMD_REG, - MAX310X_EXTREG_ENBL); + ret = s->if_cfg->extended_reg_enable(dev, true); if (ret) return ret; - regmap_read(s->regmap, MAX310X_REVID_EXTREG, &val); - regmap_write(s->regmap, MAX310X_GLOBALCMD_REG, MAX310X_EXTREG_DSBL); + regmap_read(s->regmap, s->if_cfg->rev_id_reg, &val); + s->if_cfg->extended_reg_enable(dev, false); if (((val & MAX310x_REV_MASK) != MAX3109_REV_ID)) { dev_err(dev, "%s ID 0x%02x does not match\n", s->devtype->name, val); @@ -387,13 +393,12 @@ static int max14830_detect(struct device *dev) unsigned int val = 0; int ret; - ret = regmap_write(s->regmap, MAX310X_GLOBALCMD_REG, - MAX310X_EXTREG_ENBL); + ret = s->if_cfg->extended_reg_enable(dev, true); if (ret) return ret; - regmap_read(s->regmap, MAX310X_REVID_EXTREG, &val); - regmap_write(s->regmap, MAX310X_GLOBALCMD_REG, MAX310X_EXTREG_DSBL); + regmap_read(s->regmap, s->if_cfg->rev_id_reg, &val); + s->if_cfg->extended_reg_enable(dev, false); if (((val & MAX310x_REV_MASK) != MAX14830_REV_ID)) { dev_err(dev, "%s ID 0x%02x does not match\n", s->devtype->name, val); @@ -1233,6 +1238,7 @@ static int max310x_gpio_set_config(struct gpio_chip *chip, unsigned int offset, #endif static int max310x_probe(struct device *dev, const struct max310x_devtype *devtype, + const struct max310x_if_cfg *if_cfg, struct regmap *regmaps[], int irq) { int i, ret, fmin, fmax, freq; @@ -1291,6 +1297,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty s->regmap = regmaps[0]; s->devtype = devtype; + s->if_cfg = if_cfg; dev_set_drvdata(dev, s); /* Check device to ensure we are talking to what we expect */ @@ -1441,6 +1448,19 @@ static struct regmap_config regcfg = { }; #ifdef CONFIG_SPI_MASTER +static int max310x_spi_extended_reg_enable(struct device *dev, bool enable) +{ + struct max310x_port *s = dev_get_drvdata(dev); + + return regmap_write(s->regmap, MAX310X_GLOBALCMD_REG, + enable ? MAX310X_EXTREG_ENBL : MAX310X_EXTREG_DSBL); +} + +static const struct max310x_if_cfg __maybe_unused max310x_spi_if_cfg = { + .extended_reg_enable = max310x_spi_extended_reg_enable, + .rev_id_reg = MAX310X_SPI_REVID_EXTREG, +}; + static int max310x_spi_probe(struct spi_device *spi) { const struct max310x_devtype *devtype; @@ -1467,7 +1487,7 @@ static int max310x_spi_probe(struct spi_device *spi) regmaps[i] = devm_regmap_init_spi(spi, ®cfg); } - return max310x_probe(&spi->dev, devtype, regmaps, spi->irq); + return max310x_probe(&spi->dev, devtype, &max310x_spi_if_cfg, regmaps, spi->irq); } static void max310x_spi_remove(struct spi_device *spi) -- cgit v1.2.3 From 2e1f2d9a9bdbe12ee475c82a45ac46a278e8049a Mon Sep 17 00:00:00 2001 From: Cosmin Tanislav Date: Sun, 5 Jun 2022 17:46:59 +0300 Subject: serial: max310x: implement I2C support I2C implementation on this chip has a few key differences compared to SPI, as described in previous patches. * extended register space access needs no extra logic * slave address is used to select which UART to communicate with To accommodate these differences, add an I2C interface config, set the RevID register address and implement an empty method for setting the GlobalCommand register, since no special handling is needed for the extended register space. To handle the port-specific slave address, create an I2C dummy device for each port, except the base one (UART0), which is expected to be the one specified in firmware, and create a regmap for each I2C device. Add minimum and maximum slave addresses to each devtype for sanity checking. Also, use a separate regmap config with no write_flag_mask, since I2C has a R/W bit in its slave address, and set the max register to the address of the RevID register, since the extended register space needs no extra logic. Finally, add the I2C driver. Reviewed-by: Andy Shevchenko Signed-off-by: Cosmin Tanislav Link: https://lore.kernel.org/r/20220605144659.4169853-5-demonsingur@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 1 + drivers/tty/serial/max310x.c | 135 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 135 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index a452748c69b2..8a3ee1525d80 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -324,6 +324,7 @@ config SERIAL_MAX310X depends on SPI_MASTER select SERIAL_CORE select REGMAP_SPI if SPI_MASTER + select REGMAP_I2C if I2C help This selects support for an advanced UART from Maxim (Dallas). Supported ICs are MAX3107, MAX3108, MAX3109, MAX14830. diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index ef6b91242524..0f7c5908fee0 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -73,6 +74,7 @@ /* Extended registers */ #define MAX310X_SPI_REVID_EXTREG MAX310X_REG_05 /* Revision ID */ +#define MAX310X_I2C_REVID_EXTREG (0x25) /* Revision ID */ /* IRQ register bits */ #define MAX310X_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */ @@ -252,6 +254,10 @@ struct max310x_if_cfg { }; struct max310x_devtype { + struct { + unsigned short min; + unsigned short max; + } slave_addr; char name[9]; int nr; u8 mode1; @@ -423,6 +429,10 @@ static const struct max310x_devtype max3107_devtype = { .mode1 = MAX310X_MODE1_AUTOSLEEP_BIT | MAX310X_MODE1_IRQSEL_BIT, .detect = max3107_detect, .power = max310x_power, + .slave_addr = { + .min = 0x2c, + .max = 0x2f, + }, }; static const struct max310x_devtype max3108_devtype = { @@ -431,6 +441,10 @@ static const struct max310x_devtype max3108_devtype = { .mode1 = MAX310X_MODE1_AUTOSLEEP_BIT, .detect = max3108_detect, .power = max310x_power, + .slave_addr = { + .min = 0x60, + .max = 0x6f, + }, }; static const struct max310x_devtype max3109_devtype = { @@ -439,6 +453,10 @@ static const struct max310x_devtype max3109_devtype = { .mode1 = MAX310X_MODE1_AUTOSLEEP_BIT, .detect = max3109_detect, .power = max310x_power, + .slave_addr = { + .min = 0x60, + .max = 0x6f, + }, }; static const struct max310x_devtype max14830_devtype = { @@ -447,6 +465,10 @@ static const struct max310x_devtype max14830_devtype = { .mode1 = MAX310X_MODE1_IRQSEL_BIT, .detect = max14830_detect, .power = max14830_power, + .slave_addr = { + .min = 0x60, + .max = 0x6f, + }, }; static bool max310x_reg_writeable(struct device *dev, unsigned int reg) @@ -1516,6 +1538,97 @@ static struct spi_driver max310x_spi_driver = { }; #endif +#ifdef CONFIG_I2C +static int max310x_i2c_extended_reg_enable(struct device *dev, bool enable) +{ + return 0; +} + +static struct regmap_config regcfg_i2c = { + .reg_bits = 8, + .val_bits = 8, + .cache_type = REGCACHE_RBTREE, + .writeable_reg = max310x_reg_writeable, + .volatile_reg = max310x_reg_volatile, + .precious_reg = max310x_reg_precious, + .max_register = MAX310X_I2C_REVID_EXTREG, +}; + +static const struct max310x_if_cfg max310x_i2c_if_cfg = { + .extended_reg_enable = max310x_i2c_extended_reg_enable, + .rev_id_reg = MAX310X_I2C_REVID_EXTREG, +}; + +static unsigned short max310x_i2c_slave_addr(unsigned short addr, + unsigned int nr) +{ + /* + * For MAX14830 and MAX3109, the slave address depends on what the + * A0 and A1 pins are tied to. + * See Table I2C Address Map of the datasheet. + * Based on that table, the following formulas were determined. + * UART1 - UART0 = 0x10 + * UART2 - UART1 = 0x20 + 0x10 + * UART3 - UART2 = 0x10 + */ + + addr -= nr * 0x10; + + if (nr >= 2) + addr -= 0x20; + + return addr; +} + +static int max310x_i2c_probe(struct i2c_client *client) +{ + const struct max310x_devtype *devtype = + device_get_match_data(&client->dev); + struct i2c_client *port_client; + struct regmap *regmaps[4]; + unsigned int i; + u8 port_addr; + + if (client->addr < devtype->slave_addr.min || + client->addr > devtype->slave_addr.max) + return dev_err_probe(&client->dev, -EINVAL, + "Slave addr 0x%x outside of range [0x%x, 0x%x]\n", + client->addr, devtype->slave_addr.min, + devtype->slave_addr.max); + + regmaps[0] = devm_regmap_init_i2c(client, ®cfg_i2c); + + for (i = 1; i < devtype->nr; i++) { + port_addr = max310x_i2c_slave_addr(client->addr, i); + port_client = devm_i2c_new_dummy_device(&client->dev, + client->adapter, + port_addr); + + regmaps[i] = devm_regmap_init_i2c(port_client, ®cfg_i2c); + } + + return max310x_probe(&client->dev, devtype, &max310x_i2c_if_cfg, + regmaps, client->irq); +} + +static int max310x_i2c_remove(struct i2c_client *client) +{ + max310x_remove(&client->dev); + + return 0; +} + +static struct i2c_driver max310x_i2c_driver = { + .driver = { + .name = MAX310X_NAME, + .of_match_table = max310x_dt_ids, + .pm = &max310x_pm_ops, + }, + .probe_new = max310x_i2c_probe, + .remove = max310x_i2c_remove, +}; +#endif + static int __init max310x_uart_init(void) { int ret; @@ -1529,15 +1642,35 @@ static int __init max310x_uart_init(void) #ifdef CONFIG_SPI_MASTER ret = spi_register_driver(&max310x_spi_driver); if (ret) - uart_unregister_driver(&max310x_uart); + goto err_spi_register; +#endif + +#ifdef CONFIG_I2C + ret = i2c_add_driver(&max310x_i2c_driver); + if (ret) + goto err_i2c_register; #endif + return 0; + +#ifdef CONFIG_I2C +err_i2c_register: + spi_unregister_driver(&max310x_spi_driver); +#endif + +err_spi_register: + uart_unregister_driver(&max310x_uart); + return ret; } module_init(max310x_uart_init); static void __exit max310x_uart_exit(void) { +#ifdef CONFIG_I2C + i2c_del_driver(&max310x_i2c_driver); +#endif + #ifdef CONFIG_SPI_MASTER spi_unregister_driver(&max310x_spi_driver); #endif -- cgit v1.2.3 From 767cc6681b1b17f4cbba0b8b37bf6dbb1322c9ac Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Tue, 7 Jun 2022 11:41:53 +0300 Subject: serial: 8250: kill __do_stop_tx() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There seems to be little reason for __do_stop_tx() to exits on its own. It is rather simple and is only called from __stop_tx(). Thus, move its logic into __stop_tx(). Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220607084154.8172-1-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 78b6dedc43e6..448cfbb05f63 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1503,12 +1503,6 @@ static void __stop_tx_rs485(struct uart_8250_port *p, u64 stop_delay) } } -static inline void __do_stop_tx(struct uart_8250_port *p) -{ - if (serial8250_clear_THRI(p)) - serial8250_rpm_put_tx(p); -} - static inline void __stop_tx(struct uart_8250_port *p) { struct uart_8250_em485 *em485 = p->em485; @@ -1542,7 +1536,9 @@ static inline void __stop_tx(struct uart_8250_port *p) __stop_tx_rs485(p, stop_delay); } - __do_stop_tx(p); + + if (serial8250_clear_THRI(p)) + serial8250_rpm_put_tx(p); } static void serial8250_stop_tx(struct uart_port *port) -- cgit v1.2.3 From 90574a5b5a048af7c8c1de8977da498f1e2bdce9 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Tue, 7 Jun 2022 11:41:54 +0300 Subject: serial: 8250: handle __start_tx() call in start_tx() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As either start_tx_rs485() or start_tx() calls __start_tx() as the last line of their logic, it makes sense to just move that call into start_tx(). When start_tx_rs485() wants to defer tx using timer, return false so start_tx() can return based on it. Reorganize em485 code in serial8250_start_tx() so that the return can be shared for the cases where tx start is deferred. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220607084154.8172-2-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 448cfbb05f63..a3ffbdfe8fae 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1610,7 +1610,8 @@ void serial8250_em485_start_tx(struct uart_8250_port *up) } EXPORT_SYMBOL_GPL(serial8250_em485_start_tx); -static inline void start_tx_rs485(struct uart_port *port) +/* Returns false, if start_tx_timer was setup to defer TX start */ +static bool start_tx_rs485(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); struct uart_8250_em485 *em485 = up->em485; @@ -1638,11 +1639,11 @@ static inline void start_tx_rs485(struct uart_port *port) em485->active_timer = &em485->start_tx_timer; start_hrtimer_ms(&em485->start_tx_timer, up->port.rs485.delay_rts_before_send); - return; + return false; } } - __start_tx(port); + return true; } static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t) @@ -1672,14 +1673,12 @@ static void serial8250_start_tx(struct uart_port *port) serial8250_rpm_get_tx(up); - if (em485 && - em485->active_timer == &em485->start_tx_timer) - return; - - if (em485) - start_tx_rs485(port); - else - __start_tx(port); + if (em485) { + if ((em485->active_timer == &em485->start_tx_timer) || + !start_tx_rs485(port)) + return; + } + __start_tx(port); } static void serial8250_throttle(struct uart_port *port) -- cgit v1.2.3 From ce338e4477cfdff0abeb27eff2d43fc379ee9ebb Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Wed, 8 Jun 2022 12:54:26 +0300 Subject: serial: 8250: Store to lsr_save_flags after lsr read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not all LSR register flags are preserved across reads. Therefore, LSR readers must store the non-preserved bits into lsr_save_flags. This fix was initially mixed into feature commit f6f586102add ("serial: 8250: Handle UART without interrupt on TEMT using em485"). However, that feature change had a flaw and it was reverted to make room for simpler approach providing the same feature. The embedded fix got reverted with the feature change. Re-add the lsr_save_flags fix and properly mark it's a fix. Link: https://lore.kernel.org/all/1d6c31d-d194-9e6a-ddf9-5f29af829f3@linux.intel.com/T/#m1737eef986bd20cf19593e344cebd7b0244945fc Fixes: e490c9144cfa ("tty: Add software emulated RS485 support for 8250") Co-developed-by: Uwe Kleine-König Reviewed-by: Andy Shevchenko Signed-off-by: Uwe Kleine-König Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220608095431.18376-2-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index a3ffbdfe8fae..209ecb1f29ed 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1511,6 +1511,8 @@ static inline void __stop_tx(struct uart_8250_port *p) unsigned char lsr = serial_in(p, UART_LSR); u64 stop_delay = 0; + p->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; + if (!(lsr & UART_LSR_THRE)) return; /* -- cgit v1.2.3 From bdb70c424df1543bc02ee2639aecebd20318c599 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Wed, 8 Jun 2022 12:54:27 +0300 Subject: serial: 8250: Create serial_lsr_in() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LSR register readers need to be careful in order to not lose bits that are not preserved across reads. Create a helper that takes care of storing the non-preserved bits into lsr_save_flags. Reviewed-by: Andy Shevchenko Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220608095431.18376-3-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.h | 20 ++++++++++++++++++++ drivers/tty/serial/8250/8250_core.c | 3 +-- drivers/tty/serial/8250/8250_port.c | 15 ++++----------- 3 files changed, 25 insertions(+), 13 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 696030cfcb09..c89cb881d9b0 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -123,6 +123,26 @@ static inline void serial_out(struct uart_8250_port *up, int offset, int value) up->port.serial_out(&up->port, offset, value); } +/** + * serial_lsr_in - Read LSR register and preserve flags across reads + * @up: uart 8250 port + * + * Read LSR register and handle saving non-preserved flags across reads. + * The flags that are not preserved across reads are stored into + * up->lsr_saved_flags. + * + * Returns LSR value or'ed with the preserved flags (if any). + */ +static inline unsigned int serial_lsr_in(struct uart_8250_port *up) +{ + unsigned int lsr = up->lsr_saved_flags; + + lsr |= serial_in(up, UART_LSR); + up->lsr_saved_flags = lsr & LSR_SAVE_FLAGS; + + return lsr; +} + /* * For the 16C950 */ diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index cfbd2de0ca6e..b0320de3379c 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -276,8 +276,7 @@ static void serial8250_backup_timeout(struct timer_list *t) * the "Diva" UART used on the management processor on many HP * ia64 and parisc boxes. */ - lsr = serial_in(up, UART_LSR); - up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; + lsr = serial_lsr_in(up); if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) && (!uart_circ_empty(&up->port.state->xmit) || up->port.x_char) && (lsr & UART_LSR_THRE)) { diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 209ecb1f29ed..5a5e81dd3b74 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1508,11 +1508,9 @@ static inline void __stop_tx(struct uart_8250_port *p) struct uart_8250_em485 *em485 = p->em485; if (em485) { - unsigned char lsr = serial_in(p, UART_LSR); + unsigned char lsr = serial_lsr_in(p); u64 stop_delay = 0; - p->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; - if (!(lsr & UART_LSR_THRE)) return; /* @@ -1569,10 +1567,8 @@ static inline void __start_tx(struct uart_port *port) if (serial8250_set_THRI(up)) { if (up->bugs & UART_BUG_TXEN) { - unsigned char lsr; + unsigned char lsr = serial_lsr_in(up); - lsr = serial_in(up, UART_LSR); - up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; if (lsr & UART_LSR_THRE) serial8250_tx_chars(up); } @@ -2002,8 +1998,7 @@ static unsigned int serial8250_tx_empty(struct uart_port *port) serial8250_rpm_get(up); spin_lock_irqsave(&port->lock, flags); - lsr = serial_port_in(port, UART_LSR); - up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; + lsr = serial_lsr_in(up); spin_unlock_irqrestore(&port->lock, flags); serial8250_rpm_put(up); @@ -2079,9 +2074,7 @@ static void wait_for_lsr(struct uart_8250_port *up, int bits) /* Wait up to 10ms for the character(s) to be sent. */ for (;;) { - status = serial_in(up, UART_LSR); - - up->lsr_saved_flags |= status & LSR_SAVE_FLAGS; + status = serial_lsr_in(up); if ((status & bits) == bits) break; -- cgit v1.2.3 From 6a4241e8f9b17aa17f55842d6478f280c22d2b44 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Wed, 8 Jun 2022 12:54:28 +0300 Subject: serial: 8250: Get preserved flags using serial_lsr_in() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit serial8250_handle_irq() assumes it's the first to read LSR register. However, there are 8250 drivers which perform LSR read in their own irq handler prior to calling serial8250_handle_irq(). As not all flags are preserved across LSR reads, use serial_lsr_in() helper to get all the preserved flags. This commit might fix other commits too besides the ones for DW UART mentioned below. It's just not clear to me which of the other devices clear some of the LSR flags on read. AFAIK, nobody has complained about this problem (either against DW or other devices) so it might not have that bad impact in the end. Fixes: 424d79183af0 ("serial: 8250_dw: Avoid "too much work" from bogus rx timeout interrupt") Fixes: aa63d786cea2 ("serial: 8250: dw: Add support for DMA flow controlling devices") Reviewed-by: Andy Shevchenko Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220608095431.18376-4-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 5a5e81dd3b74..92fb2e39134e 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1917,7 +1917,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) spin_lock_irqsave(&port->lock, flags); - status = serial_port_in(port, UART_LSR); + status = serial_lsr_in(up); /* * If port is stopped and there are no error conditions in the -- cgit v1.2.3 From 7a3525e48cf7c1d85c38cedb452912cb99b60c43 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Wed, 8 Jun 2022 12:54:29 +0300 Subject: serial: 8250: Adjust misleading LSR related comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit serial8250_rx_chars() has max_count based character limit. If it triggers, the function returns the old LSR value (and it has never returned only flags which were not handled). Adjust the comment to match behavior and warn about which flags can be depended on. I'd have moved LSR read before LSR read and used serial_lsr_in() also here but I came across an old discussion about the topic. That discussion generated commit d22f8f10683c ("serial: 8250: Fix lost rx state") so I left the code as it is (it works as long as the callers only use a subset of the LSR flags which holds true today) and changed the comment instead. Link: https://www.spinics.net/lists/linux-serial/msg16220.html Reviewed-by: Andy Shevchenko Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220608095431.18376-5-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 92fb2e39134e..30e0aaf52adc 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1783,9 +1783,11 @@ void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr) EXPORT_SYMBOL_GPL(serial8250_read_char); /* - * serial8250_rx_chars: processes according to the passed in LSR - * value, and returns the remaining LSR bits not handled - * by this Rx routine. + * serial8250_rx_chars - Read characters. The first LSR value must be passed in. + * + * Returns LSR bits. The caller should rely only on non-Rx related LSR bits + * (such as THRE) because the LSR value might come from an already consumed + * character. */ unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) { -- cgit v1.2.3 From 197eb5c416ff0e52d152e6ff59b4e759d2f3e10d Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Wed, 8 Jun 2022 12:54:30 +0300 Subject: serial: 8250_dw: Use serial_lsr_in() in dw8250_handle_irq() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dw8250_handle_irq() reads LSR under a few conditions, convert both to use serial_lsr_in() in order to preserve LSR flags properly across reads. Fixes: 424d79183af0 ("serial: 8250_dw: Avoid "too much work" from bogus rx timeout interrupt") Fixes: aa63d786cea2 ("serial: 8250: dw: Add support for DMA flow controlling devices") Cc: Douglas Anderson Cc: Phil Edworthy Cc: Miquel Raynal Reviewed-by: Andy Shevchenko Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220608095431.18376-6-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index f57bbd32ef11..1fae45991812 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -253,7 +253,7 @@ static int dw8250_handle_irq(struct uart_port *p) */ if (!up->dma && rx_timeout) { spin_lock_irqsave(&p->lock, flags); - status = p->serial_in(p, UART_LSR); + status = serial_lsr_in(up); if (!(status & (UART_LSR_DR | UART_LSR_BI))) (void) p->serial_in(p, UART_RX); @@ -263,7 +263,7 @@ static int dw8250_handle_irq(struct uart_port *p) /* Manually stop the Rx DMA transfer when acting as flow controller */ if (quirks & DW_UART_QUIRK_IS_DMA_FC && up->dma && up->dma->rx_running && rx_timeout) { - status = p->serial_in(p, UART_LSR); + status = serial_lsr_in(up); if (status & (UART_LSR_DR | UART_LSR_BI)) { dw8250_writel_ext(p, RZN1_UART_RDMACR, 0); dw8250_writel_ext(p, DW_UART_DMASA, 1); -- cgit v1.2.3 From af14f3007e2dca0d112f10f6717ba43093f74e81 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Wed, 8 Jun 2022 12:54:31 +0300 Subject: serial: 8250_dw: Store LSR into lsr_saved_flags in dw8250_tx_wait_empty() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure LSR flags are preserved in dw8250_tx_wait_empty(). This function is called from a low-level out function and therefore cannot call serial_lsr_in() as it would lead to infinite recursion. It is borderline if the flags need to be saved here at all since this code relates to writing LCR register which usually implies no important characters should be arriving. Fixes: 914eaf935ec7 ("serial: 8250_dw: Allow TX FIFO to drain before writing to UART_LCR") Reviewed-by: Andy Shevchenko Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220608095431.18376-7-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 1fae45991812..4cc69bb612ab 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -122,12 +122,15 @@ static void dw8250_check_lcr(struct uart_port *p, int value) /* Returns once the transmitter is empty or we run out of retries */ static void dw8250_tx_wait_empty(struct uart_port *p) { + struct uart_8250_port *up = up_to_u8250p(p); unsigned int tries = 20000; unsigned int delay_threshold = tries - 1000; unsigned int lsr; while (tries--) { lsr = readb (p->membase + (UART_LSR << p->regshift)); + up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; + if (lsr & UART_LSR_TEMT) break; -- cgit v1.2.3 From 8322b1f527159de578aab277629296575a11eb3c Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:03:58 +0300 Subject: serial: Add uart_rs485_config() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A few serial drivers make a call to rs485_config() themselves (all these seem to relate to init). Convert them all to use a common helper which makes it easy to make adjustments on tasks related to it as serial_rs485 struct sanitization is going to be added. In pci_fintek_setup() (in 8250_pci.c), the rs485_config() call was made with NULL, however, it can be changed to pass uart_port's rs485 struct. No other callers should pass NULL into rs485_config() so the NULL check can now be eliminated. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-2-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 6 ++---- drivers/tty/serial/8250/8250_port.c | 2 +- drivers/tty/serial/fsl_lpuart.c | 2 +- drivers/tty/serial/imx.c | 2 +- drivers/tty/serial/serial_core.c | 6 ++++++ include/linux/serial_core.h | 1 + 6 files changed, 12 insertions(+), 7 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index a17619db7939..fb0a49e39072 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1562,9 +1562,7 @@ static int pci_fintek_rs485_config(struct uart_port *port, pci_read_config_byte(pci_dev, 0x40 + 8 * *index + 7, &setting); - if (!rs485) - rs485 = &port->rs485; - else if (rs485->flags & SER_RS485_ENABLED) + if (rs485->flags & SER_RS485_ENABLED) memset(rs485->padding, 0, sizeof(rs485->padding)); else memset(rs485, 0, sizeof(*rs485)); @@ -1689,7 +1687,7 @@ static int pci_fintek_init(struct pci_dev *dev) * pciserial_resume_ports() */ port = serial8250_get_port(priv->line[i]); - pci_fintek_rs485_config(&port->port, NULL); + uart_rs485_config(&port->port); } else { /* First init without port data * force init to RS232 Mode diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 30e0aaf52adc..af550a4a27f8 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -3191,7 +3191,7 @@ static void serial8250_config_port(struct uart_port *port, int flags) autoconfig(up); if (port->rs485.flags & SER_RS485_ENABLED) - port->rs485_config(port, &port->rs485); + uart_rs485_config(port); /* if access method is AU, it is a 16550 with a quirk */ if (port->type == PORT_16550A && port->iotype == UPIO_AU) diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 0d6e62f6bb07..509a7912fa9d 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -2724,7 +2724,7 @@ static int lpuart_probe(struct platform_device *pdev) sport->port.rs485.delay_rts_after_send) dev_err(&pdev->dev, "driver doesn't support RTS delays\n"); - sport->port.rs485_config(&sport->port, &sport->port.rs485); + uart_rs485_config(&sport->port); ret = devm_request_irq(&pdev->dev, sport->port.irq, handler, 0, DRIVER_NAME, sport); diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 30edb35a6a15..17fb9a57078b 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -2338,7 +2338,7 @@ static int imx_uart_probe(struct platform_device *pdev) dev_err(&pdev->dev, "low-active RTS not possible when receiver is off, enabling receiver\n"); - imx_uart_rs485_config(&sport->port, &sport->port.rs485); + uart_rs485_config(&sport->port); /* Disable interrupts before requesting them */ ucr1 = imx_uart_readl(sport, UCR1); diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 9a85b41caa0a..8466181db4e9 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1276,6 +1276,12 @@ static int uart_get_icount(struct tty_struct *tty, return 0; } +int uart_rs485_config(struct uart_port *port) +{ + return port->rs485_config(port, &port->rs485); +} +EXPORT_SYMBOL_GPL(uart_rs485_config); + static int uart_get_rs485_config(struct uart_port *port, struct serial_rs485 __user *rs485) { diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index cbd5070bc87f..d3ebb4db2d80 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -592,4 +592,5 @@ static inline int uart_handle_break(struct uart_port *port) !((cflag) & CLOCAL)) int uart_get_rs485_mode(struct uart_port *port); +int uart_rs485_config(struct uart_port *port); #endif /* LINUX_SERIAL_CORE_H */ -- cgit v1.2.3 From 2dbd0c14ebe8836eaf890c7f50f3fc5d26d67d95 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:03:59 +0300 Subject: serial: Move serial_rs485 sanitization into separate function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add uart_sanitize_serial_rs485() function for sanitizing serial_rs485 structure fields. No functional changes. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-3-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 55 ++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 25 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 8466181db4e9..44a50158552d 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1276,6 +1276,35 @@ static int uart_get_icount(struct tty_struct *tty, return 0; } +static void uart_sanitize_serial_rs485(struct uart_port *port, struct serial_rs485 *rs485) +{ + /* pick sane settings if the user hasn't */ + if (!(rs485->flags & SER_RS485_RTS_ON_SEND) == + !(rs485->flags & SER_RS485_RTS_AFTER_SEND)) { + dev_warn_ratelimited(port->dev, + "%s (%d): invalid RTS setting, using RTS_ON_SEND instead\n", + port->name, port->line); + rs485->flags |= SER_RS485_RTS_ON_SEND; + rs485->flags &= ~SER_RS485_RTS_AFTER_SEND; + } + + if (rs485->delay_rts_before_send > RS485_MAX_RTS_DELAY) { + rs485->delay_rts_before_send = RS485_MAX_RTS_DELAY; + dev_warn_ratelimited(port->dev, + "%s (%d): RTS delay before sending clamped to %u ms\n", + port->name, port->line, rs485->delay_rts_before_send); + } + + if (rs485->delay_rts_after_send > RS485_MAX_RTS_DELAY) { + rs485->delay_rts_after_send = RS485_MAX_RTS_DELAY; + dev_warn_ratelimited(port->dev, + "%s (%d): RTS delay after sending clamped to %u ms\n", + port->name, port->line, rs485->delay_rts_after_send); + } + /* Return clean padding area to userspace */ + memset(rs485->padding, 0, sizeof(rs485->padding)); +} + int uart_rs485_config(struct uart_port *port) { return port->rs485_config(port, &port->rs485); @@ -1311,31 +1340,7 @@ static int uart_set_rs485_config(struct uart_port *port, if (copy_from_user(&rs485, rs485_user, sizeof(*rs485_user))) return -EFAULT; - /* pick sane settings if the user hasn't */ - if (!(rs485.flags & SER_RS485_RTS_ON_SEND) == - !(rs485.flags & SER_RS485_RTS_AFTER_SEND)) { - dev_warn_ratelimited(port->dev, - "%s (%d): invalid RTS setting, using RTS_ON_SEND instead\n", - port->name, port->line); - rs485.flags |= SER_RS485_RTS_ON_SEND; - rs485.flags &= ~SER_RS485_RTS_AFTER_SEND; - } - - if (rs485.delay_rts_before_send > RS485_MAX_RTS_DELAY) { - rs485.delay_rts_before_send = RS485_MAX_RTS_DELAY; - dev_warn_ratelimited(port->dev, - "%s (%d): RTS delay before sending clamped to %u ms\n", - port->name, port->line, rs485.delay_rts_before_send); - } - - if (rs485.delay_rts_after_send > RS485_MAX_RTS_DELAY) { - rs485.delay_rts_after_send = RS485_MAX_RTS_DELAY; - dev_warn_ratelimited(port->dev, - "%s (%d): RTS delay after sending clamped to %u ms\n", - port->name, port->line, rs485.delay_rts_after_send); - } - /* Return clean padding area to userspace */ - memset(rs485.padding, 0, sizeof(rs485.padding)); + uart_sanitize_serial_rs485(port, &rs485); spin_lock_irqsave(&port->lock, flags); ret = port->rs485_config(port, &rs485); -- cgit v1.2.3 From 8925c31c1ac2f1e05da988581f2a70a2a8c4d638 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:00 +0300 Subject: serial: Add rs485_supported to uart_port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Preparing to move serial_rs485 struct sanitization into serial core, each driver has to provide what fields/flags it supports. This information is pointed into by rs485_supported. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-4-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 1 + include/linux/serial_core.h | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index b0320de3379c..90ddc8924811 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1003,6 +1003,7 @@ int serial8250_register_8250_port(const struct uart_8250_port *up) uart->port.throttle = up->port.throttle; uart->port.unthrottle = up->port.unthrottle; uart->port.rs485_config = up->port.rs485_config; + uart->port.rs485_supported = up->port.rs485_supported; uart->port.rs485 = up->port.rs485; uart->rs485_start_tx = up->rs485_start_tx; uart->rs485_stop_tx = up->rs485_stop_tx; diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index d3ebb4db2d80..5518b70177b3 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -254,6 +254,7 @@ struct uart_port { struct attribute_group *attr_group; /* port specific attributes */ const struct attribute_group **tty_groups; /* all attributes (serial core use only) */ struct serial_rs485 rs485; + const struct serial_rs485 *rs485_supported; /* Supported mask for serial_rs485 */ struct gpio_desc *rs485_term_gpio; /* enable RS485 bus termination */ struct serial_iso7816 iso7816; void *private_data; /* generic platform data pointer */ -- cgit v1.2.3 From 43ee34131cedca95c413b5e6203f4545309d2450 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:01 +0300 Subject: serial: 8250: Create serial8250_em485_supported for em485 users MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create serial8250_em485_supported for the serial_rs485 features supported by the em485 framework. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-5-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.h | 1 + drivers/tty/serial/8250/8250_port.c | 8 ++++++++ 2 files changed, 9 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index c89cb881d9b0..b120da57c61f 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -207,6 +207,7 @@ int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485); void serial8250_em485_start_tx(struct uart_8250_port *p); void serial8250_em485_stop_tx(struct uart_8250_port *p); void serial8250_em485_destroy(struct uart_8250_port *p); +extern struct serial_rs485 serial8250_em485_supported; /* MCR <-> TIOCM conversion */ static inline int serial8250_TIOCM_to_MCR(int tiocm) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index af550a4a27f8..65a60e4808ea 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -647,6 +647,14 @@ void serial8250_em485_destroy(struct uart_8250_port *p) } EXPORT_SYMBOL_GPL(serial8250_em485_destroy); +struct serial_rs485 serial8250_em485_supported = { + .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND | + SER_RS485_TERMINATE_BUS | SER_RS485_RX_DURING_TX, + .delay_rts_before_send = 1, + .delay_rts_after_send = 1, +}; +EXPORT_SYMBOL_GPL(serial8250_em485_supported); + /** * serial8250_em485_config() - generic ->rs485_config() callback * @port: uart port -- cgit v1.2.3 From 499b1160bc026eb7774bcf5b82b9e0ec2f6ae0be Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:02 +0300 Subject: serial: 8250_bcm2835aux: Use serial8250_em485_supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bcm2835aux uses em485, fill in rs485_supported accordingly. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-6-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_bcm2835aux.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c index 2a1226a78a0c..d9f1e618cfbd 100644 --- a/drivers/tty/serial/8250/8250_bcm2835aux.c +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c @@ -108,6 +108,7 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) up.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SKIP_TEST | UPF_IOREMAP; up.port.rs485_config = serial8250_em485_config; + up.port.rs485_supported = &serial8250_em485_supported; up.rs485_start_tx = bcm2835aux_rs485_start_tx; up.rs485_stop_tx = bcm2835aux_rs485_stop_tx; -- cgit v1.2.3 From 62a4b3d274192c845cde4e885bfa7c2bedf18330 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:03 +0300 Subject: serial: 8250_dwlib: Fill in rs485_supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add information on supported serial_rs485 features. When the driver is using em485, take advantage of serial8250_em485_supported. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-7-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dwlib.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c index fbabfdd8c7b8..120b29519d74 100644 --- a/drivers/tty/serial/8250/8250_dwlib.c +++ b/drivers/tty/serial/8250/8250_dwlib.c @@ -149,6 +149,11 @@ static bool dw8250_detect_rs485_hw(struct uart_port *p) return reg; } +static const struct serial_rs485 dw8250_rs485_supported = { + .flags = SER_RS485_ENABLED | SER_RS485_RX_DURING_TX | SER_RS485_RTS_ON_SEND | + SER_RS485_RTS_AFTER_SEND, +}; + void dw8250_setup_port(struct uart_port *p) { struct dw8250_port_data *pd = p->private_data; @@ -159,8 +164,10 @@ void dw8250_setup_port(struct uart_port *p) pd->hw_rs485_support = dw8250_detect_rs485_hw(p); if (pd->hw_rs485_support) { p->rs485_config = dw8250_rs485_config; + p->rs485_supported = &dw8250_rs485_supported; } else { p->rs485_config = serial8250_em485_config; + p->rs485_supported = &serial8250_em485_supported; up->rs485_start_tx = serial8250_em485_start_tx; up->rs485_stop_tx = serial8250_em485_stop_tx; } -- cgit v1.2.3 From 59c221f8e1269278161313048c71929c9950b2c4 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:04 +0300 Subject: serial: 8250_exar: Fill in rs485_supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add information on supported serial_rs485 features. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-8-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_exar.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index 7292917ac878..11916f603a3d 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -113,6 +113,7 @@ struct exar8250; struct exar8250_platform { int (*rs485_config)(struct uart_port *, struct serial_rs485 *); + const struct serial_rs485 *rs485_supported; int (*register_gpio)(struct pci_dev *, struct uart_8250_port *); void (*unregister_gpio)(struct uart_8250_port *); }; @@ -431,10 +432,15 @@ static int generic_rs485_config(struct uart_port *port, return 0; } +static const struct serial_rs485 generic_rs485_supported = { + .flags = SER_RS485_ENABLED, +}; + static const struct exar8250_platform exar8250_default_platform = { .register_gpio = xr17v35x_register_gpio, .unregister_gpio = xr17v35x_unregister_gpio, .rs485_config = generic_rs485_config, + .rs485_supported = &generic_rs485_supported, }; static int iot2040_rs485_config(struct uart_port *port, @@ -470,6 +476,10 @@ static int iot2040_rs485_config(struct uart_port *port, return generic_rs485_config(port, rs485); } +static const struct serial_rs485 iot2040_rs485_supported = { + .flags = SER_RS485_ENABLED | SER_RS485_RX_DURING_TX | SER_RS485_TERMINATE_BUS, +}; + static const struct property_entry iot2040_gpio_properties[] = { PROPERTY_ENTRY_U32("exar,first-pin", 10), PROPERTY_ENTRY_U32("ngpios", 1), @@ -498,6 +508,7 @@ static int iot2040_register_gpio(struct pci_dev *pcidev, static const struct exar8250_platform iot2040_platform = { .rs485_config = iot2040_rs485_config, + .rs485_supported = &iot2040_rs485_supported, .register_gpio = iot2040_register_gpio, .unregister_gpio = xr17v35x_unregister_gpio, }; @@ -540,6 +551,7 @@ pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev, port->port.uartclk = baud * 16; port->port.rs485_config = platform->rs485_config; + port->port.rs485_supported = platform->rs485_supported; /* * Setup the UART clock for the devices on expansion slot to -- cgit v1.2.3 From 70780464846f763c00aa4fa3fda67525d3bb7fe8 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:05 +0300 Subject: serial: 8250_fintek: Fill in rs485_supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add information on supported serial_rs485 features. Differentiate based on which port is in question. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-9-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_fintek.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index dba5950b8d0e..6e98c376e082 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -424,6 +424,17 @@ static int probe_setup_port(struct fintek_8250 *pdata, return -ENODEV; } +/* Only the first port supports delays */ +static const struct serial_rs485 fintek_8250_rs485_supported_port0 = { + .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND, + .delay_rts_before_send = 1, + .delay_rts_after_send = 1, +}; + +static const struct serial_rs485 fintek_8250_rs485_supported = { + .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND, +}; + static void fintek_8250_set_rs485_handler(struct uart_8250_port *uart) { struct fintek_8250 *pdata = uart->port.private_data; @@ -435,6 +446,10 @@ static void fintek_8250_set_rs485_handler(struct uart_8250_port *uart) case CHIP_ID_F81866: case CHIP_ID_F81865: uart->port.rs485_config = fintek_8250_rs485_config; + if (!pdata->index) + uart->port.rs485_supported = &fintek_8250_rs485_supported_port0; + else + uart->port.rs485_supported = &fintek_8250_rs485_supported; break; default: /* No RS485 Auto direction functional */ -- cgit v1.2.3 From 4f4c90bb2a5178124391d617c32c4261c53277e7 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:06 +0300 Subject: serial: 8250_lpc18cc: Fill in rs485_supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add information on supported serial_rs485 features. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-10-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_lpc18xx.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_lpc18xx.c b/drivers/tty/serial/8250/8250_lpc18xx.c index 570e25d6f37e..66ce5d05fe9c 100644 --- a/drivers/tty/serial/8250/8250_lpc18xx.c +++ b/drivers/tty/serial/8250/8250_lpc18xx.c @@ -98,6 +98,12 @@ static void lpc18xx_uart_serial_out(struct uart_port *p, int offset, int value) writel(value, p->membase + offset); } +static const struct serial_rs485 lpc18xx_rs485_supported = { + .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND, + .delay_rts_after_send = 1, + /* Delay RTS before send is not supported */ +}; + static int lpc18xx_serial_probe(struct platform_device *pdev) { struct lpc18xx_uart_data *data; @@ -168,6 +174,7 @@ static int lpc18xx_serial_probe(struct platform_device *pdev) uart.port.uartclk = clk_get_rate(data->clk_uart); uart.port.private_data = data; uart.port.rs485_config = lpc18xx_rs485_config; + uart.port.rs485_supported = &lpc18xx_rs485_supported; uart.port.serial_out = lpc18xx_uart_serial_out; uart.dma = &data->dma; -- cgit v1.2.3 From 6d345f7cf83ce035d6b25724e4c72156098186b3 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:07 +0300 Subject: serial: 8250_of: Use serial8250_em485_supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 8250_of uses em485, fill in rs485_supported accordingly. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-11-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_of.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 5a699a1aa79c..65cccd559db2 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -165,6 +165,7 @@ static int of_platform_serial_setup(struct platform_device *ofdev, port->dev = &ofdev->dev; port->rs485_config = serial8250_em485_config; + port->rs485_supported = &serial8250_em485_supported; up->rs485_start_tx = serial8250_em485_start_tx; up->rs485_stop_tx = serial8250_em485_stop_tx; -- cgit v1.2.3 From 456d523b1be3a0a0c3498fce55b32fc205fac7e1 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:08 +0300 Subject: serial: 8250_pci: Fill in rs485_supported for pci_fintek MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add information on supported serial_rs485 features. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-12-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index fb0a49e39072..a76254031bc2 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1597,6 +1597,11 @@ static int pci_fintek_rs485_config(struct uart_port *port, return 0; } +static const struct serial_rs485 pci_fintek_rs485_supported = { + .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND, + /* F81504/508/512 does not support RTS delay before or after send */ +}; + static int pci_fintek_setup(struct serial_private *priv, const struct pciserial_board *board, struct uart_8250_port *port, int idx) @@ -1616,6 +1621,7 @@ static int pci_fintek_setup(struct serial_private *priv, port->port.iotype = UPIO_PORT; port->port.iobase = iobase; port->port.rs485_config = pci_fintek_rs485_config; + port->port.rs485_supported = &pci_fintek_rs485_supported; data = devm_kzalloc(&pdev->dev, sizeof(u8), GFP_KERNEL); if (!data) -- cgit v1.2.3 From ebe2cf736a0426b228b73f858cdd782c77c109c3 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:09 +0300 Subject: serial: pl011: Fill in rs485_supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add information on supported serial_rs485 features. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-13-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 97ef41cb2721..cdc466e89aa8 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2751,6 +2751,13 @@ static int pl011_register_port(struct uart_amba_port *uap) return ret; } +static const struct serial_rs485 pl011_rs485_supported = { + .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND | + SER_RS485_RX_DURING_TX, + .delay_rts_before_send = 1, + .delay_rts_after_send = 1, +}; + static int pl011_probe(struct amba_device *dev, const struct amba_id *id) { struct uart_amba_port *uap; @@ -2777,6 +2784,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) uap->port.irq = dev->irq[0]; uap->port.ops = &amba_pl011_pops; uap->port.rs485_config = pl011_rs485_config; + uap->port.rs485_supported = &pl011_rs485_supported; snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev)); ret = pl011_setup_port(&dev->dev, uap, &dev->res, portnr); -- cgit v1.2.3 From e849145e1fdd2d6d7bde26a5b3dbfd11567ce071 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:10 +0300 Subject: serial: ar933x: Fill in rs485_supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add information on supported serial_rs485 features. In the case where RTS is lacking, RS485 cannot be enabled so provide zero rs485_supported for that case. Perhaps it would make sense to not provide rs485_config() at all in that case but such a change would have userspace visible impact/change in behavior so this patch does not attempt it. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-14-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/ar933x_uart.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c index 6269dbf93546..ab2c5b2a1ce8 100644 --- a/drivers/tty/serial/ar933x_uart.c +++ b/drivers/tty/serial/ar933x_uart.c @@ -702,6 +702,11 @@ static struct uart_driver ar933x_uart_driver = { .cons = NULL, /* filled in runtime */ }; +static const struct serial_rs485 ar933x_no_rs485 = {}; +static const struct serial_rs485 ar933x_rs485_supported = { + .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND, +}; + static int ar933x_uart_probe(struct platform_device *pdev) { struct ar933x_uart_port *up; @@ -773,6 +778,7 @@ static int ar933x_uart_probe(struct platform_device *pdev) port->fifosize = AR933X_UART_FIFO_SIZE; port->ops = &ar933x_uart_ops; port->rs485_config = ar933x_config_rs485; + port->rs485_supported = &ar933x_rs485_supported; baud = ar933x_uart_get_baud(port->uartclk, AR933X_UART_MAX_SCALE, 1); up->min_baud = max_t(unsigned int, baud, AR933X_UART_MIN_BAUD); @@ -796,6 +802,7 @@ static int ar933x_uart_probe(struct platform_device *pdev) !up->rts_gpiod) { dev_err(&pdev->dev, "lacking rts-gpio, disabling RS485\n"); port->rs485.flags &= ~SER_RS485_ENABLED; + port->rs485_supported = &ar933x_no_rs485; } #ifdef CONFIG_SERIAL_AR933X_CONSOLE -- cgit v1.2.3 From af47c491e3c78e051a5e4d1832dbb29a8ab97799 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:11 +0300 Subject: serial: atmel: Fill in rs485_supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add information on supported serial_rs485 features. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-15-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index dd1c7e4bd1c9..74dd1d3ac46f 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -2473,6 +2473,12 @@ static const struct uart_ops atmel_pops = { #endif }; +static const struct serial_rs485 atmel_rs485_supported = { + .flags = SER_RS485_ENABLED | SER_RS485_RTS_AFTER_SEND | SER_RS485_RX_DURING_TX, + .delay_rts_before_send = 1, + .delay_rts_after_send = 1, +}; + /* * Configure the port from the platform device resource info. */ @@ -2494,6 +2500,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, port->mapbase = mpdev->resource[0].start; port->irq = platform_get_irq(mpdev, 0); port->rs485_config = atmel_config_rs485; + port->rs485_supported = &atmel_rs485_supported; port->iso7816_config = atmel_config_iso7816; port->membase = NULL; -- cgit v1.2.3 From 07481f448b635d7cebb92d5940f5bea5c4395a26 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:12 +0300 Subject: serial: fsl_lpuart: Fill in rs485_supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add information on supported serial_rs485 features. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-16-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/fsl_lpuart.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 509a7912fa9d..88692dc9eefa 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -2621,6 +2621,11 @@ static struct uart_driver lpuart_reg = { .cons = LPUART_CONSOLE, }; +static const struct serial_rs485 lpuart_rs485_supported = { + .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND, + /* delay_rts_* and RX_DURING_TX are not supported */ +}; + static int lpuart_probe(struct platform_device *pdev) { const struct lpuart_soc_data *sdata = of_device_get_match_data(&pdev->dev); @@ -2660,6 +2665,7 @@ static int lpuart_probe(struct platform_device *pdev) sport->port.rs485_config = lpuart32_config_rs485; else sport->port.rs485_config = lpuart_config_rs485; + sport->port.rs485_supported = &lpuart_rs485_supported; sport->ipg_clk = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(sport->ipg_clk)) { -- cgit v1.2.3 From 00d7a00e2a6ff60140068cadb6739ee0a13f5297 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:13 +0300 Subject: serial: imx: Fill in rs485_supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add information on supported serial_rs485 features. In the case where RTS is lacking, RS485 cannot be enabled so provide zero rs485_supported for that case. Perhaps it would make sense to not provide rs485_config() at all in that case but such a change would have userspace visible impact/change in behavior so this patch does not attempt it. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-17-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 17fb9a57078b..9d5f505008f7 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -2200,6 +2200,14 @@ static enum hrtimer_restart imx_trigger_stop_tx(struct hrtimer *t) return HRTIMER_NORESTART; } +static const struct serial_rs485 imx_no_rs485 = {}; /* No RS485 if no RTS */ +static const struct serial_rs485 imx_rs485_supported = { + .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND | + SER_RS485_RX_DURING_TX, + .delay_rts_before_send = 1, + .delay_rts_after_send = 1, +}; + /* Default RX DMA buffer configuration */ #define RX_DMA_PERIODS 16 #define RX_DMA_PERIOD_LEN (PAGE_SIZE / 4) @@ -2279,6 +2287,11 @@ static int imx_uart_probe(struct platform_device *pdev) sport->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE); sport->port.ops = &imx_uart_pops; sport->port.rs485_config = imx_uart_rs485_config; + /* RTS is required to control the RS485 transmitter */ + if (sport->have_rtscts || sport->have_rtsgpio) + sport->port.rs485_supported = &imx_rs485_supported; + else + sport->port.rs485_supported = &imx_no_rs485; sport->port.flags = UPF_BOOT_AUTOCONF; timer_setup(&sport->timer, imx_uart_timeout, 0); -- cgit v1.2.3 From 2b947cf9e335bb1152a3395e461b9c8e94738730 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:14 +0300 Subject: serial: max310x: Fill in rs485_supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add information on supported serial_rs485 features. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-18-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/max310x.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 0f7c5908fee0..7b0c1351d75e 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -1259,6 +1259,12 @@ static int max310x_gpio_set_config(struct gpio_chip *chip, unsigned int offset, } #endif +static const struct serial_rs485 max310x_rs485_supported = { + .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX, + .delay_rts_before_send = 1, + .delay_rts_after_send = 1, +}; + static int max310x_probe(struct device *dev, const struct max310x_devtype *devtype, const struct max310x_if_cfg *if_cfg, struct regmap *regmaps[], int irq) @@ -1366,6 +1372,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty s->p[i].port.membase = (void __iomem *)~0; s->p[i].port.uartclk = uartclk; s->p[i].port.rs485_config = max310x_rs485_config; + s->p[i].port.rs485_supported = &max310x_rs485_supported; s->p[i].port.ops = &max310x_ops; s->p[i].regmap = regmaps[i]; -- cgit v1.2.3 From 949b4dbfb6b39ae0de5cfce0d74543b92c6df93d Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:15 +0300 Subject: serial: mcf: Fill in rs485_supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add information on supported serial_rs485 features. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-19-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mcf.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c index 2aec62b5d6c4..655255e0c76a 100644 --- a/drivers/tty/serial/mcf.c +++ b/drivers/tty/serial/mcf.c @@ -453,6 +453,10 @@ static int mcf_config_rs485(struct uart_port *port, struct serial_rs485 *rs485) return 0; } +static const struct serial_rs485 mcf_rs485_supported = { + .flags = SER_RS485_ENABLED | SER_RS485_RTS_AFTER_SEND, +}; + /****************************************************************************/ /* @@ -502,6 +506,7 @@ int __init early_mcf_setup(struct mcf_platform_uart *platp) port->uartclk = MCF_BUSCLK; port->flags = UPF_BOOT_AUTOCONF; port->rs485_config = mcf_config_rs485; + port->rs485_supported = &mcf_rs485_supported; port->ops = &mcf_uart_ops; } @@ -629,6 +634,7 @@ static int mcf_probe(struct platform_device *pdev) port->ops = &mcf_uart_ops; port->flags = UPF_BOOT_AUTOCONF; port->rs485_config = mcf_config_rs485; + port->rs485_supported = &mcf_rs485_supported; port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); uart_add_one_port(&mcf_driver, port); -- cgit v1.2.3 From d45e50d087765606cdb0728798697467fd5bcc9e Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:16 +0300 Subject: serial: omap: Fill in rs485_supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add information on supported serial_rs485 features. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-20-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 46f4d4cacb6e..98622c35d896 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1559,6 +1559,13 @@ static int serial_omap_probe_rs485(struct uart_omap_port *up, return 0; } +static const struct serial_rs485 serial_omap_rs485_supported = { + .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND | + SER_RS485_RX_DURING_TX, + .delay_rts_before_send = 1, + .delay_rts_after_send = 1, +}; + static int serial_omap_probe(struct platform_device *pdev) { struct omap_uart_port_info *omap_up_info = dev_get_platdata(&pdev->dev); @@ -1636,6 +1643,7 @@ static int serial_omap_probe(struct platform_device *pdev) up->port.flags = omap_up_info->flags; up->port.uartclk = omap_up_info->uartclk; up->port.rs485_config = serial_omap_config_rs485; + up->port.rs485_supported = &serial_omap_rs485_supported; if (!up->port.uartclk) { up->port.uartclk = DEFAULT_CLK_SPEED; dev_warn(&pdev->dev, -- cgit v1.2.3 From 267913ecf73745ca3e8fc8282671b0b4f24df5fe Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:17 +0300 Subject: serial: sc16is7xx: Fill in rs485_supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add information on supported serial_rs485 features. This driver does not support delay_rts_after_send but the pre-existing behavior is to return -EINVAL if delay_rts_after_send is non-zero. In contrast, other drivers that do not support delay_rts_after_send either zero delay_rts_after_send or do not care (leave the inaccurate value). As changing this would cause userspace visible impact, the change is not attempted here. But perhaps it should be still tried (maybe nobody finds that kind of API oddity significant)? Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-21-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sc16is7xx.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 8472bf70477c..b3162dfe97b1 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -1354,6 +1354,12 @@ static int sc16is7xx_gpio_direction_output(struct gpio_chip *chip, } #endif +static const struct serial_rs485 sc16is7xx_rs485_supported = { + .flags = SER_RS485_ENABLED | SER_RS485_RTS_AFTER_SEND, + .delay_rts_before_send = 1, + .delay_rts_after_send = 1, /* Not supported but keep returning -EINVAL */ +}; + static int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype, struct regmap *regmap, int irq) @@ -1456,6 +1462,7 @@ static int sc16is7xx_probe(struct device *dev, s->p[i].port.iotype = UPIO_PORT; s->p[i].port.uartclk = freq; s->p[i].port.rs485_config = sc16is7xx_config_rs485; + s->p[i].port.rs485_supported = &sc16is7xx_rs485_supported; s->p[i].port.ops = &sc16is7xx_ops; s->p[i].old_mctrl = 0; s->p[i].port.line = sc16is7xx_alloc_line(); -- cgit v1.2.3 From aeae8f222fdd34bdddc1050dc073e56b2242c9b5 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:18 +0300 Subject: serial: stm32: Fill in rs485_supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add information on supported serial_rs485 features. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-22-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/stm32-usart.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index b7b44f4050d4..db3dd9731ee1 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -1375,6 +1375,13 @@ static void stm32_usart_deinit_port(struct stm32_port *stm32port) clk_disable_unprepare(stm32port->clk); } +static const struct serial_rs485 stm32_rs485_supported = { + .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND | + SER_RS485_RX_DURING_TX, + .delay_rts_before_send = 1, + .delay_rts_after_send = 1, +}; + static int stm32_usart_init_port(struct stm32_port *stm32port, struct platform_device *pdev) { @@ -1394,6 +1401,7 @@ static int stm32_usart_init_port(struct stm32_port *stm32port, port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_STM32_CONSOLE); port->irq = irq; port->rs485_config = stm32_usart_config_rs485; + port->rs485_supported = &stm32_rs485_supported; ret = stm32_usart_init_rs485(port, pdev); if (ret) -- cgit v1.2.3 From be2e2cb1d28195792539ac2539f8c40c39d3dd4c Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:19 +0300 Subject: serial: Sanitize rs485_struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sanitize serial_rs485 struct before calling into rs485_setup. The drivers provide supported_rs485 to help sanitization of the fields. If neither of SER_RS485_RTS_ON_SEND or SER_RS485_RTS_AFTER_SEND supported, don't pretend they can be set to sane settings but clear them both instead. If only one of them is supported it may look tempting to use the one driver supports to set the other, however, the userspace does not have that information readily available so it wouldn't be helpful. While adjusting the documentation, remove also the claim that TIOCGRS485 would call driver specific code. In reality, it does nothing else than copies the stored serial_rs485 structure from uart_port to userspace. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-23-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/serial/serial-rs485.rst | 12 ++++++--- drivers/tty/serial/serial_core.c | 33 +++++++++++++++++++++--- 2 files changed, 37 insertions(+), 8 deletions(-) (limited to 'drivers/tty/serial') diff --git a/Documentation/driver-api/serial/serial-rs485.rst b/Documentation/driver-api/serial/serial-rs485.rst index 6bc824f948f9..00b5d333acba 100644 --- a/Documentation/driver-api/serial/serial-rs485.rst +++ b/Documentation/driver-api/serial/serial-rs485.rst @@ -38,10 +38,14 @@ RS485 Serial Communications the values given by the device tree. Any driver for devices capable of working both as RS232 and RS485 should - implement the rs485_config callback in the uart_port structure. The - serial_core calls rs485_config to do the device specific part in response - to TIOCSRS485 and TIOCGRS485 ioctls (see below). The rs485_config callback - receives a pointer to struct serial_rs485. + implement the rs485_config callback and provide rs485_supported in the + uart_port structure. The serial core calls rs485_config to do the device + specific part in response to TIOCSRS485 ioctl (see below). The rs485_config + callback receives a pointer to a sanitizated serial_rs485 structure. The + serial_rs485 userspace provides is sanitized before calling rs485_config + using rs485_supported that indicates what RS485 features the driver supports + for the uart_port. TIOCGRS485 ioctl can be used to read back the + serial_rs485 structure matching to the current configuration. 4. Usage from user-level ======================== diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 44a50158552d..f0d7b3d20731 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1278,36 +1278,61 @@ static int uart_get_icount(struct tty_struct *tty, static void uart_sanitize_serial_rs485(struct uart_port *port, struct serial_rs485 *rs485) { + u32 supported_flags = port->rs485_supported->flags; + /* pick sane settings if the user hasn't */ - if (!(rs485->flags & SER_RS485_RTS_ON_SEND) == + if ((supported_flags & (SER_RS485_RTS_ON_SEND|SER_RS485_RTS_AFTER_SEND)) && + !(rs485->flags & SER_RS485_RTS_ON_SEND) == !(rs485->flags & SER_RS485_RTS_AFTER_SEND)) { dev_warn_ratelimited(port->dev, "%s (%d): invalid RTS setting, using RTS_ON_SEND instead\n", port->name, port->line); rs485->flags |= SER_RS485_RTS_ON_SEND; rs485->flags &= ~SER_RS485_RTS_AFTER_SEND; + supported_flags |= SER_RS485_RTS_ON_SEND|SER_RS485_RTS_AFTER_SEND; } - if (rs485->delay_rts_before_send > RS485_MAX_RTS_DELAY) { + if (!port->rs485_supported->delay_rts_before_send) { + if (rs485->delay_rts_before_send) { + dev_warn_ratelimited(port->dev, + "%s (%d): RTS delay before sending not supported\n", + port->name, port->line); + } + rs485->delay_rts_before_send = 0; + } else if (rs485->delay_rts_before_send > RS485_MAX_RTS_DELAY) { rs485->delay_rts_before_send = RS485_MAX_RTS_DELAY; dev_warn_ratelimited(port->dev, "%s (%d): RTS delay before sending clamped to %u ms\n", port->name, port->line, rs485->delay_rts_before_send); } - if (rs485->delay_rts_after_send > RS485_MAX_RTS_DELAY) { + if (!port->rs485_supported->delay_rts_after_send) { + if (rs485->delay_rts_after_send) { + dev_warn_ratelimited(port->dev, + "%s (%d): RTS delay after sending not supported\n", + port->name, port->line); + } + rs485->delay_rts_after_send = 0; + } else if (rs485->delay_rts_after_send > RS485_MAX_RTS_DELAY) { rs485->delay_rts_after_send = RS485_MAX_RTS_DELAY; dev_warn_ratelimited(port->dev, "%s (%d): RTS delay after sending clamped to %u ms\n", port->name, port->line, rs485->delay_rts_after_send); } + + rs485->flags &= supported_flags; + /* Return clean padding area to userspace */ memset(rs485->padding, 0, sizeof(rs485->padding)); } int uart_rs485_config(struct uart_port *port) { - return port->rs485_config(port, &port->rs485); + struct serial_rs485 *rs485 = &port->rs485; + + uart_sanitize_serial_rs485(port, rs485); + + return port->rs485_config(port, rs485); } EXPORT_SYMBOL_GPL(uart_rs485_config); -- cgit v1.2.3 From 596a9171472ba31edce566e938524dbbe3c54183 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:20 +0300 Subject: serial: Clear rs485 struct when non-RS485 mode is set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When SER_RS485_ENABLED is not set, having any other flag/field set in serial_rs485 struct does not have an effect different from not having them set. Thus, make the serial_rs485 struct also match the behavior for all flags, not just SER_RS485_ENABLED. Some drivers do similar clearing of rs485 struct in their rs485_config() already, but not all. This change makes the behavior consistent across drivers. Don't try to validate rs485 struct further when no RS485 is requested, this silences some bogus warnings. This change has (minor) userspace visible impact. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-24-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index f0d7b3d20731..6be538720564 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1280,6 +1280,11 @@ static void uart_sanitize_serial_rs485(struct uart_port *port, struct serial_rs4 { u32 supported_flags = port->rs485_supported->flags; + if (!(rs485->flags & SER_RS485_ENABLED)) { + memset(rs485, 0, sizeof(*rs485)); + return; + } + /* pick sane settings if the user hasn't */ if ((supported_flags & (SER_RS485_RTS_ON_SEND|SER_RS485_RTS_AFTER_SEND)) && !(rs485->flags & SER_RS485_RTS_ON_SEND) == @@ -1329,10 +1334,15 @@ static void uart_sanitize_serial_rs485(struct uart_port *port, struct serial_rs4 int uart_rs485_config(struct uart_port *port) { struct serial_rs485 *rs485 = &port->rs485; + int ret; uart_sanitize_serial_rs485(port, rs485); - return port->rs485_config(port, rs485); + ret = port->rs485_config(port, rs485); + if (ret) + memset(rs485, 0, sizeof(*rs485)); + + return ret; } EXPORT_SYMBOL_GPL(uart_rs485_config); -- cgit v1.2.3 From 51ad36baacb3b2fd1bd980138a937d30d6c84cdf Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:21 +0300 Subject: serial: return -EINVAL for non-legacy RS485 flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to be add new flags more cleanly and safely, return -EINVAL from TIOCSRS485 ioctl for the flags bits which are not among the current legacy ones. This might cause a regression for userspace as those non-flag bits do not currently trigger -EINVAL. However, it would only occur if the userspace is sending garbage bits so perhaps we'll get away with this change. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-25-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 6be538720564..621fc15e2e54 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1276,6 +1276,27 @@ static int uart_get_icount(struct tty_struct *tty, return 0; } +#define SER_RS485_LEGACY_FLAGS (SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | \ + SER_RS485_RTS_AFTER_SEND | SER_RS485_RX_DURING_TX | \ + SER_RS485_TERMINATE_BUS) + +static int uart_check_rs485_flags(struct uart_port *port, struct serial_rs485 *rs485) +{ + u32 flags = rs485->flags; + + /* Don't return -EINVAL for unsupported legacy flags */ + flags &= ~SER_RS485_LEGACY_FLAGS; + + /* + * For any bit outside of the legacy ones that is not supported by + * the driver, return -EINVAL. + */ + if (flags & ~port->rs485_supported->flags) + return -EINVAL; + + return 0; +} + static void uart_sanitize_serial_rs485(struct uart_port *port, struct serial_rs485 *rs485) { u32 supported_flags = port->rs485_supported->flags; @@ -1375,6 +1396,9 @@ static int uart_set_rs485_config(struct uart_port *port, if (copy_from_user(&rs485, rs485_user, sizeof(*rs485_user))) return -EFAULT; + ret = uart_check_rs485_flags(port, &rs485); + if (ret) + return ret; uart_sanitize_serial_rs485(port, &rs485); spin_lock_irqsave(&port->lock, flags); -- cgit v1.2.3 From 9cdaf4fc2e6f8eeb137dbf6c5d6346cbf249ff49 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:22 +0300 Subject: serial: 8250_dwlib: Remove serial_rs485 sanitization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Serial core handles serial_rs485 sanitization and rs485 struct assignment. As serial_rs485 is already clear for the non-RS485 case by serial core, there no need to clear flags in the driver. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-26-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dwlib.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c index 120b29519d74..c83e7eaf3877 100644 --- a/drivers/tty/serial/8250/8250_dwlib.c +++ b/drivers/tty/serial/8250/8250_dwlib.c @@ -93,9 +93,6 @@ static int dw8250_rs485_config(struct uart_port *p, struct serial_rs485 *rs485) tcr &= ~DW_UART_TCR_XFER_MODE; if (rs485->flags & SER_RS485_ENABLED) { - /* Clear unsupported flags. */ - rs485->flags &= SER_RS485_ENABLED | SER_RS485_RX_DURING_TX | - SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND; tcr |= DW_UART_TCR_RS485_EN; if (rs485->flags & SER_RS485_RX_DURING_TX) { @@ -111,8 +108,6 @@ static int dw8250_rs485_config(struct uart_port *p, struct serial_rs485 *rs485) dw8250_writel_ext(p, DW_UART_DE_EN, 1); dw8250_writel_ext(p, DW_UART_RE_EN, 1); } else { - rs485->flags = 0; - tcr &= ~DW_UART_TCR_RS485_EN; } @@ -127,11 +122,6 @@ static int dw8250_rs485_config(struct uart_port *p, struct serial_rs485 *rs485) dw8250_writel_ext(p, DW_UART_TCR, tcr); - rs485->delay_rts_before_send = 0; - rs485->delay_rts_after_send = 0; - - p->rs485 = *rs485; - return 0; } -- cgit v1.2.3 From cf426544a4131c54c2e49b40547c43cfe2e56b76 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:23 +0300 Subject: serial: 8250_fintek: Remove serial_rs485 sanitization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Serial core handles serial_rs485 sanitization and copying rs485 struct. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-27-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_fintek.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index 6e98c376e082..1fb86c73786c 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -206,19 +206,7 @@ static int fintek_8250_rs485_config(struct uart_port *port, if (!(rs485->flags & SER_RS485_RTS_ON_SEND) == !(rs485->flags & SER_RS485_RTS_AFTER_SEND)) return -EINVAL; - memset(rs485->padding, 0, sizeof(rs485->padding)); config |= RS485_URA; - } else { - memset(rs485, 0, sizeof(*rs485)); - } - - rs485->flags &= SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | - SER_RS485_RTS_AFTER_SEND; - - /* Only the first port supports delays */ - if (pdata->index) { - rs485->delay_rts_before_send = 0; - rs485->delay_rts_after_send = 0; } if (rs485->delay_rts_before_send) { @@ -241,8 +229,6 @@ static int fintek_8250_rs485_config(struct uart_port *port, sio_write_reg(pdata, RS485, config); fintek_8250_exit_key(pdata->base_port); - port->rs485 = *rs485; - return 0; } -- cgit v1.2.3 From ebc3c2a4cdba004de57f7d8316603ac61218d9d8 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:24 +0300 Subject: serial: 8250: lpc18xx: Remove serial_rs485 sanitization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Serial core handles serial_rs485 sanitization and copying rs485 struct. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-28-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_lpc18xx.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_lpc18xx.c b/drivers/tty/serial/8250/8250_lpc18xx.c index 66ce5d05fe9c..3a1cb51cbc91 100644 --- a/drivers/tty/serial/8250/8250_lpc18xx.c +++ b/drivers/tty/serial/8250/8250_lpc18xx.c @@ -40,14 +40,6 @@ static int lpc18xx_rs485_config(struct uart_port *port, u32 rs485_dly_reg = 0; unsigned baud_clk; - if (rs485->flags & SER_RS485_ENABLED) - memset(rs485->padding, 0, sizeof(rs485->padding)); - else - memset(rs485, 0, sizeof(*rs485)); - - rs485->flags &= SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | - SER_RS485_RTS_AFTER_SEND; - if (rs485->flags & SER_RS485_ENABLED) { rs485_ctrl_reg |= LPC18XX_UART_RS485CTRL_NMMEN | LPC18XX_UART_RS485CTRL_DCTRL; @@ -73,14 +65,9 @@ static int lpc18xx_rs485_config(struct uart_port *port, / baud_clk; } - /* Delay RTS before send not supported */ - rs485->delay_rts_before_send = 0; - serial_out(up, LPC18XX_UART_RS485CTRL, rs485_ctrl_reg); serial_out(up, LPC18XX_UART_RS485DLY, rs485_dly_reg); - port->rs485 = *rs485; - return 0; } -- cgit v1.2.3 From 61bca7da91c680ef140ecb35c27d887406bd4167 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:25 +0300 Subject: serial: 8250_pci: Remove serial_rs485 sanitization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Serial core handles serial_rs485 sanitization and copying rs485 struct. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-29-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index a76254031bc2..b6d71268aa7d 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1562,14 +1562,6 @@ static int pci_fintek_rs485_config(struct uart_port *port, pci_read_config_byte(pci_dev, 0x40 + 8 * *index + 7, &setting); - if (rs485->flags & SER_RS485_ENABLED) - memset(rs485->padding, 0, sizeof(rs485->padding)); - else - memset(rs485, 0, sizeof(*rs485)); - - /* F81504/508/512 not support RTS delay before or after send */ - rs485->flags &= SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND; - if (rs485->flags & SER_RS485_ENABLED) { /* Enable RTS H/W control mode */ setting |= FINTEK_RTS_CONTROL_BY_HW; @@ -1581,9 +1573,6 @@ static int pci_fintek_rs485_config(struct uart_port *port, /* RTS driving low on TX */ setting |= FINTEK_RTS_INVERT; } - - rs485->delay_rts_after_send = 0; - rs485->delay_rts_before_send = 0; } else { /* Disable RTS H/W control mode */ setting &= ~(FINTEK_RTS_CONTROL_BY_HW | FINTEK_RTS_INVERT); @@ -1591,9 +1580,6 @@ static int pci_fintek_rs485_config(struct uart_port *port, pci_write_config_byte(pci_dev, 0x40 + 8 * *index + 7, setting); - if (rs485 != &port->rs485) - port->rs485 = *rs485; - return 0; } -- cgit v1.2.3 From b9759cba3221767ac1910b0cff65ec588003b9a6 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:26 +0300 Subject: serial: pl011: Remove serial_rs485 sanitization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Serial core handles serial_rs485 sanitization. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-30-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index cdc466e89aa8..eccd66625d25 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2681,17 +2681,12 @@ static int pl011_find_free_port(void) static int pl011_get_rs485_mode(struct uart_amba_port *uap) { struct uart_port *port = &uap->port; - struct serial_rs485 *rs485 = &port->rs485; int ret; ret = uart_get_rs485_mode(port); if (ret) return ret; - /* clamp the delays to [0, 100ms] */ - rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); - rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U); - return 0; } -- cgit v1.2.3 From 7195eefb38d76d2353e658b10a8b1c2b1f8341e3 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:27 +0300 Subject: serial: fsl_lpuart: Call core's sanitization and remove custom one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Serial core handles serial_rs485 sanitization. Remove custom sanitization from lpuart_config_rs485. This change loses dev_err when SER_RS485_RX_DURING_TX is set due to incorrect configuration. Other drivers do not do similar prinout for full-duplex case and it should be done in serial core if it is desirable to notify on this condition. Personally, I doesn't see it important because the kernel gracefully downgrades to half-duplex. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-31-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/fsl_lpuart.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 88692dc9eefa..d35414cb3e4e 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -1365,11 +1365,6 @@ static int lpuart_config_rs485(struct uart_port *port, ~(UARTMODEM_TXRTSPOL | UARTMODEM_TXRTSE); writeb(modem, sport->port.membase + UARTMODEM); - /* clear unsupported configurations */ - rs485->delay_rts_before_send = 0; - rs485->delay_rts_after_send = 0; - rs485->flags &= ~SER_RS485_RX_DURING_TX; - if (rs485->flags & SER_RS485_ENABLED) { /* Enable auto RS-485 RTS mode */ modem |= UARTMODEM_TXRTSE; @@ -1400,11 +1395,6 @@ static int lpuart32_config_rs485(struct uart_port *port, & ~(UARTMODEM_TXRTSPOL | UARTMODEM_TXRTSE); lpuart32_write(&sport->port, modem, UARTMODIR); - /* clear unsupported configurations */ - rs485->delay_rts_before_send = 0; - rs485->delay_rts_after_send = 0; - rs485->flags &= ~SER_RS485_RX_DURING_TX; - if (rs485->flags & SER_RS485_ENABLED) { /* Enable auto RS-485 RTS mode */ modem |= UARTMODEM_TXRTSE; @@ -2723,13 +2713,6 @@ static int lpuart_probe(struct platform_device *pdev) if (ret) goto failed_get_rs485; - if (sport->port.rs485.flags & SER_RS485_RX_DURING_TX) - dev_err(&pdev->dev, "driver doesn't support RX during TX\n"); - - if (sport->port.rs485.delay_rts_before_send || - sport->port.rs485.delay_rts_after_send) - dev_err(&pdev->dev, "driver doesn't support RTS delays\n"); - uart_rs485_config(&sport->port); ret = devm_request_irq(&pdev->dev, sport->port.irq, handler, 0, -- cgit v1.2.3 From 55e18c6b6d426818032d5e0f9d88d87fd2a8ae30 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:28 +0300 Subject: serial: imx: Remove serial_rs485 sanitization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver provides different rs485_supported for the case where RTS is not available making it unnecessary to handle it in imx_uart_rs485_config. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-32-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 9d5f505008f7..f4edde54175f 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1913,10 +1913,6 @@ static int imx_uart_rs485_config(struct uart_port *port, struct imx_port *sport = (struct imx_port *)port; u32 ucr2; - /* RTS is required to control the transmitter */ - if (!sport->have_rtscts && !sport->have_rtsgpio) - rs485conf->flags &= ~SER_RS485_ENABLED; - if (rs485conf->flags & SER_RS485_ENABLED) { /* Enable receiver if low-active RTS signal is requested */ if (sport->have_rtscts && !sport->have_rtsgpio && -- cgit v1.2.3 From ad98c78bd011ca76d1667aa3cb53562dfb29725a Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:29 +0300 Subject: serial: max310x: Remove serial_rs485 sanitization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Serial core handles serial_rs485 sanitization. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-33-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/max310x.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 7b0c1351d75e..4915a786e315 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -1045,8 +1045,6 @@ static int max310x_rs485_config(struct uart_port *port, (rs485->delay_rts_after_send > 0x0f)) return -ERANGE; - rs485->flags &= SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX | - SER_RS485_ENABLED; port->rs485 = *rs485; schedule_work(&one->rs_work); -- cgit v1.2.3 From e25ed4a8857f8bf6d4f51bea0ff6c6a80adbb7fe Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:30 +0300 Subject: serial: 8250_exar: Remove serial_rs485 assignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Serial core handles serial_rs485 assignment. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-34-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_exar.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index 11916f603a3d..528779b40049 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -427,8 +427,6 @@ static int generic_rs485_config(struct uart_port *port, if (is_rs485) writeb(UART_EXAR_RS485_DLY(4), p + UART_MSR); - port->rs485 = *rs485; - return 0; } -- cgit v1.2.3 From fd93a3d851c54198a517c6209947cc0569e1059d Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:31 +0300 Subject: serial: mcf: Remove serial_rs485 assignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Serial core handles serial_rs485 assignment. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-35-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mcf.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c index 655255e0c76a..036f178e3d66 100644 --- a/drivers/tty/serial/mcf.c +++ b/drivers/tty/serial/mcf.c @@ -448,7 +448,6 @@ static int mcf_config_rs485(struct uart_port *port, struct serial_rs485 *rs485) } writeb(mr1, port->membase + MCFUART_UMR); writeb(mr2, port->membase + MCFUART_UMR); - port->rs485 = *rs485; return 0; } -- cgit v1.2.3 From bbdcbc1301ce16d5cbabfbccaacb87f047a0a309 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:32 +0300 Subject: serial: sc16is7xx: Remove serial_rs485 assignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Serial core handles serial_rs485 assignment. It is safe to remove this assignment because sc16is7xx_reg_proc() takes port.lock at start (and sc16is7xx_reconf_rs485() would too). Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-36-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sc16is7xx.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index b3162dfe97b1..2ceecaa4a478 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -1143,7 +1143,6 @@ static int sc16is7xx_config_rs485(struct uart_port *port, return -EINVAL; } - port->rs485 = *rs485; one->config.flags |= SC16IS7XX_RECONF_RS485; kthread_queue_work(&s->kworker, &one->reg_work); -- cgit v1.2.3 From 84f2faa7852e1f55d89bb0c99b3a672b87b11f87 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 6 Jun 2022 13:04:33 +0300 Subject: serial: 8250: Remove serial_rs485 sanitization from em485 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Serial core handles serial_rs485 sanitization. When em485 init fails, there are two possible paths of entry: 1) uart_rs485_config (init path) that fully clears port->rs485 on error. 2) ioctl path with a pre-existing, valid port->rs485 unto which the kernel falls back on error and port->rs485 should therefore be kept untouched. The temporary rs485 struct is not returned to userspace in case of error so its flag don't matter. ...Thus SER_RS485_ENABLED clearing on error can/should be dropped. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220606100433.13793-37-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 65a60e4808ea..953b0fadfd4c 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -675,13 +675,6 @@ int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485) rs485->flags &= ~SER_RS485_RTS_AFTER_SEND; } - /* clamp the delays to [0, 100ms] */ - rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); - rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U); - - memset(rs485->padding, 0, sizeof(rs485->padding)); - port->rs485 = *rs485; - gpiod_set_value(port->rs485_term_gpio, rs485->flags & SER_RS485_TERMINATE_BUS); @@ -689,15 +682,8 @@ int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485) * Both serial8250_em485_init() and serial8250_em485_destroy() * are idempotent. */ - if (rs485->flags & SER_RS485_ENABLED) { - int ret = serial8250_em485_init(up); - - if (ret) { - rs485->flags &= ~SER_RS485_ENABLED; - port->rs485.flags &= ~SER_RS485_ENABLED; - } - return ret; - } + if (rs485->flags & SER_RS485_ENABLED) + return serial8250_em485_init(up); serial8250_em485_destroy(up); return 0; -- cgit v1.2.3 From 2069cb2e1f3ed2d97e8b6fe818982432de7f4e69 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 11 Jun 2022 10:42:06 +0200 Subject: serial: sifive: Remove useless license text when SPDX-License-Identifier is already used An SPDX-License-Identifier is already in place. There is no need to duplicate part of the corresponding license. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/dbc54eff6f4e077d9126054f395d5bc5b3405917.1654936915.git.christophe.jaillet@wanadoo.fr Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sifive.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/sifive.c b/drivers/tty/serial/sifive.c index c0869b080cc3..5c3a07546a58 100644 --- a/drivers/tty/serial/sifive.c +++ b/drivers/tty/serial/sifive.c @@ -4,16 +4,6 @@ * Copyright (C) 2018 Paul Walmsley * Copyright (C) 2018-2019 SiFive * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * * Based partially on: * - drivers/tty/serial/pxa.c * - drivers/tty/serial/amba-pl011.c -- cgit v1.2.3 From 5db6db08c6de4f95865c16a5f5b46726da295809 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 13 Jun 2022 10:57:35 +0300 Subject: serial: 8250: Use UART_LCR_WLEN8 instead of literal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use UART_LCR_WLEN8 instead of literal 0x03 in size_fifo(). Reviewed-by: Jiri Slaby Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220613075736.12283-1-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 3e3d784aa628..3a8747ec672b 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -843,7 +843,7 @@ static int size_fifo(struct uart_8250_port *up) serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); old_dl = serial_dl_read(up); serial_dl_write(up, 0x0001); - serial_out(up, UART_LCR, 0x03); + serial_out(up, UART_LCR, UART_LCR_WLEN8); for (count = 0; count < 256; count++) serial_out(up, UART_TX, count); mdelay(20);/* FIXME - schedule_timeout */ -- cgit v1.2.3 From d4b06172861bfcb390fc196bf616f60e95665e7d Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 13 Jun 2022 10:57:36 +0300 Subject: serial: 8250_pericom: Use UART_LCR_DLAB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use UART_LCR_DLAB instead of literal. Reviewed-by: Jiri Slaby Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220613075736.12283-2-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pericom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_pericom.c b/drivers/tty/serial/8250/8250_pericom.c index 95ff10f25d58..b8d5b7714a9d 100644 --- a/drivers/tty/serial/8250/8250_pericom.c +++ b/drivers/tty/serial/8250/8250_pericom.c @@ -73,7 +73,7 @@ static void pericom_do_set_divisor(struct uart_port *port, unsigned int baud, struct uart_8250_port *up = up_to_u8250p(port); int lcr = serial_port_in(port, UART_LCR); - serial_port_out(port, UART_LCR, lcr | 0x80); + serial_port_out(port, UART_LCR, lcr | UART_LCR_DLAB); serial_dl_write(up, divisor); serial_port_out(port, 2, 16 - scr); serial_port_out(port, UART_LCR, lcr); -- cgit v1.2.3 From f9008285bb69e4713918a665250ab2d356b731ba Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 13 Jun 2022 14:39:05 +0300 Subject: serial: Drop timeout from uart_port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 31f6bd7fad3b ("serial: Store character timing information to uart_port"), per frame timing information is available on uart_port. Uart port's timeout can be derived from frame_time by multiplying with fifosize. Most callers of uart_poll_timeout are not made under port's lock. To be on the safe side, make sure frame_time is only accessed once. As fifo_size is effectively a constant, it shouldn't cause any issues. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220613113905.22962-1-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/serial/driver.rst | 5 +++-- drivers/tty/serial/mux.c | 6 ------ drivers/tty/serial/serial_core.c | 25 ++++++++++--------------- include/linux/serial_core.h | 16 ++++++++++++++-- 4 files changed, 27 insertions(+), 25 deletions(-) (limited to 'drivers/tty/serial') diff --git a/Documentation/driver-api/serial/driver.rst b/Documentation/driver-api/serial/driver.rst index 7ef83fd3917b..1e7ab4142d49 100644 --- a/Documentation/driver-api/serial/driver.rst +++ b/Documentation/driver-api/serial/driver.rst @@ -422,8 +422,9 @@ Other functions --------------- uart_update_timeout(port,cflag,baud) - Update the FIFO drain timeout, port->timeout, according to the - number of bits, parity, stop bits and baud rate. + Update the frame timing information according to the number of bits, + parity, stop bits and baud rate. The FIFO drain timeout is derived + from the frame timing information. Locking: caller is expected to take port->lock diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c index 643dfbcc43f9..0ba0f4d9459d 100644 --- a/drivers/tty/serial/mux.c +++ b/drivers/tty/serial/mux.c @@ -481,12 +481,6 @@ static int __init mux_probe(struct parisc_device *dev) port->line = port_cnt; port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MUX_CONSOLE); - /* The port->timeout needs to match what is present in - * uart_wait_until_sent in serial_core.c. Otherwise - * the time spent in msleep_interruptable will be very - * long, causing the appearance of a console hang. - */ - port->timeout = HZ / 50; spin_lock_init(&port->lock); status = uart_add_one_port(&mux_driver, port); diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 1368b0ef7d7f..75ece750bedc 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -327,13 +327,14 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) } /** - * uart_update_timeout - update per-port FIFO timeout. + * uart_update_timeout - update per-port frame timing information. * @port: uart_port structure describing the port * @cflag: termios cflag value * @baud: speed of the port * - * Set the port FIFO timeout value. The @cflag value should - * reflect the actual hardware settings. + * Set the port frame timing information from which the FIFO timeout + * value is derived. The @cflag value should reflect the actual hardware + * settings. */ void uart_update_timeout(struct uart_port *port, unsigned int cflag, @@ -343,13 +344,6 @@ uart_update_timeout(struct uart_port *port, unsigned int cflag, u64 frame_time; frame_time = (u64)size * NSEC_PER_SEC; - size *= port->fifosize; - - /* - * Figure the timeout to send the above number of bits. - * Add .02 seconds of slop - */ - port->timeout = (HZ * size) / baud + HZ/50; port->frame_time = DIV64_U64_ROUND_UP(frame_time, baud); } EXPORT_SYMBOL(uart_update_timeout); @@ -1698,7 +1692,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) { struct uart_state *state = tty->driver_data; struct uart_port *port; - unsigned long char_time, expire; + unsigned long char_time, expire, fifo_timeout; port = uart_port_ref(state); if (!port) @@ -1728,12 +1722,13 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) * amount of time to send the entire FIFO, it probably won't * ever clear. This assumes the UART isn't doing flow * control, which is currently the case. Hence, if it ever - * takes longer than port->timeout, this is probably due to a + * takes longer than FIFO timeout, this is probably due to a * UART bug of some kind. So, we clamp the timeout parameter at - * 2*port->timeout. + * 2 * FIFO timeout. */ - if (timeout == 0 || timeout > 2 * port->timeout) - timeout = 2 * port->timeout; + fifo_timeout = uart_fifo_timeout(port); + if (timeout == 0 || timeout > 2 * fifo_timeout) + timeout = 2 * fifo_timeout; } expire = jiffies + timeout; diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 8032ffa741ed..faaf2372c60d 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -232,7 +232,6 @@ struct uart_port { int hw_stopped; /* sw-assisted CTS flow state */ unsigned int mctrl; /* current modem ctrl settings */ - unsigned int timeout; /* character-based timeout */ unsigned int frame_time; /* frame timing in ns */ unsigned int type; /* port type */ const struct uart_ops *ops; @@ -335,10 +334,23 @@ unsigned int uart_get_baud_rate(struct uart_port *port, struct ktermios *termios unsigned int max); unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud); +/* + * Calculates FIFO drain time. + */ +static inline unsigned long uart_fifo_timeout(struct uart_port *port) +{ + u64 fifo_timeout = (u64)READ_ONCE(port->frame_time) * port->fifosize; + + /* Add .02 seconds of slop */ + fifo_timeout += 20 * NSEC_PER_MSEC; + + return max(nsecs_to_jiffies(fifo_timeout), 1UL); +} + /* Base timer interval for polling */ static inline int uart_poll_timeout(struct uart_port *port) { - int timeout = port->timeout; + int timeout = uart_fifo_timeout(port); return timeout > 6 ? (timeout / 2 - 2) : 1; } -- cgit v1.2.3 From eb01611056cf835cf2c1cc1a800bfff9386c82ea Mon Sep 17 00:00:00 2001 From: Liang He Date: Wed, 15 Jun 2022 19:17:47 +0800 Subject: drivers: tty: serial: Add missing of_node_put() in serial-tegra.c In tegra_uart_init(), of_find_matching_node() will return a node pointer with refcount incremented. We should use of_node_put() when it is not used anymore. Signed-off-by: Liang He Link: https://lore.kernel.org/r/20220615111747.3963930-1-windhl@126.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial-tegra.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c index 101fb585e6f9..ad4f3567ff90 100644 --- a/drivers/tty/serial/serial-tegra.c +++ b/drivers/tty/serial/serial-tegra.c @@ -1667,6 +1667,7 @@ static int __init tegra_uart_init(void) node = of_find_matching_node(NULL, tegra_uart_of_match); if (node) match = of_match_node(tegra_uart_of_match, node); + of_node_put(node); if (match) cdata = match->data; if (cdata) -- cgit v1.2.3 From d24d7bb2cd947676f9b71fb944d045e09b8b282f Mon Sep 17 00:00:00 2001 From: Liang He Date: Sat, 18 Jun 2022 14:08:50 +0800 Subject: tty: serial: Fix refcount leak bug in ucc_uart.c In soc_info(), of_find_node_by_type() will return a node pointer with refcount incremented. We should use of_node_put() when it is not used anymore. Acked-by: Timur Tabi Signed-off-by: Liang He Link: https://lore.kernel.org/r/20220618060850.4058525-1-windhl@126.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/ucc_uart.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c index 6000853973c1..3cc9ef08455c 100644 --- a/drivers/tty/serial/ucc_uart.c +++ b/drivers/tty/serial/ucc_uart.c @@ -1137,6 +1137,8 @@ static unsigned int soc_info(unsigned int *rev_h, unsigned int *rev_l) /* No compatible property, so try the name. */ soc_string = np->name; + of_node_put(np); + /* Extract the SOC number from the "PowerPC," string */ if ((sscanf(soc_string, "PowerPC,%u", &soc) != 1) || !soc) return 0; -- cgit v1.2.3 From ab8ba6c59d5ab4f894cd731c0b05825576d15ed1 Mon Sep 17 00:00:00 2001 From: Xiang wangx Date: Mon, 20 Jun 2022 18:46:53 +0800 Subject: serial: kgdboc: Fix typo in comment Delete the redundant word 'the'. Signed-off-by: Xiang wangx Link: https://lore.kernel.org/r/20220620104653.5451-1-wangxiang@cdjrlc.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/kgdboc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c index 79b7db8580e0..7aa37be3216a 100644 --- a/drivers/tty/serial/kgdboc.c +++ b/drivers/tty/serial/kgdboc.c @@ -342,7 +342,7 @@ static int param_set_kgdboc_var(const char *kmessage, /* * Configure with the new params as long as init already ran. * Note that we can get called before init if someone loads us - * with "modprobe kgdboc kgdboc=..." or if they happen to use the + * with "modprobe kgdboc kgdboc=..." or if they happen to use * the odd syntax of "kgdboc.kgdboc=..." on the kernel command. */ if (configured >= 0) -- cgit v1.2.3 From b50058b82e0a0ea2cb11889c261cb7d587b62e1c Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Thu, 16 Jun 2022 17:00:21 +0300 Subject: tty: serial: atmel: stop using legacy pm ops Stop using legacy PM ops and switch using dev_pm_ops. Along with it #ifdef CONFIG_PM are removed and __maybe_unused and pm_ptr() used instead. Coding style recommends (at chapter Conditional Compilation) to avoid using preprocessor conditional and use __maybe_unused instead. Acked-by: Richard Genoud Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20220616140024.2081238-2-claudiu.beznea@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 74dd1d3ac46f..c618d7e93058 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -166,7 +166,6 @@ struct atmel_uart_port { unsigned int fidi_min; unsigned int fidi_max; -#ifdef CONFIG_PM struct { u32 cr; u32 mr; @@ -177,7 +176,6 @@ struct atmel_uart_port { u32 fmr; u32 fimr; } cache; -#endif int (*prepare_rx)(struct uart_port *port); int (*prepare_tx)(struct uart_port *port); @@ -2718,7 +2716,6 @@ static struct uart_driver atmel_uart = { .cons = ATMEL_CONSOLE_DEVICE, }; -#ifdef CONFIG_PM static bool atmel_serial_clk_will_stop(void) { #ifdef CONFIG_ARCH_AT91 @@ -2728,10 +2725,9 @@ static bool atmel_serial_clk_will_stop(void) #endif } -static int atmel_serial_suspend(struct platform_device *pdev, - pm_message_t state) +static int __maybe_unused atmel_serial_suspend(struct device *dev) { - struct uart_port *port = platform_get_drvdata(pdev); + struct uart_port *port = dev_get_drvdata(dev); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); if (uart_console(port) && console_suspend_enabled) { @@ -2756,14 +2752,14 @@ static int atmel_serial_suspend(struct platform_device *pdev, } /* we can not wake up if we're running on slow clock */ - atmel_port->may_wakeup = device_may_wakeup(&pdev->dev); + atmel_port->may_wakeup = device_may_wakeup(dev); if (atmel_serial_clk_will_stop()) { unsigned long flags; spin_lock_irqsave(&atmel_port->lock_suspended, flags); atmel_port->suspended = true; spin_unlock_irqrestore(&atmel_port->lock_suspended, flags); - device_set_wakeup_enable(&pdev->dev, 0); + device_set_wakeup_enable(dev, 0); } uart_suspend_port(&atmel_uart, port); @@ -2771,9 +2767,9 @@ static int atmel_serial_suspend(struct platform_device *pdev, return 0; } -static int atmel_serial_resume(struct platform_device *pdev) +static int __maybe_unused atmel_serial_resume(struct device *dev) { - struct uart_port *port = platform_get_drvdata(pdev); + struct uart_port *port = dev_get_drvdata(dev); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); unsigned long flags; @@ -2808,14 +2804,10 @@ static int atmel_serial_resume(struct platform_device *pdev) spin_unlock_irqrestore(&atmel_port->lock_suspended, flags); uart_resume_port(&atmel_uart, port); - device_set_wakeup_enable(&pdev->dev, atmel_port->may_wakeup); + device_set_wakeup_enable(dev, atmel_port->may_wakeup); return 0; } -#else -#define atmel_serial_suspend NULL -#define atmel_serial_resume NULL -#endif static void atmel_serial_probe_fifos(struct atmel_uart_port *atmel_port, struct platform_device *pdev) @@ -3019,14 +3011,16 @@ static int atmel_serial_remove(struct platform_device *pdev) return ret; } +static SIMPLE_DEV_PM_OPS(atmel_serial_pm_ops, atmel_serial_suspend, + atmel_serial_resume); + static struct platform_driver atmel_serial_driver = { .probe = atmel_serial_probe, .remove = atmel_serial_remove, - .suspend = atmel_serial_suspend, - .resume = atmel_serial_resume, .driver = { .name = "atmel_usart_serial", .of_match_table = of_match_ptr(atmel_serial_dt_ids), + .pm = pm_ptr(&atmel_serial_pm_ops), }, }; -- cgit v1.2.3 From 84b476b124d4581d0c18e2e39e14fca52feedffd Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Thu, 16 Jun 2022 17:00:22 +0300 Subject: tty: serial: atmel: use devm_clk_get() Use devm_clk_get() for serial clock instead of clk_get()/clk_put(). With this move the clk_get in driver's probe function. Acked-by: Richard Genoud Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20220616140024.2081238-3-claudiu.beznea@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 50 ++++++++++++--------------------------- 1 file changed, 15 insertions(+), 35 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index c618d7e93058..4cec97fd7241 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -2508,24 +2508,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, if (ret) return ret; - /* for console, the clock could already be configured */ - if (!atmel_port->clk) { - atmel_port->clk = clk_get(&mpdev->dev, "usart"); - if (IS_ERR(atmel_port->clk)) { - ret = PTR_ERR(atmel_port->clk); - atmel_port->clk = NULL; - return ret; - } - ret = clk_prepare_enable(atmel_port->clk); - if (ret) { - clk_put(atmel_port->clk); - atmel_port->clk = NULL; - return ret; - } - port->uartclk = clk_get_rate(atmel_port->clk); - clk_disable_unprepare(atmel_port->clk); - /* only enable clock when USART is in use */ - } + port->uartclk = clk_get_rate(atmel_port->clk); /* * Use TXEMPTY for interrupt when rs485 or ISO7816 else TXRDY or @@ -2896,14 +2879,23 @@ static int atmel_serial_probe(struct platform_device *pdev) atomic_set(&atmel_port->tasklet_shutdown, 0); spin_lock_init(&atmel_port->lock_suspended); + atmel_port->clk = devm_clk_get(&pdev->dev, "usart"); + if (IS_ERR(atmel_port->clk)) { + ret = PTR_ERR(atmel_port->clk); + goto err; + } + ret = clk_prepare_enable(atmel_port->clk); + if (ret) + goto err; + ret = atmel_init_port(atmel_port, pdev); if (ret) - goto err_clear_bit; + goto err_clk_disable_unprepare; atmel_port->gpios = mctrl_gpio_init(&atmel_port->uart, 0); if (IS_ERR(atmel_port->gpios)) { ret = PTR_ERR(atmel_port->gpios); - goto err_clear_bit; + goto err_clk_disable_unprepare; } if (!atmel_use_pdc_rx(&atmel_port->uart)) { @@ -2912,7 +2904,7 @@ static int atmel_serial_probe(struct platform_device *pdev) sizeof(struct atmel_uart_char), GFP_KERNEL); if (!data) - goto err_alloc_ring; + goto err_clk_disable_unprepare; atmel_port->rx_ring.buf = data; } @@ -2936,12 +2928,6 @@ static int atmel_serial_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); platform_set_drvdata(pdev, atmel_port); - /* - * The peripheral clock has been disabled by atmel_init_port(): - * enable it before accessing I/O registers - */ - clk_prepare_enable(atmel_port->clk); - if (rs485_enabled) { atmel_uart_writel(&atmel_port->uart, ATMEL_US_MR, ATMEL_US_USMODE_NORMAL); @@ -2965,12 +2951,8 @@ static int atmel_serial_probe(struct platform_device *pdev) err_add_port: kfree(atmel_port->rx_ring.buf); atmel_port->rx_ring.buf = NULL; -err_alloc_ring: - if (!uart_console(&atmel_port->uart)) { - clk_put(atmel_port->clk); - atmel_port->clk = NULL; - } -err_clear_bit: +err_clk_disable_unprepare: + clk_disable_unprepare(atmel_port->clk); clear_bit(atmel_port->uart.line, atmel_ports_in_use); err: return ret; @@ -3004,8 +2986,6 @@ static int atmel_serial_remove(struct platform_device *pdev) clear_bit(port->line, atmel_ports_in_use); - clk_put(atmel_port->clk); - atmel_port->clk = NULL; pdev->dev.of_node = NULL; return ret; -- cgit v1.2.3 From 61dbc75ce00f4e27da61683d23cb4f9f3ef3f944 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Thu, 16 Jun 2022 17:00:23 +0300 Subject: tty: serial: atmel: remove enable/disable clock due to atmel_console_setup() There is no need for clk_prepare_enable() at the beginning of atmel_console_setup() and clk_disable_unprepare() at the end of atmel_console_setup() as the clock is already enabled when calling atmel_console_setup() and its disablement is done at the end of probe. Acked-by: Richard Genoud Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20220616140024.2081238-4-claudiu.beznea@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 4cec97fd7241..3a94c2bdda72 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -2617,7 +2617,6 @@ static void __init atmel_console_get_options(struct uart_port *port, int *baud, static int __init atmel_console_setup(struct console *co, char *options) { - int ret; struct uart_port *port = &atmel_ports[co->index].uart; struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); int baud = 115200; @@ -2630,10 +2629,6 @@ static int __init atmel_console_setup(struct console *co, char *options) return -ENODEV; } - ret = clk_prepare_enable(atmel_ports[co->index].clk); - if (ret) - return ret; - atmel_uart_writel(port, ATMEL_US_IDR, -1); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN); @@ -2914,17 +2909,6 @@ static int atmel_serial_probe(struct platform_device *pdev) if (ret) goto err_add_port; -#ifdef CONFIG_SERIAL_ATMEL_CONSOLE - if (uart_console(&atmel_port->uart) - && ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) { - /* - * The serial core enabled the clock for us, so undo - * the clk_prepare_enable() in atmel_console_setup() - */ - clk_disable_unprepare(atmel_port->clk); - } -#endif - device_init_wakeup(&pdev->dev, 1); platform_set_drvdata(pdev, atmel_port); -- cgit v1.2.3 From df5dac860111aa9cfab61521494d25825446cfcc Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Thu, 16 Jun 2022 17:00:24 +0300 Subject: serial: st-asc: remove include of pm_runtime.h st-asc driver doesn't use helpers from pm_runtime.h thus remove its include. Reviewed-by: Patrice Chotard Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20220616140024.2081238-5-claudiu.beznea@microchip.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/st-asc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c index 1b0da603ab54..cce42f4c9bc2 100644 --- a/drivers/tty/serial/st-asc.c +++ b/drivers/tty/serial/st-asc.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 24b5596a858d1b27e63b4f7f894403f0f3dc31c3 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Fri, 24 Jun 2022 23:54:19 +0300 Subject: serial: msm: Convert container_of UART_TO_MSM to static inline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create static inline instead of define as it provides type safety and is safer wrt. macros expansion. Reviewed-by: Jiri Slaby Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220624205424.12686-2-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/msm_serial.c | 49 ++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 23 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index e676ec761f18..15cab9c4b295 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -181,7 +181,10 @@ struct msm_port { struct msm_dma rx_dma; }; -#define UART_TO_MSM(uart_port) container_of(uart_port, struct msm_port, uart) +static inline struct msm_port *to_msm_port(struct uart_port *up) +{ + return container_of(up, struct msm_port, uart); +} static void msm_write(struct uart_port *port, unsigned int val, unsigned int off) @@ -221,7 +224,7 @@ static void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port) static void msm_serial_set_mnd_regs(struct uart_port *port) { - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); /* * These registers don't exist so we change the clk input rate @@ -404,7 +407,7 @@ static inline void msm_wait_for_xmitr(struct uart_port *port) static void msm_stop_tx(struct uart_port *port) { - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); msm_port->imr &= ~UART_IMR_TXLEV; msm_write(port, msm_port->imr, UART_IMR); @@ -412,7 +415,7 @@ static void msm_stop_tx(struct uart_port *port) static void msm_start_tx(struct uart_port *port) { - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); struct msm_dma *dma = &msm_port->tx_dma; /* Already started in DMA mode */ @@ -690,7 +693,7 @@ sw_mode: static void msm_stop_rx(struct uart_port *port) { - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); struct msm_dma *dma = &msm_port->rx_dma; msm_port->imr &= ~(UART_IMR_RXLEV | UART_IMR_RXSTALE); @@ -702,7 +705,7 @@ static void msm_stop_rx(struct uart_port *port) static void msm_enable_ms(struct uart_port *port) { - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); msm_port->imr |= UART_IMR_DELTA_CTS; msm_write(port, msm_port->imr, UART_IMR); @@ -714,7 +717,7 @@ static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr) struct tty_port *tport = &port->state->port; unsigned int sr; int count = 0; - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); if ((msm_read(port, UART_SR) & UART_SR_OVERRUN)) { port->icount.overrun++; @@ -837,7 +840,7 @@ static void msm_handle_rx(struct uart_port *port) static void msm_handle_tx_pio(struct uart_port *port, unsigned int tx_count) { struct circ_buf *xmit = &port->state->xmit; - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); unsigned int num_chars; unsigned int tf_pointer = 0; void __iomem *tf; @@ -883,7 +886,7 @@ static void msm_handle_tx_pio(struct uart_port *port, unsigned int tx_count) static void msm_handle_tx(struct uart_port *port) { - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); struct circ_buf *xmit = &msm_port->uart.state->xmit; struct msm_dma *dma = &msm_port->tx_dma; unsigned int pio_count, dma_count, dma_min; @@ -947,7 +950,7 @@ static void msm_handle_delta_cts(struct uart_port *port) static irqreturn_t msm_uart_irq(int irq, void *dev_id) { struct uart_port *port = dev_id; - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); struct msm_dma *dma = &msm_port->rx_dma; unsigned long flags; unsigned int misr; @@ -1002,7 +1005,7 @@ static unsigned int msm_get_mctrl(struct uart_port *port) static void msm_reset(struct uart_port *port) { - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); unsigned int mr; /* reset everything */ @@ -1055,7 +1058,7 @@ static const struct msm_baud_map * msm_find_best_baud(struct uart_port *port, unsigned int baud, unsigned long *rate) { - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); unsigned int divisor, result; unsigned long target, old, best_rate = 0, diff, best_diff = ULONG_MAX; const struct msm_baud_map *entry, *end, *best; @@ -1124,7 +1127,7 @@ static int msm_set_baud_rate(struct uart_port *port, unsigned int baud, unsigned long *saved_flags) { unsigned int rxstale, watermark, mask; - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); const struct msm_baud_map *entry; unsigned long flags, rate; @@ -1185,7 +1188,7 @@ static int msm_set_baud_rate(struct uart_port *port, unsigned int baud, static void msm_init_clock(struct uart_port *port) { - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); clk_prepare_enable(msm_port->clk); clk_prepare_enable(msm_port->pclk); @@ -1194,7 +1197,7 @@ static void msm_init_clock(struct uart_port *port) static int msm_startup(struct uart_port *port) { - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); unsigned int data, rfr_level, mask; int ret; @@ -1246,7 +1249,7 @@ err_irq: static void msm_shutdown(struct uart_port *port) { - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); msm_port->imr = 0; msm_write(port, 0, UART_IMR); /* disable interrupts */ @@ -1262,7 +1265,7 @@ static void msm_shutdown(struct uart_port *port) static void msm_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); struct msm_dma *dma = &msm_port->rx_dma; unsigned long flags; unsigned int baud, mr; @@ -1416,7 +1419,7 @@ static int msm_verify_port(struct uart_port *port, struct serial_struct *ser) static void msm_power(struct uart_port *port, unsigned int state, unsigned int oldstate) { - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); switch (state) { case 0: @@ -1435,7 +1438,7 @@ static void msm_power(struct uart_port *port, unsigned int state, #ifdef CONFIG_CONSOLE_POLL static int msm_poll_get_char_single(struct uart_port *port) { - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); unsigned int rf_reg = msm_port->is_uartdm ? UARTDM_RF : UART_RF; if (!(msm_read(port, UART_SR) & UART_SR_RX_READY)) @@ -1489,7 +1492,7 @@ static int msm_poll_get_char(struct uart_port *port) { u32 imr; int c; - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); /* Disable all interrupts */ imr = msm_read(port, UART_IMR); @@ -1509,7 +1512,7 @@ static int msm_poll_get_char(struct uart_port *port) static void msm_poll_put_char(struct uart_port *port, unsigned char c) { u32 imr; - struct msm_port *msm_port = UART_TO_MSM(port); + struct msm_port *msm_port = to_msm_port(port); /* Disable all interrupts */ imr = msm_read(port, UART_IMR); @@ -1677,7 +1680,7 @@ static void msm_console_write(struct console *co, const char *s, BUG_ON(co->index < 0 || co->index >= UART_NR); port = msm_get_port_from_line(co->index); - msm_port = UART_TO_MSM(port); + msm_port = to_msm_port(port); __msm_console_write(port, s, count, msm_port->is_uartdm); } @@ -1808,7 +1811,7 @@ static int msm_serial_probe(struct platform_device *pdev) port = msm_get_port_from_line(line); port->dev = &pdev->dev; - msm_port = UART_TO_MSM(port); + msm_port = to_msm_port(port); id = of_match_device(msm_uartdm_table, &pdev->dev); if (id) -- cgit v1.2.3 From fddbab7b40b34d204c4dfa7c6a62e5f7c1920e98 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Fri, 24 Jun 2022 23:54:20 +0300 Subject: serial: msm: Rename UART_* defines to MSM_UART_* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using UART_* to name defines is a bit problematic. When trying to do unrelated cleanup which also involved tweaking header inclusion logic, caused UART_CSR from serial_reg.h to leak into msm's namespace which is also among msm defines. Thus, rename all UART_* ones to MSM_UART_* to eliminate possibility of collisions. Reviewed-by: Jiri Slaby Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220624205424.12686-3-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/msm_serial.c | 501 ++++++++++++++++++++-------------------- 1 file changed, 250 insertions(+), 251 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index 15cab9c4b295..3159889ddae1 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -29,103 +29,103 @@ #include #include -#define UART_MR1 0x0000 - -#define UART_MR1_AUTO_RFR_LEVEL0 0x3F -#define UART_MR1_AUTO_RFR_LEVEL1 0x3FF00 -#define UART_DM_MR1_AUTO_RFR_LEVEL1 0xFFFFFF00 -#define UART_MR1_RX_RDY_CTL BIT(7) -#define UART_MR1_CTS_CTL BIT(6) - -#define UART_MR2 0x0004 -#define UART_MR2_ERROR_MODE BIT(6) -#define UART_MR2_BITS_PER_CHAR 0x30 -#define UART_MR2_BITS_PER_CHAR_5 (0x0 << 4) -#define UART_MR2_BITS_PER_CHAR_6 (0x1 << 4) -#define UART_MR2_BITS_PER_CHAR_7 (0x2 << 4) -#define UART_MR2_BITS_PER_CHAR_8 (0x3 << 4) -#define UART_MR2_STOP_BIT_LEN_ONE (0x1 << 2) -#define UART_MR2_STOP_BIT_LEN_TWO (0x3 << 2) -#define UART_MR2_PARITY_MODE_NONE 0x0 -#define UART_MR2_PARITY_MODE_ODD 0x1 -#define UART_MR2_PARITY_MODE_EVEN 0x2 -#define UART_MR2_PARITY_MODE_SPACE 0x3 -#define UART_MR2_PARITY_MODE 0x3 - -#define UART_CSR 0x0008 - -#define UART_TF 0x000C +#define MSM_UART_MR1 0x0000 + +#define MSM_UART_MR1_AUTO_RFR_LEVEL0 0x3F +#define MSM_UART_MR1_AUTO_RFR_LEVEL1 0x3FF00 +#define MSM_UART_DM_MR1_AUTO_RFR_LEVEL1 0xFFFFFF00 +#define MSM_UART_MR1_RX_RDY_CTL BIT(7) +#define MSM_UART_MR1_CTS_CTL BIT(6) + +#define MSM_UART_MR2 0x0004 +#define MSM_UART_MR2_ERROR_MODE BIT(6) +#define MSM_UART_MR2_BITS_PER_CHAR 0x30 +#define MSM_UART_MR2_BITS_PER_CHAR_5 (0x0 << 4) +#define MSM_UART_MR2_BITS_PER_CHAR_6 (0x1 << 4) +#define MSM_UART_MR2_BITS_PER_CHAR_7 (0x2 << 4) +#define MSM_UART_MR2_BITS_PER_CHAR_8 (0x3 << 4) +#define MSM_UART_MR2_STOP_BIT_LEN_ONE (0x1 << 2) +#define MSM_UART_MR2_STOP_BIT_LEN_TWO (0x3 << 2) +#define MSM_UART_MR2_PARITY_MODE_NONE 0x0 +#define MSM_UART_MR2_PARITY_MODE_ODD 0x1 +#define MSM_UART_MR2_PARITY_MODE_EVEN 0x2 +#define MSM_UART_MR2_PARITY_MODE_SPACE 0x3 +#define MSM_UART_MR2_PARITY_MODE 0x3 + +#define MSM_UART_CSR 0x0008 + +#define MSM_UART_TF 0x000C #define UARTDM_TF 0x0070 -#define UART_CR 0x0010 -#define UART_CR_CMD_NULL (0 << 4) -#define UART_CR_CMD_RESET_RX (1 << 4) -#define UART_CR_CMD_RESET_TX (2 << 4) -#define UART_CR_CMD_RESET_ERR (3 << 4) -#define UART_CR_CMD_RESET_BREAK_INT (4 << 4) -#define UART_CR_CMD_START_BREAK (5 << 4) -#define UART_CR_CMD_STOP_BREAK (6 << 4) -#define UART_CR_CMD_RESET_CTS (7 << 4) -#define UART_CR_CMD_RESET_STALE_INT (8 << 4) -#define UART_CR_CMD_PACKET_MODE (9 << 4) -#define UART_CR_CMD_MODE_RESET (12 << 4) -#define UART_CR_CMD_SET_RFR (13 << 4) -#define UART_CR_CMD_RESET_RFR (14 << 4) -#define UART_CR_CMD_PROTECTION_EN (16 << 4) -#define UART_CR_CMD_STALE_EVENT_DISABLE (6 << 8) -#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4) -#define UART_CR_CMD_FORCE_STALE (4 << 8) -#define UART_CR_CMD_RESET_TX_READY (3 << 8) -#define UART_CR_TX_DISABLE BIT(3) -#define UART_CR_TX_ENABLE BIT(2) -#define UART_CR_RX_DISABLE BIT(1) -#define UART_CR_RX_ENABLE BIT(0) -#define UART_CR_CMD_RESET_RXBREAK_START ((1 << 11) | (2 << 4)) - -#define UART_IMR 0x0014 -#define UART_IMR_TXLEV BIT(0) -#define UART_IMR_RXSTALE BIT(3) -#define UART_IMR_RXLEV BIT(4) -#define UART_IMR_DELTA_CTS BIT(5) -#define UART_IMR_CURRENT_CTS BIT(6) -#define UART_IMR_RXBREAK_START BIT(10) - -#define UART_IPR_RXSTALE_LAST 0x20 -#define UART_IPR_STALE_LSB 0x1F -#define UART_IPR_STALE_TIMEOUT_MSB 0x3FF80 -#define UART_DM_IPR_STALE_TIMEOUT_MSB 0xFFFFFF80 - -#define UART_IPR 0x0018 -#define UART_TFWR 0x001C -#define UART_RFWR 0x0020 -#define UART_HCR 0x0024 - -#define UART_MREG 0x0028 -#define UART_NREG 0x002C -#define UART_DREG 0x0030 -#define UART_MNDREG 0x0034 -#define UART_IRDA 0x0038 -#define UART_MISR_MODE 0x0040 -#define UART_MISR_RESET 0x0044 -#define UART_MISR_EXPORT 0x0048 -#define UART_MISR_VAL 0x004C -#define UART_TEST_CTRL 0x0050 - -#define UART_SR 0x0008 -#define UART_SR_HUNT_CHAR BIT(7) -#define UART_SR_RX_BREAK BIT(6) -#define UART_SR_PAR_FRAME_ERR BIT(5) -#define UART_SR_OVERRUN BIT(4) -#define UART_SR_TX_EMPTY BIT(3) -#define UART_SR_TX_READY BIT(2) -#define UART_SR_RX_FULL BIT(1) -#define UART_SR_RX_READY BIT(0) - -#define UART_RF 0x000C +#define MSM_UART_CR 0x0010 +#define MSM_UART_CR_CMD_NULL (0 << 4) +#define MSM_UART_CR_CMD_RESET_RX (1 << 4) +#define MSM_UART_CR_CMD_RESET_TX (2 << 4) +#define MSM_UART_CR_CMD_RESET_ERR (3 << 4) +#define MSM_UART_CR_CMD_RESET_BREAK_INT (4 << 4) +#define MSM_UART_CR_CMD_START_BREAK (5 << 4) +#define MSM_UART_CR_CMD_STOP_BREAK (6 << 4) +#define MSM_UART_CR_CMD_RESET_CTS (7 << 4) +#define MSM_UART_CR_CMD_RESET_STALE_INT (8 << 4) +#define MSM_UART_CR_CMD_PACKET_MODE (9 << 4) +#define MSM_UART_CR_CMD_MODE_RESET (12 << 4) +#define MSM_UART_CR_CMD_SET_RFR (13 << 4) +#define MSM_UART_CR_CMD_RESET_RFR (14 << 4) +#define MSM_UART_CR_CMD_PROTECTION_EN (16 << 4) +#define MSM_UART_CR_CMD_STALE_EVENT_DISABLE (6 << 8) +#define MSM_UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4) +#define MSM_UART_CR_CMD_FORCE_STALE (4 << 8) +#define MSM_UART_CR_CMD_RESET_TX_READY (3 << 8) +#define MSM_UART_CR_TX_DISABLE BIT(3) +#define MSM_UART_CR_TX_ENABLE BIT(2) +#define MSM_UART_CR_RX_DISABLE BIT(1) +#define MSM_UART_CR_RX_ENABLE BIT(0) +#define MSM_UART_CR_CMD_RESET_RXBREAK_START ((1 << 11) | (2 << 4)) + +#define MSM_UART_IMR 0x0014 +#define MSM_UART_IMR_TXLEV BIT(0) +#define MSM_UART_IMR_RXSTALE BIT(3) +#define MSM_UART_IMR_RXLEV BIT(4) +#define MSM_UART_IMR_DELTA_CTS BIT(5) +#define MSM_UART_IMR_CURRENT_CTS BIT(6) +#define MSM_UART_IMR_RXBREAK_START BIT(10) + +#define MSM_UART_IPR_RXSTALE_LAST 0x20 +#define MSM_UART_IPR_STALE_LSB 0x1F +#define MSM_UART_IPR_STALE_TIMEOUT_MSB 0x3FF80 +#define MSM_UART_DM_IPR_STALE_TIMEOUT_MSB 0xFFFFFF80 + +#define MSM_UART_IPR 0x0018 +#define MSM_UART_TFWR 0x001C +#define MSM_UART_RFWR 0x0020 +#define MSM_UART_HCR 0x0024 + +#define MSM_UART_MREG 0x0028 +#define MSM_UART_NREG 0x002C +#define MSM_UART_DREG 0x0030 +#define MSM_UART_MNDREG 0x0034 +#define MSM_UART_IRDA 0x0038 +#define MSM_UART_MISR_MODE 0x0040 +#define MSM_UART_MISR_RESET 0x0044 +#define MSM_UART_MISR_EXPORT 0x0048 +#define MSM_UART_MISR_VAL 0x004C +#define MSM_UART_TEST_CTRL 0x0050 + +#define MSM_UART_SR 0x0008 +#define MSM_UART_SR_HUNT_CHAR BIT(7) +#define MSM_UART_SR_RX_BREAK BIT(6) +#define MSM_UART_SR_PAR_FRAME_ERR BIT(5) +#define MSM_UART_SR_OVERRUN BIT(4) +#define MSM_UART_SR_TX_EMPTY BIT(3) +#define MSM_UART_SR_TX_READY BIT(2) +#define MSM_UART_SR_RX_FULL BIT(1) +#define MSM_UART_SR_RX_READY BIT(0) + +#define MSM_UART_RF 0x000C #define UARTDM_RF 0x0070 -#define UART_MISR 0x0010 -#define UART_ISR 0x0014 -#define UART_ISR_TX_READY BIT(7) +#define MSM_UART_MISR 0x0010 +#define MSM_UART_ISR 0x0014 +#define MSM_UART_ISR_TX_READY BIT(7) #define UARTDM_RXFS 0x50 #define UARTDM_RXFS_BUF_SHIFT 0x7 @@ -203,10 +203,10 @@ unsigned int msm_read(struct uart_port *port, unsigned int off) */ static void msm_serial_set_mnd_regs_tcxo(struct uart_port *port) { - msm_write(port, 0x06, UART_MREG); - msm_write(port, 0xF1, UART_NREG); - msm_write(port, 0x0F, UART_DREG); - msm_write(port, 0x1A, UART_MNDREG); + msm_write(port, 0x06, MSM_UART_MREG); + msm_write(port, 0xF1, MSM_UART_NREG); + msm_write(port, 0x0F, MSM_UART_DREG); + msm_write(port, 0x1A, MSM_UART_MNDREG); port->uartclk = 1843200; } @@ -215,10 +215,10 @@ static void msm_serial_set_mnd_regs_tcxo(struct uart_port *port) */ static void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port) { - msm_write(port, 0x18, UART_MREG); - msm_write(port, 0xF6, UART_NREG); - msm_write(port, 0x0F, UART_DREG); - msm_write(port, 0x0A, UART_MNDREG); + msm_write(port, 0x18, MSM_UART_MREG); + msm_write(port, 0xF6, MSM_UART_NREG); + msm_write(port, 0x0F, MSM_UART_DREG); + msm_write(port, 0x0A, MSM_UART_MNDREG); port->uartclk = 1843200; } @@ -395,22 +395,22 @@ static inline void msm_wait_for_xmitr(struct uart_port *port) { unsigned int timeout = 500000; - while (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY)) { - if (msm_read(port, UART_ISR) & UART_ISR_TX_READY) + while (!(msm_read(port, MSM_UART_SR) & MSM_UART_SR_TX_EMPTY)) { + if (msm_read(port, MSM_UART_ISR) & MSM_UART_ISR_TX_READY) break; udelay(1); if (!timeout--) break; } - msm_write(port, UART_CR_CMD_RESET_TX_READY, UART_CR); + msm_write(port, MSM_UART_CR_CMD_RESET_TX_READY, MSM_UART_CR); } static void msm_stop_tx(struct uart_port *port) { struct msm_port *msm_port = to_msm_port(port); - msm_port->imr &= ~UART_IMR_TXLEV; - msm_write(port, msm_port->imr, UART_IMR); + msm_port->imr &= ~MSM_UART_IMR_TXLEV; + msm_write(port, msm_port->imr, MSM_UART_IMR); } static void msm_start_tx(struct uart_port *port) @@ -422,8 +422,8 @@ static void msm_start_tx(struct uart_port *port) if (dma->count) return; - msm_port->imr |= UART_IMR_TXLEV; - msm_write(port, msm_port->imr, UART_IMR); + msm_port->imr |= MSM_UART_IMR_TXLEV; + msm_write(port, msm_port->imr, MSM_UART_IMR); } static void msm_reset_dm_count(struct uart_port *port, int count) @@ -459,8 +459,8 @@ static void msm_complete_tx_dma(void *args) msm_write(port, val, UARTDM_DMEN); if (msm_port->is_uartdm > UARTDM_1P3) { - msm_write(port, UART_CR_CMD_RESET_TX, UART_CR); - msm_write(port, UART_CR_TX_ENABLE, UART_CR); + msm_write(port, MSM_UART_CR_CMD_RESET_TX, MSM_UART_CR); + msm_write(port, MSM_UART_CR_TX_ENABLE, MSM_UART_CR); } count = dma->count - state.residue; @@ -471,8 +471,8 @@ static void msm_complete_tx_dma(void *args) xmit->tail &= UART_XMIT_SIZE - 1; /* Restore "Tx FIFO below watermark" interrupt */ - msm_port->imr |= UART_IMR_TXLEV; - msm_write(port, msm_port->imr, UART_IMR); + msm_port->imr |= MSM_UART_IMR_TXLEV; + msm_write(port, msm_port->imr, MSM_UART_IMR); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); @@ -519,8 +519,8 @@ static int msm_handle_tx_dma(struct msm_port *msm_port, unsigned int count) * Using DMA complete for Tx FIFO reload, no need for * "Tx FIFO below watermark" one, disable it */ - msm_port->imr &= ~UART_IMR_TXLEV; - msm_write(port, msm_port->imr, UART_IMR); + msm_port->imr &= ~MSM_UART_IMR_TXLEV; + msm_write(port, msm_port->imr, MSM_UART_IMR); dma->count = count; @@ -562,10 +562,10 @@ static void msm_complete_rx_dma(void *args) val &= ~dma->enable_bit; msm_write(port, val, UARTDM_DMEN); - if (msm_read(port, UART_SR) & UART_SR_OVERRUN) { + if (msm_read(port, MSM_UART_SR) & MSM_UART_SR_OVERRUN) { port->icount.overrun++; tty_insert_flip_char(tport, 0, TTY_OVERRUN); - msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR); + msm_write(port, MSM_UART_CR_CMD_RESET_ERR, MSM_UART_CR); } count = msm_read(port, UARTDM_RX_TOTAL_SNAP); @@ -587,7 +587,7 @@ static void msm_complete_rx_dma(void *args) continue; } - if (!(port->read_status_mask & UART_SR_RX_BREAK)) + if (!(port->read_status_mask & MSM_UART_SR_RX_BREAK)) flag = TTY_NORMAL; spin_unlock_irqrestore(&port->lock, flags); @@ -641,23 +641,23 @@ static void msm_start_rx_dma(struct msm_port *msm_port) * Using DMA for FIFO off-load, no need for "Rx FIFO over * watermark" or "stale" interrupts, disable them */ - msm_port->imr &= ~(UART_IMR_RXLEV | UART_IMR_RXSTALE); + msm_port->imr &= ~(MSM_UART_IMR_RXLEV | MSM_UART_IMR_RXSTALE); /* * Well, when DMA is ADM3 engine(implied by <= UARTDM v1.3), * we need RXSTALE to flush input DMA fifo to memory */ if (msm_port->is_uartdm < UARTDM_1P4) - msm_port->imr |= UART_IMR_RXSTALE; + msm_port->imr |= MSM_UART_IMR_RXSTALE; - msm_write(uart, msm_port->imr, UART_IMR); + msm_write(uart, msm_port->imr, MSM_UART_IMR); dma->count = UARTDM_RX_SIZE; dma_async_issue_pending(dma->chan); - msm_write(uart, UART_CR_CMD_RESET_STALE_INT, UART_CR); - msm_write(uart, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR); + msm_write(uart, MSM_UART_CR_CMD_RESET_STALE_INT, MSM_UART_CR); + msm_write(uart, MSM_UART_CR_CMD_STALE_EVENT_ENABLE, MSM_UART_CR); val = msm_read(uart, UARTDM_DMEN); val |= dma->enable_bit; @@ -679,16 +679,16 @@ sw_mode: * Switch from DMA to SW/FIFO mode. After clearing Rx BAM (UARTDM_DMEN), * receiver must be reset. */ - msm_write(uart, UART_CR_CMD_RESET_RX, UART_CR); - msm_write(uart, UART_CR_RX_ENABLE, UART_CR); + msm_write(uart, MSM_UART_CR_CMD_RESET_RX, MSM_UART_CR); + msm_write(uart, MSM_UART_CR_RX_ENABLE, MSM_UART_CR); - msm_write(uart, UART_CR_CMD_RESET_STALE_INT, UART_CR); + msm_write(uart, MSM_UART_CR_CMD_RESET_STALE_INT, MSM_UART_CR); msm_write(uart, 0xFFFFFF, UARTDM_DMRX); - msm_write(uart, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR); + msm_write(uart, MSM_UART_CR_CMD_STALE_EVENT_ENABLE, MSM_UART_CR); /* Re-enable RX interrupts */ - msm_port->imr |= (UART_IMR_RXLEV | UART_IMR_RXSTALE); - msm_write(uart, msm_port->imr, UART_IMR); + msm_port->imr |= MSM_UART_IMR_RXLEV | MSM_UART_IMR_RXSTALE; + msm_write(uart, msm_port->imr, MSM_UART_IMR); } static void msm_stop_rx(struct uart_port *port) @@ -696,8 +696,8 @@ static void msm_stop_rx(struct uart_port *port) struct msm_port *msm_port = to_msm_port(port); struct msm_dma *dma = &msm_port->rx_dma; - msm_port->imr &= ~(UART_IMR_RXLEV | UART_IMR_RXSTALE); - msm_write(port, msm_port->imr, UART_IMR); + msm_port->imr &= ~(MSM_UART_IMR_RXLEV | MSM_UART_IMR_RXSTALE); + msm_write(port, msm_port->imr, MSM_UART_IMR); if (dma->chan) msm_stop_dma(port, dma); @@ -707,8 +707,8 @@ static void msm_enable_ms(struct uart_port *port) { struct msm_port *msm_port = to_msm_port(port); - msm_port->imr |= UART_IMR_DELTA_CTS; - msm_write(port, msm_port->imr, UART_IMR); + msm_port->imr |= MSM_UART_IMR_DELTA_CTS; + msm_write(port, msm_port->imr, MSM_UART_IMR); } static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr) @@ -719,18 +719,18 @@ static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr) int count = 0; struct msm_port *msm_port = to_msm_port(port); - if ((msm_read(port, UART_SR) & UART_SR_OVERRUN)) { + if ((msm_read(port, MSM_UART_SR) & MSM_UART_SR_OVERRUN)) { port->icount.overrun++; tty_insert_flip_char(tport, 0, TTY_OVERRUN); - msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR); + msm_write(port, MSM_UART_CR_CMD_RESET_ERR, MSM_UART_CR); } - if (misr & UART_IMR_RXSTALE) { + if (misr & MSM_UART_IMR_RXSTALE) { count = msm_read(port, UARTDM_RX_TOTAL_SNAP) - msm_port->old_snap_state; msm_port->old_snap_state = 0; } else { - count = 4 * (msm_read(port, UART_RFWR)); + count = 4 * (msm_read(port, MSM_UART_RFWR)); msm_port->old_snap_state += count; } @@ -742,8 +742,8 @@ static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr) unsigned char buf[4]; int sysrq, r_count, i; - sr = msm_read(port, UART_SR); - if ((sr & UART_SR_RX_READY) == 0) { + sr = msm_read(port, MSM_UART_SR); + if ((sr & MSM_UART_SR_RX_READY) == 0) { msm_port->old_snap_state -= count; break; } @@ -762,7 +762,7 @@ static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr) continue; } - if (!(port->read_status_mask & UART_SR_RX_BREAK)) + if (!(port->read_status_mask & MSM_UART_SR_RX_BREAK)) flag = TTY_NORMAL; spin_unlock(&port->lock); @@ -776,10 +776,10 @@ static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr) tty_flip_buffer_push(tport); - if (misr & (UART_IMR_RXSTALE)) - msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR); + if (misr & (MSM_UART_IMR_RXSTALE)) + msm_write(port, MSM_UART_CR_CMD_RESET_STALE_INT, MSM_UART_CR); msm_write(port, 0xFFFFFF, UARTDM_DMRX); - msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR); + msm_write(port, MSM_UART_CR_CMD_STALE_EVENT_ENABLE, MSM_UART_CR); /* Try to use DMA */ msm_start_rx_dma(msm_port); @@ -795,25 +795,25 @@ static void msm_handle_rx(struct uart_port *port) * Handle overrun. My understanding of the hardware is that overrun * is not tied to the RX buffer, so we handle the case out of band. */ - if ((msm_read(port, UART_SR) & UART_SR_OVERRUN)) { + if ((msm_read(port, MSM_UART_SR) & MSM_UART_SR_OVERRUN)) { port->icount.overrun++; tty_insert_flip_char(tport, 0, TTY_OVERRUN); - msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR); + msm_write(port, MSM_UART_CR_CMD_RESET_ERR, MSM_UART_CR); } /* and now the main RX loop */ - while ((sr = msm_read(port, UART_SR)) & UART_SR_RX_READY) { + while ((sr = msm_read(port, MSM_UART_SR)) & MSM_UART_SR_RX_READY) { unsigned int c; char flag = TTY_NORMAL; int sysrq; - c = msm_read(port, UART_RF); + c = msm_read(port, MSM_UART_RF); - if (sr & UART_SR_RX_BREAK) { + if (sr & MSM_UART_SR_RX_BREAK) { port->icount.brk++; if (uart_handle_break(port)) continue; - } else if (sr & UART_SR_PAR_FRAME_ERR) { + } else if (sr & MSM_UART_SR_PAR_FRAME_ERR) { port->icount.frame++; } else { port->icount.rx++; @@ -822,9 +822,9 @@ static void msm_handle_rx(struct uart_port *port) /* Mask conditions we're ignorning. */ sr &= port->read_status_mask; - if (sr & UART_SR_RX_BREAK) + if (sr & MSM_UART_SR_RX_BREAK) flag = TTY_BREAK; - else if (sr & UART_SR_PAR_FRAME_ERR) + else if (sr & MSM_UART_SR_PAR_FRAME_ERR) flag = TTY_FRAME; spin_unlock(&port->lock); @@ -848,7 +848,7 @@ static void msm_handle_tx_pio(struct uart_port *port, unsigned int tx_count) if (msm_port->is_uartdm) tf = port->membase + UARTDM_TF; else - tf = port->membase + UART_TF; + tf = port->membase + MSM_UART_TF; if (tx_count && msm_port->is_uartdm) msm_reset_dm_count(port, tx_count); @@ -857,7 +857,7 @@ static void msm_handle_tx_pio(struct uart_port *port, unsigned int tx_count) int i; char buf[4] = { 0 }; - if (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) + if (!(msm_read(port, MSM_UART_SR) & MSM_UART_SR_TX_READY)) break; if (msm_port->is_uartdm) @@ -898,7 +898,7 @@ static void msm_handle_tx(struct uart_port *port) if (msm_port->is_uartdm) tf = port->membase + UARTDM_TF; else - tf = port->membase + UART_TF; + tf = port->membase + MSM_UART_TF; buf[0] = port->x_char; @@ -942,7 +942,7 @@ static void msm_handle_tx(struct uart_port *port) static void msm_handle_delta_cts(struct uart_port *port) { - msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR); + msm_write(port, MSM_UART_CR_CMD_RESET_CTS, MSM_UART_CR); port->icount.cts++; wake_up_interruptible(&port->state->port.delta_msr_wait); } @@ -957,20 +957,20 @@ static irqreturn_t msm_uart_irq(int irq, void *dev_id) u32 val; spin_lock_irqsave(&port->lock, flags); - misr = msm_read(port, UART_MISR); - msm_write(port, 0, UART_IMR); /* disable interrupt */ + misr = msm_read(port, MSM_UART_MISR); + msm_write(port, 0, MSM_UART_IMR); /* disable interrupt */ - if (misr & UART_IMR_RXBREAK_START) { + if (misr & MSM_UART_IMR_RXBREAK_START) { msm_port->break_detected = true; - msm_write(port, UART_CR_CMD_RESET_RXBREAK_START, UART_CR); + msm_write(port, MSM_UART_CR_CMD_RESET_RXBREAK_START, MSM_UART_CR); } - if (misr & (UART_IMR_RXLEV | UART_IMR_RXSTALE)) { + if (misr & (MSM_UART_IMR_RXLEV | MSM_UART_IMR_RXSTALE)) { if (dma->count) { - val = UART_CR_CMD_STALE_EVENT_DISABLE; - msm_write(port, val, UART_CR); - val = UART_CR_CMD_RESET_STALE_INT; - msm_write(port, val, UART_CR); + val = MSM_UART_CR_CMD_STALE_EVENT_DISABLE; + msm_write(port, val, MSM_UART_CR); + val = MSM_UART_CR_CMD_RESET_STALE_INT; + msm_write(port, val, MSM_UART_CR); /* * Flush DMA input fifo to memory, this will also * trigger DMA RX completion @@ -982,12 +982,12 @@ static irqreturn_t msm_uart_irq(int irq, void *dev_id) msm_handle_rx(port); } } - if (misr & UART_IMR_TXLEV) + if (misr & MSM_UART_IMR_TXLEV) msm_handle_tx(port); - if (misr & UART_IMR_DELTA_CTS) + if (misr & MSM_UART_IMR_DELTA_CTS) msm_handle_delta_cts(port); - msm_write(port, msm_port->imr, UART_IMR); /* restore interrupt */ + msm_write(port, msm_port->imr, MSM_UART_IMR); /* restore interrupt */ spin_unlock_irqrestore(&port->lock, flags); return IRQ_HANDLED; @@ -995,7 +995,7 @@ static irqreturn_t msm_uart_irq(int irq, void *dev_id) static unsigned int msm_tx_empty(struct uart_port *port) { - return (msm_read(port, UART_SR) & UART_SR_TX_EMPTY) ? TIOCSER_TEMT : 0; + return (msm_read(port, MSM_UART_SR) & MSM_UART_SR_TX_EMPTY) ? TIOCSER_TEMT : 0; } static unsigned int msm_get_mctrl(struct uart_port *port) @@ -1009,15 +1009,15 @@ static void msm_reset(struct uart_port *port) unsigned int mr; /* reset everything */ - msm_write(port, UART_CR_CMD_RESET_RX, UART_CR); - msm_write(port, UART_CR_CMD_RESET_TX, UART_CR); - msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR); - msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR); - msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR); - msm_write(port, UART_CR_CMD_RESET_RFR, UART_CR); - mr = msm_read(port, UART_MR1); - mr &= ~UART_MR1_RX_RDY_CTL; - msm_write(port, mr, UART_MR1); + msm_write(port, MSM_UART_CR_CMD_RESET_RX, MSM_UART_CR); + msm_write(port, MSM_UART_CR_CMD_RESET_TX, MSM_UART_CR); + msm_write(port, MSM_UART_CR_CMD_RESET_ERR, MSM_UART_CR); + msm_write(port, MSM_UART_CR_CMD_RESET_BREAK_INT, MSM_UART_CR); + msm_write(port, MSM_UART_CR_CMD_RESET_CTS, MSM_UART_CR); + msm_write(port, MSM_UART_CR_CMD_RESET_RFR, MSM_UART_CR); + mr = msm_read(port, MSM_UART_MR1); + mr &= ~MSM_UART_MR1_RX_RDY_CTL; + msm_write(port, mr, MSM_UART_MR1); /* Disable DM modes */ if (msm_port->is_uartdm) @@ -1028,24 +1028,24 @@ static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl) { unsigned int mr; - mr = msm_read(port, UART_MR1); + mr = msm_read(port, MSM_UART_MR1); if (!(mctrl & TIOCM_RTS)) { - mr &= ~UART_MR1_RX_RDY_CTL; - msm_write(port, mr, UART_MR1); - msm_write(port, UART_CR_CMD_RESET_RFR, UART_CR); + mr &= ~MSM_UART_MR1_RX_RDY_CTL; + msm_write(port, mr, MSM_UART_MR1); + msm_write(port, MSM_UART_CR_CMD_RESET_RFR, MSM_UART_CR); } else { - mr |= UART_MR1_RX_RDY_CTL; - msm_write(port, mr, UART_MR1); + mr |= MSM_UART_MR1_RX_RDY_CTL; + msm_write(port, mr, MSM_UART_MR1); } } static void msm_break_ctl(struct uart_port *port, int break_ctl) { if (break_ctl) - msm_write(port, UART_CR_CMD_START_BREAK, UART_CR); + msm_write(port, MSM_UART_CR_CMD_START_BREAK, MSM_UART_CR); else - msm_write(port, UART_CR_CMD_STOP_BREAK, UART_CR); + msm_write(port, MSM_UART_CR_CMD_STOP_BREAK, MSM_UART_CR); } struct msm_baud_map { @@ -1142,45 +1142,45 @@ static int msm_set_baud_rate(struct uart_port *port, unsigned int baud, *saved_flags = flags; port->uartclk = rate; - msm_write(port, entry->code, UART_CSR); + msm_write(port, entry->code, MSM_UART_CSR); /* RX stale watermark */ rxstale = entry->rxstale; - watermark = UART_IPR_STALE_LSB & rxstale; + watermark = MSM_UART_IPR_STALE_LSB & rxstale; if (msm_port->is_uartdm) { - mask = UART_DM_IPR_STALE_TIMEOUT_MSB; + mask = MSM_UART_DM_IPR_STALE_TIMEOUT_MSB; } else { - watermark |= UART_IPR_RXSTALE_LAST; - mask = UART_IPR_STALE_TIMEOUT_MSB; + watermark |= MSM_UART_IPR_RXSTALE_LAST; + mask = MSM_UART_IPR_STALE_TIMEOUT_MSB; } watermark |= mask & (rxstale << 2); - msm_write(port, watermark, UART_IPR); + msm_write(port, watermark, MSM_UART_IPR); /* set RX watermark */ watermark = (port->fifosize * 3) / 4; - msm_write(port, watermark, UART_RFWR); + msm_write(port, watermark, MSM_UART_RFWR); /* set TX watermark */ - msm_write(port, 10, UART_TFWR); + msm_write(port, 10, MSM_UART_TFWR); - msm_write(port, UART_CR_CMD_PROTECTION_EN, UART_CR); + msm_write(port, MSM_UART_CR_CMD_PROTECTION_EN, MSM_UART_CR); msm_reset(port); /* Enable RX and TX */ - msm_write(port, UART_CR_TX_ENABLE | UART_CR_RX_ENABLE, UART_CR); + msm_write(port, MSM_UART_CR_TX_ENABLE | MSM_UART_CR_RX_ENABLE, MSM_UART_CR); /* turn on RX and CTS interrupts */ - msm_port->imr = UART_IMR_RXLEV | UART_IMR_RXSTALE | - UART_IMR_CURRENT_CTS | UART_IMR_RXBREAK_START; + msm_port->imr = MSM_UART_IMR_RXLEV | MSM_UART_IMR_RXSTALE | + MSM_UART_IMR_CURRENT_CTS | MSM_UART_IMR_RXBREAK_START; - msm_write(port, msm_port->imr, UART_IMR); + msm_write(port, msm_port->imr, MSM_UART_IMR); if (msm_port->is_uartdm) { - msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR); + msm_write(port, MSM_UART_CR_CMD_RESET_STALE_INT, MSM_UART_CR); msm_write(port, 0xFFFFFF, UARTDM_DMRX); - msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR); + msm_write(port, MSM_UART_CR_CMD_STALE_EVENT_ENABLE, MSM_UART_CR); } return baud; @@ -1212,18 +1212,18 @@ static int msm_startup(struct uart_port *port) rfr_level = port->fifosize; /* set automatic RFR level */ - data = msm_read(port, UART_MR1); + data = msm_read(port, MSM_UART_MR1); if (msm_port->is_uartdm) - mask = UART_DM_MR1_AUTO_RFR_LEVEL1; + mask = MSM_UART_DM_MR1_AUTO_RFR_LEVEL1; else - mask = UART_MR1_AUTO_RFR_LEVEL1; + mask = MSM_UART_MR1_AUTO_RFR_LEVEL1; data &= ~mask; - data &= ~UART_MR1_AUTO_RFR_LEVEL0; + data &= ~MSM_UART_MR1_AUTO_RFR_LEVEL0; data |= mask & (rfr_level << 2); - data |= UART_MR1_AUTO_RFR_LEVEL0 & rfr_level; - msm_write(port, data, UART_MR1); + data |= MSM_UART_MR1_AUTO_RFR_LEVEL0 & rfr_level; + msm_write(port, data, MSM_UART_MR1); if (msm_port->is_uartdm) { msm_request_tx_dma(msm_port, msm_port->uart.mapbase); @@ -1252,7 +1252,7 @@ static void msm_shutdown(struct uart_port *port) struct msm_port *msm_port = to_msm_port(port); msm_port->imr = 0; - msm_write(port, 0, UART_IMR); /* disable interrupts */ + msm_write(port, 0, MSM_UART_IMR); /* disable interrupts */ if (msm_port->is_uartdm) msm_release_dma(msm_port); @@ -1282,60 +1282,60 @@ static void msm_set_termios(struct uart_port *port, struct ktermios *termios, tty_termios_encode_baud_rate(termios, baud, baud); /* calculate parity */ - mr = msm_read(port, UART_MR2); - mr &= ~UART_MR2_PARITY_MODE; + mr = msm_read(port, MSM_UART_MR2); + mr &= ~MSM_UART_MR2_PARITY_MODE; if (termios->c_cflag & PARENB) { if (termios->c_cflag & PARODD) - mr |= UART_MR2_PARITY_MODE_ODD; + mr |= MSM_UART_MR2_PARITY_MODE_ODD; else if (termios->c_cflag & CMSPAR) - mr |= UART_MR2_PARITY_MODE_SPACE; + mr |= MSM_UART_MR2_PARITY_MODE_SPACE; else - mr |= UART_MR2_PARITY_MODE_EVEN; + mr |= MSM_UART_MR2_PARITY_MODE_EVEN; } /* calculate bits per char */ - mr &= ~UART_MR2_BITS_PER_CHAR; + mr &= ~MSM_UART_MR2_BITS_PER_CHAR; switch (termios->c_cflag & CSIZE) { case CS5: - mr |= UART_MR2_BITS_PER_CHAR_5; + mr |= MSM_UART_MR2_BITS_PER_CHAR_5; break; case CS6: - mr |= UART_MR2_BITS_PER_CHAR_6; + mr |= MSM_UART_MR2_BITS_PER_CHAR_6; break; case CS7: - mr |= UART_MR2_BITS_PER_CHAR_7; + mr |= MSM_UART_MR2_BITS_PER_CHAR_7; break; case CS8: default: - mr |= UART_MR2_BITS_PER_CHAR_8; + mr |= MSM_UART_MR2_BITS_PER_CHAR_8; break; } /* calculate stop bits */ - mr &= ~(UART_MR2_STOP_BIT_LEN_ONE | UART_MR2_STOP_BIT_LEN_TWO); + mr &= ~(MSM_UART_MR2_STOP_BIT_LEN_ONE | MSM_UART_MR2_STOP_BIT_LEN_TWO); if (termios->c_cflag & CSTOPB) - mr |= UART_MR2_STOP_BIT_LEN_TWO; + mr |= MSM_UART_MR2_STOP_BIT_LEN_TWO; else - mr |= UART_MR2_STOP_BIT_LEN_ONE; + mr |= MSM_UART_MR2_STOP_BIT_LEN_ONE; /* set parity, bits per char, and stop bit */ - msm_write(port, mr, UART_MR2); + msm_write(port, mr, MSM_UART_MR2); /* calculate and set hardware flow control */ - mr = msm_read(port, UART_MR1); - mr &= ~(UART_MR1_CTS_CTL | UART_MR1_RX_RDY_CTL); + mr = msm_read(port, MSM_UART_MR1); + mr &= ~(MSM_UART_MR1_CTS_CTL | MSM_UART_MR1_RX_RDY_CTL); if (termios->c_cflag & CRTSCTS) { - mr |= UART_MR1_CTS_CTL; - mr |= UART_MR1_RX_RDY_CTL; + mr |= MSM_UART_MR1_CTS_CTL; + mr |= MSM_UART_MR1_RX_RDY_CTL; } - msm_write(port, mr, UART_MR1); + msm_write(port, mr, MSM_UART_MR1); /* Configure status bits to ignore based on termio flags. */ port->read_status_mask = 0; if (termios->c_iflag & INPCK) - port->read_status_mask |= UART_SR_PAR_FRAME_ERR; + port->read_status_mask |= MSM_UART_SR_PAR_FRAME_ERR; if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) - port->read_status_mask |= UART_SR_RX_BREAK; + port->read_status_mask |= MSM_UART_SR_RX_BREAK; uart_update_timeout(port, termios->c_cflag, baud); @@ -1439,9 +1439,9 @@ static void msm_power(struct uart_port *port, unsigned int state, static int msm_poll_get_char_single(struct uart_port *port) { struct msm_port *msm_port = to_msm_port(port); - unsigned int rf_reg = msm_port->is_uartdm ? UARTDM_RF : UART_RF; + unsigned int rf_reg = msm_port->is_uartdm ? UARTDM_RF : MSM_UART_RF; - if (!(msm_read(port, UART_SR) & UART_SR_RX_READY)) + if (!(msm_read(port, MSM_UART_SR) & MSM_UART_SR_RX_READY)) return NO_POLL_CHAR; return msm_read(port, rf_reg) & 0xff; @@ -1459,7 +1459,7 @@ static int msm_poll_get_char_dm(struct uart_port *port) c = sp[sizeof(slop) - count]; count--; /* Or if FIFO is empty */ - } else if (!(msm_read(port, UART_SR) & UART_SR_RX_READY)) { + } else if (!(msm_read(port, MSM_UART_SR) & MSM_UART_SR_RX_READY)) { /* * If RX packing buffer has less than a word, force stale to * push contents into RX FIFO @@ -1467,14 +1467,13 @@ static int msm_poll_get_char_dm(struct uart_port *port) count = msm_read(port, UARTDM_RXFS); count = (count >> UARTDM_RXFS_BUF_SHIFT) & UARTDM_RXFS_BUF_MASK; if (count) { - msm_write(port, UART_CR_CMD_FORCE_STALE, UART_CR); + msm_write(port, MSM_UART_CR_CMD_FORCE_STALE, MSM_UART_CR); slop = msm_read(port, UARTDM_RF); c = sp[0]; count--; - msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR); + msm_write(port, MSM_UART_CR_CMD_RESET_STALE_INT, MSM_UART_CR); msm_write(port, 0xFFFFFF, UARTDM_DMRX); - msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, - UART_CR); + msm_write(port, MSM_UART_CR_CMD_STALE_EVENT_ENABLE, MSM_UART_CR); } else { c = NO_POLL_CHAR; } @@ -1495,8 +1494,8 @@ static int msm_poll_get_char(struct uart_port *port) struct msm_port *msm_port = to_msm_port(port); /* Disable all interrupts */ - imr = msm_read(port, UART_IMR); - msm_write(port, 0, UART_IMR); + imr = msm_read(port, MSM_UART_IMR); + msm_write(port, 0, MSM_UART_IMR); if (msm_port->is_uartdm) c = msm_poll_get_char_dm(port); @@ -1504,7 +1503,7 @@ static int msm_poll_get_char(struct uart_port *port) c = msm_poll_get_char_single(port); /* Enable interrupts */ - msm_write(port, imr, UART_IMR); + msm_write(port, imr, MSM_UART_IMR); return c; } @@ -1515,25 +1514,25 @@ static void msm_poll_put_char(struct uart_port *port, unsigned char c) struct msm_port *msm_port = to_msm_port(port); /* Disable all interrupts */ - imr = msm_read(port, UART_IMR); - msm_write(port, 0, UART_IMR); + imr = msm_read(port, MSM_UART_IMR); + msm_write(port, 0, MSM_UART_IMR); if (msm_port->is_uartdm) msm_reset_dm_count(port, 1); /* Wait until FIFO is empty */ - while (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) + while (!(msm_read(port, MSM_UART_SR) & MSM_UART_SR_TX_READY)) cpu_relax(); /* Write a character */ - msm_write(port, c, msm_port->is_uartdm ? UARTDM_TF : UART_TF); + msm_write(port, c, msm_port->is_uartdm ? UARTDM_TF : MSM_UART_TF); /* Wait until FIFO is empty */ - while (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) + while (!(msm_read(port, MSM_UART_SR) & MSM_UART_SR_TX_READY)) cpu_relax(); /* Enable interrupts */ - msm_write(port, imr, UART_IMR); + msm_write(port, imr, MSM_UART_IMR); } #endif @@ -1591,7 +1590,7 @@ static struct msm_port msm_uart_ports[] = { }, }; -#define UART_NR ARRAY_SIZE(msm_uart_ports) +#define MSM_UART_NR ARRAY_SIZE(msm_uart_ports) static inline struct uart_port *msm_get_port_from_line(unsigned int line) { @@ -1612,7 +1611,7 @@ static void __msm_console_write(struct uart_port *port, const char *s, if (is_uartdm) tf = port->membase + UARTDM_TF; else - tf = port->membase + UART_TF; + tf = port->membase + MSM_UART_TF; /* Account for newlines that will get a carriage return added */ for (i = 0; i < count; i++) @@ -1658,7 +1657,7 @@ static void __msm_console_write(struct uart_port *port, const char *s, } } - while (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) + while (!(msm_read(port, MSM_UART_SR) & MSM_UART_SR_TX_READY)) cpu_relax(); iowrite32_rep(tf, buf, 1); @@ -1677,7 +1676,7 @@ static void msm_console_write(struct console *co, const char *s, struct uart_port *port; struct msm_port *msm_port; - BUG_ON(co->index < 0 || co->index >= UART_NR); + BUG_ON(co->index < 0 || co->index >= MSM_UART_NR); port = msm_get_port_from_line(co->index); msm_port = to_msm_port(port); @@ -1693,7 +1692,7 @@ static int msm_console_setup(struct console *co, char *options) int parity = 'n'; int flow = 'n'; - if (unlikely(co->index >= UART_NR || co->index < 0)) + if (unlikely(co->index >= MSM_UART_NR || co->index < 0)) return -ENXIO; port = msm_get_port_from_line(co->index); @@ -1774,7 +1773,7 @@ static struct uart_driver msm_uart_driver = { .owner = THIS_MODULE, .driver_name = "msm_serial", .dev_name = "ttyMSM", - .nr = UART_NR, + .nr = MSM_UART_NR, .cons = MSM_CONSOLE, }; @@ -1804,7 +1803,7 @@ static int msm_serial_probe(struct platform_device *pdev) if (line < 0) line = atomic_inc_return(&msm_uart_next_id) - 1; - if (unlikely(line < 0 || line >= UART_NR)) + if (unlikely(line < 0 || line >= MSM_UART_NR)) return -ENXIO; dev_info(&pdev->dev, "msm_serial: detected port #%d\n", line); -- cgit v1.2.3 From 27a1c39215a2f4f4ca6bae0dba1bebc8e16a01a0 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Fri, 24 Jun 2022 23:54:22 +0300 Subject: serial: 8250: Use C99 array initializer & define UART_REG_UNMAPPED MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use C99 array initializer insteads of comments and make unmapped checks more obvious. Reviewed-by: Jiri Slaby Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220624205424.12686-5-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 38 +++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 3a8747ec672b..1311b00f8194 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -336,27 +336,29 @@ static void default_serial_dl_write(struct uart_8250_port *up, int value) #ifdef CONFIG_SERIAL_8250_RT288X +#define UART_REG_UNMAPPED -1 + /* Au1x00/RT288x UART hardware has a weird register layout */ static const s8 au_io_in_map[8] = { - 0, /* UART_RX */ - 2, /* UART_IER */ - 3, /* UART_IIR */ - 5, /* UART_LCR */ - 6, /* UART_MCR */ - 7, /* UART_LSR */ - 8, /* UART_MSR */ - -1, /* UART_SCR (unmapped) */ + [UART_RX] = 0, + [UART_IER] = 2, + [UART_IIR] = 3, + [UART_LCR] = 5, + [UART_MCR] = 6, + [UART_LSR] = 7, + [UART_MSR] = 8, + [UART_SCR] = UART_REG_UNMAPPED, }; static const s8 au_io_out_map[8] = { - 1, /* UART_TX */ - 2, /* UART_IER */ - 4, /* UART_FCR */ - 5, /* UART_LCR */ - 6, /* UART_MCR */ - -1, /* UART_LSR (unmapped) */ - -1, /* UART_MSR (unmapped) */ - -1, /* UART_SCR (unmapped) */ + [UART_TX] = 1, + [UART_IER] = 2, + [UART_FCR] = 4, + [UART_LCR] = 5, + [UART_MCR] = 6, + [UART_LSR] = UART_REG_UNMAPPED, + [UART_MSR] = UART_REG_UNMAPPED, + [UART_SCR] = UART_REG_UNMAPPED, }; unsigned int au_serial_in(struct uart_port *p, int offset) @@ -364,7 +366,7 @@ unsigned int au_serial_in(struct uart_port *p, int offset) if (offset >= ARRAY_SIZE(au_io_in_map)) return UINT_MAX; offset = au_io_in_map[offset]; - if (offset < 0) + if (offset == UART_REG_UNMAPPED) return UINT_MAX; return __raw_readl(p->membase + (offset << p->regshift)); } @@ -374,7 +376,7 @@ void au_serial_out(struct uart_port *p, int offset, int value) if (offset >= ARRAY_SIZE(au_io_out_map)) return; offset = au_io_out_map[offset]; - if (offset < 0) + if (offset == UART_REG_UNMAPPED) return; __raw_writel(value, p->membase + (offset << p->regshift)); } -- cgit v1.2.3 From eb47b59afb7e46c952d7b03884245364990d4910 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Fri, 24 Jun 2022 23:54:23 +0300 Subject: serial: Convert SERIAL_XMIT_SIZE to UART_XMIT_SIZE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both UART_XMIT_SIZE and SERIAL_XMIT_SIZE are defined. Make them all UART_XMIT_SIZE. Reviewed-by: Jiri Slaby Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220624205424.12686-6-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/amiserial.c | 18 +++++++++--------- drivers/tty/mips_ejtag_fdc.c | 2 +- drivers/tty/serial/meson_uart.c | 2 +- drivers/tty/serial/owl-uart.c | 2 +- drivers/tty/serial/rda-uart.c | 2 +- include/linux/serial.h | 6 ------ 6 files changed, 13 insertions(+), 19 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index afb2d373dd47..5458e2b1c125 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -283,12 +284,12 @@ static void transmit_chars(struct serial_state *info) amiga_custom.serdat = info->xmit.buf[info->xmit.tail++] | 0x100; mb(); - info->xmit.tail = info->xmit.tail & (SERIAL_XMIT_SIZE-1); + info->xmit.tail = info->xmit.tail & (UART_XMIT_SIZE - 1); info->icount.tx++; if (CIRC_CNT(info->xmit.head, info->xmit.tail, - SERIAL_XMIT_SIZE) < WAKEUP_CHARS) + UART_XMIT_SIZE) < WAKEUP_CHARS) tty_wakeup(info->tport.tty); #ifdef SERIAL_DEBUG_INTR @@ -708,13 +709,13 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch) local_irq_save(flags); if (CIRC_SPACE(info->xmit.head, info->xmit.tail, - SERIAL_XMIT_SIZE) == 0) { + UART_XMIT_SIZE) == 0) { local_irq_restore(flags); return 0; } info->xmit.buf[info->xmit.head++] = ch; - info->xmit.head &= SERIAL_XMIT_SIZE-1; + info->xmit.head &= UART_XMIT_SIZE - 1; local_irq_restore(flags); return 1; } @@ -753,15 +754,14 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count while (1) { c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, - SERIAL_XMIT_SIZE); + UART_XMIT_SIZE); if (count < c) c = count; if (c <= 0) { break; } memcpy(info->xmit.buf + info->xmit.head, buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); + info->xmit.head = (info->xmit.head + c) & (UART_XMIT_SIZE - 1); buf += c; count -= c; ret += c; @@ -788,14 +788,14 @@ static unsigned int rs_write_room(struct tty_struct *tty) { struct serial_state *info = tty->driver_data; - return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); + return CIRC_SPACE(info->xmit.head, info->xmit.tail, UART_XMIT_SIZE); } static unsigned int rs_chars_in_buffer(struct tty_struct *tty) { struct serial_state *info = tty->driver_data; - return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); + return CIRC_CNT(info->xmit.head, info->xmit.tail, UART_XMIT_SIZE); } static void rs_flush_buffer(struct tty_struct *tty) diff --git a/drivers/tty/mips_ejtag_fdc.c b/drivers/tty/mips_ejtag_fdc.c index 49907427a165..e81701a66429 100644 --- a/drivers/tty/mips_ejtag_fdc.c +++ b/drivers/tty/mips_ejtag_fdc.c @@ -916,7 +916,7 @@ static int mips_ejtag_fdc_tty_probe(struct mips_cdmm_device *dev) mips_ejtag_fdc_write(priv, REG_FDCFG, cfg); /* Make each port's xmit FIFO big enough to fill FDC TX FIFO */ - priv->xmit_size = min(tx_fifo * 4, (unsigned int)SERIAL_XMIT_SIZE); + priv->xmit_size = min(tx_fifo * 4, (unsigned int)UART_XMIT_SIZE); driver = tty_alloc_driver(NUM_TTY_CHANNELS, TTY_DRIVER_REAL_RAW); if (IS_ERR(driver)) diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index 4869c0059c98..6c8db19fd572 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -162,7 +162,7 @@ static void meson_uart_start_tx(struct uart_port *port) ch = xmit->buf[xmit->tail]; writel(ch, port->membase + AML_UART_WFIFO); - xmit->tail = (xmit->tail+1) & (SERIAL_XMIT_SIZE - 1); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; } diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c index 44d20e5a7dd3..888e17e3f25f 100644 --- a/drivers/tty/serial/owl-uart.c +++ b/drivers/tty/serial/owl-uart.c @@ -201,7 +201,7 @@ static void owl_uart_send_chars(struct uart_port *port) ch = xmit->buf[xmit->tail]; owl_uart_write(port, ch, OWL_UART_TXDAT); - xmit->tail = (xmit->tail + 1) & (SERIAL_XMIT_SIZE - 1); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; } diff --git a/drivers/tty/serial/rda-uart.c b/drivers/tty/serial/rda-uart.c index f556b4955f59..feb2054aba37 100644 --- a/drivers/tty/serial/rda-uart.c +++ b/drivers/tty/serial/rda-uart.c @@ -353,7 +353,7 @@ static void rda_uart_send_chars(struct uart_port *port) ch = xmit->buf[xmit->tail]; rda_uart_write(port, ch, RDA_UART_RXTX_BUFFER); - xmit->tail = (xmit->tail + 1) & (SERIAL_XMIT_SIZE - 1); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; } diff --git a/include/linux/serial.h b/include/linux/serial.h index 0b8b7d7c8f33..70a9866e4abb 100644 --- a/include/linux/serial.h +++ b/include/linux/serial.h @@ -9,7 +9,6 @@ #ifndef _LINUX_SERIAL_H #define _LINUX_SERIAL_H -#include #include /* Helper for dealing with UART_LCR_WLEN* defines */ @@ -25,11 +24,6 @@ struct async_icount { __u32 buf_overrun; }; -/* - * The size of the serial xmit buffer is 1 page, or 4096 bytes - */ -#define SERIAL_XMIT_SIZE PAGE_SIZE - #include #endif /* _LINUX_SERIAL_H */ -- cgit v1.2.3 From 34619de1b8cb52afa90bbeb3b4fbad34c28f19cf Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Fri, 24 Jun 2022 23:54:24 +0300 Subject: serial: Consolidate BOTH_EMPTY use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per file BOTH_EMPTY defines are littering our source code here and there. Define once in serial.h and create helper for the check too. Reviewed-by: Jiri Slaby Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220624205424.12686-7-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- arch/mips/ath79/early_printk.c | 9 +++++---- drivers/accessibility/speakup/serialio.h | 3 +-- drivers/tty/serial/8250/8250_early.c | 4 +--- drivers/tty/serial/8250/8250_port.c | 12 +++++------- drivers/tty/serial/omap-serial.c | 7 +++---- drivers/tty/serial/pch_uart.c | 7 +++---- drivers/tty/serial/pxa.c | 5 ++--- drivers/tty/serial/sunsu.c | 4 +--- drivers/tty/serial/vr41xx_siu.c | 4 +--- include/linux/serial.h | 9 +++++++++ 10 files changed, 31 insertions(+), 33 deletions(-) (limited to 'drivers/tty/serial') diff --git a/arch/mips/ath79/early_printk.c b/arch/mips/ath79/early_printk.c index 8751d067f98f..f6d02b425a10 100644 --- a/arch/mips/ath79/early_printk.c +++ b/arch/mips/ath79/early_printk.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -29,15 +30,15 @@ static inline void prom_putchar_wait(void __iomem *reg, u32 mask, u32 val) } while (1); } -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) - static void prom_putchar_ar71xx(char ch) { void __iomem *base = (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE)); - prom_putchar_wait(base + UART_LSR * 4, BOTH_EMPTY, BOTH_EMPTY); + prom_putchar_wait(base + UART_LSR * 4, UART_LSR_BOTH_EMPTY, + UART_LSR_BOTH_EMPTY); __raw_writel((unsigned char)ch, base + UART_TX * 4); - prom_putchar_wait(base + UART_LSR * 4, BOTH_EMPTY, BOTH_EMPTY); + prom_putchar_wait(base + UART_LSR * 4, UART_LSR_BOTH_EMPTY, + UART_LSR_BOTH_EMPTY); } static void prom_putchar_ar933x(char ch) diff --git a/drivers/accessibility/speakup/serialio.h b/drivers/accessibility/speakup/serialio.h index 6f8f86f161bb..b4f9a1925b81 100644 --- a/drivers/accessibility/speakup/serialio.h +++ b/drivers/accessibility/speakup/serialio.h @@ -33,9 +33,8 @@ struct old_serial_port { #define NUM_DISABLE_TIMEOUTS 3 /* buffer timeout in ms */ #define SPK_TIMEOUT 100 -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) #define spk_serial_tx_busy() \ - ((inb(speakup_info.port_tts + UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY) + (!uart_lsr_tx_empty(inb(speakup_info.port_tts + UART_LSR))) #endif diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c index e52585064565..f271becfc46c 100644 --- a/drivers/tty/serial/8250/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c @@ -84,8 +84,6 @@ static void serial8250_early_out(struct uart_port *port, int offset, int value) } } -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) - static void serial_putc(struct uart_port *port, unsigned char c) { unsigned int status; @@ -94,7 +92,7 @@ static void serial_putc(struct uart_port *port, unsigned char c) for (;;) { status = serial8250_early_in(port, UART_LSR); - if ((status & BOTH_EMPTY) == BOTH_EMPTY) + if (uart_lsr_tx_empty(status)) break; cpu_relax(); } diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 1311b00f8194..55b252954a92 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -50,8 +50,6 @@ #define DEBUG_AUTOCONF(fmt...) do { } while (0) #endif -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) - /* * Here we define the default xmit fifo size used for each type of UART. */ @@ -1843,7 +1841,7 @@ void serial8250_tx_chars(struct uart_8250_port *up) if (uart_circ_empty(xmit)) break; if ((up->capabilities & UART_CAP_HFIFO) && - (serial_in(up, UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY) + !uart_lsr_tx_empty(serial_in(up, UART_LSR))) break; /* The BCM2835 MINI UART THRE bit is really a not-full bit. */ if ((up->capabilities & UART_CAP_MINI) && @@ -2003,7 +2001,7 @@ static unsigned int serial8250_tx_empty(struct uart_port *port) serial8250_rpm_put(up); - return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0; + return uart_lsr_tx_empty(lsr) ? TIOCSER_TEMT : 0; } unsigned int serial8250_do_get_mctrl(struct uart_port *port) @@ -2151,7 +2149,7 @@ static void serial8250_put_poll_char(struct uart_port *port, else serial_port_out(port, UART_IER, 0); - wait_for_xmitr(up, BOTH_EMPTY); + wait_for_xmitr(up, UART_LSR_BOTH_EMPTY); /* * Send the character out. */ @@ -2161,7 +2159,7 @@ static void serial8250_put_poll_char(struct uart_port *port, * Finally, wait for transmitter to become empty * and restore the IER */ - wait_for_xmitr(up, BOTH_EMPTY); + wait_for_xmitr(up, UART_LSR_BOTH_EMPTY); serial_port_out(port, UART_IER, ier); serial8250_rpm_put(up); } @@ -3431,7 +3429,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, * Finally, wait for transmitter to become empty * and restore the IER */ - wait_for_xmitr(up, BOTH_EMPTY); + wait_for_xmitr(up, UART_LSR_BOTH_EMPTY); if (em485) { mdelay(port->rs485.delay_rts_after_send); diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 98622c35d896..52cb1a68b053 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -1102,8 +1103,6 @@ serial_omap_type(struct uart_port *port) return up->name; } -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) - static void __maybe_unused wait_for_xmitr(struct uart_omap_port *up) { unsigned int status, tmout = 10000; @@ -1118,7 +1117,7 @@ static void __maybe_unused wait_for_xmitr(struct uart_omap_port *up) if (--tmout == 0) break; udelay(1); - } while ((status & BOTH_EMPTY) != BOTH_EMPTY); + } while (!uart_lsr_tx_empty(status)); /* Wait up to 1s for flow control if necessary */ if (up->port.flags & UPF_CONS_FLOW) { @@ -1186,7 +1185,7 @@ static void omap_serial_early_putc(struct uart_port *port, unsigned char c) for (;;) { status = omap_serial_early_in(port, UART_LSR); - if ((status & BOTH_EMPTY) == BOTH_EMPTY) + if (uart_lsr_tx_empty(status)) break; cpu_relax(); } diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 3b26524d48e3..8a9065e4a903 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -3,6 +3,7 @@ *Copyright (C) 2011 LAPIS Semiconductor Co., Ltd. */ #include +#include #include #include #include @@ -189,8 +190,6 @@ enum { #define PCH_UART_HAL_LOOP (PCH_UART_MCR_LOOP) #define PCH_UART_HAL_AFE (PCH_UART_MCR_AFE) -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) - #define DEFAULT_UARTCLK 1843200 /* 1.8432 MHz */ #define CMITC_UARTCLK 192000000 /* 192.0000 MHz */ #define FRI2_64_UARTCLK 64000000 /* 64.0000 MHz */ @@ -1516,7 +1515,7 @@ static void pch_uart_put_poll_char(struct uart_port *port, * Finally, wait for transmitter to become empty * and restore the IER */ - wait_for_xmitr(priv, BOTH_EMPTY); + wait_for_xmitr(priv, UART_LSR_BOTH_EMPTY); iowrite8(ier, priv->membase + UART_IER); } #endif /* CONFIG_CONSOLE_POLL */ @@ -1602,7 +1601,7 @@ pch_console_write(struct console *co, const char *s, unsigned int count) * Finally, wait for transmitter to become empty * and restore the IER */ - wait_for_xmitr(priv, BOTH_EMPTY); + wait_for_xmitr(priv, UART_LSR_BOTH_EMPTY); iowrite8(ier, priv->membase + UART_IER); if (port_locked) diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c index e80ba8e10407..9309ffd87c8e 100644 --- a/drivers/tty/serial/pxa.c +++ b/drivers/tty/serial/pxa.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -575,8 +576,6 @@ static struct uart_driver serial_pxa_reg; #ifdef CONFIG_SERIAL_PXA_CONSOLE -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) - /* * Wait for transmitter & holding register to empty */ @@ -594,7 +593,7 @@ static void wait_for_xmitr(struct uart_pxa_port *up) if (--tmout == 0) break; udelay(1); - } while ((status & BOTH_EMPTY) != BOTH_EMPTY); + } while (!uart_lsr_tx_empty(status)); /* Wait up to 1s for flow control if necessary */ if (up->port.flags & UPF_CONS_FLOW) { diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index fff50b5b82eb..84d545e5a8c7 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c @@ -1249,8 +1249,6 @@ static int sunsu_kbd_ms_init(struct uart_sunsu_port *up) #ifdef CONFIG_SERIAL_SUNSU_CONSOLE -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) - /* * Wait for transmitter & holding register to empty */ @@ -1268,7 +1266,7 @@ static void wait_for_xmitr(struct uart_sunsu_port *up) if (--tmout == 0) break; udelay(1); - } while ((status & BOTH_EMPTY) != BOTH_EMPTY); + } while (!uart_lsr_tx_empty(status)); /* Wait up to 1s for flow control if necessary */ if (up->port.flags & UPF_CONS_FLOW) { diff --git a/drivers/tty/serial/vr41xx_siu.c b/drivers/tty/serial/vr41xx_siu.c index e0bf003ca3a1..1ba689a81abd 100644 --- a/drivers/tty/serial/vr41xx_siu.c +++ b/drivers/tty/serial/vr41xx_siu.c @@ -703,8 +703,6 @@ static int siu_init_ports(struct platform_device *pdev) #ifdef CONFIG_SERIAL_VR41XX_CONSOLE -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) - static void wait_for_xmitr(struct uart_port *port) { int timeout = 10000; @@ -715,7 +713,7 @@ static void wait_for_xmitr(struct uart_port *port) if (lsr & UART_LSR_BI) lsr_break_flag[port->line] = UART_LSR_BI; - if ((lsr & BOTH_EMPTY) == BOTH_EMPTY) + if (uart_lsr_tx_empty(lsr)) break; } while (timeout-- > 0); diff --git a/include/linux/serial.h b/include/linux/serial.h index 70a9866e4abb..3d6fe3ef92cf 100644 --- a/include/linux/serial.h +++ b/include/linux/serial.h @@ -10,10 +10,19 @@ #define _LINUX_SERIAL_H #include +#include /* Helper for dealing with UART_LCR_WLEN* defines */ #define UART_LCR_WLEN(x) ((x) - 5) +/* FIFO and shifting register empty */ +#define UART_LSR_BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + +static inline bool uart_lsr_tx_empty(u16 lsr) +{ + return (lsr & UART_LSR_BOTH_EMPTY) == UART_LSR_BOTH_EMPTY; +} + /* * Counters of the input lines (CTS, DSR, RI, CD) interrupts */ -- cgit v1.2.3 From f8ba5680a56be696b3f4343ed0a591abab807da4 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Fri, 24 Jun 2022 23:42:05 +0300 Subject: serial: 8250: make saved LSR larger MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DW flags address received as BIT(8) in LSR. In order to not lose that on read, enlarge lsr_saved_flags to u16. Adjust lsr/status variables and related call chains to use u16. Technically, some of these type conversion would not be needed but it doesn't hurt to be consistent. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220624204210.11112-2-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.h | 4 ++-- drivers/tty/serial/8250/8250_exar.c | 2 +- drivers/tty/serial/8250/8250_fsl.c | 2 +- drivers/tty/serial/8250/8250_ingenic.c | 2 +- drivers/tty/serial/8250/8250_omap.c | 7 +++---- drivers/tty/serial/8250/8250_port.c | 17 +++++++++-------- include/linux/serial_8250.h | 6 +++--- 7 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index b120da57c61f..0ff5688ba90c 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -133,9 +133,9 @@ static inline void serial_out(struct uart_8250_port *up, int offset, int value) * * Returns LSR value or'ed with the preserved flags (if any). */ -static inline unsigned int serial_lsr_in(struct uart_8250_port *up) +static inline u16 serial_lsr_in(struct uart_8250_port *up) { - unsigned int lsr = up->lsr_saved_flags; + u16 lsr = up->lsr_saved_flags; lsr |= serial_in(up, UART_LSR); up->lsr_saved_flags = lsr & LSR_SAVE_FLAGS; diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index 528779b40049..3d999eec4087 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -195,11 +195,11 @@ static int xr17v35x_startup(struct uart_port *port) static void exar_shutdown(struct uart_port *port) { - unsigned char lsr; bool tx_complete = false; struct uart_8250_port *up = up_to_u8250p(port); struct circ_buf *xmit = &port->state->xmit; int i = 0; + u16 lsr; do { lsr = serial_in(up, UART_LSR); diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c index 9c01c531349d..fd4005fcd0d6 100644 --- a/drivers/tty/serial/8250/8250_fsl.c +++ b/drivers/tty/serial/8250/8250_fsl.c @@ -25,8 +25,8 @@ int fsl8250_handle_irq(struct uart_port *port) { - unsigned char lsr, orig_lsr; unsigned long flags; + u16 lsr, orig_lsr; unsigned int iir; struct uart_8250_port *up = up_to_u8250p(port); diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c index cff91aa03f29..2b2f5d8d24b9 100644 --- a/drivers/tty/serial/8250/8250_ingenic.c +++ b/drivers/tty/serial/8250/8250_ingenic.c @@ -54,7 +54,7 @@ static void early_out(struct uart_port *port, int offset, uint8_t value) static void ingenic_early_console_putc(struct uart_port *port, unsigned char c) { - uint8_t lsr; + u16 lsr; do { lsr = early_in(port, UART_LSR); diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index ac8bfa042391..0dcecbbc3967 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -1115,8 +1115,7 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir) return omap_8250_rx_dma(up); } -static unsigned char omap_8250_handle_rx_dma(struct uart_8250_port *up, - u8 iir, unsigned char status) +static u16 omap_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir, u16 status) { if ((status & (UART_LSR_DR | UART_LSR_BI)) && (iir & UART_IIR_RDI)) { @@ -1130,7 +1129,7 @@ static unsigned char omap_8250_handle_rx_dma(struct uart_8250_port *up, } static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir, - unsigned char status) + u16 status) { /* * Queue a new transfer if FIFO has data. @@ -1164,7 +1163,7 @@ static int omap_8250_dma_handle_irq(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); struct omap8250_priv *priv = up->port.private_data; - unsigned char status; + u16 status; u8 iir; serial8250_rpm_get(up); diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 55b252954a92..c8ae0e8376d4 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1502,7 +1502,7 @@ static inline void __stop_tx(struct uart_8250_port *p) struct uart_8250_em485 *em485 = p->em485; if (em485) { - unsigned char lsr = serial_lsr_in(p); + u16 lsr = serial_lsr_in(p); u64 stop_delay = 0; p->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; @@ -1563,7 +1563,7 @@ static inline void __start_tx(struct uart_port *port) if (serial8250_set_THRI(up)) { if (up->bugs & UART_BUG_TXEN) { - unsigned char lsr = serial_lsr_in(up); + u16 lsr = serial_lsr_in(up); if (lsr & UART_LSR_THRE) serial8250_tx_chars(up); @@ -1716,7 +1716,7 @@ static void serial8250_enable_ms(struct uart_port *port) serial8250_rpm_put(up); } -void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr) +void serial8250_read_char(struct uart_8250_port *up, u16 lsr) { struct uart_port *port = &up->port; unsigned char ch; @@ -1785,7 +1785,7 @@ EXPORT_SYMBOL_GPL(serial8250_read_char); * (such as THRE) because the LSR value might come from an already consumed * character. */ -unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) +u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr) { struct uart_port *port = &up->port; int max_count = 256; @@ -1905,10 +1905,10 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir) */ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) { - unsigned char status; struct uart_8250_port *up = up_to_u8250p(port); bool skip_rx = false; unsigned long flags; + u16 status; if (iir & UART_IIR_NO_INT) return 0; @@ -1991,7 +1991,7 @@ static unsigned int serial8250_tx_empty(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); unsigned long flags; - unsigned int lsr; + u16 lsr; serial8250_rpm_get(up); @@ -2114,8 +2114,8 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits) static int serial8250_get_poll_char(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); - unsigned char lsr; int status; + u16 lsr; serial8250_rpm_get(up); @@ -2170,8 +2170,9 @@ int serial8250_do_startup(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); unsigned long flags; - unsigned char lsr, iir; + unsigned char iir; int retval; + u16 lsr; if (!port->fifosize) port->fifosize = uart_config[port->type].fifo_size; diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index ff84a3ed10ea..4565f25ba9a2 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -119,7 +119,7 @@ struct uart_8250_port { * be immediately processed. */ #define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS - unsigned char lsr_saved_flags; + u16 lsr_saved_flags; #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA unsigned char msr_saved_flags; @@ -170,8 +170,8 @@ extern void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, unsigned int quot_frac); extern int fsl8250_handle_irq(struct uart_port *port); int serial8250_handle_irq(struct uart_port *port, unsigned int iir); -unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr); -void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr); +u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr); +void serial8250_read_char(struct uart_8250_port *up, u16 lsr); void serial8250_tx_chars(struct uart_8250_port *up); unsigned int serial8250_modem_status(struct uart_8250_port *up); void serial8250_init_port(struct uart_8250_port *up); -- cgit v1.2.3 From 507bd6fbaaefcb8dd89bd00baddf00b439d30c51 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Fri, 24 Jun 2022 23:42:06 +0300 Subject: serial: 8250: create lsr_save_mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow drivers to alter LSR save mask. Reviewed-by: Andy Shevchenko Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220624204210.11112-3-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.h | 2 +- drivers/tty/serial/8250/8250_core.c | 4 ++++ drivers/tty/serial/8250/8250_dw.c | 2 +- include/linux/serial_8250.h | 1 + 4 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 0ff5688ba90c..5cc967fe3b59 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -138,7 +138,7 @@ static inline u16 serial_lsr_in(struct uart_8250_port *up) u16 lsr = up->lsr_saved_flags; lsr |= serial_in(up, UART_LSR); - up->lsr_saved_flags = lsr & LSR_SAVE_FLAGS; + up->lsr_saved_flags = lsr & up->lsr_save_mask; return lsr; } diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 90ddc8924811..57e86133af4f 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1007,6 +1007,7 @@ int serial8250_register_8250_port(const struct uart_8250_port *up) uart->port.rs485 = up->port.rs485; uart->rs485_start_tx = up->rs485_start_tx; uart->rs485_stop_tx = up->rs485_stop_tx; + uart->lsr_save_mask = up->lsr_save_mask; uart->dma = up->dma; /* Take tx_loadsz from fifosize if it wasn't set separately */ @@ -1094,6 +1095,9 @@ int serial8250_register_8250_port(const struct uart_8250_port *up) ret = 0; } + if (!uart->lsr_save_mask) + uart->lsr_save_mask = LSR_SAVE_FLAGS; /* Use default LSR mask */ + /* Initialise interrupt backoff work if required */ if (up->overrun_backoff_time_ms > 0) { uart->overrun_backoff_time_ms = diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 4cc69bb612ab..167a691c7b19 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -129,7 +129,7 @@ static void dw8250_tx_wait_empty(struct uart_port *p) while (tries--) { lsr = readb (p->membase + (UART_LSR << p->regshift)); - up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; + up->lsr_saved_flags |= lsr & up->lsr_save_mask; if (lsr & UART_LSR_TEMT) break; diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 4565f25ba9a2..8c7b793aa4d7 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -120,6 +120,7 @@ struct uart_8250_port { */ #define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS u16 lsr_saved_flags; + u16 lsr_save_mask; #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA unsigned char msr_saved_flags; -- cgit v1.2.3 From 79b3e69fa4a1c796d1002faf70da3280430eab61 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Fri, 24 Jun 2022 23:42:07 +0300 Subject: serial: 8250_lpss: Use 32-bit reads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use 32-bit reads in order to not lose higher bits of DW UART regs. This change does not fix any known issue as the high bits are not used for anything related to 8250 driver (dw8250_readl_ext and dw8250_writel_ext used within the dwlib are already doing readl/writel/ioread32be/iowrite32be anyway). This change is necessary to enables 9th bit address mode. DW UART reports address frames with BIT(8) of LSR. Reviewed-by: Andy Shevchenko Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220624204210.11112-4-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_lpss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c index 0f5af061e0b4..4ba43bef9933 100644 --- a/drivers/tty/serial/8250/8250_lpss.c +++ b/drivers/tty/serial/8250/8250_lpss.c @@ -330,7 +330,7 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id) uart.port.irq = pci_irq_vector(pdev, 0); uart.port.private_data = &lpss->data; uart.port.type = PORT_16550A; - uart.port.iotype = UPIO_MEM; + uart.port.iotype = UPIO_MEM32; uart.port.regshift = 2; uart.port.uartclk = lpss->board->base_baud * 16; uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE; -- cgit v1.2.3 From ae50bb2752836277ae15aa4e9d99074d6d947946 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Fri, 24 Jun 2022 23:42:08 +0300 Subject: serial: take termios_rwsem for ->rs485_config() & pass termios as param MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To be able to alter ADDRB within ->rs485_config(), take termios_rwsem before calling ->rs485_config() and pass termios. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220624204210.11112-5-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.h | 3 ++- drivers/tty/serial/8250/8250_dwlib.c | 3 ++- drivers/tty/serial/8250/8250_exar.c | 9 +++++---- drivers/tty/serial/8250/8250_fintek.c | 2 +- drivers/tty/serial/8250/8250_lpc18xx.c | 2 +- drivers/tty/serial/8250/8250_pci.c | 2 +- drivers/tty/serial/8250/8250_port.c | 3 ++- drivers/tty/serial/amba-pl011.c | 2 +- drivers/tty/serial/ar933x_uart.c | 2 +- drivers/tty/serial/atmel_serial.c | 2 +- drivers/tty/serial/fsl_lpuart.c | 4 ++-- drivers/tty/serial/imx.c | 2 +- drivers/tty/serial/max310x.c | 2 +- drivers/tty/serial/mcf.c | 3 ++- drivers/tty/serial/omap-serial.c | 3 ++- drivers/tty/serial/sc16is7xx.c | 2 +- drivers/tty/serial/serial_core.c | 14 ++++++++++---- drivers/tty/serial/stm32-usart.c | 2 +- include/linux/serial_core.h | 1 + 19 files changed, 38 insertions(+), 25 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 5cc967fe3b59..287153d32536 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -203,7 +203,8 @@ void serial8250_rpm_put(struct uart_8250_port *p); void serial8250_rpm_get_tx(struct uart_8250_port *p); void serial8250_rpm_put_tx(struct uart_8250_port *p); -int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485); +int serial8250_em485_config(struct uart_port *port, struct ktermios *termios, + struct serial_rs485 *rs485); void serial8250_em485_start_tx(struct uart_8250_port *p); void serial8250_em485_stop_tx(struct uart_8250_port *p); void serial8250_em485_destroy(struct uart_8250_port *p); diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c index c83e7eaf3877..d1ff3daeb0ba 100644 --- a/drivers/tty/serial/8250/8250_dwlib.c +++ b/drivers/tty/serial/8250/8250_dwlib.c @@ -85,7 +85,8 @@ void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct } EXPORT_SYMBOL_GPL(dw8250_do_set_termios); -static int dw8250_rs485_config(struct uart_port *p, struct serial_rs485 *rs485) +static int dw8250_rs485_config(struct uart_port *p, struct ktermios *termios, + struct serial_rs485 *rs485) { u32 tcr; diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index 3d999eec4087..f5344cfe303c 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -112,7 +112,8 @@ struct exar8250; struct exar8250_platform { - int (*rs485_config)(struct uart_port *, struct serial_rs485 *); + int (*rs485_config)(struct uart_port *port, struct ktermios *termios, + struct serial_rs485 *rs485); const struct serial_rs485 *rs485_supported; int (*register_gpio)(struct pci_dev *, struct uart_8250_port *); void (*unregister_gpio)(struct uart_8250_port *); @@ -409,7 +410,7 @@ static void xr17v35x_unregister_gpio(struct uart_8250_port *port) port->port.private_data = NULL; } -static int generic_rs485_config(struct uart_port *port, +static int generic_rs485_config(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485) { bool is_rs485 = !!(rs485->flags & SER_RS485_ENABLED); @@ -441,7 +442,7 @@ static const struct exar8250_platform exar8250_default_platform = { .rs485_supported = &generic_rs485_supported, }; -static int iot2040_rs485_config(struct uart_port *port, +static int iot2040_rs485_config(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485) { bool is_rs485 = !!(rs485->flags & SER_RS485_ENABLED); @@ -471,7 +472,7 @@ static int iot2040_rs485_config(struct uart_port *port, value |= mode; writeb(value, p + UART_EXAR_MPIOLVL_7_0); - return generic_rs485_config(port, rs485); + return generic_rs485_config(port, termios, rs485); } static const struct serial_rs485 iot2040_rs485_supported = { diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index 1fb86c73786c..eea693f5b577 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -191,7 +191,7 @@ static int fintek_8250_get_ldn_range(struct fintek_8250 *pdata, int *min, return -ENODEV; } -static int fintek_8250_rs485_config(struct uart_port *port, +static int fintek_8250_rs485_config(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485) { uint8_t config = 0; diff --git a/drivers/tty/serial/8250/8250_lpc18xx.c b/drivers/tty/serial/8250/8250_lpc18xx.c index 3a1cb51cbc91..d7cb3bb52069 100644 --- a/drivers/tty/serial/8250/8250_lpc18xx.c +++ b/drivers/tty/serial/8250/8250_lpc18xx.c @@ -32,7 +32,7 @@ struct lpc18xx_uart_data { int line; }; -static int lpc18xx_rs485_config(struct uart_port *port, +static int lpc18xx_rs485_config(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485) { struct uart_8250_port *up = up_to_u8250p(port); diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index b6d71268aa7d..d31d2350a9db 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1553,7 +1553,7 @@ pci_brcm_trumanage_setup(struct serial_private *priv, #define FINTEK_RTS_INVERT BIT(5) /* We should do proper H/W transceiver setting before change to RS485 mode */ -static int pci_fintek_rs485_config(struct uart_port *port, +static int pci_fintek_rs485_config(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485) { struct pci_dev *pci_dev = to_pci_dev(port->dev); diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index c8ae0e8376d4..d4337d8346c8 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -664,7 +664,8 @@ EXPORT_SYMBOL_GPL(serial8250_em485_supported); * if the uart is incapable of driving RTS as a Transmit Enable signal in * hardware, relying on software emulation instead. */ -int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485) +int serial8250_em485_config(struct uart_port *port, struct ktermios *termios, + struct serial_rs485 *rs485) { struct uart_8250_port *up = up_to_u8250p(port); diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index eccd66625d25..c8f52945a4aa 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2197,7 +2197,7 @@ static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser) return ret; } -static int pl011_rs485_config(struct uart_port *port, +static int pl011_rs485_config(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485) { struct uart_amba_port *uap = diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c index ab2c5b2a1ce8..b73ce13683db 100644 --- a/drivers/tty/serial/ar933x_uart.c +++ b/drivers/tty/serial/ar933x_uart.c @@ -580,7 +580,7 @@ static const struct uart_ops ar933x_uart_ops = { .verify_port = ar933x_uart_verify_port, }; -static int ar933x_config_rs485(struct uart_port *port, +static int ar933x_config_rs485(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485conf) { struct ar933x_uart_port *up = diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 3a94c2bdda72..bc6004679585 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -283,7 +283,7 @@ static void atmel_tasklet_schedule(struct atmel_uart_port *atmel_port, } /* Enable or disable the rs485 support */ -static int atmel_config_rs485(struct uart_port *port, +static int atmel_config_rs485(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485conf) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index d35414cb3e4e..8fe0494d4057 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -1355,7 +1355,7 @@ static void lpuart_dma_rx_free(struct uart_port *port) sport->dma_rx_cookie = -EINVAL; } -static int lpuart_config_rs485(struct uart_port *port, +static int lpuart_config_rs485(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485) { struct lpuart_port *sport = container_of(port, @@ -1385,7 +1385,7 @@ static int lpuart_config_rs485(struct uart_port *port, return 0; } -static int lpuart32_config_rs485(struct uart_port *port, +static int lpuart32_config_rs485(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485) { struct lpuart_port *sport = container_of(port, diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index f4edde54175f..3457006cea3f 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1907,7 +1907,7 @@ static void imx_uart_poll_put_char(struct uart_port *port, unsigned char c) #endif /* called with port.lock taken and irqs off or from .probe without locking */ -static int imx_uart_rs485_config(struct uart_port *port, +static int imx_uart_rs485_config(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485conf) { struct imx_port *sport = (struct imx_port *)port; diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 4915a786e315..e162bfb44080 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -1036,7 +1036,7 @@ static void max310x_rs_proc(struct work_struct *ws) MAX310X_MODE2_ECHOSUPR_BIT, mode2); } -static int max310x_rs485_config(struct uart_port *port, +static int max310x_rs485_config(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485) { struct max310x_one *one = to_max310x_port(port); diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c index 036f178e3d66..73c5287b8e5e 100644 --- a/drivers/tty/serial/mcf.c +++ b/drivers/tty/serial/mcf.c @@ -431,7 +431,8 @@ static int mcf_verify_port(struct uart_port *port, struct serial_struct *ser) /****************************************************************************/ /* Enable or disable the RS485 support */ -static int mcf_config_rs485(struct uart_port *port, struct serial_rs485 *rs485) +static int mcf_config_rs485(struct uart_port *port, struct ktermios *termios, + struct serial_rs485 *rs485) { unsigned char mr1, mr2; diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 52cb1a68b053..196bae704f85 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1324,7 +1324,8 @@ static inline void serial_omap_add_console_port(struct uart_omap_port *up) /* Enable or disable the rs485 support */ static int -serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485) +serial_omap_config_rs485(struct uart_port *port, struct ktermios *termios, + struct serial_rs485 *rs485) { struct uart_omap_port *up = to_uart_omap_port(port); unsigned int mode; diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 2ceecaa4a478..8cb92a3b3fb8 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -1127,7 +1127,7 @@ static void sc16is7xx_set_termios(struct uart_port *port, spin_unlock_irqrestore(&port->lock, flags); } -static int sc16is7xx_config_rs485(struct uart_port *port, +static int sc16is7xx_config_rs485(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485) { struct sc16is7xx_port *s = dev_get_drvdata(port->dev); diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 75ece750bedc..2529153c8979 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1353,7 +1353,7 @@ int uart_rs485_config(struct uart_port *port) uart_sanitize_serial_rs485(port, rs485); - ret = port->rs485_config(port, rs485); + ret = port->rs485_config(port, NULL, rs485); if (ret) memset(rs485, 0, sizeof(*rs485)); @@ -1377,7 +1377,7 @@ static int uart_get_rs485_config(struct uart_port *port, return 0; } -static int uart_set_rs485_config(struct uart_port *port, +static int uart_set_rs485_config(struct tty_struct *tty, struct uart_port *port, struct serial_rs485 __user *rs485_user) { struct serial_rs485 rs485; @@ -1396,7 +1396,7 @@ static int uart_set_rs485_config(struct uart_port *port, uart_sanitize_serial_rs485(port, &rs485); spin_lock_irqsave(&port->lock, flags); - ret = port->rs485_config(port, &rs485); + ret = port->rs485_config(port, &tty->termios, &rs485); if (!ret) port->rs485 = rs485; spin_unlock_irqrestore(&port->lock, flags); @@ -1505,6 +1505,10 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) if (ret != -ENOIOCTLCMD) goto out; + /* rs485_config requires more locking than others */ + if (cmd == TIOCGRS485) + down_write(&tty->termios_rwsem); + mutex_lock(&port->mutex); uport = uart_port_check(state); @@ -1528,7 +1532,7 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) break; case TIOCSRS485: - ret = uart_set_rs485_config(uport, uarg); + ret = uart_set_rs485_config(tty, uport, uarg); break; case TIOCSISO7816: @@ -1545,6 +1549,8 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) } out_up: mutex_unlock(&port->mutex); + if (cmd == TIOCGRS485) + up_write(&tty->termios_rwsem); out: return ret; } diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index db3dd9731ee1..13992e64a7df 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -97,7 +97,7 @@ static void stm32_usart_config_reg_rs485(u32 *cr1, u32 *cr3, u32 delay_ADE, *cr1 |= rs485_deat_dedt; } -static int stm32_usart_config_rs485(struct uart_port *port, +static int stm32_usart_config_rs485(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485conf) { struct stm32_port *stm32_port = to_stm32_port(port); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index faaf2372c60d..b7b86ee3cb12 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -133,6 +133,7 @@ struct uart_port { unsigned int old); void (*handle_break)(struct uart_port *); int (*rs485_config)(struct uart_port *, + struct ktermios *termios, struct serial_rs485 *rs485); int (*iso7816_config)(struct uart_port *, struct serial_iso7816 *iso7816); -- cgit v1.2.3 From 4f768e94774c58c9f7f54ebd38dadf172970046a Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Fri, 24 Jun 2022 23:42:09 +0300 Subject: serial: Support for RS-485 multipoint addresses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for RS-485 multipoint addressing using 9th bit [*]. The addressing mode is configured through ->rs485_config(). ADDRB in termios indicates 9th bit addressing mode is enabled. In this mode, 9th bit is used to indicate an address (byte) within the communication line. ADDRB can only be enabled/disabled through ->rs485_config() that is also responsible for setting the destination and receiver (filter) addresses. Add traps to detect unwanted changes to struct serial_rs485 layout using static_assert(). [*] Technically, RS485 is just an electronic spec and does not itself specify the 9th bit addressing mode but 9th bit seems at least "semi-standard" way to do addressing with RS485. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220624204210.11112-6-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/serial/driver.rst | 2 ++ Documentation/driver-api/serial/serial-rs485.rst | 26 +++++++++++++++++++++++- drivers/tty/serial/serial_core.c | 22 +++++++++++++++++++- drivers/tty/tty_ioctl.c | 4 ++++ include/uapi/asm-generic/termbits-common.h | 1 + include/uapi/linux/serial.h | 20 ++++++++++++++++-- 6 files changed, 71 insertions(+), 4 deletions(-) (limited to 'drivers/tty/serial') diff --git a/Documentation/driver-api/serial/driver.rst b/Documentation/driver-api/serial/driver.rst index 1e7ab4142d49..ee1679858aa2 100644 --- a/Documentation/driver-api/serial/driver.rst +++ b/Documentation/driver-api/serial/driver.rst @@ -261,6 +261,8 @@ hardware. - parity enable PARODD - odd parity (when PARENB is in force) + ADDRB + - address bit (changed through .rs485_config()). CREAD - enable reception of characters (if not set, still receive characters from the port, but diff --git a/Documentation/driver-api/serial/serial-rs485.rst b/Documentation/driver-api/serial/serial-rs485.rst index 00b5d333acba..6ebad75c74ed 100644 --- a/Documentation/driver-api/serial/serial-rs485.rst +++ b/Documentation/driver-api/serial/serial-rs485.rst @@ -99,7 +99,31 @@ RS485 Serial Communications /* Error handling. See errno. */ } -5. References +5. Multipoint Addressing +======================== + + The Linux kernel provides addressing mode for multipoint RS-485 serial + communications line. The addressing mode is enabled with SER_RS485_ADDRB + flag in serial_rs485. Struct serial_rs485 has two additional flags and + fields for enabling receive and destination addresses. + + Address mode flags: + - SER_RS485_ADDRB: Enabled addressing mode (sets also ADDRB in termios). + - SER_RS485_ADDR_RECV: Receive (filter) address enabled. + - SER_RS485_ADDR_DEST: Set destination address. + + Address fields (enabled with corresponding SER_RS485_ADDR_* flag): + - addr_recv: Receive address. + - addr_dest: Destination address. + + Once a receive address is set, the communication can occur only with the + particular device and other peers are filtered out. It is left up to the + receiver side to enforce the filtering. Receive address will be cleared + if SER_RS485_ADDR_RECV is not set. + + Note: not all devices supporting RS485 support multipoint addressing. + +6. References ============= [1] include/uapi/linux/serial.h diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 2529153c8979..85ef7ef00b82 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1288,6 +1288,17 @@ static int uart_check_rs485_flags(struct uart_port *port, struct serial_rs485 *r if (flags & ~port->rs485_supported->flags) return -EINVAL; + /* Asking for address w/o addressing mode? */ + if (!(rs485->flags & SER_RS485_ADDRB) && + (rs485->flags & (SER_RS485_ADDR_RECV|SER_RS485_ADDR_DEST))) + return -EINVAL; + + /* Address given but not enabled? */ + if (!(rs485->flags & SER_RS485_ADDR_RECV) && rs485->addr_recv) + return -EINVAL; + if (!(rs485->flags & SER_RS485_ADDR_DEST) && rs485->addr_dest) + return -EINVAL; + return 0; } @@ -1343,7 +1354,8 @@ static void uart_sanitize_serial_rs485(struct uart_port *port, struct serial_rs4 rs485->flags &= supported_flags; /* Return clean padding area to userspace */ - memset(rs485->padding, 0, sizeof(rs485->padding)); + memset(rs485->padding0, 0, sizeof(rs485->padding0)); + memset(rs485->padding1, 0, sizeof(rs485->padding1)); } int uart_rs485_config(struct uart_port *port) @@ -3402,5 +3414,13 @@ int uart_get_rs485_mode(struct uart_port *port) } EXPORT_SYMBOL_GPL(uart_get_rs485_mode); +/* Compile-time assertions for serial_rs485 layout */ +static_assert(offsetof(struct serial_rs485, padding) == + (offsetof(struct serial_rs485, delay_rts_after_send) + sizeof(__u32))); +static_assert(offsetof(struct serial_rs485, padding1) == + offsetof(struct serial_rs485, padding[1])); +static_assert((offsetof(struct serial_rs485, padding[4]) + sizeof(__u32)) == + sizeof(struct serial_rs485)); + MODULE_DESCRIPTION("Serial driver core"); MODULE_LICENSE("GPL"); diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index adae687f654b..2a76b330e108 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -319,6 +319,8 @@ unsigned char tty_get_frame_size(unsigned int cflag) bits++; if (cflag & PARENB) bits++; + if (cflag & ADDRB) + bits++; return bits; } @@ -353,6 +355,8 @@ int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios) old_termios = tty->termios; tty->termios = *new_termios; unset_locked_termios(tty, &old_termios); + /* Reset any ADDRB changes, ADDRB is changed through ->rs485_config() */ + tty->termios.c_cflag ^= (tty->termios.c_cflag ^ old_termios.c_cflag) & ADDRB; if (tty->ops->set_termios) tty->ops->set_termios(tty, &old_termios); diff --git a/include/uapi/asm-generic/termbits-common.h b/include/uapi/asm-generic/termbits-common.h index 4d084fe8def5..4a6a79f28b21 100644 --- a/include/uapi/asm-generic/termbits-common.h +++ b/include/uapi/asm-generic/termbits-common.h @@ -46,6 +46,7 @@ typedef unsigned int speed_t; #define EXTA B19200 #define EXTB B38400 +#define ADDRB 0x20000000 /* address bit */ #define CMSPAR 0x40000000 /* mark or space (stick) parity */ #define CRTSCTS 0x80000000 /* flow control */ diff --git a/include/uapi/linux/serial.h b/include/uapi/linux/serial.h index fa6b16e5fdd8..cea06924b295 100644 --- a/include/uapi/linux/serial.h +++ b/include/uapi/linux/serial.h @@ -126,10 +126,26 @@ struct serial_rs485 { #define SER_RS485_TERMINATE_BUS (1 << 5) /* Enable bus termination (if supported) */ + +/* RS-485 addressing mode */ +#define SER_RS485_ADDRB (1 << 6) /* Enable addressing mode */ +#define SER_RS485_ADDR_RECV (1 << 7) /* Receive address filter */ +#define SER_RS485_ADDR_DEST (1 << 8) /* Destination address */ + __u32 delay_rts_before_send; /* Delay before send (milliseconds) */ __u32 delay_rts_after_send; /* Delay after send (milliseconds) */ - __u32 padding[5]; /* Memory is cheap, new structs - are a royal PITA .. */ + + /* The fields below are defined by flags */ + union { + __u32 padding[5]; /* Memory is cheap, new structs are a pain */ + + struct { + __u8 addr_recv; + __u8 addr_dest; + __u8 padding0[2]; + __u32 padding1[4]; + }; + }; }; /* -- cgit v1.2.3 From f287f971e2569827fe9fb3a8d55a37703a13cf29 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Fri, 24 Jun 2022 23:42:10 +0300 Subject: serial: 8250_dwlib: Support for 9th bit multipoint addressing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add 9th bit multipoint addressing mode for DW UART. 9th bit addressing can be used only when HW RS485 is available. Updating RAR (receive address register) is bit tricky because busy indication is not be available when DW UART is strictly 16550 compatible, which is the case with the hardware I was testing with. RAR should not be updated while receive is in progress which is now achieved by deasserting RE and waiting for one frame (in case rx would be in progress, the driver seems to have no way of knowing it w/o busy indication). Because of this complexity, it's better to avoid doing it unless really needed. Co-developed-by: Heikki Krogerus Co-developed-by: Andy Shevchenko Co-developed-by: Raymond Tan Co-developed-by: Lakshmi Sowjanya Signed-off-by: Heikki Krogerus Signed-off-by: Andy Shevchenko Signed-off-by: Raymond Tan Signed-off-by: Lakshmi Sowjanya Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220624204210.11112-7-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dwlib.c | 102 ++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c index d1ff3daeb0ba..da330ef46446 100644 --- a/drivers/tty/serial/8250/8250_dwlib.c +++ b/drivers/tty/serial/8250/8250_dwlib.c @@ -3,8 +3,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -16,9 +18,18 @@ #define DW_UART_DE_EN 0xb0 /* Driver Output Enable Register */ #define DW_UART_RE_EN 0xb4 /* Receiver Output Enable Register */ #define DW_UART_DLF 0xc0 /* Divisor Latch Fraction Register */ +#define DW_UART_RAR 0xc4 /* Receive Address Register */ +#define DW_UART_TAR 0xc8 /* Transmit Address Register */ +#define DW_UART_LCR_EXT 0xcc /* Line Extended Control Register */ #define DW_UART_CPR 0xf4 /* Component Parameter Register */ #define DW_UART_UCV 0xf8 /* UART Component Version */ +/* Receive / Transmit Address Register bits */ +#define DW_UART_ADDR_MASK GENMASK(7, 0) + +/* Line Status Register bits */ +#define DW_UART_LSR_ADDR_RCVD BIT(8) + /* Transceiver Control Register bits */ #define DW_UART_TCR_RS485_EN BIT(0) #define DW_UART_TCR_RE_POL BIT(1) @@ -28,6 +39,12 @@ #define DW_UART_TCR_XFER_MODE_SW_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 1) #define DW_UART_TCR_XFER_MODE_DE_OR_RE FIELD_PREP(DW_UART_TCR_XFER_MODE, 2) +/* Line Extended Control Register bits */ +#define DW_UART_LCR_EXT_DLS_E BIT(0) +#define DW_UART_LCR_EXT_ADDR_MATCH BIT(1) +#define DW_UART_LCR_EXT_SEND_ADDR BIT(2) +#define DW_UART_LCR_EXT_TRANSMIT_MODE BIT(3) + /* Component Parameter Register bits */ #define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0) #define DW_UART_CPR_AFCE_MODE (1 << 4) @@ -82,9 +99,83 @@ void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios, struct p->status |= UPSTAT_AUTOCTS; serial8250_do_set_termios(p, termios, old); + + /* Filter addresses which have 9th bit set */ + p->ignore_status_mask |= DW_UART_LSR_ADDR_RCVD; + p->read_status_mask |= DW_UART_LSR_ADDR_RCVD; } EXPORT_SYMBOL_GPL(dw8250_do_set_termios); +/* + * Wait until re is de-asserted for sure. An ongoing receive will keep + * re asserted until end of frame. Without BUSY indication available, + * only available course of action is to wait for the time it takes to + * receive one frame (there might nothing to receive but w/o BUSY the + * driver cannot know). + */ +static void dw8250_wait_re_deassert(struct uart_port *p) +{ + ndelay(p->frame_time); +} + +static void dw8250_update_rar(struct uart_port *p, u32 addr) +{ + u32 re_en = dw8250_readl_ext(p, DW_UART_RE_EN); + + /* + * RAR shouldn't be changed while receiving. Thus, de-assert RE_EN + * if asserted and wait. + */ + if (re_en) + dw8250_writel_ext(p, DW_UART_RE_EN, 0); + dw8250_wait_re_deassert(p); + dw8250_writel_ext(p, DW_UART_RAR, addr); + if (re_en) + dw8250_writel_ext(p, DW_UART_RE_EN, re_en); +} + +static void dw8250_rs485_set_addr(struct uart_port *p, struct serial_rs485 *rs485, + struct ktermios *termios) +{ + u32 lcr = dw8250_readl_ext(p, DW_UART_LCR_EXT); + + if (rs485->flags & SER_RS485_ADDRB) { + lcr |= DW_UART_LCR_EXT_DLS_E; + if (termios) + termios->c_cflag |= ADDRB; + + if (rs485->flags & SER_RS485_ADDR_RECV) { + u32 delta = p->rs485.flags ^ rs485->flags; + + /* + * rs485 (param) is equal to uart_port's rs485 only during init + * (during init, delta is not yet applicable). + */ + if (unlikely(&p->rs485 == rs485)) + delta = rs485->flags; + + if ((delta & SER_RS485_ADDR_RECV) || + (p->rs485.addr_recv != rs485->addr_recv)) + dw8250_update_rar(p, rs485->addr_recv); + lcr |= DW_UART_LCR_EXT_ADDR_MATCH; + } else { + lcr &= ~DW_UART_LCR_EXT_ADDR_MATCH; + } + if (rs485->flags & SER_RS485_ADDR_DEST) { + /* + * Don't skip writes here as another endpoint could + * have changed communication line's destination + * address in between. + */ + dw8250_writel_ext(p, DW_UART_TAR, rs485->addr_dest); + lcr |= DW_UART_LCR_EXT_SEND_ADDR; + } + } else { + lcr = 0; + } + dw8250_writel_ext(p, DW_UART_LCR_EXT, lcr); +} + static int dw8250_rs485_config(struct uart_port *p, struct ktermios *termios, struct serial_rs485 *rs485) { @@ -109,6 +200,9 @@ static int dw8250_rs485_config(struct uart_port *p, struct ktermios *termios, dw8250_writel_ext(p, DW_UART_DE_EN, 1); dw8250_writel_ext(p, DW_UART_RE_EN, 1); } else { + if (termios) + termios->c_cflag &= ~ADDRB; + tcr &= ~DW_UART_TCR_RS485_EN; } @@ -123,6 +217,10 @@ static int dw8250_rs485_config(struct uart_port *p, struct ktermios *termios, dw8250_writel_ext(p, DW_UART_TCR, tcr); + /* Addressing mode can only be set up after TCR */ + if (rs485->flags & SER_RS485_ENABLED) + dw8250_rs485_set_addr(p, rs485, termios); + return 0; } @@ -142,7 +240,8 @@ static bool dw8250_detect_rs485_hw(struct uart_port *p) static const struct serial_rs485 dw8250_rs485_supported = { .flags = SER_RS485_ENABLED | SER_RS485_RX_DURING_TX | SER_RS485_RTS_ON_SEND | - SER_RS485_RTS_AFTER_SEND, + SER_RS485_RTS_AFTER_SEND | SER_RS485_ADDRB | SER_RS485_ADDR_RECV | + SER_RS485_ADDR_DEST, }; void dw8250_setup_port(struct uart_port *p) @@ -155,6 +254,7 @@ void dw8250_setup_port(struct uart_port *p) pd->hw_rs485_support = dw8250_detect_rs485_hw(p); if (pd->hw_rs485_support) { p->rs485_config = dw8250_rs485_config; + up->lsr_save_mask = LSR_SAVE_FLAGS | DW_UART_LSR_ADDR_RCVD; p->rs485_supported = &dw8250_rs485_supported; } else { p->rs485_config = serial8250_em485_config; -- cgit v1.2.3 From 9636047ffafcf5988946c05f0ebd7e0b2114aa74 Mon Sep 17 00:00:00 2001 From: Chanho Park Date: Wed, 29 Jun 2022 09:55:38 +0900 Subject: tty: serial: samsung_tty: support more than 4 uart ports Regarding Exynos Auto v9 SoC, it supports uarts up to 12. However, the maximum number of the ports has been derived from CONFIG_SERIAL_SAMSUNG_UARTS and tightly coupled with the config for previous Samsung SoCs such as s3c24xx and s3c64xx. To overcome this limitation, this changes the usage of the definition to UART_NR which is widely used from other serial drivers. This also defines the value to 12 only for ARM64 SoCs to not affect the change to previous arm32 SoCs. Instead of enumerating all the ports as predefined arrays, this introduces s3c24xx_serial_init_port_default that is initializing the structure as the default value. Reviewed-by: Hector Martin Reviewed-by: Krzysztof Kozlowski Signed-off-by: Chanho Park Link: https://lore.kernel.org/r/20220629005538.60132-1-chanho61.park@samsung.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung_tty.c | 82 ++++++++++++---------------------------- 1 file changed, 25 insertions(+), 57 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c index d5ca904def34..3e0aa2923605 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -48,6 +48,12 @@ #define S3C24XX_SERIAL_MAJOR 204 #define S3C24XX_SERIAL_MINOR 64 +#ifdef CONFIG_ARM64 +#define UART_NR 12 +#else +#define UART_NR CONFIG_SERIAL_SAMSUNG_UARTS +#endif + #define S3C24XX_TX_PIO 1 #define S3C24XX_TX_DMA 2 #define S3C24XX_RX_PIO 1 @@ -87,7 +93,7 @@ struct s3c24xx_uart_info { struct s3c24xx_serial_drv_data { const struct s3c24xx_uart_info info; const struct s3c2410_uartcfg def_cfg; - const unsigned int fifosize[CONFIG_SERIAL_SAMSUNG_UARTS]; + const unsigned int fifosize[UART_NR]; }; struct s3c24xx_uart_dma { @@ -1802,67 +1808,27 @@ static const struct uart_ops apple_s5l_serial_ops = { static struct uart_driver s3c24xx_uart_drv = { .owner = THIS_MODULE, .driver_name = "s3c2410_serial", - .nr = CONFIG_SERIAL_SAMSUNG_UARTS, + .nr = UART_NR, .cons = S3C24XX_SERIAL_CONSOLE, .dev_name = S3C24XX_SERIAL_NAME, .major = S3C24XX_SERIAL_MAJOR, .minor = S3C24XX_SERIAL_MINOR, }; -#define __PORT_LOCK_UNLOCKED(i) \ - __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[i].port.lock) -static struct s3c24xx_uart_port -s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = { - [0] = { - .port = { - .lock = __PORT_LOCK_UNLOCKED(0), - .iotype = UPIO_MEM, - .uartclk = 0, - .fifosize = 16, - .ops = &s3c24xx_serial_ops, - .flags = UPF_BOOT_AUTOCONF, - .line = 0, - } - }, - [1] = { - .port = { - .lock = __PORT_LOCK_UNLOCKED(1), - .iotype = UPIO_MEM, - .uartclk = 0, - .fifosize = 16, - .ops = &s3c24xx_serial_ops, - .flags = UPF_BOOT_AUTOCONF, - .line = 1, - } - }, -#if CONFIG_SERIAL_SAMSUNG_UARTS > 2 - [2] = { - .port = { - .lock = __PORT_LOCK_UNLOCKED(2), - .iotype = UPIO_MEM, - .uartclk = 0, - .fifosize = 16, - .ops = &s3c24xx_serial_ops, - .flags = UPF_BOOT_AUTOCONF, - .line = 2, - } - }, -#endif -#if CONFIG_SERIAL_SAMSUNG_UARTS > 3 - [3] = { - .port = { - .lock = __PORT_LOCK_UNLOCKED(3), - .iotype = UPIO_MEM, - .uartclk = 0, - .fifosize = 16, - .ops = &s3c24xx_serial_ops, - .flags = UPF_BOOT_AUTOCONF, - .line = 3, - } - } -#endif -}; -#undef __PORT_LOCK_UNLOCKED +static struct s3c24xx_uart_port s3c24xx_serial_ports[UART_NR]; + +static void s3c24xx_serial_init_port_default(int index) { + struct uart_port *port = &s3c24xx_serial_ports[index].port; + + spin_lock_init(&port->lock); + + port->iotype = UPIO_MEM; + port->uartclk = 0; + port->fifosize = 16; + port->ops = &s3c24xx_serial_ops; + port->flags = UPF_BOOT_AUTOCONF; + port->line = index; +} /* s3c24xx_serial_resetport * @@ -2178,6 +2144,8 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) } ourport = &s3c24xx_serial_ports[index]; + s3c24xx_serial_init_port_default(index); + ourport->drv_data = s3c24xx_get_driver_data(pdev); if (!ourport->drv_data) { dev_err(&pdev->dev, "could not find driver data\n"); @@ -2576,7 +2544,7 @@ s3c24xx_serial_console_setup(struct console *co, char *options) /* is this a valid port */ - if (co->index == -1 || co->index >= CONFIG_SERIAL_SAMSUNG_UARTS) + if (co->index == -1 || co->index >= UART_NR) co->index = 0; port = &s3c24xx_serial_ports[co->index].port; -- cgit v1.2.3 From 72a43046b61a3fe7164a622224bcdfc3cf6b795d Mon Sep 17 00:00:00 2001 From: Chanho Park Date: Wed, 29 Jun 2022 09:41:41 +0900 Subject: tty: serial: samsung_tty: loopback mode support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Internal loopback mode can be supported by setting UCON register's Loopback Mode bit. The mode & bit can be supported since s3c2410 and later SoCs. The prefix of LOOPBACK / BIT(5) naming should be also changed to S3C2410_ in order to avoid confusion. Reviewed-by: Krzysztof Kozlowski Reviewed-by: Ilpo Järvinen Signed-off-by: Chanho Park Link: https://lore.kernel.org/r/20220629004141.51484-1-chanho61.park@samsung.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung_tty.c | 8 ++++++++ include/linux/serial_s3c.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c index 3e0aa2923605..8971fbb49fa3 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -1018,6 +1018,7 @@ static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port) static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) { unsigned int umcon = rd_regl(port, S3C2410_UMCON); + unsigned int ucon = rd_reg(port, S3C2410_UCON); if (mctrl & TIOCM_RTS) umcon |= S3C2410_UMCOM_RTS_LOW; @@ -1025,6 +1026,13 @@ static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) umcon &= ~S3C2410_UMCOM_RTS_LOW; wr_regl(port, S3C2410_UMCON, umcon); + + if (mctrl & TIOCM_LOOP) + ucon |= S3C2410_UCON_LOOPBACK; + else + ucon &= ~S3C2410_UCON_LOOPBACK; + + wr_regl(port, S3C2410_UCON, ucon); } static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state) diff --git a/include/linux/serial_s3c.h b/include/linux/serial_s3c.h index dec15f5b3dec..1672cf0810ef 100644 --- a/include/linux/serial_s3c.h +++ b/include/linux/serial_s3c.h @@ -83,7 +83,7 @@ #define S3C2410_UCON_RXIRQMODE (1<<0) #define S3C2410_UCON_RXFIFO_TOI (1<<7) #define S3C2443_UCON_RXERR_IRQEN (1<<6) -#define S3C2443_UCON_LOOPBACK (1<<5) +#define S3C2410_UCON_LOOPBACK (1<<5) #define S3C2410_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ S3C2410_UCON_RXILEVEL | \ -- cgit v1.2.3 From 137b2d985928890557f8e73cf7e53677637b7af8 Mon Sep 17 00:00:00 2001 From: Zhang Jiaming Date: Wed, 29 Jun 2022 17:44:11 +0800 Subject: serial: 8250_port: Fix spelling mistake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change 'timeing' to 'timing'. Change 'Characteres' to 'Characters'. Reviewed-by: Ilpo Järvinen Signed-off-by: Zhang Jiaming Link: https://lore.kernel.org/r/20220629094411.39066-1-jiaming@nfschina.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index d4337d8346c8..ed2a606f2da7 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1511,7 +1511,7 @@ static inline void __stop_tx(struct uart_8250_port *p) if (!(lsr & UART_LSR_THRE)) return; /* - * To provide required timeing and allow FIFO transfer, + * To provide required timing and allow FIFO transfer, * __stop_tx_rs485() must be called only when both FIFO and * shift register are empty. The device driver should either * enable interrupt on TEMT or set UART_CAP_NOTEMT that will @@ -2798,7 +2798,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, port->read_status_mask |= UART_LSR_BI; /* - * Characteres to ignore + * Characters to ignore */ port->ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) -- cgit v1.2.3 From b9491b2e45d71eb64245560e208897af95ffbf95 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Tue, 28 Jun 2022 12:01:28 +0300 Subject: serial: 8250_dw: Take port lock while accessing LSR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Accessing LSR requires port lock because it mutates lsr_saved_flags in serial_lsr_in(). Fixes: 197eb5c416ff ("serial: 8250_dw: Use serial_lsr_in() in dw8250_handle_irq()") Reviewed-by: Andy Shevchenko Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/c5879db7-bee9-93f-526e-872a292442@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 167a691c7b19..f78b13db1b1e 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -266,7 +266,10 @@ static int dw8250_handle_irq(struct uart_port *p) /* Manually stop the Rx DMA transfer when acting as flow controller */ if (quirks & DW_UART_QUIRK_IS_DMA_FC && up->dma && up->dma->rx_running && rx_timeout) { + spin_lock_irqsave(&p->lock, flags); status = serial_lsr_in(up); + spin_unlock_irqrestore(&p->lock, flags); + if (status & (UART_LSR_DR | UART_LSR_BI)) { dw8250_writel_ext(p, RZN1_UART_RDMACR, 0); dw8250_writel_ext(p, DW_UART_DMASA, 1); -- cgit v1.2.3 From 65e20e8cbbccaf0968474d27420c3a5170a5a5b8 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Tue, 28 Jun 2022 14:07:05 +0200 Subject: earlycon: prevent multiple register_console() If the earlycon parameter is given twice, the kernel will spit out a WARN() in register_console() because it was already registered. The non-dt variant setup_earlycon() already handles that gracefully. The dt variant of_setup_earlycon() doesn't. Add the check there and add the -EALREADY handling in early_init_dt_scan_chosen_stdout(). FWIW, this doesn't happen if CONFIG_ACPI_SPCR_TABLE is set. In that case the registration is delayed until after earlycon parameter(s) are parsed. Reviewed-by: Rob Herring Signed-off-by: Michael Walle Link: https://lore.kernel.org/r/20220628120705.200617-1-michael@walle.cc Signed-off-by: Greg Kroah-Hartman --- drivers/of/fdt.c | 4 +++- drivers/tty/serial/earlycon.c | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index a8f5b6532165..043b12be22d6 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -1025,6 +1025,7 @@ int __init early_init_dt_scan_chosen_stdout(void) int l; const struct earlycon_id *match; const void *fdt = initial_boot_params; + int ret; offset = fdt_path_offset(fdt, "/chosen"); if (offset < 0) @@ -1057,7 +1058,8 @@ int __init early_init_dt_scan_chosen_stdout(void) if (fdt_node_check_compatible(fdt, offset, match->compatible)) continue; - if (of_setup_earlycon(match, offset, options) == 0) + ret = of_setup_earlycon(match, offset, options); + if (!ret || ret == -EALREADY) return 0; } return -ENODEV; diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 57c70851f22a..88d08ba1ca83 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -253,6 +253,9 @@ int __init of_setup_earlycon(const struct earlycon_id *match, bool big_endian; u64 addr; + if (early_con.flags & CON_ENABLED) + return -EALREADY; + spin_lock_init(&port->lock); port->iotype = UPIO_MEM; addr = of_flat_dt_translate_address(node); -- cgit v1.2.3 From 6343ecd76c828951fbe55e7d5b29e1923655aed9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 Jun 2022 12:38:16 +0300 Subject: serial: 8250_dw: Sort headers alphabetically MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For the sake of better maintenance, sort included headers alphabetically. While at it, split the serial group of headers which makes clear the subsystem the driver belongs to. Reviewed-by: Ilpo Järvinen Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20220630093816.28271-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index f78b13db1b1e..e4211c5b3b00 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -9,26 +9,27 @@ * LCR is written whilst busy. If it is, then a busy detect interrupt is * raised, the LCR needs to be rewritten and the uart status register read. */ +#include +#include #include #include #include #include #include -#include -#include +#include #include #include +#include #include -#include -#include -#include -#include -#include #include -#include +#include +#include #include +#include +#include + #include "8250_dwlib.h" /* Offsets for the DesignWare specific registers */ -- cgit v1.2.3 From 808313bc2182ab60761eed82d2c345883fbc65a7 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 30 Jun 2022 13:05:07 +0300 Subject: serial: 8250_dw: Drop PM ifdeffery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop CONFIG_PM and CONFIG_PM_SLEEP ifdeffery while converting dw8250_pm_ops to use new PM macros. Since we are using runtime PM, wrap dw8250_pm_ops into pm_ptr(). Reviewed-by: Ilpo Järvinen Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20220630100507.31113-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index e4211c5b3b00..b5b783f01221 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -695,7 +695,6 @@ static int dw8250_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP static int dw8250_suspend(struct device *dev) { struct dw8250_data *data = dev_get_drvdata(dev); @@ -713,9 +712,7 @@ static int dw8250_resume(struct device *dev) return 0; } -#endif /* CONFIG_PM_SLEEP */ -#ifdef CONFIG_PM static int dw8250_runtime_suspend(struct device *dev) { struct dw8250_data *data = dev_get_drvdata(dev); @@ -737,11 +734,10 @@ static int dw8250_runtime_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops dw8250_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(dw8250_suspend, dw8250_resume) - SET_RUNTIME_PM_OPS(dw8250_runtime_suspend, dw8250_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(dw8250_suspend, dw8250_resume) + RUNTIME_PM_OPS(dw8250_runtime_suspend, dw8250_runtime_resume, NULL) }; static const struct dw8250_platform_data dw8250_dw_apb = { @@ -799,7 +795,7 @@ MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match); static struct platform_driver dw8250_platform_driver = { .driver = { .name = "dw-apb-uart", - .pm = &dw8250_pm_ops, + .pm = pm_ptr(&dw8250_pm_ops), .of_match_table = dw8250_of_match, .acpi_match_table = dw8250_acpi_match, }, -- cgit v1.2.3 From e9f9736679566cfa4158a40820cd50a46e601349 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Thu, 30 Jun 2022 13:05:36 +0300 Subject: 8250_dwlib: Convert bitops to newer form MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of open-coding, use BIT(), GENMASK(), and FIELD_GET() helpers. Reviewed-by: Andy Shevchenko Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220630100536.41329-1-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dwlib.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c index da330ef46446..a8bbed74ea70 100644 --- a/drivers/tty/serial/8250/8250_dwlib.c +++ b/drivers/tty/serial/8250/8250_dwlib.c @@ -46,21 +46,21 @@ #define DW_UART_LCR_EXT_TRANSMIT_MODE BIT(3) /* Component Parameter Register bits */ -#define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0) -#define DW_UART_CPR_AFCE_MODE (1 << 4) -#define DW_UART_CPR_THRE_MODE (1 << 5) -#define DW_UART_CPR_SIR_MODE (1 << 6) -#define DW_UART_CPR_SIR_LP_MODE (1 << 7) -#define DW_UART_CPR_ADDITIONAL_FEATURES (1 << 8) -#define DW_UART_CPR_FIFO_ACCESS (1 << 9) -#define DW_UART_CPR_FIFO_STAT (1 << 10) -#define DW_UART_CPR_SHADOW (1 << 11) -#define DW_UART_CPR_ENCODED_PARMS (1 << 12) -#define DW_UART_CPR_DMA_EXTRA (1 << 13) -#define DW_UART_CPR_FIFO_MODE (0xff << 16) +#define DW_UART_CPR_ABP_DATA_WIDTH GENMASK(1, 0) +#define DW_UART_CPR_AFCE_MODE BIT(4) +#define DW_UART_CPR_THRE_MODE BIT(5) +#define DW_UART_CPR_SIR_MODE BIT(6) +#define DW_UART_CPR_SIR_LP_MODE BIT(7) +#define DW_UART_CPR_ADDITIONAL_FEATURES BIT(8) +#define DW_UART_CPR_FIFO_ACCESS BIT(9) +#define DW_UART_CPR_FIFO_STAT BIT(10) +#define DW_UART_CPR_SHADOW BIT(11) +#define DW_UART_CPR_ENCODED_PARMS BIT(12) +#define DW_UART_CPR_DMA_EXTRA BIT(13) +#define DW_UART_CPR_FIFO_MODE GENMASK(23, 16) /* Helper for FIFO size calculation */ -#define DW_UART_CPR_FIFO_SIZE(a) (((a >> 16) & 0xff) * 16) +#define DW_UART_CPR_FIFO_SIZE(a) (FIELD_GET(DW_UART_CPR_FIFO_MODE, (a)) * 16) /* * divisor = div(I) + div(F) -- cgit v1.2.3 From 309f7beddf053bd0560b07f3251ac64a5872ecf9 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Tue, 28 Jun 2022 16:42:31 +0300 Subject: serial: 8250_dw: Use dw8250_serial_out() in dw8250_serial_out38x() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Place dw8250_serial_out() before dw8250_serial_out38x() so that it can be called from dw8250_serial_out38x() to do the actual write. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220628134234.53771-2-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index b5b783f01221..e419e032895c 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -144,29 +144,23 @@ static void dw8250_tx_wait_empty(struct uart_port *p) } } -static void dw8250_serial_out38x(struct uart_port *p, int offset, int value) +static void dw8250_serial_out(struct uart_port *p, int offset, int value) { struct dw8250_data *d = to_dw8250_data(p->private_data); - /* Allow the TX to drain before we reconfigure */ - if (offset == UART_LCR) - dw8250_tx_wait_empty(p); - writeb(value, p->membase + (offset << p->regshift)); if (offset == UART_LCR && !d->uart_16550_compatible) dw8250_check_lcr(p, value); } - -static void dw8250_serial_out(struct uart_port *p, int offset, int value) +static void dw8250_serial_out38x(struct uart_port *p, int offset, int value) { - struct dw8250_data *d = to_dw8250_data(p->private_data); - - writeb(value, p->membase + (offset << p->regshift)); + /* Allow the TX to drain before we reconfigure */ + if (offset == UART_LCR) + dw8250_tx_wait_empty(p); - if (offset == UART_LCR && !d->uart_16550_compatible) - dw8250_check_lcr(p, value); + dw8250_serial_out(p, offset, value); } static unsigned int dw8250_serial_in(struct uart_port *p, int offset) -- cgit v1.2.3 From 9d3aaceb73acadf134596a2f8db9c451c1332d3d Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 4 Jul 2022 10:51:19 +0200 Subject: serial: 8250_fsl: Don't report FE, PE and OE twice MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some Freescale 8250 implementations have the problem that a single long break results in one irq per character frame time. The code in fsl8250_handle_irq() that is supposed to handle that uses the BI bit in lsr_saved_flags to detect such a situation and then skip the second received character. However it also stores other error bits and so after a single frame error the character received in the next irq handling is passed to the upper layer with a frame error, too. So after a spike on the data line (which is correctly recognized as a frame error) the following valid character is thrown away, because the driver reports a frame error for that one, too. To weaken this problem restrict saving LSR to only the BI bit. Note however that the handling is still broken: - lsr_saved_flags is updated using orig_lsr which is the LSR content for the first received char, but there might be more in the FIFO, so a character is thrown away that is received later and not necessarily the one following the break. - The doubled break might be the 2nd and 3rd char in the FIFO, so the workaround doesn't catch these, because serial8250_rx_chars() doesn't handle the workaround. - lsr_saved_flags might have set UART_LSR_BI at the entry of fsl8250_handle_irq() which doesn't originate from fsl8250_handle_irq()'s "up->lsr_saved_flags |= orig_lsr & UART_LSR_BI;" but from e.g. from serial8250_tx_empty(). - For a long or a short break this isn't about two characters, but more or only a single one. Fixes: 9deaa53ac7fa ("serial: add irq handler for Freescale 16550 errata.") Acked-by: Ilpo Järvinen Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20220704085119.55900-1-u.kleine-koenig@pengutronix.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_fsl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c index fd4005fcd0d6..8aad15622a2e 100644 --- a/drivers/tty/serial/8250/8250_fsl.c +++ b/drivers/tty/serial/8250/8250_fsl.c @@ -77,7 +77,7 @@ int fsl8250_handle_irq(struct uart_port *port) if ((lsr & UART_LSR_THRE) && (up->ier & UART_IER_THRI)) serial8250_tx_chars(up); - up->lsr_saved_flags = orig_lsr; + up->lsr_saved_flags |= orig_lsr & UART_LSR_BI; uart_unlock_and_check_sysrq_irqrestore(&up->port, flags); -- cgit v1.2.3 From 0139da50dc53f0ce2804e83566d290c7e626fd17 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 4 Jul 2022 12:45:14 +0300 Subject: serial: Embed rs485_supported to uart_port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Embed rs485_supported to uart_port to allow serial core to tweak it as needed. Reviewed-by: Lino Sanfilippo Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220704094515.6831-2-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_bcm2835aux.c | 2 +- drivers/tty/serial/8250/8250_dwlib.c | 4 ++-- drivers/tty/serial/8250/8250_exar.c | 2 +- drivers/tty/serial/8250/8250_fintek.c | 4 ++-- drivers/tty/serial/8250/8250_lpc18xx.c | 2 +- drivers/tty/serial/8250/8250_of.c | 2 +- drivers/tty/serial/8250/8250_pci.c | 2 +- drivers/tty/serial/amba-pl011.c | 2 +- drivers/tty/serial/ar933x_uart.c | 4 ++-- drivers/tty/serial/atmel_serial.c | 2 +- drivers/tty/serial/fsl_lpuart.c | 2 +- drivers/tty/serial/imx.c | 4 ++-- drivers/tty/serial/max310x.c | 2 +- drivers/tty/serial/mcf.c | 4 ++-- drivers/tty/serial/omap-serial.c | 2 +- drivers/tty/serial/sc16is7xx.c | 2 +- drivers/tty/serial/serial_core.c | 8 ++++---- drivers/tty/serial/stm32-usart.c | 2 +- include/linux/serial_core.h | 2 +- 19 files changed, 27 insertions(+), 27 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c index d9f1e618cfbd..047e14ccb165 100644 --- a/drivers/tty/serial/8250/8250_bcm2835aux.c +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c @@ -108,7 +108,7 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) up.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_SKIP_TEST | UPF_IOREMAP; up.port.rs485_config = serial8250_em485_config; - up.port.rs485_supported = &serial8250_em485_supported; + up.port.rs485_supported = serial8250_em485_supported; up.rs485_start_tx = bcm2835aux_rs485_start_tx; up.rs485_stop_tx = bcm2835aux_rs485_stop_tx; diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c index a8bbed74ea70..2c3b1468bd88 100644 --- a/drivers/tty/serial/8250/8250_dwlib.c +++ b/drivers/tty/serial/8250/8250_dwlib.c @@ -255,10 +255,10 @@ void dw8250_setup_port(struct uart_port *p) if (pd->hw_rs485_support) { p->rs485_config = dw8250_rs485_config; up->lsr_save_mask = LSR_SAVE_FLAGS | DW_UART_LSR_ADDR_RCVD; - p->rs485_supported = &dw8250_rs485_supported; + p->rs485_supported = dw8250_rs485_supported; } else { p->rs485_config = serial8250_em485_config; - p->rs485_supported = &serial8250_em485_supported; + p->rs485_supported = serial8250_em485_supported; up->rs485_start_tx = serial8250_em485_start_tx; up->rs485_stop_tx = serial8250_em485_stop_tx; } diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index f5344cfe303c..314a05e009df 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -550,7 +550,7 @@ pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev, port->port.uartclk = baud * 16; port->port.rs485_config = platform->rs485_config; - port->port.rs485_supported = platform->rs485_supported; + port->port.rs485_supported = *(platform->rs485_supported); /* * Setup the UART clock for the devices on expansion slot to diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index eea693f5b577..65b6b3cbaff6 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -433,9 +433,9 @@ static void fintek_8250_set_rs485_handler(struct uart_8250_port *uart) case CHIP_ID_F81865: uart->port.rs485_config = fintek_8250_rs485_config; if (!pdata->index) - uart->port.rs485_supported = &fintek_8250_rs485_supported_port0; + uart->port.rs485_supported = fintek_8250_rs485_supported_port0; else - uart->port.rs485_supported = &fintek_8250_rs485_supported; + uart->port.rs485_supported = fintek_8250_rs485_supported; break; default: /* No RS485 Auto direction functional */ diff --git a/drivers/tty/serial/8250/8250_lpc18xx.c b/drivers/tty/serial/8250/8250_lpc18xx.c index d7cb3bb52069..d6ca0d47e9d5 100644 --- a/drivers/tty/serial/8250/8250_lpc18xx.c +++ b/drivers/tty/serial/8250/8250_lpc18xx.c @@ -161,7 +161,7 @@ static int lpc18xx_serial_probe(struct platform_device *pdev) uart.port.uartclk = clk_get_rate(data->clk_uart); uart.port.private_data = data; uart.port.rs485_config = lpc18xx_rs485_config; - uart.port.rs485_supported = &lpc18xx_rs485_supported; + uart.port.rs485_supported = lpc18xx_rs485_supported; uart.port.serial_out = lpc18xx_uart_serial_out; uart.dma = &data->dma; diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 65cccd559db2..1b461fba15a3 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -165,7 +165,7 @@ static int of_platform_serial_setup(struct platform_device *ofdev, port->dev = &ofdev->dev; port->rs485_config = serial8250_em485_config; - port->rs485_supported = &serial8250_em485_supported; + port->rs485_supported = serial8250_em485_supported; up->rs485_start_tx = serial8250_em485_start_tx; up->rs485_stop_tx = serial8250_em485_stop_tx; diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index d31d2350a9db..8a39ae072c65 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1607,7 +1607,7 @@ static int pci_fintek_setup(struct serial_private *priv, port->port.iotype = UPIO_PORT; port->port.iobase = iobase; port->port.rs485_config = pci_fintek_rs485_config; - port->port.rs485_supported = &pci_fintek_rs485_supported; + port->port.rs485_supported = pci_fintek_rs485_supported; data = devm_kzalloc(&pdev->dev, sizeof(u8), GFP_KERNEL); if (!data) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index c8f52945a4aa..abeceeefdece 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2779,7 +2779,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) uap->port.irq = dev->irq[0]; uap->port.ops = &amba_pl011_pops; uap->port.rs485_config = pl011_rs485_config; - uap->port.rs485_supported = &pl011_rs485_supported; + uap->port.rs485_supported = pl011_rs485_supported; snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev)); ret = pl011_setup_port(&dev->dev, uap, &dev->res, portnr); diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c index b73ce13683db..f931ecbc0bc0 100644 --- a/drivers/tty/serial/ar933x_uart.c +++ b/drivers/tty/serial/ar933x_uart.c @@ -778,7 +778,7 @@ static int ar933x_uart_probe(struct platform_device *pdev) port->fifosize = AR933X_UART_FIFO_SIZE; port->ops = &ar933x_uart_ops; port->rs485_config = ar933x_config_rs485; - port->rs485_supported = &ar933x_rs485_supported; + port->rs485_supported = ar933x_rs485_supported; baud = ar933x_uart_get_baud(port->uartclk, AR933X_UART_MAX_SCALE, 1); up->min_baud = max_t(unsigned int, baud, AR933X_UART_MIN_BAUD); @@ -802,7 +802,7 @@ static int ar933x_uart_probe(struct platform_device *pdev) !up->rts_gpiod) { dev_err(&pdev->dev, "lacking rts-gpio, disabling RS485\n"); port->rs485.flags &= ~SER_RS485_ENABLED; - port->rs485_supported = &ar933x_no_rs485; + port->rs485_supported = ar933x_no_rs485; } #ifdef CONFIG_SERIAL_AR933X_CONSOLE diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index bc6004679585..30ba9eef7b39 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -2498,7 +2498,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, port->mapbase = mpdev->resource[0].start; port->irq = platform_get_irq(mpdev, 0); port->rs485_config = atmel_config_rs485; - port->rs485_supported = &atmel_rs485_supported; + port->rs485_supported = atmel_rs485_supported; port->iso7816_config = atmel_config_iso7816; port->membase = NULL; diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 8fe0494d4057..fc7d235a1e27 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -2655,7 +2655,7 @@ static int lpuart_probe(struct platform_device *pdev) sport->port.rs485_config = lpuart32_config_rs485; else sport->port.rs485_config = lpuart_config_rs485; - sport->port.rs485_supported = &lpuart_rs485_supported; + sport->port.rs485_supported = lpuart_rs485_supported; sport->ipg_clk = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(sport->ipg_clk)) { diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 3457006cea3f..522445a8f666 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -2285,9 +2285,9 @@ static int imx_uart_probe(struct platform_device *pdev) sport->port.rs485_config = imx_uart_rs485_config; /* RTS is required to control the RS485 transmitter */ if (sport->have_rtscts || sport->have_rtsgpio) - sport->port.rs485_supported = &imx_rs485_supported; + sport->port.rs485_supported = imx_rs485_supported; else - sport->port.rs485_supported = &imx_no_rs485; + sport->port.rs485_supported = imx_no_rs485; sport->port.flags = UPF_BOOT_AUTOCONF; timer_setup(&sport->timer, imx_uart_timeout, 0); diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index e162bfb44080..ab10ca4a45b5 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -1370,7 +1370,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty s->p[i].port.membase = (void __iomem *)~0; s->p[i].port.uartclk = uartclk; s->p[i].port.rs485_config = max310x_rs485_config; - s->p[i].port.rs485_supported = &max310x_rs485_supported; + s->p[i].port.rs485_supported = max310x_rs485_supported; s->p[i].port.ops = &max310x_ops; s->p[i].regmap = regmaps[i]; diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c index 73c5287b8e5e..f4aaaadd0742 100644 --- a/drivers/tty/serial/mcf.c +++ b/drivers/tty/serial/mcf.c @@ -506,7 +506,7 @@ int __init early_mcf_setup(struct mcf_platform_uart *platp) port->uartclk = MCF_BUSCLK; port->flags = UPF_BOOT_AUTOCONF; port->rs485_config = mcf_config_rs485; - port->rs485_supported = &mcf_rs485_supported; + port->rs485_supported = mcf_rs485_supported; port->ops = &mcf_uart_ops; } @@ -634,7 +634,7 @@ static int mcf_probe(struct platform_device *pdev) port->ops = &mcf_uart_ops; port->flags = UPF_BOOT_AUTOCONF; port->rs485_config = mcf_config_rs485; - port->rs485_supported = &mcf_rs485_supported; + port->rs485_supported = mcf_rs485_supported; port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_MCF_CONSOLE); uart_add_one_port(&mcf_driver, port); diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 196bae704f85..0aa666e247d5 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1643,7 +1643,7 @@ static int serial_omap_probe(struct platform_device *pdev) up->port.flags = omap_up_info->flags; up->port.uartclk = omap_up_info->uartclk; up->port.rs485_config = serial_omap_config_rs485; - up->port.rs485_supported = &serial_omap_rs485_supported; + up->port.rs485_supported = serial_omap_rs485_supported; if (!up->port.uartclk) { up->port.uartclk = DEFAULT_CLK_SPEED; dev_warn(&pdev->dev, diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 8cb92a3b3fb8..259e08cc347c 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -1461,7 +1461,7 @@ static int sc16is7xx_probe(struct device *dev, s->p[i].port.iotype = UPIO_PORT; s->p[i].port.uartclk = freq; s->p[i].port.rs485_config = sc16is7xx_config_rs485; - s->p[i].port.rs485_supported = &sc16is7xx_rs485_supported; + s->p[i].port.rs485_supported = sc16is7xx_rs485_supported; s->p[i].port.ops = &sc16is7xx_ops; s->p[i].old_mctrl = 0; s->p[i].port.line = sc16is7xx_alloc_line(); diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 85ef7ef00b82..a9cf1044a9fa 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1285,7 +1285,7 @@ static int uart_check_rs485_flags(struct uart_port *port, struct serial_rs485 *r * For any bit outside of the legacy ones that is not supported by * the driver, return -EINVAL. */ - if (flags & ~port->rs485_supported->flags) + if (flags & ~port->rs485_supported.flags) return -EINVAL; /* Asking for address w/o addressing mode? */ @@ -1304,7 +1304,7 @@ static int uart_check_rs485_flags(struct uart_port *port, struct serial_rs485 *r static void uart_sanitize_serial_rs485(struct uart_port *port, struct serial_rs485 *rs485) { - u32 supported_flags = port->rs485_supported->flags; + u32 supported_flags = port->rs485_supported.flags; if (!(rs485->flags & SER_RS485_ENABLED)) { memset(rs485, 0, sizeof(*rs485)); @@ -1323,7 +1323,7 @@ static void uart_sanitize_serial_rs485(struct uart_port *port, struct serial_rs4 supported_flags |= SER_RS485_RTS_ON_SEND|SER_RS485_RTS_AFTER_SEND; } - if (!port->rs485_supported->delay_rts_before_send) { + if (!port->rs485_supported.delay_rts_before_send) { if (rs485->delay_rts_before_send) { dev_warn_ratelimited(port->dev, "%s (%d): RTS delay before sending not supported\n", @@ -1337,7 +1337,7 @@ static void uart_sanitize_serial_rs485(struct uart_port *port, struct serial_rs4 port->name, port->line, rs485->delay_rts_before_send); } - if (!port->rs485_supported->delay_rts_after_send) { + if (!port->rs485_supported.delay_rts_after_send) { if (rs485->delay_rts_after_send) { dev_warn_ratelimited(port->dev, "%s (%d): RTS delay after sending not supported\n", diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 13992e64a7df..ff5c7e0ebc4c 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -1401,7 +1401,7 @@ static int stm32_usart_init_port(struct stm32_port *stm32port, port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_STM32_CONSOLE); port->irq = irq; port->rs485_config = stm32_usart_config_rs485; - port->rs485_supported = &stm32_rs485_supported; + port->rs485_supported = stm32_rs485_supported; ret = stm32_usart_init_rs485(port, pdev); if (ret) diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index b7b86ee3cb12..a6fa7c40c330 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -255,7 +255,7 @@ struct uart_port { struct attribute_group *attr_group; /* port specific attributes */ const struct attribute_group **tty_groups; /* all attributes (serial core use only) */ struct serial_rs485 rs485; - const struct serial_rs485 *rs485_supported; /* Supported mask for serial_rs485 */ + struct serial_rs485 rs485_supported; /* Supported mask for serial_rs485 */ struct gpio_desc *rs485_term_gpio; /* enable RS485 bus termination */ struct serial_iso7816 iso7816; void *private_data; /* generic platform data pointer */ -- cgit v1.2.3 From 8bec874f84d826288a6cfa6acc683d15c218d78c Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Mon, 4 Jul 2022 12:45:15 +0300 Subject: serial: RS485 termination is supported if DT provides one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When DT provides rs485-term, set termination flag as supported. Reviewed-by: Lino Sanfilippo Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220704094515.6831-3-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index a9cf1044a9fa..1db44cde76f6 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -3409,6 +3409,8 @@ int uart_get_rs485_mode(struct uart_port *port) port->rs485_term_gpio = NULL; return dev_err_probe(dev, ret, "Cannot get rs485-term-gpios\n"); } + if (port->rs485_term_gpio) + port->rs485_supported.flags |= SER_RS485_TERMINATE_BUS; return 0; } -- cgit v1.2.3 From ef5a03a26c87a760bc3d86b5af7b773e82f8b1b7 Mon Sep 17 00:00:00 2001 From: Cameron Williams Date: Mon, 11 Jul 2022 16:35:10 +0100 Subject: tty: 8250: Add support for Brainboxes PX cards. Add support for some of the Brainboxes PCIe (PX) range of serial cards, including the PX-101, PX-235/PX-246, PX-203/PX-257, PX-260/PX-701, PX-310, PX-313, PX-320/PX-324/PX-376/PX-387, PX-335/PX-346, PX-368, PX-420, PX-803 and PX-846. Signed-off-by: Cameron Williams Cc: stable Link: https://lore.kernel.org/r/AM5PR0202MB2564669252BDC59BF55A6E87C4879@AM5PR0202MB2564.eurprd02.prod.outlook.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 109 +++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 8a39ae072c65..6f66dc2ebacc 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -5066,6 +5066,115 @@ static const struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b2_4_115200 }, + /* + * Brainboxes PX-101 + */ + { PCI_VENDOR_ID_INTASHIELD, 0x4005, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_b0_2_115200 }, + { PCI_VENDOR_ID_INTASHIELD, 0x4019, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_oxsemi_2_15625000 }, + /* + * Brainboxes PX-235/246 + */ + { PCI_VENDOR_ID_INTASHIELD, 0x4004, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_b0_1_115200 }, + { PCI_VENDOR_ID_INTASHIELD, 0x4016, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_oxsemi_1_15625000 }, + /* + * Brainboxes PX-203/PX-257 + */ + { PCI_VENDOR_ID_INTASHIELD, 0x4006, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_b0_2_115200 }, + { PCI_VENDOR_ID_INTASHIELD, 0x4015, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_oxsemi_4_15625000 }, + /* + * Brainboxes PX-260/PX-701 + */ + { PCI_VENDOR_ID_INTASHIELD, 0x400A, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_oxsemi_4_15625000 }, + /* + * Brainboxes PX-310 + */ + { PCI_VENDOR_ID_INTASHIELD, 0x400E, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_oxsemi_2_15625000 }, + /* + * Brainboxes PX-313 + */ + { PCI_VENDOR_ID_INTASHIELD, 0x400C, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_oxsemi_2_15625000 }, + /* + * Brainboxes PX-320/324/PX-376/PX-387 + */ + { PCI_VENDOR_ID_INTASHIELD, 0x400B, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_oxsemi_1_15625000 }, + /* + * Brainboxes PX-335/346 + */ + { PCI_VENDOR_ID_INTASHIELD, 0x400F, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_oxsemi_4_15625000 }, + /* + * Brainboxes PX-368 + */ + { PCI_VENDOR_ID_INTASHIELD, 0x4010, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_oxsemi_4_15625000 }, + /* + * Brainboxes PX-420 + */ + { PCI_VENDOR_ID_INTASHIELD, 0x4000, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_b0_4_115200 }, + { PCI_VENDOR_ID_INTASHIELD, 0x4011, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_oxsemi_4_15625000 }, + /* + * Brainboxes PX-803 + */ + { PCI_VENDOR_ID_INTASHIELD, 0x4009, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_b0_1_115200 }, + { PCI_VENDOR_ID_INTASHIELD, 0x401E, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_oxsemi_1_15625000 }, + /* + * Brainboxes PX-846 + */ + { PCI_VENDOR_ID_INTASHIELD, 0x4008, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_b0_1_115200 }, + { PCI_VENDOR_ID_INTASHIELD, 0x4017, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_oxsemi_1_15625000 }, + /* * Perle PCI-RAS cards */ -- cgit v1.2.3 From 806a449725cbd679a7f52c394d3c87b451d66bd5 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 11 Jul 2022 10:42:52 +0200 Subject: serial: 8250: SERIAL_8250_ASPEED_VUART should depend on ARCH_ASPEED The Aspeed Virtual UART is only present on Aspeed BMC platforms. Hence add a dependency on ARCH_ASPEED, to prevent asking the user about this driver when configuring a kernel without Aspeed BMC support. Reviewed-by: Jeremy Kerr Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/259138c372d433005b4871789ef9ee8d15320307.1657528861.git.geert+renesas@glider.be Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index fdb6c4188695..d0b49e15fbf5 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -254,6 +254,7 @@ config SERIAL_8250_ASPEED_VUART depends on SERIAL_8250 depends on OF depends on REGMAP && MFD_SYSCON + depends on ARCH_ASPEED || COMPILE_TEST help If you want to use the virtual UART (VUART) device on Aspeed BMC platforms, enable this option. This enables the 16550A- -- cgit v1.2.3 From 1d46c08d246e2e0a2d81985727392a5a8348d06a Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 12 Jul 2022 16:07:45 +0200 Subject: tty: serial: samsung_tty: fix s3c24xx_serial_set_mctrl() S3C2410_UCON is a 32bit register, so it must be read with rd_regl() instead of rd_reg(), otherwise the upper bits will be zeroed. Fix this. Fixes: 72a43046b61a ("tty: serial: samsung_tty: loopback mode support") Tested-by: Chanho Park Reviewed-by: Krzysztof Kozlowski Reviewed-by: Chanho Park Signed-off-by: Marek Szyprowski Link: https://lore.kernel.org/r/20220712140745.30362-1-m.szyprowski@samsung.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung_tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c index 8971fbb49fa3..0fd4ac58c6ce 100644 --- a/drivers/tty/serial/samsung_tty.c +++ b/drivers/tty/serial/samsung_tty.c @@ -1018,7 +1018,7 @@ static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port) static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) { unsigned int umcon = rd_regl(port, S3C2410_UMCON); - unsigned int ucon = rd_reg(port, S3C2410_UCON); + unsigned int ucon = rd_regl(port, S3C2410_UCON); if (mctrl & TIOCM_RTS) umcon |= S3C2410_UMCOM_RTS_LOW; -- cgit v1.2.3 From 4f4e670342b14f302e17c93bd22fc943bbaaf1de Mon Sep 17 00:00:00 2001 From: VAMSHI GAJJELA Date: Wed, 13 Jul 2022 18:47:22 +0530 Subject: serial: 8250_dw: Avoid pslverr on reading empty receiver fifo With PSLVERR_RESP_EN parameter set to 1, the device generates an error response when an attempt to read an empty RBR with FIFO enabled. This happens when LCR writes are ignored when UART is busy. dw8250_check_lcr() in retries to update LCR, invokes dw8250_force_idle() to clear and reset FIFO and eventually reads UART_RX causing the error. Avoid this by not reading RBR/UART_RX when no data is available. Reviewed-by: Andy Shevchenko Signed-off-by: VAMSHI GAJJELA Link: https://lore.kernel.org/r/20220713131722.2316829-1-vamshigajjela@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index e419e032895c..f9e85ed0c50b 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -83,8 +83,21 @@ static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) static void dw8250_force_idle(struct uart_port *p) { struct uart_8250_port *up = up_to_u8250p(p); + unsigned int lsr; serial8250_clear_and_reinit_fifos(up); + + /* + * With PSLVERR_RESP_EN parameter set to 1, the device generates an + * error response when an attempt to read an empty RBR with FIFO + * enabled. + */ + if (up->fcr & UART_FCR_ENABLE_FIFO) { + lsr = p->serial_in(p, UART_LSR); + if (!(lsr & UART_LSR_DR)) + return; + } + (void)p->serial_in(p, UART_RX); } -- cgit v1.2.3 From 3182efd036c1b955403d131258234896cbd9fbeb Mon Sep 17 00:00:00 2001 From: Doug Berger Date: Wed, 13 Jul 2022 20:13:15 -0700 Subject: serial: 8250_bcm7271: Save/restore RTS in suspend/resume Commit 9cabe26e65a8 ("serial: 8250_bcm7271: UART errors after resuming from S2") prevented an early enabling of RTS during resume, but it did not actively restore the RTS state after resume. Fixes: 9cabe26e65a8 ("serial: 8250_bcm7271: UART errors after resuming from S2") Signed-off-by: Doug Berger Signed-off-by: Florian Fainelli Link: https://lore.kernel.org/r/20220714031316.404918-1-f.fainelli@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_bcm7271.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c index 9b878d023dac..8efdc271eb75 100644 --- a/drivers/tty/serial/8250/8250_bcm7271.c +++ b/drivers/tty/serial/8250/8250_bcm7271.c @@ -1139,16 +1139,19 @@ static int __maybe_unused brcmuart_suspend(struct device *dev) struct brcmuart_priv *priv = dev_get_drvdata(dev); struct uart_8250_port *up = serial8250_get_port(priv->line); struct uart_port *port = &up->port; - - serial8250_suspend_port(priv->line); - clk_disable_unprepare(priv->baud_mux_clk); + unsigned long flags; /* * This will prevent resume from enabling RTS before the - * baud rate has been resored. + * baud rate has been restored. */ + spin_lock_irqsave(&port->lock, flags); priv->saved_mctrl = port->mctrl; - port->mctrl = 0; + port->mctrl &= ~TIOCM_RTS; + spin_unlock_irqrestore(&port->lock, flags); + + serial8250_suspend_port(priv->line); + clk_disable_unprepare(priv->baud_mux_clk); return 0; } @@ -1158,6 +1161,7 @@ static int __maybe_unused brcmuart_resume(struct device *dev) struct brcmuart_priv *priv = dev_get_drvdata(dev); struct uart_8250_port *up = serial8250_get_port(priv->line); struct uart_port *port = &up->port; + unsigned long flags; int ret; ret = clk_prepare_enable(priv->baud_mux_clk); @@ -1180,7 +1184,15 @@ static int __maybe_unused brcmuart_resume(struct device *dev) start_rx_dma(serial8250_get_port(priv->line)); } serial8250_resume_port(priv->line); - port->mctrl = priv->saved_mctrl; + + if (priv->saved_mctrl & TIOCM_RTS) { + /* Restore RTS */ + spin_lock_irqsave(&port->lock, flags); + port->mctrl |= TIOCM_RTS; + port->ops->set_mctrl(port, port->mctrl); + spin_unlock_irqrestore(&port->lock, flags); + } + return 0; } -- cgit v1.2.3 From 996fd3cf9c0f37d17867ccc26f8b746169463fcd Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo Date: Sun, 10 Jul 2022 18:44:35 +0200 Subject: serial: ar933x: Fix check for RS485 support RS485 is not possible without an RTS GPIO regardless of whether RS485 is enabled at boot time or not. So correct the concerning check in the probe() function. Fixes: e849145e1fdd ("serial: ar933x: Fill in rs485_supported") Signed-off-by: Lino Sanfilippo Link: https://lore.kernel.org/r/20220710164442.2958979-2-LinoSanfilippo@gmx.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/ar933x_uart.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c index f931ecbc0bc0..f7b4638d69e5 100644 --- a/drivers/tty/serial/ar933x_uart.c +++ b/drivers/tty/serial/ar933x_uart.c @@ -798,11 +798,12 @@ static int ar933x_uart_probe(struct platform_device *pdev) up->rts_gpiod = mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_RTS); - if ((port->rs485.flags & SER_RS485_ENABLED) && - !up->rts_gpiod) { - dev_err(&pdev->dev, "lacking rts-gpio, disabling RS485\n"); - port->rs485.flags &= ~SER_RS485_ENABLED; + if (!up->rts_gpiod) { port->rs485_supported = ar933x_no_rs485; + if (port->rs485.flags & SER_RS485_ENABLED) { + dev_err(&pdev->dev, "lacking rts-gpio, disabling RS485\n"); + port->rs485.flags &= ~SER_RS485_ENABLED; + } } #ifdef CONFIG_SERIAL_AR933X_CONSOLE -- cgit v1.2.3 From 184842622c97da2f88f365a981af05432baa5385 Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo Date: Sun, 10 Jul 2022 18:44:36 +0200 Subject: serial: ar933x: Remove superfluous code in ar933x_config_rs485() In ar933x_config_rs485() the check for the RTS GPIO is not needed since in case the GPIO is not available at driver init ar933x_no_rs485 is assigned to port->rs485_supported and this function is never called. So remove the check. Also in uart_set_rs485_config() the serial core already assigns the passed serial_rs485 struct to the uart port. So remove the assignment in the drivers rs485_config() function to avoid redundancy. Signed-off-by: Lino Sanfilippo Link: https://lore.kernel.org/r/20220710164442.2958979-3-LinoSanfilippo@gmx.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/ar933x_uart.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c index f7b4638d69e5..32caeac12985 100644 --- a/drivers/tty/serial/ar933x_uart.c +++ b/drivers/tty/serial/ar933x_uart.c @@ -583,15 +583,6 @@ static const struct uart_ops ar933x_uart_ops = { static int ar933x_config_rs485(struct uart_port *port, struct ktermios *termios, struct serial_rs485 *rs485conf) { - struct ar933x_uart_port *up = - container_of(port, struct ar933x_uart_port, port); - - if ((rs485conf->flags & SER_RS485_ENABLED) && - !up->rts_gpiod) { - dev_err(port->dev, "RS485 needs rts-gpio\n"); - return 1; - } - port->rs485 = *rs485conf; return 0; } -- cgit v1.2.3 From 44b27aec9d9680875a1a250bc8bcefc234a37c9f Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo Date: Sun, 10 Jul 2022 18:44:37 +0200 Subject: serial: core, 8250: set RS485 termination GPIO in serial core In serial8250_em485_config() the termination GPIO is set with the uart_port spinlock held. This is an issue if setting the GPIO line can sleep (e.g. since the concerning GPIO expander is connected via SPI or I2C). Fix this by setting the termination line outside of the uart_port spinlock in the serial core and using gpiod_set_value_cansleep() which instead of gpiod_set_value() allows it to sleep. Beside fixing the termination GPIO line setting for the 8250 driver this change also makes setting the termination GPIO generic for all UART drivers. Signed-off-by: Lino Sanfilippo Link: https://lore.kernel.org/r/20220710164442.2958979-4-LinoSanfilippo@gmx.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 3 --- drivers/tty/serial/serial_core.c | 12 ++++++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index ed2a606f2da7..72252d956f17 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -676,9 +676,6 @@ int serial8250_em485_config(struct uart_port *port, struct ktermios *termios, rs485->flags &= ~SER_RS485_RTS_AFTER_SEND; } - gpiod_set_value(port->rs485_term_gpio, - rs485->flags & SER_RS485_TERMINATE_BUS); - /* * Both serial8250_em485_init() and serial8250_em485_destroy() * are idempotent. diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 1db44cde76f6..047ec51dbd41 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1358,12 +1358,23 @@ static void uart_sanitize_serial_rs485(struct uart_port *port, struct serial_rs4 memset(rs485->padding1, 0, sizeof(rs485->padding1)); } +static void uart_set_rs485_termination(struct uart_port *port, + const struct serial_rs485 *rs485) +{ + if (!(rs485->flags & SER_RS485_ENABLED)) + return; + + gpiod_set_value_cansleep(port->rs485_term_gpio, + !!(rs485->flags & SER_RS485_TERMINATE_BUS)); +} + int uart_rs485_config(struct uart_port *port) { struct serial_rs485 *rs485 = &port->rs485; int ret; uart_sanitize_serial_rs485(port, rs485); + uart_set_rs485_termination(port, rs485); ret = port->rs485_config(port, NULL, rs485); if (ret) @@ -1406,6 +1417,7 @@ static int uart_set_rs485_config(struct tty_struct *tty, struct uart_port *port, if (ret) return ret; uart_sanitize_serial_rs485(port, &rs485); + uart_set_rs485_termination(port, &rs485); spin_lock_irqsave(&port->lock, flags); ret = port->rs485_config(port, &tty->termios, &rs485); -- cgit v1.2.3 From d8fcd9cfbde5acd42a407d8b48fa80ad9d513bde Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo Date: Sun, 10 Jul 2022 18:44:38 +0200 Subject: serial: core: move sanitizing of RS485 delays into own function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the sanitizing of RS485 delays out of uart_sanitize_serial_rs485() into the new function uart_sanitize_serial_rs485_delays(). Reviewed-by: Ilpo Järvinen Signed-off-by: Lino Sanfilippo Link: https://lore.kernel.org/r/20220710164442.2958979-5-LinoSanfilippo@gmx.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 46 +++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 20 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 047ec51dbd41..3158f05a328c 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1302,27 +1302,9 @@ static int uart_check_rs485_flags(struct uart_port *port, struct serial_rs485 *r return 0; } -static void uart_sanitize_serial_rs485(struct uart_port *port, struct serial_rs485 *rs485) +static void uart_sanitize_serial_rs485_delays(struct uart_port *port, + struct serial_rs485 *rs485) { - u32 supported_flags = port->rs485_supported.flags; - - if (!(rs485->flags & SER_RS485_ENABLED)) { - memset(rs485, 0, sizeof(*rs485)); - return; - } - - /* pick sane settings if the user hasn't */ - if ((supported_flags & (SER_RS485_RTS_ON_SEND|SER_RS485_RTS_AFTER_SEND)) && - !(rs485->flags & SER_RS485_RTS_ON_SEND) == - !(rs485->flags & SER_RS485_RTS_AFTER_SEND)) { - dev_warn_ratelimited(port->dev, - "%s (%d): invalid RTS setting, using RTS_ON_SEND instead\n", - port->name, port->line); - rs485->flags |= SER_RS485_RTS_ON_SEND; - rs485->flags &= ~SER_RS485_RTS_AFTER_SEND; - supported_flags |= SER_RS485_RTS_ON_SEND|SER_RS485_RTS_AFTER_SEND; - } - if (!port->rs485_supported.delay_rts_before_send) { if (rs485->delay_rts_before_send) { dev_warn_ratelimited(port->dev, @@ -1350,9 +1332,33 @@ static void uart_sanitize_serial_rs485(struct uart_port *port, struct serial_rs4 "%s (%d): RTS delay after sending clamped to %u ms\n", port->name, port->line, rs485->delay_rts_after_send); } +} + +static void uart_sanitize_serial_rs485(struct uart_port *port, struct serial_rs485 *rs485) +{ + u32 supported_flags = port->rs485_supported.flags; + + if (!(rs485->flags & SER_RS485_ENABLED)) { + memset(rs485, 0, sizeof(*rs485)); + return; + } + + /* Pick sane settings if the user hasn't */ + if ((supported_flags & (SER_RS485_RTS_ON_SEND|SER_RS485_RTS_AFTER_SEND)) && + !(rs485->flags & SER_RS485_RTS_ON_SEND) == + !(rs485->flags & SER_RS485_RTS_AFTER_SEND)) { + dev_warn_ratelimited(port->dev, + "%s (%d): invalid RTS setting, using RTS_ON_SEND instead\n", + port->name, port->line); + rs485->flags |= SER_RS485_RTS_ON_SEND; + rs485->flags &= ~SER_RS485_RTS_AFTER_SEND; + supported_flags |= SER_RS485_RTS_ON_SEND|SER_RS485_RTS_AFTER_SEND; + } rs485->flags &= supported_flags; + uart_sanitize_serial_rs485_delays(port, rs485); + /* Return clean padding area to userspace */ memset(rs485->padding0, 0, sizeof(rs485->padding0)); memset(rs485->padding1, 0, sizeof(rs485->padding1)); -- cgit v1.2.3 From 4dfd10351e49a767f145fb0f6bf7f408f54ab94b Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo Date: Sun, 10 Jul 2022 18:44:39 +0200 Subject: serial: core: sanitize RS485 delays read from device tree Currently the RTS delays set via device tree are not clamped to a maximum value although the device tree bindings documentation for RS485 claims that only a maximum of 1000 msecs is allowed. So clamp the values to avoid arbitrary high delay settings. However clamp the values to 100 instead of 1000 msecs to be consistent which the maximum that is allowed when setting the delays from userspace via the UART ioctl TIOCSRS485. Signed-off-by: Lino Sanfilippo Link: https://lore.kernel.org/r/20220710164442.2958979-6-LinoSanfilippo@gmx.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 3158f05a328c..ac198d0d4c80 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -3395,6 +3395,8 @@ int uart_get_rs485_mode(struct uart_port *port) rs485conf->delay_rts_after_send = 0; } + uart_sanitize_serial_rs485_delays(port, rs485conf); + /* * Clear full-duplex and enabled flags, set RTS polarity to active high * to get to a defined state with the following properties: -- cgit v1.2.3 From c64e17584ba78552b51a27374b54686259826360 Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo Date: Sun, 10 Jul 2022 18:44:41 +0200 Subject: serial: 8250_dwlib: remove redundant sanity check for RS485 flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before the drivers rs485_config() function is called the serial core already ensures that only one of both options RTS on send or RTS after send is set. So remove the concerning sanity check in the driver function to avoid redundancy. Reviewed-by: Ilpo Järvinen Signed-off-by: Lino Sanfilippo Link: https://lore.kernel.org/r/20220710164442.2958979-8-LinoSanfilippo@gmx.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dwlib.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_dwlib.c b/drivers/tty/serial/8250/8250_dwlib.c index 2c3b1468bd88..dbe4d44f60d4 100644 --- a/drivers/tty/serial/8250/8250_dwlib.c +++ b/drivers/tty/serial/8250/8250_dwlib.c @@ -187,16 +187,10 @@ static int dw8250_rs485_config(struct uart_port *p, struct ktermios *termios, if (rs485->flags & SER_RS485_ENABLED) { tcr |= DW_UART_TCR_RS485_EN; - if (rs485->flags & SER_RS485_RX_DURING_TX) { + if (rs485->flags & SER_RS485_RX_DURING_TX) tcr |= DW_UART_TCR_XFER_MODE_DE_DURING_RE; - } else { - /* HW does not support same DE level for tx and rx */ - if (!(rs485->flags & SER_RS485_RTS_ON_SEND) == - !(rs485->flags & SER_RS485_RTS_AFTER_SEND)) - return -EINVAL; - + else tcr |= DW_UART_TCR_XFER_MODE_DE_OR_RE; - } dw8250_writel_ext(p, DW_UART_DE_EN, 1); dw8250_writel_ext(p, DW_UART_RE_EN, 1); } else { -- cgit v1.2.3 From 5095ca634f8b134cc202a5f5e4985d2b81f0ef0a Mon Sep 17 00:00:00 2001 From: Lino Sanfilippo Date: Sun, 10 Jul 2022 18:44:42 +0200 Subject: serial: 8250: lpc18xx: Remove redundant sanity check for RS485 flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before the drivers rs485_config() function is called the serial core already ensures that only one of both options RTS on send or RTS after send is set. So remove the concerning sanity check in the driver function to avoid redundancy. Reviewed-by: Ilpo Järvinen Signed-off-by: Lino Sanfilippo Link: https://lore.kernel.org/r/20220710164442.2958979-9-LinoSanfilippo@gmx.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_lpc18xx.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_lpc18xx.c b/drivers/tty/serial/8250/8250_lpc18xx.c index d6ca0d47e9d5..6dc85aaba5d0 100644 --- a/drivers/tty/serial/8250/8250_lpc18xx.c +++ b/drivers/tty/serial/8250/8250_lpc18xx.c @@ -44,12 +44,8 @@ static int lpc18xx_rs485_config(struct uart_port *port, struct ktermios *termios rs485_ctrl_reg |= LPC18XX_UART_RS485CTRL_NMMEN | LPC18XX_UART_RS485CTRL_DCTRL; - if (rs485->flags & SER_RS485_RTS_ON_SEND) { + if (rs485->flags & SER_RS485_RTS_ON_SEND) rs485_ctrl_reg |= LPC18XX_UART_RS485CTRL_OINV; - rs485->flags &= ~SER_RS485_RTS_AFTER_SEND; - } else { - rs485->flags |= SER_RS485_RTS_AFTER_SEND; - } } if (rs485->delay_rts_after_send) { -- cgit v1.2.3 From ceefa81e6e69b020997205e5c30a42d43aa5ae63 Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Fri, 15 Jul 2022 16:03:22 +0200 Subject: serial: remove VR41XX serial driver Commit d3164e2f3b0a ("MIPS: Remove VR41xx support") removed support for MIPS VR41xx platform, so remove exclusive drivers for this platform, too. Signed-off-by: Thomas Bogendoerfer Link: https://lore.kernel.org/r/20220715140322.135825-1-tsbogend@alpha.franken.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 17 - drivers/tty/serial/Makefile | 1 - drivers/tty/serial/vr41xx_siu.c | 932 --------------------------------------- include/uapi/linux/serial_core.h | 4 - 4 files changed, 954 deletions(-) delete mode 100644 drivers/tty/serial/vr41xx_siu.c (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 8a3ee1525d80..f92963a2226b 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -890,23 +890,6 @@ config SERIAL_TXX9_STDSERIAL bool "TX39XX/49XX SIO act as standard serial" depends on !SERIAL_8250 && SERIAL_TXX9 -config SERIAL_VR41XX - tristate "NEC VR4100 series Serial Interface Unit support" - depends on CPU_VR41XX - select SERIAL_CORE - help - If you have a NEC VR4100 series processor and you want to use - Serial Interface Unit(SIU) or Debug Serial Interface Unit(DSIU) - (not include VR4111/VR4121 DSIU), say Y. Otherwise, say N. - -config SERIAL_VR41XX_CONSOLE - bool "Enable NEC VR4100 series Serial Interface Unit console" - depends on SERIAL_VR41XX=y - select SERIAL_CORE_CONSOLE - help - If you have a NEC VR4100 series processor and you want to use - a console on a serial port, say Y. Otherwise, say N. - config SERIAL_JSM tristate "Digi International NEO and Classic PCI Support" depends on PCI diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 61cc8de95571..238a9557b487 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -51,7 +51,6 @@ obj-$(CONFIG_SERIAL_SCCNXP) += sccnxp.o obj-$(CONFIG_SERIAL_SC16IS7XX_CORE) += sc16is7xx.o obj-$(CONFIG_SERIAL_JSM) += jsm/ obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o -obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o obj-$(CONFIG_SERIAL_MSM) += msm_serial.o diff --git a/drivers/tty/serial/vr41xx_siu.c b/drivers/tty/serial/vr41xx_siu.c deleted file mode 100644 index 1ba689a81abd..000000000000 --- a/drivers/tty/serial/vr41xx_siu.c +++ /dev/null @@ -1,932 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Driver for NEC VR4100 series Serial Interface Unit. - * - * Copyright (C) 2004-2008 Yoichi Yuasa - * - * Based on drivers/serial/8250.c, by Russell King. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define SIU_BAUD_BASE 1152000 -#define SIU_MAJOR 204 -#define SIU_MINOR_BASE 82 - -#define RX_MAX_COUNT 256 -#define TX_MAX_COUNT 15 - -#define SIUIRSEL 0x08 - #define TMICMODE 0x20 - #define TMICTX 0x10 - #define IRMSEL 0x0c - #define IRMSEL_HP 0x08 - #define IRMSEL_TEMIC 0x04 - #define IRMSEL_SHARP 0x00 - #define IRUSESEL 0x02 - #define SIRSEL 0x01 - -static struct uart_port siu_uart_ports[SIU_PORTS_MAX] = { - [0 ... SIU_PORTS_MAX-1] = { - .lock = __SPIN_LOCK_UNLOCKED(siu_uart_ports->lock), - .irq = 0, - }, -}; - -#ifdef CONFIG_SERIAL_VR41XX_CONSOLE -static uint8_t lsr_break_flag[SIU_PORTS_MAX]; -#endif - -#define siu_read(port, offset) readb((port)->membase + (offset)) -#define siu_write(port, offset, value) writeb((value), (port)->membase + (offset)) - -void vr41xx_select_siu_interface(siu_interface_t interface) -{ - struct uart_port *port; - unsigned long flags; - uint8_t irsel; - - port = &siu_uart_ports[0]; - - spin_lock_irqsave(&port->lock, flags); - - irsel = siu_read(port, SIUIRSEL); - if (interface == SIU_INTERFACE_IRDA) - irsel |= SIRSEL; - else - irsel &= ~SIRSEL; - siu_write(port, SIUIRSEL, irsel); - - spin_unlock_irqrestore(&port->lock, flags); -} -EXPORT_SYMBOL_GPL(vr41xx_select_siu_interface); - -void vr41xx_use_irda(irda_use_t use) -{ - struct uart_port *port; - unsigned long flags; - uint8_t irsel; - - port = &siu_uart_ports[0]; - - spin_lock_irqsave(&port->lock, flags); - - irsel = siu_read(port, SIUIRSEL); - if (use == FIR_USE_IRDA) - irsel |= IRUSESEL; - else - irsel &= ~IRUSESEL; - siu_write(port, SIUIRSEL, irsel); - - spin_unlock_irqrestore(&port->lock, flags); -} -EXPORT_SYMBOL_GPL(vr41xx_use_irda); - -void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed) -{ - struct uart_port *port; - unsigned long flags; - uint8_t irsel; - - port = &siu_uart_ports[0]; - - spin_lock_irqsave(&port->lock, flags); - - irsel = siu_read(port, SIUIRSEL); - irsel &= ~(IRMSEL | TMICTX | TMICMODE); - switch (module) { - case SHARP_IRDA: - irsel |= IRMSEL_SHARP; - break; - case TEMIC_IRDA: - irsel |= IRMSEL_TEMIC | TMICMODE; - if (speed == IRDA_TX_4MBPS) - irsel |= TMICTX; - break; - case HP_IRDA: - irsel |= IRMSEL_HP; - break; - default: - break; - } - siu_write(port, SIUIRSEL, irsel); - - spin_unlock_irqrestore(&port->lock, flags); -} -EXPORT_SYMBOL_GPL(vr41xx_select_irda_module); - -static inline void siu_clear_fifo(struct uart_port *port) -{ - siu_write(port, UART_FCR, UART_FCR_ENABLE_FIFO); - siu_write(port, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | - UART_FCR_CLEAR_XMIT); - siu_write(port, UART_FCR, 0); -} - -static inline unsigned long siu_port_size(struct uart_port *port) -{ - switch (port->type) { - case PORT_VR41XX_SIU: - return 11UL; - case PORT_VR41XX_DSIU: - return 8UL; - } - - return 0; -} - -static inline unsigned int siu_check_type(struct uart_port *port) -{ - if (port->line == 0) - return PORT_VR41XX_SIU; - if (port->line == 1 && port->irq) - return PORT_VR41XX_DSIU; - - return PORT_UNKNOWN; -} - -static inline const char *siu_type_name(struct uart_port *port) -{ - switch (port->type) { - case PORT_VR41XX_SIU: - return "SIU"; - case PORT_VR41XX_DSIU: - return "DSIU"; - } - - return NULL; -} - -static unsigned int siu_tx_empty(struct uart_port *port) -{ - uint8_t lsr; - - lsr = siu_read(port, UART_LSR); - if (lsr & UART_LSR_TEMT) - return TIOCSER_TEMT; - - return 0; -} - -static void siu_set_mctrl(struct uart_port *port, unsigned int mctrl) -{ - uint8_t mcr = 0; - - if (mctrl & TIOCM_DTR) - mcr |= UART_MCR_DTR; - if (mctrl & TIOCM_RTS) - mcr |= UART_MCR_RTS; - if (mctrl & TIOCM_OUT1) - mcr |= UART_MCR_OUT1; - if (mctrl & TIOCM_OUT2) - mcr |= UART_MCR_OUT2; - if (mctrl & TIOCM_LOOP) - mcr |= UART_MCR_LOOP; - - siu_write(port, UART_MCR, mcr); -} - -static unsigned int siu_get_mctrl(struct uart_port *port) -{ - uint8_t msr; - unsigned int mctrl = 0; - - msr = siu_read(port, UART_MSR); - if (msr & UART_MSR_DCD) - mctrl |= TIOCM_CAR; - if (msr & UART_MSR_RI) - mctrl |= TIOCM_RNG; - if (msr & UART_MSR_DSR) - mctrl |= TIOCM_DSR; - if (msr & UART_MSR_CTS) - mctrl |= TIOCM_CTS; - - return mctrl; -} - -static void siu_stop_tx(struct uart_port *port) -{ - unsigned long flags; - uint8_t ier; - - spin_lock_irqsave(&port->lock, flags); - - ier = siu_read(port, UART_IER); - ier &= ~UART_IER_THRI; - siu_write(port, UART_IER, ier); - - spin_unlock_irqrestore(&port->lock, flags); -} - -static void siu_start_tx(struct uart_port *port) -{ - unsigned long flags; - uint8_t ier; - - spin_lock_irqsave(&port->lock, flags); - - ier = siu_read(port, UART_IER); - ier |= UART_IER_THRI; - siu_write(port, UART_IER, ier); - - spin_unlock_irqrestore(&port->lock, flags); -} - -static void siu_stop_rx(struct uart_port *port) -{ - unsigned long flags; - uint8_t ier; - - spin_lock_irqsave(&port->lock, flags); - - ier = siu_read(port, UART_IER); - ier &= ~UART_IER_RLSI; - siu_write(port, UART_IER, ier); - - port->read_status_mask &= ~UART_LSR_DR; - - spin_unlock_irqrestore(&port->lock, flags); -} - -static void siu_enable_ms(struct uart_port *port) -{ - unsigned long flags; - uint8_t ier; - - spin_lock_irqsave(&port->lock, flags); - - ier = siu_read(port, UART_IER); - ier |= UART_IER_MSI; - siu_write(port, UART_IER, ier); - - spin_unlock_irqrestore(&port->lock, flags); -} - -static void siu_break_ctl(struct uart_port *port, int ctl) -{ - unsigned long flags; - uint8_t lcr; - - spin_lock_irqsave(&port->lock, flags); - - lcr = siu_read(port, UART_LCR); - if (ctl == -1) - lcr |= UART_LCR_SBC; - else - lcr &= ~UART_LCR_SBC; - siu_write(port, UART_LCR, lcr); - - spin_unlock_irqrestore(&port->lock, flags); -} - -static inline void receive_chars(struct uart_port *port, uint8_t *status) -{ - uint8_t lsr, ch; - char flag; - int max_count = RX_MAX_COUNT; - - lsr = *status; - - do { - ch = siu_read(port, UART_RX); - port->icount.rx++; - flag = TTY_NORMAL; - -#ifdef CONFIG_SERIAL_VR41XX_CONSOLE - lsr |= lsr_break_flag[port->line]; - lsr_break_flag[port->line] = 0; -#endif - if (unlikely(lsr & (UART_LSR_BI | UART_LSR_FE | - UART_LSR_PE | UART_LSR_OE))) { - if (lsr & UART_LSR_BI) { - lsr &= ~(UART_LSR_FE | UART_LSR_PE); - port->icount.brk++; - - if (uart_handle_break(port)) - goto ignore_char; - } - - if (lsr & UART_LSR_FE) - port->icount.frame++; - if (lsr & UART_LSR_PE) - port->icount.parity++; - if (lsr & UART_LSR_OE) - port->icount.overrun++; - - lsr &= port->read_status_mask; - if (lsr & UART_LSR_BI) - flag = TTY_BREAK; - if (lsr & UART_LSR_FE) - flag = TTY_FRAME; - if (lsr & UART_LSR_PE) - flag = TTY_PARITY; - } - - if (uart_handle_sysrq_char(port, ch)) - goto ignore_char; - - uart_insert_char(port, lsr, UART_LSR_OE, ch, flag); - - ignore_char: - lsr = siu_read(port, UART_LSR); - } while ((lsr & UART_LSR_DR) && (max_count-- > 0)); - - tty_flip_buffer_push(&port->state->port); - - *status = lsr; -} - -static inline void check_modem_status(struct uart_port *port) -{ - uint8_t msr; - - msr = siu_read(port, UART_MSR); - if ((msr & UART_MSR_ANY_DELTA) == 0) - return; - if (msr & UART_MSR_DDCD) - uart_handle_dcd_change(port, msr & UART_MSR_DCD); - if (msr & UART_MSR_TERI) - port->icount.rng++; - if (msr & UART_MSR_DDSR) - port->icount.dsr++; - if (msr & UART_MSR_DCTS) - uart_handle_cts_change(port, msr & UART_MSR_CTS); - - wake_up_interruptible(&port->state->port.delta_msr_wait); -} - -static inline void transmit_chars(struct uart_port *port) -{ - struct circ_buf *xmit; - int max_count = TX_MAX_COUNT; - - xmit = &port->state->xmit; - - if (port->x_char) { - siu_write(port, UART_TX, port->x_char); - port->icount.tx++; - port->x_char = 0; - return; - } - - if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - siu_stop_tx(port); - return; - } - - do { - siu_write(port, UART_TX, xmit->buf[xmit->tail]); - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - port->icount.tx++; - if (uart_circ_empty(xmit)) - break; - } while (max_count-- > 0); - - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(port); - - if (uart_circ_empty(xmit)) - siu_stop_tx(port); -} - -static irqreturn_t siu_interrupt(int irq, void *dev_id) -{ - struct uart_port *port; - uint8_t iir, lsr; - - port = (struct uart_port *)dev_id; - - iir = siu_read(port, UART_IIR); - if (iir & UART_IIR_NO_INT) - return IRQ_NONE; - - lsr = siu_read(port, UART_LSR); - if (lsr & UART_LSR_DR) - receive_chars(port, &lsr); - - check_modem_status(port); - - if (lsr & UART_LSR_THRE) - transmit_chars(port); - - return IRQ_HANDLED; -} - -static int siu_startup(struct uart_port *port) -{ - int retval; - - if (port->membase == NULL) - return -ENODEV; - - siu_clear_fifo(port); - - (void)siu_read(port, UART_LSR); - (void)siu_read(port, UART_RX); - (void)siu_read(port, UART_IIR); - (void)siu_read(port, UART_MSR); - - if (siu_read(port, UART_LSR) == 0xff) - return -ENODEV; - - retval = request_irq(port->irq, siu_interrupt, 0, siu_type_name(port), port); - if (retval) - return retval; - - if (port->type == PORT_VR41XX_DSIU) - vr41xx_enable_dsiuint(DSIUINT_ALL); - - siu_write(port, UART_LCR, UART_LCR_WLEN8); - - spin_lock_irq(&port->lock); - siu_set_mctrl(port, port->mctrl); - spin_unlock_irq(&port->lock); - - siu_write(port, UART_IER, UART_IER_RLSI | UART_IER_RDI); - - (void)siu_read(port, UART_LSR); - (void)siu_read(port, UART_RX); - (void)siu_read(port, UART_IIR); - (void)siu_read(port, UART_MSR); - - return 0; -} - -static void siu_shutdown(struct uart_port *port) -{ - unsigned long flags; - uint8_t lcr; - - siu_write(port, UART_IER, 0); - - spin_lock_irqsave(&port->lock, flags); - - port->mctrl &= ~TIOCM_OUT2; - siu_set_mctrl(port, port->mctrl); - - spin_unlock_irqrestore(&port->lock, flags); - - lcr = siu_read(port, UART_LCR); - lcr &= ~UART_LCR_SBC; - siu_write(port, UART_LCR, lcr); - - siu_clear_fifo(port); - - (void)siu_read(port, UART_RX); - - if (port->type == PORT_VR41XX_DSIU) - vr41xx_disable_dsiuint(DSIUINT_ALL); - - free_irq(port->irq, port); -} - -static void siu_set_termios(struct uart_port *port, struct ktermios *new, - struct ktermios *old) -{ - tcflag_t c_cflag, c_iflag; - uint8_t lcr, fcr, ier; - unsigned int baud, quot; - unsigned long flags; - - c_cflag = new->c_cflag; - lcr = UART_LCR_WLEN(tty_get_char_size(c_cflag)); - - if (c_cflag & CSTOPB) - lcr |= UART_LCR_STOP; - if (c_cflag & PARENB) - lcr |= UART_LCR_PARITY; - if ((c_cflag & PARODD) != PARODD) - lcr |= UART_LCR_EPAR; - if (c_cflag & CMSPAR) - lcr |= UART_LCR_SPAR; - - baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16); - quot = uart_get_divisor(port, baud); - - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10; - - spin_lock_irqsave(&port->lock, flags); - - uart_update_timeout(port, c_cflag, baud); - - c_iflag = new->c_iflag; - - port->read_status_mask = UART_LSR_THRE | UART_LSR_OE | UART_LSR_DR; - if (c_iflag & INPCK) - port->read_status_mask |= UART_LSR_FE | UART_LSR_PE; - if (c_iflag & (IGNBRK | BRKINT | PARMRK)) - port->read_status_mask |= UART_LSR_BI; - - port->ignore_status_mask = 0; - if (c_iflag & IGNPAR) - port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE; - if (c_iflag & IGNBRK) { - port->ignore_status_mask |= UART_LSR_BI; - if (c_iflag & IGNPAR) - port->ignore_status_mask |= UART_LSR_OE; - } - - if ((c_cflag & CREAD) == 0) - port->ignore_status_mask |= UART_LSR_DR; - - ier = siu_read(port, UART_IER); - ier &= ~UART_IER_MSI; - if (UART_ENABLE_MS(port, c_cflag)) - ier |= UART_IER_MSI; - siu_write(port, UART_IER, ier); - - siu_write(port, UART_LCR, lcr | UART_LCR_DLAB); - - siu_write(port, UART_DLL, (uint8_t)quot); - siu_write(port, UART_DLM, (uint8_t)(quot >> 8)); - - siu_write(port, UART_LCR, lcr); - - siu_write(port, UART_FCR, fcr); - - siu_set_mctrl(port, port->mctrl); - - spin_unlock_irqrestore(&port->lock, flags); -} - -static void siu_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) -{ - switch (state) { - case 0: - switch (port->type) { - case PORT_VR41XX_SIU: - vr41xx_supply_clock(SIU_CLOCK); - break; - case PORT_VR41XX_DSIU: - vr41xx_supply_clock(DSIU_CLOCK); - break; - } - break; - case 3: - switch (port->type) { - case PORT_VR41XX_SIU: - vr41xx_mask_clock(SIU_CLOCK); - break; - case PORT_VR41XX_DSIU: - vr41xx_mask_clock(DSIU_CLOCK); - break; - } - break; - } -} - -static const char *siu_type(struct uart_port *port) -{ - return siu_type_name(port); -} - -static void siu_release_port(struct uart_port *port) -{ - unsigned long size; - - if (port->flags & UPF_IOREMAP) { - iounmap(port->membase); - port->membase = NULL; - } - - size = siu_port_size(port); - release_mem_region(port->mapbase, size); -} - -static int siu_request_port(struct uart_port *port) -{ - unsigned long size; - struct resource *res; - - size = siu_port_size(port); - res = request_mem_region(port->mapbase, size, siu_type_name(port)); - if (res == NULL) - return -EBUSY; - - if (port->flags & UPF_IOREMAP) { - port->membase = ioremap(port->mapbase, size); - if (port->membase == NULL) { - release_resource(res); - return -ENOMEM; - } - } - - return 0; -} - -static void siu_config_port(struct uart_port *port, int flags) -{ - if (flags & UART_CONFIG_TYPE) { - port->type = siu_check_type(port); - (void)siu_request_port(port); - } -} - -static int siu_verify_port(struct uart_port *port, struct serial_struct *serial) -{ - if (port->type != PORT_VR41XX_SIU && port->type != PORT_VR41XX_DSIU) - return -EINVAL; - if (port->irq != serial->irq) - return -EINVAL; - if (port->iotype != serial->io_type) - return -EINVAL; - if (port->mapbase != (unsigned long)serial->iomem_base) - return -EINVAL; - - return 0; -} - -static const struct uart_ops siu_uart_ops = { - .tx_empty = siu_tx_empty, - .set_mctrl = siu_set_mctrl, - .get_mctrl = siu_get_mctrl, - .stop_tx = siu_stop_tx, - .start_tx = siu_start_tx, - .stop_rx = siu_stop_rx, - .enable_ms = siu_enable_ms, - .break_ctl = siu_break_ctl, - .startup = siu_startup, - .shutdown = siu_shutdown, - .set_termios = siu_set_termios, - .pm = siu_pm, - .type = siu_type, - .release_port = siu_release_port, - .request_port = siu_request_port, - .config_port = siu_config_port, - .verify_port = siu_verify_port, -}; - -static int siu_init_ports(struct platform_device *pdev) -{ - struct uart_port *port; - struct resource *res; - int *type = dev_get_platdata(&pdev->dev); - int i; - - if (!type) - return 0; - - port = siu_uart_ports; - for (i = 0; i < SIU_PORTS_MAX; i++) { - port->type = type[i]; - if (port->type == PORT_UNKNOWN) - continue; - port->irq = platform_get_irq(pdev, i); - port->uartclk = SIU_BAUD_BASE * 16; - port->fifosize = 16; - port->regshift = 0; - port->iotype = UPIO_MEM; - port->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; - port->line = i; - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - port->mapbase = res->start; - port++; - } - - return i; -} - -#ifdef CONFIG_SERIAL_VR41XX_CONSOLE - -static void wait_for_xmitr(struct uart_port *port) -{ - int timeout = 10000; - uint8_t lsr, msr; - - do { - lsr = siu_read(port, UART_LSR); - if (lsr & UART_LSR_BI) - lsr_break_flag[port->line] = UART_LSR_BI; - - if (uart_lsr_tx_empty(lsr)) - break; - } while (timeout-- > 0); - - if (port->flags & UPF_CONS_FLOW) { - timeout = 1000000; - - do { - msr = siu_read(port, UART_MSR); - if ((msr & UART_MSR_CTS) != 0) - break; - } while (timeout-- > 0); - } -} - -static void siu_console_putchar(struct uart_port *port, unsigned char ch) -{ - wait_for_xmitr(port); - siu_write(port, UART_TX, ch); -} - -static void siu_console_write(struct console *con, const char *s, unsigned count) -{ - struct uart_port *port; - uint8_t ier; - - port = &siu_uart_ports[con->index]; - - ier = siu_read(port, UART_IER); - siu_write(port, UART_IER, 0); - - uart_console_write(port, s, count, siu_console_putchar); - - wait_for_xmitr(port); - siu_write(port, UART_IER, ier); -} - -static int __init siu_console_setup(struct console *con, char *options) -{ - struct uart_port *port; - int baud = 9600; - int parity = 'n'; - int bits = 8; - int flow = 'n'; - - if (con->index >= SIU_PORTS_MAX) - con->index = 0; - - port = &siu_uart_ports[con->index]; - if (port->membase == NULL) { - if (port->mapbase == 0) - return -ENODEV; - port->membase = ioremap(port->mapbase, siu_port_size(port)); - } - - if (port->type == PORT_VR41XX_SIU) - vr41xx_select_siu_interface(SIU_INTERFACE_RS232C); - - if (options != NULL) - uart_parse_options(options, &baud, &parity, &bits, &flow); - - return uart_set_options(port, con, baud, parity, bits, flow); -} - -static struct uart_driver siu_uart_driver; - -static struct console siu_console = { - .name = "ttyVR", - .write = siu_console_write, - .device = uart_console_device, - .setup = siu_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, - .data = &siu_uart_driver, -}; - -static int siu_console_init(void) -{ - struct uart_port *port; - int i; - - for (i = 0; i < SIU_PORTS_MAX; i++) { - port = &siu_uart_ports[i]; - port->ops = &siu_uart_ops; - } - - register_console(&siu_console); - - return 0; -} - -console_initcall(siu_console_init); - -void __init vr41xx_siu_early_setup(struct uart_port *port) -{ - if (port->type == PORT_UNKNOWN) - return; - - siu_uart_ports[port->line].line = port->line; - siu_uart_ports[port->line].type = port->type; - siu_uart_ports[port->line].uartclk = SIU_BAUD_BASE * 16; - siu_uart_ports[port->line].mapbase = port->mapbase; - siu_uart_ports[port->line].ops = &siu_uart_ops; -} - -#define SERIAL_VR41XX_CONSOLE &siu_console -#else -#define SERIAL_VR41XX_CONSOLE NULL -#endif - -static struct uart_driver siu_uart_driver = { - .owner = THIS_MODULE, - .driver_name = "SIU", - .dev_name = "ttyVR", - .major = SIU_MAJOR, - .minor = SIU_MINOR_BASE, - .cons = SERIAL_VR41XX_CONSOLE, -}; - -static int siu_probe(struct platform_device *dev) -{ - struct uart_port *port; - int num, i, retval; - - num = siu_init_ports(dev); - if (num <= 0) - return -ENODEV; - - siu_uart_driver.nr = num; - retval = uart_register_driver(&siu_uart_driver); - if (retval) - return retval; - - for (i = 0; i < num; i++) { - port = &siu_uart_ports[i]; - port->ops = &siu_uart_ops; - port->dev = &dev->dev; - port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_VR41XX_CONSOLE); - - retval = uart_add_one_port(&siu_uart_driver, port); - if (retval < 0) { - port->dev = NULL; - break; - } - } - - if (i == 0 && retval < 0) { - uart_unregister_driver(&siu_uart_driver); - return retval; - } - - return 0; -} - -static int siu_remove(struct platform_device *dev) -{ - struct uart_port *port; - int i; - - for (i = 0; i < siu_uart_driver.nr; i++) { - port = &siu_uart_ports[i]; - if (port->dev == &dev->dev) { - uart_remove_one_port(&siu_uart_driver, port); - port->dev = NULL; - } - } - - uart_unregister_driver(&siu_uart_driver); - - return 0; -} - -static int siu_suspend(struct platform_device *dev, pm_message_t state) -{ - struct uart_port *port; - int i; - - for (i = 0; i < siu_uart_driver.nr; i++) { - port = &siu_uart_ports[i]; - if ((port->type == PORT_VR41XX_SIU || - port->type == PORT_VR41XX_DSIU) && port->dev == &dev->dev) - uart_suspend_port(&siu_uart_driver, port); - - } - - return 0; -} - -static int siu_resume(struct platform_device *dev) -{ - struct uart_port *port; - int i; - - for (i = 0; i < siu_uart_driver.nr; i++) { - port = &siu_uart_ports[i]; - if ((port->type == PORT_VR41XX_SIU || - port->type == PORT_VR41XX_DSIU) && port->dev == &dev->dev) - uart_resume_port(&siu_uart_driver, port); - } - - return 0; -} - -static struct platform_driver siu_device_driver = { - .probe = siu_probe, - .remove = siu_remove, - .suspend = siu_suspend, - .resume = siu_resume, - .driver = { - .name = "SIU", - }, -}; - -module_platform_driver(siu_device_driver); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:SIU"); diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index 6faf502b7860..3ba34d8378bd 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h @@ -124,10 +124,6 @@ /* TXX9 type number */ #define PORT_TXX9 64 -/* NEC VR4100 series SIU/DSIU */ -#define PORT_VR41XX_SIU 65 -#define PORT_VR41XX_DSIU 66 - /* Samsung S3C2400 SoC */ #define PORT_S3C2400 67 -- cgit v1.2.3 From b9f1736e475dba0d6da48fdcb831248ab1597886 Mon Sep 17 00:00:00 2001 From: Guo Mengqi Date: Fri, 15 Jul 2022 10:33:12 +0800 Subject: serial: 8250_bcm2835aux: Add missing clk_disable_unprepare() The error path when get clock frequency fails in bcm2835aux_serial driver does not correctly disable the clock. This flaw was found using a static analysis tool "Hulk Robot", which reported the following warning when analyzing linux-next/master: drivers/tty/serial/8250/8250_bcm2835aux.c: warning: clk_disable_unprepare_missing.cocci The cocci script checks for the existence of clk_disable_unprepare() paired with clk_prepare_enable(). Add the missing clk_disable_unprepare() to the error path. Fixes: fcc446c8aa63 ("serial: 8250_bcm2835aux: Add ACPI support") Reported-by: Hulk Robot Reviewed-by: Florian Fainelli Signed-off-by: Guo Mengqi Link: https://lore.kernel.org/r/20220715023312.37808-1-guomengqi3@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_bcm2835aux.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c index 047e14ccb165..15a2387a5b25 100644 --- a/drivers/tty/serial/8250/8250_bcm2835aux.c +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c @@ -167,8 +167,10 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) uartclk = clk_get_rate(data->clk); if (!uartclk) { ret = device_property_read_u32(&pdev->dev, "clock-frequency", &uartclk); - if (ret) - return dev_err_probe(&pdev->dev, ret, "could not get clk rate\n"); + if (ret) { + dev_err_probe(&pdev->dev, ret, "could not get clk rate\n"); + goto dis_clk; + } } /* the HW-clock divider for bcm2835aux is 8, -- cgit v1.2.3 From c474c775716edd46a51bf8161142bbd1545f8733 Mon Sep 17 00:00:00 2001 From: Vijaya Krishna Nivarthi Date: Sat, 16 Jul 2022 00:25:43 +0530 Subject: tty: serial: qcom-geni-serial: Fix get_clk_div_rate() which otherwise could return a sub-optimal clock rate. In the logic around call to clk_round_rate(), for some corner conditions, get_clk_div_rate() could return an sub-optimal clock rate. Also, if an exact clock rate was not found lowest clock was being returned. Search for suitable clock rate in 2 steps a) exact match or within 2% tolerance b) within 5% tolerance This also takes care of corner conditions. Fixes: c2194bc999d4 ("tty: serial: qcom-geni-serial: Remove uart frequency table. Instead, find suitable frequency with call to clk_round_rate") Reviewed-by: Douglas Anderson Signed-off-by: Vijaya Krishna Nivarthi Link: https://lore.kernel.org/r/1657911343-1909-1-git-send-email-quic_vnivarth@quicinc.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/qcom_geni_serial.c | 88 +++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 35 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index f8f950641ad9..f754619451dc 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -940,52 +940,63 @@ static int qcom_geni_serial_startup(struct uart_port *uport) return 0; } -static unsigned long get_clk_div_rate(struct clk *clk, unsigned int baud, - unsigned int sampling_rate, unsigned int *clk_div) +static unsigned long find_clk_rate_in_tol(struct clk *clk, unsigned int desired_clk, + unsigned int *clk_div, unsigned int percent_tol) { - unsigned long ser_clk; - unsigned long desired_clk; - unsigned long freq, prev; + unsigned long freq; unsigned long div, maxdiv; - int64_t mult; - - desired_clk = baud * sampling_rate; - if (!desired_clk) { - pr_err("%s: Invalid frequency\n", __func__); - return 0; - } + u64 mult; + unsigned long offset, abs_tol, achieved; + abs_tol = div_u64((u64)desired_clk * percent_tol, 100); maxdiv = CLK_DIV_MSK >> CLK_DIV_SHFT; - prev = 0; - - for (div = 1; div <= maxdiv; div++) { - mult = div * desired_clk; - if (mult > ULONG_MAX) + div = 1; + while (div <= maxdiv) { + mult = (u64)div * desired_clk; + if (mult != (unsigned long)mult) break; - freq = clk_round_rate(clk, (unsigned long)mult); - if (!(freq % desired_clk)) { - ser_clk = freq; - break; - } + offset = div * abs_tol; + freq = clk_round_rate(clk, mult - offset); - if (!prev) - ser_clk = freq; - else if (prev == freq) + /* Can only get lower if we're done */ + if (freq < mult - offset) break; - prev = freq; - } + /* + * Re-calculate div in case rounding skipped rates but we + * ended up at a good one, then check for a match. + */ + div = DIV_ROUND_CLOSEST(freq, desired_clk); + achieved = DIV_ROUND_CLOSEST(freq, div); + if (achieved <= desired_clk + abs_tol && + achieved >= desired_clk - abs_tol) { + *clk_div = div; + return freq; + } - if (!ser_clk) { - pr_err("%s: Can't find matching DFS entry for baud %d\n", - __func__, baud); - return ser_clk; + div = DIV_ROUND_UP(freq, desired_clk); } - *clk_div = ser_clk / desired_clk; - if (!(*clk_div)) - *clk_div = 1; + return 0; +} + +static unsigned long get_clk_div_rate(struct clk *clk, unsigned int baud, + unsigned int sampling_rate, unsigned int *clk_div) +{ + unsigned long ser_clk; + unsigned long desired_clk; + + desired_clk = baud * sampling_rate; + if (!desired_clk) + return 0; + + /* + * try to find a clock rate within 2% tolerance, then within 5% + */ + ser_clk = find_clk_rate_in_tol(clk, desired_clk, clk_div, 2); + if (!ser_clk) + ser_clk = find_clk_rate_in_tol(clk, desired_clk, clk_div, 5); return ser_clk; } @@ -1020,8 +1031,15 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport, clk_rate = get_clk_div_rate(port->se.clk, baud, sampling_rate, &clk_div); - if (!clk_rate) + if (!clk_rate) { + dev_err(port->se.dev, + "Couldn't find suitable clock rate for %lu\n", + baud * sampling_rate); goto out_restart_rx; + } + + dev_dbg(port->se.dev, "desired_rate-%lu, clk_rate-%lu, clk_div-%u\n", + baud * sampling_rate, clk_rate, clk_div); uport->uartclk = clk_rate; dev_pm_opp_set_rate(uport->dev, clk_rate); -- cgit v1.2.3 From 070298c84e5b924c688a4d08c3a9193175cdffd8 Mon Sep 17 00:00:00 2001 From: Shenwei Wang Date: Thu, 14 Jul 2022 13:58:58 -0500 Subject: serial: fsl_lpuart: zero out parity bit in CS7 mode The LPUART hardware doesn't zero out the parity bit on the received characters. This behavior won't impact the use cases of CS8 because the parity bit is the 9th bit which is not currently used by software. But the parity bit for CS7 must be zeroed out by software in order to get the correct raw data. Signed-off-by: Shenwei Wang Link: https://lore.kernel.org/r/20220714185858.615373-1-shenwei.wang@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/fsl_lpuart.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index fc7d235a1e27..afa0f941c862 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -274,6 +274,8 @@ struct lpuart_port { int rx_dma_rng_buf_len; unsigned int dma_tx_nents; wait_queue_head_t dma_wait; + bool is_cs7; /* Set to true when character size is 7 */ + /* and the parity is enabled */ }; struct lpuart_soc_data { @@ -1022,6 +1024,9 @@ static void lpuart32_rxint(struct lpuart_port *sport) flg = TTY_OVERRUN; } + if (sport->is_cs7) + rx &= 0x7F; + if (tty_insert_flip_char(port, rx, flg) == 0) sport->port.icount.buf_overrun++; } @@ -1107,6 +1112,17 @@ static void lpuart_handle_sysrq(struct lpuart_port *sport) } } +static int lpuart_tty_insert_flip_string(struct tty_port *port, + unsigned char *chars, size_t size, bool is_cs7) +{ + int i; + + if (is_cs7) + for (i = 0; i < size; i++) + chars[i] &= 0x7F; + return tty_insert_flip_string(port, chars, size); +} + static void lpuart_copy_rx_to_tty(struct lpuart_port *sport) { struct tty_port *port = &sport->port.state->port; @@ -1217,7 +1233,8 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport) if (ring->head < ring->tail) { count = sport->rx_sgl.length - ring->tail; - copied = tty_insert_flip_string(port, ring->buf + ring->tail, count); + copied = lpuart_tty_insert_flip_string(port, ring->buf + ring->tail, + count, sport->is_cs7); if (copied != count) sport->port.icount.buf_overrun++; ring->tail = 0; @@ -1227,7 +1244,8 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport) /* Finally we read data from tail to head */ if (ring->tail < ring->head) { count = ring->head - ring->tail; - copied = tty_insert_flip_string(port, ring->buf + ring->tail, count); + copied = lpuart_tty_insert_flip_string(port, ring->buf + ring->tail, + count, sport->is_cs7); if (copied != count) sport->port.icount.buf_overrun++; /* Wrap ring->head if needed */ @@ -2066,6 +2084,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, ctrl = old_ctrl = lpuart32_read(&sport->port, UARTCTRL); bd = lpuart32_read(&sport->port, UARTBAUD); modem = lpuart32_read(&sport->port, UARTMODIR); + sport->is_cs7 = false; /* * only support CS8 and CS7, and for CS7 must enable PE. * supported mode: @@ -2184,6 +2203,9 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, lpuart32_write(&sport->port, ctrl, UARTCTRL); /* restore control register */ + if ((ctrl & (UARTCTRL_PE | UARTCTRL_M)) == UARTCTRL_PE) + sport->is_cs7 = true; + if (old && sport->lpuart_dma_rx_use) { if (!lpuart_start_rx_dma(sport)) rx_dma_timer_init(sport); -- cgit v1.2.3 From c7039ce904c0f80253a1171d10353e7832c3e4b3 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 21 Jul 2022 22:24:30 +0100 Subject: serial: stm32: make info structs static to avoid sparse warnings The info structs are local only to the stm32-usart.c driver and are triggering sparse warnings about being undecalred. Move these into the main driver code and make them static to avoid the following warnings: drivers/tty/serial/stm32-usart.h:42:25: warning: symbol 'stm32f4_info' was not declared. Should it be static? drivers/tty/serial/stm32-usart.h:63:25: warning: symbol 'stm32f7_info' was not declared. Should it be static? drivers/tty/serial/stm32-usart.h:85:25: warning: symbol 'stm32h7_info' was not declared. Should it be static? Signed-off-by: Ben Dooks Link: https://lore.kernel.org/r/20220721212430.453192-1-ben-linux@fluff.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/stm32-usart.c | 69 ++++++++++++++++++++++++++++++++++++++++ drivers/tty/serial/stm32-usart.h | 68 --------------------------------------- 2 files changed, 69 insertions(+), 68 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index ff5c7e0ebc4c..f8ea95d14309 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -35,6 +35,75 @@ #include "serial_mctrl_gpio.h" #include "stm32-usart.h" + +/* Register offsets */ +static struct stm32_usart_info stm32f4_info = { + .ofs = { + .isr = 0x00, + .rdr = 0x04, + .tdr = 0x04, + .brr = 0x08, + .cr1 = 0x0c, + .cr2 = 0x10, + .cr3 = 0x14, + .gtpr = 0x18, + .rtor = UNDEF_REG, + .rqr = UNDEF_REG, + .icr = UNDEF_REG, + }, + .cfg = { + .uart_enable_bit = 13, + .has_7bits_data = false, + .fifosize = 1, + } +}; + +static struct stm32_usart_info stm32f7_info = { + .ofs = { + .cr1 = 0x00, + .cr2 = 0x04, + .cr3 = 0x08, + .brr = 0x0c, + .gtpr = 0x10, + .rtor = 0x14, + .rqr = 0x18, + .isr = 0x1c, + .icr = 0x20, + .rdr = 0x24, + .tdr = 0x28, + }, + .cfg = { + .uart_enable_bit = 0, + .has_7bits_data = true, + .has_swap = true, + .fifosize = 1, + } +}; + +static struct stm32_usart_info stm32h7_info = { + .ofs = { + .cr1 = 0x00, + .cr2 = 0x04, + .cr3 = 0x08, + .brr = 0x0c, + .gtpr = 0x10, + .rtor = 0x14, + .rqr = 0x18, + .isr = 0x1c, + .icr = 0x20, + .rdr = 0x24, + .tdr = 0x28, + }, + .cfg = { + .uart_enable_bit = 0, + .has_7bits_data = true, + .has_swap = true, + .has_wakeup = true, + .has_fifo = true, + .fifosize = 16, + } +}; + static void stm32_usart_stop_tx(struct uart_port *port); static void stm32_usart_transmit_chars(struct uart_port *port); static void __maybe_unused stm32_usart_console_putchar(struct uart_port *port, unsigned char ch); diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h index ee69c203b926..0ec41a732c88 100644 --- a/drivers/tty/serial/stm32-usart.h +++ b/drivers/tty/serial/stm32-usart.h @@ -38,74 +38,6 @@ struct stm32_usart_info { #define UNDEF_REG 0xff -/* Register offsets */ -struct stm32_usart_info stm32f4_info = { - .ofs = { - .isr = 0x00, - .rdr = 0x04, - .tdr = 0x04, - .brr = 0x08, - .cr1 = 0x0c, - .cr2 = 0x10, - .cr3 = 0x14, - .gtpr = 0x18, - .rtor = UNDEF_REG, - .rqr = UNDEF_REG, - .icr = UNDEF_REG, - }, - .cfg = { - .uart_enable_bit = 13, - .has_7bits_data = false, - .fifosize = 1, - } -}; - -struct stm32_usart_info stm32f7_info = { - .ofs = { - .cr1 = 0x00, - .cr2 = 0x04, - .cr3 = 0x08, - .brr = 0x0c, - .gtpr = 0x10, - .rtor = 0x14, - .rqr = 0x18, - .isr = 0x1c, - .icr = 0x20, - .rdr = 0x24, - .tdr = 0x28, - }, - .cfg = { - .uart_enable_bit = 0, - .has_7bits_data = true, - .has_swap = true, - .fifosize = 1, - } -}; - -struct stm32_usart_info stm32h7_info = { - .ofs = { - .cr1 = 0x00, - .cr2 = 0x04, - .cr3 = 0x08, - .brr = 0x0c, - .gtpr = 0x10, - .rtor = 0x14, - .rqr = 0x18, - .isr = 0x1c, - .icr = 0x20, - .rdr = 0x24, - .tdr = 0x28, - }, - .cfg = { - .uart_enable_bit = 0, - .has_7bits_data = true, - .has_swap = true, - .has_wakeup = true, - .has_fifo = true, - .fifosize = 16, - } -}; - /* USART_SR (F4) / USART_ISR (F7) */ #define USART_SR_PE BIT(0) #define USART_SR_FE BIT(1) -- cgit v1.2.3 From 707f816f25590c20e056b3bd4a17ce69b03fe856 Mon Sep 17 00:00:00 2001 From: Sherry Sun Date: Mon, 25 Jul 2022 13:01:15 +0800 Subject: tty: serial: fsl_lpuart: correct the count of break characters The LPUART can't distinguish between a break signal and a framing error, so need to count the break characters if there is a framing error and received data is zero instead of the parity error. Fixes: 5541a9bacfe5 ("serial: fsl_lpuart: handle break and make sysrq work") Reviewed-by: Michael Walle Signed-off-by: Sherry Sun Link: https://lore.kernel.org/r/20220725050115.12396-1-sherry.sun@nxp.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/fsl_lpuart.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index afa0f941c862..f6c33cd228c8 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -992,12 +992,12 @@ static void lpuart32_rxint(struct lpuart_port *sport) if (sr & (UARTSTAT_PE | UARTSTAT_OR | UARTSTAT_FE)) { if (sr & UARTSTAT_PE) { + sport->port.icount.parity++; + } else if (sr & UARTSTAT_FE) { if (is_break) sport->port.icount.brk++; else - sport->port.icount.parity++; - } else if (sr & UARTSTAT_FE) { - sport->port.icount.frame++; + sport->port.icount.frame++; } if (sr & UARTSTAT_OR) @@ -1012,12 +1012,12 @@ static void lpuart32_rxint(struct lpuart_port *sport) sr &= sport->port.read_status_mask; if (sr & UARTSTAT_PE) { + flg = TTY_PARITY; + } else if (sr & UARTSTAT_FE) { if (is_break) flg = TTY_BREAK; else - flg = TTY_PARITY; - } else if (sr & UARTSTAT_FE) { - flg = TTY_FRAME; + flg = TTY_FRAME; } if (sr & UARTSTAT_OR) -- cgit v1.2.3 From a7209541239e5dd44d981289e5f9059222d40fd1 Mon Sep 17 00:00:00 2001 From: Narendra Hadke Date: Tue, 26 Jul 2022 11:12:21 +0200 Subject: serial: mvebu-uart: uart2 error bits clearing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For mvebu uart2, error bits are not cleared on buffer read. This causes interrupt loop and system hang. Cc: stable@vger.kernel.org Reviewed-by: Yi Guo Reviewed-by: Nadav Haklai Signed-off-by: Narendra Hadke Signed-off-by: Pali Rohár Link: https://lore.kernel.org/r/20220726091221.12358-1-pali@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mvebu-uart.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c index 0429c2a54290..ff61a8d00014 100644 --- a/drivers/tty/serial/mvebu-uart.c +++ b/drivers/tty/serial/mvebu-uart.c @@ -265,6 +265,7 @@ static void mvebu_uart_rx_chars(struct uart_port *port, unsigned int status) struct tty_port *tport = &port->state->port; unsigned char ch = 0; char flag = 0; + int ret; do { if (status & STAT_RX_RDY(port)) { @@ -277,6 +278,16 @@ static void mvebu_uart_rx_chars(struct uart_port *port, unsigned int status) port->icount.parity++; } + /* + * For UART2, error bits are not cleared on buffer read. + * This causes interrupt loop and system hang. + */ + if (IS_EXTENDED(port) && (status & STAT_BRK_ERR)) { + ret = readl(port->membase + UART_STAT); + ret |= STAT_BRK_ERR; + writel(ret, port->membase + UART_STAT); + } + if (status & STAT_BRK_DET) { port->icount.brk++; status &= ~(STAT_FRM_ERR | STAT_PAR_ERR); -- cgit v1.2.3 From c4bd17a6ddf3b92bf9d7939ae251570ace14bb52 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 28 Jul 2022 08:10:52 +0200 Subject: Documentation: serial: dedup kernel-doc for uart functions Some of the serial (uart_*) functions are documented twice. Once as kernel-doc along their sources and once in Documentation. So deduplicate these texts, merge them into kernel-doc in the sources, and link them using kernel-doc: from the Documentation. To be properly linked and rendered, tabulators had to be removed from the comments. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20220728061056.20799-2-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/serial/driver.rst | 84 +---------------- drivers/tty/serial/serial_core.c | 141 +++++++++++++++++------------ 2 files changed, 87 insertions(+), 138 deletions(-) (limited to 'drivers/tty/serial') diff --git a/Documentation/driver-api/serial/driver.rst b/Documentation/driver-api/serial/driver.rst index cb0ec6db4f1e..ac9620e97f4b 100644 --- a/Documentation/driver-api/serial/driver.rst +++ b/Documentation/driver-api/serial/driver.rst @@ -69,85 +69,11 @@ uart_ops Other functions --------------- -uart_update_timeout(port,cflag,baud) - Update the frame timing information according to the number of bits, - parity, stop bits and baud rate. The FIFO drain timeout is derived - from the frame timing information. - - Locking: caller is expected to take port->lock - - Interrupts: n/a - -uart_get_baud_rate(port,termios,old,min,max) - Return the numeric baud rate for the specified termios, taking - account of the special 38400 baud "kludge". The B0 baud rate - is mapped to 9600 baud. - - If the baud rate is not within min..max, then if old is non-NULL, - the original baud rate will be tried. If that exceeds the - min..max constraint, 9600 baud will be returned. termios will - be updated to the baud rate in use. - - Note: min..max must always allow 9600 baud to be selected. - - Locking: caller dependent. - - Interrupts: n/a - -uart_get_divisor(port,baud) - Return the divisor (baud_base / baud) for the specified baud - rate, appropriately rounded. - - If 38400 baud and custom divisor is selected, return the - custom divisor instead. - - Locking: caller dependent. - - Interrupts: n/a - -uart_match_port(port1,port2) - This utility function can be used to determine whether two - uart_port structures describe the same port. - - Locking: n/a - - Interrupts: n/a - -uart_write_wakeup(port) - A driver is expected to call this function when the number of - characters in the transmit buffer have dropped below a threshold. - - Locking: port->lock should be held. - - Interrupts: n/a - -uart_register_driver(drv) - Register a uart driver with the core driver. We in turn register - with the tty layer, and initialise the core driver per-port state. - - drv->port should be NULL, and the per-port structures should be - registered using uart_add_one_port after this call has succeeded. - - Locking: none - - Interrupts: enabled - -uart_unregister_driver() - Remove all references to a driver from the core driver. The low - level driver must have removed all its ports via the - uart_remove_one_port() if it registered them with uart_add_one_port(). - - Locking: none - - Interrupts: enabled - -**uart_suspend_port()** - -**uart_resume_port()** - -**uart_add_one_port()** - -**uart_remove_one_port()** +.. kernel-doc:: drivers/tty/serial/serial_core.c + :identifiers: uart_update_timeout uart_get_baud_rate uart_get_divisor + uart_match_port uart_write_wakeup uart_register_driver + uart_unregister_driver uart_suspend_port uart_resume_port + uart_add_one_port uart_remove_one_port Other notes ----------- diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index ac198d0d4c80..c302aa34668d 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -97,9 +97,16 @@ static inline struct uart_port *uart_port_check(struct uart_state *state) return state->uart_port; } -/* - * This routine is used by the interrupt handler to schedule processing in - * the software interrupt portion of the driver. +/** + * uart_write_wakeup - schedule write processing + * @port: port to be processed + * + * This routine is used by the interrupt handler to schedule processing in the + * software interrupt portion of the driver. A driver is expected to call this + * function when the number of characters in the transmit buffer have dropped + * below a threshold. + * + * Locking: @port->lock should be held */ void uart_write_wakeup(struct uart_port *port) { @@ -327,14 +334,16 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) } /** - * uart_update_timeout - update per-port frame timing information. - * @port: uart_port structure describing the port - * @cflag: termios cflag value - * @baud: speed of the port + * uart_update_timeout - update per-port frame timing information + * @port: uart_port structure describing the port + * @cflag: termios cflag value + * @baud: speed of the port * - * Set the port frame timing information from which the FIFO timeout - * value is derived. The @cflag value should reflect the actual hardware - * settings. + * Set the @port frame timing information from which the FIFO timeout value is + * derived. The @cflag value should reflect the actual hardware settings as + * number of bits, parity, stop bits and baud rate is taken into account here. + * + * Locking: caller is expected to take @port->lock */ void uart_update_timeout(struct uart_port *port, unsigned int cflag, @@ -349,23 +358,25 @@ uart_update_timeout(struct uart_port *port, unsigned int cflag, EXPORT_SYMBOL(uart_update_timeout); /** - * uart_get_baud_rate - return baud rate for a particular port - * @port: uart_port structure describing the port in question. - * @termios: desired termios settings. - * @old: old termios (or NULL) - * @min: minimum acceptable baud rate - * @max: maximum acceptable baud rate + * uart_get_baud_rate - return baud rate for a particular port + * @port: uart_port structure describing the port in question. + * @termios: desired termios settings + * @old: old termios (or %NULL) + * @min: minimum acceptable baud rate + * @max: maximum acceptable baud rate + * + * Decode the termios structure into a numeric baud rate, taking account of the + * magic 38400 baud rate (with spd_* flags), and mapping the %B0 rate to 9600 + * baud. * - * Decode the termios structure into a numeric baud rate, - * taking account of the magic 38400 baud rate (with spd_* - * flags), and mapping the %B0 rate to 9600 baud. + * If the new baud rate is invalid, try the @old termios setting. If it's still + * invalid, we try 9600 baud. * - * If the new baud rate is invalid, try the old termios setting. - * If it's still invalid, we try 9600 baud. + * The @termios structure is updated to reflect the baud rate we're actually + * going to be using. Don't do this for the case where B0 is requested ("hang + * up"). * - * Update the @termios structure to reflect the baud rate - * we're actually going to be using. Don't do this for the case - * where B0 is requested ("hang up"). + * Locking: caller dependent */ unsigned int uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, @@ -450,11 +461,17 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, EXPORT_SYMBOL(uart_get_baud_rate); /** - * uart_get_divisor - return uart clock divisor - * @port: uart_port structure describing the port. - * @baud: desired baud rate + * uart_get_divisor - return uart clock divisor + * @port: uart_port structure describing the port + * @baud: desired baud rate + * + * Calculate the divisor (baud_base / baud) for the specified @baud, + * appropriately rounded. * - * Calculate the uart clock divisor for the port. + * If 38400 baud and custom divisor is selected, return the custom divisor + * instead. + * + * Locking: caller dependent */ unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud) @@ -2683,17 +2700,19 @@ static const struct tty_port_operations uart_port_ops = { }; /** - * uart_register_driver - register a driver with the uart core layer - * @drv: low level driver structure + * uart_register_driver - register a driver with the uart core layer + * @drv: low level driver structure + * + * Register a uart driver with the core driver. We in turn register with the + * tty layer, and initialise the core driver per-port state. * - * Register a uart driver with the core driver. We in turn register - * with the tty layer, and initialise the core driver per-port state. + * We have a proc file in /proc/tty/driver which is named after the normal + * driver. * - * We have a proc file in /proc/tty/driver which is named after the - * normal driver. + * @drv->port should be %NULL, and the per-port structures should be registered + * using uart_add_one_port() after this call has succeeded. * - * drv->port should be NULL, and the per-port structures should be - * registered using uart_add_one_port after this call has succeeded. + * Locking: none, Interrupts: enabled */ int uart_register_driver(struct uart_driver *drv) { @@ -2757,13 +2776,14 @@ out: EXPORT_SYMBOL(uart_register_driver); /** - * uart_unregister_driver - remove a driver from the uart core layer - * @drv: low level driver structure + * uart_unregister_driver - remove a driver from the uart core layer + * @drv: low level driver structure + * + * Remove all references to a driver from the core driver. The low level + * driver must have removed all its ports via the uart_remove_one_port() if it + * registered them with uart_add_one_port(). (I.e. @drv->port is %NULL.) * - * Remove all references to a driver from the core driver. The low - * level driver must have removed all its ports via the - * uart_remove_one_port() if it registered them with uart_add_one_port(). - * (ie, drv->port == NULL) + * Locking: none, Interrupts: enabled */ void uart_unregister_driver(struct uart_driver *drv) { @@ -3012,16 +3032,15 @@ static const struct attribute_group tty_dev_attr_group = { }; /** - * uart_add_one_port - attach a driver-defined port structure - * @drv: pointer to the uart low level driver structure for this port - * @uport: uart port structure to use for this port. + * uart_add_one_port - attach a driver-defined port structure + * @drv: pointer to the uart low level driver structure for this port + * @uport: uart port structure to use for this port. * - * Context: task context, might sleep + * Context: task context, might sleep * - * This allows the driver to register its own uart_port structure - * with the core driver. The main purpose is to allow the low - * level uart drivers to expand uart_port, rather than having yet - * more levels of structures. + * This allows the driver @drv to register its own uart_port structure with the + * core driver. The main purpose is to allow the low level uart drivers to + * expand uart_port, rather than having yet more levels of structures. */ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) { @@ -3116,15 +3135,14 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) EXPORT_SYMBOL(uart_add_one_port); /** - * uart_remove_one_port - detach a driver defined port structure - * @drv: pointer to the uart low level driver structure for this port - * @uport: uart port structure for this port + * uart_remove_one_port - detach a driver defined port structure + * @drv: pointer to the uart low level driver structure for this port + * @uport: uart port structure for this port * - * Context: task context, might sleep + * Context: task context, might sleep * - * This unhooks (and hangs up) the specified port structure from the - * core driver. No further calls will be made to the low-level code - * for this port. + * This unhooks (and hangs up) the specified port structure from the core + * driver. No further calls will be made to the low-level code for this port. */ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport) { @@ -3196,8 +3214,13 @@ out: } EXPORT_SYMBOL(uart_remove_one_port); -/* - * Are the two ports equivalent? +/** + * uart_match_port - are the two ports equivalent? + * @port1: first port + * @port2: second port + * + * This utility function can be used to determine whether two uart_port + * structures describe the same port. */ bool uart_match_port(const struct uart_port *port1, const struct uart_port *port2) -- cgit v1.2.3 From 27940abd555228fdda39a40081ae02450c500f35 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 28 Jul 2022 08:10:53 +0200 Subject: Documentation: serial: move GPIO kernel-doc to the functions The GPIO uart functions are documented in Documentation. Move and transform this documentation into kernel-doc directly in the code and reference it in Documentation using kernel-doc:. This makes it easier to update, maintain and check by the build. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20220728061056.20799-3-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/serial/driver.rst | 32 +++----------------- drivers/tty/serial/serial_mctrl_gpio.c | 48 ++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 28 deletions(-) (limited to 'drivers/tty/serial') diff --git a/Documentation/driver-api/serial/driver.rst b/Documentation/driver-api/serial/driver.rst index ac9620e97f4b..cae280f39189 100644 --- a/Documentation/driver-api/serial/driver.rst +++ b/Documentation/driver-api/serial/driver.rst @@ -94,31 +94,7 @@ Modem control lines via GPIO Some helpers are provided in order to set/get modem control lines via GPIO. -mctrl_gpio_init(port, idx): - This will get the {cts,rts,...}-gpios from device tree if they are - present and request them, set direction etc, and return an - allocated structure. `devm_*` functions are used, so there's no need - to call mctrl_gpio_free(). - As this sets up the irq handling make sure to not handle changes to the - gpio input lines in your driver, too. - -mctrl_gpio_free(dev, gpios): - This will free the requested gpios in mctrl_gpio_init(). - As `devm_*` functions are used, there's generally no need to call - this function. - -mctrl_gpio_to_gpiod(gpios, gidx) - This returns the gpio_desc structure associated to the modem line - index. - -mctrl_gpio_set(gpios, mctrl): - This will sets the gpios according to the mctrl state. - -mctrl_gpio_get(gpios, mctrl): - This will update mctrl with the gpios values. - -mctrl_gpio_enable_ms(gpios): - Enables irqs and handling of changes to the ms lines. - -mctrl_gpio_disable_ms(gpios): - Disables irqs and handling of changes to the ms lines. +.. kernel-doc:: drivers/tty/serial/serial_mctrl_gpio.c + :identifiers: mctrl_gpio_init mctrl_gpio_free mctrl_gpio_to_gpiod + mctrl_gpio_set mctrl_gpio_get mctrl_gpio_enable_ms + mctrl_gpio_disable_ms diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c index 1663b3afc3a0..7d5aaa8d422b 100644 --- a/drivers/tty/serial/serial_mctrl_gpio.c +++ b/drivers/tty/serial/serial_mctrl_gpio.c @@ -42,6 +42,13 @@ static bool mctrl_gpio_flags_is_dir_out(unsigned int idx) return mctrl_gpios_desc[idx].flags & GPIOD_FLAGS_BIT_DIR_OUT; } +/** + * mctrl_gpio_set - set gpios according to mctrl state + * @gpios: gpios to set + * @mctrl: state to set + * + * Set the gpios according to the mctrl state. + */ void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl) { enum mctrl_gpio_idx i; @@ -63,6 +70,12 @@ void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl) } EXPORT_SYMBOL_GPL(mctrl_gpio_set); +/** + * mctrl_gpio_to_gpiod - obtain gpio_desc of modem line index + * @gpios: gpios to look into + * @gidx: index of the modem line + * Returns: the gpio_desc structure associated to the modem line index + */ struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios, enum mctrl_gpio_idx gidx) { @@ -73,6 +86,14 @@ struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios, } EXPORT_SYMBOL_GPL(mctrl_gpio_to_gpiod); +/** + * mctrl_gpio_get - update mctrl with the gpios values. + * @gpios: gpios to get the info from + * @mctrl: mctrl to set + * Returns: modified mctrl (the same value as in @mctrl) + * + * Update mctrl with the gpios values. + */ unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl) { enum mctrl_gpio_idx i; @@ -189,6 +210,17 @@ static irqreturn_t mctrl_gpio_irq_handle(int irq, void *context) return IRQ_HANDLED; } +/** + * mctrl_gpio_init - initialize uart gpios + * @port: port to initialize gpios for + * @idx: index of the gpio in the @port's device + * + * This will get the {cts,rts,...}-gpios from device tree if they are present + * and request them, set direction etc, and return an allocated structure. + * `devm_*` functions are used, so there's no need to call mctrl_gpio_free(). + * As this sets up the irq handling, make sure to not handle changes to the + * gpio input lines in your driver, too. + */ struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx) { struct mctrl_gpios *gpios; @@ -235,6 +267,14 @@ struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx) } EXPORT_SYMBOL_GPL(mctrl_gpio_init); +/** + * mctrl_gpio_free - explicitly free uart gpios + * @dev: uart port's device + * @gpios: gpios structure to be freed + * + * This will free the requested gpios in mctrl_gpio_init(). As `devm_*` + * functions are used, there's generally no need to call this function. + */ void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios) { enum mctrl_gpio_idx i; @@ -253,6 +293,10 @@ void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios) } EXPORT_SYMBOL_GPL(mctrl_gpio_free); +/** + * mctrl_gpio_enable_ms - enable irqs and handling of changes to the ms lines + * @gpios: gpios to enable + */ void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios) { enum mctrl_gpio_idx i; @@ -278,6 +322,10 @@ void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios) } EXPORT_SYMBOL_GPL(mctrl_gpio_enable_ms); +/** + * mctrl_gpio_disable_ms - disable irqs and handling of changes to the ms lines + * @gpios: gpios to disable + */ void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios) { enum mctrl_gpio_idx i; -- cgit v1.2.3 From 987233b342b950653d21c5e3e5b78689c995c869 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 28 Jul 2022 08:10:55 +0200 Subject: tty: serial: serial_core, reformat kernel-doc for functions There are many annotated functions in serial_core.c, but they do not completely conform to the kernel-doc style. So reformat them and link them from the Documentation. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20220728061056.20799-5-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/serial/driver.rst | 11 +-- drivers/tty/serial/serial_core.c | 107 ++++++++++++++--------------- 2 files changed, 60 insertions(+), 58 deletions(-) (limited to 'drivers/tty/serial') diff --git a/Documentation/driver-api/serial/driver.rst b/Documentation/driver-api/serial/driver.rst index 13b580e887b4..e1b440f2c02b 100644 --- a/Documentation/driver-api/serial/driver.rst +++ b/Documentation/driver-api/serial/driver.rst @@ -25,10 +25,10 @@ Console Support --------------- The serial core provides a few helper functions. This includes identifing -the correct port structure (via uart_get_console) and decoding command line -arguments (uart_parse_options). +the correct port structure (via uart_get_console()) and decoding command line +arguments (uart_parse_options()). -There is also a helper function (uart_console_write) which performs a +There is also a helper function (uart_console_write()) which performs a character by character write, translating newlines to CRLF sequences. Driver writers are recommended to use this function rather than implementing their own version. @@ -73,7 +73,10 @@ Other functions :identifiers: uart_update_timeout uart_get_baud_rate uart_get_divisor uart_match_port uart_write_wakeup uart_register_driver uart_unregister_driver uart_suspend_port uart_resume_port - uart_add_one_port uart_remove_one_port + uart_add_one_port uart_remove_one_port uart_console_write + uart_parse_earlycon uart_parse_options uart_set_options + uart_get_lsr_info uart_handle_dcd_change uart_handle_cts_change + uart_try_toggle_sysrq Other notes ----------- diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index c302aa34668d..b2943da2d32c 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1034,10 +1034,10 @@ static int uart_set_info_user(struct tty_struct *tty, struct serial_struct *ss) } /** - * uart_get_lsr_info - get line status register info - * @tty: tty associated with the UART - * @state: UART being queried - * @value: returned modem value + * uart_get_lsr_info - get line status register info + * @tty: tty associated with the UART + * @state: UART being queried + * @value: returned modem value */ static int uart_get_lsr_info(struct tty_struct *tty, struct uart_state *state, unsigned int __user *value) @@ -2072,11 +2072,11 @@ static void uart_port_spin_lock_init(struct uart_port *port) #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL) /** - * uart_console_write - write a console message to a serial port - * @port: the port to write the message - * @s: array of characters - * @count: number of characters in string to write - * @putchar: function to write character to port + * uart_console_write - write a console message to a serial port + * @port: the port to write the message + * @s: array of characters + * @count: number of characters in string to write + * @putchar: function to write character to port */ void uart_console_write(struct uart_port *port, const char *s, unsigned int count, @@ -2115,24 +2115,23 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co) } /** - * uart_parse_earlycon - Parse earlycon options - * @p: ptr to 2nd field (ie., just beyond ',') - * @iotype: ptr for decoded iotype (out) - * @addr: ptr for decoded mapbase/iobase (out) - * @options: ptr for field; NULL if not present (out) + * uart_parse_earlycon - Parse earlycon options + * @p: ptr to 2nd field (ie., just beyond ',') + * @iotype: ptr for decoded iotype (out) + * @addr: ptr for decoded mapbase/iobase (out) + * @options: ptr for field; %NULL if not present (out) * - * Decodes earlycon kernel command line parameters of the form - * earlycon=,io|mmio|mmio16|mmio32|mmio32be|mmio32native,, - * console=,io|mmio|mmio16|mmio32|mmio32be|mmio32native,, + * Decodes earlycon kernel command line parameters of the form: + * * earlycon=,io|mmio|mmio16|mmio32|mmio32be|mmio32native,, + * * console=,io|mmio|mmio16|mmio32|mmio32be|mmio32native,, * - * The optional form + * The optional form: + * * earlycon=,0x, + * * console=,0x, * - * earlycon=,0x, - * console=,0x, + * is also accepted; the returned @iotype will be %UPIO_MEM. * - * is also accepted; the returned @iotype will be UPIO_MEM. - * - * Returns 0 on success or -EINVAL on failure + * Returns: 0 on success or -%EINVAL on failure */ int uart_parse_earlycon(char *p, unsigned char *iotype, resource_size_t *addr, char **options) @@ -2177,16 +2176,16 @@ int uart_parse_earlycon(char *p, unsigned char *iotype, resource_size_t *addr, EXPORT_SYMBOL_GPL(uart_parse_earlycon); /** - * uart_parse_options - Parse serial port baud/parity/bits/flow control. - * @options: pointer to option string - * @baud: pointer to an 'int' variable for the baud rate. - * @parity: pointer to an 'int' variable for the parity. - * @bits: pointer to an 'int' variable for the number of data bits. - * @flow: pointer to an 'int' variable for the flow control character. + * uart_parse_options - Parse serial port baud/parity/bits/flow control. + * @options: pointer to option string + * @baud: pointer to an 'int' variable for the baud rate. + * @parity: pointer to an 'int' variable for the parity. + * @bits: pointer to an 'int' variable for the number of data bits. + * @flow: pointer to an 'int' variable for the flow control character. * - * uart_parse_options decodes a string containing the serial console - * options. The format of the string is , - * eg: 115200n8r + * uart_parse_options() decodes a string containing the serial console + * options. The format of the string is , + * eg: 115200n8r */ void uart_parse_options(const char *options, int *baud, int *parity, @@ -2207,13 +2206,13 @@ uart_parse_options(const char *options, int *baud, int *parity, EXPORT_SYMBOL_GPL(uart_parse_options); /** - * uart_set_options - setup the serial console parameters - * @port: pointer to the serial ports uart_port structure - * @co: console pointer - * @baud: baud rate - * @parity: parity character - 'n' (none), 'o' (odd), 'e' (even) - * @bits: number of data bits - * @flow: flow control character - 'r' (rts) + * uart_set_options - setup the serial console parameters + * @port: pointer to the serial ports uart_port structure + * @co: console pointer + * @baud: baud rate + * @parity: parity character - 'n' (none), 'o' (odd), 'e' (even) + * @bits: number of data bits + * @flow: flow control character - 'r' (rts) */ int uart_set_options(struct uart_port *port, struct console *co, @@ -3248,11 +3247,11 @@ bool uart_match_port(const struct uart_port *port1, EXPORT_SYMBOL(uart_match_port); /** - * uart_handle_dcd_change - handle a change of carrier detect state - * @uport: uart_port structure for the open port - * @status: new carrier detect status, nonzero if active + * uart_handle_dcd_change - handle a change of carrier detect state + * @uport: uart_port structure for the open port + * @status: new carrier detect status, nonzero if active * - * Caller must hold uport->lock + * Caller must hold uport->lock. */ void uart_handle_dcd_change(struct uart_port *uport, unsigned int status) { @@ -3283,11 +3282,11 @@ void uart_handle_dcd_change(struct uart_port *uport, unsigned int status) EXPORT_SYMBOL_GPL(uart_handle_dcd_change); /** - * uart_handle_cts_change - handle a change of clear-to-send state - * @uport: uart_port structure for the open port - * @status: new clear to send status, nonzero if active + * uart_handle_cts_change - handle a change of clear-to-send state + * @uport: uart_port structure for the open port + * @status: new clear to send status, nonzero if active * - * Caller must hold uport->lock + * Caller must hold uport->lock. */ void uart_handle_cts_change(struct uart_port *uport, unsigned int status) { @@ -3358,15 +3357,15 @@ static void uart_sysrq_on(struct work_struct *w) static DECLARE_WORK(sysrq_enable_work, uart_sysrq_on); /** - * uart_try_toggle_sysrq - Enables SysRq from serial line - * @port: uart_port structure where char(s) after BREAK met - * @ch: new character in the sequence after received BREAK + * uart_try_toggle_sysrq - Enables SysRq from serial line + * @port: uart_port structure where char(s) after BREAK met + * @ch: new character in the sequence after received BREAK * - * Enables magic SysRq when the required sequence is met on port - * (see CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE). + * Enables magic SysRq when the required sequence is met on port + * (see CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE). * - * Returns false if @ch is out of enabling sequence and should be - * handled some other way, true if @ch was consumed. + * Returns: %false if @ch is out of enabling sequence and should be + * handled some other way, %true if @ch was consumed. */ bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch) { -- cgit v1.2.3 From 9e5f399f5c9f62e537735f2f8e42bd2f7c255c1f Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 28 Jul 2022 08:10:56 +0200 Subject: tty: serial: document uart_get_console() This was the only function mentioned in the text, but was neither linked nor documented. So document and link it, so that hyperlinking works in the text. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20220728061056.20799-6-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/serial/driver.rst | 2 +- drivers/tty/serial/serial_core.c | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/tty/serial') diff --git a/Documentation/driver-api/serial/driver.rst b/Documentation/driver-api/serial/driver.rst index e1b440f2c02b..23c6b956cd90 100644 --- a/Documentation/driver-api/serial/driver.rst +++ b/Documentation/driver-api/serial/driver.rst @@ -76,7 +76,7 @@ Other functions uart_add_one_port uart_remove_one_port uart_console_write uart_parse_earlycon uart_parse_options uart_set_options uart_get_lsr_info uart_handle_dcd_change uart_handle_cts_change - uart_try_toggle_sysrq + uart_try_toggle_sysrq uart_get_console Other notes ----------- diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index b2943da2d32c..339f4c421503 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2092,10 +2092,15 @@ void uart_console_write(struct uart_port *port, const char *s, } EXPORT_SYMBOL_GPL(uart_console_write); -/* - * Check whether an invalid uart number has been specified, and - * if so, search for the first available port that does have - * console support. +/** + * uart_get_console - get uart port for console + * @ports: ports to search in + * @nr: number of @ports + * @co: console to search for + * Returns: uart_port for the console @co + * + * Check whether an invalid uart number has been specified (as @co->index), and + * if so, search for the first available port that does have console support. */ struct uart_port * __init uart_get_console(struct uart_port *ports, int nr, struct console *co) -- cgit v1.2.3 From 0fec518018cc5ceffa706370b6e3acbbb1e3c798 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 2 Aug 2022 13:23:09 -0700 Subject: tty: serial: qcom-geni-serial: Fix %lu -> %u in print statements When we multiply an unsigned int by a u32 we still end up with an unsigned int. That means we should specify "%u" not "%lu" in the format code. NOTE: this fix was chosen instead of somehow promoting the value to "unsigned long" since the max baud rate from the earlier call to uart_get_baud_rate() is 4000000 and the max sampling rate is 32. 4000000 * 32 = 0x07a12000, not even close to overflowing 32-bits. Fixes: c474c775716e ("tty: serial: qcom-geni-serial: Fix get_clk_div_rate() which otherwise could return a sub-optimal clock rate.") Reported-by: Mark Brown Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20220802132250.1.Iea061e14157a17e114dbe2eca764568a02d6b889@changeid Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/qcom_geni_serial.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial') diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index f754619451dc..f7c1f1807040 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -1033,12 +1033,12 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport, sampling_rate, &clk_div); if (!clk_rate) { dev_err(port->se.dev, - "Couldn't find suitable clock rate for %lu\n", + "Couldn't find suitable clock rate for %u\n", baud * sampling_rate); goto out_restart_rx; } - dev_dbg(port->se.dev, "desired_rate-%lu, clk_rate-%lu, clk_div-%u\n", + dev_dbg(port->se.dev, "desired_rate-%u, clk_rate-%lu, clk_div-%u\n", baud * sampling_rate, clk_rate, clk_div); uport->uartclk = clk_rate; -- cgit v1.2.3