| #include <nand.h> |
| #include <spi_flash.h> |
| #include <common.h> |
| #include <linux/types.h> |
| #include <linux/mtd/mtd.h> |
| #include <linux/mtd/nand.h> |
| #include <linux/mtd/partitions.h> |
| #include <asm/errno.h> |
| #include <asm/string.h> |
| #include <mtd/pxa3xx_bbm.h> |
| #include <asm/arch/pxa3xx_nand.h> |
| |
| int nand_curr_device = -1; |
| #ifdef CONFIG_CMD_NAND |
| nand_info_t nand_info[CONFIG_SYS_MAX_NAND_DEVICE]; |
| #endif |
| #ifdef CONFIG_CMD_ONENAND |
| extern struct mtd_info onenand_mtd; |
| #endif |
| |
| #ifdef CONFIG_NAND_PXA |
| |
| #ifdef MEP_OTA_FLASH_ADDRESS |
| void nand_lock_priv_block(void) |
| { |
| int chip = nand_curr_device; |
| |
| if (chip < 0) |
| return; |
| |
| nand_info[chip].protect_enabled = 1; |
| } |
| |
| void nand_unlock_priv_block(void) |
| { |
| int chip = nand_curr_device; |
| |
| if (chip < 0) |
| return; |
| |
| nand_info[chip].protect_enabled = 0; |
| } |
| |
| static void nand_init_proctect_block(nand_info_t *nand) |
| { |
| nand->protect_enabled = 1; |
| nand->protect_start = MEP_OTA_FLASH_ADDRESS; |
| nand->protect_end = MEP_OTA_FLASH_ADDRESS + MEP_OTA_FLASH_LEN; |
| } |
| #endif |
| |
| void nand_init() |
| { |
| struct pxa3xx_nand_platform_data pxa_nandinfo; |
| struct pxa3xx_nand *nand; |
| int chip; |
| |
| pxa_nandinfo.mmio_base = CONFIG_SYS_NAND_BASE; |
| pxa_nandinfo.enable_arbiter = 1; |
| pxa_nandinfo.RD_CNT_DEL = 0; |
| |
| nand = pxa3xx_nand_probe(&pxa_nandinfo); |
| if (!nand) { |
| printf("pxa3xx-nand probe failed!!\n"); |
| return; |
| } |
| |
| for (chip = 0; chip < CONFIG_SYS_MAX_NAND_DEVICE; chip ++) { |
| if (nand->mtd[chip]) { |
| #ifdef MEP_OTA_FLASH_ADDRESS |
| nand_init_proctect_block(nand->mtd[chip]); |
| #endif |
| memcpy(&(nand_info[chip]), nand->mtd[chip], sizeof(struct mtd_info)); |
| |
| if (nand_curr_device < 0) |
| nand_curr_device = chip; |
| } |
| } |
| |
| if (nand_curr_device < 0) |
| printf("No NAND dev is found !!!\n\n"); |
| } |
| #endif |
| |
| #ifdef CONFIG_SPI_COPYBACK_NAND |
| #define BACK_NTIM_OF 0x1000 |
| #define BACK_OBM_OF 0x30000 |
| #define BACK_UBOOT_OF 0x40000 |
| #define BACK_ZIMAGE_OF 0x100000 |
| #define BURN_ZIMAGE_OF 0x400000 |
| #define MAX_NTIM_SIZE 0x1000 |
| #define MAX_OBM_SIZE 0xf000 |
| #define MAX_UBOOT_SIZE 0x30000 |
| #define MAX_ZIMAGE_SIZE 0x300000 |
| #define NTIM_HEADER_1 0x30102 |
| #define NTIM_HEADER_2 0x54494d48 |
| #define BBT_INIT_COMMAND "bbt init nand new" |
| int nand_update_callback(void) |
| { |
| void *buf = (void *)0x500000; |
| size_t retlen; |
| int ret; |
| unsigned int header_1, header_2; |
| struct mtd_info *mtd; |
| |
| if (nand_curr_device != 0) |
| return -1; |
| |
| mtd = &nand_info[0]; |
| mtd->read(mtd, 0, mtd->writesize, &retlen, buf); |
| header_1 = *(unsigned int*)buf; |
| header_2 = *((unsigned int*)buf + 1); |
| if (header_1 == NTIM_HEADER_1 && header_2 == NTIM_HEADER_2) { |
| return 1; |
| } |
| else { |
| extern int not_updating; |
| extern struct spi_flash *flash; |
| struct erase_info instr = { |
| .callback = NULL, |
| }; |
| |
| printf("\n### begin to update nand from spi nor ###\n"); |
| run_command("nand device 1", 0); |
| not_updating = 1; |
| run_command(BBT_INIT_COMMAND, 0); |
| run_command("nand device 0", 0); |
| not_updating = 0; |
| run_command(BBT_INIT_COMMAND, 0); |
| not_updating = 1; |
| instr.addr = mtd->erasesize; |
| instr.len = instr.addr * 3; |
| printf("\nerasing.."); |
| ret = mtd->erase(mtd, &instr); |
| if (ret) { |
| printf("erase 1-3 block failed!!!\n"); |
| goto UPDATE_FAILED; |
| } |
| |
| instr.addr = BACK_ZIMAGE_OF; |
| instr.len = MAX_ZIMAGE_SIZE * 2; |
| ret = mtd->erase(mtd, &instr); |
| if (ret) { |
| printf("erase 0x100000-0x700000 failed!!!\n"); |
| goto UPDATE_FAILED; |
| } |
| |
| printf("spi read 1.."); |
| ret = spi_flash_read(flash, BACK_NTIM_OF, MAX_NTIM_SIZE, buf); |
| if (ret) { |
| printf("read ntim failed\n"); |
| goto UPDATE_FAILED; |
| } |
| |
| printf("2.."); |
| buf += MAX_NTIM_SIZE; |
| ret = spi_flash_read(flash, BACK_OBM_OF, MAX_OBM_SIZE, buf); |
| if (ret) { |
| printf("read obm failed\n"); |
| goto UPDATE_FAILED; |
| } |
| |
| printf("3.."); |
| buf += MAX_OBM_SIZE; |
| ret = spi_flash_read(flash, BACK_UBOOT_OF, MAX_UBOOT_SIZE, |
| buf); |
| if (ret) { |
| printf("read uboot failed\n"); |
| goto UPDATE_FAILED; |
| } |
| |
| printf("4.."); |
| buf += MAX_UBOOT_SIZE; |
| ret = spi_flash_read(flash, BACK_ZIMAGE_OF, MAX_ZIMAGE_SIZE, |
| buf); |
| if (ret) { |
| printf("read zImage failed\n"); |
| goto UPDATE_FAILED; |
| } |
| |
| printf("nand write 1.."); |
| buf = (void *)0x500000; |
| ret = mtd->write(mtd, 0, MAX_NTIM_SIZE, &retlen, buf); |
| if (ret) { |
| printf("update ntim failed!!\n"); |
| goto UPDATE_FAILED; |
| } |
| |
| printf("2.."); |
| buf += MAX_NTIM_SIZE; |
| ret = mtd->write(mtd, mtd->erasesize, MAX_OBM_SIZE, &retlen, |
| buf); |
| if (ret) { |
| printf("update obm failed!!\n"); |
| goto UPDATE_FAILED; |
| } |
| |
| printf("3.."); |
| buf += MAX_OBM_SIZE; |
| ret = mtd->write(mtd, mtd->erasesize * 2, MAX_UBOOT_SIZE, |
| &retlen, buf); |
| if (ret) { |
| printf("update uboot failed!!\n"); |
| goto UPDATE_FAILED; |
| } |
| |
| printf("4.."); |
| buf += MAX_UBOOT_SIZE; |
| ret = mtd->write(mtd, BURN_ZIMAGE_OF, MAX_ZIMAGE_SIZE, |
| &retlen, buf); |
| if (ret) { |
| printf("update zImage failed!!\n"); |
| goto UPDATE_FAILED; |
| } |
| |
| printf("update done!!\n"); |
| return 0; |
| UPDATE_FAILED: |
| |
| printf("!!!update failed!!!\n"); |
| return -1; |
| } |
| } |
| #endif |