1d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo/* 2d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * PowerPC 4xx Clock and Power Management 3d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * 4d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * Copyright (C) 2010, Applied Micro Circuits Corporation 5d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * Victor Gallardo (vgallardo@apm.com) 6d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * 7d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * Based on arch/powerpc/platforms/44x/idle.c: 8d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * Jerone Young <jyoung5@us.ibm.com> 9d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * Copyright 2008 IBM Corp. 10d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * 11d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * Based on arch/powerpc/sysdev/fsl_pmc.c: 12d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * Anton Vorontsov <avorontsov@ru.mvista.com> 13d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * Copyright 2009 MontaVista Software, Inc. 14d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * 15d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * See file CREDITS for list of people who contributed to this 16d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * project. 17d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * 18d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * This program is free software; you can redistribute it and/or 19d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * modify it under the terms of the GNU General Public License as 20d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * published by the Free Software Foundation; either version 2 of 21d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * the License, or (at your option) any later version. 22d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * 23d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * This program is distributed in the hope that it will be useful, 24d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * but WITHOUT ANY WARRANTY; without even the implied warranty of 25d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * GNU General Public License for more details. 27d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * 28d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * You should have received a copy of the GNU General Public License 29d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * along with this program; if not, write to the Free Software 30d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 31d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * MA 02111-1307 USA 32d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo */ 33d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 34d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo#include <linux/kernel.h> 35d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo#include <linux/of_platform.h> 36d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo#include <linux/sysfs.h> 37d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo#include <linux/cpu.h> 38d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo#include <linux/suspend.h> 39d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo#include <asm/dcr.h> 40d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo#include <asm/dcr-native.h> 41d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo#include <asm/machdep.h> 42d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 43d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo#define CPM_ER 0 44d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo#define CPM_FR 1 45d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo#define CPM_SR 2 46d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 47d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo#define CPM_IDLE_WAIT 0 48d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo#define CPM_IDLE_DOZE 1 49d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 50d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostruct cpm { 51d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo dcr_host_t dcr_host; 52d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo unsigned int dcr_offset[3]; 53d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo unsigned int powersave_off; 54d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo unsigned int unused; 55d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo unsigned int idle_doze; 56d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo unsigned int standby; 57d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo unsigned int suspend; 58d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo}; 59d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 60d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic struct cpm cpm; 61d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 62d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostruct cpm_idle_mode { 63d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo unsigned int enabled; 64d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo const char *name; 65d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo}; 66d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 67d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic struct cpm_idle_mode idle_mode[] = { 68d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo [CPM_IDLE_WAIT] = { 1, "wait" }, /* default */ 69d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo [CPM_IDLE_DOZE] = { 0, "doze" }, 70d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo}; 71d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 72d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic unsigned int cpm_set(unsigned int cpm_reg, unsigned int mask) 73d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo{ 74d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo unsigned int value; 75d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 76d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo /* CPM controller supports 3 different types of sleep interface 77d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * known as class 1, 2 and 3. For class 1 units, they are 78d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * unconditionally put to sleep when the corresponding CPM bit is 79d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * set. For class 2 and 3 units this is not case; if they can be 80d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * put to to sleep, they will. Here we do not verify, we just 81d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * set them and expect them to eventually go off when they can. 82d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo */ 83d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo value = dcr_read(cpm.dcr_host, cpm.dcr_offset[cpm_reg]); 84d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo dcr_write(cpm.dcr_host, cpm.dcr_offset[cpm_reg], value | mask); 85d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 86d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo /* return old state, to restore later if needed */ 87d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo return value; 88d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo} 89d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 90d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic void cpm_idle_wait(void) 91d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo{ 92d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo unsigned long msr_save; 93d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 94d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo /* save off initial state */ 95d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo msr_save = mfmsr(); 96d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo /* sync required when CPM0_ER[CPU] is set */ 97d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo mb(); 98d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo /* set wait state MSR */ 99d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo mtmsr(msr_save|MSR_WE|MSR_EE|MSR_CE|MSR_DE); 100d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo isync(); 101d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo /* return to initial state */ 102d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo mtmsr(msr_save); 103d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo isync(); 104d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo} 105d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 106d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic void cpm_idle_sleep(unsigned int mask) 107d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo{ 108d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo unsigned int er_save; 109d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 110d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo /* update CPM_ER state */ 111d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo er_save = cpm_set(CPM_ER, mask); 112d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 113d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo /* go to wait state so that CPM0_ER[CPU] can take effect */ 114d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm_idle_wait(); 115d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 116d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo /* restore CPM_ER state */ 117d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo dcr_write(cpm.dcr_host, cpm.dcr_offset[CPM_ER], er_save); 118d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo} 119d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 120d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic void cpm_idle_doze(void) 121d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo{ 122d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm_idle_sleep(cpm.idle_doze); 123d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo} 124d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 125d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic void cpm_idle_config(int mode) 126d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo{ 127d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo int i; 128d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 129d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo if (idle_mode[mode].enabled) 130d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo return; 131d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 132d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo for (i = 0; i < ARRAY_SIZE(idle_mode); i++) 133d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo idle_mode[i].enabled = 0; 134d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 135d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo idle_mode[mode].enabled = 1; 136d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo} 137d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 138d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic ssize_t cpm_idle_show(struct kobject *kobj, 139d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo struct kobj_attribute *attr, char *buf) 140d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo{ 141d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo char *s = buf; 142d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo int i; 143d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 144d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo for (i = 0; i < ARRAY_SIZE(idle_mode); i++) { 145d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo if (idle_mode[i].enabled) 146d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo s += sprintf(s, "[%s] ", idle_mode[i].name); 147d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo else 148d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo s += sprintf(s, "%s ", idle_mode[i].name); 149d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo } 150d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 151d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo *(s-1) = '\n'; /* convert the last space to a newline */ 152d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 153d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo return s - buf; 154d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo} 155d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 156d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic ssize_t cpm_idle_store(struct kobject *kobj, 157d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo struct kobj_attribute *attr, 158d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo const char *buf, size_t n) 159d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo{ 160d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo int i; 161d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo char *p; 162d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo int len; 163d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 164d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo p = memchr(buf, '\n', n); 165d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo len = p ? p - buf : n; 166d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 167d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo for (i = 0; i < ARRAY_SIZE(idle_mode); i++) { 168d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo if (strncmp(buf, idle_mode[i].name, len) == 0) { 169d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm_idle_config(i); 170d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo return n; 171d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo } 172d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo } 173d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 174d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo return -EINVAL; 175d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo} 176d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 177d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic struct kobj_attribute cpm_idle_attr = 178d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo __ATTR(idle, 0644, cpm_idle_show, cpm_idle_store); 179d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 180d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic void cpm_idle_config_sysfs(void) 181d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo{ 1828a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers struct device *dev; 183d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo unsigned long ret; 184d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 1858a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers dev = get_cpu_device(0); 186d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 1878a25a2fd126c621f44f3aeaef80d51f00fc11639Kay Sievers ret = sysfs_create_file(&dev->kobj, 188d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo &cpm_idle_attr.attr); 189d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo if (ret) 190d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo printk(KERN_WARNING 191d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo "cpm: failed to create idle sysfs entry\n"); 192d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo} 193d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 194d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic void cpm_idle(void) 195d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo{ 196d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo if (idle_mode[CPM_IDLE_DOZE].enabled) 197d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm_idle_doze(); 198d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo else 199d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm_idle_wait(); 200d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo} 201d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 202d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic int cpm_suspend_valid(suspend_state_t state) 203d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo{ 204d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo switch (state) { 205d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo case PM_SUSPEND_STANDBY: 206d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo return !!cpm.standby; 207d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo case PM_SUSPEND_MEM: 208d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo return !!cpm.suspend; 209d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo default: 210d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo return 0; 211d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo } 212d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo} 213d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 214d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic void cpm_suspend_standby(unsigned int mask) 215d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo{ 216d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo unsigned long tcr_save; 217d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 218d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo /* disable decrement interrupt */ 219d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo tcr_save = mfspr(SPRN_TCR); 220d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo mtspr(SPRN_TCR, tcr_save & ~TCR_DIE); 221d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 222d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo /* go to sleep state */ 223d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm_idle_sleep(mask); 224d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 225d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo /* restore decrement interrupt */ 226d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo mtspr(SPRN_TCR, tcr_save); 227d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo} 228d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 229d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic int cpm_suspend_enter(suspend_state_t state) 230d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo{ 231d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo switch (state) { 232d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo case PM_SUSPEND_STANDBY: 233d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm_suspend_standby(cpm.standby); 234d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo break; 235d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo case PM_SUSPEND_MEM: 236d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm_suspend_standby(cpm.suspend); 237d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo break; 238d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo } 239d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 240d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo return 0; 241d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo} 242d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 243d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic struct platform_suspend_ops cpm_suspend_ops = { 244d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo .valid = cpm_suspend_valid, 245d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo .enter = cpm_suspend_enter, 246d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo}; 247d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 248d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic int cpm_get_uint_property(struct device_node *np, 249d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo const char *name) 250d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo{ 251d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo int len; 252d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo const unsigned int *prop = of_get_property(np, name, &len); 253d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 254d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo if (prop == NULL || len < sizeof(u32)) 255d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo return 0; 256d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 257d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo return *prop; 258d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo} 259d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 260d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic int __init cpm_init(void) 261d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo{ 262d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo struct device_node *np; 263d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo int dcr_base, dcr_len; 264d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo int ret = 0; 265d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 266d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo if (!cpm.powersave_off) { 267d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm_idle_config(CPM_IDLE_WAIT); 268d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo ppc_md.power_save = &cpm_idle; 269d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo } 270d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 271d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo np = of_find_compatible_node(NULL, NULL, "ibm,cpm"); 272d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo if (!np) { 273d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo ret = -EINVAL; 274d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo goto out; 275d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo } 276d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 277d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo dcr_base = dcr_resource_start(np, 0); 278d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo dcr_len = dcr_resource_len(np, 0); 279d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 280d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo if (dcr_base == 0 || dcr_len == 0) { 281d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo printk(KERN_ERR "cpm: could not parse dcr property for %s\n", 282d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo np->full_name); 283d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo ret = -EINVAL; 284d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo goto out; 285d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo } 286d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 287d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm.dcr_host = dcr_map(np, dcr_base, dcr_len); 288d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 289d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo if (!DCR_MAP_OK(cpm.dcr_host)) { 290d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo printk(KERN_ERR "cpm: failed to map dcr property for %s\n", 291d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo np->full_name); 292d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo ret = -EINVAL; 293d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo goto out; 294d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo } 295d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 296d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo /* All 4xx SoCs with a CPM controller have one of two 297d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * different order for the CPM registers. Some have the 298d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * CPM registers in the following order (ER,FR,SR). The 299d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo * others have them in the following order (SR,ER,FR). 300d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo */ 301d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 302d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo if (cpm_get_uint_property(np, "er-offset") == 0) { 303d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm.dcr_offset[CPM_ER] = 0; 304d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm.dcr_offset[CPM_FR] = 1; 305d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm.dcr_offset[CPM_SR] = 2; 306d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo } else { 307d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm.dcr_offset[CPM_ER] = 1; 308d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm.dcr_offset[CPM_FR] = 2; 309d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm.dcr_offset[CPM_SR] = 0; 310d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo } 311d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 312d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo /* Now let's see what IPs to turn off for the following modes */ 313d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 314d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm.unused = cpm_get_uint_property(np, "unused-units"); 315d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm.idle_doze = cpm_get_uint_property(np, "idle-doze"); 316d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm.standby = cpm_get_uint_property(np, "standby"); 317d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm.suspend = cpm_get_uint_property(np, "suspend"); 318d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 319d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo /* If some IPs are unused let's turn them off now */ 320d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 321d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo if (cpm.unused) { 322d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm_set(CPM_ER, cpm.unused); 323d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm_set(CPM_FR, cpm.unused); 324d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo } 325d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 326d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo /* Now let's export interfaces */ 327d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 328d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo if (!cpm.powersave_off && cpm.idle_doze) 329d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm_idle_config_sysfs(); 330d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 331d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo if (cpm.standby || cpm.suspend) 332d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo suspend_set_ops(&cpm_suspend_ops); 333d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardoout: 334d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo if (np) 335d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo of_node_put(np); 336d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo return ret; 337d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo} 338d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 339d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardolate_initcall(cpm_init); 340d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo 341d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardostatic int __init cpm_powersave_off(char *arg) 342d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo{ 343d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo cpm.powersave_off = 1; 344d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo return 0; 345d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo} 346d164f6d4f9108126f69ba2963cf6fb7ef4ba9232Victor Gallardo__setup("powersave=off", cpm_powersave_off); 347