diff --git a/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts b/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts index 0ad29f31da10..5183e64fc1f9 100644 --- a/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts +++ b/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts @@ -341,6 +341,16 @@ status = "ok"; }; + gpio_keypad{ + compatible = "amlogic, gpio_keypad"; + status = "okay"; + scan_period = <20>; + key_num = <1>; + key_name = "power"; + key_code = <116>; + reg = <0x0 0xFF800000 0x0 0x400>; + }; + }; /* end of / */ &meson_fb { diff --git a/drivers/amlogic/input/keyboard/gpio_keypad.c b/drivers/amlogic/input/keyboard/gpio_keypad.c index 33abc17b92b0..3fa6ea35bc30 100644 --- a/drivers/amlogic/input/keyboard/gpio_keypad.c +++ b/drivers/amlogic/input/keyboard/gpio_keypad.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,9 @@ #define DEFAULT_POLL_MODE 0 #define KEY_JITTER_COUNT 1 +#define AO_DEBUG_REG0 ((0x28 << 2)) +static unsigned long gpiopower; + struct pin_desc { int current_status; struct gpio_desc *desc; @@ -52,6 +56,23 @@ struct gpio_keypad { struct input_dev *input_dev; }; +static int __init gpiopower_setup(char *str) +{ + int ret; + + if (str == NULL) { + gpiopower = 0; + return -EINVAL; + } + + ret = kstrtoul(str, 0, &gpiopower); + + pr_info("%s gpiopower : %ld\n", __func__, gpiopower); + + return 0; +} +__setup("gpiopower=", gpiopower_setup); + static irqreturn_t gpio_irq_handler(int irq, void *data) { struct gpio_keypad *keypad; @@ -148,6 +169,9 @@ static int meson_gpio_kp_probe(struct platform_device *pdev) int ret, i; struct input_dev *input_dev; struct gpio_keypad *keypad; + struct resource *res; + int val, err; + void __iomem *ao_reg; if (!(pdev->dev.of_node)) { dev_err(&pdev->dev, @@ -179,11 +203,50 @@ static int meson_gpio_kp_probe(struct platform_device *pdev) (keypad->key_size)*sizeof(*(keypad->key)), GFP_KERNEL); if (!(keypad->key)) return -EINVAL; + if (gpiopower) { + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res) { + ao_reg = ioremap(res->start, res->end - res->start); + } else { + dev_info(&pdev->dev, "Failed to get AO reg\n"); + ao_reg = NULL; + } + } for (i = 0; i < keypad->key_size; i++) { - //get all gpio desc. - desc = devm_gpiod_get_index(&pdev->dev, "key", i, GPIOD_IN); - if (!desc) - return -EINVAL; + if (gpiopower) { + if (gpio_is_valid(gpiopower)) { + err = devm_gpio_request_one(&pdev->dev, + gpiopower, GPIOF_IN, "gpio_keys"); + if (err < 0) { + dev_err(&pdev->dev, "Failed to request GPIO %ld, error %d\n", + gpiopower, err); + return -EINVAL; + } + desc = gpio_to_desc(gpiopower); + if (!desc) { + dev_err(&pdev->dev, "Failed to get desc\n"); + return -EINVAL; + } + + if (ao_reg) { + val = readl((ao_reg + AO_DEBUG_REG0)); + val |= (gpiopower << 16); + writel(val, (ao_reg + AO_DEBUG_REG0)); + } + } else { + dev_err(&pdev->dev, "invalid gpio %ld\n", + gpiopower); + return -EINVAL; + } + } else { + //get all gpio desc. + desc = devm_gpiod_get_index(&pdev->dev, + "key", i, GPIOD_IN); + if (IS_ERR(desc)) { + dev_err(&pdev->dev, "failed to get gpio index from dts\n"); + return -EINVAL; + } + } keypad->key[i].desc = desc; //The gpio default is high level. keypad->key[i].current_status = 1;