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

Commit 6f0310a1 authored by Yuriy Kolerov's avatar Yuriy Kolerov Committed by Vineet Gupta
Browse files

ARCv2: IDU-intc: Use build registers for getting numbers of interrupts



This enhancement is needed to allow masking all available common interrupts
in IDU interrupt controller in boot time since the kernel can
discover a number of them from the build register. Also now there
is no need to specify in device tree a list of used core interrupts
by IDU. E.g. before:

    idu_intc: idu-interrupt-controller {
        compatible = "snps,archs-idu-intc";
        interrupt-controller;
        interrupt-parent = <&core_intc>;
        #interrupt-cells = <2>;
        interrupts = <24 25 26 27 28 29 30 31>;
    };

and after:

    idu_intc: idu-interrupt-controller {
        compatible = "snps,archs-idu-intc";
        interrupt-controller;
        interrupt-parent = <&core_intc>;
        #interrupt-cells = <2>;
    };

Signed-off-by: default avatarYuriy Kolerov <yuriy.kolerov@synopsys.com>
Signed-off-by: default avatarVineet Gupta <vgupta@synopsys.com>
parent be568e78
Loading
Loading
Loading
Loading
+9 −10
Original line number Diff line number Diff line
@@ -230,14 +230,12 @@ static struct irq_chip idu_irq_chip = {

};

static irq_hw_number_t idu_first_hwirq;

static void idu_cascade_isr(struct irq_desc *desc)
{
	struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
	struct irq_chip *core_chip = irq_desc_get_chip(desc);
	irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc));
	irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq;
	irq_hw_number_t idu_hwirq = core_hwirq - FIRST_EXT_IRQ;

	chained_irq_enter(core_chip, desc);
	generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
@@ -283,17 +281,20 @@ static int __init
idu_of_init(struct device_node *intc, struct device_node *parent)
{
	struct irq_domain *domain;
	/* Read IDU BCR to confirm nr_irqs */
	int nr_irqs = of_irq_count(intc);
	int nr_irqs;
	int i, virq;
	struct mcip_bcr mp;
	struct mcip_idu_bcr idu_bcr;

	READ_BCR(ARC_REG_MCIP_BCR, mp);

	if (!mp.idu)
		panic("IDU not detected, but DeviceTree using it");

	pr_info("MCIP: IDU referenced from Devicetree %d irqs\n", nr_irqs);
	READ_BCR(ARC_REG_MCIP_IDU_BCR, idu_bcr);
	nr_irqs = mcip_idu_bcr_to_nr_irqs(idu_bcr);

	pr_info("MCIP: IDU supports %u common irqs\n", nr_irqs);

	domain = irq_domain_add_linear(intc, nr_irqs, &idu_irq_ops, NULL);

@@ -306,10 +307,8 @@ idu_of_init(struct device_node *intc, struct device_node *parent)
		 * however we need it to get the parent virq and set IDU handler
		 * as first level isr
		 */
		virq = irq_of_parse_and_map(intc, i);
		if (!i)
			idu_first_hwirq = irqd_to_hwirq(irq_get_irq_data(virq));

		virq = irq_create_mapping(NULL, i + FIRST_EXT_IRQ);
		BUG_ON(!virq);
		irq_set_chained_handler_and_data(virq, idu_cascade_isr, domain);
	}

+17 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <soc/arc/aux.h>

#define ARC_REG_MCIP_BCR	0x0d0
#define ARC_REG_MCIP_IDU_BCR	0x0D5
#define ARC_REG_MCIP_CMD	0x600
#define ARC_REG_MCIP_WDATA	0x601
#define ARC_REG_MCIP_READBACK	0x602
@@ -69,6 +70,22 @@ struct mcip_bcr {
#endif
};

struct mcip_idu_bcr {
#ifdef CONFIG_CPU_BIG_ENDIAN
	unsigned int pad:21, cirqnum:3, ver:8;
#else
	unsigned int ver:8, cirqnum:3, pad:21;
#endif
};


/*
 * Build register for IDU contains not an actual number of supported common
 * interrupts but an exponent of 2 which must be multiplied by 4 to
 * get a number of supported common interrupts.
 */
#define mcip_idu_bcr_to_nr_irqs(bcr) (4 * (1 << (bcr).cirqnum))

/*
 * MCIP programming model
 *