- set lpc288x[ch] svn file props
[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 "replacements.h"
35
36 #include "lpc288x.h"
37
38 #include "flash.h"
39 #include "target.h"
40 #include "log.h"
41 #include "binarybuffer.h"
42 #include "types.h"
43
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47
48 #define LOAD_TIMER_ERASE 0
49 #define LOAD_TIMER_WRITE 1
50
51 #define FLASH_PAGE_SIZE 512
52
53 /* LPC288X control registers */
54 #define DBGU_CIDR 0x8000507C
55 /* LPC288X flash registers */
56 #define F_CTRL 0x80102000 /* Flash control register R/W 0x5 */
57 #define F_STAT 0x80102004 /* Flash status register RO 0x45 */
58 #define F_PROG_TIME 0x80102008 /* Flash program time register R/W 0 */
59 #define F_WAIT 0x80102010 /* Flash read wait state register R/W 0xC004 */
60 #define F_CLK_TIME 0x8010201C /* Flash clock divider for 66 kHz generation R/W 0 */
61 #define F_INTEN_CLR 0x80102FD8 /* Clear interrupt enable bits WO - */
62 #define F_INTEN_SET 0x80102FDC /* Set interrupt enable bits WO - */
63 #define F_INT_STAT 0x80102FE0 /* Interrupt status bits RO 0 */
64 #define F_INTEN 0x80102FE4 /* Interrupt enable bits RO 0 */
65 #define F_INT_CLR 0x80102FE8 /* Clear interrupt status bits WO */
66 #define F_INT_SET 0x80102FEC /* Set interrupt status bits WO - */
67 #define FLASH_PD 0x80005030 /* Allows turning off the Flash memory for power savings. R/W 1*/
68 #define FLASH_INIT 0x80005034 /* Monitors Flash readiness, such as recovery from Power Down mode. R/W -*/
69
70 /* F_CTRL bits */
71 #define FC_CS 0x0001
72 #define FC_FUNC 0x0002
73 #define FC_WEN 0x0004
74 #define FC_RD_LATCH 0x0020
75 #define FC_PROTECT 0x0080
76 #define FC_SET_DATA 0x0400
77 #define FC_RSSL 0x0800
78 #define FC_PROG_REQ 0x1000
79 #define FC_CLR_BUF 0x4000
80 #define FC_LOAD_REQ 0x8000
81 /* F_STAT bits */
82 #define FS_DONE 0x0001
83 #define FS_PROGGNT 0x0002
84 #define FS_RDY 0x0004
85 #define FS_ERR 0x0020
86 /* F_PROG_TIME */
87 #define FPT_TIME_MASK 0x7FFF
88
89 #define FPT_ENABLE 0x8000
90 /* F_WAIT */
91 #define FW_WAIT_STATES_MASK 0x00FF
92 #define FW_SET_MASK 0xC000
93
94 /* F_CLK_TIME */
95 #define FCT_CLK_DIV_MASK 0x0FFF
96
97
98
99 int lpc288x_register_commands(struct command_context_s *cmd_ctx);
100 int lpc288x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
101 int lpc288x_erase(struct flash_bank_s *bank, int first, int last);
102 int lpc288x_protect(struct flash_bank_s *bank, int set, int first, int last);
103 int lpc288x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
104 int lpc288x_probe(struct flash_bank_s *bank);
105 int lpc288x_auto_probe(struct flash_bank_s *bank);
106 int lpc288x_erase_check(struct flash_bank_s *bank);
107 int lpc288x_protect_check(struct flash_bank_s *bank);
108 int lpc288x_info(struct flash_bank_s *bank, char *buf, int buf_size);
109 void lpc288x_set_flash_mode(flash_bank_t *bank, u8 flashplane, int mode);
110 u32 lpc288x_wait_status_busy(flash_bank_t *bank, int timeout);
111 void lpc288x_load_timer(int erase, struct target_s *target);
112 void lpc288x_set_flash_clk(struct flash_bank_s *bank);
113 u32 lpc288x_system_ready(struct flash_bank_s *bank);
114 int lpc288x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
115
116 flash_driver_t lpc288x_flash =
117 {
118 .name = "lpc288x",
119 .register_commands = lpc288x_register_commands,
120 .flash_bank_command = lpc288x_flash_bank_command,
121 .erase = lpc288x_erase,
122 .protect = lpc288x_protect,
123 .write = lpc288x_write,
124 .probe = lpc288x_probe,
125 .auto_probe = lpc288x_probe,
126 .erase_check = lpc288x_erase_check,
127 .protect_check = lpc288x_protect_check,
128 .info = lpc288x_info
129 };
130
131
132 int lpc288x_register_commands(struct command_context_s *cmd_ctx)
133 {
134 return ERROR_OK;
135 }
136
137
138
139 u32 lpc288x_wait_status_busy(flash_bank_t *bank, int timeout)
140 {
141 u32 status;
142 target_t *target = bank->target;
143 do
144 {
145 usleep(1000);
146 timeout--;
147 target_read_u32(target, F_STAT, &status);
148 }while (((status & FS_DONE) == 0) && timeout);
149
150 if(timeout == 0)
151 {
152 LOG_DEBUG("Timedout!");
153 return ERROR_FLASH_OPERATION_FAILED;
154 }
155 return ERROR_OK;
156 }
157
158 /* Read device id register and fill in driver info structure */
159 int lpc288x_read_part_info(struct flash_bank_s *bank)
160 {
161 lpc288x_flash_bank_t *lpc288x_info = bank->driver_priv;
162 target_t *target = bank->target;
163 u32 cidr, status;
164 int sectornum;
165
166 int i = 0;
167 u32 offset;
168
169 if (lpc288x_info->cidr == 0x0102100A)
170 return ERROR_OK; /* already probed, multiple probes may cause memory leak, not allowed */
171
172 /* Read and parse chip identification register */
173 target_read_u32(target, DBGU_CIDR, &cidr);
174
175 if (cidr != 0x0102100A)
176 {
177 LOG_WARNING("Cannot identify target as an LPC288X (%08X)",cidr);
178 return ERROR_FLASH_OPERATION_FAILED;
179 }
180
181 lpc288x_info->cidr = cidr;
182 lpc288x_info->sector_size_break = 0x000F0000;
183 lpc288x_info->target_name = "LPC288x";
184
185 /* setup the sector info... */
186 offset = bank->base;
187 bank->num_sectors = 23;
188 bank->sectors = malloc(sizeof(flash_sector_t) * 23);
189
190 for (i = 0; i < 15; i++)
191 {
192 bank->sectors[i].offset = offset;
193 bank->sectors[i].size = 64 * 1024;
194 offset += bank->sectors[i].size;
195 bank->sectors[i].is_erased = -1;
196 bank->sectors[i].is_protected = 1;
197 }
198 for (i = 15; i < 23; i++)
199 {
200 bank->sectors[i].offset = offset;
201 bank->sectors[i].size = 8 * 1024;
202 offset += bank->sectors[i].size;
203 bank->sectors[i].is_erased = -1;
204 bank->sectors[i].is_protected = 1;
205 }
206
207 return ERROR_OK;
208 }
209
210 int lpc288x_protect_check(struct flash_bank_s *bank)
211 {
212 return ERROR_OK;
213 }
214
215 /* flash_bank LPC288x 0 0 0 0 <target#> <cclk>
216 */
217 int lpc288x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
218 {
219 lpc288x_flash_bank_t *lpc288x_info;
220 int i;
221
222 if (argc < 6)
223 {
224 LOG_WARNING("incomplete flash_bank LPC288x configuration");
225 return ERROR_FLASH_BANK_INVALID;
226 }
227
228 lpc288x_info = malloc(sizeof(lpc288x_flash_bank_t));
229 bank->driver_priv = lpc288x_info;
230
231 /* part wasn't probed for info yet */
232 lpc288x_info->cidr = 0;
233 lpc288x_info->cclk = strtoul(args[6], NULL, 0);
234
235 return ERROR_OK;
236 }
237
238 /*
239 The frequency is the AHB clock frequency divided by (CLK_DIV ×
240 3) + 1. This must be programmed such that the Flash
241 Programming clock frequency is 66 kHz ± 20%.
242 AHB = 12 MHz ?
243 12000000/66000 = 182
244 CLK_DIV = 60 ?
245 */
246 void lpc288x_set_flash_clk(struct flash_bank_s *bank)
247 {
248 u32 clk_time;
249 lpc288x_flash_bank_t *lpc288x_info = bank->driver_priv;
250 clk_time = (lpc288x_info->cclk / 66000) / 3;
251 target_write_u32(bank->target, F_CTRL, FC_CS | FC_WEN );
252 target_write_u32(bank->target, F_CLK_TIME, clk_time);
253 }
254
255 /*
256 AHB tcyc (in ns) 83 ns
257
258 LOAD_TIMER_ERASE FPT_TIME = ((400,000,000 / AHB tcyc (in ns)) - 2) / 512
259 = 9412 (9500) (AN10548 9375)
260 LOAD_TIMER_WRITE FPT_TIME = ((1,000,000 / AHB tcyc (in ns)) - 2) / 512
261 = 23 (75) (AN10548 72 - is this wrong?)
262
263 TODO: Sort out timing calcs ;)
264 */
265 void lpc288x_load_timer(int erase, struct target_s *target)
266 {
267 if(erase == LOAD_TIMER_ERASE)
268 {
269 target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 9500);
270 }
271 else
272 {
273 target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 75);
274 }
275 }
276
277
278
279 u32 lpc288x_system_ready(struct flash_bank_s *bank)
280 {
281 lpc288x_flash_bank_t *lpc288x_info = bank->driver_priv;
282 if (lpc288x_info->cidr == 0)
283 {
284 return ERROR_FLASH_BANK_NOT_PROBED;
285 }
286
287 if (bank->target->state != TARGET_HALTED)
288 {
289 return ERROR_TARGET_NOT_HALTED;
290 }
291 return ERROR_OK;
292 }
293
294 int lpc288x_erase_check(struct flash_bank_s *bank)
295 {
296 u32 buffer, test_bytes;
297 u32 addr, sector, i, status = lpc288x_system_ready(bank); /* probed? halted? */
298 if(status != ERROR_OK)
299 {
300 LOG_INFO("Processor not halted/not probed");
301 return status;
302 }
303
304 return ERROR_OK;
305 }
306
307 int lpc288x_erase(struct flash_bank_s *bank, int first, int last)
308 {
309 u32 status;
310 int sector;
311 target_t *target = bank->target;
312
313 status = lpc288x_system_ready(bank); /* probed? halted? */
314 if(status != ERROR_OK)
315 {
316 return status;
317 }
318
319 if ((first < 0) || (last < first) || (last >= bank->num_sectors))
320 {
321 LOG_INFO("Bad sector range");
322 return ERROR_FLASH_SECTOR_INVALID;
323 }
324
325 /* Configure the flash controller timing */
326 lpc288x_set_flash_clk(bank);
327
328 for (sector = first; sector <= last; sector++)
329 {
330 if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
331 {
332 return ERROR_FLASH_OPERATION_FAILED;
333 }
334
335 lpc288x_load_timer(LOAD_TIMER_ERASE,target);
336
337 target_write_u32( target,
338 bank->sectors[sector].offset,
339 0x00);
340
341 target_write_u32( target,
342 F_CTRL,
343 FC_PROG_REQ |
344 FC_PROTECT |
345 FC_CS);
346 }
347 if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
348 {
349 return ERROR_FLASH_OPERATION_FAILED;
350 }
351 return ERROR_OK;
352
353 }
354
355
356 int lpc288x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
357 {
358 u8 page_buffer[FLASH_PAGE_SIZE];
359 u32 i, status, source_offset,dest_offset;
360 target_t *target = bank->target;
361 u32 bytes_remaining = count;
362 u32 first_sector, last_sector, sector, page;
363
364 /* probed? halted? */
365 status = lpc288x_system_ready(bank);
366 if(status != ERROR_OK)
367 {
368 return status;
369 }
370
371 /* Initialise search indices */
372 first_sector = last_sector = 0xffffffff;
373
374 /* validate the write range... */
375 for(i = 0; i < bank->num_sectors; i++)
376 {
377 if((offset >= bank->sectors[i].offset) &&
378 (offset < (bank->sectors[i].offset + bank->sectors[i].size)) &&
379 (first_sector == 0xffffffff))
380 {
381 first_sector = i;
382 /* all writes must start on a sector boundary... */
383 if (offset % bank->sectors[i].size)
384 {
385 LOG_INFO("offset 0x%x breaks required alignment 0x%x", offset, bank->sectors[i].size);
386 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
387 }
388 }
389 if(((offset + count) > bank->sectors[i].offset) &&
390 ((offset + count) <= (bank->sectors[i].offset + bank->sectors[i].size)) &&
391 (last_sector == 0xffffffff))
392 {
393 last_sector = i;
394 }
395 }
396
397 /* Range check... */
398 if (first_sector == 0xffffffff || last_sector == 0xffffffff)
399 {
400 LOG_INFO("Range check failed %x %x", offset, count);
401 return ERROR_FLASH_DST_OUT_OF_BANK;
402 }
403
404 /* Configure the flash controller timing */
405 lpc288x_set_flash_clk(bank);
406
407 /* initialise the offsets */
408 source_offset = 0;
409 dest_offset = 0;
410
411 for (sector=first_sector; sector<=last_sector; sector++)
412 {
413 for(page = 0; page < bank->sectors[sector].size / FLASH_PAGE_SIZE; page++)
414 {
415 if(bytes_remaining == 0)
416 {
417 count = 0;
418 memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
419 }
420 else if (bytes_remaining < FLASH_PAGE_SIZE)
421 {
422 count = bytes_remaining;
423 memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
424 memcpy(page_buffer, &buffer[source_offset], count);
425 }
426 else
427 {
428 count = FLASH_PAGE_SIZE;
429 memcpy(page_buffer, &buffer[source_offset], count);
430 }
431
432 /* Wait for flash to become ready */
433 if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
434 {
435 return ERROR_FLASH_OPERATION_FAILED;
436 }
437
438 /* fill flash data latches with 1's */
439 target_write_u32(target, F_CTRL,
440 FC_CS |
441 FC_SET_DATA |
442 FC_WEN |
443 FC_FUNC );
444
445 target_write_u32(target, F_CTRL,
446 FC_CS |
447 FC_WEN |
448 FC_FUNC );
449 /*would be better to use the clean target_write_buffer() interface but
450 it seems not to be a LOT slower....
451 bulk_write_memory() is no quicker :(*/
452 #if 1
453 if (target->type->write_memory(target, offset + dest_offset, 4, 128, page_buffer) != ERROR_OK)
454 {
455 LOG_ERROR("Write failed s %x p %x", sector, page);
456 return ERROR_FLASH_OPERATION_FAILED;
457 }
458 #else
459 if(target_write_buffer(target, offset + dest_offset, FLASH_PAGE_SIZE, page_buffer) != ERROR_OK)
460 {
461 LOG_INFO("Write to flash buffer failed");
462 return ERROR_FLASH_OPERATION_FAILED;
463 }
464 #endif
465 dest_offset += FLASH_PAGE_SIZE;
466 source_offset += count;
467 bytes_remaining -= count;
468
469 lpc288x_load_timer(LOAD_TIMER_WRITE, target);
470
471 target_write_u32( target,
472 F_CTRL,
473 FC_PROG_REQ |
474 FC_PROTECT |
475 FC_FUNC |
476 FC_CS);
477
478
479 }
480 }
481
482 return ERROR_OK;
483 }
484
485
486 int lpc288x_probe(struct flash_bank_s *bank)
487 {
488 /* we only deal with LPC2888 so flash config is fixed
489 */
490 lpc288x_flash_bank_t *lpc288x_info = bank->driver_priv;
491 int retval;
492
493 if (lpc288x_info->cidr != 0)
494 {
495 return ERROR_OK; /* already probed */
496 }
497
498 if (bank->target->state != TARGET_HALTED)
499 {
500 return ERROR_TARGET_NOT_HALTED;
501 }
502
503 retval = lpc288x_read_part_info(bank);
504 if (retval != ERROR_OK)
505 return retval;
506
507 return ERROR_OK;
508 }
509
510
511 int lpc288x_info(struct flash_bank_s *bank, char *buf, int buf_size)
512 {
513 snprintf(buf, buf_size, "lpc288x flash driver");
514 return ERROR_OK;
515 }
516
517 int lpc288x_protect(struct flash_bank_s *bank, int set, int first, int last)
518 {
519 int lockregion, status;
520 u32 value;
521 target_t *target = bank->target;
522
523 /* probed? halted? */
524 status = lpc288x_system_ready(bank);
525 if(status != ERROR_OK)
526 {
527 return status;
528 }
529
530 if ((first < 0) || (last < first) || (last >= bank->num_sectors))
531 {
532 return ERROR_FLASH_SECTOR_INVALID;
533 }
534
535 /* Configure the flash controller timing */
536 lpc288x_set_flash_clk(bank);
537
538 for (lockregion = first; lockregion <= last; lockregion++)
539 {
540 if(set)
541 {
542 /* write an odd value to base addy to protect... */
543 value = 0x01;
544 }
545 else
546 {
547 /* write an even value to base addy to unprotect... */
548 value = 0x00;
549 }
550 target_write_u32( target,
551 bank->sectors[lockregion].offset,
552 value);
553
554 target_write_u32( target,
555 F_CTRL,
556 FC_LOAD_REQ |
557 FC_PROTECT |
558 FC_WEN |
559 FC_FUNC |
560 FC_CS);
561 }
562
563 return ERROR_OK;
564 }
565

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)