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