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