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/mcfcache.h>
25 #include <asm/cacheflush.h>
27 #include <asm/mcfmmu.h>
28 #include <asm/setup.h>
30 #include <asm/traps.h>
34 #include <asm/pgalloc.h>
36 #include <asm/mcfsim.h>
38 #include <asm/bootinfo.h>
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>
48 #ifdef CONFIG_M547X_8X
49 #include <asm/m548xgpt.h>
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;
59 extern char m68k_command_line[CL_SIZE];
60 struct mem_info m68k_ramdisk;
63 static int irq_enable[NR_IRQS];
64 unsigned long num_pages;
66 void coldfire_sort_memrec(void)
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) {
76 m68k_memory[i] = m68k_memory[j];
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 \
87 m68k_memory[i-1].addr+m68k_memory[i-1].size,
96 * Use uboot commandline if told to
99 int __init uboot_commandline(char *bootargs)
101 extern unsigned long uboot_init_sp;
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;
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;
112 initrd_start = uboot_init_sp + 8 + offset;
114 if ( *((unsigned long*)initrd_start) != 0)
116 initrd_stop = uboot_init_sp + 12 + offset;
118 m68k_ramdisk.addr = initrd_start;
119 m68k_ramdisk.size = *((unsigned long*)initrd_stop) - *((unsigned long*)initrd_start);
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);
132 * This routine does things not done in the bootloader.
135 // Default command line is required to be passed from defconfig.
137 asmlinkage void __init cf_early_init(void)
139 struct bi_record *record = (struct bi_record *) &_end;
143 #if defined(CONFIG_M5445X)
144 SET_VBR((void *)MCF_RAMBAR1);
145 #elif defined(CONFIG_M547X_8X)
146 SET_VBR((void *)MCF_RAMBAR0);
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;
160 #if defined(CONFIG_M5445X)
161 #if defined(CONFIG_NOR_FLASH_BASE)
162 MCF_FBCS_CSAR(1) = CONFIG_NOR_FLASH_BASE;
164 MCF_FBCS_CSAR(1) = 0x00000000;
167 #if CONFIG_SDRAM_SIZE > (256*1024*1024)
168 /* Init optional SDRAM chip select */
169 MCF_SDRAMC_SDCS(1) = (256*1024*1024) | 0x1B;
171 #endif /* CONFIG_M5445X */
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));
184 m68k_machtype = MACH_CFMMU;
185 m68k_fputype = FPU_CFV4E;
186 m68k_mmutype = MMU_CFV4E;
187 m68k_cputype = CPU_CFV4E;
190 m68k_memory[m68k_num_memory].addr = CONFIG_SDRAM_BASE;
191 m68k_memory[m68k_num_memory++].size = CONFIG_SDRAM_SIZE;
194 if (!uboot_commandline(m68k_command_line))
195 strncpy(m68k_command_line, CONFIG_BOOTPARAM_STRING, CL_SIZE-1);
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]);
206 /* Mark end of tags. */
207 record = (struct bi_record *) ((void *) record + record->size);
211 record->size = sizeof(record->tag) + sizeof(record->size)
212 + sizeof(record->data[0]) + sizeof(record->data[1]);
214 /* Invalidate caches via CACR */
216 cacr_set(CACHE_DISABLE_MODE);
218 /* Turn on caches via CACR, enable EUSP */
219 cacr_set(CACHE_INITIAL_MODE);
223 #if defined(CONFIG_M5445X)
224 void settimericr(unsigned int timer, unsigned int level)
226 volatile unsigned char *icrp;
232 case 2: irq = 33; icr = MCFSIM_ICR_TIMER2; break;
233 default: irq = 32; icr = MCFSIM_ICR_TIMER1; break;
236 icrp = (volatile unsigned char *) (icr);
238 coldfire_enable_irq0(irq);
243 /* Assembler routines */
244 asmlinkage void buserr(void);
245 asmlinkage void trap(void);
246 asmlinkage void system_call(void);
247 asmlinkage void inthandler(void);
249 void __init coldfire_trap_init(void)
254 #if defined(CONFIG_M5445X)
255 vectors = (e_vector *)MCF_RAMBAR1;
256 #elif defined(CONFIG_M547X_8X)
257 vectors = (e_vector *)MCF_RAMBAR0;
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.
265 for (i = 3; (i <= 23); i++)
267 for (i = 33; (i <= 63); i++)
269 for (i = 24; (i <= 31); i++)
270 vectors[i] = inthandler;
271 for (i = 64; (i < 255); i++)
272 vectors[i] = inthandler;
276 vectors[32] = system_call;
279 #if defined(CONFIG_M5445X)
281 void coldfire_tick(void)
283 /* Reset the ColdFire timer */
284 __raw_writeb(MCF_DTIM_DTER_CAP | MCF_DTIM_DTER_REF, MCF_DTIM0_DTER);
287 void __init coldfire_sched_init(irq_handler_t handler)
289 unsigned int mcf_timerlevel = 5;
290 unsigned int mcf_timervector = 64+32;
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, \
298 request_irq(mcf_timervector, handler, IRQF_DISABLED, \
299 "timer", (void *)MCF_DTIM0_DTMR);
301 settimericr(1, mcf_timerlevel);
304 int timerirqpending(int timer)
306 unsigned int imr = 0;
309 case 1: imr = 0x1; break;
310 case 2: imr = 0x2; break;
314 return (getiprh() & imr);
317 unsigned long coldfire_gettimeoffset(void)
319 volatile unsigned long trr, tcn, offset;
321 tcn = __raw_readw(MCF_DTIM0_DTCN);
322 trr = __raw_readl(MCF_DTIM0_DTRR);
323 offset = (tcn * (1000000 / HZ)) / trr;
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;
331 #elif defined(CONFIG_M547X_8X)
333 void coldfire_tick(void)
335 /* Reset the ColdFire timer */
336 MCF_SSR(0) = MCF_SSR_ST;
339 void __init coldfire_sched_init(irq_handler_t handler)
341 int irq = ISC_SLTn(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;
350 unsigned long coldfire_gettimeoffset(void)
352 volatile unsigned long trr, tcn, offset;
356 offset = (trr - tcn) * ((1000000 >> 3) / HZ) / (trr >> 3);
357 if (MCF_SSR(0) & MCF_SSR_ST)
358 offset += 1000000 / HZ;
365 void coldfire_reboot(void)
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"
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);
381 static void coldfire_get_model(char *model)
383 sprintf(model, "Version 4 ColdFire");
387 coldfire_bootmem_alloc(unsigned long memory_start, unsigned long memory_end)
389 unsigned long base_pfn;
391 /* compute total pages in system */
392 num_pages = PAGE_ALIGN(memory_end - PAGE_OFFSET) >> PAGE_SHIFT;
394 /* align start/end to page boundries */
395 memory_start = PAGE_ALIGN(memory_start);
396 memory_end = memory_end & PAGE_MASK;
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;
403 high_memory = (void *)memory_end;
404 availmem = memory_start;
406 /* setup bootmem data */
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));
414 void __init config_coldfire(void)
416 unsigned long endmem, startmem;
420 * Calculate endmem from m68k_memory, assume all are contiguous
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;
427 printk(KERN_INFO "starting up linux startmem 0x%lx, endmem 0x%lx, \
428 size %luMB\n", startmem, endmem, (endmem - startmem) >> 20);
430 memset(irq_enable, 0, sizeof(irq_enable));
433 * Setup coldfire mach-specific handlers
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;
443 coldfire_bootmem_alloc(startmem, endmem-1);
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,
458 #if defined(CONFIG_DUMMY_CONSOLE) || defined(CONFIG_FRAMEBUFFER_CONSOLE)
459 conswitchp = &dummy_con;
464 //no special boot record
465 int coldfire_parse_bootinfo(const struct bi_record *)