1/* 2 * Initial setup-routines for HP 9000 based hardware. 3 * 4 * Copyright (C) 1991, 1992, 1995 Linus Torvalds 5 * Modifications for PA-RISC (C) 1999-2008 Helge Deller <deller@gmx.de> 6 * Modifications copyright 1999 SuSE GmbH (Philipp Rumpf) 7 * Modifications copyright 2000 Martin K. Petersen <mkp@mkp.net> 8 * Modifications copyright 2000 Philipp Rumpf <prumpf@tux.org> 9 * Modifications copyright 2001 Ryan Bradetich <rbradetich@uswest.net> 10 * 11 * Initial PA-RISC Version: 04-23-1999 by Helge Deller 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2, or (at your option) 16 * any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 26 * 27 */ 28#include <linux/delay.h> 29#include <linux/init.h> 30#include <linux/mm.h> 31#include <linux/module.h> 32#include <linux/seq_file.h> 33#include <linux/slab.h> 34#include <linux/cpu.h> 35#include <asm/param.h> 36#include <asm/cache.h> 37#include <asm/hardware.h> /* for register_parisc_driver() stuff */ 38#include <asm/processor.h> 39#include <asm/page.h> 40#include <asm/pdc.h> 41#include <asm/pdcpat.h> 42#include <asm/irq.h> /* for struct irq_region */ 43#include <asm/parisc-device.h> 44 45struct system_cpuinfo_parisc boot_cpu_data __read_mostly; 46EXPORT_SYMBOL(boot_cpu_data); 47 48DEFINE_PER_CPU(struct cpuinfo_parisc, cpu_data); 49 50extern int update_cr16_clocksource(void); /* from time.c */ 51 52/* 53** PARISC CPU driver - claim "device" and initialize CPU data structures. 54** 55** Consolidate per CPU initialization into (mostly) one module. 56** Monarch CPU will initialize boot_cpu_data which shouldn't 57** change once the system has booted. 58** 59** The callback *should* do per-instance initialization of 60** everything including the monarch. "Per CPU" init code in 61** setup.c:start_parisc() has migrated here and start_parisc() 62** will call register_parisc_driver(&cpu_driver) before calling do_inventory(). 63** 64** The goal of consolidating CPU initialization into one place is 65** to make sure all CPUs get initialized the same way. 66** The code path not shared is how PDC hands control of the CPU to the OS. 67** The initialization of OS data structures is the same (done below). 68*/ 69 70static void __cpuinit 71init_percpu_prof(unsigned long cpunum) 72{ 73 struct cpuinfo_parisc *p; 74 75 p = &per_cpu(cpu_data, cpunum); 76 p->prof_counter = 1; 77 p->prof_multiplier = 1; 78} 79 80 81/** 82 * processor_probe - Determine if processor driver should claim this device. 83 * @dev: The device which has been found. 84 * 85 * Determine if processor driver should claim this chip (return 0) or not 86 * (return 1). If so, initialize the chip and tell other partners in crime 87 * they have work to do. 88 */ 89static int __cpuinit processor_probe(struct parisc_device *dev) 90{ 91 unsigned long txn_addr; 92 unsigned long cpuid; 93 struct cpuinfo_parisc *p; 94 95#ifdef CONFIG_SMP 96 if (num_online_cpus() >= nr_cpu_ids) { 97 printk(KERN_INFO "num_online_cpus() >= nr_cpu_ids\n"); 98 return 1; 99 } 100#else 101 if (boot_cpu_data.cpu_count > 0) { 102 printk(KERN_INFO "CONFIG_SMP=n ignoring additional CPUs\n"); 103 return 1; 104 } 105#endif 106 107 /* logical CPU ID and update global counter 108 * May get overwritten by PAT code. 109 */ 110 cpuid = boot_cpu_data.cpu_count; 111 txn_addr = dev->hpa.start; /* for legacy PDC */ 112 113#ifdef CONFIG_64BIT 114 if (is_pdc_pat()) { 115 ulong status; 116 unsigned long bytecnt; 117 pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell; 118#undef USE_PAT_CPUID 119#ifdef USE_PAT_CPUID 120 struct pdc_pat_cpu_num cpu_info; 121#endif 122 123 pa_pdc_cell = kmalloc(sizeof (*pa_pdc_cell), GFP_KERNEL); 124 if (!pa_pdc_cell) 125 panic("couldn't allocate memory for PDC_PAT_CELL!"); 126 127 status = pdc_pat_cell_module(&bytecnt, dev->pcell_loc, 128 dev->mod_index, PA_VIEW, pa_pdc_cell); 129 130 BUG_ON(PDC_OK != status); 131 132 /* verify it's the same as what do_pat_inventory() found */ 133 BUG_ON(dev->mod_info != pa_pdc_cell->mod_info); 134 BUG_ON(dev->pmod_loc != pa_pdc_cell->mod_location); 135 136 txn_addr = pa_pdc_cell->mod[0]; /* id_eid for IO sapic */ 137 138 kfree(pa_pdc_cell); 139 140#ifdef USE_PAT_CPUID 141/* We need contiguous numbers for cpuid. Firmware's notion 142 * of cpuid is for physical CPUs and we just don't care yet. 143 * We'll care when we need to query PAT PDC about a CPU *after* 144 * boot time (ie shutdown a CPU from an OS perspective). 145 */ 146 /* get the cpu number */ 147 status = pdc_pat_cpu_get_number(&cpu_info, dev->hpa.start); 148 149 BUG_ON(PDC_OK != status); 150 151 if (cpu_info.cpu_num >= NR_CPUS) { 152 printk(KERN_WARNING "IGNORING CPU at 0x%x," 153 " cpu_slot_id > NR_CPUS" 154 " (%ld > %d)\n", 155 dev->hpa.start, cpu_info.cpu_num, NR_CPUS); 156 /* Ignore CPU since it will only crash */ 157 boot_cpu_data.cpu_count--; 158 return 1; 159 } else { 160 cpuid = cpu_info.cpu_num; 161 } 162#endif 163 } 164#endif 165 166 p = &per_cpu(cpu_data, cpuid); 167 boot_cpu_data.cpu_count++; 168 169 /* initialize counters - CPU 0 gets it_value set in time_init() */ 170 if (cpuid) 171 memset(p, 0, sizeof(struct cpuinfo_parisc)); 172 173 p->loops_per_jiffy = loops_per_jiffy; 174 p->dev = dev; /* Save IODC data in case we need it */ 175 p->hpa = dev->hpa.start; /* save CPU hpa */ 176 p->cpuid = cpuid; /* save CPU id */ 177 p->txn_addr = txn_addr; /* save CPU IRQ address */ 178#ifdef CONFIG_SMP 179 init_percpu_prof(cpuid); 180#endif 181 182 /* 183 ** CONFIG_SMP: init_smp_config() will attempt to get CPUs into 184 ** OS control. RENDEZVOUS is the default state - see mem_set above. 185 ** p->state = STATE_RENDEZVOUS; 186 */ 187 188 189 /* 190 * Bring this CPU up now! (ignore bootstrap cpuid == 0) 191 */ 192#ifdef CONFIG_SMP 193 if (cpuid) { 194 set_cpu_present(cpuid, true); 195 cpu_up(cpuid); 196 } 197#endif 198 199 /* If we've registered more than one cpu, 200 * we'll use the jiffies clocksource since cr16 201 * is not synchronized between CPUs. 202 */ 203 update_cr16_clocksource(); 204 205 return 0; 206} 207 208/** 209 * collect_boot_cpu_data - Fill the boot_cpu_data structure. 210 * 211 * This function collects and stores the generic processor information 212 * in the boot_cpu_data structure. 213 */ 214void __init collect_boot_cpu_data(void) 215{ 216 memset(&boot_cpu_data, 0, sizeof(boot_cpu_data)); 217 218 boot_cpu_data.cpu_hz = 100 * PAGE0->mem_10msec; /* Hz of this PARISC */ 219 220 /* get CPU-Model Information... */ 221#define p ((unsigned long *)&boot_cpu_data.pdc.model) 222 if (pdc_model_info(&boot_cpu_data.pdc.model) == PDC_OK) 223 printk(KERN_INFO 224 "model %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", 225 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]); 226#undef p 227 228 if (pdc_model_versions(&boot_cpu_data.pdc.versions, 0) == PDC_OK) 229 printk(KERN_INFO "vers %08lx\n", 230 boot_cpu_data.pdc.versions); 231 232 if (pdc_model_cpuid(&boot_cpu_data.pdc.cpuid) == PDC_OK) 233 printk(KERN_INFO "CPUID vers %ld rev %ld (0x%08lx)\n", 234 (boot_cpu_data.pdc.cpuid >> 5) & 127, 235 boot_cpu_data.pdc.cpuid & 31, 236 boot_cpu_data.pdc.cpuid); 237 238 if (pdc_model_capabilities(&boot_cpu_data.pdc.capabilities) == PDC_OK) 239 printk(KERN_INFO "capabilities 0x%lx\n", 240 boot_cpu_data.pdc.capabilities); 241 242 if (pdc_model_sysmodel(boot_cpu_data.pdc.sys_model_name) == PDC_OK) 243 printk(KERN_INFO "model %s\n", 244 boot_cpu_data.pdc.sys_model_name); 245 246 boot_cpu_data.hversion = boot_cpu_data.pdc.model.hversion; 247 boot_cpu_data.sversion = boot_cpu_data.pdc.model.sversion; 248 249 boot_cpu_data.cpu_type = parisc_get_cpu_type(boot_cpu_data.hversion); 250 boot_cpu_data.cpu_name = cpu_name_version[boot_cpu_data.cpu_type][0]; 251 boot_cpu_data.family_name = cpu_name_version[boot_cpu_data.cpu_type][1]; 252} 253 254 255 256/** 257 * init_per_cpu - Handle individual processor initializations. 258 * @cpunum: logical processor number. 259 * 260 * This function handles initialization for *every* CPU 261 * in the system: 262 * 263 * o Set "default" CPU width for trap handlers 264 * 265 * o Enable FP coprocessor 266 * REVISIT: this could be done in the "code 22" trap handler. 267 * (frowands idea - that way we know which processes need FP 268 * registers saved on the interrupt stack.) 269 * NEWS FLASH: wide kernels need FP coprocessor enabled to handle 270 * formatted printing of %lx for example (double divides I think) 271 * 272 * o Enable CPU profiling hooks. 273 */ 274int __cpuinit init_per_cpu(int cpunum) 275{ 276 int ret; 277 struct pdc_coproc_cfg coproc_cfg; 278 279 set_firmware_width(); 280 ret = pdc_coproc_cfg(&coproc_cfg); 281 282 if(ret >= 0 && coproc_cfg.ccr_functional) { 283 mtctl(coproc_cfg.ccr_functional, 10); /* 10 == Coprocessor Control Reg */ 284 285 /* FWIW, FP rev/model is a more accurate way to determine 286 ** CPU type. CPU rev/model has some ambiguous cases. 287 */ 288 per_cpu(cpu_data, cpunum).fp_rev = coproc_cfg.revision; 289 per_cpu(cpu_data, cpunum).fp_model = coproc_cfg.model; 290 291 printk(KERN_INFO "FP[%d] enabled: Rev %ld Model %ld\n", 292 cpunum, coproc_cfg.revision, coproc_cfg.model); 293 294 /* 295 ** store status register to stack (hopefully aligned) 296 ** and clear the T-bit. 297 */ 298 asm volatile ("fstd %fr0,8(%sp)"); 299 300 } else { 301 printk(KERN_WARNING "WARNING: No FP CoProcessor?!" 302 " (coproc_cfg.ccr_functional == 0x%lx, expected 0xc0)\n" 303#ifdef CONFIG_64BIT 304 "Halting Machine - FP required\n" 305#endif 306 , coproc_cfg.ccr_functional); 307#ifdef CONFIG_64BIT 308 mdelay(100); /* previous chars get pushed to console */ 309 panic("FP CoProc not reported"); 310#endif 311 } 312 313 /* FUTURE: Enable Performance Monitor : ccr bit 0x20 */ 314 init_percpu_prof(cpunum); 315 316 return ret; 317} 318 319/* 320 * Display CPU info for all CPUs. 321 */ 322int 323show_cpuinfo (struct seq_file *m, void *v) 324{ 325 unsigned long cpu; 326 327 for_each_online_cpu(cpu) { 328 const struct cpuinfo_parisc *cpuinfo = &per_cpu(cpu_data, cpu); 329#ifdef CONFIG_SMP 330 if (0 == cpuinfo->hpa) 331 continue; 332#endif 333 seq_printf(m, "processor\t: %lu\n" 334 "cpu family\t: PA-RISC %s\n", 335 cpu, boot_cpu_data.family_name); 336 337 seq_printf(m, "cpu\t\t: %s\n", boot_cpu_data.cpu_name ); 338 339 /* cpu MHz */ 340 seq_printf(m, "cpu MHz\t\t: %d.%06d\n", 341 boot_cpu_data.cpu_hz / 1000000, 342 boot_cpu_data.cpu_hz % 1000000 ); 343 344 seq_printf(m, "capabilities\t:"); 345 if (boot_cpu_data.pdc.capabilities & PDC_MODEL_OS32) 346 seq_printf(m, " os32"); 347 if (boot_cpu_data.pdc.capabilities & PDC_MODEL_OS64) 348 seq_printf(m, " os64"); 349 seq_printf(m, "\n"); 350 351 seq_printf(m, "model\t\t: %s\n" 352 "model name\t: %s\n", 353 boot_cpu_data.pdc.sys_model_name, 354 cpuinfo->dev ? 355 cpuinfo->dev->name : "Unknown"); 356 357 seq_printf(m, "hversion\t: 0x%08x\n" 358 "sversion\t: 0x%08x\n", 359 boot_cpu_data.hversion, 360 boot_cpu_data.sversion ); 361 362 /* print cachesize info */ 363 show_cache_info(m); 364 365 seq_printf(m, "bogomips\t: %lu.%02lu\n", 366 cpuinfo->loops_per_jiffy / (500000 / HZ), 367 (cpuinfo->loops_per_jiffy / (5000 / HZ)) % 100); 368 369 seq_printf(m, "software id\t: %ld\n\n", 370 boot_cpu_data.pdc.model.sw_id); 371 } 372 return 0; 373} 374 375static const struct parisc_device_id processor_tbl[] = { 376 { HPHW_NPROC, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, SVERSION_ANY_ID }, 377 { 0, } 378}; 379 380static struct parisc_driver cpu_driver = { 381 .name = "CPU", 382 .id_table = processor_tbl, 383 .probe = processor_probe 384}; 385 386/** 387 * processor_init - Processor initialization procedure. 388 * 389 * Register this driver. 390 */ 391void __init processor_init(void) 392{ 393 register_parisc_driver(&cpu_driver); 394} 395