Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ee483a9e authored by Archana Sathyakumar's avatar Archana Sathyakumar Committed by Maulik Shah
Browse files

pinctrl: qcom: Support using tlmm direct connect GPIOs



To make GPIO interrupt handling faster, GPIOs are routed to TLMM and to
the GIC directly. These GPIOs are termed as direct connect GPIOs. Update
the direct connect data structure to use TLMM direct connect GPIOs.

Change-Id: If74e26c893a85d2a5984db2a634055c7fa432322
Signed-off-by: default avatarArchana Sathyakumar <asathyak@codeaurora.org>
Signed-off-by: default avatarLina Iyer <ilina@codeaurora.org>
parent 10fc5a2d
Loading
Loading
Loading
Loading
+80 −5
Original line number Diff line number Diff line
@@ -1072,6 +1072,62 @@ 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;
	void __iomem *base;

	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;

	raw_spin_lock_irqsave(&pctrl->lock, flags);

	g = &pctrl->soc->groups[d->hwirq];
	base = reassign_pctrl_reg(pctrl->soc, d->hwirq);

	val = readl_relaxed(base + g->dir_conn_reg + (offset * 4));
	val |= polarity << 8;

	writel_relaxed(val, base + g->dir_conn_reg + (offset * 4));

	raw_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);
@@ -1379,12 +1435,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);
@@ -1464,9 +1520,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++) {
+2 −0
Original line number Diff line number Diff line
@@ -133,10 +133,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;
};

/**