X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fstr9xpec.c;h=fc2ed3590f4dd772e910e2cc5913c1c636f08dfc;hp=3796a4b19060976c289cfbcfdb74f51a82bfda35;hb=2a34cc8eb6a8431ecebad1279d19ce919978a778;hpb=e018c7c1d29e8dabb9b4a90bb9eb3574eb1668bb diff --git a/src/flash/nor/str9xpec.c b/src/flash/nor/str9xpec.c index 3796a4b190..fc2ed3590f 100644 --- a/src/flash/nor/str9xpec.c +++ b/src/flash/nor/str9xpec.c @@ -25,15 +25,64 @@ #endif #include "imp.h" -#include "str9xpec.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; @@ -44,13 +93,14 @@ int str9xpec_set_instr(struct jtag_tap *tap, uint32_t new_instr, tap_state_t end struct scan_field field; 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(tap, 1, &field, end_state); + jtag_add_ir_scan(tap, &field, end_state); - free(field.out_value); + free(t); } return ERROR_OK; @@ -69,7 +119,7 @@ static uint8_t str9xpec_isc_status(struct jtag_tap *tap) field.in_value = &status; - jtag_add_dr_scan(tap, 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); @@ -156,7 +206,7 @@ static int str9xpec_read_config(struct flash_bank *bank) field.in_value = str9xpec_info->options; - jtag_add_dr_scan(tap, 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); @@ -242,8 +292,7 @@ FLASH_BANK_COMMAND_HANDLER(str9xpec_flash_bank_command) if (CMD_ARGC < 6) { - LOG_WARNING("incomplete flash_bank str9x configuration"); - return ERROR_FLASH_BANK_INVALID; + return ERROR_COMMAND_SYNTAX_ERROR; } str9xpec_info = malloc(sizeof(struct str9xpec_flash_controller)); @@ -256,7 +305,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); @@ -302,7 +352,7 @@ static int str9xpec_blank_check(struct flash_bank *bank, int first, int last) field.out_value = buffer; field.in_value = NULL; - jtag_add_dr_scan(tap, 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 */ @@ -406,7 +456,7 @@ static int str9xpec_erase_area(struct flash_bank *bank, int first, int last) field.out_value = buffer; field.in_value = NULL; - jtag_add_dr_scan(tap, 1, &field, jtag_set_end_state(TAP_IDLE)); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_execute_queue(); jtag_add_sleep(10); @@ -466,7 +516,7 @@ static int str9xpec_lock_device(struct flash_bank *bank) field.out_value = NULL; field.in_value = &status; - jtag_add_dr_scan(tap, 1, &field, jtag_get_end_state()); + jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); jtag_execute_queue(); } while (!(status & ISC_STATUS_BUSY)); @@ -546,12 +596,13 @@ static int str9xpec_set_address(struct flash_bank *bank, uint8_t sector) field.out_value = §or; field.in_value = NULL; - jtag_add_dr_scan(tap, 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); @@ -619,7 +670,8 @@ 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) { @@ -629,7 +681,7 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off field.out_value = (buffer + bytes_written); field.in_value = NULL; - jtag_add_dr_scan(tap, 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); @@ -641,7 +693,7 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off field.out_value = NULL; field.in_value = scanbuf; - jtag_add_dr_scan(tap, 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); @@ -662,14 +714,9 @@ 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; - while (bytes_remaining > 0) - { - last_dword[i++] = *(buffer + bytes_written); - bytes_remaining--; - bytes_written++; - } + /* copy the last remaining bytes into the write buffer */ + memcpy(last_dword, buffer+bytes_written, bytes_remaining); str9xpec_set_instr(tap, ISC_PROGRAM, TAP_IRPAUSE); @@ -677,7 +724,7 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off field.out_value = last_dword; field.in_value = NULL; - jtag_add_dr_scan(tap, 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); @@ -689,7 +736,7 @@ static int str9xpec_write(struct flash_bank *bank, uint8_t *buffer, uint32_t off field.out_value = NULL; field.in_value = scanbuf; - jtag_add_dr_scan(tap, 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); @@ -742,7 +789,7 @@ COMMAND_HANDLER(str9xpec_handle_part_id_command) field.out_value = NULL; field.in_value = buffer; - jtag_add_dr_scan(tap, 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); @@ -759,7 +806,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; @@ -772,8 +819,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_read_command) if (CMD_ARGC < 1) { - command_print(CMD_CTX, "str9xpec options_read "); - return ERROR_OK; + return ERROR_COMMAND_SYNTAX_ERROR; } struct flash_bank *bank; @@ -858,7 +904,7 @@ static int str9xpec_write_options(struct flash_bank *bank) field.out_value = str9xpec_info->options; field.in_value = NULL; - jtag_add_dr_scan(tap, 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); @@ -870,7 +916,7 @@ static int str9xpec_write_options(struct flash_bank *bank) field.out_value = NULL; field.in_value = &status; - jtag_add_dr_scan(tap, 1, &field, jtag_get_end_state()); + jtag_add_dr_scan(tap, 1, &field, TAP_IRPAUSE); jtag_execute_queue(); } while (!(status & ISC_STATUS_BUSY)); @@ -886,8 +932,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_write_command) if (CMD_ARGC < 1) { - command_print(CMD_CTX, "str9xpec options_write "); - return ERROR_OK; + return ERROR_COMMAND_SYNTAX_ERROR; } struct flash_bank *bank; @@ -913,8 +958,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_cmap_command) if (CMD_ARGC < 2) { - command_print(CMD_CTX, "str9xpec options_cmap "); - return ERROR_OK; + return ERROR_COMMAND_SYNTAX_ERROR; } struct flash_bank *bank; @@ -942,8 +986,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdthd_command) if (CMD_ARGC < 2) { - command_print(CMD_CTX, "str9xpec options_lvdthd <2.4v | 2.7v>"); - return ERROR_OK; + return ERROR_COMMAND_SYNTAX_ERROR; } struct flash_bank *bank; @@ -971,8 +1014,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdsel_command) if (CMD_ARGC < 2) { - command_print(CMD_CTX, "str9xpec options_lvdsel "); - return ERROR_OK; + return ERROR_COMMAND_SYNTAX_ERROR; } struct flash_bank *bank; @@ -1000,8 +1042,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_lvdwarn_command) if (CMD_ARGC < 2) { - command_print(CMD_CTX, "str9xpec options_lvdwarn "); - return ERROR_OK; + return ERROR_COMMAND_SYNTAX_ERROR; } struct flash_bank *bank; @@ -1029,8 +1070,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_lock_command) if (CMD_ARGC < 1) { - command_print(CMD_CTX, "str9xpec lock "); - return ERROR_OK; + return ERROR_COMMAND_SYNTAX_ERROR; } struct flash_bank *bank; @@ -1052,8 +1092,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_unlock_command) if (CMD_ARGC < 1) { - command_print(CMD_CTX, "str9xpec unlock "); - return ERROR_OK; + return ERROR_COMMAND_SYNTAX_ERROR; } struct flash_bank *bank; @@ -1082,8 +1121,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_enable_turbo_command) if (CMD_ARGC < 1) { - command_print(CMD_CTX, "str9xpec enable_turbo "); - return ERROR_OK; + return ERROR_COMMAND_SYNTAX_ERROR; } struct flash_bank *bank; @@ -1129,8 +1167,7 @@ COMMAND_HANDLER(str9xpec_handle_flash_disable_turbo_command) if (CMD_ARGC < 1) { - command_print(CMD_CTX, "str9xpec disable_turbo "); - return ERROR_OK; + return ERROR_COMMAND_SYNTAX_ERROR; } struct flash_bank *bank; @@ -1160,60 +1197,70 @@ COMMAND_HANDLER(str9xpec_handle_flash_disable_turbo_command) static const struct command_registration str9xpec_config_command_handlers[] = { { .name = "enable_turbo", + .usage = "", .handler = str9xpec_handle_flash_enable_turbo_command, .mode = COMMAND_EXEC, .help = "enable str9xpec turbo mode", }, { .name = "disable_turbo", + .usage = "", .handler = str9xpec_handle_flash_disable_turbo_command, .mode = COMMAND_EXEC, .help = "disable str9xpec turbo mode", }, { .name = "options_cmap", + .usage = " ", .handler = str9xpec_handle_flash_options_cmap_command, .mode = COMMAND_EXEC, .help = "configure str9xpec boot sector", }, { .name = "options_lvdthd", + .usage = " <2.4v | 2.7v>", .handler = str9xpec_handle_flash_options_lvdthd_command, .mode = COMMAND_EXEC, .help = "configure str9xpec lvd threshold", }, { .name = "options_lvdsel", + .usage = " ", .handler = str9xpec_handle_flash_options_lvdsel_command, .mode = COMMAND_EXEC, .help = "configure str9xpec lvd selection", }, { .name = "options_lvdwarn", + .usage = " ", .handler = str9xpec_handle_flash_options_lvdwarn_command, .mode = COMMAND_EXEC, .help = "configure str9xpec lvd warning", }, { .name = "options_read", + .usage = "", .handler = str9xpec_handle_flash_options_read_command, .mode = COMMAND_EXEC, .help = "read str9xpec options", }, { .name = "options_write", + .usage = "", .handler = str9xpec_handle_flash_options_write_command, .mode = COMMAND_EXEC, .help = "write str9xpec options", }, { .name = "lock", + .usage = "", .handler = str9xpec_handle_flash_lock_command, .mode = COMMAND_EXEC, .help = "lock str9xpec device", }, { .name = "unlock", + .usage = "", .handler = str9xpec_handle_flash_unlock_command, .mode = COMMAND_EXEC, .help = "unlock str9xpec device", @@ -1226,11 +1273,13 @@ static const struct command_registration str9xpec_config_command_handlers[] = { }, COMMAND_REGISTRATION_DONE }; + static const struct command_registration str9xpec_command_handlers[] = { { .name = "str9xpec", .mode = COMMAND_ANY, .help = "str9xpec flash command group", + .usage = "", .chain = str9xpec_config_command_handlers, }, COMMAND_REGISTRATION_DONE @@ -1243,9 +1292,10 @@ struct flash_driver str9xpec_flash = { .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 = str9xpec_info, + .info = get_str9xpec_info, };