Remove FSF mailing address.
[openocd.git] / contrib / loaders / flash / at91sam7x / samflash.c
1 /***************************************************************************
2 * Copyright (C) 2007 by Pavel Chromy *
3 * chromy@asix.cz *
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, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
18 #include "samflash.h"
19
20
21 unsigned int flash_page_count = 1024;
22 unsigned int flash_page_size = 256;
23
24 /* pages per lock bit */
25 unsigned int flash_lock_pages = 1024/16;
26
27
28 /* detect chip and set loader parameters */
29 int flash_init(void)
30 {
31 unsigned int nvpsiz;
32
33 nvpsiz = (inr(DBGU_CIDR) >> 8)&0xf;
34
35 switch (nvpsiz) {
36 case 3:
37 /* AT91SAM7x32 */
38 flash_page_count = 256;
39 flash_page_size = 128;
40 flash_lock_pages = 256/8;
41 break;
42 case 5:
43 /* AT91SAM7x64 */
44 flash_page_count = 512;
45 flash_page_size = 128;
46 flash_lock_pages = 512/16;
47 break;
48 case 7:
49 /* AT91SAM7x128*/
50 flash_page_count = 512;
51 flash_page_size = 256;
52 flash_lock_pages = 512/8;
53 break;
54 case 9:
55 /* AT91SAM7x256 */
56 flash_page_count = 1024;
57 flash_page_size = 256;
58 flash_lock_pages = 1024/16;
59 break;
60 case 10:
61 /* AT91SAM7x512 */
62 flash_page_count = 2048;
63 flash_page_size = 256;
64 flash_lock_pages = 2048/32;
65 break;
66 default:
67 return FLASH_STAT_INITE;
68 }
69 return FLASH_STAT_OK;
70 }
71
72
73 /* program single flash page */
74 int flash_page_program(uint32 *data, int page_num)
75 {
76 int i;
77 int efc_ofs;
78
79 uint32 *flash_ptr;
80 uint32 *data_ptr;
81
82 /* select proper controller */
83 if (page_num >= 1024) efc_ofs = 0x10;
84 else efc_ofs = 0;
85
86 /* wait until FLASH is ready, just for sure */
87 while ((inr(MC_FSR + efc_ofs)&MC_FRDY) == 0);
88
89 /* calculate page address, only lower 8 bits are used to address the latch,
90 but the upper part of address is needed for writing to proper EFC */
91 flash_ptr = (uint32 *)(FLASH_AREA_ADDR + (page_num*flash_page_size));
92 data_ptr = data;
93
94 /* copy data to latch */
95 for (i = flash_page_size/4; i; i--) {
96 /* we do not use memcpy to be sure that only 32 bit access is used */
97 *(flash_ptr++)=*(data_ptr++);
98 }
99
100 /* page number and page write command to FCR */
101 outr(MC_FCR + efc_ofs, ((page_num&0x3ff) << 8) | MC_KEY | MC_FCMD_WP);
102
103 /* wait until it's done */
104 while ((inr(MC_FSR + efc_ofs)&MC_FRDY) == 0);
105
106 /* check for errors */
107 if ((inr(MC_FSR + efc_ofs)&MC_PROGE)) return FLASH_STAT_PROGE;
108 if ((inr(MC_FSR + efc_ofs)&MC_LOCKE)) return FLASH_STAT_LOCKE;
109
110 #if 0
111 /* verify written data */
112 flash_ptr = (uint32 *)(FLASH_AREA_ADDR + (page_num*flash_page_size));
113 data_ptr = data;
114
115 for (i = flash_page_size/4; i; i--) {
116 if (*(flash_ptr++)!=*(data_ptr++)) return FLASH_STAT_VERIFE;
117 }
118 #endif
119
120 return FLASH_STAT_OK;
121 }
122
123
124 int flash_erase_plane(int efc_ofs)
125 {
126 unsigned int lockbits;
127 int page_num;
128
129 page_num = 0;
130 lockbits = inr(MC_FSR + efc_ofs) >> 16;
131 while (lockbits) {
132 if (lockbits&1) {
133
134 /* wait until FLASH is ready, just for sure */
135 while ((inr(MC_FSR + efc_ofs)&MC_FRDY) == 0);
136
137 outr(MC_FCR + efc_ofs, ((page_num&0x3ff) << 8) | 0x5a000004);
138
139 /* wait until it's done */
140 while ((inr(MC_FSR + efc_ofs)&MC_FRDY) == 0);
141
142 /* check for errors */
143 if ((inr(MC_FSR + efc_ofs)&MC_PROGE)) return FLASH_STAT_PROGE;
144 if ((inr(MC_FSR + efc_ofs)&MC_LOCKE)) return FLASH_STAT_LOCKE;
145
146 }
147 if ((page_num += flash_lock_pages) > flash_page_count) break;
148 lockbits>>=1;
149 }
150
151 /* wait until FLASH is ready, just for sure */
152 while ((inr(MC_FSR + efc_ofs)&MC_FRDY) == 0);
153
154 /* erase all command to FCR */
155 outr(MC_FCR + efc_ofs, 0x5a000008);
156
157 /* wait until it's done */
158 while ((inr(MC_FSR + efc_ofs)&MC_FRDY) == 0);
159
160 /* check for errors */
161 if ((inr(MC_FSR + efc_ofs)&MC_PROGE)) return FLASH_STAT_PROGE;
162 if ((inr(MC_FSR + efc_ofs)&MC_LOCKE)) return FLASH_STAT_LOCKE;
163
164 /* set no erase before programming */
165 outr(MC_FMR + efc_ofs, inr(MC_FMR + efc_ofs) | 0x80);
166
167 return FLASH_STAT_OK;
168 }
169
170
171 /* erase whole chip */
172 int flash_erase_all(void)
173 {
174 int result;
175
176 if ((result = flash_erase_plane(0)) != FLASH_STAT_OK) return result;
177
178 /* the second flash controller, if any */
179 if (flash_page_count > 1024) result = flash_erase_plane(0x10);
180
181 return result;
182 }
183
184
185 int flash_verify(uint32 adr, unsigned int len, uint8 *src)
186 {
187 unsigned char *flash_ptr;
188
189 flash_ptr = (uint8 *)FLASH_AREA_ADDR + adr;
190 for (;len; len--) {
191 if (*(flash_ptr++)!=*(src++)) return FLASH_STAT_VERIFE;
192 }
193 return FLASH_STAT_OK;
194 }