reduce size
[romboot.git] / dataflash.cpp
blob1d9f6f746eae27081b4e4dcdb00fcf62be36da4f
1 //*----------------------------------------------------------------------------
2 //* ATMEL Microcontroller Software Support - ROUSSET -
3 //*----------------------------------------------------------------------------
4 //* The software is delivered "AS IS" without warranty or condition of any
5 //* kind, either express, implied or statutory. This includes without
6 //* limitation any warranty or condition with respect to merchantability or
7 //* fitness for any particular purpose, or against the infringements of
8 //* intellectual property rights of others.
9 //*----------------------------------------------------------------------------
10 //* File Name : dataflash.c
11 //* Object : High level functions for the dataflash
12 //* Creation : HIi 10/10/2003
13 //*----------------------------------------------------------------------------
15 #include "dataflash.h"
16 #include "com.h"
17 void AT91F_InitSdram(void);
21 AT91S_DATAFLASH_INFO dataflash_info[CFG_MAX_DATAFLASH_BANKS];
22 static AT91S_DataFlash DataFlashInst;
24 int cs[][CFG_MAX_DATAFLASH_BANKS] = {
25 {CFG_DATAFLASH_LOGIC_ADDR_CS0, 0}, /* Logical adress, CS */
26 {CFG_DATAFLASH_LOGIC_ADDR_CS1, 1}, /* Logical adress, CS */
27 {CFG_DATAFLASH_LOGIC_ADDR_CS2, 2}, /* Logical adress, CS */
28 {CFG_DATAFLASH_LOGIC_ADDR_CS3, 3}
31 #define SIZE_REGS_64M 0x2188c159
32 #define SIZE_REGS_128M 0x2188c15a
35 int AT91F_DataflashInit (void)
37 int i;
38 int dfcode;
40 AT91F_SpiInit ();
42 for (i = 0; i < CFG_MAX_DATAFLASH_BANKS; i++) {
43 dataflash_info[i].Desc.state = IDLE;
44 dataflash_info[i].id = 0;
45 dataflash_info[i].Device.pages_number = 0;
46 dfcode = AT91F_DataflashProbe(cs[i][1], &dataflash_info[i].Desc);
48 switch (dfcode) {
49 #if 0
50 case AT45DB161:
51 printf("\n\rflash nb %d found",i);
52 dataflash_info[i].Device.pages_number = 4096;
53 dataflash_info[i].Device.pages_size = 528;
54 dataflash_info[i].Device.page_offset = 10;
55 dataflash_info[i].Device.byte_mask = 0x300;
56 dataflash_info[i].Device.cs = cs[i][1];
57 dataflash_info[i].Desc.DataFlash_state = IDLE;
58 dataflash_info[i].logical_address = cs[i][0];
59 dataflash_info[i].id = dfcode;
60 break;
62 case AT45DB321:
63 printf("\n\rflash nb %d found",i);
64 dataflash_info[i].Device.pages_number = 8192;
65 dataflash_info[i].Device.pages_size = 528;
66 dataflash_info[i].Device.page_offset = 10;
67 dataflash_info[i].Device.byte_mask = 0x300;
68 dataflash_info[i].Device.cs = cs[i][1];
69 dataflash_info[i].Desc.DataFlash_state = IDLE;
70 dataflash_info[i].logical_address = cs[i][0];
71 dataflash_info[i].id = dfcode;
72 break;
73 #endif
75 case AT45DB642:
76 printf("\n\rflash nb %d found",i);
77 dataflash_info[i].Device.pages_number = 8192;
78 dataflash_info[i].Device.pages_size = 1056;
79 dataflash_info[i].Device.page_offset = 11;
80 dataflash_info[i].Device.byte_mask = 0x700;
81 dataflash_info[i].Device.cs = cs[i][1];
82 dataflash_info[i].Desc.DataFlash_state = IDLE;
83 dataflash_info[i].logical_address = cs[i][0];
84 dataflash_info[i].id = dfcode;
85 break;
86 case AT45DB128:
87 printf("\n\rflash nb %d found",i);
88 dataflash_info[i].Device.pages_number = 16384;
89 dataflash_info[i].Device.pages_size = 1056;
90 dataflash_info[i].Device.page_offset = 11;
91 dataflash_info[i].Device.byte_mask = 0x700;
92 dataflash_info[i].Device.cs = cs[i][1];
93 dataflash_info[i].Desc.DataFlash_state = IDLE;
94 dataflash_info[i].logical_address = cs[i][0];
95 dataflash_info[i].id = dfcode;
96 break;
98 default:
99 printf("\n\rflash nb %d not found",i);
100 break;
103 printf("\n\r");
104 AT91F_InitSdram();
105 return (1);
108 int get_size_reg()
110 if ((dataflash_info[2].id != 0) && (dataflash_info[3].id != 0 )){
111 return SIZE_REGS_128M;
113 else {
114 return SIZE_REGS_64M;
118 void AT91F_DataflashPrintInfo(void)
120 int i;
121 int *pregister;
123 for (i = 0; i < CFG_MAX_DATAFLASH_BANKS; i++) {
124 if (dataflash_info[i].id != 0) {
125 printf ("DataFlash:");
126 switch (dataflash_info[i].id) {
127 #ifndef REDUCE_CODE_SIZE
128 case AT45DB161:
129 printf ("AT45DB161\n\r");
130 break;
132 case AT45DB321:
133 printf ("AT45DB321\n\r");
134 break;
135 #endif
136 case AT45DB642:
137 printf ("AT45DB642\n\r");
138 break;
139 case AT45DB128:
140 printf ("AT45DB128\n\r");
141 break;
144 printf ("Nb pages: %6d\n\r"
145 "Page Size: %6d\n\r"
146 "Size=%8d bytes\n\r"
147 "Logical address: 0x%08X\n\r",
148 (unsigned int) dataflash_info[i].Device.pages_number,
149 (unsigned int) dataflash_info[i].Device.pages_size,
150 (unsigned int) dataflash_info[i].Device.pages_number *
151 dataflash_info[i].Device.pages_size,
152 (unsigned int) dataflash_info[i].logical_address);
158 /*------------------------------------------------------------------------------*/
159 /* Function Name : AT91F_DataflashSelect */
160 /* Object : Select the correct device */
161 /*------------------------------------------------------------------------------*/
162 AT91PS_DataFlash AT91F_DataflashSelect (AT91PS_DataFlash pFlash,
163 unsigned int *addr)
165 char addr_valid = 0;
166 int i;
168 for (i = 0; i < CFG_MAX_DATAFLASH_BANKS; i++)
169 if ((*addr & 0xFF000000) == dataflash_info[i].logical_address) {
170 addr_valid = 1;
171 break;
173 if (!addr_valid) {
174 pFlash = (AT91PS_DataFlash) 0;
175 return pFlash;
177 pFlash->pDataFlashDesc = &(dataflash_info[i].Desc);
178 pFlash->pDevice = &(dataflash_info[i].Device);
179 *addr -= dataflash_info[i].logical_address;
180 return (pFlash);
184 /*------------------------------------------------------------------------------*/
185 /* Function Name : addr_dataflash */
186 /* Object : Test if address is valid */
187 /*------------------------------------------------------------------------------*/
188 int addr_dataflash (unsigned long addr)
190 int addr_valid = 0;
191 int i;
193 for (i = 0; i < CFG_MAX_DATAFLASH_BANKS; i++) {
194 if ((((int) addr) & 0xFF000000) ==
195 dataflash_info[i].logical_address) {
196 addr_valid = 1;
197 break;
201 return addr_valid;
204 /*------------------------------------------------------------------------------*/
205 /* Function Name : read_dataflash */
206 /* Object : dataflash memory read */
207 /*------------------------------------------------------------------------------*/
208 int read_dataflash (unsigned long addr, unsigned long size, char *result)
210 unsigned int AddrToRead = addr;
211 // AT91F_DataflashPrintInfo();
212 AT91PS_DataFlash pFlash = &DataFlashInst;
214 pFlash = AT91F_DataflashSelect (pFlash, &AddrToRead);
215 if (pFlash == 0)
216 return -1;
218 return (AT91F_DataFlashRead (pFlash, AddrToRead, size, result));
222 /*-----------------------------------------------------------------------------*/
223 /* Function Name : write_dataflash */
224 /* Object : write a block in dataflash */
225 /*-----------------------------------------------------------------------------*/
226 int write_dataflash (unsigned long addr_dest, unsigned int addr_src,
227 unsigned int size)
229 unsigned int AddrToWrite = addr_dest;
230 AT91PS_DataFlash pFlash = &DataFlashInst;
232 pFlash = AT91F_DataflashSelect (pFlash, &AddrToWrite);
233 if (AddrToWrite == -1)
234 return -1;
236 return AT91F_DataFlashWrite (pFlash, (unsigned char *) addr_src, AddrToWrite, size);
240 int erase_dataflash(int nb)
242 AT91PS_DataFlash pFlash = &DataFlashInst;
243 AT91S_DataFlashStatus status;
244 int page_nb;
246 if ( dataflash_info[nb].id != 0) {
247 AT91F_SpiEnable(pFlash->pDevice->cs);
249 pFlash->pDataFlashDesc = &(dataflash_info[nb].Desc);
250 pFlash->pDevice = &(dataflash_info[nb].Device);
251 for ( page_nb = 0 ; page_nb < dataflash_info[nb].Device.pages_number ; page_nb++) {
252 if ( page_nb % 16 == 0)
253 printf("Erase page nb %d\r\n",page_nb);
254 status = AT91F_PageErase(pFlash,page_nb);
255 AT91F_DataFlashWaitReady(pFlash->pDataFlashDesc, AT91C_DATAFLASH_TIMEOUT);
256 if (!status) {
257 printf("Erase page nb %d error\n",page_nb);
258 return AT91C_DATAFLASH_ERROR;
268 * Le sector protection register ( spr) contient la liste des secteurs de dataflash
269 * a protéger.
271 * On efface le spr par la cmd
273 * Erase Sector Protection Register 3DH 2AH 7FH CFH
275 * On programme le spr par
277 * Program Sector Protection Register 3DH 2AH 7FH FCH
279 * avec dans les bytes suivants la protection des secteurs.
280 * Cette protection peut être activée par la command
282 * Enable Sector Protection 3DH 2AH 7FH A9H
284 * Le conte,u du registre peut etre lu par
286 * Read Sector Protection Register 32H xxH xxH xxH
288 * et désactivée par
290 * Disable Sector Protection 3DH 2AH 7FH 9AH
293 static void clear_desc( AT91S_DataflashDesc *d)
295 #ifdef REDUCE_CODE_SIZE
296 int i;
297 char *ptr1 = ( char *)d;
298 for ( i = 0 ; i < sizeof(AT91S_DataflashDesc) ; i++)
300 *ptr1 = 0;
301 ptr1++;
304 #else
305 d->tx_cmd_pt = 0;
306 d->rx_cmd_pt = 0;
307 d->tx_cmd_size = 0;
308 d->rx_cmd_size = 0;
309 d->tx_data_size = 0;
310 d->rx_data_size = 0;
311 d->tx_data_pt = 0;
312 d->rx_data_pt = 0;
313 d->state = 0;
314 d->DataFlash_state = 0;
315 d->command[0] = 0;
316 d->command[1] = 0;
317 d->command[2] = 0;
318 d->command[3] = 0;
319 d->command[4] = 0;
320 d->command[5] = 0;
321 d->command[6] = 0;
322 d->command[7] = 0;
323 #endif
327 void memset(unsigned char *ptr,char val , int size)
329 int i;
330 for ( i = 0 ; i < size ; i++) {
331 *ptr = val;
332 ptr++;
335 AT91S_DataflashDesc desc;
337 t_read_lock_cmd read_lock_cmd_sector =
340 0x32,0x00,0x00,0x00
346 t_read_lock_cmd read_lock_cmd_lockdown=
349 0x35,0x00,0x00,0x00
355 t_read_lock_cmd read_lock_cmd_security=
358 0x77,0x00,0x00,0x00
360 128,
364 void AT91F_SpiEnable(int cs);
366 void read_lock_reg(t_read_lock_cmd *ptrcmd)
368 int i;
369 unsigned char rx[129];
370 char *ptr;
371 int fl_nb;
373 for ( fl_nb = 0 ; fl_nb < CFG_MAX_DATAFLASH_BANKS ; fl_nb++) {
375 if (dataflash_info[fl_nb].id != 0) {
376 AT91F_SpiEnable(cs[fl_nb][1]);
378 clear_desc(&desc);
379 memset(rx,0,sizeof(rx));
380 rx[0] = 8;
381 desc.tx_cmd_pt = ptrcmd->cmd;
382 desc.rx_cmd_pt = rx;
383 desc.tx_cmd_size = 4;
384 desc.rx_cmd_size = 4;
385 desc.tx_data_size = ptrcmd->txsize;
386 desc.rx_data_size = ptrcmd->rxsize;
387 desc.tx_data_pt = rx;
388 desc.rx_data_pt = rx;
390 AT91F_SpiWrite(&desc);
391 printf("\n\r");
392 if ( ptrcmd == &read_lock_cmd_sector ) {
393 printf("Lock status register");
395 if ( ptrcmd == &read_lock_cmd_lockdown ) {
396 printf("lockdown status register");
398 if ( ptrcmd == &read_lock_cmd_security ) {
399 printf("security register ");
401 printf("size %d flash_nb %d \n\r",ptrcmd->rxsize,fl_nb);
402 for ( i = 0 ; i < ptrcmd->rxsize ; i++ ) {
403 if ((i % 16) == 0) {
404 printf("\n\r");
406 printf("0x%02x:",rx[i]);
408 printf("\n\r");
414 unsigned char clear_lock_cmd[4]=
416 0x3D,0x2A,0x7F,0xCF
419 int test_fl_info(int fl_nb)
421 if (dataflash_info[fl_nb].id != 0) {
422 AT91F_SpiEnable(cs[fl_nb][1]);
424 clear_desc(&desc);
425 return(1);
427 else {
428 return(0);
432 void erase_lock_reg(int fl_nb)
434 int i;
435 unsigned char rx[33];
436 if (test_fl_info(fl_nb)) {
437 memset(rx,0,sizeof(rx));
439 desc.tx_cmd_pt = clear_lock_cmd;
440 desc.rx_cmd_pt = rx;
441 desc.tx_cmd_size = 4;
442 desc.rx_cmd_size = 4;
443 AT91F_SpiWrite(&desc);
447 unsigned char lock_unlock_cmd[4]=
449 0x3D,0x2A,0x7F,0xFC
452 unsigned char enable_lock_unlock_cmd[4]=
454 0x3D,0x2A,0x7F,0xA9
457 unsigned char disable_lock_unlock_cmd[4]=
459 0x3D,0x2A,0x7F,0x9A
463 void flash_en_lock_unlock(unsigned char *cmd)
465 unsigned char rxf[4];
466 unsigned char rx[33];
468 desc.tx_cmd_pt = cmd;
469 desc.rx_cmd_pt = rxf;
470 desc.tx_cmd_size = 4;
471 desc.rx_cmd_size = 4;
473 AT91F_SpiWrite(&desc);
476 void program_lock_reg(int fl_nb)
478 unsigned char rxf[4];
479 unsigned char rx[33];
480 if (test_fl_info(fl_nb)) {
482 memset(rx,0xff,sizeof(rx));
483 desc.tx_cmd_pt = lock_unlock_cmd;
484 desc.rx_cmd_pt = rxf;
485 desc.tx_cmd_size = 4;
486 desc.rx_cmd_size = 4;
487 desc.tx_data_size = 32;
488 desc.rx_data_size = 32;
489 desc.tx_data_pt = rx;
490 desc.rx_data_pt = rx;
492 AT91F_SpiWrite(&desc);
496 void flash_enable_lock(int fl_nb)
498 int i;
499 if (test_fl_info(fl_nb)) {
500 flash_en_lock_unlock(enable_lock_unlock_cmd);
504 void flash_disable_lock(int fl_nb)
506 int i;
507 if (test_fl_info(fl_nb)) {
508 flash_en_lock_unlock(disable_lock_unlock_cmd);