⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jedec.c

📁 老版本的mtd-snap
💻 C
📖 第 1 页 / 共 2 页
字号:
/* JEDEC Flash Interface. * This is an older type of interface for self programming flash. It is  * commonly use in older AMD chips and is obsolete compared with CFI. * It is called JEDEC because the JEDEC association distributes the ID codes * for the chips. * * See the AMD flash databook for information on how to operate the interface. * * This code does not support anything wider than 8 bit flash chips, I am * not going to guess how to send commands to them, plus I expect they will * all speak CFI.. * * $Id: jedec.c,v 1.22 2005/01/05 18:05:11 dwmw2 Exp $ */#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/mtd/jedec.h>#include <linux/mtd/map.h>#include <linux/mtd/mtd.h>#include <linux/mtd/compatmac.h>static struct mtd_info *jedec_probe(struct map_info *);static int jedec_probe8(struct map_info *map,unsigned long base,		  struct jedec_private *priv);static int jedec_probe16(struct map_info *map,unsigned long base,		  struct jedec_private *priv);static int jedec_probe32(struct map_info *map,unsigned long base,		  struct jedec_private *priv);static void jedec_flash_chip_scan(struct jedec_private *priv,unsigned long start,			    unsigned long len);static int flash_erase(struct mtd_info *mtd, struct erase_info *instr);static int flash_write(struct mtd_info *mtd, loff_t start, size_t len,		       size_t *retlen, const u_char *buf);static unsigned long my_bank_size;/* Listing of parts and sizes. We need this table to learn the sector   size of the chip and the total length */static const struct JEDECTable JEDEC_table[] = {	{		.jedec		= 0x013D,		.name		= "AMD Am29F017D",		.size		= 2*1024*1024,		.sectorsize	= 64*1024,		.capabilities	= MTD_CAP_NORFLASH	},	{		.jedec		= 0x01AD,		.name		= "AMD Am29F016",		.size		= 2*1024*1024,		.sectorsize	= 64*1024,		.capabilities	= MTD_CAP_NORFLASH	},	{		.jedec		= 0x01D5,		.name		= "AMD Am29F080",		.size		= 1*1024*1024,		.sectorsize	= 64*1024,		.capabilities	= MTD_CAP_NORFLASH	},	{		.jedec		= 0x01A4,		.name		= "AMD Am29F040",		.size		= 512*1024,		.sectorsize	= 64*1024,		.capabilities	= MTD_CAP_NORFLASH	},	{		.jedec		= 0x20E3,		.name		= "AMD Am29W040B",		.size		= 512*1024,		.sectorsize	= 64*1024,		.capabilities	= MTD_CAP_NORFLASH	},	{		.jedec		= 0xC2AD,		.name		= "Macronix MX29F016",		.size		= 2*1024*1024,		.sectorsize	= 64*1024,		.capabilities	= MTD_CAP_NORFLASH	},	{ .jedec = 0x0 }};static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id);static void jedec_sync(struct mtd_info *mtd) {};static int jedec_read(struct mtd_info *mtd, loff_t from, size_t len, 		      size_t *retlen, u_char *buf);static int jedec_read_banked(struct mtd_info *mtd, loff_t from, size_t len, 			     size_t *retlen, u_char *buf);static struct mtd_info *jedec_probe(struct map_info *map);static struct mtd_chip_driver jedec_chipdrv = {	.probe	= jedec_probe,	.name	= "jedec",	.module	= THIS_MODULE};/* Probe entry point */static struct mtd_info *jedec_probe(struct map_info *map){   struct mtd_info *MTD;   struct jedec_private *priv;   unsigned long Base;   unsigned long SectorSize;   unsigned count;   unsigned I,Uniq;   char Part[200];   memset(&priv,0,sizeof(priv));   MTD = kmalloc(sizeof(struct mtd_info) + sizeof(struct jedec_private), GFP_KERNEL);   if (!MTD)	   return NULL;   memset(MTD, 0, sizeof(struct mtd_info) + sizeof(struct jedec_private));   priv = (struct jedec_private *)&MTD[1];      my_bank_size = map->size;   if (map->size/my_bank_size > MAX_JEDEC_CHIPS)   {      printk("mtd: Increase MAX_JEDEC_CHIPS, too many banks.\n");      kfree(MTD);      return NULL;   }      for (Base = 0; Base < map->size; Base += my_bank_size)   {      // Perhaps zero could designate all tests?      if (map->buswidth == 0)	 map->buswidth = 1;            if (map->buswidth == 1){	 if (jedec_probe8(map,Base,priv) == 0) {		 printk("did recognize jedec chip\n");		 kfree(MTD);	         return NULL;	 }      }      if (map->buswidth == 2)	 jedec_probe16(map,Base,priv);      if (map->buswidth == 4)	 jedec_probe32(map,Base,priv);   }      // Get the biggest sector size   SectorSize = 0;   for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)   {	   //	   printk("priv->chips[%d].jedec is %x\n",I,priv->chips[I].jedec);	   //	   printk("priv->chips[%d].sectorsize is %lx\n",I,priv->chips[I].sectorsize);      if (priv->chips[I].sectorsize > SectorSize)	 SectorSize = priv->chips[I].sectorsize;   }      // Quickly ensure that the other sector sizes are factors of the largest   for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)   {      if ((SectorSize/priv->chips[I].sectorsize)*priv->chips[I].sectorsize != SectorSize)      {	 printk("mtd: Failed. Device has incompatible mixed sector sizes\n");	 kfree(MTD);	 return NULL;      }         }      /* Generate a part name that includes the number of different chips and      other configuration information */   count = 1;   strlcpy(Part,map->name,sizeof(Part)-10);   strcat(Part," ");   Uniq = 0;   for (I = 0; priv->chips[I].jedec != 0 && I < MAX_JEDEC_CHIPS; I++)   {      const struct JEDECTable *JEDEC;            if (priv->chips[I+1].jedec == priv->chips[I].jedec)      {	 count++;	 continue;      }            // Locate the chip in the jedec table      JEDEC = jedec_idtoinf(priv->chips[I].jedec >> 8,priv->chips[I].jedec);      if (JEDEC == 0)      {	 printk("mtd: Internal Error, JEDEC not set\n");	 kfree(MTD);	 return NULL;      }            if (Uniq != 0)	 strcat(Part,",");      Uniq++;            if (count != 1)	 sprintf(Part+strlen(Part),"%x*[%s]",count,JEDEC->name);      else	 sprintf(Part+strlen(Part),"%s",JEDEC->name);      if (strlen(Part) > sizeof(Part)*2/3)	 break;      count = 1;   }      /* Determine if the chips are organized in a linear fashion, or if there      are empty banks. Note, the last bank does not count here, only the      first banks are important. Holes on non-bank boundaries can not exist      due to the way the detection algorithm works. */   if (priv->size < my_bank_size)      my_bank_size = priv->size;   priv->is_banked = 0;   //printk("priv->size is %x, my_bank_size is %x\n",priv->size,my_bank_size);   //printk("priv->bank_fill[0] is %x\n",priv->bank_fill[0]);   if (!priv->size) {	   printk("priv->size is zero\n");	   kfree(MTD);	   return NULL;   }   if (priv->size/my_bank_size) {	   if (priv->size/my_bank_size == 1) {		   priv->size = my_bank_size;	   }	   else {		   for (I = 0; I != priv->size/my_bank_size - 1; I++)		   {		      if (priv->bank_fill[I] != my_bank_size)			 priv->is_banked = 1;		      		      /* This even could be eliminated, but new de-optimized read/write			 functions have to be written */		      printk("priv->bank_fill[%d] is %lx, priv->bank_fill[0] is %lx\n",I,priv->bank_fill[I],priv->bank_fill[0]);		      if (priv->bank_fill[I] != priv->bank_fill[0])		      {			 printk("mtd: Failed. Cannot handle unsymmetric banking\n");			 kfree(MTD);			 return NULL;		      }      		   }	   }   }   if (priv->is_banked == 1)      strcat(Part,", banked");   //   printk("Part: '%s'\n",Part);      memset(MTD,0,sizeof(*MTD));  // strlcpy(MTD->name,Part,sizeof(MTD->name));   MTD->name = map->name;   MTD->type = MTD_NORFLASH;   MTD->flags = MTD_CAP_NORFLASH;   MTD->erasesize = SectorSize*(map->buswidth);   //   printk("MTD->erasesize is %x\n",(unsigned int)MTD->erasesize);   MTD->size = priv->size;   //   printk("MTD->size is %x\n",(unsigned int)MTD->size);   //MTD->module = THIS_MODULE; // ? Maybe this should be the low level module?   MTD->erase = flash_erase;   if (priv->is_banked == 1)      MTD->read = jedec_read_banked;   else      MTD->read = jedec_read;   MTD->write = flash_write;   MTD->sync = jedec_sync;   MTD->priv = map;   map->fldrv_priv = priv;   map->fldrv = &jedec_chipdrv;   __module_get(THIS_MODULE);   return MTD;}/* Helper for the JEDEC function, JEDEC numbers all have odd parity */static int checkparity(u_char C){   u_char parity = 0;   while (C != 0)   {      parity ^= C & 1;      C >>= 1;   }   return parity == 1;}/* Take an array of JEDEC numbers that represent interleved flash chips   and process them. Check to make sure they are good JEDEC numbers, look   them up and then add them to the chip list */   static int handle_jedecs(struct map_info *map,__u8 *Mfg,__u8 *Id,unsigned Count,		  unsigned long base,struct jedec_private *priv){   unsigned I,J;   unsigned long Size;   unsigned long SectorSize;   const struct JEDECTable *JEDEC;   // Test #2 JEDEC numbers exhibit odd parity   for (I = 0; I != Count; I++)   {      if (checkparity(Mfg[I]) == 0 || checkparity(Id[I]) == 0)	 return 0;   }      // Finally, just make sure all the chip sizes are the same   JEDEC = jedec_idtoinf(Mfg[0],Id[0]);      if (JEDEC == 0)   {      printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]);      return 0;   }      Size = JEDEC->size;   SectorSize = JEDEC->sectorsize;   for (I = 0; I != Count; I++)   {      JEDEC = jedec_idtoinf(Mfg[0],Id[0]);      if (JEDEC == 0)      {	 printk("mtd: Found JEDEC flash chip, but do not have a table entry for %x:%x\n",Mfg[0],Mfg[1]);	 return 0;      }      if (Size != JEDEC->size || SectorSize != JEDEC->sectorsize)      {	 printk("mtd: Failed. Interleved flash does not have matching characteristics\n");	 return 0;      }         }   // Load the Chips   for (I = 0; I != MAX_JEDEC_CHIPS; I++)   {      if (priv->chips[I].jedec == 0)	 break;   }   if (I + Count > MAX_JEDEC_CHIPS)   {      printk("mtd: Device has too many chips. Increase MAX_JEDEC_CHIPS\n");      return 0;   }            // Add them to the table   for (J = 0; J != Count; J++)   {      unsigned long Bank;	       JEDEC = jedec_idtoinf(Mfg[J],Id[J]);      priv->chips[I].jedec = (Mfg[J] << 8) | Id[J];      priv->chips[I].size = JEDEC->size;      priv->chips[I].sectorsize = JEDEC->sectorsize;      priv->chips[I].base = base + J;      priv->chips[I].datashift = J*8;      priv->chips[I].capabilities = JEDEC->capabilities;      priv->chips[I].offset = priv->size + J;      // log2 n :|      priv->chips[I].addrshift = 0;      for (Bank = Count; Bank != 1; Bank >>= 1, priv->chips[I].addrshift++);            // Determine how filled this bank is.      Bank = base & (~(my_bank_size-1));      if (priv->bank_fill[Bank/my_bank_size] < base + 	  (JEDEC->size << priv->chips[I].addrshift) - Bank)	 priv->bank_fill[Bank/my_bank_size] =  base + (JEDEC->size << priv->chips[I].addrshift) - Bank;      I++;   }   priv->size += priv->chips[I-1].size*Count;	    return priv->chips[I-1].size;}/* Lookup the chip information from the JEDEC ID table. */static const struct JEDECTable *jedec_idtoinf(__u8 mfr,__u8 id){   __u16 Id = (mfr << 8) | id;   unsigned long I = 0;   for (I = 0; JEDEC_table[I].jedec != 0; I++)      if (JEDEC_table[I].jedec == Id)	 return JEDEC_table + I;   return NULL;}// Look for flash using an 8 bit bus interfacestatic int jedec_probe8(struct map_info *map,unsigned long base,		  struct jedec_private *priv){    #define flread(x) map_read8(map,base+x)   #define flwrite(v,x) map_write8(map,v,base+x)   const unsigned long AutoSel1 = 0xAA;   const unsigned long AutoSel2 = 0x55;   const unsigned long AutoSel3 = 0x90;   const unsigned long Reset = 0xF0;   __u32 OldVal;   __u8 Mfg[1];   __u8 Id[1];   unsigned I;   unsigned long Size;   // Wait for any write/erase operation to settle   OldVal = flread(base);   for (I = 0; OldVal != flread(base) && I < 10000; I++)      OldVal = flread(base);      // Reset the chip   flwrite(Reset,0x555);       // Send the sequence   flwrite(AutoSel1,0x555);   flwrite(AutoSel2,0x2AA);   flwrite(AutoSel3,0x555);      //  Get the JEDEC numbers   Mfg[0] = flread(0);   Id[0] = flread(1);   //   printk("Mfg is %x, Id is %x\n",Mfg[0],Id[0]);         Size = handle_jedecs(map,Mfg,Id,1,base,priv);   //   printk("handle_jedecs Size is %x\n",(unsigned int)Size);   if (Size == 0)   {      flwrite(Reset,0x555);      return 0;   }      // Reset.   flwrite(Reset,0x555);      return 1;      #undef flread   #undef flwrite}// Look for flash using a 16 bit bus interface (ie 2 8-bit chips)static int jedec_probe16(struct map_info *map,unsigned long base,		  struct jedec_private *priv){   return 0;}// Look for flash using a 32 bit bus interface (ie 4 8-bit chips)static int jedec_probe32(struct map_info *map,unsigned long base,		  struct jedec_private *priv){   #define flread(x) map_read32(map,base+((x)<<2))   #define flwrite(v,x) map_write32(map,v,base+((x)<<2))   const unsigned long AutoSel1 = 0xAAAAAAAA;   const unsigned long AutoSel2 = 0x55555555;   const unsigned long AutoSel3 = 0x90909090;   const unsigned long Reset = 0xF0F0F0F0;   __u32 OldVal;   __u8 Mfg[4];   __u8 Id[4];   unsigned I;   unsigned long Size;   // Wait for any write/erase operation to settle

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -