mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-13 06:42:56 +00:00
142 lines
4.1 KiB
Text
142 lines
4.1 KiB
Text
|
Lightweight UBI and UBI fastmap support
|
||
|
|
||
|
# Copyright (C) Thomas Gleixner <tglx@linutronix.de>
|
||
|
#
|
||
|
# SPDX-License-Identifier: GPL 2.0+ BSD-3-Clause
|
||
|
|
||
|
Scans the UBI information and loads the requested static volumes into
|
||
|
memory.
|
||
|
|
||
|
Configuration Options:
|
||
|
|
||
|
CONFIG_SPL_UBI
|
||
|
Enables the SPL UBI support
|
||
|
|
||
|
CONFIG_SPL_UBI_MAX_VOL_LEBS
|
||
|
The maximum number of logical eraseblocks which a static volume
|
||
|
to load can contain. Used for sizing the scan data structure
|
||
|
|
||
|
CONFIG_SPL_UBI_MAX_PEB_SIZE
|
||
|
The maximum physical erase block size. Either a compile time
|
||
|
constant or runtime detection. Used for sizing the scan data
|
||
|
structure
|
||
|
|
||
|
CONFIG_SPL_UBI_MAX_PEBS
|
||
|
The maximum physical erase block count. Either a compile time
|
||
|
constant or runtime detection. Used for sizing the scan data
|
||
|
structure
|
||
|
|
||
|
CONFIG_SPL_UBI_VOL_IDS
|
||
|
The maximum volume ids which can be loaded. Used for sizing the
|
||
|
scan data structure.
|
||
|
|
||
|
Usage notes:
|
||
|
|
||
|
In the board config file define for example:
|
||
|
|
||
|
#define CONFIG_SPL_UBI
|
||
|
#define CONFIG_SPL_UBI_MAX_VOL_LEBS 256
|
||
|
#define CONFIG_SPL_UBI_MAX_PEB_SIZE (256*1024)
|
||
|
#define CONFIG_SPL_UBI_MAX_PEBS 4096
|
||
|
#define CONFIG_SPL_UBI_VOL_IDS 8
|
||
|
|
||
|
The size requirement is roughly as follows:
|
||
|
|
||
|
2k for the basic data structure
|
||
|
+ CONFIG_SPL_UBI_VOL_IDS * CONFIG_SPL_UBI_MAX_VOL_LEBS * 8
|
||
|
+ CONFIG_SPL_UBI_MAX_PEBS * 64
|
||
|
+ CONFIG_SPL_UBI_MAX_PEB_SIZE * UBI_FM_MAX_BLOCKS
|
||
|
|
||
|
The last one is big, but I really don't care in that stage. Real world
|
||
|
implementations only use the first couple of blocks, but the code
|
||
|
handles up to UBI_FM_MAX_BLOCKS.
|
||
|
|
||
|
Given the above configuration example the requirement is about 5M
|
||
|
which is usually not a problem to reserve in the RAM along with the
|
||
|
other areas like the kernel/dts load address.
|
||
|
|
||
|
So something like this will do the trick:
|
||
|
|
||
|
#define SPL_FINFO_ADDR 0x80800000
|
||
|
#define SPL_DTB_LOAD_ADDR 0x81800000
|
||
|
#define SPL_KERNEL_LOAD_ADDR 0x82000000
|
||
|
|
||
|
In the board file, implement the following:
|
||
|
|
||
|
static struct ubispl_load myvolumes[] = {
|
||
|
{
|
||
|
.vol_id = 0, /* kernel volume */
|
||
|
.load_addr = (void *)SPL_KERNEL_LOAD_ADDR,
|
||
|
},
|
||
|
{
|
||
|
.vol_id = 1, /* DT blob */
|
||
|
.load_addr = (void *)SPL_DTB_LOAD_ADDR,
|
||
|
}
|
||
|
};
|
||
|
|
||
|
int spl_start_uboot(void)
|
||
|
{
|
||
|
struct ubispl_info info;
|
||
|
|
||
|
info.ubi = (struct ubi_scan_info *) SPL_FINFO_ADDR;
|
||
|
info.fastmap = 1;
|
||
|
info.read = nand_spl_read_flash;
|
||
|
|
||
|
#if COMPILE_TIME_DEFINED
|
||
|
/*
|
||
|
* MY_NAND_NR_SPL_PEBS is the number of physical erase blocks
|
||
|
* in the FLASH which are reserved for the SPL. Think about
|
||
|
* mtd partitions:
|
||
|
*
|
||
|
* part_spl { .start = 0, .end = 4 }
|
||
|
* part_ubi { .start = 4, .end = NR_PEBS }
|
||
|
*/
|
||
|
info.peb_offset = MY_NAND_NR_SPL_PEBS;
|
||
|
info.peb_size = CONFIG_SYS_NAND_BLOCK_SIZE;
|
||
|
info.vid_offset = MY_NAND_UBI_VID_OFFS;
|
||
|
info.leb_start = MY_NAND_UBI_DATA_OFFS;
|
||
|
info.peb_count = MY_NAND_UBI_NUM_PEBS;
|
||
|
#else
|
||
|
get_flash_info(&flash_info);
|
||
|
info.peb_offset = MY_NAND_NR_SPL_PEBS;
|
||
|
info.peb_size = flash_info.peb_size;
|
||
|
|
||
|
/*
|
||
|
* The VID and Data offset depend on the capability of the
|
||
|
* FLASH chip to do subpage writes.
|
||
|
*
|
||
|
* If the flash chip supports subpage writes, then the VID
|
||
|
* header starts at the second subpage. So for 2k pages size
|
||
|
* with 4 subpages the VID offset is 512. The DATA offset is 2k.
|
||
|
*
|
||
|
* If the flash chip does not support subpage writes then the
|
||
|
* VID offset is FLASH_PAGE_SIZE and the DATA offset
|
||
|
* 2 * FLASH_PAGE_SIZE
|
||
|
*/
|
||
|
info.vid_offset = flash_info.vid_offset;
|
||
|
info.leb_start = flash_info.data_offset;
|
||
|
|
||
|
/*
|
||
|
* The flash reports the total number of erase blocks, so
|
||
|
* we need to subtract the number of blocks which are reserved
|
||
|
* for the SPL itself and not managed by UBI.
|
||
|
*/
|
||
|
info.peb_count = flash_info.peb_count - MY_NAND_NR_SPL_PEBS;
|
||
|
#endif
|
||
|
|
||
|
ret = ubispl_load_volumes(&info, myvolumes, ARRAY_SIZE(myvolumes);
|
||
|
|
||
|
....
|
||
|
|
||
|
}
|
||
|
|
||
|
Note: you can load any payload that way. You can even load u-boot from
|
||
|
UBI, so the only non UBI managed FLASH area is the one which is
|
||
|
reserved for the SPL itself and read from the SoC ROM.
|
||
|
|
||
|
And you can do fallback scenarios:
|
||
|
|
||
|
if (ubispl_load_volumes(&info, volumes0, ARRAY_SIZE(volumes0)))
|
||
|
if (ubispl_load_volumes(&info, volumes1, ARRAY_SIZE(volumes1)))
|
||
|
ubispl_load_volumes(&info, vol_uboot, ARRAY_SIZE(vol_uboot));
|