diff options
35 files changed, 1112 insertions, 319 deletions
diff --git a/Documentation/devicetree/bindings/input/st-keyscan.txt b/Documentation/devicetree/bindings/input/st-keyscan.txt new file mode 100644 index 000000000000..51eb428e5c85 --- /dev/null +++ b/Documentation/devicetree/bindings/input/st-keyscan.txt @@ -0,0 +1,60 @@ +* ST Keyscan controller Device Tree bindings + +The ST keyscan controller Device Tree binding is based on the +matrix-keymap. + +Required properties: +- compatible: "st,sti-keyscan" + +- reg: Register base address and size of st-keyscan controller. + +- interrupts: Interrupt number for the st-keyscan controller. + +- clocks: Must contain one entry, for the module clock. + See ../clocks/clock-bindings.txt for details. + +- pinctrl: Should specify pin control groups used for this controller. + See ../pinctrl/pinctrl-bindings.txt for details. + +- linux,keymap: The keymap for keys as described in the binding document + devicetree/bindings/input/matrix-keymap.txt. + +- keypad,num-rows: Number of row lines connected to the keypad controller. + +- keypad,num-columns: Number of column lines connected to the keypad + controller. + +Optional property: +- st,debounce_us: Debouncing interval time in microseconds + +Example: + +keyscan: keyscan@fe4b0000 { + compatible = "st,sti-keyscan"; + reg = <0xfe4b0000 0x2000>; + interrupts = <GIC_SPI 212 IRQ_TYPE_NONE>; + clocks = <&CLK_SYSIN>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_keyscan>; + + keypad,num-rows = <4>; + keypad,num-columns = <4>; + st,debounce_us = <5000>; + + linux,keymap = < MATRIX_KEY(0x00, 0x00, KEY_F13) + MATRIX_KEY(0x00, 0x01, KEY_F9) + MATRIX_KEY(0x00, 0x02, KEY_F5) + MATRIX_KEY(0x00, 0x03, KEY_F1) + MATRIX_KEY(0x01, 0x00, KEY_F14) + MATRIX_KEY(0x01, 0x01, KEY_F10) + MATRIX_KEY(0x01, 0x02, KEY_F6) + MATRIX_KEY(0x01, 0x03, KEY_F2) + MATRIX_KEY(0x02, 0x00, KEY_F15) + MATRIX_KEY(0x02, 0x01, KEY_F11) + MATRIX_KEY(0x02, 0x02, KEY_F7) + MATRIX_KEY(0x02, 0x03, KEY_F3) + MATRIX_KEY(0x03, 0x00, KEY_F16) + MATRIX_KEY(0x03, 0x01, KEY_F12) + MATRIX_KEY(0x03, 0x02, KEY_F8) + MATRIX_KEY(0x03, 0x03, KEY_F4) >; + }; diff --git a/Documentation/devicetree/bindings/input/touchscreen/sun4i.txt b/Documentation/devicetree/bindings/input/touchscreen/sun4i.txt new file mode 100644 index 000000000000..aef57791f40b --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/sun4i.txt @@ -0,0 +1,20 @@ +sun4i resistive touchscreen controller +-------------------------------------- + +Required properties: + - compatible: "allwinner,sun4i-a10-ts" + - reg: mmio address range of the chip + - interrupts: interrupt to which the chip is connected + +Optional properties: + - allwinner,ts-attached: boolean indicating that an actual touchscreen is + attached to the controller + +Example: + + rtp: rtp@01c25000 { + compatible = "allwinner,sun4i-a10-ts"; + reg = <0x01c25000 0x100>; + interrupts = <29>; + allwinner,ts-attached; + }; diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index ce953d895f5b..fd325ec9f064 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -629,12 +629,10 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p) return copy_to_user(p, str, len) ? -EFAULT : len; } -#define OLD_KEY_MAX 0x1ff static int handle_eviocgbit(struct input_dev *dev, unsigned int type, unsigned int size, void __user *p, int compat_mode) { - static unsigned long keymax_warn_time; unsigned long *bits; int len; @@ -652,24 +650,8 @@ static int handle_eviocgbit(struct input_dev *dev, default: return -EINVAL; } - /* - * Work around bugs in userspace programs that like to do - * EVIOCGBIT(EV_KEY, KEY_MAX) and not realize that 'len' - * should be in bytes, not in bits. - */ - if (type == EV_KEY && size == OLD_KEY_MAX) { - len = OLD_KEY_MAX; - if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000)) - pr_warning("(EVIOCGBIT): Suspicious buffer size %u, " - "limiting output to %zu bytes. See " - "http://userweb.kernel.org/~dtor/eviocgbit-bug.html\n", - OLD_KEY_MAX, - BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long)); - } - return bits_to_user(bits, len, size, p, compat_mode); } -#undef OLD_KEY_MAX static int evdev_handle_get_keycode(struct input_dev *dev, void __user *p) { diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c index 7f161d93203c..3664f81655ca 100644 --- a/drivers/input/input-polldev.c +++ b/drivers/input/input-polldev.c @@ -147,6 +147,11 @@ static struct attribute_group input_polldev_attribute_group = { .attrs = sysfs_attrs }; +static const struct attribute_group *input_polldev_attribute_groups[] = { + &input_polldev_attribute_group, + NULL +}; + /** * input_allocate_polled_device - allocate memory for polled device * @@ -171,6 +176,91 @@ struct input_polled_dev *input_allocate_polled_device(void) } EXPORT_SYMBOL(input_allocate_polled_device); +struct input_polled_devres { + struct input_polled_dev *polldev; +}; + +static int devm_input_polldev_match(struct device *dev, void *res, void *data) +{ + struct input_polled_devres *devres = res; + + return devres->polldev == data; +} + +static void devm_input_polldev_release(struct device *dev, void *res) +{ + struct input_polled_devres *devres = res; + struct input_polled_dev *polldev = devres->polldev; + + dev_dbg(dev, "%s: dropping reference/freeing %s\n", + __func__, dev_name(&polldev->input->dev)); + + input_put_device(polldev->input); + kfree(polldev); +} + +static void devm_input_polldev_unregister(struct device *dev, void *res) +{ + struct input_polled_devres *devres = res; + struct input_polled_dev *polldev = devres->polldev; + + dev_dbg(dev, "%s: unregistering device %s\n", + __func__, dev_name(&polldev->input->dev)); + input_unregister_device(polldev->input); + + /* + * Note that we are still holding extra reference to the input + * device so it will stick around until devm_input_polldev_release() + * is called. + */ +} + +/** + * devm_input_allocate_polled_device - allocate managed polled device + * @dev: device owning the polled device being created + * + * Returns prepared &struct input_polled_dev or %NULL. + * + * Managed polled input devices do not need to be explicitly unregistered + * or freed as it will be done automatically when owner device unbinds + * from * its driver (or binding fails). Once such managed polled device + * is allocated, it is ready to be set up and registered in the same + * fashion as regular polled input devices (using + * input_register_polled_device() function). + * + * If you want to manually unregister and free such managed polled devices, + * it can be still done by calling input_unregister_polled_device() and + * input_free_polled_device(), although it is rarely needed. + * + * NOTE: the owner device is set up as parent of input device and users + * should not override it. + */ +struct input_polled_dev *devm_input_allocate_polled_device(struct device *dev) +{ + struct input_polled_dev *polldev; + struct input_polled_devres *devres; + + devres = devres_alloc(devm_input_polldev_release, sizeof(*devres), + GFP_KERNEL); + if (!devres) + return NULL; + + polldev = input_allocate_polled_device(); + if (!polldev) { + devres_free(devres); + return NULL; + } + + polldev->input->dev.parent = dev; + polldev->devres_managed = true; + + devres->polldev = polldev; + devres_add(dev, devres); + + return polldev; +} +EXPORT_SYMBOL(devm_input_allocate_polled_device); + /** * input_free_polled_device - free memory allocated for polled device * @dev: device to free @@ -181,7 +271,12 @@ EXPORT_SYMBOL(input_allocate_polled_device); void input_free_polled_device(struct input_polled_dev *dev) { if (dev) { - input_free_device(dev->input); + if (dev->devres_managed) + WARN_ON(devres_destroy(dev->input->dev.parent, + devm_input_polldev_release, + devm_input_polldev_match, + dev)); + input_put_device(dev->input); kfree(dev); } } @@ -199,26 +294,35 @@ EXPORT_SYMBOL(input_free_polled_device); */ int input_register_polled_device(struct input_polled_dev *dev) { + struct input_polled_devres *devres = NULL; struct input_dev *input = dev->input; int error; + if (dev->devres_managed) { + devres = devres_alloc(devm_input_polldev_unregister, + sizeof(*devres), GFP_KERNEL); + if (!devres) + return -ENOMEM; + + devres->polldev = dev; + } + input_set_drvdata(input, dev); INIT_DELAYED_WORK(&dev->work, input_polled_device_work); + if (!dev->poll_interval) dev->poll_interval = 500; if (!dev->poll_interval_max) dev->poll_interval_max = dev->poll_interval; + input->open = input_open_polled_device; input->close = input_close_polled_device; - error = input_register_device(input); - if (error) - return error; + input->dev.groups = input_polldev_attribute_groups; - error = sysfs_create_group(&input->dev.kobj, - &input_polldev_attribute_group); + error = input_register_device(input); if (error) { - input_unregister_device(input); + devres_free(devres); return error; } @@ -231,6 +335,12 @@ int input_register_polled_device(struct input_polled_dev *dev) */ input_get_device(input); + if (dev->devres_managed) { + dev_dbg(input->dev.parent, "%s: registering %s with devres.\n", + __func__, dev_name(&input->dev)); + devres_add(input->dev.parent, devres); + } + return 0; } EXPORT_SYMBOL(input_register_polled_device); @@ -245,8 +355,11 @@ EXPORT_SYMBOL(input_register_polled_device); */ void input_unregister_polled_device(struct input_polled_dev *dev) { - sysfs_remove_group(&dev->input->dev.kobj, - &input_polldev_attribute_group); + if (dev->devres_managed) + WARN_ON(devres_destroy(dev->input->dev.parent, + devm_input_polldev_unregister, + devm_input_polldev_match, + dev)); input_unregister_device(dev->input); } diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 76842d7dc2e3..948a30304870 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -524,6 +524,17 @@ config KEYBOARD_STOWAWAY To compile this driver as a module, choose M here: the module will be called stowaway. +config KEYBOARD_ST_KEYSCAN + tristate "STMicroelectronics keyscan support" + depends on ARCH_STI || COMPILE_TEST + select INPUT_MATRIXKMAP + help + Say Y here if you want to use a keypad attached to the keyscan block + on some STMicroelectronics SoC devices. + + To compile this driver as a module, choose M here: the + module will be called st-keyscan. + config KEYBOARD_SUNKBD tristate "Sun Type 4 and Type 5 keyboard" select SERIO diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 11cff7b84b47..7504ae19049d 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o obj-$(CONFIG_KEYBOARD_SPEAR) += spear-keyboard.o obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o +obj-$(CONFIG_KEYBOARD_ST_KEYSCAN) += st-keyscan.o obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o diff --git a/drivers/input/keyboard/clps711x-keypad.c b/drivers/input/keyboard/clps711x-keypad.c index 3955aecee44b..552b65c6e6b0 100644 --- a/drivers/input/keyboard/clps711x-keypad.c +++ b/drivers/input/keyboard/clps711x-keypad.c @@ -185,7 +185,7 @@ static int clps711x_keypad_remove(struct platform_device *pdev) return 0; } -static struct of_device_id clps711x_keypad_of_match[] = { +static const struct of_device_id clps711x_keypad_of_match[] = { { .compatible = "cirrus,clps711x-keypad", }, { } }; diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 2db13246eb8e..8c98e97f8e41 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -424,6 +424,16 @@ out: return IRQ_HANDLED; } +static void gpio_keys_quiesce_key(void *data) +{ + struct gpio_button_data *bdata = data; + + if (bdata->timer_debounce) + del_timer_sync(&bdata->timer); + + cancel_work_sync(&bdata->work); +} + static int gpio_keys_setup_key(struct platform_device *pdev, struct input_dev *input, struct gpio_button_data *bdata, @@ -433,7 +443,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev, struct device *dev = &pdev->dev; irq_handler_t isr; unsigned long irqflags; - int irq, error; + int irq; + int error; bdata->input = input; bdata->button = button; @@ -441,7 +452,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev, if (gpio_is_valid(button->gpio)) { - error = gpio_request_one(button->gpio, GPIOF_IN, desc); + error = devm_gpio_request_one(&pdev->dev, button->gpio, + GPIOF_IN, desc); if (error < 0) { dev_err(dev, "Failed to request GPIO %d, error %d\n", button->gpio, error); @@ -463,7 +475,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev, dev_err(dev, "Unable to get irq number for GPIO %d, error %d\n", button->gpio, error); - goto fail; + return error; } bdata->irq = irq; @@ -497,26 +509,33 @@ static int gpio_keys_setup_key(struct platform_device *pdev, input_set_capability(input, button->type ?: EV_KEY, button->code); /* + * Install custom action to cancel debounce timer and + * workqueue item. + */ + error = devm_add_action(&pdev->dev, gpio_keys_quiesce_key, bdata); + if (error) { + dev_err(&pdev->dev, + "failed to register quiesce action, error: %d\n", + error); + return error; + } + + /* * If platform has specified that the button can be disabled, * we don't want it to share the interrupt line. */ if (!button->can_disable) irqflags |= IRQF_SHARED; - error = request_any_context_irq(bdata->irq, isr, irqflags, desc, bdata); + error = devm_request_any_context_irq(&pdev->dev, bdata->irq, + isr, irqflags, desc, bdata); if (error < 0) { dev_err(dev, "Unable to claim irq %d; error %d\n", bdata->irq, error); - goto fail; + return error; } return 0; - -fail: - if (gpio_is_valid(button->gpio)) - gpio_free(button->gpio); - - return error; } static void gpio_keys_report_state(struct gpio_keys_drvdata *ddata) @@ -578,23 +597,18 @@ gpio_keys_get_devtree_pdata(struct device *dev) int i; node = dev->of_node; - if (!node) { - error = -ENODEV; - goto err_out; - } + if (!node) + return ERR_PTR(-ENODEV); nbuttons = of_get_child_count(node); - if (nbuttons == 0) { - error = -ENODEV; - goto err_out; - } + if (nbuttons == 0) + return ERR_PTR(-ENODEV); - pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button), - GFP_KERNEL); - if (!pdata) { - error = -ENOMEM; - goto err_out; - } + pdata = devm_kzalloc(dev, + sizeof(*pdata) + nbuttons * sizeof(*button), + GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); pdata->buttons = (struct gpio_keys_button *)(pdata + 1); pdata->nbuttons = nbuttons; @@ -619,7 +633,7 @@ gpio_keys_get_devtree_pdata(struct device *dev) dev_err(dev, "Failed to get gpio flags, error: %d\n", error); - goto err_free_pdata; + return ERR_PTR(error); } button = &pdata->buttons[i++]; @@ -630,8 +644,7 @@ gpio_keys_get_devtree_pdata(struct device *dev) if (of_property_read_u32(pp, "linux,code", &button->code)) { dev_err(dev, "Button without keycode: 0x%x\n", button->gpio); - error = -EINVAL; - goto err_free_pdata; + return ERR_PTR(-EINVAL); } button->desc = of_get_property(pp, "label", NULL); @@ -646,20 +659,13 @@ gpio_keys_get_devtree_pdata(struct device *dev) button->debounce_interval = 5; } - if (pdata->nbuttons == 0) { - error = -EINVAL; - goto err_free_pdata; - } + if (pdata->nbuttons == 0) + return ERR_PTR(-EINVAL); return pdata; - -err_free_pdata: - kfree(pdata); -err_out: - return ERR_PTR(error); } -static struct of_device_id gpio_keys_of_match[] = { +static const struct of_device_id gpio_keys_of_match[] = { { .compatible = "gpio-keys", }, { }, }; @@ -675,22 +681,13 @@ gpio_keys_get_devtree_pdata(struct device *dev) #endif -static void gpio_remove_key(struct gpio_button_data *bdata) -{ - free_irq(bdata->irq, bdata); - if (bdata->timer_debounce) - del_timer_sync(&bdata->timer); - cancel_work_sync(&bdata->work); - if (gpio_is_valid(bdata->button->gpio)) - gpio_free(bdata->button->gpio); -} - static int gpio_keys_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); struct gpio_keys_drvdata *ddata; struct input_dev *input; + size_t size; int i, error; int wakeup = 0; @@ -700,14 +697,18 @@ static int gpio_keys_probe(struct platform_device *pdev) return PTR_ERR(pdata); } - ddata = kzalloc(sizeof(struct gpio_keys_drvdata) + - pdata->nbuttons * sizeof(struct gpio_button_data), - GFP_KERNEL); - input = input_allocate_device(); - if (!ddata || !input) { + size = sizeof(struct gpio_keys_drvdata) + + pdata->nbuttons * sizeof(struct gpio_button_data); + ddata = devm_kzalloc(dev, size, GFP_KERNEL); + if (!ddata) { dev_err(dev, "failed to allocate state\n"); - error = -ENOMEM; - goto fail1; + return -ENOMEM; + } + + input = devm_input_allocate_device(dev); + if (!input) { + dev_err(dev, "failed to allocate input device\n"); + return -ENOMEM; } ddata->pdata = pdata; @@ -738,7 +739,7 @@ static int gpio_keys_probe(struct platform_device *pdev) error = gpio_keys_setup_key(pdev, input, bdata, button); if (error) - goto fail2; + return error; if (button->wakeup) wakeup = 1; @@ -748,57 +749,31 @@ static int gpio_keys_probe(struct platform_device *pdev) if (error) { dev_err(dev, "Unable to export keys/switches, error: %d\n", error); - goto fail2; + return error; } error = input_register_device(input); if (error) { dev_err(dev, "Unable to register input device, error: %d\n", error); - goto fail3; + goto err_remove_group; } device_init_wakeup(&pdev->dev, wakeup); return 0; - fail3: +err_remove_group: sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); - fail2: - while (--i >= 0) - gpio_remove_key(&ddata->data[i]); - - fail1: - input_free_device(input); - kfree(ddata); - /* If we have no platform data, we allocated pdata dynamically. */ - if (!dev_get_platdata(&pdev->dev)) - kfree(pdata); - return error; } static int gpio_keys_remove(struct platform_device *pdev) { - struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); - struct input_dev *input = ddata->input; - int i; - sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); device_init_wakeup(&pdev->dev, 0); - for (i = 0; i < ddata->pdata->nbuttons; i++) - gpio_remove_key(&ddata->data[i]); - - input_unregister_device(input); - - /* If we have no platform data, we allocated pdata dynamically. */ - if (!dev_get_platdata(&pdev->dev)) - kfree(ddata->pdata); - - kfree(ddata); - return 0; } diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index e571e194ff84..432d36395f35 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c @@ -120,12 +120,10 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct if (nbuttons == 0) return NULL; - pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button), - GFP_KERNEL); - if (!pdata) { - error = -ENOMEM; - goto err_out; - } + pdata = devm_kzalloc(dev, sizeof(*pdata) + nbuttons * sizeof(*button), + GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); pdata->buttons = (struct gpio_keys_button *)(pdata + 1); pdata->nbuttons = nbuttons; @@ -151,7 +149,7 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct dev_err(dev, "Failed to get gpio flags, error: %d\n", error); - goto err_free_pdata; + return ERR_PTR(error); } button = &pdata->buttons[i++]; @@ -162,8 +160,7 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct if (of_property_read_u32(pp, "linux,code", &button->code)) { dev_err(dev, "Button without keycode: 0x%x\n", button->gpio); - error = -EINVAL; - goto err_free_pdata; + return ERR_PTR(-EINVAL); } button->desc = of_get_property(pp, "label", NULL); @@ -178,20 +175,13 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct button->debounce_interval = 5; } - if (pdata->nbuttons == 0) { - error = -EINVAL; - goto err_free_pdata; - } + if (pdata->nbuttons == 0) + return ERR_PTR(-EINVAL); return pdata; - -err_free_pdata: - kfree(pdata); -err_out: - return ERR_PTR(error); } -static struct of_device_id gpio_keys_polled_of_match[] = { +static const struct of_device_id gpio_keys_polled_of_match[] = { { .compatible = "gpio-keys-polled", }, { }, }; @@ -213,6 +203,7 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) struct gpio_keys_polled_dev *bdev; struct input_polled_dev *poll_dev; struct input_dev *input; + size_t size; int error; int i; @@ -228,24 +219,21 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) if (!pdata->poll_interval) { dev_err(dev, "missing poll_interval value\n"); - error = -EINVAL; - goto err_free_pdata; + return -EINVAL; } - bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) + - pdata->nbuttons * sizeof(struct gpio_keys_button_data), - GFP_KERNEL); + size = sizeof(struct gpio_keys_polled_dev) + + pdata->nbuttons * sizeof(struct gpio_keys_button_data); + bdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); if (!bdev) { dev_err(dev, "no memory for private data\n"); - error = -ENOMEM; - goto err_free_pdata; + return -ENOMEM; } - poll_dev = input_allocate_polled_device(); + poll_dev = devm_input_allocate_polled_device(&pdev->dev); if (!poll_dev) { dev_err(dev, "no memory for polled device\n"); - error = -ENOMEM; - goto err_free_bdev; + return -ENOMEM; } poll_dev->private = bdev; @@ -258,7 +246,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) input->name = pdev->name; input->phys = DRV_NAME"/input0"; - input->dev.parent = &pdev->dev; input->id.bustype = BUS_HOST; input->id.vendor = 0x0001; @@ -277,16 +264,15 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) if (button->wakeup) { dev_err(dev, DRV_NAME " does not support wakeup\n"); - error = -EINVAL; - goto err_free_gpio; + return -EINVAL; } - error = gpio_request_one(gpio, GPIOF_IN, - button->desc ?: DRV_NAME); + error = devm_gpio_request_one(&pdev->dev, gpio, GPIOF_IN, + button->desc ? : DRV_NAME); if (error) { dev_err(dev, "unable to claim gpio %u, err=%d\n", gpio, error); - goto err_free_gpio; + return error; } bdata->can_sleep = gpio_cansleep(gpio); @@ -306,7 +292,7 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) if (error) { dev_err(dev, "unable to register polled device, err=%d\n", error); - goto err_free_gpio; + return error; } /* report initial state of the buttons */ |
