2 * linux/arch/m68k/coldfire/config.c
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
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.
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>
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>
29 #include <asm/cfmmu.h>
30 #include <asm/setup.h>
32 #include <asm/traps.h>
36 #include <asm/pgalloc.h>
38 #include <asm/mcfsim.h>
41 #include <asm/bootinfo.h>
42 #include <asm/m5485gpt.h>
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
;
51 static int irq_enable
[NR_IRQS
];
52 unsigned long num_pages
;
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
);
62 /* ethernet mac addresses from uboot */
63 unsigned char uboot_enet0
[6];
64 unsigned char uboot_enet1
[6];
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: "
86 "addr gap between 0x%lx & 0x%lx\n",
87 m68k_memory
[i
-1].addr
+m68k_memory
[i
-1].size
,
98 int __init
uboot_commandline(char *bootargs
)
100 int len
= 0, cmd_line_len
;
101 static struct uboot_record uboot_info
;
102 u32 offset
= PAGE_OFFSET_RAW
- PHYS_OFFSET
;
104 extern unsigned long uboot_info_stk
;
106 /* validate address */
107 if ((uboot_info_stk
< PAGE_OFFSET_RAW
) ||
108 (uboot_info_stk
>= (PAGE_OFFSET_RAW
+ CONFIG_SDRAM_SIZE
)))
111 /* Add offset to get post-remapped kernel memory location */
112 uboot_info
.bdi
= (struct bd_info
*)((*(u32
*)(uboot_info_stk
))
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
;
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);
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
,\
133 * This routine does things not done in the bootloader.
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"
140 asmlinkage
void __init
cf_early_init(void)
142 struct bi_record
*record
= (struct bi_record
*) &_end
;
146 SET_VBR((void *)MCF_RAMBAR0
);
148 /* Mask all interrupts */
149 MCF_IMRL
= 0xFFFFFFFF;
150 MCF_IMRH
= 0xFFFFFFFF;
152 m68k_machtype
= MACH_CFMMU
;
153 m68k_fputype
= FPU_CFV4E
;
154 m68k_mmutype
= MMU_CFV4E
;
155 m68k_cputype
= CPU_CFV4E
;
158 m68k_memory
[m68k_num_memory
].addr
= CONFIG_SDRAM_BASE
;
159 m68k_memory
[m68k_num_memory
++].size
= CONFIG_SDRAM_SIZE
;
161 if (!uboot_commandline(m68k_command_line
)) {
162 #if defined(CONFIG_BOOTPARAM)
163 strncpy(m68k_command_line
, CONFIG_BOOTPARAM_STRING
, CL_SIZE
-1);
165 strcpy(m68k_command_line
, DEFAULT_COMMAND_LINE
);
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]);
177 /* Mark end of tags. */
178 record
= (struct bi_record
*) ((void *) record
+ record
->size
);
182 record
->size
= sizeof(record
->tag
) + sizeof(record
->size
)
183 + sizeof(record
->data
[0]) + sizeof(record
->data
[1]);
185 /* Invalidate caches via CACR */
187 cacr_set(CACHE_DISABLE_MODE
);
189 /* Turn on caches via CACR, enable EUSP */
190 cacr_set(CACHE_INITIAL_MODE
);
194 /* Assembler routines */
195 asmlinkage
void buserr(void);
196 asmlinkage
void trap(void);
197 asmlinkage
void system_call(void);
198 asmlinkage
void inthandler(void);
200 void __init
coldfire_trap_init(void)
205 vectors
= (e_vector
*)MCF_RAMBAR0
;
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.
212 for (i
= 3; (i
<= 23); i
++)
214 for (i
= 33; (i
<= 63); i
++)
216 for (i
= 24; (i
<= 31); i
++)
217 vectors
[i
] = inthandler
;
218 for (i
= 64; (i
< 255); i
++)
219 vectors
[i
] = inthandler
;
223 vectors
[32] = system_call
;
226 #ifndef CONFIG_GENERIC_CLOCKEVENTS
227 void coldfire_tick(void)
229 /* Reset the ColdFire timer */
230 MCF_SSR(0) = MCF_SSR_ST
;
233 void __init
coldfire_sched_init(irq_handler_t handler
)
235 int irq
= ISC_SLTn(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
;
244 unsigned long coldfire_gettimeoffset(void)
246 volatile unsigned long trr
, tcn
, offset
;
250 offset
= (trr
- tcn
) * ((1000000 >> 3) / HZ
) / (trr
>> 3);
251 if (MCF_SSR(0) & MCF_SSR_ST
)
252 offset
+= 1000000 / HZ
;
257 static unsigned long long sched_dtim_clk_val
;
259 unsigned long long sched_clock(void)
262 unsigned long long cycles
;
263 volatile unsigned long trr
, tcn
, offset
;
265 local_irq_save(flags
);
268 offset
= (trr
- tcn
);
269 cycles
= sched_dtim_clk_val
;
270 local_irq_restore(flags
);
272 return cycles
+ offset
;
275 unsigned long long sys_dtim2_read(void)
278 unsigned long long cycles
;
279 volatile unsigned long trr
, tcn
, offset
;
281 local_irq_save(flags
);
284 offset
= (trr
- tcn
);
285 cycles
= sched_dtim_clk_val
;
286 local_irq_restore(flags
);
288 return cycles
+ offset
;
291 static irqreturn_t
coldfire_dtim_clk_irq(int irq
, void *dev
)
293 struct clock_event_device
*evt
=
294 (struct clock_event_device
*)dev
;
296 MCF_SSR(0) = MCF_SSR_ST
;
297 sched_dtim_clk_val
+= (MCF_BUSCLK
) / HZ
;;
298 evt
->event_handler(evt
);
302 void sys_dtim2_init(struct clock_event_device
*evt
)
304 int irq
= ISC_SLTn(0);
306 sched_dtim_clk_val
= 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
;
316 void coldfire_reboot(void)
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);
324 static void coldfire_get_model(char *model
)
326 sprintf(model
, "Version 4 ColdFire");
330 coldfire_bootmem_alloc(unsigned long memory_start
, unsigned long memory_end
)
332 unsigned long base_pfn
;
334 /* compute total pages in system */
335 num_pages
= PAGE_ALIGN(memory_end
- PAGE_OFFSET
) >> PAGE_SHIFT
;
337 /* align start/end to page boundries */
338 memory_start
= PAGE_ALIGN(memory_start
);
339 memory_end
= memory_end
& PAGE_MASK
;
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
;
346 high_memory
= (void *)memory_end
;
347 availmem
= memory_start
;
349 /* setup bootmem data */
351 availmem
+= init_bootmem_node(NODE_DATA(0), min_low_pfn
,
352 base_pfn
, max_low_pfn
);
353 availmem
= PAGE_ALIGN(availmem
);
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
);
362 /* turn over physram */
363 free_bootmem(__pa(availmem
), memory_end
- (availmem
));
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;
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
);
373 printk(KERN_INFO
"mdma=0x%x pa(mdma)=0x%lx\n",
374 MAX_DMA_ADDRESS
, __pa(MAX_DMA_ADDRESS
));
377 void __init
config_coldfire(void)
379 unsigned long endmem
, startmem
;
383 * Calculate endmem from m68k_memory, assume all are contiguous
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
;
390 printk(KERN_INFO
"starting up linux startmem 0x%lx, endmem 0x%lx, \
391 size %luMB\n", startmem
, endmem
, (endmem
- startmem
) >> 20);
393 memset(irq_enable
, 0, sizeof(irq_enable
));
396 * Setup coldfire mach-specific handlers
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
;
404 mach_reset
= coldfire_reboot
;
405 /* mach_hwclk = coldfire_hwclk; to be done */
406 mach_get_model
= coldfire_get_model
;
408 coldfire_bootmem_alloc(startmem
, endmem
-1);
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,
423 #if defined(CONFIG_DUMMY_CONSOLE) || defined(CONFIG_FRAMEBUFFER_CONSOLE)
424 conswitchp
= &dummy_con
;
427 #if defined(CONFIG_SERIAL_COLDFIRE)
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
433 register_console(&mcfrs_console
);