U-Boot
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2000 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
September 2008
- 151 participants
- 458 discussions
Dear Ben,
Sorry to nag,
I'm just checking in to see if you plan to push the patches I submitted,
the last discussion on them are listed below:
1. [U-boot] [PATCHv2 1/2] NET: QE: UEC: Make uec_miiphy_read() and
uec_miiphy_write() use the devname arg.
http://lists.denx.de/pipermail/u-boot/2008-August/038968.html
2. [U-Boot] [U-boot] [PATCH 2/2] NET: QE: UEC: Allow uec
re-initialization based on netretry environment variable.
http://lists.denx.de/pipermail/u-boot/2008-August/038976.html
Some newbie questions:
1. Is there a supposed to be a NACK e-mail if the patch is being rejected?
2. What is the proper way to check about patch status update like this?
Thanks for all your help,
Regards,
- Richard Retanubun.
6
6

[U-Boot] [PATCH] devices: Use list_add_tail() instead of list_add() to register a device
by Stefan Roese 05 Sep '08
by Stefan Roese 05 Sep '08
05 Sep '08
This patch fixes a problem spotted on Glacier/Canyonlands (and most
likely lots of other board ports), that no serial output was seen
after console initialization in console_init_r(). This is because the
last added console device was used instead of the first added.
This patch fixes this problem by using list_add_tail() instead of
list_add() to register a device. This way the first added console
is used again.
Signed-off-by: Stefan Roese <sr(a)denx.de>
---
common/devices.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/common/devices.c b/common/devices.c
index 8beebe2..7d0ac2e 100644
--- a/common/devices.c
+++ b/common/devices.c
@@ -155,7 +155,7 @@ int device_register (device_t * dev)
_dev = device_clone(dev);
if(!_dev)
return -1;
- list_add(&(_dev->list), &(devs.list));
+ list_add_tail(&(_dev->list), &(devs.list));
return 0;
}
--
1.5.6.5
2
1

[U-Boot] [PATCH 2/2] Update Kilauea board support to use PPC4xx DDR autocalibration routines.
by Adam Graham 05 Sep '08
by Adam Graham 05 Sep '08
05 Sep '08
Signed-off-by: Adam Graham <agraham(a)amcc.com>
---
cpu/ppc4xx/44x_spd_ddr2.c | 158 ++++++++++++++++++++++++----------------
cpu/ppc4xx/Makefile | 3 +
include/asm-ppc/ppc4xx-sdram.h | 3 +-
include/common.h | 21 +++++
include/configs/kilauea.h | 19 +++++
include/ppc440.h | 13 ---
include/ppc4xx.h | 13 +++
7 files changed, 153 insertions(+), 77 deletions(-)
diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c
index 15250d4..f1d7684 100644
--- a/cpu/ppc4xx/44x_spd_ddr2.c
+++ b/cpu/ppc4xx/44x_spd_ddr2.c
@@ -60,8 +60,6 @@
"SDRAM_" #mnemonic, SDRAM_##mnemonic, data); \
} while (0)
-static inline void ppc4xx_ibm_ddr2_register_dump(void);
-
#if defined(CONFIG_SPD_EEPROM)
/*-----------------------------------------------------------------------------+
@@ -260,62 +258,19 @@ static void program_ecc_addr(unsigned long start_address,
unsigned long num_bytes,
unsigned long tlb_word2_i_value);
#endif
+#if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
static void program_DQS_calibration(unsigned long *dimm_populated,
- unsigned char *iic0_dimm_addr,
- unsigned long num_dimm_banks);
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
#ifdef HARD_CODED_DQS /* calibration test with hardvalues */
static void test(void);
#else
static void DQS_calibration_process(void);
#endif
+#endif
int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
void dcbz_area(u32 start_address, u32 num_bytes);
-static u32 mfdcr_any(u32 dcr)
-{
- u32 val;
-
- switch (dcr) {
- case SDRAM_R0BAS + 0:
- val = mfdcr(SDRAM_R0BAS + 0);
- break;
- case SDRAM_R0BAS + 1:
- val = mfdcr(SDRAM_R0BAS + 1);
- break;
- case SDRAM_R0BAS + 2:
- val = mfdcr(SDRAM_R0BAS + 2);
- break;
- case SDRAM_R0BAS + 3:
- val = mfdcr(SDRAM_R0BAS + 3);
- break;
- default:
- printf("DCR %d not defined in case statement!!!\n", dcr);
- val = 0; /* just to satisfy the compiler */
- }
-
- return val;
-}
-
-static void mtdcr_any(u32 dcr, u32 val)
-{
- switch (dcr) {
- case SDRAM_R0BAS + 0:
- mtdcr(SDRAM_R0BAS + 0, val);
- break;
- case SDRAM_R0BAS + 1:
- mtdcr(SDRAM_R0BAS + 1, val);
- break;
- case SDRAM_R0BAS + 2:
- mtdcr(SDRAM_R0BAS + 2, val);
- break;
- case SDRAM_R0BAS + 3:
- mtdcr(SDRAM_R0BAS + 3, val);
- break;
- default:
- printf("DCR %d not defined in case statement!!!\n", dcr);
- }
-}
-
static unsigned char spd_read(uchar chip, uint addr)
{
unsigned char data[2];
@@ -609,7 +564,11 @@ phys_size_t initdram(int board_type)
/*------------------------------------------------------------------
* DQS calibration.
*-----------------------------------------------------------------*/
+#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
+ DQS_autocalibration();
+#else
program_DQS_calibration(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+#endif
#ifdef CONFIG_DDR_ECC
/*------------------------------------------------------------------
@@ -2329,18 +2288,6 @@ static unsigned long is_ecc_enabled(void)
return ecc;
}
-static void blank_string(int size)
-{
- int i;
-
- for (i=0; i<size; i++)
- putc('\b');
- for (i=0; i<size; i++)
- putc(' ');
- for (i=0; i<size; i++)
- putc('\b');
-}
-
#ifdef CONFIG_DDR_ECC
/*-----------------------------------------------------------------------------+
* program_ecc.
@@ -2468,6 +2415,7 @@ static void program_ecc_addr(unsigned long start_address,
}
#endif
+#if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
/*-----------------------------------------------------------------------------+
* program_DQS_calibration.
*-----------------------------------------------------------------------------*/
@@ -3001,7 +2949,8 @@ static void test(void)
(ppcMfdcr_sdram(SDRAM_MCOPT1) & ~SDRAM_MCOPT1_MCHK_MASK)
| ecc_temp);
}
-#endif
+#endif /* !HARD_CODED_DQS */
+#endif /* !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) */
#else /* CONFIG_SPD_EEPROM */
@@ -3104,9 +3053,12 @@ phys_size_t initdram(int board_type)
/* Set Delay Control Registers */
mtsdram(SDRAM_DLCR, CFG_SDRAM0_DLCR);
+
+#if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
mtsdram(SDRAM_RDCC, CFG_SDRAM0_RDCC);
mtsdram(SDRAM_RQDC, CFG_SDRAM0_RQDC);
mtsdram(SDRAM_RFDC, CFG_SDRAM0_RFDC);
+#endif /* !CONFIG_PPC4xx_DDR_AUTOCALIBRATION */
/*
* Enable Controller by SDRAM0_MCOPT2[DCEN] = 1:
@@ -3115,18 +3067,98 @@ phys_size_t initdram(int board_type)
mfsdram(SDRAM_MCOPT2, val);
mtsdram(SDRAM_MCOPT2, val | SDRAM_MCOPT2_DCEN_ENABLE);
+#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
+#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
+ /*------------------------------------------------------------------
+ | DQS calibration.
+ +-----------------------------------------------------------------*/
+ DQS_autocalibration();
+#endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */
+#endif /* CONFIG_PPC4xx_DDR_AUTOCALIBRATION */
+
#if defined(CONFIG_DDR_ECC)
ecc_init(CFG_SDRAM_BASE, CFG_MBYTES_SDRAM << 20);
#endif /* defined(CONFIG_DDR_ECC) */
ppc4xx_ibm_ddr2_register_dump();
+
+#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
+ /*
+ * Clear potential errors resulting from auto-calibration.
+ * If not done, then we could get an interrupt later on when
+ * exceptions are enabled.
+ */
+ set_mcsr(get_mcsr());
+#endif /* CONFIG_PPC4xx_DDR_AUTOCALIBRATION */
+
#endif /* !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) */
return (CFG_MBYTES_SDRAM << 20);
}
#endif /* CONFIG_SPD_EEPROM */
-static inline void ppc4xx_ibm_ddr2_register_dump(void)
+#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
+#if defined(CONFIG_440)
+u32 mfdcr_any(u32 dcr)
+{
+ u32 val;
+
+ switch (dcr) {
+ case SDRAM_R0BAS + 0:
+ val = mfdcr(SDRAM_R0BAS + 0);
+ break;
+ case SDRAM_R0BAS + 1:
+ val = mfdcr(SDRAM_R0BAS + 1);
+ break;
+ case SDRAM_R0BAS + 2:
+ val = mfdcr(SDRAM_R0BAS + 2);
+ break;
+ case SDRAM_R0BAS + 3:
+ val = mfdcr(SDRAM_R0BAS + 3);
+ break;
+ default:
+ printf("DCR %d not defined in case statement!!!\n", dcr);
+ val = 0; /* just to satisfy the compiler */
+ }
+
+ return val;
+}
+
+void mtdcr_any(u32 dcr, u32 val)
+{
+ switch (dcr) {
+ case SDRAM_R0BAS + 0:
+ mtdcr(SDRAM_R0BAS + 0, val);
+ break;
+ case SDRAM_R0BAS + 1:
+ mtdcr(SDRAM_R0BAS + 1, val);
+ break;
+ case SDRAM_R0BAS + 2:
+ mtdcr(SDRAM_R0BAS + 2, val);
+ break;
+ case SDRAM_R0BAS + 3:
+ mtdcr(SDRAM_R0BAS + 3, val);
+ break;
+ default:
+ printf("DCR %d not defined in case statement!!!\n", dcr);
+ }
+}
+#endif /* defined(CONFIG_440) */
+
+void blank_string(int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++)
+ putc('\b');
+ for (i = 0; i < size; i++)
+ putc(' ');
+ for (i = 0; i < size; i++)
+ putc('\b');
+}
+#endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */
+
+inline void ppc4xx_ibm_ddr2_register_dump(void)
{
#if defined(DEBUG)
printf("\nPPC4xx IBM DDR2 Register Dump:\n");
diff --git a/cpu/ppc4xx/Makefile b/cpu/ppc4xx/Makefile
index c773400..75f3e49 100644
--- a/cpu/ppc4xx/Makefile
+++ b/cpu/ppc4xx/Makefile
@@ -35,6 +35,9 @@ SOBJS += kgdb.o
COBJS := 40x_spd_sdram.o
COBJS += 44x_spd_ddr.o
COBJS += 44x_spd_ddr2.o
+ifdef CONFIG_PPC4xx_DDR_AUTOCALIBRATION
+COBJS += 4xx_ibm_ddr2_autocalib.o
+endif
COBJS += 4xx_pci.o
COBJS += 4xx_pcie.o
COBJS += bedbug_405.o
diff --git a/include/asm-ppc/ppc4xx-sdram.h b/include/asm-ppc/ppc4xx-sdram.h
index 0174d62..a1ef029 100644
--- a/include/asm-ppc/ppc4xx-sdram.h
+++ b/include/asm-ppc/ppc4xx-sdram.h
@@ -29,6 +29,7 @@
/*
* SDRAM Controller
*/
+
/*
* XXX - ToDo: Revisit file to change all these lower case defines into
* upper case. Also needs to be done in the controller setup code too
@@ -256,6 +257,7 @@
#define SDRAM_DLYCAL_DLCV_ENCODE(x) (((x)<<2) & SDRAM_DLYCAL_DLCV_MASK)
#define SDRAM_DLYCAL_DLCV_DECODE(x) (((x) & SDRAM_DLYCAL_DLCV_MASK)>>2)
+#if !defined(CONFIG_405EX)
/*
* Memory queue defines
*/
@@ -293,7 +295,6 @@
#define SDRAM_PLBADDUHB (SDRAMQ_DCR_BASE+0x10) /* PLB base address upper 32 LL */
-#if !defined(CONFIG_405EX)
/*
* Memory Bank 0-7 configuration
*/
diff --git a/include/common.h b/include/common.h
index a394988..2516bfd 100644
--- a/include/common.h
+++ b/include/common.h
@@ -287,6 +287,27 @@ void pciinfo (int, int);
#endif
#endif
+/*
+ * Prototypes
+ */
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
+void blank_string(int);
+inline void ppc4xx_ibm_ddr2_register_dump(void);
+#if defined(CONFIG_440)
+u32 mfdcr_any(u32);
+void mtdcr_any(u32, u32);
+#endif
+#if defined(CONFIG_SPD_EEPROM)
+u32 ddr_wrdtr(u32);
+u32 ddr_clktr(u32);
+void spd_ddr_init_hang(void);
+#endif
+#endif /* defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2) */
+
+#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
+u32 DQS_autocalibration(void);
+#endif /* CONFIG_PPC4xx_DDR_AUTOCALIBRATION */
+
int misc_init_f (void);
int misc_init_r (void);
diff --git a/include/configs/kilauea.h b/include/configs/kilauea.h
index a475f97..f9eaa77 100644
--- a/include/configs/kilauea.h
+++ b/include/configs/kilauea.h
@@ -223,6 +223,22 @@
*----------------------------------------------------------------------*/
#define CFG_MBYTES_SDRAM (256) /* 256MB */
+/*
+ * CONFIG_PPC4xx_DDR_AUTOCALIBRATION
+ *
+ * Note: DDR Autocalibration Method_A scans the full range of possible PPC4xx
+ * SDRAM Controller DDR autocalibration values and takes a lot longer
+ * to run than Method_B.
+ * (See the Method_A and Method_B algorithm discription in the file:
+ * cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c)
+ * Define CONFIG_PPC4xx_DDR_METHOD_A to use DDR autocalibration Method_A
+ *
+ * DDR Autocalibration Method_B is the default.
+ */
+#define CONFIG_PPC4xx_DDR_AUTOCALIBRATION /* IBM DDR autocalibration */
+#define DEBUG_PPC4xx_DDR_AUTOCALIBRATION /* dynamic DDR autocal debug */
+#undef CONFIG_PPC4xx_DDR_METHOD_A
+
#define CFG_SDRAM0_MB0CF_BASE (( 0 << 20) + CFG_SDRAM_BASE)
/* DDR1/2 SDRAM Device Control Register Data Values */
@@ -386,6 +402,9 @@
#define CONFIG_HAS_ETH1 1 /* add support for "eth1addr" */
#define CONFIG_PHY1_ADDR 2
+/* Debug messages for the DDR autocalibration */
+#define CONFIG_AUTOCALIB "silent\0" /* default is non-verbose */
+
/*
* Default environment variables
*/
diff --git a/include/ppc440.h b/include/ppc440.h
index 3584fd2..be8d3ff 100644
--- a/include/ppc440.h
+++ b/include/ppc440.h
@@ -2064,19 +2064,6 @@
#ifndef __ASSEMBLY__
-static inline u32 get_mcsr(void)
-{
- u32 val;
-
- asm volatile("mfspr %0, 0x23c" : "=r" (val) :);
- return val;
-}
-
-static inline void set_mcsr(u32 val)
-{
- asm volatile("mtspr 0x23c, %0" : "=r" (val) :);
-}
-
#endif /* _ASMLANGUAGE */
#endif /* __PPC440_H__ */
diff --git a/include/ppc4xx.h b/include/ppc4xx.h
index 59a3b06..e216663 100644
--- a/include/ppc4xx.h
+++ b/include/ppc4xx.h
@@ -203,6 +203,19 @@ typedef struct
unsigned long pllPlbDiv;
} PPC4xx_SYS_INFO;
+static inline u32 get_mcsr(void)
+{
+ u32 val;
+
+ asm volatile("mfspr %0, 0x23c" : "=r" (val) :);
+ return val;
+}
+
+static inline void set_mcsr(u32 val)
+{
+ asm volatile("mtspr 0x23c, %0" : "=r" (val) :);
+}
+
#endif /* __ASSEMBLY__ */
#endif /* __PPC4XX_H__ */
--
1.5.5
2
1

