struct mtd_info *amd_flash_probe(struct map_info *map) { /* Keep this table on the stack so that it gets deallocated after the * probe is done. */ const struct amd_flash_info table[] = { { mfr_id: MANUFACTURER_AMD, dev_id: AM29LV160DT, name: "AMD AM29LV160DT", size: 0x00200000, numeraseregions: 4, regions: { { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, { offset: 0x1F0000, erasesize: 0x08000, numblocks: 1 }, { offset: 0x1F8000, erasesize: 0x02000, numblocks: 2 }, { offset: 0x1FC000, erasesize: 0x04000, numblocks: 1 } } }, { mfr_id: MANUFACTURER_AMD, dev_id: AM29LV160DB, name: "AMD AM29LV160DB", size: 0x00200000, numeraseregions: 4, regions: { { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } } }, { mfr_id: MANUFACTURER_TOSHIBA, dev_id: TC58FVT160, name: "Toshiba TC58FVT160", size: 0x00200000, numeraseregions: 4, regions: { { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, { offset: 0x1F0000, erasesize: 0x08000, numblocks: 1 }, { offset: 0x1F8000, erasesize: 0x02000, numblocks: 2 }, { offset: 0x1FC000, erasesize: 0x04000, numblocks: 1 } } }, { mfr_id: MANUFACTURER_FUJITSU, dev_id: MBM29LV160TE, name: "Fujitsu MBM29LV160TE", size: 0x00200000, numeraseregions: 4, regions: { { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, { offset: 0x1F0000, erasesize: 0x08000, numblocks: 1 }, { offset: 0x1F8000, erasesize: 0x02000, numblocks: 2 }, { offset: 0x1FC000, erasesize: 0x04000, numblocks: 1 } } }, { mfr_id: MANUFACTURER_TOSHIBA, dev_id: TC58FVB160, name: "Toshiba TC58FVB160", size: 0x00200000, numeraseregions: 4, regions: { { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } } }, { mfr_id: MANUFACTURER_FUJITSU, dev_id: MBM29LV160BE, name: "Fujitsu MBM29LV160BE", size: 0x00200000, numeraseregions: 4, regions: { { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } } }, { mfr_id: MANUFACTURER_AMD, dev_id: AM29LV800BB, name: "AMD AM29LV800BB", size: 0x00100000, numeraseregions: 4, regions: { { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, { offset: 0x010000, erasesize: 0x10000, numblocks: 15 } } }, { mfr_id: MANUFACTURER_AMD, dev_id: AM29F800BB, name: "AMD AM29F800BB", size: 0x00100000, numeraseregions: 4, regions: { { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, { offset: 0x010000, erasesize: 0x10000, numblocks: 15 } } }, { mfr_id: MANUFACTURER_AMD, dev_id: AM29LV800BT, name: "AMD AM29LV800BT", size: 0x00100000, numeraseregions: 4, regions: { { offset: 0x000000, erasesize: 0x10000, numblocks: 15 }, { offset: 0x0F0000, erasesize: 0x08000, numblocks: 1 }, { offset: 0x0F8000, erasesize: 0x02000, numblocks: 2 }, { offset: 0x0FC000, erasesize: 0x04000, numblocks: 1 } } }, { mfr_id: MANUFACTURER_AMD, dev_id: AM29F800BT, name: "AMD AM29F800BT", size: 0x00100000, numeraseregions: 4, regions: { { offset: 0x000000, erasesize: 0x10000, numblocks: 15 }, { offset: 0x0F0000, erasesize: 0x08000, numblocks: 1 }, { offset: 0x0F8000, erasesize: 0x02000, numblocks: 2 }, { offset: 0x0FC000, erasesize: 0x04000, numblocks: 1 } } }, { mfr_id: MANUFACTURER_AMD, dev_id: AM29LV800BB, name: "AMD AM29LV800BB", size: 0x00100000, numeraseregions: 4, regions: { { offset: 0x000000, erasesize: 0x10000, numblocks: 15 }, { offset: 0x0F0000, erasesize: 0x08000, numblocks: 1 }, { offset: 0x0F8000, erasesize: 0x02000, numblocks: 2 }, { offset: 0x0FC000, erasesize: 0x04000, numblocks: 1 } } }, { mfr_id: MANUFACTURER_ST, dev_id: M29W800T, name: "ST M29W800T", size: 0x00100000, numeraseregions: 4, regions: { { offset: 0x000000, erasesize: 0x10000, numblocks: 15 }, { offset: 0x0F0000, erasesize: 0x08000, numblocks: 1 }, { offset: 0x0F8000, erasesize: 0x02000, numblocks: 2 }, { offset: 0x0FC000, erasesize: 0x04000, numblocks: 1 } } }, { mfr_id: MANUFACTURER_ST, dev_id: M29W160DT, name: "ST M29W160DT", size: 0x00200000, numeraseregions: 4, regions: { { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, { offset: 0x1F0000, erasesize: 0x08000, numblocks: 1 }, { offset: 0x1F8000, erasesize: 0x02000, numblocks: 2 }, { offset: 0x1FC000, erasesize: 0x04000, numblocks: 1 } } }, { mfr_id: MANUFACTURER_ST, dev_id: M29W160DB, name: "ST M29W160DB", size: 0x00200000, numeraseregions: 4, regions: { { offset: 0x000000, erasesize: 0x04000, numblocks: 1 }, { offset: 0x004000, erasesize: 0x02000, numblocks: 2 }, { offset: 0x008000, erasesize: 0x08000, numblocks: 1 }, { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } } }, { mfr_id: MANUFACTURER_AMD, dev_id: AM29BDS323D, name: "AMD AM29BDS323D", size: 0x00400000, numeraseregions: 3, regions: { { offset: 0x000000, erasesize: 0x10000, numblocks: 48 }, { offset: 0x300000, erasesize: 0x10000, numblocks: 15 }, { offset: 0x3f0000, erasesize: 0x02000, numblocks: 8 }, } }, { mfr_id: MANUFACTURER_AMD, dev_id: AM29BDS643D, name: "AMD AM29BDS643D", size: 0x00800000, numeraseregions: 3, regions: { { offset: 0x000000, erasesize: 0x10000, numblocks: 96 }, { offset: 0x600000, erasesize: 0x10000, numblocks: 31 }, { offset: 0x7f0000, erasesize: 0x02000, numblocks: 8 }, } }, { mfr_id: MANUFACTURER_ATMEL, dev_id: AT49xV16x, name: "Atmel AT49xV16x", size: 0x00200000, numeraseregions: 2, regions: { { offset: 0x000000, erasesize: 0x02000, numblocks: 8 }, { offset: 0x010000, erasesize: 0x10000, numblocks: 31 } } }, { mfr_id: MANUFACTURER_ATMEL, dev_id: AT49xV16xT, name: "Atmel AT49xV16xT", size: 0x00200000, numeraseregions: 2, regions: { { offset: 0x000000, erasesize: 0x10000, numblocks: 31 }, { offset: 0x1F0000, erasesize: 0x02000, numblocks: 8 } } } };
struct mtd_info *mtd; struct flchip chips[MAX_AMD_CHIPS]; int table_pos[MAX_AMD_CHIPS]; struct amd_flash_private temp; struct amd_flash_private *private; u_long size; unsigned long base; int i; int reg_idx; int offset;
mtd = (struct mtd_info*)mmalloc(sizeof(*mtd)); if (!mtd) { printk("%s: malloc failed for info structure
", map->name); return NULL; } memset(mtd, 0, sizeof(*mtd)); mtd->priv = map;
memset(&temp, 0, sizeof(temp));
printk("%s: Probing for AMD compatible flash...
", map->name);
if ((table_pos[0] = probe_new_chip(mtd, 0, NULL, &temp, table, sizeof(table)/sizeof(table[0]))) == -1) { printk("%s: Found no AMD compatible device at location zero
", map->name); mfree(mtd);
return NULL; }
chips[0].start = 0; temp.numchips = 1;
for (size = mtd->size; size > 1; size >>= 1) { temp.chipshift++; } switch (temp.interleave) { case 2: temp.chipshift += 1; break; case 4: temp.chipshift += 2; break; }
/* Find out if there are any more chips in the map. */ for (base = (1 << temp.chipshift); base < map->size; base += (1 << temp.chipshift)) { int numchips = temp.numchips; table_pos[numchips] = probe_new_chip(mtd, base, chips, &temp, table, sizeof(table)/sizeof(table[0])); }
mtd->eraseregions = mmalloc(sizeof(struct mtd_erase_region_info) * mtd->numeraseregions); if (!mtd->eraseregions) { printk("%s: Failed to allocate " "memory for MTD erase region info
", map->name); mfree(mtd); map->fldrv_priv = NULL; return 0; }
reg_idx = 0; offset = 0; for (i = 0; i < temp.numchips; i++) { int dev_size; int j;
dev_size = 0; for (j = 0; j < table[table_pos]].numeraseregions; j++) { mtd->eraseregions[reg_idx].offset = offset + (table[table_pos]].regions[j].offset * temp.interleave); mtd->eraseregions[reg_idx].erasesize = table[table_pos]].regions[j].erasesize * temp.interleave; mtd->eraseregions[reg_idx].numblocks = table[table_pos]].regions[j].numblocks; if (mtd->erasesize < mtd->eraseregions[reg_idx].erasesize) { mtd->erasesize = mtd->eraseregions[reg_idx].erasesize; } dev_size += mtd->eraseregions[reg_idx].erasesize * mtd->eraseregions[reg_idx].numblocks; reg_idx++; } offset += dev_size; } mtd->type = MTD_NORFLASH; mtd->flags = MTD_CAP_NORFLASH; mtd->name = map->name; mtd->erase = amd_flash_erase; mtd->write = amd_flash_write; mtd->lock = amd_flash_lock; mtd->unlock = amd_flash_unlock;
private = mmalloc(sizeof(*private) + (sizeof(struct flchip) * temp.numchips)); if (!private) { printk("%s: kmalloc failed for private structure
", map->name); mfree(mtd); map->fldrv_priv = NULL; return NULL; } memcpy(private, &temp, sizeof(temp)); memcpy(private->chips, chips, sizeof(struct flchip) * private->numchips);
map->fldrv_priv = private; /* map->fldrv = &amd_flash_chipdrv; */
return mtd; } |