mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-12 06:12:58 +00:00
e895a4b06f
This function can fail if the device tree runs out of space. Rather than silently booting with an incomplete device tree, allow the failure to be detected. Unfortunately this involves changing a lot of places in the code. I have not changed behvaiour to return an error where one is not currently returned, to avoid unexpected breakage. Eventually it would be nice to allow boards to register functions to be called to update the device tree. This would avoid all the many functions to do this. However it's not clear yet if this should be done using driver model or with a linker list. This work is left for later. Signed-off-by: Simon Glass <sjg@chromium.org> Acked-by: Anatolij Gustschin <agust@denx.de>
163 lines
4.2 KiB
C
163 lines
4.2 KiB
C
/*
|
|
* (C) Copyright 2007-2008
|
|
* Stefan Roese, DENX Software Engineering, sr@denx.de.
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <watchdog.h>
|
|
#include <command.h>
|
|
#include <asm/cache.h>
|
|
#include <asm/ppc4xx.h>
|
|
|
|
#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
|
|
#include <libfdt.h>
|
|
#include <fdt_support.h>
|
|
#include <asm/4xx_pcie.h>
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
int __ft_board_setup(void *blob, bd_t *bd)
|
|
{
|
|
int rc;
|
|
int i;
|
|
u32 bxcr;
|
|
u32 ranges[EBC_NUM_BANKS * 4];
|
|
u32 *p = ranges;
|
|
char ebc_path[] = "/plb/opb/ebc";
|
|
|
|
ft_cpu_setup(blob, bd);
|
|
|
|
/*
|
|
* Read 4xx EBC bus bridge registers to get mappings of the
|
|
* peripheral banks into the OPB/PLB address space
|
|
*/
|
|
for (i = 0; i < EBC_NUM_BANKS; i++) {
|
|
mtdcr(EBC0_CFGADDR, EBC_BXCR(i));
|
|
bxcr = mfdcr(EBC0_CFGDATA);
|
|
|
|
if ((bxcr & EBC_BXCR_BU_MASK) != EBC_BXCR_BU_NONE) {
|
|
*p++ = i;
|
|
*p++ = 0;
|
|
*p++ = bxcr & EBC_BXCR_BAS_MASK;
|
|
*p++ = EBC_BXCR_BANK_SIZE(bxcr);
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_FDT_FIXUP_NOR_FLASH_SIZE
|
|
/* Update reg property in all nor flash nodes too */
|
|
fdt_fixup_nor_flash_size(blob);
|
|
#endif
|
|
|
|
/* Some 405 PPC's have EBC as direct PLB child in the dts */
|
|
if (fdt_path_offset(blob, ebc_path) < 0)
|
|
strcpy(ebc_path, "/plb/ebc");
|
|
rc = fdt_find_and_setprop(blob, ebc_path, "ranges", ranges,
|
|
(p - ranges) * sizeof(u32), 1);
|
|
if (rc) {
|
|
printf("Unable to update property EBC mappings, err=%s\n",
|
|
fdt_strerror(rc));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
int ft_board_setup(void *blob, bd_t *bd)
|
|
__attribute__((weak, alias("__ft_board_setup")));
|
|
|
|
/*
|
|
* Fixup all PCIe nodes by setting the device_type property
|
|
* to "pci-endpoint" instead is "pci" for endpoint ports.
|
|
* This property will get checked later by the Linux driver
|
|
* to properly configure the PCIe port in Linux (again).
|
|
*/
|
|
void fdt_pcie_setup(void *blob)
|
|
{
|
|
const char *compat = "ibm,plb-pciex";
|
|
const char *prop = "device_type";
|
|
const char *prop_val = "pci-endpoint";
|
|
const u32 *port;
|
|
int no;
|
|
int rc;
|
|
|
|
/* Search first PCIe node */
|
|
no = fdt_node_offset_by_compatible(blob, -1, compat);
|
|
while (no != -FDT_ERR_NOTFOUND) {
|
|
port = fdt_getprop(blob, no, "port", NULL);
|
|
if (port == NULL) {
|
|
printf("WARNING: could not find port property\n");
|
|
} else {
|
|
if (is_end_point(*port)) {
|
|
rc = fdt_setprop(blob, no, prop, prop_val,
|
|
strlen(prop_val) + 1);
|
|
if (rc < 0)
|
|
printf("WARNING: could not set %s for %s: %s.\n",
|
|
prop, compat, fdt_strerror(rc));
|
|
}
|
|
}
|
|
|
|
/* Jump to next PCIe node */
|
|
no = fdt_node_offset_by_compatible(blob, no, compat);
|
|
}
|
|
}
|
|
|
|
void ft_cpu_setup(void *blob, bd_t *bd)
|
|
{
|
|
sys_info_t sys_info;
|
|
int off, ndepth = 0;
|
|
|
|
get_sys_info(&sys_info);
|
|
|
|
do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, "timebase-frequency",
|
|
bd->bi_intfreq, 1);
|
|
do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, "clock-frequency",
|
|
bd->bi_intfreq, 1);
|
|
do_fixup_by_path_u32(blob, "/plb", "clock-frequency", sys_info.freqPLB, 1);
|
|
do_fixup_by_path_u32(blob, "/plb/opb", "clock-frequency", sys_info.freqOPB, 1);
|
|
|
|
if (fdt_path_offset(blob, "/plb/opb/ebc") >= 0)
|
|
do_fixup_by_path_u32(blob, "/plb/opb/ebc", "clock-frequency",
|
|
sys_info.freqEBC, 1);
|
|
else
|
|
do_fixup_by_path_u32(blob, "/plb/ebc", "clock-frequency",
|
|
sys_info.freqEBC, 1);
|
|
|
|
fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
|
|
|
|
/*
|
|
* Fixup all UART clocks for CPU internal UARTs
|
|
* (only these UARTs are definitely clocked by gd->arch.uart_clk)
|
|
*
|
|
* These UARTs are direct childs of /plb/opb. This code
|
|
* does not touch any UARTs that are connected to the ebc.
|
|
*/
|
|
off = fdt_path_offset(blob, "/plb/opb");
|
|
while ((off = fdt_next_node(blob, off, &ndepth)) >= 0) {
|
|
/*
|
|
* process all sub nodes and stop when we are back
|
|
* at the starting depth
|
|
*/
|
|
if (ndepth <= 0)
|
|
break;
|
|
|
|
/* only update direct childs */
|
|
if ((ndepth == 1) &&
|
|
(fdt_node_check_compatible(blob, off, "ns16550") == 0))
|
|
fdt_setprop(blob, off,
|
|
"clock-frequency",
|
|
(void *)&gd->arch.uart_clk, 4);
|
|
}
|
|
|
|
/*
|
|
* Fixup all ethernet nodes
|
|
* Note: aliases in the dts are required for this
|
|
*/
|
|
fdt_fixup_ethernet(blob);
|
|
|
|
/*
|
|
* Fixup all available PCIe nodes by setting the device_type property
|
|
*/
|
|
fdt_pcie_setup(blob);
|
|
}
|
|
#endif /* CONFIG_OF_LIBFDT && CONFIG_OF_BOARD_SETUP */
|