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

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)