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

Commit 426f127a authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drivers: irqchip: pdc: add IPC logging support"

parents bd35862f db09974c
Loading
Loading
Loading
Loading
+96 −4
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@

#include <linux/err.h>
#include <linux/init.h>
#include <linux/ipc_logging.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/irqdomain.h>
@@ -18,6 +19,8 @@
#include <linux/slab.h>
#include <linux/types.h>

#define PDC_IPC_LOG_SZ		2

#define PDC_MAX_IRQS		138
#define PDC_MAX_GPIO_IRQS	256

@@ -36,9 +39,11 @@ struct pdc_pin_region {
};

static DEFINE_RAW_SPINLOCK(pdc_lock);
static void __iomem *pdc_base;
static void __iomem *pdc_base, *pdc_cfg_base;
static struct pdc_pin_region *pdc_region;
static int pdc_region_cnt;
static resource_size_t pdc_cfg_size;
static void *pdc_ipc_log;

static void pdc_reg_write(int reg, u32 i, u32 val)
{
@@ -63,15 +68,34 @@ static void pdc_enable_intr(struct irq_data *d, bool on)
	enable = pdc_reg_read(IRQ_ENABLE_BANK, index);
	enable = on ? ENABLE_INTR(enable, mask) : CLEAR_INTR(enable, mask);
	pdc_reg_write(IRQ_ENABLE_BANK, index, enable);
	ipc_log_string(pdc_ipc_log, "PIN=%d enable=%d", d->hwirq, on);
	raw_spin_unlock(&pdc_lock);
}

static void qcom_pdc_gic_mask(struct irq_data *d)
static void qcom_pdc_gic_disable(struct irq_data *d)
{
	if (d->hwirq == GPIO_NO_WAKE_IRQ)
		return;

	pdc_enable_intr(d, false);
	irq_chip_disable_parent(d);
}

static void qcom_pdc_gic_enable(struct irq_data *d)
{
	if (d->hwirq == GPIO_NO_WAKE_IRQ)
		return;

	pdc_enable_intr(d, true);
	irq_chip_enable_parent(d);
}

static void qcom_pdc_gic_mask(struct irq_data *d)
{
	if (d->hwirq == GPIO_NO_WAKE_IRQ)
		return;

	ipc_log_string(pdc_ipc_log, "PIN=%d mask", d->hwirq);
	irq_chip_mask_parent(d);
}

@@ -80,10 +104,37 @@ static void qcom_pdc_gic_unmask(struct irq_data *d)
	if (d->hwirq == GPIO_NO_WAKE_IRQ)
		return;

	pdc_enable_intr(d, true);
	ipc_log_string(pdc_ipc_log, "PIN=%d unmask", d->hwirq);
	irq_chip_unmask_parent(d);
}

static int spi_configure_type(irq_hw_number_t hwirq, unsigned int type)
{
	int spi = hwirq - 32;
	unsigned int pin = spi / 32;
	unsigned int mask = BIT(spi % 32);
	void __iomem *cfg_reg = pdc_cfg_base + pin * 4;
	unsigned int val;
	unsigned long flags;

	if (pin * 4 > pdc_cfg_size)
		return -EFAULT;

	raw_spin_lock_irqsave(&pdc_lock, flags);
	val = readl_relaxed(cfg_reg);
	rmb(); /* Ensure the read is complete before modifying */
	val &= ~mask;
	if (type & IRQ_TYPE_LEVEL_MASK)
		val |= mask;
	writel_relaxed(val, cfg_reg);
	ipc_log_string(pdc_ipc_log,
		       "SPI config: GIC-SPI=%d (reg=%d,bit=%d) val=%d",
		       spi, pin, spi % 32, type & IRQ_TYPE_LEVEL_MASK);
	raw_spin_unlock_irqrestore(&pdc_lock, flags);

	return 0;
}

