--- zzzz-none-000/linux-2.6.28.10/drivers/mtd/chips/cfi_cmdset_0002.c 2009-05-02 18:54:43.000000000 +0000 +++ puma5-6360-529/linux-2.6.28.10/drivers/mtd/chips/cfi_cmdset_0002.c 2011-12-09 15:50:23.000000000 +0000 @@ -82,6 +82,28 @@ }; +/*------------------------------------------------------------------------------------------*\ + * No scheduling in panic mode +\*------------------------------------------------------------------------------------------*/ +extern unsigned int tffs_panic_mode; + +static inline void cfi_add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait) { + if(!tffs_panic_mode) + add_wait_queue(q, wait); +} +static inline void cfi_remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait) { + if(!tffs_panic_mode) + remove_wait_queue(q, wait); +} + +static inline void cfi_schedule(void) { + if(!tffs_panic_mode) + schedule(); + else + cfi_udelay(10000); +} + + /* #define DEBUG_CFI_FEATURES */ @@ -359,6 +381,7 @@ extp = (struct cfi_pri_amdstd*)cfi_read_pri(map, adr, sizeof(*extp), "Amd/Fujitsu"); if (!extp) { + printk(KERN_ERR "[%s:%d] Cannot read chip feature table... Probe failure!\n", __func__, __LINE__); kfree(mtd); return NULL; } @@ -597,7 +620,7 @@ /* Erase suspend */ /* It's harmless to issue the Erase-Suspend and Erase-Resume * commands when the erase algorithm isn't in progress. */ - map_write(map, CMD(0xB0), chip->in_progress_block_addr); + map_cmd_write(map, CMD(0xB0), chip->in_progress_block_addr); chip->oldstate = FL_ERASING; chip->state = FL_ERASE_SUSPENDING; chip->erase_suspended = 1; @@ -611,7 +634,7 @@ * there was an error (so leave the erase * routine to recover from it) or we trying to * use the erase-in-progress sector. */ - map_write(map, CMD(0x30), chip->in_progress_block_addr); + map_cmd_write(map, CMD(0x30), chip->in_progress_block_addr); chip->state = FL_ERASING; chip->oldstate = FL_READY; printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__); @@ -643,10 +666,10 @@ default: sleep: set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); + cfi_add_wait_queue(&chip->wq, &wait); spin_unlock(chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); + cfi_schedule(); + cfi_remove_wait_queue(&chip->wq, &wait); spin_lock(chip->mutex); goto resettime; } @@ -660,7 +683,7 @@ switch(chip->oldstate) { case FL_ERASING: chip->state = chip->oldstate; - map_write(map, CMD(0x30), chip->in_progress_block_addr); + map_cmd_write(map, CMD(0x30), chip->in_progress_block_addr); chip->oldstate = FL_READY; chip->state = FL_ERASING; break; @@ -708,7 +731,7 @@ struct cfi_private *cfi = map->fldrv_priv; if (chip->state != FL_POINT && chip->state != FL_READY) { - map_write(map, CMD(0xf0), adr); + map_cmd_write(map, CMD(0xf0), adr); chip->state = FL_READY; } (void) map_read(map, adr); @@ -753,7 +776,7 @@ * we resume the whole thing at once). Yes, it * can happen! */ - map_write(map, CMD(0xb0), adr); + map_cmd_write(map, CMD(0xb0), adr); usec -= xip_elapsed_since(start); suspended = xip_currtime(); do { @@ -775,7 +798,7 @@ break; chip->state = FL_XIP_WHILE_ERASING; chip->erase_suspended = 1; - map_write(map, CMD(0xf0), adr); + map_cmd_write(map, CMD(0xf0), adr); (void) map_read(map, adr); xip_iprefetch(); local_irq_enable(); @@ -793,17 +816,17 @@ while (chip->state != FL_XIP_WHILE_ERASING) { DECLARE_WAITQUEUE(wait, current); set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); + cfi_add_wait_queue(&chip->wq, &wait); spin_unlock(chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); + cfi_schedule(); + cfi_remove_wait_queue(&chip->wq, &wait); spin_lock(chip->mutex); } /* Disallow XIP again */ local_irq_disable(); /* Resume the write or erase operation */ - map_write(map, CMD(0x30), adr); + map_cmd_write(map, CMD(0x30), adr); chip->state = oldstate; start = xip_currtime(); } else if (usec >= 1000000/HZ) { @@ -874,6 +897,28 @@ #endif +/*------------------------------------------------------------------------------------------*\ +\*------------------------------------------------------------------------------------------*/ +#if defined(CONFIG_MACH_FUSIV) +struct _nmi_vector_gap { + unsigned int in_use; + unsigned long long start; + unsigned long long gap_size; + unsigned long long end; +}; + +struct _nmi_vector_gap nmi_vector_gap; + +void set_nmi_vetor_gap(unsigned int start, unsigned int firmware_size, unsigned int gap_size) { + nmi_vector_gap.start = (unsigned long long)start & ((16ULL << 20) - 1ULL); /*--- funktioniert bis zur Flashgröße von 16 MByte ---*/ + nmi_vector_gap.gap_size = gap_size; + nmi_vector_gap.end = (unsigned long long)firmware_size; + nmi_vector_gap.in_use = 1; +} +#endif /*--- #if defined(CONFIG_MACH_FUSIV) ---*/ + +extern unsigned int tffs_spi_mode; + static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf) { unsigned long cmd_addr; @@ -885,23 +930,58 @@ /* Ensure cmd read/writes are aligned. */ cmd_addr = adr & ~(map_bankwidth(map)-1); - spin_lock(chip->mutex); + if(!tffs_spi_mode) + spin_lock(chip->mutex); + ret = get_chip(map, chip, cmd_addr, FL_READY); if (ret) { - spin_unlock(chip->mutex); + if(!tffs_spi_mode) + spin_unlock(chip->mutex); return ret; } if (chip->state != FL_POINT && chip->state != FL_READY) { - map_write(map, CMD(0xf0), cmd_addr); + map_cmd_write(map, CMD(0xf0), cmd_addr); chip->state = FL_READY; } +#if defined(CONFIG_MACH_FUSIV) + + /*--- wir sind jenseites/höher als der nmi vector gap aber unterhalb des JFFS ---*/ + if (nmi_vector_gap.in_use && (adr > nmi_vector_gap.start) && (adr < nmi_vector_gap.end)) { + /*--- printk(KERN_ERR "[%s] adr 0x%llx (groesser gap start, kleiner end: %llx)\n", __FUNCTION__, adr, nmi_vector_gap.end); ---*/ + map_copy_from(map, buf, adr + nmi_vector_gap.gap_size, len); + + /*--- wir sind unterhalb des nmi vector gaps, die länge kann aber hineinreichen ---*/ + } else if (nmi_vector_gap.in_use && (adr <= nmi_vector_gap.start)) { + + /*--- eine Aufteilung ist nötig ---*/ + if(adr + len > nmi_vector_gap.start) { + unsigned int len_part = nmi_vector_gap.start - adr; + /*--- printk(KERN_ERR "[%s] adr 0x%llx (kleiner gap start, aufteilung noetig, part 0x%x und 0x%x)\n", __FUNCTION__, adr, len_part, len - len_part); ---*/ + if(len_part) + map_copy_from(map, buf, adr, len_part); + map_copy_from(map, buf + len_part, adr + nmi_vector_gap.gap_size + len_part, len - len_part); + + /*--- eine Aufteilung ist nicht nötig ---*/ + } else { + /*--- printk(KERN_ERR "[%s] adr 0x%llx (kleiner gap start)\n", __FUNCTION__, adr); ---*/ + map_copy_from(map, buf, adr, len); + } + } else { + /*--- printk(KERN_ERR "[%s] adr 0x%llx (groesser end 0x%llx)\n", __FUNCTION__, adr, nmi_vector_gap.end); ---*/ + map_copy_from(map, buf, adr, len); + } + +#else map_copy_from(map, buf, adr, len); +#endif put_chip(map, chip, cmd_addr); - spin_unlock(chip->mutex); + + if(!tffs_spi_mode) + spin_unlock(chip->mutex); return 0; } @@ -919,7 +999,6 @@ chipnum = (from >> cfi->chipshift); ofs = from - (chipnum << cfi->chipshift); - *retlen = 0; while (len) { @@ -962,12 +1041,12 @@ printk(KERN_DEBUG "Waiting for chip to read, status = %d\n", chip->state); #endif set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); + cfi_add_wait_queue(&chip->wq, &wait); spin_unlock(chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); + cfi_schedule(); + cfi_remove_wait_queue(&chip->wq, &wait); #if 0 if(signal_pending(current)) return -EINTR; @@ -1013,7 +1092,6 @@ chipnum=from>>3; ofs=from & 7; - *retlen = 0; while (len) { @@ -1107,10 +1185,10 @@ DECLARE_WAITQUEUE(wait, current); set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); + cfi_add_wait_queue(&chip->wq, &wait); spin_unlock(chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); + cfi_schedule(); + cfi_remove_wait_queue(&chip->wq, &wait); timeo = jiffies + (HZ / 2); /* FIXME */ spin_lock(chip->mutex); continue; @@ -1132,7 +1210,7 @@ /* Did we succeed? */ if (!chip_good(map, adr, datum)) { /* reset on all failures. */ - map_write( map, CMD(0xF0), chip->start ); + map_cmd_write( map, CMD(0xF0), chip->start ); /* FIXME - should have reset delay before continuing */ if (++retry_cnt <= MAX_WORD_RETRIES) @@ -1183,12 +1261,12 @@ printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state); #endif set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&cfi->chips[chipnum].wq, &wait); + cfi_add_wait_queue(&cfi->chips[chipnum].wq, &wait); spin_unlock(cfi->chips[chipnum].mutex); - schedule(); - remove_wait_queue(&cfi->chips[chipnum].wq, &wait); + cfi_schedule(); + cfi_remove_wait_queue(&cfi->chips[chipnum].wq, &wait); #if 0 if(signal_pending(current)) return -EINTR; @@ -1261,12 +1339,12 @@ printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state); #endif set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&cfi->chips[chipnum].wq, &wait); + cfi_add_wait_queue(&cfi->chips[chipnum].wq, &wait); spin_unlock(cfi->chips[chipnum].mutex); - schedule(); - remove_wait_queue(&cfi->chips[chipnum].wq, &wait); + cfi_schedule(); + cfi_remove_wait_queue(&cfi->chips[chipnum].wq, &wait); #if 0 if(signal_pending(current)) return -EINTR; @@ -1332,13 +1410,13 @@ //cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); /* Write Buffer Load */ - map_write(map, CMD(0x25), cmd_adr); + map_cmd_write(map, CMD(0x25), cmd_adr); chip->state = FL_WRITING_TO_BUFFER; /* Write length of data to come */ words = len / map_bankwidth(map); - map_write(map, CMD(words - 1), cmd_adr); + map_cmd_write(map, CMD(words - 1), cmd_adr); /* Write data */ z = 0; while(z < words * map_bankwidth(map)) { @@ -1353,7 +1431,7 @@ adr += z; /* Write Buffer Program Confirm: GO GO GO */ - map_write(map, CMD(0x29), cmd_adr); + map_cmd_write(map, CMD(0x29), cmd_adr); chip->state = FL_WRITING; INVALIDATE_CACHE_UDELAY(map, chip, @@ -1368,10 +1446,10 @@ DECLARE_WAITQUEUE(wait, current); set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); + cfi_add_wait_queue(&chip->wq, &wait); spin_unlock(chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); + cfi_schedule(); + cfi_remove_wait_queue(&chip->wq, &wait); timeo = jiffies + (HZ / 2); /* FIXME */ spin_lock(chip->mutex); continue; @@ -1390,7 +1468,7 @@ } /* reset on all failures. */ - map_write( map, CMD(0xF0), chip->start ); + map_cmd_write( map, CMD(0xF0), chip->start ); xip_enable(map, chip, adr); /* FIXME - should have reset delay before continuing */ @@ -1536,10 +1614,10 @@ if (chip->state != FL_ERASING) { /* Someone's suspended the erase. Sleep */ set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); + cfi_add_wait_queue(&chip->wq, &wait); spin_unlock(chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); + cfi_schedule(); + cfi_remove_wait_queue(&chip->wq, &wait); spin_lock(chip->mutex); continue; } @@ -1565,7 +1643,7 @@ /* Did we succeed? */ if (!chip_good(map, adr, map_word_ff(map))) { /* reset on all failures. */ - map_write( map, CMD(0xF0), chip->start ); + map_cmd_write( map, CMD(0xF0), chip->start ); /* FIXME - should have reset delay before continuing */ ret = -EIO; @@ -1608,7 +1686,7 @@ cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); - map_write(map, CMD(0x30), adr); + map_cmd_write(map, CMD(0x30), adr); chip->state = FL_ERASING; chip->erase_suspended = 0; @@ -1624,10 +1702,10 @@ if (chip->state != FL_ERASING) { /* Someone's suspended the erase. Sleep */ set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); + cfi_add_wait_queue(&chip->wq, &wait); spin_unlock(chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); + cfi_schedule(); + cfi_remove_wait_queue(&chip->wq, &wait); spin_lock(chip->mutex); continue; } @@ -1656,7 +1734,7 @@ /* Did we succeed? */ if (!chip_good(map, adr, map_word_ff(map))) { /* reset on all failures. */ - map_write( map, CMD(0xF0), chip->start ); + map_cmd_write( map, CMD(0xF0), chip->start ); /* FIXME - should have reset delay before continuing */ ret = -EIO; @@ -1735,7 +1813,7 @@ cfi->device_type, NULL); cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); - map_write(map, CMD(0x40), chip->start + adr); + map_cmd_write(map, CMD(0x40), chip->start + adr); chip->state = FL_READY; put_chip(map, chip, adr + chip->start); @@ -1763,7 +1841,7 @@ cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); - map_write(map, CMD(0x70), adr); + map_cmd_write(map, CMD(0x70), adr); chip->state = FL_READY; put_chip(map, chip, adr + chip->start); @@ -1818,13 +1896,13 @@ default: /* Not an idle state */ set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); + cfi_add_wait_queue(&chip->wq, &wait); spin_unlock(chip->mutex); - schedule(); + cfi_schedule(); - remove_wait_queue(&chip->wq, &wait); + cfi_remove_wait_queue(&chip->wq, &wait); goto retry; } @@ -1915,7 +1993,7 @@ if (chip->state == FL_PM_SUSPENDED) { chip->state = FL_READY; - map_write(map, CMD(0xF0), chip->start); + map_cmd_write(map, CMD(0xF0), chip->start); wake_up(&chip->wq); } else