diff options
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/raw/lpc32xx_nand_mlc.c | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/lpc32xx_nand_slc.c | 78 | ||||
-rw-r--r-- | drivers/mtd/spi/sandbox.c | 10 | ||||
-rw-r--r-- | drivers/mtd/spi/sf-uclass.c | 9 | ||||
-rw-r--r-- | drivers/mtd/spi/sf_internal.h | 3 | ||||
-rw-r--r-- | drivers/mtd/spi/sf_probe.c | 8 | ||||
-rw-r--r-- | drivers/mtd/spi/spi_flash.c | 12 |
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 |