X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-uboot.git;a=blobdiff_plain;f=arch%2Farm%2Fcpu%2Farmv7%2Fmx6%2Fsoc.c;h=c45c2f9d03f09896f8a367c95c4611507eab65c8;hp=172527987d573137cc1d0fde06557606669beca6;hb=2e62c0bab7fe68ba2ab3baf6777537267a26ac02;hpb=17998eff9021b7b579c0387e934d8c52603fe247 diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c index 172527987d..c45c2f9d03 100644 --- a/arch/arm/cpu/armv7/mx6/soc.c +++ b/arch/arm/cpu/armv7/mx6/soc.c @@ -8,18 +8,46 @@ */ #include +#include +#include #include +#include #include #include #include #include #include +#include #include #include #include #include #include #include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define __data __attribute__((section(".data"))) + +#ifdef CONFIG_MX6_TEMPERATURE_MIN +#define TEMPERATURE_MIN CONFIG_MX6_TEMPERATURE_MIN +#else +#define TEMPERATURE_MIN (-40) +#endif +#ifdef CONFIG_MX6_TEMPERATURE_HOT +#define TEMPERATURE_HOT CONFIG_MX6_TEMPERATURE_HOT +#else +#define TEMPERATURE_HOT 80 +#endif +#ifdef CONFIG_MX6_TEMPERATURE_MAX +#define TEMPERATURE_MAX CONFIG_MX6_TEMPERATURE_MAX +#else +#define TEMPERATURE_MAX 125 +#endif +#define TEMP_AVG_COUNT 5 +#define TEMP_WARN_THRESHOLD 5 enum ldo_reg { LDO_ARM, @@ -35,16 +63,36 @@ struct scu_regs { u32 fpga_rev; }; +#if defined(CONFIG_IMX6_THERMAL) +static const struct imx_thermal_plat imx6_thermal_plat = { + .regs = (void *)ANATOP_BASE_ADDR, + .fuse_bank = 1, + .fuse_word = 6, +}; + +U_BOOT_DEVICE(imx6_thermal) = { + .name = "imx_thermal", + .platdata = &imx6_thermal_plat, +}; +#endif + +u32 get_nr_cpus(void) +{ + struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR; + return readl(&scu->config) & 3; +} + u32 get_cpu_rev(void) { struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; u32 reg = readl(&anatop->digprog_sololite); u32 type = ((reg >> 16) & 0xff); + u32 major, cfg = 0; if (type != MXC_CPU_MX6SL) { reg = readl(&anatop->digprog); struct scu_regs *scu = (struct scu_regs *)SCU_BASE_ADDR; - u32 cfg = readl(&scu->config) & 3; + cfg = readl(&scu->config) & 3; type = ((reg >> 16) & 0xff); if (type == MXC_CPU_MX6DL) { if (!cfg) @@ -57,8 +105,95 @@ u32 get_cpu_rev(void) } } + major = ((reg >> 8) & 0xff); + if ((major >= 1) && + ((type == MXC_CPU_MX6Q) || (type == MXC_CPU_MX6D))) { + major--; + type = MXC_CPU_MX6QP; + if (cfg == 1) + type = MXC_CPU_MX6DP; + } reg &= 0xff; /* mx6 silicon revision */ - return (type << 12) | (reg + 0x10); + return (type << 12) | (reg + (0x10 * (major + 1))); +} + +/* + * 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; +} + +/* + * 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 @@ -79,9 +214,15 @@ u32 __weak get_board_rev(void) void init_aips(void) { struct aipstz_regs *aips1, *aips2; +#ifdef CONFIG_SOC_MX6SX + struct aipstz_regs *aips3; +#endif - aips1 = (struct aipstz_regs *)AIPS1_BASE_ADDR; - aips2 = (struct aipstz_regs *)AIPS2_BASE_ADDR; + aips1 = (struct aipstz_regs *)AIPS1_ARB_BASE_ADDR; + aips2 = (struct aipstz_regs *)AIPS2_ARB_BASE_ADDR; +#ifdef CONFIG_SOC_MX6SX + aips3 = (struct aipstz_regs *)AIPS3_ARB_BASE_ADDR; +#endif /* * Set all MPROTx to be non-bufferable, trusted for R/W, @@ -107,6 +248,26 @@ void init_aips(void) writel(0x00000000, &aips2->opacr2); writel(0x00000000, &aips2->opacr3); writel(0x00000000, &aips2->opacr4); + +#ifdef CONFIG_SOC_MX6SX + /* + * Set all MPROTx to be non-bufferable, trusted for R/W, + * not forced to user-mode. + */ + writel(0x77777777, &aips3->mprot0); + writel(0x77777777, &aips3->mprot1); + + /* + * Set all OPACRx to be non-bufferable, not require + * supervisor privilege level for access,allow for + * write access and untrusted master access. + */ + writel(0x00000000, &aips3->opacr0); + writel(0x00000000, &aips3->opacr1); + writel(0x00000000, &aips3->opacr2); + writel(0x00000000, &aips3->opacr3); + writel(0x00000000, &aips3->opacr4); +#endif } static void clear_ldo_ramp(void) @@ -124,10 +285,9 @@ static void clear_ldo_ramp(void) } /* - * Set the VDDSOC + * Set the PMU_REG_CORE register * - * Mask out the REG_CORE[22:18] bits (REG2_TRIG) and set - * them to the specified millivolt level. + * Set LDO_SOC/PU/ARM regulators to the specified millivolt level. * Possible values are from 0.725V to 1.450V in steps of * 0.025V (25mV). */ @@ -177,10 +337,185 @@ static int set_ldo_voltage(enum ldo_reg ldo, u32 mv) return 0; } +static u32 __data thermal_calib; + +#define FACTOR0 10000000 +#define FACTOR1 15976 +#define FACTOR2 4297157 + +int raw_to_celsius(unsigned int raw, unsigned int raw_25c, unsigned int raw_hot, + unsigned int hot_temp) +{ + int temperature; + + if (raw_hot != 0 && hot_temp != 0) { + unsigned int raw_n40c, ratio; + + ratio = ((raw_25c - raw_hot) * 100) / (hot_temp - 25); + raw_n40c = raw_25c + (13 * ratio) / 20; + if (raw <= raw_n40c) + temperature = (raw_n40c - raw) * 100 / ratio - 40; + else + temperature = TEMPERATURE_MIN; + } else { + u64 temp64 = FACTOR0; + unsigned int c1, c2; + /* + * Derived from linear interpolation: + * slope = 0.4297157 - (0.0015976 * 25C fuse) + * slope = (FACTOR2 - FACTOR1 * n1) / FACTOR0 + * (Nmeas - n1) / (Tmeas - t1) = slope + * We want to reduce this down to the minimum computation necessary + * for each temperature read. Also, we want Tmeas in millicelsius + * and we don't want to lose precision from integer division. So... + * Tmeas = (Nmeas - n1) / slope + t1 + * milli_Tmeas = 1000 * (Nmeas - n1) / slope + 1000 * t1 + * milli_Tmeas = -1000 * (n1 - Nmeas) / slope + 1000 * t1 + * Let constant c1 = (-1000 / slope) + * milli_Tmeas = (n1 - Nmeas) * c1 + 1000 * t1 + * Let constant c2 = n1 *c1 + 1000 * t1 + * milli_Tmeas = c2 - Nmeas * c1 + */ + temp64 *= 1000; + do_div(temp64, FACTOR1 * raw_25c - FACTOR2); + c1 = temp64; + c2 = raw_25c * c1 + 1000 * 25; + temperature = (c2 - raw * c1) / 1000; + } + return temperature; +} + +int read_cpu_temperature(void) +{ + unsigned int reg, tmp, i; + unsigned int raw_25c, raw_hot, hot_temp; + int temperature; + struct anatop_regs *const anatop = (void *)ANATOP_BASE_ADDR; + struct mx6_ocotp_regs *const ocotp_regs = (void *)OCOTP_BASE_ADDR; + + if (!thermal_calib) { + enable_ocotp_clk(1); + writel(1, &ocotp_regs->hw_ocotp_read_ctrl); + thermal_calib = readl(&ocotp_regs->hw_ocotp_ana1); + writel(0, &ocotp_regs->hw_ocotp_read_ctrl); + enable_ocotp_clk(0); + } + + if (thermal_calib == 0 || thermal_calib == 0xffffffff) + return TEMPERATURE_MIN; + + /* Fuse data layout: + * [31:20] sensor value @ 25C + * [19:8] sensor value of hot + * [7:0] hot temperature value */ + raw_25c = thermal_calib >> 20; + raw_hot = (thermal_calib & 0xfff00) >> 8; + hot_temp = thermal_calib & 0xff; + + /* now we only using single measure, every time we measure + * the temperature, we will power on/off the anadig module + */ + writel(BM_ANADIG_TEMPSENSE0_POWER_DOWN, &anatop->tempsense0_clr); + writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_set); + + /* write measure freq */ + writel(327, &anatop->tempsense1); + writel(BM_ANADIG_TEMPSENSE0_MEASURE_TEMP, &anatop->tempsense0_clr); + writel(BM_ANADIG_TEMPSENSE0_FINISHED, &anatop->tempsense0_clr); + writel(BM_ANADIG_TEMPSENSE0_MEASURE_TEMP, &anatop->tempsense0_set); + + /* average the temperature value over multiple readings */ + for (i = 0; i < TEMP_AVG_COUNT; i++) { + static int failed; + int limit = 100; + + while ((readl(&anatop->tempsense0) & + BM_ANADIG_TEMPSENSE0_FINISHED) == 0) { + udelay(10000); + if (--limit < 0) + break; + } + if ((readl(&anatop->tempsense0) & + BM_ANADIG_TEMPSENSE0_FINISHED) == 0) { + if (!failed) { + printf("Failed to read temp sensor\n"); + failed = 1; + } + return 0; + } + failed = 0; + reg = (readl(&anatop->tempsense0) & + BM_ANADIG_TEMPSENSE0_TEMP_VALUE) >> + BP_ANADIG_TEMPSENSE0_TEMP_VALUE; + if (i == 0) + tmp = reg; + else + tmp = (tmp * i + reg) / (i + 1); + writel(BM_ANADIG_TEMPSENSE0_FINISHED, + &anatop->tempsense0_clr); + } + + temperature = raw_to_celsius(tmp, raw_25c, raw_hot, hot_temp); + + /* power down anatop thermal sensor */ + writel(BM_ANADIG_TEMPSENSE0_POWER_DOWN, &anatop->tempsense0_set); + writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_clr); + + return temperature; +} + +int check_cpu_temperature(int boot) +{ + static int __data max_temp; + int boot_limit = getenv_ulong("max_boot_temp", 10, TEMPERATURE_HOT); + int tmp = read_cpu_temperature(); + bool first = true; + + if (tmp < TEMPERATURE_MIN || tmp > TEMPERATURE_MAX) { + printf("Temperature: can't get valid data!\n"); + return tmp; + } + + if (!boot) { + if (tmp > boot_limit) { + printf("CPU is %d C, too hot, resetting...\n", tmp); + udelay(100000); + reset_cpu(0); + } + if (tmp > max_temp) { + if (tmp > boot_limit - TEMP_WARN_THRESHOLD) + printf("WARNING: CPU temperature %d C\n", tmp); + max_temp = tmp; + } + } else { + printf("Temperature: %d C, calibration data 0x%x\n", + tmp, thermal_calib); + while (tmp >= boot_limit) { + if (first) { + printf("CPU is %d C, too hot to boot, waiting...\n", + tmp); + first = false; + } + if (ctrlc()) + break; + udelay(50000); + tmp = read_cpu_temperature(); + if (tmp > boot_limit - TEMP_WARN_THRESHOLD && tmp != max_temp) + printf("WARNING: CPU temperature %d C\n", tmp); + max_temp = tmp; + } + } + return tmp; +} + static void imx_set_wdog_powerdown(bool enable) { struct wdog_regs *wdog1 = (struct wdog_regs *)WDOG1_BASE_ADDR; struct wdog_regs *wdog2 = (struct wdog_regs *)WDOG2_BASE_ADDR; + struct wdog_regs *wdog3 = (struct wdog_regs *)WDOG3_BASE_ADDR; + + if (is_cpu_type(MXC_CPU_MX6SX) || is_cpu_type(MXC_CPU_MX6UL)) + writew(enable, &wdog3->wmcr); /* Write to the PDE (Power Down Enable) bit */ writew(enable, &wdog1->wmcr); @@ -202,9 +537,56 @@ static void set_ahb_rate(u32 val) static void clear_mmdc_ch_mask(void) { struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + u32 reg; + reg = readl(&mxc_ccm->ccdr); /* Clear MMDC channel mask */ - writel(0, &mxc_ccm->ccdr); + reg &= ~(MXC_CCM_CCDR_MMDC_CH1_HS_MASK | MXC_CCM_CCDR_MMDC_CH0_HS_MASK); + writel(reg, &mxc_ccm->ccdr); +} + +static void init_bandgap(void) +{ + struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; + /* + * Ensure the bandgap has stabilized. + */ + while (!(readl(&anatop->ana_misc0) & 0x80)) + ; + /* + * For best noise performance of the analog blocks using the + * outputs of the bandgap, the reftop_selfbiasoff bit should + * be set. + */ + writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_set); +} + +#ifdef CONFIG_SOC_MX6SL +static void set_preclk_from_osc(void) +{ + struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + u32 reg; + + reg = readl(&mxc_ccm->cscmr1); + reg |= MXC_CCM_CSCMR1_PER_CLK_SEL_MASK; + writel(reg, &mxc_ccm->cscmr1); +} +#endif + +#define SRC_SCR_WARM_RESET_ENABLE 0 + +static void init_src(void) +{ + struct src *src_regs = (struct src *)SRC_BASE_ADDR; + u32 val; + + /* + * force warm reset sources to generate cold reset + * for a more reliable restart + */ + val = readl(&src_regs->scr); + val &= ~(1 << SRC_SCR_WARM_RESET_ENABLE); + writel(val, &src_regs->scr); } int arch_cpu_init(void) @@ -214,6 +596,13 @@ int arch_cpu_init(void) /* Need to clear MMDC_CHx_MASK to make warm reset work. */ clear_mmdc_ch_mask(); + /* + * Disable self-bias circuit in the analog bandap. + * The self-bias circuit is used by the bandgap during startup. + * This bit should be set after the bandgap has initialized. + */ + init_bandgap(); + /* * When low freq boot is enabled, ROM will not set AHB * freq, so we need to ensure AHB freq is 132MHz in such @@ -222,13 +611,24 @@ int arch_cpu_init(void) if (mxc_get_clock(MXC_ARM_CLK) == 396000000) set_ahb_rate(132000000); + /* Set perclk to source from OSC 24MHz */ +#if defined(CONFIG_SOC_MX6SL) + set_preclk_from_osc(); +#endif + imx_set_wdog_powerdown(false); /* Disable PDE bit of WMCR register */ -#ifdef CONFIG_APBH_DMA - /* Start APBH DMA */ +#ifdef CONFIG_VIDEO_IPUV3 + gd->arch.ipu_hw_rev = IPUV3_HW_REV_IPUV3H; +#endif +#ifdef CONFIG_APBH_DMA + /* Timer is required for Initializing APBH DMA */ + timer_init(); mxs_dma_init(); #endif + init_src(); + return 0; } @@ -242,10 +642,25 @@ int board_postclk_init(void) #ifndef CONFIG_SYS_DCACHE_OFF void enable_caches(void) { +#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) + enum dcache_option option = DCACHE_WRITETHROUGH; +#else + enum dcache_option option = DCACHE_WRITEBACK; +#endif + /* Avoid random hang when download by usb */ invalidate_dcache_all(); + /* Enable D-cache. I-cache is already enabled in start.S */ dcache_enable(); + + /* Enable caching on OCRAM and ROM */ + mmu_set_region_dcache_behaviour(ROMCP_ARB_BASE_ADDR, + ROMCP_ARB_END_ADDR, + option); + mmu_set_region_dcache_behaviour(IRAM_BASE_ADDR, + IRAM_SIZE, + option); } #endif @@ -259,14 +674,13 @@ void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) u32 value = readl(&fuse->mac_addr_high); mac[0] = (value >> 8); - mac[1] = value ; + mac[1] = value; value = readl(&fuse->mac_addr_low); - mac[2] = value >> 24 ; - mac[3] = value >> 16 ; - mac[4] = value >> 8 ; - mac[5] = value ; - + mac[2] = value >> 24; + mac[3] = value >> 16; + mac[4] = value >> 8; + mac[5] = value; } #endif @@ -285,18 +699,18 @@ void boot_mode_apply(unsigned cfg_val) /* * cfg_val will be used for * Boot_cfg4[7:0]:Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0] - * After reset, if GPR10[28] is 1, ROM will copy GPR9[25:0] - * to SBMR1, which will determine the boot device. + * After reset, if GPR10[28] is 1, ROM will use GPR9[25:0] + * instead of SBMR1 to determine the boot device. */ const struct boot_mode soc_boot_modes[] = { {"normal", MAKE_CFGVAL(0x00, 0x00, 0x00, 0x00)}, /* reserved value should start rom usb */ {"usb", MAKE_CFGVAL(0x01, 0x00, 0x00, 0x00)}, {"sata", MAKE_CFGVAL(0x20, 0x00, 0x00, 0x00)}, - {"escpi1:0", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x08)}, - {"escpi1:1", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x18)}, - {"escpi1:2", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x28)}, - {"escpi1:3", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x38)}, + {"ecspi1:0", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x08)}, + {"ecspi1:1", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x18)}, + {"ecspi1:2", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x28)}, + {"ecspi1:3", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x38)}, /* 4 bit bus width */ {"esdhc1", MAKE_CFGVAL(0x40, 0x20, 0x00, 0x00)}, {"esdhc2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)}, @@ -308,9 +722,13 @@ const struct boot_mode soc_boot_modes[] = { void s_init(void) { struct anatop_regs *anatop = (struct anatop_regs *)ANATOP_BASE_ADDR; - int is_6q = is_cpu_type(MXC_CPU_MX6Q); + struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; u32 mask480; u32 mask528; + u32 reg, periph1, periph2; + + if (is_cpu_type(MXC_CPU_MX6SX) || is_cpu_type(MXC_CPU_MX6UL)) + return; /* Due to hardware limitation, on MX6Q we need to gate/ungate all PFDs * to make sure PFD is working right, otherwise, PFDs may @@ -322,15 +740,23 @@ void s_init(void) ANATOP_PFD_CLKGATE_MASK(1) | ANATOP_PFD_CLKGATE_MASK(2) | ANATOP_PFD_CLKGATE_MASK(3); - mask528 = ANATOP_PFD_CLKGATE_MASK(0) | - ANATOP_PFD_CLKGATE_MASK(1) | + mask528 = ANATOP_PFD_CLKGATE_MASK(1) | ANATOP_PFD_CLKGATE_MASK(3); - /* - * Don't reset PFD2 on DL/S - */ - if (is_6q) + reg = readl(&ccm->cbcmr); + periph2 = ((reg & MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK) + >> MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET); + periph1 = ((reg & MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK) + >> MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET); + + /* Checking if PLL2 PFD0 or PLL2 PFD2 is using for periph clock */ + if ((periph2 != 0x2) && (periph1 != 0x2)) + mask528 |= ANATOP_PFD_CLKGATE_MASK(0); + + if ((periph2 != 0x1) && (periph1 != 0x1) && + (periph2 != 0x3) && (periph1 != 0x3)) mask528 |= ANATOP_PFD_CLKGATE_MASK(2); + writel(mask480, &anatop->pfd_480_set); writel(mask528, &anatop->pfd_528_set); writel(mask480, &anatop->pfd_480_clr); @@ -385,7 +811,15 @@ void v7_outer_cache_enable(void) struct pl310_regs *const pl310 = (struct pl310_regs *)L2_PL310_BASE; unsigned int val; -#if defined CONFIG_MX6SL + + /* + * Set bit 22 in the auxiliary control register. If this bit + * is cleared, PL310 treats Normal Shared Non-cacheable + * accesses as Cacheable no-allocate. + */ + setbits_le32(&pl310->pl310_aux_ctrl, L310_SHARED_ATT_OVERRIDE_ENABLE); + +#if defined CONFIG_SOC_MX6SL struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; val = readl(&iomux->gpr[11]); if (val & IOMUXC_GPR11_L2CACHE_AS_OCRAM) { @@ -395,6 +829,9 @@ void v7_outer_cache_enable(void) } #endif + /* Must disable the L2 before changing the latency parameters */ + clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); + writel(0x132, &pl310->pl310_tag_latency_ctrl); writel(0x132, &pl310->pl310_data_latency_ctrl); @@ -413,7 +850,7 @@ void v7_outer_cache_enable(void) * double linefill feature. This is the default behavior. */ -#ifndef CONFIG_MX6Q +#ifndef CONFIG_SOC_MX6Q val |= 0x40800000; #endif writel(val, &pl310->pl310_prefetch_ctrl);