diff --git a/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts b/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts index 061bed9dcad7..fd7156dff1ac 100644 --- a/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts +++ b/arch/arm64/boot/dts/amlogic/meson64_odroidn2.dts @@ -339,6 +339,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 570c084d4301..fbd4e0690cf6 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 @@ -33,6 +34,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; @@ -55,6 +59,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; @@ -157,6 +178,9 @@ static int meson_gpio_kp_probe(struct platform_device *pdev) struct input_dev *input_dev; struct gpio_keypad *keypad; bool pwrkey_update_flg = false; + struct resource *res; + int val, err; + void __iomem *ao_reg = NULL; if (!(pdev->dev.of_node)) { dev_err(&pdev->dev, @@ -188,11 +212,47 @@ 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 (IS_ERR_OR_NULL(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_OR_NULL(desc)) + return -EINVAL; + } keypad->key[i].desc = desc; //The gpio default is high level. keypad->key[i].current_status = 1;