1/* 2 * 3 * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu> 4 * 5 * Copyright 2000-2001 MontaVista Software Inc. 6 * Completed implementation. 7 * Author: MontaVista Software, Inc. <source@mvista.com> 8 * Frank Rowand <frank_rowand@mvista.com> 9 * Debbie Chu <debbie_chu@mvista.com> 10 * Further modifications by Armin Kuster 11 * 12 * Module name: ppc4xx_setup.c 13 * 14 */ 15 16#include <linux/init.h> 17#include <linux/smp.h> 18#include <linux/threads.h> 19#include <linux/spinlock.h> 20#include <linux/reboot.h> 21#include <linux/param.h> 22#include <linux/string.h> 23#include <linux/initrd.h> 24#include <linux/pci.h> 25#include <linux/rtc.h> 26#include <linux/console.h> 27#include <linux/ide.h> 28#include <linux/serial_reg.h> 29#include <linux/seq_file.h> 30 31#include <asm/system.h> 32#include <asm/processor.h> 33#include <asm/machdep.h> 34#include <asm/page.h> 35#include <asm/kgdb.h> 36#include <asm/ibm4xx.h> 37#include <asm/time.h> 38#include <asm/todc.h> 39#include <asm/ppc4xx_pic.h> 40#include <asm/pci-bridge.h> 41#include <asm/bootinfo.h> 42 43#include <syslib/gen550.h> 44 45/* Function Prototypes */ 46extern void abort(void); 47extern void ppc4xx_find_bridges(void); 48 49/* Global Variables */ 50bd_t __res; 51 52void __init 53ppc4xx_setup_arch(void) 54{ 55#if !defined(CONFIG_BDI_SWITCH) 56 /* 57 * The Abatron BDI JTAG debugger does not tolerate others 58 * mucking with the debug registers. 59 */ 60 mtspr(SPRN_DBCR0, (DBCR0_IDM)); 61 mtspr(SPRN_DBSR, 0xffffffff); 62#endif 63 64 /* Setup PCI host bridges */ 65#ifdef CONFIG_PCI 66 ppc4xx_find_bridges(); 67#endif 68} 69 70/* 71 * This routine pretty-prints the platform's internal CPU clock 72 * frequencies into the buffer for usage in /proc/cpuinfo. 73 */ 74 75static int 76ppc4xx_show_percpuinfo(struct seq_file *m, int i) 77{ 78 seq_printf(m, "clock\t\t: %ldMHz\n", (long)__res.bi_intfreq / 1000000); 79 80 return 0; 81} 82 83/* 84 * This routine pretty-prints the platform's internal bus clock 85 * frequencies into the buffer for usage in /proc/cpuinfo. 86 */ 87static int 88ppc4xx_show_cpuinfo(struct seq_file *m) 89{ 90 bd_t *bip = &__res; 91 92 seq_printf(m, "machine\t\t: %s\n", PPC4xx_MACHINE_NAME); 93 seq_printf(m, "plb bus clock\t: %ldMHz\n", 94 (long) bip->bi_busfreq / 1000000); 95#ifdef CONFIG_PCI 96 seq_printf(m, "pci bus clock\t: %dMHz\n", 97 bip->bi_pci_busfreq / 1000000); 98#endif 99 100 return 0; 101} 102 103/* 104 * Return the virtual address representing the top of physical RAM. 105 */ 106static unsigned long __init 107ppc4xx_find_end_of_memory(void) 108{ 109 return ((unsigned long) __res.bi_memsize); 110} 111 112void __init 113ppc4xx_map_io(void) 114{ 115 io_block_mapping(PPC4xx_ONB_IO_VADDR, 116 PPC4xx_ONB_IO_PADDR, PPC4xx_ONB_IO_SIZE, _PAGE_IO); 117#ifdef CONFIG_PCI 118 io_block_mapping(PPC4xx_PCI_IO_VADDR, 119 PPC4xx_PCI_IO_PADDR, PPC4xx_PCI_IO_SIZE, _PAGE_IO); 120 io_block_mapping(PPC4xx_PCI_CFG_VADDR, 121 PPC4xx_PCI_CFG_PADDR, PPC4xx_PCI_CFG_SIZE, _PAGE_IO); 122 io_block_mapping(PPC4xx_PCI_LCFG_VADDR, 123 PPC4xx_PCI_LCFG_PADDR, PPC4xx_PCI_LCFG_SIZE, _PAGE_IO); 124#endif 125} 126 127void __init 128ppc4xx_init_IRQ(void) 129{ 130 ppc4xx_pic_init(); 131} 132 133static void 134ppc4xx_restart(char *cmd) 135{ 136 printk("%s\n", cmd); 137 abort(); 138} 139 140static void 141ppc4xx_power_off(void) 142{ 143 printk("System Halted\n"); 144 local_irq_disable(); 145 while (1) ; 146} 147 148static void 149ppc4xx_halt(void) 150{ 151 printk("System Halted\n"); 152 local_irq_disable(); 153 while (1) ; 154} 155 156/* 157 * This routine retrieves the internal processor frequency from the board 158 * information structure, sets up the kernel timer decrementer based on 159 * that value, enables the 4xx programmable interval timer (PIT) and sets 160 * it up for auto-reload. 161 */ 162static void __init 163ppc4xx_calibrate_decr(void) 164{ 165 unsigned int freq; 166 bd_t *bip = &__res; 167 168#if defined(CONFIG_WALNUT) || defined(CONFIG_SYCAMORE) 169 /* Walnut boot rom sets DCR CHCR1 (aka CPC0_CR1) bit CETE to 1 */ 170 mtdcr(DCRN_CHCR1, mfdcr(DCRN_CHCR1) & ~CHR1_CETE); 171#endif 172 freq = bip->bi_tbfreq; 173 tb_ticks_per_jiffy = freq / HZ; 174 tb_to_us = mulhwu_scale_factor(freq, 1000000); 175 176 /* Set the time base to zero. 177 ** At 200 Mhz, time base will rollover in ~2925 years. 178 */ 179 180 mtspr(SPRN_TBWL, 0); 181 mtspr(SPRN_TBWU, 0); 182 183 /* Clear any pending timer interrupts */ 184 185 mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS); 186 mtspr(SPRN_TCR, TCR_PIE | TCR_ARE); 187 188 /* Set the PIT reload value and just let it run. */ 189 mtspr(SPRN_PIT, tb_ticks_per_jiffy); 190} 191 192/* 193 * IDE stuff. 194 * should be generic for every IDE PCI chipset 195 */ 196#if defined(CONFIG_PCI) && defined(CONFIG_IDE) 197static void 198ppc4xx_ide_init_hwif_ports(hw_regs_t * hw, unsigned long data_port, 199 unsigned long ctrl_port, int *irq) 200{ 201 int i; 202 203 for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i) 204 hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET; 205 206 hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; 207} 208#endif /* defined(CONFIG_PCI) && defined(CONFIG_IDE) */ 209 210TODC_ALLOC(); 211 212/* 213 * Input(s): 214 * r3 - Optional pointer to a board information structure. 215 * r4 - Optional pointer to the physical starting address of the init RAM 216 * disk. 217 * r5 - Optional pointer to the physical ending address of the init RAM 218 * disk. 219 * r6 - Optional pointer to the physical starting address of any kernel 220 * command-line parameters. 221 * r7 - Optional pointer to the physical ending address of any kernel 222 * command-line parameters. 223 */ 224void __init 225ppc4xx_init(unsigned long r3, unsigned long r4, unsigned long r5, 226 unsigned long r6, unsigned long r7) 227{ 228 parse_bootinfo(find_bootinfo()); 229 230 /* 231 * If we were passed in a board information, copy it into the 232 * residual data area. 233 */ 234 if (r3) 235 __res = *(bd_t *)(r3 + KERNELBASE); 236 237#if defined(CONFIG_BLK_DEV_INITRD) 238 /* 239 * If the init RAM disk has been configured in, and there's a valid 240 * starting address for it, set it up. 241 */ 242 if (r4) { 243 initrd_start = r4 + KERNELBASE; 244 initrd_end = r5 + KERNELBASE; 245 } 246#endif /* CONFIG_BLK_DEV_INITRD */ 247 248 /* Copy the kernel command line arguments to a safe place. */ 249 250 if (r6) { 251 *(char *) (r7 + KERNELBASE) = 0; 252 strcpy(cmd_line, (char *) (r6 + KERNELBASE)); 253 } 254 255 /* Initialize machine-dependent vectors */ 256 257 ppc_md.setup_arch = ppc4xx_setup_arch; 258 ppc_md.show_percpuinfo = ppc4xx_show_percpuinfo; 259 ppc_md.show_cpuinfo = ppc4xx_show_cpuinfo; 260 ppc_md.init_IRQ = ppc4xx_init_IRQ; 261 262 ppc_md.restart = ppc4xx_restart; 263 ppc_md.power_off = ppc4xx_power_off; 264 ppc_md.halt = ppc4xx_halt; 265 266 ppc_md.calibrate_decr = ppc4xx_calibrate_decr; 267 268 ppc_md.find_end_of_memory = ppc4xx_find_end_of_memory; 269 ppc_md.setup_io_mappings = ppc4xx_map_io; 270 271#ifdef CONFIG_SERIAL_TEXT_DEBUG 272 ppc_md.progress = gen550_progress; 273#endif 274 275#if defined(CONFIG_PCI) && defined(CONFIG_IDE) 276 ppc_ide_md.ide_init_hwif = ppc4xx_ide_init_hwif_ports; 277#endif /* defined(CONFIG_PCI) && defined(CONFIG_IDE) */ 278} 279 280/* Called from machine_check_exception */ 281void platform_machine_check(struct pt_regs *regs) 282{ 283#if defined(DCRN_PLB0_BEAR) 284 printk("PLB0: BEAR= 0x%08x ACR= 0x%08x BESR= 0x%08x\n", 285 mfdcr(DCRN_PLB0_BEAR), mfdcr(DCRN_PLB0_ACR), 286 mfdcr(DCRN_PLB0_BESR)); 287#endif 288#if defined(DCRN_POB0_BEAR) 289 printk("PLB0 to OPB: BEAR= 0x%08x BESR0= 0x%08x BESR1= 0x%08x\n", 290 mfdcr(DCRN_POB0_BEAR), mfdcr(DCRN_POB0_BESR0), 291 mfdcr(DCRN_POB0_BESR1)); 292#endif 293 294} 295