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