1 /***************************************************************************
\r
2 * Copyright (C) 2008 by *
\r
3 * Karl RobinSod <karl.robinsod@gmail.com> *
\r
5 * This program is free software; you can redistribute it and/or modify *
\r
6 * it under the terms of the GNU General Public License as published by *
\r
7 * the Free Software Foundation; either version 2 of the License, or *
\r
8 * (at your option) any later version. *
\r
10 * This program is distributed in the hope that it will be useful, *
\r
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
\r
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
\r
13 * GNU General Public License for more details. *
\r
15 * You should have received a copy of the GNU General Public License *
\r
16 * along with this program; if not, write to the *
\r
17 * Free Software Foundation, Inc., *
\r
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
\r
19 ***************************************************************************/
\r
21 /***************************************************************************
\r
22 * There are some things to notice
\r
24 * You need to unprotect flash sectors each time you connect the OpenOCD
\r
25 * Dumping 1MB takes about 60 Seconds
\r
26 * Full erase (sectors 0-22 inclusive) takes 2-4 seconds
\r
27 * Writing 1MB takes 88 seconds
\r
29 ***************************************************************************/
\r
30 #ifdef HAVE_CONFIG_H
\r
34 #include "replacements.h"
\r
36 #include "lpc288x.h"
\r
41 #include "binarybuffer.h"
\r
48 #define LOAD_TIMER_ERASE 0
\r
49 #define LOAD_TIMER_WRITE 1
\r
51 #define FLASH_PAGE_SIZE 512
\r
53 /* LPC288X control registers */
\r
54 #define DBGU_CIDR 0x8000507C
\r
55 /* LPC288X flash registers */
\r
56 #define F_CTRL 0x80102000 /* Flash control register R/W 0x5 */
\r
57 #define F_STAT 0x80102004 /* Flash status register RO 0x45 */
\r
58 #define F_PROG_TIME 0x80102008 /* Flash program time register R/W 0 */
\r
59 #define F_WAIT 0x80102010 /* Flash read wait state register R/W 0xC004 */
\r
60 #define F_CLK_TIME 0x8010201C /* Flash clock divider for 66 kHz generation R/W 0 */
\r
61 #define F_INTEN_CLR 0x80102FD8 /* Clear interrupt enable bits WO - */
\r
62 #define F_INTEN_SET 0x80102FDC /* Set interrupt enable bits WO - */
\r
63 #define F_INT_STAT 0x80102FE0 /* Interrupt status bits RO 0 */
\r
64 #define F_INTEN 0x80102FE4 /* Interrupt enable bits RO 0 */
\r
65 #define F_INT_CLR 0x80102FE8 /* Clear interrupt status bits WO */
\r
66 #define F_INT_SET 0x80102FEC /* Set interrupt status bits WO - */
\r
67 #define FLASH_PD 0x80005030 /* Allows turning off the Flash memory for power savings. R/W 1*/
\r
68 #define FLASH_INIT 0x80005034 /* Monitors Flash readiness, such as recovery from Power Down mode. R/W -*/
\r
71 #define FC_CS 0x0001
\r
72 #define FC_FUNC 0x0002
\r
73 #define FC_WEN 0x0004
\r
74 #define FC_RD_LATCH 0x0020
\r
75 #define FC_PROTECT 0x0080
\r
76 #define FC_SET_DATA 0x0400
\r
77 #define FC_RSSL 0x0800
\r
78 #define FC_PROG_REQ 0x1000
\r
79 #define FC_CLR_BUF 0x4000
\r
80 #define FC_LOAD_REQ 0x8000
\r
82 #define FS_DONE 0x0001
\r
83 #define FS_PROGGNT 0x0002
\r
84 #define FS_RDY 0x0004
\r
85 #define FS_ERR 0x0020
\r
87 #define FPT_TIME_MASK 0x7FFF
\r
89 #define FPT_ENABLE 0x8000
\r
91 #define FW_WAIT_STATES_MASK 0x00FF
\r
92 #define FW_SET_MASK 0xC000
\r
95 #define FCT_CLK_DIV_MASK 0x0FFF
\r
99 int lpc288x_register_commands(struct command_context_s *cmd_ctx);
\r
100 int lpc288x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
\r
101 int lpc288x_erase(struct flash_bank_s *bank, int first, int last);
\r
102 int lpc288x_protect(struct flash_bank_s *bank, int set, int first, int last);
\r
103 int lpc288x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
\r
104 int lpc288x_probe(struct flash_bank_s *bank);
\r
105 int lpc288x_auto_probe(struct flash_bank_s *bank);
\r
106 int lpc288x_erase_check(struct flash_bank_s *bank);
\r
107 int lpc288x_protect_check(struct flash_bank_s *bank);
\r
108 int lpc288x_info(struct flash_bank_s *bank, char *buf, int buf_size);
\r
109 void lpc288x_set_flash_mode(flash_bank_t *bank, u8 flashplane, int mode);
\r
110 u32 lpc288x_wait_status_busy(flash_bank_t *bank, int timeout);
\r
111 void lpc288x_load_timer(int erase, struct target_s *target);
\r
112 void lpc288x_set_flash_clk(struct flash_bank_s *bank);
\r
113 u32 lpc288x_system_ready(struct flash_bank_s *bank);
\r
114 int lpc288x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
\r
116 flash_driver_t lpc288x_flash =
\r
119 .register_commands = lpc288x_register_commands,
\r
120 .flash_bank_command = lpc288x_flash_bank_command,
\r
121 .erase = lpc288x_erase,
\r
122 .protect = lpc288x_protect,
\r
123 .write = lpc288x_write,
\r
124 .probe = lpc288x_probe,
\r
125 .auto_probe = lpc288x_probe,
\r
126 .erase_check = lpc288x_erase_check,
\r
127 .protect_check = lpc288x_protect_check,
\r
128 .info = lpc288x_info
\r
132 int lpc288x_register_commands(struct command_context_s *cmd_ctx)
\r
139 u32 lpc288x_wait_status_busy(flash_bank_t *bank, int timeout)
\r
142 target_t *target = bank->target;
\r
147 target_read_u32(target, F_STAT, &status);
\r
148 }while (((status & FS_DONE) == 0) && timeout);
\r
152 LOG_DEBUG("Timedout!");
\r
153 return ERROR_FLASH_OPERATION_FAILED;
\r
158 /* Read device id register and fill in driver info structure */
\r
159 int lpc288x_read_part_info(struct flash_bank_s *bank)
\r
161 lpc288x_flash_bank_t *lpc288x_info = bank->driver_priv;
\r
162 target_t *target = bank->target;
\r
169 if (lpc288x_info->cidr == 0x0102100A)
\r
170 return ERROR_OK; /* already probed, multiple probes may cause memory leak, not allowed */
\r
172 /* Read and parse chip identification register */
\r
173 target_read_u32(target, DBGU_CIDR, &cidr);
\r
175 if (cidr != 0x0102100A)
\r
177 LOG_WARNING("Cannot identify target as an LPC288X (%08X)",cidr);
\r
178 return ERROR_FLASH_OPERATION_FAILED;
\r
181 lpc288x_info->cidr = cidr;
\r
182 lpc288x_info->sector_size_break = 0x000F0000;
\r
183 lpc288x_info->target_name = "LPC288x";
\r
185 /* setup the sector info... */
\r
186 offset = bank->base;
\r
187 bank->num_sectors = 23;
\r
188 bank->sectors = malloc(sizeof(flash_sector_t) * 23);
\r
190 for (i = 0; i < 15; i++)
\r
192 bank->sectors[i].offset = offset;
\r
193 bank->sectors[i].size = 64 * 1024;
\r
194 offset += bank->sectors[i].size;
\r
195 bank->sectors[i].is_erased = -1;
\r
196 bank->sectors[i].is_protected = 1;
\r
198 for (i = 15; i < 23; i++)
\r
200 bank->sectors[i].offset = offset;
\r
201 bank->sectors[i].size = 8 * 1024;
\r
202 offset += bank->sectors[i].size;
\r
203 bank->sectors[i].is_erased = -1;
\r
204 bank->sectors[i].is_protected = 1;
\r
210 int lpc288x_protect_check(struct flash_bank_s *bank)
\r
215 /* flash_bank LPC288x 0 0 0 0 <target#> <cclk>
\r
217 int lpc288x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
\r
219 lpc288x_flash_bank_t *lpc288x_info;
\r
224 LOG_WARNING("incomplete flash_bank LPC288x configuration");
\r
225 return ERROR_FLASH_BANK_INVALID;
\r
228 lpc288x_info = malloc(sizeof(lpc288x_flash_bank_t));
\r
229 bank->driver_priv = lpc288x_info;
\r
231 /* part wasn't probed for info yet */
\r
232 lpc288x_info->cidr = 0;
\r
233 lpc288x_info->cclk = strtoul(args[6], NULL, 0);
\r
239 The frequency is the AHB clock frequency divided by (CLK_DIV ×
\r
240 3) + 1. This must be programmed such that the Flash
\r
241 Programming clock frequency is 66 kHz ± 20%.
\r
243 12000000/66000 = 182
\r
246 void lpc288x_set_flash_clk(struct flash_bank_s *bank)
\r
249 lpc288x_flash_bank_t *lpc288x_info = bank->driver_priv;
\r
250 clk_time = (lpc288x_info->cclk / 66000) / 3;
\r
251 target_write_u32(bank->target, F_CTRL, FC_CS | FC_WEN );
\r
252 target_write_u32(bank->target, F_CLK_TIME, clk_time);
\r
256 AHB tcyc (in ns) 83 ns
\r
258 LOAD_TIMER_ERASE FPT_TIME = ((400,000,000 / AHB tcyc (in ns)) - 2) / 512
\r
259 = 9412 (9500) (AN10548 9375)
\r
260 LOAD_TIMER_WRITE FPT_TIME = ((1,000,000 / AHB tcyc (in ns)) - 2) / 512
\r
261 = 23 (75) (AN10548 72 - is this wrong?)
\r
263 TODO: Sort out timing calcs ;)
\r
265 void lpc288x_load_timer(int erase, struct target_s *target)
\r
267 if(erase == LOAD_TIMER_ERASE)
\r
269 target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 9500);
\r
273 target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 75);
\r
279 u32 lpc288x_system_ready(struct flash_bank_s *bank)
\r
281 lpc288x_flash_bank_t *lpc288x_info = bank->driver_priv;
\r
282 if (lpc288x_info->cidr == 0)
\r
284 return ERROR_FLASH_BANK_NOT_PROBED;
\r
287 if (bank->target->state != TARGET_HALTED)
\r
289 return ERROR_TARGET_NOT_HALTED;
\r
294 int lpc288x_erase_check(struct flash_bank_s *bank)
\r
296 u32 buffer, test_bytes;
\r
297 u32 addr, sector, i, status = lpc288x_system_ready(bank); /* probed? halted? */
\r
298 if(status != ERROR_OK)
\r
300 LOG_INFO("Processor not halted/not probed");
\r
307 int lpc288x_erase(struct flash_bank_s *bank, int first, int last)
\r
311 target_t *target = bank->target;
\r
313 status = lpc288x_system_ready(bank); /* probed? halted? */
\r
314 if(status != ERROR_OK)
\r
319 if ((first < 0) || (last < first) || (last >= bank->num_sectors))
\r
321 LOG_INFO("Bad sector range");
\r
322 return ERROR_FLASH_SECTOR_INVALID;
\r
325 /* Configure the flash controller timing */
\r
326 lpc288x_set_flash_clk(bank);
\r
328 for (sector = first; sector <= last; sector++)
\r
330 if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
\r
332 return ERROR_FLASH_OPERATION_FAILED;
\r
335 lpc288x_load_timer(LOAD_TIMER_ERASE,target);
\r
337 target_write_u32( target,
\r
338 bank->sectors[sector].offset,
\r
341 target_write_u32( target,
\r
347 if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
\r
349 return ERROR_FLASH_OPERATION_FAILED;
\r
356 int lpc288x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
\r
358 u8 page_buffer[FLASH_PAGE_SIZE];
\r
359 u32 i, status, source_offset,dest_offset;
\r
360 target_t *target = bank->target;
\r
361 u32 bytes_remaining = count;
\r
362 u32 first_sector, last_sector, sector, page;
\r
364 /* probed? halted? */
\r
365 status = lpc288x_system_ready(bank);
\r
366 if(status != ERROR_OK)
\r
371 /* Initialise search indices */
\r
372 first_sector = last_sector = 0xffffffff;
\r
374 /* validate the write range... */
\r
375 for(i = 0; i < bank->num_sectors; i++)
\r
377 if((offset >= bank->sectors[i].offset) &&
\r
378 (offset < (bank->sectors[i].offset + bank->sectors[i].size)) &&
\r
379 (first_sector == 0xffffffff))
\r
382 /* all writes must start on a sector boundary... */
\r
383 if (offset % bank->sectors[i].size)
\r
385 LOG_INFO("offset 0x%x breaks required alignment 0x%x", offset, bank->sectors[i].size);
\r
386 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
\r
389 if(((offset + count) > bank->sectors[i].offset) &&
\r
390 ((offset + count) <= (bank->sectors[i].offset + bank->sectors[i].size)) &&
\r
391 (last_sector == 0xffffffff))
\r
397 /* Range check... */
\r
398 if (first_sector == 0xffffffff || last_sector == 0xffffffff)
\r
400 LOG_INFO("Range check failed %x %x", offset, count);
\r
401 return ERROR_FLASH_DST_OUT_OF_BANK;
\r
404 /* Configure the flash controller timing */
\r
405 lpc288x_set_flash_clk(bank);
\r
407 /* initialise the offsets */
\r
411 for (sector=first_sector; sector<=last_sector; sector++)
\r
413 for(page = 0; page < bank->sectors[sector].size / FLASH_PAGE_SIZE; page++)
\r
415 if(bytes_remaining == 0)
\r
418 memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
\r
420 else if (bytes_remaining < FLASH_PAGE_SIZE)
\r
422 count = bytes_remaining;
\r
423 memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
\r
424 memcpy(page_buffer, &buffer[source_offset], count);
\r
428 count = FLASH_PAGE_SIZE;
\r
429 memcpy(page_buffer, &buffer[source_offset], count);
\r
432 /* Wait for flash to become ready */
\r
433 if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
\r
435 return ERROR_FLASH_OPERATION_FAILED;
\r
438 /* fill flash data latches with 1's */
\r
439 target_write_u32(target, F_CTRL,
\r
445 target_write_u32(target, F_CTRL,
\r
449 /*would be better to use the clean target_write_buffer() interface but
\r
450 it seems not to be a LOT slower....
\r
451 bulk_write_memory() is no quicker :(*/
\r
453 if (target->type->write_memory(target, offset + dest_offset, 4, 128, page_buffer) != ERROR_OK)
\r
455 LOG_ERROR("Write failed s %x p %x", sector, page);
\r
456 return ERROR_FLASH_OPERATION_FAILED;
\r
459 if(target_write_buffer(target, offset + dest_offset, FLASH_PAGE_SIZE, page_buffer) != ERROR_OK)
\r
461 LOG_INFO("Write to flash buffer failed");
\r
462 return ERROR_FLASH_OPERATION_FAILED;
\r
465 dest_offset += FLASH_PAGE_SIZE;
\r
466 source_offset += count;
\r
467 bytes_remaining -= count;
\r
469 lpc288x_load_timer(LOAD_TIMER_WRITE, target);
\r
471 target_write_u32( target,
\r
486 int lpc288x_probe(struct flash_bank_s *bank)
\r
488 /* we only deal with LPC2888 so flash config is fixed
\r
490 lpc288x_flash_bank_t *lpc288x_info = bank->driver_priv;
\r
493 if (lpc288x_info->cidr != 0)
\r
495 return ERROR_OK; /* already probed */
\r
498 if (bank->target->state != TARGET_HALTED)
\r
500 return ERROR_TARGET_NOT_HALTED;
\r
503 retval = lpc288x_read_part_info(bank);
\r
504 if (retval != ERROR_OK)
\r
511 int lpc288x_info(struct flash_bank_s *bank, char *buf, int buf_size)
\r
513 snprintf(buf, buf_size, "lpc288x flash driver");
\r
517 int lpc288x_protect(struct flash_bank_s *bank, int set, int first, int last)
\r
519 int lockregion, status;
\r
521 target_t *target = bank->target;
\r
523 /* probed? halted? */
\r
524 status = lpc288x_system_ready(bank);
\r
525 if(status != ERROR_OK)
\r
530 if ((first < 0) || (last < first) || (last >= bank->num_sectors))
\r
532 return ERROR_FLASH_SECTOR_INVALID;
\r
535 /* Configure the flash controller timing */
\r
536 lpc288x_set_flash_clk(bank);
\r
538 for (lockregion = first; lockregion <= last; lockregion++)
\r
542 /* write an odd value to base addy to protect... */
\r
547 /* write an even value to base addy to unprotect... */
\r
550 target_write_u32( target,
\r
551 bank->sectors[lockregion].offset,
\r
554 target_write_u32( target,
\r