[U-Boot] [PATCH 1/2] am43xx: Update EMIF DDR3 Configuration for AM43x GP

From: "Franklin S. Cooper Jr" fcooper@ti.com
* Boot failures have been discovered due to a combination of routing issues and non optimal ddr3 timings in the EMIF * Since ddr3 timings are different after significant board layout changes different timings are required for alpha, beta and production boards.
Signed-off-by: Franklin S. Cooper Jr fcooper@ti.com --- arch/arm/include/asm/arch-am33xx/omap.h | 2 + board/ti/am43xx/board.c | 101 +++++++++++++++++++++++++++++++ board/ti/am43xx/board.h | 11 ++++ 3 files changed, 114 insertions(+)
diff --git a/arch/arm/include/asm/arch-am33xx/omap.h b/arch/arm/include/asm/arch-am33xx/omap.h index 0855d16..e5c0b0d 100644 --- a/arch/arm/include/asm/arch-am33xx/omap.h +++ b/arch/arm/include/asm/arch-am33xx/omap.h @@ -29,6 +29,8 @@ #define SRAM_SCRATCH_SPACE_ADDR 0x40337C00 #define AM4372_BOARD_NAME_START SRAM_SCRATCH_SPACE_ADDR #define AM4372_BOARD_NAME_END SRAM_SCRATCH_SPACE_ADDR + 0xC +#define AM4372_BOARD_VERSION_START SRAM_SCRATCH_SPACE_ADDR + 0xD +#define AM4372_BOARD_VERSION_END SRAM_SCRATCH_SPACE_ADDR + 0x14 #define QSPI_BASE 0x47900000 #endif #endif diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c index 054a452..5eaa4a5 100644 --- a/board/ti/am43xx/board.c +++ b/board/ti/am43xx/board.c @@ -68,6 +68,9 @@ static int read_eeprom(struct am43xx_board_id *header) strncpy(am43xx_board_name, (char *)header->name, sizeof(header->name)); am43xx_board_name[sizeof(header->name)] = 0;
+ strncpy(am43xx_board_rev, (char *)header->version, sizeof(header->version)); + am43xx_board_rev[sizeof(header->version)] = 0; + return 0; }
@@ -217,6 +220,44 @@ const struct emif_regs ddr3_emif_regs_400Mhz = { .emif_rd_wr_exec_thresh = 0x00000405 };
+/* EMIF DDR3 Configurations are different for beta AM43X GP EVMs */ +const struct emif_regs ddr3_emif_regs_400Mhz_beta = { + .sdram_config = 0x638413B2, + .ref_ctrl = 0x00000C30, + .sdram_tim1 = 0xEAAAD4DB, + .sdram_tim2 = 0x266B7FDA, + .sdram_tim3 = 0x107F8678, + .read_idle_ctrl = 0x00050000, + .zq_config = 0x50074BE4, + .temp_alert_config = 0x0, + .emif_ddr_phy_ctlr_1 = 0x0E004008, + .emif_ddr_ext_phy_ctrl_1 = 0x08020080, + .emif_ddr_ext_phy_ctrl_2 = 0x00000065, + .emif_ddr_ext_phy_ctrl_3 = 0x00000091, + .emif_ddr_ext_phy_ctrl_4 = 0x000000B5, + .emif_ddr_ext_phy_ctrl_5 = 0x000000E5, + .emif_rd_wr_exec_thresh = 0x00000405 +}; + +/* EMIF DDR3 Configurations are different for production AM43X GP EVMs */ +const struct emif_regs ddr3_emif_regs_400Mhz_production = { + .sdram_config = 0x638413B2, + .ref_ctrl = 0x00000C30, + .sdram_tim1 = 0xEAAAD4DB, + .sdram_tim2 = 0x266B7FDA, + .sdram_tim3 = 0x107F8678, + .read_idle_ctrl = 0x00050000, + .zq_config = 0x50074BE4, + .temp_alert_config = 0x0, + .emif_ddr_phy_ctlr_1 = 0x0E004008, + .emif_ddr_ext_phy_ctrl_1 = 0x08020080, + .emif_ddr_ext_phy_ctrl_2 = 0x00000066, + .emif_ddr_ext_phy_ctrl_3 = 0x00000091, + .emif_ddr_ext_phy_ctrl_4 = 0x000000B9, + .emif_ddr_ext_phy_ctrl_5 = 0x000000E6, + .emif_rd_wr_exec_thresh = 0x00000405 +}; + static const struct emif_regs ddr3_sk_emif_regs_400Mhz = { .sdram_config = 0x638413b2, .sdram_config2 = 0x00000000, @@ -262,6 +303,52 @@ const u32 ext_phy_ctrl_const_base_ddr3[] = { 0x08102040 };
+const u32 ext_phy_ctrl_const_base_ddr3_beta[] = { + 0x00000000, + 0x00000045, + 0x00000046, + 0x00000048, + 0x00000047, + 0x00000000, + 0x0000004C, + 0x00000070, + 0x00000085, + 0x000000A3, + 0x00000000, + 0x0000000C, + 0x00000030, + 0x00000045, + 0x00000063, + 0x00000000, + 0x0, + 0x0, + 0x40000000, + 0x08102040 +}; + +const u32 ext_phy_ctrl_const_base_ddr3_production[] = { + 0x00000000, + 0x00000044, + 0x00000044, + 0x00000046, + 0x00000046, + 0x00000000, + 0x00000059, + 0x00000077, + 0x00000093, + 0x000000A8, + 0x00000000, + 0x00000019, + 0x00000037, + 0x00000053, + 0x00000068, + 0x00000000, + 0x0, + 0x0, + 0x40000000, + 0x08102040 +}; + static const u32 ext_phy_ctrl_const_base_ddr3_sk[] = { /* first 5 are taken care by emif_regs */ 0x00700070, @@ -309,6 +396,12 @@ void emif_get_ext_phy_ctrl_const_regs(const u32 **regs, u32 *size) if (board_is_eposevm()) { *regs = ext_phy_ctrl_const_base_lpddr2; *size = ARRAY_SIZE(ext_phy_ctrl_const_base_lpddr2); + } else if (board_is_evm_14_or_later()) { + *regs = ext_phy_ctrl_const_base_ddr3_production; + *size = ARRAY_SIZE(ext_phy_ctrl_const_base_ddr3_production); + } else if (board_is_evm_12_or_later()) { + *regs = ext_phy_ctrl_const_base_ddr3_beta; + *size = ARRAY_SIZE(ext_phy_ctrl_const_base_ddr3_beta); } else if (board_is_gpevm()) { *regs = ext_phy_ctrl_const_base_ddr3; *size = ARRAY_SIZE(ext_phy_ctrl_const_base_ddr3); @@ -473,6 +566,14 @@ void sdram_init(void) */ if (board_is_eposevm()) { config_ddr(0, &ioregs_lpddr2, NULL, NULL, &emif_regs_lpddr2, 0); + } else if (board_is_evm_14_or_later()) { + enable_vtt_regulator(); + config_ddr(0, &ioregs_ddr3, NULL, NULL, + &ddr3_emif_regs_400Mhz_production, 0); + } else if (board_is_evm_12_or_later()) { + enable_vtt_regulator(); + config_ddr(0, &ioregs_ddr3, NULL, NULL, + &ddr3_emif_regs_400Mhz_beta, 0); } else if (board_is_gpevm()) { enable_vtt_regulator(); config_ddr(0, &ioregs_ddr3, NULL, NULL, diff --git a/board/ti/am43xx/board.h b/board/ti/am43xx/board.h index 017047d..8e12191 100644 --- a/board/ti/am43xx/board.h +++ b/board/ti/am43xx/board.h @@ -15,6 +15,7 @@ #include <asm/arch/omap.h>
static char *const am43xx_board_name = (char *)AM4372_BOARD_NAME_START; +static char *const am43xx_board_rev = (char *)AM4372_BOARD_VERSION_START;
/* * TI AM437x EVMs define a system EEPROM that defines certain sub-fields. @@ -52,6 +53,16 @@ static inline int board_is_sk(void) return !strncmp(am43xx_board_name, "AM43__SK", HDR_NAME_LEN); }
+static inline int board_is_evm_14_or_later(void) +{ + return (board_is_gpevm() && strncmp("1.4", am43xx_board_rev, 3) <= 0); +} + +static inline int board_is_evm_12_or_later(void) +{ + return (board_is_gpevm() && strncmp("1.2", am43xx_board_rev, 3) <= 0); +} + void enable_uart0_pin_mux(void); void enable_board_pin_mux(void); void enable_i2c0_pin_mux(void);

* This is done by limiting the ARM's bandwidth and setting DSS priority in the EMIF controller to ensure underflows do not occur. --- arch/arm/cpu/armv7/am33xx/ddr.c | 12 ++++ arch/arm/include/asm/arch-am33xx/cpu.h | 23 ++++++- arch/arm/include/asm/arch-am33xx/hardware_am43xx.h | 3 + arch/arm/include/asm/emif.h | 15 ++++- board/ti/am43xx/board.c | 68 ++++++++++++++++++-- 5 files changed, 111 insertions(+), 10 deletions(-)
diff --git a/arch/arm/cpu/armv7/am33xx/ddr.c b/arch/arm/cpu/armv7/am33xx/ddr.c index bbe9d1a..fc66872 100644 --- a/arch/arm/cpu/armv7/am33xx/ddr.c +++ b/arch/arm/cpu/armv7/am33xx/ddr.c @@ -94,6 +94,18 @@ void config_sdram_emif4d5(const struct emif_regs *regs, int nr) writel(regs->emif_rd_wr_exec_thresh, &emif_reg[nr]->emif_rd_wr_exec_thresh);
+ /* + * for most SOCs these registers won't need to be changed so only + * write to these registers if someone explicitly has set the + * register's value. + */ + if(regs->emif_cos_config) { + writel(regs->emif_prio_class_serv_map, &emif_reg[nr]->emif_prio_class_serv_map); + writel(regs->emif_connect_id_serv_1_map, &emif_reg[nr]->emif_connect_id_serv_1_map); + writel(regs->emif_connect_id_serv_2_map, &emif_reg[nr]->emif_connect_id_serv_2_map); + writel(regs->emif_cos_config, &emif_reg[nr]->emif_cos_config); + } + writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl); writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw); writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config); diff --git a/arch/arm/include/asm/arch-am33xx/cpu.h b/arch/arm/include/asm/arch-am33xx/cpu.h index aa10fab..8dd69b3 100644 --- a/arch/arm/include/asm/arch-am33xx/cpu.h +++ b/arch/arm/include/asm/arch-am33xx/cpu.h @@ -489,6 +489,12 @@ struct ctrl_stat { #define OMAP_GPIO_SETDATAOUT 0x0194
/* Control Device Register */ + + /* Control Device Register */ +#define MREQPRIO_0_SAB_INIT1_MASK 0xFFFFFF8F +#define MREQPRIO_0_SAB_INIT0_MASK 0xFFFFFFF8 +#define MREQPRIO_1_DSS_MASK 0xFFFFFF8F + struct ctrl_dev { unsigned int deviceid; /* offset 0x00 */ unsigned int resv1[7]; @@ -502,10 +508,25 @@ struct ctrl_dev { unsigned int macid1h; /* offset 0x3c */ unsigned int resv4[4]; unsigned int miisel; /* offset 0x50 */ - unsigned int resv5[106]; + unsigned int resv5[7]; + unsigned int mreqprio_0; /* offset 0x70 */ + unsigned int mreqprio_1; /* offset 0x74 */ + unsigned int resv6[97]; unsigned int efuse_sma; /* offset 0x1FC */ };
+/* Bandwidth Limiter Portion of the L3Fast Configuration Register */ +#define BW_LIMITER_BW_FRAC_MASK 0xFFFFFFE0 +#define BW_LIMITER_BW_INT_MASK 0xFFFFFFF0 +#define BW_LIMITER_BW_WATERMARK_MASK 0xFFFFF800 + +struct l3f_cfg_bwlimiter { + u32 padding0[2]; + u32 modena_init0_bw_fractional; + u32 modena_init0_bw_integer; + u32 modena_init0_watermark_0; +}; + /* gmii_sel register defines */ #define GMII1_SEL_MII 0x0 #define GMII1_SEL_RMII 0x1 diff --git a/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h b/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h index 15399dc..b470319 100644 --- a/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h +++ b/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h @@ -13,6 +13,9 @@
/* Module base addresses */
+/* L3 Fast Configuration Bandwidth Limiter Base Address */ +#define L3F_CFG_BWLIMITER 0x44005200 + /* UART Base Address */ #define UART0_BASE 0x44E09000
diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h index 45668ca..b8d6bdc 100644 --- a/arch/arm/include/asm/emif.h +++ b/arch/arm/include/asm/emif.h @@ -642,11 +642,16 @@ struct emif_reg_struct { u32 emif_ddr_phy_ctrl_1; u32 emif_ddr_phy_ctrl_1_shdw; u32 emif_ddr_phy_ctrl_2; - u32 padding7[12]; + u32 padding7[4]; + u32 emif_prio_class_serv_map; + u32 emif_connect_id_serv_1_map; + u32 emif_connect_id_serv_2_map; + u32 padding8[5]; u32 emif_rd_wr_exec_thresh; - u32 padding8[7]; + u32 emif_cos_config; + u32 padding9[6]; u32 emif_ddr_phy_status[21]; - u32 padding9[27]; + u32 padding10[27]; u32 emif_ddr_ext_phy_ctrl_1; u32 emif_ddr_ext_phy_ctrl_1_shdw; u32 emif_ddr_ext_phy_ctrl_2; @@ -1137,6 +1142,10 @@ struct emif_regs { u32 emif_rd_wr_lvl_rmp_ctl; u32 emif_rd_wr_lvl_ctl; u32 emif_rd_wr_exec_thresh; + u32 emif_prio_class_serv_map; + u32 emif_connect_id_serv_1_map; + u32 emif_connect_id_serv_2_map; + u32 emif_cos_config; };
struct lpddr2_mr_regs { diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c index 5eaa4a5..7e239f1 100644 --- a/board/ti/am43xx/board.c +++ b/board/ti/am43xx/board.c @@ -157,12 +157,16 @@ const struct emif_regs emif_regs_lpddr2 = { .emif_rd_wr_lvl_rmp_ctl = 0x0, .emif_rd_wr_lvl_ctl = 0x0, .emif_ddr_phy_ctlr_1 = 0x0E084006, - .emif_rd_wr_exec_thresh = 0x00000405, + .emif_rd_wr_exec_thresh = 0x80000405, .emif_ddr_ext_phy_ctrl_1 = 0x04010040, .emif_ddr_ext_phy_ctrl_2 = 0x00500050, .emif_ddr_ext_phy_ctrl_3 = 0x00500050, .emif_ddr_ext_phy_ctrl_4 = 0x00500050, - .emif_ddr_ext_phy_ctrl_5 = 0x00500050 + .emif_ddr_ext_phy_ctrl_5 = 0x00500050, + .emif_prio_class_serv_map = 0x80000001, + .emif_connect_id_serv_1_map = 0x80000094, + .emif_connect_id_serv_2_map = 0x00000000, + .emif_cos_config = 0x000FFFFF };
const u32 ext_phy_ctrl_const_base_lpddr2[] = { @@ -217,7 +221,11 @@ const struct emif_regs ddr3_emif_regs_400Mhz = { .emif_rd_wr_lvl_rmp_win = 0x0, .emif_rd_wr_lvl_rmp_ctl = 0x0, .emif_rd_wr_lvl_ctl = 0x0, - .emif_rd_wr_exec_thresh = 0x00000405 + .emif_rd_wr_exec_thresh = 0x80000405, + .emif_prio_class_serv_map = 0x80000001, + .emif_connect_id_serv_1_map = 0x80000094, + .emif_connect_id_serv_2_map = 0x00000000, + .emif_cos_config = 0x000FFFFF };
/* EMIF DDR3 Configurations are different for beta AM43X GP EVMs */ @@ -236,7 +244,11 @@ const struct emif_regs ddr3_emif_regs_400Mhz_beta = { .emif_ddr_ext_phy_ctrl_3 = 0x00000091, .emif_ddr_ext_phy_ctrl_4 = 0x000000B5, .emif_ddr_ext_phy_ctrl_5 = 0x000000E5, - .emif_rd_wr_exec_thresh = 0x00000405 + .emif_rd_wr_exec_thresh = 0x80000405, + .emif_prio_class_serv_map = 0x80000001, + .emif_connect_id_serv_1_map = 0x80000094, + .emif_connect_id_serv_2_map = 0x00000000, + .emif_cos_config = 0x000FFFFF };
/* EMIF DDR3 Configurations are different for production AM43X GP EVMs */ @@ -255,7 +267,11 @@ const struct emif_regs ddr3_emif_regs_400Mhz_production = { .emif_ddr_ext_phy_ctrl_3 = 0x00000091, .emif_ddr_ext_phy_ctrl_4 = 0x000000B9, .emif_ddr_ext_phy_ctrl_5 = 0x000000E6, - .emif_rd_wr_exec_thresh = 0x00000405 + .emif_rd_wr_exec_thresh = 0x80000405, + .emif_prio_class_serv_map = 0x80000001, + .emif_connect_id_serv_1_map = 0x80000094, + .emif_connect_id_serv_2_map = 0x00000000, + .emif_cos_config = 0x000FFFFF };
static const struct emif_regs ddr3_sk_emif_regs_400Mhz = { @@ -277,7 +293,11 @@ static const struct emif_regs ddr3_sk_emif_regs_400Mhz = { .emif_rd_wr_lvl_rmp_win = 0x0, .emif_rd_wr_lvl_rmp_ctl = 0x00000000, .emif_rd_wr_lvl_ctl = 0x00000000, - .emif_rd_wr_exec_thresh = 0x00000000, + .emif_rd_wr_exec_thresh = 0x80000000, + .emif_prio_class_serv_map = 0x80000001, + .emif_connect_id_serv_1_map = 0x80000094, + .emif_connect_id_serv_2_map = 0x00000000, + .emif_cos_config = 0x000FFFFF };
const u32 ext_phy_ctrl_const_base_ddr3[] = { @@ -587,8 +607,44 @@ void sdram_init(void)
int board_init(void) { + struct l3f_cfg_bwlimiter *bwlimiter = (struct l3f_cfg_bwlimiter *)L3F_CFG_BWLIMITER; + u32 mreqprio_0, mreqprio_1, modena_init0_bw_fractional, + modena_init0_bw_integer, modena_init0_watermark_0; + gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+ /* Clear all important bits for DSS errata that may need to be tweaked*/ + mreqprio_0 = readl(&cdev->mreqprio_0) & MREQPRIO_0_SAB_INIT1_MASK & + MREQPRIO_0_SAB_INIT0_MASK; + + mreqprio_1 = readl(&cdev->mreqprio_1) & MREQPRIO_1_DSS_MASK; + + modena_init0_bw_fractional = readl(&bwlimiter->modena_init0_bw_fractional) & + BW_LIMITER_BW_FRAC_MASK; + + modena_init0_bw_integer = readl(&bwlimiter->modena_init0_bw_integer) & + BW_LIMITER_BW_INT_MASK; + + modena_init0_watermark_0 = readl(&bwlimiter->modena_init0_watermark_0) & + BW_LIMITER_BW_WATERMARK_MASK; + + /* Setting MReq Priority of the DSS*/ + mreqprio_0 |= 0x77; + + /* + * Set L3 Fast Configuration Register + * Limiting bandwith for ARM core to 700 MBPS + */ + modena_init0_bw_fractional |= 0x10; + modena_init0_bw_integer |= 0x3; + + writel(mreqprio_0, &cdev->mreqprio_0); + writel(mreqprio_1, &cdev->mreqprio_1); + + writel(modena_init0_bw_fractional, &bwlimiter->modena_init0_bw_fractional); + writel(modena_init0_bw_integer, &bwlimiter->modena_init0_bw_integer); + writel(modena_init0_watermark_0, &bwlimiter->modena_init0_watermark_0); + return 0; }

On Fri, Jun 27, 2014 at 01:31:15PM -0500, Cooper Jr., Franklin wrote:
- This is done by limiting the ARM's bandwidth and setting DSS priority in the EMIF controller to ensure underflows do not occur.
Applied to u-boot/master, thanks!

On Fri, Jun 27, 2014 at 01:31:14PM -0500, Cooper Jr., Franklin wrote:
From: "Franklin S. Cooper Jr" fcooper@ti.com
- Boot failures have been discovered due to a combination of routing issues and non optimal ddr3 timings in the EMIF
- Since ddr3 timings are different after significant board layout changes different timings are required for alpha, beta and production boards.
Signed-off-by: Franklin S. Cooper Jr fcooper@ti.com
Applied to u-boot/master, thanks!
participants (2)
-
Franklin S Cooper Jr
-
Tom Rini