X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Fpci%2Fpci_auto.c;h=0412bf3515f8e905d98ee79096e36f56149e3170;hb=a69fdc7787bfa2f27eed74c2ee58c28ce932d502;hp=ed928574061600118a7ed8c0e83398c5c070291c;hpb=e72d344386bf80738fab7a6bd37cb321f443093a;p=platform%2Fkernel%2Fu-boot.git diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c index ed92857..0412bf3 100644 --- a/drivers/pci/pci_auto.c +++ b/drivers/pci/pci_auto.c @@ -14,15 +14,6 @@ #include #include -#undef DEBUG -#ifdef DEBUG -#define DEBUGF(x...) printf(x) -#else -#define DEBUGF(x...) -#endif /* DEBUG */ - -#define PCIAUTO_IDE_MODE_MASK 0x05 - /* the user can define CONFIG_SYS_PCI_CACHE_LINE_SIZE to avoid problems */ #ifndef CONFIG_SYS_PCI_CACHE_LINE_SIZE #define CONFIG_SYS_PCI_CACHE_LINE_SIZE 8 @@ -53,20 +44,21 @@ int pciauto_region_allocate(struct pci_region *res, pci_size_t size, pci_addr_t addr; if (!res) { - DEBUGF("No resource"); + debug("No resource"); goto error; } addr = ((res->bus_lower - 1) | (size - 1)) + 1; if (addr - res->bus_start + size > res->size) { - DEBUGF("No room in resource"); + debug("No room in resource"); goto error; } res->bus_lower = addr + size; - DEBUGF("address=0x%llx bus_lower=0x%llx", (u64)addr, (u64)res->bus_lower); + debug("address=0x%llx bus_lower=0x%llx", (unsigned long long)addr, + (unsigned long long)res->bus_lower); *bar = addr; return 0; @@ -91,10 +83,13 @@ void pciauto_setup_device(struct pci_controller *hose, u16 cmdstat = 0; int bar, bar_nr = 0; #ifndef CONFIG_PCI_ENUM_ONLY + u8 header_type; + int rom_addr; pci_addr_t bar_value; struct pci_region *bar_res; int found_mem64 = 0; #endif + u16 class; pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat); cmdstat = (cmdstat & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) | PCI_COMMAND_MASTER; @@ -123,7 +118,8 @@ void pciauto_setup_device(struct pci_controller *hose, bar_res = io; #endif - DEBUGF("PCI Autoconfig: BAR %d, I/O, size=0x%llx, ", bar_nr, (u64)bar_size); + debug("PCI Autoconfig: BAR %d, I/O, size=0x%llx, ", + bar_nr, (unsigned long long)bar_size); } else { if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) { @@ -153,7 +149,9 @@ void pciauto_setup_device(struct pci_controller *hose, bar_res = mem; #endif - DEBUGF("PCI Autoconfig: BAR %d, Mem, size=0x%llx, ", bar_nr, (u64)bar_size); + debug("PCI Autoconfig: BAR %d, %s, size=0x%llx, ", + bar_nr, bar_res == prefetch ? "Prf" : "Mem", + (unsigned long long)bar_size); } #ifndef CONFIG_PCI_ENUM_ONLY @@ -180,58 +178,82 @@ void pciauto_setup_device(struct pci_controller *hose, cmdstat |= (bar_response & PCI_BASE_ADDRESS_SPACE) ? PCI_COMMAND_IO : PCI_COMMAND_MEMORY; - DEBUGF("\n"); + debug("\n"); bar_nr++; } +#ifndef CONFIG_PCI_ENUM_ONLY + /* Configure the expansion ROM address */ + pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &header_type); + header_type &= 0x7f; + if (header_type != PCI_HEADER_TYPE_CARDBUS) { + rom_addr = (header_type == PCI_HEADER_TYPE_NORMAL) ? + PCI_ROM_ADDRESS : PCI_ROM_ADDRESS1; + pci_hose_write_config_dword(hose, dev, rom_addr, 0xfffffffe); + pci_hose_read_config_dword(hose, dev, rom_addr, &bar_response); + if (bar_response) { + bar_size = -(bar_response & ~1); + debug("PCI Autoconfig: ROM, size=%#x, ", + (unsigned int)bar_size); + if (pciauto_region_allocate(mem, bar_size, + &bar_value) == 0) { + pci_hose_write_config_dword(hose, dev, rom_addr, + bar_value); + } + cmdstat |= PCI_COMMAND_MEMORY; + debug("\n"); + } + } +#endif + + /* PCI_COMMAND_IO must be set for VGA device */ + pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class); + if (class == PCI_CLASS_DISPLAY_VGA) + cmdstat |= PCI_COMMAND_IO; + pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat); pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, CONFIG_SYS_PCI_CACHE_LINE_SIZE); pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80); } -int pciauto_setup_rom(struct pci_controller *hose, pci_dev_t dev) -{ - pci_addr_t bar_value; - pci_size_t bar_size; - u32 bar_response; - u16 cmdstat = 0; - - pci_hose_write_config_dword(hose, dev, PCI_ROM_ADDRESS, 0xfffffffe); - pci_hose_read_config_dword(hose, dev, PCI_ROM_ADDRESS, &bar_response); - if (!bar_response) - return -ENOENT; - - bar_size = -(bar_response & ~1); - DEBUGF("PCI Autoconfig: ROM, size=%#x, ", bar_size); - if (pciauto_region_allocate(hose->pci_mem, bar_size, &bar_value) == 0) { - pci_hose_write_config_dword(hose, dev, PCI_ROM_ADDRESS, - bar_value); - } - DEBUGF("\n"); - pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat); - cmdstat |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; - pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat); - - return 0; -} - void pciauto_prescan_setup_bridge(struct pci_controller *hose, pci_dev_t dev, int sub_bus) { - struct pci_region *pci_mem = hose->pci_mem; - struct pci_region *pci_prefetch = hose->pci_prefetch; - struct pci_region *pci_io = hose->pci_io; - u16 cmdstat; + struct pci_region *pci_mem; + struct pci_region *pci_prefetch; + struct pci_region *pci_io; + u16 cmdstat, prefechable_64; + +#ifdef CONFIG_DM_PCI + /* The root controller has the region information */ + struct pci_controller *ctlr_hose = pci_bus_to_hose(0); + + pci_mem = ctlr_hose->pci_mem; + pci_prefetch = ctlr_hose->pci_prefetch; + pci_io = ctlr_hose->pci_io; +#else + pci_mem = hose->pci_mem; + pci_prefetch = hose->pci_prefetch; + pci_io = hose->pci_io; +#endif pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat); + pci_hose_read_config_word(hose, dev, PCI_PREF_MEMORY_BASE, + &prefechable_64); + prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK; /* Configure bus number registers */ +#ifdef CONFIG_DM_PCI + pci_hose_write_config_byte(hose, dev, PCI_PRIMARY_BUS, PCI_BUS(dev)); + pci_hose_write_config_byte(hose, dev, PCI_SECONDARY_BUS, sub_bus); +#else pci_hose_write_config_byte(hose, dev, PCI_PRIMARY_BUS, PCI_BUS(dev) - hose->first_busno); pci_hose_write_config_byte(hose, dev, PCI_SECONDARY_BUS, sub_bus - hose->first_busno); +#endif pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, 0xff); if (pci_mem) { @@ -252,12 +274,26 @@ void pciauto_prescan_setup_bridge(struct pci_controller *hose, /* Set up memory and I/O filter limits, assume 32-bit I/O space */ pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE, (pci_prefetch->bus_lower & 0xfff00000) >> 16); + if (prefechable_64 == PCI_PREF_RANGE_TYPE_64) +#ifdef CONFIG_SYS_PCI_64BIT + pci_hose_write_config_dword(hose, dev, + PCI_PREF_BASE_UPPER32, + pci_prefetch->bus_lower >> 32); +#else + pci_hose_write_config_dword(hose, dev, + PCI_PREF_BASE_UPPER32, + 0x0); +#endif cmdstat |= PCI_COMMAND_MEMORY; } else { /* We don't support prefetchable memory for now, so disable */ pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE, 0x1000); pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, 0x0); + if (prefechable_64 == PCI_PREF_RANGE_TYPE_64) { + pci_hose_write_config_word(hose, dev, PCI_PREF_BASE_UPPER32, 0x0); + pci_hose_write_config_word(hose, dev, PCI_PREF_LIMIT_UPPER32, 0x0); + } } if (pci_io) { @@ -280,13 +316,30 @@ void pciauto_prescan_setup_bridge(struct pci_controller *hose, void pciauto_postscan_setup_bridge(struct pci_controller *hose, pci_dev_t dev, int sub_bus) { - struct pci_region *pci_mem = hose->pci_mem; - struct pci_region *pci_prefetch = hose->pci_prefetch; - struct pci_region *pci_io = hose->pci_io; + struct pci_region *pci_mem; + struct pci_region *pci_prefetch; + struct pci_region *pci_io; + +#ifdef CONFIG_DM_PCI + /* The root controller has the region information */ + struct pci_controller *ctlr_hose = pci_bus_to_hose(0); + + pci_mem = ctlr_hose->pci_mem; + pci_prefetch = ctlr_hose->pci_prefetch; + pci_io = ctlr_hose->pci_io; +#else + pci_mem = hose->pci_mem; + pci_prefetch = hose->pci_prefetch; + pci_io = hose->pci_io; +#endif /* Configure bus number registers */ +#ifdef CONFIG_DM_PCI + pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, sub_bus); +#else pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, sub_bus - hose->first_busno); +#endif if (pci_mem) { /* Round memory allocator to 1MB boundary */ @@ -297,11 +350,28 @@ void pciauto_postscan_setup_bridge(struct pci_controller *hose, } if (pci_prefetch) { + u16 prefechable_64; + + pci_hose_read_config_word(hose, dev, + PCI_PREF_MEMORY_LIMIT, + &prefechable_64); + prefechable_64 &= PCI_PREF_RANGE_TYPE_MASK; + /* Round memory allocator to 1MB boundary */ pciauto_region_align(pci_prefetch, 0x100000); pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, (pci_prefetch->bus_lower - 1) >> 16); + if (prefechable_64 == PCI_PREF_RANGE_TYPE_64) +#ifdef CONFIG_SYS_PCI_64BIT + pci_hose_write_config_dword(hose, dev, + PCI_PREF_LIMIT_UPPER32, + (pci_prefetch->bus_lower - 1) >> 32); +#else + pci_hose_write_config_dword(hose, dev, + PCI_PREF_LIMIT_UPPER32, + 0x0); +#endif } if (pci_io) { @@ -349,7 +419,7 @@ void pciauto_config_init(struct pci_controller *hose) if (hose->pci_mem) { pciauto_region_init(hose->pci_mem); - DEBUGF("PCI Autoconfig: Bus Memory region: [0x%llx-0x%llx],\n" + debug("PCI Autoconfig: Bus Memory region: [0x%llx-0x%llx],\n" "\t\tPhysical Memory [%llx-%llxx]\n", (u64)hose->pci_mem->bus_start, (u64)(hose->pci_mem->bus_start + hose->pci_mem->size - 1), @@ -360,7 +430,7 @@ void pciauto_config_init(struct pci_controller *hose) if (hose->pci_prefetch) { pciauto_region_init(hose->pci_prefetch); - DEBUGF("PCI Autoconfig: Bus Prefetchable Mem: [0x%llx-0x%llx],\n" + debug("PCI Autoconfig: Bus Prefetchable Mem: [0x%llx-0x%llx],\n" "\t\tPhysical Memory [%llx-%llx]\n", (u64)hose->pci_prefetch->bus_start, (u64)(hose->pci_prefetch->bus_start + @@ -373,7 +443,7 @@ void pciauto_config_init(struct pci_controller *hose) if (hose->pci_io) { pciauto_region_init(hose->pci_io); - DEBUGF("PCI Autoconfig: Bus I/O region: [0x%llx-0x%llx],\n" + debug("PCI Autoconfig: Bus I/O region: [0x%llx-0x%llx],\n" "\t\tPhysical Memory: [%llx-%llx]\n", (u64)hose->pci_io->bus_start, (u64)(hose->pci_io->bus_start + hose->pci_io->size - 1), @@ -389,22 +459,44 @@ void pciauto_config_init(struct pci_controller *hose) */ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev) { + struct pci_region *pci_mem; + struct pci_region *pci_prefetch; + struct pci_region *pci_io; unsigned int sub_bus = PCI_BUS(dev); unsigned short class; - unsigned char prg_iface; int n; +#ifdef CONFIG_DM_PCI + /* The root controller has the region information */ + struct pci_controller *ctlr_hose = pci_bus_to_hose(0); + + pci_mem = ctlr_hose->pci_mem; + pci_prefetch = ctlr_hose->pci_prefetch; + pci_io = ctlr_hose->pci_io; +#else + pci_mem = hose->pci_mem; + pci_prefetch = hose->pci_prefetch; + pci_io = hose->pci_io; +#endif + pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class); switch (class) { case PCI_CLASS_BRIDGE_PCI: - hose->current_busno++; - pciauto_setup_device(hose, dev, 2, hose->pci_mem, - hose->pci_prefetch, hose->pci_io); + debug("PCI Autoconfig: Found P2P bridge, device %d\n", + PCI_DEV(dev)); - DEBUGF("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_DEV(dev)); + pciauto_setup_device(hose, dev, 2, pci_mem, + pci_prefetch, pci_io); +#ifdef CONFIG_DM_PCI + n = dm_pci_hose_probe_bus(hose, dev); + if (n < 0) + return n; + sub_bus = (unsigned int)n; +#else /* Passing in current_busno allows for sibling P2P bridges */ + hose->current_busno++; pciauto_prescan_setup_bridge(hose, dev, hose->current_busno); /* * need to figure out if this is a subordinate bridge on the bus @@ -417,17 +509,7 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev) pciauto_postscan_setup_bridge(hose, dev, sub_bus); sub_bus = hose->current_busno; - break; - - case PCI_CLASS_STORAGE_IDE: - pci_hose_read_config_byte(hose, dev, PCI_CLASS_PROG, &prg_iface); - if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) { - DEBUGF("PCI Autoconfig: Skipping legacy mode IDE controller\n"); - return sub_bus; - } - - pciauto_setup_device(hose, dev, 6, hose->pci_mem, - hose->pci_prefetch, hose->pci_io); +#endif break; case PCI_CLASS_BRIDGE_CARDBUS: @@ -435,19 +517,21 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev) * just do a minimal setup of the bridge, * let the OS take care of the rest */ - pciauto_setup_device(hose, dev, 0, hose->pci_mem, - hose->pci_prefetch, hose->pci_io); + pciauto_setup_device(hose, dev, 0, pci_mem, + pci_prefetch, pci_io); - DEBUGF("PCI Autoconfig: Found P2CardBus bridge, device %d\n", - PCI_DEV(dev)); + debug("PCI Autoconfig: Found P2CardBus bridge, device %d\n", + PCI_DEV(dev)); +#ifndef CONFIG_DM_PCI hose->current_busno++; +#endif break; #if defined(CONFIG_PCIAUTO_SKIP_HOST_BRIDGE) case PCI_CLASS_BRIDGE_OTHER: - DEBUGF("PCI Autoconfig: Skipping bridge device %d\n", - PCI_DEV(dev)); + debug("PCI Autoconfig: Skipping bridge device %d\n", + PCI_DEV(dev)); break; #endif #if defined(CONFIG_MPC834x) && !defined(CONFIG_VME8349) @@ -458,18 +542,18 @@ int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev) * device claiming resources io/mem/irq.. we only allow for * the PIMMR window to be allocated (BAR0 - 1MB size) */ - DEBUGF("PCI Autoconfig: Broken bridge found, only minimal config\n"); + debug("PCI Autoconfig: Broken bridge found, only minimal config\n"); pciauto_setup_device(hose, dev, 0, hose->pci_mem, hose->pci_prefetch, hose->pci_io); break; #endif case PCI_CLASS_PROCESSOR_POWERPC: /* an agent or end-point */ - DEBUGF("PCI AutoConfig: Found PowerPC device\n"); + debug("PCI AutoConfig: Found PowerPC device\n"); default: - pciauto_setup_device(hose, dev, 6, hose->pci_mem, - hose->pci_prefetch, hose->pci_io); + pciauto_setup_device(hose, dev, 6, pci_mem, + pci_prefetch, pci_io); break; }