diff options
Diffstat (limited to 'drivers/mtd/onenand/onenand_sim.c')
-rw-r--r-- | drivers/mtd/onenand/onenand_sim.c | 81 |
1 files changed, 74 insertions, 7 deletions
diff --git a/drivers/mtd/onenand/onenand_sim.c b/drivers/mtd/onenand/onenand_sim.c index d64200b7c94b..f6e3c8aebd3a 100644 --- a/drivers/mtd/onenand/onenand_sim.c +++ b/drivers/mtd/onenand/onenand_sim.c | |||
@@ -6,6 +6,10 @@ | |||
6 | * Copyright © 2005-2007 Samsung Electronics | 6 | * Copyright © 2005-2007 Samsung Electronics |
7 | * Kyungmin Park <kyungmin.park@samsung.com> | 7 | * Kyungmin Park <kyungmin.park@samsung.com> |
8 | * | 8 | * |
9 | * Vishak G <vishak.g at samsung.com>, Rohit Hagargundgi <h.rohit at samsung.com> | ||
10 | * Flex-OneNAND simulator support | ||
11 | * Copyright (C) Samsung Electronics, 2008 | ||
12 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License version 2 as | 14 | * it under the terms of the GNU General Public License version 2 as |
11 | * published by the Free Software Foundation. | 15 | * published by the Free Software Foundation. |
@@ -24,16 +28,38 @@ | |||
24 | #ifndef CONFIG_ONENAND_SIM_MANUFACTURER | 28 | #ifndef CONFIG_ONENAND_SIM_MANUFACTURER |
25 | #define CONFIG_ONENAND_SIM_MANUFACTURER 0xec | 29 | #define CONFIG_ONENAND_SIM_MANUFACTURER 0xec |
26 | #endif | 30 | #endif |
31 | |||
27 | #ifndef CONFIG_ONENAND_SIM_DEVICE_ID | 32 | #ifndef CONFIG_ONENAND_SIM_DEVICE_ID |
28 | #define CONFIG_ONENAND_SIM_DEVICE_ID 0x04 | 33 | #define CONFIG_ONENAND_SIM_DEVICE_ID 0x04 |
29 | #endif | 34 | #endif |
35 | |||
36 | #define CONFIG_FLEXONENAND ((CONFIG_ONENAND_SIM_DEVICE_ID >> 9) & 1) | ||
37 | |||
30 | #ifndef CONFIG_ONENAND_SIM_VERSION_ID | 38 | #ifndef CONFIG_ONENAND_SIM_VERSION_ID |
31 | #define CONFIG_ONENAND_SIM_VERSION_ID 0x1e | 39 | #define CONFIG_ONENAND_SIM_VERSION_ID 0x1e |
32 | #endif | 40 | #endif |
33 | 41 | ||
42 | #ifndef CONFIG_ONENAND_SIM_TECHNOLOGY_ID | ||
43 | #define CONFIG_ONENAND_SIM_TECHNOLOGY_ID CONFIG_FLEXONENAND | ||
44 | #endif | ||
45 | |||
46 | /* Initial boundary values for Flex-OneNAND Simulator */ | ||
47 | #ifndef CONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY | ||
48 | #define CONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY 0x01 | ||
49 | #endif | ||
50 | |||
51 | #ifndef CONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY | ||
52 | #define CONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY 0x01 | ||
53 | #endif | ||
54 | |||
34 | static int manuf_id = CONFIG_ONENAND_SIM_MANUFACTURER; | 55 | static int manuf_id = CONFIG_ONENAND_SIM_MANUFACTURER; |
35 | static int device_id = CONFIG_ONENAND_SIM_DEVICE_ID; | 56 | static int device_id = CONFIG_ONENAND_SIM_DEVICE_ID; |
36 | static int version_id = CONFIG_ONENAND_SIM_VERSION_ID; | 57 | static int version_id = CONFIG_ONENAND_SIM_VERSION_ID; |
58 | static int technology_id = CONFIG_ONENAND_SIM_TECHNOLOGY_ID; | ||
59 | static int boundary[] = { | ||
60 | CONFIG_FLEXONENAND_SIM_DIE0_BOUNDARY, | ||
61 | CONFIG_FLEXONENAND_SIM_DIE1_BOUNDARY, | ||
62 | }; | ||
37 | 63 | ||
38 | struct onenand_flash { | 64 | struct onenand_flash { |
39 | void __iomem *base; | 65 | void __iomem *base; |
@@ -57,12 +83,18 @@ struct onenand_flash { | |||
57 | (writew(v, this->base + ONENAND_REG_WP_STATUS)) | 83 | (writew(v, this->base + ONENAND_REG_WP_STATUS)) |
58 | 84 | ||
59 | /* It has all 0xff chars */ | 85 | /* It has all 0xff chars */ |
60 | #define MAX_ONENAND_PAGESIZE (2048 + 64) | 86 | #define MAX_ONENAND_PAGESIZE (4096 + 128) |
61 | static unsigned char *ffchars; | 87 | static unsigned char *ffchars; |
62 | 88 | ||
89 | #if CONFIG_FLEXONENAND | ||
90 | #define PARTITION_NAME "Flex-OneNAND simulator partition" | ||
91 | #else | ||
92 | #define PARTITION_NAME "OneNAND simulator partition" | ||
93 | #endif | ||
94 | |||
63 | static struct mtd_partition os_partitions[] = { | 95 | static struct mtd_partition os_partitions[] = { |
64 | { | 96 | { |
65 | .name = "OneNAND simulator partition", | 97 | .name = PARTITION_NAME, |
66 | .offset = 0, | 98 | .offset = 0, |
67 | .size = MTDPART_SIZ_FULL, | 99 | .size = MTDPART_SIZ_FULL, |
68 | }, | 100 | }, |
@@ -104,6 +136,7 @@ static void onenand_lock_handle(struct onenand_chip *this, int cmd) | |||
104 | 136 | ||
105 | switch (cmd) { | 137 | switch (cmd) { |
106 | case ONENAND_CMD_UNLOCK: | 138 | case ONENAND_CMD_UNLOCK: |
139 | case ONENAND_CMD_UNLOCK_ALL: | ||
107 | if (block_lock_scheme) | 140 | if (block_lock_scheme) |
108 | ONENAND_SET_WP_STATUS(ONENAND_WP_US, this); | 141 | ONENAND_SET_WP_STATUS(ONENAND_WP_US, this); |
109 | else | 142 | else |
@@ -228,10 +261,12 @@ static void onenand_data_handle(struct onenand_chip *this, int cmd, | |||
228 | { | 261 | { |
229 | struct mtd_info *mtd = &info->mtd; | 262 | struct mtd_info *mtd = &info->mtd; |
230 | struct onenand_flash *flash = this->priv; | 263 | struct onenand_flash *flash = this->priv; |
231 | int main_offset, spare_offset; | 264 | int main_offset, spare_offset, die = 0; |
232 | void __iomem *src; | 265 | void __iomem *src; |
233 | void __iomem *dest; | 266 | void __iomem *dest; |
234 | unsigned int i; | 267 | unsigned int i; |
268 | static int pi_operation; | ||
269 | int erasesize, rgn; | ||
235 | 270 | ||
236 | if (dataram) { | 271 | if (dataram) { |
237 | main_offset = mtd->writesize; | 272 | main_offset = mtd->writesize; |
@@ -241,10 +276,27 @@ static void onenand_data_handle(struct onenand_chip *this, int cmd, | |||
241 | spare_offset = 0; | 276 | spare_offset = 0; |
242 | } | 277 | } |
243 | 278 | ||
279 | if (pi_operation) { | ||
280 | die = readw(this->base + ONENAND_REG_START_ADDRESS2); | ||
281 | die >>= ONENAND_DDP_SHIFT; | ||
282 | } | ||
283 | |||
244 | switch (cmd) { | 284 | switch (cmd) { |
285 | case FLEXONENAND_CMD_PI_ACCESS: | ||
286 | pi_operation = 1; | ||
287 | break; | ||
288 | |||
289 | case ONENAND_CMD_RESET: | ||
290 | pi_operation = 0; | ||
291 | break; | ||
292 | |||
245 | case ONENAND_CMD_READ: | 293 | case ONENAND_CMD_READ: |
246 | src = ONENAND_CORE(flash) + offset; | 294 | src = ONENAND_CORE(flash) + offset; |
247 | dest = ONENAND_MAIN_AREA(this, main_offset); | 295 | dest = ONENAND_MAIN_AREA(this, main_offset); |
296 | if (pi_operation) { | ||
297 | writew(boundary[die], this->base + ONENAND_DATARAM); | ||
298 | break; | ||
299 | } | ||
248 | memcpy(dest, src, mtd->writesize); | 300 | memcpy(dest, src, mtd->writesize); |
249 | /* Fall through */ | 301 | /* Fall through */ |
250 | 302 | ||
@@ -257,6 +309,10 @@ static void onenand_data_handle(struct onenand_chip *this, int cmd, | |||
257 | case ONENAND_CMD_PROG: | 309 | case ONENAND_CMD_PROG: |
258 | src = ONENAND_MAIN_AREA(this, main_offset); | 310 | src = ONENAND_MAIN_AREA(this, main_offset); |
259 | dest = ONENAND_CORE(flash) + offset; | 311 | dest = ONENAND_CORE(flash) + offset; |
312 | if (pi_operation) { | ||
313 | boundary[die] = readw(this->base + ONENAND_DATARAM); | ||
314 | break; | ||
315 | } | ||
260 | /* To handle partial write */ | 316 | /* To handle partial write */ |
261 | for (i = 0; i < (1 << mtd->subpage_sft); i++) { | 317 | for (i = 0; i < (1 << mtd->subpage_sft); i++) { |
262 | int off = i * this->subpagesize; | 318 | int off = i * this->subpagesize; |
@@ -284,9 +340,18 @@ static void onenand_data_handle(struct onenand_chip *this, int cmd, | |||
284 | break; | 340 | break; |
285 | 341 | ||
286 | case ONENAND_CMD_ERASE: | 342 | case ONENAND_CMD_ERASE: |
287 | memset(ONENAND_CORE(flash) + offset, 0xff, mtd->erasesize); | 343 | if (pi_operation) |
344 | break; | ||
345 | |||
346 | if (FLEXONENAND(this)) { | ||
347 | rgn = flexonenand_region(mtd, offset); | ||
348 | erasesize = mtd->eraseregions[rgn].erasesize; | ||
349 | } else | ||
350 | erasesize = mtd->erasesize; | ||
351 | |||
352 | memset(ONENAND_CORE(flash) + offset, 0xff, erasesize); | ||
288 | memset(ONENAND_CORE_SPARE(flash, this, offset), 0xff, | 353 | memset(ONENAND_CORE_SPARE(flash, this, offset), 0xff, |
289 | (mtd->erasesize >> 5)); | 354 | (erasesize >> 5)); |
290 | break; | 355 | break; |
291 | 356 | ||
292 | default: | 357 | default: |
@@ -339,7 +404,7 @@ static void onenand_command_handle(struct onenand_chip *this, int cmd) | |||
339 | } | 404 | } |
340 | 405 | ||
341 | if (block != -1) | 406 | if (block != -1) |
342 | offset += block << this->erase_shift; | 407 | offset = onenand_addr(this, block); |
343 | 408 | ||
344 | if (page != -1) | 409 | if (page != -1) |
345 | offset += page << this->page_shift; | 410 | offset += page << this->page_shift; |
@@ -390,6 +455,7 @@ static int __init flash_init(struct onenand_flash *flash) | |||
390 | } | 455 | } |
391 | 456 | ||
392 | density = device_id >> ONENAND_DEVICE_DENSITY_SHIFT; | 457 | density = device_id >> ONENAND_DEVICE_DENSITY_SHIFT; |
458 | density &= ONENAND_DEVICE_DENSITY_MASK; | ||
393 | size = ((16 << 20) << density); | 459 | size = ((16 << 20) << density); |
394 | 460 | ||
395 | ONENAND_CORE(flash) = vmalloc(size + (size >> 5)); | 461 | ONENAND_CORE(flash) = vmalloc(size + (size >> 5)); |
@@ -405,8 +471,9 @@ static int __init flash_init(struct onenand_flash *flash) | |||
405 | writew(manuf_id, flash->base + ONENAND_REG_MANUFACTURER_ID); | 471 | writew(manuf_id, flash->base + ONENAND_REG_MANUFACTURER_ID); |
406 | writew(device_id, flash->base + ONENAND_REG_DEVICE_ID); | 472 | writew(device_id, flash->base + ONENAND_REG_DEVICE_ID); |
407 | writew(version_id, flash->base + ONENAND_REG_VERSION_ID); | 473 | writew(version_id, flash->base + ONENAND_REG_VERSION_ID); |
474 | writew(technology_id, flash->base + ONENAND_REG_TECHNOLOGY); | ||
408 | 475 | ||
409 | if (density < 2) | 476 | if (density < 2 && (!CONFIG_FLEXONENAND)) |
410 | buffer_size = 0x0400; /* 1KiB page */ | 477 | buffer_size = 0x0400; /* 1KiB page */ |
411 | else | 478 | else |
412 | buffer_size = 0x0800; /* 2KiB page */ | 479 | buffer_size = 0x0800; /* 2KiB page */ |