| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Driver for keys on GPIO lines capable of generating interrupts. |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright 2005 Phil Blundell |
|---|
| 5 | 6 | * Copyright 2010, 2011 David Jander <david@protonic.nl> |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 9 | | - * published by the Free Software Foundation. |
|---|
| 10 | 7 | */ |
|---|
| 11 | 8 | |
|---|
| 12 | 9 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 31 | 28 | #include <linux/of_irq.h> |
|---|
| 32 | 29 | #include <linux/spinlock.h> |
|---|
| 33 | 30 | #include <dt-bindings/input/gpio-keys.h> |
|---|
| 31 | +#include <trace/hooks/wakeupbypass.h> |
|---|
| 34 | 32 | |
|---|
| 35 | 33 | struct gpio_button_data { |
|---|
| 36 | 34 | const struct gpio_keys_button *button; |
|---|
| .. | .. |
|---|
| 58 | 56 | struct input_dev *input; |
|---|
| 59 | 57 | struct mutex disable_lock; |
|---|
| 60 | 58 | unsigned short *keymap; |
|---|
| 61 | | - struct gpio_button_data data[0]; |
|---|
| 59 | + struct gpio_button_data data[]; |
|---|
| 62 | 60 | }; |
|---|
| 63 | 61 | |
|---|
| 64 | 62 | /* |
|---|
| .. | .. |
|---|
| 354 | 352 | &dev_attr_disabled_switches.attr, |
|---|
| 355 | 353 | NULL, |
|---|
| 356 | 354 | }; |
|---|
| 357 | | - |
|---|
| 358 | | -static const struct attribute_group gpio_keys_attr_group = { |
|---|
| 359 | | - .attrs = gpio_keys_attrs, |
|---|
| 360 | | -}; |
|---|
| 355 | +ATTRIBUTE_GROUPS(gpio_keys); |
|---|
| 361 | 356 | |
|---|
| 362 | 357 | static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) |
|---|
| 363 | 358 | { |
|---|
| .. | .. |
|---|
| 500 | 495 | spin_lock_init(&bdata->lock); |
|---|
| 501 | 496 | |
|---|
| 502 | 497 | if (child) { |
|---|
| 503 | | - bdata->gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL, |
|---|
| 504 | | - child, |
|---|
| 505 | | - GPIOD_IN, |
|---|
| 506 | | - desc); |
|---|
| 498 | + bdata->gpiod = devm_fwnode_gpiod_get(dev, child, |
|---|
| 499 | + NULL, GPIOD_IN, desc); |
|---|
| 507 | 500 | if (IS_ERR(bdata->gpiod)) { |
|---|
| 508 | 501 | error = PTR_ERR(bdata->gpiod); |
|---|
| 509 | 502 | if (error == -ENOENT) { |
|---|
| .. | .. |
|---|
| 582 | 575 | IRQ_TYPE_EDGE_RISING : IRQ_TYPE_EDGE_FALLING; |
|---|
| 583 | 576 | break; |
|---|
| 584 | 577 | case EV_ACT_ANY: |
|---|
| 585 | | - /* fall through */ |
|---|
| 586 | 578 | default: |
|---|
| 587 | 579 | /* |
|---|
| 588 | 580 | * For other cases, we are OK letting suspend/resume |
|---|
| .. | .. |
|---|
| 774 | 766 | struct fwnode_handle *child = NULL; |
|---|
| 775 | 767 | struct gpio_keys_drvdata *ddata; |
|---|
| 776 | 768 | struct input_dev *input; |
|---|
| 777 | | - size_t size; |
|---|
| 778 | 769 | int i, error; |
|---|
| 779 | 770 | int wakeup = 0; |
|---|
| 780 | 771 | |
|---|
| .. | .. |
|---|
| 784 | 775 | return PTR_ERR(pdata); |
|---|
| 785 | 776 | } |
|---|
| 786 | 777 | |
|---|
| 787 | | - size = sizeof(struct gpio_keys_drvdata) + |
|---|
| 788 | | - pdata->nbuttons * sizeof(struct gpio_button_data); |
|---|
| 789 | | - ddata = devm_kzalloc(dev, size, GFP_KERNEL); |
|---|
| 778 | + ddata = devm_kzalloc(dev, struct_size(ddata, data, pdata->nbuttons), |
|---|
| 779 | + GFP_KERNEL); |
|---|
| 790 | 780 | if (!ddata) { |
|---|
| 791 | 781 | dev_err(dev, "failed to allocate state\n"); |
|---|
| 792 | 782 | return -ENOMEM; |
|---|
| .. | .. |
|---|
| 855 | 845 | } |
|---|
| 856 | 846 | |
|---|
| 857 | 847 | fwnode_handle_put(child); |
|---|
| 858 | | - |
|---|
| 859 | | - error = devm_device_add_group(dev, &gpio_keys_attr_group); |
|---|
| 860 | | - if (error) { |
|---|
| 861 | | - dev_err(dev, "Unable to export keys/switches, error: %d\n", |
|---|
| 862 | | - error); |
|---|
| 863 | | - return error; |
|---|
| 864 | | - } |
|---|
| 865 | 848 | |
|---|
| 866 | 849 | error = input_register_device(input); |
|---|
| 867 | 850 | if (error) { |
|---|
| .. | .. |
|---|
| 976 | 959 | struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); |
|---|
| 977 | 960 | struct input_dev *input = ddata->input; |
|---|
| 978 | 961 | int error; |
|---|
| 962 | + int wakeup_bypass_enabled = 0; |
|---|
| 963 | + |
|---|
| 964 | + trace_android_vh_wakeup_bypass(&wakeup_bypass_enabled); |
|---|
| 979 | 965 | |
|---|
| 980 | 966 | if (device_may_wakeup(dev)) { |
|---|
| 981 | | - error = gpio_keys_enable_wakeup(ddata); |
|---|
| 982 | | - if (error) |
|---|
| 983 | | - return error; |
|---|
| 967 | + if (!wakeup_bypass_enabled) { |
|---|
| 968 | + error = gpio_keys_enable_wakeup(ddata); |
|---|
| 969 | + if (error) |
|---|
| 970 | + return error; |
|---|
| 971 | + } |
|---|
| 984 | 972 | } else { |
|---|
| 985 | 973 | mutex_lock(&input->mutex); |
|---|
| 986 | 974 | if (input->users) |
|---|
| .. | .. |
|---|
| 996 | 984 | struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); |
|---|
| 997 | 985 | struct input_dev *input = ddata->input; |
|---|
| 998 | 986 | int error = 0; |
|---|
| 987 | + int wakeup_bypass_enabled = 0; |
|---|
| 988 | + |
|---|
| 989 | + trace_android_vh_wakeup_bypass(&wakeup_bypass_enabled); |
|---|
| 999 | 990 | |
|---|
| 1000 | 991 | if (device_may_wakeup(dev)) { |
|---|
| 1001 | | - gpio_keys_disable_wakeup(ddata); |
|---|
| 992 | + if (!wakeup_bypass_enabled) |
|---|
| 993 | + gpio_keys_disable_wakeup(ddata); |
|---|
| 1002 | 994 | } else { |
|---|
| 1003 | 995 | mutex_lock(&input->mutex); |
|---|
| 1004 | 996 | if (input->users) |
|---|
| .. | .. |
|---|
| 1015 | 1007 | |
|---|
| 1016 | 1008 | static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume); |
|---|
| 1017 | 1009 | |
|---|
| 1010 | +static void gpio_keys_shutdown(struct platform_device *pdev) |
|---|
| 1011 | +{ |
|---|
| 1012 | + int ret; |
|---|
| 1013 | + |
|---|
| 1014 | + ret = gpio_keys_suspend(&pdev->dev); |
|---|
| 1015 | + if (ret) |
|---|
| 1016 | + dev_err(&pdev->dev, "failed to shutdown\n"); |
|---|
| 1017 | +} |
|---|
| 1018 | + |
|---|
| 1018 | 1019 | static struct platform_driver gpio_keys_device_driver = { |
|---|
| 1019 | 1020 | .probe = gpio_keys_probe, |
|---|
| 1021 | + .shutdown = gpio_keys_shutdown, |
|---|
| 1020 | 1022 | .driver = { |
|---|
| 1021 | 1023 | .name = "gpio-keys", |
|---|
| 1022 | 1024 | .pm = &gpio_keys_pm_ops, |
|---|
| 1023 | 1025 | .of_match_table = gpio_keys_of_match, |
|---|
| 1026 | + .dev_groups = gpio_keys_groups, |
|---|
| 1024 | 1027 | } |
|---|
| 1025 | 1028 | }; |
|---|
| 1026 | 1029 | |
|---|