/*
 * GIC does not handle falling edge or active low. To allow falling edge and
 * active low interrupts to be handled at GIC, PDC has an inverter that inverts
@@ -121,7 +172,9 @@ enum pdc_irq_config_bits {
static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
{
	int pin_out = d->hwirq;
	int parent_hwirq = d->parent_data->hwirq;
	enum pdc_irq_config_bits pdc_type;
	int ret;

	if (pin_out == GPIO_NO_WAKE_IRQ)
		return 0;
@@ -151,6 +204,15 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type)
	}

	pdc_reg_write(IRQ_i_CFG, pin_out, pdc_type);
	ipc_log_string(pdc_ipc_log, "Set type: PIN=%d pdc_type=%d gic_type=%d",
		       pin_out, pdc_type, type);

	/* Additionally, configure (only) the GPIO in the f/w */
	if (d->domain->host_data) {
		ret = spi_configure_type(parent_hwirq, type);
		if (ret)
			return ret;
	}

	return irq_chip_set_type_parent(d, type);
}
@@ -160,6 +222,8 @@ static struct irq_chip qcom_pdc_gic_chip = {
	.irq_eoi		= irq_chip_eoi_parent,
	.irq_mask		= qcom_pdc_gic_mask,
	.irq_unmask		= qcom_pdc_gic_unmask,
	.irq_disable		= qcom_pdc_gic_disable,
	.irq_enable		= qcom_pdc_gic_enable,
	.irq_retrigger		= irq_chip_retrigger_hierarchy,
	.irq_set_type		= qcom_pdc_gic_set_type,
	.flags			= IRQCHIP_MASK_ON_SUSPEND |
@@ -233,6 +297,8 @@ static int qcom_pdc_alloc(struct irq_domain *domain, unsigned int virq,
	parent_fwspec.param[1]    = parent_hwirq;
	parent_fwspec.param[2]    = type;

	ipc_log_string(pdc_ipc_log, "Alloc: PIN=%d GIC-SPI=%d",
		       hwirq, parent_hwirq);
	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
					    &parent_fwspec);
}
@@ -271,6 +337,13 @@ static int qcom_pdc_gpio_alloc(struct irq_domain *domain, unsigned int virq,

	qcom_fwspec->mask = true;

	/* Additionally, configure GPIO PDC in the f/w */
	if (domain->host_data) {
		ret = spi_configure_type(parent_hwirq, type);
		if (ret)
			return ret;
	}

	if (type & IRQ_TYPE_EDGE_BOTH)
		type = IRQ_TYPE_EDGE_RISING;

@@ -283,6 +356,8 @@ static int qcom_pdc_gpio_alloc(struct irq_domain *domain, unsigned int virq,
	parent_fwspec.param[1]    = parent_hwirq;
	parent_fwspec.param[2]    = type;

	ipc_log_string(pdc_ipc_log, "GPIO alloc: PIN=%d GIC-SPI=%d",
		       hwirq, parent_hwirq);
	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
					    &parent_fwspec);
}
@@ -336,9 +411,19 @@ static int pdc_setup_pin_mapping(struct device_node *np)
	return 0;
}

static int __init qcom_pdc_early_init(void)
{
	pdc_ipc_log = ipc_log_context_create(PDC_IPC_LOG_SZ, "pdc", 0);

	return 0;

}
core_initcall(qcom_pdc_early_init);

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

	pdc_base = of_iomap(node, 0);
@@ -369,10 +454,17 @@ static int qcom_pdc_init(struct device_node *node, struct device_node *parent)
		goto fail;
	}

	ret = of_address_to_resource(node, 1, &res);
	if (!ret) {
		pdc_cfg_size = resource_size(&res);
		pdc_cfg_base = ioremap(res.start, pdc_cfg_size);
	}

	pdc_gpio_domain = irq_domain_create_hierarchy(parent_domain, 0,
						      PDC_MAX_GPIO_IRQS,
						      of_fwnode_handle(node),
						      &qcom_pdc_gpio_ops, NULL);
						      &qcom_pdc_gpio_ops,
						      pdc_cfg_base);
	if (!pdc_gpio_domain) {
		pr_err("GIC domain add failed for GPIO domain\n");
		ret = -ENOMEM;
+60 −16
Original line number Diff line number Diff line
@@ -633,7 +633,7 @@ static void msm_gpio_update_dual_edge_pos(struct msm_pinctrl *pctrl,
		val, val2);
}

