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

Commit fa00cb26 authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

Merge tag 'irqchip-core-4.6' of git://git.infradead.org/users/jcooper/linux into irq/core

Pull irqchip core changes for v4.6 from Jason Cooper:

- mvebu (armada-370-xp)
   - MSI support
   - Deconflict with mvebu's arm64 code

- ts4800
   - Restrict when ts4800 driver can be built
   - Make ts4800_ic_ops static const

- bcm2836: Drop superfluous memory barrier
parents f944b5a7 e4e1c0ea
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -3,7 +3,6 @@ menuconfig ARCH_MVEBU
	depends on ARCH_MULTI_V7 || ARCH_MULTI_V5
	select ARCH_SUPPORTS_BIG_ENDIAN
	select CLKSRC_MMIO
	select GENERIC_IRQ_CHIP
	select PINCTRL
	select PLAT_ORION
	select SOC_BUS
@@ -29,6 +28,7 @@ config MACH_ARMADA_370
	bool "Marvell Armada 370 boards"
	depends on ARCH_MULTI_V7
	select ARMADA_370_CLK
	select ARMADA_370_XP_IRQ
	select CPU_PJ4B
	select MACH_MVEBU_V7
	select PINCTRL_ARMADA_370
@@ -39,6 +39,7 @@ config MACH_ARMADA_370
config MACH_ARMADA_375
	bool "Marvell Armada 375 boards"
	depends on ARCH_MULTI_V7
	select ARMADA_370_XP_IRQ
	select ARM_ERRATA_720789
	select ARM_ERRATA_753970
	select ARM_GIC
@@ -58,6 +59,7 @@ config MACH_ARMADA_38X
	select ARM_ERRATA_720789
	select ARM_ERRATA_753970
	select ARM_GIC
	select ARMADA_370_XP_IRQ
	select ARMADA_38X_CLK
	select HAVE_ARM_SCU
	select HAVE_ARM_TWD if SMP
@@ -72,6 +74,7 @@ config MACH_ARMADA_39X
	bool "Marvell Armada 39x boards"
	depends on ARCH_MULTI_V7
	select ARM_GIC
	select ARMADA_370_XP_IRQ
	select ARMADA_39X_CLK
	select CACHE_L2X0
	select HAVE_ARM_SCU
@@ -86,6 +89,7 @@ config MACH_ARMADA_39X
config MACH_ARMADA_XP
	bool "Marvell Armada XP boards"
	depends on ARCH_MULTI_V7
	select ARMADA_370_XP_IRQ
	select ARMADA_XP_CLK
	select CPU_PJ4B
	select MACH_MVEBU_V7
+6 −0
Original line number Diff line number Diff line
@@ -60,6 +60,11 @@ config ARM_VIC_NR
	  The maximum number of VICs available in the system, for
	  power management.

config ARMADA_370_XP_IRQ
	bool
	select GENERIC_IRQ_CHIP
	select PCI_MSI_IRQ_DOMAIN if PCI_MSI

config ATMEL_AIC_IRQ
	bool
	select GENERIC_IRQ_CHIP
@@ -165,6 +170,7 @@ config TS4800_IRQ
	tristate "TS-4800 IRQ controller"
	select IRQ_DOMAIN
	depends on HAS_IOMEM
	depends on SOC_IMX51 || COMPILE_TEST
	help
	  Support for the TS-4800 FPGA IRQ controller

+1 −1
Original line number Diff line number Diff line
@@ -5,7 +5,6 @@ obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o
obj-$(CONFIG_ARCH_EXYNOS)		+= exynos-combiner.o
obj-$(CONFIG_ARCH_HIP04)		+= irq-hip04.o
obj-$(CONFIG_ARCH_MMP)			+= irq-mmp.o
obj-$(CONFIG_ARCH_MVEBU)		+= irq-armada-370-xp.o
obj-$(CONFIG_IRQ_MXS)			+= irq-mxs.o
obj-$(CONFIG_ARCH_TEGRA)		+= irq-tegra.o
obj-$(CONFIG_ARCH_S3C24XX)		+= irq-s3c24xx.o
@@ -28,6 +27,7 @@ obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v3-its-pci-msi.o irq-g
obj-$(CONFIG_HISILICON_IRQ_MBIGEN)	+= irq-mbigen.o
obj-$(CONFIG_ARM_NVIC)			+= irq-nvic.o
obj-$(CONFIG_ARM_VIC)			+= irq-vic.o
obj-$(CONFIG_ARMADA_370_XP_IRQ)		+= irq-armada-370-xp.o
obj-$(CONFIG_ATMEL_AIC_IRQ)		+= irq-atmel-aic-common.o irq-atmel-aic.o
obj-$(CONFIG_ATMEL_AIC5_IRQ)	+= irq-atmel-aic-common.o irq-atmel-aic5.o
obj-$(CONFIG_I8259)			+= irq-i8259.o
+66 −90
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ static u32 doorbell_mask_reg;
static int parent_irq;
#ifdef CONFIG_PCI_MSI
static struct irq_domain *armada_370_xp_msi_domain;
static struct irq_domain *armada_370_xp_msi_inner_domain;
static DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR);
static DEFINE_MUTEX(msi_used_lock);
static phys_addr_t msi_doorbell_addr;
@@ -115,127 +116,102 @@ static void armada_370_xp_irq_unmask(struct irq_data *d)

