?? mtd.patch
字號:
rinfo = (struct cfi_intelext_regioninfo *)&extp->extra[extra_size];@@ -274,6 +308,9 @@ * sizeof(struct cfi_intelext_blockinfo); } + if (extp->MinorVersion >= '4')+ extra_size += sizeof(struct cfi_intelext_programming_regioninfo);+ if (extp_size < sizeof(*extp) + extra_size) { need_more: extp_size = sizeof(*extp) + extra_size;@@ -324,7 +361,9 @@ mtd->resume = cfi_intelext_resume; mtd->flags = MTD_CAP_NORFLASH; mtd->name = map->name;- ++ mtd->reboot_notifier.notifier_call = cfi_intelext_reboot;+ if (cfi->cfi_mode == CFI_MODE_CFI) { /* * It's a real CFI chip, not one for which the probe@@ -416,15 +455,19 @@ } for (i=0; i<mtd->numeraseregions;i++){- printk(KERN_DEBUG "%d: offset=0x%x,size=0x%x,blocks=%d\n",+ printk(KERN_DEBUG "erase region %d: offset=0x%x,size=0x%x,blocks=%d\n", i,mtd->eraseregions[i].offset, mtd->eraseregions[i].erasesize, mtd->eraseregions[i].numblocks); } -#if 0- mtd->read_user_prot_reg = cfi_intelext_read_user_prot_reg;+#ifdef CONFIG_MTD_OTP mtd->read_fact_prot_reg = cfi_intelext_read_fact_prot_reg;+ mtd->read_user_prot_reg = cfi_intelext_read_user_prot_reg;+ mtd->write_user_prot_reg = cfi_intelext_write_user_prot_reg;+ mtd->lock_user_prot_reg = cfi_intelext_lock_user_prot_reg;+ mtd->get_fact_prot_info = cfi_intelext_get_fact_prot_info;+ mtd->get_user_prot_info = cfi_intelext_get_user_prot_info; #endif /* This function has the potential to distort the reality@@ -433,6 +476,7 @@ goto setup_err; __module_get(THIS_MODULE);+ register_reboot_notifier(&mtd->reboot_notifier); return mtd; setup_err:@@ -463,7 +507,7 @@ * arrangement at this point. This can be rearranged in the future * if someone feels motivated enough. --nico */- if (extp && extp->MajorVersion == '1' && extp->MinorVersion == '3'+ if (extp && extp->MajorVersion == '1' && extp->MinorVersion >= '3' && extp->FeatureSupport & (1 << 9)) { struct cfi_private *newcfi; struct flchip *chip;@@ -471,15 +515,20 @@ int offs, numregions, numparts, partshift, numvirtchips, i, j; /* Protection Register info */- offs = (extp->NumProtectionFields - 1) * (4 + 6);+ offs = (extp->NumProtectionFields - 1) *+ sizeof(struct cfi_intelext_otpinfo); /* Burst Read info */- offs += 6;+ offs += (extp->MinorVersion < '4') ? 6 : 5; /* Number of partition regions */ numregions = extp->extra[offs]; offs += 1; + /* skip the sizeof(partregion) field in CFI 1.4 */+ if (extp->MinorVersion >= '4')+ offs += 2;+ /* Number of hardware partitions */ numparts = 0; for (i = 0; i < numregions; i++) {@@ -491,6 +540,20 @@ sizeof(struct cfi_intelext_blockinfo); } + /* Programming Region info */+ if (extp->MinorVersion >= '4') {+ struct cfi_intelext_programming_regioninfo *prinfo;+ prinfo = (struct cfi_intelext_programming_regioninfo *)&extp->extra[offs];+ MTD_PROGREGION_SIZE(mtd) = cfi->interleave << prinfo->ProgRegShift;+ MTD_PROGREGION_CTRLMODE_VALID(mtd) = cfi->interleave * prinfo->ControlValid;+ MTD_PROGREGION_CTRLMODE_INVALID(mtd) = cfi->interleave * prinfo->ControlInvalid;+ mtd->flags |= MTD_PROGRAM_REGIONS;+ printk(KERN_DEBUG "%s: program region size/ctrl_valid/ctrl_inval = %d/%d/%d\n",+ map->name, MTD_PROGREGION_SIZE(mtd),+ MTD_PROGREGION_CTRLMODE_VALID(mtd),+ MTD_PROGREGION_CTRLMODE_INVALID(mtd));+ }+ /* * All functions below currently rely on all chips having * the same geometry so we'll just assume that all hardware@@ -563,7 +626,7 @@ resettime: timeo = jiffies + HZ; retry:- if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING)) {+ if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING || mode == FL_OTP_WRITE)) { /* * OK. We have possibility for contension on the write/erase * operations which are global to the real chip and not per@@ -635,8 +698,8 @@ break; if (time_after(jiffies, timeo)) {- printk(KERN_ERR "Waiting for chip to be ready timed out. Status %lx\n", - status.x[0]);+ printk(KERN_ERR "%s: Waiting for chip to be ready timed out. Status %lx\n", + map->name, status.x[0]); return -EIO; } spin_unlock(chip->mutex);@@ -683,8 +746,8 @@ map_write(map, CMD(0x70), adr); chip->state = FL_ERASING; chip->oldstate = FL_READY;- printk(KERN_ERR "Chip not ready after erase "- "suspended: status = 0x%lx\n", status.x[0]);+ printk(KERN_ERR "%s: Chip not ready after erase "+ "suspended: status = 0x%lx\n", map->name, status.x[0]); return -EIO; } @@ -791,7 +854,7 @@ DISABLE_VPP(map); break; default:- printk(KERN_ERR "put_chip() called with oldstate %d!!\n", chip->oldstate);+ printk(KERN_ERR "%s: put_chip() called with oldstate %d!!\n", map->name, chip->oldstate); } wake_up(&chip->wq); }@@ -807,10 +870,6 @@ * assembly to make sure inline functions were actually inlined and that gcc * didn't emit calls to its own support functions). Also configuring MTD CFI * support to a single buswidth and a single interleave is also recommended.- * Note that not only IRQs are disabled but the preemption count is also- * increased to prevent other locking primitives (namely spin_unlock) from- * decrementing the preempt count to zero and scheduling the CPU away while- * not in array mode. */ static void xip_disable(struct map_info *map, struct flchip *chip,@@ -818,7 +877,6 @@ { /* TODO: chips with no XIP use should ignore and return */ (void) map_read(map, adr); /* ensure mmu mapping is up to date */- preempt_disable(); local_irq_disable(); } @@ -831,9 +889,8 @@ chip->state = FL_READY; } (void) map_read(map, adr);- asm volatile (".rep 8; nop; .endr"); /* fill instruction prefetch */+ xip_iprefetch(); local_irq_enable();- preempt_enable(); } /*@@ -909,7 +966,7 @@ (void) map_read(map, adr); asm volatile (".rep 8; nop; .endr"); local_irq_enable();- preempt_enable();+ spin_unlock(chip->mutex); asm volatile (".rep 8; nop; .endr"); cond_resched(); @@ -919,15 +976,15 @@ * a suspended erase state. If so let's wait * until it's done. */- preempt_disable();+ spin_lock(chip->mutex); while (chip->state != newstate) { DECLARE_WAITQUEUE(wait, current); set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&chip->wq, &wait);- preempt_enable();+ spin_unlock(chip->mutex); schedule(); remove_wait_queue(&chip->wq, &wait);- preempt_disable();+ spin_lock(chip->mutex); } /* Disallow XIP again */ local_irq_disable();@@ -956,12 +1013,14 @@ * The INVALIDATE_CACHED_RANGE() macro is normally used in parallel while * the flash is actively programming or erasing since we have to poll for * the operation to complete anyway. We can't do that in a generic way with- * a XIP setup so do it before the actual flash operation in this case.+ * a XIP setup so do it before the actual flash operation in this case+ * and stub it out from INVALIDATE_CACHE_UDELAY. */-#undef INVALIDATE_CACHED_RANGE-#define INVALIDATE_CACHED_RANGE(x...)-#define XIP_INVAL_CACHED_RANGE(map, from, size) \- do { if(map->inval_cache) map->inval_cache(map, from, size); } while(0)+#define XIP_INVAL_CACHED_RANGE(map, from, size) \+ INVALIDATE_CACHED_RANGE(map, from, size)++#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \+ UDELAY(map, chip, adr, usec) /* * Extra notes:@@ -984,11 +1043,23 @@ #define xip_disable(map, chip, adr) #define xip_enable(map, chip, adr)--#define UDELAY(map, chip, adr, usec) cfi_udelay(usec)- #define XIP_INVAL_CACHED_RANGE(x...) +#define UDELAY(map, chip, adr, usec) \+do { \+ spin_unlock(chip->mutex); \+ cfi_udelay(usec); \+ spin_lock(chip->mutex); \+} while (0)++#define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \+do { \+ spin_unlock(chip->mutex); \+ INVALIDATE_CACHED_RANGE(map, adr, len); \+ cfi_udelay(usec); \+ spin_lock(chip->mutex); \+} while (0)+ #endif static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len)@@ -1094,7 +1165,7 @@ if(chip->ref_point_counter == 0) chip->state = FL_READY; } else- printk(KERN_ERR "Warning: unpoint called on non pointed region\n"); /* Should this give an error? */+ printk(KERN_ERR "%s: Warning: unpoint called on non pointed region\n", map->name); /* Should this give an error? */ put_chip(map, chip, chip->start); spin_unlock(chip->mutex);@@ -1176,121 +1247,31 @@ return ret; } -#if 0-static int __xipram cfi_intelext_read_prot_reg (struct mtd_info *mtd,- loff_t from, size_t len,- size_t *retlen,- u_char *buf,- int base_offst, int reg_sz)-{- struct map_info *map = mtd->priv;- struct cfi_private *cfi = map->fldrv_priv;- struct cfi_pri_intelext *extp = cfi->cmdset_priv;- struct flchip *chip;- int ofs_factor = cfi->interleave * cfi->device_type;- int count = len;- int chip_num, offst;- int ret;-- chip_num = ((unsigned int)from/reg_sz);- offst = from - (reg_sz*chip_num)+base_offst;-- while (count) {- /* Calculate which chip & protection register offset we need */-- if (chip_num >= cfi->numchips)- goto out;-- chip = &cfi->chips[chip_num];- - spin_lock(chip->mutex);- ret = get_chip(map, chip, chip->start, FL_JEDEC_QUERY);- if (ret) {- spin_unlock(chip->mutex);- return (len-count)?:ret;- }-- xip_disable(map, chip, chip->start);-- if (chip->state != FL_JEDEC_QUERY) {- map_write(map, CMD(0x90), chip->start);- chip->state = FL_JEDEC_QUERY;- }-- while (count && ((offst-base_offst) < reg_sz)) {- *buf = map_read8(map,(chip->start+((extp->ProtRegAddr+1)*ofs_factor)+offst));- buf++;- offst++;- count--;- }-- xip_enable(map, chip, chip->start);- put_chip(map, chip, chip->start);- spin_unlock(chip->mutex);-- /* Move on to the next chip */- chip_num++;- offst = base_offst;- }- - out: - return len-count;-}- -static int cfi_intelext_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)-{- struct map_info *map = mtd->priv;- struct cfi_private *cfi = map->fldrv_priv;- struct cfi_pri_intelext *extp=cfi->cmdset_priv;- int base_offst,reg_sz;- - /* Check that we actually have some protection registers */- if(!extp || !(extp->FeatureSupport&64)){- printk(KERN_WARNING "%s: This flash device has no protection data to read!\n",map->name);- return 0;- }-- base_offst=(1<<extp->FactProtRegSize);- reg_sz=(1<<extp->UserProtRegSize);-- return cfi_intelext_read_prot_reg(mtd, from, len, retlen, buf, base_offst, reg_sz);-}--static int cfi_intelext_read_fact_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)-{- struct map_info *map = mtd->priv;- struct cfi_private *cfi = map->fldrv_priv;- struct cfi_pri_intelext *extp=cfi->cmdset_priv;- int base_offst,reg_sz;- - /* Check that we actually have some protection registers */- if(!extp || !(extp->FeatureSupport&64)){- printk(KERN_WARNING "%s: This flash device has no protection data to read!\n",map->name);- return 0;- }-- base_offst=0;- reg_sz=(1<<extp->FactProtRegSize);-- return cfi_intelext_read_prot_reg(mtd, from, len, retlen, buf, base_offst, reg_sz);-}-#endif- static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,- unsigned long adr, map_word datum)+ unsigned long adr, map_word datum, int mode) { struct cfi_private *cfi = map->fldrv_priv;- map_word status, status_OK;+ map_word status, status_OK, write_cmd; unsigned long timeo; int z, ret=0; adr += chip->start; - /* Let's determine this according to the interleave only once */+ /* Let's determine those according to the interleave only once */ status_OK = CMD(0x80);+ switch (mode) {+ case FL_WRITING:+ write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0x40) : CMD(0x41);+ break;+ case FL_OTP_WRITE:+ write_cmd = CMD(0xc0);+ break;+ default:+ return -EINVAL;+ } spin_lock(chip->mutex);- ret = get_chip(map, chip, adr, FL_WRITING);+ ret = get_chip(map, chip, adr, mode); if (ret) { spin_unlock(chip->mutex); return ret;@@ -1299,19 +1280,18 @@ XIP_INVAL_CACHED_RANGE(map, adr, map_bankwidth(map)); ENABLE_VPP(map); xip_disable(map, chip, adr);- map_write(map, CMD(0x40), adr);+ map_write(map, write_cmd, adr); map_write(map, datum, adr);- chip->state = FL_WRITING;+ chip->state = mode; - spin_unlock(chip->mutex);- INVALIDATE_CACHED_RANGE(map, adr, map_bankwidth(map));- UDELAY(map, chip, adr, chip->word_write_time);- spin_lock(chip->mutex);+ INVALIDATE_CACHE_UDELAY(map, chip,+ adr, map_bankwidth(map),+ chip->word_write_time); timeo = jiffies + (HZ/2); z = 0; for (;;) {- if (chip->state != FL_WRITING) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -