STATIC_PREFIX void debugrom_save_to_spi(int argc, char * argv[]) { spi_init(); if(argc!=4) return; unsigned dest,src,size; if(get_dword(argv[1],&dest)||get_dword(argv[2],&src) || get_dword(argv[3],&size)) return; spi_program(dest,src,size); }
void handle_write(struct usb_ep *ep,struct usb_request *req) { struct cloner *cloner = req->context; if(req->status == -ECONNRESET) { cloner->ack = -ECONNRESET; return; } if (req->actual != req->length) { printf("write transfer length is err,actual=%08x,length=%08x\n",req->actual,req->length); cloner->ack = -EIO; return; } if(cloner->cmd_type == VR_UPDATE_CFG) { cloner->ack = 0; return; } if (cloner->args->transfer_data_chk) { uint32_t tmp_crc = local_crc32(0xffffffff,req->buf,req->actual); if (cloner->cmd->write.crc != tmp_crc) { printf("crc is errr! src crc=%08x crc=%08x\n",cloner->cmd->write.crc,tmp_crc); cloner->ack = -EINVAL; return; } } #define OPS(x,y) ((x<<16)|(y&0xffff)) switch(cloner->cmd->write.ops) { case OPS(I2C,RAW): cloner->ack = i2c_program(cloner); break; #ifdef CONFIG_JZ_NAND_MGR case OPS(NAND,IMAGE): cloner->ack = nand_program(cloner); break; #endif #ifdef CONFIG_MTD_NAND_JZ case OPS(NAND, MTD_RAW): cloner->ack = nand_mtd_raw_program(cloner); break; case OPS(NAND, MTD_UBI): cloner->ack = nand_mtd_ubi_program(cloner); break; #endif #ifdef CONFIG_JZ_MMC case OPS(MMC,0): case OPS(MMC,1): case OPS(MMC,2): cloner->ack = mmc_program(cloner,cloner->cmd->write.ops & 0xffff); break; #endif #ifdef CONFIG_CMD_EFUSE case OPS(EFUSE,RAW): cloner->ack = efuse_program(cloner); break; #endif case OPS(SPI_NOR,RAW): cloner->ack = spi_program(cloner); break; #ifdef CONFIG_MTD_SPINAND case OPS(SPI_NAND,RAW): cloner->ack = spinand_program(cloner); break; #endif #ifdef CONFIG_JZ_SFC case OPS(SFC_NOR,RAW): cloner->ack = sfc_program(cloner); break; #endif #ifdef CONFIG_MTD_SFCNAND case OPS(SFC_NAND,RAW): cloner->ack = spinand_program(cloner); break; #endif case OPS(MEMORY,RAW): cloner->ack = 0; break; case OPS(REGISTER,RAW): { volatile unsigned int *tmp = (void *)cloner->cmd->write.partation; if((unsigned)tmp > 0xb0000000 && (unsigned)tmp < 0xb8000000) { *tmp = *((int*)cloner->write_req->buf); cloner->ack = 0; } else { printf("OPS(REGISTER,RAW): not supported address."); cloner->ack = -ENODEV; } } break; default: cloner->ack = clmg_write(cloner); } #undef OPS }
/* * Erase the flash device(s) addressed. */ int fl_erase_device(void *base, int size, int verbose) { struct fl_map *map; struct fl_device *dev; int mask, ok, block; int timeout; if(tgt_flashwrite_enable() == 0) { printf("Flash can't be write enabled\n"); return(-2); /* Flash can't be write enabled */ } dev = fl_devident(base, &map); if(dev == NULL) { printf("No flash found at %x\n",(u_int32_t)base); return(-3); /* No flash device found at address */ } /* * Sanity checks! */ if(size == -1 && (int)base == map->fl_map_base) { size = map->fl_map_size; /* Entire flash */ } if(dev->fl_varsecsize != NULL) { int offset = (int)(base - map->fl_map_base) + map->fl_map_offset; int totalsize; printf("offset=%x,base=%x\n",offset,map->fl_map_base); for(block=0, totalsize=0; totalsize < offset; block++) { totalsize += dev->fl_varsecsize[block] * map->fl_map_chips; } mask = ((dev->fl_varsecsize[block] * map->fl_map_width / map->fl_map_chips) - 1); if((int)base & mask) { size += (int)base & mask; base = (void *)((int)base & ~mask); } else if((size + ((int)base - map->fl_map_base)) > map->fl_map_size) { return(-4); /* End beyound end of flash */ } base -= map->fl_map_base; } else { mask = ((dev->fl_secsize * map->fl_map_width / map->fl_map_chips) - 1); if((int)base & mask) { size += (int)base & mask; base = (void *)((int)base & ~mask); } else if((size + ((int)base - map->fl_map_base)) > map->fl_map_size) { return(-4); /* End beyound end of flash */ } base -= map->fl_map_base; block = (int)base / map->fl_map_chips / dev->fl_secsize; size = (size + mask) & ~mask; /* Round up to catch entire flash */ } tgt_flashwrite_enable(); fl_write_protect_unlock(map, dev, 0);/* Disable write protection of SST49LF040B/SST49LF008A */ while(size > 0) { int boffs = (int)base; #if 0 if(size == map->fl_map_size && dev->fl_cap & (FL_CAP_DE|FL_CAP_A7)) { /* * Erase entire devices using the BULK erase feature */ if(verbose) { printf("Erasing all FLASH blocks. "); } (*dev->functions->erase_chip)(map, dev); size = 0; } else { #endif /* * Not entire flash or no BULK erase feature. We * use sector/block erase. */ if(verbose) { printf("\rErasing FLASH block %3d \b\b\b\b\b", block); } if((*dev->functions->erase_sector)(map, dev, boffs) != 0) { printf("\nError: Failed to enter erase mode\n"); (*dev->functions->erase_suspend)(map, dev); (*dev->functions->reset)(map, dev); return(-4); } if(dev->fl_varsecsize != NULL) { base += dev->fl_varsecsize[block] * map->fl_map_chips; size -= dev->fl_varsecsize[block] * map->fl_map_chips; block++; } else { base += dev->fl_secsize * map->fl_map_chips; size -= dev->fl_secsize * map->fl_map_chips; block++; } // } delay(1000); for(timeout = 0 ; ((ok = (*dev->functions->isbusy)(map, dev, 0xffffffff, boffs, TRUE)) == 1) && (timeout < PFLASH_MAX_TIMEOUT); timeout++) { delay(1000); if(verbose) { dotik(256, 0); } } delay(1000); if(!(timeout < PFLASH_MAX_TIMEOUT)) { (*dev->functions->erase_suspend)(map, dev); } (*dev->functions->reset)(map, dev); if(verbose) { if(!(timeout < PFLASH_MAX_TIMEOUT)) { /* XXX if timed out what should really happen here? This doesn't look right. */ printf("\b\b, command timed out!\n"); } else { printf("\b Done.\n"); } } } tgt_flashwrite_disable(); fl_write_protect_lock(map, dev, 0);/* Enable write protection of SST49LF040B/SST49LF008A */ return(ok); } int fl_program(void *fl_base, void *data_base, int data_size, int verbose) { char *nvrambuf; char *nvramsecbuf; char *nvram; int offs,count,left; struct fl_device *dev=fl_devident(fl_base,0); int nvram_size=dev->fl_secsize; nvramsecbuf = (char *)malloc(nvram_size); if(nvramsecbuf == 0) { printf("Warning! Unable to malloc nvrambuffer!\n"); return(-1); } nvram = fl_base; left = data_size; while(left) { offs = (int)nvram &(nvram_size - 1); nvram = (int)nvram & ~(nvram_size - 1); count = min(nvram_size-offs,left); memcpy(nvramsecbuf, nvram, nvram_size); nvrambuf = nvramsecbuf + offs; memcpy(nvrambuf,data_base,count); #ifdef NVRAM_IN_FLASH #ifndef LS3B_SPI_BOOT if(fl_erase_device(nvram, nvram_size, verbose)) { printf("Error! Nvram erase failed!\n"); free(nvramsecbuf); return(0); } if(fl_program_device(nvram, nvramsecbuf, nvram_size, verbose)) { printf("Error! Nvram program failed!\n"); free(nvramsecbuf); return(0); } #else spi_erase( (unsigned long)(nvram)- tgt_flashmap()->fl_map_base, nvram_size); if( spi_program(nvramsecbuf, (unsigned long)(nvram)- tgt_flashmap()->fl_map_base, nvram_size, 0) ) { printf("Error! Nvram program failed!\n"); free(nvramsecbuf); return(0); } #endif #endif data_base += count; nvram += nvram_size; left -= count; } free(nvramsecbuf); return 0; }