[U-Boot] [PATCH 1/2] PPC4xx IBM Memory Controller DDR autocalibration routines.
by Adam Graham 05 Sep '08
by Adam Graham 05 Sep '08
05 Sep '08
Alternate SDRAM DDR autocalibration routine that can be generically used
for any PPC4xx chips that have the IBM SDRAM Controller core allowing for
support of more DIMM/memory chip vendors and gets the DDR autocalibration
values which give the best read latency performance (SDRAM0_RDCC.[RDSS]).
Two alternate SDRAM DDR autocalibration algoritm are provided in this patch,
"Method_A" and "Method_B". DDR autocalibration Method_A scans the full range
of possible PPC4xx SDRAM Controller DDR autocalibration values and takes a
lot longer to run than Method_B. Method_B executes in the same amount of time
as the currently existing DDR autocalibration routine, i.e. 1 second or so.
Normally Method_B is used and it is set as the default method.
The current U-Boot PPC4xx DDR autocalibration code calibrates the IBM SDRAM
Controller registers.[bit-field]:
1) SDRAM0_RQDC.[RQFD]
2) SDRAM0_RFDC.[RFFD]
This alternate PPC4xx DDR autocalibration code calibrates the following
IBM SDRAM Controller registers.[bit-field]:
1) SDRAM0_WRDTR.[WDTR]
2) SDRAM0_CLKTR.[CKTR]
3) SDRAM0_RQDC.[RQFD]
4) SDRAM0_RFDC.[RFFD]
and will also use the calibrated settings of the above four registers that
produce the best "Read Sample Cycle Select" value in the SDRAM0_RDCC.[RDSS]
register.[bit-field].
Signed-off-by: Adam Graham <agraham(a)amcc.com>
---
cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c | 1212 +++++++++++++++++++++++++++++++++++
1 files changed, 1212 insertions(+), 0 deletions(-)
create mode 100644 cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
diff --git a/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c b/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
new file mode 100644
index 0000000..83b9883
--- /dev/null
+++ b/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
@@ -0,0 +1,1212 @@
+/*
+ * cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
+ * This SPD SDRAM detection code supports AMCC PPC44x cpu's with a
+ * DDR2 controller (non Denali Core). Those currently are:
+ *
+ * 405: 405EX
+ * 440/460: 440SP/440SPe/460EX/460GT/460SX
+ *
+ * (C) Copyright 2008 Applied Micro Circuits Corporation
+ * Adam Graham <agraham(a)amcc.com>
+ *
+ * (C) Copyright 2007-2008
+ * Stefan Roese, DENX Software Engineering, sr(a)denx.de.
+ *
+ * COPYRIGHT AMCC CORPORATION 2004
+ *
+ * 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
+ *
+ */
+
+/* define DEBUG for debugging output (obviously ;-)) */
+#undef DEBUG
+
+#include <common.h>
+#include <ppc4xx.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+
+#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
+
+/*
+ * Only compile the DDR auto-calibration code for NOR boot and
+ * not for NAND boot (NAND SPL and NAND U-Boot - NUB)
+ */
+#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
+
+#define MAXBXCF 4
+#define SDRAM_RXBAS_SHIFT_1M 20
+
+#if defined(CFG_DECREMENT_PATTERNS)
+#define NUMMEMTESTS 24
+#else
+#define NUMMEMTESTS 8
+#endif /* CFG_DECREMENT_PATTERNS */
+#define NUMLOOPS 1 /* configure as you deem approporiate */
+#define NUMMEMWORDS 16
+
+/* Private Structure Definitions */
+
+struct autocal_regs {
+ u32 rffd;
+ u32 rqfd;
+};
+
+struct ddrautocal {
+ u32 rffd;
+ u32 rffd_min;
+ u32 rffd_max;
+ u32 rffd_size;
+ u32 rqfd;
+ u32 rqfd_size;
+ u32 rdcc;
+ u32 flags;
+};
+
+struct sdram_timing {
+ u32 wrdtr;
+ u32 clktr;
+};
+
+struct sdram_timing_clks {
+ u32 wrdtr;
+ u32 clktr;
+ u32 rdcc;
+ u32 flags;
+};
+
+struct autocal_clks {
+ struct sdram_timing_clks clocks;
+ struct ddrautocal autocal;
+};
+
+/*--------------------------------------------------------------------------+
+ * Prototypes
+ *--------------------------------------------------------------------------*/
+#if defined(CONFIG_PPC4xx_DDR_METHOD_A)
+static u32 DQS_calibration_methodA(struct ddrautocal *);
+static u32 program_DQS_calibration_methodA(struct ddrautocal *);
+#else
+static u32 DQS_calibration_methodB(struct ddrautocal *);
+static u32 program_DQS_calibration_methodB(struct ddrautocal *);
+#endif
+static int short_mem_test(u32 *);
+
+/*
+ * To provide an interface for board specific config values in this common
+ * DDR setup code, we implement he "weak" default functions here. They return
+ * the default value back to the caller.
+ *
+ * Please see include/configs/yucca.h for an example fora board specific
+ * implementation.
+ */
+
+#if !defined(CONFIG_SPD_EEPROM)
+u32 __ddr_wrdtr(u32 default_val)
+{
+ return default_val;
+}
+u32 ddr_wrdtr(u32) __attribute__((weak, alias("__ddr_wrdtr")));
+
+u32 __ddr_clktr(u32 default_val)
+{
+ return default_val;
+}
+u32 ddr_clktr(u32) __attribute__((weak, alias("__ddr_clktr")));
+
+/*
+ * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed
+ */
+void __spd_ddr_init_hang(void)
+{
+ hang();
+}
+void
+spd_ddr_init_hang(void) __attribute__((weak, alias("__spd_ddr_init_hang")));
+#endif /* defined(CONFIG_SPD_EEPROM) */
+
+ulong __ddr_scan_option(ulong default_val)
+{
+ return default_val;
+}
+ulong ddr_scan_option(ulong) __attribute__((weak, alias("__ddr_scan_option")));
+
+static u32 *get_membase(int bxcr_num)
+{
+ ulong bxcf;
+ u32 *membase;
+
+#if defined(SDRAM_R0BAS)
+ /* BAS from Memory Queue rank reg. */
+ membase =
+ (u32 *)(SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+bxcr_num)));
+ bxcf = 0; /* just to satisfy the compiler */
+#else
+ /* BAS from SDRAM_MBxCF mem rank reg. */
+ mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
+ membase = (u32 *)((bxcf & 0xfff80000) << 3);
+#endif
+
+ return membase;
+}
+
+static inline void ecc_clear_status_reg(void)
+{
+ mtsdram(SDRAM_ECCCR, 0xffffffff);
+#if defined(SDRAM_R0BAS)
+ mtdcr(SDRAM_ERRSTATLL, 0xffffffff);
+#endif
+}
+
+static int ecc_check_status_reg(void)
+{
+ u32 ecc_status;
+
+ /*
+ * Compare suceeded, now check
+ * if got ecc error. If got an
+ * ecc error, then don't count
+ * this as a passing value
+ */
+ mfsdram(SDRAM_ECCCR, ecc_status);
+ if (ecc_status != 0x00000000) {
+ /* clear on error */
+ ecc_clear_status_reg();
+ /* ecc check failure */
+ return 0;
+ }
+ ecc_clear_status_reg();
+ sync();
+
+ return 1;
+}
+
+/* return 1 if passes, 0 if fail */
+static int short_mem_test(u32 *base_address)
+{
+ int i, j, l;
+ u32 ecc_mode = 0;
+
+ ulong test[NUMMEMTESTS][NUMMEMWORDS] = {
+ /* 0 */ {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF},
+ /* 1 */ {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000},
+ /* 2 */ {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+ 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+ 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+ 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555},
+ /* 3 */ {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+ 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+ 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+ 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA},
+ /* 4 */ {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+ 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+ 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+ 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A},
+ /* 5 */ {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+ 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+ 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+ 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5},
+ /* 6 */ {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+ 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+ 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+ 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA},
+ /* 7 */ {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+ 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+ 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+ 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55},
+
+#if defined(CFG_DECREMENT_PATTERNS)
+ /* 8 */ {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff},
+ /* 9 */ {0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
+ 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
+ 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
+ 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe},
+ /* 10 */{0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
+ 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
+ 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
+ 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd},
+ /* 11 */{0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
+ 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
+ 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
+ 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc},
+ /* 12 */{0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
+ 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
+ 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
+ 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb},
+ /* 13 */{0xfffafffa, 0xfffafffa, 0xfffffffa, 0xfffafffa,
+ 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa,
+ 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa,
+ 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa},
+ /* 14 */{0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
+ 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
+ 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
+ 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9},
+ /* 15 */{0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
+ 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
+ 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
+ 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8},
+ /* 16 */{0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
+ 0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
+ 0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
+ 0xfff7ffff, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7},
+ /* 17 */{0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
+ 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
+ 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
+ 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7},
+ /* 18 */{0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
+ 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
+ 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
+ 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5},
+ /* 19 */{0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
+ 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
+ 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
+ 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4},
+ /* 20 */{0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
+ 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
+ 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
+ 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3},
+ /* 21 */{0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
+ 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
+ 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
+ 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2},
+ /* 22 */{0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
+ 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
+ 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
+ 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1},
+ /* 23 */{0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
+ 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
+ 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
+ 0xfff0fff0, 0xfff0fffe, 0xfff0fff0, 0xfff0fff0},
+#endif /* CFG_DECREMENT_PATTERNS */
+ };
+
+ mfsdram(SDRAM_MCOPT1, ecc_mode);
+ if ((ecc_mode & SDRAM_MCOPT1_MCHK_CHK_REP) ==
+ SDRAM_MCOPT1_MCHK_CHK_REP) {
+ ecc_clear_status_reg();
+ sync();
+ ecc_mode = 1;
+ } else {
+ ecc_mode = 0;
+ }
+
+ /*
+ * Run the short memory test.
+ */
+ for (i = 0; i < NUMMEMTESTS; i++) {
+ for (j = 0; j < NUMMEMWORDS; j++) {
+ base_address[j] = test[i][j];
+ ppcDcbf((ulong)&(base_address[j]));
+ }
+ sync();
+ for (l = 0; l < NUMLOOPS; l++) {
+ for (j = 0; j < NUMMEMWORDS; j++) {
+ if (base_address[j] != test[i][j]) {
+ ppcDcbf((u32)&(base_address[j]));
+ return 0;
+ } else {
+ if (ecc_mode) {
+ if (!ecc_check_status_reg())
+ return 0;
+ }
+ }
+ ppcDcbf((u32)&(base_address[j]));
+ } /* for (j = 0; j < NUMMEMWORDS; j++) */
+ sync();
+ } /* for (l=0; l<NUMLOOPS; l++) */
+ }
+
+ return 1;
+}
+
+#if defined(CONFIG_PPC4xx_DDR_METHOD_A)
+/*-----------------------------------------------------------------------------+
+| program_DQS_calibration_methodA.
++-----------------------------------------------------------------------------*/
+static u32 program_DQS_calibration_methodA(struct ddrautocal *ddrcal)
+{
+ u32 pass_result = 0;
+
+#ifdef DEBUG
+ ulong temp;
+
+ mfsdram(SDRAM_RDCC, temp);
+ debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp);
+#endif
+
+ pass_result = DQS_calibration_methodA(ddrcal);
+
+ return pass_result;
+}
+
+/*
+ * DQS_calibration_methodA()
+ *
+ * Autocalibration Method A
+ *
+ * ARRAY [Entire DQS Range] DQS_Valid_Window ; initialized to all zeros
+ * ARRAY [Entire FDBK Range] FDBK_Valid_Window; initialized to all zeros
+ * MEMWRITE(addr, expected_data);
+ * for (i = 0; i < Entire DQS Range; i++) { RQDC.RQFD
+ * for (j = 0; j < Entire FDBK Range; j++) { RFDC.RFFD
+ * MEMREAD(addr, actual_data);
+ * if (actual_data == expected_data) {
+ * DQS_Valid_Window[i] = 1; RQDC.RQFD
+ * FDBK_Valid_Window[i][j] = 1; RFDC.RFFD
+ * }
+ * }
+ * }
+ */
+static u32 DQS_calibration_methodA(struct ddrautocal *cal)
+{
+ ulong rfdc_reg;
+ ulong rffd;
+
+ ulong rqdc_reg;
+ ulong rqfd;
+
+ u32 *membase;
+ ulong bxcf;
+ int rqfd_average;
+ int bxcr_num;
+ int rffd_average;
+ int pass;
+ u32 passed = 0;
+
+ int in_window;
+ struct autocal_regs curr_win_min;
+ struct autocal_regs curr_win_max;
+ struct autocal_regs best_win_min;
+ struct autocal_regs best_win_max;
+ struct autocal_regs loop_win_min;
+ struct autocal_regs loop_win_max;
+
+#ifdef DEBUG
+ ulong temp;
+#endif
+ ulong rdcc;
+
+ char slash[] = "\\|/-\\|/-";
+ int loopi = 0;
+
+ /* start */
+ in_window = 0;
+
+ memset(&curr_win_min, 0, sizeof(curr_win_min));
+ memset(&curr_win_max, 0, sizeof(curr_win_max));
+ memset(&best_win_min, 0, sizeof(best_win_min));
+ memset(&best_win_max, 0, sizeof(best_win_max));
+ memset(&loop_win_min, 0, sizeof(loop_win_min));
+ memset(&loop_win_max, 0, sizeof(loop_win_max));
+
+ rdcc = 0;
+
+ /*
+ * Program RDCC register
+ * Read sample cycle auto-update enable
+ */
+ mtsdram(SDRAM_RDCC, SDRAM_RDCC_RDSS_T1 | SDRAM_RDCC_RSAE_ENABLE);
+
+#ifdef DEBUG
+ mfsdram(SDRAM_RDCC, temp);
+ debug("<%s>SDRAM_RDCC=0x%x\n", __func__, temp);
+ mfsdram(SDRAM_RTSR, temp);
+ debug("<%s>SDRAM_RTSR=0x%x\n", __func__, temp);
+ mfsdram(SDRAM_FCSR, temp);
+ debug("<%s>SDRAM_FCSR=0x%x\n", __func__, temp);
+#endif
+
+ /*
+ * Program RQDC register
+ * Internal DQS delay mechanism enable
+ */
+ mtsdram(SDRAM_RQDC,
+ SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x00));
+
+#ifdef DEBUG
+ mfsdram(SDRAM_RQDC, temp);
+ debug("<%s>SDRAM_RQDC=0x%x\n", __func__, temp);
+#endif
+
+ /*
+ * Program RFDC register
+ * Set Feedback Fractional Oversample
+ * Auto-detect read sample cycle enable
+ */
+ mtsdram(SDRAM_RFDC, SDRAM_RFDC_ARSE_ENABLE |
+ SDRAM_RFDC_RFOS_ENCODE(0) | SDRAM_RFDC_RFFD_ENCODE(0));
+
+#ifdef DEBUG
+ mfsdram(SDRAM_RFDC, temp);
+ debug("<%s>SDRAM_RFDC=0x%x\n", __func__, temp);
+#endif
+
+ putc(' ');
+ for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) {
+
+ mfsdram(SDRAM_RQDC, rqdc_reg);
+ rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
+ mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd));
+
+ putc('\b');
+ putc(slash[loopi++ % 8]);
+
+ curr_win_min.rffd = 0;
+ curr_win_max.rffd = 0;
+ in_window = 0;
+
+ for (rffd = 0, pass = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) {
+ mfsdram(SDRAM_RFDC, rfdc_reg);
+ rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
+ mtsdram(SDRAM_RFDC,
+ rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));
+
+ for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
+ mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
+
+ /* Banks enabled */
+ if (bxcf & SDRAM_BXCF_M_BE_MASK) {
+ /* Bank is enabled */
+ membase = get_membase(bxcr_num);
+ pass = short_mem_test(membase);
+ } /* if bank enabled */
+ } /* for bxcr_num */
+
+ /* If this value passed update RFFD windows */
+ if (pass && !in_window) { /* at the start of window */
+ in_window = 1;
+ curr_win_min.rffd = curr_win_max.rffd = rffd;
+ curr_win_min.rqfd = curr_win_max.rqfd = rqfd;
+ mfsdram(SDRAM_RDCC, rdcc); /*record this value*/
+ } else if (!pass && in_window) { /* at end of window */
+ in_window = 0;
+ } else if (pass && in_window) { /* within the window */
+ curr_win_max.rffd = rffd;
+ curr_win_max.rqfd = rqfd;
+ }
+ /* else if (!pass && !in_window)
+ skip - no pass, not currently in a window */
+
+ if (in_window) {
+ if ((curr_win_max.rffd - curr_win_min.rffd) >
+ (best_win_max.rffd - best_win_min.rffd)) {
+ best_win_min.rffd = curr_win_min.rffd;
+ best_win_max.rffd = curr_win_max.rffd;
+
+ best_win_min.rqfd = curr_win_min.rqfd;
+ best_win_max.rqfd = curr_win_max.rqfd;
+ cal->rdcc = rdcc;
+ }
+ passed = 1;
+ }
+ } /* RFDC.RFFD */
+
+ /*
+ * save-off the best window results of the RFDC.RFFD
+ * for this RQDC.RQFD setting
+ */
+ /*
+ * if (just ended RFDC.RFDC loop pass window) >
+ * (prior RFDC.RFFD loop pass window)
+ */
+ if ((best_win_max.rffd - best_win_min.rffd) >
+ (loop_win_max.rffd - loop_win_min.rffd)) {
+ loop_win_min.rffd = best_win_min.rffd;
+ loop_win_max.rffd = best_win_max.rffd;
+ loop_win_min.rqfd = rqfd;
+ loop_win_max.rqfd = rqfd;
+ debug("RQFD.min 0x%08x, RQFD.max 0x%08x, "
+ "RFFD.min 0x%08x, RFFD.max 0x%08x\n",
+ loop_win_min.rqfd, loop_win_max.rqfd,
+ loop_win_min.rffd, loop_win_max.rffd);
+ }
+ } /* RQDC.RQFD */
+
+ putc('\b');
+
+ debug("\n");
+
+ if ((loop_win_min.rffd == 0) && (loop_win_max.rffd == 0) &&
+ (best_win_min.rffd == 0) && (best_win_max.rffd == 0) &&
+ (best_win_min.rqfd == 0) && (best_win_max.rqfd == 0)) {
+ passed = 0;
+ }
+
+ /*
+ * Need to program RQDC before RFDC.
+ */
+ debug("<%s> RQFD Min: 0x%x\n", __func__, loop_win_min.rqfd);
+ debug("<%s> RQFD Max: 0x%x\n", __func__, loop_win_max.rqfd);
+ rqfd_average = loop_win_max.rqfd;
+
+ if (rqfd_average < 0)
+ rqfd_average = 0;
+
+ if (rqfd_average > SDRAM_RQDC_RQFD_MAX)
+ rqfd_average = SDRAM_RQDC_RQFD_MAX;
+
+ debug("<%s> RFFD average: 0x%08x\n", __func__, rqfd_average);
+ mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
+ SDRAM_RQDC_RQFD_ENCODE(rqfd_average));
+
+ debug("<%s> RFFD Min: 0x%08x\n", __func__, loop_win_min.rffd);
+ debug("<%s> RFFD Max: 0x%08x\n", __func__, loop_win_max.rffd);
+ rffd_average = ((loop_win_min.rffd + loop_win_max.rffd) / 2);
+
+ if (rffd_average < 0)
+ rffd_average = 0;
+
+ if (rffd_average > SDRAM_RFDC_RFFD_MAX)
+ rffd_average = SDRAM_RFDC_RFFD_MAX;
+
+ debug("<%s> RFFD average: 0x%08x\n", __func__, rffd_average);
+ mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average));
+
+ /* if something passed, then return the size of the largest window */
+ if (passed != 0) {
+ passed = loop_win_max.rffd - loop_win_min.rffd;
+ cal->rqfd = rqfd_average;
+ cal->rffd = rffd_average;
+ cal->rffd_min = loop_win_min.rffd;
+ cal->rffd_max = loop_win_max.rffd;
+ }
+
+ return (u32)passed;
+}
+
+#else /* !defined(CONFIG_PPC4xx_DDR_METHOD_A) */
+
+/*-----------------------------------------------------------------------------+
+| program_DQS_calibration_methodB.
++-----------------------------------------------------------------------------*/
+static u32 program_DQS_calibration_methodB(struct ddrautocal *ddrcal)
+{
+ u32 pass_result = 0;
+
+#ifdef DEBUG
+ ulong temp;
+#endif
+
+ /*
+ * Program RDCC register
+ * Read sample cycle auto-update enable
+ */
+ mtsdram(SDRAM_RDCC, SDRAM_RDCC_RDSS_T2 | SDRAM_RDCC_RSAE_ENABLE);
+
+#ifdef DEBUG
+ mfsdram(SDRAM_RDCC, temp);
+ debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp);
+#endif
+
+ /*
+ * Program RQDC register
+ * Internal DQS delay mechanism enable
+ */
+ mtsdram(SDRAM_RQDC,
+#if defined(CONFIG_DDR_RQDC_START_VAL)
+ SDRAM_RQDC_RQDE_ENABLE |
+ SDRAM_RQDC_RQFD_ENCODE(CONFIG_DDR_RQDC_START_VAL));
+#else
+ SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x38));
+#endif
+
+#ifdef DEBUG
+ mfsdram(SDRAM_RQDC, temp);
+ debug("<%s>SDRAM_RQDC=0x%08x\n", __func__, temp);
+#endif
+
+ /*
+ * Program RFDC register
+ * Set Feedback Fractional Oversample
+ * Auto-detect read sample cycle enable
+ */
+ mtsdram(SDRAM_RFDC, SDRAM_RFDC_ARSE_ENABLE |
+ SDRAM_RFDC_RFOS_ENCODE(0) |
+ SDRAM_RFDC_RFFD_ENCODE(0));
+
+#ifdef DEBUG
+ mfsdram(SDRAM_RFDC, temp);
+ debug("<%s>SDRAM_RFDC=0x%08x\n", __func__, temp);
+#endif
+
+ pass_result = DQS_calibration_methodB(ddrcal);
+
+ return pass_result;
+}
+
+/*
+ * DQS_calibration_methodB()
+ *
+ * Autocalibration Method B
+ *
+ * ARRAY [Entire DQS Range] DQS_Valid_Window ; initialized to all zeros
+ * ARRAY [Entire Feedback Range] FDBK_Valid_Window; initialized to all zeros
+ * MEMWRITE(addr, expected_data);
+ * Initialialize the DQS delay to 80 degrees (MCIF0_RRQDC[RQFD]=0x38).
+ *
+ * for (j = 0; j < Entire Feedback Range; j++) {
+ * MEMREAD(addr, actual_data);
+ * if (actual_data == expected_data) {
+ * FDBK_Valid_Window[j] = 1;
+ * }
+ * }
+ *
+ * Set MCIF0_RFDC[RFFD] to the middle of the FDBK_Valid_Window.
+ *
+ * for (i = 0; i < Entire DQS Range; i++) {
+ * MEMREAD(addr, actual_data);
+ * if (actual_data == expected_data) {
+ * DQS_Valid_Window[i] = 1;
+ * }
+ * }
+ *
+ * Set MCIF0_RRQDC[RQFD] to the middle of the DQS_Valid_Window.
+ */
+/*-----------------------------------------------------------------------------+
+| DQS_calibration_methodB.
++-----------------------------------------------------------------------------*/
+static u32 DQS_calibration_methodB(struct ddrautocal *cal)
+{
+ ulong rfdc_reg;
+ ulong rffd;
+
+ ulong rqdc_reg;
+ ulong rqfd;
+
+ ulong rdcc;
+
+ u32 *membase;
+ ulong bxcf;
+ int rqfd_average;
+ int bxcr_num;
+ int rffd_average;
+ int pass;
+ uint passed = 0;
+
+ int in_window;
+ u32 curr_win_min, curr_win_max;
+ u32 best_win_min, best_win_max;
+ u32 size = 0;
+
+ /*------------------------------------------------------------------
+ | Test to determine the best read clock delay tuning bits.
+ |
+ | Before the DDR controller can be used, the read clock delay needs to
+ | be set. This is SDRAM_RQDC[RQFD] and SDRAM_RFDC[RFFD].
+ | This value cannot be hardcoded into the program because it changes
+ | depending on the board's setup and environment.
+ | To do this, all delay values are tested to see if they
+ | work or not. By doing this, you get groups of fails with groups of
+ | passing values. The idea is to find the start and end of a passing
+ | window and take the center of it to use as the read clock delay.
+ |
+ | A failure has to be seen first so that when we hit a pass, we know
+ | that it is truely the start of the window. If we get passing values
+ | to start off with, we don't know if we are at the start of the window
+ |
+ | The code assumes that a failure will always be found.
+ | If a failure is not found, there is no easy way to get the middle
+ | of the passing window. I guess we can pretty much pick any value
+ | but some values will be better than others. Since the lowest speed
+ | we can clock the DDR interface at is 200 MHz (2x 100 MHz PLB speed),
+ | from experimentation it is safe to say you will always have a failure
+ +-----------------------------------------------------------------*/
+
+ debug("\n\n");
+
+ in_window = 0;
+ rdcc = 0;
+
+ curr_win_min = curr_win_max = 0;
+ best_win_min = best_win_max = 0;
+ for (rffd = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) {
+ mfsdram(SDRAM_RFDC, rfdc_reg);
+ rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
+ mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));
+
+ pass = 1;
+ for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
+ mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
+
+ /* Banks enabled */
+ if (bxcf & SDRAM_BXCF_M_BE_MASK) {
+ /* Bank is enabled */
+ membase = get_membase(bxcr_num);
+ pass &= short_mem_test(membase);
+ } /* if bank enabled */
+ } /* for bxcf_num */
+
+ /* If this value passed */
+ if (pass && !in_window) { /* start of passing window */
+ in_window = 1;
+ curr_win_min = curr_win_max = rffd;
+ mfsdram(SDRAM_RDCC, rdcc); /* record this value */
+ } else if (!pass && in_window) { /* end passing window */
+ in_window = 0;
+ } else if (pass && in_window) { /* within the passing window */
+ curr_win_max = rffd;
+ }
+
+ if (in_window) {
+ if ((curr_win_max - curr_win_min) >
+ (best_win_max - best_win_min)) {
+ best_win_min = curr_win_min;
+ best_win_max = curr_win_max;
+ cal->rdcc = rdcc;
+ }
+ passed = 1;
+ }
+ } /* for rffd */
+
+ if ((best_win_min == 0) && (best_win_max == 0))
+ passed = 0;
+ else
+ size = best_win_max - best_win_min;
+
+ debug("RFFD Min: 0x%x\n", best_win_min);
+ debug("RFFD Max: 0x%x\n", best_win_max);
+ rffd_average = ((best_win_min + best_win_max) / 2);
+
+ cal->rffd_min = best_win_min;
+ cal->rffd_max = best_win_max;
+
+ if (rffd_average < 0)
+ rffd_average = 0;
+
+ if (rffd_average > SDRAM_RFDC_RFFD_MAX)
+ rffd_average = SDRAM_RFDC_RFFD_MAX;
+
+ mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average));
+
+ rffd = rffd_average;
+ in_window = 0;
+
+ curr_win_min = curr_win_max = 0;
+ best_win_min = best_win_max = 0;
+ for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) {
+ mfsdram(SDRAM_RQDC, rqdc_reg);
+ rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
+ mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd));
+
+ pass = 1;
+ for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
+
+ mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
+
+ /* Banks enabled */
+ if (bxcf & SDRAM_BXCF_M_BE_MASK) {
+ /* Bank is enabled */
+ membase = get_membase(bxcr_num);
+ pass &= short_mem_test(membase);
+ } /* if bank enabled */
+ } /* for bxcf_num */
+
+ /* If this value passed */
+ if (pass && !in_window) {
+ in_window = 1;
+ curr_win_min = curr_win_max = rqfd;
+ } else if (!pass && in_window) {
+ in_window = 0;
+ } else if (pass && in_window) {
+ curr_win_max = rqfd;
+ }
+
+ if (in_window) {
+ if ((curr_win_max - curr_win_min) >
+ (best_win_max - best_win_min)) {
+ best_win_min = curr_win_min;
+ best_win_max = curr_win_max;
+ }
+ passed = 1;
+ }
+ } /* for rqfd */
+
+ if ((best_win_min == 0) && (best_win_max == 0))
+ passed = 0;
+
+ debug("RQFD Min: 0x%x\n", best_win_min);
+ debug("RQFD Max: 0x%x\n", best_win_max);
+ rqfd_average = ((best_win_min + best_win_max) / 2);
+
+ if (rqfd_average < 0)
+ rqfd_average = 0;
+
+ if (rqfd_average > SDRAM_RQDC_RQFD_MAX)
+ rqfd_average = SDRAM_RQDC_RQFD_MAX;
+
+ mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
+ SDRAM_RQDC_RQFD_ENCODE(rqfd_average));
+
+ mfsdram(SDRAM_RQDC, rqdc_reg);
+ mfsdram(SDRAM_RFDC, rfdc_reg);
+
+ /*
+ * Need to program RQDC before RFDC. The value is read above.
+ * That is the reason why auto cal not work.
+ * See, comments below.
+ */
+ mtsdram(SDRAM_RQDC, rqdc_reg);
+ mtsdram(SDRAM_RFDC, rfdc_reg);
+
+ debug("RQDC: 0x%08X\n", rqdc_reg);
+ debug("RFDC: 0x%08X\n", rfdc_reg);
+
+ /* if something passed, then return the size of the largest window */
+ if (passed != 0) {
+ passed = size;
+ cal->rqfd = rqfd_average;
+ cal->rffd = rffd_average;
+ }
+
+ return (uint)passed;
+}
+#endif /* defined(CONFIG_PPC4xx_DDR_METHOD_A) */
+
+/*
+ * Default table for DDR auto-calibration of all
+ * possible WRDTR and CLKTR values.
+ * Table format is:
+ * {SDRAM_WRDTR.[WDTR], SDRAM_CLKTR.[CKTR]}
+ *
+ * Table is terminated with {-1, -1} value pair.
+ *
+ * Board vendors can specify their own board specific subset of
+ * known working {SDRAM_WRDTR.[WDTR], SDRAM_CLKTR.[CKTR]} value
+ * pairs via a board defined ddr_scan_option() function.
+ */
+struct sdram_timing full_scan_options[] = {
+ {0, 0}, {0, 1}, {0, 2}, {0, 3},
+ {1, 0}, {1, 1}, {1, 2}, {1, 3},
+ {2, 0}, {2, 1}, {2, 2}, {2, 3},
+ {3, 0}, {3, 1}, {3, 2}, {3, 3},
+ {4, 0}, {4, 1}, {4, 2}, {4, 3},
+ {5, 0}, {5, 1}, {5, 2}, {5, 3},
+ {6, 0}, {6, 1}, {6, 2}, {6, 3},
+ {-1, -1}
+};
+
+/*---------------------------------------------------------------------------+
+| DQS_calibration.
++----------------------------------------------------------------------------*/
+u32 DQS_autocalibration(void)
+{
+ u32 wdtr;
+ u32 clkp;
+ u32 result = 0;
+ u32 best_result = 0;
+ u32 best_rdcc;
+ struct ddrautocal ddrcal;
+ struct autocal_clks tcal;
+ ulong rfdc_reg;
+ ulong rqdc_reg;
+ u32 val;
+ int verbose_lvl = 0;
+ char *str;
+ char slash[] = "\\|/-\\|/-";
+ int loopi = 0;
+ struct sdram_timing *scan_list;
+
+#if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION)
+ int i;
+ char tmp[64]; /* long enough for environment variables */
+#endif
+
+ memset(&tcal, 0, sizeof(tcal));
+
+ ddr_scan_option((ulong)full_scan_options);
+
+ scan_list =
+ (struct sdram_timing *)ddr_scan_option((ulong)full_scan_options);
+
+ mfsdram(SDRAM_MCOPT1, val);
+ if ((val & SDRAM_MCOPT1_MCHK_CHK_REP) == SDRAM_MCOPT1_MCHK_CHK_REP)
+ str = "ECC Auto calibration -";
+ else
+ str = "Auto calibration -";
+
+ puts(str);
+
+#if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION)
+ i = getenv_r("autocalib", tmp, sizeof(tmp));
+ if (i < 0)
+ strcpy(tmp, CONFIG_AUTOCALIB);
+
+ if (strcmp(tmp, "final") == 0) {
+ /* display the final autocalibration results only */
+ verbose_lvl = 1;
+ } else if (strcmp(tmp, "loop") == 0) {
+ /* display summary autocalibration info per iteration */
+ verbose_lvl = 2;
+ } else if (strcmp(tmp, "display") == 0) {
+ /* display full debug autocalibration window info. */
+ verbose_lvl = 3;
+ }
+#endif /* (DEBUG_PPC4xx_DDR_AUTOCALIBRATION) */
+
+ best_rdcc = (SDRAM_RDCC_RDSS_T4 >> 30);
+
+ while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) {
+ wdtr = scan_list->wrdtr;
+ clkp = scan_list->clktr;
+
+ mfsdram(SDRAM_WRDTR, val);
+ val &= ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK);
+ mtsdram(SDRAM_WRDTR, (val |
+ ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC | (wdtr << 25))));
+
+ mtsdram(SDRAM_CLKTR, clkp << 30);
+
+ putc('\b');
+ putc(slash[loopi++ % 8]);
+
+#ifdef DEBUG
+ debug("\n");
+ debug("*** --------------\n");
+ mfsdram(SDRAM_WRDTR, val);
+ debug("*** SDRAM_WRDTR set to 0x%08x\n", val);
+ mfsdram(SDRAM_CLKTR, val);
+ debug("*** SDRAM_CLKTR set to 0x%08x\n", val);
+#endif
+
+ debug("\n");
+ if (verbose_lvl > 2) {
+ printf("*** SDRAM_WRDTR (wdtr) set to %d\n", wdtr);
+ printf("*** SDRAM_CLKTR (clkp) set to %d\n", clkp);
+ }
+
+ memset(&ddrcal, 0, sizeof(ddrcal));
+
+ /*
+ * DQS calibration.
+ */
+ /*
+ * program_DQS_calibration_method[A|B]() returns 0 if no
+ * passing RFDC.[RFFD] window is found or returns the size
+ * of the best passing window; in the case of a found passing
+ * window, the ddrcal will contain the values of the best
+ * window RQDC.[RQFD] and RFDC.[RFFD].
+ */
+
+ /*
+ * Call PPC4xx SDRAM DDR autocalibration methodA or methodB.
+ * Default is methodB.
+ * Defined the autocalibration method in the board specific
+ * header file.
+ * Please see include/configs/kilauea.h for an example for
+ * a board specific implementation.
+ */
+#if defined(CONFIG_PPC4xx_DDR_METHOD_A)
+ result = program_DQS_calibration_methodA(&ddrcal);
+#else
+ result = program_DQS_calibration_methodB(&ddrcal);
+#endif
+
+ sync();
+
+ /*
+ * Clear potential errors resulting from auto-calibration.
+ * If not done, then we could get an interrupt later on when
+ * exceptions are enabled.
+ */
+ set_mcsr(get_mcsr());
+
+ val = ddrcal.rdcc; /* RDCC from the best passing window */
+
+ udelay(100);
+
+ if (verbose_lvl > 1) {
+ char *tstr;
+ switch ((val >> 30)) {
+ case 0:
+ if (result != 0)
+ tstr = "T1";
+ else
+ tstr = "N/A";
+ break;
+ case 1:
+ tstr = "T2";
+ break;
+ case 2:
+ tstr = "T3";
+ break;
+ case 3:
+ tstr = "T4";
+ break;
+ default:
+ tstr = "unknown";
+ break;
+ }
+ printf("** WRDTR(%d) CLKTR(%d), Wind (%d), best (%d), "
+ "max-min(0x%04x)(0x%04x), RDCC: %s\n",
+ wdtr, clkp, result, best_result,
+ ddrcal.rffd_min, ddrcal.rffd_max, tstr);
+ }
+
+ /*
+ * The DQS calibration "result" is either "0"
+ * if no passing window was found, or is the
+ * size of the RFFD passing window.
+ */
+ if (result != 0) {
+ tcal.autocal.flags = 1;
+ debug("*** (%d)(%d) result passed window size: 0x%08x, "
+ "rqfd = 0x%08x, rffd = 0x%08x, rdcc = 0x%08x\n",
+ wdtr, clkp, result, ddrcal.rqfd,
+ ddrcal.rffd, ddrcal.rdcc);
+ /*
+ * Save the SDRAM_WRDTR and SDRAM_CLKTR
+ * settings for the largest returned
+ * RFFD passing window size.
+ */
+ if (result > best_result) {
+ /*
+ * want the lowest Read Sample Cycle Select
+ */
+ val = (val & SDRAM_RDCC_RDSS_MASK) >> 30;
+ debug("*** (%d) (%d) current_rdcc, best_rdcc\n",
+ val, best_rdcc);
+ if (val <= best_rdcc) {
+ best_rdcc = val;
+ tcal.clocks.wrdtr = wdtr;
+ tcal.clocks.clktr = clkp;
+ tcal.clocks.rdcc = (val << 30);
+ tcal.autocal.rqfd = ddrcal.rqfd;
+ tcal.autocal.rffd = ddrcal.rffd;
+ best_result = result;
+
+ if (verbose_lvl > 2) {
+ printf("** (%d)(%d) "
+ "best result: 0x%04x\n",
+ wdtr, clkp,
+ best_result);
+ printf("** (%d)(%d) "
+ "best WRDTR: 0x%04x\n",
+ wdtr, clkp,
+ tcal.clocks.wrdtr);
+ printf("** (%d)(%d) "
+ "best CLKTR: 0x%04x\n",
+ wdtr, clkp,
+ tcal.clocks.clktr);
+ printf("** (%d)(%d) "
+ "best RQDC: 0x%04x\n",
+ wdtr, clkp,
+ tcal.autocal.rqfd);
+ printf("** (%d)(%d) "
+ "best RFDC: 0x%04x\n",
+ wdtr, clkp,
+ tcal.autocal.rffd);
+ printf("** (%d)(%d) "
+ "best RDCC: 0x%08x\n",
+ wdtr, clkp,
+ (u32)tcal.clocks.rdcc);
+ mfsdram(SDRAM_RTSR, val);
+ printf("** (%d)(%d) best "
+ "loop RTSR: 0x%08x\n",
+ wdtr, clkp, val);
+ mfsdram(SDRAM_FCSR, val);
+ printf("** (%d)(%d) best "
+ "loop FCSR: 0x%08x\n",
+ wdtr, clkp, val);
+ }
+ } /* if (val <= best_rdcc) */
+ } /* if (result >= best_result) */
+ } /* if (result != 0) */
+ scan_list++;
+ } /* while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) */
+
+ if (tcal.autocal.flags == 1) {
+ if (verbose_lvl > 0) {
+ printf("*** --------------\n");
+ printf("*** best_result window size: %d\n",
+ best_result);
+ printf("*** best_result WRDTR: 0x%04x\n",
+ tcal.clocks.wrdtr);
+ printf("*** best_result CLKTR: 0x%04x\n",
+ tcal.clocks.clktr);
+ printf("*** best_result RQFD: 0x%04x\n",
+ tcal.autocal.rqfd);
+ printf("*** best_result RFFD: 0x%04x\n",
+ tcal.autocal.rffd);
+ printf("*** best_result RDCC: 0x%04x\n",
+ tcal.clocks.rdcc);
+ printf("*** --------------\n");
+ printf("\n");
+ }
+
+ /*
+ * if got best passing result window, then lock in the
+ * best CLKTR, WRDTR, RQFD, and RFFD values
+ */
+ mfsdram(SDRAM_WRDTR, val);
+ mtsdram(SDRAM_WRDTR, (val &
+ ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK)) |
+ ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC |
+ (tcal.clocks.wrdtr << 25)));
+
+ mtsdram(SDRAM_CLKTR, tcal.clocks.clktr << 30);
+
+ mfsdram(SDRAM_RQDC, rqdc_reg);
+ rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
+ mtsdram(SDRAM_RQDC, rqdc_reg |
+ SDRAM_RQDC_RQFD_ENCODE(tcal.autocal.rqfd));
+
+ mfsdram(SDRAM_RQDC, rqdc_reg);
+ debug("*** best_result: read value SDRAM_RQDC 0x%08x\n",
+ rqdc_reg);
+
+ mfsdram(SDRAM_RFDC, rfdc_reg);
+ rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
+ mtsdram(SDRAM_RFDC, rfdc_reg |
+ SDRAM_RFDC_RFFD_ENCODE(tcal.autocal.rffd));
+
+ mfsdram(SDRAM_RFDC, rfdc_reg);
+ debug("*** best_result: read value SDRAM_RFDC 0x%08x\n",
+ rfdc_reg);
+ mfsdram(SDRAM_RDCC, val);
+ debug("*** SDRAM_RDCC 0x%08x\n", val);
+ } else {
+ /*
+ * no valid windows were found
+ */
+ printf("DQS memory calibration window can not be determined, "
+ "terminating u-boot.\n");
+ ppc4xx_ibm_ddr2_register_dump();
+ spd_ddr_init_hang();
+ }
+
+ blank_string(strlen(str));
+
+ return 0;
+}
+#else /* defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) */
+u32 DQS_autocalibration(void)
+{
+ return 0;
+}
+#endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */
+#endif /* defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) */
--
1.5.5
2
1

