mtd,ubi,ubifs: sync with linux v3.15
snyc with linux v3.15:
commit 1860e379875dfe7271c649058aeddffe5afd9d0d
Author: Linus Torvalds <torvalds@linux-foundation.org>
Date:   Sun Jun 8 11:19:54 2014 -0700
    Linux 3.15
Signed-off-by: Heiko Schocher <hs@denx.de>
Cc: Scott Wood <scottwood@freescale.com>
Cc: Tom Rini <trini@ti.com>
			
			
This commit is contained in:
		
							parent
							
								
									ddf7bcfa6c
								
							
						
					
					
						commit
						4e67c57125
					
				|  | @ -1011,14 +1011,14 @@ EXPORT_SYMBOL_GPL(mtd_read_oob); | ||||||
|  * devices. The user data is one time programmable but the factory data is read |  * devices. The user data is one time programmable but the factory data is read | ||||||
|  * only. |  * only. | ||||||
|  */ |  */ | ||||||
| int mtd_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, | int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, | ||||||
| 			   size_t len) | 			   struct otp_info *buf) | ||||||
| { | { | ||||||
| 	if (!mtd->_get_fact_prot_info) | 	if (!mtd->_get_fact_prot_info) | ||||||
| 		return -EOPNOTSUPP; | 		return -EOPNOTSUPP; | ||||||
| 	if (!len) | 	if (!len) | ||||||
| 		return 0; | 		return 0; | ||||||
| 	return mtd->_get_fact_prot_info(mtd, buf, len); | 	return mtd->_get_fact_prot_info(mtd, len, retlen, buf); | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(mtd_get_fact_prot_info); | EXPORT_SYMBOL_GPL(mtd_get_fact_prot_info); | ||||||
| 
 | 
 | ||||||
|  | @ -1034,14 +1034,14 @@ int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(mtd_read_fact_prot_reg); | EXPORT_SYMBOL_GPL(mtd_read_fact_prot_reg); | ||||||
| 
 | 
 | ||||||
| int mtd_get_user_prot_info(struct mtd_info *mtd, struct otp_info *buf, | int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, | ||||||
| 			   size_t len) | 			   struct otp_info *buf) | ||||||
| { | { | ||||||
| 	if (!mtd->_get_user_prot_info) | 	if (!mtd->_get_user_prot_info) | ||||||
| 		return -EOPNOTSUPP; | 		return -EOPNOTSUPP; | ||||||
| 	if (!len) | 	if (!len) | ||||||
| 		return 0; | 		return 0; | ||||||
| 	return mtd->_get_user_prot_info(mtd, buf, len); | 	return mtd->_get_user_prot_info(mtd, len, retlen, buf); | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(mtd_get_user_prot_info); | EXPORT_SYMBOL_GPL(mtd_get_user_prot_info); | ||||||
| 
 | 
 | ||||||
|  | @ -1060,12 +1060,22 @@ EXPORT_SYMBOL_GPL(mtd_read_user_prot_reg); | ||||||
| int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, | int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, | ||||||
| 			    size_t *retlen, u_char *buf) | 			    size_t *retlen, u_char *buf) | ||||||
| { | { | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
| 	*retlen = 0; | 	*retlen = 0; | ||||||
| 	if (!mtd->_write_user_prot_reg) | 	if (!mtd->_write_user_prot_reg) | ||||||
| 		return -EOPNOTSUPP; | 		return -EOPNOTSUPP; | ||||||
| 	if (!len) | 	if (!len) | ||||||
| 		return 0; | 		return 0; | ||||||
| 	return mtd->_write_user_prot_reg(mtd, to, len, retlen, buf); | 	ret = mtd->_write_user_prot_reg(mtd, to, len, retlen, buf); | ||||||
|  | 	if (ret) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * If no data could be written at all, we are out of memory and | ||||||
|  | 	 * must return -ENOSPC. | ||||||
|  | 	 */ | ||||||
|  | 	return (*retlen) ? 0 : -ENOSPC; | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(mtd_write_user_prot_reg); | EXPORT_SYMBOL_GPL(mtd_write_user_prot_reg); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -178,11 +178,12 @@ static int part_read_user_prot_reg(struct mtd_info *mtd, loff_t from, | ||||||
| 						 retlen, buf); | 						 retlen, buf); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int part_get_user_prot_info(struct mtd_info *mtd, | static int part_get_user_prot_info(struct mtd_info *mtd, size_t len, | ||||||
| 		struct otp_info *buf, size_t len) | 				   size_t *retlen, struct otp_info *buf) | ||||||
| { | { | ||||||
| 	struct mtd_part *part = PART(mtd); | 	struct mtd_part *part = PART(mtd); | ||||||
| 	return part->master->_get_user_prot_info(part->master, buf, len); | 	return part->master->_get_user_prot_info(part->master, len, retlen, | ||||||
|  | 						 buf); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, | static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, | ||||||
|  | @ -193,11 +194,12 @@ static int part_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, | ||||||
| 						 retlen, buf); | 						 retlen, buf); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int part_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, | static int part_get_fact_prot_info(struct mtd_info *mtd, size_t len, | ||||||
| 		size_t len) | 				   size_t *retlen, struct otp_info *buf) | ||||||
| { | { | ||||||
| 	struct mtd_part *part = PART(mtd); | 	struct mtd_part *part = PART(mtd); | ||||||
| 	return part->master->_get_fact_prot_info(part->master, buf, len); | 	return part->master->_get_fact_prot_info(part->master, len, retlen, | ||||||
|  | 						 buf); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int part_write(struct mtd_info *mtd, loff_t to, size_t len, | static int part_write(struct mtd_info *mtd, loff_t to, size_t len, | ||||||
|  |  | ||||||
|  | @ -744,7 +744,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, | ||||||
| 	/* Serially input address */ | 	/* Serially input address */ | ||||||
| 	if (column != -1) { | 	if (column != -1) { | ||||||
| 		/* Adjust columns for 16 bit buswidth */ | 		/* Adjust columns for 16 bit buswidth */ | ||||||
| 		if ((chip->options & NAND_BUSWIDTH_16) && | 		if (chip->options & NAND_BUSWIDTH_16 && | ||||||
| 				!nand_opcode_8bits(command)) | 				!nand_opcode_8bits(command)) | ||||||
| 			column >>= 1; | 			column >>= 1; | ||||||
| 		chip->cmd_ctrl(mtd, column, ctrl); | 		chip->cmd_ctrl(mtd, column, ctrl); | ||||||
|  | @ -837,7 +837,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, | ||||||
| 		/* Serially input address */ | 		/* Serially input address */ | ||||||
| 		if (column != -1) { | 		if (column != -1) { | ||||||
| 			/* Adjust columns for 16 bit buswidth */ | 			/* Adjust columns for 16 bit buswidth */ | ||||||
| 			if ((chip->options & NAND_BUSWIDTH_16) && | 			if (chip->options & NAND_BUSWIDTH_16 && | ||||||
| 					!nand_opcode_8bits(command)) | 					!nand_opcode_8bits(command)) | ||||||
| 				column >>= 1; | 				column >>= 1; | ||||||
| 			chip->cmd_ctrl(mtd, column, ctrl); | 			chip->cmd_ctrl(mtd, column, ctrl); | ||||||
|  | @ -1346,9 +1346,11 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, | ||||||
|  * @data_offs: offset of requested data within the page |  * @data_offs: offset of requested data within the page | ||||||
|  * @readlen: data length |  * @readlen: data length | ||||||
|  * @bufpoi: buffer to store read data |  * @bufpoi: buffer to store read data | ||||||
|  |  * @page: page number to read | ||||||
|  */ |  */ | ||||||
| static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | ||||||
| 			uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi) | 			uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, | ||||||
|  | 			int page) | ||||||
| { | { | ||||||
| 	int start_step, end_step, num_steps; | 	int start_step, end_step, num_steps; | ||||||
| 	uint32_t *eccpos = chip->ecc.layout->eccpos; | 	uint32_t *eccpos = chip->ecc.layout->eccpos; | ||||||
|  | @ -1356,13 +1358,14 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | ||||||
| 	int data_col_addr, i, gaps = 0; | 	int data_col_addr, i, gaps = 0; | ||||||
| 	int datafrag_len, eccfrag_len, aligned_len, aligned_pos; | 	int datafrag_len, eccfrag_len, aligned_len, aligned_pos; | ||||||
| 	int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; | 	int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; | ||||||
| 	int index = 0; | 	int index; | ||||||
| 	unsigned int max_bitflips = 0; | 	unsigned int max_bitflips = 0; | ||||||
| 
 | 
 | ||||||
| 	/* Column address within the page aligned to ECC size (256bytes) */ | 	/* Column address within the page aligned to ECC size (256bytes) */ | ||||||
| 	start_step = data_offs / chip->ecc.size; | 	start_step = data_offs / chip->ecc.size; | ||||||
| 	end_step = (data_offs + readlen - 1) / chip->ecc.size; | 	end_step = (data_offs + readlen - 1) / chip->ecc.size; | ||||||
| 	num_steps = end_step - start_step + 1; | 	num_steps = end_step - start_step + 1; | ||||||
|  | 	index = start_step * chip->ecc.bytes; | ||||||
| 
 | 
 | ||||||
| 	/* Data size aligned to ECC ecc.size */ | 	/* Data size aligned to ECC ecc.size */ | ||||||
| 	datafrag_len = num_steps * chip->ecc.size; | 	datafrag_len = num_steps * chip->ecc.size; | ||||||
|  | @ -1399,8 +1402,6 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, | ||||||
| 		 * Send the command to read the particular ECC bytes take care | 		 * Send the command to read the particular ECC bytes take care | ||||||
| 		 * about buswidth alignment in read_buf. | 		 * about buswidth alignment in read_buf. | ||||||
| 		 */ | 		 */ | ||||||
| 		index = start_step * chip->ecc.bytes; |  | ||||||
| 
 |  | ||||||
| 		aligned_pos = eccpos[index] & ~(busw - 1); | 		aligned_pos = eccpos[index] & ~(busw - 1); | ||||||
| 		aligned_len = eccfrag_len; | 		aligned_len = eccfrag_len; | ||||||
| 		if (eccpos[index] & (busw - 1)) | 		if (eccpos[index] & (busw - 1)) | ||||||
|  | @ -1725,7 +1726,8 @@ read_retry: | ||||||
| 			else if (!aligned && NAND_HAS_SUBPAGE_READ(chip) && | 			else if (!aligned && NAND_HAS_SUBPAGE_READ(chip) && | ||||||
| 				 !oob) | 				 !oob) | ||||||
| 				ret = chip->ecc.read_subpage(mtd, chip, | 				ret = chip->ecc.read_subpage(mtd, chip, | ||||||
| 							col, bytes, bufpoi); | 							col, bytes, bufpoi, | ||||||
|  | 							page); | ||||||
| 			else | 			else | ||||||
| 				ret = chip->ecc.read_page(mtd, chip, bufpoi, | 				ret = chip->ecc.read_page(mtd, chip, bufpoi, | ||||||
| 							  oob_required, page); | 							  oob_required, page); | ||||||
|  | @ -2189,7 +2191,7 @@ static int nand_write_page_raw_syndrome(struct mtd_info *mtd, | ||||||
| 			oob += chip->ecc.prepad; | 			oob += chip->ecc.prepad; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		chip->read_buf(mtd, oob, eccbytes); | 		chip->write_buf(mtd, oob, eccbytes); | ||||||
| 		oob += eccbytes; | 		oob += eccbytes; | ||||||
| 
 | 
 | ||||||
| 		if (chip->ecc.postpad) { | 		if (chip->ecc.postpad) { | ||||||
|  | @ -3154,7 +3156,6 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_SYS_NAND_ONFI_DETECTION |  | ||||||
| /* Sanitize ONFI strings so we can safely print them */ | /* Sanitize ONFI strings so we can safely print them */ | ||||||
| #ifndef __UBOOT__ | #ifndef __UBOOT__ | ||||||
| static void sanitize_string(uint8_t *s, size_t len) | static void sanitize_string(uint8_t *s, size_t len) | ||||||
|  | @ -3189,6 +3190,7 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len) | ||||||
| 	return crc; | 	return crc; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_SYS_NAND_ONFI_DETECTION | ||||||
| /* Parse the Extended Parameter Page. */ | /* Parse the Extended Parameter Page. */ | ||||||
| static int nand_flash_detect_ext_param_page(struct mtd_info *mtd, | static int nand_flash_detect_ext_param_page(struct mtd_info *mtd, | ||||||
| 		struct nand_chip *chip, struct nand_onfi_params *p) | 		struct nand_chip *chip, struct nand_onfi_params *p) | ||||||
|  | @ -3304,15 +3306,6 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, | ||||||
| 		chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I') | 		chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I') | ||||||
| 		return 0; | 		return 0; | ||||||
| 
 | 
 | ||||||
| 	/*
 |  | ||||||
| 	 * ONFI must be probed in 8-bit mode or with NAND_BUSWIDTH_AUTO, not |  | ||||||
| 	 * with NAND_BUSWIDTH_16 |  | ||||||
| 	 */ |  | ||||||
| 	if (chip->options & NAND_BUSWIDTH_16) { |  | ||||||
| 		pr_err("ONFI cannot be probed in 16-bit mode; aborting\n"); |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1); | 	chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1); | ||||||
| 	for (i = 0; i < 3; i++) { | 	for (i = 0; i < 3; i++) { | ||||||
| 		for (j = 0; j < sizeof(*p); j++) | 		for (j = 0; j < sizeof(*p); j++) | ||||||
|  | @ -3408,6 +3401,87 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * Check if the NAND chip is JEDEC compliant, returns 1 if it is, 0 otherwise. | ||||||
|  |  */ | ||||||
|  | static int nand_flash_detect_jedec(struct mtd_info *mtd, struct nand_chip *chip, | ||||||
|  | 					int *busw) | ||||||
|  | { | ||||||
|  | 	struct nand_jedec_params *p = &chip->jedec_params; | ||||||
|  | 	struct jedec_ecc_info *ecc; | ||||||
|  | 	int val; | ||||||
|  | 	int i, j; | ||||||
|  | 
 | ||||||
|  | 	/* Try JEDEC for unknown chip or LP */ | ||||||
|  | 	chip->cmdfunc(mtd, NAND_CMD_READID, 0x40, -1); | ||||||
|  | 	if (chip->read_byte(mtd) != 'J' || chip->read_byte(mtd) != 'E' || | ||||||
|  | 		chip->read_byte(mtd) != 'D' || chip->read_byte(mtd) != 'E' || | ||||||
|  | 		chip->read_byte(mtd) != 'C') | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	chip->cmdfunc(mtd, NAND_CMD_PARAM, 0x40, -1); | ||||||
|  | 	for (i = 0; i < 3; i++) { | ||||||
|  | 		for (j = 0; j < sizeof(*p); j++) | ||||||
|  | 			((uint8_t *)p)[j] = chip->read_byte(mtd); | ||||||
|  | 
 | ||||||
|  | 		if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 510) == | ||||||
|  | 				le16_to_cpu(p->crc)) | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (i == 3) { | ||||||
|  | 		pr_err("Could not find valid JEDEC parameter page; aborting\n"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Check version */ | ||||||
|  | 	val = le16_to_cpu(p->revision); | ||||||
|  | 	if (val & (1 << 2)) | ||||||
|  | 		chip->jedec_version = 10; | ||||||
|  | 	else if (val & (1 << 1)) | ||||||
|  | 		chip->jedec_version = 1; /* vendor specific version */ | ||||||
|  | 
 | ||||||
|  | 	if (!chip->jedec_version) { | ||||||
|  | 		pr_info("unsupported JEDEC version: %d\n", val); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sanitize_string(p->manufacturer, sizeof(p->manufacturer)); | ||||||
|  | 	sanitize_string(p->model, sizeof(p->model)); | ||||||
|  | 	if (!mtd->name) | ||||||
|  | 		mtd->name = p->model; | ||||||
|  | 
 | ||||||
|  | 	mtd->writesize = le32_to_cpu(p->byte_per_page); | ||||||
|  | 
 | ||||||
|  | 	/* Please reference to the comment for nand_flash_detect_onfi. */ | ||||||
|  | 	mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1); | ||||||
|  | 	mtd->erasesize *= mtd->writesize; | ||||||
|  | 
 | ||||||
|  | 	mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); | ||||||
|  | 
 | ||||||
|  | 	/* Please reference to the comment for nand_flash_detect_onfi. */ | ||||||
|  | 	chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1); | ||||||
|  | 	chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count; | ||||||
|  | 	chip->bits_per_cell = p->bits_per_cell; | ||||||
|  | 
 | ||||||
|  | 	if (jedec_feature(chip) & JEDEC_FEATURE_16_BIT_BUS) | ||||||
|  | 		*busw = NAND_BUSWIDTH_16; | ||||||
|  | 	else | ||||||
|  | 		*busw = 0; | ||||||
|  | 
 | ||||||
|  | 	/* ECC info */ | ||||||
|  | 	ecc = &p->ecc_info[0]; | ||||||
|  | 
 | ||||||
|  | 	if (ecc->codeword_size >= 9) { | ||||||
|  | 		chip->ecc_strength_ds = ecc->ecc_bits; | ||||||
|  | 		chip->ecc_step_ds = 1 << ecc->codeword_size; | ||||||
|  | 	} else { | ||||||
|  | 		pr_warn("Invalid codeword size\n"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * nand_id_has_period - Check if an ID string has a given wraparound period |  * nand_id_has_period - Check if an ID string has a given wraparound period | ||||||
|  * @id_data: the ID string |  * @id_data: the ID string | ||||||
|  | @ -3718,10 +3792,10 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip, | ||||||
|  */ |  */ | ||||||
| static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | ||||||
| 						  struct nand_chip *chip, | 						  struct nand_chip *chip, | ||||||
| 						  int busw, |  | ||||||
| 						  int *maf_id, int *dev_id, | 						  int *maf_id, int *dev_id, | ||||||
| 						  struct nand_flash_dev *type) | 						  struct nand_flash_dev *type) | ||||||
| { | { | ||||||
|  | 	int busw; | ||||||
| 	int i, maf_idx; | 	int i, maf_idx; | ||||||
| 	u8 id_data[8]; | 	u8 id_data[8]; | ||||||
| 
 | 
 | ||||||
|  | @ -3777,6 +3851,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | ||||||
| 		/* Check is chip is ONFI compliant */ | 		/* Check is chip is ONFI compliant */ | ||||||
| 		if (nand_flash_detect_onfi(mtd, chip, &busw)) | 		if (nand_flash_detect_onfi(mtd, chip, &busw)) | ||||||
| 			goto ident_done; | 			goto ident_done; | ||||||
|  | 
 | ||||||
|  | 		/* Check if the chip is JEDEC compliant */ | ||||||
|  | 		if (nand_flash_detect_jedec(mtd, chip, &busw)) | ||||||
|  | 			goto ident_done; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!type->name) | 	if (!type->name) | ||||||
|  | @ -3856,12 +3934,29 @@ ident_done: | ||||||
| 
 | 
 | ||||||
| 	pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n", | 	pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n", | ||||||
| 		*maf_id, *dev_id); | 		*maf_id, *dev_id); | ||||||
|  | 
 | ||||||
| #ifdef CONFIG_SYS_NAND_ONFI_DETECTION | #ifdef CONFIG_SYS_NAND_ONFI_DETECTION | ||||||
| 	pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, | 	if (chip->onfi_version) | ||||||
| 		chip->onfi_version ? chip->onfi_params.model : type->name); | 		pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, | ||||||
|  | 				chip->onfi_params.model); | ||||||
|  | 	else if (chip->jedec_version) | ||||||
|  | 		pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, | ||||||
|  | 				chip->jedec_params.model); | ||||||
|  | 	else | ||||||
|  | 		pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, | ||||||
|  | 				type->name); | ||||||
| #else | #else | ||||||
| 	pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, type->name); | 	if (chip->jedec_version) | ||||||
|  | 		pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, | ||||||
|  | 				chip->jedec_params.model); | ||||||
|  | 	else | ||||||
|  | 		pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, | ||||||
|  | 				type->name); | ||||||
|  | 
 | ||||||
|  | 	pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, | ||||||
|  | 		type->name); | ||||||
| #endif | #endif | ||||||
|  | 
 | ||||||
| 	pr_info("%dMiB, %s, page size: %d, OOB size: %d\n", | 	pr_info("%dMiB, %s, page size: %d, OOB size: %d\n", | ||||||
| 		(int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC", | 		(int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC", | ||||||
| 		mtd->writesize, mtd->oobsize); | 		mtd->writesize, mtd->oobsize); | ||||||
|  | @ -3882,18 +3977,16 @@ ident_done: | ||||||
| int nand_scan_ident(struct mtd_info *mtd, int maxchips, | int nand_scan_ident(struct mtd_info *mtd, int maxchips, | ||||||
| 		    struct nand_flash_dev *table) | 		    struct nand_flash_dev *table) | ||||||
| { | { | ||||||
| 	int i, busw, nand_maf_id, nand_dev_id; | 	int i, nand_maf_id, nand_dev_id; | ||||||
| 	struct nand_chip *chip = mtd->priv; | 	struct nand_chip *chip = mtd->priv; | ||||||
| 	struct nand_flash_dev *type; | 	struct nand_flash_dev *type; | ||||||
| 
 | 
 | ||||||
| 	/* Get buswidth to select the correct functions */ |  | ||||||
| 	busw = chip->options & NAND_BUSWIDTH_16; |  | ||||||
| 	/* Set the default functions */ | 	/* Set the default functions */ | ||||||
| 	nand_set_defaults(chip, busw); | 	nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16); | ||||||
| 
 | 
 | ||||||
| 	/* Read the flash type */ | 	/* Read the flash type */ | ||||||
| 	type = nand_get_flash_type(mtd, chip, busw, | 	type = nand_get_flash_type(mtd, chip, &nand_maf_id, | ||||||
| 				&nand_maf_id, &nand_dev_id, table); | 				   &nand_dev_id, table); | ||||||
| 
 | 
 | ||||||
| 	if (IS_ERR(type)) { | 	if (IS_ERR(type)) { | ||||||
| 		if (!(chip->options & NAND_SCAN_SILENT_NODEV)) | 		if (!(chip->options & NAND_SCAN_SILENT_NODEV)) | ||||||
|  | @ -3947,15 +4040,30 @@ int nand_scan_tail(struct mtd_info *mtd) | ||||||
| 	int i; | 	int i; | ||||||
| 	struct nand_chip *chip = mtd->priv; | 	struct nand_chip *chip = mtd->priv; | ||||||
| 	struct nand_ecc_ctrl *ecc = &chip->ecc; | 	struct nand_ecc_ctrl *ecc = &chip->ecc; | ||||||
|  | 	struct nand_buffers *nbuf; | ||||||
| 
 | 
 | ||||||
| 	/* New bad blocks should be marked in OOB, flash-based BBT, or both */ | 	/* New bad blocks should be marked in OOB, flash-based BBT, or both */ | ||||||
| 	BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && | 	BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && | ||||||
| 			!(chip->bbt_options & NAND_BBT_USE_FLASH)); | 			!(chip->bbt_options & NAND_BBT_USE_FLASH)); | ||||||
| 
 | 
 | ||||||
| 	if (!(chip->options & NAND_OWN_BUFFERS)) | 	if (!(chip->options & NAND_OWN_BUFFERS)) { | ||||||
| 		chip->buffers = kmalloc(sizeof(*chip->buffers), GFP_KERNEL); | #ifndef __UBOOT__ | ||||||
| 	if (!chip->buffers) | 		nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize | ||||||
| 		return -ENOMEM; | 				+ mtd->oobsize * 3, GFP_KERNEL); | ||||||
|  | 		if (!nbuf) | ||||||
|  | 			return -ENOMEM; | ||||||
|  | 		nbuf->ecccalc = (uint8_t *)(nbuf + 1); | ||||||
|  | 		nbuf->ecccode = nbuf->ecccalc + mtd->oobsize; | ||||||
|  | 		nbuf->databuf = nbuf->ecccode + mtd->oobsize; | ||||||
|  | #else | ||||||
|  | 		nbuf = kzalloc(sizeof(struct nand_buffers), GFP_KERNEL); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 		chip->buffers = nbuf; | ||||||
|  | 	} else { | ||||||
|  | 		if (!chip->buffers) | ||||||
|  | 			return -ENOMEM; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Set the internal oob buffer location, just after the page data */ | 	/* Set the internal oob buffer location, just after the page data */ | ||||||
| 	chip->oob_poi = chip->buffers->databuf + mtd->writesize; | 	chip->oob_poi = chip->buffers->databuf + mtd->writesize; | ||||||
|  | @ -4076,7 +4184,7 @@ int nand_scan_tail(struct mtd_info *mtd) | ||||||
| 
 | 
 | ||||||
| 	case NAND_ECC_SOFT_BCH: | 	case NAND_ECC_SOFT_BCH: | ||||||
| 		if (!mtd_nand_has_bch()) { | 		if (!mtd_nand_has_bch()) { | ||||||
| 			pr_warn("CONFIG_MTD_ECC_BCH not enabled\n"); | 			pr_warn("CONFIG_MTD_NAND_ECC_BCH not enabled\n"); | ||||||
| 			BUG(); | 			BUG(); | ||||||
| 		} | 		} | ||||||
| 		ecc->calculate = nand_bch_calculate_ecc; | 		ecc->calculate = nand_bch_calculate_ecc; | ||||||
|  |  | ||||||
|  | @ -59,6 +59,9 @@ struct nand_flash_dev nand_flash_ids[] = { | ||||||
| 	{"TC58NVG6D2 64G 3.3V 8-bit", | 	{"TC58NVG6D2 64G 3.3V 8-bit", | ||||||
| 		{ .id = {0x98, 0xde, 0x94, 0x82, 0x76, 0x56, 0x04, 0x20} }, | 		{ .id = {0x98, 0xde, 0x94, 0x82, 0x76, 0x56, 0x04, 0x20} }, | ||||||
| 		  SZ_8K, SZ_8K, SZ_2M, 0, 8, 640, NAND_ECC_INFO(40, SZ_1K) }, | 		  SZ_8K, SZ_8K, SZ_2M, 0, 8, 640, NAND_ECC_INFO(40, SZ_1K) }, | ||||||
|  | 	{"SDTNRGAMA 64G 3.3V 8-bit", | ||||||
|  | 		{ .id = {0x45, 0xde, 0x94, 0x93, 0x76, 0x50} }, | ||||||
|  | 		  SZ_16K, SZ_8K, SZ_4M, 0, 6, 1280, NAND_ECC_INFO(40, SZ_1K) }, | ||||||
| 
 | 
 | ||||||
| 	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS), | 	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS), | ||||||
| 	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS), | 	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS), | ||||||
|  |  | ||||||
|  | @ -1331,6 +1331,15 @@ int ubi_init(void) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	err = ubiblock_init(); | ||||||
|  | 	if (err) { | ||||||
|  | 		ubi_err("block: cannot initialize, error %d", err); | ||||||
|  | 
 | ||||||
|  | 		/* See comment above re-ubi_is_module(). */ | ||||||
|  | 		if (ubi_is_module()) | ||||||
|  | 			goto out_detach; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| 
 | 
 | ||||||
| out_detach: | out_detach: | ||||||
|  | @ -1363,6 +1372,8 @@ void ubi_exit(void) | ||||||
| { | { | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
|  | 	ubiblock_exit(); | ||||||
|  | 
 | ||||||
| 	for (i = 0; i < UBI_MAX_DEVICES; i++) | 	for (i = 0; i < UBI_MAX_DEVICES; i++) | ||||||
| 		if (ubi_devices[i]) { | 		if (ubi_devices[i]) { | ||||||
| 			mutex_lock(&ubi_devices_mutex); | 			mutex_lock(&ubi_devices_mutex); | ||||||
|  |  | ||||||
|  | @ -12,7 +12,6 @@ | ||||||
| 
 | 
 | ||||||
| #define __UBOOT__ | #define __UBOOT__ | ||||||
| #ifndef __UBOOT__ | #ifndef __UBOOT__ | ||||||
| #include <linux/init.h> |  | ||||||
| #include <linux/types.h> | #include <linux/types.h> | ||||||
| #include <linux/list.h> | #include <linux/list.h> | ||||||
| #include <linux/rbtree.h> | #include <linux/rbtree.h> | ||||||
|  | @ -884,6 +883,26 @@ int ubi_update_fastmap(struct ubi_device *ubi); | ||||||
| int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, | int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, | ||||||
| 		     int fm_anchor); | 		     int fm_anchor); | ||||||
| 
 | 
 | ||||||
|  | /* block.c */ | ||||||
|  | #ifdef CONFIG_MTD_UBI_BLOCK | ||||||
|  | int ubiblock_init(void); | ||||||
|  | void ubiblock_exit(void); | ||||||
|  | int ubiblock_create(struct ubi_volume_info *vi); | ||||||
|  | int ubiblock_remove(struct ubi_volume_info *vi); | ||||||
|  | #else | ||||||
|  | static inline int ubiblock_init(void) { return 0; } | ||||||
|  | static inline void ubiblock_exit(void) {} | ||||||
|  | static inline int ubiblock_create(struct ubi_volume_info *vi) | ||||||
|  | { | ||||||
|  | 	return -ENOSYS; | ||||||
|  | } | ||||||
|  | static inline int ubiblock_remove(struct ubi_volume_info *vi) | ||||||
|  | { | ||||||
|  | 	return -ENOSYS; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * ubi_rb_for_each_entry - walk an RB-tree. |  * ubi_rb_for_each_entry - walk an RB-tree. | ||||||
|  * @rb: a pointer to type 'struct rb_node' to use as a loop counter |  * @rb: a pointer to type 'struct rb_node' to use as a loop counter | ||||||
|  |  | ||||||
|  | @ -672,6 +672,8 @@ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi) | ||||||
| 
 | 
 | ||||||
| 	e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF); | 	e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF); | ||||||
| 	self_check_in_wl_tree(ubi, e, &ubi->free); | 	self_check_in_wl_tree(ubi, e, &ubi->free); | ||||||
|  | 	ubi->free_count--; | ||||||
|  | 	ubi_assert(ubi->free_count >= 0); | ||||||
| 	rb_erase(&e->u.rb, &ubi->free); | 	rb_erase(&e->u.rb, &ubi->free); | ||||||
| 
 | 
 | ||||||
| 	return e; | 	return e; | ||||||
|  | @ -685,6 +687,9 @@ int ubi_wl_get_peb(struct ubi_device *ubi) | ||||||
| 	peb = __wl_get_peb(ubi); | 	peb = __wl_get_peb(ubi); | ||||||
| 	spin_unlock(&ubi->wl_lock); | 	spin_unlock(&ubi->wl_lock); | ||||||
| 
 | 
 | ||||||
|  | 	if (peb < 0) | ||||||
|  | 		return peb; | ||||||
|  | 
 | ||||||
| 	err = ubi_self_check_all_ff(ubi, peb, ubi->vid_hdr_aloffset, | 	err = ubi_self_check_all_ff(ubi, peb, ubi->vid_hdr_aloffset, | ||||||
| 				    ubi->peb_size - ubi->vid_hdr_aloffset); | 				    ubi->peb_size - ubi->vid_hdr_aloffset); | ||||||
| 	if (err) { | 	if (err) { | ||||||
|  | @ -1077,6 +1082,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, | ||||||
| 
 | 
 | ||||||
| 			/* Give the unused PEB back */ | 			/* Give the unused PEB back */ | ||||||
| 			wl_tree_add(e2, &ubi->free); | 			wl_tree_add(e2, &ubi->free); | ||||||
|  | 			ubi->free_count++; | ||||||
| 			goto out_cancel; | 			goto out_cancel; | ||||||
| 		} | 		} | ||||||
| 		self_check_in_wl_tree(ubi, e1, &ubi->used); | 		self_check_in_wl_tree(ubi, e1, &ubi->used); | ||||||
|  |  | ||||||
|  | @ -531,7 +531,7 @@ static void ubifs_evict_inode(struct inode *inode) | ||||||
| 	dbg_gen("inode %lu, mode %#x", inode->i_ino, (int)inode->i_mode); | 	dbg_gen("inode %lu, mode %#x", inode->i_ino, (int)inode->i_mode); | ||||||
| 	ubifs_assert(!atomic_read(&inode->i_count)); | 	ubifs_assert(!atomic_read(&inode->i_count)); | ||||||
| 
 | 
 | ||||||
| 	truncate_inode_pages(&inode->i_data, 0); | 	truncate_inode_pages_final(&inode->i_data); | ||||||
| 
 | 
 | ||||||
| 	if (inode->i_nlink) | 	if (inode->i_nlink) | ||||||
| 		goto done; | 		goto done; | ||||||
|  | @ -1786,7 +1786,7 @@ static int ubifs_remount_rw(struct ubifs_info *c) | ||||||
| 	if (c->space_fixup) { | 	if (c->space_fixup) { | ||||||
| 		err = ubifs_fixup_free_space(c); | 		err = ubifs_fixup_free_space(c); | ||||||
| 		if (err) | 		if (err) | ||||||
| 			return err; | 			goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = check_free_space(c); | 	err = check_free_space(c); | ||||||
|  | @ -2063,6 +2063,7 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) | ||||||
| 	int err; | 	int err; | ||||||
| 	struct ubifs_info *c = sb->s_fs_info; | 	struct ubifs_info *c = sb->s_fs_info; | ||||||
| 
 | 
 | ||||||
|  | 	sync_filesystem(sb); | ||||||
| 	dbg_gen("old flags %#lx, new flags %#x", sb->s_flags, *flags); | 	dbg_gen("old flags %#lx, new flags %#x", sb->s_flags, *flags); | ||||||
| 
 | 
 | ||||||
| 	err = ubifs_parse_options(c, data, 1); | 	err = ubifs_parse_options(c, data, 1); | ||||||
|  |  | ||||||
|  | @ -219,12 +219,12 @@ struct mtd_info { | ||||||
| 			  struct mtd_oob_ops *ops); | 			  struct mtd_oob_ops *ops); | ||||||
| 	int (*_write_oob) (struct mtd_info *mtd, loff_t to, | 	int (*_write_oob) (struct mtd_info *mtd, loff_t to, | ||||||
| 			   struct mtd_oob_ops *ops); | 			   struct mtd_oob_ops *ops); | ||||||
| 	int (*_get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, | 	int (*_get_fact_prot_info) (struct mtd_info *mtd, size_t len, | ||||||
| 				    size_t len); | 				    size_t *retlen, struct otp_info *buf); | ||||||
| 	int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, | 	int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, | ||||||
| 				    size_t len, size_t *retlen, u_char *buf); | 				    size_t len, size_t *retlen, u_char *buf); | ||||||
| 	int (*_get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, | 	int (*_get_user_prot_info) (struct mtd_info *mtd, size_t len, | ||||||
| 				    size_t len); | 				    size_t *retlen, struct otp_info *buf); | ||||||
| 	int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from, | 	int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from, | ||||||
| 				    size_t len, size_t *retlen, u_char *buf); | 				    size_t len, size_t *retlen, u_char *buf); | ||||||
| 	int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to, | 	int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to, | ||||||
|  | @ -303,12 +303,12 @@ static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to, | ||||||
| 	return mtd->_write_oob(mtd, to, ops); | 	return mtd->_write_oob(mtd, to, ops); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int mtd_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, | int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, | ||||||
| 			   size_t len); | 			   struct otp_info *buf); | ||||||
| int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, | int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, | ||||||
| 			   size_t *retlen, u_char *buf); | 			   size_t *retlen, u_char *buf); | ||||||
| int mtd_get_user_prot_info(struct mtd_info *mtd, struct otp_info *buf, | int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, | ||||||
| 			   size_t len); | 			   struct otp_info *buf); | ||||||
| int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, | int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, | ||||||
| 			   size_t *retlen, u_char *buf); | 			   size_t *retlen, u_char *buf); | ||||||
| int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, | int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, | ||||||
|  |  | ||||||
|  | @ -59,15 +59,15 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); | ||||||
| 
 | 
 | ||||||
