]> rtime.felk.cvut.cz Git - mcf548x/linux.git/blob - arch/m68k/coldfire/config.c
ef2c4000d21e16c17860161b0ea144d05ee2db53
[mcf548x/linux.git] / arch / m68k / coldfire / config.c
1 /*
2  *  linux/arch/m68k/coldfire/config.c
3  *
4  *  Kurt Mahan kmahan@freescale.com
5  *  Matt Waddel Matt.Waddel@freescale.com
6  *  Copyright Freescale Semiconductor, Inc. 2007, 2008
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  */
13
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/string.h>
17 #include <linux/kernel.h>
18 #include <linux/console.h>
19 #include <linux/bootmem.h>
20 #include <linux/mm.h>
21 #include <asm/bootinfo.h>
22 #include <asm/machdep.h>
23 #include <asm/coldfire.h>
24 #include <asm/cache.h>
25 #include <asm/cacheflush.h>
26 #include <asm/io.h>
27 #include <asm/mmu.h>
28 #include <asm/setup.h>
29 #include <asm/irq.h>
30 #include <asm/traps.h>
31 #include <asm/movs.h>
32 #include <asm/movs.h>
33 #include <asm/page.h>
34 #include <asm/pgalloc.h>
35
36 #include <asm/mcfsim.h>
37
38 #ifdef CONFIG_UBOOT
39
40 #if defined(CONFIG_M5445X)
41 #define UBOOT_EXTRA_CLOCKS
42 #elif defined(CONFIG_M547X_8X)
43 #define UBOOT_PCI
44 #endif
45
46 #endif
47
48 #include <asm/bootinfo.h>
49
50 #ifdef CONFIG_M5445X
51 #include <asm/mcf5445x_intc.h>
52 #include <asm/mcf5445x_sdramc.h>
53 #include <asm/mcf5445x_fbcs.h>
54 #include <asm/mcf5445x_dtim.h>
55 #include <asm/mcf5445x_xbs.h>
56 #endif
57
58 #ifdef CONFIG_M547X_8X
59 #include <asm/m5485gpt.h>
60 #endif
61
62 extern int get_irq_list(struct seq_file *p, void *v);
63 extern char _text, _end;
64 extern char _etext, _edata, __init_begin, __init_end;
65 extern struct console mcfrs_console;
66 extern unsigned long availmem;
67
68 #if CONFIG_UBOOT
69 extern char m68k_command_line[CL_SIZE];
70 #endif
71
72 static int irq_enable[NR_IRQS];
73 unsigned long num_pages;
74
75 void coldfire_sort_memrec(void)
76 {
77         int i, j;
78
79         /* Sort the m68k_memory records by address */
80         for (i = 0; i < m68k_num_memory; ++i) {
81                 for (j = i + 1; j < m68k_num_memory; ++j) {
82                         if (m68k_memory[i].addr > m68k_memory[j].addr) {
83                                 struct mem_info tmp;
84                                 tmp = m68k_memory[i];
85                                 m68k_memory[i] = m68k_memory[j];
86                                 m68k_memory[j] = tmp;
87                         }
88                 }
89         }
90         /* Trim off discontiguous bits */
91         for (i = 1; i < m68k_num_memory; ++i) {
92                 if ((m68k_memory[i-1].addr + m68k_memory[i-1].size) !=
93                         m68k_memory[i].addr) {
94                         printk(KERN_DEBUG "m68k_parse_bootinfo: addr gap between \
95                                 0x%lx & 0x%lx\n",
96                                 m68k_memory[i-1].addr+m68k_memory[i-1].size,
97                                 m68k_memory[i].addr);
98                         m68k_num_memory = i;
99                         break;
100                 }
101         }
102 }
103
104 /*
105  * Use uboot commandline if told to
106  */
107  #ifdef CONFIG_UBOOT
108 int __init uboot_commandline(char *bootargs)
109 {
110         extern unsigned long uboot_init_sp;
111         
112         int len = 0, cmd_line_len;
113         unsigned long cmd_line_stop, cmd_line_start;
114         u32 offset = PAGE_OFFSET_RAW - PHYS_OFFSET;
115
116         //uboot_init_sp parameters - must add offset to them !!
117         cmd_line_start = uboot_init_sp + 16 + offset;
118         cmd_line_start = uboot_init_sp + 20 + offset;
119
120         /* copy command line */
121         cmd_line_len = cmd_line_stop - cmd_line_start;
122         if ((cmd_line_len > 0) && (cmd_line_len < CL_SIZE-1))
123                 len = (int)strncpy(bootargs, (char *)cmd_line_start,cmd_line_len);
124
125         return len;
126 }
127 #endif
128
129 /*
130  * This routine does things not done in the bootloader.
131  */
132
133 // Default command line is required to be passed from defconfig.
134
135 asmlinkage void __init cf_early_init(void)
136 {
137         struct bi_record *record = (struct bi_record *) &_end;
138
139         extern char _end;
140
141 #if defined(CONFIG_M5445X)
142         SET_VBR((void *)MCF_RAMBAR1);
143 #elif defined(CONFIG_M547X_8X)
144         SET_VBR((void *)MCF_RAMBAR0);
145 #endif
146
147         /* Mask all interrupts */
148 #if defined(CONFIG_M5445X)
149         MCF_INTC0_IMRL = 0xFFFFFFFF;
150         MCF_INTC0_IMRH = 0xFFFFFFFF;
151         MCF_INTC1_IMRL = 0xFFFFFFFF;
152         MCF_INTC1_IMRH = 0xFFFFFFFF;
153 #elif defined(CONFIG_M547X_8X)
154         MCF_IMRL = 0xFFFFFFFF;
155         MCF_IMRH = 0xFFFFFFFF;
156 #endif
157
158 #if defined(CONFIG_M5445X)
159 #if defined(CONFIG_NOR_FLASH_BASE)
160         MCF_FBCS_CSAR(1) = CONFIG_NOR_FLASH_BASE;
161 #else
162         MCF_FBCS_CSAR(1) = 0x00000000;
163 #endif
164
165 #if CONFIG_SDRAM_SIZE > (256*1024*1024)
166         /* Init optional SDRAM chip select */
167         MCF_SDRAMC_SDCS(1) = (256*1024*1024) | 0x1B;
168 #endif
169 #endif /* CONFIG_M5445X */
170
171 #if defined(CONFIG_M5445X)
172         /* Setup SDRAM crossbar(XBS) priorities */
173         MCF_XBS_PRS2 = (MCF_XBS_PRS_M0(MCF_XBS_PRI_2) |
174                         MCF_XBS_PRS_M1(MCF_XBS_PRI_3) |
175                         MCF_XBS_PRS_M2(MCF_XBS_PRI_4) |
176                         MCF_XBS_PRS_M3(MCF_XBS_PRI_5) |
177                         MCF_XBS_PRS_M5(MCF_XBS_PRI_6) |
178                         MCF_XBS_PRS_M6(MCF_XBS_PRI_1) |
179                         MCF_XBS_PRS_M7(MCF_XBS_PRI_7));
180 #endif
181
182         m68k_machtype = MACH_CFMMU;
183         m68k_fputype = FPU_CFV4E;
184         m68k_mmutype = MMU_CFV4E;
185         m68k_cputype = CPU_CFV4E;
186
187         m68k_num_memory = 0;
188         m68k_memory[m68k_num_memory].addr = CONFIG_SDRAM_BASE;
189         m68k_memory[m68k_num_memory++].size = CONFIG_SDRAM_SIZE;
190
191 #ifdef CONFIG_UBOOT
192         if (!uboot_commandline(m68k_command_line))      
193                 strncpy(m68k_command_line, CONFIG_BOOTPARAM_STRING, CL_SIZE-1);
194 #endif
195
196 #if defined(CONFIG_BLK_DEV_INITRD)
197         /* add initrd image */
198         record = (struct bi_record *) ((void *)record + record->size);
199         record->tag = BI_RAMDISK;
200         record->size =  sizeof(record->tag) + sizeof(record->size)
201                 + sizeof(record->data[0]) + sizeof(record->data[1]);
202 #endif
203
204         /* Mark end of tags. */
205         record = (struct bi_record *) ((void *) record + record->size);
206         record->tag = 0;
207         record->data[0] = 0;
208         record->data[1] = 0;
209         record->size = sizeof(record->tag) + sizeof(record->size)
210                 + sizeof(record->data[0]) + sizeof(record->data[1]);
211
212         /* Invalidate caches via CACR */
213         flush_bcache();
214         cacr_set(CACHE_DISABLE_MODE);
215
216         /* Turn on caches via CACR, enable EUSP */
217         cacr_set(CACHE_INITIAL_MODE);
218
219 }
220
221 #if defined(CONFIG_M5445X)
222 void settimericr(unsigned int timer, unsigned int level)
223 {
224         volatile unsigned char *icrp;
225         unsigned int icr;
226         unsigned char irq;
227
228         if (timer <= 2) {
229                 switch (timer) {
230                 case 2:  irq = 33; icr = MCFSIM_ICR_TIMER2; break;
231                 default: irq = 32; icr = MCFSIM_ICR_TIMER1; break;
232                 }
233
234                 icrp = (volatile unsigned char *) (icr);
235                 *icrp = level;
236                 coldfire_enable_irq0(irq);
237         }
238 }
239 #endif
240
241 /* Assembler routines */
242 asmlinkage void buserr(void);
243 asmlinkage void trap(void);
244 asmlinkage void system_call(void);
245 asmlinkage void inthandler(void);
246
247 void __init coldfire_trap_init(void)
248 {
249         int i = 0;
250         e_vector *vectors;
251
252 #if defined(CONFIG_M5445X)
253         vectors = (e_vector *)MCF_RAMBAR1;
254 #elif defined(CONFIG_M547X_8X)
255         vectors = (e_vector *)MCF_RAMBAR0;
256 #endif
257         /*
258          * There is a common trap handler and common interrupt
259          * handler that handle almost every vector. We treat
260          * the system call and bus error special, they get their
261          * own first level handlers.
262          */
263         for (i = 3; (i <= 23); i++)
264                 vectors[i] = trap;
265         for (i = 33; (i <= 63); i++)
266                 vectors[i] = trap;
267         for (i = 24; (i <= 31); i++)
268                 vectors[i] = inthandler;
269         for (i = 64; (i < 255); i++)
270                 vectors[i] = inthandler;
271
272         vectors[255] = 0;
273         vectors[2] = buserr;
274         vectors[32] = system_call;
275 }
276
277 #if defined(CONFIG_M5445X)
278
279 void coldfire_tick(void)
280 {
281         /* Reset the ColdFire timer */
282         __raw_writeb(MCF_DTIM_DTER_CAP | MCF_DTIM_DTER_REF, MCF_DTIM0_DTER);
283 }
284
285 void __init coldfire_sched_init(irq_handler_t handler)
286 {
287         unsigned int    mcf_timerlevel = 5;
288         unsigned int    mcf_timervector = 64+32;
289
290         __raw_writew(MCF_DTIM_DTMR_RST_RST, MCF_DTIM0_DTMR);
291         __raw_writel(((MCF_BUSCLK / 16) / HZ), MCF_DTIM0_DTRR);
292         __raw_writew(MCF_DTIM_DTMR_ORRI | MCF_DTIM_DTMR_CLK_DIV16 |
293                      MCF_DTIM_DTMR_FRR  | MCF_DTIM_DTMR_RST_EN, \
294                      MCF_DTIM0_DTMR);
295
296         request_irq(mcf_timervector, handler, IRQF_DISABLED, \
297                     "timer", (void *)MCF_DTIM0_DTMR);
298
299         settimericr(1, mcf_timerlevel);
300 }
301
302 int timerirqpending(int timer)
303 {
304         unsigned int imr = 0;
305
306         switch (timer) {
307         case 1:  imr = 0x1; break;
308         case 2:  imr = 0x2; break;
309         default: break;
310         }
311
312         return (getiprh() & imr);
313 }
314
315 unsigned long coldfire_gettimeoffset(void)
316 {
317         volatile unsigned long trr, tcn, offset;
318
319         tcn = __raw_readw(MCF_DTIM0_DTCN);
320         trr = __raw_readl(MCF_DTIM0_DTRR);
321         offset = (tcn * (1000000 / HZ)) / trr;
322
323         /* Check if we just wrapped the counters and maybe missed a tick */
324         if ((offset < (1000000 / HZ / 2)) && timerirqpending(1))
325                 offset += 1000000 / HZ;
326         return offset;
327 }
328
329 #elif defined(CONFIG_M547X_8X)
330
331 void coldfire_tick(void)
332 {
333         /* Reset the ColdFire timer */
334         MCF_SSR(0) = MCF_SSR_ST;
335 }
336
337 void __init coldfire_sched_init(irq_handler_t handler)
338 {
339         int irq = ISC_SLTn(0);
340
341         MCF_SCR(0) = 0;
342         MCF_ICR(irq) = ILP_SLT0;
343         request_irq(64 + irq, handler, IRQF_DISABLED, "ColdFire Timer 0", NULL);
344         MCF_SLTCNT(0) = MCF_BUSCLK / HZ;
345         MCF_SCR(0) |=  MCF_SCR_TEN | MCF_SCR_IEN | MCF_SCR_RUN;
346 }
347
348 unsigned long coldfire_gettimeoffset(void)
349 {
350         volatile unsigned long trr, tcn, offset;
351         trr = MCF_SLTCNT(0);
352         tcn = MCF_SCNT(0);
353
354         offset = (trr - tcn) * ((1000000 >> 3) / HZ) / (trr >> 3);
355         if (MCF_SSR(0) & MCF_SSR_ST)
356                 offset += 1000000 / HZ;
357
358         return offset;
359 }
360
361 #endif
362
363 void coldfire_reboot(void)
364 {
365 #if defined(CONFIG_M5445X)
366         /* disable interrupts and do a software reset */
367         asm("movew #0x2700, %%sr\n\t"
368             "moveb #0x80, %%d0\n\t"
369             "moveb %%d0, 0xfc0a0000\n\t"
370             : : : "%d0");
371 #elif defined(CONFIG_M547X_8X)
372         /* disable interrupts and enable the watchdog */
373         printk(KERN_INFO "Rebooting\n");
374         asm("movew #0x2700, %sr\n");
375         MCF_GPT_GMS0 = MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE | MCF_GPT_GMS_TMS(4);
376 #endif
377 }
378
379 static void coldfire_get_model(char *model)
380 {
381         sprintf(model, "Version 4 ColdFire");
382 }
383
384 static void __init
385 coldfire_bootmem_alloc(unsigned long memory_start, unsigned long memory_end)
386 {
387         unsigned long base_pfn;
388
389         /* compute total pages in system */
390         num_pages = PAGE_ALIGN(memory_end - PAGE_OFFSET) >> PAGE_SHIFT;
391
392         /* align start/end to page boundries */
393         memory_start = PAGE_ALIGN(memory_start);
394         memory_end = memory_end & PAGE_MASK;
395
396         /* page numbers */
397         base_pfn = __pa(PAGE_OFFSET) >> PAGE_SHIFT;
398         min_low_pfn = __pa(memory_start) >> PAGE_SHIFT;
399         max_low_pfn = __pa(memory_end) >> PAGE_SHIFT;
400
401         high_memory = (void *)memory_end;
402         availmem = memory_start;
403
404         /* setup bootmem data */
405         m68k_setup_node(0);
406         availmem += init_bootmem_node(NODE_DATA(0), min_low_pfn,
407                 base_pfn, max_low_pfn);
408         availmem = PAGE_ALIGN(availmem);
409         free_bootmem(__pa(availmem), memory_end - (availmem));
410 }
411
412 void __init config_coldfire(void)
413 {
414         unsigned long endmem, startmem;
415         int i;
416
417         /*
418          * Calculate endmem from m68k_memory, assume all are contiguous
419          */
420         startmem = ((((int) &_end) + (PAGE_SIZE - 1)) & PAGE_MASK);
421         endmem = PAGE_OFFSET;
422         for (i = 0; i < m68k_num_memory; ++i)
423                 endmem += m68k_memory[i].size;
424
425         printk(KERN_INFO "starting up linux startmem 0x%lx, endmem 0x%lx, \
426                 size %luMB\n", startmem,  endmem, (endmem - startmem) >> 20);
427
428         memset(irq_enable, 0, sizeof(irq_enable));
429
430         /*
431          * Setup coldfire mach-specific handlers
432          */
433         mach_max_dma_address    = 0xffffffff;
434         mach_sched_init         = coldfire_sched_init;
435         mach_tick               = coldfire_tick;
436         mach_gettimeoffset      = coldfire_gettimeoffset;
437         mach_reset              = coldfire_reboot;
438 /*      mach_hwclk              = coldfire_hwclk; to be done */
439         mach_get_model          = coldfire_get_model;
440
441         coldfire_bootmem_alloc(startmem, endmem-1);
442
443         /*
444          * initrd setup
445          */
446 /* #ifdef CONFIG_BLK_DEV_INITRD
447         if (m68k_ramdisk.size)  {
448                 reserve_bootmem (__pa(m68k_ramdisk.addr), m68k_ramdisk.size);
449                 initrd_start = (unsigned long) m68k_ramdisk.addr;
450                 initrd_end = initrd_start + m68k_ramdisk.size;
451                 printk (KERN_DEBUG "initrd: %08lx - %08lx\n", initrd_start,
452                         initrd_end);
453         }
454 #endif */
455
456 #if defined(CONFIG_DUMMY_CONSOLE) || defined(CONFIG_FRAMEBUFFER_CONSOLE)
457         conswitchp = &dummy_con;
458 #endif
459
460 }