]> git.sur5r.net Git - u-boot/blobdiff - drivers/mtd/spi/sf_probe.c
sf: Add lock ops for SST SPI NOR flash
[u-boot] / drivers / mtd / spi / sf_probe.c
index 26364269be1a5e823efc99bd498262bd1a9d3393..52dace42eeaa1a6858879a4ce262170eb29de4ec 100644 (file)
@@ -13,6 +13,7 @@
 #include <errno.h>
 #include <fdtdec.h>
 #include <malloc.h>
+#include <mapmem.h>
 #include <spi.h>
 #include <spi_flash.h>
 #include <asm/io.h>
@@ -24,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,
@@ -97,6 +99,37 @@ static int spi_flash_set_qeb(struct spi_flash *flash, u8 idcode0)
        }
 }
 
+#ifdef CONFIG_SPI_FLASH_BAR
+static int spi_flash_read_bank(struct spi_flash *flash, u8 idcode0)
+{
+       u8 curr_bank = 0;
+       int ret;
+
+       if (flash->size <= SPI_FLASH_16MB_BOUN)
+               goto bank_end;
+
+       switch (idcode0) {
+       case SPI_FLASH_CFI_MFR_SPANSION:
+               flash->bank_read_cmd = CMD_BANKADDR_BRRD;
+               flash->bank_write_cmd = CMD_BANKADDR_BRWR;
+       default:
+               flash->bank_read_cmd = CMD_EXTNADDR_RDEAR;
+               flash->bank_write_cmd = CMD_EXTNADDR_WREAR;
+       }
+
+       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 ret;
+       }
+
+bank_end:
+       flash->bank_curr = curr_bank;
+       return 0;
+}
+#endif
+
 static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
                                     struct spi_flash *flash)
 {
@@ -135,13 +168,34 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
 #ifndef CONFIG_DM_SPI_FLASH
        flash->write = spi_flash_cmd_write_ops;
 #if defined(CONFIG_SPI_FLASH_SST)
-       if (params->flags & SST_WP)
-               flash->write = sst_write_wp;
+       if (params->flags & SST_WR)
+               flash->flags |= SNOR_F_SST_WR;
+
+       if (params->flags & SNOR_F_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
 
+       /* lock hooks are flash specific - assign them based on idcode0 */
+       switch (idcode[0]) {
+#if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST)
+       case SPI_FLASH_CFI_MFR_STMICRO:
+       case SPI_FLASH_CFI_MFR_SST:
+               flash->flash_lock = stm_lock;
+               flash->flash_unlock = stm_unlock;
+               flash->flash_is_locked = stm_is_locked;
+#endif
+               break;
+       default:
+               debug("SF: Lock ops not supported for %02x flash\n", idcode[0]);
+       }
+
        /* Compute the flash size */
        flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0;
        /*
@@ -178,6 +232,9 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
                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) {
@@ -214,34 +271,16 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
                flash->dummy_byte = 1;
        }
 
-       /* Poll cmd selection */
-       flash->poll_cmd = CMD_READ_STATUS;
 #ifdef CONFIG_SPI_FLASH_STMICRO
        if (params->flags & E_FSR)
-               flash->poll_cmd = CMD_FLAG_STATUS;
+               flash->flags |= SNOR_F_USE_FSR;
 #endif
 
        /* Configure the BAR - discover bank cmds and read current bank */
 #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;
-
-               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 ret;
-               }
-               flash->bank_curr = curr_bank;
-       } else {
-               flash->bank_curr = curr_bank;
-       }
+       int ret = spi_flash_read_bank(flash, idcode[0]);
+       if (ret < 0)
+               return ret;
 #endif
 
        /* Flash powers up read-only, so clear BP# bits */
@@ -254,7 +293,7 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
        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;
@@ -280,35 +319,7 @@ 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;
-
-       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
+#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
 
 /**
  * spi_flash_probe_slave() - Probe for a SPI flash device on a bus
@@ -363,7 +374,7 @@ int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash)
                }
        }
 
-#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;
@@ -388,13 +399,9 @@ int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash)
                puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
        }
 #endif
-       if (spi_enable_wp_pin(flash))
-               puts("Enable WP pin failed\n");
-
-       /* Release spi bus */
-       spi_release_bus(spi);
-
-       return 0;
+#ifdef CONFIG_SPI_FLASH_MTD
+       ret = spi_flash_mtd_register(flash);
+#endif
 
 err_read_id:
        spi_release_bus(spi);
@@ -428,6 +435,8 @@ struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs,
        struct spi_slave *bus;
 
        bus = spi_setup_slave(busnum, cs, max_hz, spi_mode);
+       if (!bus)
+               return NULL;
        return spi_flash_probe_tail(bus);
 }
 
@@ -438,12 +447,17 @@ struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node,
        struct spi_slave *bus;
 
        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);
 }
@@ -453,7 +467,7 @@ void spi_flash_free(struct spi_flash *flash)
 static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len,
                              void *buf)
 {
-       struct spi_flash *flash = dev->uclass_priv;
+       struct spi_flash *flash = dev_get_uclass_priv(dev);
 
        return spi_flash_cmd_read_ops(flash, offset, len, buf);
 }
@@ -461,26 +475,36 @@ static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len,
 int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len,
                        const void *buf)
 {
-       struct spi_flash *flash = dev->uclass_priv;
+       struct spi_flash *flash = dev_get_uclass_priv(dev);
+
+#if defined(CONFIG_SPI_FLASH_SST)
+       if (flash->flags & SNOR_F_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->uclass_priv;
+       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 spi_slave *slave = dev_get_parent_priv(dev);
+       struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
        struct spi_flash *flash;
 
-       flash = dev->uclass_priv;
+       flash = dev_get_uclass_priv(dev);
        flash->dev = dev;
-       debug("%s: slave=%p, cs=%d\n", __func__, slave, slave->cs);
+       debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs);
        return spi_flash_probe_slave(slave, flash);
 }