target/xtensa: avoid IHI for writes to non-executable memory
[openocd.git] / src / flash / nor / dsp5680xx_flash.c
blobb1625f11f04a890d8a4dece53424c5593abc4e91
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2011 by Rodrigo L. Rosa *
5 * rodrigorosa.LG@gmail.com *
6 * *
7 * Based on a file written by: *
8 * Kevin McGuire *
9 * Marcel Wijlaars *
10 * Michael Ashton *
11 ***************************************************************************/
13 /**
14 * @file dsp5680xx_flash.c
15 * @author Rodrigo L. Rosa <rodrigorosa.LG@gmail.com>
16 * @date Thu Jun 9 18:21:58 2011
18 * @brief This file implements the basic functions to run flashing commands
19 * from the TCL interface.
20 * It allows the user to flash the Freescale 5680xx DSP.
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
29 #include "imp.h"
30 #include <helper/binarybuffer.h>
31 #include <helper/time_support.h>
32 #include <target/algorithm.h>
33 #include <target/dsp5680xx.h>
35 static int dsp5680xx_build_sector_list(struct flash_bank *bank)
37 bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
39 for (unsigned int i = 0; i < bank->num_sectors; ++i) {
40 bank->sectors[i].offset = i * HFM_SECTOR_SIZE;
41 bank->sectors[i].size = HFM_SECTOR_SIZE;
42 bank->sectors[i].is_erased = -1;
43 bank->sectors[i].is_protected = -1;
45 LOG_USER("%s not tested yet.", __func__);
46 return ERROR_OK;
50 /* flash bank dsp5680xx 0 0 0 0 <target#> */
51 FLASH_BANK_COMMAND_HANDLER(dsp5680xx_flash_bank_command)
53 bank->base = HFM_FLASH_BASE_ADDR;
54 bank->size = HFM_SIZE_BYTES; /* top 4k not accessible */
55 bank->num_sectors = HFM_SECTOR_COUNT;
56 dsp5680xx_build_sector_list(bank);
58 return ERROR_OK;
61 /**
62 * A memory mapped register (PROT) holds information regarding sector protection.
63 * Protection refers to undesired core access.
64 * The value in this register is loaded from flash upon reset.
66 * @param bank
68 * @return
70 static int dsp5680xx_flash_protect_check(struct flash_bank *bank)
72 int retval = ERROR_OK;
74 uint16_t protected = 0;
76 retval = dsp5680xx_f_protect_check(bank->target, &protected);
77 if (retval != ERROR_OK) {
78 for (int i = 0; i < HFM_SECTOR_COUNT; i++)
79 bank->sectors[i].is_protected = -1;
80 return ERROR_OK;
82 for (int i = 0; i < HFM_SECTOR_COUNT / 2; i++) {
83 if (protected & 1) {
84 bank->sectors[2 * i].is_protected = 1;
85 bank->sectors[2 * i + 1].is_protected = 1;
86 } else {
87 bank->sectors[2 * i].is_protected = 0;
88 bank->sectors[2 * i + 1].is_protected = 0;
90 protected = (protected >> 1);
92 return retval;
95 /**
96 * Protection functionality is not implemented.
97 * The current implementation applies/removes security on the chip.
98 * The chip is effectively secured/unsecured after the first reset
99 * following the execution of this function.
101 * @param bank
102 * @param set Apply or remove security on the chip.
103 * @param first This parameter is ignored.
104 * @param last This parameter is ignored.
106 * @return
108 static int dsp5680xx_flash_protect(struct flash_bank *bank, int set,
109 unsigned int first, unsigned int last)
112 * This applies security to flash module after next reset, it does
113 * not actually apply protection (protection refers to undesired access from the core)
115 int retval;
117 if (set)
118 retval = dsp5680xx_f_lock(bank->target);
119 else
120 retval = dsp5680xx_f_unlock(bank->target);
122 return retval;
126 * The dsp5680xx use word addressing. The "/2" that appear in the following code
127 * are a workaround for the fact that OpenOCD uses byte addressing.
129 * @param bank
130 * @param buffer Data to write to flash.
131 * @param offset
132 * @param count In bytes (2 bytes per address).
134 * @return
136 static int dsp5680xx_flash_write(struct flash_bank *bank, const uint8_t *buffer,
137 uint32_t offset, uint32_t count)
139 if ((offset + count / 2) > bank->size) {
140 LOG_ERROR("%s: Flash bank cannot fit data.", __func__);
141 return ERROR_FAIL;
143 if (offset % 2) {
145 * Writing to odd addresses not supported.
146 * This chip uses word addressing, Openocd only supports byte addressing.
147 * The workaround results in disabling writing to odd byte addresses
149 LOG_ERROR("%s: Writing to odd addresses not supported for this target", __func__);
150 return ERROR_FAIL;
152 return dsp5680xx_f_wr(bank->target, buffer, bank->base + offset / 2, count, 0);
155 static int dsp5680xx_probe(struct flash_bank *bank)
157 LOG_DEBUG("%s not implemented", __func__);
158 return ERROR_OK;
162 * The flash module (FM) on the dsp5680xx supports both individual sector
163 * and mass erase of the flash memory.
164 * If this function is called with @a first == @a last == 0 or if @a first is the
165 * first sector (#0) and @a last is the last sector then the mass erase command
166 * is executed (much faster than erasing each sector individually).
168 * @param bank
169 * @param first
170 * @param last
172 * @return
174 static int dsp5680xx_flash_erase(struct flash_bank *bank, unsigned int first,
175 unsigned int last)
177 return dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last);
181 * The flash module (FM) on the dsp5680xx support a blank check function.
182 * This function executes the FM's blank check functionality on each and every sector.
184 * @param bank
186 * @return
188 static int dsp5680xx_flash_erase_check(struct flash_bank *bank)
190 int retval = ERROR_OK;
192 uint8_t erased = 0;
194 uint32_t i;
196 for (i = 0; i < HFM_SECTOR_COUNT; i++) {
197 retval = dsp5680xx_f_erase_check(bank->target, &erased, i);
198 if (retval != ERROR_OK) {
199 bank->sectors[i].is_erased = -1;
200 } else {
201 if (erased)
202 bank->sectors[i].is_erased = 1;
203 else
204 bank->sectors[i].is_erased = 0;
207 return retval;
210 const struct flash_driver dsp5680xx_flash = {
211 .name = "dsp5680xx_flash",
212 .flash_bank_command = dsp5680xx_flash_bank_command,
213 .erase = dsp5680xx_flash_erase,
214 .protect = dsp5680xx_flash_protect,
215 .write = dsp5680xx_flash_write,
216 /* .read = default_flash_read, */
217 .probe = dsp5680xx_probe,
218 .auto_probe = dsp5680xx_probe,
219 .erase_check = dsp5680xx_flash_erase_check,
220 .protect_check = dsp5680xx_flash_protect_check,