From 3625fd64ef929af4d158027aa5beee703f1294fc Mon Sep 17 00:00:00 2001 From: Tim Harvey Date: Mon, 18 May 2015 07:07:02 -0700 Subject: arm: mx6: ddr: set fast-exit on DDR3 if pd_fast_exit specified Commit fa8b7d66f49f0c7bd41467fe78f6488d8af6976a introduced fast-exit support to the MMDC however enabling it on the DDR3 got missed. Make sure we enable it on the DDR3 as well. Gateworks uses Micron memory as well as Winbond in MX6. We have found in testing that we need to enable fast-exit for Winbond stability. Gateworks boards are currently the only boards using the MX6 SPL and enabling fast-exit mode. Signed-off-by: Tim Harvey --- arch/arm/cpu/armv7/mx6/ddr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/arm/cpu/armv7') diff --git a/arch/arm/cpu/armv7/mx6/ddr.c b/arch/arm/cpu/armv7/mx6/ddr.c index 5d5bd0f546..86c8354217 100644 --- a/arch/arm/cpu/armv7/mx6/ddr.c +++ b/arch/arm/cpu/armv7/mx6/ddr.c @@ -521,7 +521,8 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo, /* MR0 */ val = ((tcl - 1) << 4) | /* CAS */ (1 << 8) | /* DLL Reset */ - ((twr - 3) << 9); /* Write Recovery */ + ((twr - 3) << 9) | /* Write Recovery */ + (sysinfo->pd_fast_exit << 12); /* Precharge PD PLL on */ debug("MR0 CS%d: 0x%08x\n", cs, (u32)MR(val, 0, 3, cs)); mmdc0->mdscr = MR(val, 0, 3, cs); /* ZQ calibration */ -- cgit From 9b9449c3e2809994d260f4f783b98652e7b6353b Mon Sep 17 00:00:00 2001 From: Tim Harvey Date: Mon, 18 May 2015 07:02:24 -0700 Subject: imx: mx6: add get_cpu_speed_grade_hz func to return MHz speed grade from OTP The IMX6 has four different speed grades determined by eFUSE SPEED_GRADING indicated by OCOTP_CFG3[17:16] which is at 0x440 in the Fusemap Description Table. Return this frequency so that it can be used elsewhere. Note that the IMX6SDLRM and the IMX6SXRM do not indicate this in the their Fusemap Description Table however Freescale has confirmed that these eFUSE bits match the description within the IMX6DQRM and that they will be added to the next revision of the respective reference manuals. These have been tested with IMX6 Quad/Solo/Dual-light 800Mhz and 1GHz grades. Signed-off-by: Tim Harvey --- arch/arm/cpu/armv7/mx6/soc.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'arch/arm/cpu/armv7') diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c index 21ef9d0573..f91b725b15 100644 --- a/arch/arm/cpu/armv7/mx6/soc.c +++ b/arch/arm/cpu/armv7/mx6/soc.c @@ -83,6 +83,47 @@ u32 get_cpu_rev(void) return (type << 12) | (reg + 0x10); } +/* + * OCOTP_CFG3[17:16] (see Fusemap Description Table offset 0x440) + * defines a 2-bit SPEED_GRADING + */ +#define OCOTP_CFG3_SPEED_SHIFT 16 +#define OCOTP_CFG3_SPEED_800MHZ 0 +#define OCOTP_CFG3_SPEED_850MHZ 1 +#define OCOTP_CFG3_SPEED_1GHZ 2 +#define OCOTP_CFG3_SPEED_1P2GHZ 3 + +u32 get_cpu_speed_grade_hz(void) +{ + struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; + struct fuse_bank *bank = &ocotp->bank[0]; + struct fuse_bank0_regs *fuse = + (struct fuse_bank0_regs *)bank->fuse_regs; + uint32_t val; + + val = readl(&fuse->cfg3); + val >>= OCOTP_CFG3_SPEED_SHIFT; + val &= 0x3; + + switch (val) { + /* Valid for IMX6DQ */ + case OCOTP_CFG3_SPEED_1P2GHZ: + if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D)) + return 1200000000; + /* Valid for IMX6SX/IMX6SDL/IMX6DQ */ + case OCOTP_CFG3_SPEED_1GHZ: + return 996000000; + /* Valid for IMX6DQ */ + case OCOTP_CFG3_SPEED_850MHZ: + if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D)) + return 852000000; + /* Valid for IMX6SX/IMX6SDL/IMX6DQ */ + case OCOTP_CFG3_SPEED_800MHZ: + return 792000000; + } + return 0; +} + #ifdef CONFIG_REVISION_TAG u32 __weak get_board_rev(void) { -- cgit From f0e8e8944dc9bdddd0e3e3b7dbd8ac76008b32a4 Mon Sep 17 00:00:00 2001 From: Tim Harvey Date: Mon, 18 May 2015 06:56:45 -0700 Subject: imx: mx6: add get_cpu_temp_grade to obtain cpu temperature grade from OTP The MX6 has a temperature grade defined by OCOTP_MEM0[7:6] which is at 0x480 in the Fusemap Description Table in the reference manual. Return this value as well as min/max temperature based on the value. Note that the IMX6SDLRM and the IMX6SXRM do not indicate this in the their Fusemap Description Table however Freescale has confirmed that these eFUSE bits match the description within the IMX6DQRM and that they will be added to the next revision of the respective reference manuals. This has been tested with IMX6 Automative and Industrial parts. Signed-off-by: Tim Harvey --- arch/arm/cpu/armv7/mx6/soc.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'arch/arm/cpu/armv7') diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c index f91b725b15..b21bd03a8a 100644 --- a/arch/arm/cpu/armv7/mx6/soc.c +++ b/arch/arm/cpu/armv7/mx6/soc.c @@ -124,6 +124,44 @@ u32 get_cpu_speed_grade_hz(void) return 0; } +/* + * OCOTP_MEM0[7:6] (see Fusemap Description Table offset 0x480) + * defines a 2-bit Temperature Grade + * + * return temperature grade and min/max temperature in celcius + */ +#define OCOTP_MEM0_TEMP_SHIFT 6 + +u32 get_cpu_temp_grade(int *minc, int *maxc) +{ + struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; + struct fuse_bank *bank = &ocotp->bank[1]; + struct fuse_bank1_regs *fuse = + (struct fuse_bank1_regs *)bank->fuse_regs; + uint32_t val; + + val = readl(&fuse->mem0); + val >>= OCOTP_MEM0_TEMP_SHIFT; + val &= 0x3; + + if (minc && maxc) { + if (val == TEMP_AUTOMOTIVE) { + *minc = -40; + *maxc = 125; + } else if (val == TEMP_INDUSTRIAL) { + *minc = -40; + *maxc = 105; + } else if (val == TEMP_EXTCOMMERCIAL) { + *minc = -20; + *maxc = 105; + } else { + *minc = 0; + *maxc = 95; + } + } + return val; +} + #ifdef CONFIG_REVISION_TAG u32 __weak get_board_rev(void) { -- cgit From 21a26940f9048e668f9a79f64b802406b2e8d18c Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Mon, 18 May 2015 10:56:24 +0200 Subject: arm, imx6, i2c: add I2C4 for MX6DL add I2C4 modul for MX6DL based boards. Signed-off-by: Heiko Schocher --- arch/arm/cpu/armv7/mx6/clock.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'arch/arm/cpu/armv7') diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index 055f44e8e4..ae99945304 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -140,23 +140,34 @@ int enable_usdhc_clk(unsigned char enable, unsigned bus_num) #endif #ifdef CONFIG_SYS_I2C_MXC -/* i2c_num can be from 0 - 2 */ +/* i2c_num can be from 0 - 3 */ int enable_i2c_clk(unsigned char enable, unsigned i2c_num) { u32 reg; u32 mask; - if (i2c_num > 2) + if (i2c_num > 3) return -EINVAL; - - mask = MXC_CCM_CCGR_CG_MASK - << (MXC_CCM_CCGR2_I2C1_SERIAL_OFFSET + (i2c_num << 1)); - reg = __raw_readl(&imx_ccm->CCGR2); - if (enable) - reg |= mask; - else - reg &= ~mask; - __raw_writel(reg, &imx_ccm->CCGR2); + if (i2c_num < 3) { + mask = MXC_CCM_CCGR_CG_MASK + << (MXC_CCM_CCGR2_I2C1_SERIAL_OFFSET + + (i2c_num << 1)); + reg = __raw_readl(&imx_ccm->CCGR2); + if (enable) + reg |= mask; + else + reg &= ~mask; + __raw_writel(reg, &imx_ccm->CCGR2); + } else { + mask = MXC_CCM_CCGR_CG_MASK + << (MXC_CCM_CCGR1_I2C4_SERIAL_OFFSET); + reg = __raw_readl(&imx_ccm->CCGR1); + if (enable) + reg |= mask; + else + reg &= ~mask; + __raw_writel(reg, &imx_ccm->CCGR1); + } return 0; } #endif -- cgit