From 93cc1e2b6d33b9fd588a640ba161f6db377d6181 Mon Sep 17 00:00:00 2001 From: Hal Feng Date: Wed, 9 Aug 2023 14:06:59 +0800 Subject: board: starfive: Add StarFive VisionFive 2 board support Add board support for StarFive VisionFive 2. The code is ported from tag JH7110_VF2_515_v3.9.3 of VF2 repo. Signed-off-by: Hal Feng --- board/starfive/visionfive2/starfive_visionfive2.c | 547 ++++++++++++++++++++++ 1 file changed, 547 insertions(+) create mode 100644 board/starfive/visionfive2/starfive_visionfive2.c (limited to 'board/starfive/visionfive2/starfive_visionfive2.c') diff --git a/board/starfive/visionfive2/starfive_visionfive2.c b/board/starfive/visionfive2/starfive_visionfive2.c new file mode 100644 index 0000000000..1d14c618dc --- /dev/null +++ b/board/starfive/visionfive2/starfive_visionfive2.c @@ -0,0 +1,547 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 Starfive, Inc. + * Author: yanhong + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SYS_CLOCK_ENABLE(clk) \ + setbits_le32(SYS_CRG_BASE + clk, CLK_ENABLE_MASK) + +#define PCB_REVISION_MASK 0xF0 +#define PCB_REVISION_SHIFT 4 +#define PCB_REVISION_A 0x0A +#define PCB_REVISION_B 0x0B +#define CHIP_REVISION_SHIFT 80 + +#define CPU_VOL_BINNING_OFFSET 0x7fc + +enum { + BOOT_FLASH = 0, + BOOT_SD, + BOOT_EMMC, + BOOT_UART, +}; + +enum chip_type_t { + CHIP_A = 0, + CHIP_B, + CHIP_MAX, +}; + +enum board_type_t { + BOARD_1000M_1000M = 0, + BOARD_1000M_100M, + BOARD_TYPE_MAX, +}; + + +enum cpu_voltage_type_t { + CPU_VOL_1020 = 0xef0, + CPU_VOL_1040 = 0xfff, + CPU_VOL_1060 = 0xff0, + CPU_VOL_1000 = 0x8f0, +}; +#define CPU_VOL_MASK 0xfff + +static void sys_reset_clear(ulong assert, ulong status, u32 rst) +{ + u32 value; + + clrbits_le32(SYS_CRG_BASE + assert, BIT(rst)); + do { + value = in_le32(SYS_CRG_BASE + status); + } while ((value & BIT(rst)) != BIT(rst)); +} + +static void jh7110_timer_init(void) +{ + SYS_CLOCK_ENABLE(TIMER_CLK_APB_SHIFT); + SYS_CLOCK_ENABLE(TIMER_CLK_TIMER0_SHIFT); + SYS_CLOCK_ENABLE(TIMER_CLK_TIMER1_SHIFT); + SYS_CLOCK_ENABLE(TIMER_CLK_TIMER2_SHIFT); + SYS_CLOCK_ENABLE(TIMER_CLK_TIMER3_SHIFT); + + sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT, + SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_APB_SHIFT); + sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT, + SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_TIMER0_SHIFT); + sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT, + SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_TIMER1_SHIFT); + sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT, + SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_TIMER2_SHIFT); + sys_reset_clear(SYS_CRG_RESET_ASSERT3_SHIFT, + SYS_CRG_RESET_STATUS3_SHIFT, TIMER_RSTN_TIMER3_SHIFT); +} + +static void jh7110_gmac_init_1000M(int id) +{ + switch (id) { + case 0: + clrsetbits_le32(AON_SYSCON_BASE + AON_SYSCFG_12, + GMAC5_0_SEL_I_MASK, + BIT(GMAC5_0_SEL_I_SHIFT) & GMAC5_0_SEL_I_MASK); + break; + + case 1: + clrsetbits_le32(SYS_SYSCON_BASE + SYS_SYSCON_144, + GMAC5_1_SEL_I_MASK, + BIT(GMAC5_1_SEL_I_SHIFT) & GMAC5_1_SEL_I_MASK); + break; + + default: + break; + } +} + +static void jh7110_gmac_init_100M(int id) +{ + switch (id) { + case 0: + clrsetbits_le32(AON_SYSCON_BASE + AON_SYSCFG_12, + GMAC5_0_SEL_I_MASK, + (4 << GMAC5_0_SEL_I_SHIFT) & GMAC5_0_SEL_I_MASK); + setbits_le32(AON_CRG_BASE + GMAC5_0_CLK_TX_SHIFT, 0x1000000); + setbits_le32(AON_CRG_BASE + GMAC5_0_CLK_RX_SHIFT, 0x1000000); + break; + + case 1: + clrsetbits_le32(SYS_SYSCON_BASE + SYS_SYSCON_144, + GMAC5_1_SEL_I_MASK, + (4 << GMAC5_1_SEL_I_SHIFT) & GMAC5_1_SEL_I_MASK); + setbits_le32(SYS_CRG_BASE + GMAC5_1_CLK_TX_SHIFT, 0x1000000); + setbits_le32(SYS_CRG_BASE + GMAC5_1_CLK_RX_SHIFT, 0x1000000); + break; + + default: + break; + } +} + +static void jh7110_gmac_sel_tx_to_rgmii(int id) +{ + switch (id) { + case 0: + clrsetbits_le32(AON_CRG_BASE + GMAC5_0_CLK_TX_SHIFT, + GMAC5_0_CLK_TX_MASK, + BIT(GMAC5_0_CLK_TX_BIT) & GMAC5_0_CLK_TX_MASK); + break; + + case 1: + clrsetbits_le32(SYS_CRG_BASE + GMAC5_1_CLK_TX_SHIFT, + GMAC5_1_CLK_TX_MASK, + BIT(GMAC5_1_CLK_TX_BIT) & GMAC5_1_CLK_TX_MASK); + break; + + default: + break; + } +} + +static void set_uboot_fdt_addr_env(void) +{ + char str[17]; + ulong fdt_addr = (ulong)gd->fdt_blob; + + sprintf(str, "0x%lx", fdt_addr); + env_set("uboot_fdt_addr", str); +} + +static int get_chip_type(void) +{ + int type; + int len = -1; + u8 data; + + len = get_data_from_eeprom(CHIP_REVISION_SHIFT, 1, &data); + if (len <= 0) { + env_set("chip_vision", "UNKOWN"); + return -EINVAL; + } + + switch (data) { + case 'a': + case 'A': + type = CHIP_A; + env_set("chip_vision", "A"); + break; + case 'b': + case 'B': + type = CHIP_B; + env_set("chip_vision", "B"); + break; + default: + type = CHIP_MAX; + env_set("chip_vision", "UNKOWN"); + break; + } + return type; +} +static int get_board_type(void) +{ + u8 pv; + int type; + + pv = get_pcb_revision_from_eeprom(); + pv = (pv & PCB_REVISION_MASK) >> PCB_REVISION_SHIFT; + + if (pv == PCB_REVISION_A) { + type = BOARD_1000M_100M; + } else if (pv == PCB_REVISION_B) { + type = BOARD_1000M_1000M; + } else { + type = BOARD_TYPE_MAX; + } + + return type; +} + +static void jh7110_gmac_init(int chip_type, int pcb_type) +{ + switch (chip_type) { + case CHIP_A: + break; + case CHIP_B: + default: + jh7110_gmac_sel_tx_to_rgmii(0); + jh7110_gmac_sel_tx_to_rgmii(1); + break; + } + + switch (pcb_type) { + case BOARD_1000M_100M: + jh7110_gmac_init_1000M(0); + jh7110_gmac_init_100M(1); + break; + + case BOARD_1000M_1000M: + default: + jh7110_gmac_init_1000M(0); + jh7110_gmac_init_1000M(1); + break; + } +} + +static void jh7110_usb_init(bool usb2_enable) +{ + if (usb2_enable) { + /*usb 2.0 utmi phy init*/ + clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_4, + USB_MODE_STRAP_MASK, + (2<ram_base); + env_set_hex("memory_size", gd->ram_size); + + ret = uclass_get_device(UCLASS_VIDEO, 0, &dev); + if (ret) + return ret; + + ret = video_bmp_display(dev, (ulong)&bmp_logo_bitmap[0], BMP_ALIGN_CENTER, BMP_ALIGN_CENTER, true); + if (ret) + goto err; + +err: + return 0; +} +#endif + +#ifdef CONFIG_MISC_INIT_R + +int misc_init_r(void) +{ + char mac0[6] = {0x6c, 0xcf, 0x39, 0x6c, 0xde, 0xad}; + char mac1[6] = {0x6c, 0xcf, 0x39, 0x7c, 0xae, 0x5d}; + +#if CONFIG_IS_ENABLED(STARFIVE_OTP) + struct udevice *dev; + char buf[16]; + int ret; +#define MACADDR_OFFSET 0x8 + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_DRIVER_GET(starfive_otp), &dev); + if (ret) { + debug("%s: could not find otp device\n", __func__); + goto err; + } + + ret = misc_read(dev, MACADDR_OFFSET, buf, sizeof(buf)); + if (ret != sizeof(buf)) + printf("%s: error reading mac from OTP\n", __func__); + else + if (buf[0] != 0xff) { + memcpy(mac0, buf, 6); + memcpy(mac1, &buf[8], 6); + } +err: +#endif + eth_env_set_enetaddr("eth0addr", mac0); + eth_env_set_enetaddr("eth1addr", mac1); + + get_chip_type(); + set_uboot_fdt_addr_env(); +#if CONFIG_IS_ENABLED(STARFIVE_OTP) + get_cpu_voltage_type(dev); +#endif + return 0; +} +#endif + +#ifdef CONFIG_ID_EEPROM + +#include +#define STARFIVE_JH7110_EEPROM_DDRINFO_OFFSET 91 + +static bool check_eeprom_dram_info(ulong size) +{ + switch (size) { + case 1: + case 2: + case 4: + case 8: + case 16: + return true; + default: + return false; + } +} + +static int resize_ddr_from_eeprom(void) +{ + struct udevice *dev; + ulong size; + u32 len = 1; + u8 data = 0; + int ret; + + /* I2C init */ + ret = uclass_get_device(UCLASS_I2C, 0, &dev); + if (ret) { + debug("I2C init failed: %d\n", ret); + return 0; + } + + /* read memory size info */ + ret = get_data_from_eeprom(STARFIVE_JH7110_EEPROM_DDRINFO_OFFSET, len, &data); + if (ret == len) { + size = hextoul(&data, NULL); + if (check_eeprom_dram_info(size)) + return size; + } + return 0; +} +#else +static int resize_ddr_from_eeprom(void) +{ + return 0; +} +#endif /* CONFIG_ID_EEPROM */ + +int board_ddr_size(void) +{ + return resize_ddr_from_eeprom(); +} -- cgit v1.2.3