Root/target/linux/coldfire/files-2.6.31/arch/m68k/coldfire/m547x/config.c

1/*
2 * linux/arch/m68k/coldfire/config.c
3 *
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
8 *
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.
13 */
14
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>
21#include <linux/mm.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>
28#include <linux/io.h>
29#include <asm/cfmmu.h>
30#include <asm/setup.h>
31#include <asm/irq.h>
32#include <asm/traps.h>
33#include <asm/movs.h>
34#include <asm/movs.h>
35#include <asm/page.h>
36#include <asm/pgalloc.h>
37
38#include <asm/mcfsim.h>
39
40#define UBOOT_PCI
41#include <asm/bootinfo.h>
42#include <asm/m5485gpt.h>
43
44extern int get_irq_list(struct seq_file *p, void *v);
45extern char _text, _end;
46extern char _etext, _edata, __init_begin, __init_end;
47extern struct console mcfrs_console;
48extern char m68k_command_line[CL_SIZE];
49extern unsigned long availmem;
50
51static int irq_enable[NR_IRQS];
52unsigned long num_pages;
53
54/* cf dma physical addresses */
55unsigned long cf_dma_base;
56unsigned long cf_dma_end;
57unsigned long cf_dma_size;
58EXPORT_SYMBOL(cf_dma_base);
59EXPORT_SYMBOL(cf_dma_end);
60EXPORT_SYMBOL(cf_dma_size);
61
62/* ethernet mac addresses from uboot */
63unsigned char uboot_enet0[6];
64unsigned char uboot_enet1[6];
65
66void 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: "
86                "addr gap between 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 * UBoot Handler
97 */
98int __init uboot_commandline(char *bootargs)
99{
100    int len = 0, cmd_line_len;
101    static struct uboot_record uboot_info;
102    u32 offset = PAGE_OFFSET_RAW - PHYS_OFFSET;
103
104    extern unsigned long uboot_info_stk;
105
106    /* validate address */
107    if ((uboot_info_stk < PAGE_OFFSET_RAW) ||
108        (uboot_info_stk >= (PAGE_OFFSET_RAW + CONFIG_SDRAM_SIZE)))
109        return 0;
110
111    /* Add offset to get post-remapped kernel memory location */
112    uboot_info.bdi = (struct bd_info *)((*(u32 *)(uboot_info_stk))
113                            + offset);
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;
118
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);
122
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,\
127                   cmd_line_len);
128
129    return len;
130}
131
132/*
133 * This routine does things not done in the bootloader.
134 */
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"
139
140asmlinkage void __init cf_early_init(void)
141{
142    struct bi_record *record = (struct bi_record *) &_end;
143
144    extern char _end;
145
146    SET_VBR((void *)MCF_RAMBAR0);
147
148    /* Mask all interrupts */
149    MCF_IMRL = 0xFFFFFFFF;
150    MCF_IMRH = 0xFFFFFFFF;
151
152    m68k_machtype = MACH_CFMMU;
153    m68k_fputype = FPU_CFV4E;
154    m68k_mmutype = MMU_CFV4E;
155    m68k_cputype = CPU_CFV4E;
156
157    m68k_num_memory = 0;
158    m68k_memory[m68k_num_memory].addr = CONFIG_SDRAM_BASE;
159    m68k_memory[m68k_num_memory++].size = CONFIG_SDRAM_SIZE;
160
161    if (!uboot_commandline(m68k_command_line)) {
162#if defined(CONFIG_BOOTPARAM)
163        strncpy(m68k_command_line, CONFIG_BOOTPARAM_STRING, CL_SIZE-1);
164#else
165        strcpy(m68k_command_line, DEFAULT_COMMAND_LINE);
166#endif
167    }
168
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]);
175#endif
176
177    /* Mark end of tags. */
178    record = (struct bi_record *) ((void *) record + record->size);
179    record->tag = 0;
180    record->data[0] = 0;
181    record->data[1] = 0;
182    record->size = sizeof(record->tag) + sizeof(record->size)
183        + sizeof(record->data[0]) + sizeof(record->data[1]);
184
185    /* Invalidate caches via CACR */
186    flush_bcache();
187    cacr_set(CACHE_DISABLE_MODE);
188
189    /* Turn on caches via CACR, enable EUSP */
190    cacr_set(CACHE_INITIAL_MODE);
191
192}
193
194/* Assembler routines */
195asmlinkage void buserr(void);
196asmlinkage void trap(void);
197asmlinkage void system_call(void);
198asmlinkage void inthandler(void);
199
200void __init coldfire_trap_init(void)
201{
202    int i = 0;
203    e_vector *vectors;
204
205    vectors = (e_vector *)MCF_RAMBAR0;
206    /*
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.
211     */
212    for (i = 3; (i <= 23); i++)
213        vectors[i] = trap;
214    for (i = 33; (i <= 63); i++)
215        vectors[i] = trap;
216    for (i = 24; (i <= 31); i++)
217        vectors[i] = inthandler;
218    for (i = 64; (i < 255); i++)
219        vectors[i] = inthandler;
220
221    vectors[255] = 0;
222    vectors[2] = buserr;
223    vectors[32] = system_call;
224}
225
226#ifndef CONFIG_GENERIC_CLOCKEVENTS
227void coldfire_tick(void)
228{
229    /* Reset the ColdFire timer */
230    MCF_SSR(0) = MCF_SSR_ST;
231}
232
233void __init coldfire_sched_init(irq_handler_t handler)
234{
235    int irq = ISC_SLTn(0);
236
237    MCF_SCR(0) = 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;
242}
243
244unsigned long coldfire_gettimeoffset(void)
245{
246    volatile unsigned long trr, tcn, offset;
247    trr = MCF_SLTCNT(0);
248    tcn = MCF_SCNT(0);
249
250    offset = (trr - tcn) * ((1000000 >> 3) / HZ) / (trr >> 3);
251    if (MCF_SSR(0) & MCF_SSR_ST)
252        offset += 1000000 / HZ;
253
254    return offset;
255}
256#else
257static unsigned long long sched_dtim_clk_val;
258
259unsigned long long sched_clock(void)
260{
261    unsigned long flags;
262    unsigned long long cycles;
263    volatile unsigned long trr, tcn, offset;
264
265    local_irq_save(flags);
266    trr = MCF_SLTCNT(0);
267    tcn = MCF_SCNT(0);
268    offset = (trr - tcn);
269    cycles = sched_dtim_clk_val;
270    local_irq_restore(flags);
271
272    return cycles + offset;
273}
274
275unsigned long long sys_dtim2_read(void)
276{
277    unsigned long flags;
278    unsigned long long cycles;
279    volatile unsigned long trr, tcn, offset;
280
281    local_irq_save(flags);
282    trr = MCF_SLTCNT(0);
283    tcn = MCF_SCNT(0);
284    offset = (trr - tcn);
285    cycles = sched_dtim_clk_val;
286    local_irq_restore(flags);
287
288    return cycles + offset;
289}
290
291static irqreturn_t coldfire_dtim_clk_irq(int irq, void *dev)
292{
293    struct clock_event_device *evt =
294        (struct clock_event_device *)dev;
295
296    MCF_SSR(0) = MCF_SSR_ST;
297    sched_dtim_clk_val += (MCF_BUSCLK) / HZ;;
298    evt->event_handler(evt);
299    return IRQ_HANDLED;
300}
301
302void sys_dtim2_init(struct clock_event_device *evt)
303{
304    int irq = ISC_SLTn(0);
305
306    sched_dtim_clk_val = 0;
307    MCF_SCR(0) = 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;
313}
314#endif
315
316void coldfire_reboot(void)
317{
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);
322}
323
324static void coldfire_get_model(char *model)
325{
326    sprintf(model, "Version 4 ColdFire");
327}
328
329static void __init
330coldfire_bootmem_alloc(unsigned long memory_start, unsigned long memory_end)
331{
332    unsigned long base_pfn;
333
334    /* compute total pages in system */
335    num_pages = PAGE_ALIGN(memory_end - PAGE_OFFSET) >> PAGE_SHIFT;
336
337    /* align start/end to page boundries */
338    memory_start = PAGE_ALIGN(memory_start);
339    memory_end = memory_end & PAGE_MASK;
340
341    /* page numbers */
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;
345
346    high_memory = (void *)memory_end;
347    availmem = memory_start;
348
349    /* setup bootmem data */
350    m68k_setup_node(0);
351    availmem += init_bootmem_node(NODE_DATA(0), min_low_pfn,
352        base_pfn, max_low_pfn);
353    availmem = PAGE_ALIGN(availmem);
354
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);
361
362    /* turn over physram */
363    free_bootmem(__pa(availmem), memory_end - (availmem));
364
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;
369
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);
372
373    printk(KERN_INFO "mdma=0x%x pa(mdma)=0x%lx\n",
374            MAX_DMA_ADDRESS, __pa(MAX_DMA_ADDRESS));
375}
376
377void __init config_coldfire(void)
378{
379    unsigned long endmem, startmem;
380    int i;
381
382    /*
383     * Calculate endmem from m68k_memory, assume all are contiguous
384     */
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;
389
390    printk(KERN_INFO "starting up linux startmem 0x%lx, endmem 0x%lx, \
391        size %luMB\n", startmem, endmem, (endmem - startmem) >> 20);
392
393    memset(irq_enable, 0, sizeof(irq_enable));
394
395    /*
396     * Setup coldfire mach-specific handlers
397     */
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;
403#endif
404    mach_reset = coldfire_reboot;
405/* mach_hwclk = coldfire_hwclk; to be done */
406    mach_get_model = coldfire_get_model;
407
408    coldfire_bootmem_alloc(startmem, endmem-1);
409
410    /*
411     * initrd setup
412     */
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,
419            initrd_end);
420    }
421#endif */
422
423#if defined(CONFIG_DUMMY_CONSOLE) || defined(CONFIG_FRAMEBUFFER_CONSOLE)
424    conswitchp = &dummy_con;
425#endif
426
427#if defined(CONFIG_SERIAL_COLDFIRE)
428    /*
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
432     */
433    register_console(&mcfrs_console);
434#endif
435}
436

Archive Download this file



interactive