summaryrefslogtreecommitdiff
path: root/arch/x86/include/asm/pirq_routing.h
blob: 0afcb4615e9c9fd37845b03d61e3693cbecbca9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
 *
 * Ported from coreboot src/arch/x86/include/arch/pirq_routing.h
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#ifndef _PIRQ_ROUTING_H_
#define _PIRQ_ROUTING_H_

/*
 * This is the maximum number on interrupt entries that a PCI device may have.
 *   This is NOT the number of slots or devices in the system
 *   This is NOT the number of entries in the PIRQ table
 *
 * This tells us that in the PIRQ table, we are going to have 4 link-bitmap
 * entries per PCI device which is fixed at 4: INTA, INTB, INTC, and INTD.
 *
 * CAUTION: If you change this, PIRQ routing will not work correctly.
 */
#define MAX_INTX_ENTRIES	4

#define PIRQ_SIGNATURE		\
	(('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
#define PIRQ_VERSION		0x0100

struct __packed irq_info {
	u8 bus;			/* Bus number */
	u8 devfn;		/* Device and function number */
	struct __packed {
		u8 link;	/* IRQ line ID, 0=not routed */
		u16 bitmap;	/* Available IRQs */
	} irq[MAX_INTX_ENTRIES];
	u8 slot;		/* Slot number, 0=onboard */
	u8 rfu;
};

struct __packed irq_routing_table {
	u32 signature;		/* PIRQ_SIGNATURE */
	u16 version;		/* PIRQ_VERSION */
	u16 size;		/* Table size in bytes */
	u8 rtr_bus;		/* busno of the interrupt router */
	u8 rtr_devfn;		/* devfn of the interrupt router */
	u16 exclusive_irqs;	/* IRQs devoted exclusively to PCI usage */
	u16 rtr_vendor;		/* Vendor ID of the interrupt router */
	u16 rtr_device;		/* Device ID of the interrupt router */
	u32 miniport_data;
	u8 rfu[11];
	u8 checksum;		/* Modulo 256 checksum must give zero */
	struct irq_info slots[CONFIG_IRQ_SLOT_COUNT];
};

/**
 * get_irq_slot_count() - Get the number of entries in the irq_info table
 *
 * This calculates the number of entries for the irq_info table.
 *
 * @rt:		pointer to the base address of the struct irq_info
 * @return:	number of entries
 */
static inline int get_irq_slot_count(struct irq_routing_table *rt)
{
	return (rt->size - 32) / sizeof(struct irq_info);
}

/**
 * pirq_check_irq_routed() - Check whether an IRQ is routed to 8259 PIC
 *
 * This function checks whether an IRQ is routed to 8259 PIC for a given link.
 *
 * Note: this function should be provided by the platform codes, as the
 * implementation of interrupt router may be different.
 *
 * @dev:	irq router's udevice
 * @link:	link number which represents a PIRQ
 * @irq:	the 8259 IRQ number
 * @return:	true if the irq is already routed to 8259 for a given link,
 *		false elsewise
 */
bool pirq_check_irq_routed(struct udevice *dev, int link, u8 irq);

/**
 * pirq_translate_link() - Translate a link value
 *
 * This function translates a platform-specific link value to a link number.
 * On Intel platforms, the link value is normally a offset into the PCI
 * configuration space into the legacy bridge.
 *
 * Note: this function should be provided by the platform codes, as the
 * implementation of interrupt router may be different.
 *
 * @dev:	irq router's udevice
 * @link:	platform-specific link value
 * @return:	link number which represents a PIRQ
 */
int pirq_translate_link(struct udevice *dev, int link);

/**
 * pirq_assign_irq() - Assign an IRQ to a PIRQ link
 *
 * This function assigns the IRQ to a PIRQ link so that the PIRQ is routed to
 * the 8259 PIC.
 *
 * Note: this function should be provided by the platform codes, as the
 * implementation of interrupt router may be different.
 *
 * @dev:	irq router's udevice
 * @link:	link number which represents a PIRQ
 * @irq:	IRQ to which the PIRQ is routed
 */
void pirq_assign_irq(struct udevice *dev, int link, u8 irq);

/**
 * pirq_route_irqs() - Route PIRQs to 8259 PIC
 *
 * This function configures all PCI devices' interrupt pins and maps them to
 * PIRQs and finally 8259 PIC. The routed irq number is written to interrupt
 * line register in the configuration space of the PCI device for OS to use.
 * The configuration source is taken from a struct irq_info table, the format
 * of which is defined in PIRQ routing table spec and PCI BIOS spec.
 *
 * @dev:	irq router's udevice
 * @irq:	pointer to the base address of the struct irq_info
 * @num:	number of entries in the struct irq_info
 */
void pirq_route_irqs(struct udevice *dev, struct irq_info *irq, int num);

/**
 * copy_pirq_routing_table() - Copy a PIRQ routing table
 *
 * This helper function copies the given PIRQ routing table to a given address.
 * Before copying, it does several sanity tests against the PIRQ routing table.
 * It also fixes up the table checksum and align the given address to a 16 byte
 * boundary to meet the PIRQ routing table spec requirements.
 *
 * @addr:	address to store the copied PIRQ routing table
 * @rt:		pointer to the PIRQ routing table to copy from
 * @return:	end address of the copied PIRQ routing table
 */
u32 copy_pirq_routing_table(u32 addr, struct irq_routing_table *rt);

#endif /* _PIRQ_ROUTING_H_ */