uboot/drivers/mtd/spi/sf_ops.c
<<
>>
Prefs
   1/*
   2 * SPI flash operations
   3 *
   4 * Copyright (C) 2008 Atmel Corporation
   5 * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
   6 * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
   7 *
   8 * SPDX-License-Identifier:     GPL-2.0+
   9 */
  10
  11#include <common.h>
  12#include <errno.h>
  13#include <malloc.h>
  14#include <spi.h>
  15#include <spi_flash.h>
  16#include <watchdog.h>
  17
  18#include "sf_internal.h"
  19
  20static void spi_flash_addr(u32 addr, u8 *cmd)
  21{
  22        /* cmd[0] is actual command */
  23        cmd[1] = addr >> 16;
  24        cmd[2] = addr >> 8;
  25        cmd[3] = addr >> 0;
  26}
  27
  28int spi_flash_cmd_read_status(struct spi_flash *flash, u8 *rs)
  29{
  30        int ret;
  31        u8 cmd;
  32
  33        cmd = CMD_READ_STATUS;
  34        ret = spi_flash_read_common(flash, &cmd, 1, rs, 1);
  35        if (ret < 0) {
  36                debug("SF: fail to read status register\n");
  37                return ret;
  38        }
  39
  40        return 0;
  41}
  42
  43int spi_flash_cmd_write_status(struct spi_flash *flash, u8 ws)
  44{
  45        u8 cmd;
  46        int ret;
  47
  48        cmd = CMD_WRITE_STATUS;
  49        ret = spi_flash_write_common(flash, &cmd, 1, &ws, 1);
  50        if (ret < 0) {
  51                debug("SF: fail to write status register\n");
  52                return ret;
  53        }
  54
  55        return 0;
  56}
  57
  58#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND)
  59int spi_flash_cmd_read_config(struct spi_flash *flash, u8 *rc)
  60{
  61        int ret;
  62        u8 cmd;
  63
  64        cmd = CMD_READ_CONFIG;
  65        ret = spi_flash_read_common(flash, &cmd, 1, rc, 1);
  66        if (ret < 0) {
  67                debug("SF: fail to read config register\n");
  68                return ret;
  69        }
  70
  71        return 0;
  72}
  73
  74int spi_flash_cmd_write_config(struct spi_flash *flash, u8 wc)
  75{
  76        u8 data[2];
  77        u8 cmd;
  78        int ret;
  79
  80        ret = spi_flash_cmd_read_status(flash, &data[0]);
  81        if (ret < 0)
  82                return ret;
  83
  84        cmd = CMD_WRITE_STATUS;
  85        data[1] = wc;
  86        ret = spi_flash_write_common(flash, &cmd, 1, &data, 2);
  87        if (ret) {
  88                debug("SF: fail to write config register\n");
  89                return ret;
  90        }
  91
  92        return 0;
  93}
  94#endif
  95
  96#ifdef CONFIG_SPI_FLASH_BAR
  97static int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel)
  98{
  99        u8 cmd;
 100        int ret;
 101
 102        if (flash->bank_curr == bank_sel) {
 103                debug("SF: not require to enable bank%d\n", bank_sel);
 104                return 0;
 105        }
 106
 107        cmd = flash->bank_write_cmd;
 108        ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1);
 109        if (ret < 0) {
 110                debug("SF: fail to write bank register\n");
 111                return ret;
 112        }
 113        flash->bank_curr = bank_sel;
 114
 115        return 0;
 116}
 117
 118static int spi_flash_bank(struct spi_flash *flash, u32 offset)
 119{
 120        u8 bank_sel;
 121        int ret;
 122
 123        bank_sel = offset / (SPI_FLASH_16MB_BOUN << flash->shift);
 124
 125        ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
 126        if (ret) {
 127                debug("SF: fail to set bank%d\n", bank_sel);
 128                return ret;
 129        }
 130
 131        return bank_sel;
 132}
 133#endif
 134
 135#ifdef CONFIG_SF_DUAL_FLASH
 136static void spi_flash_dual_flash(struct spi_flash *flash, u32 *addr)
 137{
 138        switch (flash->dual_flash) {
 139        case SF_DUAL_STACKED_FLASH:
 140                if (*addr >= (flash->size >> 1)) {
 141                        *addr -= flash->size >> 1;
 142                        flash->spi->flags |= SPI_XFER_U_PAGE;
 143                } else {
 144                        flash->spi->flags &= ~SPI_XFER_U_PAGE;
 145                }
 146                break;
 147        case SF_DUAL_PARALLEL_FLASH:
 148                *addr >>= flash->shift;
 149                break;
 150        default:
 151                debug("SF: Unsupported dual_flash=%d\n", flash->dual_flash);
 152                break;
 153        }
 154}
 155#endif
 156
 157int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
 158{
 159        struct spi_slave *spi = flash->spi;
 160        unsigned long timebase;
 161        unsigned long flags = SPI_XFER_BEGIN;
 162        int ret;
 163        u8 status;
 164        u8 check_status = 0x0;
 165        u8 poll_bit = STATUS_WIP;
 166        u8 cmd = flash->poll_cmd;
 167
 168        if (cmd == CMD_FLAG_STATUS) {
 169                poll_bit = STATUS_PEC;
 170                check_status = poll_bit;
 171        }
 172
 173#ifdef CONFIG_SF_DUAL_FLASH
 174        if (spi->flags & SPI_XFER_U_PAGE)
 175                flags |= SPI_XFER_U_PAGE;
 176#endif
 177        ret = spi_xfer(spi, 8, &cmd, NULL, flags);
 178        if (ret) {
 179                debug("SF: fail to read %s status register\n",
 180                      cmd == CMD_READ_STATUS ? "read" : "flag");
 181                return ret;
 182        }
 183
 184        timebase = get_timer(0);
 185        do {
 186                WATCHDOG_RESET();
 187
 188                ret = spi_xfer(spi, 8, NULL, &status, 0);
 189                if (ret)
 190                        return -1;
 191
 192                if ((status & poll_bit) == check_status)
 193                        break;
 194
 195        } while (get_timer(timebase) < timeout);
 196
 197        spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
 198
 199        if ((status & poll_bit) == check_status)
 200                return 0;
 201
 202        /* Timed out */
 203        debug("SF: time out!\n");
 204        return -1;
 205}
 206
 207int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
 208                size_t cmd_len, const void *buf, size_t buf_len)
 209{
 210        struct spi_slave *spi = flash->spi;
 211        unsigned long timeout = SPI_FLASH_PROG_TIMEOUT;
 212        int ret;
 213
 214        if (buf == NULL)
 215                timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT;
 216
 217        ret = spi_claim_bus(flash->spi);
 218        if (ret) {
 219                debug("SF: unable to claim SPI bus\n");
 220                return ret;
 221        }
 222
 223        ret = spi_flash_cmd_write_enable(flash);
 224        if (ret < 0) {
 225                debug("SF: enabling write failed\n");
 226                return ret;
 227        }
 228
 229        ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len);
 230        if (ret < 0) {
 231                debug("SF: write cmd failed\n");
 232                return ret;
 233        }
 234
 235        ret = spi_flash_cmd_wait_ready(flash, timeout);
 236        if (ret < 0) {
 237                debug("SF: write %s timed out\n",
 238                      timeout == SPI_FLASH_PROG_TIMEOUT ?
 239                        "program" : "page erase");
 240                return ret;
 241        }
 242
 243        spi_release_bus(spi);
 244
 245        return ret;
 246}
 247
 248int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
 249{
 250        u32 erase_size, erase_addr;
 251        u8 cmd[SPI_FLASH_CMD_LEN];
 252        int ret = -1;
 253
 254        erase_size = flash->erase_size;
 255        if (offset % erase_size || len % erase_size) {
 256                debug("SF: Erase offset/length not multiple of erase size\n");
 257                return -1;
 258        }
 259
 260        cmd[0] = flash->erase_cmd;
 261        while (len) {
 262                erase_addr = offset;
 263
 264#ifdef CONFIG_SF_DUAL_FLASH
 265                if (flash->dual_flash > SF_SINGLE_FLASH)
 266                        spi_flash_dual_flash(flash, &erase_addr);
 267#endif
 268#ifdef CONFIG_SPI_FLASH_BAR
 269                ret = spi_flash_bank(flash, erase_addr);
 270                if (ret < 0)
 271                        return ret;
 272#endif
 273                spi_flash_addr(erase_addr, cmd);
 274
 275                debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
 276                      cmd[2], cmd[3], erase_addr);
 277
 278                ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
 279                if (ret < 0) {
 280                        debug("SF: erase failed\n");
 281                        break;
 282                }
 283
 284                offset += erase_size;
 285                len -= erase_size;
 286        }
 287
 288        return ret;
 289}
 290
 291int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
 292                size_t len, const void *buf)
 293{
 294        unsigned long byte_addr, page_size;
 295        u32 write_addr;
 296        size_t chunk_len, actual;
 297        u8 cmd[SPI_FLASH_CMD_LEN];
 298        int ret = -1;
 299
 300        page_size = flash->page_size;
 301
 302        cmd[0] = flash->write_cmd;
 303        for (actual = 0; actual < len; actual += chunk_len) {
 304                write_addr = offset;
 305
 306#ifdef CONFIG_SF_DUAL_FLASH
 307                if (flash->dual_flash > SF_SINGLE_FLASH)
 308                        spi_flash_dual_flash(flash, &write_addr);
 309#endif
 310#ifdef CONFIG_SPI_FLASH_BAR
 311                ret = spi_flash_bank(flash, write_addr);
 312                if (ret < 0)
 313                        return ret;
 314#endif
 315                byte_addr = offset % page_size;
 316                chunk_len = min(len - actual, (size_t)(page_size - byte_addr));
 317
 318                if (flash->spi->max_write_size)
 319                        chunk_len = min(chunk_len,
 320                                        (size_t)flash->spi->max_write_size);
 321
 322                spi_flash_addr(write_addr, cmd);
 323
 324                debug("SF: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
 325                      buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
 326
 327                ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
 328                                        buf + actual, chunk_len);
 329                if (ret < 0) {
 330                        debug("SF: write failed\n");
 331                        break;
 332                }
 333
 334                offset += chunk_len;
 335        }
 336
 337        return ret;
 338}
 339
 340int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
 341                size_t cmd_len, void *data, size_t data_len)
 342{
 343        struct spi_slave *spi = flash->spi;
 344        int ret;
 345
 346        ret = spi_claim_bus(flash->spi);
 347        if (ret) {
 348                debug("SF: unable to claim SPI bus\n");
 349                return ret;
 350        }
 351
 352        ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
 353        if (ret < 0) {
 354                debug("SF: read cmd failed\n");
 355                return ret;
 356        }
 357
 358        spi_release_bus(spi);
 359
 360        return ret;
 361}
 362
 363int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
 364                size_t len, void *data)
 365{
 366        u8 *cmd, cmdsz;
 367        u32 remain_len, read_len, read_addr;
 368        int bank_sel = 0;
 369        int ret = -1;
 370
 371        /* Handle memory-mapped SPI */
 372        if (flash->memory_map) {
 373                ret = spi_claim_bus(flash->spi);
 374                if (ret) {
 375                        debug("SF: unable to claim SPI bus\n");
 376                        return ret;
 377                }
 378                spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP);
 379                memcpy(data, flash->memory_map + offset, len);
 380                spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP_END);
 381                spi_release_bus(flash->spi);
 382                return 0;
 383        }
 384
 385        cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte;
 386        cmd = calloc(1, cmdsz);
 387        if (!cmd) {
 388                debug("SF: Failed to allocate cmd\n");
 389                return -ENOMEM;
 390        }
 391
 392        cmd[0] = flash->read_cmd;
 393        while (len) {
 394                read_addr = offset;
 395
 396#ifdef CONFIG_SF_DUAL_FLASH
 397                if (flash->dual_flash > SF_SINGLE_FLASH)
 398                        spi_flash_dual_flash(flash, &read_addr);
 399#endif
 400#ifdef CONFIG_SPI_FLASH_BAR
 401                bank_sel = spi_flash_bank(flash, read_addr);
 402                if (bank_sel < 0)
 403                        return ret;
 404#endif
 405                remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) *
 406                                (bank_sel + 1)) - offset;
 407                if (len < remain_len)
 408                        read_len = len;
 409                else
 410                        read_len = remain_len;
 411
 412                spi_flash_addr(read_addr, cmd);
 413
 414                ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
 415                if (ret < 0) {
 416                        debug("SF: read failed\n");
 417                        break;
 418                }
 419
 420                offset += read_len;
 421                len -= read_len;
 422                data += read_len;
 423        }
 424
 425        free(cmd);
 426        return ret;
 427}
 428
 429#ifdef CONFIG_SPI_FLASH_SST
 430static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
 431{
 432        int ret;
 433        u8 cmd[4] = {
 434                CMD_SST_BP,
 435                offset >> 16,
 436                offset >> 8,
 437                offset,
 438        };
 439
 440        debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
 441              spi_w8r8(flash->spi, CMD_READ_STATUS), buf, cmd[0], offset);
 442
 443        ret = spi_flash_cmd_write_enable(flash);
 444        if (ret)
 445                return ret;
 446
 447        ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf, 1);
 448        if (ret)
 449                return ret;
 450
 451        return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
 452}
 453
 454int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
 455                const void *buf)
 456{
 457        size_t actual, cmd_len;
 458        int ret;
 459        u8 cmd[4];
 460
 461        ret = spi_claim_bus(flash->spi);
 462        if (ret) {
 463                debug("SF: Unable to claim SPI bus\n");
 464                return ret;
 465        }
 466
 467        /* If the data is not word aligned, write out leading single byte */
 468        actual = offset % 2;
 469        if (actual) {
 470                ret = sst_byte_write(flash, offset, buf);
 471                if (ret)
 472                        goto done;
 473        }
 474        offset += actual;
 475
 476        ret = spi_flash_cmd_write_enable(flash);
 477        if (ret)
 478                goto done;
 479
 480        cmd_len = 4;
 481        cmd[0] = CMD_SST_AAI_WP;
 482        cmd[1] = offset >> 16;
 483        cmd[2] = offset >> 8;
 484        cmd[3] = offset;
 485
 486        for (; actual < len - 1; actual += 2) {
 487                debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
 488                      spi_w8r8(flash->spi, CMD_READ_STATUS), buf + actual,
 489                      cmd[0], offset);
 490
 491                ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len,
 492                                        buf + actual, 2);
 493                if (ret) {
 494                        debug("SF: sst word program failed\n");
 495                        break;
 496                }
 497
 498                ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
 499                if (ret)
 500                        break;
 501
 502                cmd_len = 1;
 503                offset += 2;
 504        }
 505
 506        if (!ret)
 507                ret = spi_flash_cmd_write_disable(flash);
 508
 509        /* If there is a single trailing byte, write it out */
 510        if (!ret && actual != len)
 511                ret = sst_byte_write(flash, offset, buf + actual);
 512
 513 done:
 514        debug("SF: sst: program %s %zu bytes @ 0x%zx\n",
 515              ret ? "failure" : "success", len, offset - actual);
 516
 517        spi_release_bus(flash->spi);
 518        return ret;
 519}
 520
 521int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len,
 522                const void *buf)
 523{
 524        size_t actual;
 525        int ret;
 526
 527        ret = spi_claim_bus(flash->spi);
 528        if (ret) {
 529                debug("SF: Unable to claim SPI bus\n");
 530                return ret;
 531        }
 532
 533        for (actual = 0; actual < len; actual++) {
 534                ret = sst_byte_write(flash, offset, buf + actual);
 535                if (ret) {
 536                        debug("SF: sst byte program failed\n");
 537                        break;
 538                }
 539                offset++;
 540        }
 541
 542        if (!ret)
 543                ret = spi_flash_cmd_write_disable(flash);
 544
 545        debug("SF: sst: program %s %zu bytes @ 0x%zx\n",
 546              ret ? "failure" : "success", len, offset - actual);
 547
 548        spi_release_bus(flash->spi);
 549        return ret;
 550}
 551#endif
 552