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