Merge tag 'v5.4-rc5' into next
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Sun, 27 Oct 2019 18:00:19 +0000 (11:00 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Sun, 27 Oct 2019 18:00:19 +0000 (11:00 -0700)
Sync up with mainline.

20 files changed:
Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
Documentation/devicetree/bindings/input/fsl,mpr121-touchkey.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/input/input.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/input/keys.txt [deleted file]
Documentation/devicetree/bindings/input/mpr121-touchkey.txt [deleted file]
Documentation/devicetree/bindings/input/mtk-pmic-keys.txt
Documentation/devicetree/bindings/input/st,stpmic1-onkey.txt
drivers/input/input-poller.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/keyboard/adp5589-keys.c
drivers/input/keyboard/imx_sc_key.c [new file with mode: 0644]
drivers/input/keyboard/mpr121_touchkey.c
drivers/input/misc/hp_sdc_rtc.c
drivers/input/mouse/Kconfig
drivers/input/mouse/gpio_mouse.c
drivers/input/touchscreen/atmel_mxt_ts.c
drivers/input/touchscreen/pixcir_i2c_ts.c
include/linux/input.h
include/linux/platform_data/pixcir_i2c_ts.h [deleted file]

index c149fadc6f47f38f45d13edfd638d7e16c6c5af2..70c1a624486d2db0c7e6380ef1895aa6485bbf2a 100644 (file)
@@ -157,6 +157,15 @@ Required properties:
 Optional properties:
 - timeout-sec: contains the watchdog timeout in seconds.
 
+SCU key bindings based on SCU Message Protocol
+------------------------------------------------------------
+
+Required properties:
+- compatible: should be:
+              "fsl,imx8qxp-sc-key"
+              followed by "fsl,imx-sc-key";
+- linux,keycodes: See Documentation/devicetree/bindings/input/keys.txt
+
 Example (imx8qxp):
 -------------
 aliases {
@@ -220,6 +229,11 @@ firmware {
                        compatible = "fsl,imx8qxp-sc-rtc";
                };
 
+               scu_key: scu-key {
+                       compatible = "fsl,imx8qxp-sc-key", "fsl,imx-sc-key";
+                       linux,keycodes = <KEY_POWER>;
+               };
+
                watchdog {
                        compatible = "fsl,imx8qxp-sc-wdt", "fsl,imx-sc-wdt";
                        timeout-sec = <60>;
diff --git a/Documentation/devicetree/bindings/input/fsl,mpr121-touchkey.yaml b/Documentation/devicetree/bindings/input/fsl,mpr121-touchkey.yaml
new file mode 100644 (file)
index 0000000..5b37be0
--- /dev/null
@@ -0,0 +1,89 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/fsl,mpr121-touchkey.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale MPR121 capacitive touch sensor controller
+
+maintainers:
+  - Dmitry Torokhov <dmitry.torokhov@gmail.com>
+
+description: |
+  The MPR121 supports up to 12 completely independent electrodes/capacitance
+  sensing inputs in which 8 are multifunctional for LED driving and GPIO.
+  https://www.nxp.com/docs/en/data-sheet/MPR121.pdf
+
+allOf:
+  - $ref: input.yaml#
+
+anyOf:
+  - required: [ interrupts ]
+  - required: [ poll-interval ]
+
+properties:
+  compatible:
+    const: fsl,mpr121-touchkey
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  vdd-supply:
+    maxItems: 1
+
+  linux,keycodes:
+    minItems: 1
+    maxItems: 12
+
+  wakeup-source:
+    description: Use any event on keypad as wakeup event.
+    type: boolean
+
+required:
+  - compatible
+  - reg
+  - vdd-supply
+  - linux,keycodes
+
+examples:
+  - |
+    // Example with interrupts
+    #include "dt-bindings/input/input.h"
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        mpr121@5a {
+            compatible = "fsl,mpr121-touchkey";
+            reg = <0x5a>;
+            interrupt-parent = <&gpio1>;
+            interrupts = <28 2>;
+            autorepeat;
+            vdd-supply = <&ldo4_reg>;
+            linux,keycodes = <KEY_0>, <KEY_1>, <KEY_2>, <KEY_3>,
+                             <KEY_4>, <KEY_5>, <KEY_6>, <KEY_7>,
+                             <KEY_8>, <KEY_9>, <KEY_A>, <KEY_B>;
+        };
+    };
+
+  - |
+    // Example with polling
+    #include "dt-bindings/input/input.h"
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        mpr121@5a {
+            compatible = "fsl,mpr121-touchkey";
+            reg = <0x5a>;
+            poll-interval = <20>;
+            autorepeat;
+            vdd-supply = <&ldo4_reg>;
+            linux,keycodes = <KEY_0>, <KEY_1>, <KEY_2>, <KEY_3>,
+                             <KEY_4>, <KEY_5>, <KEY_6>, <KEY_7>,
+                             <KEY_8>, <KEY_9>, <KEY_A>, <KEY_B>;
+        };
+    };
diff --git a/Documentation/devicetree/bindings/input/input.yaml b/Documentation/devicetree/bindings/input/input.yaml
new file mode 100644 (file)
index 0000000..6d51904
--- /dev/null
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/input.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Common input schema binding
+
+maintainers:
+  - Dmitry Torokhov <dmitry.torokhov@gmail.com>
+
+properties:
+  autorepeat:
+    description: Enable autorepeat when key is pressed and held down.
+    type: boolean
+
+  linux,keycodes:
+    description:
+      Specifies an array of numeric keycode values to be used for reporting
+      button presses.
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32-array
+      - items:
+          minimum: 0
+          maximum: 0xff
+
+  poll-interval:
+    description: Poll interval time in milliseconds.
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  power-off-time-sec:
+    description:
+      Duration in seconds which the key should be kept pressed for device to
+      power off automatically. Device with key pressed shutdown feature can
+      specify this property.
+    $ref: /schemas/types.yaml#/definitions/uint32
diff --git a/Documentation/devicetree/bindings/input/keys.txt b/Documentation/devicetree/bindings/input/keys.txt
deleted file mode 100644 (file)
index f5a5ddd..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-General Keys Properties:
-
-Optional properties for Keys:
-- power-off-time-sec: Duration in seconds which the key should be kept
-       pressed for device to power off automatically. Device with key pressed
-       shutdown feature can specify this property.
-- linux,keycodes: Specifies the numeric keycode values to be used for
-       reporting key presses.
diff --git a/Documentation/devicetree/bindings/input/mpr121-touchkey.txt b/Documentation/devicetree/bindings/input/mpr121-touchkey.txt
deleted file mode 100644 (file)
index b7c61ee..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-* Freescale MPR121 Controllor
-
-Required Properties:
-- compatible:          Should be "fsl,mpr121-touchkey"
-- reg:                 The I2C slave address of the device.
-- interrupts:          The interrupt number to the cpu.
-- vdd-supply:          Phandle to the Vdd power supply.
-- linux,keycodes:      Specifies an array of numeric keycode values to
-                       be used for reporting button presses. The array can
-                       contain up to 12 entries.
-
-Optional Properties:
-- wakeup-source:       Use any event on keypad as wakeup event.
-- autorepeat:          Enable autorepeat feature.
-
-Example:
-
-#include "dt-bindings/input/input.h"
-
-       touchkey: mpr121@5a {
-               compatible = "fsl,mpr121-touchkey";
-               reg = <0x5a>;
-               interrupt-parent = <&gpio1>;
-               interrupts = <28 2>;
-               autorepeat;
-               vdd-supply = <&ldo4_reg>;
-               linux,keycodes = <KEY_0>, <KEY_1>, <KEY_2>, <KEY_3>,
-                               <KEY_4> <KEY_5>, <KEY_6>, <KEY_7>,
-                               <KEY_8>, <KEY_9>, <KEY_A>, <KEY_B>;
-       };
index 2888d07c2ef0629e9a092619b7f1f9dc04d2d890..535d92885372b0ec8138a2ff1896953656bbb0b9 100644 (file)
@@ -10,13 +10,13 @@ Documentation/devicetree/bindings/mfd/mt6397.txt
 
 Required properties:
 - compatible: "mediatek,mt6397-keys" or "mediatek,mt6323-keys"
-- linux,keycodes: See Documentation/devicetree/bindings/input/keys.txt
+- linux,keycodes: See Documentation/devicetree/bindings/input/input.yaml
 
 Optional Properties:
 - wakeup-source: See Documentation/devicetree/bindings/power/wakeup-source.txt
 - mediatek,long-press-mode: Long press key shutdown setting, 1 for
        pwrkey only, 2 for pwrkey/homekey together, others for disabled.
-- power-off-time-sec: See Documentation/devicetree/bindings/input/keys.txt
+- power-off-time-sec: See Documentation/devicetree/bindings/input/input.yaml
 
 Example:
 
index 4494613ae7ad5c04c5e44fc38a0bf622a4153d13..eb8e83736c02e29120f80a6085c9193452623b6f 100644 (file)
@@ -15,7 +15,7 @@ Optional properties:
 - st,onkey-pu-inactive: onkey pull up is not active
 - power-off-time-sec: Duration in seconds which the key should be kept
         pressed for device to power off automatically (from 1 to 16 seconds).
-        see See Documentation/devicetree/bindings/input/keys.txt
+        see See Documentation/devicetree/bindings/input/input.yaml
 
 Example:
 
index 1b3d28964bb23db3508b5f977e936170bd1fbc95..7d6b4e8879f11d84417c59ea4b1ab078de959902 100644 (file)
@@ -123,6 +123,15 @@ void input_set_max_poll_interval(struct input_dev *dev, unsigned int interval)
 }
 EXPORT_SYMBOL(input_set_max_poll_interval);
 
