File: /usr/src/linux/arch/ppc/kernel/walnut_setup.c

1     /*
2      * BK Id: SCCS/s.walnut_setup.c 1.5 05/17/01 18:14:22 cort
3      */
4     /*
5      *
6      *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
7      *
8      *    Module name: walnut_setup.c
9      *
10      *    Description:
11      *      Architecture- / platform-specific boot-time initialization code for
12      *      the IBM PowerPC 403GP "Walnut" evaluation board. Adapted from original
13      *      code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
14      *      <dan@net4x.com>.
15      *
16      */
17     
18     #include <linux/config.h>
19     #include <linux/init.h>
20     #include <linux/smp.h>
21     #include <linux/threads.h>
22     #include <linux/interrupt.h>
23     #include <linux/param.h>
24     #include <linux/string.h>
25     #include <linux/blk.h>
26     
27     #include <asm/processor.h>
28     #include <asm/board.h>
29     #include <asm/machdep.h>
30     #include <asm/page.h>
31     
32     #include "local_irq.h"
33     #include "ppc4xx_pic.h"
34     #include <asm/time.h>
35     #include "walnut_setup.h"
36     
37     
38     /* Function Prototypes */
39     
40     extern void abort(void);
41     
42     /* Global Variables */
43     
44     unsigned char __res[sizeof(bd_t)];
45     
46     
47     /*
48      * void __init walnut_init()
49      *
50      * Description:
51      *   This routine...
52      *
53      * Input(s):
54      *   r3 - Optional pointer to a board information structure.
55      *   r4 - Optional pointer to the physical starting address of the init RAM
56      *        disk.
57      *   r5 - Optional pointer to the physical ending address of the init RAM
58      *        disk.
59      *   r6 - Optional pointer to the physical starting address of any kernel
60      *        command-line parameters.
61      *   r7 - Optional pointer to the physical ending address of any kernel
62      *        command-line parameters.
63      *
64      * Output(s):
65      *   N/A
66      *
67      * Returns:
68      *   N/A
69      *
70      */
71     void __init
72     walnut_init(unsigned long r3, unsigned long r4, unsigned long r5, 
73     	    unsigned long r6, unsigned long r7)
74     {
75     	/*
76     	 * If we were passed in a board information, copy it into the
77     	 * residual data area.
78     	 */
79     	if (r3) {
80     		memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
81     	}
82     
83     #if defined(CONFIG_BLK_DEV_INITRD)
84     	/*
85     	 * If the init RAM disk has been configured in, and there's a valid
86     	 * starting address for it, set it up.
87     	 */
88     	if (r4) {
89     		initrd_start = r4 + KERNELBASE;
90     		initrd_end = r5 + KERNELBASE;
91     	}
92     #endif /* CONFIG_BLK_DEV_INITRD */
93     
94     	/* Copy the kernel command line arguments to a safe place. */
95     
96     	if (r6) {
97      		*(char *)(r7 + KERNELBASE) = 0;
98     		strcpy(cmd_line, (char *)(r6 + KERNELBASE));
99     	}
100     
101     	/* Initialize machine-dependency vectors */
102     
103     	ppc_md.setup_arch	 	= walnut_setup_arch;
104     	ppc_md.setup_residual	 	= walnut_setup_residual;
105     	ppc_md.get_cpuinfo	 	= NULL;
106     	ppc_md.irq_cannonicalize 	= NULL;
107     	ppc_md.init_IRQ		 	= walnut_init_IRQ;
108     	ppc_md.get_irq		 	= walnut_get_irq;
109     	ppc_md.init		 	= NULL;
110     
111     	ppc_md.restart		 	= walnut_restart;
112     	ppc_md.power_off	 	= walnut_power_off;
113     	ppc_md.halt		 	= walnut_halt;
114     
115     	ppc_md.time_init	 	= walnut_time_init;
116     	ppc_md.set_rtc_time	 	= walnut_set_rtc_time;
117     	ppc_md.get_rtc_time	 	= walnut_get_rtc_time;
118     	ppc_md.calibrate_decr	 	= walnut_calibrate_decr;
119     
120     	ppc_md.kbd_setkeycode    	= NULL;
121     	ppc_md.kbd_getkeycode    	= NULL;
122     	ppc_md.kbd_translate     	= NULL;
123     	ppc_md.kbd_unexpected_up 	= NULL;
124     	ppc_md.kbd_leds          	= NULL;
125     	ppc_md.kbd_init_hw       	= NULL;
126     
127     #if defined(CONFIG_MAGIC_SYSRQ)
128     	ppc_md.ppc_kbd_sysrq_xlate	= NULL;
129     #endif
130     
131     	return;
132     }
133     
134     /*
135      * Document me.
136      */
137     void __init
138     walnut_setup_arch(void)
139     {
140     	/* XXX - Implement me */
141     }
142     
143     /*
144      * int walnut_setup_residual()
145      *
146      * Description:
147      *   This routine pretty-prints the platform's internal CPU and bus clock
148      *   frequencies into the buffer for usage in /proc/cpuinfo.
149      *
150      * Input(s):
151      *  *buffer - Buffer into which CPU and bus clock frequencies are to be
152      *            printed.
153      *
154      * Output(s):
155      *  *buffer - Buffer with the CPU and bus clock frequencies.
156      *
157      * Returns:
158      *   The number of bytes copied into 'buffer' if OK, otherwise zero or less
159      *   on error.
160      */
161     int
162     walnut_setup_residual(char *buffer)
163     {
164     	int len = 0;
165     	bd_t *bp = (bd_t *)__res;
166     
167     	len += sprintf(len + buffer,
168     		       "clock\t\t: %dMHz\n"
169     		       "bus clock\t\t: %dMHz\n",
170     		       bp->bi_intfreq / 1000000,
171     		       bp->bi_busfreq / 1000000);
172     
173     	return (len);
174     }
175     
176     /*
177      * Document me.
178      */
179     void __init
180     walnut_init_IRQ(void)
181     {
182     	int i;
183     
184     	ppc4xx_pic_init();
185     
186     	for (i = 0; i < NR_IRQS; i++) {
187     		irq_desc[i].handler = ppc4xx_pic;
188     	}
189     
190     	return;
191     }
192     
193     /*
194      * Document me.
195      */
196     int
197     walnut_get_irq(struct pt_regs *regs)
198     {
199     	return (ppc4xx_pic_get_irq(regs));
200     }
201     
202     /*
203      * Document me.
204      */
205     void
206     walnut_restart(char *cmd)
207     {
208     	abort();
209     }
210     
211     /*
212      * Document me.
213      */
214     void
215     walnut_power_off(void)
216     {
217     	walnut_restart(NULL);
218     }
219     
220     /*
221      * Document me.
222      */
223     void
224     walnut_halt(void)
225     {
226     	walnut_restart(NULL);
227     }
228     
229     /*
230      * Document me.
231      */
232     long __init
233     walnut_time_init(void)
234     {
235     	/* XXX - Implement me */
236     	return 0;
237     }
238     
239     /*
240      * Document me.
241      */
242     int __init
243     walnut_set_rtc_time(unsigned long time)
244     {
245     	/* XXX - Implement me */
246     
247     	return (0);
248     }
249     
250     /*
251      * Document me.
252      */
253     unsigned long __init
254     walnut_get_rtc_time(void)
255     {
256     	/* XXX - Implement me */
257     
258     	return (0);
259     }
260     
261     /*
262      * void __init walnut_calibrate_decr()
263      *
264      * Description:
265      *   This routine retrieves the internal processor frequency from the board
266      *   information structure, sets up the kernel timer decrementer based on
267      *   that value, enables the 403 programmable interval timer (PIT) and sets
268      *   it up for auto-reload.
269      *
270      * Input(s):
271      *   N/A
272      *
273      * Output(s):
274      *   N/A
275      *
276      * Returns:
277      *   N/A
278      *
279      */
280     void __init
281     walnut_calibrate_decr(void)
282     {
283     	unsigned int freq;
284     	bd_t *bip = (bd_t *)__res;
285     
286     	freq = bip->bi_intfreq;
287     
288     	decrementer_count = freq / HZ;
289     	count_period_num = 1;
290     	count_period_den = freq;
291     
292     	/* Enable the PIT and set auto-reload of its value */
293     
294     	mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
295     
296     	/* Clear any pending timer interrupts */
297     
298     	mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
299     }
300