* [PATCH 1/5] microblaze: Use of_find_compatible_node for timer and
@ 2011-12-09 11:45 Michal Simek
[not found] ` <1323431121-12780-1-git-send-email-monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>
0 siblings, 1 reply; 7+ messages in thread
From: Michal Simek @ 2011-12-09 11:45 UTC (permalink / raw)
To: robherring2-Re5JQEeQqe8AvxtiuMwx3w
Cc: anton.vorontsov-QSEj5FYQhm4dnm+yROfE0A,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Calling of_find_compatible_node instead of calling private code
which does the same.
Signed-off-by: Michal Simek <monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>
---
arch/microblaze/kernel/intc.c | 17 ++++-------------
arch/microblaze/kernel/timer.c | 17 ++++-------------
2 files changed, 8 insertions(+), 26 deletions(-)
diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c
index eb41441..da33e45 100644
--- a/arch/microblaze/kernel/intc.c
+++ b/arch/microblaze/kernel/intc.c
@@ -99,7 +99,7 @@ unsigned int get_irq(struct pt_regs *regs)
void __init init_IRQ(void)
{
- u32 i, j, intr_type;
+ u32 i, intr_type;
struct device_node *intc = NULL;
#ifdef CONFIG_SELFMOD_INTC
unsigned int intc_baseaddr = 0;
@@ -113,16 +113,7 @@ void __init init_IRQ(void)
0
};
#endif
- const char * const intc_list[] = {
- "xlnx,xps-intc-1.00.a",
- NULL
- };
-
- for (j = 0; intc_list[j] != NULL; j++) {
- intc = of_find_compatible_node(NULL, NULL, intc_list[j]);
- if (intc)
- break;
- }
+ intc = of_find_compatible_node(NULL, NULL, "xlnx,xps-intc-1.00.a");
BUG_ON(!intc);
intc_baseaddr = be32_to_cpup(of_get_property(intc,
@@ -140,8 +131,8 @@ void __init init_IRQ(void)
#ifdef CONFIG_SELFMOD_INTC
selfmod_function((int *) arr_func, intc_baseaddr);
#endif
- printk(KERN_INFO "%s #0 at 0x%08x, num_irq=%d, edge=0x%x\n",
- intc_list[j], intc_baseaddr, nr_irq, intr_type);
+ printk(KERN_INFO "XPS intc #0 at 0x%08x, num_irq=%d, edge=0x%x\n",
+ intc_baseaddr, nr_irq, intr_mask);
/*
* Disable all external interrupts until they are
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c
index af74b11..3ba1e1c 100644
--- a/arch/microblaze/kernel/timer.c
+++ b/arch/microblaze/kernel/timer.c
@@ -243,7 +243,7 @@ static int timer_initialized;
void __init time_init(void)
{
- u32 irq, i = 0;
+ u32 irq;
u32 timer_num = 1;
struct device_node *timer = NULL;
const void *prop;
@@ -258,16 +258,7 @@ void __init time_init(void)
0
};
#endif
- const char * const timer_list[] = {
- "xlnx,xps-timer-1.00.a",
- NULL
- };
-
- for (i = 0; timer_list[i] != NULL; i++) {
- timer = of_find_compatible_node(NULL, NULL, timer_list[i]);
- if (timer)
- break;
- }
+ timer = of_find_compatible_node(NULL, NULL, "xlnx,xps-timer-1.00.a");
BUG_ON(!timer);
timer_baseaddr = be32_to_cpup(of_get_property(timer, "reg", NULL));
@@ -283,8 +274,8 @@ void __init time_init(void)
#ifdef CONFIG_SELFMOD_TIMER
selfmod_function((int *) arr_func, timer_baseaddr);
#endif
- printk(KERN_INFO "%s #0 at 0x%08x, irq=%d\n",
- timer_list[i], timer_baseaddr, irq);
+ printk(KERN_INFO "XPS timer #0 at 0x%08x, irq=%d\n",
+ timer_baseaddr, irq);
/* If there is clock-frequency property than use it */
prop = of_get_property(timer, "clock-frequency", NULL);
--
1.7.5.4
^ permalink raw reply related [flat|nested] 7+ messages in thread[parent not found: <1323431121-12780-1-git-send-email-monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>]
* [PATCH 2/5] microblaze: intc: Change variable name [not found] ` <1323431121-12780-1-git-send-email-monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org> @ 2011-12-09 11:45 ` Michal Simek [not found] ` <1323431121-12780-2-git-send-email-monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org> 0 siblings, 1 reply; 7+ messages in thread From: Michal Simek @ 2011-12-09 11:45 UTC (permalink / raw) To: robherring2-Re5JQEeQqe8AvxtiuMwx3w Cc: anton.vorontsov-QSEj5FYQhm4dnm+yROfE0A, devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, linux-kernel-u79uwXL29TY76Z2rM5mHXA intr_type is mask - change name. s/intr_type/intr_mask/g Signed-off-by: Michal Simek <monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org> --- arch/microblaze/kernel/intc.c | 11 +++++------ 1 files changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c index da33e45..1293098 100644 --- a/arch/microblaze/kernel/intc.c +++ b/arch/microblaze/kernel/intc.c @@ -99,7 +99,7 @@ unsigned int get_irq(struct pt_regs *regs) void __init init_IRQ(void) { - u32 i, intr_type; + u32 i, intr_mask; struct device_node *intc = NULL; #ifdef CONFIG_SELFMOD_INTC unsigned int intc_baseaddr = 0; @@ -122,10 +122,9 @@ void __init init_IRQ(void) nr_irq = be32_to_cpup(of_get_property(intc, "xlnx,num-intr-inputs", NULL)); - intr_type = - be32_to_cpup(of_get_property(intc, - "xlnx,kind-of-intr", NULL)); - if (intr_type > (u32)((1ULL << nr_irq) - 1)) + intr_mask = + be32_to_cpup(of_get_property(intc, "xlnx,kind-of-intr", NULL)); + if (intr_mask > (u32)((1ULL << nr_irq) - 1)) printk(KERN_INFO " ERROR: Mismatch in kind-of-intr param\n"); #ifdef CONFIG_SELFMOD_INTC @@ -147,7 +146,7 @@ void __init init_IRQ(void) out_be32(intc_baseaddr + MER, MER_HIE | MER_ME); for (i = 0; i < nr_irq; ++i) { - if (intr_type & (0x00000001 << i)) { + if (intr_mask & (0x00000001 << i)) { irq_set_chip_and_handler_name(i, &intc_dev, handle_edge_irq, "edge"); irq_clear_status_flags(i, IRQ_LEVEL); -- 1.7.5.4 ^ permalink raw reply related [flat|nested] 7+ messages in thread
[parent not found: <1323431121-12780-2-git-send-email-monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>]
* [PATCH 3/5] microblaze: Use irq_of_parse_and_map for timer [not found] ` <1323431121-12780-2-git-send-email-monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org> @ 2011-12-09 11:45 ` Michal Simek 2011-12-09 11:45 ` [PATCH 4/5] microblaze: Change NO_IRQ to 0 Michal Simek 0 siblings, 1 reply; 7+ messages in thread From: Michal Simek @ 2011-12-09 11:45 UTC (permalink / raw) To: robherring2-Re5JQEeQqe8AvxtiuMwx3w Cc: anton.vorontsov-QSEj5FYQhm4dnm+yROfE0A, devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, linux-kernel-u79uwXL29TY76Z2rM5mHXA It is necessary to call generic function for irq finding. The main reason is that this generic function calls irq_create_of_mapping which can add some shift because of NO_IRQ. Signed-off-by: Michal Simek <monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org> --- arch/microblaze/kernel/timer.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index 3ba1e1c..52e3eaf 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c @@ -263,7 +263,7 @@ void __init time_init(void) timer_baseaddr = be32_to_cpup(of_get_property(timer, "reg", NULL)); timer_baseaddr = (unsigned long) ioremap(timer_baseaddr, PAGE_SIZE); - irq = be32_to_cpup(of_get_property(timer, "interrupts", NULL)); + irq = irq_of_parse_and_map(timer, 0); timer_num = be32_to_cpup(of_get_property(timer, "xlnx,one-timer-only", NULL)); if (timer_num) { -- 1.7.5.4 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/5] microblaze: Change NO_IRQ to 0 2011-12-09 11:45 ` [PATCH 3/5] microblaze: Use irq_of_parse_and_map for timer Michal Simek @ 2011-12-09 11:45 ` Michal Simek 2011-12-09 11:45 ` [PATCH 5/5] microblaze: Introduce IRQ_SW_OFFSET to help with sw IRQ Michal Simek 0 siblings, 1 reply; 7+ messages in thread From: Michal Simek @ 2011-12-09 11:45 UTC (permalink / raw) To: robherring2 Cc: grant.likely, devicetree-discuss, anton.vorontsov, linux-kernel As has been discussed many times[1], Using NO_IRQ set to anything other than 0 is bug waiting to happen since many drivers follow the pattern "if (!irq)" for testing whether or not an irq has been set. This patch changes the Microblaze NO_IRQ setting from -1 to 0 to bring it in line with most of the rest of the kernel. It also prepares for Microblaze eventually supporting multiple interrupt controllers by breaking the assumption that hwirq# == Linux IRQ#. The Linux IRQ number is just a cookie with no guarantee of a direct relationship with the hardware irq arrangement. At this point, Microblaze interrupt handling only supports only one instance of one kind of interrupt controller (xilinx_intc). This change shouldn't affect any architecture code outside of the interrupt controller driver and the irq_of mapping. Updated to 3.2 and to use irq_data.hwirq by Rob Herring. [1] http://lkml.org/lkml/2005/11/21/221 Signed-off-by: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Rob Herring <rob.herring@calxeda.com> Signed-off-by: Michal Simek <monstr@monstr.eu> --- arch/microblaze/include/asm/irq.h | 4 ++-- arch/microblaze/kernel/intc.c | 31 ++++++++++++++++++------------- arch/microblaze/kernel/irq.c | 10 ++++++---- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/arch/microblaze/include/asm/irq.h b/arch/microblaze/include/asm/irq.h index cc54187..b07c179 100644 --- a/arch/microblaze/include/asm/irq.h +++ b/arch/microblaze/include/asm/irq.h @@ -9,7 +9,7 @@ #ifndef _ASM_MICROBLAZE_IRQ_H #define _ASM_MICROBLAZE_IRQ_H -#define NR_IRQS 32 +#define NR_IRQS (32 + 1) /* Add 1 to skip over IRQ0 */ #include <asm-generic/irq.h> /* This type is the placeholder for a hardware interrupt number. It has to @@ -20,7 +20,7 @@ typedef unsigned long irq_hw_number_t; extern unsigned int nr_irq; -#define NO_IRQ (-1) +#define NO_IRQ 0 struct pt_regs; extern void do_IRQ(struct pt_regs *regs); diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c index 1293098..c66fce9c 100644 --- a/arch/microblaze/kernel/intc.c +++ b/arch/microblaze/kernel/intc.c @@ -42,8 +42,9 @@ unsigned int nr_irq; static void intc_enable_or_unmask(struct irq_data *d) { - unsigned long mask = 1 << d->irq; - pr_debug("enable_or_unmask: %d\n", d->irq); + unsigned long mask = 1 << d->hwirq; + + pr_debug("enable_or_unmask: %ld\n", d->hwirq); out_be32(INTC_BASE + SIE, mask); /* ack level irqs because they can't be acked during @@ -56,20 +57,21 @@ static void intc_enable_or_unmask(struct irq_data *d) static void intc_disable_or_mask(struct irq_data *d) { - pr_debug("disable: %d\n", d->irq); - out_be32(INTC_BASE + CIE, 1 << d->irq); + pr_debug("disable: %ld\n", d->hwirq); + out_be32(INTC_BASE + CIE, 1 << d->hwirq); } static void intc_ack(struct irq_data *d) { - pr_debug("ack: %d\n", d->irq); - out_be32(INTC_BASE + IAR, 1 << d->irq); + pr_debug("ack: %ld\n", d->hwirq); + out_be32(INTC_BASE + IAR, 1 << d->hwirq); } static void intc_mask_ack(struct irq_data *d) { - unsigned long mask = 1 << d->irq; - pr_debug("disable_and_ack: %d\n", d->irq); + unsigned long mask = 1 << d->hwirq; + + pr_debug("disable_and_ack: %ld\n", d->hwirq); out_be32(INTC_BASE + CIE, mask); out_be32(INTC_BASE + IAR, mask); } @@ -90,8 +92,11 @@ unsigned int get_irq(struct pt_regs *regs) * NOTE: This function is the one that needs to be improved in * order to handle multiple interrupt controllers. It currently * is hardcoded to check for interrupts only on the first INTC. + * + * Linux IRQ# is currently offset by one to map to the hardware + * irq number. So hardware IRQ0 maps to Linux irq 1. */ - irq = in_be32(INTC_BASE + IVR); + irq = in_be32(INTC_BASE + IVR) + 1; pr_debug("get_irq: %d\n", irq); return irq; @@ -116,8 +121,7 @@ void __init init_IRQ(void) intc = of_find_compatible_node(NULL, NULL, "xlnx,xps-intc-1.00.a"); BUG_ON(!intc); - intc_baseaddr = be32_to_cpup(of_get_property(intc, - "reg", NULL)); + intc_baseaddr = be32_to_cpup(of_get_property(intc, "reg", NULL)); intc_baseaddr = (unsigned long) ioremap(intc_baseaddr, PAGE_SIZE); nr_irq = be32_to_cpup(of_get_property(intc, "xlnx,num-intr-inputs", NULL)); @@ -145,8 +149,8 @@ void __init init_IRQ(void) /* Turn on the Master Enable. */ out_be32(intc_baseaddr + MER, MER_HIE | MER_ME); - for (i = 0; i < nr_irq; ++i) { - if (intr_mask & (0x00000001 << i)) { + for (i = 1; i <= nr_irq; ++i) { + if (intr_mask & (0x00000001 << (i - 1))) { irq_set_chip_and_handler_name(i, &intc_dev, handle_edge_irq, "edge"); irq_clear_status_flags(i, IRQ_LEVEL); @@ -155,5 +159,6 @@ void __init init_IRQ(void) handle_level_irq, "level"); irq_set_status_flags(i, IRQ_LEVEL); } + irq_get_irq_data(i)->hwirq = i - 1; } } diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c index e5d63a8..ac1b463 100644 --- a/arch/microblaze/kernel/irq.c +++ b/arch/microblaze/kernel/irq.c @@ -33,11 +33,11 @@ void __irq_entry do_IRQ(struct pt_regs *regs) irq_enter(); irq = get_irq(regs); next_irq: - BUG_ON(irq == -1U); + BUG_ON(!irq); generic_handle_irq(irq); irq = get_irq(regs); - if (irq != -1U) { + if (irq) { pr_debug("next irq: %d\n", irq); ++concurrent_irq; goto next_irq; @@ -52,13 +52,15 @@ next_irq: intc without any cascades or any connection that's why mapping is 1:1 */ unsigned int irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq) { - return hwirq; + return hwirq + 1; } EXPORT_SYMBOL_GPL(irq_create_mapping); unsigned int irq_create_of_mapping(struct device_node *controller, const u32 *intspec, unsigned int intsize) { - return intspec[0]; + /* Hardware irq is mapped to Linux IRQ# by a 1 offset. Linux irq + * 0 means no IRQ. */ + return intspec[0] + 1; } EXPORT_SYMBOL_GPL(irq_create_of_mapping); -- 1.7.5.4 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 5/5] microblaze: Introduce IRQ_SW_OFFSET to help with sw IRQ 2011-12-09 11:45 ` [PATCH 4/5] microblaze: Change NO_IRQ to 0 Michal Simek @ 2011-12-09 11:45 ` Michal Simek 2011-12-09 14:12 ` Rob Herring 0 siblings, 1 reply; 7+ messages in thread From: Michal Simek @ 2011-12-09 11:45 UTC (permalink / raw) To: robherring2 Cc: grant.likely, devicetree-discuss, anton.vorontsov, linux-kernel If you setup IRQ_OFFSET > nr_irq you completely separate hardware and software IRQs which help you with debugging. For example: IRQ_SW_OFFSET = 32 DTS HW(line) LINUX timer - 2 3 35 sysace 4 5 37 serial 5 6 38 HW line is setup DTS + NO_IRQ_OFFSET to ensure that NO_IRQ is always 0. ~ # cat /proc/interrupts CPU0 35: 3570 Xilinx INTC-level timer 37: 0 Xilinx INTC-level systemace 38: 108 Xilinx INTC-level serial Signed-off-by: Michal Simek <monstr@monstr.eu> --- arch/microblaze/include/asm/irq.h | 12 +++++++++++- arch/microblaze/kernel/intc.c | 11 ++++------- arch/microblaze/kernel/irq.c | 9 ++++----- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/arch/microblaze/include/asm/irq.h b/arch/microblaze/include/asm/irq.h index b07c179..97e98f1 100644 --- a/arch/microblaze/include/asm/irq.h +++ b/arch/microblaze/include/asm/irq.h @@ -9,7 +9,17 @@ #ifndef _ASM_MICROBLAZE_IRQ_H #define _ASM_MICROBLAZE_IRQ_H -#define NR_IRQS (32 + 1) /* Add 1 to skip over IRQ0 */ + +/* + * Linux IRQ# is currently offset by one to map to the hardware + * irq number. So hardware IRQ0 maps to Linux irq 1. + */ +#define NO_IRQ_OFFSET 1 + +/* Use greater value to separate software and hw IRQs */ +#define IRQ_SW_OFFSET 0 +#define IRQ_OFFSET (NO_IRQ_OFFSET + IRQ_SW_OFFSET) +#define NR_IRQS (32 + IRQ_OFFSET) #include <asm-generic/irq.h> /* This type is the placeholder for a hardware interrupt number. It has to diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c index c66fce9c..44b177e 100644 --- a/arch/microblaze/kernel/intc.c +++ b/arch/microblaze/kernel/intc.c @@ -92,11 +92,8 @@ unsigned int get_irq(struct pt_regs *regs) * NOTE: This function is the one that needs to be improved in * order to handle multiple interrupt controllers. It currently * is hardcoded to check for interrupts only on the first INTC. - * - * Linux IRQ# is currently offset by one to map to the hardware - * irq number. So hardware IRQ0 maps to Linux irq 1. */ - irq = in_be32(INTC_BASE + IVR) + 1; + irq = in_be32(INTC_BASE + IVR) + NO_IRQ_OFFSET; pr_debug("get_irq: %d\n", irq); return irq; @@ -149,8 +146,8 @@ void __init init_IRQ(void) /* Turn on the Master Enable. */ out_be32(intc_baseaddr + MER, MER_HIE | MER_ME); - for (i = 1; i <= nr_irq; ++i) { - if (intr_mask & (0x00000001 << (i - 1))) { + for (i = IRQ_OFFSET; i < (nr_irq + IRQ_OFFSET); ++i) { + if (intr_mask & (0x00000001 << (i - IRQ_OFFSET))) { irq_set_chip_and_handler_name(i, &intc_dev, handle_edge_irq, "edge"); irq_clear_status_flags(i, IRQ_LEVEL); @@ -159,6 +156,6 @@ void __init init_IRQ(void) handle_level_irq, "level"); irq_set_status_flags(i, IRQ_LEVEL); } - irq_get_irq_data(i)->hwirq = i - 1; + irq_get_irq_data(i)->hwirq = i - IRQ_OFFSET; } } diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c index ac1b463..bbebcae 100644 --- a/arch/microblaze/kernel/irq.c +++ b/arch/microblaze/kernel/irq.c @@ -34,7 +34,8 @@ void __irq_entry do_IRQ(struct pt_regs *regs) irq = get_irq(regs); next_irq: BUG_ON(!irq); - generic_handle_irq(irq); + /* Substract 1 because of get_irq */ + generic_handle_irq(irq + IRQ_OFFSET - NO_IRQ_OFFSET); irq = get_irq(regs); if (irq) { @@ -52,15 +53,13 @@ next_irq: intc without any cascades or any connection that's why mapping is 1:1 */ unsigned int irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq) { - return hwirq + 1; + return hwirq + IRQ_OFFSET; } EXPORT_SYMBOL_GPL(irq_create_mapping); unsigned int irq_create_of_mapping(struct device_node *controller, const u32 *intspec, unsigned int intsize) { - /* Hardware irq is mapped to Linux IRQ# by a 1 offset. Linux irq - * 0 means no IRQ. */ - return intspec[0] + 1; + return intspec[0] + IRQ_OFFSET; } EXPORT_SYMBOL_GPL(irq_create_of_mapping); -- 1.7.5.4 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 5/5] microblaze: Introduce IRQ_SW_OFFSET to help with sw IRQ 2011-12-09 11:45 ` [PATCH 5/5] microblaze: Introduce IRQ_SW_OFFSET to help with sw IRQ Michal Simek @ 2011-12-09 14:12 ` Rob Herring 2011-12-10 10:41 ` Michal Simek 0 siblings, 1 reply; 7+ messages in thread From: Rob Herring @ 2011-12-09 14:12 UTC (permalink / raw) To: Michal Simek Cc: grant.likely, devicetree-discuss, anton.vorontsov, linux-kernel On 12/09/2011 05:45 AM, Michal Simek wrote: > If you setup IRQ_OFFSET > nr_irq you completely separate hardware > and software IRQs which help you with debugging. > > For example: > IRQ_SW_OFFSET = 32 > > DTS HW(line) LINUX > timer - 2 3 35 > sysace 4 5 37 > serial 5 6 38 > > HW line is setup DTS + NO_IRQ_OFFSET to ensure that NO_IRQ is always 0. > This is really confusing. DTS is the HW numbering. The last 2 columns are both Linux IRQ numbering. Just create a single define for an offset. Then I would combine this into the previous patch. Rob > ~ # cat /proc/interrupts > CPU0 > 35: 3570 Xilinx INTC-level timer > 37: 0 Xilinx INTC-level systemace > 38: 108 Xilinx INTC-level serial > > Signed-off-by: Michal Simek <monstr@monstr.eu> > --- > arch/microblaze/include/asm/irq.h | 12 +++++++++++- > arch/microblaze/kernel/intc.c | 11 ++++------- > arch/microblaze/kernel/irq.c | 9 ++++----- > 3 files changed, 19 insertions(+), 13 deletions(-) > > diff --git a/arch/microblaze/include/asm/irq.h b/arch/microblaze/include/asm/irq.h > index b07c179..97e98f1 100644 > --- a/arch/microblaze/include/asm/irq.h > +++ b/arch/microblaze/include/asm/irq.h > @@ -9,7 +9,17 @@ > #ifndef _ASM_MICROBLAZE_IRQ_H > #define _ASM_MICROBLAZE_IRQ_H > > -#define NR_IRQS (32 + 1) /* Add 1 to skip over IRQ0 */ > + > +/* > + * Linux IRQ# is currently offset by one to map to the hardware > + * irq number. So hardware IRQ0 maps to Linux irq 1. > + */ > +#define NO_IRQ_OFFSET 1 > + > +/* Use greater value to separate software and hw IRQs */ > +#define IRQ_SW_OFFSET 0 > +#define IRQ_OFFSET (NO_IRQ_OFFSET + IRQ_SW_OFFSET) > +#define NR_IRQS (32 + IRQ_OFFSET) > #include <asm-generic/irq.h> > > /* This type is the placeholder for a hardware interrupt number. It has to > diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c > index c66fce9c..44b177e 100644 > --- a/arch/microblaze/kernel/intc.c > +++ b/arch/microblaze/kernel/intc.c > @@ -92,11 +92,8 @@ unsigned int get_irq(struct pt_regs *regs) > * NOTE: This function is the one that needs to be improved in > * order to handle multiple interrupt controllers. It currently > * is hardcoded to check for interrupts only on the first INTC. > - * > - * Linux IRQ# is currently offset by one to map to the hardware > - * irq number. So hardware IRQ0 maps to Linux irq 1. > */ > - irq = in_be32(INTC_BASE + IVR) + 1; > + irq = in_be32(INTC_BASE + IVR) + NO_IRQ_OFFSET; > pr_debug("get_irq: %d\n", irq); > > return irq; > @@ -149,8 +146,8 @@ void __init init_IRQ(void) > /* Turn on the Master Enable. */ > out_be32(intc_baseaddr + MER, MER_HIE | MER_ME); > > - for (i = 1; i <= nr_irq; ++i) { > - if (intr_mask & (0x00000001 << (i - 1))) { > + for (i = IRQ_OFFSET; i < (nr_irq + IRQ_OFFSET); ++i) { > + if (intr_mask & (0x00000001 << (i - IRQ_OFFSET))) { > irq_set_chip_and_handler_name(i, &intc_dev, > handle_edge_irq, "edge"); > irq_clear_status_flags(i, IRQ_LEVEL); > @@ -159,6 +156,6 @@ void __init init_IRQ(void) > handle_level_irq, "level"); > irq_set_status_flags(i, IRQ_LEVEL); > } > - irq_get_irq_data(i)->hwirq = i - 1; > + irq_get_irq_data(i)->hwirq = i - IRQ_OFFSET; > } > } > diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c > index ac1b463..bbebcae 100644 > --- a/arch/microblaze/kernel/irq.c > +++ b/arch/microblaze/kernel/irq.c > @@ -34,7 +34,8 @@ void __irq_entry do_IRQ(struct pt_regs *regs) > irq = get_irq(regs); > next_irq: > BUG_ON(!irq); > - generic_handle_irq(irq); > + /* Substract 1 because of get_irq */ > + generic_handle_irq(irq + IRQ_OFFSET - NO_IRQ_OFFSET); > > irq = get_irq(regs); > if (irq) { > @@ -52,15 +53,13 @@ next_irq: > intc without any cascades or any connection that's why mapping is 1:1 */ > unsigned int irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq) > { > - return hwirq + 1; > + return hwirq + IRQ_OFFSET; > } > EXPORT_SYMBOL_GPL(irq_create_mapping); > > unsigned int irq_create_of_mapping(struct device_node *controller, > const u32 *intspec, unsigned int intsize) > { > - /* Hardware irq is mapped to Linux IRQ# by a 1 offset. Linux irq > - * 0 means no IRQ. */ > - return intspec[0] + 1; > + return intspec[0] + IRQ_OFFSET; > } > EXPORT_SYMBOL_GPL(irq_create_of_mapping); ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 5/5] microblaze: Introduce IRQ_SW_OFFSET to help with sw IRQ 2011-12-09 14:12 ` Rob Herring @ 2011-12-10 10:41 ` Michal Simek 0 siblings, 0 replies; 7+ messages in thread From: Michal Simek @ 2011-12-10 10:41 UTC (permalink / raw) To: Rob Herring Cc: grant.likely, devicetree-discuss, anton.vorontsov, linux-kernel Rob Herring wrote: > On 12/09/2011 05:45 AM, Michal Simek wrote: >> If you setup IRQ_OFFSET > nr_irq you completely separate hardware >> and software IRQs which help you with debugging. >> >> For example: >> IRQ_SW_OFFSET = 32 >> >> DTS HW(line) LINUX >> timer - 2 3 35 >> sysace 4 5 37 >> serial 5 6 38 >> >> HW line is setup DTS + NO_IRQ_OFFSET to ensure that NO_IRQ is always 0. >> > > This is really confusing. DTS is the HW numbering. The last 2 columns > are both Linux IRQ numbering. Just create a single define for an offset. > Then I would combine this into the previous patch. > DTS generator, which we used for DTS generator for more than 2 years, generates for the first IRQ in the system this property "interrupts = < 0 2 >;" Which is HW line 1 and linux irq_data->hwirq 0 (because of shift) and irq_data->irq = 1 for SW_OFFSET=0. Anyway no problem to keep just NO_IRQ_OFFSET value. Thanks, Michal -- Michal Simek, Ing. (M.Eng) w: www.monstr.eu p: +42-0-721842854 Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/ Microblaze U-BOOT custodian ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2011-12-10 10:41 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-12-09 11:45 [PATCH 1/5] microblaze: Use of_find_compatible_node for timer and Michal Simek
[not found] ` <1323431121-12780-1-git-send-email-monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>
2011-12-09 11:45 ` [PATCH 2/5] microblaze: intc: Change variable name Michal Simek
[not found] ` <1323431121-12780-2-git-send-email-monstr-pSz03upnqPeHXe+LvDLADg@public.gmane.org>
2011-12-09 11:45 ` [PATCH 3/5] microblaze: Use irq_of_parse_and_map for timer Michal Simek
2011-12-09 11:45 ` [PATCH 4/5] microblaze: Change NO_IRQ to 0 Michal Simek
2011-12-09 11:45 ` [PATCH 5/5] microblaze: Introduce IRQ_SW_OFFSET to help with sw IRQ Michal Simek
2011-12-09 14:12 ` Rob Herring
2011-12-10 10:41 ` Michal Simek
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).