* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
+* You should have received a copy of the GNU General Public License *
+* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
/* Flash controller configuration values */
#define FLASH_ID_XMC4500 0xA2
-#define FLASH_ID_XMC4800 0x92
+#define FLASH_ID_XMC4300_XMC4700_4800 0x92
#define FLASH_ID_XMC4100_4200 0x9C
#define FLASH_ID_XMC4400 0x9F
/* At this point, we know which flash controller ID we're
* talking to and simply need to fill out the bank structure accordingly */
- LOG_DEBUG("%d sectors", bank->num_sectors);
+ LOG_DEBUG("%u sectors", bank->num_sectors);
switch (bank->num_sectors) {
case 8:
capacity = sector_capacity_16;
break;
default:
- LOG_ERROR("Unexpected number of sectors, %d\n",
+ LOG_ERROR("Unexpected number of sectors, %u\n",
bank->num_sectors);
return ERROR_FAIL;
}
uint32_t total_offset = 0;
bank->sectors = calloc(bank->num_sectors,
sizeof(struct flash_sector));
- for (int i = 0; i < bank->num_sectors; i++) {
+ for (unsigned int i = 0; i < bank->num_sectors; i++) {
bank->sectors[i].size = capacity[i] * 1024;
bank->sectors[i].offset = total_offset;
bank->sectors[i].is_erased = -1;
}
/* This part doesn't follow the typical standard of 0xff
- * being the default padding value.*/
- bank->default_padded_value = 0x00;
+ * being the erased value.*/
+ bank->default_padded_value = bank->erased_value = 0x00;
return ERROR_OK;
}
bank->num_sectors = 12;
LOG_DEBUG("XMC4xxx: XMC4500 detected.");
break;
- case FLASH_ID_XMC4800:
+ case FLASH_ID_XMC4300_XMC4700_4800:
bank->num_sectors = 16;
- LOG_DEBUG("XMC4xxx: XMC4800 detected.");
+ LOG_DEBUG("XMC4xxx: XMC4700/4800 detected.");
break;
default:
LOG_ERROR("XMC4xxx: Unexpected flash ID. got %02" PRIx8,
}
static int xmc4xxx_get_sector_start_addr(struct flash_bank *bank,
- int sector, uint32_t *ret_addr)
+ unsigned int sector, uint32_t *ret_addr)
{
/* Make sure we understand this sector */
if (sector > bank->num_sectors)
return res;
}
-static int xmc4xxx_erase(struct flash_bank *bank, int first, int last)
+static int xmc4xxx_erase(struct flash_bank *bank, unsigned int first,
+ unsigned int last)
{
struct xmc4xxx_flash_bank *fb = bank->driver_priv;
int res;
uint32_t tmp_addr;
/* Loop through the sectors and erase each one */
- for (int i = first; i <= last; i++) {
+ for (unsigned int i = first; i <= last; i++) {
res = xmc4xxx_get_sector_start_addr(bank, i, &tmp_addr);
if (res != ERROR_OK) {
- LOG_ERROR("Invalid sector %d", i);
+ LOG_ERROR("Invalid sector %u", i);
return res;
}
- LOG_DEBUG("Erasing sector %d @ 0x%08"PRIx32, i, tmp_addr);
+ LOG_DEBUG("Erasing sector %u @ 0x%08"PRIx32, i, tmp_addr);
res = xmc4xxx_erase_sector(bank, tmp_addr, false);
if (res != ERROR_OK) {
return res;
}
-/* The logical erase value of an xmc4xxx memory cell is 0x00,
- * therefore, we cannot use the built in flash blank check and must
- * implement our own */
-
-/** Checks whether a memory region is zeroed. */
-int xmc4xxx_blank_check_memory(struct target *target,
- uint32_t address, uint32_t count, uint32_t *blank)
-{
- struct working_area *erase_check_algorithm;
- struct reg_param reg_params[3];
- struct armv7m_algorithm armv7m_info;
- int retval;
-
- /* see contrib/loaders/erase_check/armv7m_0_erase_check.s for src */
-
- static const uint8_t erase_check_code[] = {
- /* loop: */
- 0x03, 0x78, /* ldrb r3, [r0] */
- 0x01, 0x30, /* adds r0, #1 */
- 0x1A, 0x43, /* orrs r2, r2, r3 */
- 0x01, 0x39, /* subs r1, r1, #1 */
- 0xFA, 0xD1, /* bne loop */
- 0x00, 0xBE /* bkpt #0 */
- };
-
- /* make sure we have a working area */
- if (target_alloc_working_area(target, sizeof(erase_check_code),
- &erase_check_algorithm) != ERROR_OK)
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-
- retval = target_write_buffer(target, erase_check_algorithm->address,
- sizeof(erase_check_code), (uint8_t *)erase_check_code);
- if (retval != ERROR_OK)
- return retval;
-
- armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
- armv7m_info.core_mode = ARM_MODE_THREAD;
-
- init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
- buf_set_u32(reg_params[0].value, 0, 32, address);
-
- init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
- buf_set_u32(reg_params[1].value, 0, 32, count);
-
- init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT);
- buf_set_u32(reg_params[2].value, 0, 32, 0x00);
-
- retval = target_run_algorithm(target,
- 0,
- NULL,
- 3,
- reg_params,
- erase_check_algorithm->address,
- erase_check_algorithm->address + (sizeof(erase_check_code) - 2),
- 10000,
- &armv7m_info);
-
- if (retval == ERROR_OK)
- *blank = buf_get_u32(reg_params[2].value, 0, 32);
-
- destroy_reg_param(®_params[0]);
- destroy_reg_param(®_params[1]);
- destroy_reg_param(®_params[2]);
-
- target_free_working_area(target, erase_check_algorithm);
-
- return retval;
-}
-
-static int xmc4xxx_flash_blank_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- int i;
- int retval;
- uint32_t blank;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- for (i = 0; i < bank->num_sectors; i++) {
- uint32_t address = bank->base + bank->sectors[i].offset;
- uint32_t size = bank->sectors[i].size;
-
- LOG_DEBUG("Erase checking 0x%08"PRIx32, address);
- retval = xmc4xxx_blank_check_memory(target, address, size, &blank);
-
- if (retval != ERROR_OK)
- break;
-
- if (blank == 0x00)
- bank->sectors[i].is_erased = 1;
- else
- bank->sectors[i].is_erased = 0;
- }
-
- return ERROR_OK;
-}
-
static int xmc4xxx_write_page(struct flash_bank *bank, const uint8_t *pg_buf,
uint32_t offset, bool user_config)
{
memcpy(&tmp_buf[start_pad], buffer, remaining);
if (end_pad) {
- LOG_INFO("Padding end of page @%08"PRIx32" by %d bytes",
+ LOG_INFO("Padding end of page @" TARGET_ADDR_FMT " by %d bytes",
bank->base + offset, end_pad);
memset(&tmp_buf[256 - end_pad], 0xff, end_pad);
}
}
-static int xmc4xxx_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
+static int xmc4xxx_get_info_command(struct flash_bank *bank, struct command_invocation *cmd)
{
struct xmc4xxx_flash_bank *fb = bank->driver_priv;
uint32_t scu_idcode;
break;
}
break;
+ case 0x300:
+ dev_str = "XMC4300";
+
+ switch (rev_id) {
+ case 0x1:
+ rev_str = "AA";
+ }
+ break;
case 0x400:
dev_str = "XMC4400";
break;
}
break;
+ case 0x700:
+ dev_str = "XMC4700";
+
+ switch (rev_id) {
+ case 0x1:
+ rev_str = "EES-AA";
+ break;
+ }
+ break;
case 0x800:
dev_str = "XMC4800";
break;
default:
- snprintf(buf, buf_size,
- "Cannot identify target as an XMC4xxx. SCU_ID: %"PRIx32"\n",
- scu_idcode);
+ command_print_sameline(cmd, "Cannot identify target as an XMC4xxx. SCU_ID: %"PRIx32 "\n", scu_idcode);
return ERROR_OK;
}
snprintf(prot_str, sizeof(prot_str), "\nFlash is read protected");
bool otp_enabled = false;
- for (int i = 0; i < bank->num_sectors; i++)
+ for (unsigned int i = 0; i < bank->num_sectors; i++)
if (fb->write_prot_otp[i])
otp_enabled = true;
/* If OTP Write protection is enabled (User 2), list each
* sector that has it enabled */
- char otp_str[8];
+ char otp_str[14];
if (otp_enabled) {
strcat(prot_str, "\nOTP Protection is enabled for sectors:\n");
- for (int i = 0; i < bank->num_sectors; i++) {
+ for (unsigned int i = 0; i < bank->num_sectors; i++) {
if (fb->write_prot_otp[i]) {
snprintf(otp_str, sizeof(otp_str), "- %d\n", i);
- strncat(prot_str, otp_str, ARRAY_SIZE(otp_str));
+ strncat(prot_str, otp_str, sizeof(prot_str) - strlen(prot_str) - 1);
}
}
}
- if (rev_str != NULL)
- snprintf(buf, buf_size, "%s - Rev: %s%s",
- dev_str, rev_str, prot_str);
+ if (rev_str)
+ command_print_sameline(cmd, "%s - Rev: %s%s", dev_str, rev_str, prot_str);
else
- snprintf(buf, buf_size, "%s - Rev: unknown (0x%01x)%s",
- dev_str, rev_id, prot_str);
+ command_print_sameline(cmd, "%s - Rev: unknown (0x%01x)%s", dev_str, rev_id, prot_str);
return ERROR_OK;
}
uint32_t addr;
int res;
- if ((level < 0) || (level > 1)) {
- LOG_ERROR("Invalid user level. Must be 0-1");
- return ERROR_FAIL;
- }
-
switch (level) {
case 0:
addr = UCB0_BASE;
case 1:
addr = UCB1_BASE;
break;
+ default:
+ LOG_ERROR("Invalid user level. Must be 0-1");
+ return ERROR_FAIL;
}
res = xmc4xxx_erase_sector(bank, addr, true);
/* Reference: "XMC4500 Flash Protection.pptx" app note */
static int xmc4xxx_flash_protect(struct flash_bank *bank, int level, bool read_protect,
- int first, int last)
+ unsigned int first, unsigned int last)
{
/* User configuration block buffers */
uint8_t ucp0_buf[8 * sizeof(uint32_t)] = {0};
/* We need to fill out the procon register representation
* that we will be writing to the device */
- for (int i = first; i <= last; i++)
+ for (unsigned int i = first; i <= last; i++)
procon |= 1 << i;
/* If read protection is requested, set the appropriate bit
return ERROR_OK;
}
-static int xmc4xxx_protect(struct flash_bank *bank, int set, int first, int last)
+static int xmc4xxx_protect(struct flash_bank *bank, int set, unsigned int first,
+ unsigned int last)
{
int ret;
struct xmc4xxx_flash_bank *fb = bank->driver_priv;
return ret;
}
- int sectors = bank->num_sectors;
+ unsigned int sectors = bank->num_sectors;
- /* On devices with 12 sectors, sectors 10 & 11 are ptected
+ /* On devices with 12 sectors, sectors 10 & 11 are protected
* together instead of individually */
if (sectors == 12)
sectors--;
/* Clear the protection status */
- for (int i = 0; i < bank->num_sectors; i++) {
+ for (unsigned int i = 0; i < bank->num_sectors; i++) {
bank->sectors[i].is_protected = 0;
fb->write_prot_otp[i] = false;
}
/* Check for write protection on every available
* sector */
- for (int j = 0; j < sectors; j++) {
+ for (unsigned int j = 0; j < sectors; j++) {
int set = (protection[i] & (1 << j)) ? 1 : 0;
bank->sectors[j].is_protected |= set;
}
}
- /* XMC4xxx also supports read proptection, make a note
+ /* XMC4xxx also supports read protection, make a note
* in the private driver structure */
if (protection[0] & PROCON_RPRO_MASK)
fb->read_protected = true;
fb->pw_set = true;
- command_print(CMD_CTX, "XMC4xxx flash passwords set to:\n");
- command_print(CMD_CTX, "-0x%08"PRIx32"\n", fb->pw1);
- command_print(CMD_CTX, "-0x%08"PRIx32"\n", fb->pw2);
+ command_print(CMD, "XMC4xxx flash passwords set to:\n");
+ command_print(CMD, "-0x%08"PRIx32"\n", fb->pw1);
+ command_print(CMD, "-0x%08"PRIx32"\n", fb->pw2);
return ERROR_OK;
}
.usage = "bank_id user_level[0-1]",
.help = "Permanently Removes flash protection (read and write) "
"for the specified user level",
- }, COMMAND_REGISTRATION_DONE
+ },
+ COMMAND_REGISTRATION_DONE
};
static const struct command_registration xmc4xxx_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
-struct flash_driver xmc4xxx_flash = {
+const struct flash_driver xmc4xxx_flash = {
.name = "xmc4xxx",
.commands = xmc4xxx_command_handlers,
.flash_bank_command = xmc4xxx_flash_bank_command,
.read = default_flash_read,
.probe = xmc4xxx_probe,
.auto_probe = xmc4xxx_probe,
- .erase_check = xmc4xxx_flash_blank_check,
+ .erase_check = default_flash_blank_check,
.info = xmc4xxx_get_info_command,
.protect_check = xmc4xxx_protect_check,
.protect = xmc4xxx_protect,
+ .free_driver_priv = default_flash_free_driver_priv,
};