summaryrefslogtreecommitdiff
path: root/arch/blackfin/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r--arch/blackfin/kernel/bfin_dma_5xx.c10
-rw-r--r--arch/blackfin/kernel/bfin_gpio.c20
-rw-r--r--arch/blackfin/kernel/cplb-mpu/cplbinit.c4
-rw-r--r--arch/blackfin/kernel/init_task.c2
-rw-r--r--arch/blackfin/kernel/setup.c583
-rw-r--r--arch/blackfin/kernel/traps.c2
-rw-r--r--arch/blackfin/kernel/vmlinux.lds.S47
7 files changed, 492 insertions, 176 deletions
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c
index fa9debe8..5453bc3 100644
--- a/arch/blackfin/kernel/bfin_dma_5xx.c
+++ b/arch/blackfin/kernel/bfin_dma_5xx.c
@@ -104,6 +104,16 @@ int request_dma(unsigned int channel, char *device_id)
mutex_unlock(&(dma_ch[channel].dmalock));
+#ifdef CONFIG_BF54x
+ if (channel >= CH_UART2_RX && channel <= CH_UART3_TX &&
+ strncmp(device_id, "BFIN_UART", 9) == 0)
+ dma_ch[channel].regs->peripheral_map |=
+ (channel - CH_UART2_RX + 0xC);
+ else
+ dma_ch[channel].regs->peripheral_map |=
+ (channel - CH_UART2_RX + 0x6);
+#endif
+
dma_ch[channel].device_id = device_id;
dma_ch[channel].irq_callback = NULL;
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index 6bbe0a2..08788f7 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -186,7 +186,7 @@ static struct str_ident {
char name[RESOURCE_LABEL_SIZE];
} str_ident[MAX_RESOURCES];
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM) && !defined(CONFIG_BF54x)
static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS];
static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)];
@@ -696,9 +696,8 @@ static int bfin_gpio_wakeup_type(unsigned gpio, unsigned char type)
return 0;
}
-u32 gpio_pm_setup(void)
+u32 bfin_pm_setup(void)
{
- u32 sic_iwr = 0;
u16 bank, mask, i, gpio;
for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
@@ -723,7 +722,8 @@ u32 gpio_pm_setup(void)
gpio = i;
while (mask) {
- if (mask & 1) {
+ if ((mask & 1) && (wakeup_flags_map[gpio] !=
+ PM_WAKE_IGNORE)) {
reserved_gpio_map[gpio_bank(gpio)] |=
gpio_bit(gpio);
bfin_gpio_wakeup_type(gpio,
@@ -734,21 +734,17 @@ u32 gpio_pm_setup(void)
mask >>= 1;
}
- sic_iwr |= 1 <<
- (sic_iwr_irqs[bank] - (IRQ_CORETMR + 1));
+ bfin_internal_set_wake(sic_iwr_irqs[bank], 1);
gpio_bankb[bank]->maskb_set = wakeup_map[gpio_bank(i)];
}
}
AWA_DUMMY_READ(maskb_set);
- if (sic_iwr)
- return sic_iwr;
- else
- return IWR_ENABLE_ALL;
+ return 0;
}
-void gpio_pm_restore(void)
+void bfin_pm_restore(void)
{
u16 bank, mask, i;
@@ -768,7 +764,7 @@ void gpio_pm_restore(void)
reserved_gpio_map[bank] =
gpio_bank_saved[bank].reserved;
-
+ bfin_internal_set_wake(sic_iwr_irqs[bank], 0);
}
gpio_bankb[bank]->maskb = gpio_bank_saved[bank].maskb;
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinit.c b/arch/blackfin/kernel/cplb-mpu/cplbinit.c
index e2e2b50..dc6e8a7 100644
--- a/arch/blackfin/kernel/cplb-mpu/cplbinit.c
+++ b/arch/blackfin/kernel/cplb-mpu/cplbinit.c
@@ -26,6 +26,10 @@
#include <asm/cplb.h>
#include <asm/cplbinit.h>
+#if ANOMALY_05000263
+# error the MPU will not function safely while Anomaly 05000263 applies
+#endif
+
struct cplb_entry icplb_tbl[MAX_CPLBS];
struct cplb_entry dcplb_tbl[MAX_CPLBS];
diff --git a/arch/blackfin/kernel/init_task.c b/arch/blackfin/kernel/init_task.c
index 673c860..c640154 100644
--- a/arch/blackfin/kernel/init_task.c
+++ b/arch/blackfin/kernel/init_task.c
@@ -57,5 +57,5 @@ EXPORT_SYMBOL(init_task);
* "init_task" linker map entry.
*/
union thread_union init_thread_union
- __attribute__ ((__section__(".data.init_task"))) = {
+ __attribute__ ((__section__(".init_task.data"))) = {
INIT_THREAD_INFO(init_task)};
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index 289ea9d..8229b10 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -1,30 +1,11 @@
/*
- * File: arch/blackfin/kernel/setup.c
- * Based on:
- * Author:
+ * arch/blackfin/kernel/setup.c
*
- * Created:
- * Description:
+ * Copyright 2004-2006 Analog Devices Inc.
*
- * Modified:
- * Copyright 2004-2006 Analog Devices Inc.
+ * Enter bugs at http://blackfin.uclinux.org/
*
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * Licensed under the GPL-2 or later.
*/
#include <linux/delay.h>
@@ -34,6 +15,7 @@
#include <linux/cpu.h>
#include <linux/module.h>
#include <linux/tty.h>
+#include <linux/pfn.h>
#include <linux/ext2_fs.h>
#include <linux/cramfs_fs.h>
@@ -47,6 +29,8 @@
#include <asm/fixed_code.h>
#include <asm/early_printk.h>
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
u16 _bfin_swrst;
unsigned long memory_start, memory_end, physical_mem_end;
@@ -67,6 +51,29 @@ EXPORT_SYMBOL(mtd_size);
char __initdata command_line[COMMAND_LINE_SIZE];
+/* boot memmap, for parsing "memmap=" */
+#define BFIN_MEMMAP_MAX 128 /* number of entries in bfin_memmap */
+#define BFIN_MEMMAP_RAM 1
+#define BFIN_MEMMAP_RESERVED 2
+struct bfin_memmap {
+ int nr_map;
+ struct bfin_memmap_entry {
+ unsigned long long addr; /* start of memory segment */
+ unsigned long long size;
+ unsigned long type;
+ } map[BFIN_MEMMAP_MAX];
+} bfin_memmap __initdata;
+
+/* for memmap sanitization */
+struct change_member {
+ struct bfin_memmap_entry *pentry; /* pointer to original entry */
+ unsigned long long addr; /* address for this change point */
+};
+static struct change_member change_point_list[2*BFIN_MEMMAP_MAX] __initdata;
+static struct change_member *change_point[2*BFIN_MEMMAP_MAX] __initdata;
+static struct bfin_memmap_entry *overlap_list[BFIN_MEMMAP_MAX] __initdata;
+static struct bfin_memmap_entry new_map[BFIN_MEMMAP_MAX] __initdata;
+
void __init bf53x_cache_init(void)
{
#if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE)
@@ -123,12 +130,224 @@ void __init bf53x_relocate_l1_mem(void)
}
+/* add_memory_region to memmap */
+static void __init add_memory_region(unsigned long long start,
+ unsigned long long size, int type)
+{
+ int i;
+
+ i = bfin_memmap.nr_map;
+
+ if (i == BFIN_MEMMAP_MAX) {
+ printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
+ return;
+ }
+
+ bfin_memmap.map[i].addr = start;
+ bfin_memmap.map[i].size = size;
+ bfin_memmap.map[i].type = type;
+ bfin_memmap.nr_map++;
+}
+
+/*
+ * Sanitize the boot memmap, removing overlaps.
+ */
+static int __init sanitize_memmap(struct bfin_memmap_entry *map, int *pnr_map)
+{
+ struct change_member *change_tmp;
+ unsigned long current_type, last_type;
+ unsigned long long last_addr;
+ int chgidx, still_changing;
+ int overlap_entries;
+ int new_entry;
+ int old_nr, new_nr, chg_nr;
+ int i;
+
+ /*
+ Visually we're performing the following (1,2,3,4 = memory types)
+
+ Sample memory map (w/overlaps):
+ ____22__________________
+ ______________________4_
+ ____1111________________
+ _44_____________________
+ 11111111________________
+ ____________________33__
+ ___________44___________
+ __________33333_________
+ ______________22________
+ ___________________2222_
+ _________111111111______
+ _____________________11_
+ _________________4______
+
+ Sanitized equivalent (no overlap):
+ 1_______________________
+ _44_____________________
+ ___1____________________
+ ____22__________________
+ ______11________________
+ _________1______________
+ __________3_____________
+ ___________44___________
+ _____________33_________
+ _______________2________
+ ________________1_______
+ _________________4______
+ ___________________2____
+ ____________________33__
+ ______________________4_
+ */
+ /* if there's only one memory region, don't bother */
+ if (*pnr_map < 2)
+ return -1;
+
+ old_nr = *pnr_map;
+
+ /* bail out if we find any unreasonable addresses in memmap */
+ for (i = 0; i < old_nr; i++)
+ if (map[i].addr + map[i].size < map[i].addr)
+ return -1;
+
+ /* create pointers for initial change-point information (for sorting) */
+ for (i = 0; i < 2*old_nr; i++)
+ change_point[i] = &change_point_list[i];
+
+ /* record all known change-points (starting and ending addresses),
+ omitting those that are for empty memory regions */
+ chgidx = 0;
+ for (i = 0; i < old_nr; i++) {
+ if (map[i].size != 0) {
+ change_point[chgidx]->addr = map[i].addr;
+ change_point[chgidx++]->pentry = &map[i];
+ change_point[chgidx]->addr = map[i].addr + map[i].size;
+ change_point[chgidx++]->pentry = &map[i];
+ }
+ }
+ chg_nr = chgidx; /* true number of change-points */
+
+ /* sort change-point list by memory addresses (low -> high) */
+ still_changing = 1;
+ while (still_changing) {
+ still_changing = 0;
+ for (i = 1; i < chg_nr; i++) {
+ /* if <current_addr> > <last_addr>, swap */
+ /* or, if current=<start_addr> & last=<end_addr>, swap */
+ if ((change_point[i]->addr < change_point[i-1]->addr) ||
+ ((change_point[i]->addr == change_point[i-1]->addr) &&
+ (change_point[i]->addr == change_point[i]->pentry->addr) &&
+ (change_point[i-1]->addr != change_point[i-1]->pentry->addr))
+ ) {
+ change_tmp = change_point[i];
+ change_point[i] = change_point[i-1];
+ change_point[i-1] = change_tmp;
+ still_changing = 1;
+ }
+ }
+ }
+
+ /* create a new memmap, removing overlaps */
+ overlap_entries = 0; /* number of entries in the overlap table */
+ new_entry = 0; /* index for creating new memmap entries */
+ last_type = 0; /* start with undefined memory type */
+ last_addr = 0; /* start with 0 as last starting address */
+ /* loop through change-points, determining affect on the new memmap */
+ for (chgidx = 0; chgidx < chg_nr; chgidx++) {
+ /* keep track of all overlapping memmap entries */
+ if (change_point[chgidx]->addr == change_point[chgidx]->pentry->addr) {
+ /* add map entry to overlap list (> 1 entry implies an overlap) */
+ overlap_list[overlap_entries++] = change_point[chgidx]->pentry;
+ } else {
+ /* remove entry from list (order independent, so swap with last) */
+ for (i = 0; i < overlap_entries; i++) {
+ if (overlap_list[i] == change_point[chgidx]->pentry)
+ overlap_list[i] = overlap_list[overlap_entries-1];
+ }
+ overlap_entries--;
+ }
+ /* if there are overlapping entries, decide which "type" to use */
+ /* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */
+ current_type = 0;
+ for (i = 0; i < overlap_entries; i++)
+ if (overlap_list[i]->type > current_type)
+ current_type = overlap_list[i]->type;
+ /* continue building up new memmap based on this information */
+ if (current_type != last_type) {
+ if (last_type != 0) {
+ new_map[new_entry].size =
+ change_point[chgidx]->addr - last_addr;
+ /* move forward only if the new size was non-zero */
+ if (new_map[new_entry].size != 0)
+ if (++new_entry >= BFIN_MEMMAP_MAX)
+ break; /* no more space left for new entries */
+ }
+ if (current_type != 0) {
+ new_map[new_entry].addr = change_point[chgidx]->addr;
+ new_map[new_entry].type = current_type;
+ last_addr = change_point[chgidx]->addr;
+ }
+ last_type = current_type;
+ }
+ }
+ new_nr = new_entry; /* retain count for new entries */
+
+ /* copy new mapping into original location */
+ memcpy(map, new_map, new_nr*sizeof(struct bfin_memmap_entry));
+ *pnr_map = new_nr;
+
+ return 0;
+}
+
+static void __init print_memory_map(char *who)
+{
+ int i;
+
+ for (i = 0; i < bfin_memmap.nr_map; i++) {
+ printk(KERN_DEBUG " %s: %016Lx - %016Lx ", who,
+ bfin_memmap.map[i].addr,
+ bfin_memmap.map[i].addr + bfin_memmap.map[i].size);
+ switch (bfin_memmap.map[i].type) {
+ case BFIN_MEMMAP_RAM:
+ printk("(usable)\n");
+ break;
+ case BFIN_MEMMAP_RESERVED:
+ printk("(reserved)\n");
+ break;
+ default: printk("type %lu\n", bfin_memmap.map[i].type);
+ break;
+ }
+ }
+}
+
+static __init int parse_memmap(char *arg)
+{
+ unsigned long long start_at, mem_size;
+
+ if (!arg)
+ return -EINVAL;
+
+ mem_size = memparse(arg, &arg);
+ if (*arg == '@') {
+ start_at = memparse(arg+1, &arg);
+ add_memory_region(start_at, mem_size, BFIN_MEMMAP_RAM);
+ } else if (*arg == '$') {
+ start_at = memparse(arg+1, &arg);
+ add_memory_region(start_at, mem_size, BFIN_MEMMAP_RESERVED);
+ }
+
+ return 0;
+}
+
/*
* Initial parsing of the command line. Currently, we support:
* - Controlling the linux memory size: mem=xxx[KMG]
* - Controlling the physical memory size: max_mem=xxx[KMG][$][#]
* $ -> reserved memory is dcacheable
* # -> reserved memory is icacheable
+ * - "memmap=XXX[KkmM][@][$]XXX[KkmM]" defines a memory region
+ * @ from <start> to <start>+<mem>, type RAM
+ * $ from <start> to <start>+<mem>, type RESERVED
+ *
*/
static __init void parse_cmdline_early(char *cmdline_p)
{
@@ -136,7 +355,6 @@ static __init void parse_cmdline_early(char *cmdline_p)
unsigned int memsize;
for (;;) {
if (c == ' ') {
-
if (!memcmp(to, "mem=", 4)) {
to += 4;
memsize = memparse(to, &to);
@@ -162,6 +380,9 @@ static __init void parse_cmdline_early(char *cmdline_p)
} else if (!memcmp(to, "earlyprintk=", 12)) {
to += 12;
setup_early_printk(to);
+ } else if (!memcmp(to, "memmap=", 7)) {
+ to += 7;
+ parse_memmap(to);
}
}
c = *(to++);
@@ -170,75 +391,36 @@ static __init void parse_cmdline_early(char *cmdline_p)
}
}
-void __init setup_arch(char **cmdline_p)
+/*
+ * Setup memory defaults from user config.
+ * The physical memory layout looks like:
+ *
+ * [_rambase, _ramstart]: kernel image
+ * [memory_start, memory_end]: dynamic memory managed by kernel
+ * [memory_end, _ramend]: reserved memory
+ * [meory_mtd_start(memory_end),
+ * memory_mtd_start + mtd_size]: rootfs (if any)
+ * [_ramend - DMA_UNCACHED_REGION,
+ * _ramend]: uncached DMA region
+ * [_ramend, physical_mem_end]: memory not managed by kernel
+ *
+ */
+static __init void memory_setup(void)
{
- int bootmap_size;
- unsigned long l1_length, sclk, cclk;
#ifdef CONFIG_MTD_UCLINUX
unsigned long mtd_phys = 0;
#endif
-#ifdef CONFIG_DUMMY_CONSOLE
- conswitchp = &dummy_con;
-#endif
-
-#if defined(CONFIG_CMDLINE_BOOL)
- strncpy(&command_line[0], CONFIG_CMDLINE, sizeof(command_line));
- command_line[sizeof(command_line) - 1] = 0;
-#endif
-
- /* Keep a copy of command line */
- *cmdline_p = &command_line[0];
- memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
- boot_command_line[COMMAND_LINE_SIZE - 1] = '\0';
-
- /* setup memory defaults from the user config */
- physical_mem_end = 0;
- _ramend = CONFIG_MEM_SIZE * 1024 * 1024;
-
- parse_cmdline_early(&command_line[0]);
-
- cclk = get_cclk();
- sclk = get_sclk();
-
-#if !defined(CONFIG_BFIN_KERNEL_CLOCK)
- if (ANOMALY_05000273 && cclk == sclk)
- panic("ANOMALY 05000273, SCLK can not be same as CCLK");
-#endif
+ _rambase = (unsigned long)_stext;
+ _ramstart = (unsigned long)_end;
-#ifdef BF561_FAMILY
- if (ANOMALY_05000266) {
- bfin_read_IMDMA_D0_IRQ_STATUS();
- bfin_read_IMDMA_D1_IRQ_STATUS();
+ if (DMA_UNCACHED_REGION > (_ramend - _ramstart)) {
+ console_init();
+ panic("DMA region exceeds memory limit: %lu.\n",
+ _ramend - _ramstart);
}
-#endif
-
- printk(KERN_INFO "Hardware Trace ");
- if (bfin_read_TBUFCTL() & 0x1 )
- printk("Active ");
- else
- printk("Off ");
- if (bfin_read_TBUFCTL() & 0x2)
- printk("and Enabled\n");
- else
- printk("and Disabled\n");
-
-
-#if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
- /* we need to initialize the Flashrom device here since we might
- * do things with flash early on in the boot
- */
- flash_probe();
-#endif
-
- if (physical_mem_end == 0)
- physical_mem_end = _ramend;
-
- /* by now the stack is part of the init task */
memory_end = _ramend - DMA_UNCACHED_REGION;
- _ramstart = (unsigned long)__bss_stop;
- _rambase = (unsigned long)_stext;
#ifdef CONFIG_MPU
/* Round up to multiple of 4MB. */
memory_start = (_ramstart + 0x3fffff) & ~0x3fffff;
@@ -292,7 +474,7 @@ void __init setup_arch(char **cmdline_p)
}
/* Relocate MTD image to the top of memory after the uncached memory area */
- dma_memcpy((char *)memory_end, __bss_stop, mtd_size);
+ dma_memcpy((char *)memory_end, _end, mtd_size);
memory_mtd_start = memory_end;
_ebss = memory_mtd_start; /* define _ebss for compatible */
@@ -319,13 +501,175 @@ void __init setup_arch(char **cmdline_p)
#endif
#if !defined(CONFIG_MTD_UCLINUX)
- memory_end -= SIZE_4K; /*In case there is no valid CPLB behind memory_end make sure we don't get to close*/
+ /*In case there is no valid CPLB behind memory_end make sure we don't get to close*/
+ memory_end -= SIZE_4K;
#endif
+
init_mm.start_code = (unsigned long)_stext;
init_mm.end_code = (unsigned long)_etext;
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 "Memory map:\n"
+ KERN_INFO " text = 0x%p-0x%p\n"
+ KERN_INFO " rodata = 0x%p-0x%p\n"
+ KERN_INFO " bss = 0x%p-0x%p\n"
+ KERN_INFO " data = 0x%p-0x%p\n"
+ KERN_INFO " stack = 0x%p-0x%p\n"
+ KERN_INFO " init = 0x%p-0x%p\n"
+ KERN_INFO " available = 0x%p-0x%p\n"
+#ifdef CONFIG_MTD_UCLINUX
+ KERN_INFO " rootfs = 0x%p-0x%p\n"
+#endif
+#if DMA_UNCACHED_REGION > 0
+ KERN_INFO " DMA Zone = 0x%p-0x%p\n"
+#endif
+ , _stext, _etext,
+ __start_rodata, __end_rodata,
+ __bss_start, __bss_stop,
+ _sdata, _edata,
+ (void *)&init_thread_union,
+ (void *)((int)(&init_thread_union) + 0x2000),
+ __init_begin, __init_end,
+ (void *)_ramstart, (void *)memory_end
+#ifdef CONFIG_MTD_UCLINUX
+ , (void *)memory_mtd_start, (void *)(memory_mtd_start + mtd_size)
+#endif
+#if DMA_UNCACHED_REGION > 0
+ , (void *)(_ramend - DMA_UNCACHED_REGION), (void *)(_ramend)
+#endif
+ );
+}
+
+static __init void setup_bootmem_allocator(void)
+{
+ int bootmap_size;
+ int i;
+ unsigned long min_pfn, max_pfn;
+ unsigned long curr_pfn, last_pfn, size;
+
+ /* mark memory between memory_start and memory_end usable */
+ add_memory_region(memory_start,
+ memory_end - memory_start, BFIN_MEMMAP_RAM);
+ /* sanity check for overlap */
+ sanitize_memmap(bfin_memmap.map, &bfin_memmap.nr_map);
+ print_memory_map("boot memmap");
+
+ min_pfn = PAGE_OFFSET >> PAGE_SHIFT;
+ max_pfn = memory_end >> PAGE_SHIFT;
+
+ /*
+ * give all the memory to the bootmap allocator, tell it to put the
+ * boot mem_map at the start of memory.
+ */
+ bootmap_size = init_bootmem_node(NODE_DATA(0),
+ memory_start >> PAGE_SHIFT, /* map goes here */
+ min_pfn, max_pfn);
+
+ /* register the memmap regions with the bootmem allocator */
+ for (i = 0; i < bfin_memmap.nr_map; i++) {
+ /*
+ * Reserve usable memory
+ */
+ if (bfin_memmap.map[i].type != BFIN_MEMMAP_RAM)
+ continue;
+ /*
+ * We are rounding up the start address of usable memory:
+ */
+ curr_pfn = PFN_UP(bfin_memmap.map[i].addr);
+ if (curr_pfn >= max_pfn)
+ continue;
+ /*
+ * ... and at the end of the usable range downwards:
+ */
+ last_pfn = PFN_DOWN(bfin_memmap.map[i].addr +
+ bfin_memmap.map[i].size);
+
+ if (last_pfn > max_pfn)
+ last_pfn = max_pfn;
+
+ /*
+ * .. finally, did all the rounding and playing
+ * around just make the area go away?
+ */
+ if (last_pfn <= curr_pfn)
+ continue;
+
+ size = last_pfn - curr_pfn;
+ free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
+ }
+
+ /* reserve memory before memory_start, including bootmap */
+ reserve_bootmem(PAGE_OFFSET,
+ memory_start + bootmap_size + PAGE_SIZE - 1 - PAGE_OFFSET,
+ BOOTMEM_DEFAULT);
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+ unsigned long l1_length, sclk, cclk;
+
+#ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+#endif
+
+#if defined(CONFIG_CMDLINE_BOOL)
+ strncpy(&command_line[0], CONFIG_CMDLINE, sizeof(command_line));
+ command_line[sizeof(command_line) - 1] = 0;
+#endif
+
+ /* Keep a copy of command line */
+ *cmdline_p = &command_line[0];
+ memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+ boot_command_line[COMMAND_LINE_SIZE - 1] = '\0';
+
+ /* setup memory defaults from the user config */
+ physical_mem_end = 0;
+ _ramend = CONFIG_MEM_SIZE * 1024 * 1024;
+
+ memset(&bfin_memmap, 0, sizeof(bfin_memmap));
+
+ parse_cmdline_early(&command_line[0]);
+
+ if (physical_mem_end == 0)
+ physical_mem_end = _ramend;
+
+ memory_setup();
+
+ cclk = get_cclk();
+ sclk = get_sclk();
+
+#if !defined(CONFIG_BFIN_KERNEL_CLOCK)
+ if (ANOMALY_05000273 && cclk == sclk)
+ panic("ANOMALY 05000273, SCLK can not be same as CCLK");
+#endif
+
+#ifdef BF561_FAMILY
+ if (ANOMALY_05000266) {
+ bfin_read_IMDMA_D0_IRQ_STATUS();
+ bfin_read_IMDMA_D1_IRQ_STATUS();
+ }
+#endif
+ printk(KERN_INFO "Hardware Trace ");
+ if (bfin_read_TBUFCTL() & 0x1)
+ printk("Active ");
+ else
+ printk("Off ");
+ if (bfin_read_TBUFCTL() & 0x2)
+ printk("and Enabled\n");
+ else
+ printk("and Disabled\n");
+
+#if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
+ /* we need to initialize the Flashrom device here since we might
+ * do things with flash early on in the boot
+ */
+ flash_probe();
+#endif
+
_bfin_swrst = bfin_read_SWRST();
if (_bfin_swrst & RESET_DOUBLE)
@@ -335,7 +679,7 @@ void __init setup_arch(char **cmdline_p)
else if (_bfin_swrst & RESET_SOFTWARE)
printk(KERN_NOTICE "Reset caused by Software reset\n");
- printk(KERN_INFO "Blackfin support (C) 2004-2007 Analog Devices, Inc.\n");
+ printk(KERN_INFO "Blackfin support (C) 2004-2008 Analog Devices, Inc.\n");
if (bfin_compiled_revid() == 0xffff)
printk(KERN_INFO "Compiled for ADSP-%s Rev any\n", CPU);
else if (bfin_compiled_revid() == -1)
@@ -361,55 +705,8 @@ void __init setup_arch(char **cmdline_p)
if (ANOMALY_05000273 && (cclk >> 1) <= sclk)
printk("\n\n\nANOMALY_05000273: CCLK must be >= 2*SCLK !!!\n\n\n");
- printk(KERN_INFO "Board Memory: %ldMB\n", physical_mem_end >> 20);
- printk(KERN_INFO "Kernel Managed Memory: %ldMB\n", _ramend >> 20);
-
- printk(KERN_INFO "Memory map:\n"
- KERN_INFO " text = 0x%p-0x%p\n"
- KERN_INFO " rodata = 0x%p-0x%p\n"
- KERN_INFO " data = 0x%p-0x%p\n"
- KERN_INFO " stack = 0x%p-0x%p\n"
- KERN_INFO " init = 0x%p-0x%p\n"
- KERN_INFO " bss = 0x%p-0x%p\n"
- KERN_INFO " available = 0x%p-0x%p\n"
-#ifdef CONFIG_MTD_UCLINUX
- KERN_INFO " rootfs = 0x%p-0x%p\n"
-#endif
-#if DMA_UNCACHED_REGION > 0
- KERN_INFO " DMA Zone = 0x%p-0x%p\n"
-#endif
- , _stext, _etext,
- __start_rodata, __end_rodata,
- _sdata, _edata,
- (void *)&init_thread_union, (void *)((int)(&init_thread_union) + 0x2000),
- __init_begin, __init_end,
- __bss_start, __bss_stop,
- (void *)_ramstart, (void *)memory_end
-#ifdef CONFIG_MTD_UCLINUX
- , (void *)memory_mtd_start, (void *)(memory_mtd_start + mtd_size)
-#endif
-#if DMA_UNCACHED_REGION > 0
- , (void *)(_ramend - DMA_UNCACHED_REGION), (void *)(_ramend)
-#endif
- );
+ setup_bootmem_allocator();
- /*
- * give all the memory to the bootmap allocator, tell it to put the
- * boot mem_map at the start of memory
- */
- bootmap_size = init_bootmem_node(NODE_DATA(0), memory_start >> PAGE_SHIFT, /* map goes here */
- PAGE_OFFSET >> PAGE_SHIFT,
- memory_end >> PAGE_SHIFT);
- /*
- * free the usable memory, we have to make sure we do not free
- * the bootmem bitmap so we then reserve it after freeing it :-)
- */
- free_bootmem(memory_start, memory_end - memory_start);
-
- reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT);
- /*
- * get kmalloc into gear
- */
paging_init();
/* check the size of the l1 area */
@@ -450,15 +747,15 @@ void __init setup_arch(char **cmdline_p)
static int __init topology_init(void)
{
-#if defined (CONFIG_BF561)
- static struct cpu cpu[2];
- register_cpu(&cpu[0], 0);
- register_cpu(&cpu[1], 1);
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ struct cpu *c = &per_cpu(cpu_devices, cpu);
+
+ register_cpu(c, cpu);
+ }
+
return 0;
-#else
- static struct cpu cpu[1];
- return register_cpu(cpu, 0);
-#endif
}
subsys_initcall(topology_init);
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index 66b5f3e..58717cb 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -649,7 +649,7 @@ void dump_bfin_process(struct pt_regs *fp)
if (context & 0x0020 && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR)
printk(KERN_NOTICE "HW Error context\n");
else if (context & 0x0020)
- printk(KERN_NOTICE "Defered Exception context\n");
+ printk(KERN_NOTICE "Deferred Exception context\n");
else if (context & 0x3FC0)
printk(KERN_NOTICE "Interrupt context\n");
else if (context & 0x4000)
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 8587224..aed8325 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -41,6 +41,9 @@ _jiffies = _jiffies_64;
SECTIONS
{
. = CONFIG_BOOT_LOAD;
+ /* Neither the text, ro_data or bss section need to be aligned
+ * So pack them back to back
+ */
.text :
{
__text = .;
@@ -58,22 +61,25 @@ SECTIONS
*(__ex_table)
___stop___ex_table = .;
- . = ALIGN(4);
__etext = .;
}
- RO_DATA(PAGE_SIZE)
+ /* Just in case the first read only is a 32-bit access */
+ RO_DATA(4)
+
+ .bss :
+ {
+ . = ALIGN(4);
+ ___bss_start = .;
+ *(.bss .bss.*)
+ *(COMMON)
+ ___bss_stop = .;
+ }
.data :
{
- /* make sure the init_task is aligned to the
- * kernel thread size so we can locate the kernel
- * stack properly and quickly.
- */
__sdata = .;
- . = ALIGN(THREAD_SIZE);
- *(.data.init_task)
-
+ /* This gets done first, so the glob doesn't suck it in */
. = ALIGN(32);
*(.data.cacheline_aligned)
@@ -81,10 +87,22 @@ SECTIONS
*(.data.*)
CONSTRUCTORS
+ /* make sure the init_task is aligned to the
+ * kernel thread size so we can locate the kernel
+ * stack properly and quickly.
+ */
. = ALIGN(THREAD_SIZE);
+ *(.init_task.data)
+
__edata = .;
}
+ /* The init section should be last, so when we free it, it goes into
+ * the general memory pool, and (hopefully) will decrease fragmentation
+ * a tiny bit. The init section has a _requirement_ that it be
+ * PAGE_SIZE aligned
+ */
+ . = ALIGN(PAGE_SIZE);
___init_begin = .;
.init.text :
@@ -179,16 +197,7 @@ SECTIONS
. = ALIGN(PAGE_SIZE);
___init_end = .;
- .bss :
- {
- . = ALIGN(4);
- ___bss_start = .;
- *(.bss .bss.*)
- *(COMMON)
- . = ALIGN(4);
- ___bss_stop = .;
- __end = .;
- }
+ __end =.;
STABS_DEBUG