[U-Boot] [PATCH] ppc44x: Unification of virtex5 pp440 boards v4
by Ricardo Ribalda Delgado 05 Sep '08
by Ricardo Ribalda Delgado 05 Sep '08
05 Sep '08
This patch provides an unificated way of handling xilinx v5 ppc440 boards.
It unificates 3 different things:
1) Source code
A new board called ppc440-generic has been created. This board includes
a generic tlb initialization (Maps the whole memory into virtual) and
defines board_pre_init, checkboard, initdram and get_sys_info weakly,
so, they can be replaced by specific functions.
If a new board needs to redefine any of the previous functions
(specific initialization) it can create a new directory with the
specific initializations needed. (see the example ml507 board).
2) Configuration file
Common configurations are located under configs/xilinx-ppc440.h, this
header file interpretes the xparameters file generated by EDK and
configurates u-boot in correspondence. Example: if there is a Temac,
allows CMD_CONFIG_NET
Specific configuration are located under specific configuration file.
(see the example ml507 board)
3) Makefile
Some work has been done in order to not duplicate work in the Main
Makefile. Please see the attached code.
In order to support new boards they can be implemented in the next way:
a) Simple Generic Board (90% of the time)
Using EDK generates a new xparameters.h file, replace
ppc440-generic/xparameters.h and run make xilinx-ppc440-generic_config
&& make
b) Simple Boards with special u-boot parameters (9 % of the time)
Create a new file under configs for it (use ml507.h as example) and
change your paramaters. Create a new Makefile paragraph and compile
c) Complex boards (1% of the time)
Create a new folder for the board, like the ml507
Finally, it adds support for the Avnet FX30T Evaluation board, following
the new generic structure:
Cheap board by Avnet for evaluating the Virtex5 FX technology.
This patch adds support for:
- UartLite
- 16MB Flash
- 64MB RAM
Prior using U-boot in this board, read carefully the ERRATA by Avnet
to solve some memory initialization issues.
v2 diff:
- Code Styling (Michal Simek)
- Remove unnecesary xparameters lines (Michal Simek)
- Avnet board documentation in patch
v3 diff:
- Description changed (wdenx)
- Copyright issues
- RFC->Patch Propossal
v4 diff:
- MAKEALL gives same output as other boards (stefan)
- Simplify board configuration (wdenx)
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda(a)uam.es>
---
CREDITS | 3 +-
MAINTAINERS | 2 +
MAKEALL | 4 +
Makefile | 45 +++++--
board/avnet/v5fx30teval/.gitignore | 1 +
board/avnet/v5fx30teval/Makefile | 27 ++++
board/avnet/v5fx30teval/v5fx30teval.c | 28 ++++
board/avnet/v5fx30teval/xparameters.h | 33 +++++
board/xilinx/ml507/.gitignore | 1 +
board/xilinx/ml507/Makefile | 41 +-----
board/xilinx/ml507/config.mk | 27 ----
board/xilinx/ml507/init.S | 53 -------
board/xilinx/ml507/ml507.c | 21 +---
board/xilinx/ml507/u-boot-ram.lds | 134 ------------------
board/xilinx/ml507/u-boot-rom.lds | 144 --------------------
board/xilinx/ml507/xparameters.h | 17 +--
board/xilinx/ppc440-generic/.gitignore | 1 +
board/xilinx/ppc440-generic/Makefile | 62 +++++++++
board/xilinx/ppc440-generic/init.S | 45 ++++++
board/xilinx/ppc440-generic/u-boot-ram.lds | 134 ++++++++++++++++++
board/xilinx/ppc440-generic/u-boot-rom.lds | 144 ++++++++++++++++++++
.../xilinx/ppc440-generic/xilinx_ppc440_generic.c | 52 +++++++
board/xilinx/ppc440-generic/xparameters.h | 34 +++++
include/configs/ml507.h | 91 ++-----------
include/configs/v5fx30teval.h | 49 +++++++
include/configs/xilinx-ppc440-generic.h | 49 +++++++
include/configs/xilinx-ppc440.h | 106 ++++++++++++++
27 files changed, 832 insertions(+), 516 deletions(-)
create mode 100644 board/avnet/v5fx30teval/.gitignore
create mode 100644 board/avnet/v5fx30teval/Makefile
create mode 100644 board/avnet/v5fx30teval/v5fx30teval.c
create mode 100644 board/avnet/v5fx30teval/xparameters.h
create mode 100644 board/xilinx/ml507/.gitignore
delete mode 100644 board/xilinx/ml507/config.mk
delete mode 100644 board/xilinx/ml507/init.S
delete mode 100644 board/xilinx/ml507/u-boot-ram.lds
delete mode 100644 board/xilinx/ml507/u-boot-rom.lds
create mode 100644 board/xilinx/ppc440-generic/.gitignore
create mode 100644 board/xilinx/ppc440-generic/Makefile
create mode 100644 board/xilinx/ppc440-generic/init.S
create mode 100644 board/xilinx/ppc440-generic/u-boot-ram.lds
create mode 100644 board/xilinx/ppc440-generic/u-boot-rom.lds
create mode 100644 board/xilinx/ppc440-generic/xilinx_ppc440_generic.c
create mode 100644 board/xilinx/ppc440-generic/xparameters.h
create mode 100644 include/configs/v5fx30teval.h
create mode 100644 include/configs/xilinx-ppc440-generic.h
create mode 100644 include/configs/xilinx-ppc440.h
diff --git a/CREDITS b/CREDITS
index 4fe4e63..3767322 100644
--- a/CREDITS
+++ b/CREDITS
@@ -405,7 +405,8 @@ D: Atmel AT91CAP9ADK support
N: Ricardo Ribalda Delgado
E: ricardo.ribalda(a)uam.es
-D: PPC440x5 (Virtex5), ML507 Board, eeprom_simul, adt7460
+D: PPC440x5 (Virtex5), ML507 Board, eeprom_simul, adt7460, v5fx30teval
+D: Virtex ppc440 generic architecture
W: http://www.ii.uam.es/~rribalda
N: Stefan Roese
diff --git a/MAINTAINERS b/MAINTAINERS
index 31493c2..47220e2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -318,6 +318,8 @@ Daniel Poirot <dan.poirot(a)windriver.com>
Ricardo Ribalda <ricardo.ribalda(a)uam.es>
ml507 PPC440x5
+ v5fx30teval PPC440x5
+ xilinx-pp440-generic PPC440x5
Stefan Roese <sr(a)denx.de>
diff --git a/MAKEALL b/MAKEALL
index edfee90..6aa1723 100755
--- a/MAKEALL
+++ b/MAKEALL
@@ -231,12 +231,16 @@ LIST_4xx=" \
sequoia_nand \
taihu \
taishan \
+ v5fx30teval \
+ v5fx30teval_flash \
VOH405 \
VOM405 \
W7OLMC \
W7OLMG \
walnut \
WUH405 \
+ xilinx-ppc440-generic \
+ xilinx-ppc440-generic_flash \
XPEDITE1K \
yellowstone \
yosemite \
diff --git a/Makefile b/Makefile
index 8c90dab..54b077c 100644
--- a/Makefile
+++ b/Makefile
@@ -1351,16 +1351,17 @@ ML2_config: unconfig
ml300_config: unconfig
@$(MKCONFIG) $(@:_config=) ppc ppc4xx ml300 xilinx
-ml507_flash_config: unconfig
- @mkdir -p $(obj)include $(obj)board/xilinx/ml507
- @cp $(obj)board/xilinx/ml507/u-boot-rom.lds $(obj)board/xilinx/ml507/u-boot.lds
- @echo "TEXT_BASE = 0xFE360000" > $(obj)board/xilinx/ml507/config.tmp
- @$(MKCONFIG) $(@:_flash_config=) ppc ppc4xx ml507 xilinx
-
-ml507_config: unconfig
- @mkdir -p $(obj)include $(obj)board/xilinx/ml507
- @cp $(obj)board/xilinx/ml507/u-boot-ram.lds $(obj)board/xilinx/ml507/u-boot.lds
- @$(MKCONFIG) $(@:_config=) ppc ppc4xx ml507 xilinx
+ml507_flash_config: unconfig
+ @mkdir -p $(obj)include $(obj)board/xilinx/ml507
+ @echo "LDSCRIPT := $(obj)board/xilinx/ppc440-generic/u-boot-rom.lds" > $(obj)board/xilinx/ml507/config.mk
+ @echo "TEXT_BASE := 0xFE360000" >> $(obj)board/xilinx/ml507/config.mk
+ @$(MKCONFIG) ml507 ppc ppc4xx ml507 xilinx
+
+ml507_config: unconfig
+ @mkdir -p $(obj)include $(obj)board/xilinx/ml507
+ @echo "LDSCRIPT := $(obj)board/xilinx/ppc440-generic/u-boot-ram.lds" > $(obj)board/xilinx/ml507/config.mk
+ @echo "TEXT_BASE := 0x04000000" >> $(obj)board/xilinx/ml507/config.mk
+ @$(MKCONFIG) ml507 ppc ppc4xx ml507 xilinx
ocotea_config: unconfig
@$(MKCONFIG) $(@:_config=) ppc ppc4xx ocotea amcc
@@ -1456,6 +1457,18 @@ taihu_config: unconfig
taishan_config: unconfig
@$(MKCONFIG) $(@:_config=) ppc ppc4xx taishan amcc
+v5fx30teval_config: unconfig
+ @mkdir -p $(obj)include $(obj)board/avnet/v5fx30teval
+ @echo "LDSCRIPT := $(obj)board/xilinx/ppc440-generic/u-boot-ram.lds" > $(obj)board/avnet/v5fx30teval/config.mk
+ @echo "TEXT_BASE := 0x03000000" >> $(obj)board/avnet/v5fx30teval/config.mk
+ @$(MKCONFIG) v5fx30teval ppc ppc4xx v5fx30teval avnet
+
+v5fx30teval_flash_config: unconfig
+ @mkdir -p $(obj)include $(obj)board/avnet/v5fx30teval
+ @echo "LDSCRIPT := $(obj)board/xilinx/ppc440-generic/u-boot-rom.lds" > $(obj)board/avnet/v5fx30teval/config.mk
+ @echo "TEXT_BASE := 0xFF1C0000" >> $(obj)board/avnet/v5fx30teval/config.mk
+ @$(MKCONFIG) v5fx30teval ppc ppc4xx v5fx30teval avnet
+
VOH405_config: unconfig
@$(MKCONFIG) $(@:_config=) ppc ppc4xx voh405 esd
@@ -1474,6 +1487,18 @@ sycamore_config: unconfig
WUH405_config: unconfig
@$(MKCONFIG) $(@:_config=) ppc ppc4xx wuh405 esd
+xilinx-ppc440-generic_flash_config: unconfig
+ @mkdir -p $(obj)include $(obj)board/xilinx/ppc440-generic/
+ @echo "LDSCRIPT := $(obj)board/xilinx/ppc440-generic/u-boot-rom.lds" > $(obj)board/xilinx/ppc440-generic/config.mk
+ @echo "TEXT_BASE := 0xFE360000" >> $(obj)board/xilinx/ppc440-generic/config.mk
+ @$(MKCONFIG) xilinx-ppc440-generic ppc ppc4xx ppc440-generic xilinx
+
+xilinx-ppc440-generic_config: unconfig
+ @mkdir -p $(obj)include $(obj)board/xilinx/ppc440-generic/
+ @echo "LDSCRIPT := $(obj)board/xilinx/ppc440-generic/u-boot-ram.lds" > $(obj)board/xilinx/ppc440-generic/config.mk
+ @echo "TEXT_BASE := 0x04000000" >> $(obj)board/xilinx/ppc440-generic/config.mk
+ @$(MKCONFIG) xilinx-ppc440-generic ppc ppc4xx ppc440-generic xilinx
+
XPEDITE1K_config: unconfig
@$(MKCONFIG) $(@:_config=) ppc ppc4xx xpedite1k
diff --git a/board/avnet/v5fx30teval/.gitignore b/board/avnet/v5fx30teval/.gitignore
new file mode 100644
index 0000000..6896ef6
--- /dev/null
+++ b/board/avnet/v5fx30teval/.gitignore
@@ -0,0 +1 @@
+/config.mk
diff --git a/board/avnet/v5fx30teval/Makefile b/board/avnet/v5fx30teval/Makefile
new file mode 100644
index 0000000..de23f29
--- /dev/null
+++ b/board/avnet/v5fx30teval/Makefile
@@ -0,0 +1,27 @@
+#
+# (C) Copyright 2008
+# Ricardo Ribalda,Universidad Autonoma de Madrid, ricardo.ribalda(a)uam.es
+# This work has been supported by: Qtechnology http://qtec.com/
+#
+# 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
+#
+
+COBJS += $(BOARD).o
+
+include $(SRCTREE)/board/xilinx/ppc440-generic/Makefile
diff --git a/board/avnet/v5fx30teval/v5fx30teval.c b/board/avnet/v5fx30teval/v5fx30teval.c
new file mode 100644
index 0000000..14a1d5d
--- /dev/null
+++ b/board/avnet/v5fx30teval/v5fx30teval.c
@@ -0,0 +1,28 @@
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda(a)uam.es
+ * This work has been supported by: QTechnology http://qtec.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 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <config.h>
+#include <common.h>
+#include <asm/processor.h>
+
+
+int checkboard(void)
+{
+ puts("Avnet Virtex 5 FX30 Evaluation Board\n");
+ return 0;
+}
diff --git a/board/avnet/v5fx30teval/xparameters.h b/board/avnet/v5fx30teval/xparameters.h
new file mode 100644
index 0000000..bb657fc
--- /dev/null
+++ b/board/avnet/v5fx30teval/xparameters.h
@@ -0,0 +1,33 @@
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda(a)uam.es
+ * This work has been supported by: QTechnology http://qtec.com/
+ * based on xparameters.h by Xilinx
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef XPARAMETER_H
+#define XPARAMETER_H
+
+#define XPAR_DDR2_SDRAM_MEM_BASEADDR 0x00000000
+#define XPAR_INTC_0_BASEADDR 0x81800000
+#define XPAR_UARTLITE_0_BASEADDR 0x84000000
+#define XPAR_FLASH_MEM0_BASEADDR 0xFF000000
+#define XPAR_PLB_CLOCK_FREQ_HZ 100000000
+#define XPAR_CORE_CLOCK_FREQ_HZ 400000000
+#define XPAR_INTC_MAX_NUM_INTR_INPUTS 13
+#define XPAR_UARTLITE_0_BAUDRATE 9600
+
+#endif
diff --git a/board/xilinx/ml507/.gitignore b/board/xilinx/ml507/.gitignore
new file mode 100644
index 0000000..6896ef6
--- /dev/null
+++ b/board/xilinx/ml507/.gitignore
@@ -0,0 +1 @@
+/config.mk
diff --git a/board/xilinx/ml507/Makefile b/board/xilinx/ml507/Makefile
index 7283704..de23f29 100644
--- a/board/xilinx/ml507/Makefile
+++ b/board/xilinx/ml507/Makefile
@@ -1,6 +1,7 @@
#
-# (C) Copyright 2000-2006
-# Wolfgang Denk, DENX Software Engineering, wd(a)denx.de.
+# (C) Copyright 2008
+# Ricardo Ribalda,Universidad Autonoma de Madrid, ricardo.ribalda(a)uam.es
+# This work has been supported by: Qtechnology http://qtec.com/
#
# See file CREDITS for list of people who contributed to this
# project.
@@ -21,38 +22,6 @@
# MA 02111-1307 USA
#
-include $(TOPDIR)/config.mk
-ifneq ($(OBJTREE),$(SRCTREE))
-endif
+COBJS += $(BOARD).o
-INCS :=
-CFLAGS += $(INCS)
-HOST_CFLAGS += $(INCS)
-
-LIB = $(obj)lib$(BOARD).a
-
-COBJS = $(BOARD).o
-
-SOBJS = init.o
-
-SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS))
-SOBJS := $(addprefix $(obj),$(SOBJS))
-
-$(LIB): $(OBJS) $(SOBJS)
- $(AR) $(ARFLAGS) $@ $^
-
-clean:
- rm -f $(SOBJS) $(OBJS)
-
-distclean: clean
- rm -f $(LIB) core *.bak .depend
-
-#########################################################################
-
-# defines $(obj).depend target
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
+include $(SRCTREE)/board/xilinx/ppc440-generic/Makefile
diff --git a/board/xilinx/ml507/config.mk b/board/xilinx/ml507/config.mk
deleted file mode 100644
index e827e8a..0000000
--- a/board/xilinx/ml507/config.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# (C) Copyright 2000
-# Wolfgang Denk, DENX Software Engineering, wd(a)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
-#
-sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp
-
-ifndef TEXT_BASE
-TEXT_BASE = 0x04000000
-endif
diff --git a/board/xilinx/ml507/init.S b/board/xilinx/ml507/init.S
deleted file mode 100644
index 3228a65..0000000
--- a/board/xilinx/ml507/init.S
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * (C) Copyright 2008
- * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda(a)uam.es
- * This work has been supported by: QTechnology http://qtec.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 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, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <ppc_asm.tmpl>
-#include <config.h>
-#include <asm-ppc/mmu.h>
-
-.section .bootpg,"ax"
-.globl tlbtab
-
-tlbtab:
-tlbtab_start
- /* SDRAM */
-tlbentry(XPAR_DDR2_SDRAM_MEM_BASEADDR, SZ_256M, CFG_SDRAM_BASE, 0,
- AC_R | AC_W | AC_X | SA_G | SA_I)
- /* UART */
-tlbentry(XPAR_UARTLITE_0_BASEADDR, SZ_64K, XPAR_UARTLITE_0_BASEADDR, 0,
- AC_R | AC_W | SA_G | SA_I)
- /* PIC */
-tlbentry(XPAR_INTC_0_BASEADDR, SZ_64K, XPAR_INTC_0_BASEADDR, 0,
- AC_R | AC_W | SA_G | SA_I)
-#ifdef XPAR_IIC_EEPROM_BASEADDR
- /* I2C */
-tlbentry(XPAR_IIC_EEPROM_BASEADDR, SZ_64K, XPAR_IIC_EEPROM_BASEADDR, 0,
- AC_R | AC_W | SA_G | SA_I)
-#endif
-#ifdef XPAR_LLTEMAC_0_BASEADDR
- /* Net */
-tlbentry(XPAR_LLTEMAC_0_BASEADDR, SZ_64K, XPAR_LLTEMAC_0_BASEADDR, 0,
- AC_R | AC_W | SA_G | SA_I)
-#endif
-#ifdef XPAR_FLASH_MEM0_BASEADDR
- /*Flash*/
-tlbentry(XPAR_FLASH_MEM0_BASEADDR, SZ_256M, XPAR_FLASH_MEM0_BASEADDR, 0,
- AC_R | AC_W | AC_X | SA_G | SA_I)
-#endif
-tlbtab_end
diff --git a/board/xilinx/ml507/ml507.c b/board/xilinx/ml507/ml507.c
index d499303..f9789cf 100644
--- a/board/xilinx/ml507/ml507.c
+++ b/board/xilinx/ml507/ml507.c
@@ -20,28 +20,9 @@
#include <common.h>
#include <asm/processor.h>
-int board_pre_init(void)
-{
- return 0;
-}
int checkboard(void)
{
- puts("ML507 Board\n");
+ puts("Xilinx ML507 Board\n");
return 0;
}
-
-phys_size_t initdram(int board_type)
-{
- return get_ram_size(XPAR_DDR2_SDRAM_MEM_BASEADDR,
- CFG_SDRAM_SIZE_MB * 1024 * 1024);
-}
-
-void get_sys_info(sys_info_t * sysInfo)
-{
- sysInfo->freqProcessor = XPAR_CORE_CLOCK_FREQ_HZ;
- sysInfo->freqPLB = XPAR_PLB_CLOCK_FREQ_HZ;
- sysInfo->freqPCI = 0;
-
- return;
-}
diff --git a/board/xilinx/ml507/u-boot-ram.lds b/board/xilinx/ml507/u-boot-ram.lds
deleted file mode 100644
index 2c98d27..0000000
--- a/board/xilinx/ml507/u-boot-ram.lds
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * (C) Copyright 2000-2004
- * Wolfgang Denk, DENX Software Engineering, wd(a)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
- */
-
-OUTPUT_ARCH(powerpc)
-ENTRY(_start_440)
-
-SECTIONS
-{
- /* Read-only sections, merged into text segment: */
- . = + SIZEOF_HEADERS;
- .interp : { *(.interp) }
- .hash : { *(.hash) }
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .rel.text : { *(.rel.text) }
- .rela.text : { *(.rela.text) }
- .rel.data : { *(.rel.data) }
- .rela.data : { *(.rela.data) }
- .rel.rodata : { *(.rel.rodata) }
- .rela.rodata : { *(.rela.rodata) }
- .rel.got : { *(.rel.got) }
- .rela.got : { *(.rela.got) }
- .rel.ctors : { *(.rel.ctors) }
- .rela.ctors : { *(.rela.ctors) }
- .rel.dtors : { *(.rel.dtors) }
- .rela.dtors : { *(.rela.dtors) }
- .rel.bss : { *(.rel.bss) }
- .rela.bss : { *(.rela.bss) }
- .rel.plt : { *(.rel.plt) }
- .rela.plt : { *(.rela.plt) }
- .init : { *(.init) }
- .plt : { *(.plt) }
- .text :
- {
- /* WARNING - the following is hand-optimized to fit within */
- /* the sector layout of our flash chips! XXX FIXME XXX */
-
-
- *(.text)
- *(.fixup)
- *(.got1)
- }
- _etext = .;
- PROVIDE (etext = .);
- .rodata :
- {
- *(.rodata)
- *(.rodata1)
- *(.rodata.str1.4)
- *(.eh_frame)
- }
- .fini : { *(.fini) } =0
- .ctors : { *(.ctors) }
- .dtors : { *(.dtors) }
-
- /* Read-write section, merged into data segment: */
- . = (. + 0x00FF) & 0xFFFFFF00;
- _erotext = .;
- PROVIDE (erotext = .);
- .reloc :
- {
- *(.got)
- _GOT2_TABLE_ = .;
- *(.got2)
- _FIXUP_TABLE_ = .;
- *(.fixup)
- }
- __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
- __fixup_entries = (. - _FIXUP_TABLE_)>>2;
-
- .data :
- {
- *(.data)
- *(.data1)
- *(.sdata)
- *(.sdata2)
- *(.dynamic)
- CONSTRUCTORS
- }
- _edata = .;
- PROVIDE (edata = .);
-
- . = .;
- __u_boot_cmd_start = .;
- .u_boot_cmd : { *(.u_boot_cmd) }
- __u_boot_cmd_end = .;
-
-
- . = .;
- __start___ex_table = .;
- __ex_table : { *(__ex_table) }
- __stop___ex_table = .;
-
- . = ALIGN(256);
- __init_begin = .;
- .text.init : { *(.text.init) }
- .data.init : { *(.data.init) }
- . = ALIGN(256);
- __init_end = .;
-
- __bss_start = .;
- .bss (NOLOAD) :
- {
- *(.sbss) *(.scommon)
- *(.dynbss)
- *(.bss)
- *(COMMON)
- }
-
- ppcenv_assert = ASSERT(. < 0xFFFFB000, ".bss section too big, overlaps .ppcenv section. Please update your confguration: CFG_MONITOR_BASE, CFG_MONITOR_LEN and TEXT_BASE may need to be modified.");
-
- _end = . ;
- PROVIDE (end = .);
-}
diff --git a/board/xilinx/ml507/u-boot-rom.lds b/board/xilinx/ml507/u-boot-rom.lds
deleted file mode 100644
index d5da018..0000000
--- a/board/xilinx/ml507/u-boot-rom.lds
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * (C) Copyright 2000-2004
- * Wolfgang Denk, DENX Software Engineering, wd(a)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
- */
-
-OUTPUT_ARCH(powerpc)
-ENTRY(_start_440)
-
-SECTIONS
-{
- .resetvec 0xFFFFFFFC :
- {
- *(.resetvec)
- } = 0xffff
-
- .bootpg 0xFFFFF000 :
- {
- cpu/ppc4xx/start.o (.bootpg)
- } = 0xffff
-
- /* Read-only sections, merged into text segment: */
- . = + SIZEOF_HEADERS;
- .interp : { *(.interp) }
- .hash : { *(.hash) }
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .rel.text : { *(.rel.text) }
- .rela.text : { *(.rela.text) }
- .rel.data : { *(.rel.data) }
- .rela.data : { *(.rela.data) }
- .rel.rodata : { *(.rel.rodata) }
- .rela.rodata : { *(.rela.rodata) }
- .rel.got : { *(.rel.got) }
- .rela.got : { *(.rela.got) }
- .rel.ctors : { *(.rel.ctors) }
- .rela.ctors : { *(.rela.ctors) }
- .rel.dtors : { *(.rel.dtors) }
- .rela.dtors : { *(.rela.dtors) }
- .rel.bss : { *(.rel.bss) }
- .rela.bss : { *(.rela.bss) }
- .rel.plt : { *(.rel.plt) }
- .rela.plt : { *(.rela.plt) }
- .init : { *(.init) }
- .plt : { *(.plt) }
- .text :
- {
- /* WARNING - the following is hand-optimized to fit within */
- /* the sector layout of our flash chips! XXX FIXME XXX */
-
-
- *(.text)
- *(.fixup)
- *(.got1)
- }
- _etext = .;
- PROVIDE (etext = .);
- .rodata :
- {
- *(.rodata)
- *(.rodata1)
- *(.rodata.str1.4)
- *(.eh_frame)
- }
- .fini : { *(.fini) } =0
- .ctors : { *(.ctors) }
- .dtors : { *(.dtors) }
-
- /* Read-write section, merged into data segment: */
- . = (. + 0x00FF) & 0xFFFFFF00;
- _erotext = .;
- PROVIDE (erotext = .);
- .reloc :
- {
- *(.got)
- _GOT2_TABLE_ = .;
- *(.got2)
- _FIXUP_TABLE_ = .;
- *(.fixup)
- }
- __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
- __fixup_entries = (. - _FIXUP_TABLE_)>>2;
-
- .data :
- {
- *(.data)
- *(.data1)
- *(.sdata)
- *(.sdata2)
- *(.dynamic)
- CONSTRUCTORS
- }
- _edata = .;
- PROVIDE (edata = .);
-
- . = .;
- __u_boot_cmd_start = .;
- .u_boot_cmd : { *(.u_boot_cmd) }
- __u_boot_cmd_end = .;
-
-
- . = .;
- __start___ex_table = .;
- __ex_table : { *(__ex_table) }
- __stop___ex_table = .;
-
- . = ALIGN(256);
- __init_begin = .;
- .text.init : { *(.text.init) }
- .data.init : { *(.data.init) }
- . = ALIGN(256);
- __init_end = .;
-
- __bss_start = .;
- .bss (NOLOAD) :
- {
- *(.sbss) *(.scommon)
- *(.dynbss)
- *(.bss)
- *(COMMON)
- }
-
- ppcenv_assert = ASSERT(. < 0xFFFFB000, ".bss section too big, overlaps .ppcenv section. Please update your confguration: CFG_MONITOR_BASE, CFG_MONITOR_LEN and TEXT_BASE may need to be modified.");
-
- _end = . ;
- PROVIDE (end = .);
-}
diff --git a/board/xilinx/ml507/xparameters.h b/board/xilinx/ml507/xparameters.h
index 77d2ddf..1992fff 100644
--- a/board/xilinx/ml507/xparameters.h
+++ b/board/xilinx/ml507/xparameters.h
@@ -21,15 +21,14 @@
#ifndef XPARAMETER_H
#define XPARAMETER_H
-#define XPAR_DDR2_SDRAM_MEM_BASEADDR 0x00000000
-#define XPAR_IIC_EEPROM_BASEADDR 0x81600000
-#define XPAR_INTC_0_BASEADDR 0x81800000
-#define XPAR_LLTEMAC_0_BASEADDR 0x81C00000
-#define XPAR_UARTLITE_0_BASEADDR 0x84000000
-#define XPAR_FLASH_MEM0_BASEADDR 0xFE000000
-#define XPAR_PLB_CLOCK_FREQ_HZ 100000000
-#define XPAR_CORE_CLOCK_FREQ_HZ 400000000
-#define XPAR_INTC_MAX_NUM_INTR_INPUTS 13
+#define XPAR_DDR2_SDRAM_MEM_BASEADDR 0x00000000
+#define XPAR_IIC_EEPROM_BASEADDR 0x81600000
+#define XPAR_INTC_0_BASEADDR 0x81800000
+#define XPAR_UARTLITE_0_BASEADDR 0x84000000
+#define XPAR_FLASH_MEM0_BASEADDR 0xFE000000
+#define XPAR_PLB_CLOCK_FREQ_HZ 100000000
+#define XPAR_CORE_CLOCK_FREQ_HZ 400000000
+#define XPAR_INTC_MAX_NUM_INTR_INPUTS 13
#define XPAR_UARTLITE_0_BAUDRATE 9600
#endif
diff --git a/board/xilinx/ppc440-generic/.gitignore b/board/xilinx/ppc440-generic/.gitignore
new file mode 100644
index 0000000..6896ef6
--- /dev/null
+++ b/board/xilinx/ppc440-generic/.gitignore
@@ -0,0 +1 @@
+/config.mk
diff --git a/board/xilinx/ppc440-generic/Makefile b/board/xilinx/ppc440-generic/Makefile
new file mode 100644
index 0000000..f7405a8
--- /dev/null
+++ b/board/xilinx/ppc440-generic/Makefile
@@ -0,0 +1,62 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd(a)denx.de.
+#
+# (C) Copyright 2008
+# Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda(a)uam.es
+# Work supported by Qtechnology http://www.qtec.com
+#
+# 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
+ifneq ($(OBJTREE),$(SRCTREE))
+endif
+
+INCS :=
+CFLAGS += $(INCS)
+HOST_CFLAGS += $(INCS)
+
+LIB = $(obj)lib$(BOARD).a
+
+COBJS += $(SRCTREE)/board/xilinx/ppc440-generic/xilinx_ppc440_generic.o
+
+SOBJS += $(SRCTREE)/board/xilinx/ppc440-generic/init.o
+
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+SOBJS := $(addprefix $(obj),$(SOBJS))
+
+$(LIB): $(OBJS) $(SOBJS)
+ $(AR) $(ARFLAGS) $@ $^
+
+clean:
+ rm -f $(SOBJS) $(OBJS)
+
+distclean: clean
+ rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/xilinx/ppc440-generic/init.S b/board/xilinx/ppc440-generic/init.S
new file mode 100644
index 0000000..1409467
--- /dev/null
+++ b/board/xilinx/ppc440-generic/init.S
@@ -0,0 +1,45 @@
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda(a)uam.es
+ * This work has been supported by: QTechnology http://qtec.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 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <ppc_asm.tmpl>
+#include <config.h>
+#include <asm-ppc/mmu.h>
+
+.section .bootpg,"ax"
+.globl tlbtab
+
+tlbtab:
+tlbtab_start
+tlbentry(0x00000000, SZ_256M, 0x00000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I)
+tlbentry(0x10000000, SZ_256M, 0x10000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I)
+tlbentry(0x20000000, SZ_256M, 0x20000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I)
+tlbentry(0x30000000, SZ_256M, 0x30000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I)
+tlbentry(0x40000000, SZ_256M, 0x40000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I)
+tlbentry(0x50000000, SZ_256M, 0x50000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I)
+tlbentry(0x60000000, SZ_256M, 0x60000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I)
+tlbentry(0x70000000, SZ_256M, 0x70000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I)
+tlbentry(0x80000000, SZ_256M, 0x80000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I)
+tlbentry(0x90000000, SZ_256M, 0x90000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I)
+tlbentry(0xa0000000, SZ_256M, 0xa0000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I)
+tlbentry(0xb0000000, SZ_256M, 0xb0000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I)
+tlbentry(0xc0000000, SZ_256M, 0xc0000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I)
+tlbentry(0xd0000000, SZ_256M, 0xd0000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I)
+tlbentry(0xe0000000, SZ_256M, 0xe0000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I)
+tlbentry(0xf0000000, SZ_256M, 0xf0000000, 0, AC_R | AC_W | AC_X | SA_G | SA_I)
+tlbtab_end
diff --git a/board/xilinx/ppc440-generic/u-boot-ram.lds b/board/xilinx/ppc440-generic/u-boot-ram.lds
new file mode 100644
index 0000000..2c98d27
--- /dev/null
+++ b/board/xilinx/ppc440-generic/u-boot-ram.lds
@@ -0,0 +1,134 @@
+/*
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd(a)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
+ */
+
+OUTPUT_ARCH(powerpc)
+ENTRY(_start_440)
+
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ /* WARNING - the following is hand-optimized to fit within */
+ /* the sector layout of our flash chips! XXX FIXME XXX */
+
+
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ *(.rodata.str1.4)
+ *(.eh_frame)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+
+ ppcenv_assert = ASSERT(. < 0xFFFFB000, ".bss section too big, overlaps .ppcenv section. Please update your confguration: CFG_MONITOR_BASE, CFG_MONITOR_LEN and TEXT_BASE may need to be modified.");
+
+ _end = . ;
+ PROVIDE (end = .);
+}
diff --git a/board/xilinx/ppc440-generic/u-boot-rom.lds b/board/xilinx/ppc440-generic/u-boot-rom.lds
new file mode 100644
index 0000000..d5da018
--- /dev/null
+++ b/board/xilinx/ppc440-generic/u-boot-rom.lds
@@ -0,0 +1,144 @@
+/*
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd(a)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
+ */
+
+OUTPUT_ARCH(powerpc)
+ENTRY(_start_440)
+
+SECTIONS
+{
+ .resetvec 0xFFFFFFFC :
+ {
+ *(.resetvec)
+ } = 0xffff
+
+ .bootpg 0xFFFFF000 :
+ {
+ cpu/ppc4xx/start.o (.bootpg)
+ } = 0xffff
+
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ /* WARNING - the following is hand-optimized to fit within */
+ /* the sector layout of our flash chips! XXX FIXME XXX */
+
+
+ *(.text)
+ *(.fixup)
+ *(.got1)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ *(.rodata.str1.4)
+ *(.eh_frame)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ __u_boot_cmd_end = .;
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+
+ ppcenv_assert = ASSERT(. < 0xFFFFB000, ".bss section too big, overlaps .ppcenv section. Please update your confguration: CFG_MONITOR_BASE, CFG_MONITOR_LEN and TEXT_BASE may need to be modified.");
+
+ _end = . ;
+ PROVIDE (end = .);
+}
diff --git a/board/xilinx/ppc440-generic/xilinx_ppc440_generic.c b/board/xilinx/ppc440-generic/xilinx_ppc440_generic.c
new file mode 100644
index 0000000..0867226
--- /dev/null
+++ b/board/xilinx/ppc440-generic/xilinx_ppc440_generic.c
@@ -0,0 +1,52 @@
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda(a)uam.es
+ * This work has been supported by: QTechnology http://qtec.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 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <config.h>
+#include <common.h>
+#include <asm/processor.h>
+
+int __board_pre_init(void)
+{
+ return 0;
+}
+int board_pre_init(void) __attribute__((weak, alias("__board_pre_init")));
+
+int __checkboard(void)
+{
+ puts("Xilinx PPC440 Generic Board\n");
+ return 0;
+}
+int checkboard(void) __attribute__((weak, alias("__checkboard")));
+
+phys_size_t __initdram(int board_type)
+{
+ return get_ram_size(XPAR_DDR2_SDRAM_MEM_BASEADDR,
+ CFG_SDRAM_SIZE_MB * 1024 * 1024);
+}
+phys_size_t initdram(int) __attribute__((weak, alias("__initdram")));
+
+void __get_sys_info(sys_info_t *sysInfo)
+{
+ sysInfo->freqProcessor = XPAR_CORE_CLOCK_FREQ_HZ;
+ sysInfo->freqPLB = XPAR_PLB_CLOCK_FREQ_HZ;
+ sysInfo->freqPCI = 0;
+
+ return;
+}
+void get_sys_info(sys_info_t *) __attribute__((weak, alias("__get_sys_info")));
diff --git a/board/xilinx/ppc440-generic/xparameters.h b/board/xilinx/ppc440-generic/xparameters.h
new file mode 100644
index 0000000..1992fff
--- /dev/null
+++ b/board/xilinx/ppc440-generic/xparameters.h
@@ -0,0 +1,34 @@
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda(a)uam.es
+ * This work has been supported by: QTechnology http://qtec.com/
+ * based on xparameters-ml507.h by Xilinx
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef XPARAMETER_H
+#define XPARAMETER_H
+
+#define XPAR_DDR2_SDRAM_MEM_BASEADDR 0x00000000
+#define XPAR_IIC_EEPROM_BASEADDR 0x81600000
+#define XPAR_INTC_0_BASEADDR 0x81800000
+#define XPAR_UARTLITE_0_BASEADDR 0x84000000
+#define XPAR_FLASH_MEM0_BASEADDR 0xFE000000
+#define XPAR_PLB_CLOCK_FREQ_HZ 100000000
+#define XPAR_CORE_CLOCK_FREQ_HZ 400000000
+#define XPAR_INTC_MAX_NUM_INTR_INPUTS 13
+#define XPAR_UARTLITE_0_BAUDRATE 9600
+
+#endif
diff --git a/include/configs/ml507.h b/include/configs/ml507.h
index f8cd499..37d93bb 100644
--- a/include/configs/ml507.h
+++ b/include/configs/ml507.h
@@ -17,106 +17,33 @@
#ifndef __CONFIG_H
#define __CONFIG_H
-/*
-#define DEBUG
-#define ET_DEBUG
-*/
- /*CPU*/
-#define CONFIG_XILINX_ML507 1
-#define CONFIG_XILINX_440 1
+
+/*CPU*/
#define CONFIG_440 1
-#define CONFIG_4xx 1
+#define CONFIG_XILINX_ML507 1
#include "../board/xilinx/ml507/xparameters.h"
/*Mem Map*/
-#define CFG_SDRAM_BASE 0x0
#define CFG_SDRAM_SIZE_MB 256
-#define CFG_MONITOR_BASE TEXT_BASE
-#define CFG_MONITOR_LEN ( 192 * 1024 )
-#define CFG_MALLOC_LEN ( CFG_ENV_SIZE + 128 * 1024 )
-
-/*Uart*/
-#define CONFIG_XILINX_UARTLITE
-#define CONFIG_BAUDRATE XPAR_UARTLITE_0_BAUDRATE
-#define CFG_BAUDRATE_TABLE { XPAR_UARTLITE_0_BAUDRATE }
-#define CONFIG_SERIAL_BASE XPAR_UARTLITE_0_BASEADDR
-
-/*Cmd*/
-#include <config_cmd_default.h>
-#define CONFIG_CMD_ASKENV
-#define CONFIG_CMD_CACHE
-#define CONFIG_CMD_DIAG
-#define CONFIG_CMD_ELF
-#define CONFIG_CMD_IRQ
-#define CONFIG_CMD_REGINFO
-#define CONFIG_CMD_JFFS2
-#define CONFIG_JFFS2_CMDLINE
-#undef CONFIG_CMD_I2C
-#undef CONFIG_CMD_DTT
-#undef CONFIG_CMD_NET
-#undef CONFIG_CMD_PING
-#undef CONFIG_CMD_DHCP
-#undef CONFIG_CMD_EEPROM
-#undef CONFIG_CMD_IMLS
/*Env*/
-#define CFG_ENV_IS_IN_FLASH
+#define CFG_ENV_IS_IN_FLASH 1
#define CFG_ENV_SIZE 0x20000
#define CFG_ENV_SECT_SIZE 0x20000
-#define CFG_ENV_OFFSET 0x340000
-#define CFG_ENV_ADDR (XPAR_FLASH_MEM0_BASEADDR+CFG_ENV_OFFSET)
+#define CFG_ENV_OFFSET 0x340000
+#define CFG_ENV_ADDR (XPAR_FLASH_MEM0_BASEADDR+CFG_ENV_OFFSET)
/*Misc*/
-#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */
-#define CFG_LONGHELP /* undef to save memory */
-#define CFG_PROMPT "board:/# " /* Monitor Command Prompt */
-#if defined(CONFIG_CMD_KGDB)
-#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */
-#else
-#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
-#endif
-#define CFG_PBSIZE ( CFG_CBSIZE + sizeof( CFG_PROMPT ) + 16 )
-#define CFG_MAXARGS 16 /* max number of command args */
-#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */
-#define CFG_MEMTEST_START 0x00400000 /* memtest works on */
-#define CFG_MEMTEST_END 0x00C00000 /* 4 ... 12 MB in DRAM */
-#define CFG_LOAD_ADDR 0x00400000 /* default load address */
-#define CFG_EXTBDINFO 1 /* Extended board_into (bd_t) */
-#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */
-#define CONFIG_CMDLINE_EDITING /* add command line history */
-#define CONFIG_AUTO_COMPLETE /* add autocompletion support */
-#define CONFIG_LOOPW /* enable loopw command */
-#define CONFIG_MX_CYCLIC /* enable mdc/mwc commands */
-#define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */
-#define CONFIG_VERSION_VARIABLE /* include version env variable */
-#define CFG_CONSOLE_INFO_QUIET /* don't print console @ startup */
-#define CFG_HUSH_PARSER /* Use the HUSH parser */
-#define CFG_PROMPT_HUSH_PS2 "> "
-#define CONFIG_LOADS_ECHO /* echo on for serial download */
-#define CFG_LOADS_BAUD_CHANGE /* allow baudrate change */
-#define CFG_BOOTMAPSZ ( 8 << 20 ) /* Initial Memory map for Linux */
+#define CFG_PROMPT "ml507:/# " /* Monitor Command Prompt */
#define CONFIG_PREBOOT "echo U-Boot is up and runnining;"
-/*Stack*/
-#define CFG_INIT_RAM_ADDR 0x800000 /* Initial RAM address */
-#define CFG_INIT_RAM_END 0x2000 /* End of used area in RAM */
-#define CFG_GBL_DATA_SIZE 128 /* num bytes initial data */
-#define CFG_GBL_DATA_OFFSET ( CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE )
-#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET
-/*Speed*/
-#define CONFIG_SYS_CLK_FREQ XPAR_CORE_CLOCK_FREQ_HZ
-
/*Flash*/
-#define CFG_FLASH_BASE XPAR_FLASH_MEM0_BASEADDR
#define CFG_FLASH_SIZE (32*1024*1024)
-#define CFG_FLASH_CFI 1
-#define CONFIG_FLASH_CFI_DRIVER 1
-#define CFG_FLASH_EMPTY_INFO 1
-#define CFG_MAX_FLASH_BANKS 1
#define CFG_MAX_FLASH_SECT 259
-#define CFG_FLASH_PROTECTION
#define MTDIDS_DEFAULT "nor0=ml507-flash"
#define MTDPARTS_DEFAULT "mtdparts=ml507-flash:-(user)"
+/*Generic Configs*/
+#include <configs/xilinx-ppc440.h>
#endif /* __CONFIG_H */
diff --git a/include/configs/v5fx30teval.h b/include/configs/v5fx30teval.h
new file mode 100644
index 0000000..67d8d7f
--- /dev/null
+++ b/include/configs/v5fx30teval.h
@@ -0,0 +1,49 @@
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda(a)uam.es
+ * This work has been supported by: QTechnology http://qtec.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 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*CPU*/
+#define CONFIG_440 1
+#define CONFIG_XILINX_ML507 1
+#include "../board/avnet/v5fx30teval/xparameters.h"
+
+/*Mem Map*/
+#define CFG_SDRAM_SIZE_MB 64
+
+/*Env*/
+#define CFG_ENV_IS_IN_FLASH 1
+#define CFG_ENV_SIZE 0x20000
+#define CFG_ENV_SECT_SIZE 0x20000
+#define CFG_ENV_OFFSET 0x1A0000
+#define CFG_ENV_ADDR (XPAR_FLASH_MEM0_BASEADDR+CFG_ENV_OFFSET)
+
+/*Misc*/
+#define CFG_PROMPT "v5fx30t:/# " /* Monitor Command Prompt */
+#define CONFIG_PREBOOT "echo U-Boot is up and runnining;"
+
+/*Flash*/
+#define CFG_FLASH_SIZE (16*1024*1024)
+#define CFG_MAX_FLASH_SECT 131
+#define MTDIDS_DEFAULT "nor0=v5fx30t-flash"
+#define MTDPARTS_DEFAULT "mtdparts=v5fx30t-flash:-(user)"
+
+/*Generic Configs*/
+#include <configs/xilinx-ppc440.h>
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/xilinx-ppc440-generic.h b/include/configs/xilinx-ppc440-generic.h
new file mode 100644
index 0000000..4e8080b
--- /dev/null
+++ b/include/configs/xilinx-ppc440-generic.h
@@ -0,0 +1,49 @@
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda(a)uam.es
+ * This work has been supported by: QTechnology http://qtec.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 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*CPU*/
+#define CONFIG_440 1
+#define CONFIG_XILINX_PPC440_GENERIC 1
+#include "../board/xilinx/ppc440-generic/xparameters.h"
+
+/*Mem Map*/
+#define CFG_SDRAM_SIZE_MB 256
+
+/*Env*/
+#define CFG_ENV_IS_IN_FLASH 1
+#define CFG_ENV_SIZE 0x20000
+#define CFG_ENV_SECT_SIZE 0x20000
+#define CFG_ENV_OFFSET 0x340000
+#define CFG_ENV_ADDR (XPAR_FLASH_MEM0_BASEADDR+CFG_ENV_OFFSET)
+
+/*Misc*/
+#define CFG_PROMPT "board:/# " /* Monitor Command Prompt */
+#define CONFIG_PREBOOT "echo U-Boot is up and runnining;"
+
+/*Flash*/
+#define CFG_FLASH_SIZE (32*1024*1024)
+#define CFG_MAX_FLASH_SECT 259
+#define MTDIDS_DEFAULT "nor0=ml507-flash"
+#define MTDPARTS_DEFAULT "mtdparts=ml507-flash:-(user)"
+
+/*Generic Configs*/
+#include <configs/xilinx-ppc440.h>
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/xilinx-ppc440.h b/include/configs/xilinx-ppc440.h
new file mode 100644
index 0000000..40293cd
--- /dev/null
+++ b/include/configs/xilinx-ppc440.h
@@ -0,0 +1,106 @@
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda(a)uam.es
+ * This work has been supported by: QTechnology http://qtec.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 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __CONFIG_GEN_H
+#define __CONFIG_GEN_H
+/*
+#define DEBUG
+#define ET_DEBUG
+*/
+ /*CPU*/
+#define CONFIG_XILINX_440 1
+#define CONFIG_440 1
+#define CONFIG_4xx 1
+
+/*Mem Map*/
+#define CFG_SDRAM_BASE 0x0
+#define CFG_MONITOR_BASE TEXT_BASE
+#define CFG_MONITOR_LEN (192 * 1024)
+#define CFG_MALLOC_LEN (CFG_ENV_SIZE + 128 * 1024)
+
+/*Uart*/
+#define CONFIG_XILINX_UARTLITE
+#define CONFIG_BAUDRATE XPAR_UARTLITE_0_BAUDRATE
+#define CFG_BAUDRATE_TABLE { XPAR_UARTLITE_0_BAUDRATE }
+#define CONFIG_SERIAL_BASE XPAR_UARTLITE_0_BASEADDR
+
+/*Cmd*/
+#include <config_cmd_default.h>
+#define CONFIG_CMD_ASKENV
+#define CONFIG_CMD_CACHE
+#define CONFIG_CMD_DIAG
+#define CONFIG_CMD_ELF
+#define CONFIG_CMD_IRQ
+#define CONFIG_CMD_REGINFO
+#define CONFIG_CMD_JFFS2
+#define CONFIG_JFFS2_CMDLINE
+#undef CONFIG_CMD_SPI
+#undef CONFIG_CMD_I2C
+#undef CONFIG_CMD_DTT
+#undef CONFIG_CMD_NET
+#undef CONFIG_CMD_PING
+#undef CONFIG_CMD_DHCP
+#undef CONFIG_CMD_EEPROM
+#undef CONFIG_CMD_IMLS
+
+/*Misc*/
+#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */
+#define CFG_LONGHELP /* undef to save memory */
+#if defined(CONFIG_CMD_KGDB)
+#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */
+#else
+#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
+#endif
+#define CFG_PBSIZE (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16)
+#define CFG_MAXARGS 16 /* max number of command args */
+#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */
+#define CFG_MEMTEST_START 0x00400000 /* memtest works on */
+#define CFG_MEMTEST_END 0x00C00000 /* 4 ... 12 MB in DRAM */
+#define CFG_LOAD_ADDR 0x00400000 /* default load address */
+#define CFG_EXTBDINFO 1 /* Extended board_into (bd_t) */
+#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */
+#define CONFIG_CMDLINE_EDITING /* add command line history */
+#define CONFIG_AUTO_COMPLETE /* add autocompletion support */
+#define CONFIG_LOOPW /* enable loopw command */
+#define CONFIG_MX_CYCLIC /* enable mdc/mwc commands */
+#define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */
+#define CONFIG_VERSION_VARIABLE /* include version env variable */
+#define CFG_CONSOLE_INFO_QUIET /* don't print console @ startup */
+#define CFG_HUSH_PARSER /* Use the HUSH parser */
+#define CFG_PROMPT_HUSH_PS2 "> "
+#define CONFIG_LOADS_ECHO /* echo on for serial download */
+#define CFG_LOADS_BAUD_CHANGE /* allow baudrate change */
+#define CFG_BOOTMAPSZ (8 << 20)/* Initial Memory map for Linux */
+
+/*Stack*/
+#define CFG_INIT_RAM_ADDR 0x800000 /* Initial RAM address */
+#define CFG_INIT_RAM_END 0x2000 /* End of used area in RAM */
+#define CFG_GBL_DATA_SIZE 128 /* num bytes initial data */
+#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET
+/*Speed*/
+#define CONFIG_SYS_CLK_FREQ XPAR_CORE_CLOCK_FREQ_HZ
+
+/*Flash*/
+#define CFG_FLASH_BASE XPAR_FLASH_MEM0_BASEADDR
+#define CFG_FLASH_CFI 1
+#define CONFIG_FLASH_CFI_DRIVER 1
+#define CFG_FLASH_EMPTY_INFO 1
+#define CFG_MAX_FLASH_BANKS 1
+#define CFG_FLASH_PROTECTION
+
+#endif /* __CONFIG_H */
--
1.5.6.5
2
1

