/* only needed for short periods, so this is rather simple */ #define xip_disable() local_irq_disable()
#define xip_allowed(base, map) \ do { \
(void) map_read(map, base); \
xip_iprefetch(); \
local_irq_enable(); \
} while (0)
#define xip_enable(base, map, cfi) \ do { \
cfi_qry_mode_off(base, map, cfi); \
xip_allowed(base, map); \
} while (0)
#define xip_disable_qry(base, map, cfi) \ do { \
xip_disable(); \
cfi_qry_mode_on(base, map, cfi); \
} while (0)
#else
#define xip_disable() do { } while (0) #define xip_allowed(base, map) do { } while (0) #define xip_enable(base, map, cfi) do { } while (0) #define xip_disable_qry(base, map, cfi) do { } while (0)
#endif
/* * This fixup occurs immediately after reading the CFI structure and can affect * the number of chips detected, unlike cfi_fixup, which occurs after an * mtd_info structure has been created for the chip.
*/ struct cfi_early_fixup {
uint16_t mfr;
uint16_t id; void (*fixup)(struct cfi_private *cfi);
};
if ((base + 0) >= map->size) {
printk(KERN_NOTICE "Probe at base[0x00](0x%08lx) past the end of the map(0x%08lx)\n",
(unsignedlong)base, map->size -1); return 0;
} if ((base + 0xff) >= map->size) {
printk(KERN_NOTICE "Probe at base[0x55](0x%08lx) past the end of the map(0x%08lx)\n",
(unsignedlong)base + 0x55, map->size -1); return 0;
}
if (!cfi->numchips) { /* This is the first time we're called. Set up the CFI
stuff accordingly and return */ return cfi_chip_setup(map, cfi);
}
/* Check each previous chip to see if it's an alias */ for (i=0; i < (base >> cfi->chipshift); i++) { unsignedlong start; if(!test_bit(i, chip_map)) { /* Skip location; no valid chip at this address */ continue;
}
start = i << cfi->chipshift; /* This chip should be in read mode if it's one
we've already touched. */ if (cfi_qry_present(map, start, cfi)) { /* Eep. This chip also had the QRY marker.
* Is it an alias for the new one? */
cfi_qry_mode_off(start, map, cfi);
/* If the QRY marker goes away, it's an alias */ if (!cfi_qry_present(map, start, cfi)) {
xip_allowed(base, map);
printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
map->name, base, start); return 0;
} /* Yes, it's actually got QRY for data. Most * unfortunate. Stick the new chip in read mode
* too and if it's the same, assume it's an alias. */ /* FIXME: Use other modes to do a proper check */
cfi_qry_mode_off(base, map, cfi);
if (cfi_qry_present(map, base, cfi)) {
xip_allowed(base, map);
printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
map->name, base, start); return 0;
}
}
}
/* OK, if we got to here, then none of the previous chips appear to
be aliases for the current one. */
set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */
cfi->numchips++;
/* Put it back into Read Mode */
cfi_qry_mode_off(base, map, cfi);
xip_allowed(base, map);
printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
map->name, cfi->interleave, cfi->device_type*8, base,
map->bankwidth*8);
return 1;
}
staticvoid fixup_s70gl02gs_chips(struct cfi_private *cfi)
{ /* * S70GL02GS flash reports a single 256 MiB chip, but is really made up * of two 128 MiB chips with 1024 sectors each.
*/
cfi->cfiq->DevSize = 27;
cfi->cfiq->EraseRegionInfo[0] = 0x20003ff;
pr_warn("Bad S70GL02GS CFI data; adjust to detect 2 chips\n");
}
/* * Note we put the device back into Read Mode BEFORE going into Auto * Select Mode, as some devices support nesting of modes, others * don't. This way should always work. * On cmdset 0001 the writes of 0xaa and 0x55 are not needed, and * so should be treated as nops or illegal (and so put the device * back into Read Mode, which is a nop in this case).
*/
cfi_send_gen_cmd(0xf0, 0, base, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0xaa, addr_unlock1, base, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0x55, addr_unlock2, base, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0x90, addr_unlock1, base, map, cfi, cfi->device_type, NULL);
cfi->mfr = cfi_read_query16(map, base);
cfi->id = cfi_read_query16(map, base + ofs_factor);
/* Get AMD/Spansion extended JEDEC ID */ if (cfi->mfr == CFI_MFR_AMD && (cfi->id & 0xff) == 0x7e)
cfi->id = cfi_read_query(map, base + 0xe * ofs_factor) << 8 |
cfi_read_query(map, base + 0xf * ofs_factor);
/* Put it back into Read Mode */
cfi_qry_mode_off(base, map, cfi);
xip_allowed(base, map);
cfi_early_fixup(cfi, cfi_early_fixup_table);
printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank. Manufacturer ID %#08x Chip ID %#08x\n",
map->name, cfi->interleave, cfi->device_type*8, base,
map->bankwidth*8, cfi->mfr, cfi->id);
struct mtd_info *cfi_probe(struct map_info *map)
{ /* * Just use the generic probe stuff to call our CFI-specific * chip_probe routine in all the possible permutations, etc.
*/ return mtd_do_chip_probe(map, &cfi_chip_probe);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.