Skip to content

Commit 6b79164

Browse files
maciej-w-rozyckiKAGA-KOKO
authored andcommitted
x86/PCI: Add support for the Intel 82374EB/82374SB (ESC) PIRQ router
The Intel 82374EB/82374SB EISA System Component (ESC) devices implement PCI interrupt steering with a PIRQ router[1] in the form of four PIRQ Route Control registers, available in the port I/O space accessible indirectly via the index/data register pair at 0x22/0x23, located at indices 0x60/0x61/0x62/0x63 for the PIRQ0/1/2/3# lines respectively. The semantics is the same as with the PIIX router, however it is not clear if BIOSes use register indices or line numbers as the cookie to identify PCI interrupts in their routing tables and therefore support either scheme. Accesses to the port I/O space concerned here need to be unlocked by writing the value of 0x0f to the ESC ID Register at index 0x02 beforehand[2]. Do so then and then lock access after use for safety. This locking could possibly interfere with accesses to the Intel MP spec IMCR register, implemented by the 82374SB variant of the ESC only as the PCI/APIC Control Register at index 0x70[3], for which leaving access to the configuration space concerned unlocked may have been a requirement for the BIOS to remain compliant with the MP spec. However we only poke at the IMCR register if the APIC mode is used, in which case the PIRQ router is not, so this arrangement is not going to interfere with IMCR access code. The ESC is implemented as a part of the combined southbridge also made of 82375EB/82375SB PCI-EISA Bridge (PCEB) and does itself appear in the PCI configuration space. Use the PCEB's device identification then for determining the presence of the ESC. References: [1] "82374EB/82374SB EISA System Component (ESC)", Intel Corporation, Order Number: 290476-004, March 1996, Section 3.1.12 "PIRQ[0:3]#--PIRQ Route Control Registers", pp. 44-45 [2] same, Section 3.1.1 "ESCID--ESC ID Register", p. 36 [3] same, Section 3.1.17 "PAC--PCI/APIC Control Register", p. 47 Signed-off-by: Maciej W. Rozycki <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 1ce849c commit 6b79164

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

arch/x86/pci/irq.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,74 @@ static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, i
357357
return 0;
358358
}
359359

360+
/*
361+
* PIRQ routing for the 82374EB/82374SB EISA System Component (ESC)
362+
* ASIC used with the Intel 82420 and 82430 PCIsets. The ESC is not
363+
* decoded in the PCI configuration space, so we identify it by the
364+
* accompanying 82375EB/82375SB PCI-EISA Bridge (PCEB) ASIC.
365+
*
366+
* There are four PIRQ Route Control registers, available in the
367+
* port I/O space accessible indirectly via the index/data register
368+
* pair at 0x22/0x23, located at indices 0x60/0x61/0x62/0x63 for the
369+
* PIRQ0/1/2/3# lines respectively. The semantics is the same as
370+
* with the PIIX router.
371+
*
372+
* Accesses to the port I/O space concerned here need to be unlocked
373+
* by writing the value of 0x0f to the ESC ID Register at index 0x02
374+
* beforehand. Any other value written to said register prevents
375+
* further accesses from reaching the register file, except for the
376+
* ESC ID Register being written with 0x0f again.
377+
*
378+
* References:
379+
*
380+
* "82374EB/82374SB EISA System Component (ESC)", Intel Corporation,
381+
* Order Number: 290476-004, March 1996
382+
*
383+
* "82375EB/82375SB PCI-EISA Bridge (PCEB)", Intel Corporation, Order
384+
* Number: 290477-004, March 1996
385+
*/
386+
387+
#define PC_CONF_I82374_ESC_ID 0x02u
388+
#define PC_CONF_I82374_PIRQ_ROUTE_CONTROL 0x60u
389+
390+
#define PC_CONF_I82374_ESC_ID_KEY 0x0fu
391+
392+
static int pirq_esc_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
393+
{
394+
unsigned long flags;
395+
int reg;
396+
u8 x;
397+
398+
reg = pirq;
399+
if (reg >= 1 && reg <= 4)
400+
reg += PC_CONF_I82374_PIRQ_ROUTE_CONTROL - 1;
401+
402+
raw_spin_lock_irqsave(&pc_conf_lock, flags);
403+
pc_conf_set(PC_CONF_I82374_ESC_ID, PC_CONF_I82374_ESC_ID_KEY);
404+
x = pc_conf_get(reg);
405+
pc_conf_set(PC_CONF_I82374_ESC_ID, 0);
406+
raw_spin_unlock_irqrestore(&pc_conf_lock, flags);
407+
return (x < 16) ? x : 0;
408+
}
409+
410+
static int pirq_esc_set(struct pci_dev *router, struct pci_dev *dev, int pirq,
411+
int irq)
412+
{
413+
unsigned long flags;
414+
int reg;
415+
416+
reg = pirq;
417+
if (reg >= 1 && reg <= 4)
418+
reg += PC_CONF_I82374_PIRQ_ROUTE_CONTROL - 1;
419+
420+
raw_spin_lock_irqsave(&pc_conf_lock, flags);
421+
pc_conf_set(PC_CONF_I82374_ESC_ID, PC_CONF_I82374_ESC_ID_KEY);
422+
pc_conf_set(reg, irq);
423+
pc_conf_set(PC_CONF_I82374_ESC_ID, 0);
424+
raw_spin_unlock_irqrestore(&pc_conf_lock, flags);
425+
return 1;
426+
}
427+
360428
/*
361429
* The Intel PIIX4 pirq rules are fairly simple: "pirq" is
362430
* just a pointer to the config space.
@@ -687,6 +755,11 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route
687755
return 0;
688756

689757
switch (device) {
758+
case PCI_DEVICE_ID_INTEL_82375:
759+
r->name = "PCEB/ESC";
760+
r->get = pirq_esc_get;
761+
r->set = pirq_esc_set;
762+
return 1;
690763
case PCI_DEVICE_ID_INTEL_82371FB_0:
691764
case PCI_DEVICE_ID_INTEL_82371SB_0:
692765
case PCI_DEVICE_ID_INTEL_82371AB_0:

0 commit comments

Comments
 (0)