void arch_idle_multi_core(void) { u32 reg; int cpu = smp_processor_id(); #ifdef CONFIG_LOCAL_TIMERS if (!tick_broadcast_oneshot_active() || !tick_oneshot_mode_active()) return; clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); #endif /* iMX6Q and iMX6DL */ if ((cpu_is_mx6q() && chip_rev >= IMX_CHIP_REVISION_1_2) || (cpu_is_mx6dl() && chip_rev >= IMX_CHIP_REVISION_1_1)) { /* * This code should only be executed on MX6QTO1.2 or later * and MX6DL TO1.1 or later. * These chips have the HW fix for the WAIT mode issue. * Ensure that the CGPR bit 17 is set to enable the fix. */ reg = __raw_readl(MXC_CCM_CGPR); reg |= MXC_CCM_CGPR_WAIT_MODE_FIX; __raw_writel(reg, MXC_CCM_CGPR); ca9_do_idle(); } else arch_idle_with_workaround(cpu); #ifdef CONFIG_LOCAL_TIMERS clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); #endif }
static bool tick_check_preferred(struct clock_event_device *curdev, struct clock_event_device *newdev) { /* Prefer oneshot capable device */ if (!(newdev->features & CLOCK_EVT_FEAT_ONESHOT)) { if (curdev && (curdev->features & CLOCK_EVT_FEAT_ONESHOT)) return false; if (tick_oneshot_mode_active()) return false; } /* Use the higher rated one */ return !curdev || newdev->rating > curdev->rating; }
void arch_idle(void) { int cpu = smp_processor_id(); if (enable_wait_mode) { #ifdef CONFIG_LOCAL_TIMERS if (!tick_broadcast_oneshot_active() || !tick_oneshot_mode_active()) return; clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); #endif if (enet_is_active) /* Don't allow the chip to enter WAIT mode if enet is active * and the GPIO workaround for ENET interrupts is not used, * since all ENET interrupts donot wake up the SOC. */ mxc_cpu_lp_set(WAIT_CLOCKED); else mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); if (mem_clk_on_in_wait) { u32 reg; /* * MX6SL, MX6Q (TO1.2 or later) and * MX6DL (TO1.1 or later) have a bit in * CCM_CGPR that when cleared keeps the * clocks to memories ON when ARM is in WFI. * This mode can be used when IPG clock is * very low (12MHz) and the ARM:IPG ratio * perhaps cannot be maintained. */ reg = __raw_readl(MXC_CCM_CGPR); reg &= ~MXC_CCM_CGPR_MEM_IPG_STOP_MASK; __raw_writel(reg, MXC_CCM_CGPR); ca9_do_idle(); } else if (num_possible_cpus() == 1) /* iMX6SL or iMX6DLS */ arch_idle_single_core(); else arch_idle_multi_core(cpu); #ifdef CONFIG_LOCAL_TIMERS clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); #endif } else { mxc_cpu_lp_set(WAIT_CLOCKED); ca9_do_idle(); } }
static bool tick_check_preferred(struct clock_event_device *curdev, struct clock_event_device *newdev) { /* Prefer oneshot capable device */ if (!(newdev->features & CLOCK_EVT_FEAT_ONESHOT)) { if (curdev && (curdev->features & CLOCK_EVT_FEAT_ONESHOT)) return false; if (tick_oneshot_mode_active()) return false; } /* * Use the higher rated one, but prefer a CPU local device with a lower * rating than a non-CPU local device */ return !curdev || newdev->rating > curdev->rating || !cpumask_equal(curdev->cpumask, newdev->cpumask); }