mirror of
https://git.code.sf.net/p/openocd/code
synced 2025-09-19 12:50:11 +00:00
The coding style requires the 'case' to be at the same indentation level of its 'switch' statement. Align the code accordingly. While there: - add space around operators; - remove space after cast. Skip the file contrib/firmware/angie/c/src/usb.c as it's going to be modified by a patch already pending in gerrit. No changes are reported by git log -p -w --ignore-blank-lines --patience Change-Id: I0bebd6d0cc95ddecd5794cc4c12c8412b38691e9 Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> Reviewed-on: https://review.openocd.org/c/openocd/+/9046 Tested-by: jenkins
184 lines
4.3 KiB
C
184 lines
4.3 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
/***************************************************************************
|
|
* Copyright (C) 2007 by Pavel Chromy *
|
|
* chromy@asix.cz *
|
|
***************************************************************************/
|
|
#include "samflash.h"
|
|
|
|
|
|
unsigned int flash_page_count = 1024;
|
|
unsigned int flash_page_size = 256;
|
|
|
|
/* pages per lock bit */
|
|
unsigned int flash_lock_pages = 1024/16;
|
|
|
|
|
|
/* detect chip and set loader parameters */
|
|
int flash_init(void)
|
|
{
|
|
unsigned int nvpsiz;
|
|
|
|
nvpsiz = (inr(DBGU_CIDR) >> 8)&0xf;
|
|
|
|
switch (nvpsiz) {
|
|
case 3:
|
|
/* AT91SAM7x32 */
|
|
flash_page_count = 256;
|
|
flash_page_size = 128;
|
|
flash_lock_pages = 256 / 8;
|
|
break;
|
|
case 5:
|
|
/* AT91SAM7x64 */
|
|
flash_page_count = 512;
|
|
flash_page_size = 128;
|
|
flash_lock_pages = 512 / 16;
|
|
break;
|
|
case 7:
|
|
/* AT91SAM7x128*/
|
|
flash_page_count = 512;
|
|
flash_page_size = 256;
|
|
flash_lock_pages = 512 / 8;
|
|
break;
|
|
case 9:
|
|
/* AT91SAM7x256 */
|
|
flash_page_count = 1024;
|
|
flash_page_size = 256;
|
|
flash_lock_pages = 1024 / 16;
|
|
break;
|
|
case 10:
|
|
/* AT91SAM7x512 */
|
|
flash_page_count = 2048;
|
|
flash_page_size = 256;
|
|
flash_lock_pages = 2048 / 32;
|
|
break;
|
|
default:
|
|
return FLASH_STAT_INITE;
|
|
}
|
|
return FLASH_STAT_OK;
|
|
}
|
|
|
|
|
|
/* program single flash page */
|
|
int flash_page_program(uint32 *data, int page_num)
|
|
{
|
|
int i;
|
|
int efc_ofs;
|
|
|
|
uint32 *flash_ptr;
|
|
uint32 *data_ptr;
|
|
|
|
/* select proper controller */
|
|
if (page_num >= 1024) efc_ofs = 0x10;
|
|
else efc_ofs = 0;
|
|
|
|
/* wait until FLASH is ready, just for sure */
|
|
while ((inr(MC_FSR + efc_ofs)&MC_FRDY) == 0);
|
|
|
|
/* calculate page address, only lower 8 bits are used to address the latch,
|
|
but the upper part of address is needed for writing to proper EFC */
|
|
flash_ptr = (uint32 *)(FLASH_AREA_ADDR + (page_num*flash_page_size));
|
|
data_ptr = data;
|
|
|
|
/* copy data to latch */
|
|
for (i = flash_page_size/4; i; i--) {
|
|
/* we do not use memcpy to be sure that only 32 bit access is used */
|
|
*(flash_ptr++)=*(data_ptr++);
|
|
}
|
|
|
|
/* page number and page write command to FCR */
|
|
outr(MC_FCR + efc_ofs, ((page_num&0x3ff) << 8) | MC_KEY | MC_FCMD_WP);
|
|
|
|
/* wait until it's done */
|
|
while ((inr(MC_FSR + efc_ofs)&MC_FRDY) == 0);
|
|
|
|
/* check for errors */
|
|
if ((inr(MC_FSR + efc_ofs)&MC_PROGE)) return FLASH_STAT_PROGE;
|
|
if ((inr(MC_FSR + efc_ofs)&MC_LOCKE)) return FLASH_STAT_LOCKE;
|
|
|
|
#if 0
|
|
/* verify written data */
|
|
flash_ptr = (uint32 *)(FLASH_AREA_ADDR + (page_num*flash_page_size));
|
|
data_ptr = data;
|
|
|
|
for (i = flash_page_size/4; i; i--) {
|
|
if (*(flash_ptr++)!=*(data_ptr++)) return FLASH_STAT_VERIFE;
|
|
}
|
|
#endif
|
|
|
|
return FLASH_STAT_OK;
|
|
}
|
|
|
|
|
|
int flash_erase_plane(int efc_ofs)
|
|
{
|
|
unsigned int lockbits;
|
|
int page_num;
|
|
|
|
page_num = 0;
|
|
lockbits = inr(MC_FSR + efc_ofs) >> 16;
|
|
while (lockbits) {
|
|
if (lockbits&1) {
|
|
|
|
/* wait until FLASH is ready, just for sure */
|
|
while ((inr(MC_FSR + efc_ofs)&MC_FRDY) == 0);
|
|
|
|
outr(MC_FCR + efc_ofs, ((page_num&0x3ff) << 8) | 0x5a000004);
|
|
|
|
/* wait until it's done */
|
|
while ((inr(MC_FSR + efc_ofs)&MC_FRDY) == 0);
|
|
|
|
/* check for errors */
|
|
if ((inr(MC_FSR + efc_ofs)&MC_PROGE)) return FLASH_STAT_PROGE;
|
|
if ((inr(MC_FSR + efc_ofs)&MC_LOCKE)) return FLASH_STAT_LOCKE;
|
|
|
|
}
|
|
if ((page_num += flash_lock_pages) > flash_page_count) break;
|
|
lockbits>>=1;
|
|
}
|
|
|
|
/* wait until FLASH is ready, just for sure */
|
|
while ((inr(MC_FSR + efc_ofs)&MC_FRDY) == 0);
|
|
|
|
/* erase all command to FCR */
|
|
outr(MC_FCR + efc_ofs, 0x5a000008);
|
|
|
|
/* wait until it's done */
|
|
while ((inr(MC_FSR + efc_ofs)&MC_FRDY) == 0);
|
|
|
|
/* check for errors */
|
|
if ((inr(MC_FSR + efc_ofs)&MC_PROGE)) return FLASH_STAT_PROGE;
|
|
if ((inr(MC_FSR + efc_ofs)&MC_LOCKE)) return FLASH_STAT_LOCKE;
|
|
|
|
/* set no erase before programming */
|
|
outr(MC_FMR + efc_ofs, inr(MC_FMR + efc_ofs) | 0x80);
|
|
|
|
return FLASH_STAT_OK;
|
|
}
|
|
|
|
|
|
/* erase whole chip */
|
|
int flash_erase_all(void)
|
|
{
|
|
int result;
|
|
|
|
if ((result = flash_erase_plane(0)) != FLASH_STAT_OK) return result;
|
|
|
|
/* the second flash controller, if any */
|
|
if (flash_page_count > 1024) result = flash_erase_plane(0x10);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
int flash_verify(uint32 adr, unsigned int len, uint8 *src)
|
|
{
|
|
unsigned char *flash_ptr;
|
|
|
|
flash_ptr = (uint8 *)FLASH_AREA_ADDR + adr;
|
|
for (;len; len--) {
|
|
if (*(flash_ptr++)!=*(src++)) return FLASH_STAT_VERIFE;
|
|
}
|
|
return FLASH_STAT_OK;
|
|
}
|