[U-Boot] [PATCH 1/1] ppc4xx: Add support for GPCS, SGMII and M88E1112 PHY
by Victor Gallardo 05 Sep '08
by Victor Gallardo 05 Sep '08
05 Sep '08
This patch adds GPCS, SGMII and M88E1112 PHY support
for the AMCC PPC460GT/EX processors.
Signed-off-by: Victor Gallardo <vgallardo(a)amcc.com>
---
v2:
- Added comments to GPCS PHY setup
- Minor coding style cleanup
v3:
- Generalized the PHY-less configuration even more
v4:
- Change "PHY-less" to "Fixed PHY" to standardize
cpu/ppc4xx/4xx_enet.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++-
cpu/ppc4xx/miiphy.c | 41 ++++++++++++-
include/ppc4xx_enet.h | 3 +
3 files changed, 198 insertions(+), 5 deletions(-)
diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c
index 8a38335..071ac0a 100644
--- a/cpu/ppc4xx/4xx_enet.c
+++ b/cpu/ppc4xx/4xx_enet.c
@@ -198,6 +198,7 @@
#define BI_PHYMODE_RMII 8
#endif
#endif
+#define BI_PHYMODE_SGMII 9
#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
@@ -216,6 +217,52 @@
#define MAL_RX_CHAN_MUL 1
#endif
+/*--------------------------------------------------------------------+
+ * Fixed PHY (PHY-less) support for Ethernet Ports.
+ *--------------------------------------------------------------------*/
+
+/*
+ * Some boards do not have a PHY for each ethernet port. These ports
+ * are known as Fixed PHY (or PHY-less) ports. For such ports, set
+ * the appropriate CONFIG_PHY_ADDR equal to CONFIG_FIXED_PHY and
+ * then define CFG_FIXED_PHY_PORTS to define what the speed and
+ * duplex should be for these ports in the board configuration
+ * file.
+ *
+ * For Example:
+ * #define CONFIG_FIXED_PHY 0xFFFFFFFF
+ *
+ * #define CONFIG_PHY_ADDR CONFIG_FIXED_PHY
+ * #define CONFIG_PHY1_ADDR 1
+ * #define CONFIG_PHY2_ADDR CONFIG_FIXED_PHY
+ * #define CONFIG_PHY3_ADDR 3
+ *
+ * #define CFG_FIXED_PHY_PORT(devnum,speed,duplex) \
+ * {devnum, speed, duplex},
+ *
+ * #define CFG_FIXED_PHY_PORTS \
+ * CFG_FIXED_PHY_PORT(0,1000,FULL) \
+ * CFG_FIXED_PHY_PORT(2,100,HALF)
+ */
+
+#ifndef CONFIG_FIXED_PHY
+#define CONFIG_FIXED_PHY 0xFFFFFFFF /* Fixed PHY (PHY-less) */
+#endif
+
+#ifndef CFG_FIXED_PHY_PORTS
+#define CFG_FIXED_PHY_PORTS /* default is an empty array */
+#endif
+
+struct fixed_phy_port {
+ unsigned int devnum; /* ethernet port */
+ unsigned int speed; /* specified speed 10,100 or 1000 */
+ unsigned int duplex; /* specified duplex FULL or HALF */
+};
+
+static const struct fixed_phy_port fixed_phy_port[] = {
+ CFG_FIXED_PHY_PORTS /* defined in board configuration file */
+};
+
/*-----------------------------------------------------------------------------+
* Global variables. TX and RX descriptors and buffers.
*-----------------------------------------------------------------------------*/
@@ -611,8 +658,17 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
#if defined(CONFIG_460EX)
mode = 9;
+ mfsdr(SDR0_ETH_CFG, eth_cfg);
+ if (((eth_cfg & SDR0_ETH_CFG_SGMII0_ENABLE) > 0) &&
+ ((eth_cfg & SDR0_ETH_CFG_SGMII1_ENABLE) > 0))
+ mode = 11; /* config SGMII */
#else
mode = 10;
+ mfsdr(SDR0_ETH_CFG, eth_cfg);
+ if (((eth_cfg & SDR0_ETH_CFG_SGMII0_ENABLE) > 0) &&
+ ((eth_cfg & SDR0_ETH_CFG_SGMII1_ENABLE) > 0) &&
+ ((eth_cfg & SDR0_ETH_CFG_SGMII2_ENABLE) > 0))
+ mode = 12; /* config SGMII */
#endif
/* TODO:
@@ -635,6 +691,8 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
/*
* Right now only 2*RGMII is supported. Please extend when needed.
* sr - 2008-02-19
+ * Add SGMII support.
+ * vg - 2008-07-28
*/
switch (mode) {
case 1:
@@ -761,6 +819,20 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
bis->bi_phymode[2] = BI_PHYMODE_RGMII;
bis->bi_phymode[3] = BI_PHYMODE_RGMII;
break;
+ case 11:
+ /* 2 SGMII - 460EX */
+ bis->bi_phymode[0] = BI_PHYMODE_SGMII;
+ bis->bi_phymode[1] = BI_PHYMODE_SGMII;
+ bis->bi_phymode[2] = BI_PHYMODE_NONE;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ break;
+ case 12:
+ /* 3 SGMII - 460GT */
+ bis->bi_phymode[0] = BI_PHYMODE_SGMII;
+ bis->bi_phymode[1] = BI_PHYMODE_SGMII;
+ bis->bi_phymode[2] = BI_PHYMODE_SGMII;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ break;
default:
break;
}
@@ -945,6 +1017,48 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
out_be32((void *)EMAC_M1 + hw_p->hw_addr, mode_reg);
#endif /* defined(CONFIG_440GX) || defined(CONFIG_440SP) */
+#if defined(CONFIG_GPCS_PHY_ADDR) || defined(CONFIG_GPCS_PHY1_ADDR) || \
+ defined(CONFIG_GPCS_PHY2_ADDR) || defined(CONFIG_GPCS_PHY3_ADDR)
+ if (bis->bi_phymode[devnum] == BI_PHYMODE_SGMII) {
+ /*
+ * In SGMII mode, GPCS access is needed for
+ * communication with the internal SGMII SerDes.
+ */
+ switch (devnum) {
+#if defined(CONFIG_GPCS_PHY_ADDR)
+ case 0:
+ reg = CONFIG_GPCS_PHY_ADDR;
+ break;
+#endif
+#if defined(CONFIG_GPCS_PHY1_ADDR)
+ case 1:
+ reg = CONFIG_GPCS_PHY1_ADDR;
+ break;
+#endif
+#if defined(CONFIG_GPCS_PHY2_ADDR)
+ case 2:
+ reg = CONFIG_GPCS_PHY2_ADDR;
+ break;
+#endif
+#if defined(CONFIG_GPCS_PHY3_ADDR)
+ case 3:
+ reg = CONFIG_GPCS_PHY3_ADDR;
+ break;
+#endif
+ }
+
+ mode_reg = in_be32((void *)EMAC_M1 + hw_p->hw_addr);
+ mode_reg |= EMAC_M1_MF_1000GPCS | EMAC_M1_IPPA_SET(reg);
+ out_be32((void *)EMAC_M1 + hw_p->hw_addr, mode_reg);
+
+ /* Configure GPCS interface to recommended setting for SGMII */
+ miiphy_reset(dev->name, reg);
+ miiphy_write(dev->name, reg, 0x04, 0x8120); /* AsymPause, FDX */
+ miiphy_write(dev->name, reg, 0x07, 0x2801); /* msg_pg, toggle */
+ miiphy_write(dev->name, reg, 0x00, 0x0140); /* 1Gbps, FDX */
+ }
+#endif /* defined(CONFIG_GPCS_PHY_ADDR) */
+
/* wait for PHY to complete auto negotiation */
reg_short = 0;
#ifndef CONFIG_CS8952_PHY
@@ -974,6 +1088,9 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
bis->bi_phynum[devnum] = reg;
+ if (reg == CONFIG_FIXED_PHY)
+ goto get_speed;
+
#if defined(CONFIG_PHY_RESET)
/*
* Reset the phy, only if its the first time through
@@ -986,6 +1103,27 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
miiphy_write (dev->name, reg, 0x09, 0x0e00);
miiphy_write (dev->name, reg, 0x04, 0x01e1);
#endif
+#if defined(CONFIG_M88E1112_PHY)
+ if (bis->bi_phymode[devnum] == BI_PHYMODE_SGMII) {
+ /*
+ * Marvell 88E1112 PHY needs to have the SGMII MAC
+ * interace (page 2) properly configured to
+ * communicate with the 460EX/GT GPCS interface.
+ */
+
+ /* Set access to Page 2 */
+ miiphy_write(dev->name, reg, 0x16, 0x0002);
+
+ miiphy_write(dev->name, reg, 0x00, 0x0040); /* 1Gbps */
+ miiphy_read(dev->name, reg, 0x1a, ®_short);
+ reg_short |= 0x8000; /* bypass Auto-Negotiation */
+ miiphy_write(dev->name, reg, 0x1a, reg_short);
+ miiphy_reset(dev->name, reg); /* reset MAC interface */
+
+ /* Reset access to Page 0 */
+ miiphy_write(dev->name, reg, 0x16, 0x0000);
+ }
+#endif /* defined(CONFIG_M88E1112_PHY) */
miiphy_reset (dev->name, reg);
#if defined(CONFIG_440GX) || \
@@ -1080,8 +1218,25 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
}
#endif /* #ifndef CONFIG_CS8952_PHY */
- speed = miiphy_speed (dev->name, reg);
- duplex = miiphy_duplex (dev->name, reg);
+get_speed:
+ if (reg == CONFIG_FIXED_PHY) {
+ for (i = 0; i < ARRAY_SIZE(fixed_phy_port); i++) {
+ if (devnum == fixed_phy_port[i].devnum) {
+ speed = fixed_phy_port[i].speed;
+ duplex = fixed_phy_port[i].duplex;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(fixed_phy_port)) {
+ printf("ERROR: PHY (%s) not configured correctly!\n",
+ dev->name);
+ return -1;
+ }
+ } else {
+ speed = miiphy_speed(dev->name, reg);
+ duplex = miiphy_duplex(dev->name, reg);
+ }
if (hw_p->print_speed) {
hw_p->print_speed = 0;
diff --git a/cpu/ppc4xx/miiphy.c b/cpu/ppc4xx/miiphy.c
index c882720..d303598 100644
--- a/cpu/ppc4xx/miiphy.c
+++ b/cpu/ppc4xx/miiphy.c
@@ -180,8 +180,10 @@ int phy_setup_aneg (char *devname, unsigned char addr)
*
* sr: Currently on 460EX only EMAC0 works with MDIO, so we always
* return EMAC0 offset here
+ * vg: For 460EX/460GT if internal GPCS PHY address is specified
+ * return appropriate EMAC offset
*/
-unsigned int miiphy_getemac_offset (void)
+unsigned int miiphy_getemac_offset(u8 addr)
{
#if (defined(CONFIG_440) && \
!defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
@@ -233,6 +235,39 @@ unsigned int miiphy_getemac_offset (void)
return 0x100;
#endif
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ u32 mode_reg;
+ u32 eoffset = 0;
+
+ switch (addr) {
+#if defined(CONFIG_HAS_ETH1) && defined(CONFIG_GPCS_PHY1_ADDR)
+ case CONFIG_GPCS_PHY1_ADDR:
+ mode_reg = in_be32((void *)EMAC_M1 + 0x100);
+ if (addr == EMAC_M1_IPPA_GET(mode_reg))
+ eoffset = 0x100;
+ break;
+#endif
+#if defined(CONFIG_HAS_ETH2) && defined(CONFIG_GPCS_PHY2_ADDR)
+ case CONFIG_GPCS_PHY2_ADDR:
+ mode_reg = in_be32((void *)EMAC_M1 + 0x300);
+ if (addr == EMAC_M1_IPPA_GET(mode_reg))
+ eoffset = 0x300;
+ break;
+#endif
+#if defined(CONFIG_HAS_ETH3) && defined(CONFIG_GPCS_PHY3_ADDR)
+ case CONFIG_GPCS_PHY3_ADDR:
+ mode_reg = in_be32((void *)EMAC_M1 + 0x400);
+ if (addr == EMAC_M1_IPPA_GET(mode_reg))
+ eoffset = 0x400;
+ break;
+#endif
+ default:
+ eoffset = 0;
+ break;
+ }
+ return eoffset;
+#endif
+
return 0;
#endif
}
@@ -262,7 +297,7 @@ static int emac_miiphy_command(u8 addr, u8 reg, int cmd, u16 value)
u32 emac_reg;
u32 sta_reg;
- emac_reg = miiphy_getemac_offset();
+ emac_reg = miiphy_getemac_offset(addr);
/* wait for completion */
if (emac_miiphy_wait(emac_reg) != 0)
@@ -311,7 +346,7 @@ int emac4xx_miiphy_read (char *devname, unsigned char addr, unsigned char reg,
unsigned long sta_reg;
unsigned long emac_reg;
- emac_reg = miiphy_getemac_offset ();
+ emac_reg = miiphy_getemac_offset(addr);
if (emac_miiphy_command(addr, reg, EMAC_STACR_READ, 0) != 0)
return -1;
diff --git a/include/ppc4xx_enet.h b/include/ppc4xx_enet.h
index b74c6fc..00669a7 100644
--- a/include/ppc4xx_enet.h
+++ b/include/ppc4xx_enet.h
@@ -376,6 +376,7 @@ typedef struct emac_4xx_hw_st {
#define EMAC_M1_APP (0x08000000)
#define EMAC_M1_RSVD (0x06000000)
#define EMAC_M1_IST (0x01000000)
+#define EMAC_M1_MF_1000GPCS (0x00C00000)
#define EMAC_M1_MF_1000MBPS (0x00800000) /* 0's for 10MBPS */
#define EMAC_M1_MF_100MBPS (0x00400000)
#define EMAC_M1_RFS_MASK (0x00380000)
@@ -394,6 +395,8 @@ typedef struct emac_4xx_hw_st {
#define EMAC_M1_MWSW (0x00007000)
#define EMAC_M1_JUMBO_ENABLE (0x00000800)
#define EMAC_M1_IPPA (0x000007c0)
+#define EMAC_M1_IPPA_SET(id) (((id) & 0x1f) << 6)
+#define EMAC_M1_IPPA_GET(id) (((id) >> 6) & 0x1f)
#define EMAC_M1_OBCI_GT100 (0x00000020)
#define EMAC_M1_OBCI_100 (0x00000018)
#define EMAC_M1_OBCI_83 (0x00000010)
--
1.5.5
1
0

04 Sep '08
From: Nick Spence <nick.spence(a)freescale.com>
and add mpc8313 NAND build to MAKEALL
Signed-off-by: Nick Spence <nick.spence(a)freescale.com>
Signed-off-by: Kim Phillips <kim.phillips(a)freescale.com>
---
MAKEALL | 2 +-
Makefile | 3 +++
2 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/MAKEALL b/MAKEALL
index e382947..e49f994 100755
--- a/MAKEALL
+++ b/MAKEALL
@@ -320,7 +320,7 @@ LIST_8260=" \
LIST_83xx=" \
MPC8313ERDB_33 \
- MPC8313ERDB_66 \
+ MPC8313ERDB_NAND_66 \
MPC8315ERDB \
MPC8323ERDB \
MPC832XEMDS \
diff --git a/Makefile b/Makefile
index 0f82e71..3d8b61c 100644
--- a/Makefile
+++ b/Makefile
@@ -2082,6 +2082,9 @@ MPC8313ERDB_NAND_66_config: unconfig
echo "#define CONFIG_NAND_U_BOOT" >>$(obj)include/config.h ; \
fi ;
@$(MKCONFIG) -a MPC8313ERDB ppc mpc83xx mpc8313erdb freescale
+ @if [ "$(findstring _NAND_,$@)" ] ; then \
+ echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk ; \
+ fi ;
MPC8315ERDB_config: unconfig
@$(MKCONFIG) -a MPC8315ERDB ppc mpc83xx mpc8315erdb freescale
--
1.6.0.6.gc667
2
1

[U-Boot] [PATCH 1/1 v3] ppc4xx: Add support for GPCS, SGMII and M88E1112 PHY
by Victor Gallardo 04 Sep '08
by Victor Gallardo 04 Sep '08
04 Sep '08
This patch adds GPCS, SGMII and M88E1112 PHY support
for the AMCC PPC460GT/EX processors.
Signed-off-by: Victor Gallardo <vgallardo(a)amcc.com>
---
cpu/ppc4xx/4xx_enet.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++-
cpu/ppc4xx/miiphy.c | 41 ++++++++++++-
include/ppc4xx_enet.h | 3 +
3 files changed, 201 insertions(+), 5 deletions(-)
diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c
index 8a38335..e137bac 100644
--- a/cpu/ppc4xx/4xx_enet.c
+++ b/cpu/ppc4xx/4xx_enet.c
@@ -198,6 +198,7 @@
#define BI_PHYMODE_RMII 8
#endif
#endif
+#define BI_PHYMODE_SGMII 9
#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
@@ -216,6 +217,52 @@
#define MAL_RX_CHAN_MUL 1
#endif
+/*--------------------------------------------------------------------+
+ * PHY-less support for Ethernet Ports.
+ *--------------------------------------------------------------------*/
+
+/*
+ * Some boards do not have a PHY for each ethernet port.
+ * For example on Arches board (2 CPU system) eth0 does not have
+ * a PHY, both CPU's are wired directly together (AC coupled)
+ * using SGMII0.
+ *
+ * In these cases :
+ * 1) set the appropriate CONFIG_PHY_ADDR equal to CONFIG_PHY_LESS
+ * to detect that the specified ethernet port does not have a PHY.
+ * 2) Then define CFG_PHY_LESS_PORT and CFG_PHY_LESS_PORTS in board
+ * configuration file. For example on the Arches board we would do
+ * the following.
+ * #define CFG_PHY_LESS_PORT(devnum,speed,duplex) \
+ * { devnum, speed, duplex},
+ * #define CFG_PHY_LESS_PORTS \
+ * CFG_PHY_LESS_PORT(0,1000,FULL)
+ */
+#if !defined(CONFIG_PHY_LESS)
+#define CONFIG_PHY_LESS 0xFFFFFFFF /* PHY-less mode */
+#endif
+
+#define DFLT_PHY_LESS_SPEED 100
+#define DFLT_PHY_LESS_DUPLEX FULL
+
+/*
+ * CFG_PHY_LESS_PORTS tells us about ethernet ports that have no PHY
+ * attached to them.
+ */
+#ifndef CFG_PHY_LESS_PORTS
+#define CFG_PHY_LESS_PORTS
+#endif
+
+struct phy_less_port {
+ unsigned int devnum; /* ethernet port */
+ unsigned int speed; /* specified speed 10,100 or 1000 */
+ unsigned int duplex; /* specified duplex FULL or HALF */
+};
+
+static const struct phy_less_port phy_less_port[] = {
+ CFG_PHY_LESS_PORTS /* defined in board configuration file */
+};
+
/*-----------------------------------------------------------------------------+
* Global variables. TX and RX descriptors and buffers.
*-----------------------------------------------------------------------------*/
@@ -611,8 +658,17 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
#if defined(CONFIG_460EX)
mode = 9;
+ mfsdr(SDR0_ETH_CFG, eth_cfg);
+ if (((eth_cfg & SDR0_ETH_CFG_SGMII0_ENABLE) > 0) &&
+ ((eth_cfg & SDR0_ETH_CFG_SGMII1_ENABLE) > 0))
+ mode = 11; /* config SGMII */
#else
mode = 10;
+ mfsdr(SDR0_ETH_CFG, eth_cfg);
+ if (((eth_cfg & SDR0_ETH_CFG_SGMII0_ENABLE) > 0) &&
+ ((eth_cfg & SDR0_ETH_CFG_SGMII1_ENABLE) > 0) &&
+ ((eth_cfg & SDR0_ETH_CFG_SGMII2_ENABLE) > 0))
+ mode = 12; /* config SGMII */
#endif
/* TODO:
@@ -635,6 +691,8 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
/*
* Right now only 2*RGMII is supported. Please extend when needed.
* sr - 2008-02-19
+ * Add SGMII support.
+ * vg - 2008-07-28
*/
switch (mode) {
case 1:
@@ -761,6 +819,20 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
bis->bi_phymode[2] = BI_PHYMODE_RGMII;
bis->bi_phymode[3] = BI_PHYMODE_RGMII;
break;
+ case 11:
+ /* 2 SGMII - 460EX */
+ bis->bi_phymode[0] = BI_PHYMODE_SGMII;
+ bis->bi_phymode[1] = BI_PHYMODE_SGMII;
+ bis->bi_phymode[2] = BI_PHYMODE_NONE;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ break;
+ case 12:
+ /* 3 SGMII - 460GT */
+ bis->bi_phymode[0] = BI_PHYMODE_SGMII;
+ bis->bi_phymode[1] = BI_PHYMODE_SGMII;
+ bis->bi_phymode[2] = BI_PHYMODE_SGMII;
+ bis->bi_phymode[3] = BI_PHYMODE_NONE;
+ break;
default:
break;
}
@@ -945,6 +1017,48 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
out_be32((void *)EMAC_M1 + hw_p->hw_addr, mode_reg);
#endif /* defined(CONFIG_440GX) || defined(CONFIG_440SP) */
+#if defined(CONFIG_GPCS_PHY_ADDR) || defined(CONFIG_GPCS_PHY1_ADDR) || \
+ defined(CONFIG_GPCS_PHY2_ADDR) || defined(CONFIG_GPCS_PHY3_ADDR)
+ if (bis->bi_phymode[devnum] == BI_PHYMODE_SGMII) {
+ /*
+ * In SGMII mode, GPCS access is needed for
+ * communication with the internal SGMII SerDes.
+ */
+ switch (devnum) {
+#if defined(CONFIG_GPCS_PHY_ADDR)
+ case 0:
+ reg = CONFIG_GPCS_PHY_ADDR;
+ break;
+#endif
+#if defined(CONFIG_GPCS_PHY1_ADDR)
+ case 1:
+ reg = CONFIG_GPCS_PHY1_ADDR;
+ break;
+#endif
+#if defined(CONFIG_GPCS_PHY2_ADDR)
+ case 2:
+ reg = CONFIG_GPCS_PHY2_ADDR;
+ break;
+#endif
+#if defined(CONFIG_GPCS_PHY3_ADDR)
+ case 3:
+ reg = CONFIG_GPCS_PHY3_ADDR;
+ break;
+#endif
+ }
+
+ mode_reg = in_be32((void *)EMAC_M1 + hw_p->hw_addr);
+ mode_reg |= EMAC_M1_MF_1000GPCS | EMAC_M1_IPPA_SET(reg);
+ out_be32((void *)EMAC_M1 + hw_p->hw_addr, mode_reg);
+
+ /* Configure GPCS interface to recommended setting for SGMII */
+ miiphy_reset(dev->name, reg);
+ miiphy_write(dev->name, reg, 0x04, 0x8120); /* AsymPause, FDX */
+ miiphy_write(dev->name, reg, 0x07, 0x2801); /* msg_pg, toggle */
+ miiphy_write(dev->name, reg, 0x00, 0x0140); /* 1Gbps, FDX */
+ }
+#endif /* defined(CONFIG_GPCS_PHY_ADDR) */
+
/* wait for PHY to complete auto negotiation */
reg_short = 0;
#ifndef CONFIG_CS8952_PHY
@@ -974,6 +1088,9 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
bis->bi_phynum[devnum] = reg;
+ if (reg == CONFIG_PHY_LESS)
+ goto get_speed;
+
#if defined(CONFIG_PHY_RESET)
/*
* Reset the phy, only if its the first time through
@@ -986,6 +1103,33 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
miiphy_write (dev->name, reg, 0x09, 0x0e00);
miiphy_write (dev->name, reg, 0x04, 0x01e1);
#endif
+#if defined(CONFIG_M88E1112_PHY)
+ if (bis->bi_phymode[devnum] == BI_PHYMODE_SGMII) {
+ /*
+ * Marvell 88E1112 PHY needs to have the SGMII MAC
+ * interace (page 2) properly configured to
+ * communicate with the 460EX/GT GPCS interface.
+ */
+
+ /* Set access to Page 2 */
+ miiphy_write(dev->name, reg, 0x16, 0x0002);
+
+ miiphy_write(dev->name, reg, 0x00, 0x0040); /* 1Gbps */
+ miiphy_read(dev->name, reg, 0x10, ®_short);
+ reg_short &= ~0x0C00; /* Preferred Media MASK */
+ reg_short |= 0x0800; /* Preferred Media Copper */
+ reg_short &= ~0x0380; /* Mode Select MASK */
+ reg_short |= 0x0280; /* Mode Select Copper only */
+ miiphy_write(dev->name, reg, 0x10, reg_short);
+ miiphy_read(dev->name, reg, 0x1a, ®_short);
+ reg_short |= 0x8000; /* bypass Auto-Negotiation */
+ miiphy_write(dev->name, reg, 0x1a, reg_short);
+ miiphy_reset(dev->name, reg); /* reset MAC interface */
+
+ /* Reset access to Page 0 */
+ miiphy_write(dev->name, reg, 0x16, 0x0000);
+ }
+#endif /* defined(CONFIG_M88E1112_PHY) */
miiphy_reset (dev->name, reg);
#if defined(CONFIG_440GX) || \
@@ -1080,8 +1224,22 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
}
#endif /* #ifndef CONFIG_CS8952_PHY */
- speed = miiphy_speed (dev->name, reg);
- duplex = miiphy_duplex (dev->name, reg);
+get_speed:
+ if (reg == CONFIG_PHY_LESS) {
+ speed = DFLT_PHY_LESS_SPEED;
+ duplex = DFLT_PHY_LESS_DUPLEX;
+
+ for (i = 0; i < ARRAY_SIZE(phy_less_port); i++) {
+ if (devnum == phy_less_port[i].devnum) {
+ speed = phy_less_port[i].speed;
+ duplex = phy_less_port[i].duplex;
+ break;
+ }
+ }
+ } else {
+ speed = miiphy_speed(dev->name, reg);
+ duplex = miiphy_duplex(dev->name, reg);
+ }
if (hw_p->print_speed) {
hw_p->print_speed = 0;
diff --git a/cpu/ppc4xx/miiphy.c b/cpu/ppc4xx/miiphy.c
index c882720..d303598 100644
--- a/cpu/ppc4xx/miiphy.c
+++ b/cpu/ppc4xx/miiphy.c
@@ -180,8 +180,10 @@ int phy_setup_aneg (char *devname, unsigned char addr)
*
* sr: Currently on 460EX only EMAC0 works with MDIO, so we always
* return EMAC0 offset here
+ * vg: For 460EX/460GT if internal GPCS PHY address is specified
+ * return appropriate EMAC offset
*/
-unsigned int miiphy_getemac_offset (void)
+unsigned int miiphy_getemac_offset(u8 addr)
{
#if (defined(CONFIG_440) && \
!defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
@@ -233,6 +235,39 @@ unsigned int miiphy_getemac_offset (void)
return 0x100;
#endif
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ u32 mode_reg;
+ u32 eoffset = 0;
+
+ switch (addr) {
+#if defined(CONFIG_HAS_ETH1) && defined(CONFIG_GPCS_PHY1_ADDR)
+ case CONFIG_GPCS_PHY1_ADDR:
+ mode_reg = in_be32((void *)EMAC_M1 + 0x100);
+ if (addr == EMAC_M1_IPPA_GET(mode_reg))
+ eoffset = 0x100;
+ break;
+#endif
+#if defined(CONFIG_HAS_ETH2) && defined(CONFIG_GPCS_PHY2_ADDR)
+ case CONFIG_GPCS_PHY2_ADDR:
+ mode_reg = in_be32((void *)EMAC_M1 + 0x300);
+ if (addr == EMAC_M1_IPPA_GET(mode_reg))
+ eoffset = 0x300;
+ break;
+#endif
+#if defined(CONFIG_HAS_ETH3) && defined(CONFIG_GPCS_PHY3_ADDR)
+ case CONFIG_GPCS_PHY3_ADDR:
+ mode_reg = in_be32((void *)EMAC_M1 + 0x400);
+ if (addr == EMAC_M1_IPPA_GET(mode_reg))
+ eoffset = 0x400;
+ break;
+#endif
+ default:
+ eoffset = 0;
+ break;
+ }
+ return eoffset;
+#endif
+
return 0;
#endif
}
@@ -262,7 +297,7 @@ static int emac_miiphy_command(u8 addr, u8 reg, int cmd, u16 value)
u32 emac_reg;
u32 sta_reg;
- emac_reg = miiphy_getemac_offset();
+ emac_reg = miiphy_getemac_offset(addr);
/* wait for completion */
if (emac_miiphy_wait(emac_reg) != 0)
@@ -311,7 +346,7 @@ int emac4xx_miiphy_read (char *devname, unsigned char addr, unsigned char reg,
unsigned long sta_reg;
unsigned long emac_reg;
- emac_reg = miiphy_getemac_offset ();
+ emac_reg = miiphy_getemac_offset(addr);
if (emac_miiphy_command(addr, reg, EMAC_STACR_READ, 0) != 0)
return -1;
diff --git a/include/ppc4xx_enet.h b/include/ppc4xx_enet.h
index b74c6fc..00669a7 100644
--- a/include/ppc4xx_enet.h
+++ b/include/ppc4xx_enet.h
@@ -376,6 +376,7 @@ typedef struct emac_4xx_hw_st {
#define EMAC_M1_APP (0x08000000)
#define EMAC_M1_RSVD (0x06000000)
#define EMAC_M1_IST (0x01000000)
+#define EMAC_M1_MF_1000GPCS (0x00C00000)
#define EMAC_M1_MF_1000MBPS (0x00800000) /* 0's for 10MBPS */
#define EMAC_M1_MF_100MBPS (0x00400000)
#define EMAC_M1_RFS_MASK (0x00380000)
@@ -394,6 +395,8 @@ typedef struct emac_4xx_hw_st {
#define EMAC_M1_MWSW (0x00007000)
#define EMAC_M1_JUMBO_ENABLE (0x00000800)
#define EMAC_M1_IPPA (0x000007c0)
+#define EMAC_M1_IPPA_SET(id) (((id) & 0x1f) << 6)
+#define EMAC_M1_IPPA_GET(id) (((id) >> 6) & 0x1f)
#define EMAC_M1_OBCI_GT100 (0x00000020)
#define EMAC_M1_OBCI_100 (0x00000018)
#define EMAC_M1_OBCI_83 (0x00000010)
--
1.5.5
3
7

04 Sep '08
Hi Pedro,
the SourceForge mailing list is deprecated, please use the one at
lists.denx.de.
[This time, the new address is correct]
> The u-boot version I'm using is 1.3.1 (self compiled) and Linux Kernel 2.6.23.1.
>
> It is possible to boot it with a stored kernel uImage and the oftree in the flash using a nfs filesystem,
> but I can't not boot it using the jffs2 image.
> I've read a lot of documentation from denx.de and this is my configuration at the moment:
>
> mtdparts=mtdparts=TQM5200-0:512k(uboot),256k(environment),3328k(kernel),20m(jffs2),256k(oftree)
> bootargs_mtd=setenv bootargs ${bootargs} ${mtdparts}
> bootargs_flash=setenv bootargs ${bootargs} root=/dev/mtdblock4 rw rootfstype=jffs2
> (even tried with root=/dev/mtdblock3, I'm not sure if 0 counts or not)
> bootargs_base=setenv bootargs console=ttyPSC0,115200
> bootcmd_flash=run bootargs_base bootargs_flash bootargs_mtd;bootm fC0C0000 – fD800000
>
> I've defined the partitions myself and double checked the numbers, first myself, then using the mtdparts command.
> The kernel image, oftree, and jffs2 filesystem are stored in the flash.
> The problem comes at booting. Even when "root=/dev/mtdblock4 rw rootfstype=jffs2" is passed to the kernel,
> it always tries to boot from a Ramdisk image. This is the output when I run bootcmd_flash command:
>
> => run bootcmd_flash
> ## Booting image at fc0c0000 ...
> Image Name: Linux-2.6.23.1-rt5-pcm030-1trunk
> Created: 2008-09-02 11:48:23 UTC
> Image Type: PowerPC Linux Kernel Image (gzip compressed)
> Data Size: 1534856 Bytes = 1.5 MB
> Load Address: 00000000
> Entry Point: 00000000
> Verifying Checksum ... OK
> Uncompressing Kernel Image ... OK
> ## Loading RAMDisk Image at 00000000 ...
> Bad Magic Number
>
> It seems to me that U-boot is trying to boot from RAMDisk instead of booting the kernel, but I'm not sure.
Yes, indeed. It looks like the "bootm fc0c0000 - fd800000" is not
evaluated properly. In v1.3.1 code the code lines were
(common/cmd_bootm.c:622)
#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)
/* Look for a '-' which indicates to ignore the ramdisk argument
*/
if (argc >= 3 && strcmp(argv[2], "-") == 0) {
debug ("Skipping initrd\n");
len = data = 0;
}
else
#endif
So The upstream v1.3.1 config for TQM5200 also has CONFIG_OF_LIBFDT
defined:
$ git-show v1.3.1:include/configs/TQM5200.h | grep CONFIG_OF_LIBFDT
#define CONFIG_OF_LIBFDT 1
So if you did not change that, my last explanation is that you have
hidden escape characters in the definition of bootcmd_flash. Check with
'md' on the environment sectors to find out.
Cheers
Detlev
--
Shin: a device for finding furniture in the dark.
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-40 Fax: (+49)-8142-66989-80 Email: dzu(a)denx.de
1
0
Add support for environment in NAND with automatic NOR / NAND recognition,
including unaligned environment, bad-block skipping, redundant environment
copy.
Signed-off-by: Guennadi Liakhovetski <lg(a)denx.de>
---
Changes since v1: multiple style updates, added Copyright, restored
flash_io() function, fixed NAND flag handling. Thanks for all the
comments.
diff --git a/tools/env/README b/tools/env/README
index f8a644e..91e679a 100644
--- a/tools/env/README
+++ b/tools/env/README
@@ -22,9 +22,11 @@ following lines are relevant:
#define DEVICE1_OFFSET 0x0000
#define ENV1_SIZE 0x4000
#define DEVICE1_ESIZE 0x4000
+#define DEVICE1_ENVSECTORS 2
#define DEVICE2_OFFSET 0x0000
#define ENV2_SIZE 0x4000
#define DEVICE2_ESIZE 0x4000
+#define DEVICE2_ENVSECTORS 2
Current configuration matches the environment layout of the TRAB
board.
@@ -46,3 +48,7 @@ then 1 sector.
DEVICEx_ESIZE defines the size of the first sector in the flash
partition where the environment resides.
+
+DEVICEx_ENVSECTORS defines the number of sectors that may be used for
+this environment instance. On NAND this is used to limit the range
+within which bad blocks are skipped, on NOR it is not used.
diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c
index e4fc02d..b6036c8 100644
--- a/tools/env/fw_env.c
+++ b/tools/env/fw_env.c
@@ -2,6 +2,9 @@
* (C) Copyright 2000-2008
* Wolfgang Denk, DENX Software Engineering, wd(a)denx.de.
*
+ * (C) Copyright 2008
+ * Guennadi Liakhovetski, DENX Software Engineering, lg(a)denx.de.
+ *
* See file CREDITS for list of people who contributed to this
* project.
*
@@ -45,36 +48,75 @@
#define CMD_GETENV "fw_printenv"
#define CMD_SETENV "fw_setenv"
-typedef struct envdev_s {
+#define min(x, y) ({ \
+ typeof(x) _min1 = (x); \
+ typeof(y) _min2 = (y); \
+ (void) (&_min1 == &_min2); \
+ _min1 < _min2 ? _min1 : _min2; })
+
+struct envdev_s {
char devname[16]; /* Device name */
ulong devoff; /* Device offset */
ulong env_size; /* environment size */
ulong erase_size; /* device erase size */
-} envdev_t;
+ ulong env_sectors; /* number of environment sectors */
+ uint8_t mtd_type; /* type of the MTD device */
+};
-static envdev_t envdevices[2];
-static int curdev;
+static struct envdev_s envdevices[2] =
+{
+ {
+ .mtd_type = MTD_ABSENT,
+ }, {
+ .mtd_type = MTD_ABSENT,
+ },
+};
+static int dev_current;
#define DEVNAME(i) envdevices[(i)].devname
#define DEVOFFSET(i) envdevices[(i)].devoff
#define ENVSIZE(i) envdevices[(i)].env_size
#define DEVESIZE(i) envdevices[(i)].erase_size
+#define ENVSECTORS(i) envdevices[(i)].env_sectors
+#define DEVTYPE(i) envdevices[(i)].mtd_type
-#define CFG_ENV_SIZE ENVSIZE(curdev)
+#define CFG_ENV_SIZE ENVSIZE(dev_current)
#define ENV_SIZE getenvsize()
-typedef struct environment_s {
- ulong crc; /* CRC32 over data bytes */
- unsigned char flags; /* active or obsolete */
- char *data;
-} env_t;
+struct env_image_single {
+ uint32_t crc; /* CRC32 over data bytes */
+ char data[];
+};
-static env_t environment;
+struct env_image_redundant {
+ uint32_t crc; /* CRC32 over data bytes */
+ unsigned char flags; /* active or obsolete */
+ char data[];
+};
+
+enum flag_scheme {
+ FLAG_NONE,
+ FLAG_BOOLEAN,
+ FLAG_INCREMENTAL,
+};
+
+struct environment {
+ void *image;
+ uint32_t *crc;
+ unsigned char *flags;
+ char *data;
+ enum flag_scheme flag_scheme;
+};
+
+static struct environment environment = {
+ .flag_scheme = FLAG_NONE,
+};
static int HaveRedundEnv = 0;
static unsigned char active_flag = 1;
+/* obsolete_flag must be 0 to efficiently set it on NOR flash without erasing */
static unsigned char obsolete_flag = 0;
@@ -157,7 +199,7 @@ static char default_environment[] = {
#ifdef CONFIG_EXTRA_ENV_SETTINGS
CONFIG_EXTRA_ENV_SETTINGS
#endif
- "\0" /* Termimate env_t data with 2 NULs */
+ "\0" /* Termimate struct environment data with 2 NULs */
};
static int flash_io (int mode);
@@ -186,7 +228,7 @@ char *fw_getenv (char *name)
char *env, *nxt;
if (env_init ())
- return (NULL);
+ return NULL;
for (env = environment.data; *env; env = nxt + 1) {
char *val;
@@ -195,15 +237,15 @@ char *fw_getenv (char *name)
if (nxt >= &environment.data[ENV_SIZE]) {
fprintf (stderr, "## Error: "
"environment not terminated\n");
- return (NULL);
+ return NULL;
}
}
val = envmatch (name, env);
if (!val)
continue;
- return (val);
+ return val;
}
- return (NULL);
+ return NULL;
}
/*
@@ -217,7 +259,7 @@ int fw_printenv (int argc, char *argv[])
int rc = 0;
if (env_init ())
- return (-1);
+ return -1;
if (argc == 1) { /* Print all env variables */
for (env = environment.data; *env; env = nxt + 1) {
@@ -225,13 +267,13 @@ int fw_printenv (int argc, char *argv[])
if (nxt >= &environment.data[ENV_SIZE]) {
fprintf (stderr, "## Error: "
"environment not terminated\n");
- return (-1);
+ return -1;
}
}
printf ("%s\n", env);
}
- return (0);
+ return 0;
}
if (strcmp (argv[1], "-n") == 0) {
@@ -241,7 +283,7 @@ int fw_printenv (int argc, char *argv[])
if (argc != 2) {
fprintf (stderr, "## Error: "
"`-n' option requires exactly one argument\n");
- return (-1);
+ return -1;
}
} else {
n_flag = 0;
@@ -257,7 +299,7 @@ int fw_printenv (int argc, char *argv[])
if (nxt >= &environment.data[ENV_SIZE]) {
fprintf (stderr, "## Error: "
"environment not terminated\n");
- return (-1);
+ return -1;
}
}
val = envmatch (name, env);
@@ -276,11 +318,11 @@ int fw_printenv (int argc, char *argv[])
}
}
- return (rc);
+ return rc;
}
/*
- * Deletes or sets environment variables. Returns errno style error codes:
+ * Deletes or sets environment variables. Returns -1 and sets errno error codes:
* 0 - OK
* EINVAL - need at least 1 argument
* EROFS - certain variables ("ethaddr", "serial#") cannot be
@@ -295,11 +337,12 @@ int fw_setenv (int argc, char *argv[])
char *name;
if (argc < 2) {
- return (EINVAL);
+ errno = EINVAL;
+ return -1;
}
if (env_init ())
- return (errno);
+ return -1;
name = argv[1];
@@ -311,7 +354,8 @@ int fw_setenv (int argc, char *argv[])
if (nxt >= &environment.data[ENV_SIZE]) {
fprintf (stderr, "## Error: "
"environment not terminated\n");
- return (EINVAL);
+ errno = EINVAL;
+ return -1;
}
}
if ((oldval = envmatch (name, env)) != NULL)
@@ -328,7 +372,8 @@ int fw_setenv (int argc, char *argv[])
if ((strcmp (name, "ethaddr") == 0) ||
(strcmp (name, "serial#") == 0)) {
fprintf (stderr, "Can't overwrite \"%s\"\n", name);
- return (EROFS);
+ errno = EROFS;
+ return -1;
}
if (*++nxt == '\0') {
@@ -367,7 +412,7 @@ int fw_setenv (int argc, char *argv[])
fprintf (stderr,
"Error: environment overflow, \"%s\" deleted\n",
name);
- return (-1);
+ return -1;
}
while ((*env = *name++) != '\0')
env++;
@@ -383,195 +428,430 @@ int fw_setenv (int argc, char *argv[])
WRITE_FLASH:
- /* Update CRC */
- environment.crc = crc32 (0, (uint8_t*) environment.data, ENV_SIZE);
+ /*
+ * Update CRC
+ */
+ *environment.crc = crc32 (0, (uint8_t *) environment.data, ENV_SIZE);
/* write environment back to flash */
if (flash_io (O_RDWR)) {
fprintf (stderr, "Error: can't write fw_env to flash\n");
- return (-1);
+ return -1;
}
- return (0);
+ return 0;
}
-static int flash_io (int mode)
+/*
+ * Test for bad block on NAND, just returns 0 on NOR, on NAND:
+ * 0 - block is good
+ * > 0 - block is bad
+ * < 0 - failed to test
+ */
+static int flash_bad_block (int fd, uint8_t mtd_type, loff_t *blockstart)
{
- int fd, fdr, rc, otherdev, len, resid;
- struct erase_info_user erase;
- char *data = NULL;
+ if (mtd_type == MTD_NANDFLASH) {
+ int badblock = ioctl (fd, MEMGETBADBLOCK, blockstart);
- if ((fd = open (DEVNAME (curdev), mode)) < 0) {
- fprintf (stderr,
- "Can't open %s: %s\n",
- DEVNAME (curdev), strerror (errno));
- return (-1);
+ if (badblock < 0) {
+ perror ("Cannot read bad block mark");
+ return badblock;
+ }
+
+ if (badblock) {
+#ifdef DEBUG
+ fprintf (stderr, "Bad block at 0x%llx, "
+ "skipping\n", *blockstart);
+#endif
+ return badblock;
+ }
}
- len = sizeof (environment.crc);
- if (HaveRedundEnv) {
- len += sizeof (environment.flags);
+ return 0;
+}
+
+/*
+ * Read data from flash at an offset into a provided buffer. On NAND it skips
+ * bad blocks but makes sure it stays within ENVSECTORS (dev) starting from
+ * the DEVOFFSET (dev) block. On NOR the loop is only run once.
+ */
+static int flash_read_buf (int dev, int fd, void *buf, size_t count,
+ off_t offset, uint8_t mtd_type)
+{
+ size_t blocklen; /* erase / write length - one block on NAND,
+ 0 on NOR */
+ size_t processed = 0; /* progress counter */
+ size_t readlen = count; /* current read length */
+ off_t top_of_range; /* end of the last block we may use */
+ off_t block_seek; /* offset inside the current block to the start
+ of the data */
+ loff_t blockstart; /* running start of the current block -
+ MEMGETBADBLOCK needs 64 bits */
+ int rc;
+
+ /*
+ * Start of the first block to be read, relies on the fact, that
+ * erase sector size is always a power of 2
+ */
+ blockstart = offset & ~(DEVESIZE (dev) - 1);
+
+ /* Offset inside a block */
+ block_seek = offset - blockstart;
+
+ if (mtd_type == MTD_NANDFLASH) {
+ /*
+ * NAND: calculate which blocks we are reading. We have
+ * to read one block at a time to skip bad blocks.
+ */
+ blocklen = DEVESIZE (dev);
+
+ /*
+ * To calculate the top of the range, we have to use the
+ * global DEVOFFSET (dev), which can be different from offset
+ */
+ top_of_range = (DEVOFFSET (dev) & ~(blocklen - 1)) +
+ ENVSECTORS (dev) * blocklen;
+
+ /* Limit to one block for the first read */
+ if (readlen > blocklen - block_seek)
+ readlen = blocklen - block_seek;
+ } else {
+ blocklen = 0;
+ top_of_range = offset + count;
}
- if (mode == O_RDWR) {
- if (HaveRedundEnv) {
- /* switch to next partition for writing */
- otherdev = !curdev;
- if ((fdr = open (DEVNAME (otherdev), mode)) < 0) {
- fprintf (stderr,
- "Can't open %s: %s\n",
- DEVNAME (otherdev),
- strerror (errno));
- return (-1);
- }
- } else {
- otherdev = curdev;
- fdr = fd;
- }
- printf ("Unlocking flash...\n");
- erase.length = DEVESIZE (otherdev);
- erase.start = DEVOFFSET (otherdev);
- ioctl (fdr, MEMUNLOCK, &erase);
+ /* This only runs once on NOR flash */
+ while (processed < count) {
+ rc = flash_bad_block (fd, mtd_type, &blockstart);
+ if (rc < 0) /* block test failed */
+ return -1;
- if (HaveRedundEnv) {
- erase.length = DEVESIZE (curdev);
- erase.start = DEVOFFSET (curdev);
- ioctl (fd, MEMUNLOCK, &erase);
- environment.flags = active_flag;
+ if (blockstart + block_seek + readlen > top_of_range) {
+ /* End of range is reached */
+ fprintf (stderr,
+ "Too few good blocks within range\n");
+ return -1;
}
- printf ("Done\n");
- resid = DEVESIZE (otherdev) - CFG_ENV_SIZE;
- if (resid) {
- if ((data = malloc (resid)) == NULL) {
- fprintf (stderr,
- "Cannot malloc %d bytes: %s\n",
- resid,
- strerror (errno));
- return (-1);
- }
- if (lseek (fdr, DEVOFFSET (otherdev) + CFG_ENV_SIZE, SEEK_SET)
- == -1) {
- fprintf (stderr, "seek error on %s: %s\n",
- DEVNAME (otherdev),
- strerror (errno));
- return (-1);
- }
- if ((rc = read (fdr, data, resid)) != resid) {
- fprintf (stderr,
- "read error on %s: %s\n",
- DEVNAME (otherdev),
- strerror (errno));
- return (-1);
- }
+ if (rc) { /* block is bad */
+ blockstart += blocklen;
+ continue;
}
- printf ("Erasing old environment...\n");
+ /*
+ * If a block is bad, we retry in the next block at the same
+ * offset - see common/env_nand.c::writeenv()
+ */
+ lseek (fd, blockstart + block_seek, SEEK_SET);
- erase.length = DEVESIZE (otherdev);
- erase.start = DEVOFFSET (otherdev);
- if (ioctl (fdr, MEMERASE, &erase) != 0) {
- fprintf (stderr, "MTD erase error on %s: %s\n",
- DEVNAME (otherdev),
- strerror (errno));
- return (-1);
+ rc = read (fd, buf + processed, readlen);
+ if (rc != readlen) {
+ fprintf (stderr, "Read error on %s: %s\n",
+ DEVNAME (dev), strerror (errno));
+ return -1;
}
+#ifdef DEBUG
+ fprintf (stderr, "Read 0x%x bytes at 0x%llx\n",
+ rc, blockstart + block_seek);
+#endif
+ processed += readlen;
+ readlen = min (blocklen, count - processed);
+ block_seek = 0;
+ blockstart += blocklen;
+ }
+
+ return processed;
+}
+
+/*
+ * Write count bytes at offset, but stay within ENVSETCORS (dev) sectors of
+ * DEVOFFSET (dev). Similar to the read case above, on NOR we erase and write
+ * the whole data at once.
+ */
+static int flash_write_buf (int dev, int fd, void *buf, size_t count,
+ off_t offset, uint8_t mtd_type)
+{
+ void *data;
+ struct erase_info_user erase;
+ size_t blocklen; /* length of NAND block / NOR erase sector */
+ size_t erase_len; /* whole area that can be erased - may include
+ bad blocks */
+ size_t erasesize; /* erase / write length - one block on NAND,
+ whole area on NOR */
+ size_t processed = 0; /* progress counter */
+ size_t write_total; /* total size to actually write - excludinig
+ bad blocks */
+ off_t erase_offset; /* offset to the first erase block (aligned)
+ below offset */
+ off_t block_seek; /* offset inside the erase block to the start
+ of the data */
+ off_t top_of_range; /* end of the last block we may use */
+ loff_t blockstart; /* running start of the current block -
+ MEMGETBADBLOCK needs 64 bits */
+ int rc;
+
+ blocklen = DEVESIZE (dev);
+
+ /* Erase sector size is always a power of 2 */
+ top_of_range = (DEVOFFSET (dev) & ~(blocklen - 1)) +
+ ENVSECTORS (dev) * blocklen;
- printf ("Done\n");
+ erase_offset = offset & ~(blocklen - 1);
- printf ("Writing environment to %s...\n", DEVNAME (otherdev));
- if (lseek (fdr, DEVOFFSET (otherdev), SEEK_SET) == -1) {
+ /* Maximum area we may use */
+ erase_len = top_of_range - erase_offset;
+
+ blockstart = erase_offset;
+ /* Offset inside a block */
+ block_seek = offset - erase_offset;
+
+ /*
+ * Data size we actually have to write: from the start of the block
+ * to the start of the data, then count bytes of data, and to the
+ * end of the block
+ */
+ write_total = (block_seek + count + blocklen - 1) & ~(blocklen - 1);
+
+ /*
+ * Support data anywhere within erase sectors: read out the complete
+ * area to be erased, replace the environment image, write the whole
+ * block back again.
+ */
+ if (write_total > count) {
+ data = malloc (erase_len);
+ if (!data) {
fprintf (stderr,
- "seek error on %s: %s\n",
- DEVNAME (otherdev), strerror (errno));
- return (-1);
+ "Cannot malloc %u bytes: %s\n",
+ erase_len, strerror (errno));
+ return -1;
}
- if (write (fdr, &environment, len) != len) {
- fprintf (stderr,
- "CRC write error on %s: %s\n",
- DEVNAME (otherdev), strerror (errno));
- return (-1);
+
+ rc = flash_read_buf (dev, fd, data, write_total, erase_offset,
+ mtd_type);
+ if (write_total != rc)
+ return -1;
+
+ /* Overwrite the old environment */
+ memcpy (data + block_seek, buf, count);
+ } else {
+ /*
+ * We get here, iff offset is block-aligned and count is a
+ * multiple of blocklen - see write_total calculation above
+ */
+ data = buf;
+ }
+
+ if (mtd_type == MTD_NANDFLASH) {
+ /*
+ * NAND: calculate which blocks we are writing. We have
+ * to write one block at a time to skip bad blocks.
+ */
+ erasesize = blocklen;
+ } else {
+ erasesize = erase_len;
+ }
+
+ erase.length = erasesize;
+
+ /* This only runs once on NOR flash */
+ while (processed < write_total) {
+ rc = flash_bad_block (fd, mtd_type, &blockstart);
+ if (rc < 0) /* block test failed */
+ return rc;
+
+ if (blockstart + erasesize > top_of_range) {
+ fprintf (stderr, "End of range reached, aborting\n");
+ return -1;
}
- if (write (fdr, environment.data, ENV_SIZE) != ENV_SIZE) {
+
+ if (rc) { /* block is bad */
+ blockstart += blocklen;
+ continue;
+ }
+
+ erase.start = blockstart;
+ ioctl (fd, MEMUNLOCK, &erase);
+
+ if (ioctl (fd, MEMERASE, &erase) != 0) {
+ fprintf (stderr, "MTD erase error on %s: %s\n",
+ DEVNAME (dev),
+ strerror (errno));
+ return -1;
+ }
+
+ if (lseek (fd, blockstart, SEEK_SET) == -1) {
fprintf (stderr,
- "Write error on %s: %s\n",
- DEVNAME (otherdev), strerror (errno));
- return (-1);
+ "Seek error on %s: %s\n",
+ DEVNAME (dev), strerror (errno));
+ return -1;
}
- if (resid) {
- if (write (fdr, data, resid) != resid) {
- fprintf (stderr,
- "write error on %s: %s\n",
- DEVNAME (curdev), strerror (errno));
- return (-1);
- }
- free (data);
+
+#ifdef DEBUG
+ printf ("Write 0x%x bytes at 0x%llx\n", erasesize, blockstart);
+#endif
+ if (write (fd, data + processed, erasesize) != erasesize) {
+ fprintf (stderr, "Write error on %s: %s\n",
+ DEVNAME (dev), strerror (errno));
+ return -1;
}
+
+ ioctl (fd, MEMLOCK, &erase);
+
+ processed += blocklen;
+ block_seek = 0;
+ blockstart += blocklen;
+ }
+
+ if (write_total > count)
+ free (data);
+
+ return processed;
+}
+
+/*
+ * Set obsolete flag at offset - NOR flash only
+ */
+static int flash_flag_obsolete (int dev, int fd, off_t offset)
+{
+ int rc;
+
+ /* This relies on the fact, that obsolete_flag == 0 */
+ rc = lseek (fd, offset, SEEK_SET);
+ if (rc < 0) {
+ fprintf (stderr, "Cannot seek to set the flag on %s \n",
+ DEVNAME (dev));
+ return rc;
+ }
+ rc = write (fd, &obsolete_flag, sizeof (obsolete_flag));
+ if (rc < 0)
+ perror ("Could not set obsolete flag");
+
+ return rc;
+}
+
+static int flash_write (int fd_current, int fd_target, int dev_target)
+{
+ int rc;
+
+ switch (environment.flag_scheme) {
+ case FLAG_NONE:
+ break;
+ case FLAG_INCREMENTAL:
+ (*environment.flags)++;
+ break;
+ case FLAG_BOOLEAN:
+ *environment.flags = active_flag;
+ break;
+ default:
+ fprintf (stderr, "Unimplemented flash scheme %u \n",
+ environment.flag_scheme);
+ return -1;
+ }
+
+#ifdef DEBUG
+ printf ("Writing new environment at 0x%lx on %s\n",
+ DEVOFFSET (dev_target), DEVNAME (dev_target));
+#endif
+ rc = flash_write_buf (dev_target, fd_target, environment.image,
+ CFG_ENV_SIZE, DEVOFFSET (dev_target),
+ DEVTYPE(dev_target));
+ if (rc < 0)
+ return rc;
+
+ if (environment.flag_scheme == FLAG_BOOLEAN) {
+ /* Have to set obsolete flag */
+ off_t offset = DEVOFFSET (dev_current) +
+ offsetof (struct env_image_redundant, flags);
+#ifdef DEBUG
+ printf ("Setting obsolete flag in environment at 0x%lx on %s\n",
+ DEVOFFSET (dev_current), DEVNAME (dev_current));
+#endif
+ flash_flag_obsolete (dev_current, fd_current, offset);
+ }
+
+ return 0;
+}
+
+static int flash_read (int fd)
+{
+ struct mtd_info_user mtdinfo;
+ int rc;
+
+ rc = ioctl (fd, MEMGETINFO, &mtdinfo);
+ if (rc < 0) {
+ perror ("Cannot get MTD information");
+ return -1;
+ }
+
+ if (mtdinfo.type != MTD_NORFLASH && mtdinfo.type != MTD_NANDFLASH) {
+ fprintf (stderr, "Unsupported flash type %u\n", mtdinfo.type);
+ return -1;
+ }
+
+ DEVTYPE(dev_current) = mtdinfo.type;
+
+ rc = flash_read_buf (dev_current, fd, environment.image, CFG_ENV_SIZE,
+ DEVOFFSET (dev_current), mtdinfo.type);
+
+ return (rc != CFG_ENV_SIZE) ? -1 : 0;
+}
+
+static int flash_io (int mode)
+{
+ int fd_current, fd_target, rc, dev_target;
+
+ /* dev_current: fd_current, erase_current */
+ fd_current = open (DEVNAME (dev_current), mode);
+ if (fd_current < 0) {
+ fprintf (stderr,
+ "Can't open %s: %s\n",
+ DEVNAME (dev_current), strerror (errno));
+ return -1;
+ }
+
+ if (mode == O_RDWR) {
if (HaveRedundEnv) {
- /* change flag on current active env partition */
- if (lseek (fd, DEVOFFSET (curdev) + sizeof (ulong), SEEK_SET)
- == -1) {
- fprintf (stderr, "seek error on %s: %s\n",
- DEVNAME (curdev), strerror (errno));
- return (-1);
- }
- if (write (fd, &obsolete_flag, sizeof (obsolete_flag)) !=
- sizeof (obsolete_flag)) {
+ /* switch to next partition for writing */
+ dev_target = !dev_current;
+ /* dev_target: fd_target, erase_target */
+ fd_target = open (DEVNAME (dev_target), mode);
+ if (fd_target < 0) {
fprintf (stderr,
- "Write error on %s: %s\n",
- DEVNAME (curdev), strerror (errno));
- return (-1);
+ "Can't open %s: %s\n",
+ DEVNAME (dev_target),
+ strerror (errno));
+ rc = -1;
+ goto exit;
}
+ } else {
+ dev_target = dev_current;
+ fd_target = fd_current;
}
- printf ("Done\n");
- printf ("Locking ...\n");
- erase.length = DEVESIZE (otherdev);
- erase.start = DEVOFFSET (otherdev);
- ioctl (fdr, MEMLOCK, &erase);
+
+ rc = flash_write (fd_current, fd_target, dev_target);
+
if (HaveRedundEnv) {
- erase.length = DEVESIZE (curdev);
- erase.start = DEVOFFSET (curdev);
- ioctl (fd, MEMLOCK, &erase);
- if (close (fdr)) {
+ if (close (fd_target)) {
fprintf (stderr,
"I/O error on %s: %s\n",
- DEVNAME (otherdev),
+ DEVNAME (dev_target),
strerror (errno));
- return (-1);
+ rc = -1;
}
}
- printf ("Done\n");
} else {
-
- if (lseek (fd, DEVOFFSET (curdev), SEEK_SET) == -1) {
- fprintf (stderr,
- "seek error on %s: %s\n",
- DEVNAME (curdev), strerror (errno));
- return (-1);
- }
- if (read (fd, &environment, len) != len) {
- fprintf (stderr,
- "CRC read error on %s: %s\n",
- DEVNAME (curdev), strerror (errno));
- return (-1);
- }
- if ((rc = read (fd, environment.data, ENV_SIZE)) != ENV_SIZE) {
- fprintf (stderr,
- "Read error on %s: %s\n",
- DEVNAME (curdev), strerror (errno));
- return (-1);
- }
+ rc = flash_read (fd_current);
}
- if (close (fd)) {
+exit:
+ if (close (fd_current)) {
fprintf (stderr,
- "I/O error on %s: %s\n",
- DEVNAME (curdev), strerror (errno));
- return (-1);
+ "I/O error on %s: %s\n",
+ DEVNAME (dev_current), strerror (errno));
+ return -1;
}
- /* everything ok */
- return (0);
+ return rc;
}
/*
@@ -585,10 +865,10 @@ static char *envmatch (char * s1, char * s2)
while (*s1 == *s2++)
if (*s1++ == '=')
- return (s2);
+ return s2;
if (*s1 == '\0' && *(s2 - 1) == '=')
- return (s2);
- return (NULL);
+ return s2;
+ return NULL;
}
/*
@@ -596,108 +876,156 @@ static char *envmatch (char * s1, char * s2)
*/
static int env_init (void)
{
+ int crc0, crc0_ok;
+ char flag0;
+ void *addr0;
+
int crc1, crc1_ok;
- char *addr1;
+ char flag1;
+ void *addr1;
- int crc2, crc2_ok;
- char flag1, flag2, *addr2;
+ struct env_image_single *single;
+ struct env_image_redundant *redundant;
if (parse_config ()) /* should fill envdevices */
- return 1;
+ return -1;
- if ((addr1 = calloc (1, ENV_SIZE)) == NULL) {
+ addr0 = calloc (1, CFG_ENV_SIZE);
+ if (addr0 == NULL) {
fprintf (stderr,
"Not enough memory for environment (%ld bytes)\n",
- ENV_SIZE);
- return (errno);
+ CFG_ENV_SIZE);
+ return -1;
}
/* read environment from FLASH to local buffer */
- environment.data = addr1;
- curdev = 0;
- if (flash_io (O_RDONLY)) {
- return (errno);
+ environment.image = addr0;
+
+ if (HaveRedundEnv) {
+ redundant = addr0;
+ environment.crc = &redundant->crc;
+ environment.flags = &redundant->flags;
+ environment.data = redundant->data;
+ } else {
+ single = addr0;
+ environment.crc = &single->crc;
+ environment.flags = NULL;
+ environment.data = single->data;
}
- crc1_ok = ((crc1 = crc32 (0, (uint8_t *) environment.data, ENV_SIZE))
- == environment.crc);
+ dev_current = 0;
+ if (flash_io (O_RDONLY))
+ return -1;
+
+ crc0 = crc32 (0, (uint8_t *) environment.data, ENV_SIZE);
+ crc0_ok = (crc0 == *environment.crc);
if (!HaveRedundEnv) {
- if (!crc1_ok) {
+ if (!crc0_ok) {
fprintf (stderr,
"Warning: Bad CRC, using default environment\n");
memcpy(environment.data, default_environment, sizeof default_environment);
}
} else {
- flag1 = environment.flags;
+ flag0 = *environment.flags;
- curdev = 1;
- if ((addr2 = calloc (1, ENV_SIZE)) == NULL) {
+ dev_current = 1;
+ addr1 = calloc (1, CFG_ENV_SIZE);
+ if (addr1 == NULL) {
fprintf (stderr,
"Not enough memory for environment (%ld bytes)\n",
- ENV_SIZE);
- return (errno);
+ CFG_ENV_SIZE);
+ return -1;
}
- environment.data = addr2;
+ redundant = addr1;
- if (flash_io (O_RDONLY)) {
- return (errno);
+ /*
+ * have to set environment.image for flash_read(), careful -
+ * other pointers in environment still point inside addr0
+ */
+ environment.image = addr1;
+ if (flash_io (O_RDONLY))
+ return -1;
+
+ /* Check flag scheme compatibility */
+ if (DEVTYPE(dev_current) == MTD_NORFLASH &&
+ DEVTYPE(!dev_current) == MTD_NORFLASH) {
+ environment.flag_scheme = FLAG_BOOLEAN;
+ } else if (DEVTYPE(dev_current) == MTD_NANDFLASH &&
+ DEVTYPE(!dev_current) == MTD_NANDFLASH) {
+ environment.flag_scheme = FLAG_INCREMENTAL;
+ } else {
+ fprintf (stderr, "Incompatible flash types!\n");
+ return -1;
}
- crc2_ok = ((crc2 = crc32 (0, (uint8_t *) environment.data, ENV_SIZE))
- == environment.crc);
- flag2 = environment.flags;
-
- if (crc1_ok && !crc2_ok) {
- environment.data = addr1;
- environment.flags = flag1;
- environment.crc = crc1;
- curdev = 0;
- free (addr2);
- } else if (!crc1_ok && crc2_ok) {
- environment.data = addr2;
- environment.flags = flag2;
- environment.crc = crc2;
- curdev = 1;
- free (addr1);
- } else if (!crc1_ok && !crc2_ok) {
+ crc1 = crc32 (0, (uint8_t *) redundant->data, ENV_SIZE);
+ crc1_ok = (crc1 == redundant->crc);
+ flag1 = redundant->flags;
+
+ if (crc0_ok && !crc1_ok) {
+ dev_current = 0;
+ } else if (!crc0_ok && crc1_ok) {
+ dev_current = 1;
+ } else if (!crc0_ok && !crc1_ok) {
fprintf (stderr,
"Warning: Bad CRC, using default environment\n");
- memcpy(environment.data, default_environment, sizeof default_environment);
- curdev = 0;
- free (addr1);
- } else if (flag1 == active_flag && flag2 == obsolete_flag) {
- environment.data = addr1;
- environment.flags = flag1;
- environment.crc = crc1;
- curdev = 0;
- free (addr2);
- } else if (flag1 == obsolete_flag && flag2 == active_flag) {
- environment.data = addr2;
- environment.flags = flag2;
- environment.crc = crc2;
- curdev = 1;
- free (addr1);
- } else if (flag1 == flag2) {
- environment.data = addr1;
- environment.flags = flag1;
- environment.crc = crc1;
- curdev = 0;
- free (addr2);
- } else if (flag1 == 0xFF) {
- environment.data = addr1;
- environment.flags = flag1;
- environment.crc = crc1;
- curdev = 0;
- free (addr2);
- } else if (flag2 == 0xFF) {
- environment.data = addr2;
- environment.flags = flag2;
- environment.crc = crc2;
- curdev = 1;
+ memcpy (environment.data, default_environment,
+ sizeof default_environment);
+ dev_current = 0;
+ } else {
+ switch (environment.flag_scheme) {
+ case FLAG_BOOLEAN:
+ if (flag0 == active_flag &&
+ flag1 == obsolete_flag) {
+ dev_current = 0;
+ } else if (flag0 == obsolete_flag &&
+ flag1 == active_flag) {
+ dev_current = 1;
+ } else if (flag0 == flag1) {
+ dev_current = 0;
+ } else if (flag0 == 0xFF) {
+ dev_current = 0;
+ } else if (flag1 == 0xFF) {
+ dev_current = 1;
+ } else {
+ dev_current = 0;
+ }
+ break;
+ case FLAG_INCREMENTAL:
+ if ((flag0 == 255 && flag1 == 0) ||
+ flag1 > flag0)
+ dev_current = 1;
+ else if ((flag1 == 255 && flag0 == 0) ||
+ flag0 > flag1)
+ dev_current = 0;
+ else /* flags are equal - almost impossible */
+ dev_current = 0;
+ break;
+ default:
+ fprintf (stderr, "Unknown flag scheme %u \n",
+ environment.flag_scheme);
+ return -1;
+ }
+ }
+
+ /*
+ * If we are reading, we don't need the flag and the CRC any
+ * more, if we are writing, we will re-calculate CRC and update
+ * flags before writing out
+ */
+ if (dev_current) {
+ environment.image = addr1;
+ environment.crc = &redundant->crc;
+ environment.flags = &redundant->flags;
+ environment.data = redundant->data;
+ free (addr0);
+ } else {
+ environment.image = addr0;
+ /* Other pointers are already set */
free (addr1);
}
}
- return (0);
+ return 0;
}
@@ -710,18 +1038,20 @@ static int parse_config ()
if (get_config (CONFIG_FILE)) {
fprintf (stderr,
"Cannot parse config file: %s\n", strerror (errno));
- return 1;
+ return -1;
}
#else
strcpy (DEVNAME (0), DEVICE1_NAME);
DEVOFFSET (0) = DEVICE1_OFFSET;
ENVSIZE (0) = ENV1_SIZE;
DEVESIZE (0) = DEVICE1_ESIZE;
+ ENVSECTORS (0) = DEVICE1_ENVSECTORS;
#ifdef HAVE_REDUND
strcpy (DEVNAME (1), DEVICE2_NAME);
DEVOFFSET (1) = DEVICE2_OFFSET;
ENVSIZE (1) = ENV2_SIZE;
DEVESIZE (1) = DEVICE2_ESIZE;
+ ENVSECTORS (1) = DEVICE2_ENVSECTORS;
HaveRedundEnv = 1;
#endif
#endif
@@ -729,14 +1059,14 @@ static int parse_config ()
fprintf (stderr,
"Cannot access MTD device %s: %s\n",
DEVNAME (0), strerror (errno));
- return 1;
+ return -1;
}
if (HaveRedundEnv && stat (DEVNAME (1), &st)) {
fprintf (stderr,
"Cannot access MTD device %s: %s\n",
DEVNAME (1), strerror (errno));
- return 1;
+ return -1;
}
return 0;
}
@@ -749,21 +1079,28 @@ static int get_config (char *fname)
int rc;
char dump[128];
- if ((fp = fopen (fname, "r")) == NULL) {
- return 1;
- }
-
- while ((i < 2) && ((rc = fscanf (fp, "%s %lx %lx %lx",
- DEVNAME (i),
- &DEVOFFSET (i),
- &ENVSIZE (i),
- &DEVESIZE (i) )) != EOF)) {
+ fp = fopen (fname, "r");
+ if (fp == NULL)
+ return -1;
+ while (i < 2 && fgets (dump, sizeof (dump), fp)) {
/* Skip incomplete conversions and comment strings */
- if ((rc < 3) || (*DEVNAME (i) == '#')) {
- fgets (dump, sizeof (dump), fp); /* Consume till end */
+ if (dump[0] == '#')
continue;
- }
+
+ rc = sscanf (dump, "%s %lx %lx %lx %lx",
+ DEVNAME (i),
+ &DEVOFFSET (i),
+ &ENVSIZE (i),
+ &DEVESIZE (i),
+ &ENVSECTORS (i));
+
+ if (rc < 4)
+ continue;
+
+ if (rc < 5)
+ /* Default - 1 sector */
+ ENVSECTORS (i) = 1;
i++;
}
@@ -772,7 +1109,7 @@ static int get_config (char *fname)
HaveRedundEnv = i - 1;
if (!i) { /* No valid entries found */
errno = EINVAL;
- return 1;
+ return -1;
} else
return 0;
}
diff --git a/tools/env/fw_env.config b/tools/env/fw_env.config
index 2432bd8..0fe37c9 100644
--- a/tools/env/fw_env.config
+++ b/tools/env/fw_env.config
@@ -1,7 +1,11 @@
# Configuration file for fw_(printenv/saveenv) utility.
# Up to two entries are valid, in this case the redundand
# environment sector is assumed present.
+# Notice, that the "Number of sectors" is ignored on NOR.
-# MTD device name Device offset Env. size Flash sector size
+# MTD device name Device offset Env. size Flash sector size Number of sectors
/dev/mtd1 0x0000 0x4000 0x4000
/dev/mtd2 0x0000 0x4000 0x4000
+
+# NAND example
+#/dev/mtd0 0x4000 0x4000 0x20000 2
1
0