| 1 | // SPDX-License-Identifier: GPL-2.0 | 
|---|
| 2 | /* | 
|---|
| 3 | * Primary to Sideband (P2SB) bridge access support | 
|---|
| 4 | * | 
|---|
| 5 | * Copyright (c) 2017, 2021-2022 Intel Corporation. | 
|---|
| 6 | * | 
|---|
| 7 | * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 
|---|
| 8 | *	    Jonathan Yong <jonathan.yong@intel.com> | 
|---|
| 9 | */ | 
|---|
| 10 |  | 
|---|
| 11 | #include <linux/bits.h> | 
|---|
| 12 | #include <linux/export.h> | 
|---|
| 13 | #include <linux/pci.h> | 
|---|
| 14 | #include <linux/platform_data/x86/p2sb.h> | 
|---|
| 15 |  | 
|---|
| 16 | #include <asm/cpu_device_id.h> | 
|---|
| 17 | #include <asm/intel-family.h> | 
|---|
| 18 |  | 
|---|
| 19 | #define P2SBC			0xe0 | 
|---|
| 20 | #define P2SBC_HIDE		BIT(8) | 
|---|
| 21 |  | 
|---|
| 22 | #define P2SB_DEVFN_DEFAULT	PCI_DEVFN(31, 1) | 
|---|
| 23 | #define P2SB_DEVFN_GOLDMONT	PCI_DEVFN(13, 0) | 
|---|
| 24 | #define SPI_DEVFN_GOLDMONT	PCI_DEVFN(13, 2) | 
|---|
| 25 |  | 
|---|
| 26 | static const struct x86_cpu_id p2sb_cpu_ids[] = { | 
|---|
| 27 | X86_MATCH_VFM(INTEL_ATOM_GOLDMONT, P2SB_DEVFN_GOLDMONT), | 
|---|
| 28 | X86_MATCH_VFM(INTEL_ATOM_GOLDMONT_PLUS, P2SB_DEVFN_GOLDMONT), | 
|---|
| 29 | {} | 
|---|
| 30 | }; | 
|---|
| 31 |  | 
|---|
| 32 | /* | 
|---|
| 33 | * Cache BAR0 of P2SB device functions 0 to 7. | 
|---|
| 34 | * TODO: The constant 8 is the number of functions that PCI specification | 
|---|
| 35 | *       defines. Same definitions exist tree-wide. Unify this definition and | 
|---|
| 36 | *       the other definitions then move to include/uapi/linux/pci.h. | 
|---|
| 37 | */ | 
|---|
| 38 | #define NR_P2SB_RES_CACHE 8 | 
|---|
| 39 |  | 
|---|
| 40 | struct p2sb_res_cache { | 
|---|
| 41 | u32 bus_dev_id; | 
|---|
| 42 | struct resource res; | 
|---|
| 43 | }; | 
|---|
| 44 |  | 
|---|
| 45 | static struct p2sb_res_cache p2sb_resources[NR_P2SB_RES_CACHE]; | 
|---|
| 46 | static bool p2sb_hidden_by_bios; | 
|---|
| 47 |  | 
|---|
| 48 | static void p2sb_get_devfn(unsigned int *devfn) | 
|---|
| 49 | { | 
|---|
| 50 | unsigned int fn = P2SB_DEVFN_DEFAULT; | 
|---|
| 51 | const struct x86_cpu_id *id; | 
|---|
| 52 |  | 
|---|
| 53 | id = x86_match_cpu(match: p2sb_cpu_ids); | 
|---|
| 54 | if (id) | 
|---|
| 55 | fn = (unsigned int)id->driver_data; | 
|---|
| 56 |  | 
|---|
| 57 | *devfn = fn; | 
|---|
| 58 | } | 
|---|
| 59 |  | 
|---|
| 60 | static bool p2sb_valid_resource(const struct resource *res) | 
|---|
| 61 | { | 
|---|
| 62 | return res->flags & ~IORESOURCE_UNSET; | 
|---|
| 63 | } | 
|---|
| 64 |  | 
|---|
| 65 | /* Copy resource from the first BAR of the device in question */ | 
|---|
| 66 | static void p2sb_read_bar0(struct pci_dev *pdev, struct resource *mem) | 
|---|
| 67 | { | 
|---|
| 68 | struct resource *bar0 = pci_resource_n(pdev, 0); | 
|---|
| 69 |  | 
|---|
| 70 | /* Make sure we have no dangling pointers in the output */ | 
|---|
| 71 | memset(s: mem, c: 0, n: sizeof(*mem)); | 
|---|
| 72 |  | 
|---|
| 73 | /* | 
|---|
| 74 | * We copy only selected fields from the original resource. | 
|---|
| 75 | * Because a PCI device will be removed soon, we may not use | 
|---|
| 76 | * any allocated data, hence we may not copy any pointers. | 
|---|
| 77 | */ | 
|---|
| 78 | mem->start = bar0->start; | 
|---|
| 79 | mem->end = bar0->end; | 
|---|
| 80 | mem->flags = bar0->flags; | 
|---|
| 81 | mem->desc = bar0->desc; | 
|---|
| 82 | } | 
|---|
| 83 |  | 
|---|
| 84 | static void p2sb_scan_and_cache_devfn(struct pci_bus *bus, unsigned int devfn) | 
|---|
| 85 | { | 
|---|
| 86 | struct p2sb_res_cache *cache = &p2sb_resources[PCI_FUNC(devfn)]; | 
|---|
| 87 | struct pci_dev *pdev; | 
|---|
| 88 |  | 
|---|
| 89 | pdev = pci_scan_single_device(bus, devfn); | 
|---|
| 90 | if (!pdev) | 
|---|
| 91 | return; | 
|---|
| 92 |  | 
|---|
| 93 | p2sb_read_bar0(pdev, mem: &cache->res); | 
|---|
| 94 | cache->bus_dev_id = bus->dev.id; | 
|---|
| 95 |  | 
|---|
| 96 | pci_stop_and_remove_bus_device(dev: pdev); | 
|---|
| 97 | } | 
|---|
| 98 |  | 
|---|
| 99 | static int p2sb_scan_and_cache(struct pci_bus *bus, unsigned int devfn) | 
|---|
| 100 | { | 
|---|
| 101 | /* | 
|---|
| 102 | * The BIOS prevents the P2SB device from being enumerated by the PCI | 
|---|
| 103 | * subsystem, so we need to unhide and hide it back to lookup the BAR. | 
|---|
| 104 | */ | 
|---|
| 105 | pci_bus_write_config_dword(bus, devfn, P2SBC, val: 0); | 
|---|
| 106 |  | 
|---|
| 107 | /* Scan the P2SB device and cache its BAR0 */ | 
|---|
| 108 | p2sb_scan_and_cache_devfn(bus, devfn); | 
|---|
| 109 |  | 
|---|
| 110 | /* On Goldmont p2sb_bar() also gets called for the SPI controller */ | 
|---|
| 111 | if (devfn == P2SB_DEVFN_GOLDMONT) | 
|---|
| 112 | p2sb_scan_and_cache_devfn(bus, SPI_DEVFN_GOLDMONT); | 
|---|
| 113 |  | 
|---|
| 114 | pci_bus_write_config_dword(bus, devfn, P2SBC, P2SBC_HIDE); | 
|---|
| 115 |  | 
|---|
| 116 | if (!p2sb_valid_resource(res: &p2sb_resources[PCI_FUNC(devfn)].res)) | 
|---|
| 117 | return -ENOENT; | 
|---|
| 118 |  | 
|---|
| 119 | return 0; | 
|---|
| 120 | } | 
|---|
| 121 |  | 
|---|
| 122 | static struct pci_bus *p2sb_get_bus(struct pci_bus *bus) | 
|---|
| 123 | { | 
|---|
| 124 | static struct pci_bus *p2sb_bus; | 
|---|
| 125 |  | 
|---|
| 126 | bus = bus ?: p2sb_bus; | 
|---|
| 127 | if (bus) | 
|---|
| 128 | return bus; | 
|---|
| 129 |  | 
|---|
| 130 | /* Assume P2SB is on the bus 0 in domain 0 */ | 
|---|
| 131 | p2sb_bus = pci_find_bus(domain: 0, busnr: 0); | 
|---|
| 132 | return p2sb_bus; | 
|---|
| 133 | } | 
|---|
| 134 |  | 
|---|
| 135 | static int p2sb_cache_resources(void) | 
|---|
| 136 | { | 
|---|
| 137 | unsigned int devfn_p2sb; | 
|---|
| 138 | u32 value = P2SBC_HIDE; | 
|---|
| 139 | struct pci_bus *bus; | 
|---|
| 140 | u16 class; | 
|---|
| 141 | int ret = 0; | 
|---|
| 142 |  | 
|---|
| 143 | /* Get devfn for P2SB device itself */ | 
|---|
| 144 | p2sb_get_devfn(devfn: &devfn_p2sb); | 
|---|
| 145 |  | 
|---|
| 146 | bus = p2sb_get_bus(NULL); | 
|---|
| 147 | if (!bus) | 
|---|
| 148 | return -ENODEV; | 
|---|
| 149 |  | 
|---|
| 150 | /* | 
|---|
| 151 | * When a device with same devfn exists and its device class is not | 
|---|
| 152 | * PCI_CLASS_MEMORY_OTHER for P2SB, do not touch it. | 
|---|
| 153 | */ | 
|---|
| 154 | pci_bus_read_config_word(bus, devfn: devfn_p2sb, PCI_CLASS_DEVICE, val: &class); | 
|---|
| 155 | if (!PCI_POSSIBLE_ERROR(class) && class != PCI_CLASS_MEMORY_OTHER) | 
|---|
| 156 | return -ENODEV; | 
|---|
| 157 |  | 
|---|
| 158 | /* | 
|---|
| 159 | * Prevent concurrent PCI bus scan from seeing the P2SB device and | 
|---|
| 160 | * removing via sysfs while it is temporarily exposed. | 
|---|
| 161 | */ | 
|---|
| 162 | pci_lock_rescan_remove(); | 
|---|
| 163 |  | 
|---|
| 164 | pci_bus_read_config_dword(bus, devfn: devfn_p2sb, P2SBC, val: &value); | 
|---|
| 165 | p2sb_hidden_by_bios = value & P2SBC_HIDE; | 
|---|
| 166 |  | 
|---|
| 167 | /* | 
|---|
| 168 | * If the BIOS does not hide the P2SB device then its resources | 
|---|
| 169 | * are accesilble. Cache them only if the P2SB device is hidden. | 
|---|
| 170 | */ | 
|---|
| 171 | if (p2sb_hidden_by_bios) | 
|---|
| 172 | ret = p2sb_scan_and_cache(bus, devfn: devfn_p2sb); | 
|---|
| 173 |  | 
|---|
| 174 | pci_unlock_rescan_remove(); | 
|---|
| 175 |  | 
|---|
| 176 | return ret; | 
|---|
| 177 | } | 
|---|
| 178 |  | 
|---|
| 179 | static int p2sb_read_from_cache(struct pci_bus *bus, unsigned int devfn, | 
|---|
| 180 | struct resource *mem) | 
|---|
| 181 | { | 
|---|
| 182 | struct p2sb_res_cache *cache = &p2sb_resources[PCI_FUNC(devfn)]; | 
|---|
| 183 |  | 
|---|
| 184 | if (cache->bus_dev_id != bus->dev.id) | 
|---|
| 185 | return -ENODEV; | 
|---|
| 186 |  | 
|---|
| 187 | if (!p2sb_valid_resource(res: &cache->res)) | 
|---|
| 188 | return -ENOENT; | 
|---|
| 189 |  | 
|---|
| 190 | memcpy(to: mem, from: &cache->res, len: sizeof(*mem)); | 
|---|
| 191 |  | 
|---|
| 192 | return 0; | 
|---|
| 193 | } | 
|---|
| 194 |  | 
|---|
| 195 | static int p2sb_read_from_dev(struct pci_bus *bus, unsigned int devfn, | 
|---|
| 196 | struct resource *mem) | 
|---|
| 197 | { | 
|---|
| 198 | struct pci_dev *pdev; | 
|---|
| 199 | int ret = 0; | 
|---|
| 200 |  | 
|---|
| 201 | pdev = pci_get_slot(bus, devfn); | 
|---|
| 202 | if (!pdev) | 
|---|
| 203 | return -ENODEV; | 
|---|
| 204 |  | 
|---|
| 205 | if (p2sb_valid_resource(pci_resource_n(pdev, 0))) | 
|---|
| 206 | p2sb_read_bar0(pdev, mem); | 
|---|
| 207 | else | 
|---|
| 208 | ret = -ENOENT; | 
|---|
| 209 |  | 
|---|
| 210 | pci_dev_put(dev: pdev); | 
|---|
| 211 |  | 
|---|
| 212 | return ret; | 
|---|
| 213 | } | 
|---|
| 214 |  | 
|---|
| 215 | /** | 
|---|
| 216 | * p2sb_bar - Get Primary to Sideband (P2SB) bridge device BAR | 
|---|
| 217 | * @bus: PCI bus to communicate with | 
|---|
| 218 | * @devfn: PCI slot and function to communicate with | 
|---|
| 219 | * @mem: memory resource to be filled in | 
|---|
| 220 | * | 
|---|
| 221 | * If @bus is NULL, the bus 0 in domain 0 will be used. | 
|---|
| 222 | * If @devfn is 0, it will be replaced by devfn of the P2SB device. | 
|---|
| 223 | * | 
|---|
| 224 | * Caller must provide a valid pointer to @mem. | 
|---|
| 225 | * | 
|---|
| 226 | * Return: | 
|---|
| 227 | * 0 on success or appropriate errno value on error. | 
|---|
| 228 | */ | 
|---|
| 229 | int p2sb_bar(struct pci_bus *bus, unsigned int devfn, struct resource *mem) | 
|---|
| 230 | { | 
|---|
| 231 | bus = p2sb_get_bus(bus); | 
|---|
| 232 | if (!bus) | 
|---|
| 233 | return -ENODEV; | 
|---|
| 234 |  | 
|---|
| 235 | if (!devfn) | 
|---|
| 236 | p2sb_get_devfn(devfn: &devfn); | 
|---|
| 237 |  | 
|---|
| 238 | if (p2sb_hidden_by_bios) | 
|---|
| 239 | return p2sb_read_from_cache(bus, devfn, mem); | 
|---|
| 240 |  | 
|---|
| 241 | return p2sb_read_from_dev(bus, devfn, mem); | 
|---|
| 242 | } | 
|---|
| 243 | EXPORT_SYMBOL_GPL(p2sb_bar); | 
|---|
| 244 |  | 
|---|
| 245 | static int __init p2sb_fs_init(void) | 
|---|
| 246 | { | 
|---|
| 247 | return p2sb_cache_resources(); | 
|---|
| 248 | } | 
|---|
| 249 |  | 
|---|
| 250 | /* | 
|---|
| 251 | * pci_rescan_remove_lock() can not be locked in sysfs PCI bus rescan path | 
|---|
| 252 | * because of deadlock. To avoid the deadlock, access P2SB devices with the lock | 
|---|
| 253 | * at an early step in kernel initialization and cache required resources. | 
|---|
| 254 | * | 
|---|
| 255 | * We want to run as early as possible. If the P2SB was assigned a bad BAR, | 
|---|
| 256 | * we'll need to wait on pcibios_assign_resources() to fix it. So, our list of | 
|---|
| 257 | * initcall dependencies looks something like this: | 
|---|
| 258 | * | 
|---|
| 259 | * ... | 
|---|
| 260 | * subsys_initcall (pci_subsys_init) | 
|---|
| 261 | * fs_initcall     (pcibios_assign_resources) | 
|---|
| 262 | */ | 
|---|
| 263 | fs_initcall_sync(p2sb_fs_init); | 
|---|
| 264 |  | 
|---|