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
);
133 extern void xmon(void *);
136 machine_restart(NULL
);
139 /* The decrementer counts at the system (internal) clock frequency divided by
140 * sixteen, or external oscillator divided by four. We force the processor
141 * to use system clock divided by sixteen.
143 void __init
m8xx_calibrate_decr(void)
145 bd_t
*binfo
= (bd_t
*)__res
;
146 int freq
, fp
, divisor
;
150 ((volatile immap_t
*)IMAP_ADDR
)->im_clkrstk
.cark_sccrk
= ~KAPWR_KEY
;
151 ((volatile immap_t
*)IMAP_ADDR
)->im_clkrstk
.cark_sccrk
= KAPWR_KEY
;
153 /* Force all 8xx processors to use divide by 16 processor clock.
155 ((volatile immap_t
*)IMAP_ADDR
)->im_clkrst
.car_sccr
|= 0x02000000;
157 /* Processor frequency is MHz.
158 * The value 'fp' is the number of decrementer ticks per second.
160 fp
= (binfo
->bi_intfreq
* 1000000) / 16;
161 freq
= fp
*60; /* try to make freq/1e6 an integer */
163 printk("time_init: decrementer frequency = %d/%d\n", freq
, divisor
);
164 decrementer_count
= freq
/ HZ
/ divisor
;
165 count_period_num
= divisor
;
166 count_period_den
= freq
/ 1000000;
169 /* A place holder for time base interrupts, if they are ever enabled.
171 void timebase_interrupt(int irq
, void * dev
, struct pt_regs
* regs
)
173 printk("timebase_interrupt()\n");
176 /* The RTC on the MPC8xx is an internal register.
177 * We want to protect this during power down, so we need to unlock,
178 * modify, and re-lock.
181 m8xx_set_rtc_time(unsigned long time
)
183 ((volatile immap_t
*)IMAP_ADDR
)->im_sitk
.sitk_rtck
= KAPWR_KEY
;
184 ((volatile immap_t
*)IMAP_ADDR
)->im_sit
.sit_rtc
= time
;
185 ((volatile immap_t
*)IMAP_ADDR
)->im_sitk
.sitk_rtck
= ~KAPWR_KEY
;
190 m8xx_get_rtc_time(void)
192 /* First, unlock all of the registers we are going to modify.
193 * To protect them from corruption during power down, registers
194 * that are maintained by keep alive power are "locked". To
195 * modify these registers we have to write the key value to
196 * the key location associated with the register.
197 * Some boards power up with these unlocked, while others
198 * are locked. Writing anything (including the unlock code?)
199 * to the unlocked registers will lock them again. So, here
200 * we guarantee the registers are locked, then we unlock them
203 ((volatile immap_t
*)IMAP_ADDR
)->im_sitk
.sitk_tbscrk
= ~KAPWR_KEY
;
204 ((volatile immap_t
*)IMAP_ADDR
)->im_sitk
.sitk_rtcsck
= ~KAPWR_KEY
;
205 ((volatile immap_t
*)IMAP_ADDR
)->im_sitk
.sitk_tbk
= ~KAPWR_KEY
;
206 ((volatile immap_t
*)IMAP_ADDR
)->im_sitk
.sitk_tbscrk
= KAPWR_KEY
;
207 ((volatile immap_t
*)IMAP_ADDR
)->im_sitk
.sitk_rtcsck
= KAPWR_KEY
;
208 ((volatile immap_t
*)IMAP_ADDR
)->im_sitk
.sitk_tbk
= KAPWR_KEY
;
210 /* Disable the RTC one second and alarm interrupts.
212 ((volatile immap_t
*)IMAP_ADDR
)->im_sit
.sit_rtcsc
&=
213 ~(RTCSC_SIE
| RTCSC_ALE
);
215 /* Enabling the decrementer also enables the timebase interrupts
216 * (or from the other point of view, to get decrementer interrupts
217 * we have to enable the timebase). The decrementer interrupt
218 * is wired into the vector table, nothing to do here for that.
220 ((volatile immap_t
*)IMAP_ADDR
)->im_sit
.sit_tbscr
=
221 ((mk_int_int_mask(DEC_INTERRUPT
) << 8) |
222 (TBSCR_TBF
| TBSCR_TBE
));
223 if (request_8xxirq(DEC_INTERRUPT
, timebase_interrupt
, 0, "tbint", NULL
) != 0)
224 panic("Could not allocate timer IRQ!");
226 /* Get time from the RTC.
228 return((unsigned long)(((immap_t
*)IMAP_ADDR
)->im_sit
.sit_rtc
));
232 m8xx_restart(char *cmd
)
234 extern void m8xx_gorom(void);
252 int m8xx_setup_residual(char *buffer
)
259 len
+= sprintf(len
+buffer
,"clock\t\t: %dMHz\n"
260 "bus clock\t: %dMHz\n",
261 bp
->bi_intfreq
/*/ 1000000*/,
262 bp
->bi_busfreq
/*/ 1000000*/);
267 /* Initialize the internal interrupt controller. The number of
268 * interrupts supported can vary with the processor type, and the
269 * 82xx family can have up to 64.
270 * External interrupts can be either edge or level triggered, and
271 * need to be initialized by the appropriate driver.
277 void cpm_interrupt_init(void);
279 for ( i
= 0 ; i
< NR_SIU_INTS
; i
++ )
280 irq_desc
[i
].handler
= &ppc8xx_pic
;
282 /* We could probably incorporate the CPM into the multilevel
283 * interrupt structure.
285 cpm_interrupt_init();
286 unmask_irq(CPM_INTERRUPT
);
288 #if defined(CONFIG_PCI)
289 for ( i
= NR_SIU_INTS
; i
< (NR_SIU_INTS
+ NR_8259_INTS
) ; i
++ )
290 irq_desc
[i
].handler
= &i8259_pic
;
291 i8259_pic
.irq_offset
= NR_SIU_INTS
;
293 request_8xxirq(ISA_BRIDGE_INT
, mbx_i8259_action
, 0, "8259 cascade", NULL
);
294 enable_irq(ISA_BRIDGE_INT
);
298 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
300 /* Define this to make a PCMCIA ATA Flash card work.
308 m8xx_ide_insw(ide_ioreg_t port
, void *buf
, int ns
)
311 ide_insw(port
, buf
, ns
);
313 ide_insw(port
+_IO_BASE
, buf
, ns
);
318 m8xx_ide_outsw(ide_ioreg_t port
, void *buf
, int ns
)
321 ide_outsw(port
, buf
, ns
);
323 ide_outsw(port
+_IO_BASE
, buf
, ns
);
328 m8xx_ide_default_irq(ide_ioreg_t base
)
331 return PCMCIA_INTERRUPT
;
338 m8xx_ide_default_io_base(int index
)
344 m8xx_ide_check_region(ide_ioreg_t from
, unsigned int extent
)
350 m8xx_ide_request_region(ide_ioreg_t from
,
357 m8xx_ide_release_region(ide_ioreg_t from
,
363 m8xx_ide_request_irq(unsigned int irq
,
364 void (*handler
)(int, void *, struct pt_regs
*),
370 return request_8xxirq(irq
, handler
, flags
, device
, dev_id
);
372 return request_irq(irq
, handler
, flags
, device
, dev_id
);
377 m8xx_ide_fix_driveid(struct hd_driveid
*id
)
379 ppc_generic_ide_fix_driveid(id
);
382 /* We can use an external IDE controller or wire the IDE interface to
383 * the internal PCMCIA controller.
385 void __init
m8xx_ide_init_hwif_ports(ide_ioreg_t
*p
, ide_ioreg_t base
, int *irq
)
387 ide_ioreg_t port
= base
;
390 volatile pcmconf8xx_t
*pcmp
;
397 if (base
!= 0) /* Only map the first ATA flash drive */
400 pcmp
= (pcmconf8xx_t
*)(&(((immap_t
*)IMAP_ADDR
)->im_pcmcia
));
401 if (pcmp
->pcmc_pipr
& 0x18000000)
402 return; /* No card in slot */
404 base
= (unsigned long) ioremap(PCMCIA_MEM_ADDR
, 0x200);
406 /* For the M-Systems ATA card, the first 8 registers map 1:1.
407 * The following register, control/Altstatus, is located at 0x0e.
408 * Following that, the irq offset, is not used, so we place it in
409 * an unused location, 0x0a.
412 for (i
= 1; i
< 8; ++i
)
414 *p
++ = base
+ 0x0e; /* control/altstatus */
415 *p
= base
+ 0x0a; /* IRQ, not used */
417 *irq
= PCMCIA_INTERRUPT
;
419 /* Configure the interface for this interrupt.
421 pcmp
->pcmc_pgcra
= (mk_int_int_mask(PCMCIA_INTERRUPT
) << 24) |
422 (mk_int_int_mask(PCMCIA_INTERRUPT
) << 16);
424 /* Enable status change interrupt from slot A.
426 pcmp
->pcmc_per
= 0xff100000;
427 pcmp
->pcmc_pscr
= ~0;
430 /* Just a regular IDE drive on some I/O port.
443 m8xx_init(unsigned long r3
, unsigned long r4
, unsigned long r5
,
444 unsigned long r6
, unsigned long r7
)
448 memcpy( (void *)__res
,(void *)(r3
+KERNELBASE
), sizeof(bd_t
) );
451 m8xx_setup_pci_ptrs();
454 #ifdef CONFIG_BLK_DEV_INITRD
455 /* take care of initrd if we have one */
458 initrd_start
= r4
+ KERNELBASE
;
459 initrd_end
= r5
+ KERNELBASE
;
461 #endif /* CONFIG_BLK_DEV_INITRD */
462 /* take care of cmd line */
466 *(char *)(r7
+KERNELBASE
) = 0;
467 strcpy(cmd_line
, (char *)(r6
+KERNELBASE
));
470 ppc_md
.setup_arch
= m8xx_setup_arch
;
471 ppc_md
.setup_residual
= m8xx_setup_residual
;
472 ppc_md
.get_cpuinfo
= NULL
;
473 ppc_md
.irq_cannonicalize
= NULL
;
474 ppc_md
.init_IRQ
= m8xx_init_IRQ
;
475 ppc_md
.get_irq
= m8xx_get_irq
;
478 ppc_md
.restart
= m8xx_restart
;
479 ppc_md
.power_off
= m8xx_power_off
;
480 ppc_md
.halt
= m8xx_halt
;
482 ppc_md
.time_init
= NULL
;
483 ppc_md
.set_rtc_time
= m8xx_set_rtc_time
;
484 ppc_md
.get_rtc_time
= m8xx_get_rtc_time
;
485 ppc_md
.calibrate_decr
= m8xx_calibrate_decr
;
488 ppc_md
.kbd_setkeycode
= pckbd_setkeycode
;
489 ppc_md
.kbd_getkeycode
= pckbd_getkeycode
;
490 ppc_md
.kbd_pretranslate
= pckbd_pretranslate
;
491 ppc_md
.kbd_translate
= pckbd_translate
;
492 ppc_md
.kbd_unexpected_up
= pckbd_unexpected_up
;
493 ppc_md
.kbd_leds
= pckbd_leds
;
494 ppc_md
.kbd_init_hw
= pckbd_init_hw
;
495 #ifdef CONFIG_MAGIC_SYSRQ
496 ppc_md
.kbd_sysrq_xlate
= pckbd_sysrq_xlate
;
499 ppc_md
.kbd_setkeycode
= NULL
;
500 ppc_md
.kbd_getkeycode
= NULL
;
501 ppc_md
.kbd_translate
= NULL
;
502 ppc_md
.kbd_unexpected_up
= NULL
;
503 ppc_md
.kbd_leds
= NULL
;
504 ppc_md
.kbd_init_hw
= NULL
;
505 #ifdef CONFIG_MAGIC_SYSRQ
506 ppc_md
.kbd_sysrq_xlate
= NULL
;
510 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
511 ppc_ide_md
.insw
= m8xx_ide_insw
;
512 ppc_ide_md
.outsw
= m8xx_ide_outsw
;
513 ppc_ide_md
.default_irq
= m8xx_ide_default_irq
;
514 ppc_ide_md
.default_io_base
= m8xx_ide_default_io_base
;
515 ppc_ide_md
.check_region
= m8xx_ide_check_region
;
516 ppc_ide_md
.request_region
= m8xx_ide_request_region
;
517 ppc_ide_md
.release_region
= m8xx_ide_release_region
;
518 ppc_ide_md
.fix_driveid
= m8xx_ide_fix_driveid
;
519 ppc_ide_md
.ide_init_hwif
= m8xx_ide_init_hwif_ports
;
520 ppc_ide_md
.ide_request_irq
= m8xx_ide_request_irq
;
522 ppc_ide_md
.io_base
= _IO_BASE
;