| 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)); |