Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 06 Apr 2014 19:21:23 +0200
From:      Jakub Klama <jceel@freebsd.org>
To:        freebsd-arm@freebsd.org
Subject:   [RFC] Refactored interrupt handling on ARM
Message-ID:  <53418D13.7030107@freebsd.org>
In-Reply-To: <3e7f866f4bc774975ae3c85e0df78ec2@uj.edu.pl>
References:  <3e7f866f4bc774975ae3c85e0df78ec2@uj.edu.pl>

next in thread | previous in thread | raw e-mail | index | archive | help
Hello all,

It has been a long time since my SoC 2012 ended. However, I've finally
merged refactored interrupt handling framework to head and added SMP
support (IPIs). Let's start:

What is this and how does it work?

It's a refactored interrupt handling code for ARM which supports 
multiple, stacked interrupt controllers. In particular, it creates a 
clean way to support IRQ multiplexers such as GPIO controllers with 
interrupt generation functionality. Approach used in this code is 
somewhat similar to one usedin powerpc port.

Every interrupt controller should implement methods from pic_if.m
interface - at least pic_config, pic_unmask, pic_mask and pic_eoi. It
should also install IRQ handler on parent interrupt controller 
(specified by interrupt-parent in FDT, defaulting to nexus).

The root interrupt controller is nexus - on ARM it has exactly one IRQ
line (typically nexus0:0) representing core IRQ signal (on MIPS, there
will be probably five of them). SoC interrupt controller, such as GIC
then installs handler on nexus0:0 IRQ and exposes itself as interrupt
controller by calling arm_register_pic(). When the interrupt arrives,
pic driver calls arm_dispatch_irq() function.

So, for example, a typical SoC interrupt tree can look like that:

nexus0 (provides 1 irq)
|
\-- gic0 (provides 160 irqs, uses irq nexus0:0)
     |
     \-- gpio0 (provides 8 irqs, uses irq gic0:42)
     |   |
     |   \-- mmcsd0 (uses irqs gpio0:1, gpio0:2)
     |   \-- spi0 (uses irq gpio0:3)
     |   ...
     \-- gpio1 (provides 8 irqs, uses irq gic0:43)
     \-- ehci0 (uses irq gic0:109)
     ...

Interrupt numbers used in rman are composed of two 8-bit fields: higher
8 bits are the pic index and lower 8 bits are IRQ line number inside
particular pic (so there are 256 pics supported with maximum of 256
irq lines on each). These numbers are generated using FDT_MAP_IRQ()
macro called from FDT code.

As you can see from the provided dmesg logs, irq numbers are printed in
form of "pic_name:line_number", i.e: "nexus0:0" or "gic0:109".

Of course there's still support for shared interrupt handlers - on
LPC3250 there are 3 pics attached to one in-core IRQ line.

There's also support for IPIs. Calls to pic_ipi_get(), pic_ipi_clear(),
pic_ipi_send() and ..._init_secondary() are redirected to one interrupt
controller registered as capable to do IPIs. There can be only one
interrupt controller with IPI support registered (and certainly not the
root one).

Code was tested on following platforms:
* EA3250 (arm/lpc)
* Pandaboard (arm/ti) (both with SMP enabled and disabled)

Merging it would not require any changes in existing ARM ports (unless
they will be adopted to new framework and will have ARM_INTRNG option
enabled), except for adding arm/arm/intr.c to their file lists (as it's
now not compiled-in by default). That was tested too.

dmesg outputs can be found there:
* http://people.freebsd.org/~jceel/intrng/pandaboard.dmesg.txt
* http://people.freebsd.org/~jceel/intrng/ea3250.dmesg.txt

diff against head as of r264192:
* http://people.freebsd.org/~jceel/intrng/intrng.diff

git branch containing the changes:
* https://github.com/jceel/freebsd-arm-intrng/tree/intrng

What do you think about that? That code probably needs some
improvements, especially in IPI/SMP area, but I think it's a step 
further in interrupt handling on ARM.

I really appreciate any comments and opinions.

Regards,
Jakub



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?53418D13.7030107>