diff options
author | Robert Jarzmik <robert.jarzmik@free.fr> | 2011-11-19 10:02:53 -0500 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2012-01-09 13:07:24 -0500 |
commit | de03cd716ba7b8103ef9bef425be1ac72b81aeca (patch) | |
tree | e467ab24d37ef3c20c7c43e4a3b2d5fd713df1e9 /drivers/mtd/devices | |
parent | fb50b58e488d5fb3e3600592646909ddad7bd1e5 (diff) |
mtd: docg3: add erase functions
Add erase capability to the docg3 driver. The erase block is
made of 2 physical blocks, as both share all 64 pages. That
makes an erase block of at least 64 kBytes.
Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
Reviewed-by: Ivan Djelic <ivan.djelic@parrot.com>
Reviewed-by: Mike Dunn <mikedunn@newsguy.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/devices')
-rw-r--r-- | drivers/mtd/devices/docg3.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c index fd4d47bdeec2..3087b1564a4d 100644 --- a/drivers/mtd/devices/docg3.c +++ b/drivers/mtd/devices/docg3.c | |||
@@ -1033,6 +1033,96 @@ out: | |||
1033 | } | 1033 | } |
1034 | 1034 | ||
1035 | /** | 1035 | /** |
1036 | * doc_erase_block - Erase a couple of blocks | ||
1037 | * @docg3: the device | ||
1038 | * @block0: the first block to erase (leftmost plane) | ||
1039 | * @block1: the second block to erase (rightmost plane) | ||
1040 | * | ||
1041 | * Erase both blocks, and return operation status | ||
1042 | * | ||
1043 | * Returns 0 if erase successful, -EIO if erase issue, -ETIMEOUT if chip not | ||
1044 | * ready for too long | ||
1045 | */ | ||
1046 | static int doc_erase_block(struct docg3 *docg3, int block0, int block1) | ||
1047 | { | ||
1048 | int ret, sector; | ||
1049 | |||
1050 | doc_dbg("doc_erase_block(blocks=(%d,%d))\n", block0, block1); | ||
1051 | ret = doc_reset_seq(docg3); | ||
1052 | if (ret) | ||
1053 | return -EIO; | ||
1054 | |||
1055 | doc_set_reliable_mode(docg3); | ||
1056 | doc_flash_sequence(docg3, DOC_SEQ_ERASE); | ||
1057 | |||
1058 | sector = block0 << DOC_ADDR_BLOCK_SHIFT; | ||
1059 | doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR); | ||
1060 | doc_setup_addr_sector(docg3, sector); | ||
1061 | sector = block1 << DOC_ADDR_BLOCK_SHIFT; | ||
1062 | doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR); | ||
1063 | doc_setup_addr_sector(docg3, sector); | ||
1064 | doc_delay(docg3, 1); | ||
1065 | |||
1066 | doc_flash_command(docg3, DOC_CMD_ERASECYCLE2); | ||
1067 | doc_delay(docg3, 2); | ||
1068 | |||
1069 | if (is_prot_seq_error(docg3)) { | ||
1070 | doc_err("Erase blocks %d,%d error\n", block0, block1); | ||
1071 | return -EIO; | ||
1072 | } | ||
1073 | |||
1074 | return doc_write_erase_wait_status(docg3); | ||
1075 | } | ||
1076 | |||
1077 | /** | ||
1078 | * doc_erase - Erase a portion of the chip | ||
1079 | * @mtd: the device | ||
1080 | * @info: the erase info | ||
1081 | * | ||
1082 | * Erase a bunch of contiguous blocks, by pairs, as a "mtd" page of 1024 is | ||
1083 | * split into 2 pages of 512 bytes on 2 contiguous blocks. | ||
1084 | * | ||
1085 | * Returns 0 if erase successful, -EINVAL if adressing error, -EIO if erase | ||
1086 | * issue | ||
1087 | */ | ||
1088 | static int doc_erase(struct mtd_info *mtd, struct erase_info *info) | ||
1089 | { | ||
1090 | struct docg3 *docg3 = mtd->priv; | ||
1091 | uint64_t len; | ||
1092 | int block0, block1, page, ret, ofs = 0; | ||
1093 | |||
1094 | doc_dbg("doc_erase(from=%lld, len=%lld\n", info->addr, info->len); | ||
1095 | doc_set_device_id(docg3, docg3->device_id); | ||
1096 | |||
1097 | info->state = MTD_ERASE_PENDING; | ||
1098 | calc_block_sector(info->addr + info->len, | ||
1099 | &block0, &block1, &page, &ofs); | ||
1100 | ret = -EINVAL; | ||
1101 | if (block1 > docg3->max_block || page || ofs) | ||
1102 | goto reset_err; | ||
1103 | |||
1104 | ret = 0; | ||
1105 | calc_block_sector(info->addr, &block0, &block1, &page, &ofs); | ||
1106 | doc_set_reliable_mode(docg3); | ||
1107 | for (len = info->len; !ret && len > 0; len -= mtd->erasesize) { | ||
1108 | info->state = MTD_ERASING; | ||
1109 | ret = doc_erase_block(docg3, block0, block1); | ||
1110 | block0 += 2; | ||
1111 | block1 += 2; | ||
1112 | } | ||
1113 | |||
1114 | if (ret) | ||
1115 | goto reset_err; | ||
1116 | |||
1117 | info->state = MTD_ERASE_DONE; | ||
1118 | return 0; | ||
1119 | |||
1120 | reset_err: | ||
1121 | info->state = MTD_ERASE_FAILED; | ||
1122 | return ret; | ||
1123 | } | ||
1124 | |||
1125 | /** | ||
1036 | * doc_write_page - Write a single page to the chip | 1126 | * doc_write_page - Write a single page to the chip |
1037 | * @docg3: the device | 1127 | * @docg3: the device |
1038 | * @to: the offset from first block and first page, in bytes, aligned on page | 1128 | * @to: the offset from first block and first page, in bytes, aligned on page |