diff options
Diffstat (limited to 'arch/blackfin/kernel/setup.c')
| -rw-r--r-- | arch/blackfin/kernel/setup.c | 293 |
1 files changed, 234 insertions, 59 deletions
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 95448ae9c43..4f424ae3b36 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2009 Analog Devices Inc. + * Copyright 2004-2010 Analog Devices Inc. * * Licensed under the GPL-2 or later. */ @@ -17,7 +17,7 @@ #ifdef CONFIG_MTD_UCLINUX #include <linux/mtd/map.h> #include <linux/ext2_fs.h> -#include <linux/cramfs_fs.h> +#include <uapi/linux/cramfs_fs.h> #include <linux/romfs_fs.h> #endif @@ -25,10 +25,19 @@ #include <asm/cacheflush.h> #include <asm/blackfin.h> #include <asm/cplbinit.h> +#include <asm/clocks.h> #include <asm/div64.h> #include <asm/cpu.h> #include <asm/fixed_code.h> #include <asm/early_printk.h> +#include <asm/irq_handler.h> +#include <asm/pda.h> +#ifdef CONFIG_BF60x +#include <mach/pm.h> +#endif +#ifdef CONFIG_SCB_PRIORITY +#include <asm/scb.h> +#endif u16 _bfin_swrst; EXPORT_SYMBOL(_bfin_swrst); @@ -46,15 +55,13 @@ EXPORT_SYMBOL(reserved_mem_dcache_on); #ifdef CONFIG_MTD_UCLINUX extern struct map_info uclinux_ram_map; unsigned long memory_mtd_end, memory_mtd_start, mtd_size; -unsigned long _ebss; EXPORT_SYMBOL(memory_mtd_end); EXPORT_SYMBOL(memory_mtd_start); EXPORT_SYMBOL(mtd_size); #endif char __initdata command_line[COMMAND_LINE_SIZE]; -void __initdata *init_retx, *init_saved_retx, *init_saved_seqstat, - *init_saved_icplb_fault_addr, *init_saved_dcplb_fault_addr; +struct blackfin_initial_pda __initdata initial_pda; /* boot memmap, for parsing "memmap=" */ #define BFIN_MEMMAP_MAX 128 /* number of entries in bfin_memmap */ @@ -95,7 +102,7 @@ void __init generate_cplb_tables(void) } #endif -void __cpuinit bfin_setup_caches(unsigned int cpu) +void bfin_setup_caches(unsigned int cpu) { #ifdef CONFIG_BFIN_ICACHE bfin_icache_init(icplb_tbl[cpu]); @@ -105,6 +112,8 @@ void __cpuinit bfin_setup_caches(unsigned int cpu) bfin_dcache_init(dcplb_tbl[cpu]); #endif + bfin_setup_cpudata(cpu); + /* * In cache coherence emulation mode, we need to have the * D-cache enabled before running any atomic operation which @@ -159,11 +168,10 @@ void __cpuinit bfin_setup_caches(unsigned int cpu) #endif } -void __cpuinit bfin_setup_cpudata(unsigned int cpu) +void bfin_setup_cpudata(unsigned int cpu) { struct blackfin_cpudata *cpudata = &per_cpu(cpu_data, cpu); - cpudata->idle = current; cpudata->imemctl = bfin_read_IMEM_CONTROL(); cpudata->dmemctl = bfin_read_DMEM_CONTROL(); } @@ -215,11 +223,58 @@ void __init bfin_relocate_l1_mem(void) early_dma_memcpy_done(); +#if defined(CONFIG_SMP) && defined(CONFIG_ICACHE_FLUSH_L1) + blackfin_iflush_l1_entry[0] = (unsigned long)blackfin_icache_flush_range_l1; +#endif + /* if necessary, copy L2 text/data to L2 SRAM */ if (L2_LENGTH && l2_len) memcpy(_stext_l2, _l2_lma, l2_len); } +#ifdef CONFIG_SMP +void __init bfin_relocate_coreb_l1_mem(void) +{ + unsigned long text_l1_len = (unsigned long)_text_l1_len; + unsigned long data_l1_len = (unsigned long)_data_l1_len; + unsigned long data_b_l1_len = (unsigned long)_data_b_l1_len; + + blackfin_dma_early_init(); + + /* if necessary, copy L1 text to L1 instruction SRAM */ + if (L1_CODE_LENGTH && text_l1_len) + early_dma_memcpy((void *)COREB_L1_CODE_START, _text_l1_lma, + text_l1_len); + + /* if necessary, copy L1 data to L1 data bank A SRAM */ + if (L1_DATA_A_LENGTH && data_l1_len) + early_dma_memcpy((void *)COREB_L1_DATA_A_START, _data_l1_lma, + data_l1_len); + + /* if necessary, copy L1 data B to L1 data bank B SRAM */ + if (L1_DATA_B_LENGTH && data_b_l1_len) + early_dma_memcpy((void *)COREB_L1_DATA_B_START, _data_b_l1_lma, + data_b_l1_len); + + early_dma_memcpy_done(); + +#ifdef CONFIG_ICACHE_FLUSH_L1 + blackfin_iflush_l1_entry[1] = (unsigned long)blackfin_icache_flush_range_l1 - + (unsigned long)_stext_l1 + COREB_L1_CODE_START; +#endif +} +#endif + +#ifdef CONFIG_ROMKERNEL +void __init bfin_relocate_xip_data(void) +{ + early_shadow_stamp(); + + memcpy(_sdata, _data_lma, (unsigned long)_data_len - THREAD_SIZE + sizeof(struct thread_info)); + memcpy(_sinitdata, _init_data_lma, (unsigned long)_init_data_len); +} +#endif + /* add_memory_region to memmap */ static void __init add_memory_region(unsigned long long start, unsigned long long size, int type) @@ -504,7 +559,7 @@ static __init void memory_setup(void) #endif unsigned long max_mem; - _rambase = (unsigned long)_stext; + _rambase = CONFIG_BOOT_LOAD; _ramstart = (unsigned long)_end; if (DMA_UNCACHED_REGION > (_ramend - _ramstart)) { @@ -562,7 +617,8 @@ static __init void memory_setup(void) /* ROM_FS is XIP, so if we found it, we need to limit memory */ if (memory_end > max_mem) { - pr_info("Limiting kernel memory to %liMB due to anomaly 05000263\n", max_mem >> 20); + pr_info("Limiting kernel memory to %liMB due to anomaly 05000263\n", + (max_mem - CONFIG_PHY_RAM_BASE_ADDRESS) >> 20); memory_end = max_mem; } } @@ -592,12 +648,18 @@ static __init void memory_setup(void) * doesn't exist, or we don't need to - then dont. */ if (memory_end > max_mem) { - pr_info("Limiting kernel memory to %liMB due to anomaly 05000263\n", max_mem >> 20); + pr_info("Limiting kernel memory to %liMB due to anomaly 05000263\n", + (max_mem - CONFIG_PHY_RAM_BASE_ADDRESS) >> 20); memory_end = max_mem; } #ifdef CONFIG_MPU +#if defined(CONFIG_ROMFS_ON_MTD) && defined(CONFIG_MTD_ROM) + page_mask_nelts = (((_ramend + ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE - + ASYNC_BANK0_BASE) >> PAGE_SHIFT) + 31) / 32; +#else page_mask_nelts = ((_ramend >> PAGE_SHIFT) + 31) / 32; +#endif page_mask_order = get_order(3 * page_mask_nelts * sizeof(long)); #endif @@ -606,8 +668,8 @@ static __init void memory_setup(void) init_mm.end_data = (unsigned long)_edata; init_mm.brk = (unsigned long)0; - printk(KERN_INFO "Board Memory: %ldMB\n", physical_mem_end >> 20); - printk(KERN_INFO "Kernel Managed Memory: %ldMB\n", _ramend >> 20); + printk(KERN_INFO "Board Memory: %ldMB\n", (physical_mem_end - CONFIG_PHY_RAM_BASE_ADDRESS) >> 20); + printk(KERN_INFO "Kernel Managed Memory: %ldMB\n", (_ramend - CONFIG_PHY_RAM_BASE_ADDRESS) >> 20); printk(KERN_INFO "Memory map:\n" " fixedcode = 0x%p-0x%p\n" @@ -630,7 +692,7 @@ static __init void memory_setup(void) __bss_start, __bss_stop, _sdata, _edata, (void *)&init_thread_union, - (void *)((int)(&init_thread_union) + 0x2000), + (void *)((int)(&init_thread_union) + THREAD_SIZE), __init_begin, __init_end, (void *)_ramstart, (void *)memory_end #ifdef CONFIG_MTD_UCLINUX @@ -650,7 +712,7 @@ void __init find_min_max_pfn(void) int i; max_pfn = 0; - min_low_pfn = memory_end; + min_low_pfn = PFN_DOWN(memory_end); for (i = 0; i < bfin_memmap.nr_map; i++) { unsigned long start, end; @@ -693,8 +755,7 @@ static __init void setup_bootmem_allocator(void) /* pfn of the first usable page frame after kernel image*/ if (min_low_pfn < memory_start >> PAGE_SHIFT) min_low_pfn = memory_start >> PAGE_SHIFT; - - start_pfn = PAGE_OFFSET >> PAGE_SHIFT; + start_pfn = CONFIG_PHY_RAM_BASE_ADDRESS >> PAGE_SHIFT; end_pfn = memory_end >> PAGE_SHIFT; /* @@ -739,8 +800,8 @@ static __init void setup_bootmem_allocator(void) } /* reserve memory before memory_start, including bootmap */ - reserve_bootmem(PAGE_OFFSET, - memory_start + bootmap_size + PAGE_SIZE - 1 - PAGE_OFFSET, + reserve_bootmem(CONFIG_PHY_RAM_BASE_ADDRESS, + memory_start + bootmap_size + PAGE_SIZE - 1 - CONFIG_PHY_RAM_BASE_ADDRESS, BOOTMEM_DEFAULT); } @@ -775,30 +836,90 @@ static inline int __init get_mem_size(void) u32 ddrctl = bfin_read_EBIU_DDRCTL1(); int ret = 0; switch (ddrctl & 0xc0000) { - case DEVSZ_64: ret = 64 / 8; - case DEVSZ_128: ret = 128 / 8; - case DEVSZ_256: ret = 256 / 8; - case DEVSZ_512: ret = 512 / 8; + case DEVSZ_64: + ret = 64 / 8; + break; + case DEVSZ_128: + ret = 128 / 8; + break; + case DEVSZ_256: + ret = 256 / 8; + break; + case DEVSZ_512: + ret = 512 / 8; + break; } switch (ddrctl & 0x30000) { - case DEVWD_4: ret *= 2; - case DEVWD_8: ret *= 2; - case DEVWD_16: break; + case DEVWD_4: + ret *= 2; + case DEVWD_8: + ret *= 2; + case DEVWD_16: + break; } if ((ddrctl & 0xc000) == 0x4000) ret *= 2; return ret; +#elif defined(CONFIG_BF60x) + u32 ddrctl = bfin_read_DMC0_CFG(); + int ret; + switch (ddrctl & 0xf00) { + case DEVSZ_64: + ret = 64 / 8; + break; + case DEVSZ_128: + ret = 128 / 8; + break; + case DEVSZ_256: + ret = 256 / 8; + break; + case DEVSZ_512: + ret = 512 / 8; + break; + case DEVSZ_1G: + ret = 1024 / 8; + break; + case DEVSZ_2G: + ret = 2048 / 8; + break; + } + return ret; #endif BUG(); } +__attribute__((weak)) +void __init native_machine_early_platform_add_devices(void) +{ +} + +#ifdef CONFIG_BF60x +static inline u_long bfin_get_clk(char *name) +{ + struct clk *clk; + u_long clk_rate; + + clk = clk_get(NULL, name); + if (IS_ERR(clk)) + return 0; + + clk_rate = clk_get_rate(clk); + clk_put(clk); + return clk_rate; +} +#endif + void __init setup_arch(char **cmdline_p) { + u32 mmr; unsigned long sclk, cclk; + native_machine_early_platform_add_devices(); + enable_shadow_console(); /* Check to make sure we are running on the right processor */ + mmr = bfin_cpuid(); if (unlikely(CPUID != bfin_cpuid())) printk(KERN_ERR "ERROR: Not running on ADSP-%s: unknown CPUID 0x%04x Rev 0.%d\n", CPU, bfin_cpuid(), bfin_revid()); @@ -819,6 +940,10 @@ void __init setup_arch(char **cmdline_p) memset(&bfin_memmap, 0, sizeof(bfin_memmap)); +#ifdef CONFIG_BF60x + /* Should init clock device before parse command early */ + clk_init(); +#endif /* If the user does not specify things on the command line, use * what the bootloader set things up as */ @@ -833,6 +958,7 @@ void __init setup_arch(char **cmdline_p) memory_setup(); +#ifndef CONFIG_BF60x /* Initialize Async memory banks */ bfin_write_EBIU_AMBCTL0(AMBCTL0VAL); bfin_write_EBIU_AMBCTL1(AMBCTL1VAL); @@ -842,6 +968,14 @@ void __init setup_arch(char **cmdline_p) bfin_write_EBIU_MODE(CONFIG_EBIU_MODEVAL); bfin_write_EBIU_FCTL(CONFIG_EBIU_FCTLVAL); #endif +#endif +#ifdef CONFIG_BFIN_HYSTERESIS_CONTROL + bfin_write_PORTF_HYSTERESIS(HYST_PORTF_0_15); + bfin_write_PORTG_HYSTERESIS(HYST_PORTG_0_15); + bfin_write_PORTH_HYSTERESIS(HYST_PORTH_0_15); + bfin_write_MISCPORT_HYSTERESIS((bfin_read_MISCPORT_HYSTERESIS() & + ~HYST_NONEGPIO_MASK) | HYST_NONEGPIO); +#endif cclk = get_cclk(); sclk = get_sclk(); @@ -855,17 +989,14 @@ void __init setup_arch(char **cmdline_p) bfin_read_IMDMA_D1_IRQ_STATUS(); } #endif - printk(KERN_INFO "Hardware Trace "); - if (bfin_read_TBUFCTL() & 0x1) - printk(KERN_CONT "Active "); - else - printk(KERN_CONT "Off "); - if (bfin_read_TBUFCTL() & 0x2) - printk(KERN_CONT "and Enabled\n"); - else - printk(KERN_CONT "and Disabled\n"); - printk(KERN_INFO "Boot Mode: %i\n", bfin_read_SYSCR() & 0xF); + mmr = bfin_read_TBUFCTL(); + printk(KERN_INFO "Hardware Trace %s and %sabled\n", + (mmr & 0x1) ? "active" : "off", + (mmr & 0x2) ? "en" : "dis"); +#ifndef CONFIG_BF60x + mmr = bfin_read_SYSCR(); + printk(KERN_INFO "Boot Mode: %i\n", mmr & 0xF); /* Newer parts mirror SWRST bits in SYSCR */ #if defined(CONFIG_BF53x) || defined(CONFIG_BF561) || \ @@ -873,7 +1004,7 @@ void __init setup_arch(char **cmdline_p) _bfin_swrst = bfin_read_SWRST(); #else /* Clear boot mode field */ - _bfin_swrst = bfin_read_SYSCR() & ~0xf; + _bfin_swrst = mmr & ~0xf; #endif #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT @@ -891,19 +1022,22 @@ void __init setup_arch(char **cmdline_p) printk(KERN_EMERG "Recovering from DOUBLE FAULT event\n"); #ifdef CONFIG_DEBUG_DOUBLEFAULT /* We assume the crashing kernel, and the current symbol table match */ - printk(KERN_EMERG " While handling exception (EXCAUSE = 0x%x) at %pF\n", - (int)init_saved_seqstat & SEQSTAT_EXCAUSE, init_saved_retx); - printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %pF\n", init_saved_dcplb_fault_addr); - printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %pF\n", init_saved_icplb_fault_addr); + printk(KERN_EMERG " While handling exception (EXCAUSE = %#x) at %pF\n", + initial_pda.seqstat_doublefault & SEQSTAT_EXCAUSE, + initial_pda.retx_doublefault); + printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %pF\n", + initial_pda.dcplb_doublefault_addr); + printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %pF\n", + initial_pda.icplb_doublefault_addr); #endif printk(KERN_NOTICE " The instruction at %pF caused a double exception\n", - init_retx); + initial_pda.retx); } else if (_bfin_swrst & RESET_WDOG) printk(KERN_INFO "Recovering from Watchdog event\n"); else if (_bfin_swrst & RESET_SOFTWARE) printk(KERN_NOTICE "Reset caused by Software reset\n"); - - printk(KERN_INFO "Blackfin support (C) 2004-2009 Analog Devices, Inc.\n"); +#endif + printk(KERN_INFO "Blackfin support (C) 2004-2010 Analog Devices, Inc.\n"); if (bfin_compiled_revid() == 0xffff) printk(KERN_INFO "Compiled for ADSP-%s Rev any, running on 0.%d\n", CPU, bfin_revid()); else if (bfin_compiled_revid() == -1) @@ -930,8 +1064,13 @@ void __init setup_arch(char **cmdline_p) printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n"); +#ifdef CONFIG_BF60x + printk(KERN_INFO "Processor Speed: %lu MHz core clock, %lu MHz SCLk, %lu MHz SCLK0, %lu MHz SCLK1 and %lu MHz DCLK\n", + cclk / 1000000, bfin_get_clk("SYSCLK") / 1000000, get_sclk0() / 1000000, get_sclk1() / 1000000, get_dclk() / 1000000); +#else printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n", cclk / 1000000, sclk / 1000000); +#endif setup_bootmem_allocator(); @@ -965,13 +1104,14 @@ void __init setup_arch(char **cmdline_p) #endif init_exception_vectors(); bfin_cache_init(); /* Initialize caches for the boot CPU */ +#ifdef CONFIG_SCB_PRIORITY + init_scb(); +#endif } static int __init topology_init(void) { unsigned int cpu; - /* Record CPU-private information for the boot processor. */ - bfin_setup_cpudata(0); for_each_possible_cpu(cpu) { register_cpu(&per_cpu(cpu_data, cpu).cpu, cpu); @@ -984,10 +1124,12 @@ subsys_initcall(topology_init); /* Get the input clock frequency */ static u_long cached_clkin_hz = CONFIG_CLKIN_HZ; +#ifndef CONFIG_BF60x static u_long get_clkin_hz(void) { return cached_clkin_hz; } +#endif static int __init early_init_clkin_hz(char *buf) { cached_clkin_hz = simple_strtoul(buf, NULL, 0); @@ -999,6 +1141,7 @@ static int __init early_init_clkin_hz(char *buf) } early_param("clkin_hz=", early_init_clkin_hz); +#ifndef CONFIG_BF60x /* Get the voltage input multiplier */ static u_long get_vco(void) { @@ -1021,10 +1164,14 @@ static u_long get_vco(void) cached_vco *= msel; return cached_vco; } +#endif /* Get the Core clock */ u_long get_cclk(void) { +#ifdef CONFIG_BF60x + return bfin_get_clk("CCLK"); +#else static u_long cached_cclk_pll_div, cached_cclk; u_long csel, ssel; @@ -1044,12 +1191,39 @@ u_long get_cclk(void) else cached_cclk = get_vco() >> csel; return cached_cclk; +#endif } EXPORT_SYMBOL(get_cclk); -/* Get the System clock */ +#ifdef CONFIG_BF60x +/* Get the bf60x clock of SCLK0 domain */ +u_long get_sclk0(void) +{ + return bfin_get_clk("SCLK0"); +} +EXPORT_SYMBOL(get_sclk0); + +/* Get the bf60x clock of SCLK1 domain */ +u_long get_sclk1(void) +{ + return bfin_get_clk("SCLK1"); +} +EXPORT_SYMBOL(get_sclk1); + +/* Get the bf60x DRAM clock */ +u_long get_dclk(void) +{ + return bfin_get_clk("DCLK"); +} +EXPORT_SYMBOL(get_dclk); +#endif + +/* Get the default system clock */ u_long get_sclk(void) { +#ifdef CONFIG_BF60x + return get_sclk0(); +#else static u_long cached_sclk; u_long ssel; @@ -1070,6 +1244,7 @@ u_long get_sclk(void) cached_sclk = get_vco() / ssel; return cached_sclk; +#endif } EXPORT_SYMBOL(get_sclk); @@ -1145,7 +1320,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "(Compiled for Rev %d)", bfin_compiled_revid()); } - seq_printf(m, "\ncpu MHz\t\t: %lu.%03lu/%lu.%03lu\n", + seq_printf(m, "\ncpu MHz\t\t: %lu.%06lu/%lu.%06lu\n", cclk/1000000, cclk%1000000, sclk/1000000, sclk%1000000); seq_printf(m, "bogomips\t: %lu.%02lu\n" @@ -1217,12 +1392,14 @@ static int show_cpuinfo(struct seq_file *m, void *v) dsup_banks, BFIN_DSUBBANKS, BFIN_DWAYS, BFIN_DLINES); #ifdef __ARCH_SYNC_CORE_DCACHE - seq_printf(m, "SMP Dcache Flushes\t: %lu\n\n", cpudata->dcache_invld_count); + seq_printf(m, "dcache flushes\t: %lu\n", dcache_invld_count[cpu_num]); #endif #ifdef __ARCH_SYNC_CORE_ICACHE - seq_printf(m, "SMP Icache Flushes\t: %lu\n\n", cpudata->icache_invld_count); + seq_printf(m, "icache flushes\t: %lu\n", icache_invld_count[cpu_num]); #endif + seq_printf(m, "\n"); + if (cpu_num != num_possible_cpus() - 1) return 0; @@ -1246,13 +1423,11 @@ static int show_cpuinfo(struct seq_file *m, void *v) " in data cache\n"); } seq_printf(m, "board name\t: %s\n", bfin_board_name); - seq_printf(m, "board memory\t: %ld kB (0x%p -> 0x%p)\n", - physical_mem_end >> 10, (void *)0, (void *)physical_mem_end); - seq_printf(m, "kernel memory\t: %d kB (0x%p -> 0x%p)\n", - ((int)memory_end - (int)_stext) >> 10, - _stext, - (void *)memory_end); - seq_printf(m, "\n"); + seq_printf(m, "board memory\t: %ld kB (0x%08lx -> 0x%08lx)\n", + physical_mem_end >> 10, 0ul, physical_mem_end); + seq_printf(m, "kernel memory\t: %d kB (0x%08lx -> 0x%08lx)\n", + ((int)memory_end - (int)_rambase) >> 10, + _rambase, memory_end); return 0; } @@ -1260,7 +1435,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) static void *c_start(struct seq_file *m, loff_t *pos) { if (*pos == 0) - *pos = first_cpu(cpu_online_map); + *pos = cpumask_first(cpu_online_mask); if (*pos >= num_online_cpus()) return NULL; @@ -1269,7 +1444,7 @@ static void *c_start(struct seq_file *m, loff_t *pos) static void *c_next(struct seq_file *m, void *v, loff_t *pos) { - *pos = next_cpu(*pos, cpu_online_map); + *pos = cpumask_next(*pos, cpu_online_mask); return c_start(m, pos); } |
