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