mxc_dataflash.c分析

来源:互联网 发布:淘宝无线端首页psd 编辑:程序博客网 时间:2024/05/18 00:40

这个文件是AT DataFlash chips的驱动,通过FSL SPI接口进行数据操作。


   917 static int __devinit dataflash_probe(struct spi_device *spi)
   918 {
   919     int status;
   920     struct flash_info *info;
   921
   922     /*
   923      * Try to detect dataflash by JEDEC ID.
   924      * If it succeeds we know we have either a C or D part.
   925      * D will support power of 2 pagesize option.
   926      * Both support the security register, though with different
   927      * write procedures.
   928      */
   929     info = jedec_probe(spi);
   930     if (IS_ERR(info))
   931         return PTR_ERR(info);
   932     if (info != NULL)
   933         return add_dataflash_otp(spi, info->name, info->nr_pages,
   934                      info->pagesize, info->pageoffset,
   935                      (info->flags & SUP_POW2PS) ? 'd' :
   936                      'c');
   937
   938     /*
   939      * Older chips support only legacy commands, identifing
   940      * capacity using bits in the status byte.
   941      */
   942     status = dataflash_status(spi);
   943     if (status <= 0 || status == 0xff) {
   944         DEBUG(MTD_DEBUG_LEVEL1, "%s: status error %d\n",
   945               dev_name(&spi->dev), status);
   946         if (status == 0 || status == 0xff)
   947             status = -ENODEV;
   948         return status;
   949     }
   950
   951     /* if there's a device there, assume it's dataflash.
   952      * board setup should have set spi->max_speed_max to
   953      * match f(car) for continuous reads, mode 0 or 3.
   954      */
   955     switch (status & 0x3c) {
   956     case 0x0c:      /* 0 0 1 1 x x */
   957         status = add_dataflash(spi, "AT45DB011B", 512, 264, 9);
   958         break;
   959     case 0x14:      /* 0 1 0 1 x x */
   960         status = add_dataflash(spi, "AT45DB021B", 1024, 264, 9);
   961         break;
   962     case 0x1c:      /* 0 1 1 1 x x */
   963         status = add_dataflash(spi, "AT45DB041x", 2048, 264, 9);
   964         break;
   965     case 0x24:      /* 1 0 0 1 x x */
   966         status = add_dataflash(spi, "AT45DB081B", 4096, 264, 9);
   967         break;
   968     case 0x2c:      /* 1 0 1 1 x x */
   969         status = add_dataflash(spi, "AT45DB161x", 4096, 528, 10);
   970         break;
   971     case 0x34:      /* 1 1 0 1 x x */
   972         status = add_dataflash(spi, "AT45DB321x", 8192, 528, 10);
   973         break;
   974     case 0x38:      /* 1 1 1 x x x */
   975     case 0x3c:
   976         status = add_dataflash(spi, "AT45DB642x", 8192, 1056, 11);
   977         break;
   978         /* obsolete AT45DB1282 not (yet?) supported */
   979     default:
   980         DEBUG(MTD_DEBUG_LEVEL1, "%s: unsupported device (%x)\n",
   981               dev_name(&spi->dev), status & 0x3c);
   982         status = -ENODEV;
   983     }
   984
   985     if (status < 0)
   986         DEBUG(MTD_DEBUG_LEVEL1, "%s: add_dataflash --> %d\n",
   987               dev_name(&spi->dev), status);
   988
   989     return status;
   990 }

929 jedec_probe 会读取JEDEC ID,通过ID获取预先定义的flash_info

930~936 如果我们获取了有效的flash_info,那么这是一个新的chip,可以使用预定以的参数增加data flash设备

938 ~ 949 无法获取JEDEC ID,这是一个老chip,那么要使用老式方法,dataflash_status读取status字节,通过status字节获取设备类型

955 ~ 983 根据status值,增加相应的设备类型