#ifdef CONFIG_PCI_MSI

static int armada_370_xp_alloc_msi(void)
{
	int hwirq;

	mutex_lock(&msi_used_lock);
	hwirq = find_first_zero_bit(&msi_used, PCI_MSI_DOORBELL_NR);
	if (hwirq >= PCI_MSI_DOORBELL_NR)
		hwirq = -ENOSPC;
	else
		set_bit(hwirq, msi_used);
	mutex_unlock(&msi_used_lock);
static struct irq_chip armada_370_xp_msi_irq_chip = {
	.name = "MPIC MSI",
	.irq_mask = pci_msi_mask_irq,
	.irq_unmask = pci_msi_unmask_irq,
};

	return hwirq;
}
static struct msi_domain_info armada_370_xp_msi_domain_info = {
	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
		   MSI_FLAG_MULTI_PCI_MSI),
	.chip	= &armada_370_xp_msi_irq_chip,
};

static void armada_370_xp_free_msi(int hwirq)
static void armada_370_xp_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
{
	mutex_lock(&msi_used_lock);
	if (!test_bit(hwirq, msi_used))
		pr_err("trying to free unused MSI#%d\n", hwirq);
	else
		clear_bit(hwirq, msi_used);
	mutex_unlock(&msi_used_lock);
	msg->address_lo = lower_32_bits(msi_doorbell_addr);
	msg->address_hi = upper_32_bits(msi_doorbell_addr);
	msg->data = 0xf00 | (data->hwirq + PCI_MSI_DOORBELL_START);
}

static int armada_370_xp_setup_msi_irq(struct msi_controller *chip,
				       struct pci_dev *pdev,
				       struct msi_desc *desc)
