Commit cf89c4262bd5fa70e67953126001c08ecea4f346
1 parent
a3c4f2fb26
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
tile PCI RC: support I/O space access
To enable this functionality, configure CONFIG_TILE_PCI_IO. Without this flag, the kernel still assigns I/O address ranges to the devices, but no TRIO resource and mapping support is provided. We assign disjoint I/O address ranges to separate PCIe domains. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Showing 4 changed files with 257 additions and 18 deletions Side-by-side Diff
arch/tile/Kconfig
... | ... | @@ -396,6 +396,16 @@ |
396 | 396 | config NO_IOPORT |
397 | 397 | def_bool !PCI |
398 | 398 | |
399 | +config TILE_PCI_IO | |
400 | + bool "PCI I/O space support" | |
401 | + default n | |
402 | + depends on PCI | |
403 | + depends on TILEGX | |
404 | + ---help--- | |
405 | + Enable PCI I/O space support on TILEGx. Since the PCI I/O space | |
406 | + is used by few modern PCIe endpoint devices, its support is disabled | |
407 | + by default to save the TRIO PIO Region resource for other purposes. | |
408 | + | |
399 | 409 | source "drivers/pci/Kconfig" |
400 | 410 | |
401 | 411 | config TILE_USB |
arch/tile/include/asm/io.h
... | ... | @@ -19,7 +19,8 @@ |
19 | 19 | #include <linux/bug.h> |
20 | 20 | #include <asm/page.h> |
21 | 21 | |
22 | -#define IO_SPACE_LIMIT 0xfffffffful | |
22 | +/* Maximum PCI I/O space address supported. */ | |
23 | +#define IO_SPACE_LIMIT 0xffffffff | |
23 | 24 | |
24 | 25 | /* |
25 | 26 | * Convert a physical pointer to a virtual kernel pointer for /dev/mem |
26 | 27 | |
... | ... | @@ -281,8 +282,108 @@ |
281 | 282 | |
282 | 283 | #endif |
283 | 284 | |
285 | +#if CHIP_HAS_MMIO() && defined(CONFIG_TILE_PCI_IO) | |
286 | + | |
287 | +static inline u8 inb(unsigned long addr) | |
288 | +{ | |
289 | + return readb((volatile void __iomem *) addr); | |
290 | +} | |
291 | + | |
292 | +static inline u16 inw(unsigned long addr) | |
293 | +{ | |
294 | + return readw((volatile void __iomem *) addr); | |
295 | +} | |
296 | + | |
297 | +static inline u32 inl(unsigned long addr) | |
298 | +{ | |
299 | + return readl((volatile void __iomem *) addr); | |
300 | +} | |
301 | + | |
302 | +static inline void outb(u8 b, unsigned long addr) | |
303 | +{ | |
304 | + writeb(b, (volatile void __iomem *) addr); | |
305 | +} | |
306 | + | |
307 | +static inline void outw(u16 b, unsigned long addr) | |
308 | +{ | |
309 | + writew(b, (volatile void __iomem *) addr); | |
310 | +} | |
311 | + | |
312 | +static inline void outl(u32 b, unsigned long addr) | |
313 | +{ | |
314 | + writel(b, (volatile void __iomem *) addr); | |
315 | +} | |
316 | + | |
317 | +static inline void insb(unsigned long addr, void *buffer, int count) | |
318 | +{ | |
319 | + if (count) { | |
320 | + u8 *buf = buffer; | |
321 | + do { | |
322 | + u8 x = inb(addr); | |
323 | + *buf++ = x; | |
324 | + } while (--count); | |
325 | + } | |
326 | +} | |
327 | + | |
328 | +static inline void insw(unsigned long addr, void *buffer, int count) | |
329 | +{ | |
330 | + if (count) { | |
331 | + u16 *buf = buffer; | |
332 | + do { | |
333 | + u16 x = inw(addr); | |
334 | + *buf++ = x; | |
335 | + } while (--count); | |
336 | + } | |
337 | +} | |
338 | + | |
339 | +static inline void insl(unsigned long addr, void *buffer, int count) | |
340 | +{ | |
341 | + if (count) { | |
342 | + u32 *buf = buffer; | |
343 | + do { | |
344 | + u32 x = inl(addr); | |
345 | + *buf++ = x; | |
346 | + } while (--count); | |
347 | + } | |
348 | +} | |
349 | + | |
350 | +static inline void outsb(unsigned long addr, const void *buffer, int count) | |
351 | +{ | |
352 | + if (count) { | |
353 | + const u8 *buf = buffer; | |
354 | + do { | |
355 | + outb(*buf++, addr); | |
356 | + } while (--count); | |
357 | + } | |
358 | +} | |
359 | + | |
360 | +static inline void outsw(unsigned long addr, const void *buffer, int count) | |
361 | +{ | |
362 | + if (count) { | |
363 | + const u16 *buf = buffer; | |
364 | + do { | |
365 | + outw(*buf++, addr); | |
366 | + } while (--count); | |
367 | + } | |
368 | +} | |
369 | + | |
370 | +static inline void outsl(unsigned long addr, const void *buffer, int count) | |
371 | +{ | |
372 | + if (count) { | |
373 | + const u32 *buf = buffer; | |
374 | + do { | |
375 | + outl(*buf++, addr); | |
376 | + } while (--count); | |
377 | + } | |
378 | +} | |
379 | + | |
380 | +extern void __iomem *ioport_map(unsigned long port, unsigned int len); | |
381 | +extern void ioport_unmap(void __iomem *addr); | |
382 | + | |
383 | +#else | |
384 | + | |
284 | 385 | /* |
285 | - * The Tile architecture does not support IOPORT, even with PCI. | |
386 | + * The TilePro architecture does not support IOPORT, even with PCI. | |
286 | 387 | * Unfortunately we can't yet simply not declare these methods, |
287 | 388 | * since some generic code that compiles into the kernel, but |
288 | 389 | * we never run, uses them unconditionally. |
289 | 390 | |
... | ... | @@ -290,7 +391,12 @@ |
290 | 391 | |
291 | 392 | static inline long ioport_panic(void) |
292 | 393 | { |
394 | +#ifdef __tilegx__ | |
395 | + panic("PCI IO space support is disabled. Configure the kernel with" | |
396 | + " CONFIG_TILE_PCI_IO to enable it"); | |
397 | +#else | |
293 | 398 | panic("inb/outb and friends do not exist on tile"); |
399 | +#endif | |
294 | 400 | return 0; |
295 | 401 | } |
296 | 402 | |
... | ... | @@ -335,13 +441,6 @@ |
335 | 441 | ioport_panic(); |
336 | 442 | } |
337 | 443 | |
338 | -#define inb_p(addr) inb(addr) | |
339 | -#define inw_p(addr) inw(addr) | |
340 | -#define inl_p(addr) inl(addr) | |
341 | -#define outb_p(x, addr) outb((x), (addr)) | |
342 | -#define outw_p(x, addr) outw((x), (addr)) | |
343 | -#define outl_p(x, addr) outl((x), (addr)) | |
344 | - | |
345 | 444 | static inline void insb(unsigned long addr, void *buffer, int count) |
346 | 445 | { |
347 | 446 | ioport_panic(); |
... | ... | @@ -371,6 +470,15 @@ |
371 | 470 | { |
372 | 471 | ioport_panic(); |
373 | 472 | } |
473 | + | |
474 | +#endif /* CHIP_HAS_MMIO() && defined(CONFIG_TILE_PCI_IO) */ | |
475 | + | |
476 | +#define inb_p(addr) inb(addr) | |
477 | +#define inw_p(addr) inw(addr) | |
478 | +#define inl_p(addr) inl(addr) | |
479 | +#define outb_p(x, addr) outb((x), (addr)) | |
480 | +#define outw_p(x, addr) outw((x), (addr)) | |
481 | +#define outl_p(x, addr) outl((x), (addr)) | |
374 | 482 | |
375 | 483 | #define ioread16be(addr) be16_to_cpu(ioread16(addr)) |
376 | 484 | #define ioread32be(addr) be32_to_cpu(ioread32(addr)) |
arch/tile/include/asm/pci.h
... | ... | @@ -144,6 +144,10 @@ |
144 | 144 | |
145 | 145 | int pio_mem_index; /* PIO region index for memory access */ |
146 | 146 | |
147 | +#ifdef CONFIG_TILE_PCI_IO | |
148 | + int pio_io_index; /* PIO region index for I/O space access */ | |
149 | +#endif | |
150 | + | |
147 | 151 | /* |
148 | 152 | * Mem-Map regions for all the memory controllers so that Linux can |
149 | 153 | * map all of its physical memory space to the PCI bus. |
... | ... | @@ -153,6 +157,10 @@ |
153 | 157 | int index; /* PCI domain number */ |
154 | 158 | struct pci_bus *root_bus; |
155 | 159 | |
160 | + /* PCI I/O space resource for this controller. */ | |
161 | + struct resource io_space; | |
162 | + char io_space_name[32]; | |
163 | + | |
156 | 164 | /* PCI memory space resource for this controller. */ |
157 | 165 | struct resource mem_space; |
158 | 166 | char mem_space_name[32]; |
... | ... | @@ -210,7 +218,8 @@ |
210 | 218 | } |
211 | 219 | |
212 | 220 | #define PCIBIOS_MIN_MEM 0 |
213 | -#define PCIBIOS_MIN_IO 0 | |
221 | +/* Minimum PCI I/O address, starting at the page boundary. */ | |
222 | +#define PCIBIOS_MIN_IO PAGE_SIZE | |
214 | 223 | |
215 | 224 | /* Use any cpu for PCI. */ |
216 | 225 | #define cpumask_of_pcibus(bus) cpu_online_mask |
arch/tile/kernel/pci_gx.c
... | ... | @@ -77,6 +77,9 @@ |
77 | 77 | /* Default number of seconds that the PCIe RC port probe can be delayed. */ |
78 | 78 | #define DEFAULT_RC_DELAY 10 |
79 | 79 | |
80 | +/* The PCI I/O space size in each PCI domain. */ | |
81 | +#define IO_SPACE_SIZE 0x10000 | |
82 | + | |
80 | 83 | /* Array of the PCIe ports configuration info obtained from the BIB. */ |
81 | 84 | struct pcie_port_property pcie_ports[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES]; |
82 | 85 | |
... | ... | @@ -421,6 +424,17 @@ |
421 | 424 | controller->index = i; |
422 | 425 | controller->ops = &tile_cfg_ops; |
423 | 426 | |
427 | + controller->io_space.start = PCIBIOS_MIN_IO + | |
428 | + (i * IO_SPACE_SIZE); | |
429 | + controller->io_space.end = controller->io_space.start + | |
430 | + IO_SPACE_SIZE - 1; | |
431 | + BUG_ON(controller->io_space.end > IO_SPACE_LIMIT); | |
432 | + controller->io_space.flags = IORESOURCE_IO; | |
433 | + snprintf(controller->io_space_name, | |
434 | + sizeof(controller->io_space_name), | |
435 | + "PCI I/O domain %d", i); | |
436 | + controller->io_space.name = controller->io_space_name; | |
437 | + | |
424 | 438 | /* |
425 | 439 | * The PCI memory resource is located above the PA space. |
426 | 440 | * For every host bridge, the BAR window or the MMIO aperture |
427 | 441 | |
428 | 442 | |
... | ... | @@ -861,17 +875,16 @@ |
861 | 875 | /* |
862 | 876 | * The PCI memory resource is located above the PA space. |
863 | 877 | * The memory range for the PCI root bus should not overlap |
864 | - * with the physical RAM | |
878 | + * with the physical RAM. | |
865 | 879 | */ |
866 | 880 | pci_add_resource_offset(&resources, &controller->mem_space, |
867 | 881 | controller->mem_offset); |
868 | - | |
882 | + pci_add_resource(&resources, &controller->io_space); | |
869 | 883 | controller->first_busno = next_busno; |
870 | 884 | bus = pci_scan_root_bus(NULL, next_busno, controller->ops, |
871 | 885 | controller, &resources); |
872 | 886 | controller->root_bus = bus; |
873 | 887 | next_busno = bus->busn_res.end + 1; |
874 | - | |
875 | 888 | } |
876 | 889 | |
877 | 890 | /* Do machine dependent PCI interrupt routing */ |
878 | 891 | |
... | ... | @@ -915,9 +928,9 @@ |
915 | 928 | pci_controllers[i].mem_resources[0] = |
916 | 929 | *next_bus->resource[0]; |
917 | 930 | pci_controllers[i].mem_resources[1] = |
918 | - *next_bus->resource[1]; | |
931 | + *next_bus->resource[1]; | |
919 | 932 | pci_controllers[i].mem_resources[2] = |
920 | - *next_bus->resource[2]; | |
933 | + *next_bus->resource[2]; | |
921 | 934 | |
922 | 935 | break; |
923 | 936 | } |
924 | 937 | |
... | ... | @@ -967,7 +980,40 @@ |
967 | 980 | continue; |
968 | 981 | } |
969 | 982 | |
983 | +#ifdef CONFIG_TILE_PCI_IO | |
970 | 984 | /* |
985 | + * Alloc a PIO region for PCI I/O space access for each RC port. | |
986 | + */ | |
987 | + ret = gxio_trio_alloc_pio_regions(trio_context, 1, 0, 0); | |
988 | + if (ret < 0) { | |
989 | + pr_err("PCI: I/O PIO alloc failure on TRIO %d mac %d, " | |
990 | + "give up\n", controller->trio_index, | |
991 | + controller->mac); | |
992 | + | |
993 | + continue; | |
994 | + } | |
995 | + | |
996 | + controller->pio_io_index = ret; | |
997 | + | |
998 | + /* | |
999 | + * For PIO IO, the bus_address_hi parameter is hard-coded 0 | |
1000 | + * because PCI I/O address space is 32-bit. | |
1001 | + */ | |
1002 | + ret = gxio_trio_init_pio_region_aux(trio_context, | |
1003 | + controller->pio_io_index, | |
1004 | + controller->mac, | |
1005 | + 0, | |
1006 | + HV_TRIO_PIO_FLAG_IO_SPACE); | |
1007 | + if (ret < 0) { | |
1008 | + pr_err("PCI: I/O PIO init failure on TRIO %d mac %d, " | |
1009 | + "give up\n", controller->trio_index, | |
1010 | + controller->mac); | |
1011 | + | |
1012 | + continue; | |
1013 | + } | |
1014 | +#endif | |
1015 | + | |
1016 | + /* | |
971 | 1017 | * Configure a Mem-Map region for each memory controller so |
972 | 1018 | * that Linux can map all of its PA space to the PCI bus. |
973 | 1019 | * Use the IOMMU to handle hash-for-home memory. |
... | ... | @@ -1052,8 +1098,7 @@ |
1052 | 1098 | |
1053 | 1099 | /* |
1054 | 1100 | * Enable memory address decoding, as appropriate, for the |
1055 | - * device described by the 'dev' struct. The I/O decoding | |
1056 | - * is disabled, though the TILE-Gx supports I/O addressing. | |
1101 | + * device described by the 'dev' struct. | |
1057 | 1102 | * |
1058 | 1103 | * This is called from the generic PCI layer, and can be called |
1059 | 1104 | * for bridges or endpoints. |
1060 | 1105 | |
... | ... | @@ -1134,9 +1179,76 @@ |
1134 | 1179 | * We need to keep the PCI bus address's in-page offset in the VA. |
1135 | 1180 | */ |
1136 | 1181 | return iorpc_ioremap(trio_fd, offset, size) + |
1137 | - (phys_addr & (PAGE_SIZE - 1)); | |
1182 | + (start & (PAGE_SIZE - 1)); | |
1138 | 1183 | } |
1139 | 1184 | EXPORT_SYMBOL(ioremap); |
1185 | + | |
1186 | +#ifdef CONFIG_TILE_PCI_IO | |
1187 | +/* Map a PCI I/O address into VA space. */ | |
1188 | +void __iomem *ioport_map(unsigned long port, unsigned int size) | |
1189 | +{ | |
1190 | + struct pci_controller *controller = NULL; | |
1191 | + resource_size_t bar_start; | |
1192 | + resource_size_t bar_end; | |
1193 | + resource_size_t offset; | |
1194 | + resource_size_t start; | |
1195 | + resource_size_t end; | |
1196 | + int trio_fd; | |
1197 | + int i; | |
1198 | + | |
1199 | + start = port; | |
1200 | + end = port + size - 1; | |
1201 | + | |
1202 | + /* | |
1203 | + * In the following, each PCI controller's mem_resources[0] | |
1204 | + * represents its PCI I/O resource. By searching port in each | |
1205 | + * controller's mem_resources[0], we can determine the controller | |
1206 | + * that should accept the PCI I/O access. | |
1207 | + */ | |
1208 | + | |
1209 | + for (i = 0; i < num_rc_controllers; i++) { | |
1210 | + /* | |
1211 | + * Skip controllers that are not properly initialized or | |
1212 | + * have down links. | |
1213 | + */ | |
1214 | + if (pci_controllers[i].root_bus == NULL) | |
1215 | + continue; | |
1216 | + | |
1217 | + bar_start = pci_controllers[i].mem_resources[0].start; | |
1218 | + bar_end = pci_controllers[i].mem_resources[0].end; | |
1219 | + | |
1220 | + if ((start >= bar_start) && (end <= bar_end)) { | |
1221 | + | |
1222 | + controller = &pci_controllers[i]; | |
1223 | + | |
1224 | + goto got_it; | |
1225 | + } | |
1226 | + } | |
1227 | + | |
1228 | + if (controller == NULL) | |
1229 | + return NULL; | |
1230 | + | |
1231 | +got_it: | |
1232 | + trio_fd = controller->trio->fd; | |
1233 | + | |
1234 | + /* Convert the resource start to the bus address offset. */ | |
1235 | + port -= controller->io_space.start; | |
1236 | + | |
1237 | + offset = HV_TRIO_PIO_OFFSET(controller->pio_io_index) + port; | |
1238 | + | |
1239 | + /* | |
1240 | + * We need to keep the PCI bus address's in-page offset in the VA. | |
1241 | + */ | |
1242 | + return iorpc_ioremap(trio_fd, offset, size) + (port & (PAGE_SIZE - 1)); | |
1243 | +} | |
1244 | +EXPORT_SYMBOL(ioport_map); | |
1245 | + | |
1246 | +void ioport_unmap(void __iomem *addr) | |
1247 | +{ | |
1248 | + iounmap(addr); | |
1249 | +} | |
1250 | +EXPORT_SYMBOL(ioport_unmap); | |
1251 | +#endif | |
1140 | 1252 | |
1141 | 1253 | void pci_iounmap(struct pci_dev *dev, void __iomem *addr) |
1142 | 1254 | { |