| /* |
| * This program is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 as published |
| * by the Free Software Foundation. |
| * |
| * Copyright (C) 2010 John Crispin <blogic@openwrt.org> |
| */ |
| |
| #include <linux/export.h> |
| #include <linux/clk.h> |
| #include <linux/bootmem.h> |
| #include <linux/of_platform.h> |
| #include <linux/of_fdt.h> |
| |
| #include <asm/bootinfo.h> |
| #include <asm/time.h> |
| |
| #include <lantiq.h> |
| |
| #include "prom.h" |
| #include "clk.h" |
| |
| /* access to the ebu needs to be locked between different drivers */ |
| DEFINE_SPINLOCK(ebu_lock); |
| EXPORT_SYMBOL_GPL(ebu_lock); |
| |
| /* |
| * this struct is filled by the soc specific detection code and holds |
| * information about the specific soc type, revision and name |
| */ |
| static struct ltq_soc_info soc_info; |
| |
| const char *get_system_type(void) |
| { |
| return soc_info.sys_type; |
| } |
| |
| void prom_free_prom_memory(void) |
| { |
| } |
| |
| static void __init prom_init_cmdline(void) |
| { |
| int argc = fw_arg0; |
| char **argv = (char **) KSEG1ADDR(fw_arg1); |
| int i; |
| |
| arcs_cmdline[0] = '\0'; |
| |
| for (i = 0; i < argc; i++) { |
| char *p = (char *) KSEG1ADDR(argv[i]); |
| |
| if (CPHYSADDR(p) && *p) { |
| strlcat(arcs_cmdline, p, sizeof(arcs_cmdline)); |
| strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline)); |
| } |
| } |
| } |
| |
| void __init plat_mem_setup(void) |
| { |
| ioport_resource.start = IOPORT_RESOURCE_START; |
| ioport_resource.end = IOPORT_RESOURCE_END; |
| iomem_resource.start = IOMEM_RESOURCE_START; |
| iomem_resource.end = IOMEM_RESOURCE_END; |
| |
| set_io_port_base((unsigned long) KSEG1); |
| |
| /* |
| * Load the builtin devicetree. This causes the chosen node to be |
| * parsed resulting in our memory appearing |
| */ |
| __dt_setup_arch(&__dtb_start); |
| } |
| |
| void __init device_tree_init(void) |
| { |
| unsigned long base, size; |
| |
| if (!initial_boot_params) |
| return; |
| |
| base = virt_to_phys((void *)initial_boot_params); |
| size = be32_to_cpu(initial_boot_params->totalsize); |
| |
| /* Before we do anything, lets reserve the dt blob */ |
| reserve_bootmem(base, size, BOOTMEM_DEFAULT); |
| |
| unflatten_device_tree(); |
| } |
| |
| void __init prom_init(void) |
| { |
| /* call the soc specific detetcion code and get it to fill soc_info */ |
| ltq_soc_detect(&soc_info); |
| snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev %s", |
| soc_info.name, soc_info.rev_type); |
| soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0'; |
| pr_info("SoC: %s\n", soc_info.sys_type); |
| prom_init_cmdline(); |
| |
| #if defined(CONFIG_MIPS_MT_SMP) |
| if (register_vsmp_smp_ops()) |
| panic("failed to register_vsmp_smp_ops()"); |
| #endif |
| } |
| |
| int __init plat_of_setup(void) |
| { |
| static struct of_device_id of_ids[3]; |
| |
| if (!of_have_populated_dt()) |
| panic("device tree not present"); |
| |
| strncpy(of_ids[0].compatible, soc_info.compatible, |
| sizeof(of_ids[0].compatible)); |
| strncpy(of_ids[1].compatible, "simple-bus", |
| sizeof(of_ids[1].compatible)); |
| return of_platform_populate(NULL, of_ids, NULL, NULL); |
| } |
| |
| arch_initcall(plat_of_setup); |