1#include <linux/init.h> 2#include <linux/types.h> 3#include <linux/kernel.h> 4#include <linux/mm.h> 5#include <linux/tty.h> 6#include <linux/console.h> 7#include <linux/rtc.h> 8#include <linux/vt_kern.h> 9#include <linux/interrupt.h> 10 11#include <asm/setup.h> 12#include <asm/bootinfo.h> 13#include <asm/bootinfo-apollo.h> 14#include <asm/byteorder.h> 15#include <asm/pgtable.h> 16#include <asm/apollohw.h> 17#include <asm/irq.h> 18#include <asm/rtc.h> 19#include <asm/machdep.h> 20 21u_long sio01_physaddr; 22u_long sio23_physaddr; 23u_long rtc_physaddr; 24u_long pica_physaddr; 25u_long picb_physaddr; 26u_long cpuctrl_physaddr; 27u_long timer_physaddr; 28u_long apollo_model; 29 30extern void dn_sched_init(irq_handler_t handler); 31extern void dn_init_IRQ(void); 32extern u32 dn_gettimeoffset(void); 33extern int dn_dummy_hwclk(int, struct rtc_time *); 34extern int dn_dummy_set_clock_mmss(unsigned long); 35extern void dn_dummy_reset(void); 36#ifdef CONFIG_HEARTBEAT 37static void dn_heartbeat(int on); 38#endif 39static irqreturn_t dn_timer_int(int irq,void *); 40static void dn_get_model(char *model); 41static const char *apollo_models[] = { 42 [APOLLO_DN3000-APOLLO_DN3000] = "DN3000 (Otter)", 43 [APOLLO_DN3010-APOLLO_DN3000] = "DN3010 (Otter)", 44 [APOLLO_DN3500-APOLLO_DN3000] = "DN3500 (Cougar II)", 45 [APOLLO_DN4000-APOLLO_DN3000] = "DN4000 (Mink)", 46 [APOLLO_DN4500-APOLLO_DN3000] = "DN4500 (Roadrunner)" 47}; 48 49int __init apollo_parse_bootinfo(const struct bi_record *record) 50{ 51 int unknown = 0; 52 const void *data = record->data; 53 54 switch (be16_to_cpu(record->tag)) { 55 case BI_APOLLO_MODEL: 56 apollo_model = be32_to_cpup(data); 57 break; 58 59 default: 60 unknown=1; 61 } 62 63 return unknown; 64} 65 66static void __init dn_setup_model(void) 67{ 68 pr_info("Apollo hardware found: [%s]\n", 69 apollo_models[apollo_model - APOLLO_DN3000]); 70 71 switch(apollo_model) { 72 case APOLLO_UNKNOWN: 73 panic("Unknown apollo model"); 74 break; 75 case APOLLO_DN3000: 76 case APOLLO_DN3010: 77 sio01_physaddr=SAU8_SIO01_PHYSADDR; 78 rtc_physaddr=SAU8_RTC_PHYSADDR; 79 pica_physaddr=SAU8_PICA; 80 picb_physaddr=SAU8_PICB; 81 cpuctrl_physaddr=SAU8_CPUCTRL; 82 timer_physaddr=SAU8_TIMER; 83 break; 84 case APOLLO_DN4000: 85 sio01_physaddr=SAU7_SIO01_PHYSADDR; 86 sio23_physaddr=SAU7_SIO23_PHYSADDR; 87 rtc_physaddr=SAU7_RTC_PHYSADDR; 88 pica_physaddr=SAU7_PICA; 89 picb_physaddr=SAU7_PICB; 90 cpuctrl_physaddr=SAU7_CPUCTRL; 91 timer_physaddr=SAU7_TIMER; 92 break; 93 case APOLLO_DN4500: 94 panic("Apollo model not yet supported"); 95 break; 96 case APOLLO_DN3500: 97 sio01_physaddr=SAU7_SIO01_PHYSADDR; 98 sio23_physaddr=SAU7_SIO23_PHYSADDR; 99 rtc_physaddr=SAU7_RTC_PHYSADDR; 100 pica_physaddr=SAU7_PICA; 101 picb_physaddr=SAU7_PICB; 102 cpuctrl_physaddr=SAU7_CPUCTRL; 103 timer_physaddr=SAU7_TIMER; 104 break; 105 default: 106 panic("Undefined apollo model"); 107 break; 108 } 109 110 111} 112 113int dn_serial_console_wait_key(struct console *co) { 114 115 while(!(sio01.srb_csrb & 1)) 116 barrier(); 117 return sio01.rhrb_thrb; 118} 119 120void dn_serial_console_write (struct console *co, const char *str,unsigned int count) 121{ 122 while(count--) { 123 if (*str == '\n') { 124 sio01.rhrb_thrb = (unsigned char)'\r'; 125 while (!(sio01.srb_csrb & 0x4)) 126 ; 127 } 128 sio01.rhrb_thrb = (unsigned char)*str++; 129 while (!(sio01.srb_csrb & 0x4)) 130 ; 131 } 132} 133 134void dn_serial_print (const char *str) 135{ 136 while (*str) { 137 if (*str == '\n') { 138 sio01.rhrb_thrb = (unsigned char)'\r'; 139 while (!(sio01.srb_csrb & 0x4)) 140 ; 141 } 142 sio01.rhrb_thrb = (unsigned char)*str++; 143 while (!(sio01.srb_csrb & 0x4)) 144 ; 145 } 146} 147 148void __init config_apollo(void) 149{ 150 int i; 151 152 dn_setup_model(); 153 154 mach_sched_init=dn_sched_init; /* */ 155 mach_init_IRQ=dn_init_IRQ; 156 arch_gettimeoffset = dn_gettimeoffset; 157 mach_max_dma_address = 0xffffffff; 158 mach_hwclk = dn_dummy_hwclk; /* */ 159 mach_set_clock_mmss = dn_dummy_set_clock_mmss; /* */ 160 mach_reset = dn_dummy_reset; /* */ 161#ifdef CONFIG_HEARTBEAT 162 mach_heartbeat = dn_heartbeat; 163#endif 164 mach_get_model = dn_get_model; 165 166 cpuctrl=0xaa00; 167 168 /* clear DMA translation table */ 169 for(i=0;i<0x400;i++) 170 addr_xlat_map[i]=0; 171 172} 173 174irqreturn_t dn_timer_int(int irq, void *dev_id) 175{ 176 irq_handler_t timer_handler = dev_id; 177 178 volatile unsigned char x; 179 180 timer_handler(irq, dev_id); 181 182 x = *(volatile unsigned char *)(apollo_timer + 3); 183 x = *(volatile unsigned char *)(apollo_timer + 5); 184 185 return IRQ_HANDLED; 186} 187 188void dn_sched_init(irq_handler_t timer_routine) 189{ 190 /* program timer 1 */ 191 *(volatile unsigned char *)(apollo_timer + 3) = 0x01; 192 *(volatile unsigned char *)(apollo_timer + 1) = 0x40; 193 *(volatile unsigned char *)(apollo_timer + 5) = 0x09; 194 *(volatile unsigned char *)(apollo_timer + 7) = 0xc4; 195 196 /* enable IRQ of PIC B */ 197 *(volatile unsigned char *)(pica+1)&=(~8); 198 199#if 0 200 pr_info("*(0x10803) %02x\n", 201 *(volatile unsigned char *)(apollo_timer + 0x3)); 202 pr_info("*(0x10803) %02x\n", 203 *(volatile unsigned char *)(apollo_timer + 0x3)); 204#endif 205 206 if (request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", timer_routine)) 207 pr_err("Couldn't register timer interrupt\n"); 208} 209 210u32 dn_gettimeoffset(void) 211{ 212 return 0xdeadbeef; 213} 214 215int dn_dummy_hwclk(int op, struct rtc_time *t) { 216 217 218 if(!op) { /* read */ 219 t->tm_sec=rtc->second; 220 t->tm_min=rtc->minute; 221 t->tm_hour=rtc->hours; 222 t->tm_mday=rtc->day_of_month; 223 t->tm_wday=rtc->day_of_week; 224 t->tm_mon=rtc->month; 225 t->tm_year=rtc->year; 226 } else { 227 rtc->second=t->tm_sec; 228 rtc->minute=t->tm_min; 229 rtc->hours=t->tm_hour; 230 rtc->day_of_month=t->tm_mday; 231 if(t->tm_wday!=-1) 232 rtc->day_of_week=t->tm_wday; 233 rtc->month=t->tm_mon; 234 rtc->year=t->tm_year; 235 } 236 237 return 0; 238 239} 240 241int dn_dummy_set_clock_mmss(unsigned long nowtime) 242{ 243 pr_info("set_clock_mmss\n"); 244 return 0; 245} 246 247void dn_dummy_reset(void) { 248 249 dn_serial_print("The end !\n"); 250 251 for(;;); 252 253} 254 255void dn_dummy_waitbut(void) { 256 257 dn_serial_print("waitbut\n"); 258 259} 260 261static void dn_get_model(char *model) 262{ 263 strcpy(model, "Apollo "); 264 if (apollo_model >= APOLLO_DN3000 && apollo_model <= APOLLO_DN4500) 265 strcat(model, apollo_models[apollo_model - APOLLO_DN3000]); 266} 267 268#ifdef CONFIG_HEARTBEAT 269static int dn_cpuctrl=0xff00; 270 271static void dn_heartbeat(int on) { 272 273 if(on) { 274 dn_cpuctrl&=~0x100; 275 cpuctrl=dn_cpuctrl; 276 } 277 else { 278 dn_cpuctrl&=~0x100; 279 dn_cpuctrl|=0x100; 280 cpuctrl=dn_cpuctrl; 281 } 282} 283#endif 284 285