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
343374static 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