LCOV - code coverage report
Current view: top level - drivers/mtd/chips - cfi_probe.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 67 0.0 %
Date: 2014-02-18 Functions: 0 5 0.0 %
Branches: 0 32 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :    Common Flash Interface probe code.
       3                 :            :    (C) 2000 Red Hat. GPL'd.
       4                 :            : */
       5                 :            : 
       6                 :            : #include <linux/module.h>
       7                 :            : #include <linux/types.h>
       8                 :            : #include <linux/kernel.h>
       9                 :            : #include <linux/init.h>
      10                 :            : #include <asm/io.h>
      11                 :            : #include <asm/byteorder.h>
      12                 :            : #include <linux/errno.h>
      13                 :            : #include <linux/slab.h>
      14                 :            : #include <linux/interrupt.h>
      15                 :            : 
      16                 :            : #include <linux/mtd/xip.h>
      17                 :            : #include <linux/mtd/map.h>
      18                 :            : #include <linux/mtd/cfi.h>
      19                 :            : #include <linux/mtd/gen_probe.h>
      20                 :            : 
      21                 :            : //#define DEBUG_CFI
      22                 :            : 
      23                 :            : #ifdef DEBUG_CFI
      24                 :            : static void print_cfi_ident(struct cfi_ident *);
      25                 :            : #endif
      26                 :            : 
      27                 :            : static int cfi_probe_chip(struct map_info *map, __u32 base,
      28                 :            :                           unsigned long *chip_map, struct cfi_private *cfi);
      29                 :            : static int cfi_chip_setup(struct map_info *map, struct cfi_private *cfi);
      30                 :            : 
      31                 :            : struct mtd_info *cfi_probe(struct map_info *map);
      32                 :            : 
      33                 :            : #ifdef CONFIG_MTD_XIP
      34                 :            : 
      35                 :            : /* only needed for short periods, so this is rather simple */
      36                 :            : #define xip_disable()   local_irq_disable()
      37                 :            : 
      38                 :            : #define xip_allowed(base, map) \
      39                 :            : do { \
      40                 :            :         (void) map_read(map, base); \
      41                 :            :         xip_iprefetch(); \
      42                 :            :         local_irq_enable(); \
      43                 :            : } while (0)
      44                 :            : 
      45                 :            : #define xip_enable(base, map, cfi) \
      46                 :            : do { \
      47                 :            :         cfi_qry_mode_off(base, map, cfi);               \
      48                 :            :         xip_allowed(base, map); \
      49                 :            : } while (0)
      50                 :            : 
      51                 :            : #define xip_disable_qry(base, map, cfi) \
      52                 :            : do { \
      53                 :            :         xip_disable(); \
      54                 :            :         cfi_qry_mode_on(base, map, cfi); \
      55                 :            : } while (0)
      56                 :            : 
      57                 :            : #else
      58                 :            : 
      59                 :            : #define xip_disable()                   do { } while (0)
      60                 :            : #define xip_allowed(base, map)          do { } while (0)
      61                 :            : #define xip_enable(base, map, cfi)      do { } while (0)
      62                 :            : #define xip_disable_qry(base, map, cfi) do { } while (0)
      63                 :            : 
      64                 :            : #endif
      65                 :            : 
      66                 :            : /* check for QRY.
      67                 :            :    in: interleave,type,mode
      68                 :            :    ret: table index, <0 for error
      69                 :            :  */
      70                 :            : 
      71                 :          0 : static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
      72                 :            :                                    unsigned long *chip_map, struct cfi_private *cfi)
      73                 :            : {
      74                 :            :         int i;
      75                 :            : 
      76         [ #  # ]:          0 :         if ((base + 0) >= map->size) {
      77                 :          0 :                 printk(KERN_NOTICE
      78                 :            :                         "Probe at base[0x00](0x%08lx) past the end of the map(0x%08lx)\n",
      79                 :            :                         (unsigned long)base, map->size -1);
      80                 :          0 :                 return 0;
      81                 :            :         }
      82         [ #  # ]:          0 :         if ((base + 0xff) >= map->size) {
      83                 :          0 :                 printk(KERN_NOTICE
      84                 :            :                         "Probe at base[0x55](0x%08lx) past the end of the map(0x%08lx)\n",
      85                 :            :                         (unsigned long)base + 0x55, map->size -1);
      86                 :          0 :                 return 0;
      87                 :            :         }
      88                 :            : 
      89                 :            :         xip_disable();
      90         [ #  # ]:          0 :         if (!cfi_qry_mode_on(base, map, cfi)) {
      91                 :            :                 xip_enable(base, map, cfi);
      92                 :            :                 return 0;
      93                 :            :         }
      94                 :            : 
      95         [ #  # ]:          0 :         if (!cfi->numchips) {
      96                 :            :                 /* This is the first time we're called. Set up the CFI
      97                 :            :                    stuff accordingly and return */
      98                 :          0 :                 return cfi_chip_setup(map, cfi);
      99                 :            :         }
     100                 :            : 
     101                 :            :         /* Check each previous chip to see if it's an alias */
     102         [ #  # ]:          0 :         for (i=0; i < (base >> cfi->chipshift); i++) {
     103                 :            :                 unsigned long start;
     104         [ #  # ]:          0 :                 if(!test_bit(i, chip_map)) {
     105                 :            :                         /* Skip location; no valid chip at this address */
     106                 :          0 :                         continue;
     107                 :            :                 }
     108                 :          0 :                 start = i << cfi->chipshift;
     109                 :            :                 /* This chip should be in read mode if it's one
     110                 :            :                    we've already touched. */
     111         [ #  # ]:          0 :                 if (cfi_qry_present(map, start, cfi)) {
     112                 :            :                         /* Eep. This chip also had the QRY marker.
     113                 :            :                          * Is it an alias for the new one? */
     114                 :          0 :                         cfi_qry_mode_off(start, map, cfi);
     115                 :            : 
     116                 :            :                         /* If the QRY marker goes away, it's an alias */
     117         [ #  # ]:          0 :                         if (!cfi_qry_present(map, start, cfi)) {
     118                 :            :                                 xip_allowed(base, map);
     119                 :          0 :                                 printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
     120                 :            :                                        map->name, base, start);
     121                 :          0 :                                 return 0;
     122                 :            :                         }
     123                 :            :                         /* Yes, it's actually got QRY for data. Most
     124                 :            :                          * unfortunate. Stick the new chip in read mode
     125                 :            :                          * too and if it's the same, assume it's an alias. */
     126                 :            :                         /* FIXME: Use other modes to do a proper check */
     127                 :          0 :                         cfi_qry_mode_off(base, map, cfi);
     128                 :            : 
     129         [ #  # ]:          0 :                         if (cfi_qry_present(map, base, cfi)) {
     130                 :            :                                 xip_allowed(base, map);
     131                 :          0 :                                 printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
     132                 :            :                                        map->name, base, start);
     133                 :          0 :                                 return 0;
     134                 :            :                         }
     135                 :            :                 }
     136                 :            :         }
     137                 :            : 
     138                 :            :         /* OK, if we got to here, then none of the previous chips appear to
     139                 :            :            be aliases for the current one. */
     140                 :          0 :         set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */
     141                 :          0 :         cfi->numchips++;
     142                 :            : 
     143                 :            :         /* Put it back into Read Mode */
     144                 :          0 :         cfi_qry_mode_off(base, map, cfi);
     145                 :            :         xip_allowed(base, map);
     146                 :            : 
     147                 :          0 :         printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
     148                 :          0 :                map->name, cfi->interleave, cfi->device_type*8, base,
     149                 :          0 :                map->bankwidth*8);
     150                 :            : 
     151                 :          0 :         return 1;
     152                 :            : }
     153                 :            : 
     154                 :          0 : static int __xipram cfi_chip_setup(struct map_info *map,
     155                 :          0 :                                    struct cfi_private *cfi)
     156                 :            : {
     157                 :          0 :         int ofs_factor = cfi->interleave*cfi->device_type;
     158                 :            :         __u32 base = 0;
     159                 :          0 :         int num_erase_regions = cfi_read_query(map, base + (0x10 + 28)*ofs_factor);
     160                 :            :         int i;
     161                 :            :         int addr_unlock1 = 0x555, addr_unlock2 = 0x2AA;
     162                 :            : 
     163                 :            :         xip_enable(base, map, cfi);
     164                 :            : #ifdef DEBUG_CFI
     165                 :            :         printk("Number of erase regions: %d\n", num_erase_regions);
     166                 :            : #endif
     167         [ #  # ]:          0 :         if (!num_erase_regions)
     168                 :            :                 return 0;
     169                 :            : 
     170                 :          0 :         cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL);
     171         [ #  # ]:          0 :         if (!cfi->cfiq) {
     172                 :          0 :                 printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name);
     173                 :          0 :                 return 0;
     174                 :            :         }
     175                 :            : 
     176                 :          0 :         memset(cfi->cfiq,0,sizeof(struct cfi_ident));
     177                 :            : 
     178                 :          0 :         cfi->cfi_mode = CFI_MODE_CFI;
     179                 :            : 
     180                 :          0 :         cfi->sector_erase_cmd = CMD(0x30);
     181                 :            : 
     182                 :            :         /* Read the CFI info structure */
     183                 :            :         xip_disable_qry(base, map, cfi);
     184         [ #  # ]:          0 :         for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++)
     185                 :          0 :                 ((unsigned char *)cfi->cfiq)[i] = cfi_read_query(map,base + (0x10 + i)*ofs_factor);
     186                 :            : 
     187                 :            :         /* Do any necessary byteswapping */
     188                 :          0 :         cfi->cfiq->P_ID = le16_to_cpu(cfi->cfiq->P_ID);
     189                 :            : 
     190                 :            :         cfi->cfiq->P_ADR = le16_to_cpu(cfi->cfiq->P_ADR);
     191                 :            :         cfi->cfiq->A_ID = le16_to_cpu(cfi->cfiq->A_ID);
     192                 :            :         cfi->cfiq->A_ADR = le16_to_cpu(cfi->cfiq->A_ADR);
     193                 :            :         cfi->cfiq->InterfaceDesc = le16_to_cpu(cfi->cfiq->InterfaceDesc);
     194                 :            :         cfi->cfiq->MaxBufWriteSize = le16_to_cpu(cfi->cfiq->MaxBufWriteSize);
     195                 :            : 
     196                 :            : #ifdef DEBUG_CFI
     197                 :            :         /* Dump the information therein */
     198                 :            :         print_cfi_ident(cfi->cfiq);
     199                 :            : #endif
     200                 :            : 
     201         [ #  # ]:          0 :         for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
     202                 :            :                 cfi->cfiq->EraseRegionInfo[i] = le32_to_cpu(cfi->cfiq->EraseRegionInfo[i]);
     203                 :            : 
     204                 :            : #ifdef DEBUG_CFI
     205                 :            :                 printk("  Erase Region #%d: BlockSize 0x%4.4X bytes, %d blocks\n",
     206                 :            :                        i, (cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff,
     207                 :            :                        (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1);
     208                 :            : #endif
     209                 :            :         }
     210                 :            : 
     211         [ #  # ]:          0 :         if (cfi->cfiq->P_ID == P_ID_SST_OLD) {
     212                 :            :                 addr_unlock1 = 0x5555;
     213                 :            :                 addr_unlock2 = 0x2AAA;
     214                 :            :         }
     215                 :            : 
     216                 :            :         /*
     217                 :            :          * Note we put the device back into Read Mode BEFORE going into Auto
     218                 :            :          * Select Mode, as some devices support nesting of modes, others
     219                 :            :          * don't. This way should always work.
     220                 :            :          * On cmdset 0001 the writes of 0xaa and 0x55 are not needed, and
     221                 :            :          * so should be treated as nops or illegal (and so put the device
     222                 :            :          * back into Read Mode, which is a nop in this case).
     223                 :            :          */
     224                 :            :         cfi_send_gen_cmd(0xf0,     0, base, map, cfi, cfi->device_type, NULL);
     225                 :          0 :         cfi_send_gen_cmd(0xaa, addr_unlock1, base, map, cfi, cfi->device_type, NULL);
     226                 :          0 :         cfi_send_gen_cmd(0x55, addr_unlock2, base, map, cfi, cfi->device_type, NULL);
     227                 :            :         cfi_send_gen_cmd(0x90, addr_unlock1, base, map, cfi, cfi->device_type, NULL);
     228                 :          0 :         cfi->mfr = cfi_read_query16(map, base);
     229                 :          0 :         cfi->id = cfi_read_query16(map, base + ofs_factor);
     230                 :            : 
     231                 :            :         /* Get AMD/Spansion extended JEDEC ID */
     232 [ #  # ][ #  # ]:          0 :         if (cfi->mfr == CFI_MFR_AMD && (cfi->id & 0xff) == 0x7e)
     233                 :          0 :                 cfi->id = cfi_read_query(map, base + 0xe * ofs_factor) << 8 |
     234                 :          0 :                           cfi_read_query(map, base + 0xf * ofs_factor);
     235                 :            : 
     236                 :            :         /* Put it back into Read Mode */
     237                 :          0 :         cfi_qry_mode_off(base, map, cfi);
     238                 :            :         xip_allowed(base, map);
     239                 :            : 
     240                 :          0 :         printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank. Manufacturer ID %#08x Chip ID %#08x\n",
     241                 :          0 :                map->name, cfi->interleave, cfi->device_type*8, base,
     242                 :          0 :                map->bankwidth*8, cfi->mfr, cfi->id);
     243                 :            : 
     244                 :          0 :         return 1;
     245                 :            : }
     246                 :            : 
     247                 :            : #ifdef DEBUG_CFI
     248                 :            : static char *vendorname(__u16 vendor)
     249                 :            : {
     250                 :            :         switch (vendor) {
     251                 :            :         case P_ID_NONE:
     252                 :            :                 return "None";
     253                 :            : 
     254                 :            :         case P_ID_INTEL_EXT:
     255                 :            :                 return "Intel/Sharp Extended";
     256                 :            : 
     257                 :            :         case P_ID_AMD_STD:
     258                 :            :                 return "AMD/Fujitsu Standard";
     259                 :            : 
     260                 :            :         case P_ID_INTEL_STD:
     261                 :            :                 return "Intel/Sharp Standard";
     262                 :            : 
     263                 :            :         case P_ID_AMD_EXT:
     264                 :            :                 return "AMD/Fujitsu Extended";
     265                 :            : 
     266                 :            :         case P_ID_WINBOND:
     267                 :            :                 return "Winbond Standard";
     268                 :            : 
     269                 :            :         case P_ID_ST_ADV:
     270                 :            :                 return "ST Advanced";
     271                 :            : 
     272                 :            :         case P_ID_MITSUBISHI_STD:
     273                 :            :                 return "Mitsubishi Standard";
     274                 :            : 
     275                 :            :         case P_ID_MITSUBISHI_EXT:
     276                 :            :                 return "Mitsubishi Extended";
     277                 :            : 
     278                 :            :         case P_ID_SST_PAGE:
     279                 :            :                 return "SST Page Write";
     280                 :            : 
     281                 :            :         case P_ID_SST_OLD:
     282                 :            :                 return "SST 39VF160x/39VF320x";
     283                 :            : 
     284                 :            :         case P_ID_INTEL_PERFORMANCE:
     285                 :            :                 return "Intel Performance Code";
     286                 :            : 
     287                 :            :         case P_ID_INTEL_DATA:
     288                 :            :                 return "Intel Data";
     289                 :            : 
     290                 :            :         case P_ID_RESERVED:
     291                 :            :                 return "Not Allowed / Reserved for Future Use";
     292                 :            : 
     293                 :            :         default:
     294                 :            :                 return "Unknown";
     295                 :            :         }
     296                 :            : }
     297                 :            : 
     298                 :            : 
     299                 :            : static void print_cfi_ident(struct cfi_ident *cfip)
     300                 :            : {
     301                 :            : #if 0
     302                 :            :         if (cfip->qry[0] != 'Q' || cfip->qry[1] != 'R' || cfip->qry[2] != 'Y') {
     303                 :            :                 printk("Invalid CFI ident structure.\n");
     304                 :            :                 return;
     305                 :            :         }
     306                 :            : #endif
     307                 :            :         printk("Primary Vendor Command Set: %4.4X (%s)\n", cfip->P_ID, vendorname(cfip->P_ID));
     308                 :            :         if (cfip->P_ADR)
     309                 :            :                 printk("Primary Algorithm Table at %4.4X\n", cfip->P_ADR);
     310                 :            :         else
     311                 :            :                 printk("No Primary Algorithm Table\n");
     312                 :            : 
     313                 :            :         printk("Alternative Vendor Command Set: %4.4X (%s)\n", cfip->A_ID, vendorname(cfip->A_ID));
     314                 :            :         if (cfip->A_ADR)
     315                 :            :                 printk("Alternate Algorithm Table at %4.4X\n", cfip->A_ADR);
     316                 :            :         else
     317                 :            :                 printk("No Alternate Algorithm Table\n");
     318                 :            : 
     319                 :            : 
     320                 :            :         printk("Vcc Minimum: %2d.%d V\n", cfip->VccMin >> 4, cfip->VccMin & 0xf);
     321                 :            :         printk("Vcc Maximum: %2d.%d V\n", cfip->VccMax >> 4, cfip->VccMax & 0xf);
     322                 :            :         if (cfip->VppMin) {
     323                 :            :                 printk("Vpp Minimum: %2d.%d V\n", cfip->VppMin >> 4, cfip->VppMin & 0xf);
     324                 :            :                 printk("Vpp Maximum: %2d.%d V\n", cfip->VppMax >> 4, cfip->VppMax & 0xf);
     325                 :            :         }
     326                 :            :         else
     327                 :            :                 printk("No Vpp line\n");
     328                 :            : 
     329                 :            :         printk("Typical byte/word write timeout: %d µs\n", 1<<cfip->WordWriteTimeoutTyp);
     330                 :            :         printk("Maximum byte/word write timeout: %d µs\n", (1<<cfip->WordWriteTimeoutMax) * (1<<cfip->WordWriteTimeoutTyp));
     331                 :            : 
     332                 :            :         if (cfip->BufWriteTimeoutTyp || cfip->BufWriteTimeoutMax) {
     333                 :            :                 printk("Typical full buffer write timeout: %d µs\n", 1<<cfip->BufWriteTimeoutTyp);
     334                 :            :                 printk("Maximum full buffer write timeout: %d µs\n", (1<<cfip->BufWriteTimeoutMax) * (1<<cfip->BufWriteTimeoutTyp));
     335                 :            :         }
     336                 :            :         else
     337                 :            :                 printk("Full buffer write not supported\n");
     338                 :            : 
     339                 :            :         printk("Typical block erase timeout: %d ms\n", 1<<cfip->BlockEraseTimeoutTyp);
     340                 :            :         printk("Maximum block erase timeout: %d ms\n", (1<<cfip->BlockEraseTimeoutMax) * (1<<cfip->BlockEraseTimeoutTyp));
     341                 :            :         if (cfip->ChipEraseTimeoutTyp || cfip->ChipEraseTimeoutMax) {
     342                 :            :                 printk("Typical chip erase timeout: %d ms\n", 1<<cfip->ChipEraseTimeoutTyp);
     343                 :            :                 printk("Maximum chip erase timeout: %d ms\n", (1<<cfip->ChipEraseTimeoutMax) * (1<<cfip->ChipEraseTimeoutTyp));
     344                 :            :         }
     345                 :            :         else
     346                 :            :                 printk("Chip erase not supported\n");
     347                 :            : 
     348                 :            :         printk("Device size: 0x%X bytes (%d MiB)\n", 1 << cfip->DevSize, 1<< (cfip->DevSize - 20));
     349                 :            :         printk("Flash Device Interface description: 0x%4.4X\n", cfip->InterfaceDesc);
     350                 :            :         switch(cfip->InterfaceDesc) {
     351                 :            :         case CFI_INTERFACE_X8_ASYNC:
     352                 :            :                 printk("  - x8-only asynchronous interface\n");
     353                 :            :                 break;
     354                 :            : 
     355                 :            :         case CFI_INTERFACE_X16_ASYNC:
     356                 :            :                 printk("  - x16-only asynchronous interface\n");
     357                 :            :                 break;
     358                 :            : 
     359                 :            :         case CFI_INTERFACE_X8_BY_X16_ASYNC:
     360                 :            :                 printk("  - supports x8 and x16 via BYTE# with asynchronous interface\n");
     361                 :            :                 break;
     362                 :            : 
     363                 :            :         case CFI_INTERFACE_X32_ASYNC:
     364                 :            :                 printk("  - x32-only asynchronous interface\n");
     365                 :            :                 break;
     366                 :            : 
     367                 :            :         case CFI_INTERFACE_X16_BY_X32_ASYNC:
     368                 :            :                 printk("  - supports x16 and x32 via Word# with asynchronous interface\n");
     369                 :            :                 break;
     370                 :            : 
     371                 :            :         case CFI_INTERFACE_NOT_ALLOWED:
     372                 :            :                 printk("  - Not Allowed / Reserved\n");
     373                 :            :                 break;
     374                 :            : 
     375                 :            :         default:
     376                 :            :                 printk("  - Unknown\n");
     377                 :            :                 break;
     378                 :            :         }
     379                 :            : 
     380                 :            :         printk("Max. bytes in buffer write: 0x%x\n", 1<< cfip->MaxBufWriteSize);
     381                 :            :         printk("Number of Erase Block Regions: %d\n", cfip->NumEraseRegions);
     382                 :            : 
     383                 :            : }
     384                 :            : #endif /* DEBUG_CFI */
     385                 :            : 
     386                 :            : static struct chip_probe cfi_chip_probe = {
     387                 :            :         .name           = "CFI",
     388                 :            :         .probe_chip     = cfi_probe_chip
     389                 :            : };
     390                 :            : 
     391                 :          0 : struct mtd_info *cfi_probe(struct map_info *map)
     392                 :            : {
     393                 :            :         /*
     394                 :            :          * Just use the generic probe stuff to call our CFI-specific
     395                 :            :          * chip_probe routine in all the possible permutations, etc.
     396                 :            :          */
     397                 :          0 :         return mtd_do_chip_probe(map, &cfi_chip_probe);
     398                 :            : }
     399                 :            : 
     400                 :            : static struct mtd_chip_driver cfi_chipdrv = {
     401                 :            :         .probe          = cfi_probe,
     402                 :            :         .name           = "cfi_probe",
     403                 :            :         .module         = THIS_MODULE
     404                 :            : };
     405                 :            : 
     406                 :          0 : static int __init cfi_probe_init(void)
     407                 :            : {
     408                 :          0 :         register_mtd_chip_driver(&cfi_chipdrv);
     409                 :          0 :         return 0;
     410                 :            : }
     411                 :            : 
     412                 :          0 : static void __exit cfi_probe_exit(void)
     413                 :            : {
     414                 :          0 :         unregister_mtd_chip_driver(&cfi_chipdrv);
     415                 :          0 : }
     416                 :            : 
     417                 :            : module_init(cfi_probe_init);
     418                 :            : module_exit(cfi_probe_exit);
     419                 :            : 
     420                 :            : MODULE_LICENSE("GPL");
     421                 :            : MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al.");
     422                 :            : MODULE_DESCRIPTION("Probe code for CFI-compliant flash chips");

Generated by: LCOV version 1.9