/*
Common Flash Interface probe code.
(C) 2000 Red Hat. GPL'd.
- $Id: jedec_probe.c,v 1.58 2004/11/16 18:29:00 dwmw2 Exp $
+ $Id: jedec_probe.c,v 1.51 2004/07/14 14:44:30 thayne Exp $
See JEDEC (http://www.jedec.org/) standard JESD21C (section 3.5)
for the standard this probe goes back to.
#define I82802AC 0x00ac
/* Macronix */
-#define MX29LV040C 0x004F
#define MX29LV160T 0x22C4
#define MX29LV160B 0x2249
#define MX29F016 0x00AD
#define M50FW040 0x002C
#define M50FW080 0x002D
#define M50FW016 0x002E
-#define M50LPW080 0x002F
/* SST */
#define SST29EE020 0x0010
struct unlock_addr {
- u32 addr1;
- u32 addr2;
+ int addr1;
+ int addr2;
};
ERASEINFO(0x10000,8),
}
}, {
- mfr_id: MANUFACTURER_AMD,
- dev_id: AM29F002T,
- name: "AMD AM29F002T",
- DevSize: SIZE_256KiB,
- NumEraseRegions: 4,
- regions: {ERASEINFO(0x10000,3),
+ .mfr_id = MANUFACTURER_AMD,
+ .dev_id = AM29F002T,
+ .name = "AMD AM29F002T",
+ .DevSize = SIZE_256KiB,
+ .NumEraseRegions = 4,
+ .regions = {ERASEINFO(0x10000,3),
ERASEINFO(0x08000,1),
ERASEINFO(0x02000,2),
ERASEINFO(0x04000,1)
ERASEINFO(0x04000,1)
}
}, {
- mfr_id: MANUFACTURER_HYUNDAI,
- dev_id: HY29F002T,
- name: "Hyundai HY29F002T",
- DevSize: SIZE_256KiB,
- NumEraseRegions: 4,
- regions: {ERASEINFO(0x10000,3),
+ .mfr_id = MANUFACTURER_HYUNDAI,
+ .dev_id = HY29F002T,
+ .name = "Hyundai HY29F002T",
+ .DevSize = SIZE_256KiB,
+ .NumEraseRegions = 4,
+ .regions = {ERASEINFO(0x10000,3),
ERASEINFO(0x08000,1),
ERASEINFO(0x02000,2),
ERASEINFO(0x04000,1)
.regions = {
ERASEINFO(0x10000,16),
}
- }, {
- .mfr_id = MANUFACTURER_MACRONIX,
- .dev_id = MX29LV040C,
- .name = "Macronix MX29LV040C",
- .uaddr = {
- [0] = MTD_UADDR_0x0555_0x02AA, /* x8 */
- },
- .DevSize = SIZE_512KiB,
- .CmdSet = P_ID_AMD_STD,
- .NumEraseRegions= 1,
- .regions = {
- ERASEINFO(0x10000,8),
- }
}, {
.mfr_id = MANUFACTURER_MACRONIX,
.dev_id = MX29LV160T,
ERASEINFO(0x10000,7),
}
}, {
- mfr_id: MANUFACTURER_MACRONIX,
- dev_id: MX29F002T,
- name: "Macronix MX29F002T",
- DevSize: SIZE_256KiB,
- NumEraseRegions: 4,
- regions: {ERASEINFO(0x10000,3),
+ .mfr_id = MANUFACTURER_MACRONIX,
+ .dev_id = MX29F002T,
+ .name = "Macronix MX29F002T",
+ .DevSize = SIZE_256KiB,
+ .NumEraseRegions = 4,
+ .regions = {ERASEINFO(0x10000,3),
ERASEINFO(0x08000,1),
ERASEINFO(0x02000,2),
ERASEINFO(0x04000,1)
.DevSize = SIZE_256KiB,
.CmdSet = P_ID_SST_PAGE,
.NumEraseRegions= 1,
- regions: {ERASEINFO(0x01000,64),
+ .regions = {ERASEINFO(0x01000,64),
}
}, {
.mfr_id = MANUFACTURER_SST,
.DevSize = SIZE_256KiB,
.CmdSet = P_ID_SST_PAGE,
.NumEraseRegions= 1,
- regions: {ERASEINFO(0x01000,64),
+ .regions = {ERASEINFO(0x01000,64),
}
}, {
.mfr_id = MANUFACTURER_SST,
ERASEINFO(0x01000,256),
}
}, {
- .mfr_id = MANUFACTURER_SST, /* should be CFI */
- .dev_id = SST39LF160,
- .name = "SST 39LF160",
- .uaddr = {
- [0] = MTD_UADDR_0x5555_0x2AAA, /* x8 */
- [1] = MTD_UADDR_0x5555_0x2AAA /* x16 */
- },
- .DevSize = SIZE_2MiB,
- .CmdSet = P_ID_AMD_STD,
- .NumEraseRegions= 2,
- .regions = {
- ERASEINFO(0x1000,256),
- ERASEINFO(0x1000,256)
- }
-
- }, {
.mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */
.dev_id = M29W800DT,
.name = "ST M29W800DT",
.regions = {
ERASEINFO(0x10000,32),
}
- }, {
- .mfr_id = MANUFACTURER_ST,
- .dev_id = M50LPW080,
- .name = "ST M50LPW080",
- .uaddr = {
- [0] = MTD_UADDR_UNNECESSARY, /* x8 */
- },
- .DevSize = SIZE_1MiB,
- .CmdSet = P_ID_INTEL_EXT,
- .NumEraseRegions= 1,
- .regions = {
- ERASEINFO(0x10000,16),
- }
}, {
.mfr_id = MANUFACTURER_TOSHIBA,
.dev_id = TC58FVT160,
static int jedec_probe_chip(struct map_info *map, __u32 base,
unsigned long *chip_map, struct cfi_private *cfi);
-static struct mtd_info *jedec_probe(struct map_info *map);
+struct mtd_info *jedec_probe(struct map_info *map);
static inline u32 jedec_read_mfr(struct map_info *map, __u32 base,
struct cfi_private *cfi)
{
map_word result;
unsigned long mask;
- u32 ofs = cfi_build_cmd_addr(0, cfi_interleave(cfi), cfi->device_type);
mask = (1 << (cfi->device_type * 8)) -1;
- result = map_read(map, base + ofs);
+ result = map_read(map, base);
return result.x[0] & mask;
}
static inline u32 jedec_read_id(struct map_info *map, __u32 base,
struct cfi_private *cfi)
{
+ int osf;
map_word result;
unsigned long mask;
- u32 ofs = cfi_build_cmd_addr(1, cfi_interleave(cfi), cfi->device_type);
+ osf = cfi->interleave *cfi->device_type;
mask = (1 << (cfi->device_type * 8)) -1;
- result = map_read(map, base + ofs);
+ result = map_read(map, base + osf);
return result.x[0] & mask;
}
* as they will ignore the writes and dont care what address
* the F0 is written to */
if(cfi->addr_unlock1) {
- DEBUG( MTD_DEBUG_LEVEL3,
- "reset unlock called %x %x \n",
- cfi->addr_unlock1,cfi->addr_unlock2);
- cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
- cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
+ /*printk("reset unlock called %x %x \n",cfi->addr_unlock1,cfi->addr_unlock2);*/
+ cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
}
cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
static int cfi_jedec_setup(struct cfi_private *p_cfi, int index)
{
int i,num_erase_regions;
+ unsigned long mask;
__u8 uaddr;
printk("Found: %s\n",jedec_table[index].name);
}
/* Mask out address bits which are smaller than the device type */
- p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1;
- p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2;
+ mask = ~(p_cfi->device_type-1);
+ p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1 & mask;
+ p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2 & mask;
return 1; /* ok */
}
int rc = 0; /* failure until all tests pass */
u32 mfr, id;
__u8 uaddr;
+ unsigned long mask;
/*
* The IDs must match. For X16 and X32 devices operating in
DEBUG( MTD_DEBUG_LEVEL3,
"MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n",
__func__, base, 1 << finfo->DevSize, base + (1 << finfo->DevSize) );
- if ( base + cfi_interleave(cfi) * ( 1 << finfo->DevSize ) > map->size ) {
+ if ( base + cfi->interleave * ( 1 << finfo->DevSize ) > map->size ) {
DEBUG( MTD_DEBUG_LEVEL3,
"MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n",
__func__, finfo->mfr_id, finfo->dev_id,
goto match_done;
}
+ mask = ~(cfi->device_type-1);
+
DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n",
__func__, cfi->addr_unlock1, cfi->addr_unlock2 );
if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr
- && ( unlock_addrs[uaddr].addr1 != cfi->addr_unlock1 ||
- unlock_addrs[uaddr].addr2 != cfi->addr_unlock2 ) ) {
+ && ( (unlock_addrs[uaddr].addr1 & mask) != cfi->addr_unlock1 ||
+ (unlock_addrs[uaddr].addr2 & mask) != cfi->addr_unlock2 ) ) {
DEBUG( MTD_DEBUG_LEVEL3,
- "MTD %s(): 0x%.4x 0x%.4x did not match\n",
- __func__,
- unlock_addrs[uaddr].addr1,
- unlock_addrs[uaddr].addr2);
+ "MTD %s(): 0x%.4lx 0x%.4lx did not match\n",
+ __func__,
+ unlock_addrs[uaddr].addr1 & mask,
+ unlock_addrs[uaddr].addr2 & mask);
goto match_done;
}
*/
DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): return to ID mode\n", __func__ );
if(cfi->addr_unlock1) {
- cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
- cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
+ cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
}
- cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
+ cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
/* FIXME - should have a delay before continuing */
match_done:
{
int i;
enum uaddr uaddr_idx = MTD_UADDR_NOT_SUPPORTED;
- u32 probe_offset1, probe_offset2;
retry:
if (!cfi->numchips) {
+ unsigned long mask = ~(cfi->device_type-1);
+
uaddr_idx++;
if (MTD_UADDR_UNNECESSARY == uaddr_idx)
return 0;
/* Mask out address bits which are smaller than the device type */
- cfi->addr_unlock1 = unlock_addrs[uaddr_idx].addr1;
- cfi->addr_unlock2 = unlock_addrs[uaddr_idx].addr2;
+ cfi->addr_unlock1 = unlock_addrs[uaddr_idx].addr1 & mask;
+ cfi->addr_unlock2 = unlock_addrs[uaddr_idx].addr2 & mask;
}
/* Make certain we aren't probing past the end of map */
return 0;
}
- /* Ensure the unlock addresses we try stay inside the map */
- probe_offset1 = cfi_build_cmd_addr(
- cfi->addr_unlock1,
- cfi_interleave(cfi),
- cfi->device_type);
- probe_offset2 = cfi_build_cmd_addr(
- cfi->addr_unlock1,
- cfi_interleave(cfi),
- cfi->device_type);
- if ( ((base + probe_offset1 + map_bankwidth(map)) >= map->size) ||
- ((base + probe_offset2 + map_bankwidth(map)) >= map->size))
- {
- goto retry;
+ if ((base + cfi->addr_unlock1) >= map->size) {
+ printk(KERN_NOTICE
+ "Probe at addr_unlock1(0x%08x + 0x%08x) past the end of the map(0x%08lx)\n",
+ base, cfi->addr_unlock1, map->size -1);
+
+ return 0;
}
+ if ((base + cfi->addr_unlock2) >= map->size) {
+ printk(KERN_NOTICE
+ "Probe at addr_unlock2(0x%08x + 0x%08x) past the end of the map(0x%08lx)\n",
+ base, cfi->addr_unlock2, map->size -1);
+ return 0;
+ }
+
/* Reset */
jedec_reset(base, map, cfi);
/* Autoselect Mode */
if(cfi->addr_unlock1) {
- cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
- cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
+ cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
+ cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
}
- cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
+ cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
/* FIXME - should have a delay before continuing */
if (!cfi->numchips) {
cfi->id = jedec_read_id(map, base, cfi);
DEBUG(MTD_DEBUG_LEVEL3,
"Search for id:(%02x %02x) interleave(%d) type(%d)\n",
- cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type);
+ cfi->mfr, cfi->id, cfi->interleave, cfi->device_type);
for (i=0; i<sizeof(jedec_table)/sizeof(jedec_table[0]); i++) {
if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) {
DEBUG( MTD_DEBUG_LEVEL3,
jedec_reset(base, map, cfi);
printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
- map->name, cfi_interleave(cfi), cfi->device_type*8, base,
+ map->name, cfi->interleave, cfi->device_type*8, base,
map->bankwidth*8);
return 1;
.probe_chip = jedec_probe_chip
};
-static struct mtd_info *jedec_probe(struct map_info *map)
+struct mtd_info *jedec_probe(struct map_info *map)
{
/*
* Just use the generic probe stuff to call our CFI-specific
.module = THIS_MODULE
};
-static int __init jedec_probe_init(void)
+int __init jedec_probe_init(void)
{
register_mtd_chip_driver(&jedec_chipdrv);
return 0;