+int input_get_poll_interval(struct input_dev *dev)
+{
+       if (!dev->poller)
+               return -EINVAL;
+
+       return dev->poller->poll_interval;
+}
+EXPORT_SYMBOL(input_get_poll_interval);
+
 /* SYSFS interface */
 
 static ssize_t input_dev_get_poll_interval(struct device *dev,
index 8911bc2ec42a87fb0dd7f6d00712f309aae88f5f..04ad3715c0d07f36d166425e1b33dac345b999d0 100644 (file)
@@ -469,6 +469,16 @@ config KEYBOARD_IMX
          To compile this driver as a module, choose M here: the
          module will be called imx_keypad.
 
+config KEYBOARD_IMX_SC_KEY
+       tristate "IMX SCU Key Driver"
+       depends on IMX_SCU
+       help
+         This is the system controller key driver for NXP i.MX SoCs with
+         system controller inside.
+
+         To compile this driver as a module, choose M here: the
+         module will be called imx_sc_key.
+
 config KEYBOARD_NEWTON
        tristate "Newton keyboard"
        select SERIO
index 9510325c0c5d666546b41126675282f34edeafa0..f5b17524adf2d882a31320e728e751f15d408f91 100644 (file)
@@ -29,6 +29,7 @@ obj-$(CONFIG_KEYBOARD_HIL)            += hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)         += hilkbd.o
 obj-$(CONFIG_KEYBOARD_IPAQ_MICRO)      += ipaq-micro-keys.o
 obj-$(CONFIG_KEYBOARD_IMX)             += imx_keypad.o
+obj-$(CONFIG_KEYBOARD_IMX_SC_KEY)      += imx_sc_key.o
 obj-$(CONFIG_KEYBOARD_HP6XX)           += jornada680_kbd.o
 obj-$(CONFIG_KEYBOARD_HP7XX)           += jornada720_kbd.o
 obj-$(CONFIG_KEYBOARD_LKKBD)           += lkkbd.o
index 4f96a4a99e5b867be06c10a80234166f2451f927..e7d58e7f0257c989c43b8d034af5efb77639ca80 100644 (file)
@@ -857,70 +857,35 @@ static void adp5589_report_switch_state(struct adp5589_kpad *kpad)
        input_sync(kpad->input);
 }
 
-static int adp5589_probe(struct i2c_client *client,
-                        const struct i2c_device_id *id)
+static int adp5589_keypad_add(struct adp5589_kpad *kpad, unsigned int revid)
 {
-       struct adp5589_kpad *kpad;
+       struct i2c_client *client = kpad->client;
        const struct adp5589_kpad_platform_data *pdata =
                dev_get_platdata(&client->dev);
        struct input_dev *input;
-       unsigned int revid;
-       int ret, i;
+       unsigned int i;
        int error;
 
-       if (!i2c_check_functionality(client->adapter,
-                                    I2C_FUNC_SMBUS_BYTE_DATA)) {
-               dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
-               return -EIO;
-       }
-
-       if (!pdata) {
-               dev_err(&client->dev, "no platform data?\n");
-               return -EINVAL;
-       }
-
-       kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
-       if (!kpad)
-               return -ENOMEM;
-
-       switch (id->driver_data) {
-       case ADP5585_02:
-               kpad->support_row5 = true;
-               /* fall through */
-       case ADP5585_01:
-               kpad->is_adp5585 = true;
-               kpad->var = &const_adp5585;
-               break;
-       case ADP5589:
-               kpad->support_row5 = true;
-               kpad->var = &const_adp5589;
-               break;
-       }
-
        if (!((pdata->keypad_en_mask & kpad->var->row_mask) &&
                        (pdata->keypad_en_mask >> kpad->var->col_shift)) ||
                        !pdata->keymap) {
                dev_err(&client->dev, "no rows, cols or keymap from pdata\n");
-               error = -EINVAL;
-               goto err_free_mem;
+               return -EINVAL;
        }
 
        if (pdata->keymapsize != kpad->var->keymapsize) {
                dev_err(&client->dev, "invalid keymapsize\n");
-               error = -EINVAL;
-               goto err_free_mem;
+               return -EINVAL;
        }
 
        if (!pdata->gpimap && pdata->gpimapsize) {
                dev_err(&client->dev, "invalid gpimap from pdata\n");
-               error = -EINVAL;
-               goto err_free_mem;
+               return -EINVAL;
        }
 
        if (pdata->gpimapsize > kpad->var->gpimapsize_max) {
                dev_err(&client->dev, "invalid gpimapsize\n");
-               error = -EINVAL;
-               goto err_free_mem;
+               return -EINVAL;
        }
 
        for (i = 0; i < pdata->gpimapsize; i++) {
@@ -929,41 +894,27 @@ static int adp5589_probe(struct i2c_client *client,
                if (pin < kpad->var->gpi_pin_base ||
                                pin > kpad->var->gpi_pin_end) {
                        dev_err(&client->dev, "invalid gpi pin data\n");
-                       error = -EINVAL;
-                       goto err_free_mem;
+                       return -EINVAL;
                }
 
                if ((1 << (pin - kpad->var->gpi_pin_row_base)) &
                                pdata->keypad_en_mask) {
                        dev_err(&client->dev, "invalid gpi row/col data\n");
-                       error = -EINVAL;
-                       goto err_free_mem;
+                       return -EINVAL;
                }
        }
 
        if (!client->irq) {
                dev_err(&client->dev, "no IRQ?\n");
-               error = -EINVAL;
-               goto err_free_mem;
+               return -EINVAL;
        }
 
        input = input_allocate_device();
-       if (!input) {
-               error = -ENOMEM;
-               goto err_free_mem;
-       }
+       if (!input)
+               return -ENOMEM;
 
-       kpad->client = client;
        kpad->input = input;
 
-       ret = adp5589_read(client, ADP5589_5_ID);
-       if (ret < 0) {
-               error = ret;
-               goto err_free_input;
-       }
-
-       revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK;
-
        input->name = client->name;
        input->phys = "adp5589-keys/input0";
        input->dev.parent = &client->dev;
@@ -1015,30 +966,99 @@ static int adp5589_probe(struct i2c_client *client,
                goto err_unreg_dev;
        }
 
+       device_init_wakeup(&client->dev, 1);
+
+       return 0;
+
+err_unreg_dev:
+       input_unregister_device(input);
+       input = NULL;
+err_free_input:
+       input_free_device(input);
+
+       return error;
+}
+
+static void adp5589_keypad_remove(struct adp5589_kpad *kpad)
+{
+       if (kpad->input) {
+               free_irq(kpad->client->irq, kpad);
+               input_unregister_device(kpad->input);
+       }
+}
+
+static int adp5589_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       struct adp5589_kpad *kpad;
+       const struct adp5589_kpad_platform_data *pdata =
+               dev_get_platdata(&client->dev);
+       unsigned int revid;
+       int error, ret;
+
+       if (!i2c_check_functionality(client->adapter,
+                                    I2C_FUNC_SMBUS_BYTE_DATA)) {
+               dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
+               return -EIO;
+       }
+
+       if (!pdata) {
+               dev_err(&client->dev, "no platform data?\n");
+               return -EINVAL;
+       }
+
+       kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
+       if (!kpad)
+               return -ENOMEM;
+
+       kpad->client = client;
+
+       switch (id->driver_data) {
+       case ADP5585_02:
+               kpad->support_row5 = true;
+               /* fall through */
+       case ADP5585_01:
+               kpad->is_adp5585 = true;
+               kpad->var = &const_adp5585;
+               break;
+       case ADP5589:
+               kpad->support_row5 = true;
+               kpad->var = &const_adp5589;
+               break;
+       }
+
+       ret = adp5589_read(client, ADP5589_5_ID);
+       if (ret < 0) {
+               error = ret;
+               goto err_free_mem;
+       }
+
+       revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK;
+
+       if (pdata->keymapsize) {
+               error = adp5589_keypad_add(kpad, revid);
+               if (error)
+                       goto err_free_mem;
+       }
+
        error = adp5589_setup(kpad);
        if (error)
-               goto err_free_irq;
+               goto err_keypad_remove;
 
        if (kpad->gpimapsize)
                adp5589_report_switch_state(kpad);
 
        error = adp5589_gpio_add(kpad);
        if (error)
-               goto err_free_irq;
+               goto err_keypad_remove;
 
-       device_init_wakeup(&client->dev, 1);
        i2c_set_clientdata(client, kpad);
 
        dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq);
        return 0;
 
