flash/nor/virtual: copy missing fields from master flash_bank structure
[openocd.git] / src / flash / nor / lpc288x.c
1 /***************************************************************************
2 * Copyright (C) 2008 by *
3 * Karl RobinSod <karl.robinsod@gmail.com> *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
18
19 /***************************************************************************
20 * There are some things to notice
21 *
22 * You need to unprotect flash sectors each time you connect the OpenOCD
23 * Dumping 1MB takes about 60 Seconds
24 * Full erase (sectors 0-22 inclusive) takes 2-4 seconds
25 * Writing 1MB takes 88 seconds
26 *
27 ***************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "imp.h"
33 #include <helper/binarybuffer.h>
34
35 #define LOAD_TIMER_ERASE 0
36 #define LOAD_TIMER_WRITE 1
37
38 #define FLASH_PAGE_SIZE 512
39
40 /* LPC288X control registers */
41 #define DBGU_CIDR 0x8000507C
42 /* LPC288X flash registers */
43 #define F_CTRL 0x80102000 /* Flash control register R/W 0x5 */
44 #define F_STAT 0x80102004 /* Flash status register RO 0x45 */
45 #define F_PROG_TIME 0x80102008 /* Flash program time register R/W 0 */
46 #define F_WAIT 0x80102010 /* Flash read wait state register R/W 0xC004 */
47 #define F_CLK_TIME 0x8010201C /* Flash clock divider for 66 kHz generation R/W 0
48 **/
49 #define F_INTEN_CLR 0x80102FD8 /* Clear interrupt enable bits WO - */
50 #define F_INTEN_SET 0x80102FDC /* Set interrupt enable bits WO - */
51 #define F_INT_STAT 0x80102FE0 /* Interrupt status bits RO 0 */
52 #define F_INTEN 0x80102FE4 /* Interrupt enable bits RO 0 */
53 #define F_INT_CLR 0x80102FE8 /* Clear interrupt status bits WO */
54 #define F_INT_SET 0x80102FEC /* Set interrupt status bits WO - */
55 #define FLASH_PD 0x80005030 /* Allows turning off the Flash memory for power
56 *savings. R/W 1*/
57 #define FLASH_INIT 0x80005034 /* Monitors Flash readiness, such as recovery from
58 *Power Down mode. R/W -*/
59
60 /* F_CTRL bits */
61 #define FC_CS 0x0001
62 #define FC_FUNC 0x0002
63 #define FC_WEN 0x0004
64 #define FC_RD_LATCH 0x0020
65 #define FC_PROTECT 0x0080
66 #define FC_SET_DATA 0x0400
67 #define FC_RSSL 0x0800
68 #define FC_PROG_REQ 0x1000
69 #define FC_CLR_BUF 0x4000
70 #define FC_LOAD_REQ 0x8000
71 /* F_STAT bits */
72 #define FS_DONE 0x0001
73 #define FS_PROGGNT 0x0002
74 #define FS_RDY 0x0004
75 #define FS_ERR 0x0020
76 /* F_PROG_TIME */
77 #define FPT_TIME_MASK 0x7FFF
78
79 #define FPT_ENABLE 0x8000
80 /* F_WAIT */
81 #define FW_WAIT_STATES_MASK 0x00FF
82 #define FW_SET_MASK 0xC000
83
84 /* F_CLK_TIME */
85 #define FCT_CLK_DIV_MASK 0x0FFF
86
87 struct lpc288x_flash_bank {
88 uint32_t working_area;
89 uint32_t working_area_size;
90
91 /* chip id register */
92 uint32_t cidr;
93 const char *target_name;
94 uint32_t cclk;
95
96 uint32_t sector_size_break;
97 };
98
99 static uint32_t lpc288x_wait_status_busy(struct flash_bank *bank, int timeout);
100 static void lpc288x_load_timer(int erase, struct target *target);
101 static void lpc288x_set_flash_clk(struct flash_bank *bank);
102 static uint32_t lpc288x_system_ready(struct flash_bank *bank);
103
104 static uint32_t lpc288x_wait_status_busy(struct flash_bank *bank, int timeout)
105 {
106 uint32_t status;
107 struct target *target = bank->target;
108 do {
109 alive_sleep(1);
110 timeout--;
111 target_read_u32(target, F_STAT, &status);
112 } while (((status & FS_DONE) == 0) && timeout);
113
114 if (timeout == 0) {
115 LOG_DEBUG("Timedout!");
116 return ERROR_FLASH_OPERATION_FAILED;
117 }
118 return ERROR_OK;
119 }
120
121 /* Read device id register and fill in driver info structure */
122 static int lpc288x_read_part_info(struct flash_bank *bank)
123 {
124 struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv;
125 struct target *target = bank->target;
126 uint32_t cidr;
127
128 int i = 0;
129 uint32_t offset;
130
131 if (lpc288x_info->cidr == 0x0102100A)
132 return ERROR_OK;/* already probed, multiple probes may cause memory leak, not
133 *allowed */
134
135 /* Read and parse chip identification register */
136 target_read_u32(target, DBGU_CIDR, &cidr);
137
138 if (cidr != 0x0102100A) {
139 LOG_WARNING("Cannot identify target as an LPC288X (%08" PRIx32 ")", cidr);
140 return ERROR_FLASH_OPERATION_FAILED;
141 }
142
143 lpc288x_info->cidr = cidr;
144 lpc288x_info->sector_size_break = 0x000F0000;
145 lpc288x_info->target_name = "LPC288x";
146
147 /* setup the sector info... */
148 offset = bank->base;
149 bank->num_sectors = 23;
150 bank->sectors = malloc(sizeof(struct flash_sector) * 23);
151
152 for (i = 0; i < 15; i++) {
153 bank->sectors[i].offset = offset;
154 bank->sectors[i].size = 64 * 1024;
155 offset += bank->sectors[i].size;
156 bank->sectors[i].is_erased = -1;
157 bank->sectors[i].is_protected = 1;
158 }
159 for (i = 15; i < 23; i++) {
160 bank->sectors[i].offset = offset;
161 bank->sectors[i].size = 8 * 1024;
162 offset += bank->sectors[i].size;
163 bank->sectors[i].is_erased = -1;
164 bank->sectors[i].is_protected = 1;
165 }
166
167 return ERROR_OK;
168 }
169
170 static int lpc288x_protect_check(struct flash_bank *bank)
171 {
172 return ERROR_OK;
173 }
174
175 /* flash_bank LPC288x 0 0 0 0 <target#> <cclk> */
176 FLASH_BANK_COMMAND_HANDLER(lpc288x_flash_bank_command)
177 {
178 struct lpc288x_flash_bank *lpc288x_info;
179
180 if (CMD_ARGC < 6)
181 return ERROR_COMMAND_SYNTAX_ERROR;
182
183 lpc288x_info = malloc(sizeof(struct lpc288x_flash_bank));
184 bank->driver_priv = lpc288x_info;
185
186 /* part wasn't probed for info yet */
187 lpc288x_info->cidr = 0;
188 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], lpc288x_info->cclk);
189
190 return ERROR_OK;
191 }
192
193 /* The frequency is the AHB clock frequency divided by (CLK_DIV ×3) + 1.
194 * This must be programmed such that the Flash Programming clock frequency is 66 kHz ± 20%.
195 * AHB = 12 MHz ?
196 * 12000000/66000 = 182
197 * CLK_DIV = 60 ? */
198 static void lpc288x_set_flash_clk(struct flash_bank *bank)
199 {
200 uint32_t clk_time;
201 struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv;
202 clk_time = (lpc288x_info->cclk / 66000) / 3;
203 target_write_u32(bank->target, F_CTRL, FC_CS | FC_WEN);
204 target_write_u32(bank->target, F_CLK_TIME, clk_time);
205 }
206
207 /* AHB tcyc (in ns) 83 ns
208 * LOAD_TIMER_ERASE FPT_TIME = ((400,000,000 / AHB tcyc (in ns)) - 2) / 512
209 * = 9412 (9500) (AN10548 9375)
210 * LOAD_TIMER_WRITE FPT_TIME = ((1,000,000 / AHB tcyc (in ns)) - 2) / 512
211 * = 23 (75) (AN10548 72 - is this wrong?)
212 * TODO: Sort out timing calcs ;) */
213 static void lpc288x_load_timer(int erase, struct target *target)
214 {
215 if (erase == LOAD_TIMER_ERASE)
216 target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 9500);
217 else
218 target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 75);
219 }
220
221 static uint32_t lpc288x_system_ready(struct flash_bank *bank)
222 {
223 struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv;
224 if (lpc288x_info->cidr == 0)
225 return ERROR_FLASH_BANK_NOT_PROBED;
226
227 if (bank->target->state != TARGET_HALTED) {
228 LOG_ERROR("Target not halted");
229 return ERROR_TARGET_NOT_HALTED;
230 }
231 return ERROR_OK;
232 }
233
234 static int lpc288x_erase_check(struct flash_bank *bank)
235 {
236 uint32_t status = lpc288x_system_ready(bank); /* probed? halted? */
237 if (status != ERROR_OK) {
238 LOG_INFO("Processor not halted/not probed");
239 return status;
240 }
241
242 return ERROR_OK;
243 }
244
245 static int lpc288x_erase(struct flash_bank *bank, int first, int last)
246 {
247 uint32_t status;
248 int sector;
249 struct target *target = bank->target;
250
251 status = lpc288x_system_ready(bank); /* probed? halted? */
252 if (status != ERROR_OK)
253 return status;
254
255 if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
256 LOG_INFO("Bad sector range");
257 return ERROR_FLASH_SECTOR_INVALID;
258 }
259
260 /* Configure the flash controller timing */
261 lpc288x_set_flash_clk(bank);
262
263 for (sector = first; sector <= last; sector++) {
264 if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
265 return ERROR_FLASH_OPERATION_FAILED;
266
267 lpc288x_load_timer(LOAD_TIMER_ERASE, target);
268
269 target_write_u32(target, bank->sectors[sector].offset, 0x00);
270
271 target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_CS);
272 }
273 if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
274 return ERROR_FLASH_OPERATION_FAILED;
275 return ERROR_OK;
276 }
277
278 static int lpc288x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
279 {
280 uint8_t page_buffer[FLASH_PAGE_SIZE];
281 uint32_t status, source_offset, dest_offset;
282 struct target *target = bank->target;
283 uint32_t bytes_remaining = count;
284 uint32_t first_sector, last_sector, sector, page;
285 int i;
286
287 /* probed? halted? */
288 status = lpc288x_system_ready(bank);
289 if (status != ERROR_OK)
290 return status;
291
292 /* Initialise search indices */
293 first_sector = last_sector = 0xffffffff;
294
295 /* validate the write range... */
296 for (i = 0; i < bank->num_sectors; i++) {
297 if ((offset >= bank->sectors[i].offset) &&
298 (offset < (bank->sectors[i].offset + bank->sectors[i].size)) &&
299 (first_sector == 0xffffffff)) {
300 first_sector = i;
301 /* all writes must start on a sector boundary... */
302 if (offset % bank->sectors[i].size) {
303 LOG_INFO(
304 "offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "",
305 offset,
306 bank->sectors[i].size);
307 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
308 }
309 }
310 if (((offset + count) > bank->sectors[i].offset) &&
311 ((offset + count) <= (bank->sectors[i].offset + bank->sectors[i].size)) &&
312 (last_sector == 0xffffffff))
313 last_sector = i;
314 }
315
316 /* Range check... */
317 if (first_sector == 0xffffffff || last_sector == 0xffffffff) {
318 LOG_INFO("Range check failed %" PRIx32 " %" PRIx32 "", offset, count);
319 return ERROR_FLASH_DST_OUT_OF_BANK;
320 }
321
322 /* Configure the flash controller timing */
323 lpc288x_set_flash_clk(bank);
324
325 /* initialise the offsets */
326 source_offset = 0;
327 dest_offset = 0;
328
329 for (sector = first_sector; sector <= last_sector; sector++) {
330 for (page = 0; page < bank->sectors[sector].size / FLASH_PAGE_SIZE; page++) {
331 if (bytes_remaining == 0) {
332 count = 0;
333 memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
334 } else if (bytes_remaining < FLASH_PAGE_SIZE) {
335 count = bytes_remaining;
336 memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
337 memcpy(page_buffer, &buffer[source_offset], count);
338 } else {
339 count = FLASH_PAGE_SIZE;
340 memcpy(page_buffer, &buffer[source_offset], count);
341 }
342
343 /* Wait for flash to become ready */
344 if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
345 return ERROR_FLASH_OPERATION_FAILED;
346
347 /* fill flash data latches with 1's */
348 target_write_u32(target, F_CTRL, FC_CS | FC_SET_DATA | FC_WEN | FC_FUNC);
349
350 target_write_u32(target, F_CTRL, FC_CS | FC_WEN | FC_FUNC);
351
352 if (target_write_buffer(target, offset + dest_offset, FLASH_PAGE_SIZE,
353 page_buffer) != ERROR_OK) {
354 LOG_INFO("Write to flash buffer failed");
355 return ERROR_FLASH_OPERATION_FAILED;
356 }
357
358 dest_offset += FLASH_PAGE_SIZE;
359 source_offset += count;
360 bytes_remaining -= count;
361
362 lpc288x_load_timer(LOAD_TIMER_WRITE, target);
363
364 target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_FUNC |
365 FC_CS);
366 }
367 }
368
369 return ERROR_OK;
370 }
371
372 static int lpc288x_probe(struct flash_bank *bank)
373 {
374 /* we only deal with LPC2888 so flash config is fixed */
375 struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv;
376 int retval;
377
378 if (lpc288x_info->cidr != 0)
379 return ERROR_OK;/* already probed */
380
381 if (bank->target->state != TARGET_HALTED) {
382 LOG_ERROR("Target not halted");
383 return ERROR_TARGET_NOT_HALTED;
384 }
385
386 retval = lpc288x_read_part_info(bank);
387 if (retval != ERROR_OK)
388 return retval;
389 return ERROR_OK;
390 }
391
392 static int lpc288x_protect(struct flash_bank *bank, int set, int first, int last)
393 {
394 int lockregion, status;
395 uint32_t value;
396 struct target *target = bank->target;
397
398 /* probed? halted? */
399 status = lpc288x_system_ready(bank);
400 if (status != ERROR_OK)
401 return status;
402
403 if ((first < 0) || (last < first) || (last >= bank->num_sectors))
404 return ERROR_FLASH_SECTOR_INVALID;
405
406 /* Configure the flash controller timing */
407 lpc288x_set_flash_clk(bank);
408
409 for (lockregion = first; lockregion <= last; lockregion++) {
410 if (set) {
411 /* write an odd value to base addy to protect... */
412 value = 0x01;
413 } else {
414 /* write an even value to base addy to unprotect... */
415 value = 0x00;
416 }
417 target_write_u32(target, bank->sectors[lockregion].offset, value);
418 target_write_u32(target, F_CTRL, FC_LOAD_REQ | FC_PROTECT | FC_WEN | FC_FUNC |
419 FC_CS);
420 }
421
422 return ERROR_OK;
423 }
424
425 struct flash_driver lpc288x_flash = {
426 .name = "lpc288x",
427 .flash_bank_command = lpc288x_flash_bank_command,
428 .erase = lpc288x_erase,
429 .protect = lpc288x_protect,
430 .write = lpc288x_write,
431 .read = default_flash_read,
432 .probe = lpc288x_probe,
433 .auto_probe = lpc288x_probe,
434 .erase_check = lpc288x_erase_check,
435 .protect_check = lpc288x_protect_check,
436 .free_driver_priv = default_flash_free_driver_priv,
437 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)