1b5b6b019SBin Meng /*
2b5b6b019SBin Meng * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
3b5b6b019SBin Meng *
4b5b6b019SBin Meng * Ported from coreboot src/arch/x86/include/arch/pirq_routing.h
5b5b6b019SBin Meng *
6b5b6b019SBin Meng * SPDX-License-Identifier: GPL-2.0+
7b5b6b019SBin Meng */
8b5b6b019SBin Meng
9b5b6b019SBin Meng #ifndef _PIRQ_ROUTING_H_
10b5b6b019SBin Meng #define _PIRQ_ROUTING_H_
11b5b6b019SBin Meng
12b5b6b019SBin Meng /*
13b5b6b019SBin Meng * This is the maximum number on interrupt entries that a PCI device may have.
14b5b6b019SBin Meng * This is NOT the number of slots or devices in the system
15b5b6b019SBin Meng * This is NOT the number of entries in the PIRQ table
16b5b6b019SBin Meng *
17b5b6b019SBin Meng * This tells us that in the PIRQ table, we are going to have 4 link-bitmap
18b5b6b019SBin Meng * entries per PCI device which is fixed at 4: INTA, INTB, INTC, and INTD.
19b5b6b019SBin Meng *
20b5b6b019SBin Meng * CAUTION: If you change this, PIRQ routing will not work correctly.
21b5b6b019SBin Meng */
22b5b6b019SBin Meng #define MAX_INTX_ENTRIES 4
23b5b6b019SBin Meng
24b5b6b019SBin Meng #define PIRQ_SIGNATURE \
25b5b6b019SBin Meng (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
26b5b6b019SBin Meng #define PIRQ_VERSION 0x0100
27b5b6b019SBin Meng
28b5b6b019SBin Meng struct __packed irq_info {
29b5b6b019SBin Meng u8 bus; /* Bus number */
30b5b6b019SBin Meng u8 devfn; /* Device and function number */
31b5b6b019SBin Meng struct __packed {
32b5b6b019SBin Meng u8 link; /* IRQ line ID, 0=not routed */
33b5b6b019SBin Meng u16 bitmap; /* Available IRQs */
34b5b6b019SBin Meng } irq[MAX_INTX_ENTRIES];
35b5b6b019SBin Meng u8 slot; /* Slot number, 0=onboard */
36b5b6b019SBin Meng u8 rfu;
37b5b6b019SBin Meng };
38b5b6b019SBin Meng
39b5b6b019SBin Meng struct __packed irq_routing_table {
40b5b6b019SBin Meng u32 signature; /* PIRQ_SIGNATURE */
41b5b6b019SBin Meng u16 version; /* PIRQ_VERSION */
42b5b6b019SBin Meng u16 size; /* Table size in bytes */
43b5b6b019SBin Meng u8 rtr_bus; /* busno of the interrupt router */
44b5b6b019SBin Meng u8 rtr_devfn; /* devfn of the interrupt router */
45b5b6b019SBin Meng u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */
46b5b6b019SBin Meng u16 rtr_vendor; /* Vendor ID of the interrupt router */
47b5b6b019SBin Meng u16 rtr_device; /* Device ID of the interrupt router */
48b5b6b019SBin Meng u32 miniport_data;
49b5b6b019SBin Meng u8 rfu[11];
50b5b6b019SBin Meng u8 checksum; /* Modulo 256 checksum must give zero */
51b5b6b019SBin Meng struct irq_info slots[CONFIG_IRQ_SLOT_COUNT];
52b5b6b019SBin Meng };
53b5b6b019SBin Meng
54b5b6b019SBin Meng /**
55b5b6b019SBin Meng * get_irq_slot_count() - Get the number of entries in the irq_info table
56b5b6b019SBin Meng *
57b5b6b019SBin Meng * This calculates the number of entries for the irq_info table.
58b5b6b019SBin Meng *
59b5b6b019SBin Meng * @rt: pointer to the base address of the struct irq_info
60b5b6b019SBin Meng * @return: number of entries
61b5b6b019SBin Meng */
get_irq_slot_count(struct irq_routing_table * rt)62b5b6b019SBin Meng static inline int get_irq_slot_count(struct irq_routing_table *rt)
63b5b6b019SBin Meng {
64b5b6b019SBin Meng return (rt->size - 32) / sizeof(struct irq_info);
65b5b6b019SBin Meng }
66b5b6b019SBin Meng
67b5b6b019SBin Meng /**
68b5b6b019SBin Meng * pirq_check_irq_routed() - Check whether an IRQ is routed to 8259 PIC
69b5b6b019SBin Meng *
70b5b6b019SBin Meng * This function checks whether an IRQ is routed to 8259 PIC for a given link.
71b5b6b019SBin Meng *
72b5b6b019SBin Meng * Note: this function should be provided by the platform codes, as the
73b5b6b019SBin Meng * implementation of interrupt router may be different.
74b5b6b019SBin Meng *
75*b46c2088SBin Meng * @dev: irq router's udevice
76b5b6b019SBin Meng * @link: link number which represents a PIRQ
77b5b6b019SBin Meng * @irq: the 8259 IRQ number
78b5b6b019SBin Meng * @return: true if the irq is already routed to 8259 for a given link,
79b5b6b019SBin Meng * false elsewise
80b5b6b019SBin Meng */
81*b46c2088SBin Meng bool pirq_check_irq_routed(struct udevice *dev, int link, u8 irq);
82b5b6b019SBin Meng
83b5b6b019SBin Meng /**
84b5b6b019SBin Meng * pirq_translate_link() - Translate a link value
85b5b6b019SBin Meng *
86b5b6b019SBin Meng * This function translates a platform-specific link value to a link number.
87b5b6b019SBin Meng * On Intel platforms, the link value is normally a offset into the PCI
88b5b6b019SBin Meng * configuration space into the legacy bridge.
89b5b6b019SBin Meng *
90b5b6b019SBin Meng * Note: this function should be provided by the platform codes, as the
91b5b6b019SBin Meng * implementation of interrupt router may be different.
92b5b6b019SBin Meng *
93*b46c2088SBin Meng * @dev: irq router's udevice
94b5b6b019SBin Meng * @link: platform-specific link value
95b5b6b019SBin Meng * @return: link number which represents a PIRQ
96b5b6b019SBin Meng */
97*b46c2088SBin Meng int pirq_translate_link(struct udevice *dev, int link);
98b5b6b019SBin Meng
99b5b6b019SBin Meng /**
100b5b6b019SBin Meng * pirq_assign_irq() - Assign an IRQ to a PIRQ link
101b5b6b019SBin Meng *
102b5b6b019SBin Meng * This function assigns the IRQ to a PIRQ link so that the PIRQ is routed to
103b5b6b019SBin Meng * the 8259 PIC.
104b5b6b019SBin Meng *
105b5b6b019SBin Meng * Note: this function should be provided by the platform codes, as the
106b5b6b019SBin Meng * implementation of interrupt router may be different.
107b5b6b019SBin Meng *
108*b46c2088SBin Meng * @dev: irq router's udevice
109b5b6b019SBin Meng * @link: link number which represents a PIRQ
110b5b6b019SBin Meng * @irq: IRQ to which the PIRQ is routed
111b5b6b019SBin Meng */
112*b46c2088SBin Meng void pirq_assign_irq(struct udevice *dev, int link, u8 irq);
113b5b6b019SBin Meng
114b5b6b019SBin Meng /**
115b5b6b019SBin Meng * pirq_route_irqs() - Route PIRQs to 8259 PIC
116b5b6b019SBin Meng *
117b5b6b019SBin Meng * This function configures all PCI devices' interrupt pins and maps them to
118b5b6b019SBin Meng * PIRQs and finally 8259 PIC. The routed irq number is written to interrupt
119b5b6b019SBin Meng * line register in the configuration space of the PCI device for OS to use.
120b5b6b019SBin Meng * The configuration source is taken from a struct irq_info table, the format
121b5b6b019SBin Meng * of which is defined in PIRQ routing table spec and PCI BIOS spec.
122b5b6b019SBin Meng *
123*b46c2088SBin Meng * @dev: irq router's udevice
124b5b6b019SBin Meng * @irq: pointer to the base address of the struct irq_info
125b5b6b019SBin Meng * @num: number of entries in the struct irq_info
126b5b6b019SBin Meng */
127*b46c2088SBin Meng void pirq_route_irqs(struct udevice *dev, struct irq_info *irq, int num);
128b5b6b019SBin Meng
129b5b6b019SBin Meng /**
130b5b6b019SBin Meng * copy_pirq_routing_table() - Copy a PIRQ routing table
131b5b6b019SBin Meng *
132b5b6b019SBin Meng * This helper function copies the given PIRQ routing table to a given address.
133b5b6b019SBin Meng * Before copying, it does several sanity tests against the PIRQ routing table.
134b5b6b019SBin Meng * It also fixes up the table checksum and align the given address to a 16 byte
135b5b6b019SBin Meng * boundary to meet the PIRQ routing table spec requirements.
136b5b6b019SBin Meng *
137b5b6b019SBin Meng * @addr: address to store the copied PIRQ routing table
138b5b6b019SBin Meng * @rt: pointer to the PIRQ routing table to copy from
139b5b6b019SBin Meng * @return: end address of the copied PIRQ routing table
140b5b6b019SBin Meng */
141b5b6b019SBin Meng u32 copy_pirq_routing_table(u32 addr, struct irq_routing_table *rt);
142b5b6b019SBin Meng
143b5b6b019SBin Meng #endif /* _PIRQ_ROUTING_H_ */
144