-err_free_irq:
-       free_irq(client->irq, kpad);
-err_unreg_dev:
-       input_unregister_device(input);
-       input = NULL;
-err_free_input:
-       input_free_device(input);
+err_keypad_remove:
+       adp5589_keypad_remove(kpad);
 err_free_mem:
        kfree(kpad);
 
@@ -1050,8 +1070,7 @@ static int adp5589_remove(struct i2c_client *client)
        struct adp5589_kpad *kpad = i2c_get_clientdata(client);
 
        adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0);
-       free_irq(client->irq, kpad);
-       input_unregister_device(kpad->input);
+       adp5589_keypad_remove(kpad);
        adp5589_gpio_remove(kpad);
        kfree(kpad);
 
@@ -1064,6 +1083,9 @@ static int adp5589_suspend(struct device *dev)
        struct adp5589_kpad *kpad = dev_get_drvdata(dev);
        struct i2c_client *client = kpad->client;
 
+       if (!kpad->input)
+               return 0;
+
        disable_irq(client->irq);
 
        if (device_may_wakeup(&client->dev))
@@ -1077,6 +1099,9 @@ static int adp5589_resume(struct device *dev)
        struct adp5589_kpad *kpad = dev_get_drvdata(dev);
        struct i2c_client *client = kpad->client;
 
+       if (!kpad->input)
+               return 0;
+
        if (device_may_wakeup(&client->dev))
                disable_irq_wake(client->irq);
 
diff --git a/drivers/input/keyboard/imx_sc_key.c b/drivers/input/keyboard/imx_sc_key.c
new file mode 100644 (file)
index 0000000..dd57daa
--- /dev/null
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 NXP.
+ */
+
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/firmware/imx/sci.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+
+#define DEBOUNCE_TIME                          30
+#define REPEAT_INTERVAL                                60
+
+#define SC_IRQ_BUTTON                          1
+#define SC_IRQ_GROUP_WAKE                      3
+
+#define IMX_SC_MISC_FUNC_GET_BUTTON_STATUS     18
+
+struct imx_key_drv_data {
+       u32 keycode;
+       bool keystate;  /* true: pressed, false: released */
+       struct delayed_work check_work;
+       struct input_dev *input;
+       struct imx_sc_ipc *key_ipc_handle;
+       struct notifier_block key_notifier;
+};
+
+struct imx_sc_msg_key {
+       struct imx_sc_rpc_msg hdr;
+       u8 state;
+};
+
+static int imx_sc_key_notify(struct notifier_block *nb,
+                            unsigned long event, void *group)
+{
+       struct imx_key_drv_data *priv =
+                                container_of(nb,
+                                             struct imx_key_drv_data,
+                                             key_notifier);
+
+       if ((event & SC_IRQ_BUTTON) && (*(u8 *)group == SC_IRQ_GROUP_WAKE)) {
+               schedule_delayed_work(&priv->check_work,
+                                     msecs_to_jiffies(DEBOUNCE_TIME));
+               pm_wakeup_event(priv->input->dev.parent, 0);
+       }
+
+       return 0;
+}
+
+static void imx_sc_check_for_events(struct work_struct *work)
+{
+       struct imx_key_drv_data *priv =
+                                container_of(work,
+                                             struct imx_key_drv_data,
+                                             check_work.work);
+       struct input_dev *input = priv->input;
+       struct imx_sc_msg_key msg;
+       struct imx_sc_rpc_msg *hdr = &msg.hdr;
+       bool state;
+       int error;
+
+       hdr->ver = IMX_SC_RPC_VERSION;
+       hdr->svc = IMX_SC_RPC_SVC_MISC;
+       hdr->func = IMX_SC_MISC_FUNC_GET_BUTTON_STATUS;
+       hdr->size = 1;
+
+       error = imx_scu_call_rpc(priv->key_ipc_handle, &msg, true);
+       if (error) {
+               dev_err(&input->dev, "read imx sc key failed, error %d\n", error);
+               return;
+       }
+
+       state = (bool)msg.state;
+
+       if (state ^ priv->keystate) {
+               priv->keystate = state;
+               input_event(input, EV_KEY, priv->keycode, state);
+               input_sync(input);
+               if (!priv->keystate)
+                       pm_relax(priv->input->dev.parent);
+       }
+
+       if (state)
+               schedule_delayed_work(&priv->check_work,
+                                     msecs_to_jiffies(REPEAT_INTERVAL));
+}
+
+static int imx_sc_key_probe(struct platform_device *pdev)
+{
+       struct imx_key_drv_data *priv;
+       struct input_dev *input;
+       int error;
+
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       error = imx_scu_get_handle(&priv->key_ipc_handle);
+       if (error)
+               return error;
+
+       if (device_property_read_u32(&pdev->dev, "linux,keycodes",
+                                    &priv->keycode)) {
+               dev_err(&pdev->dev, "missing linux,keycodes property\n");
+               return -EINVAL;
+       }
+
+       INIT_DELAYED_WORK(&priv->check_work, imx_sc_check_for_events);
+
+       input = devm_input_allocate_device(&pdev->dev);
+       if (!input) {
+               dev_err(&pdev->dev, "failed to allocate the input device\n");
+               return -ENOMEM;
+       }
+
+       input->name = pdev->name;
+       input->phys = "imx-sc-key/input0";
+       input->id.bustype = BUS_HOST;
+
+       input_set_capability(input, EV_KEY, priv->keycode);
+
+       error = input_register_device(input);
+       if (error) {
+               dev_err(&pdev->dev, "failed to register input device\n");
+               return error;
+       }
+
+       priv->input = input;
+       platform_set_drvdata(pdev, priv);
+
+       error = imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON,
+                                        true);
+       if (error) {
+               dev_err(&pdev->dev, "failed to enable scu group irq\n");
+               return error;
+       }
+
+       priv->key_notifier.notifier_call = imx_sc_key_notify;
+       error = imx_scu_irq_register_notifier(&priv->key_notifier);
+       if (error) {
+               imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON,
+                                        false);
+               dev_err(&pdev->dev, "failed to register scu notifier\n");
+               return error;
+       }
+
+       return 0;
+}
+
+static int imx_sc_key_remove(struct platform_device *pdev)
+{
+       struct imx_key_drv_data *priv = platform_get_drvdata(pdev);
+
+       imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON, false);
+       imx_scu_irq_unregister_notifier(&priv->key_notifier);
+       cancel_delayed_work_sync(&priv->check_work);
+
+       return 0;
+}
+
+static const struct of_device_id imx_sc_key_ids[] = {
+       { .compatible = "fsl,imx-sc-key" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_sc_key_ids);
+
+static struct platform_driver imx_sc_key_driver = {
+       .driver = {
+               .name = "imx-sc-key",
+               .of_match_table = imx_sc_key_ids,
+       },
+       .probe = imx_sc_key_probe,
+       .remove = imx_sc_key_remove,
+};
+module_platform_driver(imx_sc_key_driver);
+
+MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>");
+MODULE_DESCRIPTION("i.MX System Controller Key Driver");
+MODULE_LICENSE("GPL v2");
index ee80de44ce3f6a49460655989027405c38b30a13..40d6e5087cdef060acce22fdd4aa2a5d082cf230 100644 (file)
@@ -54,6 +54,9 @@
 /* MPR121 has 12 keys */
 #define MPR121_MAX_KEY_COUNT           12
 
+#define MPR121_MIN_POLL_INTERVAL       10
+#define MPR121_MAX_POLL_INTERVAL       200
+
 struct mpr121_touchkey {
        struct i2c_client       *client;
        struct input_dev        *input_dev;
@@ -115,11 +118,11 @@ static struct regulator *mpr121_vdd_supply_init(struct device *dev)
        return vdd_supply;
 }
 
-static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
+static void mpr_touchkey_report(struct input_dev *dev)
 {
-       struct mpr121_touchkey *mpr121 = dev_id;
-       struct i2c_client *client = mpr121->client;
+       struct mpr121_touchkey *mpr121 = input_get_drvdata(dev);
        struct input_dev *input = mpr121->input_dev;
+       struct i2c_client *client = mpr121->client;
        unsigned long bit_changed;
        unsigned int key_num;
        int reg;
@@ -127,14 +130,14 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
        reg = i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_1_ADDR);
        if (reg < 0) {
                dev_err(&client->dev, "i2c read error [%d]\n", reg);
-               goto out;
+               return;
        }
 
        reg <<= 8;
        reg |= i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_0_ADDR);
        if (reg < 0) {
                dev_err(&client->dev, "i2c read error [%d]\n", reg);
-               goto out;
+               return;
        }
 
        reg &= TOUCH_STATUS_MASK;
