Loading drivers/pinctrl/qcom/pinctrl-msm.c +77 −5 Original line number Diff line number Diff line Loading @@ -975,6 +975,59 @@ static void gpio_muxed_to_pdc(struct irq_domain *pdc_domain, struct irq_data *d) } } static bool is_gpio_tlmm_dc(struct irq_data *d, u32 type) { const struct msm_pingroup *g; unsigned long flags; struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct msm_pinctrl *pctrl; bool ret = false; unsigned int polarity = 0, offset, val; int i; if (!gc) return false; pctrl = gpiochip_get_data(gc); for (i = 0; i < pctrl->soc->n_dir_conns; i++) { struct msm_dir_conn *dir_conn = (struct msm_dir_conn *) &pctrl->soc->dir_conn[i]; if (dir_conn->gpio == d->hwirq && dir_conn->tlmm_dc) { ret = true; offset = pctrl->soc->dir_conn_irq_base - dir_conn->hwirq; break; } } if (!ret) return ret; if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)) return ret; /* * Since the default polarity is set to 0, change it to 1 for * Rising edge and active high interrupt type such that the line * is not inverted. */ polarity = 1; spin_lock_irqsave(&pctrl->lock, flags); g = &pctrl->soc->groups[d->hwirq]; val = readl_relaxed(pctrl->regs + g->dir_conn_reg + (offset * 4)); val |= polarity << 8; writel_relaxed(val, pctrl->regs + g->dir_conn_reg + (offset * 4)); spin_unlock_irqrestore(&pctrl->lock, flags); return ret; } static bool is_gpio_dual_edge(struct irq_data *d, irq_hw_number_t *dir_conn_irq) { struct irq_desc *desc = irq_data_to_desc(d); Loading Loading @@ -1283,12 +1336,12 @@ static int msm_dirconn_irq_set_type(struct irq_data *d, unsigned int type) if (!parent_data) return 0; if (type == IRQ_TYPE_EDGE_BOTH) { if (type == IRQ_TYPE_EDGE_BOTH) add_dirconn_tlmm(d, irq); } else { if (is_gpio_dual_edge(d, &irq)) else if (is_gpio_dual_edge(d, &irq)) remove_dirconn_tlmm(d, irq); } else if (is_gpio_tlmm_dc(d, type)) type = IRQ_TYPE_EDGE_RISING; if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) irq_set_handler_locked(d, handle_level_irq); Loading Loading @@ -1366,9 +1419,28 @@ static void msm_gpio_setup_dir_connects(struct msm_pinctrl *pctrl) for (i = 0; i < pctrl->soc->n_dir_conns; i++) { const struct msm_dir_conn *dirconn = &pctrl->soc->dir_conn[i]; struct irq_data *d; request_dc_interrupt(pctrl->chip.irqdomain, pdc_domain, dirconn->hwirq, dirconn->gpio); if (!dirconn->gpio) continue; if (!dirconn->tlmm_dc) continue; /* * If the gpio is routed through TLMM direct connect interrupts, * program the TLMM registers for this setup. */ d = irq_get_irq_data(irq_find_mapping(pctrl->chip.irqdomain, dirconn->gpio)); if (!d) continue; msm_dirconn_cfg_reg(d, pctrl->soc->dir_conn_irq_base - (u32)dirconn->hwirq); } for (i = 0; i < pctrl->soc->n_pdc_mux_out; i++) { Loading drivers/pinctrl/qcom/pinctrl-msm.h +2 −0 Original line number Diff line number Diff line Loading @@ -128,10 +128,12 @@ struct msm_pdc_mux_output { * struct msm_dir_conn - Direct GPIO connect configuration * @gpio: GPIO pin number * @hwirq: The GIC interrupt that the pin is connected to * @tlmm_dc: indicates if the GPIO is routed to GIC directly */ struct msm_dir_conn { unsigned int gpio; irq_hw_number_t hwirq; bool tlmm_dc; }; /** Loading Loading
drivers/pinctrl/qcom/pinctrl-msm.c +77 −5 Original line number Diff line number Diff line Loading @@ -975,6 +975,59 @@ static void gpio_muxed_to_pdc(struct irq_domain *pdc_domain, struct irq_data *d) } } static bool is_gpio_tlmm_dc(struct irq_data *d, u32 type) { const struct msm_pingroup *g; unsigned long flags; struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct msm_pinctrl *pctrl; bool ret = false; unsigned int polarity = 0, offset, val; int i; if (!gc) return false; pctrl = gpiochip_get_data(gc); for (i = 0; i < pctrl->soc->n_dir_conns; i++) { struct msm_dir_conn *dir_conn = (struct msm_dir_conn *) &pctrl->soc->dir_conn[i]; if (dir_conn->gpio == d->hwirq && dir_conn->tlmm_dc) { ret = true; offset = pctrl->soc->dir_conn_irq_base - dir_conn->hwirq; break; } } if (!ret) return ret; if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)) return ret; /* * Since the default polarity is set to 0, change it to 1 for * Rising edge and active high interrupt type such that the line * is not inverted. */ polarity = 1; spin_lock_irqsave(&pctrl->lock, flags); g = &pctrl->soc->groups[d->hwirq]; val = readl_relaxed(pctrl->regs + g->dir_conn_reg + (offset * 4)); val |= polarity << 8; writel_relaxed(val, pctrl->regs + g->dir_conn_reg + (offset * 4)); spin_unlock_irqrestore(&pctrl->lock, flags); return ret; } static bool is_gpio_dual_edge(struct irq_data *d, irq_hw_number_t *dir_conn_irq) { struct irq_desc *desc = irq_data_to_desc(d); Loading Loading @@ -1283,12 +1336,12 @@ static int msm_dirconn_irq_set_type(struct irq_data *d, unsigned int type) if (!parent_data) return 0; if (type == IRQ_TYPE_EDGE_BOTH) { if (type == IRQ_TYPE_EDGE_BOTH) add_dirconn_tlmm(d, irq); } else { if (is_gpio_dual_edge(d, &irq)) else if (is_gpio_dual_edge(d, &irq)) remove_dirconn_tlmm(d, irq); } else if (is_gpio_tlmm_dc(d, type)) type = IRQ_TYPE_EDGE_RISING; if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) irq_set_handler_locked(d, handle_level_irq); Loading Loading @@ -1366,9 +1419,28 @@ static void msm_gpio_setup_dir_connects(struct msm_pinctrl *pctrl) for (i = 0; i < pctrl->soc->n_dir_conns; i++) { const struct msm_dir_conn *dirconn = &pctrl->soc->dir_conn[i]; struct irq_data *d; request_dc_interrupt(pctrl->chip.irqdomain, pdc_domain, dirconn->hwirq, dirconn->gpio); if (!dirconn->gpio) continue; if (!dirconn->tlmm_dc) continue; /* * If the gpio is routed through TLMM direct connect interrupts, * program the TLMM registers for this setup. */ d = irq_get_irq_data(irq_find_mapping(pctrl->chip.irqdomain, dirconn->gpio)); if (!d) continue; msm_dirconn_cfg_reg(d, pctrl->soc->dir_conn_irq_base - (u32)dirconn->hwirq); } for (i = 0; i < pctrl->soc->n_pdc_mux_out; i++) { Loading
drivers/pinctrl/qcom/pinctrl-msm.h +2 −0 Original line number Diff line number Diff line Loading @@ -128,10 +128,12 @@ struct msm_pdc_mux_output { * struct msm_dir_conn - Direct GPIO connect configuration * @gpio: GPIO pin number * @hwirq: The GIC interrupt that the pin is connected to * @tlmm_dc: indicates if the GPIO is routed to GIC directly */ struct msm_dir_conn { unsigned int gpio; irq_hw_number_t hwirq; bool tlmm_dc; }; /** Loading