From 61702c3e4f064250d11395fce7d3242a2cfcf9c1 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 2 Feb 2015 14:53:26 +0200 Subject: serial: 8250_pci: convert to dev_pm_ops Convert the legacy system PM callbacks to new ones. Meanwhile, remove the redudant calls to the PCI for changing a power state since it's done by bus code. Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) (limited to 'drivers/tty/serial/8250') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index daf2c82984e9..fbe919410e0f 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -4020,41 +4020,41 @@ static void pciserial_remove_one(struct pci_dev *dev) pci_disable_device(dev); } -#ifdef CONFIG_PM -static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int pciserial_suspend_one(struct device *dev) { - struct serial_private *priv = pci_get_drvdata(dev); + struct pci_dev *pdev = to_pci_dev(dev); + struct serial_private *priv = pci_get_drvdata(pdev); if (priv) pciserial_suspend_ports(priv); - pci_save_state(dev); - pci_set_power_state(dev, pci_choose_state(dev, state)); return 0; } -static int pciserial_resume_one(struct pci_dev *dev) +static int pciserial_resume_one(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); + struct serial_private *priv = pci_get_drvdata(pdev); int err; - struct serial_private *priv = pci_get_drvdata(dev); - - pci_set_power_state(dev, PCI_D0); - pci_restore_state(dev); if (priv) { /* * The device may have been disabled. Re-enable it. */ - err = pci_enable_device(dev); + err = pci_enable_device(pdev); /* FIXME: We cannot simply error out here */ if (err) - dev_err(&dev->dev, "Unable to re-enable ports, trying to continue.\n"); + dev_err(dev, "Unable to re-enable ports, trying to continue.\n"); pciserial_resume_ports(priv); } return 0; } #endif +static SIMPLE_DEV_PM_OPS(pciserial_pm_ops, pciserial_suspend_one, + pciserial_resume_one); + static struct pci_device_id serial_pci_tbl[] = { /* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 'PCI_SUBVENDOR_ID' */ { PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI3620, @@ -5528,10 +5528,9 @@ static struct pci_driver serial_pci_driver = { .name = "serial", .probe = pciserial_init_one, .remove = pciserial_remove_one, -#ifdef CONFIG_PM - .suspend = pciserial_suspend_one, - .resume = pciserial_resume_one, -#endif + .driver = { + .pm = &pciserial_pm_ops, + }, .id_table = serial_pci_tbl, .err_handler = &serial8250_err_handler, }; -- cgit v1.2.3 From 6ae4a16cf4b6d449778697701de1b2ea86726def Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 3 Feb 2015 11:01:47 +0100 Subject: tty: serial: 8250_core: Remove trailing whitespaces No functional changes. Signed-off-by: Michal Simek Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty/serial/8250') diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index e3b9570a1eff..463425721866 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -895,7 +895,7 @@ static int broken_efr(struct uart_8250_port *up) /* * Exar ST16C2550 "A2" devices incorrectly detect as * having an EFR, and report an ID of 0x0201. See - * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html + * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html */ if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16) return 1; @@ -1260,7 +1260,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) serial_out(up, UART_LCR, save_lcr); port->fifosize = uart_config[up->port.type].fifo_size; - old_capabilities = up->capabilities; + old_capabilities = up->capabilities; up->capabilities = uart_config[port->type].flags; up->tx_loadsz = uart_config[port->type].tx_loadsz; -- cgit v1.2.3 From f3ac3fc287818a63072618b091074267bfa5184d Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 4 Feb 2015 15:03:48 +0200 Subject: serial: 8250_dw: Add missing MODULE_ALIAS() for module autoloading support Without this the module does not load automatically whenever suitable platform device appears. Reported-by: Jerome Blin Signed-off-by: Mika Westerberg Reviewed-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/tty/serial/8250') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index e60116235836..f426acc8c6b5 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -608,3 +608,4 @@ module_platform_driver(dw8250_platform_driver); MODULE_AUTHOR("Jamie Iles"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver"); +MODULE_ALIAS("platform:dw-apb-uart"); -- cgit v1.2.3 From f549e94effa163ea170d2f0c12d307cb602431c6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 23 Feb 2015 16:24:43 +0200 Subject: serial: 8250_pci: add Intel Penwell ports Intel Penwell supports 3 HSUART ports which are 8250 compatible. The patch adds necessary bits to the driver. The functions have intel_mid_* prefix due to more than one platform will use this code. Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 183 +++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) (limited to 'drivers/tty/serial/8250') diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index fbe919410e0f..c03199e122ed 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -27,6 +27,7 @@ #include #include +#include #include "8250.h" @@ -1525,6 +1526,148 @@ byt_serial_setup(struct serial_private *priv, return ret; } +#define INTEL_MID_UART_PS 0x30 +#define INTEL_MID_UART_MUL 0x34 + +static void intel_mid_set_termios_50M(struct uart_port *p, + struct ktermios *termios, + struct ktermios *old) +{ + unsigned int baud = tty_termios_baud_rate(termios); + u32 ps, mul; + + /* + * The uart clk is 50Mhz, and the baud rate come from: + * baud = 50M * MUL / (DIV * PS * DLAB) + * + * For those basic low baud rate we can get the direct + * scalar from 2746800, like 115200 = 2746800/24. For those + * higher baud rate, we handle them case by case, mainly by + * adjusting the MUL/PS registers, and DIV register is kept + * as default value 0x3d09 to make things simple. + */ + + ps = 0x10; + + switch (baud) { + case 500000: + case 1000000: + case 1500000: + case 3000000: + mul = 0x3a98; + p->uartclk = 48000000; + break; + case 2000000: + case 4000000: + mul = 0x2710; + ps = 0x08; + p->uartclk = 64000000; + break; + case 2500000: + mul = 0x30d4; + p->uartclk = 40000000; + break; + case 3500000: + mul = 0x3345; + ps = 0x0c; + p->uartclk = 56000000; + break; + default: + mul = 0x2400; + p->uartclk = 29491200; + } + + writel(ps, p->membase + INTEL_MID_UART_PS); /* set PS */ + writel(mul, p->membase + INTEL_MID_UART_MUL); /* set MUL */ + + serial8250_do_set_termios(p, termios, old); +} + +static bool intel_mid_dma_filter(struct dma_chan *chan, void *param) +{ + struct hsu_dma_slave *s = param; + + if (s->dma_dev != chan->device->dev || s->chan_id != chan->chan_id) + return false; + + chan->private = s; + return true; +} + +static int intel_mid_serial_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx, + int index, struct pci_dev *dma_dev) +{ + struct device *dev = port->port.dev; + struct uart_8250_dma *dma; + struct hsu_dma_slave *tx_param, *rx_param; + + dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL); + if (!dma) + return -ENOMEM; + + tx_param = devm_kzalloc(dev, sizeof(*tx_param), GFP_KERNEL); + if (!tx_param) + return -ENOMEM; + + rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL); + if (!rx_param) + return -ENOMEM; + + rx_param->chan_id = index * 2 + 1; + tx_param->chan_id = index * 2; + + dma->rxconf.src_maxburst = 64; + dma->txconf.dst_maxburst = 64; + + rx_param->dma_dev = &dma_dev->dev; + tx_param->dma_dev = &dma_dev->dev; + + dma->fn = intel_mid_dma_filter; + dma->rx_param = rx_param; + dma->tx_param = tx_param; + + port->port.type = PORT_16750; + port->port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE; + port->dma = dma; + + return pci_default_setup(priv, board, port, idx); +} + +#define PCI_DEVICE_ID_INTEL_PNW_UART1 0x081b +#define PCI_DEVICE_ID_INTEL_PNW_UART2 0x081c +#define PCI_DEVICE_ID_INTEL_PNW_UART3 0x081d + +static int pnw_serial_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + struct pci_dev *pdev = priv->dev; + struct pci_dev *dma_dev; + int index; + + switch (pdev->device) { + case PCI_DEVICE_ID_INTEL_PNW_UART1: + index = 0; + break; + case PCI_DEVICE_ID_INTEL_PNW_UART2: + index = 1; + break; + case PCI_DEVICE_ID_INTEL_PNW_UART3: + index = 2; + break; + default: + return -EINVAL; + } + + dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 3)); + + port->port.set_termios = intel_mid_set_termios_50M; + + return intel_mid_serial_setup(priv, board, port, idx, index, dma_dev); +} + static int pci_omegapci_setup(struct serial_private *priv, const struct pciserial_board *board, @@ -1987,6 +2130,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .subdevice = PCI_ANY_ID, .setup = byt_serial_setup, }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_PNW_UART1, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pnw_serial_setup, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_PNW_UART2, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pnw_serial_setup, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_PNW_UART3, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pnw_serial_setup, + }, { .vendor = PCI_VENDOR_ID_INTEL, .device = PCI_DEVICE_ID_INTEL_QRK_UART, @@ -2878,6 +3042,7 @@ enum pci_board_num_t { pbn_ADDIDATA_PCIe_8_3906250, pbn_ce4100_1_115200, pbn_byt, + pbn_pnw, pbn_qrk, pbn_omegapci, pbn_NETMOS9900_2s_115200, @@ -3644,6 +3809,11 @@ static struct pciserial_board pci_boards[] = { .uart_offset = 0x80, .reg_shift = 2, }, + [pbn_pnw] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 115200, + }, [pbn_qrk] = { .flags = FL_BASE0, .num_ports = 1, @@ -5376,6 +5546,19 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000, pbn_byt }, + /* + * Intel Penwell + */ + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART1, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pnw}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pnw}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART3, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pnw}, + /* * Intel Quark x1000 */ -- cgit v1.2.3 From 833b1f7b5191e4ac15dfd86aa8137f2349f0fc30 Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Tue, 3 Mar 2015 18:11:14 +0300 Subject: serial/8250_dw: use platform_get_irq() instead of platform_get_resource() It is not recommened to use platform_get_resource(pdev, IORESOURCE_IRQ) for requesting IRQ's resources any more, as they can be not ready yet in case of DT-booting. platform_get_irq() instead is a recommended way for getting IRQ even if it was not retrieved earlier. It also makes code simpler because we're getting "int" value right away and no conversion from resource to int is required. Signed-off-by: Alexey Brodkin Cc: Vineet Gupta Cc: Alan Cox Cc: Greg Kroah-Hartman Cc: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/tty/serial/8250') diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index f426acc8c6b5..06933e8826a1 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -384,18 +384,24 @@ static int dw8250_probe(struct platform_device *pdev) { struct uart_8250_port uart = {}; struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + int irq = platform_get_irq(pdev, 0); struct dw8250_data *data; int err; - if (!regs || !irq) { - dev_err(&pdev->dev, "no registers/irq defined\n"); + if (!regs) { + dev_err(&pdev->dev, "no registers defined\n"); return -EINVAL; } + if (irq < 0) { + if (irq != -EPROBE_DEFER) + dev_err(&pdev->dev, "cannot get irq\n"); + return irq; + } + spin_lock_init(&uart.port.lock); uart.port.mapbase = regs->start; - uart.port.irq = irq->start; + uart.port.irq = irq; uart.port.handle_irq = dw8250_handle_irq; uart.port.pm = dw8250_do_pm; uart.port.type = PORT_8250; -- cgit v1.2.3