1 /***************************************************************************
\r
2 * Copyright (C) 2007 by Pavel Chromy *
\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
20 #include "samflash.h"
\r
23 unsigned int flash_page_count=1024;
\r
24 unsigned int flash_page_size=256;
\r
26 /* pages per lock bit */
\r
27 unsigned int flash_lock_pages=1024/16;
\r
30 /* detect chip and set loader parameters */
\r
31 int flash_init(void)
\r
33 unsigned int nvpsiz;
\r
35 nvpsiz=(inr(DBGU_CIDR)>>8)&0xf;
\r
40 flash_page_count=256;
\r
41 flash_page_size=128;
\r
42 flash_lock_pages=256/8;
\r
46 flash_page_count=512;
\r
47 flash_page_size=128;
\r
48 flash_lock_pages=512/16;
\r
52 flash_page_count=512;
\r
53 flash_page_size=256;
\r
54 flash_lock_pages=512/8;
\r
58 flash_page_count=1024;
\r
59 flash_page_size=256;
\r
60 flash_lock_pages=1024/16;
\r
64 flash_page_count=2048;
\r
65 flash_page_size=256;
\r
66 flash_lock_pages=2048/32;
\r
69 return FLASH_STAT_INITE;
\r
71 return FLASH_STAT_OK;
\r
75 /* program single flash page */
\r
76 int flash_page_program(uint32 *data, int page_num)
\r
84 /* select proper controller */
\r
85 if (page_num>=1024) efc_ofs=0x10;
\r
88 /* wait until FLASH is ready, just for sure */
\r
89 while ((inr(MC_FSR+efc_ofs)&MC_FRDY)==0);
\r
91 /* calculate page address, only lower 8 bits are used to address the latch,
\r
92 but the upper part of address is needed for writing to proper EFC */
\r
93 flash_ptr=(uint32 *)(FLASH_AREA_ADDR+(page_num*flash_page_size));
\r
96 /* copy data to latch */
\r
97 for (i=flash_page_size/4; i; i--) {
\r
98 /* we do not use memcpy to be sure that only 32 bit access is used */
\r
99 *(flash_ptr++)=*(data_ptr++);
\r
102 /* page number and page write command to FCR */
\r
103 outr(MC_FCR+efc_ofs, ((page_num&0x3ff)<<8) | MC_KEY | MC_FCMD_WP);
\r
105 /* wait until it's done */
\r
106 while ((inr(MC_FSR+efc_ofs)&MC_FRDY)==0);
\r
108 /* check for errors */
\r
109 if ((inr(MC_FSR+efc_ofs)&MC_PROGE)) return FLASH_STAT_PROGE;
\r
110 if ((inr(MC_FSR+efc_ofs)&MC_LOCKE)) return FLASH_STAT_LOCKE;
\r
113 /* verify written data */
\r
114 flash_ptr=(uint32 *)(FLASH_AREA_ADDR+(page_num*flash_page_size));
\r
117 for (i=flash_page_size/4; i; i--) {
\r
118 if (*(flash_ptr++)!=*(data_ptr++)) return FLASH_STAT_VERIFE;
\r
122 return FLASH_STAT_OK;
\r
126 int flash_erase_plane(int efc_ofs)
\r
128 unsigned int lockbits;
\r
132 lockbits=inr(MC_FSR+efc_ofs)>>16;
\r
136 /* wait until FLASH is ready, just for sure */
\r
137 while ((inr(MC_FSR+efc_ofs)&MC_FRDY)==0);
\r
139 outr(MC_FCR+efc_ofs, ((page_num&0x3ff)<<8) | 0x5a000004);
\r
141 /* wait until it's done */
\r
142 while ((inr(MC_FSR+efc_ofs)&MC_FRDY)==0);
\r
144 /* check for errors */
\r
145 if ((inr(MC_FSR+efc_ofs)&MC_PROGE)) return FLASH_STAT_PROGE;
\r
146 if ((inr(MC_FSR+efc_ofs)&MC_LOCKE)) return FLASH_STAT_LOCKE;
\r
149 if ((page_num+=flash_lock_pages)>flash_page_count) break;
\r
153 /* wait until FLASH is ready, just for sure */
\r
154 while ((inr(MC_FSR+efc_ofs)&MC_FRDY)==0);
\r
156 /* erase all command to FCR */
\r
157 outr(MC_FCR+efc_ofs, 0x5a000008);
\r
159 /* wait until it's done */
\r
160 while ((inr(MC_FSR+efc_ofs)&MC_FRDY)==0);
\r
162 /* check for errors */
\r
163 if ((inr(MC_FSR+efc_ofs)&MC_PROGE)) return FLASH_STAT_PROGE;
\r
164 if ((inr(MC_FSR+efc_ofs)&MC_LOCKE)) return FLASH_STAT_LOCKE;
\r
166 /* set no erase before programming */
\r
167 outr(MC_FMR+efc_ofs, inr(MC_FMR+efc_ofs)|0x80);
\r
169 return FLASH_STAT_OK;
\r
173 /* erase whole chip */
\r
174 int flash_erase_all(void)
\r
178 if ((result=flash_erase_plane(0))!=FLASH_STAT_OK) return result;
\r
180 /* the second flash controller, if any */
\r
181 if (flash_page_count>1024) result=flash_erase_plane(0x10);
\r
187 int flash_verify(uint32 adr, unsigned int len, uint8 *src)
\r
189 unsigned char *flash_ptr;
\r
191 flash_ptr=(uint8 *)FLASH_AREA_ADDR+adr;
\r
192 for ( ;len; len--) {
\r
193 if (*(flash_ptr++)!=*(src++)) return FLASH_STAT_VERIFE;
\r
195 return FLASH_STAT_OK;
\r