From 41e81022a04a0294c55cfa7e366bc14b9634c66e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 24 May 2021 10:02:59 -0700 Subject: Input: usbtouchscreen - fix control-request directions The direction of the pipe argument must match the request-type direction bit or control requests may fail depending on the host-controller-driver implementation. Fix the four control requests which erroneously used usb_rcvctrlpipe(). Fixes: 1d3e20236d7a ("[PATCH] USB: usbtouchscreen: unified USB touchscreen driver") Fixes: 24ced062a296 ("usbtouchscreen: add support for DMC TSC-10/25 devices") Fixes: 9e3b25837a20 ("Input: usbtouchscreen - add support for e2i touchscreen controller") Signed-off-by: Johan Hovold Cc: stable@vger.kernel.org # 2.6.17 Link: https://lore.kernel.org/r/20210524092048.4443-1-johan@kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/usbtouchscreen.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index c847453a03c2..43c521f50c85 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -251,7 +251,7 @@ static int e2i_init(struct usbtouch_usb *usbtouch) int ret; struct usb_device *udev = interface_to_usbdev(usbtouch->interface); - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01, 0x02, 0x0000, 0x0081, NULL, 0, USB_CTRL_SET_TIMEOUT); @@ -531,7 +531,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch) if (ret) return ret; - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), MTOUCHUSB_RESET, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); @@ -543,7 +543,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch) msleep(150); for (i = 0; i < 3; i++) { - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), MTOUCHUSB_ASYNC_REPORT, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); @@ -722,7 +722,7 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) } /* start sending data */ - ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), TSC10_CMD_DATA1, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); -- cgit v1.2.3 From 0b1d6c8c00157cbfcf343925c4de81af0187a7b7 Mon Sep 17 00:00:00 2001 From: Chris Ye Date: Mon, 24 May 2021 20:53:11 -0700 Subject: Input: xpad - map "Select" button on Microsoft Xbox One controller Add "Select" button input capability and input event mapping for Microsoft Xbox One controller. From product site this is also referred as "Share" button. Signed-off-by: Chris Ye Reviewed-by: Bastien Nocera Link: https://lore.kernel.org/r/20210414021201.2462114-1-lzye@google.com Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index d69d7657ab12..29de8412e416 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -79,6 +79,7 @@ #define MAP_DPAD_TO_BUTTONS (1 << 0) #define MAP_TRIGGERS_TO_BUTTONS (1 << 1) #define MAP_STICKS_TO_NULL (1 << 2) +#define MAP_SELECT_BUTTON (1 << 3) #define DANCEPAD_MAP_CONFIG (MAP_DPAD_TO_BUTTONS | \ MAP_TRIGGERS_TO_BUTTONS | MAP_STICKS_TO_NULL) @@ -130,6 +131,7 @@ static const struct xpad_device { { 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", 0, XTYPE_XBOXONE }, { 0x045e, 0x02ea, "Microsoft X-Box One S pad", 0, XTYPE_XBOXONE }, { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, + { 0x045e, 0x0b12, "Microsoft Xbox One X pad", MAP_SELECT_BUTTON, XTYPE_XBOXONE }, { 0x046d, 0xc21d, "Logitech Gamepad F310", 0, XTYPE_XBOX360 }, { 0x046d, 0xc21e, "Logitech Gamepad F510", 0, XTYPE_XBOX360 }, { 0x046d, 0xc21f, "Logitech Gamepad F710", 0, XTYPE_XBOX360 }, @@ -864,6 +866,8 @@ static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char /* menu/view buttons */ input_report_key(dev, BTN_START, data[4] & 0x04); input_report_key(dev, BTN_SELECT, data[4] & 0x08); + if (xpad->mapping & MAP_SELECT_BUTTON) + input_report_key(dev, KEY_RECORD, data[22] & 0x01); /* buttons A,B,X,Y */ input_report_key(dev, BTN_A, data[4] & 0x10); @@ -1674,6 +1678,8 @@ static int xpad_init_input(struct usb_xpad *xpad) xpad->xtype == XTYPE_XBOXONE) { for (i = 0; xpad360_btn[i] >= 0; i++) input_set_capability(input_dev, EV_KEY, xpad360_btn[i]); + if (xpad->mapping & MAP_SELECT_BUTTON) + input_set_capability(input_dev, EV_KEY, KEY_RECORD); } else { for (i = 0; xpad_btn[i] >= 0; i++) input_set_capability(input_dev, EV_KEY, xpad_btn[i]); -- cgit v1.2.3 From d9b576917a1d0efa293801a264150a1b37691617 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Mon, 24 May 2021 11:52:42 -0700 Subject: Input: hil_kbd - fix error return code in hil_dev_connect() Return error code -EINVAL rather than '0' when the combo devices are not supported. Fixes: fa71c605c2bb ("Input: combine hil_kbd and hil_ptr drivers") Reported-by: Hulk Robot Signed-off-by: Zhen Lei Link: https://lore.kernel.org/r/20210515030053.6824-1-thunder.leizhen@huawei.com Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/hil_kbd.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index bb29a7c9a1c0..54afb38601b9 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c @@ -512,6 +512,7 @@ static int hil_dev_connect(struct serio *serio, struct serio_driver *drv) HIL_IDD_NUM_AXES_PER_SET(*idd)) { printk(KERN_INFO PREFIX "combo devices are not supported.\n"); + error = -EINVAL; goto bail1; } -- cgit v1.2.3 From 204db365077df99a487bcd41aa8c6135f783be18 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 24 Apr 2021 22:26:19 -0700 Subject: Input: evbug - remove an empty comment block This is a left-over from commit 1a59d1b8e05e ("treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156") Axe an empty and useless comment block. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/fda981546203427a0ac86ef47f231239ad18ecfe.1618520227.git.christophe.jaillet@wanadoo.fr Signed-off-by: Dmitry Torokhov --- drivers/input/evbug.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c index c0d0b121ae7e..e47bdf92088a 100644 --- a/drivers/input/evbug.c +++ b/drivers/input/evbug.c @@ -7,9 +7,6 @@ * Input driver event debug module - dumps all events into syslog */ -/* - */ - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -- cgit v1.2.3 From 94a332bd8626f6c32e7ba5835dd17eeddbb76e89 Mon Sep 17 00:00:00 2001 From: Shubhankar Kuranagatti Date: Wed, 28 Apr 2021 12:28:09 -0700 Subject: Input: ims-pcu - replace some spaces with tabs Unnecessary spaces have been replaced with tab space. This is done to maintain code uniformity. Signed-off-by: Shubhankar Kuranagatti Link: https://lore.kernel.org/r/20210428091050.ryr7kxlxre7uhye4@kewl-virtual-machine Signed-off-by: Dmitry Torokhov --- drivers/input/misc/ims-pcu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c index 81de8c4e37d0..7169255efb37 100644 --- a/drivers/input/misc/ims-pcu.c +++ b/drivers/input/misc/ims-pcu.c @@ -647,8 +647,8 @@ static int __ims_pcu_execute_command(struct ims_pcu *pcu, #define IMS_PCU_BL_DATA_OFFSET 3 static int __ims_pcu_execute_bl_command(struct ims_pcu *pcu, - u8 command, const void *data, size_t len, - u8 expected_response, int response_time) + u8 command, const void *data, size_t len, + u8 expected_response, int response_time) { int error; -- cgit v1.2.3 From fb082cd59afa7fbd3a610e9835050675040b1b99 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Tue, 25 May 2021 11:55:57 -0700 Subject: Input: resistive-adc-touch - add support for z1 and z2 channels This patch adds support for the z1 and z2 channels. These are used to calculate the applied pressure. As there is no common order of the individual channels of a resistive touch ADC, support for io-channel-names is added (although the DT bindings stated the driver already supports these). Signed-off-by: Oleksij Rempel Reviewed-by: Jonathan Cameron Link: https://lore.kernel.org/r/20210525054634.9134-5-o.rempel@pengutronix.de Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/resistive-adc-touch.c | 140 +++++++++++++++++++++--- 1 file changed, 126 insertions(+), 14 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/resistive-adc-touch.c b/drivers/input/touchscreen/resistive-adc-touch.c index e50af30183f4..0939c0e97efb 100644 --- a/drivers/input/touchscreen/resistive-adc-touch.c +++ b/drivers/input/touchscreen/resistive-adc-touch.c @@ -20,7 +20,18 @@ #define DRIVER_NAME "resistive-adc-touch" #define GRTS_DEFAULT_PRESSURE_MIN 50000 +#define GRTS_DEFAULT_PRESSURE_MAX 65535 #define GRTS_MAX_POS_MASK GENMASK(11, 0) +#define GRTS_MAX_CHANNELS 4 + +enum grts_ch_type { + GRTS_CH_NONE = 0, + GRTS_CH_X, + GRTS_CH_Y, + GRTS_CH_PRESSURE, + GRTS_CH_Z1, + GRTS_CH_Z2, +}; /** * struct grts_state - generic resistive touch screen information struct @@ -33,24 +44,59 @@ */ struct grts_state { u32 pressure_min; + u32 x_plate_ohms; bool pressure; struct iio_channel *iio_chans; struct iio_cb_buffer *iio_cb; struct input_dev *input; struct touchscreen_properties prop; + u8 ch[GRTS_MAX_CHANNELS]; }; static int grts_cb(const void *data, void *private) { const u16 *touch_info = data; struct grts_state *st = private; - unsigned int x, y, press = 0x0; + unsigned int x, y, press = 0, z1 = 0, z2; + unsigned int Rt, i; + + for (i = 0; i < ARRAY_SIZE(st->ch) && st->ch[i] != GRTS_CH_NONE; i++) { + switch (st->ch[i]) { + case GRTS_CH_X: + x = touch_info[i]; + break; + case GRTS_CH_Y: + y = touch_info[i]; + break; + case GRTS_CH_PRESSURE: + press = touch_info[i]; + break; + case GRTS_CH_Z1: + z1 = touch_info[i]; + break; + case GRTS_CH_Z2: + z2 = touch_info[i]; + break; + } + } - /* channel data coming in buffer in the order below */ - x = touch_info[0]; - y = touch_info[1]; - if (st->pressure) - press = touch_info[2]; + if (z1) { + Rt = z2; + Rt -= z1; + Rt *= st->x_plate_ohms; + Rt = DIV_ROUND_CLOSEST(Rt, 16); + Rt *= x; + Rt /= z1; + Rt = DIV_ROUND_CLOSEST(Rt, 256); + /* + * On increased pressure the resistance (Rt) is decreasing + * so, convert values to make it looks as real pressure. + */ + if (Rt < GRTS_DEFAULT_PRESSURE_MAX) + press = GRTS_DEFAULT_PRESSURE_MAX - Rt; + else + press = 0; + } if ((!x && !y) || (st->pressure && (press < st->pressure_min))) { /* report end of touch */ @@ -94,12 +140,77 @@ static void grts_disable(void *data) iio_channel_release_all_cb(data); } +static int grts_get_properties(struct grts_state *st, struct device *dev) +{ + int idx, error; + + idx = device_property_match_string(dev, "io-channel-names", "x"); + if (idx < 0) + return idx; + + if (idx >= ARRAY_SIZE(st->ch)) + return -EOVERFLOW; + + st->ch[idx] = GRTS_CH_X; + + idx = device_property_match_string(dev, "io-channel-names", "y"); + if (idx < 0) + return idx; + + if (idx >= ARRAY_SIZE(st->ch)) + return -EOVERFLOW; + + st->ch[idx] = GRTS_CH_Y; + + /* pressure is optional */ + idx = device_property_match_string(dev, "io-channel-names", "pressure"); + if (idx >= 0) { + if (idx >= ARRAY_SIZE(st->ch)) + return -EOVERFLOW; + + st->ch[idx] = GRTS_CH_PRESSURE; + st->pressure = true; + + return 0; + } + + /* if no pressure is defined, try optional z1 + z2 */ + idx = device_property_match_string(dev, "io-channel-names", "z1"); + if (idx < 0) + return 0; + + if (idx >= ARRAY_SIZE(st->ch)) + return -EOVERFLOW; + + st->ch[idx] = GRTS_CH_Z1; + + /* if z1 is provided z2 is not optional */ + idx = device_property_match_string(dev, "io-channel-names", "z2"); + if (idx < 0) + return idx; + + if (idx >= ARRAY_SIZE(st->ch)) + return -EOVERFLOW; + + st->ch[idx] = GRTS_CH_Z2; + st->pressure = true; + + error = device_property_read_u32(dev, + "touchscreen-x-plate-ohms", + &st->x_plate_ohms); + if (error) { + dev_err(dev, "can't get touchscreen-x-plate-ohms property\n"); + return error; + } + + return 0; +} + static int grts_probe(struct platform_device *pdev) { struct grts_state *st; struct input_dev *input; struct device *dev = &pdev->dev; - struct iio_channel *chan; int error; st = devm_kzalloc(dev, sizeof(struct grts_state), GFP_KERNEL); @@ -115,12 +226,13 @@ static int grts_probe(struct platform_device *pdev) return error; } - chan = &st->iio_chans[0]; - st->pressure = false; - while (chan && chan->indio_dev) { - if (!strcmp(chan->channel->datasheet_name, "pressure")) - st->pressure = true; - chan++; + if (!device_property_present(dev, "io-channel-names")) + return -ENODEV; + + error = grts_get_properties(st, dev); + if (error) { + dev_err(dev, "Failed to parse properties\n"); + return error; } if (st->pressure) { @@ -148,7 +260,7 @@ static int grts_probe(struct platform_device *pdev) input_set_abs_params(input, ABS_Y, 0, GRTS_MAX_POS_MASK - 1, 0, 0); if (st->pressure) input_set_abs_params(input, ABS_PRESSURE, st->pressure_min, - 0xffff, 0, 0); + GRTS_DEFAULT_PRESSURE_MAX, 0, 0); input_set_capability(input, EV_KEY, BTN_TOUCH); -- cgit v1.2.3 From 007704c99f52e22cd93bcc16c610d7c1a41fd9cd Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 26 May 2021 16:34:41 -0700 Subject: Input: cyttsp - probe from compatibles The driver (both SPI and I2C interface) should probe from the compatible strings, cypress,cy8ctma340 etc when using device tree, not as now, where it is probing implicitly from the I2C/SPI node name "cypress,cyttsp-i2c" etc. Reviewed-by: Javier Martinez Canillas Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20210526230352.1433537-2-linus.walleij@linaro.org Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cyttsp_i2c.c | 8 ++++++++ drivers/input/touchscreen/cyttsp_spi.c | 8 ++++++++ 2 files changed, 16 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c index 061debf64a2b..0a09f07bc23a 100644 --- a/drivers/input/touchscreen/cyttsp_i2c.c +++ b/drivers/input/touchscreen/cyttsp_i2c.c @@ -52,10 +52,18 @@ static const struct i2c_device_id cyttsp_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id); +static const struct of_device_id cyttsp_of_i2c_match[] = { + { .compatible = "cypress,cy8ctma340", }, + { .compatible = "cypress,cy8ctst341", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, cyttsp_of_i2c_match); + static struct i2c_driver cyttsp_i2c_driver = { .driver = { .name = CY_I2C_NAME, .pm = &cyttsp_pm_ops, + .of_match_table = cyttsp_of_i2c_match, }, .probe = cyttsp_i2c_probe, .id_table = cyttsp_i2c_id, diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c index 54e410921d53..8715e5354d79 100644 --- a/drivers/input/touchscreen/cyttsp_spi.c +++ b/drivers/input/touchscreen/cyttsp_spi.c @@ -160,10 +160,18 @@ static int cyttsp_spi_probe(struct spi_device *spi) return 0; } +static const struct of_device_id cyttsp_of_spi_match[] = { + { .compatible = "cypress,cy8ctma340", }, + { .compatible = "cypress,cy8ctst341", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, cyttsp_of_spi_match); + static struct spi_driver cyttsp_spi_driver = { .driver = { .name = CY_SPI_NAME, .pm = &cyttsp_pm_ops, + .of_match_table = cyttsp_of_spi_match, }, .probe = cyttsp_spi_probe, }; -- cgit v1.2.3 From 6cf3b3abbf0b3b778138c0f8936aa7820af62cfc Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 26 May 2021 16:35:11 -0700 Subject: Input: cyttsp - obtain regulators The CYTTSP TMA340 chips have two supplies: VCPIN and VDD for analog and digital voltage respectively. Add some minimal code to obtain and enable these regulators if need be. Reviewed-by: Javier Martinez Canillas Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20210526230352.1433537-3-linus.walleij@linaro.org Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cyttsp_core.c | 35 +++++++++++++++++++++++++++++++++ drivers/input/touchscreen/cyttsp_core.h | 2 ++ 2 files changed, 37 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index 106dd4962785..d9debcdeeec7 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "cyttsp_core.h" @@ -608,6 +609,14 @@ static int cyttsp_parse_properties(struct cyttsp *ts) return 0; } +static void cyttsp_disable_regulators(void *_ts) +{ + struct cyttsp *ts = _ts; + + regulator_bulk_disable(ARRAY_SIZE(ts->regulators), + ts->regulators); +} + struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, struct device *dev, int irq, size_t xfer_buf_size) { @@ -628,6 +637,32 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, ts->bus_ops = bus_ops; ts->irq = irq; + /* + * VCPIN is the analog voltage supply + * VDD is the digital voltage supply + */ + ts->regulators[0].supply = "vcpin"; + ts->regulators[1].supply = "vdd"; + error = devm_regulator_bulk_get(dev, ARRAY_SIZE(ts->regulators), + ts->regulators); + if (error) { + dev_err(dev, "Failed to get regulators: %d\n", error); + return ERR_PTR(error); + } + + error = regulator_bulk_enable(ARRAY_SIZE(ts->regulators), + ts->regulators); + if (error) { + dev_err(dev, "Cannot enable regulators: %d\n", error); + return ERR_PTR(error); + } + + error = devm_add_action_or_reset(dev, cyttsp_disable_regulators, ts); + if (error) { + dev_err(dev, "failed to install chip disable handler\n"); + return ERR_PTR(error); + } + ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(ts->reset_gpio)) { error = PTR_ERR(ts->reset_gpio); diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h index 9bc4fe7e6ac5..8eba9d8ba74a 100644 --- a/drivers/input/touchscreen/cyttsp_core.h +++ b/drivers/input/touchscreen/cyttsp_core.h @@ -23,6 +23,7 @@ #include #include #include +#include #define CY_NUM_RETRY 16 /* max number of retries for read ops */ @@ -122,6 +123,7 @@ struct cyttsp { enum cyttsp_state state; bool suspended; + struct regulator_bulk_data regulators[2]; struct gpio_desc *reset_gpio; bool use_hndshk; u8 act_dist; -- cgit v1.2.3 From b9c0ebb867d67cc4e9e1a7a2abf0ac9a2cc02051 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 30 May 2021 21:43:36 -0700 Subject: Input: elants_i2c - fix NULL dereference at probing The recent change in elants_i2c driver to support more chips introduced a regression leading to Oops at probing. The driver reads id->driver_data, but the id may be NULL depending on the device type the driver gets bound. Replace the driver data extraction with the device_get_match_data() helper, and define the driver data in OF table, too. Fixes: 9517b95bdc46 ("Input: elants_i2c - add support for eKTF3624") BugLink: https://bugzilla.suse.com/show_bug.cgi?id=1186454 Signed-off-by: Takashi Iwai Cc: Link: https://lore.kernel.org/r/20210528071024.26450-1-tiwai@suse.de Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/elants_i2c.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 17540bdb1eaf..0f9e3ec99aae 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -1396,7 +1396,7 @@ static int elants_i2c_probe(struct i2c_client *client, init_completion(&ts->cmd_done); ts->client = client; - ts->chip_id = (enum elants_chip_id)id->driver_data; + ts->chip_id = (enum elants_chip_id)(uintptr_t)device_get_match_data(&client->dev); i2c_set_clientdata(client, ts); ts->vcc33 = devm_regulator_get(&client->dev, "vcc33"); @@ -1636,8 +1636,8 @@ MODULE_DEVICE_TABLE(acpi, elants_acpi_id); #ifdef CONFIG_OF static const struct of_device_id elants_of_match[] = { - { .compatible = "elan,ekth3500" }, - { .compatible = "elan,ektf3624" }, + { .compatible = "elan,ekth3500", .data = (void *)EKTH3500 }, + { .compatible = "elan,ektf3624", .data = (void *)EKTF3624 }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, elants_of_match); -- cgit v1.2.3 From 45a4b68354ffccbc9ca71027bd34754ca24f5183 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 30 May 2021 21:44:04 -0700 Subject: Input: elants_i2c - switch to probe_new Now that we get rid of the usage of id argument at probe again, let's switch to the new i2c probe method; this will avoid for people misusing the possibly unassigned id pointer again. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20210528071024.26450-2-tiwai@suse.de Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/elants_i2c.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 0f9e3ec99aae..68f542bb809f 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -1369,8 +1369,7 @@ static bool elants_acpi_is_hid_device(struct device *dev) } #endif -static int elants_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int elants_i2c_probe(struct i2c_client *client) { union i2c_smbus_data dummy; struct elants_data *ts; @@ -1644,7 +1643,7 @@ MODULE_DEVICE_TABLE(of, elants_of_match); #endif static struct i2c_driver elants_i2c_driver = { - .probe = elants_i2c_probe, + .probe_new = elants_i2c_probe, .id_table = elants_i2c_id, .driver = { .name = DEVICE_NAME, -- cgit v1.2.3 From c9d2939dda3ba121834dba053ff8ba5026f8ce37 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 30 May 2021 21:53:00 -0700 Subject: Input: cyttsp - do not force interrupt trigger Instead of forcing interrupt trigger to be "falling edge" let's rely on the platform to set it up according to how it is set up on a given board based on data in device tree or ACPI tables. Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/YK7iO96g+7yIC0l1@google.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cyttsp_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index d9debcdeeec7..a6352d79e23d 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c @@ -699,8 +699,7 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, } error = devm_request_threaded_irq(dev, ts->irq, NULL, cyttsp_irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT | - IRQF_NO_AUTOEN, + IRQF_ONESHOT | IRQF_NO_AUTOEN, "cyttsp", ts); if (error) { dev_err(ts->dev, "failed to request IRQ %d, err: %d\n", -- cgit v1.2.3 From 02e28cf7dc2b7acbe660188a87ac0b8007dde3dd Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sun, 30 May 2021 22:24:35 -0700 Subject: Input: resistive-adc-touch - describe parameters in kernel doc Validation script is not happy: resistive-adc-touch.c:53: warning: Function parameter or member 'x_plate_ohms' not described in 'grts_state' resistive-adc-touch.c:53: warning: Function parameter or member 'ch' not described in 'grts_state' Describe parameters in kernel doc to make it happy. Fixes: fb082cd59afa ("Input: resistive-adc-touch - add support for z1 and z2 channels") Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20210528151113.85943-1-andriy.shevchenko@linux.intel.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/resistive-adc-touch.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/resistive-adc-touch.c b/drivers/input/touchscreen/resistive-adc-touch.c index 0939c0e97efb..0353400c559a 100644 --- a/drivers/input/touchscreen/resistive-adc-touch.c +++ b/drivers/input/touchscreen/resistive-adc-touch.c @@ -35,16 +35,18 @@ enum grts_ch_type { /** * struct grts_state - generic resistive touch screen information struct + * @x_plate_ohms: resistance of the X plate * @pressure_min: number representing the minimum for the pressure * @pressure: are we getting pressure info or not * @iio_chans: list of channels acquired * @iio_cb: iio_callback buffer for the data * @input: the input device structure that we register * @prop: touchscreen properties struct + * @ch: channels that are defined for the touchscreen */ struct grts_state { - u32 pressure_min; u32 x_plate_ohms; + u32 pressure_min; bool pressure; struct iio_channel *iio_chans; struct iio_cb_buffer *iio_cb; -- cgit v1.2.3 From 08729298c4eea5a9bbc0598d92ff47638a97a1ae Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sun, 30 May 2021 22:25:01 -0700 Subject: Input: resistive-adc-touch - replace OF headers with proper ones The driver is actually OF independent and doesn't need anything from OF (*). Replace OF headers with mod_devicetable.h and property.h. *) use of of_match_ptr() is actually wrong here, since it may provoke a compiler to warn about unused variable. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20210528151113.85943-2-andriy.shevchenko@linux.intel.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/resistive-adc-touch.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/resistive-adc-touch.c b/drivers/input/touchscreen/resistive-adc-touch.c index 0353400c559a..ea1884fb49a1 100644 --- a/drivers/input/touchscreen/resistive-adc-touch.c +++ b/drivers/input/touchscreen/resistive-adc-touch.c @@ -13,10 +13,10 @@ #include #include #include +#include #include -#include -#include #include +#include #define DRIVER_NAME "resistive-adc-touch" #define GRTS_DEFAULT_PRESSURE_MIN 50000 @@ -307,7 +307,7 @@ static struct platform_driver grts_driver = { .probe = grts_probe, .driver = { .name = DRIVER_NAME, - .of_match_table = of_match_ptr(grts_of_match), + .of_match_table = grts_of_match, }, }; -- cgit v1.2.3 From 60b7db914dddcc94f455b62dbcc05b49d78f4cb6 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 1 Jun 2021 15:18:11 -0700 Subject: Input: resistive-adc-touch - rework mapping of channels Instead of iterating over channels establish and use channel map to retrieve data. As a side effect this will silence "uninitialized variable" warnings. Tested-by: Oleksij Rempel Link: https://lore.kernel.org/r/YLXR2brkc4H54xtK@google.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/resistive-adc-touch.c | 114 +++++++++++------------- 1 file changed, 51 insertions(+), 63 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/resistive-adc-touch.c b/drivers/input/touchscreen/resistive-adc-touch.c index ea1884fb49a1..ea7dd9d2b2ac 100644 --- a/drivers/input/touchscreen/resistive-adc-touch.c +++ b/drivers/input/touchscreen/resistive-adc-touch.c @@ -25,12 +25,12 @@ #define GRTS_MAX_CHANNELS 4 enum grts_ch_type { - GRTS_CH_NONE = 0, GRTS_CH_X, GRTS_CH_Y, GRTS_CH_PRESSURE, GRTS_CH_Z1, GRTS_CH_Z2, + GRTS_CH_MAX = GRTS_CH_Z2 + 1 }; /** @@ -42,7 +42,7 @@ enum grts_ch_type { * @iio_cb: iio_callback buffer for the data * @input: the input device structure that we register * @prop: touchscreen properties struct - * @ch: channels that are defined for the touchscreen + * @ch_map: map of channels that are defined for the touchscreen */ struct grts_state { u32 x_plate_ohms; @@ -52,37 +52,25 @@ struct grts_state { struct iio_cb_buffer *iio_cb; struct input_dev *input; struct touchscreen_properties prop; - u8 ch[GRTS_MAX_CHANNELS]; + u8 ch_map[GRTS_CH_MAX]; }; static int grts_cb(const void *data, void *private) { const u16 *touch_info = data; struct grts_state *st = private; - unsigned int x, y, press = 0, z1 = 0, z2; - unsigned int Rt, i; - - for (i = 0; i < ARRAY_SIZE(st->ch) && st->ch[i] != GRTS_CH_NONE; i++) { - switch (st->ch[i]) { - case GRTS_CH_X: - x = touch_info[i]; - break; - case GRTS_CH_Y: - y = touch_info[i]; - break; - case GRTS_CH_PRESSURE: - press = touch_info[i]; - break; - case GRTS_CH_Z1: - z1 = touch_info[i]; - break; - case GRTS_CH_Z2: - z2 = touch_info[i]; - break; - } - } + unsigned int x, y, press; + + x = touch_info[st->ch_map[GRTS_CH_X]]; + y = touch_info[st->ch_map[GRTS_CH_Y]]; + + if (st->ch_map[GRTS_CH_PRESSURE] < GRTS_MAX_CHANNELS) { + press = touch_info[st->ch_map[GRTS_CH_PRESSURE]]; + } else if (st->ch_map[GRTS_CH_Z1] < GRTS_MAX_CHANNELS) { + unsigned int z1 = touch_info[st->ch_map[GRTS_CH_Z1]]; + unsigned int z2 = touch_info[st->ch_map[GRTS_CH_Z2]]; + unsigned int Rt; - if (z1) { Rt = z2; Rt -= z1; Rt *= st->x_plate_ohms; @@ -142,60 +130,59 @@ static void grts_disable(void *data) iio_channel_release_all_cb(data); } -static int grts_get_properties(struct grts_state *st, struct device *dev) +static int grts_map_channel(struct grts_state *st, struct device *dev, + enum grts_ch_type type, const char *name, + bool optional) { - int idx, error; - - idx = device_property_match_string(dev, "io-channel-names", "x"); - if (idx < 0) - return idx; - - if (idx >= ARRAY_SIZE(st->ch)) + int idx; + + idx = device_property_match_string(dev, "io-channel-names", name); + if (idx < 0) { + if (!optional) + return idx; + idx = GRTS_MAX_CHANNELS; + } else if (idx >= GRTS_MAX_CHANNELS) { return -EOVERFLOW; + } - st->ch[idx] = GRTS_CH_X; + st->ch_map[type] = idx; + return 0; +} - idx = device_property_match_string(dev, "io-channel-names", "y"); - if (idx < 0) - return idx; +static int grts_get_properties(struct grts_state *st, struct device *dev) +{ + int error; - if (idx >= ARRAY_SIZE(st->ch)) - return -EOVERFLOW; + error = grts_map_channel(st, dev, GRTS_CH_X, "x", false); + if (error) + return error; - st->ch[idx] = GRTS_CH_Y; + error = grts_map_channel(st, dev, GRTS_CH_Y, "y", false); + if (error) + return error; /* pressure is optional */ - idx = device_property_match_string(dev, "io-channel-names", "pressure"); - if (idx >= 0) { - if (idx >= ARRAY_SIZE(st->ch)) - return -EOVERFLOW; + error = grts_map_channel(st, dev, GRTS_CH_PRESSURE, "pressure", true); + if (error) + return error; - st->ch[idx] = GRTS_CH_PRESSURE; + if (st->ch_map[GRTS_CH_PRESSURE] < GRTS_MAX_CHANNELS) { st->pressure = true; - return 0; } /* if no pressure is defined, try optional z1 + z2 */ - idx = device_property_match_string(dev, "io-channel-names", "z1"); - if (idx < 0) - return 0; - - if (idx >= ARRAY_SIZE(st->ch)) - return -EOVERFLOW; + error = grts_map_channel(st, dev, GRTS_CH_Z1, "z1", true); + if (error) + return error; - st->ch[idx] = GRTS_CH_Z1; + if (st->ch_map[GRTS_CH_Z1] >= GRTS_MAX_CHANNELS) + return 0; /* if z1 is provided z2 is not optional */ - idx = device_property_match_string(dev, "io-channel-names", "z2"); - if (idx < 0) - return idx; - - if (idx >= ARRAY_SIZE(st->ch)) - return -EOVERFLOW; - - st->ch[idx] = GRTS_CH_Z2; - st->pressure = true; + error = grts_map_channel(st, dev, GRTS_CH_Z2, "z2", true); + if (error) + return error; error = device_property_read_u32(dev, "touchscreen-x-plate-ohms", @@ -205,6 +192,7 @@ static int grts_get_properties(struct grts_state *st, struct device *dev) return error; } + st->pressure = true; return 0; } -- cgit v1.2.3 From d27ac0fba71cfd4da45f1ba6564f32ddd2914cc4 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 1 Jun 2021 16:37:54 -0700 Subject: Input: cyttsp - remove public header There is nothing in include/linux/input/cyttsp.h that might be of interes to the kernel at large, so let's move this information into the driver code and remove the header. Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20210531052307.1433979-2-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- MAINTAINERS | 1 - drivers/input/touchscreen/cyttsp_core.c | 9 ++++++++- drivers/input/touchscreen/cyttsp_core.h | 1 - drivers/input/touchscreen/cyttsp_i2c.c | 2 ++ drivers/input/touchscreen/cyttsp_spi.c | 2 ++ include/linux/input/cyttsp.h | 29 ----------------------------- 6 files changed, 12 insertions(+), 32 deletions(-) delete mode 100644 include/linux/input/cyttsp.h (limited to 'drivers/input') diff --git a/MAINTAINERS b/MAINTAINERS index 9a43400480e2..920f33866799 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4918,7 +4918,6 @@ M: Linus Walleij L: linux-input@vger.kernel.org S: Maintained F: drivers/input/touchscreen/cyttsp* -F: include/linux/input/cyttsp.h D-LINK DIR-685 TOUCHKEYS DRIVER M: Linus Walleij diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index a6352d79e23d..1dbd849c9613 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c @@ -46,8 +46,15 @@ #define CY_MAXZ 255 #define CY_DELAY_DFLT 20 /* ms */ #define CY_DELAY_MAX 500 -#define CY_ACT_DIST_DFLT 0xF8 +/* Active distance in pixels for a gesture to be reported */ +#define CY_ACT_DIST_DFLT 0xF8 /* pixels */ #define CY_ACT_DIST_MASK 0x0F +/* Active Power state scanning/processing refresh interval */ +#define CY_ACT_INTRVL_DFLT 0x00 /* ms */ +/* Low Power state scanning/processing refresh interval */ +#define CY_LP_INTRVL_DFLT 0x0A /* ms */ +/* touch timeout for the Active power */ +#define CY_TCH_TMOUT_DFLT 0xFF /* ms */ #define CY_HNDSHK_BIT 0x80 /* device mode bits */ #define CY_OPERATE_MODE 0x00 diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h index 8eba9d8ba74a..075509e695a2 100644 --- a/drivers/input/touchscreen/cyttsp_core.h +++ b/drivers/input/touchscreen/cyttsp_core.h @@ -22,7 +22,6 @@ #include #include #include -#include #include #define CY_NUM_RETRY 16 /* max number of retries for read ops */ diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c index 0a09f07bc23a..4c8473d327ab 100644 --- a/drivers/input/touchscreen/cyttsp_i2c.c +++ b/drivers/input/touchscreen/cyttsp_i2c.c @@ -18,6 +18,8 @@ #include #include +#define CY_I2C_NAME "cyttsp-i2c" + #define CY_I2C_DATA_SIZE 128 static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = { diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c index 8715e5354d79..30c6fbf86a86 100644 --- a/drivers/input/touchscreen/cyttsp_spi.c +++ b/drivers/input/touchscreen/cyttsp_spi.c @@ -20,6 +20,8 @@ #include #include +#define CY_SPI_NAME "cyttsp-spi" + #define CY_SPI_WR_OP 0x00 /* r/~w */ #define CY_SPI_RD_OP 0x01 #define CY_SPI_CMD_BYTES 4 diff --git a/include/linux/input/cyttsp.h b/include/linux/input/cyttsp.h deleted file mode 100644 index 118b9af6e01a..000000000000 --- a/include/linux/input/cyttsp.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Header file for: - * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers. - * For use with Cypress Txx3xx parts. - * Supported parts include: - * CY8CTST341 - * CY8CTMA340 - * - * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. - * Copyright (C) 2012 Javier Martinez Canillas - * - * Contact Cypress Semiconductor at www.cypress.com (kev@cypress.com) - */ -#ifndef _CYTTSP_H_ -#define _CYTTSP_H_ - -#define CY_SPI_NAME "cyttsp-spi" -#define CY_I2C_NAME "cyttsp-i2c" -/* Active Power state scanning/processing refresh interval */ -#define CY_ACT_INTRVL_DFLT 0x00 /* ms */ -/* touch timeout for the Active power */ -#define CY_TCH_TMOUT_DFLT 0xFF /* ms */ -/* Low Power state scanning/processing refresh interval */ -#define CY_LP_INTRVL_DFLT 0x0A /* ms */ -/* Active distance in pixels for a gesture to be reported */ -#define CY_ACT_DIST_DFLT 0xF8 /* pixels */ - -#endif /* _CYTTSP_H_ */ -- cgit v1.2.3 From df4c40f484191362976f46f655c88d4ea0b6d51f Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Tue, 1 Jun 2021 21:26:34 -0700 Subject: Input: edt-ft5x06 - add support for iovcc-supply At the moment, the edt-ft5x06 driver can control a single regulator ("vcc"). However, some FocalTech touch controllers have an additional IOVCC pin that should be supplied with the digital I/O voltage. The I/O voltage might be provided by another regulator that should also be kept on. Otherwise, the touchscreen can randomly stop functioning if the regulator is turned off because no other components still require it. Implement (optional) support for also enabling an "iovcc-supply". The datasheet specifies a delay of ~ 10us before enabling VDD/VCC after IOVCC is enabled, so make sure to enable IOVCC first. Signed-off-by: Stephan Gerhold Link: https://lore.kernel.org/r/20210510193108.50178-2-stephan@gerhold.net Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/edt-ft5x06.c | 38 ++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 2eefbc2485bc..263de3bfb6cd 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -104,6 +104,7 @@ struct edt_ft5x06_ts_data { u16 num_x; u16 num_y; struct regulator *vcc; + struct regulator *iovcc; struct gpio_desc *reset_gpio; struct gpio_desc *wake_gpio; @@ -1062,11 +1063,12 @@ static void edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) } } -static void edt_ft5x06_disable_regulator(void *arg) +static void edt_ft5x06_disable_regulators(void *arg) { struct edt_ft5x06_ts_data *data = arg; regulator_disable(data->vcc); + regulator_disable(data->iovcc); } static int edt_ft5x06_ts_probe(struct i2c_client *client, @@ -1107,14 +1109,33 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, return error; } + tsdata->iovcc = devm_regulator_get(&client->dev, "iovcc"); + if (IS_ERR(tsdata->iovcc)) { + error = PTR_ERR(tsdata->iovcc); + if (error != -EPROBE_DEFER) + dev_err(&client->dev, + "failed to request iovcc regulator: %d\n", error); + return error; + } + + error = regulator_enable(tsdata->iovcc); + if (error < 0) { + dev_err(&client->dev, "failed to enable iovcc: %d\n", error); + return error; + } + + /* Delay enabling VCC for > 10us (T_ivd) after IOVCC */ + usleep_range(10, 100); + error = regulator_enable(tsdata->vcc); if (error < 0) { dev_err(&client->dev, "failed to enable vcc: %d\n", error); + regulator_disable(tsdata->iovcc); return error; } error = devm_add_action_or_reset(&client->dev, - edt_ft5x06_disable_regulator, + edt_ft5x06_disable_regulators, tsdata); if (error) return error; @@ -1289,6 +1310,9 @@ static int __maybe_unused edt_ft5x06_ts_suspend(struct device *dev) ret = regulator_disable(tsdata->vcc); if (ret) dev_warn(dev, "Failed to disable vcc\n"); + ret = regulator_disable(tsdata->iovcc); + if (ret) + dev_warn(dev, "Failed to disable iovcc\n"); return 0; } @@ -1319,9 +1343,19 @@ static int __maybe_unused edt_ft5x06_ts_resume(struct device *dev) gpiod_set_value_cansleep(reset_gpio, 1); usleep_range(5000, 6000); + ret = regulator_enable(tsdata->iovcc); + if (ret) { + dev_err(dev, "Failed to enable iovcc\n"); + return ret; + } + + /* Delay enabling VCC for > 10us (T_ivd) after IOVCC */ + usleep_range(10, 100); + ret = regulator_enable(tsdata->vcc); if (ret) { dev_err(dev, "Failed to enable vcc\n"); + regulator_disable(tsdata->iovcc); return ret; } -- cgit v1.2.3 From 2fcbda9a822db2ff990fd9f19075843737bc1685 Mon Sep 17 00:00:00 2001 From: David Collins Date: Tue, 1 Jun 2021 21:34:16 -0700 Subject: Input: pm8941-pwrkey - add support for PMK8350 PON_HLOS PMIC peripheral On Qualcomm Technologies, Inc. PMIC PMK8350, the PON peripheral is split into two peripherals: PON_HLOS and PON_PBS. The application processor only has write access to PON_HLOS which limits it to only receiving PON interrupts. Add support for the PMK8350 PON_HLOS peripheral so that its KPDPWR_N and RESIN_N interrupts can be used to detect key presses. Signed-off-by: David Collins Signed-off-by: satya priya Reviewed-by: Bjorn Andersson Link: https://lore.kernel.org/r/1620630064-16354-2-git-send-email-skakit@codeaurora.org Signed-off-by: Dmitry Torokhov --- drivers/input/misc/pm8941-pwrkey.c | 103 ++++++++++++++++++++++++++----------- 1 file changed, 72 insertions(+), 31 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c index cf8104454e74..10e3fc0eac6e 100644 --- a/drivers/input/misc/pm8941-pwrkey.c +++ b/drivers/input/misc/pm8941-pwrkey.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, 2020-2021, The Linux Foundation. All rights reserved. * Copyright (c) 2014, Sony Mobile Communications Inc. */ @@ -22,6 +22,8 @@ #define PON_RT_STS 0x10 #define PON_KPDPWR_N_SET BIT(0) #define PON_RESIN_N_SET BIT(1) +#define PON_GEN3_RESIN_N_SET BIT(6) +#define PON_GEN3_KPDPWR_N_SET BIT(7) #define PON_PS_HOLD_RST_CTL 0x5a #define PON_PS_HOLD_RST_CTL2 0x5b @@ -38,8 +40,12 @@ #define PON_DBC_DELAY_MASK 0x7 struct pm8941_data { - unsigned int pull_up_bit; - unsigned int status_bit; + unsigned int pull_up_bit; + unsigned int status_bit; + bool supports_ps_hold_poff_config; + bool supports_debounce_config; + const char *name; + const char *phys; }; struct pm8941_pwrkey { @@ -231,34 +237,40 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev) input_set_capability(pwrkey->input, EV_KEY, pwrkey->code); - pwrkey->input->name = "pm8941_pwrkey"; - pwrkey->input->phys = "pm8941_pwrkey/input0"; - - req_delay = (req_delay << 6) / USEC_PER_SEC; - req_delay = ilog2(req_delay); - - error = regmap_update_bits(pwrkey->regmap, - pwrkey->baseaddr + PON_DBC_CTL, - PON_DBC_DELAY_MASK, - req_delay); - if (error) { - dev_err(&pdev->dev, "failed to set debounce: %d\n", error); - return error; + pwrkey->input->name = pwrkey->data->name; + pwrkey->input->phys = pwrkey->data->phys; + + if (pwrkey->data->supports_debounce_config) { + req_delay = (req_delay << 6) / USEC_PER_SEC; + req_delay = ilog2(req_delay); + + error = regmap_update_bits(pwrkey->regmap, + pwrkey->baseaddr + PON_DBC_CTL, + PON_DBC_DELAY_MASK, + req_delay); + if (error) { + dev_err(&pdev->dev, "failed to set debounce: %d\n", + error); + return error; + } } - error = regmap_update_bits(pwrkey->regmap, - pwrkey->baseaddr + PON_PULL_CTL, - pwrkey->data->pull_up_bit, - pull_up ? pwrkey->data->pull_up_bit : 0); - if (error) { - dev_err(&pdev->dev, "failed to set pull: %d\n", error); - return error; + if (pwrkey->data->pull_up_bit) { + error = regmap_update_bits(pwrkey->regmap, + pwrkey->baseaddr + PON_PULL_CTL, + pwrkey->data->pull_up_bit, + pull_up ? pwrkey->data->pull_up_bit : + 0); + if (error) { + dev_err(&pdev->dev, "failed to set pull: %d\n", error); + return error; + } } error = devm_request_threaded_irq(&pdev->dev, pwrkey->irq, NULL, pm8941_pwrkey_irq, IRQF_ONESHOT, - "pm8941_pwrkey", pwrkey); + pwrkey->data->name, pwrkey); if (error) { dev_err(&pdev->dev, "failed requesting IRQ: %d\n", error); return error; @@ -271,12 +283,14 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev) return error; } - pwrkey->reboot_notifier.notifier_call = pm8941_reboot_notify, - error = register_reboot_notifier(&pwrkey->reboot_notifier); - if (error) { - dev_err(&pdev->dev, "failed to register reboot notifier: %d\n", - error); - return error; + if (pwrkey->data->supports_ps_hold_poff_config) { + pwrkey->reboot_notifier.notifier_call = pm8941_reboot_notify, + error = register_reboot_notifier(&pwrkey->reboot_notifier); + if (error) { + dev_err(&pdev->dev, "failed to register reboot notifier: %d\n", + error); + return error; + } } platform_set_drvdata(pdev, pwrkey); @@ -289,7 +303,8 @@ static int pm8941_pwrkey_remove(struct platform_device *pdev) { struct pm8941_pwrkey *pwrkey = platform_get_drvdata(pdev); - unregister_reboot_notifier(&pwrkey->reboot_notifier); + if (pwrkey->data->supports_ps_hold_poff_config) + unregister_reboot_notifier(&pwrkey->reboot_notifier); return 0; } @@ -297,16 +312,42 @@ static int pm8941_pwrkey_remove(struct platform_device *pdev) static const struct pm8941_data pwrkey_data = { .pull_up_bit = PON_KPDPWR_PULL_UP, .status_bit = PON_KPDPWR_N_SET, + .name = "pm8941_pwrkey", + .phys = "pm8941_pwrkey/input0", + .supports_ps_hold_poff_config = true, + .supports_debounce_config = true, }; static const struct pm8941_data resin_data = { .pull_up_bit = PON_RESIN_PULL_UP, .status_bit = PON_RESIN_N_SET, + .name = "pm8941_resin", + .phys = "pm8941_resin/input0", + .supports_ps_hold_poff_config = true, + .supports_debounce_config = true, +}; + +static const struct pm8941_data pon_gen3_pwrkey_data = { + .status_bit = PON_GEN3_KPDPWR_N_SET, + .name = "pmic_pwrkey", + .phys = "pmic_pwrkey/input0", + .supports_ps_hold_poff_config = false, + .supports_debounce_config = false, +}; + +static const struct pm8941_data pon_gen3_resin_data = { + .status_bit = PON_GEN3_RESIN_N_SET, + .name = "pmic_resin", + .phys = "pmic_resin/input0", + .supports_ps_hold_poff_config = false, + .supports_debounce_config = false, }; static const struct of_device_id pm8941_pwr_key_id_table[] = { { .compatible = "qcom,pm8941-pwrkey", .data = &pwrkey_data }, { .compatible = "qcom,pm8941-resin", .data = &resin_data }, + { .compatible = "qcom,pmk8350-pwrkey", .data = &pon_gen3_pwrkey_data }, + { .compatible = "qcom,pmk8350-resin", .data = &pon_gen3_resin_data }, { } }; MODULE_DEVICE_TABLE(of, pm8941_pwr_key_id_table); -- cgit v1.2.3 From 6cdc1ef84eacca85642828840f2ec4f84130c9b6 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 5 Jun 2021 16:09:36 -0700 Subject: Input: resistive-adc-touch - fix uninitialized variable 'press' In the case where st->ch_map[GRTS_CH_PRESSURE] < GRTS_MAX_CHANNELS is false and also st->ch_map[GRTS_CH_Z1] < GRTS_MAX_CHANNELS is false the variable press is not initialized and contains garbage. In this situation st->pressure is also false, so we do not actually use press value, but it is impossible for the compiler to realize this, and it emits "uninitialized variable" warning. Fix this by initializing press to 0 and allows us to also remove an else clause that sets press to 0. Addresses-Coverity: ("Uninitialized scalar variable") Fixes: 60b7db914ddd ("Input: resistive-adc-touch - rework mapping of channels") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20210603220809.155118-1-colin.king@canonical.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/resistive-adc-touch.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/resistive-adc-touch.c b/drivers/input/touchscreen/resistive-adc-touch.c index ea7dd9d2b2ac..744544a723b7 100644 --- a/drivers/input/touchscreen/resistive-adc-touch.c +++ b/drivers/input/touchscreen/resistive-adc-touch.c @@ -59,7 +59,7 @@ static int grts_cb(const void *data, void *private) { const u16 *touch_info = data; struct grts_state *st = private; - unsigned int x, y, press; + unsigned int x, y, press = 0; x = touch_info[st->ch_map[GRTS_CH_X]]; y = touch_info[st->ch_map[GRTS_CH_Y]]; @@ -84,8 +84,6 @@ static int grts_cb(const void *data, void *private) */ if (Rt < GRTS_DEFAULT_PRESSURE_MAX) press = GRTS_DEFAULT_PRESSURE_MAX - Rt; - else - press = 0; } if ((!x && !y) || (st->pressure && (press < st->pressure_min))) { -- cgit v1.2.3 From 6abee582034c123d995cd454a1ccdcf0b8699da0 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 5 Jun 2021 17:04:25 -0700 Subject: Input: cy8ctmg110_ts - rely on platform code to supply interrupt Instead of using platform data to specify GPIO that is used as interrupt source, rely on the platform and I2C core to set it up properly. Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20210603043726.3793876-1-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cy8ctmg110_ts.c | 32 +------------------------------ include/linux/input/cy8ctmg110_pdata.h | 1 - 2 files changed, 1 insertion(+), 32 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index f465bae618fe..691f35f1bdd7 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c @@ -46,7 +46,6 @@ struct cy8ctmg110 { char phys[32]; struct i2c_client *client; int reset_pin; - int irq_pin; }; /* @@ -191,7 +190,6 @@ static int cy8ctmg110_probe(struct i2c_client *client, ts->client = client; ts->input = input_dev; ts->reset_pin = pdata->reset_pin; - ts->irq_pin = pdata->irq_pin; snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&client->dev)); @@ -222,38 +220,13 @@ static int cy8ctmg110_probe(struct i2c_client *client, cy8ctmg110_power(ts, true); cy8ctmg110_set_sleepmode(ts, false); - err = gpio_request(ts->irq_pin, "touch_irq_key"); - if (err < 0) { - dev_err(&client->dev, - "Failed to request GPIO %d, error %d\n", - ts->irq_pin, err); - goto err_shutoff_device; - } - - err = gpio_direction_input(ts->irq_pin); - if (err < 0) { - dev_err(&client->dev, - "Failed to configure input direction for GPIO %d, error %d\n", - ts->irq_pin, err); - goto err_free_irq_gpio; - } - - client->irq = gpio_to_irq(ts->irq_pin); - if (client->irq < 0) { - err = client->irq; - dev_err(&client->dev, - "Unable to get irq number for GPIO %d, error %d\n", - ts->irq_pin, err); - goto err_free_irq_gpio; - } - err = request_threaded_irq(client->irq, NULL, cy8ctmg110_irq_thread, IRQF_TRIGGER_RISING | IRQF_ONESHOT, "touch_reset_key", ts); if (err < 0) { dev_err(&client->dev, "irq %d busy? error %d\n", client->irq, err); - goto err_free_irq_gpio; + goto err_shutoff_device; } err = input_register_device(input_dev); @@ -266,8 +239,6 @@ static int cy8ctmg110_probe(struct i2c_client *client, err_free_irq: free_irq(client->irq, ts); -err_free_irq_gpio: - gpio_free(ts->irq_pin); err_shutoff_device: cy8ctmg110_set_sleepmode(ts, true); cy8ctmg110_power(ts, false); @@ -318,7 +289,6 @@ static int cy8ctmg110_remove(struct i2c_client *client) free_irq(client->irq, ts); input_unregister_device(ts->input); - gpio_free(ts->irq_pin); if (ts->reset_pin) gpio_free(ts->reset_pin); kfree(ts); diff --git a/include/linux/input/cy8ctmg110_pdata.h b/include/linux/input/cy8ctmg110_pdata.h index 77582ae1745a..ee1d44545f30 100644 --- a/include/linux/input/cy8ctmg110_pdata.h +++ b/include/linux/input/cy8ctmg110_pdata.h @@ -5,7 +5,6 @@ struct cy8ctmg110_pdata { int reset_pin; /* Reset pin is wired to this GPIO (optional) */ - int irq_pin; /* IRQ pin is wired to this GPIO */ }; #endif -- cgit v1.2.3 From 9a9b1a7b2b08aa64d2876e48f51c7fbbebd5723c Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 5 Jun 2021 17:04:39 -0700 Subject: Input: cy8ctmg110_ts - do not hard code interrupt trigger Rely on the platform to set up interrupt polarity/type properly instead of hard-coding falling edge. Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20210603043726.3793876-2-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cy8ctmg110_ts.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index 691f35f1bdd7..d83257284537 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c @@ -221,8 +221,7 @@ static int cy8ctmg110_probe(struct i2c_client *client, cy8ctmg110_set_sleepmode(ts, false); err = request_threaded_irq(client->irq, NULL, cy8ctmg110_irq_thread, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - "touch_reset_key", ts); + IRQF_ONESHOT, "touch_reset_key", ts); if (err < 0) { dev_err(&client->dev, "irq %d busy? error %d\n", client->irq, err); -- cgit v1.2.3 From 2a15cebb8b40ef55d3a565b9acaec21791cb7e37 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 5 Jun 2021 17:04:49 -0700 Subject: Input: cy8ctmg110_ts - do not hardcode as wakeup source Let platform specify whether the controller should be a wakeup source by registering as I2C_CLIENT_WAKE. Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20210603043726.3793876-3-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cy8ctmg110_ts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index d83257284537..d83bf82f02d4 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c @@ -233,7 +233,7 @@ static int cy8ctmg110_probe(struct i2c_client *client, goto err_free_irq; i2c_set_clientdata(client, ts); - device_init_wakeup(&client->dev, 1); + return 0; err_free_irq: -- cgit v1.2.3 From 172b07a6ead345b625af7e5f147ec64fbd256f79 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 5 Jun 2021 17:05:00 -0700 Subject: Input: cy8ctmg110_ts - let I2C core configure wake interrupt I2C core already configures interrupt as wakeup source when device is registered using I2C_CLIENT_WAKE flag, so let's rely on it instead of configuring it ourselves. Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20210603043726.3793876-4-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cy8ctmg110_ts.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index d83bf82f02d4..f8d7ab3b6c25 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c @@ -254,12 +254,11 @@ static int __maybe_unused cy8ctmg110_suspend(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct cy8ctmg110 *ts = i2c_get_clientdata(client); - if (device_may_wakeup(&client->dev)) - enable_irq_wake(client->irq); - else { + if (!device_may_wakeup(&client->dev)) { cy8ctmg110_set_sleepmode(ts, true); cy8ctmg110_power(ts, false); } + return 0; } @@ -268,12 +267,11 @@ static int __maybe_unused cy8ctmg110_resume(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct cy8ctmg110 *ts = i2c_get_clientdata(client); - if (device_may_wakeup(&client->dev)) - disable_irq_wake(client->irq); - else { + if (!device_may_wakeup(&client->dev)) { cy8ctmg110_power(ts, true); cy8ctmg110_set_sleepmode(ts, false); } + return 0; } -- cgit v1.2.3 From 1c68b7cfd1d4902e4e6802d18331b3ab96f124c9 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 5 Jun 2021 17:05:29 -0700 Subject: Input: cy8ctmg110_ts - use endian helpers when converting data on wire Switch to using be16_to_cpup() instead of shifting and combining data by hand. Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20210603043726.3793876-5-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cy8ctmg110_ts.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index f8d7ab3b6c25..33c1360a251c 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c @@ -16,6 +16,7 @@ #include #include #include +#include #define CY8CTMG110_DRIVER_NAME "cy8ctmg110" @@ -111,7 +112,6 @@ static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc) { struct input_dev *input = tsc->input; unsigned char reg_p[CY8CTMG110_REG_MAX]; - int x, y; memset(reg_p, 0, CY8CTMG110_REG_MAX); @@ -119,16 +119,15 @@ static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc) if (cy8ctmg110_read_regs(tsc, reg_p, 9, CY8CTMG110_TOUCH_X1) != 0) return -EIO; - y = reg_p[2] << 8 | reg_p[3]; - x = reg_p[0] << 8 | reg_p[1]; - /* Number of touch */ if (reg_p[8] == 0) { input_report_key(input, BTN_TOUCH, 0); } else { input_report_key(input, BTN_TOUCH, 1); - input_report_abs(input, ABS_X, x); - input_report_abs(input, ABS_Y, y); + input_report_abs(input, ABS_X, + be16_to_cpup((__be16 *)(reg_p + 0))); + input_report_abs(input, ABS_Y, + be16_to_cpup((__be16 *)(reg_p + 2))); } input_sync(input); -- cgit v1.2.3 From 4e5220cb8e4bb8f0368e7a123c48ceb6b2f4a56d Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 5 Jun 2021 17:05:43 -0700 Subject: Input: cy8ctmg110_ts - switch to using managed resources This simplifies error handling paths and allows to get rid of cy8ctmg110_remove() method. Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20210603043726.3793876-6-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cy8ctmg110_ts.c | 74 ++++++++++++------------------- 1 file changed, 28 insertions(+), 46 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index 33c1360a251c..33ccb31cad52 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c @@ -161,6 +161,14 @@ static irqreturn_t cy8ctmg110_irq_thread(int irq, void *dev_id) return IRQ_HANDLED; } +static void cy8ctmg110_shut_off(void *_ts) +{ + struct cy8ctmg110 *ts = _ts; + + cy8ctmg110_set_sleepmode(ts, true); + cy8ctmg110_power(ts, false); +} + static int cy8ctmg110_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -179,12 +187,13 @@ static int cy8ctmg110_probe(struct i2c_client *client, I2C_FUNC_SMBUS_READ_WORD_DATA)) return -EIO; - ts = kzalloc(sizeof(struct cy8ctmg110), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ts || !input_dev) { - err = -ENOMEM; - goto err_free_mem; - } + ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL); + if (!ts) + return -ENOMEM; + + input_dev = devm_input_allocate_device(&client->dev); + if (!input_dev) + return -ENOMEM; ts->client = client; ts->input = input_dev; @@ -196,56 +205,46 @@ static int cy8ctmg110_probe(struct i2c_client *client, input_dev->name = CY8CTMG110_DRIVER_NAME " Touchscreen"; input_dev->phys = ts->phys; input_dev->id.bustype = BUS_I2C; - input_dev->dev.parent = &client->dev; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + input_set_capability(input_dev, EV_KEY, BTN_TOUCH); input_set_abs_params(input_dev, ABS_X, CY8CTMG110_X_MIN, CY8CTMG110_X_MAX, 4, 0); input_set_abs_params(input_dev, ABS_Y, CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 4, 0); if (ts->reset_pin) { - err = gpio_request(ts->reset_pin, NULL); + err = devm_gpio_request(&client->dev, ts->reset_pin, NULL); if (err) { dev_err(&client->dev, "Unable to request GPIO pin %d.\n", ts->reset_pin); - goto err_free_mem; + return err; } } cy8ctmg110_power(ts, true); cy8ctmg110_set_sleepmode(ts, false); - err = request_threaded_irq(client->irq, NULL, cy8ctmg110_irq_thread, - IRQF_ONESHOT, "touch_reset_key", ts); - if (err < 0) { + err = devm_add_action_or_reset(&client->dev, cy8ctmg110_shut_off, ts); + if (err) + return err; + + err = devm_request_threaded_irq(&client->dev, client->irq, + NULL, cy8ctmg110_irq_thread, + IRQF_ONESHOT, "touch_reset_key", ts); + if (err) { dev_err(&client->dev, "irq %d busy? error %d\n", client->irq, err); - goto err_shutoff_device; + return err; } err = input_register_device(input_dev); if (err) - goto err_free_irq; + return err; i2c_set_clientdata(client, ts); return 0; - -err_free_irq: - free_irq(client->irq, ts); -err_shutoff_device: - cy8ctmg110_set_sleepmode(ts, true); - cy8ctmg110_power(ts, false); - if (ts->reset_pin) - gpio_free(ts->reset_pin); -err_free_mem: - input_free_device(input_dev); - kfree(ts); - return err; } static int __maybe_unused cy8ctmg110_suspend(struct device *dev) @@ -276,22 +275,6 @@ static int __maybe_unused cy8ctmg110_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume); -static int cy8ctmg110_remove(struct i2c_client *client) -{ - struct cy8ctmg110 *ts = i2c_get_clientdata(client); - - cy8ctmg110_set_sleepmode(ts, true); - cy8ctmg110_power(ts, false); - - free_irq(client->irq, ts); - input_unregister_device(ts->input); - if (ts->reset_pin) - gpio_free(ts->reset_pin); - kfree(ts); - - return 0; -} - static const struct i2c_device_id cy8ctmg110_idtable[] = { { CY8CTMG110_DRIVER_NAME, 1 }, { } @@ -306,7 +289,6 @@ static struct i2c_driver cy8ctmg110_driver = { }, .id_table = cy8ctmg110_idtable, .probe = cy8ctmg110_probe, - .remove = cy8ctmg110_remove, }; module_i2c_driver(cy8ctmg110_driver); -- cgit v1.2.3 From 83b41248ed04ac64a3aafc47be2b25bc1509e2f9 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 5 Jun 2021 17:05:59 -0700 Subject: Input: cy8ctmg110_ts - switch to using gpiod API Instead of legacy gpio API let's use newer gpiod API. This also allows us to get rid of platform data. Reviewed-by: Linus Walleij Link: https://lore.kernel.org/r/20210603043726.3793876-7-dmitry.torokhov@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cy8ctmg110_ts.c | 45 +++++++++++++------------------ 1 file changed, 18 insertions(+), 27 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index 33ccb31cad52..495ef156cf43 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c @@ -7,15 +7,13 @@ * Some cleanups by Alan Cox */ -#include -#include +#include #include -#include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #define CY8CTMG110_DRIVER_NAME "cy8ctmg110" @@ -46,17 +44,18 @@ struct cy8ctmg110 { struct input_dev *input; char phys[32]; struct i2c_client *client; - int reset_pin; + struct gpio_desc *reset_gpio; }; /* * cy8ctmg110_power is the routine that is called when touch hardware - * will powered off or on. + * is being powered off or on. When powering on this routine de-asserts + * the RESET line, when powering off reset line is asserted. */ static void cy8ctmg110_power(struct cy8ctmg110 *ts, bool poweron) { - if (ts->reset_pin) - gpio_direction_output(ts->reset_pin, 1 - poweron); + if (ts->reset_gpio) + gpiod_set_value_cansleep(ts->reset_gpio, !poweron); } static int cy8ctmg110_write_regs(struct cy8ctmg110 *tsc, unsigned char reg, @@ -172,17 +171,10 @@ static void cy8ctmg110_shut_off(void *_ts) static int cy8ctmg110_probe(struct i2c_client *client, const struct i2c_device_id *id) { - const struct cy8ctmg110_pdata *pdata = dev_get_platdata(&client->dev); struct cy8ctmg110 *ts; struct input_dev *input_dev; int err; - /* No pdata no way forward */ - if (pdata == NULL) { - dev_err(&client->dev, "no pdata\n"); - return -ENODEV; - } - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) return -EIO; @@ -197,7 +189,6 @@ static int cy8ctmg110_probe(struct i2c_client *client, ts->client = client; ts->input = input_dev; - ts->reset_pin = pdata->reset_pin; snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&client->dev)); @@ -212,14 +203,14 @@ static int cy8ctmg110_probe(struct i2c_client *client, input_set_abs_params(input_dev, ABS_Y, CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 4, 0); - if (ts->reset_pin) { - err = devm_gpio_request(&client->dev, ts->reset_pin, NULL); - if (err) { - dev_err(&client->dev, - "Unable to request GPIO pin %d.\n", - ts->reset_pin); - return err; - } + /* Request and assert reset line */ + ts->reset_gpio = devm_gpiod_get_optional(&client->dev, NULL, + GPIOD_OUT_HIGH); + if (IS_ERR(ts->reset_gpio)) { + err = PTR_ERR(ts->reset_gpio); + dev_err(&client->dev, + "Unable to request reset GPIO: %d\n", err); + return err; } cy8ctmg110_power(ts, true); -- cgit v1.2.3 From 552e4047f3341ead7c7d61eddfc5c39dbf20452b Mon Sep 17 00:00:00 2001 From: Oleh Kravchenko Date: Thu, 10 Jun 2021 15:16:17 -0700 Subject: Input: add SparkFun Qwiic Joystick driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A simple analog joystick built on Low Power ATtiny85 Microcontroller. Directional movements are measured with two 10 kΩ potentiometers connected with a gimbal mechanism that separates the horizontal and vertical movements. This joystick also has a select button that is actuated when the joystick is pressed down. Input events polled over the I2C bus. Product page: https://www.sparkfun.com/products/15168 Firmware and hardware sources: https://github.com/sparkfun/Qwiic_Joystick Tested on RPi4B and O4-iMX-NANO boards. Signed-off-by: Oleh Kravchenko Reviewed-by: Jeff LaBundy Link: https://lore.kernel.org/r/20210608223130.16830-2-oleg@kaa.org.ua Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/Kconfig | 9 ++ drivers/input/joystick/Makefile | 1 + drivers/input/joystick/qwiic-joystick.c | 146 ++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 drivers/input/joystick/qwiic-joystick.c (limited to 'drivers/input') diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig index 5e38899058c1..7dfe8ea90923 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig @@ -372,6 +372,15 @@ config JOYSTICK_PXRC To compile this driver as a module, choose M here: the module will be called pxrc. +config JOYSTICK_QWIIC + tristate "SparkFun Qwiic Joystick" + depends on I2C + help + Say Y here if you want to use the SparkFun Qwiic Joystick. + + To compile this driver as a module, choose M here: the + module will be called qwiic-joystick. + config JOYSTICK_FSIA6B tristate "FlySky FS-iA6B RC Receiver" select SERIO diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile index 31d720c9e493..5174b8aba2dd 100644 --- a/drivers/input/joystick/Makefile +++ b/drivers/input/joystick/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_JOYSTICK_MAPLE) += maplecontrol.o obj-$(CONFIG_JOYSTICK_N64) += n64joy.o obj-$(CONFIG_JOYSTICK_PSXPAD_SPI) += psxpad-spi.o obj-$(CONFIG_JOYSTICK_PXRC) += pxrc.o +obj-$(CONFIG_JOYSTICK_QWIIC) += qwiic-joystick.o obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o obj-$(CONFIG_JOYSTICK_SPACEBALL) += spaceball.o obj-$(CONFIG_JOYSTICK_SPACEORB) += spaceorb.o diff --git a/drivers/input/joystick/qwiic-joystick.c b/drivers/input/joystick/qwiic-joystick.c new file mode 100644 index 000000000000..d4da31c0616c --- /dev/null +++ b/drivers/input/joystick/qwiic-joystick.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021 Oleh Kravchenko + * + * SparkFun Qwiic Joystick + * Product page:https://www.sparkfun.com/products/15168 + * Firmware and hardware sources:https://github.com/sparkfun/Qwiic_Joystick + */ + +#include +#include +#include +#include +#include + +#define DRV_NAME "qwiic-joystick" + +#define QWIIC_JSK_REG_VERS 1 +#define QWIIC_JSK_REG_DATA 3 + +#define QWIIC_JSK_MAX_AXIS GENMASK(9, 0) +#define QWIIC_JSK_FUZZ 2 +#define QWIIC_JSK_FLAT 2 +#define QWIIC_JSK_POLL_INTERVAL 16 +#define QWIIC_JSK_POLL_MIN 8 +#define QWIIC_JSK_POLL_MAX 32 + +struct qwiic_jsk { + char phys[32]; + struct input_dev *dev; + struct i2c_client *client; +}; + +struct qwiic_ver { + u8 major; + u8 minor; +}; + +struct qwiic_data { + __be16 x; + __be16 y; + u8 thumb; +}; + +static void qwiic_poll(struct input_dev *input) +{ + struct qwiic_jsk *priv = input_get_drvdata(input); + struct qwiic_data data; + int err; + + err = i2c_smbus_read_i2c_block_data(priv->client, QWIIC_JSK_REG_DATA, + sizeof(data), (u8 *)&data); + if (err != sizeof(data)) + return; + + input_report_abs(input, ABS_X, be16_to_cpu(data.x) >> 6); + input_report_abs(input, ABS_Y, be16_to_cpu(data.y) >> 6); + input_report_key(input, BTN_THUMBL, !data.thumb); + input_sync(input); +} + +static int qwiic_probe(struct i2c_client *client) +{ + struct qwiic_jsk *priv; + struct qwiic_ver vers; + int err; + + err = i2c_smbus_read_i2c_block_data(client, QWIIC_JSK_REG_VERS, + sizeof(vers), (u8 *)&vers); + if (err < 0) + return err; + if (err != sizeof(vers)) + return -EIO; + + dev_dbg(&client->dev, "SparkFun Qwiic Joystick, FW: %u.%u\n", + vers.major, vers.minor); + + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->client = client; + snprintf(priv->phys, sizeof(priv->phys), + "i2c/%s", dev_name(&client->dev)); + i2c_set_clientdata(client, priv); + + priv->dev = devm_input_allocate_device(&client->dev); + if (!priv->dev) + return -ENOMEM; + + priv->dev->id.bustype = BUS_I2C; + priv->dev->name = "SparkFun Qwiic Joystick"; + priv->dev->phys = priv->phys; + input_set_drvdata(priv->dev, priv); + + input_set_abs_params(priv->dev, ABS_X, 0, QWIIC_JSK_MAX_AXIS, + QWIIC_JSK_FUZZ, QWIIC_JSK_FLAT); + input_set_abs_params(priv->dev, ABS_Y, 0, QWIIC_JSK_MAX_AXIS, + QWIIC_JSK_FUZZ, QWIIC_JSK_FLAT); + input_set_capability(priv->dev, EV_KEY, BTN_THUMBL); + + err = input_setup_polling(priv->dev, qwiic_poll); + if (err) { + dev_err(&client->dev, "failed to set up polling: %d\n", err); + return err; + } + input_set_poll_interval(priv->dev, QWIIC_JSK_POLL_INTERVAL); + input_set_min_poll_interval(priv->dev, QWIIC_JSK_POLL_MIN); + input_set_max_poll_interval(priv->dev, QWIIC_JSK_POLL_MAX); + + err = input_register_device(priv->dev); + if (err) { + dev_err(&client->dev, "failed to register joystick: %d\n", err); + return err; + } + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id of_qwiic_match[] = { + { .compatible = "sparkfun,qwiic-joystick", }, + { }, +}; +MODULE_DEVICE_TABLE(of, of_qwiic_match); +#endif /* CONFIG_OF */ + +static const struct i2c_device_id qwiic_id_table[] = { + { KBUILD_MODNAME, 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, qwiic_id_table); + +static struct i2c_driver qwiic_driver = { + .driver = { + .name = DRV_NAME, + .of_match_table = of_match_ptr(of_qwiic_match), + }, + .id_table = qwiic_id_table, + .probe_new = qwiic_probe, +}; +module_i2c_driver(qwiic_driver); + +MODULE_AUTHOR("Oleh Kravchenko "); +MODULE_DESCRIPTION("SparkFun Qwiic Joystick driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From c2d7ed9d680fd14aa5486518bd0d0fa5963c6403 Mon Sep 17 00:00:00 2001 From: Tyson Moore Date: Mon, 14 Jun 2021 10:17:45 -0700 Subject: Input: i8042 - fix typos in comments This trivial patch fixes two spelling typos in i8042.c: - 'i8042_unlock_ship()' to 'i8042_unlock_chip()' - 'i8042_controller init' to 'i8042_controller_init' Signed-off-by: Tyson Moore Link: https://lore.kernel.org/r/20210612060753.28968-1-tyson@tyson.me Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index abae23af0791..0b9f1d0a8f8b 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -139,7 +139,7 @@ static DEFINE_SPINLOCK(i8042_lock); /* * Writers to AUX and KBD ports as well as users issuing i8042_command * directly should acquire i8042_mutex (by means of calling - * i8042_lock_chip() and i8042_unlock_ship() helpers) to ensure that + * i8042_lock_chip() and i8042_unlock_chip() helpers) to ensure that * they do not disturb each other (unfortunately in many i8042 * implementations write to one of the ports will immediately abort * command that is being processed by another port). @@ -979,7 +979,7 @@ static int i8042_controller_selftest(void) } /* - * i8042_controller init initializes the i8042 controller, and, + * i8042_controller_init initializes the i8042 controller, and, * most importantly, sets it into non-xlated mode if that's * desired. */ -- cgit v1.2.3 From 25531d612bac96dceea46994cd385791a0396aea Mon Sep 17 00:00:00 2001 From: zhouchuangao Date: Sat, 19 Jun 2021 22:10:59 -0700 Subject: Input: cros_ec_keyb - use kobj_to_dev() API Use kobj_to_dev() API instead of container_of(). Signed-off-by: zhouchuangao Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/1624025283-56360-1-git-send-email-zhouchuangao@vivo.com Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/cros_ec_keyb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index 38457d9641bd..fc02c540636e 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -644,7 +644,7 @@ static umode_t cros_ec_keyb_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct cros_ec_keyb *ckdev = dev_get_drvdata(dev); if (attr == &dev_attr_function_row_physmap.attr && -- cgit v1.2.3 From f519f78c7e95b56cadd395443bf39316fea1990c Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 19 Jun 2021 22:12:32 -0700 Subject: Input: ims-pcu - use kobj_to_dev() Use kobj_to_dev() instead of container_of() Generated by: scripts/coccinelle/api/kobj_to_dev.cocci Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20210607122533.10608-1-yuehaibing@huawei.com Signed-off-by: Dmitry Torokhov --- drivers/input/misc/ims-pcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c index 7169255efb37..6f38aa23a1ff 100644 --- a/drivers/input/misc/ims-pcu.c +++ b/drivers/input/misc/ims-pcu.c @@ -1228,7 +1228,7 @@ static struct attribute *ims_pcu_attrs[] = { static umode_t ims_pcu_is_attr_visible(struct kobject *kobj, struct attribute *attr, int n) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct usb_interface *intf = to_usb_interface(dev); struct ims_pcu *pcu = usb_get_intfdata(intf); umode_t mode = attr->mode; -- cgit v1.2.3 From 6ffd4c7964d20c88211746b4ac8a37f5c5517180 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 19 Jun 2021 22:12:43 -0700 Subject: Input: tsc200x-core - use kobj_to_dev() Use kobj_to_dev() instead of container_of() Generated by: scripts/coccinelle/api/kobj_to_dev.cocci Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20210607122451.36708-1-yuehaibing@huawei.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tsc200x-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/tsc200x-core.c b/drivers/input/touchscreen/tsc200x-core.c index ce2fe30d6b8a..b8d720d52013 100644 --- a/drivers/input/touchscreen/tsc200x-core.c +++ b/drivers/input/touchscreen/tsc200x-core.c @@ -338,7 +338,7 @@ static struct attribute *tsc200x_attrs[] = { static umode_t tsc200x_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct tsc200x *ts = dev_get_drvdata(dev); umode_t mode = attr->mode; -- cgit v1.2.3 From 50221b0b68a621a4d688ab9e4165a79a2247ad6e Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 19 Jun 2021 22:13:06 -0700 Subject: Input: atkbd - use kobj_to_dev() Use kobj_to_dev() instead of container_of() Generated by: scripts/coccinelle/api/kobj_to_dev.cocci Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20210607122653.33784-1-yuehaibing@huawei.com Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index edc613efc158..fbdef95291e9 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -324,7 +324,7 @@ static ssize_t atkbd_show_function_row_physmap(struct atkbd *atkbd, char *buf) static umode_t atkbd_attr_is_visible(struct kobject *kobj, struct attribute *attr, int i) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct serio *serio = to_serio_port(dev); struct atkbd *atkbd = serio_get_drvdata(serio); -- cgit v1.2.3 From eacacdb5fc961a7e3aec36502e4cbda8b6d5b3a8 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 19 Jun 2021 22:13:29 -0700 Subject: Input: trackpoint - use kobj_to_dev() Use kobj_to_dev() instead of container_of() Generated by: scripts/coccinelle/api/kobj_to_dev.cocci Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20210607122722.36736-1-yuehaibing@huawei.com Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/trackpoint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index ef2fa0905208..4a86b3e31d3b 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c @@ -214,7 +214,7 @@ static bool trackpoint_is_attr_available(struct psmouse *psmouse, static umode_t trackpoint_is_attr_visible(struct kobject *kobj, struct attribute *attr, int n) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct serio *serio = to_serio_port(dev); struct psmouse *psmouse = serio_get_drvdata(serio); -- cgit v1.2.3 From cac7100d4c51c04979dacdfe6c9a5e400d3f0a27 Mon Sep 17 00:00:00 2001 From: Yizhuo Zhai Date: Sat, 19 Jun 2021 22:26:50 -0700 Subject: Input: hideep - fix the uninitialized use in hideep_nvm_unlock() Inside function hideep_nvm_unlock(), variable "unmask_code" could be uninitialized if hideep_pgm_r_reg() returns error, however, it is used in the later if statement after an "and" operation, which is potentially unsafe. Signed-off-by: Yizhuo Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/hideep.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/hideep.c b/drivers/input/touchscreen/hideep.c index ddad4a82a5e5..e9547ee29756 100644 --- a/drivers/input/touchscreen/hideep.c +++ b/drivers/input/touchscreen/hideep.c @@ -361,13 +361,16 @@ static int hideep_enter_pgm(struct hideep_ts *ts) return -EIO; } -static void hideep_nvm_unlock(struct hideep_ts *ts) +static int hideep_nvm_unlock(struct hideep_ts *ts) { u32 unmask_code; + int error; hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_SFR_RPAGE); - hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code); + error = hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code); hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE); + if (error) + return error; /* make it unprotected code */ unmask_code &= ~HIDEEP_PROT_MODE; @@ -384,6 +387,8 @@ static void hideep_nvm_unlock(struct hideep_ts *ts) NVM_W_SFR(HIDEEP_NVM_MASK_OFS, ts->nvm_mask); SET_FLASH_HWCONTROL(); hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE); + + return 0; } static int hideep_check_status(struct hideep_ts *ts) @@ -462,7 +467,9 @@ static int hideep_program_nvm(struct hideep_ts *ts, u32 addr = 0; int error; - hideep_nvm_unlock(ts); + error = hideep_nvm_unlock(ts); + if (error) + return error; while (ucode_len > 0) { xfer_len = min_t(size_t, ucode_len, HIDEEP_NVM_PAGE_SIZE); -- cgit v1.2.3 From f8f84af5da9ee04ef1d271528656dac42a090d00 Mon Sep 17 00:00:00 2001 From: Alexander Larkin Date: Sun, 4 Jul 2021 22:39:36 -0700 Subject: Input: joydev - prevent use of not validated data in JSIOCSBTNMAP ioctl Even though we validate user-provided inputs we then traverse past validated data when applying the new map. The issue was originally discovered by Murray McAllister with this simple POC (if the following is executed by an unprivileged user it will instantly panic the system): int main(void) { int fd, ret; unsigned int buffer[10000]; fd = open("/dev/input/js0", O_RDONLY); if (fd == -1) printf("Error opening file\n"); ret = ioctl(fd, JSIOCSBTNMAP & ~IOCSIZE_MASK, &buffer); printf("%d\n", ret); } The solution is to traverse internal buffer which is guaranteed to only contain valid date when constructing the map. Fixes: 182d679b2298 ("Input: joydev - prevent potential read overflow in ioctl") Fixes: 999b874f4aa3 ("Input: joydev - validate axis/button maps before clobbering current ones") Reported-by: Murray McAllister Suggested-by: Linus Torvalds Signed-off-by: Alexander Larkin Link: https://lore.kernel.org/r/20210620120030.1513655-1-avlarkin82@gmail.com Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/joydev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index da8963a9f044..947d440a3be6 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -499,7 +499,7 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev, memcpy(joydev->keypam, keypam, len); for (i = 0; i < joydev->nkey; i++) - joydev->keymap[keypam[i] - BTN_MISC] = i; + joydev->keymap[joydev->keypam[i] - BTN_MISC] = i; out: kfree(keypam); -- cgit v1.2.3