843 static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
   844 {
   845     int tmp;
   846     u32 code = OP_READ_ID << 24;
   847     u32 jedec;
   848     struct flash_info *info;
   849     int status;
   850
   851     /* JEDEC also defines an optional "extended device information"
   852      * string for after vendor-specific data, after the three bytes
   853      * we use here.  Supporting some chips might require using it.
   854      *
   855      * If the vendor ID isn't Atmel's (0x1f), assume this call failed.
   856      * That's not an error; only rev C and newer chips handle it, and
   857      * only Atmel sells these chips.
   858      */
   859
   860     tmp = spi_read_write(spi, (u8 *)&code, 4);
   861     if (tmp < 0) {
   862         DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
   863               dev_name(&spi->dev), tmp);
   864         return NULL;
   865     }
   866
   867     jedec = code & 0xFFFFFF;
   868
   869     for (tmp = 0, info = dataflash_data;
   870          tmp < ARRAY_SIZE(dataflash_data); tmp++, info++) {
   871         if (info->jedec_id == jedec) {
   872             DEBUG(MTD_DEBUG_LEVEL1, "%s: OTP, sector protect%s\n",
   873                   dev_name(&spi->dev), (info->flags & SUP_POW2PS)
   874                   ? ", binary pagesize" : "");
   875             if (info->flags & SUP_POW2PS) {
   876                 status = dataflash_status(spi);
   877                 if (status < 0) {
   878                     DEBUG(MTD_DEBUG_LEVEL1,
   879                           "%s: status error %d\n",
   880                           dev_name(&spi->dev), status);
   881                     return ERR_PTR(status);
   882                 }
   883                 if (status & 0x1) {
   884                     if (info->flags & IS_POW2PS)
   885                         return info;
   886                 } else {
   887                     if (!(info->flags & IS_POW2PS))
   888                         return info;
   889                 }
   890             }
   891         }
   892     }
   893
   894     /*
   895      * Treat other chips as errors ... we won't know the right page
   896      * size (it might be binary) even when we can tell which density
   897      * class is involved (legacy chip id scheme).
   898      */
   899     dev_warn(&spi->dev, "JEDEC id %06x not handled\n", jedec);
   900     return ERR_PTR(-ENODEV);
   901 }

860 先读取 JEDEC ID

869 ~892 如果读取到JEDEC ID,在预定义的dataflash_data中找到相应的falsh_info