@@ -155,8 +158,14 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
 
        }
        input_sync(input);
+}
+
+static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
+{
+       struct mpr121_touchkey *mpr121 = dev_id;
+
+       mpr_touchkey_report(mpr121->input_dev);
 
-out:
        return IRQ_HANDLED;
 }
 
@@ -229,14 +238,10 @@ static int mpr_touchkey_probe(struct i2c_client *client,
        int vdd_uv;
        struct mpr121_touchkey *mpr121;
        struct input_dev *input_dev;
+       u32 poll_interval = 0;
        int error;
        int i;
 
-       if (!client->irq) {
-               dev_err(dev, "irq number should not be zero\n");
-               return -EINVAL;
-       }
-
        vdd_supply = mpr121_vdd_supply_init(dev);
        if (IS_ERR(vdd_supply))
                return PTR_ERR(vdd_supply);
@@ -274,6 +279,7 @@ static int mpr_touchkey_probe(struct i2c_client *client,
        if (device_property_read_bool(dev, "autorepeat"))
                __set_bit(EV_REP, input_dev->evbit);
        input_set_capability(input_dev, EV_MSC, MSC_SCAN);
+       input_set_drvdata(input_dev, mpr121);
 
        input_dev->keycode = mpr121->keycodes;
        input_dev->keycodesize = sizeof(mpr121->keycodes[0]);
@@ -288,13 +294,40 @@ static int mpr_touchkey_probe(struct i2c_client *client,
                return error;
        }
 
-       error = devm_request_threaded_irq(dev, client->irq, NULL,
-                                         mpr_touchkey_interrupt,
-                                         IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-                                         dev->driver->name, mpr121);
-       if (error) {
-               dev_err(dev, "Failed to register interrupt\n");
-               return error;
+       device_property_read_u32(dev, "poll-interval", &poll_interval);
+
+       if (client->irq) {
+               error = devm_request_threaded_irq(dev, client->irq, NULL,
+                                                 mpr_touchkey_interrupt,
+                                                 IRQF_TRIGGER_FALLING |
+                                                 IRQF_ONESHOT,
+                                                 dev->driver->name, mpr121);
+               if (error) {
+                       dev_err(dev, "Failed to register interrupt\n");
+                       return error;
+               }
+       } else if (poll_interval) {
+               if (poll_interval < MPR121_MIN_POLL_INTERVAL)
+                       return -EINVAL;
+
+               if (poll_interval > MPR121_MAX_POLL_INTERVAL)
+                       return -EINVAL;
+
+               error = input_setup_polling(input_dev, mpr_touchkey_report);
+               if (error) {
+                       dev_err(dev, "Failed to setup polling\n");
+                       return error;
+               }
+
+               input_set_poll_interval(input_dev, poll_interval);
+               input_set_min_poll_interval(input_dev,
+                                           MPR121_MIN_POLL_INTERVAL);
+               input_set_max_poll_interval(input_dev,
+                                           MPR121_MAX_POLL_INTERVAL);
+       } else {
+               dev_err(dev,
+                       "invalid IRQ number and polling not configured\n");
+               return -EINVAL;
        }
 
        error = input_register_device(input_dev);
index abca895a61563c1311bbc60b5134a2cd69c51e02..199bc17ddb1df149cc5c65038ff3ba3440d58c2c 100644 (file)
@@ -53,28 +53,10 @@ MODULE_LICENSE("Dual BSD/GPL");
 
 #define RTC_VERSION "1.10d"
 
-static DEFINE_MUTEX(hp_sdc_rtc_mutex);
 static unsigned long epoch = 2000;
 
 static struct semaphore i8042tregs;
 
-static hp_sdc_irqhook hp_sdc_rtc_isr;
-
-static struct fasync_struct *hp_sdc_rtc_async_queue;
-
-static DECLARE_WAIT_QUEUE_HEAD(hp_sdc_rtc_wait);
-
-static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf,
-                              size_t count, loff_t *ppos);
-
-static long hp_sdc_rtc_unlocked_ioctl(struct file *file,
-                                     unsigned int cmd, unsigned long arg);
-
-static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait);
-
-static int hp_sdc_rtc_open(struct inode *inode, struct file *file);
-static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on);
-
 static void hp_sdc_rtc_isr (int irq, void *dev_id, 
                            uint8_t status, uint8_t data) 
 {
@@ -283,151 +265,6 @@ static inline int hp_sdc_rtc_read_ct(struct timespec64 *res) {
        return 0;
 }
 
-
-#if 0 /* not used yet */
-/* Set the i8042 real-time clock */
-static int hp_sdc_rtc_set_rt (struct timeval *setto)
-{
-       uint32_t tenms;
-       unsigned int days;
-       hp_sdc_transaction t;
-       uint8_t tseq[11] = {
-               HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
-               HP_SDC_CMD_SET_RTMS, 3, 0, 0, 0,
-               HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
-               HP_SDC_CMD_SET_RTD, 2, 0, 0 
-       };
-
-       t.endidx = 10;
-
-       if (0xffff < setto->tv_sec / 86400) return -1;
-       days = setto->tv_sec / 86400;
-       if (0xffff < setto->tv_usec / 1000000 / 86400) return -1;
-       days += ((setto->tv_sec % 86400) + setto->tv_usec / 1000000) / 86400;
-       if (days > 0xffff) return -1;
-
-       if (0xffffff < setto->tv_sec) return -1;
-       tenms  = setto->tv_sec * 100;
-       if (0xffffff < setto->tv_usec / 10000) return -1;
-       tenms += setto->tv_usec / 10000;
-       if (tenms > 0xffffff) return -1;
-
-       tseq[3] = (uint8_t)(tenms & 0xff);
-       tseq[4] = (uint8_t)((tenms >> 8)  & 0xff);
-       tseq[5] = (uint8_t)((tenms >> 16) & 0xff);
-
-       tseq[9] = (uint8_t)(days & 0xff);
-       tseq[10] = (uint8_t)((days >> 8) & 0xff);
-
-       t.seq = tseq;
-
-       if (hp_sdc_enqueue_transaction(&t)) return -1;
-       return 0;
-}
-
-/* Set the i8042 fast handshake timer */
-static int hp_sdc_rtc_set_fhs (struct timeval *setto)
-{
-       uint32_t tenms;
-       hp_sdc_transaction t;
-       uint8_t tseq[5] = {
-               HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
-               HP_SDC_CMD_SET_FHS, 2, 0, 0
-       };
-
-       t.endidx = 4;
-
-       if (0xffff < setto->tv_sec) return -1;
-       tenms  = setto->tv_sec * 100;
-       if (0xffff < setto->tv_usec / 10000) return -1;
-       tenms += setto->tv_usec / 10000;
-       if (tenms > 0xffff) return -1;
-
-       tseq[3] = (uint8_t)(tenms & 0xff);
-       tseq[4] = (uint8_t)((tenms >> 8)  & 0xff);
-
-       t.seq = tseq;
-
-       if (hp_sdc_enqueue_transaction(&t)) return -1;
-       return 0;
-}
-
-
-/* Set the i8042 match timer (a.k.a. alarm) */
-#define hp_sdc_rtc_set_mt (setto) \
-       hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_MT)
-
-/* Set the i8042 delay timer */
-#define hp_sdc_rtc_set_dt (setto) \
-       hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_DT)
-
-/* Set the i8042 cycle timer (a.k.a. periodic) */
-#define hp_sdc_rtc_set_ct (setto) \
-       hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_CT)
-
-/* Set one of the i8042 3-byte wide timers */
-static int hp_sdc_rtc_set_i8042timer (struct timeval *setto, uint8_t setcmd)
-{
-       uint32_t tenms;
-       hp_sdc_transaction t;
-       uint8_t tseq[6] = {
-               HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
-               0, 3, 0, 0, 0
-       };
-
-       t.endidx = 6;
-
-       if (0xffffff < setto->tv_sec) return -1;
-       tenms  = setto->tv_sec * 100;
-       if (0xffffff < setto->tv_usec / 10000) return -1;
-       tenms += setto->tv_usec / 10000;
-       if (tenms > 0xffffff) return -1;
-
-       tseq[1] = setcmd;
-       tseq[3] = (uint8_t)(tenms & 0xff);
-       tseq[4] = (uint8_t)((tenms >> 8)  & 0xff);
-       tseq[5] = (uint8_t)((tenms >> 16)  & 0xff);
-
-       t.seq =                 tseq;
-
-       if (hp_sdc_enqueue_transaction(&t)) { 
-               return -1;
-       }
-       return 0;
-}
-#endif
-
-static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf,
-                              size_t count, loff_t *ppos) {
-       ssize_t retval;
-
-        if (count < sizeof(unsigned long))
-                return -EINVAL;
-
-       retval = put_user(68, (unsigned long __user *)buf);
-       return retval;
-}
-
-static __poll_t hp_sdc_rtc_poll(struct file *file, poll_table *wait)
-{
-        unsigned long l;
-
-       l = 0;
-        if (l != 0)
-                return EPOLLIN | EPOLLRDNORM;
-        return 0;
-}
-
-static int hp_sdc_rtc_open(struct inode *inode, struct file *file)
-{
-        return 0;
-}
-
-static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on)
-{
-        return fasync_helper (fd, filp, on, &hp_sdc_rtc_async_queue);
-}
-
 static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v)
 {
 #define YN(bit) ("no")
@@ -507,182 +344,6 @@ static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v)
 #undef NY
 }
 
