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