876 读取status 寄存器, bit0设置为1,表示page size设置为 2的乘方,否则可能包含带外数据。


   808 static struct flash_info __devinitdata dataflash_data[] = {
   809
   810     /*
   811      * NOTE:  chips with SUP_POW2PS (rev D and up) need two entries,
   812      * one with IS_POW2PS and the other without.  The entry with the
   813      * non-2^N byte page size can't name exact chip revisions without
   814      * losing backwards compatibility for cmdlinepart.
   815      *
   816      * These newer chips also support 128-byte security registers (with
   817      * 64 bytes one-time-programmable) and software write-protection.
   818      */
   819     {"AT45DB011B", 0x1f2200, 512, 264, 9, SUP_POW2PS},
   820     {"at45db011d", 0x1f2200, 512, 256, 8, SUP_POW2PS | IS_POW2PS},
   821
   822     {"AT45DB021B", 0x1f2300, 1024, 264, 9, SUP_POW2PS},
   823     {"at45db021d", 0x1f2300, 1024, 256, 8, SUP_POW2PS | IS_POW2PS},
   824
   825     {"AT45DB041x", 0x1f2400, 2048, 264, 9, SUP_POW2PS},
   826     {"at45db041d", 0x1f2400, 2048, 256, 8, SUP_POW2PS | IS_POW2PS},
   827
   828     {"AT45DB081B", 0x1f2500, 4096, 264, 9, SUP_POW2PS},
   829     {"at45db081d", 0x1f2500, 4096, 256, 8, SUP_POW2PS | IS_POW2PS},
   830
   831     {"AT45DB161x", 0x1f2600, 4096, 528, 10, SUP_POW2PS},
   832     {"at45db161d", 0x1f2600, 4096, 512, 9, SUP_POW2PS | IS_POW2PS},
   833
   834     {"AT45DB321x", 0x1f2700, 8192, 528, 10, 0}, /* rev C */
   835
   836     {"AT45DB321x", 0x1f2701, 8192, 528, 10, SUP_POW2PS},
   837     {"at45db321d", 0x1f2701, 8192, 512, 9, SUP_POW2PS | IS_POW2PS},
   838
   839     {"AT45DB642x", 0x1f2800, 8192, 1056, 11, SUP_POW2PS},
   840     {"at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS},
   841 };

这个flash_info数组定义了较新的chip规格,从左到右依次为:

名字, JEDEC ID,pages数目,page大小,page offset, page和2乘方关系的标志


   715 static int __devinit
   716 add_dataflash_otp(struct spi_device *spi, char *name,
   717           int nr_pages, int pagesize, int pageoffset, char revision)
   718 {
   719     struct dataflash *priv;
   720     struct mtd_info *device;
   721     struct flash_platform_data *pdata = spi->dev.platform_data;
   722     char *otp_tag = "";
   723
   724     priv = kzalloc(sizeof *priv, GFP_KERNEL);
   725     if (!priv)
   726         return -ENOMEM;
   727
   728     mutex_init(&priv->lock);
   729     priv->spi = spi;
   730     priv->page_size = pagesize;
   731     priv->page_offset = pageoffset;
   732
   733     /* name must be usable with cmdlinepart */
   734     sprintf(priv->name, "spi%d.%d-%s",
   735         spi->master->bus_num, spi->chip_select, name);
   736
   737     device = &priv->mtd;
   738     device->name = (pdata && pdata->name) ? pdata->name : priv->name;
   739     device->size = nr_pages * pagesize;
   740     device->erasesize = pagesize;
   741     device->writesize = pagesize;
   742     device->owner = THIS_MODULE;
   743     device->type = MTD_DATAFLASH;
   744     device->flags = MTD_CAP_NORFLASH;
   745     device->erase = dataflash_erase;
   746     device->read = dataflash_read;
   747     device->write = dataflash_write;
   748     device->priv = priv;
   749
   750     if (revision >= 'c')
   751         otp_tag = otp_setup(device, revision);
   752
   753     dev_info(&spi->dev, "%s (%llx KBytes) pagesize %d bytes%s\n",
   754          name, DIV_ROUND_UP(device->size, 1024), pagesize, otp_tag);
   755     dev_set_drvdata(&spi->dev, priv);
   756
   757     if (mtd_has_partitions()) {
   758         struct mtd_partition *parts;
   759         int nr_parts = 0;
   760
   761 #ifdef CONFIG_MTD_CMDLINE_PARTS
   762         static const char *part_probes[] = { "cmdlinepart", NULL, };
   763
   764         nr_parts = parse_mtd_partitions(device, part_probes, &parts, 0);
   765 #endif
   766
   767         if (nr_parts <= 0 && pdata && pdata->parts) {
   768             parts = pdata->parts;
   769             nr_parts = pdata->nr_parts;
   770         }
   771
   772         if (nr_parts > 0) {
   773             priv->partitioned = 1;
   774             return add_mtd_partitions(device, parts, nr_parts);
   775         }
   776     } else if (pdata && pdata->nr_parts)
   777         dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
   778              pdata->nr_parts, device->name);
   779
   780     return add_mtd_device(device) == 1 ? -ENODEV : 0;
   781 }

739 设备尺寸是nr_pages * pagesize;

740 ~ 741 读写单位都是page size

772~ 775 有分区信息,调用add_mtd_partitions增加mtd partitions


