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

Commit 5b273e73 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "dt-bindings: kona-pinctrl: add wakeup interrupt parent for GPIO"

parents da061aae e1e077c6
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -40,6 +40,11 @@ KONA platform.
	Definition: must be 2. Specifying the pin number and flags, as defined
		    in <dt-bindings/gpio/gpio.h>

- wakeup-parent:
	Usage: optional
	Value type: <phandle>
	Definition: A phandle to the wakeup interrupt controller for the SoC.

Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
a general description of GPIO and interrupt bindings.

@@ -183,4 +188,5 @@ Example:
		#gpio-cells = <2>;
		interrupt-controller;
		#interrupt-cells = <2>;
		wakeup-parent = <&pdc>;
	};
+69 −3
Original line number Diff line number Diff line
@@ -13,12 +13,13 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/soc/qcom/irq.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/types.h>

#define PDC_MAX_IRQS		138
#define PDC_MAX_GPIO_IRQS	256

#define CLEAR_INTR(reg, intr)	(reg & ~(1 << intr))
#define ENABLE_INTR(reg, intr)	(reg | (1 << intr))
@@ -169,7 +170,6 @@ static irq_hw_number_t get_parent_hwirq(int pin)
			return (region->parent_base + pin - region->pin_base);
	}

	WARN_ON(1);
	return ~0UL;
}

@@ -232,6 +232,60 @@ static const struct irq_domain_ops qcom_pdc_ops = {
	.free		= irq_domain_free_irqs_common,
};

static int qcom_pdc_gpio_alloc(struct irq_domain *domain, unsigned int virq,
			       unsigned int nr_irqs, void *data)
{
	struct qcom_irq_fwspec *qcom_fwspec = data;
	struct irq_fwspec *fwspec = &qcom_fwspec->fwspec;
	struct irq_fwspec parent_fwspec;
	irq_hw_number_t hwirq, parent_hwirq;
	unsigned int type;
	int ret;

	ret = qcom_pdc_translate(domain, fwspec, &hwirq, &type);
	if (ret)
		return -EINVAL;

	parent_hwirq = get_parent_hwirq(hwirq);
	if (parent_hwirq == ~0UL)
		return -EINVAL;

	ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
					    &qcom_pdc_gic_chip, NULL);
	if (ret)
		return ret;

	qcom_fwspec->mask = true;

	if (type & IRQ_TYPE_EDGE_BOTH)
		type = IRQ_TYPE_EDGE_RISING;

	if (type & IRQ_TYPE_LEVEL_MASK)
		type = IRQ_TYPE_LEVEL_HIGH;

	parent_fwspec.fwnode      = domain->parent->fwnode;
	parent_fwspec.param_count = 3;
	parent_fwspec.param[0]    = 0;
	parent_fwspec.param[1]    = parent_hwirq;
	parent_fwspec.param[2]    = type;

	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
					    &parent_fwspec);
}

static int qcom_pdc_gpio_domain_select(struct irq_domain *d,
				       struct irq_fwspec *fwspec,
				       enum irq_domain_bus_token bus_token)
{
	return (bus_token == DOMAIN_BUS_WAKEUP);
}

static const struct irq_domain_ops qcom_pdc_gpio_ops = {
	.select		= qcom_pdc_gpio_domain_select,
	.alloc		= qcom_pdc_gpio_alloc,
	.free		= irq_domain_free_irqs_common,
};

static int pdc_setup_pin_mapping(struct device_node *np)
{
	int ret, n;
@@ -270,7 +324,7 @@ static int pdc_setup_pin_mapping(struct device_node *np)

static int qcom_pdc_init(struct device_node *node, struct device_node *parent)
{
	struct irq_domain *parent_domain, *pdc_domain;
	struct irq_domain *parent_domain, *pdc_domain, *pdc_gpio_domain;
	int ret;

	pdc_base = of_iomap(node, 0);
@@ -301,6 +355,18 @@ static int qcom_pdc_init(struct device_node *node, struct device_node *parent)
		goto fail;
	}

	pdc_gpio_domain = irq_domain_create_hierarchy(parent_domain, 0,
						      PDC_MAX_GPIO_IRQS,
						      of_fwnode_handle(node),
						      &qcom_pdc_gpio_ops, NULL);
	if (!pdc_gpio_domain) {
		pr_err("GIC domain add failed for GPIO domain\n");
		ret = -ENOMEM;
		goto fail;
	}

	irq_domain_update_bus_token(pdc_gpio_domain, DOMAIN_BUS_WAKEUP);

	return 0;

fail:
+26 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2019, The Linux Foundation. All rights reserved.
 */

#ifndef __QCOM_IRQ_H
#define __QCOM_IRQ_H

#include <linux/irqdomain.h>

/**
 * struct qcom_irq_fwspec - qcom specific irq fwspec wrapper
 * @fwspec: irq fwspec
 * @mask: if true, keep the irq masked in the gpio controller
 *
 * Use this structure to communicate between the parent irq chip, MPM or PDC,
 * to the gpio chip, TLMM, about the gpio being allocated in the parent
 * and if the gpio chip should keep the line masked because the parent irq
 * chip is handling everything about the irq line.
 */
struct qcom_irq_fwspec {
	struct irq_fwspec fwspec;
	bool mask;
};

#endif