EXAR UART support for IOT2040 device
Subsystems (2)
cover EXAR UART support for IOT2040 device
Second chunk: This imports a number of preparatory patches in order to fully exploit the PCI-attached dual-port EXAR with RS232/422/485 on the IOT2040.
To avoid having to backport also API-changing patches for platform devices, I've slightly modified two patches to use a communication pattern that does not require these changes.
Jan
Axel Lin (1):
gpio: exar: Set proper output level in exar_direction_output
Jan Kiszka (18):
serial: 8250_pci: Use symbolic constants for EXAR's MPIO registers
serial: exar: Fix mapping of port I/O resources
serial: exar: Fix initialization of EXAR registers for ports > 0
serial: exar: Fix feature control register constants
serial: exar: Move Commtech adapters to 8250_exar as well
serial: pci: Remove unused pci_boards entries
serial: exar: Preconfigure xr17v35x MPIOs as output
serial: exar: Leave MPIOs as output for Commtech adapters
serial: uapi: Add support for bus termination gpio-exar/8250-exar: Fix passing in of parent PCI device
gpio: exar: Allocate resources on behalf of the platform device
gpio: exar: Fix reading of directions and values gpio-exar/8250-exar: Do not even instantiate a GPIO device for
Commtech cards
gpio: exar: Fix iomap request
gpio-exar/8250-exar: Rearrange gpiochip parenthood
serial: exar: Factor out platform hooks gpio-exar/8250-exar: Make set of exported GPIOs configurable
serial: exar: Add support for IOT2040 device
Laxman Dewangan (1):
gpio: Add devm_ apis for gpiochip_add_data and gpiochip_remove
Linus Walleij (1):
gpio: add a data pointer to gpio_chip
Paul Gortmaker (1):
serial: 8250_EXAR: fix duplicate Kconfig text and add missing help
text
Sudip Mukherjee (3):
serial: exar: split out the exar code from 8250_pci
serial: 8250_pci: remove exar code
gpio: exar: add gpio for exar cards
drivers/gpio/Kconfig | 7 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-exar.c | 196 ++++++++++ drivers/gpio/gpiolib.c | 84 ++++- drivers/tty/serial/8250/8250_exar.c | 636 ++++++++++++++++++++++++++++++++ drivers/tty/serial/8250/8250_pci.c | 484 +----------------------- drivers/tty/serial/8250/Kconfig | 9 + drivers/tty/serial/8250/Makefile | 1 + include/linux/gpio/driver.h | 18 +- include/linux/platform_data/gpio-exar.h | 21 ++ include/uapi/linux/serial.h | 3 + include/uapi/linux/serial_reg.h | 4 +- 12 files changed, 977 insertions(+), 487 deletions(-) create mode 100644 drivers/gpio/gpio-exar.c create mode 100644 drivers/tty/serial/8250/8250_exar.c create mode 100644 include/linux/platform_data/gpio-exar.h
Signature · 1 line
2.12.3
PATCH 1/25 serial: exar: split out the exar code from 8250_pci
From: Sudip Mukherjee <[email protected]>
commit d0aeaa83f0b0f7a92615bbdd6b1f96812f7dcfd2 upstream.
Add the serial driver for the Exar chips. And also register the platform device for the GPIO provided by the Exar chips.
--- drivers/tty/serial/8250/8250_exar.c | 396 ++++++++++++++++++++++++++++++++++++ drivers/tty/serial/8250/Kconfig | 4 + drivers/tty/serial/8250/Makefile | 1 + 3 files changed, 401 insertions(+) create mode 100644 drivers/tty/serial/8250/8250_exar.c
drivers/tty/serial/8250/8250_exar.c new file +396 -0
@@ -0,0 +1,396 @@ +/* +* Probe module for 8250/16550-type Exar chips PCI serial ports. +* +* Based on drivers/tty/serial/8250/8250_pci.c, +* +* Copyright (C) 2017 Sudip Mukherjee, All Rights Reserved. +* +* 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. +*/ +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/serial_core.h> +#include <linux/serial_reg.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/tty.h> +#include <linux/8250_pci.h> + +#include <asm/byteorder.h> + +#include "8250.h" + +#define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020 +#define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021 +#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022 +#define PCI_DEVICE_ID_EXAR_XR17V4358 0x4358 +#define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358 + +#define UART_EXAR_MPIOINT_7_0 0x8f/* MPIOINT[7:0] */ +#define UART_EXAR_MPIOLVL_7_0 0x90/* MPIOLVL[7:0] */ +#define UART_EXAR_MPIO3T_7_0 0x91/* MPIO3T[7:0] */ +#define UART_EXAR_MPIOINV_7_0 0x92/* MPIOINV[7:0] */ +#define UART_EXAR_MPIOSEL_7_0 0x93/* MPIOSEL[7:0] */ +#define UART_EXAR_MPIOOD_7_0 0x94/* MPIOOD[7:0] */ +#define UART_EXAR_MPIOINT_15_8 0x95/* MPIOINT[15:8] */ +#define UART_EXAR_MPIOLVL_15_8 0x96/* MPIOLVL[15:8] */ +#define UART_EXAR_MPIO3T_15_8 0x97/* MPIO3T[15:8] */ +#define UART_EXAR_MPIOINV_15_8 0x98/* MPIOINV[15:8] */ +#define UART_EXAR_MPIOSEL_15_8 0x99/* MPIOSEL[15:8] */ +#define UART_EXAR_MPIOOD_15_8 0x9a/* MPIOOD[15:8] */ + +struct exar8250 ; + +/** +* struct exar8250_board - board information +* @num_ports: number of serial ports +* @reg_shift: describes UART register mapping in PCI memory +*/ +struct exar8250_board { +unsigned int num_ports; +unsigned int reg_shift; +bool has_slave; +int (*setup)(struct exar8250 *,struct pci_dev *, +struct uart_8250_port *,int ); +void (*exit)(struct pci_dev *pcidev); +}; + +struct exar8250 { +unsigned int nr; +struct exar8250_board *board; +int line[0 ]; +}; + +static int default_setup (struct exar8250 *priv,struct pci_dev *pcidev, +int idx,unsigned int offset, +struct uart_8250_port *port) +{ +const struct exar8250_board *board = priv->board; +unsigned int bar =0 ; + + port->port.iotype =UPIO_MEM ; + port->port.mapbase =pci_resource_start (pcidev, bar) + offset; + port->port.membase =pcim_iomap_table (pcidev)[bar] + offset; + port->port.regshift = board->reg_shift; + +return 0 ; +} + +static int +pci_connect_tech_setup (struct exar8250 *priv,struct pci_dev *pcidev, +struct uart_8250_port *port,int idx) +{ +unsigned int offset = idx *0x200 ; +unsigned int baud =1843200 ; + + port->port.uartclk = baud *16 ; +return default_setup (priv, pcidev, idx, offset, port); +} + +static int +pci_xr17c154_setup (struct exar8250 *priv,struct pci_dev *pcidev, +struct uart_8250_port *port,int idx) +{ +unsigned int offset = idx *0x200 ; +unsigned int baud =921600 ; + + port->port.uartclk = baud *16 ; +return default_setup (priv, pcidev, idx, offset, port); +} + +static void setup_gpio (u8 __iomem *p) +{ +writeb (0x00 , p +UART_EXAR_MPIOINT_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIOLVL_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIO3T_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIOINV_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIOSEL_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIOOD_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIOINT_15_8 ); +writeb (0x00 , p +UART_EXAR_MPIOLVL_15_8 ); +writeb (0x00 , p +UART_EXAR_MPIO3T_15_8 ); +writeb (0x00 , p +UART_EXAR_MPIOINV_15_8 ); +writeb (0x00 , p +UART_EXAR_MPIOSEL_15_8 ); +writeb (0x00 , p +UART_EXAR_MPIOOD_15_8 ); +} + +static void * +xr17v35x_register_gpio (struct pci_dev *pcidev) +{ +struct platform_device *pdev; + + pdev =platform_device_alloc ("gpio_exar" ,PLATFORM_DEVID_AUTO ); +if (!pdev) +return NULL ; + +platform_set_drvdata (pdev, pcidev); +if (platform_device_add (pdev) <0 ) { +platform_device_put (pdev); +return NULL ; + } + +return pdev; +} + +static int +pci_xr17v35x_setup (struct exar8250 *priv,struct pci_dev *pcidev, +struct uart_8250_port *port,int idx) +{ +const struct exar8250_board *board = priv->board; +unsigned int offset = idx *0x400 ; +unsigned int baud =7812500 ; +u8 __iomem *p; +int ret; + + port->port.uartclk = baud *16 ; +/* +* Setup the uart clock for the devices on expansion slot to +* half the clock speed of the main chip (which is 125MHz) +*/ +if (board->has_slave && idx >=8 ) + port->port.uartclk /=2 ; + + p =pci_ioremap_bar (pcidev,0 ); +if (!p) +return -ENOMEM ; + +/* Setup Multipurpose Input/Output pins. */ +if (idx ==0 ) +setup_gpio (p); + +writeb (0x00 , p +UART_EXAR_8XMODE ); +writeb (UART_FCTR_EXAR_TRGD , p +UART_EXAR_FCTR ); +writeb (128 , p +UART_EXAR_TXTRG ); +writeb (128 , p +UART_EXAR_RXTRG ); +iounmap (p); + + ret =default_setup (priv, pcidev, idx, offset, port); +if (ret) +return ret; + +if (idx ==0 ) + port->port.private_data = +xr17v35x_register_gpio (pcidev); + +return 0 ; +} + +static void pci_xr17v35x_exit (struct pci_dev *pcidev) +{ +struct exar8250 *priv =pci_get_drvdata (pcidev); +struct uart_8250_port *port =serial8250_get_port (priv->line[0 ]); +struct platform_device *pdev = port->port.private_data; + +platform_device_unregister (pdev); + port->port.private_data =NULL ; +} + +static int +exar_pci_probe (struct pci_dev *pcidev,const struct pci_device_id *ent) +{ +unsigned int nr_ports, i, bar =0 , maxnr; +struct exar8250_board *board; +struct uart_8250_port uart; +struct exar8250 *priv; +int rc; + + board = (struct exar8250_board *)ent->driver_data; +if (!board) +return -EINVAL ; + + rc =pcim_enable_device (pcidev); +if (rc) +return rc; + + maxnr =pci_resource_len (pcidev, bar) >> (board->reg_shift +3 ); + + nr_ports = board->num_ports ? board->num_ports : pcidev->device &0x0f ; + + priv =devm_kzalloc (&pcidev->dev,sizeof (*priv) + +sizeof (unsigned int ) * nr_ports, +GFP_KERNEL ); +if (!priv) +return -ENOMEM ; + + priv->board = board; + +memset (&uart,0 ,sizeof (uart)); + uart.port.flags =UPF_SKIP_TEST |UPF_BOOT_AUTOCONF |UPF_SHARE_IRQ + |UPF_EXAR_EFR ; + uart.port.irq = pcidev->irq; + uart.port.dev = &pcidev->dev; + +for (i =0 ; i < nr_ports && i < maxnr; i++) { + rc = board->setup (priv, pcidev, &uart, i); +if (rc) { +dev_err (&pcidev->dev,"Failed to setup port %u\n" , i); +break ; + } + +dev_dbg (&pcidev->dev,"Setup PCI port: port %lx, irq %d, type %d\n" , + uart.port.iobase, uart.port.irq, uart.port.iotype); + + priv->line[i] =serial8250_register_8250_port (&uart); +if (priv->line[i] <0 ) { +dev_err (&pcidev->dev, +"Couldn't register serial port %lx, irq %d, type %d, error %d\n" , + uart.port.iobase, uart.port.irq, + uart.port.iotype, priv->line[i]); +break ; + } + } + priv->nr = i; +pci_set_drvdata (pcidev, priv); +return 0 ; +} + +static void exar_pci_remove (struct pci_dev *pcidev) +{ +struct exar8250 *priv =pci_get_drvdata (pcidev); +unsigned int i; + +for (i =0 ; i < priv->nr; i++) +serial8250_unregister_port (priv->line[i]); + +if (priv->board->exit) + priv->board->exit (pcidev); +} + +static int __maybe_unused exar_suspend (struct device *dev) +{ +struct pci_dev *pcidev =to_pci_dev (dev); +struct exar8250 *priv =pci_get_drvdata (pcidev); +unsigned int i; + +for (i =0 ; i < priv->nr; i++) +if (priv->line[i] >=0 ) +serial8250_suspend_port (priv->line[i]); + +/* Ensure that every init quirk is properly torn down */ +if (priv->board->exit) + priv->board->exit (pcidev); + +return 0 ; +} + +static int __maybe_unused exar_resume (struct device *dev) +{ +struct pci_dev *pcidev =to_pci_dev (dev); +struct exar8250 *priv =pci_get_drvdata (pcidev); +unsigned int i; + +for (i =0 ; i < priv->nr; i++) +if (priv->line[i] >=0 ) +serial8250_resume_port (priv->line[i]); + +return 0 ; +} + +static SIMPLE_DEV_PM_OPS(exar_pci_pm, exar_suspend, exar_resume); + +static const struct exar8250_board pbn_connect = { + .setup = pci_connect_tech_setup, +}; + +static const struct exar8250_board pbn_exar_ibm_saturn = { + .num_ports =1 , + .setup = pci_xr17c154_setup, +}; + +static const struct exar8250_board pbn_exar_XR17C15x = { + .setup = pci_xr17c154_setup, +}; + +static const struct exar8250_board pbn_exar_XR17V35x = { + .setup = pci_xr17v35x_setup, + .exit = pci_xr17v35x_exit, +}; + +static const struct exar8250_board pbn_exar_XR17V4358 = { + .num_ports =12 , + .has_slave = true, + .setup = pci_xr17v35x_setup, + .exit = pci_xr17v35x_exit, +}; + +static const struct exar8250_board pbn_exar_XR17V8358 = { + .num_ports =16 , + .has_slave = true, + .setup = pci_xr17v35x_setup, + .exit = pci_xr17v35x_exit, +}; + +#define CONNECT_DEVICE (devid, sdevid, bd) { \ + PCI_DEVICE_SUB( \ + PCI_VENDOR_ID_EXAR, \ + PCI_DEVICE_ID_EXAR_##devid, \ + PCI_SUBVENDOR_ID_CONNECT_TECH, \ + PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_##sdevid), 0, 0, \ + (kernel_ulong_t)&bd \ + } + +#define EXAR_DEVICE (vend, devid, bd) { \ + PCI_VDEVICE(vend, PCI_DEVICE_ID_##devid), (kernel_ulong_t)&bd \ + } + +#define IBM_DEVICE (devid, sdevid, bd) { \ + PCI_DEVICE_SUB( \ + PCI_VENDOR_ID_EXAR, \ + PCI_DEVICE_ID_EXAR_##devid, \ + PCI_VENDOR_ID_IBM, \ + PCI_SUBDEVICE_ID_IBM_##sdevid), 0, 0, \ + (kernel_ulong_t)&bd \ + } + +static struct pci_device_id exar_pci_tbl[] = { +CONNECT_DEVICE (XR17C152 ,UART_2_232 , pbn_connect), +CONNECT_DEVICE (XR17C154 ,UART_4_232 , pbn_connect), +CONNECT_DEVICE (XR17C158 ,UART_8_232 , pbn_connect), +CONNECT_DEVICE (XR17C152 ,UART_1_1 , pbn_connect), +CONNECT_DEVICE (XR17C154 ,UART_2_2 , pbn_connect), +CONNECT_DEVICE (XR17C158 ,UART_4_4 , pbn_connect), +CONNECT_DEVICE (XR17C152 ,UART_2 , pbn_connect), +CONNECT_DEVICE (XR17C154 ,UART_4 , pbn_connect), +CONNECT_DEVICE (XR17C158 ,UART_8 , pbn_connect), +CONNECT_DEVICE (XR17C152 ,UART_2_485 , pbn_connect), +CONNECT_DEVICE (XR17C154 ,UART_4_485 , pbn_connect), +CONNECT_DEVICE (XR17C158 ,UART_8_485 , pbn_connect), + +IBM_DEVICE (XR17C152 ,SATURN_SERIAL_ONE_PORT , pbn_exar_ibm_saturn), + +/* Exar Corp. XR17C15[248] Dual/Quad/Octal UART */ +EXAR_DEVICE (EXAR ,EXAR_XR17C152 , pbn_exar_XR17C15x), +EXAR_DEVICE (EXAR ,EXAR_XR17C154 , pbn_exar_XR17C15x), +EXAR_DEVICE (EXAR ,EXAR_XR17C158 , pbn_exar_XR17C15x), + +/* Exar Corp. XR17V[48]35[248] Dual/Quad/Octal/Hexa PCIe UARTs */ +EXAR_DEVICE (EXAR ,EXAR_XR17V352 , pbn_exar_XR17V35x), +EXAR_DEVICE (EXAR ,EXAR_XR17V354 , pbn_exar_XR17V35x), +EXAR_DEVICE (EXAR ,EXAR_XR17V358 , pbn_exar_XR17V35x), +EXAR_DEVICE (EXAR ,EXAR_XR17V4358 , pbn_exar_XR17V4358), +EXAR_DEVICE (EXAR ,EXAR_XR17V8358 , pbn_exar_XR17V8358), +EXAR_DEVICE (COMMTECH ,COMMTECH_4222PCIE , pbn_exar_XR17V35x), +EXAR_DEVICE (COMMTECH ,COMMTECH_4224PCIE , pbn_exar_XR17V35x), +EXAR_DEVICE (COMMTECH ,COMMTECH_4228PCIE , pbn_exar_XR17V35x), + {0 , } +}; +MODULE_DEVICE_TABLE (pci, exar_pci_tbl); + +static struct pci_driver exar_pci_driver = { + .name ="exar_serial" , + .probe = exar_pci_probe, + .remove = exar_pci_remove, + .driver = { + .pm = &exar_pci_pm, + }, + .id_table = exar_pci_tbl, +}; +module_pci_driver (exar_pci_driver); + +MODULE_LICENSE ("GPL" ); +MODULE_DESCRIPTION ("Exar Serial Dricer" ); +MODULE_AUTHOR ("Sudip Mukherjee <[email protected]>" );
drivers/tty/serial/8250/Kconfig +4 -0
@@ -116,6 +116,10 @@ config SERIAL_8250_PCI Note that serial ports on NetMos 9835 Multi-I/O cards are handled by the parport_serial driver, enabled with CONFIG_PARPORT_SERIAL. +config SERIAL_8250_EXAR + tristate "8250/16550 PCI device support" + depends on SERIAL_8250_PCI + config SERIAL_8250_HP300 tristate depends on SERIAL_8250 && HP300
drivers/tty/serial/8250/Makefile +1 -0
@@ -9,6 +9,7 @@ obj-$(CONFIG_SERIAL_8250) += 8250.o 8250_base.o 8250_base-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o +obj-$(CONFIG_SERIAL_8250_EXAR) += 8250_exar.o obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o
Signature · 1 line
2.12.3
PATCH 2/25 serial: 8250_pci: Use symbolic constants for EXAR's MPIO registers
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
commit b6fce7382d72274336aeafe6e44da755a371ed32 upstream.
Less magic that only requires comments.
--- drivers/tty/serial/8250/8250_pci.c | 55 +++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 21 deletions(-)
drivers/tty/serial/8250/8250_pci.c +34 -21
@@ -1755,6 +1755,19 @@ static int pci_eg20t_init(struct pci_dev *dev)#define PCI_DEVICE_ID_EXAR_XR17V4358 0x4358#define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358 +#define UART_EXAR_MPIOINT_7_0 0x8f/* MPIOINT[7:0] */ +#define UART_EXAR_MPIOLVL_7_0 0x90/* MPIOLVL[7:0] */ +#define UART_EXAR_MPIO3T_7_0 0x91/* MPIO3T[7:0] */ +#define UART_EXAR_MPIOINV_7_0 0x92/* MPIOINV[7:0] */ +#define UART_EXAR_MPIOSEL_7_0 0x93/* MPIOSEL[7:0] */ +#define UART_EXAR_MPIOOD_7_0 0x94/* MPIOOD[7:0] */ +#define UART_EXAR_MPIOINT_15_8 0x95/* MPIOINT[15:8] */ +#define UART_EXAR_MPIOLVL_15_8 0x96/* MPIOLVL[15:8] */ +#define UART_EXAR_MPIO3T_15_8 0x97/* MPIO3T[15:8] */ +#define UART_EXAR_MPIOINV_15_8 0x98/* MPIOINV[15:8] */ +#define UART_EXAR_MPIOSEL_15_8 0x99/* MPIOSEL[15:8] */ +#define UART_EXAR_MPIOOD_15_8 0x9a/* MPIOOD[15:8] */ + static int pci_xr17c154_setup(struct serial_private *priv, const struct pciserial_board *board,
@@ -1797,18 +1810,18 @@ pci_xr17v35x_setup(struct serial_private *priv,* Setup Multipurpose Input/Output pins. */ if (idx ==0 ) { -writeb (0x00 , p +0x8f );/*MPIOINT[7:0]*/ -writeb (0x00 , p +0x90 );/*MPIOLVL[7:0]*/ -writeb (0x00 , p +0x91 );/*MPIO3T[7:0]*/ -writeb (0x00 , p +0x92 );/*MPIOINV[7:0]*/ -writeb (0x00 , p +0x93 );/*MPIOSEL[7:0]*/ -writeb (0x00 , p +0x94 );/*MPIOOD[7:0]*/ -writeb (0x00 , p +0x95 );/*MPIOINT[15:8]*/ -writeb (0x00 , p +0x96 );/*MPIOLVL[15:8]*/ -writeb (0x00 , p +0x97 );/*MPIO3T[15:8]*/ -writeb (0x00 , p +0x98 );/*MPIOINV[15:8]*/ -writeb (0x00 , p +0x99 );/*MPIOSEL[15:8]*/ -writeb (0x00 , p +0x9a );/*MPIOOD[15:8]*/ +writeb (0x00 , p +UART_EXAR_MPIOINT_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIOLVL_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIO3T_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIOINV_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIOSEL_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIOOD_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIOINT_15_8 ); +writeb (0x00 , p +UART_EXAR_MPIOLVL_15_8 ); +writeb (0x00 , p +UART_EXAR_MPIO3T_15_8 ); +writeb (0x00 , p +UART_EXAR_MPIOINV_15_8 ); +writeb (0x00 , p +UART_EXAR_MPIOSEL_15_8 ); +writeb (0x00 , p +UART_EXAR_MPIOOD_15_8 ); }writeb (0x00 , p +UART_EXAR_8XMODE );writeb (UART_FCTR_EXAR_TRGD , p +UART_EXAR_FCTR );
@@ -1844,20 +1857,20 @@ pci_fastcom335_setup(struct serial_private *priv,switch (priv->dev->device) {case PCI_DEVICE_ID_COMMTECH_4222PCI335 :case PCI_DEVICE_ID_COMMTECH_4224PCI335 : -writeb (0x78 , p +0x90 );/* MPIOLVL[7:0] */ -writeb (0x00 , p +0x92 );/* MPIOINV[7:0] */ -writeb (0x00 , p +0x93 );/* MPIOSEL[7:0] */ +writeb (0x78 , p +UART_EXAR_MPIOLVL_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIOINV_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIOSEL_7_0 );break ;case PCI_DEVICE_ID_COMMTECH_2324PCI335 :case PCI_DEVICE_ID_COMMTECH_2328PCI335 : -writeb (0x00 , p +0x90 );/* MPIOLVL[7:0] */ -writeb (0xc0 , p +0x92 );/* MPIOINV[7:0] */ -writeb (0xc0 , p +0x93 );/* MPIOSEL[7:0] */ +writeb (0x00 , p +UART_EXAR_MPIOLVL_7_0 ); +writeb (0xc0 , p +UART_EXAR_MPIOINV_7_0 ); +writeb (0xc0 , p +UART_EXAR_MPIOSEL_7_0 );break ; } -writeb (0x00 , p +0x8f );/* MPIOINT[7:0] */ -writeb (0x00 , p +0x91 );/* MPIO3T[7:0] */ -writeb (0x00 , p +0x94 );/* MPIOOD[7:0] */ +writeb (0x00 , p +UART_EXAR_MPIOINT_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIO3T_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIOOD_7_0 ); }writeb (0x00 , p +UART_EXAR_8XMODE );writeb (UART_FCTR_EXAR_TRGD , p +UART_EXAR_FCTR );
Signature · 1 line
2.12.3
PATCH 3/25 serial: 8250_pci: remove exar code
In reply to Jan KiszkaFrom: Sudip Mukherjee <[email protected]>
commit 5d1a2388edee77930c8b542cf8be0c92342dbeb4 upstream.
Remove the Exar specific codes from 8250_pci and blacklist those chips so that the new Exar serial driver binds to the devices.
--- drivers/tty/serial/8250/8250_pci.c | 336 +------------------------------------ drivers/tty/serial/8250/Kconfig | 1 + 2 files changed, 4 insertions(+), 333 deletions(-)
drivers/tty/serial/8250/8250_pci.c +3 -333
@@ -1752,9 +1752,6 @@ static int pci_eg20t_init(struct pci_dev *dev)#endif } -#define PCI_DEVICE_ID_EXAR_XR17V4358 0x4358 -#define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358 -#define UART_EXAR_MPIOINT_7_0 0x8f/* MPIOINT[7:0] */ #define UART_EXAR_MPIOLVL_7_0 0x90/* MPIOLVL[7:0] */ #define UART_EXAR_MPIO3T_7_0 0x91/* MPIO3T[7:0] */
@@ -1767,71 +1764,6 @@ static int pci_eg20t_init(struct pci_dev *dev)#define UART_EXAR_MPIOINV_15_8 0x98/* MPIOINV[15:8] */ #define UART_EXAR_MPIOSEL_15_8 0x99/* MPIOSEL[15:8] */ #define UART_EXAR_MPIOOD_15_8 0x9a/* MPIOOD[15:8] */ - -static int -pci_xr17c154_setup (struct serial_private *priv, -const struct pciserial_board *board, -struct uart_8250_port *port,int idx) -{ - port->port.flags |=UPF_EXAR_EFR ; -return pci_default_setup (priv, board, port, idx); -} - -static inline int -xr17v35x_has_slave (struct serial_private *priv) -{ -const int dev_id = priv->dev->device; - -return ((dev_id ==PCI_DEVICE_ID_EXAR_XR17V4358 ) || - (dev_id ==PCI_DEVICE_ID_EXAR_XR17V8358 )); -} - -static int -pci_xr17v35x_setup (struct serial_private *priv, -const struct pciserial_board *board, -struct uart_8250_port *port,int idx) -{ -u8 __iomem *p; - - p =pci_ioremap_bar (priv->dev,0 ); -if (p ==NULL ) -return -ENOMEM ; - - port->port.flags |=UPF_EXAR_EFR ; - -/* -* Setup the uart clock for the devices on expansion slot to -* half the clock speed of the main chip (which is 125MHz) -*/ -if (xr17v35x_has_slave (priv) && idx >=8 ) - port->port.uartclk = (7812500 *16 /2 ); - -/* -* Setup Multipurpose Input/Output pins. -*/ -if (idx ==0 ) { -writeb (0x00 , p +UART_EXAR_MPIOINT_7_0 ); -writeb (0x00 , p +UART_EXAR_MPIOLVL_7_0 ); -writeb (0x00 , p +UART_EXAR_MPIO3T_7_0 ); -writeb (0x00 , p +UART_EXAR_MPIOINV_7_0 ); -writeb (0x00 , p +UART_EXAR_MPIOSEL_7_0 ); -writeb (0x00 , p +UART_EXAR_MPIOOD_7_0 ); -writeb (0x00 , p +UART_EXAR_MPIOINT_15_8 ); -writeb (0x00 , p +UART_EXAR_MPIOLVL_15_8 ); -writeb (0x00 , p +UART_EXAR_MPIO3T_15_8 ); -writeb (0x00 , p +UART_EXAR_MPIOINV_15_8 ); -writeb (0x00 , p +UART_EXAR_MPIOSEL_15_8 ); -writeb (0x00 , p +UART_EXAR_MPIOOD_15_8 ); - } -writeb (0x00 , p +UART_EXAR_8XMODE ); -writeb (UART_FCTR_EXAR_TRGD , p +UART_EXAR_FCTR ); -writeb (128 , p +UART_EXAR_TXTRG ); -writeb (128 , p +UART_EXAR_RXTRG ); -iounmap (p); - -return pci_default_setup (priv, board, port, idx); -} -#define PCI_DEVICE_ID_COMMTECH_4222PCI335 0x0004#define PCI_DEVICE_ID_COMMTECH_4224PCI335 0x0002#define PCI_DEVICE_ID_COMMTECH_2324PCI335 0x000a
@@ -1945,9 +1877,6 @@ pci_wch_ch38x_setup(struct serial_private *priv,#define PCI_VENDOR_ID_AGESTAR 0x5372#define PCI_DEVICE_ID_AGESTAR_9375 0x6872#define PCI_VENDOR_ID_ASIX 0x9710 -#define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020 -#define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021 -#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022#define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a#define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e#define PCI_DEVICE_ID_INTEL_QRK_UART 0x0936
@@ -2452,65 +2381,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .setup = pci_timedia_setup, },/* -* Exar cards -*/ - { - .vendor = PCI_VENDOR_ID_EXAR, - .device = PCI_DEVICE_ID_EXAR_XR17C152, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_xr17c154_setup, - }, - { - .vendor = PCI_VENDOR_ID_EXAR, - .device = PCI_DEVICE_ID_EXAR_XR17C154, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_xr17c154_setup, - }, - { - .vendor = PCI_VENDOR_ID_EXAR, - .device = PCI_DEVICE_ID_EXAR_XR17C158, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_xr17c154_setup, - }, - { - .vendor = PCI_VENDOR_ID_EXAR, - .device = PCI_DEVICE_ID_EXAR_XR17V352, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_xr17v35x_setup, - }, - { - .vendor = PCI_VENDOR_ID_EXAR, - .device = PCI_DEVICE_ID_EXAR_XR17V354, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_xr17v35x_setup, - }, - { - .vendor = PCI_VENDOR_ID_EXAR, - .device = PCI_DEVICE_ID_EXAR_XR17V358, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_xr17v35x_setup, - }, - { - .vendor = PCI_VENDOR_ID_EXAR, - .device = PCI_DEVICE_ID_EXAR_XR17V4358, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_xr17v35x_setup, - }, - { - .vendor = PCI_VENDOR_ID_EXAR, - .device = PCI_DEVICE_ID_EXAR_XR17V8358, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_xr17v35x_setup, - }, - /** Xircom cards */ {
@@ -2758,27 +2628,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .subdevice = PCI_ANY_ID, .setup = pci_fastcom335_setup, }, - { - .vendor = PCI_VENDOR_ID_COMMTECH, - .device = PCI_DEVICE_ID_COMMTECH_4222PCIE, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_xr17v35x_setup, - }, - { - .vendor = PCI_VENDOR_ID_COMMTECH, - .device = PCI_DEVICE_ID_COMMTECH_4224PCIE, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_xr17v35x_setup, - }, - { - .vendor = PCI_VENDOR_ID_COMMTECH, - .device = PCI_DEVICE_ID_COMMTECH_4228PCIE, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_xr17v35x_setup, - },/* * Broadcom TruManage (NetXtreme) */
@@ -2993,15 +2842,6 @@ enum pci_board_num_t { pbn_computone_6, pbn_computone_8, pbn_sbsxrsio, - pbn_exar_XR17C152, - pbn_exar_XR17C154, - pbn_exar_XR17C158, - pbn_exar_XR17V352, - pbn_exar_XR17V354, - pbn_exar_XR17V358, - pbn_exar_XR17V4358, - pbn_exar_XR17V8358, - pbn_exar_ibm_saturn, pbn_pasemi_1682M, pbn_ni8430_2, pbn_ni8430_4,
@@ -3651,76 +3491,6 @@ static struct pciserial_board pci_boards[] = { .reg_shift = 4, },/* -* Exar Corp. XR17C15[248] Dual/Quad/Octal UART -* Only basic 16550A support. -* XR17C15[24] are not tested, but they should work. -*/ - [pbn_exar_XR17C152] = { - .flags = FL_BASE0, - .num_ports = 2, - .base_baud = 921600, - .uart_offset = 0x200, - }, - [pbn_exar_XR17C154] = { - .flags = FL_BASE0, - .num_ports = 4, - .base_baud = 921600, - .uart_offset = 0x200, - }, - [pbn_exar_XR17C158] = { - .flags = FL_BASE0, - .num_ports = 8, - .base_baud = 921600, - .uart_offset = 0x200, - }, - [pbn_exar_XR17V352] = { - .flags = FL_BASE0, - .num_ports = 2, - .base_baud = 7812500, - .uart_offset = 0x400, - .reg_shift = 0, - .first_offset = 0, - }, - [pbn_exar_XR17V354] = { - .flags = FL_BASE0, - .num_ports = 4, - .base_baud = 7812500, - .uart_offset = 0x400, - .reg_shift = 0, - .first_offset = 0, - }, - [pbn_exar_XR17V358] = { - .flags = FL_BASE0, - .num_ports = 8, - .base_baud = 7812500, - .uart_offset = 0x400, - .reg_shift = 0, - .first_offset = 0, - }, - [pbn_exar_XR17V4358] = { - .flags = FL_BASE0, - .num_ports = 12, - .base_baud = 7812500, - .uart_offset = 0x400, - .reg_shift = 0, - .first_offset = 0, - }, - [pbn_exar_XR17V8358] = { - .flags = FL_BASE0, - .num_ports = 16, - .base_baud = 7812500, - .uart_offset = 0x400, - .reg_shift = 0, - .first_offset = 0, - }, - [pbn_exar_ibm_saturn] = { - .flags = FL_BASE0, - .num_ports = 1, - .base_baud = 921600, - .uart_offset = 0x200, - }, - -/* * PA Semi PWRficient PA6T-1682M on-chip UART */ [pbn_pasemi_1682M] = {
@@ -3909,6 +3679,9 @@ static const struct pci_device_id blacklist[] = { { PCI_VDEVICE(INTEL, 0x081d), }, { PCI_VDEVICE(INTEL, 0x1191), }, { PCI_VDEVICE(INTEL, 0x19d8), }, + + /* Exar devices */ + { PCI_VDEVICE(EXAR, PCI_ANY_ID), }, };/*
@@ -4347,58 +4120,6 @@ static struct pci_device_id serial_pci_tbl[] = {PCI_VENDOR_ID_AFAVLAB ,PCI_SUBDEVICE_ID_AFAVLAB_P061 ,0 ,0 , pbn_b0_4_1152000 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152, -PCI_SUBVENDOR_ID_CONNECT_TECH , -PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232 ,0 ,0 , - pbn_b0_2_1843200_200 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154, -PCI_SUBVENDOR_ID_CONNECT_TECH , -PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_232 ,0 ,0 , - pbn_b0_4_1843200_200 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158, -PCI_SUBVENDOR_ID_CONNECT_TECH , -PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_232 ,0 ,0 , - pbn_b0_8_1843200_200 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152, -PCI_SUBVENDOR_ID_CONNECT_TECH , -PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_1_1 ,0 ,0 , - pbn_b0_2_1843200_200 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154, -PCI_SUBVENDOR_ID_CONNECT_TECH , -PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_2 ,0 ,0 , - pbn_b0_4_1843200_200 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158, -PCI_SUBVENDOR_ID_CONNECT_TECH , -PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4 ,0 ,0 , - pbn_b0_8_1843200_200 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152, -PCI_SUBVENDOR_ID_CONNECT_TECH , -PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2 ,0 ,0 , - pbn_b0_2_1843200_200 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154, -PCI_SUBVENDOR_ID_CONNECT_TECH , -PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4 ,0 ,0 , - pbn_b0_4_1843200_200 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158, -PCI_SUBVENDOR_ID_CONNECT_TECH , -PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8 ,0 ,0 , - pbn_b0_8_1843200_200 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152, -PCI_SUBVENDOR_ID_CONNECT_TECH , -PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_485 ,0 ,0 , - pbn_b0_2_1843200_200 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154, -PCI_SUBVENDOR_ID_CONNECT_TECH , -PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485 ,0 ,0 , - pbn_b0_4_1843200_200 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158, -PCI_SUBVENDOR_ID_CONNECT_TECH , -PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485 ,0 ,0 , - pbn_b0_8_1843200_200 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152, -PCI_VENDOR_ID_IBM ,PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT , - 0, 0, pbn_exar_ibm_saturn }, - { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,PCI_ANY_ID ,PCI_ANY_ID ,0 ,0 , pbn_b2_bt_1_115200 },
@@ -5126,45 +4847,6 @@ static struct pci_device_id serial_pci_tbl[] = { {PCI_VENDOR_ID_DCI ,PCI_DEVICE_ID_DCI_PCCOM8 ,PCI_ANY_ID ,PCI_ANY_ID ,0 ,0 , pbn_b3_8_115200 }, - -/* -* Exar Corp. XR17C15[248] Dual/Quad/Octal UART -*/ - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152, -PCI_ANY_ID ,PCI_ANY_ID , -0 , - 0, pbn_exar_XR17C152 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154, -PCI_ANY_ID ,PCI_ANY_ID , -0 , - 0, pbn_exar_XR17C154 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158, -PCI_ANY_ID ,PCI_ANY_ID , -0 , - 0, pbn_exar_XR17C158 }, -/* -* Exar Corp. XR17V[48]35[248] Dual/Quad/Octal/Hexa PCIe UARTs -*/ - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V352, -PCI_ANY_ID ,PCI_ANY_ID , -0 , - 0, pbn_exar_XR17V352 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V354, -PCI_ANY_ID ,PCI_ANY_ID , -0 , - 0, pbn_exar_XR17V354 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V358, -PCI_ANY_ID ,PCI_ANY_ID , -0 , - 0, pbn_exar_XR17V358 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V4358, -PCI_ANY_ID ,PCI_ANY_ID , -0 , - 0, pbn_exar_XR17V4358 }, - { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V8358, -PCI_ANY_ID ,PCI_ANY_ID , -0 , - 0, pbn_exar_XR17V8358 },/* * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART */
@@ -5788,18 +5470,6 @@ static struct pci_device_id serial_pci_tbl[] = {PCI_ANY_ID ,PCI_ANY_ID ,0 , 0, pbn_b0_8_1152000_200 }, - { PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4222PCIE, -PCI_ANY_ID ,PCI_ANY_ID , -0 , - 0, pbn_exar_XR17V352 }, - { PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4224PCIE, -PCI_ANY_ID ,PCI_ANY_ID , -0 , - 0, pbn_exar_XR17V354 }, - { PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4228PCIE, -PCI_ANY_ID ,PCI_ANY_ID , -0 , - 0, pbn_exar_XR17V358 },/* Fintek PCI serial cards */ { PCI_DEVICE(0x1c29, 0x1104), .driver_data = pbn_fintek_4 },
drivers/tty/serial/8250/Kconfig +1 -0
@@ -119,6 +119,7 @@ config SERIAL_8250_PCI config SERIAL_8250_EXAR tristate "8250/16550 PCI device support" depends on SERIAL_8250_PCI + default SERIAL_8250 config SERIAL_8250_HP300 tristate
Signature · 1 line
2.12.3
PATCH 4/25 serial: exar: Fix mapping of port I/O resources
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
commit 24572af4fb6ce0726dbe12b0286de11d25ff008b upstream.
pcim_iomap_table only returns the table of mapping, it does not perform them. For that, we need to call pcim_iomap, but only if that mapping was not done before.
--- drivers/tty/serial/8250/8250_exar.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/tty/serial/8250/8250_exar.c +3 -0
@@ -72,6 +72,9 @@ static int default_setup(struct exar8250 *priv, struct pci_dev *pcidev,const struct exar8250_board *board = priv->board;unsigned int bar =0 ; +if (!pcim_iomap_table (pcidev)[bar] && !pcim_iomap (pcidev, bar,0 )) +return -ENOMEM ; + port->port.iotype =UPIO_MEM ; port->port.mapbase =pci_resource_start (pcidev, bar) + offset; port->port.membase =pcim_iomap_table (pcidev)[bar] + offset;
Signature · 1 line
2.12.3
PATCH 5/25 serial: exar: Fix initialization of EXAR registers for ports > 0
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
commit 5b5f252d67afd7bd5b923c664206d60800bf5054 upstream.
So far, pci_xr17v35x_setup always initialized 8XMODE, FCTR & Co. for port 0 because it used the address of that port instead of moving the pointer according to the port number. Fix this and remove the unneeded temporary ioremap by moving default_setup up and reusing the membase it fills into the port structure.
--- drivers/tty/serial/8250/8250_exar.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-)
drivers/tty/serial/8250/8250_exar.c +9 -13
@@ -157,27 +157,23 @@ pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,if (board->has_slave && idx >=8 ) port->port.uartclk /=2 ; - p =pci_ioremap_bar (pcidev,0 ); -if (!p) -return -ENOMEM ; + ret =default_setup (priv, pcidev, idx, offset, port); +if (ret) +return ret; -/* Setup Multipurpose Input/Output pins. */ -if (idx ==0 ) -setup_gpio (p); + p = port->port.membase;writeb (0x00 , p +UART_EXAR_8XMODE );writeb (UART_FCTR_EXAR_TRGD , p +UART_EXAR_FCTR );writeb (128 , p +UART_EXAR_TXTRG );writeb (128 , p +UART_EXAR_RXTRG ); -iounmap (p); - ret =default_setup (priv, pcidev, idx, offset, port); -if (ret) -return ret; +if (idx ==0 ) { +/* Setup Multipurpose Input/Output pins. */ +setup_gpio (p); -if (idx ==0 ) - port->port.private_data = -xr17v35x_register_gpio (pcidev); + port->port.private_data =xr17v35x_register_gpio (pcidev); + }return 0 ; }
Signature · 1 line
2.12.3
PATCH 6/25 serial: exar: Fix feature control register constants
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
commit 7795753661f1a9423c3c8fbde322f6a2a8b94b68 upstream.
According to the XR17V352 manual, bit 4 is IrDA control and bit 5 for
485. Fortunately, no driver used them so far.
--- include/uapi/linux/serial_reg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
include/uapi/linux/serial_reg.h +2 -2
@@ -366,8 +366,8 @@#define UART_EXAR_DVID 0x8d/* Device identification */ #define UART_EXAR_FCTR 0x08/* Feature Control Register */ -#define UART_FCTR_EXAR_IRDA 0x08/* IrDa data encode select */ -#define UART_FCTR_EXAR_485 0x10/* Auto 485 half duplex dir ctl */ +#define UART_FCTR_EXAR_IRDA 0x10/* IrDa data encode select */ +#define UART_FCTR_EXAR_485 0x20/* Auto 485 half duplex dir ctl */ #define UART_FCTR_EXAR_TRGA 0x00/* FIFO trigger table A */ #define UART_FCTR_EXAR_TRGB 0x60/* FIFO trigger table B */ #define UART_FCTR_EXAR_TRGC 0x80/* FIFO trigger table C */
Signature · 1 line
2.12.3
PATCH 7/25 serial: exar: Move Commtech adapters to 8250_exar as well
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
commit fc6cc9615779183f07d6ff4065368a732d09f49e upstream.
Those are Exar-based, too.
With the required refactoring of the code to fit into 8250_exar, we automatically fix the same issue pci_xr17v35x_setup had before: 8XMODE, FCTL, TXTRG and RXTRG were always only set for port 0. Now they are initialized for the correct target port by using port.membase.
Now we can also cleanly fix the blacklist of 8250_pci so that all Commtech devices are rejected and 8250_exar can handle them.
--- drivers/tty/serial/8250/8250_exar.c | 83 +++++++++++++++++++-- drivers/tty/serial/8250/8250_pci.c | 139 +----------------------------------- 2 files changed, 79 insertions(+), 143 deletions(-)
drivers/tty/serial/8250/8250_exar.c +78 -5
@@ -24,11 +24,15 @@#include "8250.h" -#define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020 -#define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021 -#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022 -#define PCI_DEVICE_ID_EXAR_XR17V4358 0x4358 -#define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358 +#define PCI_DEVICE_ID_COMMTECH_4224PCI335 0x0002 +#define PCI_DEVICE_ID_COMMTECH_4222PCI335 0x0004 +#define PCI_DEVICE_ID_COMMTECH_2324PCI335 0x000a +#define PCI_DEVICE_ID_COMMTECH_2328PCI335 0x000b +#define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020 +#define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021 +#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022 +#define PCI_DEVICE_ID_EXAR_XR17V4358 0x4358 +#define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358#define UART_EXAR_MPIOINT_7_0 0x8f/* MPIOINT[7:0] */ #define UART_EXAR_MPIOLVL_7_0 0x90/* MPIOLVL[7:0] */
@@ -84,6 +88,55 @@ static int default_setup(struct exar8250 *priv, struct pci_dev *pcidev, }static int +pci_fastcom335_setup (struct exar8250 *priv,struct pci_dev *pcidev, +struct uart_8250_port *port,int idx) +{ +unsigned int offset = idx *0x200 ; +unsigned int baud =1843200 ; +u8 __iomem *p; +int err; + + port->port.flags |=UPF_EXAR_EFR ; + port->port.uartclk = baud *16 ; + + err =default_setup (priv, pcidev, idx, offset, port); +if (err) +return err; + + p = port->port.membase; + +writeb (0x00 , p +UART_EXAR_8XMODE ); +writeb (UART_FCTR_EXAR_TRGD , p +UART_EXAR_FCTR ); +writeb (32 , p +UART_EXAR_TXTRG ); +writeb (32 , p +UART_EXAR_RXTRG ); + +/* +* Setup Multipurpose Input/Output pins. +*/ +if (idx ==0 ) { +switch (pcidev->device) { +case PCI_DEVICE_ID_COMMTECH_4222PCI335 : +case PCI_DEVICE_ID_COMMTECH_4224PCI335 : +writeb (0x78 , p +UART_EXAR_MPIOLVL_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIOINV_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIOSEL_7_0 ); +break ; +case PCI_DEVICE_ID_COMMTECH_2324PCI335 : +case PCI_DEVICE_ID_COMMTECH_2328PCI335 : +writeb (0x00 , p +UART_EXAR_MPIOLVL_7_0 ); +writeb (0xc0 , p +UART_EXAR_MPIOINV_7_0 ); +writeb (0xc0 , p +UART_EXAR_MPIOSEL_7_0 ); +break ; + } +writeb (0x00 , p +UART_EXAR_MPIOINT_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIO3T_7_0 ); +writeb (0x00 , p +UART_EXAR_MPIOOD_7_0 ); + } + +return 0 ; +} + +static int pci_connect_tech_setup (struct exar8250 *priv,struct pci_dev *pcidev,struct uart_8250_port *port,int idx) {
@@ -291,6 +344,21 @@ static int __maybe_unused exar_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(exar_pci_pm, exar_suspend, exar_resume); +static const struct exar8250_board pbn_fastcom335_2 = { + .num_ports =2 , + .setup = pci_fastcom335_setup, +}; + +static const struct exar8250_board pbn_fastcom335_4 = { + .num_ports =4 , + .setup = pci_fastcom335_setup, +}; + +static const struct exar8250_board pbn_fastcom335_8 = { + .num_ports =8 , + .setup = pci_fastcom335_setup, +}; +static const struct exar8250_board pbn_connect = { .setup = pci_connect_tech_setup, };
@@ -375,6 +443,11 @@ static struct pci_device_id exar_pci_tbl[] = {EXAR_DEVICE (COMMTECH ,COMMTECH_4222PCIE , pbn_exar_XR17V35x),EXAR_DEVICE (COMMTECH ,COMMTECH_4224PCIE , pbn_exar_XR17V35x),EXAR_DEVICE (COMMTECH ,COMMTECH_4228PCIE , pbn_exar_XR17V35x), + +EXAR_DEVICE (COMMTECH ,COMMTECH_4222PCI335 , pbn_fastcom335_2), +EXAR_DEVICE (COMMTECH ,COMMTECH_4224PCI335 , pbn_fastcom335_4), +EXAR_DEVICE (COMMTECH ,COMMTECH_2324PCI335 , pbn_fastcom335_4), +EXAR_DEVICE (COMMTECH ,COMMTECH_2328PCI335 , pbn_fastcom335_8), { 0, } };MODULE_DEVICE_TABLE (pci, exar_pci_tbl);
drivers/tty/serial/8250/8250_pci.c +1 -138
175 lines not on this page · raw message
Signature · 1 line
2.12.3
PATCH 8/25 serial: pci: Remove unused pci_boards entries
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
commit 0d560a1d549379e46139fb9eeae0b43328c76dea upstream.
Became obsolete with the split-out of 8250_exar.
--- drivers/tty/serial/8250/8250_pci.c | 22 ---------------------- 1 file changed, 22 deletions(-)
drivers/tty/serial/8250/8250_pci.c +0 -22
@@ -2651,10 +2651,6 @@ enum pci_board_num_t { pbn_b0_2_1843200, pbn_b0_4_1843200, - pbn_b0_2_1843200_200, - pbn_b0_4_1843200_200, - pbn_b0_8_1843200_200, - pbn_b0_1_4000000, pbn_b0_bt_1_115200,
@@ -2871,24 +2867,6 @@ static struct pciserial_board pci_boards[] = { .uart_offset = 8, }, - [pbn_b0_2_1843200_200] = { - .flags = FL_BASE0, - .num_ports = 2, - .base_baud = 1843200, - .uart_offset = 0x200, - }, - [pbn_b0_4_1843200_200] = { - .flags = FL_BASE0, - .num_ports = 4, - .base_baud = 1843200, - .uart_offset = 0x200, - }, - [pbn_b0_8_1843200_200] = { - .flags = FL_BASE0, - .num_ports = 8, - .base_baud = 1843200, - .uart_offset = 0x200, - }, [pbn_b0_1_4000000] = { .flags = FL_BASE0, .num_ports = 1,
Signature · 1 line
2.12.3
PATCH 9/25 serial: 8250_EXAR: fix duplicate Kconfig text and add missing help text
In reply to Jan KiszkaFrom: Paul Gortmaker <[email protected]>
commit 49e1590c2ead870f4ae5568816241c4cb9bc1606 upstream.
In commit d0aeaa83f0b0f7a92615bbdd6b1f96812f7dcfd2 ("serial: exar:
split out the exar code from 8250_pci") the exar driver got its own Kconfig. However the text for the new option was never changed from the original 8250_PCI text, and hence it appears confusing when you get asked the same question twice:
8250/16550 PCI device support (SERIAL_8250_PCI) [Y/n/m/?] (NEW)
8250/16550 PCI device support (SERIAL_8250_EXAR) [Y/n/m] (NEW)
Adding to the confusion, is that there is no help text for this new option to indicate it is specific to a certain family of cards.
Fix both issues at the same time, as well as the space vs. tab issues introduced in the same commit.
--- drivers/tty/serial/8250/Kconfig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/tty/serial/8250/Kconfig +6 -2
@@ -117,9 +117,13 @@ config SERIAL_8250_PCI by the parport_serial driver, enabled with CONFIG_PARPORT_SERIAL. config SERIAL_8250_EXAR - tristate "8250/16550 PCI device support" - depends on SERIAL_8250_PCI + tristate "8250/16550 Exar/Commtech PCI/PCIe device support" + depends on SERIAL_8250_PCI default SERIAL_8250 + help + This builds support for XR17C1xx, XR17V3xx and some Commtech + 422x PCIe serial cards that are not covered by the more generic + SERIAL_8250_PCI option. config SERIAL_8250_HP300 tristate
Signature · 1 line
2.12.3
PATCH 10/25 serial: exar: Preconfigure xr17v35x MPIOs as output
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
commit 7dea8165f1d6434dc7572004363f86339f0f4322 upstream.
This is the safe default for GPIOs with unknown external wiring.
--- drivers/tty/serial/8250/8250_exar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/tty/serial/8250/8250_exar.c +2 -2
@@ -164,13 +164,13 @@ static void setup_gpio(u8 __iomem *p)writeb (0x00 , p +UART_EXAR_MPIOLVL_7_0 );writeb (0x00 , p +UART_EXAR_MPIO3T_7_0 );writeb (0x00 , p +UART_EXAR_MPIOINV_7_0 ); -writeb (0x00 , p +UART_EXAR_MPIOSEL_7_0 ); +writeb (0xff , p +UART_EXAR_MPIOSEL_7_0 );writeb (0x00 , p +UART_EXAR_MPIOOD_7_0 );writeb (0x00 , p +UART_EXAR_MPIOINT_15_8 );writeb (0x00 , p +UART_EXAR_MPIOLVL_15_8 );writeb (0x00 , p +UART_EXAR_MPIO3T_15_8 );writeb (0x00 , p +UART_EXAR_MPIOINV_15_8 ); -writeb (0x00 , p +UART_EXAR_MPIOSEL_15_8 ); +writeb (0xff , p +UART_EXAR_MPIOSEL_15_8 );writeb (0x00 , p +UART_EXAR_MPIOOD_15_8 ); }
Signature · 1 line
2.12.3
PATCH 11/25 serial: exar: Leave MPIOs as output for Commtech adapters
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
commit bea8be656185a2808a2f255f4a91ff18215a9d0c upstream.
Commtech adapters apparently need the original setting as outputs, see
https://marc.info/?l=linux-gpio&m=149557425201323&w=2. Account for that.
--- drivers/tty/serial/8250/8250_exar.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
drivers/tty/serial/8250/8250_exar.c +11 -4
@@ -158,19 +158,26 @@ pci_xr17c154_setup(struct exar8250 *priv, struct pci_dev *pcidev,return default_setup (priv, pcidev, idx, offset, port); } -static void setup_gpio (u8 __iomem *p) +static void setup_gpio (struct pci_dev *pcidev,u8 __iomem *p) { +/* +* The Commtech adapters required the MPIOs to be driven low. The Exar +* devices will export them as GPIOs, so we pre-configure them safely +* as inputs. +*/ +u8 dir = pcidev->vendor ==PCI_VENDOR_ID_EXAR ?0xff :0x00 ; +writeb (0x00 , p +UART_EXAR_MPIOINT_7_0 );writeb (0x00 , p +UART_EXAR_MPIOLVL_7_0 );writeb (0x00 , p +UART_EXAR_MPIO3T_7_0 );writeb (0x00 , p +UART_EXAR_MPIOINV_7_0 ); -writeb (0xff , p +UART_EXAR_MPIOSEL_7_0 ); +writeb (dir, p +UART_EXAR_MPIOSEL_7_0 );writeb (0x00 , p +UART_EXAR_MPIOOD_7_0 );writeb (0x00 , p +UART_EXAR_MPIOINT_15_8 );writeb (0x00 , p +UART_EXAR_MPIOLVL_15_8 );writeb (0x00 , p +UART_EXAR_MPIO3T_15_8 );writeb (0x00 , p +UART_EXAR_MPIOINV_15_8 ); -writeb (0xff , p +UART_EXAR_MPIOSEL_15_8 ); +writeb (dir, p +UART_EXAR_MPIOSEL_15_8 );writeb (0x00 , p +UART_EXAR_MPIOOD_15_8 ); }
@@ -223,7 +230,7 @@ pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,if (idx ==0 ) {/* Setup Multipurpose Input/Output pins. */ -setup_gpio (p); +setup_gpio (pcidev, p); port->port.private_data =xr17v35x_register_gpio (pcidev); }
Signature · 1 line
2.12.3
PATCH 12/25 serial: uapi: Add support for bus termination
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
commit e8759ad17d41913dfeb49736ca7fbfbc96f32c54 upstream.
The Siemens IOT2040 comes with a RS485 interface that allows to enable or disable bus termination via software. Add a bit to the flags field of serial_rs485 that applications can set in order to request this feature from the hardware. This seems generic enough to add it for everyone. Existing driver will simply ignore it when set.
--- include/uapi/linux/serial.h | 3 +++ 1 file changed, 3 insertions(+)
include/uapi/linux/serial.h +3 -0
@@ -121,6 +121,9 @@ struct serial_rs485 {#define SER_RS485_RTS_AFTER_SEND (1 << 2)/* Logical level for RTS pin after sent*/ #define SER_RS485_RX_DURING_TX (1 << 4) +#define SER_RS485_TERMINATE_BUS (1 << 5)/* Enable bus +termination +(if supported) */ __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
Signature · 1 line
2.12.3
PATCH 13/25 gpio: add a data pointer to gpio_chip
In reply to Jan KiszkaFrom: Linus Walleij <[email protected]>
commit b08ea35a3296ee25c4cb53a977b752266dafa2c2 upstream.
This adds a void * pointer to gpio_chip so that driver can assign and retrieve some states. This is done to get rid of container_of() calls for gpio_chips embedded inside state containers, so we can remove the need to have the gpio_chip or later (planned) struct gpio_device be dynamically allocated at registration time, so that its struct device can be properly reference counted and not bound to its parent device (e.g. a platform_device) but instead live on after unregistration if it is opened by e.g. a char device or sysfs.
The data is added with the new function gpiochip_add_data() and for compatibility we add static inline wrapper function gpiochip_add() that will call gpiochip_add_data() with NULL as argument. The latter will be removed once we have exorcised gpiochip_add() from the kernel.
gpiochip_get_data() is added as a static inline accessor for drivers to quickly get their data out.
--- drivers/gpio/gpiolib.c | 10 ++++++---- include/linux/gpio/driver.h | 14 +++++++++++++- 2 files changed, 19 insertions(+), 5 deletions(-)
drivers/gpio/gpiolib.c +6 -4
@@ -280,7 +280,7 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc) }/** -* gpiochip_add() - register a gpio_chip +* gpiochip_add_data() - register a gpio_chip * @chip: the chip to register, with chip->base initialized * Context: potentially before irqs will work *
@@ -288,7 +288,7 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc)* because the chip->base is invalid or already associated with a * different chip. Otherwise it returns zero as a success code. * -* When gpiochip_add() is called very early during boot, so that GPIOs +* When gpiochip_add_data() is called very early during boot, so that GPIOs * can be freely used, the chip->dev device must be registered before * the gpio framework's arch_initcall(). Otherwise sysfs initialization * for GPIOs will fail rudely.
@@ -296,7 +296,7 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc)* If chip->base is negative, this requests dynamic assignment of * a range of valid GPIOs. */ -int gpiochip_add (struct gpio_chip *chip) +int gpiochip_add_data (struct gpio_chip *chip,void *data) {unsigned long flags;int status =0 ;
@@ -308,6 +308,8 @@ int gpiochip_add(struct gpio_chip *chip)if (!descs)return -ENOMEM ; + chip->data = data; +spin_lock_irqsave (&gpio_lock, flags);if (base <0 ) {
@@ -389,7 +391,7 @@ err_free_descs: chip->label ? : "generic");return status; } -EXPORT_SYMBOL_GPL (gpiochip_add); +EXPORT_SYMBOL_GPL (gpiochip_add_data);/** * gpiochip_remove() - unregister a gpio_chip
include/linux/gpio/driver.h +13 -1
@@ -23,6 +23,7 @@ struct seq_file;* @dev: optional device providing the GPIOs * @cdev: class device used by sysfs interface (may be NULL) * @owner: helps prevent removal of modules exporting active GPIOs +* @data: per-instance data assigned by the driver * @list: links gpio_chips together for traversal * @request: optional hook for chip-specific activation, such as * enabling module power and clock; may sleep
@@ -92,6 +93,7 @@ struct gpio_chip {struct device *dev;struct device *cdev;struct module *owner; +void *data;struct list_head list; int (*request)(struct gpio_chip *chip,
@@ -166,7 +168,11 @@ extern const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset);/* add/remove chips */ -extern int gpiochip_add (struct gpio_chip *chip); +extern int gpiochip_add_data (struct gpio_chip *chip,void *data); +static inline int gpiochip_add (struct gpio_chip *chip) +{ +return gpiochip_add_data (chip,NULL ); +}extern void gpiochip_remove (struct gpio_chip *chip);extern struct gpio_chip *gpiochip_find (void *data,int (*match)(struct gpio_chip *chip,void *data));
@@ -175,6 +181,12 @@ extern struct gpio_chip *gpiochip_find(void *data,int gpiochip_lock_as_irq (struct gpio_chip *chip,unsigned int offset);void gpiochip_unlock_as_irq (struct gpio_chip *chip,unsigned int offset); +/* get driver data */ +static inline void *gpiochip_get_data (struct gpio_chip *chip) +{ +return chip->data; +} +struct gpio_chip *gpiod_to_chip (const struct gpio_desc *desc);#ifdef CONFIG_GPIOLIB_IRQCHIP
Signature · 1 line
2.12.3
PATCH 14/25 gpio: Add devm_ apis for gpiochip_add_data and gpiochip_remove
In reply to Jan KiszkaFrom: Laxman Dewangan <[email protected]>
commit 0cf3292cde22f8843ae5d1eeb8466d8121243c1a upstream.
Add device managed APIs devm_gpiochip_add_data() and devm_gpiochip_remove() for the APIs gpiochip_add_data() and gpiochip_remove().
This helps in reducing code in error path and sometimes removal of .remove callback for driver unbind.
--- drivers/gpio/gpiolib.c | 74 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/gpio/driver.h | 4 +++ 2 files changed, 78 insertions(+)
drivers/gpio/gpiolib.c +74 -0
@@ -433,6 +433,80 @@ void gpiochip_remove(struct gpio_chip *chip) }EXPORT_SYMBOL_GPL (gpiochip_remove); +static void devm_gpio_chip_release (struct device *dev,void *res) +{ +struct gpio_chip *chip = *(struct gpio_chip **)res; + +gpiochip_remove (chip); +} + +static int devm_gpio_chip_match (struct device *dev,void *res,void *data) + +{ +struct gpio_chip **r = res; + +if (!r || !*r) { +WARN_ON (!r || !*r); +return 0 ; + } + +return *r == data; +} + +/** +* devm_gpiochip_add_data() - Resource manager piochip_add_data() +* @dev: the device pointer on which irq_chip belongs to. +* @chip: the chip to register, with chip->base initialized +* Context: potentially before irqs will work +* +* Returns a negative errno if the chip can't be registered, such as +* because the chip->base is invalid or already associated with a +* different chip. Otherwise it returns zero as a success code. +* +* The gpio chip automatically be released when the device is unbound. +*/ +int devm_gpiochip_add_data (struct device *dev,struct gpio_chip *chip, +void *data) +{ +struct gpio_chip **ptr; +int ret; + + ptr =devres_alloc (devm_gpio_chip_release,sizeof (*ptr), +GFP_KERNEL ); +if (!ptr) +return -ENOMEM ; + + ret =gpiochip_add_data (chip, data); +if (ret <0 ) { +devres_free (ptr); +return ret; + } + + *ptr = chip; +devres_add (dev, ptr); + +return 0 ; +} +EXPORT_SYMBOL_GPL (devm_gpiochip_add_data); + +/** +* devm_gpiochip_remove() - Resource manager of gpiochip_remove() +* @dev: device for which which resource was allocated +* @chip: the chip to remove +* +* A gpio_chip with any GPIOs still requested may not be removed. +*/ +void devm_gpiochip_remove (struct device *dev,struct gpio_chip *chip) +{ +int ret; + + ret =devres_release (dev, devm_gpio_chip_release, + devm_gpio_chip_match, chip); +if (!ret) +WARN_ON (ret); +} +EXPORT_SYMBOL_GPL (devm_gpiochip_remove); +/** * gpiochip_find() - iterator for locating a specific gpio_chip * @data: data to pass to match function
include/linux/gpio/driver.h +4 -0
@@ -174,6 +174,10 @@ static inline int gpiochip_add(struct gpio_chip *chip)return gpiochip_add_data (chip,NULL ); }extern void gpiochip_remove (struct gpio_chip *chip); +extern int devm_gpiochip_add_data (struct device *dev,struct gpio_chip *chip, +void *data); +extern void devm_gpiochip_remove (struct device *dev,struct gpio_chip *chip); +extern struct gpio_chip *gpiochip_find (void *data,int (*match)(struct gpio_chip *chip,void *data));
Signature · 1 line
2.12.3
PATCH 15/25 gpio: exar: add gpio for exar cards
In reply to Jan KiszkaFrom: Sudip Mukherjee <[email protected]>
commit 6596e59e63cd4c0c0b787ce8c1e8bdd1d957b16e upstream.
Exar XR17V352/354/358 chips have 16 multi-purpose inputs/outputs which can be controlled using gpio interface.
Add the gpio specific code.
--- drivers/gpio/Kconfig | 7 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-exar.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 drivers/gpio/gpio-exar.c
drivers/gpio/Kconfig +7 -0
@@ -184,6 +184,13 @@ config GPIO_ETRAXFS help Say yes here to support the GPIO controller on Axis ETRAX FS SoCs. +config GPIO_EXAR + tristate "Support for GPIO pins on XR17V352/354/358" + depends on SERIAL_8250_EXAR + help + Selecting this option will enable handling of GPIO pins present + on Exar XR17V352/354/358 chips. + config GPIO_GE_FPGA bool "GE FPGA based GPIO" depends on GE_FPGA
drivers/gpio/Makefile +1 -0
@@ -37,6 +37,7 @@ obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o obj-$(CONFIG_GPIO_EM) += gpio-em.o obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o obj-$(CONFIG_GPIO_ETRAXFS) += gpio-etraxfs.o +obj-$(CONFIG_GPIO_EXAR) += gpio-exar.o obj-$(CONFIG_GPIO_F7188X) += gpio-f7188x.o obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
drivers/gpio/gpio-exar.c new file +200 -0
200 lines not on this page · raw message
Signature · 1 line
2.12.3
PATCH 16/25 gpio: exar: Set proper output level in exar_direction_output
In reply to Jan KiszkaFrom: Axel Lin <[email protected]>
commit eddeae073760aa3186e2fa0d14a12794687fa786 upstream.
Current code does not set output level in exar_direction_output, fix it. Also move the direction_output/direction_input code block to avoid forward declaration for exar_set_value().
--- drivers/gpio/gpio-exar.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-)
drivers/gpio/gpio-exar.c +12 -11
@@ -59,17 +59,6 @@ static int exar_set_direction(struct gpio_chip *chip, int direction,return 0 ; } -static int exar_direction_output (struct gpio_chip *chip,unsigned int offset, -int value) -{ -return exar_set_direction (chip,0 , offset); -} - -static int exar_direction_input (struct gpio_chip *chip,unsigned int offset) -{ -return exar_set_direction (chip,1 , offset); -} -static int exar_get (struct gpio_chip *chip,unsigned int reg) {struct exar_gpio_chip *exar_gpio =gpiochip_get_data (chip);
@@ -116,6 +105,18 @@ static void exar_set_value(struct gpio_chip *chip, unsigned int offset,exar_update (chip, addr, value, offset %8 ); } +static int exar_direction_output (struct gpio_chip *chip,unsigned int offset, +int value) +{ +exar_set_value (chip, offset, value); +return exar_set_direction (chip,0 , offset); +} + +static int exar_direction_input (struct gpio_chip *chip,unsigned int offset) +{ +return exar_set_direction (chip,1 , offset); +} +static int gpio_exar_probe (struct platform_device *pdev) {struct pci_dev *pcidev =platform_get_drvdata (pdev);
Signature · 1 line
2.12.3
PATCH 17/25 gpio-exar/8250-exar: Fix passing in of parent PCI device
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
commit d3936d7437e388f3a91995e8f07fb82affff2f0d upstream.
This fixes reloading of the GPIO driver for the same platform device instance as created by the exar UART driver: First of all, the driver sets drvdata to its own value during probing and does not restore the original value on exit. But this won't help anyway as the core clears drvdata after the driver left.
Set the platform device parent instead.
--- drivers/gpio/gpio-exar.c | 2 +- drivers/tty/serial/8250/8250_exar.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-)
drivers/gpio/gpio-exar.c +1 -1
@@ -119,7 +119,7 @@ static int exar_direction_input(struct gpio_chip *chip, unsigned int offset)static int gpio_exar_probe (struct platform_device *pdev) { -struct pci_dev *pcidev =platform_get_drvdata (pdev); +struct pci_dev *pcidev =to_pci_dev (pdev->dev.parent);struct exar_gpio_chip *exar_gpio;void __iomem *p;int index, ret;
drivers/tty/serial/8250/8250_exar.c +2 -1
@@ -190,7 +190,8 @@ xr17v35x_register_gpio(struct pci_dev *pcidev)if (!pdev)return NULL ; -platform_set_drvdata (pdev, pcidev); + pdev->dev.parent = &pcidev->dev; +if (platform_device_add (pdev) <0 ) {platform_device_put (pdev);return NULL ;
Signature · 1 line
2.12.3
PATCH 18/25 gpio: exar: Allocate resources on behalf of the platform device
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
commit 5dab5872e59390aa9cca26ee629b95f7179f6c77 upstream.
Do not allocate resources on behalf of the parent device but on our own. Otherwise, cleanup does not properly work if gpio-exar is removed but not the parent device.
--- drivers/gpio/gpio-exar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpio/gpio-exar.c +2 -2
@@ -139,7 +139,7 @@ static int gpio_exar_probe(struct platform_device *pdev)if (!p)return -ENOMEM ; - exar_gpio =devm_kzalloc (&pcidev->dev,sizeof (*exar_gpio),GFP_KERNEL ); + exar_gpio =devm_kzalloc (&pdev->dev,sizeof (*exar_gpio),GFP_KERNEL );if (!exar_gpio)return -ENOMEM ;
@@ -160,7 +160,7 @@ static int gpio_exar_probe(struct platform_device *pdev) exar_gpio->regs = p; exar_gpio->index = index; - ret =devm_gpiochip_add_data (&pcidev->dev, + ret =devm_gpiochip_add_data (&pdev->dev, &exar_gpio->gpio_chip, exar_gpio);if (ret) goto err_destroy;
Signature · 1 line
2.12.3
PATCH 19/25 gpio: exar: Fix reading of directions and values
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
commit 7f45a875da46a112f781c25cfa9bcb93aaed4712 upstream.
First, the logic for translating a register bit to the return code of exar_get_direction and exar_get_value were wrong. And second, there was a flip regarding the register bank in exar_get_direction.
--- drivers/gpio/gpio-exar.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/gpio/gpio-exar.c +4 -4
@@ -68,7 +68,7 @@ static int exar_get(struct gpio_chip *chip, unsigned int reg) value =readb (exar_gpio->regs + reg);mutex_unlock (&exar_gpio->lock); -return !!value; +return value; }static int exar_get_direction (struct gpio_chip *chip,unsigned int offset)
@@ -78,7 +78,7 @@ static int exar_get_direction(struct gpio_chip *chip, unsigned int offset)int val; addr = bank ?EXAR_OFFSET_MPIOSEL_HI :EXAR_OFFSET_MPIOSEL_LO ; - val =exar_get (chip, addr) >> (offset %8 ); + val =exar_get (chip, addr) &BIT (offset %8 );return !!val; }
@@ -89,8 +89,8 @@ static int exar_get_value(struct gpio_chip *chip, unsigned int offset)unsigned int addr;int val; - addr = bank ?EXAR_OFFSET_MPIOLVL_LO :EXAR_OFFSET_MPIOLVL_HI ; - val =exar_get (chip, addr) >> (offset %8 ); + addr = bank ?EXAR_OFFSET_MPIOLVL_HI :EXAR_OFFSET_MPIOLVL_LO ; + val =exar_get (chip, addr) &BIT (offset %8 );return !!val; }
Signature · 1 line
2.12.3
PATCH 20/25 gpio-exar/8250-exar: Do not even instantiate a GPIO device for Commtech cards
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
commit a39f2fe7165647c2cd7bdbebb3d04061035e520f upstream.
Commtech adapters need the MPIOs for internal purposes, and the gpio-exar driver already refused to pick them up. But there is actually no point in even creating the underlying platform device.
--- drivers/gpio/gpio-exar.c | 3 --- drivers/tty/serial/8250/8250_exar.c | 4 +++- 2 files changed, 3 insertions(+), 4 deletions(-)
drivers/gpio/gpio-exar.c +0 -3
@@ -124,9 +124,6 @@ static int gpio_exar_probe(struct platform_device *pdev)void __iomem *p;int index, ret; -if (pcidev->vendor !=PCI_VENDOR_ID_EXAR ) -return -ENODEV ; -/* * Map the pci device to get the register addresses. * We will need to read and write those registers to control
drivers/tty/serial/8250/8250_exar.c +3 -1
@@ -233,7 +233,9 @@ pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,/* Setup Multipurpose Input/Output pins. */ setup_gpio (pcidev, p); - port->port.private_data =xr17v35x_register_gpio (pcidev); +if (pcidev->vendor ==PCI_VENDOR_ID_EXAR ) + port->port.private_data = +xr17v35x_register_gpio (pcidev); }return 0 ;
Signature · 1 line
2.12.3
PATCH 21/25 gpio: exar: Fix iomap request
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
commit 8847f5f9ef554269d2a06100b311d363b9727da6 upstream.
The UART driver already maps the resource for us. Trying to do this here only fails and leaves us with a non-working device.
--- drivers/gpio/gpio-exar.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
drivers/gpio/gpio-exar.c +3 -7
@@ -125,14 +125,10 @@ static int gpio_exar_probe(struct platform_device *pdev)int index, ret;/* -* Map the pci device to get the register addresses. -* We will need to read and write those registers to control -* the GPIO pins. -* Using managed functions will save us from unmaping on exit. -* As the device is enabled using managed functions by the -* UART driver we can also use managed functions here. +* The UART driver must have mapped region 0 prior to registering this +* device - use it. */ - p =pcim_iomap (pcidev,0 ,0 ); + p =pcim_iomap_table (pcidev)[0 ];if (!p)return -ENOMEM ;
Signature · 1 line
2.12.3
PATCH 22/25 gpio-exar/8250-exar: Rearrange gpiochip parenthood
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
commit 4076cf08ac7673aca7d4dd9ddf18045d08dbc292 upstream.
Set the parent of the exar gpiochip to its platform device, like other gpiochips are doing it. In order to keep the relationship discoverable for ACPI systems, set the platform device companion to the PCI device.
--- drivers/gpio/gpio-exar.c | 2 +- drivers/tty/serial/8250/8250_exar.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-)
drivers/gpio/gpio-exar.c +1 -1
@@ -142,7 +142,7 @@ static int gpio_exar_probe(struct platform_device *pdev)sprintf (exar_gpio->name,"exar_gpio%d" , index); exar_gpio->gpio_chip.label = exar_gpio->name; - exar_gpio->gpio_chip.dev = &pcidev->dev; + exar_gpio->gpio_chip.dev = &pdev->dev; exar_gpio->gpio_chip.direction_output = exar_direction_output; exar_gpio->gpio_chip.direction_input = exar_direction_input; exar_gpio->gpio_chip.get_direction = exar_get_direction;
drivers/tty/serial/8250/8250_exar.c +2 -0
@@ -9,6 +9,7 @@* it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. */ +#include <linux/acpi.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h>
@@ -191,6 +192,7 @@ xr17v35x_register_gpio(struct pci_dev *pcidev)return NULL ; pdev->dev.parent = &pcidev->dev; +ACPI_COMPANION_SET (&pdev->dev,ACPI_COMPANION (&pcidev->dev));if (platform_device_add (pdev) <0 ) {platform_device_put (pdev);
Signature · 1 line
2.12.3
PATCH 23/25 serial: exar: Factor out platform hooks
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
commit 0d963ebf57d4c6374b3a33050a18af23c1e2ede1 upstream.
This prepares the addition of IOT2040 platform support by preparing the needed setup and rs485_config hooks.
--- drivers/tty/serial/8250/8250_exar.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-)
drivers/tty/serial/8250/8250_exar.c +27 -5
@@ -50,6 +50,11 @@struct exar8250 ; +struct exar8250_platform { +int (*rs485_config)(struct uart_port *,struct serial_rs485 *); +int (*register_gpio)(struct pci_dev *,struct uart_8250_port *); +}; +/** * struct exar8250_board - board information * @num_ports: number of serial ports
@@ -183,7 +188,7 @@ static void setup_gpio(struct pci_dev *pcidev, u8 __iomem *p) }static void * -xr17v35x_register_gpio (struct pci_dev *pcidev) +__xr17v35x_register_gpio (struct pci_dev *pcidev) {struct platform_device *pdev;
@@ -202,17 +207,36 @@ xr17v35x_register_gpio(struct pci_dev *pcidev)return pdev; } +static int xr17v35x_register_gpio (struct pci_dev *pcidev, +struct uart_8250_port *port) +{ +if (pcidev->vendor ==PCI_VENDOR_ID_EXAR ) + port->port.private_data = +__xr17v35x_register_gpio (pcidev); + +return 0 ; +} + +static const struct exar8250_platform exar8250_default_platform = { + .register_gpio = xr17v35x_register_gpio, +}; +static int pci_xr17v35x_setup (struct exar8250 *priv,struct pci_dev *pcidev,struct uart_8250_port *port,int idx) {const struct exar8250_board *board = priv->board; +const struct exar8250_platform *platform;unsigned int offset = idx *0x400 ;unsigned int baud =7812500 ;u8 __iomem *p;int ret; + platform = &exar8250_default_platform; + port->port.uartclk = baud *16 ; + port->port.rs485_config = platform->rs485_config; +/* * Setup the uart clock for the devices on expansion slot to * half the clock speed of the main chip (which is 125MHz)
@@ -235,12 +259,10 @@ pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,/* Setup Multipurpose Input/Output pins. */ setup_gpio (pcidev, p); -if (pcidev->vendor ==PCI_VENDOR_ID_EXAR ) - port->port.private_data = -xr17v35x_register_gpio (pcidev); + ret = platform->register_gpio (pcidev, port); } -return 0 ; +return ret; }static void pci_xr17v35x_exit (struct pci_dev *pcidev)
Signature · 1 line
2.12.3
PATCH 24/25 gpio-exar/8250-exar: Make set of exported GPIOs configurable
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
commit 380b1e2f3a2f32bfe9c0aa85a68629eb99b043c0 upstream.
On the SIMATIC, IOT2040 only a single pin is exportable as GPIO, the rest is required to operate the UART. To allow modeling this case, expand the platform device data structure to specify a (consecutive) pin subset for exporting by the gpio-exar driver.
--- drivers/gpio/gpio-exar.c | 48 +++++++++++++++++---------------- drivers/tty/serial/8250/8250_exar.c | 14 +++++++--- include/linux/platform_data/gpio-exar.h | 21 +++++++++++++++ 3 files changed, 57 insertions(+), 26 deletions(-) create mode 100644 include/linux/platform_data/gpio-exar.h
drivers/gpio/gpio-exar.c +25 -23
@@ -15,6 +15,7 @@#include <linux/module.h> #include <linux/pci.h> #include <linux/platform_device.h> +#include <linux/platform_data/gpio-exar.h> #define EXAR_OFFSET_MPIOLVL_LO 0x90#define EXAR_OFFSET_MPIOSEL_LO 0x93
@@ -31,6 +32,7 @@ struct exar_gpio_chip {int index;void __iomem *regs;char name[20 ]; +unsigned int first_pin; }; static void exar_update(struct gpio_chip *chip, unsigned int reg, int val,
@@ -51,11 +53,12 @@ static void exar_update(struct gpio_chip *chip, unsigned int reg, int val,static int exar_set_direction (struct gpio_chip *chip,int direction,unsigned int offset) { -unsigned int bank = offset /8 ; -unsigned int addr; +struct exar_gpio_chip *exar_gpio =gpiochip_get_data (chip); +unsigned int addr = (offset + exar_gpio->first_pin) /8 ? +EXAR_OFFSET_MPIOSEL_HI :EXAR_OFFSET_MPIOSEL_LO ; +unsigned int bit = (offset + exar_gpio->first_pin) %8 ; - addr = bank ?EXAR_OFFSET_MPIOSEL_HI :EXAR_OFFSET_MPIOSEL_LO ; -exar_update (chip, addr, direction, offset %8 ); +exar_update (chip, addr, direction, bit);return 0 ; }
@@ -73,36 +76,33 @@ static int exar_get(struct gpio_chip *chip, unsigned int reg)static int exar_get_direction (struct gpio_chip *chip,unsigned int offset) { -unsigned int bank = offset /8 ; -unsigned int addr; -int val; - - addr = bank ?EXAR_OFFSET_MPIOSEL_HI :EXAR_OFFSET_MPIOSEL_LO ; - val =exar_get (chip, addr) &BIT (offset %8 ); +struct exar_gpio_chip *exar_gpio =gpiochip_get_data (chip); +unsigned int addr = (offset + exar_gpio->first_pin) /8 ? +EXAR_OFFSET_MPIOSEL_HI :EXAR_OFFSET_MPIOSEL_LO ; +unsigned int bit = (offset + exar_gpio->first_pin) %8 ; -return !!val; +return !!(exar_get (chip, addr) &BIT (bit)); }static int exar_get_value (struct gpio_chip *chip,unsigned int offset) { -unsigned int bank = offset /8 ; -unsigned int addr; -int val; - - addr = bank ?EXAR_OFFSET_MPIOLVL_HI :EXAR_OFFSET_MPIOLVL_LO ; - val =exar_get (chip, addr) &BIT (offset %8 ); +struct exar_gpio_chip *exar_gpio =gpiochip_get_data (chip); +unsigned int addr = (offset + exar_gpio->first_pin) /8 ? +EXAR_OFFSET_MPIOLVL_HI :EXAR_OFFSET_MPIOLVL_LO ; +unsigned int bit = (offset + exar_gpio->first_pin) %8 ; -return !!val; +return !!(exar_get (chip, addr) &BIT (bit)); }static void exar_set_value (struct gpio_chip *chip,unsigned int offset,int value) { -unsigned int bank = offset /8 ; -unsigned int addr; +struct exar_gpio_chip *exar_gpio =gpiochip_get_data (chip); +unsigned int addr = (offset + exar_gpio->first_pin) /8 ? +EXAR_OFFSET_MPIOLVL_HI :EXAR_OFFSET_MPIOLVL_LO ; +unsigned int bit = (offset + exar_gpio->first_pin) %8 ; - addr = bank ?EXAR_OFFSET_MPIOLVL_HI :EXAR_OFFSET_MPIOLVL_LO ; -exar_update (chip, addr, value, offset %8 ); +exar_update (chip, addr, value, bit); } static int exar_direction_output(struct gpio_chip *chip, unsigned int offset,
@@ -119,6 +119,7 @@ static int exar_direction_input(struct gpio_chip *chip, unsigned int offset)static int gpio_exar_probe (struct platform_device *pdev) { +const struct gpio_exar_pdata *pdata = pdev->dev.platform_data;struct pci_dev *pcidev =to_pci_dev (pdev->dev.parent);struct exar_gpio_chip *exar_gpio;void __iomem *p;
@@ -149,9 +150,10 @@ static int gpio_exar_probe(struct platform_device *pdev) exar_gpio->gpio_chip.get = exar_get_value; exar_gpio->gpio_chip.set = exar_set_value; exar_gpio->gpio_chip.base =-1 ; - exar_gpio->gpio_chip.ngpio =16 ; + exar_gpio->gpio_chip.ngpio = pdata->ngpios; exar_gpio->regs = p; exar_gpio->index = index; + exar_gpio->first_pin = pdata->first_pin; ret =devm_gpiochip_add_data (&pdev->dev, &exar_gpio->gpio_chip, exar_gpio);
drivers/tty/serial/8250/8250_exar.c +11 -3
@@ -20,6 +20,7 @@#include <linux/string.h> #include <linux/tty.h> #include <linux/8250_pci.h> +#include <linux/platform_data/gpio-exar.h> #include <asm/byteorder.h>
@@ -188,7 +189,8 @@ static void setup_gpio(struct pci_dev *pcidev, u8 __iomem *p) }static void * -__xr17v35x_register_gpio (struct pci_dev *pcidev) +__xr17v35x_register_gpio (struct pci_dev *pcidev, +const struct gpio_exar_pdata *pdata) {struct platform_device *pdev;
@@ -199,7 +201,8 @@ __xr17v35x_register_gpio(struct pci_dev *pcidev) pdev->dev.parent = &pcidev->dev;ACPI_COMPANION_SET (&pdev->dev,ACPI_COMPANION (&pcidev->dev)); -if (platform_device_add (pdev) <0 ) { +if (platform_device_add_data (pdev, pdata,sizeof (*pdata)) <0 || +platform_device_add (pdev) <0 ) {platform_device_put (pdev);return NULL ; }
@@ -207,12 +210,17 @@ __xr17v35x_register_gpio(struct pci_dev *pcidev)return pdev; } +static const struct gpio_exar_pdata exar_gpio_pdata = { + .first_pin =0 , + .ngpios =16 , +}; +static int xr17v35x_register_gpio (struct pci_dev *pcidev,struct uart_8250_port *port) {if (pcidev->vendor ==PCI_VENDOR_ID_EXAR ) port->port.private_data = -__xr17v35x_register_gpio (pcidev); +__xr17v35x_register_gpio (pcidev, &exar_gpio_pdata);return 0 ; }
include/linux/platform_data/gpio-exar.h new file +21 -0
@@ -0,0 +1,21 @@ +/* +* GPIO handling for Exar XR17V35X chip +* +* Copyright (c) 2017 Siemens AG +* +* Written by Jan Kiszka <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +*/ + +#ifndef __GPIO_EXAR_PDATA_H +#define __GPIO_EXAR_PDATA_H + +struct gpio_exar_pdata { +unsigned int first_pin; +unsigned int ngpios; +}; + +#endif /* __GPIO_EXAR_PDATA_H */
Signature · 1 line
2.12.3
PATCH 25/25 serial: exar: Add support for IOT2040 device
In reply to Jan KiszkaFrom: Jan Kiszka <[email protected]>
commit 413058df4331ce29f9934a5870d582c7e71fe15f upstream.
This implements the setup of RS232 and the switch-over to RS485 or RS422 for the Siemens IOT2040. That uses an EXAR XR17V352 with external logic to switch between the different modes. The external logic is controlled via MPIO pins of the EXAR controller.
Only pin 10 can be exported as GPIO on the IOT2040. It is connected to an LED.
As the XR17V352 used on the IOT2040 is not equipped with an external EEPROM, it cannot present itself as IOT2040-variant via subvendor/ subdevice IDs. Thus, we have to check via DMI for the target platform.
Co-developed with Sascha Weisenberger.
--- drivers/tty/serial/8250/8250_exar.c | 128 +++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 1 deletion(-)
drivers/tty/serial/8250/8250_exar.c +127 -1
@@ -10,6 +10,7 @@* the Free Software Foundation; either version 2 of the License. */ #include <linux/acpi.h> +#include <linux/dmi.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h>
@@ -49,6 +50,43 @@#define UART_EXAR_MPIOSEL_15_8 0x99/* MPIOSEL[15:8] */ #define UART_EXAR_MPIOOD_15_8 0x9a/* MPIOOD[15:8] */ +#define UART_EXAR_RS485_DLY (x) ((x) << 4) + +/* +* IOT2040 MPIO wiring semantics: +* +* MPIO Port Function +* ---- ---- -------- +* 0 2 Mode bit 0 +* 1 2 Mode bit 1 +* 2 2 Terminate bus +* 3 - <reserved> +* 4 3 Mode bit 0 +* 5 3 Mode bit 1 +* 6 3 Terminate bus +* 7 - <reserved> +* 8 2 Enable +* 9 3 Enable +* 10 - Red LED +* 11..15 - <unused> +*/ + +/* IOT2040 MPIOs 0..7 */ +#define IOT2040_UART_MODE_RS232 0x01 +#define IOT2040_UART_MODE_RS485 0x02 +#define IOT2040_UART_MODE_RS422 0x03 +#define IOT2040_UART_TERMINATE_BUS 0x04 + +#define IOT2040_UART1_MASK 0x0f +#define IOT2040_UART2_SHIFT 4 + +#define IOT2040_UARTS_DEFAULT_MODE 0x11/* both RS232 */ +#define IOT2040_UARTS_GPIO_LO_MODE 0x88/* reserved pins as input */ + +/* IOT2040 MPIOs 8..15 */ +#define IOT2040_UARTS_ENABLE 0x03 +#define IOT2040_UARTS_GPIO_HI_MODE 0xF8/* enable & LED as outputs */ +struct exar8250 ;struct exar8250_platform {
@@ -229,18 +267,106 @@ static const struct exar8250_platform exar8250_default_platform = { .register_gpio = xr17v35x_register_gpio, }; +static int iot2040_rs485_config (struct uart_port *port, +struct serial_rs485 *rs485) +{ +bool is_rs485 = !!(rs485->flags &SER_RS485_ENABLED ); +u8 __iomem *p = port->membase; +u8 mask =IOT2040_UART1_MASK ; +u8 mode, value; + +if (is_rs485) { +if (rs485->flags &SER_RS485_RX_DURING_TX ) + mode =IOT2040_UART_MODE_RS422 ; +else + mode =IOT2040_UART_MODE_RS485 ; + +if (rs485->flags &SER_RS485_TERMINATE_BUS ) + mode |=IOT2040_UART_TERMINATE_BUS ; + }else { + mode =IOT2040_UART_MODE_RS232 ; + } + +if (port->line ==3 ) { + mask <<=IOT2040_UART2_SHIFT ; + mode <<=IOT2040_UART2_SHIFT ; + } + + value =readb (p +UART_EXAR_MPIOLVL_7_0 ); + value &= ~mask; + value |= mode; +writeb (value, p +UART_EXAR_MPIOLVL_7_0 ); + + value =readb (p +UART_EXAR_FCTR ); +if (is_rs485) + value |=UART_FCTR_EXAR_485 ; +else + value &= ~UART_FCTR_EXAR_485 ; +writeb (value, p +UART_EXAR_FCTR ); + +if (is_rs485) +writeb (UART_EXAR_RS485_DLY (4 ), p +UART_MSR ); + + port->rs485 = *rs485; + +return 0 ; +} + +static const struct gpio_exar_pdata iot2040_gpio_pdata = { + .first_pin =10 , + .ngpios =1 , +}; + +static int iot2040_register_gpio (struct pci_dev *pcidev, +struct uart_8250_port *port) +{ +u8 __iomem *p = port->port.membase; + +writeb (IOT2040_UARTS_DEFAULT_MODE , p +UART_EXAR_MPIOLVL_7_0 ); +writeb (IOT2040_UARTS_GPIO_LO_MODE , p +UART_EXAR_MPIOSEL_7_0 ); +writeb (IOT2040_UARTS_ENABLE , p +UART_EXAR_MPIOLVL_15_8 ); +writeb (IOT2040_UARTS_GPIO_HI_MODE , p +UART_EXAR_MPIOSEL_15_8 ); + + port->port.private_data = +__xr17v35x_register_gpio (pcidev, &iot2040_gpio_pdata); + +return 0 ; +} + +static const struct exar8250_platform iot2040_platform = { + .rs485_config = iot2040_rs485_config, + .register_gpio = iot2040_register_gpio, +}; + +static const struct dmi_system_id exar_platforms[] = { + { + .matches = { +DMI_EXACT_MATCH (DMI_BOARD_NAME ,"SIMATIC IOT2000" ), +DMI_EXACT_MATCH (DMI_BOARD_ASSET_TAG , +"6ES7647-0AA00-1YA2" ), + }, + .driver_data = (void *)&iot2040_platform, + }, + {} +}; +static int pci_xr17v35x_setup (struct exar8250 *priv,struct pci_dev *pcidev,struct uart_8250_port *port,int idx) {const struct exar8250_board *board = priv->board;const struct exar8250_platform *platform; +const struct dmi_system_id *dmi_match;unsigned int offset = idx *0x400 ;unsigned int baud =7812500 ;u8 __iomem *p;int ret; - platform = &exar8250_default_platform; + dmi_match =dmi_first_match (exar_platforms); +if (dmi_match) + platform = dmi_match->driver_data; +else + platform = &exar8250_default_platform; port->port.uartclk = baud *16 ; port->port.rs485_config = platform->rs485_config;
Signature · 1 line
2.12.3
cover EXAR UART support for IOT2040 device
In reply to Jan KiszkaQuoted 7 lines · Jan Kiszka
Second chunk: This imports a number of preparatory patches in order to fully exploit the PCI-attached dual-port EXAR with RS232/422/485 on the IOT2040.
To avoid having to backport also API-changing patches for platform devices, I've slightly modified two patches to use a communication pattern that does not require these changes.
[...]
Applied this series, except the gpiolib additions which were needed earlier.
Ben.
Signature · 2 lines
Ben Hutchings Software Developer, Codethink Ltd.
cover EXAR UART support for IOT2040 device
Quoted 5 lines · Ben Hutchings
Quoted 4 lines · Jan Kiszka
Second chunk: This imports a number of preparatory patches in order to fully exploit the PCI-attached dual-port EXAR with RS232/422/485 on the IOT2040.
Quoted 7 lines
Quoted 3 lines
To avoid having to backport also API-changing patches for platform devices, I've slightly modified two patches to use a communication pattern that does not require these changes.
[...]
Applied this series, except the gpiolib additions which were needed earlier.
Yeah, sorry, this dependency slipped through (only tested the complete series).
Thanks,
Jan