diff options
-rw-r--r-- | drivers/pinctrl/pinctrl-rockchip.c | 61 |
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 | ||