Skip to content

Commit 800ebf7

Browse files
richard-bootlinpanicking
authored andcommitted
tools: sunxi-spl-image-builder: support H6/H616 NAND boot
The H6/H616 boot ROM doesn't expect a SPL scrambled the same way as older SoCs. It doesn't use a specific seeds table, it expects a maximized ECC (BCH-80), a specific BBM (FF000301) and doesn't work if empty pages are skipped (it needs its specific BBM, even in the padding). So, add a --soc=h6 option to support H6/616 with: - more ECC strengths - specific BBM - default_scrambler_seeds[] with all values - no empty pages skip In Kconfig, select BCH-80 by default for SUNXI_SPL_ECC_STRENGTH to make BROM happy. And in scripts/Makefile.xpl, use --soc=h6 option when building for a SUN50I_GEN_H6 SoC. Tested on Whatsminer H616 board, booting from NAND. Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com> Co-developed-by: James Hilliard <james.hilliard1@gmail.com> Signed-off-by: James Hilliard <james.hilliard1@gmail.com> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com> Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
1 parent bd22b7e commit 800ebf7

3 files changed

Lines changed: 75 additions & 19 deletions

File tree

drivers/mtd/nand/raw/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,7 @@ if NAND_SUNXI
489489

490490
config NAND_SUNXI_SPL_ECC_STRENGTH
491491
int "Allwinner NAND SPL ECC Strength"
492+
default 80 if SUN50I_GEN_H6
492493
default 64
493494

494495
config NAND_SUNXI_SPL_ECC_SIZE

scripts/Makefile.xpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,7 @@ $(obj)/sunxi-spl.bin: $(obj)/$(SPL_BIN).bin FORCE
457457

458458
quiet_cmd_sunxi_spl_image_builder = SUNXI_SPL_IMAGE_BUILDER $@
459459
cmd_sunxi_spl_image_builder = $(objtree)/tools/sunxi-spl-image-builder \
460+
$(if $(CONFIG_SUN50I_GEN_H6),--soc=h6) \
460461
-c $(CONFIG_NAND_SUNXI_SPL_ECC_STRENGTH)/$(CONFIG_NAND_SUNXI_SPL_ECC_SIZE) \
461462
-p $(CONFIG_SYS_NAND_PAGE_SIZE) \
462463
-o $(CONFIG_SYS_NAND_OOBSIZE) \

tools/sunxi-spl-image-builder.c

Lines changed: 73 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/bch.h>
1212

1313
#include <getopt.h>
14+
#include <string.h>
1415
#include <version.h>
1516

1617
#define BCH_PRIMITIVE_POLY 0x5803
@@ -27,6 +28,7 @@ struct image_info {
2728
int eraseblock_size;
2829
int scramble;
2930
int boot0;
31+
int h6;
3032
off_t offset;
3133
const char *source;
3234
const char *dest;
@@ -84,18 +86,29 @@ static void scramble(const struct image_info *info,
8486
uint16_t state;
8587
int i;
8688

87-
/* Boot0 is always scrambled no matter the command line option. */
88-
if (info->boot0) {
89+
/*
90+
* Bail out earlier if the user didn't ask for scrambling.
91+
* But Boot0 is always scrambled no matter the command line option.
92+
*/
93+
if (!info->boot0 && !info->scramble)
94+
return;
95+
96+
/*
97+
* On H6, the BROM scrambler seed is no different than the default one
98+
*/
99+
if (info->boot0 && !info->h6) {
89100
state = brom_scrambler_seeds[0];
90101
} else {
91-
unsigned seedmod = info->eraseblock_size / info->page_size;
92-
93-
/* Bail out earlier if the user didn't ask for scrambling. */
94-
if (!info->scramble)
95-
return;
102+
unsigned int seedmod;
96103

97-
if (seedmod > ARRAY_SIZE(default_scrambler_seeds))
104+
if (info->h6) {
105+
/* H6 boot0 uses all 128 seeds */
98106
seedmod = ARRAY_SIZE(default_scrambler_seeds);
107+
} else {
108+
seedmod = info->eraseblock_size / info->page_size;
109+
if (seedmod > ARRAY_SIZE(default_scrambler_seeds))
110+
seedmod = ARRAY_SIZE(default_scrambler_seeds);
111+
}
99112

100113
state = default_scrambler_seeds[page % seedmod];
101114
}
@@ -137,14 +150,19 @@ static int write_page(const struct image_info *info, uint8_t *buffer,
137150

138151
fwrite(buffer, info->page_size + info->oob_size, 1, dst);
139152

140-
for (i = 0; i < info->usable_page_size; i++) {
141-
if (buffer[i] != 0xff)
142-
break;
143-
}
153+
/*
154+
* H6 BROM doesn't support empty pages
155+
*/
156+
if (!info->h6) {
157+
for (i = 0; i < info->usable_page_size; i++) {
158+
if (buffer[i] != 0xff)
159+
break;
160+
}
144161

145-
/* We leave empty pages at 0xff. */
146-
if (i == info->usable_page_size)
147-
return 0;
162+
/* We leave empty pages at 0xff. */
163+
if (i == info->usable_page_size)
164+
return 0;
165+
}
148166

149167
/* Restore the source pointer to read it again. */
150168
fseek(src, -cnt, SEEK_CUR);
@@ -212,6 +230,14 @@ static int write_page(const struct image_info *info, uint8_t *buffer,
212230
}
213231

214232
memset(ecc, 0, eccbytes);
233+
234+
if (info->h6) {
235+
/* BBM taken from vendor code: FF 00 03 01 */
236+
buffer[info->ecc_step_size + 1] = 0;
237+
buffer[info->ecc_step_size + 2] = 3; // NAND_VERSION_0
238+
buffer[info->ecc_step_size + 3] = 1; // NAND_VERSION_1
239+
}
240+
215241
swap_bits(buffer, info->ecc_step_size + 4);
216242
encode_bch(bch, buffer, info->ecc_step_size + 4, ecc);
217243
swap_bits(buffer, info->ecc_step_size + 4);
@@ -303,6 +329,8 @@ static void display_help(int status)
303329
"-e <size> --eraseblock=<size> Erase block size\n"
304330
"-b --boot0 Build a boot0 image.\n"
305331
"-s --scramble Scramble data\n"
332+
"-t --soc=<soc> Build an image compatible with SoC type <soc>\n"
333+
" (possible values: a10, h6. Default: a10)\n"
306334
"-a <offset> --address=<offset> Where the image will be programmed.\n"
307335
"\n"
308336
"Notes:\n"
@@ -313,6 +341,9 @@ static void display_help(int status)
313341
" Valid ECC strengths: 16, 24, 28, 32, 40, 48, 56, 60 and 64\n"
314342
" Valid ECC step size: 512 and 1024\n"
315343
"\n"
344+
"On H6/H616, the only ECC step size supported is 1024, but more ECC\n"
345+
"strengths are supported: 44, 52, 68, 72, 76, 80\n"
346+
"\n"
316347
"If you are building a boot0 image, you'll have specify extra options.\n"
317348
"These options should be chosen based on the layouts described here:\n"
318349
" http://linux-sunxi.org/NAND#More_information_on_BROM_NAND\n"
@@ -342,7 +373,12 @@ static void display_help(int status)
342373

343374
static int check_image_info(struct image_info *info)
344375
{
345-
static int valid_ecc_strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
376+
static int ecc_strengths_a10[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
377+
static int ecc_strengths_h6[] = {
378+
16, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80
379+
};
380+
int *valid_ecc_strengths;
381+
size_t nstrengths;
346382
int eccbytes, eccsteps;
347383
unsigned i;
348384

@@ -367,12 +403,25 @@ static int check_image_info(struct image_info *info)
367403
return -EINVAL;
368404
}
369405

370-
for (i = 0; i < ARRAY_SIZE(valid_ecc_strengths); i++) {
406+
if (info->h6) {
407+
if (info->ecc_step_size != 1024) {
408+
fprintf(stderr,
409+
"H6 SoCs supports only 1024 bytes ECC step\n");
410+
return -EINVAL;
411+
}
412+
valid_ecc_strengths = ecc_strengths_h6;
413+
nstrengths = ARRAY_SIZE(ecc_strengths_h6);
414+
} else {
415+
valid_ecc_strengths = ecc_strengths_a10;
416+
nstrengths = ARRAY_SIZE(ecc_strengths_a10);
417+
}
418+
419+
for (i = 0; i < nstrengths; i++) {
371420
if (valid_ecc_strengths[i] == info->ecc_strength)
372421
break;
373422
}
374423

375-
if (i == ARRAY_SIZE(valid_ecc_strengths)) {
424+
if (i == nstrengths) {
376425
fprintf(stderr, "Invalid ECC strength argument: %d\n",
377426
info->ecc_strength);
378427
return -EINVAL;
@@ -416,10 +465,11 @@ int main(int argc, char **argv)
416465
{"boot0", no_argument, 0, 'b'},
417466
{"scramble", no_argument, 0, 's'},
418467
{"address", required_argument, 0, 'a'},
468+
{"soc", required_argument, 0, 't'},
419469
{0, 0, 0, 0},
420470
};
421471

422-
int c = getopt_long(argc, argv, "c:p:o:u:e:ba:sh",
472+
int c = getopt_long(argc, argv, "c:p:o:u:e:ba:sht:",
423473
long_options, &option_index);
424474
if (c == EOF)
425475
break;
@@ -454,6 +504,10 @@ int main(int argc, char **argv)
454504
case 'a':
455505
info.offset = strtoull(optarg, NULL, 0);
456506
break;
507+
case 't':
508+
if (strcmp("h6", optarg) == 0)
509+
info.h6 = 1;
510+
break;
457511
case '?':
458512
display_help(-1);
459513
break;

0 commit comments

Comments
 (0)