| /* The maximum number of NAND chips in an array */ | /* The maximum number of NAND chips in an array */ | ||||||
| #define NAND_MAX_CHIPS		8 | #define NAND_MAX_CHIPS		8 | ||||||
| #endif | #else | ||||||
| 
 |  | ||||||
| /*
 | /*
 | ||||||
|  * This constant declares the max. oobsize / page, which |  * This constant declares the max. oobsize / page, which | ||||||
|  * is supported now. If you add a chip with bigger oobsize/page |  * is supported now. If you add a chip with bigger oobsize/page | ||||||
|  * adjust this accordingly. |  * adjust this accordingly. | ||||||
|  */ |  */ | ||||||
| #define NAND_MAX_OOBSIZE	744 | #define NAND_MAX_OOBSIZE       744 | ||||||
| #define NAND_MAX_PAGESIZE	8192 | #define NAND_MAX_PAGESIZE      8192 | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Constants for hardware specific CLE/ALE/NCE function |  * Constants for hardware specific CLE/ALE/NCE function | ||||||
|  | @ -385,6 +385,84 @@ struct nand_onfi_vendor_micron { | ||||||
| 	u8 param_revision; | 	u8 param_revision; | ||||||
| } __packed; | } __packed; | ||||||
| 
 | 
 | ||||||
