PCIe endpoint support for AMCC Yucca 440SPe board
authorStefan Roese <sr@denx.de>
Tue, 29 Aug 2006 06:05:15 +0000 (08:05 +0200)
committerStefan Roese <sr@denx.de>
Tue, 29 Aug 2006 06:05:15 +0000 (08:05 +0200)
Patch by Tirumala R Marri, 26 Aug 2006

CHANGELOG
board/amcc/yucca/yucca.c
cpu/ppc4xx/440spe_pcie.c
cpu/ppc4xx/440spe_pcie.h

index a044b8e37d70f39e62a834e5214305682d4ea6d7..f09be8a1c161955a017726b25e694928b7b1f481 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,9 @@
 Changes since U-Boot 1.1.4:
 ======================================================================
 
+* PCIe endpoint support for AMCC Yucca 440SPe board
+  Patch by Tirumala R Marri, 26 Aug 2006
+
 * Improve DIMM detection for AMCC Yucca 440SPe board
   Improved the memory DIMM detection for the Yucca 440SPe board for
   the case where a memory DIMM is falsely detected as present.
index 65f75756c4f02722f5af1973dc1af9357fb6e82e..cd175265f0d00966de3bf46a4f9769e92021b3d2 100644 (file)
 #include <asm-ppc/io.h>
 
 #include "yucca.h"
+#include "../cpu/ppc4xx/440spe_pcie.h"
+
+#undef PCIE_ENDPOINT
+/* #define PCIE_ENDPOINT 1 */
 
 void fpga_init (void);
 
@@ -583,12 +587,12 @@ static long int yucca_probe_for_dimms(void)
 
                memset(dimm_spd_data, 0, MAX_SPD_BYTES * sizeof(char));
                if (result == 0) {
-                       /* read first byte of SPD data, if there is any data */ 
+                       /* read first byte of SPD data, if there is any data */
                        result = i2c_read(dimm_addr, 0, 1, dimm_spd_data, 1);
 
                        if (result == 0) {
                                result = dimm_spd_data[0];
-                               result = result > MAX_SPD_BYTES ? 
+                               result = result > MAX_SPD_BYTES ?
                                                MAX_SPD_BYTES : result;
                                result = i2c_read(dimm_addr, 0, 1,
                                                        dimm_spd_data, result);
@@ -596,7 +600,7 @@ static long int yucca_probe_for_dimms(void)
                }
 
                if ((result == 0) &&
-                   (dimm_spd_data[64] == MICRON_SPD_JEDEC_ID)) {       
+                   (dimm_spd_data[64] == MICRON_SPD_JEDEC_ID)) {
                        dimm_installed[dimm_num] = TRUE;
                        dimms_found++;
                        debug("DIMM slot %d: DDR2 SDRAM detected\n", dimm_num);
@@ -1029,6 +1033,57 @@ void yucca_setup_pcie_fpga_rootpoint(int port)
 
        out_be16((u16 *)FPGA_REG1C, reset_off | in_be16((u16 *)FPGA_REG1C));
 }
+/*
+ * For the given slot, set endpoint mode, send power to the slot,
+ * turn on the green LED and turn off the yellow LED, enable the clock
+ * .In end point mode reset bit is  read only.
+ */
+void yucca_setup_pcie_fpga_endpoint(int port)
+{
+       u16 power, clock, green_led, yellow_led, reset_off, rootpoint, endpoint;
+
+       switch(port) {
+       case 0:
+               rootpoint   = FPGA_REG1C_PE0_ROOTPOINT;
+               endpoint    = 0;
+               power       = FPGA_REG1A_PE0_PWRON;
+               green_led   = FPGA_REG1A_PE0_GLED;
+               clock       = FPGA_REG1A_PE0_REFCLK_ENABLE;
+               yellow_led  = FPGA_REG1A_PE0_YLED;
+               reset_off   = FPGA_REG1C_PE0_PERST;
+               break;
+       case 1:
+               rootpoint   = 0;
+               endpoint    = FPGA_REG1C_PE1_ENDPOINT;
+               power       = FPGA_REG1A_PE1_PWRON;
+               green_led   = FPGA_REG1A_PE1_GLED;
+               clock       = FPGA_REG1A_PE1_REFCLK_ENABLE;
+               yellow_led  = FPGA_REG1A_PE1_YLED;
+               reset_off   = FPGA_REG1C_PE1_PERST;
+               break;
+       case 2:
+               rootpoint   = 0;
+               endpoint    = FPGA_REG1C_PE2_ENDPOINT;
+               power       = FPGA_REG1A_PE2_PWRON;
+               green_led   = FPGA_REG1A_PE2_GLED;
+               clock       = FPGA_REG1A_PE2_REFCLK_ENABLE;
+               yellow_led  = FPGA_REG1A_PE2_YLED;
+               reset_off   = FPGA_REG1C_PE2_PERST;
+               break;
+
+       default:
+               return;
+       }
+
+       out_be16((u16 *)FPGA_REG1A,
+                ~(power | clock | green_led) &
+                (yellow_led | in_be16((u16 *)FPGA_REG1A)));
+
+       out_be16((u16 *)FPGA_REG1C,
+                ~(rootpoint | reset_off) &
+                (endpoint | in_be16((u16 *)FPGA_REG1C)));
+}
+
 
 
 static struct pci_controller pcie_hose[3] = {{0},{0},{0}};
@@ -1048,9 +1103,13 @@ void pcie_setup_hoses(void)
                if (!yucca_pcie_card_present(i))
                        continue;
 
+#ifdef PCIE_ENDPOINT
+               yucca_setup_pcie_fpga_endpoint(i);
+               if (ppc440spe_init_pcie_endport(i)) {
+#else
                yucca_setup_pcie_fpga_rootpoint(i);
-
                if (ppc440spe_init_pcie_rootport(i)) {
+#endif
                        printf("PCIE%d: initialization failed\n", i);
                        continue;
                }
@@ -1070,8 +1129,19 @@ void pcie_setup_hoses(void)
                hose->region_count = 1;
                pci_register_hose(hose);
 
-               ppc440spe_setup_pcie(hose, i);
+#ifdef PCIE_ENDPOINT
+               ppc440spe_setup_pcie_endpoint(hose, i);
+               /*
+                * Reson for no scanning is endpoint can not generate
+                * upstream configuration accesses.
+                */
+#else
+               ppc440spe_setup_pcie_rootpoint(hose, i);
+               /*
+                * Config access can only go down stream
+                */
                hose->last_busno = pci_hose_scan(hose);
+#endif
        }
 }
 #endif /* defined(CONFIG_PCI) */
index b2621c2ec5b2a8d50860968bb03d8550ca0e5a8a..6130cd283966d12032fa80afa891f160a54acbe7 100644 (file)
@@ -270,7 +270,7 @@ int ppc440spe_init_pcie(void)
        SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24));
        udelay(3);
 
-       while(time_out) {
+       while (time_out) {
                if (!(SDR_READ(PESDR0_PLLLCT3) & 0x10000000)) {
                        time_out--;
                        udelay(1);
@@ -284,6 +284,40 @@ int ppc440spe_init_pcie(void)
        return 0;
 }
 
+/*
+ *  Yucca board as End point and root point setup
+ *                    and
+ *    testing inbound and out bound windows
+ *
+ *  YUCCA board can be plugged into another yucca board or you can get PCI-E
+ *  cable which can be used to setup loop back from one port to another port.
+ *  Please rememeber that unless there is a endpoint plugged in to root port it
+ *  will not initialize. It is the same in case of endpoint , unless there is
+ *  root port attached it will not initialize.
+ *
+ *  In this release of software all the PCI-E ports are configured as either
+ *  endpoint or rootpoint.In future we will have support for selective ports
+ *  setup as endpoint and root point in single board.
+ *
+ *  Once your board came up as root point , you can verify by reading
+ *  /proc/bus/pci/devices. Where you can see the configuration registers
+ *  of end point device attached to the port.
+ *
+ *  Enpoint cofiguration can be verified by connecting Yucca board to any
+ *  host or another yucca board. Then try to scan the device. In case of
+ *  linux use "lspci" or appripriate os command.
+ *
+ *  How do I verify the inbound and out bound windows ?(yucca to yucca)
+ *  in this configuration inbound and outbound windows are setup to access
+ *  sram memroy area. SRAM is at 0x4 0000 0000 , on PLB bus. This address
+ *  is mapped at 0x90000000. From u-boot prompt write data 0xb000 0000,
+ *  This is waere your POM(PLB out bound memory window) mapped. then
+ *  read the data from other yucca board's u-boot prompt at address
+ *  0x9000 0000(SRAM). Data should match.
+ *  In case of inbound , write data to u-boot command prompt at 0xb000 0000
+ *  which is mapped to 0x4 0000 0000. Now on rootpoint yucca u-boot prompt check
+ *  data at 0x9000 0000(SRAM).Data should match.
+ */
 int ppc440spe_init_pcie_rootport(int port)
 {
        static int core_init;
@@ -326,7 +360,7 @@ int ppc440spe_init_pcie_rootport(int port)
                SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000);
                SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000);
                SDR_WRITE(PESDR0_RCSSET,
-                       (SDR_READ(PESDR0_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+                         (SDR_READ(PESDR0_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
                break;
 
        case 1:
@@ -339,7 +373,7 @@ int ppc440spe_init_pcie_rootport(int port)
                SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000);
                SDR_WRITE(PESDR1_HSSL3SET1, 0x35000000);
                SDR_WRITE(PESDR1_RCSSET,
-                       (SDR_READ(PESDR1_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+                         (SDR_READ(PESDR1_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
                break;
 
        case 2:
@@ -351,6 +385,225 @@ int ppc440spe_init_pcie_rootport(int port)
                SDR_WRITE(PESDR2_HSSL1SET1, 0x35000000);
                SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000);
                SDR_WRITE(PESDR2_HSSL3SET1, 0x35000000);
+               SDR_WRITE(PESDR2_RCSSET,
+                         (SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+               break;
+       }
+       /*
+        * Notice: the following delay has critical impact on device
+        * initialization - if too short (<50ms) the link doesn't get up.
+        */
+       mdelay(100);
+
+       switch (port) {
+       case 0:
+               val = SDR_READ(PESDR0_RCSSTS);
+               break;
+       case 1:
+               val = SDR_READ(PESDR1_RCSSTS);
+               break;
+       case 2:
+               val = SDR_READ(PESDR2_RCSSTS);
+               break;
+       }
+
+       if (val & (1 << 20)) {
+               printf("PCIE%d: PGRST failed %08x\n", port, val);
+               return -1;
+       }
+
+       /*
+        * Verify link is up
+        */
+       val = 0;
+       switch (port) {
+       case 0:
+               val = SDR_READ(PESDR0_LOOP);
+               break;
+       case 1:
+               val = SDR_READ(PESDR1_LOOP);
+               break;
+       case 2:
+               val = SDR_READ(PESDR2_LOOP);
+               break;
+       }
+       if (!(val & 0x00001000)) {
+               printf("PCIE%d: link is not up.\n", port);
+               return -1;
+       }
+
+       /*
+        * Setup UTL registers - but only on revA!
+        * We use default settings for revB chip.
+        */
+       if (!ppc440spe_revB())
+               ppc440spe_setup_utl(port);
+
+       /*
+        * We map PCI Express configuration access into the 512MB regions
+        *
+        * NOTICE: revB is very strict about PLB real addressess and ranges to
+        * be mapped for config space; it seems to only work with d_nnnn_nnnn
+        * range (hangs the core upon config transaction attempts when set
+        * otherwise) while revA uses c_nnnn_nnnn.
+        *
+        * For revA:
+        *     PCIE0: 0xc_4000_0000
+        *     PCIE1: 0xc_8000_0000
+        *     PCIE2: 0xc_c000_0000
+        *
+        * For revB:
+        *     PCIE0: 0xd_0000_0000
+        *     PCIE1: 0xd_2000_0000
+        *     PCIE2: 0xd_4000_0000
+        */
+
+       switch (port) {
+       case 0:
+               if (ppc440spe_revB()) {
+                       mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000d);
+                       mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x00000000);
+               } else {
+                       /* revA */
+                       mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c);
+                       mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000);
+               }
+               mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */
+               break;
+
+       case 1:
+               if (ppc440spe_revB()) {
+                       mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000d);
+                       mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x20000000);
+               } else {
+                       mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c);
+                       mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000);
+               }
+               mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */
+               break;
+
+       case 2:
+               if (ppc440spe_revB()) {
+                       mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000d);
+                       mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0x40000000);
+               } else {
+                       mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c);
+                       mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000);
+               }
+               mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */
+               break;
+       }
+
+       /*
+        * Check for VC0 active and assert RDY.
+        */
+       attempts = 10;
+       switch (port) {
+       case 0:
+               while(!(SDR_READ(PESDR0_RCSSTS) & (1 << 16))) {
+                       if (!(attempts--)) {
+                               printf("PCIE0: VC0 not active\n");
+                               return -1;
+                       }
+                       mdelay(1000);
+               }
+               SDR_WRITE(PESDR0_RCSSET, SDR_READ(PESDR0_RCSSET) | 1 << 20);
+               break;
+       case 1:
+               while(!(SDR_READ(PESDR1_RCSSTS) & (1 << 16))) {
+                       if (!(attempts--)) {
+                               printf("PCIE1: VC0 not active\n");
+                               return -1;
+                       }
+                       mdelay(1000);
+               }
+
+               SDR_WRITE(PESDR1_RCSSET, SDR_READ(PESDR1_RCSSET) | 1 << 20);
+               break;
+       case 2:
+               while(!(SDR_READ(PESDR2_RCSSTS) & (1 << 16))) {
+                       if (!(attempts--)) {
+                               printf("PCIE2: VC0 not active\n");
+                               return -1;
+                       }
+                       mdelay(1000);
+               }
+
+               SDR_WRITE(PESDR2_RCSSET, SDR_READ(PESDR2_RCSSET) | 1 << 20);
+               break;
+       }
+       mdelay(100);
+
+       return 0;
+}
+
+int ppc440spe_init_pcie_endport(int port)
+{
+       static int core_init;
+       volatile u32 val = 0;
+       int attempts;
+
+       if (!core_init) {
+               ++core_init;
+               if (ppc440spe_init_pcie())
+                       return -1;
+       }
+
+       /*
+        * Initialize various parts of the PCI Express core for our port:
+        *
+        * - Set as a end port and enable max width
+        *   (PXIE0 -> X8, PCIE1 and PCIE2 -> X4).
+        * - Set up UTL configuration.
+        * - Increase SERDES drive strength to levels suggested by AMCC.
+        * - De-assert RSTPYN, RSTDL and RSTGU.
+        *
+        * NOTICE for revB chip: PESDRn_UTLSET2 is not set - we leave it with
+        * default setting 0x11310000. The register has new fields,
+        * PESDRn_UTLSET2[LKINE] in particular: clearing it leads to PCIE core
+        * hang.
+        */
+       switch (port) {
+       case 0:
+               SDR_WRITE(PESDR0_DLPSET,  1 << 24 | PTYPE_LEGACY_ENDPOINT << 20 | LNKW_X8 << 12);
+
+               SDR_WRITE(PESDR0_UTLSET1, 0x20222222);
+               if (!ppc440spe_revB())
+                       SDR_WRITE(PESDR0_UTLSET2, 0x11000000);
+               SDR_WRITE(PESDR0_HSSL0SET1, 0x35000000);
+               SDR_WRITE(PESDR0_HSSL1SET1, 0x35000000);
+               SDR_WRITE(PESDR0_HSSL2SET1, 0x35000000);
+               SDR_WRITE(PESDR0_HSSL3SET1, 0x35000000);
+               SDR_WRITE(PESDR0_HSSL4SET1, 0x35000000);
+               SDR_WRITE(PESDR0_HSSL5SET1, 0x35000000);
+               SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000);
+               SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000);
+               SDR_WRITE(PESDR0_RCSSET,
+                       (SDR_READ(PESDR0_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+               break;
+
+       case 1:
+               SDR_WRITE(PESDR1_DLPSET, 1 << 24 | PTYPE_LEGACY_ENDPOINT << 20 | LNKW_X4 << 12);
+               SDR_WRITE(PESDR1_UTLSET1, 0x20222222);
+               if (!ppc440spe_revB())
+                       SDR_WRITE(PESDR1_UTLSET2, 0x11000000);
+               SDR_WRITE(PESDR1_HSSL0SET1, 0x35000000);
+               SDR_WRITE(PESDR1_HSSL1SET1, 0x35000000);
+               SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000);
+               SDR_WRITE(PESDR1_HSSL3SET1, 0x35000000);
+               SDR_WRITE(PESDR1_RCSSET,
+                       (SDR_READ(PESDR1_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+               break;
+
+       case 2:
+               SDR_WRITE(PESDR2_DLPSET, 1 << 24 | PTYPE_LEGACY_ENDPOINT << 20 | LNKW_X4 << 12);
+               SDR_WRITE(PESDR2_UTLSET1, 0x20222222);
+               if (!ppc440spe_revB())
+                       SDR_WRITE(PESDR2_UTLSET2, 0x11000000);
+               SDR_WRITE(PESDR2_HSSL0SET1, 0x35000000);
+               SDR_WRITE(PESDR2_HSSL1SET1, 0x35000000);
+               SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000);
+               SDR_WRITE(PESDR2_HSSL3SET1, 0x35000000);
                SDR_WRITE(PESDR2_RCSSET,
                        (SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
                break;
@@ -418,7 +671,6 @@ int ppc440spe_init_pcie_rootport(int port)
         *     PCIE1: 0xd_2000_0000
         *     PCIE2: 0xd_4000_0000
         */
-
        switch (port) {
        case 0:
                if (ppc440spe_revB()) {
@@ -498,29 +750,33 @@ int ppc440spe_init_pcie_rootport(int port)
        return 0;
 }
 
-void ppc440spe_setup_pcie(struct pci_controller *hose, int port)
+void ppc440spe_setup_pcie_rootpoint(struct pci_controller *hose, int port)
 {
        volatile void *mbase = NULL;
+       volatile void *rmbase = NULL;
 
        pci_set_ops(hose,
-                       pcie_read_config_byte,
-                       pcie_read_config_word,
-                       pcie_read_config_dword,
-                       pcie_write_config_byte,
-                       pcie_write_config_word,
-                       pcie_write_config_dword);
-
-       switch(port) {
+                   pcie_read_config_byte,
+                   pcie_read_config_word,
+                   pcie_read_config_dword,
+                   pcie_write_config_byte,
+                   pcie_write_config_word,
+                   pcie_write_config_dword);
+
+       switch (port) {
        case 0:
                mbase = (u32 *)CFG_PCIE0_XCFGBASE;
+               rmbase = (u32 *)CFG_PCIE0_CFGBASE;
                hose->cfg_data = (u8 *)CFG_PCIE0_CFGBASE;
                break;
        case 1:
                mbase = (u32 *)CFG_PCIE1_XCFGBASE;
+               rmbase = (u32 *)CFG_PCIE1_CFGBASE;
                hose->cfg_data = (u8 *)CFG_PCIE1_CFGBASE;
                break;
        case 2:
                mbase = (u32 *)CFG_PCIE2_XCFGBASE;
+               rmbase = (u32 *)CFG_PCIE2_CFGBASE;
                hose->cfg_data = (u8 *)CFG_PCIE2_CFGBASE;
                break;
        }
@@ -528,14 +784,9 @@ void ppc440spe_setup_pcie(struct pci_controller *hose, int port)
        /*
         * Set bus numbers on our root port
         */
-       if (ppc440spe_revB()) {
-               out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0);
-               out_8((u8 *)mbase + PCI_SECONDARY_BUS, 1);
-               out_8((u8 *)mbase + PCI_SUBORDINATE_BUS, 1);
-       } else {
-               out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0);
-               out_8((u8 *)mbase + PCI_SECONDARY_BUS, 0);
-       }
+       out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0);
+       out_8((u8 *)mbase + PCI_SECONDARY_BUS, 1);
+       out_8((u8 *)mbase + PCI_SUBORDINATE_BUS, 1);
 
        /*
         * Set up outbound translation to hose->mem_space from PLB
@@ -544,8 +795,7 @@ void ppc440spe_setup_pcie(struct pci_controller *hose, int port)
         * subregions and to enable the outbound translation.
         */
        out_le32(mbase + PECFG_POM0LAH, 0x00000000);
-       out_le32(mbase + PECFG_POM0LAL, (CFG_PCIE_MEMBASE +
-                       port * CFG_PCIE_MEMSIZE));
+       out_le32(mbase + PECFG_POM0LAL, 0x00000000);
 
        switch (port) {
        case 0:
@@ -579,14 +829,134 @@ void ppc440spe_setup_pcie(struct pci_controller *hose, int port)
        out_le32(mbase + PCI_BASE_ADDRESS_1, 0);
        out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffc);
        out_le32(mbase + PECFG_BAR0LMPA, 0);
+
+       out_le32(mbase + PECFG_PIM01SAH, 0xffff0000);
+       out_le32(mbase + PECFG_PIM01SAL, 0x00000000);
        out_le32(mbase + PECFG_PIM0LAL, 0);
        out_le32(mbase + PECFG_PIM0LAH, 0);
+       out_le32(mbase + PECFG_PIM1LAL,  0x00000000);
+       out_le32(mbase + PECFG_PIM1LAH,  0x00000004);
+       out_le32(mbase + PECFG_PIMEN, 0x1);
+
+       /* Enable I/O, Mem, and Busmaster cycles */
+       out_le16((u16 *)(mbase + PCI_COMMAND),
+                in_le16((u16 *)(mbase + PCI_COMMAND)) |
+                PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+       printf("PCIE:%d successfully set as rootpoint\n",port);
+}
+
+int ppc440spe_setup_pcie_endpoint(struct pci_controller *hose, int port)
+{
+       volatile void *mbase = NULL;
+       int attempts = 0;
+
+       pci_set_ops(hose,
+                   pcie_read_config_byte,
+                   pcie_read_config_word,
+                   pcie_read_config_dword,
+                   pcie_write_config_byte,
+                   pcie_write_config_word,
+                   pcie_write_config_dword);
+
+       switch (port) {
+       case 0:
+               mbase = (u32 *)CFG_PCIE0_XCFGBASE;
+               hose->cfg_data = (u8 *)CFG_PCIE0_CFGBASE;
+               break;
+       case 1:
+               mbase = (u32 *)CFG_PCIE1_XCFGBASE;
+               hose->cfg_data = (u8 *)CFG_PCIE1_CFGBASE;
+               break;
+       case 2:
+               mbase = (u32 *)CFG_PCIE2_XCFGBASE;
+               hose->cfg_data = (u8 *)CFG_PCIE2_CFGBASE;
+               break;
+       }
+
+       /*
+        * Set up outbound translation to hose->mem_space from PLB
+        * addresses at an offset of 0xd_0000_0000.  We set the low
+        * bits of the mask to 11 to turn off splitting into 8
+        * subregions and to enable the outbound translation.
+        */
+       out_le32(mbase + PECFG_POM0LAH, 0x00001ff8);
+       out_le32(mbase + PECFG_POM0LAL, 0x00001000);
+
+       switch (port) {
+       case 0:
+               mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0),  0x0000000d);
+               mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0),  CFG_PCIE_MEMBASE +
+                       port * CFG_PCIE_MEMSIZE);
+               mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff);
+               mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0),
+                       ~(CFG_PCIE_MEMSIZE - 1) | 3);
+               break;
+       case 1:
+               mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1),  0x0000000d);
+               mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1),  (CFG_PCIE_MEMBASE +
+                       port * CFG_PCIE_MEMSIZE));
+               mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff);
+               mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1),
+                       ~(CFG_PCIE_MEMSIZE - 1) | 3);
+               break;
+       case 2:
+               mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2),  0x0000000d);
+               mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2),  (CFG_PCIE_MEMBASE +
+                       port * CFG_PCIE_MEMSIZE));
+               mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff);
+               mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2),
+                       ~(CFG_PCIE_MEMSIZE - 1) | 3);
+               break;
+       }
+
+       /* Set up 16GB inbound memory window at 0 */
+       out_le32(mbase + PCI_BASE_ADDRESS_0, 0);
+       out_le32(mbase + PCI_BASE_ADDRESS_1, 0);
+       out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffc);
+       out_le32(mbase + PECFG_BAR0LMPA, 0);
+       out_le32(mbase + PECFG_PIM0LAL, 0x00000000);
+       out_le32(mbase + PECFG_PIM0LAH, 0x00000004);    /* pointing to SRAM */
        out_le32(mbase + PECFG_PIMEN, 0x1);
 
        /* Enable I/O, Mem, and Busmaster cycles */
        out_le16((u16 *)(mbase + PCI_COMMAND),
                 in_le16((u16 *)(mbase + PCI_COMMAND)) |
                 PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+       out_le16(mbase + 0x200,0xcaad);                 /* Setting vendor ID */
+       out_le16(mbase + 0x202,0xfeed);                 /* Setting device ID */
+       attempts = 10;
+       switch (port) {
+       case 0:
+               while (!(SDR_READ(PESDR0_RCSSTS) & (1 << 8))) {
+                       if (!(attempts--)) {
+                               printf("PCIE0: BMEN is  not active\n");
+                               return -1;
+                       }
+                       mdelay(1000);
+               }
+               break;
+       case 1:
+               while (!(SDR_READ(PESDR1_RCSSTS) & (1 << 8))) {
+                       if (!(attempts--)) {
+                               printf("PCIE1: BMEN is not active\n");
+                               return -1;
+                       }
+                       mdelay(1000);
+               }
+               break;
+       case 2:
+               while (!(SDR_READ(PESDR2_RCSSTS) & (1 << 8))) {
+                       if (!(attempts--)) {
+                               printf("PCIE2: BMEN is  not active\n");
+                               return -1;
+                       }
+                       mdelay(1000);
+               }
+               break;
+       }
+       printf("PCIE:%d successfully set as endpoint\n",port);
+
+       return 0;
 }
 #endif /* CONFIG_PCI */
 #endif /* CONFIG_440SPE */