-static int hp_sdc_rtc_ioctl(struct file *file, 
-                           unsigned int cmd, unsigned long arg)
-{
-#if 1
-       return -EINVAL;
-#else
-       
-        struct rtc_time wtime; 
-       struct timeval ttime;
-       int use_wtime = 0;
-
-       /* This needs major work. */
-
-        switch (cmd) {
-
-        case RTC_AIE_OFF:       /* Mask alarm int. enab. bit    */
-        case RTC_AIE_ON:        /* Allow alarm interrupts.      */
-       case RTC_PIE_OFF:       /* Mask periodic int. enab. bit */
-        case RTC_PIE_ON:        /* Allow periodic ints          */
-        case RTC_UIE_ON:        /* Allow ints for RTC updates.  */
-        case RTC_UIE_OFF:       /* Allow ints for RTC updates.  */
-        {
-               /* We cannot mask individual user timers and we
-                  cannot tell them apart when they occur, so it 
-                  would be disingenuous to succeed these IOCTLs */
-               return -EINVAL;
-        }
-        case RTC_ALM_READ:      /* Read the present alarm time */
-        {
-               if (hp_sdc_rtc_read_mt(&ttime)) return -EFAULT;
-               if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT;
-
-               wtime.tm_hour = ttime.tv_sec / 3600;  ttime.tv_sec %= 3600;
-               wtime.tm_min  = ttime.tv_sec / 60;    ttime.tv_sec %= 60;
-               wtime.tm_sec  = ttime.tv_sec;
-                
-               break;
-        }
-        case RTC_IRQP_READ:     /* Read the periodic IRQ rate.  */
-        {
-                return put_user(hp_sdc_rtc_freq, (unsigned long *)arg);
-        }
-        case RTC_IRQP_SET:      /* Set periodic IRQ rate.       */
-        {
-                /* 
-                 * The max we can do is 100Hz.
-                */
-
-                if ((arg < 1) || (arg > 100)) return -EINVAL;
-               ttime.tv_sec = 0;
-               ttime.tv_usec = 1000000 / arg;
-               if (hp_sdc_rtc_set_ct(&ttime)) return -EFAULT;
-               hp_sdc_rtc_freq = arg;
-                return 0;
-        }
-        case RTC_ALM_SET:       /* Store a time into the alarm */
-        {
-                /*
-                 * This expects a struct hp_sdc_rtc_time. Writing 0xff means
-                 * "don't care" or "match all" for PC timers.  The HP SDC
-                * does not support that perk, but it could be emulated fairly
-                * easily.  Only the tm_hour, tm_min and tm_sec are used.
-                * We could do it with 10ms accuracy with the HP SDC, if the 
-                * rtc interface left us a way to do that.
-                 */
-                struct hp_sdc_rtc_time alm_tm;
-
-                if (copy_from_user(&alm_tm, (struct hp_sdc_rtc_time*)arg,
-                                   sizeof(struct hp_sdc_rtc_time)))
-                       return -EFAULT;
-
-                if (alm_tm.tm_hour > 23) return -EINVAL;
-               if (alm_tm.tm_min  > 59) return -EINVAL;
-               if (alm_tm.tm_sec  > 59) return -EINVAL;  
-
-               ttime.sec = alm_tm.tm_hour * 3600 + 
-                 alm_tm.tm_min * 60 + alm_tm.tm_sec;
-               ttime.usec = 0;
-               if (hp_sdc_rtc_set_mt(&ttime)) return -EFAULT;
-                return 0;
-        }
-        case RTC_RD_TIME:       /* Read the time/date from RTC  */
-        {
-               if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT;
-                break;
-        }
-        case RTC_SET_TIME:      /* Set the RTC */
-        {
-                struct rtc_time hp_sdc_rtc_tm;
-                unsigned char mon, day, hrs, min, sec, leap_yr;
-                unsigned int yrs;
-
-                if (!capable(CAP_SYS_TIME))
-                        return -EACCES;
-               if (copy_from_user(&hp_sdc_rtc_tm, (struct rtc_time *)arg,
-                                   sizeof(struct rtc_time)))
-                        return -EFAULT;
-
-                yrs = hp_sdc_rtc_tm.tm_year + 1900;
-                mon = hp_sdc_rtc_tm.tm_mon + 1;   /* tm_mon starts at zero */
-                day = hp_sdc_rtc_tm.tm_mday;
-                hrs = hp_sdc_rtc_tm.tm_hour;
-                min = hp_sdc_rtc_tm.tm_min;
-                sec = hp_sdc_rtc_tm.tm_sec;
-
-                if (yrs < 1970)
-                        return -EINVAL;
-
-                leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
-
-                if ((mon > 12) || (day == 0))
-                        return -EINVAL;
-                if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
-                        return -EINVAL;
-               if ((hrs >= 24) || (min >= 60) || (sec >= 60))
-                        return -EINVAL;
-
-                if ((yrs -= eH) > 255)    /* They are unsigned */
-                        return -EINVAL;
-
-
-                return 0;
-        }
-        case RTC_EPOCH_READ:    /* Read the epoch.      */
-        {
-                return put_user (epoch, (unsigned long *)arg);
-        }
-        case RTC_EPOCH_SET:     /* Set the epoch.       */
-        {
-                /* 
-                 * There were no RTC clocks before 1900.
-                 */
-                if (arg < 1900)
-                 return -EINVAL;
-               if (!capable(CAP_SYS_TIME))
-                 return -EACCES;
-               
-                epoch = arg;
-                return 0;
-        }
-        default:
-                return -EINVAL;
-        }
-        return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
-#endif
-}
-
-static long hp_sdc_rtc_unlocked_ioctl(struct file *file,
-                                     unsigned int cmd, unsigned long arg)
-{
-       int ret;
-
-       mutex_lock(&hp_sdc_rtc_mutex);
-       ret = hp_sdc_rtc_ioctl(file, cmd, arg);
-       mutex_unlock(&hp_sdc_rtc_mutex);
-
-       return ret;
-}
-
-
-static const struct file_operations hp_sdc_rtc_fops = {
-        .owner =               THIS_MODULE,
-        .llseek =              no_llseek,
-        .read =                        hp_sdc_rtc_read,
-        .poll =                        hp_sdc_rtc_poll,
-        .unlocked_ioctl =      hp_sdc_rtc_unlocked_ioctl,
-        .open =                        hp_sdc_rtc_open,
-        .fasync =              hp_sdc_rtc_fasync,
-};
-
-static struct miscdevice hp_sdc_rtc_dev = {
-        .minor =       RTC_MINOR,
-        .name =                "rtc_HIL",
-        .fops =                &hp_sdc_rtc_fops
-};
-
 static int __init hp_sdc_rtc_init(void)
 {
        int ret;
@@ -696,8 +357,6 @@ static int __init hp_sdc_rtc_init(void)
 
        if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr)))
                return ret;
