Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-riscv
CI: https://source.denx.de/u-boot/custodians/u-boot-riscv/-/pipelines/26259 - Initial SPL support for T-Head TH1520 SoC - Improve usability of TH1520 with mainline SPL - Support building RV32 & RV64 images - riscv: Improve jh7110 support
This commit is contained in:
@@ -77,6 +77,14 @@ config SYS_DCACHE_OFF
|
|||||||
help
|
help
|
||||||
Do not enable data cache in U-Boot.
|
Do not enable data cache in U-Boot.
|
||||||
|
|
||||||
|
config SYS_CACHE_THEAD_CMO
|
||||||
|
bool "THEAD non-standard cache operations"
|
||||||
|
depends on !SYS_DCACHE_OFF
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Support for non-standard cache management operations on SoCs based on
|
||||||
|
T-Head C906/C910 cores.
|
||||||
|
|
||||||
config SPL_SYS_DCACHE_OFF
|
config SPL_SYS_DCACHE_OFF
|
||||||
bool "Do not enable dcache in SPL"
|
bool "Do not enable dcache in SPL"
|
||||||
depends on SPL
|
depends on SPL
|
||||||
@@ -118,6 +126,7 @@ source "arch/riscv/cpu/generic/Kconfig"
|
|||||||
source "arch/riscv/cpu/jh7110/Kconfig"
|
source "arch/riscv/cpu/jh7110/Kconfig"
|
||||||
source "arch/riscv/cpu/k1/Kconfig"
|
source "arch/riscv/cpu/k1/Kconfig"
|
||||||
source "arch/riscv/cpu/k230/Kconfig"
|
source "arch/riscv/cpu/k230/Kconfig"
|
||||||
|
source "arch/riscv/cpu/th1520/Kconfig"
|
||||||
|
|
||||||
# architecture-specific options below
|
# architecture-specific options below
|
||||||
|
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
#include <asm/hwcap.h>
|
#include <asm/hwcap.h>
|
||||||
#include <asm/cpufeature.h>
|
#include <asm/cpufeature.h>
|
||||||
#include <asm/cache.h>
|
#include <asm/cache.h>
|
||||||
|
#include <asm/global_data.h>
|
||||||
#include <dm/uclass-internal.h>
|
#include <dm/uclass-internal.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/log2.h>
|
#include <linux/log2.h>
|
||||||
@@ -746,3 +747,8 @@ __weak int cleanup_before_linux(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void arch_setup_gd(gd_t *new_gd)
|
||||||
|
{
|
||||||
|
set_gd(new_gd);
|
||||||
|
}
|
||||||
|
@@ -6,6 +6,7 @@ config SOPHGO_CV1800B
|
|||||||
bool
|
bool
|
||||||
select ARCH_EARLY_INIT_R
|
select ARCH_EARLY_INIT_R
|
||||||
select SYS_CACHE_SHIFT_6
|
select SYS_CACHE_SHIFT_6
|
||||||
|
select SYS_CACHE_THEAD_CMO
|
||||||
imply CPU
|
imply CPU
|
||||||
imply CPU_RISCV
|
imply CPU_RISCV
|
||||||
imply RISCV_TIMER
|
imply RISCV_TIMER
|
||||||
|
@@ -4,4 +4,3 @@
|
|||||||
|
|
||||||
obj-y += dram.o
|
obj-y += dram.o
|
||||||
obj-y += cpu.o
|
obj-y += cpu.o
|
||||||
obj-y += cache.o
|
|
||||||
|
22
arch/riscv/cpu/th1520/Kconfig
Normal file
22
arch/riscv/cpu/th1520/Kconfig
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
|
#
|
||||||
|
# Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||||
|
# Copyright (C) 2025, Yao Zi <ziyao@disroot.org>
|
||||||
|
|
||||||
|
config THEAD_TH1520
|
||||||
|
bool
|
||||||
|
select ARCH_EARLY_INIT_R
|
||||||
|
select SYS_CACHE_SHIFT_6
|
||||||
|
select SUPPORT_SPL
|
||||||
|
select BINMAN if SPL
|
||||||
|
select SYS_CACHE_THEAD_CMO
|
||||||
|
select CLK_THEAD
|
||||||
|
imply CPU
|
||||||
|
imply CPU_RISCV
|
||||||
|
imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE)
|
||||||
|
imply RISCV_ACLINT if RISCV_MMODE
|
||||||
|
imply SPL_RISCV_ACLINT if SPL_RISCV_MMODE
|
||||||
|
imply CMD_CPU
|
||||||
|
imply SPL_CPU
|
||||||
|
imply SPL_OPENSBI
|
||||||
|
imply SPL_LOAD_FIT
|
8
arch/riscv/cpu/th1520/Makefile
Normal file
8
arch/riscv/cpu/th1520/Makefile
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0+
|
||||||
|
#
|
||||||
|
# Copyright (C) 2025, Yao Zi <ziyao@disroot.org>
|
||||||
|
|
||||||
|
obj-y += cache.o
|
||||||
|
obj-y += cpu.o
|
||||||
|
obj-y += dram.o
|
||||||
|
obj-y += spl.o
|
32
arch/riscv/cpu/th1520/cache.c
Normal file
32
arch/riscv/cpu/th1520/cache.c
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Yao Zi <ziyao@disroot.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <cpu_func.h>
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
|
||||||
|
#define CSR_MHCR 0x7c1
|
||||||
|
#define CSR_MHCR_IE BIT(0)
|
||||||
|
#define CSR_MHCR_DE BIT(1)
|
||||||
|
|
||||||
|
void icache_enable(void)
|
||||||
|
{
|
||||||
|
csr_write(CSR_MHCR, csr_read(CSR_MHCR) | CSR_MHCR_IE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dcache_enable(void)
|
||||||
|
{
|
||||||
|
csr_write(CSR_MHCR, csr_read(CSR_MHCR) | CSR_MHCR_DE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int icache_status(void)
|
||||||
|
{
|
||||||
|
return (csr_read(CSR_MHCR) & CSR_MHCR_IE) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dcache_status(void)
|
||||||
|
{
|
||||||
|
return (csr_read(CSR_MHCR) & CSR_MHCR_DE) != 0;
|
||||||
|
}
|
21
arch/riscv/cpu/th1520/cpu.c
Normal file
21
arch/riscv/cpu/th1520/cpu.c
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Yao Zi <ziyao@disroot.org>
|
||||||
|
*
|
||||||
|
* TH1520 SoC has a set of undocumented customized PMP registers that are
|
||||||
|
* configured through MMIO operation. It must be disabled before entering
|
||||||
|
* the DRAM region, or an exception will be raised.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <cpu_func.h>
|
||||||
|
|
||||||
|
#define TH1520_PMP_BASE (void *)0xffdc020000
|
||||||
|
|
||||||
|
void th1520_invalidate_pmp(void)
|
||||||
|
{
|
||||||
|
/* Invalidate the PMP configuration as in vendor U-Boot code */
|
||||||
|
writel(0x0, TH1520_PMP_BASE + 0x0);
|
||||||
|
|
||||||
|
invalidate_icache_all();
|
||||||
|
}
|
21
arch/riscv/cpu/th1520/dram.c
Normal file
21
arch/riscv/cpu/th1520/dram.c
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <fdtdec.h>
|
||||||
|
#include <init.h>
|
||||||
|
#include <asm/global_data.h>
|
||||||
|
#include <linux/sizes.h>
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
int dram_init(void)
|
||||||
|
{
|
||||||
|
return fdtdec_setup_mem_size_base();
|
||||||
|
}
|
||||||
|
|
||||||
|
int dram_init_banksize(void)
|
||||||
|
{
|
||||||
|
return fdtdec_setup_memory_banksize();
|
||||||
|
}
|
96
arch/riscv/cpu/th1520/spl.c
Normal file
96
arch/riscv/cpu/th1520/spl.c
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 Yao Zi <ziyao@disroot.org>
|
||||||
|
*/
|
||||||
|
#include <asm/arch/iopmp.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <linux/sizes.h>
|
||||||
|
#include <log.h>
|
||||||
|
#include <init.h>
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
#define TH1520_SUBSYS_CLK (void __iomem *)(0xffff011000 + 0x220)
|
||||||
|
#define TH1520_SUBSYS_CLK_VO_EN BIT(2)
|
||||||
|
#define TH1520_SUBSYS_CLK_VI_EN BIT(1)
|
||||||
|
#define TH1520_SUBSYS_CLK_DSP_EN BIT(0)
|
||||||
|
#define TH1520_SUBSYS_RST (void __iomem *)(0xffff015000 + 0x220)
|
||||||
|
#define TH1520_SUBSYS_RST_VP_N BIT(3)
|
||||||
|
#define TH1520_SUBSYS_RST_VO_N BIT(2)
|
||||||
|
#define TH1520_SUBSYS_RST_VI_N BIT(1)
|
||||||
|
#define TH1520_SUBSYS_RST_DSP_N BIT(0)
|
||||||
|
|
||||||
|
int spl_dram_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct udevice *dev;
|
||||||
|
|
||||||
|
ret = fdtdec_setup_mem_size_base();
|
||||||
|
if (ret) {
|
||||||
|
printf("failed to setup memory size and base: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DDR init */
|
||||||
|
ret = uclass_get_device(UCLASS_RAM, 0, &dev);
|
||||||
|
if (ret) {
|
||||||
|
printf("DRAM init failed: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __iomem *th1520_iopmp_regs[] = {
|
||||||
|
TH1520_IOPMP_EMMC,
|
||||||
|
TH1520_IOPMP_SDIO0,
|
||||||
|
TH1520_IOPMP_SDIO1,
|
||||||
|
TH1520_IOPMP_USB0,
|
||||||
|
TH1520_IOPMP_AO,
|
||||||
|
TH1520_IOPMP_AUD,
|
||||||
|
TH1520_IOPMP_CHIP_DBG,
|
||||||
|
TH1520_IOPMP_EIP120I,
|
||||||
|
TH1520_IOPMP_EIP120II,
|
||||||
|
TH1520_IOPMP_EIP120III,
|
||||||
|
TH1520_IOPMP_ISP0,
|
||||||
|
TH1520_IOPMP_ISP1,
|
||||||
|
TH1520_IOPMP_DW200,
|
||||||
|
TH1520_IOPMP_VIPRE,
|
||||||
|
TH1520_IOPMP_VENC,
|
||||||
|
TH1520_IOPMP_VDEC,
|
||||||
|
TH1520_IOPMP_G2D,
|
||||||
|
TH1520_IOPMP_FCE,
|
||||||
|
TH1520_IOPMP_NPU,
|
||||||
|
TH1520_IOPMP_DPU0,
|
||||||
|
TH1520_IOPMP_DPU1,
|
||||||
|
TH1520_IOPMP_GPU,
|
||||||
|
TH1520_IOPMP_GMAC1,
|
||||||
|
TH1520_IOPMP_GMAC2,
|
||||||
|
TH1520_IOPMP_DMAC,
|
||||||
|
TH1520_IOPMP_TEE_DMAC,
|
||||||
|
TH1520_IOPMP_DSP0,
|
||||||
|
TH1520_IOPMP_DSP1,
|
||||||
|
};
|
||||||
|
|
||||||
|
void harts_early_init(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set IOPMPs to the default attribute, allowing the application
|
||||||
|
* processor to access various peripherals. Subsystem clocks should be
|
||||||
|
* enabled and resets should be deasserted ahead of time, or the HART
|
||||||
|
* will hang when configuring corresponding IOPMP entries.
|
||||||
|
*/
|
||||||
|
setbits_le32(TH1520_SUBSYS_CLK, TH1520_SUBSYS_CLK_VO_EN |
|
||||||
|
TH1520_SUBSYS_CLK_VI_EN |
|
||||||
|
TH1520_SUBSYS_CLK_DSP_EN);
|
||||||
|
setbits_le32(TH1520_SUBSYS_RST, TH1520_SUBSYS_RST_VP_N |
|
||||||
|
TH1520_SUBSYS_RST_VO_N |
|
||||||
|
TH1520_SUBSYS_RST_VI_N |
|
||||||
|
TH1520_SUBSYS_RST_DSP_N);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(th1520_iopmp_regs); i++)
|
||||||
|
writel(TH1520_IOPMP_DEFAULT_ATTR, th1520_iopmp_regs[i]);
|
||||||
|
}
|
@@ -5,6 +5,12 @@
|
|||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_64BIT
|
||||||
|
#define ARCH "riscv64"
|
||||||
|
#else
|
||||||
|
#define ARCH "riscv"
|
||||||
|
|
||||||
|
#endif
|
||||||
/ {
|
/ {
|
||||||
binman: binman {
|
binman: binman {
|
||||||
multiple-images;
|
multiple-images;
|
||||||
@@ -31,12 +37,11 @@
|
|||||||
description = "U-Boot";
|
description = "U-Boot";
|
||||||
type = "standalone";
|
type = "standalone";
|
||||||
os = "U-Boot";
|
os = "U-Boot";
|
||||||
arch = "riscv";
|
arch = ARCH;
|
||||||
compression = "none";
|
compression = "none";
|
||||||
load = /bits/ 64 <CONFIG_TEXT_BASE>;
|
load = /bits/ 64 <CONFIG_TEXT_BASE>;
|
||||||
|
|
||||||
uboot_blob: u-boot-nodtb {
|
uboot_blob: u-boot-nodtb {
|
||||||
filename = "u-boot-nodtb.bin";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
@@ -44,7 +49,7 @@
|
|||||||
description = "Linux";
|
description = "Linux";
|
||||||
type = "standalone";
|
type = "standalone";
|
||||||
os = "Linux";
|
os = "Linux";
|
||||||
arch = "riscv";
|
arch = ARCH;
|
||||||
compression = "none";
|
compression = "none";
|
||||||
load = /bits/ 64 <CONFIG_TEXT_BASE>;
|
load = /bits/ 64 <CONFIG_TEXT_BASE>;
|
||||||
|
|
||||||
@@ -57,7 +62,7 @@
|
|||||||
tee {
|
tee {
|
||||||
description = "OP-TEE";
|
description = "OP-TEE";
|
||||||
type = "tee";
|
type = "tee";
|
||||||
arch = "riscv";
|
arch = ARCH;
|
||||||
compression = "none";
|
compression = "none";
|
||||||
os = "tee";
|
os = "tee";
|
||||||
load = /bits/ 64 <CONFIG_SPL_OPTEE_LOAD_ADDR>;
|
load = /bits/ 64 <CONFIG_SPL_OPTEE_LOAD_ADDR>;
|
||||||
@@ -71,7 +76,7 @@
|
|||||||
description = "OpenSBI fw_dynamic Firmware";
|
description = "OpenSBI fw_dynamic Firmware";
|
||||||
type = "firmware";
|
type = "firmware";
|
||||||
os = "opensbi";
|
os = "opensbi";
|
||||||
arch = "riscv";
|
arch = ARCH;
|
||||||
compression = "none";
|
compression = "none";
|
||||||
load = /bits/ 64 <CONFIG_SPL_OPENSBI_LOAD_ADDR>;
|
load = /bits/ 64 <CONFIG_SPL_OPENSBI_LOAD_ADDR>;
|
||||||
entry = /bits/ 64 <CONFIG_SPL_OPENSBI_LOAD_ADDR>;
|
entry = /bits/ 64 <CONFIG_SPL_OPENSBI_LOAD_ADDR>;
|
||||||
|
@@ -27,7 +27,6 @@
|
|||||||
bootph-pre-ram;
|
bootph-pre-ram;
|
||||||
reg-offset = <0>;
|
reg-offset = <0>;
|
||||||
current-speed = <115200>;
|
current-speed = <115200>;
|
||||||
clock-frequency = <24000000>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
&mmc0 {
|
&mmc0 {
|
||||||
|
@@ -6,46 +6,6 @@
|
|||||||
#include <dt-bindings/reset/starfive,jh7110-crg.h>
|
#include <dt-bindings/reset/starfive,jh7110-crg.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
cpus: cpus {
|
|
||||||
bootph-pre-ram;
|
|
||||||
|
|
||||||
S7_0: cpu@0 {
|
|
||||||
bootph-pre-ram;
|
|
||||||
status = "okay";
|
|
||||||
cpu0_intc: interrupt-controller {
|
|
||||||
bootph-pre-ram;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
U74_1: cpu@1 {
|
|
||||||
bootph-pre-ram;
|
|
||||||
cpu1_intc: interrupt-controller {
|
|
||||||
bootph-pre-ram;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
U74_2: cpu@2 {
|
|
||||||
bootph-pre-ram;
|
|
||||||
cpu2_intc: interrupt-controller {
|
|
||||||
bootph-pre-ram;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
U74_3: cpu@3 {
|
|
||||||
bootph-pre-ram;
|
|
||||||
cpu3_intc: interrupt-controller {
|
|
||||||
bootph-pre-ram;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
U74_4: cpu@4 {
|
|
||||||
bootph-pre-ram;
|
|
||||||
cpu4_intc: interrupt-controller {
|
|
||||||
bootph-pre-ram;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
timer {
|
timer {
|
||||||
compatible = "riscv,timer";
|
compatible = "riscv,timer";
|
||||||
interrupts-extended = <&cpu0_intc 5>,
|
interrupts-extended = <&cpu0_intc 5>,
|
||||||
@@ -58,10 +18,6 @@
|
|||||||
soc {
|
soc {
|
||||||
bootph-pre-ram;
|
bootph-pre-ram;
|
||||||
|
|
||||||
clint: timer@2000000 {
|
|
||||||
bootph-pre-ram;
|
|
||||||
};
|
|
||||||
|
|
||||||
dmc: dmc@15700000 {
|
dmc: dmc@15700000 {
|
||||||
bootph-pre-ram;
|
bootph-pre-ram;
|
||||||
compatible = "starfive,jh7110-dmc";
|
compatible = "starfive,jh7110-dmc";
|
||||||
@@ -78,6 +34,34 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&clint {
|
||||||
|
bootph-pre-ram;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cpu0_intc {
|
||||||
|
bootph-pre-ram;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cpu1_intc {
|
||||||
|
bootph-pre-ram;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cpu2_intc {
|
||||||
|
bootph-pre-ram;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cpu3_intc {
|
||||||
|
bootph-pre-ram;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cpu4_intc {
|
||||||
|
bootph-pre-ram;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cpus {
|
||||||
|
bootph-pre-ram;
|
||||||
|
};
|
||||||
|
|
||||||
&osc {
|
&osc {
|
||||||
bootph-pre-ram;
|
bootph-pre-ram;
|
||||||
};
|
};
|
||||||
@@ -107,6 +91,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
&syscrg {
|
&syscrg {
|
||||||
|
assigned-clock-rates = <0>; /* cpufreq not implemented, use defaults */
|
||||||
bootph-pre-ram;
|
bootph-pre-ram;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
memory@0 {
|
memory@0 {
|
||||||
device_type = "memory";
|
device_type = "memory";
|
||||||
reg = <0x0 0x00000000 0x2 0x00000000>;
|
reg = <0x0 0x00000000 0x2 0x00000000>;
|
||||||
|
bootph-pre-ram;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -25,14 +26,6 @@
|
|||||||
clock-frequency = <32768>;
|
clock-frequency = <32768>;
|
||||||
};
|
};
|
||||||
|
|
||||||
&apb_clk {
|
|
||||||
clock-frequency = <62500000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
&uart_sclk {
|
|
||||||
clock-frequency = <100000000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
&emmc {
|
&emmc {
|
||||||
bus-width = <8>;
|
bus-width = <8>;
|
||||||
max-frequency = <198000000>;
|
max-frequency = <198000000>;
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "th1520-lichee-module-4a.dtsi"
|
#include "th1520-lichee-module-4a.dtsi"
|
||||||
|
#include "thead-th1520-binman.dtsi"
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
model = "Sipeed Lichee Pi 4A";
|
model = "Sipeed Lichee Pi 4A";
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
* Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org>
|
* Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/clock/thead,th1520-clk-ap.h>
|
||||||
#include <dt-bindings/interrupt-controller/irq.h>
|
#include <dt-bindings/interrupt-controller/irq.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
@@ -14,6 +15,7 @@
|
|||||||
cpus: cpus {
|
cpus: cpus {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
bootph-pre-ram;
|
||||||
timebase-frequency = <3000000>;
|
timebase-frequency = <3000000>;
|
||||||
|
|
||||||
c910_0: cpu@0 {
|
c910_0: cpu@0 {
|
||||||
@@ -21,6 +23,7 @@
|
|||||||
device_type = "cpu";
|
device_type = "cpu";
|
||||||
riscv,isa = "rv64imafdc";
|
riscv,isa = "rv64imafdc";
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
|
bootph-pre-ram;
|
||||||
i-cache-block-size = <64>;
|
i-cache-block-size = <64>;
|
||||||
i-cache-size = <65536>;
|
i-cache-size = <65536>;
|
||||||
i-cache-sets = <512>;
|
i-cache-sets = <512>;
|
||||||
@@ -42,6 +45,7 @@
|
|||||||
device_type = "cpu";
|
device_type = "cpu";
|
||||||
riscv,isa = "rv64imafdc";
|
riscv,isa = "rv64imafdc";
|
||||||
reg = <1>;
|
reg = <1>;
|
||||||
|
bootph-pre-ram;
|
||||||
i-cache-block-size = <64>;
|
i-cache-block-size = <64>;
|
||||||
i-cache-size = <65536>;
|
i-cache-size = <65536>;
|
||||||
i-cache-sets = <512>;
|
i-cache-sets = <512>;
|
||||||
@@ -63,6 +67,7 @@
|
|||||||
device_type = "cpu";
|
device_type = "cpu";
|
||||||
riscv,isa = "rv64imafdc";
|
riscv,isa = "rv64imafdc";
|
||||||
reg = <2>;
|
reg = <2>;
|
||||||
|
bootph-pre-ram;
|
||||||
i-cache-block-size = <64>;
|
i-cache-block-size = <64>;
|
||||||
i-cache-size = <65536>;
|
i-cache-size = <65536>;
|
||||||
i-cache-sets = <512>;
|
i-cache-sets = <512>;
|
||||||
@@ -84,6 +89,7 @@
|
|||||||
device_type = "cpu";
|
device_type = "cpu";
|
||||||
riscv,isa = "rv64imafdc";
|
riscv,isa = "rv64imafdc";
|
||||||
reg = <3>;
|
reg = <3>;
|
||||||
|
bootph-pre-ram;
|
||||||
i-cache-block-size = <64>;
|
i-cache-block-size = <64>;
|
||||||
i-cache-size = <65536>;
|
i-cache-size = <65536>;
|
||||||
i-cache-sets = <512>;
|
i-cache-sets = <512>;
|
||||||
@@ -122,25 +128,6 @@
|
|||||||
#clock-cells = <0>;
|
#clock-cells = <0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
apb_clk: apb-clk-clock {
|
|
||||||
compatible = "fixed-clock";
|
|
||||||
clock-output-names = "apb_clk";
|
|
||||||
#clock-cells = <0>;
|
|
||||||
};
|
|
||||||
|
|
||||||
uart_sclk: uart-sclk-clock {
|
|
||||||
compatible = "fixed-clock";
|
|
||||||
clock-output-names = "uart_sclk";
|
|
||||||
#clock-cells = <0>;
|
|
||||||
};
|
|
||||||
|
|
||||||
sdhci_clk: sdhci-clock {
|
|
||||||
compatible = "fixed-clock";
|
|
||||||
clock-frequency = <198000000>;
|
|
||||||
clock-output-names = "sdhci_clk";
|
|
||||||
#clock-cells = <0>;
|
|
||||||
};
|
|
||||||
|
|
||||||
soc {
|
soc {
|
||||||
compatible = "simple-bus";
|
compatible = "simple-bus";
|
||||||
interrupt-parent = <&plic>;
|
interrupt-parent = <&plic>;
|
||||||
@@ -173,8 +160,10 @@
|
|||||||
uart0: serial@ffe7014000 {
|
uart0: serial@ffe7014000 {
|
||||||
compatible = "snps,dw-apb-uart";
|
compatible = "snps,dw-apb-uart";
|
||||||
reg = <0xff 0xe7014000 0x0 0x100>;
|
reg = <0xff 0xe7014000 0x0 0x100>;
|
||||||
|
bootph-pre-ram;
|
||||||
interrupts = <36 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <36 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&uart_sclk>;
|
clocks = <&clk CLK_UART_SCLK>, <&clk CLK_UART0_PCLK>;
|
||||||
|
clock-names = "buadclk", "apb_pclk";
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
reg-io-width = <4>;
|
reg-io-width = <4>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@@ -184,7 +173,7 @@
|
|||||||
compatible = "thead,th1520-dwcmshc";
|
compatible = "thead,th1520-dwcmshc";
|
||||||
reg = <0xff 0xe7080000 0x0 0x10000>;
|
reg = <0xff 0xe7080000 0x0 0x10000>;
|
||||||
interrupts = <62 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <62 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&sdhci_clk>;
|
clocks = <&clk CLK_EMMC_SDIO>;
|
||||||
clock-names = "core";
|
clock-names = "core";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
@@ -193,7 +182,7 @@
|
|||||||
compatible = "thead,th1520-dwcmshc";
|
compatible = "thead,th1520-dwcmshc";
|
||||||
reg = <0xff 0xe7090000 0x0 0x10000>;
|
reg = <0xff 0xe7090000 0x0 0x10000>;
|
||||||
interrupts = <64 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <64 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&sdhci_clk>;
|
clocks = <&clk CLK_EMMC_SDIO>;
|
||||||
clock-names = "core";
|
clock-names = "core";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
@@ -202,7 +191,7 @@
|
|||||||
compatible = "thead,th1520-dwcmshc";
|
compatible = "thead,th1520-dwcmshc";
|
||||||
reg = <0xff 0xe70a0000 0x0 0x10000>;
|
reg = <0xff 0xe70a0000 0x0 0x10000>;
|
||||||
interrupts = <71 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <71 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&sdhci_clk>;
|
clocks = <&clk CLK_EMMC_SDIO>;
|
||||||
clock-names = "core";
|
clock-names = "core";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
@@ -211,7 +200,8 @@
|
|||||||
compatible = "snps,dw-apb-uart";
|
compatible = "snps,dw-apb-uart";
|
||||||
reg = <0xff 0xe7f00000 0x0 0x100>;
|
reg = <0xff 0xe7f00000 0x0 0x100>;
|
||||||
interrupts = <37 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <37 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&uart_sclk>;
|
clocks = <&clk CLK_UART_SCLK>, <&clk CLK_UART1_PCLK>;
|
||||||
|
clock-names = "buadclk", "apb_pclk";
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
reg-io-width = <4>;
|
reg-io-width = <4>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@@ -221,7 +211,8 @@
|
|||||||
compatible = "snps,dw-apb-uart";
|
compatible = "snps,dw-apb-uart";
|
||||||
reg = <0xff 0xe7f04000 0x0 0x100>;
|
reg = <0xff 0xe7f04000 0x0 0x100>;
|
||||||
interrupts = <39 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <39 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&uart_sclk>;
|
clocks = <&clk CLK_UART_SCLK>, <&clk CLK_UART3_PCLK>;
|
||||||
|
clock-names = "buadclk", "apb_pclk";
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
reg-io-width = <4>;
|
reg-io-width = <4>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@@ -230,6 +221,8 @@
|
|||||||
gpio2: gpio@ffe7f34000 {
|
gpio2: gpio@ffe7f34000 {
|
||||||
compatible = "snps,dw-apb-gpio";
|
compatible = "snps,dw-apb-gpio";
|
||||||
reg = <0xff 0xe7f34000 0x0 0x1000>;
|
reg = <0xff 0xe7f34000 0x0 0x1000>;
|
||||||
|
clocks = <&clk CLK_GPIO2>;
|
||||||
|
clock-names = "bus";
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
@@ -248,6 +241,8 @@
|
|||||||
gpio3: gpio@ffe7f38000 {
|
gpio3: gpio@ffe7f38000 {
|
||||||
compatible = "snps,dw-apb-gpio";
|
compatible = "snps,dw-apb-gpio";
|
||||||
reg = <0xff 0xe7f38000 0x0 0x1000>;
|
reg = <0xff 0xe7f38000 0x0 0x1000>;
|
||||||
|
clocks = <&clk CLK_GPIO3>;
|
||||||
|
clock-names = "bus";
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
@@ -266,6 +261,8 @@
|
|||||||
gpio0: gpio@ffec005000 {
|
gpio0: gpio@ffec005000 {
|
||||||
compatible = "snps,dw-apb-gpio";
|
compatible = "snps,dw-apb-gpio";
|
||||||
reg = <0xff 0xec005000 0x0 0x1000>;
|
reg = <0xff 0xec005000 0x0 0x1000>;
|
||||||
|
clocks = <&clk CLK_GPIO0>;
|
||||||
|
clock-names = "bus";
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
@@ -284,6 +281,8 @@
|
|||||||
gpio1: gpio@ffec006000 {
|
gpio1: gpio@ffec006000 {
|
||||||
compatible = "snps,dw-apb-gpio";
|
compatible = "snps,dw-apb-gpio";
|
||||||
reg = <0xff 0xec006000 0x0 0x1000>;
|
reg = <0xff 0xec006000 0x0 0x1000>;
|
||||||
|
clocks = <&clk CLK_GPIO1>;
|
||||||
|
clock-names = "bus";
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
||||||
@@ -303,16 +302,24 @@
|
|||||||
compatible = "snps,dw-apb-uart";
|
compatible = "snps,dw-apb-uart";
|
||||||
reg = <0xff 0xec010000 0x0 0x4000>;
|
reg = <0xff 0xec010000 0x0 0x4000>;
|
||||||
interrupts = <38 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <38 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&uart_sclk>;
|
clocks = <&clk CLK_UART_SCLK>, <&clk CLK_UART2_PCLK>;
|
||||||
|
clock-names = "buadclk", "apb_pclk";
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
reg-io-width = <4>;
|
reg-io-width = <4>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
clk: clock-controller@ffef010000 {
|
||||||
|
compatible = "thead,th1520-clk-ap";
|
||||||
|
reg = <0xff 0xef010000 0x0 0x1000>;
|
||||||
|
clocks = <&osc>;
|
||||||
|
#clock-cells = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
timer0: timer@ffefc32000 {
|
timer0: timer@ffefc32000 {
|
||||||
compatible = "snps,dw-apb-timer";
|
compatible = "snps,dw-apb-timer";
|
||||||
reg = <0xff 0xefc32000 0x0 0x14>;
|
reg = <0xff 0xefc32000 0x0 0x14>;
|
||||||
clocks = <&apb_clk>;
|
clocks = <&clk CLK_PERI_APB_PCLK>;
|
||||||
clock-names = "timer";
|
clock-names = "timer";
|
||||||
interrupts = <16 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <16 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@@ -321,7 +328,7 @@
|
|||||||
timer1: timer@ffefc32014 {
|
timer1: timer@ffefc32014 {
|
||||||
compatible = "snps,dw-apb-timer";
|
compatible = "snps,dw-apb-timer";
|
||||||
reg = <0xff 0xefc32014 0x0 0x14>;
|
reg = <0xff 0xefc32014 0x0 0x14>;
|
||||||
clocks = <&apb_clk>;
|
clocks = <&clk CLK_PERI_APB_PCLK>;
|
||||||
clock-names = "timer";
|
clock-names = "timer";
|
||||||
interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@@ -330,7 +337,7 @@
|
|||||||
timer2: timer@ffefc32028 {
|
timer2: timer@ffefc32028 {
|
||||||
compatible = "snps,dw-apb-timer";
|
compatible = "snps,dw-apb-timer";
|
||||||
reg = <0xff 0xefc32028 0x0 0x14>;
|
reg = <0xff 0xefc32028 0x0 0x14>;
|
||||||
clocks = <&apb_clk>;
|
clocks = <&clk CLK_PERI_APB_PCLK>;
|
||||||
clock-names = "timer";
|
clock-names = "timer";
|
||||||
interrupts = <18 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <18 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@@ -339,7 +346,7 @@
|
|||||||
timer3: timer@ffefc3203c {
|
timer3: timer@ffefc3203c {
|
||||||
compatible = "snps,dw-apb-timer";
|
compatible = "snps,dw-apb-timer";
|
||||||
reg = <0xff 0xefc3203c 0x0 0x14>;
|
reg = <0xff 0xefc3203c 0x0 0x14>;
|
||||||
clocks = <&apb_clk>;
|
clocks = <&clk CLK_PERI_APB_PCLK>;
|
||||||
clock-names = "timer";
|
clock-names = "timer";
|
||||||
interrupts = <19 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <19 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@@ -349,7 +356,8 @@
|
|||||||
compatible = "snps,dw-apb-uart";
|
compatible = "snps,dw-apb-uart";
|
||||||
reg = <0xff 0xf7f08000 0x0 0x4000>;
|
reg = <0xff 0xf7f08000 0x0 0x4000>;
|
||||||
interrupts = <40 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <40 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&uart_sclk>;
|
clocks = <&clk CLK_UART_SCLK>, <&clk CLK_UART4_PCLK>;
|
||||||
|
clock-names = "buadclk", "apb_pclk";
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
reg-io-width = <4>;
|
reg-io-width = <4>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@@ -359,16 +367,27 @@
|
|||||||
compatible = "snps,dw-apb-uart";
|
compatible = "snps,dw-apb-uart";
|
||||||
reg = <0xff 0xf7f0c000 0x0 0x4000>;
|
reg = <0xff 0xf7f0c000 0x0 0x4000>;
|
||||||
interrupts = <41 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <41 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&uart_sclk>;
|
clocks = <&clk CLK_UART_SCLK>, <&clk CLK_UART5_PCLK>;
|
||||||
|
clock-names = "buadclk", "apb_pclk";
|
||||||
reg-shift = <2>;
|
reg-shift = <2>;
|
||||||
reg-io-width = <4>;
|
reg-io-width = <4>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ddrc: ddrc@fffd000000 {
|
||||||
|
compatible = "thead,th1520-ddrc";
|
||||||
|
reg = <0xff 0xfd000000 0x0 0x1000000>,
|
||||||
|
<0xff 0xfe000000 0x0 0x1000000>,
|
||||||
|
<0xff 0xff000000 0x0 0x4000>,
|
||||||
|
<0xff 0xff005000 0x0 0x1000>;
|
||||||
|
reg-names = "phy-0", "phy-1", "ctrl", "sys";
|
||||||
|
bootph-pre-ram;
|
||||||
|
};
|
||||||
|
|
||||||
timer4: timer@ffffc33000 {
|
timer4: timer@ffffc33000 {
|
||||||
compatible = "snps,dw-apb-timer";
|
compatible = "snps,dw-apb-timer";
|
||||||
reg = <0xff 0xffc33000 0x0 0x14>;
|
reg = <0xff 0xffc33000 0x0 0x14>;
|
||||||
clocks = <&apb_clk>;
|
clocks = <&clk CLK_PERI_APB_PCLK>;
|
||||||
clock-names = "timer";
|
clock-names = "timer";
|
||||||
interrupts = <20 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <20 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@@ -377,7 +396,7 @@
|
|||||||
timer5: timer@ffffc33014 {
|
timer5: timer@ffffc33014 {
|
||||||
compatible = "snps,dw-apb-timer";
|
compatible = "snps,dw-apb-timer";
|
||||||
reg = <0xff 0xffc33014 0x0 0x14>;
|
reg = <0xff 0xffc33014 0x0 0x14>;
|
||||||
clocks = <&apb_clk>;
|
clocks = <&clk CLK_PERI_APB_PCLK>;
|
||||||
clock-names = "timer";
|
clock-names = "timer";
|
||||||
interrupts = <21 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <21 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@@ -386,7 +405,7 @@
|
|||||||
timer6: timer@ffffc33028 {
|
timer6: timer@ffffc33028 {
|
||||||
compatible = "snps,dw-apb-timer";
|
compatible = "snps,dw-apb-timer";
|
||||||
reg = <0xff 0xffc33028 0x0 0x14>;
|
reg = <0xff 0xffc33028 0x0 0x14>;
|
||||||
clocks = <&apb_clk>;
|
clocks = <&clk CLK_PERI_APB_PCLK>;
|
||||||
clock-names = "timer";
|
clock-names = "timer";
|
||||||
interrupts = <22 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <22 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
@@ -395,7 +414,7 @@
|
|||||||
timer7: timer@ffffc3303c {
|
timer7: timer@ffffc3303c {
|
||||||
compatible = "snps,dw-apb-timer";
|
compatible = "snps,dw-apb-timer";
|
||||||
reg = <0xff 0xffc3303c 0x0 0x14>;
|
reg = <0xff 0xffc3303c 0x0 0x14>;
|
||||||
clocks = <&apb_clk>;
|
clocks = <&clk CLK_PERI_APB_PCLK>;
|
||||||
clock-names = "timer";
|
clock-names = "timer";
|
||||||
interrupts = <23 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <23 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
|
55
arch/riscv/dts/thead-th1520-binman.dtsi
Normal file
55
arch/riscv/dts/thead-th1520-binman.dtsi
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Yao Zi <ziyao@disroot.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
binman: binman {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&binman {
|
||||||
|
filename = "u-boot-with-spl.bin";
|
||||||
|
|
||||||
|
u-boot-spl {
|
||||||
|
};
|
||||||
|
|
||||||
|
ddr-fw {
|
||||||
|
filename = "th1520-ddr-firmware.bin";
|
||||||
|
type = "blob-ext";
|
||||||
|
};
|
||||||
|
|
||||||
|
fit {
|
||||||
|
offset = <CONFIG_SPL_PAD_TO>;
|
||||||
|
|
||||||
|
description = "Configuration to load M-mode U-Boot";
|
||||||
|
|
||||||
|
#address-cells = <2>;
|
||||||
|
fit,fdt-list = "of-list";
|
||||||
|
|
||||||
|
images {
|
||||||
|
uboot {
|
||||||
|
description = "U-Boot";
|
||||||
|
type = "standalone";
|
||||||
|
os = "U-boot";
|
||||||
|
arch = "riscv";
|
||||||
|
compression = "none";
|
||||||
|
load = /bits/ 64 <CONFIG_TEXT_BASE>;
|
||||||
|
|
||||||
|
uboot_blob: u-boot {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
default = "conf-th1520-lichee-pi-4a";
|
||||||
|
|
||||||
|
conf-th1520-lichee-pi-4a {
|
||||||
|
description = "th1520-lichee-pi-4a";
|
||||||
|
loadables = "uboot";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
9
arch/riscv/include/asm/arch-th1520/cpu.h
Normal file
9
arch/riscv/include/asm/arch-th1520/cpu.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Yao Zi <ziyao@disroot.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ASM_TH1520_CPU_H_
|
||||||
|
#define _ASM_TH1520_CPU_H_
|
||||||
|
void th1520_invalidate_pmp(void);
|
||||||
|
#endif /* _ASM_TH1520_CPU_H_ */
|
42
arch/riscv/include/asm/arch-th1520/iopmp.h
Normal file
42
arch/riscv/include/asm/arch-th1520/iopmp.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 Yao Zi <ziyao@disroot.org>
|
||||||
|
*/
|
||||||
|
#ifndef _ASM_ARCH_TH1520_IOPMP_H_
|
||||||
|
#define _ASM_ARCH_TH1520_IOPMP_H_
|
||||||
|
|
||||||
|
#define TH1520_IOPMP_EMMC (void *)0xfffc0280c0
|
||||||
|
#define TH1520_IOPMP_SDIO0 (void *)0xfffc0290c0
|
||||||
|
#define TH1520_IOPMP_SDIO1 (void *)0xfffc02a0c0
|
||||||
|
#define TH1520_IOPMP_USB0 (void *)0xfffc02e0c0
|
||||||
|
#define TH1520_IOPMP_AO (void *)0xffffc210c0
|
||||||
|
#define TH1520_IOPMP_AUD (void *)0xffffc220c0
|
||||||
|
#define TH1520_IOPMP_CHIP_DBG (void *)0xffffc370c0
|
||||||
|
#define TH1520_IOPMP_EIP120I (void *)0xffff2200c0
|
||||||
|
#define TH1520_IOPMP_EIP120II (void *)0xffff2300c0
|
||||||
|
#define TH1520_IOPMP_EIP120III (void *)0xffff2400c0
|
||||||
|
#define TH1520_IOPMP_ISP0 (void *)0xfff40800c0
|
||||||
|
#define TH1520_IOPMP_ISP1 (void *)0xfff40810c0
|
||||||
|
#define TH1520_IOPMP_DW200 (void *)0xfff40820c0
|
||||||
|
#define TH1520_IOPMP_VIPRE (void *)0xfff40830c0
|
||||||
|
#define TH1520_IOPMP_VENC (void *)0xfffcc600c0
|
||||||
|
#define TH1520_IOPMP_VDEC (void *)0xfffcc610c0
|
||||||
|
#define TH1520_IOPMP_G2D (void *)0xfffcc620c0
|
||||||
|
#define TH1520_IOPMP_FCE (void *)0xfffcc630c0
|
||||||
|
#define TH1520_IOPMP_NPU (void *)0xffff01c0c0
|
||||||
|
#define TH1520_IOPMP_DPU0 (void *)0xffff5200c0
|
||||||
|
#define TH1520_IOPMP_DPU1 (void *)0xffff5210c0
|
||||||
|
#define TH1520_IOPMP_GPU (void *)0xffff5220c0
|
||||||
|
#define TH1520_IOPMP_GMAC1 (void *)0xfffc0010c0
|
||||||
|
#define TH1520_IOPMP_GMAC2 (void *)0xfffc0020c0
|
||||||
|
#define TH1520_IOPMP_DMAC (void *)0xffffc200c0
|
||||||
|
#define TH1520_IOPMP_TEE_DMAC (void *)0xffff2500c0
|
||||||
|
#define TH1520_IOPMP_DSP0 (void *)0xffff0580c0
|
||||||
|
#define TH1520_IOPMP_DSP1 (void *)0xffff0590c0
|
||||||
|
#define TH1520_IOPMP_AUDIO (void *)0xffffc220c0
|
||||||
|
#define TH1520_IOPMP_AUDIO0 (void *)0xffcb02e0c0
|
||||||
|
#define TH1520_IOPMP_AUDIO1 (void *)0xffcb02f0c0
|
||||||
|
|
||||||
|
#define TH1520_IOPMP_DEFAULT_ATTR 0xffffffff
|
||||||
|
|
||||||
|
#endif // _ASM_ARCH_TH1520_IOPMP_H_
|
10
arch/riscv/include/asm/arch-th1520/spl.h
Normal file
10
arch/riscv/include/asm/arch-th1520/spl.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 Yao Zi <ziyao@disroot.org>
|
||||||
|
*/
|
||||||
|
#ifndef _ASM_ARCH_TH1520_SPL_H_
|
||||||
|
#define _ASM_ARCH_TH1520_SPL_H_
|
||||||
|
|
||||||
|
void spl_dram_init(void);
|
||||||
|
|
||||||
|
#endif // _ASM_ARCH_TH1520_SPL_H_
|
@@ -14,6 +14,7 @@
|
|||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
#include <asm/u-boot.h>
|
#include <asm/u-boot.h>
|
||||||
#include <compiler.h>
|
#include <compiler.h>
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
/* Architecture-specific global data */
|
/* Architecture-specific global data */
|
||||||
struct arch_global_data {
|
struct arch_global_data {
|
||||||
@@ -47,8 +48,26 @@ struct arch_global_data {
|
|||||||
|
|
||||||
#include <asm-generic/global_data.h>
|
#include <asm-generic/global_data.h>
|
||||||
|
|
||||||
|
#if defined(__clang__) || CONFIG_IS_ENABLED(LTO)
|
||||||
|
|
||||||
|
#define DECLARE_GLOBAL_DATA_PTR
|
||||||
|
#define gd get_gd()
|
||||||
|
|
||||||
|
static inline gd_t *get_gd(void)
|
||||||
|
{
|
||||||
|
gd_t *gd_ptr;
|
||||||
|
|
||||||
|
__asm__ volatile ("mv %0, gp\n" : "=r" (gd_ptr));
|
||||||
|
|
||||||
|
return gd_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
#define DECLARE_GLOBAL_DATA_PTR register gd_t *gd asm ("gp")
|
#define DECLARE_GLOBAL_DATA_PTR register gd_t *gd asm ("gp")
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline void set_gd(volatile gd_t *gd_ptr)
|
static inline void set_gd(volatile gd_t *gd_ptr)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_64BIT
|
#ifdef CONFIG_64BIT
|
||||||
|
@@ -5,8 +5,8 @@
|
|||||||
* Ported from linux insn-def.h.
|
* Ported from linux insn-def.h.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _ASM_RISCV_BARRIER_H
|
#ifndef _ASM_RISCV_INSN_DEF_H
|
||||||
#define _ASM_RISCV_BARRIER_H
|
#define _ASM_RISCV_INSN_DEF_H
|
||||||
|
|
||||||
#define INSN_I_SIMM12_SHIFT 20
|
#define INSN_I_SIMM12_SHIFT 20
|
||||||
#define INSN_I_RS1_SHIFT 15
|
#define INSN_I_RS1_SHIFT 15
|
||||||
@@ -36,4 +36,4 @@
|
|||||||
__INSN_I(RV_##opcode, RV_##func3, RV_##rd, \
|
__INSN_I(RV_##opcode, RV_##func3, RV_##rd, \
|
||||||
RV_##rs1, RV_##simm12)
|
RV_##rs1, RV_##simm12)
|
||||||
|
|
||||||
#endif /* _ASM_RISCV_BARRIER_H */
|
#endif /* _ASM_RISCV_INSN_DEF_H */
|
||||||
|
@@ -23,6 +23,10 @@
|
|||||||
#include <asm/u-boot-riscv.h>
|
#include <asm/u-boot-riscv.h>
|
||||||
|
|
||||||
/* For image.h:image_check_target_arch() */
|
/* For image.h:image_check_target_arch() */
|
||||||
|
#ifdef CONFIG_64BIT
|
||||||
|
#define IH_ARCH_DEFAULT IH_ARCH_RISCV64
|
||||||
|
#else
|
||||||
#define IH_ARCH_DEFAULT IH_ARCH_RISCV
|
#define IH_ARCH_DEFAULT IH_ARCH_RISCV
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _U_BOOT_H_ */
|
#endif /* _U_BOOT_H_ */
|
||||||
|
@@ -11,6 +11,7 @@ obj-$(CONFIG_CMD_BOOTI) += bootm.o image.o
|
|||||||
obj-$(CONFIG_CMD_GO) += boot.o
|
obj-$(CONFIG_CMD_GO) += boot.o
|
||||||
obj-y += cache.o
|
obj-y += cache.o
|
||||||
obj-$(CONFIG_SIFIVE_CACHE) += sifive_cache.o
|
obj-$(CONFIG_SIFIVE_CACHE) += sifive_cache.o
|
||||||
|
obj-$(CONFIG_SYS_CACHE_THEAD_CMO) += thead_cmo.o
|
||||||
ifeq ($(CONFIG_$(PHASE_)RISCV_MMODE),y)
|
ifeq ($(CONFIG_$(PHASE_)RISCV_MMODE),y)
|
||||||
obj-$(CONFIG_$(PHASE_)RISCV_ACLINT) += aclint_ipi.o
|
obj-$(CONFIG_$(PHASE_)RISCV_ACLINT) += aclint_ipi.o
|
||||||
obj-$(CONFIG_ANDES_PLICSW) += andes_plicsw.o
|
obj-$(CONFIG_ANDES_PLICSW) += andes_plicsw.o
|
||||||
|
@@ -90,6 +90,10 @@ static void boot_jump_linux(struct bootm_headers *images, int flag)
|
|||||||
announce_and_cleanup(fake);
|
announce_and_cleanup(fake);
|
||||||
|
|
||||||
if (!fake) {
|
if (!fake) {
|
||||||
|
if (images->os.arch != IH_ARCH_DEFAULT) {
|
||||||
|
printf("Image arch not compatible with host arch.\n");
|
||||||
|
hang();
|
||||||
|
}
|
||||||
if (CONFIG_IS_ENABLED(OF_LIBFDT) && images->ft_len) {
|
if (CONFIG_IS_ENABLED(OF_LIBFDT) && images->ft_len) {
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
ret = smp_call_function(images->ep,
|
ret = smp_call_function(images->ep,
|
||||||
|
@@ -11,7 +11,7 @@ config SYS_VENDOR
|
|||||||
default "thead"
|
default "thead"
|
||||||
|
|
||||||
config SYS_CPU
|
config SYS_CPU
|
||||||
default "generic"
|
default "th1520"
|
||||||
|
|
||||||
config SYS_CONFIG_NAME
|
config SYS_CONFIG_NAME
|
||||||
default "th1520_lpi4a"
|
default "th1520_lpi4a"
|
||||||
@@ -22,7 +22,7 @@ config TEXT_BASE
|
|||||||
default 0x01c00000 if RISCV_SMODE
|
default 0x01c00000 if RISCV_SMODE
|
||||||
|
|
||||||
config SPL_TEXT_BASE
|
config SPL_TEXT_BASE
|
||||||
default 0x08000000
|
default 0xffe0000000
|
||||||
|
|
||||||
config SPL_OPENSBI_LOAD_ADDR
|
config SPL_OPENSBI_LOAD_ADDR
|
||||||
default 0x80000000
|
default 0x80000000
|
||||||
@@ -30,6 +30,7 @@ config SPL_OPENSBI_LOAD_ADDR
|
|||||||
config BOARD_SPECIFIC_OPTIONS
|
config BOARD_SPECIFIC_OPTIONS
|
||||||
def_bool y
|
def_bool y
|
||||||
select ARCH_EARLY_INIT_R
|
select ARCH_EARLY_INIT_R
|
||||||
|
select THEAD_TH1520
|
||||||
imply CPU
|
imply CPU
|
||||||
imply CPU_RISCV
|
imply CPU_RISCV
|
||||||
imply RISCV_TIMER if RISCV_SMODE
|
imply RISCV_TIMER if RISCV_SMODE
|
||||||
|
@@ -3,3 +3,4 @@
|
|||||||
# Copyright (c) 2023, Yixun Lan <dlan@gentoo.org>
|
# Copyright (c) 2023, Yixun Lan <dlan@gentoo.org>
|
||||||
|
|
||||||
obj-y += board.o
|
obj-y += board.o
|
||||||
|
obj-$(CONFIG_XPL_BUILD) += spl.o
|
||||||
|
48
board/thead/th1520_lpi4a/spl.c
Normal file
48
board/thead/th1520_lpi4a/spl.c
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025, Yao Zi <ziyao@disroot.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <asm/spl.h>
|
||||||
|
#include <asm/arch/cpu.h>
|
||||||
|
#include <asm/arch/spl.h>
|
||||||
|
#include <cpu_func.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <hang.h>
|
||||||
|
#include <spl.h>
|
||||||
|
|
||||||
|
u32 spl_boot_device(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We don't bother to load proper U-Boot from an external device as
|
||||||
|
* it fits in the integrated SRAM nicely.
|
||||||
|
*/
|
||||||
|
return BOOT_DEVICE_RAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
void board_init_f(ulong dummy)
|
||||||
|
{
|
||||||
|
int ret = spl_early_init();
|
||||||
|
struct udevice *dev;
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
panic("spl_early_init() failed %d\n", ret);
|
||||||
|
|
||||||
|
preloader_console_init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Manually bind CPU ahead of time to make sure in-core timers are
|
||||||
|
* available in SPL.
|
||||||
|
*/
|
||||||
|
ret = uclass_get_device(UCLASS_CPU, 0, &dev);
|
||||||
|
if (ret)
|
||||||
|
panic("failed to bind CPU: %d\n", ret);
|
||||||
|
|
||||||
|
spl_dram_init();
|
||||||
|
|
||||||
|
icache_enable();
|
||||||
|
dcache_enable();
|
||||||
|
|
||||||
|
th1520_invalidate_pmp();
|
||||||
|
}
|
@@ -92,7 +92,8 @@ static const table_entry_t uimage_arch[] = {
|
|||||||
{ IH_ARCH_ARC, "arc", "ARC", },
|
{ IH_ARCH_ARC, "arc", "ARC", },
|
||||||
{ IH_ARCH_X86_64, "x86_64", "AMD x86_64", },
|
{ IH_ARCH_X86_64, "x86_64", "AMD x86_64", },
|
||||||
{ IH_ARCH_XTENSA, "xtensa", "Xtensa", },
|
{ IH_ARCH_XTENSA, "xtensa", "Xtensa", },
|
||||||
{ IH_ARCH_RISCV, "riscv", "RISC-V", },
|
{ IH_ARCH_RISCV, "riscv", "RISC-V 32 Bit",},
|
||||||
|
{ IH_ARCH_RISCV64, "riscv64", "RISC-V 64 Bit",},
|
||||||
{ -1, "", "", },
|
{ -1, "", "", },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -130,8 +130,11 @@ int do_booti(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
|||||||
bootm_disable_interrupts();
|
bootm_disable_interrupts();
|
||||||
|
|
||||||
images.os.os = IH_OS_LINUX;
|
images.os.os = IH_OS_LINUX;
|
||||||
if (IS_ENABLED(CONFIG_RISCV_SMODE))
|
if (IS_ENABLED(CONFIG_RISCV))
|
||||||
images.os.arch = IH_ARCH_RISCV;
|
if (IS_ENABLED(CONFIG_64BIT))
|
||||||
|
images.os.arch = IH_ARCH_RISCV64;
|
||||||
|
else
|
||||||
|
images.os.arch = IH_ARCH_RISCV;
|
||||||
else if (IS_ENABLED(CONFIG_ARM64))
|
else if (IS_ENABLED(CONFIG_ARM64))
|
||||||
images.os.arch = IH_ARCH_ARM64;
|
images.os.arch = IH_ARCH_ARM64;
|
||||||
|
|
||||||
|
@@ -815,7 +815,9 @@ void board_init_r(gd_t *new_gd, ulong dest_addr)
|
|||||||
if (CONFIG_IS_ENABLED(X86_64) && !IS_ENABLED(CONFIG_EFI_APP))
|
if (CONFIG_IS_ENABLED(X86_64) && !IS_ENABLED(CONFIG_EFI_APP))
|
||||||
arch_setup_gd(new_gd);
|
arch_setup_gd(new_gd);
|
||||||
|
|
||||||
#if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
|
#if defined(CONFIG_RISCV)
|
||||||
|
set_gd(new_gd);
|
||||||
|
#elif !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
|
||||||
gd = new_gd;
|
gd = new_gd;
|
||||||
#endif
|
#endif
|
||||||
gd->flags &= ~GD_FLG_LOG_READY;
|
gd->flags &= ~GD_FLG_LOG_READY;
|
||||||
|
@@ -13,8 +13,11 @@
|
|||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
/* Unfortunately x86 or ARM can't compile this code as gd cannot be assigned */
|
/*
|
||||||
#if !defined(CONFIG_X86) && !defined(CONFIG_ARM)
|
* Unfortunately x86, ARM and RISC-V can't compile this code as gd is defined
|
||||||
|
* as macro and cannot be assigned.
|
||||||
|
*/
|
||||||
|
#if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_RISCV)
|
||||||
__weak void arch_setup_gd(struct global_data *gd_ptr)
|
__weak void arch_setup_gd(struct global_data *gd_ptr)
|
||||||
{
|
{
|
||||||
gd = gd_ptr;
|
gd = gd_ptr;
|
||||||
|
@@ -90,3 +90,21 @@ CONFIG_ZLIB_UNCOMPRESS=y
|
|||||||
CONFIG_BZIP2=y
|
CONFIG_BZIP2=y
|
||||||
CONFIG_ZSTD=y
|
CONFIG_ZSTD=y
|
||||||
CONFIG_LIB_RATIONAL=y
|
CONFIG_LIB_RATIONAL=y
|
||||||
|
CONFIG_SPL=y
|
||||||
|
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
|
||||||
|
CONFIG_SPL_LOAD_FIT_ADDRESS=0xffe0040000
|
||||||
|
CONFIG_SPL_HAVE_INIT_STACK=y
|
||||||
|
CONFIG_SPL_STACK=0xffe0170000
|
||||||
|
CONFIG_SPL_BSS_START_ADDR=0xffe0160000
|
||||||
|
CONFIG_SPL_BSS_MAX_SIZE=0x10000
|
||||||
|
CONFIG_SPL_MAX_SIZE=0x40000
|
||||||
|
CONFIG_SPL_RAM_DEVICE=y
|
||||||
|
CONFIG_RAM=y
|
||||||
|
CONFIG_SPL_RAM=y
|
||||||
|
CONFIG_SPL_THEAD_TH1520_DDR=y
|
||||||
|
CONFIG_SPL_GPIO=y
|
||||||
|
CONFIG_SPL_MMC_y
|
||||||
|
CONFIG_SPL_SYS_MALLOC=y
|
||||||
|
CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y
|
||||||
|
CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0x10000000
|
||||||
|
CONFIG_SPL_SYS_MALLOC_SIZE=0x400000
|
||||||
|
@@ -32,6 +32,8 @@ Mainline support
|
|||||||
The support for following drivers are already enabled:
|
The support for following drivers are already enabled:
|
||||||
|
|
||||||
1. ns16550 UART Driver.
|
1. ns16550 UART Driver.
|
||||||
|
2. eMMC and SD card
|
||||||
|
|
||||||
|
|
||||||
Building
|
Building
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
@@ -43,15 +45,32 @@ Building
|
|||||||
|
|
||||||
export CROSS_COMPILE=<riscv64 toolchain prefix>
|
export CROSS_COMPILE=<riscv64 toolchain prefix>
|
||||||
|
|
||||||
The U-Boot is capable of running in M-Mode, so we can directly build it.
|
3. Build DDR firmware
|
||||||
|
|
||||||
|
DDR driver requires a firmware to function, to build it:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
git clone --depth 1 https://github.com/ziyao233/th1520-firmware
|
||||||
|
cd th1520-firmware
|
||||||
|
lua5.4 ddr-generate.lua src/<CONFIGURATION_NAME>.lua th1520-ddr-firmware.bin
|
||||||
|
|
||||||
|
4. Build U-Boot images
|
||||||
|
|
||||||
|
The U-Boot is capable of running in M-Mode, so we can directly build it without
|
||||||
|
OpenSBI. The DDR firmware should be copied to U-Boot source directory before
|
||||||
|
building.
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
cd <U-Boot-dir>
|
cd <U-Boot-dir>
|
||||||
|
cp <path-to-ddr-firmware> th1520-ddr-firmware.bin
|
||||||
make th1520_lpi4a_defconfig
|
make th1520_lpi4a_defconfig
|
||||||
make
|
make
|
||||||
|
|
||||||
This will generate u-boot-dtb.bin
|
This will generate u-boot-dtb.bin and u-boot-with-spl.bin. The former contains
|
||||||
|
only proper U-Boot and is for chainloading; the later contains also SPL and
|
||||||
|
DDR firmware and is ready for booting by BROM directly.
|
||||||
|
|
||||||
Booting
|
Booting
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
@@ -61,7 +80,7 @@ and chain load the mainline u-boot image either via tftp or emmc storage,
|
|||||||
then bootup from it.
|
then bootup from it.
|
||||||
|
|
||||||
Sample boot log from Lichee PI 4A board via tftp
|
Sample boot log from Lichee PI 4A board via tftp
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
.. code-block:: none
|
.. code-block:: none
|
||||||
|
|
||||||
@@ -127,3 +146,36 @@ Sample boot log from Lichee PI 4A board via tftp
|
|||||||
Err: serial@ffe7014000
|
Err: serial@ffe7014000
|
||||||
Model: Sipeed Lichee Pi 4A
|
Model: Sipeed Lichee Pi 4A
|
||||||
LPI4A=>
|
LPI4A=>
|
||||||
|
|
||||||
|
SPL support is still in an early stage and not all of the functionalities are
|
||||||
|
available when booting from mainline SPL. When using mainline SPL,
|
||||||
|
u-boot-with-spl.bin should be loaded to SRAM through fastboot.
|
||||||
|
|
||||||
|
Sample boot log from Lichee PI 4A board via fastboot and mainline SPL
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. code-block:: none
|
||||||
|
|
||||||
|
brom_ver 8
|
||||||
|
[APP][E] protocol_connect failed, exit.
|
||||||
|
Starting download of 636588 bytes
|
||||||
|
|
||||||
|
downloading of 636588 bytes finished
|
||||||
|
|
||||||
|
U-Boot SPL 2025.04-rc2-00049-geaa9fc99d4cd-dirty (Apr 26 2025 - 13:31:41 +0000)
|
||||||
|
Trying to boot from RAM
|
||||||
|
|
||||||
|
|
||||||
|
U-Boot 2025.04-rc2-00049-geaa9fc99d4cd-dirty (Apr 26 2025 - 13:31:41 +0000)
|
||||||
|
|
||||||
|
CPU: thead,c910
|
||||||
|
Model: Sipeed Lichee Pi 4A
|
||||||
|
DRAM: 8 GiB
|
||||||
|
Core: 30 devices, 9 uclasses, devicetree: separate
|
||||||
|
MMC: mmc@ffe7080000: 0, mmc@ffe7090000: 1
|
||||||
|
Loading Environment from <NULL>... OK
|
||||||
|
In: serial@ffe7014000
|
||||||
|
Out: serial@ffe7014000
|
||||||
|
Err: serial@ffe7014000
|
||||||
|
Model: Sipeed Lichee Pi 4A
|
||||||
|
LPI4A=>
|
||||||
|
@@ -271,6 +271,7 @@ source "drivers/clk/starfive/Kconfig"
|
|||||||
source "drivers/clk/stm32/Kconfig"
|
source "drivers/clk/stm32/Kconfig"
|
||||||
source "drivers/clk/tegra/Kconfig"
|
source "drivers/clk/tegra/Kconfig"
|
||||||
source "drivers/clk/ti/Kconfig"
|
source "drivers/clk/ti/Kconfig"
|
||||||
|
source "drivers/clk/thead/Kconfig"
|
||||||
source "drivers/clk/uniphier/Kconfig"
|
source "drivers/clk/uniphier/Kconfig"
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
@@ -20,6 +20,7 @@ obj-y += imx/
|
|||||||
obj-$(CONFIG_CLK_JH7110) += starfive/
|
obj-$(CONFIG_CLK_JH7110) += starfive/
|
||||||
obj-y += tegra/
|
obj-y += tegra/
|
||||||
obj-y += ti/
|
obj-y += ti/
|
||||||
|
obj-$(CONFIG_CLK_THEAD) += thead/
|
||||||
obj-$(CONFIG_$(PHASE_)CLK_INTEL) += intel/
|
obj-$(CONFIG_$(PHASE_)CLK_INTEL) += intel/
|
||||||
obj-$(CONFIG_ARCH_ASPEED) += aspeed/
|
obj-$(CONFIG_ARCH_ASPEED) += aspeed/
|
||||||
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
|
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
|
||||||
|
19
drivers/clk/thead/Kconfig
Normal file
19
drivers/clk/thead/Kconfig
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#
|
||||||
|
# Copyright (c) 2025, Yao Zi <ziyao@disroot.org>
|
||||||
|
|
||||||
|
config CLK_THEAD
|
||||||
|
bool "Clock support for T-Head SoCs"
|
||||||
|
depends on CLK
|
||||||
|
|
||||||
|
if CLK_THEAD
|
||||||
|
|
||||||
|
config CLK_THEAD_TH1520_AP
|
||||||
|
bool "T-Head TH1520 AP clock support"
|
||||||
|
select CLK_CCF
|
||||||
|
default THEAD_TH1520
|
||||||
|
help
|
||||||
|
This enables support clock driver for T-Head TH1520 Application
|
||||||
|
processor.
|
||||||
|
|
||||||
|
endif
|
5
drivers/clk/thead/Makefile
Normal file
5
drivers/clk/thead/Makefile
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#
|
||||||
|
# Copyright (C) 2025 Yao Zi <ziyao@disroot.org>
|
||||||
|
|
||||||
|
obj-$(CONFIG_CLK_THEAD_TH1520_AP) += clk-th1520-ap.o
|
1031
drivers/clk/thead/clk-th1520-ap.c
Normal file
1031
drivers/clk/thead/clk-th1520-ap.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -135,3 +135,4 @@ source "drivers/ram/sifive/Kconfig"
|
|||||||
source "drivers/ram/stm32mp1/Kconfig"
|
source "drivers/ram/stm32mp1/Kconfig"
|
||||||
source "drivers/ram/starfive/Kconfig"
|
source "drivers/ram/starfive/Kconfig"
|
||||||
source "drivers/ram/sunxi/Kconfig"
|
source "drivers/ram/sunxi/Kconfig"
|
||||||
|
source "drivers/ram/thead/Kconfig"
|
||||||
|
@@ -30,3 +30,7 @@ obj-$(CONFIG_ARCH_OCTEON) += octeon/
|
|||||||
|
|
||||||
obj-$(CONFIG_ARCH_RENESAS) += renesas/
|
obj-$(CONFIG_ARCH_RENESAS) += renesas/
|
||||||
obj-$(CONFIG_CADENCE_DDR_CTRL) += cadence/
|
obj-$(CONFIG_CADENCE_DDR_CTRL) += cadence/
|
||||||
|
|
||||||
|
ifdef CONFIG_XPL_BUILD
|
||||||
|
obj-$(CONFIG_SPL_THEAD_TH1520_DDR) += thead/
|
||||||
|
endif
|
||||||
|
5
drivers/ram/thead/Kconfig
Normal file
5
drivers/ram/thead/Kconfig
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
config SPL_THEAD_TH1520_DDR
|
||||||
|
bool "T-Head TH1520 DDR driver in SPL"
|
||||||
|
depends on SPL_RAM && THEAD_TH1520
|
||||||
|
help
|
||||||
|
This enables DDR support for T-Head TH1520 platforms.
|
1
drivers/ram/thead/Makefile
Normal file
1
drivers/ram/thead/Makefile
Normal file
@@ -0,0 +1 @@
|
|||||||
|
obj-$(CONFIG_SPL_THEAD_TH1520_DDR) += th1520_ddr.o
|
787
drivers/ram/thead/th1520_ddr.c
Normal file
787
drivers/ram/thead/th1520_ddr.c
Normal file
@@ -0,0 +1,787 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2017-2024 Alibaba Group Holding Limited
|
||||||
|
* Copyright (C) 2025 Yao Zi <ziyao@disroot.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <binman.h>
|
||||||
|
#include <binman_sym.h>
|
||||||
|
#include <dm.h>
|
||||||
|
#include <init.h>
|
||||||
|
#include <linux/bitfield.h>
|
||||||
|
#include <linux/iopoll.h>
|
||||||
|
#include <ram.h>
|
||||||
|
|
||||||
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
struct th1520_ddr_fw {
|
||||||
|
u64 magic;
|
||||||
|
u8 type, ranknum, bitwidth, freq;
|
||||||
|
u8 reserved[8];
|
||||||
|
|
||||||
|
u32 cfgnum;
|
||||||
|
union th1520_ddr_cfg {
|
||||||
|
u32 opaddr;
|
||||||
|
|
||||||
|
struct th1520_ddr_phy {
|
||||||
|
u32 opaddr;
|
||||||
|
u16 data;
|
||||||
|
} phy;
|
||||||
|
|
||||||
|
struct th1520_ddr_range {
|
||||||
|
u32 opaddr;
|
||||||
|
u32 num;
|
||||||
|
u16 data[];
|
||||||
|
} range;
|
||||||
|
} cfgs[];
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
/* Firmware constants */
|
||||||
|
#define TH1520_DDR_MAGIC 0x4452444445415448
|
||||||
|
|
||||||
|
#define TH1520_DDR_TYPE_LPDDR4 0
|
||||||
|
#define TH1520_DDR_TYPE_LPDDR4X 1
|
||||||
|
|
||||||
|
#define TH1520_DDR_FREQ_2133 0
|
||||||
|
#define TH1520_DDR_FREQ_3200 1
|
||||||
|
#define TH1520_DDR_FREQ_3733 2
|
||||||
|
#define TH1520_DDR_FREQ_4266 3
|
||||||
|
|
||||||
|
#define TH1520_DDR_CFG_OP GENMASK(31, 24)
|
||||||
|
#define TH1520_DDR_CFG_ADDR GENMASK(23, 0)
|
||||||
|
|
||||||
|
#define TH1520_DDR_CFG_PHY0 0
|
||||||
|
#define TH1520_DDR_CFG_PHY1 1
|
||||||
|
#define TH1520_DDR_CFG_PHY 2
|
||||||
|
#define TH1520_DDR_CFG_RANGE 3
|
||||||
|
#define TH1520_DDR_CFG_WAITFW0 4
|
||||||
|
#define TH1520_DDR_CFG_WAITFW1 5
|
||||||
|
|
||||||
|
/* Driver constants */
|
||||||
|
#define TH1520_SYS_PLL_TIMEOUT_US 30
|
||||||
|
#define TH1520_CTRL_INIT_TIMEOUT_US 1000000
|
||||||
|
#define TH1520_PHY_MSG_TIMEOUT_US 1000000
|
||||||
|
|
||||||
|
/* System configuration registers */
|
||||||
|
#define TH1520_SYS_DDR_CFG0 0x00
|
||||||
|
#define TH1520_SYS_DDR_CFG0_APB_RSTN BIT(4)
|
||||||
|
#define TH1520_SYS_DDR_CFG0_CTRL_RSTN BIT(5)
|
||||||
|
#define TH1520_SYS_DDR_CFG0_PHY_PWROK_RSTN BIT(6)
|
||||||
|
#define TH1520_SYS_DDR_CFG0_PHY_CORE_RSTN BIT(7)
|
||||||
|
#define TH1520_SYS_DDR_CFG0_APB_PORT_RSTN(n) BIT(n + 4 + 4)
|
||||||
|
#define TH1520_SYS_DDR_CFG1 0x04
|
||||||
|
#define TH1520_SYS_PLL_CFG0 0x08
|
||||||
|
#define TH1520_SYS_PLL_CFG0_POSTDIV2 GENMASK(26, 24)
|
||||||
|
#define TH1520_SYS_PLL_CFG0_POSTDIV1 GENMASK(22, 20)
|
||||||
|
#define TH1520_SYS_PLL_CFG0_FBDIV GENMASK(19, 8)
|
||||||
|
#define TH1520_SYS_PLL_CFG0_REFDIV GENMASK(5, 0)
|
||||||
|
#define TH1520_SYS_PLL_CFG1 0x0c
|
||||||
|
#define TH1520_SYS_PLL_CFG1_RST BIT(30)
|
||||||
|
#define TH1520_SYS_PLL_CFG1_FOUTPOSTDIVPD BIT(27)
|
||||||
|
#define TH1520_SYS_PLL_CFG1_FOUT4PHASEPD BIT(25)
|
||||||
|
#define Th1520_SYS_PLL_CFG1_DACPD BIT(24)
|
||||||
|
#define TH1520_SYS_PLL_CFG2 0x10
|
||||||
|
#define TH1520_SYS_PLL_CFG3 0x14
|
||||||
|
#define TH1520_SYS_PLL_STS 0x18
|
||||||
|
#define TH1520_SYS_PLL_STS_EN BIT(16)
|
||||||
|
#define TH1520_SYS_PLL_STS_LOCKED BIT(0)
|
||||||
|
|
||||||
|
/* DDR Controller Registers */
|
||||||
|
#define TH1520_CTRL_MSTR 0x0000
|
||||||
|
#define TH1520_CTRL_STAT 0x0004
|
||||||
|
#define TH1520_CTRL_MRCTRL0 0x0010
|
||||||
|
#define TH1520_CTRL_MRCTRL1 0x0014
|
||||||
|
#define TH1520_CTRL_MRSTAT 0x0018
|
||||||
|
#define TH1520_CTRL_DERATEEN 0x0020
|
||||||
|
#define TH1520_CTRL_DERATEINT 0x0024
|
||||||
|
#define TH1520_CTRL_DERATECTL 0x002c
|
||||||
|
#define TH1520_CTRL_PWRCTL 0x0030
|
||||||
|
#define TH1520_CTRL_PWRTMG 0x0034
|
||||||
|
#define TH1520_CTRL_HWLPCTL 0x0038
|
||||||
|
#define TH1520_CTRL_RFSHCTL0 0x0050
|
||||||
|
#define TH1520_CTRL_RFSHCTL1 0x0054
|
||||||
|
#define TH1520_CTRL_RFSHCTL3 0x0060
|
||||||
|
#define TH1520_CTRL_RFSHTMG 0x0064
|
||||||
|
#define TH1520_CTRL_RFSHTMG1 0x0068
|
||||||
|
#define TH1520_CTRL_CRCPARCTL0 0x00c0
|
||||||
|
#define TH1520_CTRL_CRCPARSTAT 0x00cc
|
||||||
|
#define TH1520_CTRL_INIT0 0x00d0
|
||||||
|
#define TH1520_CTRL_INIT1 0x00d4
|
||||||
|
#define TH1520_CTRL_INIT2 0x00d8
|
||||||
|
#define TH1520_CTRL_INIT3 0x00dc
|
||||||
|
#define TH1520_CTRL_INIT4 0x00e0
|
||||||
|
#define TH1520_CTRL_INIT5 0x00e4
|
||||||
|
#define TH1520_CTRL_INIT6 0x00e8
|
||||||
|
#define TH1520_CTRL_INIT7 0x00ec
|
||||||
|
#define TH1520_CTRL_DIMMCTL 0x00f0
|
||||||
|
#define TH1520_CTRL_RANKCTL 0x00f4
|
||||||
|
#define TH1520_CTRL_RANKCTL1 0x00f8
|
||||||
|
#define TH1520_CTRL_DRAMTMG0 0x0100
|
||||||
|
#define TH1520_CTRL_DRAMTMG1 0x0104
|
||||||
|
#define TH1520_CTRL_DRAMTMG2 0x0108
|
||||||
|
#define TH1520_CTRL_DRAMTMG3 0x010c
|
||||||
|
#define TH1520_CTRL_DRAMTMG4 0x0110
|
||||||
|
#define TH1520_CTRL_DRAMTMG5 0x0114
|
||||||
|
#define TH1520_CTRL_DRAMTMG6 0x0118
|
||||||
|
#define TH1520_CTRL_DRAMTMG7 0x011c
|
||||||
|
#define TH1520_CTRL_DRAMTMG8 0x0120
|
||||||
|
#define TH1520_CTRL_DRAMTMG12 0x0130
|
||||||
|
#define TH1520_CTRL_DRAMTMG13 0x0134
|
||||||
|
#define TH1520_CTRL_DRAMTMG14 0x0138
|
||||||
|
#define TH1520_CTRL_DRAMTMG17 0x0144
|
||||||
|
#define TH1520_CTRL_ZQCTL0 0x0180
|
||||||
|
#define TH1520_CTRL_ZQCTL1 0x0184
|
||||||
|
#define TH1520_CTRL_ZQCTL2 0x0188
|
||||||
|
#define TH1520_CTRL_ZQSTAT 0x018c
|
||||||
|
#define TH1520_CTRL_DFITMG0 0x0190
|
||||||
|
#define TH1520_CTRL_DFITMG1 0x0194
|
||||||
|
#define TH1520_CTRL_DFILPCFG0 0x0198
|
||||||
|
#define TH1520_CTRL_DFIUPD0 0x01a0
|
||||||
|
#define TH1520_CTRL_DFIUPD1 0x01a4
|
||||||
|
#define TH1520_CTRL_DFIUPD2 0x01a8
|
||||||
|
#define TH1520_CTRL_DFIMISC 0x01b0
|
||||||
|
#define TH1520_CTRL_DFITMG2 0x01b4
|
||||||
|
#define TH1520_CTRL_DFISTAT 0x01bc
|
||||||
|
#define TH1520_CTRL_DBICTL 0x01c0
|
||||||
|
#define TH1520_CTRL_DFIPHYMSTR 0x01c4
|
||||||
|
#define TH1520_CTRL_ADDRMAP0 0x0200
|
||||||
|
#define TH1520_CTRL_ADDRMAP1 0x0204
|
||||||
|
#define TH1520_CTRL_ADDRMAP2 0x0208
|
||||||
|
#define TH1520_CTRL_ADDRMAP3 0x020c
|
||||||
|
#define TH1520_CTRL_ADDRMAP4 0x0210
|
||||||
|
#define TH1520_CTRL_ADDRMAP5 0x0214
|
||||||
|
#define TH1520_CTRL_ADDRMAP6 0x0218
|
||||||
|
#define TH1520_CTRL_ADDRMAP7 0x021c
|
||||||
|
#define TH1520_CTRL_ADDRMAP8 0x0220
|
||||||
|
#define TH1520_CTRL_ADDRMAP9 0x0224
|
||||||
|
#define TH1520_CTRL_ADDRMAP10 0x0228
|
||||||
|
#define TH1520_CTRL_ADDRMAP11 0x022c
|
||||||
|
#define TH1520_CTRL_ODTCFG 0x0240
|
||||||
|
#define TH1520_CTRL_ODTMAP 0x0244
|
||||||
|
#define TH1520_CTRL_SCHED 0x0250
|
||||||
|
#define TH1520_CTRL_SCHED1 0x0254
|
||||||
|
#define TH1520_CTRL_PERFHPR1 0x025c
|
||||||
|
#define TH1520_CTRL_PERFLPR1 0x0264
|
||||||
|
#define TH1520_CTRL_PERFWR1 0x026c
|
||||||
|
#define TH1520_CTRL_SCHED3 0x0270
|
||||||
|
#define TH1520_CTRL_SCHED4 0x0274
|
||||||
|
#define TH1520_CTRL_DBG0 0x0300
|
||||||
|
#define TH1520_CTRL_DBG1 0x0304
|
||||||
|
#define TH1520_CTRL_DBGCAM 0x0308
|
||||||
|
#define TH1520_CTRL_DBGCMD 0x030c
|
||||||
|
#define TH1520_CTRL_DBGSTAT 0x0310
|
||||||
|
#define TH1520_CTRL_SWCTL 0x0320
|
||||||
|
#define TH1520_CTRL_SWSTAT 0x0324
|
||||||
|
#define TH1520_CTRL_SWCTLSTATIC 0x0328
|
||||||
|
#define TH1520_CTRL_POISONCFG 0x036c
|
||||||
|
#define TH1520_CTRL_POISONSTAT 0x0370
|
||||||
|
#define TH1520_CTRL_DERATESTAT 0x03f0
|
||||||
|
#define TH1520_CTRL_PSTAT 0x03fc
|
||||||
|
#define TH1520_CTRL_PCCFG 0x0400
|
||||||
|
#define TH1520_CTRL_PCFGR_0 0x0404
|
||||||
|
#define TH1520_CTRL_PCFGW_0 0x0408
|
||||||
|
#define TH1520_CTRL_PCTRL_0 0x0490
|
||||||
|
#define TH1520_CTRL_PCFGQOS0_0 0x0494
|
||||||
|
#define TH1520_CTRL_PCFGQOS1_0 0x0498
|
||||||
|
#define TH1520_CTRL_PCFGWQOS0_0 0x049c
|
||||||
|
#define TH1520_CTRL_PCFGWQOS1_0 0x04a0
|
||||||
|
#define TH1520_CTRL_PCFGR_1 0x04b4
|
||||||
|
#define TH1520_CTRL_PCFGW_1 0x04b8
|
||||||
|
#define TH1520_CTRL_PCTRL_1 0x0540
|
||||||
|
#define TH1520_CTRL_PCFGQOS0_1 0x0544
|
||||||
|
#define TH1520_CTRL_PCFGQOS1_1 0x0548
|
||||||
|
#define TH1520_CTRL_PCFGWQOS0_1 0x054c
|
||||||
|
#define TH1520_CTRL_PCFGWQOS1_1 0x0550
|
||||||
|
#define TH1520_CTRL_PCFGR_2 0x0564
|
||||||
|
#define TH1520_CTRL_PCFGW_2 0x0568
|
||||||
|
#define TH1520_CTRL_PCTRL_2 0x05f0
|
||||||
|
#define TH1520_CTRL_PCFGQOS0_2 0x05f4
|
||||||
|
#define TH1520_CTRL_PCFGQOS1_2 0x05f8
|
||||||
|
#define TH1520_CTRL_PCFGWQOS0_2 0x05fc
|
||||||
|
#define TH1520_CTRL_PCFGWQOS1_2 0x0600
|
||||||
|
#define TH1520_CTRL_PCFGR_3 0x0614
|
||||||
|
#define TH1520_CTRL_PCFGW_3 0x0618
|
||||||
|
#define TH1520_CTRL_PCTRL_3 0x06a0
|
||||||
|
#define TH1520_CTRL_PCFGQOS0_3 0x06a4
|
||||||
|
#define TH1520_CTRL_PCFGQOS1_3 0x06a8
|
||||||
|
#define TH1520_CTRL_PCFGWQOS0_3 0x06ac
|
||||||
|
#define TH1520_CTRL_PCFGWQOS1_3 0x06b0
|
||||||
|
#define TH1520_CTRL_PCFGR_4 0x06c4
|
||||||
|
#define TH1520_CTRL_PCFGW_4 0x06c8
|
||||||
|
#define TH1520_CTRL_PCTRL_4 0x0750
|
||||||
|
#define TH1520_CTRL_PCFGQOS0_4 0x0754
|
||||||
|
#define TH1520_CTRL_PCFGQOS1_4 0x0758
|
||||||
|
#define TH1520_CTRL_PCFGWQOS0_4 0x075c
|
||||||
|
#define TH1520_CTRL_PCFGWQOS1_4 0x0760
|
||||||
|
#define TH1520_CTRL_UMCTL2_VER_NUMBER 0x0ff0
|
||||||
|
#define TH1520_CTRL_UMCTL2_VER_TYPE 0x0ff4
|
||||||
|
#define TH1520_CTRL_DCH1_STAT 0x1b04
|
||||||
|
#define TH1520_CTRL_DCH1_MRCTRL0 0x1b10
|
||||||
|
#define TH1520_CTRL_DCH1_MRCTRL1 0x1b14
|
||||||
|
#define TH1520_CTRL_DCH1_MRSTAT 0x1b18
|
||||||
|
#define TH1520_CTRL_DCH1_DERATECTL 0x1b2c
|
||||||
|
#define TH1520_CTRL_DCH1_PWRCTL 0x1b30
|
||||||
|
#define TH1520_CTRL_DCH1_HWLPCTL 0x1b38
|
||||||
|
#define TH1520_CTRL_DCH1_CRCPARCTL0 0x1bc0
|
||||||
|
#define TH1520_CTRL_DCH1_ZQCTL2 0x1c88
|
||||||
|
#define TH1520_CTRL_DCH1_DFISTAT 0x1cbc
|
||||||
|
#define TH1520_CTRL_DCH1_ODTMAP 0x1d44
|
||||||
|
#define TH1520_CTRL_DCH1_DBG1 0x1e04
|
||||||
|
#define TH1520_CTRL_DCH1_DBGCMD 0x1e0c
|
||||||
|
#define TH1520_CTRL_DCH1_DBGCAM 0x1e08
|
||||||
|
|
||||||
|
/* PHY configuration registers */
|
||||||
|
#define TH1520_DDR_PHY_REG(regid) ((regid) * 2)
|
||||||
|
|
||||||
|
/* UctShadowRegs */
|
||||||
|
#define TH1520_PHY_MSG_STATUS TH1520_DDR_PHY_REG(0xd0004)
|
||||||
|
#define TH1520_PHY_MSG_STATUS_EMPTY BIT(0)
|
||||||
|
/* DctWriteProt */
|
||||||
|
#define TH1520_PHY_MSG_ACK TH1520_DDR_PHY_REG(0xd0031)
|
||||||
|
#define TH1520_PHY_MSG_ACK_EN BIT(0)
|
||||||
|
/* UctWriteOnlyShadow */
|
||||||
|
#define TH1520_PHY_MSG_ID TH1520_DDR_PHY_REG(0xd0032)
|
||||||
|
#define TH1520_PHY_MSG_ID_COMPLETION 0x7
|
||||||
|
#define TH1520_PHY_MSG_ID_ERROR 0xff
|
||||||
|
/* UctDatWriteOnlyShadow */
|
||||||
|
#define TH1520_PHY_MSG_DATA TH1520_DDR_PHY_REG(0xd0034)
|
||||||
|
|
||||||
|
struct th1520_ddr_priv {
|
||||||
|
void __iomem *phy0;
|
||||||
|
void __iomem *phy1;
|
||||||
|
void __iomem *ctrl;
|
||||||
|
void __iomem *sys;
|
||||||
|
};
|
||||||
|
|
||||||
|
binman_sym_declare(ulong, ddr_fw, image_pos);
|
||||||
|
|
||||||
|
static int th1520_ddr_pll_config(void __iomem *sysreg, unsigned int frequency)
|
||||||
|
{
|
||||||
|
u32 tmp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
tmp = TH1520_SYS_PLL_CFG1_RST |
|
||||||
|
TH1520_SYS_PLL_CFG1_FOUTPOSTDIVPD |
|
||||||
|
TH1520_SYS_PLL_CFG1_FOUT4PHASEPD |
|
||||||
|
Th1520_SYS_PLL_CFG1_DACPD;
|
||||||
|
writel(tmp, sysreg + TH1520_SYS_PLL_CFG1);
|
||||||
|
|
||||||
|
switch (frequency) {
|
||||||
|
case TH1520_DDR_FREQ_3733:
|
||||||
|
writel(FIELD_PREP(TH1520_SYS_PLL_CFG0_REFDIV, 1) |
|
||||||
|
FIELD_PREP(TH1520_SYS_PLL_CFG0_FBDIV, 77) |
|
||||||
|
FIELD_PREP(TH1520_SYS_PLL_CFG0_POSTDIV1, 2) |
|
||||||
|
FIELD_PREP(TH1520_SYS_PLL_CFG0_POSTDIV2, 1),
|
||||||
|
sysreg + TH1520_SYS_PLL_CFG0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
udelay(2);
|
||||||
|
tmp &= ~TH1520_SYS_PLL_CFG1_RST;
|
||||||
|
writel(tmp, sysreg + TH1520_SYS_PLL_CFG1);
|
||||||
|
|
||||||
|
ret = readl_poll_timeout(sysreg + TH1520_SYS_PLL_STS, tmp,
|
||||||
|
tmp & TH1520_SYS_PLL_STS_LOCKED,
|
||||||
|
TH1520_SYS_PLL_TIMEOUT_US);
|
||||||
|
|
||||||
|
writel(TH1520_SYS_PLL_STS_EN, sysreg + TH1520_SYS_PLL_STS);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int th1520_ddr_ctrl_init(void __iomem *ctrlreg, struct th1520_ddr_fw *fw)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
|
writel(0x00000001, ctrlreg + TH1520_CTRL_DBG1);
|
||||||
|
writel(0x00000001, ctrlreg + TH1520_CTRL_PWRCTL);
|
||||||
|
|
||||||
|
ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_STAT, tmp,
|
||||||
|
tmp == 0x00000000,
|
||||||
|
TH1520_CTRL_INIT_TIMEOUT_US);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (fw->ranknum == 2)
|
||||||
|
writel(0x03080020, ctrlreg + TH1520_CTRL_MSTR);
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
writel(0x00003030, ctrlreg + TH1520_CTRL_MRCTRL0);
|
||||||
|
writel(0x0002d90f, ctrlreg + TH1520_CTRL_MRCTRL1);
|
||||||
|
|
||||||
|
switch (fw->freq) {
|
||||||
|
case TH1520_DDR_FREQ_3733:
|
||||||
|
writel(0x000013f3, ctrlreg + TH1520_CTRL_DERATEEN);
|
||||||
|
writel(0x40000000, ctrlreg + TH1520_CTRL_DERATEINT);
|
||||||
|
writel(0x00000001, ctrlreg + TH1520_CTRL_DERATECTL);
|
||||||
|
writel(0x00000020, ctrlreg + TH1520_CTRL_PWRCTL);
|
||||||
|
writel(0x0040ae04, ctrlreg + TH1520_CTRL_PWRTMG);
|
||||||
|
writel(0x00430000, ctrlreg + TH1520_CTRL_HWLPCTL);
|
||||||
|
writel(0x00210004, ctrlreg + TH1520_CTRL_RFSHCTL0);
|
||||||
|
writel(0x000d0021, ctrlreg + TH1520_CTRL_RFSHCTL1);
|
||||||
|
writel(0x00000001, ctrlreg + TH1520_CTRL_RFSHCTL3);
|
||||||
|
writel(0x81c00084, ctrlreg + TH1520_CTRL_RFSHTMG);
|
||||||
|
writel(0x00540000, ctrlreg + TH1520_CTRL_RFSHTMG1);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_CRCPARCTL0);
|
||||||
|
writel(0xc0020002, ctrlreg + TH1520_CTRL_INIT0);
|
||||||
|
writel(0x00010002, ctrlreg + TH1520_CTRL_INIT1);
|
||||||
|
writel(0x00001f00, ctrlreg + TH1520_CTRL_INIT2);
|
||||||
|
writel(0x00640036, ctrlreg + TH1520_CTRL_INIT3);
|
||||||
|
writel(0x00f20008, ctrlreg + TH1520_CTRL_INIT4);
|
||||||
|
writel(0x0004000b, ctrlreg + TH1520_CTRL_INIT5);
|
||||||
|
writel(0x00440012, ctrlreg + TH1520_CTRL_INIT6);
|
||||||
|
writel(0x0004001a, ctrlreg + TH1520_CTRL_INIT7);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_DIMMCTL);
|
||||||
|
writel(0x0000ab9f, ctrlreg + TH1520_CTRL_RANKCTL);
|
||||||
|
writel(0x00000017, ctrlreg + TH1520_CTRL_RANKCTL1);
|
||||||
|
writel(0x1f263f28, ctrlreg + TH1520_CTRL_DRAMTMG0);
|
||||||
|
writel(0x00080839, ctrlreg + TH1520_CTRL_DRAMTMG1);
|
||||||
|
writel(0x08121d17, ctrlreg + TH1520_CTRL_DRAMTMG2);
|
||||||
|
writel(0x00d0e000, ctrlreg + TH1520_CTRL_DRAMTMG3);
|
||||||
|
writel(0x11040a12, ctrlreg + TH1520_CTRL_DRAMTMG4);
|
||||||
|
writel(0x02050e0e, ctrlreg + TH1520_CTRL_DRAMTMG5);
|
||||||
|
writel(0x01010008, ctrlreg + TH1520_CTRL_DRAMTMG6);
|
||||||
|
writel(0x00000502, ctrlreg + TH1520_CTRL_DRAMTMG7);
|
||||||
|
writel(0x00000101, ctrlreg + TH1520_CTRL_DRAMTMG8);
|
||||||
|
writel(0x00020000, ctrlreg + TH1520_CTRL_DRAMTMG12);
|
||||||
|
writel(0x0d100002, ctrlreg + TH1520_CTRL_DRAMTMG13);
|
||||||
|
writel(0x0000010c, ctrlreg + TH1520_CTRL_DRAMTMG14);
|
||||||
|
writel(0x03a50021, ctrlreg + TH1520_CTRL_ZQCTL0);
|
||||||
|
writel(0x02f00800, ctrlreg + TH1520_CTRL_ZQCTL1);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_ZQCTL2);
|
||||||
|
writel(0x059f820c, ctrlreg + TH1520_CTRL_DFITMG0);
|
||||||
|
writel(0x000c0303, ctrlreg + TH1520_CTRL_DFITMG1);
|
||||||
|
writel(0x0351a101, ctrlreg + TH1520_CTRL_DFILPCFG0);
|
||||||
|
writel(0x00000011, ctrlreg + TH1520_CTRL_DFIMISC);
|
||||||
|
writel(0x00001f0c, ctrlreg + TH1520_CTRL_DFITMG2);
|
||||||
|
writel(0x00000007, ctrlreg + TH1520_CTRL_DBICTL);
|
||||||
|
writel(0x14000001, ctrlreg + TH1520_CTRL_DFIPHYMSTR);
|
||||||
|
writel(0x06090b40, ctrlreg + TH1520_CTRL_ODTCFG);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
writel(0x00400018, ctrlreg + TH1520_CTRL_DFIUPD0);
|
||||||
|
writel(0x00280032, ctrlreg + TH1520_CTRL_DFIUPD1);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_DFIUPD2);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_ODTMAP);
|
||||||
|
writel(0x1f829b1c, ctrlreg + TH1520_CTRL_SCHED);
|
||||||
|
writel(0x4400b00f, ctrlreg + TH1520_CTRL_SCHED1);
|
||||||
|
writel(0x0f000001, ctrlreg + TH1520_CTRL_PERFHPR1);
|
||||||
|
writel(0x0f00007f, ctrlreg + TH1520_CTRL_PERFLPR1);
|
||||||
|
writel(0x0f00007f, ctrlreg + TH1520_CTRL_PERFWR1);
|
||||||
|
writel(0x00000208, ctrlreg + TH1520_CTRL_SCHED3);
|
||||||
|
writel(0x08400810, ctrlreg + TH1520_CTRL_SCHED4);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_DBG0);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_DBG1);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_DBGCMD);
|
||||||
|
writel(0x00000001, ctrlreg + TH1520_CTRL_SWCTL);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_SWCTLSTATIC);
|
||||||
|
writel(0x00000001, ctrlreg + TH1520_CTRL_POISONCFG);
|
||||||
|
writel(0x00000001, ctrlreg + TH1520_CTRL_PCTRL_0);
|
||||||
|
writel(0x00000001, ctrlreg + TH1520_CTRL_PCTRL_1);
|
||||||
|
writel(0x00000001, ctrlreg + TH1520_CTRL_PCTRL_2);
|
||||||
|
writel(0x00000001, ctrlreg + TH1520_CTRL_PCTRL_3);
|
||||||
|
writel(0x00000001, ctrlreg + TH1520_CTRL_PCTRL_4);
|
||||||
|
writel(0x00003030, ctrlreg + TH1520_CTRL_DCH1_MRCTRL0);
|
||||||
|
writel(0x0002d90f, ctrlreg + TH1520_CTRL_DCH1_MRCTRL1);
|
||||||
|
writel(0x00000001, ctrlreg + TH1520_CTRL_DCH1_DERATECTL);
|
||||||
|
writel(0x00000020, ctrlreg + TH1520_CTRL_DCH1_PWRCTL);
|
||||||
|
writel(0x00430002, ctrlreg + TH1520_CTRL_DCH1_HWLPCTL);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_DCH1_CRCPARCTL0);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_DCH1_ZQCTL2);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_DCH1_ODTMAP);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_DCH1_DBG1);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_DCH1_DBGCMD);
|
||||||
|
|
||||||
|
ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_RFSHCTL3, tmp,
|
||||||
|
tmp == 0x00000001,
|
||||||
|
TH1520_CTRL_INIT_TIMEOUT_US);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
writel(0x00000010, ctrlreg + TH1520_CTRL_PCCFG);
|
||||||
|
writel(0x0000500f, ctrlreg + TH1520_CTRL_PCFGR_0);
|
||||||
|
writel(0x0000500f, ctrlreg + TH1520_CTRL_PCFGW_0);
|
||||||
|
writel(0x00005020, ctrlreg + TH1520_CTRL_PCFGR_1);
|
||||||
|
writel(0x0000501f, ctrlreg + TH1520_CTRL_PCFGW_1);
|
||||||
|
writel(0x0000501f, ctrlreg + TH1520_CTRL_PCFGR_2);
|
||||||
|
writel(0x0000503f, ctrlreg + TH1520_CTRL_PCFGW_2);
|
||||||
|
writel(0x000051ff, ctrlreg + TH1520_CTRL_PCFGR_3);
|
||||||
|
writel(0x000051ff, ctrlreg + TH1520_CTRL_PCFGW_3);
|
||||||
|
writel(0x0000503f, ctrlreg + TH1520_CTRL_PCFGR_4);
|
||||||
|
writel(0x0000503f, ctrlreg + TH1520_CTRL_PCFGW_4);
|
||||||
|
|
||||||
|
ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_PWRCTL, tmp,
|
||||||
|
tmp == 0x00000020,
|
||||||
|
TH1520_CTRL_INIT_TIMEOUT_US);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
writel(0x00000020, ctrlreg + TH1520_CTRL_PWRCTL);
|
||||||
|
|
||||||
|
ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_DCH1_PWRCTL, tmp,
|
||||||
|
tmp == 0x00000020,
|
||||||
|
TH1520_CTRL_INIT_TIMEOUT_US);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
writel(0x00000020, ctrlreg + TH1520_CTRL_DCH1_PWRCTL);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_DBG1);
|
||||||
|
|
||||||
|
ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_PWRCTL, tmp,
|
||||||
|
tmp == 0x00000020,
|
||||||
|
TH1520_CTRL_INIT_TIMEOUT_US);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
writel(0x00000020, ctrlreg + TH1520_CTRL_PWRCTL);
|
||||||
|
|
||||||
|
ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_PWRCTL, tmp,
|
||||||
|
tmp == 0x00000020,
|
||||||
|
TH1520_CTRL_INIT_TIMEOUT_US);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
writel(0x00000020, ctrlreg + TH1520_CTRL_PWRCTL);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_DCH1_DBG1);
|
||||||
|
|
||||||
|
ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_DCH1_PWRCTL, tmp,
|
||||||
|
tmp == 0x00000020,
|
||||||
|
TH1520_CTRL_INIT_TIMEOUT_US);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
writel(0x00000020, ctrlreg + TH1520_CTRL_DCH1_PWRCTL);
|
||||||
|
|
||||||
|
ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_DCH1_PWRCTL, tmp,
|
||||||
|
tmp == 0x00000020,
|
||||||
|
TH1520_CTRL_INIT_TIMEOUT_US);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
writel(0x00000020, ctrlreg + TH1520_CTRL_DCH1_PWRCTL);
|
||||||
|
writel(0x14000001, ctrlreg + TH1520_CTRL_DFIPHYMSTR);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_SWCTL);
|
||||||
|
writel(0x00000010, ctrlreg + TH1520_CTRL_DFIMISC);
|
||||||
|
writel(0x00000010, ctrlreg + TH1520_CTRL_DFIMISC);
|
||||||
|
writel(0x00000002, ctrlreg + TH1520_CTRL_DBG1);
|
||||||
|
writel(0x00000002, ctrlreg + TH1520_CTRL_DCH1_DBG1);
|
||||||
|
|
||||||
|
switch (fw->bitwidth) {
|
||||||
|
case 64:
|
||||||
|
writel(0x00040018, ctrlreg + TH1520_CTRL_ADDRMAP0);
|
||||||
|
writel(0x00090909, ctrlreg + TH1520_CTRL_ADDRMAP1);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_ADDRMAP2);
|
||||||
|
writel(0x01010101, ctrlreg + TH1520_CTRL_ADDRMAP3);
|
||||||
|
writel(0x00001f1f, ctrlreg + TH1520_CTRL_ADDRMAP4);
|
||||||
|
writel(0x080f0808, ctrlreg + TH1520_CTRL_ADDRMAP5);
|
||||||
|
writel(0x08080808, ctrlreg + TH1520_CTRL_ADDRMAP6);
|
||||||
|
writel(0x00000f0f, ctrlreg + TH1520_CTRL_ADDRMAP7);
|
||||||
|
writel(0x08080808, ctrlreg + TH1520_CTRL_ADDRMAP9);
|
||||||
|
writel(0x08080808, ctrlreg + TH1520_CTRL_ADDRMAP10);
|
||||||
|
writel(0x00000008, ctrlreg + TH1520_CTRL_ADDRMAP11);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int th1520_ddr_read_msg(void __iomem *phyreg, u16 *id, u16 *data)
|
||||||
|
{
|
||||||
|
u32 tmp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = readw_poll_timeout(phyreg + TH1520_PHY_MSG_STATUS, tmp,
|
||||||
|
!(tmp & TH1520_PHY_MSG_STATUS_EMPTY),
|
||||||
|
TH1520_PHY_MSG_TIMEOUT_US);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
*id = readw(phyreg + TH1520_PHY_MSG_ID);
|
||||||
|
*data = readw(phyreg + TH1520_PHY_MSG_DATA);
|
||||||
|
|
||||||
|
writew(0, phyreg + TH1520_PHY_MSG_ACK);
|
||||||
|
|
||||||
|
ret = readw_poll_timeout(phyreg + TH1520_PHY_MSG_STATUS, tmp,
|
||||||
|
tmp & TH1520_PHY_MSG_STATUS_EMPTY,
|
||||||
|
TH1520_PHY_MSG_TIMEOUT_US);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
writew(TH1520_PHY_MSG_ACK_EN, phyreg + TH1520_PHY_MSG_ACK);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int th1520_phy_wait_pmu_completion(void __iomem *phyreg)
|
||||||
|
{
|
||||||
|
u16 id, data;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = th1520_ddr_read_msg(phyreg, &id, &data);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
} while (id != TH1520_PHY_MSG_ID_COMPLETION &&
|
||||||
|
id != TH1520_PHY_MSG_ID_ERROR &&
|
||||||
|
!ret);
|
||||||
|
|
||||||
|
return id == TH1520_PHY_MSG_ID_COMPLETION ? ret : -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lpddr4_load_firmware(struct th1520_ddr_priv *priv,
|
||||||
|
struct th1520_ddr_fw *fw)
|
||||||
|
{
|
||||||
|
union th1520_ddr_cfg *cfg;
|
||||||
|
size_t i, j;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for (cfg = fw->cfgs, i = 0; i < fw->cfgnum; i++) {
|
||||||
|
u32 addr = FIELD_GET(TH1520_DDR_CFG_ADDR, cfg->opaddr) * 2;
|
||||||
|
u32 op = FIELD_GET(TH1520_DDR_CFG_OP, cfg->opaddr);
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case TH1520_DDR_CFG_PHY0:
|
||||||
|
writew(cfg->phy.data, priv->phy0 + addr);
|
||||||
|
break;
|
||||||
|
case TH1520_DDR_CFG_PHY1:
|
||||||
|
writew(cfg->phy.data, priv->phy1 + addr);
|
||||||
|
break;
|
||||||
|
case TH1520_DDR_CFG_PHY:
|
||||||
|
writew(cfg->phy.data, priv->phy0 + addr);
|
||||||
|
writew(cfg->phy.data, priv->phy1 + addr);
|
||||||
|
break;
|
||||||
|
case TH1520_DDR_CFG_RANGE:
|
||||||
|
for (j = 0; j < cfg->range.num; j++) {
|
||||||
|
writew(cfg->range.data[j],
|
||||||
|
priv->phy0 + addr + j * 2);
|
||||||
|
writew(cfg->range.data[j],
|
||||||
|
priv->phy1 + addr + j * 2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TH1520_DDR_CFG_WAITFW0:
|
||||||
|
ret = th1520_phy_wait_pmu_completion(priv->phy0);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
pr_err("phy 0 training failed: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case TH1520_DDR_CFG_WAITFW1:
|
||||||
|
ret = th1520_phy_wait_pmu_completion(priv->phy1);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
pr_err("phy 1 training failed: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pr_err("Unknown DRAM configuration %d\n", op);
|
||||||
|
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op == TH1520_DDR_CFG_RANGE)
|
||||||
|
cfg = (void *)cfg + sizeof(cfg->range) +
|
||||||
|
cfg->range.num * sizeof(u16);
|
||||||
|
else
|
||||||
|
cfg = (union th1520_ddr_cfg *)(&cfg->phy + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int th1520_ddr_ctrl_enable(void __iomem *ctrlreg,
|
||||||
|
struct th1520_ddr_fw *fw)
|
||||||
|
{
|
||||||
|
u32 tmp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
writel(0x00000030, ctrlreg + TH1520_CTRL_DFIMISC);
|
||||||
|
|
||||||
|
ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_DFISTAT, tmp,
|
||||||
|
tmp == 0x00000001,
|
||||||
|
TH1520_CTRL_INIT_TIMEOUT_US);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_DCH1_DFISTAT, tmp,
|
||||||
|
tmp == 0x00000001,
|
||||||
|
TH1520_CTRL_INIT_TIMEOUT_US);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
writel(0x00000010, ctrlreg + TH1520_CTRL_DFIMISC);
|
||||||
|
writel(0x00000011, ctrlreg + TH1520_CTRL_DFIMISC);
|
||||||
|
writel(0x0000000a, ctrlreg + TH1520_CTRL_PWRCTL);
|
||||||
|
writel(0x0000000a, ctrlreg + TH1520_CTRL_DCH1_PWRCTL);
|
||||||
|
writel(0x00000001, ctrlreg + TH1520_CTRL_SWCTL);
|
||||||
|
|
||||||
|
ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_SWSTAT, tmp,
|
||||||
|
tmp == 0x00000001,
|
||||||
|
TH1520_CTRL_INIT_TIMEOUT_US);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_STAT, tmp,
|
||||||
|
tmp == 0x00000001,
|
||||||
|
TH1520_CTRL_INIT_TIMEOUT_US);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_DCH1_STAT, tmp,
|
||||||
|
tmp == 0x00000001,
|
||||||
|
TH1520_CTRL_INIT_TIMEOUT_US);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
writel(0x14000001, ctrlreg + TH1520_CTRL_DFIPHYMSTR);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_SWCTL);
|
||||||
|
writel(0x00020002, ctrlreg + TH1520_CTRL_INIT0);
|
||||||
|
writel(0x00000001, ctrlreg + TH1520_CTRL_SWCTL);
|
||||||
|
|
||||||
|
ret = readl_poll_timeout(ctrlreg + TH1520_CTRL_SWSTAT, tmp,
|
||||||
|
tmp == 0x00000001,
|
||||||
|
TH1520_CTRL_INIT_TIMEOUT_US);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_DBG1);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_DCH1_DBG1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void th1520_ddr_enable_self_refresh(void __iomem *ctrlreg,
|
||||||
|
void __iomem *sysreg)
|
||||||
|
{
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_RFSHCTL3);
|
||||||
|
|
||||||
|
writel(0x000a0000, sysreg + TH1520_SYS_DDR_CFG1);
|
||||||
|
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_SWCTL);
|
||||||
|
writel(0x00000001, ctrlreg + TH1520_CTRL_SWCTLSTATIC);
|
||||||
|
writel(0x0040ae04, ctrlreg + TH1520_CTRL_PWRTMG);
|
||||||
|
writel(0x00430003, ctrlreg + TH1520_CTRL_HWLPCTL);
|
||||||
|
writel(0x00430003, ctrlreg + TH1520_CTRL_DCH1_HWLPCTL);
|
||||||
|
writel(0x00000001, ctrlreg + TH1520_CTRL_SWCTL);
|
||||||
|
writel(0x00000000, ctrlreg + TH1520_CTRL_SWCTLSTATIC);
|
||||||
|
writel(0x0000000b, ctrlreg + TH1520_CTRL_PWRCTL);
|
||||||
|
writel(0x0000000b, ctrlreg + TH1520_CTRL_DCH1_PWRCTL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int th1520_ddr_init(struct th1520_ddr_priv *priv)
|
||||||
|
{
|
||||||
|
struct th1520_ddr_fw *fw = (void *)binman_sym(ulong, ddr_fw, image_pos);
|
||||||
|
u32 reset;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = th1520_ddr_pll_config(priv->sys, fw->freq);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("failed to configure PLL: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset = TH1520_SYS_DDR_CFG0_PHY_PWROK_RSTN;
|
||||||
|
writel(reset, priv->sys + TH1520_SYS_DDR_CFG0);
|
||||||
|
reset |= TH1520_SYS_DDR_CFG0_PHY_CORE_RSTN;
|
||||||
|
writel(reset, priv->sys + TH1520_SYS_DDR_CFG0);
|
||||||
|
reset |= TH1520_SYS_DDR_CFG0_APB_RSTN;
|
||||||
|
writel(reset, priv->sys + TH1520_SYS_DDR_CFG0);
|
||||||
|
|
||||||
|
ret = th1520_ddr_ctrl_init(priv->ctrl, fw);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("failed to initialize DDR controller: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset |= TH1520_SYS_DDR_CFG0_APB_PORT_RSTN(0) |
|
||||||
|
TH1520_SYS_DDR_CFG0_APB_PORT_RSTN(1) |
|
||||||
|
TH1520_SYS_DDR_CFG0_APB_PORT_RSTN(2) |
|
||||||
|
TH1520_SYS_DDR_CFG0_APB_PORT_RSTN(3) |
|
||||||
|
TH1520_SYS_DDR_CFG0_APB_PORT_RSTN(4) |
|
||||||
|
TH1520_SYS_DDR_CFG0_CTRL_RSTN;
|
||||||
|
writel(reset, priv->sys + TH1520_SYS_DDR_CFG0);
|
||||||
|
|
||||||
|
lpddr4_load_firmware(priv, fw);
|
||||||
|
|
||||||
|
ret = th1520_ddr_ctrl_enable(priv->ctrl, fw);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("failed to enable DDR controller: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
th1520_ddr_enable_self_refresh(priv->ctrl, priv->sys);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int th1520_ddr_probe(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct th1520_ddr_priv *priv = dev_get_priv(dev);
|
||||||
|
fdt_addr_t addr;
|
||||||
|
|
||||||
|
addr = dev_read_addr_name(dev, "phy-0");
|
||||||
|
priv->phy0 = (void __iomem *)addr;
|
||||||
|
if (addr == FDT_ADDR_T_NONE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
addr = dev_read_addr_name(dev, "phy-1");
|
||||||
|
priv->phy1 = (void __iomem *)addr;
|
||||||
|
if (addr == FDT_ADDR_T_NONE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
addr = dev_read_addr_name(dev, "ctrl");
|
||||||
|
priv->ctrl = (void __iomem *)addr;
|
||||||
|
if (addr == FDT_ADDR_T_NONE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
addr = dev_read_addr_name(dev, "sys");
|
||||||
|
priv->sys = (void __iomem *)addr;
|
||||||
|
if (addr == FDT_ADDR_T_NONE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return th1520_ddr_init(priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int th1520_ddr_get_info(struct udevice *dev, struct ram_info *info)
|
||||||
|
{
|
||||||
|
info->base = gd->ram_base;
|
||||||
|
info->size = gd->ram_size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ram_ops th1520_ddr_ops = {
|
||||||
|
.get_info = th1520_ddr_get_info,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct udevice_id th1520_ddr_ids[] = {
|
||||||
|
{ .compatible = "thead,th1520-ddrc" },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(th1520_ddr) = {
|
||||||
|
.name = "th1520_ddr",
|
||||||
|
.id = UCLASS_RAM,
|
||||||
|
.ops = &th1520_ddr_ops,
|
||||||
|
.of_match = th1520_ddr_ids,
|
||||||
|
.probe = th1520_ddr_probe,
|
||||||
|
.priv_auto = sizeof(struct th1520_ddr_priv),
|
||||||
|
};
|
@@ -39,4 +39,6 @@
|
|||||||
"partitions=" PARTS_DEFAULT "\0" \
|
"partitions=" PARTS_DEFAULT "\0" \
|
||||||
"fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0"
|
"fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0"
|
||||||
|
|
||||||
|
#define CFG_SYS_NS16550_CLK 24000000
|
||||||
|
|
||||||
#endif /* _STARFIVE_VISIONFIVE2_H */
|
#endif /* _STARFIVE_VISIONFIVE2_H */
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <linux/sizes.h>
|
#include <linux/sizes.h>
|
||||||
|
|
||||||
|
#define CFG_SYS_NS16550_CLK 100000000
|
||||||
#define CFG_SYS_SDRAM_BASE 0x00000000
|
#define CFG_SYS_SDRAM_BASE 0x00000000
|
||||||
|
|
||||||
#define UART_BASE 0xffe7014000
|
#define UART_BASE 0xffe7014000
|
||||||
|
@@ -138,7 +138,8 @@ enum {
|
|||||||
IH_ARCH_ARC, /* Synopsys DesignWare ARC */
|
IH_ARCH_ARC, /* Synopsys DesignWare ARC */
|
||||||
IH_ARCH_X86_64, /* AMD x86_64, Intel and Via */
|
IH_ARCH_X86_64, /* AMD x86_64, Intel and Via */
|
||||||
IH_ARCH_XTENSA, /* Xtensa */
|
IH_ARCH_XTENSA, /* Xtensa */
|
||||||
IH_ARCH_RISCV, /* RISC-V */
|
IH_ARCH_RISCV, /* RISC-V 32 bit*/
|
||||||
|
IH_ARCH_RISCV64, /* RISC-V 64 bit*/
|
||||||
|
|
||||||
IH_ARCH_COUNT,
|
IH_ARCH_COUNT,
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user