Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1568793 > unrolled thread
| Started by | Yuriy Kolerov <yuriy.kolerov@synopsys.com> |
|---|---|
| First post | 2017-01-28 01:10 +0100 |
| Last post | 2017-01-28 01:10 +0100 |
| Articles | 5 — 1 participant |
Back to article view | Back to linux.kernel
[PATCH 0/6] Use build registers for getting numbers of interrupts Yuriy Kolerov <yuriy.kolerov@synopsys.com> - 2017-01-28 01:10 +0100
[PATCH 5/6] ARCv2: IRQ: Use build registers for getting numbers of interrupts Yuriy Kolerov <yuriy.kolerov@synopsys.com> - 2017-01-28 01:10 +0100
[PATCH 1/6] ARCv2: IRQ: Move structures for core intc to the header Yuriy Kolerov <yuriy.kolerov@synopsys.com> - 2017-01-28 01:10 +0100
[PATCH 6/6] ARCv2: IRQ: Set a default priority for all core interrupts Yuriy Kolerov <yuriy.kolerov@synopsys.com> - 2017-01-28 01:10 +0100
[PATCH 2/6] ARCv2: MCIP: Add structure for build register of IDU Yuriy Kolerov <yuriy.kolerov@synopsys.com> - 2017-01-28 01:10 +0100
| From | Yuriy Kolerov <yuriy.kolerov@synopsys.com> |
|---|---|
| Date | 2017-01-28 01:10 +0100 |
| Subject | [PATCH 0/6] Use build registers for getting numbers of interrupts |
| Message-ID | <t4oKC-2wK-7@gated-at.bofh.it> |
A summary:
* Use build registers for getting numbers of interrupts both for
core interrupt controller and for IDU interrupt controller.
* Set a default priority for all core interrupt to prevent
unexpected switching of banks of registers.
* Remove option for setting number of interrupts since it does
not affect a number of interrupts in IRQ domains and breaks
portability since it is impossible to change size of table of
interrupts after linkage.
Yuriy Kolerov (6):
ARCv2: IRQ: Move structures for core intc to the header
ARCv2: MCIP: Add structure for build register of IDU
ARCv2: IRQ: Add macro for the first external interrupt number
ARCv2: IRQ: Remove option for setting number of interrupts
ARCv2: IRQ: Use build registers for getting numbers of interrupts
ARCv2: IRQ: Set a default priority for all core interrupts
arch/arc/Kconfig | 11 -----------
arch/arc/include/asm/arcregs.h | 26 +++++++++++++++++++++++++
arch/arc/include/asm/irq.h | 32 +++++++++++++++++++++++++++---
arch/arc/kernel/entry-arcv2.S | 3 ++-
arch/arc/kernel/intc-arcv2.c | 44 ++++++++++++++++++++----------------------
arch/arc/kernel/mcip.c | 31 +++++++++++++++++------------
include/soc/arc/mcip.h | 17 ++++++++++++++++
7 files changed, 114 insertions(+), 50 deletions(-)
--
2.7.4
[toc] | [next] | [standalone]
| From | Yuriy Kolerov <yuriy.kolerov@synopsys.com> |
|---|---|
| Date | 2017-01-28 01:10 +0100 |
| Subject | [PATCH 5/6] ARCv2: IRQ: Use build registers for getting numbers of interrupts |
| Message-ID | <t4oKC-2wK-15@gated-at.bofh.it> |
| In reply to | #1568793 |
This enhancement allows to mask 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: Yuriy Kolerov <yuriy.kolerov@synopsys.com>
---
arch/arc/include/asm/irq.h | 3 +++
arch/arc/kernel/intc-arcv2.c | 7 ++++++-
arch/arc/kernel/mcip.c | 31 +++++++++++++++++++------------
3 files changed, 28 insertions(+), 13 deletions(-)
diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index dfa09e3..1970d78c 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -18,6 +18,9 @@
*/
#define NR_CPU_IRQS 240
+/* A fixed number of exceptions which occupy first interrupt lines */
+#define NR_EXCEPTIONS 16
+
/*
* ARCv2 can support 240 interrupts in the core interrupts controllers and
* 128 interrupts in IDU. Thus 512 virtual IRQs must be enough for most
diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index a9a7497..b2a6de4 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -123,11 +123,16 @@ static int __init
init_onchip_IRQ(struct device_node *intc, struct device_node *parent)
{
struct irq_domain *root_domain;
+ struct bcr_irq_arcv2 irq_bcr;
+ unsigned int nr_cpu_irqs;
+
+ READ_BCR(ARC_REG_IRQ_BCR, irq_bcr);
+ nr_cpu_irqs = irq_bcr.irqs + NR_EXCEPTIONS;
if (parent)
panic("DeviceTree incore intc not a root irq controller\n");
- root_domain = irq_domain_add_linear(intc, NR_CPU_IRQS, &arcv2_irq_ops, NULL);
+ root_domain = irq_domain_add_linear(intc, nr_cpu_irqs, &arcv2_irq_ops, NULL);
if (!root_domain)
panic("root irq domain not avail\n");
diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c
index 9988b42..45d45fc 100644
--- a/arch/arc/kernel/mcip.c
+++ b/arch/arc/kernel/mcip.c
@@ -157,15 +157,20 @@ static void idu_set_mode(unsigned int cmn_irq, unsigned int lvl,
__mcip_cmd_data(CMD_IDU_SET_MODE, cmn_irq, data.word);
}
-static void idu_irq_mask(struct irq_data *data)
+static void idu_irq_mask_raw(irq_hw_number_t hwirq)
{
unsigned long flags;
raw_spin_lock_irqsave(&mcip_lock, flags);
- __mcip_cmd_data(CMD_IDU_SET_MASK, data->hwirq, 1);
+ __mcip_cmd_data(CMD_IDU_SET_MASK, hwirq, 1);
raw_spin_unlock_irqrestore(&mcip_lock, flags);
}
+static void idu_irq_mask(struct irq_data *data)
+{
+ idu_irq_mask_raw(data->hwirq);
+}
+
static void idu_irq_unmask(struct irq_data *data)
{
unsigned long flags;
@@ -231,14 +236,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));
@@ -284,33 +287,37 @@ 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);
/* Parent interrupts (core-intc) are already mapped */
for (i = 0; i < nr_irqs; i++) {
+ /* Mask all common interrupts by default */
+ idu_irq_mask_raw(i);
+
/*
* Return parent uplink IRQs (towards core intc) 24,25,.....
* this step has been done before already
* 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);
}
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Yuriy Kolerov <yuriy.kolerov@synopsys.com> |
|---|---|
| Date | 2017-01-28 01:10 +0100 |
| Subject | [PATCH 1/6] ARCv2: IRQ: Move structures for core intc to the header |
| Message-ID | <t4oKC-2wK-25@gated-at.bofh.it> |
| In reply to | #1568793 |
Also add new macro ARC_REG_STATUS32 for the address of STATUS32
auxiliary register. It is better to use it instead of magic numbers.
Signed-off-by: Yuriy Kolerov <yuriy.kolerov@synopsys.com>
---
arch/arc/include/asm/arcregs.h | 26 ++++++++++++++++++++++++++
arch/arc/kernel/intc-arcv2.c | 23 +++--------------------
2 files changed, 29 insertions(+), 20 deletions(-)
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index f659942..bc1f7bf 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -38,6 +38,9 @@
#define ARC_REG_CLUSTER_BCR 0xcf
#define ARC_REG_AUX_ICCM 0x208 /* ICCM Base Addr (ARCv2) */
+/* Common for ARCompact and ARCv2 status register */
+#define ARC_REG_STATUS32 0x0A
+
/* status32 Bits Positions */
#define STATUS_AE_BIT 5 /* Exception active */
#define STATUS_DE_BIT 6 /* PC is in delay slot */
@@ -233,6 +236,29 @@ struct bcr_generic {
#endif
};
+struct bcr_irq_arcv2 {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+ unsigned int pad:3, firq:1, prio:4, exts:8, irqs:8, ver:8;
+#else
+ unsigned int ver:8, irqs:8, exts:8, prio:4, firq:1, pad:3;
+#endif
+};
+
+/*
+ ***********************************************
+ * Control registers for configuration of CPU
+ */
+
+struct aux_irq_ctrl_arcv2 {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+ unsigned int res3:18, save_idx_regs:1, res2:1, save_u_to_u:1,
+ save_lp_regs:1, save_blink:1, res:4, save_nr_gpr_pairs:5;
+#else
+ unsigned int save_nr_gpr_pairs:5, res:4, save_blink:1, save_lp_regs:1,
+ save_u_to_u:1, res2:1, save_idx_regs:1, res3:18;
+#endif
+};
+
/*
*******************************************************************
* Generic structures to hold build configuration used at runtime
diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index ecef0fb..2f31bb1 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -24,25 +24,8 @@ void arc_init_IRQ(void)
{
unsigned int tmp, irq_prio;
- struct irq_build {
-#ifdef CONFIG_CPU_BIG_ENDIAN
- unsigned int pad:3, firq:1, prio:4, exts:8, irqs:8, ver:8;
-#else
- unsigned int ver:8, irqs:8, exts:8, prio:4, firq:1, pad:3;
-#endif
- } irq_bcr;
-
- struct aux_irq_ctrl {
-#ifdef CONFIG_CPU_BIG_ENDIAN
- unsigned int res3:18, save_idx_regs:1, res2:1,
- save_u_to_u:1, save_lp_regs:1, save_blink:1,
- res:4, save_nr_gpr_pairs:5;
-#else
- unsigned int save_nr_gpr_pairs:5, res:4,
- save_blink:1, save_lp_regs:1, save_u_to_u:1,
- res2:1, save_idx_regs:1, res3:18;
-#endif
- } ictrl;
+ struct bcr_irq_arcv2 irq_bcr;
+ struct aux_irq_ctrl_arcv2 ictrl;
*(unsigned int *)&ictrl = 0;
@@ -69,7 +52,7 @@ void arc_init_IRQ(void)
irq_bcr.firq ? " FIRQ (not used)":"");
/* setup status32, don't enable intr yet as kernel doesn't want */
- tmp = read_aux_reg(0xa);
+ tmp = read_aux_reg(ARC_REG_STATUS32);
tmp |= STATUS_AD_MASK | (ARCV2_IRQ_DEF_PRIO << 1);
tmp &= ~STATUS_IE_MASK;
asm volatile("kflag %0 \n"::"r"(tmp));
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Yuriy Kolerov <yuriy.kolerov@synopsys.com> |
|---|---|
| Date | 2017-01-28 01:10 +0100 |
| Subject | [PATCH 6/6] ARCv2: IRQ: Set a default priority for all core interrupts |
| Message-ID | <t4oKC-2wK-23@gated-at.bofh.it> |
| In reply to | #1568793 |
After reset all interrupts in the core interrupt controller has
the highest priority P0. If the platform supports Fast IRQs and
has more than 1 banks of registers then CPU automatically switch
banks of registers when P0 interrupt comes.
The problem is that the kernel expects that by default switching
of banks is not used by all interrupts. It is necessary to set a
default nonzero priority for all available interrupts to avoid
undefined behaviour.
Signed-off-by: Yuriy Kolerov <yuriy.kolerov@synopsys.com>
---
arch/arc/kernel/intc-arcv2.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index b2a6de4..b9d9ce6 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -22,7 +22,7 @@
*/
void arc_init_IRQ(void)
{
- unsigned int tmp, irq_prio;
+ unsigned int tmp, irq_prio, i;
struct bcr_irq_arcv2 irq_bcr;
struct aux_irq_ctrl_arcv2 ictrl;
@@ -51,6 +51,16 @@ void arc_init_IRQ(void)
irq_prio + 1, ARCV2_IRQ_DEF_PRIO,
irq_bcr.firq ? " FIRQ (not used)":"");
+ /*
+ * Set a default priority for all available interrupts to prevent
+ * switching of register banks if Fast IRQ and multiple register banks
+ * are supported by CPU.
+ */
+ for (i = NR_EXCEPTIONS; i < irq_bcr.irqs + NR_EXCEPTIONS; i++) {
+ write_aux_reg(AUX_IRQ_SELECT, i);
+ write_aux_reg(AUX_IRQ_PRIORITY, ARCV2_IRQ_DEF_PRIO);
+ }
+
/* setup status32, don't enable intr yet as kernel doesn't want */
tmp = read_aux_reg(ARC_REG_STATUS32);
tmp |= STATUS_AD_MASK | (ARCV2_IRQ_DEF_PRIO << 1);
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Yuriy Kolerov <yuriy.kolerov@synopsys.com> |
|---|---|
| Date | 2017-01-28 01:10 +0100 |
| Subject | [PATCH 2/6] ARCv2: MCIP: Add structure for build register of IDU |
| Message-ID | <t4oKD-2wK-27@gated-at.bofh.it> |
| In reply to | #1568793 |
This structure is necessary for retrieving of supported
number of common interrupts in IDU interrupt controller.
Signed-off-by: Yuriy Kolerov <yuriy.kolerov@synopsys.com>
---
include/soc/arc/mcip.h | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/include/soc/arc/mcip.h b/include/soc/arc/mcip.h
index 6902c2a..798c01b 100644
--- a/include/soc/arc/mcip.h
+++ b/include/soc/arc/mcip.h
@@ -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
*
--
2.7.4
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web