relayd: move the interface fixup to the right place
[openwrt.git] / target / linux / coldfire / files-2.6.31 / arch / m68k / coldfire / m547x / config.c
1 /*
2  *  linux/arch/m68k/coldfire/config.c
3  *
4  *  Copyright 2007-2009 Freescale Semiconductor, Inc. All Rights Reserved.
5  *  Kurt Mahan kmahan@freescale.com
6  *  Matt Waddel Matt.Waddel@freescale.com
7  *  Shrek Wu b16972@freescale.com
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  */
14
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/string.h>
18 #include <linux/kernel.h>
19 #include <linux/console.h>
20 #include <linux/bootmem.h>
21 #include <linux/mm.h>
22 #include <linux/clockchips.h>
23 #include <asm/bootinfo.h>
24 #include <asm/machdep.h>
25 #include <asm/coldfire.h>
26 #include <asm/cfcache.h>
27 #include <asm/cacheflush.h>
28 #include <linux/io.h>
29 #include <asm/cfmmu.h>
30 #include <asm/setup.h>
31 #include <asm/irq.h>
32 #include <asm/traps.h>
33 #include <asm/movs.h>
34 #include <asm/movs.h>
35 #include <asm/page.h>
36 #include <asm/pgalloc.h>
37
38 #include <asm/mcfsim.h>
39
40 #define UBOOT_PCI
41 #include <asm/bootinfo.h>
42 #include <asm/m5485gpt.h>
43
44 extern int get_irq_list(struct seq_file *p, void *v);
45 extern char _text, _end;
46 extern char _etext, _edata, __init_begin, __init_end;
47 extern struct console mcfrs_console;
48 extern char m68k_command_line[CL_SIZE];
49 extern unsigned long availmem;
50
51 static int irq_enable[NR_IRQS];
52 unsigned long num_pages;
53
54 /* cf dma physical addresses */
55 unsigned long cf_dma_base;
56 unsigned long cf_dma_end;
57 unsigned long cf_dma_size;
58 EXPORT_SYMBOL(cf_dma_base);
59 EXPORT_SYMBOL(cf_dma_end);
60 EXPORT_SYMBOL(cf_dma_size);
61
62 /* ethernet mac addresses from uboot */
63 unsigned char uboot_enet0[6];
64 unsigned char uboot_enet1[6];
65
66 void coldfire_sort_memrec(void)
67 {
68         int i, j;
69
70         /* Sort the m68k_memory records by address */
71         for (i = 0; i < m68k_num_memory; ++i) {
72                 for (j = i + 1; j < m68k_num_memory; ++j) {
73                         if (m68k_memory[i].addr > m68k_memory[j].addr) {
74                                 struct mem_info tmp;
75                                 tmp = m68k_memory[i];
76                                 m68k_memory[i] = m68k_memory[j];
77                                 m68k_memory[j] = tmp;
78                         }
79                 }
80         }
81         /* Trim off discontiguous bits */
82         for (i = 1; i < m68k_num_memory; ++i) {
83                 if ((m68k_memory[i-1].addr + m68k_memory[i-1].size) !=
84                         m68k_memory[i].addr) {
85                         printk(KERN_DEBUG "m68k_parse_bootinfo: "
86                                 "addr gap between 0x%lx & 0x%lx\n",
87                                 m68k_memory[i-1].addr+m68k_memory[i-1].size,
88                                 m68k_memory[i].addr);
89                         m68k_num_memory = i;
90                         break;
91                 }
92         }
93 }
94
95 /*
96  * UBoot Handler
97  */
98 int __init uboot_commandline(char *bootargs)
99 {
100         int len = 0, cmd_line_len;
101         static struct uboot_record uboot_info;
102         u32 offset = PAGE_OFFSET_RAW - PHYS_OFFSET;
103
104         extern unsigned long uboot_info_stk;
105
106         /* validate address */
107         if ((uboot_info_stk < PAGE_OFFSET_RAW) ||
108             (uboot_info_stk >= (PAGE_OFFSET_RAW + CONFIG_SDRAM_SIZE)))
109                 return 0;
110
111         /* Add offset to get post-remapped kernel memory location */
112         uboot_info.bdi = (struct bd_info *)((*(u32 *)(uboot_info_stk))
113                                                         + offset);
114         uboot_info.initrd_start = (*(u32 *)(uboot_info_stk+4)) + offset;
115         uboot_info.initrd_end = (*(u32 *)(uboot_info_stk+8)) + offset;
116         uboot_info.cmd_line_start = (*(u32 *)(uboot_info_stk+12)) + offset;
117         uboot_info.cmd_line_stop = (*(u32 *)(uboot_info_stk+16)) + offset;
118
119         /* copy over mac addresses */
120         memcpy(uboot_enet0, uboot_info.bdi->bi_enet0addr, 6);
121         memcpy(uboot_enet1, uboot_info.bdi->bi_enet1addr, 6);
122
123         /* copy command line */
124         cmd_line_len = uboot_info.cmd_line_stop - uboot_info.cmd_line_start;
125         if ((cmd_line_len > 0) && (cmd_line_len < CL_SIZE-1))
126                 len = (int)strncpy(bootargs, (char *)uboot_info.cmd_line_start,\
127                                    cmd_line_len);
128
129         return len;
130 }
131
132 /*
133  * This routine does things not done in the bootloader.
134  */
135 #define DEFAULT_COMMAND_LINE \
136         "debug root=/dev/nfs rw \
137         nfsroot=172.27.155.1:/tftpboot/rigo/rootfs/ \
138         ip=172.27.155.75:172.27.155.1"
139
140 asmlinkage void __init cf_early_init(void)
141 {
142         struct bi_record *record = (struct bi_record *) &_end;
143
144         extern char _end;
145
146         SET_VBR((void *)MCF_RAMBAR0);
147
148         /* Mask all interrupts */
149         MCF_IMRL = 0xFFFFFFFF;
150         MCF_IMRH = 0xFFFFFFFF;
151
152         m68k_machtype = MACH_CFMMU;
153         m68k_fputype = FPU_CFV4E;
154         m68k_mmutype = MMU_CFV4E;
155         m68k_cputype = CPU_CFV4E;
156
157         m68k_num_memory = 0;
158         m68k_memory[m68k_num_memory].addr = CONFIG_SDRAM_BASE;
159         m68k_memory[m68k_num_memory++].size = CONFIG_SDRAM_SIZE;
160
161         if (!uboot_commandline(m68k_command_line)) {
162 #if defined(CONFIG_BOOTPARAM)
163                 strncpy(m68k_command_line, CONFIG_BOOTPARAM_STRING, CL_SIZE-1);
164 #else
165                 strcpy(m68k_command_line, DEFAULT_COMMAND_LINE);
166 #endif
167         }
168
169 #if defined(CONFIG_BLK_DEV_INITRD)
170         /* add initrd image */
171         record = (struct bi_record *) ((void *)record + record->size);
172         record->tag = BI_RAMDISK;
173         record->size =  sizeof(record->tag) + sizeof(record->size)
174                 + sizeof(record->data[0]) + sizeof(record->data[1]);
175 #endif
176
177         /* Mark end of tags. */
178         record = (struct bi_record *) ((void *) record + record->size);
179         record->tag = 0;
180         record->data[0] = 0;
181         record->data[1] = 0;
182         record->size = sizeof(record->tag) + sizeof(record->size)
183                 + sizeof(record->data[0]) + sizeof(record->data[1]);
184
185         /* Invalidate caches via CACR */
186         flush_bcache();
187         cacr_set(CACHE_DISABLE_MODE);
188
189         /* Turn on caches via CACR, enable EUSP */
190         cacr_set(CACHE_INITIAL_MODE);
191
192 }
193
194 /* Assembler routines */
195 asmlinkage void buserr(void);
196 asmlinkage void trap(void);
197 asmlinkage void system_call(void);
198 asmlinkage void inthandler(void);
199
200 void __init coldfire_trap_init(void)
201 {
202         int i = 0;
203         e_vector *vectors;
204
205         vectors = (e_vector *)MCF_RAMBAR0;
206         /*
207          * There is a common trap handler and common interrupt
208          * handler that handle almost every vector. We treat
209          * the system call and bus error special, they get their
210          * own first level handlers.
211          */
212         for (i = 3; (i <= 23); i++)
213                 vectors[i] = trap;
214         for (i = 33; (i <= 63); i++)
215                 vectors[i] = trap;
216         for (i = 24; (i <= 31); i++)
217                 vectors[i] = inthandler;
218         for (i = 64; (i < 255); i++)
219                 vectors[i] = inthandler;
220
221         vectors[255] = 0;
222         vectors[2] = buserr;
223         vectors[32] = system_call;
224 }
225
226 #ifndef CONFIG_GENERIC_CLOCKEVENTS
227 void coldfire_tick(void)
228 {
229         /* Reset the ColdFire timer */
230         MCF_SSR(0) = MCF_SSR_ST;
231 }
232
233 void __init coldfire_sched_init(irq_handler_t handler)
234 {
235         int irq = ISC_SLTn(0);
236
237         MCF_SCR(0) = 0;
238         MCF_ICR(irq) = ILP_SLT0;
239         request_irq(64 + irq, handler, IRQF_DISABLED, "ColdFire Timer 0", NULL);
240         MCF_SLTCNT(0) = MCF_BUSCLK / HZ;
241         MCF_SCR(0) |=  MCF_SCR_TEN | MCF_SCR_IEN | MCF_SCR_RUN;
242 }
243
244 unsigned long coldfire_gettimeoffset(void)
245 {
246         volatile unsigned long trr, tcn, offset;
247         trr = MCF_SLTCNT(0);
248         tcn = MCF_SCNT(0);
249
250         offset = (trr - tcn) * ((1000000 >> 3) / HZ) / (trr >> 3);
251         if (MCF_SSR(0) & MCF_SSR_ST)
252                 offset += 1000000 / HZ;
253
254         return offset;
255 }
256 #else
257 static unsigned long long sched_dtim_clk_val;
258
259 unsigned long long sched_clock(void)
260 {
261         unsigned long flags;
262         unsigned long long cycles;
263         volatile unsigned long trr, tcn, offset;
264
265         local_irq_save(flags);
266         trr = MCF_SLTCNT(0);
267         tcn = MCF_SCNT(0);
268         offset = (trr - tcn);
269         cycles = sched_dtim_clk_val;
270         local_irq_restore(flags);
271
272         return cycles + offset;
273 }
274
275 unsigned long long sys_dtim2_read(void)
276 {
277         unsigned long flags;
278         unsigned long long cycles;
279         volatile unsigned long trr, tcn, offset;
280
281         local_irq_save(flags);
282         trr = MCF_SLTCNT(0);
283         tcn = MCF_SCNT(0);
284         offset = (trr - tcn);
285         cycles = sched_dtim_clk_val;
286         local_irq_restore(flags);
287
288         return cycles + offset;
289 }
290
291 static irqreturn_t coldfire_dtim_clk_irq(int irq, void *dev)
292 {
293         struct clock_event_device *evt =
294                 (struct clock_event_device *)dev;
295
296         MCF_SSR(0) = MCF_SSR_ST;
297         sched_dtim_clk_val +=  (MCF_BUSCLK) / HZ;;
298         evt->event_handler(evt);
299         return IRQ_HANDLED;
300 }
301
302 void sys_dtim2_init(struct clock_event_device *evt)
303 {
304         int irq = ISC_SLTn(0);
305
306         sched_dtim_clk_val = 0;
307         MCF_SCR(0) = 0;
308         MCF_ICR(irq) = ILP_SLT0;
309         request_irq(64 + irq, coldfire_dtim_clk_irq, IRQF_DISABLED,
310                 "ColdFire Timer 0", (void *)evt);
311         MCF_SLTCNT(0) = MCF_BUSCLK / HZ;
312         MCF_SCR(0) |=  MCF_SCR_TEN | MCF_SCR_IEN | MCF_SCR_RUN;
313 }
314 #endif
315
316 void coldfire_reboot(void)
317 {
318         /* disable interrupts and enable the watchdog */
319         printk(KERN_INFO "Rebooting\n");
320         asm("movew #0x2700, %sr\n");
321         MCF_GPT_GMS0 = MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE | MCF_GPT_GMS_TMS(4);
322 }
323
324 static void coldfire_get_model(char *model)
325 {
326         sprintf(model, "Version 4 ColdFire");
327 }
328
329 static void __init
330 coldfire_bootmem_alloc(unsigned long memory_start, unsigned long memory_end)
331 {
332         unsigned long base_pfn;
333
334         /* compute total pages in system */
335         num_pages = PAGE_ALIGN(memory_end - PAGE_OFFSET) >> PAGE_SHIFT;
336
337         /* align start/end to page boundries */
338         memory_start = PAGE_ALIGN(memory_start);
339         memory_end = memory_end & PAGE_MASK;
340
341         /* page numbers */
342         base_pfn = __pa(PAGE_OFFSET) >> PAGE_SHIFT;
343         min_low_pfn = __pa(memory_start) >> PAGE_SHIFT;
344         max_low_pfn = __pa(memory_end) >> PAGE_SHIFT;
345
346         high_memory = (void *)memory_end;
347         availmem = memory_start;
348
349         /* setup bootmem data */
350         m68k_setup_node(0);
351         availmem += init_bootmem_node(NODE_DATA(0), min_low_pfn,
352                 base_pfn, max_low_pfn);
353         availmem = PAGE_ALIGN(availmem);
354
355         printk(KERN_INFO "** availmem=0x%lx  pa(am)=0x%lx\n",
356                         availmem, __pa(availmem));
357         printk(KERN_INFO "** mstart=0x%lx  mend=0x%lx\n",
358                         memory_start, memory_end);
359         printk(KERN_INFO "bpfn=0x%lx minpfn=0x%lx maxpfn=0x%lx\n",
360                         base_pfn, min_low_pfn, max_low_pfn);
361
362         /* turn over physram */
363         free_bootmem(__pa(availmem), memory_end - (availmem));
364
365         /* configure physical dma area */
366         cf_dma_base = __pa(PAGE_ALIGN(memory_start));
367         cf_dma_size = CONFIG_DMA_SIZE;
368         cf_dma_end = CONFIG_SDRAM_BASE + cf_dma_size - 1;
369
370         printk(KERN_INFO "dma: phys base=0x%lx  phys end=0x%lx  virt base=0x%x\n",
371                cf_dma_base, cf_dma_end, CONFIG_DMA_BASE);
372
373         printk(KERN_INFO "mdma=0x%x  pa(mdma)=0x%lx\n",
374                         MAX_DMA_ADDRESS, __pa(MAX_DMA_ADDRESS));
375 }
376
377 void __init config_coldfire(void)
378 {
379         unsigned long endmem, startmem;
380         int i;
381
382         /*
383          * Calculate endmem from m68k_memory, assume all are contiguous
384          */
385         startmem = ((((int) &_end) + (PAGE_SIZE - 1)) & PAGE_MASK);
386         endmem = PAGE_OFFSET;
387         for (i = 0; i < m68k_num_memory; ++i)
388                 endmem += m68k_memory[i].size;
389
390         printk(KERN_INFO "starting up linux startmem 0x%lx, endmem 0x%lx, \
391                 size %luMB\n", startmem,  endmem, (endmem - startmem) >> 20);
392
393         memset(irq_enable, 0, sizeof(irq_enable));
394
395         /*
396          * Setup coldfire mach-specific handlers
397          */
398         mach_max_dma_address    = 0xffffffff;
399 #ifndef CONFIG_GENERIC_CLOCKEVENTS
400         mach_sched_init         = coldfire_sched_init;
401         mach_tick               = coldfire_tick;
402         mach_gettimeoffset      = coldfire_gettimeoffset;
403 #endif
404         mach_reset              = coldfire_reboot;
405 /*      mach_hwclk              = coldfire_hwclk; to be done */
406         mach_get_model          = coldfire_get_model;
407
408         coldfire_bootmem_alloc(startmem, endmem-1);
409
410         /*
411          * initrd setup
412          */
413 /* #ifdef CONFIG_BLK_DEV_INITRD
414         if (m68k_ramdisk.size)  {
415                 reserve_bootmem (__pa(m68k_ramdisk.addr), m68k_ramdisk.size);
416                 initrd_start = (unsigned long) m68k_ramdisk.addr;
417                 initrd_end = initrd_start + m68k_ramdisk.size;
418                 printk (KERN_DEBUG "initrd: %08lx - %08lx\n", initrd_start,
419                         initrd_end);
420         }
421 #endif */
422
423 #if defined(CONFIG_DUMMY_CONSOLE) || defined(CONFIG_FRAMEBUFFER_CONSOLE)
424         conswitchp = &dummy_con;
425 #endif
426
427 #if defined(CONFIG_SERIAL_COLDFIRE)
428         /*
429          * This causes trouble when it is re-registered later.
430          * Currently this is fixed by conditionally commenting
431          * out the register_console in mcf_serial.c
432          */
433         register_console(&mcfrs_console);
434 #endif
435 }