1/* 2 * Board setup routines for Force PowerPMC-250 Processor PMC 3 * 4 * Author: Troy Benjegerdes <tbenjegerdes@mvista.com> 5 * Borrowed heavily from prpmc750_*.c by 6 * Matt Porter <mporter@mvista.com> 7 * 8 * 2001 (c) MontaVista, Software, Inc. This file is licensed under 9 * the terms of the GNU General Public License version 2. This program 10 * is licensed "as is" without any warranty of any kind, whether express 11 * or implied. 12 */ 13 14#include <linux/stddef.h> 15#include <linux/kernel.h> 16#include <linux/init.h> 17#include <linux/errno.h> 18#include <linux/reboot.h> 19#include <linux/pci.h> 20#include <linux/kdev_t.h> 21#include <linux/types.h> 22#include <linux/major.h> 23#include <linux/initrd.h> 24#include <linux/console.h> 25#include <linux/delay.h> 26#include <linux/slab.h> 27#include <linux/seq_file.h> 28#include <linux/ide.h> 29#include <linux/root_dev.h> 30 31#include <asm/byteorder.h> 32#include <asm/system.h> 33#include <asm/pgtable.h> 34#include <asm/page.h> 35#include <asm/dma.h> 36#include <asm/io.h> 37#include <asm/irq.h> 38#include <asm/machdep.h> 39#include <asm/time.h> 40#include <platforms/powerpmc250.h> 41#include <asm/open_pic.h> 42#include <asm/pci-bridge.h> 43#include <asm/mpc10x.h> 44#include <asm/uaccess.h> 45#include <asm/bootinfo.h> 46 47extern void powerpmc250_find_bridges(void); 48extern unsigned long loops_per_jiffy; 49 50static u_char powerpmc250_openpic_initsenses[] __initdata = 51{ 52 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53 1, /* PMC INTA (also MPC107 output interrupt INTA) */ 54 1, /* PMC INTB (also I82559 Ethernet controller) */ 55 1, /* PMC INTC */ 56 1, /* PMC INTD */ 57 0, /* DUART interrupt (active high) */ 58}; 59 60static int 61powerpmc250_show_cpuinfo(struct seq_file *m) 62{ 63 seq_printf(m,"machine\t\t: Force PowerPMC250\n"); 64 65 return 0; 66} 67 68static void __init 69powerpmc250_setup_arch(void) 70{ 71 /* init to some ~sane value until calibrate_delay() runs */ 72 loops_per_jiffy = 50000000/HZ; 73 74 /* Lookup PCI host bridges */ 75 powerpmc250_find_bridges(); 76 77#ifdef CONFIG_BLK_DEV_INITRD 78 if (initrd_start) 79 ROOT_DEV = Root_RAM0; 80 else 81#endif 82#ifdef CONFIG_ROOT_NFS 83 ROOT_DEV = Root_NFS; 84#else 85 ROOT_DEV = Root_SDA2; 86#endif 87 88 printk("Force PowerPMC250 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n"); 89} 90 91 92static void __init 93powerpmc250_calibrate_decr(void) 94{ 95 unsigned long freq; 96 int divisor = 4; 97 98 //freq = powerpmc250_get_bus_speed(); 99#warning hardcoded bus freq 100 freq = 100000000; 101 102 tb_ticks_per_jiffy = freq / (HZ * divisor); 103 tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000); 104} 105 106static void 107powerpmc250_restart(char *cmd) 108{ 109 local_irq_disable(); 110 /* Hard reset */ 111 writeb(0x11, 0xfe000332); 112 while(1); 113} 114 115static void 116powerpmc250_halt(void) 117{ 118 local_irq_disable(); 119 while (1); 120} 121 122static void 123powerpmc250_power_off(void) 124{ 125 powerpmc250_halt(); 126} 127 128static void __init 129powerpmc250_init_IRQ(void) 130{ 131 132 OpenPIC_InitSenses = powerpmc250_openpic_initsenses; 133 OpenPIC_NumInitSenses = sizeof(powerpmc250_openpic_initsenses); 134 mpc10x_set_openpic(); 135} 136 137/* 138 * Set BAT 3 to map 0xf0000000 to end of physical memory space. 139 */ 140static __inline__ void 141powerpmc250_set_bat(void) 142{ 143 unsigned long bat3u, bat3l; 144 static int mapping_set = 0; 145 146 if (!mapping_set) 147 { 148 __asm__ __volatile__( 149 " lis %0,0xf000\n \ 150 ori %1,%0,0x002a\n \ 151 ori %0,%0,0x1ffe\n \ 152 mtspr 0x21e,%0\n \ 153 mtspr 0x21f,%1\n \ 154 isync\n \ 155 sync " 156 : "=r" (bat3u), "=r" (bat3l)); 157 158 mapping_set = 1; 159 } 160 return; 161} 162 163static unsigned long __init 164powerpmc250_find_end_of_memory(void) 165{ 166 /* Cover I/O space with a BAT */ 167 /* yuck, better hope your ram size is a power of 2 -- paulus */ 168 powerpmc250_set_bat(); 169 170 return mpc10x_get_mem_size(MPC10X_MEM_MAP_B); 171} 172 173static void __init 174powerpmc250_map_io(void) 175{ 176 io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO); 177} 178 179void __init 180platform_init(unsigned long r3, unsigned long r4, unsigned long r5, 181 unsigned long r6, unsigned long r7) 182{ 183 parse_bootinfo(find_bootinfo()); 184 185#ifdef CONFIG_BLK_DEV_INITRD 186 if ( r4 ) 187 { 188 initrd_start = r4 + KERNELBASE; 189 initrd_end = r5 + KERNELBASE; 190 } 191#endif 192 193 /* Copy cmd_line parameters */ 194 if ( r6) 195 { 196 *(char *)(r7 + KERNELBASE) = 0; 197 strcpy(cmd_line, (char *)(r6 + KERNELBASE)); 198 } 199 200 isa_io_base = MPC10X_MAPB_ISA_IO_BASE; 201 isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE; 202 pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET; 203 204 ppc_md.setup_arch = powerpmc250_setup_arch; 205 ppc_md.show_cpuinfo = powerpmc250_show_cpuinfo; 206 ppc_md.init_IRQ = powerpmc250_init_IRQ; 207 ppc_md.get_irq = openpic_get_irq; 208 209 ppc_md.find_end_of_memory = powerpmc250_find_end_of_memory; 210 ppc_md.setup_io_mappings = powerpmc250_map_io; 211 212 ppc_md.restart = powerpmc250_restart; 213 ppc_md.power_off = powerpmc250_power_off; 214 ppc_md.halt = powerpmc250_halt; 215 216 /* PowerPMC250 has no timekeeper part */ 217 ppc_md.time_init = NULL; 218 ppc_md.get_rtc_time = NULL; 219 ppc_md.set_rtc_time = NULL; 220 ppc_md.calibrate_decr = powerpmc250_calibrate_decr; 221} 222 223 224/* 225 * (This used to be arch/ppc/platforms/powerpmc250_pci.c) 226 * 227 * PCI support for Force PowerPMC250 228 * 229 */ 230 231#undef DEBUG 232#ifdef DEBUG 233#define DBG(x...) printk(x) 234#else 235#define DBG(x...) 236#endif /* DEBUG */ 237 238static inline int __init 239powerpmc250_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) 240{ 241 static char pci_irq_table[][4] = 242 /* 243 * PCI IDSEL/INTPIN->INTLINE 244 * A B C D 245 */ 246 { 247 {17, 0, 0, 0}, /* Device 11 - 82559 */ 248 {0, 0, 0, 0}, /* 12 */ 249 {0, 0, 0, 0}, /* 13 */ 250 {0, 0, 0, 0}, /* 14 */ 251 {0, 0, 0, 0}, /* 15 */ 252 {16, 17, 18, 19}, /* Device 16 - PMC A1?? */ 253 }; 254 const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4; 255 return PCI_IRQ_TABLE_LOOKUP; 256}; 257 258static int 259powerpmc250_exclude_device(u_char bus, u_char devfn) 260{ 261 262 if ((bus == 0) && (PCI_SLOT(devfn) == 13 || PCI_SLOT(devfn) == 14)) { 263 return PCIBIOS_DEVICE_NOT_FOUND; 264 } 265 else { 266 return PCIBIOS_SUCCESSFUL; 267 } 268} 269 270void __init 271powerpmc250_find_bridges(void) 272{ 273 struct pci_controller* hose; 274 275 hose = pcibios_alloc_controller(); 276 if (!hose){ 277 printk("Can't allocate PCI 'hose' structure!!!\n"); 278 return; 279 } 280 281 hose->first_busno = 0; 282 hose->last_busno = 0xff; 283 284 if (mpc10x_bridge_init(hose, 285 MPC10X_MEM_MAP_B, 286 MPC10X_MEM_MAP_B, 287 MPC10X_MAPB_EUMB_BASE) == 0) { 288 289 hose->mem_resources[0].end = 0xffffffff; 290 291 hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); 292 293 /* ppc_md.pcibios_fixup = pcore_pcibios_fixup; */ 294 ppc_md.pci_swizzle = common_swizzle; 295 296 ppc_md.pci_exclude_device = powerpmc250_exclude_device; 297 ppc_md.pci_map_irq = powerpmc250_map_irq; 298 } else { 299 if (ppc_md.progress) 300 ppc_md.progress("Bridge init failed", 0x100); 301 printk("Host bridge init failed\n"); 302 } 303 304} 305