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