{CFI_MFR_SST, 0x00D7, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
{CFI_MFR_SST, 0x2780, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
{CFI_MFR_ATMEL, 0x00C8, cfi_fixup_atmel_reversed_erase_regions, NULL},
+ {CFI_MFR_FUJITSU, 0x22ea, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]},
{CFI_MFR_FUJITSU, 0x226b, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
{CFI_MFR_AMIC, 0xb31a, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]},
{CFI_MFR_MX, 0x225b, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]},
}
return bank->base + bank->sectors[sector].offset + offset * bank->bus_width;
}
-
}
static void cfi_command(struct flash_bank *bank, uint8_t cmd, uint8_t *cmd_buf)
data[(3 * bank->bus_width) - 1] << 16 | data[(4 * bank->bus_width) - 1] << 24;
}
+static int cfi_reset(struct flash_bank *bank)
+{
+ struct cfi_flash_bank *cfi_info = bank->driver_priv;
+ int retval = ERROR_OK;
+
+ if ((retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0))) != ERROR_OK)
+ {
+ return retval;
+ }
+
+ if ((retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0))) != ERROR_OK)
+ {
+ return retval;
+ }
+
+ if (cfi_info->manufacturer == 0x20 &&
+ (cfi_info->device_id == 0x227E || cfi_info->device_id == 0x7E))
+ {
+ /* Numonix M29W128G is cmd 0xFF intolerant - causes internal undefined state
+ * so we send an extra 0xF0 reset to fix the bug */
+ if ((retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x00))) != ERROR_OK)
+ {
+ return retval;
+ }
+ }
+
+ return retval;
+}
+
static void cfi_intel_clear_status_register(struct flash_bank *bank)
{
struct target *target = bank->target;
if ((pri_ext->pri[0] != 'P') || (pri_ext->pri[1] != 'R') || (pri_ext->pri[2] != 'I'))
{
- if ((retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0))) != ERROR_OK)
- {
- return retval;
- }
- if ((retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0))) != ERROR_OK)
+ if ((retval = cfi_reset(bank)) != ERROR_OK)
{
return retval;
}
return ERROR_FLASH_BANK_INVALID;
}
+ /* both widths must:
+ * - not exceed max value;
+ * - not be null;
+ * - be equal to a power of 2.
+ * bus must be wide enought to hold one chip */
if ((bank->chip_width > CFI_MAX_CHIP_WIDTH)
- || (bank->bus_width > CFI_MAX_BUS_WIDTH))
+ || (bank->bus_width > CFI_MAX_BUS_WIDTH)
+ || (bank->chip_width == 0)
+ || (bank->bus_width == 0)
+ || (bank->chip_width & (bank->chip_width - 1))
+ || (bank->bus_width & (bank->bus_width - 1))
+ || (bank->chip_width > bank->bus_width))
{
LOG_ERROR("chip and bus width have to specified in bytes");
return ERROR_FLASH_BANK_INVALID;
*/
if ((!set) && (!(pri_ext->feature_support & 0x20)))
{
+ /* FIX!!! this code path is broken!!!
+ *
+ * The correct approach is:
+ *
+ * 1. read out current protection status
+ *
+ * 2. override read out protection status w/unprotected.
+ *
+ * 3. re-protect what should be protected.
+ *
+ */
for (i = 0; i < bank->num_sectors; i++)
{
if (bank->sectors[i].is_protected == 1)
struct target *target = bank->target;
/* Calculate buffer size and boundary mask */
+ /* buffersize is (buffer size per chip) * (number of chips) */
+ /* bufferwsize is buffersize in words */
uint32_t buffersize = (1UL << cfi_info->max_buf_write_size) * (bank->bus_width / bank->chip_width);
uint32_t buffermask = buffersize-1;
- uint32_t bufferwsize;
+ uint32_t bufferwsize = buffersize / bank->bus_width;
/* Check for valid range */
if (address & buffermask)
bank->base, address, cfi_info->max_buf_write_size);
return ERROR_FLASH_OPERATION_FAILED;
}
- switch (bank->chip_width)
- {
- case 4 : bufferwsize = buffersize / 4; break;
- case 2 : bufferwsize = buffersize / 2; break;
- case 1 : bufferwsize = buffersize; break;
- default:
- LOG_ERROR("Unsupported chip width %d", bank->chip_width);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- bufferwsize/=(bank->bus_width / bank->chip_width);
-
/* Check for valid size */
if (wordcount > bufferwsize)
struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext;
/* Calculate buffer size and boundary mask */
+ /* buffersize is (buffer size per chip) * (number of chips) */
+ /* bufferwsize is buffersize in words */
uint32_t buffersize = (1UL << cfi_info->max_buf_write_size) * (bank->bus_width / bank->chip_width);
uint32_t buffermask = buffersize-1;
- uint32_t bufferwsize;
+ uint32_t bufferwsize = buffersize / bank->bus_width;
/* Check for valid range */
if (address & buffermask)
LOG_ERROR("Write address at base 0x%" PRIx32 ", address %" PRIx32 " not aligned to 2^%d boundary", bank->base, address, cfi_info->max_buf_write_size);
return ERROR_FLASH_OPERATION_FAILED;
}
- switch (bank->chip_width)
- {
- case 4 : bufferwsize = buffersize / 4; break;
- case 2 : bufferwsize = buffersize / 2; break;
- case 1 : bufferwsize = buffersize; break;
- default:
- LOG_ERROR("Unsupported chip width %d", bank->chip_width);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- bufferwsize/=(bank->bus_width / bank->chip_width);
/* Check for valid size */
if (wordcount > bufferwsize)
for (i = 0; i < align; ++i, ++copy_p)
{
uint8_t byte;
+ /* FIXME: access flash at bus_width size */
if ((retval = target_read_memory(target, copy_p, 1, 1, &byte)) != ERROR_OK)
{
return retval;
for (; (count == 0) && (i < bank->bus_width); ++i, ++copy_p)
{
uint8_t byte;
+ /* FIXME: access flash at bus_width size */
if ((retval = target_read_memory(target, copy_p, 1, 1, &byte)) != ERROR_OK)
{
return retval;
{
if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
{
- //adjust buffersize for chip width
+ /* Calculate buffer size and boundary mask */
+ /* buffersize is (buffer size per chip) * (number of chips) */
+ /* bufferwsize is buffersize in words */
uint32_t buffersize = (1UL << cfi_info->max_buf_write_size) * (bank->bus_width / bank->chip_width);
uint32_t buffermask = buffersize-1;
- uint32_t bufferwsize;
-
- switch (bank->chip_width)
- {
- case 4 : bufferwsize = buffersize / 4; break;
- case 2 : bufferwsize = buffersize / 2; break;
- case 1 : bufferwsize = buffersize; break;
- default:
- LOG_ERROR("Unsupported chip width %d", bank->chip_width);
- return ERROR_FLASH_OPERATION_FAILED;
- }
-
- bufferwsize/=(bank->bus_width / bank->chip_width);
+ uint32_t bufferwsize = buffersize / bank->bus_width;
/* fall back to memory writes */
while (count >= (uint32_t)bank->bus_width)
}
/* return to read array mode, so we can read from flash again for padding */
- if ((retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0))) != ERROR_OK)
- {
- return retval;
- }
- if ((retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0))) != ERROR_OK)
+ if ((retval = cfi_reset(bank)) != ERROR_OK)
{
return retval;
}
for (; i < bank->bus_width; ++i, ++copy_p)
{
uint8_t byte;
+ /* FIXME: access flash at bus_width size */
if ((retval = target_read_memory(target, copy_p, 1, 1, &byte)) != ERROR_OK)
{
return retval;
}
/* return to read array mode */
- if ((retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0))) != ERROR_OK)
- {
- return retval;
- }
- return cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0));
+ return cfi_reset(bank);
}
static void cfi_fixup_atmel_reversed_erase_regions(struct flash_bank *bank, void *param)
if ((cfi_info->qry[0] != 'Q') || (cfi_info->qry[1] != 'R') || (cfi_info->qry[2] != 'Y'))
{
- if ((retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0))) != ERROR_OK)
- {
- return retval;
- }
- if ((retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0))) != ERROR_OK)
+ if ((retval = cfi_reset(bank)) != ERROR_OK)
{
return retval;
}
uint32_t unlock1 = 0x555;
uint32_t unlock2 = 0x2aa;
int retval;
+ uint8_t value_buf0[CFI_MAX_BUS_WIDTH], value_buf1[CFI_MAX_BUS_WIDTH];
if (bank->target->state != TARGET_HALTED)
{
return retval;
}
- if (bank->chip_width == 1)
+ if ((retval = target_read_memory(target, flash_address(bank, 0, 0x00), bank->bus_width, 1, value_buf0)) != ERROR_OK)
{
- uint8_t manufacturer, device_id;
- if ((retval = target_read_u8(target, flash_address(bank, 0, 0x00), &manufacturer)) != ERROR_OK)
- {
- return retval;
- }
- if ((retval = target_read_u8(target, flash_address(bank, 0, 0x01), &device_id)) != ERROR_OK)
- {
- return retval;
- }
- cfi_info->manufacturer = manufacturer;
- cfi_info->device_id = device_id;
+ return retval;
}
- else if (bank->chip_width == 2)
+ if ((retval = target_read_memory(target, flash_address(bank, 0, 0x01), bank->bus_width, 1, value_buf1)) != ERROR_OK)
{
- if ((retval = target_read_u16(target, flash_address(bank, 0, 0x00), &cfi_info->manufacturer)) != ERROR_OK)
- {
- return retval;
- }
- if ((retval = target_read_u16(target, flash_address(bank, 0, 0x01), &cfi_info->device_id)) != ERROR_OK)
- {
- return retval;
- }
+ return retval;
+ }
+ switch (bank->chip_width) {
+ case 1:
+ cfi_info->manufacturer = *value_buf0;
+ cfi_info->device_id = *value_buf1;
+ break;
+ case 2:
+ cfi_info->manufacturer = target_buffer_get_u16(target, value_buf0);
+ cfi_info->device_id = target_buffer_get_u16(target, value_buf1);
+ break;
+ case 4:
+ cfi_info->manufacturer = target_buffer_get_u32(target, value_buf0);
+ cfi_info->device_id = target_buffer_get_u32(target, value_buf1);
+ break;
+ default:
+ LOG_ERROR("Unsupported bank chipwidth %d, can't probe memory", bank->chip_width);
+ return ERROR_FLASH_OPERATION_FAILED;
}
LOG_INFO("Flash Manufacturer/Device: 0x%04x 0x%04x", cfi_info->manufacturer, cfi_info->device_id);
/* switch back to read array mode */
- if ((retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x00))) != ERROR_OK)
- {
- return retval;
- }
- if ((retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x00))) != ERROR_OK)
+ if ((retval = cfi_reset(bank)) != ERROR_OK)
{
return retval;
}
/* return to read array mode
* we use both reset commands, as some Intel flashes fail to recognize the 0xF0 command
*/
- if ((retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0))) != ERROR_OK)
- {
- return retval;
- }
- if ((retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0))) != ERROR_OK)
+ if ((retval = cfi_reset(bank)) != ERROR_OK)
{
return retval;
}
return cfi_probe(bank);
}
-
static int cfi_intel_protect_check(struct flash_bank *bank)
{
int retval;
.write = cfi_write,
.probe = cfi_probe,
.auto_probe = cfi_auto_probe,
+ /* FIXME: access flash at bus_width size */
.erase_check = default_flash_blank_check,
.protect_check = cfi_protect_check,
.info = cfi_info,