2 * linux/arch/m68k/coldfire/config.c
4 * Kurt Mahan kmahan@freescale.com
5 * Matt Waddel Matt.Waddel@freescale.com
6 * Copyright Freescale Semiconductor, Inc. 2007, 2008
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.
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>
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>
28 #include <asm/setup.h>
30 #include <asm/traps.h>
34 #include <asm/pgalloc.h>
36 #include <asm/mcfsim.h>
40 #if defined(CONFIG_M5445X)
41 #define UBOOT_EXTRA_CLOCKS
42 #elif defined(CONFIG_M547X_8X)
48 #include <asm/bootinfo.h>
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>
58 #ifdef CONFIG_M547X_8X
59 #include <asm/m5485gpt.h>
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;
69 extern char m68k_command_line[CL_SIZE];
72 static int irq_enable[NR_IRQS];
73 unsigned long num_pages;
75 void coldfire_sort_memrec(void)
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) {
85 m68k_memory[i] = m68k_memory[j];
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 \
96 m68k_memory[i-1].addr+m68k_memory[i-1].size,
105 * Use uboot commandline if told to
108 int __init uboot_commandline(char *bootargs)
110 extern unsigned long uboot_init_sp;
112 int len = 0, cmd_line_len;
113 unsigned long cmd_line_stop, cmd_line_start;
114 u32 offset = PAGE_OFFSET_RAW - PHYS_OFFSET;
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;
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);
130 * This routine does things not done in the bootloader.
133 // Default command line is required to be passed from defconfig.
135 asmlinkage void __init cf_early_init(void)
137 struct bi_record *record = (struct bi_record *) &_end;
141 #if defined(CONFIG_M5445X)
142 SET_VBR((void *)MCF_RAMBAR1);
143 #elif defined(CONFIG_M547X_8X)
144 SET_VBR((void *)MCF_RAMBAR0);
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;
158 #if defined(CONFIG_M5445X)
159 #if defined(CONFIG_NOR_FLASH_BASE)
160 MCF_FBCS_CSAR(1) = CONFIG_NOR_FLASH_BASE;
162 MCF_FBCS_CSAR(1) = 0x00000000;
165 #if CONFIG_SDRAM_SIZE > (256*1024*1024)
166 /* Init optional SDRAM chip select */
167 MCF_SDRAMC_SDCS(1) = (256*1024*1024) | 0x1B;
169 #endif /* CONFIG_M5445X */
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));
182 m68k_machtype = MACH_CFMMU;
183 m68k_fputype = FPU_CFV4E;
184 m68k_mmutype = MMU_CFV4E;
185 m68k_cputype = CPU_CFV4E;
188 m68k_memory[m68k_num_memory].addr = CONFIG_SDRAM_BASE;
189 m68k_memory[m68k_num_memory++].size = CONFIG_SDRAM_SIZE;
192 if (!uboot_commandline(m68k_command_line))
193 strncpy(m68k_command_line, CONFIG_BOOTPARAM_STRING, CL_SIZE-1);
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]);
204 /* Mark end of tags. */
205 record = (struct bi_record *) ((void *) record + record->size);
209 record->size = sizeof(record->tag) + sizeof(record->size)
210 + sizeof(record->data[0]) + sizeof(record->data[1]);
212 /* Invalidate caches via CACR */
214 cacr_set(CACHE_DISABLE_MODE);
216 /* Turn on caches via CACR, enable EUSP */
217 cacr_set(CACHE_INITIAL_MODE);
221 #if defined(CONFIG_M5445X)
222 void settimericr(unsigned int timer, unsigned int level)
224 volatile unsigned char *icrp;
230 case 2: irq = 33; icr = MCFSIM_ICR_TIMER2; break;
231 default: irq = 32; icr = MCFSIM_ICR_TIMER1; break;
234 icrp = (volatile unsigned char *) (icr);
236 coldfire_enable_irq0(irq);
241 /* Assembler routines */
242 asmlinkage void buserr(void);
243 asmlinkage void trap(void);
244 asmlinkage void system_call(void);
245 asmlinkage void inthandler(void);
247 void __init coldfire_trap_init(void)
252 #if defined(CONFIG_M5445X)
253 vectors = (e_vector *)MCF_RAMBAR1;
254 #elif defined(CONFIG_M547X_8X)
255 vectors = (e_vector *)MCF_RAMBAR0;
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.
263 for (i = 3; (i <= 23); i++)
265 for (i = 33; (i <= 63); i++)
267 for (i = 24; (i <= 31); i++)
268 vectors[i] = inthandler;
269 for (i = 64; (i < 255); i++)
270 vectors[i] = inthandler;
274 vectors[32] = system_call;
277 #if defined(CONFIG_M5445X)
279 void coldfire_tick(void)
281 /* Reset the ColdFire timer */
282 __raw_writeb(MCF_DTIM_DTER_CAP | MCF_DTIM_DTER_REF, MCF_DTIM0_DTER);
285 void __init coldfire_sched_init(irq_handler_t handler)
287 unsigned int mcf_timerlevel = 5;
288 unsigned int mcf_timervector = 64+32;
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, \
296 request_irq(mcf_timervector, handler, IRQF_DISABLED, \
297 "timer", (void *)MCF_DTIM0_DTMR);
299 settimericr(1, mcf_timerlevel);
302 int timerirqpending(int timer)
304 unsigned int imr = 0;
307 case 1: imr = 0x1; break;
308 case 2: imr = 0x2; break;
312 return (getiprh() & imr);
315 unsigned long coldfire_gettimeoffset(void)
317 volatile unsigned long trr, tcn, offset;
319 tcn = __raw_readw(MCF_DTIM0_DTCN);
320 trr = __raw_readl(MCF_DTIM0_DTRR);
321 offset = (tcn * (1000000 / HZ)) / trr;
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;
329 #elif defined(CONFIG_M547X_8X)
331 void coldfire_tick(void)
333 /* Reset the ColdFire timer */
334 MCF_SSR(0) = MCF_SSR_ST;
337 void __init coldfire_sched_init(irq_handler_t handler)
339 int irq = ISC_SLTn(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;
348 unsigned long coldfire_gettimeoffset(void)
350 volatile unsigned long trr, tcn, offset;
354 offset = (trr - tcn) * ((1000000 >> 3) / HZ) / (trr >> 3);
355 if (MCF_SSR(0) & MCF_SSR_ST)
356 offset += 1000000 / HZ;
363 void coldfire_reboot(void)
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"
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);
379 static void coldfire_get_model(char *model)
381 sprintf(model, "Version 4 ColdFire");
385 coldfire_bootmem_alloc(unsigned long memory_start, unsigned long memory_end)
387 unsigned long base_pfn;
389 /* compute total pages in system */
390 num_pages = PAGE_ALIGN(memory_end - PAGE_OFFSET) >> PAGE_SHIFT;
392 /* align start/end to page boundries */
393 memory_start = PAGE_ALIGN(memory_start);
394 memory_end = memory_end & PAGE_MASK;
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;
401 high_memory = (void *)memory_end;
402 availmem = memory_start;
404 /* setup bootmem data */
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));
412 void __init config_coldfire(void)
414 unsigned long endmem, startmem;
418 * Calculate endmem from m68k_memory, assume all are contiguous
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;
425 printk(KERN_INFO "starting up linux startmem 0x%lx, endmem 0x%lx, \
426 size %luMB\n", startmem, endmem, (endmem - startmem) >> 20);
428 memset(irq_enable, 0, sizeof(irq_enable));
431 * Setup coldfire mach-specific handlers
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;
441 coldfire_bootmem_alloc(startmem, endmem-1);
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,
456 #if defined(CONFIG_DUMMY_CONSOLE) || defined(CONFIG_FRAMEBUFFER_CONSOLE)
457 conswitchp = &dummy_con;