[RFC 0/5] riscv: add support for Milk-V Mars board

The Milk-V Mars board is technically very close to the StarFive VisionFive 2 board.
With this patch series the VisionFive 2 U-Boot SPL will detect that it is runing on a Milk-V board and patch the device-tree accordingly. This is the same approach that has been taken to handle the differences between the Visionfive 2 1.2B and 1.3A revisions.
An alternative approach would use a separate defconfig and separate board files. As this would incur a higher effort I chose the SPL approach.
Heinrich Schuchardt (5): eeprom: starfive: function get_product_id_from_eeprom() riscv: set fdtfile on Milk-V Mars board: starfive: support Milk-V Mars board riscv: starfive: avoid including common.h doc: describe Milk-V Mars board
arch/riscv/include/asm/arch-jh7110/eeprom.h | 9 ++ board/starfive/visionfive2/spl.c | 102 +++++++++++++++--- .../visionfive2/starfive_visionfive2.c | 44 +++++--- .../visionfive2/visionfive2-i2c-eeprom.c | 9 +- doc/board/starfive/index.rst | 1 + doc/board/starfive/milk-v_mars.rst | 93 ++++++++++++++++ 6 files changed, 230 insertions(+), 28 deletions(-) create mode 100644 doc/board/starfive/milk-v_mars.rst

Export a function get_product_id_from_eeprom() to read the product ID. This value can be used for fixing up the device-tree on JH7110 based products.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com --- arch/riscv/include/asm/arch-jh7110/eeprom.h | 9 +++++++++ board/starfive/visionfive2/visionfive2-i2c-eeprom.c | 8 ++++++++ 2 files changed, 17 insertions(+)
diff --git a/arch/riscv/include/asm/arch-jh7110/eeprom.h b/arch/riscv/include/asm/arch-jh7110/eeprom.h index d2776d5b6cb..62d184aeb57 100644 --- a/arch/riscv/include/asm/arch-jh7110/eeprom.h +++ b/arch/riscv/include/asm/arch-jh7110/eeprom.h @@ -12,4 +12,13 @@ u8 get_pcb_revision_from_eeprom(void); u32 get_ddr_size_from_eeprom(void);
+/** + * get_product_id_from_eeprom - get product ID string + * + * A string like "VF7110A1-2228-D008E000-00000001" is returned. + * + * Return: product ID string + */ +const char *get_product_id_from_eeprom(void); + #endif /* _ASM_RISCV_EEPROM_H */ diff --git a/board/starfive/visionfive2/visionfive2-i2c-eeprom.c b/board/starfive/visionfive2/visionfive2-i2c-eeprom.c index c36de1a5125..a9f4376c8e1 100644 --- a/board/starfive/visionfive2/visionfive2-i2c-eeprom.c +++ b/board/starfive/visionfive2/visionfive2-i2c-eeprom.c @@ -405,6 +405,14 @@ static void set_product_id(char *string) update_crc(); }
+const char *get_product_id_from_eeprom(void) +{ + if (read_eeprom()) + return NULL; + + return pbuf.eeprom.atom1.data.pstr; +} + int do_mac(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { char *cmd;

Set environment variable fdtfile to the correct value for the Milk-V Mars board.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com --- .../visionfive2/starfive_visionfive2.c | 43 +++++++++++++------ 1 file changed, 30 insertions(+), 13 deletions(-)
diff --git a/board/starfive/visionfive2/starfive_visionfive2.c b/board/starfive/visionfive2/starfive_visionfive2.c index 78e118d5a05..9970e309690 100644 --- a/board/starfive/visionfive2/starfive_visionfive2.c +++ b/board/starfive/visionfive2/starfive_visionfive2.c @@ -9,6 +9,7 @@ #include <dm.h> #include <fdt_support.h> #include <env.h> +#include <log.h> #include <asm/arch/eeprom.h> #include <asm/io.h> #include <asm/sections.h> @@ -17,6 +18,8 @@ DECLARE_GLOBAL_DATA_PTR; #define JH7110_L2_PREFETCHER_BASE_ADDR 0x2030000 #define JH7110_L2_PREFETCHER_HART_OFFSET 0x2000 +#define FDTFILE_MILK_V_MARS \ + "starfive/jh7110-milkv-mars.dtb" #define FDTFILE_VISIONFIVE2_1_2A \ "starfive/jh7110-starfive-visionfive-2-v1.2a.dtb" #define FDTFILE_VISIONFIVE2_1_3B \ @@ -48,20 +51,34 @@ static void set_fdtfile(void) { u8 version; const char *fdtfile; + const char *product_id;
- version = get_pcb_revision_from_eeprom(); - switch (version) { - case 'a': - case 'A': - fdtfile = FDTFILE_VISIONFIVE2_1_2A; - break; - - case 'b': - case 'B': - default: - fdtfile = FDTFILE_VISIONFIVE2_1_3B; - break; - }; + product_id = get_product_id_from_eeprom(); + if (!product_id) { + log_err("Can't read EEPROM\n"); + return; + } + if (!strncmp(product_id, "MARS", 4)) { + fdtfile = FDTFILE_MILK_V_MARS; + } else if (!strncmp(product_id, "VF7110", 6)) { + version = get_pcb_revision_from_eeprom(); + + switch (version) { + case 'a': + case 'A': + fdtfile = FDTFILE_VISIONFIVE2_1_2A; + break; + + case 'b': + case 'B': + default: + fdtfile = FDTFILE_VISIONFIVE2_1_3B; + break; + } + } else { + log_err("Unknown product\n"); + return; + }
env_set("fdtfile", fdtfile); }

Sharing the info from Mars CM Lite 4GB: --------EEPROM INFO-------- Vendor : MILK-V Product full SN: MARC-V10-2340-D004E016-000006DF data version: 0x2 PCB revision: 0xc1 BOM revision: A Ethernet MAC0 address: 6c:cf:39:00:83:11 Ethernet MAC1 address: 6c:cf:39:00:83:12 --------EEPROM INFO--------
I do not like this practice of force setting fdtfile environment variable. If I set fdtfile from u-boot prompt and saveenv, I expect that my action as the user will persist over a reboot but instead it gets ignored and overwritten by this strategy. Is this necessary to happen before the boot scripts?
On Sun, Mar 3, 2024 at 5:02 AM Heinrich Schuchardt < heinrich.schuchardt@canonical.com> wrote:
Set environment variable fdtfile to the correct value for the Milk-V Mars board.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com
.../visionfive2/starfive_visionfive2.c | 43 +++++++++++++------ 1 file changed, 30 insertions(+), 13 deletions(-)
diff --git a/board/starfive/visionfive2/starfive_visionfive2.c b/board/starfive/visionfive2/starfive_visionfive2.c index 78e118d5a05..9970e309690 100644 --- a/board/starfive/visionfive2/starfive_visionfive2.c +++ b/board/starfive/visionfive2/starfive_visionfive2.c @@ -9,6 +9,7 @@ #include <dm.h> #include <fdt_support.h> #include <env.h> +#include <log.h> #include <asm/arch/eeprom.h> #include <asm/io.h> #include <asm/sections.h> @@ -17,6 +18,8 @@ DECLARE_GLOBAL_DATA_PTR; #define JH7110_L2_PREFETCHER_BASE_ADDR 0x2030000 #define JH7110_L2_PREFETCHER_HART_OFFSET 0x2000 +#define FDTFILE_MILK_V_MARS \
"starfive/jh7110-milkv-mars.dtb"
#define FDTFILE_VISIONFIVE2_1_2A \ "starfive/jh7110-starfive-visionfive-2-v1.2a.dtb" #define FDTFILE_VISIONFIVE2_1_3B \ @@ -48,20 +51,34 @@ static void set_fdtfile(void) { u8 version; const char *fdtfile;
const char *product_id;
version = get_pcb_revision_from_eeprom();
switch (version) {
case 'a':
case 'A':
fdtfile = FDTFILE_VISIONFIVE2_1_2A;
break;
case 'b':
case 'B':
default:
fdtfile = FDTFILE_VISIONFIVE2_1_3B;
break;
};
product_id = get_product_id_from_eeprom();
if (!product_id) {
log_err("Can't read EEPROM\n");
return;
}
if (!strncmp(product_id, "MARS", 4)) {
fdtfile = FDTFILE_MILK_V_MARS;
} else if (!strncmp(product_id, "VF7110", 6)) {
version = get_pcb_revision_from_eeprom();
switch (version) {
case 'a':
case 'A':
fdtfile = FDTFILE_VISIONFIVE2_1_2A;
break;
case 'b':
case 'B':
default:
fdtfile = FDTFILE_VISIONFIVE2_1_3B;
break;
}
} else {
log_err("Unknown product\n");
return;
} env_set("fdtfile", fdtfile);
}
2.43.0

