Merge tag 'input-for-v6.1-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 11 Oct 2022 17:53:25 +0000 (10:53 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 11 Oct 2022 17:53:25 +0000 (10:53 -0700)
Pull input updates from Dmitry Torokhov:

 - a new driver for IBM Operational Panel

 - a new driver for PinePhone keyboards

 - RT5120 PMIC power key support

 - various enhancements and support for new models in xpad (Xbox) driver

 - a new compatible ID for Elan touchscreen driver

 - rework of adp5588-keys driver to support configuring via device
   properties (OF, ACPI, etc) instead of platform data, and proper
   support of optional gpiochip functionality (and removal of
   gpio-adp5588 driver)

 - improvements to firmware update handling in Synaptics RMI4 driver

 - support for double key matrix in mt6779-keypad

 - support for polled mode in adc-joystick driver

 - other assorted driver fixes, cleanups and improvements

* tag 'input-for-v6.1-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (90 commits)
  Input: i8042 - fix refount leak on sparc
  Input: i8042 - add LoongArch support in i8042-acpipnpio.h
  Input: i8042 - rename i8042-x86ia64io.h to i8042-acpipnpio.h
  Input: pinephone-keyboard - support the proxied I2C bus
  Input: pinephone-keyboard - add PinePhone keyboard driver
  dt-bindings: input: Add the PinePhone keyboard binding
  dt-bindings: input: Convert hid-over-i2c to DT schema
  input: drop empty comment blocks
  Input: xpad - add X-Box Adaptive Profile button
  Input: add ABS_PROFILE to uapi and documentation
  Input: xpad - add X-Box Adaptive XBox button
  Input: xpad - add X-Box Adaptive support
  Input: ims-pcu - fix spelling mistake "BOOLTLOADER" -> "BOOTLOADER"
  Input: ibm-panel - add missing MODULE_DEVICE_TABLE
  Input: icn8505 - utilize acpi_get_subsystem_id()
  Input: xpad - decipher xpadone packages with GIP defines
  Input: xpad - refactor using BIT() macro
  Input: synaptics-rmi4 - convert to use sysfs_emit() APIs
  Input: twl4030-pwrbutton - add missing of.h include
  Input: applespi - replace zero-length array with DECLARE_FLEX_ARRAY() helper
  ...

138 files changed:
Documentation/devicetree/bindings/input/adc-joystick.yaml
Documentation/devicetree/bindings/input/adi,adp5588.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/input/hid-over-i2c.txt [deleted file]
Documentation/devicetree/bindings/input/hid-over-i2c.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/input/ibm,op-panel.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/input/mediatek,mt6779-keypad.yaml
Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/input/mtk-pmic-keys.txt [deleted file]
Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/input/qcom,pm8xxx-vib.txt [deleted file]
Documentation/devicetree/bindings/input/qcom,pm8xxx-vib.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/input/touchscreen/auo_pixcir_ts.txt
Documentation/devicetree/bindings/input/touchscreen/colibri-vf50-ts.txt
Documentation/devicetree/bindings/input/touchscreen/elan,elants_i2c.yaml
Documentation/devicetree/bindings/input/touchscreen/stmpe.txt
Documentation/input/event-codes.rst
Documentation/input/gamepad.rst
MAINTAINERS
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-adp5588.c [deleted file]
drivers/hid/hid-debug.c
drivers/input/ff-core.c
drivers/input/ff-memless.c
drivers/input/gameport/emu10k1-gp.c
drivers/input/gameport/lightning.c
drivers/input/gameport/ns558.c
drivers/input/joydev.c
drivers/input/joystick/a3d.c
drivers/input/joystick/adc-joystick.c
drivers/input/joystick/adi.c
drivers/input/joystick/amijoy.c
drivers/input/joystick/analog.c
drivers/input/joystick/cobra.c
drivers/input/joystick/db9.c
drivers/input/joystick/gamecon.c
drivers/input/joystick/gf2k.c
drivers/input/joystick/grip.c
drivers/input/joystick/guillemot.c
drivers/input/joystick/interact.c
drivers/input/joystick/joydump.c
drivers/input/joystick/magellan.c
drivers/input/joystick/sidewinder.c
drivers/input/joystick/spaceball.c
drivers/input/joystick/spaceorb.c
drivers/input/joystick/stinger.c
drivers/input/joystick/tmdc.c
drivers/input/joystick/turbografx.c
drivers/input/joystick/twidjoy.c
drivers/input/joystick/warrior.c
drivers/input/joystick/xpad.c
drivers/input/joystick/zhenhua.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/keyboard/adp5588-keys.c
drivers/input/keyboard/amikbd.c
drivers/input/keyboard/applespi.c
drivers/input/keyboard/atakbd.c
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/clps711x-keypad.c
drivers/input/keyboard/ep93xx_keypad.c
drivers/input/keyboard/imx_keypad.c
drivers/input/keyboard/lkkbd.c
drivers/input/keyboard/lm8333.c
drivers/input/keyboard/matrix_keypad.c
drivers/input/keyboard/mt6779-keypad.c
drivers/input/keyboard/mtk-pmic-keys.c
drivers/input/keyboard/newtonkbd.c
drivers/input/keyboard/pinephone-keyboard.c [new file with mode: 0644]
drivers/input/keyboard/st-keyscan.c
drivers/input/keyboard/stowaway.c
drivers/input/keyboard/sunkbd.c
drivers/input/keyboard/tc3589x-keypad.c
drivers/input/keyboard/xtkbd.c
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/ibm-panel.c [new file with mode: 0644]
drivers/input/misc/ims-pcu.c
drivers/input/misc/iqs7222.c
drivers/input/misc/keyspan_remote.c
drivers/input/misc/rt5120-pwrkey.c [new file with mode: 0644]
drivers/input/misc/twl4030-pwrbutton.c
drivers/input/misc/twl4030-vibra.c
drivers/input/mouse/elan_i2c_core.c
drivers/input/mouse/hgpk.c
drivers/input/mouse/inport.c
drivers/input/mouse/logibm.c
drivers/input/mouse/pc110pad.c
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/sermouse.c
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics_usb.c
drivers/input/mouse/vsxxxaa.c
drivers/input/rmi4/rmi_f03.c
drivers/input/rmi4/rmi_f34.c
drivers/input/rmi4/rmi_f34.h
drivers/input/rmi4/rmi_f34v7.c
drivers/input/rmi4/rmi_f54.c
drivers/input/serio/altera_ps2.c
drivers/input/serio/ambakmi.c
drivers/input/serio/ams_delta_serio.c
drivers/input/serio/apbps2.c
drivers/input/serio/ct82c710.c
drivers/input/serio/gscps2.c
drivers/input/serio/hyperv-keyboard.c
drivers/input/serio/i8042-acpipnpio.h [moved from drivers/input/serio/i8042-x86ia64io.h with 99% similarity]
drivers/input/serio/i8042-sparcio.h
drivers/input/serio/i8042.c
drivers/input/serio/i8042.h
drivers/input/serio/olpc_apsp.c
drivers/input/serio/parkbd.c
drivers/input/serio/pcips2.c
drivers/input/serio/ps2-gpio.c
drivers/input/serio/ps2mult.c
drivers/input/serio/q40kbd.c
drivers/input/serio/rpckbd.c
drivers/input/serio/sa1111ps2.c
drivers/input/serio/serio.c
drivers/input/serio/serport.c
drivers/input/serio/sun4i-ps2.c
drivers/input/tablet/acecad.c
drivers/input/tablet/aiptek.c
drivers/input/tablet/hanwang.c
drivers/input/tablet/pegasus_notetaker.c
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/atmel_mxt_ts.c
drivers/input/touchscreen/auo-pixcir-ts.c
drivers/input/touchscreen/chipone_icn8505.c
drivers/input/touchscreen/edt-ft5x06.c
drivers/input/touchscreen/gunze.c
drivers/input/touchscreen/sur40.c
drivers/input/touchscreen/usbtouchscreen.c
drivers/input/touchscreen/wacom_w8001.c
include/linux/bma150.h
include/linux/gameport.h
include/linux/input/auo-pixcir-ts.h [deleted file]
include/linux/platform_data/adp5588.h [deleted file]
include/uapi/linux/input-event-codes.h

index 64d9614..da0f8df 100644 (file)
@@ -14,6 +14,9 @@ description: >
   Bindings for joystick devices connected to ADC controllers supporting
   the Industrial I/O subsystem.
 
+allOf:
+  - $ref: input.yaml#
+
 properties:
   compatible:
     const: adc-joystick
@@ -28,6 +31,8 @@ properties:
       https://github.com/devicetree-org/dt-schema/blob/master/schemas/iio/iio-consumer.yaml
       for details.
 
+  poll-interval: true
+
   '#address-cells':
     const: 1
 
diff --git a/Documentation/devicetree/bindings/input/adi,adp5588.yaml b/Documentation/devicetree/bindings/input/adi,adp5588.yaml
new file mode 100644 (file)
index 0000000..26ea668
--- /dev/null
@@ -0,0 +1,111 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/adi,adp5588.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices ADP5588 Keypad Controller
+
+maintainers:
+  - Nuno Sá <nuno.sa@analog.com>
+
+description: |
+  Analog Devices Mobile I/O Expander and QWERTY Keypad Controller
+  https://www.analog.com/media/en/technical-documentation/data-sheets/ADP5588.pdf
+
+allOf:
+  - $ref: matrix-keymap.yaml#
+  - $ref: input.yaml#
+
+properties:
+  compatible:
+    enum:
+      - adi,adp5587
+      - adi,adp5588
+
+  reg:
+    maxItems: 1
+
+  vcc-supply:
+    description: Supply Voltage Input
+
+  reset-gpios:
+    description:
+      If specified, it will be asserted during driver probe. As the line is
+      active low, it should be marked GPIO_ACTIVE_LOW.
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  gpio-controller:
+    description:
+      This property applies if either keypad,num-rows lower than 8 or
+      keypad,num-columns lower than 10.
+
+  '#gpio-cells':
+    const: 2
+
+  interrupt-controller:
+    description:
+      This property applies if either keypad,num-rows lower than 8 or
+      keypad,num-columns lower than 10.
+
+  '#interrupt-cells':
+    const: 2
+
+  adi,unlock-keys:
+    description:
+      Specifies a maximum of 2 keys that can be used to unlock the keypad.
+      If this property is set, the keyboard will be locked and only unlocked
+      after these keys are pressed. If only one key is set, a double click is
+      needed to unlock the keypad. The value of this property cannot be bigger
+      or equal than keypad,num-rows * keypad,num-columns.
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    minItems: 1
+    maxItems: 2
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - keypad,num-rows
+  - keypad,num-columns
+  - linux,keymap
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/input/input.h>
+    #include <dt-bindings/gpio/gpio.h>
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        keys@34 {
+            compatible = "adi,adp5588";
+            reg = <0x34>;
+
+            vcc-supply = <&vcc>;
+            interrupts = <21 IRQ_TYPE_EDGE_FALLING>;
+            interrupt-parent = <&gpio>;
+            reset-gpios = <&gpio 20 GPIO_ACTIVE_LOW>;
+
+            keypad,num-rows = <1>;
+            keypad,num-columns = <9>;
+            linux,keymap = <
+                MATRIX_KEY(0x00, 0x00, KEY_1)
+                MATRIX_KEY(0x00, 0x01, KEY_2)
+                MATRIX_KEY(0x00, 0x02, KEY_3)
+                MATRIX_KEY(0x00, 0x03, KEY_4)
+                MATRIX_KEY(0x00, 0x04, KEY_5)
+                MATRIX_KEY(0x00, 0x05, KEY_6)
+                MATRIX_KEY(0x00, 0x06, KEY_7)
+                MATRIX_KEY(0x00, 0x07, KEY_8)
+                MATRIX_KEY(0x00, 0x08, KEY_9)
+            >;
+        };
+    };
+...
diff --git a/Documentation/devicetree/bindings/input/hid-over-i2c.txt b/Documentation/devicetree/bindings/input/hid-over-i2c.txt
deleted file mode 100644 (file)
index 34c43d3..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-* HID over I2C Device-Tree bindings
-
-HID over I2C provides support for various Human Interface Devices over the
-I2C bus. These devices can be for example touchpads, keyboards, touch screens
-or sensors.
-
-The specification has been written by Microsoft and is currently available here:
-http://msdn.microsoft.com/en-us/library/windows/hardware/hh852380.aspx
-
-If this binding is used, the kernel module i2c-hid will handle the communication
-with the device and the generic hid core layer will handle the protocol.
-
-Required properties:
-- compatible: must be "hid-over-i2c"
-- reg: i2c slave address
-- hid-descr-addr: HID descriptor address
-- interrupts: interrupt line
-
-Additional optional properties:
-
-Some devices may support additional optional properties to help with, e.g.,
-power sequencing. The following properties can be supported by one or more
-device-specific compatible properties, which should be used in addition to the
-"hid-over-i2c" string.
-
-- compatible:
-  * "wacom,w9013" (Wacom W9013 digitizer). Supports:
-    - vdd-supply (3.3V)
-    - vddl-supply (1.8V)
-    - post-power-on-delay-ms
-
-- vdd-supply: phandle of the regulator that provides the supply voltage.
-- post-power-on-delay-ms: time required by the device after enabling its regulators
-  or powering it on, before it is ready for communication.
-- touchscreen-inverted-x: See touchscreen.txt
-- touchscreen-inverted-y: See touchscreen.txt
-
-Example:
-
-       i2c-hid-dev@2c {
-               compatible = "hid-over-i2c";
-               reg = <0x2c>;
-               hid-descr-addr = <0x0020>;
-               interrupt-parent = <&gpx3>;
-               interrupts = <3 2>;
-       };
diff --git a/Documentation/devicetree/bindings/input/hid-over-i2c.yaml b/Documentation/devicetree/bindings/input/hid-over-i2c.yaml
new file mode 100644 (file)
index 0000000..7156b08
--- /dev/null
@@ -0,0 +1,83 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/hid-over-i2c.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: HID over I2C Devices
+
+maintainers:
+  - Benjamin Tissoires <benjamin.tissoires@redhat.com>
+  - Jiri Kosina <jkosina@suse.cz>
+
+description: |+
+  HID over I2C provides support for various Human Interface Devices over the
+  I2C bus. These devices can be for example touchpads, keyboards, touch screens
+  or sensors.
+
+  The specification has been written by Microsoft and is currently available here:
+  https://msdn.microsoft.com/en-us/library/windows/hardware/hh852380.aspx
+
+  If this binding is used, the kernel module i2c-hid will handle the communication
+  with the device and the generic hid core layer will handle the protocol.
+
+allOf:
+  - $ref: /schemas/input/touchscreen/touchscreen.yaml#
+
+properties:
+  compatible:
+    oneOf:
+      - items:
+          - enum:
+              - wacom,w9013
+          - const: hid-over-i2c
+      - description: Just "hid-over-i2c" alone is allowed, but not recommended.
+        const: hid-over-i2c
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  hid-descr-addr:
+    description: HID descriptor address
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  post-power-on-delay-ms:
+    description: Time required by the device after enabling its regulators
+      or powering it on, before it is ready for communication.
+
+  touchscreen-inverted-x: true
+
+  touchscreen-inverted-y: true
+
+  vdd-supply:
+    description: 3.3V supply
+
+  vddl-supply:
+    description: 1.8V supply
+
+  wakeup-source: true
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        hid@2c {
+            compatible = "hid-over-i2c";
+            reg = <0x2c>;
+            hid-descr-addr = <0x0020>;
+            interrupts = <3 2>;
+        };
+    };
+...
diff --git a/Documentation/devicetree/bindings/input/ibm,op-panel.yaml b/Documentation/devicetree/bindings/input/ibm,op-panel.yaml
new file mode 100644 (file)
index 0000000..29a1879
--- /dev/null
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/ibm,op-panel.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: IBM Operation Panel
+
+maintainers:
+  - Eddie James <eajames@linux.ibm.com>
+
+allOf:
+  - $ref: input.yaml#
+
+description: |
+  The IBM Operation Panel provides a simple interface to control the connected
+  server. It has a display and three buttons: two directional arrows and one
+  'Enter' button.
+
+properties:
+  compatible:
+    const: ibm,op-panel
+
+  reg:
+    maxItems: 1
+
+  linux,keycodes:
+    minItems: 1
+    maxItems: 3
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/i2c/i2c.h>
+    #include <dt-bindings/input/input.h>
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        ibm-op-panel@62 {
+            compatible = "ibm,op-panel";
+            reg = <(0x62 | I2C_OWN_SLAVE_ADDRESS)>;
+            linux,keycodes = <KEY_UP>, <KEY_DOWN>, <KEY_ENTER>;
+        };
+    };
index 7d1ab25..d768c30 100644 (file)
@@ -49,6 +49,12 @@ properties:
     maximum: 256
     default: 16
 
+  mediatek,keys-per-group:
+    description: each (row, column) group has multiple keys
+    $ref: /schemas/types.yaml#/definitions/uint32
+    default: 1
+    maximum: 2
+
 required:
   - compatible
   - reg
@@ -56,7 +62,7 @@ required:
   - clocks
   - clock-names
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
diff --git a/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml b/Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml
new file mode 100644 (file)
index 0000000..2f72ec4
--- /dev/null
@@ -0,0 +1,114 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/mediatek,pmic-keys.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek PMIC Keys
+
+maintainers:
+  - Chen Zhong <chen.zhong@mediatek.com>
+
+allOf:
+  - $ref: input.yaml#
+
+description: |
+  There are two key functions provided by MT6397, MT6323 and other MediaTek
+  PMICs: pwrkey and homekey.
+  The key functions are defined as the subnode of the function node provided
+  by the PMIC that is defined as a Multi-Function Device (MFD).
+
+  For MediaTek MT6323/MT6397 PMIC bindings see
+  Documentation/devicetree/bindings/mfd/mt6397.txt
+
+properties:
+  compatible:
+    enum:
+      - mediatek,mt6323-keys
+      - mediatek,mt6331-keys
+      - mediatek,mt6358-keys
+      - mediatek,mt6397-keys
+
+  power-off-time-sec: true
+
+  mediatek,long-press-mode:
+    description: |
+      Key long-press force shutdown setting
+      0 - disabled
+      1 - pwrkey
+      2 - pwrkey+homekey
+    $ref: /schemas/types.yaml#/definitions/uint32
+    default: 0
+    maximum: 2
+
+patternProperties:
+  "^((power|home)|(key-[a-z0-9-]+|[a-z0-9-]+-key))$":
+    $ref: input.yaml#
+
+    properties:
+      interrupts:
+        minItems: 1
+        items:
+          - description: Key press interrupt
+          - description: Key release interrupt
+
+      interrupt-names: true
+
+      linux-keycodes:
+        maxItems: 1
+
+      wakeup-source: true
+
+    required:
+      - linux,keycodes
+
+    if:
+      properties:
+        interrupt-names:
+          contains:
+            const: powerkey
+    then:
+      properties:
+        interrupt-names:
+          minItems: 1
+          items:
+            - const: powerkey
+            - const: powerkey_r
+    else:
+      properties:
+        interrupt-names:
+          minItems: 1
+          items:
+            - const: homekey
+            - const: homekey_r
+
+    unevaluatedProperties: false
+
+required:
+  - compatible
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/input/input.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    pmic {
+        compatible = "mediatek,mt6397";
+
+        keys {
+          compatible = "mediatek,mt6397-keys";
+          mediatek,long-press-mode = <1>;
+          power-off-time-sec = <0>;
+
+          key-power {
+            linux,keycodes = <KEY_POWER>;
+            wakeup-source;
+          };
+
+          key-home {
+            linux,keycodes = <KEY_VOLUMEDOWN>;
+          };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/input/mtk-pmic-keys.txt b/Documentation/devicetree/bindings/input/mtk-pmic-keys.txt
deleted file mode 100644 (file)
index 9d00f2a..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-MediaTek MT6397/MT6323 PMIC Keys Device Driver
-
-There are two key functions provided by MT6397/MT6323 PMIC, pwrkey
-and homekey. The key functions are defined as the subnode of the function
-node provided by MT6397/MT6323 PMIC that is being defined as one kind
-of Muti-Function Device (MFD)
-
-For MT6397/MT6323 MFD bindings see:
-Documentation/devicetree/bindings/mfd/mt6397.txt
-
-Required properties:
-- compatible: Should be one of:
-       - "mediatek,mt6397-keys"
-       - "mediatek,mt6323-keys"
-       - "mediatek,mt6358-keys"
-- 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/input.yaml
-
-Example:
-
-       pmic: mt6397 {
-               compatible = "mediatek,mt6397";
-
-               ...
-
-               mt6397keys: mt6397keys {
-                       compatible = "mediatek,mt6397-keys";
-                       mediatek,long-press-mode = <1>;
-                       power-off-time-sec = <0>;
-
-                       power {
-                               linux,keycodes = <116>;
-                               wakeup-source;
-                       };
-
-                       home {
-                               linux,keycodes = <114>;
-                       };
-               };
-
-       };
diff --git a/Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml b/Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml
new file mode 100644 (file)
index 0000000..e4a0ac0
--- /dev/null
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/pine64,pinephone-keyboard.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Pine64 PinePhone keyboard device tree bindings
+
+maintainers:
+  - Samuel Holland <samuel@sholland.org>
+
+description:
+  A keyboard accessory is available for the Pine64 PinePhone and PinePhone Pro.
+  It connects via I2C, providing a raw scan matrix, a flashing interface, and a
+  subordinate I2C bus for communication with a battery charger IC.
+
+properties:
+  compatible:
+    const: pine64,pinephone-keyboard
+
+  reg:
+    const: 0x15
+
+  interrupts:
+    maxItems: 1
+
+  vbat-supply:
+    description: Supply for the keyboard MCU
+
+  wakeup-source: true
+
+  i2c:
+    $ref: /schemas/i2c/i2c-controller.yaml#
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/input/input.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    i2c {
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      keyboard@15 {
+        compatible = "pine64,pinephone-keyboard";
+        reg = <0x15>;
+        interrupt-parent = <&r_pio>;
+        interrupts = <0 12 IRQ_TYPE_EDGE_FALLING>; /* PL12 */
+
+        i2c {
+          #address-cells = <1>;
+          #size-cells = <0>;
+
+          charger@75 {
+            reg = <0x75>;
+          };
+        };
+      };
+    };
diff --git a/Documentation/devicetree/bindings/input/qcom,pm8xxx-vib.txt b/Documentation/devicetree/bindings/input/qcom,pm8xxx-vib.txt
deleted file mode 100644 (file)
index 64bb990..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-Qualcomm PM8xxx PMIC Vibrator
-
-PROPERTIES
-
-- compatible:
-       Usage: required
-       Value type: <string>
-       Definition: must be one of:
-                   "qcom,pm8058-vib"
-                   "qcom,pm8916-vib"
-                   "qcom,pm8921-vib"
-
-- reg:
-       Usage: required
-       Value type: <prop-encoded-array>
-       Definition: address of vibration control register
-
-EXAMPLE
-
-       vibrator@4a {
-               compatible = "qcom,pm8058-vib";
-               reg = <0x4a>;
-       };
diff --git a/Documentation/devicetree/bindings/input/qcom,pm8xxx-vib.yaml b/Documentation/devicetree/bindings/input/qcom,pm8xxx-vib.yaml
new file mode 100644 (file)
index 0000000..c8832cd
--- /dev/null
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/qcom,pm8xxx-vib.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm PM8xxx PMIC Vibrator
+
+maintainers:
+  - Bjorn Andersson <andersson@kernel.org>
+
+properties:
+  compatible:
+    enum:
+      - qcom,pm8058-vib
+      - qcom,pm8916-vib
+      - qcom,pm8921-vib
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    pmic {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        vibrator@4a {
+            compatible = "qcom,pm8058-vib";
+            reg = <0x4a>;
+        };
+    };
index f40f21c..b8db975 100644 (file)
@@ -17,10 +17,10 @@ Example:
                auo_pixcir_ts@5c {
                        compatible = "auo,auo_pixcir_ts";
                        reg = <0x5c>;
-                       interrupts = <2 0>;
+                       interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
 
-                       gpios = <&gpf 2 0 2>, /* INT */
-                               <&gpf 5 1 0>; /* RST */
+                       gpios = <&gpf 2 0 GPIO_LEVEL_HIGH>, /* INT */
+                               <&gpf 5 1 GPIO_LEVEL_LOW>; /* RST */
 
                        x-size = <800>;
                        y-size = <600>;
index 2e1490a..ca30435 100644 (file)
@@ -3,15 +3,16 @@
 Required Properties:
 - compatible must be toradex,vf50-touchscreen
 - io-channels: adc channels being used by the Colibri VF50 module
+    IIO ADC for Y-, X-, Y+, X+ connections
 - xp-gpios: FET gate driver for input of X+
 - xm-gpios: FET gate driver for input of X-
 - yp-gpios: FET gate driver for input of Y+
 - ym-gpios: FET gate driver for input of Y-
-- interrupts: pen irq interrupt for touch detection
-- pinctrl-names: "idle", "default", "gpios"
-- pinctrl-0: pinctrl node for pen/touch detection state pinmux
+- interrupts: pen irq interrupt for touch detection, signal from X plate
+- pinctrl-names: "idle", "default"
+- pinctrl-0: pinctrl node for pen/touch detection, pinctrl must provide
+    pull-up resistor on X+, X-.
 - pinctrl-1: pinctrl node for X/Y and pressure measurement (ADC) state pinmux
-- pinctrl-2: pinctrl node for gpios functioning as FET gate drivers
 - vf50-ts-min-pressure: pressure level at which to stop measuring X/Y values
 
 Example:
@@ -26,9 +27,8 @@ Example:
                ym-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
                interrupt-parent = <&gpio0>;
                interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
-               pinctrl-names = "idle","default","gpios";
-               pinctrl-0 = <&pinctrl_touchctrl_idle>;
-               pinctrl-1 = <&pinctrl_touchctrl_default>;
-               pinctrl-2 = <&pinctrl_touchctrl_gpios>;
+               pinctrl-names = "idle","default";
+               pinctrl-0 = <&pinctrl_touchctrl_idle>, <&pinctrl_touchctrl_gpios>;
+               pinctrl-1 = <&pinctrl_touchctrl_default>, <&pinctrl_touchctrl_gpios>;
                vf50-ts-min-pressure = <200>;
        };
index a9b53c2..f9053e5 100644 (file)
@@ -14,9 +14,13 @@ allOf:
 
 properties:
   compatible:
-    enum:
-      - elan,ektf3624
-      - elan,ekth3500
+    oneOf:
+      - enum:
+          - elan,ektf3624
+          - elan,ekth3500
+      - items:
+          - const: elan,ekth3915
+          - const: elan,ekth3500
 
   reg:
     maxItems: 1
index c549924..238b515 100644 (file)
@@ -54,8 +54,7 @@ Optional properties common with MFD (deprecated):
                                1 -> 3.25 MHz
                                2 || 3 -> 6.5 MHz
 
-Node name must be stmpe_touchscreen and should be child node of stmpe node to
-which it belongs.
+Node should be child node of stmpe node to which it belongs.
 
 Note that common ADC settings of stmpe_touchscreen (child) will take precedence
 over the settings done in MFD.
index 8741d39..b455746 100644 (file)
@@ -235,6 +235,12 @@ A few EV_ABS codes have special meanings:
     BTN_TOOL_<name> signals the type of tool that is currently detected by the
     hardware and is otherwise independent of ABS_DISTANCE and/or BTN_TOUCH.
 
+* ABS_PROFILE:
+
+  - Used to describe the state of a multi-value profile switch.  An event is
+    emitted only when the selected profile changes, indicating the newly
+    selected profile value.
+
 * ABS_MT_<name>:
 
   - Used to describe multitouch input events. Please see
index 4d5e7fb..71019de 100644 (file)
@@ -189,3 +189,9 @@ Gamepads report the following events:
 - Rumble:
 
   Rumble is advertised as FF_RUMBLE.
+
+- Profile:
+
+  Some pads provide a multi-value profile selection switch.  An example is the
+  XBox Adaptive and the XBox Elite 2 controllers.  When the active profile is
+  switched, its newly selected value is emitted as an ABS_PROFILE event.
index e68a080..ce883ab 100644 (file)
@@ -554,7 +554,7 @@ M:  Michael Hennerich <michael.hennerich@analog.com>
 S:     Supported
 W:     http://wiki.analog.com/ADP5588
 W:     https://ez.analog.com/linux-software-drivers
-F:     drivers/gpio/gpio-adp5588.c
+F:     Documentation/devicetree/bindings/input/adi,adp5588.yaml
 F:     drivers/input/keyboard/adp5588-keys.c
 
 ADP8860 BACKLIGHT DRIVER (ADP8860/ADP8861/ADP8863)
@@ -9713,6 +9713,13 @@ S:       Orphan
 F:     Documentation/ia64/
 F:     arch/ia64/
 
+IBM Operation Panel Input Driver
+M:     Eddie James <eajames@linux.ibm.com>
+L:     linux-input@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/input/ibm,op-panel.yaml
+F:     drivers/input/misc/ibm-panel.c
+
 IBM Power 842 compression accelerator
 M:     Haren Myneni <haren@us.ibm.com>
 S:     Supported
@@ -12925,6 +12932,12 @@ S:     Supported
 F:     Documentation/devicetree/bindings/media/mediatek-jpeg-*.yaml
 F:     drivers/media/platform/mediatek/jpeg/
 
+MEDIATEK KEYPAD DRIVER
+M:     Mattijs Korpershoek <mkorpershoek@baylibre.com>
+S:     Supported
+F:     Documentation/devicetree/bindings/input/mediatek,mt6779-keypad.yaml
+F:     drivers/input/keyboard/mt6779-keypad.c
+
 MEDIATEK MDP DRIVER
 M:     Minghsiu Tsai <minghsiu.tsai@mediatek.com>
 M:     Houlong Wei <houlong.wei@mediatek.com>
@@ -16337,6 +16350,12 @@ F:     Documentation/devicetree/bindings/pinctrl/sunplus,*
 F:     drivers/pinctrl/sunplus/
 F:     include/dt-bindings/pinctrl/sppctl*.h
 
+PINE64 PINEPHONE KEYBOARD DRIVER
+M:     Samuel Holland <samuel@sholland.org>
+S:     Supported
+F:     Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml
+F:     drivers/input/keyboard/pinephone-keyboard.c
+
 PKTCDVD DRIVER
 M:     linux-block@vger.kernel.org
 S:     Orphan
index ed9e71d..a01af11 100644 (file)
@@ -990,20 +990,6 @@ endmenu
 menu "I2C GPIO expanders"
        depends on I2C
 
-config GPIO_ADP5588
-       tristate "ADP5588 I2C GPIO expander"
-       help
-         This option enables support for 18 GPIOs found
-         on Analog Devices ADP5588 GPIO Expanders.
-
-config GPIO_ADP5588_IRQ
-       bool "Interrupt controller support for ADP5588"
-       depends on GPIO_ADP5588=y
-       select GPIOLIB_IRQCHIP
-       help
-         Say yes here to enable the adp5588 to be used as an interrupt
-         controller. It requires the driver to be built in the kernel.
-
 config GPIO_ADNP
        tristate "Avionic Design N-bit GPIO expander"
        depends on OF_GPIO
index b67e29d..29e3beb 100644 (file)
@@ -25,7 +25,6 @@ obj-$(CONFIG_GPIO_74X164)             += gpio-74x164.o
 obj-$(CONFIG_GPIO_74XX_MMIO)           += gpio-74xx-mmio.o
 obj-$(CONFIG_GPIO_ADNP)                        += gpio-adnp.o
 obj-$(CONFIG_GPIO_ADP5520)             += gpio-adp5520.o
-obj-$(CONFIG_GPIO_ADP5588)             += gpio-adp5588.o
 obj-$(CONFIG_GPIO_AGGREGATOR)          += gpio-aggregator.o
 obj-$(CONFIG_GPIO_ALTERA_A10SR)                += gpio-altera-a10sr.o
 obj-$(CONFIG_GPIO_ALTERA)              += gpio-altera.o
diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c
deleted file mode 100644 (file)
index 9b562db..0000000
+++ /dev/null
@@ -1,446 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * GPIO Chip driver for Analog Devices
- * ADP5588/ADP5587 I/O Expander and QWERTY Keypad Controller
- *
- * Copyright 2009-2010 Analog Devices Inc.
- */
-
-#include <linux/gpio/driver.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/mod_devicetable.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#include <linux/platform_data/adp5588.h>
-
-/*
- * Early pre 4.0 Silicon required to delay readout by at least 25ms,
- * since the Event Counter Register updated 25ms after the interrupt
- * asserted.
- */
-#define WA_DELAYED_READOUT_REVID(rev)  ((rev) < 4)
-
-struct adp5588_gpio {
-       struct i2c_client *client;
-       struct gpio_chip gpio_chip;
-       struct mutex lock;      /* protect cached dir, dat_out */
-       /* protect serialized access to the interrupt controller bus */
-       struct mutex irq_lock;
-       uint8_t dat_out[3];
-       uint8_t dir[3];
-       uint8_t int_lvl_low[3];
-       uint8_t int_lvl_high[3];
-       uint8_t int_en[3];
-       uint8_t irq_mask[3];
-       uint8_t int_input_en[3];
-};
-
-static int adp5588_gpio_read(struct i2c_client *client, u8 reg)
-{
-       int ret = i2c_smbus_read_byte_data(client, reg);
-
-       if (ret < 0)
-               dev_err(&client->dev, "Read Error\n");
-
-       return ret;
-}
-
-static int adp5588_gpio_write(struct i2c_client *client, u8 reg, u8 val)
-{
-       int ret = i2c_smbus_write_byte_data(client, reg, val);
-
-       if (ret < 0)
-               dev_err(&client->dev, "Write Error\n");
-
-       return ret;
-}
-
-static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
-{
-       struct adp5588_gpio *dev = gpiochip_get_data(chip);
-       unsigned bank = ADP5588_BANK(off);
-       unsigned bit = ADP5588_BIT(off);
-       int val;
-
-       mutex_lock(&dev->lock);
-
-       if (dev->dir[bank] & bit)
-               val = dev->dat_out[bank];
-       else
-               val = adp5588_gpio_read(dev->client, GPIO_DAT_STAT1 + bank);
-
-       mutex_unlock(&dev->lock);
-
-       return !!(val & bit);
-}
-
-static void adp5588_gpio_set_value(struct gpio_chip *chip,
-                                  unsigned off, int val)
-{
-       unsigned bank, bit;
-       struct adp5588_gpio *dev = gpiochip_get_data(chip);
-
-       bank = ADP5588_BANK(off);
-       bit = ADP5588_BIT(off);
-
-       mutex_lock(&dev->lock);
-       if (val)
-               dev->dat_out[bank] |= bit;
-       else
-               dev->dat_out[bank] &= ~bit;
-
-       adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank,
-                          dev->dat_out[bank]);
-       mutex_unlock(&dev->lock);
-}
-
-static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off)
-{
-       int ret;
-       unsigned bank;
-       struct adp5588_gpio *dev = gpiochip_get_data(chip);
-
-       bank = ADP5588_BANK(off);
-
-       mutex_lock(&dev->lock);
-       dev->dir[bank] &= ~ADP5588_BIT(off);
-       ret = adp5588_gpio_write(dev->client, GPIO_DIR1 + bank, dev->dir[bank]);
-       mutex_unlock(&dev->lock);
-
-       return ret;
-}
-
-static int adp5588_gpio_direction_output(struct gpio_chip *chip,
-                                        unsigned off, int val)
-{
-       int ret;
-       unsigned bank, bit;
-       struct adp5588_gpio *dev = gpiochip_get_data(chip);
-
-       bank = ADP5588_BANK(off);
-       bit = ADP5588_BIT(off);
-
-       mutex_lock(&dev->lock);
-       dev->dir[bank] |= bit;
-
-       if (val)
-               dev->dat_out[bank] |= bit;
-       else
-               dev->dat_out[bank] &= ~bit;
-
-       ret = adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank,
-                                dev->dat_out[bank]);
-       ret |= adp5588_gpio_write(dev->client, GPIO_DIR1 + bank,
-                                dev->dir[bank]);
-       mutex_unlock(&dev->lock);
-
-       return ret;
-}
-
-#ifdef CONFIG_GPIO_ADP5588_IRQ
-
-static void adp5588_irq_bus_lock(struct irq_data *d)
-{
-       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-       struct adp5588_gpio *dev = gpiochip_get_data(gc);
-
-       mutex_lock(&dev->irq_lock);
-}
-
- /*
-  * genirq core code can issue chip->mask/unmask from atomic context.
-  * This doesn't work for slow busses where an access needs to sleep.
-  * bus_sync_unlock() is therefore called outside the atomic context,
-  * syncs the current irq mask state with the slow external controller
-  * and unlocks the bus.
-  */
-
-static void adp5588_irq_bus_sync_unlock(struct irq_data *d)
-{
-       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-       struct adp5588_gpio *dev = gpiochip_get_data(gc);
-       int i;
-
-       for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) {
-               if (dev->int_input_en[i]) {
-                       mutex_lock(&dev->lock);
-                       dev->dir[i] &= ~dev->int_input_en[i];
-                       dev->int_input_en[i] = 0;
-                       adp5588_gpio_write(dev->client, GPIO_DIR1 + i,
-                                          dev->dir[i]);
-                       mutex_unlock(&dev->lock);
-               }
-
-               if (dev->int_en[i] ^ dev->irq_mask[i]) {
-                       dev->int_en[i] = dev->irq_mask[i];
-                       adp5588_gpio_write(dev->client, GPI_EM1 + i,
-                                          dev->int_en[i]);
-               }
-       }
-
-       mutex_unlock(&dev->irq_lock);
-}
-
-static void adp5588_irq_mask(struct irq_data *d)
-{
-       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-       struct adp5588_gpio *dev = gpiochip_get_data(gc);
-
-       dev->irq_mask[ADP5588_BANK(d->hwirq)] &= ~ADP5588_BIT(d->hwirq);
-}
-
-static void adp5588_irq_unmask(struct irq_data *d)
-{
-       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-       struct adp5588_gpio *dev = gpiochip_get_data(gc);
-
-       dev->irq_mask[ADP5588_BANK(d->hwirq)] |= ADP5588_BIT(d->hwirq);
-}
-
-static int adp5588_irq_set_type(struct irq_data *d, unsigned int type)
-{
-       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-       struct adp5588_gpio *dev = gpiochip_get_data(gc);
-       uint16_t gpio = d->hwirq;
-       unsigned bank, bit;
-
-       bank = ADP5588_BANK(gpio);
-       bit = ADP5588_BIT(gpio);
-
-       dev->int_lvl_low[bank] &= ~bit;
-       dev->int_lvl_high[bank] &= ~bit;
-
-       if (type & IRQ_TYPE_EDGE_BOTH || type & IRQ_TYPE_LEVEL_HIGH)
-               dev->int_lvl_high[bank] |= bit;
-
-       if (type & IRQ_TYPE_EDGE_BOTH || type & IRQ_TYPE_LEVEL_LOW)
-               dev->int_lvl_low[bank] |= bit;
-
-       dev->int_input_en[bank] |= bit;
-
-       return 0;
-}
-
-static struct irq_chip adp5588_irq_chip = {
-       .name                   = "adp5588",
-       .irq_mask               = adp5588_irq_mask,
-       .irq_unmask             = adp5588_irq_unmask,
-       .irq_bus_lock           = adp5588_irq_bus_lock,
-       .irq_bus_sync_unlock    = adp5588_irq_bus_sync_unlock,
-       .irq_set_type           = adp5588_irq_set_type,
-};
-
-static irqreturn_t adp5588_irq_handler(int irq, void *devid)
-{
-       struct adp5588_gpio *dev = devid;
-       int status = adp5588_gpio_read(dev->client, INT_STAT);
-
-       if (status & ADP5588_KE_INT) {
-               int ev_cnt = adp5588_gpio_read(dev->client, KEY_LCK_EC_STAT);
-
-               if (ev_cnt > 0) {
-                       int i;
-
-                       for (i = 0; i < (ev_cnt & ADP5588_KEC); i++) {
-                               int key = adp5588_gpio_read(dev->client,
-                                                           Key_EVENTA + i);
-                               /* GPIN events begin at 97,
-                                * bit 7 indicates logic level
-                                */
-                               int gpio = (key & 0x7f) - 97;
-                               int lvl = key & (1 << 7);
-                               int bank = ADP5588_BANK(gpio);
-                               int bit = ADP5588_BIT(gpio);
-
-                               if ((lvl && dev->int_lvl_high[bank] & bit) ||
-                                   (!lvl && dev->int_lvl_low[bank] & bit))
-                                       handle_nested_irq(irq_find_mapping(
-                                             dev->gpio_chip.irq.domain, gpio));
-                       }
-               }
-       }
-
-       adp5588_gpio_write(dev->client, INT_STAT, status); /* Status is W1C */
-
-       return IRQ_HANDLED;
-}
-
-
-static int adp5588_irq_init_hw(struct gpio_chip *gc)
-{
-       struct adp5588_gpio *dev = gpiochip_get_data(gc);
-       /* Enable IRQs after registering chip */
-       adp5588_gpio_write(dev->client, CFG,
-                          ADP5588_AUTO_INC | ADP5588_INT_CFG | ADP5588_KE_IEN);
-
-       return 0;
-}
-
-static int adp5588_irq_setup(struct adp5588_gpio *dev)
-{
-       struct i2c_client *client = dev->client;
-       int ret;
-       struct adp5588_gpio_platform_data *pdata =
-                       dev_get_platdata(&client->dev);
-       struct gpio_irq_chip *girq;
-
-       adp5588_gpio_write(client, CFG, ADP5588_AUTO_INC);
-       adp5588_gpio_write(client, INT_STAT, -1); /* status is W1C */
-
-       mutex_init(&dev->irq_lock);
-
-       ret = devm_request_threaded_irq(&client->dev, client->irq,
-                                       NULL, adp5588_irq_handler, IRQF_ONESHOT
-                                       | IRQF_TRIGGER_FALLING | IRQF_SHARED,
-                                       dev_name(&client->dev), dev);
-       if (ret) {
-               dev_err(&client->dev, "failed to request irq %d\n",
-                       client->irq);
-               return ret;
-       }
-
-       /* This will be registered in the call to devm_gpiochip_add_data() */
-       girq = &dev->gpio_chip.irq;
-       girq->chip = &adp5588_irq_chip;
-       /* This will let us handle the parent IRQ in the driver */
-       girq->parent_handler = NULL;
-       girq->num_parents = 0;
-       girq->parents = NULL;
-       girq->first = pdata ? pdata->irq_base : 0;
-       girq->default_type = IRQ_TYPE_NONE;
-       girq->handler = handle_simple_irq;
-       girq->init_hw = adp5588_irq_init_hw;
-       girq->threaded = true;
-
-       return 0;
-}
-
-#else
-static int adp5588_irq_setup(struct adp5588_gpio *dev)
-{
-       struct i2c_client *client = dev->client;
-       dev_warn(&client->dev, "interrupt support not compiled in\n");
-
-       return 0;
-}
-
-#endif /* CONFIG_GPIO_ADP5588_IRQ */
-
-static int adp5588_gpio_probe(struct i2c_client *client)
-{
-       struct adp5588_gpio_platform_data *pdata =
-                       dev_get_platdata(&client->dev);
-       struct adp5588_gpio *dev;
-       struct gpio_chip *gc;
-       int ret, i, revid;
-       unsigned int pullup_dis_mask = 0;
-
-       if (!i2c_check_functionality(client->adapter,
-                                       I2C_FUNC_SMBUS_BYTE_DATA)) {
-               dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
-               return -EIO;
-       }
-
-       dev = devm_kzalloc(&client->dev, sizeof(*dev), GFP_KERNEL);
-       if (!dev)
-               return -ENOMEM;
-
-       dev->client = client;
-
-       gc = &dev->gpio_chip;
-       gc->direction_input = adp5588_gpio_direction_input;
-       gc->direction_output = adp5588_gpio_direction_output;
-       gc->get = adp5588_gpio_get_value;
-       gc->set = adp5588_gpio_set_value;
-       gc->can_sleep = true;
-       gc->base = -1;
-       gc->parent = &client->dev;
-
-       if (pdata) {
-               gc->base = pdata->gpio_start;
-               gc->names = pdata->names;
-               pullup_dis_mask = pdata->pullup_dis_mask;
-       }
-
-       gc->ngpio = ADP5588_MAXGPIO;
-       gc->label = client->name;
-       gc->owner = THIS_MODULE;
-
-       mutex_init(&dev->lock);
-
-       ret = adp5588_gpio_read(dev->client, DEV_ID);
-       if (ret < 0)
-               return ret;
-
-       revid = ret & ADP5588_DEVICE_ID_MASK;
-
-       for (i = 0, ret = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) {
-               dev->dat_out[i] = adp5588_gpio_read(client, GPIO_DAT_OUT1 + i);
-               dev->dir[i] = adp5588_gpio_read(client, GPIO_DIR1 + i);
-               ret |= adp5588_gpio_write(client, KP_GPIO1 + i, 0);
-               ret |= adp5588_gpio_write(client, GPIO_PULL1 + i,
-                               (pullup_dis_mask >> (8 * i)) & 0xFF);
-               ret |= adp5588_gpio_write(client, GPIO_INT_EN1 + i, 0);
-               if (ret)
-                       return ret;
-       }
-
-       if (client->irq) {
-               if (WA_DELAYED_READOUT_REVID(revid)) {
-                       dev_warn(&client->dev, "GPIO int not supported\n");
-               } else {
-                       ret = adp5588_irq_setup(dev);
-                       if (ret)
-                               return ret;
-               }
-       }
-
-       ret = devm_gpiochip_add_data(&client->dev, &dev->gpio_chip, dev);
-       if (ret)
-               return ret;
-
-       i2c_set_clientdata(client, dev);
-
-       return 0;
-}
-
-static void adp5588_gpio_remove(struct i2c_client *client)
-{
-       struct adp5588_gpio *dev = i2c_get_clientdata(client);
-
-       if (dev->client->irq)
-               free_irq(dev->client->irq, dev);
-}
-
-static const struct i2c_device_id adp5588_gpio_id[] = {
-       { "adp5588-gpio" },
-       {}
-};
-MODULE_DEVICE_TABLE(i2c, adp5588_gpio_id);
-
-static const struct of_device_id adp5588_gpio_of_id[] = {
-       { .compatible = "adi,adp5588-gpio" },
-       {}
-};
-MODULE_DEVICE_TABLE(of, adp5588_gpio_of_id);
-
-static struct i2c_driver adp5588_gpio_driver = {
-       .driver = {
-               .name = "adp5588-gpio",
-               .of_match_table = adp5588_gpio_of_id,
-       },
-       .probe_new = adp5588_gpio_probe,
-       .remove = adp5588_gpio_remove,
-       .id_table = adp5588_gpio_id,
-};
-
-module_i2c_driver(adp5588_gpio_driver);
-
-MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
-MODULE_DESCRIPTION("GPIO ADP5588 Driver");
-MODULE_LICENSE("GPL");
index 81e7e40..2ca6ab6 100644 (file)
@@ -1014,7 +1014,8 @@ static const char *absolutes[ABS_CNT] = {
        [ABS_HAT3Y] = "Hat 3Y",         [ABS_PRESSURE] = "Pressure",
        [ABS_DISTANCE] = "Distance",    [ABS_TILT_X] = "XTilt",
        [ABS_TILT_Y] = "YTilt",         [ABS_TOOL_WIDTH] = "ToolWidth",
-       [ABS_VOLUME] = "Volume",        [ABS_MISC] = "Misc",
+       [ABS_VOLUME] = "Volume",        [ABS_PROFILE] = "Profile",
+       [ABS_MISC] = "Misc",
        [ABS_MT_TOUCH_MAJOR] = "MTMajor",
        [ABS_MT_TOUCH_MINOR] = "MTMinor",
        [ABS_MT_WIDTH_MAJOR] = "MTMajorW",
index fa8d1a4..16231fe 100644 (file)
@@ -6,9 +6,6 @@
  *  Copyright (c) 2006 Dmitry Torokhov <dtor@mail.ru>
  */
 
-/*
- */
-
 /* #define DEBUG */
 
 #include <linux/input.h>
index 8229a90..c321cda 100644 (file)
@@ -6,9 +6,6 @@
  *  Copyright (c) 2006 Dmitry Torokhov <dtor@mail.ru>
  */
 
-/*
- */
-
 /* #define DEBUG */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index 11bbd1e..76ce41e 100644 (file)
@@ -7,9 +7,6 @@
  * EMU10k1 - SB Live / Audigy - gameport driver for Linux
  */
 
-/*
- */
-
 #include <asm/io.h>
 
 #include <linux/module.h>
index 87eeb4b..2ce717b 100644 (file)
@@ -7,9 +7,6 @@
  * PDPI Lightning 4 gamecard driver for Linux.
  */
 
-/*
- */
-
 #include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
index 2f80b7f..91a8cd3 100644 (file)
@@ -8,9 +8,6 @@
  * NS558 based standard IBM game port driver for Linux
  */
 
-/*
- */
-
 #include <asm/io.h>
 
 #include <linux/module.h>
index b45ddb4..5824bca 100644 (file)
@@ -746,7 +746,7 @@ static void joydev_cleanup(struct joydev *joydev)
 }
 
 /*
- * These codes are copied from from hid-ids.h, unfortunately there is no common
+ * These codes are copied from hid-ids.h, unfortunately there is no common
  * usb_ids/bt_ids.h header.
  */
 #define USB_VENDOR_ID_SONY                     0x054c
