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

Commit 6a88c47b authored by Kyungmin Park's avatar Kyungmin Park Committed by David Woodhouse
Browse files

mtd: onenand: add support for chips with 4KiB page size



This patch adds support for OneNAND chips that have 4KiB page size.

Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarMarek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 7d84b627
Loading
Loading
Loading
Loading
+19 −13
Original line number Diff line number Diff line
@@ -397,7 +397,8 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
		value = onenand_bufferram_address(this, block);
		this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);

		if (ONENAND_IS_MLC(this) || ONENAND_IS_2PLANE(this))
		if (ONENAND_IS_MLC(this) || ONENAND_IS_2PLANE(this) ||
		    ONENAND_IS_4KB_PAGE(this))
			/* It is always BufferRAM0 */
			ONENAND_SET_BUFFERRAM0(this);
		else
@@ -426,7 +427,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
		case FLEXONENAND_CMD_RECOVER_LSB:
		case ONENAND_CMD_READ:
		case ONENAND_CMD_READOOB:
			if (ONENAND_IS_MLC(this))
			if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this))
				/* It is always BufferRAM0 */
				dataram = ONENAND_SET_BUFFERRAM0(this);
			else
@@ -466,11 +467,11 @@ static inline int onenand_read_ecc(struct onenand_chip *this)
{
	int ecc, i, result = 0;

	if (!FLEXONENAND(this))
	if (!FLEXONENAND(this) && !ONENAND_IS_4KB_PAGE(this))
		return this->read_word(this->base + ONENAND_REG_ECC_STATUS);

	for (i = 0; i < 4; i++) {
		ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS + i);
		ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS + i*2);
		if (likely(!ecc))
			continue;
		if (ecc & FLEXONENAND_UNCORRECTABLE_ERROR)
@@ -1425,7 +1426,7 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
	int ret;

	onenand_get_device(mtd, FL_READING);
	ret = ONENAND_IS_MLC(this) ?
	ret = ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this) ?
		onenand_mlc_read_ops_nolock(mtd, from, &ops) :
		onenand_read_ops_nolock(mtd, from, &ops);
	onenand_release_device(mtd);
@@ -1460,7 +1461,7 @@ static int onenand_read_oob(struct mtd_info *mtd, loff_t from,

	onenand_get_device(mtd, FL_READING);
	if (ops->datbuf)
		ret = ONENAND_IS_MLC(this) ?
		ret = ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this) ?
			onenand_mlc_read_ops_nolock(mtd, from, ops) :
			onenand_read_ops_nolock(mtd, from, ops);
	else
@@ -1926,7 +1927,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
		 * 2 PLANE, MLC, and Flex-OneNAND do not support
		 * write-while-program feature.
		 */
		if (!ONENAND_IS_2PLANE(this) && !first) {
		if (!ONENAND_IS_2PLANE(this) && !ONENAND_IS_4KB_PAGE(this) && !first) {
			ONENAND_SET_PREV_BUFFERRAM(this);

			ret = this->wait(mtd, FL_WRITING);
@@ -1957,7 +1958,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
		/*
		 * 2 PLANE, MLC, and Flex-OneNAND wait here
		 */
		if (ONENAND_IS_2PLANE(this)) {
		if (ONENAND_IS_2PLANE(this) || ONENAND_IS_4KB_PAGE(this)) {
			ret = this->wait(mtd, FL_WRITING);

			/* In partial page write we don't update bufferram */
@@ -2084,7 +2085,7 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to,
			memcpy(oobbuf + column, buf, thislen);
		this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);

		if (ONENAND_IS_MLC(this)) {
		if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this)) {
			/* Set main area of DataRAM to 0xff*/
			memset(this->page_buf, 0xff, mtd->writesize);
			this->write_bufferram(mtd, ONENAND_DATARAM,
@@ -3027,7 +3028,7 @@ static int do_otp_read(struct mtd_info *mtd, loff_t from, size_t len,
	this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
	this->wait(mtd, FL_OTPING);

	ret = ONENAND_IS_MLC(this) ?
	ret = ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this) ?
		onenand_mlc_read_ops_nolock(mtd, from, &ops) :
		onenand_read_ops_nolock(mtd, from, &ops);

@@ -3372,7 +3373,10 @@ static void onenand_check_features(struct mtd_info *mtd)
	/* Lock scheme */
	switch (density) {
	case ONENAND_DEVICE_DENSITY_4Gb:
		if (ONENAND_IS_DDP(this))
			this->options |= ONENAND_HAS_2PLANE;
		else
			this->options |= ONENAND_HAS_4KB_PAGE;

	case ONENAND_DEVICE_DENSITY_2Gb:
		/* 2Gb DDP does not have 2 plane */
@@ -3393,7 +3397,7 @@ static void onenand_check_features(struct mtd_info *mtd)
		break;
	}

	if (ONENAND_IS_MLC(this))
	if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this))
		this->options &= ~ONENAND_HAS_2PLANE;

	if (FLEXONENAND(this)) {
@@ -3407,6 +3411,8 @@ static void onenand_check_features(struct mtd_info *mtd)
		printk(KERN_DEBUG "Chip support all block unlock\n");
	if (this->options & ONENAND_HAS_2PLANE)
		printk(KERN_DEBUG "Chip has 2 plane\n");
	if (this->options & ONENAND_HAS_4KB_PAGE)
		printk(KERN_DEBUG "Chip has 4KiB pagesize\n");
}

/**
@@ -3799,7 +3805,7 @@ static int onenand_probe(struct mtd_info *mtd)
	/* The data buffer size is equal to page size */
	mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
	/* We use the full BufferRAM */
	if (ONENAND_IS_MLC(this))
	if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this))
		mtd->writesize <<= 1;

	mtd->oobsize = mtd->writesize >> 5;
+4 −0
Original line number Diff line number Diff line
@@ -175,10 +175,14 @@ struct onenand_chip {
#define ONENAND_HAS_CONT_LOCK		(0x0001)
#define ONENAND_HAS_UNLOCK_ALL		(0x0002)
#define ONENAND_HAS_2PLANE		(0x0004)
#define ONENAND_HAS_4KB_PAGE		(0x0008)
#define ONENAND_SKIP_UNLOCK_CHECK	(0x0100)
#define ONENAND_PAGEBUF_ALLOC		(0x1000)
#define ONENAND_OOBBUF_ALLOC		(0x2000)

#define ONENAND_IS_4KB_PAGE(this)					\
	(this->options & ONENAND_HAS_4KB_PAGE)

/*
 * OneNAND Flash Manufacturer ID Codes
 */