38 KiB
VisionFive 2
3x C files
Sourced from https://github.com/starfive-tech/u-boot/tree/JH7110_VF2_6.6_v5.13.2 , the VisionFive 2 port of the U-Boot bootloader.
Documentation to come, prioritising K1, which does not have a EDK2 port at time of writing.
Files
spl.c
Functions
spl_board_init_f
wrapper for spl_soc_init
spl_parse_board_header
Set spl_image_size
= 0x01000000
set entrypoint
= 0x40000000
set load_addr
= 0x40000000
set os
= IH_OS_U_BOOT
(17; firmware)
spl_boot_device
read from the MODE_SELECT_REG
(0x1702002c
), and check the first 2 bits.
Boot mode | boot device |
---|---|
0 | SPI |
1 | MMC2 |
2 | MMC1 |
3 | UART |
default to log and return BOOT_DEVICE_NONE
(16)
spl_get_load_buffer
return STARFIVE_SPL_BOOT_LOAD_ADDR
(0x60000000
)
board_init_f
call starfive_jh7110_pll_set_rate
for PLL0
to 1000MHz
; set PLL0 to 1GHz
call starfive_jh7110_pll_set_rate
for PLL2
to 1188MHz
; set PLL2 to 1.188GHz
DDR control depends on clk init
This section seems to simply index these addresses, and write nothing to it.
clkrsetbits_le32
takes in 3 args; address, bits to clear, and bits to set. This then reads the address, clear and set bits, then write back to the address.
call clrsetbits_le32
with args
SYS_CRG_BASE
(0x13020000
)CLK_CPU_ROOT_SW_MASK
(0x1000000
)BIT(CLK_BUS_ROOT_SW_SHIFT) & CLK_BUS_ROOT_SW_MASK
(0x1000000
)
call clrsetbits_le32
with args
SYS_CRG_BASE + CLK_BUS_ROOT_OFFSET
(0x13020000 + 0x1000000
=0x14020000
)CLK_CPU_ROOT_SW_MASK
(0x1000000
)BIT(CLK_BUS_ROOT_SW_SHIFT) & CLK_BUS_ROOT_SW_MASK
(0x1000000
)
set clk_perh_root clk default mux sel to pll2
This section seems to simply index these addresses, and write nothing to it.
call clrsetbits_le32
with args
SYS_CRG_BASE + CLK_PERH_ROOT_OFFSET
(0x13020000 + 0x10
=0x13020010
)CLK_PERH_ROOT_MASK
(0x1000000
)BIT(CLK_PERH_ROOT_SHIFT) & CLK_PERH_ROOT_MASK
(0x1000000
)
lots of bitmanip, not worth interpreting
Improved GMAC0 TX I/O PAD compatibility
lots of bitmanip, not worth interpreting
Improved GMAC1 TX I/O PAD compatibility
lots of bitmanip, not worth interpreting
Set GPIO to 3.3v
set SYS_SYSCON_BASE + 0xc
(0x13030000 + 0xc
= 0x1303000c
) to 0x0
(doesn't immediately seem to do anything?)
setup uart0
setup jtag
reset emmc
reset sdio
init i2c5
call spl_early_init
, panic if fail
call arch_cpu_init_dm
call preloader_console_init
call spl_board_init_f
, log if fail
return
board_fit_config-name_match
No implementation, always use first config
spl_enable_uart2
set bit 31 at address SYS_CRG_BASE + CLK_UART2_APB_OFFSET
(0x13020000 + 0x254
= 0x13020254
)
set bit 31 at address SYS_CRG_BASE + CLK_UART2_CORE_OFFSET
(0x13020000 + 0x258
= 0x13020258
)
clear bits 23 and 24 at address SYS_CRG_BASE + CLK_RSTN_3_OFFSET
(0x13020000 + 0x300
= 0x13020300
)
declare GPIO 43 as digital input
set GPIO 43 digital output (???) to 0x4f
set drive strength for GPIO 43 to 3 (12mA)
set GPIO 42 as digital input
set GPIO 42 digital input (???) to 62
spl_perform_fixups
get the rtos base address and the offset, and if they both eist, call spl_enable_uart2
. set rtos_image_address to CONFIG_SPL_OPENSBI_LOAD_ADDR
(0x40000000
) + the loaded offset, then copy the rtos from the image to the base address
starfive_visionfive2.c
Functions
sys_reset_clear
clear the passed reset bit at the address SYS_CRG_BASE
(0x13020000
) + the passed assert
wait for the status register to change
jh7110_timer_init
lots of bitmanip, not worth interpreting
Enable APB, Timer0-Timer3 clocks
reset all timers
jh7110_gmac_init_1000M
init the given ethernet port at the given speed. lots of bitmanip, not worth interpreting
jh7110_gmac_init_100M
init the given ethernet port at the given speed. lots of bitmanip, not worth interpreting
jh7110_gmac_sel_tx_to_rgmii
init the ethernet port for common sub-gigabit comms (RGMII is best documented by Intel in their Cyclone V and Arria V SoC design guidelines)
set_uboot_fdt_addr_env
set envvar uboot_fdt_addr
from the devicetree blob
get_chip_type
call get_data_from_eeprom
to get the chip revision, then set the chip_vision
envvar accordingly (a->A, b->B, other -> unknown). Also return type
get_board_type
call get_pcb_revision_from_eeprfom
to get the board revision. Check the masked information for one of the 3 board versions
jh7110_gmac_init
If the passed chip type is A, do nothing. otherwise, set up the ethernet for RGMII for both ports
If the board type is BOARD_1000M_100M
, init ethernet for 1000M
on port 0 and 100M
on port 1. Otherwise, use 1000M
for both.
jh7110_usb_init
USB init; more bit manip
get_cpu_voltage_type
read the binning offset of the chip, and adjust envvar cpu_max_vol
to 1000000
, 1060000
, 1020000
; map to 0x08f0
, 0x0ff0
, and 0x0ef0
respectively
jh7110_jtag_init
JTAG init; bit manip
jh7110_i2c_init
If passed id is 5, set stuff up. Otherwise, don't do anything
get_boot_mode
check bits 1 and 2 against the value in AON_IOMUX_BASE + AON_GPIO_DIN_REG
(0x17020000 + 0x2c
= 0x1702002c
)
Boot version | encoding | bootmode envvar |
devnum envvar |
---|---|---|---|
FLASH | 0 | flash | 1 |
SD | 1 | sd | 1 |
EMMC | 2 | emmc | 0 |
default | default | uart | 1 |
jh7110_gpio_init
pin 57 set to output enable, GPO of 0 (???), DIN (???) of 9. Drive strength set to 3, and pullup resistors
pin 58 set to output enable, GPO of 0 (???), DIN (???) of 10. Drive strength set to 3, and pullup resistors
board_init
enable cache
jtag init
timer init
usb init, primarily USB2
i2c init
gpio init
board_late_init
Get boot mode, and init gmac based on chip and board type
update memory_addr
and memory_size
envvars accordingly
Get the UCLASS_VIDEO
device, and return early if fail
Display the logo provided to the screen, return quietly but early if fail
get the opmsg_shmem
object from the devicetree. If this is successful, get the base from the devicetree. and if this exists, set the eth0addr and eth1addr envvars according to read mac addresses
misc_init_r
hardcoded mac addresses of 6c:cf:39:6c:de:ad
and 6c:cf:39:7c:ae:5d
If the build config includes OTP (one-time programmable memory), try to read the mac address from the OTP first, and overwrite the hardcoded mac addresses
set the eth0addr and eth1addr based on mac address
get the chip name
set the envvar for uboot fdt address
if OTP, get cpu voltage type as well
check_eeprom_dram_info
Only exists if CONFIG_ID_EEPROM
is set
only allow valid values of 1, 2, 4, 8, and 16
resize_ddr_from_eeprom
Only has behaviour if CONFIG_ID_EEPROM
is set
Get the i2c device, return early if it doesn't init properly
get the memory size info from the eeprom, and check then return the RAM size
board_ddr_size
wrapper for resize_ddr_from_eeprom
visionfive2-i2c-eeprom.c
Functions
is_match_magic
stringcompare passed hats to hats signature
calculate_crc16
well commented and documented
update_crc
update CRC of passed eeprom atom
dump_raw_eeprom
display raw hex from eeprom
hats_atom_crc_check
check atom crc
hats_get_atom
iterate over atoms listed in header, check them. return the atom we're looking for
show_eeprom
print formatted eeprom contents
parse_eeprom_info
if correct: has_been_read set to 1, then display info else: has_been_read set to -1, dump hex data to output
Get the atom HATS_ATOM_VENDOR
, and if it exists, save the serialnumber
get the atom HATS_ATOM_CUSTOM
, and if it exists, save PCB rev, BOM rev, MAC0, and MAC1 addresses
read_eeprom
check has_been_read
, return immediately if it's set already; comms over i2c using dm_i2c_read
prog_eeprom
write eeprom from memory; comm over i2c.
check match magit from the given buffer. If it matches magic properly, write to board using dm_i2c_write
set_mac_address
check the mac address and save to the RAM-saved EEPROM copy, including update crc
set_pcb_revision
edit in-RAM EEPROM copy; update crc
set_bom_revision
set uppercase BOM revision to the in-RAM EEPROM copy; update crc
set_product_id
set product ID as string to the in-RAM EEPROM copy; update crc
init_local_copy
init in-memory EEPROM with magic number. Must be done to init blank eeprom or overwrite corrupted magic number
print_usage
print statement; does what it says on the tin
do_mac
???
mac_read_from_eeprom
dump eeprom to buffer
setup ethaddr envvars
setup serial# from eeprom ptsr
get_pcb_revision_from_eeprom
read the eeprom, and print the pcb revision
get_data_from_eeprom
direct memcpy for some data
K1-X
6x C files, multiple json, config files, 1x its file, 1x C header
Sourced from https://git.blizzard.systems/bianbu-mirror-repos/milkv-jupiter-uboot-2022.10 , which is a proxy of the BianbuOS U-Boot source repository.
No open documentation for the X60 core IP, so building everything in edk2 need to be based off publicly available information.
For any instance in this section, the following C-type define block is useful:
#define BIT(nr) (1UL <<(nr))
Correlated Files from VF2
spl.c
Functions
timer_init
Defines register GEN_CNT
(0xd5001000
), of size 0x20
, read from the address, write back to the register after modifying
__get_boot_storage
Store STORAGE_API_P_ADDR
(0xc0838498
), also get the address stored there.
If the address is the same as SDCARD_API_ENTRY
(0xffe0a548
), return BOOT_MODE_SD
,
otherwise, return the output of get_boot_pin_select
, defined in k1x.c
fix_boot_mode
If the value stored in the BOOT_DEV_FLAG_REG
(0xd4282d10
) is zero, call set_boot_mode(__get_boot_storage())
. set_boot_mode
is defined in k1x.c
, and __get_boot_storage
is defined above.
board_pinctrl_setup
SDCard Pin control setup.
MFPR_MMC1_BASE
(0xd401e1b8
) is the base address of the SD interface.
Sets all pins to MUX_MODE0
, no edge detection, all pins but CLK
to PULL_UP
(CLK
is PULL_DOWN
), and set PAD_3V_DS4
(Meaning unclear at time of writing)
Pin offset | pin name | Mux mode | edge-detect | pull-up/-down/float | PAD voltage and driver strength |
---|---|---|---|---|---|
0x00 |
MMC1_DATA3 |
0 |
None | Pull-up | PAD_3V_DS4 1 |
0x04 |
MMC1_DATA2 |
0 |
None | Pull-up | PAD_3V_DS4 1 |
0x08 |
MMC1_DATA1 |
0 |
None | Pull-up | PAD_3V_DS4 1 |
0x0c |
MMC1_DATA0 |
0 |
None | Pull-up | PAD_3V_DS4 1 |
0x10 |
MMC1_CMD |
0 |
None | Pull-up | PAD_3V_DS4 1 |
0x14 |
MMC1_CLK |
0 |
None | Pull-down | PAD_3V_DS4 1 |
adjust_cpu_freq
Parameter 1: cluster
(unknown meaning)
Parameter 2: freq
(Actrive frequency)
Read the value from ( K1X_APMU_BASE
(0xd4282800
) + a custom offset (0x38c
) + cluster * 4) into the variable val
This following bits are then cleared in val
: 0x0107
(Bits 1, 2, 3, and 13)
Switch statement based on frequency:
- 1600000Hz: set bits 1, 2, and 3 in
val
- 1228000Hz: set bit 3 in
val
- 819000Hz: set bit 1 in
val
- 614000Hz (default): set no values in
val
, setfreq
to 614000Hz
Write this value back to the originally read address. Read the bit back, set bit 12, write back, and wait until it is cleared on the other side (while loop, checking bit 12) return the frequency that was set
raise_cpu_frequency
Write 0x2dffff
to 0xd4051024
(This does....???)
Enable
CLK_1228M
Read from K1X_MPMU_BASE
(0xd4050000
) + 0x1024
, set bits 13,14,15,16, write back
Enable
PLL3(3200MHz)
Read from K1X_APB_SPARE_BASE
(0xd4090000
) + 0x012c
, set bit 31, write back.
Enable
PLL3_DIV2
Read from K1X_APB_SPARE_BASE
(0xd4090000
) + 0x0128
, set bit 1, write back.
Call cpu_get_current_dev
, save to cpu
. (Gets the current CPU; external driver/cpu/cpu-uclass.c
definition)
Read the frequency (uint32
) from the DeviceTree for cluster 0 (Not sure where this comes from). so if this fails, log it and assign the CPU frequency to 1228000Hz. Otherwise, set the CPU frequency to whatever the DT says
Read the frequency (uint32
) from the DeviceTree for cluster 1 (not sure where this comes from). so if this fails, log it and assign the CPU frequency to 614000Hz (log says 1228000 though). Otherwise, set the CPU frequency to whatever the DT says
load_board_config_from_efuse
This is enabled by the SPACEMIT_K1X_EFUSE
config variable.
Load the efuse driver, then read from the efuse into the array fuses
(2 bytes long).
If this read properly, and the first byte isn't zero:
- set
eeprom_i2c_index
to bits 0-3 of the first byte - set
eeprom_pin_group
to bits 4-5 of the first byte - set
pmic_type
to bits 0-3 of the second byte
load_chipid_from_efuse
This is enabled by the SPACEMIT_K1X_EFUSE
config variable.
Load the efuse driver, then read from the efuse into the array fuses
(32 bytes long).
Bits 191 to 251 is the chip ID, but that's larger than 1 byte, so we do the following:
- get bit 192-251 (
fuses[24]
, all bits) - left shift 1 bit, OR with bit 191 (
fuses[23]
, high bit)
load_default_board_config
Set eeprom_i2c_index
to the enviornment variable of the same name, or default back to K1_DEFAULT_EEPROM_I2C_INDEX
(2).
Set eeprom_pin_group
to the enviornment variable of the same name, or default back to K1_DEFAULT_EEPROM_PIN_GROUP
(0).
Set pmic_type
to the environment variable of the same name, or default to K1_DEFALT_PMIC_TYPE
[sic] (0).
load_board_config
Load defaults first, then load from efuse if available, then print to debuglog
read_boot_storage_emmc
Get the block device mmc:1
, dump the first partition into a buffer, and return it
read_boot_storage_sdcard
Get the block device mmc:0
, dump the first partition into a buffer, and return it
read_boot_storage_spinor
probe all MTD
devices, get the "private"
, dump the device into a buffer, and return it
read_training_info
Get the current boot storage (using get_boot_storage
from k1x.c
), get the training info, and save it to a buffer.
(iterate over possible boot storage modes, and use the appropriate read_boot_storage_*
function defined above, using address 0x10000
for EMMC or SD and 0x0
for NOR)
restore_ddr_training_info
load map system-memory address 0xC0800000
, and save it to an object. This object contains a trait "magic", along with a crc32
, chipid
, mac_addr
, version
, cs_num
, 2 reserved
arrays, and a parameter array
If booting from USB, or if the training info is the wrong size, or any of the information loaded was bad, force retraining by clearing all info and returning false, indicating failure.
flush and invalidate cache
update_ddr_training_info
load map system-memory address 0xC0800000
, and save it to an object. This object contains a trait "magic", along with a crc32
, chipid
, mac_addr
, version
, cs_num
, 2 reserved
arrays, and a parameter array
If the DDR still contains the magic training value, and the CRC is the same as we had before, we don't need to save it. Clear the magic bit and move on.
Otherwise, set all the values appropriately
update_ddr_config_info
Force update all values
spl_board_init_f
If SYS_I2C_LEGACY
is set in config, call i2c_init_board
, defined below
void i2c_init_board(void)
{
int i = 0;
mmio_write_32(0xd4051024, (*(unsigned int *)0xd4051024) | (1 << 6));
mmio_write_32(0xd4090104, (*(unsigned int *)0xd4090104) | (1 << 4));
mmio_write_32(0xd401e228, (*(unsigned int *)0xd401e228) | (1 << 1));
mmio_write_32(0xd401e22c, (*(unsigned int *)0xd401e22c) | (1 << 1));
/* init the clk & reset or pinctrl */
for (i = 0; i < sizeof(apbc_clk_reg) / sizeof(apbc_clk_reg[0]); ++i) {
mmio_write_32(apbc_clk_reg[i], (I2C_FUNCLK_33MHz << 4) | 0x4);
mmio_write_32(apbc_clk_reg[i], (I2C_FUNCLK_33MHz << 4) | 0x7);
mmio_write_32(apbc_clk_reg[i], (I2C_FUNCLK_33MHz << 4) | 0x3);
}
}
If SPACEMIT_POWER
is set in config, call board_pmic_init
; unclear how this is implemented at time of writing
call raise_cpu_frequency
call update_ddr_info
Get the UCLASS_RAM
device, and if it fails, log it. This means DRAM initialisation failed
call update_ddr_config_info
call timer_init
board_init_f
Call fix_boot_mode
, then board_pinctrl_setup
, then spl_early_init
. If the last fails, panic.
Call riscv_cpu_setup
, then preloader_console_init
, then spl_board_init_f
. If the last fails, panic.
board_fit_config_name_match
Enabled if CONFIG_SPL_LOAD_FIT
config variable is enabled
Set the buildin_name
to the previously-acquired product_name
, defaulting to k1-x_deb1
As long as the name is the same as the passed-in name, log "Boot from fit configuration", and return safely. Otherwise, fail
_spl_env_driver_lookup
Iterate over linked driver entries to find the location we're looking for. Lots of pointer shenanigans and API calls, not super important.
spl_load_env
Call get_boot_mode
. Return immediately if the boot mode is USB.
Set the environment location depending on the boot mode and the config values.
call spl_env_driver_lookup
, and if it doesn't fail, load it. If it can't load, fail back to default
get_mac_address
Call k1x_eeprom_init
. If this is successful, and the pointer passed in is real, and the TLV_CODE_MAC_BASE
2 loaded from EEPROM is successful, log the mac address and return safe, otherwise return fail.
get_product_name
Allocate memory space for the device name.
Call k1x_eeprom_init
. If this is successful, and the name was allocated properly, and the TLV_CODE_PRODUCT_NAME
loaded from EEPROM is successful, log the product name and return it. Otherwise, free the allocated memory and log that we're using the default product name.
update_ddr_info
Call k1x_eeprom_init
. Allocate and clear a chunk of memory for the DDR type from the EEPROM. Read TLV_CODE_DDR_TYPE
from the EEPROM, and save the ddr type.
Read TLV_CODE_DDR_CSNUM
from EEPROM, and if read successfully, save it.
Read TLV_CODE_DDR_DATARATE
from EEPROM, and if read successfully, save it.
spl_board_init
Call spl_load_env
, then get and save the product name using get_product_name
spl_get_load_buffer
Return a correctly cast pointer to the FIT address, according to the build-time config variable CONFIG_SPL_LOAD_FIT_ADDRESS
board_boot_order
Call get_boot_mode
, and set the value in spl_boot_lilst[0]
spl_boot_list[1]
is set as booting device from ram; that is, loading and running u-boot from RAM. No other values are assigned
k1x.c
Functions
set_boot_mode
write the boot mode enum to the BOOT_DEV_FLAG_REG
(0xd4282d10
)
get_boot_pin_select
Read from BOOT_PIN_SELECT
(0xd4282c20
), and check bits 9 and 10.
Bitmask | Boot mode |
---|---|
b00 |
BOOT_MODE_EMMC |
b10 |
BOOT_MODE_NOR |
b01 |
BOOT_MODE_NAND |
b11 |
BOOT_MODE_SD |
get_boot_mode
Get the boot mode value from BOOT_DEV_FLAG_REG
(0xd4282d10
)
Check against boot mode enum:
Hex value | boot mode |
---|---|
0x055a |
USB |
0x055b |
EMMC |
0x055c |
NAND |
0x055d |
NOR |
0x055e |
SD |
0x055f |
SHELL |
set_serialnumber_based_on_boot_mode
Get the serial number from the boot environment variable (serial#
)
Get the bootmode
If the bootmode isn't USB, and the environment variable is set, set the USB gadget download serial number
get_boot_storage
Call get_boot_mode
If the boot medium isn't SD card, call get_boot_pin_select
mmc_get_env_dev
Call get_boot_mode
If the boot mode is EMMC, return MMC_DEV_EMMC
(2), otherwise return MMC_DEV_SD
(0)
write_boot_storage_emmc
Get the EMMC block device
select the first partition, and dump the given buffer into the selected partition
write_boot_storage_sdcard
Get the SD block device
select the first partition, and dump the given buffer into the selected partition
write_boot_storage_spinor
Get the MTD
private devic, and dump the given buffer to the device
write_training_info
call get_boot_storage
Use the appropriate storage callback to write to the current boot storage
(Done using an array of struct with enum, address, and function callback pointer; iterate over array)
save_ddr_training_info
Get the info from the DDR_TRAINING_INFO_BUFF
(0xc0800000
), and if it is valid (magic bits = 0x54524444
, crc matches) pass the information to write_training_info
get_ddr_config_info
Get the info from the DDR_TRAINING_INFO_BUFF
(0xc0800000
), and if it is valid (magic bits = 0x54524444
, crc matches), set the value of ddr_cs_num
; if it isn't, set ddr_cs_num
to the default of 1
According to the comments and documentation, this seems to be DDR channel number
get_reboot_config
If the reboot_config
value is set, immediately return it.
Direct copy of commment:
K1 has non-reset register(BOOT_CIU_DEBUG_REG0) to save boot config before system reboot, but it will be clear when K1 power is down, then boot config will be save in P1.
Read from the aforementioned register (0xd4282f90
) into flag
If flag
is either BOOT_MODE_SHELL
(0x055f
) or BOOT_MODE_USB
(0x055a
), clear the BOOT_CIU_DEBUG_REG0
register, and set reboot_config
to flag
and return reboot_config
Otherwise, set reboot_config
to BOOT_MODE_BOOTSTRAP
(0x0560
).
Load the power management driver for the spacemit_pm8xx
, and if that fails log the error and return 0.
Read from the PMIC's non-reset register (address 0xab
), and log it.
If bit 0 of the config is set, set reboot_config
to BOOT_MODE_USB
, and clear the register.
If bit 1 of the config is set, set reboot_config
to BOOT_MODE_SHELL
, and clear the register.
Then return reboot_config
button_get_state_by_label
For each child of the passed in udev device, get the class platform data, and if the platform data label exists and is what we're looking for, read the boolean invert-state
as well as calling button_get_state
.
If invert-state
is true, invert the state.
Return the state of the button
If we can't find the button, return -ENOENT
(-2; Error: No entity)
get_fastboot_key_config
Get the /gpio_keys
object. If it's invalid, return -ENODEV
(-19; Error: no device)
Read the fastboot-key-combo
string, set the passed config's key_names
value. If the read call fails, return the fail value now.
Set the config's key_count
to the length of the read string.
Read fastboot-key-press-time
, set the config's press_time
value. If the read fails, return the read fail value, otherwise return 0
check_fastboot_keys
Call get_fastboot_key_config
; if it fails, log the failure and return false
log the config
Get the GPIO device. If this fails, log the failure and return false
Allocate memory for the key_states
call get_timer(0)
, and save the output.
While the updated timer is still less than the configured press time:
- iterate over the keys, get the button state. If the stateis in error or the button is not set to on, break out of this iteration loop now, and clear
all_pressed
- If
all_pressed
is cleared, free the valuekey_states
, and returnfalse
now - delay for 10ms
If we get here, the button has been pressed and held for the requisite amount of time
Free the key_states
value, log that fastboot was detected, and return true
run_fastboot_command
Call get_boot_mode
If the boot mode is USB, if the reboot config from get_reboot_config
is USB, or (if it is enabled) check_fastboot_keys
returns true:
- set
stdout
environment variable to the value found instdout_flash
- Run the command
fastboot 0
- call
refresh_config_info
run_uboot_shell
call get_boot_mode
If the boot or reboot mode is SHELL
, return 0, else return 1
_load_env_from_blk
Iterate over partitions 1 thru 16.
If getting the partition info errors, then skip it.
If the name is the same as the BOOTFS_NAME
, (bootfs
), log that we've matched and stop iterating.
If the final value of the iterator is larger than 16, return now. We couldn't find the bootfs.
Set the environment variable bootfs_part
to a string of the partition number found earlier
Set the environment variable bootfs_devname
to the device name passed in
Call the U-Boot load command to load the environment text file, from the given device name, the found device number, and the partition number, into CONFIG_SPL_LOAD_FIT_ADDRESS
(0x11000000
).
The file name is defined as env_%s.txt
, where %s
is set to CONFIG_SYS_CONFIG_NAME
, which defaults to k1-x
.
If the command doesn't run successfully, return now.
Clear the command buffer, then set the next command buffer to be env import -t 0x%x
, where %x
is CONFIG_SPL_LOAD_FIT_ADDRESS
mentioned previously.
If the command runs successfully, log such.
parse_mtdparts_and_find_bootfs
Get the value from the mtdparts
environment variable. If this value isn't set, log and return NULL
Find the start of the last partition (search for the last instance of the (
character), and if it exists, find the end of the partition (search for the first instance of the )
character.
If the end exists, and the size of the partition is the right size, copy the partition into the character buffer
Run ubi part found_partition
, and if it runs successfully, run ubi check bootfs
. If this is successful, return the found partition.
If we get here, we couldn't find a partition, return NULL
.
import_env_from_bootfs
Call get_boot_mode
If built to support ENV_IS_IN_NFS
, if the boot mode isn't USB, and the bootfs doesn't exist:
- if built to support networking, initialise the ethernet controller via
eth_initialise
- call
load_env_from_nfs
, and if successful, return now
Large switch block based on acquired boot mode; build-time config variable ENV_IS_IN_X
toggles blocks
BOOT_MODE_NAND
and ENV_IS_IN_MTD
Set the bootfs_name
to be bootfs
. If this setting fails, log and return.
call parse_mtdparts_and_find_bootfs
. If this fails, log and return.
Run the U-Boot command ubifsmount ubi0:bootfs
. If this command fails, log and return.
Allocate space for the environment text file, then run ubifsload CONFIG_SPL_LOAD_FIT_ADDRSSS env_k1-x.txt
Clear the command buffer, then run env import -t CONFIG_SPL_LOAD_FIT_ADDRESS
BOOT_MODE_NOR
call get_available_boot_blk_dev
; if this fails log and return
call blk_get_dev
, and save this value. If it is valid, call _load_env_from_blk
(BOOT_MODE_EMMC
or BOOT_MODE_SD
) and CONFIG_MMC
call mmc_get_env_dev
, and pass this output into find_mmc_device
.
If this fails, log and return.
Otherwise, call mmc_init
. If this fails, return.
Call _load_env_from_blk
to load from the mmc
run_cardfirmware_flash_command
Only actually does anything if CONFIG_MMC
is enabled
call find_mmc_device
. If this is fails, return now
Call mmc_init
. If this fails, return now
Iterate over partitions, get the info from the partition. If it fails, keep searching. If it's a match, exit iteration.
If we couldn't find it at all, return.
Run the uboot command fatsize mmc MMC_DEV_SD:partition_number FLASH_CONFIG_FILE_NAME
(FLASH_CONFIG_FILE_NAME
defaults to partition_universal.json
)
If this is successful, run flash_image mmc
setenv_boot_mode
If ENV_IS_IN_NFS
is set:
get the environment variable boot_override
, and if it exists, set the boot_device
envvar to the value from boot_override
, and clear the envvar boot_override
. Return now.
call get_boot_mode
.
In NAND
boot mode
set the envvar boot_device
to nand
In NOR
boot mode
call get_available_boot_blk_dev
, and if this fails, return now.
Set envvar boot_device
to nor
, and boot_devnum
to a string of the found block device index
In EMMC
boot mode
set envvar boot_device
to mmc
, and boot_devnum
to a string of MMC_DEV_EMMC
(2)
In SD
boot mode
set envvar boot_device
to mmc
, and boot_devnum
to a string of MMC_DEV_SD
(0)
In USB
boot mode
set envvar bootcmd
to CONFIG_BOOTCOMMAND
(bootm 0x11000000
)
Fallback
clear envvar boot_device
read_from_eeprom
call read_tlvinfo_tlv_eeprom
; if this fails, log and return
Guess-and-check offset until all the things line up (essentially)
find_tlv_in_buffer
Similar guess-and-check methodology from read_from_eeprom
mac_read_from_buffer
Call find_tlv_in_buffer
, looking for TLV_CODE_MAC_SIZE
(0x2a
). If we found it, extract from output using..... this:
maccount = (mac_size_tlv->value[0] << 8) | mac_size_tlv->value[1];
Call find_tlv_in_buffer
, looking for TLV_CODE_MAC_BASE
(0x24
). If we found it, copy the found value into the array mac_base
.
Otherwise, clear the array.
iterate over all mac options. if it passes is_valid_ethaddr
, format the string properly, format the enetvar
envvar depending on which mac address we're using, and if that envvar has not been set, set it to our valid ethaddr
Increment MAC to the next value for the next port, as long as it's valid
set_env_ethaddr
If we're given existing eeprom data, parse that, and if that fails, log and return. Otherwise, try to parse from EEPROM, and if that fails, log and return.
call eth_env_get_enetaddr
on both ethaddr
and eth1addr
, and if they're both valid, log the first mac address and return.
If we get here, we couldn't load a MAC, so let's generate one instead.
Call net_random_ethaddr
, and set mac_addr[0:2]
to 0xfe
.
Then, copy this value to the second mac address, and increment by 1
Write our found/generated mac addresses to the envvars
run tlv_eeprom
save the mac address to eeprom
, using tlv_eeprom set 0x24 mac_address
run command tlv_eeprom set 0x2a 2
run command tlv_eeprom write
set_dev_serial_no
If we're given eeprom data, search the buffer for TLV_CODE_SERIAL_NUMBER
(0x23
)
Otherwise, search eeprom
If the value exists, and has a reasonable length, set the envvar serial#
, and free temp var
refresh_config_info
For each line in this chart: Follow the same behaviour defined for set_dev_serial_number
Code | Encoding | Name | datatype |
---|---|---|---|
TLV_CODE_PRODUCT_NAME |
0x21 |
product_name |
string |
TLV_CODE_PART_NUMBER |
0x22 |
part# |
string |
TLV_CODE_SERIAL_NUMBER |
0x23 |
serial# |
string |
TLV_CODE_MANUF_DATE |
0x25 |
manufacture_date |
string |
TLV_CODE_MANUF_NAME |
0x2b |
manufacturer |
string |
TLV_CODE_WIFI_MAC_ADDR |
0x60 |
wifi_addr |
string |
TLV_CODE_BLUETOOTH_ADDR |
0x61 |
bt_addr |
string |
TLV_CODE_DEVICE_VERSION |
0x26 |
device_version |
numeric |
TLV_CODE_SDK_VERSION |
0x40 |
sdk_version |
numeric |
board_init
If build config CONFIG_DM_REGULATOR_SPM8XX
, call regulators_enable_boot_on
, and if this fails, log
If build config CONFIG_SPACEMIT_SHUTDOWN_CHARGE
, if the boot mode is usb
, call uclass_get_device_by_driver
, using the shutdown_charge
driver.
board_late_init
If the envvar product_name
isn't set, set it to DEFAULT_PRODUCT_NAME
(k1-x_deb1
)
allocate 2048 bytes, aligned to 32 bytes. If this fails, log and return -ENOMEM
(-12
, Error: No Memory)
Call read_tlvinfo_tlv_eeprom
, and if it fails, log
If the generated tlv_hdr
is not null, first_entry
isn't null, and the header passes is_valid_tlvinfo_header
, call each of the following with the buffered eeprom data:
set_env_ethaddr
set_dev_serial_no
refresh_config_info
Otherwise, call each of the above functions with an input buffer ofNULL
call set_serialnumber_based_on_boot_mode
If CONFIG_VIDEO_SPACEMIT
, call uclass_probe_all
for UCLASS_VIDEO
(118), and for UCLASS_DISPLAY
(34), and if either fails, log
If CONFIG_BUTTON
, call uclass_probe_all
for UCLASS_BUTTON
(29), and log pass/fail
call run_fastboot_command
call run_cardfirmware_flash_command
call run_uboot_shell
, and if this fails, log reboot into uboot shell
and return 0
call import_env_from_bootfs
, then if no video is connected, set envvar stdout
to serial
.
call setenv_boot_mode
set the envvar ram_size
correctly (mem=%dMB
)
get the node of the chosen boot path (/chosen
). If this fails, log and return 0.
read kernel start address from the device tree; if fail, log and return 0
set the envvar kernel_start
based on the read kernel start address, then return 0.
board_fdt_blob_setup
If the config is set correctly, check the FDT header before returning the firmware address. Otherwise, return (ulong *)&_end
(unclear what that means)
env_get_location
If priority is higher than 1, return ENVL_UNKNOWN
(0)
Get the current boot mode, and return the correct ENVL_X
, depending on CONFIG_ENV_IS_IN_X
. Default state is ENVL_UNKNOWN
, unless CONFIG_ENV_IS_NOWHERE
in which case default is ENVL_NOWHERE
.
misc_init_r
required function, no behaviour
dram_init
call get_ddr_config_info
call ddr_get_density
, multiply by SZ_1MB
(0x00100000
), save as dram_size
set ram_base
to CONFIG_SYS_SDRAM_BASE
(0x0
)
set ram_size
to dram_size
dram_init_banksize
call ddr_get_density
, multiply by SZ_1MB
(0x00100000
), save as dram_size
set bi_dram[0].start
= CONFIG_SYS_SDRAM_BASE
(0x0
)
If dram_size
> 2 gigs (encoded as 0x80000000
), set bi_dram[0].size
to 2 gigs, if CONFIG_NR_DRAM_BANKS
is more than 1, set bi_dram[1].start
to 0x100000000
, and bi_dram[1].size
to dram_size
- 2g
if dram_size
<= 2 gigs, directly assign bi_dram[0].size
as dram_size
return 0
board_get_usable_ram_top
call ddr_get_density
, multiply by SZ_1MB
(0x00100000
), save as dram_size
If dram_size
is more than 2 gigs, return 0x80000000
due to 32-bit DMA limit. otherwise, just return dram_size
board_fit_config_name_match
only exists if CONFIG_SPL_BUILD
is undefined
get the envvar product_name
, convert it to consistent formatting (k1-x_deb1
)
If the product name exists, and it fitts the passed name, log and return 0, else return 1
get_dro_from_efuse
Get the device that is compatible with the spacemit_k1x_efuse
, and if it fails, return SVT_DRO_DEFAULT_VALUE
(120)
Read from efuse, the info we want is in bank7, bits 173-181, and if that value isn't zero, return it. If it is zero, return the default (120)
get_chipinfo_from_efuse
Get the device that is compatible with the spacemit_k1x_efuse
, and if it fails, return ENODEV
(19; Error: No Device)
Read from efuse, the product ID is in bank 7, bits 182-190
Read from efuse, the waver ID is in bank 7, bits 139-154
ft_board_cpu_fixup
call fdt_path_offset
to get the root node of the devicetree. If this fails, log and return -EINVAL
(22; Error Invalid argument)
call get_chipinfo_from_efuse
, and convert the product ID and wafer ID to big-endian
call fdt_setprop
to set the product and wafer ids in the devicetree
get the cpu
node from the devicetree
get the dro
(?) value from efuse, convert to big-endian, and save to the devicetree; if fail, return failcode
return 0
ft_board_info_fixup
get the devicetree root node; if fail log and return -EINVAL
(22; Error invalid argument)
get the envvar part#
, and save it to the devicetree
ft_board_mac_addr_fixup
get the devicetree soc node.
get the envvar for both macs, and save to devicetree
ft_board_setup
If FDT_FIXUP_PARTITIONS
is enabled, and the boot mode is NOR
, call fdt_fixup_mtdparts
If FDT_SIMPLEFB
is enabled, call fdtdec_add_reserved_memory
to reserve the framebuffer memory
call each function in order
ft_board_cpu_fixup
ft_board_info_fixup
ft_board_mac_addr_fixup
return 0
has_bootarg
If all input parameters don't exist, return false.
Iterate through all parameters, skipping spaces, and check if the parameter is valid. If it is, return true.
If we never returned, then we have no valid bootargs, return false
board_fdt_chosen_bootargs
get the envvar fdt_addr
, and if it doesn't exist, return with the value in envvar bootargs
check the header of fdt
, and if it fails, log and return with the value in envvar bootargs
get the /chosen
object from the devicetree, get the property bootargs
, and save to dts_args
Log both env
and dts
bootargs.
If the dts
bootargs don't exist, immediately return with bootargs
string manip to merge both bootargs
envvar and dts_args
, then return the merged string
k1x-i2c-eeprom.c
Functions:
init_tlv_data
Read from i2c
check if the header is correct, and the rest of the size is still valid.
Read the rest of the info into the buffer
spacemit_eeprom_read
mostly move data around after data checking; not clear but it's late
i2c_set_pinctrl
wrapper for pointer shenanigans; sets value
i2c_get_pinctrl
wrapper for pointer shenanigans; sets value
k1x_eeprom_init
struct eeprom_config {
uint8_t bus;
uint16_t addr;
uint8_t pin_function;
uint32_t scl_pin_reg;
uint32_t sda_pin_reg;
};
const struct eeprom_config eeprom_info[] = {
// eeprom @deb1 & deb2: I2C2, pin group(GPIO_84, GPIO_85)
{2, 0x50, MUX_MODE4, 0xd401e154, 0xd401e158},
// eeprom @evb: I2C6, pin group(GPIO_118, GPIO_119)
{6, 0x50, MUX_MODE2, 0xd401e228, 0xd401e22c},
};
Try both eeprom options for the following:
Set the pin functions for SCL and SDA. If it fails, unset and try next iteration.
Call init_tlv_data
, return saddr
_read_from_i2c
Read from i2c. I don't fully get it, but it's a C implementation of i2c interaction
_write_to_i2c
write from i2c, see comments above
clear_eeprom
create memory block of given size, write to i2c