diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0002.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 8901c4412daf..ddc5bd783354 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
@@ -45,9 +45,11 @@ | |||
45 | #define MAX_WORD_RETRIES 3 | 45 | #define MAX_WORD_RETRIES 3 |
46 | 46 | ||
47 | #define MANUFACTURER_AMD 0x0001 | 47 | #define MANUFACTURER_AMD 0x0001 |
48 | #define MANUFACTURER_ATMEL 0x001F | ||
48 | #define MANUFACTURER_SST 0x00BF | 49 | #define MANUFACTURER_SST 0x00BF |
49 | #define SST49LF004B 0x0060 | 50 | #define SST49LF004B 0x0060 |
50 | #define SST49LF008A 0x005a | 51 | #define SST49LF008A 0x005a |
52 | #define AT49BV6416 0x00d6 | ||
51 | 53 | ||
52 | static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | 54 | static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); |
53 | static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); | 55 | static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); |
@@ -68,6 +70,9 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr | |||
68 | static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr); | 70 | static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr); |
69 | #include "fwh_lock.h" | 71 | #include "fwh_lock.h" |
70 | 72 | ||
73 | static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, size_t len); | ||
74 | static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, size_t len); | ||
75 | |||
71 | static struct mtd_chip_driver cfi_amdstd_chipdrv = { | 76 | static struct mtd_chip_driver cfi_amdstd_chipdrv = { |
72 | .probe = NULL, /* Not usable directly */ | 77 | .probe = NULL, /* Not usable directly */ |
73 | .destroy = cfi_amdstd_destroy, | 78 | .destroy = cfi_amdstd_destroy, |
@@ -199,6 +204,16 @@ static void fixup_use_erase_chip(struct mtd_info *mtd, void *param) | |||
199 | 204 | ||
200 | } | 205 | } |
201 | 206 | ||
207 | /* | ||
208 | * Some Atmel chips (e.g. the AT49BV6416) power-up with all sectors | ||
209 | * locked by default. | ||
210 | */ | ||
211 | static void fixup_use_atmel_lock(struct mtd_info *mtd, void *param) | ||
212 | { | ||
213 | mtd->lock = cfi_atmel_lock; | ||
214 | mtd->unlock = cfi_atmel_unlock; | ||
215 | } | ||
216 | |||
202 | static struct cfi_fixup cfi_fixup_table[] = { | 217 | static struct cfi_fixup cfi_fixup_table[] = { |
203 | #ifdef AMD_BOOTLOC_BUG | 218 | #ifdef AMD_BOOTLOC_BUG |
204 | { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL }, | 219 | { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL }, |
@@ -228,6 +243,7 @@ static struct cfi_fixup fixup_table[] = { | |||
228 | * we know that is the case. | 243 | * we know that is the case. |
229 | */ | 244 | */ |
230 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL }, | 245 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL }, |
246 | { CFI_MFR_ATMEL, AT49BV6416, fixup_use_atmel_lock, NULL }, | ||
231 | { 0, 0, NULL, NULL } | 247 | { 0, 0, NULL, NULL } |
232 | }; | 248 | }; |
233 | 249 | ||
@@ -1628,6 +1644,80 @@ static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr) | |||
1628 | return 0; | 1644 | return 0; |
1629 | } | 1645 | } |
1630 | 1646 | ||
1647 | static int do_atmel_lock(struct map_info *map, struct flchip *chip, | ||
1648 | unsigned long adr, int len, void *thunk) | ||
1649 | { | ||
1650 | struct cfi_private *cfi = map->fldrv_priv; | ||
1651 | int ret; | ||
1652 | |||
1653 | spin_lock(chip->mutex); | ||
1654 | ret = get_chip(map, chip, adr + chip->start, FL_LOCKING); | ||
1655 | if (ret) | ||
1656 | goto out_unlock; | ||
1657 | chip->state = FL_LOCKING; | ||
1658 | |||
1659 | DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n", | ||
1660 | __func__, adr, len); | ||
1661 | |||
1662 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, | ||
1663 | cfi->device_type, NULL); | ||
1664 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, | ||
1665 | cfi->device_type, NULL); | ||
1666 | cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, | ||
1667 | cfi->device_type, NULL); | ||
1668 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, | ||
1669 | cfi->device_type, NULL); | ||
1670 | cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, | ||
1671 | cfi->device_type, NULL); | ||
1672 | map_write(map, CMD(0x40), chip->start + adr); | ||
1673 | |||
1674 | chip->state = FL_READY; | ||
1675 | put_chip(map, chip, adr + chip->start); | ||
1676 | ret = 0; | ||
1677 | |||
1678 | out_unlock: | ||
1679 | spin_unlock(chip->mutex); | ||
1680 | return ret; | ||
1681 | } | ||
1682 | |||
1683 | static int do_atmel_unlock(struct map_info *map, struct flchip *chip, | ||
1684 | unsigned long adr, int len, void *thunk) | ||
1685 | { | ||
1686 | struct cfi_private *cfi = map->fldrv_priv; | ||
1687 | int ret; | ||
1688 | |||
1689 | spin_lock(chip->mutex); | ||
1690 | ret = get_chip(map, chip, adr + chip->start, FL_UNLOCKING); | ||
1691 | if (ret) | ||
1692 | goto out_unlock; | ||
1693 | chip->state = FL_UNLOCKING; | ||
1694 | |||
1695 | DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n", | ||
1696 | __func__, adr, len); | ||
1697 | |||
1698 | cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, | ||
1699 | cfi->device_type, NULL); | ||
1700 | map_write(map, CMD(0x70), adr); | ||
1701 | |||
1702 | chip->state = FL_READY; | ||
1703 | put_chip(map, chip, adr + chip->start); | ||
1704 | ret = 0; | ||
1705 | |||
1706 | out_unlock: | ||
1707 | spin_unlock(chip->mutex); | ||
1708 | return ret; | ||
1709 | } | ||
1710 | |||
1711 | static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, size_t len) | ||
1712 | { | ||
1713 | return cfi_varsize_frob(mtd, do_atmel_lock, ofs, len, NULL); | ||
1714 | } | ||
1715 | |||
1716 | static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) | ||
1717 | { | ||
1718 | return cfi_varsize_frob(mtd, do_atmel_unlock, ofs, len, NULL); | ||
1719 | } | ||
1720 | |||
1631 | 1721 | ||
1632 | static void cfi_amdstd_sync (struct mtd_info *mtd) | 1722 | static void cfi_amdstd_sync (struct mtd_info *mtd) |
1633 | { | 1723 | { |