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

Commit 52b0eea7 authored by Kyungmin Park's avatar Kyungmin Park Committed by Thomas Gleixner
Browse files

[PATCH] OneNAND: Sync. Burst Read support



Add OneNAND Sync. Burst Read support
Tested with OMAP platform

Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent cd5f6346
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -29,4 +29,10 @@ config MTD_ONENAND_OMAP
	help
	  Support for OneNAND flash on TI OMAP board.

config MTD_ONENAND_SYNC_READ
	bool "OneNAND Sync. Burst Read Support"
	depends on ARCH_OMAP
	help
	  This enables support for Sync. Burst Read.

endmenu
+64 −2
Original line number Diff line number Diff line
@@ -25,9 +25,10 @@
#include <asm/arch/hardware.h>
#include <asm/arch/tc.h>
#include <asm/sizes.h>
#include <asm/mach-types.h>

#define OMAP_ONENAND_FLASH_START1	OMAP_CS2A_PHYS
#define OMAP_ONENAND_FLASH_START2	OMAP_CS0_PHYS
#define OMAP_ONENAND_FLASH_START2	omap_cs3_phys()
/*
 * MTD structure for OMAP board
 */
@@ -68,10 +69,66 @@ static struct mtd_partition static_partition[] = {
	},
};

const char *part_probes[] = { "cmdlinepart", NULL,  };
static const char *part_probes[] = { "cmdlinepart", NULL,  };

#endif

#ifdef CONFIG_MTD_ONENAND_SYNC_READ
static unsigned int omap_emifs_cs;

static void omap_find_emifs_cs(unsigned int addr)
{
	/* Check CS3 */
	if (OMAP_EMIFS_CONFIG_REG & OMAP_EMIFS_CONFIG_BM && addr == 0x0) {
		omap_emifs_cs = 3;
	} else {
		omap_emifs_cs = (addr >> 26);
	}
}

/**
 * omap_onenand_mmcontrol - Control OMAP EMIFS
 */
static void omap_onenand_mmcontrol(struct mtd_info *mtd, int sync_read)
{
	struct onenand_chip *this = mtd->priv;
	static unsigned long omap_emifs_ccs, omap_emifs_acs;
	static unsigned long onenand_sys_cfg1;
	int config, emifs_ccs, emifs_acs;

	if (sync_read) {
		/*
		 * Note: BRL and RDWST is equal
		 */
		omap_emifs_ccs = EMIFS_CCS(omap_emifs_cs);
		omap_emifs_acs = EMIFS_ACS(omap_emifs_cs);
		
		emifs_ccs = 0x41141;
		emifs_acs = 0x1;

		/* OneNAND System Configuration 1 */
		onenand_sys_cfg1 = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
		config = (onenand_sys_cfg1
			& ~(0x3f << ONENAND_SYS_CFG1_BL_SHIFT))
			| ONENAND_SYS_CFG1_SYNC_READ
			| ONENAND_SYS_CFG1_BRL_4
			| ONENAND_SYS_CFG1_BL_8;
	} else {
		emifs_ccs = omap_emifs_ccs;
		emifs_acs = omap_emifs_acs;
		config = onenand_sys_cfg1;
	}

	this->write_word(config, this->base + ONENAND_REG_SYS_CFG1);
	EMIFS_CCS(omap_emifs_cs) = emifs_ccs;
	EMIFS_ACS(omap_emifs_cs) = emifs_acs;
}
#else
#define omap_find_emifs_cs(x)		do { } while (0)
#define omap_onenand_mmcontrol		NULL
#endif


/* Scan to find existance of the device at base.
   This also allocates oob and data internal buffers */
