Merge with /home/sr/git/u-boot/denx
This commit is contained in:
commit
2b75062a0f
15
CHANGELOG
15
CHANGELOG
|
@ -2,6 +2,21 @@
|
||||||
Changes since U-Boot 1.1.4:
|
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.
|
||||||
|
This issue is seen on some AMCC Yucca 440SPe validation boards if
|
||||||
|
only one 512MB memory DIMM is installed, i.e. DIMM slot 0 is
|
||||||
|
populated and DIMM slot 1 is empty. In this case, U-Boot does
|
||||||
|
not correctly detect that there is only one DIMM memory module
|
||||||
|
installed and will falsely detect two DIMM memory modules are
|
||||||
|
present and therefore U-Boot will not calculate the correct amount
|
||||||
|
of total memory and u-boot will not booting up.
|
||||||
|
Patch by Adam Graham, 24 Aug 2006
|
||||||
|
|
||||||
* Fix typo.
|
* Fix typo.
|
||||||
|
|
||||||
* Code cleanup
|
* Code cleanup
|
||||||
|
|
|
@ -32,6 +32,10 @@
|
||||||
#include <asm-ppc/io.h>
|
#include <asm-ppc/io.h>
|
||||||
|
|
||||||
#include "yucca.h"
|
#include "yucca.h"
|
||||||
|
#include "../cpu/ppc4xx/440spe_pcie.h"
|
||||||
|
|
||||||
|
#undef PCIE_ENDPOINT
|
||||||
|
/* #define PCIE_ENDPOINT 1 */
|
||||||
|
|
||||||
void fpga_init (void);
|
void fpga_init (void);
|
||||||
|
|
||||||
|
@ -562,10 +566,11 @@ int checkboard (void)
|
||||||
|
|
||||||
static long int yucca_probe_for_dimms(void)
|
static long int yucca_probe_for_dimms(void)
|
||||||
{
|
{
|
||||||
long int dimm_installed[MAXDIMMS];
|
int dimm_installed[MAXDIMMS];
|
||||||
long int dimm_num, probe_result;
|
int dimm_num, result;
|
||||||
long int dimms_found = 0;
|
int dimms_found = 0;
|
||||||
uchar dimm_addr = IIC0_DIMM0_ADDR;
|
uchar dimm_addr = IIC0_DIMM0_ADDR;
|
||||||
|
uchar dimm_spd_data[MAX_SPD_BYTES];
|
||||||
|
|
||||||
for (dimm_num = 0; dimm_num < MAXDIMMS; dimm_num++) {
|
for (dimm_num = 0; dimm_num < MAXDIMMS; dimm_num++) {
|
||||||
/* check if there is a chip at the dimm address */
|
/* check if there is a chip at the dimm address */
|
||||||
|
@ -577,12 +582,28 @@ static long int yucca_probe_for_dimms(void)
|
||||||
dimm_addr = IIC0_DIMM1_ADDR;
|
dimm_addr = IIC0_DIMM1_ADDR;
|
||||||
break;
|
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;
|
dimm_installed[dimm_num] = TRUE;
|
||||||
dimms_found++;
|
dimms_found++;
|
||||||
debug("DIMM slot %d: DDR2 SDRAM detected\n",dimm_num);
|
debug("DIMM slot %d: DDR2 SDRAM detected\n", dimm_num);
|
||||||
} else {
|
} else {
|
||||||
dimm_installed[dimm_num] = FALSE;
|
dimm_installed[dimm_num] = FALSE;
|
||||||
debug("DIMM slot %d: Not populated or cannot sucessfully probe the DIMM\n", dimm_num);
|
debug("DIMM slot %d: Not populated or cannot sucessfully probe the DIMM\n", dimm_num);
|
||||||
|
@ -1012,6 +1033,57 @@ void yucca_setup_pcie_fpga_rootpoint(int port)
|
||||||
|
|
||||||
out_be16((u16 *)FPGA_REG1C, reset_off | in_be16((u16 *)FPGA_REG1C));
|
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}};
|
static struct pci_controller pcie_hose[3] = {{0},{0},{0}};
|
||||||
|
@ -1031,9 +1103,13 @@ void pcie_setup_hoses(void)
|
||||||
if (!yucca_pcie_card_present(i))
|
if (!yucca_pcie_card_present(i))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
#ifdef PCIE_ENDPOINT
|
||||||
|
yucca_setup_pcie_fpga_endpoint(i);
|
||||||
|
if (ppc440spe_init_pcie_endport(i)) {
|
||||||
|
#else
|
||||||
yucca_setup_pcie_fpga_rootpoint(i);
|
yucca_setup_pcie_fpga_rootpoint(i);
|
||||||
|
|
||||||
if (ppc440spe_init_pcie_rootport(i)) {
|
if (ppc440spe_init_pcie_rootport(i)) {
|
||||||
|
#endif
|
||||||
printf("PCIE%d: initialization failed\n", i);
|
printf("PCIE%d: initialization failed\n", i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1053,8 +1129,19 @@ void pcie_setup_hoses(void)
|
||||||
hose->region_count = 1;
|
hose->region_count = 1;
|
||||||
pci_register_hose(hose);
|
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);
|
hose->last_busno = pci_hose_scan(hose);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* defined(CONFIG_PCI) */
|
#endif /* defined(CONFIG_PCI) */
|
||||||
|
|
|
@ -60,6 +60,9 @@ extern "C" {
|
||||||
|
|
||||||
#define NUM_TLB_ENTRIES 64
|
#define NUM_TLB_ENTRIES 64
|
||||||
|
|
||||||
|
/* MICRON SPD JEDEC ID Code (first byte) - SPD data byte [64] */
|
||||||
|
#define MICRON_SPD_JEDEC_ID 0x2c
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------+
|
/*----------------------------------------------------------------------------+
|
||||||
| TLB specific defines.
|
| TLB specific defines.
|
||||||
+----------------------------------------------------------------------------*/
|
+----------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -270,7 +270,7 @@ int ppc440spe_init_pcie(void)
|
||||||
SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24));
|
SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24));
|
||||||
udelay(3);
|
udelay(3);
|
||||||
|
|
||||||
while(time_out) {
|
while (time_out) {
|
||||||
if (!(SDR_READ(PESDR0_PLLLCT3) & 0x10000000)) {
|
if (!(SDR_READ(PESDR0_PLLLCT3) & 0x10000000)) {
|
||||||
time_out--;
|
time_out--;
|
||||||
udelay(1);
|
udelay(1);
|
||||||
|
@ -284,6 +284,40 @@ int ppc440spe_init_pcie(void)
|
||||||
return 0;
|
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)
|
int ppc440spe_init_pcie_rootport(int port)
|
||||||
{
|
{
|
||||||
static int core_init;
|
static int core_init;
|
||||||
|
@ -326,7 +360,7 @@ int ppc440spe_init_pcie_rootport(int port)
|
||||||
SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000);
|
SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000);
|
||||||
SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000);
|
SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000);
|
||||||
SDR_WRITE(PESDR0_RCSSET,
|
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;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -339,7 +373,7 @@ int ppc440spe_init_pcie_rootport(int port)
|
||||||
SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000);
|
SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000);
|
||||||
SDR_WRITE(PESDR1_HSSL3SET1, 0x35000000);
|
SDR_WRITE(PESDR1_HSSL3SET1, 0x35000000);
|
||||||
SDR_WRITE(PESDR1_RCSSET,
|
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;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
|
@ -352,7 +386,7 @@ int ppc440spe_init_pcie_rootport(int port)
|
||||||
SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000);
|
SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000);
|
||||||
SDR_WRITE(PESDR2_HSSL3SET1, 0x35000000);
|
SDR_WRITE(PESDR2_HSSL3SET1, 0x35000000);
|
||||||
SDR_WRITE(PESDR2_RCSSET,
|
SDR_WRITE(PESDR2_RCSSET,
|
||||||
(SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
|
(SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -362,9 +396,15 @@ int ppc440spe_init_pcie_rootport(int port)
|
||||||
mdelay(100);
|
mdelay(100);
|
||||||
|
|
||||||
switch (port) {
|
switch (port) {
|
||||||
case 0: val = SDR_READ(PESDR0_RCSSTS); break;
|
case 0:
|
||||||
case 1: val = SDR_READ(PESDR1_RCSSTS); break;
|
val = SDR_READ(PESDR0_RCSSTS);
|
||||||
case 2: val = SDR_READ(PESDR2_RCSSTS); break;
|
break;
|
||||||
|
case 1:
|
||||||
|
val = SDR_READ(PESDR1_RCSSTS);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
val = SDR_READ(PESDR2_RCSSTS);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val & (1 << 20)) {
|
if (val & (1 << 20)) {
|
||||||
|
@ -376,17 +416,16 @@ int ppc440spe_init_pcie_rootport(int port)
|
||||||
* Verify link is up
|
* Verify link is up
|
||||||
*/
|
*/
|
||||||
val = 0;
|
val = 0;
|
||||||
switch (port)
|
switch (port) {
|
||||||
{
|
case 0:
|
||||||
case 0:
|
val = SDR_READ(PESDR0_LOOP);
|
||||||
val = SDR_READ(PESDR0_LOOP);
|
break;
|
||||||
break;
|
case 1:
|
||||||
case 1:
|
val = SDR_READ(PESDR1_LOOP);
|
||||||
val = SDR_READ(PESDR1_LOOP);
|
break;
|
||||||
break;
|
case 2:
|
||||||
case 2:
|
val = SDR_READ(PESDR2_LOOP);
|
||||||
val = SDR_READ(PESDR2_LOOP);
|
break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (!(val & 0x00001000)) {
|
if (!(val & 0x00001000)) {
|
||||||
printf("PCIE%d: link is not up.\n", port);
|
printf("PCIE%d: link is not up.\n", port);
|
||||||
|
@ -498,29 +537,246 @@ int ppc440spe_init_pcie_rootport(int port)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ppc440spe_setup_pcie(struct pci_controller *hose, int port)
|
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;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ppc440spe_setup_pcie_rootpoint(struct pci_controller *hose, int port)
|
||||||
{
|
{
|
||||||
volatile void *mbase = NULL;
|
volatile void *mbase = NULL;
|
||||||
|
volatile void *rmbase = NULL;
|
||||||
|
|
||||||
pci_set_ops(hose,
|
pci_set_ops(hose,
|
||||||
pcie_read_config_byte,
|
pcie_read_config_byte,
|
||||||
pcie_read_config_word,
|
pcie_read_config_word,
|
||||||
pcie_read_config_dword,
|
pcie_read_config_dword,
|
||||||
pcie_write_config_byte,
|
pcie_write_config_byte,
|
||||||
pcie_write_config_word,
|
pcie_write_config_word,
|
||||||
pcie_write_config_dword);
|
pcie_write_config_dword);
|
||||||
|
|
||||||
switch(port) {
|
switch (port) {
|
||||||
case 0:
|
case 0:
|
||||||
mbase = (u32 *)CFG_PCIE0_XCFGBASE;
|
mbase = (u32 *)CFG_PCIE0_XCFGBASE;
|
||||||
|
rmbase = (u32 *)CFG_PCIE0_CFGBASE;
|
||||||
hose->cfg_data = (u8 *)CFG_PCIE0_CFGBASE;
|
hose->cfg_data = (u8 *)CFG_PCIE0_CFGBASE;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
mbase = (u32 *)CFG_PCIE1_XCFGBASE;
|
mbase = (u32 *)CFG_PCIE1_XCFGBASE;
|
||||||
|
rmbase = (u32 *)CFG_PCIE1_CFGBASE;
|
||||||
hose->cfg_data = (u8 *)CFG_PCIE1_CFGBASE;
|
hose->cfg_data = (u8 *)CFG_PCIE1_CFGBASE;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
mbase = (u32 *)CFG_PCIE2_XCFGBASE;
|
mbase = (u32 *)CFG_PCIE2_XCFGBASE;
|
||||||
|
rmbase = (u32 *)CFG_PCIE2_CFGBASE;
|
||||||
hose->cfg_data = (u8 *)CFG_PCIE2_CFGBASE;
|
hose->cfg_data = (u8 *)CFG_PCIE2_CFGBASE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -528,14 +784,9 @@ void ppc440spe_setup_pcie(struct pci_controller *hose, int port)
|
||||||
/*
|
/*
|
||||||
* Set bus numbers on our root port
|
* Set bus numbers on our root port
|
||||||
*/
|
*/
|
||||||
if (ppc440spe_revB()) {
|
out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0);
|
||||||
out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0);
|
out_8((u8 *)mbase + PCI_SECONDARY_BUS, 1);
|
||||||
out_8((u8 *)mbase + PCI_SECONDARY_BUS, 1);
|
out_8((u8 *)mbase + PCI_SUBORDINATE_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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up outbound translation to hose->mem_space from PLB
|
* 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.
|
* subregions and to enable the outbound translation.
|
||||||
*/
|
*/
|
||||||
out_le32(mbase + PECFG_POM0LAH, 0x00000000);
|
out_le32(mbase + PECFG_POM0LAH, 0x00000000);
|
||||||
out_le32(mbase + PECFG_POM0LAL, (CFG_PCIE_MEMBASE +
|
out_le32(mbase + PECFG_POM0LAL, 0x00000000);
|
||||||
port * CFG_PCIE_MEMSIZE));
|
|
||||||
|
|
||||||
switch (port) {
|
switch (port) {
|
||||||
case 0:
|
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 + PCI_BASE_ADDRESS_1, 0);
|
||||||
out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffc);
|
out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffc);
|
||||||
out_le32(mbase + PECFG_BAR0LMPA, 0);
|
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_PIM0LAL, 0);
|
||||||
out_le32(mbase + PECFG_PIM0LAH, 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);
|
out_le32(mbase + PECFG_PIMEN, 0x1);
|
||||||
|
|
||||||
/* Enable I/O, Mem, and Busmaster cycles */
|
/* Enable I/O, Mem, and Busmaster cycles */
|
||||||
out_le16((u16 *)(mbase + PCI_COMMAND),
|
out_le16((u16 *)(mbase + PCI_COMMAND),
|
||||||
in_le16((u16 *)(mbase + PCI_COMMAND)) |
|
in_le16((u16 *)(mbase + PCI_COMMAND)) |
|
||||||
PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
|
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_PCI */
|
||||||
#endif /* CONFIG_440SPE */
|
#endif /* CONFIG_440SPE */
|
||||||
|
|
|
@ -139,9 +139,17 @@
|
||||||
*/
|
*/
|
||||||
#define PECFG_BAR0LMPA 0x210
|
#define PECFG_BAR0LMPA 0x210
|
||||||
#define PECFG_BAR0HMPA 0x214
|
#define PECFG_BAR0HMPA 0x214
|
||||||
|
#define PECFG_BAR1MPA 0x218
|
||||||
|
#define PECFG_BAR2MPA 0x220
|
||||||
|
|
||||||
#define PECFG_PIMEN 0x33c
|
#define PECFG_PIMEN 0x33c
|
||||||
#define PECFG_PIM0LAL 0x340
|
#define PECFG_PIM0LAL 0x340
|
||||||
#define PECFG_PIM0LAH 0x344
|
#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_POM0LAL 0x380
|
||||||
#define PECFG_POM0LAH 0x384
|
#define PECFG_POM0LAH 0x384
|
||||||
|
|
||||||
|
@ -156,7 +164,8 @@
|
||||||
int ppc440spe_init_pcie(void);
|
int ppc440spe_init_pcie(void);
|
||||||
int ppc440spe_init_pcie_rootport(int port);
|
int ppc440spe_init_pcie_rootport(int port);
|
||||||
void yucca_setup_pcie_fpga_rootpoint(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 yucca_pcie_card_present(int port);
|
||||||
int pcie_hose_scan(struct pci_controller *hose, int bus);
|
int pcie_hose_scan(struct pci_controller *hose, int bus);
|
||||||
#endif /* __440SPE_PCIE_H */
|
#endif /* __440SPE_PCIE_H */
|
||||||
|
|
Loading…
Reference in New Issue