Commit 83a36838 authored by Kyungmin Park's avatar Kyungmin Park Committed by Thomas Gleixner

[MTD] OneNAND: Enhanced support for DDP (Dual Densitiy Packages)

Add density mask for better support of DDP chips.
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent a41371eb
...@@ -84,25 +84,23 @@ static void onenand_writew(unsigned short value, void __iomem *addr) ...@@ -84,25 +84,23 @@ static void onenand_writew(unsigned short value, void __iomem *addr)
/** /**
* onenand_block_address - [DEFAULT] Get block address * onenand_block_address - [DEFAULT] Get block address
* @param device the device id * @param this onenand chip data structure
* @param block the block * @param block the block
* @return translated block address if DDP, otherwise same * @return translated block address if DDP, otherwise same
* *
* Setup Start Address 1 Register (F100h) * Setup Start Address 1 Register (F100h)
*/ */
static int onenand_block_address(int device, int block) static int onenand_block_address(struct onenand_chip *this, int block)
{ {
if (device & ONENAND_DEVICE_IS_DDP) { if (this->device_id & ONENAND_DEVICE_IS_DDP) {
/* Device Flash Core select, NAND Flash Block Address */ /* Device Flash Core select, NAND Flash Block Address */
int dfs = 0, density, mask; int dfs = 0;
density = device >> ONENAND_DEVICE_DENSITY_SHIFT; if (block & this->density_mask)
mask = (1 << (density + 6));
if (block & mask)
dfs = 1; dfs = 1;
return (dfs << ONENAND_DDP_SHIFT) | (block & (mask - 1)); return (dfs << ONENAND_DDP_SHIFT) |
(block & (this->density_mask - 1));
} }
return block; return block;
...@@ -110,22 +108,19 @@ static int onenand_block_address(int device, int block) ...@@ -110,22 +108,19 @@ static int onenand_block_address(int device, int block)
/** /**
* onenand_bufferram_address - [DEFAULT] Get bufferram address * onenand_bufferram_address - [DEFAULT] Get bufferram address
* @param device the device id * @param this onenand chip data structure
* @param block the block * @param block the block
* @return set DBS value if DDP, otherwise 0 * @return set DBS value if DDP, otherwise 0
* *
* Setup Start Address 2 Register (F101h) for DDP * Setup Start Address 2 Register (F101h) for DDP
*/ */
static int onenand_bufferram_address(int device, int block) static int onenand_bufferram_address(struct onenand_chip *this, int block)
{ {
if (device & ONENAND_DEVICE_IS_DDP) { if (this->device_id & ONENAND_DEVICE_IS_DDP) {
/* Device BufferRAM Select */ /* Device BufferRAM Select */
int dbs = 0, density, mask; int dbs = 0;
density = device >> ONENAND_DEVICE_DENSITY_SHIFT;
mask = (1 << (density + 6));
if (block & mask) if (block & this->density_mask)
dbs = 1; dbs = 1;
return (dbs << ONENAND_DDP_SHIFT); return (dbs << ONENAND_DDP_SHIFT);
...@@ -223,7 +218,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le ...@@ -223,7 +218,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
/* NOTE: The setting order of the registers is very important! */ /* NOTE: The setting order of the registers is very important! */
if (cmd == ONENAND_CMD_BUFFERRAM) { if (cmd == ONENAND_CMD_BUFFERRAM) {
/* Select DataRAM for DDP */ /* Select DataRAM for DDP */
value = onenand_bufferram_address(this->device_id, block); value = onenand_bufferram_address(this, block);
this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
/* Switch to the next data buffer */ /* Switch to the next data buffer */
...@@ -234,7 +229,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le ...@@ -234,7 +229,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
if (block != -1) { if (block != -1) {
/* Write 'DFS, FBA' of Flash */ /* Write 'DFS, FBA' of Flash */
value = onenand_block_address(this->device_id, block); value = onenand_block_address(this, block);
this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
} }
...@@ -263,7 +258,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le ...@@ -263,7 +258,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
if (readcmd) { if (readcmd) {
/* Select DataRAM for DDP */ /* Select DataRAM for DDP */
value = onenand_bufferram_address(this->device_id, block); value = onenand_bufferram_address(this, block);
this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
} }
} }
...@@ -1313,7 +1308,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) ...@@ -1313,7 +1308,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
continue; continue;
/* Set block address for read block status */ /* Set block address for read block status */
value = onenand_block_address(this->device_id, block); value = onenand_block_address(this, block);
this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
/* Check lock status */ /* Check lock status */
...@@ -1415,6 +1410,8 @@ static int onenand_probe(struct mtd_info *mtd) ...@@ -1415,6 +1410,8 @@ static int onenand_probe(struct mtd_info *mtd)
density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT; density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT;
this->chipsize = (16 << density) << 20; this->chipsize = (16 << density) << 20;
/* Set density mask. it is used for DDP */
this->density_mask = (1 << (density + 6));
/* OneNAND page size & block size */ /* OneNAND page size & block size */
/* The data buffer size is equal to page size */ /* The data buffer size is equal to page size */
......
...@@ -84,6 +84,7 @@ struct onenand_chip { ...@@ -84,6 +84,7 @@ struct onenand_chip {
void __iomem *base; void __iomem *base;
unsigned int chipsize; unsigned int chipsize;
unsigned int device_id; unsigned int device_id;
unsigned int density_mask;
unsigned int options; unsigned int options;
unsigned int erase_shift; unsigned int erase_shift;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment