X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fstr9xpec.c;h=c06e6d163dd707c1c9db3e259a1f54712fe0f248;hb=da8ce5f2e193b8637202d56c69b22a158a12e32a;hp=96e12596a6694bcc58e0bd59c103c5f9d3f01ffc;hpb=fe9228a32db930be297d4d3b35ffb94d6de1b9ab;p=openocd.git diff --git a/src/flash/nor/str9xpec.c b/src/flash/nor/str9xpec.c index 96e12596a6..c06e6d163d 100644 --- a/src/flash/nor/str9xpec.c +++ b/src/flash/nor/str9xpec.c @@ -24,15 +24,65 @@ #include "config.h" #endif -#include "str9xpec.h" -#include "arm7_9_common.h" +#include "imp.h" +#include + + +/* ISC commands */ + +#define ISC_IDCODE 0xFE +#define ISC_MFG_READ 0x4C +#define ISC_CONFIGURATION 0x07 +#define ISC_ENABLE 0x0C +#define ISC_DISABLE 0x0F +#define ISC_NOOP 0x10 +#define ISC_ADDRESS_SHIFT 0x11 +#define ISC_CLR_STATUS 0x13 +#define ISC_PROGRAM 0x20 +#define ISC_PROGRAM_SECURITY 0x22 +#define ISC_PROGRAM_UC 0x23 +#define ISC_ERASE 0x30 +#define ISC_READ 0x50 +#define ISC_BLANK_CHECK 0x60 + +/* ISC_DEFAULT bit definitions */ + +#define ISC_STATUS_SECURITY 0x40 +#define ISC_STATUS_INT_ERROR 0x30 +#define ISC_STATUS_MODE 0x08 +#define ISC_STATUS_BUSY 0x04 +#define ISC_STATUS_ERROR 0x03 + +/* Option bytes definitions */ + +#define STR9XPEC_OPT_CSMAPBIT 48 +#define STR9XPEC_OPT_LVDTHRESBIT 49 +#define STR9XPEC_OPT_LVDSELBIT 50 +#define STR9XPEC_OPT_LVDWARNBIT 51 +#define STR9XPEC_OPT_OTPBIT 63 + +enum str9xpec_status_codes +{ + STR9XPEC_INVALID_COMMAND = 1, + STR9XPEC_ISC_SUCCESS = 2, + STR9XPEC_ISC_DISABLED = 3, + STR9XPEC_ISC_INTFAIL = 32, +}; +struct str9xpec_flash_controller +{ + struct jtag_tap *tap; + uint32_t *sector_bits; + int chain_pos; + int isc_enable; + uint8_t options[8]; +}; static int str9xpec_erase_area(struct flash_bank *bank, int first, int last); static int str9xpec_set_address(struct flash_bank *bank, uint8_t sector); static int str9xpec_write_options(struct flash_bank *bank); -int str9xpec_set_instr(struct jtag_tap *tap, uint32_t new_instr, tap_state_t end_state) +static int str9xpec_set_instr(struct jtag_tap *tap, uint32_t new_instr, tap_state_t end_state) { if (tap == NULL) { return ERROR_TARGET_INVALID; @@ -42,15 +92,15 @@ int str9xpec_set_instr(struct jtag_tap *tap, uint32_t new_instr, tap_state_t end { struct scan_field field; - field.tap = tap; field.num_bits = tap->ir_length; - field.out_value = calloc(DIV_ROUND_UP(field.num_bits, 8), 1); - buf_set_u32(field.out_value, 0, field.num_bits, new_instr); + void * t = calloc(DIV_ROUND_UP(field.num_bits, 8), 1); + field.out_value = t; + buf_set_u32(t, 0, field.num_bits, new_instr); field.in_value = NULL; - jtag_add_ir_scan(1, &field, end_state); + jtag_add_ir_scan(tap, &field, end_state); - free(field.out_value); + free(t); } return ERROR_OK; @@ -64,13 +114,12 @@ static uint8_t str9xpec_isc_status(struct jtag_tap *tap) if (str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE) != ERROR_OK) return ISC_STATUS_ERROR; - field.tap = tap; field.num_bits = 8; field.out_value = NULL; field.in_value = &status; - jtag_add_dr_scan(1, &field, jtag_set_end_state(TAP_IDLE)); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_execute_queue(); LOG_DEBUG("status: 0x%2.2x", status); @@ -152,13 +201,12 @@ static int str9xpec_read_config(struct flash_bank *bank) /* execute ISC_CONFIGURATION command */ str9xpec_set_instr(tap, ISC_CONFIGURATION, TAP_IRPAUSE); - field.tap = tap; field.num_bits = 64; field.out_value = NULL; field.in_value = str9xpec_info->options; - jtag_add_dr_scan(1, &field, jtag_set_end_state(TAP_IDLE)); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_execute_queue(); status = str9xpec_isc_status(tap); @@ -258,7 +306,8 @@ FLASH_BANK_COMMAND_HANDLER(str9xpec_flash_bank_command) arm7_9 = armv4_5->arch_info; jtag_info = &arm7_9->jtag_info; - str9xpec_info->tap = bank->target->tap; + /* The core is the next tap after the flash controller in the chain */ + str9xpec_info->tap = jtag_tap_by_position(jtag_info->tap->abs_chain_position - 1); str9xpec_info->isc_enable = 0; str9xpec_build_block_list(bank); @@ -300,21 +349,19 @@ static int str9xpec_blank_check(struct flash_bank *bank, int first, int last) /* execute ISC_BLANK_CHECK command */ str9xpec_set_instr(tap, ISC_BLANK_CHECK, TAP_IRPAUSE); - field.tap = tap; field.num_bits = 64; field.out_value = buffer; field.in_value = NULL; - jtag_add_dr_scan(1, &field, jtag_set_end_state(TAP_IDLE)); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_add_sleep(40000); /* read blank check result */ - field.tap = tap; field.num_bits = 64; field.out_value = NULL; field.in_value = buffer; - jtag_add_dr_scan(1, &field, TAP_IRPAUSE); + jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE); jtag_execute_queue(); status = str9xpec_isc_status(tap); @@ -406,12 +453,11 @@ static int str9xpec_erase_area(struct flash_bank *bank, int first, int last) /* execute ISC_ERASE command */ str9xpec_set_instr(tap, ISC_ERASE, TAP_IRPAUSE); - field.tap = tap; field.num_bits = 64; field.out_value = buffer; field.in_value = NULL; - jtag_add_dr_scan(1, &field, jtag_set_end_state(TAP_IDLE)); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_execute_queue(); jtag_add_sleep(10); @@ -467,12 +513,11 @@ static int str9xpec_lock_device(struct flash_bank *bank) str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE); do { - field.tap = tap; field.num_bits = 8; field.out_value = NULL; field.in_value = &status; - jtag_add_dr_scan(1, &field, jtag_get_end_state()); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_execute_queue(); } while (!(status & ISC_STATUS_BUSY)); @@ -548,17 +593,17 @@ static int str9xpec_set_address(struct flash_bank *bank, uint8_t sector) /* set flash controller address */ str9xpec_set_instr(tap, ISC_ADDRESS_SHIFT, TAP_IRPAUSE); - field.tap = tap; field.num_bits = 8; field.out_value = §or; field.in_value = NULL; - jtag_add_dr_scan(1, &field, jtag_get_end_state()); + jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE); return ERROR_OK; } -static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) +static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, + uint32_t offset, uint32_t count) { struct str9xpec_flash_controller *str9xpec_info = bank->driver_priv; uint32_t dwords_remaining = (count / 8); @@ -626,18 +671,18 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off { str9xpec_set_address(bank, str9xpec_info->sector_bits[i]); - dwords_remaining = dwords_remaining < (bank->sectors[i].size/8) ? dwords_remaining : (bank->sectors[i].size/8); + dwords_remaining = dwords_remaining < (bank->sectors[i].size/8) + ? dwords_remaining : (bank->sectors[i].size/8); while (dwords_remaining > 0) { str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE); - field.tap = tap; field.num_bits = 64; field.out_value = (buffer + bytes_written); field.in_value = NULL; - jtag_add_dr_scan(1, &field, jtag_set_end_state(TAP_IDLE)); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); /* small delay before polling */ jtag_add_sleep(50); @@ -645,12 +690,11 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE); do { - field.tap = tap; field.num_bits = 8; field.out_value = NULL; field.in_value = scanbuf; - jtag_add_dr_scan(1, &field, jtag_get_end_state()); + jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE); jtag_execute_queue(); status = buf_get_u32(scanbuf, 0, 8); @@ -671,7 +715,7 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off if (bytes_remaining) { uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - int i = 0; + i = 0; while (bytes_remaining > 0) { @@ -682,12 +726,11 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE); - field.tap = tap; field.num_bits = 64; field.out_value = last_dword; field.in_value = NULL; - jtag_add_dr_scan(1, &field, jtag_set_end_state(TAP_IDLE)); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); /* small delay before polling */ jtag_add_sleep(50); @@ -695,12 +738,11 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE); do { - field.tap = tap; field.num_bits = 8; field.out_value = NULL; field.in_value = scanbuf; - jtag_add_dr_scan(1, &field, jtag_get_end_state()); + jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE); jtag_execute_queue(); status = buf_get_u32(scanbuf, 0, 8); @@ -749,12 +791,11 @@ COMMAND_HANDLER(str9xpec_handle_part_id_command) str9xpec_set_instr(tap, ISC_IDCODE, TAP_IRPAUSE); - field.tap = tap; field.num_bits = 32; field.out_value = NULL; field.in_value = buffer; - jtag_add_dr_scan(1, &field, jtag_set_end_state(TAP_IDLE)); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_execute_queue(); idcode = buf_get_u32(buffer, 0, 32); @@ -771,7 +812,7 @@ static int str9xpec_erase_check(struct flash_bank *bank) return str9xpec_blank_check(bank, 0, bank->num_sectors - 1); } -static int str9xpec_info(struct flash_bank *bank, char *buf, int buf_size) +static int get_str9xpec_info(struct flash_bank *bank, char *buf, int buf_size) { snprintf(buf, buf_size, "str9xpec flash driver info"); return ERROR_OK; @@ -866,12 +907,11 @@ static int str9xpec_write_options(struct flash_bank *bank) /* execute ISC_PROGRAM command */ str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE); - field.tap = tap; field.num_bits = 64; field.out_value = str9xpec_info->options; field.in_value = NULL; - jtag_add_dr_scan(1, &field, jtag_set_end_state(TAP_IDLE)); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); /* small delay before polling */ jtag_add_sleep(50); @@ -879,12 +919,11 @@ static int str9xpec_write_options(struct flash_bank *bank) str9xpec_set_instr(tap, ISC_NOOP, TAP_IRPAUSE); do { - field.tap = tap; field.num_bits = 8; field.out_value = NULL; field.in_value = &status; - jtag_add_dr_scan(1, &field, jtag_get_end_state()); + jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE); jtag_execute_queue(); } while (!(status & ISC_STATUS_BUSY)); @@ -914,6 +953,10 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_write_command) if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS) return ERROR_FLASH_OPERATION_FAILED; + command_print(CMD_CTX, "str9xpec write options complete.\n" + "INFO: a reset or power cycle is required " + "for the new settings to take effect."); + return ERROR_OK; } @@ -1076,6 +1119,10 @@ COMMAND_HANDLER(str9xpec_handle_flash_unlock_command) if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS) return ERROR_FLASH_OPERATION_FAILED; + command_print(CMD_CTX, "str9xpec unlocked.\n" + "INFO: a reset or power cycle is required " + "for the new settings to take effect."); + return ERROR_OK; } @@ -1232,6 +1279,7 @@ static const struct command_registration str9xpec_config_command_handlers[] = { }, COMMAND_REGISTRATION_DONE }; + static const struct command_registration str9xpec_command_handlers[] = { { .name = "str9xpec", @@ -1243,15 +1291,16 @@ static const struct command_registration str9xpec_command_handlers[] = { }; struct flash_driver str9xpec_flash = { - .name = "str9xpec", - .commands = str9xpec_command_handlers, - .flash_bank_command = &str9xpec_flash_bank_command, - .erase = &str9xpec_erase, - .protect = &str9xpec_protect, - .write = &str9xpec_write, - .probe = &str9xpec_probe, - .auto_probe = &str9xpec_probe, - .erase_check = &str9xpec_erase_check, - .protect_check = &str9xpec_protect_check, - .info = &str9xpec_info, - }; + .name = "str9xpec", + .commands = str9xpec_command_handlers, + .flash_bank_command = str9xpec_flash_bank_command, + .erase = str9xpec_erase, + .protect = str9xpec_protect, + .write = str9xpec_write, + .read = default_flash_read, + .probe = str9xpec_probe, + .auto_probe = str9xpec_probe, + .erase_check = str9xpec_erase_check, + .protect_check = str9xpec_protect_check, + .info = get_str9xpec_info, +};