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> 12d3d2176aSDavid Gibson 13d3d2176aSDavid Gibson #include <asm/current.h> 14d3d2176aSDavid Gibson #include <asm/processor.h> 15d3d2176aSDavid Gibson #include <asm/cputable.h> 16d3d2176aSDavid Gibson #include <asm/hvcall.h> 17d3d2176aSDavid Gibson #include <asm/prom.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> 22*6909f179SGautham 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 /* 36b950bdd0SBenjamin Herrenschmidt * SMT snooze delay stuff, 64-bit only for now 37b950bdd0SBenjamin Herrenschmidt */ 38d3d2176aSDavid Gibson 39b950bdd0SBenjamin Herrenschmidt #ifdef CONFIG_PPC64 40b950bdd0SBenjamin Herrenschmidt 410ddd3e7dSAnton Blanchard /* Time in microseconds we delay before sleeping in the idle loop */ 4234852ed5SDaniel Axtens static DEFINE_PER_CPU(long, smt_snooze_delay) = { 100 }; 43d3d2176aSDavid Gibson 448a25a2fdSKay Sievers static ssize_t store_smt_snooze_delay(struct device *dev, 458a25a2fdSKay Sievers struct device_attribute *attr, 464a0b2b4dSAndi Kleen const char *buf, 47d3d2176aSDavid Gibson size_t count) 48d3d2176aSDavid Gibson { 498a25a2fdSKay Sievers struct cpu *cpu = container_of(dev, struct cpu, dev); 50d3d2176aSDavid Gibson ssize_t ret; 51b878dc00SAnton Blanchard long snooze; 52d3d2176aSDavid Gibson 53b878dc00SAnton Blanchard ret = sscanf(buf, "%ld", &snooze); 54d3d2176aSDavid Gibson if (ret != 1) 55d3d2176aSDavid Gibson return -EINVAL; 56d3d2176aSDavid Gibson 578a25a2fdSKay Sievers per_cpu(smt_snooze_delay, cpu->dev.id) = snooze; 58d3d2176aSDavid Gibson return count; 59d3d2176aSDavid Gibson } 60d3d2176aSDavid Gibson 618a25a2fdSKay Sievers static ssize_t show_smt_snooze_delay(struct device *dev, 628a25a2fdSKay Sievers struct device_attribute *attr, 634a0b2b4dSAndi Kleen char *buf) 64d3d2176aSDavid Gibson { 658a25a2fdSKay Sievers struct cpu *cpu = container_of(dev, struct cpu, dev); 66d3d2176aSDavid Gibson 678a25a2fdSKay Sievers return sprintf(buf, "%ld\n", per_cpu(smt_snooze_delay, cpu->dev.id)); 68d3d2176aSDavid Gibson } 69d3d2176aSDavid Gibson 708a25a2fdSKay Sievers static DEVICE_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay, 71d3d2176aSDavid Gibson store_smt_snooze_delay); 72d3d2176aSDavid Gibson 73d3d2176aSDavid Gibson static int __init setup_smt_snooze_delay(char *str) 74d3d2176aSDavid Gibson { 75d3d2176aSDavid Gibson unsigned int cpu; 76b878dc00SAnton Blanchard long snooze; 77d3d2176aSDavid Gibson 78d3d2176aSDavid Gibson if (!cpu_has_feature(CPU_FTR_SMT)) 79d3d2176aSDavid Gibson return 1; 80d3d2176aSDavid Gibson 81b878dc00SAnton Blanchard snooze = simple_strtol(str, NULL, 10); 820e551954SKAMEZAWA Hiroyuki for_each_possible_cpu(cpu) 83d3d2176aSDavid Gibson per_cpu(smt_snooze_delay, cpu) = snooze; 84d3d2176aSDavid Gibson 85d3d2176aSDavid Gibson return 1; 86d3d2176aSDavid Gibson } 87d3d2176aSDavid Gibson __setup("smt-snooze-delay=", setup_smt_snooze_delay); 88d3d2176aSDavid Gibson 89b950bdd0SBenjamin Herrenschmidt #endif /* CONFIG_PPC64 */ 90d3d2176aSDavid Gibson 91fcdb524dSMadhavan Srinivasan #define __SYSFS_SPRSETUP_READ_WRITE(NAME, ADDRESS, EXTRA) \ 92fcdb524dSMadhavan Srinivasan static void read_##NAME(void *val) \ 93fcdb524dSMadhavan Srinivasan { \ 94fcdb524dSMadhavan Srinivasan *(unsigned long *)val = mfspr(ADDRESS); \ 95fcdb524dSMadhavan Srinivasan } \ 96fcdb524dSMadhavan Srinivasan static void write_##NAME(void *val) \ 97fcdb524dSMadhavan Srinivasan { \ 98fcdb524dSMadhavan Srinivasan EXTRA; \ 99fcdb524dSMadhavan Srinivasan mtspr(ADDRESS, *(unsigned long *)val); \ 100fcdb524dSMadhavan Srinivasan } 101fcdb524dSMadhavan Srinivasan 102fcdb524dSMadhavan Srinivasan #define __SYSFS_SPRSETUP_SHOW_STORE(NAME) \ 103fcdb524dSMadhavan Srinivasan static ssize_t show_##NAME(struct device *dev, \ 104fcdb524dSMadhavan Srinivasan struct device_attribute *attr, \ 105fcdb524dSMadhavan Srinivasan char *buf) \ 106fcdb524dSMadhavan Srinivasan { \ 107fcdb524dSMadhavan Srinivasan struct cpu *cpu = container_of(dev, struct cpu, dev); \ 108fcdb524dSMadhavan Srinivasan unsigned long val; \ 109fcdb524dSMadhavan Srinivasan smp_call_function_single(cpu->dev.id, read_##NAME, &val, 1); \ 110fcdb524dSMadhavan Srinivasan return sprintf(buf, "%lx\n", val); \ 111fcdb524dSMadhavan Srinivasan } \ 112fcdb524dSMadhavan Srinivasan static ssize_t __used \ 113fcdb524dSMadhavan Srinivasan store_##NAME(struct device *dev, struct device_attribute *attr, \ 114fcdb524dSMadhavan Srinivasan const char *buf, size_t count) \ 115fcdb524dSMadhavan Srinivasan { \ 116fcdb524dSMadhavan Srinivasan struct cpu *cpu = container_of(dev, struct cpu, dev); \ 117fcdb524dSMadhavan Srinivasan unsigned long val; \ 118fcdb524dSMadhavan Srinivasan int ret = sscanf(buf, "%lx", &val); \ 119fcdb524dSMadhavan Srinivasan if (ret != 1) \ 120fcdb524dSMadhavan Srinivasan return -EINVAL; \ 121fcdb524dSMadhavan Srinivasan smp_call_function_single(cpu->dev.id, write_##NAME, &val, 1); \ 122fcdb524dSMadhavan Srinivasan return count; \ 123fcdb524dSMadhavan Srinivasan } 124fcdb524dSMadhavan Srinivasan 125fcdb524dSMadhavan Srinivasan #define SYSFS_PMCSETUP(NAME, ADDRESS) \ 126fcdb524dSMadhavan Srinivasan __SYSFS_SPRSETUP_READ_WRITE(NAME, ADDRESS, ppc_enable_pmcs()) \ 127fcdb524dSMadhavan Srinivasan __SYSFS_SPRSETUP_SHOW_STORE(NAME) 128fcdb524dSMadhavan Srinivasan #define SYSFS_SPRSETUP(NAME, ADDRESS) \ 129fcdb524dSMadhavan Srinivasan __SYSFS_SPRSETUP_READ_WRITE(NAME, ADDRESS, ) \ 130fcdb524dSMadhavan Srinivasan __SYSFS_SPRSETUP_SHOW_STORE(NAME) 131fcdb524dSMadhavan Srinivasan 132fcdb524dSMadhavan Srinivasan #define SYSFS_SPRSETUP_SHOW_STORE(NAME) \ 133fcdb524dSMadhavan Srinivasan __SYSFS_SPRSETUP_SHOW_STORE(NAME) 134fcdb524dSMadhavan Srinivasan 135fcdb524dSMadhavan Srinivasan #ifdef CONFIG_PPC64 136fcdb524dSMadhavan Srinivasan 137fcdb524dSMadhavan Srinivasan /* 138fcdb524dSMadhavan Srinivasan * This is the system wide DSCR register default value. Any 139fcdb524dSMadhavan Srinivasan * change to this default value through the sysfs interface 140fcdb524dSMadhavan Srinivasan * will update all per cpu DSCR default values across the 141fcdb524dSMadhavan Srinivasan * system stored in their respective PACA structures. 142fcdb524dSMadhavan Srinivasan */ 143fcdb524dSMadhavan Srinivasan static unsigned long dscr_default; 144fcdb524dSMadhavan Srinivasan 145fcdb524dSMadhavan Srinivasan /** 146fcdb524dSMadhavan Srinivasan * read_dscr() - Fetch the cpu specific DSCR default 147fcdb524dSMadhavan Srinivasan * @val: Returned cpu specific DSCR default value 148fcdb524dSMadhavan Srinivasan * 149fcdb524dSMadhavan Srinivasan * This function returns the per cpu DSCR default value 150fcdb524dSMadhavan Srinivasan * for any cpu which is contained in it's PACA structure. 151fcdb524dSMadhavan Srinivasan */ 152fcdb524dSMadhavan Srinivasan static void read_dscr(void *val) 153fcdb524dSMadhavan Srinivasan { 154fcdb524dSMadhavan Srinivasan *(unsigned long *)val = get_paca()->dscr_default; 155fcdb524dSMadhavan Srinivasan } 156fcdb524dSMadhavan Srinivasan 157fcdb524dSMadhavan Srinivasan 158fcdb524dSMadhavan Srinivasan /** 159fcdb524dSMadhavan Srinivasan * write_dscr() - Update the cpu specific DSCR default 160fcdb524dSMadhavan Srinivasan * @val: New cpu specific DSCR default value to update 161fcdb524dSMadhavan Srinivasan * 162fcdb524dSMadhavan Srinivasan * This function updates the per cpu DSCR default value 163fcdb524dSMadhavan Srinivasan * for any cpu which is contained in it's PACA structure. 164fcdb524dSMadhavan Srinivasan */ 165fcdb524dSMadhavan Srinivasan static void write_dscr(void *val) 166fcdb524dSMadhavan Srinivasan { 167fcdb524dSMadhavan Srinivasan get_paca()->dscr_default = *(unsigned long *)val; 168fcdb524dSMadhavan Srinivasan if (!current->thread.dscr_inherit) { 169fcdb524dSMadhavan Srinivasan current->thread.dscr = *(unsigned long *)val; 170fcdb524dSMadhavan Srinivasan mtspr(SPRN_DSCR, *(unsigned long *)val); 171fcdb524dSMadhavan Srinivasan } 172fcdb524dSMadhavan Srinivasan } 173fcdb524dSMadhavan Srinivasan 174fcdb524dSMadhavan Srinivasan SYSFS_SPRSETUP_SHOW_STORE(dscr); 175fcdb524dSMadhavan Srinivasan static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr); 176fcdb524dSMadhavan Srinivasan 177fcdb524dSMadhavan Srinivasan static void add_write_permission_dev_attr(struct device_attribute *attr) 178fcdb524dSMadhavan Srinivasan { 179fcdb524dSMadhavan Srinivasan attr->attr.mode |= 0200; 180fcdb524dSMadhavan Srinivasan } 181fcdb524dSMadhavan Srinivasan 182fcdb524dSMadhavan Srinivasan /** 183fcdb524dSMadhavan Srinivasan * show_dscr_default() - Fetch the system wide DSCR default 184fcdb524dSMadhavan Srinivasan * @dev: Device structure 185fcdb524dSMadhavan Srinivasan * @attr: Device attribute structure 186fcdb524dSMadhavan Srinivasan * @buf: Interface buffer 187fcdb524dSMadhavan Srinivasan * 188fcdb524dSMadhavan Srinivasan * This function returns the system wide DSCR default value. 189fcdb524dSMadhavan Srinivasan */ 190fcdb524dSMadhavan Srinivasan static ssize_t show_dscr_default(struct device *dev, 191fcdb524dSMadhavan Srinivasan struct device_attribute *attr, char *buf) 192fcdb524dSMadhavan Srinivasan { 193fcdb524dSMadhavan Srinivasan return sprintf(buf, "%lx\n", dscr_default); 194fcdb524dSMadhavan Srinivasan } 195fcdb524dSMadhavan Srinivasan 196fcdb524dSMadhavan Srinivasan /** 197fcdb524dSMadhavan Srinivasan * store_dscr_default() - Update the system wide DSCR default 198fcdb524dSMadhavan Srinivasan * @dev: Device structure 199fcdb524dSMadhavan Srinivasan * @attr: Device attribute structure 200fcdb524dSMadhavan Srinivasan * @buf: Interface buffer 201fcdb524dSMadhavan Srinivasan * @count: Size of the update 202fcdb524dSMadhavan Srinivasan * 203fcdb524dSMadhavan Srinivasan * This function updates the system wide DSCR default value. 204fcdb524dSMadhavan Srinivasan */ 205fcdb524dSMadhavan Srinivasan static ssize_t __used store_dscr_default(struct device *dev, 206fcdb524dSMadhavan Srinivasan struct device_attribute *attr, const char *buf, 207fcdb524dSMadhavan Srinivasan size_t count) 208fcdb524dSMadhavan Srinivasan { 209fcdb524dSMadhavan Srinivasan unsigned long val; 210fcdb524dSMadhavan Srinivasan int ret = 0; 211fcdb524dSMadhavan Srinivasan 212fcdb524dSMadhavan Srinivasan ret = sscanf(buf, "%lx", &val); 213fcdb524dSMadhavan Srinivasan if (ret != 1) 214fcdb524dSMadhavan Srinivasan return -EINVAL; 215fcdb524dSMadhavan Srinivasan dscr_default = val; 216fcdb524dSMadhavan Srinivasan 217fcdb524dSMadhavan Srinivasan on_each_cpu(write_dscr, &val, 1); 218fcdb524dSMadhavan Srinivasan 219fcdb524dSMadhavan Srinivasan return count; 220fcdb524dSMadhavan Srinivasan } 221fcdb524dSMadhavan Srinivasan 222fcdb524dSMadhavan Srinivasan static DEVICE_ATTR(dscr_default, 0600, 223fcdb524dSMadhavan Srinivasan show_dscr_default, store_dscr_default); 224fcdb524dSMadhavan Srinivasan 225fcdb524dSMadhavan Srinivasan static void sysfs_create_dscr_default(void) 226fcdb524dSMadhavan Srinivasan { 227fcdb524dSMadhavan Srinivasan if (cpu_has_feature(CPU_FTR_DSCR)) { 228fcdb524dSMadhavan Srinivasan int err = 0; 229fcdb524dSMadhavan Srinivasan int cpu; 230fcdb524dSMadhavan Srinivasan 231fcdb524dSMadhavan Srinivasan dscr_default = spr_default_dscr; 232fcdb524dSMadhavan Srinivasan for_each_possible_cpu(cpu) 233fcdb524dSMadhavan Srinivasan paca_ptrs[cpu]->dscr_default = dscr_default; 234fcdb524dSMadhavan Srinivasan 235fcdb524dSMadhavan Srinivasan err = device_create_file(cpu_subsys.dev_root, &dev_attr_dscr_default); 236fcdb524dSMadhavan Srinivasan } 237fcdb524dSMadhavan Srinivasan } 238fcdb524dSMadhavan Srinivasan #endif /* CONFIG_PPC64 */ 239fcdb524dSMadhavan Srinivasan 240a7189483SWang Dongsheng #ifdef CONFIG_PPC_FSL_BOOK3E 241a7189483SWang Dongsheng #define MAX_BIT 63 242a7189483SWang Dongsheng 243a7189483SWang Dongsheng static u64 pw20_wt; 244a7189483SWang Dongsheng static u64 altivec_idle_wt; 245a7189483SWang Dongsheng 246a7189483SWang Dongsheng static unsigned int get_idle_ticks_bit(u64 ns) 247a7189483SWang Dongsheng { 248a7189483SWang Dongsheng u64 cycle; 249a7189483SWang Dongsheng 250a7189483SWang Dongsheng if (ns >= 10000) 251a7189483SWang Dongsheng cycle = div_u64(ns + 500, 1000) * tb_ticks_per_usec; 252a7189483SWang Dongsheng else 253a7189483SWang Dongsheng cycle = div_u64(ns * tb_ticks_per_usec, 1000); 254a7189483SWang Dongsheng 255a7189483SWang Dongsheng if (!cycle) 256a7189483SWang Dongsheng return 0; 257a7189483SWang Dongsheng 258a7189483SWang Dongsheng return ilog2(cycle); 259a7189483SWang Dongsheng } 260a7189483SWang Dongsheng 261a7189483SWang Dongsheng static void do_show_pwrmgtcr0(void *val) 262a7189483SWang Dongsheng { 263a7189483SWang Dongsheng u32 *value = val; 264a7189483SWang Dongsheng 265a7189483SWang Dongsheng *value = mfspr(SPRN_PWRMGTCR0); 266a7189483SWang Dongsheng } 267a7189483SWang Dongsheng 268a7189483SWang Dongsheng static ssize_t show_pw20_state(struct device *dev, 269a7189483SWang Dongsheng struct device_attribute *attr, char *buf) 270a7189483SWang Dongsheng { 271a7189483SWang Dongsheng u32 value; 272a7189483SWang Dongsheng unsigned int cpu = dev->id; 273a7189483SWang Dongsheng 274a7189483SWang Dongsheng smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1); 275a7189483SWang Dongsheng 276a7189483SWang Dongsheng value &= PWRMGTCR0_PW20_WAIT; 277a7189483SWang Dongsheng 278a7189483SWang Dongsheng return sprintf(buf, "%u\n", value ? 1 : 0); 279a7189483SWang Dongsheng } 280a7189483SWang Dongsheng 281a7189483SWang Dongsheng static void do_store_pw20_state(void *val) 282a7189483SWang Dongsheng { 283a7189483SWang Dongsheng u32 *value = val; 284a7189483SWang Dongsheng u32 pw20_state; 285a7189483SWang Dongsheng 286a7189483SWang Dongsheng pw20_state = mfspr(SPRN_PWRMGTCR0); 287a7189483SWang Dongsheng 288a7189483SWang Dongsheng if (*value) 289a7189483SWang Dongsheng pw20_state |= PWRMGTCR0_PW20_WAIT; 290a7189483SWang Dongsheng else 291a7189483SWang Dongsheng pw20_state &= ~PWRMGTCR0_PW20_WAIT; 292a7189483SWang Dongsheng 293a7189483SWang Dongsheng mtspr(SPRN_PWRMGTCR0, pw20_state); 294a7189483SWang Dongsheng } 295a7189483SWang Dongsheng 296a7189483SWang Dongsheng static ssize_t store_pw20_state(struct device *dev, 297a7189483SWang Dongsheng struct device_attribute *attr, 298a7189483SWang Dongsheng const char *buf, size_t count) 299a7189483SWang Dongsheng { 300a7189483SWang Dongsheng u32 value; 301a7189483SWang Dongsheng unsigned int cpu = dev->id; 302a7189483SWang Dongsheng 303a7189483SWang Dongsheng if (kstrtou32(buf, 0, &value)) 304a7189483SWang Dongsheng return -EINVAL; 305a7189483SWang Dongsheng 306a7189483SWang Dongsheng if (value > 1) 307a7189483SWang Dongsheng return -EINVAL; 308a7189483SWang Dongsheng 309a7189483SWang Dongsheng smp_call_function_single(cpu, do_store_pw20_state, &value, 1); 310a7189483SWang Dongsheng 311a7189483SWang Dongsheng return count; 312a7189483SWang Dongsheng } 313a7189483SWang Dongsheng 314a7189483SWang Dongsheng static ssize_t show_pw20_wait_time(struct device *dev, 315a7189483SWang Dongsheng struct device_attribute *attr, char *buf) 316a7189483SWang Dongsheng { 317a7189483SWang Dongsheng u32 value; 318a7189483SWang Dongsheng u64 tb_cycle = 1; 319a7189483SWang Dongsheng u64 time; 320a7189483SWang Dongsheng 321a7189483SWang Dongsheng unsigned int cpu = dev->id; 322a7189483SWang Dongsheng 323a7189483SWang Dongsheng if (!pw20_wt) { 324a7189483SWang Dongsheng smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1); 325a7189483SWang Dongsheng value = (value & PWRMGTCR0_PW20_ENT) >> 326a7189483SWang Dongsheng PWRMGTCR0_PW20_ENT_SHIFT; 327a7189483SWang Dongsheng 328a7189483SWang Dongsheng tb_cycle = (tb_cycle << (MAX_BIT - value + 1)); 329a7189483SWang Dongsheng /* convert ms to ns */ 330a7189483SWang Dongsheng if (tb_ticks_per_usec > 1000) { 331a7189483SWang Dongsheng time = div_u64(tb_cycle, tb_ticks_per_usec / 1000); 332a7189483SWang Dongsheng } else { 333a7189483SWang Dongsheng u32 rem_us; 334a7189483SWang Dongsheng 335a7189483SWang Dongsheng time = div_u64_rem(tb_cycle, tb_ticks_per_usec, 336a7189483SWang Dongsheng &rem_us); 337a7189483SWang Dongsheng time = time * 1000 + rem_us * 1000 / tb_ticks_per_usec; 338a7189483SWang Dongsheng } 339a7189483SWang Dongsheng } else { 340a7189483SWang Dongsheng time = pw20_wt; 341a7189483SWang Dongsheng } 342a7189483SWang Dongsheng 343a7189483SWang Dongsheng return sprintf(buf, "%llu\n", time > 0 ? time : 0); 344a7189483SWang Dongsheng } 345a7189483SWang Dongsheng 346a7189483SWang Dongsheng static void set_pw20_wait_entry_bit(void *val) 347a7189483SWang Dongsheng { 348a7189483SWang Dongsheng u32 *value = val; 349a7189483SWang Dongsheng u32 pw20_idle; 350a7189483SWang Dongsheng 351a7189483SWang Dongsheng pw20_idle = mfspr(SPRN_PWRMGTCR0); 352a7189483SWang Dongsheng 353a7189483SWang Dongsheng /* Set Automatic PW20 Core Idle Count */ 354a7189483SWang Dongsheng /* clear count */ 355a7189483SWang Dongsheng pw20_idle &= ~PWRMGTCR0_PW20_ENT; 356a7189483SWang Dongsheng 357a7189483SWang Dongsheng /* set count */ 358a7189483SWang Dongsheng pw20_idle |= ((MAX_BIT - *value) << PWRMGTCR0_PW20_ENT_SHIFT); 359a7189483SWang Dongsheng 360a7189483SWang Dongsheng mtspr(SPRN_PWRMGTCR0, pw20_idle); 361a7189483SWang Dongsheng } 362a7189483SWang Dongsheng 363a7189483SWang Dongsheng static ssize_t store_pw20_wait_time(struct device *dev, 364a7189483SWang Dongsheng struct device_attribute *attr, 365a7189483SWang Dongsheng const char *buf, size_t count) 366a7189483SWang Dongsheng { 367a7189483SWang Dongsheng u32 entry_bit; 368a7189483SWang Dongsheng u64 value; 369a7189483SWang Dongsheng 370a7189483SWang Dongsheng unsigned int cpu = dev->id; 371a7189483SWang Dongsheng 372a7189483SWang Dongsheng if (kstrtou64(buf, 0, &value)) 373a7189483SWang Dongsheng return -EINVAL; 374a7189483SWang Dongsheng 375a7189483SWang Dongsheng if (!value) 376a7189483SWang Dongsheng return -EINVAL; 377a7189483SWang Dongsheng 378a7189483SWang Dongsheng entry_bit = get_idle_ticks_bit(value); 379a7189483SWang Dongsheng if (entry_bit > MAX_BIT) 380a7189483SWang Dongsheng return -EINVAL; 381a7189483SWang Dongsheng 382a7189483SWang Dongsheng pw20_wt = value; 383a7189483SWang Dongsheng 384a7189483SWang Dongsheng smp_call_function_single(cpu, set_pw20_wait_entry_bit, 385a7189483SWang Dongsheng &entry_bit, 1); 386a7189483SWang Dongsheng 387a7189483SWang Dongsheng return count; 388a7189483SWang Dongsheng } 389a7189483SWang Dongsheng 390a7189483SWang Dongsheng static ssize_t show_altivec_idle(struct device *dev, 391a7189483SWang Dongsheng struct device_attribute *attr, char *buf) 392a7189483SWang Dongsheng { 393a7189483SWang Dongsheng u32 value; 394a7189483SWang Dongsheng unsigned int cpu = dev->id; 395a7189483SWang Dongsheng 396a7189483SWang Dongsheng smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1); 397a7189483SWang Dongsheng 398a7189483SWang Dongsheng value &= PWRMGTCR0_AV_IDLE_PD_EN; 399a7189483SWang Dongsheng 400a7189483SWang Dongsheng return sprintf(buf, "%u\n", value ? 1 : 0); 401a7189483SWang Dongsheng } 402a7189483SWang Dongsheng 403a7189483SWang Dongsheng static void do_store_altivec_idle(void *val) 404a7189483SWang Dongsheng { 405a7189483SWang Dongsheng u32 *value = val; 406a7189483SWang Dongsheng u32 altivec_idle; 407a7189483SWang Dongsheng 408a7189483SWang Dongsheng altivec_idle = mfspr(SPRN_PWRMGTCR0); 409a7189483SWang Dongsheng 410a7189483SWang Dongsheng if (*value) 411a7189483SWang Dongsheng altivec_idle |= PWRMGTCR0_AV_IDLE_PD_EN; 412a7189483SWang Dongsheng else 413a7189483SWang Dongsheng altivec_idle &= ~PWRMGTCR0_AV_IDLE_PD_EN; 414a7189483SWang Dongsheng 415a7189483SWang Dongsheng mtspr(SPRN_PWRMGTCR0, altivec_idle); 416a7189483SWang Dongsheng } 417a7189483SWang Dongsheng 418a7189483SWang Dongsheng static ssize_t store_altivec_idle(struct device *dev, 419a7189483SWang Dongsheng struct device_attribute *attr, 420a7189483SWang Dongsheng const char *buf, size_t count) 421a7189483SWang Dongsheng { 422a7189483SWang Dongsheng u32 value; 423a7189483SWang Dongsheng unsigned int cpu = dev->id; 424a7189483SWang Dongsheng 425a7189483SWang Dongsheng if (kstrtou32(buf, 0, &value)) 426a7189483SWang Dongsheng return -EINVAL; 427a7189483SWang Dongsheng 428a7189483SWang Dongsheng if (value > 1) 429a7189483SWang Dongsheng return -EINVAL; 430a7189483SWang Dongsheng 431a7189483SWang Dongsheng smp_call_function_single(cpu, do_store_altivec_idle, &value, 1); 432a7189483SWang Dongsheng 433a7189483SWang Dongsheng return count; 434a7189483SWang Dongsheng } 435a7189483SWang Dongsheng 436a7189483SWang Dongsheng static ssize_t show_altivec_idle_wait_time(struct device *dev, 437a7189483SWang Dongsheng struct device_attribute *attr, char *buf) 438a7189483SWang Dongsheng { 439a7189483SWang Dongsheng u32 value; 440a7189483SWang Dongsheng u64 tb_cycle = 1; 441a7189483SWang Dongsheng u64 time; 442a7189483SWang Dongsheng 443a7189483SWang Dongsheng unsigned int cpu = dev->id; 444a7189483SWang Dongsheng 445a7189483SWang Dongsheng if (!altivec_idle_wt) { 446a7189483SWang Dongsheng smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1); 447a7189483SWang Dongsheng value = (value & PWRMGTCR0_AV_IDLE_CNT) >> 448a7189483SWang Dongsheng PWRMGTCR0_AV_IDLE_CNT_SHIFT; 449a7189483SWang Dongsheng 450a7189483SWang Dongsheng tb_cycle = (tb_cycle << (MAX_BIT - value + 1)); 451a7189483SWang Dongsheng /* convert ms to ns */ 452a7189483SWang Dongsheng if (tb_ticks_per_usec > 1000) { 453a7189483SWang Dongsheng time = div_u64(tb_cycle, tb_ticks_per_usec / 1000); 454a7189483SWang Dongsheng } else { 455a7189483SWang Dongsheng u32 rem_us; 456a7189483SWang Dongsheng 457a7189483SWang Dongsheng time = div_u64_rem(tb_cycle, tb_ticks_per_usec, 458a7189483SWang Dongsheng &rem_us); 459a7189483SWang Dongsheng time = time * 1000 + rem_us * 1000 / tb_ticks_per_usec; 460a7189483SWang Dongsheng } 461a7189483SWang Dongsheng } else { 462a7189483SWang Dongsheng time = altivec_idle_wt; 463a7189483SWang Dongsheng } 464a7189483SWang Dongsheng 465a7189483SWang Dongsheng return sprintf(buf, "%llu\n", time > 0 ? time : 0); 466a7189483SWang Dongsheng } 467a7189483SWang Dongsheng 468a7189483SWang Dongsheng static void set_altivec_idle_wait_entry_bit(void *val) 469a7189483SWang Dongsheng { 470a7189483SWang Dongsheng u32 *value = val; 471a7189483SWang Dongsheng u32 altivec_idle; 472a7189483SWang Dongsheng 473a7189483SWang Dongsheng altivec_idle = mfspr(SPRN_PWRMGTCR0); 474a7189483SWang Dongsheng 475a7189483SWang Dongsheng /* Set Automatic AltiVec Idle Count */ 476a7189483SWang Dongsheng /* clear count */ 477a7189483SWang Dongsheng altivec_idle &= ~PWRMGTCR0_AV_IDLE_CNT; 478a7189483SWang Dongsheng 479a7189483SWang Dongsheng /* set count */ 480a7189483SWang Dongsheng altivec_idle |= ((MAX_BIT - *value) << PWRMGTCR0_AV_IDLE_CNT_SHIFT); 481a7189483SWang Dongsheng 482a7189483SWang Dongsheng mtspr(SPRN_PWRMGTCR0, altivec_idle); 483a7189483SWang Dongsheng } 484a7189483SWang Dongsheng 485a7189483SWang Dongsheng static ssize_t store_altivec_idle_wait_time(struct device *dev, 486a7189483SWang Dongsheng struct device_attribute *attr, 487a7189483SWang Dongsheng const char *buf, size_t count) 488a7189483SWang Dongsheng { 489a7189483SWang Dongsheng u32 entry_bit; 490a7189483SWang Dongsheng u64 value; 491a7189483SWang Dongsheng 492a7189483SWang Dongsheng unsigned int cpu = dev->id; 493a7189483SWang Dongsheng 494a7189483SWang Dongsheng if (kstrtou64(buf, 0, &value)) 495a7189483SWang Dongsheng return -EINVAL; 496a7189483SWang Dongsheng 497a7189483SWang Dongsheng if (!value) 498a7189483SWang Dongsheng return -EINVAL; 499a7189483SWang Dongsheng 500a7189483SWang Dongsheng entry_bit = get_idle_ticks_bit(value); 501a7189483SWang Dongsheng if (entry_bit > MAX_BIT) 502a7189483SWang Dongsheng return -EINVAL; 503a7189483SWang Dongsheng 504a7189483SWang Dongsheng altivec_idle_wt = value; 505a7189483SWang Dongsheng 506a7189483SWang Dongsheng smp_call_function_single(cpu, set_altivec_idle_wait_entry_bit, 507a7189483SWang Dongsheng &entry_bit, 1); 508a7189483SWang Dongsheng 509a7189483SWang Dongsheng return count; 510a7189483SWang Dongsheng } 511a7189483SWang Dongsheng 512a7189483SWang Dongsheng /* 513a7189483SWang Dongsheng * Enable/Disable interface: 514a7189483SWang Dongsheng * 0, disable. 1, enable. 515a7189483SWang Dongsheng */ 516a7189483SWang Dongsheng static DEVICE_ATTR(pw20_state, 0600, show_pw20_state, store_pw20_state); 517a7189483SWang Dongsheng static DEVICE_ATTR(altivec_idle, 0600, show_altivec_idle, store_altivec_idle); 518a7189483SWang Dongsheng 519a7189483SWang Dongsheng /* 520a7189483SWang Dongsheng * Set wait time interface:(Nanosecond) 521a7189483SWang Dongsheng * Example: Base on TBfreq is 41MHZ. 522a7189483SWang Dongsheng * 1~48(ns): TB[63] 523a7189483SWang Dongsheng * 49~97(ns): TB[62] 524a7189483SWang Dongsheng * 98~195(ns): TB[61] 525a7189483SWang Dongsheng * 196~390(ns): TB[60] 526a7189483SWang Dongsheng * 391~780(ns): TB[59] 527a7189483SWang Dongsheng * 781~1560(ns): TB[58] 528a7189483SWang Dongsheng * ... 529a7189483SWang Dongsheng */ 530a7189483SWang Dongsheng static DEVICE_ATTR(pw20_wait_time, 0600, 531a7189483SWang Dongsheng show_pw20_wait_time, 532a7189483SWang Dongsheng store_pw20_wait_time); 533a7189483SWang Dongsheng static DEVICE_ATTR(altivec_idle_wait_time, 0600, 534a7189483SWang Dongsheng show_altivec_idle_wait_time, 535a7189483SWang Dongsheng store_altivec_idle_wait_time); 536a7189483SWang Dongsheng #endif 537a7189483SWang Dongsheng 538d3d2176aSDavid Gibson /* 539d3d2176aSDavid Gibson * Enabling PMCs will slow partition context switch times so we only do 540d3d2176aSDavid Gibson * it the first time we write to the PMCs. 541d3d2176aSDavid Gibson */ 542d3d2176aSDavid Gibson 543d3d2176aSDavid Gibson static DEFINE_PER_CPU(char, pmcs_enabled); 544d3d2176aSDavid Gibson 545b950bdd0SBenjamin Herrenschmidt void ppc_enable_pmcs(void) 546d3d2176aSDavid Gibson { 547a6dbf93aSPaul Mackerras ppc_set_pmu_inuse(1); 548a6dbf93aSPaul Mackerras 549d3d2176aSDavid Gibson /* Only need to enable them once */ 55069111bacSChristoph Lameter if (__this_cpu_read(pmcs_enabled)) 551d3d2176aSDavid Gibson return; 552d3d2176aSDavid Gibson 55369111bacSChristoph Lameter __this_cpu_write(pmcs_enabled, 1); 554d3d2176aSDavid Gibson 555d3d2176aSDavid Gibson if (ppc_md.enable_pmcs) 556d3d2176aSDavid Gibson ppc_md.enable_pmcs(); 557d3d2176aSDavid Gibson } 558b950bdd0SBenjamin Herrenschmidt EXPORT_SYMBOL(ppc_enable_pmcs); 559d3d2176aSDavid Gibson 56039a360efSSam bobroff 5616529c13dSOlof Johansson 5626529c13dSOlof Johansson /* Let's define all possible registers, we'll only hook up the ones 5636529c13dSOlof Johansson * that are implemented on the current processor 5646529c13dSOlof Johansson */ 5656529c13dSOlof Johansson 56622697da3SKajol Jain #ifdef CONFIG_PMU_SYSFS 567fcdb524dSMadhavan Srinivasan #if defined(CONFIG_PPC64) || defined(CONFIG_PPC_BOOK3S_32) 568b950bdd0SBenjamin Herrenschmidt #define HAS_PPC_PMC_CLASSIC 1 569b950bdd0SBenjamin Herrenschmidt #define HAS_PPC_PMC_IBM 1 570b950bdd0SBenjamin Herrenschmidt #endif 571b950bdd0SBenjamin Herrenschmidt 572b950bdd0SBenjamin Herrenschmidt #ifdef CONFIG_PPC64 573fcdb524dSMadhavan Srinivasan #define HAS_PPC_PMC_PA6T 1 574fcdb524dSMadhavan Srinivasan #define HAS_PPC_PMC56 1 575fcdb524dSMadhavan Srinivasan #endif 576b950bdd0SBenjamin Herrenschmidt 577fcdb524dSMadhavan Srinivasan #ifdef CONFIG_PPC_BOOK3S_32 578fcdb524dSMadhavan Srinivasan #define HAS_PPC_PMC_G4 1 579fcdb524dSMadhavan Srinivasan #endif 58022697da3SKajol Jain #endif /* CONFIG_PMU_SYSFS */ 581fcdb524dSMadhavan Srinivasan 582fcdb524dSMadhavan Srinivasan #if defined(CONFIG_PPC64) && defined(CONFIG_DEBUG_MISC) 583fcdb524dSMadhavan Srinivasan #define HAS_PPC_PA6T 584fcdb524dSMadhavan Srinivasan #endif 585fcdb524dSMadhavan Srinivasan /* 586fcdb524dSMadhavan Srinivasan * SPRs which are not related to PMU. 587fcdb524dSMadhavan Srinivasan */ 588fcdb524dSMadhavan Srinivasan #ifdef CONFIG_PPC64 589fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(purr, SPRN_PURR); 590fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(spurr, SPRN_SPURR); 591fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(pir, SPRN_PIR); 592b6d34eb4SAnton Blanchard SYSFS_SPRSETUP(tscr, SPRN_TSCR); 593d3d2176aSDavid Gibson 594d1211af3SMadhavan Srinivasan /* 595d1211af3SMadhavan Srinivasan Lets only enable read for phyp resources and 596d1211af3SMadhavan Srinivasan enable write when needed with a separate function. 597d1211af3SMadhavan Srinivasan Lets be conservative and default to pseries. 598d1211af3SMadhavan Srinivasan */ 599d5dae721SBenjamin Herrenschmidt static DEVICE_ATTR(spurr, 0400, show_spurr, NULL); 600d1211af3SMadhavan Srinivasan static DEVICE_ATTR(purr, 0400, show_purr, store_purr); 6017affca35SLinus Torvalds static DEVICE_ATTR(pir, 0400, show_pir, NULL); 602b6d34eb4SAnton Blanchard static DEVICE_ATTR(tscr, 0600, show_tscr, store_tscr); 603b950bdd0SBenjamin Herrenschmidt #endif /* CONFIG_PPC64 */ 604b950bdd0SBenjamin Herrenschmidt 605fcdb524dSMadhavan Srinivasan #ifdef HAS_PPC_PMC_CLASSIC 606fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(mmcr0, SPRN_MMCR0); 607fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(mmcr1, SPRN_MMCR1); 608fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(pmc1, SPRN_PMC1); 609fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(pmc2, SPRN_PMC2); 610fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(pmc3, SPRN_PMC3); 611fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(pmc4, SPRN_PMC4); 612fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(pmc5, SPRN_PMC5); 613fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(pmc6, SPRN_PMC6); 614fcdb524dSMadhavan Srinivasan #endif 615fcdb524dSMadhavan Srinivasan 616fcdb524dSMadhavan Srinivasan #ifdef HAS_PPC_PMC_G4 617fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(mmcr2, SPRN_MMCR2); 618fcdb524dSMadhavan Srinivasan #endif 619fcdb524dSMadhavan Srinivasan 620fcdb524dSMadhavan Srinivasan #ifdef HAS_PPC_PMC56 621fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(pmc7, SPRN_PMC7); 622fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(pmc8, SPRN_PMC8); 623fcdb524dSMadhavan Srinivasan 624fcdb524dSMadhavan Srinivasan SYSFS_PMCSETUP(mmcra, SPRN_MMCRA); 625fcdb524dSMadhavan Srinivasan 626fcdb524dSMadhavan Srinivasan static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra); 627fcdb524dSMadhavan Srinivasan #endif /* HAS_PPC_PMC56 */ 628fcdb524dSMadhavan Srinivasan 629fcdb524dSMadhavan Srinivasan 630fcdb524dSMadhavan Srinivasan 631fcdb524dSMadhavan Srinivasan 632b950bdd0SBenjamin Herrenschmidt #ifdef HAS_PPC_PMC_PA6T 63325fc530eSOlof Johansson SYSFS_PMCSETUP(pa6t_pmc0, SPRN_PA6T_PMC0); 63425fc530eSOlof Johansson SYSFS_PMCSETUP(pa6t_pmc1, SPRN_PA6T_PMC1); 63525fc530eSOlof Johansson SYSFS_PMCSETUP(pa6t_pmc2, SPRN_PA6T_PMC2); 63625fc530eSOlof Johansson SYSFS_PMCSETUP(pa6t_pmc3, SPRN_PA6T_PMC3); 63725fc530eSOlof Johansson SYSFS_PMCSETUP(pa6t_pmc4, SPRN_PA6T_PMC4); 63825fc530eSOlof Johansson SYSFS_PMCSETUP(pa6t_pmc5, SPRN_PA6T_PMC5); 639fcdb524dSMadhavan Srinivasan #endif 640fcdb524dSMadhavan Srinivasan 641fcdb524dSMadhavan Srinivasan #ifdef HAS_PPC_PA6T 642fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(hid0, SPRN_HID0); 643fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(hid1, SPRN_HID1); 644fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(hid4, SPRN_HID4); 645fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(hid5, SPRN_HID5); 646fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima0, SPRN_PA6T_IMA0); 647fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima1, SPRN_PA6T_IMA1); 648fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima2, SPRN_PA6T_IMA2); 649fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima3, SPRN_PA6T_IMA3); 650fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima4, SPRN_PA6T_IMA4); 651fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima5, SPRN_PA6T_IMA5); 652fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima6, SPRN_PA6T_IMA6); 653fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima7, SPRN_PA6T_IMA7); 654fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima8, SPRN_PA6T_IMA8); 655fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ima9, SPRN_PA6T_IMA9); 656fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(imaat, SPRN_PA6T_IMAAT); 657fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(btcr, SPRN_PA6T_BTCR); 658fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(pccr, SPRN_PA6T_PCCR); 659fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(rpccr, SPRN_PA6T_RPCCR); 660fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(der, SPRN_PA6T_DER); 661fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(mer, SPRN_PA6T_MER); 662fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ber, SPRN_PA6T_BER); 663fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(ier, SPRN_PA6T_IER); 664fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(sier, SPRN_PA6T_SIER); 665fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(siar, SPRN_PA6T_SIAR); 666fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(tsr0, SPRN_PA6T_TSR0); 667fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(tsr1, SPRN_PA6T_TSR1); 668fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(tsr2, SPRN_PA6T_TSR2); 669fd7e4296SMadhavan Srinivasan SYSFS_SPRSETUP(tsr3, SPRN_PA6T_TSR3); 670fcdb524dSMadhavan Srinivasan #endif /* HAS_PPC_PA6T */ 6716529c13dSOlof Johansson 672b950bdd0SBenjamin Herrenschmidt #ifdef HAS_PPC_PMC_IBM 6738a25a2fdSKay Sievers static struct device_attribute ibm_common_attrs[] = { 6748a25a2fdSKay Sievers __ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0), 6758a25a2fdSKay Sievers __ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1), 6766529c13dSOlof Johansson }; 677fcdb524dSMadhavan Srinivasan #endif /* HAS_PPC_PMC_IBM */ 6786529c13dSOlof Johansson 679b950bdd0SBenjamin Herrenschmidt #ifdef HAS_PPC_PMC_G4 6808a25a2fdSKay Sievers static struct device_attribute g4_common_attrs[] = { 6818a25a2fdSKay Sievers __ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0), 6828a25a2fdSKay Sievers __ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1), 6838a25a2fdSKay Sievers __ATTR(mmcr2, 0600, show_mmcr2, store_mmcr2), 684b950bdd0SBenjamin Herrenschmidt }; 685b950bdd0SBenjamin Herrenschmidt #endif /* HAS_PPC_PMC_G4 */ 686b950bdd0SBenjamin Herrenschmidt 687fcdb524dSMadhavan Srinivasan #ifdef HAS_PPC_PMC_CLASSIC 6888a25a2fdSKay Sievers static struct device_attribute classic_pmc_attrs[] = { 6898a25a2fdSKay Sievers __ATTR(pmc1, 0600, show_pmc1, store_pmc1), 6908a25a2fdSKay Sievers __ATTR(pmc2, 0600, show_pmc2, store_pmc2), 6918a25a2fdSKay Sievers __ATTR(pmc3, 0600, show_pmc3, store_pmc3), 6928a25a2fdSKay Sievers __ATTR(pmc4, 0600, show_pmc4, store_pmc4), 6938a25a2fdSKay Sievers __ATTR(pmc5, 0600, show_pmc5, store_pmc5), 6948a25a2fdSKay Sievers __ATTR(pmc6, 0600, show_pmc6, store_pmc6), 695fcdb524dSMadhavan Srinivasan #ifdef HAS_PPC_PMC56 6968a25a2fdSKay Sievers __ATTR(pmc7, 0600, show_pmc7, store_pmc7), 6978a25a2fdSKay Sievers __ATTR(pmc8, 0600, show_pmc8, store_pmc8), 698b950bdd0SBenjamin Herrenschmidt #endif 6996529c13dSOlof Johansson }; 700fcdb524dSMadhavan Srinivasan #endif 7016529c13dSOlof Johansson 702fcdb524dSMadhavan Srinivasan #if defined(HAS_PPC_PMC_PA6T) || defined(HAS_PPC_PA6T) 7038a25a2fdSKay Sievers static struct device_attribute pa6t_attrs[] = { 704fcdb524dSMadhavan Srinivasan #ifdef HAS_PPC_PMC_PA6T 7058a25a2fdSKay Sievers __ATTR(mmcr0, 0600, show_mmcr0, store_mmcr0), 7068a25a2fdSKay Sievers __ATTR(mmcr1, 0600, show_mmcr1, store_mmcr1), 7078a25a2fdSKay Sievers __ATTR(pmc0, 0600, show_pa6t_pmc0, store_pa6t_pmc0), 7088a25a2fdSKay Sievers __ATTR(pmc1, 0600, show_pa6t_pmc1, store_pa6t_pmc1), 7098a25a2fdSKay Sievers __ATTR(pmc2, 0600, show_pa6t_pmc2, store_pa6t_pmc2), 7108a25a2fdSKay Sievers __ATTR(pmc3, 0600, show_pa6t_pmc3, store_pa6t_pmc3), 7118a25a2fdSKay Sievers __ATTR(pmc4, 0600, show_pa6t_pmc4, store_pa6t_pmc4), 7128a25a2fdSKay Sievers __ATTR(pmc5, 0600, show_pa6t_pmc5, store_pa6t_pmc5), 713fcdb524dSMadhavan Srinivasan #endif 714fcdb524dSMadhavan Srinivasan #ifdef HAS_PPC_PA6T 7158a25a2fdSKay Sievers __ATTR(hid0, 0600, show_hid0, store_hid0), 7168a25a2fdSKay Sievers __ATTR(hid1, 0600, show_hid1, store_hid1), 7178a25a2fdSKay Sievers __ATTR(hid4, 0600, show_hid4, store_hid4), 7188a25a2fdSKay Sievers __ATTR(hid5, 0600, show_hid5, store_hid5), 7198a25a2fdSKay Sievers __ATTR(ima0, 0600, show_ima0, store_ima0), 7208a25a2fdSKay Sievers __ATTR(ima1, 0600, show_ima1, store_ima1), 7218a25a2fdSKay Sievers __ATTR(ima2, 0600, show_ima2, store_ima2), 7228a25a2fdSKay Sievers __ATTR(ima3, 0600, show_ima3, store_ima3), 7238a25a2fdSKay Sievers __ATTR(ima4, 0600, show_ima4, store_ima4), 7248a25a2fdSKay Sievers __ATTR(ima5, 0600, show_ima5, store_ima5), 7258a25a2fdSKay Sievers __ATTR(ima6, 0600, show_ima6, store_ima6), 7268a25a2fdSKay Sievers __ATTR(ima7, 0600, show_ima7, store_ima7), 7278a25a2fdSKay Sievers __ATTR(ima8, 0600, show_ima8, store_ima8), 7288a25a2fdSKay Sievers __ATTR(ima9, 0600, show_ima9, store_ima9), 7298a25a2fdSKay Sievers __ATTR(imaat, 0600, show_imaat, store_imaat), 7308a25a2fdSKay Sievers __ATTR(btcr, 0600, show_btcr, store_btcr), 7318a25a2fdSKay Sievers __ATTR(pccr, 0600, show_pccr, store_pccr), 7328a25a2fdSKay Sievers __ATTR(rpccr, 0600, show_rpccr, store_rpccr), 7338a25a2fdSKay Sievers __ATTR(der, 0600, show_der, store_der), 7348a25a2fdSKay Sievers __ATTR(mer, 0600, show_mer, store_mer), 7358a25a2fdSKay Sievers __ATTR(ber, 0600, show_ber, store_ber), 7368a25a2fdSKay Sievers __ATTR(ier, 0600, show_ier, store_ier), 7378a25a2fdSKay Sievers __ATTR(sier, 0600, show_sier, store_sier), 7388a25a2fdSKay Sievers __ATTR(siar, 0600, show_siar, store_siar), 7398a25a2fdSKay Sievers __ATTR(tsr0, 0600, show_tsr0, store_tsr0), 7408a25a2fdSKay Sievers __ATTR(tsr1, 0600, show_tsr1, store_tsr1), 7418a25a2fdSKay Sievers __ATTR(tsr2, 0600, show_tsr2, store_tsr2), 7428a25a2fdSKay Sievers __ATTR(tsr3, 0600, show_tsr3, store_tsr3), 743fcdb524dSMadhavan Srinivasan #endif /* HAS_PPC_PA6T */ 7446529c13dSOlof Johansson }; 745fcdb524dSMadhavan Srinivasan #endif 7466529c13dSOlof Johansson 747734560acSRyan Grimm #ifdef CONFIG_PPC_SVM 748734560acSRyan Grimm static ssize_t show_svm(struct device *dev, struct device_attribute *attr, char *buf) 749734560acSRyan Grimm { 750734560acSRyan Grimm return sprintf(buf, "%u\n", is_secure_guest()); 751734560acSRyan Grimm } 752734560acSRyan Grimm static DEVICE_ATTR(svm, 0444, show_svm, NULL); 753734560acSRyan Grimm 754734560acSRyan Grimm static void create_svm_file(void) 755734560acSRyan Grimm { 756734560acSRyan Grimm device_create_file(cpu_subsys.dev_root, &dev_attr_svm); 757734560acSRyan Grimm } 758734560acSRyan Grimm #else 759734560acSRyan Grimm static void create_svm_file(void) 760734560acSRyan Grimm { 761734560acSRyan Grimm } 762734560acSRyan Grimm #endif /* CONFIG_PPC_SVM */ 763734560acSRyan Grimm 764*6909f179SGautham R. Shenoy #ifdef CONFIG_PPC_PSERIES 765*6909f179SGautham R. Shenoy static void read_idle_purr(void *val) 766*6909f179SGautham R. Shenoy { 767*6909f179SGautham R. Shenoy u64 *ret = val; 768*6909f179SGautham R. Shenoy 769*6909f179SGautham R. Shenoy *ret = read_this_idle_purr(); 770*6909f179SGautham R. Shenoy } 771*6909f179SGautham R. Shenoy 772*6909f179SGautham R. Shenoy static ssize_t idle_purr_show(struct device *dev, 773*6909f179SGautham R. Shenoy struct device_attribute *attr, char *buf) 774*6909f179SGautham R. Shenoy { 775*6909f179SGautham R. Shenoy struct cpu *cpu = container_of(dev, struct cpu, dev); 776*6909f179SGautham R. Shenoy u64 val; 777*6909f179SGautham R. Shenoy 778*6909f179SGautham R. Shenoy smp_call_function_single(cpu->dev.id, read_idle_purr, &val, 1); 779*6909f179SGautham R. Shenoy return sprintf(buf, "%llx\n", val); 780*6909f179SGautham R. Shenoy } 781*6909f179SGautham R. Shenoy static DEVICE_ATTR(idle_purr, 0400, idle_purr_show, NULL); 782*6909f179SGautham R. Shenoy 783*6909f179SGautham R. Shenoy static void create_idle_purr_file(struct device *s) 784*6909f179SGautham R. Shenoy { 785*6909f179SGautham R. Shenoy if (firmware_has_feature(FW_FEATURE_LPAR)) 786*6909f179SGautham R. Shenoy device_create_file(s, &dev_attr_idle_purr); 787*6909f179SGautham R. Shenoy } 788*6909f179SGautham R. Shenoy 789*6909f179SGautham R. Shenoy static void remove_idle_purr_file(struct device *s) 790*6909f179SGautham R. Shenoy { 791*6909f179SGautham R. Shenoy if (firmware_has_feature(FW_FEATURE_LPAR)) 792*6909f179SGautham R. Shenoy device_remove_file(s, &dev_attr_idle_purr); 793*6909f179SGautham R. Shenoy } 794*6909f179SGautham R. Shenoy 795*6909f179SGautham R. Shenoy static void read_idle_spurr(void *val) 796*6909f179SGautham R. Shenoy { 797*6909f179SGautham R. Shenoy u64 *ret = val; 798*6909f179SGautham R. Shenoy 799*6909f179SGautham R. Shenoy *ret = read_this_idle_spurr(); 800*6909f179SGautham R. Shenoy } 801*6909f179SGautham R. Shenoy 802*6909f179SGautham R. Shenoy static ssize_t idle_spurr_show(struct device *dev, 803*6909f179SGautham R. Shenoy struct device_attribute *attr, char *buf) 804*6909f179SGautham R. Shenoy { 805*6909f179SGautham R. Shenoy struct cpu *cpu = container_of(dev, struct cpu, dev); 806*6909f179SGautham R. Shenoy u64 val; 807*6909f179SGautham R. Shenoy 808*6909f179SGautham R. Shenoy smp_call_function_single(cpu->dev.id, read_idle_spurr, &val, 1); 809*6909f179SGautham R. Shenoy return sprintf(buf, "%llx\n", val); 810*6909f179SGautham R. Shenoy } 811*6909f179SGautham R. Shenoy static DEVICE_ATTR(idle_spurr, 0400, idle_spurr_show, NULL); 812*6909f179SGautham R. Shenoy 813*6909f179SGautham R. Shenoy static void create_idle_spurr_file(struct device *s) 814*6909f179SGautham R. Shenoy { 815*6909f179SGautham R. Shenoy if (firmware_has_feature(FW_FEATURE_LPAR)) 816*6909f179SGautham R. Shenoy device_create_file(s, &dev_attr_idle_spurr); 817*6909f179SGautham R. Shenoy } 818*6909f179SGautham R. Shenoy 819*6909f179SGautham R. Shenoy static void remove_idle_spurr_file(struct device *s) 820*6909f179SGautham R. Shenoy { 821*6909f179SGautham R. Shenoy if (firmware_has_feature(FW_FEATURE_LPAR)) 822*6909f179SGautham R. Shenoy device_remove_file(s, &dev_attr_idle_spurr); 823*6909f179SGautham R. Shenoy } 824*6909f179SGautham R. Shenoy 825*6909f179SGautham R. Shenoy #else /* CONFIG_PPC_PSERIES */ 826*6909f179SGautham R. Shenoy #define create_idle_purr_file(s) 827*6909f179SGautham R. Shenoy #define remove_idle_purr_file(s) 828*6909f179SGautham R. Shenoy #define create_idle_spurr_file(s) 829*6909f179SGautham R. Shenoy #define remove_idle_spurr_file(s) 830*6909f179SGautham R. Shenoy #endif /* CONFIG_PPC_PSERIES */ 831*6909f179SGautham R. Shenoy 832977ab257SSebastian Andrzej Siewior static int register_cpu_online(unsigned int cpu) 833d3d2176aSDavid Gibson { 834d3d2176aSDavid Gibson struct cpu *c = &per_cpu(cpu_devices, cpu); 8358a25a2fdSKay Sievers struct device *s = &c->dev; 8368a25a2fdSKay Sievers struct device_attribute *attrs, *pmc_attrs; 8376529c13dSOlof Johansson int i, nattrs; 838d3d2176aSDavid Gibson 839e76ca277STyrel Datwyler /* For cpus present at boot a reference was already grabbed in register_cpu() */ 840e76ca277STyrel Datwyler if (!s->of_node) 841e76ca277STyrel Datwyler s->of_node = of_get_cpu_node(cpu, NULL); 842e76ca277STyrel Datwyler 843b950bdd0SBenjamin Herrenschmidt #ifdef CONFIG_PPC64 844f5339277SStephen Rothwell if (cpu_has_feature(CPU_FTR_SMT)) 8458a25a2fdSKay Sievers device_create_file(s, &dev_attr_smt_snooze_delay); 846b950bdd0SBenjamin Herrenschmidt #endif 847d3d2176aSDavid Gibson 848d3d2176aSDavid Gibson /* PMC stuff */ 8496529c13dSOlof Johansson switch (cur_cpu_spec->pmc_type) { 850b950bdd0SBenjamin Herrenschmidt #ifdef HAS_PPC_PMC_IBM 8516529c13dSOlof Johansson case PPC_PMC_IBM: 8526529c13dSOlof Johansson attrs = ibm_common_attrs; 8538a25a2fdSKay Sievers nattrs = sizeof(ibm_common_attrs) / sizeof(struct device_attribute); 854b950bdd0SBenjamin Herrenschmidt pmc_attrs = classic_pmc_attrs; 8556529c13dSOlof Johansson break; 856b950bdd0SBenjamin Herrenschmidt #endif /* HAS_PPC_PMC_IBM */ 857b950bdd0SBenjamin Herrenschmidt #ifdef HAS_PPC_PMC_G4 858b950bdd0SBenjamin Herrenschmidt case PPC_PMC_G4: 859b950bdd0SBenjamin Herrenschmidt attrs = g4_common_attrs; 8608a25a2fdSKay Sievers nattrs = sizeof(g4_common_attrs) / sizeof(struct device_attribute); 861b950bdd0SBenjamin Herrenschmidt pmc_attrs = classic_pmc_attrs; 862b950bdd0SBenjamin Herrenschmidt break; 863b950bdd0SBenjamin Herrenschmidt #endif /* HAS_PPC_PMC_G4 */ 864fcdb524dSMadhavan Srinivasan #if defined(HAS_PPC_PMC_PA6T) || defined(HAS_PPC_PA6T) 8656529c13dSOlof Johansson case PPC_PMC_PA6T: 8666529c13dSOlof Johansson /* PA Semi starts counting at PMC0 */ 8676529c13dSOlof Johansson attrs = pa6t_attrs; 8688a25a2fdSKay Sievers nattrs = sizeof(pa6t_attrs) / sizeof(struct device_attribute); 8696529c13dSOlof Johansson pmc_attrs = NULL; 8706529c13dSOlof Johansson break; 871fcdb524dSMadhavan Srinivasan #endif 8726529c13dSOlof Johansson default: 8736529c13dSOlof Johansson attrs = NULL; 8746529c13dSOlof Johansson nattrs = 0; 8756529c13dSOlof Johansson pmc_attrs = NULL; 8766529c13dSOlof Johansson } 877d3d2176aSDavid Gibson 8786529c13dSOlof Johansson for (i = 0; i < nattrs; i++) 8798a25a2fdSKay Sievers device_create_file(s, &attrs[i]); 8806529c13dSOlof Johansson 8816529c13dSOlof Johansson if (pmc_attrs) 8826529c13dSOlof Johansson for (i = 0; i < cur_cpu_spec->num_pmcs; i++) 8838a25a2fdSKay Sievers device_create_file(s, &pmc_attrs[i]); 884d3d2176aSDavid Gibson 885b950bdd0SBenjamin Herrenschmidt #ifdef CONFIG_PPC64 88622697da3SKajol Jain #ifdef CONFIG_PMU_SYSFS 887d3d2176aSDavid Gibson if (cpu_has_feature(CPU_FTR_MMCRA)) 8888a25a2fdSKay Sievers device_create_file(s, &dev_attr_mmcra); 88922697da3SKajol Jain #endif /* CONFIG_PMU_SYSFS */ 890d3d2176aSDavid Gibson 891d1211af3SMadhavan Srinivasan if (cpu_has_feature(CPU_FTR_PURR)) { 892d1211af3SMadhavan Srinivasan if (!firmware_has_feature(FW_FEATURE_LPAR)) 893d1211af3SMadhavan Srinivasan add_write_permission_dev_attr(&dev_attr_purr); 8948a25a2fdSKay Sievers device_create_file(s, &dev_attr_purr); 895*6909f179SGautham R. Shenoy create_idle_purr_file(s); 896d1211af3SMadhavan Srinivasan } 8974c198557SAnton Blanchard 898*6909f179SGautham R. Shenoy if (cpu_has_feature(CPU_FTR_SPURR)) { 8998a25a2fdSKay Sievers device_create_file(s, &dev_attr_spurr); 900*6909f179SGautham R. Shenoy create_idle_spurr_file(s); 901*6909f179SGautham R. Shenoy } 902f050982aSAnton Blanchard 9034c198557SAnton Blanchard if (cpu_has_feature(CPU_FTR_DSCR)) 9048a25a2fdSKay Sievers device_create_file(s, &dev_attr_dscr); 905595fe914SAnanth N Mavinakayanahalli 906595fe914SAnanth N Mavinakayanahalli if (cpu_has_feature(CPU_FTR_PPCAS_ARCH_V2)) 9077affca35SLinus Torvalds device_create_file(s, &dev_attr_pir); 908b6d34eb4SAnton Blanchard 909c134f0d5SCyril Bur if (cpu_has_feature(CPU_FTR_ARCH_206) && 910c134f0d5SCyril Bur !firmware_has_feature(FW_FEATURE_LPAR)) 911b6d34eb4SAnton Blanchard device_create_file(s, &dev_attr_tscr); 912b950bdd0SBenjamin Herrenschmidt #endif /* CONFIG_PPC64 */ 913124c27d3SNathan Lynch 914a7189483SWang Dongsheng #ifdef CONFIG_PPC_FSL_BOOK3E 915a7189483SWang Dongsheng if (PVR_VER(cur_cpu_spec->pvr_value) == PVR_VER_E6500) { 916a7189483SWang Dongsheng device_create_file(s, &dev_attr_pw20_state); 917a7189483SWang Dongsheng device_create_file(s, &dev_attr_pw20_wait_time); 918a7189483SWang Dongsheng 919a7189483SWang Dongsheng device_create_file(s, &dev_attr_altivec_idle); 920a7189483SWang Dongsheng device_create_file(s, &dev_attr_altivec_idle_wait_time); 921a7189483SWang Dongsheng } 922a7189483SWang Dongsheng #endif 92393197a36SNathan Lynch cacheinfo_cpu_online(cpu); 924977ab257SSebastian Andrzej Siewior return 0; 925d3d2176aSDavid Gibson } 926d3d2176aSDavid Gibson 9273f2290e1SMichael Ellerman #ifdef CONFIG_HOTPLUG_CPU 928977ab257SSebastian Andrzej Siewior static int unregister_cpu_online(unsigned int cpu) 929d3d2176aSDavid Gibson { 930d3d2176aSDavid Gibson struct cpu *c = &per_cpu(cpu_devices, cpu); 9318a25a2fdSKay Sievers struct device *s = &c->dev; 9328a25a2fdSKay Sievers struct device_attribute *attrs, *pmc_attrs; 9336529c13dSOlof Johansson int i, nattrs; 934d3d2176aSDavid Gibson 93572486f1fSSiddha, Suresh B BUG_ON(!c->hotpluggable); 936d3d2176aSDavid Gibson 937a1e0eb10SMilton Miller #ifdef CONFIG_PPC64 938f5339277SStephen Rothwell if (cpu_has_feature(CPU_FTR_SMT)) 9398a25a2fdSKay Sievers device_remove_file(s, &dev_attr_smt_snooze_delay); 940a1e0eb10SMilton Miller #endif 941d3d2176aSDavid Gibson 942d3d2176aSDavid Gibson /* PMC stuff */ 9436529c13dSOlof Johansson switch (cur_cpu_spec->pmc_type) { 944b950bdd0SBenjamin Herrenschmidt #ifdef HAS_PPC_PMC_IBM 9456529c13dSOlof Johansson case PPC_PMC_IBM: 9466529c13dSOlof Johansson attrs = ibm_common_attrs; 9478a25a2fdSKay Sievers nattrs = sizeof(ibm_common_attrs) / sizeof(struct device_attribute); 948b950bdd0SBenjamin Herrenschmidt pmc_attrs = classic_pmc_attrs; 9496529c13dSOlof Johansson break; 950b950bdd0SBenjamin Herrenschmidt #endif /* HAS_PPC_PMC_IBM */ 951b950bdd0SBenjamin Herrenschmidt #ifdef HAS_PPC_PMC_G4 952b950bdd0SBenjamin Herrenschmidt case PPC_PMC_G4: 953b950bdd0SBenjamin Herrenschmidt attrs = g4_common_attrs; 9548a25a2fdSKay Sievers nattrs = sizeof(g4_common_attrs) / sizeof(struct device_attribute); 955b950bdd0SBenjamin Herrenschmidt pmc_attrs = classic_pmc_attrs; 956b950bdd0SBenjamin Herrenschmidt break; 957b950bdd0SBenjamin Herrenschmidt #endif /* HAS_PPC_PMC_G4 */ 958fcdb524dSMadhavan Srinivasan #if defined(HAS_PPC_PMC_PA6T) || defined(HAS_PPC_PA6T) 9596529c13dSOlof Johansson case PPC_PMC_PA6T: 9606529c13dSOlof Johansson /* PA Semi starts counting at PMC0 */ 9616529c13dSOlof Johansson attrs = pa6t_attrs; 9628a25a2fdSKay Sievers nattrs = sizeof(pa6t_attrs) / sizeof(struct device_attribute); 9636529c13dSOlof Johansson pmc_attrs = NULL; 9646529c13dSOlof Johansson break; 965fcdb524dSMadhavan Srinivasan #endif 9666529c13dSOlof Johansson default: 9676529c13dSOlof Johansson attrs = NULL; 9686529c13dSOlof Johansson nattrs = 0; 9696529c13dSOlof Johansson pmc_attrs = NULL; 9706529c13dSOlof Johansson } 971d3d2176aSDavid Gibson 9726529c13dSOlof Johansson for (i = 0; i < nattrs; i++) 9738a25a2fdSKay Sievers device_remove_file(s, &attrs[i]); 9746529c13dSOlof Johansson 9756529c13dSOlof Johansson if (pmc_attrs) 9766529c13dSOlof Johansson for (i = 0; i < cur_cpu_spec->num_pmcs; i++) 9778a25a2fdSKay Sievers device_remove_file(s, &pmc_attrs[i]); 978d3d2176aSDavid Gibson 979b950bdd0SBenjamin Herrenschmidt #ifdef CONFIG_PPC64 98022697da3SKajol Jain #ifdef CONFIG_PMU_SYSFS 981d3d2176aSDavid Gibson if (cpu_has_feature(CPU_FTR_MMCRA)) 9828a25a2fdSKay Sievers device_remove_file(s, &dev_attr_mmcra); 98322697da3SKajol Jain #endif /* CONFIG_PMU_SYSFS */ 984d3d2176aSDavid Gibson 985*6909f179SGautham R. Shenoy if (cpu_has_feature(CPU_FTR_PURR)) { 9868a25a2fdSKay Sievers device_remove_file(s, &dev_attr_purr); 987*6909f179SGautham R. Shenoy remove_idle_purr_file(s); 988*6909f179SGautham R. Shenoy } 9894c198557SAnton Blanchard 990*6909f179SGautham R. Shenoy if (cpu_has_feature(CPU_FTR_SPURR)) { 9918a25a2fdSKay Sievers device_remove_file(s, &dev_attr_spurr); 992*6909f179SGautham R. Shenoy remove_idle_spurr_file(s); 993*6909f179SGautham 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 1006a7189483SWang Dongsheng #ifdef CONFIG_PPC_FSL_BOOK3E 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 1113d3d2176aSDavid Gibson static void register_nodes(void) 1114d3d2176aSDavid Gibson { 1115d3d2176aSDavid Gibson int i; 1116d3d2176aSDavid Gibson 11170fc44159SYasunori Goto for (i = 0; i < MAX_NUMNODES; i++) 11180fc44159SYasunori Goto register_one_node(i); 1119d3d2176aSDavid Gibson } 1120953039c8SJeremy Kerr 11218a25a2fdSKay Sievers int sysfs_add_device_to_node(struct device *dev, int nid) 1122953039c8SJeremy Kerr { 11238732794bSWen Congyang struct node *node = node_devices[nid]; 112410fbcf4cSKay Sievers return sysfs_create_link(&node->dev.kobj, &dev->kobj, 1125953039c8SJeremy Kerr kobject_name(&dev->kobj)); 1126953039c8SJeremy Kerr } 112712654f77SJohannes Berg EXPORT_SYMBOL_GPL(sysfs_add_device_to_node); 1128953039c8SJeremy Kerr 11298a25a2fdSKay Sievers void sysfs_remove_device_from_node(struct device *dev, int nid) 1130953039c8SJeremy Kerr { 11318732794bSWen Congyang struct node *node = node_devices[nid]; 113210fbcf4cSKay Sievers sysfs_remove_link(&node->dev.kobj, kobject_name(&dev->kobj)); 1133953039c8SJeremy Kerr } 113412654f77SJohannes Berg EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node); 1135953039c8SJeremy Kerr 1136d3d2176aSDavid Gibson #else 1137d3d2176aSDavid Gibson static void register_nodes(void) 1138d3d2176aSDavid Gibson { 1139d3d2176aSDavid Gibson return; 1140d3d2176aSDavid Gibson } 1141953039c8SJeremy Kerr 1142d3d2176aSDavid Gibson #endif 1143d3d2176aSDavid Gibson 1144d3d2176aSDavid Gibson /* Only valid if CPU is present. */ 11458a25a2fdSKay Sievers static ssize_t show_physical_id(struct device *dev, 11468a25a2fdSKay Sievers struct device_attribute *attr, char *buf) 1147d3d2176aSDavid Gibson { 11488a25a2fdSKay Sievers struct cpu *cpu = container_of(dev, struct cpu, dev); 1149d3d2176aSDavid Gibson 11508a25a2fdSKay Sievers return sprintf(buf, "%d\n", get_hard_smp_processor_id(cpu->dev.id)); 1151d3d2176aSDavid Gibson } 11528a25a2fdSKay Sievers static DEVICE_ATTR(physical_id, 0444, show_physical_id, NULL); 1153d3d2176aSDavid Gibson 1154d3d2176aSDavid Gibson static int __init topology_init(void) 1155d3d2176aSDavid Gibson { 1156977ab257SSebastian Andrzej Siewior int cpu, r; 1157d3d2176aSDavid Gibson 1158d3d2176aSDavid Gibson register_nodes(); 1159d1a55113SSrivatsa S. Bhat 11600e551954SKAMEZAWA Hiroyuki for_each_possible_cpu(cpu) { 1161d3d2176aSDavid Gibson struct cpu *c = &per_cpu(cpu_devices, cpu); 1162d3d2176aSDavid Gibson 1163d3d2176aSDavid Gibson /* 1164d3d2176aSDavid Gibson * For now, we just see if the system supports making 1165d3d2176aSDavid Gibson * the RTAS calls for CPU hotplug. But, there may be a 1166d3d2176aSDavid Gibson * more comprehensive way to do this for an individual 1167d3d2176aSDavid Gibson * CPU. For instance, the boot cpu might never be valid 1168d3d2176aSDavid Gibson * for hotplugging. 1169d3d2176aSDavid Gibson */ 117072486f1fSSiddha, Suresh B if (ppc_md.cpu_die) 117172486f1fSSiddha, Suresh B c->hotpluggable = 1; 1172d3d2176aSDavid Gibson 117372486f1fSSiddha, Suresh B if (cpu_online(cpu) || c->hotpluggable) { 117476b67ed9SKAMEZAWA Hiroyuki register_cpu(c, cpu); 1175d3d2176aSDavid Gibson 11768a25a2fdSKay Sievers device_create_file(&c->dev, &dev_attr_physical_id); 1177d3d2176aSDavid Gibson } 1178d3d2176aSDavid Gibson } 1179977ab257SSebastian Andrzej Siewior r = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powerpc/topology:online", 1180977ab257SSebastian Andrzej Siewior register_cpu_online, unregister_cpu_online); 1181977ab257SSebastian Andrzej Siewior WARN_ON(r < 0); 1182efcac658SAlexey Kardashevskiy #ifdef CONFIG_PPC64 1183efcac658SAlexey Kardashevskiy sysfs_create_dscr_default(); 1184efcac658SAlexey Kardashevskiy #endif /* CONFIG_PPC64 */ 1185d3d2176aSDavid Gibson 1186734560acSRyan Grimm create_svm_file(); 1187734560acSRyan Grimm 1188d3d2176aSDavid Gibson return 0; 1189d3d2176aSDavid Gibson } 1190e9e77ce8SKevin Corry subsys_initcall(topology_init); 1191