~funderscore blog cgit wiki get in touch
aboutsummaryrefslogtreecommitdiff
blob: ff008bc3118a27572380f51ded443295e4a0ad4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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));