-       if (misc_register(&hp_sdc_rtc_dev) != 0)
-               printk(KERN_INFO "Could not register misc. dev for i8042 rtc\n");
 
         proc_create_single("driver/rtc", 0, NULL, hp_sdc_rtc_proc_show);
 
@@ -710,7 +369,6 @@ static int __init hp_sdc_rtc_init(void)
 static void __exit hp_sdc_rtc_exit(void)
 {
        remove_proc_entry ("driver/rtc", NULL);
-        misc_deregister(&hp_sdc_rtc_dev);
        hp_sdc_release_timer_irq(hp_sdc_rtc_isr);
         printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support unloaded\n");
 }
index 652c38e3c0b5f2941babcb4aafe60aedf38671a2..bf738d3b7fe41610a59a8c1d36ebc0ff0cf6ccb9 100644 (file)
@@ -381,7 +381,6 @@ config MOUSE_VSXXXAA
 config MOUSE_GPIO
        tristate "GPIO mouse"
        depends on GPIOLIB || COMPILE_TEST
-       select INPUT_POLLDEV
        help
          This driver simulates a mouse on GPIO lines of various CPUs (and some
          other chips).
index 461436f6f087cb9ddde7e6634b0f971366c0aa83..23507fce3a2b370de808dc09075b78b8dfe67bf1 100644 (file)
@@ -8,7 +8,7 @@
 
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/input-polldev.h>
+#include <linux/input.h>
 #include <linux/gpio/consumer.h>
 #include <linux/property.h>
 #include <linux/of.h>
