]> git.sur5r.net Git - openocd/blob - src/flash/nor/dsp5680xx_flash.c
flash: Constify write buffer
[openocd] / src / flash / nor / dsp5680xx_flash.c
1 /***************************************************************************
2  *   Copyright (C) 2011 by Rodrigo L. Rosa                                 *
3  *   rodrigorosa.LG@gmail.com                                              *
4  *                                                                         *
5  *   Based on a file written by:                                           *
6  *   Kevin McGuire                                                         *
7  *   Marcel Wijlaars                                                       *
8  *   Michael Ashton                                                        *
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version.                                   *
14  *                                                                         *
15  *   This program is distributed in the hope that it will be useful,       *
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  *   GNU General Public License for more details.                          *
19  *                                                                         *
20  *   You should have received a copy of the GNU General Public License     *
21  *   along with this program; if not, write to the                         *
22  *   Free Software Foundation, Inc.,                                       *
23  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
24  ***************************************************************************/
25
26 /**
27  * @file   dsp5680xx_flash.c
28  * @author Rodrigo L. Rosa <rodrigorosa.LG@gmail.com>
29  * @date   Thu Jun  9 18:21:58 2011
30  *
31  * @brief  This file implements the basic functions to run flashing commands
32  * from the TCL interface.
33  * It allows the user to flash the Freescale 5680xx DSP.
34  *
35  *
36  */
37
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41
42 #include "imp.h"
43 #include <helper/binarybuffer.h>
44 #include <helper/time_support.h>
45 #include <target/algorithm.h>
46 #include <target/dsp5680xx.h>
47
48 static int dsp5680xx_build_sector_list(struct flash_bank *bank)
49 {
50         uint32_t offset = HFM_FLASH_BASE_ADDR;
51
52         bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
53         int i;
54
55         for (i = 0; i < bank->num_sectors; ++i) {
56                 bank->sectors[i].offset = i * HFM_SECTOR_SIZE;
57                 bank->sectors[i].size = HFM_SECTOR_SIZE;
58                 offset += bank->sectors[i].size;
59                 bank->sectors[i].is_erased = -1;
60                 bank->sectors[i].is_protected = -1;
61         }
62         LOG_USER("%s not tested yet.", __func__);
63         return ERROR_OK;
64
65 }
66
67 /* flash bank dsp5680xx 0 0 0 0 <target#> */
68 FLASH_BANK_COMMAND_HANDLER(dsp5680xx_flash_bank_command)
69 {
70         bank->base = HFM_FLASH_BASE_ADDR;
71         bank->size = HFM_SIZE_BYTES; /* top 4k not accessible */
72         bank->num_sectors = HFM_SECTOR_COUNT;
73         dsp5680xx_build_sector_list(bank);
74
75         return ERROR_OK;
76 }
77
78 /**
79  * A memory mapped register (PROT) holds information regarding sector protection.
80  * Protection refers to undesired core access.
81  * The value in this register is loaded from flash upon reset.
82  *
83  * @param bank
84  *
85  * @return
86  */
87 static int dsp5680xx_flash_protect_check(struct flash_bank *bank)
88 {
89         int retval = ERROR_OK;
90
91         uint16_t protected = 0;
92
93         retval = dsp5680xx_f_protect_check(bank->target, &protected);
94         if (retval != ERROR_OK) {
95                 for (int i = 0; i < HFM_SECTOR_COUNT; i++)
96                         bank->sectors[i].is_protected = -1;
97                 return ERROR_OK;
98         }
99         for (int i = 0; i < HFM_SECTOR_COUNT / 2; i++) {
100                 if (protected & 1) {
101                         bank->sectors[2 * i].is_protected = 1;
102                         bank->sectors[2 * i + 1].is_protected = 1;
103                 } else {
104                         bank->sectors[2 * i].is_protected = 0;
105                         bank->sectors[2 * i + 1].is_protected = 0;
106                 }
107                 protected = (protected >> 1);
108         }
109         return retval;
110 }
111
112 /**
113  * Protection funcionality is not implemented.
114  * The current implementation applies/removes security on the chip.
115  * The chip is effectively secured/unsecured after the first reset
116  * following the execution of this function.
117  *
118  * @param bank
119  * @param set Apply or remove security on the chip.
120  * @param first This parameter is ignored.
121  * @param last This parameter is ignored.
122  *
123  * @return
124  */
125 static int dsp5680xx_flash_protect(struct flash_bank *bank, int set, int first,
126                                    int last)
127 {
128 /**
129  * This applies security to flash module after next reset, it does
130  * not actually apply protection (protection refers to undesired access from the core)
131  */
132         int retval;
133
134         if (set)
135                 retval = dsp5680xx_f_lock(bank->target);
136         else {
137                 retval = dsp5680xx_f_unlock(bank->target);
138                 if (retval == ERROR_OK) {
139                         /* mark all as erased */
140                         for (int i = 0; i <= (HFM_SECTOR_COUNT - 1); i++)
141                                 /* FM does not recognize it as erased if erased via JTAG. */
142                                 bank->sectors[i].is_erased = 1;
143                 }
144         }
145         return retval;
146 }
147
148 /**
149  * The dsp5680xx use word addressing. The "/2" that appear in the following code
150  * are a workaround for the fact that OpenOCD uses byte addressing.
151  *
152  * @param bank
153  * @param buffer Data to write to flash.
154  * @param offset
155  * @param count In bytes (2 bytes per address).
156  *
157  * @return
158  */
159 static int dsp5680xx_flash_write(struct flash_bank *bank, const uint8_t* buffer,
160                                  uint32_t offset, uint32_t count)
161 {
162         int retval;
163
164         if ((offset + count / 2) > bank->size) {
165                 LOG_ERROR("%s: Flash bank cannot fit data.", __func__);
166                 return ERROR_FAIL;
167         }
168         if (offset % 2) {
169                 /**
170                  * Writing to odd addresses not supported.
171                  * This chip uses word addressing, Openocd only supports byte addressing.
172                  * The workaround results in disabling writing to odd byte addresses
173                  */
174                 LOG_ERROR("%s: Writing to odd addresses not supported for this target", __func__);
175                 return ERROR_FAIL;
176         }
177         retval = dsp5680xx_f_wr(bank->target, buffer, bank->base + offset / 2, count, 0);
178         uint32_t addr_word;
179
180         for (addr_word = bank->base + offset / 2; addr_word < count / 2;
181                         addr_word += (HFM_SECTOR_SIZE / 2)) {
182                 if (retval == ERROR_OK)
183                         bank->sectors[addr_word / (HFM_SECTOR_SIZE / 2)].is_erased = 0;
184                 else
185                         bank->sectors[addr_word / (HFM_SECTOR_SIZE / 2)].is_erased = -1;
186         }
187         return retval;
188 }
189
190 static int dsp5680xx_probe(struct flash_bank *bank)
191 {
192         LOG_DEBUG("%s not implemented", __func__);
193         return ERROR_OK;
194 }
195
196 /**
197  * The flash module (FM) on the dsp5680xx supports both individual sector
198  * and mass erase of the flash memory.
199  * If this function is called with @first == @last == 0 or if @first is the
200  * first sector (#0) and @last is the last sector then the mass erase command
201  * is executed (much faster than erasing each sector individually).
202  *
203  * @param bank
204  * @param first
205  * @param last
206  *
207  * @return
208  */
209 static int dsp5680xx_flash_erase(struct flash_bank *bank, int first, int last)
210 {
211         int retval;
212
213         retval = dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last);
214         if ((!(first | last)) || ((first == 0) && (last == (HFM_SECTOR_COUNT - 1))))
215                 last = HFM_SECTOR_COUNT - 1;
216         if (retval == ERROR_OK)
217                 for (int i = first; i <= last; i++)
218                         bank->sectors[i].is_erased = 1;
219         else
220                 /**
221                  * If an error occurred unknown status
222                  *is set even though some sector could have been correctly erased.
223                  */
224                 for (int i = first; i <= last; i++)
225                         bank->sectors[i].is_erased = -1;
226         return retval;
227 }
228
229 /**
230  * The flash module (FM) on the dsp5680xx support a blank check function.
231  * This function executes the FM's blank check functionality on each and every sector.
232  *
233  * @param bank
234  *
235  * @return
236  */
237 static int dsp5680xx_flash_erase_check(struct flash_bank *bank)
238 {
239         int retval = ERROR_OK;
240
241         uint8_t erased = 0;
242
243         uint32_t i;
244
245         for (i = 0; i < HFM_SECTOR_COUNT; i++) {
246                 if (bank->sectors[i].is_erased == -1) {
247                         retval = dsp5680xx_f_erase_check(bank->target, &erased, i);
248                         if (retval != ERROR_OK) {
249                                 bank->sectors[i].is_erased = -1;
250                         } else {
251                                 if (erased)
252                                         bank->sectors[i].is_erased = 1;
253                                 else
254                                         bank->sectors[i].is_erased = 0;
255                         }
256                 }
257         }
258         return retval;
259 }
260
261 struct flash_driver dsp5680xx_flash = {
262         .name = "dsp5680xx_flash",
263         .flash_bank_command = dsp5680xx_flash_bank_command,
264         .erase = dsp5680xx_flash_erase,
265         .protect = dsp5680xx_flash_protect,
266         .write = dsp5680xx_flash_write,
267         /* .read = default_flash_read, */
268         .probe = dsp5680xx_probe,
269         .auto_probe = dsp5680xx_probe,
270         .erase_check = dsp5680xx_flash_erase_check,
271         .protect_check = dsp5680xx_flash_protect_check,
272 };