aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKyungmin Park <kyungmin.park@samsung.com>2005-09-28 23:53:16 -0400
committerThomas Gleixner <tglx@mtd.linutronix.de>2005-11-06 16:59:48 -0500
commit83a368380e172c1b2e9fd6ec2a62e457684adf0c (patch)
treedd5150d734a383ac042b02f7447f22a46f46a28c
parenta41371eb6d9b368e53867cd85156f07371e9f72f (diff)
[MTD] OneNAND: Enhanced support for DDP (Dual Densitiy Packages)
Add density mask for better support of DDP chips. Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--drivers/mtd/onenand/onenand_base.c39
-rw-r--r--include/linux/mtd/onenand.h1
2 files changed, 19 insertions, 21 deletions
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index a002d4025b29..99de2f055eb1 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -84,25 +84,23 @@ static void onenand_writew(unsigned short value, void __iomem *addr)
84 84
85/** 85/**
86 * onenand_block_address - [DEFAULT] Get block address 86 * onenand_block_address - [DEFAULT] Get block address
87 * @param device the device id 87 * @param this onenand chip data structure
88 * @param block the block 88 * @param block the block
89 * @return translated block address if DDP, otherwise same 89 * @return translated block address if DDP, otherwise same
90 * 90 *
91 * Setup Start Address 1 Register (F100h) 91 * Setup Start Address 1 Register (F100h)
92 */ 92 */
93static int onenand_block_address(int device, int block) 93static int onenand_block_address(struct onenand_chip *this, int block)
94{ 94{
95 if (device & ONENAND_DEVICE_IS_DDP) { 95 if (this->device_id & ONENAND_DEVICE_IS_DDP) {
96 /* Device Flash Core select, NAND Flash Block Address */ 96 /* Device Flash Core select, NAND Flash Block Address */
97 int dfs = 0, density, mask; 97 int dfs = 0;
98 98
99 density = device >> ONENAND_DEVICE_DENSITY_SHIFT; 99 if (block & this->density_mask)
100 mask = (1 << (density + 6));
101
102 if (block & mask)
103 dfs = 1; 100 dfs = 1;
104 101
105 return (dfs << ONENAND_DDP_SHIFT) | (block & (mask - 1)); 102 return (dfs << ONENAND_DDP_SHIFT) |
103 (block & (this->density_mask - 1));
106 } 104 }
107 105
108 return block; 106 return block;
@@ -110,22 +108,19 @@ static int onenand_block_address(int device, int block)
110 108
111/** 109/**
112 * onenand_bufferram_address - [DEFAULT] Get bufferram address 110 * onenand_bufferram_address - [DEFAULT] Get bufferram address
113 * @param device the device id 111 * @param this onenand chip data structure
114 * @param block the block 112 * @param block the block
115 * @return set DBS value if DDP, otherwise 0 113 * @return set DBS value if DDP, otherwise 0
116 * 114 *
117 * Setup Start Address 2 Register (F101h) for DDP 115 * Setup Start Address 2 Register (F101h) for DDP
118 */ 116 */
119static int onenand_bufferram_address(int device, int block) 117static int onenand_bufferram_address(struct onenand_chip *this, int block)
120{ 118{
121 if (device & ONENAND_DEVICE_IS_DDP) { 119 if (this->device_id & ONENAND_DEVICE_IS_DDP) {
122 /* Device BufferRAM Select */ 120 /* Device BufferRAM Select */
123 int dbs = 0, density, mask; 121 int dbs = 0;
124
125 density = device >> ONENAND_DEVICE_DENSITY_SHIFT;
126 mask = (1 << (density + 6));
127 122
128 if (block & mask) 123 if (block & this->density_mask)
129 dbs = 1; 124 dbs = 1;
130 125
131 return (dbs << ONENAND_DDP_SHIFT); 126 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 /* NOTE: The setting order of the registers is very important! */ 218 /* NOTE: The setting order of the registers is very important! */
224 if (cmd == ONENAND_CMD_BUFFERRAM) { 219 if (cmd == ONENAND_CMD_BUFFERRAM) {
225 /* Select DataRAM for DDP */ 220 /* Select DataRAM for DDP */
226 value = onenand_bufferram_address(this->device_id, block); 221 value = onenand_bufferram_address(this, block);
227 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); 222 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
228 223
229 /* Switch to the next data buffer */ 224 /* 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 229
235 if (block != -1) { 230 if (block != -1) {
236 /* Write 'DFS, FBA' of Flash */ 231 /* Write 'DFS, FBA' of Flash */
237 value = onenand_block_address(this->device_id, block); 232 value = onenand_block_address(this, block);
238 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); 233 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
239 } 234 }
240 235
@@ -263,7 +258,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
263 258
264 if (readcmd) { 259 if (readcmd) {
265 /* Select DataRAM for DDP */ 260 /* Select DataRAM for DDP */
266 value = onenand_bufferram_address(this->device_id, block); 261 value = onenand_bufferram_address(this, block);
267 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); 262 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
268 } 263 }
269 } 264 }
@@ -1313,7 +1308,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
1313 continue; 1308 continue;
1314 1309
1315 /* Set block address for read block status */ 1310 /* Set block address for read block status */
1316 value = onenand_block_address(this->device_id, block); 1311 value = onenand_block_address(this, block);
1317 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); 1312 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
1318 1313
1319 /* Check lock status */ 1314 /* Check lock status */
@@ -1415,6 +1410,8 @@ static int onenand_probe(struct mtd_info *mtd)
1415 1410
1416 density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT; 1411 density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT;
1417 this->chipsize = (16 << density) << 20; 1412 this->chipsize = (16 << density) << 20;
1413 /* Set density mask. it is used for DDP */
1414 this->density_mask = (1 << (density + 6));
1418 1415
1419 /* OneNAND page size & block size */ 1416 /* OneNAND page size & block size */
1420 /* The data buffer size is equal to page size */ 1417 /* The data buffer size is equal to page size */
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index afaa6342aa7f..d27fd12d096d 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -84,6 +84,7 @@ struct onenand_chip {
84 void __iomem *base; 84 void __iomem *base;
85 unsigned int chipsize; 85 unsigned int chipsize;
86 unsigned int device_id; 86 unsigned int device_id;
87 unsigned int density_mask;
87 unsigned int options; 88 unsigned int options;
88 89
89 unsigned int erase_shift; 90 unsigned int erase_shift;