ppc4xx: Dynamic configuration of 4xx PCIe mode as root or endpoint mode
authorStefan Roese <sr@denx.de>
Sat, 13 Oct 2007 14:43:23 +0000 (16:43 +0200)
committerStefan Roese <sr@denx.de>
Wed, 31 Oct 2007 20:20:50 +0000 (21:20 +0100)
This patch adds support for dynamic configuration of PCIe ports for the
AMCC PPC4xx boards equipped with PCIe interfaces. These are the PPC440SPe
boards Yucca & Katmai and the 405EX board Kilauea.

This dynamic configuration is done via the "pcie_mode" environement
variable. This variable can be set to "EP" or "RP" for endpoint or
rootpoint mode. Multiple values can be joined via the ":" delimiter.
Here an example:

pcie_mode=RP:EP:EP

This way, PCIe port 0 will be configured as rootpoint, PCIe port 1 and 2
as endpoint.

Per default Yucca will be configured as:
pcie_mode=RP:EP:EP

Per default Katmai will be configured as:
pcie_mode=RP:RP:REP

Per default Kilauea will be configured as:
pcie_mode=RP:RP

Signed-off-by: Tirumala R Marri <tmarri@amcc.com>
Signed-off-by: Stefan Roese <sr@denx.de>
board/amcc/katmai/katmai.c
board/amcc/kilauea/kilauea.c
board/amcc/yucca/yucca.c
cpu/ppc4xx/4xx_pcie.c
include/asm-ppc/4xx_pcie.h
include/configs/katmai.h
include/configs/kilauea.h
include/configs/yucca.h

index f1c352c..0627a7a 100644 (file)
@@ -30,9 +30,6 @@
 #include <asm/gpio.h>
 #include <asm/4xx_pcie.h>
 
-#undef PCIE_ENDPOINT
-/* #define PCIE_ENDPOINT 1 */
-
 DECLARE_GLOBAL_DATA_PTR;
 
 int board_early_init_f (void)
@@ -392,6 +389,7 @@ void pcie_setup_hoses(int busno)
 {
        struct pci_controller *hose;
        int i, bus;
+       int ret = 0;
        char *env;
        unsigned int delay;
 
@@ -405,11 +403,14 @@ void pcie_setup_hoses(int busno)
                if (!katmai_pcie_card_present(i))
                        continue;
 
-#ifdef PCIE_ENDPOINT
-               if (ppc4xx_init_pcie_endport(i)) {
-#else
-               if (ppc4xx_init_pcie_rootport(i)) {
-#endif
+               if (is_end_point(i)) {
+                       printf("PCIE%d: will be configured as endpoint\n", i);
+                       ret = ppc4xx_init_pcie_endport(i);
+               } else {
+                       printf("PCIE%d: will be configured as root-complex\n", i);
+                       ret = ppc4xx_init_pcie_rootport(i);
+               }
+               if (ret) {
                        printf("PCIE%d: initialization failed\n", i);
                        continue;
                }
@@ -424,35 +425,33 @@ void pcie_setup_hoses(int busno)
                               CFG_PCIE_MEMBASE + i * CFG_PCIE_MEMSIZE,
                               CFG_PCIE_MEMBASE + i * CFG_PCIE_MEMSIZE,
                               CFG_PCIE_MEMSIZE,
-                              PCI_REGION_MEM
-                       );
+                              PCI_REGION_MEM);
                hose->region_count = 1;
                pci_register_hose(hose);
 
-#ifdef PCIE_ENDPOINT
-               ppc4xx_setup_pcie_endpoint(hose, i);
-               /*
-                * Reson for no scanning is endpoint can not generate
-                * upstream configuration accesses.
-                */
-#else
-               ppc4xx_setup_pcie_rootpoint(hose, i);
-
-               env = getenv ("pciscandelay");
-               if (env != NULL) {
-                       delay = simple_strtoul (env, NULL, 10);
-                       if (delay > 5)
-                               printf ("Warning, expect noticable delay before PCIe"
-                                       "scan due to 'pciscandelay' value!\n");
-                       mdelay (delay * 1000);
+               if (is_end_point(i)) {
+                       ppc4xx_setup_pcie_endpoint(hose, i);
+                       /*
+                        * Reson for no scanning is endpoint can not generate
+                        * upstream configuration accesses.
+                        */
+               } else {
+                       ppc4xx_setup_pcie_rootpoint(hose, i);
+                       env = getenv ("pciscandelay");
+                       if (env != NULL) {
+                               delay = simple_strtoul(env, NULL, 10);
+                               if (delay > 5)
+                                       printf("Warning, expect noticable delay before "
+                                              "PCIe scan due to 'pciscandelay' value!\n");
+                               mdelay(delay * 1000);
+                       }
+
+                       /*
+                        * Config access can only go down stream
+                        */
+                       hose->last_busno = pci_hose_scan(hose);
+                       bus = hose->last_busno + 1;
                }
-
-               /*
-                * Config access can only go down stream
-                */
-               hose->last_busno = pci_hose_scan(hose);
-               bus = hose->last_busno + 1;
-#endif
        }
 }
 #endif /* defined(CONFIG_PCI) */
