blob: 080fd25a745c7c85164ec166aa438b264be45a1b [file] [log] [blame] [edit]
/*
* Aml
*
* (C) 2012 8
*/
#include "../include/phynand.h"
#include <asm/arch/secure_apb.h>
#include <asm/cpu_id.h>
extern int aml_ubootenv_init(struct amlnand_chip *aml_chip);
#if (AML_CFG_DTB_RSV_EN)
extern int amlnf_dtb_init(struct amlnand_chip *aml_chip);
#endif
extern int amlnand_save_info_by_name(struct amlnand_chip *aml_chip,unsigned char * info,unsigned char * buf, u8 * name,unsigned size);
extern int aml_nand_update_key(struct amlnand_chip * aml_chip, char *key_ptr);
extern int aml_nand_update_ubootenv(struct amlnand_chip * aml_chip, char *env_ptr);
#ifdef AML_NAND_UBOOT
struct list_head nf_dev_list;
struct list_head nlogic_dev_list;
#endif /* AML_NAND_UBOOT */
struct bch_desc bch_list_m8[MAX_ECC_MODE_NUM] = {
[0] = ECC_INFORMATION("NAND_RAW_MODE",
NAND_ECC_SOFT_MODE,
0,
0,
0,
0),
[1] = ECC_INFORMATION("NAND_BCH8_MODE",
NAND_ECC_BCH8_MODE,
NAND_ECC_UNIT_SIZE,
NAND_BCH8_ECC_SIZE,
2,
1),
[2] = ECC_INFORMATION("NAND_BCH8_1K_MODE" ,
NAND_ECC_BCH8_1K_MODE,
NAND_ECC_UNIT_1KSIZE,
NAND_BCH8_1K_ECC_SIZE,
2,
2),
[3] = ECC_INFORMATION("NAND_BCH24_1K_MODE" ,
NAND_ECC_BCH24_1K_MODE,
NAND_ECC_UNIT_1KSIZE,
NAND_BCH24_1K_ECC_SIZE,
2,
3),
[4] = ECC_INFORMATION("NAND_BCH30_1K_MODE" ,
NAND_ECC_BCH30_1K_MODE,
NAND_ECC_UNIT_1KSIZE,
NAND_BCH30_1K_ECC_SIZE,
2,
4),
[5] = ECC_INFORMATION("NAND_BCH40_1K_MODE" ,
NAND_ECC_BCH40_1K_MODE,
NAND_ECC_UNIT_1KSIZE,
NAND_BCH40_1K_ECC_SIZE,
2,
5),
[6] = ECC_INFORMATION("NAND_BCH50_1K_MODE" ,
NAND_ECC_BCH50_1K_MODE,
NAND_ECC_UNIT_1KSIZE,
NAND_BCH50_1K_ECC_SIZE,
2,
6),
[7] = ECC_INFORMATION("NAND_BCH60_1K_MODE" ,
NAND_ECC_BCH60_1K_MODE,
NAND_ECC_UNIT_1KSIZE,
NAND_BCH60_1K_ECC_SIZE,
2,
7),
[8] = ECC_INFORMATION("NAND_SHORT_MODE" ,
NAND_ECC_SHORT_MODE,
NAND_ECC_UNIT_SHORT,
NAND_BCH60_1K_ECC_SIZE,
2,
8),
};
struct bch_desc bch_list[MAX_ECC_MODE_NUM] = {
[0] = ECC_INFORMATION("NAND_RAW_MODE",
NAND_ECC_SOFT_MODE,
0,
0,
0,
0),
[1] = ECC_INFORMATION("NAND_BCH8_MODE",
NAND_ECC_BCH8_MODE,
NAND_ECC_UNIT_SIZE,
NAND_BCH8_ECC_SIZE,
2,
1),
[2] = ECC_INFORMATION("NAND_BCH8_1K_MODE" ,
NAND_ECC_BCH8_1K_MODE,
NAND_ECC_UNIT_1KSIZE,
NAND_BCH8_1K_ECC_SIZE,
2,
2),
[3] = ECC_INFORMATION("NAND_BCH16_1K_MODE" ,
NAND_ECC_BCH16_1K_MODE,
NAND_ECC_UNIT_1KSIZE,
NAND_BCH16_1K_ECC_SIZE,
2,
3),
[4] = ECC_INFORMATION("NAND_BCH24_1K_MODE" ,
NAND_ECC_BCH24_1K_MODE,
NAND_ECC_UNIT_1KSIZE,
NAND_BCH24_1K_ECC_SIZE,
2,
4),
[5] = ECC_INFORMATION("NAND_BCH30_1K_MODE" ,
NAND_ECC_BCH30_1K_MODE,
NAND_ECC_UNIT_1KSIZE,
NAND_BCH30_1K_ECC_SIZE,
2,
5),
[6] = ECC_INFORMATION("NAND_BCH40_1K_MODE" ,
NAND_ECC_BCH40_1K_MODE,
NAND_ECC_UNIT_1KSIZE,
NAND_BCH40_1K_ECC_SIZE,
2,
6),
[7] = ECC_INFORMATION("NAND_BCH60_1K_MODE" ,
NAND_ECC_BCH60_1K_MODE,
NAND_ECC_UNIT_1KSIZE,
NAND_BCH60_1K_ECC_SIZE,
2,
7),
[8] = ECC_INFORMATION("NAND_SHORT_MODE" ,
NAND_ECC_SHORT_MODE,
NAND_ECC_UNIT_SHORT,
NAND_BCH60_1K_ECC_SIZE,
2,
8),
};
#ifndef AML_NAND_UBOOT
static dma_addr_t nfdata_dma_addr;
static dma_addr_t nfinfo_dma_addr;
spinlock_t amlnf_lock;
wait_queue_head_t amlnf_wq;
#endif
struct list_head nphy_dev_list;
struct list_head nf_dev_list;
void *aml_nand_malloc(u32 size)
{
return kmalloc(size, GFP_KERNEL);
}
void aml_nand_free(void *ptr)
{
kfree(ptr);
}
#ifndef AML_NAND_UBOOT
void *amlnf_dma_malloc(uint32 size, unsigned char flag)
{
if (flag == 0) //data
return dma_alloc_coherent(NULL, size, &nfdata_dma_addr, GFP_KERNEL);
if (flag == 1) //usr
return dma_alloc_coherent(NULL, size, &nfinfo_dma_addr, GFP_KERNEL);
}
void amlnf_dma_free(const void *ptr, u32 size, u8 flag)
{
if (flag == 0) /* data */
dma_free_coherent(NULL, size, (void *)ptr, nfdata_dma_addr);
if (flag == 1) /* usr */
dma_free_coherent(NULL, size, (void *)ptr, nfinfo_dma_addr);
}
#endif
/*
* under os.
*/
#ifndef AML_NAND_UBOOT
int amlphy_prepare(u32 flag)
{
spin_lock_init(&amlnf_lock);
init_waitqueue_head(&amlnf_wq);
return 0;
}
int phydev_suspend(struct amlnand_phydev *phydev)
{
struct amlnand_chip *aml_chip = (struct amlnand_chip *)phydev->priv;
#ifdef AML_NAND_RB_IRQ
u32 flags;
#endif
if (!strncmp((char *)phydev->name,
NAND_BOOT_NAME,
strlen((const char *)NAND_BOOT_NAME)))
return 0;
aml_nand_dbg("phydev_suspend: entered!");
#ifdef AML_NAND_RB_IRQ
spin_lock_irqsave(&amlnf_lock, flags);
#else
spin_lock(&amlnf_lock);
#endif
set_chip_state(aml_chip, CHIP_PM_SUSPENDED);
#ifdef AML_NAND_RB_IRQ
spin_unlock_irqrestore(&amlnf_lock, flags);
#else
spin_unlock(&amlnf_lock);
#endif
return 0;
}
void phydev_resume(struct amlnand_phydev *phydev)
{
amlchip_resume(phydev);
return;
}
int nand_idleflag = 0;
#define NAND_CTRL_NONE_RB (1<<1)
void nand_get_chip(void *chip)
{
struct amlnand_chip *aml_chip = (struct amlnand_chip *)chip;
struct hw_controller *controller = &(aml_chip->controller);
int retry = 0, ret;
while (1) {
/* mutex_lock(&spi_nand_mutex); */
nand_idleflag = 1;
if ((controller->option & NAND_CTRL_NONE_RB) == 0)
ret = pinctrl_select_state(aml_chip->nand_pinctrl ,
aml_chip->nand_rbstate);
else
ret = pinctrl_select_state(aml_chip->nand_pinctrl ,
aml_chip->nand_norbstate);
if (ret < 0)
aml_nand_msg("%s:%d %s can't get pinctrl",
__func__,
__LINE__,
dev_name(&aml_chip->device));
else
break;
if (retry++ > 10)
aml_nand_msg("get pin fail over 10 times retry=%d",
retry);
}
return;
}
void nand_release_chip(void *chip)
{
struct amlnand_chip *aml_chip = (struct amlnand_chip *)chip;
struct hw_controller *controller = &(aml_chip->controller);
int ret;
if (nand_idleflag) {
/* enter standby state. */
controller->enter_standby(controller);
ret = pinctrl_select_state(aml_chip->nand_pinctrl,
aml_chip->nand_idlestate);
if (ret < 0)
aml_nand_msg("select idle state error");
nand_idleflag = 0;
/* mutex_unlock(&spi_nand_mutex); */
}
}
/**
* amlnand_get_device - [GENERIC] Get chip for selected access
*
* Get the device and lock it for exclusive access
*/
int amlnand_get_device(struct amlnand_chip *aml_chip,
enum chip_state_t new_state)
{
#ifdef AML_NAND_RB_IRQ
u32 flags;
#endif
DECLARE_WAITQUEUE(wait, current);
retry:
#ifdef AML_NAND_RB_IRQ
spin_lock_irqsave(&amlnf_lock, flags);
#else
spin_lock(&amlnf_lock);
#endif
if (get_chip_state(aml_chip) == CHIP_READY) {
set_chip_state(aml_chip, new_state);
#ifdef AML_NAND_RB_IRQ
spin_unlock_irqrestore(&amlnf_lock, flags);
#else
spin_unlock(&amlnf_lock);
#endif
/* set nand pinmux here */
nand_get_chip(aml_chip);
return 0;
}
set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&amlnf_wq, &wait);
#ifdef AML_NAND_IRQ_MODE
spin_unlock_irqrestore(&amlnf_lock, flags);
#else
spin_unlock(&amlnf_lock);
#endif
schedule();
remove_wait_queue(&amlnf_wq, &wait);
goto retry;
}
/**
* nand_release_device - [GENERIC] release chip
* @aml_chip: nand chip structure
*
* Deselect, release chip lock and wake up anyone waiting on the device
*/
void amlnand_release_device(struct amlnand_chip *aml_chip)
{
#ifdef AML_NAND_RB_IRQ
u32 flags;
#endif
/* Release the controller and the chip */
#ifdef AML_NAND_RB_IRQ
spin_lock_irqsave(&amlnf_lock, flags);
#else
spin_lock(&amlnf_lock);
#endif
set_chip_state(aml_chip, CHIP_READY);
wake_up(&amlnf_wq);
#ifdef AML_NAND_RB_IRQ
spin_unlock_irqrestore(&amlnf_lock, flags);
#else
spin_unlock(&amlnf_lock);
#endif
/* clear nand pinmux here */
nand_release_chip(aml_chip);
}
#else /* AML_NAND_UBOOT, uboot ways below */
#ifndef P_PAD_DS_REG0A
#define P_PAD_DS_REG0A (volatile uint32_t *)(0xff634400 + (0x0d0 << 2))
#endif
void nand_get_chip(void *chip)
{
/* fixme, */
cpu_id_t cpu_id = get_cpu_id();
/* pull up enable */
aml_nand_dbg("PAD_PULL_UP_EN_REG2 0x%x, PAD_PULL_UP_REG2 0x%x, PERIPHS_PIN_MUX_4 0x%x", P_PAD_PULL_UP_EN_REG2, P_PAD_PULL_UP_REG2, P_PERIPHS_PIN_MUX_4);
if (cpu_id.family_id == MESON_CPU_MAJOR_ID_G12A) {
AMLNF_SET_REG_MASK(P_PAD_PULL_UP_EN_REG4, 0x1FFF);
AMLNF_SET_REG_MASK(P_PAD_PULL_UP_REG4, 0x1F00);
AMLNF_WRITE_REG(P_PERIPHS_PIN_MUX_0, 0x11111111);
AMLNF_WRITE_REG(P_PERIPHS_PIN_MUX_1, 0x22122222);
writel(0x55555555, P_PAD_DS_REG0A);
} else {
AMLNF_SET_REG_MASK(P_PAD_PULL_UP_EN_REG2, 0x87ff);
/* pull direction, dqs pull down */
AMLNF_SET_REG_MASK(P_PAD_PULL_UP_REG2, 0x8700);
/* switch pinmux */
if (cpu_id.family_id >= MESON_CPU_MAJOR_ID_GXL) {
AMLNF_CLEAR_REG_MASK(P_PERIPHS_PIN_MUX_7,
((0x7 << 28) | (0x1FF << 15) | (0xF << 10)));
AMLNF_SET_REG_MASK(P_PERIPHS_PIN_MUX_7, ((0x1<<31) | 0xff));
} else if (cpu_id.family_id == MESON_CPU_MAJOR_ID_GXBB) {
AMLNF_SET_REG_MASK(P_PERIPHS_PIN_MUX_4, ((0x1<<30) | (0x3ff<<20)));
AMLNF_CLEAR_REG_MASK(P_PERIPHS_PIN_MUX_0, (0x1 << 19));
AMLNF_CLEAR_REG_MASK(P_PERIPHS_PIN_MUX_4, (0x3 << 18));
AMLNF_CLEAR_REG_MASK(P_PERIPHS_PIN_MUX_5, (0xF));
}
aml_nand_dbg("PAD_PULL_UP_EN_REG2 0x%x, PAD_PULL_UP_REG2 0x%x, PERIPHS_PIN_MUX_4 0x%x", AMLNF_READ_REG(P_PAD_PULL_UP_EN_REG2), AMLNF_READ_REG(P_PAD_PULL_UP_REG2), AMLNF_READ_REG(P_PERIPHS_PIN_MUX_4));
}
return ;
}
void nand_release_chip(void *chip)
{
struct amlnand_chip *aml_chip = (struct amlnand_chip *)chip;
struct hw_controller * controller;
cpu_id_t cpu_id = get_cpu_id();
controller = &aml_chip->controller;
NFC_SEND_CMD_STANDBY(controller, 5);
/* do not release cs0 & cs1 */
//fixme,
if (cpu_id.family_id >= MESON_CPU_MAJOR_ID_GXL) {
//AMLNF_CLEAR_REG_MASK(P_PERIPHS_PIN_MUX_7, ((0x1<<30) | (0x3f << 30)));
} else if (cpu_id.family_id == MESON_CPU_MAJOR_ID_GXBB) {
//AMLNF_CLEAR_REG_MASK(P_PERIPHS_PIN_MUX_2, ((0x33f<<20) | (0x1<< 30)));
}
return;
}
int amlnand_get_device(struct amlnand_chip *aml_chip, enum chip_state_t new_state)
{
nand_get_chip(aml_chip);
set_chip_state(aml_chip, new_state);
return 0;
}
void amlnand_release_device(struct amlnand_chip *aml_chip)
{
set_chip_state(aml_chip, CHIP_READY);
//clear nand pinmux here
nand_release_chip(aml_chip);
}
#endif
void pinmux_select_chip(unsigned ce_enable, unsigned rb_enable, unsigned flag)
{
#ifdef AML_NAND_UBOOT
if (!((ce_enable >> 10) & 1))
AMLNF_SET_REG_MASK(P_PERIPHS_PIN_MUX_4, (1 << 26));
if (!((ce_enable >> 10) & 2))
AMLNF_SET_REG_MASK(P_PERIPHS_PIN_MUX_4, (1 << 27));
if (!((ce_enable >> 10) & 4))
AMLNF_SET_REG_MASK(P_PERIPHS_PIN_MUX_4, (1 << 28));
if (!((ce_enable >> 10) & 8))
AMLNF_SET_REG_MASK(P_PERIPHS_PIN_MUX_4, (1 << 29));
#endif /* */
}
void set_nand_core_clk(struct hw_controller *controller, int clk_freq)
{
cpu_id_t cpu_id = get_cpu_id();
if ((cpu_id.family_id >= MESON_CPU_MAJOR_ID_GXBB)) {
/* basic test code for gxb using 24Mhz, fixme. */
//amlnf_write_reg32(controller->nand_clk_reg, 0x81000201); //24Mhz/1
if (clk_freq == 200) {
/* 1000Mhz/5 = 200Mhz */
amlnf_write_reg32(controller->nand_clk_reg, 0x81000245);
}
else if (clk_freq == 250) {
/* 1000Mhz/4 = 250Mhz */
amlnf_write_reg32(controller->nand_clk_reg, 0x81000244);
} else {
/* 1000Mhz/5 = 200Mhz */
amlnf_write_reg32(controller->nand_clk_reg, 0x81000245);
printk("%s() %d, using default clock setting!\n", __func__, __LINE__);
}
//printk("clk_reg 0x%x\n", AMLNF_READ_REG(controller->nand_clk_reg));
return;
} else {
printk("cpu type can not support!\n");
}
return;
}
void get_sys_clk_rate(struct hw_controller *controller, int *rate)
{
u32 cpu_type;
#ifndef AML_NAND_UBOOT
struct clk *sys_clk;
#endif
cpu_type = get_cpu_type();
if (cpu_type >= MESON_CPU_MAJOR_ID_M8) {
/* 200-250Mhz */
set_nand_core_clk(controller, *rate);
}
return;
}
/*
set nand info into page0_buf
*/
void nand_boot_info_prepare(struct amlnand_phydev *phydev,
u8 *page0_buf)
{
struct amlnand_chip *aml_chip = (struct amlnand_chip *)phydev->priv;
struct nand_flash *flash = &(aml_chip->flash);
struct phydev_ops *devops = &(phydev->ops);
struct hw_controller *controller = &(aml_chip->controller);
struct en_slc_info *slc_info = NULL;
int i, nand_read_info;
u32 en_slc, configure_data;
u32 boot_num = 1, each_boot_pages;
u32 valid_pages = BOOT_COPY_NUM * BOOT_PAGES_PER_COPY;
nand_page0_t * p_nand_page0 = NULL;
ext_info_t * p_ext_info = NULL;
nand_setup_t * p_nand_setup = NULL;
slc_info = &(controller->slc_info);
p_nand_page0 = (nand_page0_t *) page0_buf;
p_nand_setup = &p_nand_page0->nand_setup;
p_ext_info = &p_nand_page0->ext_info;
configure_data = NFC_CMD_N2M(controller->ran_mode,
controller->bch_mode, 0, (controller->ecc_unit >> 3),
controller->ecc_steps);
/* hynix 2x and lower... */
if ((flash->new_type < 10) && (flash->new_type))
en_slc = 1;
else if (flash->new_type == SANDISK_19NM)
en_slc = 2;
else
en_slc = 0;
//memset(page0_buf, 0x0, flash->pagesize);
memset(p_nand_page0, 0x0, sizeof(nand_page0_t));
p_nand_setup->cfg.d32 = (configure_data|(1<<23) | (1<<22) | (2<<20) | (1<<19));
printk("cfg.d32 0x%x\n", p_nand_setup->cfg.d32);
/* need finish here for romboot retry */
p_nand_setup->id = 0;
p_nand_setup->max = 0;
memset(p_nand_page0->page_list,
0,
NAND_PAGELIST_CNT);
if (en_slc) {
p_nand_setup->cfg.b.page_list = 1;
if (en_slc == 1) {
memcpy(p_nand_page0->page_list,
(u8 *)(&slc_info->pagelist[1]),
NAND_PAGELIST_CNT);
} else if (en_slc == 2) {
p_nand_setup->cfg.b.a2 = 1;
for (i = 1; i < NAND_PAGELIST_CNT; i++)
p_nand_page0->page_list[i-1] = i<<1;
}
}
/* chip_num occupy the lowest 2 bit */
nand_read_info = controller->chip_num;
/*
make it
1)calu the number of boot saved and pages each boot needs.
2)the number is 2*n but less than 4.
*/
aml_nand_msg("valid_pages = %d en_slc = %d devops->len = %llx",
valid_pages,
en_slc, devops->len);
valid_pages = (en_slc)?(valid_pages>>1):valid_pages;
for (i = 1;
i < ((valid_pages*flash->pagesize)/devops->len + 1); i++) {
if (((valid_pages*flash->pagesize)/(2*i) >= devops->len)
&& (boot_num < 4))
boot_num <<= 1;
else
break;
}
each_boot_pages = valid_pages/boot_num;
each_boot_pages = (en_slc)?(each_boot_pages<<1):each_boot_pages;
p_ext_info->read_info = nand_read_info;
p_ext_info->new_type = aml_chip->flash.new_type;
p_ext_info->page_per_blk = flash->blocksize / flash->pagesize;
p_ext_info->ce_mask = aml_chip->ce_bit_mask;
p_ext_info->xlc = 2;
p_ext_info->boot_num = boot_num;
p_ext_info->each_boot_pages = each_boot_pages;
printk("new_type = 0x%x\n", p_ext_info->new_type);
printk("page_per_blk = 0x%x\n", p_ext_info->page_per_blk);
aml_nand_msg("boot_num = %d each_boot_pages = %d", boot_num,
each_boot_pages);
}
void uboot_set_ran_mode(struct amlnand_phydev *phydev)
{
struct amlnand_chip *aml_chip = (struct amlnand_chip *)phydev->priv;
struct hw_controller *controller = &(aml_chip->controller);
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8)
controller->ran_mode = 1;
else
controller->ran_mode = 0;
}
int aml_sys_info_init(struct amlnand_chip *aml_chip)
{
#if (AML_CFG_KEY_RSV_EN)
struct nand_arg_info *nand_key = &aml_chip->nand_key;
#endif
#ifdef CONFIG_SECURE_NAND
struct nand_arg_info *nand_secure = &aml_chip->nand_secure;
#endif
#if (AML_CFG_DTB_RSV_EN)
struct nand_arg_info *amlnf_dtb = &aml_chip->amlnf_dtb;
#endif
struct nand_arg_info *uboot_env = &aml_chip->uboot_env;
u8 *buf = NULL;
u32 buf_size = 0;
int ret = 0;
buf_size = 0x40000; /*rsv item max size is 256KB*/
buf = aml_nand_malloc(buf_size);
if (!buf)
aml_nand_msg("aml_sys_info_init : malloc failed");
memset(buf, 0x0, buf_size);
NAND_LINE
#if (AML_CFG_KEY_RSV_EN)
if (nand_key->arg_valid == 0) {
NAND_LINE
ret = aml_key_init(aml_chip);
if (ret < 0) {
aml_nand_msg("nand key init failed");
goto exit_error;
}
}
#endif
#ifdef CONFIG_SECURE_NAND
if (nand_secure->arg_valid == 0) {
NAND_LINE
ret = aml_secure_init(aml_chip);
if (ret < 0) {
aml_nand_msg("nand secure init failed");
goto exit_error;
}
}
#endif
#if (AML_CFG_DTB_RSV_EN)
if (amlnf_dtb->arg_valid == 0) {
NAND_LINE
ret = amlnf_dtb_init(aml_chip);
if (ret < 0) {
aml_nand_msg("amlnf dtb init failed");
/* fixme, should go on! */
//goto exit_error;
}
}
#endif
NAND_LINE
printk("boot_device_flag %d\n", boot_device_flag);
if ((uboot_env->arg_valid == 0) && (boot_device_flag == 1)) {
NAND_LINE
ret = aml_ubootenv_init(aml_chip);
if (ret < 0) {
aml_nand_msg("nand uboot env init failed");
goto exit_error;
}
}
#if (AML_CFG_KEY_RSV_EN)
if (nand_key->arg_valid == 0) {
NAND_LINE
ret = amlnand_save_info_by_name(aml_chip,
(u8 *)(&(aml_chip->nand_key)),
buf,
(u8 *)KEY_INFO_HEAD_MAGIC,
aml_chip->keysize);
NAND_LINE
if (ret < 0) {
aml_nand_msg("nand save default key failed");
goto exit_error;
}
}
#endif
#ifdef CONFIG_SECURE_NAND
/*save a empty value! */
if (nand_secure->arg_valid == 0) {
NAND_LINE
ret = amlnand_save_info_by_name(aml_chip,
(u8 *)&(aml_chip->nand_secure),
buf,
(u8 *)SECURE_INFO_HEAD_MAGIC,
CONFIG_SECURE_SIZE);
if (ret < 0) {
aml_nand_msg("nand save default secure_ptr failed");
goto exit_error;
}
}
#endif
#if (AML_CFG_DTB_RSV_EN)
/* fixme, no need to save a empty dtb. */
#endif
NAND_LINE
exit_error:
kfree(buf);
buf = NULL;
return ret;
}
int aml_sys_info_error_handle(struct amlnand_chip *aml_chip)
{
#if (AML_CFG_KEY_RSV_EN)
if ((aml_chip->nand_key.arg_valid == 1) &&
(aml_chip->nand_key.update_flag)) {
aml_nand_update_key(aml_chip, NULL);
aml_chip->nand_key.update_flag = 0;
aml_nand_msg("NAND UPDATE CKECK : ");
aml_nand_msg("arg %s:arg_valid=%d,blk_addr=%d,page_addr=%d",
"nandkey",
aml_chip->nand_key.arg_valid,
aml_chip->nand_key.valid_blk_addr,
aml_chip->nand_key.valid_page_addr);
}
#endif
#ifdef CONFIG_SECURE_NAND
if ((aml_chip->nand_secure.arg_valid == 1)
&& (aml_chip->nand_secure.update_flag)) {
aml_nand_update_secure(aml_chip, NULL);
aml_chip->nand_secure.update_flag = 0;
aml_nand_msg("NAND UPDATE CKECK : ");
aml_nand_msg("arg%s:arg_valid=%d,blk_addr=%d,page_addr=%d",
"nandsecure",
aml_chip->nand_secure.arg_valid,
aml_chip->nand_secure.valid_blk_addr,
aml_chip->nand_secure.valid_page_addr);
}
#endif
#if (AML_CFG_DTB_RSV_EN)
if ((aml_chip->amlnf_dtb.arg_valid == 1)
&& (aml_chip->amlnf_dtb.update_flag)) {
aml_nand_update_dtb(aml_chip, NULL);
aml_chip->amlnf_dtb.update_flag = 0;
aml_nand_msg("NAND UPDATE CKECK : ");
aml_nand_msg("arg%s:arg_valid=%d,blk_addr=%d,page_addr=%d",
"dtb",
aml_chip->amlnf_dtb.arg_valid,
aml_chip->amlnf_dtb.valid_blk_addr,
aml_chip->amlnf_dtb.valid_page_addr);
}
#endif
if ((aml_chip->uboot_env.arg_valid == 1)
&& (aml_chip->uboot_env.update_flag)) {
aml_nand_update_ubootenv(aml_chip, NULL);
aml_chip->uboot_env.update_flag = 0;
aml_nand_msg("NAND UPDATE CKECK : ");
aml_nand_msg("arg%s:arg_valid=%d,blk_addr=%d,page_addr=%d",
"ubootenv",
aml_chip->uboot_env.arg_valid,
aml_chip->uboot_env.valid_blk_addr,
aml_chip->uboot_env.valid_page_addr);
}
return 0;
}
#ifdef AML_NAND_UBOOT
/*fixme, */
extern int info_disprotect;
void amlnf_disprotect(char * name)
{
//struct amlnand_chip *aml_chip = aml_nand_chip;
/* #ifdef CONFIG_SECURITYKEY */
if (strcmp((const char *)name, "key") == 0) {
aml_nand_msg("disprotect key");
info_disprotect |= DISPROTECT_KEY;
aml_nand_chip->protect |= DISPROTECT_KEY;
}
/*#endif */
#ifdef CONFIG_SECURE_NAND
if (strcmp((const char *)name, "secure") == 0) {
aml_nand_msg("disprotect secure");
info_disprotect |= DISPROTECT_SECURE;
aml_nand_chip->protect |= DISPROTECT_SECURE;
}
#endif
if (strcmp((const char *)name, "fbbt") == 0) {
aml_nand_msg("disprotect fbbt");
info_disprotect |= DISPROTECT_FBBT;
aml_nand_chip->protect |= DISPROTECT_FBBT;
}
if (strcmp((const char *)name, "hynix") == 0) {
aml_nand_msg("disprotect hynix");
info_disprotect |= DISPROTECT_HYNIX;
aml_nand_chip->protect |= DISPROTECT_HYNIX;
}
if (strcmp((const char *)name, "dbg") == 0) {
aml_nand_msg("disprotect dbg");
info_disprotect |= DISPROTECT_DBG;
aml_nand_chip->protect |= DISPROTECT_DBG;
}
aml_nand_msg("disprotect 0x%08x", info_disprotect);
return ;
}
#endif