]> git.sur5r.net Git - u-boot/blobdiff - board/amcc/yucca/yucca.c
Merge with /home/wd/git/u-boot/mailing-list/Haavard_Skinnemoen
[u-boot] / board / amcc / yucca / yucca.c
index 8fb4cfa8847f6b2938af4273ae2cf58f41050b32..e9b34dd249a9c9333c7cccf2138a978319fc0d81 100644 (file)
  * MA 02111-1307 USA
  *
  * Port to AMCC-440SPE Evaluation Board SOP - April 2005
+ *
+ * PCIe supporting routines derived from Linux 440SPe PCIe driver.
  */
 
 #include <common.h>
 #include <ppc4xx.h>
 #include <asm/processor.h>
 #include <i2c.h>
+#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);
 
@@ -39,6 +47,9 @@ int get_console_port(void);
 unsigned long ppcMfcpr(unsigned long cpr_reg);
 unsigned long ppcMfsdr(unsigned long sdr_reg);
 
+int ppc440spe_init_pcie_rootport(int port);
+void ppc440spe_setup_pcie(struct pci_controller *hose, int port);
+
 #define DEBUG_ENV
 #ifdef DEBUG_ENV
 #define DEBUGF(fmt,args...) printf(fmt ,##args)
@@ -541,27 +552,25 @@ int board_early_init_f (void)
 
 int checkboard (void)
 {
-       sys_info_t sysinfo;
-
-       get_sys_info (&sysinfo);
-
-       printf ("Board: AMCC 440SPe Evaluation Board\n");
-       printf ("\tVCO: %lu MHz\n", sysinfo.freqVCOMhz / 1000000);
-       printf ("\tCPU: %lu MHz\n", sysinfo.freqProcessor / 1000000);
-       printf ("\tPLB: %lu MHz\n", sysinfo.freqPLB / 1000000);
-       printf ("\tOPB: %lu MHz\n", sysinfo.freqOPB / 1000000);
-       printf ("\tEPB: %lu MHz\n", sysinfo.freqEPB / 1000000);
-       printf ("\tPCI: %lu MHz\n", sysinfo.freqPCI / 1000000);
-       printf ("\tDDR: %lu MHz\n", sysinfo.freqDDR / 1000000);
+       char *s = getenv("serial#");
+
+       printf("Board: Yucca - AMCC 440SPe Evaluation Board");
+       if (s != NULL) {
+               puts(", serial# ");
+               puts(s);
+       }
+       putc('\n');
+
        return 0;
 }
 
 static long int yucca_probe_for_dimms(void)
 {
-       long int        dimm_installed[MAXDIMMS];
-       long int        dimm_num, probe_result;
-       long int        dimms_found = 0;
-       uchar           dimm_addr = IIC0_DIMM0_ADDR;
+       int     dimm_installed[MAXDIMMS];
+       int     dimm_num, result;
+       int     dimms_found = 0;
+       uchar   dimm_addr = IIC0_DIMM0_ADDR;
+       uchar   dimm_spd_data[MAX_SPD_BYTES];
 
        for (dimm_num = 0; dimm_num < MAXDIMMS; dimm_num++) {
                /* check if there is a chip at the dimm address */
@@ -573,12 +582,28 @@ static long int yucca_probe_for_dimms(void)
                                dimm_addr = IIC0_DIMM1_ADDR;
                                break;
                }
-               probe_result = i2c_probe(dimm_addr);
 
-               if (probe_result == 0) {
+               result = i2c_probe(dimm_addr);
+
+               memset(dimm_spd_data, 0, MAX_SPD_BYTES * sizeof(char));
+               if (result == 0) {
+                       /* 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 ?
+                                               MAX_SPD_BYTES : result;
+                               result = i2c_read(dimm_addr, 0, 1,
+                                                       dimm_spd_data, result);
+                       }
+               }
+
+               if ((result == 0) &&
+                   (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);
+                       debug("DIMM slot %d: DDR2 SDRAM detected\n", dimm_num);
                } else {
                        dimm_installed[dimm_num] = FALSE;
                        debug("DIMM slot %d: Not populated or cannot sucessfully probe the DIMM\n", dimm_num);
@@ -911,6 +936,7 @@ void pci_target_init(struct pci_controller * hose )
 }
 #endif /* defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) */
 
+#if defined(CONFIG_PCI)
 /*************************************************************************
  *  is_pci_host
  *
@@ -926,12 +952,195 @@ void pci_target_init(struct pci_controller * hose )
  *
  *
  ************************************************************************/
-#if defined(CONFIG_PCI)
 int is_pci_host(struct pci_controller *hose)
 {
        /* The yucca board is always configured as host. */
        return 1;
 }
+
+int yucca_pcie_card_present(int port)
+{
+       u16 reg;
+
+       reg = in_be16((u16 *)FPGA_REG1C);
+       switch(port) {
+       case 0:
+               return !(reg & FPGA_REG1C_PE0_PRSNT);
+       case 1:
+               return !(reg & FPGA_REG1C_PE1_PRSNT);
+       case 2:
+               return !(reg & FPGA_REG1C_PE2_PRSNT);
+       default:
+               return 0;
+       }
+}
+
+/*
+ * For the given slot, set rootpoint mode, send power to the slot,
+ * turn on the green LED and turn off the yellow LED, enable the clock
+ * and turn off reset.
+ */
+void yucca_setup_pcie_fpga_rootpoint(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,
+                ~(endpoint | reset_off) &
+                (rootpoint | in_be16((u16 *)FPGA_REG1C)));
+       /*
+        * Leave device in reset for a while after powering on the
+        * slot to give it a chance to initialize.
+        */
+       udelay(250 * 1000);
+
+       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}};
+
+void pcie_setup_hoses(void)
+{
+       struct pci_controller *hose;
+       int i, bus;
+
+       /*
+        * assume we're called after the PCIX hose is initialized, which takes
+        * bus ID 0 and therefore start numbering PCIe's from 1.
+        */
+       bus = 1;
+       for (i = 0; i <= 2; i++) {
+               /* Check for yucca card presence */
+               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;
+               }
+
+               hose = &pcie_hose[i];
+               hose->first_busno = bus;
+               hose->last_busno  = bus;
+               bus++;
+
+               /* setup mem resource */
+               pci_set_region(hose->regions + 0,
+                       CFG_PCIE_MEMBASE + i * CFG_PCIE_MEMSIZE,
+                       CFG_PCIE_MEMBASE + i * CFG_PCIE_MEMSIZE,
+                       CFG_PCIE_MEMSIZE,
+                       PCI_REGION_MEM
+                       );
+               hose->region_count = 1;
+               pci_register_hose(hose);
+
+#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) */
 
 int misc_init_f (void)
@@ -1097,4 +1306,3 @@ unsigned long ppcMfsdr(unsigned long sdr_reg)
 
        return (sdr_value);
 }
-