예제 #1
0
 int32_t nand_secure_read(struct amlnand_chip * aml_chip, char *buf,int len)
{
	//struct amlnand_chip * aml_chip = provider->priv;
	//secure_t *secure_ptr = NULL;
	unsigned char *secure_ptr = NULL;
	int error = 0;
	if(len > CONFIG_SECURE_SIZE)
	{
		aml_nand_msg("key data len too much,%s\n",__func__);
		return -EFAULT;
	}
	secure_ptr = kzalloc(CONFIG_SECURE_SIZE, GFP_KERNEL);
	if(secure_ptr == NULL)
		return -ENOMEM;
	memset(secure_ptr,0,CONFIG_SECURE_SIZE);

	error = amlnand_read_info_by_name(aml_chip, (unsigned char *)(&aml_chip->nand_secure),secure_ptr,(unsigned char *)SECURE_INFO_HEAD_MAGIC, CONFIG_SECURE_SIZE);
	if (error) 
	{
		aml_nand_msg("read key error,%s\n",__func__);
		error = -EFAULT;
		goto exit;
	}
	//memcpy(buf, secure_ptr->data, len);
	memcpy(buf, secure_ptr, len);
exit:
	kfree(secure_ptr);
	return error;
}
예제 #2
0
int aml_nand_update_secure(struct amlnand_chip * aml_chip, char *secure_ptr)
{
	int ret = 0;
	char malloc_flag = 0;
	unsigned char *secure_buf = NULL;
	
	if(secure_buf == NULL){
		
		secure_buf = kzalloc(CONFIG_SECURE_SIZE, GFP_KERNEL);
		if(secure_buf == NULL)
			return -ENOMEM;
		memset(secure_buf,0,CONFIG_SECURE_SIZE);
		ret = amlnand_read_info_by_name(aml_chip, (unsigned char *)(&aml_chip->nand_secure),secure_buf,(unsigned char *)SECURE_INFO_HEAD_MAGIC, CONFIG_SECURE_SIZE);
		if (ret) 
		{
			aml_nand_msg("read key error,%s\n",__func__);
			ret = -EFAULT;
			goto exit;
		}
	}else{
		secure_buf = (unsigned char *)secure_ptr;
	}
	
	ret = amlnand_save_info_by_name(aml_chip, (unsigned char *)(&aml_chip->nand_secure), secure_buf, (unsigned char *)SECURE_INFO_HEAD_MAGIC, CONFIG_SECURE_SIZE);
	if(ret < 0){
		aml_nand_msg("aml_nand_update_secure : update secure failed");
	}
	
exit:	
	if(malloc_flag && (secure_buf)){
		kfree(secure_buf);
		secure_buf = NULL;
	}
	return 0;
}
예제 #3
0
/*****************************************************************************
*Name         :
*Description  :
*Parameter    :
*Return       :
*Note         :
*****************************************************************************/
static void part_resume(struct ntd_info *ntd)
{
	struct amlnand_phydev *phy;
	/* int ret = 0; */
	phy = ntd->priv;
	if (phy == NULL) {
		aml_nand_msg("%s : get phy dev failed", __func__);
		return;
	}
	 phy->resume(phy);

	aml_nand_msg("part_resume %s", phy->name);

	return;
}
예제 #4
0
int32_t nand_secure_write(struct amlnand_chip * aml_chip, char *buf,int len)
{
	secure_t *secure_ptr = NULL;
	int error = 0;

	if(len > CONFIG_SECURE_SIZE)
	{
		aml_nand_msg("key data len too much,%s\n",__func__);
		return -EFAULT;
	}
	
	secure_ptr = kzalloc(CONFIG_SECURE_SIZE, GFP_KERNEL);
	if(secure_ptr == NULL)
		return -ENOMEM;
	
	memset(secure_ptr,0,CONFIG_SECURE_SIZE);
	memcpy(secure_ptr->data + 0, buf, len);
	amlnand_get_device(aml_chip, CHIP_WRITING);

	error = amlnand_save_info_by_name(aml_chip, (unsigned char *)&(aml_chip->nand_secure),(unsigned char *)secure_ptr,SECURE_INFO_HEAD_MAGIC, CONFIG_SECURE_SIZE);
	if (error) 
	{
		printk("save key error,%s\n",__func__);
		error = -EFAULT;
		goto exit;
	}
exit:
	amlnand_release_device(aml_chip);
	kfree(secure_ptr);
	return error;
}
예제 #5
0
static int controller_queue_rb_irq(struct hw_controller *controller,
	unsigned char chipnr)
{
	int ret = 0, timeout = 0;

	if (chipnr != NAND_CHIP_UNDEFINE)/* skip dma operation */
		controller->select_chip(controller, chipnr);

	reinit_completion(&rb_complete);
	controller_open_interrupt(controller);
	NFC_SEND_CMD_IDLE(controller, NAND_TWB_TIME_CYCLE);
	controller->cmd_ctrl(controller, NAND_CMD_STATUS, NAND_CTRL_CLE);
	NFC_SEND_CMD_IDLE(controller, NAND_TWB_TIME_CYCLE);
	/* */
	smp_rmb();
	/* */
	smp_wmb();

	NFC_SEND_CMD_RB_IRQ(controller, 18);
	/* NFC_SEND_CMD_IDLE(controller, NAND_TWB_TIME_CYCLE); */

	timeout = wait_for_completion_timeout(&rb_complete, 800);
	if (timeout == 0) {
		aml_nand_msg("***[nand] rb irq timeout");
		ret = -NAND_BUSY_FAILURE;
	}

	controller_close_interrupt(controller);
	return ret;
}
int roomboot_nand_write(struct amlnand_phydev *phydev)
{
	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 chip_operation *operation = &(aml_chip->operation);	
	struct chip_ops_para *ops_para = &(aml_chip->ops_para);

	uint64_t offset , write_len, addr;
	unsigned char * buffer;
	int pages_per_blk = 0, ret = 0;
	int oob_set = 0;
	offset = devops->addr;
	write_len = devops->len;
	buffer = devops->datbuf;

	if (offset != 0){
		aml_nand_msg("Wrong addr begin");
		return -1;
	}
	if(write_len <  phydev->erasesize){
		write_len =  phydev->erasesize;
	}
	if((flash->new_type) &&((flash->new_type < 10) || (flash->new_type == SANDISK_19NM))){
		write_len =  phydev->erasesize >> 1;
	}
예제 #7
0
static int controller_queue_rb_irq(struct hw_controller *controller, unsigned char chipnr)
{
    int ret = 0, timeout = 0;

    if(chipnr != NAND_CHIP_UNDEFINE){  //skip dma operation
	    controller->select_chip(controller, chipnr);
	}

    init_completion(&controller_rb_completion);
    controller_open_interrupt();
    NFC_SEND_CMD_IDLE(controller->chip_selected, NAND_TWB_TIME_CYCLE);
    controller->cmd_ctrl(controller, NAND_CMD_STATUS, NAND_CTRL_CLE);
    NFC_SEND_CMD_IDLE(controller->chip_selected, NAND_TWB_TIME_CYCLE);
    smp_rmb();
    smp_wmb();

    NFC_SEND_CMD_RB_IRQ(18);
    //NFC_SEND_CMD_IDLE(controller->chip_selected, NAND_TWB_TIME_CYCLE);

    timeout = wait_for_completion_timeout(&controller_rb_completion, 200);
    if(timeout == 0){
        aml_nand_msg("***nand irq timeout here");
		ret = -NAND_BUSY_FAILURE;
    }

    controller_close_interrupt();

    return ret;
}
예제 #8
0
static int controller_select_chip(struct hw_controller *controller, unsigned char chipnr)
{
	int  ret = 0;

	switch (chipnr) {
		case 0:
		case 1:
		case 2:
		case 3:
			controller->chip_selected = controller->ce_enable[chipnr];
			controller->rb_received = controller->rb_enable[chipnr];
#ifdef AML_NAND_UBOOT
			for (i=0; i < controller->chip_num; i++) {
				pinmux_select_chip(controller->ce_enable[i], controller->rb_enable[i], ((controller->option & NAND_CTRL_NONE_RB) == 0));
			}
#endif

			NFC_SEND_CMD_IDLE(controller->chip_selected, 0);

			break;

		default:
			BUG();
			controller->chip_selected = CE_NOT_SEL;
			ret = -NAND_SELECT_CHIP_FAILURE;
			aml_nand_msg("failed");
			break;
	}

	return ret;
}
예제 #9
0
int amlnf_env_read(unsigned char *buf,int len)
{
	unsigned char *env_buf = NULL;
	//int ret=0, i=0;
	int ret=0;
	
	aml_nand_msg("uboot env amlnf_env_read : ####");

	if(aml_chip_env == NULL){
		return 0;
	}

	if(len > CONFIG_ENV_SIZE) 
	{
		aml_nand_msg("uboot env data len too much,%s",__func__);
		return -EFAULT;
	}

	if(aml_chip_env->uboot_env.arg_valid == 0){
		memset(buf,0x0,len);
		return 0;
	}
	
	env_buf = aml_nand_malloc(CONFIG_ENV_SIZE);
	if (env_buf == NULL){
		aml_nand_msg("nand malloc for uboot env failed");
		ret = -1;
		goto exit_err;
	}
	memset(env_buf,0,CONFIG_ENV_SIZE);

	ret = amlnand_read_info_by_name(aml_chip_env, (unsigned char *)&(aml_chip_env->uboot_env),env_buf,(unsigned char *)ENV_INFO_HEAD_MAGIC, CONFIG_ENV_SIZE);
	if (ret) {
		aml_nand_msg("nand uboot env error,%s",__func__);
		ret = -EFAULT;
		goto exit_err;
	}
	memcpy(buf,env_buf, len);
	
exit_err:
	if(env_buf){
		kfree(env_buf);
		env_buf= NULL;
	}
	return ret;
}
예제 #10
0
static int controller_hwecc_correct(struct hw_controller *controller,
	unsigned int size,
	unsigned char *oob_buf)
{
	unsigned int ecc_step_num, cur_ecc, usr_info;
	unsigned int info_times_int_len = PER_INFO_BYTE/sizeof(unsigned int);
	struct amlnand_chip *aml_chip = controller->aml_chip;
	int max_ecc = 0;
	int user_offset = 0;
	unsigned int tmp_value;

	if (controller->oob_mod == 1)
		user_offset = 4;

	if (size % controller->ecc_unit) {
		aml_nand_msg("err para size for ecc correct %x,and ecc_unit:%x",
			size,
			controller->ecc_unit);
		return -NAND_ARGUMENT_FAILURE;
	}

	controller->ecc_cnt_cur = 0;
	 for (ecc_step_num = 0;
		ecc_step_num < (size / controller->ecc_unit);
		ecc_step_num++) {
		/* check if there have uncorrectable sector */
		tmp_value = ecc_step_num*info_times_int_len + user_offset;
		usr_info = (*(u32 *)(&(controller->user_buf[tmp_value])));
		cur_ecc = NAND_ECC_CNT(usr_info);
		/*
		aml_nand_dbg("uncorrected for cur_ecc:%d, usr_buf[%d]:%x",
			cur_ecc,
			ecc_step_num,
			usr_info);
		*/
		if (cur_ecc == 0x3f) {
			controller->zero_cnt = NAND_ZERO_CNT(usr_info);
			if (max_ecc < controller->zero_cnt)
				max_ecc =  controller->zero_cnt;
			/*
			aml_nand_dbg("uncorrected for ecc_step_num:%d,
				zero_cnt:%d",
				ecc_step_num,
				controller->zero_cnt);
			*/
			return NAND_ECC_FAILURE;
		} else {
			controller->ecc_cnt_cur =
				(controller->ecc_cnt_cur > cur_ecc) ?
				controller->ecc_cnt_cur : cur_ecc;
			if (max_ecc < controller->ecc_cnt_cur)
				max_ecc =  controller->ecc_cnt_cur;
		}
	}
	aml_chip->max_ecc_per_page = max_ecc;
	return 0;
}
예제 #11
0
/*****************************************************************************
*Name         :
*Description  :
*Parameter    :
*Return       :
*Note         :
*****************************************************************************/
static int part_suspend(struct ntd_info *ntd)
{
	struct amlnand_phydev *phy;
	int ret = 0;
	phy = ntd->priv;


	if (phy == NULL) {
		aml_nand_msg("%s : get phy dev failed", __func__);
		return 0;
	}
	ret = phy->suspend(phy);
	if (ret)
		aml_nand_msg("part_suspend %s  failed!!!", phy->name);

	aml_nand_msg("part_suspend %s", phy->name);

	return ret;
}
예제 #12
0
int secure_storage_nand_write(char *buf,unsigned int len)
{
	 struct amlnand_chip *aml_chip = aml_chip_secure;
	int ret = 0;
	
	ret = nand_secure_write(aml_chip,buf,len);
	if(ret < 0){
		aml_nand_msg("secure storage nand write failed\n");
	}

	return ret;
}
예제 #13
0
int aml_key_init(struct amlnand_chip *aml_chip)
{
	int ret = 0;
	meson_key *key_ptr = NULL;
	aml_keybox_provider_t *provider; 
	
	key_ptr = aml_nand_malloc(CONFIG_KEYSIZE);
	if (key_ptr == NULL){
		aml_nand_msg("nand malloc for key_ptr failed");
		ret = -1;
		goto exit_error0;
	}
	memset(key_ptr,0x0,CONFIG_KEYSIZE);
	aml_nand_dbg("nand key: nand_key_probe. ");

	ret = amlnand_info_init(aml_chip, (unsigned char *)&(aml_chip->nand_key),(unsigned char *)key_ptr,(unsigned char *)KEY_INFO_HEAD_MAGIC, CONFIG_KEYSIZE);
	if(ret < 0){
		aml_nand_msg("invalid nand key\n");
	}
	
	aml_chip_key = aml_chip;
	nand_provider.priv=aml_chip_key;	

	provider = aml_keybox_provider_get(nand_provider.name); 
	if(provider){ 
		return ret; 
	} 
	
	ret = aml_keybox_provider_register(&nand_provider); 
	if(ret){ 
		BUG(); 
	} 
	
exit_error0:
	if(key_ptr){
		aml_nand_free(key_ptr);
		key_ptr =NULL;
	}
	return ret;
}
예제 #14
0
int aml_secure_init(struct amlnand_chip *aml_chip)
{
	int ret = 0;
	unsigned char *secure_ptr = NULL;
	
	secure_ptr = aml_nand_malloc(CONFIG_SECURE_SIZE);
	if (secure_ptr == NULL){
		aml_nand_msg("nand malloc for secure_ptr failed");
		ret = -1;
		goto exit_error0;
	}
	memset(secure_ptr,0x0,CONFIG_SECURE_SIZE);
	aml_nand_dbg("nand secure: nand_secure_probe. ");
	
	ret = amlnand_info_init(aml_chip, (unsigned char *)(&aml_chip->nand_secure),secure_ptr,(unsigned char *)SECURE_INFO_HEAD_MAGIC, CONFIG_SECURE_SIZE);
	if(ret < 0){
		aml_nand_msg("invalid nand secure_ptr\n");
		ret = -1;
		goto exit_error0;
	}

#if 0
	aml_nand_msg("nand secure debug :: save secure again !!!!");
	ret = amlnand_save_info_by_name( aml_chip,&(aml_chip->nand_secure),secure_ptr, SECURE_INFO_HEAD_MAGIC,CONFIG_SECURE_SIZE);
	if(ret < 0){
		aml_nand_msg("nand save default secure_ptr failed aigain!!");
	}

#endif
	
	aml_chip_secure = aml_chip;

exit_error0:
	if(secure_ptr){
		aml_nand_free(secure_ptr);
		secure_ptr =NULL;
	}
	return ret;
}
예제 #15
0
 int aml_nand_update_key(struct amlnand_chip * aml_chip, char *key_ptr)
{
	int ret = 0;
	int malloc_flag = 0;
	char *key_buf = NULL;
	
	if(key_buf == NULL){
		
		key_buf = kzalloc(CONFIG_KEYSIZE, GFP_KERNEL);
		malloc_flag = 1;
		if(key_buf == NULL)
			return -ENOMEM;
		memset(key_buf,0,CONFIG_KEYSIZE);
		ret = amlnand_read_info_by_name(aml_chip, (unsigned char *)&(aml_chip->nand_key),(unsigned char *)key_buf,(unsigned char *)KEY_INFO_HEAD_MAGIC, CONFIG_KEYSIZE);
		if (ret) {
			aml_nand_msg("read key error,%s\n",__func__);
			ret = -EFAULT;
			goto exit;
		}
	}else{
		key_buf = key_ptr;
	}
	
	aml_nand_msg("aml_chip->nand_key : arg_type%d valid %d,update_flag %d,valid_blk_addr %d,valid_page_addr %d",aml_chip->nand_key.arg_type,aml_chip->nand_key.arg_valid,\
		aml_chip->nand_key.update_flag,aml_chip->nand_key.valid_blk_addr,aml_chip->nand_key.valid_page_addr);
	
	ret = amlnand_save_info_by_name( aml_chip,(unsigned char *)&(aml_chip->nand_key),(unsigned char *)key_buf, (unsigned char *)KEY_INFO_HEAD_MAGIC,CONFIG_KEYSIZE);
	if(ret < 0){
		aml_nand_msg("aml_nand_update_key : save key info failed");
	}
	
exit:
	if(malloc_flag &&(key_buf)){
		kfree(key_buf);
		key_buf = NULL;
	}	
	return 0;
}
예제 #16
0
int aml_nand_update_ubootenv(struct amlnand_chip * aml_chip, char *env_ptr)
{
	int ret = 0;
	char malloc_flag = 0;
	char *env_buf = NULL;
	
	if(env_buf == NULL){
		
		env_buf = kzalloc(CONFIG_ENV_SIZE, GFP_KERNEL);
		malloc_flag = 1;
		if(env_buf == NULL)
			return -ENOMEM;
		memset(env_buf,0,CONFIG_ENV_SIZE);
		ret = amlnand_read_info_by_name(aml_chip, (unsigned char *)&(aml_chip->uboot_env),(unsigned char *)env_buf,(unsigned char *)ENV_INFO_HEAD_MAGIC, CONFIG_ENV_SIZE);
		if (ret) 
		{
			aml_nand_msg("read ubootenv error,%s\n",__func__);
			ret = -EFAULT;
			goto exit;
		}
	}else{
		env_buf = env_ptr;
	}
	
	ret = amlnand_save_info_by_name(aml_chip, (unsigned char *)&(aml_chip->uboot_env),(unsigned char *)env_buf,(unsigned char *)ENV_INFO_HEAD_MAGIC, CONFIG_ENV_SIZE);
	if(ret < 0){
		aml_nand_msg("aml_nand_update_secure : update secure failed");
	}
	
exit:	
	if(malloc_flag &&(env_buf)){
		kfree(env_buf);
		env_buf = NULL;
	}
	return 0;
}
예제 #17
0
int aml_ubootenv_init(struct amlnand_chip *aml_chip)
{
	int ret = 0;
	unsigned char * env_buf = NULL;
	aml_chip_env = aml_chip;
	
	env_buf = aml_nand_malloc(CONFIG_ENV_SIZE);
	if (env_buf == NULL){
		aml_nand_msg("nand malloc for secure_ptr failed");
		ret = -1;
		goto exit_err;
	}
	memset(env_buf,0x0,CONFIG_ENV_SIZE);
	
	ret = amlnand_info_init(aml_chip, (unsigned char *)&(aml_chip->uboot_env),env_buf,(unsigned char *)ENV_INFO_HEAD_MAGIC, CONFIG_ENV_SIZE);
	if(ret < 0){
		aml_nand_msg("aml_ubootenv_init failed\n");
		ret = -1;
		goto exit_err;
	}

	/*if(aml_chip->uboot_env.arg_valid == 0){
		memset(env_buf,0x0,CONFIG_ENV_SIZE);
		ret = amlnf_env_save(env_buf,CONFIG_ENV_SIZE);
		if(ret){
			aml_nand_msg("amlnf_env_save: save env failed");
		}
	}*/
	
exit_err:
	if(env_buf){
		kfree(env_buf);
		env_buf = NULL;
	}
	return ret;
}
예제 #18
0
static int controller_dma_timer_handle(struct hw_controller *controller)
{
    struct amlnand_chip *aml_chip = controller->aml_chip;
	struct nand_flash *flash = &(aml_chip->flash);
    int timeout, time_start;

    time_start = (flash->pagesize + flash->oobsize)*50+5000;
    init_completion(&controller_dma_completion);
    hrtimer_start(&controller->timer,ktime_set(0, time_start), HRTIMER_MODE_REL);

    timeout = wait_for_completion_timeout(&controller_dma_completion, 50);   //max 500mS
    if(timeout == 0){
       aml_nand_msg("dma time out");
       return -NAND_BUSY_FAILURE;
    }

    return 0;
}
예제 #19
0
int amlnand_get_partition_table(void)
{	
	int ret=0;

	if(part_table == NULL){
		aml_nand_msg("part_table from ACS is NULL, do not init nand");
		return -NAND_FAILED;
	}
	
	amlnand_config = aml_nand_malloc(MAX_NAND_PART_NUM * sizeof(struct amlnf_partition));
	if(!amlnand_config){
		aml_nand_dbg("amlnand_config: malloc failed!");
		ret = -NAND_MALLOC_FAILURE;
	}
	
	//show_partition_table();

	memcpy(amlnand_config, part_table, (MAX_NAND_PART_NUM * sizeof(struct amlnf_partition)));
	
	return ret;
}
예제 #20
0
static int controller_select_chip(struct hw_controller *controller,
	unsigned char chipnr)
{
	int  ret = 0;

	switch (chipnr) {
	case 0:
	case 1:
	case 2:
	case 3:
		controller->chip_selected = controller->ce_enable[chipnr];
		controller->rb_received = controller->rb_enable[chipnr];
		NFC_SEND_CMD_IDLE(controller, 0);
		break;
	default:
		BUG();
		controller->chip_selected = CE_NOT_SEL;
		ret = -NAND_SELECT_CHIP_FAILURE;
		aml_nand_msg("failed");
		break;
	}
	return ret;
}
예제 #21
0
/*****************************************************************************
*Name         :
*Description  :
*Parameter    :
*Return       :
*Note         :
*****************************************************************************/
static int part_flush(struct ntd_info *ntd)
{
	aml_nand_msg("part_flush");
	return 0;
}
예제 #22
0
/*****************************************************************************
*Name         :
*Description  :
*Parameter    :
*Return       :
*Note         :
*****************************************************************************/
void print_ntd(struct ntd_info *ntd)
{
	aml_nand_msg("ntd->name %s", ntd->name);
	aml_nand_msg("ntd->offset %llx", ntd->offset);
	aml_nand_msg("ntd->flags %lx", ntd->flags);
	aml_nand_msg("ntd->size %llx", ntd->size);
	aml_nand_msg("ntd->blocksize %ld", ntd->blocksize);
	aml_nand_msg("ntd->pagesize %ld", ntd->pagesize);
	aml_nand_msg("ntd->oobsize %ld", ntd->oobsize);
	aml_nand_msg("ntd->blocksize_shift %ld", ntd->blocksize_shift);
	aml_nand_msg("ntd->pagesize_shift %ld", ntd->pagesize_shift);
	aml_nand_msg("ntd->blocksize_mask %ld", ntd->blocksize_mask);
	aml_nand_msg("ntd->pagesize_mask %ld", ntd->pagesize_mask);
	aml_nand_msg("ntd->index %ld", ntd->index);

}
예제 #23
0
/*****************************************************************************
*Name         :
*Description  :
*Parameter    :
*Return       :
*Note         :
*****************************************************************************/
static struct ntd_info *allocate_partition(struct amlnand_phydev *master)
{
	struct ntd_info *slave;
	char *name;

	uint block = 0;

	uint block_num = 0;
	/* allocate the partition structure */
	slave = kzalloc(sizeof(*slave), GFP_KERNEL);
	/* name = kstrdup(part->name, GFP_KERNEL); */
	name = kstrdup(master->name, GFP_KERNEL);
	if (!name || !slave) {
		aml_nand_msg("\"%s\":mem alloc err while creating partitions",
			master->name);
		kfree(name);
		kfree(slave);
		return ERR_PTR(-ENOMEM);
	}

	/* set up the NTD object for this partition */
	slave->flags = master->flags;
	slave->blocksize = master->erasesize;
	slave->pagesize = master->writesize;
	slave->oobsize = master->oobavail;
	slave->name = name;
	slave->blocksize_shift = ffs(slave->blocksize) - 1;
	slave->pagesize_shift = ffs(slave->pagesize) - 1;

	slave->parts = (struct ntd_partition *)master->partitions;
	slave->nr_partitions = master->nr_partitions;

	/* slave->owner = master->owner; */
	/* slave->dev.parent = master->dev.parent; */
	/* printk("-------------------------------slave->dev.parentr  %d\n",
		slave->dev.parent); */

	slave->read_page_with_oob = read_page_with_oob;
	slave->write_page_with_oob = write_page_with_oob;
	slave->read_only_oob = read_only_oob;

	slave->block_isbad = part_block_isbad;
	slave->block_markbad = part_block_markbad;

	slave->suspend = part_suspend;
	slave->resume = part_resume;
	slave->flush = part_flush;
	slave->get_device = NULL;
	slave->put_device = NULL;

	slave->erase = part_erase;
	slave->priv = master;

	slave->offset = master->offset;
	slave->size = master->size;

	if ((slave->flags & NTD_WRITEABLE) &&
		ntd_mod_by_eb(slave->offset, slave)) {
		/* Doesn't start on a boundary of major erase size */
		/* FIXME: Let it be writable if it is on a boundary of
		 * _minor_ erase size though */
		slave->flags &= ~NTD_WRITEABLE;
		aml_nand_msg("ntd:part \"%s\" doesn't start on blk boundary",
			slave->name);
		aml_nand_msg("force read-only");
	}

	if ((slave->flags & NTD_WRITEABLE)
		&& ntd_mod_by_eb(slave->size, slave)) {
		slave->flags &= ~NTD_WRITEABLE;
		aml_nand_msg("ntd:part \"%s\" doesn't end on block",
			slave->name);
		aml_nand_msg("force read-only");
	}

	/* print_ntd(slave); */

	block_num = (uint)(slave->size >> slave->blocksize_shift);
	do {
		if (slave->block_isbad(slave, block))
			slave->badblocks++;
		block++;
		block_num--;
	} while (block_num != 0);

	/* out_register: */
	return slave;
}
static int write_uboot(struct amlnand_phydev *phydev)
{
	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 chip_operation *operation = &(aml_chip->operation);	
	struct chip_ops_para *ops_para = &(aml_chip->ops_para);
	struct en_slc_info *slc_info = &(controller->slc_info);
	unsigned char *fill_buf;
	unsigned char *oob_buf, *page0_buf, tmp_bch_mode, tmp_user_mode, tmp_ecc_limit, tmp_ecc_max,tmp_rand;
	unsigned configure_data, pages_per_blk, oobsize, page_size, tmp_size,priv_lsb,ops_tem; 
	unsigned short tmp_ecc_unit, tmp_ecc_bytes, tmp_ecc_steps;
	uint64_t addr, writelen = 0, len = 0;
	int chip_num=1, nand_read_info, new_nand_type, i, ret = 0;
	unsigned char  *tmp_buf;
	
	if((devops->addr + devops->len) >  phydev->size){
		aml_nand_msg("writeboot:out of space and addr:%llx len:%llx phydev->offset:%llx phydev->size:%llx",\
						devops->addr, devops->len, phydev->offset, phydev->size);
		return -NAND_ARGUMENT_FAILURE;
	}

	if((devops->len == 0) && (devops->ooblen == 0)){
		aml_nand_msg("len equal zero here");
		return NAND_SUCCESS;
	}

	if(devops->addr != 0){
		aml_nand_msg("addr do not equal zero here for uboot write");
		return NAND_SUCCESS;
	}

	tmp_ecc_unit = controller->ecc_unit;
	tmp_ecc_bytes = controller->ecc_bytes;
	tmp_bch_mode = controller->bch_mode;
	tmp_user_mode	= controller->user_mode;
	tmp_ecc_limit = controller->ecc_cnt_limit;
	tmp_ecc_max = controller->ecc_max;
	tmp_ecc_steps = controller->ecc_steps;
	tmp_rand = controller->ran_mode;
	if (controller->bch_mode == NAND_ECC_BCH_SHORT){
		page_size = (flash->pagesize / 512) * NAND_ECC_UNIT_SHORT;
	}
	
	oobsize = controller->ecc_steps*controller->user_mode;

	tmp_size = phydev->writesize;
	//phydev->writesize = page_size;

	//amlnand_get_device(aml_chip, CHIP_WRITING);

	oob_buf = aml_nand_malloc(oobsize);
	if(oob_buf == NULL){
		aml_nand_msg("malloc failed and oobavail:%d", phydev->oobavail);
		ret = -NAND_MALLOC_FAILURE;
		goto error_exit;
	}
	memset(oob_buf,0x0,oobsize);
	page0_buf = aml_nand_malloc(flash->pagesize);
	if(page0_buf == NULL){
		aml_nand_msg("malloc failed and oobavail:%d", flash->pagesize);
		ret = -NAND_MALLOC_FAILURE;
		goto error_exit;
	}
	memset(page0_buf,0x0,flash->pagesize);
	len = devops->len;
	for (i=0; i<oobsize; i+=2){
		oob_buf[i] = 0x55;
		oob_buf[i+1] = 0xaa;
	}
	fill_buf = aml_nand_malloc(flash->pagesize);
	if(fill_buf == NULL){
		aml_nand_msg("malloc failed and oobavail:%d", flash->pagesize);
		ret = -NAND_MALLOC_FAILURE;
		goto error_exit;
	}
	memset(fill_buf,0xff,(flash->pagesize + flash->oobsize));
	
	//clear ops_para here
	memset(ops_para, 0, sizeof(struct chip_ops_para));
	addr = phydev->offset + devops->addr;
	ops_para->option = phydev->option;	
	ops_para->data_buf = devops->datbuf;	
	ops_para->oob_buf = oob_buf;
	
	if((flash->new_type) &&((flash->new_type < 10) || (flash->new_type == SANDISK_19NM)))
	ops_para->option |= DEV_SLC_MODE;
	
	configure_data = NFC_CMD_N2M(controller->ran_mode, controller->bch_mode, 0, (controller->ecc_unit >> 3), controller->ecc_steps);	

	//configure_data = NFC_CMD_N2M(controller->ran_mode, NAND_ECC_BCH60_1K, 1, (controller->ecc_unit >> 3), controller->ecc_steps); 
	pages_per_blk = flash->blocksize / flash->pagesize;
	aml_nand_msg("configure_data:%x, pages_per_blk:%x", configure_data, pages_per_blk);

	nand_boot_info_prepare(phydev,page0_buf);
	unsigned char * lazy_buf = devops->datbuf;
	for(i=0; i<BOOT_COPY_NUM; i++){
		writelen = 0;
		addr = 0;
		addr += flash->pagesize*(BOOT_PAGES_PER_COPY*i);
		ops_para->data_buf = lazy_buf;	
		devops->datbuf = lazy_buf;
		while(1){
			if(((((unsigned)addr / flash->pagesize)) % BOOT_PAGES_PER_COPY) == 0){
				uboot_set_ran_mode(phydev);
				ops_para->data_buf = page0_buf;
				
				page_size = (flash->pagesize / 512) * NAND_ECC_UNIT_SHORT;
				phydev->writesize = page_size;
#if 1
				controller->ecc_unit = NAND_ECC_UNIT_SHORT;
				controller->ecc_bytes = NAND_BCH60_1K_ECC_SIZE;
				controller->bch_mode = NAND_ECC_BCH_SHORT;
				controller->user_mode = 2;			
				controller->ecc_cnt_limit = 55;
				controller->ecc_max = 60;
				controller->ecc_steps = (flash->pagesize+flash->oobsize)/512;
#endif 	
			}
			ops_para->page_addr = ((unsigned)addr / flash->pagesize);// /controller->chip_num;	
			ops_tem = ops_para->page_addr ;
			if((ops_para->option & DEV_SLC_MODE)) {
				if((flash->new_type > 0) && (flash->new_type < 10))
					ops_para->page_addr = (ops_para->page_addr & (~(pages_per_blk -1))) |(slc_info->pagelist[ops_para->page_addr % 256]);
				if (flash->new_type == SANDISK_19NM) 
					ops_para->page_addr = (ops_para->page_addr & (~(pages_per_blk -1))) |((ops_para->page_addr % pages_per_blk) << 1);
			}
#if 1
			if(flash->new_type ==HYNIX_1YNM_8GB) {
				if((ops_tem % 256)>1) {
					priv_lsb =  (ops_tem & (~(pages_per_blk -1))) |(slc_info->pagelist[(ops_tem % 256)-1]);
				ops_tem = ops_para->page_addr ;
				while(ops_tem > (priv_lsb+1)) {
				ops_para->data_buf = fill_buf;				
				controller->bch_mode =NAND_ECC_NONE;
				ops_para->page_addr = priv_lsb+1;
				 operation->write_page(aml_chip);
				 priv_lsb++;
					}
				ops_para->page_addr = ops_tem;
				ops_para->data_buf = devops->datbuf;
				controller->ecc_unit = tmp_ecc_unit;
				controller->ecc_bytes = tmp_ecc_bytes;
				controller->bch_mode =tmp_bch_mode;
				controller->user_mode =tmp_user_mode;
				controller->ecc_cnt_limit =tmp_ecc_limit;
				controller->ecc_max =tmp_ecc_max;	
				controller->ecc_steps = tmp_ecc_steps;
				phydev->writesize = tmp_size;
				controller->ran_mode = tmp_rand;
				}	
			}
	#endif
			if(((((unsigned)addr / flash->pagesize)) % BOOT_PAGES_PER_COPY) != 0)
					ops_para->data_buf = devops->datbuf;
			ret = operation->write_page(aml_chip);			
			if(ret<0){			
				aml_nand_msg("fail page_addr:%d", ops_para->page_addr); 		
				break;
			}
						
			if((((unsigned)addr / flash->pagesize) % BOOT_PAGES_PER_COPY) == 0){
				controller->ran_mode = 1;
				addr += flash->pagesize;
				ops_para->data_buf = devops->datbuf;				
#if 1
				controller->ecc_unit = tmp_ecc_unit;
				controller->ecc_bytes = tmp_ecc_bytes;
				controller->bch_mode =tmp_bch_mode;
				controller->user_mode =tmp_user_mode;
				controller->ecc_cnt_limit =tmp_ecc_limit;
				controller->ecc_max =tmp_ecc_max;	
				controller->ecc_steps = tmp_ecc_steps;
				phydev->writesize = tmp_size;
#endif
				continue;
			}	
			
			addr += flash->pagesize;
			devops->datbuf += phydev->writesize;
			writelen += phydev->writesize;
			
			if((writelen >= UBOOT_WRITE_SIZE)&&(writelen < phydev->erasesize)){
				devops->datbuf = fill_buf;
			}
			if((writelen >= (len-flash->pagesize))||((unsigned)addr%flash->blocksize ==0)){
				break;
			}
		}
	}
	
	devops->retlen = writelen;
	
error_exit: 
	//amlnand_release_device(aml_chip);
	
	controller->ran_mode = 1;
	controller->ecc_unit = tmp_ecc_unit;
	controller->ecc_bytes = tmp_ecc_bytes;
	controller->bch_mode =tmp_bch_mode;
	controller->user_mode =tmp_user_mode;
	controller->ecc_cnt_limit =tmp_ecc_limit;
	controller->ecc_max =tmp_ecc_max;	
	controller->ecc_steps = tmp_ecc_steps;
	phydev->writesize = tmp_size;
	if(fill_buf){
		kfree(fill_buf);
		fill_buf =NULL;
	}
	if(page0_buf){
		kfree(page0_buf);
		page0_buf =NULL;
	}
	
	return ret;
}
static int read_uboot(struct amlnand_phydev *phydev)
{
	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 chip_operation *operation = &(aml_chip->operation);	
	struct chip_ops_para *ops_para = &(aml_chip->ops_para);
	struct en_slc_info *slc_info = &(controller->slc_info);
	
	unsigned configure_data, pages_per_blk, configure_data_w, pages_per_blk_w, page_size, tmp_size;
	unsigned char tmp_bch_mode, tmp_user_mode, tmp_ecc_limit, tmp_ecc_max;
	unsigned short tmp_ecc_unit, tmp_ecc_bytes, tmp_ecc_steps;
	uint64_t addr, readlen = 0, len = 0;
	int  ret = 0;

	if((devops->addr + devops->len) >  phydev->size){
		aml_nand_msg("read uboot:out of space and addr:%llx len:%llx phydev->offset:%llx phydev->size:%llx",\
						devops->addr, devops->len, phydev->offset, phydev->size);
		return -NAND_ARGUMENT_FAILURE;
	}

	if((devops->len == 0) && (devops->ooblen == 0)){
		aml_nand_msg("len equal zero here");
		return NAND_SUCCESS;
	}

	tmp_ecc_unit = controller->ecc_unit;
	tmp_ecc_bytes = controller->ecc_bytes;
	tmp_bch_mode = controller->bch_mode;
	tmp_user_mode	= controller->user_mode;
	tmp_ecc_limit = controller->ecc_cnt_limit;
	tmp_ecc_max = controller->ecc_max;
	tmp_ecc_steps = controller->ecc_steps;


	if (controller->bch_mode == NAND_ECC_BCH_SHORT){
		page_size = (flash->pagesize / 512) * NAND_ECC_UNIT_SHORT;
	}

	tmp_size = phydev->writesize;
	//phydev->writesize = page_size;

	//amlnand_get_device(aml_chip, CHIP_READING);

	//clear ops_para here
	memset(ops_para, 0, sizeof(struct chip_ops_para));

	if(devops->len == 0){
		len = phydev->writesize;
		ops_para->ooblen = devops->ooblen;
	}
	else{
		len = devops->len;
		ops_para->ooblen = devops->ooblen;
	}
	
	addr = phydev->offset + devops->addr;
	ops_para->data_buf = devops->datbuf;	
	ops_para->option = phydev->option;	
	ops_para->oob_buf = devops->oobbuf;
	
	if(devops->mode == NAND_SOFT_ECC){
		ops_para->option |= DEV_ECC_SOFT_MODE;
	}
	
	if((flash->new_type) &&((flash->new_type < 10) || (flash->new_type == SANDISK_19NM)))
		ops_para->option |= DEV_SLC_MODE;
	
	pages_per_blk = flash->blocksize / flash->pagesize; 
	configure_data = NFC_CMD_N2M(controller->ran_mode, controller->bch_mode, 0, (controller->ecc_unit >> 3), controller->ecc_steps);
	while(1){
		if ((((unsigned)addr / flash->pagesize )%BOOT_PAGES_PER_COPY) == 0){
				uboot_set_ran_mode(phydev);
				page_size = (flash->pagesize / 512) * NAND_ECC_UNIT_SHORT;
				phydev->writesize = page_size;
#if 1
				controller->ecc_unit = NAND_ECC_UNIT_SHORT;
				controller->ecc_bytes = NAND_BCH60_1K_ECC_SIZE;
				controller->bch_mode = NAND_ECC_BCH_SHORT;
				controller->user_mode = 2;			
				controller->ecc_cnt_limit = 55;
				controller->ecc_max = 60;
				controller->ecc_steps = (flash->pagesize+flash->oobsize)/512;
#endif	
			
		}else{		
			controller->ran_mode = 1;
		}
		
		ops_para->page_addr = ((unsigned)addr / flash->pagesize);// /controller->chip_num;	
		if((ops_para->option & DEV_SLC_MODE)) {
			if((flash->new_type > 0) && (flash->new_type <10))
				ops_para->page_addr = (ops_para->page_addr & (~(pages_per_blk -1))) |(slc_info->pagelist[ops_para->page_addr % 256]);
			if (flash->new_type == SANDISK_19NM) 
				ops_para->page_addr = (ops_para->page_addr & (~(pages_per_blk -1))) |((ops_para->page_addr % pages_per_blk) << 1);
		}
		
		ret = operation->read_page(aml_chip);
		if((ops_para->ecc_err) || (ret<0)){			
			aml_nand_msg("fail page_addr:%d", ops_para->page_addr); 		
			break;
		}
							
		//check info page
		if((!strncmp((char*)phydev->name, NAND_BOOT_NAME, strlen((const char*)NAND_BOOT_NAME))) 
				&& (((((unsigned)addr / flash->pagesize ))%BOOT_PAGES_PER_COPY) == 0)){
				
			controller->ran_mode = 1;  // 1
			
			
			memcpy((unsigned char *)(&configure_data_w), ops_para->data_buf, sizeof(int));
			memcpy((unsigned char *)(&pages_per_blk_w), ops_para->data_buf+4, sizeof(int));
			
			aml_nand_msg("configure_data:%x, pages_per_blk:%x", configure_data, pages_per_blk);
			/*if ((pages_per_blk_w != pages_per_blk) || (configure_data_w != configure_data)){
				aml_nand_msg("nand boot check data failed, and configure_data_w:0x%x, pages_per_blk_w:0x%x",\
					configure_data_w, pages_per_blk_w);
			}*/
			addr += flash->pagesize;	
#if 1
			controller->ecc_unit = tmp_ecc_unit;
			controller->ecc_bytes = tmp_ecc_bytes;
			controller->bch_mode =tmp_bch_mode;
			controller->user_mode =tmp_user_mode;
			controller->ecc_cnt_limit =tmp_ecc_limit;
			controller->ecc_max =tmp_ecc_max;		
			controller->ecc_steps = tmp_ecc_steps;
			phydev->writesize = tmp_size;
#endif
			continue;
		}
		
		addr += flash->pagesize;		
		ops_para->data_buf += phydev->writesize;
		readlen += phydev->writesize;
		
		if(readlen >= len){
			break;
		}
	}

	devops->retlen = readlen;
	
	//amlnand_release_device(aml_chip);

	if(!ret){
		if(ops_para->ecc_err){
			ret = NAND_ECC_FAILURE;
		}
		/*else if(ops_para->bit_flip){
			ret = NAND_BITFLIP_FAILURE;
		}*/
	}
	
	controller->ran_mode = 1;		
	controller->ecc_unit = tmp_ecc_unit;
	controller->ecc_bytes = tmp_ecc_bytes;
	controller->bch_mode =tmp_bch_mode;
	controller->user_mode =tmp_user_mode;
	controller->ecc_cnt_limit =tmp_ecc_limit;
	controller->ecc_max =tmp_ecc_max;		
	controller->ecc_steps = tmp_ecc_steps;
	phydev->writesize = tmp_size;
		
	return ret;
}