/* * Hide the first two arguments to __cpu_suspend - these are an implementation * detail which platform code shouldn't have to know about. */ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) { struct mm_struct *mm = current->active_mm; u32 __mpidr = cpu_logical_map(smp_processor_id()); int ret; if (!idmap_pgd) return -EINVAL; /* * Provide a temporary page table with an identity mapping for * the MMU-enable code, required for resuming. On successful * resume (indicated by a zero return code), we need to switch * back to the correct page tables. */ ret = __cpu_suspend(arg, fn, __mpidr); if (ret == 0) { cpu_switch_mm(mm->pgd, mm); local_flush_tlb_all(); } else { local_flush_tlb_all_non_is(); } return ret; }
/* * Hide the first two arguments to __cpu_suspend - these are an implementation * detail which platform code shouldn't have to know about. */ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) { struct mm_struct *mm = current->active_mm; int ret; if (!idmap_pgd) return -EINVAL; /* * Provide a temporary page table with an identity mapping for * the MMU-enable code, required for resuming. On successful * resume (indicated by a zero return code), we need to switch * back to the correct page tables. */ ret = __cpu_suspend(arg, fn); if (ret == 0) { cpu_switch_mm(mm->pgd, mm); #if defined(CONFIG_BCM_KF_ARM_BCM963XX) local_flush_bp_all(); #endif local_flush_tlb_all(); } return ret; }
/** * cpu_suspend * * @arg: argument to pass to the finisher function */ int cpu_suspend(unsigned long arg) { struct mm_struct *mm = current->active_mm; int ret, cpu = smp_processor_id(); unsigned long flags; /* * If cpu_ops have not been registered or suspend * has not been initialized, cpu_suspend call fails early. */ if (!cpu_ops[cpu] || !cpu_ops[cpu]->cpu_suspend) return -EOPNOTSUPP; /* * From this point debug exceptions are disabled to prevent * updates to mdscr register (saved and restored along with * general purpose registers) from kernel debuggers. */ local_dbg_save(flags); /* * mm context saved on the stack, it will be restored when * the cpu comes out of reset through the identity mapped * page tables, so that the thread address space is properly * set-up on function return. */ ret = __cpu_suspend(arg); pclog(); if (ret == 0) { cpu_switch_mm(mm->pgd, mm); flush_tlb_all(); /* * Restore per-cpu offset before any kernel * subsystem relying on it has a chance to run. */ set_my_cpu_offset(per_cpu_offset(cpu)); /* * Restore HW breakpoint registers to sane values * before debug exceptions are possibly reenabled * through local_dbg_restore. */ if (hw_breakpoint_restore) hw_breakpoint_restore(NULL); } /* * Restore pstate flags. OS lock and mdscr have been already * restored, so from this point onwards, debugging is fully * renabled if it was enabled when core started shutdown. */ local_dbg_restore(flags); return ret; }
/** * cpu_suspend * * @arg: argument to pass to the finisher function * @fn: suspend finisher function, the function that executes last * operations required to suspend a processor */ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) { struct mm_struct *mm = current->active_mm; int ret; /* * Save the mm context on the stack, it will be restored when * the cpu comes out of reset through the identity mapped * page tables, so that the thread address space is properly * set-up on function return. */ ret = __cpu_suspend(arg, fn); if (ret == 0) { cpu_switch_mm(mm->pgd, mm); flush_tlb_all(); } return ret; }
static void __suspend_enter(enum suspend_state_t state) { __record_dbg_status(PM_SUSPEND_ENTER | 5); if (HAL_Wakeup_SetSrc(1)) return ; __record_dbg_status(PM_SUSPEND_ENTER | 6); debug_jtag_deinit(); PM_LOGN("device info. rst:%x clk:%x\n", CCM->BUS_PERIPH_RST_CTRL, CCM->BUS_PERIPH_CLK_CTRL); /* debug info. */ PM_SetCPUBootArg((uint32_t)&vault_arm_registers); if (state >= PM_MODE_HIBERNATION) { __record_dbg_status(PM_SUSPEND_ENTER | 7); PM_SetCPUBootArg(PM_MODE_MAGIC | state); #ifdef __CONFIG_ARCH_APP_CORE HAL_Wakeup_SetIOHold((1 << WAKEUP_IO_MAX) - 1); #endif pm_power_off(PM_SHUTDOWN); /* never return */ } else if (state < PM_MODE_STANDBY) { __record_dbg_status(PM_SUSPEND_ENTER | 8); /* TODO: set system bus to low freq */ __cpu_sleep(state); /* TODO: restore system bus to normal freq */ } else { __record_dbg_status(PM_SUSPEND_ENTER | 9); __cpu_suspend(state); } PM_BUG_ON(!PM_IRQ_GET_FLAGS()); __record_dbg_status(PM_SUSPEND_ENTER | 0xa); debug_jtag_init(); __record_dbg_status(PM_SUSPEND_ENTER | 0xb); HAL_Wakeup_ClrSrc(1); }
int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) { u32 __mpidr = cpu_logical_map(smp_processor_id()); return __cpu_suspend(arg, fn, __mpidr); }