Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6fb277ba authored by Florian Fainelli's avatar Florian Fainelli Committed by David Woodhouse
Browse files

mtd: nand: split ONFI detection logic to its own function



In order to reduce the indentation and improve the readability of nand_get_
flash_type, split the ONFI detection logic to its own function. The detection
logic inside nand_flash_detect_onfi is also rewritten to allow for less
indentation.

Signed-off-by: default avatarFlorian Fainelli <ffainelli@freebox.fr>
Signed-off-by: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent d1e1f4e4
Loading
Loading
Loading
Loading
+71 −61
Original line number Diff line number Diff line
@@ -2818,6 +2818,72 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
	return crc;
}

/*
 * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise
 */
static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
					int busw)
{
	struct nand_onfi_params *p = &chip->onfi_params;
	int i;
	int val;

	/* try ONFI for unknow chip or LP */
	chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
	if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
		chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
		return 0;

	printk(KERN_INFO "ONFI flash detected\n");
	chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
	for (i = 0; i < 3; i++) {
		chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
		if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
				le16_to_cpu(p->crc)) {
			printk(KERN_INFO "ONFI param page %d valid\n", i);
			break;
		}
	}

	if (i == 3)
		return 0;

	/* check version */
	val = le16_to_cpu(p->revision);
	if (val == 1 || val > (1 << 4)) {
		printk(KERN_INFO "%s: unsupported ONFI version: %d\n",
								__func__, val);
		return 0;
	}

	if (val & (1 << 4))
		chip->onfi_version = 22;
	else if (val & (1 << 3))
		chip->onfi_version = 21;
	else if (val & (1 << 2))
		chip->onfi_version = 20;
	else
		chip->onfi_version = 10;

	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);
	mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize;
	mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
	chip->chipsize = le32_to_cpu(p->blocks_per_lun) * mtd->erasesize;
	busw = 0;
	if (le16_to_cpu(p->features) & 1)
		busw = NAND_BUSWIDTH_16;

	chip->options &= ~NAND_CHIPOPTIONS_MSK;
	chip->options |= (NAND_NO_READRDY |
			NAND_NO_AUTOINCR) & NAND_CHIPOPTIONS_MSK;

	return 1;
}

/*
 * Get the flash and manufacturer id and lookup if the type is supported
 */
@@ -2828,6 +2894,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
{
	int i, maf_idx;
	u8 id_data[8];
	int ret;

	/* Select the device */
	chip->select_chip(mtd, 0);
@@ -2872,67 +2939,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,

	chip->onfi_version = 0;
	if (!type->name || !type->pagesize) {
		/* try ONFI for unknow chip or LP */
		chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
		if (chip->read_byte(mtd) == 'O' &&
			chip->read_byte(mtd) == 'N' &&
			chip->read_byte(mtd) == 'F' &&
			chip->read_byte(mtd) == 'I') {

			struct nand_onfi_params *p = &chip->onfi_params;
			int i;

			printk(KERN_INFO "ONFI flash detected\n");
			chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
			for (i = 0; i < 3; i++) {
				chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
				if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
								le16_to_cpu(p->crc))
				{
					 printk(KERN_INFO "ONFI param page %d valid\n", i);
					 break;
				}
			}

			if (i < 3) {
				/* check version */
				int val = le16_to_cpu(p->revision);
				if (val == 1 || val > (1 << 4))
					printk(KERN_INFO "%s: unsupported ONFI version: %d\n",
						__func__, val);
				else {
					if (val & (1 << 4))
						chip->onfi_version = 22;
					else if (val & (1 << 3))
						chip->onfi_version = 21;
					else if (val & (1 << 2))
						chip->onfi_version = 20;
					else
						chip->onfi_version = 10;
				}
			}

			if (chip->onfi_version) {
				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);
				mtd->erasesize = le32_to_cpu(p->pages_per_block)*mtd->writesize;
				mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
				chip->chipsize = le32_to_cpu(p->blocks_per_lun) * mtd->erasesize;
				busw = 0;
				if (le16_to_cpu(p->features) & 1)
					busw = NAND_BUSWIDTH_16;

				chip->options &= ~NAND_CHIPOPTIONS_MSK;
				chip->options |= (NAND_NO_READRDY |
						NAND_NO_AUTOINCR) & NAND_CHIPOPTIONS_MSK;

		/* Check is chip is ONFI compliant */
		ret = nand_flash_detect_onfi(mtd, chip, busw);
		if (ret)
			goto ident_done;

			}
		}
	}

	chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);