+/* #define DEBUG_CFI_FEATURES */
+
+
+#ifdef DEBUG_CFI_FEATURES
+static void cfi_tell_features(struct cfi_pri_amdstd *extp)
+{
+ const char* erase_suspend[3] = {
+ "Not supported", "Read only", "Read/write"
+ };
+ const char* top_bottom[6] = {
+ "No WP", "8x8KiB sectors at top & bottom, no WP",
+ "Bottom boot", "Top boot",
+ "Uniform, Bottom WP", "Uniform, Top WP"
+ };
+
+ printk(" Silicon revision: %d\n", extp->SiliconRevision >> 1);
+ printk(" Address sensitive unlock: %s\n",
+ (extp->SiliconRevision & 1) ? "Not required" : "Required");
+
+ if (extp->EraseSuspend < ARRAY_SIZE(erase_suspend))
+ printk(" Erase Suspend: %s\n", erase_suspend[extp->EraseSuspend]);
+ else
+ printk(" Erase Suspend: Unknown value %d\n", extp->EraseSuspend);
+
+ if (extp->BlkProt == 0)
+ printk(" Block protection: Not supported\n");
+ else
+ printk(" Block protection: %d sectors per group\n", extp->BlkProt);
+
+
+ printk(" Temporary block unprotect: %s\n",
+ extp->TmpBlkUnprotect ? "Supported" : "Not supported");
+ printk(" Block protect/unprotect scheme: %d\n", extp->BlkProtUnprot);
+ printk(" Number of simultaneous operations: %d\n", extp->SimultaneousOps);
+ printk(" Burst mode: %s\n",
+ extp->BurstMode ? "Supported" : "Not supported");
+ if (extp->PageMode == 0)
+ printk(" Page mode: Not supported\n");
+ else
+ printk(" Page mode: %d word page\n", extp->PageMode << 2);
+
+ printk(" Vpp Supply Minimum Program/Erase Voltage: %d.%d V\n",
+ extp->VppMin >> 4, extp->VppMin & 0xf);
+ printk(" Vpp Supply Maximum Program/Erase Voltage: %d.%d V\n",
+ extp->VppMax >> 4, extp->VppMax & 0xf);
+
+ if (extp->TopBottom < ARRAY_SIZE(top_bottom))
+ printk(" Top/Bottom Boot Block: %s\n", top_bottom[extp->TopBottom]);
+ else
+ printk(" Top/Bottom Boot Block: Unknown value %d\n", extp->TopBottom);
+}
+#endif
+
+#ifdef AMD_BOOTLOC_BUG
+/* Wheee. Bring me the head of someone at AMD. */
+static void fixup_amd_bootblock(struct mtd_info *mtd, void* param)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ struct cfi_pri_amdstd *extp = cfi->cmdset_priv;
+ __u8 major = extp->MajorVersion;
+ __u8 minor = extp->MinorVersion;
+
+ if (((major << 8) | minor) < 0x3131) {
+ /* CFI version 1.0 => don't trust bootloc */
+ if (cfi->id & 0x80) {
+ printk(KERN_WARNING "%s: JEDEC Device ID is 0x%02X. Assuming broken CFI table.\n", map->name, cfi->id);
+ extp->TopBottom = 3; /* top boot */
+ } else {
+ extp->TopBottom = 2; /* bottom boot */
+ }
+ }
+}
+#endif
+
+static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ if (cfi->cfiq->BufWriteTimeoutTyp) {
+ DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" );
+ mtd->write = cfi_amdstd_write_buffers;
+ }
+}
+
+static void fixup_use_secsi(struct mtd_info *mtd, void *param)
+{
+ /* Setup for chips with a secsi area */
+ mtd->read_user_prot_reg = cfi_amdstd_secsi_read;
+ mtd->read_fact_prot_reg = cfi_amdstd_secsi_read;
+}
+
+static void fixup_use_erase_chip(struct mtd_info *mtd, void *param)
+{
+ struct map_info *map = mtd->priv;
+ struct cfi_private *cfi = map->fldrv_priv;
+ if ((cfi->cfiq->NumEraseRegions == 1) &&
+ ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0)) {
+ mtd->erase = cfi_amdstd_erase_chip;
+ }
+
+}
+
+static struct cfi_fixup cfi_fixup_table[] = {
+#ifdef AMD_BOOTLOC_BUG
+ { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL },
+#endif
+ { CFI_MFR_AMD, 0x0050, fixup_use_secsi, NULL, },
+ { CFI_MFR_AMD, 0x0053, fixup_use_secsi, NULL, },
+ { CFI_MFR_AMD, 0x0055, fixup_use_secsi, NULL, },
+ { CFI_MFR_AMD, 0x0056, fixup_use_secsi, NULL, },
+ { CFI_MFR_AMD, 0x005C, fixup_use_secsi, NULL, },
+ { CFI_MFR_AMD, 0x005F, fixup_use_secsi, NULL, },
+#if !FORCE_WORD_WRITE
+ { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
+#endif
+ { 0, 0, NULL, NULL }
+};
+static struct cfi_fixup jedec_fixup_table[] = {
+ { MANUFACTURER_SST, SST49LF004B, fixup_use_fwh_lock, NULL, },
+ { 0, 0, NULL, NULL }
+};
+
+static struct cfi_fixup fixup_table[] = {
+ /* The CFI vendor ids and the JEDEC vendor IDs appear
+ * to be common. It is like the devices id's are as
+ * well. This table is to pick all cases where
+ * we know that is the case.
+ */
+ { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL },
+ { 0, 0, NULL, NULL }
+};
+
+