uboot/drivers/mtd/spi/sf_probe.c
<<
>>
Prefs
   1/*
   2 * SPI flash probing
   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 <dm.h>
  13#include <errno.h>
  14#include <malloc.h>
  15#include <spi.h>
  16#include <spi_flash.h>
  17
  18#include "sf_internal.h"
  19
  20/**
  21 * spi_flash_probe_slave() - Probe for a SPI flash device on a bus
  22 *
  23 * @flashp: Pointer to place to put flash info, which may be NULL if the
  24 * space should be allocated
  25 */
  26static int spi_flash_probe_slave(struct spi_flash *flash)
  27{
  28        struct spi_slave *spi = flash->spi;
  29        int ret;
  30
  31        /* Setup spi_slave */
  32        if (!spi) {
  33                printf("SF: Failed to set up slave\n");
  34                return -ENODEV;
  35        }
  36
  37        /* Claim spi bus */
  38        ret = spi_claim_bus(spi);
  39        if (ret) {
  40                debug("SF: Failed to claim SPI bus: %d\n", ret);
  41                return ret;
  42        }
  43#if 0
  44        if (spi->option == SF_DUAL_PARALLEL_FLASH)
  45                spi->flags |= SPI_XFER_LOWER;
  46        /* Read the ID codes */
  47        ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
  48        if (ret) {
  49                printf("SF: Failed to get idcodes\n");
  50                goto err_read_id;
  51        }
  52
  53#ifdef CONFIG_SPI_GENERIC
  54        if (spi->option == SF_DUAL_PARALLEL_FLASH) {
  55                spi->flags |= SPI_XFER_UPPER;
  56                ret = spi_flash_cmd(spi, CMD_READ_ID, idcode_up,
  57                                    sizeof(idcode_up));
  58                if (ret) {
  59                        printf("SF: Failed to get idcodes\n");
  60                        goto err_read_id;
  61                }
  62                for (i = 0; i < sizeof(idcode); i++) {
  63                        if (idcode[i] != idcode_up[i]) {
  64                                printf("SF: Failed to get same idcodes\n");
  65                                goto err_read_id;
  66                        }
  67                }
  68        }
  69#endif
  70#ifdef DEBUG
  71        printf("SF: Got idcodes\n");
  72        print_buffer(0, idcode, 1, sizeof(idcode), 0);
  73#endif
  74
  75        if (spi_flash_validate_params(spi, idcode, flash)) {
  76
  77#endif
  78
  79        ret = spi_flash_scan(flash);
  80        if (ret)
  81                goto err_read_id;
  82
  83#ifdef CONFIG_SPI_FLASH_MTD
  84        ret = spi_flash_mtd_register(flash);
  85#endif
  86
  87err_read_id:
  88        spi_release_bus(spi);
  89        return ret;
  90}
  91
  92#ifndef CONFIG_DM_SPI_FLASH
  93static struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus)
  94{
  95        struct spi_flash *flash;
  96
  97        /* Allocate space if needed (not used by sf-uclass */
  98        flash = calloc(1, sizeof(*flash));
  99        if (!flash) {
 100                debug("SF: Failed to allocate spi_flash\n");
 101                return NULL;
 102        }
 103
 104        flash->spi = bus;
 105        if (spi_flash_probe_slave(flash)) {
 106                spi_free_slave(bus);
 107                free(flash);
 108                return NULL;
 109        }
 110
 111        return flash;
 112}
 113
 114struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs,
 115                unsigned int max_hz, unsigned int spi_mode)
 116{
 117        struct spi_slave *bus;
 118
 119        bus = spi_setup_slave(busnum, cs, max_hz, spi_mode);
 120        if (!bus)
 121                return NULL;
 122        return spi_flash_probe_tail(bus);
 123}
 124
 125#ifdef CONFIG_OF_SPI_FLASH
 126struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node,
 127                                      int spi_node)
 128{
 129        struct spi_slave *bus;
 130
 131        bus = spi_setup_slave_fdt(blob, slave_node, spi_node);
 132        if (!bus)
 133                return NULL;
 134        return spi_flash_probe_tail(bus);
 135}
 136#endif
 137
 138void spi_flash_free(struct spi_flash *flash)
 139{
 140#ifdef CONFIG_SPI_FLASH_MTD
 141        spi_flash_mtd_unregister();
 142#endif
 143        spi_free_slave(flash->spi);
 144        free(flash);
 145}
 146
 147#else /* defined CONFIG_DM_SPI_FLASH */
 148
 149static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len,
 150                              void *buf)
 151{
 152        struct spi_flash *flash = dev_get_uclass_priv(dev);
 153
 154        return spi_flash_cmd_read_ops(flash, offset, len, buf);
 155}
 156
 157static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len,
 158                        const void *buf)
 159{
 160        struct spi_flash *flash = dev_get_uclass_priv(dev);
 161
 162#if defined(CONFIG_SPI_FLASH_SST)
 163        if (flash->flags & SNOR_F_SST_WR) {
 164                if (flash->spi->mode & SPI_TX_BYTE)
 165                        return sst_write_bp(flash, offset, len, buf);
 166                else
 167                        return sst_write_wp(flash, offset, len, buf);
 168        }
 169#endif
 170
 171        return spi_flash_cmd_write_ops(flash, offset, len, buf);
 172}
 173
 174static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
 175{
 176        struct spi_flash *flash = dev_get_uclass_priv(dev);
 177
 178        return spi_flash_cmd_erase_ops(flash, offset, len);
 179}
 180
 181static int spi_flash_std_probe(struct udevice *dev)
 182{
 183        struct spi_slave *slave = dev_get_parent_priv(dev);
 184        struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
 185        struct spi_flash *flash;
 186
 187        flash = dev_get_uclass_priv(dev);
 188        flash->dev = dev;
 189        flash->spi = slave;
 190        debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs);
 191        return spi_flash_probe_slave(flash);
 192}
 193
 194static const struct dm_spi_flash_ops spi_flash_std_ops = {
 195        .read = spi_flash_std_read,
 196        .write = spi_flash_std_write,
 197        .erase = spi_flash_std_erase,
 198};
 199
 200static const struct udevice_id spi_flash_std_ids[] = {
 201        { .compatible = "spi-flash" },
 202        { }
 203};
 204
 205U_BOOT_DRIVER(spi_flash_std) = {
 206        .name           = "spi_flash_std",
 207        .id             = UCLASS_SPI_FLASH,
 208        .of_match       = spi_flash_std_ids,
 209        .probe          = spi_flash_std_probe,
 210        .priv_auto_alloc_size = sizeof(struct spi_flash),
 211        .ops            = &spi_flash_std_ops,
 212};
 213
 214#endif /* CONFIG_DM_SPI_FLASH */
 215