aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/pinctrl-rockchip.c
diff options
context:
space:
mode:
authorHeiko Stübner <heiko@sntech.de>2013-10-15 19:09:08 -0400
committerLinus Walleij <linus.walleij@linaro.org>2013-10-16 09:33:55 -0400
commit5a92750133ffd998e92e4f7ed874fae61d67aeed (patch)
treeffa91f3262c9d952ae27cbee3fc6f02ccab362b5 /drivers/pinctrl/pinctrl-rockchip.c
parent6ca5274d1d1258b0e84bc1a0d67ca160d8658e5a (diff)
pinctrl: rockchip: emulate both edge triggered interrupts
The gpio interrupt controller on Rockchip socs can do edge triggers only for single edges but not both. Nevertheless a lot of gpio users rely on the availability of both-edge triggered interrupts - i.e. gpio-keys. Therefore implement a solution similar to pinctrl-coh901 re-setting the triggering edge depending on the gpio value in the interrupt demuxer. Signed-off-by: Heiko Stuebner <heiko@sntech.de> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/pinctrl-rockchip.c')
-rw-r--r--drivers/pinctrl/pinctrl-rockchip.c61
1 files changed, 54 insertions, 7 deletions
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index f5e53a723152..e939c28cbf1f 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -101,7 +101,7 @@ struct rockchip_pin_bank {
101 struct gpio_chip gpio_chip; 101 struct gpio_chip gpio_chip;
102 struct pinctrl_gpio_range grange; 102 struct pinctrl_gpio_range grange;
103 spinlock_t slock; 103 spinlock_t slock;
104 104 u32 toggle_edge_mode;
105}; 105};
106 106
107#define PIN_BANK(id, pins, label) \ 107#define PIN_BANK(id, pins, label) \
@@ -1078,7 +1078,9 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
1078{ 1078{
1079 struct irq_chip *chip = irq_get_chip(irq); 1079 struct irq_chip *chip = irq_get_chip(irq);
1080 struct rockchip_pin_bank *bank = irq_get_handler_data(irq); 1080 struct rockchip_pin_bank *bank = irq_get_handler_data(irq);
1081 u32 polarity = 0, data = 0;
1081 u32 pend; 1082 u32 pend;
1083 bool edge_changed = false;
1082 1084
1083 dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name); 1085 dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name);
1084 1086
@@ -1086,6 +1088,12 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
1086 1088
1087 pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS); 1089 pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS);
1088 1090
1091 if (bank->toggle_edge_mode) {
1092 polarity = readl_relaxed(bank->reg_base +
1093 GPIO_INT_POLARITY);
1094 data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT);
1095 }
1096
1089 while (pend) { 1097 while (pend) {
1090 unsigned int virq; 1098 unsigned int virq;
1091 1099
@@ -1100,9 +1108,30 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
1100 1108
1101 dev_dbg(bank->drvdata->dev, "handling irq %d\n", irq); 1109 dev_dbg(bank->drvdata->dev, "handling irq %d\n", irq);
1102 1110
1111 /*
1112 * Triggering IRQ on both rising and falling edge
1113 * needs manual intervention.
1114 */
1115 if (bank->toggle_edge_mode & BIT(irq)) {
1116 if (data & BIT(irq))
1117 polarity &= ~BIT(irq);
1118 else
1119 polarity |= BIT(irq);
1120
1121 edge_changed = true;
1122 }
1123
1103 generic_handle_irq(virq); 1124 generic_handle_irq(virq);
1104 } 1125 }
1105 1126
1127 if (bank->toggle_edge_mode && edge_changed) {
1128 /* Interrupt params should only be set with ints disabled */
1129 data = readl_relaxed(bank->reg_base + GPIO_INTEN);
1130 writel_relaxed(0, bank->reg_base + GPIO_INTEN);
1131 writel(polarity, bank->reg_base + GPIO_INT_POLARITY);
1132 writel(data, bank->reg_base + GPIO_INTEN);
1133 }
1134
1106 chained_irq_exit(chip, desc); 1135 chained_irq_exit(chip, desc);
1107} 1136}
1108 1137
@@ -1115,6 +1144,12 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
1115 u32 level; 1144 u32 level;
1116 u32 data; 1145 u32 data;
1117 1146
1147 /* make sure the pin is configured as gpio input */
1148 rockchip_set_mux(bank, d->hwirq, RK_FUNC_GPIO);
1149 data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
1150 data &= ~mask;
1151 writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
1152
1118 if (type & IRQ_TYPE_EDGE_BOTH) 1153 if (type & IRQ_TYPE_EDGE_BOTH)
1119 __irq_set_handler_locked(d->irq, handle_edge_irq); 1154 __irq_set_handler_locked(d->irq, handle_edge_irq);
1120 else 1155 else
@@ -1126,19 +1161,37 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
1126 polarity = readl_relaxed(gc->reg_base + GPIO_INT_POLARITY); 1161 polarity = readl_relaxed(gc->reg_base + GPIO_INT_POLARITY);
1127 1162
1128 switch (type) { 1163 switch (type) {
1164 case IRQ_TYPE_EDGE_BOTH:
1165 bank->toggle_edge_mode |= mask;
1166 level |= mask;
1167
1168 /*
1169 * Determine gpio state. If 1 next interrupt should be falling
1170 * otherwise rising.
1171 */
1172 data = readl(bank->reg_base + GPIO_EXT_PORT);
1173 if (data & mask)
1174 polarity &= ~mask;
1175 else
1176 polarity |= mask;
1177 break;
1129 case IRQ_TYPE_EDGE_RISING: 1178 case IRQ_TYPE_EDGE_RISING:
1179 bank->toggle_edge_mode &= ~mask;
1130 level |= mask; 1180 level |= mask;
1131 polarity |= mask; 1181 polarity |= mask;
1132 break; 1182 break;
1133 case IRQ_TYPE_EDGE_FALLING: 1183 case IRQ_TYPE_EDGE_FALLING:
1184 bank->toggle_edge_mode &= ~mask;
1134 level |= mask; 1185 level |= mask;
1135 polarity &= ~mask; 1186 polarity &= ~mask;
1136 break; 1187 break;
1137 case IRQ_TYPE_LEVEL_HIGH: 1188 case IRQ_TYPE_LEVEL_HIGH:
1189 bank->toggle_edge_mode &= ~mask;
1138 level &= ~mask; 1190 level &= ~mask;
1139 polarity |= mask; 1191 polarity |= mask;
1140 break; 1192 break;
1141 case IRQ_TYPE_LEVEL_LOW: 1193 case IRQ_TYPE_LEVEL_LOW:
1194 bank->toggle_edge_mode &= ~mask;
1142 level &= ~mask; 1195 level &= ~mask;
1143 polarity &= ~mask; 1196 polarity &= ~mask;
1144 break; 1197 break;
@@ -1152,12 +1205,6 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
1152 1205
1153 irq_gc_unlock(gc); 1206 irq_gc_unlock(gc);
1154 1207
1155 /* make sure the pin is configured as gpio input */
1156 rockchip_set_mux(bank, d->hwirq, RK_FUNC_GPIO);
1157 data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
1158 data &= ~mask;
1159 writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
1160
1161 return 0; 1208 return 0;
1162} 1209}
1163 1210