mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 15:41:40 +00:00
Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-riscv
- Add ethernet driver for StarFive JH7110 SoC - Add ACLINT mtimer and mswi devices support - Add Lichee PI 4A board
This commit is contained in:
commit
bf5152d010
54 changed files with 2578 additions and 188 deletions
|
@ -1330,7 +1330,7 @@ F: doc/arch/riscv.rst
|
|||
F: doc/usage/sbi.rst
|
||||
F: drivers/sysreset/sysreset_sbi.c
|
||||
F: drivers/timer/andes_plmt_timer.c
|
||||
F: drivers/timer/sifive_clint_timer.c
|
||||
F: drivers/timer/riscv_aclint_timer.c
|
||||
F: tools/prelink-riscv.c
|
||||
|
||||
RISC-V CANAAN KENDRYTE K210
|
||||
|
|
|
@ -27,6 +27,10 @@ config TARGET_SIFIVE_UNMATCHED
|
|||
config TARGET_STARFIVE_VISIONFIVE2
|
||||
bool "Support StarFive VisionFive2 Board"
|
||||
|
||||
config TARGET_TH1520_LPI4A
|
||||
bool "Support Sipeed's TH1520 Lichee PI 4A Board"
|
||||
select SYS_CACHE_SHIFT_6
|
||||
|
||||
config TARGET_SIPEED_MAIX
|
||||
bool "Support Sipeed Maix Board"
|
||||
select SYS_CACHE_SHIFT_6
|
||||
|
@ -66,6 +70,7 @@ source "board/emulation/qemu-riscv/Kconfig"
|
|||
source "board/microchip/mpfs_icicle/Kconfig"
|
||||
source "board/sifive/unleashed/Kconfig"
|
||||
source "board/sifive/unmatched/Kconfig"
|
||||
source "board/thead/th1520_lpi4a/Kconfig"
|
||||
source "board/openpiton/riscv64/Kconfig"
|
||||
source "board/sipeed/maix/Kconfig"
|
||||
source "board/starfive/visionfive2/Kconfig"
|
||||
|
@ -185,18 +190,22 @@ config DMA_ADDR_T_64BIT
|
|||
bool
|
||||
default y if 64BIT
|
||||
|
||||
config SIFIVE_CLINT
|
||||
config RISCV_ACLINT
|
||||
bool
|
||||
depends on RISCV_MMODE
|
||||
select REGMAP
|
||||
select SYSCON
|
||||
help
|
||||
The SiFive CLINT block holds memory-mapped control and status registers
|
||||
The RISC-V ACLINT block holds memory-mapped control and status registers
|
||||
associated with software and timer interrupts.
|
||||
|
||||
config SPL_SIFIVE_CLINT
|
||||
config SPL_RISCV_ACLINT
|
||||
bool
|
||||
depends on SPL_RISCV_MMODE
|
||||
select SPL_REGMAP
|
||||
select SPL_SYSCON
|
||||
help
|
||||
The SiFive CLINT block holds memory-mapped control and status registers
|
||||
The RISC-V ACLINT block holds memory-mapped control and status registers
|
||||
associated with software and timer interrupts.
|
||||
|
||||
config SIFIVE_CACHE
|
||||
|
|
|
@ -11,7 +11,7 @@ config SIFIVE_FU540
|
|||
imply CPU
|
||||
imply CPU_RISCV
|
||||
imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE)
|
||||
imply SPL_SIFIVE_CLINT
|
||||
imply SPL_RISCV_ACLINT
|
||||
imply CMD_CPU
|
||||
imply SPL_CPU
|
||||
imply SPL_OPENSBI
|
||||
|
|
|
@ -11,7 +11,7 @@ config SIFIVE_FU740
|
|||
imply CPU
|
||||
imply CPU_RISCV
|
||||
imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE)
|
||||
imply SPL_SIFIVE_CLINT
|
||||
imply SPL_RISCV_ACLINT
|
||||
imply CMD_CPU
|
||||
imply SPL_CPU
|
||||
imply SPL_OPENSBI
|
||||
|
|
|
@ -9,8 +9,8 @@ config GENERIC_RISCV
|
|||
imply CPU
|
||||
imply CPU_RISCV
|
||||
imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE)
|
||||
imply SIFIVE_CLINT if RISCV_MMODE
|
||||
imply SPL_SIFIVE_CLINT if SPL_RISCV_MMODE
|
||||
imply RISCV_ACLINT if RISCV_MMODE
|
||||
imply SPL_RISCV_ACLINT if SPL_RISCV_MMODE
|
||||
imply CMD_CPU
|
||||
imply SPL_CPU
|
||||
imply SPL_OPENSBI
|
||||
|
|
|
@ -25,4 +25,4 @@ config STARFIVE_JH7110
|
|||
imply SPL_CPU
|
||||
imply SPL_LOAD_FIT
|
||||
imply SPL_OPENSBI
|
||||
imply SPL_SIFIVE_CLINT
|
||||
imply SPL_RISCV_ACLINT
|
||||
|
|
|
@ -3,19 +3,49 @@
|
|||
* Copyright (C) 2022 StarFive Technology Co., Ltd.
|
||||
* Author: Yanhong Wang<yanhong.wang@starfivetech.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/eeprom.h>
|
||||
#include <asm/csr.h>
|
||||
#include <asm/sections.h>
|
||||
#include <dm.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <log.h>
|
||||
#include <init.h>
|
||||
|
||||
#define CSR_U74_FEATURE_DISABLE 0x7c1
|
||||
#define L2_LIM_MEM_END 0x81FFFFFUL
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static bool check_ddr_size(phys_size_t size)
|
||||
{
|
||||
switch (size) {
|
||||
case SZ_2:
|
||||
case SZ_4:
|
||||
case SZ_8:
|
||||
case SZ_16:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int spl_soc_init(void)
|
||||
{
|
||||
int ret;
|
||||
struct udevice *dev;
|
||||
phys_size_t size;
|
||||
|
||||
ret = fdtdec_setup_mem_size_base();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Read the definition of the DDR size from eeprom, and if not,
|
||||
* use the definition in DT
|
||||
*/
|
||||
size = (get_ddr_size_from_eeprom() >> 16) & 0xFF;
|
||||
if (check_ddr_size(size))
|
||||
gd->ram_size = size << 30;
|
||||
|
||||
/* DDR init */
|
||||
ret = uclass_get_device(UCLASS_RAM, 0, &dev);
|
||||
|
|
|
@ -7,8 +7,8 @@ dtb-$(CONFIG_TARGET_OPENPITON_RISCV64) += openpiton-riscv64.dtb
|
|||
dtb-$(CONFIG_TARGET_SIFIVE_UNLEASHED) += hifive-unleashed-a00.dtb
|
||||
dtb-$(CONFIG_TARGET_SIFIVE_UNMATCHED) += hifive-unmatched-a00.dtb
|
||||
dtb-$(CONFIG_TARGET_SIPEED_MAIX) += k210-maix-bit.dtb
|
||||
dtb-$(CONFIG_TARGET_STARFIVE_VISIONFIVE2) += jh7110-starfive-visionfive-2-v1.3b.dtb
|
||||
dtb-$(CONFIG_TARGET_STARFIVE_VISIONFIVE2) += jh7110-starfive-visionfive-2-v1.2a.dtb
|
||||
dtb-$(CONFIG_TARGET_STARFIVE_VISIONFIVE2) += jh7110-starfive-visionfive-2.dtb
|
||||
dtb-$(CONFIG_TARGET_TH1520_LPI4A) += th1520-lichee-pi-4a.dtb
|
||||
include $(srctree)/scripts/Makefile.dts
|
||||
|
||||
targets += $(dtb-y)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR MIT
|
||||
/*
|
||||
* Copyright (C) 2022 StarFive Technology Co., Ltd.
|
||||
* Copyright (C) 2023 StarFive Technology Co., Ltd.
|
||||
*/
|
||||
|
||||
#include "binman.dtsi"
|
||||
|
@ -67,3 +67,40 @@
|
|||
};
|
||||
};
|
||||
|
||||
&i2c5_pins {
|
||||
bootph-pre-ram;
|
||||
i2c-pins {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c5 {
|
||||
bootph-pre-ram;
|
||||
eeprom@50 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
};
|
||||
|
||||
&binman {
|
||||
itb {
|
||||
fit {
|
||||
images {
|
||||
fdt-1 {
|
||||
description = "NAME";
|
||||
load = <0x40400000>;
|
||||
compression = "none";
|
||||
|
||||
uboot_fdt_blob: blob-ext {
|
||||
filename = "u-boot.dtb";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
configurations {
|
||||
conf-1 {
|
||||
fdt = "fdt-1";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -1,12 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR MIT
|
||||
/*
|
||||
* Copyright (C) 2022 StarFive Technology Co., Ltd.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
#include "jh7110-starfive-visionfive-2.dtsi"
|
||||
|
||||
/ {
|
||||
model = "StarFive VisionFive 2 v1.2A";
|
||||
compatible = "starfive,visionfive-2-v1.2a", "starfive,jh7110";
|
||||
};
|
|
@ -1,69 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR MIT
|
||||
/*
|
||||
* Copyright (C) 2022 StarFive Technology Co., Ltd.
|
||||
*/
|
||||
|
||||
#include "binman.dtsi"
|
||||
#include "jh7110-u-boot.dtsi"
|
||||
/ {
|
||||
chosen {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
firmware {
|
||||
spi0 = &qspi;
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
config {
|
||||
bootph-pre-ram;
|
||||
u-boot,spl-payload-offset = <0x100000>;
|
||||
};
|
||||
|
||||
memory@40000000 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&mmc0 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&mmc1 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&qspi {
|
||||
bootph-pre-ram;
|
||||
|
||||
nor-flash@0 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
};
|
||||
|
||||
&sysgpio {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
&mmc0_pins {
|
||||
bootph-pre-ram;
|
||||
mmc0-pins-rest {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
};
|
||||
|
||||
&mmc1_pins {
|
||||
bootph-pre-ram;
|
||||
mmc1-pins0 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
|
||||
mmc1-pins1 {
|
||||
bootph-pre-ram;
|
||||
};
|
||||
};
|
||||
|
|
@ -1,12 +1,11 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR MIT
|
||||
/*
|
||||
* Copyright (C) 2022 StarFive Technology Co., Ltd.
|
||||
* Copyright (C) 2023 StarFive Technology Co., Ltd.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
#include "jh7110-starfive-visionfive-2.dtsi"
|
||||
|
||||
/ {
|
||||
model = "StarFive VisionFive 2 v1.3B";
|
||||
compatible = "starfive,visionfive-2-v1.3b", "starfive,jh7110";
|
||||
};
|
|
@ -17,6 +17,8 @@
|
|||
i2c2 = &i2c2;
|
||||
i2c5 = &i2c5;
|
||||
i2c6 = &i2c6;
|
||||
ethernet0 = &gmac0;
|
||||
ethernet1 = &gmac1;
|
||||
};
|
||||
|
||||
chosen {
|
||||
|
@ -118,6 +120,12 @@
|
|||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c5_pins>;
|
||||
status = "okay";
|
||||
|
||||
eeprom@50 {
|
||||
compatible = "atmel,24c04";
|
||||
reg = <0x50>;
|
||||
pagesize = <16>;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c6 {
|
||||
|
@ -317,3 +325,35 @@
|
|||
assigned-clock-parents = <&osc>;
|
||||
assigned-clock-rates = <0>;
|
||||
};
|
||||
|
||||
&gmac0 {
|
||||
phy-handle = <&phy0>;
|
||||
phy-mode = "rgmii-id";
|
||||
status = "okay";
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "snps,dwmac-mdio";
|
||||
|
||||
phy0: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&gmac1 {
|
||||
phy-handle = <&phy1>;
|
||||
phy-mode = "rgmii-id";
|
||||
status = "okay";
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "snps,dwmac-mdio";
|
||||
|
||||
phy1: ethernet-phy@1 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -235,6 +235,13 @@
|
|||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
stmmac_axi_setup: stmmac-axi-config {
|
||||
snps,lpi_en;
|
||||
snps,wr_osr_lmt = <4>;
|
||||
snps,rd_osr_lmt = <4>;
|
||||
snps,blen = <256 128 64 32 0 0 0>;
|
||||
};
|
||||
|
||||
soc {
|
||||
compatible = "simple-bus";
|
||||
interrupt-parent = <&plic>;
|
||||
|
@ -539,6 +546,68 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
gmac0: ethernet@16030000 {
|
||||
compatible = "starfive,jh7110-dwmac", "snps,dwmac-5.20";
|
||||
reg = <0x0 0x16030000 0x0 0x10000>;
|
||||
clocks = <&aoncrg JH7110_AONCLK_GMAC0_AXI>,
|
||||
<&aoncrg JH7110_AONCLK_GMAC0_AHB>,
|
||||
<&syscrg JH7110_SYSCLK_GMAC0_PTP>,
|
||||
<&aoncrg JH7110_AONCLK_GMAC0_TX_INV>,
|
||||
<&syscrg JH7110_SYSCLK_GMAC0_GTXC>;
|
||||
clock-names = "stmmaceth", "pclk", "ptp_ref",
|
||||
"tx", "gtx";
|
||||
resets = <&aoncrg JH7110_AONRST_GMAC0_AXI>,
|
||||
<&aoncrg JH7110_AONRST_GMAC0_AHB>;
|
||||
reset-names = "stmmaceth", "ahb";
|
||||
interrupts = <7>, <6>, <5>;
|
||||
interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
|
||||
snps,multicast-filter-bins = <64>;
|
||||
snps,perfect-filter-entries = <8>;
|
||||
rx-fifo-depth = <2048>;
|
||||
tx-fifo-depth = <2048>;
|
||||
snps,fixed-burst;
|
||||
snps,no-pbl-x8;
|
||||
snps,force_thresh_dma_mode;
|
||||
snps,axi-config = <&stmmac_axi_setup>;
|
||||
snps,tso;
|
||||
snps,en-tx-lpi-clockgating;
|
||||
snps,txpbl = <16>;
|
||||
snps,rxpbl = <16>;
|
||||
starfive,syscon = <&aon_syscon 0xc 0x12>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gmac1: ethernet@16040000 {
|
||||
compatible = "starfive,jh7110-dwmac", "snps,dwmac-5.20";
|
||||
reg = <0x0 0x16040000 0x0 0x10000>;
|
||||
clocks = <&syscrg JH7110_SYSCLK_GMAC1_AXI>,
|
||||
<&syscrg JH7110_SYSCLK_GMAC1_AHB>,
|
||||
<&syscrg JH7110_SYSCLK_GMAC1_PTP>,
|
||||
<&syscrg JH7110_SYSCLK_GMAC1_TX_INV>,
|
||||
<&syscrg JH7110_SYSCLK_GMAC1_GTXC>;
|
||||
clock-names = "stmmaceth", "pclk", "ptp_ref",
|
||||
"tx", "gtx";
|
||||
resets = <&syscrg JH7110_SYSRST_GMAC1_AXI>,
|
||||
<&syscrg JH7110_SYSRST_GMAC1_AHB>;
|
||||
reset-names = "stmmaceth", "ahb";
|
||||
interrupts = <78>, <77>, <76>;
|
||||
interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
|
||||
snps,multicast-filter-bins = <64>;
|
||||
snps,perfect-filter-entries = <8>;
|
||||
rx-fifo-depth = <2048>;
|
||||
tx-fifo-depth = <2048>;
|
||||
snps,fixed-burst;
|
||||
snps,no-pbl-x8;
|
||||
snps,force_thresh_dma_mode;
|
||||
snps,axi-config = <&stmmac_axi_setup>;
|
||||
snps,tso;
|
||||
snps,en-tx-lpi-clockgating;
|
||||
snps,txpbl = <16>;
|
||||
snps,rxpbl = <16>;
|
||||
starfive,syscon = <&sys_syscon 0x90 0x2>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
aoncrg: clock-controller@17000000 {
|
||||
compatible = "starfive,jh7110-aoncrg";
|
||||
reg = <0x0 0x17000000 0x0 0x10000>;
|
||||
|
|
34
arch/riscv/dts/th1520-lichee-module-4a.dtsi
Normal file
34
arch/riscv/dts/th1520-lichee-module-4a.dtsi
Normal file
|
@ -0,0 +1,34 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org>
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "th1520.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Sipeed Lichee Module 4A";
|
||||
compatible = "sipeed,lichee-module-4a", "thead,th1520";
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x00000000 0x2 0x00000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&osc {
|
||||
clock-frequency = <24000000>;
|
||||
};
|
||||
|
||||
&osc_32k {
|
||||
clock-frequency = <32768>;
|
||||
};
|
||||
|
||||
&apb_clk {
|
||||
clock-frequency = <62500000>;
|
||||
};
|
||||
|
||||
&uart_sclk {
|
||||
clock-frequency = <100000000>;
|
||||
};
|
32
arch/riscv/dts/th1520-lichee-pi-4a.dts
Normal file
32
arch/riscv/dts/th1520-lichee-pi-4a.dts
Normal file
|
@ -0,0 +1,32 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org>
|
||||
*/
|
||||
|
||||
#include "th1520-lichee-module-4a.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Sipeed Lichee Pi 4A";
|
||||
compatible = "sipeed,lichee-pi-4a", "sipeed,lichee-module-4a", "thead,th1520";
|
||||
|
||||
aliases {
|
||||
gpio0 = &gpio0;
|
||||
gpio1 = &gpio1;
|
||||
gpio2 = &gpio2;
|
||||
gpio3 = &gpio3;
|
||||
serial0 = &uart0;
|
||||
serial1 = &uart1;
|
||||
serial2 = &uart2;
|
||||
serial3 = &uart3;
|
||||
serial4 = &uart4;
|
||||
serial5 = &uart5;
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
status = "okay";
|
||||
};
|
406
arch/riscv/dts/th1520.dtsi
Normal file
406
arch/riscv/dts/th1520.dtsi
Normal file
|
@ -0,0 +1,406 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2021 Alibaba Group Holding Limited.
|
||||
* Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org>
|
||||
*/
|
||||
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
/ {
|
||||
compatible = "thead,th1520";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
cpus: cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
timebase-frequency = <3000000>;
|
||||
|
||||
c910_0: cpu@0 {
|
||||
compatible = "thead,c910", "riscv";
|
||||
device_type = "cpu";
|
||||
riscv,isa = "rv64imafdc";
|
||||
reg = <0>;
|
||||
i-cache-block-size = <64>;
|
||||
i-cache-size = <65536>;
|
||||
i-cache-sets = <512>;
|
||||
d-cache-block-size = <64>;
|
||||
d-cache-size = <65536>;
|
||||
d-cache-sets = <512>;
|
||||
next-level-cache = <&l2_cache>;
|
||||
mmu-type = "riscv,sv39";
|
||||
|
||||
cpu0_intc: interrupt-controller {
|
||||
compatible = "riscv,cpu-intc";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
c910_1: cpu@1 {
|
||||
compatible = "thead,c910", "riscv";
|
||||
device_type = "cpu";
|
||||
riscv,isa = "rv64imafdc";
|
||||
reg = <1>;
|
||||
i-cache-block-size = <64>;
|
||||
i-cache-size = <65536>;
|
||||
i-cache-sets = <512>;
|
||||
d-cache-block-size = <64>;
|
||||
d-cache-size = <65536>;
|
||||
d-cache-sets = <512>;
|
||||
next-level-cache = <&l2_cache>;
|
||||
mmu-type = "riscv,sv39";
|
||||
|
||||
cpu1_intc: interrupt-controller {
|
||||
compatible = "riscv,cpu-intc";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
c910_2: cpu@2 {
|
||||
compatible = "thead,c910", "riscv";
|
||||
device_type = "cpu";
|
||||
riscv,isa = "rv64imafdc";
|
||||
reg = <2>;
|
||||
i-cache-block-size = <64>;
|
||||
i-cache-size = <65536>;
|
||||
i-cache-sets = <512>;
|
||||
d-cache-block-size = <64>;
|
||||
d-cache-size = <65536>;
|
||||
d-cache-sets = <512>;
|
||||
next-level-cache = <&l2_cache>;
|
||||
mmu-type = "riscv,sv39";
|
||||
|
||||
cpu2_intc: interrupt-controller {
|
||||
compatible = "riscv,cpu-intc";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
c910_3: cpu@3 {
|
||||
compatible = "thead,c910", "riscv";
|
||||
device_type = "cpu";
|
||||
riscv,isa = "rv64imafdc";
|
||||
reg = <3>;
|
||||
i-cache-block-size = <64>;
|
||||
i-cache-size = <65536>;
|
||||
i-cache-sets = <512>;
|
||||
d-cache-block-size = <64>;
|
||||
d-cache-size = <65536>;
|
||||
d-cache-sets = <512>;
|
||||
next-level-cache = <&l2_cache>;
|
||||
mmu-type = "riscv,sv39";
|
||||
|
||||
cpu3_intc: interrupt-controller {
|
||||
compatible = "riscv,cpu-intc";
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
l2_cache: l2-cache {
|
||||
compatible = "cache";
|
||||
cache-block-size = <64>;
|
||||
cache-level = <2>;
|
||||
cache-size = <1048576>;
|
||||
cache-sets = <1024>;
|
||||
cache-unified;
|
||||
};
|
||||
};
|
||||
|
||||
osc: oscillator {
|
||||
compatible = "fixed-clock";
|
||||
clock-output-names = "osc_24m";
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
osc_32k: 32k-oscillator {
|
||||
compatible = "fixed-clock";
|
||||
clock-output-names = "osc_32k";
|
||||
#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>;
|
||||
};
|
||||
|
||||
soc {
|
||||
compatible = "simple-bus";
|
||||
interrupt-parent = <&plic>;
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
plic: interrupt-controller@ffd8000000 {
|
||||
compatible = "thead,th1520-plic", "thead,c900-plic";
|
||||
reg = <0xff 0xd8000000 0x0 0x01000000>;
|
||||
interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>,
|
||||
<&cpu1_intc 11>, <&cpu1_intc 9>,
|
||||
<&cpu2_intc 11>, <&cpu2_intc 9>,
|
||||
<&cpu3_intc 11>, <&cpu3_intc 9>;
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
riscv,ndev = <240>;
|
||||
};
|
||||
|
||||
clint: timer@ffdc000000 {
|
||||
compatible = "thead,th1520-clint", "thead,c900-clint";
|
||||
reg = <0xff 0xdc000000 0x0 0x00010000>;
|
||||
interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>,
|
||||
<&cpu1_intc 3>, <&cpu1_intc 7>,
|
||||
<&cpu2_intc 3>, <&cpu2_intc 7>,
|
||||
<&cpu3_intc 3>, <&cpu3_intc 7>;
|
||||
};
|
||||
|
||||
uart0: serial@ffe7014000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
reg = <0xff 0xe7014000 0x0 0x100>;
|
||||
interrupts = <36 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&uart_sclk>;
|
||||
reg-shift = <2>;
|
||||
reg-io-width = <4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart1: serial@ffe7f00000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
reg = <0xff 0xe7f00000 0x0 0x100>;
|
||||
interrupts = <37 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&uart_sclk>;
|
||||
reg-shift = <2>;
|
||||
reg-io-width = <4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart3: serial@ffe7f04000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
reg = <0xff 0xe7f04000 0x0 0x100>;
|
||||
interrupts = <39 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&uart_sclk>;
|
||||
reg-shift = <2>;
|
||||
reg-io-width = <4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
gpio2: gpio@ffe7f34000 {
|
||||
compatible = "snps,dw-apb-gpio";
|
||||
reg = <0xff 0xe7f34000 0x0 0x1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
portc: gpio-controller@0 {
|
||||
compatible = "snps,dw-apb-gpio-port";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
ngpios = <32>;
|
||||
reg = <0>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <58 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio3: gpio@ffe7f38000 {
|
||||
compatible = "snps,dw-apb-gpio";
|
||||
reg = <0xff 0xe7f38000 0x0 0x1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
portd: gpio-controller@0 {
|
||||
compatible = "snps,dw-apb-gpio-port";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
ngpios = <32>;
|
||||
reg = <0>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <59 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio0: gpio@ffec005000 {
|
||||
compatible = "snps,dw-apb-gpio";
|
||||
reg = <0xff 0xec005000 0x0 0x1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
porta: gpio-controller@0 {
|
||||
compatible = "snps,dw-apb-gpio-port";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
ngpios = <32>;
|
||||
reg = <0>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <56 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio1: gpio@ffec006000 {
|
||||
compatible = "snps,dw-apb-gpio";
|
||||
reg = <0xff 0xec006000 0x0 0x1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
portb: gpio-controller@0 {
|
||||
compatible = "snps,dw-apb-gpio-port";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
ngpios = <32>;
|
||||
reg = <0>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <57 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
uart2: serial@ffec010000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
reg = <0xff 0xec010000 0x0 0x4000>;
|
||||
interrupts = <38 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&uart_sclk>;
|
||||
reg-shift = <2>;
|
||||
reg-io-width = <4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
timer0: timer@ffefc32000 {
|
||||
compatible = "snps,dw-apb-timer";
|
||||
reg = <0xff 0xefc32000 0x0 0x14>;
|
||||
clocks = <&apb_clk>;
|
||||
clock-names = "timer";
|
||||
interrupts = <16 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
timer1: timer@ffefc32014 {
|
||||
compatible = "snps,dw-apb-timer";
|
||||
reg = <0xff 0xefc32014 0x0 0x14>;
|
||||
clocks = <&apb_clk>;
|
||||
clock-names = "timer";
|
||||
interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
timer2: timer@ffefc32028 {
|
||||
compatible = "snps,dw-apb-timer";
|
||||
reg = <0xff 0xefc32028 0x0 0x14>;
|
||||
clocks = <&apb_clk>;
|
||||
clock-names = "timer";
|
||||
interrupts = <18 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
timer3: timer@ffefc3203c {
|
||||
compatible = "snps,dw-apb-timer";
|
||||
reg = <0xff 0xefc3203c 0x0 0x14>;
|
||||
clocks = <&apb_clk>;
|
||||
clock-names = "timer";
|
||||
interrupts = <19 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart4: serial@fff7f08000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
reg = <0xff 0xf7f08000 0x0 0x4000>;
|
||||
interrupts = <40 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&uart_sclk>;
|
||||
reg-shift = <2>;
|
||||
reg-io-width = <4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart5: serial@fff7f0c000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
reg = <0xff 0xf7f0c000 0x0 0x4000>;
|
||||
interrupts = <41 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&uart_sclk>;
|
||||
reg-shift = <2>;
|
||||
reg-io-width = <4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
timer4: timer@ffffc33000 {
|
||||
compatible = "snps,dw-apb-timer";
|
||||
reg = <0xff 0xffc33000 0x0 0x14>;
|
||||
clocks = <&apb_clk>;
|
||||
clock-names = "timer";
|
||||
interrupts = <20 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
timer5: timer@ffffc33014 {
|
||||
compatible = "snps,dw-apb-timer";
|
||||
reg = <0xff 0xffc33014 0x0 0x14>;
|
||||
clocks = <&apb_clk>;
|
||||
clock-names = "timer";
|
||||
interrupts = <21 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
timer6: timer@ffffc33028 {
|
||||
compatible = "snps,dw-apb-timer";
|
||||
reg = <0xff 0xffc33028 0x0 0x14>;
|
||||
clocks = <&apb_clk>;
|
||||
clock-names = "timer";
|
||||
interrupts = <22 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
timer7: timer@ffffc3303c {
|
||||
compatible = "snps,dw-apb-timer";
|
||||
reg = <0xff 0xffc3303c 0x0 0x14>;
|
||||
clocks = <&apb_clk>;
|
||||
clock-names = "timer";
|
||||
interrupts = <23 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
ao_gpio0: gpio@fffff41000 {
|
||||
compatible = "snps,dw-apb-gpio";
|
||||
reg = <0xff 0xfff41000 0x0 0x1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
porte: gpio-controller@0 {
|
||||
compatible = "snps,dw-apb-gpio-port";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
ngpios = <32>;
|
||||
reg = <0>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <76 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
ao_gpio1: gpio@fffff52000 {
|
||||
compatible = "snps,dw-apb-gpio";
|
||||
reg = <0xff 0xfff52000 0x0 0x1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
portf: gpio-controller@0 {
|
||||
compatible = "snps,dw-apb-gpio-port";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
ngpios = <32>;
|
||||
reg = <0>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <55 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
13
arch/riscv/include/asm/arch-jh7110/eeprom.h
Normal file
13
arch/riscv/include/asm/arch-jh7110/eeprom.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) 2023 StarFive Technology Co., Ltd.
|
||||
* Author: Yanhong Wang<yanhong.wang@starfivetech.com>
|
||||
*/
|
||||
|
||||
#ifndef _ASM_RISCV_EEPROM_H
|
||||
#define _ASM_RISCV_EEPROM_H
|
||||
|
||||
u8 get_pcb_revision_from_eeprom(void);
|
||||
u32 get_ddr_size_from_eeprom(void);
|
||||
|
||||
#endif /* _ASM_RISCV_EEPROM_H */
|
|
@ -18,8 +18,8 @@
|
|||
struct arch_global_data {
|
||||
long boot_hart; /* boot hart id */
|
||||
phys_addr_t firmware_fdt_addr;
|
||||
#if CONFIG_IS_ENABLED(SIFIVE_CLINT)
|
||||
void __iomem *clint; /* clint base address */
|
||||
#if CONFIG_IS_ENABLED(RISCV_ACLINT)
|
||||
void __iomem *aclint; /* aclint base address */
|
||||
#endif
|
||||
#ifdef CONFIG_ANDES_PLICSW
|
||||
void __iomem *plicsw; /* andes plicsw base address */
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*/
|
||||
enum {
|
||||
RISCV_NONE,
|
||||
RISCV_SYSCON_CLINT, /* Core Local Interruptor (CLINT) */
|
||||
RISCV_SYSCON_ACLINT, /* Advanced Core Local Interruptor (ACLINT) */
|
||||
RISCV_SYSCON_PLICSW, /* Andes PLICSW */
|
||||
};
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ obj-$(CONFIG_CMD_GO) += boot.o
|
|||
obj-y += cache.o
|
||||
obj-$(CONFIG_SIFIVE_CACHE) += sifive_cache.o
|
||||
ifeq ($(CONFIG_$(SPL_)RISCV_MMODE),y)
|
||||
obj-$(CONFIG_$(SPL_)SIFIVE_CLINT) += sifive_clint.o
|
||||
obj-$(CONFIG_$(SPL_)RISCV_ACLINT) += aclint_ipi.o
|
||||
obj-$(CONFIG_ANDES_PLICSW) += andes_plicsw.o
|
||||
else
|
||||
obj-$(CONFIG_SBI) += sbi.o
|
||||
|
|
|
@ -10,9 +10,12 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <regmap.h>
|
||||
#include <syscon.h>
|
||||
#include <asm/global_data.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/syscon.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/* MSIP registers */
|
||||
|
@ -26,12 +29,16 @@ int riscv_init_ipi(void)
|
|||
struct udevice *dev;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_TIMER,
|
||||
DM_DRIVER_GET(sifive_clint), &dev);
|
||||
DM_DRIVER_GET(riscv_aclint_timer), &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
gd->arch.clint = dev_read_addr_ptr(dev);
|
||||
if (!gd->arch.clint)
|
||||
if (dev_get_driver_data(dev) != 0)
|
||||
gd->arch.aclint = dev_read_addr_ptr(dev);
|
||||
else
|
||||
gd->arch.aclint = syscon_get_first_range(RISCV_SYSCON_ACLINT);
|
||||
|
||||
if (!gd->arch.aclint)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
|
@ -39,21 +46,33 @@ int riscv_init_ipi(void)
|
|||
|
||||
int riscv_send_ipi(int hart)
|
||||
{
|
||||
writel(1, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
|
||||
writel(1, (void __iomem *)MSIP_REG(gd->arch.aclint, hart));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int riscv_clear_ipi(int hart)
|
||||
{
|
||||
writel(0, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
|
||||
writel(0, (void __iomem *)MSIP_REG(gd->arch.aclint, hart));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int riscv_get_ipi(int hart, int *pending)
|
||||
{
|
||||
*pending = readl((void __iomem *)MSIP_REG(gd->arch.clint, hart));
|
||||
*pending = readl((void __iomem *)MSIP_REG(gd->arch.aclint, hart));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id riscv_aclint_swi_ids[] = {
|
||||
{ .compatible = "riscv,aclint-mswi", .data = RISCV_SYSCON_ACLINT },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(riscv_aclint_swi) = {
|
||||
.name = "riscv_aclint_swi",
|
||||
.id = UCLASS_SYSCON,
|
||||
.of_match = riscv_aclint_swi_ids,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
|
@ -29,7 +29,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
|
|||
select SUPPORT_SPL
|
||||
imply CPU_RISCV
|
||||
imply RISCV_TIMER
|
||||
imply SPL_SIFIVE_CLINT
|
||||
imply SPL_RISCV_ACLINT
|
||||
imply CMD_CPU
|
||||
imply SPL_CPU_SUPPORT
|
||||
imply SPL_SMP
|
||||
|
|
|
@ -34,7 +34,7 @@ config BOARD_SPECIFIC_OPTIONS
|
|||
imply SMP
|
||||
imply DM_SERIAL
|
||||
imply SIFIVE_SERIAL
|
||||
imply SIFIVE_CLINT
|
||||
imply RISCV_ACLINT
|
||||
imply POWER_DOMAIN
|
||||
imply SIMPLE_PM_BUS
|
||||
imply CLK_K210
|
||||
|
|
|
@ -5,3 +5,4 @@
|
|||
|
||||
obj-y := starfive_visionfive2.o
|
||||
obj-$(CONFIG_SPL_BUILD) += spl.o
|
||||
obj-$(CONFIG_ID_EEPROM) += visionfive2-i2c-eeprom.o
|
||||
|
|
|
@ -5,16 +5,173 @@
|
|||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/eeprom.h>
|
||||
#include <asm/arch/regs.h>
|
||||
#include <asm/arch/spl.h>
|
||||
#include <asm/io.h>
|
||||
#include <dt-bindings/clock/starfive,jh7110-crg.h>
|
||||
#include <fdt_support.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <log.h>
|
||||
#include <spl.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
#define JH7110_CLK_CPU_ROOT_OFFSET 0x0U
|
||||
#define JH7110_CLK_CPU_ROOT_SHIFT 24
|
||||
#define JH7110_CLK_CPU_ROOT_MASK GENMASK(29, 24)
|
||||
|
||||
struct starfive_vf2_pro {
|
||||
const char *path;
|
||||
const char *name;
|
||||
const char *value;
|
||||
};
|
||||
|
||||
static const struct starfive_vf2_pro starfive_vera[] = {
|
||||
{"/soc/ethernet@16030000/mdio/ethernet-phy@0", "rx-internal-delay-ps",
|
||||
"1900"},
|
||||
{"/soc/ethernet@16030000/mdio/ethernet-phy@0", "tx-internal-delay-ps",
|
||||
"1350"}
|
||||
};
|
||||
|
||||
static const struct starfive_vf2_pro starfive_verb[] = {
|
||||
{"/soc/ethernet@16030000", "starfive,tx-use-rgmii-clk", NULL},
|
||||
{"/soc/ethernet@16040000", "starfive,tx-use-rgmii-clk", NULL},
|
||||
|
||||
{"/soc/ethernet@16030000/mdio/ethernet-phy@0",
|
||||
"motorcomm,tx-clk-adj-enabled", NULL},
|
||||
{"/soc/ethernet@16030000/mdio/ethernet-phy@0",
|
||||
"motorcomm,tx-clk-100-inverted", NULL},
|
||||
{"/soc/ethernet@16030000/mdio/ethernet-phy@0",
|
||||
"motorcomm,tx-clk-1000-inverted", NULL},
|
||||
{"/soc/ethernet@16030000/mdio/ethernet-phy@0",
|
||||
"rx-internal-delay-ps", "1900"},
|
||||
{"/soc/ethernet@16030000/mdio/ethernet-phy@0",
|
||||
"tx-internal-delay-ps", "1500"},
|
||||
|
||||
{"/soc/ethernet@16040000/mdio/ethernet-phy@1",
|
||||
"motorcomm,tx-clk-adj-enabled", NULL},
|
||||
{ "/soc/ethernet@16040000/mdio/ethernet-phy@1",
|
||||
"motorcomm,tx-clk-100-inverted", NULL},
|
||||
{"/soc/ethernet@16040000/mdio/ethernet-phy@1",
|
||||
"rx-internal-delay-ps", "0"},
|
||||
{"/soc/ethernet@16040000/mdio/ethernet-phy@1",
|
||||
"tx-internal-delay-ps", "0"},
|
||||
};
|
||||
|
||||
void spl_fdt_fixup_version_a(void *fdt)
|
||||
{
|
||||
u32 phandle;
|
||||
u8 i;
|
||||
int offset;
|
||||
int ret;
|
||||
|
||||
fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model",
|
||||
"StarFive VisionFive 2 v1.2A");
|
||||
|
||||
offset = fdt_path_offset(fdt, "/soc/clock-controller@13020000");
|
||||
phandle = fdt_get_phandle(fdt, offset);
|
||||
offset = fdt_path_offset(fdt, "/soc/ethernet@16040000");
|
||||
|
||||
fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle);
|
||||
fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_SYSCLK_GMAC1_TX);
|
||||
fdt_appendprop_u32(fdt, offset, "assigned-clocks", phandle);
|
||||
fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_SYSCLK_GMAC1_RX);
|
||||
|
||||
fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle);
|
||||
fdt_appendprop_u32(fdt, offset, "assigned-clock-parents",
|
||||
JH7110_SYSCLK_GMAC1_RMII_RTX);
|
||||
fdt_appendprop_u32(fdt, offset, "assigned-clock-parents", phandle);
|
||||
fdt_appendprop_u32(fdt, offset, "assigned-clock-parents",
|
||||
JH7110_SYSCLK_GMAC1_RMII_RTX);
|
||||
|
||||
fdt_setprop_string(fdt, fdt_path_offset(fdt, "/soc/ethernet@16040000"),
|
||||
"phy-mode", "rmii");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(starfive_vera); i++) {
|
||||
offset = fdt_path_offset(fdt, starfive_vera[i].path);
|
||||
|
||||
if (starfive_vera[i].value)
|
||||
ret = fdt_setprop_u32(fdt, offset, starfive_vera[i].name,
|
||||
dectoul(starfive_vera[i].value, NULL));
|
||||
else
|
||||
ret = fdt_setprop_empty(fdt, offset, starfive_vera[i].name);
|
||||
|
||||
if (ret) {
|
||||
pr_err("%s set prop %s fail.\n", __func__, starfive_vera[i].name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void spl_fdt_fixup_version_b(void *fdt)
|
||||
{
|
||||
u32 phandle;
|
||||
u8 i;
|
||||
int offset;
|
||||
int ret;
|
||||
|
||||
fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model",
|
||||
"StarFive VisionFive 2 v1.3B");
|
||||
|
||||
/* gmac0 */
|
||||
offset = fdt_path_offset(fdt, "/soc/clock-controller@17000000");
|
||||
phandle = fdt_get_phandle(fdt, offset);
|
||||
offset = fdt_path_offset(fdt, "/soc/ethernet@16030000");
|
||||
|
||||
fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle);
|
||||
fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_AONCLK_GMAC0_TX);
|
||||
fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle);
|
||||
fdt_appendprop_u32(fdt, offset, "assigned-clock-parents",
|
||||
JH7110_AONCLK_GMAC0_RMII_RTX);
|
||||
|
||||
/* gmac1 */
|
||||
offset = fdt_path_offset(fdt, "/soc/clock-controller@13020000");
|
||||
phandle = fdt_get_phandle(fdt, offset);
|
||||
offset = fdt_path_offset(fdt, "/soc/ethernet@16040000");
|
||||
|
||||
fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle);
|
||||
fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_SYSCLK_GMAC1_TX);
|
||||
fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle);
|
||||
fdt_appendprop_u32(fdt, offset, "assigned-clock-parents",
|
||||
JH7110_SYSCLK_GMAC1_RMII_RTX);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(starfive_verb); i++) {
|
||||
offset = fdt_path_offset(fdt, starfive_verb[i].path);
|
||||
|
||||
if (starfive_verb[i].value)
|
||||
ret = fdt_setprop_u32(fdt, offset, starfive_verb[i].name,
|
||||
dectoul(starfive_verb[i].value, NULL));
|
||||
else
|
||||
ret = fdt_setprop_empty(fdt, offset, starfive_verb[i].name);
|
||||
|
||||
if (ret) {
|
||||
pr_err("%s set prop %s fail.\n", __func__, starfive_verb[i].name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void spl_perform_fixups(struct spl_image_info *spl_image)
|
||||
{
|
||||
u8 version;
|
||||
|
||||
version = get_pcb_revision_from_eeprom();
|
||||
switch (version) {
|
||||
case 'a':
|
||||
case 'A':
|
||||
spl_fdt_fixup_version_a(spl_image->fdt_addr);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
case 'B':
|
||||
default:
|
||||
spl_fdt_fixup_version_b(spl_image->fdt_addr);
|
||||
break;
|
||||
};
|
||||
|
||||
/* Update the memory size which read form eeprom or DT */
|
||||
fdt_fixup_memory(spl_image->fdt_addr, 0x40000000, gd->ram_size);
|
||||
}
|
||||
int spl_board_init_f(void)
|
||||
{
|
||||
int ret;
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/sections.h>
|
||||
#include <cpu_func.h>
|
||||
#include <dm.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#define JH7110_L2_PREFETCHER_BASE_ADDR 0x2030000
|
||||
|
@ -38,3 +40,14 @@ int board_init(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *board_fdt_blob_setup(int *err)
|
||||
{
|
||||
*err = 0;
|
||||
if (IS_ENABLED(CONFIG_OF_SEPARATE) || IS_ENABLED(CONFIG_OF_BOARD)) {
|
||||
if (gd->arch.firmware_fdt_addr)
|
||||
return (ulong *)(uintptr_t)gd->arch.firmware_fdt_addr;
|
||||
}
|
||||
|
||||
return (ulong *)&_end;
|
||||
}
|
||||
|
|
561
board/starfive/visionfive2/visionfive2-i2c-eeprom.c
Normal file
561
board/starfive/visionfive2/visionfive2-i2c-eeprom.c
Normal file
|
@ -0,0 +1,561 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2023 StarFive Technology Co., Ltd.
|
||||
* Author: Yanhong Wang<yanhong.wang@starfivetech.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <env.h>
|
||||
#include <i2c.h>
|
||||
#include <init.h>
|
||||
#include <u-boot/crc.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#define FORMAT_VERSION 0x2
|
||||
#define PCB_VERSION 0xB1
|
||||
#define BOM_VERSION 'A'
|
||||
/*
|
||||
* BYTES_PER_EEPROM_PAGE: the 24FC04H datasheet says that data can
|
||||
* only be written in page mode, which means 16 bytes at a time:
|
||||
* 16-Byte Page Write Buffer
|
||||
*/
|
||||
#define BYTES_PER_EEPROM_PAGE 16
|
||||
|
||||
/*
|
||||
* EEPROM_WRITE_DELAY_MS: the 24FC04H datasheet says it takes up to
|
||||
* 5ms to complete a given write:
|
||||
* Write Cycle Time (byte or page) ro Page Write Time 5 ms, Maximum
|
||||
*/
|
||||
#define EEPROM_WRITE_DELAY_MS 5000
|
||||
/*
|
||||
* StarFive OUI. Registration Date is 20xx-xx-xx
|
||||
*/
|
||||
#define STARFIVE_OUI_PREFIX "6C:CF:39:"
|
||||
#define STARFIVE_DEFAULT_MAC0 "6C:CF:39:6C:DE:AD"
|
||||
#define STARFIVE_DEFAULT_MAC1 "6C:CF:39:6C:DE:AE"
|
||||
|
||||
/* Magic number at the first four bytes of EEPROM HATs */
|
||||
#define STARFIVE_EEPROM_HATS_SIG "SFVF" /* StarFive VisionFive */
|
||||
|
||||
#define STARFIVE_EEPROM_HATS_SIZE_MAX 256 /* Header + Atom1&4(v1) */
|
||||
#define STARFIVE_EEPROM_WP_OFFSET 0 /* Read only field */
|
||||
#define STARFIVE_EEPROM_ATOM1_PSTR "VF7110A1-2228-D008E000-00000001\0"
|
||||
#define STARFIVE_EEPROM_ATOM1_PSTR_SIZE 32
|
||||
#define STARFIVE_EEPROM_ATOM1_SN_OFFSET 23
|
||||
#define STARFIVE_EEPROM_ATOM1_VSTR "StarFive Technology Co., Ltd.\0\0\0"
|
||||
#define STARFIVE_EEPROM_ATOM1_VSTR_SIZE 32
|
||||
|
||||
#define MAGIC_NUMBER_BYTES 4
|
||||
#define MAC_ADDR_BYTES 6
|
||||
#define MAC_ADDR_STRLEN 17
|
||||
|
||||
/*
|
||||
* Atom Types
|
||||
* 0x0000 = invalid
|
||||
* 0x0001 = vendor info
|
||||
* 0x0002 = GPIO map
|
||||
* 0x0003 = Linux device tree blob
|
||||
* 0x0004 = manufacturer custom data
|
||||
* 0x0005-0xfffe = reserved for future use
|
||||
* 0xffff = invalid
|
||||
*/
|
||||
|
||||
#define HATS_ATOM_INVALID 0x0000
|
||||
#define HATS_ATOM_VENDOR 0x0001
|
||||
#define HATS_ATOM_GPIO 0x0002
|
||||
#define HATS_ATOM_DTB 0x0003
|
||||
#define HATS_ATOM_CUSTOM 0x0004
|
||||
#define HATS_ATOM_INVALID_END 0xffff
|
||||
|
||||
struct eeprom_header {
|
||||
char signature[MAGIC_NUMBER_BYTES]; /* ASCII table signature */
|
||||
u8 version; /* EEPROM data format version */
|
||||
/* (0x00 reserved, 0x01 = first version) */
|
||||
u8 reversed; /* 0x00, Reserved field */
|
||||
u16 numatoms; /* total atoms in EEPROM */
|
||||
u32 eeplen; /* total length in bytes of all eeprom data */
|
||||
/* (including this header) */
|
||||
};
|
||||
|
||||
struct eeprom_atom_header {
|
||||
u16 type;
|
||||
u16 count;
|
||||
u32 dlen;
|
||||
};
|
||||
|
||||
struct eeprom_atom1_data {
|
||||
u8 uuid[16];
|
||||
u16 pid;
|
||||
u16 pver;
|
||||
u8 vslen;
|
||||
u8 pslen;
|
||||
uchar vstr[STARFIVE_EEPROM_ATOM1_VSTR_SIZE];
|
||||
uchar pstr[STARFIVE_EEPROM_ATOM1_PSTR_SIZE]; /* product SN */
|
||||
};
|
||||
|
||||
struct starfive_eeprom_atom1 {
|
||||
struct eeprom_atom_header header;
|
||||
struct eeprom_atom1_data data;
|
||||
u16 crc;
|
||||
};
|
||||
|
||||
struct eeprom_atom4_data {
|
||||
u16 version;
|
||||
u8 pcb_revision; /* PCB version */
|
||||
u8 bom_revision; /* BOM version */
|
||||
u8 mac0_addr[MAC_ADDR_BYTES]; /* Ethernet0 MAC */
|
||||
u8 mac1_addr[MAC_ADDR_BYTES]; /* Ethernet1 MAC */
|
||||
u8 reserved[2];
|
||||
};
|
||||
|
||||
struct starfive_eeprom_atom4 {
|
||||
struct eeprom_atom_header header;
|
||||
struct eeprom_atom4_data data;
|
||||
u16 crc;
|
||||
};
|
||||
|
||||
struct starfive_eeprom {
|
||||
struct eeprom_header header;
|
||||
struct starfive_eeprom_atom1 atom1;
|
||||
struct starfive_eeprom_atom4 atom4;
|
||||
};
|
||||
|
||||
static union {
|
||||
struct starfive_eeprom eeprom;
|
||||
uchar buf[STARFIVE_EEPROM_HATS_SIZE_MAX];
|
||||
} pbuf __section(".data");
|
||||
|
||||
/* Set to 1 if we've read EEPROM into memory */
|
||||
static int has_been_read __section(".data");
|
||||
|
||||
static inline int is_match_magic(void)
|
||||
{
|
||||
return strncmp(pbuf.eeprom.header.signature, STARFIVE_EEPROM_HATS_SIG,
|
||||
MAGIC_NUMBER_BYTES);
|
||||
}
|
||||
|
||||
/* Calculate the current CRC */
|
||||
static inline u32 calculate_crc16(struct eeprom_atom_header *head)
|
||||
{
|
||||
uint len = sizeof(struct eeprom_atom_header) + head->dlen - sizeof(u16);
|
||||
|
||||
return crc16(0, (void *)head, len);
|
||||
}
|
||||
|
||||
/* This function should be called after each update to the EEPROM structure */
|
||||
static inline void update_crc(void)
|
||||
{
|
||||
pbuf.eeprom.atom1.crc = calculate_crc16(&pbuf.eeprom.atom1.header);
|
||||
pbuf.eeprom.atom4.crc = calculate_crc16(&pbuf.eeprom.atom4.header);
|
||||
}
|
||||
|
||||
static void dump_raw_eeprom(void)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 len;
|
||||
|
||||
len = sizeof(struct starfive_eeprom);
|
||||
for (i = 0; i < len; i++) {
|
||||
if ((i % 16) == 0)
|
||||
printf("%02X: ", i);
|
||||
printf("%02X ", ((u8 *)pbuf.buf)[i]);
|
||||
if (((i % 16) == 15) || (i == len - 1))
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* show_eeprom - display the contents of the EEPROM
|
||||
*/
|
||||
static void show_eeprom(void)
|
||||
{
|
||||
if (has_been_read != 1)
|
||||
return;
|
||||
|
||||
printf("\n--------EEPROM INFO--------\n");
|
||||
printf("Vendor : %s\n", pbuf.eeprom.atom1.data.vstr);
|
||||
printf("Product full SN: %s\n", pbuf.eeprom.atom1.data.pstr);
|
||||
printf("data version: 0x%x\n", pbuf.eeprom.atom4.data.version);
|
||||
if (pbuf.eeprom.atom4.data.version == 2) {
|
||||
printf("PCB revision: 0x%x\n", pbuf.eeprom.atom4.data.pcb_revision);
|
||||
printf("BOM revision: %c\n", pbuf.eeprom.atom4.data.bom_revision);
|
||||
printf("Ethernet MAC0 address: %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
pbuf.eeprom.atom4.data.mac0_addr[0], pbuf.eeprom.atom4.data.mac0_addr[1],
|
||||
pbuf.eeprom.atom4.data.mac0_addr[2], pbuf.eeprom.atom4.data.mac0_addr[3],
|
||||
pbuf.eeprom.atom4.data.mac0_addr[4], pbuf.eeprom.atom4.data.mac0_addr[5]);
|
||||
printf("Ethernet MAC1 address: %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
pbuf.eeprom.atom4.data.mac1_addr[0], pbuf.eeprom.atom4.data.mac1_addr[1],
|
||||
pbuf.eeprom.atom4.data.mac1_addr[2], pbuf.eeprom.atom4.data.mac1_addr[3],
|
||||
pbuf.eeprom.atom4.data.mac1_addr[4], pbuf.eeprom.atom4.data.mac1_addr[5]);
|
||||
} else {
|
||||
printf("Custom data v%d is not Supported\n", pbuf.eeprom.atom4.data.version);
|
||||
}
|
||||
printf("--------EEPROM INFO--------\n\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* set_mac_address() - stores a MAC address into the local EEPROM copy
|
||||
*
|
||||
* This function takes a pointer to MAC address string
|
||||
* (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number),
|
||||
* stores it in the MAC address field of the EEPROM local copy, and
|
||||
* updates the local copy of the CRC.
|
||||
*/
|
||||
static void set_mac_address(char *string, int index)
|
||||
{
|
||||
u8 i;
|
||||
u8 *mac;
|
||||
|
||||
if (strncasecmp(STARFIVE_OUI_PREFIX, string,
|
||||
strlen(STARFIVE_OUI_PREFIX))) {
|
||||
printf("The MAC address doesn't match StarFive OUI %s\n",
|
||||
STARFIVE_OUI_PREFIX);
|
||||
return;
|
||||
}
|
||||
mac = (index == 0) ? pbuf.eeprom.atom4.data.mac0_addr :
|
||||
pbuf.eeprom.atom4.data.mac1_addr;
|
||||
|
||||
for (i = 0; *string && (i < MAC_ADDR_BYTES); i++) {
|
||||
mac[i] = hextoul(string, &string);
|
||||
|
||||
if (*string == ':')
|
||||
string++;
|
||||
}
|
||||
|
||||
update_crc();
|
||||
}
|
||||
|
||||
/**
|
||||
* init_local_copy() - initialize the in-memory EEPROM copy
|
||||
*
|
||||
* Initialize the in-memory EEPROM copy with the magic number. Must
|
||||
* be done when preparing to initialize a blank EEPROM, or overwrite
|
||||
* one with a corrupted magic number.
|
||||
*/
|
||||
static void init_local_copy(void)
|
||||
{
|
||||
memset((void *)pbuf.buf, 0, sizeof(struct starfive_eeprom));
|
||||
memcpy(pbuf.eeprom.header.signature, STARFIVE_EEPROM_HATS_SIG,
|
||||
strlen(STARFIVE_EEPROM_HATS_SIG));
|
||||
pbuf.eeprom.header.version = FORMAT_VERSION;
|
||||
pbuf.eeprom.header.numatoms = 2;
|
||||
pbuf.eeprom.header.eeplen = sizeof(struct starfive_eeprom);
|
||||
|
||||
pbuf.eeprom.atom1.header.type = HATS_ATOM_VENDOR;
|
||||
pbuf.eeprom.atom1.header.count = 1;
|
||||
pbuf.eeprom.atom1.header.dlen = sizeof(struct eeprom_atom1_data) + sizeof(u16);
|
||||
pbuf.eeprom.atom1.data.vslen = STARFIVE_EEPROM_ATOM1_VSTR_SIZE;
|
||||
pbuf.eeprom.atom1.data.pslen = STARFIVE_EEPROM_ATOM1_PSTR_SIZE;
|
||||
memcpy(pbuf.eeprom.atom1.data.vstr, STARFIVE_EEPROM_ATOM1_VSTR,
|
||||
strlen(STARFIVE_EEPROM_ATOM1_VSTR));
|
||||
memcpy(pbuf.eeprom.atom1.data.pstr, STARFIVE_EEPROM_ATOM1_PSTR,
|
||||
strlen(STARFIVE_EEPROM_ATOM1_PSTR));
|
||||
|
||||
pbuf.eeprom.atom4.header.type = HATS_ATOM_CUSTOM;
|
||||
pbuf.eeprom.atom4.header.count = 2;
|
||||
pbuf.eeprom.atom4.header.dlen = sizeof(struct eeprom_atom4_data) + sizeof(u16);
|
||||
pbuf.eeprom.atom4.data.version = FORMAT_VERSION;
|
||||
pbuf.eeprom.atom4.data.pcb_revision = PCB_VERSION;
|
||||
pbuf.eeprom.atom4.data.bom_revision = BOM_VERSION;
|
||||
set_mac_address(STARFIVE_DEFAULT_MAC0, 0);
|
||||
set_mac_address(STARFIVE_DEFAULT_MAC1, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* prog_eeprom() - write the EEPROM from memory
|
||||
*/
|
||||
static int prog_eeprom(unsigned int size)
|
||||
{
|
||||
unsigned int i;
|
||||
void *p;
|
||||
uchar tmp_buff[STARFIVE_EEPROM_HATS_SIZE_MAX];
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
if (is_match_magic()) {
|
||||
printf("MAGIC ERROR, Please check the data@%p.\n", pbuf.buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM,
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR,
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
|
||||
&dev);
|
||||
if (ret) {
|
||||
printf("Get i2c bus:%d addr:%d fail.\n", CONFIG_SYS_EEPROM_BUS_NUM,
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0, p = (u8 *)pbuf.buf; i < size; ) {
|
||||
if (!ret)
|
||||
ret = dm_i2c_write(dev, i, p, min((int)(size - i),
|
||||
BYTES_PER_EEPROM_PAGE));
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
udelay(EEPROM_WRITE_DELAY_MS);
|
||||
i += BYTES_PER_EEPROM_PAGE;
|
||||
p += BYTES_PER_EEPROM_PAGE;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
/* Verify the write by reading back the EEPROM and comparing */
|
||||
ret = dm_i2c_read(dev,
|
||||
STARFIVE_EEPROM_WP_OFFSET,
|
||||
tmp_buff,
|
||||
STARFIVE_EEPROM_HATS_SIZE_MAX);
|
||||
if (!ret && memcmp((void *)pbuf.buf, (void *)tmp_buff,
|
||||
STARFIVE_EEPROM_HATS_SIZE_MAX))
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
has_been_read = -1;
|
||||
printf("Programming failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Programming passed.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* read_eeprom() - read the EEPROM into memory, if it hasn't been read already
|
||||
*/
|
||||
static int read_eeprom(void)
|
||||
{
|
||||
int ret;
|
||||
struct udevice *dev;
|
||||
|
||||
if (has_been_read == 1)
|
||||
return 0;
|
||||
|
||||
ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM,
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR, 1, &dev);
|
||||
if (!ret)
|
||||
ret = dm_i2c_read(dev, 0, (u8 *)pbuf.buf,
|
||||
STARFIVE_EEPROM_HATS_SIZE_MAX);
|
||||
|
||||
has_been_read = (ret == 0) ? 1 : 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_pcb_revision() - stores a StarFive PCB revision into the local EEPROM copy
|
||||
*
|
||||
* Takes a pointer to a string representing the numeric PCB revision in
|
||||
* decimal ("0" - "255"), stores it in the pcb_revision field of the
|
||||
* EEPROM local copy, and updates the CRC of the local copy.
|
||||
*/
|
||||
static void set_pcb_revision(char *string)
|
||||
{
|
||||
u32 p;
|
||||
|
||||
p = simple_strtoul(string, &string, 16);
|
||||
if (p > U8_MAX) {
|
||||
printf("%s must not be greater than %d\n", "PCB revision",
|
||||
U8_MAX);
|
||||
return;
|
||||
}
|
||||
|
||||
pbuf.eeprom.atom4.data.pcb_revision = p;
|
||||
|
||||
update_crc();
|
||||
}
|
||||
|
||||
/**
|
||||
* set_bom_revision() - stores a StarFive BOM revision into the local EEPROM copy
|
||||
*
|
||||
* Takes a pointer to a uppercase ASCII character representing the BOM
|
||||
* revision ("A" - "Z"), stores it in the bom_revision field of the
|
||||
* EEPROM local copy, and updates the CRC of the local copy.
|
||||
*/
|
||||
static void set_bom_revision(char *string)
|
||||
{
|
||||
if (string[0] < 'A' || string[0] > 'Z') {
|
||||
printf("BOM revision must be an uppercase letter between A and Z\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pbuf.eeprom.atom4.data.bom_revision = string[0];
|
||||
|
||||
update_crc();
|
||||
}
|
||||
|
||||
/**
|
||||
* set_product_id() - stores a StarFive product ID into the local EEPROM copy
|
||||
*
|
||||
* Takes a pointer to a string representing the numeric product ID in
|
||||
* string ("VF7100A1-2150-D008E000-00000001\0"), stores it in the product string
|
||||
* field of the EEPROM local copy, and updates the CRC of the local copy.
|
||||
*/
|
||||
static void set_product_id(char *string)
|
||||
{
|
||||
u32 len;
|
||||
|
||||
len = (strlen(string) > STARFIVE_EEPROM_ATOM1_PSTR_SIZE) ?
|
||||
STARFIVE_EEPROM_ATOM1_PSTR_SIZE : strlen(string);
|
||||
|
||||
memcpy((void *)pbuf.eeprom.atom1.data.pstr, (void *)string, len);
|
||||
|
||||
update_crc();
|
||||
}
|
||||
|
||||
static int print_usage(void)
|
||||
{
|
||||
printf("display and program the system ID and MAC addresses in EEPROM\n"
|
||||
"[read_eeprom|initialize|write_eeprom|mac_address|pcb_revision|bom_revision|product_id]\n"
|
||||
"mac read_eeprom\n"
|
||||
" - read EEPROM content into memory data structure\n"
|
||||
"mac write_eeprom\n"
|
||||
" - save memory data structure to the EEPROM\n"
|
||||
"mac initialize\n"
|
||||
" - initialize the in-memory EEPROM copy with default data\n"
|
||||
"mac mac0_address <xx:xx:xx:xx:xx:xx>\n"
|
||||
" - stores a MAC0 address into the local EEPROM copy\n"
|
||||
"mac mac1_address <xx:xx:xx:xx:xx:xx>\n"
|
||||
" - stores a MAC1 address into the local EEPROM copy\n"
|
||||
"mac pcb_revision <?>\n"
|
||||
" - stores a StarFive PCB revision into the local EEPROM copy\n"
|
||||
"mac bom_revision <A>\n"
|
||||
" - stores a StarFive BOM revision into the local EEPROM copy\n"
|
||||
"mac product_id <VF7110A1-2228-D008E000-xxxxxxxx>\n"
|
||||
" - stores a StarFive product ID into the local EEPROM copy\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_mac(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
||||
{
|
||||
char *cmd;
|
||||
|
||||
if (argc == 1) {
|
||||
show_eeprom();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc > 3)
|
||||
return print_usage();
|
||||
|
||||
cmd = argv[1];
|
||||
|
||||
/* Commands with no argument */
|
||||
if (!strcmp(cmd, "read_eeprom")) {
|
||||
has_been_read = 0;
|
||||
return read_eeprom();
|
||||
} else if (!strcmp(cmd, "initialize")) {
|
||||
init_local_copy();
|
||||
return 0;
|
||||
} else if (!strcmp(cmd, "write_eeprom")) {
|
||||
return prog_eeprom(STARFIVE_EEPROM_HATS_SIZE_MAX);
|
||||
}
|
||||
|
||||
if (argc != 3)
|
||||
return print_usage();
|
||||
|
||||
if (is_match_magic()) {
|
||||
printf("Please read the EEPROM ('read_eeprom') and/or initialize the EEPROM ('initialize') first.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(cmd, "mac0_address")) {
|
||||
set_mac_address(argv[2], 0);
|
||||
return 0;
|
||||
} else if (!strcmp(cmd, "mac1_address")) {
|
||||
set_mac_address(argv[2], 1);
|
||||
return 0;
|
||||
} else if (!strcmp(cmd, "pcb_revision")) {
|
||||
set_pcb_revision(argv[2]);
|
||||
return 0;
|
||||
} else if (!strcmp(cmd, "bom_revision")) {
|
||||
set_bom_revision(argv[2]);
|
||||
return 0;
|
||||
} else if (!strcmp(cmd, "product_id")) {
|
||||
set_product_id(argv[2]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return print_usage();
|
||||
}
|
||||
|
||||
/**
|
||||
* mac_read_from_eeprom() - read the MAC address & the serial number in EEPROM
|
||||
*
|
||||
* This function reads the MAC address and the serial number from EEPROM and
|
||||
* sets the appropriate environment variables for each one read.
|
||||
*
|
||||
* The environment variables are only set if they haven't been set already.
|
||||
* This ensures that any user-saved variables are never overwritten.
|
||||
*
|
||||
* If CONFIG_ID_EEPROM is enabled, this function will be called in
|
||||
* "static init_fnc_t init_sequence_r[]" of u-boot/common/board_r.c.
|
||||
*/
|
||||
int mac_read_from_eeprom(void)
|
||||
{
|
||||
/**
|
||||
* try to fill the buff from EEPROM,
|
||||
* always return SUCCESS, even some error happens.
|
||||
*/
|
||||
if (read_eeprom()) {
|
||||
dump_raw_eeprom();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 1, setup ethaddr env
|
||||
eth_env_set_enetaddr("eth0addr", pbuf.eeprom.atom4.data.mac0_addr);
|
||||
eth_env_set_enetaddr("eth1addr", pbuf.eeprom.atom4.data.mac1_addr);
|
||||
|
||||
/**
|
||||
* 2, setup serial# env, reference to hifive-platform-i2c-eeprom.c,
|
||||
* serial# can be a ASCII string, but not just a hex number, so we
|
||||
* setup serial# in the 32Byte format:
|
||||
* "VF7100A1-2201-D008E000-00000001;"
|
||||
* "<product>-<date>-<DDR&eMMC>-<serial_number>"
|
||||
* <date>: 4Byte, should be the output of `date +%y%W`
|
||||
* <DDR&eMMC>: 8Byte, "D008" means 8GB, "D01T" means 1TB;
|
||||
* "E000" means no eMMC,"E032" means 32GB, "E01T" means 1TB.
|
||||
* <serial_number>: 8Byte, the Unique Identifier of board in hex.
|
||||
*/
|
||||
if (!env_get("serial#"))
|
||||
env_set("serial#", pbuf.eeprom.atom1.data.pstr);
|
||||
|
||||
printf("StarFive EEPROM format v%u\n", pbuf.eeprom.header.version);
|
||||
show_eeprom();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_pcb_revision_from_eeprom - get the PCB revision
|
||||
*
|
||||
* 1.2A return 'A'/'a', 1.3B return 'B'/'b',other values are illegal
|
||||
*/
|
||||
u8 get_pcb_revision_from_eeprom(void)
|
||||
{
|
||||
u8 pv = 0xFF;
|
||||
|
||||
if (read_eeprom())
|
||||
return pv;
|
||||
|
||||
return pbuf.eeprom.atom1.data.pstr[6];
|
||||
}
|
||||
|
||||
/**
|
||||
* get_ddr_size_from_eeprom - get the DDR size
|
||||
* pstr: VF7110A1-2228-D008E000-00000001
|
||||
* VF7110A1/VF7110B1 : VisionFive JH7110A /VisionFive JH7110B
|
||||
* D008: 8GB LPDDR4
|
||||
* E000: No emmc device, ECxx: include emmc device, xx: Capacity size[GB]
|
||||
* return: the field of 'D008E000'
|
||||
*/
|
||||
|
||||
u32 get_ddr_size_from_eeprom(void)
|
||||
{
|
||||
u32 pv = 0xFFFFFFFF;
|
||||
|
||||
if (read_eeprom())
|
||||
return pv;
|
||||
|
||||
return hextoul(&pbuf.eeprom.atom1.data.pstr[14], NULL);
|
||||
}
|
42
board/thead/th1520_lpi4a/Kconfig
Normal file
42
board/thead/th1520_lpi4a/Kconfig
Normal file
|
@ -0,0 +1,42 @@
|
|||
if TARGET_TH1520_LPI4A
|
||||
|
||||
config ARCH_THEAD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SYS_BOARD
|
||||
default "th1520_lpi4a"
|
||||
|
||||
config SYS_VENDOR
|
||||
default "thead"
|
||||
|
||||
config SYS_CPU
|
||||
default "generic"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
default "th1520_lpi4a"
|
||||
|
||||
config TEXT_BASE
|
||||
default 0x01b00000 if SPL
|
||||
default 0x01c00000 if !RISCV_SMODE
|
||||
default 0x01c00000 if RISCV_SMODE
|
||||
|
||||
config SPL_TEXT_BASE
|
||||
default 0x08000000
|
||||
|
||||
config SPL_OPENSBI_LOAD_ADDR
|
||||
default 0x80000000
|
||||
|
||||
config BOARD_SPECIFIC_OPTIONS
|
||||
def_bool y
|
||||
select ARCH_EARLY_INIT_R
|
||||
imply CPU
|
||||
imply CPU_RISCV
|
||||
imply RISCV_TIMER if RISCV_SMODE
|
||||
imply CMD_CPU
|
||||
imply SMP
|
||||
imply SUPPORT_OF_CONTROL
|
||||
imply OF_CONTROL
|
||||
imply OF_REAL
|
||||
|
||||
endif
|
7
board/thead/th1520_lpi4a/MAINTAINERS
Normal file
7
board/thead/th1520_lpi4a/MAINTAINERS
Normal file
|
@ -0,0 +1,7 @@
|
|||
Lichee PI 4A
|
||||
M: Wei Fu <wefu@redhat.com>
|
||||
M: Yixun Lan <dlan@gentoo.org>
|
||||
S: Maintained
|
||||
F: board/thead/th1520_lpi4a/
|
||||
F: configs/th1520_lpi4a_defconfig
|
||||
F: doc/board/thead/lpi4a.rst
|
5
board/thead/th1520_lpi4a/Makefile
Normal file
5
board/thead/th1520_lpi4a/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Copyright (c) 2023, Yixun Lan <dlan@gentoo.org>
|
||||
|
||||
obj-y += board.o
|
15
board/thead/th1520_lpi4a/board.c
Normal file
15
board/thead/th1520_lpi4a/board.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) 2023, Yixun Lan <dlan@gentoo.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <cpu_func.h>
|
||||
|
||||
int board_init(void)
|
||||
{
|
||||
enable_caches();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -7,12 +7,13 @@ CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
|
|||
CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80000000
|
||||
CONFIG_SF_DEFAULT_SPEED=100000000
|
||||
CONFIG_SPL_DM_SPI=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="jh7110-starfive-visionfive-2-v1.3b"
|
||||
CONFIG_DEFAULT_DEVICE_TREE="jh7110-starfive-visionfive-2"
|
||||
CONFIG_SPL_TEXT_BASE=0x8000000
|
||||
CONFIG_SYS_PROMPT="StarFive #"
|
||||
CONFIG_OF_LIBFDT_OVERLAY=y
|
||||
CONFIG_DM_RESET=y
|
||||
CONFIG_SPL_MMC=y
|
||||
CONFIG_SPL_DRIVERS_MISC=y
|
||||
CONFIG_SPL_STACK=0x8180000
|
||||
CONFIG_SPL=y
|
||||
CONFIG_SPL_SPI_FLASH_SUPPORT=y
|
||||
|
@ -23,6 +24,7 @@ CONFIG_SPL_OPENSBI_LOAD_ADDR=0x40000000
|
|||
CONFIG_ARCH_RV64I=y
|
||||
CONFIG_CMODEL_MEDANY=y
|
||||
CONFIG_RISCV_SMODE=y
|
||||
# CONFIG_OF_BOARD_FIXUP is not set
|
||||
CONFIG_FIT=y
|
||||
CONFIG_DISTRO_DEFAULTS=y
|
||||
CONFIG_QSPI_BOOT=y
|
||||
|
@ -31,9 +33,11 @@ CONFIG_USE_BOOTARGS=y
|
|||
CONFIG_BOOTARGS="console=ttyS0,115200 debug rootwait earlycon=sbi"
|
||||
CONFIG_USE_PREBOOT=y
|
||||
CONFIG_PREBOOT="setenv fdt_addr ${fdtcontroladdr};fdt addr ${fdtcontroladdr};"
|
||||
CONFIG_DEFAULT_FDT_FILE="starfive/jh7110-starfive-visionfive-2-v1.3b.dtb"
|
||||
CONFIG_DEFAULT_FDT_FILE="starfive/jh7110-starfive-visionfive-2.dtb"
|
||||
CONFIG_DISPLAY_CPUINFO=y
|
||||
CONFIG_DISPLAY_BOARDINFO=y
|
||||
CONFIG_ID_EEPROM=y
|
||||
CONFIG_SYS_EEPROM_BUS_NUM=5
|
||||
CONFIG_SPL_MAX_SIZE=0x40000
|
||||
CONFIG_SPL_PAD_TO=0x0
|
||||
CONFIG_SPL_BSS_START_ADDR=0x8040000
|
||||
|
@ -45,19 +49,34 @@ CONFIG_CUSTOM_SYS_SPL_MALLOC_ADDR=0x80000000
|
|||
CONFIG_SYS_SPL_MALLOC_SIZE=0x400000
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION=y
|
||||
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION=0x2
|
||||
CONFIG_SPL_I2C=y
|
||||
CONFIG_SPL_DM_SPI_FLASH=y
|
||||
CONFIG_SPL_DM_RESET=y
|
||||
CONFIG_SPL_SPI_LOAD=y
|
||||
CONFIG_SYS_CBSIZE=256
|
||||
CONFIG_SYS_PBSIZE=276
|
||||
CONFIG_SYS_BOOTM_LEN=0x4000000
|
||||
CONFIG_CMD_EEPROM=y
|
||||
CONFIG_SYS_EEPROM_SIZE=512
|
||||
CONFIG_SYS_EEPROM_PAGE_WRITE_BITS=4
|
||||
CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS=5
|
||||
CONFIG_CMD_MEMINFO=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_TFTPPUT=y
|
||||
CONFIG_OF_BOARD=y
|
||||
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
||||
CONFIG_SPL_DM_SEQ_ALIAS=y
|
||||
CONFIG_REGMAP=y
|
||||
CONFIG_SYSCON=y
|
||||
CONFIG_SPL_CLK_COMPOSITE_CCF=y
|
||||
CONFIG_CLK_COMPOSITE_CCF=y
|
||||
CONFIG_SPL_CLK_JH7110=y
|
||||
# CONFIG_I2C is not set
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_SYS_I2C_DW=y
|
||||
CONFIG_MISC=y
|
||||
CONFIG_I2C_EEPROM=y
|
||||
CONFIG_SPL_I2C_EEPROM=y
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR=0X50
|
||||
CONFIG_MMC_HS400_SUPPORT=y
|
||||
CONFIG_SPL_MMC_HS400_SUPPORT=y
|
||||
CONFIG_MMC_DW=y
|
||||
|
@ -66,6 +85,13 @@ CONFIG_SPI_FLASH_EON=y
|
|||
CONFIG_SPI_FLASH_GIGADEVICE=y
|
||||
CONFIG_SPI_FLASH_ISSI=y
|
||||
CONFIG_SPI_FLASH_MACRONIX=y
|
||||
CONFIG_PHY_MOTORCOMM=y
|
||||
CONFIG_DM_MDIO=y
|
||||
CONFIG_DM_ETH_PHY=y
|
||||
CONFIG_DWC_ETH_QOS=y
|
||||
CONFIG_DWC_ETH_QOS_STARFIVE=y
|
||||
CONFIG_RGMII=y
|
||||
CONFIG_RMII=y
|
||||
CONFIG_PINCTRL=y
|
||||
CONFIG_PINCONF=y
|
||||
CONFIG_SPL_PINCTRL=y
|
||||
|
|
82
configs/th1520_lpi4a_defconfig
Normal file
82
configs/th1520_lpi4a_defconfig
Normal file
|
@ -0,0 +1,82 @@
|
|||
CONFIG_RISCV=y
|
||||
CONFIG_SYS_MALLOC_LEN=0x800000
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x3000
|
||||
CONFIG_NR_DRAM_BANKS=1
|
||||
CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
|
||||
CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80200000
|
||||
CONFIG_DEFAULT_DEVICE_TREE="th1520-lichee-pi-4a"
|
||||
CONFIG_SYS_PROMPT="LPI4A=> "
|
||||
CONFIG_SYS_LOAD_ADDR=0x80200000
|
||||
# CONFIG_SMP is not set
|
||||
CONFIG_TARGET_TH1520_LPI4A=y
|
||||
CONFIG_ARCH_RV64I=y
|
||||
CONFIG_OF_BOARD_FIXUP=y
|
||||
CONFIG_SYS_BOOT_GET_CMDLINE=y
|
||||
CONFIG_SYS_BOOT_GET_KBD=y
|
||||
CONFIG_FIT=y
|
||||
# CONFIG_FIT_FULL_CHECK is not set
|
||||
# CONFIG_FIT_PRINT is not set
|
||||
# CONFIG_BOOTSTD is not set
|
||||
# CONFIG_LEGACY_IMAGE_FORMAT is not set
|
||||
CONFIG_DISTRO_DEFAULTS=y
|
||||
CONFIG_BOOTARGS_SUBST=y
|
||||
CONFIG_BOOTCOMMAND=""
|
||||
CONFIG_DEFAULT_FDT_FILE="thead/th1520-lichee-pi-4a.dtb"
|
||||
CONFIG_LOG=y
|
||||
CONFIG_DISPLAY_CPUINFO=y
|
||||
CONFIG_DISPLAY_BOARDINFO=y
|
||||
CONFIG_DISPLAY_BOARDINFO_LATE=y
|
||||
CONFIG_SYS_CBSIZE=256
|
||||
CONFIG_SYS_PBSIZE=276
|
||||
CONFIG_CMD_CONFIG=y
|
||||
CONFIG_CMD_LICENSE=y
|
||||
CONFIG_CMD_BOOTZ=y
|
||||
# CONFIG_BOOTM_NETBSD is not set
|
||||
# CONFIG_BOOTM_PLAN9 is not set
|
||||
# CONFIG_BOOTM_RTEMS is not set
|
||||
# CONFIG_BOOTM_VXWORKS is not set
|
||||
CONFIG_SYS_BOOTM_LEN=0x4000000
|
||||
CONFIG_CMD_BOOTMENU=y
|
||||
# CONFIG_CMD_ELF is not set
|
||||
# CONFIG_CMD_IMI is not set
|
||||
# CONFIG_CMD_XIMG is not set
|
||||
# CONFIG_CMD_EXPORTENV is not set
|
||||
# CONFIG_CMD_IMPORTENV is not set
|
||||
# CONFIG_CMD_EDITENV is not set
|
||||
# CONFIG_CMD_SAVEENV is not set
|
||||
# CONFIG_CMD_CRC32 is not set
|
||||
# CONFIG_CMD_MEMORY is not set
|
||||
# CONFIG_CMD_LZMADEC is not set
|
||||
# CONFIG_CMD_UNLZ4 is not set
|
||||
# CONFIG_CMD_UNZIP is not set
|
||||
# CONFIG_CMD_LOADB is not set
|
||||
# CONFIG_CMD_LOADS is not set
|
||||
# CONFIG_CMD_ITEST is not set
|
||||
# CONFIG_CMD_SOURCE is not set
|
||||
# CONFIG_CMD_SETEXPR is not set
|
||||
# CONFIG_CMD_SLEEP is not set
|
||||
CONFIG_PARTITION_TYPE_GUID=y
|
||||
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
||||
CONFIG_VERSION_VARIABLE=y
|
||||
# CONFIG_NET is not set
|
||||
# CONFIG_BLOCK_CACHE is not set
|
||||
# CONFIG_GPIO is not set
|
||||
# CONFIG_I2C is not set
|
||||
# CONFIG_INPUT is not set
|
||||
# CONFIG_DM_MMC is not set
|
||||
# CONFIG_MTD is not set
|
||||
# CONFIG_POWER is not set
|
||||
CONFIG_SYS_NS16550=y
|
||||
CONFIG_RISCV_TIMER=y
|
||||
CONFIG_AES=y
|
||||
CONFIG_BLAKE2=y
|
||||
CONFIG_SHA512=y
|
||||
CONFIG_LZ4=y
|
||||
CONFIG_LZMA=y
|
||||
CONFIG_LZO=y
|
||||
CONFIG_ZLIB_UNCOMPRESS=y
|
||||
CONFIG_BZIP2=y
|
||||
CONFIG_ZSTD=y
|
||||
CONFIG_LIB_RATIONAL=y
|
||||
# CONFIG_EFI_LOADER is not set
|
||||
# CONFIG_LMB_USE_MAX_REGIONS is not set
|
|
@ -45,6 +45,7 @@ Board-specific doc
|
|||
starfive/index
|
||||
ste/index
|
||||
tbs/index
|
||||
thead/index
|
||||
ti/index
|
||||
toradex/index
|
||||
variscite/index
|
||||
|
|
|
@ -62,7 +62,7 @@ Now build the U-Boot SPL and U-Boot proper
|
|||
.. code-block:: console
|
||||
|
||||
cd <U-Boot-dir>
|
||||
make starfive_visionfive2_13b_defconfig
|
||||
make starfive_visionfive2_defconfig
|
||||
make OPENSBI=$(opensbi_dir)/opensbi/build/platform/generic/firmware/fw_dynamic.bin
|
||||
|
||||
This will generate spl/u-boot-spl.bin and FIT image (u-boot.itb)
|
||||
|
@ -118,7 +118,7 @@ Program the SD card
|
|||
sudo cp u-boot.itb /mnt/
|
||||
sudo cp Image.gz /mnt/
|
||||
sudo cp initramfs.cpio.gz /mnt/
|
||||
sudo cp jh7110-starfive-visionfive-2-v1.3b.dtb /mnt/
|
||||
sudo cp jh7110-starfive-visionfive-2.dtb /mnt/
|
||||
sudo umount /mnt
|
||||
|
||||
Booting
|
||||
|
@ -264,7 +264,7 @@ Sample boot log from StarFive VisionFive2 board
|
|||
|
||||
StarFive #fatload mmc 1:3 ${kernel_addr_r} Image.gz
|
||||
6429424 bytes read in 394 ms (15.6 MiB/s)
|
||||
StarFive #fatload mmc 1:3 ${fdt_addr_r} jh7110-starfive-visionfive-2-v1.3b.dtb
|
||||
StarFive #fatload mmc 1:3 ${fdt_addr_r} jh7110-starfive-visionfive-2.dtb
|
||||
11285 bytes read in 5 ms (2.2 MiB/s)
|
||||
StarFive #fatload mmc 1:3 ${ramdisk_addr_r} initramfs.cpio.gz
|
||||
152848495 bytes read in 9271 ms (15.7 MiB/s)
|
||||
|
|
9
doc/board/thead/index.rst
Normal file
9
doc/board/thead/index.rst
Normal file
|
@ -0,0 +1,9 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
T-HEAD
|
||||
========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
lpi4a
|
129
doc/board/thead/lpi4a.rst
Normal file
129
doc/board/thead/lpi4a.rst
Normal file
|
@ -0,0 +1,129 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
Sipeed's Lichee PI 4A based on T-HEAD TH1520 SoC
|
||||
================================================
|
||||
|
||||
The LicheePi4A is a high-performance RISC-V SBC based on TH1520(4xC910@1.85GHz),
|
||||
comes with 4/8/16 GB RAM, and up to 128GB eMMC, and rich peripherals.
|
||||
|
||||
- SoC T-HEAD TH1520 SoC
|
||||
- System Memory 4GB, 8GB, or 16GB LPDDR4X
|
||||
- Storage eMMC flash with 8/32/128 GB
|
||||
- external microSD slot
|
||||
- Networking 2x Gigabit Ethernet
|
||||
- WiFi+BT
|
||||
- Display HDMI2.0, 4-lane MIPI DSI
|
||||
- Camera 4-lane MIPI CSI + 2x2-lane MIPI CSI
|
||||
- Audio Onboard Speaker, 2xMEMS MIC, 3.5mm headphone jack
|
||||
- USB 4xUSB3.0 Type-A, 1xUSB2.0 Type-C
|
||||
- GPIO 2x10Pin breakout, UART/IIC/SPI
|
||||
- Power DC 12V/2A, POE 5V/2.4A, USB Type-C 5V/2A
|
||||
|
||||
TH1520 RISC-V SoC
|
||||
-----------------
|
||||
|
||||
The TH1520 SoC consist of quad-core RISC-V Xuantie C910 (RV64GCV) processor,
|
||||
Xuantie C906 audio DSP, low power Xuantie E902 core, it also integrate
|
||||
Imagination GPU for graphics, and 4 TOPS NPU for AI acceleration.
|
||||
|
||||
Mainline support
|
||||
----------------
|
||||
|
||||
The support for following drivers are already enabled:
|
||||
|
||||
1. ns16550 UART Driver.
|
||||
|
||||
Building
|
||||
~~~~~~~~
|
||||
|
||||
1. Add the RISC-V toolchain to your PATH.
|
||||
2. Setup ARCH & cross compilation environment variable:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
export CROSS_COMPILE=<riscv64 toolchain prefix>
|
||||
|
||||
The U-Boot is capable of running in M-Mode, so we can directly build it.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cd <U-Boot-dir>
|
||||
make th1520_lpi4a_defconfig
|
||||
make
|
||||
|
||||
This will generate u-boot-dtb.bin
|
||||
|
||||
Booting
|
||||
~~~~~~~
|
||||
|
||||
Currently, we rely on vendor u-boot to initialize the clock, pinctrl subsystem,
|
||||
and chain load the mainline u-boot image either via tftp or emmc storage,
|
||||
then bootup from it.
|
||||
|
||||
Sample boot log from Lichee PI 4A board via tftp
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
brom_ver 8
|
||||
[APP][E] protocol_connect failed, exit.
|
||||
|
||||
U-Boot SPL 2020.01-00016-g8c870a6be8 (May 20 2023 - 01:04:49 +0000)
|
||||
FM[1] lpddr4x dualrank freq=3733 64bit dbi_off=n sdram init
|
||||
ddr initialized, jump to uboot
|
||||
image has no header
|
||||
|
||||
|
||||
U-Boot 2020.01-00016-g8c870a6be8 (May 20 2023 - 01:04:49 +0000)
|
||||
|
||||
CPU: rv64imafdcvsu
|
||||
Model: T-HEAD c910 light
|
||||
DRAM: 8 GiB
|
||||
C910 CPU FREQ: 750MHz
|
||||
AHB2_CPUSYS_HCLK FREQ: 250MHz
|
||||
AHB3_CPUSYS_PCLK FREQ: 125MHz
|
||||
PERISYS_AHB_HCLK FREQ: 250MHz
|
||||
PERISYS_APB_PCLK FREQ: 62MHz
|
||||
GMAC PLL POSTDIV FREQ: 1000MHZ
|
||||
DPU0 PLL POSTDIV FREQ: 1188MHZ
|
||||
DPU1 PLL POSTDIV FREQ: 1188MHZ
|
||||
MMC: sdhci@ffe7080000: 0, sd@ffe7090000: 1
|
||||
Loading Environment from MMC... OK
|
||||
Error reading output register
|
||||
Warning: cannot get lcd-en GPIO
|
||||
LCD panel cannot be found : -121
|
||||
splash screen startup cost 16 ms
|
||||
In: serial
|
||||
Out: serial
|
||||
Err: serial
|
||||
Net:
|
||||
Warning: ethernet@ffe7070000 using MAC address from ROM
|
||||
eth0: ethernet@ffe7070000ethernet@ffe7070000:0 is connected to ethernet@ffe7070000. Reconnecting to ethernet@ffe7060000
|
||||
|
||||
Warning: ethernet@ffe7060000 (eth1) using random MAC address - 42:25:d4:16:5f:fc
|
||||
, eth1: ethernet@ffe7060000
|
||||
Hit any key to stop autoboot: 2
|
||||
ethernet@ffe7060000 Waiting for PHY auto negotiation to complete.. done
|
||||
Speed: 1000, full duplex
|
||||
Using ethernet@ffe7070000 device
|
||||
TFTP from server 192.168.8.50; our IP address is 192.168.8.45
|
||||
Filename 'u-boot-dtb.bin'.
|
||||
Load address: 0x1c00000
|
||||
Loading: * #########################
|
||||
8 MiB/s
|
||||
done
|
||||
Bytes transferred = 376686 (5bf6e hex)
|
||||
## Starting application at 0x01C00000 ...
|
||||
|
||||
U-Boot 2023.07-rc2-00004-g1befbe31c1 (May 23 2023 - 18:40:01 +0800)
|
||||
|
||||
CPU: rv64imafdc
|
||||
Model: Sipeed Lichee Pi 4A
|
||||
DRAM: 8 GiB
|
||||
Core: 13 devices, 6 uclasses, devicetree: separate
|
||||
Loading Environment from <NULL>... OK
|
||||
In: serial@ffe7014000
|
||||
Out: serial@ffe7014000
|
||||
Err: serial@ffe7014000
|
||||
Model: Sipeed Lichee Pi 4A
|
||||
LPI4A=>
|
|
@ -249,6 +249,13 @@ config DWC_ETH_QOS_QCOM
|
|||
The Synopsys Designware Ethernet QOS IP block with specific
|
||||
configuration used in Qcom QCS404 SoC.
|
||||
|
||||
config DWC_ETH_QOS_STARFIVE
|
||||
bool "Synopsys DWC Ethernet QOS device support for STARFIVE"
|
||||
depends on DWC_ETH_QOS
|
||||
help
|
||||
The Synopsys Designware Ethernet QOS IP block with specific
|
||||
configuration used in STARFIVE JH7110 soc.
|
||||
|
||||
config E1000
|
||||
bool "Intel PRO/1000 Gigabit Ethernet support"
|
||||
depends on PCI
|
||||
|
|
|
@ -21,6 +21,7 @@ obj-$(CONFIG_DSA_SANDBOX) += dsa_sandbox.o
|
|||
obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o
|
||||
obj-$(CONFIG_DWC_ETH_QOS_IMX) += dwc_eth_qos_imx.o
|
||||
obj-$(CONFIG_DWC_ETH_QOS_QCOM) += dwc_eth_qos_qcom.o
|
||||
obj-$(CONFIG_DWC_ETH_QOS_STARFIVE) += dwc_eth_qos_starfive.o
|
||||
obj-$(CONFIG_E1000) += e1000.o
|
||||
obj-$(CONFIG_E1000_SPI) += e1000_spi.o
|
||||
obj-$(CONFIG_EEPRO100) += eepro100.o
|
||||
|
|
|
@ -1725,6 +1725,12 @@ static const struct udevice_id eqos_ids[] = {
|
|||
.data = (ulong)&eqos_qcom_config
|
||||
},
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_DWC_ETH_QOS_STARFIVE)
|
||||
{
|
||||
.compatible = "starfive,jh7110-dwmac",
|
||||
.data = (ulong)&eqos_jh7110_config
|
||||
},
|
||||
#endif
|
||||
|
||||
{ }
|
||||
};
|
||||
|
|
|
@ -289,3 +289,4 @@ int eqos_null_ops(struct udevice *dev);
|
|||
|
||||
extern struct eqos_config eqos_imx_config;
|
||||
extern struct eqos_config eqos_qcom_config;
|
||||
extern struct eqos_config eqos_jh7110_config;
|
||||
|
|
249
drivers/net/dwc_eth_qos_starfive.c
Normal file
249
drivers/net/dwc_eth_qos_starfive.c
Normal file
|
@ -0,0 +1,249 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2023 StarFive Technology Co., Ltd.
|
||||
* Author: Yanhong Wang<yanhong.wang@starfivetech.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <eth_phy.h>
|
||||
#include <net.h>
|
||||
#include <regmap.h>
|
||||
#include <reset.h>
|
||||
#include <syscon.h>
|
||||
|
||||
#include "dwc_eth_qos.h"
|
||||
|
||||
#define STARFIVE_DWMAC_PHY_INFT_RGMII 0x1
|
||||
#define STARFIVE_DWMAC_PHY_INFT_RMII 0x4
|
||||
#define STARFIVE_DWMAC_PHY_INFT_FIELD 0x7U
|
||||
|
||||
struct starfive_platform_data {
|
||||
struct regmap *regmap;
|
||||
struct reset_ctl_bulk resets;
|
||||
struct clk_bulk clks;
|
||||
phy_interface_t interface;
|
||||
u32 offset;
|
||||
u32 shift;
|
||||
bool tx_use_rgmii_clk;
|
||||
};
|
||||
|
||||
static int eqos_interface_init_jh7110(struct udevice *dev)
|
||||
{
|
||||
struct eth_pdata *pdata = dev_get_plat(dev);
|
||||
struct starfive_platform_data *data = pdata->priv_pdata;
|
||||
struct ofnode_phandle_args args;
|
||||
unsigned int mode;
|
||||
int ret;
|
||||
|
||||
switch (data->interface) {
|
||||
case PHY_INTERFACE_MODE_RMII:
|
||||
mode = STARFIVE_DWMAC_PHY_INFT_RMII;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
mode = STARFIVE_DWMAC_PHY_INFT_RGMII;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = dev_read_phandle_with_args(dev, "starfive,syscon", NULL,
|
||||
2, 0, &args);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (args.args_count != 2)
|
||||
return -EINVAL;
|
||||
|
||||
data->offset = args.args[0];
|
||||
data->shift = args.args[1];
|
||||
data->regmap = syscon_regmap_lookup_by_phandle(dev, "starfive,syscon");
|
||||
if (IS_ERR(data->regmap)) {
|
||||
ret = PTR_ERR(data->regmap);
|
||||
pr_err("Failed to get regmap: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return regmap_update_bits(data->regmap, data->offset,
|
||||
STARFIVE_DWMAC_PHY_INFT_FIELD << data->shift,
|
||||
mode << data->shift);
|
||||
}
|
||||
|
||||
static int eqos_set_tx_clk_speed_jh7110(struct udevice *dev)
|
||||
{
|
||||
struct eqos_priv *eqos = dev_get_priv(dev);
|
||||
struct eth_pdata *pdata = dev_get_plat(dev);
|
||||
struct starfive_platform_data *data = pdata->priv_pdata;
|
||||
struct clk *pclk, *c;
|
||||
ulong rate;
|
||||
int ret;
|
||||
|
||||
/* Generally, the rgmii_tx clock is provided by the internal clock,
|
||||
* which needs to match the corresponding clock frequency according
|
||||
* to different speeds. If the rgmii_tx clock is provided by the
|
||||
* external rgmii_rxin, there is no need to configure the clock
|
||||
* internally, because rgmii_rxin will be adaptively adjusted.
|
||||
*/
|
||||
if (data->tx_use_rgmii_clk)
|
||||
return 0;
|
||||
|
||||
switch (eqos->phy->speed) {
|
||||
case SPEED_1000:
|
||||
rate = 125 * 1000 * 1000;
|
||||
break;
|
||||
case SPEED_100:
|
||||
rate = 25 * 1000 * 1000;
|
||||
break;
|
||||
case SPEED_10:
|
||||
rate = 2.5 * 1000 * 1000;
|
||||
break;
|
||||
default:
|
||||
pr_err("invalid speed %d", eqos->phy->speed);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* eqos->clk_tx clock has no set rate operation, so just set the parent
|
||||
* clock rate directly
|
||||
*/
|
||||
ret = clk_get_by_id(eqos->clk_tx.id, &c);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pclk = clk_get_parent(c);
|
||||
if (pclk) {
|
||||
ret = clk_set_rate(pclk, rate);
|
||||
if (ret < 0) {
|
||||
pr_err("jh7110 (clk_tx, %lu) failed: %d", rate, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ulong eqos_get_tick_clk_rate_jh7110(struct udevice *dev)
|
||||
{
|
||||
struct eqos_priv *eqos = dev_get_priv(dev);
|
||||
|
||||
return clk_get_rate(&eqos->clk_tx);
|
||||
}
|
||||
|
||||
static int eqos_start_clks_jh7110(struct udevice *dev)
|
||||
{
|
||||
struct eth_pdata *pdata = dev_get_plat(dev);
|
||||
struct starfive_platform_data *data = pdata->priv_pdata;
|
||||
|
||||
return clk_enable_bulk(&data->clks);
|
||||
}
|
||||
|
||||
static int eqos_stop_clks_jh7110(struct udevice *dev)
|
||||
{
|
||||
struct eth_pdata *pdata = dev_get_plat(dev);
|
||||
struct starfive_platform_data *data = pdata->priv_pdata;
|
||||
|
||||
return clk_disable_bulk(&data->clks);
|
||||
}
|
||||
|
||||
static int eqos_start_resets_jh7110(struct udevice *dev)
|
||||
{
|
||||
struct eth_pdata *pdata = dev_get_plat(dev);
|
||||
struct starfive_platform_data *data = pdata->priv_pdata;
|
||||
|
||||
return reset_deassert_bulk(&data->resets);
|
||||
}
|
||||
|
||||
static int eqos_stop_resets_jh7110(struct udevice *dev)
|
||||
{
|
||||
struct eth_pdata *pdata = dev_get_plat(dev);
|
||||
struct starfive_platform_data *data = pdata->priv_pdata;
|
||||
|
||||
return reset_assert_bulk(&data->resets);
|
||||
}
|
||||
|
||||
static int eqos_remove_resources_jh7110(struct udevice *dev)
|
||||
{
|
||||
struct eth_pdata *pdata = dev_get_plat(dev);
|
||||
struct starfive_platform_data *data = pdata->priv_pdata;
|
||||
|
||||
reset_assert_bulk(&data->resets);
|
||||
clk_disable_bulk(&data->clks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eqos_probe_resources_jh7110(struct udevice *dev)
|
||||
{
|
||||
struct eqos_priv *eqos = dev_get_priv(dev);
|
||||
struct eth_pdata *pdata = dev_get_plat(dev);
|
||||
struct starfive_platform_data *data;
|
||||
int ret;
|
||||
|
||||
data = calloc(1, sizeof(struct starfive_platform_data));
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
pdata->priv_pdata = data;
|
||||
data->interface = eqos->config->interface(dev);
|
||||
if (data->interface == PHY_INTERFACE_MODE_NA) {
|
||||
pr_err("Invalid PHY interface\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = reset_get_bulk(dev, &data->resets);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = clk_get_bulk(dev, &data->clks);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = clk_get_by_name(dev, "gtx", &eqos->clk_tx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
data->tx_use_rgmii_clk = dev_read_bool(dev, "starfive,tx-use-rgmii-clk");
|
||||
|
||||
return eqos_interface_init_jh7110(dev);
|
||||
}
|
||||
|
||||
static struct eqos_ops eqos_jh7110_ops = {
|
||||
.eqos_inval_desc = eqos_inval_desc_generic,
|
||||
.eqos_flush_desc = eqos_flush_desc_generic,
|
||||
.eqos_inval_buffer = eqos_inval_buffer_generic,
|
||||
.eqos_flush_buffer = eqos_flush_buffer_generic,
|
||||
.eqos_probe_resources = eqos_probe_resources_jh7110,
|
||||
.eqos_remove_resources = eqos_remove_resources_jh7110,
|
||||
.eqos_stop_resets = eqos_stop_resets_jh7110,
|
||||
.eqos_start_resets = eqos_start_resets_jh7110,
|
||||
.eqos_stop_clks = eqos_stop_clks_jh7110,
|
||||
.eqos_start_clks = eqos_start_clks_jh7110,
|
||||
.eqos_calibrate_pads = eqos_null_ops,
|
||||
.eqos_disable_calibration = eqos_null_ops,
|
||||
.eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_jh7110,
|
||||
.eqos_get_enetaddr = eqos_null_ops,
|
||||
.eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_jh7110
|
||||
};
|
||||
|
||||
/* mdio_wait: There is no need to wait after setting the MAC_MDIO_Address register
|
||||
* swr_wait: Software reset bit must be read at least 4 CSR clock cycles
|
||||
* after it is written to 1.
|
||||
* config_mac: Enable rx queue to DCB mode.
|
||||
* config_mac_mdio: CSR clock range is 250-300 Mhz.
|
||||
* axi_bus_width: The width of the data bus is 64 bit.
|
||||
*/
|
||||
struct eqos_config __maybe_unused eqos_jh7110_config = {
|
||||
.reg_access_always_ok = false,
|
||||
.mdio_wait = 0,
|
||||
.swr_wait = 4,
|
||||
.config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
|
||||
.config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
|
||||
.axi_bus_width = EQOS_AXI_WIDTH_64,
|
||||
.interface = dev_read_phy_mode,
|
||||
.ops = &eqos_jh7110_ops
|
||||
};
|
|
@ -220,6 +220,12 @@ config PHY_MICREL_KSZ8XXX
|
|||
|
||||
endif # PHY_MICREL
|
||||
|
||||
config PHY_MOTORCOMM
|
||||
tristate "Motorcomm PHYs"
|
||||
help
|
||||
Enables support for Motorcomm network PHYs.
|
||||
Currently supports the YT8531 Gigabit Ethernet PHYs.
|
||||
|
||||
config PHY_MSCC
|
||||
bool "Microsemi Corp Ethernet PHYs support"
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ obj-$(CONFIG_PHY_MARVELL_10G) += marvell10g.o
|
|||
obj-$(CONFIG_PHY_MICREL_KSZ8XXX) += micrel_ksz8xxx.o
|
||||
obj-$(CONFIG_PHY_MICREL_KSZ90X1) += micrel_ksz90x1.o
|
||||
obj-$(CONFIG_PHY_MESON_GXL) += meson-gxl.o
|
||||
obj-$(CONFIG_PHY_MOTORCOMM) += motorcomm.o
|
||||
obj-$(CONFIG_PHY_NATSEMI) += natsemi.o
|
||||
obj-$(CONFIG_PHY_NXP_C45_TJA11XX) += nxp-c45-tja11xx.o
|
||||
obj-$(CONFIG_PHY_NXP_TJA11XX) += nxp-tja11xx.o
|
||||
|
|
437
drivers/net/phy/motorcomm.c
Normal file
437
drivers/net/phy/motorcomm.c
Normal file
|
@ -0,0 +1,437 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Motorcomm 8531 PHY driver.
|
||||
*
|
||||
* Copyright (C) 2023 StarFive Technology Co., Ltd.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
#include <phy.h>
|
||||
#include <linux/bitfield.h>
|
||||
|
||||
#define PHY_ID_YT8531 0x4f51e91b
|
||||
#define PHY_ID_MASK GENMASK(31, 0)
|
||||
|
||||
/* Extended Register's Address Offset Register */
|
||||
#define YTPHY_PAGE_SELECT 0x1E
|
||||
|
||||
/* Extended Register's Data Register */
|
||||
#define YTPHY_PAGE_DATA 0x1F
|
||||
|
||||
#define YTPHY_SYNCE_CFG_REG 0xA012
|
||||
|
||||
#define YTPHY_DTS_OUTPUT_CLK_DIS 0
|
||||
#define YTPHY_DTS_OUTPUT_CLK_25M 25000000
|
||||
#define YTPHY_DTS_OUTPUT_CLK_125M 125000000
|
||||
|
||||
#define YT8531_SCR_SYNCE_ENABLE BIT(6)
|
||||
/* 1b0 output 25m clock *default*
|
||||
* 1b1 output 125m clock
|
||||
*/
|
||||
#define YT8531_SCR_CLK_FRE_SEL_125M BIT(4)
|
||||
#define YT8531_SCR_CLK_SRC_MASK GENMASK(3, 1)
|
||||
#define YT8531_SCR_CLK_SRC_PLL_125M 0
|
||||
#define YT8531_SCR_CLK_SRC_UTP_RX 1
|
||||
#define YT8531_SCR_CLK_SRC_SDS_RX 2
|
||||
#define YT8531_SCR_CLK_SRC_CLOCK_FROM_DIGITAL 3
|
||||
#define YT8531_SCR_CLK_SRC_REF_25M 4
|
||||
#define YT8531_SCR_CLK_SRC_SSC_25M 5
|
||||
|
||||
/* 1b0 use original tx_clk_rgmii *default*
|
||||
* 1b1 use inverted tx_clk_rgmii.
|
||||
*/
|
||||
#define YT8531_RC1R_TX_CLK_SEL_INVERTED BIT(14)
|
||||
#define YT8531_RC1R_RX_DELAY_MASK GENMASK(13, 10)
|
||||
#define YT8531_RC1R_FE_TX_DELAY_MASK GENMASK(7, 4)
|
||||
#define YT8531_RC1R_GE_TX_DELAY_MASK GENMASK(3, 0)
|
||||
#define YT8531_RC1R_RGMII_0_000_NS 0
|
||||
#define YT8531_RC1R_RGMII_0_150_NS 1
|
||||
#define YT8531_RC1R_RGMII_0_300_NS 2
|
||||
#define YT8531_RC1R_RGMII_0_450_NS 3
|
||||
#define YT8531_RC1R_RGMII_0_600_NS 4
|
||||
#define YT8531_RC1R_RGMII_0_750_NS 5
|
||||
#define YT8531_RC1R_RGMII_0_900_NS 6
|
||||
#define YT8531_RC1R_RGMII_1_050_NS 7
|
||||
#define YT8531_RC1R_RGMII_1_200_NS 8
|
||||
#define YT8531_RC1R_RGMII_1_350_NS 9
|
||||
#define YT8531_RC1R_RGMII_1_500_NS 10
|
||||
#define YT8531_RC1R_RGMII_1_650_NS 11
|
||||
#define YT8531_RC1R_RGMII_1_800_NS 12
|
||||
#define YT8531_RC1R_RGMII_1_950_NS 13
|
||||
#define YT8531_RC1R_RGMII_2_100_NS 14
|
||||
#define YT8531_RC1R_RGMII_2_250_NS 15
|
||||
|
||||
/* Phy gmii clock gating Register */
|
||||
#define YT8531_CLOCK_GATING_REG 0xC
|
||||
#define YT8531_CGR_RX_CLK_EN BIT(12)
|
||||
|
||||
/* Specific Status Register */
|
||||
#define YTPHY_SPECIFIC_STATUS_REG 0x11
|
||||
#define YTPHY_DUPLEX_MASK BIT(13)
|
||||
#define YTPHY_DUPLEX_SHIFT 13
|
||||
#define YTPHY_SPEED_MODE_MASK GENMASK(15, 14)
|
||||
#define YTPHY_SPEED_MODE_SHIFT 14
|
||||
|
||||
#define YT8531_EXTREG_SLEEP_CONTROL1_REG 0x27
|
||||
#define YT8531_ESC1R_SLEEP_SW BIT(15)
|
||||
#define YT8531_ESC1R_PLLON_SLP BIT(14)
|
||||
|
||||
#define YT8531_RGMII_CONFIG1_REG 0xA003
|
||||
|
||||
#define YT8531_CHIP_CONFIG_REG 0xA001
|
||||
#define YT8531_CCR_SW_RST BIT(15)
|
||||
/* 1b0 disable 1.9ns rxc clock delay *default*
|
||||
* 1b1 enable 1.9ns rxc clock delay
|
||||
*/
|
||||
#define YT8531_CCR_RXC_DLY_EN BIT(8)
|
||||
#define YT8531_CCR_RXC_DLY_1_900_NS 1900
|
||||
|
||||
/* bits in struct ytphy_plat_priv->flag */
|
||||
#define TX_CLK_ADJ_ENABLED BIT(0)
|
||||
#define AUTO_SLEEP_DISABLED BIT(1)
|
||||
#define KEEP_PLL_ENABLED BIT(2)
|
||||
#define TX_CLK_10_INVERTED BIT(3)
|
||||
#define TX_CLK_100_INVERTED BIT(4)
|
||||
#define TX_CLK_1000_INVERTED BIT(5)
|
||||
|
||||
struct ytphy_plat_priv {
|
||||
u32 rx_delay_ps;
|
||||
u32 tx_delay_ps;
|
||||
u32 clk_out_frequency;
|
||||
u32 flag;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ytphy_cfg_reg_map - map a config value to a register value
|
||||
* @cfg: value in device configuration
|
||||
* @reg: value in the register
|
||||
*/
|
||||
struct ytphy_cfg_reg_map {
|
||||
u32 cfg;
|
||||
u32 reg;
|
||||
};
|
||||
|
||||
static const struct ytphy_cfg_reg_map ytphy_rgmii_delays[] = {
|
||||
/* for tx delay / rx delay with YT8531_CCR_RXC_DLY_EN is not set. */
|
||||
{ 0, YT8531_RC1R_RGMII_0_000_NS },
|
||||
{ 150, YT8531_RC1R_RGMII_0_150_NS },
|
||||
{ 300, YT8531_RC1R_RGMII_0_300_NS },
|
||||
{ 450, YT8531_RC1R_RGMII_0_450_NS },
|
||||
{ 600, YT8531_RC1R_RGMII_0_600_NS },
|
||||
{ 750, YT8531_RC1R_RGMII_0_750_NS },
|
||||
{ 900, YT8531_RC1R_RGMII_0_900_NS },
|
||||
{ 1050, YT8531_RC1R_RGMII_1_050_NS },
|
||||
{ 1200, YT8531_RC1R_RGMII_1_200_NS },
|
||||
{ 1350, YT8531_RC1R_RGMII_1_350_NS },
|
||||
{ 1500, YT8531_RC1R_RGMII_1_500_NS },
|
||||
{ 1650, YT8531_RC1R_RGMII_1_650_NS },
|
||||
{ 1800, YT8531_RC1R_RGMII_1_800_NS },
|
||||
{ 1950, YT8531_RC1R_RGMII_1_950_NS }, /* default tx/rx delay */
|
||||
{ 2100, YT8531_RC1R_RGMII_2_100_NS },
|
||||
{ 2250, YT8531_RC1R_RGMII_2_250_NS },
|
||||
|
||||
/* only for rx delay with YT8531_CCR_RXC_DLY_EN is set. */
|
||||
{ 0 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_000_NS },
|
||||
{ 150 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_150_NS },
|
||||
{ 300 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_300_NS },
|
||||
{ 450 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_450_NS },
|
||||
{ 600 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_600_NS },
|
||||
{ 750 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_750_NS },
|
||||
{ 900 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_0_900_NS },
|
||||
{ 1050 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_050_NS },
|
||||
{ 1200 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_200_NS },
|
||||
{ 1350 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_350_NS },
|
||||
{ 1500 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_500_NS },
|
||||
{ 1650 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_650_NS },
|
||||
{ 1800 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_800_NS },
|
||||
{ 1950 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_1_950_NS },
|
||||
{ 2100 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_2_100_NS },
|
||||
{ 2250 + YT8531_CCR_RXC_DLY_1_900_NS, YT8531_RC1R_RGMII_2_250_NS }
|
||||
};
|
||||
|
||||
static u32 ytphy_get_delay_reg_value(struct phy_device *phydev,
|
||||
u32 val,
|
||||
u16 *rxc_dly_en)
|
||||
{
|
||||
int tb_size = ARRAY_SIZE(ytphy_rgmii_delays);
|
||||
int tb_size_half = tb_size / 2;
|
||||
int i;
|
||||
|
||||
/* when rxc_dly_en is NULL, it is get the delay for tx, only half of
|
||||
* tb_size is valid.
|
||||
*/
|
||||
if (!rxc_dly_en)
|
||||
tb_size = tb_size_half;
|
||||
|
||||
for (i = 0; i < tb_size; i++) {
|
||||
if (ytphy_rgmii_delays[i].cfg == val) {
|
||||
if (rxc_dly_en && i < tb_size_half)
|
||||
*rxc_dly_en = 0;
|
||||
return ytphy_rgmii_delays[i].reg;
|
||||
}
|
||||
}
|
||||
|
||||
pr_warn("Unsupported value %d, using default (%u)\n",
|
||||
val, YT8531_RC1R_RGMII_1_950_NS);
|
||||
|
||||
/* when rxc_dly_en is not NULL, it is get the delay for rx.
|
||||
* The rx default in dts and ytphy_rgmii_clk_delay_config is 1950 ps,
|
||||
* so YT8531_CCR_RXC_DLY_EN should not be set.
|
||||
*/
|
||||
if (rxc_dly_en)
|
||||
*rxc_dly_en = 0;
|
||||
|
||||
return YT8531_RC1R_RGMII_1_950_NS;
|
||||
}
|
||||
|
||||
static int ytphy_modify_ext(struct phy_device *phydev, u16 regnum, u16 mask,
|
||||
u16 set)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = phy_write(phydev, MDIO_DEVAD_NONE, YTPHY_PAGE_SELECT, regnum);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return phy_modify(phydev, MDIO_DEVAD_NONE, YTPHY_PAGE_DATA, mask, set);
|
||||
}
|
||||
|
||||
static int ytphy_rgmii_clk_delay_config(struct phy_device *phydev)
|
||||
{
|
||||
struct ytphy_plat_priv *priv = phydev->priv;
|
||||
u16 rxc_dly_en = YT8531_CCR_RXC_DLY_EN;
|
||||
u32 rx_reg, tx_reg;
|
||||
u16 mask, val = 0;
|
||||
int ret;
|
||||
|
||||
rx_reg = ytphy_get_delay_reg_value(phydev, priv->rx_delay_ps,
|
||||
&rxc_dly_en);
|
||||
tx_reg = ytphy_get_delay_reg_value(phydev, priv->tx_delay_ps,
|
||||
NULL);
|
||||
|
||||
switch (phydev->interface) {
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
rxc_dly_en = 0;
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
val |= FIELD_PREP(YT8531_RC1R_RX_DELAY_MASK, rx_reg);
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
rxc_dly_en = 0;
|
||||
val |= FIELD_PREP(YT8531_RC1R_GE_TX_DELAY_MASK, tx_reg);
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
val |= FIELD_PREP(YT8531_RC1R_RX_DELAY_MASK, rx_reg) |
|
||||
FIELD_PREP(YT8531_RC1R_GE_TX_DELAY_MASK, tx_reg);
|
||||
break;
|
||||
default: /* do not support other modes */
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ret = ytphy_modify_ext(phydev, YT8531_CHIP_CONFIG_REG,
|
||||
YT8531_CCR_RXC_DLY_EN, rxc_dly_en);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Generally, it is not necessary to adjust YT8531_RC1R_FE_TX_DELAY */
|
||||
mask = YT8531_RC1R_RX_DELAY_MASK | YT8531_RC1R_GE_TX_DELAY_MASK;
|
||||
return ytphy_modify_ext(phydev, YT8531_RGMII_CONFIG1_REG, mask, val);
|
||||
}
|
||||
|
||||
static int yt8531_parse_status(struct phy_device *phydev)
|
||||
{
|
||||
int val;
|
||||
int speed, speed_mode;
|
||||
|
||||
val = phy_read(phydev, MDIO_DEVAD_NONE, YTPHY_SPECIFIC_STATUS_REG);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
speed_mode = (val & YTPHY_SPEED_MODE_MASK) >> YTPHY_SPEED_MODE_SHIFT;
|
||||
switch (speed_mode) {
|
||||
case 2:
|
||||
speed = SPEED_1000;
|
||||
break;
|
||||
case 1:
|
||||
speed = SPEED_100;
|
||||
break;
|
||||
default:
|
||||
speed = SPEED_10;
|
||||
break;
|
||||
}
|
||||
|
||||
phydev->speed = speed;
|
||||
phydev->duplex = (val & YTPHY_DUPLEX_MASK) >> YTPHY_DUPLEX_SHIFT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int yt8531_startup(struct phy_device *phydev)
|
||||
{
|
||||
struct ytphy_plat_priv *priv = phydev->priv;
|
||||
u16 val = 0;
|
||||
int ret;
|
||||
|
||||
ret = genphy_update_link(phydev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = yt8531_parse_status(phydev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (phydev->speed < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(priv->flag & TX_CLK_ADJ_ENABLED))
|
||||
return 0;
|
||||
|
||||
switch (phydev->speed) {
|
||||
case SPEED_1000:
|
||||
if (priv->flag & TX_CLK_1000_INVERTED)
|
||||
val = YT8531_RC1R_TX_CLK_SEL_INVERTED;
|
||||
break;
|
||||
case SPEED_100:
|
||||
if (priv->flag & TX_CLK_100_INVERTED)
|
||||
val = YT8531_RC1R_TX_CLK_SEL_INVERTED;
|
||||
break;
|
||||
case SPEED_10:
|
||||
if (priv->flag & TX_CLK_10_INVERTED)
|
||||
val = YT8531_RC1R_TX_CLK_SEL_INVERTED;
|
||||
break;
|
||||
default:
|
||||
printf("UNKNOWN SPEED\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = ytphy_modify_ext(phydev, YT8531_RGMII_CONFIG1_REG,
|
||||
YT8531_RC1R_TX_CLK_SEL_INVERTED, val);
|
||||
if (ret < 0)
|
||||
pr_warn("Modify TX_CLK_SEL err:%d\n", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ytphy_dt_parse(struct phy_device *phydev)
|
||||
{
|
||||
struct ytphy_plat_priv *priv = phydev->priv;
|
||||
|
||||
priv->clk_out_frequency = ofnode_read_u32_default(phydev->node,
|
||||
"motorcomm,clk-out-frequency-hz",
|
||||
YTPHY_DTS_OUTPUT_CLK_DIS);
|
||||
priv->rx_delay_ps = ofnode_read_u32_default(phydev->node,
|
||||
"rx-internal-delay-ps",
|
||||
YT8531_RC1R_RGMII_1_950_NS);
|
||||
priv->tx_delay_ps = ofnode_read_u32_default(phydev->node,
|
||||
"tx-internal-delay-ps",
|
||||
YT8531_RC1R_RGMII_1_950_NS);
|
||||
|
||||
if (ofnode_read_bool(phydev->node, "motorcomm,auto-sleep-disabled"))
|
||||
priv->flag |= AUTO_SLEEP_DISABLED;
|
||||
|
||||
if (ofnode_read_bool(phydev->node, "motorcomm,keep-pll-enabled"))
|
||||
priv->flag |= KEEP_PLL_ENABLED;
|
||||
|
||||
if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-adj-enabled"))
|
||||
priv->flag |= TX_CLK_ADJ_ENABLED;
|
||||
|
||||
if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-10-inverted"))
|
||||
priv->flag |= TX_CLK_10_INVERTED;
|
||||
|
||||
if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-100-inverted"))
|
||||
priv->flag |= TX_CLK_100_INVERTED;
|
||||
|
||||
if (ofnode_read_bool(phydev->node, "motorcomm,tx-clk-1000-inverted"))
|
||||
priv->flag |= TX_CLK_1000_INVERTED;
|
||||
}
|
||||
|
||||
static int yt8531_config(struct phy_device *phydev)
|
||||
{
|
||||
struct ytphy_plat_priv *priv = phydev->priv;
|
||||
u16 mask, val;
|
||||
int ret;
|
||||
|
||||
ret = genphy_config_aneg(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ytphy_dt_parse(phydev);
|
||||
switch (priv->clk_out_frequency) {
|
||||
case YTPHY_DTS_OUTPUT_CLK_DIS:
|
||||
mask = YT8531_SCR_SYNCE_ENABLE;
|
||||
val = 0;
|
||||
break;
|
||||
case YTPHY_DTS_OUTPUT_CLK_25M:
|
||||
mask = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_SRC_MASK |
|
||||
YT8531_SCR_CLK_FRE_SEL_125M;
|
||||
val = YT8531_SCR_SYNCE_ENABLE |
|
||||
FIELD_PREP(YT8531_SCR_CLK_SRC_MASK,
|
||||
YT8531_SCR_CLK_SRC_REF_25M);
|
||||
break;
|
||||
case YTPHY_DTS_OUTPUT_CLK_125M:
|
||||
mask = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_SRC_MASK |
|
||||
YT8531_SCR_CLK_FRE_SEL_125M;
|
||||
val = YT8531_SCR_SYNCE_ENABLE | YT8531_SCR_CLK_FRE_SEL_125M |
|
||||
FIELD_PREP(YT8531_SCR_CLK_SRC_MASK,
|
||||
YT8531_SCR_CLK_SRC_PLL_125M);
|
||||
break;
|
||||
default:
|
||||
pr_warn("Freq err:%u\n", priv->clk_out_frequency);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = ytphy_modify_ext(phydev, YTPHY_SYNCE_CFG_REG, mask,
|
||||
val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ytphy_rgmii_clk_delay_config(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (priv->flag & AUTO_SLEEP_DISABLED) {
|
||||
/* disable auto sleep */
|
||||
ret = ytphy_modify_ext(phydev,
|
||||
YT8531_EXTREG_SLEEP_CONTROL1_REG,
|
||||
YT8531_ESC1R_SLEEP_SW, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (priv->flag & KEEP_PLL_ENABLED) {
|
||||
/* enable RXC clock when no wire plug */
|
||||
ret = ytphy_modify_ext(phydev,
|
||||
YT8531_CLOCK_GATING_REG,
|
||||
YT8531_CGR_RX_CLK_EN, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int yt8531_probe(struct phy_device *phydev)
|
||||
{
|
||||
struct ytphy_plat_priv *priv;
|
||||
|
||||
priv = calloc(1, sizeof(struct ytphy_plat_priv));
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
phydev->priv = priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_PHY_DRIVER(motorcomm8531) = {
|
||||
.name = "YT8531 Gigabit Ethernet",
|
||||
.uid = PHY_ID_YT8531,
|
||||
.mask = PHY_ID_MASK,
|
||||
.features = PHY_GBIT_FEATURES,
|
||||
.probe = &yt8531_probe,
|
||||
.config = &yt8531_config,
|
||||
.startup = &yt8531_startup,
|
||||
.shutdown = &genphy_shutdown,
|
||||
};
|
|
@ -72,8 +72,6 @@ static int starfive_ddr_probe(struct udevice *dev)
|
|||
u64 rate;
|
||||
int ret;
|
||||
|
||||
/* Read memory base and size from DT */
|
||||
fdtdec_setup_mem_size_base();
|
||||
priv->info.base = gd->ram_base;
|
||||
priv->info.size = gd->ram_size;
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ obj-$(CONFIG_RISCV_TIMER) += riscv_timer.o
|
|||
obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o
|
||||
obj-$(CONFIG_SANDBOX_TIMER) += sandbox_timer.o
|
||||
obj-$(CONFIG_SP804_TIMER) += sp804_timer.o
|
||||
obj-$(CONFIG_$(SPL_)SIFIVE_CLINT) += sifive_clint_timer.o
|
||||
obj-$(CONFIG_$(SPL_)RISCV_ACLINT) += riscv_aclint_timer.o
|
||||
obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o
|
||||
obj-$(CONFIG_STM32_TIMER) += stm32_timer.o
|
||||
obj-$(CONFIG_TEGRA_TIMER) += tegra-timer.o
|
||||
|
|
74
drivers/timer/riscv_aclint_timer.c
Normal file
74
drivers/timer/riscv_aclint_timer.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2020, Sean Anderson <seanga2@gmail.com>
|
||||
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <timer.h>
|
||||
#include <asm/io.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#define CLINT_MTIME_OFFSET 0xbff8
|
||||
#define ACLINT_MTIME_OFFSET 0
|
||||
|
||||
/* mtime register */
|
||||
#define MTIME_REG(base, offset) ((ulong)(base) + (offset))
|
||||
|
||||
static u64 notrace riscv_aclint_timer_get_count(struct udevice *dev)
|
||||
{
|
||||
return readq((void __iomem *)MTIME_REG(dev_get_priv(dev),
|
||||
dev_get_driver_data(dev)));
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(RISCV_MMODE) && IS_ENABLED(CONFIG_TIMER_EARLY)
|
||||
/**
|
||||
* timer_early_get_rate() - Get the timer rate before driver model
|
||||
*/
|
||||
unsigned long notrace timer_early_get_rate(void)
|
||||
{
|
||||
return RISCV_MMODE_TIMER_FREQ;
|
||||
}
|
||||
|
||||
/**
|
||||
* timer_early_get_count() - Get the timer count before driver model
|
||||
*
|
||||
*/
|
||||
u64 notrace timer_early_get_count(void)
|
||||
{
|
||||
return readq((void __iomem *)MTIME_REG(RISCV_MMODE_TIMERBASE,
|
||||
RISCV_MMODE_TIMEROFF));
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct timer_ops riscv_aclint_timer_ops = {
|
||||
.get_count = riscv_aclint_timer_get_count,
|
||||
};
|
||||
|
||||
static int riscv_aclint_timer_probe(struct udevice *dev)
|
||||
{
|
||||
dev_set_priv(dev, dev_read_addr_ptr(dev));
|
||||
if (!dev_get_priv(dev))
|
||||
return -EINVAL;
|
||||
|
||||
return timer_timebase_fallback(dev);
|
||||
}
|
||||
|
||||
static const struct udevice_id riscv_aclint_timer_ids[] = {
|
||||
{ .compatible = "riscv,clint0", .data = CLINT_MTIME_OFFSET },
|
||||
{ .compatible = "sifive,clint0", .data = CLINT_MTIME_OFFSET },
|
||||
{ .compatible = "riscv,aclint-mtimer", .data = ACLINT_MTIME_OFFSET },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(riscv_aclint_timer) = {
|
||||
.name = "riscv_aclint_timer",
|
||||
.id = UCLASS_TIMER,
|
||||
.of_match = riscv_aclint_timer_ids,
|
||||
.probe = riscv_aclint_timer_probe,
|
||||
.ops = &riscv_aclint_timer_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
|
@ -1,68 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2020, Sean Anderson <seanga2@gmail.com>
|
||||
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <timer.h>
|
||||
#include <asm/io.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/* mtime register */
|
||||
#define MTIME_REG(base) ((ulong)(base) + 0xbff8)
|
||||
|
||||
static u64 notrace sifive_clint_get_count(struct udevice *dev)
|
||||
{
|
||||
return readq((void __iomem *)MTIME_REG(dev_get_priv(dev)));
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(RISCV_MMODE) && IS_ENABLED(CONFIG_TIMER_EARLY)
|
||||
/**
|
||||
* timer_early_get_rate() - Get the timer rate before driver model
|
||||
*/
|
||||
unsigned long notrace timer_early_get_rate(void)
|
||||
{
|
||||
return RISCV_MMODE_TIMER_FREQ;
|
||||
}
|
||||
|
||||
/**
|
||||
* timer_early_get_count() - Get the timer count before driver model
|
||||
*
|
||||
*/
|
||||
u64 notrace timer_early_get_count(void)
|
||||
{
|
||||
return readq((void __iomem *)MTIME_REG(RISCV_MMODE_TIMERBASE));
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct timer_ops sifive_clint_ops = {
|
||||
.get_count = sifive_clint_get_count,
|
||||
};
|
||||
|
||||
static int sifive_clint_probe(struct udevice *dev)
|
||||
{
|
||||
dev_set_priv(dev, dev_read_addr_ptr(dev));
|
||||
if (!dev_get_priv(dev))
|
||||
return -EINVAL;
|
||||
|
||||
return timer_timebase_fallback(dev);
|
||||
}
|
||||
|
||||
static const struct udevice_id sifive_clint_ids[] = {
|
||||
{ .compatible = "riscv,clint0" },
|
||||
{ .compatible = "sifive,clint0" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sifive_clint) = {
|
||||
.name = "sifive_clint",
|
||||
.id = UCLASS_TIMER,
|
||||
.of_match = sifive_clint_ids,
|
||||
.probe = sifive_clint_probe,
|
||||
.ops = &sifive_clint_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
|
@ -11,8 +11,8 @@
|
|||
#define CFG_SYS_SDRAM_BASE 0x80000000
|
||||
|
||||
#define RISCV_MMODE_TIMERBASE 0x2000000
|
||||
#define RISCV_MMODE_TIMEROFF 0xbff8
|
||||
#define RISCV_MMODE_TIMER_FREQ 1000000
|
||||
|
||||
#define RISCV_SMODE_TIMER_FREQ 1000000
|
||||
|
||||
/* Environment options */
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
#define CFG_SYS_SDRAM_BASE 0x80000000
|
||||
|
||||
#define RISCV_MMODE_TIMERBASE 0x2000000
|
||||
#define RISCV_MMODE_TIMEROFF 0xbff8
|
||||
#define RISCV_MMODE_TIMER_FREQ 1000000
|
||||
|
||||
#define RISCV_SMODE_TIMER_FREQ 1000000
|
||||
|
||||
/* Environment options */
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#define _STARFIVE_VISIONFIVE2_H
|
||||
|
||||
#define RISCV_MMODE_TIMERBASE 0x2000000
|
||||
#define RISCV_MMODE_TIMEROFF 0xbff8
|
||||
#define RISCV_MMODE_TIMER_FREQ 4000000
|
||||
#define RISCV_SMODE_TIMER_FREQ 4000000
|
||||
|
||||
|
|
22
include/configs/th1520_lpi4a.h
Normal file
22
include/configs/th1520_lpi4a.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (c) 2023 Yixun Lan <dlan@gentoo.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TH1520_LPI4A_H
|
||||
#define __TH1520_LPI4A_H
|
||||
|
||||
#include <linux/sizes.h>
|
||||
|
||||
#define CFG_SYS_SDRAM_BASE 0x00000000
|
||||
|
||||
#define UART_BASE 0xffe7014000
|
||||
#define UART_REG_WIDTH 32
|
||||
|
||||
/* Environment options */
|
||||
|
||||
#define CFG_EXTRA_ENV_SETTINGS \
|
||||
"PS1=[LPi4A]# \0"
|
||||
|
||||
#endif /* __TH1520_LPI4A_H */
|
Loading…
Reference in a new issue