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; }
static int mx6_suspend_enter(suspend_state_t state) { unsigned int wake_irq_isr[4]; struct gic_dist_state gds; struct gic_cpu_state gcs; 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 TKT094231: can't support ARM_POWER_OFF mode */ if (state == PM_SUSPEND_MEM && cpu_is_mx6dl()) state = PM_SUSPEND_STANDBY; switch (state) { case PM_SUSPEND_MEM: gpu_power_down(); usb_power_down_handler(); mxc_cpu_lp_set(ARM_POWER_OFF); break; case PM_SUSPEND_STANDBY: mxc_cpu_lp_set(STOP_POWER_OFF); break; default: return -EINVAL; } if (state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY) { if (pm_data && pm_data->suspend_enter) pm_data->suspend_enter(); local_flush_tlb_all(); flush_cache_all(); if (state == PM_SUSPEND_MEM) { /* preserve gic state */ save_gic_dist_state(0, &gds); save_gic_cpu_state(0, &gcs); } suspend_in_iram(state, (unsigned long)iram_paddr, (unsigned long)suspend_iram_base); if (state == PM_SUSPEND_MEM) { /* restore gic registers */ restore_gic_dist_state(0, &gds); restore_gic_cpu_state(0, &gcs); usb_power_up_handler(); gpu_power_up(); } mx6_suspend_restore(); if (pm_data && pm_data->suspend_exit) pm_data->suspend_exit(); } else { cpu_do_idle(); } return 0; }