From 7241443f67bb352183bcfd7e3b807b87f2777b5d Mon Sep 17 00:00:00 2001 From: Heiko Stübner Date: Sat, 23 Feb 2013 12:08:55 -0800 Subject: Input: auo_pixcir_ts - add devicetree support Add the necessary code to create the needed platformdata from devicetree informations. The interrupt mode of the chip is not set via devicetree, as it is not a property of the hardware but instead only a preferred type of operation. This should probably be made settable via configfs in the future. The option set as default is the mode the datasheet mentions as default. Signed-off-by: Heiko Stuebner Signed-off-by: Dmitry Torokhov --- .../bindings/input/touchscreen/auo_pixcir_ts.txt | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/auo_pixcir_ts.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/input/touchscreen/auo_pixcir_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/auo_pixcir_ts.txt new file mode 100644 index 000000000000..f40f21c642b9 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/auo_pixcir_ts.txt @@ -0,0 +1,30 @@ +* AUO in-cell touchscreen controller using Pixcir sensors + +Required properties: +- compatible: must be "auo,auo_pixcir_ts" +- reg: I2C address of the chip +- interrupts: interrupt to which the chip is connected +- gpios: gpios the chip is connected to + first one is the interrupt gpio and second one the reset gpio +- x-size: horizontal resolution of touchscreen +- y-size: vertical resolution of touchscreen + +Example: + + i2c@00000000 { + /* ... */ + + auo_pixcir_ts@5c { + compatible = "auo,auo_pixcir_ts"; + reg = <0x5c>; + interrupts = <2 0>; + + gpios = <&gpf 2 0 2>, /* INT */ + <&gpf 5 1 0>; /* RST */ + + x-size = <800>; + y-size = <600>; + }; + + /* ... */ + }; -- cgit v1.2.3 From b4a034dab147776eab8eb8b2997ea16ef0e32c17 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Mon, 25 Feb 2013 22:51:37 -0800 Subject: Input: add support for GRLIB APBPS2 PS/2 Keyboard/Mouse APBPS2 is a PS/2 core part of GRLIB found in SPARC32/LEON products. Signed-off-by: Daniel Hellstrom Signed-off-by: Dmitry Torokhov --- .../bindings/input/ps2keyb-mouse-apbps2.txt | 16 ++ drivers/input/serio/Kconfig | 10 + drivers/input/serio/Makefile | 1 + drivers/input/serio/apbps2.c | 230 +++++++++++++++++++++ 4 files changed, 257 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/ps2keyb-mouse-apbps2.txt create mode 100644 drivers/input/serio/apbps2.c (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/input/ps2keyb-mouse-apbps2.txt b/Documentation/devicetree/bindings/input/ps2keyb-mouse-apbps2.txt new file mode 100644 index 000000000000..3029c5694cf6 --- /dev/null +++ b/Documentation/devicetree/bindings/input/ps2keyb-mouse-apbps2.txt @@ -0,0 +1,16 @@ +Aeroflex Gaisler APBPS2 PS/2 Core, supporting Keyboard or Mouse. + +The APBPS2 PS/2 core is available in the GRLIB VHDL IP core library. + +Note: In the ordinary environment for the APBPS2 core, a LEON SPARC system, +these properties are built from information in the AMBA plug&play and from +bootloader settings. + +Required properties: + +- name : Should be "GAISLER_APBPS2" or "01_060" +- reg : Address and length of the register set for the device +- interrupts : Interrupt numbers for this device + +For further information look in the documentation for the GLIB IP core library: +http://www.gaisler.com/products/grlib/grip.pdf diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 560c243bfcaf..dbb170916dd1 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -244,4 +244,14 @@ config SERIO_ARC_PS2 To compile this driver as a module, choose M here; the module will be called arc_ps2. +config SERIO_APBPS2 + tristate "GRLIB APBPS2 PS/2 keyboard/mouse controller" + depends on OF + help + Say Y here if you want support for GRLIB APBPS2 peripherals used + to connect to PS/2 keyboard and/or mouse. + + To compile this driver as a module, choose M here: the module will + be called apbps2. + endif diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile index 4b0c8f84f1c1..8edb36c2cdb4 100644 --- a/drivers/input/serio/Makefile +++ b/drivers/input/serio/Makefile @@ -26,3 +26,4 @@ obj-$(CONFIG_SERIO_AMS_DELTA) += ams_delta_serio.o obj-$(CONFIG_SERIO_XILINX_XPS_PS2) += xilinx_ps2.o obj-$(CONFIG_SERIO_ALTERA_PS2) += altera_ps2.o obj-$(CONFIG_SERIO_ARC_PS2) += arc_ps2.o +obj-$(CONFIG_SERIO_APBPS2) += apbps2.o diff --git a/drivers/input/serio/apbps2.c b/drivers/input/serio/apbps2.c new file mode 100644 index 000000000000..2c14e6fa64c2 --- /dev/null +++ b/drivers/input/serio/apbps2.c @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2013 Aeroflex Gaisler + * + * This driver supports the APBPS2 PS/2 core available in the GRLIB + * VHDL IP core library. + * + * Full documentation of the APBPS2 core can be found here: + * http://www.gaisler.com/products/grlib/grip.pdf + * + * See "Documentation/devicetree/bindings/input/ps2keyb-mouse-apbps2.txt" for + * information on open firmware properties. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Contributors: Daniel Hellstrom + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct apbps2_regs { + u32 __iomem data; /* 0x00 */ + u32 __iomem status; /* 0x04 */ + u32 __iomem ctrl; /* 0x08 */ + u32 __iomem reload; /* 0x0c */ +}; + +#define APBPS2_STATUS_DR (1<<0) +#define APBPS2_STATUS_PE (1<<1) +#define APBPS2_STATUS_FE (1<<2) +#define APBPS2_STATUS_KI (1<<3) +#define APBPS2_STATUS_RF (1<<4) +#define APBPS2_STATUS_TF (1<<5) +#define APBPS2_STATUS_TCNT (0x1f<<22) +#define APBPS2_STATUS_RCNT (0x1f<<27) + +#define APBPS2_CTRL_RE (1<<0) +#define APBPS2_CTRL_TE (1<<1) +#define APBPS2_CTRL_RI (1<<2) +#define APBPS2_CTRL_TI (1<<3) + +struct apbps2_priv { + struct serio *io; + struct apbps2_regs *regs; +}; + +static int apbps2_idx; + +static irqreturn_t apbps2_isr(int irq, void *dev_id) +{ + struct apbps2_priv *priv = dev_id; + unsigned long status, data, rxflags; + irqreturn_t ret = IRQ_NONE; + + while ((status = ioread32be(&priv->regs->status)) & APBPS2_STATUS_DR) { + data = ioread32be(&priv->regs->data); + rxflags = (status & APBPS2_STATUS_PE) ? SERIO_PARITY : 0; + rxflags |= (status & APBPS2_STATUS_FE) ? SERIO_FRAME : 0; + + /* clear error bits? */ + if (rxflags) + iowrite32be(0, &priv->regs->status); + + serio_interrupt(priv->io, data, rxflags); + + ret = IRQ_HANDLED; + } + + return ret; +} + +static int apbps2_write(struct serio *io, unsigned char val) +{ + struct apbps2_priv *priv = io->port_data; + unsigned int tleft = 10000; /* timeout in 100ms */ + + /* delay until PS/2 controller has room for more chars */ + while ((ioread32be(&priv->regs->status) & APBPS2_STATUS_TF) && tleft--) + udelay(10); + + if ((ioread32be(&priv->regs->status) & APBPS2_STATUS_TF) == 0) { + iowrite32be(val, &priv->regs->data); + + iowrite32be(APBPS2_CTRL_RE | APBPS2_CTRL_RI | APBPS2_CTRL_TE, + &priv->regs->ctrl); + return 0; + } + + return -ETIMEDOUT; +} + +static int apbps2_open(struct serio *io) +{ + struct apbps2_priv *priv = io->port_data; + int limit; + unsigned long tmp; + + /* clear error flags */ + iowrite32be(0, &priv->regs->status); + + /* Clear old data if available (unlikely) */ + limit = 1024; + while ((ioread32be(&priv->regs->status) & APBPS2_STATUS_DR) && --limit) + tmp = ioread32be(&priv->regs->data); + + /* Enable reciever and it's interrupt */ + iowrite32be(APBPS2_CTRL_RE | APBPS2_CTRL_RI, &priv->regs->ctrl); + + return 0; +} + +static void apbps2_close(struct serio *io) +{ + struct apbps2_priv *priv = io->port_data; + + /* stop interrupts at PS/2 HW level */ + iowrite32be(0, &priv->regs->ctrl); +} + +/* Initialize one APBPS2 PS/2 core */ +static int apbps2_of_probe(struct platform_device *ofdev) +{ + struct apbps2_priv *priv; + int irq, err; + u32 freq_hz; + struct resource *res; + + priv = devm_kzalloc(&ofdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) { + dev_err(&ofdev->dev, "memory allocation failed\n"); + return -ENOMEM; + } + + /* Find Device Address */ + res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); + priv->regs = devm_request_and_ioremap(&ofdev->dev, res); + if (!priv->regs) { + dev_err(&ofdev->dev, "io-regs mapping failed\n"); + return -EBUSY; + } + + /* Reset hardware, disable interrupt */ + iowrite32be(0, &priv->regs->ctrl); + + /* IRQ */ + irq = irq_of_parse_and_map(ofdev->dev.of_node, 0); + err = devm_request_irq(&ofdev->dev, irq, apbps2_isr, + IRQF_SHARED, "apbps2", priv); + if (err) { + dev_err(&ofdev->dev, "request IRQ%d failed\n", irq); + return err; + } + + /* Get core frequency */ + if (of_property_read_u32(ofdev->dev.of_node, "freq", &freq_hz)) { + dev_err(&ofdev->dev, "unable to get core frequency\n"); + return -EINVAL; + } + + /* Set reload register to core freq in kHz/10 */ + iowrite32be(freq_hz / 10000, &priv->regs->reload); + + priv->io = kzalloc(sizeof(struct serio), GFP_KERNEL); + if (!priv->io) + return -ENOMEM; + + priv->io->id.type = SERIO_8042; + priv->io->open = apbps2_open; + priv->io->close = apbps2_close; + priv->io->write = apbps2_write; + priv->io->port_data = priv; + strlcpy(priv->io->name, "APBPS2 PS/2", sizeof(priv->io->name)); + snprintf(priv->io->phys, sizeof(priv->io->phys), + "apbps2_%d", apbps2_idx++); + + dev_info(&ofdev->dev, "irq = %d, base = 0x%p\n", irq, priv->regs); + + serio_register_port(priv->io); + + platform_set_drvdata(ofdev, priv); + + return 0; +} + +static int apbps2_of_remove(struct platform_device *of_dev) +{ + struct apbps2_priv *priv = platform_get_drvdata(of_dev); + + serio_unregister_port(priv->io); + + return 0; +} + +static struct of_device_id apbps2_of_match[] = { + { .name = "GAISLER_APBPS2", }, + { .name = "01_060", }, + {} +}; + +MODULE_DEVICE_TABLE(of, apbps2_of_match); + +static struct platform_driver apbps2_of_driver = { + .driver = { + .name = "grlib-apbps2", + .owner = THIS_MODULE, + .of_match_table = apbps2_of_match, + }, + .probe = apbps2_of_probe, + .remove = apbps2_of_remove, +}; + +module_platform_driver(apbps2_of_driver); + +MODULE_AUTHOR("Aeroflex Gaisler AB."); +MODULE_DESCRIPTION("GRLIB APBPS2 PS/2 serial I/O"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 2c0a4f8b870dbeb48e3351899bd0e0cc886d4985 Mon Sep 17 00:00:00 2001 From: Mischa Jonker Date: Sun, 31 Mar 2013 00:25:33 -0700 Subject: Input: arc_ps2 - add support for device tree Add match table for device tree binding and dts binding doc. Signed-off-by: Mischa Jonker Signed-off-by: Dmitry Torokhov --- Documentation/devicetree/bindings/serio/snps-arc_ps2.txt | 16 ++++++++++++++++ drivers/input/serio/arc_ps2.c | 14 ++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/serio/snps-arc_ps2.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/serio/snps-arc_ps2.txt b/Documentation/devicetree/bindings/serio/snps-arc_ps2.txt new file mode 100644 index 000000000000..38c2f21e8044 --- /dev/null +++ b/Documentation/devicetree/bindings/serio/snps-arc_ps2.txt @@ -0,0 +1,16 @@ +* ARC PS/2 driver: PS/2 block used in some ARC FPGA's & nSIM OSCI model + +Required properties: +- compatible : "snps,arc_ps2" +- reg : offset and length (always 0x14) of registers +- interrupts : interrupt +- interrupt-names : name of interrupt, must be "arc_ps2_irq" + +Example: + +serio@c9000400 { + compatible = "snps,arc_ps2"; + reg = <0xc9000400 0x14>; + interrupts = <13>; + interrupt-names = "arc_ps2_irq"; +} diff --git a/drivers/input/serio/arc_ps2.c b/drivers/input/serio/arc_ps2.c index c52e3e589f72..3fb7727c8ea5 100644 --- a/drivers/input/serio/arc_ps2.c +++ b/drivers/input/serio/arc_ps2.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -259,10 +260,19 @@ static int arc_ps2_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id arc_ps2_match[] = { + { .compatible = "snps,arc_ps2" }, + { }, +}; +MODULE_DEVICE_TABLE(of, arc_ps2_match); +#endif + static struct platform_driver arc_ps2_driver = { .driver = { - .name = "arc_ps2", - .owner = THIS_MODULE, + .name = "arc_ps2", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(arc_ps2_match), }, .probe = arc_ps2_probe, .remove = arc_ps2_remove, -- cgit v1.2.3 From e6a90810559cc3755a5b1629d1fd0b914462f98c Mon Sep 17 00:00:00 2001 From: Bastian Hecht Date: Mon, 15 Apr 2013 09:31:00 -0700 Subject: Input: st1232 - add reset pin handling We add the possibility to hand over a GPIO number for the reset pin. This way we can remove existing board code that takes care of it and group this information properly in the platform data or in the device tree configuration. Signed-off-by: Bastian Hecht Acked-by: Laurent Pinchart Signed-off-by: Dmitry Torokhov --- .../bindings/input/touchscreen/sitronix-st1232.txt | 24 +++++++++++ drivers/input/touchscreen/st1232.c | 47 ++++++++++++++++++++-- include/linux/platform_data/st1232_pdata.h | 13 ++++++ 3 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/sitronix-st1232.txt create mode 100644 include/linux/platform_data/st1232_pdata.h (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/input/touchscreen/sitronix-st1232.txt b/Documentation/devicetree/bindings/input/touchscreen/sitronix-st1232.txt new file mode 100644 index 000000000000..64ad48b824a2 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/sitronix-st1232.txt @@ -0,0 +1,24 @@ +* Sitronix st1232 touchscreen controller + +Required properties: +- compatible: must be "sitronix,st1232" +- reg: I2C address of the chip +- interrupts: interrupt to which the chip is connected + +Optional properties: +- gpios: a phandle to the reset GPIO + +Example: + + i2c@00000000 { + /* ... */ + + touchscreen@55 { + compatible = "sitronix,st1232"; + reg = <0x55>; + interrupts = <2 0>; + gpios = <&gpio1 166 0>; + }; + + /* ... */ + }; diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index 75d8eb5ee609..1740a2496371 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -19,13 +19,16 @@ */ #include +#include #include #include #include #include +#include #include #include #include +#include #define ST1232_TS_NAME "st1232-ts" @@ -48,6 +51,7 @@ struct st1232_ts_data { struct input_dev *input_dev; struct st1232_ts_finger finger[MAX_FINGERS]; struct dev_pm_qos_request low_latency_req; + int reset_gpio; }; static int st1232_ts_read_data(struct st1232_ts_data *ts) @@ -139,10 +143,17 @@ end: return IRQ_HANDLED; } +static void st1232_ts_power(struct st1232_ts_data *ts, bool poweron) +{ + if (gpio_is_valid(ts->reset_gpio)) + gpio_direction_output(ts->reset_gpio, poweron); +} + static int st1232_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct st1232_ts_data *ts; + struct st1232_pdata *pdata = client->dev.platform_data; struct input_dev *input_dev; int error; @@ -167,6 +178,25 @@ static int st1232_ts_probe(struct i2c_client *client, ts->client = client; ts->input_dev = input_dev; + if (pdata) + ts->reset_gpio = pdata->reset_gpio; + else if (client->dev.of_node) + ts->reset_gpio = of_get_gpio(client->dev.of_node, 0); + else + ts->reset_gpio = -ENODEV; + + if (gpio_is_valid(ts->reset_gpio)) { + error = devm_gpio_request(&client->dev, ts->reset_gpio, NULL); + if (error) { + dev_err(&client->dev, + "Unable to request GPIO pin %d.\n", + ts->reset_gpio); + return error; + } + } + + st1232_ts_power(ts, true); + input_dev->name = "st1232-touchscreen"; input_dev->id.bustype = BUS_I2C; input_dev->dev.parent = &client->dev; @@ -203,7 +233,10 @@ static int st1232_ts_probe(struct i2c_client *client, static int st1232_ts_remove(struct i2c_client *client) { + struct st1232_ts_data *ts = i2c_get_clientdata(client); + device_init_wakeup(&client->dev, 0); + st1232_ts_power(ts, false); return 0; } @@ -212,11 +245,14 @@ static int st1232_ts_remove(struct i2c_client *client) static int st1232_ts_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); + struct st1232_ts_data *ts = i2c_get_clientdata(client); - if (device_may_wakeup(&client->dev)) + if (device_may_wakeup(&client->dev)) { enable_irq_wake(client->irq); - else + } else { disable_irq(client->irq); + st1232_ts_power(ts, false); + } return 0; } @@ -224,11 +260,14 @@ static int st1232_ts_suspend(struct device *dev) static int st1232_ts_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); + struct st1232_ts_data *ts = i2c_get_clientdata(client); - if (device_may_wakeup(&client->dev)) + if (device_may_wakeup(&client->dev)) { disable_irq_wake(client->irq); - else + } else { + st1232_ts_power(ts, true); enable_irq(client->irq); + } return 0; } diff --git a/include/linux/platform_data/st1232_pdata.h b/include/linux/platform_data/st1232_pdata.h new file mode 100644 index 000000000000..cac3e7b4c454 --- /dev/null +++ b/include/linux/platform_data/st1232_pdata.h @@ -0,0 +1,13 @@ +#ifndef _LINUX_ST1232_PDATA_H +#define _LINUX_ST1232_PDATA_H + +/* + * Optional platform data + * + * Use this if you want the driver to drive the reset pin. + */ +struct st1232_pdata { + int reset_gpio; +}; + +#endif -- cgit v1.2.3