index 68475fa..fd1827b 100644 (file)
@@ -7,9 +7,6 @@
  * FP-Gaming Assassin 3D joystick driver for Linux
  */
 
-/*
- */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index e0cfdc8..c0deff5 100644 (file)
@@ -26,8 +26,23 @@ struct adc_joystick {
        struct adc_joystick_axis *axes;
        struct iio_channel *chans;
        int num_chans;
+       bool polled;
 };
 
+static void adc_joystick_poll(struct input_dev *input)
+{
+       struct adc_joystick *joy = input_get_drvdata(input);
+       int i, val, ret;
+
+       for (i = 0; i < joy->num_chans; i++) {
+               ret = iio_read_channel_raw(&joy->chans[i], &val);
+               if (ret < 0)
+                       return;
+               input_report_abs(input, joy->axes[i].code, val);
+       }
+       input_sync(input);
+}
+
 static int adc_joystick_handle(const void *data, void *private)
 {
        struct adc_joystick *joy = private;
@@ -179,6 +194,7 @@ static int adc_joystick_probe(struct platform_device *pdev)
        int error;
        int bits;
        int i;
+       unsigned int poll_interval;
 
        joy = devm_kzalloc(dev, sizeof(*joy), GFP_KERNEL);
        if (!joy)
@@ -192,8 +208,25 @@ static int adc_joystick_probe(struct platform_device *pdev)
                return error;
        }
 
