Try   HackMD

VisionFive/JH7100 ideas

Pseudocode conventions

(Who knows, might need them)

  • Memory ranges: start_addr + size, e.g. 0x2000_0000 + 256MiB
  • Bit ranges: [end:start], both inclusive.
  • Data addresses: type[addr], e.g. uint32_t[0x1185_81a0]

Boot process

Generally in this order:

  • Boot ROM (Mask ROM 0x18400000, no source code)
  • secondBoot (SPI flash offset 0x00_0000 to intRAM0 0x1800_0000)
  • ddrinit (SPI flash offset 0x01_0000 to intRAM1 0x1808_0000)
  • OpenSBI + u-boot (SPI flash offset 0x04_0000 to DDR 0x8000_0000)
  • payload, mostly Linux (Usually on storage such as SD card or USB drive, or network)

There are various 'secret' register definitions in the vendor source code. I've collected some of them in this gist.

Boot ROM

You can just dump the code and put it into Ghidra or something.

Based on ddrinit, or at least very similar. Unused code in ddrinit can be found in the Boot ROM.

On the VisionFive board.

  • SCFG_boot_mode = 0
  • PAD_GPIO[61:60] = 0 (Set with resistors)
  • PAD_GPIO[62] = 'BOOT MODE' button (Held is 1)
  • PAD_GPIO[63] = 1 (Set with resistors)

Boot always goes to ROM, which is 0x1184_0000 + 32KiB

Not hart 0

  • wfi (Expecting MSI from CLINT)
  • Reads uint32_t[0x1801_fffc]
  • Jumps to that address

Hart 0

  • gpio_init() (Commented out code in ddrinit)
  • uart_init(3) (9600 baud at 'DEBUG' port)
  • If button held: boot_from_uart()
  • Otherwise: boot_from_spi(1), loads secondBoot

secondBoot

ddrinit

DRAM Controller

The controller is an OpenEdges OMC (ORBIT Memory Controller). The following information is copied from the website.

DRAM Support
  • JEDEC compliant LPDDR5x/5/4x/4/3, DDR4/3, GDDR6, HBM3 support
  • Up to 4 ranks/channel (configurable)
High Performance
  • Proprietary out-of-order scheduling algorithm​
  • Dual-PHY control for 2x DRAM channel bandwidth with a single OMC instance
Low Power Consumption
  • Ultra-low power consumption with HW controlled dynamic DRAM frequency scaling
  • Automatically handles training activities required for frequency change
  • Automated DRAM power management

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

OpenSBI + U-Boot

Booting and create a combined FIT uImage:
https://www.thegoodpenguin.co.uk/blog/u-boot-fit-image-overview/

Booting from SD card

Flat image
# load files from FAT fs from SD card to memory
fatload mmc 0 80200000 Image
fatload mmc 0 82200000 jh7100-starfive-visionfive-v1.dtb
# set a kernel cmdline, aka bootargs in U-Boot
setenv bootargs "console=ttyS0,115200 earlycon=sbi"
# boot a raw Image; note: the "-" means that we have no initrd
booti 80200000 - 82200000
FIT image
fatload mmc 0 80200000 mImage
setenv bootargs "console=ttyS0,115200 earlycon=sbi"
bootm 80200000

Network boot

We can use centre from Harvey OS to serve TFTP and DHCP.

setenv serverip 192.168.22.1
setenv bootargs "console=ttyS0,115200 earlycon=sbi"
dhcp;tftpboot 80200000 mImage;bootm 80200000

Linux

A bunch of very interesting stuff in the device tree files:

Peripherals and other ports

(Q)SPI flash

  • Clocks: qspi_refclk, qspi_ahb, qspi_apb
  • Resets: qspi_core, qspi_ahb, qspi_apb

cdns,qspi-nor

The flash chip on-board supports QSPI but actually only single-wire SPI is ever used. Resets to reading with EBh command so AHB doesn't work at power-on.

  • Reading AHB requires:
    • uint32_t[0x11800000] = 0x01000000 (secondBoot, early)
      • _SWITCH_CLOCK_clk_cpundbus_root_SOURCE_clk_pll0_out_
    • uint32_t[0x11800010] = 0x01000000 (secondBoot, early)
      • _SWITCH_CLOCK_clk_perh0_root_SOURCE_clk_pll0_out_
    • uint32_t[0x11860004] = 0x00000003 (secondBoot, when reading flash)

