|
@@ -101,25 +101,6 @@ PCI_READ_VIA_DWORD_OP(word, u16 *, 0x02)
|
|
|
PCI_WRITE_VIA_DWORD_OP(byte, u8, 0x03, 0x000000ff)
|
|
|
PCI_WRITE_VIA_DWORD_OP(word, u16, 0x02, 0x0000ffff)
|
|
|
|
|
|
-/* Get a virtual address associated with a BAR region */
|
|
|
-void *pci_map_bar(pci_dev_t pdev, int bar, int flags)
|
|
|
-{
|
|
|
- pci_addr_t pci_bus_addr;
|
|
|
- u32 bar_response;
|
|
|
-
|
|
|
- /* read BAR address */
|
|
|
- pci_read_config_dword(pdev, bar, &bar_response);
|
|
|
- pci_bus_addr = (pci_addr_t)(bar_response & ~0xf);
|
|
|
-
|
|
|
- /*
|
|
|
- * Pass "0" as the length argument to pci_bus_to_virt. The arg
|
|
|
- * isn't actualy used on any platform because u-boot assumes a static
|
|
|
- * linear mapping. In the future, this could read the BAR size
|
|
|
- * and pass that as the size if needed.
|
|
|
- */
|
|
|
- return pci_bus_to_virt(pdev, pci_bus_addr, flags, 0, MAP_NOCACHE);
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
*
|
|
|
*/
|
|
@@ -187,106 +168,22 @@ int pci_last_busno(void)
|
|
|
pci_dev_t pci_find_devices(struct pci_device_id *ids, int index)
|
|
|
{
|
|
|
struct pci_controller * hose;
|
|
|
- u16 vendor, device;
|
|
|
- u8 header_type;
|
|
|
pci_dev_t bdf;
|
|
|
- int i, bus, found_multi = 0;
|
|
|
+ int bus;
|
|
|
|
|
|
for (hose = pci_get_hose_head(); hose; hose = hose->next) {
|
|
|
#ifdef CONFIG_SYS_SCSI_SCAN_BUS_REVERSE
|
|
|
- for (bus = hose->last_busno; bus >= hose->first_busno; bus--)
|
|
|
+ for (bus = hose->last_busno; bus >= hose->first_busno; bus--) {
|
|
|
#else
|
|
|
- for (bus = hose->first_busno; bus <= hose->last_busno; bus++)
|
|
|
+ for (bus = hose->first_busno; bus <= hose->last_busno; bus++) {
|
|
|
#endif
|
|
|
- for (bdf = PCI_BDF(bus, 0, 0);
|
|
|
- bdf < PCI_BDF(bus + 1, 0, 0);
|
|
|
- bdf += PCI_BDF(0, 0, 1)) {
|
|
|
- if (pci_skip_dev(hose, bdf))
|
|
|
- continue;
|
|
|
-
|
|
|
- if (!PCI_FUNC(bdf)) {
|
|
|
- pci_read_config_byte(bdf,
|
|
|
- PCI_HEADER_TYPE,
|
|
|
- &header_type);
|
|
|
-
|
|
|
- found_multi = header_type & 0x80;
|
|
|
- } else {
|
|
|
- if (!found_multi)
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- pci_read_config_word(bdf,
|
|
|
- PCI_VENDOR_ID,
|
|
|
- &vendor);
|
|
|
- pci_read_config_word(bdf,
|
|
|
- PCI_DEVICE_ID,
|
|
|
- &device);
|
|
|
-
|
|
|
- for (i = 0; ids[i].vendor != 0; i++) {
|
|
|
- if (vendor == ids[i].vendor &&
|
|
|
- device == ids[i].device) {
|
|
|
- if (index <= 0)
|
|
|
- return bdf;
|
|
|
-
|
|
|
- index--;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return -1;
|
|
|
-}
|
|
|
-
|
|
|
-pci_dev_t pci_find_class(uint find_class, int index)
|
|
|
-{
|
|
|
- int bus;
|
|
|
- int devnum;
|
|
|
- pci_dev_t bdf;
|
|
|
- uint32_t class;
|
|
|
-
|
|
|
- for (bus = 0; bus <= pci_last_busno(); bus++) {
|
|
|
- for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES - 1; devnum++) {
|
|
|
- pci_read_config_dword(PCI_BDF(bus, devnum, 0),
|
|
|
- PCI_CLASS_REVISION, &class);
|
|
|
- if (class >> 16 == 0xffff)
|
|
|
- continue;
|
|
|
-
|
|
|
- for (bdf = PCI_BDF(bus, devnum, 0);
|
|
|
- bdf <= PCI_BDF(bus, devnum,
|
|
|
- PCI_MAX_PCI_FUNCTIONS - 1);
|
|
|
- bdf += PCI_BDF(0, 0, 1)) {
|
|
|
- pci_read_config_dword(bdf, PCI_CLASS_REVISION,
|
|
|
- &class);
|
|
|
- class >>= 8;
|
|
|
-
|
|
|
- if (class != find_class)
|
|
|
- continue;
|
|
|
- /*
|
|
|
- * Decrement the index. We want to return the
|
|
|
- * correct device, so index is 0 for the first
|
|
|
- * matching device, 1 for the second, etc.
|
|
|
- */
|
|
|
- if (index) {
|
|
|
- index--;
|
|
|
- continue;
|
|
|
- }
|
|
|
- /* Return index'th controller. */
|
|
|
+ bdf = pci_hose_find_devices(hose, bus, ids, &index);
|
|
|
+ if (bdf != -1)
|
|
|
return bdf;
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return -ENODEV;
|
|
|
-}
|
|
|
-
|
|
|
-pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
|
|
|
-{
|
|
|
- struct pci_device_id ids[2] = { {}, {0, 0} };
|
|
|
-
|
|
|
- ids[0].vendor = vendor;
|
|
|
- ids[0].device = device;
|
|
|
-
|
|
|
- return pci_find_devices(ids, index);
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -355,87 +252,6 @@ pci_addr_t pci_hose_phys_to_bus (struct pci_controller *hose,
|
|
|
return bus_addr;
|
|
|
}
|
|
|
|
|
|
-int __pci_hose_bus_to_phys(struct pci_controller *hose,
|
|
|
- pci_addr_t bus_addr,
|
|
|
- unsigned long flags,
|
|
|
- unsigned long skip_mask,
|
|
|
- phys_addr_t *pa)
|
|
|
-{
|
|
|
- struct pci_region *res;
|
|
|
- int i;
|
|
|
-
|
|
|
- for (i = 0; i < hose->region_count; i++) {
|
|
|
- res = &hose->regions[i];
|
|
|
-
|
|
|
- if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
|
|
|
- continue;
|
|
|
-
|
|
|
- if (res->flags & skip_mask)
|
|
|
- continue;
|
|
|
-
|
|
|
- if (bus_addr >= res->bus_start &&
|
|
|
- (bus_addr - res->bus_start) < res->size) {
|
|
|
- *pa = (bus_addr - res->bus_start + res->phys_start);
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
-phys_addr_t pci_hose_bus_to_phys(struct pci_controller* hose,
|
|
|
- pci_addr_t bus_addr,
|
|
|
- unsigned long flags)
|
|
|
-{
|
|
|
- phys_addr_t phys_addr = 0;
|
|
|
- int ret;
|
|
|
-
|
|
|
- if (!hose) {
|
|
|
- puts("pci_hose_bus_to_phys: invalid hose\n");
|
|
|
- return phys_addr;
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * if PCI_REGION_MEM is set we do a two pass search with preference
|
|
|
- * on matches that don't have PCI_REGION_SYS_MEMORY set
|
|
|
- */
|
|
|
- if ((flags & PCI_REGION_MEM) == PCI_REGION_MEM) {
|
|
|
- ret = __pci_hose_bus_to_phys(hose, bus_addr,
|
|
|
- flags, PCI_REGION_SYS_MEMORY, &phys_addr);
|
|
|
- if (!ret)
|
|
|
- return phys_addr;
|
|
|
- }
|
|
|
-
|
|
|
- ret = __pci_hose_bus_to_phys(hose, bus_addr, flags, 0, &phys_addr);
|
|
|
-
|
|
|
- if (ret)
|
|
|
- puts("pci_hose_bus_to_phys: invalid physical address\n");
|
|
|
-
|
|
|
- return phys_addr;
|
|
|
-}
|
|
|
-
|
|
|
-void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum,
|
|
|
- u32 addr_and_ctrl)
|
|
|
-{
|
|
|
- int bar;
|
|
|
-
|
|
|
- bar = PCI_BASE_ADDRESS_0 + barnum * 4;
|
|
|
- pci_hose_write_config_dword(hose, dev, bar, addr_and_ctrl);
|
|
|
-}
|
|
|
-
|
|
|
-u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum)
|
|
|
-{
|
|
|
- u32 addr;
|
|
|
- int bar;
|
|
|
-
|
|
|
- bar = PCI_BASE_ADDRESS_0 + barnum * 4;
|
|
|
- pci_hose_read_config_dword(hose, dev, bar, &addr);
|
|
|
- if (addr & PCI_BASE_ADDRESS_SPACE_IO)
|
|
|
- return addr & PCI_BASE_ADDRESS_IO_MASK;
|
|
|
- else
|
|
|
- return addr & PCI_BASE_ADDRESS_MEM_MASK;
|
|
|
-}
|
|
|
-
|
|
|
int pci_hose_config_device(struct pci_controller *hose,
|
|
|
pci_dev_t dev,
|
|
|
unsigned long io,
|
|
@@ -576,91 +392,6 @@ void pci_cfgfunc_do_nothing(struct pci_controller *hose,
|
|
|
*/
|
|
|
extern int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev);
|
|
|
|
|
|
-#if defined(CONFIG_CMD_PCI) || defined(CONFIG_PCI_SCAN_SHOW)
|
|
|
-const char * pci_class_str(u8 class)
|
|
|
-{
|
|
|
- switch (class) {
|
|
|
- case PCI_CLASS_NOT_DEFINED:
|
|
|
- return "Build before PCI Rev2.0";
|
|
|
- break;
|
|
|
- case PCI_BASE_CLASS_STORAGE:
|
|
|
- return "Mass storage controller";
|
|
|
- break;
|
|
|
- case PCI_BASE_CLASS_NETWORK:
|
|
|
- return "Network controller";
|
|
|
- break;
|
|
|
- case PCI_BASE_CLASS_DISPLAY:
|
|
|
- return "Display controller";
|
|
|
- break;
|
|
|
- case PCI_BASE_CLASS_MULTIMEDIA:
|
|
|
- return "Multimedia device";
|
|
|
- break;
|
|
|
- case PCI_BASE_CLASS_MEMORY:
|
|
|
- return "Memory controller";
|
|
|
- break;
|
|
|
- case PCI_BASE_CLASS_BRIDGE:
|
|
|
- return "Bridge device";
|
|
|
- break;
|
|
|
- case PCI_BASE_CLASS_COMMUNICATION:
|
|
|
- return "Simple comm. controller";
|
|
|
- break;
|
|
|
- case PCI_BASE_CLASS_SYSTEM:
|
|
|
- return "Base system peripheral";
|
|
|
- break;
|
|
|
- case PCI_BASE_CLASS_INPUT:
|
|
|
- return "Input device";
|
|
|
- break;
|
|
|
- case PCI_BASE_CLASS_DOCKING:
|
|
|
- return "Docking station";
|
|
|
- break;
|
|
|
- case PCI_BASE_CLASS_PROCESSOR:
|
|
|
- return "Processor";
|
|
|
- break;
|
|
|
- case PCI_BASE_CLASS_SERIAL:
|
|
|
- return "Serial bus controller";
|
|
|
- break;
|
|
|
- case PCI_BASE_CLASS_INTELLIGENT:
|
|
|
- return "Intelligent controller";
|
|
|
- break;
|
|
|
- case PCI_BASE_CLASS_SATELLITE:
|
|
|
- return "Satellite controller";
|
|
|
- break;
|
|
|
- case PCI_BASE_CLASS_CRYPT:
|
|
|
- return "Cryptographic device";
|
|
|
- break;
|
|
|
- case PCI_BASE_CLASS_SIGNAL_PROCESSING:
|
|
|
- return "DSP";
|
|
|
- break;
|
|
|
- case PCI_CLASS_OTHERS:
|
|
|
- return "Does not fit any class";
|
|
|
- break;
|
|
|
- default:
|
|
|
- return "???";
|
|
|
- break;
|
|
|
- };
|
|
|
-}
|
|
|
-#endif /* CONFIG_CMD_PCI || CONFIG_PCI_SCAN_SHOW */
|
|
|
-
|
|
|
-__weak int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
|
|
|
-{
|
|
|
- /*
|
|
|
- * Check if pci device should be skipped in configuration
|
|
|
- */
|
|
|
- if (dev == PCI_BDF(hose->first_busno, 0, 0)) {
|
|
|
-#if defined(CONFIG_PCI_CONFIG_HOST_BRIDGE) /* don't skip host bridge */
|
|
|
- /*
|
|
|
- * Only skip configuration if "pciconfighost" is not set
|
|
|
- */
|
|
|
- if (getenv("pciconfighost") == NULL)
|
|
|
- return 1;
|
|
|
-#else
|
|
|
- return 1;
|
|
|
-#endif
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
#ifdef CONFIG_PCI_SCAN_SHOW
|
|
|
__weak int pci_print_dev(struct pci_controller *hose, pci_dev_t dev)
|
|
|
{
|