add const keyword to some APIs
[openocd.git] / src / flash / 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, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21 /***************************************************************************
22 * There are some things to notice
23 *
24 * You need to unprotect flash sectors each time you connect the OpenOCD
25 * Dumping 1MB takes about 60 Seconds
26 * Full erase (sectors 0-22 inclusive) takes 2-4 seconds
27 * Writing 1MB takes 88 seconds
28 *
29 ***************************************************************************/
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include "lpc288x.h"
35 #include "binarybuffer.h"
36
37
38 #define LOAD_TIMER_ERASE 0
39 #define LOAD_TIMER_WRITE 1
40
41 #define FLASH_PAGE_SIZE 512
42
43 /* LPC288X control registers */
44 #define DBGU_CIDR 0x8000507C
45 /* LPC288X flash registers */
46 #define F_CTRL 0x80102000 /* Flash control register R/W 0x5 */
47 #define F_STAT 0x80102004 /* Flash status register RO 0x45 */
48 #define F_PROG_TIME 0x80102008 /* Flash program time register R/W 0 */
49 #define F_WAIT 0x80102010 /* Flash read wait state register R/W 0xC004 */
50 #define F_CLK_TIME 0x8010201C /* Flash clock divider for 66 kHz generation R/W 0 */
51 #define F_INTEN_CLR 0x80102FD8 /* Clear interrupt enable bits WO - */
52 #define F_INTEN_SET 0x80102FDC /* Set interrupt enable bits WO - */
53 #define F_INT_STAT 0x80102FE0 /* Interrupt status bits RO 0 */
54 #define F_INTEN 0x80102FE4 /* Interrupt enable bits RO 0 */
55 #define F_INT_CLR 0x80102FE8 /* Clear interrupt status bits WO */
56 #define F_INT_SET 0x80102FEC /* Set interrupt status bits WO - */
57 #define FLASH_PD 0x80005030 /* Allows turning off the Flash memory for power savings. R/W 1*/
58 #define FLASH_INIT 0x80005034 /* Monitors Flash readiness, such as recovery from 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 #if 0
88 static int lpc288x_register_commands(struct command_context_s *cmd_ctx);
89 static int lpc288x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
90 static int lpc288x_erase(struct flash_bank_s *bank, int first, int last);
91 static int lpc288x_protect(struct flash_bank_s *bank, int set, int first, int last);
92 static int lpc288x_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count);
93 static int lpc288x_probe(struct flash_bank_s *bank);
94 static int lpc288x_erase_check(struct flash_bank_s *bank);
95 static int lpc288x_protect_check(struct flash_bank_s *bank);
96 static int lpc288x_info(struct flash_bank_s *bank, char *buf, int buf_size);
97 #endif
98 static uint32_t lpc288x_wait_status_busy(flash_bank_t *bank, int timeout);
99 static void lpc288x_load_timer(int erase, struct target_s *target);
100 static void lpc288x_set_flash_clk(struct flash_bank_s *bank);
101 static uint32_t lpc288x_system_ready(struct flash_bank_s *bank);
102
103 static uint32_t lpc288x_wait_status_busy(flash_bank_t *bank, int timeout)
104 {
105 uint32_t status;
106 target_t *target = bank->target;
107 do
108 {
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 {
116 LOG_DEBUG("Timedout!");
117 return ERROR_FLASH_OPERATION_FAILED;
118 }
119 return ERROR_OK;
120 }
121
122 /* Read device id register and fill in driver info structure */
123 static int lpc288x_read_part_info(struct flash_bank_s *bank)
124 {
125 lpc288x_flash_bank_t *lpc288x_info = bank->driver_priv;
126 target_t *target = bank->target;
127 uint32_t cidr;
128
129 int i = 0;
130 uint32_t offset;
131
132 if (lpc288x_info->cidr == 0x0102100A)
133 return ERROR_OK; /* already probed, multiple probes may cause memory leak, not allowed */
134
135 /* Read and parse chip identification register */
136 target_read_u32(target, DBGU_CIDR, &cidr);
137
138 if (cidr != 0x0102100A)
139 {
140 LOG_WARNING("Cannot identify target as an LPC288X (%08" PRIx32 ")",cidr);
141 return ERROR_FLASH_OPERATION_FAILED;
142 }
143
144 lpc288x_info->cidr = cidr;
145 lpc288x_info->sector_size_break = 0x000F0000;
146 lpc288x_info->target_name = "LPC288x";
147
148 /* setup the sector info... */
149 offset = bank->base;
150 bank->num_sectors = 23;
151 bank->sectors = malloc(sizeof(flash_sector_t) * 23);
152
153 for (i = 0; i < 15; i++)
154 {
155 bank->sectors[i].offset = offset;
156 bank->sectors[i].size = 64 * 1024;
157 offset += bank->sectors[i].size;
158 bank->sectors[i].is_erased = -1;
159 bank->sectors[i].is_protected = 1;
160 }
161 for (i = 15; i < 23; i++)
162 {
163 bank->sectors[i].offset = offset;
164 bank->sectors[i].size = 8 * 1024;
165 offset += bank->sectors[i].size;
166 bank->sectors[i].is_erased = -1;
167 bank->sectors[i].is_protected = 1;
168 }
169
170 return ERROR_OK;
171 }
172
173 static int lpc288x_protect_check(struct flash_bank_s *bank)
174 {
175 return ERROR_OK;
176 }
177
178 /* flash_bank LPC288x 0 0 0 0 <target#> <cclk> */
179 static int lpc288x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
180 {
181 lpc288x_flash_bank_t *lpc288x_info;
182
183 if (argc < 6)
184 {
185 LOG_WARNING("incomplete flash_bank LPC288x configuration");
186 return ERROR_FLASH_BANK_INVALID;
187 }
188
189 lpc288x_info = malloc(sizeof(lpc288x_flash_bank_t));
190 bank->driver_priv = lpc288x_info;
191
192 /* part wasn't probed for info yet */
193 lpc288x_info->cidr = 0;
194 COMMAND_PARSE_NUMBER(u32, args[6], lpc288x_info->cclk);
195
196 return ERROR_OK;
197 }
198
199 /* The frequency is the AHB clock frequency divided by (CLK_DIV ×3) + 1.
200 * This must be programmed such that the Flash Programming clock frequency is 66 kHz ± 20%.
201 * AHB = 12 MHz ?
202 * 12000000/66000 = 182
203 * CLK_DIV = 60 ? */
204 static void lpc288x_set_flash_clk(struct flash_bank_s *bank)
205 {
206 uint32_t clk_time;
207 lpc288x_flash_bank_t *lpc288x_info = bank->driver_priv;
208 clk_time = (lpc288x_info->cclk / 66000) / 3;
209 target_write_u32(bank->target, F_CTRL, FC_CS | FC_WEN);
210 target_write_u32(bank->target, F_CLK_TIME, clk_time);
211 }
212
213 /* AHB tcyc (in ns) 83 ns
214 * LOAD_TIMER_ERASE FPT_TIME = ((400,000,000 / AHB tcyc (in ns)) - 2) / 512
215 * = 9412 (9500) (AN10548 9375)
216 * LOAD_TIMER_WRITE FPT_TIME = ((1,000,000 / AHB tcyc (in ns)) - 2) / 512
217 * = 23 (75) (AN10548 72 - is this wrong?)
218 * TODO: Sort out timing calcs ;) */
219 static void lpc288x_load_timer(int erase, struct target_s *target)
220 {
221 if (erase == LOAD_TIMER_ERASE)
222 {
223 target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 9500);
224 }
225 else
226 {
227 target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 75);
228 }
229 }
230
231 static uint32_t lpc288x_system_ready(struct flash_bank_s *bank)
232 {
233 lpc288x_flash_bank_t *lpc288x_info = bank->driver_priv;
234 if (lpc288x_info->cidr == 0)
235 {
236 return ERROR_FLASH_BANK_NOT_PROBED;
237 }
238
239 if (bank->target->state != TARGET_HALTED)
240 {
241 LOG_ERROR("Target not halted");
242 return ERROR_TARGET_NOT_HALTED;
243 }
244 return ERROR_OK;
245 }
246
247 static int lpc288x_erase_check(struct flash_bank_s *bank)
248 {
249 uint32_t status = lpc288x_system_ready(bank); /* probed? halted? */
250 if (status != ERROR_OK)
251 {
252 LOG_INFO("Processor not halted/not probed");
253 return status;
254 }
255
256 return ERROR_OK;
257 }
258
259 static int lpc288x_erase(struct flash_bank_s *bank, int first, int last)
260 {
261 uint32_t status;
262 int sector;
263 target_t *target = bank->target;
264
265 status = lpc288x_system_ready(bank); /* probed? halted? */
266 if (status != ERROR_OK)
267 {
268 return status;
269 }
270
271 if ((first < 0) || (last < first) || (last >= bank->num_sectors))
272 {
273 LOG_INFO("Bad sector range");
274 return ERROR_FLASH_SECTOR_INVALID;
275 }
276
277 /* Configure the flash controller timing */
278 lpc288x_set_flash_clk(bank);
279
280 for (sector = first; sector <= last; sector++)
281 {
282 if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
283 {
284 return ERROR_FLASH_OPERATION_FAILED;
285 }
286
287 lpc288x_load_timer(LOAD_TIMER_ERASE,target);
288
289 target_write_u32(target, bank->sectors[sector].offset, 0x00);
290
291 target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_CS);
292 }
293 if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
294 {
295 return ERROR_FLASH_OPERATION_FAILED;
296 }
297 return ERROR_OK;
298 }
299
300 static int lpc288x_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
301 {
302 uint8_t page_buffer[FLASH_PAGE_SIZE];
303 uint32_t status, source_offset,dest_offset;
304 target_t *target = bank->target;
305 uint32_t bytes_remaining = count;
306 uint32_t first_sector, last_sector, sector, page;
307 int i;
308
309 /* probed? halted? */
310 status = lpc288x_system_ready(bank);
311 if (status != ERROR_OK)
312 {
313 return status;
314 }
315
316 /* Initialise search indices */
317 first_sector = last_sector = 0xffffffff;
318
319 /* validate the write range... */
320 for (i = 0; i < bank->num_sectors; i++)
321 {
322 if ((offset >= bank->sectors[i].offset) &&
323 (offset < (bank->sectors[i].offset + bank->sectors[i].size)) &&
324 (first_sector == 0xffffffff))
325 {
326 first_sector = i;
327 /* all writes must start on a sector boundary... */
328 if (offset % bank->sectors[i].size)
329 {
330 LOG_INFO("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "", offset, bank->sectors[i].size);
331 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
332 }
333 }
334 if (((offset + count) > bank->sectors[i].offset) &&
335 ((offset + count) <= (bank->sectors[i].offset + bank->sectors[i].size)) &&
336 (last_sector == 0xffffffff))
337 {
338 last_sector = i;
339 }
340 }
341
342 /* Range check... */
343 if (first_sector == 0xffffffff || last_sector == 0xffffffff)
344 {
345 LOG_INFO("Range check failed %" PRIx32 " %" PRIx32 "", offset, count);
346 return ERROR_FLASH_DST_OUT_OF_BANK;
347 }
348
349 /* Configure the flash controller timing */
350 lpc288x_set_flash_clk(bank);
351
352 /* initialise the offsets */
353 source_offset = 0;
354 dest_offset = 0;
355
356 for (sector = first_sector; sector <= last_sector; sector++)
357 {
358 for (page = 0; page < bank->sectors[sector].size / FLASH_PAGE_SIZE; page++)
359 {
360 if (bytes_remaining == 0)
361 {
362 count = 0;
363 memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
364 }
365 else if (bytes_remaining < FLASH_PAGE_SIZE)
366 {
367 count = bytes_remaining;
368 memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
369 memcpy(page_buffer, &buffer[source_offset], count);
370 }
371 else
372 {
373 count = FLASH_PAGE_SIZE;
374 memcpy(page_buffer, &buffer[source_offset], count);
375 }
376
377 /* Wait for flash to become ready */
378 if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
379 {
380 return ERROR_FLASH_OPERATION_FAILED;
381 }
382
383 /* fill flash data latches with 1's */
384 target_write_u32(target, F_CTRL, FC_CS | FC_SET_DATA | FC_WEN | FC_FUNC);
385
386 target_write_u32(target, F_CTRL, FC_CS | FC_WEN | FC_FUNC);
387 /*would be better to use the clean target_write_buffer() interface but
388 * it seems not to be a LOT slower....
389 * bulk_write_memory() is no quicker :(*/
390 #if 1
391 if (target_write_memory(target, offset + dest_offset, 4, 128, page_buffer) != ERROR_OK)
392 {
393 LOG_ERROR("Write failed s %" PRIx32 " p %" PRIx32 "", sector, page);
394 return ERROR_FLASH_OPERATION_FAILED;
395 }
396 #else
397 if (target_write_buffer(target, offset + dest_offset, FLASH_PAGE_SIZE, page_buffer) != ERROR_OK)
398 {
399 LOG_INFO("Write to flash buffer failed");
400 return ERROR_FLASH_OPERATION_FAILED;
401 }
402 #endif
403 dest_offset += FLASH_PAGE_SIZE;
404 source_offset += count;
405 bytes_remaining -= count;
406
407 lpc288x_load_timer(LOAD_TIMER_WRITE, target);
408
409 target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_FUNC | FC_CS);
410 }
411 }
412
413 return ERROR_OK;
414 }
415
416 static int lpc288x_probe(struct flash_bank_s *bank)
417 {
418 /* we only deal with LPC2888 so flash config is fixed */
419 lpc288x_flash_bank_t *lpc288x_info = bank->driver_priv;
420 int retval;
421
422 if (lpc288x_info->cidr != 0)
423 {
424 return ERROR_OK; /* already probed */
425 }
426
427 if (bank->target->state != TARGET_HALTED)
428 {
429 LOG_ERROR("Target not halted");
430 return ERROR_TARGET_NOT_HALTED;
431 }
432
433 retval = lpc288x_read_part_info(bank);
434 if (retval != ERROR_OK)
435 return retval;
436 return ERROR_OK;
437 }
438
439 static int lpc288x_info(struct flash_bank_s *bank, char *buf, int buf_size)
440 {
441 snprintf(buf, buf_size, "lpc288x flash driver");
442 return ERROR_OK;
443 }
444
445 static int lpc288x_protect(struct flash_bank_s *bank, int set, int first, int last)
446 {
447 int lockregion, status;
448 uint32_t value;
449 target_t *target = bank->target;
450
451 /* probed? halted? */
452 status = lpc288x_system_ready(bank);
453 if (status != ERROR_OK)
454 {
455 return status;
456 }
457
458 if ((first < 0) || (last < first) || (last >= bank->num_sectors))
459 {
460 return ERROR_FLASH_SECTOR_INVALID;
461 }
462
463 /* Configure the flash controller timing */
464 lpc288x_set_flash_clk(bank);
465
466 for (lockregion = first; lockregion <= last; lockregion++)
467 {
468 if (set)
469 {
470 /* write an odd value to base addy to protect... */
471 value = 0x01;
472 }
473 else
474 {
475 /* write an even value to base addy to unprotect... */
476 value = 0x00;
477 }
478 target_write_u32(target, bank->sectors[lockregion].offset, value);
479 target_write_u32(target, F_CTRL, FC_LOAD_REQ | FC_PROTECT | FC_WEN | FC_FUNC | FC_CS);
480 }
481
482 return ERROR_OK;
483 }
484
485 flash_driver_t lpc288x_flash = {
486 .name = "lpc288x",
487 .flash_bank_command = &lpc288x_flash_bank_command,
488 .erase = &lpc288x_erase,
489 .protect = &lpc288x_protect,
490 .write = &lpc288x_write,
491 .probe = &lpc288x_probe,
492 .auto_probe = &lpc288x_probe,
493 .erase_check = &lpc288x_erase_check,
494 .protect_check = &lpc288x_protect_check,
495 .info = &lpc288x_info,
496 };

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)