Merge 5472d60c12 ("Merge tag 'trace-v6.18-2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace") into android-mainline

Steps on the way to v6.18-rc1

Change-Id: I15e6b0829a5a7e0cea05d47fd6dd8abe60d919af
Signed-off-by: Carlos Llamas <cmllamas@google.com>
This commit is contained in:
Carlos Llamas authored and Treehugger Robot committed 2025-11-05 19:16:40 -08:00
commit b2de6741be
509 files changed
+21076 -8436

No files matched your search

+6
View File
@@ -23,3 +23,9 @@ Contact: Longfang Liu <liulongfang@huawei.com>
Description: Read the live migration status of the vfio device.
The contents of the state file reflects the migration state
relative to those defined in the vfio_device_mig_state enum
What: /sys/kernel/debug/vfio/<device>/migration/features
Date: Oct 2025
KernelVersion: 6.18
Contact: Cédric Le Goater <clg@redhat.com>
Description: Read the migration features of the vfio device.
@@ -103,6 +103,28 @@ properties:
- compatible
- "#pwm-cells"
touchscreen:
type: object
$ref: /schemas/input/touchscreen/touchscreen.yaml#
additionalProperties: false
properties:
compatible:
const: raspberrypi,firmware-ts
firmware:
deprecated: true
description: Phandle to RPi's firmware device node.
touchscreen-size-x: true
touchscreen-size-y: true
touchscreen-inverted-x: true
touchscreen-inverted-y: true
touchscreen-swapped-x-y: true
required:
- compatible
required:
- compatible
- mboxes
@@ -135,5 +157,11 @@ examples:
compatible = "raspberrypi,firmware-poe-pwm";
#pwm-cells = <2>;
};
ts: touchscreen {
compatible = "raspberrypi,firmware-ts";
touchscreen-size-x = <800>;
touchscreen-size-y = <480>;
};
};
...
@@ -16,6 +16,7 @@ description: |
allOf:
- $ref: input.yaml#
- $ref: touchscreen/touchscreen.yaml#
properties:
compatible:
@@ -95,7 +96,7 @@ required:
- reg
- interrupts
additionalProperties: false
unevaluatedProperties: false
examples:
- |
@@ -0,0 +1,48 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/awinic,aw86927.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Awinic AW86927 LRA Haptic IC
maintainers:
- Griffin Kroah-Hartman <griffin.kroah@fairphone.com>
properties:
compatible:
const: awinic,aw86927
reg:
maxItems: 1
reset-gpios:
maxItems: 1
interrupts:
maxItems: 1
required:
- compatible
- reg
- reset-gpios
- interrupts
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
vibrator@5a {
compatible = "awinic,aw86927";
reg = <0x5a>;
interrupts-extended = <&tlmm 101 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&tlmm 100 GPIO_ACTIVE_LOW>;
};
};
@@ -1,34 +0,0 @@
NXP LPC32xx Key Scan Interface
This binding is based on the matrix-keymap binding with the following
changes:
Required Properties:
- compatible: Should be "nxp,lpc3220-key"
- reg: Physical base address of the controller and length of memory mapped
region.
- interrupts: The interrupt number to the cpu.
- clocks: phandle to clock controller plus clock-specifier pair
- nxp,debounce-delay-ms: Debounce delay in ms
- nxp,scan-delay-ms: Repeated scan period in ms
- linux,keymap: the key-code to be reported when the key is pressed
and released, see also
Documentation/devicetree/bindings/input/matrix-keymap.txt
Note: keypad,num-rows and keypad,num-columns are required, and must be equal
since LPC32xx only supports square matrices
Example:
key@40050000 {
compatible = "nxp,lpc3220-key";
reg = <0x40050000 0x1000>;
clocks = <&clk LPC32XX_CLK_KEY>;
interrupt-parent = <&sic1>;
interrupts = <22 IRQ_TYPE_LEVEL_HIGH>;
keypad,num-rows = <1>;
keypad,num-columns = <1>;
nxp,debounce-delay-ms = <3>;
nxp,scan-delay-ms = <34>;
linux,keymap = <0x00000002>;
};
@@ -0,0 +1,61 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/nxp,lpc3220-key.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP LPC32xx Key Scan Interface
maintainers:
- Frank Li <Frank.Li@nxp.com>
properties:
compatible:
const: nxp,lpc3220-key
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
nxp,debounce-delay-ms:
description: Debounce delay in ms
nxp,scan-delay-ms:
description: Repeated scan period in ms
required:
- compatible
- reg
- interrupts
- clocks
- nxp,debounce-delay-ms
- nxp,scan-delay-ms
- linux,keymap
allOf:
- $ref: matrix-keymap.yaml#
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/clock/lpc32xx-clock.h>
key@40050000 {
compatible = "nxp,lpc3220-key";
reg = <0x40050000 0x1000>;
clocks = <&clk LPC32XX_CLK_KEY>;
interrupt-parent = <&sic1>;
interrupts = <22 IRQ_TYPE_LEVEL_HIGH>;
keypad,num-rows = <1>;
keypad,num-columns = <1>;
nxp,debounce-delay-ms = <3>;
nxp,scan-delay-ms = <34>;
linux,keymap = <0x00000002>;
};
@@ -10,9 +10,6 @@ maintainers:
- Courtney Cavin <courtney.cavin@sonymobile.com>
- Vinod Koul <vkoul@kernel.org>
allOf:
- $ref: input.yaml#
properties:
compatible:
enum:
@@ -25,23 +22,40 @@ properties:
maxItems: 1
debounce:
description: |
Time in microseconds that key must be pressed or
released for state change interrupt to trigger.
description:
Time in microseconds that key must be pressed or released for state
change interrupt to trigger.
$ref: /schemas/types.yaml#/definitions/uint32
bias-pull-up:
description: |
Presence of this property indicates that the KPDPWR_N
pin should be configured for pull up.
description:
Presence of this property indicates that the KPDPWR_N pin should be
configured for pull up.
$ref: /schemas/types.yaml#/definitions/flag
wakeup-source:
description:
Button can wake-up the system. Only applicable for 'resin', 'pwrkey'
always wakes the system by default.
linux,code:
description: |
The input key-code associated with the power key.
Use the linux event codes defined in
include/dt-bindings/input/linux-event-codes.h
When property is omitted KEY_POWER is assumed.
description:
The input key-code associated with the power key. Use the linux event
codes defined in include/dt-bindings/input/linux-event-codes.h.
When property is omitted KEY_POWER is assumed.
allOf:
- $ref: input.yaml#
- if:
properties:
compatible:
contains:
enum:
- qcom,pm8941-pwrkey
- qcom,pmk8350-pwrkey
then:
properties:
wakeup-source: false
required:
- compatible
@@ -1,10 +0,0 @@
This binding is based on the matrix-keymap binding with the following
changes:
keypad,num-rows and keypad,num-columns are required.
Required properties:
- compatible: "ti,tca8418"
- reg: the I2C address
- interrupts: IRQ line number, should trigger on falling edge
- linux,keymap: Keys definitions, see keypad-matrix.
@@ -0,0 +1,61 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/ti,tca8418.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI TCA8418 I2C/SMBus keypad scanner
maintainers:
- Frank Li <Frank.Li@nxp.com>
properties:
compatible:
enum:
- ti,tca8418
reg:
maxItems: 1
interrupts:
maxItems: 1
required:
- compatible
- reg
- interrupts
allOf:
- $ref: matrix-keymap.yaml#
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
keypad@34 {
compatible = "ti,tca8418";
reg = <0x34>;
interrupt-parent = <&gpio5>;
interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
keypad,num-rows = <4>;
keypad,num-columns = <4>;
linux,keymap = < MATRIX_KEY(0x00, 0x01, BTN_0)
MATRIX_KEY(0x00, 0x00, BTN_1)
MATRIX_KEY(0x01, 0x01, BTN_2)
MATRIX_KEY(0x01, 0x00, BTN_3)
MATRIX_KEY(0x02, 0x00, BTN_4)
MATRIX_KEY(0x00, 0x03, BTN_5)
MATRIX_KEY(0x00, 0x02, BTN_6)
MATRIX_KEY(0x01, 0x03, BTN_7)
MATRIX_KEY(0x01, 0x02, BTN_8)
MATRIX_KEY(0x02, 0x02, BTN_9)
>;
};
};
@@ -1,43 +0,0 @@
* Rohm BU21013 Touch Screen
Required properties:
- compatible : "rohm,bu21013_tp"
- reg : I2C device address
- reset-gpios : GPIO pin enabling (selecting) chip (CS)
- interrupt-parent : the phandle for the gpio controller
- interrupts : (gpio) interrupt to which the chip is connected
Optional properties:
- touch-gpios : GPIO pin registering a touch event
- <supply_name>-supply : Phandle to a regulator supply
- touchscreen-size-x : General touchscreen binding, see [1].
- touchscreen-size-y : General touchscreen binding, see [1].
- touchscreen-inverted-x : General touchscreen binding, see [1].
- touchscreen-inverted-y : General touchscreen binding, see [1].
- touchscreen-swapped-x-y : General touchscreen binding, see [1].
[1] All general touchscreen properties are described in
Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt.
Deprecated properties:
- rohm,touch-max-x : Maximum outward permitted limit in the X axis
- rohm,touch-max-y : Maximum outward permitted limit in the Y axis
- rohm,flip-x : Flip touch coordinates on the X axis
- rohm,flip-y : Flip touch coordinates on the Y axis
Example:
i2c@80110000 {
bu21013_tp@5c {
compatible = "rohm,bu21013_tp";
reg = <0x5c>;
interrupt-parent = <&gpio2>;
interrupts <&20 IRQ_TYPE_LEVEL_LOW>;
touch-gpio = <&gpio2 20 GPIO_ACTIVE_LOW>;
avdd-supply = <&ab8500_ldo_aux1_reg>;
touchscreen-size-x = <384>;
touchscreen-size-y = <704>;
touchscreen-inverted-y;
};
};
@@ -9,27 +9,35 @@ title: EETI EXC3000 series touchscreen controller
maintainers:
- Dmitry Torokhov <dmitry.torokhov@gmail.com>
allOf:
- $ref: touchscreen.yaml#
properties:
compatible:
oneOf:
- const: eeti,exc3000
- const: eeti,exc80h60
- const: eeti,exc80h84
- const: eeti,egalax_ts # Do NOT use for new binding
- const: eeti,exc3000-i2c
deprecated: true
- items:
- enum:
- eeti,exc81w32
- const: eeti,exc80h84
reg:
const: 0x2a
enum: [0x4, 0xa, 0x2a]
interrupts:
maxItems: 1
reset-gpios:
maxItems: 1
wakeup-gpios:
maxItems: 1
vdd-supply:
description: Power supply regulator for the chip
attn-gpios:
deprecated: true
maxItems: 1
description: Phandle to a GPIO to check whether interrupt is still
latched. This is necessary for platforms that lack
support for level-triggered IRQs.
touchscreen-size-x: true
touchscreen-size-y: true
touchscreen-inverted-x: true
@@ -40,11 +48,33 @@ required:
- compatible
- reg
- interrupts
- touchscreen-size-x
- touchscreen-size-y
additionalProperties: false
allOf:
- $ref: touchscreen.yaml#
- if:
properties:
compatible:
not:
contains:
enum:
- eeti,egalax_ts
- eeti,exc3000-i2c
then:
properties:
reg:
const: 0x2a
wakeup-gpios: false
attn-gpios: false
required:
- touchscreen-size-x
- touchscreen-size-y
examples:
- |
#include "dt-bindings/interrupt-controller/irq.h"
@@ -1,30 +0,0 @@
Bindings for EETI touchscreen controller
Required properties:
- compatible: should be "eeti,exc3000-i2c"
- reg: I2C address of the chip. Should be set to <0xa>
- interrupts: interrupt to which the chip is connected
Optional properties:
- attn-gpios: A handle to a GPIO to check whether interrupt is still
latched. This is necessary for platforms that lack
support for level-triggered IRQs.
The following optional properties described in touchscreen.txt are
also supported:
- touchscreen-inverted-x
- touchscreen-inverted-y
- touchscreen-swapped-x-y
Example:
i2c-master {
touchscreen@a {
compatible = "eeti,exc3000-i2c";
reg = <0xa>;
interrupt-parent = <&gpio>;
interrupts = <123 IRQ_TYPE_EDGE_RISING>;
attn-gpios = <&gpio 123 GPIO_ACTIVE_HIGH>;
};
};
@@ -1,18 +0,0 @@
* EETI eGalax Multiple Touch Controller
Required properties:
- compatible: must be "eeti,egalax_ts"
- reg: i2c slave address
- interrupts: touch controller interrupt
- wakeup-gpios: the gpio pin to be used for waking up the controller
and also used as irq pin
Example:
touchscreen@4 {
compatible = "eeti,egalax_ts";
reg = <0x04>;
interrupt-parent = <&gpio1>;
interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
wakeup-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
};
@@ -62,6 +62,20 @@ properties:
description: Number of data samples which are averaged for each read.
enum: [ 1, 4, 8, 16, 32 ]
debounce-delay-us:
description: |
Minimum duration in microseconds a signal must remain stable
to be considered valid.
Drivers must convert this value to IPG clock cycles and map
it to one of the four discrete thresholds exposed by the
TSC_DEBUG_MODE2 register:
0: 8191 IPG cycles
1: 4095 IPG cycles
2: 2047 IPG cycles
3: 1023 IPG cycles
required:
- compatible
- reg
@@ -62,7 +62,6 @@ additionalProperties: false
required:
- compatible
- reg
- interrupts
examples:
- |
@@ -0,0 +1,81 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/touchscreen/himax,hx852es.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Himax HX852x(ES) touch panel controller
maintainers:
- Stephan Gerhold <stephan@gerhold.net>
allOf:
- $ref: touchscreen.yaml#
properties:
compatible:
items:
- enum:
- himax,hx8525e
- himax,hx8526e
- himax,hx8527e
- const: himax,hx852es
reg:
maxItems: 1
interrupts:
maxItems: 1
description: Touch Screen Interrupt (TSIX), active low
reset-gpios:
maxItems: 1
description: External Reset (XRES), active low
vcca-supply:
description: Analog power supply (VCCA)
vccd-supply:
description: Digital power supply (VCCD)
touchscreen-inverted-x: true
touchscreen-inverted-y: true
touchscreen-size-x: true
touchscreen-size-y: true
touchscreen-swapped-x-y: true
linux,keycodes:
minItems: 1
maxItems: 4
required:
- compatible
- reg
- interrupts
- reset-gpios
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
touchscreen@48 {
compatible = "himax,hx8527e", "himax,hx852es";
reg = <0x48>;
interrupt-parent = <&tlmm>;
interrupts = <13 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&tlmm 12 GPIO_ACTIVE_LOW>;
vcca-supply = <&reg_ts_vcca>;
vccd-supply = <&pm8916_l6>;
linux,keycodes = <KEY_BACK KEY_HOMEPAGE KEY_APPSELECT>;
};
};
...
@@ -0,0 +1,65 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/touchscreen/hynitron,cst816x.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Hynitron CST816x Series Capacitive Touch controller
maintainers:
- Oleh Kuzhylnyi <kuzhylol@gmail.com>
description: |
Bindings for CST816x high performance self-capacitance touch chip series
with single point gesture and real two-point operation.
properties:
compatible:
enum:
- hynitron,cst816s
reg:
maxItems: 1
interrupts:
maxItems: 1
reset-gpios:
maxItems: 1
linux,keycodes:
minItems: 1
items:
- description: Slide up gesture
- description: Slide down gesture
- description: Slide left gesture
- description: Slide right gesture
- description: Long press gesture
required:
- compatible
- reg
- interrupts
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/linux-event-codes.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
touchscreen@15 {
compatible = "hynitron,cst816s";
reg = <0x15>;
interrupt-parent = <&gpio0>;
interrupts = <4 IRQ_TYPE_EDGE_RISING>;
reset-gpios = <&gpio 17 GPIO_ACTIVE_LOW>;
linux,keycodes = <KEY_UP>, <KEY_DOWN>, <KEY_LEFT>, <KEY_RIGHT>,
<BTN_TOOL_TRIPLETAP>;
};
};
...
@@ -35,6 +35,7 @@ properties:
linux,keycodes:
description: Keycodes for the touch keys
minItems: 2
maxItems: 5
touchscreen-size-x: true
@@ -87,5 +88,22 @@ examples:
touchscreen-inverted-y;
};
};
- |
#include <dt-bindings/input/linux-event-codes.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
touchscreen@50 {
compatible = "imagis,ist3032c";
reg = <0x50>;
interrupt-parent = <&gpio>;
interrupts = <72 IRQ_TYPE_EDGE_FALLING>;
vdd-supply = <&ldo2>;
touchscreen-size-x = <480>;
touchscreen-size-y = <800>;
linux,keycodes = <KEY_APPSELECT>, <KEY_BACK>;
};
};
...
@@ -1,17 +0,0 @@
* MAXI MAX11801 Resistive touch screen controller with i2c interface
Required properties:
- compatible: must be "maxim,max11801"
- reg: i2c slave address
- interrupts: touch controller interrupt
Example:
&i2c1 {
max11801: touchscreen@48 {
compatible = "maxim,max11801";
reg = <0x48>;
interrupt-parent = <&gpio3>;
interrupts = <31 IRQ_TYPE_EDGE_FALLING>;
};
};
@@ -0,0 +1,46 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/touchscreen/maxim,max11801.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MAXI MAX11801 Resistive touch screen controller with i2c interface
maintainers:
- Frank Li <Frank.Li@nxp.com>
properties:
compatible:
const: maxim,max11801
reg:
maxItems: 1
interrupts:
maxItems: 1
allOf:
- $ref: touchscreen.yaml
required:
- compatible
- reg
- interrupts
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
touchscreen@48 {
compatible = "maxim,max11801";
reg = <0x48>;
interrupt-parent = <&gpio3>;
interrupts = <31 IRQ_TYPE_EDGE_FALLING>;
};
};
@@ -1,26 +0,0 @@
Raspberry Pi firmware based 7" touchscreen
=====================================
Required properties:
- compatible: "raspberrypi,firmware-ts"
Optional properties:
- firmware: Reference to RPi's firmware device node
- touchscreen-size-x: See touchscreen.txt
- touchscreen-size-y: See touchscreen.txt
- touchscreen-inverted-x: See touchscreen.txt
- touchscreen-inverted-y: See touchscreen.txt
- touchscreen-swapped-x-y: See touchscreen.txt
Example:
firmware: firmware-rpi {
compatible = "raspberrypi,bcm2835-firmware";
mboxes = <&mailbox>;
ts: touchscreen {
compatible = "raspberrypi,firmware-ts";
touchscreen-size-x = <800>;
touchscreen-size-y = <480>;
};
};
@@ -55,7 +55,7 @@ properties:
touchscreen-min-pressure: true
touchscreen-x-plate-ohms: true
additionalProperties: false
unevaluatedProperties: false
required:
- compatible
@@ -0,0 +1,95 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/touchscreen/rohm,bu21013.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Rohm BU21013 touchscreen
description:
Rohm BU21013 I2C driven touchscreen controller.
maintainers:
- Dario Binacchi <dario.binacchi@amarulasolutions.com>
allOf:
- $ref: touchscreen.yaml#
properties:
compatible:
enum:
- rohm,bu21013_tp
reg:
maxItems: 1
interrupts:
maxItems: 1
reset-gpios:
maxItems: 1
touch-gpios:
maxItems: 1
description: GPIO registering a touch event.
avdd-supply:
description: Analogic power supply
rohm,touch-max-x:
deprecated: true
description: Maximum value on the X axis.
$ref: /schemas/types.yaml#/definitions/uint32
rohm,touch-max-y:
deprecated: true
description: Maximum value on the Y axis.
$ref: /schemas/types.yaml#/definitions/uint32
rohm,flip-x:
deprecated: true
description: Flip touch coordinates on the X axis
type: boolean
rohm,flip-y:
deprecated: true
description: Flip touch coordinates on the Y axis
type: boolean
touchscreen-inverted-x: true
touchscreen-inverted-y: true
touchscreen-size-x: true
touchscreen-size-y: true
touchscreen-swapped-x-y: true
additionalProperties: false
required:
- compatible
- reg
- reset-gpios
- interrupts
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
touchscreen@5c {
compatible = "rohm,bu21013_tp";
reg = <0x5c>;
interrupt-parent = <&gpio2>;
interrupts = <0x20 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio2 19 GPIO_ACTIVE_LOW>;
touch-gpios = <&gpio2 20 GPIO_ACTIVE_LOW>;
avdd-supply = <&ab8500_ldo_aux1_reg>;
touchscreen-size-x = <384>;
touchscreen-size-y = <704>;
touchscreen-inverted-y;
};
};
@@ -0,0 +1,52 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/touchscreen/semtech,sx8654.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Semtech SX8654 I2C Touchscreen Controller
maintainers:
- Frank Li <Frank.Li@nxp.com>
properties:
compatible:
enum:
- semtech,sx8650
- semtech,sx8654
- semtech,sx8655
- semtech,sx8656
reg:
maxItems: 1
interrupts:
maxItems: 1
reset-gpios:
maxItems: 1
required:
- compatible
- reg
- interrupts
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
touchscreen@48 {
compatible = "semtech,sx8654";
reg = <0x48>;
interrupt-parent = <&gpio6>;
interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&gpio4 2 GPIO_ACTIVE_LOW>;
};
};
@@ -1,23 +0,0 @@
* Semtech SX8654 I2C Touchscreen Controller
Required properties:
- compatible: must be one of the following, depending on the model:
"semtech,sx8650"
"semtech,sx8654"
"semtech,sx8655"
"semtech,sx8656"
- reg: i2c slave address
- interrupts: touch controller interrupt
Optional properties:
- reset-gpios: GPIO specification for the NRST input
Example:
sx8654@48 {
compatible = "semtech,sx8654";
reg = <0x48>;
interrupt-parent = <&gpio6>;
interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&gpio4 2 GPIO_ACTIVE_LOW>;
};
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/touchscreen/ti.tsc2007.yaml#
$id: http://devicetree.org/schemas/input/touchscreen/ti,tsc2007.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments tsc2007 touchscreen controller
@@ -26,6 +26,8 @@ properties:
pendown-gpio: true
wakeup-source: true
ti,max-rt:
$ref: /schemas/types.yaml#/definitions/uint32
description: maximum pressure.
@@ -1 +0,0 @@
See touchscreen.yaml
@@ -206,6 +206,10 @@ properties:
unevaluatedProperties: false
debounce-delay-us:
description: Minimum duration in microseconds a signal must remain stable
to be considered valid.
dependencies:
touchscreen-size-x: [ touchscreen-size-y ]
touchscreen-size-y: [ touchscreen-size-x ]
@@ -0,0 +1,62 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/touchscreen/zeitec,zet6223.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Zeitec ZET6223 touchscreen controller
description:
Zeitec ZET6223 I2C driven touchscreen controller.
maintainers:
- Dario Binacchi <dario.binacchi@amarulasolutions.com>
allOf:
- $ref: touchscreen.yaml#
properties:
compatible:
enum:
- zeitec,zet6223
reg:
maxItems: 1
interrupts:
maxItems: 1
vio-supply:
description: 1.8V or 3.3V VIO supply.
vcc-supply:
description: 3.3V VCC supply.
touchscreen-inverted-x: true
touchscreen-inverted-y: true
touchscreen-size-x: true
touchscreen-size-y: true
touchscreen-swapped-x-y: true
additionalProperties: false
required:
- compatible
- reg
- interrupts
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
touchscreen@76 {
compatible = "zeitec,zet6223";
reg = <0x76>;
interrupt-parent = <&pio>;
interrupts = <6 11 IRQ_TYPE_EDGE_FALLING>;
};
};
@@ -1,30 +0,0 @@
Zeitec ZET6223 I2C touchscreen controller
Required properties:
- compatible : "zeitec,zet6223"
- reg : I2C slave address of the chip (0x76)
- interrupts : interrupt specification for the zet6223 interrupt
Optional properties:
- vio-supply : Specification for VIO supply (1.8V or 3.3V,
depending on system interface needs).
- vcc-supply : Specification for 3.3V VCC supply.
- touchscreen-size-x : See touchscreen.txt
- touchscreen-size-y : See touchscreen.txt
- touchscreen-inverted-x : See touchscreen.txt
- touchscreen-inverted-y : See touchscreen.txt
- touchscreen-swapped-x-y : See touchscreen.txt
Example:
i2c@00000000 {
zet6223: touchscreen@76 {
compatible = "zeitec,zet6223";
reg = <0x76>;
interrupt-parent = <&pio>;
interrupts = <6 11 IRQ_TYPE_EDGE_FALLING>
};
};
@@ -0,0 +1,64 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/mailbox/mediatek,mt8196-gpueb-mbox.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek MFlexGraphics GPUEB Mailbox Controller
maintainers:
- Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
properties:
compatible:
enum:
- mediatek,mt8196-gpueb-mbox
reg:
items:
- description: mailbox data registers
- description: mailbox control registers
reg-names:
items:
- const: data
- const: ctl
clocks:
items:
- description: main clock of the GPUEB MCU
interrupts:
items:
- description: fires when a new message is received
"#mbox-cells":
const: 1
description:
The number of the mailbox channel.
required:
- compatible
- reg
- reg-names
- clocks
- interrupts
- "#mbox-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/mediatek,mt8196-clock.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
mailbox@4b09fd80 {
compatible = "mediatek,mt8196-gpueb-mbox";
reg = <0x4b09fd80 0x280>,
<0x4b170000 0x7c>;
reg-names = "data", "ctl";
clocks = <&topckgen CLK_TOP_MFG_EB>;
interrupts = <GIC_SPI 608 IRQ_TYPE_LEVEL_HIGH 0>;
#mbox-cells = <1>;
};
@@ -15,8 +15,13 @@ description:
properties:
compatible:
items:
- const: qcom,x1e80100-cpucp-mbox
oneOf:
- items:
- enum:
- qcom,glymur-cpucp-mbox
- const: qcom,x1e80100-cpucp-mbox
- enum:
- qcom,x1e80100-cpucp-mbox
reg:
items:
+8 -2
View File
@@ -924,7 +924,7 @@ R: Pali Rohár <pali@kernel.org>
F: drivers/input/mouse/alps.*
ALTERA MAILBOX DRIVER
M: Mun Yew Tham <mun.yew.tham@intel.com>
M: Tien Sung Ang <tiensung.ang@altera.com>
S: Maintained
F: drivers/mailbox/mailbox-altera.c
@@ -11168,6 +11168,13 @@ S: Maintained
F: Documentation/devicetree/bindings/input/touchscreen/himax,hx83112b.yaml
F: drivers/input/touchscreen/himax_hx83112b.c
HIMAX HX852X TOUCHSCREEN DRIVER
M: Stephan Gerhold <stephan@gerhold.net>
L: linux-input@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/input/touchscreen/himax,hx852es.yaml
F: drivers/input/touchscreen/himax_hx852x.c
HIPPI
M: Jes Sorensen <jes@trained-monkey.org>
S: Maintained
@@ -20131,7 +20138,6 @@ R: Alexander Shishkin <alexander.shishkin@linux.intel.com>
R: Jiri Olsa <jolsa@kernel.org>
R: Ian Rogers <irogers@google.com>
R: Adrian Hunter <adrian.hunter@intel.com>
R: "Liang, Kan" <kan.liang@linux.intel.com>
L: linux-perf-users@vger.kernel.org
L: linux-kernel@vger.kernel.org
S: Supported
+1
View File
@@ -25,6 +25,7 @@ endif
KBUILD_CFLAGS_DECOMPRESSOR := $(CLANG_FLAGS) -m64 -O2 -mpacked-stack -std=gnu11
KBUILD_CFLAGS_DECOMPRESSOR += -DDISABLE_BRANCH_PROFILING -D__NO_FORTIFY
KBUILD_CFLAGS_DECOMPRESSOR += -D__DECOMPRESSOR
KBUILD_CFLAGS_DECOMPRESSOR += -Wno-pointer-sign
KBUILD_CFLAGS_DECOMPRESSOR += -fno-delete-null-pointer-checks -msoft-float -mbackchain
KBUILD_CFLAGS_DECOMPRESSOR += -fno-asynchronous-unwind-tables
KBUILD_CFLAGS_DECOMPRESSOR += -ffreestanding
+1 -1
View File
@@ -27,7 +27,7 @@ static inline unsigned long __hypfs_sprp_diag304(void *data, unsigned long cmd)
{
union register_pair r1 = { .even = virt_to_phys(data), };
asm volatile("diag %[r1],%[r3],0x304\n"
asm volatile("diag %[r1],%[r3],0x304"
: [r1] "+&d" (r1.pair)
: [r3] "d" (cmd)
: "memory");
+9 -9
View File
@@ -143,7 +143,7 @@ static inline struct ap_queue_status ap_tapq(ap_qid_t qid,
" lghi 2,0\n" /* 0 into gr2 */
" .insn rre,0xb2af0000,0,0\n" /* PQAP(TAPQ) */
" lgr %[reg1],1\n" /* gr1 (status) into reg1 */
" lgr %[reg2],2\n" /* gr2 into reg2 */
" lgr %[reg2],2" /* gr2 into reg2 */
: [reg1] "=&d" (reg1.value), [reg2] "=&d" (reg2)
: [qid] "d" (qid)
: "cc", "0", "1", "2");
@@ -186,7 +186,7 @@ static inline struct ap_queue_status ap_rapq(ap_qid_t qid, int fbit)
asm volatile(
" lgr 0,%[reg0]\n" /* qid arg into gr0 */
" .insn rre,0xb2af0000,0,0\n" /* PQAP(RAPQ) */
" lgr %[reg1],1\n" /* gr1 (status) into reg1 */
" lgr %[reg1],1" /* gr1 (status) into reg1 */
: [reg1] "=&d" (reg1.value)
: [reg0] "d" (reg0)
: "cc", "0", "1");
@@ -211,7 +211,7 @@ static inline struct ap_queue_status ap_zapq(ap_qid_t qid, int fbit)
asm volatile(
" lgr 0,%[reg0]\n" /* qid arg into gr0 */
" .insn rre,0xb2af0000,0,0\n" /* PQAP(ZAPQ) */
" lgr %[reg1],1\n" /* gr1 (status) into reg1 */
" lgr %[reg1],1" /* gr1 (status) into reg1 */
: [reg1] "=&d" (reg1.value)
: [reg0] "d" (reg0)
: "cc", "0", "1");
@@ -315,7 +315,7 @@ static inline struct ap_queue_status ap_aqic(ap_qid_t qid,
" lgr 1,%[reg1]\n" /* irq ctrl into gr1 */
" lgr 2,%[reg2]\n" /* ni addr into gr2 */
" .insn rre,0xb2af0000,0,0\n" /* PQAP(AQIC) */
" lgr %[reg1],1\n" /* gr1 (status) into reg1 */
" lgr %[reg1],1" /* gr1 (status) into reg1 */
: [reg1] "+&d" (reg1.value)
: [reg0] "d" (reg0), [reg2] "d" (reg2)
: "cc", "memory", "0", "1", "2");
@@ -363,7 +363,7 @@ static inline struct ap_queue_status ap_qact(ap_qid_t qid, int ifbit,
" lgr 1,%[reg1]\n" /* qact in info into gr1 */
" .insn rre,0xb2af0000,0,0\n" /* PQAP(QACT) */
" lgr %[reg1],1\n" /* gr1 (status) into reg1 */
" lgr %[reg2],2\n" /* qact out info into reg2 */
" lgr %[reg2],2" /* qact out info into reg2 */
: [reg1] "+&d" (reg1.value), [reg2] "=&d" (reg2)
: [reg0] "d" (reg0)
: "cc", "0", "1", "2");
@@ -388,7 +388,7 @@ static inline struct ap_queue_status ap_bapq(ap_qid_t qid)
asm volatile(
" lgr 0,%[reg0]\n" /* qid arg into gr0 */
" .insn rre,0xb2af0000,0,0\n" /* PQAP(BAPQ) */
" lgr %[reg1],1\n" /* gr1 (status) into reg1 */
" lgr %[reg1],1" /* gr1 (status) into reg1 */
: [reg1] "=&d" (reg1.value)
: [reg0] "d" (reg0)
: "cc", "0", "1");
@@ -416,7 +416,7 @@ static inline struct ap_queue_status ap_aapq(ap_qid_t qid, unsigned int sec_idx)
" lgr 0,%[reg0]\n" /* qid arg into gr0 */
" lgr 2,%[reg2]\n" /* secret index into gr2 */
" .insn rre,0xb2af0000,0,0\n" /* PQAP(AAPQ) */
" lgr %[reg1],1\n" /* gr1 (status) into reg1 */
" lgr %[reg1],1" /* gr1 (status) into reg1 */
: [reg1] "=&d" (reg1.value)
: [reg0] "d" (reg0), [reg2] "d" (reg2)
: "cc", "0", "1", "2");
@@ -453,7 +453,7 @@ static inline struct ap_queue_status ap_nqap(ap_qid_t qid,
" lgr 0,%[reg0]\n" /* qid param in gr0 */
"0: .insn rre,0xb2ad0000,%[nqap_r1],%[nqap_r2]\n"
" brc 2,0b\n" /* handle partial completion */
" lgr %[reg1],1\n" /* gr1 (status) into reg1 */
" lgr %[reg1],1" /* gr1 (status) into reg1 */
: [reg0] "+&d" (reg0), [reg1] "=&d" (reg1.value),
[nqap_r2] "+&d" (nqap_r2.pair)
: [nqap_r1] "d" (nqap_r1.pair)
@@ -518,7 +518,7 @@ static inline struct ap_queue_status ap_dqap(ap_qid_t qid,
" brc 6,0b\n" /* handle partial complete */
"2: lgr %[reg0],0\n" /* gr0 (qid + info) into reg0 */
" lgr %[reg1],1\n" /* gr1 (status) into reg1 */
" lgr %[reg2],2\n" /* gr2 (res length) into reg2 */
" lgr %[reg2],2" /* gr2 (res length) into reg2 */
: [reg0] "+&d" (reg0), [reg1] "=&d" (reg1.value),
[reg2] "=&d" (reg2), [rp1] "+&d" (rp1.pair),
[rp2] "+&d" (rp2.pair)
+14 -14
View File
@@ -17,7 +17,7 @@ static __always_inline int __atomic_read(const int *ptr)
int val;
asm volatile(
" l %[val],%[ptr]\n"
" l %[val],%[ptr]"
: [val] "=d" (val) : [ptr] "R" (*ptr));
return val;
}
@@ -26,11 +26,11 @@ static __always_inline void __atomic_set(int *ptr, int val)
{
if (__builtin_constant_p(val) && val >= S16_MIN && val <= S16_MAX) {
asm volatile(
" mvhi %[ptr],%[val]\n"
" mvhi %[ptr],%[val]"
: [ptr] "=Q" (*ptr) : [val] "K" (val));
} else {
asm volatile(
" st %[val],%[ptr]\n"
" st %[val],%[ptr]"
: [ptr] "=R" (*ptr) : [val] "d" (val));
}
}
@@ -40,7 +40,7 @@ static __always_inline long __atomic64_read(const long *ptr)
long val;
asm volatile(
" lg %[val],%[ptr]\n"
" lg %[val],%[ptr]"
: [val] "=d" (val) : [ptr] "RT" (*ptr));
return val;
}
@@ -49,11 +49,11 @@ static __always_inline void __atomic64_set(long *ptr, long val)
{
if (__builtin_constant_p(val) && val >= S16_MIN && val <= S16_MAX) {
asm volatile(
" mvghi %[ptr],%[val]\n"
" mvghi %[ptr],%[val]"
: [ptr] "=Q" (*ptr) : [val] "K" (val));
} else {
asm volatile(
" stg %[val],%[ptr]\n"
" stg %[val],%[ptr]"
: [ptr] "=RT" (*ptr) : [val] "d" (val));
}
}
@@ -66,7 +66,7 @@ static __always_inline op_type op_name(op_type val, op_type *ptr) \
op_type old; \
\
asm volatile( \
op_string " %[old],%[val],%[ptr]\n" \
op_string " %[old],%[val],%[ptr]" \
op_barrier \
: [old] "=d" (old), [ptr] "+QS" (*ptr) \
: [val] "d" (val) : "cc", "memory"); \
@@ -75,7 +75,7 @@ static __always_inline op_type op_name(op_type val, op_type *ptr) \
#define __ATOMIC_OPS(op_name, op_type, op_string) \
__ATOMIC_OP(op_name, op_type, op_string, "") \
__ATOMIC_OP(op_name##_barrier, op_type, op_string, "bcr 14,0\n")
__ATOMIC_OP(op_name##_barrier, op_type, op_string, "\nbcr 14,0")
__ATOMIC_OPS(__atomic_add, int, "laa")
__ATOMIC_OPS(__atomic_and, int, "lan")
@@ -94,14 +94,14 @@ __ATOMIC_OPS(__atomic64_xor, long, "laxg")
static __always_inline void op_name(op_type val, op_type *ptr) \
{ \
asm volatile( \
op_string " %[ptr],%[val]\n" \
op_string " %[ptr],%[val]" \
op_barrier \
: [ptr] "+QS" (*ptr) : [val] "i" (val) : "cc", "memory");\
}
#define __ATOMIC_CONST_OPS(op_name, op_type, op_string) \
__ATOMIC_CONST_OP(op_name, op_type, op_string, "") \
__ATOMIC_CONST_OP(op_name##_barrier, op_type, op_string, "bcr 14,0\n")
__ATOMIC_CONST_OP(op_name##_barrier, op_type, op_string, "\nbcr 14,0")
__ATOMIC_CONST_OPS(__atomic_add_const, int, "asi")
__ATOMIC_CONST_OPS(__atomic64_add_const, long, "agsi")
@@ -179,7 +179,7 @@ static __always_inline bool op_name(op_type val, op_type *ptr) \
int cc; \
\
asm volatile( \
op_string " %[tmp],%[val],%[ptr]\n" \
op_string " %[tmp],%[val],%[ptr]" \
op_barrier \
: "=@cc" (cc), [tmp] "=d" (tmp), [ptr] "+QS" (*ptr) \
: [val] "d" (val) \
@@ -189,7 +189,7 @@ static __always_inline bool op_name(op_type val, op_type *ptr) \
#define __ATOMIC_TEST_OPS(op_name, op_type, op_string) \
__ATOMIC_TEST_OP(op_name, op_type, op_string, "") \
__ATOMIC_TEST_OP(op_name##_barrier, op_type, op_string, "bcr 14,0\n")
__ATOMIC_TEST_OP(op_name##_barrier, op_type, op_string, "\nbcr 14,0")
__ATOMIC_TEST_OPS(__atomic_add_and_test, int, "laal")
__ATOMIC_TEST_OPS(__atomic64_add_and_test, long, "laalg")
@@ -203,7 +203,7 @@ static __always_inline bool op_name(op_type val, op_type *ptr) \
int cc; \
\
asm volatile( \
op_string " %[ptr],%[val]\n" \
op_string " %[ptr],%[val]" \
op_barrier \
: "=@cc" (cc), [ptr] "+QS" (*ptr) \
: [val] "i" (val) \
@@ -213,7 +213,7 @@ static __always_inline bool op_name(op_type val, op_type *ptr) \
#define __ATOMIC_CONST_TEST_OPS(op_name, op_type, op_string) \
__ATOMIC_CONST_TEST_OP(op_name, op_type, op_string, "") \
__ATOMIC_CONST_TEST_OP(op_name##_barrier, op_type, op_string, "bcr 14,0\n")
__ATOMIC_CONST_TEST_OP(op_name##_barrier, op_type, op_string, "\nbcr 14,0")
__ATOMIC_CONST_TEST_OPS(__atomic_add_const_and_test, int, "alsi")
__ATOMIC_CONST_TEST_OPS(__atomic64_add_const_and_test, long, "algsi")
+4 -4
View File
@@ -18,9 +18,9 @@
#ifdef MARCH_HAS_Z196_FEATURES
/* Fast-BCR without checkpoint synchronization */
#define __ASM_BCR_SERIALIZE "bcr 14,0\n"
#define __ASM_BCR_SERIALIZE "bcr 14,0"
#else
#define __ASM_BCR_SERIALIZE "bcr 15,0\n"
#define __ASM_BCR_SERIALIZE "bcr 15,0"
#endif
static __always_inline void bcr_serialize(void)
@@ -69,12 +69,12 @@ static inline unsigned long array_index_mask_nospec(unsigned long index,
if (__builtin_constant_p(size) && size > 0) {
asm(" clgr %2,%1\n"
" slbgr %0,%0\n"
" slbgr %0,%0"
:"=d" (mask) : "d" (size-1), "d" (index) :"cc");
return mask;
}
asm(" clgr %1,%2\n"
" slbgr %0,%0\n"
" slbgr %0,%0"
:"=d" (mask) : "d" (size), "d" (index) :"cc");
return ~mask;
}
+1 -1
View File
@@ -62,7 +62,7 @@ static __always_inline bool arch_test_bit(unsigned long nr, const volatile unsig
addr += (nr ^ (BITS_PER_LONG - BITS_PER_BYTE)) / BITS_PER_BYTE;
mask = 1UL << (nr & (BITS_PER_BYTE - 1));
asm volatile(
" tm %[addr],%[mask]\n"
" tm %[addr],%[mask]"
: "=@cc" (cc)
: [addr] "Q" (*addr), [mask] "I" (mask)
);
+1 -1
View File
@@ -27,7 +27,7 @@ static inline __wsum cksm(const void *buff, int len, __wsum sum)
kmsan_check_memory(buff, len);
asm volatile(
"0: cksm %[sum],%[rp]\n"
" jo 0b\n"
" jo 0b"
: [sum] "+&d" (sum), [rp] "+&d" (rp.pair) : : "cc", "memory");
return sum;
}
+6 -6
View File
@@ -18,7 +18,7 @@ void __cmpxchg_called_with_bad_pointer(void);
static __always_inline u32 __cs_asm(u64 ptr, u32 old, u32 new)
{
asm volatile(
" cs %[old],%[new],%[ptr]\n"
" cs %[old],%[new],%[ptr]"
: [old] "+d" (old), [ptr] "+Q" (*(u32 *)ptr)
: [new] "d" (new)
: "memory", "cc");
@@ -28,7 +28,7 @@ static __always_inline u32 __cs_asm(u64 ptr, u32 old, u32 new)
static __always_inline u64 __csg_asm(u64 ptr, u64 old, u64 new)
{
asm volatile(
" csg %[old],%[new],%[ptr]\n"
" csg %[old],%[new],%[ptr]"
: [old] "+d" (old), [ptr] "+QS" (*(u64 *)ptr)
: [new] "d" (new)
: "memory", "cc");
@@ -126,7 +126,7 @@ static __always_inline u64 __arch_cmpxchg(u64 ptr, u64 old, u64 new, int size)
} \
case 4: { \
asm volatile( \
" cs %[__old],%[__new],%[__ptr]\n" \
" cs %[__old],%[__new],%[__ptr]" \
: [__old] "+d" (*__oldp), \
[__ptr] "+Q" (*(ptr)), \
"=@cc" (__cc) \
@@ -136,7 +136,7 @@ static __always_inline u64 __arch_cmpxchg(u64 ptr, u64 old, u64 new, int size)
} \
case 8: { \
asm volatile( \
" csg %[__old],%[__new],%[__ptr]\n" \
" csg %[__old],%[__new],%[__ptr]" \
: [__old] "+d" (*__oldp), \
[__ptr] "+QS" (*(ptr)), \
"=@cc" (__cc) \
@@ -241,7 +241,7 @@ static __always_inline u64 __arch_xchg(u64 ptr, u64 x, int size)
static __always_inline u128 arch_cmpxchg128(volatile u128 *ptr, u128 old, u128 new)
{
asm volatile(
" cdsg %[old],%[new],%[ptr]\n"
" cdsg %[old],%[new],%[ptr]"
: [old] "+d" (old), [ptr] "+QS" (*ptr)
: [new] "d" (new)
: "memory", "cc");
@@ -258,7 +258,7 @@ static __always_inline bool arch_try_cmpxchg128(volatile u128 *ptr, u128 *oldp,
int cc;
asm volatile(
" cdsg %[old],%[new],%[ptr]\n"
" cdsg %[old],%[new],%[ptr]"
: [old] "+d" (*oldp), [ptr] "+QS" (*ptr), "=@cc" (cc)
: [new] "d" (new)
: "memory");
+12 -12
View File
@@ -229,7 +229,7 @@ static __always_inline void __cpacf_query_rre(u32 opc, u8 r1, u8 r2,
asm volatile(
" la %%r1,%[pb]\n"
" lghi %%r0,%[fc]\n"
" .insn rre,%[opc] << 16,%[r1],%[r2]\n"
" .insn rre,%[opc] << 16,%[r1],%[r2]"
: [pb] "=R" (*pb)
: [opc] "i" (opc), [fc] "i" (fc),
[r1] "i" (r1), [r2] "i" (r2)
@@ -242,7 +242,7 @@ static __always_inline void __cpacf_query_rrf(u32 opc, u8 r1, u8 r2, u8 r3,
asm volatile(
" la %%r1,%[pb]\n"
" lghi %%r0,%[fc]\n"
" .insn rrf,%[opc] << 16,%[r1],%[r2],%[r3],%[m4]\n"
" .insn rrf,%[opc] << 16,%[r1],%[r2],%[r3],%[m4]"
: [pb] "=R" (*pb)
: [opc] "i" (opc), [fc] "i" (fc), [r1] "i" (r1),
[r2] "i" (r2), [r3] "i" (r3), [m4] "i" (m4)
@@ -416,7 +416,7 @@ static inline int cpacf_km(unsigned long func, void *param,
" lgr 0,%[fc]\n"
" lgr 1,%[pba]\n"
"0: .insn rre,%[opc] << 16,%[dst],%[src]\n"
" brc 1,0b\n" /* handle partial completion */
" brc 1,0b" /* handle partial completion */
: [src] "+&d" (s.pair), [dst] "+&d" (d.pair)
: [fc] "d" (func), [pba] "d" ((unsigned long)param),
[opc] "i" (CPACF_KM)
@@ -448,7 +448,7 @@ static inline int cpacf_kmc(unsigned long func, void *param,
" lgr 0,%[fc]\n"
" lgr 1,%[pba]\n"
"0: .insn rre,%[opc] << 16,%[dst],%[src]\n"
" brc 1,0b\n" /* handle partial completion */
" brc 1,0b" /* handle partial completion */
: [src] "+&d" (s.pair), [dst] "+&d" (d.pair)
: [fc] "d" (func), [pba] "d" ((unsigned long)param),
[opc] "i" (CPACF_KMC)
@@ -476,7 +476,7 @@ static inline void cpacf_kimd(unsigned long func, void *param,
" lgr 0,%[fc]\n"
" lgr 1,%[pba]\n"
"0: .insn rrf,%[opc] << 16,0,%[src],8,0\n"
" brc 1,0b\n" /* handle partial completion */
" brc 1,0b" /* handle partial completion */
: [src] "+&d" (s.pair)
: [fc] "d" (func), [pba] "d" ((unsigned long)(param)),
[opc] "i" (CPACF_KIMD)
@@ -501,7 +501,7 @@ static inline void cpacf_klmd(unsigned long func, void *param,
" lgr 0,%[fc]\n"
" lgr 1,%[pba]\n"
"0: .insn rrf,%[opc] << 16,0,%[src],8,0\n"
" brc 1,0b\n" /* handle partial completion */
" brc 1,0b" /* handle partial completion */
: [src] "+&d" (s.pair)
: [fc] "d" (func), [pba] "d" ((unsigned long)param),
[opc] "i" (CPACF_KLMD)
@@ -530,7 +530,7 @@ static inline int _cpacf_kmac(unsigned long *gr0, void *param,
" lgr 1,%[pba]\n"
"0: .insn rre,%[opc] << 16,0,%[src]\n"
" brc 1,0b\n" /* handle partial completion */
" lgr %[r0],0\n"
" lgr %[r0],0"
: [r0] "+d" (*gr0), [src] "+&d" (s.pair)
: [pba] "d" ((unsigned long)param),
[opc] "i" (CPACF_KMAC)
@@ -580,7 +580,7 @@ static inline int cpacf_kmctr(unsigned long func, void *param, u8 *dest,
" lgr 0,%[fc]\n"
" lgr 1,%[pba]\n"
"0: .insn rrf,%[opc] << 16,%[dst],%[src],%[ctr],0\n"
" brc 1,0b\n" /* handle partial completion */
" brc 1,0b" /* handle partial completion */
: [src] "+&d" (s.pair), [dst] "+&d" (d.pair),
[ctr] "+&d" (c.pair)
: [fc] "d" (func), [pba] "d" ((unsigned long)param),
@@ -614,7 +614,7 @@ static inline void cpacf_prno(unsigned long func, void *param,
" lgr 0,%[fc]\n"
" lgr 1,%[pba]\n"
"0: .insn rre,%[opc] << 16,%[dst],%[seed]\n"
" brc 1,0b\n" /* handle partial completion */
" brc 1,0b" /* handle partial completion */
: [dst] "+&d" (d.pair)
: [fc] "d" (func), [pba] "d" ((unsigned long)param),
[seed] "d" (s.pair), [opc] "i" (CPACF_PRNO)
@@ -640,7 +640,7 @@ static inline void cpacf_trng(u8 *ucbuf, unsigned long ucbuf_len,
asm volatile (
" lghi 0,%[fc]\n"
"0: .insn rre,%[opc] << 16,%[ucbuf],%[cbuf]\n"
" brc 1,0b\n" /* handle partial completion */
" brc 1,0b" /* handle partial completion */
: [ucbuf] "+&d" (u.pair), [cbuf] "+&d" (c.pair)
: [fc] "K" (CPACF_PRNO_TRNG), [opc] "i" (CPACF_PRNO)
: "cc", "memory", "0");
@@ -692,7 +692,7 @@ static inline void cpacf_pckmo(long func, void *param)
asm volatile(
" lgr 0,%[fc]\n"
" lgr 1,%[pba]\n"
" .insn rre,%[opc] << 16,0,0\n" /* PCKMO opcode */
" .insn rre,%[opc] << 16,0,0" /* PCKMO opcode */
:
: [fc] "d" (func), [pba] "d" ((unsigned long)param),
[opc] "i" (CPACF_PCKMO)
@@ -725,7 +725,7 @@ static inline void cpacf_kma(unsigned long func, void *param, u8 *dest,
" lgr 0,%[fc]\n"
" lgr 1,%[pba]\n"
"0: .insn rrf,%[opc] << 16,%[dst],%[src],%[aad],0\n"
" brc 1,0b\n" /* handle partial completion */
" brc 1,0b" /* handle partial completion */
: [dst] "+&d" (d.pair), [src] "+&d" (s.pair),
[aad] "+&d" (a.pair)
: [fc] "d" (func), [pba] "d" ((unsigned long)param),
+4 -4
View File
@@ -100,7 +100,7 @@ struct ctlreg {
BUILD_BUG_ON(sizeof(struct addrtype) != _esize); \
typecheck(struct ctlreg, array[0]); \
asm volatile( \
" lctlg %[_low],%[_high],%[_arr]\n" \
" lctlg %[_low],%[_high],%[_arr]" \
: \
: [_arr] "Q" (*(struct addrtype *)(&array)), \
[_low] "i" (low), [_high] "i" (high) \
@@ -119,7 +119,7 @@ struct ctlreg {
BUILD_BUG_ON(sizeof(struct addrtype) != _esize); \
typecheck(struct ctlreg, array[0]); \
asm volatile( \
" stctg %[_low],%[_high],%[_arr]\n" \
" stctg %[_low],%[_high],%[_arr]" \
: [_arr] "=Q" (*(struct addrtype *)(&array)) \
: [_low] "i" (low), [_high] "i" (high)); \
} while (0)
@@ -127,7 +127,7 @@ struct ctlreg {
static __always_inline void local_ctl_load(unsigned int cr, struct ctlreg *reg)
{
asm volatile(
" lctlg %[cr],%[cr],%[reg]\n"
" lctlg %[cr],%[cr],%[reg]"
:
: [reg] "Q" (*reg), [cr] "i" (cr)
: "memory");
@@ -136,7 +136,7 @@ static __always_inline void local_ctl_load(unsigned int cr, struct ctlreg *reg)
static __always_inline void local_ctl_store(unsigned int cr, struct ctlreg *reg)
{
asm volatile(
" stctg %[cr],%[cr],%[reg]\n"
" stctg %[cr],%[cr],%[reg]"
: [reg] "=Q" (*reg)
: [cr] "i" (cr));
}
+18 -18
View File
@@ -38,7 +38,7 @@ asm(".include \"asm/fpu-insn-asm.h\"\n");
static __always_inline void fpu_cefbr(u8 f1, s32 val)
{
asm volatile("cefbr %[f1],%[val]\n"
asm volatile("cefbr %[f1],%[val]"
:
: [f1] "I" (f1), [val] "d" (val)
: "memory");
@@ -48,7 +48,7 @@ static __always_inline unsigned long fpu_cgebr(u8 f2, u8 mode)
{
unsigned long val;
asm volatile("cgebr %[val],%[mode],%[f2]\n"
asm volatile("cgebr %[val],%[mode],%[f2]"
: [val] "=d" (val)
: [f2] "I" (f2), [mode] "I" (mode)
: "memory");
@@ -57,7 +57,7 @@ static __always_inline unsigned long fpu_cgebr(u8 f2, u8 mode)
static __always_inline void fpu_debr(u8 f1, u8 f2)
{
asm volatile("debr %[f1],%[f2]\n"
asm volatile("debr %[f1],%[f2]"
:
: [f1] "I" (f1), [f2] "I" (f2)
: "memory");
@@ -66,7 +66,7 @@ static __always_inline void fpu_debr(u8 f1, u8 f2)
static __always_inline void fpu_ld(unsigned short fpr, freg_t *reg)
{
instrument_read(reg, sizeof(*reg));
asm volatile("ld %[fpr],%[reg]\n"
asm volatile("ld %[fpr],%[reg]"
:
: [fpr] "I" (fpr), [reg] "Q" (reg->ui)
: "memory");
@@ -74,7 +74,7 @@ static __always_inline void fpu_ld(unsigned short fpr, freg_t *reg)
static __always_inline void fpu_ldgr(u8 f1, u32 val)
{
asm volatile("ldgr %[f1],%[val]\n"
asm volatile("ldgr %[f1],%[val]"
:
: [f1] "I" (f1), [val] "d" (val)
: "memory");
@@ -113,7 +113,7 @@ static inline void fpu_lfpc_safe(unsigned int *fpc)
static __always_inline void fpu_std(unsigned short fpr, freg_t *reg)
{
instrument_write(reg, sizeof(*reg));
asm volatile("std %[fpr],%[reg]\n"
asm volatile("std %[fpr],%[reg]"
: [reg] "=Q" (reg->ui)
: [fpr] "I" (fpr)
: "memory");
@@ -181,7 +181,7 @@ static __always_inline void fpu_vgfmg(u8 v1, u8 v2, u8 v3)
static __always_inline void fpu_vl(u8 v1, const void *vxr)
{
instrument_read(vxr, sizeof(__vector128));
asm volatile("VL %[v1],%O[vxr],,%R[vxr]\n"
asm volatile("VL %[v1],%O[vxr],,%R[vxr]"
:
: [vxr] "Q" (*(__vector128 *)vxr),
[v1] "I" (v1)
@@ -195,7 +195,7 @@ static __always_inline void fpu_vl(u8 v1, const void *vxr)
instrument_read(vxr, sizeof(__vector128));
asm volatile(
" la 1,%[vxr]\n"
" VL %[v1],0,,1\n"
" VL %[v1],0,,1"
:
: [vxr] "R" (*(__vector128 *)vxr),
[v1] "I" (v1)
@@ -239,7 +239,7 @@ static __always_inline void fpu_vll(u8 v1, u32 index, const void *vxr)
size = min(index + 1, sizeof(__vector128));
instrument_read(vxr, size);
asm volatile("VLL %[v1],%[index],%O[vxr],%R[vxr]\n"
asm volatile("VLL %[v1],%[index],%O[vxr],%R[vxr]"
:
: [vxr] "Q" (*(u8 *)vxr),
[index] "d" (index),
@@ -257,7 +257,7 @@ static __always_inline void fpu_vll(u8 v1, u32 index, const void *vxr)
instrument_read(vxr, size);
asm volatile(
" la 1,%[vxr]\n"
" VLL %[v1],%[index],0,1\n"
" VLL %[v1],%[index],0,1"
:
: [vxr] "R" (*(u8 *)vxr),
[index] "d" (index),
@@ -277,7 +277,7 @@ static __always_inline void fpu_vll(u8 v1, u32 index, const void *vxr)
} *_v = (void *)(_vxrs); \
\
instrument_read(_v, size); \
asm volatile("VLM %[v1],%[v3],%O[vxrs],%R[vxrs]\n" \
asm volatile("VLM %[v1],%[v3],%O[vxrs],%R[vxrs]" \
: \
: [vxrs] "Q" (*_v), \
[v1] "I" (_v1), [v3] "I" (_v3) \
@@ -297,7 +297,7 @@ static __always_inline void fpu_vll(u8 v1, u32 index, const void *vxr)
instrument_read(_v, size); \
asm volatile( \
" la 1,%[vxrs]\n" \
" VLM %[v1],%[v3],0,1\n" \
" VLM %[v1],%[v3],0,1" \
: \
: [vxrs] "R" (*_v), \
[v1] "I" (_v1), [v3] "I" (_v3) \
@@ -360,7 +360,7 @@ static __always_inline void fpu_vsrlb(u8 v1, u8 v2, u8 v3)
static __always_inline void fpu_vst(u8 v1, const void *vxr)
{
instrument_write(vxr, sizeof(__vector128));
asm volatile("VST %[v1],%O[vxr],,%R[vxr]\n"
asm volatile("VST %[v1],%O[vxr],,%R[vxr]"
: [vxr] "=Q" (*(__vector128 *)vxr)
: [v1] "I" (v1)
: "memory");
@@ -373,7 +373,7 @@ static __always_inline void fpu_vst(u8 v1, const void *vxr)
instrument_write(vxr, sizeof(__vector128));
asm volatile(
" la 1,%[vxr]\n"
" VST %[v1],0,,1\n"
" VST %[v1],0,,1"
: [vxr] "=R" (*(__vector128 *)vxr)
: [v1] "I" (v1)
: "memory", "1");
@@ -389,7 +389,7 @@ static __always_inline void fpu_vstl(u8 v1, u32 index, const void *vxr)
size = min(index + 1, sizeof(__vector128));
instrument_write(vxr, size);
asm volatile("VSTL %[v1],%[index],%O[vxr],%R[vxr]\n"
asm volatile("VSTL %[v1],%[index],%O[vxr],%R[vxr]"
: [vxr] "=Q" (*(u8 *)vxr)
: [index] "d" (index), [v1] "I" (v1)
: "memory");
@@ -405,7 +405,7 @@ static __always_inline void fpu_vstl(u8 v1, u32 index, const void *vxr)
instrument_write(vxr, size);
asm volatile(
" la 1,%[vxr]\n"
" VSTL %[v1],%[index],0,1\n"
" VSTL %[v1],%[index],0,1"
: [vxr] "=R" (*(u8 *)vxr)
: [index] "d" (index), [v1] "I" (v1)
: "memory", "1");
@@ -423,7 +423,7 @@ static __always_inline void fpu_vstl(u8 v1, u32 index, const void *vxr)
} *_v = (void *)(_vxrs); \
\
instrument_write(_v, size); \
asm volatile("VSTM %[v1],%[v3],%O[vxrs],%R[vxrs]\n" \
asm volatile("VSTM %[v1],%[v3],%O[vxrs],%R[vxrs]" \
: [vxrs] "=Q" (*_v) \
: [v1] "I" (_v1), [v3] "I" (_v3) \
: "memory"); \
@@ -442,7 +442,7 @@ static __always_inline void fpu_vstl(u8 v1, u32 index, const void *vxr)
instrument_write(_v, size); \
asm volatile( \
" la 1,%[vxrs]\n" \
" VSTM %[v1],%[v3],0,1\n" \
" VSTM %[v1],%[v3],0,1" \
: [vxrs] "=R" (*_v) \
: [v1] "I" (_v1), [v3] "I" (_v3) \
: "memory", "1"); \
+1 -1
View File
@@ -76,7 +76,7 @@ long __kvm_hypercall##args(unsigned long nr HYPERCALL_PARM_##args) \
HYPERCALL_REGS_##args; \
\
asm volatile ( \
" diag 2,4,0x500\n" \
" diag 2,4,0x500" \
: "=d" (__rc) \
: "d" (__nr) HYPERCALL_FMT_##args \
: "memory", "cc"); \
+10
View File
@@ -246,6 +246,16 @@ int clp_refresh_fh(u32 fid, u32 *fh);
/* UID */
void update_uid_checking(bool new);
/* Firmware Sysfs */
int __init __zpci_fw_sysfs_init(void);
static inline int __init zpci_fw_sysfs_init(void)
{
if (IS_ENABLED(CONFIG_SYSFS))
return __zpci_fw_sysfs_init();
return 0;
}
/* IOMMU Interface */
int zpci_init_iommu(struct zpci_dev *zdev);
void zpci_destroy_iommu(struct zpci_dev *zdev);
+4 -4
View File
@@ -73,13 +73,13 @@
if (__builtin_constant_p(val__) && \
((szcast)val__ > -129) && ((szcast)val__ < 128)) { \
asm volatile( \
op2 " %[ptr__],%[val__]\n" \
op2 " %[ptr__],%[val__]" \
: [ptr__] "+Q" (*ptr__) \
: [val__] "i" ((szcast)val__) \
: "cc"); \
} else { \
asm volatile( \
op1 " %[old__],%[val__],%[ptr__]\n" \
op1 " %[old__],%[val__],%[ptr__]" \
: [old__] "=d" (old__), [ptr__] "+Q" (*ptr__) \
: [val__] "d" (val__) \
: "cc"); \
@@ -98,7 +98,7 @@
preempt_disable_notrace(); \
ptr__ = raw_cpu_ptr(&(pcp)); \
asm volatile( \
op " %[old__],%[val__],%[ptr__]\n" \
op " %[old__],%[val__],%[ptr__]" \
: [old__] "=d" (old__), [ptr__] "+Q" (*ptr__) \
: [val__] "d" (val__) \
: "cc"); \
@@ -117,7 +117,7 @@
preempt_disable_notrace(); \
ptr__ = raw_cpu_ptr(&(pcp)); \
asm volatile( \
op " %[old__],%[val__],%[ptr__]\n" \
op " %[old__],%[val__],%[ptr__]" \
: [old__] "=d" (old__), [ptr__] "+Q" (*ptr__) \
: [val__] "d" (val__) \
: "cc"); \
+1 -1
View File
@@ -163,7 +163,7 @@ static __always_inline void __stackleak_poison(unsigned long erase_low,
"2: stg %[poison],0(%[addr])\n"
" j 4f\n"
"3: mvc 8(1,%[addr]),0(%[addr])\n"
"4:\n"
"4:"
: [addr] "+&a" (erase_low), [count] "+&d" (count), [tmp] "=&a" (tmp)
: [poison] "d" (poison)
: "memory", "cc"
+1 -1
View File
@@ -19,7 +19,7 @@
\
BUILD_BUG_ON(sizeof(x) != 16); \
asm volatile( \
" lpq %[val],%[_x]\n" \
" lpq %[val],%[_x]" \
: [val] "=d" (__u.val) \
: [_x] "QS" (x) \
: "memory"); \
+1 -1
View File
@@ -98,7 +98,7 @@ static inline void arch_spin_unlock(arch_spinlock_t *lp)
kcsan_release();
asm_inline volatile(
ALTERNATIVE("nop", ".insn rre,0xb2fa0000,7,0", ALT_FACILITY(49)) /* NIAI 7 */
" mvhhi %[lock],0\n"
" mvhhi %[lock],0"
: [lock] "=Q" (((unsigned short *)&lp->lock)[1])
:
: "memory");
+2 -2
View File
@@ -199,7 +199,7 @@ static __always_inline unsigned long get_stack_pointer(struct task_struct *task,
" lg 15,%[_stack]\n" \
" stg %[_frame],%[_bc](15)\n" \
" brasl 14,%[_fn]\n" \
" lgr 15,%[_prev]\n" \
" lgr 15,%[_prev]" \
: [_prev] "=&d" (prev), CALL_FMT_##nr \
: [_stack] "R" (__stack), \
[_bc] "i" (offsetof(struct stack_frame, back_chain)), \
@@ -250,7 +250,7 @@ static __always_inline unsigned long get_stack_pointer(struct task_struct *task,
" lra 14,0(1)\n" \
" lpswe %[psw_enter]\n" \
"0: lpswe 0(7)\n" \
"1:\n" \
"1:" \
: CALL_FMT_##nr, [psw_leave] "=Q" (psw_leave) \
: [psw_enter] "Q" (psw_enter) \
: "7", CALL_CLOBBER_##nr); \
+1 -1
View File
@@ -125,7 +125,7 @@ static inline void *memscan(void *s, int c, size_t n)
asm volatile(
" lgr 0,%[c]\n"
"0: srst %[ret],%[s]\n"
" jo 0b\n"
" jo 0b"
: [ret] "+&a" (ret), [s] "+&a" (s)
: [c] "d" (c)
: "cc", "memory", "0");
+1 -1
View File
@@ -155,7 +155,7 @@ long syscall##nr(unsigned long syscall SYSCALL_PARM_##nr) \
SYSCALL_REGS_##nr; \
\
asm volatile ( \
" svc 0\n" \
" svc 0" \
: "=d" (rc) \
: "d" (r1) SYSCALL_FMT_##nr \
: "memory"); \
+1 -1
View File
@@ -81,7 +81,7 @@ static inline void set_tod_programmable_field(u16 val)
{
asm volatile(
" lgr 0,%[val]\n"
" sckpf\n"
" sckpf"
:
: [val] "d" ((unsigned long)val)
: "0");
+1 -1
View File
@@ -66,7 +66,7 @@ static inline unsigned long diag310(unsigned long subcode, unsigned long size, v
union register_pair rp = { .even = (unsigned long)addr, .odd = size };
diag_stat_inc(DIAG_STAT_X310);
asm volatile("diag %[rp],%[subcode],0x310\n"
asm volatile("diag %[rp],%[subcode],0x310"
: [rp] "+d" (rp.pair)
: [subcode] "d" (subcode)
: "memory");
+1 -1
View File
@@ -101,7 +101,7 @@ static unsigned long diag324(unsigned long subcode, void *addr)
union register_pair rp = { .even = (unsigned long)addr };
diag_stat_inc(DIAG_STAT_X324);
asm volatile("diag %[rp],%[subcode],0x324\n"
asm volatile("diag %[rp],%[subcode],0x324"
: [rp] "+d" (rp.pair)
: [subcode] "d" (subcode)
: "memory");
+44 -62
View File
@@ -80,6 +80,15 @@ static int paicrypt_root_alloc(void)
/* Release the PMU if event is the last perf event */
static DEFINE_MUTEX(pai_reserve_mutex);
/* Free all memory allocated for event counting/sampling setup */
static void paicrypt_free(struct paicrypt_mapptr *mp)
{
free_page((unsigned long)mp->mapptr->page);
kvfree(mp->mapptr->save);
kfree(mp->mapptr);
mp->mapptr = NULL;
}
/* Adjust usage counters and remove allocated memory when all users are
* gone.
*/
@@ -93,15 +102,8 @@ static void paicrypt_event_destroy_cpu(struct perf_event *event, int cpu)
"refcnt %u\n", __func__, event->attr.config,
event->cpu, cpump->active_events,
refcount_read(&cpump->refcnt));
if (refcount_dec_and_test(&cpump->refcnt)) {
debug_sprintf_event(cfm_dbg, 4, "%s page %#lx save %p\n",
__func__, (unsigned long)cpump->page,
cpump->save);
free_page((unsigned long)cpump->page);
kvfree(cpump->save);
kfree(cpump);
mp->mapptr = NULL;
}
if (refcount_dec_and_test(&cpump->refcnt))
paicrypt_free(mp);
paicrypt_root_free();
mutex_unlock(&pai_reserve_mutex);
}
@@ -175,14 +177,13 @@ static u64 paicrypt_getall(struct perf_event *event)
*
* Allocate the memory for the event.
*/
static struct paicrypt_map *paicrypt_busy(struct perf_event *event, int cpu)
static int paicrypt_alloc_cpu(struct perf_event *event, int cpu)
{
struct paicrypt_map *cpump = NULL;
struct paicrypt_mapptr *mp;
int rc;
mutex_lock(&pai_reserve_mutex);
/* Allocate root node */
rc = paicrypt_root_alloc();
if (rc)
@@ -192,58 +193,44 @@ static struct paicrypt_map *paicrypt_busy(struct perf_event *event, int cpu)
mp = per_cpu_ptr(paicrypt_root.mapptr, cpu);
cpump = mp->mapptr;
if (!cpump) { /* Paicrypt_map allocated? */
rc = -ENOMEM;
cpump = kzalloc(sizeof(*cpump), GFP_KERNEL);
if (!cpump) {
rc = -ENOMEM;
goto free_root;
if (!cpump)
goto undo;
/* Allocate memory for counter page and counter extraction.
* Only the first counting event has to allocate a page.
*/
mp->mapptr = cpump;
cpump->page = (unsigned long *)get_zeroed_page(GFP_KERNEL);
cpump->save = kvmalloc_array(paicrypt_cnt + 1,
sizeof(struct pai_userdata),
GFP_KERNEL);
if (!cpump->page || !cpump->save) {
paicrypt_free(mp);
goto undo;
}
INIT_LIST_HEAD(&cpump->syswide_list);
}
/* Allocate memory for counter page and counter extraction.
* Only the first counting event has to allocate a page.
*/
if (cpump->page) {
refcount_set(&cpump->refcnt, 1);
rc = 0;
} else {
refcount_inc(&cpump->refcnt);
goto unlock;
}
rc = -ENOMEM;
cpump->page = (unsigned long *)get_zeroed_page(GFP_KERNEL);
if (!cpump->page)
goto free_paicrypt_map;
cpump->save = kvmalloc_array(paicrypt_cnt + 1,
sizeof(struct pai_userdata), GFP_KERNEL);
if (!cpump->save) {
free_page((unsigned long)cpump->page);
cpump->page = NULL;
goto free_paicrypt_map;
undo:
if (rc) {
/* Error in allocation of event, decrement anchor. Since
* the event in not created, its destroy() function is never
* invoked. Adjust the reference counter for the anchor.
*/
paicrypt_root_free();
}
/* Set mode and reference count */
rc = 0;
refcount_set(&cpump->refcnt, 1);
mp->mapptr = cpump;
debug_sprintf_event(cfm_dbg, 5, "%s users %d refcnt %u page %#lx "
"save %p rc %d\n", __func__, cpump->active_events,
refcount_read(&cpump->refcnt),
(unsigned long)cpump->page, cpump->save, rc);
goto unlock;
free_paicrypt_map:
/* Undo memory allocation */
kfree(cpump);
mp->mapptr = NULL;
free_root:
paicrypt_root_free();
unlock:
mutex_unlock(&pai_reserve_mutex);
return rc ? ERR_PTR(rc) : cpump;
return rc;
}
static int paicrypt_event_init_all(struct perf_event *event)
static int paicrypt_alloc(struct perf_event *event)
{
struct paicrypt_map *cpump;
struct cpumask *maskptr;
int cpu, rc = -ENOMEM;
@@ -252,12 +239,11 @@ static int paicrypt_event_init_all(struct perf_event *event)
goto out;
for_each_online_cpu(cpu) {
cpump = paicrypt_busy(event, cpu);
if (IS_ERR(cpump)) {
rc = paicrypt_alloc_cpu(event, cpu);
if (rc) {
for_each_cpu(cpu, maskptr)
paicrypt_event_destroy_cpu(event, cpu);
kfree(maskptr);
rc = PTR_ERR(cpump);
goto out;
}
cpumask_set_cpu(cpu, maskptr);
@@ -279,7 +265,6 @@ out:
static int paicrypt_event_init(struct perf_event *event)
{
struct perf_event_attr *a = &event->attr;
struct paicrypt_map *cpump;
int rc = 0;
/* PAI crypto PMU registered as PERF_TYPE_RAW, check event type */
@@ -301,13 +286,10 @@ static int paicrypt_event_init(struct perf_event *event)
}
}
if (event->cpu >= 0) {
cpump = paicrypt_busy(event, event->cpu);
if (IS_ERR(cpump))
rc = PTR_ERR(cpump);
} else {
rc = paicrypt_event_init_all(event);
}
if (event->cpu >= 0)
rc = paicrypt_alloc_cpu(event, event->cpu);
else
rc = paicrypt_alloc(event);
if (rc) {
free_page(PAI_SAVE_AREA(event));
goto out;
+1 -1
View File
@@ -839,7 +839,7 @@ static void __init setup_control_program_code(void)
return;
diag_stat_inc(DIAG_STAT_X318);
asm volatile("diag %0,0,0x318\n" : : "d" (diag318_info.val));
asm volatile("diag %0,0,0x318" : : "d" (diag318_info.val));
}
/*
+1 -1
View File
@@ -11,7 +11,7 @@ static inline unsigned long load_real_address(unsigned long address)
unsigned long real;
asm volatile(
" lra %[real],0(%[address])\n"
" lra %[real],0(%[address])"
: [real] "=d" (real)
: [address] "a" (address)
: "cc");
+1 -1
View File
@@ -340,7 +340,7 @@ static void pcpu_delegate(struct pcpu *pcpu, int cpu,
"0: sigp 0,%0,%2 # sigp restart to target cpu\n"
" brc 2,0b # busy, try again\n"
"1: sigp 0,%1,%3 # sigp stop to current cpu\n"
" brc 2,1b # busy, try again\n"
" brc 2,1b # busy, try again"
: : "d" (pcpu->address), "d" (source_cpu),
"K" (SIGP_RESTART), "K" (SIGP_STOP)
: "0", "1", "cc");
+2 -2
View File
@@ -866,8 +866,8 @@ static int find_secret_in_page(const u8 secret_id[UV_SECRET_ID_LEN],
return -ENOENT;
}
/*
* Do the actual search for `uv_get_secret_metadata`.
/**
* uv_find_secret() - search secret metadata for a given secret id.
* @secret_id: search pattern.
* @list: ephemeral buffer space
* @secret: output data, containing the secret's metadata.
+3 -3
View File
@@ -356,7 +356,7 @@ static __always_inline void pfcr_query(u8 (*query)[16])
{
asm volatile(
" lghi 0,0\n"
" .insn rsy,0xeb0000000016,0,0,%[query]\n"
" .insn rsy,0xeb0000000016,0,0,%[query]"
: [query] "=QS" (*query)
:
: "cc", "0");
@@ -368,7 +368,7 @@ static __always_inline void __sortl_query(u8 (*query)[32])
" lghi 0,0\n"
" la 1,%[query]\n"
/* Parameter registers are ignored */
" .insn rre,0xb9380000,2,4\n"
" .insn rre,0xb9380000,2,4"
: [query] "=R" (*query)
:
: "cc", "0", "1");
@@ -380,7 +380,7 @@ static __always_inline void __dfltcc_query(u8 (*query)[32])
" lghi 0,0\n"
" la 1,%[query]\n"
/* Parameter registers are ignored */
" .insn rrf,0xb9390000,2,4,6,0\n"
" .insn rrf,0xb9390000,2,4,6,0"
: [query] "=R" (*query)
:
: "cc", "0", "1");
+3 -3
View File
@@ -96,7 +96,7 @@ static inline int arch_load_niai4(int *lock)
asm_inline volatile(
ALTERNATIVE("nop", ".insn rre,0xb2fa0000,4,0", ALT_FACILITY(49)) /* NIAI 4 */
" l %[owner],%[lock]\n"
" l %[owner],%[lock]"
: [owner] "=d" (owner) : [lock] "R" (*lock) : "memory");
return owner;
}
@@ -109,7 +109,7 @@ static inline int arch_try_cmpxchg_niai8(int *lock, int old, int new)
asm_inline volatile(
ALTERNATIVE("nop", ".insn rre,0xb2fa0000,8,0", ALT_FACILITY(49)) /* NIAI 8 */
" cs %[old],%[new],%[lock]\n"
" cs %[old],%[new],%[lock]"
: [old] "+d" (old), [lock] "+Q" (*lock), "=@cc" (cc)
: [new] "d" (new)
: "memory");
@@ -124,7 +124,7 @@ static inline int arch_try_cmpxchg_niai8(int *lock, int old, int new)
asm_inline volatile(
ALTERNATIVE("nop", ".insn rre,0xb2fa0000,8,0", ALT_FACILITY(49)) /* NIAI 8 */
" cs %[old],%[new],%[lock]\n"
" cs %[old],%[new],%[lock]"
: [old] "+d" (old), [lock] "+Q" (*lock)
: [new] "d" (new)
: "cc", "memory");
+4 -4
View File
@@ -27,7 +27,7 @@ static inline char *__strend(const char *s)
asm volatile(
" lghi 0,0\n"
"0: srst %[e],%[s]\n"
" jo 0b\n"
" jo 0b"
: [e] "+&a" (e), [s] "+&a" (s)
:
: "cc", "memory", "0");
@@ -41,7 +41,7 @@ static inline char *__strnend(const char *s, size_t n)
asm volatile(
" lghi 0,0\n"
"0: srst %[p],%[s]\n"
" jo 0b\n"
" jo 0b"
: [p] "+&d" (p), [s] "+&a" (s)
:
: "cc", "memory", "0");
@@ -95,7 +95,7 @@ char *strcat(char *dest, const char *src)
"0: srst %[dummy],%[dest]\n"
" jo 0b\n"
"1: mvst %[dummy],%[src]\n"
" jo 1b\n"
" jo 1b"
: [dummy] "+&a" (dummy), [dest] "+&a" (dest), [src] "+&a" (src)
:
: "cc", "memory", "0");
@@ -291,7 +291,7 @@ void *memscan(void *s, int c, size_t n)
asm volatile(
" lgr 0,%[c]\n"
"0: srst %[ret],%[s]\n"
" jo 0b\n"
" jo 0b"
: [ret] "+&a" (ret), [s] "+&a" (s)
: [c] "d" (c)
: "cc", "memory", "0");
+2 -2
View File
@@ -150,7 +150,7 @@ static __always_inline struct pt_regs fake_pt_regs(void)
regs.gprs[15] = current_stack_pointer;
asm volatile(
"basr %[psw_addr],0\n"
"basr %[psw_addr],0"
: [psw_addr] "=d" (regs.psw.addr));
return regs;
}
@@ -232,7 +232,7 @@ static noinline void test_unwind_kprobed_func(void)
asm volatile(
" nopr %%r7\n"
"test_unwind_kprobed_insn:\n"
" nopr %%r7\n"
" nopr %%r7"
:);
}
+4 -4
View File
@@ -27,7 +27,7 @@ static void xor_xc_2(unsigned long bytes, unsigned long * __restrict p1,
"1: exrl %0,2f\n"
" j 3f\n"
"2: xc 0(1,%1),0(%2)\n"
"3:\n"
"3:"
: : "d" (bytes), "a" (p1), "a" (p2)
: "0", "cc", "memory");
}
@@ -53,7 +53,7 @@ static void xor_xc_3(unsigned long bytes, unsigned long * __restrict p1,
" j 4f\n"
"2: xc 0(1,%1),0(%2)\n"
"3: xc 0(1,%1),0(%3)\n"
"4:\n"
"4:"
: "+d" (bytes), "+a" (p1), "+a" (p2), "+a" (p3)
: : "0", "cc", "memory");
}
@@ -84,7 +84,7 @@ static void xor_xc_4(unsigned long bytes, unsigned long * __restrict p1,
"2: xc 0(1,%1),0(%2)\n"
"3: xc 0(1,%1),0(%3)\n"
"4: xc 0(1,%1),0(%4)\n"
"5:\n"
"5:"
: "+d" (bytes), "+a" (p1), "+a" (p2), "+a" (p3), "+a" (p4)
: : "0", "cc", "memory");
}
@@ -121,7 +121,7 @@ static void xor_xc_5(unsigned long bytes, unsigned long * __restrict p1,
"3: xc 0(1,%1),0(%3)\n"
"4: xc 0(1,%1),0(%4)\n"
"5: xc 0(1,%1),0(%5)\n"
"6:\n"
"6:"
: "+d" (bytes), "+a" (p1), "+a" (p2), "+a" (p3), "+a" (p4),
"+a" (p5)
: : "0", "cc", "memory");
+1 -1
View File
@@ -41,7 +41,7 @@ static notrace long s390_kernel_write_odd(void *dst, const void *src, size_t siz
" ex %1,0(1)\n"
" lg %1,0(%3)\n"
" lra %0,0(%0)\n"
" sturg %1,%0\n"
" sturg %1,%0"
: "+&a" (aligned), "+&a" (count), "=m" (tmp)
: "a" (&tmp), "a" (&tmp[offset]), "a" (src)
: "cc", "memory", "1");
+1 -1
View File
@@ -245,7 +245,7 @@ static inline unsigned long base_lra(unsigned long address)
unsigned long real;
asm volatile(
" lra %0,0(%1)\n"
" lra %0,0(%1)"
: "=d" (real) : "a" (address) : "cc");
return real;
}
+4
View File
@@ -1188,6 +1188,10 @@ static int __init pci_base_init(void)
if (rc)
goto out_find;
rc = zpci_fw_sysfs_init();
if (rc)
goto out_find;
s390_pci_initialized = 1;
return 0;
+2 -2
View File
@@ -145,7 +145,7 @@ int zpci_set_irq_ctrl(u16 ctl, u8 isc, union zpci_sic_iib *iib)
return -EIO;
asm volatile(
".insn rsy,0xeb00000000d1,%[ctl],%[isc],%[iib]\n"
".insn rsy,0xeb00000000d1,%[ctl],%[isc],%[iib]"
: : [ctl] "d" (ctl), [isc] "d" (isc << 27), [iib] "Q" (*iib));
return 0;
@@ -442,7 +442,7 @@ EXPORT_SYMBOL_GPL(zpci_write_block);
static inline void __pciwb_mio(void)
{
asm volatile (".insn rre,0xb9d50000,0,0\n");
asm volatile (".insn rre,0xb9d50000,0,0");
}
void zpci_barrier(void)
+25
View File
@@ -41,6 +41,9 @@ zpci_attr(segment1, "0x%02x\n", pfip[1]);
zpci_attr(segment2, "0x%02x\n", pfip[2]);
zpci_attr(segment3, "0x%02x\n", pfip[3]);
#define ZPCI_FW_ATTR_RO(_name) \
static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
static ssize_t mio_enabled_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -164,6 +167,13 @@ static ssize_t uid_is_unique_show(struct device *dev,
}
static DEVICE_ATTR_RO(uid_is_unique);
static ssize_t uid_checking_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sysfs_emit(buf, "%d\n", zpci_unique_uid ? 1 : 0);
}
ZPCI_FW_ATTR_RO(uid_checking);
/* analogous to smbios index */
static ssize_t index_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -233,3 +243,18 @@ const struct attribute_group pfip_attr_group = {
.name = "pfip",
.attrs = pfip_attrs,
};
static struct attribute *clp_fw_attrs[] = {
&uid_checking_attr.attr,
NULL,
};
static struct attribute_group clp_fw_attr_group = {
.name = "clp",
.attrs = clp_fw_attrs,
};
int __init __zpci_fw_sysfs_init(void)
{
return sysfs_create_group(firmware_kobj, &clp_fw_attr_group);
}
+1 -1
View File
@@ -8,9 +8,9 @@
/* #define DEBUG */
#include <linux/export.h>
#include <linux/input.h>
#include <linux/limits.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/overflow.h>
#include <linux/sched.h>
+1
View File
@@ -10,6 +10,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/module.h>
+1
View File
@@ -9,6 +9,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/export.h>
#include <linux/stddef.h>
#include <linux/module.h>
#include <linux/io.h>
+30
View File
@@ -6,6 +6,7 @@
*/
#include <linux/export.h>
#include <linux/sprintf.h>
#include <linux/uaccess.h>
#include "input-compat.h"
@@ -94,6 +95,28 @@ int input_ff_effect_from_user(const char __user *buffer, size_t size,
return 0;
}
int input_bits_to_string(char *buf, int buf_size, unsigned long bits,
bool skip_empty)
{
int len = 0;
if (in_compat_syscall()) {
u32 dword = bits >> 32;
if (dword || !skip_empty)
len += snprintf(buf, buf_size, "%x ", dword);
dword = bits & 0xffffffffUL;
if (dword || !skip_empty || len)
len += snprintf(buf + len, max(buf_size - len, 0),
"%x", dword);
} else {
if (bits || !skip_empty)
len += snprintf(buf, buf_size, "%lx", bits);
}
return len;
}
#else
int input_event_from_user(const char __user *buffer,
@@ -126,6 +149,13 @@ int input_ff_effect_from_user(const char __user *buffer, size_t size,
return 0;
}
int input_bits_to_string(char *buf, int buf_size, unsigned long bits,
bool skip_empty)
{
return bits || !skip_empty ?
snprintf(buf, buf_size, "%lx", bits) : 0;
}
#endif /* CONFIG_COMPAT */
EXPORT_SYMBOL_GPL(input_event_from_user);
+3
View File
@@ -75,4 +75,7 @@ int input_event_to_user(char __user *buffer,
int input_ff_effect_from_user(const char __user *buffer, size_t size,
struct ff_effect *effect);
int input_bits_to_string(char *buf, int buf_size, unsigned long bits,
bool skip_empty);
#endif /* _INPUT_COMPAT_H */
+1
View File
@@ -4,6 +4,7 @@
*/
#include <linux/device.h>
#include <linux/export.h>
#include <linux/input.h>
#include <linux/jiffies.h>
#include <linux/mutex.h>
+1 -35
View File
@@ -8,6 +8,7 @@
#define pr_fmt(fmt) KBUILD_BASENAME ": " fmt
#include <linux/export.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/idr.h>
@@ -998,41 +999,6 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han
return error;
}
#ifdef CONFIG_COMPAT
static int input_bits_to_string(char *buf, int buf_size,
unsigned long bits, bool skip_empty)
{
int len = 0;
if (in_compat_syscall()) {
u32 dword = bits >> 32;
if (dword || !skip_empty)
len += snprintf(buf, buf_size, "%x ", dword);
dword = bits & 0xffffffffUL;
if (dword || !skip_empty || len)
len += snprintf(buf + len, max(buf_size - len, 0),
"%x", dword);
} else {
if (bits || !skip_empty)
len += snprintf(buf, buf_size, "%lx", bits);
}
return len;
}
#else /* !CONFIG_COMPAT */
static int input_bits_to_string(char *buf, int buf_size,
unsigned long bits, bool skip_empty)
{
return bits || !skip_empty ?
snprintf(buf, buf_size, "%lx", bits) : 0;
}
#endif
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *proc_bus_input_dir;
@@ -6,6 +6,7 @@
* USB/RS232 I-Force joysticks and wheels.
*/
#include <linux/export.h>
#include <linux/unaligned.h>
#include "iforce.h"
@@ -6,6 +6,7 @@
* USB/RS232 I-Force joysticks and wheels.
*/
#include <linux/export.h>
#include <linux/unaligned.h>
#include "iforce.h"
+5 -1
View File
@@ -344,7 +344,11 @@ static int psxpad_spi_probe(struct spi_device *spi)
/* (PlayStation 1/2 joypad might be possible works 250kHz/500kHz) */
spi->controller->min_speed_hz = 125000;
spi->controller->max_speed_hz = 125000;
spi_setup(spi);
err = spi_setup(spi);
if (err) {
dev_err(&spi->dev, "failed to set up SPI: %d\n", err);
return err;
}
/* pad settings */
psxpad_set_motor_level(pad, 0, 0);
-18
View File
@@ -262,24 +262,6 @@ config KEYBOARD_GPIO_POLLED
To compile this driver as a module, choose M here: the
module will be called gpio_keys_polled.
config KEYBOARD_TCA6416
tristate "TCA6416/TCA6408A Keypad Support"
depends on I2C
help
This driver implements basic keypad functionality
for keys connected through TCA6416/TCA6408A IO expanders.
Say Y here if your device has keys connected to
TCA6416/TCA6408A IO expander. Your board-specific setup logic
must also provide pin-mask details(of which TCA6416 pins
are used for keypad).
If enabled the entire TCA6416 device will be managed through
this driver.
To compile this driver as a module, choose M here: the
module will be called tca6416_keypad.
config KEYBOARD_TCA8418
tristate "TCA8418 Keypad Support"
depends on I2C
-1
View File
@@ -23,7 +23,6 @@ obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o
obj-$(CONFIG_KEYBOARD_GOLDFISH_EVENTS) += goldfish_events.o
obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
obj-$(CONFIG_KEYBOARD_GPIO_POLLED) += gpio_keys_polled.o
obj-$(CONFIG_KEYBOARD_TCA6416) += tca6416-keypad.o
obj-$(CONFIG_KEYBOARD_TCA8418) += tca8418_keypad.o
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
+192 -318
View File
@@ -12,7 +12,8 @@
* on some suggestions by Nicolas Pitre <nico@fluxnic.net>.
*/
#include <linux/bits.h>
#include <linux/bitfield.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
@@ -20,124 +21,148 @@
#include <linux/io.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/input/matrix_keypad.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/platform_data/keypad-pxa27x.h>
/*
* Keypad Controller registers
*/
#define KPC 0x0000 /* Keypad Control register */
#define KPDK 0x0008 /* Keypad Direct Key register */
#define KPREC 0x0010 /* Keypad Rotary Encoder register */
#define KPMK 0x0018 /* Keypad Matrix Key register */
#define KPAS 0x0020 /* Keypad Automatic Scan register */
#define KPC 0x0000 /* Keypad Control register */
#define KPDK 0x0008 /* Keypad Direct Key register */
#define KPREC 0x0010 /* Keypad Rotary Encoder register */
#define KPMK 0x0018 /* Keypad Matrix Key register */
#define KPAS 0x0020 /* Keypad Automatic Scan register */
/* Keypad Automatic Scan Multiple Key Presser register 0-3 */
#define KPASMKP0 0x0028
#define KPASMKP1 0x0030
#define KPASMKP2 0x0038
#define KPASMKP3 0x0040
#define KPKDI 0x0048
#define KPASMKP0 0x0028
#define KPASMKP1 0x0030
#define KPASMKP2 0x0038
#define KPASMKP3 0x0040
#define KPKDI 0x0048
/* bit definitions */
#define KPC_MKRN(n) ((((n) - 1) & 0x7) << 26) /* matrix key row number */
#define KPC_MKCN(n) ((((n) - 1) & 0x7) << 23) /* matrix key column number */
#define KPC_DKN(n) ((((n) - 1) & 0x7) << 6) /* direct key number */
#define KPC_MKRN_MASK GENMASK(28, 26)
#define KPC_MKCN_MASK GENMASK(25, 23)
#define KPC_DKN_MASK GENMASK(8, 6)
#define KPC_MKRN(n) FIELD_PREP(KPC_MKRN_MASK, (n) - 1)
#define KPC_MKCN(n) FIELD_PREP(KPC_MKCN_MASK, (n) - 1)
#define KPC_DKN(n) FIELD_PREP(KPC_DKN_MASK, (n) - 1)
#define KPC_AS (0x1 << 30) /* Automatic Scan bit */
#define KPC_ASACT (0x1 << 29) /* Automatic Scan on Activity */
#define KPC_MI (0x1 << 22) /* Matrix interrupt bit */
#define KPC_IMKP (0x1 << 21) /* Ignore Multiple Key Press */
#define KPC_AS BIT(30) /* Automatic Scan bit */
#define KPC_ASACT BIT(29) /* Automatic Scan on Activity */
#define KPC_MI BIT(22) /* Matrix interrupt bit */
#define KPC_IMKP BIT(21) /* Ignore Multiple Key Press */
#define KPC_MS(n) (0x1 << (13 + (n))) /* Matrix scan line 'n' */
#define KPC_MS_ALL (0xff << 13)
#define KPC_MS(n) BIT(13 + (n)) /* Matrix scan line 'n' */
#define KPC_MS_ALL GENMASK(20, 13)
#define KPC_ME (0x1 << 12) /* Matrix Keypad Enable */
#define KPC_MIE (0x1 << 11) /* Matrix Interrupt Enable */
#define KPC_DK_DEB_SEL (0x1 << 9) /* Direct Keypad Debounce Select */
#define KPC_DI (0x1 << 5) /* Direct key interrupt bit */
#define KPC_RE_ZERO_DEB (0x1 << 4) /* Rotary Encoder Zero Debounce */
#define KPC_REE1 (0x1 << 3) /* Rotary Encoder1 Enable */
#define KPC_REE0 (0x1 << 2) /* Rotary Encoder0 Enable */
#define KPC_DE (0x1 << 1) /* Direct Keypad Enable */
#define KPC_DIE (0x1 << 0) /* Direct Keypad interrupt Enable */
#define KPC_ME BIT(12) /* Matrix Keypad Enable */
#define KPC_MIE BIT(11) /* Matrix Interrupt Enable */
#define KPC_DK_DEB_SEL BIT(9) /* Direct Keypad Debounce Select */
#define KPC_DI BIT(5) /* Direct key interrupt bit */
#define KPC_RE_ZERO_DEB BIT(4) /* Rotary Encoder Zero Debounce */
#define KPC_REE1 BIT(3) /* Rotary Encoder1 Enable */
#define KPC_REE0 BIT(2) /* Rotary Encoder0 Enable */
#define KPC_DE BIT(1) /* Direct Keypad Enable */
#define KPC_DIE BIT(0) /* Direct Keypad interrupt Enable */
#define KPDK_DKP (0x1 << 31)
#define KPDK_DK(n) ((n) & 0xff)
#define KPDK_DKP BIT(31)
#define KPDK_DK_MASK GENMASK(7, 0)
#define KPDK_DK(n) FIELD_GET(KPDK_DK_MASK, n)
#define KPREC_OF1 (0x1 << 31)
#define kPREC_UF1 (0x1 << 30)
#define KPREC_OF0 (0x1 << 15)
#define KPREC_UF0 (0x1 << 14)
#define KPREC_OF1 BIT(31)
#define KPREC_UF1 BIT(30)
#define KPREC_OF0 BIT(15)
#define KPREC_UF0 BIT(14)
#define KPREC_RECOUNT0(n) ((n) & 0xff)
#define KPREC_RECOUNT1(n) (((n) >> 16) & 0xff)
#define KPREC_RECOUNT0_MASK GENMASK(7, 0)
#define KPREC_RECOUNT1_MASK GENMASK(23, 16)
#define KPREC_RECOUNT0(n) FIELD_GET(KPREC_RECOUNT0_MASK, n)
#define KPREC_RECOUNT1(n) FIELD_GET(KPREC_RECOUNT1_MASK, n)
#define KPMK_MKP (0x1 << 31)
#define KPAS_SO (0x1 << 31)
#define KPASMKPx_SO (0x1 << 31)
#define KPMK_MKP BIT(31)
#define KPAS_SO BIT(31)
#define KPASMKPx_SO BIT(31)
#define KPAS_MUKP(n) (((n) >> 26) & 0x1f)
#define KPAS_RP(n) (((n) >> 4) & 0xf)
#define KPAS_CP(n) ((n) & 0xf)
#define KPAS_MUKP_MASK GENMASK(30, 26)
#define KPAS_RP_MASK GENMASK(7, 4)
#define KPAS_CP_MASK GENMASK(3, 0)
#define KPAS_MUKP(n) FIELD_GET(KPAS_MUKP_MASK, n)
#define KPAS_RP(n) FIELD_GET(KPAS_RP_MASK, n)
#define KPAS_CP(n) FIELD_GET(KPAS_CP_MASK, n)
#define KPASMKP_MKC_MASK (0xff)
#define KPASMKP_MKC_MASK GENMASK(7, 0)
#define keypad_readl(off) __raw_readl(keypad->mmio_base + (off))
#define keypad_writel(off, v) __raw_writel((v), keypad->mmio_base + (off))
#define MAX_MATRIX_KEY_ROWS 8
#define MAX_MATRIX_KEY_COLS 8
#define MAX_DIRECT_KEY_NUM 8
#define MAX_ROTARY_ENCODERS 2
#define MAX_MATRIX_KEY_NUM (MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS)
#define MAX_KEYPAD_KEYS (MAX_MATRIX_KEY_NUM + MAX_DIRECT_KEY_NUM)
struct pxa27x_keypad {
const struct pxa27x_keypad_platform_data *pdata;
struct pxa27x_keypad_rotary {
unsigned short *key_codes;
int rel_code;
bool enabled;
};
struct pxa27x_keypad {
struct clk *clk;
struct input_dev *input_dev;
void __iomem *mmio_base;
int irq;
unsigned short keycodes[MAX_KEYPAD_KEYS];
int rotary_rel_code[2];
unsigned int matrix_key_rows;
unsigned int matrix_key_cols;
unsigned int row_shift;
/* state row bits of each column scan */
uint32_t matrix_key_state[MAX_MATRIX_KEY_COLS];
uint32_t direct_key_state;
unsigned int direct_key_num;
unsigned int direct_key_mask;
bool direct_key_low_active;
/* key debounce interval */
unsigned int debounce_interval;
unsigned short keycodes[MAX_KEYPAD_KEYS];
/* state row bits of each column scan */
u32 matrix_key_state[MAX_MATRIX_KEY_COLS];
u32 direct_key_state;
struct pxa27x_keypad_rotary rotary[MAX_ROTARY_ENCODERS];
};
#ifdef CONFIG_OF
static int pxa27x_keypad_matrix_key_parse_dt(struct pxa27x_keypad *keypad,
struct pxa27x_keypad_platform_data *pdata)
static int pxa27x_keypad_matrix_key_parse(struct pxa27x_keypad *keypad)
{
struct input_dev *input_dev = keypad->input_dev;
struct device *dev = input_dev->dev.parent;
u32 rows, cols;
int error;
error = matrix_keypad_parse_properties(dev, &rows, &cols);
error = matrix_keypad_parse_properties(dev, &keypad->matrix_key_rows,
&keypad->matrix_key_cols);
if (error)
return error;
if (rows > MAX_MATRIX_KEY_ROWS || cols > MAX_MATRIX_KEY_COLS) {
if (keypad->matrix_key_rows > MAX_MATRIX_KEY_ROWS ||
keypad->matrix_key_cols > MAX_MATRIX_KEY_COLS) {
dev_err(dev, "rows or cols exceeds maximum value\n");
return -EINVAL;
}
pdata->matrix_key_rows = rows;
pdata->matrix_key_cols = cols;
keypad->row_shift = get_count_order(keypad->matrix_key_cols);
error = matrix_keypad_build_keymap(NULL, NULL,
pdata->matrix_key_rows,
pdata->matrix_key_cols,
keypad->matrix_key_rows,
keypad->matrix_key_cols,
keypad->keycodes, input_dev);
if (error)
return error;
@@ -145,20 +170,17 @@ static int pxa27x_keypad_matrix_key_parse_dt(struct pxa27x_keypad *keypad,
return 0;
}
static int pxa27x_keypad_direct_key_parse_dt(struct pxa27x_keypad *keypad,
struct pxa27x_keypad_platform_data *pdata)
static int pxa27x_keypad_direct_key_parse(struct pxa27x_keypad *keypad)
{
struct input_dev *input_dev = keypad->input_dev;
struct device *dev = input_dev->dev.parent;
struct device_node *np = dev->of_node;
const __be16 *prop;
unsigned short code;
unsigned int proplen, size;
int count;
int i;
int error;
error = of_property_read_u32(np, "marvell,direct-key-count",
&pdata->direct_key_num);
error = device_property_read_u32(dev, "marvell,direct-key-count",
&keypad->direct_key_num);
if (error) {
/*
* If do not have marvel,direct-key-count defined,
@@ -167,151 +189,121 @@ static int pxa27x_keypad_direct_key_parse_dt(struct pxa27x_keypad *keypad,
return error == -EINVAL ? 0 : error;
}
error = of_property_read_u32(np, "marvell,direct-key-mask",
&pdata->direct_key_mask);
error = device_property_read_u32(dev, "marvell,direct-key-mask",
&keypad->direct_key_mask);
if (error) {
if (error != -EINVAL)
return error;
/*
* If marvell,direct-key-mask is not defined, driver will use
* default value. Default value is set when configure the keypad.
* a default value based on number of direct keys set up.
* The default value is calculated in pxa27x_keypad_config().
*/
pdata->direct_key_mask = 0;
keypad->direct_key_mask = 0;
}
pdata->direct_key_low_active = of_property_read_bool(np,
"marvell,direct-key-low-active");
keypad->direct_key_low_active =
device_property_read_bool(dev, "marvell,direct-key-low-active");
prop = of_get_property(np, "marvell,direct-key-map", &proplen);
if (!prop)
count = device_property_count_u16(dev, "marvell,direct-key-map");
if (count <= 0 || count > MAX_DIRECT_KEY_NUM)
return -EINVAL;
if (proplen % sizeof(u16))
return -EINVAL;
error = device_property_read_u16_array(dev, "marvell,direct-key-map",
&keypad->keycodes[MAX_MATRIX_KEY_NUM],
count);
size = proplen / sizeof(u16);
/* Only MAX_DIRECT_KEY_NUM is accepted.*/
if (size > MAX_DIRECT_KEY_NUM)
return -EINVAL;
for (i = 0; i < size; i++) {
code = be16_to_cpup(prop + i);
keypad->keycodes[MAX_MATRIX_KEY_NUM + i] = code;
for (i = 0; i < count; i++) {
code = keypad->keycodes[MAX_MATRIX_KEY_NUM + i];
__set_bit(code, input_dev->keybit);
}
return 0;
}
static int pxa27x_keypad_rotary_parse_dt(struct pxa27x_keypad *keypad,
struct pxa27x_keypad_platform_data *pdata)
static int pxa27x_keypad_rotary_parse(struct pxa27x_keypad *keypad)
{
const __be32 *prop;
int i, relkey_ret;
unsigned int code, proplen;
const char *rotaryname[2] = {
"marvell,rotary0", "marvell,rotary1"};
const char relkeyname[] = {"marvell,rotary-rel-key"};
static const char * const rotaryname[] = { "marvell,rotary0", "marvell,rotary1" };
struct input_dev *input_dev = keypad->input_dev;
struct device *dev = input_dev->dev.parent;
struct device_node *np = dev->of_node;
struct pxa27x_keypad_rotary *encoder;
unsigned int code;
int i;
int error;
relkey_ret = of_property_read_u32(np, relkeyname, &code);
/* if can read correct rotary key-code, we do not need this. */
if (relkey_ret == 0) {
unsigned short relcode;
error = device_property_read_u32(dev, "marvell,rotary-rel-key", &code);
if (!error) {
for (i = 0; i < MAX_ROTARY_ENCODERS; i++, code >>= 16) {
encoder = &keypad->rotary[i];
encoder->enabled = true;
encoder->rel_code = code & 0xffff;
input_set_capability(input_dev, EV_REL, encoder->rel_code);
}
/* rotary0 taks lower half, rotary1 taks upper half. */
relcode = code & 0xffff;
pdata->rotary0_rel_code = (code & 0xffff);
__set_bit(relcode, input_dev->relbit);
relcode = code >> 16;
pdata->rotary1_rel_code = relcode;
__set_bit(relcode, input_dev->relbit);
return 0;
}
for (i = 0; i < 2; i++) {
prop = of_get_property(np, rotaryname[i], &proplen);
for (i = 0; i < MAX_ROTARY_ENCODERS; i++) {
encoder = &keypad->rotary[i];
/*
* If the prop is not set, it means keypad does not need
* initialize the rotaryX.
*/
if (!prop)
if (!device_property_present(dev, rotaryname[i]))
continue;
code = be32_to_cpup(prop);
error = device_property_read_u32(dev, rotaryname[i], &code);
if (error)
return error;
/*
* Not all up/down key code are valid.
* Now we depends on direct-rel-code.
*/
if ((!(code & 0xffff) || !(code >> 16)) && relkey_ret) {
return relkey_ret;
} else {
unsigned int n = MAX_MATRIX_KEY_NUM + (i << 1);
unsigned short keycode;
if (!(code & 0xffff) || !(code >> 16))
return -EINVAL;
keycode = code & 0xffff;
keypad->keycodes[n] = keycode;
__set_bit(keycode, input_dev->keybit);
encoder->enabled = true;
encoder->rel_code = -1;
encoder->key_codes = &keypad->keycodes[MAX_MATRIX_KEY_NUM + i * 2];
encoder->key_codes[0] = code & 0xffff;
encoder->key_codes[1] = code >> 16;
keycode = code >> 16;
keypad->keycodes[n + 1] = keycode;
__set_bit(keycode, input_dev->keybit);
if (i == 0)
pdata->rotary0_rel_code = -1;
else
pdata->rotary1_rel_code = -1;
}
if (i == 0)
pdata->enable_rotary0 = 1;
else
pdata->enable_rotary1 = 1;
input_set_capability(input_dev, EV_KEY, encoder->key_codes[0]);
input_set_capability(input_dev, EV_KEY, encoder->key_codes[1]);
}
keypad->rotary_rel_code[0] = pdata->rotary0_rel_code;
keypad->rotary_rel_code[1] = pdata->rotary1_rel_code;
return 0;
}
static int pxa27x_keypad_build_keycode_from_dt(struct pxa27x_keypad *keypad)
static int pxa27x_keypad_parse_properties(struct pxa27x_keypad *keypad)
{
struct input_dev *input_dev = keypad->input_dev;
struct device *dev = input_dev->dev.parent;
struct device_node *np = dev->of_node;
struct pxa27x_keypad_platform_data *pdata;
int error;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
dev_err(dev, "failed to allocate memory for pdata\n");
return -ENOMEM;
}
error = pxa27x_keypad_matrix_key_parse_dt(keypad, pdata);
error = pxa27x_keypad_matrix_key_parse(keypad);
if (error) {
dev_err(dev, "failed to parse matrix key\n");
return error;
}
error = pxa27x_keypad_direct_key_parse_dt(keypad, pdata);
error = pxa27x_keypad_direct_key_parse(keypad);
if (error) {
dev_err(dev, "failed to parse direct key\n");
return error;
}
error = pxa27x_keypad_rotary_parse_dt(keypad, pdata);
error = pxa27x_keypad_rotary_parse(keypad);
if (error) {
dev_err(dev, "failed to parse rotary key\n");
return error;
}
error = of_property_read_u32(np, "marvell,debounce-interval",
&pdata->debounce_interval);
error = device_property_read_u32(dev, "marvell,debounce-interval",
&keypad->debounce_interval);
if (error) {
dev_err(dev, "failed to parse debounce-interval\n");
return error;
@@ -323,95 +315,15 @@ static int pxa27x_keypad_build_keycode_from_dt(struct pxa27x_keypad *keypad)
*/
input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes);
keypad->pdata = pdata;
return 0;
}
#else
static int pxa27x_keypad_build_keycode_from_dt(struct pxa27x_keypad *keypad)
{
dev_info(keypad->input_dev->dev.parent, "missing platform data\n");
return -EINVAL;
}
#endif
static int pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
{
const struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
struct input_dev *input_dev = keypad->input_dev;
unsigned short keycode;
int i;
int error;
error = matrix_keypad_build_keymap(pdata->matrix_keymap_data, NULL,
pdata->matrix_key_rows,
pdata->matrix_key_cols,
keypad->keycodes, input_dev);
if (error)
return error;
/*
* The keycodes may not only include matrix keys but also the direct
* or rotary keys.
*/
input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes);
/* For direct keys. */
for (i = 0; i < pdata->direct_key_num; i++) {
keycode = pdata->direct_key_map[i];
keypad->keycodes[MAX_MATRIX_KEY_NUM + i] = keycode;
__set_bit(keycode, input_dev->keybit);
}
if (pdata->enable_rotary0) {
if (pdata->rotary0_up_key && pdata->rotary0_down_key) {
keycode = pdata->rotary0_up_key;
keypad->keycodes[MAX_MATRIX_KEY_NUM + 0] = keycode;
__set_bit(keycode, input_dev->keybit);
keycode = pdata->rotary0_down_key;
keypad->keycodes[MAX_MATRIX_KEY_NUM + 1] = keycode;
__set_bit(keycode, input_dev->keybit);
keypad->rotary_rel_code[0] = -1;
} else {
keypad->rotary_rel_code[0] = pdata->rotary0_rel_code;
__set_bit(pdata->rotary0_rel_code, input_dev->relbit);
}
}
if (pdata->enable_rotary1) {
if (pdata->rotary1_up_key && pdata->rotary1_down_key) {
keycode = pdata->rotary1_up_key;
keypad->keycodes[MAX_MATRIX_KEY_NUM + 2] = keycode;
__set_bit(keycode, input_dev->keybit);
keycode = pdata->rotary1_down_key;
keypad->keycodes[MAX_MATRIX_KEY_NUM + 3] = keycode;
__set_bit(keycode, input_dev->keybit);
keypad->rotary_rel_code[1] = -1;
} else {
keypad->rotary_rel_code[1] = pdata->rotary1_rel_code;
__set_bit(pdata->rotary1_rel_code, input_dev->relbit);
}
}
__clear_bit(KEY_RESERVED, input_dev->keybit);
return 0;
}
static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad)
{
const struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
struct input_dev *input_dev = keypad->input_dev;
int row, col, num_keys_pressed = 0;
uint32_t new_state[MAX_MATRIX_KEY_COLS];
uint32_t kpas = keypad_readl(KPAS);
u32 new_state[MAX_MATRIX_KEY_COLS];
u32 kpas = keypad_readl(KPAS);
num_keys_pressed = KPAS_MUKP(kpas);
@@ -425,19 +337,19 @@ static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad)
row = KPAS_RP(kpas);
/* if invalid row/col, treat as no key pressed */
if (col >= pdata->matrix_key_cols ||
row >= pdata->matrix_key_rows)
if (col >= keypad->matrix_key_cols ||
row >= keypad->matrix_key_rows)
goto scan;
new_state[col] = (1 << row);
new_state[col] = BIT(row);
goto scan;
}
if (num_keys_pressed > 1) {
uint32_t kpasmkp0 = keypad_readl(KPASMKP0);
uint32_t kpasmkp1 = keypad_readl(KPASMKP1);
uint32_t kpasmkp2 = keypad_readl(KPASMKP2);
uint32_t kpasmkp3 = keypad_readl(KPASMKP3);
u32 kpasmkp0 = keypad_readl(KPASMKP0);
u32 kpasmkp1 = keypad_readl(KPASMKP1);
u32 kpasmkp2 = keypad_readl(KPASMKP2);
u32 kpasmkp3 = keypad_readl(KPASMKP3);
new_state[0] = kpasmkp0 & KPASMKP_MKC_MASK;
new_state[1] = (kpasmkp0 >> 16) & KPASMKP_MKC_MASK;
@@ -449,23 +361,23 @@ static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad)
new_state[7] = (kpasmkp3 >> 16) & KPASMKP_MKC_MASK;
}
scan:
for (col = 0; col < pdata->matrix_key_cols; col++) {
uint32_t bits_changed;
for (col = 0; col < keypad->matrix_key_cols; col++) {
u32 bits_changed;
int code;
bits_changed = keypad->matrix_key_state[col] ^ new_state[col];
if (bits_changed == 0)
continue;
for (row = 0; row < pdata->matrix_key_rows; row++) {
if ((bits_changed & (1 << row)) == 0)
for (row = 0; row < keypad->matrix_key_rows; row++) {
if ((bits_changed & BIT(row)) == 0)
continue;
code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
input_event(input_dev, EV_MSC, MSC_SCAN, code);
input_report_key(input_dev, keypad->keycodes[code],
new_state[col] & (1 << row));
new_state[col] & BIT(row));
}
}
input_sync(input_dev);
@@ -474,7 +386,7 @@ scan:
#define DEFAULT_KPREC (0x007f007f)
static inline int rotary_delta(uint32_t kprec)
static inline int rotary_delta(u32 kprec)
{
if (kprec & KPREC_OF0)
return (kprec & 0xff) + 0x7f;
@@ -486,14 +398,16 @@ static inline int rotary_delta(uint32_t kprec)
static void report_rotary_event(struct pxa27x_keypad *keypad, int r, int delta)
{
struct pxa27x_keypad_rotary *encoder = &keypad->rotary[r];
struct input_dev *dev = keypad->input_dev;
if (delta == 0)
if (!encoder->enabled || delta == 0)
return;
if (keypad->rotary_rel_code[r] == -1) {
int code = MAX_MATRIX_KEY_NUM + 2 * r + (delta > 0 ? 0 : 1);
unsigned char keycode = keypad->keycodes[code];
if (encoder->rel_code == -1) {
int idx = delta > 0 ? 0 : 1;
int code = MAX_MATRIX_KEY_NUM + 2 * r + idx;
unsigned char keycode = encoder->key_codes[idx];
/* simulate a press-n-release */
input_event(dev, EV_MSC, MSC_SCAN, code);
@@ -503,45 +417,43 @@ static void report_rotary_event(struct pxa27x_keypad *keypad, int r, int delta)
input_report_key(dev, keycode, 0);
input_sync(dev);
} else {
input_report_rel(dev, keypad->rotary_rel_code[r], delta);
input_report_rel(dev, encoder->rel_code, delta);
input_sync(dev);
}
}
static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad)
{
const struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
uint32_t kprec;
u32 kprec;
int i;
/* read and reset to default count value */
kprec = keypad_readl(KPREC);
keypad_writel(KPREC, DEFAULT_KPREC);
if (pdata->enable_rotary0)
for (i = 0; i < MAX_ROTARY_ENCODERS; i++) {
report_rotary_event(keypad, 0, rotary_delta(kprec));
if (pdata->enable_rotary1)
report_rotary_event(keypad, 1, rotary_delta(kprec >> 16));
kprec >>= 16;
}
}
static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad)
{
const struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
struct input_dev *input_dev = keypad->input_dev;
unsigned int new_state;
uint32_t kpdk, bits_changed;
u32 kpdk, bits_changed;
int i;
kpdk = keypad_readl(KPDK);
if (pdata->enable_rotary0 || pdata->enable_rotary1)
if (keypad->rotary[0].enabled || keypad->rotary[1].enabled)
pxa27x_keypad_scan_rotary(keypad);
/*
* The KPDR_DK only output the key pin level, so it relates to board,
* and low level may be active.
*/
if (pdata->direct_key_low_active)
if (keypad->direct_key_low_active)
new_state = ~KPDK_DK(kpdk) & keypad->direct_key_mask;
else
new_state = KPDK_DK(kpdk) & keypad->direct_key_mask;
@@ -551,34 +463,24 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad)
if (bits_changed == 0)
return;
for (i = 0; i < pdata->direct_key_num; i++) {
if (bits_changed & (1 << i)) {
for (i = 0; i < keypad->direct_key_num; i++) {
if (bits_changed & BIT(i)) {
int code = MAX_MATRIX_KEY_NUM + i;
input_event(input_dev, EV_MSC, MSC_SCAN, code);
input_report_key(input_dev, keypad->keycodes[code],
new_state & (1 << i));
new_state & BIT(i));
}
}
input_sync(input_dev);
keypad->direct_key_state = new_state;
}
static void clear_wakeup_event(struct pxa27x_keypad *keypad)
{
const struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
if (pdata->clear_wakeup_event)
(pdata->clear_wakeup_event)();
}
static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id)
{
struct pxa27x_keypad *keypad = dev_id;
unsigned long kpc = keypad_readl(KPC);
clear_wakeup_event(keypad);
if (kpc & KPC_DI)
pxa27x_keypad_scan_direct(keypad);
@@ -590,7 +492,6 @@ static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id)
static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
{
const struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
unsigned int mask = 0, direct_key_num = 0;
unsigned long kpc = 0;
@@ -598,36 +499,34 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
keypad_readl(KPC);
/* enable matrix keys with automatic scan */
if (pdata->matrix_key_rows && pdata->matrix_key_cols) {
if (keypad->matrix_key_rows && keypad->matrix_key_cols) {
kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL;
kpc |= KPC_MKRN(pdata->matrix_key_rows) |
KPC_MKCN(pdata->matrix_key_cols);
kpc |= KPC_MKRN(keypad->matrix_key_rows) |
KPC_MKCN(keypad->matrix_key_cols);
}
/* enable rotary key, debounce interval same as direct keys */
if (pdata->enable_rotary0) {
if (keypad->rotary[0].enabled) {
mask |= 0x03;
direct_key_num = 2;
kpc |= KPC_REE0;
}
if (pdata->enable_rotary1) {
if (keypad->rotary[1].enabled) {
mask |= 0x0c;
direct_key_num = 4;
kpc |= KPC_REE1;
}
if (pdata->direct_key_num > direct_key_num)
direct_key_num = pdata->direct_key_num;
if (keypad->direct_key_num > direct_key_num)
direct_key_num = keypad->direct_key_num;
/*
* Direct keys usage may not start from KP_DKIN0, check the platfrom
* mask data to config the specific.
*/
if (pdata->direct_key_mask)
keypad->direct_key_mask = pdata->direct_key_mask;
else
keypad->direct_key_mask = ((1 << direct_key_num) - 1) & ~mask;
if (!keypad->direct_key_mask)
keypad->direct_key_mask = GENMASK(direct_key_num - 1, 0) & ~mask;
/* enable direct key */
if (direct_key_num)
@@ -635,7 +534,7 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
keypad_writel(KPC, kpc | KPC_RE_ZERO_DEB);
keypad_writel(KPREC, DEFAULT_KPREC);
keypad_writel(KPKDI, pdata->debounce_interval);
keypad_writel(KPKDI, keypad->debounce_interval);
}
static int pxa27x_keypad_open(struct input_dev *dev)
@@ -709,19 +608,12 @@ static int pxa27x_keypad_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(pxa27x_keypad_pm_ops,
pxa27x_keypad_suspend, pxa27x_keypad_resume);
static int pxa27x_keypad_probe(struct platform_device *pdev)
{
const struct pxa27x_keypad_platform_data *pdata =
dev_get_platdata(&pdev->dev);
struct device_node *np = pdev->dev.of_node;
struct pxa27x_keypad *keypad;
struct input_dev *input_dev;
int irq, error;
/* Driver need build keycode from device tree or pdata */
if (!np && !pdata)
return -EINVAL;
int irq;
int error;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
@@ -736,7 +628,6 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
if (!input_dev)
return -ENOMEM;
keypad->pdata = pdata;
keypad->input_dev = input_dev;
keypad->irq = irq;
@@ -765,29 +656,12 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
if (pdata) {
error = pxa27x_keypad_build_keycode(keypad);
} else {
error = pxa27x_keypad_build_keycode_from_dt(keypad);
/*
* Data that we get from DT resides in dynamically
* allocated memory so we need to update our pdata
* pointer.
*/
pdata = keypad->pdata;
}
error = pxa27x_keypad_parse_properties(keypad);
if (error) {
dev_err(&pdev->dev, "failed to build keycode\n");
dev_err(&pdev->dev, "failed to parse keypad properties\n");
return error;
}
keypad->row_shift = get_count_order(pdata->matrix_key_cols);
if ((pdata->enable_rotary0 && keypad->rotary_rel_code[0] != -1) ||
(pdata->enable_rotary1 && keypad->rotary_rel_code[1] != -1)) {
input_dev->evbit[0] |= BIT_MASK(EV_REL);
}
error = devm_request_irq(&pdev->dev, irq, pxa27x_keypad_irq_handler,
0, pdev->name, keypad);
if (error) {
+15 -56
View File
@@ -14,6 +14,7 @@
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/input/matrix_keypad.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/kernel.h>
@@ -22,7 +23,6 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/platform_data/keyboard-spear.h>
/* Keyboard Registers */
#define MODE_CTL_REG 0x00
@@ -56,13 +56,12 @@ struct spear_kbd {
void __iomem *io_base;
struct clk *clk;
unsigned int irq;
unsigned int mode;
unsigned int suspended_rate;
u32 mode;
u32 suspended_rate;
u32 mode_ctl_reg;
unsigned short last_key;
unsigned short keycodes[NUM_ROWS * NUM_COLS];
bool rep;
bool irq_wake_enabled;
u32 mode_ctl_reg;
};
static irqreturn_t spear_kbd_interrupt(int irq, void *dev_id)
@@ -143,46 +142,8 @@ static void spear_kbd_close(struct input_dev *dev)
kbd->last_key = KEY_RESERVED;
}
#ifdef CONFIG_OF
static int spear_kbd_parse_dt(struct platform_device *pdev,
struct spear_kbd *kbd)
{
struct device_node *np = pdev->dev.of_node;
int error;
u32 val, suspended_rate;
if (!np) {
dev_err(&pdev->dev, "Missing DT data\n");
return -EINVAL;
}
if (of_property_read_bool(np, "autorepeat"))
kbd->rep = true;
if (of_property_read_u32(np, "suspended_rate", &suspended_rate))
kbd->suspended_rate = suspended_rate;
error = of_property_read_u32(np, "st,mode", &val);
if (error) {
dev_err(&pdev->dev, "DT: Invalid or missing mode\n");
return error;
}
kbd->mode = val;
return 0;
}
#else
static inline int spear_kbd_parse_dt(struct platform_device *pdev,
struct spear_kbd *kbd)
{
return -ENOSYS;
}
#endif
static int spear_kbd_probe(struct platform_device *pdev)
{
struct kbd_platform_data *pdata = dev_get_platdata(&pdev->dev);
const struct matrix_keymap_data *keymap = pdata ? pdata->keymap : NULL;
struct spear_kbd *kbd;
struct input_dev *input_dev;
int irq;
@@ -198,6 +159,14 @@ static int spear_kbd_probe(struct platform_device *pdev)
return -ENOMEM;
}
error = device_property_read_u32(&pdev->dev, "st,mode", &kbd->mode);
if (error) {
dev_err(&pdev->dev, "Invalid or missing mode\n");
return error;
}
device_property_read_u32(&pdev->dev, "suspended_rate", &kbd->suspended_rate);
input_dev = devm_input_allocate_device(&pdev->dev);
if (!input_dev) {
dev_err(&pdev->dev, "unable to allocate input device\n");
@@ -207,16 +176,6 @@ static int spear_kbd_probe(struct platform_device *pdev)
kbd->input = input_dev;
kbd->irq = irq;
if (!pdata) {
error = spear_kbd_parse_dt(pdev, kbd);
if (error)
return error;
} else {
kbd->mode = pdata->mode;
kbd->rep = pdata->rep;
kbd->suspended_rate = pdata->suspended_rate;
}
kbd->io_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(kbd->io_base))
return PTR_ERR(kbd->io_base);
@@ -234,21 +193,21 @@ static int spear_kbd_probe(struct platform_device *pdev)
input_dev->open = spear_kbd_open;
input_dev->close = spear_kbd_close;
error = matrix_keypad_build_keymap(keymap, NULL, NUM_ROWS, NUM_COLS,
error = matrix_keypad_build_keymap(NULL, NULL, NUM_ROWS, NUM_COLS,
kbd->keycodes, input_dev);
if (error) {
dev_err(&pdev->dev, "Failed to build keymap\n");
return error;
}
if (kbd->rep)
if (device_property_read_bool(&pdev->dev, "autorepeat"))
__set_bit(EV_REP, input_dev->evbit);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
input_set_drvdata(input_dev, kbd);
error = devm_request_irq(&pdev->dev, irq, spear_kbd_interrupt, 0,
"keyboard", kbd);
"keyboard", kbd);
if (error) {
dev_err(&pdev->dev, "request_irq failed\n");
return error;
-305
View File
@@ -1,305 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Driver for keys on TCA6416 I2C IO expander
*
* Copyright (C) 2010 Texas Instruments
*
* Author : Sriramakrishnan.A.G. <srk@ti.com>
*/
#include <linux/types.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/tca6416_keypad.h>
#define TCA6416_INPUT 0
#define TCA6416_OUTPUT 1
#define TCA6416_INVERT 2
#define TCA6416_DIRECTION 3
#define TCA6416_POLL_INTERVAL 100 /* msec */
static const struct i2c_device_id tca6416_id[] = {
{ "tca6416-keys", 16, },
{ "tca6408-keys", 8, },
{ }
};
MODULE_DEVICE_TABLE(i2c, tca6416_id);
struct tca6416_keypad_chip {
uint16_t reg_output;
uint16_t reg_direction;
uint16_t reg_input;
struct i2c_client *client;
struct input_dev *input;
int io_size;
u16 pinmask;
bool use_polling;
struct tca6416_button buttons[];
};
static int tca6416_write_reg(struct tca6416_keypad_chip *chip, int reg, u16 val)
{
int error;
error = chip->io_size > 8 ?
i2c_smbus_write_word_data(chip->client, reg << 1, val) :
i2c_smbus_write_byte_data(chip->client, reg, val);
if (error < 0) {
dev_err(&chip->client->dev,
"%s failed, reg: %d, val: %d, error: %d\n",
__func__, reg, val, error);
return error;
}
return 0;
}
static int tca6416_read_reg(struct tca6416_keypad_chip *chip, int reg, u16 *val)
{
int retval;
retval = chip->io_size > 8 ?
i2c_smbus_read_word_data(chip->client, reg << 1) :
i2c_smbus_read_byte_data(chip->client, reg);
if (retval < 0) {
dev_err(&chip->client->dev, "%s failed, reg: %d, error: %d\n",
__func__, reg, retval);
return retval;
}
*val = (u16)retval;
return 0;
}
static void tca6416_keys_scan(struct input_dev *input)
{
struct tca6416_keypad_chip *chip = input_get_drvdata(input);
u16 reg_val, val;
int error, i, pin_index;
error = tca6416_read_reg(chip, TCA6416_INPUT, &reg_val);
if (error)
return;
reg_val &= chip->pinmask;
/* Figure out which lines have changed */
val = reg_val ^ chip->reg_input;
chip->reg_input = reg_val;
for (i = 0, pin_index = 0; i < 16; i++) {
if (val & (1 << i)) {
struct tca6416_button *button = &chip->buttons[pin_index];
unsigned int type = button->type ?: EV_KEY;
int state = ((reg_val & (1 << i)) ? 1 : 0)
^ button->active_low;
input_event(input, type, button->code, !!state);
input_sync(input);
}
if (chip->pinmask & (1 << i))
pin_index++;
}
}
/*
* This is threaded IRQ handler and this can (and will) sleep.
*/
static irqreturn_t tca6416_keys_isr(int irq, void *dev_id)
{
tca6416_keys_scan(dev_id);
return IRQ_HANDLED;
}
static int tca6416_keys_open(struct input_dev *dev)
{
struct tca6416_keypad_chip *chip = input_get_drvdata(dev);
if (!chip->use_polling) {
/* Get initial device state in case it has switches */
tca6416_keys_scan(dev);
enable_irq(chip->client->irq);
}
return 0;
}
static void tca6416_keys_close(struct input_dev *dev)
{
struct tca6416_keypad_chip *chip = input_get_drvdata(dev);
if (!chip->use_polling)
disable_irq(chip->client->irq);
}
static int tca6416_setup_registers(struct tca6416_keypad_chip *chip)
{
int error;
error = tca6416_read_reg(chip, TCA6416_OUTPUT, &chip->reg_output);
if (error)
return error;
error = tca6416_read_reg(chip, TCA6416_DIRECTION, &chip->reg_direction);
if (error)
return error;
/* ensure that keypad pins are set to input */
error = tca6416_write_reg(chip, TCA6416_DIRECTION,
chip->reg_direction | chip->pinmask);
if (error)
return error;
error = tca6416_read_reg(chip, TCA6416_DIRECTION, &chip->reg_direction);
if (error)
return error;
error = tca6416_read_reg(chip, TCA6416_INPUT, &chip->reg_input);
if (error)
return error;
chip->reg_input &= chip->pinmask;
return 0;
}
static int tca6416_keypad_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct tca6416_keys_platform_data *pdata;
struct tca6416_keypad_chip *chip;
struct input_dev *input;
int error;
int i;
/* Check functionality */
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) {
dev_err(&client->dev, "%s adapter not supported\n",
dev_driver_string(&client->adapter->dev));
return -ENODEV;
}
pdata = dev_get_platdata(&client->dev);
if (!pdata) {
dev_dbg(&client->dev, "no platform data\n");
return -EINVAL;
}
chip = devm_kzalloc(&client->dev,
struct_size(chip, buttons, pdata->nbuttons),
GFP_KERNEL);
if (!chip)
return -ENOMEM;
input = devm_input_allocate_device(&client->dev);
if (!input)
return -ENOMEM;
chip->client = client;
chip->input = input;
chip->io_size = id->driver_data;
chip->pinmask = pdata->pinmask;
chip->use_polling = pdata->use_polling;
input->phys = "tca6416-keys/input0";
input->name = client->name;
input->open = tca6416_keys_open;
input->close = tca6416_keys_close;
input->id.bustype = BUS_HOST;
input->id.vendor = 0x0001;
input->id.product = 0x0001;
input->id.version = 0x0100;
/* Enable auto repeat feature of Linux input subsystem */
if (pdata->rep)
__set_bit(EV_REP, input->evbit);
for (i = 0; i < pdata->nbuttons; i++) {
unsigned int type;
chip->buttons[i] = pdata->buttons[i];
type = (pdata->buttons[i].type) ?: EV_KEY;
input_set_capability(input, type, pdata->buttons[i].code);
}
input_set_drvdata(input, chip);
/*
* Initialize cached registers from their original values.
* we can't share this chip with another i2c master.
*/
error = tca6416_setup_registers(chip);
if (error)
return error;
if (chip->use_polling) {
error = input_setup_polling(input, tca6416_keys_scan);
if (error) {
dev_err(&client->dev, "Failed to setup polling\n");
return error;
}
input_set_poll_interval(input, TCA6416_POLL_INTERVAL);
} else {
error = devm_request_threaded_irq(&client->dev, client->irq,
NULL, tca6416_keys_isr,
IRQF_TRIGGER_FALLING |
IRQF_ONESHOT |
IRQF_NO_AUTOEN,
"tca6416-keypad", input);
if (error) {
dev_dbg(&client->dev,
"Unable to claim irq %d; error %d\n",
client->irq, error);
return error;
}
}
error = input_register_device(input);
if (error) {
dev_dbg(&client->dev,
"Unable to register input device, error: %d\n", error);
return error;
}
i2c_set_clientdata(client, chip);
return 0;
}
static struct i2c_driver tca6416_keypad_driver = {
.driver = {
.name = "tca6416-keypad",
},
.probe = tca6416_keypad_probe,
.id_table = tca6416_id,
};
static int __init tca6416_keypad_init(void)
{
return i2c_add_driver(&tca6416_keypad_driver);
}
subsys_initcall(tca6416_keypad_init);
static void __exit tca6416_keypad_exit(void)
{
i2c_del_driver(&tca6416_keypad_driver);
}
module_exit(tca6416_keypad_exit);
MODULE_AUTHOR("Sriramakrishnan <srk@ti.com>");
MODULE_DESCRIPTION("Keypad driver over tca6416 IO expander");
MODULE_LICENSE("GPL");
+1 -12
View File
@@ -373,18 +373,7 @@ static struct i2c_driver tca8418_keypad_driver = {
.probe = tca8418_keypad_probe,
.id_table = tca8418_id,
};
static int __init tca8418_keypad_init(void)
{
return i2c_add_driver(&tca8418_keypad_driver);
}
subsys_initcall(tca8418_keypad_init);
static void __exit tca8418_keypad_exit(void)
{
i2c_del_driver(&tca8418_keypad_driver);
}
module_exit(tca8418_keypad_exit);
module_i2c_driver(tca8418_keypad_driver);
MODULE_AUTHOR("Kyle Manna <kyle.manna@fuel7.com>");
MODULE_DESCRIPTION("Keypad driver for TCA8418");
+6 -29
View File
@@ -28,10 +28,6 @@
* an internal state machine that decodes pressed keys, including
* multi-key combinations.
*
* This driver lets boards define what keycodes they wish to report for
* which scancodes, as part of the "struct twl4030_keypad_data" used in
* the probe() routine.
*
* See the TPS65950 documentation; that's the general availability
* version of the TWL5030 second generation part.
*/
@@ -47,7 +43,6 @@
struct twl4030_keypad {
unsigned short keymap[TWL4030_KEYMAP_SIZE];
u16 kp_state[TWL4030_MAX_ROWS];
bool autorepeat;
unsigned int n_rows;
unsigned int n_cols;
int irq;
@@ -322,8 +317,6 @@ static int twl4030_kp_program(struct twl4030_keypad *kp)
*/
static int twl4030_kp_probe(struct platform_device *pdev)
{
struct twl4030_keypad_data *pdata = dev_get_platdata(&pdev->dev);
const struct matrix_keymap_data *keymap_data = NULL;
struct twl4030_keypad *kp;
struct input_dev *input;
u8 reg;
@@ -350,24 +343,10 @@ static int twl4030_kp_probe(struct platform_device *pdev)
input->id.product = 0x0001;
input->id.version = 0x0003;
if (pdata) {
if (!pdata->rows || !pdata->cols || !pdata->keymap_data) {
dev_err(&pdev->dev, "Missing platform_data\n");
return -EINVAL;
}
kp->n_rows = pdata->rows;
kp->n_cols = pdata->cols;
kp->autorepeat = pdata->rep;
keymap_data = pdata->keymap_data;
} else {
error = matrix_keypad_parse_properties(&pdev->dev, &kp->n_rows,
&kp->n_cols);
if (error)
return error;
kp->autorepeat = true;
}
error = matrix_keypad_parse_properties(&pdev->dev,
&kp->n_rows, &kp->n_cols);
if (error)
return error;
if (kp->n_rows > TWL4030_MAX_ROWS || kp->n_cols > TWL4030_MAX_COLS) {
dev_err(&pdev->dev,
@@ -379,7 +358,7 @@ static int twl4030_kp_probe(struct platform_device *pdev)
if (kp->irq < 0)
return kp->irq;
error = matrix_keypad_build_keymap(keymap_data, NULL,
error = matrix_keypad_build_keymap(NULL, NULL,
TWL4030_MAX_ROWS,
1 << TWL4030_ROW_SHIFT,
kp->keymap, input);
@@ -389,9 +368,7 @@ static int twl4030_kp_probe(struct platform_device *pdev)
}
input_set_capability(input, EV_MSC, MSC_SCAN);
/* Enable auto repeat feature of Linux input subsystem */
if (kp->autorepeat)
__set_bit(EV_REP, input->evbit);
__set_bit(EV_REP, input->evbit);
error = input_register_device(input);
if (error) {
+11
View File
@@ -126,6 +126,17 @@ config INPUT_ATMEL_CAPTOUCH
To compile this driver as a module, choose M here: the
module will be called atmel_captouch.
config INPUT_AW86927
tristate "Awinic AW86927 Haptic Driver Support"
depends on I2C && INPUT
select INPUT_FF_MEMLESS
select REGMAP_I2C
help
Say Y here if you have an Awinic AW86927 haptic chip.
To compile this driver as a module, choose M here: the
module will be called aw86927.
config INPUT_BBNSM_PWRKEY
tristate "NXP BBNSM Power Key Driver"
depends on ARCH_MXC || COMPILE_TEST
+1
View File
@@ -22,6 +22,7 @@ obj-$(CONFIG_INPUT_ATC260X_ONKEY) += atc260x-onkey.o
obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o
obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o
obj-$(CONFIG_INPUT_ATMEL_CAPTOUCH) += atmel_captouch.o
obj-$(CONFIG_INPUT_AW86927) += aw86927.o
obj-$(CONFIG_INPUT_BBNSM_PWRKEY) += nxp-bbnsm-pwrkey.o
obj-$(CONFIG_INPUT_BMA150) += bma150.o
obj-$(CONFIG_INPUT_CM109) += cm109.o
+1
View File
@@ -6,6 +6,7 @@
*/
#include <linux/device.h>
#include <linux/export.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
+1
View File
@@ -9,6 +9,7 @@
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+846
View File
@@ -0,0 +1,846 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2025 Griffin Kroah-Hartman <griffin.kroah@fairphone.com>
*
* Partially based on vendor driver:
* Copyright (c) 2021 AWINIC Technology CO., LTD
*
*/
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/types.h>
#define AW86927_RSTCFG_REG 0x00
#define AW86927_RSTCFG_SOFTRST 0xaa
#define AW86927_SYSINT_REG 0x02
#define AW86927_SYSINT_BST_SCPI BIT(7)
#define AW86927_SYSINT_BST_OVPI BIT(6)
#define AW86927_SYSINT_UVLI BIT(5)
#define AW86927_SYSINT_FF_AEI BIT(4)
#define AW86927_SYSINT_FF_AFI BIT(3)
#define AW86927_SYSINT_OCDI BIT(2)
#define AW86927_SYSINT_OTI BIT(1)
#define AW86927_SYSINT_DONEI BIT(0)
#define AW86927_SYSINTM_REG 0x03
#define AW86927_SYSINTM_BST_OVPM BIT(6)
#define AW86927_SYSINTM_FF_AEM BIT(4)
#define AW86927_SYSINTM_FF_AFM BIT(3)
#define AW86927_SYSINTM_DONEM BIT(0)
#define AW86927_PLAYCFG1_REG 0x06
#define AW86927_PLAYCFG1_BST_MODE_MASK GENMASK(7, 7)
#define AW86927_PLAYCFG1_BST_MODE_BYPASS 0
#define AW86927_PLAYCFG1_BST_VOUT_VREFSET_MASK GENMASK(6, 0)
#define AW86927_PLAYCFG1_BST_8500MV 0x50
#define AW86927_PLAYCFG2_REG 0x07
#define AW86927_PLAYCFG3_REG 0x08
#define AW86927_PLAYCFG3_AUTO_BST_MASK GENMASK(4, 4)
#define AW86927_PLAYCFG3_AUTO_BST_ENABLE 1
#define AW86927_PLAYCFG3_AUTO_BST_DISABLE 0
#define AW86927_PLAYCFG3_PLAY_MODE_MASK GENMASK(1, 0)
#define AW86927_PLAYCFG3_PLAY_MODE_RAM 0
#define AW86927_PLAYCFG4_REG 0x09
#define AW86927_PLAYCFG4_STOP BIT(1)
#define AW86927_PLAYCFG4_GO BIT(0)
#define AW86927_WAVCFG1_REG 0x0a
#define AW86927_WAVCFG1_WAVSEQ1_MASK GENMASK(6, 0)
#define AW86927_WAVCFG2_REG 0x0b
#define AW86927_WAVCFG2_WAVSEQ2_MASK GENMASK(6, 0)
#define AW86927_WAVCFG9_REG 0x12
#define AW86927_WAVCFG9_SEQ1LOOP_MASK GENMASK(7, 4)
#define AW86927_WAVCFG9_SEQ1LOOP_INFINITELY 0x0f
#define AW86927_CONTCFG1_REG 0x18
#define AW86927_CONTCFG1_BRK_BST_MD_MASK GENMASK(6, 6)
#define AW86927_CONTCFG5_REG 0x1c
#define AW86927_CONTCFG5_BST_BRK_GAIN_MASK GENMASK(7, 4)
#define AW86927_CONTCFG5_BRK_GAIN_MASK GENMASK(3, 0)
#define AW86927_CONTCFG10_REG 0x21
#define AW86927_CONTCFG10_BRK_TIME_MASK GENMASK(7, 0)
#define AW86927_CONTCFG10_BRK_TIME_DEFAULT 8
#define AW86927_CONTCFG13_REG 0x24
#define AW86927_CONTCFG13_TSET_MASK GENMASK(7, 4)
#define AW86927_CONTCFG13_BEME_SET_MASK GENMASK(3, 0)
#define AW86927_BASEADDRH_REG 0x2d
#define AW86927_BASEADDRL_REG 0x2e
#define AW86927_GLBRD5_REG 0x3f
#define AW86927_GLBRD5_STATE_MASK GENMASK(3, 0)
#define AW86927_GLBRD5_STATE_STANDBY 0
#define AW86927_RAMADDRH_REG 0x40
#define AW86927_RAMADDRL_REG 0x41
#define AW86927_RAMDATA_REG 0x42
#define AW86927_SYSCTRL3_REG 0x45
#define AW86927_SYSCTRL3_STANDBY_MASK GENMASK(5, 5)
#define AW86927_SYSCTRL3_STANDBY_ON 1
#define AW86927_SYSCTRL3_STANDBY_OFF 0
#define AW86927_SYSCTRL3_EN_RAMINIT_MASK GENMASK(2, 2)
#define AW86927_SYSCTRL3_EN_RAMINIT_ON 1
#define AW86927_SYSCTRL3_EN_RAMINIT_OFF 0
#define AW86927_SYSCTRL4_REG 0x46
#define AW86927_SYSCTRL4_WAVDAT_MODE_MASK GENMASK(6, 5)
#define AW86927_SYSCTRL4_WAVDAT_24K 0
#define AW86927_SYSCTRL4_INT_EDGE_MODE_MASK GENMASK(4, 4)
#define AW86927_SYSCTRL4_INT_EDGE_MODE_POS 0
#define AW86927_SYSCTRL4_INT_MODE_MASK GENMASK(3, 3)
#define AW86927_SYSCTRL4_INT_MODE_EDGE 1
#define AW86927_SYSCTRL4_GAIN_BYPASS_MASK GENMASK(0, 0)
#define AW86927_PWMCFG1_REG 0x48
#define AW86927_PWMCFG1_PRC_EN_MASK GENMASK(7, 7)
#define AW86927_PWMCFG1_PRC_DISABLE 0
#define AW86927_PWMCFG3_REG 0x4a
#define AW86927_PWMCFG3_PR_EN_MASK GENMASK(7, 7)
#define AW86927_PWMCFG3_PRCTIME_MASK GENMASK(6, 0)
#define AW86927_PWMCFG4_REG 0x4b
#define AW86927_PWMCFG4_PRTIME_MASK GENMASK(7, 0)
#define AW86927_VBATCTRL_REG 0x4c
#define AW86927_VBATCTRL_VBAT_MODE_MASK GENMASK(6, 6)
#define AW86927_VBATCTRL_VBAT_MODE_SW 0
#define AW86927_DETCFG1_REG 0x4d
#define AW86927_DETCFG1_DET_GO_MASK GENMASK(1, 0)
#define AW86927_DETCFG1_DET_GO_DET_SEQ0 1
#define AW86927_DETCFG1_DET_GO_NA 0
#define AW86927_DETCFG2_REG 0x4e
#define AW86927_DETCFG2_DET_SEQ0_MASK GENMASK(6, 3)
#define AW86927_DETCFG2_DET_SEQ0_VBAT 0
#define AW86927_DETCFG2_D2S_GAIN_MASK GENMASK(2, 0)
#define AW86927_DETCFG2_D2S_GAIN_10 4
#define AW86927_CHIPIDH_REG 0x57
#define AW86927_CHIPIDL_REG 0x58
#define AW86927_CHIPID 0x9270
#define AW86927_TMCFG_REG 0x5b
#define AW86927_TMCFG_UNLOCK 0x7d
#define AW86927_TMCFG_LOCK 0x00
#define AW86927_ANACFG11_REG 0x70
#define AW86927_ANACFG12_REG 0x71
#define AW86927_ANACFG12_BST_SKIP_MASK GENMASK(7, 7)
#define AW86927_ANACFG12_BST_SKIP_SHUTDOWN 1
#define AW86927_ANACFG13_REG 0x72
#define AW86927_ANACFG13_BST_PC_MASK GENMASK(7, 4)
#define AW86927_ANACFG13_BST_PEAKCUR_3P45A 6
#define AW86927_ANACFG15_REG 0x74
#define AW86927_ANACFG15_BST_PEAK_MODE_MASK GENMASK(7, 7)
#define AW86927_ANACFG15_BST_PEAK_BACK 1
#define AW86927_ANACFG16_REG 0x75
#define AW86927_ANACFG16_BST_SRC_MASK GENMASK(4, 4)
#define AW86927_ANACFG16_BST_SRC_3NS 0
/* default value of base addr */
#define AW86927_RAM_BASE_ADDR 0x800
#define AW86927_BASEADDRH_VAL 0x08
#define AW86927_BASEADDRL_VAL 0x00
enum aw86927_work_mode {
AW86927_STANDBY_MODE,
AW86927_RAM_MODE,
};
struct aw86927_data {
struct work_struct play_work;
struct device *dev;
struct input_dev *input_dev;
struct i2c_client *client;
struct regmap *regmap;
struct gpio_desc *reset_gpio;
bool running;
};
static const struct regmap_config aw86927_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.cache_type = REGCACHE_NONE,
.max_register = 0x80,
};
/*
* Sine wave representing the magnitude of the drive to be used.
* Data is encoded in two's complement.
* round(84 * sin(x / 16.25))
*/
static const u8 aw86927_waveform[] = {
0x00, 0x05, 0x0a, 0x0f, 0x14, 0x1a, 0x1f, 0x23, 0x28, 0x2d, 0x31, 0x35,
0x39, 0x3d, 0x41, 0x44, 0x47, 0x4a, 0x4c, 0x4f, 0x51, 0x52, 0x53, 0x54,
0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0x52, 0x51, 0x4f, 0x4d, 0x4a, 0x47,
0x44, 0x41, 0x3d, 0x3a, 0x36, 0x31, 0x2d, 0x28, 0x24, 0x1f, 0x1a, 0x15,
0x10, 0x0a, 0x05, 0x00, 0xfc, 0xf6, 0xf1, 0xec, 0xe7, 0xe2, 0xdd, 0xd8,
0xd4, 0xcf, 0xcb, 0xc7, 0xc3, 0xbf, 0xbc, 0xb9, 0xb6, 0xb4, 0xb1, 0xb0,
0xae, 0xad, 0xac, 0xab, 0xab, 0xab, 0xab, 0xab, 0xac, 0xae, 0xaf, 0xb1,
0xb3, 0xb6, 0xb8, 0xbc, 0xbf, 0xc2, 0xc6, 0xca, 0xce, 0xd3, 0xd7, 0xdc,
0xe1, 0xe6, 0xeb, 0xf0, 0xf5, 0xfb
};
struct aw86927_sram_waveform_header {
u8 version;
__be16 start_address;
__be16 end_address;
} __packed;
static const struct aw86927_sram_waveform_header sram_waveform_header = {
.version = 0x01,
.start_address = cpu_to_be16(AW86927_RAM_BASE_ADDR +
sizeof(struct aw86927_sram_waveform_header)),
.end_address = cpu_to_be16(AW86927_RAM_BASE_ADDR +
sizeof(struct aw86927_sram_waveform_header) +
ARRAY_SIZE(aw86927_waveform) - 1),
};
static int aw86927_wait_enter_standby(struct aw86927_data *haptics)
{
unsigned int reg_val;
int err;
err = regmap_read_poll_timeout(haptics->regmap, AW86927_GLBRD5_REG, reg_val,
(FIELD_GET(AW86927_GLBRD5_STATE_MASK, reg_val) ==
AW86927_GLBRD5_STATE_STANDBY),
2500, 2500 * 100);
if (err) {
dev_err(haptics->dev, "did not enter standby: %d\n", err);
return err;
}
return 0;
}
static int aw86927_play_mode(struct aw86927_data *haptics, u8 play_mode)
{
int err;
switch (play_mode) {
case AW86927_STANDBY_MODE:
/* Briefly toggle standby, then toggle back to standby off */
err = regmap_update_bits(haptics->regmap,
AW86927_SYSCTRL3_REG,
AW86927_SYSCTRL3_STANDBY_MASK,
FIELD_PREP(AW86927_SYSCTRL3_STANDBY_MASK,
AW86927_SYSCTRL3_STANDBY_ON));
if (err)
return err;
err = regmap_update_bits(haptics->regmap,
AW86927_SYSCTRL3_REG,
AW86927_SYSCTRL3_STANDBY_MASK,
FIELD_PREP(AW86927_SYSCTRL3_STANDBY_MASK,
AW86927_SYSCTRL3_STANDBY_OFF));
if (err)
return err;
break;
case AW86927_RAM_MODE:
err = regmap_update_bits(haptics->regmap,
AW86927_PLAYCFG3_REG,
AW86927_PLAYCFG3_PLAY_MODE_MASK,
FIELD_PREP(AW86927_PLAYCFG3_PLAY_MODE_MASK,
AW86927_PLAYCFG3_PLAY_MODE_RAM));
if (err)
return err;
err = regmap_update_bits(haptics->regmap,
AW86927_PLAYCFG1_REG,
AW86927_PLAYCFG1_BST_MODE_MASK,
FIELD_PREP(AW86927_PLAYCFG1_BST_MODE_MASK,
AW86927_PLAYCFG1_BST_MODE_BYPASS));
if (err)
return err;
err = regmap_update_bits(haptics->regmap,
AW86927_VBATCTRL_REG,
AW86927_VBATCTRL_VBAT_MODE_MASK,
FIELD_PREP(AW86927_VBATCTRL_VBAT_MODE_MASK,
AW86927_VBATCTRL_VBAT_MODE_SW));
if (err)
return err;
break;
}
return 0;
}
static int aw86927_stop(struct aw86927_data *haptics)
{
int err;
err = regmap_write(haptics->regmap, AW86927_PLAYCFG4_REG, AW86927_PLAYCFG4_STOP);
if (err) {
dev_err(haptics->dev, "Failed to stop playback: %d\n", err);
return err;
}
err = aw86927_wait_enter_standby(haptics);
if (err) {
dev_err(haptics->dev, "Failed to enter standby, trying to force it\n");
err = aw86927_play_mode(haptics, AW86927_STANDBY_MODE);
if (err)
return err;
}
return 0;
}
static int aw86927_haptics_play(struct input_dev *dev, void *data, struct ff_effect *effect)
{
struct aw86927_data *haptics = input_get_drvdata(dev);
int level;
level = effect->u.rumble.strong_magnitude;
if (!level)
level = effect->u.rumble.weak_magnitude;
/* If already running, don't restart playback */
if (haptics->running && level)
return 0;
haptics->running = level;
schedule_work(&haptics->play_work);
return 0;
}
static int aw86927_play_sine(struct aw86927_data *haptics)
{
int err;
err = aw86927_stop(haptics);
if (err)
return err;
err = aw86927_play_mode(haptics, AW86927_RAM_MODE);
if (err)
return err;
err = regmap_update_bits(haptics->regmap, AW86927_PLAYCFG3_REG,
AW86927_PLAYCFG3_AUTO_BST_MASK,
FIELD_PREP(AW86927_PLAYCFG3_AUTO_BST_MASK,
AW86927_PLAYCFG3_AUTO_BST_ENABLE));
if (err)
return err;
/* Set waveseq 1 to the first wave */
err = regmap_update_bits(haptics->regmap, AW86927_WAVCFG1_REG,
AW86927_WAVCFG1_WAVSEQ1_MASK,
FIELD_PREP(AW86927_WAVCFG1_WAVSEQ1_MASK, 1));
if (err)
return err;
/* set wavseq 2 to zero */
err = regmap_update_bits(haptics->regmap, AW86927_WAVCFG2_REG,
AW86927_WAVCFG2_WAVSEQ2_MASK,
FIELD_PREP(AW86927_WAVCFG2_WAVSEQ2_MASK, 0));
if (err)
return err;
err = regmap_update_bits(haptics->regmap,
AW86927_WAVCFG9_REG,
AW86927_WAVCFG9_SEQ1LOOP_MASK,
FIELD_PREP(AW86927_WAVCFG9_SEQ1LOOP_MASK,
AW86927_WAVCFG9_SEQ1LOOP_INFINITELY));
if (err)
return err;
/* set gain to value lower than 0x80 to avoid distorted playback */
err = regmap_write(haptics->regmap, AW86927_PLAYCFG2_REG, 0x7c);
if (err)
return err;
/* Start playback */
err = regmap_write(haptics->regmap, AW86927_PLAYCFG4_REG, AW86927_PLAYCFG4_GO);
if (err)
return err;
return 0;
}
static void aw86927_close(struct input_dev *input)
{
struct aw86927_data *haptics = input_get_drvdata(input);
struct device *dev = &haptics->client->dev;
int err;
cancel_work_sync(&haptics->play_work);
err = aw86927_stop(haptics);
if (err)
dev_err(dev, "Failed to close the Driver: %d\n", err);
}
static void aw86927_haptics_play_work(struct work_struct *work)
{
struct aw86927_data *haptics =
container_of(work, struct aw86927_data, play_work);
struct device *dev = &haptics->client->dev;
int err;
if (haptics->running)
err = aw86927_play_sine(haptics);
else
err = aw86927_stop(haptics);
if (err)
dev_err(dev, "Failed to execute work command: %d\n", err);
}
static void aw86927_hw_reset(struct aw86927_data *haptics)
{
/* Assert reset */
gpiod_set_value_cansleep(haptics->reset_gpio, 1);
/* Wait ~1ms */
usleep_range(1000, 2000);
/* Deassert reset */
gpiod_set_value_cansleep(haptics->reset_gpio, 0);
/* Wait ~8ms until I2C is accessible */
usleep_range(8000, 8500);
}
static int aw86927_haptic_init(struct aw86927_data *haptics)
{
int err;
err = regmap_update_bits(haptics->regmap,
AW86927_SYSCTRL4_REG,
AW86927_SYSCTRL4_WAVDAT_MODE_MASK,
FIELD_PREP(AW86927_SYSCTRL4_WAVDAT_MODE_MASK,
AW86927_SYSCTRL4_WAVDAT_24K));
if (err)
return err;
/* enable gain bypass */
err = regmap_update_bits(haptics->regmap,
AW86927_SYSCTRL4_REG,
AW86927_SYSCTRL4_GAIN_BYPASS_MASK,
FIELD_PREP(AW86927_SYSCTRL4_GAIN_BYPASS_MASK,
0x01));
if (err)
return err;
err = regmap_write(haptics->regmap,
AW86927_TMCFG_REG, AW86927_TMCFG_UNLOCK);
if (err)
return err;
err = regmap_write(haptics->regmap, AW86927_ANACFG11_REG, 0x0f);
if (err)
return err;
err = regmap_update_bits(haptics->regmap,
AW86927_ANACFG12_REG,
AW86927_ANACFG12_BST_SKIP_MASK,
FIELD_PREP(AW86927_ANACFG12_BST_SKIP_MASK,
AW86927_ANACFG12_BST_SKIP_SHUTDOWN));
if (err)
return err;
err = regmap_update_bits(haptics->regmap,
AW86927_ANACFG15_REG,
AW86927_ANACFG15_BST_PEAK_MODE_MASK,
FIELD_PREP(AW86927_ANACFG15_BST_PEAK_MODE_MASK,
AW86927_ANACFG15_BST_PEAK_BACK));
if (err)
return err;
err = regmap_update_bits(haptics->regmap,
AW86927_ANACFG16_REG,
AW86927_ANACFG16_BST_SRC_MASK,
FIELD_PREP(AW86927_ANACFG16_BST_SRC_MASK,
AW86927_ANACFG16_BST_SRC_3NS));
if (err)
return err;
err = regmap_write(haptics->regmap,
AW86927_TMCFG_REG, AW86927_TMCFG_LOCK);
if (err)
return err;
err = regmap_update_bits(haptics->regmap,
AW86927_CONTCFG1_REG,
AW86927_CONTCFG1_BRK_BST_MD_MASK,
FIELD_PREP(AW86927_CONTCFG1_BRK_BST_MD_MASK, 0x00));
if (err)
return err;
err = regmap_write(haptics->regmap,
AW86927_CONTCFG5_REG,
FIELD_PREP(AW86927_CONTCFG5_BST_BRK_GAIN_MASK, 0x05) |
FIELD_PREP(AW86927_CONTCFG5_BRK_GAIN_MASK, 0x08));
if (err)
return err;
err = regmap_update_bits(haptics->regmap, AW86927_CONTCFG10_REG,
AW86927_CONTCFG10_BRK_TIME_MASK,
FIELD_PREP(AW86927_CONTCFG10_BRK_TIME_MASK,
AW86927_CONTCFG10_BRK_TIME_DEFAULT));
if (err)
return err;
err = regmap_write(haptics->regmap,
AW86927_CONTCFG13_REG,
FIELD_PREP(AW86927_CONTCFG13_TSET_MASK, 0x06) |
FIELD_PREP(AW86927_CONTCFG13_BEME_SET_MASK, 0x02));
if (err)
return err;
err = regmap_update_bits(haptics->regmap,
AW86927_DETCFG2_REG,
AW86927_DETCFG2_D2S_GAIN_MASK,
FIELD_PREP(AW86927_DETCFG2_D2S_GAIN_MASK,
AW86927_DETCFG2_D2S_GAIN_10));
if (err)
return err;
err = regmap_update_bits(haptics->regmap,
AW86927_PWMCFG1_REG,
AW86927_PWMCFG1_PRC_EN_MASK,
FIELD_PREP(AW86927_PWMCFG1_PRC_EN_MASK,
AW86927_PWMCFG1_PRC_DISABLE));
if (err)
return err;
err = regmap_write(haptics->regmap,
AW86927_PWMCFG3_REG,
FIELD_PREP(AW86927_PWMCFG3_PR_EN_MASK, 0x01) |
FIELD_PREP(AW86927_PWMCFG3_PRCTIME_MASK, 0x3f));
if (err)
return err;
err = regmap_update_bits(haptics->regmap,
AW86927_PWMCFG4_REG,
AW86927_PWMCFG4_PRTIME_MASK,
FIELD_PREP(AW86927_PWMCFG4_PRTIME_MASK, 0x32));
if (err)
return err;
err = regmap_write(haptics->regmap,
AW86927_TMCFG_REG, AW86927_TMCFG_UNLOCK);
if (err)
return err;
err = regmap_update_bits(haptics->regmap,
AW86927_ANACFG13_REG,
AW86927_ANACFG13_BST_PC_MASK,
FIELD_PREP(AW86927_ANACFG13_BST_PC_MASK,
AW86927_ANACFG13_BST_PEAKCUR_3P45A));
if (err)
return err;
err = regmap_write(haptics->regmap,
AW86927_TMCFG_REG, AW86927_TMCFG_LOCK);
if (err)
return err;
err = regmap_update_bits(haptics->regmap,
AW86927_PLAYCFG1_REG,
AW86927_PLAYCFG1_BST_VOUT_VREFSET_MASK,
FIELD_PREP(AW86927_PLAYCFG1_BST_VOUT_VREFSET_MASK,
AW86927_PLAYCFG1_BST_8500MV));
if (err)
return err;
err = regmap_update_bits(haptics->regmap,
AW86927_PLAYCFG3_REG,
AW86927_PLAYCFG3_AUTO_BST_MASK,
FIELD_PREP(AW86927_PLAYCFG3_AUTO_BST_MASK,
AW86927_PLAYCFG3_AUTO_BST_DISABLE));
if (err)
return err;
return 0;
}
static int aw86927_ram_init(struct aw86927_data *haptics)
{
int err;
err = aw86927_wait_enter_standby(haptics);
if (err)
return err;
/* Enable SRAM init */
err = regmap_update_bits(haptics->regmap,
AW86927_SYSCTRL3_REG,
AW86927_SYSCTRL3_EN_RAMINIT_MASK,
FIELD_PREP(AW86927_SYSCTRL3_EN_RAMINIT_MASK,
AW86927_SYSCTRL3_EN_RAMINIT_ON));
/* Set base address for the start of the SRAM waveforms */
err = regmap_write(haptics->regmap,
AW86927_BASEADDRH_REG, AW86927_BASEADDRH_VAL);
if (err)
return err;
err = regmap_write(haptics->regmap,
AW86927_BASEADDRL_REG, AW86927_BASEADDRL_VAL);
if (err)
return err;
/* Set start of SRAM, before the data is written it will be the same as the base */
err = regmap_write(haptics->regmap,
AW86927_RAMADDRH_REG, AW86927_BASEADDRH_VAL);
if (err)
return err;
err = regmap_write(haptics->regmap,
AW86927_RAMADDRL_REG, AW86927_BASEADDRL_VAL);
if (err)
return err;
/* Write waveform header to SRAM */
err = regmap_noinc_write(haptics->regmap, AW86927_RAMDATA_REG,
&sram_waveform_header, sizeof(sram_waveform_header));
if (err)
return err;
/* Write waveform to SRAM */
err = regmap_noinc_write(haptics->regmap, AW86927_RAMDATA_REG,
aw86927_waveform, ARRAY_SIZE(aw86927_waveform));
if (err)
return err;
err = regmap_update_bits(haptics->regmap,
AW86927_DETCFG2_REG,
AW86927_DETCFG2_DET_SEQ0_MASK,
FIELD_PREP(AW86927_DETCFG2_DET_SEQ0_MASK,
AW86927_DETCFG2_DET_SEQ0_VBAT));
if (err)
return err;
err = regmap_update_bits(haptics->regmap,
AW86927_DETCFG1_REG,
AW86927_DETCFG1_DET_GO_MASK,
FIELD_PREP(AW86927_DETCFG1_DET_GO_MASK,
AW86927_DETCFG1_DET_GO_DET_SEQ0));
if (err)
return err;
usleep_range(3000, 3500);
err = regmap_update_bits(haptics->regmap,
AW86927_DETCFG1_REG,
AW86927_DETCFG1_DET_GO_MASK,
FIELD_PREP(AW86927_DETCFG1_DET_GO_MASK,
AW86927_DETCFG1_DET_GO_NA));
if (err)
return err;
/* Disable SRAM init */
err = regmap_update_bits(haptics->regmap,
AW86927_SYSCTRL3_REG,
AW86927_SYSCTRL3_EN_RAMINIT_MASK,
FIELD_PREP(AW86927_SYSCTRL3_EN_RAMINIT_MASK,
AW86927_SYSCTRL3_EN_RAMINIT_OFF));
if (err)
return err;
return 0;
}
static irqreturn_t aw86927_irq(int irq, void *data)
{
struct aw86927_data *haptics = data;
struct device *dev = &haptics->client->dev;
unsigned int reg_val;
int err;
err = regmap_read(haptics->regmap, AW86927_SYSINT_REG, &reg_val);
if (err) {
dev_err(dev, "Failed to read SYSINT register: %d\n", err);
return IRQ_NONE;
}
if (reg_val & AW86927_SYSINT_BST_SCPI)
dev_err(dev, "Received a Short Circuit Protection interrupt\n");
if (reg_val & AW86927_SYSINT_BST_OVPI)
dev_err(dev, "Received an Over Voltage Protection interrupt\n");
if (reg_val & AW86927_SYSINT_UVLI)
dev_err(dev, "Received an Under Voltage Lock Out interrupt\n");
if (reg_val & AW86927_SYSINT_OCDI)
dev_err(dev, "Received an Over Current interrupt\n");
if (reg_val & AW86927_SYSINT_OTI)
dev_err(dev, "Received an Over Temperature interrupt\n");
if (reg_val & AW86927_SYSINT_DONEI)
dev_dbg(dev, "Chip playback done!\n");
if (reg_val & AW86927_SYSINT_FF_AFI)
dev_dbg(dev, "The RTP mode FIFO is almost full!\n");
if (reg_val & AW86927_SYSINT_FF_AEI)
dev_dbg(dev, "The RTP mode FIFO is almost empty!\n");
return IRQ_HANDLED;
}
static int aw86927_detect(struct aw86927_data *haptics)
{
__be16 read_buf;
u16 chip_id;
int err;
err = regmap_bulk_read(haptics->regmap, AW86927_CHIPIDH_REG, &read_buf, 2);
if (err)
return dev_err_probe(haptics->dev, err, "Failed to read CHIPID registers\n");
chip_id = be16_to_cpu(read_buf);
if (chip_id != AW86927_CHIPID) {
dev_err(haptics->dev, "Unexpected CHIPID value 0x%x\n", chip_id);
return -ENODEV;
}
return 0;
}
static int aw86927_probe(struct i2c_client *client)
{
struct aw86927_data *haptics;
int err;
haptics = devm_kzalloc(&client->dev, sizeof(struct aw86927_data), GFP_KERNEL);
if (!haptics)
return -ENOMEM;
haptics->dev = &client->dev;
haptics->client = client;
i2c_set_clientdata(client, haptics);
haptics->regmap = devm_regmap_init_i2c(client, &aw86927_regmap_config);
if (IS_ERR(haptics->regmap))
return dev_err_probe(haptics->dev, PTR_ERR(haptics->regmap),
"Failed to allocate register map\n");
haptics->input_dev = devm_input_allocate_device(haptics->dev);
if (!haptics->input_dev)
return -ENOMEM;
haptics->reset_gpio = devm_gpiod_get(haptics->dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(haptics->reset_gpio))
return dev_err_probe(haptics->dev, PTR_ERR(haptics->reset_gpio),
"Failed to get reset gpio\n");
/* Hardware reset */
aw86927_hw_reset(haptics);
/* Software reset */
err = regmap_write(haptics->regmap, AW86927_RSTCFG_REG, AW86927_RSTCFG_SOFTRST);
if (err)
return dev_err_probe(haptics->dev, err, "Failed Software reset\n");
/* Wait ~3ms until I2C is accessible */
usleep_range(3000, 3500);
err = aw86927_detect(haptics);
if (err)
return dev_err_probe(haptics->dev, err, "Failed to find chip\n");
/* IRQ config */
err = regmap_write(haptics->regmap, AW86927_SYSCTRL4_REG,
FIELD_PREP(AW86927_SYSCTRL4_INT_MODE_MASK,
AW86927_SYSCTRL4_INT_MODE_EDGE) |
FIELD_PREP(AW86927_SYSCTRL4_INT_EDGE_MODE_MASK,
AW86927_SYSCTRL4_INT_EDGE_MODE_POS));
if (err)
return dev_err_probe(haptics->dev, err, "Failed to configure interrupt modes\n");
err = regmap_write(haptics->regmap, AW86927_SYSINTM_REG,
AW86927_SYSINTM_BST_OVPM |
AW86927_SYSINTM_FF_AEM |
AW86927_SYSINTM_FF_AFM |
AW86927_SYSINTM_DONEM);
if (err)
return dev_err_probe(haptics->dev, err, "Failed to configure interrupt masks\n");
err = devm_request_threaded_irq(haptics->dev, client->irq, NULL,
aw86927_irq, IRQF_ONESHOT, NULL, haptics);
if (err)
return dev_err_probe(haptics->dev, err, "Failed to request threaded irq\n");
INIT_WORK(&haptics->play_work, aw86927_haptics_play_work);
haptics->input_dev->name = "aw86927-haptics";
haptics->input_dev->close = aw86927_close;
input_set_drvdata(haptics->input_dev, haptics);
input_set_capability(haptics->input_dev, EV_FF, FF_RUMBLE);
err = input_ff_create_memless(haptics->input_dev, NULL, aw86927_haptics_play);
if (err)
return dev_err_probe(haptics->dev, err, "Failed to create FF dev\n");
/* Set up registers */
err = aw86927_play_mode(haptics, AW86927_STANDBY_MODE);
if (err)
return dev_err_probe(haptics->dev, err,
"Failed to enter standby for Haptic init\n");
err = aw86927_haptic_init(haptics);
if (err)
return dev_err_probe(haptics->dev, err, "Haptic init failed\n");
/* RAM init, upload the waveform for playback */
err = aw86927_ram_init(haptics);
if (err)
return dev_err_probe(haptics->dev, err, "Failed to init aw86927 sram\n");
err = input_register_device(haptics->input_dev);
if (err)
return dev_err_probe(haptics->dev, err, "Failed to register input device\n");
return 0;
}
static const struct of_device_id aw86927_of_id[] = {
{ .compatible = "awinic,aw86927" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, aw86927_of_id);
static struct i2c_driver aw86927_driver = {
.driver = {
.name = "aw86927-haptics",
.of_match_table = aw86927_of_id,
},
.probe = aw86927_probe,
};
module_i2c_driver(aw86927_driver);
MODULE_AUTHOR("Griffin Kroah-Hartman <griffin.kroah@fairphone.com>");
MODULE_DESCRIPTION("AWINIC AW86927 LRA Haptic Driver");
MODULE_LICENSE("GPL");
+1
View File
@@ -6,6 +6,7 @@
* Author: Hemanth V <hemanthv@ti.com>
*/
#include <linux/export.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+10 -2
View File
@@ -60,6 +60,7 @@ struct pm8941_data {
bool supports_ps_hold_poff_config;
bool supports_debounce_config;
bool has_pon_pbs;
bool wakeup_source_default;
const char *name;
const char *phys;
};
@@ -245,7 +246,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(pm8941_pwr_key_pm_ops,
static int pm8941_pwrkey_probe(struct platform_device *pdev)
{
struct pm8941_pwrkey *pwrkey;
bool pull_up;
bool pull_up, wakeup;
struct device *parent;
struct device_node *regmap_node;
const __be32 *addr;
@@ -402,8 +403,11 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
}
}
wakeup = pwrkey->data->wakeup_source_default ||
of_property_read_bool(pdev->dev.of_node, "wakeup-source");
platform_set_drvdata(pdev, pwrkey);
device_init_wakeup(&pdev->dev, 1);
device_init_wakeup(&pdev->dev, wakeup);
return 0;
}
@@ -424,6 +428,7 @@ static const struct pm8941_data pwrkey_data = {
.supports_ps_hold_poff_config = true,
.supports_debounce_config = true,
.has_pon_pbs = false,
.wakeup_source_default = true,
};
static const struct pm8941_data resin_data = {
@@ -434,6 +439,7 @@ static const struct pm8941_data resin_data = {
.supports_ps_hold_poff_config = true,
.supports_debounce_config = true,
.has_pon_pbs = false,
.wakeup_source_default = false,
};
static const struct pm8941_data pon_gen3_pwrkey_data = {
@@ -443,6 +449,7 @@ static const struct pm8941_data pon_gen3_pwrkey_data = {
.supports_ps_hold_poff_config = false,
.supports_debounce_config = false,
.has_pon_pbs = true,
.wakeup_source_default = true,
};
static const struct pm8941_data pon_gen3_resin_data = {
@@ -452,6 +459,7 @@ static const struct pm8941_data pon_gen3_resin_data = {
.supports_ps_hold_poff_config = false,
.supports_debounce_config = false,
.has_pon_pbs = true,
.wakeup_source_default = false,
};
static const struct of_device_id pm8941_pwr_key_id_table[] = {
+1
View File
@@ -775,6 +775,7 @@ static int uinput_ff_upload_to_user(char __user *buffer,
if (in_compat_syscall()) {
struct uinput_ff_upload_compat ff_up_compat;
memset(&ff_up_compat, 0, sizeof(ff_up_compat));
ff_up_compat.request_id = ff_up->request_id;
ff_up_compat.retval = ff_up->retval;
/*
+1
View File
@@ -4,6 +4,7 @@
* Copyright (c) 2011 Unixphere
*/
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/of.h>
+3
View File
@@ -7,6 +7,9 @@
#ifndef _RMI_2D_SENSOR_H
#define _RMI_2D_SENSOR_H
#include <linux/rmi.h>
#include <linux/types.h>
enum rmi_2d_sensor_object_type {
RMI_2D_OBJECT_NONE,
RMI_2D_OBJECT_FINGER,
+1
View File
@@ -4,6 +4,7 @@
* Copyright (c) 2011 Unixphere
*/
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/irq.h>
+1
View File
@@ -21,6 +21,7 @@
#include <linux/irqdomain.h>
#include <uapi/linux/input.h>
#include <linux/rmi.h>
#include <linux/export.h>
#include "rmi_bus.h"
#include "rmi_driver.h"
Loaded 100 of 509 files, more files were not shown because too many files have changed in this diff. Show more