Skip to contentSkip to conversation

S3C64XX support

PATCH In review Kyungmin Park 2 participants 4 messages Oct 20, 2008 – Oct 21, 2008

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 S3C64XX support

PLEASE DON'T COMMIT IT

Hi,

It's OneNAND support on New Samsung Mobile CPU S3C64XX series Now it's only tested with s3c6410 with UBI & UBIFS.
If you want to use it on s3c6400, you should change some values.

There's some ugly hack for support s3c64xx. It will be handled more fancy later.

Any comments are welcome

Thank you,
Kyungmin Park
---

drivers/mtd/onenand/Kconfig +6 -0
index cb41cbc..1a4b8f7 100644
@@ -27,6 +27,12 @@ config MTD_ONENAND_GENERIC
 	help
 	  Support for OneNAND flash via platform device driver.
 
+config MTD_ONENAND_S3C64XX
+	tristate "S3C64XX OneNAND Controller support"
+	depends on CPU_S3C64XX
+	help
+	  The S3C64XX has own OneNAND controller.
+
 config MTD_ONENAND_OTP
 	bool "OneNAND OTP Support"
 	help
drivers/mtd/onenand/Makefile +1 -0
index 4d2eacf..cba6eea 100644
@@ -7,6 +7,7 @@ obj-$(CONFIG_MTD_ONENAND)		+= onenand.o
 
 # Board specific.
 obj-$(CONFIG_MTD_ONENAND_GENERIC)	+= generic.o
+obj-$(CONFIG_MTD_ONENAND_S3C64XX)	+= s3c64xx.o
 
 # Simulator
 obj-$(CONFIG_MTD_ONENAND_SIM)		+= onenand_sim.o
drivers/mtd/onenand/onenand_base.c +26 -14
index 926cf3a..5811999 100644
@@ -636,6 +636,9 @@ static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr)
 	int blockpage, found = 0;
 	unsigned int i;
 
+	if (this->options & ONENAND_DONT_USE_BUFFERRAM)
+		return 0;
+
 	if (ONENAND_IS_2PLANE(this))
 		blockpage = onenand_get_2x_blockpage(mtd, addr);
 	else
@@ -832,7 +835,7 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
 	size_t ooblen = ops->ooblen;
 	u_char *buf = ops->datbuf;
 	u_char *oobbuf = ops->oobbuf;
-	int read = 0, column, thislen;
+	int read = 0, column, thislen, nextlen;
 	int oobread = 0, oobcolumn, thisooblen, oobsize;
 	int ret = 0, boundary = 0;
 	int writesize = this->writesize;
@@ -858,10 +861,16 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
 
  	/* Read-while-load method */
 
+	thislen = min_t(int, writesize, len - read);
+	column = from & (writesize - 1);
+	if (column + thislen > writesize)
+		thislen = writesize - column;
+
  	/* Do first load to bufferRAM */
  	if (read < len) {
  		if (!onenand_check_bufferram(mtd, from)) {
-			this->command(mtd, ONENAND_CMD_READ, from, writesize);
+			this->main_buf = buf;
+			this->command(mtd, ONENAND_CMD_READ, from, thislen);
  			ret = this->wait(mtd, FL_READING);
  			onenand_update_bufferram(mtd, from, !ret);
 			if (ret == -EBADMSG)
@@ -869,16 +878,13 @@ static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
  		}
  	}
 
