* Re: [PATCH v2] Input: mms114 - drop platform data and use generic APIs
From: Dmitry Torokhov @ 2018-01-24 19:37 UTC (permalink / raw)
To: Simon Shields
Cc: Andi Shyti, linux-input-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring
In-Reply-To: <20180113020456.12391-1-simon-WP75azK+jQYgsBAKwltoeQ@public.gmane.org>
On Sat, Jan 13, 2018 at 01:04:56PM +1100, Simon Shields wrote:
> The MMS114 platform data has no in-tree users, so drop it,
> and make the driver depend on CONFIG_OF.
>
> Switch to using the standard touchscreen properties via
> touchscreen_parse_properties(), and move the old DT parsing code
> to use device_property_*() APIs.
>
> Finally, use touchscreen_report_pos to report x/y coordinates
> and drop the custom x/y inversion code.
>
> Signed-off-by: Simon Shields <simon-WP75azK+jQYgsBAKwltoeQ@public.gmane.org>
> ---
> .../bindings/input/touchscreen/mms114.txt | 29 ++--
> drivers/input/touchscreen/Kconfig | 1 +
> drivers/input/touchscreen/mms114.c | 152 +++++++++------------
> include/linux/platform_data/mms114.h | 24 ----
> 4 files changed, 83 insertions(+), 123 deletions(-)
> delete mode 100644 include/linux/platform_data/mms114.h
>
> diff --git a/Documentation/devicetree/bindings/input/touchscreen/mms114.txt b/Documentation/devicetree/bindings/input/touchscreen/mms114.txt
> index 89d4c56c5671..8f9f9f38eff4 100644
> --- a/Documentation/devicetree/bindings/input/touchscreen/mms114.txt
> +++ b/Documentation/devicetree/bindings/input/touchscreen/mms114.txt
> @@ -4,14 +4,18 @@ Required properties:
> - compatible: must be "melfas,mms114"
> - reg: I2C address of the chip
> - interrupts: interrupt to which the chip is connected
> -- x-size: horizontal resolution of touchscreen
> -- y-size: vertical resolution of touchscreen
> +- touchscreen-size-x: See [1]
> +- touchscreen-size-y: See [1]
>
> Optional properties:
> -- contact-threshold:
> -- moving-threshold:
> -- x-invert: invert X axis
> -- y-invert: invert Y axis
> +- touchscreen-fuzz-x: See [1]
> +- touchscreen-fuzz-y: See [1]
> +- touchscreen-fuzz-pressure: See [1]
> +- touchscreen-inverted-x: See [1]
> +- touchscreen-inverted-y: See [1]
> +- touchscreen-swapped-x-y: See [1]
> +
> +[1]: Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt
>
> Example:
>
> @@ -22,12 +26,13 @@ Example:
> compatible = "melfas,mms114";
> reg = <0x48>;
> interrupts = <39 0>;
> - x-size = <720>;
> - y-size = <1280>;
> - contact-threshold = <10>;
> - moving-threshold = <10>;
> - x-invert;
> - y-invert;
> + touchscreen-size-x = <720>;
> + touchscreen-size-y = <1280>;
> + touchscreen-fuzz-x = <10>;
> + touchscreen-fuzz-y = <10>;
> + touchscreen-fuzz-pressure = <10>;
> + touchscreen-inverted-x;
> + touchscreen-inverted-y;
> };
>
> /* ... */
> diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
> index 38a226f9fcbd..f7ea5522ef91 100644
> --- a/drivers/input/touchscreen/Kconfig
> +++ b/drivers/input/touchscreen/Kconfig
> @@ -524,6 +524,7 @@ config TOUCHSCREEN_MCS5000
> config TOUCHSCREEN_MMS114
> tristate "MELFAS MMS114 touchscreen"
> depends on I2C
> + depends on OF
There is no need for that, with generic device properties we can use it
with ACPI or static board files.
> help
> Say Y here if you have the MELFAS MMS114 touchscreen controller
> chip in your system.
> diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
> index e5eeb6311f7d..6276a3387cd4 100644
> --- a/drivers/input/touchscreen/mms114.c
> +++ b/drivers/input/touchscreen/mms114.c
> @@ -12,8 +12,8 @@
> #include <linux/of.h>
> #include <linux/i2c.h>
> #include <linux/input/mt.h>
> +#include <linux/input/touchscreen.h>
> #include <linux/interrupt.h>
> -#include <linux/platform_data/mms114.h>
> #include <linux/regulator/consumer.h>
> #include <linux/slab.h>
>
> @@ -55,7 +55,9 @@ struct mms114_data {
> struct input_dev *input_dev;
> struct regulator *core_reg;
> struct regulator *io_reg;
> - const struct mms114_platform_data *pdata;
> + struct touchscreen_properties props;
> + unsigned int contact_threshold;
> + unsigned int moving_threshold;
>
> /* Use cache data for mode control register(write only) */
> u8 cache_mode_control;
> @@ -143,7 +145,6 @@ static int mms114_write_reg(struct mms114_data *data, unsigned int reg,
>
> static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *touch)
> {
> - const struct mms114_platform_data *pdata = data->pdata;
> struct i2c_client *client = data->client;
> struct input_dev *input_dev = data->input_dev;
> unsigned int id;
> @@ -163,16 +164,6 @@ static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *tou
> id = touch->id - 1;
> x = touch->x_lo | touch->x_hi << 8;
> y = touch->y_lo | touch->y_hi << 8;
> - if (x > pdata->x_size || y > pdata->y_size) {
> - dev_dbg(&client->dev,
> - "Wrong touch coordinates (%d, %d)\n", x, y);
> - return;
> - }
> -
> - if (pdata->x_invert)
> - x = pdata->x_size - x;
> - if (pdata->y_invert)
> - y = pdata->y_size - y;
>
> dev_dbg(&client->dev,
> "id: %d, type: %d, pressed: %d, x: %d, y: %d, width: %d, strength: %d\n",
> @@ -183,9 +174,8 @@ static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *tou
> input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, touch->pressed);
>
> if (touch->pressed) {
> + touchscreen_report_pos(input_dev, &data->props, x, y, true);
> input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, touch->width);
> - input_report_abs(input_dev, ABS_MT_POSITION_X, x);
> - input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
> input_report_abs(input_dev, ABS_MT_PRESSURE, touch->strength);
> }
> }
> @@ -263,7 +253,7 @@ static int mms114_get_version(struct mms114_data *data)
>
> static int mms114_setup_regs(struct mms114_data *data)
> {
> - const struct mms114_platform_data *pdata = data->pdata;
> + const struct touchscreen_properties *props = &data->props;
> int val;
> int error;
>
> @@ -275,32 +265,32 @@ static int mms114_setup_regs(struct mms114_data *data)
> if (error < 0)
> return error;
>
> - val = (pdata->x_size >> 8) & 0xf;
> - val |= ((pdata->y_size >> 8) & 0xf) << 4;
> + val = (props->max_x >> 8) & 0xf;
> + val |= ((props->max_y >> 8) & 0xf) << 4;
> error = mms114_write_reg(data, MMS114_XY_RESOLUTION_H, val);
> if (error < 0)
> return error;
>
> - val = pdata->x_size & 0xff;
> + val = props->max_x & 0xff;
> error = mms114_write_reg(data, MMS114_X_RESOLUTION, val);
> if (error < 0)
> return error;
>
> - val = pdata->y_size & 0xff;
> + val = props->max_x & 0xff;
> error = mms114_write_reg(data, MMS114_Y_RESOLUTION, val);
> if (error < 0)
> return error;
>
> - if (pdata->contact_threshold) {
> + if (data->contact_threshold) {
> error = mms114_write_reg(data, MMS114_CONTACT_THRESHOLD,
> - pdata->contact_threshold);
> + data->contact_threshold);
> if (error < 0)
> return error;
> }
>
> - if (pdata->moving_threshold) {
> + if (data->moving_threshold) {
> error = mms114_write_reg(data, MMS114_MOVING_THRESHOLD,
> - pdata->moving_threshold);
> + data->moving_threshold);
> if (error < 0)
> return error;
> }
> @@ -335,9 +325,6 @@ static int mms114_start(struct mms114_data *data)
> return error;
> }
>
> - if (data->pdata->cfg_pin)
> - data->pdata->cfg_pin(true);
> -
> enable_irq(client->irq);
>
> return 0;
> @@ -350,9 +337,6 @@ static void mms114_stop(struct mms114_data *data)
>
> disable_irq(client->irq);
>
> - if (data->pdata->cfg_pin)
> - data->pdata->cfg_pin(false);
> -
> error = regulator_disable(data->io_reg);
> if (error)
> dev_warn(&client->dev, "Failed to disable vdd: %d\n", error);
> @@ -376,67 +360,43 @@ static void mms114_input_close(struct input_dev *dev)
> mms114_stop(data);
> }
>
> -#ifdef CONFIG_OF
> -static struct mms114_platform_data *mms114_parse_dt(struct device *dev)
> +static int mms114_parse_dt(struct mms114_data *data)
> {
> - struct mms114_platform_data *pdata;
> - struct device_node *np = dev->of_node;
> -
> - if (!np)
> - return NULL;
> + struct device *dev = &data->client->dev;
> + struct touchscreen_properties *props = &data->props;
>
> - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
> - if (!pdata) {
> - dev_err(dev, "failed to allocate platform data\n");
> - return NULL;
> + if (device_property_read_u32(dev, "x-size", &props->max_x)) {
> + dev_dbg(dev, "failed to get legacy x-size property\n");
> + return -EINVAL;
> }
>
> - if (of_property_read_u32(np, "x-size", &pdata->x_size)) {
> - dev_err(dev, "failed to get x-size property\n");
> - return NULL;
> + if (device_property_read_u32(dev, "y-size", &props->max_y)) {
> + dev_dbg(dev, "failed to get legacy y-size property\n");
> + return -EINVAL;
> }
>
> - if (of_property_read_u32(np, "y-size", &pdata->y_size)) {
> - dev_err(dev, "failed to get y-size property\n");
> - return NULL;
> - }
> + device_property_read_u32(dev, "contact-threshold",
> + &data->contact_threshold);
> + device_property_read_u32(dev, "moving-threshold",
> + &data->moving_threshold);
>
> - of_property_read_u32(np, "contact-threshold",
> - &pdata->contact_threshold);
> - of_property_read_u32(np, "moving-threshold",
> - &pdata->moving_threshold);
> + if (device_property_read_bool(dev, "x-invert"))
> + props->invert_x = true;
> + if (device_property_read_bool(dev, "y-invert"))
> + props->invert_y = true;
>
> - if (of_find_property(np, "x-invert", NULL))
> - pdata->x_invert = true;
> - if (of_find_property(np, "y-invert", NULL))
> - pdata->y_invert = true;
> + props->swap_x_y = false;
>
> - return pdata;
> -}
> -#else
> -static inline struct mms114_platform_data *mms114_parse_dt(struct device *dev)
> -{
> - return NULL;
> + return 0;
> }
> -#endif
>
> static int mms114_probe(struct i2c_client *client,
> const struct i2c_device_id *id)
> {
> - const struct mms114_platform_data *pdata;
> struct mms114_data *data;
> struct input_dev *input_dev;
> int error;
>
> - pdata = dev_get_platdata(&client->dev);
> - if (!pdata)
> - pdata = mms114_parse_dt(&client->dev);
> -
> - if (!pdata) {
> - dev_err(&client->dev, "Need platform data\n");
> - return -EINVAL;
> - }
> -
> if (!i2c_check_functionality(client->adapter,
> I2C_FUNC_PROTOCOL_MANGLING)) {
> dev_err(&client->dev,
> @@ -453,8 +413,39 @@ static int mms114_probe(struct i2c_client *client,
> }
>
> data->client = client;
> +
> + input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
> + input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X);
> + input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y);
> + input_set_capability(input_dev, EV_ABS, ABS_MT_PRESSURE);
> + input_set_capability(input_dev, EV_ABS, ABS_MT_TOUCH_MAJOR);
> +
> + input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
> +
> + if (mms114_parse_dt(data) < 0) {
> + /* No valid legacy binding found, try the common one */
> + touchscreen_parse_properties(input_dev, true, &data->props);
My preference would be going in the other direction: try the newer
binding first, fall back to legacy.
I have a couple more changes ot the driver, I'll post them and the
updated version of your patch as well.
Thanks.
--
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 2/4] Input: mms114 - mark as direct input device
From: Dmitry Torokhov @ 2018-01-24 19:38 UTC (permalink / raw)
To: Simon Shields, Andi Shyti; +Cc: Rob Herring, linux-input, linux-kernel
In-Reply-To: <20180124193804.155654-1-dmitry.torokhov@gmail.com>
mms14 is a touchscreen and thus a direct input device; let's mark it
as such. This also allows us to drop some initialization code as
input_init_mt_slots() will do that for us.
Also add error handling for input_mt_init_slots().
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/touchscreen/mms114.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index 92f2e9da351f1..c3480db5d21ed 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -462,14 +462,6 @@ static int mms114_probe(struct i2c_client *client,
input_dev->open = mms114_input_open;
input_dev->close = mms114_input_close;
- __set_bit(EV_ABS, input_dev->evbit);
- __set_bit(EV_KEY, input_dev->evbit);
- __set_bit(BTN_TOUCH, input_dev->keybit);
- input_set_abs_params(input_dev, ABS_X, 0, data->pdata->x_size, 0, 0);
- input_set_abs_params(input_dev, ABS_Y, 0, data->pdata->y_size, 0, 0);
-
- /* For multi touch */
- input_mt_init_slots(input_dev, MMS114_MAX_TOUCH, 0);
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
0, MMS114_MAX_AREA, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
@@ -478,6 +470,11 @@ static int mms114_probe(struct i2c_client *client,
0, data->pdata->y_size, 0, 0);
input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
+ error = input_mt_init_slots(input_dev, MMS114_MAX_TOUCH,
+ INPUT_MT_DIRECT);
+ if (error)
+ return error;
+
input_set_drvdata(input_dev, data);
i2c_set_clientdata(client, data);
--
2.16.0.rc1.238.g530d649a79-goog
^ permalink raw reply related
* [PATCH 3/4] Input: mms114 - drop platform data and use generic APIs
From: Dmitry Torokhov @ 2018-01-24 19:38 UTC (permalink / raw)
To: Simon Shields, Andi Shyti; +Cc: Rob Herring, linux-input, linux-kernel
In-Reply-To: <20180124193804.155654-1-dmitry.torokhov@gmail.com>
From: Simon Shields <simon@lineageos.org>
The MMS114 platform data has no in-tree users, so drop it.
Switch to using the standard touchscreen properties via
touchscreen_parse_properties(), and move the old DT parsing code
to use device_property_*() APIs.
Finally, use touchscreen_report_pos to report x/y coordinates
and drop the custom x/y inversion code.
Signed-off-by: Simon Shields <simon@lineageos.org>
Reviewed-by: Rob Herring <robh@kernel.org>
Patchwork-Id: 10162101
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
.../bindings/input/touchscreen/mms114.txt | 29 ++--
drivers/input/touchscreen/mms114.c | 147 +++++++++------------
include/linux/platform_data/mms114.h | 24 ----
3 files changed, 82 insertions(+), 118 deletions(-)
delete mode 100644 include/linux/platform_data/mms114.h
diff --git a/Documentation/devicetree/bindings/input/touchscreen/mms114.txt b/Documentation/devicetree/bindings/input/touchscreen/mms114.txt
index 89d4c56c56711..8f9f9f38eff4a 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/mms114.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/mms114.txt
@@ -4,14 +4,18 @@ Required properties:
- compatible: must be "melfas,mms114"
- reg: I2C address of the chip
- interrupts: interrupt to which the chip is connected
-- x-size: horizontal resolution of touchscreen
-- y-size: vertical resolution of touchscreen
+- touchscreen-size-x: See [1]
+- touchscreen-size-y: See [1]
Optional properties:
-- contact-threshold:
-- moving-threshold:
-- x-invert: invert X axis
-- y-invert: invert Y axis
+- touchscreen-fuzz-x: See [1]
+- touchscreen-fuzz-y: See [1]
+- touchscreen-fuzz-pressure: See [1]
+- touchscreen-inverted-x: See [1]
+- touchscreen-inverted-y: See [1]
+- touchscreen-swapped-x-y: See [1]
+
+[1]: Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt
Example:
@@ -22,12 +26,13 @@ Example:
compatible = "melfas,mms114";
reg = <0x48>;
interrupts = <39 0>;
- x-size = <720>;
- y-size = <1280>;
- contact-threshold = <10>;
- moving-threshold = <10>;
- x-invert;
- y-invert;
+ touchscreen-size-x = <720>;
+ touchscreen-size-y = <1280>;
+ touchscreen-fuzz-x = <10>;
+ touchscreen-fuzz-y = <10>;
+ touchscreen-fuzz-pressure = <10>;
+ touchscreen-inverted-x;
+ touchscreen-inverted-y;
};
/* ... */
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index c3480db5d21ed..69e4288bf8aa3 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -12,8 +12,8 @@
#include <linux/of.h>
#include <linux/i2c.h>
#include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
#include <linux/interrupt.h>
-#include <linux/platform_data/mms114.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
@@ -55,7 +55,9 @@ struct mms114_data {
struct input_dev *input_dev;
struct regulator *core_reg;
struct regulator *io_reg;
- const struct mms114_platform_data *pdata;
+ struct touchscreen_properties props;
+ unsigned int contact_threshold;
+ unsigned int moving_threshold;
/* Use cache data for mode control register(write only) */
u8 cache_mode_control;
@@ -143,7 +145,6 @@ static int mms114_write_reg(struct mms114_data *data, unsigned int reg,
static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *touch)
{
- const struct mms114_platform_data *pdata = data->pdata;
struct i2c_client *client = data->client;
struct input_dev *input_dev = data->input_dev;
unsigned int id;
@@ -163,16 +164,6 @@ static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *tou
id = touch->id - 1;
x = touch->x_lo | touch->x_hi << 8;
y = touch->y_lo | touch->y_hi << 8;
- if (x > pdata->x_size || y > pdata->y_size) {
- dev_dbg(&client->dev,
- "Wrong touch coordinates (%d, %d)\n", x, y);
- return;
- }
-
- if (pdata->x_invert)
- x = pdata->x_size - x;
- if (pdata->y_invert)
- y = pdata->y_size - y;
dev_dbg(&client->dev,
"id: %d, type: %d, pressed: %d, x: %d, y: %d, width: %d, strength: %d\n",
@@ -183,9 +174,8 @@ static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *tou
input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, touch->pressed);
if (touch->pressed) {
+ touchscreen_report_pos(input_dev, &data->props, x, y, true);
input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, touch->width);
- input_report_abs(input_dev, ABS_MT_POSITION_X, x);
- input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
input_report_abs(input_dev, ABS_MT_PRESSURE, touch->strength);
}
}
@@ -263,7 +253,7 @@ static int mms114_get_version(struct mms114_data *data)
static int mms114_setup_regs(struct mms114_data *data)
{
- const struct mms114_platform_data *pdata = data->pdata;
+ const struct touchscreen_properties *props = &data->props;
int val;
int error;
@@ -275,32 +265,32 @@ static int mms114_setup_regs(struct mms114_data *data)
if (error < 0)
return error;
- val = (pdata->x_size >> 8) & 0xf;
- val |= ((pdata->y_size >> 8) & 0xf) << 4;
+ val = (props->max_x >> 8) & 0xf;
+ val |= ((props->max_y >> 8) & 0xf) << 4;
error = mms114_write_reg(data, MMS114_XY_RESOLUTION_H, val);
if (error < 0)
return error;
- val = pdata->x_size & 0xff;
+ val = props->max_x & 0xff;
error = mms114_write_reg(data, MMS114_X_RESOLUTION, val);
if (error < 0)
return error;
- val = pdata->y_size & 0xff;
+ val = props->max_x & 0xff;
error = mms114_write_reg(data, MMS114_Y_RESOLUTION, val);
if (error < 0)
return error;
- if (pdata->contact_threshold) {
+ if (data->contact_threshold) {
error = mms114_write_reg(data, MMS114_CONTACT_THRESHOLD,
- pdata->contact_threshold);
+ data->contact_threshold);
if (error < 0)
return error;
}
- if (pdata->moving_threshold) {
+ if (data->moving_threshold) {
error = mms114_write_reg(data, MMS114_MOVING_THRESHOLD,
- pdata->moving_threshold);
+ data->moving_threshold);
if (error < 0)
return error;
}
@@ -335,9 +325,6 @@ static int mms114_start(struct mms114_data *data)
return error;
}
- if (data->pdata->cfg_pin)
- data->pdata->cfg_pin(true);
-
enable_irq(client->irq);
return 0;
@@ -350,9 +337,6 @@ static void mms114_stop(struct mms114_data *data)
disable_irq(client->irq);
- if (data->pdata->cfg_pin)
- data->pdata->cfg_pin(false);
-
error = regulator_disable(data->io_reg);
if (error)
dev_warn(&client->dev, "Failed to disable vdd: %d\n", error);
@@ -376,67 +360,43 @@ static void mms114_input_close(struct input_dev *dev)
mms114_stop(data);
}
-#ifdef CONFIG_OF
-static struct mms114_platform_data *mms114_parse_dt(struct device *dev)
+static int mms114_parse_legacy_bindings(struct mms114_data *data)
{
- struct mms114_platform_data *pdata;
- struct device_node *np = dev->of_node;
-
- if (!np)
- return NULL;
+ struct device *dev = &data->client->dev;
+ struct touchscreen_properties *props = &data->props;
- pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata) {
- dev_err(dev, "failed to allocate platform data\n");
- return NULL;
+ if (device_property_read_u32(dev, "x-size", &props->max_x)) {
+ dev_dbg(dev, "failed to get legacy x-size property\n");
+ return -EINVAL;
}
- if (of_property_read_u32(np, "x-size", &pdata->x_size)) {
- dev_err(dev, "failed to get x-size property\n");
- return NULL;
+ if (device_property_read_u32(dev, "y-size", &props->max_y)) {
+ dev_dbg(dev, "failed to get legacy y-size property\n");
+ return -EINVAL;
}
- if (of_property_read_u32(np, "y-size", &pdata->y_size)) {
- dev_err(dev, "failed to get y-size property\n");
- return NULL;
- }
+ device_property_read_u32(dev, "contact-threshold",
+ &data->contact_threshold);
+ device_property_read_u32(dev, "moving-threshold",
+ &data->moving_threshold);
- of_property_read_u32(np, "contact-threshold",
- &pdata->contact_threshold);
- of_property_read_u32(np, "moving-threshold",
- &pdata->moving_threshold);
+ if (device_property_read_bool(dev, "x-invert"))
+ props->invert_x = true;
+ if (device_property_read_bool(dev, "y-invert"))
+ props->invert_y = true;
- if (of_find_property(np, "x-invert", NULL))
- pdata->x_invert = true;
- if (of_find_property(np, "y-invert", NULL))
- pdata->y_invert = true;
+ props->swap_x_y = false;
- return pdata;
-}
-#else
-static inline struct mms114_platform_data *mms114_parse_dt(struct device *dev)
-{
- return NULL;
+ return 0;
}
-#endif
static int mms114_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- const struct mms114_platform_data *pdata;
struct mms114_data *data;
struct input_dev *input_dev;
int error;
- pdata = dev_get_platdata(&client->dev);
- if (!pdata)
- pdata = mms114_parse_dt(&client->dev);
-
- if (!pdata) {
- dev_err(&client->dev, "Need platform data\n");
- return -EINVAL;
- }
-
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_PROTOCOL_MANGLING)) {
dev_err(&client->dev,
@@ -454,7 +414,38 @@ static int mms114_probe(struct i2c_client *client,
data->client = client;
data->input_dev = input_dev;
- data->pdata = pdata;
+
+ input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X);
+ input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y);
+ input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+ 0, MMS114_MAX_AREA, 0, 0);
+
+ touchscreen_parse_properties(input_dev, true, &data->props);
+ if (!data->props.max_x || !data->props.max_y) {
+ dev_dbg(&client->dev,
+ "missing X/Y size properties, trying legacy bindings\n");
+ error = mms114_parse_legacy_bindings(data);
+ if (error)
+ return error;
+
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+ 0, data->props.max_x, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+ 0, data->props.max_y, 0, 0);
+ }
+
+ /*
+ * The firmware handles movement and pressure fuzz, so
+ * don't duplicate that in software.
+ */
+ data->moving_threshold = input_abs_get_fuzz(input_dev,
+ ABS_MT_POSITION_X);
+ data->contact_threshold = input_abs_get_fuzz(input_dev,
+ ABS_MT_PRESSURE);
+ input_abs_set_fuzz(input_dev, ABS_MT_POSITION_X, 0);
+ input_abs_set_fuzz(input_dev, ABS_MT_POSITION_Y, 0);
+ input_abs_set_fuzz(input_dev, ABS_MT_PRESSURE, 0);
input_dev->name = "MELFAS MMS114 Touchscreen";
input_dev->id.bustype = BUS_I2C;
@@ -462,14 +453,6 @@ static int mms114_probe(struct i2c_client *client,
input_dev->open = mms114_input_open;
input_dev->close = mms114_input_close;
- input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
- 0, MMS114_MAX_AREA, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_X,
- 0, data->pdata->x_size, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
- 0, data->pdata->y_size, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
-
error = input_mt_init_slots(input_dev, MMS114_MAX_TOUCH,
INPUT_MT_DIRECT);
if (error)
diff --git a/include/linux/platform_data/mms114.h b/include/linux/platform_data/mms114.h
deleted file mode 100644
index 5722ebfb27382..0000000000000
--- a/include/linux/platform_data/mms114.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundationr
- */
-
-#ifndef __LINUX_MMS114_H
-#define __LINUX_MMS114_H
-
-struct mms114_platform_data {
- unsigned int x_size;
- unsigned int y_size;
- unsigned int contact_threshold;
- unsigned int moving_threshold;
- bool x_invert;
- bool y_invert;
-
- void (*cfg_pin)(bool);
-};
-
-#endif /* __LINUX_MMS114_H */
--
2.16.0.rc1.238.g530d649a79-goog
^ permalink raw reply related
* [PATCH 0/4] MMS114 touchscreen patches
From: Dmitry Torokhov @ 2018-01-24 19:38 UTC (permalink / raw)
To: Simon Shields, Andi Shyti; +Cc: Rob Herring, linux-input, linux-kernel
Hi,
This is a combination of couple of my patches + Simons patches dropping
support for platform data and adding support for mms152, slightly reworked.
Andi, because patches changed a bit I did not add your reviewed-by or
tested-by, please take another look.
Thanks!
Dmitry Torokhov (2):
Input: mms114 - do not clobber interrupt trigger
Input: mms114 - mark as direct input device
Simon Shields (2):
Input: mms114 - drop platform data and use generic APIs
Input: mms114 - add support for mms152
.../bindings/input/touchscreen/mms114.txt | 35 ++--
drivers/input/touchscreen/mms114.c | 229 ++++++++++++---------
include/linux/platform_data/mms114.h | 24 ---
3 files changed, 151 insertions(+), 137 deletions(-)
delete mode 100644 include/linux/platform_data/mms114.h
--
Dmitry
^ permalink raw reply
* [PATCH 1/4] Input: mms114 - do not clobber interrupt trigger
From: Dmitry Torokhov @ 2018-01-24 19:38 UTC (permalink / raw)
To: Simon Shields, Andi Shyti; +Cc: Rob Herring, linux-input, linux-kernel
In-Reply-To: <20180124193804.155654-1-dmitry.torokhov@gmail.com>
Rely on the platform (device tree, ACPI, etc) to properly configure
interrupt trigger/polarity instead of hardcoding the falling edge.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/touchscreen/mms114.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index e5eeb6311f7de..92f2e9da351f1 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -497,9 +497,9 @@ static int mms114_probe(struct i2c_client *client,
return error;
}
- error = devm_request_threaded_irq(&client->dev, client->irq, NULL,
- mms114_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- dev_name(&client->dev), data);
+ error = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, mms114_interrupt, IRQF_ONESHOT,
+ dev_name(&client->dev), data);
if (error) {
dev_err(&client->dev, "Failed to register interrupt\n");
return error;
--
2.16.0.rc1.238.g530d649a79-goog
^ permalink raw reply related
* [PATCH 4/4] Input: mms114 - add support for mms152
From: Dmitry Torokhov @ 2018-01-24 19:38 UTC (permalink / raw)
To: Simon Shields, Andi Shyti; +Cc: Rob Herring, linux-input, linux-kernel
In-Reply-To: <20180124193804.155654-1-dmitry.torokhov@gmail.com>
From: Simon Shields <simon@lineageos.org>
MMS152 has no configuration registers, but the packet format used in
interrupts is identical to mms114.
Signed-off-by: Simon Shields <simon@lineageos.org>
Patchwork-Id: 10125841
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
.../bindings/input/touchscreen/mms114.txt | 6 +-
drivers/input/touchscreen/mms114.c | 89 +++++++++++++++++-----
2 files changed, 74 insertions(+), 21 deletions(-)
diff --git a/Documentation/devicetree/bindings/input/touchscreen/mms114.txt b/Documentation/devicetree/bindings/input/touchscreen/mms114.txt
index 8f9f9f38eff4a..2cd954051d299 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/mms114.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/mms114.txt
@@ -1,7 +1,9 @@
-* MELFAS MMS114 touchscreen controller
+* MELFAS MMS114/MMS152 touchscreen controller
Required properties:
-- compatible: must be "melfas,mms114"
+- compatible: should be one of:
+ - "melfas,mms114"
+ - "melfas,mms152"
- reg: I2C address of the chip
- interrupts: interrupt to which the chip is connected
- touchscreen-size-x: See [1]
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index 69e4288bf8aa3..06d4ce9a3e547 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/i2c.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
@@ -33,6 +34,9 @@
#define MMS114_INFOMATION 0x10
#define MMS114_TSP_REV 0xF0
+#define MMS152_FW_REV 0xE1
+#define MMS152_COMPAT_GROUP 0xF2
+
/* Minimum delay time is 50us between stop and start signal of i2c */
#define MMS114_I2C_DELAY 50
@@ -50,12 +54,18 @@
#define MMS114_TYPE_TOUCHSCREEN 1
#define MMS114_TYPE_TOUCHKEY 2
+enum mms_type {
+ TYPE_MMS114 = 114,
+ TYPE_MMS152 = 152,
+};
+
struct mms114_data {
struct i2c_client *client;
struct input_dev *input_dev;
struct regulator *core_reg;
struct regulator *io_reg;
struct touchscreen_properties props;
+ enum mms_type type;
unsigned int contact_threshold;
unsigned int moving_threshold;
@@ -241,12 +251,28 @@ static int mms114_get_version(struct mms114_data *data)
u8 buf[6];
int error;
- error = __mms114_read_reg(data, MMS114_TSP_REV, 6, buf);
- if (error < 0)
- return error;
+ switch (data->type) {
+ case TYPE_MMS152:
+ error = __mms114_read_reg(data, MMS152_FW_REV, 3, buf);
+ if (error)
+ return error;
+ buf[3] = i2c_smbus_read_byte_data(data->client,
+ MMS152_COMPAT_GROUP);
+ if (buf[3] < 0)
+ return buf[3];
+ dev_info(dev, "TSP FW Rev: bootloader 0x%x / core 0x%x / config 0x%x, Compat group: %c\n",
+ buf[0], buf[1], buf[2], buf[3]);
+ break;
+
+ case TYPE_MMS114:
+ error = __mms114_read_reg(data, MMS114_TSP_REV, 6, buf);
+ if (error)
+ return error;
- dev_info(dev, "TSP Rev: 0x%x, HW Rev: 0x%x, Firmware Ver: 0x%x\n",
- buf[0], buf[1], buf[3]);
+ dev_info(dev, "TSP Rev: 0x%x, HW Rev: 0x%x, Firmware Ver: 0x%x\n",
+ buf[0], buf[1], buf[3]);
+ break;
+ }
return 0;
}
@@ -261,6 +287,10 @@ static int mms114_setup_regs(struct mms114_data *data)
if (error < 0)
return error;
+ /* MMS152 has no configuration or power on registers */
+ if (data->type == TYPE_MMS152)
+ return 0;
+
error = mms114_set_active(data, true);
if (error < 0)
return error;
@@ -395,6 +425,7 @@ static int mms114_probe(struct i2c_client *client,
{
struct mms114_data *data;
struct input_dev *input_dev;
+ const void *match_data;
int error;
if (!i2c_check_functionality(client->adapter,
@@ -415,6 +446,13 @@ static int mms114_probe(struct i2c_client *client,
data->client = client;
data->input_dev = input_dev;
+ /* FIXME: switch to device_get_match_data() when available */
+ match_data = of_device_get_match_data(&client->dev);
+ if (!match_data)
+ return -EINVAL;
+
+ data->type = (enum mms_type)match_data;
+
input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X);
input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y);
input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
@@ -435,19 +473,26 @@ static int mms114_probe(struct i2c_client *client,
0, data->props.max_y, 0, 0);
}
- /*
- * The firmware handles movement and pressure fuzz, so
- * don't duplicate that in software.
- */
- data->moving_threshold = input_abs_get_fuzz(input_dev,
- ABS_MT_POSITION_X);
- data->contact_threshold = input_abs_get_fuzz(input_dev,
- ABS_MT_PRESSURE);
- input_abs_set_fuzz(input_dev, ABS_MT_POSITION_X, 0);
- input_abs_set_fuzz(input_dev, ABS_MT_POSITION_Y, 0);
- input_abs_set_fuzz(input_dev, ABS_MT_PRESSURE, 0);
-
- input_dev->name = "MELFAS MMS114 Touchscreen";
+ if (data->type == TYPE_MMS114) {
+ /*
+ * The firmware handles movement and pressure fuzz, so
+ * don't duplicate that in software.
+ */
+ data->moving_threshold = input_abs_get_fuzz(input_dev,
+ ABS_MT_POSITION_X);
+ data->contact_threshold = input_abs_get_fuzz(input_dev,
+ ABS_MT_PRESSURE);
+ input_abs_set_fuzz(input_dev, ABS_MT_POSITION_X, 0);
+ input_abs_set_fuzz(input_dev, ABS_MT_POSITION_Y, 0);
+ input_abs_set_fuzz(input_dev, ABS_MT_PRESSURE, 0);
+ }
+
+ input_dev->name = devm_kasprintf(&client->dev, GFP_KERNEL,
+ "MELFAS MMS%d Touchscreen",
+ data->type);
+ if (!input_dev->name)
+ return -ENOMEM;
+
input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev;
input_dev->open = mms114_input_open;
@@ -549,7 +594,13 @@ MODULE_DEVICE_TABLE(i2c, mms114_id);
#ifdef CONFIG_OF
static const struct of_device_id mms114_dt_match[] = {
- { .compatible = "melfas,mms114" },
+ {
+ .compatible = "melfas,mms114",
+ .data = (void *)TYPE_MMS114,
+ }, {
+ .compatible = "melfas,mms152",
+ .data = (void *)TYPE_MMS152,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, mms114_dt_match);
--
2.16.0.rc1.238.g530d649a79-goog
^ permalink raw reply related
* [PATCH 0/2] Input-appletouch: Adjustments for two function implementations
From: SF Markus Elfring @ 2018-01-24 19:55 UTC (permalink / raw)
To: linux-input, Arvind Yadav, Dmitry Torokhov; +Cc: LKML, kernel-janitors
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Wed, 24 Jan 2018 20:50:20 +0100
Two update suggestions were taken into account
from static source code analysis.
Markus Elfring (2):
Delete an error message for a failed memory allocation in atp_geyser_init()
Improve a size determination in atp_probe()
drivers/input/mouse/appletouch.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
--
2.16.1
^ permalink raw reply
* [PATCH 1/2] Input: appletouch: Delete an error message for a failed memory allocation in atp_geyser_init()
From: SF Markus Elfring @ 2018-01-24 19:56 UTC (permalink / raw)
To: linux-input, Arvind Yadav, Dmitry Torokhov; +Cc: LKML, kernel-janitors
In-Reply-To: <a86a6a93-21eb-4571-465c-24d4c0687965@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Wed, 24 Jan 2018 20:40:54 +0100
Omit an extra message for a memory allocation failure in this function.
This issue was detected by using the Coccinelle software.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/input/mouse/appletouch.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c
index 81a695d0b4e0..3a709d21ea93 100644
--- a/drivers/input/mouse/appletouch.c
+++ b/drivers/input/mouse/appletouch.c
@@ -280,10 +280,8 @@ static int atp_geyser_init(struct atp *dev)
int ret;
data = kmalloc(8, GFP_KERNEL);
- if (!data) {
- dev_err(&dev->intf->dev, "Out of memory\n");
+ if (!data)
return -ENOMEM;
- }
size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
ATP_GEYSER_MODE_READ_REQUEST_ID,
--
2.16.1
^ permalink raw reply related
* [PATCH 2/2] Input: appletouch: Improve a size determination in atp_probe()
From: SF Markus Elfring @ 2018-01-24 19:57 UTC (permalink / raw)
To: linux-input, Arvind Yadav, Dmitry Torokhov
In-Reply-To: <a86a6a93-21eb-4571-465c-24d4c0687965@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Wed, 24 Jan 2018 20:46:49 +0100
Replace the specification of a data structure by a pointer dereference
as the parameter for the operator "sizeof" to make the corresponding size
determination a bit safer according to the Linux coding style convention.
This issue was detected by using the Coccinelle software.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/input/mouse/appletouch.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c
index 3a709d21ea93..ea4888693889 100644
--- a/drivers/input/mouse/appletouch.c
+++ b/drivers/input/mouse/appletouch.c
@@ -866,7 +866,7 @@ static int atp_probe(struct usb_interface *iface,
}
/* allocate memory for our device state and initialize it */
- dev = kzalloc(sizeof(struct atp), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
input_dev = input_allocate_device();
if (!dev || !input_dev) {
dev_err(&iface->dev, "Out of memory\n");
--
2.16.1
^ permalink raw reply related
* Re: [PATCH 4/4] Input: mms114 - add support for mms152
From: Marcus Folkesson @ 2018-01-24 20:04 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Simon Shields, Andi Shyti, Rob Herring, linux-input, linux-kernel
In-Reply-To: <20180124193804.155654-5-dmitry.torokhov@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1371 bytes --]
Hello Dmitry,
On Wed, Jan 24, 2018 at 11:38:04AM -0800, Dmitry Torokhov wrote:
> From: Simon Shields <simon@lineageos.org>
>
> @@ -241,12 +251,28 @@ static int mms114_get_version(struct mms114_data *data)
> u8 buf[6];
> int error;
>
> - error = __mms114_read_reg(data, MMS114_TSP_REV, 6, buf);
> - if (error < 0)
> - return error;
> + switch (data->type) {
> + case TYPE_MMS152:
> + error = __mms114_read_reg(data, MMS152_FW_REV, 3, buf);
> + if (error)
> + return error;
> + buf[3] = i2c_smbus_read_byte_data(data->client,
> + MMS152_COMPAT_GROUP);
> + if (buf[3] < 0)
> + return buf[3];
buf is unsigned.
Maybe
error = i2c_smbus_read_byte_data(data->client,
MMS152_COMPAT_GROUP);
if (error < 0)
return error;
Instead?
> + dev_info(dev, "TSP FW Rev: bootloader 0x%x / core 0x%x / config 0x%x, Compat group: %c\n",
> + buf[0], buf[1], buf[2], buf[3]);
> + break;
> +
> + case TYPE_MMS114:
> + error = __mms114_read_reg(data, MMS114_TSP_REV, 6, buf);
> + if (error)
> + return error;
>
> - dev_info(dev, "TSP Rev: 0x%x, HW Rev: 0x%x, Firmware Ver: 0x%x\n",
> - buf[0], buf[1], buf[3]);
> + dev_info(dev, "TSP Rev: 0x%x, HW Rev: 0x%x, Firmware Ver: 0x%x\n",
> + buf[0], buf[1], buf[3]);
> + break;
> + }
>
> return 0;
> }
Best regards
Marcus Folkesson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* [PATCH 0/3] Input-bcm5974: Adjustments for two function implementations
From: SF Markus Elfring @ 2018-01-24 20:29 UTC (permalink / raw)
To: linux-input, Dmitry Torokhov, Henrik Rydberg; +Cc: LKML, kernel-janitors
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Wed, 24 Jan 2018 21:25:24 +0100
Three update suggestions were taken into account
from static source code analysis.
Markus Elfring (3):
Delete an error message for a failed memory allocation
in bcm5974_wellspring_mode()
Return directly after a failed kmalloc() in bcm5974_wellspring_mode()
Improve a size determination in bcm5974_probe()
drivers/input/mouse/bcm5974.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
--
2.16.1
^ permalink raw reply
* [PATCH 1/3] Input: bcm5974: Delete an error message for a failed memory allocation in bcm5974_wellspring_mode()
From: SF Markus Elfring @ 2018-01-24 20:30 UTC (permalink / raw)
To: linux-input, Dmitry Torokhov, Henrik Rydberg; +Cc: LKML, kernel-janitors
In-Reply-To: <0505482c-287f-8809-76e3-960cf45b3c0a@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Wed, 24 Jan 2018 21:09:28 +0100
Omit an extra message for a memory allocation failure in this function.
This issue was detected by using the Coccinelle software.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/input/mouse/bcm5974.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index d0122134f320..994805513df9 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -670,7 +670,6 @@ static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on)
data = kmalloc(c->um_size, GFP_KERNEL);
if (!data) {
- dev_err(&dev->intf->dev, "out of memory\n");
retval = -ENOMEM;
goto out;
}
--
2.16.1
^ permalink raw reply related
* [PATCH 2/3] Input: bcm5974: Return directly after a failed kmalloc() in bcm5974_wellspring_mode()
From: SF Markus Elfring @ 2018-01-24 20:31 UTC (permalink / raw)
To: linux-input, Dmitry Torokhov, Henrik Rydberg; +Cc: LKML, kernel-janitors
In-Reply-To: <0505482c-287f-8809-76e3-960cf45b3c0a@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Wed, 24 Jan 2018 21:14:51 +0100
Return directly after a call of the function "kmalloc" failed
at the beginning.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/input/mouse/bcm5974.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index 994805513df9..685f56c08931 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -669,10 +669,8 @@ static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on)
return 0;
data = kmalloc(c->um_size, GFP_KERNEL);
- if (!data) {
- retval = -ENOMEM;
- goto out;
- }
+ if (!data)
+ return -ENOMEM;
/* read configuration */
size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
--
2.16.1
^ permalink raw reply related
* [PATCH 3/3] Input: bcm5974: Improve a size determination in bcm5974_probe()
From: SF Markus Elfring @ 2018-01-24 20:32 UTC (permalink / raw)
To: linux-input, Dmitry Torokhov, Henrik Rydberg; +Cc: LKML, kernel-janitors
In-Reply-To: <0505482c-287f-8809-76e3-960cf45b3c0a@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Wed, 24 Jan 2018 21:21:11 +0100
Replace the specification of a data structure by a pointer dereference
as the parameter for the operator "sizeof" to make the corresponding size
determination a bit safer according to the Linux coding style convention.
This issue was detected by using the Coccinelle software.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/input/mouse/bcm5974.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index 685f56c08931..c827b31c8530 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -915,7 +915,7 @@ static int bcm5974_probe(struct usb_interface *iface,
cfg = bcm5974_get_config(udev);
/* allocate memory for our device state and initialize it */
- dev = kzalloc(sizeof(struct bcm5974), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
input_dev = input_allocate_device();
if (!dev || !input_dev) {
dev_err(&iface->dev, "out of memory\n");
--
2.16.1
^ permalink raw reply related
* Re: [PATCH] Input: atmel_mxt_ts: Delete error messages for a failed memory allocation in two functions
From: Nick Dyer @ 2018-01-24 20:35 UTC (permalink / raw)
To: SF Markus Elfring; +Cc: linux-input, Dmitry Torokhov, LKML, kernel-janitors
In-Reply-To: <e6d21a83-6628-66f6-d7ce-bb5bf530faf2@users.sourceforge.net>
On Sun, Jan 21, 2018 at 10:33:50PM +0100, SF Markus Elfring wrote:
> Omit extra messages for a memory allocation failure in these functions.
>
> This issue was detected by using the Coccinelle software.
>
> Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
Thanks!
Signed-off-by: Nick Dyer <nick@shmanahar.org>
> ---
> drivers/input/touchscreen/atmel_mxt_ts.c | 9 ++-------
> 1 file changed, 2 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
> index 7659bc48f1db..f38711e9c256 100644
> --- a/drivers/input/touchscreen/atmel_mxt_ts.c
> +++ b/drivers/input/touchscreen/atmel_mxt_ts.c
> @@ -1507,10 +1507,8 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
> MXT_INFO_CHECKSUM_SIZE;
> config_mem_size = data->mem_size - cfg_start_ofs;
> config_mem = kzalloc(config_mem_size, GFP_KERNEL);
> - if (!config_mem) {
> - dev_err(dev, "Failed to allocate memory\n");
> + if (!config_mem)
> return -ENOMEM;
> - }
>
> ret = mxt_prepare_cfg_mem(data, cfg, data_pos, cfg_start_ofs,
> config_mem, config_mem_size);
> @@ -1612,10 +1610,8 @@ static int mxt_get_object_table(struct mxt_data *data)
>
> table_size = data->info.object_num * sizeof(struct mxt_object);
> object_table = kzalloc(table_size, GFP_KERNEL);
> - if (!object_table) {
> - dev_err(&data->client->dev, "Failed to allocate memory\n");
> + if (!object_table)
> return -ENOMEM;
> - }
>
> error = __mxt_read_reg(client, MXT_OBJECT_START, table_size,
> object_table);
> @@ -1714,7 +1710,6 @@ static int mxt_get_object_table(struct mxt_data *data)
> data->msg_buf = kcalloc(data->max_reportid,
> data->T5_msg_size, GFP_KERNEL);
> if (!data->msg_buf) {
> - dev_err(&client->dev, "Failed to allocate message buffer\n");
> error = -ENOMEM;
> goto free_object_table;
> }
> --
> 2.16.0
>
^ permalink raw reply
* Re: [PATCH] input/rmi4: Delete an error message for a failed memory allocation in two functions
From: Nick Dyer @ 2018-01-24 20:36 UTC (permalink / raw)
To: SF Markus Elfring
Cc: linux-input, Andrew Duggan, Benjamin Tissoires,
Christophe Jaillet, Dmitry Torokhov, Lyude Paul, Wei Yongjun,
LKML, kernel-janitors
In-Reply-To: <423a3ec4-eef2-f663-d6b8-9ec9d31ddfc2@users.sourceforge.net>
On Wed, Jan 24, 2018 at 07:28:44PM +0100, SF Markus Elfring wrote:
> Omit an extra message for a memory allocation failure in these functions.
>
> This issue was detected by using the Coccinelle software.
>
> Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
Signed-off-by: Nick Dyer <nick@shmanahar.org>
> ---
> drivers/input/rmi4/rmi_driver.c | 4 +---
> drivers/input/rmi4/rmi_f30.c | 4 +---
> 2 files changed, 2 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
> index 4f2bb5947a4e..6c47e4f3ca7e 100644
> --- a/drivers/input/rmi4/rmi_driver.c
> +++ b/drivers/input/rmi4/rmi_driver.c
> @@ -1060,10 +1060,8 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
>
> size = BITS_TO_LONGS(data->irq_count) * sizeof(unsigned long);
> data->irq_memory = devm_kzalloc(dev, size * 4, GFP_KERNEL);
> - if (!data->irq_memory) {
> - dev_err(dev, "Failed to allocate memory for irq masks.\n");
> + if (!data->irq_memory)
> return -ENOMEM;
> - }
>
> data->irq_status = data->irq_memory + size * 0;
> data->fn_irq_bits = data->irq_memory + size * 1;
> diff --git a/drivers/input/rmi4/rmi_f30.c b/drivers/input/rmi4/rmi_f30.c
> index 82e0f0d43d55..a111ea370c30 100644
> --- a/drivers/input/rmi4/rmi_f30.c
> +++ b/drivers/input/rmi4/rmi_f30.c
> @@ -238,10 +238,8 @@ static int rmi_f30_map_gpios(struct rmi_function *fn,
> button_count,
> sizeof(f30->gpioled_key_map[0]),
> GFP_KERNEL);
> - if (!f30->gpioled_key_map) {
> - dev_err(&fn->dev, "Failed to allocate gpioled map memory.\n");
> + if (!f30->gpioled_key_map)
> return -ENOMEM;
> - }
>
> for (i = 0; i < button_count; i++) {
> if (!rmi_f30_is_valid_button(i, f30->ctrl))
> --
> 2.16.1
>
^ permalink raw reply
* [PATCH 0/2] Input: wm831x-on: Adjustments for wm831x_on_probe()
From: SF Markus Elfring @ 2018-01-24 21:20 UTC (permalink / raw)
To: linux-input, patches, Dmitry Torokhov; +Cc: LKML, kernel-janitors
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Wed, 24 Jan 2018 22:15:43 +0100
Two update suggestions were taken into account
from static source code analysis.
Markus Elfring (2):
Delete an error message for a failed memory allocation
Improve a size determination
drivers/input/misc/wm831x-on.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
--
2.16.1
^ permalink raw reply
* [PATCH 1/2] Input: wm831x-on: Delete an error message for a failed memory allocation in wm831x_on_probe()
From: SF Markus Elfring @ 2018-01-24 21:21 UTC (permalink / raw)
To: linux-input, patches, Dmitry Torokhov; +Cc: LKML, kernel-janitors
In-Reply-To: <e307cfde-58e2-3f4d-ecd7-5c80ace0bb5b@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Wed, 24 Jan 2018 21:55:49 +0100
Omit an extra message for a memory allocation failure in this function.
This issue was detected by using the Coccinelle software.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/input/misc/wm831x-on.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c
index 1b44de265a0a..06f5c4857a0c 100644
--- a/drivers/input/misc/wm831x-on.c
+++ b/drivers/input/misc/wm831x-on.c
@@ -77,10 +77,8 @@ static int wm831x_on_probe(struct platform_device *pdev)
wm831x_on = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_on),
GFP_KERNEL);
- if (!wm831x_on) {
- dev_err(&pdev->dev, "Can't allocate data\n");
+ if (!wm831x_on)
return -ENOMEM;
- }
wm831x_on->wm831x = wm831x;
INIT_DELAYED_WORK(&wm831x_on->work, wm831x_poll_on);
--
2.16.1
^ permalink raw reply related
* [PATCH 2/2] Input: wm831x-on: Improve a size determination in wm831x_on_probe()
From: SF Markus Elfring @ 2018-01-24 21:22 UTC (permalink / raw)
To: linux-input, patches, Dmitry Torokhov; +Cc: LKML, kernel-janitors
In-Reply-To: <e307cfde-58e2-3f4d-ecd7-5c80ace0bb5b@users.sourceforge.net>
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Wed, 24 Jan 2018 21:58:42 +0100
Replace the specification of a data structure by a pointer dereference
as the parameter for the operator "sizeof" to make the corresponding size
determination a bit safer according to the Linux coding style convention.
This issue was detected by using the Coccinelle software.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
drivers/input/misc/wm831x-on.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c
index 06f5c4857a0c..0d8f7a11f63d 100644
--- a/drivers/input/misc/wm831x-on.c
+++ b/drivers/input/misc/wm831x-on.c
@@ -75,8 +75,7 @@ static int wm831x_on_probe(struct platform_device *pdev)
int irq = wm831x_irq(wm831x, platform_get_irq(pdev, 0));
int ret;
- wm831x_on = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_on),
- GFP_KERNEL);
+ wm831x_on = devm_kzalloc(&pdev->dev, sizeof(*wm831x_on), GFP_KERNEL);
if (!wm831x_on)
return -ENOMEM;
--
2.16.1
^ permalink raw reply related
* [PATCH v1] Revert "Input: synaptics_rmi4 - use devm_device_add_group() for attributes in F01"
From: Nick Dyer @ 2018-01-24 21:26 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Benjamin Tissoires, Andrew Duggan, Christopher Heiny, linux-input,
Chris Healy, Lucas Stach, Nick Dyer
Since the sysfs attribute hangs off the RMI bus, which doesn't go away during
firmware flash, it needs to be explictly removed, otherwise we would try and
register the same attribute twice.
This reverts commit 36a44af5c176d619552d99697433261141dd1296.
Signed-off-by: Nick Dyer <nick@shmanahar.org>
---
drivers/input/rmi4/rmi_f01.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/input/rmi4/rmi_f01.c b/drivers/input/rmi4/rmi_f01.c
index ae966e3..8a07ae1 100644
--- a/drivers/input/rmi4/rmi_f01.c
+++ b/drivers/input/rmi4/rmi_f01.c
@@ -570,14 +570,19 @@ static int rmi_f01_probe(struct rmi_function *fn)
dev_set_drvdata(&fn->dev, f01);
- error = devm_device_add_group(&fn->rmi_dev->dev, &rmi_f01_attr_group);
+ error = sysfs_create_group(&fn->rmi_dev->dev.kobj, &rmi_f01_attr_group);
if (error)
- dev_warn(&fn->dev,
- "Failed to create attribute group: %d\n", error);
+ dev_warn(&fn->dev, "Failed to create sysfs group: %d\n", error);
return 0;
}
+static void rmi_f01_remove(struct rmi_function *fn)
+{
+ /* Note that the bus device is used, not the F01 device */
+ sysfs_remove_group(&fn->rmi_dev->dev.kobj, &rmi_f01_attr_group);
+}
+
static int rmi_f01_config(struct rmi_function *fn)
{
struct f01_data *f01 = dev_get_drvdata(&fn->dev);
@@ -717,6 +722,7 @@ struct rmi_function_handler rmi_f01_handler = {
},
.func = 0x01,
.probe = rmi_f01_probe,
+ .remove = rmi_f01_remove,
.config = rmi_f01_config,
.attention = rmi_f01_attention,
.suspend = rmi_f01_suspend,
--
2.7.4
^ permalink raw reply related
* [PATCH v1] Input: synaptics-rmi4 - convert irq distribution to irq_domain
From: Nick Dyer @ 2018-01-24 21:26 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Benjamin Tissoires, Andrew Duggan, Christopher Heiny, linux-input,
Chris Healy, Lucas Stach, Nick Dyer
Convert the RMI driver to use the standard mechanism for
distributing IRQs to the various functions.
Tested on:
* S7300 (F11, F34, F54)
* S7817 (F12, F34, F54)
Signed-off-by: Nick Dyer <nick@shmanahar.org>
---
drivers/input/rmi4/Kconfig | 1 +
drivers/input/rmi4/rmi_bus.c | 13 ++++++++-
drivers/input/rmi4/rmi_bus.h | 3 +-
drivers/input/rmi4/rmi_driver.c | 65 ++++++++++++++++++++---------------------
drivers/input/rmi4/rmi_f01.c | 10 +++----
drivers/input/rmi4/rmi_f03.c | 9 +++---
drivers/input/rmi4/rmi_f11.c | 25 +++++++---------
drivers/input/rmi4/rmi_f12.c | 8 ++---
drivers/input/rmi4/rmi_f30.c | 9 +++---
drivers/input/rmi4/rmi_f34.c | 5 ++--
drivers/input/rmi4/rmi_f54.c | 6 ----
include/linux/rmi.h | 2 ++
12 files changed, 81 insertions(+), 75 deletions(-)
diff --git a/drivers/input/rmi4/Kconfig b/drivers/input/rmi4/Kconfig
index 7172b88..fad2eae 100644
--- a/drivers/input/rmi4/Kconfig
+++ b/drivers/input/rmi4/Kconfig
@@ -3,6 +3,7 @@
#
config RMI4_CORE
tristate "Synaptics RMI4 bus support"
+ select IRQ_DOMAIN
help
Say Y here if you want to support the Synaptics RMI4 bus. This is
required for all RMI4 device support.
diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c
index ae1bffe..ae288d6 100644
--- a/drivers/input/rmi4/rmi_bus.c
+++ b/drivers/input/rmi4/rmi_bus.c
@@ -178,7 +178,18 @@ static int rmi_function_probe(struct device *dev)
if (handler->probe) {
error = handler->probe(fn);
- return error;
+ if (error)
+ return error;
+ }
+
+ if (fn->irq_base && handler->attention) {
+ error = devm_request_threaded_irq(&fn->dev, fn->irq_base, NULL,
+ handler->attention, IRQF_ONESHOT,
+ dev_name(&fn->dev), fn);
+ if (error) {
+ dev_err(dev, "Failed registering IRQ %d\n", error);
+ return error;
+ }
}
return 0;
diff --git a/drivers/input/rmi4/rmi_bus.h b/drivers/input/rmi4/rmi_bus.h
index b7625a9..745a030 100644
--- a/drivers/input/rmi4/rmi_bus.h
+++ b/drivers/input/rmi4/rmi_bus.h
@@ -35,6 +35,7 @@ struct rmi_function {
struct device dev;
struct list_head node;
+ unsigned int irq_base;
unsigned int num_of_irqs;
unsigned int irq_pos;
unsigned long irq_mask[];
@@ -76,7 +77,7 @@ struct rmi_function_handler {
void (*remove)(struct rmi_function *fn);
int (*config)(struct rmi_function *fn);
int (*reset)(struct rmi_function *fn);
- int (*attention)(struct rmi_function *fn, unsigned long *irq_bits);
+ irqreturn_t (*attention)(int irq, void *ctx);
int (*suspend)(struct rmi_function *fn);
int (*resume)(struct rmi_function *fn);
};
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index 141ea22..b7ef1f5a 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -21,6 +21,7 @@
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/of.h>
+#include <linux/irqdomain.h>
#include <uapi/linux/input.h>
#include <linux/rmi.h>
#include "rmi_bus.h"
@@ -127,28 +128,11 @@ static int rmi_driver_process_config_requests(struct rmi_device *rmi_dev)
return 0;
}
-static void process_one_interrupt(struct rmi_driver_data *data,
- struct rmi_function *fn)
-{
- struct rmi_function_handler *fh;
-
- if (!fn || !fn->dev.driver)
- return;
-
- fh = to_rmi_function_handler(fn->dev.driver);
- if (fh->attention) {
- bitmap_and(data->fn_irq_bits, data->irq_status, fn->irq_mask,
- data->irq_count);
- if (!bitmap_empty(data->fn_irq_bits, data->irq_count))
- fh->attention(fn, data->fn_irq_bits);
- }
-}
-
static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
{
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
struct device *dev = &rmi_dev->dev;
- struct rmi_function *entry;
+ int i;
int error;
if (!data)
@@ -173,16 +157,8 @@ static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
*/
mutex_unlock(&data->irq_mutex);
- /*
- * It would be nice to be able to use irq_chip to handle these
- * nested IRQs. Unfortunately, most of the current customers for
- * this driver are using older kernels (3.0.x) that don't support
- * the features required for that. Once they've shifted to more
- * recent kernels (say, 3.3 and higher), this should be switched to
- * use irq_chip.
- */
- list_for_each_entry(entry, &data->function_list, node)
- process_one_interrupt(data, entry);
+ for_each_set_bit(i, data->irq_status, data->irq_count)
+ handle_nested_irq(irq_find_mapping(data->irqdomain, i));
if (data->input)
input_sync(data->input);
@@ -847,6 +823,10 @@ int rmi_initial_reset(struct rmi_device *rmi_dev, void *ctx,
return pdt->page_start == 0 ? RMI_SCAN_CONTINUE : -ENODEV;
}
+static struct irq_chip rmi_irq_chip = {
+ .name = "rmi4",
+};
+
static int rmi_create_function(struct rmi_device *rmi_dev,
void *ctx, const struct pdt_entry *pdt)
{
@@ -878,9 +858,18 @@ static int rmi_create_function(struct rmi_device *rmi_dev,
fn->irq_pos = *current_irq_count;
*current_irq_count += fn->num_of_irqs;
- for (i = 0; i < fn->num_of_irqs; i++)
+ for (i = 0; i < fn->num_of_irqs; i++) {
set_bit(fn->irq_pos + i, fn->irq_mask);
+ fn->irq_base = irq_create_mapping(data->irqdomain,
+ fn->irq_pos + i);
+
+
+ irq_set_chip_data(fn->irq_base, data);
+ irq_set_chip_and_handler(fn->irq_base, &rmi_irq_chip,
+ handle_simple_irq);
+ }
+
error = rmi_register_function(fn);
if (error)
goto err_put_fn;
@@ -1000,9 +989,12 @@ EXPORT_SYMBOL_GPL(rmi_driver_resume);
static int rmi_driver_remove(struct device *dev)
{
struct rmi_device *rmi_dev = to_rmi_device(dev);
+ struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
rmi_disable_irq(rmi_dev, false);
+ irq_domain_remove(data->irqdomain);
+
rmi_f34_remove_sysfs(rmi_dev);
rmi_free_function_list(rmi_dev);
@@ -1034,7 +1026,8 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
{
struct rmi_device *rmi_dev = data->rmi_dev;
struct device *dev = &rmi_dev->dev;
- int irq_count;
+ struct device_node *rmi_of_node = rmi_dev->xport->dev->of_node;
+ int irq_count = 0;
size_t size;
int retval;
@@ -1045,7 +1038,6 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
* being accessed.
*/
rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Counting IRQs.\n", __func__);
- irq_count = 0;
data->bootloader_mode = false;
retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_count_irqs);
@@ -1057,6 +1049,14 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
if (data->bootloader_mode)
dev_warn(dev, "Device in bootloader mode.\n");
+ /* Allocate and register a linear revmap irq_domain */
+ data->irqdomain = irq_domain_add_linear(rmi_of_node, irq_count,
+ &irq_domain_simple_ops, data);
+ if (!data->irqdomain) {
+ dev_err(&rmi_dev->dev, "Failed to create IRQ domain\n");
+ return PTR_ERR(data->irqdomain);
+ }
+
data->irq_count = irq_count;
data->num_of_irq_regs = (data->irq_count + 7) / 8;
@@ -1079,10 +1079,9 @@ int rmi_init_functions(struct rmi_driver_data *data)
{
struct rmi_device *rmi_dev = data->rmi_dev;
struct device *dev = &rmi_dev->dev;
- int irq_count;
+ int irq_count = 0;
int retval;
- irq_count = 0;
rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Creating functions.\n", __func__);
retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_create_function);
if (retval < 0) {
diff --git a/drivers/input/rmi4/rmi_f01.c b/drivers/input/rmi4/rmi_f01.c
index 8a07ae1..4edaa14 100644
--- a/drivers/input/rmi4/rmi_f01.c
+++ b/drivers/input/rmi4/rmi_f01.c
@@ -681,9 +681,9 @@ static int rmi_f01_resume(struct rmi_function *fn)
return 0;
}
-static int rmi_f01_attention(struct rmi_function *fn,
- unsigned long *irq_bits)
+static irqreturn_t rmi_f01_attention(int irq, void *ctx)
{
+ struct rmi_function *fn = ctx;
struct rmi_device *rmi_dev = fn->rmi_dev;
int error;
u8 device_status;
@@ -692,7 +692,7 @@ static int rmi_f01_attention(struct rmi_function *fn,
if (error) {
dev_err(&fn->dev,
"Failed to read device status: %d.\n", error);
- return error;
+ return IRQ_RETVAL(error);
}
if (RMI_F01_STATUS_BOOTLOADER(device_status))
@@ -704,11 +704,11 @@ static int rmi_f01_attention(struct rmi_function *fn,
error = rmi_dev->driver->reset_handler(rmi_dev);
if (error) {
dev_err(&fn->dev, "Device reset failed: %d\n", error);
- return error;
+ return IRQ_RETVAL(error);
}
}
- return 0;
+ return IRQ_HANDLED;
}
struct rmi_function_handler rmi_f01_handler = {
diff --git a/drivers/input/rmi4/rmi_f03.c b/drivers/input/rmi4/rmi_f03.c
index ad71a5e..b9f07c9 100644
--- a/drivers/input/rmi4/rmi_f03.c
+++ b/drivers/input/rmi4/rmi_f03.c
@@ -199,8 +199,9 @@ static int rmi_f03_config(struct rmi_function *fn)
return 0;
}
-static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
+static irqreturn_t rmi_f03_attention(int irq, void *ctx)
{
+ struct rmi_function *fn = ctx;
struct rmi_device *rmi_dev = fn->rmi_dev;
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
struct f03_data *f03 = dev_get_drvdata(&fn->dev);
@@ -217,7 +218,7 @@ static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
/* First grab the data passed by the transport device */
if (drvdata->attn_data.size < ob_len) {
dev_warn(&fn->dev, "F03 interrupted, but data is missing!\n");
- return 0;
+ return IRQ_HANDLED;
}
memcpy(obs, drvdata->attn_data.data, ob_len);
@@ -233,7 +234,7 @@ static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
"%s: Failed to read F03 output buffers: %d\n",
__func__, error);
serio_interrupt(f03->serio, 0, SERIO_TIMEOUT);
- return error;
+ return IRQ_RETVAL(error);
}
}
@@ -259,7 +260,7 @@ static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
serio_interrupt(f03->serio, ob_data, serio_flags);
}
- return 0;
+ return IRQ_HANDLED;
}
static void rmi_f03_remove(struct rmi_function *fn)
diff --git a/drivers/input/rmi4/rmi_f11.c b/drivers/input/rmi4/rmi_f11.c
index bc5e37f..e587c87 100644
--- a/drivers/input/rmi4/rmi_f11.c
+++ b/drivers/input/rmi4/rmi_f11.c
@@ -571,8 +571,7 @@ static inline u8 rmi_f11_parse_finger_state(const u8 *f_state, u8 n_finger)
static void rmi_f11_finger_handler(struct f11_data *f11,
struct rmi_2d_sensor *sensor,
- unsigned long *irq_bits, int num_irq_regs,
- int size)
+ int num_irq_regs, int size)
{
const u8 *f_state = f11->data.f_state;
u8 finger_state;
@@ -581,12 +580,7 @@ static void rmi_f11_finger_handler(struct f11_data *f11,
int rel_fingers;
int abs_size = sensor->nbr_fingers * RMI_F11_ABS_BYTES;
- int abs_bits = bitmap_and(f11->result_bits, irq_bits, f11->abs_mask,
- num_irq_regs * 8);
- int rel_bits = bitmap_and(f11->result_bits, irq_bits, f11->rel_mask,
- num_irq_regs * 8);
-
- if (abs_bits) {
+ if (sensor->report_abs) {
if (abs_size > size)
abs_fingers = size / RMI_F11_ABS_BYTES;
else
@@ -606,7 +600,7 @@ static void rmi_f11_finger_handler(struct f11_data *f11,
}
}
- if (rel_bits) {
+ if (sensor->report_rel) {
if ((abs_size + sensor->nbr_fingers * RMI_F11_REL_BYTES) > size)
rel_fingers = (size - abs_size) / RMI_F11_REL_BYTES;
else
@@ -616,7 +610,7 @@ static void rmi_f11_finger_handler(struct f11_data *f11,
rmi_f11_rel_pos_report(f11, i);
}
- if (abs_bits) {
+ if (sensor->report_abs) {
/*
* the absolute part is made in 2 parts to allow the kernel
* tracking to take place.
@@ -1275,8 +1269,9 @@ static int rmi_f11_config(struct rmi_function *fn)
return 0;
}
-static int rmi_f11_attention(struct rmi_function *fn, unsigned long *irq_bits)
+static irqreturn_t rmi_f11_attention(int irq, void *ctx)
{
+ struct rmi_function *fn = ctx;
struct rmi_device *rmi_dev = fn->rmi_dev;
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
struct f11_data *f11 = dev_get_drvdata(&fn->dev);
@@ -1302,13 +1297,13 @@ static int rmi_f11_attention(struct rmi_function *fn, unsigned long *irq_bits)
data_base_addr, f11->sensor.data_pkt,
f11->sensor.pkt_size);
if (error < 0)
- return error;
+ return IRQ_RETVAL(error);
}
- rmi_f11_finger_handler(f11, &f11->sensor, irq_bits,
- drvdata->num_of_irq_regs, valid_bytes);
+ rmi_f11_finger_handler(f11, &f11->sensor,
+ drvdata->num_of_irq_regs, valid_bytes);
- return 0;
+ return IRQ_HANDLED;
}
static int rmi_f11_resume(struct rmi_function *fn)
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index 8b0db08..e226def 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -197,10 +197,10 @@ static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, int size)
rmi_2d_sensor_abs_report(sensor, &sensor->objs[i], i);
}
-static int rmi_f12_attention(struct rmi_function *fn,
- unsigned long *irq_nr_regs)
+static irqreturn_t rmi_f12_attention(int irq, void *ctx)
{
int retval;
+ struct rmi_function *fn = ctx;
struct rmi_device *rmi_dev = fn->rmi_dev;
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
struct f12_data *f12 = dev_get_drvdata(&fn->dev);
@@ -222,7 +222,7 @@ static int rmi_f12_attention(struct rmi_function *fn,
if (retval < 0) {
dev_err(&fn->dev, "Failed to read object data. Code: %d.\n",
retval);
- return retval;
+ return IRQ_RETVAL(retval);
}
}
@@ -232,7 +232,7 @@ static int rmi_f12_attention(struct rmi_function *fn,
input_mt_sync_frame(sensor->input);
- return 0;
+ return IRQ_HANDLED;
}
static int rmi_f12_write_control_regs(struct rmi_function *fn)
diff --git a/drivers/input/rmi4/rmi_f30.c b/drivers/input/rmi4/rmi_f30.c
index 82e0f0d..5e3ed5a 100644
--- a/drivers/input/rmi4/rmi_f30.c
+++ b/drivers/input/rmi4/rmi_f30.c
@@ -122,8 +122,9 @@ static void rmi_f30_report_button(struct rmi_function *fn,
}
}
-static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
+static irqreturn_t rmi_f30_attention(int irq, void *ctx)
{
+ struct rmi_function *fn = ctx;
struct f30_data *f30 = dev_get_drvdata(&fn->dev);
struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);
int error;
@@ -134,7 +135,7 @@ static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
if (drvdata->attn_data.size < f30->register_count) {
dev_warn(&fn->dev,
"F30 interrupted, but data is missing\n");
- return 0;
+ return IRQ_HANDLED;
}
memcpy(f30->data_regs, drvdata->attn_data.data,
f30->register_count);
@@ -147,7 +148,7 @@ static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
dev_err(&fn->dev,
"%s: Failed to read F30 data registers: %d\n",
__func__, error);
- return error;
+ return IRQ_RETVAL(error);
}
}
@@ -159,7 +160,7 @@ static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
rmi_f03_commit_buttons(f30->f03);
}
- return 0;
+ return IRQ_HANDLED;
}
static int rmi_f30_config(struct rmi_function *fn)
diff --git a/drivers/input/rmi4/rmi_f34.c b/drivers/input/rmi4/rmi_f34.c
index 4cfe970..7268cf9 100644
--- a/drivers/input/rmi4/rmi_f34.c
+++ b/drivers/input/rmi4/rmi_f34.c
@@ -101,8 +101,9 @@ static int rmi_f34_command(struct f34_data *f34, u8 command,
return 0;
}
-static int rmi_f34_attention(struct rmi_function *fn, unsigned long *irq_bits)
+static irqreturn_t rmi_f34_attention(int irq, void *ctx)
{
+ struct rmi_function *fn = ctx;
struct f34_data *f34 = dev_get_drvdata(&fn->dev);
int ret;
u8 status;
@@ -127,7 +128,7 @@ static int rmi_f34_attention(struct rmi_function *fn, unsigned long *irq_bits)
complete(&f34->v7.cmd_done);
}
- return 0;
+ return IRQ_HANDLED;
}
static int rmi_f34_write_blocks(struct f34_data *f34, const void *data,
diff --git a/drivers/input/rmi4/rmi_f54.c b/drivers/input/rmi4/rmi_f54.c
index 5343f2c..98a935e 100644
--- a/drivers/input/rmi4/rmi_f54.c
+++ b/drivers/input/rmi4/rmi_f54.c
@@ -610,11 +610,6 @@ static void rmi_f54_work(struct work_struct *work)
mutex_unlock(&f54->data_mutex);
}
-static int rmi_f54_attention(struct rmi_function *fn, unsigned long *irqbits)
-{
- return 0;
-}
-
static int rmi_f54_config(struct rmi_function *fn)
{
struct rmi_driver *drv = fn->rmi_dev->driver;
@@ -756,6 +751,5 @@ struct rmi_function_handler rmi_f54_handler = {
.func = 0x54,
.probe = rmi_f54_probe,
.config = rmi_f54_config,
- .attention = rmi_f54_attention,
.remove = rmi_f54_remove,
};
diff --git a/include/linux/rmi.h b/include/linux/rmi.h
index 64125443..5ef5c7c 100644
--- a/include/linux/rmi.h
+++ b/include/linux/rmi.h
@@ -354,6 +354,8 @@ struct rmi_driver_data {
struct mutex irq_mutex;
struct input_dev *input;
+ struct irq_domain *irqdomain;
+
u8 pdt_props;
u8 num_rx_electrodes;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH 4/4] Input: mms114 - add support for mms152
From: Dmitry Torokhov @ 2018-01-24 21:27 UTC (permalink / raw)
To: Marcus Folkesson
Cc: Simon Shields, Andi Shyti, Rob Herring, linux-input, linux-kernel
In-Reply-To: <20180124200408.GB705@gmail.com>
On Wed, Jan 24, 2018 at 09:04:08PM +0100, Marcus Folkesson wrote:
> Hello Dmitry,
>
> On Wed, Jan 24, 2018 at 11:38:04AM -0800, Dmitry Torokhov wrote:
> > From: Simon Shields <simon@lineageos.org>
> >
> > @@ -241,12 +251,28 @@ static int mms114_get_version(struct mms114_data *data)
> > u8 buf[6];
> > int error;
> >
> > - error = __mms114_read_reg(data, MMS114_TSP_REV, 6, buf);
> > - if (error < 0)
> > - return error;
> > + switch (data->type) {
> > + case TYPE_MMS152:
> > + error = __mms114_read_reg(data, MMS152_FW_REV, 3, buf);
> > + if (error)
> > + return error;
> > + buf[3] = i2c_smbus_read_byte_data(data->client,
> > + MMS152_COMPAT_GROUP);
> > + if (buf[3] < 0)
> > + return buf[3];
>
> buf is unsigned.
>
> Maybe
> error = i2c_smbus_read_byte_data(data->client,
> MMS152_COMPAT_GROUP);
> if (error < 0)
> return error;
> Instead?
Good catch. I think I'd rather have a separate variable "group" for
this.
Thank you.
>
>
> > + dev_info(dev, "TSP FW Rev: bootloader 0x%x / core 0x%x / config 0x%x, Compat group: %c\n",
> > + buf[0], buf[1], buf[2], buf[3]);
> > + break;
> > +
> > + case TYPE_MMS114:
> > + error = __mms114_read_reg(data, MMS114_TSP_REV, 6, buf);
> > + if (error)
> > + return error;
> >
> > - dev_info(dev, "TSP Rev: 0x%x, HW Rev: 0x%x, Firmware Ver: 0x%x\n",
> > - buf[0], buf[1], buf[3]);
> > + dev_info(dev, "TSP Rev: 0x%x, HW Rev: 0x%x, Firmware Ver: 0x%x\n",
> > + buf[0], buf[1], buf[3]);
> > + break;
> > + }
> >
> > return 0;
> > }
>
>
> Best regards
> Marcus Folkesson
--
Dmitry
^ permalink raw reply
* [PATCH 4/4 v2] Input: mms114 - add support for mms152
From: Dmitry Torokhov @ 2018-01-24 21:32 UTC (permalink / raw)
To: Marcus Folkesson
Cc: Simon Shields, Andi Shyti, Rob Herring, linux-input, linux-kernel
In-Reply-To: <20180124200408.GB705@gmail.com>
From: Simon Shields <simon@lineageos.org>
MMS152 has no configuration registers, but the packet format used in
interrupts is identical to mms114.
Signed-off-by: Simon Shields <simon@lineageos.org>
Patchwork-Id: 10125841
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
V2: Fixed issue pointed by Marcus Folkesson.
.../bindings/input/touchscreen/mms114.txt | 6 +
drivers/input/touchscreen/mms114.c | 92 ++++++++++++++++----
2 files changed, 77 insertions(+), 21 deletions(-)
diff --git a/Documentation/devicetree/bindings/input/touchscreen/mms114.txt b/Documentation/devicetree/bindings/input/touchscreen/mms114.txt
index 8f9f9f38eff4a..2cd954051d299 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/mms114.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/mms114.txt
@@ -1,7 +1,9 @@
-* MELFAS MMS114 touchscreen controller
+* MELFAS MMS114/MMS152 touchscreen controller
Required properties:
-- compatible: must be "melfas,mms114"
+- compatible: should be one of:
+ - "melfas,mms114"
+ - "melfas,mms152"
- reg: I2C address of the chip
- interrupts: interrupt to which the chip is connected
- touchscreen-size-x: See [1]
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index 69e4288bf8aa3..c54f4afe11037 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/i2c.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
@@ -33,6 +34,9 @@
#define MMS114_INFOMATION 0x10
#define MMS114_TSP_REV 0xF0
+#define MMS152_FW_REV 0xE1
+#define MMS152_COMPAT_GROUP 0xF2
+
/* Minimum delay time is 50us between stop and start signal of i2c */
#define MMS114_I2C_DELAY 50
@@ -50,12 +54,18 @@
#define MMS114_TYPE_TOUCHSCREEN 1
#define MMS114_TYPE_TOUCHKEY 2
+enum mms_type {
+ TYPE_MMS114 = 114,
+ TYPE_MMS152 = 152,
+};
+
struct mms114_data {
struct i2c_client *client;
struct input_dev *input_dev;
struct regulator *core_reg;
struct regulator *io_reg;
struct touchscreen_properties props;
+ enum mms_type type;
unsigned int contact_threshold;
unsigned int moving_threshold;
@@ -239,14 +249,33 @@ static int mms114_get_version(struct mms114_data *data)
{
struct device *dev = &data->client->dev;
u8 buf[6];
+ int group;
int error;
- error = __mms114_read_reg(data, MMS114_TSP_REV, 6, buf);
- if (error < 0)
- return error;
+ switch (data->type) {
+ case TYPE_MMS152:
+ error = __mms114_read_reg(data, MMS152_FW_REV, 3, buf);
+ if (error)
+ return error;
+
+ group = i2c_smbus_read_byte_data(data->client,
+ MMS152_COMPAT_GROUP);
+ if (group < 0)
+ return group;
+
+ dev_info(dev, "TSP FW Rev: bootloader 0x%x / core 0x%x / config 0x%x, Compat group: %c\n",
+ buf[0], buf[1], buf[2], group);
+ break;
+
+ case TYPE_MMS114:
+ error = __mms114_read_reg(data, MMS114_TSP_REV, 6, buf);
+ if (error)
+ return error;
- dev_info(dev, "TSP Rev: 0x%x, HW Rev: 0x%x, Firmware Ver: 0x%x\n",
- buf[0], buf[1], buf[3]);
+ dev_info(dev, "TSP Rev: 0x%x, HW Rev: 0x%x, Firmware Ver: 0x%x\n",
+ buf[0], buf[1], buf[3]);
+ break;
+ }
return 0;
}
@@ -261,6 +290,10 @@ static int mms114_setup_regs(struct mms114_data *data)
if (error < 0)
return error;
+ /* MMS152 has no configuration or power on registers */
+ if (data->type == TYPE_MMS152)
+ return 0;
+
error = mms114_set_active(data, true);
if (error < 0)
return error;
@@ -395,6 +428,7 @@ static int mms114_probe(struct i2c_client *client,
{
struct mms114_data *data;
struct input_dev *input_dev;
+ const void *match_data;
int error;
if (!i2c_check_functionality(client->adapter,
@@ -415,6 +449,13 @@ static int mms114_probe(struct i2c_client *client,
data->client = client;
data->input_dev = input_dev;
+ /* FIXME: switch to device_get_match_data() when available */
+ match_data = of_device_get_match_data(&client->dev);
+ if (!match_data)
+ return -EINVAL;
+
+ data->type = (enum mms_type)match_data;
+
input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X);
input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y);
input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
@@ -435,19 +476,26 @@ static int mms114_probe(struct i2c_client *client,
0, data->props.max_y, 0, 0);
}
- /*
- * The firmware handles movement and pressure fuzz, so
- * don't duplicate that in software.
- */
- data->moving_threshold = input_abs_get_fuzz(input_dev,
- ABS_MT_POSITION_X);
- data->contact_threshold = input_abs_get_fuzz(input_dev,
- ABS_MT_PRESSURE);
- input_abs_set_fuzz(input_dev, ABS_MT_POSITION_X, 0);
- input_abs_set_fuzz(input_dev, ABS_MT_POSITION_Y, 0);
- input_abs_set_fuzz(input_dev, ABS_MT_PRESSURE, 0);
-
- input_dev->name = "MELFAS MMS114 Touchscreen";
+ if (data->type == TYPE_MMS114) {
+ /*
+ * The firmware handles movement and pressure fuzz, so
+ * don't duplicate that in software.
+ */
+ data->moving_threshold = input_abs_get_fuzz(input_dev,
+ ABS_MT_POSITION_X);
+ data->contact_threshold = input_abs_get_fuzz(input_dev,
+ ABS_MT_PRESSURE);
+ input_abs_set_fuzz(input_dev, ABS_MT_POSITION_X, 0);
+ input_abs_set_fuzz(input_dev, ABS_MT_POSITION_Y, 0);
+ input_abs_set_fuzz(input_dev, ABS_MT_PRESSURE, 0);
+ }
+
+ input_dev->name = devm_kasprintf(&client->dev, GFP_KERNEL,
+ "MELFAS MMS%d Touchscreen",
+ data->type);
+ if (!input_dev->name)
+ return -ENOMEM;
+
input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev;
input_dev->open = mms114_input_open;
@@ -549,7 +597,13 @@ MODULE_DEVICE_TABLE(i2c, mms114_id);
#ifdef CONFIG_OF
static const struct of_device_id mms114_dt_match[] = {
- { .compatible = "melfas,mms114" },
+ {
+ .compatible = "melfas,mms114",
+ .data = (void *)TYPE_MMS114,
+ }, {
+ .compatible = "melfas,mms152",
+ .data = (void *)TYPE_MMS152,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, mms114_dt_match);
^ permalink raw reply related
* Re: [PATCH v1] Input: synaptics-rmi4 - convert irq distribution to irq_domain
From: Dmitry Torokhov @ 2018-01-24 21:37 UTC (permalink / raw)
To: Nick Dyer
Cc: Benjamin Tissoires, Andrew Duggan, Christopher Heiny, linux-input,
Chris Healy, Lucas Stach
In-Reply-To: <1516829193-27590-1-git-send-email-nick@shmanahar.org>
On Wed, Jan 24, 2018 at 09:26:33PM +0000, Nick Dyer wrote:
> Convert the RMI driver to use the standard mechanism for
> distributing IRQs to the various functions.
>
> Tested on:
> * S7300 (F11, F34, F54)
> * S7817 (F12, F34, F54)
Awesome! Thank you!
>
> Signed-off-by: Nick Dyer <nick@shmanahar.org>
> ---
> drivers/input/rmi4/Kconfig | 1 +
> drivers/input/rmi4/rmi_bus.c | 13 ++++++++-
> drivers/input/rmi4/rmi_bus.h | 3 +-
> drivers/input/rmi4/rmi_driver.c | 65 ++++++++++++++++++++---------------------
> drivers/input/rmi4/rmi_f01.c | 10 +++----
> drivers/input/rmi4/rmi_f03.c | 9 +++---
> drivers/input/rmi4/rmi_f11.c | 25 +++++++---------
> drivers/input/rmi4/rmi_f12.c | 8 ++---
> drivers/input/rmi4/rmi_f30.c | 9 +++---
> drivers/input/rmi4/rmi_f34.c | 5 ++--
> drivers/input/rmi4/rmi_f54.c | 6 ----
> include/linux/rmi.h | 2 ++
> 12 files changed, 81 insertions(+), 75 deletions(-)
>
> diff --git a/drivers/input/rmi4/Kconfig b/drivers/input/rmi4/Kconfig
> index 7172b88..fad2eae 100644
> --- a/drivers/input/rmi4/Kconfig
> +++ b/drivers/input/rmi4/Kconfig
> @@ -3,6 +3,7 @@
> #
> config RMI4_CORE
> tristate "Synaptics RMI4 bus support"
> + select IRQ_DOMAIN
> help
> Say Y here if you want to support the Synaptics RMI4 bus. This is
> required for all RMI4 device support.
> diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c
> index ae1bffe..ae288d6 100644
> --- a/drivers/input/rmi4/rmi_bus.c
> +++ b/drivers/input/rmi4/rmi_bus.c
> @@ -178,7 +178,18 @@ static int rmi_function_probe(struct device *dev)
>
> if (handler->probe) {
> error = handler->probe(fn);
> - return error;
> + if (error)
> + return error;
> + }
> +
> + if (fn->irq_base && handler->attention) {
> + error = devm_request_threaded_irq(&fn->dev, fn->irq_base, NULL,
Does this mean we have a thread for each function? The "parent" IRQ is
already threaded, I wonder if we could piggy-back on it... Or irqchip
code will not allow us to sleep in nested interrupt unless it is on a
separate thread?
Sorry, just dumping random thoughts, I have not looked at tghe IRQ ocre
code closely.
> + handler->attention, IRQF_ONESHOT,
> + dev_name(&fn->dev), fn);
> + if (error) {
> + dev_err(dev, "Failed registering IRQ %d\n", error);
> + return error;
> + }
> }
>
> return 0;
> diff --git a/drivers/input/rmi4/rmi_bus.h b/drivers/input/rmi4/rmi_bus.h
> index b7625a9..745a030 100644
> --- a/drivers/input/rmi4/rmi_bus.h
> +++ b/drivers/input/rmi4/rmi_bus.h
> @@ -35,6 +35,7 @@ struct rmi_function {
> struct device dev;
> struct list_head node;
>
> + unsigned int irq_base;
> unsigned int num_of_irqs;
> unsigned int irq_pos;
> unsigned long irq_mask[];
> @@ -76,7 +77,7 @@ struct rmi_function_handler {
> void (*remove)(struct rmi_function *fn);
> int (*config)(struct rmi_function *fn);
> int (*reset)(struct rmi_function *fn);
> - int (*attention)(struct rmi_function *fn, unsigned long *irq_bits);
> + irqreturn_t (*attention)(int irq, void *ctx);
> int (*suspend)(struct rmi_function *fn);
> int (*resume)(struct rmi_function *fn);
> };
> diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
> index 141ea22..b7ef1f5a 100644
> --- a/drivers/input/rmi4/rmi_driver.c
> +++ b/drivers/input/rmi4/rmi_driver.c
> @@ -21,6 +21,7 @@
> #include <linux/pm.h>
> #include <linux/slab.h>
> #include <linux/of.h>
> +#include <linux/irqdomain.h>
> #include <uapi/linux/input.h>
> #include <linux/rmi.h>
> #include "rmi_bus.h"
> @@ -127,28 +128,11 @@ static int rmi_driver_process_config_requests(struct rmi_device *rmi_dev)
> return 0;
> }
>
> -static void process_one_interrupt(struct rmi_driver_data *data,
> - struct rmi_function *fn)
> -{
> - struct rmi_function_handler *fh;
> -
> - if (!fn || !fn->dev.driver)
> - return;
> -
> - fh = to_rmi_function_handler(fn->dev.driver);
> - if (fh->attention) {
> - bitmap_and(data->fn_irq_bits, data->irq_status, fn->irq_mask,
> - data->irq_count);
> - if (!bitmap_empty(data->fn_irq_bits, data->irq_count))
> - fh->attention(fn, data->fn_irq_bits);
> - }
> -}
> -
> static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
> {
> struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
> struct device *dev = &rmi_dev->dev;
> - struct rmi_function *entry;
> + int i;
> int error;
>
> if (!data)
> @@ -173,16 +157,8 @@ static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
> */
> mutex_unlock(&data->irq_mutex);
>
> - /*
> - * It would be nice to be able to use irq_chip to handle these
> - * nested IRQs. Unfortunately, most of the current customers for
> - * this driver are using older kernels (3.0.x) that don't support
> - * the features required for that. Once they've shifted to more
> - * recent kernels (say, 3.3 and higher), this should be switched to
> - * use irq_chip.
> - */
> - list_for_each_entry(entry, &data->function_list, node)
> - process_one_interrupt(data, entry);
> + for_each_set_bit(i, data->irq_status, data->irq_count)
> + handle_nested_irq(irq_find_mapping(data->irqdomain, i));
>
> if (data->input)
> input_sync(data->input);
> @@ -847,6 +823,10 @@ int rmi_initial_reset(struct rmi_device *rmi_dev, void *ctx,
> return pdt->page_start == 0 ? RMI_SCAN_CONTINUE : -ENODEV;
> }
>
> +static struct irq_chip rmi_irq_chip = {
> + .name = "rmi4",
> +};
> +
> static int rmi_create_function(struct rmi_device *rmi_dev,
> void *ctx, const struct pdt_entry *pdt)
> {
> @@ -878,9 +858,18 @@ static int rmi_create_function(struct rmi_device *rmi_dev,
> fn->irq_pos = *current_irq_count;
> *current_irq_count += fn->num_of_irqs;
>
> - for (i = 0; i < fn->num_of_irqs; i++)
> + for (i = 0; i < fn->num_of_irqs; i++) {
> set_bit(fn->irq_pos + i, fn->irq_mask);
>
> + fn->irq_base = irq_create_mapping(data->irqdomain,
> + fn->irq_pos + i);
> +
> +
> + irq_set_chip_data(fn->irq_base, data);
> + irq_set_chip_and_handler(fn->irq_base, &rmi_irq_chip,
> + handle_simple_irq);
> + }
> +
> error = rmi_register_function(fn);
> if (error)
> goto err_put_fn;
> @@ -1000,9 +989,12 @@ EXPORT_SYMBOL_GPL(rmi_driver_resume);
> static int rmi_driver_remove(struct device *dev)
> {
> struct rmi_device *rmi_dev = to_rmi_device(dev);
> + struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
>
> rmi_disable_irq(rmi_dev, false);
>
> + irq_domain_remove(data->irqdomain);
> +
> rmi_f34_remove_sysfs(rmi_dev);
> rmi_free_function_list(rmi_dev);
>
> @@ -1034,7 +1026,8 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
> {
> struct rmi_device *rmi_dev = data->rmi_dev;
> struct device *dev = &rmi_dev->dev;
> - int irq_count;
> + struct device_node *rmi_of_node = rmi_dev->xport->dev->of_node;
> + int irq_count = 0;
> size_t size;
> int retval;
>
> @@ -1045,7 +1038,6 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
> * being accessed.
> */
> rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Counting IRQs.\n", __func__);
> - irq_count = 0;
> data->bootloader_mode = false;
>
> retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_count_irqs);
> @@ -1057,6 +1049,14 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
> if (data->bootloader_mode)
> dev_warn(dev, "Device in bootloader mode.\n");
>
> + /* Allocate and register a linear revmap irq_domain */
> + data->irqdomain = irq_domain_add_linear(rmi_of_node, irq_count,
> + &irq_domain_simple_ops, data);
> + if (!data->irqdomain) {
> + dev_err(&rmi_dev->dev, "Failed to create IRQ domain\n");
> + return PTR_ERR(data->irqdomain);
> + }
> +
> data->irq_count = irq_count;
> data->num_of_irq_regs = (data->irq_count + 7) / 8;
>
> @@ -1079,10 +1079,9 @@ int rmi_init_functions(struct rmi_driver_data *data)
> {
> struct rmi_device *rmi_dev = data->rmi_dev;
> struct device *dev = &rmi_dev->dev;
> - int irq_count;
> + int irq_count = 0;
> int retval;
>
> - irq_count = 0;
> rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Creating functions.\n", __func__);
> retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_create_function);
> if (retval < 0) {
> diff --git a/drivers/input/rmi4/rmi_f01.c b/drivers/input/rmi4/rmi_f01.c
> index 8a07ae1..4edaa14 100644
> --- a/drivers/input/rmi4/rmi_f01.c
> +++ b/drivers/input/rmi4/rmi_f01.c
> @@ -681,9 +681,9 @@ static int rmi_f01_resume(struct rmi_function *fn)
> return 0;
> }
>
> -static int rmi_f01_attention(struct rmi_function *fn,
> - unsigned long *irq_bits)
> +static irqreturn_t rmi_f01_attention(int irq, void *ctx)
> {
> + struct rmi_function *fn = ctx;
> struct rmi_device *rmi_dev = fn->rmi_dev;
> int error;
> u8 device_status;
> @@ -692,7 +692,7 @@ static int rmi_f01_attention(struct rmi_function *fn,
> if (error) {
> dev_err(&fn->dev,
> "Failed to read device status: %d.\n", error);
> - return error;
> + return IRQ_RETVAL(error);
> }
>
> if (RMI_F01_STATUS_BOOTLOADER(device_status))
> @@ -704,11 +704,11 @@ static int rmi_f01_attention(struct rmi_function *fn,
> error = rmi_dev->driver->reset_handler(rmi_dev);
> if (error) {
> dev_err(&fn->dev, "Device reset failed: %d\n", error);
> - return error;
> + return IRQ_RETVAL(error);
> }
> }
>
> - return 0;
> + return IRQ_HANDLED;
> }
>
> struct rmi_function_handler rmi_f01_handler = {
> diff --git a/drivers/input/rmi4/rmi_f03.c b/drivers/input/rmi4/rmi_f03.c
> index ad71a5e..b9f07c9 100644
> --- a/drivers/input/rmi4/rmi_f03.c
> +++ b/drivers/input/rmi4/rmi_f03.c
> @@ -199,8 +199,9 @@ static int rmi_f03_config(struct rmi_function *fn)
> return 0;
> }
>
> -static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
> +static irqreturn_t rmi_f03_attention(int irq, void *ctx)
> {
> + struct rmi_function *fn = ctx;
> struct rmi_device *rmi_dev = fn->rmi_dev;
> struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
> struct f03_data *f03 = dev_get_drvdata(&fn->dev);
> @@ -217,7 +218,7 @@ static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
> /* First grab the data passed by the transport device */
> if (drvdata->attn_data.size < ob_len) {
> dev_warn(&fn->dev, "F03 interrupted, but data is missing!\n");
> - return 0;
> + return IRQ_HANDLED;
> }
>
> memcpy(obs, drvdata->attn_data.data, ob_len);
> @@ -233,7 +234,7 @@ static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
> "%s: Failed to read F03 output buffers: %d\n",
> __func__, error);
> serio_interrupt(f03->serio, 0, SERIO_TIMEOUT);
> - return error;
> + return IRQ_RETVAL(error);
> }
> }
>
> @@ -259,7 +260,7 @@ static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
> serio_interrupt(f03->serio, ob_data, serio_flags);
> }
>
> - return 0;
> + return IRQ_HANDLED;
> }
>
> static void rmi_f03_remove(struct rmi_function *fn)
> diff --git a/drivers/input/rmi4/rmi_f11.c b/drivers/input/rmi4/rmi_f11.c
> index bc5e37f..e587c87 100644
> --- a/drivers/input/rmi4/rmi_f11.c
> +++ b/drivers/input/rmi4/rmi_f11.c
> @@ -571,8 +571,7 @@ static inline u8 rmi_f11_parse_finger_state(const u8 *f_state, u8 n_finger)
>
> static void rmi_f11_finger_handler(struct f11_data *f11,
> struct rmi_2d_sensor *sensor,
> - unsigned long *irq_bits, int num_irq_regs,
> - int size)
> + int num_irq_regs, int size)
> {
> const u8 *f_state = f11->data.f_state;
> u8 finger_state;
> @@ -581,12 +580,7 @@ static void rmi_f11_finger_handler(struct f11_data *f11,
> int rel_fingers;
> int abs_size = sensor->nbr_fingers * RMI_F11_ABS_BYTES;
>
> - int abs_bits = bitmap_and(f11->result_bits, irq_bits, f11->abs_mask,
> - num_irq_regs * 8);
> - int rel_bits = bitmap_and(f11->result_bits, irq_bits, f11->rel_mask,
> - num_irq_regs * 8);
> -
> - if (abs_bits) {
> + if (sensor->report_abs) {
> if (abs_size > size)
> abs_fingers = size / RMI_F11_ABS_BYTES;
> else
> @@ -606,7 +600,7 @@ static void rmi_f11_finger_handler(struct f11_data *f11,
> }
> }
>
> - if (rel_bits) {
> + if (sensor->report_rel) {
> if ((abs_size + sensor->nbr_fingers * RMI_F11_REL_BYTES) > size)
> rel_fingers = (size - abs_size) / RMI_F11_REL_BYTES;
> else
> @@ -616,7 +610,7 @@ static void rmi_f11_finger_handler(struct f11_data *f11,
> rmi_f11_rel_pos_report(f11, i);
> }
>
> - if (abs_bits) {
> + if (sensor->report_abs) {
> /*
> * the absolute part is made in 2 parts to allow the kernel
> * tracking to take place.
> @@ -1275,8 +1269,9 @@ static int rmi_f11_config(struct rmi_function *fn)
> return 0;
> }
>
> -static int rmi_f11_attention(struct rmi_function *fn, unsigned long *irq_bits)
> +static irqreturn_t rmi_f11_attention(int irq, void *ctx)
> {
> + struct rmi_function *fn = ctx;
> struct rmi_device *rmi_dev = fn->rmi_dev;
> struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
> struct f11_data *f11 = dev_get_drvdata(&fn->dev);
> @@ -1302,13 +1297,13 @@ static int rmi_f11_attention(struct rmi_function *fn, unsigned long *irq_bits)
> data_base_addr, f11->sensor.data_pkt,
> f11->sensor.pkt_size);
> if (error < 0)
> - return error;
> + return IRQ_RETVAL(error);
> }
>
> - rmi_f11_finger_handler(f11, &f11->sensor, irq_bits,
> - drvdata->num_of_irq_regs, valid_bytes);
> + rmi_f11_finger_handler(f11, &f11->sensor,
> + drvdata->num_of_irq_regs, valid_bytes);
>
> - return 0;
> + return IRQ_HANDLED;
> }
>
> static int rmi_f11_resume(struct rmi_function *fn)
> diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
> index 8b0db08..e226def 100644
> --- a/drivers/input/rmi4/rmi_f12.c
> +++ b/drivers/input/rmi4/rmi_f12.c
> @@ -197,10 +197,10 @@ static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, int size)
> rmi_2d_sensor_abs_report(sensor, &sensor->objs[i], i);
> }
>
> -static int rmi_f12_attention(struct rmi_function *fn,
> - unsigned long *irq_nr_regs)
> +static irqreturn_t rmi_f12_attention(int irq, void *ctx)
> {
> int retval;
> + struct rmi_function *fn = ctx;
> struct rmi_device *rmi_dev = fn->rmi_dev;
> struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
> struct f12_data *f12 = dev_get_drvdata(&fn->dev);
> @@ -222,7 +222,7 @@ static int rmi_f12_attention(struct rmi_function *fn,
> if (retval < 0) {
> dev_err(&fn->dev, "Failed to read object data. Code: %d.\n",
> retval);
> - return retval;
> + return IRQ_RETVAL(retval);
> }
> }
>
> @@ -232,7 +232,7 @@ static int rmi_f12_attention(struct rmi_function *fn,
>
> input_mt_sync_frame(sensor->input);
>
> - return 0;
> + return IRQ_HANDLED;
> }
>
> static int rmi_f12_write_control_regs(struct rmi_function *fn)
> diff --git a/drivers/input/rmi4/rmi_f30.c b/drivers/input/rmi4/rmi_f30.c
> index 82e0f0d..5e3ed5a 100644
> --- a/drivers/input/rmi4/rmi_f30.c
> +++ b/drivers/input/rmi4/rmi_f30.c
> @@ -122,8 +122,9 @@ static void rmi_f30_report_button(struct rmi_function *fn,
> }
> }
>
> -static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
> +static irqreturn_t rmi_f30_attention(int irq, void *ctx)
> {
> + struct rmi_function *fn = ctx;
> struct f30_data *f30 = dev_get_drvdata(&fn->dev);
> struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);
> int error;
> @@ -134,7 +135,7 @@ static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
> if (drvdata->attn_data.size < f30->register_count) {
> dev_warn(&fn->dev,
> "F30 interrupted, but data is missing\n");
> - return 0;
> + return IRQ_HANDLED;
> }
> memcpy(f30->data_regs, drvdata->attn_data.data,
> f30->register_count);
> @@ -147,7 +148,7 @@ static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
> dev_err(&fn->dev,
> "%s: Failed to read F30 data registers: %d\n",
> __func__, error);
> - return error;
> + return IRQ_RETVAL(error);
> }
> }
>
> @@ -159,7 +160,7 @@ static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
> rmi_f03_commit_buttons(f30->f03);
> }
>
> - return 0;
> + return IRQ_HANDLED;
> }
>
> static int rmi_f30_config(struct rmi_function *fn)
> diff --git a/drivers/input/rmi4/rmi_f34.c b/drivers/input/rmi4/rmi_f34.c
> index 4cfe970..7268cf9 100644
> --- a/drivers/input/rmi4/rmi_f34.c
> +++ b/drivers/input/rmi4/rmi_f34.c
> @@ -101,8 +101,9 @@ static int rmi_f34_command(struct f34_data *f34, u8 command,
> return 0;
> }
>
> -static int rmi_f34_attention(struct rmi_function *fn, unsigned long *irq_bits)
> +static irqreturn_t rmi_f34_attention(int irq, void *ctx)
> {
> + struct rmi_function *fn = ctx;
> struct f34_data *f34 = dev_get_drvdata(&fn->dev);
> int ret;
> u8 status;
> @@ -127,7 +128,7 @@ static int rmi_f34_attention(struct rmi_function *fn, unsigned long *irq_bits)
> complete(&f34->v7.cmd_done);
> }
>
> - return 0;
> + return IRQ_HANDLED;
> }
>
> static int rmi_f34_write_blocks(struct f34_data *f34, const void *data,
> diff --git a/drivers/input/rmi4/rmi_f54.c b/drivers/input/rmi4/rmi_f54.c
> index 5343f2c..98a935e 100644
> --- a/drivers/input/rmi4/rmi_f54.c
> +++ b/drivers/input/rmi4/rmi_f54.c
> @@ -610,11 +610,6 @@ static void rmi_f54_work(struct work_struct *work)
> mutex_unlock(&f54->data_mutex);
> }
>
> -static int rmi_f54_attention(struct rmi_function *fn, unsigned long *irqbits)
> -{
> - return 0;
> -}
> -
> static int rmi_f54_config(struct rmi_function *fn)
> {
> struct rmi_driver *drv = fn->rmi_dev->driver;
> @@ -756,6 +751,5 @@ struct rmi_function_handler rmi_f54_handler = {
> .func = 0x54,
> .probe = rmi_f54_probe,
> .config = rmi_f54_config,
> - .attention = rmi_f54_attention,
> .remove = rmi_f54_remove,
> };
> diff --git a/include/linux/rmi.h b/include/linux/rmi.h
> index 64125443..5ef5c7c 100644
> --- a/include/linux/rmi.h
> +++ b/include/linux/rmi.h
> @@ -354,6 +354,8 @@ struct rmi_driver_data {
> struct mutex irq_mutex;
> struct input_dev *input;
>
> + struct irq_domain *irqdomain;
> +
> u8 pdt_props;
>
> u8 num_rx_electrodes;
> --
> 2.7.4
>
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v1] Input: synaptics-rmi4 - convert irq distribution to irq_domain
From: Christopher Heiny @ 2018-01-24 21:37 UTC (permalink / raw)
To: Nick Dyer, Dmitry Torokhov
Cc: Benjamin Tissoires, Andrew Duggan, linux-input, Chris Healy,
Lucas Stach
In-Reply-To: <1516829193-27590-1-git-send-email-nick@shmanahar.org>
On Wed, 2018-01-24 at 21:26 +0000, Nick Dyer wrote:
> Convert the RMI driver to use the standard mechanism for
> distributing IRQs to the various functions.
>
> Tested on:
> * S7300 (F11, F34, F54)
> * S7817 (F12, F34, F54)
>
> Signed-off-by: Nick Dyer <nick@shmanahar.org>
Acked-by: Christopher Heiny <cheiny@synaptics.com>
Thanks for the fix - it replaces a bit of paleozoic cruft that I'd
forgotten all about. I'm not able to bench test this, but don't see
any gotchas on a read-through.
Cheers,
Chris
> ---
> drivers/input/rmi4/Kconfig | 1 +
> drivers/input/rmi4/rmi_bus.c | 13 ++++++++-
> drivers/input/rmi4/rmi_bus.h | 3 +-
> drivers/input/rmi4/rmi_driver.c | 65 ++++++++++++++++++++-----------
> ----------
> drivers/input/rmi4/rmi_f01.c | 10 +++----
> drivers/input/rmi4/rmi_f03.c | 9 +++---
> drivers/input/rmi4/rmi_f11.c | 25 +++++++---------
> drivers/input/rmi4/rmi_f12.c | 8 ++---
> drivers/input/rmi4/rmi_f30.c | 9 +++---
> drivers/input/rmi4/rmi_f34.c | 5 ++--
> drivers/input/rmi4/rmi_f54.c | 6 ----
> include/linux/rmi.h | 2 ++
> 12 files changed, 81 insertions(+), 75 deletions(-)
>
> diff --git a/drivers/input/rmi4/Kconfig b/drivers/input/rmi4/Kconfig
> index 7172b88..fad2eae 100644
> --- a/drivers/input/rmi4/Kconfig
> +++ b/drivers/input/rmi4/Kconfig
> @@ -3,6 +3,7 @@
> #
> config RMI4_CORE
> tristate "Synaptics RMI4 bus support"
> + select IRQ_DOMAIN
> help
> Say Y here if you want to support the Synaptics RMI4
> bus. This is
> required for all RMI4 device support.
> diff --git a/drivers/input/rmi4/rmi_bus.c
> b/drivers/input/rmi4/rmi_bus.c
> index ae1bffe..ae288d6 100644
> --- a/drivers/input/rmi4/rmi_bus.c
> +++ b/drivers/input/rmi4/rmi_bus.c
> @@ -178,7 +178,18 @@ static int rmi_function_probe(struct device
> *dev)
>
> if (handler->probe) {
> error = handler->probe(fn);
> - return error;
> + if (error)
> + return error;
> + }
> +
> + if (fn->irq_base && handler->attention) {
> + error = devm_request_threaded_irq(&fn->dev, fn-
> >irq_base, NULL,
> + handler->attention,
> IRQF_ONESHOT,
> + dev_name(&fn->dev), fn);
> + if (error) {
> + dev_err(dev, "Failed registering IRQ %d\n",
> error);
> + return error;
> + }
> }
>
> return 0;
> diff --git a/drivers/input/rmi4/rmi_bus.h
> b/drivers/input/rmi4/rmi_bus.h
> index b7625a9..745a030 100644
> --- a/drivers/input/rmi4/rmi_bus.h
> +++ b/drivers/input/rmi4/rmi_bus.h
> @@ -35,6 +35,7 @@ struct rmi_function {
> struct device dev;
> struct list_head node;
>
> + unsigned int irq_base;
> unsigned int num_of_irqs;
> unsigned int irq_pos;
> unsigned long irq_mask[];
> @@ -76,7 +77,7 @@ struct rmi_function_handler {
> void (*remove)(struct rmi_function *fn);
> int (*config)(struct rmi_function *fn);
> int (*reset)(struct rmi_function *fn);
> - int (*attention)(struct rmi_function *fn, unsigned long
> *irq_bits);
> + irqreturn_t (*attention)(int irq, void *ctx);
> int (*suspend)(struct rmi_function *fn);
> int (*resume)(struct rmi_function *fn);
> };
> diff --git a/drivers/input/rmi4/rmi_driver.c
> b/drivers/input/rmi4/rmi_driver.c
> index 141ea22..b7ef1f5a 100644
> --- a/drivers/input/rmi4/rmi_driver.c
> +++ b/drivers/input/rmi4/rmi_driver.c
> @@ -21,6 +21,7 @@
> #include <linux/pm.h>
> #include <linux/slab.h>
> #include <linux/of.h>
> +#include <linux/irqdomain.h>
> #include <uapi/linux/input.h>
> #include <linux/rmi.h>
> #include "rmi_bus.h"
> @@ -127,28 +128,11 @@ static int
> rmi_driver_process_config_requests(struct rmi_device *rmi_dev)
> return 0;
> }
>
> -static void process_one_interrupt(struct rmi_driver_data *data,
> - struct rmi_function *fn)
> -{
> - struct rmi_function_handler *fh;
> -
> - if (!fn || !fn->dev.driver)
> - return;
> -
> - fh = to_rmi_function_handler(fn->dev.driver);
> - if (fh->attention) {
> - bitmap_and(data->fn_irq_bits, data->irq_status, fn-
> >irq_mask,
> - data->irq_count);
> - if (!bitmap_empty(data->fn_irq_bits, data-
> >irq_count))
> - fh->attention(fn, data->fn_irq_bits);
> - }
> -}
> -
> static int rmi_process_interrupt_requests(struct rmi_device
> *rmi_dev)
> {
> struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev-
> >dev);
> struct device *dev = &rmi_dev->dev;
> - struct rmi_function *entry;
> + int i;
> int error;
>
> if (!data)
> @@ -173,16 +157,8 @@ static int rmi_process_interrupt_requests(struct
> rmi_device *rmi_dev)
> */
> mutex_unlock(&data->irq_mutex);
>
> - /*
> - * It would be nice to be able to use irq_chip to handle
> these
> - * nested IRQs. Unfortunately, most of the current
> customers for
> - * this driver are using older kernels (3.0.x) that don't
> support
> - * the features required for that. Once they've shifted to
> more
> - * recent kernels (say, 3.3 and higher), this should be
> switched to
> - * use irq_chip.
> - */
> - list_for_each_entry(entry, &data->function_list, node)
> - process_one_interrupt(data, entry);
> + for_each_set_bit(i, data->irq_status, data->irq_count)
> + handle_nested_irq(irq_find_mapping(data->irqdomain,
> i));
>
> if (data->input)
> input_sync(data->input);
> @@ -847,6 +823,10 @@ int rmi_initial_reset(struct rmi_device
> *rmi_dev, void *ctx,
> return pdt->page_start == 0 ? RMI_SCAN_CONTINUE : -ENODEV;
> }
>
> +static struct irq_chip rmi_irq_chip = {
> + .name = "rmi4",
> +};
> +
> static int rmi_create_function(struct rmi_device *rmi_dev,
> void *ctx, const struct pdt_entry
> *pdt)
> {
> @@ -878,9 +858,18 @@ static int rmi_create_function(struct rmi_device
> *rmi_dev,
> fn->irq_pos = *current_irq_count;
> *current_irq_count += fn->num_of_irqs;
>
> - for (i = 0; i < fn->num_of_irqs; i++)
> + for (i = 0; i < fn->num_of_irqs; i++) {
> set_bit(fn->irq_pos + i, fn->irq_mask);
>
> + fn->irq_base = irq_create_mapping(data->irqdomain,
> + fn->irq_pos + i);
> +
> +
> + irq_set_chip_data(fn->irq_base, data);
> + irq_set_chip_and_handler(fn->irq_base,
> &rmi_irq_chip,
> + handle_simple_irq);
> + }
> +
> error = rmi_register_function(fn);
> if (error)
> goto err_put_fn;
> @@ -1000,9 +989,12 @@ EXPORT_SYMBOL_GPL(rmi_driver_resume);
> static int rmi_driver_remove(struct device *dev)
> {
> struct rmi_device *rmi_dev = to_rmi_device(dev);
> + struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev-
> >dev);
>
> rmi_disable_irq(rmi_dev, false);
>
> + irq_domain_remove(data->irqdomain);
> +
> rmi_f34_remove_sysfs(rmi_dev);
> rmi_free_function_list(rmi_dev);
>
> @@ -1034,7 +1026,8 @@ int rmi_probe_interrupts(struct rmi_driver_data
> *data)
> {
> struct rmi_device *rmi_dev = data->rmi_dev;
> struct device *dev = &rmi_dev->dev;
> - int irq_count;
> + struct device_node *rmi_of_node = rmi_dev->xport->dev-
> >of_node;
> + int irq_count = 0;
> size_t size;
> int retval;
>
> @@ -1045,7 +1038,6 @@ int rmi_probe_interrupts(struct rmi_driver_data
> *data)
> * being accessed.
> */
> rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Counting IRQs.\n",
> __func__);
> - irq_count = 0;
> data->bootloader_mode = false;
>
> retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_count_irqs);
> @@ -1057,6 +1049,14 @@ int rmi_probe_interrupts(struct
> rmi_driver_data *data)
> if (data->bootloader_mode)
> dev_warn(dev, "Device in bootloader mode.\n");
>
> + /* Allocate and register a linear revmap irq_domain */
> + data->irqdomain = irq_domain_add_linear(rmi_of_node,
> irq_count,
> + &irq_domain_simple_o
> ps, data);
> + if (!data->irqdomain) {
> + dev_err(&rmi_dev->dev, "Failed to create IRQ
> domain\n");
> + return PTR_ERR(data->irqdomain);
> + }
> +
> data->irq_count = irq_count;
> data->num_of_irq_regs = (data->irq_count + 7) / 8;
>
> @@ -1079,10 +1079,9 @@ int rmi_init_functions(struct rmi_driver_data
> *data)
> {
> struct rmi_device *rmi_dev = data->rmi_dev;
> struct device *dev = &rmi_dev->dev;
> - int irq_count;
> + int irq_count = 0;
> int retval;
>
> - irq_count = 0;
> rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Creating functions.\n",
> __func__);
> retval = rmi_scan_pdt(rmi_dev, &irq_count,
> rmi_create_function);
> if (retval < 0) {
> diff --git a/drivers/input/rmi4/rmi_f01.c
> b/drivers/input/rmi4/rmi_f01.c
> index 8a07ae1..4edaa14 100644
> --- a/drivers/input/rmi4/rmi_f01.c
> +++ b/drivers/input/rmi4/rmi_f01.c
> @@ -681,9 +681,9 @@ static int rmi_f01_resume(struct rmi_function
> *fn)
> return 0;
> }
>
> -static int rmi_f01_attention(struct rmi_function *fn,
> - unsigned long *irq_bits)
> +static irqreturn_t rmi_f01_attention(int irq, void *ctx)
> {
> + struct rmi_function *fn = ctx;
> struct rmi_device *rmi_dev = fn->rmi_dev;
> int error;
> u8 device_status;
> @@ -692,7 +692,7 @@ static int rmi_f01_attention(struct rmi_function
> *fn,
> if (error) {
> dev_err(&fn->dev,
> "Failed to read device status: %d.\n",
> error);
> - return error;
> + return IRQ_RETVAL(error);
> }
>
> if (RMI_F01_STATUS_BOOTLOADER(device_status))
> @@ -704,11 +704,11 @@ static int rmi_f01_attention(struct
> rmi_function *fn,
> error = rmi_dev->driver->reset_handler(rmi_dev);
> if (error) {
> dev_err(&fn->dev, "Device reset failed:
> %d\n", error);
> - return error;
> + return IRQ_RETVAL(error);
> }
> }
>
> - return 0;
> + return IRQ_HANDLED;
> }
>
> struct rmi_function_handler rmi_f01_handler = {
> diff --git a/drivers/input/rmi4/rmi_f03.c
> b/drivers/input/rmi4/rmi_f03.c
> index ad71a5e..b9f07c9 100644
> --- a/drivers/input/rmi4/rmi_f03.c
> +++ b/drivers/input/rmi4/rmi_f03.c
> @@ -199,8 +199,9 @@ static int rmi_f03_config(struct rmi_function
> *fn)
> return 0;
> }
>
> -static int rmi_f03_attention(struct rmi_function *fn, unsigned long
> *irq_bits)
> +static irqreturn_t rmi_f03_attention(int irq, void *ctx)
> {
> + struct rmi_function *fn = ctx;
> struct rmi_device *rmi_dev = fn->rmi_dev;
> struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev-
> >dev);
> struct f03_data *f03 = dev_get_drvdata(&fn->dev);
> @@ -217,7 +218,7 @@ static int rmi_f03_attention(struct rmi_function
> *fn, unsigned long *irq_bits)
> /* First grab the data passed by the transport
> device */
> if (drvdata->attn_data.size < ob_len) {
> dev_warn(&fn->dev, "F03 interrupted, but
> data is missing!\n");
> - return 0;
> + return IRQ_HANDLED;
> }
>
> memcpy(obs, drvdata->attn_data.data, ob_len);
> @@ -233,7 +234,7 @@ static int rmi_f03_attention(struct rmi_function
> *fn, unsigned long *irq_bits)
> "%s: Failed to read F03 output
> buffers: %d\n",
> __func__, error);
> serio_interrupt(f03->serio, 0,
> SERIO_TIMEOUT);
> - return error;
> + return IRQ_RETVAL(error);
> }
> }
>
> @@ -259,7 +260,7 @@ static int rmi_f03_attention(struct rmi_function
> *fn, unsigned long *irq_bits)
> serio_interrupt(f03->serio, ob_data, serio_flags);
> }
>
> - return 0;
> + return IRQ_HANDLED;
> }
>
> static void rmi_f03_remove(struct rmi_function *fn)
> diff --git a/drivers/input/rmi4/rmi_f11.c
> b/drivers/input/rmi4/rmi_f11.c
> index bc5e37f..e587c87 100644
> --- a/drivers/input/rmi4/rmi_f11.c
> +++ b/drivers/input/rmi4/rmi_f11.c
> @@ -571,8 +571,7 @@ static inline u8 rmi_f11_parse_finger_state(const
> u8 *f_state, u8 n_finger)
>
> static void rmi_f11_finger_handler(struct f11_data *f11,
> struct rmi_2d_sensor *sensor,
> - unsigned long *irq_bits, int
> num_irq_regs,
> - int size)
> + int num_irq_regs, int size)
> {
> const u8 *f_state = f11->data.f_state;
> u8 finger_state;
> @@ -581,12 +580,7 @@ static void rmi_f11_finger_handler(struct
> f11_data *f11,
> int rel_fingers;
> int abs_size = sensor->nbr_fingers * RMI_F11_ABS_BYTES;
>
> - int abs_bits = bitmap_and(f11->result_bits, irq_bits, f11-
> >abs_mask,
> - num_irq_regs * 8);
> - int rel_bits = bitmap_and(f11->result_bits, irq_bits, f11-
> >rel_mask,
> - num_irq_regs * 8);
> -
> - if (abs_bits) {
> + if (sensor->report_abs) {
> if (abs_size > size)
> abs_fingers = size / RMI_F11_ABS_BYTES;
> else
> @@ -606,7 +600,7 @@ static void rmi_f11_finger_handler(struct
> f11_data *f11,
> }
> }
>
> - if (rel_bits) {
> + if (sensor->report_rel) {
> if ((abs_size + sensor->nbr_fingers *
> RMI_F11_REL_BYTES) > size)
> rel_fingers = (size - abs_size) /
> RMI_F11_REL_BYTES;
> else
> @@ -616,7 +610,7 @@ static void rmi_f11_finger_handler(struct
> f11_data *f11,
> rmi_f11_rel_pos_report(f11, i);
> }
>
> - if (abs_bits) {
> + if (sensor->report_abs) {
> /*
> * the absolute part is made in 2 parts to allow the
> kernel
> * tracking to take place.
> @@ -1275,8 +1269,9 @@ static int rmi_f11_config(struct rmi_function
> *fn)
> return 0;
> }
>
> -static int rmi_f11_attention(struct rmi_function *fn, unsigned long
> *irq_bits)
> +static irqreturn_t rmi_f11_attention(int irq, void *ctx)
> {
> + struct rmi_function *fn = ctx;
> struct rmi_device *rmi_dev = fn->rmi_dev;
> struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev-
> >dev);
> struct f11_data *f11 = dev_get_drvdata(&fn->dev);
> @@ -1302,13 +1297,13 @@ static int rmi_f11_attention(struct
> rmi_function *fn, unsigned long *irq_bits)
> data_base_addr, f11-
> >sensor.data_pkt,
> f11->sensor.pkt_size);
> if (error < 0)
> - return error;
> + return IRQ_RETVAL(error);
> }
>
> - rmi_f11_finger_handler(f11, &f11->sensor, irq_bits,
> - drvdata->num_of_irq_regs,
> valid_bytes);
> + rmi_f11_finger_handler(f11, &f11->sensor,
> + drvdata->num_of_irq_regs,
> valid_bytes);
>
> - return 0;
> + return IRQ_HANDLED;
> }
>
> static int rmi_f11_resume(struct rmi_function *fn)
> diff --git a/drivers/input/rmi4/rmi_f12.c
> b/drivers/input/rmi4/rmi_f12.c
> index 8b0db08..e226def 100644
> --- a/drivers/input/rmi4/rmi_f12.c
> +++ b/drivers/input/rmi4/rmi_f12.c
> @@ -197,10 +197,10 @@ static void rmi_f12_process_objects(struct
> f12_data *f12, u8 *data1, int size)
> rmi_2d_sensor_abs_report(sensor, &sensor->objs[i],
> i);
> }
>
> -static int rmi_f12_attention(struct rmi_function *fn,
> - unsigned long *irq_nr_regs)
> +static irqreturn_t rmi_f12_attention(int irq, void *ctx)
> {
> int retval;
> + struct rmi_function *fn = ctx;
> struct rmi_device *rmi_dev = fn->rmi_dev;
> struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev-
> >dev);
> struct f12_data *f12 = dev_get_drvdata(&fn->dev);
> @@ -222,7 +222,7 @@ static int rmi_f12_attention(struct rmi_function
> *fn,
> if (retval < 0) {
> dev_err(&fn->dev, "Failed to read object
> data. Code: %d.\n",
> retval);
> - return retval;
> + return IRQ_RETVAL(retval);
> }
> }
>
> @@ -232,7 +232,7 @@ static int rmi_f12_attention(struct rmi_function
> *fn,
>
> input_mt_sync_frame(sensor->input);
>
> - return 0;
> + return IRQ_HANDLED;
> }
>
> static int rmi_f12_write_control_regs(struct rmi_function *fn)
> diff --git a/drivers/input/rmi4/rmi_f30.c
> b/drivers/input/rmi4/rmi_f30.c
> index 82e0f0d..5e3ed5a 100644
> --- a/drivers/input/rmi4/rmi_f30.c
> +++ b/drivers/input/rmi4/rmi_f30.c
> @@ -122,8 +122,9 @@ static void rmi_f30_report_button(struct
> rmi_function *fn,
> }
> }
>
> -static int rmi_f30_attention(struct rmi_function *fn, unsigned long
> *irq_bits)
> +static irqreturn_t rmi_f30_attention(int irq, void *ctx)
> {
> + struct rmi_function *fn = ctx;
> struct f30_data *f30 = dev_get_drvdata(&fn->dev);
> struct rmi_driver_data *drvdata = dev_get_drvdata(&fn-
> >rmi_dev->dev);
> int error;
> @@ -134,7 +135,7 @@ static int rmi_f30_attention(struct rmi_function
> *fn, unsigned long *irq_bits)
> if (drvdata->attn_data.size < f30->register_count) {
> dev_warn(&fn->dev,
> "F30 interrupted, but data is
> missing\n");
> - return 0;
> + return IRQ_HANDLED;
> }
> memcpy(f30->data_regs, drvdata->attn_data.data,
> f30->register_count);
> @@ -147,7 +148,7 @@ static int rmi_f30_attention(struct rmi_function
> *fn, unsigned long *irq_bits)
> dev_err(&fn->dev,
> "%s: Failed to read F30 data
> registers: %d\n",
> __func__, error);
> - return error;
> + return IRQ_RETVAL(error);
> }
> }
>
> @@ -159,7 +160,7 @@ static int rmi_f30_attention(struct rmi_function
> *fn, unsigned long *irq_bits)
> rmi_f03_commit_buttons(f30->f03);
> }
>
> - return 0;
> + return IRQ_HANDLED;
> }
>
> static int rmi_f30_config(struct rmi_function *fn)
> diff --git a/drivers/input/rmi4/rmi_f34.c
> b/drivers/input/rmi4/rmi_f34.c
> index 4cfe970..7268cf9 100644
> --- a/drivers/input/rmi4/rmi_f34.c
> +++ b/drivers/input/rmi4/rmi_f34.c
> @@ -101,8 +101,9 @@ static int rmi_f34_command(struct f34_data *f34,
> u8 command,
> return 0;
> }
>
> -static int rmi_f34_attention(struct rmi_function *fn, unsigned long
> *irq_bits)
> +static irqreturn_t rmi_f34_attention(int irq, void *ctx)
> {
> + struct rmi_function *fn = ctx;
> struct f34_data *f34 = dev_get_drvdata(&fn->dev);
> int ret;
> u8 status;
> @@ -127,7 +128,7 @@ static int rmi_f34_attention(struct rmi_function
> *fn, unsigned long *irq_bits)
> complete(&f34->v7.cmd_done);
> }
>
> - return 0;
> + return IRQ_HANDLED;
> }
>
> static int rmi_f34_write_blocks(struct f34_data *f34, const void
> *data,
> diff --git a/drivers/input/rmi4/rmi_f54.c
> b/drivers/input/rmi4/rmi_f54.c
> index 5343f2c..98a935e 100644
> --- a/drivers/input/rmi4/rmi_f54.c
> +++ b/drivers/input/rmi4/rmi_f54.c
> @@ -610,11 +610,6 @@ static void rmi_f54_work(struct work_struct
> *work)
> mutex_unlock(&f54->data_mutex);
> }
>
> -static int rmi_f54_attention(struct rmi_function *fn, unsigned long
> *irqbits)
> -{
> - return 0;
> -}
> -
> static int rmi_f54_config(struct rmi_function *fn)
> {
> struct rmi_driver *drv = fn->rmi_dev->driver;
> @@ -756,6 +751,5 @@ struct rmi_function_handler rmi_f54_handler = {
> .func = 0x54,
> .probe = rmi_f54_probe,
> .config = rmi_f54_config,
> - .attention = rmi_f54_attention,
> .remove = rmi_f54_remove,
> };
> diff --git a/include/linux/rmi.h b/include/linux/rmi.h
> index 64125443..5ef5c7c 100644
> --- a/include/linux/rmi.h
> +++ b/include/linux/rmi.h
> @@ -354,6 +354,8 @@ struct rmi_driver_data {
> struct mutex irq_mutex;
> struct input_dev *input;
>
> + struct irq_domain *irqdomain;
> +
> u8 pdt_props;
>
> u8 num_rx_electrodes;
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox