Because the inbound pci windows are mapped generously, set up the more specific outbound windows first. This way, when we search the pci regions for something, we will hit on the more specific region. This can actually be a problem on systems with large amounts of RAM. Signed-off-by: Becky Bruce <beckyb@kernel.crashing.org>
365 lines
8.4 KiB
C
365 lines
8.4 KiB
C
/*
|
|
* Copyright 2006, 2007 Freescale Semiconductor.
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <pci.h>
|
|
#include <asm/processor.h>
|
|
#include <asm/immap_86xx.h>
|
|
#include <asm/immap_fsl_pci.h>
|
|
#include <asm/fsl_ddr_sdram.h>
|
|
#include <asm/io.h>
|
|
#include <libfdt.h>
|
|
#include <fdt_support.h>
|
|
#include <netdev.h>
|
|
|
|
#include "../common/pixis.h"
|
|
|
|
phys_size_t fixed_sdram(void);
|
|
|
|
int board_early_init_f(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int checkboard(void)
|
|
{
|
|
printf ("Board: MPC8641HPCN, System ID: 0x%02x, "
|
|
"System Version: 0x%02x, FPGA Version: 0x%02x\n",
|
|
in8(PIXIS_BASE + PIXIS_ID), in8(PIXIS_BASE + PIXIS_VER),
|
|
in8(PIXIS_BASE + PIXIS_PVER));
|
|
return 0;
|
|
}
|
|
|
|
|
|
phys_size_t
|
|
initdram(int board_type)
|
|
{
|
|
phys_size_t dram_size = 0;
|
|
|
|
#if defined(CONFIG_SPD_EEPROM)
|
|
dram_size = fsl_ddr_sdram();
|
|
#else
|
|
dram_size = fixed_sdram();
|
|
#endif
|
|
|
|
#if defined(CONFIG_SYS_RAMBOOT)
|
|
puts(" DDR: ");
|
|
return dram_size;
|
|
#endif
|
|
|
|
puts(" DDR: ");
|
|
return dram_size;
|
|
}
|
|
|
|
|
|
#if !defined(CONFIG_SPD_EEPROM)
|
|
/*
|
|
* Fixed sdram init -- doesn't use serial presence detect.
|
|
*/
|
|
phys_size_t
|
|
fixed_sdram(void)
|
|
{
|
|
#if !defined(CONFIG_SYS_RAMBOOT)
|
|
volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
|
|
volatile ccsr_ddr_t *ddr = &immap->im_ddr1;
|
|
|
|
ddr->cs0_bnds = CONFIG_SYS_DDR_CS0_BNDS;
|
|
ddr->cs0_config = CONFIG_SYS_DDR_CS0_CONFIG;
|
|
ddr->timing_cfg_3 = CONFIG_SYS_DDR_TIMING_3;
|
|
ddr->timing_cfg_0 = CONFIG_SYS_DDR_TIMING_0;
|
|
ddr->timing_cfg_1 = CONFIG_SYS_DDR_TIMING_1;
|
|
ddr->timing_cfg_2 = CONFIG_SYS_DDR_TIMING_2;
|
|
ddr->sdram_mode_1 = CONFIG_SYS_DDR_MODE_1;
|
|
ddr->sdram_mode_2 = CONFIG_SYS_DDR_MODE_2;
|
|
ddr->sdram_interval = CONFIG_SYS_DDR_INTERVAL;
|
|
ddr->sdram_data_init = CONFIG_SYS_DDR_DATA_INIT;
|
|
ddr->sdram_clk_cntl = CONFIG_SYS_DDR_CLK_CTRL;
|
|
ddr->sdram_ocd_cntl = CONFIG_SYS_DDR_OCD_CTRL;
|
|
ddr->sdram_ocd_status = CONFIG_SYS_DDR_OCD_STATUS;
|
|
|
|
#if defined (CONFIG_DDR_ECC)
|
|
ddr->err_disable = 0x0000008D;
|
|
ddr->err_sbe = 0x00ff0000;
|
|
#endif
|
|
asm("sync;isync");
|
|
|
|
udelay(500);
|
|
|
|
#if defined (CONFIG_DDR_ECC)
|
|
/* Enable ECC checking */
|
|
ddr->sdram_cfg_1 = (CONFIG_SYS_DDR_CONTROL | 0x20000000);
|
|
#else
|
|
ddr->sdram_cfg_1 = CONFIG_SYS_DDR_CONTROL;
|
|
ddr->sdram_cfg_2 = CONFIG_SYS_DDR_CONTROL2;
|
|
#endif
|
|
asm("sync; isync");
|
|
|
|
udelay(500);
|
|
#endif
|
|
return CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
|
|
}
|
|
#endif /* !defined(CONFIG_SPD_EEPROM) */
|
|
|
|
|
|
#if defined(CONFIG_PCI)
|
|
static struct pci_controller pci1_hose;
|
|
#endif /* CONFIG_PCI */
|
|
|
|
#ifdef CONFIG_PCI2
|
|
static struct pci_controller pci2_hose;
|
|
#endif /* CONFIG_PCI2 */
|
|
|
|
int first_free_busno = 0;
|
|
|
|
extern int fsl_pci_setup_inbound_windows(struct pci_region *r);
|
|
extern void fsl_pci_init(struct pci_controller *hose);
|
|
|
|
void pci_init_board(void)
|
|
{
|
|
#ifdef CONFIG_PCI1
|
|
{
|
|
volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *) CONFIG_SYS_PCI1_ADDR;
|
|
struct pci_controller *hose = &pci1_hose;
|
|
struct pci_region *r = hose->regions;
|
|
volatile immap_t *immap = (immap_t *) CONFIG_SYS_CCSRBAR;
|
|
volatile ccsr_gur_t *gur = &immap->im_gur;
|
|
uint devdisr = gur->devdisr;
|
|
uint io_sel = (gur->pordevsr & MPC8641_PORDEVSR_IO_SEL)
|
|
>> MPC8641_PORDEVSR_IO_SEL_SHIFT;
|
|
|
|
#ifdef DEBUG
|
|
uint host1_agent = (gur->porbmsr & MPC8641_PORBMSR_HA)
|
|
>> MPC8641_PORBMSR_HA_SHIFT;
|
|
uint pex1_agent = (host1_agent == 0) || (host1_agent == 1);
|
|
#endif
|
|
if ((io_sel == 2 || io_sel == 3 || io_sel == 5
|
|
|| io_sel == 6 || io_sel == 7 || io_sel == 0xF)
|
|
&& !(devdisr & MPC86xx_DEVDISR_PCIEX1)) {
|
|
debug("PCI-EXPRESS 1: %s \n", pex1_agent ? "Agent" : "Host");
|
|
debug("0x%08x=0x%08x ", &pci->pme_msg_det, pci->pme_msg_det);
|
|
if (pci->pme_msg_det) {
|
|
pci->pme_msg_det = 0xffffffff;
|
|
debug(" with errors. Clearing. Now 0x%08x",
|
|
pci->pme_msg_det);
|
|
}
|
|
debug("\n");
|
|
|
|
/* outbound memory */
|
|
pci_set_region(r++,
|
|
CONFIG_SYS_PCI1_MEM_BASE,
|
|
CONFIG_SYS_PCI1_MEM_PHYS,
|
|
CONFIG_SYS_PCI1_MEM_SIZE,
|
|
PCI_REGION_MEM);
|
|
|
|
/* outbound io */
|
|
pci_set_region(r++,
|
|
CONFIG_SYS_PCI1_IO_BASE,
|
|
CONFIG_SYS_PCI1_IO_PHYS,
|
|
CONFIG_SYS_PCI1_IO_SIZE,
|
|
PCI_REGION_IO);
|
|
|
|
/* inbound */
|
|
r += fsl_pci_setup_inbound_windows(r);
|
|
|
|
hose->region_count = r - hose->regions;
|
|
|
|
hose->first_busno=first_free_busno;
|
|
pci_setup_indirect(hose, (int) &pci->cfg_addr, (int) &pci->cfg_data);
|
|
|
|
fsl_pci_init(hose);
|
|
|
|
first_free_busno=hose->last_busno+1;
|
|
printf (" PCI-EXPRESS 1 on bus %02x - %02x\n",
|
|
hose->first_busno,hose->last_busno);
|
|
|
|
/*
|
|
* Activate ULI1575 legacy chip by performing a fake
|
|
* memory access. Needed to make ULI RTC work.
|
|
*/
|
|
in_be32((unsigned *) ((char *)(CONFIG_SYS_PCI1_MEM_BASE
|
|
+ CONFIG_SYS_PCI1_MEM_SIZE - 0x1000000)));
|
|
|
|
} else {
|
|
puts("PCI-EXPRESS 1: Disabled\n");
|
|
}
|
|
}
|
|
#else
|
|
puts("PCI-EXPRESS1: Disabled\n");
|
|
#endif /* CONFIG_PCI1 */
|
|
|
|
#ifdef CONFIG_PCI2
|
|
{
|
|
volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *) CONFIG_SYS_PCI2_ADDR;
|
|
struct pci_controller *hose = &pci2_hose;
|
|
struct pci_region *r = hose->regions;
|
|
|
|
/* outbound memory */
|
|
pci_set_region(r++,
|
|
CONFIG_SYS_PCI2_MEM_BASE,
|
|
CONFIG_SYS_PCI2_MEM_PHYS,
|
|
CONFIG_SYS_PCI2_MEM_SIZE,
|
|
PCI_REGION_MEM);
|
|
|
|
/* outbound io */
|
|
pci_set_region(r++,
|
|
CONFIG_SYS_PCI2_IO_BASE,
|
|
CONFIG_SYS_PCI2_IO_PHYS,
|
|
CONFIG_SYS_PCI2_IO_SIZE,
|
|
PCI_REGION_IO);
|
|
|
|
/* inbound */
|
|
r += fsl_pci_setup_inbound_windows(r);
|
|
|
|
hose->region_count = r - hose->regions;
|
|
|
|
hose->first_busno=first_free_busno;
|
|
pci_setup_indirect(hose, (int) &pci->cfg_addr, (int) &pci->cfg_data);
|
|
|
|
fsl_pci_init(hose);
|
|
|
|
first_free_busno=hose->last_busno+1;
|
|
printf (" PCI-EXPRESS 2 on bus %02x - %02x\n",
|
|
hose->first_busno,hose->last_busno);
|
|
}
|
|
#else
|
|
puts("PCI-EXPRESS 2: Disabled\n");
|
|
#endif /* CONFIG_PCI2 */
|
|
|
|
}
|
|
|
|
|
|
#if defined(CONFIG_OF_BOARD_SETUP)
|
|
extern void ft_fsl_pci_setup(void *blob, const char *pci_alias,
|
|
struct pci_controller *hose);
|
|
|
|
void
|
|
ft_board_setup(void *blob, bd_t *bd)
|
|
{
|
|
int off;
|
|
u64 *tmp;
|
|
u32 *addrcells;
|
|
|
|
ft_cpu_setup(blob, bd);
|
|
|
|
#ifdef CONFIG_PCI1
|
|
ft_fsl_pci_setup(blob, "pci0", &pci1_hose);
|
|
#endif
|
|
#ifdef CONFIG_PCI2
|
|
ft_fsl_pci_setup(blob, "pci1", &pci2_hose);
|
|
#endif
|
|
|
|
/*
|
|
* Warn if it looks like the device tree doesn't match u-boot.
|
|
* This is just an estimation, based on the location of CCSR,
|
|
* which is defined by the "reg" property in the soc node.
|
|
*/
|
|
off = fdt_path_offset(blob, "/soc8641");
|
|
addrcells = (u32 *)fdt_getprop(blob, 0, "#address-cells", NULL);
|
|
tmp = (u64 *)fdt_getprop(blob, off, "reg", NULL);
|
|
|
|
if (tmp) {
|
|
u64 addr;
|
|
if (addrcells && (*addrcells == 1))
|
|
addr = *(u32 *)tmp;
|
|
else
|
|
addr = *tmp;
|
|
|
|
if (addr != CONFIG_SYS_CCSRBAR_PHYS)
|
|
printf("WARNING: The CCSRBAR address in your .dts "
|
|
"does not match the address of the CCSR "
|
|
"in u-boot. This means your .dts might "
|
|
"be old.\n");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
* get_board_sys_clk
|
|
* Reads the FPGA on board for CONFIG_SYS_CLK_FREQ
|
|
*/
|
|
|
|
unsigned long
|
|
get_board_sys_clk(ulong dummy)
|
|
{
|
|
u8 i, go_bit, rd_clks;
|
|
ulong val = 0;
|
|
|
|
go_bit = in8(PIXIS_BASE + PIXIS_VCTL);
|
|
go_bit &= 0x01;
|
|
|
|
rd_clks = in8(PIXIS_BASE + PIXIS_VCFGEN0);
|
|
rd_clks &= 0x1C;
|
|
|
|
/*
|
|
* Only if both go bit and the SCLK bit in VCFGEN0 are set
|
|
* should we be using the AUX register. Remember, we also set the
|
|
* GO bit to boot from the alternate bank on the on-board flash
|
|
*/
|
|
|
|
if (go_bit) {
|
|
if (rd_clks == 0x1c)
|
|
i = in8(PIXIS_BASE + PIXIS_AUX);
|
|
else
|
|
i = in8(PIXIS_BASE + PIXIS_SPD);
|
|
} else {
|
|
i = in8(PIXIS_BASE + PIXIS_SPD);
|
|
}
|
|
|
|
i &= 0x07;
|
|
|
|
switch (i) {
|
|
case 0:
|
|
val = 33000000;
|
|
break;
|
|
case 1:
|
|
val = 40000000;
|
|
break;
|
|
case 2:
|
|
val = 50000000;
|
|
break;
|
|
case 3:
|
|
val = 66000000;
|
|
break;
|
|
case 4:
|
|
val = 83000000;
|
|
break;
|
|
case 5:
|
|
val = 100000000;
|
|
break;
|
|
case 6:
|
|
val = 134000000;
|
|
break;
|
|
case 7:
|
|
val = 166000000;
|
|
break;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
int board_eth_init(bd_t *bis)
|
|
{
|
|
/* Initialize TSECs */
|
|
cpu_eth_init(bis);
|
|
return pci_eth_init(bis);
|
|
}
|