]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - drivers/mtd/spi/sf_probe.c
arm: mx6: remove CONFIG_ macros that are now included in Kconfig from header file
[karo-tx-uboot.git] / drivers / mtd / spi / sf_probe.c
index 4d148d1ace3749744cbc1e9ef190f5fdcb84649a..954376de15365f10fac0e378225e103e59a0ceec 100644 (file)
@@ -9,8 +9,11 @@
  */
 
 #include <common.h>
+#include <dm.h>
+#include <errno.h>
 #include <fdtdec.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <spi.h>
 #include <spi_flash.h>
 #include <asm/io.h>
@@ -22,6 +25,7 @@ DECLARE_GLOBAL_DATA_PTR;
 /* Read commands array */
 static u8 spi_read_cmds_array[] = {
        CMD_READ_ARRAY_SLOW,
+       CMD_READ_ARRAY_FAST,
        CMD_READ_DUAL_OUTPUT_FAST,
        CMD_READ_DUAL_IO_FAST,
        CMD_READ_QUAD_OUTPUT_FAST,
@@ -95,15 +99,15 @@ static int spi_flash_set_qeb(struct spi_flash *flash, u8 idcode0)
        }
 }
 
-static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
-               u8 *idcode)
+static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
+                                    struct spi_flash *flash)
 {
        const struct spi_flash_params *params;
-       struct spi_flash *flash;
        u8 cmd;
        u16 jedec = idcode[1] << 8 | idcode[2];
        u16 ext_jedec = idcode[3] << 8 | idcode[4];
 
+       /* Validate params from spi_flash_params table */
        params = spi_flash_params_table;
        for (; params->name != NULL; params++) {
                if ((params->jedec >> 16) == idcode[0]) {
@@ -120,13 +124,7 @@ static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
                printf("SF: Unsupported flash IDs: ");
                printf("manuf %02x, jedec %04x, ext_jedec %04x\n",
                       idcode[0], jedec, ext_jedec);
-               return NULL;
-       }
-
-       flash = calloc(1, sizeof(*flash));
-       if (!flash) {
-               debug("SF: Failed to allocate spi_flash\n");
-               return NULL;
+               return -EPROTONOSUPPORT;
        }
 
        /* Assign spi data */
@@ -134,15 +132,24 @@ static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
        flash->name = params->name;
        flash->memory_map = spi->memory_map;
        flash->dual_flash = flash->spi->option;
+#ifdef CONFIG_DM_SPI_FLASH
+       flash->flags = params->flags;
+#endif
 
        /* Assign spi_flash ops */
+#ifndef CONFIG_DM_SPI_FLASH
        flash->write = spi_flash_cmd_write_ops;
-#ifdef CONFIG_SPI_FLASH_SST
-       if (params->flags & SST_WP)
-               flash->write = sst_write_wp;
+#if defined(CONFIG_SPI_FLASH_SST)
+       if (params->flags & SST_WR) {
+               if (flash->spi->op_mode_tx & SPI_OPM_TX_BP)
+                       flash->write = sst_write_bp;
+               else
+                       flash->write = sst_write_wp;
+       }
 #endif
        flash->erase = spi_flash_cmd_erase_ops;
        flash->read = spi_flash_cmd_read_ops;
+#endif
 
        /* Compute the flash size */
        flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0;
@@ -180,6 +187,9 @@ static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
                flash->erase_size = flash->sector_size;
        }
 
+       /* Now erase size becomes valid sector size */
+       flash->sector_size = flash->erase_size;
+
        /* Look for the fastest read cmd */
        cmd = fls(params->e_rd_cmd & flash->spi->op_mode_rx);
        if (cmd) {
@@ -227,15 +237,18 @@ static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
 #ifdef CONFIG_SPI_FLASH_BAR
        u8 curr_bank = 0;
        if (flash->size > SPI_FLASH_16MB_BOUN) {
+               int ret;
+
                flash->bank_read_cmd = (idcode[0] == 0x01) ?
                                        CMD_BANKADDR_BRRD : CMD_EXTNADDR_RDEAR;
                flash->bank_write_cmd = (idcode[0] == 0x01) ?
                                        CMD_BANKADDR_BRWR : CMD_EXTNADDR_WREAR;
 
-               if (spi_flash_read_common(flash, &flash->bank_read_cmd, 1,
-                                         &curr_bank, 1)) {
+               ret = spi_flash_read_common(flash, &flash->bank_read_cmd, 1,
+                                           &curr_bank, 1);
+               if (ret) {
                        debug("SF: fail to read bank addr register\n");
-                       return NULL;
+                       return ret;
                }
                flash->bank_curr = curr_bank;
        } else {
@@ -250,10 +263,10 @@ static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
                spi_flash_cmd_write_status(flash, 0);
 #endif
 
-       return flash;
+       return 0;
 }
 
-#ifdef CONFIG_OF_CONTROL
+#if CONFIG_IS_ENABLED(OF_CONTROL)
 int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
 {
        fdt_addr_t addr;
@@ -279,53 +292,31 @@ int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
 
        return 0;
 }
-#endif /* CONFIG_OF_CONTROL */
-
-#ifdef CONFIG_SYS_SPI_ST_ENABLE_WP_PIN
-/* enable the W#/Vpp signal to disable writing to the status register */
-static int spi_enable_wp_pin(struct spi_flash *flash)
-{
-       u8 status;
-       int ret;
-
-       ret = spi_flash_cmd_read_status(flash, &status);
-       if (ret < 0)
-               return ret;
+#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
 
-       ret = spi_flash_cmd_write_status(flash, STATUS_SRWD);
-       if (ret < 0)
-               return ret;
-
-       ret = spi_flash_cmd_write_disable(flash);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-#else
-static int spi_enable_wp_pin(struct spi_flash *flash)
-{
-       return 0;
-}
-#endif
-
-static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi)
+/**
+ * spi_flash_probe_slave() - Probe for a SPI flash device on a bus
+ *
+ * @spi: Bus to probe
+ * @flashp: Pointer to place to put flash info, which may be NULL if the
+ * space should be allocated
+ */
+int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash)
 {
-       struct spi_flash *flash = NULL;
        u8 idcode[5];
        int ret;
 
        /* Setup spi_slave */
        if (!spi) {
                printf("SF: Failed to set up slave\n");
-               return NULL;
+               return -ENODEV;
        }
 
        /* Claim spi bus */
        ret = spi_claim_bus(spi);
        if (ret) {
                debug("SF: Failed to claim SPI bus: %d\n", ret);
-               goto err_claim_bus;
+               return ret;
        }
 
        /* Read the ID codes */
@@ -340,10 +331,10 @@ static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi)
        print_buffer(0, idcode, 1, sizeof(idcode), 0);
 #endif
 
-       /* Validate params from spi_flash_params table */
-       flash = spi_flash_validate_params(spi, idcode);
-       if (!flash)
+       if (spi_flash_validate_params(spi, idcode, flash)) {
+               ret = -EINVAL;
                goto err_read_id;
+       }
 
        /* Set the quad enable bit - only for quad commands */
        if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) ||
@@ -351,13 +342,15 @@ static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi)
            (flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) {
                if (spi_flash_set_qeb(flash, idcode[0])) {
                        debug("SF: Fail to set QEB for %02x\n", idcode[0]);
-                       return NULL;
+                       ret = -EINVAL;
+                       goto err_read_id;
                }
        }
 
