blob: 85cbc5f783febdb2d4a5c3d9c6313018ced39c2d [file] [log] [blame]
wdenk381669a2003-06-16 23:50:08 +00001/* LowLevel function for ATMEL DataFlash support
2 * Author : Hamid Ikdoumi (Atmel)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
17 * MA 02111-1307 USA
18 *
19 */
20#include <common.h>
21#include <config.h>
22#ifdef CONFIG_HAS_DATAFLASH
23#include <asm/hardware.h>
24#include <dataflash.h>
25
26AT91S_DATAFLASH_INFO dataflash_info[CFG_MAX_DATAFLASH_BANKS];
27static AT91S_DataFlash DataFlashInst;
28
Stelian Pop05a333b2008-01-20 21:07:00 +000029struct dataflash_addr {
30 unsigned long addr;
31 int cs;
32};
33
Stelian Pop03c684d2008-03-26 21:52:36 +010034#if defined(CONFIG_AT91SAM9260EK)
Stelian Pop05a333b2008-01-20 21:07:00 +000035struct dataflash_addr cs[CFG_MAX_DATAFLASH_BANKS] = {
wdenk381669a2003-06-16 23:50:08 +000036 {CFG_DATAFLASH_LOGIC_ADDR_CS0, 0}, /* Logical adress, CS */
Peter Pearsede5b02c2007-08-14 10:10:52 +010037 {CFG_DATAFLASH_LOGIC_ADDR_CS1, 1}
38};
Stelian Pop6c939742008-01-20 19:49:21 +000039#elif defined(CONFIG_AT91SAM9263EK) || defined(CONFIG_AT91CAP9ADK)
Stelian Pop05a333b2008-01-20 21:07:00 +000040struct dataflash_addr cs[CFG_MAX_DATAFLASH_BANKS] = {
41 {CFG_DATAFLASH_LOGIC_ADDR_CS0, 0}, /* Logical adress, CS */
Peter Pearsede5b02c2007-08-14 10:10:52 +010042};
43#else
Stelian Pop05a333b2008-01-20 21:07:00 +000044struct dataflash_addr cs[CFG_MAX_DATAFLASH_BANKS] = {
Peter Pearsede5b02c2007-08-14 10:10:52 +010045 {CFG_DATAFLASH_LOGIC_ADDR_CS0, 0}, /* Logical adress, CS */
wdenk381669a2003-06-16 23:50:08 +000046 {CFG_DATAFLASH_LOGIC_ADDR_CS3, 3}
47};
Peter Pearsede5b02c2007-08-14 10:10:52 +010048#endif
wdenk381669a2003-06-16 23:50:08 +000049
wdenk86765902003-12-06 23:55:10 +000050/*define the area offsets*/
Peter Pearsede5b02c2007-08-14 10:10:52 +010051dataflash_protect_t area_list[NB_DATAFLASH_AREA] = {
Stelian Pop03c684d2008-03-26 21:52:36 +010052 {0x00000000, 0x000041FF, FLAG_PROTECT_SET, 0, "Bootstrap"},
53 {0x00004200, 0x000083FF, FLAG_PROTECT_CLEAR, 0, "Environment"},
54 {0x00008400, 0x0003DDFF, FLAG_PROTECT_SET, 0, "U-Boot"},
55 {0x0003DE00, 0x0023DE3F, FLAG_PROTECT_CLEAR, 0, "Kernel"},
56 {0x0023DE40, 0xFFFFFFFF, FLAG_PROTECT_CLEAR, 0, "FS"},
Peter Pearsede5b02c2007-08-14 10:10:52 +010057};
wdenk86765902003-12-06 23:55:10 +000058
wdenk381669a2003-06-16 23:50:08 +000059extern void AT91F_SpiInit (void);
60extern int AT91F_DataflashProbe (int i, AT91PS_DataflashDesc pDesc);
61extern int AT91F_DataFlashRead (AT91PS_DataFlash pDataFlash,
62 unsigned long addr,
63 unsigned long size, char *buffer);
wdenk86765902003-12-06 23:55:10 +000064extern int AT91F_DataFlashWrite( AT91PS_DataFlash pDataFlash,
Peter Pearsede5b02c2007-08-14 10:10:52 +010065 unsigned char *src,
66 int dest,
67 int size );
wdenk381669a2003-06-16 23:50:08 +000068
69int AT91F_DataflashInit (void)
70{
71 int i, j;
72 int dfcode;
Stelian Pop03c684d2008-03-26 21:52:36 +010073 int part;
Peter Pearsede5b02c2007-08-14 10:10:52 +010074 int last_part;
75 int found[CFG_MAX_DATAFLASH_BANKS];
76 unsigned char protected;
wdenk381669a2003-06-16 23:50:08 +000077
78 AT91F_SpiInit ();
79
80 for (i = 0; i < CFG_MAX_DATAFLASH_BANKS; i++) {
Peter Pearsede5b02c2007-08-14 10:10:52 +010081 found[i] = 0;
wdenk86765902003-12-06 23:55:10 +000082 dataflash_info[i].Desc.state = IDLE;
wdenk381669a2003-06-16 23:50:08 +000083 dataflash_info[i].id = 0;
84 dataflash_info[i].Device.pages_number = 0;
Stelian Pop05a333b2008-01-20 21:07:00 +000085 dfcode = AT91F_DataflashProbe (cs[i].cs,
Peter Pearsede5b02c2007-08-14 10:10:52 +010086 &dataflash_info[i].Desc);
wdenk381669a2003-06-16 23:50:08 +000087
88 switch (dfcode) {
89 case AT45DB161:
90 dataflash_info[i].Device.pages_number = 4096;
91 dataflash_info[i].Device.pages_size = 528;
92 dataflash_info[i].Device.page_offset = 10;
93 dataflash_info[i].Device.byte_mask = 0x300;
Stelian Pop05a333b2008-01-20 21:07:00 +000094 dataflash_info[i].Device.cs = cs[i].cs;
wdenk381669a2003-06-16 23:50:08 +000095 dataflash_info[i].Desc.DataFlash_state = IDLE;
Stelian Pop05a333b2008-01-20 21:07:00 +000096 dataflash_info[i].logical_address = cs[i].addr;
wdenk381669a2003-06-16 23:50:08 +000097 dataflash_info[i].id = dfcode;
Peter Pearsede5b02c2007-08-14 10:10:52 +010098 found[i] += dfcode;;
wdenk381669a2003-06-16 23:50:08 +000099 break;
100
101 case AT45DB321:
102 dataflash_info[i].Device.pages_number = 8192;
103 dataflash_info[i].Device.pages_size = 528;
104 dataflash_info[i].Device.page_offset = 10;
105 dataflash_info[i].Device.byte_mask = 0x300;
Stelian Pop05a333b2008-01-20 21:07:00 +0000106 dataflash_info[i].Device.cs = cs[i].cs;
wdenk381669a2003-06-16 23:50:08 +0000107 dataflash_info[i].Desc.DataFlash_state = IDLE;
Stelian Pop05a333b2008-01-20 21:07:00 +0000108 dataflash_info[i].logical_address = cs[i].addr;
wdenk381669a2003-06-16 23:50:08 +0000109 dataflash_info[i].id = dfcode;
Peter Pearsede5b02c2007-08-14 10:10:52 +0100110 found[i] += dfcode;;
wdenk381669a2003-06-16 23:50:08 +0000111 break;
112
113 case AT45DB642:
114 dataflash_info[i].Device.pages_number = 8192;
115 dataflash_info[i].Device.pages_size = 1056;
116 dataflash_info[i].Device.page_offset = 11;
117 dataflash_info[i].Device.byte_mask = 0x700;
Stelian Pop05a333b2008-01-20 21:07:00 +0000118 dataflash_info[i].Device.cs = cs[i].cs;
wdenk381669a2003-06-16 23:50:08 +0000119 dataflash_info[i].Desc.DataFlash_state = IDLE;
Stelian Pop05a333b2008-01-20 21:07:00 +0000120 dataflash_info[i].logical_address = cs[i].addr;
wdenk381669a2003-06-16 23:50:08 +0000121 dataflash_info[i].id = dfcode;
Peter Pearsede5b02c2007-08-14 10:10:52 +0100122 found[i] += dfcode;;
wdenk381669a2003-06-16 23:50:08 +0000123 break;
Peter Pearsede5b02c2007-08-14 10:10:52 +0100124
wdenk86765902003-12-06 23:55:10 +0000125 case AT45DB128:
126 dataflash_info[i].Device.pages_number = 16384;
127 dataflash_info[i].Device.pages_size = 1056;
128 dataflash_info[i].Device.page_offset = 11;
129 dataflash_info[i].Device.byte_mask = 0x700;
Stelian Pop05a333b2008-01-20 21:07:00 +0000130 dataflash_info[i].Device.cs = cs[i].cs;
wdenk86765902003-12-06 23:55:10 +0000131 dataflash_info[i].Desc.DataFlash_state = IDLE;
Stelian Pop05a333b2008-01-20 21:07:00 +0000132 dataflash_info[i].logical_address = cs[i].addr;
wdenk86765902003-12-06 23:55:10 +0000133 dataflash_info[i].id = dfcode;
Peter Pearsede5b02c2007-08-14 10:10:52 +0100134 found[i] += dfcode;;
wdenk86765902003-12-06 23:55:10 +0000135 break;
wdenk381669a2003-06-16 23:50:08 +0000136
137 default:
Peter Pearsede5b02c2007-08-14 10:10:52 +0100138 dfcode = 0;
wdenk381669a2003-06-16 23:50:08 +0000139 break;
140 }
wdenk86765902003-12-06 23:55:10 +0000141 /* set the last area end to the dataflash size*/
142 area_list[NB_DATAFLASH_AREA -1].end =
143 (dataflash_info[i].Device.pages_number *
144 dataflash_info[i].Device.pages_size)-1;
wdenk381669a2003-06-16 23:50:08 +0000145
Stelian Pop03c684d2008-03-26 21:52:36 +0100146 part = 0;
147 last_part = 0;
wdenk86765902003-12-06 23:55:10 +0000148 /* set the area addresses */
149 for(j = 0; j<NB_DATAFLASH_AREA; j++) {
Peter Pearsede5b02c2007-08-14 10:10:52 +0100150 if(found[i]!=0) {
Wolfgang Denk0611c492007-08-14 18:42:36 +0200151 dataflash_info[i].Device.area_list[j].start =
152 area_list[part].start +
Peter Pearsede5b02c2007-08-14 10:10:52 +0100153 dataflash_info[i].logical_address;
154 if(area_list[part].end == 0xffffffff) {
Wolfgang Denk0611c492007-08-14 18:42:36 +0200155 dataflash_info[i].Device.area_list[j].end =
156 dataflash_info[i].end_address +
Peter Pearsede5b02c2007-08-14 10:10:52 +0100157 dataflash_info [i].logical_address;
158 last_part = 1;
159 } else {
Wolfgang Denk0611c492007-08-14 18:42:36 +0200160 dataflash_info[i].Device.area_list[j].end =
161 area_list[part].end +
Peter Pearsede5b02c2007-08-14 10:10:52 +0100162 dataflash_info[i].logical_address;
163 }
164 protected = area_list[part].protected;
165 /* Set the environment according to the label...*/
166 if(protected == FLAG_PROTECT_INVALID) {
Wolfgang Denk0611c492007-08-14 18:42:36 +0200167 dataflash_info[i].Device.area_list[j].protected =
Peter Pearsede5b02c2007-08-14 10:10:52 +0100168 FLAG_PROTECT_INVALID;
169 } else {
Wolfgang Denk0611c492007-08-14 18:42:36 +0200170 dataflash_info[i].Device.area_list[j].protected =
Peter Pearsede5b02c2007-08-14 10:10:52 +0100171 protected;
172 }
173 strcpy((char*)(dataflash_info[i].Device.area_list[j].label),
174 (const char *)area_list[part].label);
175 }
176 part++;
wdenk86765902003-12-06 23:55:10 +0000177 }
wdenk381669a2003-06-16 23:50:08 +0000178 }
Peter Pearsede5b02c2007-08-14 10:10:52 +0100179 return found[0];
wdenk381669a2003-06-16 23:50:08 +0000180}
181
Peter Pearsede5b02c2007-08-14 10:10:52 +0100182#ifdef CONFIG_NEW_DF_PARTITION
183int AT91F_DataflashSetEnv (void)
184{
185 int i, j;
186 int part;
187 unsigned char env;
188 unsigned char s[32]; /* Will fit a long int in hex */
189 unsigned long start;
Stelian Pop03c684d2008-03-26 21:52:36 +0100190
Peter Pearsede5b02c2007-08-14 10:10:52 +0100191 for (i = 0, part= 0; i < CFG_MAX_DATAFLASH_BANKS; i++) {
192 for(j = 0; j<NB_DATAFLASH_AREA; j++) {
193 env = area_list[part].setenv;
194 /* Set the environment according to the label...*/
195 if((env & FLAG_SETENV) == FLAG_SETENV) {
Wolfgang Denk0611c492007-08-14 18:42:36 +0200196 start =
Peter Pearsede5b02c2007-08-14 10:10:52 +0100197 dataflash_info[i].Device.area_list[j].start;
198 sprintf(s,"%X",start);
199 setenv(area_list[part].label,s);
200 }
201 part++;
202 }
203 }
204}
205#endif
wdenk381669a2003-06-16 23:50:08 +0000206
wdenk381669a2003-06-16 23:50:08 +0000207void dataflash_print_info (void)
208{
wdenk86765902003-12-06 23:55:10 +0000209 int i, j;
wdenk381669a2003-06-16 23:50:08 +0000210
211 for (i = 0; i < CFG_MAX_DATAFLASH_BANKS; i++) {
212 if (dataflash_info[i].id != 0) {
Peter Pearsede5b02c2007-08-14 10:10:52 +0100213 printf("DataFlash:");
wdenk381669a2003-06-16 23:50:08 +0000214 switch (dataflash_info[i].id) {
215 case AT45DB161:
Peter Pearsede5b02c2007-08-14 10:10:52 +0100216 printf("AT45DB161\n");
wdenk381669a2003-06-16 23:50:08 +0000217 break;
218
219 case AT45DB321:
Peter Pearsede5b02c2007-08-14 10:10:52 +0100220 printf("AT45DB321\n");
wdenk381669a2003-06-16 23:50:08 +0000221 break;
222
223 case AT45DB642:
Peter Pearsede5b02c2007-08-14 10:10:52 +0100224 printf("AT45DB642\n");
wdenk381669a2003-06-16 23:50:08 +0000225 break;
wdenk86765902003-12-06 23:55:10 +0000226 case AT45DB128:
Peter Pearsede5b02c2007-08-14 10:10:52 +0100227 printf("AT45DB128\n");
wdenk86765902003-12-06 23:55:10 +0000228 break;
wdenk381669a2003-06-16 23:50:08 +0000229 }
230
Peter Pearsede5b02c2007-08-14 10:10:52 +0100231 printf("Nb pages: %6d\n"
wdenk381669a2003-06-16 23:50:08 +0000232 "Page Size: %6d\n"
233 "Size=%8d bytes\n"
234 "Logical address: 0x%08X\n",
235 (unsigned int) dataflash_info[i].Device.pages_number,
236 (unsigned int) dataflash_info[i].Device.pages_size,
237 (unsigned int) dataflash_info[i].Device.pages_number *
238 dataflash_info[i].Device.pages_size,
239 (unsigned int) dataflash_info[i].logical_address);
wdenk86765902003-12-06 23:55:10 +0000240 for (j=0; j< NB_DATAFLASH_AREA; j++) {
Peter Pearsede5b02c2007-08-14 10:10:52 +0100241 switch(dataflash_info[i].Device.area_list[j].protected) {
242 case FLAG_PROTECT_SET:
243 case FLAG_PROTECT_CLEAR:
244 printf("Area %i:\t%08lX to %08lX %s", j,
245 dataflash_info[i].Device.area_list[j].start,
246 dataflash_info[i].Device.area_list[j].end,
247 (dataflash_info[i].Device.area_list[j].protected==FLAG_PROTECT_SET) ? "(RO)" : " ");
248#ifdef CONFIG_NEW_DF_PARTITION
249 printf(" %s\n", dataflash_info[i].Device.area_list[j].label);
250#else
251 printf("\n");
252#endif
253 break;
254#ifdef CONFIG_NEW_DF_PARTITION
255 case FLAG_PROTECT_INVALID:
256 break;
257#endif
258 }
wdenk86765902003-12-06 23:55:10 +0000259 }
wdenk381669a2003-06-16 23:50:08 +0000260 }
261 }
262}
263
Peter Pearsede5b02c2007-08-14 10:10:52 +0100264/*---------------------------------------------------------------------------*/
Stelian Pop03c684d2008-03-26 21:52:36 +0100265/* Function Name : AT91F_DataflashSelect */
Peter Pearsede5b02c2007-08-14 10:10:52 +0100266/* Object : Select the correct device */
267/*---------------------------------------------------------------------------*/
Wolfgang Denk0611c492007-08-14 18:42:36 +0200268AT91PS_DataFlash AT91F_DataflashSelect (AT91PS_DataFlash pFlash,
Peter Pearsede5b02c2007-08-14 10:10:52 +0100269 unsigned long *addr)
wdenk381669a2003-06-16 23:50:08 +0000270{
271 char addr_valid = 0;
272 int i;
273
274 for (i = 0; i < CFG_MAX_DATAFLASH_BANKS; i++)
Peter Pearsede5b02c2007-08-14 10:10:52 +0100275 if ( dataflash_info[i].id
Stelian Pop0f79f36c2008-01-14 22:08:14 +0100276 && ((((int) *addr) & 0xFF000000) ==
Peter Pearsede5b02c2007-08-14 10:10:52 +0100277 dataflash_info[i].logical_address)) {
wdenk381669a2003-06-16 23:50:08 +0000278 addr_valid = 1;
279 break;
280 }
281 if (!addr_valid) {
282 pFlash = (AT91PS_DataFlash) 0;
283 return pFlash;
284 }
285 pFlash->pDataFlashDesc = &(dataflash_info[i].Desc);
286 pFlash->pDevice = &(dataflash_info[i].Device);
287 *addr -= dataflash_info[i].logical_address;
288 return (pFlash);
289}
290
Peter Pearsede5b02c2007-08-14 10:10:52 +0100291/*---------------------------------------------------------------------------*/
Stelian Pop03c684d2008-03-26 21:52:36 +0100292/* Function Name : addr_dataflash */
Peter Pearsede5b02c2007-08-14 10:10:52 +0100293/* Object : Test if address is valid */
294/*---------------------------------------------------------------------------*/
wdenk381669a2003-06-16 23:50:08 +0000295int addr_dataflash (unsigned long addr)
296{
297 int addr_valid = 0;
298 int i;
299
300 for (i = 0; i < CFG_MAX_DATAFLASH_BANKS; i++) {
301 if ((((int) addr) & 0xFF000000) ==
302 dataflash_info[i].logical_address) {
303 addr_valid = 1;
304 break;
305 }
306 }
307
308 return addr_valid;
309}
Stelian Pop03c684d2008-03-26 21:52:36 +0100310
Peter Pearsede5b02c2007-08-14 10:10:52 +0100311/*---------------------------------------------------------------------------*/
Stelian Pop03c684d2008-03-26 21:52:36 +0100312/* Function Name : size_dataflash */
Peter Pearsede5b02c2007-08-14 10:10:52 +0100313/* Object : Test if address is valid regarding the size */
314/*---------------------------------------------------------------------------*/
Wolfgang Denk0611c492007-08-14 18:42:36 +0200315int size_dataflash (AT91PS_DataFlash pdataFlash, unsigned long addr,
Peter Pearsede5b02c2007-08-14 10:10:52 +0100316 unsigned long size)
wdenk86765902003-12-06 23:55:10 +0000317{
318 /* is outside the dataflash */
319 if (((int)addr & 0x0FFFFFFF) > (pdataFlash->pDevice->pages_size *
320 pdataFlash->pDevice->pages_number)) return 0;
321 /* is too large for the dataflash */
322 if (size > ((pdataFlash->pDevice->pages_size *
Wolfgang Denk0611c492007-08-14 18:42:36 +0200323 pdataFlash->pDevice->pages_number) -
Peter Pearsede5b02c2007-08-14 10:10:52 +0100324 ((int)addr & 0x0FFFFFFF))) return 0;
wdenk86765902003-12-06 23:55:10 +0000325
326 return 1;
327}
Stelian Pop03c684d2008-03-26 21:52:36 +0100328
Peter Pearsede5b02c2007-08-14 10:10:52 +0100329/*---------------------------------------------------------------------------*/
Stelian Pop03c684d2008-03-26 21:52:36 +0100330/* Function Name : prot_dataflash */
Peter Pearsede5b02c2007-08-14 10:10:52 +0100331/* Object : Test if destination area is protected */
332/*---------------------------------------------------------------------------*/
wdenk86765902003-12-06 23:55:10 +0000333int prot_dataflash (AT91PS_DataFlash pdataFlash, unsigned long addr)
334{
Stelian Pop03c684d2008-03-26 21:52:36 +0100335 int area;
336
wdenk86765902003-12-06 23:55:10 +0000337 /* find area */
338 for (area=0; area < NB_DATAFLASH_AREA; area++) {
339 if ((addr >= pdataFlash->pDevice->area_list[area].start) &&
340 (addr < pdataFlash->pDevice->area_list[area].end))
341 break;
342 }
Wolfgang Denk0611c492007-08-14 18:42:36 +0200343 if (area == NB_DATAFLASH_AREA)
Peter Pearsede5b02c2007-08-14 10:10:52 +0100344 return -1;
345
wdenk86765902003-12-06 23:55:10 +0000346 /*test protection value*/
Wolfgang Denk0611c492007-08-14 18:42:36 +0200347 if (pdataFlash->pDevice->area_list[area].protected == FLAG_PROTECT_SET)
Peter Pearsede5b02c2007-08-14 10:10:52 +0100348 return 0;
Wolfgang Denk0611c492007-08-14 18:42:36 +0200349 if (pdataFlash->pDevice->area_list[area].protected == FLAG_PROTECT_INVALID)
Peter Pearsede5b02c2007-08-14 10:10:52 +0100350 return 0;
wdenk86765902003-12-06 23:55:10 +0000351
352 return 1;
353}
Stelian Pop03c684d2008-03-26 21:52:36 +0100354
Peter Pearsede5b02c2007-08-14 10:10:52 +0100355/*--------------------------------------------------------------------------*/
356/* Function Name : dataflash_real_protect */
357/* Object : protect/unprotect area */
358/*--------------------------------------------------------------------------*/
Wolfgang Denk0611c492007-08-14 18:42:36 +0200359int dataflash_real_protect (int flag, unsigned long start_addr,
Peter Pearsede5b02c2007-08-14 10:10:52 +0100360 unsigned long end_addr)
wdenk86765902003-12-06 23:55:10 +0000361{
Stelian Pop03c684d2008-03-26 21:52:36 +0100362 int i,j, area1, area2, addr_valid = 0;
363
wdenk86765902003-12-06 23:55:10 +0000364 /* find dataflash */
365 for (i = 0; i < CFG_MAX_DATAFLASH_BANKS; i++) {
366 if ((((int) start_addr) & 0xF0000000) ==
367 dataflash_info[i].logical_address) {
368 addr_valid = 1;
369 break;
370 }
371 }
372 if (!addr_valid) {
373 return -1;
374 }
375 /* find start area */
376 for (area1=0; area1 < NB_DATAFLASH_AREA; area1++) {
Wolfgang Denk0611c492007-08-14 18:42:36 +0200377 if (start_addr == dataflash_info[i].Device.area_list[area1].start)
Peter Pearsede5b02c2007-08-14 10:10:52 +0100378 break;
wdenk86765902003-12-06 23:55:10 +0000379 }
380 if (area1 == NB_DATAFLASH_AREA) return -1;
381 /* find end area */
382 for (area2=0; area2 < NB_DATAFLASH_AREA; area2++) {
Wolfgang Denk0611c492007-08-14 18:42:36 +0200383 if (end_addr == dataflash_info[i].Device.area_list[area2].end)
Peter Pearsede5b02c2007-08-14 10:10:52 +0100384 break;
wdenk86765902003-12-06 23:55:10 +0000385 }
Wolfgang Denk0611c492007-08-14 18:42:36 +0200386 if (area2 == NB_DATAFLASH_AREA)
Peter Pearsede5b02c2007-08-14 10:10:52 +0100387 return -1;
wdenk86765902003-12-06 23:55:10 +0000388
389 /*set protection value*/
390 for(j = area1; j < area2+1 ; j++)
Wolfgang Denk0611c492007-08-14 18:42:36 +0200391 if(dataflash_info[i].Device.area_list[j].protected
Peter Pearsede5b02c2007-08-14 10:10:52 +0100392 != FLAG_PROTECT_INVALID) {
393 if (flag == 0) {
Wolfgang Denk0611c492007-08-14 18:42:36 +0200394 dataflash_info[i].Device.area_list[j].protected
Peter Pearsede5b02c2007-08-14 10:10:52 +0100395 = FLAG_PROTECT_CLEAR;
396 } else {
Wolfgang Denk0611c492007-08-14 18:42:36 +0200397 dataflash_info[i].Device.area_list[j].protected
Peter Pearsede5b02c2007-08-14 10:10:52 +0100398 = FLAG_PROTECT_SET;
399 }
400 }
wdenk86765902003-12-06 23:55:10 +0000401
402 return (area2-area1+1);
403}
wdenk381669a2003-06-16 23:50:08 +0000404
Peter Pearsede5b02c2007-08-14 10:10:52 +0100405/*---------------------------------------------------------------------------*/
Stelian Pop03c684d2008-03-26 21:52:36 +0100406/* Function Name : read_dataflash */
Peter Pearsede5b02c2007-08-14 10:10:52 +0100407/* Object : dataflash memory read */
408/*---------------------------------------------------------------------------*/
wdenk381669a2003-06-16 23:50:08 +0000409int read_dataflash (unsigned long addr, unsigned long size, char *result)
410{
Wolfgang Denk7fa6e902006-03-11 22:53:33 +0100411 unsigned long AddrToRead = addr;
wdenk381669a2003-06-16 23:50:08 +0000412 AT91PS_DataFlash pFlash = &DataFlashInst;
413
414 pFlash = AT91F_DataflashSelect (pFlash, &AddrToRead);
wdenk86765902003-12-06 23:55:10 +0000415
wdenk381669a2003-06-16 23:50:08 +0000416 if (pFlash == 0)
wdenk86765902003-12-06 23:55:10 +0000417 return ERR_UNKNOWN_FLASH_TYPE;
418
419 if (size_dataflash(pFlash,addr,size) == 0)
420 return ERR_INVAL;
wdenk381669a2003-06-16 23:50:08 +0000421
422 return (AT91F_DataFlashRead (pFlash, AddrToRead, size, result));
423}
424
Peter Pearsede5b02c2007-08-14 10:10:52 +0100425/*---------------------------------------------------------------------------*/
Stelian Pop03c684d2008-03-26 21:52:36 +0100426/* Function Name : write_dataflash */
Peter Pearsede5b02c2007-08-14 10:10:52 +0100427/* Object : write a block in dataflash */
428/*---------------------------------------------------------------------------*/
wdenk381669a2003-06-16 23:50:08 +0000429int write_dataflash (unsigned long addr_dest, unsigned long addr_src,
Peter Pearsede5b02c2007-08-14 10:10:52 +0100430 unsigned long size)
wdenk381669a2003-06-16 23:50:08 +0000431{
Wolfgang Denk7fa6e902006-03-11 22:53:33 +0100432 unsigned long AddrToWrite = addr_dest;
wdenk381669a2003-06-16 23:50:08 +0000433 AT91PS_DataFlash pFlash = &DataFlashInst;
434
435 pFlash = AT91F_DataflashSelect (pFlash, &AddrToWrite);
wdenk86765902003-12-06 23:55:10 +0000436
437 if (pFlash == 0)
438 return ERR_UNKNOWN_FLASH_TYPE;
439
440 if (size_dataflash(pFlash,addr_dest,size) == 0)
441 return ERR_INVAL;
442
443 if (prot_dataflash(pFlash,addr_dest) == 0)
444 return ERR_PROTECTED;
445
wdenk381669a2003-06-16 23:50:08 +0000446 if (AddrToWrite == -1)
447 return -1;
448
Wolfgang Denk0611c492007-08-14 18:42:36 +0200449 return AT91F_DataFlashWrite (pFlash, (uchar *)addr_src,
Peter Pearsede5b02c2007-08-14 10:10:52 +0100450 AddrToWrite, size);
wdenk381669a2003-06-16 23:50:08 +0000451}
452
wdenk381669a2003-06-16 23:50:08 +0000453void dataflash_perror (int err)
454{
455 switch (err) {
456 case ERR_OK:
457 break;
458 case ERR_TIMOUT:
Peter Pearsede5b02c2007-08-14 10:10:52 +0100459 printf("Timeout writing to DataFlash\n");
wdenk381669a2003-06-16 23:50:08 +0000460 break;
461 case ERR_PROTECTED:
Peter Pearsede5b02c2007-08-14 10:10:52 +0100462 printf("Can't write to protected/invalid DataFlash sectors\n");
wdenk381669a2003-06-16 23:50:08 +0000463 break;
464 case ERR_INVAL:
Peter Pearsede5b02c2007-08-14 10:10:52 +0100465 printf("Outside available DataFlash\n");
wdenk381669a2003-06-16 23:50:08 +0000466 break;
467 case ERR_UNKNOWN_FLASH_TYPE:
Peter Pearsede5b02c2007-08-14 10:10:52 +0100468 printf("Unknown Type of DataFlash\n");
wdenk381669a2003-06-16 23:50:08 +0000469 break;
470 case ERR_PROG_ERROR:
Peter Pearsede5b02c2007-08-14 10:10:52 +0100471 printf("General DataFlash Programming Error\n");
wdenk381669a2003-06-16 23:50:08 +0000472 break;
473 default:
Peter Pearsede5b02c2007-08-14 10:10:52 +0100474 printf("%s[%d] FIXME: rc=%d\n", __FILE__, __LINE__, err);
wdenk381669a2003-06-16 23:50:08 +0000475 break;
476 }
477}
478
479#endif