bool usb_icbug_swfix_need(void) { if (cpu_is_mx6sl()) return false; else if ((mx6q_revision() > IMX_CHIP_REVISION_1_1)) return false; else if ((mx6dl_revision() > IMX_CHIP_REVISION_1_0)) return false; return true; }
static void mx6_set_cpu_type(void) { u32 cpu_type = readl(IO_ADDRESS(ANATOP_BASE_ADDR + 0x280)); cpu_type >>= 16; if (cpu_type == 0x60) { mxc_set_cpu_type(MXC_CPU_MX6SL); imx_print_silicon_rev("i.MX6SoloLite", mx6sl_revision()); return; } cpu_type = readl(IO_ADDRESS(ANATOP_BASE_ADDR + 0x260)); cpu_type >>= 16; if (cpu_type == 0x63) { mxc_set_cpu_type(MXC_CPU_MX6Q); imx_print_silicon_rev("i.MX6Q", mx6q_revision()); } else if (cpu_type == 0x61) { mxc_set_cpu_type(MXC_CPU_MX6DL); imx_print_silicon_rev("i.MX6DL/SOLO", mx6dl_revision()); } else pr_err("Unknown CPU type: %x\n", cpu_type); }
static int mx6_suspend_enter(suspend_state_t state) { unsigned int wake_irq_isr[4]; unsigned int cpu_type; struct gic_dist_state gds; struct gic_cpu_state gcs; bool arm_pg = false; if (cpu_is_mx6q()) cpu_type = MXC_CPU_MX6Q; else if (cpu_is_mx6dl()) cpu_type = MXC_CPU_MX6DL; else cpu_type = MXC_CPU_MX6SL; wake_irq_isr[0] = __raw_readl(gpc_base + GPC_ISR1_OFFSET) & gpc_wake_irq[0]; wake_irq_isr[1] = __raw_readl(gpc_base + GPC_ISR2_OFFSET) & gpc_wake_irq[1]; wake_irq_isr[2] = __raw_readl(gpc_base + GPC_ISR3_OFFSET) & gpc_wake_irq[2]; wake_irq_isr[3] = __raw_readl(gpc_base + GPC_ISR4_OFFSET) & gpc_wake_irq[3]; if (wake_irq_isr[0] | wake_irq_isr[1] | wake_irq_isr[2] | wake_irq_isr[3]) { printk(KERN_INFO "There are wakeup irq pending,system resume!\n"); printk(KERN_INFO "wake_irq_isr[0-3]: 0x%x, 0x%x, 0x%x, 0x%x\n", wake_irq_isr[0], wake_irq_isr[1], wake_irq_isr[2], wake_irq_isr[3]); return 0; } mx6_suspend_store(); /* * i.MX6dl TO1.0/i.MX6dq TO1.1/1.0 TKT094231: can't support * ARM_POWER_OFF mode. */ if (state == PM_SUSPEND_MEM && ((mx6dl_revision() == IMX_CHIP_REVISION_1_0) || (cpu_is_mx6q() && mx6q_revision() <= IMX_CHIP_REVISION_1_1))) { state = PM_SUSPEND_STANDBY; } switch (state) { case PM_SUSPEND_MEM: disp_power_down(); usb_power_down_handler(); mxc_cpu_lp_set(ARM_POWER_OFF); arm_pg = true; break; case PM_SUSPEND_STANDBY: if (cpu_is_mx6sl()) { disp_power_down(); usb_power_down_handler(); mxc_cpu_lp_set(STOP_XTAL_ON); arm_pg = true; } else mxc_cpu_lp_set(STOP_POWER_OFF); break; default: return -EINVAL; } /* * L2 can exit by 'reset' or Inband beacon (from remote EP) * toggling phy_powerdown has same effect as 'inband beacon' * So, toggle bit18 of GPR1, to fix errata * "PCIe PCIe does not support L2 Power Down" */ __raw_writel(__raw_readl(IOMUXC_GPR1) | (1 << 18), IOMUXC_GPR1); if (state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY) { local_flush_tlb_all(); flush_cache_all(); if (arm_pg) { /* preserve gic state */ save_gic_dist_state(0, &gds); save_gic_cpu_state(0, &gcs); } if (pm_data && pm_data->suspend_enter) pm_data->suspend_enter(); suspend_in_iram(state, (unsigned long)iram_paddr, (unsigned long)suspend_iram_base, cpu_type); if (pm_data && pm_data->suspend_exit) pm_data->suspend_exit(); /* Reset the RBC counter. */ /* All interrupts should be masked before the * RBC counter is reset. */ /* Mask all interrupts. These will be unmasked by * the mx6_suspend_restore routine below. */ __raw_writel(0xffffffff, gpc_base + 0x08); __raw_writel(0xffffffff, gpc_base + 0x0c); __raw_writel(0xffffffff, gpc_base + 0x10); __raw_writel(0xffffffff, gpc_base + 0x14); /* Clear the RBC counter and RBC_EN bit. */ /* Disable the REG_BYPASS_COUNTER. */ __raw_writel(__raw_readl(MXC_CCM_CCR) & ~MXC_CCM_CCR_RBC_EN, MXC_CCM_CCR); /* Make sure we clear REG_BYPASS_COUNT*/ __raw_writel(__raw_readl(MXC_CCM_CCR) & (~MXC_CCM_CCR_REG_BYPASS_CNT_MASK), MXC_CCM_CCR); /* Need to wait for a minimum of 2 CLKILS (32KHz) for the * counter to clear and reset. */ udelay(80); if (arm_pg) { /* restore gic registers */ restore_gic_dist_state(0, &gds); restore_gic_cpu_state(0, &gcs); } if (state == PM_SUSPEND_MEM || (cpu_is_mx6sl())) { usb_power_up_handler(); disp_power_up(); } mx6_suspend_restore(); __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, anatop_base + HW_ANADIG_ANA_MISC0_CLR); } else { cpu_do_idle(); } /* * L2 can exit by 'reset' or Inband beacon (from remote EP) * toggling phy_powerdown has same effect as 'inband beacon' * So, toggle bit18 of GPR1, to fix errata * "PCIe PCIe does not support L2 Power Down" */ __raw_writel(__raw_readl(IOMUXC_GPR1) & (~(1 << 18)), IOMUXC_GPR1); return 0; }
/* set cpu low power mode before WFI instruction */ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode) { int stop_mode = 0; void __iomem *anatop_base = IO_ADDRESS(ANATOP_BASE_ADDR); u32 ccm_clpcr, anatop_val; ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK); switch (mode) { case WAIT_CLOCKED: break; case WAIT_UNCLOCKED: ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET; break; case WAIT_UNCLOCKED_POWER_OFF: case STOP_POWER_OFF: case ARM_POWER_OFF: if (mode == WAIT_UNCLOCKED_POWER_OFF) { ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY; ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS; ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET; if (cpu_is_mx6sl()) { ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS; ccm_clpcr |= MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY; } else ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS; stop_mode = 0; } else if (mode == STOP_POWER_OFF) { ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET; ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET; ccm_clpcr |= MXC_CCM_CLPCR_VSTBY; ccm_clpcr |= MXC_CCM_CLPCR_SBYOS; if (cpu_is_mx6sl()) { ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS; ccm_clpcr |= MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY; } else ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS; stop_mode = 1; } else { ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET; ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET; ccm_clpcr |= MXC_CCM_CLPCR_VSTBY; ccm_clpcr |= MXC_CCM_CLPCR_SBYOS; if (cpu_is_mx6sl()) { ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS; ccm_clpcr |= MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY; } else ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS; stop_mode = 2; } break; case STOP_XTAL_ON: ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET; ccm_clpcr |= MXC_CCM_CLPCR_VSTBY; ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS; if (cpu_is_mx6sl()) { ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS; ccm_clpcr |= MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY; } else ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS; stop_mode = 3; break; default: printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode); return; } if (stop_mode > 0) { gpc_set_wakeup(gpc_wake_irq); /* Power down and power up sequence */ /* The PUPSCR counter counts in terms of CLKIL (32KHz) cycles. * The PUPSCR should include the time it takes for the ARM LDO to * ramp up. */ __raw_writel(0x202, gpc_base + GPC_PGC_CPU_PUPSCR_OFFSET); /* The PDNSCR is a counter that counts in IPG_CLK cycles. This counter * can be set to minimum values to power down faster. */ __raw_writel(0x101, gpc_base + GPC_PGC_CPU_PDNSCR_OFFSET); if (stop_mode >= 2) { /* dormant mode, need to power off the arm core */ __raw_writel(0x1, gpc_base + GPC_PGC_CPU_PDN_OFFSET); if (cpu_is_mx6q() || cpu_is_mx6dl()) { /* If stop_mode_config is clear, then 2P5 will be off, need to enable weak 2P5, as DDR IO need 2P5 as pre-driver */ if ((__raw_readl(anatop_base + HW_ANADIG_ANA_MISC0) & BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG) == 0) { /* Enable weak 2P5 linear regulator */ anatop_val = __raw_readl(anatop_base + HW_ANADIG_REG_2P5); anatop_val |= BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG; __raw_writel(anatop_val, anatop_base + HW_ANADIG_REG_2P5); } if (mx6q_revision() != IMX_CHIP_REVISION_1_0) { /* Enable fet_odrive */ anatop_val = __raw_readl(anatop_base + HW_ANADIG_REG_CORE); anatop_val |= BM_ANADIG_REG_CORE_FET_ODRIVE; __raw_writel(anatop_val, anatop_base + HW_ANADIG_REG_CORE); } } else { if (stop_mode == 2) { /* Disable VDDHIGH_IN to VDDSNVS_IN * power path, only used when VDDSNVS_IN * is powered by dedicated * power rail */ anatop_val = __raw_readl(anatop_base + HW_ANADIG_ANA_MISC0); anatop_val |= BM_ANADIG_ANA_MISC0_RTC_RINGOSC_EN; __raw_writel(anatop_val, anatop_base + HW_ANADIG_ANA_MISC0); /* Need to enable pull down if 2P5 is disabled */ anatop_val = __raw_readl(anatop_base + HW_ANADIG_REG_2P5); anatop_val |= BM_ANADIG_REG_2P5_ENABLE_PULLDOWN; __raw_writel(anatop_val, anatop_base + HW_ANADIG_REG_2P5); } } if (stop_mode != 3) { /* Make sure we clear WB_COUNT * and re-config it. */ __raw_writel(__raw_readl(MXC_CCM_CCR) & (~MXC_CCM_CCR_WB_COUNT_MASK), MXC_CCM_CCR); /* Reconfigure WB, need to set WB counter * to 0x7 to make sure it work normally */ __raw_writel(__raw_readl(MXC_CCM_CCR) | (0x7 << MXC_CCM_CCR_WB_COUNT_OFFSET), MXC_CCM_CCR); /* Set WB_PER enable */ ccm_clpcr |= MXC_CCM_CLPCR_WB_PER_AT_LPM; } } if (cpu_is_mx6sl() || (mx6q_revision() > IMX_CHIP_REVISION_1_1) || (mx6dl_revision() > IMX_CHIP_REVISION_1_0)) { u32 reg; /* We need to allow the memories to be clock gated * in STOP mode, else the power consumption will * be very high. */ reg = __raw_readl(MXC_CCM_CGPR); reg |= MXC_CCM_CGPR_MEM_IPG_STOP_MASK; if (!cpu_is_mx6sl()) { /* * For MX6QTO1.2 or later and MX6DLTO1.1 or later, * ensure that the CCM_CGPR bit 17 is cleared before * dormant mode is entered. */ reg &= ~MXC_CCM_CGPR_WAIT_MODE_FIX; } __raw_writel(reg, MXC_CCM_CGPR); } } __raw_writel(ccm_clpcr, MXC_CCM_CLPCR); }
unsigned int hdmi_SDMA_check(void) { return (mx6q_revision() > IMX_CHIP_REVISION_1_1) || (mx6dl_revision() > IMX_CHIP_REVISION_1_0); }
static int __init post_cpu_init(void) { unsigned int reg; void __iomem *base; u32 iram_size; if (cpu_is_mx6q()) iram_size = MX6Q_IRAM_SIZE; else iram_size = MX6DL_MX6SL_IRAM_SIZE; iram_init(MX6Q_IRAM_BASE_ADDR, iram_size); base = ioremap(AIPS1_ON_BASE_ADDR, PAGE_SIZE); __raw_writel(0x0, base + 0x40); __raw_writel(0x0, base + 0x44); __raw_writel(0x0, base + 0x48); __raw_writel(0x0, base + 0x4C); reg = __raw_readl(base + 0x50) & 0x00FFFFFF; __raw_writel(reg, base + 0x50); iounmap(base); base = ioremap(AIPS2_ON_BASE_ADDR, PAGE_SIZE); __raw_writel(0x0, base + 0x40); __raw_writel(0x0, base + 0x44); __raw_writel(0x0, base + 0x48); __raw_writel(0x0, base + 0x4C); reg = __raw_readl(base + 0x50) & 0x00FFFFFF; __raw_writel(reg, base + 0x50); iounmap(base); /* Allow SCU_CLK to be disabled when all cores are in WFI*/ base = IO_ADDRESS(SCU_BASE_ADDR); reg = __raw_readl(base); reg |= 0x20; __raw_writel(reg, base); /* Disable SRC warm reset to work aound system reboot issue */ base = IO_ADDRESS(SRC_BASE_ADDR); reg = __raw_readl(base); reg &= ~0x1; __raw_writel(reg, base); gpc_base = MX6_IO_ADDRESS(GPC_BASE_ADDR); ccm_base = MX6_IO_ADDRESS(CCM_BASE_ADDR); /* enable AXI cache for VDOA/VPU/IPU * set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 * clear OCRAM_CTL bits to disable pipeline control */ reg = __raw_readl(IOMUXC_GPR3); reg &= ~IOMUXC_GPR3_OCRAM_CTL_EN; __raw_writel(reg, IOMUXC_GPR3); reg = __raw_readl(IOMUXC_GPR4); reg |= IOMUXC_GPR4_VDOA_CACHE_EN | IOMUXC_GPR4_VPU_CACHE_EN | IOMUXC_GPR4_IPU_CACHE_EN; __raw_writel(reg, IOMUXC_GPR4); __raw_writel(IOMUXC_GPR6_IPU1_QOS, IOMUXC_GPR6); __raw_writel(IOMUXC_GPR7_IPU2_QOS, IOMUXC_GPR7); num_cpu_idle_lock = 0x0; if (cpu_is_mx6dl()) num_cpu_idle_lock = 0xffff0000; #ifdef CONFIG_SMP switch (setup_max_cpus) { case 3: num_cpu_idle_lock = 0xff000000; break; case 2: num_cpu_idle_lock = 0xffff0000; break; case 1: case 0: num_cpu_idle_lock = 0xffffff00; break; } #endif /* * The option to keep ARM memory clocks enabled during WAIT * is only available on MX6SL, MX6DQ TO1.2 (or later) and * MX6DL TO1.1 (or later) * So if the user specifies "mem_clk_on" on any other chip, * ensure that it is disabled. */ if (!cpu_is_mx6sl() && (mx6q_revision() < IMX_CHIP_REVISION_1_2) && (mx6dl_revision() < IMX_CHIP_REVISION_1_1)) mem_clk_on_in_wait = false; if (cpu_is_mx6q()) chip_rev = mx6q_revision(); else if (cpu_is_mx6dl()) chip_rev = mx6dl_revision(); else chip_rev = mx6sl_revision(); /* mx6sl doesn't have pcie. save power, disable PCIe PHY */ if (!cpu_is_mx6sl()) { reg = __raw_readl(IOMUXC_GPR1); reg = reg & (~IOMUXC_GPR1_PCIE_REF_CLK_EN); reg |= IOMUXC_GPR1_TEST_POWERDOWN; __raw_writel(reg, IOMUXC_GPR1); } return 0; }