static char onenand_name[] = "onenand";
@@ -102,14 +159,19 @@ static int __init omap_onenand_init (void)

	/* Link the private data with the MTD structure */
	omap_onenand_mtd->priv = this;
	this->mmcontrol = omap_onenand_mmcontrol;

        /* try the first address */
	this->base = ioremap(OMAP_ONENAND_FLASH_START1, SZ_128K);
	omap_find_emifs_cs(OMAP_ONENAND_FLASH_START1);

	omap_onenand_mtd->name = onenand_name;
	if (onenand_scan(omap_onenand_mtd, 1)){
		/* try the second address */
		iounmap(this->base);
		this->base = ioremap(OMAP_ONENAND_FLASH_START2, SZ_128K);
		omap_find_emifs_cs(OMAP_ONENAND_FLASH_START2);

		if (onenand_scan(omap_onenand_mtd, 1)) {
			iounmap(this->base);
                        err = -ENXIO;
+37 −2
Original line number Diff line number Diff line
@@ -378,6 +378,35 @@ static int onenand_read_bufferram(struct mtd_info *mtd, int area,
	return 0;
}

/**
 * onenand_sync_read_bufferram - [OneNAND Interface] Read the bufferram area with Sync. Burst mode
 * @param mtd		MTD data structure
 * @param area		BufferRAM area
 * @param buffer	the databuffer to put/get data
 * @param offset	offset to read from or write to
 * @param count		number of bytes to read/write
 *
 * Read the BufferRAM area with Sync. Burst Mode
 */
static int onenand_sync_read_bufferram(struct mtd_info *mtd, int area,
		unsigned char *buffer, int offset, size_t count)
{
	struct onenand_chip *this = mtd->priv;
	void __iomem *bufferram;

	bufferram = this->base + area;

	bufferram += onenand_bufferram_offset(mtd, area);

	this->mmcontrol(mtd, ONENAND_SYS_CFG1_SYNC_READ);

	memcpy(buffer, bufferram + offset, count);

	this->mmcontrol(mtd, 0);

	return 0;
}

/**
 * onenand_write_bufferram - [OneNAND Interface] Write the bufferram area
 * @param mtd		MTD data structure
@@ -1273,8 +1302,8 @@ static int onenand_check_maf(int manuf)
                        break;
        }

        printk(KERN_DEBUG "OneNAND Manufacturer: %s\n",
                onenand_manuf_ids[i].name);
        printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n",
                onenand_manuf_ids[i].name, manuf);

        return (i != ONENAND_MFR_UNKNOWN);
}
@@ -1385,6 +1414,12 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
	if (onenand_probe(mtd))
		return -ENXIO;

	/* Set Sync. Burst Read after probing */
	if (this->mmcontrol) {
		printk(KERN_INFO "OneNAND Sync. Burst Read support\n");
		this->read_bufferram = onenand_sync_read_bufferram;
	}

	this->state = FL_READY;
	init_waitqueue_head(&this->wq);
	spin_lock_init(&this->chip_lock);
+1 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ struct onenand_chip {
			const unsigned char *buffer, int offset, size_t count);
	unsigned short (*read_word)(void __iomem *addr);
	void (*write_word)(unsigned short value, void __iomem *addr);
	void (*mmcontrol)(struct mtd_info *mtd, int sync_read);

	spinlock_t		chip_lock;
	wait_queue_head_t	wq;
+15 −2
Original line number Diff line number Diff line
@@ -121,8 +121,21 @@
 * System Configuration 1 Register F221h (R, R/W)
 */
#define ONENAND_SYS_CFG1_SYNC_READ	(1 << 15)
#define ONENAND_SYS_CFG1_BRL		(1 << 12)
#define ONENAND_SYS_CFG1_BL		(1 << 9)
#define ONENAND_SYS_CFG1_BRL_7		(7 << 12)
#define ONENAND_SYS_CFG1_BRL_6		(6 << 12)
#define ONENAND_SYS_CFG1_BRL_5		(5 << 12)
#define ONENAND_SYS_CFG1_BRL_4		(4 << 12)
#define ONENAND_SYS_CFG1_BRL_3		(3 << 12)
#define ONENAND_SYS_CFG1_BRL_10		(2 << 12)
#define ONENAND_SYS_CFG1_BRL_9		(1 << 12)
#define ONENAND_SYS_CFG1_BRL_8		(0 << 12)
#define ONENAND_SYS_CFG1_BRL_SHIFT	(12)
#define ONENAND_SYS_CFG1_BL_32		(4 << 9)
#define ONENAND_SYS_CFG1_BL_16		(3 << 9)
#define ONENAND_SYS_CFG1_BL_8		(2 << 9)
#define ONENAND_SYS_CFG1_BL_4		(1 << 9)
#define ONENAND_SYS_CFG1_BL_CONT	(0 << 9)
#define ONENAND_SYS_CFG1_BL_SHIFT	(9)
#define ONENAND_SYS_CFG1_NO_ECC		(1 << 8)
#define ONENAND_SYS_CFG1_RDY		(1 << 7)
#define ONENAND_SYS_CFG1_INT		(1 << 6)