summaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-07 21:40:27 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-07 21:40:27 +0200
commitc7d28eca1d58d335ff8de6f33559b221bdd029f9 (patch)
tree3522cae5809d6912ccc307a4b0a7dea3ffeb8225 /drivers/tty
parentMerge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cl... (diff)
parentserial: exar: Add support for IOT2040 device (diff)
downloadlinux-c7d28eca1d58d335ff8de6f33559b221bdd029f9.tar.xz
linux-c7d28eca1d58d335ff8de6f33559b221bdd029f9.zip
Merge tag 'gpio-v4.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO updates from Linus Walleij: "This is the bulk of GPIO changes for the v4.13 series. Some administrativa: I have a slew of 8250 serial patches and the new IOT2040 serial+GPIO driver coming in through this tree, along with a whole bunch of Exar 8250 fixes. These are ACKed by Greg and also hit drivers/platform/* where they are ACKed by Andy Shevchenko. Speaking about drivers/platform/* there is also a bunch of ACPI stuff coming through that route, again ACKed by Andy. The MCP23S08 changes are coming in here as well. You already have the commits in your tree, so this is just a result of sharing an immutable branch between pin control and GPIO. Core: - Export add/remove for lookup tables so that modules can export GPIO descriptor tables. - Handle GPIO sleep states: it is now possible to flag that a GPIO line may loose its state during suspend/resume of the system to save power. This is used in the Wolfson Micro Arizona driver. - ACPI-based GPIO was tightened up a lot around the edges. - Use bitmap_fill() to speed up a loop. New drivers: - Exar XRA1403 SPI-based GPIO. - MVEBU driver now supports Armada 7K and 8K. - LP87565 PMIC GPIO. - Renesas R-CAR R8A7743 (RZ/G1M). - The new IOT2040 8250 serial/GPIO also comes in through this changeset. Substantial driver changes: - Seriously fix the Exar 8250 GPIO portions to work. - The MCP23S08 was moved out to a pin control driver. - Convert MEVEBU to use regmap for register access. - Drop Vulcan support from the Broadcom driver. - Serious cleanup and improvement of the mockup driver, giving us a better test coverage. Misc: - Lots of janitorial clean up. - A bunch of documentation fixes" * tag 'gpio-v4.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (70 commits) serial: exar: Add support for IOT2040 device gpio-exar/8250-exar: Make set of exported GPIOs configurable platform: Accept const properties serial: exar: Factor out platform hooks gpio-exar/8250-exar: Rearrange gpiochip parenthood gpio: exar: Fix iomap request gpio-exar/8250-exar: Do not even instantiate a GPIO device for Commtech cards serial: uapi: Add support for bus termination gpio: rcar: Add R8A7743 (RZ/G1M) support gpio: gpio-wcove: Fix GPIO control register offset calculation gpio: lp87565: Add support for GPIO gpio: dwapb: fix missing first irq for edgeboth irq type MAINTAINERS: Take maintainership for GPIO ACPI support gpio: exar: Fix reading of directions and values gpio: exar: Allocate resources on behalf of the platform device gpio-exar/8250-exar: Fix passing in of parent PCI device gpio: mockup: use devm_kcalloc() where applicable gpio: mockup: add myself as author gpio: mockup: improve the error message gpio: mockup: don't return magic numbers from probe() ...
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/serial/8250/8250_exar.c173
1 files changed, 168 insertions, 5 deletions
diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
index a309bcffffcd..b5c98e5bf524 100644
--- a/drivers/tty/serial/8250/8250_exar.c
+++ b/drivers/tty/serial/8250/8250_exar.c
@@ -9,10 +9,13 @@
* 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/dmi.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/property.h>
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
#include <linux/slab.h>
@@ -60,8 +63,50 @@
#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 {
+ 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
@@ -194,7 +239,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 property_entry *properties)
{
struct platform_device *pdev;
@@ -202,8 +248,11 @@ xr17v35x_register_gpio(struct pci_dev *pcidev)
if (!pdev)
return NULL;
- platform_set_drvdata(pdev, pcidev);
- if (platform_device_add(pdev) < 0) {
+ pdev->dev.parent = &pcidev->dev;
+ ACPI_COMPANION_SET(&pdev->dev, ACPI_COMPANION(&pcidev->dev));
+
+ if (platform_device_add_properties(pdev, properties) < 0 ||
+ platform_device_add(pdev) < 0) {
platform_device_put(pdev);
return NULL;
}
@@ -211,17 +260,131 @@ xr17v35x_register_gpio(struct pci_dev *pcidev)
return pdev;
}
+static const struct property_entry exar_gpio_properties[] = {
+ PROPERTY_ENTRY_U32("linux,first-pin", 0),
+ PROPERTY_ENTRY_U32("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, exar_gpio_properties);
+
+ return 0;
+}
+
+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 property_entry iot2040_gpio_properties[] = {
+ PROPERTY_ENTRY_U32("linux,first-pin", 10),
+ PROPERTY_ENTRY_U32("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_properties);
+
+ 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;
+ 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;
+
/*
* Setup the uart clock for the devices on expansion slot to
* half the clock speed of the main chip (which is 125MHz)
@@ -244,10 +407,10 @@ 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);
+ ret = platform->register_gpio(pcidev, port);
}
- return 0;
+ return ret;
}
static void pci_xr17v35x_exit(struct pci_dev *pcidev)