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.18-rc7 577 lines 13 kB view raw
1/* 2 * Copyright (C) 1995 Linus Torvalds 3 * Adapted from 'alpha' version by Gary Thomas 4 * Modified by Cort Dougan (cort@cs.nmt.edu) 5 * Synergy Microsystems board support by Dan Cox (dan@synergymicro.com) 6 * 7 */ 8 9#include <linux/stddef.h> 10#include <linux/kernel.h> 11#include <linux/init.h> 12#include <linux/errno.h> 13#include <linux/reboot.h> 14#include <linux/pci.h> 15#include <linux/time.h> 16#include <linux/kdev_t.h> 17#include <linux/types.h> 18#include <linux/major.h> 19#include <linux/initrd.h> 20#include <linux/console.h> 21#include <linux/seq_file.h> 22#include <linux/root_dev.h> 23#include <linux/bcd.h> 24 25#include <asm/system.h> 26#include <asm/pgtable.h> 27#include <asm/page.h> 28#include <asm/dma.h> 29#include <asm/io.h> 30#include <asm/m48t35.h> 31#include <platforms/gemini.h> 32#include <asm/time.h> 33#include <asm/open_pic.h> 34#include <asm/bootinfo.h> 35#include <asm/machdep.h> 36 37void gemini_find_bridges(void); 38static int gemini_get_clock_speed(void); 39extern void gemini_pcibios_fixup(void); 40 41static char *gemini_board_families[] = { 42 "VGM", "VSS", "KGM", "VGR", "VCM", "VCS", "KCM", "VCR" 43}; 44static int gemini_board_count = sizeof(gemini_board_families) / 45 sizeof(gemini_board_families[0]); 46 47static unsigned int cpu_7xx[16] = { 48 0, 15, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0 49}; 50static unsigned int cpu_6xx[16] = { 51 0, 0, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 0, 12, 7, 0 52}; 53 54/* 55 * prom_init is the Gemini version of prom.c:prom_init. We only need 56 * the BSS clearing code, so I copied that out of prom.c. This is a 57 * lot simpler than hacking prom.c so it will build with Gemini. -VAL 58 */ 59 60#define PTRRELOC(x) ((typeof(x))((unsigned long)(x) + offset)) 61 62unsigned long 63prom_init(void) 64{ 65 unsigned long offset = reloc_offset(); 66 unsigned long phys; 67 extern char __bss_start, _end; 68 69 /* First zero the BSS -- use memset, some arches don't have 70 * caches on yet */ 71 memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start); 72 73 /* Default */ 74 phys = offset + KERNELBASE; 75 76 gemini_prom_init(); 77 78 return phys; 79} 80 81int 82gemini_show_cpuinfo(struct seq_file *m) 83{ 84 unsigned char reg, rev; 85 char *family; 86 unsigned int type; 87 88 reg = readb(GEMINI_FEAT); 89 family = gemini_board_families[((reg>>4) & 0xf)]; 90 if (((reg>>4) & 0xf) > gemini_board_count) 91 printk(KERN_ERR "cpuinfo(): unable to determine board family\n"); 92 93 reg = readb(GEMINI_BREV); 94 type = (reg>>4) & 0xf; 95 rev = reg & 0xf; 96 97 reg = readb(GEMINI_BECO); 98 99 seq_printf(m, "machine\t\t: Gemini %s%d, rev %c, eco %d\n", 100 family, type, (rev + 'A'), (reg & 0xf)); 101 102 seq_printf(m, "board\t\t: Gemini %s", family); 103 if (type > 9) 104 seq_printf(m, "%c", (type - 10) + 'A'); 105 else 106 seq_printf(m, "%d", type); 107 108 seq_printf(m, ", rev %c, eco %d\n", (rev + 'A'), (reg & 0xf)); 109 110 seq_printf(m, "clock\t\t: %dMhz\n", gemini_get_clock_speed()); 111 112 return 0; 113} 114 115static u_char gemini_openpic_initsenses[] = { 116 1, 117 1, 118 1, 119 1, 120 0, 121 0, 122 1, /* remainder are level-triggered */ 123}; 124 125#define GEMINI_MPIC_ADDR (0xfcfc0000) 126#define GEMINI_MPIC_PCI_CFG (0x80005800) 127 128void __init gemini_openpic_init(void) 129{ 130 131 OpenPIC_Addr = (volatile struct OpenPIC *) 132 grackle_read(GEMINI_MPIC_PCI_CFG + 0x10); 133 OpenPIC_InitSenses = gemini_openpic_initsenses; 134 OpenPIC_NumInitSenses = sizeof( gemini_openpic_initsenses ); 135 136 ioremap( GEMINI_MPIC_ADDR, OPENPIC_SIZE); 137} 138 139 140extern unsigned long loops_per_jiffy; 141extern int root_mountflags; 142extern char cmd_line[]; 143 144void 145gemini_heartbeat(void) 146{ 147 static unsigned long led = GEMINI_LEDBASE+(4*8); 148 static char direction = 8; 149 150 151 /* We only want to do this on 1 CPU */ 152 if (smp_processor_id()) 153 return; 154 *(char *)led = 0; 155 if ( (led + direction) > (GEMINI_LEDBASE+(7*8)) || 156 (led + direction) < (GEMINI_LEDBASE+(4*8)) ) 157 direction *= -1; 158 led += direction; 159 *(char *)led = 0xff; 160 ppc_md.heartbeat_count = ppc_md.heartbeat_reset; 161} 162 163void __init gemini_setup_arch(void) 164{ 165 extern char cmd_line[]; 166 167 168 loops_per_jiffy = 50000000/HZ; 169 170#ifdef CONFIG_BLK_DEV_INITRD 171 /* bootable off CDROM */ 172 if (initrd_start) 173 ROOT_DEV = Root_SR0; 174 else 175#endif 176 ROOT_DEV = Root_SDA1; 177 178 /* nothing but serial consoles... */ 179 sprintf(cmd_line, "%s console=ttyS0", cmd_line); 180 181 printk("Boot arguments: %s\n", cmd_line); 182 183 ppc_md.heartbeat = gemini_heartbeat; 184 ppc_md.heartbeat_reset = HZ/8; 185 ppc_md.heartbeat_count = 1; 186 187 /* Lookup PCI hosts */ 188 gemini_find_bridges(); 189 /* take special pains to map the MPIC, since it isn't mapped yet */ 190 gemini_openpic_init(); 191 /* start the L2 */ 192 gemini_init_l2(); 193} 194 195 196int 197gemini_get_clock_speed(void) 198{ 199 unsigned long hid1, pvr; 200 int clock; 201 202 pvr = mfspr(SPRN_PVR); 203 hid1 = (mfspr(SPRN_HID1) >> 28) & 0xf; 204 if (PVR_VER(pvr) == 8 || 205 PVR_VER(pvr) == 12) 206 hid1 = cpu_7xx[hid1]; 207 else 208 hid1 = cpu_6xx[hid1]; 209 210 switch((readb(GEMINI_BSTAT) & 0xc) >> 2) { 211 212 case 0: 213 default: 214 clock = (hid1*100)/3; 215 break; 216 217 case 1: 218 clock = (hid1*125)/3; 219 break; 220 221 case 2: 222 clock = (hid1*50); 223 break; 224 } 225 226 return clock; 227} 228 229void __init gemini_init_l2(void) 230{ 231 unsigned char reg, brev, fam, creg; 232 unsigned long cache; 233 unsigned long pvr; 234 235 reg = readb(GEMINI_L2CFG); 236 brev = readb(GEMINI_BREV); 237 fam = readb(GEMINI_FEAT); 238 pvr = mfspr(SPRN_PVR); 239 240 switch(PVR_VER(pvr)) { 241 242 case 8: 243 if (reg & 0xc0) 244 cache = (((reg >> 6) & 0x3) << 28); 245 else 246 cache = 0x3 << 28; 247 248#ifdef CONFIG_SMP 249 /* Pre-3.0 processor revs had snooping errata. Leave 250 their L2's disabled with SMP. -- Dan */ 251 if (PVR_CFG(pvr) < 3) { 252 printk("Pre-3.0 750; L2 left disabled!\n"); 253 return; 254 } 255#endif /* CONFIG_SMP */ 256 257 /* Special case: VGM5-B's came before L2 ratios were set on 258 the board. Processor speed shouldn't be too high, so 259 set L2 ratio to 1:1.5. */ 260 if ((brev == 0x51) && ((fam & 0xa0) >> 4) == 0) 261 reg |= 1; 262 263 /* determine best cache ratio based upon what the board 264 tells us (which sometimes _may_ not be true) and 265 the processor speed. */ 266 else { 267 if (gemini_get_clock_speed() > 250) 268 reg = 2; 269 } 270 break; 271 case 12: 272 { 273 static unsigned long l2_size_val = 0; 274 275 if (!l2_size_val) 276 l2_size_val = _get_L2CR(); 277 cache = l2_size_val; 278 break; 279 } 280 case 4: 281 case 9: 282 creg = readb(GEMINI_CPUSTAT); 283 if (((creg & 0xc) >> 2) != 1) 284 printk("Dual-604 boards don't support the use of L2\n"); 285 else 286 writeb(1, GEMINI_L2CFG); 287 return; 288 default: 289 printk("Unknown processor; L2 left disabled\n"); 290 return; 291 } 292 293 cache |= ((1<<reg) << 25); 294 cache |= (L2CR_L2RAM_MASK|L2CR_L2CTL|L2CR_L2DO); 295 _set_L2CR(0); 296 _set_L2CR(cache | L2CR_L2E); 297 298} 299 300void 301gemini_restart(char *cmd) 302{ 303 local_irq_disable(); 304 /* make a clean restart, not via the MPIC */ 305 _gemini_reboot(); 306 for(;;); 307} 308 309void 310gemini_power_off(void) 311{ 312 for(;;); 313} 314 315void 316gemini_halt(void) 317{ 318 gemini_restart(NULL); 319} 320 321void __init gemini_init_IRQ(void) 322{ 323 /* gemini has no 8259 */ 324 openpic_init(1, 0, 0, -1); 325} 326 327#define gemini_rtc_read(x) (readb(GEMINI_RTC+(x))) 328#define gemini_rtc_write(val,x) (writeb((val),(GEMINI_RTC+(x)))) 329 330/* ensure that the RTC is up and running */ 331long __init gemini_time_init(void) 332{ 333 unsigned char reg; 334 335 reg = gemini_rtc_read(M48T35_RTC_CONTROL); 336 337 if ( reg & M48T35_RTC_STOPPED ) { 338 printk(KERN_INFO "M48T35 real-time-clock was stopped. Now starting...\n"); 339 gemini_rtc_write((reg & ~(M48T35_RTC_STOPPED)), M48T35_RTC_CONTROL); 340 gemini_rtc_write((reg | M48T35_RTC_SET), M48T35_RTC_CONTROL); 341 } 342 return 0; 343} 344 345#undef DEBUG_RTC 346 347unsigned long 348gemini_get_rtc_time(void) 349{ 350 unsigned int year, mon, day, hour, min, sec; 351 unsigned char reg; 352 353 reg = gemini_rtc_read(M48T35_RTC_CONTROL); 354 gemini_rtc_write((reg|M48T35_RTC_READ), M48T35_RTC_CONTROL); 355#ifdef DEBUG_RTC 356 printk("get rtc: reg = %x\n", reg); 357#endif 358 359 do { 360 sec = gemini_rtc_read(M48T35_RTC_SECONDS); 361 min = gemini_rtc_read(M48T35_RTC_MINUTES); 362 hour = gemini_rtc_read(M48T35_RTC_HOURS); 363 day = gemini_rtc_read(M48T35_RTC_DOM); 364 mon = gemini_rtc_read(M48T35_RTC_MONTH); 365 year = gemini_rtc_read(M48T35_RTC_YEAR); 366 } while( sec != gemini_rtc_read(M48T35_RTC_SECONDS)); 367#ifdef DEBUG_RTC 368 printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n", 369 sec, min, hour, day, mon, year); 370#endif 371 372 gemini_rtc_write(reg, M48T35_RTC_CONTROL); 373 374 BCD_TO_BIN(sec); 375 BCD_TO_BIN(min); 376 BCD_TO_BIN(hour); 377 BCD_TO_BIN(day); 378 BCD_TO_BIN(mon); 379 BCD_TO_BIN(year); 380 381 if ((year += 1900) < 1970) 382 year += 100; 383#ifdef DEBUG_RTC 384 printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n", 385 sec, min, hour, day, mon, year); 386#endif 387 388 return mktime( year, mon, day, hour, min, sec ); 389} 390 391 392int 393gemini_set_rtc_time( unsigned long now ) 394{ 395 unsigned char reg; 396 struct rtc_time tm; 397 398 to_tm( now, &tm ); 399 400 reg = gemini_rtc_read(M48T35_RTC_CONTROL); 401#ifdef DEBUG_RTC 402 printk("set rtc: reg = %x\n", reg); 403#endif 404 405 gemini_rtc_write((reg|M48T35_RTC_SET), M48T35_RTC_CONTROL); 406#ifdef DEBUG_RTC 407 printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n", 408 tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year); 409#endif 410 411 tm.tm_year -= 1900; 412 BIN_TO_BCD(tm.tm_sec); 413 BIN_TO_BCD(tm.tm_min); 414 BIN_TO_BCD(tm.tm_hour); 415 BIN_TO_BCD(tm.tm_mon); 416 BIN_TO_BCD(tm.tm_mday); 417 BIN_TO_BCD(tm.tm_year); 418#ifdef DEBUG_RTC 419 printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n", 420 tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year); 421#endif 422 423 gemini_rtc_write(tm.tm_sec, M48T35_RTC_SECONDS); 424 gemini_rtc_write(tm.tm_min, M48T35_RTC_MINUTES); 425 gemini_rtc_write(tm.tm_hour, M48T35_RTC_HOURS); 426 gemini_rtc_write(tm.tm_mday, M48T35_RTC_DOM); 427 gemini_rtc_write(tm.tm_mon, M48T35_RTC_MONTH); 428 gemini_rtc_write(tm.tm_year, M48T35_RTC_YEAR); 429 430 /* done writing */ 431 gemini_rtc_write(reg, M48T35_RTC_CONTROL); 432 433 return 0; 434} 435 436/* use the RTC to determine the decrementer count */ 437void __init gemini_calibrate_decr(void) 438{ 439 int freq, divisor; 440 unsigned char reg; 441 442 /* determine processor bus speed */ 443 reg = readb(GEMINI_BSTAT); 444 445 switch(((reg & 0x0c)>>2)&0x3) { 446 case 0: 447 default: 448 freq = 66667; 449 break; 450 case 1: 451 freq = 83000; 452 break; 453 case 2: 454 freq = 100000; 455 break; 456 } 457 458 freq *= 1000; 459 divisor = 4; 460 tb_ticks_per_jiffy = freq / HZ / divisor; 461 tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000); 462} 463 464unsigned long __init gemini_find_end_of_memory(void) 465{ 466 unsigned long total; 467 unsigned char reg; 468 469 reg = readb(GEMINI_MEMCFG); 470 total = ((1<<((reg & 0x7) - 1)) * 471 (8<<((reg >> 3) & 0x7))); 472 total *= (1024*1024); 473 return total; 474} 475 476static void __init 477gemini_map_io(void) 478{ 479 io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO); 480 io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO); 481} 482 483#ifdef CONFIG_SMP 484static int 485smp_gemini_probe(void) 486{ 487 int i, nr; 488 489 nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK) >> 2; 490 if (nr == 0) 491 nr = 4; 492 493 if (nr > 1) { 494 openpic_request_IPIs(); 495 for (i = 1; i < nr; ++i) 496 smp_hw_index[i] = i; 497 } 498 499 return nr; 500} 501 502static void 503smp_gemini_kick_cpu(int nr) 504{ 505 openpic_reset_processor_phys(1 << nr); 506 openpic_reset_processor_phys(0); 507} 508 509static void 510smp_gemini_setup_cpu(int cpu_nr) 511{ 512 if (OpenPIC_Addr) 513 do_openpic_setup_cpu(); 514 if (cpu_nr > 0) 515 gemini_init_l2(); 516} 517 518static struct smp_ops_t gemini_smp_ops = { 519 smp_openpic_message_pass, 520 smp_gemini_probe, 521 smp_gemini_kick_cpu, 522 smp_gemini_setup_cpu, 523 .give_timebase = smp_generic_give_timebase, 524 .take_timebase = smp_generic_take_timebase, 525}; 526#endif /* CONFIG_SMP */ 527 528void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5, 529 unsigned long r6, unsigned long r7) 530{ 531 int i; 532 533 /* Restore BATs for now */ 534 mtspr(SPRN_DBAT3U, 0xf0001fff); 535 mtspr(SPRN_DBAT3L, 0xf000002a); 536 537 parse_bootinfo(find_bootinfo()); 538 539 for(i = 0; i < GEMINI_LEDS; i++) 540 gemini_led_off(i); 541 542 ISA_DMA_THRESHOLD = 0; 543 DMA_MODE_READ = 0; 544 DMA_MODE_WRITE = 0; 545 546#ifdef CONFIG_BLK_DEV_INITRD 547 if ( r4 ) 548 { 549 initrd_start = r4 + KERNELBASE; 550 initrd_end = r5 + KERNELBASE; 551 } 552#endif 553 554 ppc_md.setup_arch = gemini_setup_arch; 555 ppc_md.show_cpuinfo = gemini_show_cpuinfo; 556 ppc_md.init_IRQ = gemini_init_IRQ; 557 ppc_md.get_irq = openpic_get_irq; 558 ppc_md.init = NULL; 559 560 ppc_md.restart = gemini_restart; 561 ppc_md.power_off = gemini_power_off; 562 ppc_md.halt = gemini_halt; 563 564 ppc_md.time_init = gemini_time_init; 565 ppc_md.set_rtc_time = gemini_set_rtc_time; 566 ppc_md.get_rtc_time = gemini_get_rtc_time; 567 ppc_md.calibrate_decr = gemini_calibrate_decr; 568 569 ppc_md.find_end_of_memory = gemini_find_end_of_memory; 570 ppc_md.setup_io_mappings = gemini_map_io; 571 572 ppc_md.pcibios_fixup_bus = gemini_pcibios_fixup; 573 574#ifdef CONFIG_SMP 575 smp_ops = &gemini_smp_ops; 576#endif /* CONFIG_SMP */ 577}