diff options
author | Kyungmin Park <kyungmin.park@samsung.com> | 2005-09-28 23:53:16 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@mtd.linutronix.de> | 2005-11-06 16:59:48 -0500 |
commit | 83a368380e172c1b2e9fd6ec2a62e457684adf0c (patch) | |
tree | dd5150d734a383ac042b02f7447f22a46f46a28c | |
parent | a41371eb6d9b368e53867cd85156f07371e9f72f (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.c | 39 | ||||
-rw-r--r-- | include/linux/mtd/onenand.h | 1 |
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 | */ |
93 | static int onenand_block_address(int device, int block) | 93 | static 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 | */ |
119 | static int onenand_bufferram_address(int device, int block) | 117 | static 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; |