2 * $Id: m8xx_setup.c,v 1.4 1999/09/18 18:40:36 dmalek 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)
10 * Further modified for generic 8xx by Dan.
14 * bootup setup stuff..
17 #include <linux/config.h>
18 #include <linux/errno.h>
19 #include <linux/sched.h>
20 #include <linux/kernel.h>
22 #include <linux/stddef.h>
23 #include <linux/unistd.h>
24 #include <linux/ptrace.h>
25 #include <linux/malloc.h>
26 #include <linux/user.h>
27 #include <linux/a.out.h>
28 #include <linux/tty.h>
29 #include <linux/major.h>
30 #include <linux/interrupt.h>
31 #include <linux/reboot.h>
32 #include <linux/init.h>
33 #include <linux/blk.h>
34 #include <linux/ioport.h>
35 #include <linux/ide.h>
36 #include <linux/bootmem.h>
39 #include <asm/processor.h>
40 #include <asm/residual.h>
42 #include <asm/pgtable.h>
44 #include <asm/mpc8xx.h>
45 #include <asm/8xx_immap.h>
46 #include <asm/machdep.h>
49 #include "ppc8xx_pic.h"
51 static int m8xx_set_rtc_time(unsigned long time
);
52 unsigned long m8xx_get_rtc_time(void);
53 void m8xx_calibrate_decr(void);
56 extern int mackbd_setkeycode(unsigned int scancode
, unsigned int keycode
);
57 extern int mackbd_getkeycode(unsigned int scancode
);
58 extern int mackbd_pretranslate(unsigned char scancode
, char raw_mode
);
59 extern int mackbd_translate(unsigned char scancode
, unsigned char *keycode
,
61 extern char mackbd_unexpected_up(unsigned char keycode
);
62 extern void mackbd_leds(unsigned char leds
);
63 extern void mackbd_init_hw(void);
66 extern unsigned long loops_per_sec
;
68 unsigned char __res
[sizeof(bd_t
)];
69 unsigned long empty_zero_page
[1024];
71 #ifdef CONFIG_BLK_DEV_RAM
72 extern int rd_doload
; /* 1 = load ramdisk, 0 = don't load */
73 extern int rd_prompt
; /* 1 = prompt for ramdisk, 0 = don't prompt */
74 extern int rd_image_start
; /* starting block # of image */
77 extern char saved_command_line
[256];
79 extern unsigned long find_available_memory(void);
80 extern void m8xx_cpm_reset(uint
);
82 void __init
adbdev_init(void)
90 extern char cmd_line
[];
92 cpm_page
= (int) alloc_bootmem_pages(PAGE_SIZE
);
94 printk("Boot arguments: %s\n", cmd_line
);
96 /* Reset the Communication Processor Module.
98 m8xx_cpm_reset(cpm_page
);
101 ROOT_DEV
= to_kdev_t(0x0301); /* hda1 */
104 #ifdef CONFIG_BLK_DEV_INITRD
106 ROOT_DEV
= to_kdev_t(0x0200); /* floppy */
111 #if 0 /* XXX this may need to be updated for the new bootmem stuff,
112 or possibly just deleted (see set_phys_avail() in init.c).
114 /* initrd_start and size are setup by boot/head.S and kernel/head.S */
117 if (initrd_end
> *memory_end_p
)
119 printk("initrd extends beyond end of memory "
120 "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
121 initrd_end
,*memory_end_p
);
135 machine_restart(NULL
);
138 /* A place holder for time base interrupts, if they are ever enabled.
140 void timebase_interrupt(int irq
, void * dev
, struct pt_regs
* regs
)
142 printk("timebase_interrupt()\n");
145 /* The decrementer counts at the system (internal) clock frequency divided by
146 * sixteen, or external oscillator divided by four. We force the processor
147 * to use system clock divided by sixteen.
149 void __init
m8xx_calibrate_decr(void)
151 bd_t
*binfo
= (bd_t
*)__res
;
152 int freq
, fp
, divisor
;
156 ((volatile immap_t
*)IMAP_ADDR
)->im_clkrstk
.cark_sccrk
= ~KAPWR_KEY
;
157 ((volatile immap_t
*)IMAP_ADDR
)->im_clkrstk
.cark_sccrk
= KAPWR_KEY
;
159 /* Force all 8xx processors to use divide by 16 processor clock.
161 ((volatile immap_t
*)IMAP_ADDR
)->im_clkrst
.car_sccr
|= 0x02000000;
163 /* Processor frequency is MHz.
164 * The value 'fp' is the number of decrementer ticks per second.
166 fp
= (binfo
->bi_intfreq
* 1000000) / 16;
167 freq
= fp
*60; /* try to make freq/1e6 an integer */
169 printk("time_init: decrementer frequency = %d/%d\n", freq
, divisor
);
170 tb_ticks_per_jiffy
= freq
/ HZ
/ divisor
;
171 tb_to_us
= mulhwu_scale_factor(freq
/ divisor
, 1000000);
173 /* Perform some more timer/timebase initialization. This used
174 * to be done elsewhere, but other changes caused it to get
175 * called more than once....that is a bad thing.
177 * First, unlock all of the registers we are going to modify.
178 * To protect them from corruption during power down, registers
179 * that are maintained by keep alive power are "locked". To
180 * modify these registers we have to write the key value to
181 * the key location associated with the register.
182 * Some boards power up with these unlocked, while others
183 * are locked. Writing anything (including the unlock code?)
184 * to the unlocked registers will lock them again. So, here
185 * we guarantee the registers are locked, then we unlock them
188 ((volatile immap_t
*)IMAP_ADDR
)->im_sitk
.sitk_tbscrk
= ~KAPWR_KEY
;
189 ((volatile immap_t
*)IMAP_ADDR
)->im_sitk
.sitk_rtcsck
= ~KAPWR_KEY
;
190 ((volatile immap_t
*)IMAP_ADDR
)->im_sitk
.sitk_tbk
= ~KAPWR_KEY
;
191 ((volatile immap_t
*)IMAP_ADDR
)->im_sitk
.sitk_tbscrk
= KAPWR_KEY
;
192 ((volatile immap_t
*)IMAP_ADDR
)->im_sitk
.sitk_rtcsck
= KAPWR_KEY
;
193 ((volatile immap_t
*)IMAP_ADDR
)->im_sitk
.sitk_tbk
= KAPWR_KEY
;
195 /* Disable the RTC one second and alarm interrupts.
197 ((volatile immap_t
*)IMAP_ADDR
)->im_sit
.sit_rtcsc
&=
198 ~(RTCSC_SIE
| RTCSC_ALE
);
200 /* Enabling the decrementer also enables the timebase interrupts
201 * (or from the other point of view, to get decrementer interrupts
202 * we have to enable the timebase). The decrementer interrupt
203 * is wired into the vector table, nothing to do here for that.
205 ((volatile immap_t
*)IMAP_ADDR
)->im_sit
.sit_tbscr
=
206 ((mk_int_int_mask(DEC_INTERRUPT
) << 8) |
207 (TBSCR_TBF
| TBSCR_TBE
));
209 if (request_8xxirq(DEC_INTERRUPT
, timebase_interrupt
, 0, "tbint", NULL
) != 0)
210 panic("Could not allocate timer IRQ!");
213 /* The RTC on the MPC8xx is an internal register.
214 * We want to protect this during power down, so we need to unlock,
215 * modify, and re-lock.
218 m8xx_set_rtc_time(unsigned long time
)
220 ((volatile immap_t
*)IMAP_ADDR
)->im_sitk
.sitk_rtck
= KAPWR_KEY
;
221 ((volatile immap_t
*)IMAP_ADDR
)->im_sit
.sit_rtc
= time
;
222 ((volatile immap_t
*)IMAP_ADDR
)->im_sitk
.sitk_rtck
= ~KAPWR_KEY
;
227 m8xx_get_rtc_time(void)
229 /* Get time from the RTC.
231 return((unsigned long)(((immap_t
*)IMAP_ADDR
)->im_sit
.sit_rtc
));
235 m8xx_restart(char *cmd
)
237 extern void m8xx_gorom(void);
255 int m8xx_setup_residual(char *buffer
)
262 len
+= sprintf(len
+buffer
,"clock\t\t: %dMHz\n"
263 "bus clock\t: %dMHz\n",
264 bp
->bi_intfreq
/*/ 1000000*/,
265 bp
->bi_busfreq
/*/ 1000000*/);
270 /* Initialize the internal interrupt controller. The number of
271 * interrupts supported can vary with the processor type, and the
272 * 82xx family can have up to 64.
273 * External interrupts can be either edge or level triggered, and
274 * need to be initialized by the appropriate driver.
280 void cpm_interrupt_init(void);
282 for ( i
= 0 ; i
< NR_SIU_INTS
; i
++ )
283 irq_desc
[i
].handler
= &ppc8xx_pic
;
285 /* We could probably incorporate the CPM into the multilevel
286 * interrupt structure.
288 cpm_interrupt_init();
289 unmask_irq(CPM_INTERRUPT
);
291 #if defined(CONFIG_PCI)
292 for ( i
= NR_SIU_INTS
; i
< (NR_SIU_INTS
+ NR_8259_INTS
) ; i
++ )
293 irq_desc
[i
].handler
= &i8259_pic
;
294 i8259_pic
.irq_offset
= NR_SIU_INTS
;
296 request_8xxirq(ISA_BRIDGE_INT
, mbx_i8259_action
, 0, "8259 cascade", NULL
);
297 enable_irq(ISA_BRIDGE_INT
);
301 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
303 /* Define this to make a PCMCIA ATA Flash card work.
311 m8xx_ide_insw(ide_ioreg_t port
, void *buf
, int ns
)
314 ide_insw(port
, buf
, ns
);
316 ide_insw(port
+_IO_BASE
, buf
, ns
);
321 m8xx_ide_outsw(ide_ioreg_t port
, void *buf
, int ns
)
324 ide_outsw(port
, buf
, ns
);
326 ide_outsw(port
+_IO_BASE
, buf
, ns
);
331 m8xx_ide_default_irq(ide_ioreg_t base
)
334 return PCMCIA_INTERRUPT
;
341 m8xx_ide_default_io_base(int index
)
347 m8xx_ide_check_region(ide_ioreg_t from
, unsigned int extent
)
353 m8xx_ide_request_region(ide_ioreg_t from
,
360 m8xx_ide_release_region(ide_ioreg_t from
,
366 m8xx_ide_request_irq(unsigned int irq
,
367 void (*handler
)(int, void *, struct pt_regs
*),
373 return request_8xxirq(irq
, handler
, flags
, device
, dev_id
);
375 return request_irq(irq
, handler
, flags
, device
, dev_id
);
380 m8xx_ide_fix_driveid(struct hd_driveid
*id
)
382 ppc_generic_ide_fix_driveid(id
);
385 /* We can use an external IDE controller or wire the IDE interface to
386 * the internal PCMCIA controller.
388 void __init
m8xx_ide_init_hwif_ports(ide_ioreg_t
*p
, ide_ioreg_t base
, int *irq
)
390 ide_ioreg_t port
= base
;
393 volatile pcmconf8xx_t
*pcmp
;
400 if (base
!= 0) /* Only map the first ATA flash drive */
403 pcmp
= (pcmconf8xx_t
*)(&(((immap_t
*)IMAP_ADDR
)->im_pcmcia
));
404 if (pcmp
->pcmc_pipr
& 0x18000000)
405 return; /* No card in slot */
407 base
= (unsigned long) ioremap(PCMCIA_MEM_ADDR
, 0x200);
409 /* For the M-Systems ATA card, the first 8 registers map 1:1.
410 * The following register, control/Altstatus, is located at 0x0e.
411 * Following that, the irq offset, is not used, so we place it in
412 * an unused location, 0x0a.
415 for (i
= 1; i
< 8; ++i
)
417 *p
++ = base
+ 0x0e; /* control/altstatus */
418 *p
= base
+ 0x0a; /* IRQ, not used */
420 *irq
= PCMCIA_INTERRUPT
;
422 /* Configure the interface for this interrupt.
424 pcmp
->pcmc_pgcra
= (mk_int_int_mask(PCMCIA_INTERRUPT
) << 24) |
425 (mk_int_int_mask(PCMCIA_INTERRUPT
) << 16);
427 /* Enable status change interrupt from slot A.
429 pcmp
->pcmc_per
= 0xff100000;
430 pcmp
->pcmc_pscr
= ~0;
433 /* Just a regular IDE drive on some I/O port.
446 m8xx_init(unsigned long r3
, unsigned long r4
, unsigned long r5
,
447 unsigned long r6
, unsigned long r7
)
451 memcpy( (void *)__res
,(void *)(r3
+KERNELBASE
), sizeof(bd_t
) );
454 m8xx_setup_pci_ptrs();
457 #ifdef CONFIG_BLK_DEV_INITRD
458 /* take care of initrd if we have one */
461 initrd_start
= r4
+ KERNELBASE
;
462 initrd_end
= r5
+ KERNELBASE
;
464 #endif /* CONFIG_BLK_DEV_INITRD */
465 /* take care of cmd line */
469 *(char *)(r7
+KERNELBASE
) = 0;
470 strcpy(cmd_line
, (char *)(r6
+KERNELBASE
));
473 ppc_md
.setup_arch
= m8xx_setup_arch
;
474 ppc_md
.setup_residual
= m8xx_setup_residual
;
475 ppc_md
.get_cpuinfo
= NULL
;
476 ppc_md
.irq_cannonicalize
= NULL
;
477 ppc_md
.init_IRQ
= m8xx_init_IRQ
;
478 ppc_md
.get_irq
= m8xx_get_irq
;
481 ppc_md
.restart
= m8xx_restart
;
482 ppc_md
.power_off
= m8xx_power_off
;
483 ppc_md
.halt
= m8xx_halt
;
485 ppc_md
.time_init
= NULL
;
486 ppc_md
.set_rtc_time
= m8xx_set_rtc_time
;
487 ppc_md
.get_rtc_time
= m8xx_get_rtc_time
;
488 ppc_md
.calibrate_decr
= m8xx_calibrate_decr
;
491 ppc_md
.kbd_setkeycode
= pckbd_setkeycode
;
492 ppc_md
.kbd_getkeycode
= pckbd_getkeycode
;
493 ppc_md
.kbd_pretranslate
= pckbd_pretranslate
;
494 ppc_md
.kbd_translate
= pckbd_translate
;
495 ppc_md
.kbd_unexpected_up
= pckbd_unexpected_up
;
496 ppc_md
.kbd_leds
= pckbd_leds
;
497 ppc_md
.kbd_init_hw
= pckbd_init_hw
;
498 #ifdef CONFIG_MAGIC_SYSRQ
499 ppc_md
.kbd_sysrq_xlate
= pckbd_sysrq_xlate
;
502 ppc_md
.kbd_setkeycode
= NULL
;
503 ppc_md
.kbd_getkeycode
= NULL
;
504 ppc_md
.kbd_translate
= NULL
;
505 ppc_md
.kbd_unexpected_up
= NULL
;
506 ppc_md
.kbd_leds
= NULL
;
507 ppc_md
.kbd_init_hw
= NULL
;
508 #ifdef CONFIG_MAGIC_SYSRQ
509 ppc_md
.kbd_sysrq_xlate
= NULL
;
513 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
514 ppc_ide_md
.insw
= m8xx_ide_insw
;
515 ppc_ide_md
.outsw
= m8xx_ide_outsw
;
516 ppc_ide_md
.default_irq
= m8xx_ide_default_irq
;
517 ppc_ide_md
.default_io_base
= m8xx_ide_default_io_base
;
518 ppc_ide_md
.check_region
= m8xx_ide_check_region
;
519 ppc_ide_md
.request_region
= m8xx_ide_request_region
;
520 ppc_ide_md
.release_region
= m8xx_ide_release_region
;
521 ppc_ide_md
.fix_driveid
= m8xx_ide_fix_driveid
;
522 ppc_ide_md
.ide_init_hwif
= m8xx_ide_init_hwif_ports
;
523 ppc_ide_md
.ide_request_irq
= m8xx_ide_request_irq
;
525 ppc_ide_md
.io_base
= _IO_BASE
;