summaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorLadislav Michl <ladis@linux-mips.org>2019-01-09 12:28:14 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2019-01-14 12:14:25 +0100
commit9d0e9062cae80554112d8a6d94a0abc5aa446e8e (patch)
treef457b58158152fb457fc8eca0fdd81303db2f2f2 /drivers/mtd
parenta550aaba61974fef8eeb25b8e91e05a0255a1516 (diff)
downloadbarebox-9d0e9062cae80554112d8a6d94a0abc5aa446e8e.tar.gz
barebox-9d0e9062cae80554112d8a6d94a0abc5aa446e8e.tar.xz
mtd: core: Fix erase area alignment for non power of 2 erasesize
Devices as AT45DB161 DataFlash uses non power of two page size (528) while present alignment algorithm relies on erasesize being power of 2. Fix that by introducing helper functions rounding to any multiply. Note that logic is sligthly changed to be consistent as ending address is moved forward to include also last byte meant to be erased while previous implementation moved it backward. Signed-off-by: Ladislav Michl <ladis@linux-mips.org> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/core.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c
index d3cbe502fa..f44c6cfc69 100644
--- a/drivers/mtd/core.c
+++ b/drivers/mtd/core.c
@@ -141,15 +141,28 @@ static struct mtd_erase_region_info *mtd_find_erase_region(struct mtd_info *mtd,
return NULL;
}
+static loff_t __mtd_erase_round(loff_t x, uint32_t esize, int up)
+{
+ uint64_t dividend = x;
+ uint32_t mod = do_div(dividend, esize);
+ if (mod == 0)
+ return x;
+ if (up)
+ x += esize;
+ return x - mod;
+}
+#define mtd_erase_round_up(x, esize) __mtd_erase_round(x, esize, 1)
+#define mtd_erase_round_down(x, esize) __mtd_erase_round(x, esize, 0)
+
static int mtd_erase_align(struct mtd_info *mtd, loff_t *count, loff_t *offset)
{
struct mtd_erase_region_info *e;
loff_t ofs;
if (mtd->numeraseregions == 0) {
- ofs = *offset & ~(loff_t)(mtd->erasesize - 1);
- *count += (*offset - ofs);
- *count = ALIGN(*count, mtd->erasesize);
+ ofs = mtd_erase_round_down(*offset, mtd->erasesize);
+ *count += *offset - ofs;
+ *count = mtd_erase_round_up(*count, mtd->erasesize);
*offset = ofs;
return 0;
}
@@ -158,14 +171,14 @@ static int mtd_erase_align(struct mtd_info *mtd, loff_t *count, loff_t *offset)
if (!e)
return -EINVAL;
- ofs = *offset & ~(e->erasesize - 1);
- *count += (*offset - ofs);
+ ofs = mtd_erase_round_down(*offset, e->erasesize);
+ *count += *offset - ofs;
e = mtd_find_erase_region(mtd, *offset + *count);
if (!e)
return -EINVAL;
- *count = ALIGN(*count, e->erasesize);
+ *count = mtd_erase_round_up(*count, e->erasesize);
*offset = ofs;
return 0;