uboot/board/cobra5272/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000-2003
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <common.h>
   9#include <console.h>
  10
  11#define PHYS_FLASH_1 CONFIG_SYS_FLASH_BASE
  12#define FLASH_BANK_SIZE 0x200000
  13
  14flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
  15
  16void flash_print_info (flash_info_t * info)
  17{
  18        int i;
  19
  20        switch (info->flash_id & FLASH_VENDMASK) {
  21        case (AMD_MANUFACT & FLASH_VENDMASK):
  22                printf ("AMD: ");
  23                break;
  24        default:
  25                printf ("Unknown Vendor ");
  26                break;
  27        }
  28
  29        switch (info->flash_id & FLASH_TYPEMASK) {
  30        case (AMD_ID_PL160CB & FLASH_TYPEMASK):
  31                printf ("AM29PL160CB (16Mbit)\n");
  32                break;
  33        default:
  34                printf ("Unknown Chip Type\n");
  35                goto Done;
  36                break;
  37        }
  38
  39        printf ("  Size: %ld MB in %d Sectors\n",
  40                info->size >> 20, info->sector_count);
  41
  42        printf ("  Sector Start Addresses:");
  43        for (i = 0; i < info->sector_count; i++) {
  44                if ((i % 5) == 0) {
  45                        printf ("\n   ");
  46                }
  47                printf (" %08lX%s", info->start[i],
  48                        info->protect[i] ? " (RO)" : "     ");
  49        }
  50        printf ("\n");
  51
  52Done:
  53        return;
  54}
  55
  56
  57unsigned long flash_init (void)
  58{
  59        int i, j;
  60        ulong size = 0;
  61
  62        for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
  63                ulong flashbase = 0;
  64
  65                flash_info[i].flash_id =
  66                        (AMD_MANUFACT & FLASH_VENDMASK) |
  67                        (AMD_ID_PL160CB & FLASH_TYPEMASK);
  68                flash_info[i].size = FLASH_BANK_SIZE;
  69                flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
  70                memset (flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
  71                if (i == 0)
  72                        flashbase = PHYS_FLASH_1;
  73                else
  74                        panic ("configured to many flash banks!\n");
  75
  76                for (j = 0; j < flash_info[i].sector_count; j++) {
  77                        if (j == 0) {
  78                                /* 1st is 16 KiB */
  79                                flash_info[i].start[j] = flashbase;
  80                        }
  81                        if ((j >= 1) && (j <= 2)) {
  82                                /* 2nd and 3rd are 8 KiB */
  83                                flash_info[i].start[j] =
  84                                        flashbase + 0x4000 + 0x2000 * (j - 1);
  85                        }
  86                        if (j == 3) {
  87                                /* 4th is 224 KiB */
  88                                flash_info[i].start[j] = flashbase + 0x8000;
  89                        }
  90                        if ((j >= 4) && (j <= 10)) {
  91                                /* rest is 256 KiB */
  92                                flash_info[i].start[j] =
  93                                        flashbase + 0x40000 + 0x40000 * (j -
  94                                                                         4);
  95                        }
  96                }
  97                size += flash_info[i].size;
  98        }
  99
 100        flash_protect (FLAG_PROTECT_SET,
 101                       CONFIG_SYS_FLASH_BASE,
 102                       CONFIG_SYS_FLASH_BASE + 0x3ffff, &flash_info[0]);
 103
 104        return size;
 105}
 106
 107
 108#define CMD_READ_ARRAY          0x00F0
 109#define CMD_UNLOCK1             0x00AA
 110#define CMD_UNLOCK2             0x0055
 111#define CMD_ERASE_SETUP         0x0080
 112#define CMD_ERASE_CONFIRM       0x0030
 113#define CMD_PROGRAM             0x00A0
 114#define CMD_UNLOCK_BYPASS       0x0020
 115
 116#define MEM_FLASH_ADDR1         (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x00000555<<1)))
 117#define MEM_FLASH_ADDR2         (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x000002AA<<1)))
 118
 119#define BIT_ERASE_DONE          0x0080
 120#define BIT_RDY_MASK            0x0080
 121#define BIT_PROGRAM_ERROR       0x0020
 122#define BIT_TIMEOUT             0x80000000      /* our flag */
 123
 124#define READY 1
 125#define ERR   2
 126#define TMO   4
 127
 128
 129int flash_erase (flash_info_t * info, int s_first, int s_last)
 130{
 131        ulong result;
 132        int iflag, cflag, prot, sect;
 133        int rc = ERR_OK;
 134        int chip1;
 135        ulong start;
 136
 137        /* first look for protection bits */
 138
 139        if (info->flash_id == FLASH_UNKNOWN)
 140                return ERR_UNKNOWN_FLASH_TYPE;
 141
 142        if ((s_first < 0) || (s_first > s_last)) {
 143                return ERR_INVAL;
 144        }
 145
 146        if ((info->flash_id & FLASH_VENDMASK) !=
 147            (AMD_MANUFACT & FLASH_VENDMASK)) {
 148                return ERR_UNKNOWN_FLASH_VENDOR;
 149        }
 150
 151        prot = 0;
 152        for (sect = s_first; sect <= s_last; ++sect) {
 153                if (info->protect[sect]) {
 154                        prot++;
 155                }
 156        }
 157        if (prot)
 158                return ERR_PROTECTED;
 159
 160        /*
 161         * Disable interrupts which might cause a timeout
 162         * here. Remember that our exception vectors are
 163         * at address 0 in the flash, and we don't want a
 164         * (ticker) exception to happen while the flash
 165         * chip is in programming mode.
 166         */
 167
 168        cflag = icache_status ();
 169        icache_disable ();
 170        iflag = disable_interrupts ();
 171
 172        printf ("\n");
 173
 174        /* Start erase on unprotected sectors */
 175        for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
 176                printf ("Erasing sector %2d ... ", sect);
 177
 178                /* arm simple, non interrupt dependent timer */
 179                start = get_timer(0);
 180
 181                if (info->protect[sect] == 0) { /* not protected */
 182                        volatile u16 *addr =
 183                                (volatile u16 *) (info->start[sect]);
 184
 185                        MEM_FLASH_ADDR1 = CMD_UNLOCK1;
 186                        MEM_FLASH_ADDR2 = CMD_UNLOCK2;
 187                        MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
 188
 189                        MEM_FLASH_ADDR1 = CMD_UNLOCK1;
 190                        MEM_FLASH_ADDR2 = CMD_UNLOCK2;
 191                        *addr = CMD_ERASE_CONFIRM;
 192
 193                        /* wait until flash is ready */
 194                        chip1 = 0;
 195
 196                        do {
 197                                result = *addr;
 198
 199                                /* check timeout */
 200                                if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 201                                        MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
 202                                        chip1 = TMO;
 203                                        break;
 204                                }
 205
 206                                if (!chip1
 207                                    && (result & 0xFFFF) & BIT_ERASE_DONE)
 208                                        chip1 = READY;
 209
 210                        } while (!chip1);
 211
 212                        MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
 213
 214                        if (chip1 == ERR) {
 215                                rc = ERR_PROG_ERROR;
 216                                goto outahere;
 217                        }
 218                        if (chip1 == TMO) {
 219                                rc = ERR_TIMOUT;
 220                                goto outahere;
 221                        }
 222
 223                        printf ("ok.\n");
 224                } else {        /* it was protected */
 225
 226                        printf ("protected!\n");
 227                }
 228        }
 229
 230        if (ctrlc ())
 231                printf ("User Interrupt!\n");
 232
 233      outahere:
 234        /* allow flash to settle - wait 10 ms */
 235        udelay (10000);
 236
 237        if (iflag)
 238                enable_interrupts ();
 239
 240        if (cflag)
 241                icache_enable ();
 242
 243        return rc;
 244}
 245
 246static int write_word (flash_info_t * info, ulong dest, ulong data)
 247{
 248        volatile u16 *addr = (volatile u16 *) dest;
 249        ulong result;
 250        int rc = ERR_OK;
 251        int cflag, iflag;
 252        int chip1;
 253        ulong start;
 254
 255        /*
 256         * Check if Flash is (sufficiently) erased
 257         */
 258        result = *addr;
 259        if ((result & data) != data)
 260                return ERR_NOT_ERASED;
 261
 262
 263        /*
 264         * Disable interrupts which might cause a timeout
 265         * here. Remember that our exception vectors are
 266         * at address 0 in the flash, and we don't want a
 267         * (ticker) exception to happen while the flash
 268         * chip is in programming mode.
 269         */
 270
 271        cflag = icache_status ();
 272        icache_disable ();
 273        iflag = disable_interrupts ();
 274
 275        MEM_FLASH_ADDR1 = CMD_UNLOCK1;
 276        MEM_FLASH_ADDR2 = CMD_UNLOCK2;
 277        MEM_FLASH_ADDR1 = CMD_PROGRAM;
 278        *addr = data;
 279
 280        /* arm simple, non interrupt dependent timer */
 281        start = get_timer(0);
 282
 283        /* wait until flash is ready */
 284        chip1 = 0;
 285        do {
 286                result = *addr;
 287
 288                /* check timeout */
 289                if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 290                        chip1 = ERR | TMO;
 291                        break;
 292                }
 293                if (!chip1 && ((result & 0x80) == (data & 0x80)))
 294                        chip1 = READY;
 295
 296        } while (!chip1);
 297
 298        *addr = CMD_READ_ARRAY;
 299
 300        if (chip1 == ERR || *addr != data)
 301                rc = ERR_PROG_ERROR;
 302
 303        if (iflag)
 304                enable_interrupts ();
 305
 306        if (cflag)
 307                icache_enable ();
 308
 309        return rc;
 310}
 311
 312
 313int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
 314{
 315        ulong wp, data;
 316        int rc;
 317
 318        if (addr & 1) {
 319                printf ("unaligned destination not supported\n");
 320                return ERR_ALIGN;
 321        }
 322
 323#if 0
 324        if (cnt & 1) {
 325                printf ("odd transfer sizes not supported\n");
 326                return ERR_ALIGN;
 327        }
 328#endif
 329
 330        wp = addr;
 331
 332        if (addr & 1) {
 333                data = (*((volatile u8 *) addr) << 8) | *((volatile u8 *)
 334                                                          src);
 335                if ((rc = write_word (info, wp - 1, data)) != 0) {
 336                        return (rc);
 337                }
 338                src += 1;
 339                wp += 1;
 340                cnt -= 1;
 341        }
 342
 343        while (cnt >= 2) {
 344                data = *((volatile u16 *) src);
 345                if ((rc = write_word (info, wp, data)) != 0) {
 346                        return (rc);
 347                }
 348                src += 2;
 349                wp += 2;
 350                cnt -= 2;
 351        }
 352
 353        if (cnt == 1) {
 354                data = (*((volatile u8 *) src) << 8) |
 355                        *((volatile u8 *) (wp + 1));
 356                if ((rc = write_word (info, wp, data)) != 0) {
 357                        return (rc);
 358                }
 359                src += 1;
 360                wp += 1;
 361                cnt -= 1;
 362        }
 363
 364        return ERR_OK;
 365}
 366