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

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)