/** * @fn spi_flash_erase * @brief Erase from data from SPI flash * @param[IN] u32Offset * Address to write to at the SPI flash * @param[IN] u32Sz * Data size * @return Status of execution * @note Data size is limited by the SPI flash size only */ sint8 spi_flash_erase(uint32 u32Offset, uint32 u32Sz) { uint32 i = 0; sint8 ret = M2M_SUCCESS; uint8 tmp = 0; #ifdef PROFILING uint32 t; t = GetTickCount(); #endif M2M_PRINT("\r\n>Start erasing...\r\n"); for(i = u32Offset; i < (u32Sz +u32Offset); i += (16*FLASH_PAGE_SZ)) { ret += spi_flash_write_enable(); ret += spi_flash_read_status_reg(&tmp); ret += spi_flash_sector_erase(i + 10); ret += spi_flash_read_status_reg(&tmp); do { if(ret != M2M_SUCCESS) goto ERR; ret += spi_flash_read_status_reg(&tmp); }while(tmp & 0x01); } M2M_PRINT("Done\r\n"); #ifdef PROFILING M2M_PRINT("#Erase time = %f sec\n", (GetTickCount()-t)/1000.0); #endif ERR: return ret; }
static u64_t spi_flash_write(struct block_t * blk, u8_t * buf, u64_t blkno, u64_t blkcnt) { struct spi_flash_private_data_t * dat = (struct spi_flash_private_data_t *)blk->priv; u64_t addr = blkno * blk->blksz; s64_t count = blkcnt * blk->blksz; u8_t * pbuf = buf; u64_t i; if(dat->id->flags & SECTOR_4K) { for(i = 0; i < blkcnt; i++) spi_flash_sector_erase_4k(dat->dev, addr + i * blk->blksz); } else { for(i = 0; i < blkcnt; i++) spi_flash_sector_erase(dat->dev, addr + i * blk->blksz); } while(count > 0) { spi_flash_write_one_page(dat->dev, addr, pbuf); addr += 256; pbuf += 256; count -= 256; } return blkcnt; }
void handle_erase_block(struct cfw_message *msg) { ll_storage_erase_block_req_msg_t * req = (ll_storage_erase_block_req_msg_t *) msg; ll_storage_erase_block_rsp_msg_t * resp = (ll_storage_erase_block_rsp_msg_t *) cfw_alloc_rsp_msg(msg, MSG_ID_LL_ERASE_BLOCK_RSP, sizeof(*resp)); flash_device_t flash; uint16_t flash_id = 0; int16_t partition_index = -1; uint32_t i = 0; DRIVER_API_RC ret = DRV_RC_FAIL; if (req->no_blks == 0) { pr_debug(LOG_MODULE_MAIN, "LL Storage Service - Write Block: Invalid write size"); ret = DRV_RC_INVALID_OPERATION; goto send; } for (i = 0; i < ll_storage_config.no_part; i++) if (ll_storage_config.partitions[i].partition_id == req->partition_id) { flash_id = ll_storage_config.partitions[i].flash_id; partition_index = i; break; } if (partition_index == -1) { pr_debug(LOG_MODULE_MAIN, "LL Storage Service - Write Block: Invalid partition ID"); ret = DRV_RC_FAIL; goto send; } uint16_t last_block = ll_storage_config.partitions[partition_index].start_block + req->st_blk + req->no_blks - 1; if (last_block > ll_storage_config.partitions[partition_index].end_block) { pr_debug(LOG_MODULE_MAIN, "LL Storage Service - Write Block: Partition overflow"); ret = DRV_RC_OUT_OF_MEM; goto send; } flash = flash_devices[flash_id]; if (flash.flash_location == EMBEDDED_FLASH) { ret = soc_flash_block_erase(ll_storage_config.partitions[partition_index].start_block + req->st_blk, req->no_blks); } #ifdef CONFIG_SPI_FLASH else { // SERIAL_FLASH ret = spi_flash_sector_erase((struct device *)&pf_sba_device_flash_spi0, ll_storage_config.partitions[partition_index].start_block + req->st_blk, req->no_blks); } #endif send: resp->rsp_header.status = ret; cfw_send_message(resp); }
/* We could store these in the mtd structure, but we only support 1 device.. static struct mtd_info *mtd_info; */ static int sf_erase(struct mtd_info *mtd, struct erase_info *instr) { int ret; struct wmt_sf_info_t *info = (struct wmt_sf_info_t *)mtd->priv; struct sfreg_t *sfreg = info->reg; REG32_VAL(PMCEU_ADDR) |= SF_CLOCK_EN; ret = spi_flash_sector_erase((unsigned long)instr->addr, sfreg); if (ret != ERR_OK) { printk(KERN_ERR "sf_erase() error at address 0x%lx \n", (unsigned long)instr->addr); return -EINVAL; } instr->state = MTD_ERASE_DONE; mtd_erase_callback(instr); REG32_VAL(PMCEU_ADDR) &= ~(SF_CLOCK_EN); return 0; }
void handle_write_partition(struct cfw_message *msg) { ll_storage_write_partition_req_msg_t * req = (ll_storage_write_partition_req_msg_t *) msg; ll_storage_write_partition_rsp_msg_t * resp = (ll_storage_write_partition_rsp_msg_t *) cfw_alloc_rsp_msg(msg, MSG_ID_LL_WRITE_PARTITION_RSP, sizeof(*resp)); flash_device_t flash; uint16_t flash_id = 0; int16_t partition_index = -1; uint32_t i = 0; uint32_t size = 0; unsigned int retlen = 0; DRIVER_API_RC ret = DRV_RC_FAIL; if ((req->write_type == WRITE_REQ) && (req->buffer == NULL)) { pr_debug(LOG_MODULE_MAIN, "LL Storage Service - Write Data: Invalid write buffer"); ret = DRV_RC_INVALID_CONFIG; goto send; } if ((req->write_type == WRITE_REQ) && (req->size == 0)) { pr_debug(LOG_MODULE_MAIN, "LL Storage Service - Write Data: Invalid write size"); ret = DRV_RC_INVALID_OPERATION; goto send; } for (i = 0; i < ll_storage_config.no_part; i++) if (ll_storage_config.partitions[i].partition_id == req->partition_id) { flash_id = ll_storage_config.partitions[i].flash_id; partition_index = i; break; } if (partition_index == -1) { pr_debug(LOG_MODULE_MAIN, "LL Storage Service - Write Data: Invalid partition ID"); ret = DRV_RC_FAIL; goto send; } flash = flash_devices[flash_id]; if ((req->write_type == WRITE_REQ) && (((ll_storage_config.partitions[partition_index].start_block * flash.block_size) + (req->st_offset + req->size)) > (ll_storage_config.partitions[partition_index].end_block * flash.block_size))) { pr_debug(LOG_MODULE_MAIN, "LL Storage Service - Write Data: Partition overflow"); ret = DRV_RC_OUT_OF_MEM; goto send; } size = req->size / sizeof (uint32_t) + !!(req->size % sizeof (uint32_t)); if (req->write_type == ERASE_REQ) { if (flash.flash_location == EMBEDDED_FLASH) { ret = soc_flash_block_erase(ll_storage_config.partitions[partition_index].start_block, (ll_storage_config.partitions[partition_index].end_block - ll_storage_config.partitions[partition_index].start_block) + 1); #ifdef CONFIG_SPI_FLASH } else {// SERIAL_FLASH ret = spi_flash_sector_erase((struct device *)&pf_sba_device_flash_spi0, ll_storage_config.partitions[partition_index].start_block, (ll_storage_config.partitions[partition_index].end_block - ll_storage_config.partitions[partition_index].start_block) + 1); #endif } } else { uint32_t address = ((ll_storage_config.partitions[partition_index].start_block * flash.block_size) + req->st_offset); if (flash.flash_location == EMBEDDED_FLASH) { ret = soc_flash_write(address, size, &retlen, req->buffer); #ifdef CONFIG_SPI_FLASH } else {// SERIAL_FLASH ret = spi_flash_write((struct device *)&pf_sba_device_flash_spi0, address, size, &retlen, req->buffer); #endif } resp->actual_size = (retlen * sizeof(uint32_t)) - (((req->size % sizeof(uint32_t))) ? (4 - (req->size % sizeof(uint32_t))):0); } send: resp->rsp_header.status = ret; resp->write_type = req->write_type; cfw_send_message(resp); }