-       /* Count how many channels we got. NULL terminated. */
+       error = device_property_read_u32(dev, "poll-interval", &poll_interval);
+       if (error) {
+               /* -EINVAL means the property is absent. */
+               if (error != -EINVAL)
+                       return error;
+       } else if (poll_interval == 0) {
+               dev_err(dev, "Unable to get poll-interval\n");
+               return -EINVAL;
+       } else {
+               joy->polled = true;
+       }
+
+       /*
+        * Count how many channels we got. NULL terminated.
+        * Do not check the storage size if using polling.
+        */
        for (i = 0; joy->chans[i].indio_dev; i++) {
+               if (joy->polled)
+                       continue;
                bits = joy->chans[i].channel->scan_type.storagebits;
                if (!bits || bits > 16) {
                        dev_err(dev, "Unsupported channel storage size\n");
@@ -215,23 +248,31 @@ static int adc_joystick_probe(struct platform_device *pdev)
        joy->input = input;
        input->name = pdev->name;
        input->id.bustype = BUS_HOST;
-       input->open = adc_joystick_open;
-       input->close = adc_joystick_close;
 
        error = adc_joystick_set_axes(dev, joy);
        if (error)
                return error;
 
-       joy->buffer = iio_channel_get_all_cb(dev, adc_joystick_handle, joy);
-       if (IS_ERR(joy->buffer)) {
-               dev_err(dev, "Unable to allocate callback buffer\n");
-               return PTR_ERR(joy->buffer);
-       }
+       if (joy->polled) {
+               input_setup_polling(input, adc_joystick_poll);
+               input_set_poll_interval(input, poll_interval);
+       } else {
+               input->open = adc_joystick_open;
+               input->close = adc_joystick_close;
+
+               joy->buffer = iio_channel_get_all_cb(dev, adc_joystick_handle,
+                                                    joy);
+               if (IS_ERR(joy->buffer)) {
+                       dev_err(dev, "Unable to allocate callback buffer\n");
+                       return PTR_ERR(joy->buffer);
+               }
 
-       error = devm_add_action_or_reset(dev, adc_joystick_cleanup, joy->buffer);
-       if (error)  {
-               dev_err(dev, "Unable to add action\n");
-               return error;
+               error = devm_add_action_or_reset(dev, adc_joystick_cleanup,
+                                                joy->buffer);
+               if (error)  {
+                       dev_err(dev, "Unable to add action\n");
+                       return error;
+               }
        }
 
        input_set_drvdata(input, joy);
index e10d57b..f1a720b 100644 (file)
@@ -7,9 +7,6 @@
  * Logitech ADI joystick family driver for Linux
  */
 
-/*
- */
-
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
index 12456a1..3752dc2 100644 (file)
@@ -7,9 +7,6 @@
  * Driver for Amiga joysticks for Linux/m68k
  */
 
-/*
- */
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
index 3088c5b..0c9e172 100644 (file)
@@ -7,9 +7,6 @@
  * Analog joystick and gamepad driver for Linux
  */
 
-/*
- */
-
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
index 41e1936..7ff78c9 100644 (file)
@@ -7,9 +7,6 @@
  * Creative Labs Blaster GamePad Cobra driver for Linux
  */
 
-/*
- */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index 434d265..4fba28b 100644 (file)
@@ -10,9 +10,6 @@
  * Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver for Linux
  */
 
-/*
- */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/delay.h>
index d37645e..41d5dac 100644 (file)
@@ -11,9 +11,6 @@
  *     Raphael Assenat
  */
 
-/*
- */
-
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/kernel.h>
index 920feba..abefbd1 100644 (file)
@@ -7,9 +7,6 @@
  * Genius Flight 2000 joystick driver for Linux
  */
 
-/*
- */
-
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
index fe798bc..0e86b26 100644 (file)
@@ -7,9 +7,6 @@
  * Gravis/Kensington GrIP protocol joystick and gamepad driver for Linux
  */
 
-/*
- */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index 8eeacdb..205eb6f 100644 (file)
@@ -7,9 +7,6 @@
  * Guillemot Digital Interface Protocol driver for Linux
  */
 
-/*
- */
-
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/module.h>
index ca22d84..03a9f08 100644 (file)
@@ -10,9 +10,6 @@
  * InterAct digital gamepad/joystick driver for Linux
  */
 
-/*
- */
-
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/module.h>
index 70f63f9..865652a 100644 (file)
@@ -8,9 +8,6 @@
  * out of the joystick port into the syslog ...
  */
 
-/*
- */
-
 #include <linux/module.h>
 #include <linux/gameport.h>
 #include <linux/kernel.h>
index edb8e19..017ef8c 100644 (file)
@@ -7,9 +7,6 @@
  * Magellan and Space Mouse 6dof controller driver for Linux
  */
 
-/*
- */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index 8e9672d..7282301 100644 (file)
@@ -7,9 +7,6 @@
  * Microsoft SideWinder joystick family driver for Linux
  */
 
-/*
- */
-
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
index a85a4f3..fa8ec53 100644 (file)
@@ -11,9 +11,6 @@
  * SpaceTec SpaceBall 2003/3003/4000 FLX driver for Linux
  */
 
-/*
- */
-
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/module.h>
index 5571714..dbbc69f 100644 (file)
@@ -10,9 +10,6 @@
  * SpaceTec SpaceOrb 360 and Avenger 6dof controller driver for Linux
  */
 
-/*
- */
-
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/module.h>
index c20425f..530de46 100644 (file)
@@ -8,9 +8,6 @@
  * Gravis Stinger gamepad driver for Linux
  */
 
-/*
- */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index 7416de8..93562ec 100644 (file)
@@ -10,9 +10,6 @@
  * ThrustMaster DirectConnect (BSP) joystick family driver for Linux
  */
 
-/*
- */
-
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
index dfe7a2c..dfb9c68 100644 (file)
@@ -10,9 +10,6 @@
  * TurboGraFX parallel port interface driver for Linux.
  */
 
-/*
- */
-
 #include <linux/kernel.h>
 #include <linux/parport.h>
 #include <linux/input.h>
index 174c69a..9b6792a 100644 (file)
@@ -32,9 +32,6 @@
  * Arndt Schoenewald <arndt@quelltext.com>
  */
 
-/*
- */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index 42bdbc2..f66bddf 100644 (file)
@@ -7,9 +7,6 @@
  * Logitech WingMan Warrior joystick driver for Linux
  */
 
-/*
- */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index 18190b5..2959d80 100644 (file)
@@ -61,6 +61,7 @@
  * Later changes can be tracked in SCM.
  */
 
+#include <linux/bits.h>
 #include <linux/kernel.h>
 #include <linux/input.h>
 #include <linux/rcupdate.h>
@@ -80,6 +81,9 @@
 #define MAP_TRIGGERS_TO_BUTTONS                (1 << 1)
 #define MAP_STICKS_TO_NULL             (1 << 2)
 #define MAP_SELECT_BUTTON              (1 << 3)
+#define MAP_PADDLES                    (1 << 4)
+#define MAP_PROFILE_BUTTON             (1 << 5)
+
 #define DANCEPAD_MAP_CONFIG    (MAP_DPAD_TO_BUTTONS |                  \
                                MAP_TRIGGERS_TO_BUTTONS | MAP_STICKS_TO_NULL)
 
 #define XTYPE_XBOXONE     3
 #define XTYPE_UNKNOWN     4
 
+/* Send power-off packet to xpad360w after holding the mode button for this many
+ * seconds
+ */
+#define XPAD360W_POWEROFF_TIMEOUT 5
+
+#define PKT_XB              0
+#define PKT_XBE1            1
+#define PKT_XBE2_FW_OLD     2
+#define PKT_XBE2_FW_5_EARLY 3
+#define PKT_XBE2_FW_5_11    4
+
 static bool dpad_to_buttons;
 module_param(dpad_to_buttons, bool, S_IRUGO);
 MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads");
@@ -111,8 +126,11 @@ static const struct xpad_device {
        char *name;
        u8 mapping;
        u8 xtype;
+       u8 packet_type;
 } xpad_device[] = {
        { 0x0079, 0x18d4, "GPD Win 2 X-Box Controller", 0, XTYPE_XBOX360 },
+       { 0x03eb, 0xff01, "Wooting One (Legacy)", 0, XTYPE_XBOX360 },
+       { 0x03eb, 0xff02, "Wooting Two (Legacy)", 0, XTYPE_XBOX360 },
        { 0x044f, 0x0f00, "Thrustmaster Wheel", 0, XTYPE_XBOX },
        { 0x044f, 0x0f03, "Thrustmaster Wheel", 0, XTYPE_XBOX },
        { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX },
@@ -128,9 +146,11 @@ static const struct xpad_device {
        { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
        { 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE },
        { 0x045e, 0x02dd, "Microsoft X-Box One pad (Firmware 2015)", 0, XTYPE_XBOXONE },
-       { 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", 0, XTYPE_XBOXONE },
+       { 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", MAP_PADDLES, XTYPE_XBOXONE },
+       { 0x045e, 0x0b00, "Microsoft X-Box One Elite 2 pad", MAP_PADDLES, XTYPE_XBOXONE },
        { 0x045e, 0x02ea, "Microsoft X-Box One S pad", 0, XTYPE_XBOXONE },
        { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
+       { 0x045e, 0x0b0a, "Microsoft X-Box Adaptive Controller", MAP_PROFILE_BUTTON, XTYPE_XBOXONE },
        { 0x045e, 0x0b12, "Microsoft Xbox Series S|X Controller", MAP_SELECT_BUTTON, XTYPE_XBOXONE },
        { 0x046d, 0xc21d, "Logitech Gamepad F310", 0, XTYPE_XBOX360 },
        { 0x046d, 0xc21e, "Logitech Gamepad F510", 0, XTYPE_XBOX360 },
@@ -244,6 +264,7 @@ static const struct xpad_device {
        { 0x0f0d, 0x0063, "Hori Real Arcade Pro Hayabusa (USA) Xbox One", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE },
        { 0x0f0d, 0x0067, "HORIPAD ONE", 0, XTYPE_XBOXONE },
        { 0x0f0d, 0x0078, "Hori Real Arcade Pro V Kai Xbox One", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE },
+       { 0x0f0d, 0x00c5, "Hori Fighting Commander ONE", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE },
        { 0x0f30, 0x010b, "Philips Recoil", 0, XTYPE_XBOX },
        { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX },
        { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX },
@@ -260,6 +281,7 @@ static const struct xpad_device {
        { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
        { 0x1430, 0xf801, "RedOctane Controller", 0, XTYPE_XBOX360 },
        { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 },
+       { 0x146b, 0x0604, "Bigben Interactive DAIJA Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x1532, 0x0037, "Razer Sabertooth", 0, XTYPE_XBOX360 },
        { 0x1532, 0x0a00, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE },
        { 0x1532, 0x0a03, "Razer Wildcat", 0, XTYPE_XBOXONE },
@@ -325,6 +347,7 @@ static const struct xpad_device {
        { 0x24c6, 0x5502, "Hori Fighting Stick VX Alt", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x24c6, 0x5503, "Hori Fighting Edge", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x24c6, 0x5506, "Hori SOULCALIBUR V Stick", 0, XTYPE_XBOX360 },
+       { 0x24c6, 0x5510, "Hori Fighting Commander ONE (Xbox 360/PC Mode)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x24c6, 0x550d, "Hori GEM Xbox controller", 0, XTYPE_XBOX360 },
        { 0x24c6, 0x550e, "Hori Real Arcade Pro V Kai 360", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x24c6, 0x551a, "PowerA FUSION Pro Controller", 0, XTYPE_XBOXONE },
@@ -334,6 +357,14 @@ static const struct xpad_device {
        { 0x24c6, 0x5b03, "Thrustmaster Ferrari 458 Racing Wheel", 0, XTYPE_XBOX360 },
        { 0x24c6, 0x5d04, "Razer Sabertooth", 0, XTYPE_XBOX360 },
        { 0x24c6, 0xfafe, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
+       { 0x2563, 0x058d, "OneXPlayer Gamepad", 0, XTYPE_XBOX360 },
+       { 0x2dc8, 0x2000, "8BitDo Pro 2 Wired Controller fox Xbox", 0, XTYPE_XBOXONE },
+       { 0x31e3, 0x1100, "Wooting One", 0, XTYPE_XBOX360 },
+       { 0x31e3, 0x1200, "Wooting Two", 0, XTYPE_XBOX360 },
+       { 0x31e3, 0x1210, "Wooting Lekker", 0, XTYPE_XBOX360 },
+       { 0x31e3, 0x1220, "Wooting Two HE", 0, XTYPE_XBOX360 },
+       { 0x31e3, 0x1300, "Wooting 60HE (AVR)", 0, XTYPE_XBOX360 },
+       { 0x31e3, 0x1310, "Wooting 60HE (ARM)", 0, XTYPE_XBOX360 },
        { 0x3285, 0x0607, "Nacon GC-100", 0, XTYPE_XBOX360 },
        { 0x3767, 0x0101, "Fanatec Speedster 3 Forceshock Wheel", 0, XTYPE_XBOX },
        { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX },
@@ -390,6 +421,13 @@ static const signed short xpad_abs_triggers[] = {
        -1
 };
 
+/* used when the controller has extra paddle buttons */
+static const signed short xpad_btn_paddles[] = {
+       BTN_TRIGGER_HAPPY5, BTN_TRIGGER_HAPPY6, /* paddle upper right, lower right */
+       BTN_TRIGGER_HAPPY7, BTN_TRIGGER_HAPPY8, /* paddle upper left, lower left */
+       -1                                              /* terminating entry */
+};
+
 /*
  * Xbox 360 has a vendor-specific class, so we cannot match it with only
  * USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we
@@ -419,6 +457,7 @@ static const signed short xpad_abs_triggers[] = {
 static const struct usb_device_id xpad_table[] = {
        { USB_INTERFACE_INFO('X', 'B', 0) },    /* X-Box USB-IF not approved class */
        XPAD_XBOX360_VENDOR(0x0079),            /* GPD Win 2 Controller */
+       XPAD_XBOX360_VENDOR(0x03eb),            /* Wooting Keyboards (Legacy) */
        XPAD_XBOX360_VENDOR(0x044f),            /* Thrustmaster X-Box 360 controllers */
        XPAD_XBOX360_VENDOR(0x045e),            /* Microsoft X-Box 360 controllers */
        XPAD_XBOXONE_VENDOR(0x045e),            /* Microsoft X-Box One controllers */
@@ -429,6 +468,7 @@ static const struct usb_device_id xpad_table[] = {
        { USB_DEVICE(0x0738, 0x4540) },         /* Mad Catz Beat Pad */
        XPAD_XBOXONE_VENDOR(0x0738),            /* Mad Catz FightStick TE 2 */
        XPAD_XBOX360_VENDOR(0x07ff),            /* Mad Catz GamePad */
+       XPAD_XBOX360_VENDOR(0x0c12),            /* Zeroplus X-Box 360 controllers */
        XPAD_XBOX360_VENDOR(0x0e6f),            /* 0x0e6f X-Box 360 controllers */
        XPAD_XBOXONE_VENDOR(0x0e6f),            /* 0x0e6f X-Box One controllers */
        XPAD_XBOX360_VENDOR(0x0f0d),            /* Hori Controllers */
@@ -450,8 +490,12 @@ static const struct usb_device_id xpad_table[] = {
        XPAD_XBOXONE_VENDOR(0x20d6),            /* PowerA Controllers */
        XPAD_XBOX360_VENDOR(0x24c6),            /* PowerA Controllers */
        XPAD_XBOXONE_VENDOR(0x24c6),            /* PowerA Controllers */
+       XPAD_XBOX360_VENDOR(0x2563),            /* OneXPlayer Gamepad */
+       XPAD_XBOX360_VENDOR(0x260d),            /* Dareu H101 */
+       XPAD_XBOXONE_VENDOR(0x2dc8),            /* 8BitDo Pro 2 Wired Controller for Xbox */
        XPAD_XBOXONE_VENDOR(0x2e24),            /* Hyperkin Duke X-Box One pad */
        XPAD_XBOX360_VENDOR(0x2f24),            /* GameSir Controllers */
+       XPAD_XBOX360_VENDOR(0x31e3),            /* Wooting Keyboards */
        XPAD_XBOX360_VENDOR(0x3285),            /* Nacon GC-100 */
        { }
 };
@@ -473,13 +517,52 @@ struct xboxone_init_packet {
                .len            = ARRAY_SIZE(_data),    \
        }
 
+/*
+ * starting with xbox one, the game input protocol is used
+ * magic numbers are taken from
+ * - https://github.com/xpadneo/gip-dissector/blob/main/src/gip-dissector.lua
+ * - https://github.com/medusalix/xone/blob/master/bus/protocol.c
+ */
+#define GIP_CMD_ACK      0x01
+#define GIP_CMD_IDENTIFY 0x04
+#define GIP_CMD_POWER    0x05
+#define GIP_CMD_AUTHENTICATE 0x06
+#define GIP_CMD_VIRTUAL_KEY  0x07
+#define GIP_CMD_RUMBLE   0x09
+#define GIP_CMD_LED      0x0a
+#define GIP_CMD_FIRMWARE 0x0c
+#define GIP_CMD_INPUT    0x20
+
+#define GIP_SEQ0 0x00
+
+#define GIP_OPT_ACK      0x10
+#define GIP_OPT_INTERNAL 0x20
+
+/*
+ * length of the command payload encoded with
+ * https://en.wikipedia.org/wiki/LEB128
+ * which is a no-op for N < 128
+ */
+#define GIP_PL_LEN(N) (N)
+
+/*
+ * payload specific defines
+ */
+#define GIP_PWR_ON 0x00
+#define GIP_LED_ON 0x01
+
+#define GIP_MOTOR_R  BIT(0)
+#define GIP_MOTOR_L  BIT(1)
+#define GIP_MOTOR_RT BIT(2)
+#define GIP_MOTOR_LT BIT(3)
+#define GIP_MOTOR_ALL (GIP_MOTOR_R | GIP_MOTOR_L | GIP_MOTOR_RT | GIP_MOTOR_LT)
 
 /*
  * This packet is required for all Xbox One pads with 2015
  * or later firmware installed (or present from the factory).
  */
-static const u8 xboxone_fw2015_init[] = {
-       0x05, 0x20, 0x00, 0x01, 0x00
+static const u8 xboxone_power_on[] = {
+       GIP_CMD_POWER, GIP_OPT_INTERNAL, GIP_SEQ0, GIP_PL_LEN(1), GIP_PWR_ON
 };
 
 /*
@@ -489,7 +572,16 @@ static const u8 xboxone_fw2015_init[] = {
  * Bluetooth mode.
  */
 static const u8 xboxone_s_init[] = {
-       0x05, 0x20, 0x00, 0x0f, 0x06
+       GIP_CMD_POWER, GIP_OPT_INTERNAL, GIP_SEQ0, 0x0f, 0x06
+};
+
+/*
+ * This packet is required to get additional input data
+ * from Xbox One Elite Series 2 (0x045e:0x0b00) pads.
+ * We mostly do this right now to get paddle data
+ */
+static const u8 extra_input_packet_init[] = {
+       0x4d, 0x10, 0x01, 0x02, 0x07, 0x00
 };
 
 /*
@@ -497,9 +589,9 @@ static const u8 xboxone_s_init[] = {
  * (0x0e6f:0x0165) to finish initialization and for Hori pads
  * (0x0f0d:0x0067) to make the analog sticks work.
  */
-static const u8 xboxone_hori_init[] = {
-       0x01, 0x20, 0x00, 0x09, 0x00, 0x04, 0x20, 0x3a,
-       0x00, 0x00, 0x00, 0x80, 0x00
+static const u8 xboxone_hori_ack_id[] = {
+       GIP_CMD_ACK, GIP_OPT_INTERNAL, GIP_SEQ0, GIP_PL_LEN(9),
+       0x00, GIP_CMD_IDENTIFY, GIP_OPT_INTERNAL, 0x3a, 0x00, 0x00, 0x00, 0x80, 0x00
 };
 
 /*
@@ -507,8 +599,8 @@ static const u8 xboxone_hori_init[] = {
  * sending input reports. These pads include: (0x0e6f:0x02ab),
  * (0x0e6f:0x02a4), (0x0e6f:0x02a6).
  */
-static const u8 xboxone_pdp_init1[] = {
-       0x0a, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14
+static const u8 xboxone_pdp_led_on[] = {
+       GIP_CMD_LED, GIP_OPT_INTERNAL, GIP_SEQ0, GIP_PL_LEN(3), 0x00, GIP_LED_ON, 0x14
 };
 
 /*
@@ -516,8 +608,8 @@ static const u8 xboxone_pdp_init1[] = {
  * sending input reports. These pads include: (0x0e6f:0x02ab),
  * (0x0e6f:0x02a4), (0x0e6f:0x02a6).
  */
-static const u8 xboxone_pdp_init2[] = {
-       0x06, 0x20, 0x00, 0x02, 0x01, 0x00
+static const u8 xboxone_pdp_auth[] = {
+       GIP_CMD_AUTHENTICATE, GIP_OPT_INTERNAL, GIP_SEQ0, GIP_PL_LEN(2), 0x01, 0x00
 };
 
 /*
@@ -525,8 +617,8 @@ static const u8 xboxone_pdp_init2[] = {
  * sending input reports. One of those pads is (0x24c6:0x543a).
  */
 static const u8 xboxone_rumblebegin_init[] = {
-       0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
-       0x1D, 0x1D, 0xFF, 0x00, 0x00
+       GIP_CMD_RUMBLE, 0x00, GIP_SEQ0, GIP_PL_LEN(9),
+       0x00, GIP_MOTOR_ALL, 0x00, 0x00, 0x1D, 0x1D, 0xFF, 0x00, 0x00
 };
 
 /*
@@ -536,8 +628,8 @@ static const u8 xboxone_rumblebegin_init[] = {
  * spin up to enough speed to actually vibrate the gamepad.
  */
 static const u8 xboxone_rumbleend_init[] = {
-       0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00
+       GIP_CMD_RUMBLE, 0x00, GIP_SEQ0, GIP_PL_LEN(9),
+       0x00, GIP_MOTOR_ALL, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
 /*
@@ -547,13 +639,14 @@ static const u8 xboxone_rumbleend_init[] = {
  * packet is going to be sent.
  */
 static const struct xboxone_init_packet xboxone_init_packets[] = {
-       XBOXONE_INIT_PKT(0x0e6f, 0x0165, xboxone_hori_init),
-       XBOXONE_INIT_PKT(0x0f0d, 0x0067, xboxone_hori_init),
-       XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_fw2015_init),
+       XBOXONE_INIT_PKT(0x0e6f, 0x0165, xboxone_hori_ack_id),
+       XBOXONE_INIT_PKT(0x0f0d, 0x0067, xboxone_hori_ack_id),
+       XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_power_on),
        XBOXONE_INIT_PKT(0x045e, 0x02ea, xboxone_s_init),
        XBOXONE_INIT_PKT(0x045e, 0x0b00, xboxone_s_init),
-       XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_init1),
-       XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_init2),
+       XBOXONE_INIT_PKT(0x045e, 0x0b00, extra_input_packet_init),
+       XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_led_on),
+       XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_auth),
        XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumblebegin_init),
        XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumblebegin_init),
        XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumblebegin_init),
@@ -608,14 +701,17 @@ struct usb_xpad {
 
        int mapping;                    /* map d-pad to buttons or to axes */
        int xtype;                      /* type of xbox device */
+       int packet_type;                /* type of the extended packet */
        int pad_nr;                     /* the order x360 pads were attached */
        const char *name;               /* name of the device */
        struct work_struct work;        /* init/remove device from callback */
+       time64_t mode_btn_down_ts;
 };
 
 static int xpad_init_input(struct usb_xpad *xpad);
 static void xpad_deinit_input(struct usb_xpad *xpad);
 static void xpadone_ack_mode_report(struct usb_xpad *xpad, u8 seq_num);
+static void xpad360w_poweroff_controller(struct usb_xpad *xpad);
 
 /*
  *     xpad_process_packet
@@ -656,10 +752,10 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
        /* digital pad */
        if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
                /* dpad as buttons (left, right, up, down) */
-               input_report_key(dev, BTN_TRIGGER_HAPPY1, data[2] & 0x04);
-               input_report_key(dev, BTN_TRIGGER_HAPPY2, data[2] & 0x08);
-               input_report_key(dev, BTN_TRIGGER_HAPPY3, data[2] & 0x01);
-               input_report_key(dev, BTN_TRIGGER_HAPPY4, data[2] & 0x02);
+               input_report_key(dev, BTN_TRIGGER_HAPPY1, data[2] & BIT(2));
+               input_report_key(dev, BTN_TRIGGER_HAPPY2, data[2] & BIT(3));
+               input_report_key(dev, BTN_TRIGGER_HAPPY3, data[2] & BIT(0));
+               input_report_key(dev, BTN_TRIGGER_HAPPY4, data[2] & BIT(1));
        } else {
                input_report_abs(dev, ABS_HAT0X,
                                 !!(data[2] & 0x08) - !!(data[2] & 0x04));
@@ -668,10 +764,10 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
        }
 
        /* start/back buttons and stick press left/right */
-       input_report_key(dev, BTN_START,  data[2] & 0x10);
-       input_report_key(dev, BTN_SELECT, data[2] & 0x20);
-       input_report_key(dev, BTN_THUMBL, data[2] & 0x40);
-       input_report_key(dev, BTN_THUMBR, data[2] & 0x80);
+       input_report_key(dev, BTN_START,  data[2] & BIT(4));
+       input_report_key(dev, BTN_SELECT, data[2] & BIT(5));
+       input_report_key(dev, BTN_THUMBL, data[2] & BIT(6));
+       input_report_key(dev, BTN_THUMBR, data[2] & BIT(7));
 
        /* "analog" buttons A, B, X, Y */
        input_report_key(dev, BTN_A, data[4]);
@@ -683,6 +779,10 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
        input_report_key(dev, BTN_C, data[8]);
        input_report_key(dev, BTN_Z, data[9]);
 
+       /* Profile button has a value of 0-3, so it is reported as an axis */
+       if (xpad->mapping & MAP_PROFILE_BUTTON)
+               input_report_abs(dev, ABS_PROFILE, data[34]);
+
        input_sync(dev);
 }
 
@@ -706,10 +806,10 @@ static void xpad360_process_packet(struct usb_xpad *xpad, struct input_dev *dev,
        /* digital pad */
        if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
                /* dpad as buttons (left, right, up, down) */
-               input_report_key(dev, BTN_TRIGGER_HAPPY1, data[2] & 0x04);
-               input_report_key(dev, BTN_TRIGGER_HAPPY2, data[2] & 0x08);
-               input_report_key(dev, BTN_TRIGGER_HAPPY3, data[2] & 0x01);
-               input_report_key(dev, BTN_TRIGGER_HAPPY4, data[2] & 0x02);
+               input_report_key(dev, BTN_TRIGGER_HAPPY1, data[2] & BIT(2));
+               input_report_key(dev, BTN_TRIGGER_HAPPY2, data[2] & BIT(3));
+               input_report_key(dev, BTN_TRIGGER_HAPPY3, data[2] & BIT(0));
+               input_report_key(dev, BTN_TRIGGER_HAPPY4, data[2] & BIT(1));
        }
 
        /*
@@ -727,21 +827,21 @@ static void xpad360_process_packet(struct usb_xpad *xpad, struct input_dev *dev,
        }
 
        /* start/back buttons */
-       input_report_key(dev, BTN_START,  data[2] & 0x10);
-       input_report_key(dev, BTN_SELECT, data[2] & 0x20);
+       input_report_key(dev, BTN_START,  data[2] & BIT(4));
+       input_report_key(dev, BTN_SELECT, data[2] & BIT(5));
 
        /* stick press left/right */
-       input_report_key(dev, BTN_THUMBL, data[2] & 0x40);
-       input_report_key(dev, BTN_THUMBR, data[2] & 0x80);
+       input_report_key(dev, BTN_THUMBL, data[2] & BIT(6));
+       input_report_key(dev, BTN_THUMBR, data[2] & BIT(7));
 
        /* buttons A,B,X,Y,TL,TR and MODE */
-       input_report_key(dev, BTN_A,    data[3] & 0x10);
-       input_report_key(dev, BTN_B,    data[3] & 0x20);
-       input_report_key(dev, BTN_X,    data[3] & 0x40);
-       input_report_key(dev, BTN_Y,    data[3] & 0x80);
-       input_report_key(dev, BTN_TL,   data[3] & 0x01);
-       input_report_key(dev, BTN_TR,   data[3] & 0x02);
-       input_report_key(dev, BTN_MODE, data[3] & 0x04);
+       input_report_key(dev, BTN_A,    data[3] & BIT(4));
+       input_report_key(dev, BTN_B,    data[3] & BIT(5));
+       input_report_key(dev, BTN_X,    data[3] & BIT(6));
+       input_report_key(dev, BTN_Y,    data[3] & BIT(7));
+       input_report_key(dev, BTN_TL,   data[3] & BIT(0));
+       input_report_key(dev, BTN_TR,   data[3] & BIT(1));
+       input_report_key(dev, BTN_MODE, data[3] & BIT(2));
 
        if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
                /* left stick */
@@ -767,6 +867,23 @@ static void xpad360_process_packet(struct usb_xpad *xpad, struct input_dev *dev,
        }
 
        input_sync(dev);
+
+       /* XBOX360W controllers can't be turned off without driver assistance */
+       if (xpad->xtype == XTYPE_XBOX360W) {
+               if (xpad->mode_btn_down_ts > 0 && xpad->pad_present &&
+                   ((ktime_get_seconds() - xpad->mode_btn_down_ts) >=
+                    XPAD360W_POWEROFF_TIMEOUT)) {
+                       xpad360w_poweroff_controller(xpad);
+                       xpad->mode_btn_down_ts = 0;
+                       return;
+               }
+
+               /* mode button down/up */
+               if (data[3] & BIT(2))
+                       xpad->mode_btn_down_ts = ktime_get_seconds();
+               else
+                       xpad->mode_btn_down_ts = 0;
+       }
 }
 
 static void xpad_presence_work(struct work_struct *work)
@@ -846,87 +963,154 @@ static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned cha
 static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
 {
        struct input_dev *dev = xpad->dev;
+       bool do_sync = false;
 
        /* the xbox button has its own special report */
-       if (data[0] == 0X07) {
+       if (data[0] == GIP_CMD_VIRTUAL_KEY) {
                /*
                 * The Xbox One S controller requires these reports to be
                 * acked otherwise it continues sending them forever and
                 * won't report further mode button events.
                 */
-               if (data[1] == 0x30)
+               if (data[1] == (GIP_OPT_ACK | GIP_OPT_INTERNAL))
                        xpadone_ack_mode_report(xpad, data[2]);
 
-               input_report_key(dev, BTN_MODE, data[4] & 0x01);
+               input_report_key(dev, BTN_MODE, data[4] & GENMASK(1, 0));
                input_sync(dev);
-               return;
-       }
-       /* check invalid packet */
-       else if (data[0] != 0X20)
-               return;
 
-       /* menu/view buttons */
-       input_report_key(dev, BTN_START,  data[4] & 0x04);
-       input_report_key(dev, BTN_SELECT, data[4] & 0x08);
-       if (xpad->mapping & MAP_SELECT_BUTTON)
-               input_report_key(dev, KEY_RECORD, data[22] & 0x01);
+               do_sync = true;
+       } else if (data[0] == GIP_CMD_FIRMWARE) {
+               /* Some packet formats force us to use this separate to poll paddle inputs */
+               if (xpad->packet_type == PKT_XBE2_FW_5_11) {
+                       /* Mute paddles if controller is in a custom profile slot
+                        * Checked by looking at the active profile slot to
+                        * verify it's the default slot
+                        */
+                       if (data[19] != 0)
+                               data[18] = 0;
 
-       /* buttons A,B,X,Y */
-       input_report_key(dev, BTN_A,    data[4] & 0x10);
-       input_report_key(dev, BTN_B,    data[4] & 0x20);
-       input_report_key(dev, BTN_X,    data[4] & 0x40);
-       input_report_key(dev, BTN_Y,    data[4] & 0x80);
+                       /* Elite Series 2 split packet paddle bits */
+                       input_report_key(dev, BTN_TRIGGER_HAPPY5, data[18] & BIT(0));
+                       input_report_key(dev, BTN_TRIGGER_HAPPY6, data[18] & BIT(1));
+                       input_report_key(dev, BTN_TRIGGER_HAPPY7, data[18] & BIT(2));
+                       input_report_key(dev, BTN_TRIGGER_HAPPY8, data[18] & BIT(3));
 
-       /* digital pad */
-       if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
-               /* dpad as buttons (left, right, up, down) */
-               input_report_key(dev, BTN_TRIGGER_HAPPY1, data[5] & 0x04);
-               input_report_key(dev, BTN_TRIGGER_HAPPY2, data[5] & 0x08);
-               input_report_key(dev, BTN_TRIGGER_HAPPY3, data[5] & 0x01);
-               input_report_key(dev, BTN_TRIGGER_HAPPY4, data[5] & 0x02);
-       } else {
-               input_report_abs(dev, ABS_HAT0X,
-                                !!(data[5] & 0x08) - !!(data[5] & 0x04));
-               input_report_abs(dev, ABS_HAT0Y,
-                                !!(data[5] & 0x02) - !!(data[5] & 0x01));
-       }
-
-       /* TL/TR */
-       input_report_key(dev, BTN_TL,   data[5] & 0x10);
-       input_report_key(dev, BTN_TR,   data[5] & 0x20);
+                       do_sync = true;
+               }
+       } else if (data[0] == GIP_CMD_INPUT) { /* The main valid packet type for inputs */
+               /* menu/view buttons */
+               input_report_key(dev, BTN_START,  data[4] & BIT(2));
+               input_report_key(dev, BTN_SELECT, data[4] & BIT(3));
+               if (xpad->mapping & MAP_SELECT_BUTTON)
+                       input_report_key(dev, KEY_RECORD, data[22] & BIT(0));
+
+               /* buttons A,B,X,Y */
+               input_report_key(dev, BTN_A,    data[4] & BIT(4));
+               input_report_key(dev, BTN_B,    data[4] & BIT(5));
+               input_report_key(dev, BTN_X,    data[4] & BIT(6));
+               input_report_key(dev, BTN_Y,    data[4] & BIT(7));
+
+               /* digital pad */
+               if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
+                       /* dpad as buttons (left, right, up, down) */
+                       input_report_key(dev, BTN_TRIGGER_HAPPY1, data[5] & BIT(2));
+                       input_report_key(dev, BTN_TRIGGER_HAPPY2, data[5] & BIT(3));
+                       input_report_key(dev, BTN_TRIGGER_HAPPY3, data[5] & BIT(0));
+                       input_report_key(dev, BTN_TRIGGER_HAPPY4, data[5] & BIT(1));
+               } else {
+                       input_report_abs(dev, ABS_HAT0X,
+                                       !!(data[5] & 0x08) - !!(data[5] & 0x04));
+                       input_report_abs(dev, ABS_HAT0Y,
+                                       !!(data[5] & 0x02) - !!(data[5] & 0x01));
+               }
 
-       /* stick press left/right */
-       input_report_key(dev, BTN_THUMBL, data[5] & 0x40);
-       input_report_key(dev, BTN_THUMBR, data[5] & 0x80);
+               /* TL/TR */
+               input_report_key(dev, BTN_TL,   data[5] & BIT(4));
+               input_report_key(dev, BTN_TR,   data[5] & BIT(5));
+
+               /* stick press left/right */
+               input_report_key(dev, BTN_THUMBL, data[5] & BIT(6));
+               input_report_key(dev, BTN_THUMBR, data[5] & BIT(7));
+
+               if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
+                       /* left stick */
+                       input_report_abs(dev, ABS_X,
+                                       (__s16) le16_to_cpup((__le16 *)(data + 10)));
+                       input_report_abs(dev, ABS_Y,
+                                       ~(__s16) le16_to_cpup((__le16 *)(data + 12)));
+
+                       /* right stick */
+                       input_report_abs(dev, ABS_RX,
+                                       (__s16) le16_to_cpup((__le16 *)(data + 14)));
+                       input_report_abs(dev, ABS_RY,
+                                       ~(__s16) le16_to_cpup((__le16 *)(data + 16)));
+               }
 
-       if (!(xpad->mapping & MAP_STICKS_TO_NULL)) {
-               /* left stick */
-               input_report_abs(dev, ABS_X,
-                                (__s16) le16_to_cpup((__le16 *)(data + 10)));
-               input_report_abs(dev, ABS_Y,
-                                ~(__s16) le16_to_cpup((__le16 *)(data + 12)));
+               /* triggers left/right */
+               if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
+                       input_report_key(dev, BTN_TL2,
+                                       (__u16) le16_to_cpup((__le16 *)(data + 6)));
+                       input_report_key(dev, BTN_TR2,
+                                       (__u16) le16_to_cpup((__le16 *)(data + 8)));
+               } else {
+                       input_report_abs(dev, ABS_Z,
+                                       (__u16) le16_to_cpup((__le16 *)(data + 6)));
+                       input_report_abs(dev, ABS_RZ,
+                                       (__u16) le16_to_cpup((__le16 *)(data + 8)));
+               }
 
-               /* right stick */
-               input_report_abs(dev, ABS_RX,
-                                (__s16) le16_to_cpup((__le16 *)(data + 14)));
-               input_report_abs(dev, ABS_RY,
-                                ~(__s16) le16_to_cpup((__le16 *)(data + 16)));
-       }
+               /* paddle handling */
+               /* based on SDL's SDL_hidapi_xboxone.c */
+               if (xpad->mapping & MAP_PADDLES) {
+                       if (xpad->packet_type == PKT_XBE1) {
+                               /* Mute paddles if controller has a custom mapping applied.
+                                * Checked by comparing the current mapping
+                                * config against the factory mapping config
+                                */
+                               if (memcmp(&data[4], &data[18], 2) != 0)
+                                       data[32] = 0;
+
+                               /* OG Elite Series Controller paddle bits */
+                               input_report_key(dev, BTN_TRIGGER_HAPPY5, data[32] & BIT(1));
+                               input_report_key(dev, BTN_TRIGGER_HAPPY6, data[32] & BIT(3));
+                               input_report_key(dev, BTN_TRIGGER_HAPPY7, data[32] & BIT(0));
+                               input_report_key(dev, BTN_TRIGGER_HAPPY8, data[32] & BIT(2));
+                       } else if (xpad->packet_type == PKT_XBE2_FW_OLD) {
+                               /* Mute paddles if controller has a custom mapping applied.
+                                * Checked by comparing the current mapping
+                                * config against the factory mapping config
+                                */
+                               if (data[19] != 0)
+                                       data[18] = 0;
+
+                               /* Elite Series 2 4.x firmware paddle bits */
+                               input_report_key(dev, BTN_TRIGGER_HAPPY5, data[18] & BIT(0));
+                               input_report_key(dev, BTN_TRIGGER_HAPPY6, data[18] & BIT(1));
+                               input_report_key(dev, BTN_TRIGGER_HAPPY7, data[18] & BIT(2));
+                               input_report_key(dev, BTN_TRIGGER_HAPPY8, data[18] & BIT(3));
+                       } else if (xpad->packet_type == PKT_XBE2_FW_5_EARLY) {
+                               /* Mute paddles if controller has a custom mapping applied.
+                                * Checked by comparing the current mapping
+                                * config against the factory mapping config
+                                */
+                               if (data[23] != 0)
+                                       data[22] = 0;
+
+                               /* Elite Series 2 5.x firmware paddle bits
+                                * (before the packet was split)
+                                */
+                               input_report_key(dev, BTN_TRIGGER_HAPPY5, data[22] & BIT(0));
+                               input_report_key(dev, BTN_TRIGGER_HAPPY6, data[22] & BIT(1));
+                               input_report_key(dev, BTN_TRIGGER_HAPPY7, data[22] & BIT(2));
+                               input_report_key(dev, BTN_TRIGGER_HAPPY8, data[22] & BIT(3));
+                       }
+               }
 
-       /* triggers left/right */
-       if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
-               input_report_key(dev, BTN_TL2,
-                                (__u16) le16_to_cpup((__le16 *)(data + 6)));
-               input_report_key(dev, BTN_TR2,
-                                (__u16) le16_to_cpup((__le16 *)(data + 8)));
-       } else {
-               input_report_abs(dev, ABS_Z,
-                                (__u16) le16_to_cpup((__le16 *)(data + 6)));
-               input_report_abs(dev, ABS_RZ,
-                                (__u16) le16_to_cpup((__le16 *)(data + 8)));
+               do_sync = true;
        }
 
-       input_sync(dev);
+       if (do_sync)
+               input_sync(dev);
 }
 
 static void xpad_irq_in(struct urb *urb)
@@ -1226,8 +1410,8 @@ static void xpadone_ack_mode_report(struct usb_xpad *xpad, u8 seq_num)
        struct xpad_output_packet *packet =
                        &xpad->out_packets[XPAD_OUT_CMD_IDX];
        static const u8 mode_report_ack[] = {
-               0x01, 0x20, 0x00, 0x09, 0x00, 0x07, 0x20, 0x02,
-               0x00, 0x00, 0x00, 0x00, 0x00
+               GIP_CMD_ACK, GIP_OPT_INTERNAL, GIP_SEQ0, GIP_PL_LEN(9),
+               0x00, GIP_CMD_VIRTUAL_KEY, GIP_OPT_INTERNAL, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
        };
 
        spin_lock_irqsave(&xpad->odata_lock, flags);
@@ -1305,14 +1489,14 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
                break;
 
        case XTYPE_XBOXONE:
-               packet->data[0] = 0x09; /* activate rumble */
+               packet->data[0] = GIP_CMD_RUMBLE; /* activate rumble */
                packet->data[1] = 0x00;
                packet->data[2] = xpad->odata_serial++;
-               packet->data[3] = 0x09;
+               packet->data[3] = GIP_PL_LEN(9);
                packet->data[4] = 0x00;
-               packet->data[5] = 0x0F;
-               packet->data[6] = 0x00;
-               packet->data[7] = 0x00;
+               packet->data[5] = GIP_MOTOR_ALL;
+               packet->data[6] = 0x00; /* left trigger */
+               packet->data[7] = 0x00; /* right trigger */
                packet->data[8] = strong / 512; /* left actuator */
                packet->data[9] = weak / 512;   /* right actuator */
                packet->data[10] = 0xFF; /* on period */
@@ -1622,6 +1806,9 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
        case ABS_HAT0Y: /* the d-pad (only if dpad is mapped to axes */
                input_set_abs_params(input_dev, abs, -1, 1, 0, 0);
                break;
+       case ABS_PROFILE: /* 4 value profile button (such as on XAC) */
+               input_set_abs_params(input_dev, abs, 0, 4, 0, 0);
+               break;
        default:
                input_set_abs_params(input_dev, abs, 0, 0, 0, 0);
                break;
@@ -1693,6 +1880,12 @@ static int xpad_init_input(struct usb_xpad *xpad)
                                             xpad_btn_pad[i]);
        }
 
+       /* set up paddles if the controller has them */
+       if (xpad->mapping & MAP_PADDLES) {
+               for (i = 0; xpad_btn_paddles[i] >= 0; i++)
+                       input_set_capability(input_dev, EV_KEY, xpad_btn_paddles[i]);
+       }
+
        /*
         * This should be a simple else block. However historically
         * xbox360w has mapped DPAD to buttons while xbox360 did not. This
@@ -1714,6 +1907,10 @@ static int xpad_init_input(struct usb_xpad *xpad)
                        xpad_set_up_abs(input_dev, xpad_abs_triggers[i]);
        }
 
+       /* setup profile button as an axis with 4 possible values */
+       if (xpad->mapping & MAP_PROFILE_BUTTON)
+               xpad_set_up_abs(input_dev, ABS_PROFILE);
+
        error = xpad_init_ff(xpad);
        if (error)
                goto err_free_input;
@@ -1779,6 +1976,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
        xpad->mapping = xpad_device[i].mapping;
        xpad->xtype = xpad_device[i].xtype;
        xpad->name = xpad_device[i].name;
+       xpad->packet_type = PKT_XB;
        INIT_WORK(&xpad->work, xpad_presence_work);
 
        if (xpad->xtype == XTYPE_UNKNOWN) {
@@ -1844,6 +2042,38 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
 
        usb_set_intfdata(intf, xpad);
 
+       /* Packet type detection */
+       if (le16_to_cpu(udev->descriptor.idVendor) == 0x045e) { /* Microsoft controllers */
+               if (le16_to_cpu(udev->descriptor.idProduct) == 0x02e3) {
+                       /* The original elite controller always uses the oldest
+                        * type of extended packet
+                        */
+                       xpad->packet_type = PKT_XBE1;
+               } else if (le16_to_cpu(udev->descriptor.idProduct) == 0x0b00) {
+                       /* The elite 2 controller has seen multiple packet
+                        * revisions. These are tied to specific firmware
+                        * versions
+                        */
+                       if (le16_to_cpu(udev->descriptor.bcdDevice) < 0x0500) {
+                               /* This is the format that the Elite 2 used
+                                * prior to the BLE update
+                                */
+                               xpad->packet_type = PKT_XBE2_FW_OLD;
+                       } else if (le16_to_cpu(udev->descriptor.bcdDevice) <
+                                  0x050b) {
+                               /* This is the format that the Elite 2 used
+                                * prior to the update that split the packet
+                                */
+                               xpad->packet_type = PKT_XBE2_FW_5_EARLY;
+                       } else {
+                               /* The split packet format that was introduced
+                                * in firmware v5.11
+                                */
+                               xpad->packet_type = PKT_XBE2_FW_5_11;
+                       }
+               }
+       }
+
        if (xpad->xtype == XTYPE_XBOX360W) {
                /*
                 * Submit the int URB immediately rather than waiting for open
@@ -1972,7 +2202,6 @@ static struct usb_driver xpad_driver = {
        .disconnect     = xpad_disconnect,
        .suspend        = xpad_suspend,
        .resume         = xpad_resume,
-       .reset_resume   = xpad_resume,
        .id_table       = xpad_table,
 };
 
index d553117..3f2460e 100644 (file)
@@ -28,9 +28,6 @@
  * coder :-(
  */
 
-/*
- */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index a20ee69..0029211 100644 (file)
@@ -40,6 +40,9 @@ config KEYBOARD_ADP5520
 config KEYBOARD_ADP5588
        tristate "ADP5588/87 I2C QWERTY Keypad and IO Expander"
        depends on I2C
+       select GPIOLIB
+       select GPIOLIB_IRQCHIP
+       select INPUT_MATRIXKMAP
        help
          Say Y here if you want to use a ADP5588/87 attached to your
          system I2C bus.
@@ -186,7 +189,7 @@ config KEYBOARD_QT2160
 
 config KEYBOARD_CLPS711X
        tristate "CLPS711X Keypad support"
-       depends on OF_GPIO && (ARCH_CLPS711X || COMPILE_TEST)
+       depends on ARCH_CLPS711X || COMPILE_TEST
        select INPUT_MATRIXKMAP
        help
          Say Y here to enable the matrix keypad on the Cirrus Logic
@@ -524,6 +527,19 @@ config KEYBOARD_OPENCORES
          To compile this driver as a module, choose M here; the
          module will be called opencores-kbd.
 
+config KEYBOARD_PINEPHONE
+       tristate "Pine64 PinePhone Keyboard"
+       depends on I2C && REGULATOR
+       select CRC8
+       select INPUT_MATRIXKMAP
+       help
+         Say Y here to enable support for the keyboard in the Pine64 PinePhone
+         keyboard case. This driver supports the FLOSS firmware available at
+         https://megous.com/git/pinephone-keyboard/
+
+         To compile this driver as a module, choose M here; the
+         module will be called pinephone-keyboard.
+
 config KEYBOARD_PXA27x
        tristate "PXA27x/PXA3xx keypad support"
        depends on PXA27x || PXA3xx || ARCH_MMP
index 721936e..5f67196 100644 (file)
@@ -52,6 +52,7 @@ obj-$(CONFIG_KEYBOARD_NSPIRE)         += nspire-keypad.o
 obj-$(CONFIG_KEYBOARD_OMAP)            += omap-keypad.o
 obj-$(CONFIG_KEYBOARD_OMAP4)           += omap4-keypad.o
 obj-$(CONFIG_KEYBOARD_OPENCORES)       += opencores-kbd.o
+obj-$(CONFIG_KEYBOARD_PINEPHONE)       += pinephone-keyboard.o
 obj-$(CONFIG_KEYBOARD_PMIC8XXX)                += pmic8xxx-keypad.o
 obj-$(CONFIG_KEYBOARD_PXA27x)          += pxa27x_keypad.o
 obj-$(CONFIG_KEYBOARD_PXA930_ROTARY)   += pxa930_rotary.o
index e271973..7cd83c8 100644 (file)
  * Copyright (C) 2008-2010 Analog Devices Inc.
  */
 
+#include <linux/bits.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
+#include <linux/gpio/consumer.h>
 #include <linux/gpio/driver.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
+#include <linux/input/matrix_keypad.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/ktime.h>
 #include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/pinctrl/pinconf-generic.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/timekeeping.h>
 
-#include <linux/platform_data/adp5588.h>
+#define DEV_ID 0x00            /* Device ID */
+#define CFG 0x01               /* Configuration Register1 */
+#define INT_STAT 0x02          /* Interrupt Status Register */
+#define KEY_LCK_EC_STAT 0x03   /* Key Lock and Event Counter Register */
+#define KEY_EVENTA 0x04                /* Key Event Register A */
+#define KEY_EVENTB 0x05                /* Key Event Register B */
+#define KEY_EVENTC 0x06                /* Key Event Register C */
+#define KEY_EVENTD 0x07                /* Key Event Register D */
+#define KEY_EVENTE 0x08                /* Key Event Register E */
+#define KEY_EVENTF 0x09                /* Key Event Register F */
+#define KEY_EVENTG 0x0A                /* Key Event Register G */
+#define KEY_EVENTH 0x0B                /* Key Event Register H */
+#define KEY_EVENTI 0x0C                /* Key Event Register I */
+#define KEY_EVENTJ 0x0D                /* Key Event Register J */
+#define KP_LCK_TMR 0x0E                /* Keypad Lock1 to Lock2 Timer */
+#define UNLOCK1 0x0F           /* Unlock Key1 */
+#define UNLOCK2 0x10           /* Unlock Key2 */
+#define GPIO_INT_STAT1 0x11    /* GPIO Interrupt Status */
+#define GPIO_INT_STAT2 0x12    /* GPIO Interrupt Status */
+#define GPIO_INT_STAT3 0x13    /* GPIO Interrupt Status */
+#define GPIO_DAT_STAT1 0x14    /* GPIO Data Status, Read twice to clear */
+#define GPIO_DAT_STAT2 0x15    /* GPIO Data Status, Read twice to clear */
+#define GPIO_DAT_STAT3 0x16    /* GPIO Data Status, Read twice to clear */
+#define GPIO_DAT_OUT1 0x17     /* GPIO DATA OUT */
+#define GPIO_DAT_OUT2 0x18     /* GPIO DATA OUT */
+#define GPIO_DAT_OUT3 0x19     /* GPIO DATA OUT */
+#define GPIO_INT_EN1 0x1A      /* GPIO Interrupt Enable */
+#define GPIO_INT_EN2 0x1B      /* GPIO Interrupt Enable */
+#define GPIO_INT_EN3 0x1C      /* GPIO Interrupt Enable */
+#define KP_GPIO1 0x1D          /* Keypad or GPIO Selection */
+#define KP_GPIO2 0x1E          /* Keypad or GPIO Selection */
+#define KP_GPIO3 0x1F          /* Keypad or GPIO Selection */
+#define GPI_EM1 0x20           /* GPI Event Mode 1 */
+#define GPI_EM2 0x21           /* GPI Event Mode 2 */
+#define GPI_EM3 0x22           /* GPI Event Mode 3 */
+#define GPIO_DIR1 0x23         /* GPIO Data Direction */
+#define GPIO_DIR2 0x24         /* GPIO Data Direction */
+#define GPIO_DIR3 0x25         /* GPIO Data Direction */
+#define GPIO_INT_LVL1 0x26     /* GPIO Edge/Level Detect */
+#define GPIO_INT_LVL2 0x27     /* GPIO Edge/Level Detect */
+#define GPIO_INT_LVL3 0x28     /* GPIO Edge/Level Detect */
+#define DEBOUNCE_DIS1 0x29     /* Debounce Disable */
+#define DEBOUNCE_DIS2 0x2A     /* Debounce Disable */
+#define DEBOUNCE_DIS3 0x2B     /* Debounce Disable */
+#define GPIO_PULL1 0x2C                /* GPIO Pull Disable */
+#define GPIO_PULL2 0x2D                /* GPIO Pull Disable */
+#define GPIO_PULL3 0x2E                /* GPIO Pull Disable */
+#define CMP_CFG_STAT 0x30      /* Comparator Configuration and Status Register */
+#define CMP_CONFG_SENS1 0x31   /* Sensor1 Comparator Configuration Register */
+#define CMP_CONFG_SENS2 0x32   /* L2 Light Sensor Reference Level, Output Falling for Sensor 1 */
+#define CMP1_LVL2_TRIP 0x33    /* L2 Light Sensor Hysteresis (Active when Output Rising) for Sensor 1 */
+#define CMP1_LVL2_HYS 0x34     /* L3 Light Sensor Reference Level, Output Falling For Sensor 1 */
+#define CMP1_LVL3_TRIP 0x35    /* L3 Light Sensor Hysteresis (Active when Output Rising) For Sensor 1 */
+#define CMP1_LVL3_HYS 0x36     /* Sensor 2 Comparator Configuration Register */
+#define CMP2_LVL2_TRIP 0x37    /* L2 Light Sensor Reference Level, Output Falling for Sensor 2 */
+#define CMP2_LVL2_HYS 0x38     /* L2 Light Sensor Hysteresis (Active when Output Rising) for Sensor 2 */
+#define CMP2_LVL3_TRIP 0x39    /* L3 Light Sensor Reference Level, Output Falling For Sensor 2 */
+#define CMP2_LVL3_HYS 0x3A     /* L3 Light Sensor Hysteresis (Active when Output Rising) For Sensor 2 */
+#define CMP1_ADC_DAT_R1 0x3B   /* Comparator 1 ADC data Register1 */
+#define CMP1_ADC_DAT_R2 0x3C   /* Comparator 1 ADC data Register2 */
+#define CMP2_ADC_DAT_R1 0x3D   /* Comparator 2 ADC data Register1 */
+#define CMP2_ADC_DAT_R2 0x3E   /* Comparator 2 ADC data Register2 */
+
+#define ADP5588_DEVICE_ID_MASK 0xF
+
+ /* Configuration Register1 */
+#define ADP5588_AUTO_INC       BIT(7)
+#define ADP5588_GPIEM_CFG      BIT(6)
+#define ADP5588_OVR_FLOW_M     BIT(5)
+#define ADP5588_INT_CFG                BIT(4)
+#define ADP5588_OVR_FLOW_IEN   BIT(3)
+#define ADP5588_K_LCK_IM       BIT(2)
+#define ADP5588_GPI_IEN                BIT(1)
+#define ADP5588_KE_IEN         BIT(0)
+
+/* Interrupt Status Register */
+#define ADP5588_CMP2_INT       BIT(5)
+#define ADP5588_CMP1_INT       BIT(4)
+#define ADP5588_OVR_FLOW_INT   BIT(3)
+#define ADP5588_K_LCK_INT      BIT(2)
+#define ADP5588_GPI_INT                BIT(1)
+#define ADP5588_KE_INT         BIT(0)
+
+/* Key Lock and Event Counter Register */
+#define ADP5588_K_LCK_EN       BIT(6)
+#define ADP5588_LCK21          0x30
+#define ADP5588_KEC            GENMASK(3, 0)
+
+#define ADP5588_MAXGPIO                18
+#define ADP5588_BANK(offs)     ((offs) >> 3)
+#define ADP5588_BIT(offs)      (1u << ((offs) & 0x7))
+
+/* Put one of these structures in i2c_board_info platform_data */
+
+/*
+ * 128 so it fits matrix-keymap maximum number of keys when the full
+ * 10cols * 8rows are used.
+ */
+#define ADP5588_KEYMAPSIZE 128
+
+#define GPI_PIN_ROW0 97
+#define GPI_PIN_ROW1 98
+#define GPI_PIN_ROW2 99
+#define GPI_PIN_ROW3 100
+#define GPI_PIN_ROW4 101
+#define GPI_PIN_ROW5 102
+#define GPI_PIN_ROW6 103
+#define GPI_PIN_ROW7 104
+#define GPI_PIN_COL0 105
+#define GPI_PIN_COL1 106
+#define GPI_PIN_COL2 107
+#define GPI_PIN_COL3 108
+#define GPI_PIN_COL4 109
+#define GPI_PIN_COL5 110
+#define GPI_PIN_COL6 111
+#define GPI_PIN_COL7 112
+#define GPI_PIN_COL8 113
+#define GPI_PIN_COL9 114
+
+#define GPI_PIN_ROW_BASE GPI_PIN_ROW0
+#define GPI_PIN_ROW_END GPI_PIN_ROW7
+#define GPI_PIN_COL_BASE GPI_PIN_COL0
+#define GPI_PIN_COL_END GPI_PIN_COL9
+
+#define GPI_PIN_BASE GPI_PIN_ROW_BASE
+#define GPI_PIN_END GPI_PIN_COL_END
+
+#define ADP5588_ROWS_MAX (GPI_PIN_ROW7 - GPI_PIN_ROW0 + 1)
+#define ADP5588_COLS_MAX (GPI_PIN_COL9 - GPI_PIN_COL0 + 1)
+
+#define ADP5588_GPIMAPSIZE_MAX (GPI_PIN_END - GPI_PIN_BASE + 1)
 
 /* Key Event Register xy */
-#define KEY_EV_PRESSED         (1 << 7)
-#define KEY_EV_MASK            (0x7F)
+#define KEY_EV_PRESSED         BIT(7)
+#define KEY_EV_MASK            GENMASK(6, 0)
 
-#define KP_SEL(x)              (0xFFFF >> (16 - x))    /* 2^x-1 */
+#define KP_SEL(x)              (BIT(x) - 1)    /* 2^x-1 */
 
 #define KEYP_MAX_EVENT         10
 
 #define WA_DELAYED_READOUT_REVID(rev)          ((rev) < 4)
 #define WA_DELAYED_READOUT_TIME                        25
 
+#define ADP5588_INVALID_HWIRQ  (~0UL)
+
 struct adp5588_kpad {
        struct i2c_client *client;
        struct input_dev *input;
        ktime_t irq_time;
        unsigned long delay;
+       u32 row_shift;
+       u32 rows;
+       u32 cols;
+       u32 unlock_keys[2];
+       int nkeys_unlock;
        unsigned short keycode[ADP5588_KEYMAPSIZE];
-       const struct adp5588_gpi_map *gpimap;
-       unsigned short gpimapsize;
-#ifdef CONFIG_GPIOLIB
        unsigned char gpiomap[ADP5588_MAXGPIO];
        struct gpio_chip gc;
        struct mutex gpio_lock; /* Protect cached dir, dat_out */
        u8 dat_out[3];
        u8 dir[3];
-#endif
+       u8 int_en[3];
+       u8 irq_mask[3];
+       u8 pull_dis[3];
 };
 
 static int adp5588_read(struct i2c_client *client, u8 reg)
@@ -72,8 +214,7 @@ static int adp5588_write(struct i2c_client *client, u8 reg, u8 val)
        return i2c_smbus_write_byte_data(client, reg, val);
 }
 
-#ifdef CONFIG_GPIOLIB
-static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
+static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned int off)
 {
        struct adp5588_kpad *kpad = gpiochip_get_data(chip);
        unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
@@ -93,7 +234,7 @@ static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
 }
 
 static void adp5588_gpio_set_value(struct gpio_chip *chip,
-                                  unsigned off, int val)
+                                  unsigned int off, int val)
 {
        struct adp5588_kpad *kpad = gpiochip_get_data(chip);
        unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
@@ -106,13 +247,47 @@ static void adp5588_gpio_set_value(struct gpio_chip *chip,
        else
                kpad->dat_out[bank] &= ~bit;
 
-       adp5588_write(kpad->client, GPIO_DAT_OUT1 + bank,
-                          kpad->dat_out[bank]);
+       adp5588_write(kpad->client, GPIO_DAT_OUT1 + bank, kpad->dat_out[bank]);
 
        mutex_unlock(&kpad->gpio_lock);
 }
 
-static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off)
+static int adp5588_gpio_set_config(struct gpio_chip *chip,  unsigned int off,
+                                  unsigned long config)
+{
+       struct adp5588_kpad *kpad = gpiochip_get_data(chip);
+       unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
+       unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);
+       bool pull_disable;
+       int ret;
+
+       switch (pinconf_to_config_param(config)) {
+       case PIN_CONFIG_BIAS_PULL_UP:
+               pull_disable = false;
+               break;
+       case PIN_CONFIG_BIAS_DISABLE:
+               pull_disable = true;
+               break;
+       default:
+               return -ENOTSUPP;
+       }
+
+       mutex_lock(&kpad->gpio_lock);
+
+       if (pull_disable)
+               kpad->pull_dis[bank] |= bit;
+       else
+               kpad->pull_dis[bank] &= bit;
+
+       ret = adp5588_write(kpad->client, GPIO_PULL1 + bank,
+                           kpad->pull_dis[bank]);
+
+       mutex_unlock(&kpad->gpio_lock);
+
+       return ret;
+}
+
+static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned int off)
 {
        struct adp5588_kpad *kpad = gpiochip_get_data(chip);
        unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
@@ -130,7 +305,7 @@ static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off)
 }
 
 static int adp5588_gpio_direction_output(struct gpio_chip *chip,
-                                        unsigned off, int val)
+                                        unsigned int off, int val)
 {
        struct adp5588_kpad *kpad = gpiochip_get_data(chip);
        unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
@@ -147,17 +322,19 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip,
                kpad->dat_out[bank] &= ~bit;
 
        ret = adp5588_write(kpad->client, GPIO_DAT_OUT1 + bank,
-                                kpad->dat_out[bank]);
-       ret |= adp5588_write(kpad->client, GPIO_DIR1 + bank,
-                                kpad->dir[bank]);
+                           kpad->dat_out[bank]);
+       if (ret)
+               goto out_unlock;
+
+       ret = adp5588_write(kpad->client, GPIO_DIR1 + bank, kpad->dir[bank]);
 
