/*
* Joshua Henderson, joshua.henderson@microchip.com
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
*
* This program is distributed in the hope 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.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/of_address.h>
#include <linux/of_fdt.h>
#include <linux/of_platform.h>
#include <linux/platform_data/sdhci-pic32.h>
#include <asm/fw/fw.h>
#include <asm/mips-boards/generic.h>
#include <asm/prom.h>
#include "pic32mzda.h"
const char *get_system_type(void)
{
return "PIC32MZDA";
}
static ulong get_fdtaddr(void)
{
ulong ftaddr = 0;
if (fw_passed_dtb && !fw_arg2 && !fw_arg3)
return (ulong)fw_passed_dtb;
if (__dtb_start < __dtb_end)
ftaddr = (ulong)__dtb_start;
return ftaddr;
}
void __init plat_mem_setup(void)
{
void *dtb;
dtb = (void *)get_fdtaddr();
if (!dtb) {
pr_err("pic32: no DTB found.\n");
return;
}
/*
* Load the builtin device tree. This causes the chosen node to be
* parsed resulting in our memory appearing.
*/
__dt_setup_arch(dtb);
pr_info("Found following command lines\n");
pr_info(" boot_command_line: %s\n", boot_command_line);
pr_info(" arcs_cmdline : %s\n", arcs_cmdline);
#ifdef [31mCONFIG_CMDLINE_BOOL[0m
pr_info(" builtin_cmdline : %s\n", [31mCONFIG_CMDLINE[0m);
#endif
if (dtb != __dtb_start)
strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
#ifdef [31mCONFIG_EARLY_PRINTK[0m
fw_init_early_console(-1);
#endif
pic32_config_init();
}
static __init void pic32_init_cmdline(int argc, char *argv[])
{
unsigned int count = COMMAND_LINE_SIZE - 1;
int i;
char *dst = &(arcs_cmdline[0]);
char *src;
for (i = 1; i < argc && count; ++i) {
src = argv[i];
while (*src && count) {
*dst++ = *src++;
--count;
}
*dst++ = ' ';
}
if (i > 1)
--dst;
*dst = 0;
}
void __init prom_init(void)
{
pic32_init_cmdline((int)fw_arg0, (char **)fw_arg1);
}
void __init prom_free_prom_memory(void)
{
}
void __init device_tree_init(void)
{
if (!initial_boot_params)
return;
unflatten_and_copy_device_tree();
}
static struct pic32_sdhci_platform_data sdhci_data = {
.setup_dma = pic32_set_sdhci_adma_fifo_threshold,
};
static struct of_dev_auxdata pic32_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("microchip,pic32mzda-sdhci", 0, "sdhci", &sdhci_data),
{ /* sentinel */}
};
static int __init pic32_of_prepare_platform_data(struct of_dev_auxdata *lookup)
{
struct device_node *root, *np;
struct resource res;
root = of_find_node_by_path("/");
for (; lookup->compatible; lookup++) {
np = of_find_compatible_node(NULL, NULL, lookup->compatible);
if (np) {
lookup->name = (char *)np->name;
if (lookup->phys_addr)
continue;
if (!of_address_to_resource(np, 0, &res))
lookup->phys_addr = res.start;
}
}
return 0;
}
static int __init plat_of_setup(void)
{
if (!of_have_populated_dt())
panic("Device tree not present");
pic32_of_prepare_platform_data(pic32_auxdata_lookup);
if (of_platform_default_populate(NULL, pic32_auxdata_lookup, NULL))
panic("Failed to populate DT");
return 0;
}
arch_initcall(plat_of_setup);