-#ifdef CONFIG_OF_CONTROL
+#if CONFIG_IS_ENABLED(OF_CONTROL)
        if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {
                debug("SF: FDT decode error\n");
+               ret = -EINVAL;
                goto err_read_id;
        }
 #endif
@@ -379,43 +372,133 @@ static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi)
                puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
        }
 #endif
-       if (spi_enable_wp_pin(flash))
-               puts("Enable WP pin failed\n");
+#ifdef CONFIG_SPI_FLASH_MTD
+       ret = spi_flash_mtd_register(flash);
+#endif
 
-       /* Release spi bus */
+err_read_id:
        spi_release_bus(spi);
+       return ret;
+}
 
-       return flash;
+#ifndef CONFIG_DM_SPI_FLASH
+struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus)
+{
+       struct spi_flash *flash;
 
-err_read_id:
-       spi_release_bus(spi);
-err_claim_bus:
-       spi_free_slave(spi);
-       return NULL;
+       /* Allocate space if needed (not used by sf-uclass */
+       flash = calloc(1, sizeof(*flash));
+       if (!flash) {
+               debug("SF: Failed to allocate spi_flash\n");
+               return NULL;
+       }
+
+       if (spi_flash_probe_slave(bus, flash)) {
+               spi_free_slave(bus);
+               free(flash);
+               return NULL;
+       }
+
+       return flash;
 }
 
-struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
+struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs,
                unsigned int max_hz, unsigned int spi_mode)
 {
-       struct spi_slave *spi;
+       struct spi_slave *bus;
 
-       spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
-       return spi_flash_probe_slave(spi);
+       bus = spi_setup_slave(busnum, cs, max_hz, spi_mode);
+       if (!bus)
+               return NULL;
+       return spi_flash_probe_tail(bus);
 }
 
 #ifdef CONFIG_OF_SPI_FLASH
 struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node,
                                      int spi_node)
 {
-       struct spi_slave *spi;
+       struct spi_slave *bus;
 
-       spi = spi_setup_slave_fdt(blob, slave_node, spi_node);
-       return spi_flash_probe_slave(spi);
+       bus = spi_setup_slave_fdt(blob, slave_node, spi_node);
+       if (!bus)
+               return NULL;
+       return spi_flash_probe_tail(bus);
 }
 #endif
 
 void spi_flash_free(struct spi_flash *flash)
 {
+#ifdef CONFIG_SPI_FLASH_MTD
+       spi_flash_mtd_unregister();
+#endif
        spi_free_slave(flash->spi);
        free(flash);
 }
+
+#else /* defined CONFIG_DM_SPI_FLASH */
+
+static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len,
+                             void *buf)
+{
+       struct spi_flash *flash = dev_get_uclass_priv(dev);
+
+       return spi_flash_cmd_read_ops(flash, offset, len, buf);
+}
+
+int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len,
+                       const void *buf)
+{
+       struct spi_flash *flash = dev_get_uclass_priv(dev);
+
+#if defined(CONFIG_SPI_FLASH_SST)
+       if (flash->flags & SST_WR) {
+               if (flash->spi->op_mode_tx & SPI_OPM_TX_BP)
+                       return sst_write_bp(flash, offset, len, buf);
+               else
+                       return sst_write_wp(flash, offset, len, buf);
+       }
+#endif
+
+       return spi_flash_cmd_write_ops(flash, offset, len, buf);
+}
+
+int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
+{
+       struct spi_flash *flash = dev_get_uclass_priv(dev);
+
+       return spi_flash_cmd_erase_ops(flash, offset, len);
+}
+
+int spi_flash_std_probe(struct udevice *dev)
+{
+       struct spi_slave *slave = dev_get_parentdata(dev);
+       struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
+       struct spi_flash *flash;
+
+       flash = dev_get_uclass_priv(dev);
+       flash->dev = dev;
+       debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs);
+       return spi_flash_probe_slave(slave, flash);
+}
+
+static const struct dm_spi_flash_ops spi_flash_std_ops = {
+       .read = spi_flash_std_read,
+       .write = spi_flash_std_write,
+       .erase = spi_flash_std_erase,
+};
+
+static const struct udevice_id spi_flash_std_ids[] = {
+       { .compatible = "spi-flash" },
+       { }
+};
+
+U_BOOT_DRIVER(spi_flash_std) = {
+       .name           = "spi_flash_std",
+       .id             = UCLASS_SPI_FLASH,
+       .of_match       = spi_flash_std_ids,
+       .probe          = spi_flash_std_probe,
+       .priv_auto_alloc_size = sizeof(struct spi_flash),
+       .ops            = &spi_flash_std_ops,
+};
+
+#endif /* CONFIG_DM_SPI_FLASH */