Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pinctrl: qcom: handle intr_target_reg wakeup_present/enable bits

New platforms uses a new set of bits to control the wakeirq
delivery to the PDC block.

The intr_wakeup_present_bit indicates if the GPIO supports
wakeirq and intr_wakeup_enable_bit enables wakeirq delivery
to the PDC block.

While the name seems to imply this only enables wakeup events,
it is required to allow interrupts events to the PDC block.

Enable this bit in the irq resource request/free if:
- gpio is in wakeirq map
- has the intr_wakeup_present_bit
- the intr_wakeup_enable_bit is set

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
Link: https://lore.kernel.org/r/20231106-topic-sm8650-upstream-tlmm-v3-2-0e179c368933@linaro.org
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Neil Armstrong and committed by
Linus Walleij
76b446f5 d92618ca

+47
+42
drivers/pinctrl/qcom/pinctrl-msm.c
··· 1196 1196 { 1197 1197 struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 1198 1198 struct msm_pinctrl *pctrl = gpiochip_get_data(gc); 1199 + const struct msm_pingroup *g = &pctrl->soc->groups[d->hwirq]; 1200 + unsigned long flags; 1199 1201 int ret; 1200 1202 1201 1203 if (!try_module_get(gc->owner)) ··· 1223 1221 */ 1224 1222 irq_set_status_flags(d->irq, IRQ_DISABLE_UNLAZY); 1225 1223 1224 + /* 1225 + * If the wakeup_enable bit is present and marked as available for the 1226 + * requested GPIO, it should be enabled when the GPIO is marked as 1227 + * wake irq in order to allow the interrupt event to be transfered to 1228 + * the PDC HW. 1229 + * While the name implies only the wakeup event, it's also required for 1230 + * the interrupt event. 1231 + */ 1232 + if (test_bit(d->hwirq, pctrl->skip_wake_irqs) && g->intr_wakeup_present_bit) { 1233 + u32 intr_cfg; 1234 + 1235 + raw_spin_lock_irqsave(&pctrl->lock, flags); 1236 + 1237 + intr_cfg = msm_readl_intr_cfg(pctrl, g); 1238 + if (intr_cfg & BIT(g->intr_wakeup_present_bit)) { 1239 + intr_cfg |= BIT(g->intr_wakeup_enable_bit); 1240 + msm_writel_intr_cfg(intr_cfg, pctrl, g); 1241 + } 1242 + 1243 + raw_spin_unlock_irqrestore(&pctrl->lock, flags); 1244 + } 1245 + 1226 1246 return 0; 1227 1247 out: 1228 1248 module_put(gc->owner); ··· 1254 1230 static void msm_gpio_irq_relres(struct irq_data *d) 1255 1231 { 1256 1232 struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 1233 + struct msm_pinctrl *pctrl = gpiochip_get_data(gc); 1234 + const struct msm_pingroup *g = &pctrl->soc->groups[d->hwirq]; 1235 + unsigned long flags; 1236 + 1237 + /* Disable the wakeup_enable bit if it has been set in msm_gpio_irq_reqres() */ 1238 + if (test_bit(d->hwirq, pctrl->skip_wake_irqs) && g->intr_wakeup_present_bit) { 1239 + u32 intr_cfg; 1240 + 1241 + raw_spin_lock_irqsave(&pctrl->lock, flags); 1242 + 1243 + intr_cfg = msm_readl_intr_cfg(pctrl, g); 1244 + if (intr_cfg & BIT(g->intr_wakeup_present_bit)) { 1245 + intr_cfg &= ~BIT(g->intr_wakeup_enable_bit); 1246 + msm_writel_intr_cfg(intr_cfg, pctrl, g); 1247 + } 1248 + 1249 + raw_spin_unlock_irqrestore(&pctrl->lock, flags); 1250 + } 1257 1251 1258 1252 gpiochip_unlock_as_irq(gc, d->hwirq); 1259 1253 module_put(gc->owner);
+5
drivers/pinctrl/qcom/pinctrl-msm.h
··· 58 58 * @intr_enable_bit: Offset in @intr_cfg_reg for enabling the interrupt for this group. 59 59 * @intr_status_bit: Offset in @intr_status_reg for reading and acking the interrupt 60 60 * status. 61 + * @intr_wakeup_present_bit: Offset in @intr_target_reg specifying the GPIO can generate 62 + * wakeup events. 63 + * @intr_wakeup_enable_bit: Offset in @intr_target_reg to enable wakeup events for the GPIO. 61 64 * @intr_target_bit: Offset in @intr_target_reg for configuring the interrupt routing. 62 65 * @intr_target_width: Number of bits used for specifying interrupt routing target. 63 66 * @intr_target_kpss_val: Value in @intr_target_bit for specifying that the interrupt from ··· 103 100 unsigned intr_status_bit:5; 104 101 unsigned intr_ack_high:1; 105 102 103 + unsigned intr_wakeup_present_bit:5; 104 + unsigned intr_wakeup_enable_bit:5; 106 105 unsigned intr_target_bit:5; 107 106 unsigned intr_target_width:5; 108 107 unsigned intr_target_kpss_val:5;