irqchip: sm1 support double-edge gpio irq trigger [1/1]
authorQianggui Song <qianggui.song@amlogic.com>
Fri, 8 Mar 2019 07:40:42 +0000 (15:40 +0800)
committerJianxiong Pan <jianxiong.pan@amlogic.com>
Fri, 29 Mar 2019 12:24:31 +0000 (20:24 +0800)
PD#SWPL-5395

Problem:
sm1 support double-edge trigger, current code do not support.

Solution:
add relatvie bitmask to support this function.

Verify:
ptm & sm1_skt

Change-Id: I48ebc9b38db868f946c49b6fd5f98d427b2669df
Signed-off-by: Qianggui Song <qianggui.song@amlogic.com>
Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt
arch/arm/boot/dts/amlogic/mesonsm1.dtsi
arch/arm64/boot/dts/amlogic/mesonsm1.dtsi
drivers/amlogic/irqchip/irq-meson-gpio.c

index 4dfe69f..3f305fd 100644 (file)
@@ -19,6 +19,7 @@ Required properties:
    “amlogic,meson-g12a-gpio-intc” for G12A SoCs (S905D2, S905X2, S905Y2)
    “amlogic,meson-txl-gpio-intc” for TXL SoCs (T950, T952, T960, T962)
    “amlogic,meson-tl1-gpio-intc” for TL1 SoCs (T962X2)
+   “amlogic,meson-sm1-gpio-intc” for SM1 SoCs (S905D3, S905X3, S905Y3)
 - interrupt-parent : a phandle to the GIC the interrupts are routed to.
    Usually this is provided at the root level of the device tree as it is
    common to most of the SoC.
index 61d5b1f..9cb9d78 100644 (file)
 
                        gpio_intc: interrupt-controller@f080 {
                                compatible = "amlogic,meson-gpio-intc",
-                                               "amlogic,meson-g12a-gpio-intc";
+                                               "amlogic,meson-sm1-gpio-intc";
                                reg = <0xf080 0x10>;
                                interrupt-controller;
                                #interrupt-cells = <2>;
index a3bddfe..906622a 100644 (file)
 
                        gpio_intc: interrupt-controller@f080 {
                                compatible = "amlogic,meson-gpio-intc",
-                                               "amlogic,meson-g12a-gpio-intc";
+                                               "amlogic,meson-sm1-gpio-intc";
                                reg = <0x0 0xf080 0x0 0x10>;
                                interrupt-controller;
                                #interrupt-cells = <2>;
index a875b21..d353df4 100644 (file)
 #define REG_EDGE_POL_MASK(x)   (BIT(x) | BIT(16 + (x)))
 #define REG_EDGE_POL_EDGE(x)   BIT(x)
 #define REG_EDGE_POL_LOW(x)    BIT(16 + (x))
+#define REG_EDGE_BOTH_EDGE(x)  BIT(8 + (x))
 #define REG_PIN_SEL_SHIFT(x)   (((x) % 4) * 8)
 #define REG_FILTER_SEL_SHIFT(x)        ((x) * 4)
 
 struct meson_gpio_irq_params {
        unsigned int nr_hwirq;
+       u8 support_double_edge;
 };
 
 static const struct meson_gpio_irq_params meson8_params = {
@@ -83,6 +85,11 @@ static const struct meson_gpio_irq_params tl1_params = {
        .nr_hwirq = 102,
 };
 
+static const struct meson_gpio_irq_params sm1_params = {
+       .nr_hwirq = 100,
+       .support_double_edge = 1,
+};
+
 static const struct of_device_id meson_irq_gpio_matches[] = {
        { .compatible = "amlogic,meson8-gpio-intc", .data = &meson8_params },
        { .compatible = "amlogic,meson8b-gpio-intc", .data = &meson8b_params },
@@ -93,11 +100,13 @@ static const struct of_device_id meson_irq_gpio_matches[] = {
        { .compatible = "amlogic,meson-g12a-gpio-intc", .data = &g12a_params },
        { .compatible = "amlogic,meson-txl-gpio-intc", .data = &txl_params },
        { .compatible = "amlogic,meson-tl1-gpio-intc", .data = &tl1_params },
+       { .compatible = "amlogic,meson-sm1-gpio-intc", .data = &sm1_params },
        { }
 };
 
 struct meson_gpio_irq_controller {
        unsigned int nr_hwirq;
+       u8 support_double_edge;
        void __iomem *base;
        u32 channel_irqs[NUM_CHANNEL];
        DECLARE_BITMAP(channel_map, NUM_CHANNEL);
@@ -200,8 +209,16 @@ static int meson_gpio_irq_type_setup(struct meson_gpio_irq_controller *ctl,
         */
        type &= IRQ_TYPE_SENSE_MASK;
 
-       if (type == IRQ_TYPE_EDGE_BOTH)
-               return -EINVAL;
+       if (type == IRQ_TYPE_EDGE_BOTH) {
+               if (!ctl->support_double_edge)
+                       return -EINVAL;
+               val |= REG_EDGE_BOTH_EDGE(idx);
+               spin_lock(&ctl->lock);
+               meson_gpio_irq_update_bits(ctl, REG_EDGE_POL,
+                                  REG_EDGE_BOTH_EDGE(idx), val);
+               spin_unlock(&ctl->lock);
+               return 0;
+       }
 
        if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
                val |= REG_EDGE_POL_EDGE(idx);
@@ -211,6 +228,14 @@ static int meson_gpio_irq_type_setup(struct meson_gpio_irq_controller *ctl,
 
        spin_lock(&ctl->lock);
 
+       /* Double-edge has priority over all others. If a double-edge gpio
+        * changes to another method's, we need to reset the corresponding bit
+        * of double-edge register.
+        */
+       if (ctl->support_double_edge)
+               meson_gpio_irq_update_bits(ctl, REG_EDGE_POL,
+                                          REG_EDGE_BOTH_EDGE(idx), 0);
+
        meson_gpio_irq_update_bits(ctl, REG_EDGE_POL,
                                   REG_EDGE_POL_MASK(idx), val);
 
@@ -369,6 +394,7 @@ static int __init meson_gpio_irq_parse_dt(struct device_node *node,
 
        params = match->data;
        ctl->nr_hwirq = params->nr_hwirq;
+       ctl->support_double_edge = params->support_double_edge;
 
        ret = of_property_read_variable_u32_array(node,
                                                  "amlogic,channel-interrupts",