index 47df7620a6d6a4cd88ef2fa3457b37db88564293..2becc777222b0732c838d5d242fa8768cf7e6f81 100644 (file)
  */
 #define PECFG_BAR0LMPA         0x210
 #define PECFG_BAR0HMPA         0x214
+#define PECFG_BAR1MPA          0x218
+#define PECFG_BAR2MPA          0x220
+
 #define PECFG_PIMEN            0x33c
 #define PECFG_PIM0LAL          0x340
 #define PECFG_PIM0LAH          0x344
+#define PECFG_PIM1LAL          0x348
+#define PECFG_PIM1LAH          0x34c
+#define PECFG_PIM01SAL         0x350
+#define PECFG_PIM01SAH         0x354
+
 #define PECFG_POM0LAL          0x380
 #define PECFG_POM0LAH          0x384
 
 int ppc440spe_init_pcie(void);
 int ppc440spe_init_pcie_rootport(int port);
 void yucca_setup_pcie_fpga_rootpoint(int port);
-void ppc440spe_setup_pcie(struct pci_controller *hose, int port);
+void ppc440spe_setup_pcie_rootpoint(struct pci_controller *hose, int port);
+int ppc440spe_setup_pcie_endpoint(struct pci_controller *hose, int port);
 int yucca_pcie_card_present(int port);
 int pcie_hose_scan(struct pci_controller *hose, int bus);
 #endif /* __440SPE_PCIE_H */