index 8767f75..b59bd6f 100644 (file)
@@ -299,35 +299,29 @@ void pci_target_init(struct pci_controller * hose )
 #endif /* defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) */
 
 #ifdef CONFIG_PCI
-static int pcie_port_is_rootpoint(int port)
-{
-       return 1;
-}
-
 static struct pci_controller pcie_hose[2] = {{0},{0}};
 
 void pcie_setup_hoses(int busno)
 {
        struct pci_controller *hose;
        int i, bus;
+       int ret = 0;
        bus = busno;
        char *env;
        unsigned int delay;
 
        for (i = 0; i < 2; i++) {
 
-               if (pcie_port_is_rootpoint(i)) {
-                       printf("PORT%d will be configured as root-complex\n", i);
-                       if (ppc4xx_init_pcie_rootport(i)) {
-                               printf("PCIE%d: initialization failed\n", i);
-                               continue;
-                       }
+               if (is_end_point(i)) {
+                       printf("PCIE%d: will be configured as endpoint\n", i);
+                       ret = ppc4xx_init_pcie_endport(i);
                } else {
-                       printf("PORT%d will be configured as endpoint\n", i);
-                       if (ppc4xx_init_pcie_endport(i)) {
-                               printf("PCIE%d: initialization failed\n", i);
-                               continue;
-                       }
+                       printf("PCIE%d: will be configured as root-complex\n", i);
+                       ret = ppc4xx_init_pcie_rootport(i);
+               }
+               if (ret) {
+                       printf("PCIE%d: initialization failed\n", i);
+                       continue;
                }
 
                hose = &pcie_hose[i];
@@ -344,25 +338,29 @@ void pcie_setup_hoses(int busno)
                hose->region_count = 1;
                pci_register_hose(hose);
 
-               if (pcie_port_is_rootpoint(i))
-                       ppc4xx_setup_pcie_rootpoint(hose, i);
-               else
-                       ppc4xx_setup_pcie_endpoint(hose, i);
-
-               env = getenv("pciscandelay");
-               if (env != NULL) {
-                       delay = simple_strtoul(env, NULL, 10);
-                       if (delay > 5)
-                               printf("Warning, expect noticable delay before PCIe"
-                                      "scan due to 'pciscandelay' value!\n");
-                       mdelay(delay * 1000);
-               }
+               if (is_end_point(i)) {
+                       ppc4xx_setup_pcie_endpoint(hose, i);
+                       /*
+                        * Reson for no scanning is endpoint can not generate
+                        * upstream configuration accesses.
+                        */
+               } else {
+                       ppc4xx_setup_pcie_rootpoint(hose, i);
+                       env = getenv ("pciscandelay");
+                       if (env != NULL) {
+                               delay = simple_strtoul(env, NULL, 10);
+                               if (delay > 5)
+                                       printf("Warning, expect noticable delay before "
+                                              "PCIe scan due to 'pciscandelay' value!\n");
+                               mdelay(delay * 1000);
+                       }
 
-               /*
-                * Config access can only go down stream
-                */
-               hose->last_busno = pci_hose_scan(hose);
-               bus = hose->last_busno + 1;
+                       /*
+                        * Config access can only go down stream
+                        */
+                       hose->last_busno = pci_hose_scan(hose);
+                       bus = hose->last_busno + 1;
+               }
        }
 }
 #endif
index c46721c..efdf814 100644 (file)
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#undef PCIE_ENDPOINT
-/* #define PCIE_ENDPOINT 1 */
 
 void fpga_init (void);
-
 void get_sys_info(PPC440_SYS_INFO *board_cfg );
 int compare_to_true(char *str );
 char *remove_l_w_space(char *in_str );
@@ -847,6 +844,7 @@ void pcie_setup_hoses(int busno)
 {
        struct pci_controller *hose;
        int i, bus;
+       int ret = 0;
        char *env;
        unsigned int delay;
 
@@ -860,16 +858,19 @@ void pcie_setup_hoses(int busno)
                if (!yucca_pcie_card_present(i))
                        continue;
 
-#ifdef PCIE_ENDPOINT
-               yucca_setup_pcie_fpga_endpoint(i);
-               if (ppc4xx_init_pcie_endport(i)) {
-#else
-               yucca_setup_pcie_fpga_rootpoint(i);
-               if (ppc4xx_init_pcie_rootport(i)) {
-#endif
-                       printf("PCIE%d: initialization failed\n", i);
-                       continue;
+               if (is_end_point(i)) {
+                       printf("PCIE%d: will be configured as endpoint\n",i);
+                       yucca_setup_pcie_fpga_endpoint(i);
+                       ret = ppc4xx_init_pcie_endport(i);
+               } else {
+                       printf("PCIE%d: will be configured as root-complex\n",i);
+                       yucca_setup_pcie_fpga_rootpoint(i);
+                       ret = ppc4xx_init_pcie_rootport(i);
                }
+               if (ret) {
+                       printf("PCIE%d: initialization failed\n", i);
+                       continue;
+               }
 
                hose = &pcie_hose[i];
                hose->first_busno = bus;
@@ -881,35 +882,33 @@ void pcie_setup_hoses(int busno)
                        CFG_PCIE_MEMBASE + i * CFG_PCIE_MEMSIZE,
                        CFG_PCIE_MEMBASE + i * CFG_PCIE_MEMSIZE,
                        CFG_PCIE_MEMSIZE,
-                       PCI_REGION_MEM
-                       );
+                       PCI_REGION_MEM);
                hose->region_count = 1;
                pci_register_hose(hose);
 
-#ifdef PCIE_ENDPOINT
-               ppc4xx_setup_pcie_endpoint(hose, i);
-               /*
-                * Reson for no scanning is endpoint can not generate
-                * upstream configuration accesses.
-                */
-#else
-               ppc4xx_setup_pcie_rootpoint(hose, i);
-
-               env = getenv ("pciscandelay");
-               if (env != NULL) {
-                       delay = simple_strtoul (env, NULL, 10);
-                       if (delay > 5)
-                               printf ("Warning, expect noticable delay before PCIe"
-                                       "scan due to 'pciscandelay' value!\n");
-                       mdelay (delay * 1000);
-               }
+               if (is_end_point(i)) {
+                       ppc4xx_setup_pcie_endpoint(hose, i);
+                       /*
+                        * Reson for no scanning is endpoint can not generate
+                        * upstream configuration accesses.
+                        */
+               } else {
+                       ppc4xx_setup_pcie_rootpoint(hose, i);
+                       env = getenv("pciscandelay");
+                       if (env != NULL) {
+                               delay = simple_strtoul(env, NULL, 10);
+                               if (delay > 5)
+                                       printf("Warning, expect noticable delay before "
+                                              "PCIe scan due to 'pciscandelay' value!\n");
+                               mdelay(delay * 1000);
+                       }
 
-               /*
-                * Config access can only go down stream
-                */
-               hose->last_busno = pci_hose_scan(hose);
-               bus = hose->last_busno + 1;
-#endif
+                       /*
+                        * Config access can only go down stream
+                        */
+                       hose->last_busno = pci_hose_scan(hose);
+                       bus = hose->last_busno + 1;
+               }
        }
 }
 #endif /* defined(CONFIG_PCI) */
index 7ee0e5b..9ab3588 100644 (file)
@@ -46,6 +46,20 @@ enum {
        LNKW_X8                 = 0x8
 };
 
+static int validate_endpoint(struct pci_controller *hose)
+{
+       if (hose->cfg_data == (u8 *)CFG_PCIE0_CFGBASE)
+               return (is_end_point(0));
+       else if (hose->cfg_data == (u8 *)CFG_PCIE1_CFGBASE)
+               return (is_end_point(1));
+#if CFG_PCIE_NR_PORTS > 2
+       else if (hose->cfg_data == (u8 *)CFG_PCIE2_CFGBASE)
+               return (is_end_point(2));
+#endif
+
+       return 0;
+}
+
 static u8* pcie_get_base(struct pci_controller *hose, unsigned int devfn)
 {
        u8 *base = (u8*)hose->cfg_data;
@@ -95,6 +109,9 @@ static int pcie_read_config(struct pci_controller *hose, unsigned int devfn,
        u8 *address;
        *val = 0;
 
+       if (validate_endpoint(hose))
+               return 0;               /* No upstream config access */
+
        /*
         * Bus numbers are relative to hose->first_busno
         */
@@ -150,6 +167,9 @@ static int pcie_write_config(struct pci_controller *hose, unsigned int devfn,
 
        u8 *address;
 
+       if (validate_endpoint(hose))
+               return 0;               /* No upstream config access */
+
        /*
         * Bus numbers are relative to hose->first_busno
         */
@@ -595,9 +615,9 @@ int ppc4xx_init_pcie_port(int port, int rootport)
        u32 low, high;
 
        if (!core_init) {
-               ++core_init;
                if (ppc4xx_init_pcie())
                        return -1;
+               ++core_init;
        }
 
        /*
index 17ac57b..1830c6a 100644 (file)
 #define U64_TO_U32_LOW(val)    ((u32)((val) & 0x00000000ffffffffULL))
 #define U64_TO_U32_HIGH(val)   ((u32)((val) >> 32))
 
+/*
+ * Prototypes
+ */
 int ppc4xx_init_pcie(void);
 int ppc4xx_init_pcie_rootport(int port);
 int ppc4xx_init_pcie_endport(int port);
@@ -251,6 +254,55 @@ void ppc4xx_setup_pcie_rootpoint(struct pci_controller *hose, int port);
 int ppc4xx_setup_pcie_endpoint(struct pci_controller *hose, int port);
 int pcie_hose_scan(struct pci_controller *hose, int bus);
 
+/*
+ * Function to determine root port or endport from env variable.
+ */
+static inline int is_end_point(int port)
+{
+       static char s[10], *tk;
+
+       strcpy(s, getenv("pcie_mode"));
+       tk = strtok(s, ":");
+
+       switch (port) {
+       case 0:
+               if (tk != NULL) {
+                       if (!(strcmp(tk, "ep") && strcmp(tk, "EP")))
+                               return 1;
+                       else
+                               return 0;
+               }
+               else
+                       return 0;
+
+       case 1:
+               tk = strtok(NULL, ":");
+               if (tk != NULL) {
+                       if (!(strcmp(tk, "ep") && strcmp(tk, "EP")))
+                               return 1;
+                       else
+                               return 0;
+               }
+               else
+                       return 0;
+
+       case 2:
+               tk = strtok(NULL, ":");
+               if (tk != NULL)
+                       tk = strtok(NULL, ":");
+               if (tk != NULL) {
+                       if (!(strcmp(tk, "ep") && strcmp(tk, "EP")))
+                               return 1;
+                       else
+                               return 0;
+               }
+               else
+                       return 0;
+       }
+
+       return 0;
+}
+
 static inline void mdelay(int n)
 {
        u32 ms = n;
index 8a96327..cccfc13 100644 (file)
        "upd=run load;run update\0"                                     \
        "kozio=bootm ffc60000\0"                                        \
        "pciconfighost=1\0"                                             \
+       "pcie_mode=RP:RP:RP\0"                                          \
        ""
 #define CONFIG_BOOTCOMMAND     "run flash_self"
 
index 461f8f0..f5e2023 100644 (file)
                "setenv filesize;saveenv\0"                             \
        "nupd=run nload nupdate\0"                                      \
        "pciconfighost=1\0"                                             \
+       "pcie_mode=RP:RP\0"                                             \
        ""
 #define CONFIG_BOOTCOMMAND     "run flash_self"
 
index ab7fb0a..2b4024d 100644 (file)
                "setenv filesize;saveenv\0"                             \
        "upd=run load;run update\0"                                     \
        "pciconfighost=1\0"                                             \
+       "pcie_mode=RP:EP:EP\0"                                          \
        ""
 #define CONFIG_BOOTCOMMAND     "run flash_self"