1 /***************************************************************************
2 * Copyright (C) 2008 by *
3 * Karl RobinSod <karl.robinsod@gmail.com> *
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. *
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. *
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 ***************************************************************************/
21 /***************************************************************************
22 * There are some things to notice
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
29 ***************************************************************************/
35 #include "binarybuffer.h"
38 #define LOAD_TIMER_ERASE 0
39 #define LOAD_TIMER_WRITE 1
41 #define FLASH_PAGE_SIZE 512
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 -*/
62 #define FC_FUNC 0x0002
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
72 #define FS_DONE 0x0001
73 #define FS_PROGGNT 0x0002
77 #define FPT_TIME_MASK 0x7FFF
79 #define FPT_ENABLE 0x8000
81 #define FW_WAIT_STATES_MASK 0x00FF
82 #define FW_SET_MASK 0xC000
85 #define FCT_CLK_DIV_MASK 0x0FFF
87 static uint32_t lpc288x_wait_status_busy(struct flash_bank
*bank
, int timeout
);
88 static void lpc288x_load_timer(int erase
, struct target
*target
);
89 static void lpc288x_set_flash_clk(struct flash_bank
*bank
);
90 static uint32_t lpc288x_system_ready(struct flash_bank
*bank
);
92 static uint32_t lpc288x_wait_status_busy(struct flash_bank
*bank
, int timeout
)
95 struct target
*target
= bank
->target
;
100 target_read_u32(target
, F_STAT
, &status
);
101 } while (((status
& FS_DONE
) == 0) && timeout
);
105 LOG_DEBUG("Timedout!");
106 return ERROR_FLASH_OPERATION_FAILED
;
111 /* Read device id register and fill in driver info structure */
112 static int lpc288x_read_part_info(struct flash_bank
*bank
)
114 struct lpc288x_flash_bank
*lpc288x_info
= bank
->driver_priv
;
115 struct target
*target
= bank
->target
;
121 if (lpc288x_info
->cidr
== 0x0102100A)
122 return ERROR_OK
; /* already probed, multiple probes may cause memory leak, not allowed */
124 /* Read and parse chip identification register */
125 target_read_u32(target
, DBGU_CIDR
, &cidr
);
127 if (cidr
!= 0x0102100A)
129 LOG_WARNING("Cannot identify target as an LPC288X (%08" PRIx32
")",cidr
);
130 return ERROR_FLASH_OPERATION_FAILED
;
133 lpc288x_info
->cidr
= cidr
;
134 lpc288x_info
->sector_size_break
= 0x000F0000;
135 lpc288x_info
->target_name
= "LPC288x";
137 /* setup the sector info... */
139 bank
->num_sectors
= 23;
140 bank
->sectors
= malloc(sizeof(struct flash_sector
) * 23);
142 for (i
= 0; i
< 15; i
++)
144 bank
->sectors
[i
].offset
= offset
;
145 bank
->sectors
[i
].size
= 64 * 1024;
146 offset
+= bank
->sectors
[i
].size
;
147 bank
->sectors
[i
].is_erased
= -1;
148 bank
->sectors
[i
].is_protected
= 1;
150 for (i
= 15; i
< 23; i
++)
152 bank
->sectors
[i
].offset
= offset
;
153 bank
->sectors
[i
].size
= 8 * 1024;
154 offset
+= bank
->sectors
[i
].size
;
155 bank
->sectors
[i
].is_erased
= -1;
156 bank
->sectors
[i
].is_protected
= 1;
162 static int lpc288x_protect_check(struct flash_bank
*bank
)
167 /* flash_bank LPC288x 0 0 0 0 <target#> <cclk> */
168 FLASH_BANK_COMMAND_HANDLER(lpc288x_flash_bank_command
)
170 struct lpc288x_flash_bank
*lpc288x_info
;
174 LOG_WARNING("incomplete flash_bank LPC288x configuration");
175 return ERROR_FLASH_BANK_INVALID
;
178 lpc288x_info
= malloc(sizeof(struct lpc288x_flash_bank
));
179 bank
->driver_priv
= lpc288x_info
;
181 /* part wasn't probed for info yet */
182 lpc288x_info
->cidr
= 0;
183 COMMAND_PARSE_NUMBER(u32
, args
[6], lpc288x_info
->cclk
);
188 /* The frequency is the AHB clock frequency divided by (CLK_DIV ×3) + 1.
189 * This must be programmed such that the Flash Programming clock frequency is 66 kHz ± 20%.
191 * 12000000/66000 = 182
193 static void lpc288x_set_flash_clk(struct flash_bank
*bank
)
196 struct lpc288x_flash_bank
*lpc288x_info
= bank
->driver_priv
;
197 clk_time
= (lpc288x_info
->cclk
/ 66000) / 3;
198 target_write_u32(bank
->target
, F_CTRL
, FC_CS
| FC_WEN
);
199 target_write_u32(bank
->target
, F_CLK_TIME
, clk_time
);
202 /* AHB tcyc (in ns) 83 ns
203 * LOAD_TIMER_ERASE FPT_TIME = ((400,000,000 / AHB tcyc (in ns)) - 2) / 512
204 * = 9412 (9500) (AN10548 9375)
205 * LOAD_TIMER_WRITE FPT_TIME = ((1,000,000 / AHB tcyc (in ns)) - 2) / 512
206 * = 23 (75) (AN10548 72 - is this wrong?)
207 * TODO: Sort out timing calcs ;) */
208 static void lpc288x_load_timer(int erase
, struct target
*target
)
210 if (erase
== LOAD_TIMER_ERASE
)
212 target_write_u32(target
, F_PROG_TIME
, FPT_ENABLE
| 9500);
216 target_write_u32(target
, F_PROG_TIME
, FPT_ENABLE
| 75);
220 static uint32_t lpc288x_system_ready(struct flash_bank
*bank
)
222 struct lpc288x_flash_bank
*lpc288x_info
= bank
->driver_priv
;
223 if (lpc288x_info
->cidr
== 0)
225 return ERROR_FLASH_BANK_NOT_PROBED
;
228 if (bank
->target
->state
!= TARGET_HALTED
)
230 LOG_ERROR("Target not halted");
231 return ERROR_TARGET_NOT_HALTED
;
236 static int lpc288x_erase_check(struct flash_bank
*bank
)
238 uint32_t status
= lpc288x_system_ready(bank
); /* probed? halted? */
239 if (status
!= ERROR_OK
)
241 LOG_INFO("Processor not halted/not probed");
248 static int lpc288x_erase(struct flash_bank
*bank
, int first
, int last
)
252 struct target
*target
= bank
->target
;
254 status
= lpc288x_system_ready(bank
); /* probed? halted? */
255 if (status
!= ERROR_OK
)
260 if ((first
< 0) || (last
< first
) || (last
>= bank
->num_sectors
))
262 LOG_INFO("Bad sector range");
263 return ERROR_FLASH_SECTOR_INVALID
;
266 /* Configure the flash controller timing */
267 lpc288x_set_flash_clk(bank
);
269 for (sector
= first
; sector
<= last
; sector
++)
271 if (lpc288x_wait_status_busy(bank
, 1000) != ERROR_OK
)
273 return ERROR_FLASH_OPERATION_FAILED
;
276 lpc288x_load_timer(LOAD_TIMER_ERASE
,target
);
278 target_write_u32(target
, bank
->sectors
[sector
].offset
, 0x00);
280 target_write_u32(target
, F_CTRL
, FC_PROG_REQ
| FC_PROTECT
| FC_CS
);
282 if (lpc288x_wait_status_busy(bank
, 1000) != ERROR_OK
)
284 return ERROR_FLASH_OPERATION_FAILED
;
289 static int lpc288x_write(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
291 uint8_t page_buffer
[FLASH_PAGE_SIZE
];
292 uint32_t status
, source_offset
,dest_offset
;
293 struct target
*target
= bank
->target
;
294 uint32_t bytes_remaining
= count
;
295 uint32_t first_sector
, last_sector
, sector
, page
;
298 /* probed? halted? */
299 status
= lpc288x_system_ready(bank
);
300 if (status
!= ERROR_OK
)
305 /* Initialise search indices */
306 first_sector
= last_sector
= 0xffffffff;
308 /* validate the write range... */
309 for (i
= 0; i
< bank
->num_sectors
; i
++)
311 if ((offset
>= bank
->sectors
[i
].offset
) &&
312 (offset
< (bank
->sectors
[i
].offset
+ bank
->sectors
[i
].size
)) &&
313 (first_sector
== 0xffffffff))
316 /* all writes must start on a sector boundary... */
317 if (offset
% bank
->sectors
[i
].size
)
319 LOG_INFO("offset 0x%" PRIx32
" breaks required alignment 0x%" PRIx32
"", offset
, bank
->sectors
[i
].size
);
320 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
323 if (((offset
+ count
) > bank
->sectors
[i
].offset
) &&
324 ((offset
+ count
) <= (bank
->sectors
[i
].offset
+ bank
->sectors
[i
].size
)) &&
325 (last_sector
== 0xffffffff))
332 if (first_sector
== 0xffffffff || last_sector
== 0xffffffff)
334 LOG_INFO("Range check failed %" PRIx32
" %" PRIx32
"", offset
, count
);
335 return ERROR_FLASH_DST_OUT_OF_BANK
;
338 /* Configure the flash controller timing */
339 lpc288x_set_flash_clk(bank
);
341 /* initialise the offsets */
345 for (sector
= first_sector
; sector
<= last_sector
; sector
++)
347 for (page
= 0; page
< bank
->sectors
[sector
].size
/ FLASH_PAGE_SIZE
; page
++)
349 if (bytes_remaining
== 0)
352 memset(page_buffer
, 0xFF, FLASH_PAGE_SIZE
);
354 else if (bytes_remaining
< FLASH_PAGE_SIZE
)
356 count
= bytes_remaining
;
357 memset(page_buffer
, 0xFF, FLASH_PAGE_SIZE
);
358 memcpy(page_buffer
, &buffer
[source_offset
], count
);
362 count
= FLASH_PAGE_SIZE
;
363 memcpy(page_buffer
, &buffer
[source_offset
], count
);
366 /* Wait for flash to become ready */
367 if (lpc288x_wait_status_busy(bank
, 1000) != ERROR_OK
)
369 return ERROR_FLASH_OPERATION_FAILED
;
372 /* fill flash data latches with 1's */
373 target_write_u32(target
, F_CTRL
, FC_CS
| FC_SET_DATA
| FC_WEN
| FC_FUNC
);
375 target_write_u32(target
, F_CTRL
, FC_CS
| FC_WEN
| FC_FUNC
);
376 /*would be better to use the clean target_write_buffer() interface but
377 * it seems not to be a LOT slower....
378 * bulk_write_memory() is no quicker :(*/
380 if (target_write_memory(target
, offset
+ dest_offset
, 4, 128, page_buffer
) != ERROR_OK
)
382 LOG_ERROR("Write failed s %" PRIx32
" p %" PRIx32
"", sector
, page
);
383 return ERROR_FLASH_OPERATION_FAILED
;
386 if (target_write_buffer(target
, offset
+ dest_offset
, FLASH_PAGE_SIZE
, page_buffer
) != ERROR_OK
)
388 LOG_INFO("Write to flash buffer failed");
389 return ERROR_FLASH_OPERATION_FAILED
;
392 dest_offset
+= FLASH_PAGE_SIZE
;
393 source_offset
+= count
;
394 bytes_remaining
-= count
;
396 lpc288x_load_timer(LOAD_TIMER_WRITE
, target
);
398 target_write_u32(target
, F_CTRL
, FC_PROG_REQ
| FC_PROTECT
| FC_FUNC
| FC_CS
);
405 static int lpc288x_probe(struct flash_bank
*bank
)
407 /* we only deal with LPC2888 so flash config is fixed */
408 struct lpc288x_flash_bank
*lpc288x_info
= bank
->driver_priv
;
411 if (lpc288x_info
->cidr
!= 0)
413 return ERROR_OK
; /* already probed */
416 if (bank
->target
->state
!= TARGET_HALTED
)
418 LOG_ERROR("Target not halted");
419 return ERROR_TARGET_NOT_HALTED
;
422 retval
= lpc288x_read_part_info(bank
);
423 if (retval
!= ERROR_OK
)
428 static int lpc288x_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
430 snprintf(buf
, buf_size
, "lpc288x flash driver");
434 static int lpc288x_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
436 int lockregion
, status
;
438 struct target
*target
= bank
->target
;
440 /* probed? halted? */
441 status
= lpc288x_system_ready(bank
);
442 if (status
!= ERROR_OK
)
447 if ((first
< 0) || (last
< first
) || (last
>= bank
->num_sectors
))
449 return ERROR_FLASH_SECTOR_INVALID
;
452 /* Configure the flash controller timing */
453 lpc288x_set_flash_clk(bank
);
455 for (lockregion
= first
; lockregion
<= last
; lockregion
++)
459 /* write an odd value to base addy to protect... */
464 /* write an even value to base addy to unprotect... */
467 target_write_u32(target
, bank
->sectors
[lockregion
].offset
, value
);
468 target_write_u32(target
, F_CTRL
, FC_LOAD_REQ
| FC_PROTECT
| FC_WEN
| FC_FUNC
| FC_CS
);
474 struct flash_driver lpc288x_flash
= {
476 .flash_bank_command
= &lpc288x_flash_bank_command
,
477 .erase
= &lpc288x_erase
,
478 .protect
= &lpc288x_protect
,
479 .write
= &lpc288x_write
,
480 .probe
= &lpc288x_probe
,
481 .auto_probe
= &lpc288x_probe
,
482 .erase_check
= &lpc288x_erase_check
,
483 .protect_check
= &lpc288x_protect_check
,
484 .info
= &lpc288x_info
,