11da177e4SLinus Torvalds #include <linux/types.h> 21da177e4SLinus Torvalds #include <linux/kernel.h> 31da177e4SLinus Torvalds #include <linux/mm.h> 41da177e4SLinus Torvalds #include <linux/tty.h> 51da177e4SLinus Torvalds #include <linux/console.h> 61da177e4SLinus Torvalds #include <linux/rtc.h> 71da177e4SLinus Torvalds #include <linux/vt_kern.h> 81da177e4SLinus Torvalds #include <linux/interrupt.h> 91da177e4SLinus Torvalds 101da177e4SLinus Torvalds #include <asm/setup.h> 111da177e4SLinus Torvalds #include <asm/bootinfo.h> 121da177e4SLinus Torvalds #include <asm/pgtable.h> 131da177e4SLinus Torvalds #include <asm/apollohw.h> 141da177e4SLinus Torvalds #include <asm/irq.h> 151da177e4SLinus Torvalds #include <asm/rtc.h> 161da177e4SLinus Torvalds #include <asm/machdep.h> 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds u_long sio01_physaddr; 191da177e4SLinus Torvalds u_long sio23_physaddr; 201da177e4SLinus Torvalds u_long rtc_physaddr; 211da177e4SLinus Torvalds u_long pica_physaddr; 221da177e4SLinus Torvalds u_long picb_physaddr; 231da177e4SLinus Torvalds u_long cpuctrl_physaddr; 241da177e4SLinus Torvalds u_long timer_physaddr; 251da177e4SLinus Torvalds u_long apollo_model; 261da177e4SLinus Torvalds 2740220c1aSDavid Howells extern void dn_sched_init(irq_handler_t handler); 281da177e4SLinus Torvalds extern void dn_init_IRQ(void); 291da177e4SLinus Torvalds extern unsigned long dn_gettimeoffset(void); 301da177e4SLinus Torvalds extern int dn_dummy_hwclk(int, struct rtc_time *); 311da177e4SLinus Torvalds extern int dn_dummy_set_clock_mmss(unsigned long); 321da177e4SLinus Torvalds extern void dn_dummy_reset(void); 331da177e4SLinus Torvalds #ifdef CONFIG_HEARTBEAT 341da177e4SLinus Torvalds static void dn_heartbeat(int on); 351da177e4SLinus Torvalds #endif 362850bc27SAl Viro static irqreturn_t dn_timer_int(int irq,void *); 371da177e4SLinus Torvalds static void dn_get_model(char *model); 381da177e4SLinus Torvalds static const char *apollo_models[] = { 391da177e4SLinus Torvalds [APOLLO_DN3000-APOLLO_DN3000] = "DN3000 (Otter)", 401da177e4SLinus Torvalds [APOLLO_DN3010-APOLLO_DN3000] = "DN3010 (Otter)", 411da177e4SLinus Torvalds [APOLLO_DN3500-APOLLO_DN3000] = "DN3500 (Cougar II)", 421da177e4SLinus Torvalds [APOLLO_DN4000-APOLLO_DN3000] = "DN4000 (Mink)", 431da177e4SLinus Torvalds [APOLLO_DN4500-APOLLO_DN3000] = "DN4500 (Roadrunner)" 441da177e4SLinus Torvalds }; 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds int apollo_parse_bootinfo(const struct bi_record *record) { 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds int unknown = 0; 491da177e4SLinus Torvalds const unsigned long *data = record->data; 501da177e4SLinus Torvalds 511da177e4SLinus Torvalds switch(record->tag) { 521da177e4SLinus Torvalds case BI_APOLLO_MODEL: 531da177e4SLinus Torvalds apollo_model=*data; 541da177e4SLinus Torvalds break; 551da177e4SLinus Torvalds 561da177e4SLinus Torvalds default: 571da177e4SLinus Torvalds unknown=1; 581da177e4SLinus Torvalds } 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds return unknown; 611da177e4SLinus Torvalds } 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds void dn_setup_model(void) { 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds printk("Apollo hardware found: "); 671da177e4SLinus Torvalds printk("[%s]\n", apollo_models[apollo_model - APOLLO_DN3000]); 681da177e4SLinus Torvalds 691da177e4SLinus Torvalds switch(apollo_model) { 701da177e4SLinus Torvalds case APOLLO_UNKNOWN: 711da177e4SLinus Torvalds panic("Unknown apollo model"); 721da177e4SLinus Torvalds break; 731da177e4SLinus Torvalds case APOLLO_DN3000: 741da177e4SLinus Torvalds case APOLLO_DN3010: 751da177e4SLinus Torvalds sio01_physaddr=SAU8_SIO01_PHYSADDR; 761da177e4SLinus Torvalds rtc_physaddr=SAU8_RTC_PHYSADDR; 771da177e4SLinus Torvalds pica_physaddr=SAU8_PICA; 781da177e4SLinus Torvalds picb_physaddr=SAU8_PICB; 791da177e4SLinus Torvalds cpuctrl_physaddr=SAU8_CPUCTRL; 801da177e4SLinus Torvalds timer_physaddr=SAU8_TIMER; 811da177e4SLinus Torvalds break; 821da177e4SLinus Torvalds case APOLLO_DN4000: 831da177e4SLinus Torvalds sio01_physaddr=SAU7_SIO01_PHYSADDR; 841da177e4SLinus Torvalds sio23_physaddr=SAU7_SIO23_PHYSADDR; 851da177e4SLinus Torvalds rtc_physaddr=SAU7_RTC_PHYSADDR; 861da177e4SLinus Torvalds pica_physaddr=SAU7_PICA; 871da177e4SLinus Torvalds picb_physaddr=SAU7_PICB; 881da177e4SLinus Torvalds cpuctrl_physaddr=SAU7_CPUCTRL; 891da177e4SLinus Torvalds timer_physaddr=SAU7_TIMER; 901da177e4SLinus Torvalds break; 911da177e4SLinus Torvalds case APOLLO_DN4500: 921da177e4SLinus Torvalds panic("Apollo model not yet supported"); 931da177e4SLinus Torvalds break; 941da177e4SLinus Torvalds case APOLLO_DN3500: 951da177e4SLinus Torvalds sio01_physaddr=SAU7_SIO01_PHYSADDR; 961da177e4SLinus Torvalds sio23_physaddr=SAU7_SIO23_PHYSADDR; 971da177e4SLinus Torvalds rtc_physaddr=SAU7_RTC_PHYSADDR; 981da177e4SLinus Torvalds pica_physaddr=SAU7_PICA; 991da177e4SLinus Torvalds picb_physaddr=SAU7_PICB; 1001da177e4SLinus Torvalds cpuctrl_physaddr=SAU7_CPUCTRL; 1011da177e4SLinus Torvalds timer_physaddr=SAU7_TIMER; 1021da177e4SLinus Torvalds break; 1031da177e4SLinus Torvalds default: 1041da177e4SLinus Torvalds panic("Undefined apollo model"); 1051da177e4SLinus Torvalds break; 1061da177e4SLinus Torvalds } 1071da177e4SLinus Torvalds 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds } 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds int dn_serial_console_wait_key(struct console *co) { 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds while(!(sio01.srb_csrb & 1)) 1141da177e4SLinus Torvalds barrier(); 1151da177e4SLinus Torvalds return sio01.rhrb_thrb; 1161da177e4SLinus Torvalds } 1171da177e4SLinus Torvalds 1181da177e4SLinus Torvalds void dn_serial_console_write (struct console *co, const char *str,unsigned int count) 1191da177e4SLinus Torvalds { 1201da177e4SLinus Torvalds while(count--) { 1211da177e4SLinus Torvalds if (*str == '\n') { 1221da177e4SLinus Torvalds sio01.rhrb_thrb = (unsigned char)'\r'; 1231da177e4SLinus Torvalds while (!(sio01.srb_csrb & 0x4)) 1241da177e4SLinus Torvalds ; 1251da177e4SLinus Torvalds } 1261da177e4SLinus Torvalds sio01.rhrb_thrb = (unsigned char)*str++; 1271da177e4SLinus Torvalds while (!(sio01.srb_csrb & 0x4)) 1281da177e4SLinus Torvalds ; 1291da177e4SLinus Torvalds } 1301da177e4SLinus Torvalds } 1311da177e4SLinus Torvalds 1321da177e4SLinus Torvalds void dn_serial_print (const char *str) 1331da177e4SLinus Torvalds { 1341da177e4SLinus Torvalds while (*str) { 1351da177e4SLinus Torvalds if (*str == '\n') { 1361da177e4SLinus Torvalds sio01.rhrb_thrb = (unsigned char)'\r'; 1371da177e4SLinus Torvalds while (!(sio01.srb_csrb & 0x4)) 1381da177e4SLinus Torvalds ; 1391da177e4SLinus Torvalds } 1401da177e4SLinus Torvalds sio01.rhrb_thrb = (unsigned char)*str++; 1411da177e4SLinus Torvalds while (!(sio01.srb_csrb & 0x4)) 1421da177e4SLinus Torvalds ; 1431da177e4SLinus Torvalds } 1441da177e4SLinus Torvalds } 1451da177e4SLinus Torvalds 14666a3f820SAl Viro void __init config_apollo(void) 14766a3f820SAl Viro { 1481da177e4SLinus Torvalds int i; 1491da177e4SLinus Torvalds 1501da177e4SLinus Torvalds dn_setup_model(); 1511da177e4SLinus Torvalds 1521da177e4SLinus Torvalds mach_sched_init=dn_sched_init; /* */ 1531da177e4SLinus Torvalds mach_init_IRQ=dn_init_IRQ; 1541da177e4SLinus Torvalds mach_gettimeoffset = dn_gettimeoffset; 1551da177e4SLinus Torvalds mach_max_dma_address = 0xffffffff; 1561da177e4SLinus Torvalds mach_hwclk = dn_dummy_hwclk; /* */ 1571da177e4SLinus Torvalds mach_set_clock_mmss = dn_dummy_set_clock_mmss; /* */ 1581da177e4SLinus Torvalds mach_reset = dn_dummy_reset; /* */ 1591da177e4SLinus Torvalds #ifdef CONFIG_HEARTBEAT 1601da177e4SLinus Torvalds mach_heartbeat = dn_heartbeat; 1611da177e4SLinus Torvalds #endif 1621da177e4SLinus Torvalds mach_get_model = dn_get_model; 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds cpuctrl=0xaa00; 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds /* clear DMA translation table */ 1671da177e4SLinus Torvalds for(i=0;i<0x400;i++) 1681da177e4SLinus Torvalds addr_xlat_map[i]=0; 1691da177e4SLinus Torvalds 1701da177e4SLinus Torvalds } 1711da177e4SLinus Torvalds 1722850bc27SAl Viro irqreturn_t dn_timer_int(int irq, void *dev_id) 1730aa78106SRoman Zippel { 17440220c1aSDavid Howells irq_handler_t timer_handler = dev_id; 1751da177e4SLinus Torvalds 1761da177e4SLinus Torvalds volatile unsigned char x; 1771da177e4SLinus Torvalds 1782850bc27SAl Viro timer_handler(irq, dev_id); 1791da177e4SLinus Torvalds 180*1525e06eSGeert Uytterhoeven x = *(volatile unsigned char *)(apollo_timer + 3); 181*1525e06eSGeert Uytterhoeven x = *(volatile unsigned char *)(apollo_timer + 5); 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds return IRQ_HANDLED; 1841da177e4SLinus Torvalds } 1851da177e4SLinus Torvalds 18640220c1aSDavid Howells void dn_sched_init(irq_handler_t timer_routine) 1872850bc27SAl Viro { 1881da177e4SLinus Torvalds /* program timer 1 */ 189*1525e06eSGeert Uytterhoeven *(volatile unsigned char *)(apollo_timer + 3) = 0x01; 190*1525e06eSGeert Uytterhoeven *(volatile unsigned char *)(apollo_timer + 1) = 0x40; 191*1525e06eSGeert Uytterhoeven *(volatile unsigned char *)(apollo_timer + 5) = 0x09; 192*1525e06eSGeert Uytterhoeven *(volatile unsigned char *)(apollo_timer + 7) = 0xc4; 1931da177e4SLinus Torvalds 1941da177e4SLinus Torvalds /* enable IRQ of PIC B */ 1951da177e4SLinus Torvalds *(volatile unsigned char *)(pica+1)&=(~8); 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds #if 0 198*1525e06eSGeert Uytterhoeven printk("*(0x10803) %02x\n",*(volatile unsigned char *)(apollo_timer + 0x3)); 199*1525e06eSGeert Uytterhoeven printk("*(0x10803) %02x\n",*(volatile unsigned char *)(apollo_timer + 0x3)); 2001da177e4SLinus Torvalds #endif 2011da177e4SLinus Torvalds 20284430653SGeert Uytterhoeven if (request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", timer_routine)) 20384430653SGeert Uytterhoeven pr_err("Couldn't register timer interrupt\n"); 2041da177e4SLinus Torvalds } 2051da177e4SLinus Torvalds 2061da177e4SLinus Torvalds unsigned long dn_gettimeoffset(void) { 2071da177e4SLinus Torvalds 2081da177e4SLinus Torvalds return 0xdeadbeef; 2091da177e4SLinus Torvalds 2101da177e4SLinus Torvalds } 2111da177e4SLinus Torvalds 2121da177e4SLinus Torvalds int dn_dummy_hwclk(int op, struct rtc_time *t) { 2131da177e4SLinus Torvalds 2141da177e4SLinus Torvalds 2151da177e4SLinus Torvalds if(!op) { /* read */ 2161da177e4SLinus Torvalds t->tm_sec=rtc->second; 2171da177e4SLinus Torvalds t->tm_min=rtc->minute; 2181da177e4SLinus Torvalds t->tm_hour=rtc->hours; 2191da177e4SLinus Torvalds t->tm_mday=rtc->day_of_month; 2201da177e4SLinus Torvalds t->tm_wday=rtc->day_of_week; 2211da177e4SLinus Torvalds t->tm_mon=rtc->month; 2221da177e4SLinus Torvalds t->tm_year=rtc->year; 2231da177e4SLinus Torvalds } else { 2241da177e4SLinus Torvalds rtc->second=t->tm_sec; 2251da177e4SLinus Torvalds rtc->minute=t->tm_min; 2261da177e4SLinus Torvalds rtc->hours=t->tm_hour; 2271da177e4SLinus Torvalds rtc->day_of_month=t->tm_mday; 2281da177e4SLinus Torvalds if(t->tm_wday!=-1) 2291da177e4SLinus Torvalds rtc->day_of_week=t->tm_wday; 2301da177e4SLinus Torvalds rtc->month=t->tm_mon; 2311da177e4SLinus Torvalds rtc->year=t->tm_year; 2321da177e4SLinus Torvalds } 2331da177e4SLinus Torvalds 2341da177e4SLinus Torvalds return 0; 2351da177e4SLinus Torvalds 2361da177e4SLinus Torvalds } 2371da177e4SLinus Torvalds 2381da177e4SLinus Torvalds int dn_dummy_set_clock_mmss(unsigned long nowtime) { 2391da177e4SLinus Torvalds 2401da177e4SLinus Torvalds printk("set_clock_mmss\n"); 2411da177e4SLinus Torvalds 2421da177e4SLinus Torvalds return 0; 2431da177e4SLinus Torvalds 2441da177e4SLinus Torvalds } 2451da177e4SLinus Torvalds 2461da177e4SLinus Torvalds void dn_dummy_reset(void) { 2471da177e4SLinus Torvalds 2481da177e4SLinus Torvalds dn_serial_print("The end !\n"); 2491da177e4SLinus Torvalds 2501da177e4SLinus Torvalds for(;;); 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds } 2531da177e4SLinus Torvalds 2541da177e4SLinus Torvalds void dn_dummy_waitbut(void) { 2551da177e4SLinus Torvalds 2561da177e4SLinus Torvalds dn_serial_print("waitbut\n"); 2571da177e4SLinus Torvalds 2581da177e4SLinus Torvalds } 2591da177e4SLinus Torvalds 2601da177e4SLinus Torvalds static void dn_get_model(char *model) 2611da177e4SLinus Torvalds { 2621da177e4SLinus Torvalds strcpy(model, "Apollo "); 2631da177e4SLinus Torvalds if (apollo_model >= APOLLO_DN3000 && apollo_model <= APOLLO_DN4500) 2641da177e4SLinus Torvalds strcat(model, apollo_models[apollo_model - APOLLO_DN3000]); 2651da177e4SLinus Torvalds } 2661da177e4SLinus Torvalds 2671da177e4SLinus Torvalds #ifdef CONFIG_HEARTBEAT 2681da177e4SLinus Torvalds static int dn_cpuctrl=0xff00; 2691da177e4SLinus Torvalds 2701da177e4SLinus Torvalds static void dn_heartbeat(int on) { 2711da177e4SLinus Torvalds 2721da177e4SLinus Torvalds if(on) { 2731da177e4SLinus Torvalds dn_cpuctrl&=~0x100; 2741da177e4SLinus Torvalds cpuctrl=dn_cpuctrl; 2751da177e4SLinus Torvalds } 2761da177e4SLinus Torvalds else { 2771da177e4SLinus Torvalds dn_cpuctrl&=~0x100; 2781da177e4SLinus Torvalds dn_cpuctrl|=0x100; 2791da177e4SLinus Torvalds cpuctrl=dn_cpuctrl; 2801da177e4SLinus Torvalds } 2811da177e4SLinus Torvalds } 2821da177e4SLinus Torvalds #endif 2831da177e4SLinus Torvalds 284