static void msm_gpio_irq_mask(struct irq_data *d)
static void _msm_gpio_irq_mask(struct irq_data *d)
{
	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
	struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
@@ -643,13 +643,6 @@ static void msm_gpio_irq_mask(struct irq_data *d)

	g = &pctrl->soc->groups[d->hwirq];

	if (d->parent_data)
		irq_chip_mask_parent(d);

	/* Monitored by parent wakeup controller? */
	if (test_bit(d->hwirq, pctrl->wakeup_masked_irqs))
		return;

	raw_spin_lock_irqsave(&pctrl->lock, flags);

	val = readl(pctrl->regs + g->intr_cfg_reg);
@@ -684,7 +677,7 @@ static void msm_gpio_irq_mask(struct irq_data *d)
	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
}

static void msm_gpio_irq_unmask(struct irq_data *d)
static void _msm_gpio_irq_unmask(struct irq_data *d)
{
	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
	struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
@@ -694,13 +687,6 @@ static void msm_gpio_irq_unmask(struct irq_data *d)

	g = &pctrl->soc->groups[d->hwirq];

	if (d->parent_data)
		irq_chip_unmask_parent(d);

	/* Monitored by parent wakeup controller? Keep masked */
	if (test_bit(d->hwirq, pctrl->wakeup_masked_irqs))
		return;

	raw_spin_lock_irqsave(&pctrl->lock, flags);

	val = readl(pctrl->regs + g->intr_cfg_reg);
@@ -713,6 +699,62 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
}

static void msm_gpio_irq_mask(struct irq_data *d)
{
	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
	struct msm_pinctrl *pctrl = gpiochip_get_data(gc);

	if (d->parent_data)
		irq_chip_mask_parent(d);

	if (test_bit(d->hwirq, pctrl->wakeup_masked_irqs))
		return;

	_msm_gpio_irq_mask(d);
}

static void msm_gpio_irq_unmask(struct irq_data *d)
{
	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
	struct msm_pinctrl *pctrl = gpiochip_get_data(gc);

	if (d->parent_data)
		irq_chip_unmask_parent(d);

	if (test_bit(d->hwirq, pctrl->wakeup_masked_irqs))
		return;

	_msm_gpio_irq_unmask(d);
}

static void msm_gpio_irq_disable(struct irq_data *d)
{
	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
	struct msm_pinctrl *pctrl = gpiochip_get_data(gc);

	if (d->parent_data)
		irq_chip_disable_parent(d);

	if (test_bit(d->hwirq, pctrl->wakeup_masked_irqs))
		return;

	_msm_gpio_irq_mask(d);
}

static void msm_gpio_irq_enable(struct irq_data *d)
{
	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
	struct msm_pinctrl *pctrl = gpiochip_get_data(gc);

	if (d->parent_data)
		irq_chip_enable_parent(d);

	if (test_bit(d->hwirq, pctrl->wakeup_masked_irqs))
		return;

	_msm_gpio_irq_unmask(d);
}

static void msm_gpio_irq_ack(struct irq_data *d)
{
	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
@@ -1034,6 +1076,8 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)

	pctrl->irq_chip.name = "msmgpio";
	pctrl->irq_chip.irq_eoi	= irq_chip_eoi_parent;
	pctrl->irq_chip.irq_enable = msm_gpio_irq_enable;
	pctrl->irq_chip.irq_disable = msm_gpio_irq_disable;
	pctrl->irq_chip.irq_mask = msm_gpio_irq_mask;
	pctrl->irq_chip.irq_unmask = msm_gpio_irq_unmask;
	pctrl->irq_chip.irq_ack = msm_gpio_irq_ack;