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