|  | struct jedec_ecc_info { | ||||||
|  | 	u8 ecc_bits; | ||||||
|  | 	u8 codeword_size; | ||||||
|  | 	__le16 bb_per_lun; | ||||||
|  | 	__le16 block_endurance; | ||||||
|  | 	u8 reserved[2]; | ||||||
|  | } __packed; | ||||||
|  | 
 | ||||||
|  | /* JEDEC features */ | ||||||
|  | #define JEDEC_FEATURE_16_BIT_BUS	(1 << 0) | ||||||
|  | 
 | ||||||
|  | struct nand_jedec_params { | ||||||
|  | 	/* rev info and features block */ | ||||||
|  | 	/* 'J' 'E' 'S' 'D'  */ | ||||||
|  | 	u8 sig[4]; | ||||||
|  | 	__le16 revision; | ||||||
|  | 	__le16 features; | ||||||
|  | 	u8 opt_cmd[3]; | ||||||
|  | 	__le16 sec_cmd; | ||||||
|  | 	u8 num_of_param_pages; | ||||||
|  | 	u8 reserved0[18]; | ||||||
|  | 
 | ||||||
|  | 	/* manufacturer information block */ | ||||||
|  | 	char manufacturer[12]; | ||||||
|  | 	char model[20]; | ||||||
|  | 	u8 jedec_id[6]; | ||||||
|  | 	u8 reserved1[10]; | ||||||
|  | 
 | ||||||
|  | 	/* memory organization block */ | ||||||
|  | 	__le32 byte_per_page; | ||||||
|  | 	__le16 spare_bytes_per_page; | ||||||
|  | 	u8 reserved2[6]; | ||||||
|  | 	__le32 pages_per_block; | ||||||
|  | 	__le32 blocks_per_lun; | ||||||
|  | 	u8 lun_count; | ||||||
|  | 	u8 addr_cycles; | ||||||
|  | 	u8 bits_per_cell; | ||||||
|  | 	u8 programs_per_page; | ||||||
|  | 	u8 multi_plane_addr; | ||||||
|  | 	u8 multi_plane_op_attr; | ||||||
|  | 	u8 reserved3[38]; | ||||||
|  | 
 | ||||||
|  | 	/* electrical parameter block */ | ||||||
|  | 	__le16 async_sdr_speed_grade; | ||||||
|  | 	__le16 toggle_ddr_speed_grade; | ||||||
|  | 	__le16 sync_ddr_speed_grade; | ||||||
|  | 	u8 async_sdr_features; | ||||||
|  | 	u8 toggle_ddr_features; | ||||||
|  | 	u8 sync_ddr_features; | ||||||
|  | 	__le16 t_prog; | ||||||
|  | 	__le16 t_bers; | ||||||
|  | 	__le16 t_r; | ||||||
|  | 	__le16 t_r_multi_plane; | ||||||
|  | 	__le16 t_ccs; | ||||||
|  | 	__le16 io_pin_capacitance_typ; | ||||||
|  | 	__le16 input_pin_capacitance_typ; | ||||||
|  | 	__le16 clk_pin_capacitance_typ; | ||||||
|  | 	u8 driver_strength_support; | ||||||
|  | 	__le16 t_ald; | ||||||
|  | 	u8 reserved4[36]; | ||||||
|  | 
 | ||||||
|  | 	/* ECC and endurance block */ | ||||||
|  | 	u8 guaranteed_good_blocks; | ||||||
|  | 	__le16 guaranteed_block_endurance; | ||||||
|  | 	struct jedec_ecc_info ecc_info[4]; | ||||||
|  | 	u8 reserved5[29]; | ||||||
|  | 
 | ||||||
|  | 	/* reserved */ | ||||||
|  | 	u8 reserved6[148]; | ||||||
|  | 
 | ||||||
|  | 	/* vendor */ | ||||||
|  | 	__le16 vendor_rev_num; | ||||||
|  | 	u8 reserved7[88]; | ||||||
|  | 
 | ||||||
|  | 	/* CRC for Parameter Page */ | ||||||
|  | 	__le16 crc; | ||||||
|  | } __packed; | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices |  * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices | ||||||
|  * @lock:               protection lock |  * @lock:               protection lock | ||||||
|  | @ -455,7 +533,7 @@ struct nand_ecc_ctrl { | ||||||
| 	int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, | 	int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, | ||||||
| 			uint8_t *buf, int oob_required, int page); | 			uint8_t *buf, int oob_required, int page); | ||||||
| 	int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip, | 	int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip, | ||||||
| 			uint32_t offs, uint32_t len, uint8_t *buf); | 			uint32_t offs, uint32_t len, uint8_t *buf, int page); | ||||||
| 	int (*write_subpage)(struct mtd_info *mtd, struct nand_chip *chip, | 	int (*write_subpage)(struct mtd_info *mtd, struct nand_chip *chip, | ||||||
| 			uint32_t offset, uint32_t data_len, | 			uint32_t offset, uint32_t data_len, | ||||||
| 			const uint8_t *data_buf, int oob_required); | 			const uint8_t *data_buf, int oob_required); | ||||||
|  | @ -472,17 +550,17 @@ struct nand_ecc_ctrl { | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * struct nand_buffers - buffer structure for read/write |  * struct nand_buffers - buffer structure for read/write | ||||||
|  * @ecccalc:	buffer for calculated ECC |  * @ecccalc:	buffer pointer for calculated ECC, size is oobsize. | ||||||
|  * @ecccode:	buffer for ECC read from flash |  * @ecccode:	buffer pointer for ECC read from flash, size is oobsize. | ||||||
|  * @databuf:	buffer for data - dynamically sized |  * @databuf:	buffer pointer for data, size is (page size + oobsize). | ||||||
|  * |  * | ||||||
|  * Do not change the order of buffers. databuf and oobrbuf must be in |  * Do not change the order of buffers. databuf and oobrbuf must be in | ||||||
|  * consecutive order. |  * consecutive order. | ||||||
|  */ |  */ | ||||||
| struct nand_buffers { | struct nand_buffers { | ||||||
| #ifndef __UBOOT__ | #ifndef __UBOOT__ | ||||||
| 	uint8_t	*ecccalc; | 	uint8_t *ecccalc; | ||||||
| 	uint8_t	*ecccode; | 	uint8_t *ecccode; | ||||||
| 	uint8_t *databuf; | 	uint8_t *databuf; | ||||||
| #else | #else | ||||||
| 	uint8_t	ecccalc[ALIGN(NAND_MAX_OOBSIZE, ARCH_DMA_MINALIGN)]; | 	uint8_t	ecccalc[ALIGN(NAND_MAX_OOBSIZE, ARCH_DMA_MINALIGN)]; | ||||||
|  | @ -567,8 +645,12 @@ struct nand_buffers { | ||||||
|  * @subpagesize:	[INTERN] holds the subpagesize |  * @subpagesize:	[INTERN] holds the subpagesize | ||||||
|  * @onfi_version:	[INTERN] holds the chip ONFI version (BCD encoded), |  * @onfi_version:	[INTERN] holds the chip ONFI version (BCD encoded), | ||||||
|  *			non 0 if ONFI supported. |  *			non 0 if ONFI supported. | ||||||
|  |  * @jedec_version:	[INTERN] holds the chip JEDEC version (BCD encoded), | ||||||
|  |  *			non 0 if JEDEC supported. | ||||||
|  * @onfi_params:	[INTERN] holds the ONFI page parameter when ONFI is |  * @onfi_params:	[INTERN] holds the ONFI page parameter when ONFI is | ||||||
|  *			supported, 0 otherwise. |  *			supported, 0 otherwise. | ||||||
|  |  * @jedec_params:	[INTERN] holds the JEDEC parameter page when JEDEC is | ||||||
|  |  *			supported, 0 otherwise. | ||||||
|  * @read_retries:	[INTERN] the number of read retry modes supported |  * @read_retries:	[INTERN] the number of read retry modes supported | ||||||
|  * @onfi_set_features:	[REPLACEABLE] set the features for ONFI nand |  * @onfi_set_features:	[REPLACEABLE] set the features for ONFI nand | ||||||
|  * @onfi_get_features:	[REPLACEABLE] get the features for ONFI nand |  * @onfi_get_features:	[REPLACEABLE] get the features for ONFI nand | ||||||
|  | @ -646,9 +728,11 @@ struct nand_chip { | ||||||
| 	int badblockbits; | 	int badblockbits; | ||||||
| 
 | 
 | ||||||
| 	int onfi_version; | 	int onfi_version; | ||||||
|  | 	int jedec_version; | ||||||
| #ifdef CONFIG_SYS_NAND_ONFI_DETECTION | #ifdef CONFIG_SYS_NAND_ONFI_DETECTION | ||||||
| 	struct nand_onfi_params	onfi_params; | 	struct nand_onfi_params	onfi_params; | ||||||
| #endif | #endif | ||||||
|  | 	struct nand_jedec_params jedec_params; | ||||||
|   |   | ||||||
| 	int read_retries; | 	int read_retries; | ||||||
| 
 | 
 | ||||||
|  | @ -923,6 +1007,13 @@ static inline int nand_opcode_8bits(unsigned int command) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* return the supported JEDEC features. */ | ||||||
|  | static inline int jedec_feature(struct nand_chip *chip) | ||||||
|  | { | ||||||
|  | 	return chip->jedec_version ? le16_to_cpu(chip->jedec_params.features) | ||||||
|  | 		: 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #ifdef __UBOOT__ | #ifdef __UBOOT__ | ||||||
| /* Standard NAND functions from nand_base.c */ | /* Standard NAND functions from nand_base.c */ | ||||||
| void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len); | void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len); | ||||||
|  |  | ||||||
|  | @ -122,6 +122,16 @@ | ||||||
|  * used. A pointer to a &struct ubi_set_vol_prop_req object is expected to be |  * used. A pointer to a &struct ubi_set_vol_prop_req object is expected to be | ||||||
|  * passed. The object describes which property should be set, and to which value |  * passed. The object describes which property should be set, and to which value | ||||||
|  * it should be set. |  * it should be set. | ||||||
|  |  * | ||||||
|  |  * Block devices on UBI volumes | ||||||
|  |  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
|  |  * | ||||||
|  |  * To create a R/O block device on top of an UBI volume the %UBI_IOCVOLCRBLK | ||||||
|  |  * should be used. A pointer to a &struct ubi_blkcreate_req object is expected | ||||||
|  |  * to be passed, which is not used and reserved for future usage. | ||||||
|  |  * | ||||||
|  |  * Conversely, to remove a block device the %UBI_IOCVOLRMBLK should be used, | ||||||
|  |  * which takes no arguments. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -179,6 +189,10 @@ | ||||||
| /* Set an UBI volume property */ | /* Set an UBI volume property */ | ||||||
| #define UBI_IOCSETVOLPROP _IOW(UBI_VOL_IOC_MAGIC, 6, \ | #define UBI_IOCSETVOLPROP _IOW(UBI_VOL_IOC_MAGIC, 6, \ | ||||||
| 			       struct ubi_set_vol_prop_req) | 			       struct ubi_set_vol_prop_req) | ||||||
|  | /* Create a R/O block device on top of an UBI volume */ | ||||||
|  | #define UBI_IOCVOLCRBLK _IOW(UBI_VOL_IOC_MAGIC, 7, struct ubi_blkcreate_req) | ||||||
|  | /* Remove the R/O block device */ | ||||||
|  | #define UBI_IOCVOLRMBLK _IO(UBI_VOL_IOC_MAGIC, 8) | ||||||
| 
 | 
 | ||||||
| /* Maximum MTD device name length supported by UBI */ | /* Maximum MTD device name length supported by UBI */ | ||||||
| #define MAX_UBI_MTD_NAME_LEN 127 | #define MAX_UBI_MTD_NAME_LEN 127 | ||||||
|  | @ -408,4 +422,12 @@ struct ubi_set_vol_prop_req { | ||||||
| 	__u64 value; | 	__u64 value; | ||||||
| }  __packed; | }  __packed; | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * struct ubi_blkcreate_req - a data structure used in block creation requests. | ||||||
|  |  * @padding: reserved for future, not used, has to be zeroed | ||||||
|  |  */ | ||||||
|  | struct ubi_blkcreate_req { | ||||||
|  | 	__s8  padding[128]; | ||||||
|  | }  __packed; | ||||||
|  | 
 | ||||||
| #endif /* __UBI_USER_H__ */ | #endif /* __UBI_USER_H__ */ | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue