dataflash.c

来源:互联网 发布:中国第一位程序员 编辑:程序博客网 时间:2024/05/22 15:41
00001 /* LowLevel function for ATMEL DataFlash support00002  * Author : Hamid Ikdoumi (Atmel)00003  *00004  * This program is free software; you can redistribute it and/or00005  * modify it under the terms of the GNU General Public License as00006  * published by the Free Software Foundation; either version 2 of00007  * the License, or (at your option) any later version.00008  *00009  * This program is distributed in the hope that it will be useful,00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the00012  * GNU General Public License for more details.00013  *00014  * You should have received a copy of the GNU General Public License00015  * along with this program; if not, write to the Free Software00016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,00017  * MA 02111-1307 USA00018  *00019  */00020 #include <common.h>00021 #include <config.h>00022 #include <asm/hardware.h>00023 #include <dataflash.h>00024 00025 static AT91S_DataFlash DataFlashInst;00026 00027 extern void AT91F_SpiInit (void);00028 extern int AT91F_DataflashProbe (int i, AT91PS_DataflashDesc pDesc);00029 extern int AT91F_DataFlashRead (AT91PS_DataFlash pDataFlash,00030                             unsigned long addr,00031                             unsigned long size, char *buffer);00032 extern int AT91F_DataFlashWrite( AT91PS_DataFlash pDataFlash,00033                             unsigned char *src,00034                             int dest,00035                             int size );00036 00037 int AT91F_DataflashInit (void)00038 {00039        int i, j;00040        int dfcode;00041        int part;00042        int last_part;00043        int found[CONFIG_SYS_MAX_DATAFLASH_BANKS];00044        unsigned char protected;00045 00046        AT91F_SpiInit ();00047 00048        for (i = 0; i < CONFIG_SYS_MAX_DATAFLASH_BANKS; i++) {00049               found[i] = 0;00050               dataflash_info[i].Desc.state = IDLE;00051               dataflash_info[i].id = 0;00052               dataflash_info[i].Device.pages_number = 0;00053               dfcode = AT91F_DataflashProbe (cs[i].cs,00054                             &dataflash_info[i].Desc);00055 00056               switch (dfcode) {00057               case AT45DB021:00058                      dataflash_info[i].Device.pages_number = 1024;00059                      dataflash_info[i].Device.pages_size = 264;00060                      dataflash_info[i].Device.page_offset = 9;00061                      dataflash_info[i].Device.byte_mask = 0x300;00062                      dataflash_info[i].Device.cs = cs[i].cs;00063                      dataflash_info[i].Desc.DataFlash_state = IDLE;00064                      dataflash_info[i].logical_address = cs[i].addr;00065                      dataflash_info[i].id = dfcode;00066                      found[i] += dfcode;;00067                      break;00068 00069               case AT45DB081:00070                      dataflash_info[i].Device.pages_number = 4096;00071                      dataflash_info[i].Device.pages_size = 264;00072                      dataflash_info[i].Device.page_offset = 9;00073                      dataflash_info[i].Device.byte_mask = 0x300;00074                      dataflash_info[i].Device.cs = cs[i].cs;00075                      dataflash_info[i].Desc.DataFlash_state = IDLE;00076                      dataflash_info[i].logical_address = cs[i].addr;00077                      dataflash_info[i].id = dfcode;00078                      found[i] += dfcode;;00079                      break;00080 00081               case AT45DB161:00082                      dataflash_info[i].Device.pages_number = 4096;00083                      dataflash_info[i].Device.pages_size = 528;00084                      dataflash_info[i].Device.page_offset = 10;00085                      dataflash_info[i].Device.byte_mask = 0x300;00086                      dataflash_info[i].Device.cs = cs[i].cs;00087                      dataflash_info[i].Desc.DataFlash_state = IDLE;00088                      dataflash_info[i].logical_address = cs[i].addr;00089                      dataflash_info[i].id = dfcode;00090                      found[i] += dfcode;;00091                      break;00092 00093               case AT45DB321:00094                      dataflash_info[i].Device.pages_number = 8192;00095                      dataflash_info[i].Device.pages_size = 528;00096                      dataflash_info[i].Device.page_offset = 10;00097                      dataflash_info[i].Device.byte_mask = 0x300;00098                      dataflash_info[i].Device.cs = cs[i].cs;00099                      dataflash_info[i].Desc.DataFlash_state = IDLE;00100                      dataflash_info[i].logical_address = cs[i].addr;00101                      dataflash_info[i].id = dfcode;00102                      found[i] += dfcode;;00103                      break;00104 00105               case AT45DB642:00106                      dataflash_info[i].Device.pages_number = 8192;00107                      dataflash_info[i].Device.pages_size = 1056;00108                      dataflash_info[i].Device.page_offset = 11;00109                      dataflash_info[i].Device.byte_mask = 0x700;00110                      dataflash_info[i].Device.cs = cs[i].cs;00111                      dataflash_info[i].Desc.DataFlash_state = IDLE;00112                      dataflash_info[i].logical_address = cs[i].addr;00113                      dataflash_info[i].id = dfcode;00114                      found[i] += dfcode;;00115                      break;00116 00117               case AT45DB128:00118                      dataflash_info[i].Device.pages_number = 16384;00119                      dataflash_info[i].Device.pages_size = 1056;00120                      dataflash_info[i].Device.page_offset = 11;00121                      dataflash_info[i].Device.byte_mask = 0x700;00122                      dataflash_info[i].Device.cs = cs[i].cs;00123                      dataflash_info[i].Desc.DataFlash_state = IDLE;00124                      dataflash_info[i].logical_address = cs[i].addr;00125                      dataflash_info[i].id = dfcode;00126                      found[i] += dfcode;;00127                      break;00128 00129               default:00130                      dfcode = 0;00131                      break;00132               }00133               /* set the last area end to the dataflash size*/00134               dataflash_info[i].end_address =00135                             (dataflash_info[i].Device.pages_number *00136                             dataflash_info[i].Device.pages_size) - 1;00137 00138               part = 0;00139               last_part = 0;00140               /* set the area addresses */00141               for(j = 0; j < NB_DATAFLASH_AREA; j++) {00142                      if(found[i]!=0) {00143                             dataflash_info[i].Device.area_list[j].start =00144                                    area_list[part].start +00145                                    dataflash_info[i].logical_address;00146                             if(area_list[part].end == 0xffffffff) {00147                                    dataflash_info[i].Device.area_list[j].end =00148                                           dataflash_info[i].end_address +00149                                           dataflash_info[i].logical_address;00150                                    last_part = 1;00151                             } else {00152                                    dataflash_info[i].Device.area_list[j].end =00153                                           area_list[part].end +00154                                           dataflash_info[i].logical_address;00155                             }00156                             protected = area_list[part].protected;00157                             /* Set the environment according to the label...*/00158                             if(protected == FLAG_PROTECT_INVALID) {00159                                    dataflash_info[i].Device.area_list[j].protected =00160                                           FLAG_PROTECT_INVALID;00161                             } else {00162                                    dataflash_info[i].Device.area_list[j].protected =00163                                           protected;00164                             }00165                             strcpy((char*)(dataflash_info[i].Device.area_list[j].label),00166                                           (const char *)area_list[part].label);00167                      }00168                      part++;00169               }00170        }00171        return found[0];00172 }00173 00174 void AT91F_DataflashSetEnv (void)00175 {00176        int i, j;00177        int part;00178        unsigned char env;00179        unsigned char s[32]; /* Will fit a long int in hex */00180        unsigned long start;00181 00182        for (i = 0, part= 0; i < CONFIG_SYS_MAX_DATAFLASH_BANKS; i++) {00183               for(j = 0; j < NB_DATAFLASH_AREA; j++) {00184                      env = area_list[part].setenv;00185                      /* Set the environment according to the label...*/00186                      if((env & FLAG_SETENV) == FLAG_SETENV) {00187                             start = dataflash_info[i].Device.area_list[j].start;00188                             sprintf((char*) s,"%lX",start);00189                             setenv((char*) area_list[part].label,(char*) s);00190                      }00191                      part++;00192               }00193        }00194 }00195 00196 void dataflash_print_info (void)00197 {00198        int i, j;00199 00200        for (i = 0; i < CONFIG_SYS_MAX_DATAFLASH_BANKS; i++) {00201               if (dataflash_info[i].id != 0) {00202                      printf("DataFlash:");00203                      switch (dataflash_info[i].id) {00204                      case AT45DB021:00205                             printf("AT45DB021\n");00206                             break;00207                      case AT45DB161:00208                             printf("AT45DB161\n");00209                             break;00210 00211                      case AT45DB321:00212                             printf("AT45DB321\n");00213                             break;00214 00215                      case AT45DB642:00216                             printf("AT45DB642\n");00217                             break;00218                      case AT45DB128:00219                             printf("AT45DB128\n");00220                             break;00221                      }00222 00223                      printf("Nb pages: %6d\n"00224                             "Page Size: %6d\n"00225                             "Size=%8d bytes\n"00226                             "Logical address: 0x%08X\n",00227                             (unsigned int) dataflash_info[i].Device.pages_number,00228                             (unsigned int) dataflash_info[i].Device.pages_size,00229                             (unsigned int) dataflash_info[i].Device.pages_number *00230                             dataflash_info[i].Device.pages_size,00231                             (unsigned int) dataflash_info[i].logical_address);00232                      for (j = 0; j < NB_DATAFLASH_AREA; j++) {00233                             switch(dataflash_info[i].Device.area_list[j].protected) {00234                             case   FLAG_PROTECT_SET:00235                             case   FLAG_PROTECT_CLEAR:00236                                    printf("Area %i:\t%08lX to %08lX %s", j,00237                                           dataflash_info[i].Device.area_list[j].start,00238                                           dataflash_info[i].Device.area_list[j].end,00239                                           (dataflash_info[i].Device.area_list[j].protected==FLAG_PROTECT_SET) ? "(RO)" : "    ");00240                                           printf(" %s\n",      dataflash_info[i].Device.area_list[j].label);00241                                    break;00242                             case   FLAG_PROTECT_INVALID:00243                                    break;00244                             }00245                      }00246               }00247        }00248 }00249 00250 /*---------------------------------------------------------------------------*/00251 /* Function Name       : AT91F_DataflashSelect                             */00252 /* Object              : Select the correct device                         */00253 /*---------------------------------------------------------------------------*/00254 AT91PS_DataFlash AT91F_DataflashSelect (AT91PS_DataFlash pFlash,00255                             unsigned long *addr)00256 {00257        char addr_valid = 0;00258        int i;00259 00260        for (i = 0; i < CONFIG_SYS_MAX_DATAFLASH_BANKS; i++)00261               if ( dataflash_info[i].id00262                      && ((((int) *addr) & 0xFF000000) ==00263                      dataflash_info[i].logical_address)) {00264                      addr_valid = 1;00265                      break;00266               }00267        if (!addr_valid) {00268               pFlash = (AT91PS_DataFlash) 0;00269               return pFlash;00270        }00271        pFlash->pDataFlashDesc = &(dataflash_info[i].Desc);00272        pFlash->pDevice = &(dataflash_info[i].Device);00273        *addr -= dataflash_info[i].logical_address;00274        return (pFlash);00275 }00276 00277 /*---------------------------------------------------------------------------*/00278 /* Function Name       : addr_dataflash                                    */00279 /* Object              : Test if address is valid                          */00280 /*---------------------------------------------------------------------------*/00281 int addr_dataflash (unsigned long addr)00282 {00283        int addr_valid = 0;00284        int i;00285 00286        for (i = 0; i < CONFIG_SYS_MAX_DATAFLASH_BANKS; i++) {00287               if ((((int) addr) & 0xFF000000) ==00288                      dataflash_info[i].logical_address) {00289                      addr_valid = 1;00290                      break;00291               }00292        }00293 00294        return addr_valid;00295 }00296 00297 /*---------------------------------------------------------------------------*/00298 /* Function Name       : size_dataflash                                    */00299 /* Object              : Test if address is valid regarding the size       */00300 /*---------------------------------------------------------------------------*/00301 int size_dataflash (AT91PS_DataFlash pdataFlash, unsigned long addr,00302                      unsigned long size)00303 {00304        /* is outside the dataflash */00305        if (((int)addr & 0x0FFFFFFF) > (pdataFlash->pDevice->pages_size *00306               pdataFlash->pDevice->pages_number)) return 0;00307        /* is too large for the dataflash */00308        if (size > ((pdataFlash->pDevice->pages_size *00309               pdataFlash->pDevice->pages_number) -00310               ((int)addr & 0x0FFFFFFF))) return 0;00311 00312        return 1;00313 }00314 00315 /*---------------------------------------------------------------------------*/00316 /* Function Name       : prot_dataflash                                    */00317 /* Object              : Test if destination area is protected             */00318 /*---------------------------------------------------------------------------*/00319 int prot_dataflash (AT91PS_DataFlash pdataFlash, unsigned long addr)00320 {00321        int area;00322 00323        /* find area */00324        for (area = 0; area < NB_DATAFLASH_AREA; area++) {00325               if ((addr >= pdataFlash->pDevice->area_list[area].start) &&00326                      (addr < pdataFlash->pDevice->area_list[area].end))00327                      break;00328        }00329        if (area == NB_DATAFLASH_AREA)00330               return -1;00331 00332        /*test protection value*/00333        if (pdataFlash->pDevice->area_list[area].protected == FLAG_PROTECT_SET)00334               return 0;00335        if (pdataFlash->pDevice->area_list[area].protected == FLAG_PROTECT_INVALID)00336               return 0;00337 00338        return 1;00339 }00340 00341 /*--------------------------------------------------------------------------*/00342 /* Function Name       : dataflash_real_protect                           */00343 /* Object              : protect/unprotect area                           */00344 /*--------------------------------------------------------------------------*/00345 int dataflash_real_protect (int flag, unsigned long start_addr,00346                             unsigned long end_addr)00347 {00348        int i,j, area1, area2, addr_valid = 0;00349 00350        /* find dataflash */00351        for (i = 0; i < CONFIG_SYS_MAX_DATAFLASH_BANKS; i++) {00352               if ((((int) start_addr) & 0xF0000000) ==00353                      dataflash_info[i].logical_address) {00354                             addr_valid = 1;00355                             break;00356               }00357        }00358        if (!addr_valid) {00359               return -1;00360        }00361        /* find start area */00362        for (area1 = 0; area1 < NB_DATAFLASH_AREA; area1++) {00363               if (start_addr == dataflash_info[i].Device.area_list[area1].start)00364                      break;00365        }00366        if (area1 == NB_DATAFLASH_AREA) return -1;00367        /* find end area */00368        for (area2 = 0; area2 < NB_DATAFLASH_AREA; area2++) {00369               if (end_addr == dataflash_info[i].Device.area_list[area2].end)00370                      break;00371        }00372        if (area2 == NB_DATAFLASH_AREA)00373               return -1;00374 00375        /*set protection value*/00376        for(j = area1; j < area2 + 1 ; j++)00377               if(dataflash_info[i].Device.area_list[j].protected00378                             != FLAG_PROTECT_INVALID) {00379                      if (flag == 0) {00380                             dataflash_info[i].Device.area_list[j].protected00381                                    = FLAG_PROTECT_CLEAR;00382                      } else {00383                             dataflash_info[i].Device.area_list[j].protected00384                                    = FLAG_PROTECT_SET;00385                      }00386               }00387 00388        return (area2 - area1 + 1);00389 }00390 00391 /*---------------------------------------------------------------------------*/00392 /* Function Name       : read_dataflash                                    */00393 /* Object              : dataflash memory read                             */00394 /*---------------------------------------------------------------------------*/00395 int read_dataflash (unsigned long addr, unsigned long size, char *result)00396 {00397        unsigned long AddrToRead = addr;00398        AT91PS_DataFlash pFlash = &DataFlashInst;00399 00400        pFlash = AT91F_DataflashSelect (pFlash, &AddrToRead);00401 00402        if (pFlash == 0)00403               return ERR_UNKNOWN_FLASH_TYPE;00404 00405        if (size_dataflash(pFlash,addr,size) == 0)00406               return ERR_INVAL;00407 00408        return (AT91F_DataFlashRead (pFlash, AddrToRead, size, result));00409 }00410 00411 /*---------------------------------------------------------------------------*/00412 /* Function Name       : write_dataflash                            */00413 /* Object              : write a block in dataflash                        */00414 /*---------------------------------------------------------------------------*/00415 int write_dataflash (unsigned long addr_dest, unsigned long addr_src,00416                      unsigned long size)00417 {00418        unsigned long AddrToWrite = addr_dest;00419        AT91PS_DataFlash pFlash = &DataFlashInst;00420 00421        pFlash = AT91F_DataflashSelect (pFlash, &AddrToWrite);00422 00423        if (pFlash == 0)00424               return ERR_UNKNOWN_FLASH_TYPE;00425 00426        if (size_dataflash(pFlash,addr_dest,size) == 0)00427               return ERR_INVAL;00428 00429        if (prot_dataflash(pFlash,addr_dest) == 0)00430               return ERR_PROTECTED;00431 00432        if (AddrToWrite == -1)00433               return -1;00434 00435        return AT91F_DataFlashWrite (pFlash, (uchar *)addr_src,00436                                           AddrToWrite, size);00437 }00438 00439 void dataflash_perror (int err)00440 {00441        switch (err) {00442        case ERR_OK:00443               break;00444        case ERR_TIMOUT:00445               printf("Timeout writing to DataFlash\n");00446               break;00447        case ERR_PROTECTED:00448               printf("Can't write to protected/invalid DataFlash sectors\n");00449               break;00450        case ERR_INVAL:00451               printf("Outside available DataFlash\n");00452               break;00453        case ERR_UNKNOWN_FLASH_TYPE:00454               printf("Unknown Type of DataFlash\n");00455               break;00456        case ERR_PROG_ERROR:00457               printf("General DataFlash Programming Error\n");00458               break;00459        default:00460               printf("%s[%d] FIXME: rc=%d\n", __FILE__, __LINE__, err);00461               break;00462        }00463 }--------------------------------------------------------------------------------

原创粉丝点击