diff options
author | John Keeping <john@metanate.com> | 2017-03-23 06:59:31 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2017-03-28 05:18:50 -0400 |
commit | 88bb94216f59e10802aaf78c858a4146085faf18 (patch) | |
tree | d096b789e02460b33c2e9f20334ad008a8262fd0 /drivers/pinctrl/pinctrl-rockchip.c | |
parent | 05709c3e88f5f0adb7889facbfd546c998f65d59 (diff) |
pinctrl: rockchip: avoid hardirq-unsafe functions in irq_chip
With real-time preemption, regmap functions cannot be used in the
implementation of irq_chip since they use spinlocks which may sleep.
Move the setting of the mux for IRQs to an irq_bus_sync_unlock handler
where we are allowed to sleep.
Signed-off-by: John Keeping <john@metanate.com>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Tested-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.c | 44 |
1 files changed, 40 insertions, 4 deletions
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 9dd981ddbb17..f141aa0430b1 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c | |||
@@ -143,6 +143,9 @@ struct rockchip_drv { | |||
143 | * @gpio_chip: gpiolib chip | 143 | * @gpio_chip: gpiolib chip |
144 | * @grange: gpio range | 144 | * @grange: gpio range |
145 | * @slock: spinlock for the gpio bank | 145 | * @slock: spinlock for the gpio bank |
146 | * @irq_lock: bus lock for irq chip | ||
147 | * @new_irqs: newly configured irqs which must be muxed as GPIOs in | ||
148 | * irq_bus_sync_unlock() | ||
146 | */ | 149 | */ |
147 | struct rockchip_pin_bank { | 150 | struct rockchip_pin_bank { |
148 | void __iomem *reg_base; | 151 | void __iomem *reg_base; |
@@ -165,6 +168,8 @@ struct rockchip_pin_bank { | |||
165 | struct pinctrl_gpio_range grange; | 168 | struct pinctrl_gpio_range grange; |
166 | raw_spinlock_t slock; | 169 | raw_spinlock_t slock; |
167 | u32 toggle_edge_mode; | 170 | u32 toggle_edge_mode; |
171 | struct mutex irq_lock; | ||
172 | u32 new_irqs; | ||
168 | }; | 173 | }; |
169 | 174 | ||
170 | #define PIN_BANK(id, pins, label) \ | 175 | #define PIN_BANK(id, pins, label) \ |
@@ -2129,11 +2134,12 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) | |||
2129 | int ret; | 2134 | int ret; |
2130 | 2135 | ||
2131 | /* make sure the pin is configured as gpio input */ | 2136 | /* make sure the pin is configured as gpio input */ |
2132 | ret = rockchip_set_mux(bank, d->hwirq, RK_FUNC_GPIO); | 2137 | ret = rockchip_verify_mux(bank, d->hwirq, RK_FUNC_GPIO); |
2133 | if (ret < 0) | 2138 | if (ret < 0) |
2134 | return ret; | 2139 | return ret; |
2135 | 2140 | ||
2136 | clk_enable(bank->clk); | 2141 | bank->new_irqs |= mask; |
2142 | |||
2137 | raw_spin_lock_irqsave(&bank->slock, flags); | 2143 | raw_spin_lock_irqsave(&bank->slock, flags); |
2138 | 2144 | ||
2139 | data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); | 2145 | data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); |
@@ -2191,7 +2197,6 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) | |||
2191 | default: | 2197 | default: |
2192 | irq_gc_unlock(gc); | 2198 | irq_gc_unlock(gc); |
2193 | raw_spin_unlock_irqrestore(&bank->slock, flags); | 2199 | raw_spin_unlock_irqrestore(&bank->slock, flags); |
2194 | clk_disable(bank->clk); | ||
2195 | return -EINVAL; | 2200 | return -EINVAL; |
2196 | } | 2201 | } |
2197 | 2202 | ||
@@ -2200,7 +2205,6 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) | |||
2200 | 2205 | ||
2201 | irq_gc_unlock(gc); | 2206 | irq_gc_unlock(gc); |
2202 | raw_spin_unlock_irqrestore(&bank->slock, flags); | 2207 | raw_spin_unlock_irqrestore(&bank->slock, flags); |
2203 | clk_disable(bank->clk); | ||
2204 | 2208 | ||
2205 | return 0; | 2209 | return 0; |
2206 | } | 2210 | } |
@@ -2244,6 +2248,34 @@ static void rockchip_irq_disable(struct irq_data *d) | |||
2244 | clk_disable(bank->clk); | 2248 | clk_disable(bank->clk); |
2245 | } | 2249 | } |
2246 | 2250 | ||
2251 | static void rockchip_irq_bus_lock(struct irq_data *d) | ||
2252 | { | ||
2253 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
2254 | struct rockchip_pin_bank *bank = gc->private; | ||
2255 | |||
2256 | clk_enable(bank->clk); | ||
2257 | mutex_lock(&bank->irq_lock); | ||
2258 | } | ||
2259 | |||
2260 | static void rockchip_irq_bus_sync_unlock(struct irq_data *d) | ||
2261 | { | ||
2262 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
2263 | struct rockchip_pin_bank *bank = gc->private; | ||
2264 | |||
2265 | while (bank->new_irqs) { | ||
2266 | unsigned int irq = __ffs(bank->new_irqs); | ||
2267 | int ret; | ||
2268 | |||
2269 | ret = rockchip_set_mux(bank, irq, RK_FUNC_GPIO); | ||
2270 | WARN_ON(ret < 0); | ||
2271 | |||
2272 | bank->new_irqs &= ~BIT(irq); | ||
2273 | } | ||
2274 | |||
2275 | mutex_unlock(&bank->irq_lock); | ||
2276 | clk_disable(bank->clk); | ||
2277 | } | ||
2278 | |||
2247 | static int rockchip_interrupts_register(struct platform_device *pdev, | 2279 | static int rockchip_interrupts_register(struct platform_device *pdev, |
2248 | struct rockchip_pinctrl *info) | 2280 | struct rockchip_pinctrl *info) |
2249 | { | 2281 | { |
@@ -2310,6 +2342,9 @@ static int rockchip_interrupts_register(struct platform_device *pdev, | |||
2310 | gc->chip_types[0].chip.irq_suspend = rockchip_irq_suspend; | 2342 | gc->chip_types[0].chip.irq_suspend = rockchip_irq_suspend; |
2311 | gc->chip_types[0].chip.irq_resume = rockchip_irq_resume; | 2343 | gc->chip_types[0].chip.irq_resume = rockchip_irq_resume; |
2312 | gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type; | 2344 | gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type; |
2345 | gc->chip_types[0].chip.irq_bus_lock = rockchip_irq_bus_lock; | ||
2346 | gc->chip_types[0].chip.irq_bus_sync_unlock = | ||
2347 | rockchip_irq_bus_sync_unlock; | ||
2313 | gc->wake_enabled = IRQ_MSK(bank->nr_pins); | 2348 | gc->wake_enabled = IRQ_MSK(bank->nr_pins); |
2314 | 2349 | ||
2315 | irq_set_chained_handler_and_data(bank->irq, | 2350 | irq_set_chained_handler_and_data(bank->irq, |
@@ -2483,6 +2518,7 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data( | |||
2483 | int bank_pins = 0; | 2518 | int bank_pins = 0; |
2484 | 2519 | ||
2485 | raw_spin_lock_init(&bank->slock); | 2520 | raw_spin_lock_init(&bank->slock); |
2521 | mutex_init(&bank->irq_lock); | ||
2486 | bank->drvdata = d; | 2522 | bank->drvdata = d; |
2487 | bank->pin_base = ctrl->nr_pins; | 2523 | bank->pin_base = ctrl->nr_pins; |
2488 | ctrl->nr_pins += bank->nr_pins; | 2524 | ctrl->nr_pins += bank->nr_pins; |