On 3/8/24 23:37, E Shattow wrote:
Sharing the info from Mars CM Lite 4GB: --------EEPROM INFO-------- Vendor : MILK-V Product full SN: MARC-V10-2340-D004E016-000006DF data version: 0x2 PCB revision: 0xc1 BOM revision: A Ethernet MAC0 address: 6c:cf:39:00:83:11 Ethernet MAC1 address: 6c:cf:39:00:83:12 --------EEPROM INFO--------
I do not like this practice of force setting fdtfile environment variable. If I set fdtfile from u-boot prompt and saveenv, I expect that my action as the user will persist over a reboot but instead it gets ignored and overwritten by this strategy. Is this necessary to happen before the boot scripts?
We could check if $fdtfile is already set before the update.
This would require that the default environment does not include it. Cf.
include/configs/starfive-visionfive2.h:51: "fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0" \
Best regards
Heinrich
On Sun, Mar 3, 2024 at 5:02 AM Heinrich Schuchardt <heinrich.schuchardt@canonical.com mailto:heinrich.schuchardt@canonical.com> wrote:
Set environment variable fdtfile to the correct value for the Milk-V Mars board. Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com <mailto:heinrich.schuchardt@canonical.com>> --- .../visionfive2/starfive_visionfive2.c | 43 +++++++++++++------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/board/starfive/visionfive2/starfive_visionfive2.c b/board/starfive/visionfive2/starfive_visionfive2.c index 78e118d5a05..9970e309690 100644 --- a/board/starfive/visionfive2/starfive_visionfive2.c +++ b/board/starfive/visionfive2/starfive_visionfive2.c @@ -9,6 +9,7 @@ #include <dm.h> #include <fdt_support.h> #include <env.h> +#include <log.h> #include <asm/arch/eeprom.h> #include <asm/io.h> #include <asm/sections.h> @@ -17,6 +18,8 @@ DECLARE_GLOBAL_DATA_PTR; #define JH7110_L2_PREFETCHER_BASE_ADDR 0x2030000 #define JH7110_L2_PREFETCHER_HART_OFFSET 0x2000 +#define FDTFILE_MILK_V_MARS \ + "starfive/jh7110-milkv-mars.dtb" #define FDTFILE_VISIONFIVE2_1_2A \ "starfive/jh7110-starfive-visionfive-2-v1.2a.dtb" #define FDTFILE_VISIONFIVE2_1_3B \ @@ -48,20 +51,34 @@ static void set_fdtfile(void) { u8 version; const char *fdtfile; + const char *product_id; - version = get_pcb_revision_from_eeprom(); - switch (version) { - case 'a': - case 'A': - fdtfile = FDTFILE_VISIONFIVE2_1_2A; - break; - - case 'b': - case 'B': - default: - fdtfile = FDTFILE_VISIONFIVE2_1_3B; - break; - }; + product_id = get_product_id_from_eeprom(); + if (!product_id) { + log_err("Can't read EEPROM\n"); + return; + } + if (!strncmp(product_id, "MARS", 4)) { + fdtfile = FDTFILE_MILK_V_MARS; + } else if (!strncmp(product_id, "VF7110", 6)) { + version = get_pcb_revision_from_eeprom(); + + switch (version) { + case 'a': + case 'A': + fdtfile = FDTFILE_VISIONFIVE2_1_2A; + break; + + case 'b': + case 'B': + default: + fdtfile = FDTFILE_VISIONFIVE2_1_3B; + break; + } + } else { + log_err("Unknown product\n"); + return; + } env_set("fdtfile", fdtfile); } -- 2.43.0

On Fri, Mar 8, 2024 at 2:57 PM Heinrich Schuchardt < heinrich.schuchardt@canonical.com> wrote: ...
I do not like this practice of force setting fdtfile environment variable. If I set fdtfile from u-boot prompt and saveenv, I expect that my action as the user will persist over a reboot but instead it gets ignored and overwritten by this strategy. Is this necessary to happen before the boot scripts?
We could check if $fdtfile is already set before the update.
This would require that the default environment does not include it. Cf.
include/configs/starfive-visionfive2.h:51: "fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0" \
...
The default environment is expected to have a sensible default, and implicitly is only used when there is a checksum error (so no existing valid fdtfile environment variable). It is not nice to remove capability from userspace i.e. Linux mtd interface access to update u-boot environment variables; setting fdtfile as such has no effect as it will always be force set by this routine. The workaround now is to set fdtfile from a boot.scr but that adds a dependency to reside on storage (which is not always true for all boot situations).
What of "fdtfile=${fdtfile_board}" for the default environment and this routine instead updates $fdtfile_board (or similar) ? I'm not sure what to suggest, or if this is a common practice for u-boot board support. Thanks - E

The differences between the Milk-V Mars board and the VisionFive 2 board are small enough that we can support both using the same U-Boot build.
* The model and compatible property are taken from proposed Linux patches. * The EEPROM is atmel,24c02 according to the vendor U-Boot. * The second Ethernet port is not available.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com --- board/starfive/visionfive2/spl.c | 101 +++++++++++++++++++++++++++---- 1 file changed, 89 insertions(+), 12 deletions(-)
diff --git a/board/starfive/visionfive2/spl.c b/board/starfive/visionfive2/spl.c index 1b49945d11b..c62624a2eb5 100644 --- a/board/starfive/visionfive2/spl.c +++ b/board/starfive/visionfive2/spl.c @@ -27,6 +27,26 @@ struct starfive_vf2_pro { const char *value; };
+static const struct starfive_vf2_pro milk_v_mars[] = { + {"/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", + "motorcomm,rx-clk-drv-microamp", "3970"}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "motorcomm,rx-data-drv-microamp", "2910"}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "rx-internal-delay-ps", "1900"}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "tx-internal-delay-ps", "1500"}, +}; + static const struct starfive_vf2_pro starfive_vera[] = { {"/soc/ethernet@16030000/mdio/ethernet-phy@0", "rx-internal-delay-ps", "1900"}, @@ -67,6 +87,51 @@ static const struct starfive_vf2_pro starfive_verb[] = { "tx-internal-delay-ps", "0"}, };
+void spl_fdt_fixup_mars(void *fdt) +{ + static const char compat[] = "milkv,mars\0starfive,jh7110"; + u32 phandle; + u8 i; + int offset; + int ret; + + fdt_setprop(fdt, fdt_path_offset(fdt, "/"), "compatible", compat, sizeof(compat)); + fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model", + "Milk-V Mars"); + fdt_setprop_string(fdt, fdt_path_offset(fdt, "/soc/i2c@12050000/eeprom@50"), + "compatible", "atmel,24c02"); + + /* 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 */ + fdt_setprop_string(fdt, fdt_path_offset(fdt, "/soc/ethernet@16040000"), + "status", "disabled"); + + for (i = 0; i < ARRAY_SIZE(milk_v_mars); i++) { + offset = fdt_path_offset(fdt, milk_v_mars[i].path); + + if (starfive_verb[i].value) + ret = fdt_setprop_u32(fdt, offset, milk_v_mars[i].name, + dectoul(milk_v_mars[i].value, NULL)); + else + ret = fdt_setprop_empty(fdt, offset, milk_v_mars[i].name); + + if (ret) { + pr_err("%s set prop %s fail.\n", __func__, milk_v_mars[i].name); + break; + } + } +} + void spl_fdt_fixup_version_a(void *fdt) { static const char compat[] = "starfive,visionfive-2-v1.2a\0starfive,jh7110"; @@ -167,22 +232,34 @@ void spl_fdt_fixup_version_b(void *fdt) void spl_perform_fixups(struct spl_image_info *spl_image) { u8 version; + const char *product_id;
- 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); + product_id = get_product_id_from_eeprom(); + if (!product_id) { + pr_err("Can't read EEPROM\n"); + return; + } + if (!strncmp(product_id, "MARS", 4)) { + spl_fdt_fixup_mars(spl_image->fdt_addr); + } else if (!strncmp(product_id, "VF7110", 6)) { + 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; + }; + } else { + pr_err("Unknown product %s\n", product_id); };
- /* Update the memory size which read form eeprom or DT */ + /* Update the memory size which read from eeprom or DT */ fdt_fixup_memory(spl_image->fdt_addr, 0x40000000, gd->ram_size); }