-	thislen = min_t(int, writesize, len - read);
-	column = from & (writesize - 1);
-	if (column + thislen > writesize)
-		thislen = writesize - column;
-
  	while (!ret) {
  		/* If there is more to load then start next load */
  		from += thislen;
  		if (read + thislen < len) {
-			this->command(mtd, ONENAND_CMD_READ, from, writesize);
+			this->main_buf = buf + thislen;
+			nextlen = min_t(int, writesize, len - thislen - read);
+			this->command(mtd, ONENAND_CMD_READ, from, nextlen);
  			/*
  			 * Chip boundary handling in DDP
  			 * Now we issued chip 1 read and pointed chip 1
@@ -999,6 +1005,7 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
 		thislen = oobsize - column;
 		thislen = min_t(int, thislen, len);
 
+		this->spare_buf = buf;
 		this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize);
 
 		onenand_update_bufferram(mtd, from, 0);
@@ -1129,11 +1136,8 @@ static int onenand_bbt_wait(struct mtd_info *mtd, int state)
 
 	if (interrupt & ONENAND_INT_READ) {
 		int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
-		if (ecc & ONENAND_ECC_2BIT_ALL) {
-			printk(KERN_INFO "onenand_bbt_wait: ecc error = 0x%04x"
-				", controller error 0x%04x\n", ecc, ctrl);
+		if (ecc & ONENAND_ECC_2BIT_ALL)
 			return ONENAND_BBT_READ_ERROR;
-		}
 	} else {
 		printk(KERN_ERR "onenand_bbt_wait: read timeout!"
 			"ctrl=0x%04x intr=0x%04x\n", ctrl, interrupt);
@@ -1189,11 +1193,12 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
 		thislen = mtd->oobsize - column;
 		thislen = min_t(int, thislen, len);
 
+		this->spare_buf = buf;
 		this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize);
 
 		onenand_update_bufferram(mtd, from, 0);
 
-		ret = onenand_bbt_wait(mtd, FL_READING);
+		ret = this->bbt_wait(mtd, FL_READING);
 		if (ret)
 			break;
 
@@ -2116,6 +2121,9 @@ static void onenand_unlock_all(struct mtd_info *mtd)
 		    & ONENAND_CTRL_ONGO)
 			continue;
 
+		if (this->options & ONENAND_SKIP_UNLOCK_CHECK)
+			return;
+
 		/* Check lock status */
 		if (onenand_check_lock_status(this))
 			return;
@@ -2699,6 +2707,10 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
 		this->command = onenand_command;
 	if (!this->wait)
 		onenand_setup_wait(mtd);
+	if (!this->bbt_wait)
+		this->bbt_wait = onenand_bbt_wait;
+	if (!this->unlock_all)
+		this->unlock_all = onenand_unlock_all;
 
 	if (!this->read_bufferram)
 		this->read_bufferram = onenand_read_bufferram;
@@ -2812,7 +2824,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
 	mtd->owner = THIS_MODULE;
 
 	/* Unlock whole block */
-	onenand_unlock_all(mtd);
+	this->unlock_all(mtd);
 
 	return this->scan_bbt(mtd);
 }
drivers/mtd/onenand/s3c64xx.c new file +652 -0

652 lines not on this page · raw message

include/asm-arm/plat-s3c/s3c64xx-onenand.h new file +77 -0

77 lines not on this page · raw message

include/linux/mtd/onenand.h +7 -0
index 9aa2a91..64f173a 100644
@@ -108,6 +108,8 @@ struct onenand_chip {
 
 	int (*command)(struct mtd_info *mtd, int cmd, loff_t address, size_t len);
 	int (*wait)(struct mtd_info *mtd, int state);
+	int (*bbt_wait)(struct mtd_info *mtd, int state);
+	void (*unlock_all)(struct mtd_info *mtd);
 	int (*read_bufferram)(struct mtd_info *mtd, int area,
 			unsigned char *buffer, int offset, size_t count);
 	int (*write_bufferram)(struct mtd_info *mtd, int area,
@@ -121,6 +123,9 @@ struct onenand_chip {
 	struct completion	complete;
 	int			irq;
 
+	unsigned char		*main_buf;
+	unsigned char		*spare_buf;
+
 	spinlock_t		chip_lock;
 	wait_queue_head_t	wq;
 	onenand_state_t		state;
@@ -169,6 +174,8 @@ struct onenand_chip {
 #define ONENAND_HAS_CONT_LOCK		(0x0001)
 #define ONENAND_HAS_UNLOCK_ALL		(0x0002)
 #define ONENAND_HAS_2PLANE		(0x0004)
+#define ONENAND_SKIP_UNLOCK_CHECK	(0x0010)
+#define ONENAND_DONT_USE_BUFFERRAM	(0x0020)
 #define ONENAND_PAGEBUF_ALLOC		(0x1000)
 #define ONENAND_OOBBUF_ALLOC		(0x2000)
 
#1 lore raw
Quoted 6 lines · Kyungmin Park

It's OneNAND support on New Samsung Mobile CPU S3C64XX series Now it's only tested with s3c6410 with UBI & UBIFS. If you want to use it on s3c6400, you should change some values.

There's some ugly hack for support s3c64xx. It will be handled more fancy later.

Any comments are welcome

Why not just make it a separate driver and skip using onenand_base etc?

#2 lore raw
Quoted 6 lines · Adrian Hunter
Quoted 5 lines · Kyungmin Park

It's OneNAND support on New Samsung Mobile CPU S3C64XX series Now it's only tested with s3c6410 with UBI & UBIFS.
If you want to use it on s3c6400, you should change some values.

Quoted 7 lines
Quoted 4 lines

There's some ugly hack for support s3c64xx. It will be handled more fancy later.

Any comments are welcome

Why not just make it a separate driver and skip using onenand_base etc?

DId you see the s3c64xx OneNAND controller?. It has its own OneNAND controller and don't use the OneNAND memory access method as OMAP.

Yes it's possible to make an own OneNAND driver for s3c64xx, but maybe a half of codes are redundant except the access method so I want to use default onenand_base and just redefine the OneNAND function for s3c64xx.

Thank you,
Kyungmin Park

#3 lore raw
Quoted 14 lines · Kyungmin Park
Quoted 11 lines · Adrian Hunter
Quoted 8 lines · Kyungmin Park

It's OneNAND support on New Samsung Mobile CPU S3C64XX series Now it's only tested with s3c6410 with UBI & UBIFS.
If you want to use it on s3c6400, you should change some values.

There's some ugly hack for support s3c64xx. It will be handled more fancy later.

Any comments are welcome

Why not just make it a separate driver and skip using onenand_base etc?

Quoted 7 lines

DId you see the s3c64xx OneNAND controller?. It has its own OneNAND controller and don't use the OneNAND memory access method as OMAP.

Yes it's possible to make an own OneNAND driver for s3c64xx, but maybe a half of codes are redundant except the access method so I want to use default onenand_base and just redefine the OneNAND function for s3c64xx.

I glanced at the code. It did not look like there was much code from onenand_base that was needed, so wouldn't it be cleaner to just copy those bits?