/******************************************************************************
* Ok335xS U-Boot 进度条原理跟踪
* 说明:
* 如果系统通过U-Boot进行烧写的话,同时显示屏上又没有显示,只能通过debug port
* 进行察看进度,这对于生产来说是不可行,有一个烧写进度条,是有必要的,于是跟踪
* 一下手里的U-Boot有有进度条的原理,看看是如何做到的。
*
* 2017-7-4 深圳 龙华樟坑村 曾剑锋
*****************************************************************************/
void board_init_r(gd_t *id, ulong dest_addr)
{
char *s;
bd_t *bd;
ulong malloc_start;
#if !defined(CONFIG_SYS_NO_FLASH)
ulong flash_size;
#endif
gd = id;
bd = gd->bd;
gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
monitor_flash_len = _end_ofs;
/* Enable caches */
enable_caches();
debug("monitor flash len: %08lX\n", monitor_flash_len);
board_init(); /* Setup chipselects */
#ifdef CONFIG_SERIAL_MULTI
serial_initialize();
#endif
debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
#ifdef CONFIG_LOGBUFFER
logbuff_init_ptrs();
#endif
#ifdef CONFIG_POST
post_output_backlog();
#endif
/* The Malloc area is immediately below the monitor copy in DRAM */
malloc_start = dest_addr - TOTAL_MALLOC_LEN;
mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN);
stdio_init(); /* get the devices list going. */
/**
* zengjf 2015-9-26 open pwm out pin
*/
//draw_rect(2,2,2+401,2+31,RGB(255,0,0));//draw rectangle
//__raw_writel((1<<12) | (1<<22), 0x44E07194);
#if !defined(CONFIG_SYS_NO_FLASH)
puts("Flash: ");
flash_size = flash_init();
if (flash_size > 0) {
# ifdef CONFIG_SYS_FLASH_CHECKSUM
print_size(flash_size, "");
/*
* Compute and print flash CRC if flashchecksum is set to 'y'
*
* NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
*/
s = getenv("flashchecksum");
if (s && (*s == 'y')) {
printf(" CRC: %08X", crc32(0,
(const unsigned char *) CONFIG_SYS_FLASH_BASE,
flash_size));
}
putc('\n');
# else /* !CONFIG_SYS_FLASH_CHECKSUM */
print_size(flash_size, "\n");
# endif /* CONFIG_SYS_FLASH_CHECKSUM */
} else {
puts(failed);
hang();
}
#endif
puts("zengjf :\n");
#if defined(CONFIG_CMD_NAND)
puts("NAND : ");
nand_init(); /* go init the NAND */ ---------------------+
#endif |
|
#if defined(CONFIG_CMD_ONENAND) |
onenand_init(); |
#endif |
|
#ifdef CONFIG_GENERIC_MMC |
puts("MMC: "); |
mmc_initialize(bd); |
#endif |
|
#ifdef CONFIG_HAS_DATAFLASH |
AT91F_DataflashInit(); |
dataflash_print_info(); |
#endif |
|
/* initialize environment */ |
env_relocate(); |
|
#if defined(CONFIG_CMD_PCI) || defined(CONFIG_PCI) |
arm_pci_init(); |
#endif |
|
/* IP Address */ |
gd->bd->bi_ip_addr = getenv_IPaddr("ipaddr"); |
|
|
jumptable_init(); |
|
#if defined(CONFIG_API) |
/* Initialize API */ |
api_init(); |
#endif |
|
console_init_r(); /* fully init console as a device */ |
|
#if defined(CONFIG_ARCH_MISC_INIT) |
/* miscellaneous arch dependent initialisations */ |
arch_misc_init(); |
#endif |
#if defined(CONFIG_MISC_INIT_R) |
/* miscellaneous platform dependent initialisations */ |
misc_init_r(); ----------------------------------*--------+
#endif | |
| |
/* set up exceptions */ | |
interrupt_init(); | |
/* enable exceptions */ | |
enable_interrupts(); | |
| |
/* Perform network card initialisation if necessary */ | |
#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96) | |
/* XXX: this needs to be moved to board init */ | |
if (getenv("ethaddr")) { | |
uchar enetaddr[6]; | |
eth_getenv_enetaddr("ethaddr", enetaddr); | |
smc_set_mac_addr(enetaddr); | |
} | |
#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */ | |
| |
/* Initialize from environment */ | |
s = getenv("loadaddr"); | |
if (s != NULL) | |
load_addr = simple_strtoul(s, NULL, 16); | |
#if defined(CONFIG_CMD_NET) | |
s = getenv("bootfile"); | |
if (s != NULL) | |
copy_filename(BootFile, s, sizeof(BootFile)); | |
#endif | |
| |
#ifdef BOARD_LATE_INIT | |
board_late_init(); | |
#endif | |
| |
#ifdef CONFIG_BITBANGMII | |
bb_miiphy_init(); | |
#endif | |
#if defined(CONFIG_CMD_NET) | |
#if defined(CONFIG_NET_MULTI) | |
puts("Net: "); | |
#endif | |
eth_initialize(gd->bd); | |
#if defined(CONFIG_RESET_PHY_R) | |
debug("Reset Ethernet PHY\n"); | |
reset_phy(); | |
#endif | |
#endif | |
| |
#ifdef CONFIG_POST | |
post_run(NULL, POST_RAM | post_bootmode_get(0)); | |
#endif | |
| |
#if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER) | |
/* | |
* Export available size of memory for Linux, | |
* taking into account the protected RAM at top of memory | |
*/ | |
{ | |
ulong pram; | |
uchar memsz[32]; | |
#ifdef CONFIG_PRAM | |
char *s; | |
| |
s = getenv("pram"); | |
if (s != NULL) | |
pram = simple_strtoul(s, NULL, 10); | |
else | |
pram = CONFIG_PRAM; | |
#else | |
pram = 0; | |
#endif | |
#ifdef CONFIG_LOGBUFFER | |
#ifndef CONFIG_ALT_LB_ADDR | |
/* Also take the logbuffer into account (pram is in kB) */ | |
pram += (LOGBUFF_LEN + LOGBUFF_OVERHEAD) / 1024; | |
#endif | |
#endif | |
sprintf((char *)memsz, "%ldk", (gd->ram_size / 1024) - pram); | |
setenv("mem", (char *)memsz); | |
} | |
#endif | |
| |
/* main_loop() can return to retry autoboot, if so just run it again. */| |
for (;;) { | |
main_loop(); | |
} | |
| |
/* NOTREACHED - no way out of command loop except booting */ | |
} | |
| |
void nand_init(void) <--------------------------------+ |
{ |
int i; |
unsigned int size = 0; |
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) { |
nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i]); --------+ |
size += nand_info[i].size / 1024; | |
if (nand_curr_device == -1) | |
nand_curr_device = i; | |
} | |
printf("%u MiB\n", size / 1024); | |
| |
#ifdef CONFIG_SYS_NAND_SELECT_DEVICE | |
/* | |
* Select the chip in the board/cpu specific driver | |
*/ | |
board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device);| |
#endif | |
} | |
| |
static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand, <------+ |
ulong base_addr) |
{ |
int maxchips = CONFIG_SYS_NAND_MAX_CHIPS; |
static int __attribute__((unused)) i = 0; |
|
if (maxchips < 1) |
maxchips = 1; |
mtd->priv = nand; |
|
nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr; |
if (board_nand_init(nand) == 0) { ----------------+ |
if (nand_scan(mtd, maxchips) == 0) { ----------------*-+ |
if (!mtd->name) | | |
mtd->name = (char *)default_nand_name; | | |
#ifdef CONFIG_NEEDS_MANUAL_RELOC | | |
else | | |
mtd->name += gd->reloc_off; | | |
#endif | | |
| | |
#ifdef CONFIG_MTD_DEVICE | | |
/* | | |
* Add MTD device so that we can reference it later | | |
* via the mtdcore infrastructure (e.g. ubi). | | |
*/ | | |
sprintf(dev_name[i], "nand%d", i); | | |
mtd->name = dev_name[i++]; | | |
add_mtd_device(mtd); | | |
#endif | | |
} else | | |
mtd->name = NULL; | | |
} else { | | |
mtd->name = NULL; | | |
mtd->size = 0; | | |
} | | |
| | |
} | | |
| | |
#ifdef CONFIG_NAND_DAVINCI | | |
int board_nand_init(struct nand_chip *nand) <--------------+ | |
{ | |
davinci_nand_init(nand); ---------------+ | |
| | |
return 0; | | |
} | | |
#endif | | |
| | |
void davinci_nand_init(struct nand_chip *nand) <--------------+ | |
{ | |
nand->chip_delay = 0; | |
#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT | |
nand->options |= NAND_USE_FLASH_BBT; | |
#endif | |
#ifdef CONFIG_SYS_NAND_HW_ECC | |
nand->ecc.mode = NAND_ECC_HW; | |
nand->ecc.size = 512; | |
nand->ecc.bytes = 3; | |
nand->ecc.calculate = nand_davinci_calculate_ecc; | |
nand->ecc.correct = nand_davinci_correct_data; | |
nand->ecc.hwctl = nand_davinci_enable_hwecc; | |
#else | |
nand->ecc.mode = NAND_ECC_SOFT; | |
#endif /* CONFIG_SYS_NAND_HW_ECC */ | |
#ifdef CONFIG_SYS_NAND_4BIT_HW_ECC_OOBFIRST | |
nand->ecc.mode = NAND_ECC_HW_OOB_FIRST; | |
nand->ecc.size = 512; | |
nand->ecc.bytes = 10; | |
nand->ecc.calculate = nand_davinci_4bit_calculate_ecc; | |
nand->ecc.correct = nand_davinci_4bit_correct_data; | |
nand->ecc.hwctl = nand_davinci_4bit_enable_hwecc; | |
nand->ecc.layout = &nand_davinci_4bit_layout_oobfirst; | |
#endif | |
/* Set address of hardware control function */ | |
nand->cmd_ctrl = nand_davinci_hwcontrol; | |
| |
nand->read_buf = nand_davinci_read_buf; | |
nand->write_buf = nand_davinci_write_buf; | |
| |
nand->dev_ready = nand_davinci_dev_ready; | |
| |
nand_flash_init(); | |
} | |
| |
int nand_scan(struct mtd_info *mtd, int maxchips) <-------------+ |
{ |
int ret; |
|
ret = nand_scan_ident(mtd, maxchips, NULL); --------------+ |
if (!ret) --------------*------------+ |
ret = nand_scan_tail(mtd); | | |
return ret; | | |
} | | |
| | |
int nand_scan_ident(struct mtd_info *mtd, int maxchips, <-------------+ | |
const struct nand_flash_dev *table) | |
{ | |
int i, busw, nand_maf_id, nand_dev_id; | |
struct nand_chip *chip = mtd->priv; | |
const struct nand_flash_dev *type; | |
| |
/* Get buswidth to select the correct functions */ | |
busw = chip->options & NAND_BUSWIDTH_16; | |
/* Set the default functions */ | |
nand_set_defaults(chip, busw); | |
| |
/* Read the flash type */ | |
type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id, &nand_dev_id, table);| |
| |
if (IS_ERR(type)) { | |
#ifndef CONFIG_SYS_NAND_QUIET_TEST | |
printk(KERN_WARNING "No NAND device found!!!\n"); | |
#endif | |
chip->select_chip(mtd, -1); | |
return PTR_ERR(type); | |
} | |
| |
/* Check for a chip array */ | |
for (i = 1; i < maxchips; i++) { | |
chip->select_chip(mtd, i); | |
/* See comment in nand_get_flash_type for reset */ | |
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); | |
/* Send the command for reading device ID */ | |
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); | |
/* Read manufacturer and device IDs */ | |
if (nand_maf_id != chip->read_byte(mtd) || | |
nand_dev_id != chip->read_byte(mtd)) | |
break; | |
} | |
#ifdef DEBUG | |
if (i > 1) | |
printk(KERN_INFO "%d NAND chips detected\n", i); | |
#endif | |
| |
/* Store the number of chips and calc total size for mtd */ | |
chip->numchips = i; | |
mtd->size = i * chip->chipsize; | |
| |
return 0; | |
} | |
| |
int nand_scan_tail(struct mtd_info *mtd) <---------------------------------+ |
{ |
uint32_t dev_width; |
int i; |
struct nand_chip *chip = mtd->priv; |
|
if (!(chip->options & NAND_OWN_BUFFERS)) |
chip->buffers = kmalloc(sizeof(*chip->buffers), GFP_KERNEL); |
if (!chip->buffers) |
return -ENOMEM; |
|
/* Set the internal oob buffer location, just after the page data */ |
chip->oob_poi = chip->buffers->databuf + mtd->writesize; |
|
dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1; |
|
/* |
* If no default placement scheme is given, select an appropriate one |
*/ |
if (!chip->ecc.layout) { |
switch (mtd->oobsize) { |
case 8: |
chip->ecc.layout = &nand_oob_8; |
break; |
case 16: |
chip->ecc.layout = &nand_oob_16; |
break; |
case 64: |
chip->ecc.layout = &nand_oob_64; |
break; |
case 128: |
chip->ecc.layout = &nand_oob_128; |
break; |
default: |
printk(KERN_WARNING "No oob scheme defined for " |
"oobsize %d\n", mtd->oobsize); |
} |
} |
|
if (!chip->write_page) |
chip->write_page = nand_write_page; |
|
/* |
* check ECC mode, default to software if 3byte/512byte hardware ECC is |
* selected and we have 256 byte pagesize fallback to software ECC |
*/ |
|
switch (chip->ecc.mode) { |
case NAND_ECC_HW_OOB_FIRST: |
/* Similar to NAND_ECC_HW, but a separate read_page handle */ |
if (!chip->ecc.calculate || !chip->ecc.correct || |
!chip->ecc.hwctl) { |
printk(KERN_WARNING "No ECC functions supplied, " |
"Hardware ECC not possible\n"); |
BUG(); |
} |
if (!chip->ecc.read_page) |
chip->ecc.read_page = nand_read_page_hwecc_oob_first; |
|
case NAND_ECC_HW: |
/* Use standard hwecc read page function ? */ |
if (!chip->ecc.read_page) |
chip->ecc.read_page = nand_read_page_hwecc; |
if (!chip->ecc.write_page) |
chip->ecc.write_page = nand_write_page_hwecc; |
if (!chip->ecc.read_page_raw) |
chip->ecc.read_page_raw = nand_read_page_raw; |
if (!chip->ecc.write_page_raw) |
chip->ecc.write_page_raw = nand_write_page_raw; |
if (!chip->ecc.read_oob) |
chip->ecc.read_oob = nand_read_oob_std; |
if (!chip->ecc.write_oob) |
chip->ecc.write_oob = nand_write_oob_std; |
|
case NAND_ECC_HW_SYNDROME: |
if ((!chip->ecc.calculate || !chip->ecc.correct || |
!chip->ecc.hwctl) && |
(!chip->ecc.read_page || |
chip->ecc.read_page == nand_read_page_hwecc || |
!chip->ecc.write_page || |
chip->ecc.write_page == nand_write_page_hwecc)) { |
printk(KERN_WARNING "No ECC functions supplied, " |
"Hardware ECC not possible\n"); |
BUG(); |
} |
/* Use standard syndrome read/write page function ? */ |
if (!chip->ecc.read_page) |
chip->ecc.read_page = nand_read_page_syndrome; |
if (!chip->ecc.write_page) |
chip->ecc.write_page = nand_write_page_syndrome; |
if (!chip->ecc.read_page_raw) |
chip->ecc.read_page_raw = nand_read_page_raw_syndrome; |
if (!chip->ecc.write_page_raw) |
chip->ecc.write_page_raw = nand_write_page_raw_syndrome; |
if (!chip->ecc.read_oob) |
chip->ecc.read_oob = nand_read_oob_syndrome; |
if (!chip->ecc.write_oob) |
chip->ecc.write_oob = nand_write_oob_syndrome; |
|
if (mtd->writesize >= chip->ecc.size) |
break; |
printk(KERN_WARNING "%d byte HW ECC not possible on " |
"%d byte page size, fallback to SW ECC\n", |
chip->ecc.size, mtd->writesize); |
chip->ecc.mode = NAND_ECC_SOFT; |
|
case NAND_ECC_SOFT: |
chip->ecc.calculate = nand_calculate_ecc; |
chip->ecc.correct = nand_correct_data; |
chip->ecc.read_page = nand_read_page_swecc; |
chip->ecc.read_subpage = nand_read_subpage; |
chip->ecc.write_page = nand_write_page_swecc; |
chip->ecc.read_page_raw = nand_read_page_raw; |
chip->ecc.write_page_raw = nand_write_page_raw; |
chip->ecc.read_oob = nand_read_oob_std; |
chip->ecc.write_oob = nand_write_oob_std; |
chip->ecc.size = 256; |
chip->ecc.bytes = 3; |
break; |
|
#if !defined(CONFIG_TI81XX) |
case NAND_ECC_4BIT_SOFT: |
/* Use standard hwecc read page function */ |
if (!chip->ecc.read_page) |
chip->ecc.read_page = nand_read_page_hwecc; |
if (!chip->ecc.write_page) |
chip->ecc.write_page = nand_write_page_hwecc; |
if (!chip->ecc.read_oob) |
chip->ecc.read_oob = nand_read_oob_std; |
if (!chip->ecc.write_oob) |
chip->ecc.write_oob = nand_write_oob_std; |
chip->ecc.size = 2048; |
chip->ecc.bytes = 28; |
chip->ecc.hwctl = omap_enable_hwecc_bch4; |
chip->ecc.calculate = omap_calculate_ecc_bch4; |
chip->ecc.correct = omap_correct_data_bch4; |
chip->ecc.layout = omap_get_ecc_layout_bch(dev_width, 4); |
omap_hwecc_init_bch(chip); |
break; |
|
case NAND_ECC_8BIT_SOFT: |
/* Use standard hwecc read page function */ |
if (!chip->ecc.read_page) |
chip->ecc.read_page = nand_read_page_hwecc; |
if (!chip->ecc.write_page) |
chip->ecc.write_page = nand_write_page_hwecc; |
if (!chip->ecc.read_oob) |
chip->ecc.read_oob = nand_read_oob_std; |
if (!chip->ecc.write_oob) |
chip->ecc.write_oob = nand_write_oob_std; |
chip->ecc.size = 2048; |
chip->ecc.bytes = 52; |
chip->ecc.hwctl = omap_enable_hwecc_bch8; |
chip->ecc.calculate = omap_calculate_ecc_bch8; |
chip->ecc.correct = omap_correct_data_bch8; |
chip->ecc.layout = omap_get_ecc_layout_bch(dev_width, 8); |
omap_hwecc_init_bch(chip); |
|
break; |
#endif |
|
case NAND_ECC_NONE: |
printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. " |
"This is not recommended !!\n"); |
chip->ecc.read_page = nand_read_page_raw; |
chip->ecc.write_page = nand_write_page_raw; |
chip->ecc.read_oob = nand_read_oob_std; |
chip->ecc.read_page_raw = nand_read_page_raw; |
chip->ecc.write_page_raw = nand_write_page_raw; |
chip->ecc.write_oob = nand_write_oob_std; |
chip->ecc.size = mtd->writesize; |
chip->ecc.bytes = 0; |
break; |
|
default: |
printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n", |
chip->ecc.mode); |
BUG(); |
} |
|
/* |
* The number of bytes available for a client to place data into |
* the out of band area |
*/ |
chip->ecc.layout->oobavail = 0; |
for (i = 0; chip->ecc.layout->oobfree[i].length |
&& i < ARRAY_SIZE(chip->ecc.layout->oobfree); i++) |
chip->ecc.layout->oobavail += |
chip->ecc.layout->oobfree[i].length; |
mtd->oobavail = chip->ecc.layout->oobavail; |
|
/* |
* Set the number of read / write steps for one page depending on ECC |
* mode |
*/ |
chip->ecc.steps = mtd->writesize / chip->ecc.size; |
if(chip->ecc.steps * chip->ecc.size != mtd->writesize) { |
printk(KERN_WARNING "Invalid ecc parameters\n"); |
BUG(); |
} |
chip->ecc.total = chip->ecc.steps * chip->ecc.bytes; |
|
/* |
* Allow subpage writes up to ecc.steps. Not possible for MLC |
* FLASH. |
*/ |
if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && |
!(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) { |
switch(chip->ecc.steps) { |
case 2: |
mtd->subpage_sft = 1; |
break; |
case 4: |
case 8: |
case 16: |
mtd->subpage_sft = 2; |
break; |
} |
} |
chip->subpagesize = mtd->writesize >> mtd->subpage_sft; |
|
/* Initialize state */ |
chip->state = FL_READY; |
|
/* De-select the device */ |
chip->select_chip(mtd, -1); |
|
/* Invalidate the pagebuffer reference */ |
chip->pagebuf = -1; |
|
/* Fill in remaining MTD driver data */ |
mtd->type = MTD_NANDFLASH; |
mtd->flags = MTD_CAP_NANDFLASH; |
mtd->erase = nand_erase; |
mtd->point = NULL; |
mtd->unpoint = NULL; |
mtd->read = nand_read; |
mtd->write = nand_write; --------------------------------+ |
mtd->read_oob = nand_read_oob; | |
mtd->write_oob = nand_write_oob; | |
mtd->sync = nand_sync; | |
mtd->lock = NULL; | |
mtd->unlock = NULL; | |
mtd->block_isbad = nand_block_isbad; | |
mtd->block_markbad = nand_block_markbad; | |
| |
/* propagate ecc.layout to mtd_info */ | |
mtd->ecclayout = chip->ecc.layout; | |
| |
/* Check, if we should skip the bad block table scan */ | |
if (chip->options & NAND_SKIP_BBTSCAN) | |
chip->options |= NAND_BBT_SCANNED; | |
| |
return 0; | |
} | |
| |
static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,<---+ |
size_t *retlen, const uint8_t *buf) |
{ |
struct nand_chip *chip = mtd->priv; |
int ret; |
|
/* Do not allow writes past end of device */ |
if ((to + len) > mtd->size) |
return -EINVAL; |
if (!len) |
return 0; |
|
nand_get_device(chip, mtd, FL_WRITING); |
|
chip->ops.len = len; |
chip->ops.datbuf = (uint8_t *)buf; |
chip->ops.oobbuf = NULL; |
|
ret = nand_do_write_ops(mtd, to, &chip->ops); --------------+ |
| |
*retlen = chip->ops.retlen; | |
| |
nand_release_device(mtd); | |
| |
return ret; | |
} | |
| |
static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, <------+ |
struct mtd_oob_ops *ops) |
{ |
int chipnr, realpage, page, blockmask, column; |
struct nand_chip *chip = mtd->priv; |
uint32_t writelen = ops->len; |
uint8_t *oob = ops->oobbuf; |
uint8_t *buf = ops->datbuf; |
int ret, subpage; |
|
ops->retlen = 0; |
if (!writelen) |
return 0; |
|
column = to & (mtd->writesize - 1); |
subpage = column || (writelen & (mtd->writesize - 1)); |
|
if (subpage && oob) |
return -EINVAL; |
|
chipnr = (int)(to >> chip->chip_shift); |
chip->select_chip(mtd, chipnr); |
|
/* Check, if it is write protected */ |
if (nand_check_wp(mtd)) { |
printk (KERN_NOTICE "nand_do_write_ops: Device is write protected\n"); |
return -EIO; |
} |
|
realpage = (int)(to >> chip->page_shift); |
page = realpage & chip->pagemask; |
blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1; |
|
/* Invalidate the page cache, when we write to the cached page */ |
if (to <= (chip->pagebuf << chip->page_shift) && |
(chip->pagebuf << chip->page_shift) < (to + ops->len)) |
chip->pagebuf = -1; |
|
/* If we're not given explicit OOB data, let it be 0xFF */ |
if (likely(!oob)) |
memset(chip->oob_poi, 0xff, mtd->oobsize); |
|
while(1) { |
WATCHDOG_RESET(); |
|
int bytes = mtd->writesize; |
int cached = writelen > bytes && page != blockmask; |
uint8_t *wbuf = buf; |
|
/* Partial page write ? */ |
if (unlikely(column || writelen < (mtd->writesize - 1))) { |
cached = 0; |
bytes = min_t(int, bytes - column, (int) writelen); |
chip->pagebuf = -1; |
memset(chip->buffers->databuf, 0xff, mtd->writesize); |
memcpy(&chip->buffers->databuf[column], buf, bytes); |
wbuf = chip->buffers->databuf; |
} |
|
if (unlikely(oob)) |
oob = nand_fill_oob(chip, oob, ops); |
|
ret = chip->write_page(mtd, chip, wbuf, page, cached, |
(ops->mode == MTD_OOB_RAW)); |
if (ret) |
break; |
|
writelen -= bytes; |
|
if(!g_need_skip) |
show_process(ops->len - writelen,ops->len); --------+ |
| |
if (!writelen) | |
break; | |
| |
column = 0; | |
buf += bytes; | |
realpage++; | |
| |
page = realpage & chip->pagemask; | |
/* Check, if we cross a chip boundary */ | |
if (!page) { | |
chipnr++; | |
chip->select_chip(mtd, -1); | |
chip->select_chip(mtd, chipnr); | |
} | |
} | |
| |
ops->retlen = ops->len - writelen; | |
if (unlikely(oob)) | |
ops->oobretlen = ops->ooblen; | |
| |
return ret; | |
} | |
| |
int g_on = 0; | |
void show_process(unsigned long a,unsigned long b) <-------+ |
{ |
static int last_percent = 100,type = 0; |
int percent = 0,i = 0; |
char buf[512]; |
char *title = "",*env; |
if(!g_on)return; |
percent = a/(b/100); |
|
if(percent != last_percent) |
{ |
update_led(); |
|
/*update uart console*/ |
printf("\r%02d%% complete",percent); |
|
/*update lcd process bar*/ |
if(last_percent == 100) |
{ |
env = getenv("TYPE"); |
if(env) |
type = (*env)-'0'; |
else |
type = 9; |
|
switch(type) |
{ |
case 0: |
title = "Erasing nand chip............"; |
break; |
case 1: |
title = "Reading MLO from MMC........."; |
break; |
case 2: |
title = "Burning MLO to nand.........."; |
break; |
case 3: |
title = "Reading u-boot.img from MMC.."; |
break; |
case 4: |
title = "Burning u-boot.img to nand..."; |
break; |
case 5: |
title = "Reading uImage from MMC......"; |
break; |
case 6: |
title = "Burning uImage to nand......."; |
break; |
case 7: |
title = "Reading ubi.img from MMC....."; |
break; |
case 8: |
title = "Burning ubi.img to nand......"; |
break; |
default: |
title = "env is null.................."; |
break; |
} |
|
video_drawchars(x1,y1, title, strlen(title)); --------------------+ |
draw_rect(x2,y2,x2+401,y2+31,RGB(255,0,0));//draw rectangle | |
draw_bar(x2+1,y2+1,x2+400,y2+30,RGB(0,0,0));//clear old bar | |
draw_bar(x2+1,y2+1,x2+1+percent*4,y2+30,RGB(0,0,255));//draw bar | |
} | |
else // just draw increased bar | |
{ | |
draw_bar(x2+1+last_percent*4,y2+1,x2+percent*4,y2+30,RGB(0,0,255)); | |
} | |
| |
/*update lcd console*/ | |
sprintf(buf," %02d%% complete ",percent); | |
video_drawchars(x3,y3, buf, strlen(buf)); | |
} | |
| |
last_percent = percent; | |
| |
if(percent == 100) | |
{ | |
if(type == 8) | |
{ | |
char *ok = "Update system to nand success,you can now boot from nand";| |
//draw_bar(0,0,VIDEO_VISIBLE_COLS,VIDEO_VISIBLE_ROWS,RGB(0,0,0)); | |
video_drawchars(x2-24,y3+32, ok, strlen(ok)); | |
} | |
| |
printf("\n"); | |
} | |
} | |
| |
void video_drawchars(int xx, int yy, unsigned char *s, int count) <------------+ |
{ |
u8 *cdat, *dest, *dest0; |
int rows, offset, c; |
|
offset = yy * VIDEO_LINE_LEN + xx * VIDEO_PIXEL_SIZE; |
dest0 = video_fb_address + offset; |
|
switch (VIDEO_DATA_FORMAT) { |
case GDF__8BIT_INDEX: |
case GDF__8BIT_332RGB: |
while (count--) { |
c = *s; |
cdat = video_fontdata + c * VIDEO_FONT_HEIGHT; |
for (rows = VIDEO_FONT_HEIGHT, dest = dest0; |
rows--; dest += VIDEO_LINE_LEN) { |
u8 bits = *cdat++; |
|
((u32 *) dest)[0] = |
(video_font_draw_table8[bits >> 4] & |
eorx) ^ bgx; |
((u32 *) dest)[1] = |
(video_font_draw_table8[bits & 15] & |
eorx) ^ bgx; |
} |
dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE; |
s++; |
} |
break; |
|
case GDF_15BIT_555RGB: |
while (count--) { |
c = *s; |
cdat = video_fontdata + c * VIDEO_FONT_HEIGHT; |
for (rows = VIDEO_FONT_HEIGHT, dest = dest0; |
rows--; dest += VIDEO_LINE_LEN) { |
u8 bits = *cdat++; |
|
((u32 *) dest)[0] = |
SHORTSWAP32((video_font_draw_table15 |
[bits >> 6] & eorx) ^ |
bgx); |
((u32 *) dest)[1] = |
SHORTSWAP32((video_font_draw_table15 |
[bits >> 4 & 3] & eorx) ^ |
bgx); |
((u32 *) dest)[2] = |
SHORTSWAP32((video_font_draw_table15 |
[bits >> 2 & 3] & eorx) ^ |
bgx); |
((u32 *) dest)[3] = |
SHORTSWAP32((video_font_draw_table15 |
[bits & 3] & eorx) ^ |
bgx); |
} |
dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE; |
s++; |
} |
break; |
|
case GDF_16BIT_565RGB: |
dest0 += 2;//align memory for 16bpp |
while (count--) { |
c = *s; |
cdat = video_fontdata + c * VIDEO_FONT_HEIGHT; |
for (rows = VIDEO_FONT_HEIGHT, dest = dest0; |
rows--; dest += VIDEO_LINE_LEN) { |
u8 bits = *cdat++; |
((u32 *) dest)[0] = |
SHORTSWAP32((video_font_draw_table16 |
[bits >> 6] & eorx) ^ |
bgx); |
((u32 *) dest)[1] = |
SHORTSWAP32((video_font_draw_table16 |
[bits >> 4 & 3] & eorx) ^ |
bgx); |
((u32 *) dest)[2] = |
SHORTSWAP32((video_font_draw_table16 |
[bits >> 2 & 3] & eorx) ^ |
bgx); |
((u32 *) dest)[3] = |
SHORTSWAP32((video_font_draw_table16 |
[bits & 3] & eorx) ^ |
bgx); |
} |
dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE; |
s++; |
} |
break; |
|
case GDF_32BIT_X888RGB: |
while (count--) { |
c = *s; |
cdat = video_fontdata + c * VIDEO_FONT_HEIGHT; |
for (rows = VIDEO_FONT_HEIGHT, dest = dest0; |
rows--; dest += VIDEO_LINE_LEN) { |
u8 bits = *cdat++; |
|
((u32 *) dest)[0] = |
SWAP32((video_font_draw_table32 |
[bits >> 4][0] & eorx) ^ bgx); |
((u32 *) dest)[1] = |
SWAP32((video_font_draw_table32 |
[bits >> 4][1] & eorx) ^ bgx); |
((u32 *) dest)[2] = |
SWAP32((video_font_draw_table32 |
[bits >> 4][2] & eorx) ^ bgx); |
((u32 *) dest)[3] = |
SWAP32((video_font_draw_table32 |
[bits >> 4][3] & eorx) ^ bgx); |
((u32 *) dest)[4] = |
SWAP32((video_font_draw_table32 |
[bits & 15][0] & eorx) ^ bgx); |
((u32 *) dest)[5] = |
SWAP32((video_font_draw_table32 |
[bits & 15][1] & eorx) ^ bgx); |
((u32 *) dest)[6] = |
SWAP32((video_font_draw_table32 |
[bits & 15][2] & eorx) ^ bgx); |
((u32 *) dest)[7] = |
SWAP32((video_font_draw_table32 |
[bits & 15][3] & eorx) ^ bgx); |
} |
dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE; |
s++; |
} |
break; |
|
case GDF_24BIT_888RGB: |
while (count--) { |
c = *s; |
cdat = video_fontdata + c * VIDEO_FONT_HEIGHT; |
for (rows = VIDEO_FONT_HEIGHT, dest = dest0; |
rows--; dest += VIDEO_LINE_LEN) { |
u8 bits = *cdat++; |
|
((u32 *) dest)[0] = |
(video_font_draw_table24[bits >> 4][0] |
& eorx) ^ bgx; |
((u32 *) dest)[1] = |
(video_font_draw_table24[bits >> 4][1] |
& eorx) ^ bgx; |
((u32 *) dest)[2] = |
(video_font_draw_table24[bits >> 4][2] |
& eorx) ^ bgx; |
((u32 *) dest)[3] = |
(video_font_draw_table24[bits & 15][0] |
& eorx) ^ bgx; |
((u32 *) dest)[4] = |
(video_font_draw_table24[bits & 15][1] |
& eorx) ^ bgx; |
((u32 *) dest)[5] = |
(video_font_draw_table24[bits & 15][2] |
& eorx) ^ bgx; |
} |
dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE; |
s++; |
} |
break; |
} |
} |
|
int misc_init_r(void) <------------------------------------------+
{
#ifdef DEBUG
unsigned int cntr;
unsigned char *valPtr;
debug("EVM Configuration - ");
debug("\tBoard id %x, profile %x, db %d\n", board_id, profile,
daughter_board_connected);
debug("Base Board EEPROM Data\n");
valPtr = (unsigned char *)&header;
for(cntr = 0; cntr < sizeof(header); cntr++) {
if(cntr % 16 == 0)
debug("\n0x%02x :", cntr);
debug(" 0x%02x", (unsigned int)valPtr[cntr]);
}
debug("\n\n");
debug("Board identification from EEPROM contents:\n");
debug("\tBoard name : %.8s\n", header.name);
debug("\tBoard version: %.4s\n", header.version);
debug("\tBoard serial : %.12s\n", header.serial);
debug("\tBoard config : %.6s\n\n", header.config);
#endif
#ifdef AUTO_UPDATESYS
/*sdÆô¶¯²Å×Ô¶¯¸üÐÂϵͳ*/
if(*((int *)0x80000000) == 8)
run_command("run auto_update_nand", 0); ----------+
#endif |
|
if(*((int *)0x80000000) == 8) |
setenv("bootdev","MMC"); |
else |
setenv("bootdev","NAND"); |
|
return 0; |
} |
|
int run_command (const char *cmd, int flag) <------------+
{
cmd_tbl_t *cmdtp;
char cmdbuf[CONFIG_SYS_CBSIZE]; /* working copy of cmd */
char *token; /* start of token in cmdbuf */
char *sep; /* end of token (separator) in cmdbuf */
char finaltoken[CONFIG_SYS_CBSIZE];
char *str = cmdbuf;
char *argv[CONFIG_SYS_MAXARGS + 1]; /* NULL terminated */
int argc, inquotes;
int repeatable = 1;
int rc = 0;
#ifdef DEBUG_PARSER
printf ("[RUN_COMMAND] cmd[%p]=\"", cmd);
puts (cmd ? cmd : "NULL"); /* use puts - string may be loooong */
puts ("\"\n");
#endif
clear_ctrlc(); /* forget any previous Control C */
if (!cmd || !*cmd) {
return -1; /* empty command */
}
if (strlen(cmd) >= CONFIG_SYS_CBSIZE) {
puts ("## Command too long!\n");
return -1;
}
strcpy (cmdbuf, cmd);
/* Process separators and check for invalid
* repeatable commands
*/
#ifdef DEBUG_PARSER
printf ("[PROCESS_SEPARATORS] %s\n", cmd);
#endif
while (*str) {
/*
* Find separator, or string end
* Allow simple escape of ';' by writing "\;"
*/
for (inquotes = 0, sep = str; *sep; sep++) {
if ((*sep=='\'') &&
(*(sep-1) != '\\'))
inquotes=!inquotes;
if (!inquotes &&
(*sep == ';') && /* separator */
( sep != str) && /* past string start */
(*(sep-1) != '\\')) /* and NOT escaped */
break;
}
/*
* Limit the token to data between separators
*/
token = str;
if (*sep) {
str = sep + 1; /* start of command for next pass */
*sep = '\0';
}
else
str = sep; /* no more commands for next pass */
#ifdef DEBUG_PARSER
printf ("token: \"%s\"\n", token);
#endif
/* find macros in this token and replace them */
process_macros (token, finaltoken);
/* Extract arguments */
if ((argc = parse_line (finaltoken, argv)) == 0) {
rc = -1; /* no command at all */
continue;
}
/* Look up command in command table */
if ((cmdtp = find_cmd(argv[0])) == NULL) {
printf ("Unknown command '%s' - try 'help'\n", argv[0]);
rc = -1; /* give up after bad command */
continue;
}
/* found - check max args */
if (argc > cmdtp->maxargs) {
cmd_usage(cmdtp);
rc = -1;
continue;
}
#if defined(CONFIG_CMD_BOOTD)
/* avoid "bootd" recursion */
if (cmdtp->cmd == do_bootd) {
#ifdef DEBUG_PARSER
printf ("[%s]\n", finaltoken);
#endif
if (flag & CMD_FLAG_BOOTD) {
puts ("'bootd' recursion detected\n");
rc = -1;
continue;
} else {
flag |= CMD_FLAG_BOOTD;
}
}
#endif
/* OK - call function to do the command */
if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {
rc = -1;
}
repeatable &= cmdtp->repeatable;
/* Did the user stop this? */
if (had_ctrlc ())
return -1; /* if stopped then not repeatable */
}
return rc ? rc : repeatable;
}