ODROID-C5: gpio/irqchip: Add GPIO wakeup feature on suspend/resume
Signed-off-by: Dongjin Kim <tobetter@gmail.com>
Change-Id: I5b1292f7af270fadaa75062e3b2ab12b1978495f
diff --git a/drivers/gpio/irqchip/irq-meson-gpio.c b/drivers/gpio/irqchip/irq-meson-gpio.c
index 77a86ea..d5574f3 100644
--- a/drivers/gpio/irqchip/irq-meson-gpio.c
+++ b/drivers/gpio/irqchip/irq-meson-gpio.c
@@ -17,6 +17,9 @@
#ifdef CONFIG_AMLOGIC_MODIFY
#include <linux/amlogic/glb_timer.h>
#endif
+#if defined(CONFIG_ARCH_MESON_ODROID_COMMON)
+#include <linux/amlogic/aml_mbox.h>
+#endif
#define NUM_CHANNEL 8
#define MAX_INPUT_MUX 256
@@ -26,6 +29,10 @@
#define REG_PIN_47_SEL 0x08
#define REG_FILTER_SEL 0x0c
+#if defined(CONFIG_ARCH_MESON_ODROID_COMMON)
+static struct mbox_chan *mbox_chan = NULL;
+#endif
+
/* use for A1 like chips */
#define REG_PIN_A1_SEL 0x04
@@ -929,6 +936,12 @@
platform_set_drvdata(pdev, ctl);
#endif /* CONFIG_AMLOGIC_MODIFY */
+#if defined(CONFIG_ARCH_MESON_ODROID_COMMON)
+ mbox_chan = aml_mbox_request_channel_byidx(irq_dev, 0);
+ if (IS_ERR_OR_NULL(mbox_chan))
+ mbox_chan = NULL;
+#endif
+
return 0;
free_channel_irqs:
@@ -982,6 +995,38 @@
};
#endif /* CONFIG_AMLOGIC_MODIFY */
+#if defined(CONFIG_ARCH_MESON_ODROID_COMMON)
+int irq_meson_gpio_suspend(struct irq_desc *desc, int on)
+{
+ struct irq_data *data;
+ u32 *channel_hwirq;
+ u32 buf[4];
+
+ if (on) {
+ if (!desc)
+ return 0;
+
+ data = &desc->irq_data;
+ channel_hwirq = irq_data_get_irq_chip_data(data);
+ if (*channel_hwirq == 0)
+ return -EINVAL;
+
+ buf[0] = 151 + data->hwirq;
+ buf[1] = 1; // Currently support LOW only
+ buf[2] = (1 << 0); // EVENT_SHORT
+ buf[3] = 2; // DUMMY
+ } else {
+ buf[0] = 0xffffffff;
+ }
+
+ aml_mbox_transfer_data(mbox_chan, MBOX_CMD_SET_KEYPAD,
+ &buf, sizeof(buf), NULL, 0, MBOX_SYNC);
+
+ return 0;
+}
+EXPORT_SYMBOL(irq_meson_gpio_suspend);
+#endif
+
static const struct of_device_id meson_gpio_irq_match_table[] = {
{ .compatible = "amlogic,meson-gpio-intc" },
{}
diff --git a/drivers/gpio/pinctrl/pinctrl-meson-s7d.c b/drivers/gpio/pinctrl/pinctrl-meson-s7d.c
index 3f4c2b8..5cfefdc 100644
--- a/drivers/gpio/pinctrl/pinctrl-meson-s7d.c
+++ b/drivers/gpio/pinctrl/pinctrl-meson-s7d.c
@@ -1386,11 +1386,47 @@
{ },
};
+#if defined(CONFIG_ARCH_MESON_ODROID_COMMON)
+extern int irq_meson_gpio_suspend(struct irq_desc *desc, int on);
+
+static void meson_pinctrl_shutdown(struct platform_device *pdev)
+{
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(meson_s7d_periphs_banks); i++) {
+ struct meson_bank *bank = &meson_s7d_periphs_banks[i];
+ for (j = bank->irq_first; j <= bank->irq_last; j++) {
+ struct irq_desc *desc = irq_to_desc(j);
+ irq_meson_gpio_suspend(desc, 1);
+ }
+ }
+}
+
+static int meson_pinctrl_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ meson_pinctrl_shutdown(pdev);
+ return 0;
+}
+
+static int meson_pinctrl_resume(struct platform_device *pdev)
+{
+ irq_meson_gpio_suspend(NULL, 0);
+
+ return 0;
+}
+#endif
+
static struct platform_driver meson_s7d_pinctrl_driver = {
.probe = meson_pinctrl_probe,
.driver = {
.name = "meson-s7d-pinctrl",
},
+#if defined(CONFIG_ARCH_MESON_ODROID_COMMON)
+ .suspend = meson_pinctrl_suspend,
+ .resume = meson_pinctrl_resume,
+ .shutdown = meson_pinctrl_shutdown,
+#endif
};
#ifndef MODULE
diff --git a/include/linux/amlogic/aml_mbox_cmd.h b/include/linux/amlogic/aml_mbox_cmd.h
index 90b6102..11c4b4b 100644
--- a/include/linux/amlogic/aml_mbox_cmd.h
+++ b/include/linux/amlogic/aml_mbox_cmd.h
@@ -71,6 +71,7 @@
#define CMD_BL4_WAIT_UNLOCK 0xD6
#define CMD_BL4_SEND 0xD7
#define CMD_BL4_LISTEN 0xD8
+#define CMD_SET_KEYPAD 0xF6
#define CMD_LEDS_STATE 0xF7
#define CMD_SET_IR_STATE 0xF8
#define CMD_SET_FD650 0x68
@@ -137,6 +138,7 @@
#define MBOX_CMD_BL4_WAIT_UNLOCK __MBX_COMPOSE_MSG(MBX_SYSTEM, CMD_BL4_WAIT_UNLOCK)
#define MBOX_CMD_BL4_SEND __MBX_COMPOSE_MSG(MBX_SYSTEM, CMD_BL4_SEND)
#define MBOX_CMD_BL4_LISTEN __MBX_COMPOSE_MSG(MBX_SYSTEM, CMD_BL4_LISTEN)
+#define MBOX_CMD_SET_KEYPAD __MBX_COMPOSE_MSG(MBX_SYSTEM, CMD_SET_KEYPAD)
#define MBOX_CMD_LEDS_STATE __MBX_COMPOSE_MSG(MBX_SYSTEM, CMD_LEDS_STATE)
#define MBOX_CMD_SET_IR_STATE __MBX_COMPOSE_MSG(MBX_SYSTEM, CMD_SET_IR_STATE)
#define MBOX_CMD_SET_FD650 __MBX_COMPOSE_MSG(MBX_SYSTEM, CMD_SET_FD650)