387 static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
   388                size_t *retlen, const u_char *buf)
   389 {
   390     struct dataflash *priv = mtd->priv;
   391     struct spi_device *spi = priv->spi;
   392     u32 pageaddr, addr, offset, writelen;
   393     size_t remaining = len;
   394     u_char *writebuf = (u_char *) buf;
   395     int status = -EINVAL;
   396     u_char txer[SPI_FIFOSIZE] = { 0 };
   397     uint8_t *command = priv->command;
   398     u_char *d = txer;
   399     u_char *s = (u_char *) buf;
   400     int delta = 0, l = 0, i = 0, count = 0;
   401
   402     DEBUG(MTD_DEBUG_LEVEL2, "%s: write 0x%x..0x%x\n",
   403           dev_name(&spi->dev), (unsigned)to, (unsigned)(to + len));
   404
   405     *retlen = 0;
   406
   407     /* Sanity checks */
   408     if (!len)
   409         return 0;
   410
   411     if ((to + len) > mtd->size)
   412         return -EINVAL;
   413
   414     pageaddr = ((unsigned)to / priv->page_size);
   415     offset = ((unsigned)to % priv->page_size);
   416     if (offset + len > priv->page_size)
   417         writelen = priv->page_size - offset;
   418     else
   419         writelen = len;
   420
   421     mutex_lock(&priv->lock);
   422
   423     while (remaining > 0) {
   424         DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n",
   425               pageaddr, offset, writelen);
   426
   427         addr = pageaddr << priv->page_offset;
   428
   429         /* (1) Maybe transfer partial page to Buffer1 */
   430         if (writelen != priv->page_size) {
   431             command[3] = OP_TRANSFER_BUF1;
   432             command[2] = (addr & 0x00FF0000) >> 16;
   433             command[1] = (addr & 0x0000FF00) >> 8;
   434             command[0] = 0;
   435
   436             DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n",
   437                   command[3], command[2], command[1], command[0]);
   438
   439             status = spi_read_write(spi, command, CMD_SIZE);
   440             if (status) {
   441                 mutex_unlock(&priv->lock);
   442                 return status;
   443
   444             }
   445
   446             (void)dataflash_waitready(spi);
   447         }
   448
   449         count = writelen;
   450         while (count) {
   451             d = txer;
   452             l = count > (SPI_FIFOSIZE - CMD_SIZE) ?
   453                 SPI_FIFOSIZE - CMD_SIZE : count;
   454
   455             delta = l % 4;
   456             if (delta) {
   457                 switch (delta) {
   458                 case 1:
   459                     d[0] = OP_WRITE_BUFFER1;
   460                     d[6] = (offset >> 8) & 0xff;
   461                     d[5] = offset & 0xff;
   462                     d[4] = *s++;
   463                     break;
   464                 case 2:
   465                     d[1] = OP_WRITE_BUFFER1;
   466                     d[7] = (offset >> 8) & 0xff;
   467                     d[6] = offset & 0xff;
   468                     d[5] = *s++;
   469                     d[4] = *s++;
   470                     break;
   471                 case 3:
   472                     d[2] = OP_WRITE_BUFFER1;
   473                     d[0] = (offset >> 8) & 0xff;
   474                     d[7] = offset & 0xff;
   475                     d[6] = *s++;
   476                     d[5] = *s++;
   477                     d[4] = *s++;
   478                     break;
   479                 default:
   480                     break;
   481                 }
   482
   483                 DEBUG(MTD_DEBUG_LEVEL3,
   484                       "WRITEBUF: (%x) %x %x %x\n",
   485                       txer[3], txer[2], txer[1], txer[0]);
   486
   487                 status = spi_read_write(spi, txer,
   488                             delta + CMD_SIZE);
   489                 if (status) {
   490                     mutex_unlock(&priv->lock);
   491                     return status;
   492                 }
   493
   494                 /* update */
   495                 count -= delta;
   496                 offset += delta;
   497                 l -= delta;
   498             }
   499
   500             d[3] = OP_WRITE_BUFFER1;
   501             d[1] = (offset >> 8) & 0xff;
   502             d[0] = offset & 0xff;
   503
   504             for (i = 0, d += 4; i < l / 4; i++, d += 4) {
   505                 d[3] = *s++;
   506                 d[2] = *s++;
   507                 d[1] = *s++;
   508                 d[0] = *s++;
   509             }
   510
   511             DEBUG(MTD_DEBUG_LEVEL3, "WRITEBUF: (%x) %x %x %x\n",
   512                   txer[3], txer[2], txer[1], txer[0]);
   513
   514             status = spi_read_write(spi, txer, l + CMD_SIZE);
   515             if (status) {
   516                 mutex_unlock(&priv->lock);
   517                 return status;
   518             }
   519
   520             /* update */
   521             count -= l;
   522             offset += l;
   523         }
   524
   525         /* (2) Program full page via Buffer1 */
   526         command[3] = OP_MWERASE_BUFFER1;
   527         command[2] = (addr >> 16) & 0xff;
   528         command[1] = (addr >> 8) & 0xff;
   529
   530         DEBUG(MTD_DEBUG_LEVEL3, "PROGRAM: (%x) %x %x %x\n",
   531               command[3], command[2], command[1], command[0]);
   532
   533         status = spi_read_write(spi, command, CMD_SIZE);
   534         if (status) {
   535             mutex_unlock(&priv->lock);
   536             return status;
   537         }
   538
   539         (void)dataflash_waitready(spi);
   540
   541         remaining -= writelen;
   542         pageaddr++;
   543         offset = 0;
   544         writebuf += writelen;
   545         *retlen += writelen;
   546
   547         if (remaining > priv->page_size)
   548             writelen = priv->page_size;
   549         else
   550             writelen = remaining;
   551     }
   552     mutex_unlock(&priv->lock);
   553
   554     return status;
   555 }

