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