summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHal Feng <hal.feng@starfivetech.com>2023-08-09 09:06:59 +0300
committerHal Feng <hal.feng@starfivetech.com>2023-11-29 05:51:13 +0300
commit4d348e3fb479c1462f408db1ae6f6ba124ec6b17 (patch)
tree7a3a45d8fb69eaeb977e44b47467f78b3732e7c6
parent60884ca5ec70d8f03d342c69e5f807a76a2a4f47 (diff)
downloadu-boot-4d348e3fb479c1462f408db1ae6f6ba124ec6b17.tar.xz
board: starfive: Add StarFive Devkits board support
Add board support for StarFive Devkits. The code is ported from tag JH7110_DVK_515_v3.9.3 of Devkits repo. Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
-rw-r--r--board/starfive/devkits/Kconfig52
-rw-r--r--board/starfive/devkits/MAINTAINERS7
-rw-r--r--board/starfive/devkits/Makefile10
-rw-r--r--board/starfive/devkits/devkits-i2c-eeprom.c758
-rw-r--r--board/starfive/devkits/spl.c166
-rw-r--r--board/starfive/devkits/starfive_devkits.c482
-rw-r--r--include/configs/starfive-devkits.h405
7 files changed, 1880 insertions, 0 deletions
diff --git a/board/starfive/devkits/Kconfig b/board/starfive/devkits/Kconfig
new file mode 100644
index 0000000000..b5db828ae2
--- /dev/null
+++ b/board/starfive/devkits/Kconfig
@@ -0,0 +1,52 @@
+if TARGET_STARFIVE_DEVKITS
+
+config SYS_CPU
+ default "jh7110"
+
+config SYS_BOARD
+ default "devkits"
+
+config SYS_VENDOR
+ default "starfive"
+
+config SYS_CONFIG_NAME
+ default "starfive-devkits"
+
+config ENV_SIZE
+ default 0x2000 if ENV_IS_IN_SPI_FLASH
+
+config ENV_OFFSET
+ default 0x140000 if ENV_IS_IN_SPI_FLASH
+
+config SYS_TEXT_BASE
+ default 0x40200000 if SPL
+ default 0x40000000 if !RISCV_SMODE
+ default 0x40200000 if RISCV_SMODE
+
+config SPL_TEXT_BASE
+ default 0x08000000
+
+config SPL_OPENSBI_LOAD_ADDR
+ default 0x80000000
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+ def_bool y
+ select STARFIVE_JH7110
+ imply CMD_DHCP
+ imply CMD_EXT2
+ imply CMD_EXT4
+ imply CMD_FAT
+ imply CMD_FS_GENERIC
+ imply CMD_GPT
+ imply PARTITION_TYPE_GUID
+ imply CMD_NET
+ imply CMD_PING
+ imply CMD_SF
+ imply DOS_PARTITION
+ imply EFI_PARTITION
+ imply IP_DYN
+ imply ISO_PARTITION
+ imply PHY_LIB
+ imply PHY_MSCC
+
+endif
diff --git a/board/starfive/devkits/MAINTAINERS b/board/starfive/devkits/MAINTAINERS
new file mode 100644
index 0000000000..f6eee7e833
--- /dev/null
+++ b/board/starfive/devkits/MAINTAINERS
@@ -0,0 +1,7 @@
+STARFIVE JH7110 DevKits BOARD
+M: Yanhong Wang <yanhong.wang@starfivetech.com>
+S: Maintained
+F: arch/riscv/include/asm/arch-jh7110/
+F: board/starfive/devkits/
+F: include/configs/starfive-devkits.h
+F: configs/starfive_devkits_defconfig
diff --git a/board/starfive/devkits/Makefile b/board/starfive/devkits/Makefile
new file mode 100644
index 0000000000..40dc09b706
--- /dev/null
+++ b/board/starfive/devkits/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2021 Shanghai StarFive Technology Co., Ltd.
+#
+
+obj-y := starfive_devkits.o
+
+obj-$(CONFIG_SPL_BUILD) += spl.o
+
+obj-$(CONFIG_ID_EEPROM) += devkits-i2c-eeprom.o
diff --git a/board/starfive/devkits/devkits-i2c-eeprom.c b/board/starfive/devkits/devkits-i2c-eeprom.c
new file mode 100644
index 0000000000..55fbda3bcf
--- /dev/null
+++ b/board/starfive/devkits/devkits-i2c-eeprom.c
@@ -0,0 +1,758 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
+ * Written by Wei Fu (wefu@redhat.com)
+ */
+
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <i2c.h>
+#include <init.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+//#include <u-boot/crc.h>
+/*
+ * MAGIC_NUMBER_BYTES: number of bytes used by the magic number
+ */
+#define MAGIC_NUMBER_BYTES 4
+
+/*
+ * SERIAL_NUMBER_BYTES: number of bytes used by the board serial
+ * number
+ */
+//#define SERIAL_NUMBER_BYTES 16
+
+/*
+ * MAC_ADDR_BYTES: number of bytes used by the Ethernet MAC address
+ */
+#define MAC_ADDR_BYTES 6
+
+/*
+ * MAC_ADDR_STRLEN: length of mac address string
+ */
+#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_hats_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_hats_atom_header {
+ u16 type;
+ u16 count;
+ u32 dlen;
+};
+
+/**
+ * static eeprom: EEPROM layout for the StarFive platform I2C format
+ */
+struct starfive_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_hats_atom_header header;
+ struct starfive_eeprom_atom1_data data;
+ u16 crc16;
+};
+
+struct starfive_eeprom_atom4_v1_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_v1 {
+ struct eeprom_hats_atom_header header;
+ struct starfive_eeprom_atom4_v1_data data;
+ u16 crc16;
+};
+
+/* Set to 1 if we've read EEPROM into memory
+ * Set to -1 if EEPROM data is wrong
+ */
+static int has_been_read;
+
+/**
+ * helper struct for getting info from the local EEPROM copy.
+ * most of the items are pointers to the eeprom_wp_buff.
+ * ONLY serialnum is the u32 from the last 8 Bytes of product string
+ */
+struct starfive_eeprom_info {
+ char *vstr; /* Vendor string in ATOM1 */
+ char *pstr; /* product string in ATOM1 */
+ u32 serialnum; /* serial number from in product string*/
+ u16 *version; /* custom data version in ATOM4 */
+ u8 *pcb_revision; /* PCB version in ATOM4 */
+ u8 *bom_revision; /* BOM version in ATOM4 */
+ u8 *mac0_addr; /* Ethernet0 MAC in ATOM4 */
+ u8 *mac1_addr; /* Ethernet1 MAC in ATOM4 */
+};
+static struct starfive_eeprom_info einfo;
+
+
+static uchar eeprom_wp_buff[STARFIVE_EEPROM_HATS_SIZE_MAX];
+static struct eeprom_hats_header starfive_eeprom_hats_header_default = {
+ .signature = STARFIVE_EEPROM_HATS_SIG,
+ .version = FORMAT_VERSION,
+ .numatoms = 2,
+ .eeplen = sizeof(struct eeprom_hats_header) +
+ sizeof(struct starfive_eeprom_atom1) +
+ sizeof(struct starfive_eeprom_atom4_v1)
+};
+static struct starfive_eeprom_atom1 starfive_eeprom_atom1_default = {
+ .header = {
+ .type = HATS_ATOM_VENDOR,
+ .count = 1,
+ .dlen = sizeof(struct starfive_eeprom_atom1_data) + sizeof(u16)
+ },
+ .data = {
+ .uuid = {0},
+ .pid = 0,
+ .pver = 0,
+ .vslen = STARFIVE_EEPROM_ATOM1_VSTR_SIZE,
+ .pslen = STARFIVE_EEPROM_ATOM1_PSTR_SIZE,
+ .vstr = STARFIVE_EEPROM_ATOM1_VSTR,
+ .pstr = STARFIVE_EEPROM_ATOM1_PSTR
+ }
+};
+static struct starfive_eeprom_atom4_v1 starfive_eeprom_atom4_v1_default = {
+ .header = {
+ .type = HATS_ATOM_CUSTOM,
+ .count = 2,
+ .dlen = sizeof(struct starfive_eeprom_atom4_v1_data) + sizeof(u16)
+ },
+ .data = {
+ .version = FORMAT_VERSION,
+ .pcb_revision = PCB_VERSION,
+ .bom_revision = BOM_VERSION,
+ .mac0_addr = STARFIVE_DEFAULT_MAC0,
+ .mac1_addr = STARFIVE_DEFAULT_MAC1,
+ .reserved = {0}
+ }
+};
+
+//static u8 starfive_default_mac[MAC_ADDR_BYTES] = STARFIVE_DEFAULT_MAC;
+
+/**
+ * is_match_magic() - Does the magic number match that of a StarFive EEPROM?
+ *
+ * @hats: the pointer of eeprom_hats_header
+ * Return: status code, 0: Yes, non-0: NO
+ */
+static inline int is_match_magic(char *hats)
+{
+ return strncmp(hats, STARFIVE_EEPROM_HATS_SIG, MAGIC_NUMBER_BYTES);
+}
+
+/**
+ * calculate_crc16() - Calculate the current CRC for atom
+ * Porting from https://github.com/raspberrypi/hats, getcrc
+ * @data: the pointer of eeprom_hats_atom_header
+ * @size: total length in bytes of the entire atom
+ * (type, count, dlen, data)
+ * Return: result: crc16 code
+ */
+#define CRC16 0x8005
+static u16 calculate_crc16(uchar* data, unsigned int size)
+{
+ int i, j = 0x0001;
+ u16 out = 0, crc = 0;
+ int bits_read = 0, bit_flag;
+
+ /* Sanity check: */
+ if((data == NULL) || size == 0)
+ return 0;
+
+ while(size > 0) {
+ bit_flag = out >> 15;
+
+ /* Get next bit: */
+ out <<= 1;
+ // item a) work from the least significant bits
+ out |= (*data >> bits_read) & 1;
+
+ /* Increment bit counter: */
+ bits_read++;
+ if(bits_read > 7) {
+ bits_read = 0;
+ data++;
+ size--;
+ }
+
+ /* Cycle check: */
+ if(bit_flag)
+ out ^= CRC16;
+ }
+
+ // item b) "push out" the last 16 bits
+ for (i = 0; i < 16; ++i) {
+ bit_flag = out >> 15;
+ out <<= 1;
+ if(bit_flag)
+ out ^= CRC16;
+ }
+
+ // item c) reverse the bits
+ for (i = 0x8000; i != 0; i >>=1, j <<= 1) {
+ if (i & out)
+ crc |= j;
+ }
+
+ return crc;
+}
+
+/* This function should be called after each update to any EEPROM ATOM */
+static inline void update_crc(struct eeprom_hats_atom_header *atom)
+{
+ uint atom_crc_offset = sizeof(struct eeprom_hats_atom_header) +
+ atom->dlen - sizeof(u16);
+ u16 *atom_crc_p = (void *) atom + atom_crc_offset;
+ *atom_crc_p = calculate_crc16((uchar*) atom, atom_crc_offset);
+}
+
+/**
+ * dump_raw_eeprom - display the raw contents of the EEPROM
+ */
+static void dump_raw_eeprom(u8 *e, unsigned int size)
+{
+ unsigned int i;
+
+ printf("EEPROM dump: (0x%x bytes)\n", size);
+
+ for (i = 0; i < size; i++) {
+ if (!(i % 0x10))
+ printf("%02X: ", i);
+
+ printf("%02X ", e[i]);
+
+ if (((i % 16) == 15) || (i == size - 1))
+ printf("\n");
+ }
+
+ return;
+}
+
+static int hats_atom_crc_check(struct eeprom_hats_atom_header *atom)
+{
+ u16 atom_crc, data_crc;
+ uint atom_crc_offset = sizeof(struct eeprom_hats_atom_header) +
+ atom->dlen - sizeof(atom_crc);
+ u16 *atom_crc_p = (void *) atom + atom_crc_offset;
+
+ atom_crc = *atom_crc_p;
+ data_crc = calculate_crc16((uchar *) atom, atom_crc_offset);
+ if (atom_crc == data_crc)
+ return 0;
+
+ printf("EEPROM HATs: CRC ERROR in atom %x type %x, (%x!=%x)\n",
+ atom->count, atom->type, atom_crc, data_crc);
+ return -1;
+}
+
+static void *hats_get_atom(struct eeprom_hats_header *header, u16 type)
+ {
+ struct eeprom_hats_atom_header *atom;
+ void *hats_eeprom_max = (void *)header + header->eeplen;
+ void *temp = (void *)header + sizeof(struct eeprom_hats_header);
+
+ for (int numatoms = (int)header->numatoms; numatoms > 0; numatoms--) {
+ atom = (struct eeprom_hats_atom_header *)temp;
+ if (hats_atom_crc_check(atom))
+ return NULL;
+ if (atom->type == type)
+ return (void *)atom;
+ /* go to next atom */
+ temp = (void *)atom + sizeof(struct eeprom_hats_atom_header) +
+ atom->dlen;
+ if (temp > hats_eeprom_max) {
+ printf("EEPROM HATs: table overflow next@%p, max@%p\n",
+ temp, hats_eeprom_max);
+ break;
+ }
+ }
+
+ /* fail to get atom */
+ return NULL;
+}
+
+/**
+ * show_eeprom - display the contents of the EEPROM
+ */
+static void show_eeprom(struct starfive_eeprom_info *einfo)
+{
+ if (has_been_read != 1)
+ return;
+
+ printf("\n--------EEPROM INFO--------\n");
+ printf("Vendor : %s\n", einfo->vstr);
+ printf("Product full SN: %s\n", einfo->pstr);
+ printf("data version: 0x%x\n", *einfo->version);
+ if (1 == *einfo->version) {
+ printf("PCB revision: 0x%x\n", *einfo->pcb_revision);
+ printf("BOM revision: %c\n", *einfo->bom_revision);
+ printf("Ethernet MAC0 address: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ einfo->mac0_addr[0], einfo->mac0_addr[1],
+ einfo->mac0_addr[2], einfo->mac0_addr[3],
+ einfo->mac0_addr[4], einfo->mac0_addr[5]);
+ printf("Ethernet MAC1 address: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ einfo->mac1_addr[0], einfo->mac1_addr[1],
+ einfo->mac1_addr[2], einfo->mac1_addr[3],
+ einfo->mac1_addr[4], einfo->mac1_addr[5]);
+ } else {
+ printf("Custom data v%d is not Supported\n", *einfo->version);
+ }
+ printf("--------EEPROM INFO--------\n\n");
+}
+
+/**
+ * parse_eeprom_info - parse the contents of the EEPROM
+ * If everthing gose right,
+ * 1, set has_been_read to 1
+ * 2, display info
+ *
+ * If anything goes wrong,
+ * 1, set has_been_read to -1
+ * 2, dump data by hex for debug
+ *
+ * @buf: the pointer of eeprom_hats_header in memory
+ * Return: status code, 0: Success, non-0: Fail
+ *
+ */
+static int parse_eeprom_info(struct eeprom_hats_header *buf)
+{
+ struct eeprom_hats_atom_header *atom;
+ void *atom_data;
+ struct starfive_eeprom_atom1_data *atom1 = NULL;
+ struct starfive_eeprom_atom4_v1_data *atom4_v1 = NULL;
+
+ if (is_match_magic((char *)buf)) {
+ printf("Not a StarFive EEPROM data format - magic error\n");
+ goto error;
+ };
+
+ printf("StarFive EEPROM format v%u\n", buf->version);
+
+ // parse atom1(verdor)
+ atom = (struct eeprom_hats_atom_header *)
+ hats_get_atom(buf, HATS_ATOM_VENDOR);
+ if (atom) {
+ atom_data = (void *)atom +
+ sizeof(struct eeprom_hats_atom_header);
+ atom1 = (struct starfive_eeprom_atom1_data *)atom_data;
+ einfo.vstr = atom1->vstr;
+ einfo.pstr = atom1->pstr;
+ einfo.serialnum = (u32)hextoul((void *)atom1->pstr +
+ STARFIVE_EEPROM_ATOM1_SN_OFFSET,
+ NULL);
+ } else {
+ printf("fail to get vendor atom\n");
+ goto error;
+ };
+
+ // parse atom4(custom)
+ atom = (struct eeprom_hats_atom_header *)
+ hats_get_atom(buf, HATS_ATOM_CUSTOM);
+ if (atom) {
+ atom_data = (void *)atom +
+ sizeof(struct eeprom_hats_atom_header);
+ atom4_v1 = (struct starfive_eeprom_atom4_v1_data *)atom_data;
+ einfo.version = &atom4_v1->version;
+ if (*einfo.version == 1) {
+ einfo.pcb_revision = &atom4_v1->pcb_revision;
+ einfo.bom_revision = &atom4_v1->bom_revision;
+ einfo.mac0_addr = atom4_v1->mac0_addr;
+ einfo.mac1_addr = atom4_v1->mac1_addr;
+ }
+ } else {
+ printf("fail to get custom data atom\n");
+ goto error;
+ };
+
+ // everthing gose right
+ has_been_read = 1;
+ show_eeprom(&einfo);
+ return 0;
+
+error:
+ has_been_read = -1;
+ dump_raw_eeprom(eeprom_wp_buff,
+ STARFIVE_EEPROM_HATS_SIZE_MAX);
+ return -1;
+}
+
+/**
+ * read_eeprom() - read the EEPROM into memory, if it hasn't been read yet
+ * @buf: the pointer of eeprom data buff
+ * Return: status code, 0: Success, non-0: Fail
+ * Note: depend on CONFIG_SYS_EEPROM_BUS_NUM
+ * CONFIG_SYS_I2C_EEPROM_ADDR
+ * STARFIVE_EEPROM_WP_OFFSET
+ * STARFIVE_EEPROM_HATS_SIZE_MAX
+ */
+static int read_eeprom(uint8_t *buf)
+{
+ 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,
+ CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
+ &dev);
+ if (!ret) {
+ ret = dm_i2c_read(dev, STARFIVE_EEPROM_WP_OFFSET,
+ buf, STARFIVE_EEPROM_HATS_SIZE_MAX);
+ }
+
+ if (ret) {
+ printf("fail to read EEPROM.\n");
+ return ret;
+ }
+
+ return parse_eeprom_info((struct eeprom_hats_header *)buf);
+}
+
+/**
+ * prog_eeprom() - write the EEPROM from memory
+ */
+static int prog_eeprom(uint8_t *buf, unsigned int size)
+{
+ unsigned int i;
+ void *p;
+ uchar tmp_buff[STARFIVE_EEPROM_HATS_SIZE_MAX];
+ struct udevice *dev;
+ int ret = i2c_get_chip_for_busnum(CONFIG_SYS_EEPROM_BUS_NUM,
+ CONFIG_SYS_I2C_EEPROM_ADDR,
+ CONFIG_SYS_I2C_EEPROM_ADDR_LEN,
+ &dev);
+
+ if (is_match_magic(buf)) {
+ printf("MAGIC ERROR, Please check the data@%p.\n", buf);
+ return -1;
+ }
+
+ for (i = 0, p = buf; i < size;
+ i += BYTES_PER_EEPROM_PAGE, p += BYTES_PER_EEPROM_PAGE) {
+ if (!ret)
+ ret = dm_i2c_write(dev,
+ i + STARFIVE_EEPROM_WP_OFFSET,
+ p, min((int)(size - i),
+ BYTES_PER_EEPROM_PAGE));
+ if (ret)
+ break;
+ udelay(EEPROM_WRITE_DELAY_MS);
+ }
+
+ 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 *)buf, (void *)tmp_buff,
+ STARFIVE_EEPROM_HATS_SIZE_MAX))
+ ret = -1;
+ }
+
+ if (ret) {
+ has_been_read = -1;
+ printf("Programming failed.Temp buff:\n");
+ dump_raw_eeprom(tmp_buff,
+ STARFIVE_EEPROM_HATS_SIZE_MAX);
+ return -1;
+ }
+
+ printf("Programming passed.\n");
+ return 0;
+}
+
+/**
+ * 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)
+{
+ unsigned int i;
+ struct eeprom_hats_atom_header *atom4;
+ atom4 = (struct eeprom_hats_atom_header *)
+ hats_get_atom((struct eeprom_hats_header *)eeprom_wp_buff,
+ HATS_ATOM_CUSTOM);
+
+ 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;
+ }
+
+ for (i = 0; *string && (i < MAC_ADDR_BYTES); i++) {
+ if (index == 0) {
+ einfo.mac0_addr[i] = hextoul(string, &string);
+ } else {
+ einfo.mac1_addr[i] = hextoul(string, &string);
+ }
+ if (*string == ':')
+ string++;
+ }
+
+ update_crc(atom4);
+}
+
+/**
+ * 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)
+{
+ u8 p;
+ uint base = 16;
+ struct eeprom_hats_atom_header *atom4;
+ atom4 = (struct eeprom_hats_atom_header *)
+ hats_get_atom((struct eeprom_hats_header *)eeprom_wp_buff,
+ HATS_ATOM_CUSTOM);
+
+ p = (u8)simple_strtoul(string, NULL, base);
+ if (p > U8_MAX) {
+ printf("%s must not be greater than %d\n", "PCB revision",
+ U8_MAX);
+ return;
+ }
+
+ *einfo.pcb_revision = p;
+
+ update_crc(atom4);
+}
+
+/**
+ * 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)
+{
+ struct eeprom_hats_atom_header *atom4;
+ atom4 = (struct eeprom_hats_atom_header *)
+ hats_get_atom((struct eeprom_hats_header *)eeprom_wp_buff,
+ HATS_ATOM_CUSTOM);
+
+ if (string[0] < 'A' || string[0] > 'Z') {
+ printf("BOM revision must be an uppercase letter between A and Z\n");
+ return;
+ }
+
+ *einfo.bom_revision = string[0];
+
+ update_crc(atom4);
+}
+
+/**
+ * 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 ("DK7110B1-2150-D104EC32-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)
+{
+ struct eeprom_hats_atom_header *atom1;
+ atom1 = (struct eeprom_hats_atom_header *)
+ hats_get_atom((struct eeprom_hats_header *)eeprom_wp_buff,
+ HATS_ATOM_VENDOR);
+
+ memcpy((void *)einfo.pstr, (void *)string,
+ STARFIVE_EEPROM_ATOM1_PSTR_SIZE);
+
+ update_crc(atom1);
+}
+
+/**
+ * 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(uchar *buff)
+{
+ struct eeprom_hats_header *hats = (struct eeprom_hats_header *)buff;
+ struct eeprom_hats_atom_header *atom1 = (void *)hats +
+ sizeof(struct eeprom_hats_header);
+ struct eeprom_hats_atom_header *atom4_v1 = (void *)atom1 +
+ sizeof(struct starfive_eeprom_atom1);
+
+ memcpy((void *)hats, (void *)&starfive_eeprom_hats_header_default,
+ sizeof(struct eeprom_hats_header));
+ memcpy((void *)atom1, (void *)&starfive_eeprom_atom1_default,
+ sizeof(struct starfive_eeprom_atom1));
+ memcpy((void *)atom4_v1, (void *)&starfive_eeprom_atom4_v1_default,
+ sizeof(struct starfive_eeprom_atom4_v1));
+
+ update_crc(atom1);
+ update_crc(atom4_v1);
+}
+
+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 <DK7110B1-2150-D104EC32-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(&einfo);
+ 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(eeprom_wp_buff);
+ } else if (!strcmp(cmd, "initialize")) {
+ init_local_copy(eeprom_wp_buff);
+ return 0;
+ } else if (!strcmp(cmd, "write_eeprom")) {
+ return prog_eeprom(eeprom_wp_buff,
+ STARFIVE_EEPROM_HATS_SIZE_MAX);
+ }
+
+ if (argc != 3)
+ return print_usage();
+
+ if (is_match_magic(eeprom_wp_buff)) {
+ 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(eeprom_wp_buff))
+ return 0;
+
+ // 1, setup ethaddr env
+ eth_env_set_enetaddr("eth0addr", einfo.mac0_addr);
+ eth_env_set_enetaddr("eth1addr", einfo.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:
+ * "DK7110B1-2150-D104EC32-00000001\0;"
+ * "<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#", einfo.pstr);
+
+ return 0;
+}
+
diff --git a/board/starfive/devkits/spl.c b/board/starfive/devkits/spl.c
new file mode 100644
index 0000000000..d5f43b4747
--- /dev/null
+++ b/board/starfive/devkits/spl.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022-2023 StarFive Technology Co., Ltd.
+ * Author: yanhong <yanhong.wang@starfivetech.com>
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <asm/arch/spl.h>
+#include <asm/io.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/jh7110-regs.h>
+#include <asm/arch/clk.h>
+#include <image.h>
+#include <log.h>
+#include <spl.h>
+
+#define MODE_SELECT_REG 0x1702002c
+
+int spl_board_init_f(void)
+{
+ int ret;
+
+ ret = spl_soc_init();
+ if (ret) {
+ debug("JH7110 SPL init failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+u32 spl_boot_device(void)
+{
+ int boot_mode = 0;
+
+ boot_mode = readl((const volatile void *)MODE_SELECT_REG) & 0x3;
+ switch (boot_mode) {
+ case 0:
+ return BOOT_DEVICE_SPI;
+ case 1:
+ return BOOT_DEVICE_MMC2;
+ case 2:
+ return BOOT_DEVICE_MMC1;
+ case 3:
+ return BOOT_DEVICE_UART;
+ default:
+ debug("Unsupported boot device 0x%x.\n",
+ boot_mode);
+ return BOOT_DEVICE_NONE;
+ }
+}
+
+struct image_header *spl_get_load_buffer(ssize_t offset, size_t size)
+{
+ return (struct image_header *)(STARFIVE_SPL_BOOT_LOAD_ADDR);
+}
+
+void board_init_f(ulong dummy)
+{
+ int ret;
+
+ /* Adjust cpu frequency, the default is 1.0GHz */
+ starfive_jh7110_pll_set_rate(PLL0, 1000000000);
+
+ /*change pll2 to 1188MHz*/
+ starfive_jh7110_pll_set_rate(PLL2, 1188000000);
+
+ /*DDR control depend clk init*/
+ clrsetbits_le32(SYS_CRG_BASE, CLK_CPU_ROOT_SW_MASK,
+ BIT(CLK_CPU_ROOT_SW_SHIFT) & CLK_CPU_ROOT_SW_MASK);
+
+ clrsetbits_le32(SYS_CRG_BASE + CLK_BUS_ROOT_OFFSET,
+ CLK_BUS_ROOT_SW_MASK,
+ BIT(CLK_BUS_ROOT_SW_SHIFT) & CLK_BUS_ROOT_SW_MASK);
+
+ /*Set clk_perh_root clk default mux sel to pll2*/
+ clrsetbits_le32(SYS_CRG_BASE + CLK_PERH_ROOT_OFFSET,
+ CLK_PERH_ROOT_MASK,
+ BIT(CLK_PERH_ROOT_SHIFT) & CLK_PERH_ROOT_MASK);
+
+ clrsetbits_le32(SYS_CRG_BASE + CLK_NOC_BUS_STG_AXI_OFFSET,
+ CLK_NOC_BUS_STG_AXI_EN_MASK,
+ BIT(CLK_NOC_BUS_STG_AXI_EN_SHIFT)
+ & CLK_NOC_BUS_STG_AXI_EN_MASK);
+
+ clrsetbits_le32(AON_CRG_BASE + CLK_AON_APB_FUNC_OFFSET,
+ CLK_AON_APB_FUNC_SW_MASK,
+ BIT(CLK_AON_APB_FUNC_SW_SHIFT) & CLK_AON_APB_FUNC_SW_MASK);
+
+ /* switch qspi clk to pll0 */
+ clrsetbits_le32(SYS_CRG_BASE + CLK_QSPI_REF_OFFSET,
+ CLK_QSPI_REF_SW_MASK,
+ BIT(CLK_QSPI_REF_SW_SHIFT) & CLK_QSPI_REF_SW_MASK);
+
+ /*set GPIO to 3.3v*/
+ setbits_le32(SYS_SYSCON_BASE + 0xC, 0x0);
+
+ /* Improved GMAC0 TX I/O PAD capability */
+ clrsetbits_le32(AON_IOMUX_BASE + 0x78, 0x3, BIT(0) & 0x3);
+ clrsetbits_le32(AON_IOMUX_BASE + 0x7c, 0x3, BIT(0) & 0x3);
+ clrsetbits_le32(AON_IOMUX_BASE + 0x80, 0x3, BIT(0) & 0x3);
+ clrsetbits_le32(AON_IOMUX_BASE + 0x84, 0x3, BIT(0) & 0x3);
+ clrsetbits_le32(AON_IOMUX_BASE + 0x88, 0x3, BIT(0) & 0x3);
+
+ /* Improved GMAC1 TX I/O PAD capability */
+ clrsetbits_le32(SYS_IOMUX_BASE + 0x26c, 0x3, BIT(0) & 0x3);
+ clrsetbits_le32(SYS_IOMUX_BASE + 0x270, 0x3, BIT(0) & 0x3);
+ clrsetbits_le32(SYS_IOMUX_BASE + 0x274, 0x3, BIT(0) & 0x3);
+ clrsetbits_le32(SYS_IOMUX_BASE + 0x278, 0x3, BIT(0) & 0x3);
+ clrsetbits_le32(SYS_IOMUX_BASE + 0x27c, 0x3, BIT(0) & 0x3);
+
+ SYS_IOMUX_DOEN(62, LOW);
+ SYS_IOMUX_DOUT(62, 19);
+ SYS_IOMUX_SET_DS(64, 2);
+ SYS_IOMUX_SET_SLEW(64, 1);
+ SYS_IOMUX_SET_DS(65, 1);
+ SYS_IOMUX_SET_DS(66, 1);
+ SYS_IOMUX_SET_DS(67, 1);
+ SYS_IOMUX_SET_DS(68, 1);
+ SYS_IOMUX_SET_DS(69, 1);
+ SYS_IOMUX_SET_DS(70, 1);
+ SYS_IOMUX_SET_DS(71, 1);
+ SYS_IOMUX_SET_DS(72, 1);
+ SYS_IOMUX_SET_DS(73, 1);
+
+ SYS_IOMUX_DOEN(10, LOW);
+ SYS_IOMUX_DOUT(10, 55);
+ SYS_IOMUX_SET_SLEW(10, 1);
+ SYS_IOMUX_SET_DS(10, 2);
+ SYS_IOMUX_COMPLEX(9, 44, 57, 19);
+ SYS_IOMUX_SET_DS(9, 1);
+ SYS_IOMUX_COMPLEX(11, 45, 58, 20);
+ SYS_IOMUX_SET_DS(11, 1);
+ SYS_IOMUX_COMPLEX(12, 46, 59, 21);
+ SYS_IOMUX_SET_DS(12, 1);
+ SYS_IOMUX_COMPLEX(7, 47, 60, 22);
+ SYS_IOMUX_SET_DS(7, 1);
+ SYS_IOMUX_COMPLEX(8, 48, 61, 23);
+ SYS_IOMUX_SET_DS(8, 1);
+
+ ret = spl_early_init();
+ if (ret)
+ panic("spl_early_init() failed: %d\n", ret);
+
+ arch_cpu_init_dm();
+
+ preloader_console_init();
+
+ ret = spl_board_init_f();
+ if (ret) {
+ debug("spl_board_init_f init failed: %d\n", ret);
+ return;
+ }
+}
+
+#ifdef CONFIG_SPL_LOAD_FIT
+int board_fit_config_name_match(const char *name)
+{
+ /* boot using first FIT config */
+ return 0;
+}
+#endif
+
+
diff --git a/board/starfive/devkits/starfive_devkits.c b/board/starfive/devkits/starfive_devkits.c
new file mode 100644
index 0000000000..741c190d2e
--- /dev/null
+++ b/board/starfive/devkits/starfive_devkits.c
@@ -0,0 +1,482 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022-2023 StarFive Technology Co., Ltd.
+ * Author: yanhong <yanhong.wang@starfivetech.com>
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/jh7110-regs.h>
+#include <asm/gpio.h>
+#include <cpu_func.h>
+#include <dm/uclass.h>
+#include <dm/device.h>
+#include <env.h>
+#include <i2c.h>
+#include <inttypes.h>
+#include <misc.h>
+#include <linux/bitops.h>
+#include <asm/arch/gpio.h>
+#include <bmp_logo.h>
+#include <video.h>
+#include <splash.h>
+#include <asm/gpio.h>
+#include <linux/err.h>
+
+
+#define SYS_CLOCK_ENABLE(clk) \
+ setbits_le32(SYS_CRG_BASE + clk, CLK_ENABLE_MASK)
+
+#define CPU_VOL_BINNING_OFFSET 0x7fc
+enum {
+ BOOT_FLASH = 0,
+ BOOT_SD,
+ BOOT_EMMC,
+ BOOT_UART,
+};
+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_i2c_init (int id)
+{
+ switch (id) {
+ case 5:
+ //scl
+ SYS_IOMUX_COMPLEX(19, 79, 0, 42);
+ //sda
+ SYS_IOMUX_COMPLEX(20, 80, 0, 43);
+
+ 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 jh7110_gmac_io_pad(int id)
+{
+ u32 cap = BIT(0); /* 2.5V */
+
+ switch (id) {
+ case 0:
+ /* Improved GMAC0 TX I/O PAD capability */
+ clrsetbits_le32(AON_IOMUX_BASE + 0x78, 0x3, cap & 0x3);
+ clrsetbits_le32(AON_IOMUX_BASE + 0x7c, 0x3, cap & 0x3);
+ clrsetbits_le32(AON_IOMUX_BASE + 0x80, 0x3, cap & 0x3);
+ clrsetbits_le32(AON_IOMUX_BASE + 0x84, 0x3, cap & 0x3);
+ clrsetbits_le32(AON_IOMUX_BASE + 0x88, 0x3, cap & 0x3);
+ break;
+ case 1:
+ /* Improved GMAC1 TX I/O PAD capability */
+ clrsetbits_le32(SYS_IOMUX_BASE + 0x26c, 0x3, cap & 0x3);
+ clrsetbits_le32(SYS_IOMUX_BASE + 0x270, 0x3, cap & 0x3);
+ clrsetbits_le32(SYS_IOMUX_BASE + 0x274, 0x3, cap & 0x3);
+ clrsetbits_le32(SYS_IOMUX_BASE + 0x278, 0x3, cap & 0x3);
+ clrsetbits_le32(SYS_IOMUX_BASE + 0x27c, 0x3, cap & 0x3);
+ break;
+ }
+}
+
+static void jh7110_gmac_init(int id)
+{
+ jh7110_gmac_sel_tx_to_rgmii(id);
+ jh7110_gmac_io_pad(id);
+}
+
+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<<USB_MODE_STRAP_SHIFT) &
+ USB_MODE_STRAP_MASK);/*2:host mode, 4:device mode*/
+ clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_4,
+ USB_OTG_SUSPENDM_BYPS_MASK,
+ BIT(USB_OTG_SUSPENDM_BYPS_SHIFT)
+ & USB_OTG_SUSPENDM_BYPS_MASK);
+ clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_4,
+ USB_OTG_SUSPENDM_MASK,
+ BIT(USB_OTG_SUSPENDM_SHIFT) &
+ USB_OTG_SUSPENDM_MASK);/*HOST = 1. DEVICE = 0;*/
+ clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_4,
+ USB_PLL_EN_MASK,
+ BIT(USB_PLL_EN_SHIFT) & USB_PLL_EN_MASK);
+ clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_4,
+ USB_REFCLK_MODE_MASK,
+ BIT(USB_REFCLK_MODE_SHIFT) & USB_REFCLK_MODE_MASK);
+ /* usb 2.0 phy mode,REPLACE USB3.0 PHY module = 1;else = 0*/
+ clrsetbits_le32(SYS_SYSCON_BASE + SYS_SYSCON_24,
+ PDRSTN_SPLIT_MASK,
+ BIT(PDRSTN_SPLIT_SHIFT) &
+ PDRSTN_SPLIT_MASK);
+ } else {
+ /*usb 3.0 pipe phy config*/
+ clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_196,
+ PCIE_CKREF_SRC_MASK,
+ (0<<PCIE_CKREF_SRC_SHIFT) & PCIE_CKREF_SRC_MASK);
+ clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_196,
+ PCIE_CLK_SEL_MASK,
+ (0<<PCIE_CLK_SEL_SHIFT) & PCIE_CLK_SEL_MASK);
+ clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_328,
+ PCIE_PHY_MODE_MASK,
+ BIT(PCIE_PHY_MODE_SHIFT) & PCIE_PHY_MODE_MASK);
+ clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_500,
+ PCIE_USB3_BUS_WIDTH_MASK,
+ (0 << PCIE_USB3_BUS_WIDTH_SHIFT) &
+ PCIE_USB3_BUS_WIDTH_MASK);
+ clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_500,
+ PCIE_USB3_RATE_MASK,
+ (0 << PCIE_USB3_RATE_SHIFT) & PCIE_USB3_RATE_MASK);
+ clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_500,
+ PCIE_USB3_RX_STANDBY_MASK,
+ (0 << PCIE_USB3_RX_STANDBY_SHIFT)
+ & PCIE_USB3_RX_STANDBY_MASK);
+ clrsetbits_le32(STG_SYSCON_BASE + STG_SYSCON_500,
+ PCIE_USB3_PHY_ENABLE_MASK,
+ BIT(PCIE_USB3_PHY_ENABLE_SHIFT)
+ & PCIE_USB3_PHY_ENABLE_MASK);
+
+ /* usb 3.0 phy mode,REPLACE USB3.0 PHY module = 1;else = 0*/
+ clrsetbits_le32(SYS_SYSCON_BASE + SYS_SYSCON_24,
+ PDRSTN_SPLIT_MASK,
+ (0 << PDRSTN_SPLIT_SHIFT) & PDRSTN_SPLIT_MASK);
+ }
+}
+
+#if CONFIG_IS_ENABLED(STARFIVE_OTP)
+static void get_cpu_voltage_type(struct udevice *dev)
+{
+ int ret;
+ u32 buf = CPU_VOL_1040;
+
+ ret = misc_read(dev, CPU_VOL_BINNING_OFFSET, &buf, sizeof(buf));
+ if (ret != sizeof(buf))
+ printf("%s: error reading CPU vol from OTP\n", __func__);
+ else {
+ switch ((buf & CPU_VOL_MASK)) {
+ case CPU_VOL_1000:
+ env_set("cpu_max_vol", "1000000");
+ break;
+ case CPU_VOL_1060:
+ env_set("cpu_max_vol", "1060000");
+ break;
+ case CPU_VOL_1020:
+ env_set("cpu_max_vol", "1020000");
+ break;
+ default:
+ env_set("cpu_max_vol", "1040000");
+ break;
+ }
+ }
+}
+#endif
+
+static void get_boot_mode(void)
+{
+ u32 value;
+
+ value = in_le32(AON_IOMUX_BASE + AON_GPIO_DIN_REG);
+ switch (value & 0x03) {
+ case BOOT_FLASH:
+ env_set("bootmode", "flash");
+ env_set("devnum", "1");
+ break;
+
+ case BOOT_SD:
+ env_set("bootmode", "sd");
+ env_set("devnum", "1");
+ break;
+
+ case BOOT_EMMC:
+ env_set("bootmode", "emmc");
+ env_set("devnum", "0");
+ break;
+
+ default:
+ env_set("bootmode", "uart");
+ env_set("devnum", "1");
+ break;
+ }
+}
+
+#define CONFIG_SYS_PMIC_BUS_NUM 5
+#define CONFIG_SYS_I2C_PMIC_ADDR 0x36
+#define CONFIG_SYS_I2C_PMIC_ADDR_LEN 1
+#define AXP15060_DCDC_MODE_CTRL_2 0x1b
+#define AXP15060_DCDC5_MODE_BIT BIT(4)
+#define AXP15060_PWR_SEQUENCE_CTRL 0X32
+#define AXP15060_RST_PMIC_BY_PWROK_BIT BIT(4)
+
+int set_pmic(void)
+{
+ int ret;
+ struct udevice *dev;
+ u8 temp_buf;
+
+ ret = i2c_get_chip_for_busnum(CONFIG_SYS_PMIC_BUS_NUM,
+ CONFIG_SYS_I2C_PMIC_ADDR,
+ CONFIG_SYS_I2C_PMIC_ADDR_LEN,
+ &dev);
+
+ if (!ret) {
+ /* Set Pmic DCDC5 Mode as PWM */
+ ret = dm_i2c_read(dev,
+ AXP15060_DCDC_MODE_CTRL_2,
+ &temp_buf,
+ sizeof(temp_buf));
+ if (ret)
+ printf("%s: can't read pmic dcdc5 mode register\n",
+ __func__);
+
+ temp_buf = temp_buf | AXP15060_DCDC5_MODE_BIT;
+ ret = dm_i2c_write(dev,
+ AXP15060_DCDC_MODE_CTRL_2,
+ &temp_buf,
+ sizeof(temp_buf));
+ if (ret)
+ printf("%s: can't write pmic dcdc5 mode register\n",
+ __func__);
+
+ /* Enable PWROK in PMIC */
+ ret = dm_i2c_read(dev,
+ AXP15060_PWR_SEQUENCE_CTRL,
+ &temp_buf,
+ sizeof(temp_buf));
+ if (ret)
+ printf("%s: can't read pmic power disbale & down sequence register\n",
+ __func__);
+
+ temp_buf = temp_buf | AXP15060_RST_PMIC_BY_PWROK_BIT;
+ ret = dm_i2c_write(dev,
+ AXP15060_PWR_SEQUENCE_CTRL,
+ &temp_buf,
+ sizeof(temp_buf));
+ if (ret)
+ printf("%s: can't write pmic power disbale & down sequence register\n",
+ __func__);
+
+ }
+
+ return 0;
+}
+
+int board_init(void)
+{
+ enable_caches();
+
+ jh7110_timer_init();
+ jh7110_usb_init(true);
+ jh7110_gmac_init(0);
+ jh7110_gmac_init(1);
+ jh7110_i2c_init(5);
+
+ return 0;
+}
+
+#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);
+
+#if CONFIG_IS_ENABLED(STARFIVE_OTP)
+ get_cpu_voltage_type(dev);
+#endif
+ return 0;
+}
+#endif
+
+int board_late_init(void)
+{
+ struct udevice *dev;
+ int ret;
+
+ get_boot_mode();
+
+ env_set("chip_vision", "B");
+
+ /*
+ * save the memory info by environment variable in u-boot,
+ * It will used to update the memory configuration in dts,
+ * which passed to kernel lately.
+ */
+ env_set_hex("memory_addr", gd->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;
+
+}
+
+static int jh7110_get_gpio_val(u32 gpio)
+{
+ int ret;
+
+ ret = gpio_request(gpio, "ddr_gpio");
+ if (!ret) {
+ ret = gpio_direction_input(gpio);
+ if (!ret)
+ ret = gpio_get_value(gpio);
+
+ gpio_free(gpio);
+ }
+
+ return ret;
+}
+
+int board_ddr_size(void)
+{
+ int val, ret;
+
+ val = jh7110_get_gpio_val(21);
+ if (IS_ERR_VALUE(val))
+ return val;
+
+ ret = jh7110_get_gpio_val(22);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+
+ val |= (ret << 1);
+
+ switch (val) {
+ case 0x0:
+ ret = 8; //8GB
+ break;
+ case 0x1:
+ ret = 4; //4GB
+ break;
+ case 0x2:
+ ret = 2; //2GB
+ break;
+ case 0x3:
+ ret = 1; //1GB
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ };
+
+ return ret;
+}
+
+static int starfive_get_gpio_val(u32 gpio)
+{
+ int ret;
+
+ ret = gpio_request(gpio, "ddr_gpio");
+ if (!ret) {
+ ret = gpio_direction_input(gpio);
+ if (!ret)
+ ret = gpio_get_value(gpio);
+
+ gpio_free(gpio);
+ }
+
+ return ret;
+}
+
+/* get ddr type from GPIO23,GPIO24 DDR4 or LPDDR4 */
+int starfive_get_ddr_type(void)
+{
+ int val, ret;
+
+ val = starfive_get_gpio_val(23);
+ if (IS_ERR_VALUE(val))
+ return val;
+
+ ret = starfive_get_gpio_val(24);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+
+ return val | (ret << 1);
+}
diff --git a/include/configs/starfive-devkits.h b/include/configs/starfive-devkits.h
new file mode 100644
index 0000000000..b7547d8064
--- /dev/null
+++ b/include/configs/starfive-devkits.h
@@ -0,0 +1,405 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021 Shanghai StarFive Technology Co., Ltd.
+ * YanHong Wang <yanhong.wang@starfivetech.com>
+ */
+
+#ifndef _STARFIVE_DEVKITS_H
+#define _STARFIVE_DEVKITS_H
+
+#include <version.h>
+#include <linux/sizes.h>
+
+#ifdef CONFIG_SPL
+
+#define CONFIG_SPL_MAX_SIZE 0x00040000
+#define CONFIG_SPL_BSS_START_ADDR 0x08040000
+#define CONFIG_SPL_BSS_MAX_SIZE 0x00010000
+#define CONFIG_SYS_SPL_MALLOC_START 0x42000000
+#define CONFIG_SYS_SPL_MALLOC_SIZE 0x00800000
+
+#define CONFIG_SPL_STACK (0x08000000 + 0x00180000 - \
+ GENERATED_GBL_DATA_SIZE)
+
+#define STARFIVE_SPL_BOOT_LOAD_ADDR 0x60000000
+#endif
+
+#define CONFIG_SYS_BOOTM_LEN SZ_64M
+
+#define CONFIG_SYS_CACHELINE_SIZE 64
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buffer Size */
+
+/*
+ * Print Buffer Size
+ */
+#define CONFIG_SYS_PBSIZE \
+ (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+
+/*
+ * max number of command args
+ */
+#define CONFIG_SYS_MAXARGS 16
+
+/*
+ * Boot Argument Buffer Size
+ */
+#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
+
+/*
+ * Size of malloc() pool
+ * 512kB is suggested, (CONFIG_ENV_SIZE + 128 * 1024) was not enough
+ */
+#define CONFIG_SYS_MALLOC_LEN SZ_8M
+
+#define CONFIG_SYS_SDRAM_BASE 0x40000000
+
+/* Init Stack Pointer */
+#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + SZ_8M)
+
+#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE + SZ_16M)
+#define CONFIG_STANDALONE_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE + SZ_16M)
+
+/*
+ * Ethernet
+ */
+#ifdef CONFIG_CMD_NET
+#define CONFIG_DW_ALTDESCRIPTOR
+#define DWC_NET_PHYADDR 0
+#define CONFIG_ARP_TIMEOUT 500
+#define PHY_ANEG_TIMEOUT 8000 /* PHY needs longer aneg time */
+#define CONFIG_NETMASK 255.255.255.0
+#define CONFIG_IPADDR 192.168.120.230
+#define CONFIG_IP_DEFRAG
+#ifndef CONFIG_NET_MAXDEFRAG
+#define CONFIG_NET_MAXDEFRAG 16384
+#endif
+#endif
+
+/* HACK these should have '#if defined (stuff) around them like zynqp*/
+#define BOOT_TARGET_DEVICES(func) func(DHCP, dhcp, na) func(MMC, mmc, 0)
+
+#include <config_distro_bootcmd.h>
+
+
+#include <environment/distro/sf.h>
+
+#define TYPE_GUID_LOADER1 "5B193300-FC78-40CD-8002-E86C45580B47"
+#define TYPE_GUID_LOADER2 "2E54B353-1271-4842-806F-E436D6AF6985"
+#define TYPE_GUID_SYSTEM "0FC63DAF-8483-4772-8E79-3D69D8477DE4"
+
+#define CPU_VOL_1020_SET \
+ "cpu_vol_1020_set=" \
+ "fdt set /opp-table-0/opp-1500000000 opp-microvolt <1020000>;\0"
+
+#define CPU_VOL_1040_SET \
+ "cpu_vol_1040_set=" \
+ "fdt set /opp-table-0/opp-1500000000 opp-microvolt <1040000>;\0"
+
+#define CPU_VOL_1060_SET \
+ "cpu_vol_1060_set=" \
+ "fdt set /opp-table-0/opp-1500000000 opp-microvolt <1060000>;\0"
+
+#define CPU_SPEED_1250_SET \
+ "cpu_speed_1250_set=" \
+ "fdt rm /opp-table-0/opp-375000000;" \
+ "fdt rm /opp-table-0/opp-500000000;" \
+ "fdt rm /opp-table-0/opp-750000000;" \
+ "fdt rm /opp-table-0/opp-1500000000;\0"
+
+#define CPU_SPEED_1500_SET \
+ "cpu_speed_1500_set=" \
+ "fdt rm /opp-table-0/opp-312500000;" \
+ "fdt rm /opp-table-0/opp-417000000;" \
+ "fdt rm /opp-table-0/opp-625000000;" \
+ "fdt rm /opp-table-0/opp-1250000000;\0"
+
+#define CMA_SIZE_SET \
+ "cma_start=70000000\0" \
+ "cma_1g=b000000\0" \
+ "cma_2g=20000000\0" \
+ "cma_4g=40000000\0" \
+ "cma_8g=60000000\0" \
+ "cma_node=/reserved-memory/linux,cma\0" \
+ "cma_ddr1g_set=" \
+ "fdt set ${cma_node} size <0x0 0x${cma_1g}>;" \
+ "fdt set ${cma_node} alloc-ranges <0x0 0x${cma_start} 0x0 0x${cma_1g}>;\0" \
+ "cma_ddr2g_set=" \
+ "fdt set ${cma_node} size <0x0 0x${cma_2g}>;" \
+ "fdt set ${cma_node} alloc-ranges <0x0 0x${cma_start} 0x0 0x${cma_2g}>;\0" \
+ "cma_ddr4g_set=" \
+ "fdt set ${cma_node} size <0x0 0x${cma_4g}>;" \
+ "fdt set ${cma_node} alloc-ranges <0x0 0x${cma_start} 0x0 0x${cma_4g}>;\0" \
+ "cma_ddr8g_set=" \
+ "fdt set ${cma_node} size <0x0 0x${cma_8g}>;" \
+ "fdt set ${cma_node} alloc-ranges <0x0 0x${cma_start} 0x0 0x${cma_8g}>;\0" \
+ "cma_resize=" \
+ "if test ${memory_size} -eq 40000000; then " \
+ "run cma_ddr1g_set;" \
+ "elif test ${memory_size} -eq 80000000; then " \
+ "run cma_ddr2g_set;" \
+ "elif test ${memory_size} -eq 100000000; then " \
+ "run cma_ddr4g_set;" \
+ "elif test ${memory_size} -ge 200000000; then " \
+ "run cma_ddr8g_set;" \
+ "fi; \0 "
+
+#define CPU_FREQ_VOL_SET \
+ "cpu_vol_set=" \
+ "if test ${cpu_max_vol} = 1000000; then " \
+ "run cpu_speed_1250_set; " \
+ "else " \
+ "run cpu_speed_1500_set; " \
+ "if test ${cpu_max_vol} = 1060000; then " \
+ "run cpu_vol_1060_set; " \
+ "elif test ${cpu_max_vol} = 1020000; then " \
+ "run cpu_vol_1020_set; " \
+ "else " \
+ "run cpu_vol_1040_set; " \
+ "fi; " \
+ "fi; \0"
+
+#define DEVKITS_MEM_SET \
+ "devkits_mem_set=" \
+ "fdt memory ${memory_addr} ${memory_size};" \
+ "run cma_resize; \0"
+
+#define CHIPA_GMAC_SET \
+ "chipa_gmac_set=" \
+ "fdt set /soc/ethernet@16030000/ethernet-phy@0 tx_inverted_10 <0x1>;" \
+ "fdt set /soc/ethernet@16030000/ethernet-phy@0 tx_inverted_100 <0x1>;" \
+ "fdt set /soc/ethernet@16030000/ethernet-phy@0 tx_inverted_1000 <0x1>;\0"
+
+#define CHIPA_SET \
+ "chipa_set=" \
+ "if test ${chip_vision} = B; then " \
+ "run chipa_gmac_set;" \
+ "fi; \0" \
+ "chipa_set_uboot=" \
+ "fdt addr ${fdtcontroladdr};" \
+ "run chipa_set;\0" \
+ "chipa_set_linux=" \
+ "fdt addr ${fdt_addr_r};" \
+ "run devkits_mem_set;" \
+ "run chipa_set;\0"
+
+#define PARTS_DEFAULT \
+ "name=loader1,start=17K,size=1M,type=${type_guid_gpt_loader1};" \
+ "name=loader2,size=4MB,type=${type_guid_gpt_loader2};" \
+ "name=system,size=-,bootable,type=${type_guid_gpt_system};"
+
+#define JH7110_SDK_BOOTENV \
+ "bootdir=/boot\0" \
+ "bootpart=3\0" \
+ "rootpart=4\0" \
+ "load_sdk_uenv=" \
+ "fatload ${bootdev} ${devnum}:${bootpart} ${loadaddr} ${bootenv_sdk};" \
+ "env import -t ${loadaddr} ${filesize}; \0" \
+ "mmc_test_and_boot=" \
+ "if mmc dev ${devnum}; then " \
+ "echo Try booting from MMC${devnum} ...; " \
+ "setenv sdev_blk mmcblk${devnum}p${rootpart};" \
+ "run load_sdk_uenv; run boot2;" \
+ "fi;\0" \
+ "bootenv_mmc=" \
+ "setenv bootdev mmc;" \
+ "if test ${bootmode} = flash; then " \
+ "for mmc_devnum in ${mmc_devnum_l}; do " \
+ "setenv devnum ${mmc_devnum}; " \
+ "run mmc_test_and_boot;" \
+ "done;" \
+ "fi; " \
+ "if test ${bootmode} = sd; then " \
+ "setenv devnum ${sd_devnum};" \
+ "run mmc_test_and_boot;" \
+ "fi; " \
+ "if test ${bootmode} = emmc; then " \
+ "setenv devnum ${emmc_devnum};"\
+ "run mmc_test_and_boot;" \
+ "fi; \0" \
+ "bootenv_nvme=" \
+ "if test ${bootmode} = flash; then " \
+ "for nvme_devnum in ${nvme_devnum_l}; do " \
+ "setenv devnum ${nvme_devnum};" \
+ "if pci enum; then " \
+ "nvme scan; " \
+ "fi; " \
+ "if nvme dev ${devnum}; then " \
+ "echo Try booting from NVME${devnum} ...; " \
+ "setenv bootdev nvme;" \
+ "setenv sdev_blk nvme${devnum}n1p${rootpart};" \
+ "run load_sdk_uenv; run boot2;" \
+ "fi; " \
+ "done; " \
+ "fi; \0" \
+ "sdk_boot_env=" \
+ "for bootdev_s in ${boot_devs}; do " \
+ "run bootenv_${bootdev_s}; " \
+ "done;\0" \
+ "fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0"
+
+#define DEVKITS_SDK_BOOTENV \
+ "bootenv=uEnv.txt\0" \
+ "bootenv_sdk=devkits_uEnv.txt\0"\
+ "boot_devs=mmc nvme\0" \
+ "emmc_devnum=0\0" \
+ "sd_devnum=1\0" \
+ "mmc_devnum_l=1 0\0" \
+ "nvme_devnum_l=0 0\0"
+
+#define JH7110_DISTRO_BOOTENV \
+ "bootdir=/boot\0" \
+ "bootpart=3\0" \
+ "rootpart=4\0" \
+ "load_distro_uenv=" \
+ "fatload ${bootdev} ${devnum}:${bootpart} ${loadaddr} /${bootenv}; " \
+ "env import ${loadaddr} ${filesize}; \0" \
+ "fdt_loaddtb=" \
+ "fatload ${bootdev} ${devnum}:${bootpart} ${fdt_addr_r} /dtbs/${fdtfile}; fdt addr ${fdt_addr_r}; \0" \
+ "fdt_sizecheck=" \
+ "fatsize ${bootdev} ${devnum}:${bootpart} /dtbs/${fdtfile}; \0" \
+ "set_fdt_distro=" \
+ "run chipa_set_linux; run cpu_vol_set;" \
+ "fatwrite ${bootdev} ${devnum}:${bootpart} ${fdt_addr_r} /dtbs/${fdtfile} ${filesize}; \0" \
+ "bootcmd_distro=" \
+ "run load_distro_uenv; " \
+ "run fdt_loaddtb; run fdt_sizecheck; run set_fdt_distro; " \
+ "sysboot ${bootdev} ${devnum}:${bootpart} fat ${scriptaddr} /${boot_syslinux_conf}; \0" \
+ "distro_mmc_test_and_boot=" \
+ "if mmc dev ${devnum}; then " \
+ "echo Try booting from MMC${devnum} ...; " \
+ "run bootcmd_distro;" \
+ "fi;\0" \
+ "distro_bootenv_mmc=" \
+ "setenv bootdev mmc;" \
+ "if test ${bootmode} = flash; then " \
+ "for mmc_devnum in ${mmc_devnum_l}; do "\
+ "setenv devnum ${mmc_devnum}; " \
+ "run distro_mmc_test_and_boot;" \
+ "done;" \
+ "fi; " \
+ "if test ${bootmode} = sd; then " \
+ "setenv devnum ${sd_devnum};" \
+ "run distro_mmc_test_and_boot;" \
+ "fi; " \
+ "if test ${bootmode} = emmc; then " \
+ "setenv devnum ${emmc_devnum};"\
+ "run distro_mmc_test_and_boot;" \
+ "fi; \0" \
+ "distro_bootenv_nvme=" \
+ "if test ${bootmode} = flash; then " \
+ "for nvme_devnum in ${nvme_devnum_l}; do " \
+ "setenv devnum ${nvme_devnum};" \
+ "if pci enum; then " \
+ "nvme scan; " \
+ "fi; " \
+ "if nvme dev ${devnum}; then " \
+ "echo Try booting from NVME${devnum} ...; " \
+ "setenv bootdev nvme;" \
+ "run bootcmd_distro; " \
+ "fi; " \
+ "done; " \
+ "fi; \0" \
+ "distro_boot_env=" \
+ "echo Tring booting distro ...;" \
+ "for bootdev_s in ${boot_devs}; do " \
+ "run distro_bootenv_${bootdev_s}; " \
+ "done; \0"
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "fdt_high=0xffffffffffffffff\0" \
+ "initrd_high=0xffffffffffffffff\0" \
+ "kernel_addr_r=0x40200000\0" \
+ "kernel_comp_addr_r=0x5a000000\0" \
+ "kernel_comp_size=0x4000000\0" \
+ "fdt_addr_r=0x46000000\0" \
+ "scriptaddr=0x43900000\0" \
+ "script_offset_f=0x1fff000\0" \
+ "script_size_f=0x1000\0" \
+ "pxefile_addr_r=0x45900000\0" \
+ "ramdisk_addr_r=0x46100000\0" \
+ "fdtoverlay_addr_r=0x4f000000\0" \
+ "loadaddr=0x60000000\0" \
+ CHIPA_GMAC_SET \
+ CHIPA_SET \
+ CPU_VOL_1020_SET \
+ CPU_VOL_1040_SET \
+ CPU_VOL_1060_SET \
+ CPU_SPEED_1250_SET \
+ CPU_SPEED_1500_SET \
+ CPU_FREQ_VOL_SET \
+ DEVKITS_MEM_SET \
+ DEVKITS_SDK_BOOTENV \
+ CMA_SIZE_SET \
+ JH7110_SDK_BOOTENV \
+ JH7110_DISTRO_BOOTENV \
+ "type_guid_gpt_loader1=" TYPE_GUID_LOADER1 "\0" \
+ "type_guid_gpt_loader2=" TYPE_GUID_LOADER2 "\0" \
+ "type_guid_gpt_system=" TYPE_GUID_SYSTEM "\0" \
+ "partitions=" PARTS_DEFAULT "\0" \
+ BOOTENV \
+ BOOTENV_SF
+
+#define CONFIG_SYS_BAUDRATE_TABLE {9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600}
+#define CONFIG_SYS_LOADS_BAUD_CHANGE 1 /* allow baudrate change */
+
+/* 6.25MHz RTC clock, StarFive JH7110*/
+#define CONFIG_SYS_HZ_CLOCK 4000000
+
+#define __io
+
+#define memset_io(c, v, l) memset((c), (v), (l))
+#define memcpy_fromio(a, c, l) memcpy((a), (c), (l))
+#define memcpy_toio(c, a, l) memcpy((c), (a), (l))
+
+#define CONFIG_ID_EEPROM
+
+#ifdef CONFIG_ID_EEPROM /* EEPROM for SN and MAC */
+#define CONFIG_SYS_EEPROM_BUS_NUM 5
+
+#define FORMAT_VERSION 0x01
+#define PCB_VERSION 0xB0
+#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 {0x6c, 0xcf, 0x39, 0x6c, 0xde, 0xad}
+#define STARFIVE_DEFAULT_MAC1 {0x6c, 0xcf, 0x39, 0x7c, 0xae, 0x5d}
+
+/* Magic number at the first four bytes of EEPROM HATs */
+#define STARFIVE_EEPROM_HATS_SIG "SFDK" /* 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 "DK7110B1-2150-D104EC32-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
+#endif
+
+#define CONFIG_VIDEO_BMP_LOGO
+#define CONFIG_VIDEO_LOGO
+#define CONFIG_BMP_16BPP
+#define CONFIG_BMP_24BPP
+#define CONFIG_BMP_32BPP
+
+#endif /* _STARFIVE_DEVKITS_H */