2 * $Id: mbx_setup.c,v 1.10 1999/05/14 07:24:19 davem Exp $
4 * linux/arch/ppc/kernel/setup.c
6 * Copyright (C) 1995 Linus Torvalds
7 * Adapted from 'alpha' version by Gary Thomas
8 * Modified by Cort Dougan (cort@cs.nmt.edu)
9 * Modified for MBX using prep/chrp/pmac functions by Dan (dmalek@jlc.net)
13 * bootup setup stuff..
16 #include <linux/config.h>
17 #include <linux/errno.h>
18 #include <linux/sched.h>
19 #include <linux/kernel.h>
21 #include <linux/stddef.h>
22 #include <linux/unistd.h>
23 #include <linux/ptrace.h>
24 #include <linux/malloc.h>
25 #include <linux/user.h>
26 #include <linux/a.out.h>
27 #include <linux/tty.h>
28 #include <linux/major.h>
29 #include <linux/interrupt.h>
30 #include <linux/reboot.h>
31 #include <linux/init.h>
32 #include <linux/blk.h>
33 #include <linux/ioport.h>
36 #include <asm/processor.h>
37 #include <asm/residual.h>
39 #include <asm/pgtable.h>
42 #include <asm/machdep.h>
45 #include "local_irq.h"
47 static int mbx_set_rtc_time(unsigned long time
);
48 unsigned long mbx_get_rtc_time(void);
49 void mbx_calibrate_decr(void);
51 extern int mackbd_setkeycode(unsigned int scancode
, unsigned int keycode
);
52 extern int mackbd_getkeycode(unsigned int scancode
);
53 extern int mackbd_translate(unsigned char scancode
, unsigned char *keycode
,
55 extern char mackbd_unexpected_up(unsigned char keycode
);
56 extern void mackbd_leds(unsigned char leds
);
57 extern void mackbd_init_hw(void);
59 extern unsigned long loops_per_sec
;
61 unsigned long empty_zero_page
[1024];
63 #ifdef CONFIG_BLK_DEV_RAM
64 extern int rd_doload
; /* 1 = load ramdisk, 0 = don't load */
65 extern int rd_prompt
; /* 1 = prompt for ramdisk, 0 = don't prompt */
66 extern int rd_image_start
; /* starting block # of image */
69 extern char saved_command_line
[256];
71 extern unsigned long find_available_memory(void);
72 extern void m8xx_cpm_reset(uint
);
74 void __init
adbdev_init(void)
79 mbx_setup_arch(unsigned long * memory_start_p
, unsigned long * memory_end_p
))
82 extern char cmd_line
[];
84 cpm_page
= *memory_start_p
;
85 *memory_start_p
+= PAGE_SIZE
;
88 "%s root=/dev/nfs nfsroot=/sys/mbxroot",
90 printk("Boot arguments: %s\n", cmd_line
);
92 /* Reset the Communication Processor Module.
94 m8xx_cpm_reset(cpm_page
);
97 ROOT_DEV
= to_kdev_t(0x0301); /* hda1 */
100 #ifdef CONFIG_BLK_DEV_INITRD
102 ROOT_DEV
= to_kdev_t(0x0200); /* floppy */
107 /* initrd_start and size are setup by boot/head.S and kernel/head.S */
110 if (initrd_end
> *memory_end_p
)
112 printk("initrd extends beyond end of memory "
113 "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
114 initrd_end
,*memory_end_p
);
121 request_region(0x20,0x20,"pic1");
122 request_region(0xa0,0x20,"pic2");
123 request_region(0x00,0x20,"dma1");
124 request_region(0x40,0x20,"timer");
125 request_region(0x80,0x10,"dma page reg");
126 request_region(0xc0,0x20,"dma2");
134 extern void xmon(void *);
137 machine_restart(NULL
);
140 /* The decrementer counts at the system (internal) clock frequency divided by
141 * sixteen, or external oscillator divided by four. Currently, we only
142 * support the MBX, which is system clock divided by sixteen.
144 __initfunc(void mbx_calibrate_decr(void))
146 bd_t
*binfo
= (bd_t
*)&res
;
147 int freq
, fp
, divisor
;
149 if ((((immap_t
*)MBX_IMAP_ADDR
)->im_clkrst
.car_sccr
& 0x02000000) == 0)
150 printk("WARNING: Wrong decrementer source clock.\n");
152 /* The manual says the frequency is in Hz, but it is really
153 * as MHz. The value 'fp' is the number of decrementer ticks
156 fp
= (binfo
->bi_intfreq
* 1000000) / 16;
157 freq
= fp
*60; /* try to make freq/1e6 an integer */
159 printk("time_init: decrementer frequency = %d/%d\n", freq
, divisor
);
160 decrementer_count
= freq
/ HZ
/ divisor
;
161 count_period_num
= divisor
;
162 count_period_den
= freq
/ 1000000;
165 /* A place holder for time base interrupts, if they are ever enabled.
167 void timebase_interrupt(int irq
, void * dev
, struct pt_regs
* regs
)
169 printk("timebase_interrupt()\n");
172 /* The RTC on the MPC8xx is an internal register.
173 * We want to protect this during power down, so we need to unlock,
174 * modify, and re-lock.
177 mbx_set_rtc_time(unsigned long time
)
179 ((immap_t
*)MBX_IMAP_ADDR
)->im_sitk
.sitk_rtck
= KAPWR_KEY
;
180 ((immap_t
*)MBX_IMAP_ADDR
)->im_sit
.sit_rtc
= time
;
181 ((immap_t
*)MBX_IMAP_ADDR
)->im_sitk
.sitk_rtck
= ~KAPWR_KEY
;
185 initfunc(unsigned long
186 mbx_get_rtc_time(void)
188 /* First, unlock all of the registers we are going to modify.
189 * To protect them from corruption during power down, registers
190 * that are maintained by keep alive power are "locked". To
191 * modify these registers we have to write the key value to
192 * the key location associated with the register.
194 ((immap_t
*)MBX_IMAP_ADDR
)->im_sitk
.sitk_tbscrk
= KAPWR_KEY
;
195 ((immap_t
*)MBX_IMAP_ADDR
)->im_sitk
.sitk_rtcsck
= KAPWR_KEY
;
198 /* Disable the RTC one second and alarm interrupts.
200 ((immap_t
*)MBX_IMAP_ADDR
)->im_sit
.sit_rtcsc
&=
201 ~(RTCSC_SIE
| RTCSC_ALE
);
203 /* Enabling the decrementer also enables the timebase interrupts
204 * (or from the other point of view, to get decrementer interrupts
205 * we have to enable the timebase). The decrementer interrupt
206 * is wired into the vector table, nothing to do here for that.
208 ((immap_t
*)MBX_IMAP_ADDR
)->im_sit
.sit_tbscr
=
209 ((mk_int_int_mask(DEC_INTERRUPT
) << 8) |
210 (TBSCR_TBF
| TBSCR_TBE
));
211 if (request_irq(DEC_INTERRUPT
, timebase_interrupt
, 0, "tbint", NULL
) != 0)
212 panic("Could not allocate timer IRQ!");
214 /* Get time from the RTC.
216 return ((immap_t
*)MBX_IMAP_ADDR
)->im_sit
.sit_rtc
;
220 mbx_restart(char *cmd
)
222 extern void MBX_gorom(void);
240 int mbx_setup_residual(char *buffer
)
244 extern RESIDUAL
*res
;
248 len
+= sprintf(len
+buffer
,"clock\t\t: %dMHz\n"
249 "bus clock\t: %dMHz\n",
250 bp
->bi_intfreq
/*/ 1000000*/,
251 bp
->bi_busfreq
/*/ 1000000*/);
257 mbx_do_IRQ(struct pt_regs
*regs
,
262 unsigned long bits
= 0;
264 /* For MPC8xx, read the SIVEC register and shift the bits down
265 * to get the irq number. */
266 bits
= ((immap_t
*)IMAP_ADDR
)->im_siu_conf
.sc_sivec
;
268 irq
+= ppc8xx_pic
.irq_offset
;
272 printk(KERN_DEBUG
"Bogus interrupt %d from PC = %lx\n",
274 spurious_interrupts
++;
277 ppc_irq_dispatch_handler( regs
, irq
);
282 static void mbx_i8259_action(int cpl
, void *dev_id
, struct pt_regs
*regs
)
286 /* A bug in the QSpan chip causes it to give us 0xff always
287 * when doing a character read. So read 32 bits and shift.
288 * This doesn't seem to return useful values anyway, but
289 * read it to make sure things are acked.
292 irq
= (inl(0x508) >> 24)&0xff;
293 if ( irq
!= 0xff ) printk("iack %d\n", irq
);
304 irq
+= i8259_pic
.irq_offset
;
305 ppc_irq_dispatch_handler( regs
, irq
);
309 /* On MBX8xx, the interrupt control (SIEL) was set by EPPC-bug. External
310 * interrupts can be either edge or level triggered, but there is no
311 * reason for us to change the EPPC-bug values (it would not work if we did).
318 ppc8xx_pic
.irq_offset
= 16;
319 for ( i
= 16 ; i
< 32 ; i
++ )
320 irq_desc
[i
].ctl
= &ppc8xx_pic
;
321 unmask_irq(CPM_INTERRUPT
);
323 for ( i
= 0 ; i
< 16 ; i
++ )
324 irq_desc
[i
].ctl
= &i8259_pic
;
326 request_irq(ISA_BRIDGE_INT
, mbx_i8259_action
, 0, "8259 cascade", NULL
);
327 enable_irq(ISA_BRIDGE_INT
);
330 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
335 mbx_ide_insw(ide_ioreg_t port
, void *buf
, int ns
)
337 ide_insw(port
+_IO_BASE
), buf
, ns
);
341 mbx_ide_outsw(ide_ioreg_t port
, void *buf
, int ns
)
343 ide_outsw(port
+_IO_BASE
, buf
, ns
);
347 mbx_ide_default_irq(ide_ioreg_t base
)
353 mbx_ide_default_io_base(int index
)
359 mbx_ide_check_region(ide_ioreg_t from
, unsigned int extent
)
365 mbx_ide_request_region(ide_ioreg_t from
,
372 mbx_ide_release_region(ide_ioreg_t from
,
378 mbx_ide_fix_driveid(struct hd_driveid
*id
)
380 ppc_generic_ide_fix_driveid(id
);
384 mbx_ide_init_hwif_ports(hw_regs_t
*hw
, ide_ioreg_t data_port
, ide_ioreg_t ctrl_port
, int *irq
)
386 ide_ioreg_t reg
= data_port
;
391 if (data_port
!= 0) /* Only map the first ATA flash drive */
396 reg
= (ide_ioreg_t
) ioremap(PCMCIA_MEM_ADDR
, 0x200);
398 for (i
= IDE_DATA_OFFSET
; i
<= IDE_STATUS_OFFSET
; i
++) {
399 hw
->io_ports
[i
] = reg
;
403 /* Does not matter */
406 hw
->io_ports
[IDE_CONTROL_OFFSET
] = ctrl_port
;
408 hw
->io_ports
[IDE_CONTROL_OFFSET
] = reg
;
417 mbx_init(unsigned long r3
, unsigned long r4
, unsigned long r5
,
418 unsigned long r6
, unsigned long r7
))
422 memcpy( (void *)&res
,(void *)(r3
+KERNELBASE
), sizeof(bd_t
) );
425 mbx_setup_pci_ptrs();
428 #ifdef CONFIG_BLK_DEV_INITRD
429 /* take care of initrd if we have one */
432 initrd_start
= r4
+ KERNELBASE
;
433 initrd_end
= r5
+ KERNELBASE
;
435 #endif /* CONFIG_BLK_DEV_INITRD */
436 /* take care of cmd line */
440 *(char *)(r7
+KERNELBASE
) = 0;
441 strcpy(cmd_line
, (char *)(r6
+KERNELBASE
));
444 ppc_md
.setup_arch
= mbx_setup_arch
;
445 ppc_md
.setup_residual
= mbx_setup_residual
;
446 ppc_md
.get_cpuinfo
= NULL
;
447 ppc_md
.irq_cannonicalize
= NULL
;
448 ppc_md
.init_IRQ
= mbx_init_IRQ
;
449 ppc_md
.do_IRQ
= mbx_do_IRQ
;
452 ppc_md
.restart
= mbx_restart
;
453 ppc_md
.power_off
= mbx_power_off
;
454 ppc_md
.halt
= mbx_halt
;
456 ppc_md
.time_init
= NULL
;
457 ppc_md
.set_rtc_time
= mbx_set_rtc_time
;
458 ppc_md
.get_rtc_time
= mbx_get_rtc_time
;
459 ppc_md
.calibrate_decr
= mbx_calibrate_decr
;
461 ppc_md
.kbd_setkeycode
= pckbd_setkeycode
;
462 ppc_md
.kbd_getkeycode
= pckbd_getkeycode
;
463 ppc_md
.kbd_translate
= pckbd_translate
;
464 ppc_md
.kbd_unexpected_up
= pckbd_unexpected_up
;
465 ppc_md
.kbd_leds
= pckbd_leds
;
466 ppc_md
.kbd_init_hw
= pckbd_init_hw
;
467 #ifdef CONFIG_MAGIC_SYSRQ
468 ppc_md
.kbd_sysrq_xlate
= pckbd_sysrq_xlate
;
471 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
472 ppc_ide_md
.insw
= mbx_ide_insw
;
473 ppc_ide_md
.outsw
= mbx_ide_outsw
;
474 ppc_ide_md
.default_irq
= mbx_ide_default_irq
;
475 ppc_ide_md
.default_io_base
= mbx_ide_default_io_base
;
476 ppc_ide_md
.check_region
= mbx_ide_check_region
;
477 ppc_ide_md
.request_region
= mbx_ide_request_region
;
478 ppc_ide_md
.release_region
= mbx_ide_release_region
;
479 ppc_ide_md
.fix_driveid
= mbx_ide_fix_driveid
;
480 ppc_ide_md
.ide_init_hwif
= mbx_ide_init_hwif_ports
;
482 ppc_ide_md
.io_base
= _IO_BASE
;