| /* |
| * (C) Copyright 2000 |
| * Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
| * |
| * See file CREDITS for list of people who contributed to this |
| * project. |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License as |
| * published by the Free Software Foundation; either version 2 of |
| * the License, or (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
| * MA 02111-1307 USA |
| * |
| */ |
| /******************************************************************************* |
| Copyright (C) Marvell International Ltd. and its affiliates |
| |
| ******************************************************************************** |
| Marvell GPL License Option |
| |
| If you received this File from Marvell, you may opt to use, redistribute and/or |
| modify this File in accordance with the terms and conditions of the General |
| Public License Version 2, June 1991 (the "GPL License"), a copy of which is |
| available along with the File in the license.txt file or by writing to the Free |
| Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or |
| on the worldwide web at http://www.gnu.org/licenses/gpl.txt. |
| |
| THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED |
| WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY |
| DISCLAIMED. The GPL License provides additional details about this warranty |
| disclaimer. |
| |
| *******************************************************************************/ |
| |
| /* PCI.c - PCI functions */ |
| #include "mvCommon.h" |
| #include <common.h> |
| #include <config.h> |
| #include <command.h> |
| #if defined(CONFIG_CMD_PCI) |
| |
| #include <pci.h> |
| #include "mvSysPexApi.h" |
| #include "pex/mvPexRegs.h" |
| #include "gpp/mvGpp.h" |
| //#include "pci-if/mvPciIf.h" |
| #include "ctrlEnv/mvCtrlEnvLib.h" |
| #include "ctrlEnv/mvCtrlEnvSpec.h" |
| #include "boardEnv/mvBoardEnvLib.h" |
| #include "ctrlEnv/sys/mvCpuIf.h" |
| #include "pci-if/pci_util/mvPciUtils.h" |
| |
| #undef DEBUG |
| #ifdef DEBUG |
| #define DB(x) x |
| #else |
| #define DB(x) |
| #endif /* DEBUG */ |
| |
| /* global definetion */ |
| #define REG_NUM_MASK (0x3FF << 2) |
| |
| /* global indicate wether we are in the scan process */ |
| unsigned int scan_in_progress = 0; |
| extern unsigned int whoAmI(void); |
| |
| #if defined(CONFIG_CMD_BSP) |
| /****************************************************************************** |
| * Category - PCI0 |
| * Functionality- Scans PCI0 for devices and prints relevant information |
| * Need modifications (Yes/No) - No |
| *****************************************************************************/ |
| MV_BOOL scanPci(MV_U32 host) |
| { |
| MV_U32 index, numOfElements = 4 * 8, barIndex; |
| MV_PCI_DEVICE pciDevices[4 * 8]; //3 slots and us,Max 8 functions per slot |
| |
| memset(&pciDevices, 0, 12 * sizeof(MV_PCI_DEVICE)); |
| |
| if (mvPciScan(host, pciDevices, &numOfElements) != MV_OK) { |
| DB(printf("scanPci:mvPciScan failed for host %d \n", host)); |
| return MV_FALSE; |
| } |
| |
| for (index = 0; index < numOfElements; index++) { |
| printf("\nBus: %x Device: %x Func: %x Vendor ID: %x Device ID: %x\n", |
| pciDevices[index].busNumber, |
| pciDevices[index].deviceNum, |
| pciDevices[index].function, |
| pciDevices[index].venID, |
| pciDevices[index].deviceID); |
| |
| printf("-------------------------------------------------------------------\n"); |
| |
| printf("Class: %s\n", pciDevices[index].type); |
| |
| /* check if we are bridge*/ |
| if ((pciDevices[index].baseClassCode == PCI_BRIDGE_CLASS) && |
| (pciDevices[index].subClassCode == P2P_BRIDGE_SUB_CLASS_CODE)) { |
| printf("Primary Bus:0x%x \tSecondary Bus:0x%x \tSubordinate Bus:0x%x\n", |
| pciDevices[index].p2pPrimBusNum, |
| pciDevices[index].p2pSecBusNum, |
| pciDevices[index].p2pSubBusNum); |
| |
| printf("IO Base:0x%x \t\tIO Limit:0x%x", pciDevices[index].p2pIObase, |
| pciDevices[index].p2pIOLimit); |
| |
| (pciDevices[index].bIO32) ? (printf(" (32Bit IO)\n")) : |
| (printf(" (16Bit IO)\n")); |
| |
| printf("Memory Base:0x%x \tMemory Limit:0x%x\n", pciDevices[index].p2pMemBase, |
| pciDevices[index].p2pMemLimit); |
| |
| printf("Pref Memory Base:0x%x \tPref Memory Limit:0x%x", |
| pciDevices[index].p2pPrefMemBase, |
| pciDevices[index].p2pPrefMemLimit); |
| |
| (pciDevices[index].bPrefMem64) ? (printf(" (64Bit PrefMem)\n")) : |
| (printf(" (32Bit PrefMem)\n")); |
| if (pciDevices[index].bPrefMem64) { |
| printf("Pref Base Upper 32bit:0x%x \tPref Limit Base Upper32 bit:0x%x\n", |
| pciDevices[index].p2pPrefBaseUpper32Bits, |
| pciDevices[index].p2pPrefLimitUpper32Bits); |
| } |
| } |
| |
| for (barIndex = 0; barIndex < pciDevices[index].barsNum; barIndex++) { |
| if (pciDevices[index].pciBar[barIndex].barType == PCI_64BIT_BAR) { |
| printf("PCI_BAR%d (%s-%s) base: %x%08x%s", barIndex, |
| (pciDevices[index].pciBar[barIndex].barMapping == PCI_MEMORY_BAR) ? "Mem" : "I/O", |
| "64bit", |
| pciDevices[index].pciBar[barIndex].barBaseHigh, |
| pciDevices[index].pciBar[barIndex].barBaseLow, |
| (pciDevices[index].pciBar[barIndex].barBaseLow == 0) ? "\t\t" : "\t"); |
| }else if (pciDevices[index].pciBar[barIndex].barType == PCI_32BIT_BAR) { |
| printf("PCI_BAR%d (%s-%s) base: %x%s", barIndex, |
| (pciDevices[index].pciBar[barIndex].barMapping == PCI_MEMORY_BAR) ? "Mem" : "I/O", |
| "32bit", |
| pciDevices[index].pciBar[barIndex].barBaseLow, |
| (pciDevices[index].pciBar[barIndex].barBaseLow == 0) ? "\t\t\t" : "\t\t"); |
| } |
| |
| if (pciDevices[index].pciBar[barIndex].barSizeHigh != 0) |
| printf("size: %d%08d bytes\n", pciDevices[index].pciBar[barIndex].barSizeHigh, |
| pciDevices[index].pciBar[barIndex].barSizeLow); |
| else |
| printf("size: %dMb\n", pciDevices[index].pciBar[barIndex].barSizeLow / 1024 / 1024); |
| } |
| } |
| return MV_TRUE; |
| } |
| |
| int sp_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| MV_U32 host = 0; |
| #ifdef CONFIG_PCIE_IF_MAPPING |
| MV_BOARD_PEX_INFO *boardPexInfo = mvBoardPexInfoGet(); |
| #endif |
| MV_U32 pexHWInf = 0; |
| |
| #ifdef CONFIG_PCIE_IF_MAPPING |
| printf("PCI interfaces mapping:\n"); |
| printf("+-------------------------+---+---+---+---+---+---+---+\n"); |
| printf("| Active interface number | 0 | 1 | 2 | 3 |\n"); |
| printf("+-------------------------+---+---+---+---+---+---+---+\n"); |
| printf("| HW interface number | %d | %d | %d | %d |\n", |
| boardPexInfo->pexMapping[0], boardPexInfo->pexMapping[1], |
| boardPexInfo->pexMapping[2], boardPexInfo->pexMapping[3]); |
| printf("+-------------------------+---+---+---+---+---+---+---+\n\n"); |
| #endif |
| |
| if (argc > 1) |
| host = simple_strtoul(argv[1], NULL, 10); |
| |
| if (host >= mvCtrlPexMaxIfGet()) { |
| printf("PCI %d doesn't exist\n", host); |
| return 1; |
| } |
| |
| #ifdef CONFIG_PCIE_IF_MAPPING |
| pexHWInf = boardPexInfo->pexMapping[host]; |
| #else |
| pexHWInf = host; |
| #endif |
| |
| printf("Scanning PCIe HW interface %d\n", pexHWInf); |
| if ( scanPci(pexHWInf) == MV_FALSE) |
| printf("PCIe %d Scan - FAILED!!.\n", host); |
| return 1; |
| } |
| |
| U_BOOT_CMD( |
| sp, 2, 1, sp_cmd, |
| "scan and detect all devices on PCI-e interface", |
| "[active interface number]\n" |
| ); |
| |
| int me_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| MV_U32 host = 0; |
| |
| if (argc > 1) |
| host = simple_strtoul(argv[1], NULL, 10); |
| |
| if (host >= mvCtrlPexMaxIfGet()) { |
| printf("Master %d doesn't exist\n", host); |
| return 1; |
| } |
| |
| if (mvPexMasterEnable(host, MV_TRUE) == MV_OK) |
| printf("PCIe %d Master enabled.\n", host); |
| else |
| printf("PCIe %d Master enabled -FAILED!!\n", host); |
| |
| return 1; |
| } |
| |
| U_BOOT_CMD( |
| me, 2, 1, me_cmd, |
| "me - PCIe master enable\n", |
| " [0/1] \n" |
| "\tEnable the MV device as Master on PCIe 0/1. \n" |
| ); |
| |
| int se_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| MV_U32 host = 0, dev = 0, bus = 0; |
| #ifdef CONFIG_PCIE_IF_MAPPING |
| MV_BOARD_PEX_INFO *boardPexInfo = mvBoardPexInfoGet(); |
| #endif |
| MV_U32 pexHWInf = 0; |
| |
| if (argc != 4) { |
| printf("Usage:\n%s\n", cmdtp->usage); |
| return 1; |
| } |
| |
| host = simple_strtoul(argv[1], NULL, 10); |
| bus = simple_strtoul(argv[2], NULL, 16); |
| dev = simple_strtoul(argv[3], NULL, 16); |
| |
| if (host >= mvCtrlPexMaxIfGet()) { |
| printf("PCIe %d doesn't exist\n", host); |
| return 1; |
| } |
| |
| #ifdef CONFIG_PCIE_IF_MAPPING |
| pexHWInf = boardPexInfo->pexMapping[host]; |
| #else |
| pexHWInf = host; |
| #endif |
| |
| if (mvPexSlaveEnable(pexHWInf, bus, dev, MV_TRUE) == MV_OK) |
| printf("PCIe %d Bus %d Slave 0x%x enabled.\n", host, bus, dev); |
| else |
| printf("PCIe %d Bus %d Slave 0x%x enabled - FAILED!!.\n", host, bus, dev); |
| return 1; |
| } |
| |
| U_BOOT_CMD( |
| se, 4, 1, se_cmd, |
| "se - PCIe Slave enable\n", |
| " [0/1] bus dev \n" |
| "\tEnable the PCIe device as Slave on PCIe 0/1. \n" |
| ); |
| |
| /****************************************************************************** |
| * Functionality- The commands changes the pci remap register and displays the |
| * address to be used in order to access PCI 0. |
| *****************************************************************************/ |
| int mapPci_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| MV_ADDR_WIN pciWin; |
| MV_TARGET target = 0; |
| MV_U32 host = 0, effectiveBaseAddress = 0; |
| #ifdef CONFIG_PCIE_IF_MAPPING |
| MV_BOARD_PEX_INFO *boardPexInfo = mvBoardPexInfoGet(); |
| #endif |
| MV_U32 pexHWInf = 0; |
| |
| pciWin.baseLow = 0; |
| pciWin.baseHigh = 0; |
| |
| if (argc > 1) |
| host = simple_strtoul(argv[1], NULL, 10); |
| |
| if (argc > 2) |
| pciWin.baseLow = simple_strtoul(argv[2], NULL, 16); |
| |
| if (host >= mvCtrlPexMaxIfGet()) { |
| printf("PCIe %d doesn't exist\n", host); |
| return 1; |
| } |
| |
| #ifdef CONFIG_PCIE_IF_MAPPING |
| pexHWInf = boardPexInfo->pexMapping[host]; |
| #else |
| pexHWInf = host; |
| #endif |
| |
| target = PCI0_MEM0 + (2 * pexHWInf); |
| |
| printf("mapping pci %x to address 0x%x\n", host, pciWin.baseLow); |
| |
| #if defined(MV_INCLUDE_PEX) || defined(MV_INCLUDE_PCI) |
| effectiveBaseAddress = mvCpuIfPexRemap(target, &pciWin); |
| #endif |
| |
| if ( effectiveBaseAddress == 0xffffffff) { |
| printf("Error remapping\n"); |
| return 1; |
| } |
| |
| printf("PCIe %x Access base address : %x\n", host, effectiveBaseAddress); |
| return 1; |
| } |
| |
| U_BOOT_CMD( |
| mp, 3, 1, mapPci_cmd, |
| "mp - map PCIe BAR\n", |
| " [0/1] address \n" |
| "\tChange the remap of PCIe 0/1 window 0 to address 'addrress'.\n" |
| "\tIt also displays the new access address, since the remap is not always\n" |
| "\tthe same as requested. \n" |
| ); |
| |
| #endif |
| |
| MV_U32 mv_mem_ctrl_dev(MV_U32 pexIf, MV_U32 bus, MV_U32 dev) |
| { |
| MV_U32 ven, class; |
| |
| ven = mvPexConfigRead(pexIf, bus, dev, 0, PCI_VENDOR_ID) & 0xffff; |
| class = (mvPexConfigRead(pexIf, bus, dev, 0, PCI_REVISION_ID) >> 16 ) & 0xffff; |
| /* if we got any other Marvell PCI cards ignore it. */ |
| if (((ven == 0x11ab) && (class == PCI_CLASS_MEMORY_OTHER)) || |
| ((ven == 0x11ab) && (class == PCI_CLASS_BRIDGE_HOST))) |
| return 1; |
| return 0; |
| } |
| |
| static int mv_read_config_dword(struct pci_controller *hose, |
| pci_dev_t dev, |
| int offset, u32* value) |
| { |
| MV_U32 bus, func, regOff, dev_no; |
| char *env; |
| |
| bus = PCI_BUS(dev); |
| dev_no = PCI_DEV(dev); |
| |
| func = (MV_U32)PCI_FUNC(dev); |
| regOff = (MV_U32)offset & REG_NUM_MASK; |
| |
| /* We will scan only ourselves and the PCI slots that exist on the |
| board, because we may have a case that we have one slot that has |
| a Cardbus connector, and because CardBus answers all IDsels we want |
| to scan only this slot and ourseleves. |
| */ |
| |
| if ( scan_in_progress == 1) { |
| env = getenv("disaMvPnp"); |
| if (env && ( (strcmp(env, "yes") == 0) || (strcmp(env, "Yes") == 0) ) ) { |
| if ( mv_mem_ctrl_dev((MV_U32)hose->cfg_addr, bus, dev_no) ) { |
| *value = 0xffffffff; |
| return 0; |
| } |
| } |
| } |
| |
| *value = (u32)mvPexConfigRead((MV_U32)hose->cfg_addr, bus, dev_no, |
| func, regOff); |
| |
| DB(printf("PEX%d CFG READ bus=%d dev=%d func=%d reg=%x val=%x\n", |
| hose->cfg_addr, bus, dev_no, func, regOff, *value)); |
| |
| return 0; |
| } |
| |
| static int mv_write_config_dword(struct pci_controller *hose, |
| pci_dev_t dev, |
| int offset, u32 value) |
| { |
| MV_U32 bus, func, regOff, dev_no; |
| |
| bus = PCI_BUS(dev); |
| dev_no = PCI_DEV(dev); |
| func = (MV_U32)PCI_FUNC(dev); |
| regOff = offset & REG_NUM_MASK; |
| mvPexConfigWrite((MV_U32)hose->cfg_addr, bus, dev_no, func, regOff, value); |
| |
| DB(printf("PEX%d CFG WRITE bus=%d dev=%d func=%d reg=%x val=%x\n", |
| hose->cfg_addr, bus, dev_no, func, regOff, value)); |
| |
| return 0; |
| } |
| |
| static void mv_setup_ide(struct pci_controller *hose, |
| pci_dev_t dev, struct pci_config_table *entry) |
| { |
| static const int ide_bar[] = { 8, 4, 8, 4, 16, 1024 }; |
| u32 bar_response, bar_value; |
| int bar; |
| |
| for (bar = 0; bar < 6; bar++) { |
| /*ronen different function for 3rd bank.*/ |
| unsigned int offset = (bar < 2) ? bar * 8 : 0x100 + (bar - 2) * 8; |
| |
| pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + offset, 0x0); |
| pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + offset, &bar_response); |
| |
| pciauto_region_allocate(bar_response & PCI_BASE_ADDRESS_SPACE_IO ? |
| hose->pci_io : hose->pci_mem, ide_bar[bar], &bar_value); |
| |
| pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, bar_value); |
| } |
| } |
| |
| static void mv_setup_host(struct pci_controller *hose, |
| pci_dev_t dev, struct pci_config_table *entry) |
| { |
| //skip our host |
| DB(printf("skipping :bus=%x dev=%x fun=%x\n", |
| (unsigned int)PCI_BUS(dev), |
| (unsigned int)PCI_DEV(dev), |
| (unsigned int)PCI_FUNC(dev))); |
| return; |
| } |
| |
| static void mv_pci_bus_mode_display(MV_U32 host, int bus) |
| { |
| #if defined(MV_INCLUDE_PEX) |
| |
| MV_PEX_MODE pexMode; |
| MV_U32 pexHWInf; |
| MV_32 linkDelayCount; |
| #ifdef CONFIG_PCIE_IF_MAPPING |
| MV_BOARD_PEX_INFO *boardPexInfo = mvBoardPexInfoGet(); |
| if (boardPexInfo == NULL) { |
| printf("mv_pci_bus_mode_display: mvBoardPexInfoGet failed\n"); |
| return; |
| } |
| pexHWInf = boardPexInfo->pexMapping[host]; |
| #else |
| pexHWInf = host; |
| #endif |
| |
| if (mvPexModeGet(pexHWInf, &pexMode) != MV_OK) |
| printf("mv_pci_bus_mode_display: mvPexModeGet failed\n"); |
| |
| #ifdef CONFIG_PCIE_IF_MAPPING |
| printf("PCI-e %d (IF %d - bus %d) ", pexHWInf , host, bus); |
| #else |
| printf("PCI-e %d: (bus %d) ",host, bus); |
| #endif |
| |
| switch (pexMode.pexType) { |
| case MV_PEX_ROOT_COMPLEX: |
| printf("Root Complex Interface"); |
| break; |
| case MV_PEX_END_POINT: |
| printf("End Point Interface"); |
| break; |
| } |
| linkDelayCount = 2000; |
| while (!(pexMode.pexLinkUp) && (linkDelayCount)) { |
| mvOsDelay(1); |
| linkDelayCount--; |
| if (mvPexModeGet(pexHWInf, &pexMode) != MV_OK) { |
| printf("mv_pci_bus_mode_display: mvPexModeGet failed\n"); |
| break; |
| } |
| } |
| |
| /* Check if we have link */ |
| if (!(pexMode.pexLinkUp)) |
| printf(", no Link.\n"); |
| else{ |
| if (MV_PEX_WITDH_X1 == pexMode.pexWidth) |
| printf(", Detected Link X1"); |
| else if (MV_PEX_WITDH_X4 == pexMode.pexWidth) |
| printf(", Detected Link X4"); |
| if (MV_PEX_GEN2_0 == pexMode.pexGen) |
| printf(", GEN 2.0\n"); |
| else if (MV_PEX_GEN1_1 == pexMode.pexGen) |
| printf(", GEN 1.1\n"); |
| |
| } |
| |
| return; |
| |
| #endif /* MV_INCLUDE_PEX */ |
| } |
| |
| struct pci_config_table mv_config_table[] = { |
| { PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE, |
| PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, mv_setup_ide }, |
| |
| { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, |
| PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, mv_setup_host }, //PCI host |
| |
| {} |
| |
| }; |
| |
| /* Defines for more modularity of the pci_init_board function */ |
| |
| struct pci_controller pci_hose[MV_PEX_MAX_IF]; |
| |
| #define PCI_IF_MEM(pexIf) ((pexIf == 0) ? PCI_IF0_MEM0 : PCI_IF1_MEM0) |
| #define PCI_IF_REMAPED_MEM_BASE(pexIf) ((pexIf == 0) ? PCI_IF0_REMAPED_MEM_BASE : PCI_IF1_REMAPED_MEM_BASE) |
| #define PCI_IF_MEM_BASE(pexIf) ((pexIf == 0) ? PCI_IF0_MEM0_BASE : PCI_IF1_MEM0_BASE) |
| #define PCI_IF_MEM_SIZE(pexIf) ((pexIf == 0) ? PCI_IF0_MEM0_SIZE : PCI_IF1_MEM0_SIZE) |
| #define PCI_IF_IO_BASE(pexIf) ((pexIf == 0) ? PCI_IF0_IO_BASE : PCI_IF1_IO_BASE) |
| #define PCI_IF_IO_SIZE(pexIf) ((pexIf == 0) ? PCI_IF0_IO_SIZE : PCI_IF1_IO_SIZE) |
| |
| /* because of CIV team needs we are gonna do a remap to PCI memory */ |
| #define PCI_IF0_REMAPED_MEM_BASE 0x40000000 |
| #define PCI_IF1_REMAPED_MEM_BASE 0x40000000 |
| |
| int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev) |
| { |
| return 0; |
| } |
| |
| void pci_init_board(void) |
| { |
| /* Pex scan skipped by secondary CPUs*/ |
| if (whoAmI() != 0) |
| return; |
| |
| MV_U32 activePexCount; |
| MV_ADDR_WIN rempWin; |
| MV_CPU_DEC_WIN cpuAddrDecWin; |
| PCI_IF_MODE pexIfMode = PCI_IF_MODE_HOST; |
| MV_U32 pexHWInf, pexIf; |
| struct pci_controller *pci; |
| char *env; |
| int status; |
| MV_U32 link_found, lastPexIfWithFoundLink; |
| #ifdef CONFIG_PCIE_IF_MAPPING |
| MV_BOARD_PEX_INFO *boardPexInfo = mvBoardPexInfoGet(); |
| #endif |
| |
| activePexCount = mvCtrlPexMaxIfGet(); |
| if (activePexCount == 0) |
| return; |
| |
| env = getenv("disaMvPnp"); |
| |
| if (env && ( (strcmp(env, "yes") == 0) || (strcmp(env, "Yes") == 0) ) ) |
| printf("Warning: skip configuration of Marvell devices!!!\n"); |
| |
| DB(printf("Start scan of %d PEX interfaces\n", activePexCount)); |
| |
| /* Initialize and scan all PEX interfaces */ |
| for (pexIf = 0; pexIf < activePexCount; pexIf++) { |
| |
| pci = &pci_hose[pexIf]; |
| #ifdef CONFIG_PCIE_IF_MAPPING |
| pexHWInf = boardPexInfo->pexMapping[pexIf]; |
| #else |
| pexHWInf = pexIf; |
| #endif |
| DB(printf("Starting scan of PEX%d\n", pexHWInf)); |
| |
| /* Set bus numbers in U-BOOT stack */ |
| if (pexIf == 0) { |
| pci->first_busno = 0; |
| pci->last_busno = 0; |
| link_found = 0; |
| lastPexIfWithFoundLink = 0; |
| } |
| else if (!link_found) { |
| /* No link was found in previous PEX interfaces */ |
| pci->first_busno = 0; |
| DB(printf("Set first,last=%d,%d bus numbers in U-BOOT stack for pexIf %d\n", |
| pci->first_busno, pci->last_busno, pexIf)); |
| } |
| else { |
| pci->first_busno = pci_hose[lastPexIfWithFoundLink].last_busno + 1; |
| pci->last_busno = pci->first_busno; |
| DB(printf("Set first,last=%d,%d bus numbers in U-BOOT stack according to previously found pexIf.last_busno=%d.%d\n", |
| pci->first_busno, pci->last_busno, lastPexIfWithFoundLink, |
| pci_hose[lastPexIfWithFoundLink].last_busno)); |
| } |
| |
| pci->config_table = mv_config_table; |
| /* Check if PEX IF is powered */ |
| if (MV_FALSE == mvCtrlPwrClckGet(PEX_UNIT_ID, pexHWInf)) |
| continue; |
| |
| /* Set device or host mode */ |
| #if defined(MV_INCLUDE_PEX) |
| /* Set pex mode incase S@R not exist */ |
| env = getenv("pexMode"); |
| if (env && (((strcmp(env, "EP") == 0) || (strcmp(env, "ep") == 0) ))) |
| pexIfMode = MV_PEX_END_POINT; |
| else |
| pexIfMode = MV_PEX_ROOT_COMPLEX; |
| #endif |
| |
| #if defined(DB_78X60_PCAC) || defined(DB_78X60_PCAC_REV2) || defined(DB_88F6710_PCAC) |
| pexIfMode = MV_PEX_END_POINT; |
| #endif |
| |
| #if defined(DB_78X60_AMC) |
| pexIfMode = MV_PEX_ROOT_COMPLEX; |
| #endif |
| |
| DB(printf("Initializing HAL\n")); |
| |
| status = mvSysPexInit(pexHWInf, pexIfMode, pexIf); |
| if (status == MV_ERROR) |
| printf("pci_init_board:Error calling mvPexIfInit for PCI-e%d (%d)\n", |
| pexHWInf, pexIf); |
| else { |
| if (status == MV_OK) { |
| /* Start counting PCI buses since at least one interface was found with LINK UP */ |
| link_found = 1; |
| lastPexIfWithFoundLink = pexIf; |
| |
| /* Link detected. Set U-BOOT scan parameters */ |
| pci->current_busno = pci->first_busno; |
| pci->last_busno = 0xff; |
| |
| /* |
| * Set device number to 1 to enable detecting |
| * Devices that answer only when device is 0 |
| */ |
| DB(printf("Set local device number to 1 in pexHWInf %d\n", pexHWInf)); |
| mvPexLocalDevNumSet(pexHWInf, 1); |
| |
| /* Set bus No based on previous scan results */ |
| DB(printf("Set bus number %d in pexHWInf %d on previous scan results\n", |
| pci->first_busno, pexHWInf)); |
| if (mvPexLocalBusNumSet(pexHWInf, pci->first_busno) != MV_OK) |
| printf("pci_init_board:Error calling mvPexLocalBusNumSet for pexIf %d\n", pexIf); |
| }else { |
| /* Interface with no link */ |
| printf("PCI-e %d: Detected No Link.\n", pexIf); |
| if (pci->first_busno) { |
| pci->first_busno = 0; |
| pci->last_busno = 0; |
| } |
| continue; |
| } |
| } |
| |
| /* Print PEX unit, port, active IF and first bus numbers */ |
| mv_pci_bus_mode_display(pexIf, pci->first_busno); |
| |
| /* Skip scan if link is down */ |
| if (status == MV_NO_SUCH) { |
| pci->last_busno = pci->first_busno; |
| continue; |
| } |
| |
| /* Get the address decode windows */ |
| DB(printf("Setting memory regions\n")); |
| if (MV_OK != mvCpuIfTargetWinGet(PCI_MEM(pexHWInf, 0), &cpuAddrDecWin)) { |
| printf("%s: ERR. mvCpuIfTargetWinGet failed\n", __FUNCTION__); |
| return; |
| } |
| |
| rempWin.baseLow = ((cpuAddrDecWin.addrWin.baseLow & 0x0fffffff) | PCI_IF_REMAPED_MEM_BASE(pexHWInf)); |
| rempWin.baseHigh = 0; |
| |
| /* Perform a remap for the PEX0 interface */ |
| DB(printf("Performing remap for the PCI-e%d interface\n", pexHWInf)); |
| if (0xffffffff == mvCpuIfPexRemap(PCI_MEM(pexHWInf, 0), &rempWin)) { |
| printf("%s:mvCpuIfPexRemap failed, %d\n", __FUNCTION__, pexHWInf); |
| return; |
| } |
| |
| /* PCI memory space */ |
| pci_set_region(pci->regions + 0, |
| rempWin.baseLow, /* bus address */ |
| cpuAddrDecWin.addrWin.baseLow, |
| cpuAddrDecWin.addrWin.size, |
| PCI_REGION_MEM); |
| |
| if (MV_OK != mvCpuIfTargetWinGet(PCI_IO(pexHWInf), &cpuAddrDecWin)) |
| /* No I/O space */ |
| pci->region_count = 1; |
| else { |
| /* PCI I/O space */ |
| pci_set_region(pci->regions + 1, |
| cpuAddrDecWin.addrWin.baseLow, |
| cpuAddrDecWin.addrWin.baseLow, |
| cpuAddrDecWin.addrWin.size, |
| PCI_REGION_IO); |
| pci->region_count = 2; |
| } |
| |
| /* Connect to U-BOOT PCI stack */ |
| pci_set_ops(pci, |
| pci_hose_read_config_byte_via_dword, |
| pci_hose_read_config_word_via_dword, |
| mv_read_config_dword, |
| pci_hose_write_config_byte_via_dword, |
| pci_hose_write_config_word_via_dword, |
| mv_write_config_dword); |
| |
| pci->cfg_addr = (unsigned int*)pexHWInf; |
| |
| pci->config_table[1].bus = mvPexLocalBusNumGet(pexHWInf); |
| pci->config_table[1].dev = mvPexLocalDevNumGet(pexHWInf); |
| |
| pci_register_hose(pci); |
| |
| if (pexIfMode == PCI_IF_MODE_HOST) { |
| /* Perform the PCI bus scan */ |
| DB(printf("Starting bus scan\n")); |
| scan_in_progress = 1; |
| pci->last_busno = pci_hose_scan(pci); |
| scan_in_progress = 0; |
| |
| /*pci_fixup_bridge(pci, pexHWInf, pexIf);*/ |
| |
| }else |
| pci->last_busno = pci->first_busno; |
| } |
| |
| DB(printf("Completed PCI-e scan\n")); |
| #ifdef DB_FPGA |
| MV_REG_BIT_RESET(PCI_BASE_ADDR_ENABLE_REG(0), BIT10); |
| #endif |
| } |
| |
| #endif /* CONFIG_PCI */ |