Commit 35c222fd authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mtd/for-5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux

Pull MTD updates from Miquel Raynal:
 "MTD core
   - block2mtd: page index should use pgoff_t
   - maps: physmap: minimal Runtime PM support
   - maps: pcmciamtd: avoid possible sleep-in-atomic-context bugs
   - concat: Fix a comment referring to an unknown symbol

  Raw NAND:
   - Macronix: Use match_string() helper
   - Atmel: switch to using devm_fwnode_gpiod_get()
   - Denali: rework the SKIP_BYTES feature and add reset controlling
   - Brcmnand: set appropriate DMA mask
   - Cadence: add unspecified HAS_IOMEM dependency
   - Various cleanup.

  Onenand:
   - Rename Samsung and Omap2 drivers to avoid possible build warnings
   - Enable compile testing
   - Various build issues
   - Kconfig cleanup

  SPI-NAND:
   - Support for Toshiba TC58CVG2S0HRAIJ

  SPI-NOR:
   - Add support for TB selection using SR bit 6,
   - Add support for few flashes"

* tag 'mtd/for-5.6' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: (41 commits)
  mtd: concat: Fix a comment referring to an unknown symbol
  mtd: rawnand: add unspecified HAS_IOMEM dependency
  mtd: block2mtd: page index should use pgoff_t
  mtd: maps: physmap: Add minimal Runtime PM support
  mtd: maps: pcmciamtd: fix possible sleep-in-atomic-context bugs in pcmciamtd_set_vpp()
  mtd: onenand: Rename omap2 driver to avoid a build warning
  mtd: onenand: Use a better name for samsung driver
  mtd: rawnand: atmel: switch to using devm_fwnode_gpiod_get()
  mtd: spinand: add support for Toshiba TC58CVG2S0HRAIJ
  mtd: rawnand: macronix: Use match_string() helper to simplify the code
  mtd: sharpslpart: Fix unsigned comparison to zero
  mtd: onenand: Enable compile testing of OMAP and Samsung drivers
  mtd: onenand: samsung: Fix printing format for size_t on 64-bit
  mtd: onenand: samsung: Fix pointer cast -Wpointer-to-int-cast warnings on 64 bit
  mtd: rawnand: denali: remove hard-coded DENALI_DEFAULT_OOB_SKIP_BYTES
  mtd: rawnand: denali_dt: add reset controlling
  dt-bindings: mtd: denali_dt: document reset property
  mtd: rawnand: denali_dt: Add support for configuring SPARE_AREA_SKIP_BYTES
  mtd: rawnand: denali_dt: error out if platform has no associated data
  mtd: rawnand: brcmnand: Set appropriate DMA mask
  ...