向mtd设备偏移为@to 写入@len字节,写入数据为@buf,写入的数量@retlen
写入是一个大循环,部分页的写和整页的写方式是不一样的
                                                          
414 ~ 415 to 是要写入的flash 的偏移地址; pageaddr 是对应的flash的页号;offset则是在page内的偏移地址
416 ~ 419 如果页内偏移加上@len大于一页,那么本次只写入offset到页面结束的字节数;否则写入@len

430 ~ 434 通过spi发送写命令,使用BUF1,command[2], command[1] 保存着page address, 从AT45 datasheet可以看出PA12~PA0是page address,也就是说只支持最多8192个page;注意,这里仅仅是发送一个写入命令,真正的数据传输在后面。

446 在传输过程中RDY/BUSY可以用来监视是否传输已经完成

449 ~ 523 真正的写入过程,这里最多只能写入4 bytes,不足4 bytes要分开写

526 ~ 539 开始启动整页对齐的写入,真正的写入过程是449~523


289 static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
 290               size_t *retlen, u_char *buf)
 291 {
 292     struct dataflash *priv = mtd->priv;
 293     struct spi_device *spi = priv->spi;
 294     u32 addr;
 295     int rx_len = 0, count = 0, i = 0;
 296     u_char txer[SPI_FIFOSIZE];
 297     u_char *s = txer;
 298     u_char *d = buf;
 299     int cmd_len = CMD_SIZE + DUMY_SIZE;
 300     int status = 0;
 301
 302     DEBUG(MTD_DEBUG_LEVEL2, "%s: read 0x%x..0x%x\n",
 303           dev_name(&priv->spi->dev), (unsigned)from, (unsigned)(from + len));
 304
 305     *retlen = 0;
 306
 307     /* Sanity checks */
 308     if (!len)
 309         return 0;
 310
 311     if (from + len > mtd->size)
 312         return -EINVAL;
 313
 314     /* Calculate flash page/byte address */
 315     addr = (((unsigned)from / priv->page_size) << priv->page_offset)
 316         + ((unsigned)from % priv->page_size);
 317
 318     mutex_unlock(&priv->lock);
 319
 320     while (len > 0) {
 321
 322         rx_len = len > (SPI_FIFOSIZE - cmd_len) ?
 323             SPI_FIFOSIZE - cmd_len : len;
 324
 325         txer[3] = OP_READ_CONTINUOUS;
 326         txer[2] = (addr >> 16) & 0xff;
 327         txer[1] = (addr >> 8) & 0xff;
 328         txer[0] = addr & 0xff;
 329
 330         status = spi_read_write(spi, txer,
 331                     roundup(rx_len, 4) + cmd_len);
 332         if (status) {
 333             mutex_unlock(&priv->lock);
 334             return status;
 335         }
 336
 337         s = txer + cmd_len;
 338
 339         for (i = rx_len; i >= 0; i -= 4, s += 4) {
 340             if (i < 4) {
 341                 if (i == 1) {
 342                     *d = s[3];
 343                 } else if (i == 2) {
 344                     *d++ = s[3];
 345                     *d++ = s[2];
 346                 } else if (i == 3) {
 347                     *d++ = s[3];
 348                     *d++ = s[2];
 349                     *d++ = s[1];
 350                 }
 351
 352                 break;
 353             }
 354
 355             *d++ = s[3];
 356             *d++ = s[2];
 357             *d++ = s[1];
 358             *d++ = s[0];
 359         }
 360
 361         /* updaate */
 362         len -= rx_len;
 363         addr += rx_len;
 364         count += rx_len;
 365
 366         DEBUG(MTD_DEBUG_LEVEL2,
 367               "%s: left:0x%x, from:0x%08x, to:0x%p, done: 0x%x\n",
 368               __func__, len, (u32) addr, d, count);
 369     }
 370
 371     *retlen = count;
 372
 373     DEBUG(MTD_DEBUG_LEVEL2, "%s: %d bytes read\n", __func__, count);
 374
 375     mutex_unlock(&priv->lock);
 376
 377     return status;
 378 }


