mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-09-27 23:20:26 +09:00
fa18ed7658
The LS1043A rev1.1 silicon supports two types of GIC offset: 4K alignment and 64K alignment. The bit SCFG_GIC400_ALIGN[GIC_ADDR_BIT] is used to choose which offset will be used. The LS1043A rev1.0 silicon only supports the CIG offset with 4K alignment. If GIC_ADDR_BIT bit is set, 4K alignment is used, or else 64K alignment is used. 64K alignment is the default setting. Overriding the weak smp_kick_all_cpus, the new impletment is able to detect GIC offset. The default GIC offset in kernel device tree is using 4K alignment, it need to be fixed if 64K alignment is detected. Signed-off-by: Wenbin Song <wenbin.song@nxp.com> Signed-off-by: Mingkai Hu <mingkai.hu@nxp.com> Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com> Reviewed-by: York Sun <york.sun@nxp.com>
245 lines
6.1 KiB
C
245 lines
6.1 KiB
C
/*
|
|
* Copyright 2014-2015 Freescale Semiconductor, Inc.
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <efi_loader.h>
|
|
#include <libfdt.h>
|
|
#include <fdt_support.h>
|
|
#include <phy.h>
|
|
#ifdef CONFIG_FSL_LSCH3
|
|
#include <asm/arch/fdt.h>
|
|
#endif
|
|
#ifdef CONFIG_FSL_ESDHC
|
|
#include <fsl_esdhc.h>
|
|
#endif
|
|
#ifdef CONFIG_SYS_DPAA_FMAN
|
|
#include <fsl_fman.h>
|
|
#endif
|
|
#ifdef CONFIG_MP
|
|
#include <asm/arch/mp.h>
|
|
#endif
|
|
#include <fsl_sec.h>
|
|
#include <asm/arch-fsl-layerscape/soc.h>
|
|
#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
|
|
#include <asm/armv8/sec_firmware.h>
|
|
#endif
|
|
|
|
int fdt_fixup_phy_connection(void *blob, int offset, phy_interface_t phyc)
|
|
{
|
|
return fdt_setprop_string(blob, offset, "phy-connection-type",
|
|
phy_string_for_interface(phyc));
|
|
}
|
|
|
|
#ifdef CONFIG_MP
|
|
void ft_fixup_cpu(void *blob)
|
|
{
|
|
int off;
|
|
__maybe_unused u64 spin_tbl_addr = (u64)get_spin_tbl_addr();
|
|
fdt32_t *reg;
|
|
int addr_cells;
|
|
u64 val, core_id;
|
|
size_t *boot_code_size = &(__secondary_boot_code_size);
|
|
#if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT) && \
|
|
defined(CONFIG_FSL_PPA_ARMV8_PSCI)
|
|
int node;
|
|
u32 psci_ver;
|
|
|
|
/* Check the psci version to determine if the psci is supported */
|
|
psci_ver = sec_firmware_support_psci_version();
|
|
if (psci_ver == 0xffffffff) {
|
|
/* remove psci DT node */
|
|
node = fdt_path_offset(blob, "/psci");
|
|
if (node >= 0)
|
|
goto remove_psci_node;
|
|
|
|
node = fdt_node_offset_by_compatible(blob, -1, "arm,psci");
|
|
if (node >= 0)
|
|
goto remove_psci_node;
|
|
|
|
node = fdt_node_offset_by_compatible(blob, -1, "arm,psci-0.2");
|
|
if (node >= 0)
|
|
goto remove_psci_node;
|
|
|
|
node = fdt_node_offset_by_compatible(blob, -1, "arm,psci-1.0");
|
|
if (node >= 0)
|
|
goto remove_psci_node;
|
|
|
|
remove_psci_node:
|
|
if (node >= 0)
|
|
fdt_del_node(blob, node);
|
|
} else {
|
|
return;
|
|
}
|
|
#endif
|
|
off = fdt_path_offset(blob, "/cpus");
|
|
if (off < 0) {
|
|
puts("couldn't find /cpus node\n");
|
|
return;
|
|
}
|
|
of_bus_default_count_cells(blob, off, &addr_cells, NULL);
|
|
|
|
off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
|
|
while (off != -FDT_ERR_NOTFOUND) {
|
|
reg = (fdt32_t *)fdt_getprop(blob, off, "reg", 0);
|
|
if (reg) {
|
|
core_id = of_read_number(reg, addr_cells);
|
|
if (core_id == 0 || (is_core_online(core_id))) {
|
|
val = spin_tbl_addr;
|
|
val += id_to_core(core_id) *
|
|
SPIN_TABLE_ELEM_SIZE;
|
|
val = cpu_to_fdt64(val);
|
|
fdt_setprop_string(blob, off, "enable-method",
|
|
"spin-table");
|
|
fdt_setprop(blob, off, "cpu-release-addr",
|
|
&val, sizeof(val));
|
|
} else {
|
|
debug("skipping offline core\n");
|
|
}
|
|
} else {
|
|
puts("Warning: found cpu node without reg property\n");
|
|
}
|
|
off = fdt_node_offset_by_prop_value(blob, off, "device_type",
|
|
"cpu", 4);
|
|
}
|
|
|
|
fdt_add_mem_rsv(blob, (uintptr_t)&secondary_boot_code,
|
|
*boot_code_size);
|
|
#if defined(CONFIG_EFI_LOADER) && !defined(CONFIG_SPL_BUILD)
|
|
efi_add_memory_map((uintptr_t)&secondary_boot_code,
|
|
ALIGN(*boot_code_size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT,
|
|
EFI_RESERVED_MEMORY_TYPE, false);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
void fsl_fdt_disable_usb(void *blob)
|
|
{
|
|
int off;
|
|
/*
|
|
* SYSCLK is used as a reference clock for USB. When the USB
|
|
* controller is used, SYSCLK must meet the additional requirement
|
|
* of 100 MHz.
|
|
*/
|
|
if (CONFIG_SYS_CLK_FREQ != 100000000) {
|
|
off = fdt_node_offset_by_compatible(blob, -1, "snps,dwc3");
|
|
while (off != -FDT_ERR_NOTFOUND) {
|
|
fdt_status_disabled(blob, off);
|
|
off = fdt_node_offset_by_compatible(blob, off,
|
|
"snps,dwc3");
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_HAS_FEATURE_GIC64K_ALIGN
|
|
static void fdt_fixup_gic(void *blob)
|
|
{
|
|
int offset, err;
|
|
u64 reg[8];
|
|
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
|
unsigned int val;
|
|
struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
|
|
int align_64k = 0;
|
|
|
|
val = gur_in32(&gur->svr);
|
|
|
|
if (SVR_SOC_VER(val) != SVR_LS1043A) {
|
|
align_64k = 1;
|
|
} else if (SVR_REV(val) != REV1_0) {
|
|
val = scfg_in32(&scfg->gic_align) & (0x01 << GIC_ADDR_BIT);
|
|
if (!val)
|
|
align_64k = 1;
|
|
}
|
|
|
|
offset = fdt_subnode_offset(blob, 0, "interrupt-controller@1400000");
|
|
if (offset < 0) {
|
|
printf("WARNING: fdt_subnode_offset can't find node %s: %s\n",
|
|
"interrupt-controller@1400000", fdt_strerror(offset));
|
|
return;
|
|
}
|
|
|
|
/* Fixup gic node align with 64K */
|
|
if (align_64k) {
|
|
reg[0] = cpu_to_fdt64(GICD_BASE_64K);
|
|
reg[1] = cpu_to_fdt64(GICD_SIZE_64K);
|
|
reg[2] = cpu_to_fdt64(GICC_BASE_64K);
|
|
reg[3] = cpu_to_fdt64(GICC_SIZE_64K);
|
|
reg[4] = cpu_to_fdt64(GICH_BASE_64K);
|
|
reg[5] = cpu_to_fdt64(GICH_SIZE_64K);
|
|
reg[6] = cpu_to_fdt64(GICV_BASE_64K);
|
|
reg[7] = cpu_to_fdt64(GICV_SIZE_64K);
|
|
} else {
|
|
/* Fixup gic node align with default */
|
|
reg[0] = cpu_to_fdt64(GICD_BASE);
|
|
reg[1] = cpu_to_fdt64(GICD_SIZE);
|
|
reg[2] = cpu_to_fdt64(GICC_BASE);
|
|
reg[3] = cpu_to_fdt64(GICC_SIZE);
|
|
reg[4] = cpu_to_fdt64(GICH_BASE);
|
|
reg[5] = cpu_to_fdt64(GICH_SIZE);
|
|
reg[6] = cpu_to_fdt64(GICV_BASE);
|
|
reg[7] = cpu_to_fdt64(GICV_SIZE);
|
|
}
|
|
|
|
err = fdt_setprop(blob, offset, "reg", reg, sizeof(reg));
|
|
if (err < 0) {
|
|
printf("WARNING: fdt_setprop can't set %s from node %s: %s\n",
|
|
"reg", "interrupt-controller@1400000",
|
|
fdt_strerror(err));
|
|
return;
|
|
}
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
void ft_cpu_setup(void *blob, bd_t *bd)
|
|
{
|
|
#ifdef CONFIG_FSL_LSCH2
|
|
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
|
unsigned int svr = in_be32(&gur->svr);
|
|
|
|
/* delete crypto node if not on an E-processor */
|
|
if (!IS_E_PROCESSOR(svr))
|
|
fdt_fixup_crypto_node(blob, 0);
|
|
#if CONFIG_SYS_FSL_SEC_COMPAT >= 4
|
|
else {
|
|
ccsr_sec_t __iomem *sec;
|
|
|
|
sec = (void __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
|
|
fdt_fixup_crypto_node(blob, sec_in32(&sec->secvid_ms));
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef CONFIG_MP
|
|
ft_fixup_cpu(blob);
|
|
#endif
|
|
|
|
#ifdef CONFIG_SYS_NS16550
|
|
do_fixup_by_compat_u32(blob, "fsl,ns16550",
|
|
"clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
|
|
#endif
|
|
|
|
do_fixup_by_compat_u32(blob, "fixed-clock",
|
|
"clock-frequency", CONFIG_SYS_CLK_FREQ, 1);
|
|
|
|
#ifdef CONFIG_PCI
|
|
ft_pci_setup(blob, bd);
|
|
#endif
|
|
|
|
#ifdef CONFIG_FSL_ESDHC
|
|
fdt_fixup_esdhc(blob, bd);
|
|
#endif
|
|
|
|
#ifdef CONFIG_SYS_DPAA_FMAN
|
|
fdt_fixup_fman_firmware(blob);
|
|
#endif
|
|
fsl_fdt_disable_usb(blob);
|
|
|
|
#ifdef CONFIG_HAS_FEATURE_GIC64K_ALIGN
|
|
fdt_fixup_gic(blob);
|
|
#endif
|
|
}
|