1 /* 2 * MPC85xx PM operators 3 * 4 * Copyright 2015 Freescale Semiconductor Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2 of the License, or (at your 9 * option) any later version. 10 */ 11 12 #define pr_fmt(fmt) "%s: " fmt, __func__ 13 14 #include <linux/kernel.h> 15 #include <linux/of.h> 16 #include <linux/of_address.h> 17 #include <linux/fsl/guts.h> 18 19 #include <asm/io.h> 20 #include <asm/fsl_pm.h> 21 22 static struct ccsr_guts __iomem *guts; 23 24 static void mpc85xx_irq_mask(int cpu) 25 { 26 27 } 28 29 static void mpc85xx_irq_unmask(int cpu) 30 { 31 32 } 33 34 static void mpc85xx_cpu_die(int cpu) 35 { 36 u32 tmp; 37 38 tmp = (mfspr(SPRN_HID0) & ~(HID0_DOZE|HID0_SLEEP)) | HID0_NAP; 39 mtspr(SPRN_HID0, tmp); 40 41 /* Enter NAP mode. */ 42 tmp = mfmsr(); 43 tmp |= MSR_WE; 44 asm volatile( 45 "msync\n" 46 "mtmsr %0\n" 47 "isync\n" 48 : 49 : "r" (tmp)); 50 } 51 52 static void mpc85xx_cpu_up_prepare(int cpu) 53 { 54 55 } 56 57 static void mpc85xx_freeze_time_base(bool freeze) 58 { 59 uint32_t mask; 60 61 mask = CCSR_GUTS_DEVDISR_TB0 | CCSR_GUTS_DEVDISR_TB1; 62 if (freeze) 63 setbits32(&guts->devdisr, mask); 64 else 65 clrbits32(&guts->devdisr, mask); 66 67 in_be32(&guts->devdisr); 68 } 69 70 static const struct of_device_id mpc85xx_smp_guts_ids[] = { 71 { .compatible = "fsl,mpc8572-guts", }, 72 { .compatible = "fsl,p1020-guts", }, 73 { .compatible = "fsl,p1021-guts", }, 74 { .compatible = "fsl,p1022-guts", }, 75 { .compatible = "fsl,p1023-guts", }, 76 { .compatible = "fsl,p2020-guts", }, 77 { .compatible = "fsl,bsc9132-guts", }, 78 {}, 79 }; 80 81 static const struct fsl_pm_ops mpc85xx_pm_ops = { 82 .freeze_time_base = mpc85xx_freeze_time_base, 83 .irq_mask = mpc85xx_irq_mask, 84 .irq_unmask = mpc85xx_irq_unmask, 85 .cpu_die = mpc85xx_cpu_die, 86 .cpu_up_prepare = mpc85xx_cpu_up_prepare, 87 }; 88 89 int __init mpc85xx_setup_pmc(void) 90 { 91 struct device_node *np; 92 93 np = of_find_matching_node(NULL, mpc85xx_smp_guts_ids); 94 if (np) { 95 guts = of_iomap(np, 0); 96 of_node_put(np); 97 if (!guts) { 98 pr_err("Could not map guts node address\n"); 99 return -ENOMEM; 100 } 101 } 102 103 qoriq_pm_ops = &mpc85xx_pm_ops; 104 105 return 0; 106 } 107