30953942abb3e2a773908867ca24a8d7204e8cff
[fw/openocd] / 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 }