static int armada_370_xp_msi_set_affinity(struct irq_data *irq_data,
					  const struct cpumask *mask, bool force)
{
	struct msi_msg msg;
	int virq, hwirq;

	/* We support MSI, but not MSI-X */
	if (desc->msi_attrib.is_msix)
		return -EINVAL;

	hwirq = armada_370_xp_alloc_msi();
	if (hwirq < 0)
		return hwirq;

	virq = irq_create_mapping(armada_370_xp_msi_domain, hwirq);
	if (!virq) {
		armada_370_xp_free_msi(hwirq);
	 return -EINVAL;
}

	irq_set_msi_desc(virq, desc);
static struct irq_chip armada_370_xp_msi_bottom_irq_chip = {
	.name			= "MPIC MSI",
	.irq_compose_msi_msg	= armada_370_xp_compose_msi_msg,
	.irq_set_affinity	= armada_370_xp_msi_set_affinity,
};

static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq,
				   unsigned int nr_irqs, void *args)
{
	int hwirq, i;

	msg.address_lo = msi_doorbell_addr;
	msg.address_hi = 0;
	msg.data = 0xf00 | (hwirq + 16);
	mutex_lock(&msi_used_lock);

	pci_write_msi_msg(virq, &msg);
	return 0;
	hwirq = bitmap_find_next_zero_area(msi_used, PCI_MSI_DOORBELL_NR,
					   0, nr_irqs, 0);
	if (hwirq >= PCI_MSI_DOORBELL_NR) {
		mutex_unlock(&msi_used_lock);
		return -ENOSPC;
	}

static void armada_370_xp_teardown_msi_irq(struct msi_controller *chip,
					   unsigned int irq)
{
	struct irq_data *d = irq_get_irq_data(irq);
	unsigned long hwirq = d->hwirq;
	bitmap_set(msi_used, hwirq, nr_irqs);
	mutex_unlock(&msi_used_lock);

	irq_dispose_mapping(irq);
	armada_370_xp_free_msi(hwirq);
	for (i = 0; i < nr_irqs; i++) {
		irq_domain_set_info(domain, virq + i, hwirq + i,
				    &armada_370_xp_msi_bottom_irq_chip,
				    domain->host_data, handle_simple_irq,
				    NULL, NULL);
	}

static struct irq_chip armada_370_xp_msi_irq_chip = {
	.name = "armada_370_xp_msi_irq",
	.irq_enable = pci_msi_unmask_irq,
	.irq_disable = pci_msi_mask_irq,
	.irq_mask = pci_msi_mask_irq,
	.irq_unmask = pci_msi_unmask_irq,
};
	return hwirq;
}

static int armada_370_xp_msi_map(struct irq_domain *domain, unsigned int virq,
				 irq_hw_number_t hw)
static void armada_370_xp_msi_free(struct irq_domain *domain,
				   unsigned int virq, unsigned int nr_irqs)
{
	irq_set_chip_and_handler(virq, &armada_370_xp_msi_irq_chip,
				 handle_simple_irq);
	struct irq_data *d = irq_domain_get_irq_data(domain, virq);

	return 0;
	mutex_lock(&msi_used_lock);
	bitmap_clear(msi_used, d->hwirq, nr_irqs);
	mutex_unlock(&msi_used_lock);
}

static const struct irq_domain_ops armada_370_xp_msi_irq_ops = {
	.map = armada_370_xp_msi_map,
static const struct irq_domain_ops armada_370_xp_msi_domain_ops = {
	.alloc	= armada_370_xp_msi_alloc,
	.free	= armada_370_xp_msi_free,
};

static int armada_370_xp_msi_init(struct device_node *node,
				  phys_addr_t main_int_phys_base)
{
	struct msi_controller *msi_chip;
	u32 reg;
	int ret;

	msi_doorbell_addr = main_int_phys_base +
		ARMADA_370_XP_SW_TRIG_INT_OFFS;

	msi_chip = kzalloc(sizeof(*msi_chip), GFP_KERNEL);
	if (!msi_chip)
	armada_370_xp_msi_inner_domain =
		irq_domain_add_linear(NULL, PCI_MSI_DOORBELL_NR,
				      &armada_370_xp_msi_domain_ops, NULL);
	if (!armada_370_xp_msi_inner_domain)
		return -ENOMEM;

	msi_chip->setup_irq = armada_370_xp_setup_msi_irq;
	msi_chip->teardown_irq = armada_370_xp_teardown_msi_irq;
	msi_chip->of_node = node;

	armada_370_xp_msi_domain =
		irq_domain_add_linear(NULL, PCI_MSI_DOORBELL_NR,
				      &armada_370_xp_msi_irq_ops,
				      NULL);
		pci_msi_create_irq_domain(of_node_to_fwnode(node),
					  &armada_370_xp_msi_domain_info,
					  armada_370_xp_msi_inner_domain);
	if (!armada_370_xp_msi_domain) {
		kfree(msi_chip);
		irq_domain_remove(armada_370_xp_msi_inner_domain);
		return -ENOMEM;
	}

	ret = of_pci_msi_chip_add(msi_chip);
	if (ret < 0) {
		irq_domain_remove(armada_370_xp_msi_domain);
		kfree(msi_chip);
		return ret;
	}

	reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS)
		| PCI_MSI_DOORBELL_MASK;

@@ -280,7 +256,7 @@ static int armada_xp_set_affinity(struct irq_data *d,
#endif

static struct irq_chip armada_370_xp_irq_chip = {
	.name		= "armada_370_xp_irq",
	.name		= "MPIC",
	.irq_mask       = armada_370_xp_irq_mask,
	.irq_mask_ack   = armada_370_xp_irq_mask,
	.irq_unmask     = armada_370_xp_irq_unmask,
@@ -427,12 +403,12 @@ static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained)
			continue;

		if (is_chained) {
			irq = irq_find_mapping(armada_370_xp_msi_domain,
					       msinr - 16);
			irq = irq_find_mapping(armada_370_xp_msi_inner_domain,
					       msinr - PCI_MSI_DOORBELL_START);
			generic_handle_irq(irq);
		} else {
			irq = msinr - 16;
			handle_domain_irq(armada_370_xp_msi_domain,
			irq = msinr - PCI_MSI_DOORBELL_START;
			handle_domain_irq(armada_370_xp_msi_inner_domain,
					  irq, regs);
		}
	}
@@ -604,8 +580,8 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
	armada_370_xp_mpic_domain =
		irq_domain_add_linear(node, nr_irqs,
				&armada_370_xp_mpic_irq_ops, NULL);

	BUG_ON(!armada_370_xp_mpic_domain);
	armada_370_xp_mpic_domain->bus_token = DOMAIN_BUS_WIRED;

	/* Setup for the boot CPU */
	armada_xp_mpic_perf_init();
+0 −1
Original line number Diff line number Diff line
@@ -229,7 +229,6 @@ int __init bcm2836_smp_boot_secondary(unsigned int cpu,
	unsigned long secondary_startup_phys =
		(unsigned long)virt_to_phys((void *)secondary_startup);

	dsb();
	writel(secondary_startup_phys,
	       intc.base + LOCAL_MAILBOX3_SET0 + 16 * cpu);

Loading