X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fcfi.c;h=aa4540af553c91bd8dc65927ba7a8ef0a223a7a1;hb=bbc8f4e6cec361a34028dad4b5000c136f4f48b2;hp=325dce905e98440526d95160d4322b1b0de4c70f;hpb=c9e58238c3b1ae181a7d54bc5255ef98771493c2;p=openocd.git diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c index 325dce905e..aa4540af55 100644 --- a/src/flash/nor/cfi.c +++ b/src/flash/nor/cfi.c @@ -3,6 +3,7 @@ * Dominic.Rath@gmx.de * * Copyright (C) 2009 Michael Schwingen * * michael@schwingen.org * + * Copyright (C) 2010 Øyvind Harboe * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -103,7 +104,6 @@ static __inline__ uint32_t flash_address(struct flash_bank *bank, int sector, ui } 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) @@ -231,6 +231,35 @@ static uint32_t cfi_query_u32(struct flash_bank *bank, int sector, uint32_t offs 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; @@ -334,11 +363,7 @@ static int cfi_read_intel_pri_ext(struct flash_bank *bank) 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; } @@ -598,12 +623,8 @@ FLASH_BANK_COMMAND_HANDLER(cfi_flash_bank_command) return ERROR_FLASH_BANK_INVALID; } - uint16_t chip_width, bus_width; - COMMAND_PARSE_NUMBER(u16, CMD_ARGV[3], chip_width); - COMMAND_PARSE_NUMBER(u16, CMD_ARGV[4], bus_width); - - if ((chip_width > CFI_MAX_CHIP_WIDTH) - || (bus_width > CFI_MAX_BUS_WIDTH)) + if ((bank->chip_width > CFI_MAX_CHIP_WIDTH) + || (bank->bus_width > CFI_MAX_BUS_WIDTH)) { LOG_ERROR("chip and bus width have to specified in bytes"); return ERROR_FLASH_BANK_INVALID; @@ -855,6 +876,17 @@ static int cfi_intel_protect(struct flash_bank *bank, int set, int first, int la */ 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) @@ -891,6 +923,7 @@ static int cfi_protect(struct flash_bank *bank, int set, int first, int last) if ((first < 0) || (last < first) || (last >= bank->num_sectors)) { + LOG_ERROR("Invalid sector range"); return ERROR_FLASH_SECTOR_INVALID; } @@ -901,14 +934,12 @@ static int cfi_protect(struct flash_bank *bank, int set, int first, int last) { case 1: case 3: - cfi_intel_protect(bank, set, first, last); + return cfi_intel_protect(bank, set, first, last); break; default: LOG_ERROR("protect: cfi primary command set %i unsupported", cfi_info->pri_id); - break; + return ERROR_FAIL; } - - return ERROR_OK; } /* FIXME Replace this by a simple memcpy() - still unsure about sideeffects */ @@ -1120,7 +1151,7 @@ static int cfi_intel_write_block(struct flash_bank *bank, uint8_t *buffer, uint3 /* Get a workspace buffer for the data to flash starting with 32k size. Half size until buffer would be smaller 256 Bytem then fail back */ /* FIXME Why 256 bytes, why not 32 bytes (smallest flash write page */ - while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) + while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; if (buffer_size <= 256) @@ -1145,7 +1176,7 @@ static int cfi_intel_write_block(struct flash_bank *bank, uint8_t *buffer, uint3 busy_pattern_val = cfi_command_val(bank, 0x80); error_pattern_val = cfi_command_val(bank, 0x7e); - LOG_INFO("Using target buffer at 0x%08" PRIx32 " and of size 0x%04" PRIx32, source->address, buffer_size); + LOG_DEBUG("Using target buffer at 0x%08" PRIx32 " and of size 0x%04" PRIx32, source->address, buffer_size); /* Programming main loop */ while (count > 0) @@ -1166,7 +1197,7 @@ static int cfi_intel_write_block(struct flash_bank *bank, uint8_t *buffer, uint3 buf_set_u32(reg_params[5].value, 0, 32, busy_pattern_val); buf_set_u32(reg_params[6].value, 0, 32, error_pattern_val); - LOG_INFO("Write 0x%04" PRIx32 " bytes to flash at 0x%08" PRIx32 , thisrun_count, address); + LOG_DEBUG("Write 0x%04" PRIx32 " bytes to flash at 0x%08" PRIx32 , thisrun_count, address); /* Execute algorithm, assume breakpoint for last instruction */ retval = target_run_algorithm(target, 0, NULL, 7, reg_params, @@ -1448,7 +1479,7 @@ static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer, ui } /* the following code still assumes target code is fixed 24*4 bytes */ - while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) + while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { buffer_size /= 2; if (buffer_size <= 256) @@ -1970,11 +2001,7 @@ static int cfi_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, } /* 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; } @@ -2008,11 +2035,7 @@ static int cfi_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, } /* 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) @@ -2076,11 +2099,7 @@ static int cfi_query_string(struct flash_bank *bank, int address) 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; } @@ -2161,11 +2180,7 @@ static int cfi_probe(struct flash_bank *bank) 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; } @@ -2282,11 +2297,7 @@ static int cfi_probe(struct flash_bank *bank) /* 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; } @@ -2370,7 +2381,6 @@ static int cfi_auto_probe(struct flash_bank *bank) return cfi_probe(bank); } - static int cfi_intel_protect_check(struct flash_bank *bank) { int retval;