On Sun, Mar 3, 2024 at 5:02 AM Heinrich Schuchardt < heinrich.schuchardt@canonical.com> wrote: ...
- The EEPROM is atmel,24c02 according to the vendor U-Boot.
...
The same vendor (Milk-V) U-Boot change is present on their branch for Mars CM Lite (which despite the naming has more in common with Pine64 Star64 than Mars); However on visual inspection the silkscreen markings are for 24c04. See: [Photo flatbed scans of Mars CM Lite 4GB rev 1.01]( https://github.com/geerlingguy/sbc-reviews/issues/22#issuecomment-1872478605). Can this be determined at runtime, or I must trust that this is not a wrongly marked chip?

P.S. Found the longer description at https://github.com/milkv-mars/mars-buildroot-sdk/commit/d381610c92827de01b25... as follows: "if configured as 24c04, its address will occupy 0x51, conflicting with the RTC chip pcf85063 on the IO-Board. Refer to: Documentation/misc-devices/eeprom.rst". What does that even mean, it is for Raspberry Pi Compute IO carrier only?
On Thu, Mar 7, 2024 at 3:03 PM E Shattow lucent@gmail.com wrote:
On Sun, Mar 3, 2024 at 5:02 AM Heinrich Schuchardt < heinrich.schuchardt@canonical.com> wrote: ...
- The EEPROM is atmel,24c02 according to the vendor U-Boot.
...
The same vendor (Milk-V) U-Boot change is present on their branch for Mars CM Lite (which despite the naming has more in common with Pine64 Star64 than Mars); However on visual inspection the silkscreen markings are for 24c04. See: [Photo flatbed scans of Mars CM Lite 4GB rev 1.01]( https://github.com/geerlingguy/sbc-reviews/issues/22#issuecomment-1872478605). Can this be determined at runtime, or I must trust that this is not a wrongly marked chip?

On 3/8/24 03:06, E Shattow wrote:
P.S. Found the longer description at https://github.com/milkv-mars/mars-buildroot-sdk/commit/d381610c92827de01b25... https://github.com/milkv-mars/mars-buildroot-sdk/commit/d381610c92827de01b25843786012351b3f35519 as follows: "if configured as 24c04, its address will occupy 0x51, conflicting with the RTC chip pcf85063 on the IO-Board. Refer to: Documentation/misc-devices/eeprom.rst". What does that even mean, it is for Raspberry Pi Compute IO carrier only?
According to https://ww1.microchip.com/downloads/en/devicedoc/doc0180.pdf the chips differ in how their address lines are used. Either they select a chip or a memory address.
The chip is at reg 0x50. So it could be that if you read the upper memory of atmel,24c04 it would use reg 0x51.
https://datasheets.raspberrypi.com/cm4io/cm4io-datasheet.pdf says the CM4IO board has an RTC at address 0x51.
Together with the commit message this really sounds like the smaller chip size is faked due to incompatibility.
As you mentioned to have access to a CM module I would like to know what its serial number looks like to understand what if it can be used to detect if we are running U-Boot on full board or a CM module.
For my Milk-V board I have:
MARS-V11-2340-D008E000-xxxxxxxx
Best regards
Heinrich

On 3/8/24 04:20, Heinrich Schuchardt wrote:
On 3/8/24 03:06, E Shattow wrote:
P.S. Found the longer description at https://github.com/milkv-mars/mars-buildroot-sdk/commit/d381610c92827de01b25... https://github.com/milkv-mars/mars-buildroot-sdk/commit/d381610c92827de01b25843786012351b3f35519 as follows: "if configured as 24c04, its address will occupy 0x51, conflicting with the RTC chip pcf85063 on the IO-Board. Refer to: Documentation/misc-devices/eeprom.rst". What does that even mean, it is for Raspberry Pi Compute IO carrier only?
According to https://ww1.microchip.com/downloads/en/devicedoc/doc0180.pdf the chips differ in how their address lines are used. Either they select a chip or a memory address.
The chip is at reg 0x50. So it could be that if you read the upper memory of atmel,24c04 it would use reg 0x51.
https://datasheets.raspberrypi.com/cm4io/cm4io-datasheet.pdf says the CM4IO board has an RTC at address 0x51.
Together with the commit message this really sounds like the smaller chip size is faked due to incompatibility.
Running i2cdetect on my Mars Milk-V board shows that a device is responding to address 0x51:
$ sudo i2cdetect 5 I will probe file /dev/i2c-5. I will probe address range 0x08-0x77. Continue? [Y/n] y 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: 10: 20: 30: -- -- -- -- -- -- UU -- 40: 50: 50 51 -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: 70:
As you mentioned to have access to a CM module I would like to know what its serial number looks like to understand what if it can be used to detect if we are running U-Boot on full board or a CM module.
For my Milk-V board I have:
MARS-V11-2340-D008E000-xxxxxxxx
Best regards
Heinrich

On 08.03.24 00:03, E Shattow wrote:
On Sun, Mar 3, 2024 at 5:02 AM Heinrich Schuchardt <heinrich.schuchardt@canonical.com mailto:heinrich.schuchardt@canonical.com> wrote: ...
* The EEPROM is atmel,24c02 according to the vendor U-Boot.
...
The same vendor (Milk-V) U-Boot change is present on their branch for Mars CM Lite (which despite the naming has more in common with Pine64 Star64 than Mars); However on visual inspection the silkscreen markings are for 24c04. See: [Photo flatbed scans of Mars CM Lite 4GB rev 1.01](https://github.com/geerlingguy/sbc-reviews/issues/22#issuecomment-1872478605 https://github.com/geerlingguy/sbc-reviews/issues/22#issuecomment-1872478605). Can this be determined at runtime, or I must trust that this is not a wrongly marked chip?
On the Milk-V Mars there is a chip marked "24C04F 21626P" like on the photo on the CM module from the thread above. This should be the EEPROM.
In some datasheets F is appended to mark the voltage range.
So this atmel,24c02 change seems really only be relevant if you have a CM module on a baseboard with an RTC at 0x51.
Best regards
Heinrich

The usage of common.h is deprecated. Remove it from board files.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com --- board/starfive/visionfive2/spl.c | 1 - board/starfive/visionfive2/starfive_visionfive2.c | 1 - board/starfive/visionfive2/visionfive2-i2c-eeprom.c | 1 - 3 files changed, 3 deletions(-)
diff --git a/board/starfive/visionfive2/spl.c b/board/starfive/visionfive2/spl.c index c62624a2eb5..1699ed20acf 100644 --- a/board/starfive/visionfive2/spl.c +++ b/board/starfive/visionfive2/spl.c @@ -4,7 +4,6 @@ * Author: Yanhong Wangyanhong.wang@starfivetech.com */
-#include <common.h> #include <asm/arch/eeprom.h> #include <asm/arch/gpio.h> #include <asm/arch/regs.h> diff --git a/board/starfive/visionfive2/starfive_visionfive2.c b/board/starfive/visionfive2/starfive_visionfive2.c index 9970e309690..e299769e50e 100644 --- a/board/starfive/visionfive2/starfive_visionfive2.c +++ b/board/starfive/visionfive2/starfive_visionfive2.c @@ -4,7 +4,6 @@ * Author: Yanhong Wangyanhong.wang@starfivetech.com */
-#include <common.h> #include <cpu_func.h> #include <dm.h> #include <fdt_support.h> diff --git a/board/starfive/visionfive2/visionfive2-i2c-eeprom.c b/board/starfive/visionfive2/visionfive2-i2c-eeprom.c index a9f4376c8e1..ddef7d61235 100644 --- a/board/starfive/visionfive2/visionfive2-i2c-eeprom.c +++ b/board/starfive/visionfive2/visionfive2-i2c-eeprom.c @@ -4,7 +4,6 @@ * Author: Yanhong Wangyanhong.wang@starfivetech.com */
-#include <common.h> #include <command.h> #include <env.h> #include <i2c.h>

Add instructions to build U-Boot for the Milk-V Mars board
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com --- doc/board/starfive/index.rst | 1 + doc/board/starfive/milk-v_mars.rst | 93 ++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 doc/board/starfive/milk-v_mars.rst
diff --git a/doc/board/starfive/index.rst b/doc/board/starfive/index.rst index 0c52dc7b095..2762bf74c11 100644 --- a/doc/board/starfive/index.rst +++ b/doc/board/starfive/index.rst @@ -6,4 +6,5 @@ StarFive .. toctree:: :maxdepth: 1
+ milk-v_mars.rst visionfive2 diff --git a/doc/board/starfive/milk-v_mars.rst b/doc/board/starfive/milk-v_mars.rst new file mode 100644 index 00000000000..9cfd5d7bddd --- /dev/null +++ b/doc/board/starfive/milk-v_mars.rst @@ -0,0 +1,93 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Milk-V Mars +=========== + +U-Boot for the Milk-V Mars uses the same U-Boot binaries as the VisionFive 2 +board. In U-Boot SPL the actual board is detected and the device-tree patched +accordingly. + +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 M-mode software OpenSBI provides the supervisor binary interface (SBI) and +is responsible for the switch to S-Mode. It is a prerequisite to build U-Boot. +Support for the JH7110 was introduced in OpenSBI 1.2. It is recommended to use +a current release. + +.. code-block:: console + + git clone https://github.com/riscv/opensbi.git + cd opensbi + make PLATFORM=generic FW_TEXT_START=0x40000000 FW_OPTIONS=0 + +Now build the U-Boot SPL and U-Boot proper. + +.. code-block:: console + + cd <U-Boot-dir> + make starfive_visionfive2_defconfig + make OPENSBI=$(opensbi_dir)/build/platform/generic/firmware/fw_dynamic.bin + +This will generate the U-Boot SPL image (spl/u-boot-spl.bin.normal.out) as well +as the FIT image (u-boot.itb) with OpenSBI and U-Boot. + +Boot source selection +~~~~~~~~~~~~~~~~~~~~~ + +The board provides the DIP switches MSEL[1:0] to select the boot device out of +SPI flash, eMMC, SD-card, UART. To select booting from SD-card set the DIP +switches MSEL[1:0] to 10. + +Preparing the SD-Card +~~~~~~~~~~~~~~~~~~~~~ + +The device firmware loads U-Boot SPL (u-boot-spl.bin.normal.out) from the +partition with type GUID 2E54B353-1271-4842-806F-E436D6AF6985. You are free +to choose any partition number. + +With the default configuration U-Boot SPL loads the U-Boot FIT image +(u-boot.itb) from partition 2 (CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION=0x2). +When formatting it is recommended to use GUID +BC13C2FF-59E6-4262-A352-B275FD6F7172 for this partition. + +The FIT image (u-boot.itb) is a combination of OpenSBI's fw_dynamic.bin, +u-boot-nodtb.bin and the device tree blob. + +Format the SD card (make sure the disk has GPT, otherwise use gdisk to switch) + +.. code-block:: bash + + sudo sgdisk --clear \ + --set-alignment=2 \ + --new=1:4096:8191 --change-name=1:spl --typecode=1:2E54B353-1271-4842-806F-E436D6AF6985\ + --new=2:8192:16383 --change-name=2:uboot --typecode=2:BC13C2FF-59E6-4262-A352-B275FD6F7172 \ + --new=3:16384:1654784 --change-name=3:system --typecode=3:EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 \ + /dev/sdb + +Copy U-Boot to the SD card + +.. code-block:: bash + + sudo dd if=u-boot-spl.bin.normal.out of=/dev/sdb1 + sudo dd if=u-boot.itb of=/dev/sdb2 + + sudo mount /dev/sdb3 /mnt/ + sudo cp u-boot-spl.bin.normal.out /mnt/ + sudo cp u-boot.itb /mnt/ + sudo cp Image.gz /mnt/ + sudo cp initramfs.cpio.gz /mnt/ + sudo cp jh7110-starfive-visionfive-2.dtb /mnt/ + sudo umount /mnt + +Booting +~~~~~~~ + +Once you plugin the sdcard and power up, you should see the U-Boot prompt.

On Sun, Mar 3, 2024 at 5:02 AM Heinrich Schuchardt < heinrich.schuchardt@canonical.com> wrote: ...
+The board provides the DIP switches MSEL[1:0] to select the boot device out of +SPI flash, eMMC, SD-card, UART. To select booting from SD-card set the DIP +switches MSEL[1:0] to 10.
This does not match the [Milk-V Mars vendor documentation]( https://milkv.io/docs/mars/getting-started/bootloader). Maybe you have a different board revision?

On 3/8/24 00:20, E Shattow wrote:
On Sun, Mar 3, 2024 at 5:02 AM Heinrich Schuchardt <heinrich.schuchardt@canonical.com mailto:heinrich.schuchardt@canonical.com> wrote: ...
+The board provides the DIP switches MSEL[1:0] to select the boot device out of +SPI flash, eMMC, SD-card, UART. To select booting from SD-card set the DIP +switches MSEL[1:0] to 10.
This does not match the [Milk-V Mars vendor documentation](https://milkv.io/docs/mars/getting-started/bootloader https://milkv.io/docs/mars/getting-started/bootloader). Maybe you have a different board revision?
Thank you for reviewing.
My board revision is V1.21 according to the silk screen.
The Milk-V Mars has DIP switches for the boot selection as shown in https://gist.github.com/xypron/e28f95b1ed6911aeb9699ba63ae1a885
If you look at the photo https://milkv.io/assets/images/mars-icon-04-e8814f18158a0e9d4387f4fa330693f1... in the https://milkv.io/mars page, it also shows DIP switches (in the SPI-Flash position) on a rev 1.2 board.
Did you see a board without DIP switches being sold?
The silk screen markings on the board and the switch don't match. The same confusion exists on the VisionFive2.
So maybe I should better write in a table:
SPI-Flash: GPIO0=L GPIO1=L
SD-Card: GPIO0=H GPIO1=L
eMMC: GPIO0=L GPIO1=H
UART: GPIO0=H GPIO1=H
Best regards
Heinrich

Yes this reference to GPIO high/low states is clearer to understand. Have you tested the DIP switch functionality to confirm?; It is not shown in the MilkV documentation or outdated schematics and I don't have a Mars to test. I did find function descriptions from what is likely cut-and-paste of VisionFive2 board reference.
Ref: https://github.com/milkv-mars/mars-files/blob/main/Mars_hardware_schematics/... Sheet 7 of 22 JH7110 GPIOs There is a schematic for SW2 (bootloader button?) that lists an inset table: * - GPIO_1 - GPIO_0 - Boot * - 0 - 0 - Flash * - 0 - 1 - SD * - 1 - 0 - eMMC * - 1 - 1 - UART
That circuit on SW2 appears to pull high both RGPIO_1 and RGPIO_0 with transistors. Again, no DIP switch as this is an earlier revision.
Ref: https://doc-en.rvspace.org/VisionFive2/Developer_Guide/JH7110_Boot_UG.pdf page 9 table 1-4: RGPIO1=0x0 RGPIO0=0x0 Boot Source: Quad SPI NOR flash memory, Read SPL from Sector 0. RGPIO1=0x1 RGPIO0=0x1 Boot Source: UART0, (description of UART Xmodem function).
Following in the same document on page 13 figure 2-1 Boot Flow: JH7110 supports the following boot devices. QSPI Flash (For SPL + OpenSBI + U-Boot) + NVMe/SD Card/eMMC (For Kernel + Fi le System and later) Note: System will detect in sequence whether it can boot from the following device sequence: NVMe > SD > eMMC. For example, if the boot program is found on the SD, eMMC will be ignored.
Again in this document Figure 4-2 on page 17 is a visual listing of the DIP switch positions for QSPI, SDIO, eMMC, and UART boot modes, of the VisionFive2 board.
The only consistent physical interface over VisionFive2, Mars, Star64, Mars CM all is RGPIO1=L RGPIO0=L SPI and RGPIO1=H RGPIO1=H UART; either by DIP switch or pushbutton attached circuit. So, I question our assumptions about what the actual behavior is for RGPIO1=H RGPIO0=L pairing and RGPIO1=L RGPIO0=H, and in what circumstance would there be followed a device sequence as suggested by the JH7110 reference. Why does the StarFive documentation list a JH7110 boot device sequence if there is also these H+L or L+H pairings to choose the device?
On Thu, Mar 7, 2024 at 6:37 PM Heinrich Schuchardt < heinrich.schuchardt@canonical.com> wrote:
On 3/8/24 00:20, E Shattow wrote:
On Sun, Mar 3, 2024 at 5:02 AM Heinrich Schuchardt <heinrich.schuchardt@canonical.com mailto:heinrich.schuchardt@canonical.com> wrote: ...
+The board provides the DIP switches MSEL[1:0] to select the boot device out of +SPI flash, eMMC, SD-card, UART. To select booting from SD-card set the DIP +switches MSEL[1:0] to 10.
This does not match the [Milk-V Mars vendor documentation](https://milkv.io/docs/mars/getting-started/bootloader https://milkv.io/docs/mars/getting-started/bootloader). Maybe you
have
a different board revision?
Thank you for reviewing.
My board revision is V1.21 according to the silk screen.
The Milk-V Mars has DIP switches for the boot selection as shown in https://gist.github.com/xypron/e28f95b1ed6911aeb9699ba63ae1a885
If you look at the photo
https://milkv.io/assets/images/mars-icon-04-e8814f18158a0e9d4387f4fa330693f1... in the https://milkv.io/mars page, it also shows DIP switches (in the SPI-Flash position) on a rev 1.2 board.
Did you see a board without DIP switches being sold?
The silk screen markings on the board and the switch don't match. The same confusion exists on the VisionFive2.
So maybe I should better write in a table:
SPI-Flash: GPIO0=L GPIO1=L
SD-Card: GPIO0=H GPIO1=L
eMMC: GPIO0=L GPIO1=H
UART: GPIO0=H GPIO1=H
Best regards
Heinrich

On 3/8/24 22:48, E Shattow wrote:
Yes this reference to GPIO high/low states is clearer to understand. Have you tested the DIP switch functionality to confirm?; It is not shown in the MilkV documentation or outdated schematics and I don't have a Mars to test. I did find function descriptions from what is likely cut-and-paste of VisionFive2 board reference.
Ref: https://github.com/milkv-mars/mars-files/blob/main/Mars_hardware_schematics/... https://github.com/milkv-mars/mars-files/blob/main/Mars_hardware_schematics/Mars_V1.11_20230821.pdf Sheet 7 of 22 JH7110 GPIOs There is a schematic for SW2 (bootloader button?) that lists an inset table:
- GPIO_1
- GPIO_0 - Boot
- 0
- 0 - Flash
- 0
- 1 - SD
- 1
- 0 - eMMC
- 1
- 1 - UART
That circuit on SW2 appears to pull high both RGPIO_1 and RGPIO_0 with transistors. Again, no DIP switch as this is an earlier revision.
Ref: https://doc-en.rvspace.org/VisionFive2/Developer_Guide/JH7110_Boot_UG.pdf https://doc-en.rvspace.org/VisionFive2/Developer_Guide/JH7110_Boot_UG.pdf page 9 table 1-4: RGPIO1=0x0 RGPIO0=0x0 Boot Source: Quad SPI NOR flash memory, Read SPL from Sector 0. RGPIO1=0x1 RGPIO0=0x1 Boot Source: UART0, (description of UART Xmodem function).
Following in the same document on page 13 figure 2-1 Boot Flow: JH7110supportsthefollowingbootdevices. QSPIFlash(ForSPL + OpenSBI + U-Boot)+NVMe/SDCard/eMMC(ForKernel+FileSystemandlater) Note: System will detect in sequence whether it can boot from the following device sequence: NVMe > SD > eMMC. For example,if the boot program is found on the SD, eMMC will be ignored.
The GPIOs select from where U-Boot SPL is loaded. Currently U-Boot SPL loads main U-Boot from the same device. But you could change it to scan multiple devices for main U-Boot.
Once you have successfully loaded main U-Boot, main U-Boot will scan the different boot devices. This includes NVME, eMMC, SD, USB, Network.
Currently upstream U-Boot development is moving from hard coded sequences in board files to configurable boot sequences.
Again in this document Figure 4-2 on page 17 is a visual listing of the DIP switch positions for QSPI, SDIO, eMMC, and UART boot modes, of the VisionFive2 board.
These are just the same switches as on the Milk-V.
The only consistent physical interface over VisionFive2, Mars, Star64, Mars CM all is RGPIO1=L RGPIO0=L SPI and RGPIO1=H RGPIO1=H UART; either by DIP switch or pushbutton attached circuit. So, I question our assumptions about what the actual behavior is for RGPIO1=H RGPIO0=L pairing and RGPIO1=L RGPIO0=H, and in what circumstance would there be followed a device sequence as suggested by the JH7110 reference. Why does the StarFive documentation list a JH7110 boot device sequence if there is also these H+L or L+H pairings to choose the device?
As said the device sequence including NVMe is not realized by the code loading U-Boot SPL. It is realized in main U-Boot.
Best regards
Heinrich
On Thu, Mar 7, 2024 at 6:37 PM Heinrich Schuchardt <heinrich.schuchardt@canonical.com mailto:heinrich.schuchardt@canonical.com> wrote:
On 3/8/24 00:20, E Shattow wrote: > > On Sun, Mar 3, 2024 at 5:02 AM Heinrich Schuchardt > <heinrich.schuchardt@canonical.com <mailto:heinrich.schuchardt@canonical.com> > <mailto:heinrich.schuchardt@canonical.com <mailto:heinrich.schuchardt@canonical.com>>> wrote: > ... > > +The board provides the DIP switches MSEL[1:0] to select the boot > device out of > +SPI flash, eMMC, SD-card, UART. To select booting from SD-card set > the DIP > +switches MSEL[1:0] to 10. > > > This does not match the [Milk-V Mars vendor > documentation](https://milkv.io/docs/mars/getting-started/bootloader <https://milkv.io/docs/mars/getting-started/bootloader> > <https://milkv.io/docs/mars/getting-started/bootloader <https://milkv.io/docs/mars/getting-started/bootloader>>). Maybe you have > a different board revision? Thank you for reviewing. My board revision is V1.21 according to the silk screen. The Milk-V Mars has DIP switches for the boot selection as shown in https://gist.github.com/xypron/e28f95b1ed6911aeb9699ba63ae1a885 <https://gist.github.com/xypron/e28f95b1ed6911aeb9699ba63ae1a885> If you look at the photo https://milkv.io/assets/images/mars-icon-04-e8814f18158a0e9d4387f4fa330693f1.webp <https://milkv.io/assets/images/mars-icon-04-e8814f18158a0e9d4387f4fa330693f1.webp> in the https://milkv.io/mars <https://milkv.io/mars> page, it also shows DIP switches (in the SPI-Flash position) on a rev 1.2 board. Did you see a board without DIP switches being sold? The silk screen markings on the board and the switch don't match. The same confusion exists on the VisionFive2. So maybe I should better write in a table: SPI-Flash: GPIO0=L GPIO1=L SD-Card: GPIO0=H GPIO1=L eMMC: GPIO0=L GPIO1=H UART: GPIO0=H GPIO1=H Best regards Heinrich
participants (2)
-
E Shattow
-
Heinrich Schuchardt