int flash_erase_region(kdev_t dev, __u32 offset, __u32 size) { int minor; struct flashpartition *part; unsigned char *erase_start; short retries = 5; short success; minor = MINOR(dev); if (minor < FLASH_MINOR) { return -EINVAL; } part = &partitions[minor - FLASH_MINOR]; if (!part->start) { return -EINVAL; } /* Start the erasure, then sleep and wake up now and then to see * if it's done. */ erase_start = part->start + offset; flash_safe_acquire(part); do { flash_init_erase(erase_start, size); while (flash_is_busy((flashptr)erase_start)) { current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies + HZ / 2; schedule(); } success = ((flashptr)erase_start)[0] == FLASH_ERASE_STATE && ((flashptr)erase_start)[1] == FLASH_ERASE_STATE && ((flashptr)erase_start)[2] == FLASH_ERASE_STATE && ((flashptr)erase_start)[3] == FLASH_ERASE_STATE; if (!success) { printk(KERN_NOTICE "flash: erase of region " "[0x%p, 0x%p] failed once\n", erase_start, erase_start + size); } } while (retries-- && !success); flash_safe_release(part); if (retries == 0 && !success) { printk(KERN_WARNING "flash: erase of region " "[0x%p, 0x%p] totally failed\n", erase_start, erase_start + size); return -1; } return 0; }
static void flash_wait_for_write_complete() { int ii; for (ii = 0;flash_is_busy(); ii++) { // TODO check for timeout vTaskDelay(1); } //shell_printf("waited %d", ii); }
static int32_t flash_status_check_orig(flash_info_t * info, cfiptr_t cptr, cfiword_t * cword, uint32_t tout, char *prompt) { uint32_t start; /* Wait for command completion */ start = get_timer(0); while (flash_is_busy(info, cptr, cword)) { if ((flash_time_out(info, cptr)) || ((get_timer(start)) > tout * CFG_HZ)) { if (flash_is_busy(info, cptr, cword)) { printf("Flash %s timeout at address %x data %x\n", prompt, (uint32_t) cptr.cp, cword->l); flash_write_cmd(info, 0, 0, info->cmd_reset); return ERR_TIMOUT; } } } return ERR_OK; }
void flash_busy_wait_erase(unsigned char *ptr) { flashptr flashStart; ptr = (unsigned char *)((unsigned long)ptr | MEM_NON_CACHEABLE); flashStart = (flashptr)getchip(ptr)->start; /* busy-wait for flash completion - when D6 stops toggling between * reads. */ while (flash_is_busy(flashStart)) /* nothing */; }
static int flash_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int minor; struct flashpartition *part; struct flashchipinfo *finfo; if (!inode || !inode->i_rdev) return -EINVAL; minor = MINOR(inode->i_rdev); if(minor < FLASH_MINOR) return -EINVAL; /* only ioctl's for flash devices */ part = &partitions[minor - FLASH_MINOR]; switch(cmd) { case FLASHIO_CHIPINFO: if(!suser()) return -EACCES; if(arg == 0) return -EINVAL; finfo = (struct flashchipinfo *)arg; /* TODO: verify arg */ finfo->isValid = chips[0].isValid; finfo->manufacturer_id = chips[0].manufacturer_id; finfo->device_id = chips[0].device_id; finfo->size = chips[0].size; finfo->sectorsize = chips[0].sectorsize; return 0; case FLASHIO_ERASEALL: FDEBUG(printk("flash_ioctl(): Got FLASHIO_ERASEALL request.\n")); if(!part->start) return -EINVAL; if(!suser()) return -EACCES; /* Invalidate all pages and buffers */ invalidate_inodes(inode->i_rdev); invalidate_buffers(inode->i_rdev); /* * Start the erasure, then sleep and wake up now and * then to see if it's done. We use the waitqueue to * make sure we don't start erasing in the middle of * a write, or that nobody start using the flash while * we're erasing. * * TODO: break up partition erases that spans more than one * chip. */ flash_safe_acquire(part); flash_init_erase(part->start, part->size); #if 1 flash_finalize_erase(part->start, part->size); #else while (flash_is_busy(part->start) || !flash_pos_is_clean(part->start)) { current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies + HZ / 2; schedule(); } #endif flash_safe_release(part); return 0; default: return -EPERM; } return -EPERM; }