/* Write, assuming that someone has kindly erased the appropriate * sector(s). * Note: "block_offset" is the base of the current erase block. * "data_offset" is the absolute address (from the 0-base of this * device's memory) of the beginning of the write-destination. * This device has no need for "block_offset", but it's included for * function type compatibility. */ int alt_epcs_flash_write_block(alt_flash_dev* flash_info, int block_offset, int data_offset, const void* data, int length) { int ret_code; alt_flash_epcs_dev *f = (alt_flash_epcs_dev*)flash_info; int buffer_offset = 0; int length_of_current_write; ret_code = alt_epcs_test_address(flash_info, data_offset); if (ret_code >= 0) { /* "Block" writes must be broken up into the page writes that * the device understands. Partial page writes are allowed. */ while (length) { int next_page_start = (data_offset + f->page_size) & ~(f->page_size - 1); length_of_current_write = MIN(length, next_page_start - data_offset); epcs_write_buffer(f->register_base, data_offset, &((const alt_u8*)data)[buffer_offset], length_of_current_write); length -= length_of_current_write; buffer_offset += length_of_current_write; data_offset = next_page_start; } } return ret_code; }
/* * * Erase the selected erase block ("sector erase", from the POV * of the EPCS data sheet). */ int alt_epcs_flash_erase_block(alt_flash_dev* flash_info, int block_offset) { int ret_code = 0; alt_flash_epcs_dev *f = (alt_flash_epcs_dev*)flash_info; ret_code = alt_epcs_test_address(flash_info, block_offset); if (ret_code >= 0) { /* Send the Sector Erase command, whose 3 address bytes are anywhere * within the chosen sector. */ epcs_sector_erase(f->register_base, block_offset, f->four_bytes_mode); } return ret_code; }
/* * * Erase the selected erase block ("sector erase", from the POV * of the EPCS data sheet). */ int alt_epcs_flash_erase_block(alt_flash_dev* flash_info, int block_offset) { int ret_code = 0; alt_flash_epcs_dev *f = (alt_flash_epcs_dev*)flash_info; ret_code = alt_epcs_test_address(flash_info, block_offset); if (ret_code >= 0) { /* Execute a WREN instruction */ epcs_write_enable(f->register_base); /* Send the Sector Erase command, whose 3 address bytes are anywhere * within the chosen sector. */ epcs_sector_erase(f->register_base, block_offset); } return ret_code; }
/* * If you try to read beyond the end of the memory, you'll wrap around * to the beginning. Reads that start beyond the end of the memory are * flagged as errors with EIO (is there a better error code?). */ int alt_epcs_flash_read(alt_flash_dev* flash_info, int offset, void* dest_addr, int length) { int ret_code = 0; alt_flash_epcs_dev *f = (alt_flash_epcs_dev*)flash_info; ret_code = alt_epcs_test_address(flash_info, offset); if (ret_code >= 0) { ret_code = epcs_read_buffer(f->register_base, offset, dest_addr, length); /* epcs_read_buffer returns the number of buffers read, but * alt_epcs_flash_read returns 0 on success, <0 on failure. */ if (ret_code == length) { ret_code = 0; } } return ret_code; }