02b08045a0
Microblaze little-endian toolchain exports __MICROBLAZEEL__ which is used in the kernel to identify little/big endian. The most of the changes are in loading values from DTB which is always big endian. Little endian platforms are based on new AXI bus which has impact to early uartlite initialization. Signed-off-by: Michal Simek <monstr@monstr.eu>
198 lines
5.1 KiB
C
198 lines
5.1 KiB
C
/*
|
|
* Procedures for creating, accessing and interpreting the device tree.
|
|
*
|
|
* Paul Mackerras August 1996.
|
|
* Copyright (C) 1996-2005 Paul Mackerras.
|
|
*
|
|
* Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
|
|
* {engebret|bergner}@us.ibm.com
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#include <stdarg.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/string.h>
|
|
#include <linux/init.h>
|
|
#include <linux/threads.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/types.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/stringify.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/initrd.h>
|
|
#include <linux/bitops.h>
|
|
#include <linux/module.h>
|
|
#include <linux/kexec.h>
|
|
#include <linux/debugfs.h>
|
|
#include <linux/irq.h>
|
|
#include <linux/memblock.h>
|
|
|
|
#include <asm/prom.h>
|
|
#include <asm/page.h>
|
|
#include <asm/processor.h>
|
|
#include <asm/irq.h>
|
|
#include <linux/io.h>
|
|
#include <asm/system.h>
|
|
#include <asm/mmu.h>
|
|
#include <asm/pgtable.h>
|
|
#include <asm/sections.h>
|
|
#include <asm/pci-bridge.h>
|
|
|
|
void __init early_init_dt_scan_chosen_arch(unsigned long node)
|
|
{
|
|
/* No Microblaze specific code here */
|
|
}
|
|
|
|
void __init early_init_dt_add_memory_arch(u64 base, u64 size)
|
|
{
|
|
memblock_add(base, size);
|
|
}
|
|
|
|
u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
|
|
{
|
|
return memblock_alloc(size, align);
|
|
}
|
|
|
|
#ifdef CONFIG_EARLY_PRINTK
|
|
/* MS this is Microblaze specifig function */
|
|
static int __init early_init_dt_scan_serial(unsigned long node,
|
|
const char *uname, int depth, void *data)
|
|
{
|
|
unsigned long l;
|
|
char *p;
|
|
int *addr;
|
|
|
|
pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
|
|
|
|
/* find all serial nodes */
|
|
if (strncmp(uname, "serial", 6) != 0)
|
|
return 0;
|
|
|
|
early_init_dt_check_for_initrd(node);
|
|
|
|
/* find compatible node with uartlite */
|
|
p = of_get_flat_dt_prop(node, "compatible", &l);
|
|
if ((strncmp(p, "xlnx,xps-uartlite", 17) != 0) &&
|
|
(strncmp(p, "xlnx,opb-uartlite", 17) != 0) &&
|
|
(strncmp(p, "xlnx,axi-uartlite", 17) != 0))
|
|
return 0;
|
|
|
|
addr = of_get_flat_dt_prop(node, "reg", &l);
|
|
return be32_to_cpup(addr); /* return address */
|
|
}
|
|
|
|
/* this function is looking for early uartlite console - Microblaze specific */
|
|
int __init early_uartlite_console(void)
|
|
{
|
|
return of_scan_flat_dt(early_init_dt_scan_serial, NULL);
|
|
}
|
|
|
|
/* MS this is Microblaze specifig function */
|
|
static int __init early_init_dt_scan_serial_full(unsigned long node,
|
|
const char *uname, int depth, void *data)
|
|
{
|
|
unsigned long l;
|
|
char *p;
|
|
unsigned int addr;
|
|
|
|
pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
|
|
|
|
/* find all serial nodes */
|
|
if (strncmp(uname, "serial", 6) != 0)
|
|
return 0;
|
|
|
|
early_init_dt_check_for_initrd(node);
|
|
|
|
/* find compatible node with uartlite */
|
|
p = of_get_flat_dt_prop(node, "compatible", &l);
|
|
|
|
if ((strncmp(p, "xlnx,xps-uart16550", 18) != 0) &&
|
|
(strncmp(p, "xlnx,axi-uart16550", 18) != 0))
|
|
return 0;
|
|
|
|
addr = *(u32 *)of_get_flat_dt_prop(node, "reg", &l);
|
|
addr += *(u32 *)of_get_flat_dt_prop(node, "reg-offset", &l);
|
|
return be32_to_cpu(addr); /* return address */
|
|
}
|
|
|
|
/* this function is looking for early uartlite console - Microblaze specific */
|
|
int __init early_uart16550_console(void)
|
|
{
|
|
return of_scan_flat_dt(early_init_dt_scan_serial_full, NULL);
|
|
}
|
|
#endif
|
|
|
|
void __init early_init_devtree(void *params)
|
|
{
|
|
pr_debug(" -> early_init_devtree(%p)\n", params);
|
|
|
|
/* Setup flat device-tree pointer */
|
|
initial_boot_params = params;
|
|
|
|
/* Retrieve various informations from the /chosen node of the
|
|
* device-tree, including the platform type, initrd location and
|
|
* size, TCE reserve, and more ...
|
|
*/
|
|
of_scan_flat_dt(early_init_dt_scan_chosen, NULL);
|
|
|
|
/* Scan memory nodes and rebuild MEMBLOCKs */
|
|
memblock_init();
|
|
of_scan_flat_dt(early_init_dt_scan_root, NULL);
|
|
of_scan_flat_dt(early_init_dt_scan_memory, NULL);
|
|
|
|
/* Save command line for /proc/cmdline and then parse parameters */
|
|
strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
|
|
parse_early_param();
|
|
|
|
memblock_analyze();
|
|
|
|
pr_debug("Phys. mem: %lx\n", (unsigned long) memblock_phys_mem_size());
|
|
|
|
pr_debug(" <- early_init_devtree()\n");
|
|
}
|
|
|
|
#ifdef CONFIG_BLK_DEV_INITRD
|
|
void __init early_init_dt_setup_initrd_arch(unsigned long start,
|
|
unsigned long end)
|
|
{
|
|
initrd_start = (unsigned long)__va(start);
|
|
initrd_end = (unsigned long)__va(end);
|
|
initrd_below_start_ok = 1;
|
|
}
|
|
#endif
|
|
|
|
/*******
|
|
*
|
|
* New implementation of the OF "find" APIs, return a refcounted
|
|
* object, call of_node_put() when done. The device tree and list
|
|
* are protected by a rw_lock.
|
|
*
|
|
* Note that property management will need some locking as well,
|
|
* this isn't dealt with yet.
|
|
*
|
|
*******/
|
|
|
|
#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
|
|
static struct debugfs_blob_wrapper flat_dt_blob;
|
|
|
|
static int __init export_flat_device_tree(void)
|
|
{
|
|
struct dentry *d;
|
|
|
|
flat_dt_blob.data = initial_boot_params;
|
|
flat_dt_blob.size = initial_boot_params->totalsize;
|
|
|
|
d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,
|
|
of_debugfs_root, &flat_dt_blob);
|
|
if (!d)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
device_initcall(export_flat_device_tree);
|
|
#endif
|