MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / arch / i386 / pci / mmconfig.c
blobf42c45305bb5bcbe054a82e8a681bfa3dae6bf5d
1 /*
2 * Copyright (C) 2004 Matthew Wilcox <matthew@wil.cx>
3 * Copyright (C) 2004 Intel Corp.
5 * This code is released under the GNU General Public License version 2.
6 */
8 /*
9 * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
12 #include <linux/pci.h>
13 #include <linux/init.h>
14 #include "pci.h"
16 /* The physical address of the MMCONFIG aperture. Set from ACPI tables. */
17 u32 pci_mmcfg_base_addr;
19 #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
21 /* The base address of the last MMCONFIG device accessed */
22 static u32 mmcfg_last_accessed_device;
25 * Functions for accessing PCI configuration space with MMCONFIG accesses
28 static inline void pci_exp_set_dev_base(int bus, int devfn)
30 u32 dev_base = pci_mmcfg_base_addr | (bus << 20) | (devfn << 12);
31 if (dev_base != mmcfg_last_accessed_device) {
32 mmcfg_last_accessed_device = dev_base;
33 set_fixmap(FIX_PCIE_MCFG, dev_base);
37 static int pci_mmcfg_read(int seg, int bus, int devfn, int reg, int len, u32 *value)
39 unsigned long flags;
41 if (!value || (bus > 255) || (devfn > 255) || (reg > 4095))
42 return -EINVAL;
44 spin_lock_irqsave(&pci_config_lock, flags);
46 pci_exp_set_dev_base(bus, devfn);
48 switch (len) {
49 case 1:
50 *value = readb(mmcfg_virt_addr + reg);
51 break;
52 case 2:
53 *value = readw(mmcfg_virt_addr + reg);
54 break;
55 case 4:
56 *value = readl(mmcfg_virt_addr + reg);
57 break;
60 spin_unlock_irqrestore(&pci_config_lock, flags);
62 return 0;
65 static int pci_mmcfg_write(int seg, int bus, int devfn, int reg, int len, u32 value)
67 unsigned long flags;
69 if ((bus > 255) || (devfn > 255) || (reg > 4095))
70 return -EINVAL;
72 spin_lock_irqsave(&pci_config_lock, flags);
74 pci_exp_set_dev_base(bus, devfn);
76 switch (len) {
77 case 1:
78 writeb(value, mmcfg_virt_addr + reg);
79 break;
80 case 2:
81 writew(value, mmcfg_virt_addr + reg);
82 break;
83 case 4:
84 writel(value, mmcfg_virt_addr + reg);
85 break;
88 /* Dummy read to flush PCI write */
89 readl(mmcfg_virt_addr);
91 spin_unlock_irqrestore(&pci_config_lock, flags);
93 return 0;
96 static struct pci_raw_ops pci_mmcfg = {
97 .read = pci_mmcfg_read,
98 .write = pci_mmcfg_write,
101 static int __init pci_mmcfg_init(void)
103 if ((pci_probe & PCI_PROBE_MMCONF) == 0)
104 goto out;
105 if (!pci_mmcfg_base_addr)
106 goto out;
108 printk(KERN_INFO "PCI: Using MMCONFIG\n");
109 raw_pci_ops = &pci_mmcfg;
110 pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
112 out:
113 return 0;
116 arch_initcall(pci_mmcfg_init);