parents e84bcd61 4575243c
...@@ -14,6 +14,11 @@ Required properties: ...@@ -14,6 +14,11 @@ Required properties:
interface clock, and the ECC circuit clock. interface clock, and the ECC circuit clock.
- clock-names: should contain "nand", "nand_x", "ecc" - clock-names: should contain "nand", "nand_x", "ecc"
Optional properties:
- resets: may contain phandles to the controller core reset, the register
reset
- reset-names: may contain "nand", "reg"
Sub-nodes: Sub-nodes:
Sub-nodes represent available NAND chips. Sub-nodes represent available NAND chips.
...@@ -46,6 +51,8 @@ nand: nand@ff900000 { ...@@ -46,6 +51,8 @@ nand: nand@ff900000 {
reg-names = "nand_data", "denali_reg"; reg-names = "nand_data", "denali_reg";
clocks = <&nand_clk>, <&nand_x_clk>, <&nand_ecc_clk>; clocks = <&nand_clk>, <&nand_x_clk>, <&nand_ecc_clk>;
clock-names = "nand", "nand_x", "ecc"; clock-names = "nand", "nand_x", "ecc";
resets = <&nand_rst>, <&nand_reg_rst>;
reset-names = "nand", "reg";
interrupts = <0 144 4>; interrupts = <0 144 4>;
nand@0 { nand@0 {
......
...@@ -44,7 +44,7 @@ struct block2mtd_dev { ...@@ -44,7 +44,7 @@ struct block2mtd_dev {
static LIST_HEAD(blkmtd_device_list); static LIST_HEAD(blkmtd_device_list);
static struct page *page_read(struct address_space *mapping, int index) static struct page *page_read(struct address_space *mapping, pgoff_t index)
{ {
return read_mapping_page(mapping, index, NULL); return read_mapping_page(mapping, index, NULL);
} }
...@@ -54,7 +54,7 @@ static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len) ...@@ -54,7 +54,7 @@ static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len)
{ {
struct address_space *mapping = dev->blkdev->bd_inode->i_mapping; struct address_space *mapping = dev->blkdev->bd_inode->i_mapping;
struct page *page; struct page *page;
int index = to >> PAGE_SHIFT; // page index pgoff_t index = to >> PAGE_SHIFT; // page index
int pages = len >> PAGE_SHIFT; int pages = len >> PAGE_SHIFT;
u_long *p; u_long *p;
u_long *max; u_long *max;
...@@ -103,7 +103,7 @@ static int block2mtd_read(struct mtd_info *mtd, loff_t from, size_t len, ...@@ -103,7 +103,7 @@ static int block2mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
{ {
struct block2mtd_dev *dev = mtd->priv; struct block2mtd_dev *dev = mtd->priv;
struct page *page; struct page *page;
int index = from >> PAGE_SHIFT; pgoff_t index = from >> PAGE_SHIFT;
int offset = from & (PAGE_SIZE-1); int offset = from & (PAGE_SIZE-1);
int cpylen; int cpylen;
...@@ -137,7 +137,7 @@ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf, ...@@ -137,7 +137,7 @@ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf,
{ {
struct page *page; struct page *page;
struct address_space *mapping = dev->blkdev->bd_inode->i_mapping; struct address_space *mapping = dev->blkdev->bd_inode->i_mapping;
int index = to >> PAGE_SHIFT; // page index pgoff_t index = to >> PAGE_SHIFT; // page index
int offset = to & ~PAGE_MASK; // page offset int offset = to & ~PAGE_MASK; // page offset
int cpylen; int cpylen;
......
...@@ -294,16 +294,15 @@ static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *f ...@@ -294,16 +294,15 @@ static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *f
} }
static DEFINE_SPINLOCK(pcmcia_vpp_lock); static DEFINE_MUTEX(pcmcia_vpp_lock);
static int pcmcia_vpp_refcnt; static int pcmcia_vpp_refcnt;
static void pcmciamtd_set_vpp(struct map_info *map, int on) static void pcmciamtd_set_vpp(struct map_info *map, int on)
{ {
struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
struct pcmcia_device *link = dev->p_dev; struct pcmcia_device *link = dev->p_dev;
unsigned long flags;
pr_debug("dev = %p on = %d vpp = %d\n\n", dev, on, dev->vpp); pr_debug("dev = %p on = %d vpp = %d\n\n", dev, on, dev->vpp);
spin_lock_irqsave(&pcmcia_vpp_lock, flags); mutex_lock(&pcmcia_vpp_lock);
if (on) { if (on) {
if (++pcmcia_vpp_refcnt == 1) /* first nested 'on' */ if (++pcmcia_vpp_refcnt == 1) /* first nested 'on' */
pcmcia_fixup_vpp(link, dev->vpp); pcmcia_fixup_vpp(link, dev->vpp);
...@@ -311,7 +310,7 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on) ...@@ -311,7 +310,7 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on)
if (--pcmcia_vpp_refcnt == 0) /* last nested 'off' */ if (--pcmcia_vpp_refcnt == 0) /* last nested 'off' */
pcmcia_fixup_vpp(link, 0); pcmcia_fixup_vpp(link, 0);
} }
spin_unlock_irqrestore(&pcmcia_vpp_lock, flags); mutex_unlock(&pcmcia_vpp_lock);
} }
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <linux/mtd/cfi_endian.h> #include <linux/mtd/cfi_endian.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include "physmap-gemini.h" #include "physmap-gemini.h"
...@@ -64,16 +65,16 @@ static int physmap_flash_remove(struct platform_device *dev) ...@@ -64,16 +65,16 @@ static int physmap_flash_remove(struct platform_device *dev)
{ {
struct physmap_flash_info *info; struct physmap_flash_info *info;
struct physmap_flash_data *physmap_data; struct physmap_flash_data *physmap_data;
int i, err; int i, err = 0;
info = platform_get_drvdata(dev); info = platform_get_drvdata(dev);
if (!info) if (!info)
return 0; goto out;
if (info->cmtd) { if (info->cmtd) {
err = mtd_device_unregister(info->cmtd); err = mtd_device_unregister(info->cmtd);
if (err) if (err)
return err; goto out;
if (info->cmtd != info->mtds[0]) if (info->cmtd != info->mtds[0])
mtd_concat_destroy(info->cmtd); mtd_concat_destroy(info->cmtd);
...@@ -88,7 +89,10 @@ static int physmap_flash_remove(struct platform_device *dev) ...@@ -88,7 +89,10 @@ static int physmap_flash_remove(struct platform_device *dev)
if (physmap_data && physmap_data->exit) if (physmap_data && physmap_data->exit)
physmap_data->exit(dev); physmap_data->exit(dev);
return 0; out:
pm_runtime_put(&dev->dev);
pm_runtime_disable(&dev->dev);
return err;
} }
static void physmap_set_vpp(struct map_info *map, int state) static void physmap_set_vpp(struct map_info *map, int state)
...@@ -484,13 +488,19 @@ static int physmap_flash_probe(struct platform_device *dev) ...@@ -484,13 +488,19 @@ static int physmap_flash_probe(struct platform_device *dev)
return -EINVAL; return -EINVAL;
} }
pm_runtime_enable(&dev->dev);
pm_runtime_get_sync(&dev->dev);
if (dev->dev.of_node) if (dev->dev.of_node)
err = physmap_flash_of_init(dev); err = physmap_flash_of_init(dev);
else else
err = physmap_flash_pdata_init(dev); err = physmap_flash_pdata_init(dev);
if (err) if (err) {
pm_runtime_put(&dev->dev);
pm_runtime_disable(&dev->dev);
return err; return err;
}
for (i = 0; i < info->nmaps; i++) { for (i = 0; i < info->nmaps; i++) {
struct resource *res; struct resource *res;
......
...@@ -841,10 +841,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c ...@@ -841,10 +841,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
return &concat->mtd; return &concat->mtd;
} }
/* /* Cleans the context obtained from mtd_concat_create() */
* This function destroys an MTD object obtained from concat_mtd_devs()
*/
void mtd_concat_destroy(struct mtd_info *mtd) void mtd_concat_destroy(struct mtd_info *mtd)
{ {
struct mtd_concat *concat = CONCAT(mtd); struct mtd_concat *concat = CONCAT(mtd);
......
...@@ -25,7 +25,7 @@ config MTD_ONENAND_GENERIC ...@@ -25,7 +25,7 @@ config MTD_ONENAND_GENERIC
config MTD_ONENAND_OMAP2 config MTD_ONENAND_OMAP2
tristate "OneNAND on OMAP2/OMAP3 support" tristate "OneNAND on OMAP2/OMAP3 support"
depends on ARCH_OMAP2 || ARCH_OMAP3 depends on ARCH_OMAP2 || ARCH_OMAP3 || (COMPILE_TEST && ARM)
depends on OF || COMPILE_TEST depends on OF || COMPILE_TEST
help help
Support for a OneNAND flash device connected to an OMAP2/OMAP3 SoC Support for a OneNAND flash device connected to an OMAP2/OMAP3 SoC
...@@ -34,7 +34,7 @@ config MTD_ONENAND_OMAP2 ...@@ -34,7 +34,7 @@ config MTD_ONENAND_OMAP2
config MTD_ONENAND_SAMSUNG config MTD_ONENAND_SAMSUNG
tristate "OneNAND on Samsung SOC controller support" tristate "OneNAND on Samsung SOC controller support"
depends on ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS4 depends on ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS4 || COMPILE_TEST
help help
Support for a OneNAND flash device connected to an Samsung SOC. Support for a OneNAND flash device connected to an Samsung SOC.
S3C64XX uses command mapping method. S3C64XX uses command mapping method.
......
...@@ -8,7 +8,7 @@ obj-$(CONFIG_MTD_ONENAND) += onenand.o ...@@ -8,7 +8,7 @@ obj-$(CONFIG_MTD_ONENAND) += onenand.o
# Board specific. # Board specific.
obj-$(CONFIG_MTD_ONENAND_GENERIC) += generic.o obj-$(CONFIG_MTD_ONENAND_GENERIC) += generic.o
obj-$(CONFIG_MTD_ONENAND_OMAP2) += omap2.o obj-$(CONFIG_MTD_ONENAND_OMAP2) += onenand_omap2.o
obj-$(CONFIG_MTD_ONENAND_SAMSUNG) += samsung_mtd.o obj-$(CONFIG_MTD_ONENAND_SAMSUNG) += onenand_samsung.o
onenand-objs = onenand_base.o onenand_bbt.o onenand-objs = onenand_base.o onenand_bbt.o
...@@ -248,7 +248,7 @@ static unsigned short s3c_onenand_readw(void __iomem *addr) ...@@ -248,7 +248,7 @@ static unsigned short s3c_onenand_readw(void __iomem *addr)
} }
/* BootRAM access control */ /* BootRAM access control */
if ((unsigned int) addr < ONENAND_DATARAM && onenand->bootram_command) { if ((unsigned long)addr < ONENAND_DATARAM && onenand->bootram_command) {
if (word_addr == 0) if (word_addr == 0)
return s3c_read_reg(MANUFACT_ID_OFFSET); return s3c_read_reg(MANUFACT_ID_OFFSET);
if (word_addr == 1) if (word_addr == 1)
...@@ -289,7 +289,7 @@ static void s3c_onenand_writew(unsigned short value, void __iomem *addr) ...@@ -289,7 +289,7 @@ static void s3c_onenand_writew(unsigned short value, void __iomem *addr)
} }
/* BootRAM access control */ /* BootRAM access control */
if ((unsigned int)addr < ONENAND_DATARAM) { if ((unsigned long)addr < ONENAND_DATARAM) {
if (value == ONENAND_CMD_READID) { if (value == ONENAND_CMD_READID) {
onenand->bootram_command = 1; onenand->bootram_command = 1;
return; return;
...@@ -658,7 +658,7 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, ...@@ -658,7 +658,7 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area,
dma_dst = dma_map_single(dev, buf, count, DMA_FROM_DEVICE); dma_dst = dma_map_single(dev, buf, count, DMA_FROM_DEVICE);
} }
if (dma_mapping_error(dev, dma_dst)) { if (dma_mapping_error(dev, dma_dst)) {
dev_err(dev, "Couldn't map a %d byte buffer for DMA\n", count); dev_err(dev, "Couldn't map a %zu byte buffer for DMA\n", count);
goto normal; goto normal;
} }
err = s5pc110_dma_ops(dma_dst, dma_src, err = s5pc110_dma_ops(dma_dst, dma_src,
...@@ -728,13 +728,12 @@ static void s3c_onenand_check_lock_status(struct mtd_info *mtd) ...@@ -728,13 +728,12 @@ static void s3c_onenand_check_lock_status(struct mtd_info *mtd)
struct onenand_chip *this = mtd->priv; struct onenand_chip *this = mtd->priv;
struct device *dev = &onenand->pdev->dev; struct device *dev = &onenand->pdev->dev;
unsigned int block, end; unsigned int block, end;
int tmp;
end = this->chipsize >> this->erase_shift; end = this->chipsize >> this->erase_shift;
for (block = 0; block < end; block++) { for (block = 0; block < end; block++) {
unsigned int mem_addr = onenand->mem_addr(block, 0, 0); unsigned int mem_addr = onenand->mem_addr(block, 0, 0);
tmp = s3c_read_cmd(CMD_MAP_01(onenand, mem_addr)); s3c_read_cmd(CMD_MAP_01(onenand, mem_addr));
if (s3c_read_reg(INT_ERR_STAT_OFFSET) & LOCKED_BLK) { if (s3c_read_reg(INT_ERR_STAT_OFFSET) & LOCKED_BLK) {
dev_err(dev, "block %d is write-protected!\n", block); dev_err(dev, "block %d is write-protected!\n", block);
......
...@@ -452,7 +452,7 @@ config MTD_NAND_PLATFORM ...@@ -452,7 +452,7 @@ config MTD_NAND_PLATFORM
config MTD_NAND_CADENCE config MTD_NAND_CADENCE
tristate "Support Cadence NAND (HPNFC) controller" tristate "Support Cadence NAND (HPNFC) controller"
depends on OF || COMPILE_TEST depends on (OF || COMPILE_TEST) && HAS_IOMEM
help help
Enable the driver for NAND flash on platforms using a Cadence NAND Enable the driver for NAND flash on platforms using a Cadence NAND
controller. controller.
......
...@@ -1578,9 +1578,8 @@ static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc, ...@@ -1578,9 +1578,8 @@ static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc,
nand->numcs = numcs; nand->numcs = numcs;
gpio = devm_fwnode_get_index_gpiod_from_child(nc->dev, "det", 0, gpio = devm_fwnode_gpiod_get(nc->dev, of_fwnode_handle(np),
&np->fwnode, GPIOD_IN, "det", GPIOD_IN, "nand-det");
"nand-det");
if (IS_ERR(gpio) && PTR_ERR(gpio) != -ENOENT) { if (IS_ERR(gpio) && PTR_ERR(gpio) != -ENOENT) {
dev_err(nc->dev, dev_err(nc->dev,
"Failed to get detect gpio (err = %ld)\n", "Failed to get detect gpio (err = %ld)\n",
...@@ -1624,9 +1623,10 @@ static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc, ...@@ -1624,9 +1623,10 @@ static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc,
nand->cs[i].rb.type = ATMEL_NAND_NATIVE_RB; nand->cs[i].rb.type = ATMEL_NAND_NATIVE_RB;
nand->cs[i].rb.id = val; nand->cs[i].rb.id = val;
} else { } else {
gpio = devm_fwnode_get_index_gpiod_from_child(nc->dev, gpio = devm_fwnode_gpiod_get_index(nc->dev,
"rb", i, &np->fwnode, of_fwnode_handle(np),
GPIOD_IN, "nand-rb"); "rb", i, GPIOD_IN,
"nand-rb");
if (IS_ERR(gpio) && PTR_ERR(gpio) != -ENOENT) { if (IS_ERR(gpio) && PTR_ERR(gpio) != -ENOENT) {
dev_err(nc->dev, dev_err(nc->dev,
"Failed to get R/B gpio (err = %ld)\n", "Failed to get R/B gpio (err = %ld)\n",
...@@ -1640,9 +1640,9 @@ static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc, ...@@ -1640,9 +1640,9 @@ static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc,
} }
} }
gpio = devm_fwnode_get_index_gpiod_from_child(nc->dev, "cs", gpio = devm_fwnode_gpiod_get_index(nc->dev,
i, &np->fwnode, of_fwnode_handle(np),
GPIOD_OUT_HIGH, "cs", i, GPIOD_OUT_HIGH,
"nand-cs"); "nand-cs");
if (IS_ERR(gpio) && PTR_ERR(gpio) != -ENOENT) { if (IS_ERR(gpio) && PTR_ERR(gpio) != -ENOENT) {
dev_err(nc->dev, dev_err(nc->dev,
......
...@@ -2635,6 +2635,16 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) ...@@ -2635,6 +2635,16 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
/* initialize the dma version */ /* initialize the dma version */
brcmnand_flash_dma_revision_init(ctrl); brcmnand_flash_dma_revision_init(ctrl);
ret = -EIO;
if (ctrl->nand_version >= 0x0700)
ret = dma_set_mask_and_coherent(&pdev->dev,
DMA_BIT_MASK(40));
if (ret)
ret = dma_set_mask_and_coherent(&pdev->dev,
DMA_BIT_MASK(32));
if (ret)
goto err;
/* linked-list and stop on error */ /* linked-list and stop on error */
flash_dma_writel(ctrl, FLASH_DMA_MODE, FLASH_DMA_MODE_MASK); flash_dma_writel(ctrl, FLASH_DMA_MODE, FLASH_DMA_MODE_MASK);
flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0); flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0);
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include "denali.h" #include "denali.h"
#define DENALI_NAND_NAME "denali-nand" #define DENALI_NAND_NAME "denali-nand"
#define DENALI_DEFAULT_OOB_SKIP_BYTES 8
/* for Indexed Addressing */ /* for Indexed Addressing */
#define DENALI_INDEXED_CTRL 0x00 #define DENALI_INDEXED_CTRL 0x00
...@@ -1302,15 +1301,16 @@ int denali_init(struct denali_controller *denali) ...@@ -1302,15 +1301,16 @@ int denali_init(struct denali_controller *denali)
/* /*
* Set how many bytes should be skipped before writing data in OOB. * Set how many bytes should be skipped before writing data in OOB.
* If a non-zero value has already been set (by firmware or something), * If a platform requests a non-zero value, set it to the register.
* just use it. Otherwise, set the driver's default. * Otherwise, read the value out, expecting it has already been set up
* by firmware.
*/ */
denali->oob_skip_bytes = ioread32(denali->reg + SPARE_AREA_SKIP_BYTES); if (denali->oob_skip_bytes)
if (!denali->oob_skip_bytes) {
denali->oob_skip_bytes = DENALI_DEFAULT_OOB_SKIP_BYTES;
iowrite32(denali->oob_skip_bytes, iowrite32(denali->oob_skip_bytes,
denali->reg + SPARE_AREA_SKIP_BYTES); denali->reg + SPARE_AREA_SKIP_BYTES);
} else
denali->oob_skip_bytes = ioread32(denali->reg +
SPARE_AREA_SKIP_BYTES);
iowrite32(0, denali->reg + TRANSFER_SPARE_REG); iowrite32(0, denali->reg + TRANSFER_SPARE_REG);
iowrite32(GENMASK(denali->nbanks - 1, 0), denali->reg + RB_PIN_ENABLED); iowrite32(GENMASK(denali->nbanks - 1, 0), denali->reg + RB_PIN_ENABLED);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
*/ */
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/ioport.h> #include <linux/ioport.h>
...@@ -14,6 +15,7 @@ ...@@ -14,6 +15,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/reset.h>
#include "denali.h" #include "denali.h"
...@@ -22,11 +24,14 @@ struct denali_dt { ...@@ -22,11 +24,14 @@ struct denali_dt {
struct clk *clk; /* core clock */ struct clk *clk; /* core clock */
struct clk *clk_x; /* bus interface clock */ struct clk *clk_x; /* bus interface clock */
struct clk *clk_ecc; /* ECC circuit clock */ struct clk *clk_ecc; /* ECC circuit clock */
struct reset_control *rst; /* core reset */
struct reset_control *rst_reg; /* register reset */
}; };
struct denali_dt_data { struct denali_dt_data {
unsigned int revision; unsigned int revision;
unsigned int caps; unsigned int caps;
unsigned int oob_skip_bytes;
const struct nand_ecc_caps *ecc_caps; const struct nand_ecc_caps *ecc_caps;
}; };
...@@ -34,6 +39,7 @@ NAND_ECC_CAPS_SINGLE(denali_socfpga_ecc_caps, denali_calc_ecc_bytes, ...@@ -34,6 +39,7 @@ NAND_ECC_CAPS_SINGLE(denali_socfpga_ecc_caps, denali_calc_ecc_bytes,
512, 8, 15); 512, 8, 15);
static const struct denali_dt_data denali_socfpga_data = { static const struct denali_dt_data denali_socfpga_data = {
.caps = DENALI_CAP_HW_ECC_FIXUP, .caps = DENALI_CAP_HW_ECC_FIXUP,
.oob_skip_bytes = 2,
.ecc_caps = &denali_socfpga_ecc_caps, .ecc_caps = &denali_socfpga_ecc_caps,
}; };
...@@ -42,6 +48,7 @@ NAND_ECC_CAPS_SINGLE(denali_uniphier_v5a_ecc_caps, denali_calc_ecc_bytes, ...@@ -42,6 +48,7 @@ NAND_ECC_CAPS_SINGLE(denali_uniphier_v5a_ecc_caps, denali_calc_ecc_bytes,
static const struct denali_dt_data denali_uniphier_v5a_data = { static const struct denali_dt_data denali_uniphier_v5a_data = {
.caps = DENALI_CAP_HW_ECC_FIXUP | .caps = DENALI_CAP_HW_ECC_FIXUP |
DENALI_CAP_DMA_64BIT, DENALI_CAP_DMA_64BIT,
.oob_skip_bytes = 8,
.ecc_caps = &denali_uniphier_v5a_ecc_caps, .ecc_caps = &denali_uniphier_v5a_ecc_caps,
}; };
...@@ -51,6 +58,7 @@ static const struct denali_dt_data denali_uniphier_v5b_data = { ...@@ -51,6 +58,7 @@ static const struct denali_dt_data denali_uniphier_v5b_data = {
.revision = 0x0501, .revision = 0x0501,
.caps = DENALI_CAP_HW_ECC_FIXUP | .caps = DENALI_CAP_HW_ECC_FIXUP |
DENALI_CAP_DMA_64BIT, DENALI_CAP_DMA_64BIT,
.oob_skip_bytes = 8,
.ecc_caps = &denali_uniphier_v5b_ecc_caps, .ecc_caps = &denali_uniphier_v5b_ecc_caps,
}; };
...@@ -118,11 +126,13 @@ static int denali_dt_probe(struct platform_device *pdev) ...@@ -118,11 +126,13 @@ static int denali_dt_probe(struct platform_device *pdev)
denali = &dt->controller; denali = &dt->controller;
data = of_device_get_match_data(dev); data = of_device_get_match_data(dev);
if (data) { if (WARN_ON(!data))
return -EINVAL;
denali->revision = data->revision; denali->revision = data->revision;
denali->caps = data->caps; denali->caps = data->caps;
denali->oob_skip_bytes = data->oob_skip_bytes;
denali->ecc_caps = data->ecc_caps; denali->ecc_caps = data->ecc_caps;
}
denali->dev = dev; denali->dev = dev;
denali->irq = platform_get_irq(pdev, 0); denali->irq = platform_get_irq(pdev, 0);
...@@ -151,6 +161,14 @@ static int denali_dt_probe(struct platform_device *pdev) ...@@ -151,6 +161,14 @@ static int denali_dt_probe(struct platform_device *pdev)
if (IS_ERR(dt->clk_ecc)) if (IS_ERR(dt->clk_ecc))
return PTR_ERR(dt->clk_ecc); return PTR_ERR(dt->clk_ecc);
dt->rst = devm_reset_control_get_optional_shared(dev, "nand");
if (IS_ERR(dt->rst))
return PTR_ERR(dt->rst);
dt->rst_reg = devm_reset_control_get_optional_shared(dev, "reg");
if (IS_ERR(dt->rst_reg))
return PTR_ERR(dt->rst_reg);
ret = clk_prepare_enable(dt->clk); ret = clk_prepare_enable(dt->clk);
if (ret) if (ret)
return ret; return ret;
...@@ -166,10 +184,30 @@ static int denali_dt_probe(struct platform_device *pdev) ...@@ -166,10 +184,30 @@ static int denali_dt_probe(struct platform_device *pdev)
denali->clk_rate = clk_get_rate(dt->clk); denali->clk_rate = clk_get_rate(dt->clk);
denali->clk_x_rate = clk_get_rate(dt->clk_x); denali->clk_x_rate = clk_get_rate(dt->clk_x);
ret = denali_init(denali); /*
* Deassert the register reset, and the core reset in this order.
* Deasserting the core reset while the register reset is asserted
* will cause unpredictable behavior in the controller.
*/
ret = reset_control_deassert(dt->rst_reg);
if (ret) if (ret)
goto out_disable_clk_ecc; goto out_disable_clk_ecc;
ret = reset_control_deassert(dt->rst);
if (ret)
goto out_assert_rst_reg;
/*
* When the reset is deasserted, the initialization sequence is kicked
* (bootstrap process). The driver must wait until it finished.
* Otherwise, it will result in unpredictable behavior.
*/
usleep_range(200, 1000);
ret = denali_init(denali);
if (ret)
goto out_assert_rst;
for_each_child_of_node(dev->of_node, np) { for_each_child_of_node(dev->of_node, np) {
ret = denali_dt_chip_init(denali, np); ret = denali_dt_chip_init(denali, np);
if (ret) { if (ret) {
...@@ -184,6 +222,10 @@ static int denali_dt_probe(struct platform_device *pdev) ...@@ -184,6 +222,10 @@ static int denali_dt_probe(struct platform_device *pdev)
out_remove_denali: out_remove_denali:
denali_remove(denali); denali_remove(denali);
out_assert_rst:
reset_control_assert(dt->rst);
out_assert_rst_reg:
reset_control_assert(dt->rst_reg);
out_disable_clk_ecc: out_disable_clk_ecc:
clk_disable_unprepare(dt->clk_ecc); clk_disable_unprepare(dt->clk_ecc);
out_disable_clk_x: out_disable_clk_x:
...@@ -199,6 +241,8 @@ static int denali_dt_remove(struct platform_device *pdev) ...@@ -199,6 +241,8 @@ static int denali_dt_remove(struct platform_device *pdev)
struct denali_dt *dt = platform_get_drvdata(pdev); struct denali_dt *dt = platform_get_drvdata(pdev);
denali_remove(&dt->controller); denali_remove(&dt->controller);
reset_control_assert(dt->rst);
reset_control_assert(dt->rst_reg);
clk_disable_unprepare(dt->clk_ecc); clk_disable_unprepare(dt->clk_ecc);
clk_disable_unprepare(dt->clk_x); clk_disable_unprepare(dt->clk_x);
clk_disable_unprepare(dt->clk); clk_disable_unprepare(dt->clk);
......
...@@ -438,7 +438,7 @@ static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset, ...@@ -438,7 +438,7 @@ static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset,
buffer += blksize; buffer += blksize;
offset += blksize; offset += blksize;
size -= blksize; size -= blksize;
}; }
} }
/* Copy data from/to NFC main and spare buffers */ /* Copy data from/to NFC main and spare buffers */
......
...@@ -59,7 +59,7 @@ static void macronix_nand_onfi_init(struct nand_chip *chip) ...@@ -59,7 +59,7 @@ static void macronix_nand_onfi_init(struct nand_chip *chip)
*/ */
static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip) static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip)
{ {
unsigned int i; int i;
static const char * const broken_get_timings[] = { static const char * const broken_get_timings[] = {
"MX30LF1G18AC", "MX30LF1G18AC",
"MX30LF1G28AC", "MX30LF1G28AC",
...@@ -80,12 +80,9 @@ static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip) ...@@ -80,12 +80,9 @@ static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip)
if (!chip->parameters.supports_set_get_features) if (!chip->parameters.supports_set_get_features)
return; return;
for (i = 0; i < ARRAY_SIZE(broken_get_timings); i++) { i = match_string(broken_get_timings, ARRAY_SIZE(broken_get_timings),
if (!strcmp(broken_get_timings[i], chip->parameters.model)) chip->parameters.model);
break; if (i < 0)
}
if (i == ARRAY_SIZE(broken_get_timings))
return; return;
bitmap_clear(chip->parameters.get_feature_list, bitmap_clear(chip->parameters.get_feature_list,
......
...@@ -124,6 +124,16 @@ static const struct spinand_info toshiba_spinand_table[] = { ...@@ -124,6 +124,16 @@ static const struct spinand_info toshiba_spinand_table[] = {
0, 0,
SPINAND_ECCINFO(&tc58cxgxsx_ooblayout, SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
tc58cxgxsx_ecc_get_status)), tc58cxgxsx_ecc_get_status)),
/* 3.3V 4Gb */
SPINAND_INFO("TC58CVG2S0", 0xED,
NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
NAND_ECCREQ(8, 512),
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
&write_cache_variants,
&update_cache_variants),
0,
SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
tc58cxgxsx_ecc_get_status)),
/* 1.8V 1Gb */ /* 1.8V 1Gb */
SPINAND_INFO("TC58CYG0S3", 0xB2, SPINAND_INFO("TC58CYG0S3", 0xB2,
NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
......
...@@ -165,10 +165,10 @@ static int sharpsl_nand_get_logical_num(u8 *oob) ...@@ -165,10 +165,10 @@ static int sharpsl_nand_get_logical_num(u8 *oob)
static int sharpsl_nand_init_ftl(struct mtd_info *mtd, struct sharpsl_ftl *ftl) static int sharpsl_nand_init_ftl(struct mtd_info *mtd, struct sharpsl_ftl *ftl)
{ {
unsigned int block_num, log_num, phymax; unsigned int block_num, phymax;
int i, ret, log_num;
loff_t block_adr; loff_t block_adr;
u8 *oob; u8 *oob;
int i, ret;
oob = kzalloc(mtd->oobsize, GFP_KERNEL); oob = kzalloc(mtd->oobsize, GFP_KERNEL);
if (!oob) if (!oob)
......
...@@ -46,11 +46,11 @@ config SPI_CADENCE_QUADSPI ...@@ -46,11 +46,11 @@ config SPI_CADENCE_QUADSPI
Flash as an MTD device. Flash as an MTD device.
config SPI_HISI_SFC config SPI_HISI_SFC
tristate "Hisilicon SPI-NOR Flash Controller(SFC)" tristate "Hisilicon FMC SPI-NOR Flash Controller(SFC)"
depends on ARCH_HISI || COMPILE_TEST depends on ARCH_HISI || COMPILE_TEST
depends on HAS_IOMEM depends on HAS_IOMEM
help help
This enables support for hisilicon SPI-NOR flash controller. This enables support for HiSilicon FMC SPI-NOR flash controller.
config SPI_MTK_QUADSPI config SPI_MTK_QUADSPI
tristate "MediaTek Quad SPI controller" tristate "MediaTek Quad SPI controller"
......
...@@ -305,7 +305,7 @@ static void aspeed_smc_stop_user(struct spi_nor *nor) ...@@ -305,7 +305,7 @@ static void aspeed_smc_stop_user(struct spi_nor *nor)
writel(ctl, chip->ctl); /* default to fread or read mode */ writel(ctl, chip->ctl); /* default to fread or read mode */
} }
static int aspeed_smc_prep(struct spi_nor *nor, enum spi_nor_ops ops) static int aspeed_smc_prep(struct spi_nor *nor)
{ {
struct aspeed_smc_chip *chip = nor->priv; struct aspeed_smc_chip *chip = nor->priv;
...@@ -313,7 +313,7 @@ static int aspeed_smc_prep(struct spi_nor *nor, enum spi_nor_ops ops) ...@@ -313,7 +313,7 @@ static int aspeed_smc_prep(struct spi_nor *nor, enum spi_nor_ops ops)
return 0; return 0;
} }
static void aspeed_smc_unprep(struct spi_nor *nor, enum spi_nor_ops ops) static void aspeed_smc_unprep(struct spi_nor *nor)
{ {
struct aspeed_smc_chip *chip = nor->priv; struct aspeed_smc_chip *chip = nor->priv;
......
...@@ -1062,7 +1062,7 @@ static int cqspi_erase(struct spi_nor *nor, loff_t offs) ...@@ -1062,7 +1062,7 @@ static int cqspi_erase(struct spi_nor *nor, loff_t offs)
return 0; return 0;
} }
static int cqspi_prep(struct spi_nor *nor, enum spi_nor_ops ops) static int cqspi_prep(struct spi_nor *nor)
{ {
struct cqspi_flash_pdata *f_pdata = nor->priv; struct cqspi_flash_pdata *f_pdata = nor->priv;
struct cqspi_st *cqspi = f_pdata->cqspi; struct cqspi_st *cqspi = f_pdata->cqspi;
...@@ -1072,7 +1072,7 @@ static int cqspi_prep(struct spi_nor *nor, enum spi_nor_ops ops) ...@@ -1072,7 +1072,7 @@ static int cqspi_prep(struct spi_nor *nor, enum spi_nor_ops ops)
return 0; return 0;
} }
static void cqspi_unprep(struct spi_nor *nor, enum spi_nor_ops ops) static void cqspi_unprep(struct spi_nor *nor)
{ {
struct cqspi_flash_pdata *f_pdata = nor->priv; struct cqspi_flash_pdata *f_pdata = nor->priv;
struct cqspi_st *cqspi = f_pdata->cqspi; struct cqspi_st *cqspi = f_pdata->cqspi;
......
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
/* /*
* HiSilicon SPI Nor Flash Controller Driver * HiSilicon FMC SPI-NOR flash controller driver
* *
* Copyright (c) 2015-2016 HiSilicon Technologies Co., Ltd. * Copyright (c) 2015-2016 HiSilicon Technologies Co., Ltd.
*/ */
...@@ -144,7 +144,7 @@ static void hisi_spi_nor_init(struct hifmc_host *host) ...@@ -144,7 +144,7 @@ static void hisi_spi_nor_init(struct hifmc_host *host)
writel(reg, host->regbase + FMC_SPI_TIMING_CFG); writel(reg, host->regbase + FMC_SPI_TIMING_CFG);
} }
static int hisi_spi_nor_prep(struct spi_nor *nor, enum spi_nor_ops ops) static int hisi_spi_nor_prep(struct spi_nor *nor)
{ {
struct hifmc_priv *priv = nor->priv; struct hifmc_priv *priv = nor->priv;
struct hifmc_host *host = priv->host; struct hifmc_host *host = priv->host;
...@@ -167,7 +167,7 @@ static int hisi_spi_nor_prep(struct spi_nor *nor, enum spi_nor_ops ops) ...@@ -167,7 +167,7 @@ static int hisi_spi_nor_prep(struct spi_nor *nor, enum spi_nor_ops ops)
return ret; return ret;
} }
static void hisi_spi_nor_unprep(struct spi_nor *nor, enum spi_nor_ops ops) static void hisi_spi_nor_unprep(struct spi_nor *nor)
{ {
struct hifmc_priv *priv = nor->priv; struct hifmc_priv *priv = nor->priv;
struct hifmc_host *host = priv->host; struct hifmc_host *host = priv->host;
......
...@@ -70,10 +70,12 @@ static const struct pci_device_id intel_spi_pci_ids[] = { ...@@ -70,10 +70,12 @@ static const struct pci_device_id intel_spi_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x4b24), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0x4b24), (unsigned long)&bxt_info },
{ PCI_VDEVICE(INTEL, 0x4da4), (unsigned long)&bxt_info },
{ PCI_VDEVICE(INTEL, 0xa0a4), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0xa0a4), (unsigned long)&bxt_info },
{ PCI_VDEVICE(INTEL, 0xa1a4), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0xa1a4), (unsigned long)&bxt_info },
{ PCI_VDEVICE(INTEL, 0xa224), (unsigned long)&bxt_info }, { PCI_VDEVICE(INTEL, 0xa224), (unsigned long)&bxt_info },
{ PCI_VDEVICE(INTEL, 0xa324), (unsigned long)&cnl_info }, { PCI_VDEVICE(INTEL, 0xa324), (unsigned long)&cnl_info },
{ PCI_VDEVICE(INTEL, 0xa3a4), (unsigned long)&bxt_info },
{ }, { },
}; };
MODULE_DEVICE_TABLE(pci, intel_spi_pci_ids); MODULE_DEVICE_TABLE(pci, intel_spi_pci_ids);
......
This diff is collapsed.
...@@ -128,7 +128,8 @@ ...@@ -128,7 +128,8 @@
#define SR_BP0 BIT(2) /* Block protect 0 */ #define SR_BP0 BIT(2) /* Block protect 0 */
#define SR_BP1 BIT(3) /* Block protect 1 */ #define SR_BP1 BIT(3) /* Block protect 1 */
#define SR_BP2 BIT(4) /* Block protect 2 */ #define SR_BP2 BIT(4) /* Block protect 2 */
#define SR_TB BIT(5) /* Top/Bottom protect */ #define SR_TB_BIT5 BIT(5) /* Top/Bottom protect */
#define SR_TB_BIT6 BIT(6) /* Top/Bottom protect */
#define SR_SRWD BIT(7) /* SR write protect */ #define SR_SRWD BIT(7) /* SR write protect */
/* Spansion/Cypress specific status bits */ /* Spansion/Cypress specific status bits */
#define SR_E_ERR BIT(5) #define SR_E_ERR BIT(5)
...@@ -224,14 +225,6 @@ static inline u8 spi_nor_get_protocol_width(enum spi_nor_protocol proto) ...@@ -224,14 +225,6 @@ static inline u8 spi_nor_get_protocol_width(enum spi_nor_protocol proto)
return spi_nor_get_protocol_data_nbits(proto); return spi_nor_get_protocol_data_nbits(proto);
} }
enum spi_nor_ops {
SPI_NOR_OPS_READ = 0,
SPI_NOR_OPS_WRITE,
SPI_NOR_OPS_ERASE,
SPI_NOR_OPS_LOCK,
SPI_NOR_OPS_UNLOCK,
};
enum spi_nor_option_flags { enum spi_nor_option_flags {
SNOR_F_USE_FSR = BIT(0), SNOR_F_USE_FSR = BIT(0),
SNOR_F_HAS_SR_TB = BIT(1), SNOR_F_HAS_SR_TB = BIT(1),
...@@ -244,6 +237,7 @@ enum spi_nor_option_flags { ...@@ -244,6 +237,7 @@ enum spi_nor_option_flags {
SNOR_F_HAS_LOCK = BIT(8), SNOR_F_HAS_LOCK = BIT(8),
SNOR_F_HAS_16BIT_SR = BIT(9), SNOR_F_HAS_16BIT_SR = BIT(9),
SNOR_F_NO_READ_CR = BIT(10), SNOR_F_NO_READ_CR = BIT(10),
SNOR_F_HAS_SR_TB_BIT6 = BIT(11),
}; };
...@@ -483,8 +477,8 @@ struct spi_nor; ...@@ -483,8 +477,8 @@ struct spi_nor;
* opcode via write_reg(). * opcode via write_reg().
*/ */
struct spi_nor_controller_ops { struct spi_nor_controller_ops {
int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops); int (*prepare)(struct spi_nor *nor);
void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops); void (*unprepare)(struct spi_nor *nor);
int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, size_t len); int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, size_t len);
int (*write_reg)(struct spi_nor *nor, u8 opcode, const u8 *buf, int (*write_reg)(struct spi_nor *nor, u8 opcode, const u8 *buf,
size_t len); size_t len);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment