uboot/drivers/mtd/spi/spi_flash.c
<<
>>
Prefs
   1/*
   2 * SPI flash interface
   3 *
   4 * Copyright (C) 2008 Atmel Corporation
   5 * Licensed under the GPL-2 or later.
   6 */
   7
   8#include <common.h>
   9#include <malloc.h>
  10#include <spi.h>
  11#include <spi_flash.h>
  12
  13#include "spi_flash_internal.h"
  14
  15int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len)
  16{
  17        unsigned long flags = SPI_XFER_BEGIN;
  18        int ret;
  19
  20        if (len == 0)
  21                flags |= SPI_XFER_END;
  22
  23        ret = spi_xfer(spi, 8, &cmd, NULL, flags);
  24        if (ret) {
  25                debug("SF: Failed to send command %02x: %d\n", cmd, ret);
  26                return ret;
  27        }
  28
  29        if (len) {
  30                ret = spi_xfer(spi, len * 8, NULL, response, SPI_XFER_END);
  31                if (ret)
  32                        debug("SF: Failed to read response (%zu bytes): %d\n",
  33                                        len, ret);
  34        }
  35
  36        return ret;
  37}
  38
  39int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
  40                size_t cmd_len, void *data, size_t data_len)
  41{
  42        unsigned long flags = SPI_XFER_BEGIN;
  43        int ret;
  44
  45        if (data_len == 0)
  46                flags |= SPI_XFER_END;
  47
  48        ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags);
  49        if (ret) {
  50                debug("SF: Failed to send read command (%zu bytes): %d\n",
  51                                cmd_len, ret);
  52        } else if (data_len != 0) {
  53                ret = spi_xfer(spi, data_len * 8, NULL, data, SPI_XFER_END);
  54                if (ret)
  55                        debug("SF: Failed to read %zu bytes of data: %d\n",
  56                                        data_len, ret);
  57        }
  58
  59        return ret;
  60}
  61
  62int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
  63                const void *data, size_t data_len)
  64{
  65        unsigned long flags = SPI_XFER_BEGIN;
  66        int ret;
  67
  68        if (data_len == 0)
  69                flags |= SPI_XFER_END;
  70
  71        ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags);
  72        if (ret) {
  73                debug("SF: Failed to send read command (%zu bytes): %d\n",
  74                                cmd_len, ret);
  75        } else if (data_len != 0) {
  76                ret = spi_xfer(spi, data_len * 8, data, NULL, SPI_XFER_END);
  77                if (ret)
  78                        debug("SF: Failed to read %zu bytes of data: %d\n",
  79                                        data_len, ret);
  80        }
  81
  82        return ret;
  83}
  84
  85
  86int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
  87                size_t cmd_len, void *data, size_t data_len)
  88{
  89        struct spi_slave *spi = flash->spi;
  90        int ret;
  91
  92        spi_claim_bus(spi);
  93        ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
  94        spi_release_bus(spi);
  95
  96        return ret;
  97}
  98
  99struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
 100                unsigned int max_hz, unsigned int spi_mode)
 101{
 102        struct spi_slave *spi;
 103        struct spi_flash *flash;
 104        int ret;
 105        u8 idcode[5];
 106
 107        spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
 108        if (!spi) {
 109                debug("SF: Failed to set up slave\n");
 110                return NULL;
 111        }
 112
 113        ret = spi_claim_bus(spi);
 114        if (ret) {
 115                debug("SF: Failed to claim SPI bus: %d\n", ret);
 116                goto err_claim_bus;
 117        }
 118
 119        /* Read the ID codes */
 120        ret = spi_flash_cmd(spi, CMD_READ_ID, &idcode, sizeof(idcode));
 121        if (ret)
 122                goto err_read_id;
 123
 124        debug("SF: Got idcode %02x %02x %02x %02x %02x\n", idcode[0],
 125                        idcode[1], idcode[2], idcode[3], idcode[4]);
 126
 127        switch (idcode[0]) {
 128#ifdef CONFIG_SPI_FLASH_SPANSION
 129        case 0x01:
 130                flash = spi_flash_probe_spansion(spi, idcode);
 131                break;
 132#endif
 133#ifdef CONFIG_SPI_FLASH_ATMEL
 134        case 0x1F:
 135                flash = spi_flash_probe_atmel(spi, idcode);
 136                break;
 137#endif
 138#ifdef CONFIG_SPI_FLASH_MACRONIX
 139        case 0xc2:
 140                flash = spi_flash_probe_macronix(spi, idcode);
 141                break;
 142#endif
 143#ifdef CONFIG_SPI_FLASH_WINBOND
 144        case 0xef:
 145                flash = spi_flash_probe_winbond(spi, idcode);
 146                break;
 147#endif
 148#ifdef CONFIG_SPI_FLASH_STMICRO
 149        case 0x20:
 150                flash = spi_flash_probe_stmicro(spi, idcode);
 151                break;
 152#endif
 153#ifdef CONFIG_SPI_FLASH_SST
 154        case 0xBF:
 155                flash = spi_flash_probe_sst(spi, idcode);
 156                break;
 157#endif
 158        default:
 159                debug("SF: Unsupported manufacturer %02X\n", idcode[0]);
 160                flash = NULL;
 161                break;
 162        }
 163
 164        if (!flash)
 165                goto err_manufacturer_probe;
 166
 167        spi_release_bus(spi);
 168
 169        return flash;
 170
 171err_manufacturer_probe:
 172err_read_id:
 173        spi_release_bus(spi);
 174err_claim_bus:
 175        spi_free_slave(spi);
 176        return NULL;
 177}
 178
 179void spi_flash_free(struct spi_flash *flash)
 180{
 181        spi_free_slave(flash->spi);
 182        free(flash);
 183}
 184