diff options
Diffstat (limited to 'arch/m68k/apollo')
-rw-r--r-- | arch/m68k/apollo/Makefile | 5 | ||||
-rw-r--r-- | arch/m68k/apollo/config.c | 305 | ||||
-rw-r--r-- | arch/m68k/apollo/dma.c | 50 | ||||
-rw-r--r-- | arch/m68k/apollo/dn_ints.c | 125 |
4 files changed, 485 insertions, 0 deletions
diff --git a/arch/m68k/apollo/Makefile b/arch/m68k/apollo/Makefile new file mode 100644 index 000000000000..39264f3b6ad6 --- /dev/null +++ b/arch/m68k/apollo/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | # | ||
2 | # Makefile for Linux arch/m68k/amiga source directory | ||
3 | # | ||
4 | |||
5 | obj-y := config.o dn_ints.o dma.o | ||
diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c new file mode 100644 index 000000000000..264929471253 --- /dev/null +++ b/arch/m68k/apollo/config.c | |||
@@ -0,0 +1,305 @@ | |||
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 | |||
diff --git a/arch/m68k/apollo/dma.c b/arch/m68k/apollo/dma.c new file mode 100644 index 000000000000..aed8be177ef1 --- /dev/null +++ b/arch/m68k/apollo/dma.c | |||
@@ -0,0 +1,50 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/kernel.h> | ||
3 | #include <linux/mm.h> | ||
4 | #include <linux/kd.h> | ||
5 | #include <linux/tty.h> | ||
6 | #include <linux/console.h> | ||
7 | |||
8 | #include <asm/setup.h> | ||
9 | #include <asm/bootinfo.h> | ||
10 | #include <asm/system.h> | ||
11 | #include <asm/pgtable.h> | ||
12 | #include <asm/apollodma.h> | ||
13 | #include <asm/io.h> | ||
14 | |||
15 | /* note only works for 16 Bit 1 page DMA's */ | ||
16 | |||
17 | static unsigned short next_free_xlat_entry=0; | ||
18 | |||
19 | unsigned short dma_map_page(unsigned long phys_addr,int count,int type) { | ||
20 | |||
21 | unsigned long page_aligned_addr=phys_addr & (~((1<<12)-1)); | ||
22 | unsigned short start_map_addr=page_aligned_addr >> 10; | ||
23 | unsigned short free_xlat_entry, *xlat_map_entry; | ||
24 | int i; | ||
25 | |||
26 | free_xlat_entry=next_free_xlat_entry; | ||
27 | for(i=0,xlat_map_entry=addr_xlat_map+(free_xlat_entry<<2);i<8;i++,xlat_map_entry++) { | ||
28 | #if 0 | ||
29 | printk("phys_addr: %x, page_aligned_addr: %x, start_map_addr: %x\n",phys_addr,page_aligned_addr,start_map_addr+i); | ||
30 | #endif | ||
31 | out_be16(xlat_map_entry, start_map_addr+i); | ||
32 | } | ||
33 | |||
34 | next_free_xlat_entry+=2; | ||
35 | if(next_free_xlat_entry>125) | ||
36 | next_free_xlat_entry=0; | ||
37 | |||
38 | #if 0 | ||
39 | printk("next_free_xlat_entry: %d\n",next_free_xlat_entry); | ||
40 | #endif | ||
41 | |||
42 | return free_xlat_entry<<10; | ||
43 | } | ||
44 | |||
45 | void dma_unmap_page(unsigned short dma_addr) { | ||
46 | |||
47 | return ; | ||
48 | |||
49 | } | ||
50 | |||
diff --git a/arch/m68k/apollo/dn_ints.c b/arch/m68k/apollo/dn_ints.c new file mode 100644 index 000000000000..a31259359a12 --- /dev/null +++ b/arch/m68k/apollo/dn_ints.c | |||
@@ -0,0 +1,125 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/kernel.h> | ||
3 | #include <linux/jiffies.h> | ||
4 | #include <linux/kernel_stat.h> | ||
5 | #include <linux/timer.h> | ||
6 | |||
7 | #include <asm/system.h> | ||
8 | #include <asm/irq.h> | ||
9 | #include <asm/traps.h> | ||
10 | #include <asm/page.h> | ||
11 | #include <asm/machdep.h> | ||
12 | #include <asm/apollohw.h> | ||
13 | #include <asm/errno.h> | ||
14 | |||
15 | static irq_handler_t dn_irqs[16]; | ||
16 | |||
17 | irqreturn_t dn_process_int(int irq, struct pt_regs *fp) | ||
18 | { | ||
19 | irqreturn_t res = IRQ_NONE; | ||
20 | |||
21 | if(dn_irqs[irq-160].handler) { | ||
22 | res = dn_irqs[irq-160].handler(irq,dn_irqs[irq-160].dev_id,fp); | ||
23 | } else { | ||
24 | printk("spurious irq %d occurred\n",irq); | ||
25 | } | ||
26 | |||
27 | *(volatile unsigned char *)(pica)=0x20; | ||
28 | *(volatile unsigned char *)(picb)=0x20; | ||
29 | |||
30 | return res; | ||
31 | } | ||
32 | |||
33 | void dn_init_IRQ(void) { | ||
34 | |||
35 | int i; | ||
36 | |||
37 | for(i=0;i<16;i++) { | ||
38 | dn_irqs[i].handler=NULL; | ||
39 | dn_irqs[i].flags=IRQ_FLG_STD; | ||
40 | dn_irqs[i].dev_id=NULL; | ||
41 | dn_irqs[i].devname=NULL; | ||
42 | } | ||
43 | |||
44 | } | ||
45 | |||
46 | int dn_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) { | ||
47 | |||
48 | if((irq<0) || (irq>15)) { | ||
49 | printk("Trying to request invalid IRQ\n"); | ||
50 | return -ENXIO; | ||
51 | } | ||
52 | |||
53 | if(!dn_irqs[irq].handler) { | ||
54 | dn_irqs[irq].handler=handler; | ||
55 | dn_irqs[irq].flags=IRQ_FLG_STD; | ||
56 | dn_irqs[irq].dev_id=dev_id; | ||
57 | dn_irqs[irq].devname=devname; | ||
58 | if(irq<8) | ||
59 | *(volatile unsigned char *)(pica+1)&=~(1<<irq); | ||
60 | else | ||
61 | *(volatile unsigned char *)(picb+1)&=~(1<<(irq-8)); | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | else { | ||
66 | printk("Trying to request already assigned irq %d\n",irq); | ||
67 | return -ENXIO; | ||
68 | } | ||
69 | |||
70 | } | ||
71 | |||
72 | void dn_free_irq(unsigned int irq, void *dev_id) { | ||
73 | |||
74 | if((irq<0) || (irq>15)) { | ||
75 | printk("Trying to free invalid IRQ\n"); | ||
76 | return ; | ||
77 | } | ||
78 | |||
79 | if(irq<8) | ||
80 | *(volatile unsigned char *)(pica+1)|=(1<<irq); | ||
81 | else | ||
82 | *(volatile unsigned char *)(picb+1)|=(1<<(irq-8)); | ||
83 | |||
84 | dn_irqs[irq].handler=NULL; | ||
85 | dn_irqs[irq].flags=IRQ_FLG_STD; | ||
86 | dn_irqs[irq].dev_id=NULL; | ||
87 | dn_irqs[irq].devname=NULL; | ||
88 | |||
89 | return ; | ||
90 | |||
91 | } | ||
92 | |||
93 | void dn_enable_irq(unsigned int irq) { | ||
94 | |||
95 | printk("dn enable irq\n"); | ||
96 | |||
97 | } | ||
98 | |||
99 | void dn_disable_irq(unsigned int irq) { | ||
100 | |||
101 | printk("dn disable irq\n"); | ||
102 | |||
103 | } | ||
104 | |||
105 | int show_dn_interrupts(struct seq_file *p, void *v) { | ||
106 | |||
107 | printk("dn get irq list\n"); | ||
108 | |||
109 | return 0; | ||
110 | |||
111 | } | ||
112 | |||
113 | struct fb_info *dn_dummy_fb_init(long *mem_start) { | ||
114 | |||
115 | printk("fb init\n"); | ||
116 | |||
117 | return NULL; | ||
118 | |||
119 | } | ||
120 | |||
121 | void dn_dummy_video_setup(char *options,int *ints) { | ||
122 | |||
123 | printk("no video yet\n"); | ||
124 | |||
125 | } | ||