1 /* 2 * Copyright (C) 2004 Matthew Wilcox <matthew@wil.cx> 3 * Copyright (C) 2004 Intel Corp. 4 * 5 * This code is released under the GNU General Public License version 2. 6 */ 7 8 /* 9 * mmconfig.c - Low-level direct PCI config space access via MMCONFIG 10 */ 11 12 #include <linux/pci.h> 13 #include <linux/init.h> 14 #include <linux/acpi.h> 15 #include <asm/e820.h> 16 #include "pci.h" 17 18 /* Assume systems with more busses have correct MCFG */ 19 #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) 20 21 /* The base address of the last MMCONFIG device accessed */ 22 static u32 mmcfg_last_accessed_device; 23 static int mmcfg_last_accessed_cpu; 24 25 /* 26 * Functions for accessing PCI configuration space with MMCONFIG accesses 27 */ 28 static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn) 29 { 30 struct acpi_mcfg_allocation *cfg; 31 int cfg_num; 32 33 if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS && 34 test_bit(PCI_SLOT(devfn) + 32*bus, pci_mmcfg_fallback_slots)) 35 return 0; 36 37 for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) { 38 cfg = &pci_mmcfg_config[cfg_num]; 39 if (cfg->pci_segment == seg && 40 (cfg->start_bus_number <= bus) && 41 (cfg->end_bus_number >= bus)) 42 return cfg->address; 43 } 44 45 /* Fall back to type 0 */ 46 return 0; 47 } 48 49 /* 50 * This is always called under pci_config_lock 51 */ 52 static void pci_exp_set_dev_base(unsigned int base, int bus, int devfn) 53 { 54 u32 dev_base = base | (bus << 20) | (devfn << 12); 55 int cpu = smp_processor_id(); 56 if (dev_base != mmcfg_last_accessed_device || 57 cpu != mmcfg_last_accessed_cpu) { 58 mmcfg_last_accessed_device = dev_base; 59 mmcfg_last_accessed_cpu = cpu; 60 set_fixmap_nocache(FIX_PCIE_MCFG, dev_base); 61 } 62 } 63 64 static int pci_mmcfg_read(unsigned int seg, unsigned int bus, 65 unsigned int devfn, int reg, int len, u32 *value) 66 { 67 unsigned long flags; 68 u32 base; 69 70 if ((bus > 255) || (devfn > 255) || (reg > 4095)) { 71 *value = -1; 72 return -EINVAL; 73 } 74 75 base = get_base_addr(seg, bus, devfn); 76 if (!base) 77 return pci_conf1_read(seg,bus,devfn,reg,len,value); 78 79 spin_lock_irqsave(&pci_config_lock, flags); 80 81 pci_exp_set_dev_base(base, bus, devfn); 82 83 switch (len) { 84 case 1: 85 *value = mmio_config_readb(mmcfg_virt_addr + reg); 86 break; 87 case 2: 88 *value = mmio_config_readw(mmcfg_virt_addr + reg); 89 break; 90 case 4: 91 *value = mmio_config_readl(mmcfg_virt_addr + reg); 92 break; 93 } 94 spin_unlock_irqrestore(&pci_config_lock, flags); 95 96 return 0; 97 } 98 99 static int pci_mmcfg_write(unsigned int seg, unsigned int bus, 100 unsigned int devfn, int reg, int len, u32 value) 101 { 102 unsigned long flags; 103 u32 base; 104 105 if ((bus > 255) || (devfn > 255) || (reg > 4095)) 106 return -EINVAL; 107 108 base = get_base_addr(seg, bus, devfn); 109 if (!base) 110 return pci_conf1_write(seg,bus,devfn,reg,len,value); 111 112 spin_lock_irqsave(&pci_config_lock, flags); 113 114 pci_exp_set_dev_base(base, bus, devfn); 115 116 switch (len) { 117 case 1: 118 mmio_config_writeb(mmcfg_virt_addr + reg, value); 119 break; 120 case 2: 121 mmio_config_writew(mmcfg_virt_addr + reg, value); 122 break; 123 case 4: 124 mmio_config_writel(mmcfg_virt_addr + reg, value); 125 break; 126 } 127 spin_unlock_irqrestore(&pci_config_lock, flags); 128 129 return 0; 130 } 131 132 static struct pci_raw_ops pci_mmcfg = { 133 .read = pci_mmcfg_read, 134 .write = pci_mmcfg_write, 135 }; 136 137 int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus, 138 unsigned int devfn) 139 { 140 return get_base_addr(seg, bus, devfn) != 0; 141 } 142 143 int __init pci_mmcfg_arch_init(void) 144 { 145 printk(KERN_INFO "PCI: Using MMCONFIG\n"); 146 raw_pci_ops = &pci_mmcfg; 147 return 1; 148 } 149