162306a36Sopenharmony_ci===============================================
262306a36Sopenharmony_ciThe irq_domain interrupt number mapping library
362306a36Sopenharmony_ci===============================================
462306a36Sopenharmony_ci
562306a36Sopenharmony_ciThe current design of the Linux kernel uses a single large number
662306a36Sopenharmony_cispace where each separate IRQ source is assigned a different number.
762306a36Sopenharmony_ciThis is simple when there is only one interrupt controller, but in
862306a36Sopenharmony_cisystems with multiple interrupt controllers the kernel must ensure
962306a36Sopenharmony_cithat each one gets assigned non-overlapping allocations of Linux
1062306a36Sopenharmony_ciIRQ numbers.
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ciThe number of interrupt controllers registered as unique irqchips
1362306a36Sopenharmony_cishow a rising tendency: for example subdrivers of different kinds
1462306a36Sopenharmony_cisuch as GPIO controllers avoid reimplementing identical callback
1562306a36Sopenharmony_cimechanisms as the IRQ core system by modelling their interrupt
1662306a36Sopenharmony_cihandlers as irqchips, i.e. in effect cascading interrupt controllers.
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ciHere the interrupt number loose all kind of correspondence to
1962306a36Sopenharmony_cihardware interrupt numbers: whereas in the past, IRQ numbers could
2062306a36Sopenharmony_cibe chosen so they matched the hardware IRQ line into the root
2162306a36Sopenharmony_ciinterrupt controller (i.e. the component actually fireing the
2262306a36Sopenharmony_ciinterrupt line to the CPU) nowadays this number is just a number.
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ciFor this reason we need a mechanism to separate controller-local
2562306a36Sopenharmony_ciinterrupt numbers, called hardware irq's, from Linux IRQ numbers.
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ciThe irq_alloc_desc*() and irq_free_desc*() APIs provide allocation of
2862306a36Sopenharmony_ciirq numbers, but they don't provide any support for reverse mapping of
2962306a36Sopenharmony_cithe controller-local IRQ (hwirq) number into the Linux IRQ number
3062306a36Sopenharmony_cispace.
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ciThe irq_domain library adds mapping between hwirq and IRQ numbers on
3362306a36Sopenharmony_citop of the irq_alloc_desc*() API.  An irq_domain to manage mapping is
3462306a36Sopenharmony_cipreferred over interrupt controller drivers open coding their own
3562306a36Sopenharmony_cireverse mapping scheme.
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ciirq_domain also implements translation from an abstract irq_fwspec
3862306a36Sopenharmony_cistructure to hwirq numbers (Device Tree and ACPI GSI so far), and can
3962306a36Sopenharmony_cibe easily extended to support other IRQ topology data sources.
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ciirq_domain usage
4262306a36Sopenharmony_ci================
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ciAn interrupt controller driver creates and registers an irq_domain by
4562306a36Sopenharmony_cicalling one of the irq_domain_add_*() or irq_domain_create_*() functions
4662306a36Sopenharmony_ci(each mapping method has a different allocator function, more on that later).
4762306a36Sopenharmony_ciThe function will return a pointer to the irq_domain on success. The caller
4862306a36Sopenharmony_cimust provide the allocator function with an irq_domain_ops structure.
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ciIn most cases, the irq_domain will begin empty without any mappings
5162306a36Sopenharmony_cibetween hwirq and IRQ numbers.  Mappings are added to the irq_domain
5262306a36Sopenharmony_ciby calling irq_create_mapping() which accepts the irq_domain and a
5362306a36Sopenharmony_cihwirq number as arguments.  If a mapping for the hwirq doesn't already
5462306a36Sopenharmony_ciexist then it will allocate a new Linux irq_desc, associate it with
5562306a36Sopenharmony_cithe hwirq, and call the .map() callback so the driver can perform any
5662306a36Sopenharmony_cirequired hardware setup.
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ciOnce a mapping has been established, it can be retrieved or used via a
5962306a36Sopenharmony_civariety of methods:
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci- irq_resolve_mapping() returns a pointer to the irq_desc structure
6262306a36Sopenharmony_ci  for a given domain and hwirq number, and NULL if there was no
6362306a36Sopenharmony_ci  mapping.
6462306a36Sopenharmony_ci- irq_find_mapping() returns a Linux IRQ number for a given domain and
6562306a36Sopenharmony_ci  hwirq number, and 0 if there was no mapping
6662306a36Sopenharmony_ci- irq_linear_revmap() is now identical to irq_find_mapping(), and is
6762306a36Sopenharmony_ci  deprecated
6862306a36Sopenharmony_ci- generic_handle_domain_irq() handles an interrupt described by a
6962306a36Sopenharmony_ci  domain and a hwirq number
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ciNote that irq domain lookups must happen in contexts that are
7262306a36Sopenharmony_cicompatible with a RCU read-side critical section.
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ciThe irq_create_mapping() function must be called *at least once*
7562306a36Sopenharmony_cibefore any call to irq_find_mapping(), lest the descriptor will not
7662306a36Sopenharmony_cibe allocated.
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ciIf the driver has the Linux IRQ number or the irq_data pointer, and
7962306a36Sopenharmony_cineeds to know the associated hwirq number (such as in the irq_chip
8062306a36Sopenharmony_cicallbacks) then it can be directly obtained from irq_data->hwirq.
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ciTypes of irq_domain mappings
8362306a36Sopenharmony_ci============================
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ciThere are several mechanisms available for reverse mapping from hwirq
8662306a36Sopenharmony_cito Linux irq, and each mechanism uses a different allocation function.
8762306a36Sopenharmony_ciWhich reverse map type should be used depends on the use case.  Each
8862306a36Sopenharmony_ciof the reverse map types are described below:
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ciLinear
9162306a36Sopenharmony_ci------
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci::
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	irq_domain_add_linear()
9662306a36Sopenharmony_ci	irq_domain_create_linear()
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ciThe linear reverse map maintains a fixed size table indexed by the
9962306a36Sopenharmony_cihwirq number.  When a hwirq is mapped, an irq_desc is allocated for
10062306a36Sopenharmony_cithe hwirq, and the IRQ number is stored in the table.
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ciThe Linear map is a good choice when the maximum number of hwirqs is
10362306a36Sopenharmony_cifixed and a relatively small number (~ < 256).  The advantages of this
10462306a36Sopenharmony_cimap are fixed time lookup for IRQ numbers, and irq_descs are only
10562306a36Sopenharmony_ciallocated for in-use IRQs.  The disadvantage is that the table must be
10662306a36Sopenharmony_cias large as the largest possible hwirq number.
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ciirq_domain_add_linear() and irq_domain_create_linear() are functionally
10962306a36Sopenharmony_ciequivalent, except for the first argument is different - the former
11062306a36Sopenharmony_ciaccepts an Open Firmware specific 'struct device_node', while the latter
11162306a36Sopenharmony_ciaccepts a more general abstraction 'struct fwnode_handle'.
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ciThe majority of drivers should use the linear map.
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ciTree
11662306a36Sopenharmony_ci----
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci::
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	irq_domain_add_tree()
12162306a36Sopenharmony_ci	irq_domain_create_tree()
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ciThe irq_domain maintains a radix tree map from hwirq numbers to Linux
12462306a36Sopenharmony_ciIRQs.  When an hwirq is mapped, an irq_desc is allocated and the
12562306a36Sopenharmony_cihwirq is used as the lookup key for the radix tree.
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ciThe tree map is a good choice if the hwirq number can be very large
12862306a36Sopenharmony_cisince it doesn't need to allocate a table as large as the largest
12962306a36Sopenharmony_cihwirq number.  The disadvantage is that hwirq to IRQ number lookup is
13062306a36Sopenharmony_cidependent on how many entries are in the table.
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ciirq_domain_add_tree() and irq_domain_create_tree() are functionally
13362306a36Sopenharmony_ciequivalent, except for the first argument is different - the former
13462306a36Sopenharmony_ciaccepts an Open Firmware specific 'struct device_node', while the latter
13562306a36Sopenharmony_ciaccepts a more general abstraction 'struct fwnode_handle'.
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ciVery few drivers should need this mapping.
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ciNo Map
14062306a36Sopenharmony_ci------
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci::
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	irq_domain_add_nomap()
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ciThe No Map mapping is to be used when the hwirq number is
14762306a36Sopenharmony_ciprogrammable in the hardware.  In this case it is best to program the
14862306a36Sopenharmony_ciLinux IRQ number into the hardware itself so that no mapping is
14962306a36Sopenharmony_cirequired.  Calling irq_create_direct_mapping() will allocate a Linux
15062306a36Sopenharmony_ciIRQ number and call the .map() callback so that driver can program the
15162306a36Sopenharmony_ciLinux IRQ number into the hardware.
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ciMost drivers cannot use this mapping, and it is now gated on the
15462306a36Sopenharmony_ciCONFIG_IRQ_DOMAIN_NOMAP option. Please refrain from introducing new
15562306a36Sopenharmony_ciusers of this API.
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ciLegacy
15862306a36Sopenharmony_ci------
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci::
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	irq_domain_add_simple()
16362306a36Sopenharmony_ci	irq_domain_add_legacy()
16462306a36Sopenharmony_ci	irq_domain_create_simple()
16562306a36Sopenharmony_ci	irq_domain_create_legacy()
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ciThe Legacy mapping is a special case for drivers that already have a
16862306a36Sopenharmony_cirange of irq_descs allocated for the hwirqs.  It is used when the
16962306a36Sopenharmony_cidriver cannot be immediately converted to use the linear mapping.  For
17062306a36Sopenharmony_ciexample, many embedded system board support files use a set of #defines
17162306a36Sopenharmony_cifor IRQ numbers that are passed to struct device registrations.  In that
17262306a36Sopenharmony_cicase the Linux IRQ numbers cannot be dynamically assigned and the legacy
17362306a36Sopenharmony_cimapping should be used.
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ciAs the name implies, the \*_legacy() functions are deprecated and only
17662306a36Sopenharmony_ciexist to ease the support of ancient platforms. No new users should be
17762306a36Sopenharmony_ciadded. Same goes for the \*_simple() functions when their use results
17862306a36Sopenharmony_ciin the legacy behaviour.
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ciThe legacy map assumes a contiguous range of IRQ numbers has already
18162306a36Sopenharmony_cibeen allocated for the controller and that the IRQ number can be
18262306a36Sopenharmony_cicalculated by adding a fixed offset to the hwirq number, and
18362306a36Sopenharmony_civisa-versa.  The disadvantage is that it requires the interrupt
18462306a36Sopenharmony_cicontroller to manage IRQ allocations and it requires an irq_desc to be
18562306a36Sopenharmony_ciallocated for every hwirq, even if it is unused.
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ciThe legacy map should only be used if fixed IRQ mappings must be
18862306a36Sopenharmony_cisupported.  For example, ISA controllers would use the legacy map for
18962306a36Sopenharmony_cimapping Linux IRQs 0-15 so that existing ISA drivers get the correct IRQ
19062306a36Sopenharmony_cinumbers.
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ciMost users of legacy mappings should use irq_domain_add_simple() or
19362306a36Sopenharmony_ciirq_domain_create_simple() which will use a legacy domain only if an IRQ range
19462306a36Sopenharmony_ciis supplied by the system and will otherwise use a linear domain mapping.
19562306a36Sopenharmony_ciThe semantics of this call are such that if an IRQ range is specified then
19662306a36Sopenharmony_cidescriptors will be allocated on-the-fly for it, and if no range is
19762306a36Sopenharmony_cispecified it will fall through to irq_domain_add_linear() or
19862306a36Sopenharmony_ciirq_domain_create_linear() which means *no* irq descriptors will be allocated.
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ciA typical use case for simple domains is where an irqchip provider
20162306a36Sopenharmony_ciis supporting both dynamic and static IRQ assignments.
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ciIn order to avoid ending up in a situation where a linear domain is
20462306a36Sopenharmony_ciused and no descriptor gets allocated it is very important to make sure
20562306a36Sopenharmony_cithat the driver using the simple domain call irq_create_mapping()
20662306a36Sopenharmony_cibefore any irq_find_mapping() since the latter will actually work
20762306a36Sopenharmony_cifor the static IRQ assignment case.
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ciirq_domain_add_simple() and irq_domain_create_simple() as well as
21062306a36Sopenharmony_ciirq_domain_add_legacy() and irq_domain_create_legacy() are functionally
21162306a36Sopenharmony_ciequivalent, except for the first argument is different - the former
21262306a36Sopenharmony_ciaccepts an Open Firmware specific 'struct device_node', while the latter
21362306a36Sopenharmony_ciaccepts a more general abstraction 'struct fwnode_handle'.
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ciHierarchy IRQ domain
21662306a36Sopenharmony_ci--------------------
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ciOn some architectures, there may be multiple interrupt controllers
21962306a36Sopenharmony_ciinvolved in delivering an interrupt from the device to the target CPU.
22062306a36Sopenharmony_ciLet's look at a typical interrupt delivering path on x86 platforms::
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci  Device --> IOAPIC -> Interrupt remapping Controller -> Local APIC -> CPU
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ciThere are three interrupt controllers involved:
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci1) IOAPIC controller
22762306a36Sopenharmony_ci2) Interrupt remapping controller
22862306a36Sopenharmony_ci3) Local APIC controller
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ciTo support such a hardware topology and make software architecture match
23162306a36Sopenharmony_cihardware architecture, an irq_domain data structure is built for each
23262306a36Sopenharmony_ciinterrupt controller and those irq_domains are organized into hierarchy.
23362306a36Sopenharmony_ciWhen building irq_domain hierarchy, the irq_domain near to the device is
23462306a36Sopenharmony_cichild and the irq_domain near to CPU is parent. So a hierarchy structure
23562306a36Sopenharmony_cias below will be built for the example above::
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	CPU Vector irq_domain (root irq_domain to manage CPU vectors)
23862306a36Sopenharmony_ci		^
23962306a36Sopenharmony_ci		|
24062306a36Sopenharmony_ci	Interrupt Remapping irq_domain (manage irq_remapping entries)
24162306a36Sopenharmony_ci		^
24262306a36Sopenharmony_ci		|
24362306a36Sopenharmony_ci	IOAPIC irq_domain (manage IOAPIC delivery entries/pins)
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ciThere are four major interfaces to use hierarchy irq_domain:
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci1) irq_domain_alloc_irqs(): allocate IRQ descriptors and interrupt
24862306a36Sopenharmony_ci   controller related resources to deliver these interrupts.
24962306a36Sopenharmony_ci2) irq_domain_free_irqs(): free IRQ descriptors and interrupt controller
25062306a36Sopenharmony_ci   related resources associated with these interrupts.
25162306a36Sopenharmony_ci3) irq_domain_activate_irq(): activate interrupt controller hardware to
25262306a36Sopenharmony_ci   deliver the interrupt.
25362306a36Sopenharmony_ci4) irq_domain_deactivate_irq(): deactivate interrupt controller hardware
25462306a36Sopenharmony_ci   to stop delivering the interrupt.
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ciFollowing changes are needed to support hierarchy irq_domain:
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci1) a new field 'parent' is added to struct irq_domain; it's used to
25962306a36Sopenharmony_ci   maintain irq_domain hierarchy information.
26062306a36Sopenharmony_ci2) a new field 'parent_data' is added to struct irq_data; it's used to
26162306a36Sopenharmony_ci   build hierarchy irq_data to match hierarchy irq_domains. The irq_data
26262306a36Sopenharmony_ci   is used to store irq_domain pointer and hardware irq number.
26362306a36Sopenharmony_ci3) new callbacks are added to struct irq_domain_ops to support hierarchy
26462306a36Sopenharmony_ci   irq_domain operations.
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ciWith support of hierarchy irq_domain and hierarchy irq_data ready, an
26762306a36Sopenharmony_ciirq_domain structure is built for each interrupt controller, and an
26862306a36Sopenharmony_ciirq_data structure is allocated for each irq_domain associated with an
26962306a36Sopenharmony_ciIRQ. Now we could go one step further to support stacked(hierarchy)
27062306a36Sopenharmony_ciirq_chip. That is, an irq_chip is associated with each irq_data along
27162306a36Sopenharmony_cithe hierarchy. A child irq_chip may implement a required action by
27262306a36Sopenharmony_ciitself or by cooperating with its parent irq_chip.
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ciWith stacked irq_chip, interrupt controller driver only needs to deal
27562306a36Sopenharmony_ciwith the hardware managed by itself and may ask for services from its
27662306a36Sopenharmony_ciparent irq_chip when needed. So we could achieve a much cleaner
27762306a36Sopenharmony_cisoftware architecture.
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ciFor an interrupt controller driver to support hierarchy irq_domain, it
28062306a36Sopenharmony_cineeds to:
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci1) Implement irq_domain_ops.alloc and irq_domain_ops.free
28362306a36Sopenharmony_ci2) Optionally implement irq_domain_ops.activate and
28462306a36Sopenharmony_ci   irq_domain_ops.deactivate.
28562306a36Sopenharmony_ci3) Optionally implement an irq_chip to manage the interrupt controller
28662306a36Sopenharmony_ci   hardware.
28762306a36Sopenharmony_ci4) No need to implement irq_domain_ops.map and irq_domain_ops.unmap,
28862306a36Sopenharmony_ci   they are unused with hierarchy irq_domain.
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ciHierarchy irq_domain is in no way x86 specific, and is heavily used to
29162306a36Sopenharmony_cisupport other architectures, such as ARM, ARM64 etc.
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ciDebugging
29462306a36Sopenharmony_ci=========
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ciMost of the internals of the IRQ subsystem are exposed in debugfs by
29762306a36Sopenharmony_citurning CONFIG_GENERIC_IRQ_DEBUGFS on.
298