1*95322526SLorenzo Pieralisi #include <linux/slab.h> 2*95322526SLorenzo Pieralisi #include <asm/cacheflush.h> 3*95322526SLorenzo Pieralisi #include <asm/cpu_ops.h> 4*95322526SLorenzo Pieralisi #include <asm/debug-monitors.h> 5*95322526SLorenzo Pieralisi #include <asm/pgtable.h> 6*95322526SLorenzo Pieralisi #include <asm/memory.h> 7*95322526SLorenzo Pieralisi #include <asm/smp_plat.h> 8*95322526SLorenzo Pieralisi #include <asm/suspend.h> 9*95322526SLorenzo Pieralisi #include <asm/tlbflush.h> 10*95322526SLorenzo Pieralisi 11*95322526SLorenzo Pieralisi extern int __cpu_suspend(unsigned long); 12*95322526SLorenzo Pieralisi /* 13*95322526SLorenzo Pieralisi * This is called by __cpu_suspend() to save the state, and do whatever 14*95322526SLorenzo Pieralisi * flushing is required to ensure that when the CPU goes to sleep we have 15*95322526SLorenzo Pieralisi * the necessary data available when the caches are not searched. 16*95322526SLorenzo Pieralisi * 17*95322526SLorenzo Pieralisi * @arg: Argument to pass to suspend operations 18*95322526SLorenzo Pieralisi * @ptr: CPU context virtual address 19*95322526SLorenzo Pieralisi * @save_ptr: address of the location where the context physical address 20*95322526SLorenzo Pieralisi * must be saved 21*95322526SLorenzo Pieralisi */ 22*95322526SLorenzo Pieralisi int __cpu_suspend_finisher(unsigned long arg, struct cpu_suspend_ctx *ptr, 23*95322526SLorenzo Pieralisi phys_addr_t *save_ptr) 24*95322526SLorenzo Pieralisi { 25*95322526SLorenzo Pieralisi int cpu = smp_processor_id(); 26*95322526SLorenzo Pieralisi 27*95322526SLorenzo Pieralisi *save_ptr = virt_to_phys(ptr); 28*95322526SLorenzo Pieralisi 29*95322526SLorenzo Pieralisi cpu_do_suspend(ptr); 30*95322526SLorenzo Pieralisi /* 31*95322526SLorenzo Pieralisi * Only flush the context that must be retrieved with the MMU 32*95322526SLorenzo Pieralisi * off. VA primitives ensure the flush is applied to all 33*95322526SLorenzo Pieralisi * cache levels so context is pushed to DRAM. 34*95322526SLorenzo Pieralisi */ 35*95322526SLorenzo Pieralisi __flush_dcache_area(ptr, sizeof(*ptr)); 36*95322526SLorenzo Pieralisi __flush_dcache_area(save_ptr, sizeof(*save_ptr)); 37*95322526SLorenzo Pieralisi 38*95322526SLorenzo Pieralisi return cpu_ops[cpu]->cpu_suspend(arg); 39*95322526SLorenzo Pieralisi } 40*95322526SLorenzo Pieralisi 41*95322526SLorenzo Pieralisi /** 42*95322526SLorenzo Pieralisi * cpu_suspend 43*95322526SLorenzo Pieralisi * 44*95322526SLorenzo Pieralisi * @arg: argument to pass to the finisher function 45*95322526SLorenzo Pieralisi */ 46*95322526SLorenzo Pieralisi int cpu_suspend(unsigned long arg) 47*95322526SLorenzo Pieralisi { 48*95322526SLorenzo Pieralisi struct mm_struct *mm = current->active_mm; 49*95322526SLorenzo Pieralisi int ret, cpu = smp_processor_id(); 50*95322526SLorenzo Pieralisi unsigned long flags; 51*95322526SLorenzo Pieralisi 52*95322526SLorenzo Pieralisi /* 53*95322526SLorenzo Pieralisi * If cpu_ops have not been registered or suspend 54*95322526SLorenzo Pieralisi * has not been initialized, cpu_suspend call fails early. 55*95322526SLorenzo Pieralisi */ 56*95322526SLorenzo Pieralisi if (!cpu_ops[cpu] || !cpu_ops[cpu]->cpu_suspend) 57*95322526SLorenzo Pieralisi return -EOPNOTSUPP; 58*95322526SLorenzo Pieralisi 59*95322526SLorenzo Pieralisi /* 60*95322526SLorenzo Pieralisi * From this point debug exceptions are disabled to prevent 61*95322526SLorenzo Pieralisi * updates to mdscr register (saved and restored along with 62*95322526SLorenzo Pieralisi * general purpose registers) from kernel debuggers. 63*95322526SLorenzo Pieralisi */ 64*95322526SLorenzo Pieralisi local_dbg_save(flags); 65*95322526SLorenzo Pieralisi 66*95322526SLorenzo Pieralisi /* 67*95322526SLorenzo Pieralisi * mm context saved on the stack, it will be restored when 68*95322526SLorenzo Pieralisi * the cpu comes out of reset through the identity mapped 69*95322526SLorenzo Pieralisi * page tables, so that the thread address space is properly 70*95322526SLorenzo Pieralisi * set-up on function return. 71*95322526SLorenzo Pieralisi */ 72*95322526SLorenzo Pieralisi ret = __cpu_suspend(arg); 73*95322526SLorenzo Pieralisi if (ret == 0) { 74*95322526SLorenzo Pieralisi cpu_switch_mm(mm->pgd, mm); 75*95322526SLorenzo Pieralisi flush_tlb_all(); 76*95322526SLorenzo Pieralisi } 77*95322526SLorenzo Pieralisi 78*95322526SLorenzo Pieralisi /* 79*95322526SLorenzo Pieralisi * Restore pstate flags. OS lock and mdscr have been already 80*95322526SLorenzo Pieralisi * restored, so from this point onwards, debugging is fully 81*95322526SLorenzo Pieralisi * renabled if it was enabled when core started shutdown. 82*95322526SLorenzo Pieralisi */ 83*95322526SLorenzo Pieralisi local_dbg_restore(flags); 84*95322526SLorenzo Pieralisi 85*95322526SLorenzo Pieralisi return ret; 86*95322526SLorenzo Pieralisi } 87*95322526SLorenzo Pieralisi 88*95322526SLorenzo Pieralisi extern struct sleep_save_sp sleep_save_sp; 89*95322526SLorenzo Pieralisi extern phys_addr_t sleep_idmap_phys; 90*95322526SLorenzo Pieralisi 91*95322526SLorenzo Pieralisi static int cpu_suspend_init(void) 92*95322526SLorenzo Pieralisi { 93*95322526SLorenzo Pieralisi void *ctx_ptr; 94*95322526SLorenzo Pieralisi 95*95322526SLorenzo Pieralisi /* ctx_ptr is an array of physical addresses */ 96*95322526SLorenzo Pieralisi ctx_ptr = kcalloc(mpidr_hash_size(), sizeof(phys_addr_t), GFP_KERNEL); 97*95322526SLorenzo Pieralisi 98*95322526SLorenzo Pieralisi if (WARN_ON(!ctx_ptr)) 99*95322526SLorenzo Pieralisi return -ENOMEM; 100*95322526SLorenzo Pieralisi 101*95322526SLorenzo Pieralisi sleep_save_sp.save_ptr_stash = ctx_ptr; 102*95322526SLorenzo Pieralisi sleep_save_sp.save_ptr_stash_phys = virt_to_phys(ctx_ptr); 103*95322526SLorenzo Pieralisi sleep_idmap_phys = virt_to_phys(idmap_pg_dir); 104*95322526SLorenzo Pieralisi __flush_dcache_area(&sleep_save_sp, sizeof(struct sleep_save_sp)); 105*95322526SLorenzo Pieralisi __flush_dcache_area(&sleep_idmap_phys, sizeof(sleep_idmap_phys)); 106*95322526SLorenzo Pieralisi 107*95322526SLorenzo Pieralisi return 0; 108*95322526SLorenzo Pieralisi } 109*95322526SLorenzo Pieralisi early_initcall(cpu_suspend_init); 110