blob: 7cf5ba16c0721f3256355d595a16c5276bd0ea4e [file] [log] [blame]
#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