296 txer是传输buffer,flash每次最多只能传输24 bytes,而且还包括命令占用的8 bytes,

320~369 通过spi_read_write连续读取flash数据,每次最多读取16 bytes

325~335 设置读取操作,读取结果放在txer中

339 ~ 359 转存读取结果从txer到@buf中


207 static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
 208 {
 209     struct dataflash *priv = (struct dataflash *)mtd->priv;
 210     struct spi_device *spi = priv->spi;
 211     unsigned blocksize = priv->page_size << 3;
 212     uint8_t *command;
 213     uint32_t        rem;
 214
 215     DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%llx len 0x%llx\n",
 216           dev_name(&spi->dev), (long long)instr->addr,
 217           (long long)instr->len);
 218
 219     /* Sanity checks */
 220     if (instr->addr + instr->len > mtd->size)
 221         return -EINVAL;
 222     div_u64_rem(instr->len, priv->page_size, &rem);
 223     if (rem)
 224         return -EINVAL;
 225     div_u64_rem(instr->addr, priv->page_size, &rem);
 226     if (rem)
 227         return -EINVAL;
 228
 229     command = priv->command;
 230
 231     mutex_lock(&priv->lock);
 232     while (instr->len > 0) {
 233         unsigned int pageaddr;
 234         int status;
 235         int do_block;
 236
 237         /* Calculate flash page address; use block erase (for speed) if
 238          * we're at a block boundary and need to erase the whole block.
 239          */
 240         pageaddr = div_u64(instr->addr, priv->page_size);
 241         do_block = (pageaddr & 0x7) == 0 && instr->len >= blocksize;
 242         pageaddr = pageaddr << priv->page_offset;
 243
 244         command[3] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE;
 245         command[2] = (uint8_t) (pageaddr >> 16);
 246         command[1] = (uint8_t) (pageaddr >> 8);
 247         command[0] = 0;
 248
 249         DEBUG(MTD_DEBUG_LEVEL3, "ERASE %s: (%x) %x %x %x [%i]\n",
 250               do_block ? "block" : "page",
 251               command[0], command[1], command[2], command[3], pageaddr);
 252
 253         status = spi_read_write(spi, command, 4);
 254         (void)dataflash_waitready(spi);
 255
 256         if (status < 0) {
 257             printk(KERN_ERR "%s: erase %x, err %d\n",
 258                    dev_name(&spi->dev), pageaddr, status);
 259             /* REVISIT:  can retry instr->retries times; or
 260              * giveup and instr->fail_addr = instr->addr;
 261              */
 262             continue;
 263         }
 264
 265         if (do_block) {
 266             instr->addr += blocksize;
 267             instr->len -= blocksize;
 268         } else {
 269             instr->addr += priv->page_size;
 270             instr->len -= priv->page_size;
 271         }
 272     }
 273     mutex_unlock(&priv->lock);
 274
 275     /* Inform MTD subsystem that erase is complete */
 276     instr->state = MTD_ERASE_DONE;
 277     mtd_erase_callback(instr);
 278
 279     return 0;
 280 }

240~242 如果删除是在block边界,那么使用block erase可以加快速度

244 ~247  A21~A9是13 bit page address,最后8bits unuseful



原创粉丝点击