Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | #include <linux/config.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/system.h> | |
14 | #include <asm/pgtable.h> | |
15 | #include <asm/apollohw.h> | |
16 | #include <asm/irq.h> | |
17 | #include <asm/rtc.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(irqreturn_t (*handler)(int,void *,struct pt_regs *)); | |
30 | extern void dn_init_IRQ(void); | |
31 | extern int dn_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); | |
32 | extern void dn_free_irq(unsigned int irq, void *dev_id); | |
33 | extern void dn_enable_irq(unsigned int); | |
34 | extern void dn_disable_irq(unsigned int); | |
35 | extern int show_dn_interrupts(struct seq_file *, void *); | |
36 | extern unsigned long dn_gettimeoffset(void); | |
37 | extern int dn_dummy_hwclk(int, struct rtc_time *); | |
38 | extern int dn_dummy_set_clock_mmss(unsigned long); | |
39 | extern void dn_dummy_reset(void); | |
40 | extern void dn_dummy_waitbut(void); | |
41 | extern struct fb_info *dn_fb_init(long *); | |
42 | extern void dn_dummy_debug_init(void); | |
43 | extern void dn_dummy_video_setup(char *,int *); | |
44 | extern irqreturn_t dn_process_int(int irq, struct pt_regs *fp); | |
45 | #ifdef CONFIG_HEARTBEAT | |
46 | static void dn_heartbeat(int on); | |
47 | #endif | |
48 | static irqreturn_t dn_timer_int(int irq,void *, struct pt_regs *); | |
49 | static irqreturn_t (*sched_timer_handler)(int, void *, struct pt_regs *)=NULL; | |
50 | static void dn_get_model(char *model); | |
51 | static const char *apollo_models[] = { | |
52 | [APOLLO_DN3000-APOLLO_DN3000] = "DN3000 (Otter)", | |
53 | [APOLLO_DN3010-APOLLO_DN3000] = "DN3010 (Otter)", | |
54 | [APOLLO_DN3500-APOLLO_DN3000] = "DN3500 (Cougar II)", | |
55 | [APOLLO_DN4000-APOLLO_DN3000] = "DN4000 (Mink)", | |
56 | [APOLLO_DN4500-APOLLO_DN3000] = "DN4500 (Roadrunner)" | |
57 | }; | |
58 | ||
59 | int apollo_parse_bootinfo(const struct bi_record *record) { | |
60 | ||
61 | int unknown = 0; | |
62 | const unsigned long *data = record->data; | |
63 | ||
64 | switch(record->tag) { | |
65 | case BI_APOLLO_MODEL: | |
66 | apollo_model=*data; | |
67 | break; | |
68 | ||
69 | default: | |
70 | unknown=1; | |
71 | } | |
72 | ||
73 | return unknown; | |
74 | } | |
75 | ||
76 | void dn_setup_model(void) { | |
77 | ||
78 | ||
79 | printk("Apollo hardware found: "); | |
80 | printk("[%s]\n", apollo_models[apollo_model - APOLLO_DN3000]); | |
81 | ||
82 | switch(apollo_model) { | |
83 | case APOLLO_UNKNOWN: | |
84 | panic("Unknown apollo model"); | |
85 | break; | |
86 | case APOLLO_DN3000: | |
87 | case APOLLO_DN3010: | |
88 | sio01_physaddr=SAU8_SIO01_PHYSADDR; | |
89 | rtc_physaddr=SAU8_RTC_PHYSADDR; | |
90 | pica_physaddr=SAU8_PICA; | |
91 | picb_physaddr=SAU8_PICB; | |
92 | cpuctrl_physaddr=SAU8_CPUCTRL; | |
93 | timer_physaddr=SAU8_TIMER; | |
94 | break; | |
95 | case APOLLO_DN4000: | |
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 | case APOLLO_DN4500: | |
105 | panic("Apollo model not yet supported"); | |
106 | break; | |
107 | case APOLLO_DN3500: | |
108 | sio01_physaddr=SAU7_SIO01_PHYSADDR; | |
109 | sio23_physaddr=SAU7_SIO23_PHYSADDR; | |
110 | rtc_physaddr=SAU7_RTC_PHYSADDR; | |
111 | pica_physaddr=SAU7_PICA; | |
112 | picb_physaddr=SAU7_PICB; | |
113 | cpuctrl_physaddr=SAU7_CPUCTRL; | |
114 | timer_physaddr=SAU7_TIMER; | |
115 | break; | |
116 | default: | |
117 | panic("Undefined apollo model"); | |
118 | break; | |
119 | } | |
120 | ||
121 | ||
122 | } | |
123 | ||
124 | int dn_serial_console_wait_key(struct console *co) { | |
125 | ||
126 | while(!(sio01.srb_csrb & 1)) | |
127 | barrier(); | |
128 | return sio01.rhrb_thrb; | |
129 | } | |
130 | ||
131 | void dn_serial_console_write (struct console *co, const char *str,unsigned int count) | |
132 | { | |
133 | while(count--) { | |
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 dn_serial_print (const char *str) | |
146 | { | |
147 | while (*str) { | |
148 | if (*str == '\n') { | |
149 | sio01.rhrb_thrb = (unsigned char)'\r'; | |
150 | while (!(sio01.srb_csrb & 0x4)) | |
151 | ; | |
152 | } | |
153 | sio01.rhrb_thrb = (unsigned char)*str++; | |
154 | while (!(sio01.srb_csrb & 0x4)) | |
155 | ; | |
156 | } | |
157 | } | |
158 | ||
159 | void config_apollo(void) { | |
160 | ||
161 | int i; | |
162 | ||
163 | dn_setup_model(); | |
164 | ||
165 | mach_sched_init=dn_sched_init; /* */ | |
166 | mach_init_IRQ=dn_init_IRQ; | |
167 | mach_default_handler=NULL; | |
168 | mach_request_irq = dn_request_irq; | |
169 | mach_free_irq = dn_free_irq; | |
170 | enable_irq = dn_enable_irq; | |
171 | disable_irq = dn_disable_irq; | |
172 | mach_get_irq_list = show_dn_interrupts; | |
173 | mach_gettimeoffset = dn_gettimeoffset; | |
174 | mach_max_dma_address = 0xffffffff; | |
175 | mach_hwclk = dn_dummy_hwclk; /* */ | |
176 | mach_set_clock_mmss = dn_dummy_set_clock_mmss; /* */ | |
177 | mach_process_int = dn_process_int; | |
178 | mach_reset = dn_dummy_reset; /* */ | |
179 | #ifdef CONFIG_DUMMY_CONSOLE | |
180 | conswitchp = &dummy_con; | |
181 | #endif | |
182 | #ifdef CONFIG_HEARTBEAT | |
183 | mach_heartbeat = dn_heartbeat; | |
184 | #endif | |
185 | mach_get_model = dn_get_model; | |
186 | ||
187 | cpuctrl=0xaa00; | |
188 | ||
189 | /* clear DMA translation table */ | |
190 | for(i=0;i<0x400;i++) | |
191 | addr_xlat_map[i]=0; | |
192 | ||
193 | } | |
194 | ||
195 | irqreturn_t dn_timer_int(int irq, void *dev_id, struct pt_regs *fp) { | |
196 | ||
197 | volatile unsigned char x; | |
198 | ||
199 | sched_timer_handler(irq,dev_id,fp); | |
200 | ||
201 | x=*(volatile unsigned char *)(timer+3); | |
202 | x=*(volatile unsigned char *)(timer+5); | |
203 | ||
204 | return IRQ_HANDLED; | |
205 | } | |
206 | ||
207 | void dn_sched_init(irqreturn_t (*timer_routine)(int, void *, struct pt_regs *)) { | |
208 | ||
209 | /* program timer 1 */ | |
210 | *(volatile unsigned char *)(timer+3)=0x01; | |
211 | *(volatile unsigned char *)(timer+1)=0x40; | |
212 | *(volatile unsigned char *)(timer+5)=0x09; | |
213 | *(volatile unsigned char *)(timer+7)=0xc4; | |
214 | ||
215 | /* enable IRQ of PIC B */ | |
216 | *(volatile unsigned char *)(pica+1)&=(~8); | |
217 | ||
218 | #if 0 | |
219 | printk("*(0x10803) %02x\n",*(volatile unsigned char *)(timer+0x3)); | |
220 | printk("*(0x10803) %02x\n",*(volatile unsigned char *)(timer+0x3)); | |
221 | #endif | |
222 | ||
223 | sched_timer_handler=timer_routine; | |
224 | request_irq(0,dn_timer_int,0,NULL,NULL); | |
225 | ||
226 | } | |
227 | ||
228 | unsigned long dn_gettimeoffset(void) { | |
229 | ||
230 | return 0xdeadbeef; | |
231 | ||
232 | } | |
233 | ||
234 | int dn_dummy_hwclk(int op, struct rtc_time *t) { | |
235 | ||
236 | ||
237 | if(!op) { /* read */ | |
238 | t->tm_sec=rtc->second; | |
239 | t->tm_min=rtc->minute; | |
240 | t->tm_hour=rtc->hours; | |
241 | t->tm_mday=rtc->day_of_month; | |
242 | t->tm_wday=rtc->day_of_week; | |
243 | t->tm_mon=rtc->month; | |
244 | t->tm_year=rtc->year; | |
245 | } else { | |
246 | rtc->second=t->tm_sec; | |
247 | rtc->minute=t->tm_min; | |
248 | rtc->hours=t->tm_hour; | |
249 | rtc->day_of_month=t->tm_mday; | |
250 | if(t->tm_wday!=-1) | |
251 | rtc->day_of_week=t->tm_wday; | |
252 | rtc->month=t->tm_mon; | |
253 | rtc->year=t->tm_year; | |
254 | } | |
255 | ||
256 | return 0; | |
257 | ||
258 | } | |
259 | ||
260 | int dn_dummy_set_clock_mmss(unsigned long nowtime) { | |
261 | ||
262 | printk("set_clock_mmss\n"); | |
263 | ||
264 | return 0; | |
265 | ||
266 | } | |
267 | ||
268 | void dn_dummy_reset(void) { | |
269 | ||
270 | dn_serial_print("The end !\n"); | |
271 | ||
272 | for(;;); | |
273 | ||
274 | } | |
275 | ||
276 | void dn_dummy_waitbut(void) { | |
277 | ||
278 | dn_serial_print("waitbut\n"); | |
279 | ||
280 | } | |
281 | ||
282 | static void dn_get_model(char *model) | |
283 | { | |
284 | strcpy(model, "Apollo "); | |
285 | if (apollo_model >= APOLLO_DN3000 && apollo_model <= APOLLO_DN4500) | |
286 | strcat(model, apollo_models[apollo_model - APOLLO_DN3000]); | |
287 | } | |
288 | ||
289 | #ifdef CONFIG_HEARTBEAT | |
290 | static int dn_cpuctrl=0xff00; | |
291 | ||
292 | static void dn_heartbeat(int on) { | |
293 | ||
294 | if(on) { | |
295 | dn_cpuctrl&=~0x100; | |
296 | cpuctrl=dn_cpuctrl; | |
297 | } | |
298 | else { | |
299 | dn_cpuctrl&=~0x100; | |
300 | dn_cpuctrl|=0x100; | |
301 | cpuctrl=dn_cpuctrl; | |
302 | } | |
303 | } | |
304 | #endif | |
305 |