+out_unlock:
        mutex_unlock(&kpad->gpio_lock);
 
        return ret;
 }
 
-static int adp5588_build_gpiomap(struct adp5588_kpad *kpad,
-                               const struct adp5588_kpad_platform_data *pdata)
+static int adp5588_build_gpiomap(struct adp5588_kpad *kpad)
 {
        bool pin_used[ADP5588_MAXGPIO];
        int n_unused = 0;
@@ -165,15 +342,12 @@ static int adp5588_build_gpiomap(struct adp5588_kpad *kpad,
 
        memset(pin_used, 0, sizeof(pin_used));
 
-       for (i = 0; i < pdata->rows; i++)
+       for (i = 0; i < kpad->rows; i++)
                pin_used[i] = true;
 
-       for (i = 0; i < pdata->cols; i++)
+       for (i = 0; i < kpad->cols; i++)
                pin_used[i + GPI_PIN_COL_BASE - GPI_PIN_BASE] = true;
 
-       for (i = 0; i < kpad->gpimapsize; i++)
-               pin_used[kpad->gpimap[i].pin - GPI_PIN_BASE] = true;
-
        for (i = 0; i < ADP5588_MAXGPIO; i++)
                if (!pin_used[i])
                        kpad->gpiomap[n_unused++] = i;
@@ -181,47 +355,101 @@ static int adp5588_build_gpiomap(struct adp5588_kpad *kpad,
        return n_unused;
 }
 
-static void adp5588_gpio_do_teardown(void *_kpad)
+static void adp5588_irq_bus_lock(struct irq_data *d)
 {
-       struct adp5588_kpad *kpad = _kpad;
-       struct device *dev = &kpad->client->dev;
-       const struct adp5588_kpad_platform_data *pdata = dev_get_platdata(dev);
-       const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data;
-       int error;
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct adp5588_kpad *kpad = gpiochip_get_data(gc);
 
-       error = gpio_data->teardown(kpad->client,
-                                   kpad->gc.base, kpad->gc.ngpio,
-                                   gpio_data->context);
-       if (error)
-               dev_warn(&kpad->client->dev, "teardown failed %d\n", error);
+       mutex_lock(&kpad->gpio_lock);
 }
 
+static void adp5588_irq_bus_sync_unlock(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct adp5588_kpad *kpad = gpiochip_get_data(gc);
+       int i;
+
+       for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) {
+               if (kpad->int_en[i] ^ kpad->irq_mask[i]) {
+                       kpad->int_en[i] = kpad->irq_mask[i];
+                       adp5588_write(kpad->client, GPI_EM1 + i, kpad->int_en[i]);
+               }
+       }
+
+       mutex_unlock(&kpad->gpio_lock);
+}
+
+static void adp5588_irq_mask(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct adp5588_kpad *kpad = gpiochip_get_data(gc);
+       irq_hw_number_t hwirq = irqd_to_hwirq(d);
+       unsigned long real_irq = kpad->gpiomap[hwirq];
+
+       kpad->irq_mask[ADP5588_BANK(real_irq)] &= ~ADP5588_BIT(real_irq);
+       gpiochip_disable_irq(gc, hwirq);
+}
+
+static void adp5588_irq_unmask(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct adp5588_kpad *kpad = gpiochip_get_data(gc);
+       irq_hw_number_t hwirq = irqd_to_hwirq(d);
+       unsigned long real_irq = kpad->gpiomap[hwirq];
+
+       gpiochip_enable_irq(gc, hwirq);
+       kpad->irq_mask[ADP5588_BANK(real_irq)] |= ADP5588_BIT(real_irq);
+}
+
+static int adp5588_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       if (!(type & IRQ_TYPE_EDGE_BOTH))
+               return -EINVAL;
+
+       irq_set_handler_locked(d, handle_edge_irq);
+
+       return 0;
+}
+
+static const struct irq_chip adp5588_irq_chip = {
+       .name = "adp5588",
+       .irq_mask = adp5588_irq_mask,
+       .irq_unmask = adp5588_irq_unmask,
+       .irq_bus_lock = adp5588_irq_bus_lock,
+       .irq_bus_sync_unlock = adp5588_irq_bus_sync_unlock,
+       .irq_set_type = adp5588_irq_set_type,
+       .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_IMMUTABLE,
+       GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
 static int adp5588_gpio_add(struct adp5588_kpad *kpad)
 {
        struct device *dev = &kpad->client->dev;
-       const struct adp5588_kpad_platform_data *pdata = dev_get_platdata(dev);
-       const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data;
+       struct gpio_irq_chip *girq;
        int i, error;
 
-       if (!gpio_data)
-               return 0;
-
-       kpad->gc.ngpio = adp5588_build_gpiomap(kpad, pdata);
+       kpad->gc.ngpio = adp5588_build_gpiomap(kpad);
        if (kpad->gc.ngpio == 0) {
                dev_info(dev, "No unused gpios left to export\n");
                return 0;
        }
 
+       kpad->gc.parent = &kpad->client->dev;
        kpad->gc.direction_input = adp5588_gpio_direction_input;
        kpad->gc.direction_output = adp5588_gpio_direction_output;
        kpad->gc.get = adp5588_gpio_get_value;
        kpad->gc.set = adp5588_gpio_set_value;
+       kpad->gc.set_config = adp5588_gpio_set_config;
        kpad->gc.can_sleep = 1;
 
-       kpad->gc.base = gpio_data->gpio_start;
+       kpad->gc.base = -1;
        kpad->gc.label = kpad->client->name;
        kpad->gc.owner = THIS_MODULE;
-       kpad->gc.names = gpio_data->names;
+
+       girq = &kpad->gc.irq;
+       gpio_irq_chip_set_chip(girq, &adp5588_irq_chip);
+       girq->handler = handle_bad_irq;
+       girq->threaded = true;
 
        mutex_init(&kpad->gpio_lock);
 
@@ -235,54 +463,87 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad)
                kpad->dat_out[i] = adp5588_read(kpad->client,
                                                GPIO_DAT_OUT1 + i);
                kpad->dir[i] = adp5588_read(kpad->client, GPIO_DIR1 + i);
+               kpad->pull_dis[i] = adp5588_read(kpad->client, GPIO_PULL1 + i);
        }
 
-       if (gpio_data->setup) {
-               error = gpio_data->setup(kpad->client,
-                                        kpad->gc.base, kpad->gc.ngpio,
-                                        gpio_data->context);
-               if (error)
-                       dev_warn(dev, "setup failed: %d\n", error);
-       }
+       return 0;
+}
 
-       if (gpio_data->teardown) {
-               error = devm_add_action(dev, adp5588_gpio_do_teardown, kpad);
-               if (error)
-                       dev_warn(dev, "failed to schedule teardown: %d\n",
-                                error);
-       }
+static unsigned long adp5588_gpiomap_get_hwirq(struct device *dev,
+                                              const u8 *map, unsigned int gpio,
+                                              unsigned int ngpios)
+{
+       unsigned int hwirq;
 
-       return 0;
+       for (hwirq = 0; hwirq < ngpios; hwirq++)
+               if (map[hwirq] == gpio)
+                       return hwirq;
+
+       /* should never happen */
+       dev_warn_ratelimited(dev, "could not find the hwirq for gpio(%u)\n", gpio);
+
+       return ADP5588_INVALID_HWIRQ;
 }
 
-#else
-static inline int adp5588_gpio_add(struct adp5588_kpad *kpad)
+static void adp5588_gpio_irq_handle(struct adp5588_kpad *kpad, int key_val,
+                                   int key_press)
 {
-       return 0;
+       unsigned int irq, gpio = key_val - GPI_PIN_BASE, irq_type;
+       struct i2c_client *client = kpad->client;
+       struct irq_data *irqd;
+       unsigned long hwirq;
+
+       hwirq = adp5588_gpiomap_get_hwirq(&client->dev, kpad->gpiomap,
+                                         gpio, kpad->gc.ngpio);
+       if (hwirq == ADP5588_INVALID_HWIRQ) {
+               dev_err(&client->dev, "Could not get hwirq for key(%u)\n", key_val);
+               return;
+       }
+
+       irq = irq_find_mapping(kpad->gc.irq.domain, hwirq);
+       if (!irq)
+               return;
+
+       irqd = irq_get_irq_data(irq);
+       if (!irqd) {
+               dev_err(&client->dev, "Could not get irq(%u) data\n", irq);
+               return;
+       }
+
+       irq_type = irqd_get_trigger_type(irqd);
+
+       /*
+        * Default is active low which means key_press is asserted on
+        * the falling edge.
+        */
+       if ((irq_type & IRQ_TYPE_EDGE_RISING && !key_press) ||
+           (irq_type & IRQ_TYPE_EDGE_FALLING && key_press))
+               handle_nested_irq(irq);
 }
-#endif
 
 static void adp5588_report_events(struct adp5588_kpad *kpad, int ev_cnt)
 {
-       int i, j;
+       int i;
 
        for (i = 0; i < ev_cnt; i++) {
-               int key = adp5588_read(kpad->client, Key_EVENTA + i);
+               int key = adp5588_read(kpad->client, KEY_EVENTA + i);
                int key_val = key & KEY_EV_MASK;
+               int key_press = key & KEY_EV_PRESSED;
 
                if (key_val >= GPI_PIN_BASE && key_val <= GPI_PIN_END) {
-                       for (j = 0; j < kpad->gpimapsize; j++) {
-                               if (key_val == kpad->gpimap[j].pin) {
-                                       input_report_switch(kpad->input,
-                                                       kpad->gpimap[j].sw_evt,
-                                                       key & KEY_EV_PRESSED);
-                                       break;
-                               }
-                       }
+                       /* gpio line used as IRQ source */
+                       adp5588_gpio_irq_handle(kpad, key_val, key_press);
                } else {
+                       int row = (key_val - 1) / ADP5588_COLS_MAX;
+                       int col =  (key_val - 1) % ADP5588_COLS_MAX;
+                       int code = MATRIX_SCAN_CODE(row, col, kpad->row_shift);
+
+                       dev_dbg_ratelimited(&kpad->client->dev,
+                                           "report key(%d) r(%d) c(%d) code(%d)\n",
+                                           key_val, row, col, kpad->keycode[code]);
+
                        input_report_key(kpad->input,
-                                        kpad->keycode[key_val - 1],
-                                        key & KEY_EV_PRESSED);
+                                        kpad->keycode[code], key_press);
                }
        }
 }
@@ -335,176 +596,145 @@ static irqreturn_t adp5588_thread_irq(int irq, void *handle)
        return IRQ_HANDLED;
 }
 