GPIO

The JH7100 has a kinda confusing GPIO multiplexer, though it's not that bad if you're just a user and never go that low level

https://elixir.bootlin.com/linux/v5.19-rc5/source/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml#L9

UART

GPIO13/GPIO14 on the 40-pin header and the 'DEBUG' header are both UART3 because of the GPIO mux thing.

IO pad configuration

The IO pad is used to configure on which GPIO pins the peripherals appear. secondBoot moves the UART to be seen on the 40 pin header instead of the extra debug header. The further vendor firmware components (DDR init, U-Boot, OpenSBI) assume that the UART is running on 115200 baud, whereas the initial mask ROM sets it to 9600 for xmodem transfer.

The UART movment happens here in secondBoot, _SET_SYSCON_REG_register104_SCFG_io_padshare_sel(6);:

https://github.com/starfive-tech/JH7100_secondBoot/blob/e17302063c9a4b74475b18ff24dd149c27257354/boot/bootmain.c#L178-L183

We can retain this switch so that we can use the boot mode / xmodem transfer to start running from SRAM for development, but still use the full baud rate on the other header. I.e., we need to hook up two USB serial adapters.

JTAG

Clocks

https://github.com/starfive-tech/linux/blob/visionfive/drivers/clk/starfive/clk-starfive-jh7100.c

E24 core

  • Clocks: e24_apb, e24rtc
  • Resets: e24

(mtime ticks according to the e24rtc)

  • JTAG on a different TAP on the same scan chain as U74
  • E24 reset vector uint32_t[0x1185_00bc] (register47_e24_reset_vector).
  • Memory map: E24 System Bus 0x8000_0000 + 2GiB is the same as U74 0x1000_0000 + 2GiB.
    • Has access to first 256MiB of DDR RAM (0x8000_0000 + 256MiB)
    • Not cache coherent!

CLIC

Info on the Core-Local Interrupt Controller:

The 'local interrupt' lines:

  • I have no idea what the CLIC is connected to.
  • The E24 CLIC is connected to the same interrupts as the U74 PLIC
    • E24 Local interrupt n is U74 PLIC interrupt source n + 1 (CLIC has lint0, but PLIC doesn't have source 0)

Is this the first silicon available to the general public with a SiFive CLIC?

Ethernet

The transceiver is a Motorcomm YT8521SH.

  • Clocks: msi_apb
  • Resets: msi_apb

Ever want to control 10 different interrupts from MMIO? I don't know why you'd want that, but

  • ChipLink/MSI Slave: 0x1247_0000 + 32KiB

Every single 4-byte word is aliased to the same 32-bit register. It seems that this device doesn't do address decoding.

Format:

  • bits[31:10] Hard-wired to zero
  • bits[9:0] Controls PLIC interrupts [42:33] and CLIC interrupts [41:32]

Vivante GC300 GPU (?)

  • Clocks: gc300_2x, gc300_ahb, gc300_axi, jpcgc300_axibus, jpcgc300_mainclk
  • Resets: gc300_2x, gc300_ahb, gc300_axi, jpcgc300_main
  • Interrupts (unknown)

(What's 'JPC'?)

This isn't even mentioned in the vendor datasheet. Secret GPU? Completely broken? Needs more info.

  • GPU2D_CSR 0x1010_0000 + 256KiB

Mainline etnaviv initializes fine, but DMA doesn't seem to work.

[   28.069600] etnaviv etnaviv: bound 10100000.gpu (ops gpu_ops [etnaviv])
[   28.073585] etnaviv-gpu 10100000.gpu: model: GC300, revision: 4635
[   28.212694] [drm] Initialized etnaviv 1.3.0 20151214 for etnaviv on minor 0

Xtensa Vision P6

If you mux out the JTAG ports, OpenOCD can recognize Xtensa from IDCODE. Need a core configuration file to do anything meaningful, so probably never going to get it