uboot/drivers/mtd/dataflash.c
<<
>>
Prefs
   1/* 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#include <asm/hardware.h>
  23#include <dataflash.h>
  24
  25static AT91S_DataFlash DataFlashInst;
  26
  27extern void AT91F_SpiInit (void);
  28extern int AT91F_DataflashProbe (int i, AT91PS_DataflashDesc pDesc);
  29extern int AT91F_DataFlashRead (AT91PS_DataFlash pDataFlash,
  30                                unsigned long addr,
  31                                unsigned long size, char *buffer);
  32extern int AT91F_DataFlashWrite( AT91PS_DataFlash pDataFlash,
  33                                unsigned char *src,
  34                                int dest,
  35                                int size );
  36
  37int AT91F_DataflashInit (void)
  38{
  39        int i, j;
  40        int dfcode;
  41        int part;
  42        int last_part;
  43        int found[CONFIG_SYS_MAX_DATAFLASH_BANKS];
  44        unsigned char protected;
  45
  46        AT91F_SpiInit ();
  47
  48        for (i = 0; i < CONFIG_SYS_MAX_DATAFLASH_BANKS; i++) {
  49                found[i] = 0;
  50                dataflash_info[i].Desc.state = IDLE;
  51                dataflash_info[i].id = 0;
  52                dataflash_info[i].Device.pages_number = 0;
  53                dfcode = AT91F_DataflashProbe (cs[i].cs,
  54                                &dataflash_info[i].Desc);
  55
  56                switch (dfcode) {
  57                case AT45DB021:
  58                        dataflash_info[i].Device.pages_number = 1024;
  59                        dataflash_info[i].Device.pages_size = 264;
  60                        dataflash_info[i].Device.page_offset = 9;
  61                        dataflash_info[i].Device.byte_mask = 0x300;
  62                        dataflash_info[i].Device.cs = cs[i].cs;
  63                        dataflash_info[i].Desc.DataFlash_state = IDLE;
  64                        dataflash_info[i].logical_address = cs[i].addr;
  65                        dataflash_info[i].id = dfcode;
  66                        found[i] += dfcode;;
  67                        break;
  68
  69                case AT45DB081:
  70                        dataflash_info[i].Device.pages_number = 4096;
  71                        dataflash_info[i].Device.pages_size = 264;
  72                        dataflash_info[i].Device.page_offset = 9;
  73                        dataflash_info[i].Device.byte_mask = 0x300;
  74                        dataflash_info[i].Device.cs = cs[i].cs;
  75                        dataflash_info[i].Desc.DataFlash_state = IDLE;
  76                        dataflash_info[i].logical_address = cs[i].addr;
  77                        dataflash_info[i].id = dfcode;
  78                        found[i] += dfcode;;
  79                        break;
  80
  81                case AT45DB161:
  82                        dataflash_info[i].Device.pages_number = 4096;
  83                        dataflash_info[i].Device.pages_size = 528;
  84                        dataflash_info[i].Device.page_offset = 10;
  85                        dataflash_info[i].Device.byte_mask = 0x300;
  86                        dataflash_info[i].Device.cs = cs[i].cs;
  87                        dataflash_info[i].Desc.DataFlash_state = IDLE;
  88                        dataflash_info[i].logical_address = cs[i].addr;
  89                        dataflash_info[i].id = dfcode;
  90                        found[i] += dfcode;;
  91                        break;
  92
  93                case AT45DB321:
  94                        dataflash_info[i].Device.pages_number = 8192;
  95                        dataflash_info[i].Device.pages_size = 528;
  96                        dataflash_info[i].Device.page_offset = 10;
  97                        dataflash_info[i].Device.byte_mask = 0x300;
  98                        dataflash_info[i].Device.cs = cs[i].cs;
  99                        dataflash_info[i].Desc.DataFlash_state = IDLE;
 100                        dataflash_info[i].logical_address = cs[i].addr;
 101                        dataflash_info[i].id = dfcode;
 102                        found[i] += dfcode;;
 103                        break;
 104
 105                case AT45DB642:
 106                        dataflash_info[i].Device.pages_number = 8192;
 107                        dataflash_info[i].Device.pages_size = 1056;
 108                        dataflash_info[i].Device.page_offset = 11;
 109                        dataflash_info[i].Device.byte_mask = 0x700;
 110                        dataflash_info[i].Device.cs = cs[i].cs;
 111                        dataflash_info[i].Desc.DataFlash_state = IDLE;
 112                        dataflash_info[i].logical_address = cs[i].addr;
 113                        dataflash_info[i].id = dfcode;
 114                        found[i] += dfcode;;
 115                        break;
 116
 117                case AT45DB128:
 118                        dataflash_info[i].Device.pages_number = 16384;
 119                        dataflash_info[i].Device.pages_size = 1056;
 120                        dataflash_info[i].Device.page_offset = 11;
 121                        dataflash_info[i].Device.byte_mask = 0x700;
 122                        dataflash_info[i].Device.cs = cs[i].cs;
 123                        dataflash_info[i].Desc.DataFlash_state = IDLE;
 124                        dataflash_info[i].logical_address = cs[i].addr;
 125                        dataflash_info[i].id = dfcode;
 126                        found[i] += dfcode;;
 127                        break;
 128
 129                default:
 130                        dfcode = 0;
 131                        break;
 132                }
 133                /* set the last area end to the dataflash size*/
 134                dataflash_info[i].end_address =
 135                                (dataflash_info[i].Device.pages_number *
 136                                dataflash_info[i].Device.pages_size) - 1;
 137
 138                part = 0;
 139                last_part = 0;
 140                /* set the area addresses */
 141                for(j = 0; j < NB_DATAFLASH_AREA; j++) {
 142                        if(found[i]!=0) {
 143                                dataflash_info[i].Device.area_list[j].start =
 144                                        area_list[part].start +
 145                                        dataflash_info[i].logical_address;
 146                                if(area_list[part].end == 0xffffffff) {
 147                                        dataflash_info[i].Device.area_list[j].end =
 148                                                dataflash_info[i].end_address +
 149                                                dataflash_info[i].logical_address;
 150                                        last_part = 1;
 151                                } else {
 152                                        dataflash_info[i].Device.area_list[j].end =
 153                                                area_list[part].end +
 154                                                dataflash_info[i].logical_address;
 155                                }
 156                                protected = area_list[part].protected;
 157                                /* Set the environment according to the label...*/
 158                                if(protected == FLAG_PROTECT_INVALID) {
 159                                        dataflash_info[i].Device.area_list[j].protected =
 160                                                FLAG_PROTECT_INVALID;
 161                                } else {
 162                                        dataflash_info[i].Device.area_list[j].protected =
 163                                                protected;
 164                                }
 165                                strcpy((char*)(dataflash_info[i].Device.area_list[j].label),
 166                                                (const char *)area_list[part].label);
 167                        }
 168                        part++;
 169                }
 170        }
 171        return found[0];
 172}
 173
 174void AT91F_DataflashSetEnv (void)
 175{
 176        int i, j;
 177        int part;
 178        unsigned char env;
 179        unsigned char s[32];    /* Will fit a long int in hex */
 180        unsigned long start;
 181
 182        for (i = 0, part= 0; i < CONFIG_SYS_MAX_DATAFLASH_BANKS; i++) {
 183                for(j = 0; j < NB_DATAFLASH_AREA; j++) {
 184                        env = area_list[part].setenv;
 185                        /* Set the environment according to the label...*/
 186                        if((env & FLAG_SETENV) == FLAG_SETENV) {
 187                                start = dataflash_info[i].Device.area_list[j].start;
 188                                sprintf((char*) s,"%lX",start);
 189                                setenv((char*) area_list[part].label,(char*) s);
 190                        }
 191                        part++;
 192                }
 193        }
 194}
 195
 196void dataflash_print_info (void)
 197{
 198        int i, j;
 199
 200        for (i = 0; i < CONFIG_SYS_MAX_DATAFLASH_BANKS; i++) {
 201                if (dataflash_info[i].id != 0) {
 202                        printf("DataFlash:");
 203                        switch (dataflash_info[i].id) {
 204                        case AT45DB021:
 205                                printf("AT45DB021\n");
 206                                break;
 207                        case AT45DB161:
 208                                printf("AT45DB161\n");
 209                                break;
 210
 211                        case AT45DB321:
 212                                printf("AT45DB321\n");
 213                                break;
 214
 215                        case AT45DB642:
 216                                printf("AT45DB642\n");
 217                                break;
 218                        case AT45DB128:
 219                                printf("AT45DB128\n");
 220                                break;
 221                        }
 222
 223                        printf("Nb pages: %6d\n"
 224                                "Page Size: %6d\n"
 225                                "Size=%8d bytes\n"
 226                                "Logical address: 0x%08X\n",
 227                                (unsigned int) dataflash_info[i].Device.pages_number,
 228                                (unsigned int) dataflash_info[i].Device.pages_size,
 229                                (unsigned int) dataflash_info[i].Device.pages_number *
 230                                dataflash_info[i].Device.pages_size,
 231                                (unsigned int) dataflash_info[i].logical_address);
 232                        for (j = 0; j < NB_DATAFLASH_AREA; j++) {
 233                                switch(dataflash_info[i].Device.area_list[j].protected) {
 234                                case    FLAG_PROTECT_SET:
 235                                case    FLAG_PROTECT_CLEAR:
 236                                        printf("Area %i:\t%08lX to %08lX %s", j,
 237                                                dataflash_info[i].Device.area_list[j].start,
 238                                                dataflash_info[i].Device.area_list[j].end,
 239                                                (dataflash_info[i].Device.area_list[j].protected==FLAG_PROTECT_SET) ? "(RO)" : "    ");
 240                                                printf(" %s\n", dataflash_info[i].Device.area_list[j].label);
 241                                        break;
 242                                case    FLAG_PROTECT_INVALID:
 243                                        break;
 244                                }
 245                        }
 246                }
 247        }
 248}
 249
 250/*---------------------------------------------------------------------------*/
 251/* Function Name       : AT91F_DataflashSelect                               */
 252/* Object              : Select the correct device                           */
 253/*---------------------------------------------------------------------------*/
 254AT91PS_DataFlash AT91F_DataflashSelect (AT91PS_DataFlash pFlash,
 255                                unsigned long *addr)
 256{
 257        char addr_valid = 0;
 258        int i;
 259
 260        for (i = 0; i < CONFIG_SYS_MAX_DATAFLASH_BANKS; i++)
 261                if ( dataflash_info[i].id
 262                        && ((((int) *addr) & 0xFF000000) ==
 263                        dataflash_info[i].logical_address)) {
 264                        addr_valid = 1;
 265                        break;
 266                }
 267        if (!addr_valid) {
 268                pFlash = (AT91PS_DataFlash) 0;
 269                return pFlash;
 270        }
 271        pFlash->pDataFlashDesc = &(dataflash_info[i].Desc);
 272        pFlash->pDevice = &(dataflash_info[i].Device);
 273        *addr -= dataflash_info[i].logical_address;
 274        return (pFlash);
 275}
 276
 277/*---------------------------------------------------------------------------*/
 278/* Function Name       : addr_dataflash                                      */
 279/* Object              : Test if address is valid                            */
 280/*---------------------------------------------------------------------------*/
 281int addr_dataflash (unsigned long addr)
 282{
 283        int addr_valid = 0;
 284        int i;
 285
 286        for (i = 0; i < CONFIG_SYS_MAX_DATAFLASH_BANKS; i++) {
 287                if ((((int) addr) & 0xFF000000) ==
 288                        dataflash_info[i].logical_address) {
 289                        addr_valid = 1;
 290                        break;
 291                }
 292        }
 293
 294        return addr_valid;
 295}
 296
 297/*---------------------------------------------------------------------------*/
 298/* Function Name       : size_dataflash                                      */
 299/* Object              : Test if address is valid regarding the size         */
 300/*---------------------------------------------------------------------------*/
 301int size_dataflash (AT91PS_DataFlash pdataFlash, unsigned long addr,
 302                        unsigned long size)
 303{
 304        /* is outside the dataflash */
 305        if (((int)addr & 0x0FFFFFFF) > (pdataFlash->pDevice->pages_size *
 306                pdataFlash->pDevice->pages_number)) return 0;
 307        /* is too large for the dataflash */
 308        if (size > ((pdataFlash->pDevice->pages_size *
 309                pdataFlash->pDevice->pages_number) -
 310                ((int)addr & 0x0FFFFFFF))) return 0;
 311
 312        return 1;
 313}
 314
 315/*---------------------------------------------------------------------------*/
 316/* Function Name       : prot_dataflash                                      */
 317/* Object              : Test if destination area is protected               */
 318/*---------------------------------------------------------------------------*/
 319int prot_dataflash (AT91PS_DataFlash pdataFlash, unsigned long addr)
 320{
 321        int area;
 322
 323        /* find area */
 324        for (area = 0; area < NB_DATAFLASH_AREA; area++) {
 325                if ((addr >= pdataFlash->pDevice->area_list[area].start) &&
 326                        (addr < pdataFlash->pDevice->area_list[area].end))
 327                        break;
 328        }
 329        if (area == NB_DATAFLASH_AREA)
 330                return -1;
 331
 332        /*test protection value*/
 333        if (pdataFlash->pDevice->area_list[area].protected == FLAG_PROTECT_SET)
 334                return 0;
 335        if (pdataFlash->pDevice->area_list[area].protected == FLAG_PROTECT_INVALID)
 336                return 0;
 337
 338        return 1;
 339}
 340
 341/*--------------------------------------------------------------------------*/
 342/* Function Name       : dataflash_real_protect                             */
 343/* Object              : protect/unprotect area                             */
 344/*--------------------------------------------------------------------------*/
 345int dataflash_real_protect (int flag, unsigned long start_addr,
 346                                unsigned long end_addr)
 347{
 348        int i,j, area1, area2, addr_valid = 0;
 349
 350        /* find dataflash */
 351        for (i = 0; i < CONFIG_SYS_MAX_DATAFLASH_BANKS; i++) {
 352                if ((((int) start_addr) & 0xF0000000) ==
 353                        dataflash_info[i].logical_address) {
 354                                addr_valid = 1;
 355                                break;
 356                }
 357        }
 358        if (!addr_valid) {
 359                return -1;
 360        }
 361        /* find start area */
 362        for (area1 = 0; area1 < NB_DATAFLASH_AREA; area1++) {
 363                if (start_addr == dataflash_info[i].Device.area_list[area1].start)
 364                        break;
 365        }
 366        if (area1 == NB_DATAFLASH_AREA) return -1;
 367        /* find end area */
 368        for (area2 = 0; area2 < NB_DATAFLASH_AREA; area2++) {
 369                if (end_addr == dataflash_info[i].Device.area_list[area2].end)
 370                        break;
 371        }
 372        if (area2 == NB_DATAFLASH_AREA)
 373                return -1;
 374
 375        /*set protection value*/
 376        for(j = area1; j < area2 + 1 ; j++)
 377                if(dataflash_info[i].Device.area_list[j].protected
 378                                != FLAG_PROTECT_INVALID) {
 379                        if (flag == 0) {
 380                                dataflash_info[i].Device.area_list[j].protected
 381                                        = FLAG_PROTECT_CLEAR;
 382                        } else {
 383                                dataflash_info[i].Device.area_list[j].protected
 384                                        = FLAG_PROTECT_SET;
 385                        }
 386                }
 387
 388        return (area2 - area1 + 1);
 389}
 390
 391/*---------------------------------------------------------------------------*/
 392/* Function Name       : read_dataflash                                      */
 393/* Object              : dataflash memory read                               */
 394/*---------------------------------------------------------------------------*/
 395int read_dataflash (unsigned long addr, unsigned long size, char *result)
 396{
 397        unsigned long AddrToRead = addr;
 398        AT91PS_DataFlash pFlash = &DataFlashInst;
 399
 400        pFlash = AT91F_DataflashSelect (pFlash, &AddrToRead);
 401
 402        if (pFlash == 0)
 403                return ERR_UNKNOWN_FLASH_TYPE;
 404
 405        if (size_dataflash(pFlash,addr,size) == 0)
 406                return ERR_INVAL;
 407
 408        return (AT91F_DataFlashRead (pFlash, AddrToRead, size, result));
 409}
 410
 411/*---------------------------------------------------------------------------*/
 412/* Function Name       : write_dataflash                                     */
 413/* Object              : write a block in dataflash                          */
 414/*---------------------------------------------------------------------------*/
 415int write_dataflash (unsigned long addr_dest, unsigned long addr_src,
 416                        unsigned long size)
 417{
 418        unsigned long AddrToWrite = addr_dest;
 419        AT91PS_DataFlash pFlash = &DataFlashInst;
 420
 421        pFlash = AT91F_DataflashSelect (pFlash, &AddrToWrite);
 422
 423        if (pFlash == 0)
 424                return ERR_UNKNOWN_FLASH_TYPE;
 425
 426        if (size_dataflash(pFlash,addr_dest,size) == 0)
 427                return ERR_INVAL;
 428
 429        if (prot_dataflash(pFlash,addr_dest) == 0)
 430                return ERR_PROTECTED;
 431
 432        if (AddrToWrite == -1)
 433                return -1;
 434
 435        return AT91F_DataFlashWrite (pFlash, (uchar *)addr_src,
 436                                                AddrToWrite, size);
 437}
 438
 439void dataflash_perror (int err)
 440{
 441        switch (err) {
 442        case ERR_OK:
 443                break;
 444        case ERR_TIMOUT:
 445                printf("Timeout writing to DataFlash\n");
 446                break;
 447        case ERR_PROTECTED:
 448                printf("Can't write to protected/invalid DataFlash sectors\n");
 449                break;
 450        case ERR_INVAL:
 451                printf("Outside available DataFlash\n");
 452                break;
 453        case ERR_UNKNOWN_FLASH_TYPE:
 454                printf("Unknown Type of DataFlash\n");
 455                break;
 456        case ERR_PROG_ERROR:
 457                printf("General DataFlash Programming Error\n");
 458                break;
 459        default:
 460                printf("%s[%d] FIXME: rc=%d\n", __FILE__, __LINE__, err);
 461                break;
 462        }
 463}
 464