apus_setup.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:20k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: %F% %I% %G% %U% %#%
  3.  */
  4. /*
  5.  *  arch/ppc/platforms/apus_setup.c
  6.  *
  7.  *  Copyright (C) 1998, 1999  Jesper Skov
  8.  *
  9.  *  Basically what is needed to replace functionality found in
  10.  *  arch/m68k allowing Amiga drivers to work under APUS.
  11.  *  Bits of code and/or ideas from arch/m68k and arch/ppc files.
  12.  *
  13.  * TODO:
  14.  *  This file needs a *really* good cleanup. Restructure and optimize.
  15.  *  Make sure it can be compiled for non-APUS configs. Begin to move
  16.  *  Amiga specific stuff into mach/amiga.
  17.  */
  18. #include <linux/config.h>
  19. #include <linux/kernel.h>
  20. #include <linux/sched.h>
  21. #include <linux/init.h>
  22. #include <linux/blk.h>
  23. #include <linux/seq_file.h>
  24. /* Needs INITSERIAL call in head.S! */
  25. #undef APUS_DEBUG
  26. #include <asm/bootinfo.h>
  27. #include <asm/setup.h>
  28. #include <asm/amigahw.h>
  29. #include <asm/amigaints.h>
  30. #include <asm/amigappc.h>
  31. #include <asm/pgtable.h>
  32. #include <asm/dma.h>
  33. #include <asm/machdep.h>
  34. #include <asm/hardirq.h>
  35. #include <asm/keyboard.h>
  36. #include <asm/time.h>
  37. unsigned long m68k_machtype;
  38. char debug_device[6] = "";
  39. extern void amiga_init_IRQ(void);
  40. extern int amiga_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode);
  41. extern char amiga_sysrq_xlate[128];
  42. extern void apus_setup_pci_ptrs(void);
  43. void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
  44. /* machine dependent keyboard functions */
  45. int (*mach_keyb_init) (void) __initdata = NULL;
  46. int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
  47. void (*mach_kbd_leds) (unsigned int) = NULL;
  48. /* machine dependent irq functions */
  49. void (*mach_init_IRQ) (void) __initdata = NULL;
  50. void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
  51. void (*mach_get_model) (char *model) = NULL;
  52. int (*mach_get_hardware_list) (char *buffer) = NULL;
  53. int (*mach_get_irq_list) (char *) = NULL;
  54. void (*mach_process_int) (int, struct pt_regs *) = NULL;
  55. /* machine dependent timer functions */
  56. unsigned long (*mach_gettimeoffset) (void);
  57. void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
  58. int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
  59. int (*mach_set_clock_mmss) (unsigned long) = NULL;
  60. void (*mach_reset)( void );
  61. long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
  62. #if defined(CONFIG_AMIGA_FLOPPY)
  63. void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
  64. #endif
  65. #ifdef CONFIG_HEARTBEAT
  66. void (*mach_heartbeat) (int) = NULL;
  67. extern void apus_heartbeat(void);
  68. #endif
  69. extern unsigned long amiga_model;
  70. extern unsigned decrementer_count;/* count value for 1e6/HZ microseconds */
  71. extern unsigned count_period_num; /* 1 decrementer count equals */
  72. extern unsigned count_period_den; /* count_period_num / count_period_den us */
  73. int num_memory = 0;
  74. struct mem_info memory[NUM_MEMINFO];/* memory description */
  75. /* FIXME: Duplicate memory data to avoid conflicts with m68k shared code. */
  76. int m68k_realnum_memory = 0;
  77. struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
  78. struct mem_info ramdisk;
  79. extern void amiga_floppy_setup(char *, int *);
  80. extern void config_amiga(void);
  81. static int __60nsram = 0;
  82. /* for cpuinfo */
  83. static int __bus_speed = 0;
  84. static int __speed_test_failed = 0;
  85. /********************************************** COMPILE PROTECTION */
  86. /* Provide some stubs that links to Amiga specific functions.
  87.  * This allows CONFIG_APUS to be removed from generic PPC files while
  88.  * preventing link errors for other PPC targets.
  89.  */
  90. unsigned long apus_get_rtc_time(void)
  91. {
  92. #ifdef CONFIG_APUS
  93. extern unsigned long m68k_get_rtc_time(void);
  94. return m68k_get_rtc_time ();
  95. #else
  96. return 0;
  97. #endif
  98. }
  99. int apus_set_rtc_time(unsigned long nowtime)
  100. {
  101. #ifdef CONFIG_APUS
  102. extern int m68k_set_rtc_time(unsigned long nowtime);
  103. return m68k_set_rtc_time (nowtime);
  104. #else
  105. return 0;
  106. #endif
  107. }
  108. /*********************************************************** SETUP */
  109. /* From arch/m68k/kernel/setup.c. */
  110. void __init apus_setup_arch(void)
  111. {
  112. #ifdef CONFIG_APUS
  113. extern char cmd_line[];
  114. int i;
  115. char *p, *q;
  116. /* Let m68k-shared code know it should do the Amiga thing. */
  117. m68k_machtype = MACH_AMIGA;
  118. /* Parse the command line for arch-specific options.
  119.  * For the m68k, this is currently only "debug=xxx" to enable printing
  120.  * certain kernel messages to some machine-specific device.  */
  121. for( p = cmd_line; p && *p; ) {
  122.     i = 0;
  123.     if (!strncmp( p, "debug=", 6 )) {
  124.     strncpy( debug_device, p+6, sizeof(debug_device)-1 );
  125.     debug_device[sizeof(debug_device)-1] = 0;
  126.     if ((q = strchr( debug_device, ' ' ))) *q = 0;
  127.     i = 1;
  128.     } else if (!strncmp( p, "60nsram", 7 )) {
  129.     APUS_WRITE (APUS_REG_WAITSTATE,
  130. REGWAITSTATE_SETRESET
  131. |REGWAITSTATE_PPCR
  132. |REGWAITSTATE_PPCW);
  133.     __60nsram = 1;
  134.     i = 1;
  135.     }
  136.     if (i) {
  137. /* option processed, delete it */
  138. if ((q = strchr( p, ' ' )))
  139.     strcpy( p, q+1 );
  140. else
  141.     *p = 0;
  142.     } else {
  143. if ((p = strchr( p, ' ' ))) ++p;
  144.     }
  145. }
  146. config_amiga();
  147. #if 0 /* Enable for logging - also include logging.o in Makefile rule */
  148. {
  149. #define LOG_SIZE 4096
  150. void* base;
  151. /* Throw away some memory - the P5 firmare stomps on top
  152.  * of CHIP memory during bootup.
  153.  */
  154. amiga_chip_alloc(0x1000);
  155. base = amiga_chip_alloc(LOG_SIZE+sizeof(klog_data_t));
  156. LOG_INIT(base, base+sizeof(klog_data_t), LOG_SIZE);
  157. }
  158. #endif
  159. #endif
  160. }
  161. int
  162. apus_show_cpuinfo(struct seq_file *m)
  163. {
  164. extern int __map_without_bats;
  165. extern unsigned long powerup_PCI_present;
  166. seq_printf(m, "machinett: Amigan");
  167. seq_printf(m, "bus speedt: %d%s", __bus_speed,
  168.    (__speed_test_failed) ? " [failed]n" : "n");
  169. seq_printf(m, "using BATst: %sn",
  170.    (__map_without_bats) ? "No" : "Yes");
  171. seq_printf(m, "ram speedt: %dnsn", (__60nsram) ? 60 : 70);
  172. seq_printf(m, "PCI bridget: %sn",
  173.    (powerup_PCI_present) ? "Yes" : "No");
  174. return 0;
  175. }
  176. static void get_current_tb(unsigned long long *time)
  177. {
  178. __asm __volatile ("1:mftbu 4      nt"
  179.   "  mftb  5      nt"
  180.   "  mftbu 6      nt"
  181.   "  cmpw  4,6    nt"
  182.   "  bne   1b     nt"
  183.   "  stw   4,0(%0)nt"
  184.   "  stw   5,4(%0)nt"
  185.   :
  186.   : "r" (time)
  187.   : "r4", "r5", "r6");
  188. }
  189. void apus_calibrate_decr(void)
  190. {
  191. #ifdef CONFIG_APUS
  192. unsigned long freq;
  193. /* This algorithm for determining the bus speed was
  194.            contributed by Ralph Schmidt. */
  195. unsigned long long start, stop;
  196. int bus_speed;
  197. int speed_test_failed = 0;
  198. {
  199. unsigned long loop = amiga_eclock / 10;
  200. get_current_tb (&start);
  201. while (loop--) {
  202. unsigned char tmp;
  203. tmp = ciaa.pra;
  204. }
  205. get_current_tb (&stop);
  206. }
  207. bus_speed = (((unsigned long)(stop-start))*10*4) / 1000000;
  208. if (AMI_1200 == amiga_model)
  209. bus_speed /= 2;
  210. if ((bus_speed >= 47) && (bus_speed < 53)) {
  211. bus_speed = 50;
  212. freq = 12500000;
  213. } else if ((bus_speed >= 57) && (bus_speed < 63)) {
  214. bus_speed = 60;
  215. freq = 15000000;
  216. } else if ((bus_speed >= 63) && (bus_speed < 69)) {
  217. bus_speed = 67;
  218. freq = 16666667;
  219. } else {
  220. printk ("APUS: Unable to determine bus speed (%d). "
  221. "Defaulting to 50MHz", bus_speed);
  222. bus_speed = 50;
  223. freq = 12500000;
  224. speed_test_failed = 1;
  225. }
  226. /* Ease diagnostics... */
  227. {
  228. extern int __map_without_bats;
  229. extern unsigned long powerup_PCI_present;
  230. printk ("APUS: BATs=%d, BUS=%dMHz",
  231. (__map_without_bats) ? 0 : 1,
  232. bus_speed);
  233. if (speed_test_failed)
  234. printk ("[FAILED - please report]");
  235. printk (", RAM=%dns, PCI bridge=%dn",
  236. (__60nsram) ? 60 : 70,
  237. (powerup_PCI_present) ? 1 : 0);
  238. /* print a bit more if asked politely... */
  239. if (!(ciaa.pra & 0x40)){
  240. extern unsigned int bat_addrs[4][3];
  241. int b;
  242. for (b = 0; b < 4; ++b) {
  243. printk ("APUS: BAT%d ", b);
  244. printk ("%08x-%08x -> %08xn",
  245. bat_addrs[b][0],
  246. bat_addrs[b][1],
  247. bat_addrs[b][2]);
  248. }
  249. }
  250. }
  251.         printk("time_init: decrementer frequency = %lu.%.6lu MHzn",
  252.        freq/1000000, freq%1000000);
  253. tb_ticks_per_jiffy = freq / HZ;
  254. tb_to_us = mulhwu_scale_factor(freq, 1000000);
  255. __bus_speed = bus_speed;
  256. __speed_test_failed = speed_test_failed;
  257. #endif
  258. }
  259. void arch_gettod(int *year, int *mon, int *day, int *hour,
  260.  int *min, int *sec)
  261. {
  262. #ifdef CONFIG_APUS
  263. if (mach_gettod)
  264. mach_gettod(year, mon, day, hour, min, sec);
  265. else
  266. *year = *mon = *day = *hour = *min = *sec = 0;
  267. #endif
  268. }
  269. /* for "kbd-reset" cmdline param */
  270. __init
  271. void kbd_reset_setup(char *str, int *ints)
  272. {
  273. }
  274. /*********************************************************** FLOPPY */
  275. #if defined(CONFIG_AMIGA_FLOPPY)
  276. __init
  277. void floppy_setup(char *str, int *ints)
  278. {
  279. if (mach_floppy_setup)
  280. mach_floppy_setup (str, ints);
  281. }
  282. #endif
  283. /*********************************************************** MEMORY */
  284. #define KMAP_MAX 32
  285. unsigned long kmap_chunks[KMAP_MAX*3];
  286. int kmap_chunk_count = 0;
  287. /* From pgtable.h */
  288. static __inline__ pte_t *my_find_pte(struct mm_struct *mm,unsigned long va)
  289. {
  290. pgd_t *dir = 0;
  291. pmd_t *pmd = 0;
  292. pte_t *pte = 0;
  293. va &= PAGE_MASK;
  294. dir = pgd_offset( mm, va );
  295. if (dir)
  296. {
  297. pmd = pmd_offset(dir, va & PAGE_MASK);
  298. if (pmd && pmd_present(*pmd))
  299. {
  300. pte = pte_offset(pmd, va);
  301. }
  302. }
  303. return pte;
  304. }
  305. /* Again simulating an m68k/mm/kmap.c function. */
  306. void kernel_set_cachemode( unsigned long address, unsigned long size,
  307.    unsigned int cmode )
  308. {
  309. unsigned long mask, flags;
  310. switch (cmode)
  311. {
  312. case IOMAP_FULL_CACHING:
  313. mask = ~(_PAGE_NO_CACHE | _PAGE_GUARDED);
  314. flags = 0;
  315. break;
  316. case IOMAP_NOCACHE_SER:
  317. mask = ~0;
  318. flags = (_PAGE_NO_CACHE | _PAGE_GUARDED);
  319. break;
  320. default:
  321. panic ("kernel_set_cachemode() doesn't support mode %dn",
  322.        cmode);
  323. break;
  324. }
  325. size /= PAGE_SIZE;
  326. address &= PAGE_MASK;
  327. while (size--)
  328. {
  329. pte_t *pte;
  330. pte = my_find_pte(&init_mm, address);
  331. if ( !pte )
  332. {
  333. printk("pte NULL in kernel_set_cachemode()n");
  334. return;
  335. }
  336.                 pte_val (*pte) &= mask;
  337.                 pte_val (*pte) |= flags;
  338.                 flush_tlb_page(find_vma(&init_mm,address),address);
  339. address += PAGE_SIZE;
  340. }
  341. }
  342. unsigned long mm_ptov (unsigned long paddr)
  343. {
  344. unsigned long ret;
  345. if (paddr < 16*1024*1024)
  346. ret = ZTWO_VADDR(paddr);
  347. else {
  348. int i;
  349. for (i = 0; i < kmap_chunk_count;){
  350. unsigned long phys = kmap_chunks[i++];
  351. unsigned long size = kmap_chunks[i++];
  352. unsigned long virt = kmap_chunks[i++];
  353. if (paddr >= phys
  354.     && paddr < (phys + size)){
  355. ret = virt + paddr - phys;
  356. goto exit;
  357. }
  358. }
  359. ret = (unsigned long) __va(paddr);
  360. }
  361. exit:
  362. #ifdef DEBUGPV
  363. printk ("PTOV(%lx)=%lxn", paddr, ret);
  364. #endif
  365. return ret;
  366. }
  367. int mm_end_of_chunk (unsigned long addr, int len)
  368. {
  369. if (memory[0].addr + memory[0].size == addr + len)
  370. return 1;
  371. return 0;
  372. }
  373. /*********************************************************** CACHE */
  374. #define L1_CACHE_BYTES 32
  375. #define MAX_CACHE_SIZE 8192
  376. void cache_push(__u32 addr, int length)
  377. {
  378. addr = mm_ptov(addr);
  379. if (MAX_CACHE_SIZE < length)
  380. length = MAX_CACHE_SIZE;
  381. while(length > 0){
  382. __asm ("dcbf 0,%0nt"
  383.        : : "r" (addr));
  384. addr += L1_CACHE_BYTES;
  385. length -= L1_CACHE_BYTES;
  386. }
  387. /* Also flush trailing block */
  388. __asm ("dcbf 0,%0nt"
  389.        "sync nt"
  390.        : : "r" (addr));
  391. }
  392. void cache_clear(__u32 addr, int length)
  393. {
  394. if (MAX_CACHE_SIZE < length)
  395. length = MAX_CACHE_SIZE;
  396. addr = mm_ptov(addr);
  397. __asm ("dcbf 0,%0nt"
  398.        "sync nt"
  399.        "icbi 0,%0 nt"
  400.        "isync nt"
  401.        : : "r" (addr));
  402. addr += L1_CACHE_BYTES;
  403. length -= L1_CACHE_BYTES;
  404. while(length > 0){
  405. __asm ("dcbf 0,%0nt"
  406.        "sync nt"
  407.        "icbi 0,%0 nt"
  408.        "isync nt"
  409.        : : "r" (addr));
  410. addr += L1_CACHE_BYTES;
  411. length -= L1_CACHE_BYTES;
  412. }
  413. __asm ("dcbf 0,%0nt"
  414.        "sync nt"
  415.        "icbi 0,%0 nt"
  416.        "isync nt"
  417.        : : "r" (addr));
  418. }
  419. /****************************************************** from setup.c */
  420. void
  421. apus_restart(char *cmd)
  422. {
  423. cli();
  424. APUS_WRITE(APUS_REG_LOCK,
  425.    REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK2);
  426. APUS_WRITE(APUS_REG_LOCK,
  427.    REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK3);
  428. APUS_WRITE(APUS_REG_LOCK,
  429.    REGLOCK_BLACKMAGICK2|REGLOCK_BLACKMAGICK3);
  430. APUS_WRITE(APUS_REG_SHADOW, REGSHADOW_SELFRESET);
  431. APUS_WRITE(APUS_REG_RESET, REGRESET_AMIGARESET);
  432. for(;;);
  433. }
  434. void
  435. apus_power_off(void)
  436. {
  437. for (;;);
  438. }
  439. void
  440. apus_halt(void)
  441. {
  442.    apus_restart(NULL);
  443. }
  444. /****************************************************** IRQ stuff */
  445. static unsigned char last_ipl[8];
  446. int apus_get_irq(struct pt_regs* regs)
  447. {
  448. unsigned char ipl_emu, mask;
  449. unsigned int level;
  450. APUS_READ(APUS_IPL_EMU, ipl_emu);
  451. level = (ipl_emu >> 3) & IPLEMU_IPLMASK;
  452. mask = IPLEMU_SETRESET|IPLEMU_DISABLEINT|level;
  453. level ^= 7;
  454. /* Save previous IPL value */
  455. if (last_ipl[level])
  456. return -2;
  457. last_ipl[level] = ipl_emu;
  458. /* Set to current IPL value */
  459. APUS_WRITE(APUS_IPL_EMU, mask);
  460. APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT|level);
  461. #ifdef __INTERRUPT_DEBUG
  462. printk("<%d:%d>", level, ~ipl_emu & IPLEMU_IPLMASK);
  463. #endif
  464. return level + IRQ_AMIGA_AUTO;
  465. }
  466. void apus_end_irq(unsigned int irq)
  467. {
  468. unsigned char ipl_emu;
  469. unsigned int level = irq - IRQ_AMIGA_AUTO;
  470. #ifdef __INTERRUPT_DEBUG
  471. printk("{%d}", ~last_ipl[level] & IPLEMU_IPLMASK);
  472. #endif
  473. /* Restore IPL to the previous value */
  474. ipl_emu = last_ipl[level] & IPLEMU_IPLMASK;
  475. APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET|IPLEMU_DISABLEINT|ipl_emu);
  476. last_ipl[level] = 0;
  477. ipl_emu ^= 7;
  478. APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT|ipl_emu);
  479. }
  480. /****************************************************** keyboard */
  481. static int apus_kbd_setkeycode(unsigned int scancode, unsigned int keycode)
  482. {
  483. return -EOPNOTSUPP;
  484. }
  485. static int apus_kbd_getkeycode(unsigned int scancode)
  486. {
  487. return scancode > 127 ? -EINVAL : scancode;
  488. }
  489. static char apus_kbd_unexpected_up(unsigned char keycode)
  490. {
  491. return 0200;
  492. }
  493. static void apus_kbd_init_hw(void)
  494. {
  495. #ifdef CONFIG_APUS
  496. extern int amiga_keyb_init(void);
  497. amiga_keyb_init();
  498. #endif
  499. }
  500. /****************************************************** debugging */
  501. /* some serial hardware definitions */
  502. #define SDR_OVRUN   (1<<15)
  503. #define SDR_RBF     (1<<14)
  504. #define SDR_TBE     (1<<13)
  505. #define SDR_TSRE    (1<<12)
  506. #define AC_SETCLR   (1<<15)
  507. #define AC_UARTBRK  (1<<11)
  508. #define SER_DTR     (1<<7)
  509. #define SER_RTS     (1<<6)
  510. #define SER_DCD     (1<<5)
  511. #define SER_CTS     (1<<4)
  512. #define SER_DSR     (1<<3)
  513. static __inline__ void ser_RTSon(void)
  514. {
  515.     ciab.pra &= ~SER_RTS; /* active low */
  516. }
  517. int __debug_ser_out( unsigned char c )
  518. {
  519. custom.serdat = c | 0x100;
  520. mb();
  521. while (!(custom.serdatr & 0x2000))
  522. barrier();
  523. return 1;
  524. }
  525. unsigned char __debug_ser_in( void )
  526. {
  527. unsigned char c;
  528. /* XXX: is that ok?? derived from amiga_ser.c... */
  529. while( !(custom.intreqr & IF_RBF) )
  530. barrier();
  531. c = custom.serdatr;
  532. /* clear the interrupt, so that another character can be read */
  533. custom.intreq = IF_RBF;
  534. return c;
  535. }
  536. int __debug_serinit( void )
  537. {
  538. unsigned long flags;
  539. save_flags (flags);
  540. cli();
  541. /* turn off Rx and Tx interrupts */
  542. custom.intena = IF_RBF | IF_TBE;
  543. /* clear any pending interrupt */
  544. custom.intreq = IF_RBF | IF_TBE;
  545. restore_flags (flags);
  546. /*
  547.  * set the appropriate directions for the modem control flags,
  548.  * and clear RTS and DTR
  549.  */
  550. ciab.ddra |= (SER_DTR | SER_RTS);   /* outputs */
  551. ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR);  /* inputs */
  552. #ifdef CONFIG_KGDB
  553. /* turn Rx interrupts on for GDB */
  554. custom.intena = IF_SETCLR | IF_RBF;
  555. ser_RTSon();
  556. #endif
  557. return 0;
  558. }
  559. void __debug_print_hex(unsigned long x)
  560. {
  561. int i;
  562. char hexchars[] = "0123456789ABCDEF";
  563. for (i = 0; i < 8; i++) {
  564. __debug_ser_out(hexchars[(x >> 28) & 15]);
  565. x <<= 4;
  566. }
  567. __debug_ser_out('n');
  568. __debug_ser_out('r');
  569. }
  570. void __debug_print_string(char* s)
  571. {
  572. unsigned char c;
  573. while((c = *s++))
  574. __debug_ser_out(c);
  575. __debug_ser_out('n');
  576. __debug_ser_out('r');
  577. }
  578. static void apus_progress(char *s, unsigned short value)
  579. {
  580. __debug_print_string(s);
  581. }
  582. /****************************************************** init */
  583. /* The number of spurious interrupts */
  584. volatile unsigned int num_spurious;
  585. extern struct irqaction amiga_sys_irqaction[AUTO_IRQS];
  586. extern void amiga_enable_irq(unsigned int irq);
  587. extern void amiga_disable_irq(unsigned int irq);
  588. struct hw_interrupt_type amiga_sys_irqctrl = {
  589. typename: "Amiga IPL",
  590. end: apus_end_irq,
  591. };
  592. struct hw_interrupt_type amiga_irqctrl = {
  593. typename: "Amiga    ",
  594. enable: amiga_enable_irq,
  595. disable: amiga_disable_irq,
  596. };
  597. #define HARDWARE_MAPPED_SIZE (512*1024)
  598. unsigned long __init apus_find_end_of_memory(void)
  599. {
  600. int shadow = 0;
  601. unsigned long total;
  602. /* The memory size reported by ADOS excludes the 512KB
  603.    reserved for PPC exception registers and possibly 512KB
  604.    containing a shadow of the ADOS ROM. */
  605. {
  606. unsigned long size = memory[0].size;
  607. /* If 2MB aligned, size was probably user
  608.                    specified. We can't tell anything about shadowing
  609.                    in this case so skip shadow assignment. */
  610. if (0 != (size & 0x1fffff)){
  611. /* Align to 512KB to ensure correct handling
  612.    of both memfile and system specified
  613.    sizes. */
  614. size = ((size+0x0007ffff) & 0xfff80000);
  615. /* If memory is 1MB aligned, assume
  616.                            shadowing. */
  617. shadow = !(size & 0x80000);
  618. }
  619. /* Add the chunk that ADOS does not see. by aligning
  620.                    the size to the nearest 2MB limit upwards.  */
  621. memory[0].size = ((size+0x001fffff) & 0xffe00000);
  622. }
  623. total = memory[0].size;
  624. /* Remove the memory chunks that are controlled by special
  625.            Phase5 hardware. */
  626. /* Remove the upper 512KB if it contains a shadow of
  627.    the ADOS ROM. FIXME: It might be possible to
  628.    disable this shadow HW. Check the booter
  629.    (ppc_boot.c) */
  630. if (shadow)
  631. total -= HARDWARE_MAPPED_SIZE;
  632. /* Remove the upper 512KB where the PPC exception
  633.    vectors are mapped. */
  634. total -= HARDWARE_MAPPED_SIZE;
  635. /* Linux/APUS only handles one block of memory -- the one on
  636.    the PowerUP board. Other system memory is horrible slow in
  637.    comparison. The user can use other memory for swapping
  638.    using the z2ram device. */
  639. ram_phys_base = memory[0].addr;
  640. return total;
  641. }
  642. static void __init
  643. apus_map_io(void)
  644. {
  645. /* Map PPC exception vectors. */
  646. io_block_mapping(0xfff00000, 0xfff00000, 0x00020000, _PAGE_KERNEL);
  647. /* Map chip and ZorroII memory */
  648. io_block_mapping(zTwoBase,   0x00000000, 0x01000000, _PAGE_IO);
  649. }
  650. __init
  651. void apus_init_IRQ(void)
  652. {
  653. struct irqaction *action;
  654. int i;
  655. #ifdef CONFIG_PCI
  656.         apus_setup_pci_ptrs();
  657. #endif
  658. for ( i = 0 ; i < AMI_IRQS; i++ ) {
  659. irq_desc[i].status = IRQ_LEVEL;
  660. if (i < IRQ_AMIGA_AUTO) {
  661. irq_desc[i].handler = &amiga_irqctrl;
  662. } else {
  663. irq_desc[i].handler = &amiga_sys_irqctrl;
  664. action = &amiga_sys_irqaction[i-IRQ_AMIGA_AUTO];
  665. if (action->name)
  666. setup_irq(i, action);
  667. }
  668. }
  669. amiga_init_IRQ();
  670. }
  671. __init
  672. void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
  673.    unsigned long r6, unsigned long r7)
  674. {
  675. extern int parse_bootinfo(const struct bi_record *);
  676. extern char _end[];
  677. /* Parse bootinfo. The bootinfo is located right after
  678.            the kernel bss */
  679. parse_bootinfo((const struct bi_record *)&_end);
  680. #ifdef CONFIG_BLK_DEV_INITRD
  681. /* Take care of initrd if we have one. Use data from
  682.    bootinfo to avoid the need to initialize PPC
  683.    registers when kernel is booted via a PPC reset. */
  684. if ( ramdisk.addr ) {
  685. initrd_start = (unsigned long) __va(ramdisk.addr);
  686. initrd_end = (unsigned long)
  687. __va(ramdisk.size + ramdisk.addr);
  688. }
  689. #endif /* CONFIG_BLK_DEV_INITRD */
  690. ISA_DMA_THRESHOLD = 0x00ffffff;
  691. ppc_md.setup_arch     = apus_setup_arch;
  692. ppc_md.show_cpuinfo   = apus_show_cpuinfo;
  693. ppc_md.init_IRQ       = apus_init_IRQ;
  694. ppc_md.get_irq        = apus_get_irq;
  695. #ifdef CONFIG_HEARTBEAT
  696. ppc_md.heartbeat      = apus_heartbeat;
  697. heartbeat_reset(0)    = 1; /* assume UP for now */
  698. heartbeat_count(0)    = 1;
  699. #endif
  700. #ifdef APUS_DEBUG
  701. __debug_serinit();
  702. ppc_md.progress       = apus_progress;
  703. #endif
  704. ppc_md.init           = NULL;
  705. ppc_md.restart        = apus_restart;
  706. ppc_md.power_off      = apus_power_off;
  707. ppc_md.halt           = apus_halt;
  708. ppc_md.time_init      = NULL;
  709. ppc_md.set_rtc_time   = apus_set_rtc_time;
  710. ppc_md.get_rtc_time   = apus_get_rtc_time;
  711. ppc_md.calibrate_decr = apus_calibrate_decr;
  712. ppc_md.find_end_of_memory = apus_find_end_of_memory;
  713. ppc_md.setup_io_mappings = apus_map_io;
  714. /* These should not be used for the APUS yet, since it uses
  715.    the M68K keyboard now. */
  716. ppc_md.kbd_setkeycode    = apus_kbd_setkeycode;
  717. ppc_md.kbd_getkeycode    = apus_kbd_getkeycode;
  718. ppc_md.kbd_translate     = amiga_kbd_translate;
  719. ppc_md.kbd_unexpected_up = apus_kbd_unexpected_up;
  720. ppc_md.kbd_init_hw       = apus_kbd_init_hw;
  721. #ifdef CONFIG_SYSRQ
  722. ppc_md.ppc_kbd_sysrq_xlate = amiga_sysrq_xlate;
  723. SYSRQ_KEY                = 0xff;
  724. #endif
  725. }