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