- remove target specific variant and use target->variant member
[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 int lpc288x_register_commands(struct command_context_s *cmd_ctx);
98 int lpc288x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
99 int lpc288x_erase(struct flash_bank_s *bank, int first, int last);
100 int lpc288x_protect(struct flash_bank_s *bank, int set, int first, int last);
101 int lpc288x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
102 int lpc288x_probe(struct flash_bank_s *bank);
103 int lpc288x_auto_probe(struct flash_bank_s *bank);
104 int lpc288x_erase_check(struct flash_bank_s *bank);
105 int lpc288x_protect_check(struct flash_bank_s *bank);
106 int lpc288x_info(struct flash_bank_s *bank, char *buf, int buf_size);
107 void lpc288x_set_flash_mode(flash_bank_t *bank, u8 flashplane, int mode);
108 u32 lpc288x_wait_status_busy(flash_bank_t *bank, int timeout);
109 void lpc288x_load_timer(int erase, struct target_s *target);
110 void lpc288x_set_flash_clk(struct flash_bank_s *bank);
111 u32 lpc288x_system_ready(struct flash_bank_s *bank);
112 int lpc288x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
113
114 flash_driver_t lpc288x_flash =
115 {
116 .name = "lpc288x",
117 .register_commands = lpc288x_register_commands,
118 .flash_bank_command = lpc288x_flash_bank_command,
119 .erase = lpc288x_erase,
120 .protect = lpc288x_protect,
121 .write = lpc288x_write,
122 .probe = lpc288x_probe,
123 .auto_probe = lpc288x_probe,
124 .erase_check = lpc288x_erase_check,
125 .protect_check = lpc288x_protect_check,
126 .info = lpc288x_info
127 };
128
129 int lpc288x_register_commands(struct command_context_s *cmd_ctx)
130 {
131 return ERROR_OK;
132 }
133
134 u32 lpc288x_wait_status_busy(flash_bank_t *bank, int timeout)
135 {
136 u32 status;
137 target_t *target = bank->target;
138 do
139 {
140 alive_sleep(1);
141 timeout--;
142 target_read_u32(target, F_STAT, &status);
143 }while (((status & FS_DONE) == 0) && timeout);
144
145 if(timeout == 0)
146 {
147 LOG_DEBUG("Timedout!");
148 return ERROR_FLASH_OPERATION_FAILED;
149 }
150 return ERROR_OK;
151 }
152
153 /* Read device id register and fill in driver info structure */
154 int lpc288x_read_part_info(struct flash_bank_s *bank)
155 {
156 lpc288x_flash_bank_t *lpc288x_info = bank->driver_priv;
157 target_t *target = bank->target;
158 u32 cidr;
159
160 int i = 0;
161 u32 offset;
162
163 if (lpc288x_info->cidr == 0x0102100A)
164 return ERROR_OK; /* already probed, multiple probes may cause memory leak, not allowed */
165
166 /* Read and parse chip identification register */
167 target_read_u32(target, DBGU_CIDR, &cidr);
168
169 if (cidr != 0x0102100A)
170 {
171 LOG_WARNING("Cannot identify target as an LPC288X (%08X)",cidr);
172 return ERROR_FLASH_OPERATION_FAILED;
173 }
174
175 lpc288x_info->cidr = cidr;
176 lpc288x_info->sector_size_break = 0x000F0000;
177 lpc288x_info->target_name = "LPC288x";
178
179 /* setup the sector info... */
180 offset = bank->base;
181 bank->num_sectors = 23;
182 bank->sectors = malloc(sizeof(flash_sector_t) * 23);
183
184 for (i = 0; i < 15; i++)
185 {
186 bank->sectors[i].offset = offset;
187 bank->sectors[i].size = 64 * 1024;
188 offset += bank->sectors[i].size;
189 bank->sectors[i].is_erased = -1;
190 bank->sectors[i].is_protected = 1;
191 }
192 for (i = 15; i < 23; i++)
193 {
194 bank->sectors[i].offset = offset;
195 bank->sectors[i].size = 8 * 1024;
196 offset += bank->sectors[i].size;
197 bank->sectors[i].is_erased = -1;
198 bank->sectors[i].is_protected = 1;
199 }
200
201 return ERROR_OK;
202 }
203
204 int lpc288x_protect_check(struct flash_bank_s *bank)
205 {
206 return ERROR_OK;
207 }
208
209 /* flash_bank LPC288x 0 0 0 0 <target#> <cclk> */
210 int lpc288x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
211 {
212 lpc288x_flash_bank_t *lpc288x_info;
213
214 if (argc < 6)
215 {
216 LOG_WARNING("incomplete flash_bank LPC288x configuration");
217 return ERROR_FLASH_BANK_INVALID;
218 }
219
220 lpc288x_info = malloc(sizeof(lpc288x_flash_bank_t));
221 bank->driver_priv = lpc288x_info;
222
223 /* part wasn't probed for info yet */
224 lpc288x_info->cidr = 0;
225 lpc288x_info->cclk = strtoul(args[6], NULL, 0);
226
227 return ERROR_OK;
228 }
229
230 /* The frequency is the AHB clock frequency divided by (CLK_DIV ×3) + 1.
231 * This must be programmed such that the Flash Programming clock frequency is 66 kHz ± 20%.
232 * AHB = 12 MHz ?
233 * 12000000/66000 = 182
234 * CLK_DIV = 60 ? */
235 void lpc288x_set_flash_clk(struct flash_bank_s *bank)
236 {
237 u32 clk_time;
238 lpc288x_flash_bank_t *lpc288x_info = bank->driver_priv;
239 clk_time = (lpc288x_info->cclk / 66000) / 3;
240 target_write_u32(bank->target, F_CTRL, FC_CS | FC_WEN);
241 target_write_u32(bank->target, F_CLK_TIME, clk_time);
242 }
243
244 /* AHB tcyc (in ns) 83 ns
245 * LOAD_TIMER_ERASE FPT_TIME = ((400,000,000 / AHB tcyc (in ns)) - 2) / 512
246 * = 9412 (9500) (AN10548 9375)
247 * LOAD_TIMER_WRITE FPT_TIME = ((1,000,000 / AHB tcyc (in ns)) - 2) / 512
248 * = 23 (75) (AN10548 72 - is this wrong?)
249 * TODO: Sort out timing calcs ;) */
250 void lpc288x_load_timer(int erase, struct target_s *target)
251 {
252 if (erase == LOAD_TIMER_ERASE)
253 {
254 target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 9500);
255 }
256 else
257 {
258 target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 75);
259 }
260 }
261
262 u32 lpc288x_system_ready(struct flash_bank_s *bank)
263 {
264 lpc288x_flash_bank_t *lpc288x_info = bank->driver_priv;
265 if (lpc288x_info->cidr == 0)
266 {
267 return ERROR_FLASH_BANK_NOT_PROBED;
268 }
269
270 if (bank->target->state != TARGET_HALTED)
271 {
272 LOG_ERROR("Target not halted");
273 return ERROR_TARGET_NOT_HALTED;
274 }
275 return ERROR_OK;
276 }
277
278 int lpc288x_erase_check(struct flash_bank_s *bank)
279 {
280 u32 status = lpc288x_system_ready(bank); /* probed? halted? */
281 if (status != ERROR_OK)
282 {
283 LOG_INFO("Processor not halted/not probed");
284 return status;
285 }
286
287 return ERROR_OK;
288 }
289
290 int lpc288x_erase(struct flash_bank_s *bank, int first, int last)
291 {
292 u32 status;
293 int sector;
294 target_t *target = bank->target;
295
296 status = lpc288x_system_ready(bank); /* probed? halted? */
297 if (status != ERROR_OK)
298 {
299 return status;
300 }
301
302 if ((first < 0) || (last < first) || (last >= bank->num_sectors))
303 {
304 LOG_INFO("Bad sector range");
305 return ERROR_FLASH_SECTOR_INVALID;
306 }
307
308 /* Configure the flash controller timing */
309 lpc288x_set_flash_clk(bank);
310
311 for (sector = first; sector <= last; sector++)
312 {
313 if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
314 {
315 return ERROR_FLASH_OPERATION_FAILED;
316 }
317
318 lpc288x_load_timer(LOAD_TIMER_ERASE,target);
319
320 target_write_u32(target, bank->sectors[sector].offset, 0x00);
321
322 target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_CS);
323 }
324 if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
325 {
326 return ERROR_FLASH_OPERATION_FAILED;
327 }
328 return ERROR_OK;
329 }
330
331 int lpc288x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
332 {
333 u8 page_buffer[FLASH_PAGE_SIZE];
334 u32 i, status, source_offset,dest_offset;
335 target_t *target = bank->target;
336 u32 bytes_remaining = count;
337 u32 first_sector, last_sector, sector, page;
338
339 /* probed? halted? */
340 status = lpc288x_system_ready(bank);
341 if (status != ERROR_OK)
342 {
343 return status;
344 }
345
346 /* Initialise search indices */
347 first_sector = last_sector = 0xffffffff;
348
349 /* validate the write range... */
350 for (i = 0; i < bank->num_sectors; i++)
351 {
352 if ((offset >= bank->sectors[i].offset) &&
353 (offset < (bank->sectors[i].offset + bank->sectors[i].size)) &&
354 (first_sector == 0xffffffff))
355 {
356 first_sector = i;
357 /* all writes must start on a sector boundary... */
358 if (offset % bank->sectors[i].size)
359 {
360 LOG_INFO("offset 0x%x breaks required alignment 0x%x", offset, bank->sectors[i].size);
361 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
362 }
363 }
364 if (((offset + count) > bank->sectors[i].offset) &&
365 ((offset + count) <= (bank->sectors[i].offset + bank->sectors[i].size)) &&
366 (last_sector == 0xffffffff))
367 {
368 last_sector = i;
369 }
370 }
371
372 /* Range check... */
373 if (first_sector == 0xffffffff || last_sector == 0xffffffff)
374 {
375 LOG_INFO("Range check failed %x %x", offset, count);
376 return ERROR_FLASH_DST_OUT_OF_BANK;
377 }
378
379 /* Configure the flash controller timing */
380 lpc288x_set_flash_clk(bank);
381
382 /* initialise the offsets */
383 source_offset = 0;
384 dest_offset = 0;
385
386 for (sector = first_sector; sector <= last_sector; sector++)
387 {
388 for (page = 0; page < bank->sectors[sector].size / FLASH_PAGE_SIZE; page++)
389 {
390 if (bytes_remaining == 0)
391 {
392 count = 0;
393 memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
394 }
395 else if (bytes_remaining < FLASH_PAGE_SIZE)
396 {
397 count = bytes_remaining;
398 memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
399 memcpy(page_buffer, &buffer[source_offset], count);
400 }
401 else
402 {
403 count = FLASH_PAGE_SIZE;
404 memcpy(page_buffer, &buffer[source_offset], count);
405 }
406
407 /* Wait for flash to become ready */
408 if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
409 {
410 return ERROR_FLASH_OPERATION_FAILED;
411 }
412
413 /* fill flash data latches with 1's */
414 target_write_u32(target, F_CTRL, FC_CS | FC_SET_DATA | FC_WEN | FC_FUNC);
415
416 target_write_u32(target, F_CTRL, FC_CS | FC_WEN | FC_FUNC);
417 /*would be better to use the clean target_write_buffer() interface but
418 * it seems not to be a LOT slower....
419 * bulk_write_memory() is no quicker :(*/
420 #if 1
421 if (target->type->write_memory(target, offset + dest_offset, 4, 128, page_buffer) != ERROR_OK)
422 {
423 LOG_ERROR("Write failed s %x p %x", sector, page);
424 return ERROR_FLASH_OPERATION_FAILED;
425 }
426 #else
427 if (target_write_buffer(target, offset + dest_offset, FLASH_PAGE_SIZE, page_buffer) != ERROR_OK)
428 {
429 LOG_INFO("Write to flash buffer failed");
430 return ERROR_FLASH_OPERATION_FAILED;
431 }
432 #endif
433 dest_offset += FLASH_PAGE_SIZE;
434 source_offset += count;
435 bytes_remaining -= count;
436
437 lpc288x_load_timer(LOAD_TIMER_WRITE, target);
438
439 target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_FUNC | FC_CS);
440 }
441 }
442
443 return ERROR_OK;
444 }
445
446 int lpc288x_probe(struct flash_bank_s *bank)
447 {
448 /* we only deal with LPC2888 so flash config is fixed */
449 lpc288x_flash_bank_t *lpc288x_info = bank->driver_priv;
450 int retval;
451
452 if (lpc288x_info->cidr != 0)
453 {
454 return ERROR_OK; /* already probed */
455 }
456
457 if (bank->target->state != TARGET_HALTED)
458 {
459 LOG_ERROR("Target not halted");
460 return ERROR_TARGET_NOT_HALTED;
461 }
462
463 retval = lpc288x_read_part_info(bank);
464 if (retval != ERROR_OK)
465 return retval;
466 return ERROR_OK;
467 }
468
469 int lpc288x_info(struct flash_bank_s *bank, char *buf, int buf_size)
470 {
471 snprintf(buf, buf_size, "lpc288x flash driver");
472 return ERROR_OK;
473 }
474
475 int lpc288x_protect(struct flash_bank_s *bank, int set, int first, int last)
476 {
477 int lockregion, status;
478 u32 value;
479 target_t *target = bank->target;
480
481 /* probed? halted? */
482 status = lpc288x_system_ready(bank);
483 if (status != ERROR_OK)
484 {
485 return status;
486 }
487
488 if ((first < 0) || (last < first) || (last >= bank->num_sectors))
489 {
490 return ERROR_FLASH_SECTOR_INVALID;
491 }
492
493 /* Configure the flash controller timing */
494 lpc288x_set_flash_clk(bank);
495
496 for (lockregion = first; lockregion <= last; lockregion++)
497 {
498 if (set)
499 {
500 /* write an odd value to base addy to protect... */
501 value = 0x01;
502 }
503 else
504 {
505 /* write an even value to base addy to unprotect... */
506 value = 0x00;
507 }
508 target_write_u32(target, bank->sectors[lockregion].offset, value);
509 target_write_u32(target, F_CTRL, FC_LOAD_REQ | FC_PROTECT | FC_WEN | FC_FUNC | FC_CS);
510 }
511
512 return ERROR_OK;
513 }

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)