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