dsp5680xx_flash: Remove unused flash bank structure
[fw/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  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, 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, 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 static int dsp5680xx_flash_info(struct flash_bank *bank, char *buf,
197                 int buf_size)
198 {
199         snprintf(buf, buf_size,
200                 "\ndsp5680xx flash driver info:\n - See comments in code.");
201         return ERROR_OK;
202 }
203
204 /**
205  * The flash module (FM) on the dsp5680xx supports both individual sector
206  * and mass erase of the flash memory.
207  * If this function is called with @first == @last == 0 or if @first is the
208  * first sector (#0) and @last is the last sector then the mass erase command
209  * is executed (much faster than erasing each sector individually).
210  *
211  * @param bank
212  * @param first
213  * @param last
214  *
215  * @return
216  */
217 static int dsp5680xx_flash_erase(struct flash_bank *bank, int first, int last)
218 {
219         int retval;
220
221         retval = dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last);
222         if ((!(first | last)) || ((first == 0) && (last == (HFM_SECTOR_COUNT - 1))))
223                 last = HFM_SECTOR_COUNT - 1;
224         if (retval == ERROR_OK)
225                 for (int i = first; i <= last; i++)
226                         bank->sectors[i].is_erased = 1;
227         else
228                 /**
229                  * If an error occurred unknown status
230                  *is set even though some sector could have been correctly erased.
231                  */
232                 for (int i = first; i <= last; i++)
233                         bank->sectors[i].is_erased = -1;
234         return retval;
235 }
236
237 /**
238  * The flash module (FM) on the dsp5680xx support a blank check function.
239  * This function executes the FM's blank check functionality on each and every sector.
240  *
241  * @param bank
242  *
243  * @return
244  */
245 static int dsp5680xx_flash_erase_check(struct flash_bank *bank)
246 {
247         int retval = ERROR_OK;
248
249         uint8_t erased = 0;
250
251         uint32_t i;
252
253         for (i = 0; i < HFM_SECTOR_COUNT; i++) {
254                 if (bank->sectors[i].is_erased == -1) {
255                         retval = dsp5680xx_f_erase_check(bank->target, &erased, i);
256                         if (retval != ERROR_OK) {
257                                 bank->sectors[i].is_erased = -1;
258                         } else {
259                                 if (erased)
260                                         bank->sectors[i].is_erased = 1;
261                                 else
262                                         bank->sectors[i].is_erased = 0;
263                         }
264                 }
265         }
266         return retval;
267 }
268
269 struct flash_driver dsp5680xx_flash = {
270         .name = "dsp5680xx_flash",
271         .flash_bank_command = dsp5680xx_flash_bank_command,
272         .erase = dsp5680xx_flash_erase,
273         .protect = dsp5680xx_flash_protect,
274         .write = dsp5680xx_flash_write,
275         /* .read = default_flash_read, */
276         .probe = dsp5680xx_probe,
277         .auto_probe = dsp5680xx_probe,
278         .erase_check = dsp5680xx_flash_erase_check,
279         .protect_check = dsp5680xx_flash_protect_check,
280         .info = dsp5680xx_flash_info
281 };