• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/arch/parisc/kernel/
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