Commit ae6b03fe authored by Shengzhou Liu's avatar Shengzhou Liu Committed by Kumar Gala
Browse files

powerpc/p3060qds: Add board related support for P3060QDS platform



The P3060QDS is a Freescale reference board for the six-core P3060 SOC.

P3060QDS Board Overview:
 Memory subsystem:
  - 2G Bytes unbuffered DDR3 SDRAM SO-DIMM(64bit bus)
  - 128M Bytes NOR flash single-chip memory
  - 16M Bytes SPI flash
  - 8K Bytes AT24C64 I2C EEPROM for RCW
 Ethernet:
  - Eight Ethernet controllers (4x1G + 4x1G/2.5G)
  - Three VSC8641 PHYs on board (2xRGMII + 1xMII)
  - Suport multiple Vitesse VSC8234 SGMII Cards in Slot1/2/3
 PCIe: Two PCI Express 2.0 controllers/ports
 USB:  Two USB2.0, USB1(TYPE-A) and USB2(TYPE-AB) on board
 I2C:  Four I2C controllers
 UART: Supports two dUARTs up to 115200 bps for console
 RapidIO:  Two RapidIO, sRIO1 and sRIO2
Signed-off-by: default avatarShengzhou Liu <Shengzhou.Liu@freescale.com>
Signed-off-by: default avatarYork Sun <yorksun@freescale.com>
Signed-off-by: default avatarKumar Gala <galak@kernel.crashing.org>
parent f2717b47
......@@ -34,6 +34,7 @@ COBJS-$(CONFIG_FSL_VIA) += cds_via.o
COBJS-$(CONFIG_FMAN_ENET) += fman.o
COBJS-$(CONFIG_FSL_PIXIS) += pixis.o
COBJS-$(CONFIG_FSL_NGPIXIS) += ngpixis.o
COBJS-$(CONFIG_FSL_QIXIS) += qixis.o
COBJS-$(CONFIG_PQ_MDS_PIB) += pq-mds-pib.o
COBJS-$(CONFIG_ID_EEPROM) += sys_eeprom.o
COBJS-$(CONFIG_FSL_SGMII_RISER) += sgmii_riser.o
......@@ -50,12 +51,14 @@ COBJS-$(CONFIG_MPC8572DS) += ics307_clk.o
COBJS-$(CONFIG_P1022DS) += ics307_clk.o
COBJS-$(CONFIG_P2020DS) += ics307_clk.o
COBJS-$(CONFIG_P3041DS) += ics307_clk.o
COBJS-$(CONFIG_P3060QDS) += ics307_clk.o
COBJS-$(CONFIG_P4080DS) += ics307_clk.o
COBJS-$(CONFIG_P5020DS) += ics307_clk.o
# deal with common files for P-series corenet based devices
SUBLIB-$(CONFIG_P2041RDB) += p_corenet/libp_corenet.o
SUBLIB-$(CONFIG_P3041DS) += p_corenet/libp_corenet.o
SUBLIB-$(CONFIG_P3060QDS) += p_corenet/libp_corenet.o
SUBLIB-$(CONFIG_P4080DS) += p_corenet/libp_corenet.o
SUBLIB-$(CONFIG_P5020DS) += p_corenet/libp_corenet.o
......
/*
* Copyright 2010 Freescale Semiconductor, Inc.
* Copyright 2010-2011 Freescale Semiconductor, Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
......@@ -25,10 +25,15 @@
#include "ics307_clk.h"
#ifdef CONFIG_FSL_NGPIXIS
#if defined(CONFIG_FSL_NGPIXIS)
#include "ngpixis.h"
#define fpga_reg pixis
#elif defined(CONFIG_FSL_QIXIS)
#include "qixis.h"
#define fpga_reg ((struct qixis *)QIXIS_BASE)
#else
#include "pixis.h"
#define fpga_reg pixis
#endif
/* define for SYS CLK or CLK1Frequency */
......@@ -143,15 +148,15 @@ static unsigned long ics307_clk_freq(u8 cw0, u8 cw1, u8 cw2)
unsigned long get_board_sys_clk(void)
{
return ics307_clk_freq(
in_8(&pixis->sclk[0]),
in_8(&pixis->sclk[1]),
in_8(&pixis->sclk[2]));
in_8(&fpga_reg->sclk[0]),
in_8(&fpga_reg->sclk[1]),
in_8(&fpga_reg->sclk[2]));
}
unsigned long get_board_ddr_clk(void)
{
return ics307_clk_freq(
in_8(&pixis->dclk[0]),
in_8(&pixis->dclk[1]),
in_8(&pixis->dclk[2]));
in_8(&fpga_reg->dclk[0]),
in_8(&fpga_reg->dclk[1]),
in_8(&fpga_reg->dclk[2]));
}
/*
* Copyright 2011 Freescale Semiconductor
* Author: Shengzhou Liu <Shengzhou.Liu@freescale.com>
*
* 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 file provides support for the QIXIS of some Freescale reference boards.
*
*/
#include <common.h>
#include <command.h>
#include <asm/io.h>
#include "qixis.h"
u8 qixis_read(unsigned int reg)
{
void *p = (void *)QIXIS_BASE;
return in_8(p + reg);
}
void qixis_write(unsigned int reg, u8 value)
{
void *p = (void *)QIXIS_BASE;
out_8(p + reg, value);
}
void qixis_reset(void)
{
QIXIS_WRITE(rst_ctl, 0x83);
}
void qixis_bank_reset(void)
{
QIXIS_WRITE(rcfg_ctl, 0x20);
QIXIS_WRITE(rcfg_ctl, 0x21);
}
/* Set the boot bank to the power-on default bank0 */
void clear_altbank(void)
{
u8 reg;
reg = QIXIS_READ(brdcfg[0]);
reg = reg & ~QIXIS_LBMAP_MASK;
QIXIS_WRITE(brdcfg[0], reg);
}
/* Set the boot bank to the alternate bank */
void set_altbank(void)
{
u8 reg;
reg = QIXIS_READ(brdcfg[0]);
reg = (reg & ~QIXIS_LBMAP_MASK) | QIXIS_LBMAP_ALTBANK;
QIXIS_WRITE(brdcfg[0], reg);
}
#ifdef DEBUG
static void qixis_dump_regs(void)
{
int i;
printf("id = %02x\n", QIXIS_READ(id));
printf("arch = %02x\n", QIXIS_READ(arch));
printf("scver = %02x\n", QIXIS_READ(scver));
printf("model = %02x\n", QIXIS_READ(model));
printf("rst_ctl = %02x\n", QIXIS_READ(rst_ctl));
printf("aux = %02x\n", QIXIS_READ(aux));
for (i = 0; i < 16; i++)
printf("brdcfg%02d = %02x\n", i, QIXIS_READ(brdcfg[i]));
for (i = 0; i < 16; i++)
printf("dutcfg%02d = %02x\n", i, QIXIS_READ(dutcfg[i]));
printf("sclk = %02x%02x%02x\n", QIXIS_READ(sclk[0]),
QIXIS_READ(sclk[1]), QIXIS_READ(sclk[2]));
printf("dclk = %02x%02x%02x\n", QIXIS_READ(dclk[0]),
QIXIS_READ(dclk[1]), QIXIS_READ(dclk[2]));
printf("aux = %02x\n", QIXIS_READ(aux));
printf("watch = %02x\n", QIXIS_READ(watch));
printf("ctl_sys = %02x\n", QIXIS_READ(ctl_sys));
printf("rcw_ctl = %02x\n", QIXIS_READ(rcw_ctl));
printf("present = %02x\n", QIXIS_READ(present));
printf("clk_spd = %02x\n", QIXIS_READ(clk_spd));
printf("stat_dut = %02x\n", QIXIS_READ(stat_dut));
printf("stat_sys = %02x\n", QIXIS_READ(stat_sys));
printf("stat_alrm = %02x\n", QIXIS_READ(stat_alrm));
printf("ctl_sys2 = %02x\n", QIXIS_READ(ctl_sys2));
}
#endif
int qixis_reset_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int i;
if (argc <= 1) {
clear_altbank();
qixis_reset();
} else if (strcmp(argv[1], "altbank") == 0) {
set_altbank();
qixis_bank_reset();
} else if (strcmp(argv[1], "watchdog") == 0) {
static char *period[9] = {"2s", "4s", "8s", "16s", "32s",
"1min", "2min", "4min", "8min"};
u8 rcfg = QIXIS_READ(rcfg_ctl);
if (argv[2] == NULL) {
printf("qixis watchdog <watchdog_period>\n");
return 0;
}
for (i = 0; i < ARRAY_SIZE(period); i++) {
if (strcmp(argv[2], period[i]) == 0) {
/* disable watchdog */
QIXIS_WRITE(rcfg_ctl, rcfg & ~0x08);
QIXIS_WRITE(watch, ((i<<2) - 1));
QIXIS_WRITE(rcfg_ctl, rcfg);
return 0;
}
}
}
#ifdef DEBUG
else if (strcmp(argv[1], "dump") == 0) {
qixis_dump_regs();
return 0;
}
#endif
else {
printf("Invalid option: %s\n", argv[1]);
return 1;
}
return 0;
}
U_BOOT_CMD(
qixis_reset, CONFIG_SYS_MAXARGS, 1, qixis_reset_cmd,
"Reset the board using the FPGA sequencer",
"- hard reset to default bank\n"
"qixis_reset altbank - reset to alternate bank\n"
"qixis watchdog <watchdog_period> - set the watchdog period\n"
" period: 1s 2s 4s 8s 16s 32s 1min 2min 4min 8min\n"
#ifdef DEBUG
"qixis_reset dump - display the QIXIS registers\n"
#endif
);
/*
* Copyright 2011 Freescale Semiconductor
* Author: Shengzhou Liu <Shengzhou.Liu@freescale.com>
*
* 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 file provides support for the QIXIS of some Freescale reference boards.
*/
#ifndef __QIXIS_H_
#define __QIXIS_H_
struct qixis {
u8 id; /* ID value uniquely identifying each QDS board type */
u8 arch; /* Board version information */
u8 scver; /* QIXIS Version Register */
u8 model; /* Information of software programming model version */
u8 tagdata;
u8 ctl_sys;
u8 aux; /* Auxiliary Register,0x06 */
u8 clk_spd;
u8 stat_dut;
u8 stat_sys;
u8 stat_alrm;
u8 present;
u8 ctl_sys2;
u8 rcw_ctl;
u8 ctl_led;
u8 i2cblk;
u8 rcfg_ctl; /* Reconfig Control Register,0x10 */
u8 rcfg_st;
u8 dcm_ad;
u8 dcm_da;
u8 dcmd;
u8 dmsg;
u8 gdc;
u8 gdd; /* DCM Debug Data Register,0x17 */
u8 dmack;
u8 res1[6];
u8 watch; /* Watchdog Register,0x1F */
u8 pwr_ctl[2]; /* Power Control Register,0x20 */
u8 res2[2];
u8 pwr_stat[4]; /* Power Status Register,0x24 */
u8 res3[8];
u8 clk_spd2[2]; /* SYSCLK clock Speed Register,0x30 */
u8 res4[2];
u8 sclk[3]; /* Clock Configuration Registers,0x34 */
u8 res5;
u8 dclk[3];
u8 res6;
u8 clk_dspd[3];
u8 res7;
u8 rst_ctl; /* Reset Control Register,0x40 */
u8 rst_stat; /* Reset Status Register */
u8 rst_rsn; /* Reset Reason Register */
u8 rst_frc[2]; /* Reset Force Registers,0x43 */
u8 res8[11];
u8 brdcfg[16]; /* Board Configuration Register,0x50 */
u8 dutcfg[16];
u8 rcw_ad[2]; /* RCW SRAM Address Registers,0x70 */
u8 rcw_data;
u8 res9[5];
u8 post_ctl;
u8 post_stat;
u8 post_dat[2];
u8 pi_d[4];
u8 gpio_io[4];
u8 gpio_dir[4];
u8 res10[20];
u8 rjtag_ctl;
u8 rjtag_dat;
u8 res11[2];
u8 trig_src[4];
u8 trig_dst[4];
u8 trig_stat;
u8 res12[3];
u8 trig_ctr[4];
u8 res13[48];
u8 aux2[4]; /* Auxiliary Registers,0xE0 */
u8 res14[10];
u8 aux_ad;
u8 aux_da;
u8 res15[16];
};
#define QIXIS_BASE 0xffdf0000
#define QIXIS_LBMAP_SWITCH 7
#define QIXIS_LBMAP_MASK 0x0f
#define QIXIS_LBMAP_SHIFT 0
#define QIXIS_LBMAP_ALTBANK 0x04
u8 qixis_read(unsigned int reg);
void qixis_write(unsigned int reg, u8 value);
#define QIXIS_READ(reg) qixis_read(offsetof(struct qixis, reg))
#define QIXIS_WRITE(reg, value) qixis_write(offsetof(struct qixis, reg), value)
#endif
#
# Copyright 2011 Freescale Semiconductor, Inc.
# (C) Copyright 2001-2006
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# 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 $(TOPDIR)/config.mk
LIB = $(obj)lib$(BOARD).o
COBJS-y += $(BOARD).o
COBJS-y += ddr.o
COBJS-y += eth.o
COBJS-y += fixed_ddr.o
SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS-y))
SOBJS := $(addprefix $(obj),$(SOBJS))
$(LIB): $(obj).depend $(OBJS) $(SOBJS)
$(call cmd_link_o_target, $(OBJS))
clean:
rm -f $(OBJS) $(SOBJS)
distclean: clean
rm -f $(LIB) core *.bak .depend
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################
/*
* Copyright 2009-2011 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* Version 2 as published by the Free Software Foundation.
*/
#include <common.h>
#include <i2c.h>
#include <hwconfig.h>
#include <asm/mmu.h>
#include <asm/fsl_ddr_sdram.h>
#include <asm/fsl_ddr_dimm_params.h>
#include <asm/fsl_law.h>
#include "p3060qds.h"
/*
* Fixed sdram init -- doesn't use serial presence detect.
*/
phys_size_t fixed_sdram(void)
{
int i;
char buf[32];
fsl_ddr_cfg_regs_t ddr_cfg_regs;
phys_size_t ddr_size;
unsigned int lawbar1_target_id;
ulong ddr_freq, ddr_freq_mhz;
ddr_freq = get_ddr_freq(0);
ddr_freq_mhz = ddr_freq / 1000000;
printf("Configuring DDR for %s MT/s data rate\n",
strmhz(buf, ddr_freq));
for (i = 0; fixed_ddr_parm_0[i].max_freq > 0; i++) {
if ((ddr_freq_mhz > fixed_ddr_parm_0[i].min_freq) &&
(ddr_freq_mhz <= fixed_ddr_parm_0[i].max_freq)) {
memcpy(&ddr_cfg_regs,
fixed_ddr_parm_0[i].ddr_settings,
sizeof(ddr_cfg_regs));
break;
}
}
if (fixed_ddr_parm_0[i].max_freq == 0)
panic("Unsupported DDR data rate %s MT/s data rate\n",
strmhz(buf, ddr_freq));
ddr_size = (phys_size_t) CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
ddr_cfg_regs.ddr_cdr1 = DDR_CDR1_DHC_EN;
fsl_ddr_set_memctl_regs(&ddr_cfg_regs, 0);
/*
* setup laws for DDR. If not interleaving, presuming half memory on
* DDR1 and the other half on DDR2
*/
if (fixed_ddr_parm_0[i].ddr_settings->cs[0].config & 0x20000000) {
if (set_ddr_laws(CONFIG_SYS_DDR_SDRAM_BASE,
ddr_size,
LAW_TRGT_IF_DDR_INTRLV) < 0) {
printf("ERROR setting Local Access Windows for DDR\n");
return 0;
}
} else {
lawbar1_target_id = LAW_TRGT_IF_DDR_1;
if (set_ddr_laws(CONFIG_SYS_DDR_SDRAM_BASE,
ddr_size,
lawbar1_target_id) < 0) {
printf("ERROR setting Local Access Windows for DDR\n");
return 0;
}
}
return ddr_size;
}
struct board_specific_params {
u32 n_ranks;
u32 datarate_mhz_high;
u32 clk_adjust;
u32 wrlvl_start;
u32 cpo;
u32 write_data_delay;
u32 force_2T;
};
/*
* This table contains all valid speeds we want to override with board
* specific parameters. datarate_mhz_high values need to be in ascending order
* for each n_ranks group.
*/
static const struct board_specific_params udimm[] = {
/*
* memory controller 0
* num| hi| clk| wrlvl | cpo |wrdata|2T
* ranks| mhz|adjst| start | |delay |
*/
{4, 850, 4, 6, 0xff, 2, 0},
{4, 950, 5, 7, 0xff, 2, 0},
{4, 1050, 5, 8, 0xff, 2, 0},
{4, 1250, 5, 10, 0xff, 2, 0},
{4, 1350, 5, 11, 0xff, 2, 0},
{4, 1666, 5, 12, 0xff, 2, 0},
{2, 850, 5, 6, 0xff, 2, 0},
{2, 950, 5, 7, 0xff, 2, 0},
{2, 1250, 4, 6, 0xff, 2, 0},
{2, 1350, 5, 7, 0xff, 2, 0},
{2, 1666, 5, 8, 0xff, 2, 0},
{1, 850, 4, 5, 0xff, 2, 0},
{1, 950, 4, 7, 0xff, 2, 0},
{1, 1666, 4, 8, 0xff, 2, 0},
{}
};
static const struct board_specific_params rdimm[] = {
/*
* memory controller 0
* num| hi| clk| wrlvl | cpo |wrdata|2T
* ranks| mhz|adjst| start | |delay |
*/
{4, 850, 4, 6, 0xff, 2, 0},
{4, 950, 5, 7, 0xff, 2, 0},
{4, 1050, 5, 8, 0xff, 2, 0},
{4, 1250, 5, 10, 0xff, 2, 0},
{4, 1350, 5, 11, 0xff, 2, 0},
{4, 1666, 5, 12, 0xff, 2, 0},
{2, 850, 4, 6, 0xff, 2, 0},
{2, 1050, 4, 7, 0xff, 2, 0},
{2, 1666, 4, 8, 0xff, 2, 0},
{1, 850, 4, 5, 0xff, 2, 0},
{1, 950, 4, 7, 0xff, 2, 0},
{1, 1666, 4, 8, 0xff, 2, 0},
{}
};
void fsl_ddr_board_options(memctl_options_t *popts,
dimm_params_t *pdimm,
unsigned int ctrl_num)
{
const struct board_specific_params *pbsp, *pbsp_highest = NULL;
ulong ddr_freq;
if (ctrl_num) {
printf("Wrong parameter for controller number %d", ctrl_num);
return;
}
if (!pdimm->n_ranks)
return;
if (popts->registered_dimm_en)
pbsp = rdimm;
else
pbsp = udimm;
/* Get clk_adjust, cpo, write_data_delay,2T, according to the board ddr
* freqency and n_banks specified in board_specific_parameters table.
*/
ddr_freq = get_ddr_freq(0) / 1000000;
while (pbsp->datarate_mhz_high) {
if (pbsp->n_ranks == pdimm->n_ranks) {
if (ddr_freq <= pbsp->datarate_mhz_high) {
popts->cpo_override = pbsp->cpo;
popts->write_data_delay =
pbsp->write_data_delay;
popts->clk_adjust = pbsp->clk_adjust;
popts->wrlvl_start = pbsp->wrlvl_start;
popts->twoT_en = pbsp->force_2T;
goto found;
}
pbsp_highest = pbsp;
}
pbsp++;
}
if (pbsp_highest) {
printf("Error: board specific timing not found "
"for data rate %lu MT/s!\n"
"Trying to use the highest speed (%u) parameters\n",
ddr_freq, pbsp_highest->datarate_mhz_high);
popts->cpo_override = pbsp_highest->cpo;
popts->write_data_delay = pbsp_highest->write_data_delay;
popts->clk_adjust = pbsp_highest->clk_adjust;
popts->wrlvl_start = pbsp_highest->wrlvl_start;
popts->twoT_en = pbsp_highest->force_2T;
} else {
panic("DIMM is not supported by this board");
}
found:
/*
* The datasheet of HMT125U7BFR8C-H9 blocks CL=7 as reservered.
* However SPD still claims CL=7 is supported. Extensive tests
* confirmed this board cannot work stably with CL=7 with this
* particular DIMM.
*/
if (ddr_freq >= 800 && ddr_freq < 1066 && \
!strncmp(pdimm[0].mpart, "HMT125U7BFR8C-H9", 16)) {
popts->cas_latency_override = 1;
popts->cas_latency_override_value = 8;
debug("Override CL to 8\n");
}
/*
* Factors to consider for half-strength driver enable:
* - number of DIMMs installed
*/
popts->half_strength_driver_enable = 0;
/*
* Write leveling override
*/
popts->wrlvl_override = 1;
popts->wrlvl_sample = 0xf;
/*
* Rtt and Rtt_WR override
*/
popts->rtt_override = 0;
/* Enable ZQ calibration */
popts->zq_en = 1;
/* DHC_EN =1, ODT = 60 Ohm */
popts->ddr_cdr1 = DDR_CDR1_DHC_EN;
}
phys_size_t initdram(int board_type)
{
phys_size_t dram_size;
puts("Initializing....");
if (fsl_use_spd()) {
puts("using SPD\n");