-static int adp5588_setup(struct i2c_client *client)
+static int adp5588_setup(struct adp5588_kpad *kpad)
 {
-       const struct adp5588_kpad_platform_data *pdata =
-                       dev_get_platdata(&client->dev);
-       const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data;
+       struct i2c_client *client = kpad->client;
        int i, ret;
-       unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0;
-
-       ret = adp5588_write(client, KP_GPIO1, KP_SEL(pdata->rows));
-       ret |= adp5588_write(client, KP_GPIO2, KP_SEL(pdata->cols) & 0xFF);
-       ret |= adp5588_write(client, KP_GPIO3, KP_SEL(pdata->cols) >> 8);
 
-       if (pdata->en_keylock) {
-               ret |= adp5588_write(client, UNLOCK1, pdata->unlock_key1);
-               ret |= adp5588_write(client, UNLOCK2, pdata->unlock_key2);
-               ret |= adp5588_write(client, KEY_LCK_EC_STAT, ADP5588_K_LCK_EN);
-       }
+       ret = adp5588_write(client, KP_GPIO1, KP_SEL(kpad->rows));
+       if (ret)
+               return ret;
 
-       for (i = 0; i < KEYP_MAX_EVENT; i++)
-               ret |= adp5588_read(client, Key_EVENTA);
+       ret = adp5588_write(client, KP_GPIO2, KP_SEL(kpad->cols) & 0xFF);
+       if (ret)
+               return ret;
 
-       for (i = 0; i < pdata->gpimapsize; i++) {
-               unsigned short pin = pdata->gpimap[i].pin;
+       ret = adp5588_write(client, KP_GPIO3, KP_SEL(kpad->cols) >> 8);
+       if (ret)
+               return ret;
 
-               if (pin <= GPI_PIN_ROW_END) {
-                       evt_mode1 |= (1 << (pin - GPI_PIN_ROW_BASE));
-               } else {
-                       evt_mode2 |= ((1 << (pin - GPI_PIN_COL_BASE)) & 0xFF);
-                       evt_mode3 |= ((1 << (pin - GPI_PIN_COL_BASE)) >> 8);
-               }
+       for (i = 0; i < kpad->nkeys_unlock; i++) {
+               ret = adp5588_write(client, UNLOCK1 + i, kpad->unlock_keys[i]);
+               if (ret)
+                       return ret;
        }
 
-       if (pdata->gpimapsize) {
-               ret |= adp5588_write(client, GPI_EM1, evt_mode1);
-               ret |= adp5588_write(client, GPI_EM2, evt_mode2);
-               ret |= adp5588_write(client, GPI_EM3, evt_mode3);
+       if (kpad->nkeys_unlock) {
+               ret = adp5588_write(client, KEY_LCK_EC_STAT, ADP5588_K_LCK_EN);
+               if (ret)
+                       return ret;
        }
 
-       if (gpio_data) {
-               for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) {
-                       int pull_mask = gpio_data->pullup_dis_mask;
-
-                       ret |= adp5588_write(client, GPIO_PULL1 + i,
-                               (pull_mask >> (8 * i)) & 0xFF);
-               }
+       for (i = 0; i < KEYP_MAX_EVENT; i++) {
+               ret = adp5588_read(client, KEY_EVENTA);
+               if (ret)
+                       return ret;
        }
 
-       ret |= adp5588_write(client, INT_STAT,
-                               ADP5588_CMP2_INT | ADP5588_CMP1_INT |
-                               ADP5588_OVR_FLOW_INT | ADP5588_K_LCK_INT |
-                               ADP5588_GPI_INT | ADP5588_KE_INT); /* Status is W1C */
+       ret = adp5588_write(client, INT_STAT,
+                           ADP5588_CMP2_INT | ADP5588_CMP1_INT |
+                           ADP5588_OVR_FLOW_INT | ADP5588_K_LCK_INT |
+                           ADP5588_GPI_INT | ADP5588_KE_INT); /* Status is W1C */
+       if (ret)
+               return ret;
 
-       ret |= adp5588_write(client, CFG, ADP5588_INT_CFG |
-                                         ADP5588_OVR_FLOW_IEN |
-                                         ADP5588_KE_IEN);
+       return adp5588_write(client, CFG, ADP5588_INT_CFG |
+                            ADP5588_OVR_FLOW_IEN | ADP5588_KE_IEN);
+}
+
+static int adp5588_fw_parse(struct adp5588_kpad *kpad)
+{
+       struct i2c_client *client = kpad->client;
+       int ret, i;
 
-       if (ret < 0) {
-               dev_err(&client->dev, "Write Error\n");
+       ret = matrix_keypad_parse_properties(&client->dev, &kpad->rows,
+                                            &kpad->cols);
+       if (ret)
                return ret;
+
+       if (kpad->rows > ADP5588_ROWS_MAX || kpad->cols > ADP5588_COLS_MAX) {
+               dev_err(&client->dev, "Invalid nr of rows(%u) or cols(%u)\n",
+                       kpad->rows, kpad->cols);
+               return -EINVAL;
        }
 
-       return 0;
-}
+       ret = matrix_keypad_build_keymap(NULL, NULL, kpad->rows, kpad->cols,
+                                        kpad->keycode, kpad->input);
+       if (ret)
+               return ret;
 
-static void adp5588_report_switch_state(struct adp5588_kpad *kpad)
-{
-       int gpi_stat1 = adp5588_read(kpad->client, GPIO_DAT_STAT1);
-       int gpi_stat2 = adp5588_read(kpad->client, GPIO_DAT_STAT2);
-       int gpi_stat3 = adp5588_read(kpad->client, GPIO_DAT_STAT3);
-       int gpi_stat_tmp, pin_loc;
-       int i;
+       kpad->row_shift = get_count_order(kpad->cols);
 
-       for (i = 0; i < kpad->gpimapsize; i++) {
-               unsigned short pin = kpad->gpimap[i].pin;
+       if (device_property_read_bool(&client->dev, "autorepeat"))
+               __set_bit(EV_REP, kpad->input->evbit);
 
-               if (pin <= GPI_PIN_ROW_END) {
-                       gpi_stat_tmp = gpi_stat1;
-                       pin_loc = pin - GPI_PIN_ROW_BASE;
-               } else if ((pin - GPI_PIN_COL_BASE) < 8) {
-                       gpi_stat_tmp = gpi_stat2;
-                       pin_loc = pin - GPI_PIN_COL_BASE;
-               } else {
-                       gpi_stat_tmp = gpi_stat3;
-                       pin_loc = pin - GPI_PIN_COL_BASE - 8;
-               }
+       kpad->nkeys_unlock = device_property_count_u32(&client->dev,
+                                                      "adi,unlock-keys");
+       if (kpad->nkeys_unlock <= 0) {
+               /* so that we don't end up enabling key lock */
+               kpad->nkeys_unlock = 0;
+               return 0;
+       }
 
-               if (gpi_stat_tmp < 0) {
-                       dev_err(&kpad->client->dev,
-                               "Can't read GPIO_DAT_STAT switch %d default to OFF\n",
-                               pin);
-                       gpi_stat_tmp = 0;
+       if (kpad->nkeys_unlock > ARRAY_SIZE(kpad->unlock_keys)) {
+               dev_err(&client->dev, "number of unlock keys(%d) > (%zu)\n",
+                       kpad->nkeys_unlock, ARRAY_SIZE(kpad->unlock_keys));
+               return -EINVAL;
+       }
+
+       ret = device_property_read_u32_array(&client->dev, "adi,unlock-keys",
+                                            kpad->unlock_keys,
+                                            kpad->nkeys_unlock);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < kpad->nkeys_unlock; i++) {
+               /*
+                * Even though it should be possible (as stated in the datasheet)
+                * to use GPIs (which are part of the keys event) as unlock keys,
+                * it was not working at all and was leading to overflow events
+                * at some point. Hence, for now, let's just allow keys which are
+                * part of keypad matrix to be used and if a reliable way of
+                * using GPIs is found, this condition can be removed/lightened.
+                */
+               if (kpad->unlock_keys[i] >= kpad->cols * kpad->rows) {
+                       dev_err(&client->dev, "Invalid unlock key(%d)\n",
+                               kpad->unlock_keys[i]);
+                       return -EINVAL;
                }
 
-               input_report_switch(kpad->input,
-                                   kpad->gpimap[i].sw_evt,
-                                   !(gpi_stat_tmp & (1 << pin_loc)));
+               /*
+                * Firmware properties keys start from 0 but on the device they
+                * start from 1.
+                */
+               kpad->unlock_keys[i] += 1;
        }
 
-       input_sync(kpad->input);
+       return 0;
 }
 
+static void adp5588_disable_regulator(void *reg)
+{
+       regulator_disable(reg);
+}
 
 static int adp5588_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
        struct adp5588_kpad *kpad;
-       const struct adp5588_kpad_platform_data *pdata =
-                       dev_get_platdata(&client->dev);
        struct input_dev *input;
+       struct gpio_desc *gpio;
+       struct regulator *vcc;
        unsigned int revid;
-       int ret, i;
+       int ret;
        int error;
 
        if (!i2c_check_functionality(client->adapter,
-                                       I2C_FUNC_SMBUS_BYTE_DATA)) {
+                                    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;
-       }
-
-       if (!pdata->rows || !pdata->cols || !pdata->keymap) {
-               dev_err(&client->dev, "no rows, cols or keymap from pdata\n");
-               return -EINVAL;
-       }
-
-       if (pdata->keymapsize != ADP5588_KEYMAPSIZE) {
-               dev_err(&client->dev, "invalid keymapsize\n");
-               return -EINVAL;
-       }
-
-       if (!pdata->gpimap && pdata->gpimapsize) {
-               dev_err(&client->dev, "invalid gpimap from pdata\n");
-               return -EINVAL;
-       }
-
-       if (pdata->gpimapsize > ADP5588_GPIMAPSIZE_MAX) {
-               dev_err(&client->dev, "invalid gpimapsize\n");
-               return -EINVAL;
-       }
-
-       for (i = 0; i < pdata->gpimapsize; i++) {
-               unsigned short pin = pdata->gpimap[i].pin;
-
-               if (pin < GPI_PIN_BASE || pin > GPI_PIN_END) {
-                       dev_err(&client->dev, "invalid gpi pin data\n");
-                       return -EINVAL;
-               }
-
-               if (pin <= GPI_PIN_ROW_END) {
-                       if (pin - GPI_PIN_ROW_BASE + 1 <= pdata->rows) {
-                               dev_err(&client->dev, "invalid gpi row data\n");
-                               return -EINVAL;
-                       }
-               } else {
-                       if (pin - GPI_PIN_COL_BASE + 1 <= pdata->cols) {
-                               dev_err(&client->dev, "invalid gpi col data\n");
-                               return -EINVAL;
-                       }
-               }
-       }
-
-       if (!client->irq) {
-               dev_err(&client->dev, "no IRQ?\n");
-               return -EINVAL;
-       }
-
        kpad = devm_kzalloc(&client->dev, sizeof(*kpad), GFP_KERNEL);
        if (!kpad)
                return -ENOMEM;
@@ -516,11 +746,38 @@ static int adp5588_probe(struct i2c_client *client,
        kpad->client = client;
        kpad->input = input;
 
+       error = adp5588_fw_parse(kpad);
+       if (error)
+               return error;
+
+       vcc = devm_regulator_get(&client->dev, "vcc");
+       if (IS_ERR(vcc))
+               return PTR_ERR(vcc);
+
+       error = regulator_enable(vcc);
+       if (error)
+               return error;
+
+       error = devm_add_action_or_reset(&client->dev,
+                                        adp5588_disable_regulator, vcc);
+       if (error)
+               return error;
+
+       gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(gpio))
+               return PTR_ERR(gpio);
+
+       if (gpio) {
+               fsleep(30);
+               gpiod_set_value_cansleep(gpio, 0);
+               fsleep(60);
+       }
+
        ret = adp5588_read(client, DEV_ID);
        if (ret < 0)
                return ret;
 
-       revid = (u8) ret & ADP5588_DEVICE_ID_MASK;
+       revid = ret & ADP5588_DEVICE_ID_MASK;
        if (WA_DELAYED_READOUT_REVID(revid))
                kpad->delay = msecs_to_jiffies(WA_DELAYED_READOUT_TIME);
 
@@ -534,32 +791,6 @@ static int adp5588_probe(struct i2c_client *client,
        input->id.product = 0x0001;
        input->id.version = revid;
 
-       input->keycodesize = sizeof(kpad->keycode[0]);
-       input->keycodemax = pdata->keymapsize;
-       input->keycode = kpad->keycode;
-
-       memcpy(kpad->keycode, pdata->keymap,
-               pdata->keymapsize * input->keycodesize);
-
-       kpad->gpimap = pdata->gpimap;
-       kpad->gpimapsize = pdata->gpimapsize;
-
-       /* setup input device */
-       __set_bit(EV_KEY, input->evbit);
-
-       if (pdata->repeat)
-               __set_bit(EV_REP, input->evbit);
-
-       for (i = 0; i < input->keycodemax; i++)
-               if (kpad->keycode[i] <= KEY_MAX)
-                       __set_bit(kpad->keycode[i], input->keybit);
-       __clear_bit(KEY_RESERVED, input->keybit);
-
-       if (kpad->gpimapsize)
-               __set_bit(EV_SW, input->evbit);
-       for (i = 0; i < kpad->gpimapsize; i++)
-               __set_bit(kpad->gpimap[i].sw_evt, input->swbit);
-
        error = input_register_device(input);
        if (error) {
                dev_err(&client->dev, "unable to register input device: %d\n",
@@ -567,6 +798,14 @@ static int adp5588_probe(struct i2c_client *client,
                return error;
        }
 
+       error = adp5588_setup(kpad);
+       if (error)
+               return error;
+
+       error = adp5588_gpio_add(kpad);
+       if (error)
+               return error;
+
        error = devm_request_threaded_irq(&client->dev, client->irq,
                                          adp5588_hard_irq, adp5588_thread_irq,
                                          IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
@@ -577,17 +816,6 @@ static int adp5588_probe(struct i2c_client *client,
                return error;
        }
 
-       error = adp5588_setup(client);
-       if (error)
-               return error;
-
-       if (kpad->gpimapsize)
-               adp5588_report_switch_state(kpad);
-
-       error = adp5588_gpio_add(kpad);
-       if (error)
-               return error;
-
        dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq);
        return 0;
 }
@@ -599,7 +827,7 @@ static void adp5588_remove(struct i2c_client *client)
        /* all resources will be freed by devm */
 }
 
-static int __maybe_unused adp5588_suspend(struct device *dev)
+static int adp5588_suspend(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
 
@@ -608,7 +836,7 @@ static int __maybe_unused adp5588_suspend(struct device *dev)
        return 0;
 }
 
-static int __maybe_unused adp5588_resume(struct device *dev)
+static int adp5588_resume(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
 
@@ -617,7 +845,7 @@ static int __maybe_unused adp5588_resume(struct device *dev)
        return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(adp5588_dev_pm_ops, adp5588_suspend, adp5588_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(adp5588_dev_pm_ops, adp5588_suspend, adp5588_resume);
 
 static const struct i2c_device_id adp5588_id[] = {
        { "adp5588-keys", 0 },
@@ -626,10 +854,18 @@ static const struct i2c_device_id adp5588_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, adp5588_id);
 
+static const struct of_device_id adp5588_of_match[] = {
+       { .compatible = "adi,adp5588" },
+       { .compatible = "adi,adp5587" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, adp5588_of_match);
+
 static struct i2c_driver adp5588_driver = {
        .driver = {
                .name = KBUILD_MODNAME,
-               .pm   = &adp5588_dev_pm_ops,
+               .of_match_table = adp5588_of_match,
+               .pm   = pm_sleep_ptr(&adp5588_dev_pm_ops),
        },
        .probe    = adp5588_probe,
        .remove   = adp5588_remove,
index 09551f6..a20a4e1 100644 (file)
@@ -10,9 +10,6 @@
  * Amiga keyboard driver for Linux/m68k
  */
 
-/*
- */
-
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/input.h>
index cbc6c0d..91a9810 100644 (file)
@@ -202,7 +202,7 @@ struct command_protocol_tp_info {
 };
 
 /**
- * struct touchpad_info - touchpad info response.
+ * struct touchpad_info_protocol - touchpad info response.
  * message.type = 0x1020, message.length = 0x006e
  *
  * @unknown1:          unknown
@@ -311,7 +311,7 @@ struct message {
                struct command_protocol_mt_init init_mt_command;
                struct command_protocol_capsl   capsl_command;
                struct command_protocol_bl      bl_command;
-               u8                              data[0];
+               DECLARE_FLEX_ARRAY(u8,          data);
        };
 };
 
index 77ed546..07e17e5 100644 (file)
@@ -21,9 +21,6 @@
  * This driver only deals with handing key events off to the input layer.
  */
 
-/*
- */
-
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/input.h>
index d413123..2469587 100644 (file)
@@ -323,11 +323,13 @@ static umode_t atkbd_attr_is_visible(struct kobject *kobj,
        return attr->mode;
 }
 
-static struct attribute_group atkbd_attribute_group = {
+static const struct attribute_group atkbd_attribute_group = {
        .attrs  = atkbd_attributes,
        .is_visible = atkbd_attr_is_visible,
 };
 
+__ATTRIBUTE_GROUPS(atkbd_attribute);
+
 static const unsigned int xl_table[] = {
        ATKBD_RET_BAT, ATKBD_RET_ERR, ATKBD_RET_ACK,
        ATKBD_RET_NAK, ATKBD_RET_HANJA, ATKBD_RET_HANGEUL,
@@ -922,8 +924,6 @@ static void atkbd_disconnect(struct serio *serio)
 {
        struct atkbd *atkbd = serio_get_drvdata(serio);
 
-       sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
-
        atkbd_disable(atkbd);
 
        input_unregister_device(atkbd->dev);
@@ -1271,21 +1271,16 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
        atkbd_set_keycode_table(atkbd);
        atkbd_set_device_attrs(atkbd);
 
-       err = sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group);
-       if (err)
-               goto fail3;
-
        atkbd_enable(atkbd);
        if (serio->write)
                atkbd_activate(atkbd);
 
        err = input_register_device(atkbd->dev);
        if (err)
-               goto fail4;
+               goto fail3;
 
        return 0;
 
- fail4: sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
  fail3:        serio_close(serio);
  fail2:        serio_set_drvdata(serio, NULL);
  fail1:        input_free_device(dev);
@@ -1378,7 +1373,8 @@ MODULE_DEVICE_TABLE(serio, atkbd_serio_ids);
 
 static struct serio_driver atkbd_drv = {
        .driver         = {
-               .name   = "atkbd",
+               .name           = "atkbd",
+               .dev_groups     = atkbd_attribute_groups,
        },
        .description    = DRIVER_DESC,
        .id_table       = atkbd_serio_ids,
index 939c886..4c1a3e6 100644 (file)
@@ -6,9 +6,11 @@
  */
 
 #include <linux/input.h>
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
-#include <linux/of_gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/platform_device.h>
+#include <linux/property.h>
 #include <linux/regmap.h>
 #include <linux/sched.h>
 #include <linux/input/matrix_keypad.h>
@@ -86,7 +88,6 @@ static int clps711x_keypad_probe(struct platform_device *pdev)
 {
        struct clps711x_keypad_data *priv;
        struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
        struct input_dev *input;
        u32 poll_interval;
        int i, err;
@@ -95,11 +96,11 @@ static int clps711x_keypad_probe(struct platform_device *pdev)
        if (!priv)
                return -ENOMEM;
 
-       priv->syscon = syscon_regmap_lookup_by_phandle(np, "syscon");
+       priv->syscon = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
        if (IS_ERR(priv->syscon))
                return PTR_ERR(priv->syscon);
 
-       priv->row_count = of_gpio_named_count(np, "row-gpios");
+       priv->row_count = gpiod_count(dev, "row");
        if (priv->row_count < 1)
                return -EINVAL;
 
@@ -119,7 +120,7 @@ static int clps711x_keypad_probe(struct platform_device *pdev)
                        return PTR_ERR(data->desc);
        }
 
-       err = of_property_read_u32(np, "poll-interval", &poll_interval);
+       err = device_property_read_u32(dev, "poll-interval", &poll_interval);
        if (err)
                return err;
 
@@ -143,7 +144,7 @@ static int clps711x_keypad_probe(struct platform_device *pdev)
                return err;
 
        input_set_capability(input, EV_MSC, MSC_SCAN);
-       if (of_property_read_bool(np, "autorepeat"))
+       if (device_property_read_bool(dev, "autorepeat"))
                __set_bit(EV_REP, input->evbit);
 
        /* Set all columns to low */
index 7a3b066..f5bf752 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/input.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/slab.h>
 #include <linux/soc/cirrus/ep93xx.h>
index ae93038..e15a936 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/err.h>
+#include <linux/input.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
index e4a1839..047b654 100644 (file)
@@ -46,9 +46,6 @@
  * http://www.vt100.net/manx/details?pn=EK-104AA-TM-001;id=21;cp=1
  */
 
-/*
- */
-
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -359,18 +356,18 @@ static void lkkbd_detection_done(struct lkkbd *lk)
         */
        switch (lk->id[4]) {
        case 1:
-               strlcpy(lk->name, "DEC LK201 keyboard", sizeof(lk->name));
+               strscpy(lk->name, "DEC LK201 keyboard", sizeof(lk->name));
 
                if (lk201_compose_is_alt)
                        lk->keycode[0xb1] = KEY_LEFTALT;
                break;
 
        case 2:
-               strlcpy(lk->name, "DEC LK401 keyboard", sizeof(lk->name));
+               strscpy(lk->name, "DEC LK401 keyboard", sizeof(lk->name));
                break;
 
        default:
-               strlcpy(lk->name, "Unknown DEC keyboard", sizeof(lk->name));
+               strscpy(lk->name, "Unknown DEC keyboard", sizeof(lk->name));
                printk(KERN_ERR
                        "lkkbd: keyboard on %s is unknown, please report to "
                        "Jan-Benedict Glaw <jbglaw@lug-owl.de>\n", lk->phys);
@@ -626,7 +623,7 @@ static int lkkbd_connect(struct serio *serio, struct serio_driver *drv)
        lk->ctrlclick_volume = ctrlclick_volume;
        memcpy(lk->keycode, lkkbd_keycode, sizeof(lk->keycode));
 
-       strlcpy(lk->name, "DEC LK keyboard", sizeof(lk->name));
+       strscpy(lk->name, "DEC LK keyboard", sizeof(lk->name));
        snprintf(lk->phys, sizeof(lk->phys), "%s/input0", serio->phys);
 
        input_dev->name = lk->name;
index 9dac22c..3052cd6 100644 (file)
@@ -4,13 +4,13 @@
  * Copyright (C) 2012 Wolfram Sang, Pengutronix <kernel@pengutronix.de>
  */
 
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/irq.h>
 #include <linux/i2c.h>
-#include <linux/interrupt.h>
+#include <linux/input.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/input/lm8333.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/slab.h>
 
 #define LM8333_FIFO_READ               0x20
 #define LM8333_DEBOUNCE                        0x22
index 30924b5..7dd3f3e 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/types.h>
 #include <linux/delay.h>
+#include <linux/gpio/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/input.h>
 #include <linux/irq.h>
@@ -416,9 +417,9 @@ matrix_keypad_parse_dt(struct device *dev)
                return ERR_PTR(-ENOMEM);
        }
 
-       pdata->num_row_gpios = nrow = of_gpio_named_count(np, "row-gpios");
-       pdata->num_col_gpios = ncol = of_gpio_named_count(np, "col-gpios");
-       if (nrow <= 0 || ncol <= 0) {
+       pdata->num_row_gpios = nrow = gpiod_count(dev, "row");
+       pdata->num_col_gpios = ncol = gpiod_count(dev, "col");
+       if (nrow < 0 || ncol < 0) {
                dev_err(dev, "number of keypad rows/columns not specified\n");
                return ERR_PTR(-EINVAL);
        }
index bf447bf..19f69d1 100644 (file)
@@ -5,6 +5,7 @@
  */
 #include <linux/bitops.h>
 #include <linux/clk.h>
+#include <linux/input.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
@@ -18,6 +19,7 @@
 #define MTK_KPD_DEBOUNCE_MASK  GENMASK(13, 0)
 #define MTK_KPD_DEBOUNCE_MAX_MS        256
 #define MTK_KPD_SEL            0x0020
+#define MTK_KPD_SEL_DOUBLE_KP_MODE     BIT(0)
 #define MTK_KPD_SEL_COL        GENMASK(15, 10)
 #define MTK_KPD_SEL_ROW        GENMASK(9, 4)
 #define MTK_KPD_SEL_COLMASK(c) GENMASK((c) + 9, 10)
@@ -31,6 +33,8 @@ struct mt6779_keypad {
        struct clk *clk;
        u32 n_rows;
        u32 n_cols;
+       void (*calc_row_col)(unsigned int key,
+                            unsigned int *row, unsigned int *col);
        DECLARE_BITMAP(keymap_state, MTK_KPD_NUM_BITS);
 };
 
@@ -67,8 +71,7 @@ static irqreturn_t mt6779_keypad_irq_handler(int irq, void *dev_id)
                        continue;
 
                key = bit_nr / 32 * 16 + bit_nr % 32;
-               row = key / 9;
-               col = key % 9;
+               keypad->calc_row_col(key, &row, &col);
 
                scancode = MATRIX_SCAN_CODE(row, col, row_shift);
                /* 1: not pressed, 0: pressed */
@@ -94,12 +97,29 @@ static void mt6779_keypad_clk_disable(void *data)
        clk_disable_unprepare(data);
 }
 
+static void mt6779_keypad_calc_row_col_single(unsigned int key,
+                                             unsigned int *row,
+                                             unsigned int *col)
+{
+       *row = key / 9;
+       *col = key % 9;
+}
+
+static void mt6779_keypad_calc_row_col_double(unsigned int key,
+                                             unsigned int *row,
+                                             unsigned int *col)
+{
+       *row = key / 13;
+       *col = (key % 13) / 2;
+}
+
 static int mt6779_keypad_pdrv_probe(struct platform_device *pdev)
 {
        struct mt6779_keypad *keypad;
        void __iomem *base;
        int irq;
        u32 debounce;
+       u32 keys_per_group;
        bool wakeup;
        int error;
 
@@ -148,6 +168,23 @@ static int mt6779_keypad_pdrv_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
+       if (device_property_read_u32(&pdev->dev, "mediatek,keys-per-group",
+                                    &keys_per_group))
+               keys_per_group = 1;
+
+       switch (keys_per_group) {
+       case 1:
+               keypad->calc_row_col = mt6779_keypad_calc_row_col_single;
+               break;
+       case 2:
+               keypad->calc_row_col = mt6779_keypad_calc_row_col_double;
+               break;
+       default:
+               dev_err(&pdev->dev,
+                       "Invalid keys-per-group: %d\n", keys_per_group);
+               return -EINVAL;
+       }
+
        wakeup = device_property_read_bool(&pdev->dev, "wakeup-source");
 
        dev_dbg(&pdev->dev, "n_row=%d n_col=%d debounce=%d\n",
@@ -166,6 +203,11 @@ static int mt6779_keypad_pdrv_probe(struct platform_device *pdev)
        regmap_write(keypad->regmap, MTK_KPD_DEBOUNCE,
                     (debounce * (1 << 5)) & MTK_KPD_DEBOUNCE_MASK);
 
+       if (keys_per_group == 2)
+               regmap_update_bits(keypad->regmap, MTK_KPD_SEL,
+                                  MTK_KPD_SEL_DOUBLE_KP_MODE,
+                                  MTK_KPD_SEL_DOUBLE_KP_MODE);
+
        regmap_update_bits(keypad->regmap, MTK_KPD_SEL, MTK_KPD_SEL_ROW,
                           MTK_KPD_SEL_ROWMASK(keypad->n_rows));
        regmap_update_bits(keypad->regmap, MTK_KPD_SEL, MTK_KPD_SEL_COL,
index 6404081..9b34da0 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/mfd/mt6323/registers.h>
+#include <linux/mfd/mt6331/registers.h>
 #include <linux/mfd/mt6358/registers.h>
 #include <linux/mfd/mt6397/core.h>
 #include <linux/mfd/mt6397/registers.h>
 #define MTK_PMIC_PWRKEY_RST    BIT(6)
 #define MTK_PMIC_HOMEKEY_RST   BIT(5)
 
+#define MTK_PMIC_MT6331_RST_DU_MASK    GENMASK(13, 12)
+#define MTK_PMIC_MT6331_PWRKEY_RST     BIT(9)
+#define MTK_PMIC_MT6331_HOMEKEY_RST    BIT(8)
+
 #define MTK_PMIC_PWRKEY_INDEX  0
 #define MTK_PMIC_HOMEKEY_INDEX 1
 #define MTK_PMIC_MAX_KEY_COUNT 2
@@ -72,6 +77,19 @@ static const struct mtk_pmic_regs mt6323_regs = {
        .rst_lprst_mask = MTK_PMIC_RST_DU_MASK,
 };
 
+static const struct mtk_pmic_regs mt6331_regs = {
+       .keys_regs[MTK_PMIC_PWRKEY_INDEX] =
+               MTK_PMIC_KEYS_REGS(MT6331_TOPSTATUS, 0x2,
+                                  MT6331_INT_MISC_CON, 0x4,
+                                  MTK_PMIC_MT6331_PWRKEY_RST),
+       .keys_regs[MTK_PMIC_HOMEKEY_INDEX] =
+               MTK_PMIC_KEYS_REGS(MT6331_TOPSTATUS, 0x4,
+                                  MT6331_INT_MISC_CON, 0x2,
+                                  MTK_PMIC_MT6331_HOMEKEY_RST),
+       .pmic_rst_reg = MT6331_TOP_RST_MISC,
+       .rst_lprst_mask = MTK_PMIC_MT6331_RST_DU_MASK,
+};
+
 static const struct mtk_pmic_regs mt6358_regs = {
        .keys_regs[MTK_PMIC_PWRKEY_INDEX] =
                MTK_PMIC_KEYS_REGS(MT6358_TOPSTATUS,
@@ -256,6 +274,9 @@ static const struct of_device_id of_mtk_pmic_keys_match_tbl[] = {
                .compatible = "mediatek,mt6323-keys",
                .data = &mt6323_regs,
        }, {
+               .compatible = "mediatek,mt6331-keys",
+               .data = &mt6331_regs,
+       }, {
                .compatible = "mediatek,mt6358-keys",
                .data = &mt6358_regs,
        }, {
index 9742261..df00a11 100644 (file)
@@ -7,9 +7,6 @@
  * Newton keyboard driver for Linux
  */
 
-/*
- */
-
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/input.h>
diff --git a/drivers/input/keyboard/pinephone-keyboard.c b/drivers/input/keyboard/pinephone-keyboard.c
new file mode 100644 (file)
index 0000000..5548699
--- /dev/null
@@ -0,0 +1,468 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
+
+#include <linux/crc8.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/matrix_keypad.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+#include <linux/types.h>
+
+#define DRV_NAME                       "pinephone-keyboard"
+
+#define PPKB_CRC8_POLYNOMIAL           0x07
+
+#define PPKB_DEVICE_ID_HI              0x00
+#define PPKB_DEVICE_ID_HI_VALUE                        'K'
+#define PPKB_DEVICE_ID_LO              0x01
+#define PPKB_DEVICE_ID_LO_VALUE                        'B'
+#define PPKB_FW_REVISION               0x02
+#define PPKB_FW_FEATURES               0x03
+#define PPKB_MATRIX_SIZE               0x06
+#define PPKB_SCAN_CRC                  0x07
+#define PPKB_SCAN_DATA                 0x08
+#define PPKB_SYS_CONFIG                        0x20
+#define PPKB_SYS_CONFIG_DISABLE_SCAN           BIT(0)
+#define PPKB_SYS_SMBUS_COMMAND         0x21
+#define PPKB_SYS_SMBUS_DATA            0x22
+#define PPKB_SYS_COMMAND               0x23
+#define PPKB_SYS_COMMAND_SMBUS_READ            0x91
+#define PPKB_SYS_COMMAND_SMBUS_WRITE           0xa1
+
+#define PPKB_ROWS                      6
+#define PPKB_COLS                      12
+
+/* Size of the scan buffer, including the CRC byte at the beginning. */
+#define PPKB_BUF_LEN                   (1 + PPKB_COLS)
+
+static const uint32_t ppkb_keymap[] = {
+       KEY(0,  0, KEY_ESC),
+       KEY(0,  1, KEY_1),
+       KEY(0,  2, KEY_2),
+       KEY(0,  3, KEY_3),
+       KEY(0,  4, KEY_4),
+       KEY(0,  5, KEY_5),
+       KEY(0,  6, KEY_6),
+       KEY(0,  7, KEY_7),
+       KEY(0,  8, KEY_8),
+       KEY(0,  9, KEY_9),
+       KEY(0, 10, KEY_0),
+       KEY(0, 11, KEY_BACKSPACE),
+
+       KEY(1,  0, KEY_TAB),
+       KEY(1,  1, KEY_Q),
+       KEY(1,  2, KEY_W),
+       KEY(1,  3, KEY_E),
+       KEY(1,  4, KEY_R),
+       KEY(1,  5, KEY_T),
+       KEY(1,  6, KEY_Y),
+       KEY(1,  7, KEY_U),
+       KEY(1,  8, KEY_I),
+       KEY(1,  9, KEY_O),
+       KEY(1, 10, KEY_P),
+       KEY(1, 11, KEY_ENTER),
+
+       KEY(2,  0, KEY_LEFTMETA),
+       KEY(2,  1, KEY_A),
+       KEY(2,  2, KEY_S),
+       KEY(2,  3, KEY_D),
+       KEY(2,  4, KEY_F),
+       KEY(2,  5, KEY_G),
+       KEY(2,  6, KEY_H),
+       KEY(2,  7, KEY_J),
+       KEY(2,  8, KEY_K),
+       KEY(2,  9, KEY_L),
+       KEY(2, 10, KEY_SEMICOLON),
+
+       KEY(3,  0, KEY_LEFTSHIFT),
+       KEY(3,  1, KEY_Z),
+       KEY(3,  2, KEY_X),
+       KEY(3,  3, KEY_C),
+       KEY(3,  4, KEY_V),
+       KEY(3,  5, KEY_B),
+       KEY(3,  6, KEY_N),
+       KEY(3,  7, KEY_M),
+       KEY(3,  8, KEY_COMMA),
+       KEY(3,  9, KEY_DOT),
+       KEY(3, 10, KEY_SLASH),
+
+       KEY(4,  1, KEY_LEFTCTRL),
+       KEY(4,  4, KEY_SPACE),
+       KEY(4,  6, KEY_APOSTROPHE),
+       KEY(4,  8, KEY_RIGHTBRACE),
+       KEY(4,  9, KEY_LEFTBRACE),
+
+       KEY(5,  2, KEY_FN),
+       KEY(5,  3, KEY_LEFTALT),
+       KEY(5,  5, KEY_RIGHTALT),
+
+       /* FN layer */
+       KEY(PPKB_ROWS + 0,  0, KEY_FN_ESC),
+       KEY(PPKB_ROWS + 0,  1, KEY_F1),
+       KEY(PPKB_ROWS + 0,  2, KEY_F2),
+       KEY(PPKB_ROWS + 0,  3, KEY_F3),
+       KEY(PPKB_ROWS + 0,  4, KEY_F4),
+       KEY(PPKB_ROWS + 0,  5, KEY_F5),
+       KEY(PPKB_ROWS + 0,  6, KEY_F6),
+       KEY(PPKB_ROWS + 0,  7, KEY_F7),
+       KEY(PPKB_ROWS + 0,  8, KEY_F8),
+       KEY(PPKB_ROWS + 0,  9, KEY_F9),
+       KEY(PPKB_ROWS + 0, 10, KEY_F10),
+       KEY(PPKB_ROWS + 0, 11, KEY_DELETE),
+
+       KEY(PPKB_ROWS + 1, 10, KEY_PAGEUP),
+
+       KEY(PPKB_ROWS + 2,  0, KEY_SYSRQ),
+       KEY(PPKB_ROWS + 2,  9, KEY_PAGEDOWN),
+       KEY(PPKB_ROWS + 2, 10, KEY_INSERT),
+
+       KEY(PPKB_ROWS + 3,  0, KEY_LEFTSHIFT),
+       KEY(PPKB_ROWS + 3,  8, KEY_HOME),
+       KEY(PPKB_ROWS + 3,  9, KEY_UP),
+       KEY(PPKB_ROWS + 3, 10, KEY_END),
+
+       KEY(PPKB_ROWS + 4, 1, KEY_LEFTCTRL),
+       KEY(PPKB_ROWS + 4, 6, KEY_LEFT),
+       KEY(PPKB_ROWS + 4, 8, KEY_RIGHT),
+       KEY(PPKB_ROWS + 4, 9, KEY_DOWN),
+
+       KEY(PPKB_ROWS + 5, 3, KEY_LEFTALT),
+       KEY(PPKB_ROWS + 5, 5, KEY_RIGHTALT),
+};
+
+static const struct matrix_keymap_data ppkb_keymap_data = {
+       .keymap         = ppkb_keymap,
+       .keymap_size    = ARRAY_SIZE(ppkb_keymap),
+};
+
+struct pinephone_keyboard {
+       struct i2c_adapter adapter;
+       struct input_dev *input;
+       u8 buf[2][PPKB_BUF_LEN];
+       u8 crc_table[CRC8_TABLE_SIZE];
+       u8 fn_state[PPKB_COLS];
+       bool buf_swap;
+       bool fn_pressed;
+};
+
+static int ppkb_adap_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+                               unsigned short flags, char read_write,
+                               u8 command, int size,
+                               union i2c_smbus_data *data)
+{
+       struct i2c_client *client = adap->algo_data;
+       u8 buf[3];
+       int ret;
+
+       buf[0] = command;
+       buf[1] = data->byte;
+       buf[2] = read_write == I2C_SMBUS_READ ? PPKB_SYS_COMMAND_SMBUS_READ
+                                             : PPKB_SYS_COMMAND_SMBUS_WRITE;
+
+       ret = i2c_smbus_write_i2c_block_data(client, PPKB_SYS_SMBUS_COMMAND,
+                                            sizeof(buf), buf);
+       if (ret)
+               return ret;
+
+       /* Read back the command status until it passes or fails. */
+       do {
+               usleep_range(300, 500);
+               ret = i2c_smbus_read_byte_data(client, PPKB_SYS_COMMAND);
+       } while (ret == buf[2]);
+       if (ret < 0)
+               return ret;
+       /* Commands return 0x00 on success and 0xff on failure. */
+       if (ret)
+               return -EIO;
+
+       if (read_write == I2C_SMBUS_READ) {
+               ret = i2c_smbus_read_byte_data(client, PPKB_SYS_SMBUS_DATA);
+               if (ret < 0)
+                       return ret;
+
+               data->byte = ret;
+       }
+
+       return 0;
+}
+
+static u32 ppkg_adap_functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_BYTE_DATA;
+}
+
+static const struct i2c_algorithm ppkb_adap_algo = {
+       .smbus_xfer             = ppkb_adap_smbus_xfer,
+       .functionality          = ppkg_adap_functionality,
+};
+
+static void ppkb_update(struct i2c_client *client)
+{
+       struct pinephone_keyboard *ppkb = i2c_get_clientdata(client);
+       unsigned short *keymap = ppkb->input->keycode;
+       int row_shift = get_count_order(PPKB_COLS);
+       u8 *old_buf = ppkb->buf[!ppkb->buf_swap];
+       u8 *new_buf = ppkb->buf[ppkb->buf_swap];
+       int col, crc, ret, row;
+       struct device *dev = &client->dev;
+
+       ret = i2c_smbus_read_i2c_block_data(client, PPKB_SCAN_CRC,
+                                           PPKB_BUF_LEN, new_buf);
+       if (ret != PPKB_BUF_LEN) {
+               dev_err(dev, "Failed to read scan data: %d\n", ret);
+               return;
+       }
+
+       crc = crc8(ppkb->crc_table, &new_buf[1], PPKB_COLS, CRC8_INIT_VALUE);
+       if (crc != new_buf[0]) {
+               dev_err(dev, "Bad scan data (%02x != %02x)\n", crc, new_buf[0]);
+               return;
+       }
+
+       ppkb->buf_swap = !ppkb->buf_swap;
+
+       for (col = 0; col < PPKB_COLS; ++col) {
+               u8 old = old_buf[1 + col];
+               u8 new = new_buf[1 + col];
+               u8 changed = old ^ new;
+
+               if (!changed)
+                       continue;
+
+               for (row = 0; row < PPKB_ROWS; ++row) {
+                       u8 mask = BIT(row);
+                       u8 value = new & mask;
+                       unsigned short code;
+                       bool fn_state;
+
+                       if (!(changed & mask))
+                               continue;
+
+                       /*
+                        * Save off the FN key state when the key was pressed,
+                        * and use that to determine the code during a release.
+                        */
+                       fn_state = value ? ppkb->fn_pressed : ppkb->fn_state[col] & mask;
+                       if (fn_state)
+                               ppkb->fn_state[col] ^= mask;
+
+                       /* The FN layer is a second set of rows. */
+                       code = MATRIX_SCAN_CODE(fn_state ? PPKB_ROWS + row : row,
+                                               col, row_shift);
+                       input_event(ppkb->input, EV_MSC, MSC_SCAN, code);
+                       input_report_key(ppkb->input, keymap[code], value);
+                       if (keymap[code] == KEY_FN)
+                               ppkb->fn_pressed = value;
+               }
+       }
+       input_sync(ppkb->input);
+}
+
+static irqreturn_t ppkb_irq_thread(int irq, void *data)
+{
+       struct i2c_client *client = data;
+
+       ppkb_update(client);
+
+       return IRQ_HANDLED;
+}
+
+static int ppkb_set_scan(struct i2c_client *client, bool enable)
+{
+       struct device *dev = &client->dev;
+       int ret, val;
+
+       ret = i2c_smbus_read_byte_data(client, PPKB_SYS_CONFIG);
+       if (ret < 0) {
+               dev_err(dev, "Failed to read config: %d\n", ret);
+               return ret;
+       }
+
+       if (enable)
+               val = ret & ~PPKB_SYS_CONFIG_DISABLE_SCAN;
+       else
+               val = ret | PPKB_SYS_CONFIG_DISABLE_SCAN;
+
+       ret = i2c_smbus_write_byte_data(client, PPKB_SYS_CONFIG, val);
+       if (ret) {
+               dev_err(dev, "Failed to write config: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int ppkb_open(struct input_dev *input)
+{
+       struct i2c_client *client = input_get_drvdata(input);
+       int error;
+
+       error = ppkb_set_scan(client, true);
+       if (error)
+               return error;
+
+       return 0;
+}
+
+static void ppkb_close(struct input_dev *input)
+{
+       struct i2c_client *client = input_get_drvdata(input);
+
+       ppkb_set_scan(client, false);
+}
+
+static void ppkb_regulator_disable(void *regulator)
+{
+       regulator_disable(regulator);
+}
+
+static int ppkb_probe(struct i2c_client *client)
+{
+       struct device *dev = &client->dev;
+       unsigned int phys_rows, phys_cols;
+       struct pinephone_keyboard *ppkb;
+       struct regulator *vbat_supply;
+       u8 info[PPKB_MATRIX_SIZE + 1];
+       struct device_node *i2c_bus;
+       int ret;
+       int error;
+
+       vbat_supply = devm_regulator_get(dev, "vbat");
+       error = PTR_ERR_OR_ZERO(vbat_supply);
+       if (error) {
+               dev_err(dev, "Failed to get VBAT supply: %d\n", error);
+               return error;
+       }
+
+       error = regulator_enable(vbat_supply);
+       if (error) {
+               dev_err(dev, "Failed to enable VBAT: %d\n", error);
+               return error;
+       }
+
+       error = devm_add_action_or_reset(dev, ppkb_regulator_disable,
+                                        vbat_supply);
+       if (error)
+               return error;
+
+       ret = i2c_smbus_read_i2c_block_data(client, 0, sizeof(info), info);
+       if (ret != sizeof(info)) {
+               error = ret < 0 ? ret : -EIO;
+               dev_err(dev, "Failed to read device ID: %d\n", error);
+               return error;
+       }
+
+       if (info[PPKB_DEVICE_ID_HI] != PPKB_DEVICE_ID_HI_VALUE ||
+           info[PPKB_DEVICE_ID_LO] != PPKB_DEVICE_ID_LO_VALUE) {
+               dev_warn(dev, "Unexpected device ID: %#02x %#02x\n",
+                        info[PPKB_DEVICE_ID_HI], info[PPKB_DEVICE_ID_LO]);
+               return -ENODEV;
+       }
+
+       dev_info(dev, "Found firmware version %d.%d features %#x\n",
+                info[PPKB_FW_REVISION] >> 4,
+                info[PPKB_FW_REVISION] & 0xf,
+                info[PPKB_FW_FEATURES]);
+
+       phys_rows = info[PPKB_MATRIX_SIZE] & 0xf;
+       phys_cols = info[PPKB_MATRIX_SIZE] >> 4;
+       if (phys_rows != PPKB_ROWS || phys_cols != PPKB_COLS) {
+               dev_err(dev, "Unexpected keyboard size %ux%u\n",
+                       phys_rows, phys_cols);
+               return -EINVAL;
+       }
+
+       /* Disable scan by default to save power. */
+       error = ppkb_set_scan(client, false);
+       if (error)
+               return error;
+
+       ppkb = devm_kzalloc(dev, sizeof(*ppkb), GFP_KERNEL);
+       if (!ppkb)
+               return -ENOMEM;
+
+       i2c_set_clientdata(client, ppkb);
+
+       i2c_bus = of_get_child_by_name(dev->of_node, "i2c");
+       if (i2c_bus) {
+               ppkb->adapter.owner = THIS_MODULE;
+               ppkb->adapter.algo = &ppkb_adap_algo;
+               ppkb->adapter.algo_data = client;
+               ppkb->adapter.dev.parent = dev;
+               ppkb->adapter.dev.of_node = i2c_bus;
+               strscpy(ppkb->adapter.name, DRV_NAME, sizeof(ppkb->adapter.name));
+
+               error = devm_i2c_add_adapter(dev, &ppkb->adapter);
+               if (error) {
+                       dev_err(dev, "Failed to add I2C adapter: %d\n", error);
+                       return error;
+               }
+       }
+
+       crc8_populate_msb(ppkb->crc_table, PPKB_CRC8_POLYNOMIAL);
+
+       ppkb->input = devm_input_allocate_device(dev);
+       if (!ppkb->input)
+               return -ENOMEM;
+
+       input_set_drvdata(ppkb->input, client);
+
+       ppkb->input->name = "PinePhone Keyboard";
+       ppkb->input->phys = DRV_NAME "/input0";
+       ppkb->input->id.bustype = BUS_I2C;
+       ppkb->input->open = ppkb_open;
+       ppkb->input->close = ppkb_close;
+
+       input_set_capability(ppkb->input, EV_MSC, MSC_SCAN);
+       __set_bit(EV_REP, ppkb->input->evbit);
+
+       error = matrix_keypad_build_keymap(&ppkb_keymap_data, NULL,
+                                          2 * PPKB_ROWS, PPKB_COLS, NULL,
+                                          ppkb->input);
+       if (error) {
+               dev_err(dev, "Failed to build keymap: %d\n", error);
+               return error;
+       }
+
+       error = input_register_device(ppkb->input);
+       if (error) {
+               dev_err(dev, "Failed to register input: %d\n", error);
+               return error;
+       }
+
+       error = devm_request_threaded_irq(dev, client->irq,
+                                         NULL, ppkb_irq_thread,
+                                         IRQF_ONESHOT, client->name, client);
+       if (error) {
+               dev_err(dev, "Failed to request IRQ: %d\n", error);
+               return error;
+       }
+
+       return 0;
+}
+
+static const struct of_device_id ppkb_of_match[] = {
+       { .compatible = "pine64,pinephone-keyboard" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ppkb_of_match);
+
+static struct i2c_driver ppkb_driver = {
+       .probe_new      = ppkb_probe,
+       .driver         = {
+               .name           = DRV_NAME,
+               .of_match_table = ppkb_of_match,
+       },
+};
+module_i2c_driver(ppkb_driver);
+
+MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
+MODULE_DESCRIPTION("Pine64 PinePhone keyboard driver");
+MODULE_LICENSE("GPL");
index a045d61..a62bb8f 100644 (file)
@@ -8,12 +8,14 @@
  * Based on sh_keysc.c, copyright 2008 Magnus Damm
  */
 
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
 #include <linux/clk.h>
-#include <linux/io.h>
+#include <linux/input.h>
 #include <linux/input/matrix_keypad.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 #define ST_KEYSCAN_MAXKEYS 16
 
index a497719..56e7849 100644 (file)
@@ -10,9 +10,6 @@
  *  by Justin Cormack
  */
 
-/*
- */
-
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/input.h>
index d450f11..b123a20 100644 (file)
@@ -7,9 +7,6 @@
  * Sun keyboard driver for Linux
  */
 
-/*
- */
-
 #include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
index 89b9575..78e5531 100644 (file)
@@ -70,7 +70,7 @@
 #define TC3589x_KBD_INT_CLR    0x1
 
 /**
- * struct tc35893_keypad_platform_data - platform specific keypad data
+ * struct tc3589x_keypad_platform_data - platform specific keypad data
  * @keymap_data:        matrix scan code table for keycodes
  * @krow:               mask for available rows, value is 0xFF
  * @kcol:               mask for available columns, value is 0xFF
index 280796d..c9d7c24 100644 (file)
@@ -7,9 +7,6 @@
  * XT keyboard driver for Linux
  */
 
-/*
- */
-
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/input.h>
index a18ab73..9f08890 100644 (file)
@@ -730,6 +730,24 @@ config INPUT_ADXL34X_SPI
          To compile this driver as a module, choose M here: the
          module will be called adxl34x-spi.
 
+config INPUT_IBM_PANEL
+       tristate "IBM Operation Panel driver"
+       depends on I2C && I2C_SLAVE
+       help
+         Say Y here if you have an IBM Operation Panel connected to your system
+         over I2C. The panel is typically connected only to a system's service
+         processor (BMC).
+
+         If unsure, say N.
+
+         The Operation Panel is a controller with some buttons and an LCD
+         display that allows someone with physical access to the system to
+         perform various administrative tasks. This driver only supports the part
+         of the controller that sends commands to the system.
+
+         To compile this driver as a module, choose M here: the module will be
+         called ibm-panel.
+
 config INPUT_IMS_PCU
        tristate "IMS Passenger Control Unit driver"
        depends on USB
@@ -891,6 +909,15 @@ config INPUT_SC27XX_VIBRA
          To compile this driver as a module, choose M here. The module will
          be called sc27xx_vibra.
 
+config INPUT_RT5120_PWRKEY
+       tristate "RT5120 PMIC power key support"
+       depends on MFD_RT5120 || COMPILE_TEST
+       help
+         This enables support for RT5120 PMIC power key driver.
+
+         To compile this driver as a module, choose M here. the module will
+         be called rt5120-pwrkey.
+
 config INPUT_STPMIC1_ONKEY
        tristate "STPMIC1 PMIC Onkey support"
        depends on MFD_STPMIC1
index 28dfc44..6abefc4 100644 (file)
@@ -41,6 +41,7 @@ obj-$(CONFIG_INPUT_GPIO_DECODER)      += gpio_decoder.o
 obj-$(CONFIG_INPUT_GPIO_VIBRA)         += gpio-vibra.o
 obj-$(CONFIG_INPUT_HISI_POWERKEY)      += hisi_powerkey.o
 obj-$(CONFIG_HP_SDC_RTC)               += hp_sdc_rtc.o
+obj-$(CONFIG_INPUT_IBM_PANEL)          += ibm-panel.o
 obj-$(CONFIG_INPUT_IMS_PCU)            += ims-pcu.o
 obj-$(CONFIG_INPUT_IQS269A)            += iqs269a.o
 obj-$(CONFIG_INPUT_IQS626A)            += iqs626a.o
@@ -69,6 +70,7 @@ obj-$(CONFIG_INPUT_RAVE_SP_PWRBUTTON) += rave-sp-pwrbutton.o
 obj-$(CONFIG_INPUT_RB532_BUTTON)       += rb532_button.o
 obj-$(CONFIG_INPUT_REGULATOR_HAPTIC)   += regulator-haptic.o
 obj-$(CONFIG_INPUT_RETU_PWRBUTTON)     += retu-pwrbutton.o
+obj-$(CONFIG_INPUT_RT5120_PWRKEY)      += rt5120-pwrkey.o
 obj-$(CONFIG_INPUT_AXP20X_PEK)         += axp20x-pek.o
 obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER)        += rotary_encoder.o
 obj-$(CONFIG_INPUT_RK805_PWRKEY)       += rk805-pwrkey.o
diff --git a/drivers/input/misc/ibm-panel.c b/drivers/input/misc/ibm-panel.c
new file mode 100644 (file)
index 0000000..a8fba00
--- /dev/null
@@ -0,0 +1,200 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) IBM Corporation 2020
+ */
+
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/limits.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/spinlock.h>
+
+#define DEVICE_NAME            "ibm-panel"
+#define PANEL_KEYCODES_COUNT   3
+
+struct ibm_panel {
+       u8 idx;
+       u8 command[11];
+       u32 keycodes[PANEL_KEYCODES_COUNT];
+       spinlock_t lock;        /* protects writes to idx and command */
+       struct input_dev *input;
+};
+
+static u8 ibm_panel_calculate_checksum(struct ibm_panel *panel)
+{
+       u8 chksum;
+       u16 sum = 0;
+       unsigned int i;
+
+       for (i = 0; i < sizeof(panel->command) - 1; ++i) {
+               sum += panel->command[i];
+               if (sum & 0xff00) {
+                       sum &= 0xff;
+                       sum++;
+               }
+       }
+
+       chksum = sum & 0xff;
+       chksum = ~chksum;
+       chksum++;
+
+       return chksum;
+}
+
+static void ibm_panel_process_command(struct ibm_panel *panel)
+{
+       u8 button;
+       u8 chksum;
+
+       if (panel->command[0] != 0xff && panel->command[1] != 0xf0) {
+               dev_dbg(&panel->input->dev, "command invalid: %02x %02x\n",
+                       panel->command[0], panel->command[1]);
+               return;
+       }
+
+       chksum = ibm_panel_calculate_checksum(panel);
+       if (chksum != panel->command[sizeof(panel->command) - 1]) {
+               dev_dbg(&panel->input->dev,
+                       "command failed checksum: %u != %u\n", chksum,
+                       panel->command[sizeof(panel->command) - 1]);
+               return;
+       }
+
+       button = panel->command[2] & 0xf;
+       if (button < PANEL_KEYCODES_COUNT) {
+               input_report_key(panel->input, panel->keycodes[button],
+                                !(panel->command[2] & 0x80));
+               input_sync(panel->input);
+       } else {
+               dev_dbg(&panel->input->dev, "unknown button %u\n",
+                       button);
+       }
+}
+
+static int ibm_panel_i2c_slave_cb(struct i2c_client *client,
+                                 enum i2c_slave_event event, u8 *val)
+{
+       unsigned long flags;
+       struct ibm_panel *panel = i2c_get_clientdata(client);
+
+       dev_dbg(&panel->input->dev, "event: %u data: %02x\n", event, *val);
+
+       spin_lock_irqsave(&panel->lock, flags);
+
+       switch (event) {
+       case I2C_SLAVE_STOP:
+               if (panel->idx == sizeof(panel->command))
+                       ibm_panel_process_command(panel);
+               else
+                       dev_dbg(&panel->input->dev,
+                               "command incorrect size %u\n", panel->idx);
+               fallthrough;
+       case I2C_SLAVE_WRITE_REQUESTED:
+               panel->idx = 0;
+               break;
+       case I2C_SLAVE_WRITE_RECEIVED:
+               if (panel->idx < sizeof(panel->command))
+                       panel->command[panel->idx++] = *val;
+               else
+                       /*
+                        * The command is too long and therefore invalid, so set the index
+                        * to it's largest possible value. When a STOP is finally received,
+                        * the command will be rejected upon processing.
+                        */
+                       panel->idx = U8_MAX;
+               break;
+       case I2C_SLAVE_READ_REQUESTED:
+       case I2C_SLAVE_READ_PROCESSED:
+               *val = 0xff;
+               break;
+       default:
+               break;
+       }
+
+       spin_unlock_irqrestore(&panel->lock, flags);
+
+       return 0;
+}
+
+static int ibm_panel_probe(struct i2c_client *client,
+                          const struct i2c_device_id *id)
+{
+       struct ibm_panel *panel;
+       int i;
+       int error;
+
+       panel = devm_kzalloc(&client->dev, sizeof(*panel), GFP_KERNEL);
+       if (!panel)
+               return -ENOMEM;
+
+       spin_lock_init(&panel->lock);
+
+       panel->input = devm_input_allocate_device(&client->dev);
+       if (!panel->input)
+               return -ENOMEM;
+
+       panel->input->name = client->name;
+       panel->input->id.bustype = BUS_I2C;
+
+       error = device_property_read_u32_array(&client->dev,
+                                              "linux,keycodes",
+                                              panel->keycodes,
+                                              PANEL_KEYCODES_COUNT);
+       if (error) {
+               /*
+                * Use gamepad buttons as defaults for compatibility with
+                * existing applications.
+                */
+               panel->keycodes[0] = BTN_NORTH;
+               panel->keycodes[1] = BTN_SOUTH;
+               panel->keycodes[2] = BTN_SELECT;
+       }
+
+       for (i = 0; i < PANEL_KEYCODES_COUNT; ++i)
+               input_set_capability(panel->input, EV_KEY, panel->keycodes[i]);
+
+       error = input_register_device(panel->input);
+       if (error) {
+               dev_err(&client->dev,
+                       "Failed to register input device: %d\n", error);
+               return error;
+       }
+
+       i2c_set_clientdata(client, panel);
+       error = i2c_slave_register(client, ibm_panel_i2c_slave_cb);
+       if (error) {
+               dev_err(&client->dev,
+                       "Failed to register as i2c slave: %d\n", error);
+               return error;
+       }
+
+       return 0;
+}
+
+static void ibm_panel_remove(struct i2c_client *client)
+{
+       i2c_slave_unregister(client);
+}
+
+static const struct of_device_id ibm_panel_match[] = {
+       { .compatible = "ibm,op-panel" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ibm_panel_match);
+
+static struct i2c_driver ibm_panel_driver = {
+       .driver = {
+               .name = DEVICE_NAME,
+               .of_match_table = ibm_panel_match,
+       },
+       .probe = ibm_panel_probe,
+       .remove = ibm_panel_remove,
+};
+module_i2c_driver(ibm_panel_driver);
+
+MODULE_AUTHOR("Eddie James <eajames@linux.ibm.com>");
+MODULE_DESCRIPTION("IBM Operation Panel Driver");
+MODULE_LICENSE("GPL");
index 6f38aa2..b2f1292 100644 (file)
@@ -744,7 +744,7 @@ static int ims_pcu_switch_to_bootloader(struct ims_pcu *pcu)
        error = ims_pcu_execute_command(pcu, JUMP_TO_BTLDR, NULL, 0);
        if (error) {
                dev_err(pcu->dev,
-                       "Failure when sending JUMP TO BOOLTLOADER command, error: %d\n",
+                       "Failure when sending JUMP TO BOOTLOADER command, error: %d\n",
                        error);
                return error;
        }
index b2e8097..ddb863b 100644 (file)
@@ -1077,7 +1077,7 @@ static int iqs7222_hard_reset(struct iqs7222_private *iqs7222)
 
 static int iqs7222_force_comms(struct iqs7222_private *iqs7222)
 {
-       u8 msg_buf[] = { 0xFF, 0x00, };
+       u8 msg_buf[] = { 0xFF, };
        int ret;
 
        /*
@@ -1771,11 +1771,9 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
        if (!chan_node)
                return 0;
 
-       if (dev_desc->allow_offset) {
-               sys_setup[dev_desc->allow_offset] |= BIT(chan_index);
-               if (fwnode_property_present(chan_node, "azoteq,ulp-allow"))
-                       sys_setup[dev_desc->allow_offset] &= ~BIT(chan_index);
-       }
+       if (dev_desc->allow_offset &&
+           fwnode_property_present(chan_node, "azoteq,ulp-allow"))
+               sys_setup[dev_desc->allow_offset] &= ~BIT(chan_index);
 
        chan_setup[0] |= IQS7222_CHAN_SETUP_0_CHAN_EN;
 
@@ -2206,6 +2204,9 @@ static int iqs7222_parse_all(struct iqs7222_private *iqs7222)
        u16 *sys_setup = iqs7222->sys_setup;
        int error, i;
 
+       if (dev_desc->allow_offset)
+               sys_setup[dev_desc->allow_offset] = U16_MAX;
+
        if (dev_desc->event_offset)
                sys_setup[dev_desc->event_offset] = IQS7222_EVENT_MASK_ATI;
 
@@ -2326,6 +2327,9 @@ static int iqs7222_report(struct iqs7222_private *iqs7222)
                        int k = 2 + j * (num_chan > 16 ? 2 : 1);
                        u16 state = le16_to_cpu(status[k + i / 16]);
 
+                       if (!iqs7222->kp_type[i][j])
+                               continue;
+
                        input_event(iqs7222->keypad,
                                    iqs7222->kp_type[i][j],
                                    iqs7222->kp_code[i][j],
index 4650f4a..bee4b13 100644 (file)
@@ -485,7 +485,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
        }
 
        if (udev->manufacturer)
-               strlcpy(remote->name, udev->manufacturer, sizeof(remote->name));
+               strscpy(remote->name, udev->manufacturer, sizeof(remote->name));
 
        if (udev->product) {
                if (udev->manufacturer)
diff --git a/drivers/input/misc/rt5120-pwrkey.c b/drivers/input/misc/rt5120-pwrkey.c
new file mode 100644 (file)
index 0000000..8a8c1ae
--- /dev/null
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2022 Richtek Technology Corp.
+ * Author: ChiYuan Huang <cy_huang@richtek.com>
+ */
+
+#include <linux/bits.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define RT5120_REG_INTSTAT     0x1E
+#define RT5120_PWRKEYSTAT_MASK BIT(7)
+
+struct rt5120_priv {
+       struct regmap *regmap;
+       struct input_dev *input;
+};
+
+static irqreturn_t rt5120_pwrkey_handler(int irq, void *devid)
+{
+       struct rt5120_priv *priv = devid;
+       unsigned int stat;
+       int error;
+
+       error = regmap_read(priv->regmap, RT5120_REG_INTSTAT, &stat);
+       if (error)
+               return IRQ_NONE;
+
+       input_report_key(priv->input, KEY_POWER,
+                        !(stat & RT5120_PWRKEYSTAT_MASK));
+       input_sync(priv->input);
+
+       return IRQ_HANDLED;
+}
+
+static int rt5120_pwrkey_probe(struct platform_device *pdev)
+{
+       struct rt5120_priv *priv;
+       struct device *dev = &pdev->dev;
+       int press_irq, release_irq;
+       int error;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->regmap = dev_get_regmap(dev->parent, NULL);
+       if (!priv->regmap) {
+               dev_err(dev, "Failed to init regmap\n");
+               return -ENODEV;
+       }
+
+       press_irq = platform_get_irq_byname(pdev, "pwrkey-press");
+       if (press_irq < 0)
+               return press_irq;
+
+       release_irq = platform_get_irq_byname(pdev, "pwrkey-release");
+       if (release_irq < 0)
+               return release_irq;
+
+       /* Make input device be device resource managed */
+       priv->input = devm_input_allocate_device(dev);
+       if (!priv->input)
+               return -ENOMEM;
+
+       priv->input->name = "rt5120_pwrkey";
+       priv->input->phys = "rt5120_pwrkey/input0";
+       priv->input->id.bustype = BUS_I2C;
+       input_set_capability(priv->input, EV_KEY, KEY_POWER);
+
+       error = input_register_device(priv->input);
+       if (error) {
+               dev_err(dev, "Failed to register input device: %d\n", error);
+               return error;
+       }
+
+       error = devm_request_threaded_irq(dev, press_irq,
+                                         NULL, rt5120_pwrkey_handler,
+                                         0, "pwrkey-press", priv);
+       if (error) {
+               dev_err(dev,
+                       "Failed to register pwrkey press irq: %d\n", error);
+               return error;
+       }
+
+       error = devm_request_threaded_irq(dev, release_irq,
+                                         NULL, rt5120_pwrkey_handler,
+                                         0, "pwrkey-release", priv);
+       if (error) {
+               dev_err(dev,
+                       "Failed to register pwrkey release irq: %d\n", error);
+               return error;
+       }
+
+       return 0;
+}
+
+static const struct of_device_id r5120_pwrkey_match_table[] = {
+       { .compatible = "richtek,rt5120-pwrkey" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, r5120_pwrkey_match_table);
+
+static struct platform_driver rt5120_pwrkey_driver = {
+       .driver = {
+               .name = "rt5120-pwrkey",
+               .of_match_table = r5120_pwrkey_match_table,
+       },
+       .probe = rt5120_pwrkey_probe,
+};
+module_platform_driver(rt5120_pwrkey_driver);
+
+MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
+MODULE_DESCRIPTION("Richtek RT5120 power key driver");
+MODULE_LICENSE("GPL");
index b307cca..e3ee063 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/errno.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/twl.h>
 
index e0ff616..5619996 100644 (file)
@@ -163,14 +163,10 @@ static int __maybe_unused twl4030_vibra_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,
                         twl4030_vibra_suspend, twl4030_vibra_resume);
 
-static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata,
-                             struct device_node *parent)
+static bool twl4030_vibra_check_coexist(struct device_node *parent)
 {
        struct device_node *node;
 
-       if (pdata && pdata->coexist)
-               return true;
-
        node = of_get_child_by_name(parent, "codec");
        if (node) {
                of_node_put(node);
@@ -182,13 +178,12 @@ static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata,
 
 static int twl4030_vibra_probe(struct platform_device *pdev)
 {
-       struct twl4030_vibra_data *pdata = dev_get_platdata(&pdev->dev);
        struct device_node *twl4030_core_node = pdev->dev.parent->of_node;
        struct vibra_info *info;
        int ret;
 
-       if (!pdata && !twl4030_core_node) {
-               dev_dbg(&pdev->dev, "platform_data not available\n");
+       if (!twl4030_core_node) {
+               dev_dbg(&pdev->dev, "twl4030 OF node is missing\n");
                return -EINVAL;
        }
 
@@ -197,7 +192,7 @@ static int twl4030_vibra_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        info->dev = &pdev->dev;
-       info->coexist = twl4030_vibra_check_coexist(pdata, twl4030_core_node);
+       info->coexist = twl4030_vibra_check_coexist(twl4030_core_node);
        INIT_WORK(&info->play_work, vibra_play_work);
 
        info->input_dev = devm_input_allocate_device(&pdev->dev);
index e1758d5..d4eb59b 100644 (file)
@@ -1311,12 +1311,6 @@ static int elan_probe(struct i2c_client *client,
                return error;
        }
 
-       error = devm_device_add_groups(dev, elan_sysfs_groups);
-       if (error) {
-               dev_err(dev, "failed to create sysfs attributes: %d\n", error);
-               return error;
-       }
-
        error = input_register_device(data->input);
        if (error) {
                dev_err(dev, "failed to register input device: %d\n", error);
@@ -1442,6 +1436,7 @@ static struct i2c_driver elan_driver = {
                .acpi_match_table = ACPI_PTR(elan_acpi_id),
                .of_match_table = of_match_ptr(elan_of_match),
                .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+               .dev_groups = elan_sysfs_groups,
        },
        .probe          = elan_probe,
        .id_table       = elan_id,
index 4dc4413..3c8310d 100644 (file)
@@ -884,7 +884,7 @@ static ssize_t hgpk_trigger_recal(struct psmouse *psmouse, void *data,
 
        /*
         * We queue work instead of doing recalibration right here
-        * to avoid adding locking to to hgpk_force_recalibrate()
+        * to avoid adding locking to hgpk_force_recalibrate()
         * since workqueue provides serialization.
         */
        psmouse_queue_work(psmouse, &priv->recalib_wq, 0);
@@ -1057,7 +1057,7 @@ void hgpk_module_init(void)
                                                strlen(hgpk_mode_name));
        if (hgpk_default_mode == HGPK_MODE_INVALID) {
                hgpk_default_mode = HGPK_MODE_MOUSE;
-               strlcpy(hgpk_mode_name, hgpk_mode_names[HGPK_MODE_MOUSE],
+               strscpy(hgpk_mode_name, hgpk_mode_names[HGPK_MODE_MOUSE],
                        sizeof(hgpk_mode_name));
        }
 }
index df5d116..401d8bf 100644 (file)
@@ -13,9 +13,6 @@
  * Inport (ATI XL and Microsoft) busmouse driver for Linux
  */
 
-/*
- */
-
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
index bd647f9..0aab63d 100644 (file)
@@ -14,9 +14,6 @@
  * Logitech Bus Mouse Driver for Linux
  */
 
-/*
- */
-
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
index f755747..efa5804 100644 (file)
@@ -10,9 +10,6 @@
  * IBM PC110 touchpad driver for Linux
  */
 
-/*
- */
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
index 0b4a303..c9a7e87 100644 (file)
@@ -94,7 +94,7 @@ PSMOUSE_DEFINE_ATTR(resync_time, S_IWUSR | S_IRUGO,
                        (void *) offsetof(struct psmouse, resync_time),
                        psmouse_show_int_attr, psmouse_set_int_attr);
 
-static struct attribute *psmouse_attributes[] = {
+static struct attribute *psmouse_dev_attrs[] = {
        &psmouse_attr_protocol.dattr.attr,
        &psmouse_attr_rate.dattr.attr,
        &psmouse_attr_resolution.dattr.attr,
@@ -103,9 +103,7 @@ static struct attribute *psmouse_attributes[] = {
        NULL
 };
 
-static const struct attribute_group psmouse_attribute_group = {
-       .attrs  = psmouse_attributes,
-};
+ATTRIBUTE_GROUPS(psmouse_dev);
 
 /*
  * psmouse_mutex protects all operations changing state of mouse
@@ -1481,8 +1479,6 @@ static void psmouse_disconnect(struct serio *serio)
        struct psmouse *psmouse = serio_get_drvdata(serio);
        struct psmouse *parent = NULL;
 
-       sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group);
-
        mutex_lock(&psmouse_mutex);
 
        psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
@@ -1647,10 +1643,6 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
        if (parent && parent->pt_activate)
                parent->pt_activate(parent);
 
-       error = sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group);
-       if (error)
-               goto err_pt_deactivate;
-
        /*
         * PS/2 devices having SMBus companions should stay disabled
         * on PS/2 side, in order to have SMBus part operable.
@@ -1666,13 +1658,6 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
        mutex_unlock(&psmouse_mutex);
        return retval;
 
- err_pt_deactivate:
-       if (parent && parent->pt_deactivate)
-               parent->pt_deactivate(parent);
-       if (input_dev) {
-               input_unregister_device(input_dev);
-               input_dev = NULL; /* so we don't try to free it below */
-       }
  err_protocol_disconnect:
        if (psmouse->disconnect)
                psmouse->disconnect(psmouse);
@@ -1791,7 +1776,8 @@ MODULE_DEVICE_TABLE(serio, psmouse_serio_ids);
 
 static struct serio_driver psmouse_drv = {
        .driver         = {
-               .name   = "psmouse",
+               .name           = "psmouse",
+               .dev_groups     = psmouse_dev_groups,
        },
        .description    = DRIVER_DESC,
        .id_table       = psmouse_serio_ids,
index caa79c1..993f903 100644 (file)
@@ -7,9 +7,6 @@
  *  Serial mouse driver for Linux
  */
 
-/*
- */
-
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index ffad142..fa021af 100644 (file)
@@ -182,6 +182,7 @@ static const char * const smbus_pnp_ids[] = {
        "LEN0099", /* X1 Extreme Gen 1 / P1 Gen 1 */
        "LEN009b", /* T580 */
        "LEN0402", /* X1 Extreme Gen 2 / P1 Gen 2 */
+       "LEN040f", /* P1 Gen 3 */
        "LEN200f", /* T450s */
        "LEN2044", /* L470  */
        "LEN2054", /* E480 */
@@ -714,8 +715,8 @@ static void synaptics_pt_create(struct psmouse *psmouse)
        }
 
        serio->id.type = SERIO_PS_PSTHRU;
-       strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
-       strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->phys));
+       strscpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
+       strscpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->phys));
        serio->write = synaptics_pt_write;
        serio->start = synaptics_pt_start;
        serio->stop = synaptics_pt_stop;
index b5ff27e..75e45f3 100644 (file)
@@ -354,7 +354,7 @@ static int synusb_probe(struct usb_interface *intf,
        synusb->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
        if (udev->manufacturer)
-               strlcpy(synusb->name, udev->manufacturer,
+               strscpy(synusb->name, udev->manufacturer,
                        sizeof(synusb->name));
 
        if (udev->product) {
index bd415f4..8af8e4a 100644 (file)
@@ -13,9 +13,6 @@
  */
 
 /*
- */
-
-/*
  * Building an adaptor to DE9 / DB25 RS232
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
@@ -138,12 +135,12 @@ static void vsxxxaa_detection_done(struct vsxxxaa *mouse)
 {
        switch (mouse->type) {
        case 0x02:
-               strlcpy(mouse->name, "DEC VSXXX-AA/-GA mouse",
+               strscpy(mouse->name, "DEC VSXXX-AA/-GA mouse",
                        sizeof(mouse->name));
                break;
 
        case 0x04:
-               strlcpy(mouse->name, "DEC VSXXX-AB digitizer",
+               strscpy(mouse->name, "DEC VSXXX-AB digitizer",
                        sizeof(mouse->name));
                break;
 
index c194b16..1e11ea3 100644 (file)
@@ -181,7 +181,7 @@ static int rmi_f03_register_pt(struct f03_data *f03)
        serio->close = rmi_f03_pt_close;
        serio->port_data = f03;
 
-       strlcpy(serio->name, "RMI4 PS/2 pass-through", sizeof(serio->name));
+       strscpy(serio->name, "RMI4 PS/2 pass-through", sizeof(serio->name));
        snprintf(serio->phys, sizeof(serio->phys), "%s/serio0",
                 dev_name(&f03->fn->dev));
        serio->dev.parent = &f03->fn->dev;
index e5dca98..0d9a575 100644 (file)
@@ -114,13 +114,13 @@ static irqreturn_t rmi_f34_attention(int irq, void *ctx)
                        complete(&f34->v5.cmd_done);
        } else {
                ret = rmi_read_block(f34->fn->rmi_dev,
-                                    f34->fn->fd.data_base_addr +
-                                               f34->v7.off.flash_status,
-                                    &status, sizeof(status));
-               rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: status: %#02x, ret: %d\n",
+                                       f34->fn->fd.data_base_addr +
+                                               V7_COMMAND_OFFSET,
+                                       &status, sizeof(status));
+               rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, "%s: cmd: %#02x, ret: %d\n",
                        __func__, status, ret);
 
-               if (!ret && !(status & 0x1f))
+               if (!ret && status == CMD_V7_IDLE)
                        complete(&f34->v7.cmd_done);
        }
 
@@ -321,13 +321,13 @@ static ssize_t rmi_driver_bootloader_id_show(struct device *dev,
                f34 = dev_get_drvdata(&fn->dev);
 
                if (f34->bl_version == 5)
-                       return scnprintf(buf, PAGE_SIZE, "%c%c\n",
-                                        f34->bootloader_id[0],
-                                        f34->bootloader_id[1]);
+                       return sysfs_emit(buf, "%c%c\n",
+                                         f34->bootloader_id[0],
+                                         f34->bootloader_id[1]);
                else
-                       return scnprintf(buf, PAGE_SIZE, "V%d.%d\n",
-                                        f34->bootloader_id[1],
-                                        f34->bootloader_id[0]);
+                       return sysfs_emit(buf, "V%d.%d\n",
+                                         f34->bootloader_id[1],
+                                         f34->bootloader_id[0]);
        }
 
        return 0;
@@ -346,7 +346,7 @@ static ssize_t rmi_driver_configuration_id_show(struct device *dev,
        if (fn) {
                f34 = dev_get_drvdata(&fn->dev);
 
-               return scnprintf(buf, PAGE_SIZE, "%s\n", f34->configuration_id);
+               return sysfs_emit(buf, "%s\n", f34->configuration_id);
        }
 
        return 0;
@@ -370,7 +370,7 @@ static int rmi_firmware_update(struct rmi_driver_data *data,
 
        f34 = dev_get_drvdata(&data->f34_container->dev);
 
-       if (f34->bl_version == 7) {
+       if (f34->bl_version >= 7) {
                if (data->pdt_props & HAS_BSR) {
                        dev_err(dev, "%s: LTS not supported\n", __func__);
                        return -ENODEV;
@@ -382,7 +382,7 @@ static int rmi_firmware_update(struct rmi_driver_data *data,
        }
 
        /* Enter flash mode */
-       if (f34->bl_version == 7)
+       if (f34->bl_version >= 7)
                ret = rmi_f34v7_start_reflash(f34, fw);
        else
                ret = rmi_f34_enable_flash(f34);
@@ -413,7 +413,7 @@ static int rmi_firmware_update(struct rmi_driver_data *data,
        f34 = dev_get_drvdata(&data->f34_container->dev);
 
        /* Perform firmware update */
-       if (f34->bl_version == 7)
+       if (f34->bl_version >= 7)
                ret = rmi_f34v7_do_reflash(f34, fw);
        else
                ret = rmi_f34_update_firmware(f34, fw);
@@ -499,7 +499,7 @@ static ssize_t rmi_driver_update_fw_status_show(struct device *dev,
        if (data->f34_container)
                update_status = rmi_f34_status(data->f34_container);
 
-       return scnprintf(buf, PAGE_SIZE, "%d\n", update_status);
+       return sysfs_emit(buf, "%d\n", update_status);
 }
 
 static DEVICE_ATTR(update_fw_status, 0444,
index 99faa8c..cfa3039 100644 (file)
@@ -222,20 +222,6 @@ struct image_metadata {
        struct physical_address phyaddr;
 };
 
-struct register_offset {
-       u8 properties;
-       u8 properties_2;
-       u8 block_size;
-       u8 block_count;
-       u8 gc_block_count;
-       u8 flash_status;
-       u8 partition_id;
-       u8 block_number;
-       u8 transfer_length;
-       u8 flash_cmd;
-       u8 payload;
-};
-
 struct rmi_f34_firmware {
        __le32 checksum;
        u8 pad1[3];
@@ -262,7 +248,6 @@ struct f34v5_data {
 struct f34v7_data {
        bool has_display_cfg;
        bool has_guest_code;
-       bool force_update;
        bool in_bl_mode;
        u8 *read_config_buf;
        size_t read_config_buf_size;
@@ -276,9 +261,7 @@ struct f34v7_data {
        u16 payload_length;
        u8 partitions;
        u16 partition_table_bytes;
-       bool new_partition_table;
 
-       struct register_offset off;
        struct block_count blkcount;
        struct physical_address phyaddr;
        struct image_metadata img;
index 8d7ec9d..886557b 100644 (file)
@@ -25,7 +25,7 @@ static int rmi_f34v7_read_flash_status(struct f34_data *f34)
        int ret;
 
        ret = rmi_read_block(f34->fn->rmi_dev,
-                       f34->fn->fd.data_base_addr + f34->v7.off.flash_status,
+                       f34->fn->fd.data_base_addr + V7_FLASH_STATUS_OFFSET,
                        &status,
                        sizeof(status));
        if (ret < 0) {
@@ -43,7 +43,7 @@ static int rmi_f34v7_read_flash_status(struct f34_data *f34)
        }
 
        ret = rmi_read_block(f34->fn->rmi_dev,
-                       f34->fn->fd.data_base_addr + f34->v7.off.flash_cmd,
+                       f34->fn->fd.data_base_addr + V7_COMMAND_OFFSET,
                        &command,
                        sizeof(command));
        if (ret < 0) {
@@ -72,6 +72,24 @@ static int rmi_f34v7_wait_for_idle(struct f34_data *f34, int timeout_ms)
        return 0;
 }
 
+static int rmi_f34v7_check_command_status(struct f34_data *f34, int timeout_ms)
+{
+       int ret;
+
+       ret = rmi_f34v7_wait_for_idle(f34, timeout_ms);
+       if (ret < 0)
+               return ret;
+
+       ret = rmi_f34v7_read_flash_status(f34);
+       if (ret < 0)
+               return ret;
+
+       if (f34->v7.flash_status != 0x00)
+               return -EIO;
+
+       return 0;
+}
+
 static int rmi_f34v7_write_command_single_transaction(struct f34_data *f34,
                                                      u8 cmd)
 {
@@ -122,7 +140,7 @@ static int rmi_f34v7_write_command_single_transaction(struct f34_data *f34,
        data_1_5.payload[1] = f34->bootloader_id[1];
 
        ret = rmi_write_block(f34->fn->rmi_dev,
-                       base + f34->v7.off.partition_id,
+                       base + V7_PARTITION_ID_OFFSET,
                        &data_1_5, sizeof(data_1_5));
        if (ret < 0) {
                dev_err(&f34->fn->dev,
@@ -195,7 +213,7 @@ static int rmi_f34v7_write_command(struct f34_data *f34, u8 cmd)
                __func__, command);
 
        ret = rmi_write_block(f34->fn->rmi_dev,
-                       base + f34->v7.off.flash_cmd,
+                       base + V7_COMMAND_OFFSET,
                        &command, sizeof(command));
        if (ret < 0) {
                dev_err(&f34->fn->dev, "%s: Failed to write flash command\n",
@@ -262,7 +280,7 @@ static int rmi_f34v7_write_partition_id(struct f34_data *f34, u8 cmd)
        }
 
        ret = rmi_write_block(f34->fn->rmi_dev,
-                       base + f34->v7.off.partition_id,
+                       base + V7_PARTITION_ID_OFFSET,
                        &partition, sizeof(partition));
        if (ret < 0) {
                dev_err(&f34->fn->dev, "%s: Failed to write partition ID\n",
@@ -290,7 +308,7 @@ static int rmi_f34v7_read_partition_table(struct f34_data *f34)
                return ret;
 
        ret = rmi_write_block(f34->fn->rmi_dev,
-                       base + f34->v7.off.block_number,
+                       base + V7_BLOCK_NUMBER_OFFSET,
                        &block_number, sizeof(block_number));
        if (ret < 0) {
                dev_err(&f34->fn->dev, "%s: Failed to write block number\n",
@@ -301,7 +319,7 @@ static int rmi_f34v7_read_partition_table(struct f34_data *f34)
        put_unaligned_le16(f34->v7.flash_config_length, &length);
 
        ret = rmi_write_block(f34->fn->rmi_dev,
-                       base + f34->v7.off.transfer_length,
+                       base + V7_TRANSFER_LENGTH_OFFSET,
                        &length, sizeof(length));
        if (ret < 0) {
                dev_err(&f34->fn->dev, "%s: Failed to write transfer length\n",
@@ -318,6 +336,10 @@ static int rmi_f34v7_read_partition_table(struct f34_data *f34)
                return ret;
        }
 
+       /*
+        * rmi_f34v7_check_command_status() can't be used here, as this
+        * function is called before IRQs are available
+        */
        timeout = msecs_to_jiffies(F34_WRITE_WAIT_MS);
        while (time_before(jiffies, timeout)) {
                usleep_range(5000, 6000);
@@ -330,7 +352,7 @@ static int rmi_f34v7_read_partition_table(struct f34_data *f34)
        }
 
        ret = rmi_read_block(f34->fn->rmi_dev,
-                       base + f34->v7.off.payload,
+                       base + V7_PAYLOAD_OFFSET,
                        f34->v7.read_config_buf,
                        f34->v7.partition_table_bytes);
        if (ret < 0) {
@@ -504,13 +526,6 @@ static int rmi_f34v7_read_queries(struct f34_data *f34)
        rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, "%s: f34->v7.block_size = %d\n",
                 __func__, f34->v7.block_size);
 
-       f34->v7.off.flash_status = V7_FLASH_STATUS_OFFSET;
-       f34->v7.off.partition_id = V7_PARTITION_ID_OFFSET;
-       f34->v7.off.block_number = V7_BLOCK_NUMBER_OFFSET;
-       f34->v7.off.transfer_length = V7_TRANSFER_LENGTH_OFFSET;
-       f34->v7.off.flash_cmd = V7_COMMAND_OFFSET;
-       f34->v7.off.payload = V7_PAYLOAD_OFFSET;
-
        f34->v7.has_display_cfg = query_1_7.partition_support[1] & HAS_DISP_CFG;
        f34->v7.has_guest_code =
                        query_1_7.partition_support[1] & HAS_GUEST_CODE;
@@ -571,68 +586,6 @@ static int rmi_f34v7_read_queries(struct f34_data *f34)
        return 0;
 }
 
-static int rmi_f34v7_check_ui_firmware_size(struct f34_data *f34)
-{
-       u16 block_count;
-
-       block_count = f34->v7.img.ui_firmware.size / f34->v7.block_size;
-       f34->update_size += block_count;
-
-       if (block_count != f34->v7.blkcount.ui_firmware) {
-               dev_err(&f34->fn->dev,
-                       "UI firmware size mismatch: %d != %d\n",
-                       block_count, f34->v7.blkcount.ui_firmware);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int rmi_f34v7_check_ui_config_size(struct f34_data *f34)
-{
-       u16 block_count;
-
-       block_count = f34->v7.img.ui_config.size / f34->v7.block_size;
-       f34->update_size += block_count;
-
-       if (block_count != f34->v7.blkcount.ui_config) {
-               dev_err(&f34->fn->dev, "UI config size mismatch\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int rmi_f34v7_check_dp_config_size(struct f34_data *f34)
-{
-       u16 block_count;
-
-       block_count = f34->v7.img.dp_config.size / f34->v7.block_size;
-       f34->update_size += block_count;
-
-       if (block_count != f34->v7.blkcount.dp_config) {
-               dev_err(&f34->fn->dev, "Display config size mismatch\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int rmi_f34v7_check_guest_code_size(struct f34_data *f34)
-{
-       u16 block_count;
-
-       block_count = f34->v7.img.guest_code.size / f34->v7.block_size;
-       f34->update_size += block_count;
-
-       if (block_count != f34->v7.blkcount.guest_code) {
-               dev_err(&f34->fn->dev, "Guest code size mismatch\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
 static int rmi_f34v7_check_bl_config_size(struct f34_data *f34)
 {
        u16 block_count;
@@ -648,58 +601,6 @@ static int rmi_f34v7_check_bl_config_size(struct f34_data *f34)
        return 0;
 }
 
-static int rmi_f34v7_erase_config(struct f34_data *f34)
-{
-       int ret;
-
-       dev_info(&f34->fn->dev, "Erasing config...\n");
-
-       init_completion(&f34->v7.cmd_done);
-
-       switch (f34->v7.config_area) {
-       case v7_UI_CONFIG_AREA:
-               ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_UI_CONFIG);
-               if (ret < 0)
-                       return ret;
-               break;
-       case v7_DP_CONFIG_AREA:
-               ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_DISP_CONFIG);
-               if (ret < 0)
-                       return ret;
-               break;
-       case v7_BL_CONFIG_AREA:
-               ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_BL_CONFIG);
-               if (ret < 0)
-                       return ret;
-               break;
-       }
-
-       ret = rmi_f34v7_wait_for_idle(f34, F34_ERASE_WAIT_MS);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
-static int rmi_f34v7_erase_guest_code(struct f34_data *f34)
-{
-       int ret;
-
-       dev_info(&f34->fn->dev, "Erasing guest code...\n");
-
-       init_completion(&f34->v7.cmd_done);
-
-       ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_GUEST_CODE);
-       if (ret < 0)
-               return ret;
-
-       ret = rmi_f34v7_wait_for_idle(f34, F34_ERASE_WAIT_MS);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
 static int rmi_f34v7_erase_all(struct f34_data *f34)
 {
        int ret;
@@ -708,32 +609,14 @@ static int rmi_f34v7_erase_all(struct f34_data *f34)
 
        init_completion(&f34->v7.cmd_done);
 
-       ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_UI_FIRMWARE);
-       if (ret < 0)
-               return ret;
-
-       ret = rmi_f34v7_wait_for_idle(f34, F34_ERASE_WAIT_MS);
+       ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_ALL);
        if (ret < 0)
                return ret;
 
-       f34->v7.config_area = v7_UI_CONFIG_AREA;
-       ret = rmi_f34v7_erase_config(f34);
+       ret = rmi_f34v7_check_command_status(f34, F34_ERASE_WAIT_MS);
        if (ret < 0)
                return ret;
 
-       if (f34->v7.has_display_cfg) {
-               f34->v7.config_area = v7_DP_CONFIG_AREA;
-               ret = rmi_f34v7_erase_config(f34);
-               if (ret < 0)
-                       return ret;
-       }
-
-       if (f34->v7.new_partition_table && f34->v7.has_guest_code) {
-               ret = rmi_f34v7_erase_guest_code(f34);
-               if (ret < 0)
-                       return ret;
-       }
-
        return 0;
 }
 
@@ -756,7 +639,7 @@ static int rmi_f34v7_read_blocks(struct f34_data *f34,
                return ret;
 
        ret = rmi_write_block(f34->fn->rmi_dev,
-                       base + f34->v7.off.block_number,
+                       base + V7_BLOCK_NUMBER_OFFSET,
                        &block_number, sizeof(block_number));
        if (ret < 0) {
                dev_err(&f34->fn->dev, "%s: Failed to write block number\n",
@@ -772,7 +655,7 @@ static int rmi_f34v7_read_blocks(struct f34_data *f34,
                put_unaligned_le16(transfer, &length);
 
                ret = rmi_write_block(f34->fn->rmi_dev,
-                               base + f34->v7.off.transfer_length,
+                               base + V7_TRANSFER_LENGTH_OFFSET,
                                &length, sizeof(length));
                if (ret < 0) {
                        dev_err(&f34->fn->dev,
@@ -787,12 +670,12 @@ static int rmi_f34v7_read_blocks(struct f34_data *f34,
                if (ret < 0)
                        return ret;
 
-               ret = rmi_f34v7_wait_for_idle(f34, F34_ENABLE_WAIT_MS);
+               ret = rmi_f34v7_check_command_status(f34, F34_ENABLE_WAIT_MS);
                if (ret < 0)
                        return ret;
 
                ret = rmi_read_block(f34->fn->rmi_dev,
-                               base + f34->v7.off.payload,
+                               base + V7_PAYLOAD_OFFSET,
                                &f34->v7.read_config_buf[index],
                                transfer * f34->v7.block_size);
                if (ret < 0) {
@@ -828,7 +711,7 @@ static int rmi_f34v7_write_f34v7_blocks(struct f34_data *f34,
                return ret;
 
        ret = rmi_write_block(f34->fn->rmi_dev,
-                       base + f34->v7.off.block_number,
+                       base + V7_BLOCK_NUMBER_OFFSET,
                        &block_number, sizeof(block_number));
        if (ret < 0) {
                dev_err(&f34->fn->dev, "%s: Failed to write block number\n",
@@ -848,7 +731,7 @@ static int rmi_f34v7_write_f34v7_blocks(struct f34_data *f34,
                init_completion(&f34->v7.cmd_done);
 
                ret = rmi_write_block(f34->fn->rmi_dev,
-                               base + f34->v7.off.transfer_length,
+                               base + V7_TRANSFER_LENGTH_OFFSET,
                                &length, sizeof(length));
                if (ret < 0) {
                        dev_err(&f34->fn->dev,
@@ -862,7 +745,7 @@ static int rmi_f34v7_write_f34v7_blocks(struct f34_data *f34,
                        return ret;
 
                ret = rmi_write_block(f34->fn->rmi_dev,
-                               base + f34->v7.off.payload,
+                               base + V7_PAYLOAD_OFFSET,
                                block_ptr, transfer * f34->v7.block_size);
                if (ret < 0) {
                        dev_err(&f34->fn->dev,
@@ -871,7 +754,7 @@ static int rmi_f34v7_write_f34v7_blocks(struct f34_data *f34,
                        return ret;
                }
 
-               ret = rmi_f34v7_wait_for_idle(f34, F34_ENABLE_WAIT_MS);
+               ret = rmi_f34v7_check_command_status(f34, F34_ENABLE_WAIT_MS);
                if (ret < 0)
                        return ret;
 
@@ -937,17 +820,6 @@ static int rmi_f34v7_write_flash_config(struct f34_data *f34)
 
        init_completion(&f34->v7.cmd_done);
 
-       ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_FLASH_CONFIG);
-       if (ret < 0)
-               return ret;
-
-       rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
-               "%s: Erase flash config command written\n", __func__);
-
-       ret = rmi_f34v7_wait_for_idle(f34, F34_WRITE_WAIT_MS);
-       if (ret < 0)
-               return ret;
-
        ret = rmi_f34v7_write_config(f34);
        if (ret < 0)
                return ret;
@@ -977,10 +849,6 @@ static int rmi_f34v7_write_partition_table(struct f34_data *f34)
        if (ret < 0)
                return ret;
 
-       ret = rmi_f34v7_erase_config(f34);
-       if (ret < 0)
-               return ret;
-
        ret = rmi_f34v7_write_flash_config(f34);
        if (ret < 0)
                return ret;
@@ -1007,33 +875,6 @@ static int rmi_f34v7_write_firmware(struct f34_data *f34)
                                            blk_count, v7_CMD_WRITE_FW);
 }
 
-static void rmi_f34v7_compare_partition_tables(struct f34_data *f34)
-{
-       if (f34->v7.phyaddr.ui_firmware != f34->v7.img.phyaddr.ui_firmware) {
-               f34->v7.new_partition_table = true;
-               return;
-       }
-
-       if (f34->v7.phyaddr.ui_config != f34->v7.img.phyaddr.ui_config) {
-               f34->v7.new_partition_table = true;
-               return;
-       }
-
-       if (f34->v7.has_display_cfg &&
-           f34->v7.phyaddr.dp_config != f34->v7.img.phyaddr.dp_config) {
-               f34->v7.new_partition_table = true;
-               return;
-       }
-
-       if (f34->v7.has_guest_code &&
-           f34->v7.phyaddr.guest_code != f34->v7.img.phyaddr.guest_code) {
-               f34->v7.new_partition_table = true;
-               return;
-       }
-
-       f34->v7.new_partition_table = false;
-}
-
 static void rmi_f34v7_parse_img_header_10_bl_container(struct f34_data *f34,
                                                       const void *image)
 {
@@ -1180,8 +1021,6 @@ static int rmi_f34v7_parse_image_info(struct f34_data *f34)
        rmi_f34v7_parse_partition_table(f34, f34->v7.img.fl_config.data,
                        &f34->v7.img.blkcount, &f34->v7.img.phyaddr);
 
-       rmi_f34v7_compare_partition_tables(f34);
-
        return 0;
 }
 
@@ -1200,53 +1039,35 @@ int rmi_f34v7_do_reflash(struct f34_data *f34, const struct firmware *fw)
 
        ret = rmi_f34v7_parse_image_info(f34);
        if (ret < 0)
-               goto fail;
-
-       if (!f34->v7.new_partition_table) {
-               ret = rmi_f34v7_check_ui_firmware_size(f34);
-               if (ret < 0)
-                       goto fail;
-
-               ret = rmi_f34v7_check_ui_config_size(f34);
-               if (ret < 0)
-                       goto fail;
-
-               if (f34->v7.has_display_cfg &&
-                   f34->v7.img.contains_display_cfg) {
-                       ret = rmi_f34v7_check_dp_config_size(f34);
-                       if (ret < 0)
-                               goto fail;
-               }
+               return ret;
 
-               if (f34->v7.has_guest_code && f34->v7.img.contains_guest_code) {
-                       ret = rmi_f34v7_check_guest_code_size(f34);
-                       if (ret < 0)
-                               goto fail;
-               }
-       } else {
-               ret = rmi_f34v7_check_bl_config_size(f34);
-               if (ret < 0)
-                       goto fail;
-       }
+       ret = rmi_f34v7_check_bl_config_size(f34);
+       if (ret < 0)
+               return ret;
 
        ret = rmi_f34v7_erase_all(f34);
        if (ret < 0)
-               goto fail;
+               return ret;
 
-       if (f34->v7.new_partition_table) {
-               ret = rmi_f34v7_write_partition_table(f34);
-               if (ret < 0)
-                       goto fail;
-               dev_info(&f34->fn->dev, "%s: Partition table programmed\n",
-                        __func__);
-       }
+       ret = rmi_f34v7_write_partition_table(f34);
+       if (ret < 0)
+               return ret;
+       dev_info(&f34->fn->dev, "%s: Partition table programmed\n", __func__);
+
+       /*
+        * Reset to reload partition table - as the previous firmware has been
+        * erased, we remain in bootloader mode.
+        */
+       ret = rmi_scan_pdt(f34->fn->rmi_dev, NULL, rmi_initial_reset);
+       if (ret < 0)
+               dev_warn(&f34->fn->dev, "RMI reset failed!\n");
 
        dev_info(&f34->fn->dev, "Writing firmware (%d bytes)...\n",
                 f34->v7.img.ui_firmware.size);
 
        ret = rmi_f34v7_write_firmware(f34);
        if (ret < 0)
-               goto fail;
+               return ret;
 
        dev_info(&f34->fn->dev, "Writing config (%d bytes)...\n",
                 f34->v7.img.ui_config.size);
@@ -1254,28 +1075,25 @@ int rmi_f34v7_do_reflash(struct f34_data *f34, const struct firmware *fw)
        f34->v7.config_area = v7_UI_CONFIG_AREA;
        ret = rmi_f34v7_write_ui_config(f34);
        if (ret < 0)
-               goto fail;
+               return ret;
 
        if (f34->v7.has_display_cfg && f34->v7.img.contains_display_cfg) {
                dev_info(&f34->fn->dev, "Writing display config...\n");
 
                ret = rmi_f34v7_write_dp_config(f34);
                if (ret < 0)
-                       goto fail;
+                       return ret;
        }
 
-       if (f34->v7.new_partition_table) {
-               if (f34->v7.has_guest_code && f34->v7.img.contains_guest_code) {
-                       dev_info(&f34->fn->dev, "Writing guest code...\n");
+       if (f34->v7.has_guest_code && f34->v7.img.contains_guest_code) {
+               dev_info(&f34->fn->dev, "Writing guest code...\n");
 
-                       ret = rmi_f34v7_write_guest_code(f34);
-                       if (ret < 0)
-                               goto fail;
-               }
+               ret = rmi_f34v7_write_guest_code(f34);
+               if (ret < 0)
+                       return ret;
        }
 
-fail:
-       return ret;
+       return 0;
 }
 
 static int rmi_f34v7_enter_flash_prog(struct f34_data *f34)
@@ -1288,8 +1106,11 @@ static int rmi_f34v7_enter_flash_prog(struct f34_data *f34)
        if (ret < 0)
                return ret;
 
-       if (f34->v7.in_bl_mode)
+       if (f34->v7.in_bl_mode) {
+               dev_info(&f34->fn->dev, "%s: Device in bootloader mode\n",
+                        __func__);
                return 0;
+       }
 
        init_completion(&f34->v7.cmd_done);
 
@@ -1297,7 +1118,7 @@ static int rmi_f34v7_enter_flash_prog(struct f34_data *f34)
        if (ret < 0)
                return ret;
 
-       ret = rmi_f34v7_wait_for_idle(f34, F34_ENABLE_WAIT_MS);
+       ret = rmi_f34v7_check_command_status(f34, F34_ENABLE_WAIT_MS);
        if (ret < 0)
                return ret;
 
@@ -1308,39 +1129,16 @@ int rmi_f34v7_start_reflash(struct f34_data *f34, const struct firmware *fw)
 {
        int ret = 0;
 
-       f34->fn->rmi_dev->driver->set_irq_bits(f34->fn->rmi_dev, f34->fn->irq_mask);
-
        f34->v7.config_area = v7_UI_CONFIG_AREA;
        f34->v7.image = fw->data;
 
        ret = rmi_f34v7_parse_image_info(f34);
        if (ret < 0)
-               goto exit;
-
-       if (!f34->v7.force_update && f34->v7.new_partition_table) {
-               dev_err(&f34->fn->dev, "%s: Partition table mismatch\n",
-                               __func__);
-               ret = -EINVAL;
-               goto exit;
-       }
+               return ret;
 
        dev_info(&f34->fn->dev, "Firmware image OK\n");
 
-       ret = rmi_f34v7_read_flash_status(f34);
-       if (ret < 0)
-               goto exit;
-
-       if (f34->v7.in_bl_mode) {
-               dev_info(&f34->fn->dev, "%s: Device in bootloader mode\n",
-                               __func__);
-       }
-
-       rmi_f34v7_enter_flash_prog(f34);
-
-       return 0;
-
-exit:
-       return ret;
+       return rmi_f34v7_enter_flash_prog(f34);
 }
 
 int rmi_f34v7_probe(struct f34_data *f34)
@@ -1384,6 +1182,5 @@ int rmi_f34v7_probe(struct f34_data *f34)
        if (ret < 0)
                return ret;
 
-       f34->v7.force_update = true;
        return 0;
 }
index c5ce907..5c3da91 100644 (file)
@@ -390,8 +390,8 @@ static int rmi_f54_vidioc_querycap(struct file *file, void *priv,
 {
        struct f54_data *f54 = video_drvdata(file);
 
-       strlcpy(cap->driver, F54_NAME, sizeof(cap->driver));
-       strlcpy(cap->card, SYNAPTICS_INPUT_DEVICE_NAME, sizeof(cap->card));
+       strscpy(cap->driver, F54_NAME, sizeof(cap->driver));
+       strscpy(cap->card, SYNAPTICS_INPUT_DEVICE_NAME, sizeof(cap->card));
        snprintf(cap->bus_info, sizeof(cap->bus_info),
                "rmi4:%s", dev_name(&f54->fn->dev));
 
@@ -410,7 +410,7 @@ static int rmi_f54_vidioc_enum_input(struct file *file, void *priv,
 
        i->type = V4L2_INPUT_TYPE_TOUCH;
 
-       strlcpy(i->name, rmi_f54_report_type_names[reptype], sizeof(i->name));
+       strscpy(i->name, rmi_f54_report_type_names[reptype], sizeof(i->name));
        return 0;
 }
 
@@ -696,7 +696,7 @@ static int rmi_f54_probe(struct rmi_function *fn)
        rmi_f54_set_input(f54, 0);
 
        /* register video device */
-       strlcpy(f54->v4l2.name, F54_NAME, sizeof(f54->v4l2.name));
+       strscpy(f54->v4l2.name, F54_NAME, sizeof(f54->v4l2.name));
        ret = v4l2_device_register(&fn->dev, &f54->v4l2);
        if (ret) {
                dev_err(&fn->dev, "Unable to register video dev.\n");
index 379e924..3a92304 100644 (file)
@@ -110,8 +110,8 @@ static int altera_ps2_probe(struct platform_device *pdev)
        serio->write            = altera_ps2_write;
        serio->open             = altera_ps2_open;
        serio->close            = altera_ps2_close;
-       strlcpy(serio->name, dev_name(&pdev->dev), sizeof(serio->name));
-       strlcpy(serio->phys, dev_name(&pdev->dev), sizeof(serio->phys));
+       strscpy(serio->name, dev_name(&pdev->dev), sizeof(serio->name));
+       strscpy(serio->phys, dev_name(&pdev->dev), sizeof(serio->phys));
        serio->port_data        = ps2if;
        serio->dev.parent       = &pdev->dev;
        ps2if->io               = serio;
index 4408245..c391700 100644 (file)
@@ -126,8 +126,8 @@ static int amba_kmi_probe(struct amba_device *dev,
        io->write       = amba_kmi_write;
        io->open        = amba_kmi_open;
        io->close       = amba_kmi_close;
-       strlcpy(io->name, dev_name(&dev->dev), sizeof(io->name));
-       strlcpy(io->phys, dev_name(&dev->dev), sizeof(io->phys));
+       strscpy(io->name, dev_name(&dev->dev), sizeof(io->name));
+       strscpy(io->phys, dev_name(&dev->dev), sizeof(io->phys));
        io->port_data   = kmi;
        io->dev.parent  = &dev->dev;
 
index 1c0be29..ec93cb4 100644 (file)
@@ -159,8 +159,8 @@ static int ams_delta_serio_init(struct platform_device *pdev)
        serio->id.type = SERIO_8042;
        serio->open = ams_delta_serio_open;
        serio->close = ams_delta_serio_close;
-       strlcpy(serio->name, "AMS DELTA keyboard adapter", sizeof(serio->name));
-       strlcpy(serio->phys, dev_name(&pdev->dev), sizeof(serio->phys));
+       strscpy(serio->name, "AMS DELTA keyboard adapter", sizeof(serio->name));
+       strscpy(serio->phys, dev_name(&pdev->dev), sizeof(serio->phys));
        serio->dev.parent = &pdev->dev;
        serio->port_data = priv;
 
index 974d7bf..9c9ce09 100644 (file)
@@ -176,7 +176,7 @@ static int apbps2_of_probe(struct platform_device *ofdev)
        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));
+       strscpy(priv->io->name, "APBPS2 PS/2", sizeof(priv->io->name));
        snprintf(priv->io->phys, sizeof(priv->io->phys),
                 "apbps2_%d", apbps2_idx++);
 
index d45009d..3da751f 100644 (file)
@@ -7,9 +7,6 @@
  *  82C710 C&T mouse port chip driver for Linux
  */
 
-/*
- */
-
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
@@ -170,7 +167,7 @@ static int ct82c710_probe(struct platform_device *dev)
        ct82c710_port->open = ct82c710_open;
        ct82c710_port->close = ct82c710_close;
        ct82c710_port->write = ct82c710_write;
-       strlcpy(ct82c710_port->name, "C&T 82c710 mouse port",
+       strscpy(ct82c710_port->name, "C&T 82c710 mouse port",
                sizeof(ct82c710_port->name));
        snprintf(ct82c710_port->phys, sizeof(ct82c710_port->phys),
                 "isa%16llx/serio0", (unsigned long long)CT82C710_DATA);
index da2c67c..633c7de 100644 (file)
@@ -361,7 +361,7 @@ static int __init gscps2_probe(struct parisc_device *dev)
 
        snprintf(serio->name, sizeof(serio->name), "gsc-ps2-%s",
                 (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse");
-       strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys));
+       strscpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys));
        serio->id.type          = SERIO_8042;
        serio->write            = gscps2_write;
        serio->open             = gscps2_open;
index 1a7b72a..d62aefb 100644 (file)
@@ -334,9 +334,9 @@ static int hv_kbd_probe(struct hv_device *hv_dev,
        hv_serio->dev.parent  = &hv_dev->device;
        hv_serio->id.type = SERIO_8042_XL;
        hv_serio->port_data = kbd_dev;
-       strlcpy(hv_serio->name, dev_name(&hv_dev->device),
+       strscpy(hv_serio->name, dev_name(&hv_dev->device),
                sizeof(hv_serio->name));
-       strlcpy(hv_serio->phys, dev_name(&hv_dev->device),
+       strscpy(hv_serio->phys, dev_name(&hv_dev->device),
                sizeof(hv_serio->phys));
 
        hv_serio->start = hv_kbd_start;
similarity index 99%
rename from drivers/input/serio/i8042-x86ia64io.h
rename to drivers/input/serio/i8042-acpipnpio.h
index 4fbec7b..0778dc0 100644 (file)
@@ -1,7 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
-#ifndef _I8042_X86IA64IO_H
-#define _I8042_X86IA64IO_H
+#ifndef _I8042_ACPIPNPIO_H
+#define _I8042_ACPIPNPIO_H
 
+#include <linux/acpi.h>
 
 #ifdef CONFIG_X86
 #include <asm/x86_init.h>
@@ -1300,7 +1301,7 @@ static char i8042_pnp_aux_name[32];
 
 static void i8042_pnp_id_to_string(struct pnp_id *id, char *dst, int dst_size)
 {
-       strlcpy(dst, "PNP:", dst_size);
+       strscpy(dst, "PNP:", dst_size);
 
        while (id) {
                strlcat(dst, " ", dst_size);
@@ -1320,7 +1321,7 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *
        if (pnp_irq_valid(dev,0))
                i8042_pnp_kbd_irq = pnp_irq(dev, 0);
 
-       strlcpy(i8042_pnp_kbd_name, did->id, sizeof(i8042_pnp_kbd_name));
+       strscpy(i8042_pnp_kbd_name, did->id, sizeof(i8042_pnp_kbd_name));
        if (strlen(pnp_dev_name(dev))) {
                strlcat(i8042_pnp_kbd_name, ":", sizeof(i8042_pnp_kbd_name));
                strlcat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
@@ -1347,7 +1348,7 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *
        if (pnp_irq_valid(dev, 0))
                i8042_pnp_aux_irq = pnp_irq(dev, 0);
 
-       strlcpy(i8042_pnp_aux_name, did->id, sizeof(i8042_pnp_aux_name));
+       strscpy(i8042_pnp_aux_name, did->id, sizeof(i8042_pnp_aux_name));
        if (strlen(pnp_dev_name(dev))) {
                strlcat(i8042_pnp_aux_name, ":", sizeof(i8042_pnp_aux_name));
                strlcat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name));
@@ -1453,9 +1454,14 @@ static int __init i8042_pnp_init(void)
                return -ENODEV;
 #else
                pr_info("PNP: No PS/2 controller found.\n");
+#if defined(__loongarch__)
+               if (acpi_disabled == 0)
+                       return -ENODEV;
+#else
                if (x86_platform.legacy.i8042 !=
                                X86_LEGACY_I8042_EXPECTED_PRESENT)
                        return -ENODEV;
+#endif
                pr_info("Probing ports directly.\n");
                return 0;
 #endif
@@ -1665,4 +1671,4 @@ static inline void i8042_platform_exit(void)
        i8042_pnp_exit();
 }
 
-#endif /* _I8042_X86IA64IO_H */
+#endif /* _I8042_ACPIPNPIO_H */
index fce7681..c712c1f 100644 (file)
@@ -3,6 +3,7 @@
 #define _I8042_SPARCIO_H
 
 #include <linux/of_device.h>
+#include <linux/types.h>
 
 #include <asm/io.h>
 #include <asm/oplib.h>
@@ -103,12 +104,25 @@ static struct platform_driver sparc_i8042_driver = {
        .remove         = sparc_i8042_remove,
 };
 
-static int __init i8042_platform_init(void)
+static bool i8042_is_mr_coffee(void)
 {
-       struct device_node *root = of_find_node_by_path("/");
-       const char *name = of_get_property(root, "name", NULL);
+       struct device_node *root;
+       const char *name;
+       bool is_mr_coffee;
+
+       root = of_find_node_by_path("/");
+
+       name = of_get_property(root, "name", NULL);
+       is_mr_coffee = name && !strcmp(name, "SUNW,JavaStation-1");
 
-       if (name && !strcmp(name, "SUNW,JavaStation-1")) {
+       of_node_put(root);
+
+       return is_mr_coffee;
+}
+
+static int __init i8042_platform_init(void)
+{
+       if (i8042_is_mr_coffee()) {
                /* Hardcoded values for MrCoffee.  */
                i8042_kbd_irq = i8042_aux_irq = 13 | 0x20;
                kbd_iobase = ioremap(0x71300060, 8);
@@ -136,10 +150,7 @@ static int __init i8042_platform_init(void)
 
 static inline void i8042_platform_exit(void)
 {
-       struct device_node *root = of_find_node_by_path("/");
-       const char *name = of_get_property(root, "name", NULL);
-
-       if (!name || strcmp(name, "SUNW,JavaStation-1"))
+       if (!i8042_is_mr_coffee())
                platform_driver_unregister(&sparc_i8042_driver);
 }
 
index 3fc0a89..f948649 100644 (file)
@@ -1341,9 +1341,9 @@ static int i8042_create_kbd_port(void)
        serio->ps2_cmd_mutex    = &i8042_mutex;
        serio->port_data        = port;
        serio->dev.parent       = &i8042_platform_device->dev;
-       strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name));
-       strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
-       strlcpy(serio->firmware_id, i8042_kbd_firmware_id,
+       strscpy(serio->name, "i8042 KBD port", sizeof(serio->name));
+       strscpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
+       strscpy(serio->firmware_id, i8042_kbd_firmware_id,
                sizeof(serio->firmware_id));
        set_primary_fwnode(&serio->dev, i8042_kbd_fwnode);
 
@@ -1371,15 +1371,15 @@ static int i8042_create_aux_port(int idx)
        serio->port_data        = port;
        serio->dev.parent       = &i8042_platform_device->dev;
        if (idx < 0) {
-               strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name));
-               strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
-               strlcpy(serio->firmware_id, i8042_aux_firmware_id,
+               strscpy(serio->name, "i8042 AUX port", sizeof(serio->name));
+               strscpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
+               strscpy(serio->firmware_id, i8042_aux_firmware_id,
                        sizeof(serio->firmware_id));
                serio->close = i8042_port_close;
        } else {
                snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx);
                snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, idx + 1);
-               strlcpy(serio->firmware_id, i8042_aux_firmware_id,
+               strscpy(serio->firmware_id, i8042_aux_firmware_id,
                        sizeof(serio->firmware_id));
        }
 
index 5538178..adb5173 100644 (file)
@@ -19,8 +19,8 @@
 #include "i8042-snirm.h"
 #elif defined(CONFIG_SPARC)
 #include "i8042-sparcio.h"
-#elif defined(CONFIG_X86) || defined(CONFIG_IA64)
-#include "i8042-x86ia64io.h"
+#elif defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_LOONGARCH)
+#include "i8042-acpipnpio.h"
 #else
 #include "i8042-io.h"
 #endif
index 59de8d9..04d2db9 100644 (file)
@@ -199,8 +199,8 @@ static int olpc_apsp_probe(struct platform_device *pdev)
        kb_serio->close         = olpc_apsp_close;
        kb_serio->port_data     = priv;
        kb_serio->dev.parent    = &pdev->dev;
-       strlcpy(kb_serio->name, "sp keyboard", sizeof(kb_serio->name));
-       strlcpy(kb_serio->phys, "sp/serio0", sizeof(kb_serio->phys));
+       strscpy(kb_serio->name, "sp keyboard", sizeof(kb_serio->name));
+       strscpy(kb_serio->phys, "sp/serio0", sizeof(kb_serio->phys));
        priv->kbio              = kb_serio;
        serio_register_port(kb_serio);
 
@@ -216,8 +216,8 @@ static int olpc_apsp_probe(struct platform_device *pdev)
        pad_serio->close        = olpc_apsp_close;
        pad_serio->port_data    = priv;
        pad_serio->dev.parent   = &pdev->dev;
-       strlcpy(pad_serio->name, "sp touchpad", sizeof(pad_serio->name));
-       strlcpy(pad_serio->phys, "sp/serio1", sizeof(pad_serio->phys));
+       strscpy(pad_serio->name, "sp touchpad", sizeof(pad_serio->name));
+       strscpy(pad_serio->phys, "sp/serio1", sizeof(pad_serio->phys));
        priv->padio             = pad_serio;
        serio_register_port(pad_serio);
 
index 51b6850..0d54895 100644 (file)
@@ -169,7 +169,7 @@ static struct serio *parkbd_allocate_serio(void)
        if (serio) {
                serio->id.type = parkbd_mode;
                serio->write = parkbd_write;
-               strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name));
+               strscpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name));
                snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", parkbd_dev->port->name);
        }
 
index bedf75d..0587875 100644 (file)
@@ -149,8 +149,8 @@ static int pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id)
        serio->write            = pcips2_write;
        serio->open             = pcips2_open;
        serio->close            = pcips2_close;
-       strlcpy(serio->name, pci_name(dev), sizeof(serio->name));
-       strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys));
+       strscpy(serio->name, pci_name(dev), sizeof(serio->name));
+       strscpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys));
        serio->port_data        = ps2if;
        serio->dev.parent       = &dev->dev;
        ps2if->io               = serio;
index 9b02dd5..bc1dc48 100644 (file)
@@ -449,8 +449,8 @@ static int ps2_gpio_probe(struct platform_device *pdev)
        serio->write = drvdata->write_enable ? ps2_gpio_write : NULL;
        serio->port_data = drvdata;
        serio->dev.parent = dev;
-       strlcpy(serio->name, dev_name(dev), sizeof(serio->name));
-       strlcpy(serio->phys, dev_name(dev), sizeof(serio->phys));
+       strscpy(serio->name, dev_name(dev), sizeof(serio->name));
+       strscpy(serio->phys, dev_name(dev), sizeof(serio->phys));
 
        drvdata->serio = serio;
        drvdata->dev = dev;
index 0071dd5..902e818 100644 (file)
@@ -131,7 +131,7 @@ static int ps2mult_create_port(struct ps2mult *psm, int i)
        if (!serio)
                return -ENOMEM;
 
-       strlcpy(serio->name, "TQC PS/2 Multiplexer", sizeof(serio->name));
+       strscpy(serio->name, "TQC PS/2 Multiplexer", sizeof(serio->name));
        snprintf(serio->phys, sizeof(serio->phys),
                 "%s/port%d", mx_serio->phys, i);
        serio->id.type = SERIO_8042;
index bd24839..ba04058 100644 (file)
@@ -10,9 +10,6 @@
  * Q40 PS/2 keyboard controller driver for Linux/m68k
  */
 
-/*
- */
-
 #include <linux/module.h>
 #include <linux/serio.h>
 #include <linux/interrupt.h>
@@ -126,8 +123,8 @@ static int q40kbd_probe(struct platform_device *pdev)
        port->close = q40kbd_close;
        port->port_data = q40kbd;
        port->dev.parent = &pdev->dev;
-       strlcpy(port->name, "Q40 Kbd Port", sizeof(port->name));
-       strlcpy(port->phys, "Q40", sizeof(port->phys));
+       strscpy(port->name, "Q40 Kbd Port", sizeof(port->name));
+       strscpy(port->phys, "Q40", sizeof(port->phys));
 
        q40kbd_stop();
 
index 37fe6a5..ce420eb 100644 (file)
@@ -8,9 +8,6 @@
  * Acorn RiscPC PS/2 keyboard controller driver for Linux/ARM
  */
 
-/*
- */
-
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/serio.h>
@@ -128,8 +125,8 @@ static int rpckbd_probe(struct platform_device *dev)
        serio->close            = rpckbd_close;
        serio->dev.parent       = &dev->dev;
        serio->port_data        = rpckbd;
-       strlcpy(serio->name, "RiscPC PS/2 kbd port", sizeof(serio->name));
-       strlcpy(serio->phys, "rpckbd/serio0", sizeof(serio->phys));
+       strscpy(serio->name, "RiscPC PS/2 kbd port", sizeof(serio->name));
+       strscpy(serio->phys, "rpckbd/serio0", sizeof(serio->phys));
 
        platform_set_drvdata(dev, serio);
        serio_register_port(serio);
index 68fac48..2724c3a 100644 (file)
@@ -267,8 +267,8 @@ static int ps2_probe(struct sa1111_dev *dev)
        serio->write            = ps2_write;
        serio->open             = ps2_open;
        serio->close            = ps2_close;
-       strlcpy(serio->name, dev_name(&dev->dev), sizeof(serio->name));
-       strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys));
+       strscpy(serio->name, dev_name(&dev->dev), sizeof(serio->name));
+       strscpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys));
        serio->port_data        = ps2if;
        serio->dev.parent       = &dev->dev;
        ps2if->io               = serio;
index ec117be..15ce320 100644 (file)
@@ -7,9 +7,6 @@
  *  Copyright (c) 2003 Daniele Bellucci
  */
 
-/*
- */
-
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/stddef.h>
index 669a728..7f7ef0e 100644 (file)
@@ -171,7 +171,7 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file,
        if (!serio)
                return -ENOMEM;
 
-       strlcpy(serio->name, "Serial port", sizeof(serio->name));
+       strscpy(serio->name, "Serial port", sizeof(serio->name));
        snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty));
        serio->id = serport->id;
        serio->id.type = SERIO_RS232;
index f15ed3d..eb26264 100644 (file)
@@ -256,8 +256,8 @@ static int sun4i_ps2_probe(struct platform_device *pdev)
        serio->close = sun4i_ps2_close;
        serio->port_data = drvdata;
        serio->dev.parent = dev;
-       strlcpy(serio->name, dev_name(dev), sizeof(serio->name));
-       strlcpy(serio->phys, dev_name(dev), sizeof(serio->phys));
+       strscpy(serio->name, dev_name(dev), sizeof(serio->name));
+       strscpy(serio->phys, dev_name(dev), sizeof(serio->phys));
 
        /* shutoff interrupt */
        writel(0, drvdata->reg_base + PS2_REG_GCTL);
index 56c7e47..b20e5a1 100644 (file)
@@ -9,9 +9,6 @@
  *      v3.2 - Added sysfs support
  */
 
-/*
- */
-
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -155,7 +152,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
        acecad->input = input_dev;
 
        if (dev->manufacturer)
-               strlcpy(acecad->name, dev->manufacturer, sizeof(acecad->name));
+               strscpy(acecad->name, dev->manufacturer, sizeof(acecad->name));
 
        if (dev->product) {
                if (dev->manufacturer)
index 24ec484..baabc51 100644 (file)
@@ -1617,7 +1617,7 @@ static ssize_t show_firmwareCode(struct device *dev, struct device_attribute *at
 
 static DEVICE_ATTR(firmware_code, S_IRUGO, show_firmwareCode, NULL);
 
-static struct attribute *aiptek_attributes[] = {
+static struct attribute *aiptek_dev_attrs[] = {
        &dev_attr_size.attr,
        &dev_attr_pointer_mode.attr,
        &dev_attr_coordinate_mode.attr,
@@ -1641,9 +1641,7 @@ static struct attribute *aiptek_attributes[] = {
        NULL
 };
 
-static const struct attribute_group aiptek_attribute_group = {
-       .attrs  = aiptek_attributes,
-};
+ATTRIBUTE_GROUPS(aiptek_dev);
 
 /***********************************************************************
  * This routine is called when a tablet has been identified. It basically
@@ -1842,26 +1840,16 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
         */
        usb_set_intfdata(intf, aiptek);
 
-       /* Set up the sysfs files
-        */
-       err = sysfs_create_group(&intf->dev.kobj, &aiptek_attribute_group);
-       if (err) {
-               dev_warn(&intf->dev, "cannot create sysfs group err: %d\n",
-                        err);
-               goto fail3;
-        }
-
        /* Register the tablet as an Input Device
         */
        err = input_register_device(aiptek->inputdev);
        if (err) {
                dev_warn(&intf->dev,
                         "input_register_device returned err: %d\n", err);
-               goto fail4;
+               goto fail3;
         }
        return 0;
 
- fail4:        sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group);
  fail3: usb_free_urb(aiptek->urb);
  fail2:        usb_free_coherent(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
                          aiptek->data_dma);
@@ -1886,7 +1874,6 @@ static void aiptek_disconnect(struct usb_interface *intf)
                 */
                usb_kill_urb(aiptek->urb);
                input_unregister_device(aiptek->inputdev);
-               sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group);
                usb_free_urb(aiptek->urb);
                usb_free_coherent(interface_to_usbdev(intf),
                                  AIPTEK_PACKET_LENGTH,
@@ -1900,6 +1887,7 @@ static struct usb_driver aiptek_driver = {
        .probe = aiptek_probe,
        .disconnect = aiptek_disconnect,
        .id_table = aiptek_ids,
+       .dev_groups = aiptek_dev_groups,
 };
 
 module_usb_driver(aiptek_driver);
index 6d58443..9bc6315 100644 (file)
@@ -5,9 +5,6 @@
  *  Copyright (c) 2010 Xing Wei <weixing@hanwang.com.cn>
  */
 
-/*
- */
-
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -356,7 +353,7 @@ static int hanwang_probe(struct usb_interface *intf, const struct usb_device_id
        usb_make_path(dev, hanwang->phys, sizeof(hanwang->phys));
        strlcat(hanwang->phys, "/input0", sizeof(hanwang->phys));
 
-       strlcpy(hanwang->name, hanwang->features->name, sizeof(hanwang->name));
+       strscpy(hanwang->name, hanwang->features->name, sizeof(hanwang->name));
        input_dev->name = hanwang->name;
        input_dev->phys = hanwang->phys;
        usb_to_input_id(dev, &input_dev->id);
index c608ac5..d836d3d 100644 (file)
@@ -319,7 +319,7 @@ static int pegasus_probe(struct usb_interface *intf,
        pegasus->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
        if (dev->manufacturer)
-               strlcpy(pegasus->name, dev->manufacturer,
+               strscpy(pegasus->name, dev->manufacturer,
                        sizeof(pegasus->name));
 
        if (dev->product) {
index 2d70c94..dc90a3e 100644 (file)
@@ -1335,7 +1335,7 @@ config TOUCHSCREEN_ZFORCE
 
 config TOUCHSCREEN_COLIBRI_VF50
        tristate "Toradex Colibri on board touchscreen driver"
-       depends on IIO && VF610_ADC
+       depends on IIO
        depends on GPIOLIB || COMPILE_TEST
        help
          Say Y here if you have a Colibri VF50 and plan to use
index 4eedea0..ccecd14 100644 (file)
@@ -2497,8 +2497,8 @@ static int mxt_vidioc_querycap(struct file *file, void *priv,
 {
        struct mxt_data *data = video_drvdata(file);
 
-       strlcpy(cap->driver, "atmel_mxt_ts", sizeof(cap->driver));
-       strlcpy(cap->card, "atmel_mxt_ts touch", sizeof(cap->card));
+       strscpy(cap->driver, "atmel_mxt_ts", sizeof(cap->driver));
+       strscpy(cap->card, "atmel_mxt_ts touch", sizeof(cap->card));
        snprintf(cap->bus_info, sizeof(cap->bus_info),
                 "I2C:%s", dev_name(&data->client->dev));
        return 0;
@@ -2514,11 +2514,11 @@ static int mxt_vidioc_enum_input(struct file *file, void *priv,
 
        switch (i->index) {
        case MXT_V4L_INPUT_REFS:
-               strlcpy(i->name, "Mutual Capacitance References",
+               strscpy(i->name, "Mutual Capacitance References",
                        sizeof(i->name));
                break;
        case MXT_V4L_INPUT_DELTAS:
-               strlcpy(i->name, "Mutual Capacitance Deltas", sizeof(i->name));
+               strscpy(i->name, "Mutual Capacitance Deltas", sizeof(i->name));
                break;
        }
 
index c33e63c..2deae5a 100644 (file)
@@ -10,6 +10,7 @@
  * Copyright (c) 2008 QUALCOMM USA, INC.
  */
 
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
 #include <linux/mutex.h>
 #include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/input/auo-pixcir-ts.h>
+#include <linux/gpio/consumer.h>
 #include <linux/of.h>
-#include <linux/of_gpio.h>
+#include <linux/property.h>
 
 /*
  * Coordinate calculation:
 #define AUO_PIXCIR_INT_RELEASE         (1 << 4)
 #define AUO_PIXCIR_INT_ENABLE          (1 << 3)
 #define AUO_PIXCIR_INT_POL_HIGH                (1 << 2)
+
+/*
+ * Interrupt modes:
+ * periodical:         interrupt is asserted periodicaly
+ * compare coordinates:        interrupt is asserted when coordinates change
+ * indicate touch:     interrupt is asserted during touch
+ */
+#define AUO_PIXCIR_INT_PERIODICAL      0x00
+#define AUO_PIXCIR_INT_COMP_COORD      0x01
+#define AUO_PIXCIR_INT_TOUCH_IND       0x02
 #define AUO_PIXCIR_INT_MODE_MASK       0x03
 
 /*
 struct auo_pixcir_ts {
        struct i2c_client       *client;
        struct input_dev        *input;
-       const struct auo_pixcir_ts_platdata *pdata;
+       struct gpio_desc        *gpio_int;
+       struct gpio_desc        *gpio_rst;
        char                    phys[32];
 
-       /* special handling for touch_indicate interupt mode */
+       unsigned int            x_max;
+       unsigned int            y_max;
+
+       /* special handling for touch_indicate interrupt mode */
        bool                    touch_ind_mode;
 
        wait_queue_head_t       wait;
@@ -125,7 +139,6 @@ static int auo_pixcir_collect_data(struct auo_pixcir_ts *ts,
                                   struct auo_point_t *point)
 {
        struct i2c_client *client = ts->client;
-       const struct auo_pixcir_ts_platdata *pdata = ts->pdata;
        uint8_t raw_coord[8];
        uint8_t raw_area[4];
        int i, ret;
@@ -152,8 +165,8 @@ static int auo_pixcir_collect_data(struct auo_pixcir_ts *ts,
                point[i].coord_y =
                        raw_coord[4 * i + 3] << 8 | raw_coord[4 * i + 2];
 
-               if (point[i].coord_x > pdata->x_max ||
-                   point[i].coord_y > pdata->y_max) {
+               if (point[i].coord_x > ts->x_max ||
+                   point[i].coord_y > ts->y_max) {
                        dev_warn(&client->dev, "coordinates (%d,%d) invalid\n",
                                point[i].coord_x, point[i].coord_y);
                        point[i].coord_x = point[i].coord_y = 0;
@@ -171,7 +184,6 @@ static int auo_pixcir_collect_data(struct auo_pixcir_ts *ts,
 static irqreturn_t auo_pixcir_interrupt(int irq, void *dev_id)
 {
        struct auo_pixcir_ts *ts = dev_id;
-       const struct auo_pixcir_ts_platdata *pdata = ts->pdata;
        struct auo_point_t point[AUO_PIXCIR_REPORT_POINTS];
        int i;
        int ret;
@@ -182,7 +194,7 @@ static irqreturn_t auo_pixcir_interrupt(int irq, void *dev_id)
 
                /* check for up event in touch touch_ind_mode */
                if (ts->touch_ind_mode) {
-                       if (gpio_get_value(pdata->gpio_int) == 0) {
+                       if (gpiod_get_value_cansleep(ts->gpio_int) == 0) {
                                input_mt_sync(ts->input);
                                input_report_key(ts->input, BTN_TOUCH, 0);
                                input_sync(ts->input);
@@ -278,11 +290,9 @@ static int auo_pixcir_power_mode(struct auo_pixcir_ts *ts, int mode)
        return 0;
 }
 
-static int auo_pixcir_int_config(struct auo_pixcir_ts *ts,
-                                          int int_setting)
+static int auo_pixcir_int_config(struct auo_pixcir_ts *ts, int int_setting)
 {
        struct i2c_client *client = ts->client;
-       const struct auo_pixcir_ts_platdata *pdata = ts->pdata;
        int ret;
 
        ret = i2c_smbus_read_byte_data(client, AUO_PIXCIR_REG_INT_SETTING);
@@ -304,7 +314,7 @@ static int auo_pixcir_int_config(struct auo_pixcir_ts *ts,
                return ret;
        }
 
-       ts->touch_ind_mode = pdata->int_setting == AUO_PIXCIR_INT_TOUCH_IND;
+       ts->touch_ind_mode = int_setting == AUO_PIXCIR_INT_TOUCH_IND;
 
        return 0;
 }
@@ -465,78 +475,22 @@ unlock:
 static SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops,
                         auo_pixcir_suspend, auo_pixcir_resume);
 
-#ifdef CONFIG_OF
-static struct auo_pixcir_ts_platdata *auo_pixcir_parse_dt(struct device *dev)
-{
-       struct auo_pixcir_ts_platdata *pdata;
-       struct device_node *np = dev->of_node;
-
-       if (!np)
-               return ERR_PTR(-ENOENT);
-
-       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
-       if (!pdata)
-               return ERR_PTR(-ENOMEM);
-
-       pdata->gpio_int = of_get_gpio(np, 0);
-       if (!gpio_is_valid(pdata->gpio_int)) {
-               dev_err(dev, "failed to get interrupt gpio\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       pdata->gpio_rst = of_get_gpio(np, 1);
-       if (!gpio_is_valid(pdata->gpio_rst)) {
-               dev_err(dev, "failed to get reset gpio\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       if (of_property_read_u32(np, "x-size", &pdata->x_max)) {
-               dev_err(dev, "failed to get x-size property\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       if (of_property_read_u32(np, "y-size", &pdata->y_max)) {
-               dev_err(dev, "failed to get y-size property\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       /* default to asserting the interrupt when the screen is touched */
-       pdata->int_setting = AUO_PIXCIR_INT_TOUCH_IND;
-
-       return pdata;
-}
-#else
-static struct auo_pixcir_ts_platdata *auo_pixcir_parse_dt(struct device *dev)
-{
-       return ERR_PTR(-EINVAL);
-}
-#endif
-
 static void auo_pixcir_reset(void *data)
 {
        struct auo_pixcir_ts *ts = data;
 
-       gpio_set_value(ts->pdata->gpio_rst, 0);
+       gpiod_set_value_cansleep(ts->gpio_rst, 1);
 }
 
 static int auo_pixcir_probe(struct i2c_client *client,
                            const struct i2c_device_id *id)
 {
-       const struct auo_pixcir_ts_platdata *pdata;
        struct auo_pixcir_ts *ts;
        struct input_dev *input_dev;
        int version;
        int error;
 
-       pdata = dev_get_platdata(&client->dev);
-       if (!pdata) {
-               pdata = auo_pixcir_parse_dt(&client->dev);
-               if (IS_ERR(pdata))
-                       return PTR_ERR(pdata);
-       }
-
-       ts = devm_kzalloc(&client->dev,
-                         sizeof(struct auo_pixcir_ts), GFP_KERNEL);
+       ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
        if (!ts)
                return -ENOMEM;
 
@@ -546,7 +500,6 @@ static int auo_pixcir_probe(struct i2c_client *client,
                return -ENOMEM;
        }
 
-       ts->pdata = pdata;
        ts->client = client;
        ts->input = input_dev;
        ts->touch_ind_mode = 0;
@@ -556,6 +509,16 @@ static int auo_pixcir_probe(struct i2c_client *client,
        snprintf(ts->phys, sizeof(ts->phys),
                 "%s/input0", dev_name(&client->dev));
 
+       if (device_property_read_u32(&client->dev, "x-size", &ts->x_max)) {
+               dev_err(&client->dev, "failed to get x-size property\n");
+               return -EINVAL;
+       }
+
+       if (device_property_read_u32(&client->dev, "y-size", &ts->y_max)) {
+               dev_err(&client->dev, "failed to get y-size property\n");
+               return -EINVAL;
+       }
+
        input_dev->name = "AUO-Pixcir touchscreen";
        input_dev->phys = ts->phys;
        input_dev->id.bustype = BUS_I2C;
@@ -569,39 +532,42 @@ static int auo_pixcir_probe(struct i2c_client *client,
        __set_bit(BTN_TOUCH, input_dev->keybit);
 
        /* For single touch */
-       input_set_abs_params(input_dev, ABS_X, 0, pdata->x_max, 0, 0);
-       input_set_abs_params(input_dev, ABS_Y, 0, pdata->y_max, 0, 0);
+       input_set_abs_params(input_dev, ABS_X, 0, ts->x_max, 0, 0);
+       input_set_abs_params(input_dev, ABS_Y, 0, ts->y_max, 0, 0);
 
        /* For multi touch */
-       input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
-                            pdata->x_max, 0, 0);
-       input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
-                            pdata->y_max, 0, 0);
-       input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0,
-                            AUO_PIXCIR_MAX_AREA, 0, 0);
-       input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0,
-                            AUO_PIXCIR_MAX_AREA, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, ts->x_max, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, ts->y_max, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+                            0, AUO_PIXCIR_MAX_AREA, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR,
+                            0, AUO_PIXCIR_MAX_AREA, 0, 0);
        input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
 
        input_set_drvdata(ts->input, ts);
 
-       error = devm_gpio_request_one(&client->dev, pdata->gpio_int,
-                                     GPIOF_DIR_IN, "auo_pixcir_ts_int");
+       ts->gpio_int = devm_gpiod_get_index(&client->dev, NULL, 0, GPIOD_IN);
+       error = PTR_ERR_OR_ZERO(ts->gpio_int);
        if (error) {
-               dev_err(&client->dev, "request of gpio %d failed, %d\n",
-                       pdata->gpio_int, error);
+               dev_err(&client->dev,
+                       "request of int gpio failed: %d\n", error);
                return error;
        }
 
-       error = devm_gpio_request_one(&client->dev, pdata->gpio_rst,
-                                     GPIOF_DIR_OUT | GPIOF_INIT_HIGH,
-                                     "auo_pixcir_ts_rst");
+       gpiod_set_consumer_name(ts->gpio_int, "auo_pixcir_ts_int");
+
+       /* Take the chip out of reset */
+       ts->gpio_rst = devm_gpiod_get_index(&client->dev, NULL, 1,
+                                           GPIOD_OUT_LOW);
+       error = PTR_ERR_OR_ZERO(ts->gpio_rst);
        if (error) {
-               dev_err(&client->dev, "request of gpio %d failed, %d\n",
-                       pdata->gpio_rst, error);
+               dev_err(&client->dev,
+                       "request of reset gpio failed: %d\n", error);
                return error;
        }
 
+       gpiod_set_consumer_name(ts->gpio_rst, "auo_pixcir_ts_rst");
+
        error = devm_add_action_or_reset(&client->dev, auo_pixcir_reset, ts);
        if (error) {
                dev_err(&client->dev, "failed to register reset action, %d\n",
@@ -619,13 +585,14 @@ static int auo_pixcir_probe(struct i2c_client *client,
 
        dev_info(&client->dev, "firmware version 0x%X\n", version);
 
-       error = auo_pixcir_int_config(ts, pdata->int_setting);
+       /* default to asserting the interrupt when the screen is touched */
+       error = auo_pixcir_int_config(ts, AUO_PIXCIR_INT_TOUCH_IND);
        if (error)
                return error;
 
        error = devm_request_threaded_irq(&client->dev, client->irq,
                                          NULL, auo_pixcir_interrupt,
-                                         IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+                                         IRQF_ONESHOT,
                                          input_dev->name, ts);
        if (error) {
                dev_err(&client->dev, "irq %d requested failed, %d\n",
index f9ca550..c421f4b 100644 (file)
@@ -364,32 +364,20 @@ static irqreturn_t icn8505_irq(int irq, void *dev_id)
 
 static int icn8505_probe_acpi(struct icn8505_data *icn8505, struct device *dev)
 {
-       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-       const char *subsys = "unknown";
-       struct acpi_device *adev;
-       union acpi_object *obj;
-       acpi_status status;
-
-       adev = ACPI_COMPANION(dev);
-       if (!adev)
-               return -ENODEV;
+       const char *subsys;
+       int error;
 
-       status = acpi_evaluate_object(adev->handle, "_SUB", NULL, &buffer);
-       if (ACPI_SUCCESS(status)) {
-               obj = buffer.pointer;
-               if (obj->type == ACPI_TYPE_STRING)
-                       subsys = obj->string.pointer;
-               else
-                       dev_warn(dev, "Warning ACPI _SUB did not return a string\n");
-       } else {
-               dev_warn(dev, "Warning ACPI _SUB failed: %#x\n", status);
-               buffer.pointer = NULL;
-       }
+       subsys = acpi_get_subsystem_id(ACPI_HANDLE(dev));
+       error = PTR_ERR_OR_ZERO(subsys);
+       if (error == -ENODATA)
+               subsys = "unknown";
+       else if (error)
+               return error;
 
        snprintf(icn8505->firmware_name, sizeof(icn8505->firmware_name),
                 "chipone/icn8505-%s.fw", subsys);
 
-       kfree(buffer.pointer);
+       kfree_const(subsys);
        return 0;
 }
 
index 5fb4413..9ac1378 100644 (file)
@@ -912,8 +912,8 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
                p = strchr(rdbuf, '*');
                if (p)
                        *p++ = '\0';
-               strlcpy(model_name, rdbuf + 1, EDT_NAME_LEN);
-               strlcpy(fw_version, p ? p : "", EDT_NAME_LEN);
+               strscpy(model_name, rdbuf + 1, EDT_NAME_LEN);
+               strscpy(fw_version, p ? p : "", EDT_NAME_LEN);
        } else if (!strncasecmp(rdbuf, "EP0", 3)) {
                tsdata->version = EDT_M12;
 
@@ -926,8 +926,8 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
                p = strchr(rdbuf, '*');
                if (p)
                        *p++ = '\0';
-               strlcpy(model_name, rdbuf, EDT_NAME_LEN);
-               strlcpy(fw_version, p ? p : "", EDT_NAME_LEN);
+               strscpy(model_name, rdbuf, EDT_NAME_LEN);
+               strscpy(fw_version, p ? p : "", EDT_NAME_LEN);
        } else {
                /* If it is not an EDT M06/M12 touchscreen, then the model
                 * detection is a bit hairy. The different ft5x06
@@ -945,7 +945,7 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
                if (error)
                        return error;
 
-               strlcpy(fw_version, rdbuf, 2);
+               strscpy(fw_version, rdbuf, 2);
 
                error = edt_ft5x06_ts_readwrite(client, 1, "\xA8",
                                                1, rdbuf);
@@ -981,7 +981,7 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
                                                        1, rdbuf);
                        if (error)
                                return error;
-                       strlcpy(fw_version, rdbuf, 1);
+                       strscpy(fw_version, rdbuf, 1);
                        snprintf(model_name, EDT_NAME_LEN,
                                 "EVERVISION-FT5726NEi");
                        break;
index e07e8e0..5a5f9da 100644 (file)
@@ -7,9 +7,6 @@
  * Gunze AHL-51S touchscreen driver for Linux
  */
 
-/*
- */
-
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
index 12f2562..8ddb3f7 100644 (file)
@@ -939,8 +939,8 @@ static int sur40_vidioc_querycap(struct file *file, void *priv,
 {
        struct sur40_state *sur40 = video_drvdata(file);
 
-       strlcpy(cap->driver, DRIVER_SHORT, sizeof(cap->driver));
-       strlcpy(cap->card, DRIVER_LONG, sizeof(cap->card));
+       strscpy(cap->driver, DRIVER_SHORT, sizeof(cap->driver));
+       strscpy(cap->card, DRIVER_LONG, sizeof(cap->card));
        usb_make_path(sur40->usbdev, cap->bus_info, sizeof(cap->bus_info));
        return 0;
 }
@@ -952,7 +952,7 @@ static int sur40_vidioc_enum_input(struct file *file, void *priv,
                return -EINVAL;
        i->type = V4L2_INPUT_TYPE_TOUCH;
        i->std = V4L2_STD_UNKNOWN;
-       strlcpy(i->name, "In-Cell Sensor", sizeof(i->name));
+       strscpy(i->name, "In-Cell Sensor", sizeof(i->name));
        i->capabilities = 0;
        return 0;
 }
index 3dda6ea..d6d04b9 100644 (file)
@@ -1708,7 +1708,7 @@ static int usbtouch_probe(struct usb_interface *intf,
        usbtouch->input = input_dev;
 
        if (udev->manufacturer)
-               strlcpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name));
+               strscpy(usbtouch->name, udev->manufacturer, sizeof(usbtouch->name));
 
        if (udev->product) {
                if (udev->manufacturer)
index 691285a..928c5ee 100644 (file)
@@ -625,7 +625,7 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
        /* For backwards-compatibility we compose the basename based on
         * capabilities and then just append the tool type
         */
-       strlcpy(basename, "Wacom Serial", sizeof(basename));
+       strscpy(basename, "Wacom Serial", sizeof(basename));
 
        err_pen = w8001_setup_pen(w8001, basename, sizeof(basename));
        err_touch = w8001_setup_touch(w8001, basename, sizeof(basename));
@@ -635,7 +635,7 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
        }
 
        if (!err_pen) {
-               strlcpy(w8001->pen_name, basename, sizeof(w8001->pen_name));
+               strscpy(w8001->pen_name, basename, sizeof(w8001->pen_name));
                strlcat(w8001->pen_name, " Pen", sizeof(w8001->pen_name));
                input_dev_pen->name = w8001->pen_name;
 
@@ -651,7 +651,7 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
        }
 
        if (!err_touch) {
-               strlcpy(w8001->touch_name, basename, sizeof(w8001->touch_name));
+               strscpy(w8001->touch_name, basename, sizeof(w8001->touch_name));
                strlcat(w8001->touch_name, " Finger",
                        sizeof(w8001->touch_name));
                input_dev_touch->name = w8001->touch_name;
index 31c9e32..4d4a62d 100644 (file)
@@ -33,8 +33,8 @@ struct bma150_cfg {
        unsigned char lg_hyst;          /* Low-G hysterisis */
        unsigned char lg_dur;           /* Low-G duration */
        unsigned char lg_thres;         /* Low-G threshold */
-       unsigned char range;            /* one of BMA0150_RANGE_xxx */
-       unsigned char bandwidth;        /* one of BMA0150_BW_xxx */
+       unsigned char range;            /* one of BMA150_RANGE_xxx */
+       unsigned char bandwidth;        /* one of BMA150_BW_xxx */
 };
 
 struct bma150_platform_data {
index 69081d8..8c2f000 100644 (file)
@@ -110,7 +110,7 @@ static inline void gameport_free_port(struct gameport *gameport)
 
 static inline void gameport_set_name(struct gameport *gameport, const char *name)
 {
-       strlcpy(gameport->name, name, sizeof(gameport->name));
+       strscpy(gameport->name, name, sizeof(gameport->name));
 }
 
 /*
diff --git a/include/linux/input/auo-pixcir-ts.h b/include/linux/input/auo-pixcir-ts.h
deleted file mode 100644 (file)
index ed07769..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Driver for AUO in-cell touchscreens
- *
- * Copyright (c) 2011 Heiko Stuebner <heiko@sntech.de>
- *
- * based on auo_touch.h from Dell Streak kernel
- *
- * Copyright (c) 2008 QUALCOMM Incorporated.
- * Copyright (c) 2008 QUALCOMM USA, INC.
- */
-
-#ifndef __AUO_PIXCIR_TS_H__
-#define __AUO_PIXCIR_TS_H__
-
-/*
- * Interrupt modes:
- * periodical:         interrupt is asserted periodicaly
- * compare coordinates:        interrupt is asserted when coordinates change
- * indicate touch:     interrupt is asserted during touch
- */
-#define AUO_PIXCIR_INT_PERIODICAL      0x00
-#define AUO_PIXCIR_INT_COMP_COORD      0x01
-#define AUO_PIXCIR_INT_TOUCH_IND       0x02
-
-/*
- * @gpio_int           interrupt gpio
- * @int_setting                one of AUO_PIXCIR_INT_*
- * @init_hw            hardwarespecific init
- * @exit_hw            hardwarespecific shutdown
- * @x_max              x-resolution
- * @y_max              y-resolution
- */
-struct auo_pixcir_ts_platdata {
-       int gpio_int;
-       int gpio_rst;
-
-       int int_setting;
-
-       unsigned int x_max;
-       unsigned int y_max;
-};
-
-#endif
diff --git a/include/linux/platform_data/adp5588.h b/include/linux/platform_data/adp5588.h
deleted file mode 100644 (file)
index 6d3f7d9..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Analog Devices ADP5588 I/O Expander and QWERTY Keypad Controller
- *
- * Copyright 2009-2010 Analog Devices Inc.
- */
-
-#ifndef _ADP5588_H
-#define _ADP5588_H
-
-#define DEV_ID 0x00            /* Device ID */
-#define CFG 0x01               /* Configuration Register1 */
-#define INT_STAT 0x02          /* Interrupt Status Register */
-#define KEY_LCK_EC_STAT 0x03   /* Key Lock and Event Counter Register */
-#define Key_EVENTA 0x04                /* Key Event Register A */
-#define Key_EVENTB 0x05                /* Key Event Register B */
-#define Key_EVENTC 0x06                /* Key Event Register C */
-#define Key_EVENTD 0x07                /* Key Event Register D */
-#define Key_EVENTE 0x08                /* Key Event Register E */
-#define Key_EVENTF 0x09                /* Key Event Register F */
-#define Key_EVENTG 0x0A                /* Key Event Register G */
-#define Key_EVENTH 0x0B                /* Key Event Register H */
-#define Key_EVENTI 0x0C                /* Key Event Register I */
-#define Key_EVENTJ 0x0D                /* Key Event Register J */
-#define KP_LCK_TMR 0x0E                /* Keypad Lock1 to Lock2 Timer */
-#define UNLOCK1 0x0F           /* Unlock Key1 */
-#define UNLOCK2 0x10           /* Unlock Key2 */
-#define GPIO_INT_STAT1 0x11    /* GPIO Interrupt Status */
-#define GPIO_INT_STAT2 0x12    /* GPIO Interrupt Status */
-#define GPIO_INT_STAT3 0x13    /* GPIO Interrupt Status */
-#define GPIO_DAT_STAT1 0x14    /* GPIO Data Status, Read twice to clear */
-#define GPIO_DAT_STAT2 0x15    /* GPIO Data Status, Read twice to clear */
-#define GPIO_DAT_STAT3 0x16    /* GPIO Data Status, Read twice to clear */
-#define GPIO_DAT_OUT1 0x17     /* GPIO DATA OUT */
-#define GPIO_DAT_OUT2 0x18     /* GPIO DATA OUT */
-#define GPIO_DAT_OUT3 0x19     /* GPIO DATA OUT */
-#define GPIO_INT_EN1 0x1A      /* GPIO Interrupt Enable */
-#define GPIO_INT_EN2 0x1B      /* GPIO Interrupt Enable */
-#define GPIO_INT_EN3 0x1C      /* GPIO Interrupt Enable */
-#define KP_GPIO1 0x1D          /* Keypad or GPIO Selection */
-#define KP_GPIO2 0x1E          /* Keypad or GPIO Selection */
-#define KP_GPIO3 0x1F          /* Keypad or GPIO Selection */
-#define GPI_EM1 0x20           /* GPI Event Mode 1 */
-#define GPI_EM2 0x21           /* GPI Event Mode 2 */
-#define GPI_EM3 0x22           /* GPI Event Mode 3 */
-#define GPIO_DIR1 0x23         /* GPIO Data Direction */
-#define GPIO_DIR2 0x24         /* GPIO Data Direction */
-#define GPIO_DIR3 0x25         /* GPIO Data Direction */
-#define GPIO_INT_LVL1 0x26     /* GPIO Edge/Level Detect */
-#define GPIO_INT_LVL2 0x27     /* GPIO Edge/Level Detect */
-#define GPIO_INT_LVL3 0x28     /* GPIO Edge/Level Detect */
-#define Debounce_DIS1 0x29     /* Debounce Disable */
-#define Debounce_DIS2 0x2A     /* Debounce Disable */
-#define Debounce_DIS3 0x2B     /* Debounce Disable */
-#define GPIO_PULL1 0x2C                /* GPIO Pull Disable */
-#define GPIO_PULL2 0x2D                /* GPIO Pull Disable */
-#define GPIO_PULL3 0x2E                /* GPIO Pull Disable */
-#define CMP_CFG_STAT 0x30      /* Comparator Configuration and Status Register */
-#define CMP_CONFG_SENS1 0x31   /* Sensor1 Comparator Configuration Register */
-#define CMP_CONFG_SENS2 0x32   /* L2 Light Sensor Reference Level, Output Falling for Sensor 1 */
-#define CMP1_LVL2_TRIP 0x33    /* L2 Light Sensor Hysteresis (Active when Output Rising) for Sensor 1 */
-#define CMP1_LVL2_HYS 0x34     /* L3 Light Sensor Reference Level, Output Falling For Sensor 1 */
-#define CMP1_LVL3_TRIP 0x35    /* L3 Light Sensor Hysteresis (Active when Output Rising) For Sensor 1 */
-#define CMP1_LVL3_HYS 0x36     /* Sensor 2 Comparator Configuration Register */
-#define CMP2_LVL2_TRIP 0x37    /* L2 Light Sensor Reference Level, Output Falling for Sensor 2 */
-#define CMP2_LVL2_HYS 0x38     /* L2 Light Sensor Hysteresis (Active when Output Rising) for Sensor 2 */
-#define CMP2_LVL3_TRIP 0x39    /* L3 Light Sensor Reference Level, Output Falling For Sensor 2 */
-#define CMP2_LVL3_HYS 0x3A     /* L3 Light Sensor Hysteresis (Active when Output Rising) For Sensor 2 */
-#define CMP1_ADC_DAT_R1 0x3B   /* Comparator 1 ADC data Register1 */
-#define CMP1_ADC_DAT_R2 0x3C   /* Comparator 1 ADC data Register2 */
-#define CMP2_ADC_DAT_R1 0x3D   /* Comparator 2 ADC data Register1 */
-#define CMP2_ADC_DAT_R2 0x3E   /* Comparator 2 ADC data Register2 */
-
-#define ADP5588_DEVICE_ID_MASK 0xF
-
- /* Configuration Register1 */
-#define ADP5588_AUTO_INC       (1 << 7)
-#define ADP5588_GPIEM_CFG      (1 << 6)
-#define ADP5588_OVR_FLOW_M     (1 << 5)
-#define ADP5588_INT_CFG                (1 << 4)
-#define ADP5588_OVR_FLOW_IEN   (1 << 3)
-#define ADP5588_K_LCK_IM       (1 << 2)
-#define ADP5588_GPI_IEN                (1 << 1)
-#define ADP5588_KE_IEN         (1 << 0)
-
-/* Interrupt Status Register */
-#define ADP5588_CMP2_INT       (1 << 5)
-#define ADP5588_CMP1_INT       (1 << 4)
-#define ADP5588_OVR_FLOW_INT   (1 << 3)
-#define ADP5588_K_LCK_INT      (1 << 2)
-#define ADP5588_GPI_INT                (1 << 1)
-#define ADP5588_KE_INT         (1 << 0)
-
-/* Key Lock and Event Counter Register */
-#define ADP5588_K_LCK_EN       (1 << 6)
-#define ADP5588_LCK21          0x30
-#define ADP5588_KEC            0xF
-
-#define ADP5588_MAXGPIO                18
-#define ADP5588_BANK(offs)     ((offs) >> 3)
-#define ADP5588_BIT(offs)      (1u << ((offs) & 0x7))
-
-/* Put one of these structures in i2c_board_info platform_data */
-
-#define ADP5588_KEYMAPSIZE     80
-
-#define GPI_PIN_ROW0 97
-#define GPI_PIN_ROW1 98
-#define GPI_PIN_ROW2 99
-#define GPI_PIN_ROW3 100
-#define GPI_PIN_ROW4 101
-#define GPI_PIN_ROW5 102
-#define GPI_PIN_ROW6 103
-#define GPI_PIN_ROW7 104
-#define GPI_PIN_COL0 105
-#define GPI_PIN_COL1 106
-#define GPI_PIN_COL2 107
-#define GPI_PIN_COL3 108
-#define GPI_PIN_COL4 109
-#define GPI_PIN_COL5 110
-#define GPI_PIN_COL6 111
-#define GPI_PIN_COL7 112
-#define GPI_PIN_COL8 113
-#define GPI_PIN_COL9 114
-
-#define GPI_PIN_ROW_BASE GPI_PIN_ROW0
-#define GPI_PIN_ROW_END GPI_PIN_ROW7
-#define GPI_PIN_COL_BASE GPI_PIN_COL0
-#define GPI_PIN_COL_END GPI_PIN_COL9
-
-#define GPI_PIN_BASE GPI_PIN_ROW_BASE
-#define GPI_PIN_END GPI_PIN_COL_END
-
-#define ADP5588_GPIMAPSIZE_MAX (GPI_PIN_END - GPI_PIN_BASE + 1)
-
-struct adp5588_gpi_map {
-       unsigned short pin;
-       unsigned short sw_evt;
-};
-
-struct adp5588_kpad_platform_data {
-       int rows;                       /* Number of rows */
-       int cols;                       /* Number of columns */
-       const unsigned short *keymap;   /* Pointer to keymap */
-       unsigned short keymapsize;      /* Keymap size */
-       unsigned repeat:1;              /* Enable key repeat */
-       unsigned en_keylock:1;          /* Enable Key Lock feature */
-       unsigned short unlock_key1;     /* Unlock Key 1 */
-       unsigned short unlock_key2;     /* Unlock Key 2 */
-       const struct adp5588_gpi_map *gpimap;
-       unsigned short gpimapsize;
-       const struct adp5588_gpio_platform_data *gpio_data;
-};
-
-struct i2c_client; /* forward declaration */
-
-struct adp5588_gpio_platform_data {
-       int gpio_start;         /* GPIO Chip base # */
-       const char *const *names;
-       unsigned irq_base;      /* interrupt base # */
-       unsigned pullup_dis_mask; /* Pull-Up Disable Mask */
-       int     (*setup)(struct i2c_client *client,
-                               unsigned gpio, unsigned ngpio,
-                               void *context);
-       int     (*teardown)(struct i2c_client *client,
-                               unsigned gpio, unsigned ngpio,
-                               void *context);
-       void    *context;
-};
-
-#endif
index dff8e7f..7ad931a 100644 (file)
 #define ABS_TOOL_WIDTH         0x1c
 
 #define ABS_VOLUME             0x20
+#define ABS_PROFILE            0x21
 
 #define ABS_MISC               0x28