@@ -48,10 +48,9 @@ extern void *kernel_addr, *update_addr, *dts_addr;
4848
4949#define NAND_MASK_ALE (1 << 21)
5050#define NAND_MASK_CLE (1 << 22)
51- #define NAND_CMD (*((volatile uint8_t *)(NAND_BASE | NAND_MASK_CLE)))
51+ #define NAND_CMD (*((volatile uint8_t *)(NAND_BASE | NAND_MASK_CLE)))
5252#define NAND_ADDR (*((volatile uint8_t *)(NAND_BASE | NAND_MASK_ALE)))
5353#define NAND_DATA (*((volatile uint8_t *)(NAND_BASE)))
54- #define NAND_DATAW (*((volatile uint32_t *)(NAND_BASE)))
5554
5655/* Command set */
5756#define NAND_CMD_STATUS 0x70
@@ -141,6 +140,80 @@ extern void *kernel_addr, *update_addr, *dts_addr;
141140#define MAX_ECC_BYTES 8
142141
143142
143+ /* Manual division operation */
144+ int division (uint32_t dividend ,
145+ uint32_t divisor ,
146+ uint32_t * quotient ,
147+ uint32_t * remainder )
148+ {
149+ uint32_t shift ;
150+ uint32_t divisor_shift ;
151+ uint32_t factor = 0 ;
152+ unsigned char end_flag = 0 ;
153+
154+ if (!divisor )
155+ return 0xffffffff ;
156+
157+ if (dividend < divisor ) {
158+ * quotient = 0 ;
159+ * remainder = dividend ;
160+ return 0 ;
161+ }
162+
163+ while (dividend >= divisor ) {
164+ for (shift = 0 , divisor_shift = divisor ;
165+ dividend >= divisor_shift ;
166+ divisor_shift <<= 1 , shift ++ ) {
167+ if (dividend - divisor_shift < divisor_shift ) {
168+ factor += 1 << shift ;
169+ dividend -= divisor_shift ;
170+ end_flag = 1 ;
171+ break ;
172+ }
173+ }
174+
175+ if (end_flag )
176+ continue ;
177+
178+ factor += 1 << (shift - 1 );
179+ dividend -= divisor_shift >> 1 ;
180+ }
181+
182+ if (quotient )
183+ * quotient = factor ;
184+
185+ if (remainder )
186+ * remainder = dividend ;
187+
188+ return 0 ;
189+ }
190+
191+ uint32_t div (uint32_t dividend , uint32_t divisor )
192+ {
193+ uint32_t quotient = 0 ;
194+ uint32_t remainder = 0 ;
195+ int ret ;
196+
197+ ret = division (dividend , divisor , & quotient , & remainder );
198+ if (ret )
199+ return 0xffffffff ;
200+
201+ return quotient ;
202+ }
203+
204+ uint32_t mod (uint32_t dividend , uint32_t divisor )
205+ {
206+ uint32_t quotient = 0 ;
207+ uint32_t remainder = 0 ;
208+ int ret ;
209+
210+ ret = division (dividend , divisor , & quotient , & remainder );
211+ if (ret )
212+ return 0xffffffff ;
213+
214+ return remainder ;
215+ }
216+
144217/* Static variables to hold nand info */
145218static uint8_t nand_manif_id ;
146219static uint8_t nand_dev_id ;
@@ -245,7 +318,7 @@ static void nand_read_info(void)
245318 nand_flash .bad_block_pos = (* (uint16_t * )(onfi_data + PARAMS_POS_FEATURES )) & 1 ;
246319 nand_flash .ext_page_len = * (uint16_t * )(onfi_data + PARAMS_POS_EXT_PARAM_PAGE_LEN );
247320 nand_flash .parameter_page = * (uint16_t * )(onfi_data + PARAMS_POS_PARAMETER_PAGE );
248- nand_flash .pages_per_block = nand_flash .block_size / nand_flash .page_size ;
321+ nand_flash .pages_per_block = div ( nand_flash .block_size , nand_flash .page_size ) ;
249322 nand_flash .pages_per_device = nand_flash .pages_per_block * nand_flash .block_count ;
250323 nand_flash .oob_size = * (uint16_t * )(onfi_data + PARAMS_POS_OOBSIZE );
251324 nand_flash .revision = * (uint16_t * )(onfi_data + PARAMS_POS_REVISION );
@@ -342,14 +415,14 @@ static int nand_check_bad_block(uint32_t block)
342415}
343416
344417
345- static uint8_t buffer_page [NAND_FLASH_PAGE_SIZE ];
346418
347419int ext_flash_read (uintptr_t address , uint8_t * data , int len )
348420{
349- uint32_t block = address / nand_flash .block_size ; /* The block where the address falls in */
350- uint32_t page = address / nand_flash .page_size ; /* The page where the address falls in */
351- uint32_t start_page_in_block = page % nand_flash .pages_per_block ; /* The start page within this block */
352- uint32_t in_block_offset = address % nand_flash .block_size ; /* The offset of the address within the block */
421+ uint8_t buffer_page [NAND_FLASH_PAGE_SIZE ];
422+ uint32_t block = div (address , nand_flash .block_size ); /* The block where the address falls in */
423+ uint32_t page = div (address , nand_flash .page_size ); /* The page where the address falls in */
424+ uint32_t start_page_in_block = mod (page , nand_flash .pages_per_block ); /* The start page within this block */
425+ uint32_t in_block_offset = mod (address , nand_flash .block_size ); /* The offset of the address within the block */
353426 uint32_t remaining = nand_flash .block_size - in_block_offset ; /* How many bytes remaining to read in the first block */
354427 uint32_t len_to_read = len ;
355428 uint8_t * buffer = data ;
@@ -378,7 +451,7 @@ int ext_flash_read(uintptr_t address, uint8_t *data, int len)
378451 } while (ret < 0 );
379452
380453 /* Amount of pages to be read from this block */
381- pages_to_read = ( sz + nand_flash .page_size - 1 ) / nand_flash .page_size ;
454+ pages_to_read = div (( sz + nand_flash .page_size - 1 ), nand_flash .page_size ) ;
382455
383456 if (pages_to_read * nand_flash .page_size > remaining )
384457 pages_to_read -- ;
@@ -397,7 +470,8 @@ int ext_flash_read(uintptr_t address, uint8_t *data, int len)
397470 if (copy ) {
398471 uint32_t * dst = (uint32_t * )data ;
399472 uint32_t * src = (uint32_t * )buffer_page ;
400- for (i = 0 ; i < (len / sizeof (uint32_t )); i ++ ) {
473+ uint32_t tot_len = (uint32_t )len ;
474+ for (i = 0 ; i < (tot_len >> 2 ); i ++ ) {
401475 dst [i ] = src [i ];
402476 }
403477 }
0 commit comments