aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorChristian Riesch <christian.riesch@omicron.at>2014-03-06 07:18:29 -0500
committerBrian Norris <computersforpeace@gmail.com>2014-07-11 22:44:25 -0400
commitaf7447505732ea729af6a99e76fc558b6e3fcbcd (patch)
treea1da6bfeccbdb113e9f5d61a0811ffd883d4e091 /drivers/mtd
parentfeb8677935d4319c6d22b017fefac1532cd80529 (diff)
mtd: cfi_cmdset_0002: Add support for writing OTP memory
This patch adds support for writing the one time programmable (OTP) memory of Micron M29EW devices. Signed-off-by: Christian Riesch <christian.riesch@omicron.at> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c67
1 files changed, 60 insertions, 7 deletions
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 612eb3d6902c..6c575e65010b 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -67,6 +67,8 @@ static int cfi_amdstd_read_fact_prot_reg(struct mtd_info *, loff_t, size_t,
67 size_t *, u_char *); 67 size_t *, u_char *);
68static int cfi_amdstd_read_user_prot_reg(struct mtd_info *, loff_t, size_t, 68static int cfi_amdstd_read_user_prot_reg(struct mtd_info *, loff_t, size_t,
69 size_t *, u_char *); 69 size_t *, u_char *);
70static int cfi_amdstd_write_user_prot_reg(struct mtd_info *, loff_t, size_t,
71 size_t *, u_char *);
70 72
71static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, 73static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
72 size_t *retlen, const u_char *buf); 74 size_t *retlen, const u_char *buf);
@@ -530,6 +532,7 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
530 mtd->_read_fact_prot_reg = cfi_amdstd_read_fact_prot_reg; 532 mtd->_read_fact_prot_reg = cfi_amdstd_read_fact_prot_reg;
531 mtd->_get_fact_prot_info = cfi_amdstd_get_fact_prot_info; 533 mtd->_get_fact_prot_info = cfi_amdstd_get_fact_prot_info;
532 mtd->_get_user_prot_info = cfi_amdstd_get_user_prot_info; 534 mtd->_get_user_prot_info = cfi_amdstd_get_user_prot_info;
535 mtd->_write_user_prot_reg = cfi_amdstd_write_user_prot_reg;
533 mtd->flags = MTD_CAP_NORFLASH; 536 mtd->flags = MTD_CAP_NORFLASH;
534 mtd->name = map->name; 537 mtd->name = map->name;
535 mtd->writesize = 1; 538 mtd->writesize = 1;
@@ -1257,6 +1260,40 @@ static int cfi_amdstd_secsi_read (struct mtd_info *mtd, loff_t from, size_t len,
1257 return ret; 1260 return ret;
1258} 1261}
1259 1262
1263static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
1264 unsigned long adr, map_word datum,
1265 int mode);
1266
1267static int do_otp_write(struct map_info *map, struct flchip *chip, loff_t adr,
1268 size_t len, u_char *buf)
1269{
1270 int ret;
1271 while (len) {
1272 unsigned long bus_ofs = adr & ~(map_bankwidth(map)-1);
1273 int gap = adr - bus_ofs;
1274 int n = min_t(int, len, map_bankwidth(map) - gap);
1275 map_word datum;
1276
1277 if (n != map_bankwidth(map)) {
1278 /* partial write of a word, load old contents */
1279 otp_enter(map, chip, bus_ofs, map_bankwidth(map));
1280 datum = map_read(map, bus_ofs);
1281 otp_exit(map, chip, bus_ofs, map_bankwidth(map));
1282 }
1283
1284 datum = map_word_load_partial(map, datum, buf, gap, n);
1285 ret = do_write_oneword(map, chip, bus_ofs, datum, FL_OTP_WRITE);
1286 if (ret)
1287 return ret;
1288
1289 adr += n;
1290 buf += n;
1291 len -= n;
1292 }
1293
1294 return 0;
1295}
1296
1260static int cfi_amdstd_otp_walk(struct mtd_info *mtd, loff_t from, size_t len, 1297static int cfi_amdstd_otp_walk(struct mtd_info *mtd, loff_t from, size_t len,
1261 size_t *retlen, u_char *buf, 1298 size_t *retlen, u_char *buf,
1262 otp_op_t action, int user_regs) 1299 otp_op_t action, int user_regs)
@@ -1400,7 +1437,17 @@ static int cfi_amdstd_read_user_prot_reg(struct mtd_info *mtd, loff_t from,
1400 buf, do_read_secsi_onechip, 1); 1437 buf, do_read_secsi_onechip, 1);
1401} 1438}
1402 1439
1403static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, map_word datum) 1440static int cfi_amdstd_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
1441 size_t len, size_t *retlen,
1442 u_char *buf)
1443{
1444 return cfi_amdstd_otp_walk(mtd, from, len, retlen, buf,
1445 do_otp_write, 1);
1446}
1447
1448static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
1449 unsigned long adr, map_word datum,
1450 int mode)
1404{ 1451{
1405 struct cfi_private *cfi = map->fldrv_priv; 1452 struct cfi_private *cfi = map->fldrv_priv;
1406 unsigned long timeo = jiffies + HZ; 1453 unsigned long timeo = jiffies + HZ;
@@ -1421,7 +1468,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
1421 adr += chip->start; 1468 adr += chip->start;
1422 1469
1423 mutex_lock(&chip->mutex); 1470 mutex_lock(&chip->mutex);
1424 ret = get_chip(map, chip, adr, FL_WRITING); 1471 ret = get_chip(map, chip, adr, mode);
1425 if (ret) { 1472 if (ret) {
1426 mutex_unlock(&chip->mutex); 1473 mutex_unlock(&chip->mutex);
1427 return ret; 1474 return ret;
@@ -1430,6 +1477,9 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
1430 pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n", 1477 pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
1431 __func__, adr, datum.x[0] ); 1478 __func__, adr, datum.x[0] );
1432 1479
1480 if (mode == FL_OTP_WRITE)
1481 otp_enter(map, chip, adr, map_bankwidth(map));
1482
1433 /* 1483 /*
1434 * Check for a NOP for the case when the datum to write is already 1484 * Check for a NOP for the case when the datum to write is already
1435 * present - it saves time and works around buggy chips that corrupt 1485 * present - it saves time and works around buggy chips that corrupt
@@ -1446,12 +1496,13 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
1446 XIP_INVAL_CACHED_RANGE(map, adr, map_bankwidth(map)); 1496 XIP_INVAL_CACHED_RANGE(map, adr, map_bankwidth(map));
1447 ENABLE_VPP(map); 1497 ENABLE_VPP(map);
1448 xip_disable(map, chip, adr); 1498 xip_disable(map, chip, adr);
1499
1449 retry: 1500 retry:
1450 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); 1501 cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1451 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); 1502 cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
1452 cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); 1503 cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
1453 map_write(map, datum, adr); 1504 map_write(map, datum, adr);
1454 chip->state = FL_WRITING; 1505 chip->state = mode;
1455 1506
1456 INVALIDATE_CACHE_UDELAY(map, chip, 1507 INVALIDATE_CACHE_UDELAY(map, chip,
1457 adr, map_bankwidth(map), 1508 adr, map_bankwidth(map),
@@ -1460,7 +1511,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
1460 /* See comment above for timeout value. */ 1511 /* See comment above for timeout value. */
1461 timeo = jiffies + uWriteTimeout; 1512 timeo = jiffies + uWriteTimeout;
1462 for (;;) { 1513 for (;;) {
1463 if (chip->state != FL_WRITING) { 1514 if (chip->state != mode) {
1464 /* Someone's suspended the write. Sleep */ 1515 /* Someone's suspended the write. Sleep */
1465 DECLARE_WAITQUEUE(wait, current); 1516 DECLARE_WAITQUEUE(wait, current);
1466 1517
@@ -1500,6 +1551,8 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
1500 } 1551 }
1501 xip_enable(map, chip, adr); 1552 xip_enable(map, chip, adr);
1502 op_done: 1553 op_done:
1554 if (mode == FL_OTP_WRITE)
1555 otp_exit(map, chip, adr, map_bankwidth(map));
1503 chip->state = FL_READY; 1556 chip->state = FL_READY;
1504 DISABLE_VPP(map); 1557 DISABLE_VPP(map);
1505 put_chip(map, chip, adr); 1558 put_chip(map, chip, adr);
@@ -1555,7 +1608,7 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
1555 tmp_buf = map_word_load_partial(map, tmp_buf, buf, i, n); 1608 tmp_buf = map_word_load_partial(map, tmp_buf, buf, i, n);
1556 1609
1557 ret = do_write_oneword(map, &cfi->chips[chipnum], 1610 ret = do_write_oneword(map, &cfi->chips[chipnum],
1558 bus_ofs, tmp_buf); 1611 bus_ofs, tmp_buf, FL_WRITING);
1559 if (ret) 1612 if (ret)
1560 return ret; 1613 return ret;
1561 1614
@@ -1579,7 +1632,7 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
1579 datum = map_word_load(map, buf); 1632 datum = map_word_load(map, buf);
1580 1633
1581 ret = do_write_oneword(map, &cfi->chips[chipnum], 1634 ret = do_write_oneword(map, &cfi->chips[chipnum],
1582 ofs, datum); 1635 ofs, datum, FL_WRITING);
1583 if (ret) 1636 if (ret)
1584 return ret; 1637 return ret;
1585 1638
@@ -1622,7 +1675,7 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
1622 tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len); 1675 tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len);
1623 1676
1624 ret = do_write_oneword(map, &cfi->chips[chipnum], 1677 ret = do_write_oneword(map, &cfi->chips[chipnum],
1625 ofs, tmp_buf); 1678 ofs, tmp_buf, FL_WRITING);
1626 if (ret) 1679 if (ret)
1627 return ret; 1680 return ret;
1628 1681