openocd: fix SPDX tag format for files .c
[fw/openocd] / src / flash / nor / dsp5680xx_flash.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
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  ***************************************************************************/
12
13 /**
14  * @file   dsp5680xx_flash.c
15  * @author Rodrigo L. Rosa <rodrigorosa.LG@gmail.com>
16  * @date   Thu Jun  9 18:21:58 2011
17  *
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.
21  *
22  *
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
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>
34
35 static int dsp5680xx_build_sector_list(struct flash_bank *bank)
36 {
37         bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
38
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;
44         }
45         LOG_USER("%s not tested yet.", __func__);
46         return ERROR_OK;
47
48 }
49
50 /* flash bank dsp5680xx 0 0 0 0 <target#> */
51 FLASH_BANK_COMMAND_HANDLER(dsp5680xx_flash_bank_command)
52 {
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);
57
58         return ERROR_OK;
59 }
60
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.
65  *
66  * @param bank
67  *
68  * @return
69  */
70 static int dsp5680xx_flash_protect_check(struct flash_bank *bank)
71 {
72         int retval = ERROR_OK;
73
74         uint16_t protected = 0;
75
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;
81         }
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;
89                 }
90                 protected = (protected >> 1);
91         }
92         return retval;
93 }
94
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.
100  *
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.
105  *
106  * @return
107  */
108 static int dsp5680xx_flash_protect(struct flash_bank *bank, int set,
109                 unsigned int first, unsigned int last)
110 {
111 /**
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)
114  */
115         int retval;
116
117         if (set)
118                 retval = dsp5680xx_f_lock(bank->target);
119         else
120                 retval = dsp5680xx_f_unlock(bank->target);
121
122         return retval;
123 }
124
125 /**
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.
128  *
129  * @param bank
130  * @param buffer Data to write to flash.
131  * @param offset
132  * @param count In bytes (2 bytes per address).
133  *
134  * @return
135  */
136 static int dsp5680xx_flash_write(struct flash_bank *bank, const uint8_t *buffer,
137                                  uint32_t offset, uint32_t count)
138 {
139         if ((offset + count / 2) > bank->size) {
140                 LOG_ERROR("%s: Flash bank cannot fit data.", __func__);
141                 return ERROR_FAIL;
142         }
143         if (offset % 2) {
144                 /**
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
148                  */
149                 LOG_ERROR("%s: Writing to odd addresses not supported for this target", __func__);
150                 return ERROR_FAIL;
151         }
152         return dsp5680xx_f_wr(bank->target, buffer, bank->base + offset / 2, count, 0);
153 }
154
155 static int dsp5680xx_probe(struct flash_bank *bank)
156 {
157         LOG_DEBUG("%s not implemented", __func__);
158         return ERROR_OK;
159 }
160
161 /**
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).
167  *
168  * @param bank
169  * @param first
170  * @param last
171  *
172  * @return
173  */
174 static int dsp5680xx_flash_erase(struct flash_bank *bank, unsigned int first,
175                 unsigned int last)
176 {
177         return dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last);
178 }
179
180 /**
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.
183  *
184  * @param bank
185  *
186  * @return
187  */
188 static int dsp5680xx_flash_erase_check(struct flash_bank *bank)
189 {
190         int retval = ERROR_OK;
191
192         uint8_t erased = 0;
193
194         uint32_t i;
195
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;
205                 }
206         }
207         return retval;
208 }
209
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,
221 };