1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 28a25a2fdSKay Sievers #include <linux/device.h> 3d3d2176aSDavid Gibson #include <linux/cpu.h> 4d3d2176aSDavid Gibson #include <linux/smp.h> 5d3d2176aSDavid Gibson #include <linux/percpu.h> 6d3d2176aSDavid Gibson #include <linux/init.h> 7d3d2176aSDavid Gibson #include <linux/sched.h> 84b16f8e2SPaul Gortmaker #include <linux/export.h> 9d3d2176aSDavid Gibson #include <linux/nodemask.h> 10d3d2176aSDavid Gibson #include <linux/cpumask.h> 11d3d2176aSDavid Gibson #include <linux/notifier.h> 12e6f6390aSChristophe Leroy #include <linux/of.h> 13d3d2176aSDavid Gibson 14d3d2176aSDavid Gibson #include <asm/current.h> 15d3d2176aSDavid Gibson #include <asm/processor.h> 16d3d2176aSDavid Gibson #include <asm/cputable.h> 17d3d2176aSDavid Gibson #include <asm/hvcall.h> 18d3d2176aSDavid Gibson #include <asm/machdep.h> 19d3d2176aSDavid Gibson #include <asm/smp.h> 20a6dbf93aSPaul Mackerras #include <asm/pmc.h> 21d1211af3SMadhavan Srinivasan #include <asm/firmware.h> 226909f179SGautham R. Shenoy #include <asm/idle.h> 23734560acSRyan Grimm #include <asm/svm.h> 24d3d2176aSDavid Gibson 2593197a36SNathan Lynch #include "cacheinfo.h" 26c0abd0c7SNicholas Piggin #include "setup.h" 2793197a36SNathan Lynch 28b950bdd0SBenjamin Herrenschmidt #ifdef CONFIG_PPC64 29b950bdd0SBenjamin Herrenschmidt #include <asm/paca.h> 30b950bdd0SBenjamin Herrenschmidt #include <asm/lppaca.h> 31b950bdd0SBenjamin Herrenschmidt #endif 32b950bdd0SBenjamin Herrenschmidt 33d3d2176aSDavid Gibson static DEFINE_PER_CPU(struct cpu, cpu_devices); 34d3d2176aSDavid Gibson 35b950bdd0SBenjamin Herrenschmidt #ifdef CONFIG_PPC64 36b950bdd0SBenjamin Herrenschmidt 37a02f6d42SJoel Stanley /* 38a02f6d42SJoel Stanley * Snooze delay has not been hooked up since 3fa8cad82b94 ("powerpc/pseries/cpuidle: 39a02f6d42SJoel Stanley * smt-snooze-delay cleanup.") and has been broken even longer. As was foretold in 40a02f6d42SJoel Stanley * 2014: 41a02f6d42SJoel Stanley * 42a02f6d42SJoel Stanley * "ppc64_util currently utilises it. Once we fix ppc64_util, propose to clean 43a02f6d42SJoel Stanley * up the kernel code." 44a02f6d42SJoel Stanley * 45a02f6d42SJoel Stanley * powerpc-utils stopped using it as of 1.3.8. At some point in the future this 46a02f6d42SJoel Stanley * code should be removed. 47a02f6d42SJoel Stanley */ 48d3d2176aSDavid Gibson 498a25a2fdSKay Sievers static ssize_t store_smt_snooze_delay(struct device *dev, 508a25a2fdSKay Sievers struct device_attribute *attr, 514a0b2b4dSAndi Kleen const char *buf, 52d3d2176aSDavid Gibson size_t count) 53d3d2176aSDavid Gibson { 54a02f6d42SJoel Stanley pr_warn_once("%s (%d) stored to unsupported smt_snooze_delay, which has no effect.\n", 55a02f6d42SJoel Stanley current->comm, current->pid); 56d3d2176aSDavid Gibson return count; 57d3d2176aSDavid Gibson } 58d3d2176aSDavid Gibson 598a25a2fdSKay Sievers static ssize_t show_smt_snooze_delay(struct device *dev, 608a25a2fdSKay Sievers struct device_attribute *attr, 614a0b2b4dSAndi Kleen char *buf) 62d3d2176aSDavid Gibson { 63a02f6d42SJoel Stanley pr_warn_once("%s (%d) read from unsupported smt_snooze_delay\n", 64a02f6d42SJoel Stanley current->comm, current->pid); 65a02f6d42SJoel Stanley return sprintf(buf, "100\n"); 66d3d2176aSDavid Gibson } 67d3d2176aSDavid Gibson 688a25a2fdSKay Sievers static DEVICE_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay, 69d3d2176aSDavid Gibson store_smt_snooze_delay); 70d3d2176aSDavid Gibson 71d3d2176aSDavid Gibson static int __init setup_smt_snooze_delay(char *str) 72d3d2176aSDavid Gibson { 73d3d2176aSDavid Gibson if (!cpu_has_feature(CPU_FTR_SMT)) 74d3d2176aSDavid Gibson return 1; 75d3d2176aSDavid Gibson 76a02f6d42SJoel Stanley pr_warn("smt-snooze-delay command line option has no effect\n"); 77d3d2176aSDavid Gibson return 1; 78d3d2176aSDavid Gibson } 79d3d2176aSDavid Gibson __setup("smt-snooze-delay=", setup_smt_snooze_delay); 80d3d2176aSDavid Gibson 81b950bdd0SBenjamin Herrenschmidt #endif /* CONFIG_PPC64 */ 82d3d2176aSDavid Gibson 83fcdb524dSMadhavan Srinivasan #define __SYSFS_SPRSETUP_READ_WRITE(NAME, ADDRESS, EXTRA) \ 84fcdb524dSMadhavan Srinivasan static void read_##NAME(void *val) \ 85fcdb524dSMadhavan Srinivasan { \ 86fcdb524dSMadhavan Srinivasan *(unsigned long *)val = mfspr(ADDRESS); \ 87fcdb524dSMadhavan Srinivasan } \ 88fcdb524dSMadhavan Srinivasan static void write_##NAME(void *val) \ 89fcdb524dSMadhavan Srinivasan { \ 90fcdb524dSMadhavan Srinivasan EXTRA; \ 91fcdb524dSMadhavan Srinivasan mtspr(ADDRESS, *(unsigned long *)val); \ 92fcdb524dSMadhavan Srinivasan } 93fcdb524dSMadhavan Srinivasan 94fcdb524dSMadhavan Srinivasan #define __SYSFS_SPRSETUP_SHOW_STORE(NAME) \ 95fcdb524dSMadhavan Srinivasan static ssize_t show_##NAME(struct device *dev, \ 96fcdb524dSMadhavan Srinivasan struct device_attribute *attr, \ 97fcdb524dSMadhavan Srinivasan char *buf) \ 98fcdb524dSMadhavan Srinivasan { \ 99fcdb524dSMadhavan Srinivasan struct cpu *cpu = container_of(dev, struct cpu, dev); \ 100fcdb524dSMadhavan Srinivasan unsigned long val; \ 101fcdb524dSMadhavan Srinivasan smp_call_function_single(cpu->dev.id, read_##NAME, &val, 1); \ 102fcdb524dSMadhavan Srinivasan return sprintf(buf, "%lx\n", val); \ 103fcdb524dSMadhavan Srinivasan } \ 104fcdb524dSMadhavan Srinivasan static ssize_t __used \ 105fcdb524dSMadhavan Srinivasan store_##NAME(struct device *dev, struct device_attribute *attr, \ 106fcdb524dSMadhavan Srinivasan const char *buf, size_t count) \ 107fcdb524dSMadhavan Srinivasan { \ 108fcdb524dSMadhavan Srinivasan struct cpu *cpu = container_of(dev, struct cpu, dev); \ 109fcdb524dSMadhavan Srinivasan unsigned long val; \ 110fcdb524dSMadhavan Srinivasan int ret = sscanf(buf, "%lx", &val); \ 111fcdb524dSMadhavan Srinivasan if (ret != 1) \ 112fcdb524dSMadhavan Srinivasan return -EINVAL; \ 113fcdb524dSMadhavan Srinivasan smp_call_function_single(cpu->dev.id, write_##NAME, &val, 1); \ 114fcdb524dSMadhavan Srinivasan return count; \ 115fcdb524dSMadhavan Srinivasan } 116fcdb524dSMadhavan Srinivasan 117fcdb524dSMadhavan Srinivasan #define SYSFS_PMCSETUP(NAME, ADDRESS) \ 118fcdb524dSMadhavan Srinivasan __SYSFS_SPRSETUP_READ_WRITE(NAME, ADDRESS, ppc_enable_pmcs()) \ 119fcdb524dSMadhavan Srinivasan __SYSFS_SPRSETUP_SHOW_STORE(NAME) 120fcdb524dSMadhavan Srinivasan #define SYSFS_SPRSETUP(NAME, ADDRESS) \ 121fcdb524dSMadhavan Srinivasan __SYSFS_SPRSETUP_READ_WRITE(NAME, ADDRESS, ) \ 122fcdb524dSMadhavan Srinivasan __SYSFS_SPRSETUP_SHOW_STORE(NAME) 123fcdb524dSMadhavan Srinivasan 124fcdb524dSMadhavan Srinivasan #define SYSFS_SPRSETUP_SHOW_STORE(NAME) \ 125fcdb524dSMadhavan Srinivasan __SYSFS_SPRSETUP_SHOW_STORE(NAME) 126fcdb524dSMadhavan Srinivasan 127fcdb524dSMadhavan Srinivasan #ifdef CONFIG_PPC64 128fcdb524dSMadhavan Srinivasan 129fcdb524dSMadhavan Srinivasan /* 130fcdb524dSMadhavan Srinivasan * This is the system wide DSCR register default value. Any 131fcdb524dSMadhavan Srinivasan * change to this default value through the sysfs interface 132fcdb524dSMadhavan Srinivasan * will update all per cpu DSCR default values across the 133fcdb524dSMadhavan Srinivasan * system stored in their respective PACA structures. 134fcdb524dSMadhavan Srinivasan */ 135fcdb524dSMadhavan Srinivasan static unsigned long dscr_default; 136fcdb524dSMadhavan Srinivasan 137fcdb524dSMadhavan Srinivasan /** 138fcdb524dSMadhavan Srinivasan * read_dscr() - Fetch the cpu specific DSCR default 139fcdb524dSMadhavan Srinivasan * @val: Returned cpu specific DSCR default value 140fcdb524dSMadhavan Srinivasan * 141fcdb524dSMadhavan Srinivasan * This function returns the per cpu DSCR default value 142fcdb524dSMadhavan Srinivasan * for any cpu which is contained in it's PACA structure. 143fcdb524dSMadhavan Srinivasan */ 144fcdb524dSMadhavan Srinivasan static void read_dscr(void *val) 145fcdb524dSMadhavan Srinivasan { 146fcdb524dSMadhavan Srinivasan *(unsigned long *)val = get_paca()->dscr_default; 147fcdb524dSMadhavan Srinivasan } 148fcdb524dSMadhavan Srinivasan 149fcdb524dSMadhavan Srinivasan 150fcdb524dSMadhavan Srinivasan /** 151fcdb524dSMadhavan Srinivasan * write_dscr() - Update the cpu specific DSCR default 152fcdb524dSMadhavan Srinivasan * @val: New cpu specific DSCR default value to update 153fcdb524dSMadhavan Srinivasan * 154fcdb524dSMadhavan Srinivasan * This function updates the per cpu DSCR default value 155fcdb524dSMadhavan Srinivasan * for any cpu which is contained in it's PACA structure. 156fcdb524dSMadhavan Srinivasan */ 157fcdb524dSMadhavan Srinivasan static void write_dscr(void *val) 158fcdb524dSMadhavan Srinivasan { 159fcdb524dSMadhavan Srinivasan get_paca()->dscr_default = *(unsigned long *)val; 160fcdb524dSMadhavan Srinivasan if (!current->thread.dscr_inherit) { 161fcdb524dSMadhavan Srinivasan current->thread.dscr = *(unsigned long *)val; 162fcdb524dSMadhavan Srinivasan mtspr(SPRN_DSCR, *(unsigned long *)val); 163fcdb524dSMadhavan Srinivasan } 164fcdb524dSMadhavan Srinivasan } 165fcdb524dSMadhavan Srinivasan 166fcdb524dSMadhavan Srinivasan SYSFS_SPRSETUP_SHOW_STORE(dscr); 167fcdb524dSMadhavan Srinivasan static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr); 168fcdb524dSMadhavan Srinivasan 169fcdb524dSMadhavan Srinivasan static void add_write_permission_dev_attr(struct device_attribute *attr) 170fcdb524dSMadhavan Srinivasan { 171fcdb524dSMadhavan Srinivasan attr->attr.mode |= 0200; 172fcdb524dSMadhavan Srinivasan } 173fcdb524dSMadhavan Srinivasan 174fcdb524dSMadhavan Srinivasan /** 175fcdb524dSMadhavan Srinivasan * show_dscr_default() - Fetch the system wide DSCR default 176fcdb524dSMadhavan Srinivasan * @dev: Device structure 177fcdb524dSMadhavan Srinivasan * @attr: Device attribute structure 178fcdb524dSMadhavan Srinivasan * @buf: Interface buffer 179fcdb524dSMadhavan Srinivasan * 180fcdb524dSMadhavan Srinivasan * This function returns the system wide DSCR default value. 181fcdb524dSMadhavan Srinivasan */ 182fcdb524dSMadhavan Srinivasan static ssize_t show_dscr_default(struct device *dev, 183fcdb524dSMadhavan Srinivasan struct device_attribute *attr, char *buf) 184fcdb524dSMadhavan Srinivasan { 185fcdb524dSMadhavan Srinivasan return sprintf(buf, "%lx\n", dscr_default); 186fcdb524dSMadhavan Srinivasan } 187fcdb524dSMadhavan Srinivasan 188fcdb524dSMadhavan Srinivasan /** 189fcdb524dSMadhavan Srinivasan * store_dscr_default() - Update the system wide DSCR default 190fcdb524dSMadhavan Srinivasan * @dev: Device structure 191fcdb524dSMadhavan Srinivasan * @attr: Device attribute structure 192fcdb524dSMadhavan Srinivasan * @buf: Interface buffer 193fcdb524dSMadhavan Srinivasan * @count: Size of the update 194fcdb524dSMadhavan Srinivasan * 195fcdb524dSMadhavan Srinivasan * This function updates the system wide DSCR default value. 196fcdb524dSMadhavan Srinivasan */ 197fcdb524dSMadhavan Srinivasan static ssize_t __used store_dscr_default(struct device *dev, 198fcdb524dSMadhavan Srinivasan struct device_attribute *attr, const char *buf, 199fcdb524dSMadhavan Srinivasan size_t count) 200fcdb524dSMadhavan Srinivasan { 201fcdb524dSMadhavan Srinivasan unsigned long val; 202fcdb524dSMadhavan Srinivasan int ret = 0; 203fcdb524dSMadhavan Srinivasan 204fcdb524dSMadhavan Srinivasan ret = sscanf(buf, "%lx", &val); 205fcdb524dSMadhavan Srinivasan if (ret != 1) 206fcdb524dSMadhavan Srinivasan return -EINVAL; 207fcdb524dSMadhavan Srinivasan dscr_default = val; 208fcdb524dSMadhavan Srinivasan 209fcdb524dSMadhavan Srinivasan on_each_cpu(write_dscr, &val, 1); 210fcdb524dSMadhavan Srinivasan 211fcdb524dSMadhavan Srinivasan return count; 212fcdb524dSMadhavan Srinivasan } 213fcdb524dSMadhavan Srinivasan 214fcdb524dSMadhavan Srinivasan static DEVICE_ATTR(dscr_default, 0600, 215fcdb524dSMadhavan Srinivasan show_dscr_default, store_dscr_default); 216fcdb524dSMadhavan Srinivasan 217d276960dSNick Child static void __init sysfs_create_dscr_default(void) 218fcdb524dSMadhavan Srinivasan { 219fcdb524dSMadhavan Srinivasan if (cpu_has_feature(CPU_FTR_DSCR)) { 220fcdb524dSMadhavan Srinivasan int cpu; 221fcdb524dSMadhavan Srinivasan 222fcdb524dSMadhavan Srinivasan dscr_default = spr_default_dscr; 223fcdb524dSMadhavan Srinivasan for_each_possible_cpu(cpu) 224fcdb524dSMadhavan Srinivasan paca_ptrs[cpu]->dscr_default = dscr_default; 225fcdb524dSMadhavan Srinivasan 2267b2aab5fSCédric Le Goater device_create_file(cpu_subsys.dev_root, &dev_attr_dscr_default); 227fcdb524dSMadhavan Srinivasan } 228fcdb524dSMadhavan Srinivasan } 229fcdb524dSMadhavan Srinivasan #endif /* CONFIG_PPC64 */ 230fcdb524dSMadhavan Srinivasan 231*3e731858SChristophe Leroy #ifdef CONFIG_PPC_E500 232a7189483SWang Dongsheng #define MAX_BIT 63 233a7189483SWang Dongsheng 234a7189483SWang Dongsheng static u64 pw20_wt; 235a7189483SWang Dongsheng static u64 altivec_idle_wt; 236a7189483SWang Dongsheng 237a7189483SWang Dongsheng static unsigned int get_idle_ticks_bit(u64 ns) 238a7189483SWang Dongsheng { 239a7189483SWang Dongsheng u64 cycle; 240a7189483SWang Dongsheng 241a7189483SWang Dongsheng if (ns >= 10000) 242a7189483SWang Dongsheng cycle = div_u64(ns + 500, 1000) * tb_ticks_per_usec; 243a7189483SWang Dongsheng else 244a7189483SWang Dongsheng cycle = div_u64(ns * tb_ticks_per_usec, 1000); 245a7189483SWang Dongsheng 246a7189483SWang Dongsheng if (!cycle) 247a7189483SWang Dongsheng return 0; 248a7189483SWang Dongsheng 249a7189483SWang Dongsheng return ilog2(cycle); 250a7189483SWang Dongsheng } 251a7189483SWang Dongsheng 252a7189483SWang Dongsheng static void do_show_pwrmgtcr0(void *val) 253a7189483SWang Dongsheng { 254a7189483SWang Dongsheng u32 *value = val; 255a7189483SWang Dongsheng 256a7189483SWang Dongsheng *value = mfspr(SPRN_PWRMGTCR0); 257a7189483SWang Dongsheng } 258a7189483SWang Dongsheng 259a7189483SWang Dongsheng static ssize_t show_pw20_state(struct device *dev, 260a7189483SWang Dongsheng struct device_attribute *attr, char *buf) 261a7189483SWang Dongsheng { 262a7189483SWang Dongsheng u32 value; 263a7189483SWang Dongsheng unsigned int cpu = dev->id; 264a7189483SWang Dongsheng 265a7189483SWang Dongsheng smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1); 266a7189483SWang Dongsheng 267a7189483SWang Dongsheng value &= PWRMGTCR0_PW20_WAIT; 268a7189483SWang Dongsheng 269a7189483SWang Dongsheng return sprintf(buf, "%u\n", value ? 1 : 0); 270a7189483SWang Dongsheng } 271a7189483SWang Dongsheng 272a7189483SWang Dongsheng static void do_store_pw20_state(void *val) 273a7189483SWang Dongsheng { 274a7189483SWang Dongsheng u32 *value = val; 275a7189483SWang Dongsheng u32 pw20_state; 276a7189483SWang Dongsheng 277a7189483SWang Dongsheng pw20_state = mfspr(SPRN_PWRMGTCR0); 278a7189483SWang Dongsheng 279a7189483SWang Dongsheng if (*value) 280a7189483SWang Dongsheng pw20_state |= PWRMGTCR0_PW20_WAIT; 281a7189483SWang Dongsheng else 282a7189483SWang Dongsheng pw20_state &= ~PWRMGTCR0_PW20_WAIT; 283a7189483SWang Dongsheng 284a7189483SWang Dongsheng mtspr(SPRN_PWRMGTCR0, pw20_state); 285a7189483SWang Dongsheng } 286a7189483SWang Dongsheng 287a7189483SWang Dongsheng static ssize_t store_pw20_state(struct device *dev, 288a7189483SWang Dongsheng struct device_attribute *attr, 289a7189483SWang Dongsheng const char *buf, size_t count) 290a7189483SWang Dongsheng { 291a7189483SWang Dongsheng u32 value; 292a7189483SWang Dongsheng unsigned int cpu = dev->id; 293a7189483SWang Dongsheng 294a7189483SWang Dongsheng if (kstrtou32(buf, 0, &value)) 295a7189483SWang Dongsheng return -EINVAL; 296a7189483SWang Dongsheng 297a7189483SWang Dongsheng if (value > 1) 298a7189483SWang Dongsheng return -EINVAL; 299a7189483SWang Dongsheng 300a7189483SWang Dongsheng smp_call_function_single(cpu, do_store_pw20_state, &value, 1); 301a7189483SWang Dongsheng 302a7189483SWang Dongsheng return count; 303a7189483SWang Dongsheng } 304a7189483SWang Dongsheng 305a7189483SWang Dongsheng static ssize_t show_pw20_wait_time(struct device *dev, 306a7189483SWang Dongsheng struct device_attribute *attr, char *buf) 307a7189483SWang Dongsheng { 308a7189483SWang Dongsheng u32 value; 309a7189483SWang Dongsheng u64 tb_cycle = 1; 310a7189483SWang Dongsheng u64 time; 311a7189483SWang Dongsheng 312a7189483SWang Dongsheng unsigned int cpu = dev->id; 313a7189483SWang Dongsheng 314a7189483SWang Dongsheng if (!pw20_wt) { 315a7189483SWang Dongsheng smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1); 316a7189483SWang Dongsheng value = (value & PWRMGTCR0_PW20_ENT) >> 317a7189483SWang Dongsheng PWRMGTCR0_PW20_ENT_SHIFT; 318a7189483SWang Dongsheng 319a7189483SWang Dongsheng tb_cycle = (tb_cycle << (MAX_BIT - value + 1)); 320a7189483SWang Dongsheng /* convert ms to ns */ 321a7189483SWang Dongsheng if (tb_ticks_per_usec > 1000) { 322a7189483SWang Dongsheng time = div_u64(tb_cycle, tb_ticks_per_usec / 1000); 323a7189483SWang Dongsheng } else { 324a7189483SWang Dongsheng u32 rem_us; 325a7189483SWang Dongsheng 326a7189483SWang Dongsheng time = div_u64_rem(tb_cycle, tb_ticks_per_usec, 327a7189483SWang Dongsheng &rem_us); 328a7189483SWang Dongsheng time = time * 1000 + rem_us * 1000 / tb_ticks_per_usec; 329a7189483SWang Dongsheng } 330a7189483SWang Dongsheng } else { 331a7189483SWang Dongsheng time = pw20_wt; 332a7189483SWang Dongsheng } 333a7189483SWang Dongsheng 334a7189483SWang Dongsheng return sprintf(buf, "%llu\n", time > 0 ? time : 0); 335a7189483SWang Dongsheng } 336a7189483SWang Dongsheng 337a7189483SWang Dongsheng static void set_pw20_wait_entry_bit(void *val) 338a7189483SWang Dongsheng { 339a7189483SWang Dongsheng u32 *value = val; 340a7189483SWang Dongsheng u32 pw20_idle; 341a7189483SWang Dongsheng 342a7189483SWang Dongsheng pw20_idle = mfspr(SPRN_PWRMGTCR0); 343a7189483SWang Dongsheng 344a7189483SWang Dongsheng /* Set Automatic PW20 Core Idle Count */ 345a7189483SWang Dongsheng /* clear count */ 346a7189483SWang Dongsheng pw20_idle &= ~PWRMGTCR0_PW20_ENT; 347a7189483SWang Dongsheng 348a7189483SWang Dongsheng /* set count */ 349a7189483SWang Dongsheng pw20_idle |= ((MAX_BIT - *value) << PWRMGTCR0_PW20_ENT_SHIFT); 350a7189483SWang Dongsheng 351a7189483SWang Dongsheng mtspr(SPRN_PWRMGTCR0, pw20_idle); 352a7189483SWang Dongsheng } 353a7189483SWang Dongsheng 354a7189483SWang Dongsheng static ssize_t store_pw20_wait_time(struct device *dev, 355a7189483SWang Dongsheng struct device_attribute *attr, 356a7189483SWang Dongsheng const char *buf, size_t count) 357a7189483SWang Dongsheng { 358a7189483SWang Dongsheng u32 entry_bit; 359a7189483SWang Dongsheng u64 value; 360a7189483SWang Dongsheng 361a7189483SWang Dongsheng unsigned int cpu = dev->id; 362a7189483SWang Dongsheng 363a7189483SWang Dongsheng if (kstrtou64(buf, 0, &value)) 364a7189483SWang Dongsheng return -EINVAL; 365a7189483SWang Dongsheng 366a7189483SWang Dongsheng if (!value) 367a7189483SWang Dongsheng return -EINVAL; 368a7189483SWang Dongsheng 369a7189483SWang Dongsheng entry_bit = get_idle_ticks_bit(value); 370a7189483SWang Dongsheng if (entry_bit > MAX_BIT) 371a7189483SWang Dongsheng return -EINVAL; 372a7189483SWang Dongsheng 373a7189483SWang Dongsheng pw20_wt = value; 374a7189483SWang Dongsheng 375a7189483SWang Dongsheng smp_call_function_single(cpu, set_pw20_wait_entry_bit, 376a7189483SWang Dongsheng &entry_bit, 1); 377a7189483SWang Dongsheng 378a7189483SWang Dongsheng return count; 379a7189483SWang Dongsheng } 380a7189483SWang Dongsheng 381a7189483SWang Dongsheng static ssize_t show_altivec_idle(struct device *dev, 382a7189483SWang Dongsheng struct device_attribute *attr, char *buf) 383a7189483SWang Dongsheng { 384a7189483SWang Dongsheng u32 value; 385a7189483SWang Dongsheng unsigned int cpu = dev->id; 386a7189483SWang Dongsheng 387a7189483SWang Dongsheng smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1); 388a7189483SWang Dongsheng 389a7189483SWang Dongsheng value &= PWRMGTCR0_AV_IDLE_PD_EN; 390a7189483SWang Dongsheng 391a7189483SWang Dongsheng return sprintf(buf, "%u\n", value ? 1 : 0); 392a7189483SWang Dongsheng } 393a7189483SWang Dongsheng 394a7189483SWang Dongsheng static void do_store_altivec_idle(void *val) 395a7189483SWang Dongsheng { 396a7189483SWang Dongsheng u32 *value = val; 397a7189483SWang Dongsheng u32 altivec_idle; 398a7189483SWang Dongsheng 399a7189483SWang Dongsheng altivec_idle = mfspr(SPRN_PWRMGTCR0); 400a7189483SWang Dongsheng 401a7189483SWang Dongsheng if (*value) 402a7189483SWang Dongsheng altivec_idle |= PWRMGTCR0_AV_IDLE_PD_EN; 403a7189483SWang Dongsheng else 404a7189483SWang Dongsheng altivec_idle &= ~PWRMGTCR0_AV_IDLE_PD_EN; 405a7189483SWang Dongsheng 406a7189483SWang Dongsheng mtspr(SPRN_PWRMGTCR0, altivec_idle); 407a7189483SWang Dongsheng } 408a7189483SWang Dongsheng 409a7189483SWang Dongsheng static ssize_t store_altivec_idle(struct device *dev, 410a7189483SWang Dongsheng struct device_attribute *attr, 411a7189483SWang Dongsheng const char *buf, size_t count) 412a7189483SWang Dongsheng { 413a7189483SWang Dongsheng u32 value; 414a7189483SWang Dongsheng unsigned int cpu = dev->id; 415a7189483SWang Dongsheng 416a7189483SWang Dongsheng if (kstrtou32(buf, 0, &value)) 417a7189483SWang Dongsheng return -EINVAL; 418a7189483SWang Dongsheng 419a7189483SWang Dongsheng if (value > 1) 420a7189483SWang Dongsheng return -EINVAL; 421a7189483SWang Dongsheng 422a7189483SWang Dongsheng smp_call_function_single(cpu, do_store_altivec_idle, &value, 1); 423a7189483SWang Dongsheng 424a7189483SWang Dongsheng return count; 425a7189483SWang Dongsheng } 426a7189483SWang Dongsheng 427a7189483SWang Dongsheng static ssize_t show_altivec_idle_wait_time(struct device *dev, 428a7189483SWang Dongsheng struct device_attribute *attr, char *buf) 429a7189483SWang Dongsheng { 430a7189483SWang Dongsheng u32 value; 431a7189483SWang Dongsheng u64 tb_cycle = 1; 432a7189483SWang Dongsheng u64 time; 433a7189483SWang Dongsheng 434a7189483SWang Dongsheng unsigned int cpu = dev->id; 435a7189483SWang Dongsheng 436a7189483SWang Dongsheng if (!altivec_idle_wt) { 437a7189483SWang Dongsheng smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1); 438a7189483SWang Dongsheng value = (value & PWRMGTCR0_AV_IDLE_CNT) >> 439a7189483SWang Dongsheng PWRMGTCR0_AV_IDLE_CNT_SHIFT; 440a7189483SWang Dongsheng 441a7189483SWang Dongsheng tb_cycle = (tb_cycle << (MAX_BIT - value + 1)); 442a7189483SWang Dongsheng /* convert ms to ns */ 443a7189483SWang Dongsheng if (tb_ticks_per_usec > 1000) { 444a7189483SWang Dongsheng time = div_u64(tb_cycle, tb_ticks_per_usec / 1000); 445a7189483SWang Dongsheng } else { 446a7189483SWang Dongsheng u32 rem_us; 447a7189483SWang Dongsheng 448a7189483SWang Dongsheng time = div_u64_rem(tb_cycle, tb_ticks_per_usec, 449a7189483SWang Dongsheng &rem_us); 450a7189483SWang Dongsheng time = time * 1000 + rem_us * 1000 / tb_ticks_per_usec; 451a7189483SWang Dongsheng } 452a7189483SWang Dongsheng } else { 453a7189483SWang Dongsheng time = altivec_idle_wt; 454a7189483SWang Dongsheng } 455a7189483SWang Dongsheng 456a7189483SWang Dongsheng return sprintf(buf, "%llu\n", time > 0 ? time : 0); 457a7189483SWang Dongsheng } 458a7189483SWang Dongsheng 459a7189483SWang Dongsheng static void set_altivec_idle_wait_entry_bit(void *val) 460a7189483SWang Dongsheng { 461a7189483SWang Dongsheng u32 *value = val; 462a7189483SWang Dongsheng u32 altivec_idle; 463a7189483SWang Dongsheng 464a7189483SWang Dongsheng altivec_idle = mfspr(SPRN_PWRMGTCR0); 465a7189483SWang Dongsheng 466a7189483SWang Dongsheng /* Set Automatic AltiVec Idle Count */ 467a7189483SWang Dongsheng /* clear count */ 468a7189483SWang Dongsheng altivec_idle &= ~PWRMGTCR0_AV_IDLE_CNT; 469a7189483SWang Dongsheng 470a7189483SWang Dongsheng /* set count */ 471a7189483SWang Dongsheng altivec_idle |= ((MAX_BIT - *value) << PWRMGTCR0_AV_IDLE_CNT_SHIFT); 472a7189483SWang Dongsheng 473a7189483SWang Dongsheng mtspr(SPRN_PWRMGTCR0, altivec_idle); 474a7189483SWang Dongsheng } 475a7189483SWang Dongsheng 476a7189483SWang Dongsheng static ssize_t store_altivec_idle_wait_time(struct device *dev, 477a7189483SWang Dongsheng struct device_attribute *attr, 478a7189483SWang Dongsheng const char *buf, size_t count) 479a7189483SWang Dongsheng { 480a7189483SWang Dongsheng u32 entry_bit; 481a7189483SWang Dongsheng u64 value; 482a7189483SWang Dongsheng 483a7189483SWang Dongsheng unsigned int cpu = dev->id; 484a7189483SWang Dongsheng 485a7189483SWang Dongsheng if (kstrtou64(buf, 0, &value)) 486a7189483SWang Dongsheng return -EINVAL; 487a7189483SWang Dongsheng 488a7189483SWang Dongsheng if (!value) 489a7189483SWang Dongsheng return -EINVAL; 490a7189483SWang Dongsheng 491a7189483SWang Dongsheng entry_bit = get_idle_ticks_bit(value); 492a7189483SWang Dongsheng if (entry_bit > MAX_BIT) 493a7189483SWang Dongsheng return -EINVAL; 494a7189483SWang Dongsheng 495a7189483SWang Dongsheng altivec_idle_wt = value; 496a7189483SWang Dongsheng 497a7189483SWang Dongsheng smp_call_function_single(cpu, set_altivec_idle_wait_entry_bit, 498a7189483SWang Dongsheng &entry_bit, 1); 499a7189483SWang Dongsheng 500a7189483SWang Dongsheng return count; 501a7189483SWang Dongsheng } 502a7189483SWang Dongsheng 503a7189483SWang Dongsheng /* 504a7189483SWang Dongsheng * Enable/Disable interface: 505a7189483SWang Dongsheng * 0, disable. 1, enable. 506a7189483SWang Dongsheng */ 507a7189483SWang Dongsheng static DEVICE_ATTR(pw20_state, 0600, show_pw20_state, store_pw20_state); 508a7189483SWang Dongsheng static DEVICE_ATTR(altivec_idle, 0600, show_altivec_idle, store_altivec_idle); 509a7189483SWang Dongsheng 510a7189483SWang Dongsheng /* 511a7189483SWang Dongsheng * Set wait time interface:(Nanosecond) 512a7189483SWang Dongsheng * Example: Base on TBfreq is 41MHZ. 513a7189483SWang Dongsheng * 1~48(ns): TB[63] 514a7189483SWang Dongsheng * 49~97(ns): TB[62] 515a7189483SWang Dongsheng * 98~195(ns): TB[61] 516a7189483SWang Dongsheng * 196~390(ns): TB[60] 517a7189483SWang Dongsheng * 391~780(ns): TB[59] 518a7189483SWang Dongsheng * 781~1560(ns): TB[58] 519a7189483SWang Dongsheng * ... 520a7189483SWang Dongsheng */ 521a7189483SWang Dongsheng static DEVICE_ATTR(pw20_wait_time, 0600, 522a7189483SWang Dongsheng show_pw20_wait_time, 523a7189483SWang Dongsheng store_pw20_wait_time); 524a7189483SWang Dongsheng static DEVICE_ATTR(altivec_idle_wait_time, 0600, 525a7189483SWang Dongsheng show_altivec_idle_wait_time, 526a7189483SWang Dongsheng store_altivec_idle_wait_time); 527a7189483SWang Dongsheng #endif 528a7189483SWang Dongsheng 529d3d2176aSDavid Gibson /* 530d3d2176aSDavid Gibson * Enabling PMCs will slow partition context switch times so we only do 531d3d2176aSDavid Gibson * it the first time we write to the PMCs. 532d3d2176aSDavid Gibson */ 533d3d2176aSDavid Gibson 534d3d2176aSDavid Gibson static DEFINE_PER_CPU(char, pmcs_enabled); 535d3d2176aSDavid Gibson 536b950bdd0SBenjamin Herrenschmidt void ppc_enable_pmcs(void) 537d3d2176aSDavid Gibson { 538a6dbf93aSPaul Mackerras ppc_set_pmu_inuse(1); 539a6dbf93aSPaul Mackerras 540d3d2176aSDavid Gibson /* Only need to enable them once */ 54169111bacSChristoph Lameter if (__this_cpu_read(pmcs_enabled)) 542d3d2176aSDavid Gibson return; 543d3d2176aSDavid Gibson 54469111bacSChristoph Lameter __this_cpu_write(pmcs_enabled, 1); 545d3d2176aSDavid Gibson 546d3d2176aSDavid Gibson if (ppc_md.enable_pmcs) 547d3d2176aSDavid Gibson ppc_md.enable_pmcs(); 548d3d2176aSDavid Gibson } 549b950bdd0SBenjamin Herrenschmidt EXPORT_SYMBOL(ppc_enable_pmcs); 550d3d2176aSDavid Gibson 55139a360efSSam bobroff 5526529c13dSOlof Johansson 5536529c13dSOlof Johansson /* Let's define all possible registers, we'll only hook up the ones 5546529c13dSOlof Johansson * that are implemented on the current processor 5556529c13dSOlof Johansson */ 5566529c13dSOlof Johansson 55722697da3SKajol Jain #ifdef CONFIG_PMU_SYSFS 558fcdb524dSMadhavan Srinivasan #if defined(CONFIG_PPC64) || defined(CONFIG_PPC_BOOK3S_32) 559b950bdd0SBenjamin Herrenschmidt #define HAS_PPC_PMC_CLASSIC 1 560b950bdd0SBenjamin Herrenschmidt #define HAS_PPC_PMC_IBM 1 561b950bdd0SBenjamin Herrenschmidt #endif 562b950bdd0SBenjamin Herrenschmidt 563b950bdd0SBenjamin Herrenschmidt #ifdef CONFIG_PPC64 564fcdb524dSMadhavan Srinivasan #define HAS_PPC_PMC_PA6T 1 565fcdb524dSMadhavan Srinivasan #define HAS_PPC_PMC56 1 566fcdb524dSMadhavan Srinivasan #endif 567b950bdd0SBenjamin Herrenschmidt 568fcdb524dSMadhavan Srinivasan #ifdef CONFIG_PPC_BOOK3S_32 569fcdb524dSMadhavan Srinivasan #define HAS_PPC_PMC_G4 1 570fcdb524dSMadhavan Srinivasan #endif 57122697da3SKajol Jain #endif /* CONFIG_PMU_SYSFS */ 572fcdb524dSMadhavan Srinivasan 573fcdb524dSMadhavan Srinivasan #if defined(CONFIG_PPC64) && defined(CONFIG_DEBUG_MISC) 574fcdb524dSMadhavan Srinivasan #define HAS_PPC_PA6T 575fcdb524dSMadhavan Srinivasan #endif 576fcdb524dSMadhavan Srinivasan /* 577fcdb524dSMadhavan Srinivasan * SPRs which are not related to PMU. 578fcdb524dSMadhavan Srinivasan */ 579fcdb524dSMadhavan Srinivasan #ifdef CONFIG_PPC64 580fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(purr, SPRN_PURR); 581fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(spurr, SPRN_SPURR); 582fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(pir, SPRN_PIR); 583b6d34eb4SAnton Blanchard SYSFS_SPRSETUP(tscr, SPRN_TSCR); 584d3d2176aSDavid Gibson 585d1211af3SMadhavan Srinivasan /* 586d1211af3SMadhavan Srinivasan Lets only enable read for phyp resources and 587d1211af3SMadhavan Srinivasan enable write when needed with a separate function. 588d1211af3SMadhavan Srinivasan Lets be conservative and default to pseries. 589d1211af3SMadhavan Srinivasan */ 590d5dae721SBenjamin Herrenschmidt static DEVICE_ATTR(spurr, 0400, show_spurr, NULL); 591d1211af3SMadhavan Srinivasan static DEVICE_ATTR(purr, 0400, show_purr, store_purr); 5927affca35SLinus Torvalds static DEVICE_ATTR(pir, 0400, show_pir, NULL); 593b6d34eb4SAnton Blanchard static DEVICE_ATTR(tscr, 0600, show_tscr, store_tscr); 594b950bdd0SBenjamin Herrenschmidt #endif /* CONFIG_PPC64 */ 595b950bdd0SBenjamin Herrenschmidt 596fcdb524dSMadhavan Srinivasan #ifdef HAS_PPC_PMC_CLASSIC 597fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(mmcr0, SPRN_MMCR0); 598fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(mmcr1, SPRN_MMCR1); 599fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(pmc1, SPRN_PMC1); 600fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(pmc2, SPRN_PMC2); 601fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(pmc3, SPRN_PMC3); 602fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(pmc4, SPRN_PMC4); 603fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(pmc5, SPRN_PMC5); 604fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(pmc6, SPRN_PMC6); 605fcdb524dSMadhavan Srinivasan #endif 606fcdb524dSMadhavan Srinivasan 607fcdb524dSMadhavan Srinivasan #ifdef HAS_PPC_PMC_G4 608fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(mmcr2, SPRN_MMCR2); 609fcdb524dSMadhavan Srinivasan #endif 610fcdb524dSMadhavan Srinivasan 611fcdb524dSMadhavan Srinivasan #ifdef HAS_PPC_PMC56 612fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(pmc7, SPRN_PMC7); 613fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(pmc8, SPRN_PMC8); 614fcdb524dSMadhavan Srinivasan 615fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(mmcra, SPRN_MMCRA); 616c718547eSMadhavan Srinivasan SYSFS_PMCSETUP(mmcr3, SPRN_MMCR3); 617fcdb524dSMadhavan Srinivasan 618fcdb524dSMadhavan Srinivasan static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra); 619c718547eSMadhavan Srinivasan static DEVICE_ATTR(mmcr3, 0600, show_mmcr3, store_mmcr3); 620fcdb524dSMadhavan Srinivasan #endif /* HAS_PPC_PMC56 */ 621fcdb524dSMadhavan Srinivasan 622fcdb524dSMadhavan Srinivasan 623fcdb524dSMadhavan Srinivasan 624fcdb524dSMadhavan Srinivasan 625b950bdd0SBenjamin Herrenschmidt #ifdef HAS_PPC_PMC_PA6T 62625fc530eSOlof Johansson SYSFS_PMCSETUP(pa6t_pmc0, SPRN_PA6T_PMC0); 62725fc530eSOlof Johansson SYSFS_PMCSETUP(pa6t_pmc1, SPRN_PA6T_PMC1); 62825fc530eSOlof Johansson SYSFS_PMCSETUP(pa6t_pmc2, SPRN_PA6T_PMC2); 62925fc530eSOlof Johansson SYSFS_PMCSETUP(pa6t_pmc3, SPRN_PA6T_PMC3); 63025fc530eSOlof Johansson SYSFS_PMCSETUP(pa6t_pmc4, SPRN_PA6T_PMC4); 63125fc530eSOlof Johansson SYSFS_PMCSETUP(pa6t_pmc5, SPRN_PA6T_PMC5); 632fcdb524dSMadhavan Srinivasan #endif 633fcdb524dSMadhavan Srinivasan 634fcdb524dSMadhavan Srinivasan #ifdef HAS_PPC_PA6T 635fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(hid0, SPRN_HID0); 636fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(hid1, SPRN_HID1); 637fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(hid4, SPRN_HID4); 638fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(hid5, SPRN_HID5); 639fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima0, SPRN_PA6T_IMA0); 640fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima1, SPRN_PA6T_IMA1); 641fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima2, SPRN_PA6T_IMA2); 642fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima3, SPRN_PA6T_IMA3); 643fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima4, SPRN_PA6T_IMA4); 644fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima5, SPRN_PA6T_IMA5); 645fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima6, SPRN_PA6T_IMA6); 646fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima7, SPRN_PA6T_IMA7); 647fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima8, SPRN_PA6T_IMA8); 648fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima9, SPRN_PA6T_IMA9); 649fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(imaat, SPRN_PA6T_IMAAT); 650fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(btcr, SPRN_PA6T_BTCR); 651fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(pccr, SPRN_PA6T_PCCR); 652fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(rpccr, SPRN_PA6T_RPCCR); 653fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(der, SPRN_PA6T_DER); 654fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(mer, SPRN_PA6T_MER); 655fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ber, SPRN_PA6T_BER); 656fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ier, SPRN_PA6T_IER); 657fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(sier, SPRN_PA6T_SIER); 658fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(siar, SPRN_PA6T_SIAR); 659fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(tsr0, SPRN_PA6T_TSR0); 660fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(tsr1, SPRN_PA6T_TSR1); 661fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(tsr2, SPRN_PA6T_TSR2); 662fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(tsr3, SPRN_PA6T_TSR3); 663fcdb524dSMadhavan Srinivasan #endif /* HAS_PPC_PA6T */ 6646529c13dSOlof Johansson 665b950bdd0SBenjamin Herrenschmidt #ifdef HAS_PPC_PMC_IBM 6668a25a2fdSKay Sievers static struct device_attribute ibm_common_attrs[] = { 6678a25a2fdSKay Sievers __ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0), 6688a25a2fdSKay Sievers __ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1), 6696529c13dSOlof Johansson }; 670fcdb524dSMadhavan Srinivasan #endif /* HAS_PPC_PMC_IBM */ 6716529c13dSOlof Johansson 672b950bdd0SBenjamin Herrenschmidt #ifdef HAS_PPC_PMC_G4 6738a25a2fdSKay Sievers static struct device_attribute g4_common_attrs[] = { 6748a25a2fdSKay Sievers __ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0), 6758a25a2fdSKay Sievers __ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1), 6768a25a2fdSKay Sievers __ATTR(mmcr2, 0600, show_mmcr2, store_mmcr2), 677b950bdd0SBenjamin Herrenschmidt }; 678b950bdd0SBenjamin Herrenschmidt #endif /* HAS_PPC_PMC_G4 */ 679b950bdd0SBenjamin Herrenschmidt 680fcdb524dSMadhavan Srinivasan #ifdef HAS_PPC_PMC_CLASSIC 6818a25a2fdSKay Sievers static struct device_attribute classic_pmc_attrs[] = { 6828a25a2fdSKay Sievers __ATTR(pmc1, 0600, show_pmc1, store_pmc1), 6838a25a2fdSKay Sievers __ATTR(pmc2, 0600, show_pmc2, store_pmc2), 6848a25a2fdSKay Sievers __ATTR(pmc3, 0600, show_pmc3, store_pmc3), 6858a25a2fdSKay Sievers __ATTR(pmc4, 0600, show_pmc4, store_pmc4), 6868a25a2fdSKay Sievers __ATTR(pmc5, 0600, show_pmc5, store_pmc5), 6878a25a2fdSKay Sievers __ATTR(pmc6, 0600, show_pmc6, store_pmc6), 688fcdb524dSMadhavan Srinivasan #ifdef HAS_PPC_PMC56 6898a25a2fdSKay Sievers __ATTR(pmc7, 0600, show_pmc7, store_pmc7), 6908a25a2fdSKay Sievers __ATTR(pmc8, 0600, show_pmc8, store_pmc8), 691b950bdd0SBenjamin Herrenschmidt #endif 6926529c13dSOlof Johansson }; 693fcdb524dSMadhavan Srinivasan #endif 6946529c13dSOlof Johansson 695fcdb524dSMadhavan Srinivasan #if defined(HAS_PPC_PMC_PA6T) || defined(HAS_PPC_PA6T) 6968a25a2fdSKay Sievers static struct device_attribute pa6t_attrs[] = { 697fcdb524dSMadhavan Srinivasan #ifdef HAS_PPC_PMC_PA6T 6988a25a2fdSKay Sievers __ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0), 6998a25a2fdSKay Sievers __ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1), 7008a25a2fdSKay Sievers __ATTR(pmc0, 0600, show_pa6t_pmc0, store_pa6t_pmc0), 7018a25a2fdSKay Sievers __ATTR(pmc1, 0600, show_pa6t_pmc1, store_pa6t_pmc1), 7028a25a2fdSKay Sievers __ATTR(pmc2, 0600, show_pa6t_pmc2, store_pa6t_pmc2), 7038a25a2fdSKay Sievers __ATTR(pmc3, 0600, show_pa6t_pmc3, store_pa6t_pmc3), 7048a25a2fdSKay Sievers __ATTR(pmc4, 0600, show_pa6t_pmc4, store_pa6t_pmc4), 7058a25a2fdSKay Sievers __ATTR(pmc5, 0600, show_pa6t_pmc5, store_pa6t_pmc5), 706fcdb524dSMadhavan Srinivasan #endif 707fcdb524dSMadhavan Srinivasan #ifdef HAS_PPC_PA6T 7088a25a2fdSKay Sievers __ATTR(hid0, 0600, show_hid0, store_hid0), 7098a25a2fdSKay Sievers __ATTR(hid1, 0600, show_hid1, store_hid1), 7108a25a2fdSKay Sievers __ATTR(hid4, 0600, show_hid4, store_hid4), 7118a25a2fdSKay Sievers __ATTR(hid5, 0600, show_hid5, store_hid5), 7128a25a2fdSKay Sievers __ATTR(ima0, 0600, show_ima0, store_ima0), 7138a25a2fdSKay Sievers __ATTR(ima1, 0600, show_ima1, store_ima1), 7148a25a2fdSKay Sievers __ATTR(ima2, 0600, show_ima2, store_ima2), 7158a25a2fdSKay Sievers __ATTR(ima3, 0600, show_ima3, store_ima3), 7168a25a2fdSKay Sievers __ATTR(ima4, 0600, show_ima4, store_ima4), 7178a25a2fdSKay Sievers __ATTR(ima5, 0600, show_ima5, store_ima5), 7188a25a2fdSKay Sievers __ATTR(ima6, 0600, show_ima6, store_ima6), 7198a25a2fdSKay Sievers __ATTR(ima7, 0600, show_ima7, store_ima7), 7208a25a2fdSKay Sievers __ATTR(ima8, 0600, show_ima8, store_ima8), 7218a25a2fdSKay Sievers __ATTR(ima9, 0600, show_ima9, store_ima9), 7228a25a2fdSKay Sievers __ATTR(imaat, 0600, show_imaat, store_imaat), 7238a25a2fdSKay Sievers __ATTR(btcr, 0600, show_btcr, store_btcr), 7248a25a2fdSKay Sievers __ATTR(pccr, 0600, show_pccr, store_pccr), 7258a25a2fdSKay Sievers __ATTR(rpccr, 0600, show_rpccr, store_rpccr), 7268a25a2fdSKay Sievers __ATTR(der, 0600, show_der, store_der), 7278a25a2fdSKay Sievers __ATTR(mer, 0600, show_mer, store_mer), 7288a25a2fdSKay Sievers __ATTR(ber, 0600, show_ber, store_ber), 7298a25a2fdSKay Sievers __ATTR(ier, 0600, show_ier, store_ier), 7308a25a2fdSKay Sievers __ATTR(sier, 0600, show_sier, store_sier), 7318a25a2fdSKay Sievers __ATTR(siar, 0600, show_siar, store_siar), 7328a25a2fdSKay Sievers __ATTR(tsr0, 0600, show_tsr0, store_tsr0), 7338a25a2fdSKay Sievers __ATTR(tsr1, 0600, show_tsr1, store_tsr1), 7348a25a2fdSKay Sievers __ATTR(tsr2, 0600, show_tsr2, store_tsr2), 7358a25a2fdSKay Sievers __ATTR(tsr3, 0600, show_tsr3, store_tsr3), 736fcdb524dSMadhavan Srinivasan #endif /* HAS_PPC_PA6T */ 7376529c13dSOlof Johansson }; 738fcdb524dSMadhavan Srinivasan #endif 7396529c13dSOlof Johansson 740734560acSRyan Grimm #ifdef CONFIG_PPC_SVM 741734560acSRyan Grimm static ssize_t show_svm(struct device *dev, struct device_attribute *attr, char *buf) 742734560acSRyan Grimm { 743734560acSRyan Grimm return sprintf(buf, "%u\n", is_secure_guest()); 744734560acSRyan Grimm } 745734560acSRyan Grimm static DEVICE_ATTR(svm, 0444, show_svm, NULL); 746734560acSRyan Grimm 747d276960dSNick Child static void __init create_svm_file(void) 748734560acSRyan Grimm { 749734560acSRyan Grimm device_create_file(cpu_subsys.dev_root, &dev_attr_svm); 750734560acSRyan Grimm } 751734560acSRyan Grimm #else 752d276960dSNick Child static void __init create_svm_file(void) 753734560acSRyan Grimm { 754734560acSRyan Grimm } 755734560acSRyan Grimm #endif /* CONFIG_PPC_SVM */ 756734560acSRyan Grimm 7576909f179SGautham R. Shenoy #ifdef CONFIG_PPC_PSERIES 7586909f179SGautham R. Shenoy static void read_idle_purr(void *val) 7596909f179SGautham R. Shenoy { 7606909f179SGautham R. Shenoy u64 *ret = val; 7616909f179SGautham R. Shenoy 7626909f179SGautham R. Shenoy *ret = read_this_idle_purr(); 7636909f179SGautham R. Shenoy } 7646909f179SGautham R. Shenoy 7656909f179SGautham R. Shenoy static ssize_t idle_purr_show(struct device *dev, 7666909f179SGautham R. Shenoy struct device_attribute *attr, char *buf) 7676909f179SGautham R. Shenoy { 7686909f179SGautham R. Shenoy struct cpu *cpu = container_of(dev, struct cpu, dev); 7696909f179SGautham R. Shenoy u64 val; 7706909f179SGautham R. Shenoy 7716909f179SGautham R. Shenoy smp_call_function_single(cpu->dev.id, read_idle_purr, &val, 1); 7726909f179SGautham R. Shenoy return sprintf(buf, "%llx\n", val); 7736909f179SGautham R. Shenoy } 7746909f179SGautham R. Shenoy static DEVICE_ATTR(idle_purr, 0400, idle_purr_show, NULL); 7756909f179SGautham R. Shenoy 7766909f179SGautham R. Shenoy static void create_idle_purr_file(struct device *s) 7776909f179SGautham R. Shenoy { 7786909f179SGautham R. Shenoy if (firmware_has_feature(FW_FEATURE_LPAR)) 7796909f179SGautham R. Shenoy device_create_file(s, &dev_attr_idle_purr); 7806909f179SGautham R. Shenoy } 7816909f179SGautham R. Shenoy 7826909f179SGautham R. Shenoy static void remove_idle_purr_file(struct device *s) 7836909f179SGautham R. Shenoy { 7846909f179SGautham R. Shenoy if (firmware_has_feature(FW_FEATURE_LPAR)) 7856909f179SGautham R. Shenoy device_remove_file(s, &dev_attr_idle_purr); 7866909f179SGautham R. Shenoy } 7876909f179SGautham R. Shenoy 7886909f179SGautham R. Shenoy static void read_idle_spurr(void *val) 7896909f179SGautham R. Shenoy { 7906909f179SGautham R. Shenoy u64 *ret = val; 7916909f179SGautham R. Shenoy 7926909f179SGautham R. Shenoy *ret = read_this_idle_spurr(); 7936909f179SGautham R. Shenoy } 7946909f179SGautham R. Shenoy 7956909f179SGautham R. Shenoy static ssize_t idle_spurr_show(struct device *dev, 7966909f179SGautham R. Shenoy struct device_attribute *attr, char *buf) 7976909f179SGautham R. Shenoy { 7986909f179SGautham R. Shenoy struct cpu *cpu = container_of(dev, struct cpu, dev); 7996909f179SGautham R. Shenoy u64 val; 8006909f179SGautham R. Shenoy 8016909f179SGautham R. Shenoy smp_call_function_single(cpu->dev.id, read_idle_spurr, &val, 1); 8026909f179SGautham R. Shenoy return sprintf(buf, "%llx\n", val); 8036909f179SGautham R. Shenoy } 8046909f179SGautham R. Shenoy static DEVICE_ATTR(idle_spurr, 0400, idle_spurr_show, NULL); 8056909f179SGautham R. Shenoy 8066909f179SGautham R. Shenoy static void create_idle_spurr_file(struct device *s) 8076909f179SGautham R. Shenoy { 8086909f179SGautham R. Shenoy if (firmware_has_feature(FW_FEATURE_LPAR)) 8096909f179SGautham R. Shenoy device_create_file(s, &dev_attr_idle_spurr); 8106909f179SGautham R. Shenoy } 8116909f179SGautham R. Shenoy 8126909f179SGautham R. Shenoy static void remove_idle_spurr_file(struct device *s) 8136909f179SGautham R. Shenoy { 8146909f179SGautham R. Shenoy if (firmware_has_feature(FW_FEATURE_LPAR)) 8156909f179SGautham R. Shenoy device_remove_file(s, &dev_attr_idle_spurr); 8166909f179SGautham R. Shenoy } 8176909f179SGautham R. Shenoy 8186909f179SGautham R. Shenoy #else /* CONFIG_PPC_PSERIES */ 8196909f179SGautham R. Shenoy #define create_idle_purr_file(s) 8206909f179SGautham R. Shenoy #define remove_idle_purr_file(s) 8216909f179SGautham R. Shenoy #define create_idle_spurr_file(s) 8226909f179SGautham R. Shenoy #define remove_idle_spurr_file(s) 8236909f179SGautham R. Shenoy #endif /* CONFIG_PPC_PSERIES */ 8246909f179SGautham R. Shenoy 825977ab257SSebastian Andrzej Siewior static int register_cpu_online(unsigned int cpu) 826d3d2176aSDavid Gibson { 827d3d2176aSDavid Gibson struct cpu *c = &per_cpu(cpu_devices, cpu); 8288a25a2fdSKay Sievers struct device *s = &c->dev; 8298a25a2fdSKay Sievers struct device_attribute *attrs, *pmc_attrs; 8306529c13dSOlof Johansson int i, nattrs; 831d3d2176aSDavid Gibson 832e76ca277STyrel Datwyler /* For cpus present at boot a reference was already grabbed in register_cpu() */ 833e76ca277STyrel Datwyler if (!s->of_node) 834e76ca277STyrel Datwyler s->of_node = of_get_cpu_node(cpu, NULL); 835e76ca277STyrel Datwyler 836b950bdd0SBenjamin Herrenschmidt #ifdef CONFIG_PPC64 837f5339277SStephen Rothwell if (cpu_has_feature(CPU_FTR_SMT)) 8388a25a2fdSKay Sievers device_create_file(s, &dev_attr_smt_snooze_delay); 839b950bdd0SBenjamin Herrenschmidt #endif 840d3d2176aSDavid Gibson 841d3d2176aSDavid Gibson /* PMC stuff */ 8426529c13dSOlof Johansson switch (cur_cpu_spec->pmc_type) { 843b950bdd0SBenjamin Herrenschmidt #ifdef HAS_PPC_PMC_IBM 8446529c13dSOlof Johansson case PPC_PMC_IBM: 8456529c13dSOlof Johansson attrs = ibm_common_attrs; 846590e1e42SJason Wang nattrs = ARRAY_SIZE(ibm_common_attrs); 847b950bdd0SBenjamin Herrenschmidt pmc_attrs = classic_pmc_attrs; 8486529c13dSOlof Johansson break; 849b950bdd0SBenjamin Herrenschmidt #endif /* HAS_PPC_PMC_IBM */ 850b950bdd0SBenjamin Herrenschmidt #ifdef HAS_PPC_PMC_G4 851b950bdd0SBenjamin Herrenschmidt case PPC_PMC_G4: 852b950bdd0SBenjamin Herrenschmidt attrs = g4_common_attrs; 853590e1e42SJason Wang nattrs = ARRAY_SIZE(g4_common_attrs); 854b950bdd0SBenjamin Herrenschmidt pmc_attrs = classic_pmc_attrs; 855b950bdd0SBenjamin Herrenschmidt break; 856b950bdd0SBenjamin Herrenschmidt #endif /* HAS_PPC_PMC_G4 */ 857fcdb524dSMadhavan Srinivasan #if defined(HAS_PPC_PMC_PA6T) || defined(HAS_PPC_PA6T) 8586529c13dSOlof Johansson case PPC_PMC_PA6T: 8596529c13dSOlof Johansson /* PA Semi starts counting at PMC0 */ 8606529c13dSOlof Johansson attrs = pa6t_attrs; 861590e1e42SJason Wang nattrs = ARRAY_SIZE(pa6t_attrs); 8626529c13dSOlof Johansson pmc_attrs = NULL; 8636529c13dSOlof Johansson break; 864fcdb524dSMadhavan Srinivasan #endif 8656529c13dSOlof Johansson default: 8666529c13dSOlof Johansson attrs = NULL; 8676529c13dSOlof Johansson nattrs = 0; 8686529c13dSOlof Johansson pmc_attrs = NULL; 8696529c13dSOlof Johansson } 870d3d2176aSDavid Gibson 8716529c13dSOlof Johansson for (i = 0; i < nattrs; i++) 8728a25a2fdSKay Sievers device_create_file(s, &attrs[i]); 8736529c13dSOlof Johansson 8746529c13dSOlof Johansson if (pmc_attrs) 8756529c13dSOlof Johansson for (i = 0; i < cur_cpu_spec->num_pmcs; i++) 8768a25a2fdSKay Sievers device_create_file(s, &pmc_attrs[i]); 877d3d2176aSDavid Gibson 878b950bdd0SBenjamin Herrenschmidt #ifdef CONFIG_PPC64 87922697da3SKajol Jain #ifdef CONFIG_PMU_SYSFS 880d3d2176aSDavid Gibson if (cpu_has_feature(CPU_FTR_MMCRA)) 8818a25a2fdSKay Sievers device_create_file(s, &dev_attr_mmcra); 882c718547eSMadhavan Srinivasan 883c718547eSMadhavan Srinivasan if (cpu_has_feature(CPU_FTR_ARCH_31)) 884c718547eSMadhavan Srinivasan device_create_file(s, &dev_attr_mmcr3); 88522697da3SKajol Jain #endif /* CONFIG_PMU_SYSFS */ 886d3d2176aSDavid Gibson 887d1211af3SMadhavan Srinivasan if (cpu_has_feature(CPU_FTR_PURR)) { 888d1211af3SMadhavan Srinivasan if (!firmware_has_feature(FW_FEATURE_LPAR)) 889d1211af3SMadhavan Srinivasan add_write_permission_dev_attr(&dev_attr_purr); 8908a25a2fdSKay Sievers device_create_file(s, &dev_attr_purr); 8916909f179SGautham R. Shenoy create_idle_purr_file(s); 892d1211af3SMadhavan Srinivasan } 8934c198557SAnton Blanchard 8946909f179SGautham R. Shenoy if (cpu_has_feature(CPU_FTR_SPURR)) { 8958a25a2fdSKay Sievers device_create_file(s, &dev_attr_spurr); 8966909f179SGautham R. Shenoy create_idle_spurr_file(s); 8976909f179SGautham R. Shenoy } 898f050982aSAnton Blanchard 8994c198557SAnton Blanchard if (cpu_has_feature(CPU_FTR_DSCR)) 9008a25a2fdSKay Sievers device_create_file(s, &dev_attr_dscr); 901595fe914SAnanth N Mavinakayanahalli 902595fe914SAnanth N Mavinakayanahalli if (cpu_has_feature(CPU_FTR_PPCAS_ARCH_V2)) 9037affca35SLinus Torvalds device_create_file(s, &dev_attr_pir); 904b6d34eb4SAnton Blanchard 905c134f0d5SCyril Bur if (cpu_has_feature(CPU_FTR_ARCH_206) && 906c134f0d5SCyril Bur !firmware_has_feature(FW_FEATURE_LPAR)) 907b6d34eb4SAnton Blanchard device_create_file(s, &dev_attr_tscr); 908b950bdd0SBenjamin Herrenschmidt #endif /* CONFIG_PPC64 */ 909124c27d3SNathan Lynch 910*3e731858SChristophe Leroy #ifdef CONFIG_PPC_E500 911a7189483SWang Dongsheng if (PVR_VER(cur_cpu_spec->pvr_value) == PVR_VER_E6500) { 912a7189483SWang Dongsheng device_create_file(s, &dev_attr_pw20_state); 913a7189483SWang Dongsheng device_create_file(s, &dev_attr_pw20_wait_time); 914a7189483SWang Dongsheng 915a7189483SWang Dongsheng device_create_file(s, &dev_attr_altivec_idle); 916a7189483SWang Dongsheng device_create_file(s, &dev_attr_altivec_idle_wait_time); 917a7189483SWang Dongsheng } 918a7189483SWang Dongsheng #endif 91993197a36SNathan Lynch cacheinfo_cpu_online(cpu); 920977ab257SSebastian Andrzej Siewior return 0; 921d3d2176aSDavid Gibson } 922d3d2176aSDavid Gibson 9233f2290e1SMichael Ellerman #ifdef CONFIG_HOTPLUG_CPU 924977ab257SSebastian Andrzej Siewior static int unregister_cpu_online(unsigned int cpu) 925d3d2176aSDavid Gibson { 926d3d2176aSDavid Gibson struct cpu *c = &per_cpu(cpu_devices, cpu); 9278a25a2fdSKay Sievers struct device *s = &c->dev; 9288a25a2fdSKay Sievers struct device_attribute *attrs, *pmc_attrs; 9296529c13dSOlof Johansson int i, nattrs; 930d3d2176aSDavid Gibson 931983f9101SNathan Lynch if (WARN_RATELIMIT(!c->hotpluggable, "cpu %d can't be offlined\n", cpu)) 932983f9101SNathan Lynch return -EBUSY; 933d3d2176aSDavid Gibson 934a1e0eb10SMilton Miller #ifdef CONFIG_PPC64 935f5339277SStephen Rothwell if (cpu_has_feature(CPU_FTR_SMT)) 9368a25a2fdSKay Sievers device_remove_file(s, &dev_attr_smt_snooze_delay); 937a1e0eb10SMilton Miller #endif 938d3d2176aSDavid Gibson 939d3d2176aSDavid Gibson /* PMC stuff */ 9406529c13dSOlof Johansson switch (cur_cpu_spec->pmc_type) { 941b950bdd0SBenjamin Herrenschmidt #ifdef HAS_PPC_PMC_IBM 9426529c13dSOlof Johansson case PPC_PMC_IBM: 9436529c13dSOlof Johansson attrs = ibm_common_attrs; 944590e1e42SJason Wang nattrs = ARRAY_SIZE(ibm_common_attrs); 945b950bdd0SBenjamin Herrenschmidt pmc_attrs = classic_pmc_attrs; 9466529c13dSOlof Johansson break; 947b950bdd0SBenjamin Herrenschmidt #endif /* HAS_PPC_PMC_IBM */ 948b950bdd0SBenjamin Herrenschmidt #ifdef HAS_PPC_PMC_G4 949b950bdd0SBenjamin Herrenschmidt case PPC_PMC_G4: 950b950bdd0SBenjamin Herrenschmidt attrs = g4_common_attrs; 951590e1e42SJason Wang nattrs = ARRAY_SIZE(g4_common_attrs); 952b950bdd0SBenjamin Herrenschmidt pmc_attrs = classic_pmc_attrs; 953b950bdd0SBenjamin Herrenschmidt break; 954b950bdd0SBenjamin Herrenschmidt #endif /* HAS_PPC_PMC_G4 */ 955fcdb524dSMadhavan Srinivasan #if defined(HAS_PPC_PMC_PA6T) || defined(HAS_PPC_PA6T) 9566529c13dSOlof Johansson case PPC_PMC_PA6T: 9576529c13dSOlof Johansson /* PA Semi starts counting at PMC0 */ 9586529c13dSOlof Johansson attrs = pa6t_attrs; 959590e1e42SJason Wang nattrs = ARRAY_SIZE(pa6t_attrs); 9606529c13dSOlof Johansson pmc_attrs = NULL; 9616529c13dSOlof Johansson break; 962fcdb524dSMadhavan Srinivasan #endif 9636529c13dSOlof Johansson default: 9646529c13dSOlof Johansson attrs = NULL; 9656529c13dSOlof Johansson nattrs = 0; 9666529c13dSOlof Johansson pmc_attrs = NULL; 9676529c13dSOlof Johansson } 968d3d2176aSDavid Gibson 9696529c13dSOlof Johansson for (i = 0; i < nattrs; i++) 9708a25a2fdSKay Sievers device_remove_file(s, &attrs[i]); 9716529c13dSOlof Johansson 9726529c13dSOlof Johansson if (pmc_attrs) 9736529c13dSOlof Johansson for (i = 0; i < cur_cpu_spec->num_pmcs; i++) 9748a25a2fdSKay Sievers device_remove_file(s, &pmc_attrs[i]); 975d3d2176aSDavid Gibson 976b950bdd0SBenjamin Herrenschmidt #ifdef CONFIG_PPC64 97722697da3SKajol Jain #ifdef CONFIG_PMU_SYSFS 978d3d2176aSDavid Gibson if (cpu_has_feature(CPU_FTR_MMCRA)) 9798a25a2fdSKay Sievers device_remove_file(s, &dev_attr_mmcra); 980c718547eSMadhavan Srinivasan 981c718547eSMadhavan Srinivasan if (cpu_has_feature(CPU_FTR_ARCH_31)) 982c718547eSMadhavan Srinivasan device_remove_file(s, &dev_attr_mmcr3); 98322697da3SKajol Jain #endif /* CONFIG_PMU_SYSFS */ 984d3d2176aSDavid Gibson 9856909f179SGautham R. Shenoy if (cpu_has_feature(CPU_FTR_PURR)) { 9868a25a2fdSKay Sievers device_remove_file(s, &dev_attr_purr); 9876909f179SGautham R. Shenoy remove_idle_purr_file(s); 9886909f179SGautham R. Shenoy } 9894c198557SAnton Blanchard 9906909f179SGautham R. Shenoy if (cpu_has_feature(CPU_FTR_SPURR)) { 9918a25a2fdSKay Sievers device_remove_file(s, &dev_attr_spurr); 9926909f179SGautham R. Shenoy remove_idle_spurr_file(s); 9936909f179SGautham R. Shenoy } 994f050982aSAnton Blanchard 9954c198557SAnton Blanchard if (cpu_has_feature(CPU_FTR_DSCR)) 9968a25a2fdSKay Sievers device_remove_file(s, &dev_attr_dscr); 997595fe914SAnanth N Mavinakayanahalli 998595fe914SAnanth N Mavinakayanahalli if (cpu_has_feature(CPU_FTR_PPCAS_ARCH_V2)) 9997affca35SLinus Torvalds device_remove_file(s, &dev_attr_pir); 1000b6d34eb4SAnton Blanchard 1001c134f0d5SCyril Bur if (cpu_has_feature(CPU_FTR_ARCH_206) && 1002c134f0d5SCyril Bur !firmware_has_feature(FW_FEATURE_LPAR)) 1003b6d34eb4SAnton Blanchard device_remove_file(s, &dev_attr_tscr); 1004b950bdd0SBenjamin Herrenschmidt #endif /* CONFIG_PPC64 */ 1005124c27d3SNathan Lynch 1006*3e731858SChristophe Leroy #ifdef CONFIG_PPC_E500 1007a7189483SWang Dongsheng if (PVR_VER(cur_cpu_spec->pvr_value) == PVR_VER_E6500) { 1008a7189483SWang Dongsheng device_remove_file(s, &dev_attr_pw20_state); 1009a7189483SWang Dongsheng device_remove_file(s, &dev_attr_pw20_wait_time); 1010a7189483SWang Dongsheng 1011a7189483SWang Dongsheng device_remove_file(s, &dev_attr_altivec_idle); 1012a7189483SWang Dongsheng device_remove_file(s, &dev_attr_altivec_idle_wait_time); 1013a7189483SWang Dongsheng } 1014a7189483SWang Dongsheng #endif 101593197a36SNathan Lynch cacheinfo_cpu_offline(cpu); 1016e76ca277STyrel Datwyler of_node_put(s->of_node); 1017e76ca277STyrel Datwyler s->of_node = NULL; 1018977ab257SSebastian Andrzej Siewior return 0; 1019d3d2176aSDavid Gibson } 10203f2290e1SMichael Ellerman #else /* !CONFIG_HOTPLUG_CPU */ 10213f2290e1SMichael Ellerman #define unregister_cpu_online NULL 10223f2290e1SMichael Ellerman #endif 102312633e80SNathan Fontenot 102412633e80SNathan Fontenot #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE 102512633e80SNathan Fontenot ssize_t arch_cpu_probe(const char *buf, size_t count) 102612633e80SNathan Fontenot { 102712633e80SNathan Fontenot if (ppc_md.cpu_probe) 102812633e80SNathan Fontenot return ppc_md.cpu_probe(buf, count); 102912633e80SNathan Fontenot 103012633e80SNathan Fontenot return -EINVAL; 103112633e80SNathan Fontenot } 103212633e80SNathan Fontenot 103312633e80SNathan Fontenot ssize_t arch_cpu_release(const char *buf, size_t count) 103412633e80SNathan Fontenot { 103512633e80SNathan Fontenot if (ppc_md.cpu_release) 103612633e80SNathan Fontenot return ppc_md.cpu_release(buf, count); 103712633e80SNathan Fontenot 103812633e80SNathan Fontenot return -EINVAL; 103912633e80SNathan Fontenot } 104012633e80SNathan Fontenot #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ 104112633e80SNathan Fontenot 10420344c6c5SChristian Krafft static DEFINE_MUTEX(cpu_mutex); 10430344c6c5SChristian Krafft 10448a25a2fdSKay Sievers int cpu_add_dev_attr(struct device_attribute *attr) 10450344c6c5SChristian Krafft { 10460344c6c5SChristian Krafft int cpu; 10470344c6c5SChristian Krafft 10480344c6c5SChristian Krafft mutex_lock(&cpu_mutex); 10490344c6c5SChristian Krafft 10500344c6c5SChristian Krafft for_each_possible_cpu(cpu) { 10518a25a2fdSKay Sievers device_create_file(get_cpu_device(cpu), attr); 10520344c6c5SChristian Krafft } 10530344c6c5SChristian Krafft 10540344c6c5SChristian Krafft mutex_unlock(&cpu_mutex); 10550344c6c5SChristian Krafft return 0; 10560344c6c5SChristian Krafft } 10578a25a2fdSKay Sievers EXPORT_SYMBOL_GPL(cpu_add_dev_attr); 10580344c6c5SChristian Krafft 10598a25a2fdSKay Sievers int cpu_add_dev_attr_group(struct attribute_group *attrs) 10600344c6c5SChristian Krafft { 10610344c6c5SChristian Krafft int cpu; 10628a25a2fdSKay Sievers struct device *dev; 10636bcc4c01SOlof Johansson int ret; 10640344c6c5SChristian Krafft 10650344c6c5SChristian Krafft mutex_lock(&cpu_mutex); 10660344c6c5SChristian Krafft 10670344c6c5SChristian Krafft for_each_possible_cpu(cpu) { 10688a25a2fdSKay Sievers dev = get_cpu_device(cpu); 10698a25a2fdSKay Sievers ret = sysfs_create_group(&dev->kobj, attrs); 10706bcc4c01SOlof Johansson WARN_ON(ret != 0); 10710344c6c5SChristian Krafft } 10720344c6c5SChristian Krafft 10730344c6c5SChristian Krafft mutex_unlock(&cpu_mutex); 10740344c6c5SChristian Krafft return 0; 10750344c6c5SChristian Krafft } 10768a25a2fdSKay Sievers EXPORT_SYMBOL_GPL(cpu_add_dev_attr_group); 10770344c6c5SChristian Krafft 10780344c6c5SChristian Krafft 10798a25a2fdSKay Sievers void cpu_remove_dev_attr(struct device_attribute *attr) 10800344c6c5SChristian Krafft { 10810344c6c5SChristian Krafft int cpu; 10820344c6c5SChristian Krafft 10830344c6c5SChristian Krafft mutex_lock(&cpu_mutex); 10840344c6c5SChristian Krafft 10850344c6c5SChristian Krafft for_each_possible_cpu(cpu) { 10868a25a2fdSKay Sievers device_remove_file(get_cpu_device(cpu), attr); 10870344c6c5SChristian Krafft } 10880344c6c5SChristian Krafft 10890344c6c5SChristian Krafft mutex_unlock(&cpu_mutex); 10900344c6c5SChristian Krafft } 10918a25a2fdSKay Sievers EXPORT_SYMBOL_GPL(cpu_remove_dev_attr); 10920344c6c5SChristian Krafft 10938a25a2fdSKay Sievers void cpu_remove_dev_attr_group(struct attribute_group *attrs) 10940344c6c5SChristian Krafft { 10950344c6c5SChristian Krafft int cpu; 10968a25a2fdSKay Sievers struct device *dev; 10970344c6c5SChristian Krafft 10980344c6c5SChristian Krafft mutex_lock(&cpu_mutex); 10990344c6c5SChristian Krafft 11000344c6c5SChristian Krafft for_each_possible_cpu(cpu) { 11018a25a2fdSKay Sievers dev = get_cpu_device(cpu); 11028a25a2fdSKay Sievers sysfs_remove_group(&dev->kobj, attrs); 11030344c6c5SChristian Krafft } 11040344c6c5SChristian Krafft 11050344c6c5SChristian Krafft mutex_unlock(&cpu_mutex); 11060344c6c5SChristian Krafft } 11078a25a2fdSKay Sievers EXPORT_SYMBOL_GPL(cpu_remove_dev_attr_group); 11080344c6c5SChristian Krafft 11090344c6c5SChristian Krafft 1110d3d2176aSDavid Gibson /* NUMA stuff */ 1111d3d2176aSDavid Gibson 1112d3d2176aSDavid Gibson #ifdef CONFIG_NUMA 11138a25a2fdSKay Sievers int sysfs_add_device_to_node(struct device *dev, int nid) 1114953039c8SJeremy Kerr { 11158732794bSWen Congyang struct node *node = node_devices[nid]; 111610fbcf4cSKay Sievers return sysfs_create_link(&node->dev.kobj, &dev->kobj, 1117953039c8SJeremy Kerr kobject_name(&dev->kobj)); 1118953039c8SJeremy Kerr } 111912654f77SJohannes Berg EXPORT_SYMBOL_GPL(sysfs_add_device_to_node); 1120953039c8SJeremy Kerr 11218a25a2fdSKay Sievers void sysfs_remove_device_from_node(struct device *dev, int nid) 1122953039c8SJeremy Kerr { 11238732794bSWen Congyang struct node *node = node_devices[nid]; 112410fbcf4cSKay Sievers sysfs_remove_link(&node->dev.kobj, kobject_name(&dev->kobj)); 1125953039c8SJeremy Kerr } 112612654f77SJohannes Berg EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node); 1127d3d2176aSDavid Gibson #endif 1128d3d2176aSDavid Gibson 1129d3d2176aSDavid Gibson /* Only valid if CPU is present. */ 11308a25a2fdSKay Sievers static ssize_t show_physical_id(struct device *dev, 11318a25a2fdSKay Sievers struct device_attribute *attr, char *buf) 1132d3d2176aSDavid Gibson { 11338a25a2fdSKay Sievers struct cpu *cpu = container_of(dev, struct cpu, dev); 1134d3d2176aSDavid Gibson 11358a25a2fdSKay Sievers return sprintf(buf, "%d\n", get_hard_smp_processor_id(cpu->dev.id)); 1136d3d2176aSDavid Gibson } 11378a25a2fdSKay Sievers static DEVICE_ATTR(physical_id, 0444, show_physical_id, NULL); 1138d3d2176aSDavid Gibson 1139d3d2176aSDavid Gibson static int __init topology_init(void) 1140d3d2176aSDavid Gibson { 1141977ab257SSebastian Andrzej Siewior int cpu, r; 1142d3d2176aSDavid Gibson 11430e551954SKAMEZAWA Hiroyuki for_each_possible_cpu(cpu) { 1144d3d2176aSDavid Gibson struct cpu *c = &per_cpu(cpu_devices, cpu); 1145d3d2176aSDavid Gibson 114639f87561SMichael Ellerman #ifdef CONFIG_HOTPLUG_CPU 1147d3d2176aSDavid Gibson /* 1148d3d2176aSDavid Gibson * For now, we just see if the system supports making 1149d3d2176aSDavid Gibson * the RTAS calls for CPU hotplug. But, there may be a 1150d3d2176aSDavid Gibson * more comprehensive way to do this for an individual 1151d3d2176aSDavid Gibson * CPU. For instance, the boot cpu might never be valid 1152d3d2176aSDavid Gibson * for hotplugging. 1153d3d2176aSDavid Gibson */ 115482414615SChristophe Leroy if (smp_ops && smp_ops->cpu_offline_self) 115572486f1fSSiddha, Suresh B c->hotpluggable = 1; 115639f87561SMichael Ellerman #endif 1157d3d2176aSDavid Gibson 115872486f1fSSiddha, Suresh B if (cpu_online(cpu) || c->hotpluggable) { 115976b67ed9SKAMEZAWA Hiroyuki register_cpu(c, cpu); 1160d3d2176aSDavid Gibson 11618a25a2fdSKay Sievers device_create_file(&c->dev, &dev_attr_physical_id); 1162d3d2176aSDavid Gibson } 1163d3d2176aSDavid Gibson } 1164977ab257SSebastian Andrzej Siewior r = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powerpc/topology:online", 1165977ab257SSebastian Andrzej Siewior register_cpu_online, unregister_cpu_online); 1166977ab257SSebastian Andrzej Siewior WARN_ON(r < 0); 1167efcac658SAlexey Kardashevskiy #ifdef CONFIG_PPC64 1168efcac658SAlexey Kardashevskiy sysfs_create_dscr_default(); 1169efcac658SAlexey Kardashevskiy #endif /* CONFIG_PPC64 */ 1170d3d2176aSDavid Gibson 1171734560acSRyan Grimm create_svm_file(); 1172734560acSRyan Grimm 1173d3d2176aSDavid Gibson return 0; 1174d3d2176aSDavid Gibson } 1175e9e77ce8SKevin Corry subsys_initcall(topology_init); 1176