summaryrefslogtreecommitdiff
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/raw/lpc32xx_nand_mlc.c4
-rw-r--r--drivers/mtd/nand/raw/lpc32xx_nand_slc.c78
-rw-r--r--drivers/mtd/spi/sandbox.c10
-rw-r--r--drivers/mtd/spi/sf-uclass.c9
-rw-r--r--drivers/mtd/spi/sf_internal.h3
-rw-r--r--drivers/mtd/spi/sf_probe.c8
-rw-r--r--drivers/mtd/spi/spi_flash.c12
7 files changed, 78 insertions, 46 deletions
diff --git a/drivers/mtd/nand/raw/lpc32xx_nand_mlc.c b/drivers/mtd/nand/raw/lpc32xx_nand_mlc.c
index 5d4ffea608..79d1489dc7 100644
--- a/drivers/mtd/nand/raw/lpc32xx_nand_mlc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_nand_mlc.c
@@ -82,6 +82,10 @@ struct lpc32xx_nand_mlc_registers {
static struct lpc32xx_nand_mlc_registers __iomem *lpc32xx_nand_mlc_registers
= (struct lpc32xx_nand_mlc_registers __iomem *)MLC_NAND_BASE;
+#if !defined(CONFIG_SYS_MAX_NAND_CHIPS)
+#define CONFIG_SYS_MAX_NAND_CHIPS 1
+#endif
+
#define clkdiv(v, w, o) (((1+(clk/v)) & w) << o)
/**
diff --git a/drivers/mtd/nand/raw/lpc32xx_nand_slc.c b/drivers/mtd/nand/raw/lpc32xx_nand_slc.c
index 99f6e15f4e..8615b112a2 100644
--- a/drivers/mtd/nand/raw/lpc32xx_nand_slc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_nand_slc.c
@@ -2,13 +2,12 @@
/*
* LPC32xx SLC NAND flash controller driver
*
- * (C) Copyright 2015 Vladimir Zapolskiy <vz@mleia.com>
+ * (C) Copyright 2015-2018 Vladimir Zapolskiy <vz@mleia.com>
+ * Copyright (c) 2015 Tyco Fire Protection Products.
*
* Hardware ECC support original source code
* Copyright (C) 2008 by NXP Semiconductors
* Author: Kevin Wells
- *
- * Copyright (c) 2015 Tyco Fire Protection Products.
*/
#include <common.h>
@@ -22,10 +21,6 @@
#include <asm/arch/dma.h>
#include <asm/arch/cpu.h>
-#if defined(CONFIG_DMA_LPC32XX) && defined(CONFIG_SPL_BUILD)
-#warning "DMA support in SPL image is not tested"
-#endif
-
struct lpc32xx_nand_slc_regs {
u32 data;
u32 addr;
@@ -78,16 +73,14 @@ struct lpc32xx_nand_slc_regs {
* Note: For large page devices, the default layouts are used. */
static struct nand_ecclayout lpc32xx_nand_oob_16 = {
.eccbytes = 6,
- .eccpos = {10, 11, 12, 13, 14, 15},
+ .eccpos = { 10, 11, 12, 13, 14, 15, },
.oobfree = {
- {.offset = 0,
- . length = 4},
- {.offset = 6,
- . length = 4}
- }
+ { .offset = 0, .length = 4, },
+ { .offset = 6, .length = 4, },
+ }
};
-#if defined(CONFIG_DMA_LPC32XX)
+#if defined(CONFIG_DMA_LPC32XX) && !defined(CONFIG_SPL_BUILD)
#define ECCSTEPS (CONFIG_SYS_NAND_PAGE_SIZE / CONFIG_SYS_NAND_ECCSIZE)
/*
@@ -165,7 +158,7 @@ static int lpc32xx_nand_dev_ready(struct mtd_info *mtd)
return readl(&lpc32xx_nand_slc_regs->stat) & STAT_NAND_READY;
}
-#if defined(CONFIG_DMA_LPC32XX)
+#if defined(CONFIG_DMA_LPC32XX) && !defined(CONFIG_SPL_BUILD)
/*
* Prepares DMA descriptors for NAND RD/WR operations
* If the size is < 256 Bytes then it is assumed to be
@@ -324,7 +317,6 @@ static void lpc32xx_nand_xfer(struct mtd_info *mtd, const u8 *buf,
if (unlikely(ret < 0))
BUG();
-
/* Wait for NAND to be ready */
while (!lpc32xx_nand_dev_ready(mtd))
;
@@ -404,46 +396,18 @@ int lpc32xx_correct_data(struct mtd_info *mtd, u_char *dat,
return ret2;
}
-#endif
-#if defined(CONFIG_DMA_LPC32XX)
static void lpc32xx_dma_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
{
lpc32xx_nand_xfer(mtd, buf, len, 1);
}
-#else
-static void lpc32xx_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
-{
- while (len-- > 0)
- *buf++ = readl(&lpc32xx_nand_slc_regs->data);
-}
-#endif
-static uint8_t lpc32xx_read_byte(struct mtd_info *mtd)
-{
- return readl(&lpc32xx_nand_slc_regs->data);
-}
-
-#if defined(CONFIG_DMA_LPC32XX)
static void lpc32xx_dma_write_buf(struct mtd_info *mtd, const uint8_t *buf,
int len)
{
lpc32xx_nand_xfer(mtd, buf, len, 0);
}
-#else
-static void lpc32xx_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
-{
- while (len-- > 0)
- writel(*buf++, &lpc32xx_nand_slc_regs->data);
-}
-#endif
-
-static void lpc32xx_write_byte(struct mtd_info *mtd, uint8_t byte)
-{
- writel(byte, &lpc32xx_nand_slc_regs->data);
-}
-#if defined(CONFIG_DMA_LPC32XX)
/* Reuse the logic from "nand_read_page_hwecc()" */
static int lpc32xx_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
@@ -511,8 +475,30 @@ static int lpc32xx_write_page_hwecc(struct mtd_info *mtd,
return 0;
}
+#else
+static void lpc32xx_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+ while (len-- > 0)
+ *buf++ = readl(&lpc32xx_nand_slc_regs->data);
+}
+
+static void lpc32xx_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+ while (len-- > 0)
+ writel(*buf++, &lpc32xx_nand_slc_regs->data);
+}
#endif
+static uint8_t lpc32xx_read_byte(struct mtd_info *mtd)
+{
+ return readl(&lpc32xx_nand_slc_regs->data);
+}
+
+static void lpc32xx_write_byte(struct mtd_info *mtd, uint8_t byte)
+{
+ writel(byte, &lpc32xx_nand_slc_regs->data);
+}
+
/*
* LPC32xx has only one SLC NAND controller, don't utilize
* CONFIG_SYS_NAND_SELF_INIT to be able to reuse this function
@@ -520,7 +506,7 @@ static int lpc32xx_write_page_hwecc(struct mtd_info *mtd,
*/
int board_nand_init(struct nand_chip *lpc32xx_chip)
{
-#if defined(CONFIG_DMA_LPC32XX)
+#if defined(CONFIG_DMA_LPC32XX) && !defined(CONFIG_SPL_BUILD)
int ret;
/* Acquire a channel for our use */
@@ -543,7 +529,7 @@ int board_nand_init(struct nand_chip *lpc32xx_chip)
lpc32xx_chip->read_byte = lpc32xx_read_byte;
lpc32xx_chip->write_byte = lpc32xx_write_byte;
-#if defined(CONFIG_DMA_LPC32XX)
+#if defined(CONFIG_DMA_LPC32XX) && !defined(CONFIG_SPL_BUILD)
/* Hardware ECC calculation is supported when DMA driver is selected */
lpc32xx_chip->ecc.mode = NAND_ECC_HW;
diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c
index 7fef754c63..7b9891cb98 100644
--- a/drivers/mtd/spi/sandbox.c
+++ b/drivers/mtd/spi/sandbox.c
@@ -57,6 +57,8 @@ static const char *sandbox_sf_state_name(enum sandbox_sf_state state)
/* Bits for the status register */
#define STAT_WIP (1 << 0)
#define STAT_WEL (1 << 1)
+#define STAT_BP_SHIFT 2
+#define STAT_BP_MASK (7 << STAT_BP_SHIFT)
/* Assume all SPI flashes have 3 byte addresses since they do atm */
#define SF_ADDR_LEN 3
@@ -102,6 +104,14 @@ struct sandbox_spi_flash_plat_data {
int cs;
};
+void sandbox_sf_set_block_protect(struct udevice *dev, int bp_mask)
+{
+ struct sandbox_spi_flash *sbsf = dev_get_priv(dev);
+
+ sbsf->status &= ~STAT_BP_MASK;
+ sbsf->status |= bp_mask << STAT_BP_SHIFT;
+}
+
/**
* This is a very strange probe function. If it has platform data (which may
* have come from the device tree) then this function gets the filename and
diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c
index 662525f016..719a2fd23a 100644
--- a/drivers/mtd/spi/sf-uclass.c
+++ b/drivers/mtd/spi/sf-uclass.c
@@ -28,6 +28,15 @@ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len)
return log_ret(sf_get_ops(dev)->erase(dev, offset, len));
}
+int spl_flash_get_sw_write_prot(struct udevice *dev)
+{
+ struct dm_spi_flash_ops *ops = sf_get_ops(dev);
+
+ if (!ops->get_sw_write_prot)
+ return -ENOSYS;
+ return log_ret(ops->get_sw_write_prot(dev));
+}
+
/*
* TODO(sjg@chromium.org): This is an old-style function. We should remove
* it when all SPI flash drivers use dm
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index 26f5c7c995..46a5044417 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -170,6 +170,9 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
/* Flash erase(sectors) operation, support all possible erase commands */
int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len);
+/* Get software write-protect value (BP bits) */
+int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash);
+
/* Lock stmicro spi flash region */
int stm_lock(struct spi_flash *flash, u32 ofs, size_t len);
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 94fde2ae7a..5a2e932de8 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -124,6 +124,13 @@ static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
return spi_flash_cmd_erase_ops(flash, offset, len);
}
+static int spi_flash_std_get_sw_write_prot(struct udevice *dev)
+{
+ struct spi_flash *flash = dev_get_uclass_priv(dev);
+
+ return spi_flash_cmd_get_sw_write_prot(flash);
+}
+
static int spi_flash_std_probe(struct udevice *dev)
{
struct spi_slave *slave = dev_get_parent_priv(dev);
@@ -141,6 +148,7 @@ 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,
+ .get_sw_write_prot = spi_flash_std_get_sw_write_prot,
};
static const struct udevice_id spi_flash_std_ids[] = {
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index a87bacd4ac..0c2392f28a 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -110,6 +110,18 @@ static int write_cr(struct spi_flash *flash, u8 wc)
}
#endif
+int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash)
+{
+ u8 status;
+ int ret;
+
+ ret = read_sr(flash, &status);
+ if (ret)
+ return ret;
+
+ return (status >> 2) & 7;
+}
+
#ifdef CONFIG_SPI_FLASH_BAR
/*
* This "clean_bar" is necessary in a situation when one was accessing