1 /* 2 * PCI auto-configuration library 3 * 4 * Author: Matt Porter <mporter@mvista.com> 5 * 6 * Copyright 2000 MontaVista Software Inc. 7 * 8 * Modifications for driver model: 9 * Copyright 2015 Google, Inc 10 * Written by Simon Glass <sjg@chromium.org> 11 * 12 * SPDX-License-Identifier: GPL-2.0+ 13 */ 14 15 #include <common.h> 16 #include <dm.h> 17 #include <errno.h> 18 #include <pci.h> 19 20 void pciauto_region_init(struct pci_region *res) 21 { 22 /* 23 * Avoid allocating PCI resources from address 0 -- this is illegal 24 * according to PCI 2.1 and moreover, this is known to cause Linux IDE 25 * drivers to fail. Use a reasonable starting value of 0x1000 instead. 26 */ 27 res->bus_lower = res->bus_start ? res->bus_start : 0x1000; 28 } 29 30 void pciauto_region_align(struct pci_region *res, pci_size_t size) 31 { 32 res->bus_lower = ((res->bus_lower - 1) | (size - 1)) + 1; 33 } 34 35 int pciauto_region_allocate(struct pci_region *res, pci_size_t size, 36 pci_addr_t *bar) 37 { 38 pci_addr_t addr; 39 40 if (!res) { 41 debug("No resource"); 42 goto error; 43 } 44 45 addr = ((res->bus_lower - 1) | (size - 1)) + 1; 46 47 if (addr - res->bus_start + size > res->size) { 48 debug("No room in resource"); 49 goto error; 50 } 51 52 res->bus_lower = addr + size; 53 54 debug("address=0x%llx bus_lower=0x%llx", (unsigned long long)addr, 55 (unsigned long long)res->bus_lower); 56 57 *bar = addr; 58 return 0; 59 60 error: 61 *bar = (pci_addr_t)-1; 62 return -1; 63 } 64 65 void pciauto_config_init(struct pci_controller *hose) 66 { 67 int i; 68 69 hose->pci_io = NULL; 70 hose->pci_mem = NULL; 71 hose->pci_prefetch = NULL; 72 73 for (i = 0; i < hose->region_count; i++) { 74 switch (hose->regions[i].flags) { 75 case PCI_REGION_IO: 76 if (!hose->pci_io || 77 hose->pci_io->size < hose->regions[i].size) 78 hose->pci_io = hose->regions + i; 79 break; 80 case PCI_REGION_MEM: 81 if (!hose->pci_mem || 82 hose->pci_mem->size < hose->regions[i].size) 83 hose->pci_mem = hose->regions + i; 84 break; 85 case (PCI_REGION_MEM | PCI_REGION_PREFETCH): 86 if (!hose->pci_prefetch || 87 hose->pci_prefetch->size < hose->regions[i].size) 88 hose->pci_prefetch = hose->regions + i; 89 break; 90 } 91 } 92 93 94 if (hose->pci_mem) { 95 pciauto_region_init(hose->pci_mem); 96 97 debug("PCI Autoconfig: Bus Memory region: [0x%llx-0x%llx],\n" 98 "\t\tPhysical Memory [%llx-%llxx]\n", 99 (u64)hose->pci_mem->bus_start, 100 (u64)(hose->pci_mem->bus_start + hose->pci_mem->size - 1), 101 (u64)hose->pci_mem->phys_start, 102 (u64)(hose->pci_mem->phys_start + hose->pci_mem->size - 1)); 103 } 104 105 if (hose->pci_prefetch) { 106 pciauto_region_init(hose->pci_prefetch); 107 108 debug("PCI Autoconfig: Bus Prefetchable Mem: [0x%llx-0x%llx],\n" 109 "\t\tPhysical Memory [%llx-%llx]\n", 110 (u64)hose->pci_prefetch->bus_start, 111 (u64)(hose->pci_prefetch->bus_start + 112 hose->pci_prefetch->size - 1), 113 (u64)hose->pci_prefetch->phys_start, 114 (u64)(hose->pci_prefetch->phys_start + 115 hose->pci_prefetch->size - 1)); 116 } 117 118 if (hose->pci_io) { 119 pciauto_region_init(hose->pci_io); 120 121 debug("PCI Autoconfig: Bus I/O region: [0x%llx-0x%llx],\n" 122 "\t\tPhysical Memory: [%llx-%llx]\n", 123 (u64)hose->pci_io->bus_start, 124 (u64)(hose->pci_io->bus_start + hose->pci_io->size - 1), 125 (u64)hose->pci_io->phys_start, 126 (u64)(hose->pci_io->phys_start + hose->pci_io->size - 1)); 127 } 128 } 129