Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.17 380 lines 8.6 kB view raw
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/config.h> 15#include <linux/stddef.h> 16#include <linux/kernel.h> 17#include <linux/init.h> 18#include <linux/errno.h> 19#include <linux/reboot.h> 20#include <linux/pci.h> 21#include <linux/kdev_t.h> 22#include <linux/types.h> 23#include <linux/major.h> 24#include <linux/initrd.h> 25#include <linux/console.h> 26#include <linux/delay.h> 27#include <linux/slab.h> 28#include <linux/seq_file.h> 29#include <linux/ide.h> 30#include <linux/root_dev.h> 31 32#include <asm/byteorder.h> 33#include <asm/system.h> 34#include <asm/pgtable.h> 35#include <asm/page.h> 36#include <asm/dma.h> 37#include <asm/io.h> 38#include <asm/irq.h> 39#include <asm/machdep.h> 40#include <asm/time.h> 41#include <platforms/powerpmc250.h> 42#include <asm/open_pic.h> 43#include <asm/pci-bridge.h> 44#include <asm/mpc10x.h> 45#include <asm/uaccess.h> 46#include <asm/bootinfo.h> 47 48extern void powerpmc250_find_bridges(void); 49extern unsigned long loops_per_jiffy; 50 51static u_char powerpmc250_openpic_initsenses[] __initdata = 52{ 53 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54 1, /* PMC INTA (also MPC107 output interrupt INTA) */ 55 1, /* PMC INTB (also I82559 Ethernet controller) */ 56 1, /* PMC INTC */ 57 1, /* PMC INTD */ 58 0, /* DUART interrupt (active high) */ 59}; 60 61static int 62powerpmc250_show_cpuinfo(struct seq_file *m) 63{ 64 seq_printf(m,"machine\t\t: Force PowerPMC250\n"); 65 66 return 0; 67} 68 69static void __init 70powerpmc250_setup_arch(void) 71{ 72 /* init to some ~sane value until calibrate_delay() runs */ 73 loops_per_jiffy = 50000000/HZ; 74 75 /* Lookup PCI host bridges */ 76 powerpmc250_find_bridges(); 77 78#ifdef CONFIG_BLK_DEV_INITRD 79 if (initrd_start) 80 ROOT_DEV = Root_RAM0; 81 else 82#endif 83#ifdef CONFIG_ROOT_NFS 84 ROOT_DEV = Root_NFS; 85#else 86 ROOT_DEV = Root_SDA2; 87#endif 88 89 printk("Force PowerPMC250 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n"); 90} 91 92#if 0 93/* 94 * Compute the PrPMC750's bus speed using the baud clock as a 95 * reference. 96 */ 97unsigned long __init powerpmc250_get_bus_speed(void) 98{ 99 unsigned long tbl_start, tbl_end; 100 unsigned long current_state, old_state, bus_speed; 101 unsigned char lcr, dll, dlm; 102 int baud_divisor, count; 103 104 /* Read the UART's baud clock divisor */ 105 lcr = readb(PRPMC750_SERIAL_0_LCR); 106 writeb(lcr | UART_LCR_DLAB, PRPMC750_SERIAL_0_LCR); 107 dll = readb(PRPMC750_SERIAL_0_DLL); 108 dlm = readb(PRPMC750_SERIAL_0_DLM); 109 writeb(lcr & ~UART_LCR_DLAB, PRPMC750_SERIAL_0_LCR); 110 baud_divisor = (dlm << 8) | dll; 111 112 /* 113 * Use the baud clock divisor and base baud clock 114 * to determine the baud rate and use that as 115 * the number of baud clock edges we use for 116 * the time base sample. Make it half the baud 117 * rate. 118 */ 119 count = PRPMC750_BASE_BAUD / (baud_divisor * 16); 120 121 /* Find the first edge of the baud clock */ 122 old_state = readb(PRPMC750_STATUS_REG) & PRPMC750_BAUDOUT_MASK; 123 do { 124 current_state = readb(PRPMC750_STATUS_REG) & 125 PRPMC750_BAUDOUT_MASK; 126 } while(old_state == current_state); 127 128 old_state = current_state; 129 130 /* Get the starting time base value */ 131 tbl_start = get_tbl(); 132 133 /* 134 * Loop until we have found a number of edges equal 135 * to half the count (half the baud rate) 136 */ 137 do { 138 do { 139 current_state = readb(PRPMC750_STATUS_REG) & 140 PRPMC750_BAUDOUT_MASK; 141 } while(old_state == current_state); 142 old_state = current_state; 143 } while (--count); 144 145 /* Get the ending time base value */ 146 tbl_end = get_tbl(); 147 148 /* Compute bus speed */ 149 bus_speed = (tbl_end-tbl_start)*128; 150 151 return bus_speed; 152} 153#endif 154 155static void __init 156powerpmc250_calibrate_decr(void) 157{ 158 unsigned long freq; 159 int divisor = 4; 160 161 //freq = powerpmc250_get_bus_speed(); 162#warning hardcoded bus freq 163 freq = 100000000; 164 165 tb_ticks_per_jiffy = freq / (HZ * divisor); 166 tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000); 167} 168 169static void 170powerpmc250_restart(char *cmd) 171{ 172 local_irq_disable(); 173 /* Hard reset */ 174 writeb(0x11, 0xfe000332); 175 while(1); 176} 177 178static void 179powerpmc250_halt(void) 180{ 181 local_irq_disable(); 182 while (1); 183} 184 185static void 186powerpmc250_power_off(void) 187{ 188 powerpmc250_halt(); 189} 190 191static void __init 192powerpmc250_init_IRQ(void) 193{ 194 195 OpenPIC_InitSenses = powerpmc250_openpic_initsenses; 196 OpenPIC_NumInitSenses = sizeof(powerpmc250_openpic_initsenses); 197 mpc10x_set_openpic(); 198} 199 200/* 201 * Set BAT 3 to map 0xf0000000 to end of physical memory space. 202 */ 203static __inline__ void 204powerpmc250_set_bat(void) 205{ 206 unsigned long bat3u, bat3l; 207 static int mapping_set = 0; 208 209 if (!mapping_set) 210 { 211 __asm__ __volatile__( 212 " lis %0,0xf000\n \ 213 ori %1,%0,0x002a\n \ 214 ori %0,%0,0x1ffe\n \ 215 mtspr 0x21e,%0\n \ 216 mtspr 0x21f,%1\n \ 217 isync\n \ 218 sync " 219 : "=r" (bat3u), "=r" (bat3l)); 220 221 mapping_set = 1; 222 } 223 return; 224} 225 226static unsigned long __init 227powerpmc250_find_end_of_memory(void) 228{ 229 /* Cover I/O space with a BAT */ 230 /* yuck, better hope your ram size is a power of 2 -- paulus */ 231 powerpmc250_set_bat(); 232 233 return mpc10x_get_mem_size(MPC10X_MEM_MAP_B); 234} 235 236static void __init 237powerpmc250_map_io(void) 238{ 239 io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO); 240} 241 242void __init 243platform_init(unsigned long r3, unsigned long r4, unsigned long r5, 244 unsigned long r6, unsigned long r7) 245{ 246 parse_bootinfo(find_bootinfo()); 247 248#ifdef CONFIG_BLK_DEV_INITRD 249 if ( r4 ) 250 { 251 initrd_start = r4 + KERNELBASE; 252 initrd_end = r5 + KERNELBASE; 253 } 254#endif 255 256 /* Copy cmd_line parameters */ 257 if ( r6) 258 { 259 *(char *)(r7 + KERNELBASE) = 0; 260 strcpy(cmd_line, (char *)(r6 + KERNELBASE)); 261 } 262 263 isa_io_base = MPC10X_MAPB_ISA_IO_BASE; 264 isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE; 265 pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET; 266 267 ppc_md.setup_arch = powerpmc250_setup_arch; 268 ppc_md.show_cpuinfo = powerpmc250_show_cpuinfo; 269 ppc_md.init_IRQ = powerpmc250_init_IRQ; 270 ppc_md.get_irq = openpic_get_irq; 271 272 ppc_md.find_end_of_memory = powerpmc250_find_end_of_memory; 273 ppc_md.setup_io_mappings = powerpmc250_map_io; 274 275 ppc_md.restart = powerpmc250_restart; 276 ppc_md.power_off = powerpmc250_power_off; 277 ppc_md.halt = powerpmc250_halt; 278 279 /* PowerPMC250 has no timekeeper part */ 280 ppc_md.time_init = NULL; 281 ppc_md.get_rtc_time = NULL; 282 ppc_md.set_rtc_time = NULL; 283 ppc_md.calibrate_decr = powerpmc250_calibrate_decr; 284} 285 286 287/* 288 * (This used to be arch/ppc/platforms/powerpmc250_pci.c) 289 * 290 * PCI support for Force PowerPMC250 291 * 292 */ 293 294#undef DEBUG 295#ifdef DEBUG 296#define DBG(x...) printk(x) 297#else 298#define DBG(x...) 299#endif /* DEBUG */ 300 301static inline int __init 302powerpmc250_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) 303{ 304 static char pci_irq_table[][4] = 305 /* 306 * PCI IDSEL/INTPIN->INTLINE 307 * A B C D 308 */ 309 { 310 {17, 0, 0, 0}, /* Device 11 - 82559 */ 311 {0, 0, 0, 0}, /* 12 */ 312 {0, 0, 0, 0}, /* 13 */ 313 {0, 0, 0, 0}, /* 14 */ 314 {0, 0, 0, 0}, /* 15 */ 315 {16, 17, 18, 19}, /* Device 16 - PMC A1?? */ 316 }; 317 const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4; 318 return PCI_IRQ_TABLE_LOOKUP; 319}; 320 321static int 322powerpmc250_exclude_device(u_char bus, u_char devfn) 323{ 324 /* 325 * While doing PCI Scan the MPC107 will 'detect' itself as 326 * device on the PCI Bus, will create an incorrect response and 327 * later will respond incorrectly to Configuration read coming 328 * from another device. 329 * 330 * The work around is that when doing a PCI Scan one 331 * should skip its own device number in the scan. 332 * 333 * The top IDsel is AD13 and the middle is AD14. 334 * 335 * -- Note from force 336 */ 337 338 if ((bus == 0) && (PCI_SLOT(devfn) == 13 || PCI_SLOT(devfn) == 14)) { 339 return PCIBIOS_DEVICE_NOT_FOUND; 340 } 341 else { 342 return PCIBIOS_SUCCESSFUL; 343 } 344} 345 346void __init 347powerpmc250_find_bridges(void) 348{ 349 struct pci_controller* hose; 350 351 hose = pcibios_alloc_controller(); 352 if (!hose){ 353 printk("Can't allocate PCI 'hose' structure!!!\n"); 354 return; 355 } 356 357 hose->first_busno = 0; 358 hose->last_busno = 0xff; 359 360 if (mpc10x_bridge_init(hose, 361 MPC10X_MEM_MAP_B, 362 MPC10X_MEM_MAP_B, 363 MPC10X_MAPB_EUMB_BASE) == 0) { 364 365 hose->mem_resources[0].end = 0xffffffff; 366 367 hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); 368 369 /* ppc_md.pcibios_fixup = pcore_pcibios_fixup; */ 370 ppc_md.pci_swizzle = common_swizzle; 371 372 ppc_md.pci_exclude_device = powerpmc250_exclude_device; 373 ppc_md.pci_map_irq = powerpmc250_map_irq; 374 } else { 375 if (ppc_md.progress) 376 ppc_md.progress("Bridge init failed", 0x100); 377 printk("Host bridge init failed\n"); 378 } 379 380}