@@ -43,10 +43,9 @@ struct gpio_mouse {
  * Timer function which is run every scan_ms ms when the device is opened.
  * The dev input variable is set to the the input_dev pointer.
  */
-static void gpio_mouse_scan(struct input_polled_dev *dev)
+static void gpio_mouse_scan(struct input_dev *input)
 {
-       struct gpio_mouse *gpio = dev->private;
-       struct input_dev *input = dev->input;
+       struct gpio_mouse *gpio = input_get_drvdata(input);
        int x, y;
 
        if (gpio->bleft)
@@ -71,18 +70,17 @@ static int gpio_mouse_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct gpio_mouse *gmouse;
-       struct input_polled_dev *input_poll;
        struct input_dev *input;
-       int ret;
+       int error;
 
        gmouse = devm_kzalloc(dev, sizeof(*gmouse), GFP_KERNEL);
        if (!gmouse)
                return -ENOMEM;
 
        /* Assign some default scanning time */
-       ret = device_property_read_u32(dev, "scan-interval-ms",
-                                      &gmouse->scan_ms);
-       if (ret || gmouse->scan_ms == 0) {
+       error = device_property_read_u32(dev, "scan-interval-ms",
+                                        &gmouse->scan_ms);
+       if (error || gmouse->scan_ms == 0) {
                dev_warn(dev, "invalid scan time, set to 50 ms\n");
                gmouse->scan_ms = 50;
        }
@@ -112,23 +110,14 @@ static int gpio_mouse_probe(struct platform_device *pdev)
        if (IS_ERR(gmouse->bright))
                return PTR_ERR(gmouse->bright);
 
-       input_poll = devm_input_allocate_polled_device(dev);
-       if (!input_poll) {
-               dev_err(dev, "not enough memory for input device\n");
+       input = devm_input_allocate_device(dev);
+       if (!input)
                return -ENOMEM;
-       }
-
-       platform_set_drvdata(pdev, input_poll);
-
-       /* set input-polldev handlers */
-       input_poll->private = gmouse;
-       input_poll->poll = gpio_mouse_scan;
-       input_poll->poll_interval = gmouse->scan_ms;
 
-       input = input_poll->input;
        input->name = pdev->name;
        input->id.bustype = BUS_HOST;
-       input->dev.parent = &pdev->dev;
+
+       input_set_drvdata(input, gmouse);
 
        input_set_capability(input, EV_REL, REL_X);
        input_set_capability(input, EV_REL, REL_Y);
@@ -139,10 +128,16 @@ static int gpio_mouse_probe(struct platform_device *pdev)
        if (gmouse->bright)
                input_set_capability(input, EV_KEY, BTN_RIGHT);
 
-       ret = input_register_polled_device(input_poll);
-       if (ret) {
+       error = input_setup_polling(input, gpio_mouse_scan);
+       if (error)
+               return error;
+
+       input_set_poll_interval(input, gmouse->scan_ms);
+
+       error = input_register_device(input);
+       if (error) {
                dev_err(dev, "could not register input device\n");
-               return ret;
+               return error;
        }
 
        dev_dbg(dev, "%d ms scan time, buttons: %s%s%s\n",
index 24c4b691b1c99005e546b348bb749d2a57869b35..ae60442efda0dcc29988d16ac32e3488c4e107ea 100644 (file)
@@ -3156,6 +3156,8 @@ static int __maybe_unused mxt_suspend(struct device *dev)
 
        mutex_unlock(&input_dev->mutex);
 
+       disable_irq(data->irq);
+
        return 0;
 }
 
@@ -3168,6 +3170,8 @@ static int __maybe_unused mxt_resume(struct device *dev)
        if (!input_dev)
                return 0;
 
+       enable_irq(data->irq);
+
        mutex_lock(&input_dev->mutex);
 
        if (input_dev->users)
index e146dfa257b15eadd866b101d73c8b3bc7d0e862..9aa09857735089b38865f9a421b92db0e4d8bd91 100644 (file)
@@ -5,22 +5,73 @@
  * Copyright (C) 2010-2011 Pixcir, Inc.
  */
 
+#include <asm/unaligned.h>
 #include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
+#include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
 #include <linux/input/mt.h>
 #include <linux/input/touchscreen.h>
-#include <linux/gpio.h>
-#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
 #include <linux/of_device.h>
-#include <linux/platform_data/pixcir_i2c_ts.h>
-#include <asm/unaligned.h>
+#include <linux/module.h>
+#include <linux/slab.h>
 
 #define PIXCIR_MAX_SLOTS       5 /* Max fingers supported by driver */
 
+/*
+ * Register map
+ */
+#define PIXCIR_REG_POWER_MODE  51
+#define PIXCIR_REG_INT_MODE    52
+
+/*
+ * Power modes:
+ * active: max scan speed
+ * idle: lower scan speed with automatic transition to active on touch
+ * halt: datasheet says sleep but this is more like halt as the chip
+ *       clocks are cut and it can only be brought out of this mode
+ *      using the RESET pin.
+ */
+enum pixcir_power_mode {
+       PIXCIR_POWER_ACTIVE,
+       PIXCIR_POWER_IDLE,
+       PIXCIR_POWER_HALT,
+};
+
+#define PIXCIR_POWER_MODE_MASK 0x03
+#define PIXCIR_POWER_ALLOW_IDLE (1UL << 2)
+
+/*
+ * Interrupt modes:
+ * periodical: interrupt is asserted periodicaly
+ * diff coordinates: interrupt is asserted when coordinates change
+ * level on touch: interrupt level asserted during touch
+ * pulse on touch: interrupt pulse asserted during touch
+ *
+ */
+enum pixcir_int_mode {
+       PIXCIR_INT_PERIODICAL,
+       PIXCIR_INT_DIFF_COORD,
+       PIXCIR_INT_LEVEL_TOUCH,
+       PIXCIR_INT_PULSE_TOUCH,
+};
+
+#define PIXCIR_INT_MODE_MASK   0x03
+#define PIXCIR_INT_ENABLE      (1UL << 3)
+#define PIXCIR_INT_POL_HIGH    (1UL << 2)
+
+/**
+ * struct pixcir_i2c_chip_data - chip related data
+ * @max_fingers:       Max number of fingers reported simultaneously by h/w
+ * @has_hw_ids:                Hardware supports finger tracking IDs
+ *
+ */
+struct pixcir_i2c_chip_data {
+       u8 max_fingers;
+       bool has_hw_ids;
+};
+
 struct pixcir_i2c_ts_data {
        struct i2c_client *client;
        struct input_dev *input;
@@ -30,7 +81,6 @@ struct pixcir_i2c_ts_data {
        struct gpio_desc *gpio_wake;
        const struct pixcir_i2c_chip_data *chip;
        struct touchscreen_properties prop;
-       int max_fingers;        /* Max fingers supported in this instance */
        bool running;
 };
 
@@ -54,7 +104,7 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
        memset(report, 0, sizeof(struct pixcir_report_data));
 
        i = chip->has_hw_ids ? 1 : 0;
-       readsize = 2 + tsdata->max_fingers * (4 + i);
+       readsize = 2 + tsdata->chip->max_fingers * (4 + i);
        if (readsize > sizeof(rdbuf))
                readsize = sizeof(rdbuf);
 
@@ -75,8 +125,8 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
        }
 
        touch = rdbuf[0] & 0x7;
-       if (touch > tsdata->max_fingers)
-               touch = tsdata->max_fingers;
+       if (touch > tsdata->chip->max_fingers)
+               touch = tsdata->chip->max_fingers;
 
        report->num_touches = touch;
        bufptr = &rdbuf[2];
@@ -192,7 +242,7 @@ static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
 
        ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_POWER_MODE);
        if (ret < 0) {
-               dev_err(dev, "%s: can't read reg 0x%x : %d\n",
+               dev_err(dev, "%s: can't read reg %d : %d\n",
                        __func__, PIXCIR_REG_POWER_MODE, ret);
                return ret;
        }
@@ -205,7 +255,7 @@ static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
 
        ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_POWER_MODE, ret);
        if (ret < 0) {
-               dev_err(dev, "%s: can't write reg 0x%x : %d\n",
+               dev_err(dev, "%s: can't write reg %d : %d\n",
                        __func__, PIXCIR_REG_POWER_MODE, ret);
                return ret;
        }
@@ -231,7 +281,7 @@ static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts,
 
        ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
        if (ret < 0) {
-               dev_err(dev, "%s: can't read reg 0x%x : %d\n",
+               dev_err(dev, "%s: can't read reg %d : %d\n",
                        __func__, PIXCIR_REG_INT_MODE, ret);
                return ret;
        }
@@ -246,7 +296,7 @@ static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts,
 
        ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
        if (ret < 0) {
-               dev_err(dev, "%s: can't write reg 0x%x : %d\n",
+               dev_err(dev, "%s: can't write reg %d : %d\n",
                        __func__, PIXCIR_REG_INT_MODE, ret);
                return ret;
        }
@@ -264,7 +314,7 @@ static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable)
 
        ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
        if (ret < 0) {
-               dev_err(dev, "%s: can't read reg 0x%x : %d\n",
+               dev_err(dev, "%s: can't read reg %d : %d\n",
                        __func__, PIXCIR_REG_INT_MODE, ret);
                return ret;
        }
@@ -276,7 +326,7 @@ static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable)
 
        ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
        if (ret < 0) {
-               dev_err(dev, "%s: can't write reg 0x%x : %d\n",
+               dev_err(dev, "%s: can't write reg %d : %d\n",
                        __func__, PIXCIR_REG_INT_MODE, ret);
                return ret;
        }
@@ -412,31 +462,9 @@ unlock:
 static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
                         pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);
 
-#ifdef CONFIG_OF
-static const struct of_device_id pixcir_of_match[];
-
-static int pixcir_parse_dt(struct device *dev,
-                          struct pixcir_i2c_ts_data *tsdata)
-{
-       tsdata->chip = of_device_get_match_data(dev);
-       if (!tsdata->chip)
-               return -EINVAL;
-
-       return 0;
-}
-#else
-static int pixcir_parse_dt(struct device *dev,
-                          struct pixcir_i2c_ts_data *tsdata)
-{
-       return -EINVAL;
-}
-#endif
-
 static int pixcir_i2c_ts_probe(struct i2c_client *client,
                               const struct i2c_device_id *id)
 {
-       const struct pixcir_ts_platform_data *pdata =
-                       dev_get_platdata(&client->dev);
        struct device *dev = &client->dev;
        struct pixcir_i2c_ts_data *tsdata;
        struct input_dev *input;
@@ -446,19 +474,11 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
        if (!tsdata)
                return -ENOMEM;
 
-       if (pdata) {
-               tsdata->chip = &pdata->chip;
-       } else if (dev->of_node) {
-               error = pixcir_parse_dt(dev, tsdata);
-               if (error)
-                       return error;
-       } else {
-               dev_err(dev, "platform data not defined\n");
-               return -EINVAL;
-       }
-
-       if (!tsdata->chip->max_fingers) {
-               dev_err(dev, "Invalid max_fingers in chip data\n");
+       tsdata->chip = device_get_match_data(dev);
+       if (!tsdata->chip && id)
+               tsdata->chip = (const void *)id->driver_data;
+       if (!tsdata->chip) {
+               dev_err(dev, "can't locate chip data\n");
                return -EINVAL;
        }
 
@@ -475,30 +495,17 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
        input->id.bustype = BUS_I2C;
        input->open = pixcir_input_open;
        input->close = pixcir_input_close;
-       input->dev.parent = dev;
-
-       if (pdata) {
-               input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
-               input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
-       } else {
-               input_set_capability(input, EV_ABS, ABS_MT_POSITION_X);
-               input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
-               touchscreen_parse_properties(input, true, &tsdata->prop);
-               if (!input_abs_get_max(input, ABS_MT_POSITION_X) ||
-                   !input_abs_get_max(input, ABS_MT_POSITION_Y)) {
-                       dev_err(dev, "Touchscreen size is not specified\n");
-                       return -EINVAL;
-               }
-       }
 
-       tsdata->max_fingers = tsdata->chip->max_fingers;
-       if (tsdata->max_fingers > PIXCIR_MAX_SLOTS) {
-               tsdata->max_fingers = PIXCIR_MAX_SLOTS;
-               dev_info(dev, "Limiting maximum fingers to %d\n",
-                        tsdata->max_fingers);
+       input_set_capability(input, EV_ABS, ABS_MT_POSITION_X);
+       input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
+       touchscreen_parse_properties(input, true, &tsdata->prop);
+       if (!input_abs_get_max(input, ABS_MT_POSITION_X) ||
+           !input_abs_get_max(input, ABS_MT_POSITION_Y)) {
+               dev_err(dev, "Touchscreen size is not specified\n");
+               return -EINVAL;
        }
 
-       error = input_mt_init_slots(input, tsdata->max_fingers,
+       error = input_mt_init_slots(input, tsdata->chip->max_fingers,
                                    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
        if (error) {
                dev_err(dev, "Error initializing Multi-Touch slots\n");
@@ -510,7 +517,9 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
        tsdata->gpio_attb = devm_gpiod_get(dev, "attb", GPIOD_IN);
        if (IS_ERR(tsdata->gpio_attb)) {
                error = PTR_ERR(tsdata->gpio_attb);
-               dev_err(dev, "Failed to request ATTB gpio: %d\n", error);
+               if (error != -EPROBE_DEFER)
+                       dev_err(dev, "Failed to request ATTB gpio: %d\n",
+                               error);
                return error;
        }
 
@@ -518,7 +527,9 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
                                                     GPIOD_OUT_LOW);
        if (IS_ERR(tsdata->gpio_reset)) {
                error = PTR_ERR(tsdata->gpio_reset);
-               dev_err(dev, "Failed to request RESET gpio: %d\n", error);
+               if (error != -EPROBE_DEFER)
+                       dev_err(dev, "Failed to request RESET gpio: %d\n",
+                               error);
                return error;
        }
 
@@ -574,14 +585,6 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
        return 0;
 }
 
-static const struct i2c_device_id pixcir_i2c_ts_id[] = {
-       { "pixcir_ts", 0 },
-       { "pixcir_tangoc", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
-
-#ifdef CONFIG_OF
 static const struct pixcir_i2c_chip_data pixcir_ts_data = {
        .max_fingers = 2,
        /* no hw id support */
@@ -592,6 +595,14 @@ static const struct pixcir_i2c_chip_data pixcir_tangoc_data = {
        .has_hw_ids = true,
 };
 
+static const struct i2c_device_id pixcir_i2c_ts_id[] = {
+       { "pixcir_ts", (unsigned long) &pixcir_ts_data },
+       { "pixcir_tangoc", (unsigned long) &pixcir_tangoc_data },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
+
+#ifdef CONFIG_OF
 static const struct of_device_id pixcir_of_match[] = {
        { .compatible = "pixcir,pixcir_ts", .data = &pixcir_ts_data },
        { .compatible = "pixcir,pixcir_tangoc", .data = &pixcir_tangoc_data },
index 94f277cd806a81c2148b380b1756951871edd019..56f2fd32e6096382e047f5cf2704adc23d404cf6 100644 (file)
@@ -383,6 +383,7 @@ int input_setup_polling(struct input_dev *dev,
 void input_set_poll_interval(struct input_dev *dev, unsigned int interval);
 void input_set_min_poll_interval(struct input_dev *dev, unsigned int interval);
 void input_set_max_poll_interval(struct input_dev *dev, unsigned int interval);
+int input_get_poll_interval(struct input_dev *dev);
 
 int __must_check input_register_handler(struct input_handler *);
 void input_unregister_handler(struct input_handler *);
diff --git a/include/linux/platform_data/pixcir_i2c_ts.h b/include/linux/platform_data/pixcir_i2c_ts.h
deleted file mode 100644 (file)
index 4ab3cd6..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef        _PIXCIR_I2C_TS_H
-#define        _PIXCIR_I2C_TS_H
-
-/*
- * Register map
- */
-#define PIXCIR_REG_POWER_MODE  51
-#define PIXCIR_REG_INT_MODE    52
-
-/*
- * Power modes:
- * active: max scan speed
- * idle: lower scan speed with automatic transition to active on touch
- * halt: datasheet says sleep but this is more like halt as the chip
- *       clocks are cut and it can only be brought out of this mode
- *      using the RESET pin.
- */
-enum pixcir_power_mode {
-       PIXCIR_POWER_ACTIVE,
-       PIXCIR_POWER_IDLE,
-       PIXCIR_POWER_HALT,
-};
-
-#define PIXCIR_POWER_MODE_MASK 0x03
-#define PIXCIR_POWER_ALLOW_IDLE (1UL << 2)
-
-/*
- * Interrupt modes:
- * periodical: interrupt is asserted periodicaly
- * diff coordinates: interrupt is asserted when coordinates change
- * level on touch: interrupt level asserted during touch
- * pulse on touch: interrupt pulse asserted druing touch
- *
- */
-enum pixcir_int_mode {
-       PIXCIR_INT_PERIODICAL,
-       PIXCIR_INT_DIFF_COORD,
-       PIXCIR_INT_LEVEL_TOUCH,
-       PIXCIR_INT_PULSE_TOUCH,
-};
-
-#define PIXCIR_INT_MODE_MASK   0x03
-#define PIXCIR_INT_ENABLE      (1UL << 3)
-#define PIXCIR_INT_POL_HIGH    (1UL << 2)
-
-/**
- * struct pixcir_irc_chip_data - chip related data
- * @max_fingers:       Max number of fingers reported simultaneously by h/w
- * @has_hw_ids:                Hardware supports finger tracking IDs
- *
- */
-struct pixcir_i2c_chip_data {
-       u8 max_fingers;
-       bool has_hw_ids;
-};
-
-struct pixcir_ts_platform_data {
-       int x_max;
-       int y_max;
-       struct pixcir_i2c_chip_data chip;
-};
-
-#endif