From ec7478fa173f65e5ee5fd2ba42c59ca3e700027b Mon Sep 17 00:00:00 2001 From: shengyong Date: Thu, 25 Jun 2015 02:23:13 +0000 Subject: mtd: nandsim: fix free of NULL pointer If allocating ns->nand_pages_slab fails, do not try to destroy it when cleaning up nandsim resources. Signed-off-by: Sheng Yong Signed-off-by: Brian Norris --- drivers/mtd/nand/nandsim.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 52c0c1a..6a74f62 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -649,7 +649,8 @@ static void free_device(struct nandsim *ns) kmem_cache_free(ns->nand_pages_slab, ns->pages[i].byte); } - kmem_cache_destroy(ns->nand_pages_slab); + if (ns->nand_pages_slab) + kmem_cache_destroy(ns->nand_pages_slab); vfree(ns->pages); } } -- cgit v1.1 From 5891a8d11f79b9a45a7334a63d0fa731875bc308 Mon Sep 17 00:00:00 2001 From: shengyong Date: Thu, 25 Jun 2015 02:23:14 +0000 Subject: mtd: nandsim: fix double free Do not call free_device() in init_nandsim, the caller - ns_init_module - will take care of that if something goes wrong. Signed-off-by: Sheng Yong Signed-off-by: Brian Norris --- drivers/mtd/nand/nandsim.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 6a74f62..95d0cc4 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -730,8 +730,7 @@ static int init_nandsim(struct mtd_info *mtd) /* Fill the partition_info structure */ if (parts_num > ARRAY_SIZE(ns->partitions)) { NS_ERR("too many partitions.\n"); - ret = -EINVAL; - goto error; + return -EINVAL; } remains = ns->geom.totsz; next_offset = 0; @@ -740,14 +739,12 @@ static int init_nandsim(struct mtd_info *mtd) if (!part_sz || part_sz > remains) { NS_ERR("bad partition size.\n"); - ret = -EINVAL; - goto error; + return -EINVAL; } ns->partitions[i].name = get_partition_name(i); if (!ns->partitions[i].name) { NS_ERR("unable to allocate memory.\n"); - ret = -ENOMEM; - goto error; + return -ENOMEM; } ns->partitions[i].offset = next_offset; ns->partitions[i].size = part_sz; @@ -758,14 +755,12 @@ static int init_nandsim(struct mtd_info *mtd) if (remains) { if (parts_num + 1 > ARRAY_SIZE(ns->partitions)) { NS_ERR("too many partitions.\n"); - ret = -EINVAL; - goto error; + return -EINVAL; } ns->partitions[i].name = get_partition_name(i); if (!ns->partitions[i].name) { NS_ERR("unable to allocate memory.\n"); - ret = -ENOMEM; - goto error; + return -ENOMEM; } ns->partitions[i].offset = next_offset; ns->partitions[i].size = remains; @@ -793,24 +788,18 @@ static int init_nandsim(struct mtd_info *mtd) printk("options: %#x\n", ns->options); if ((ret = alloc_device(ns)) != 0) - goto error; + return ret; /* Allocate / initialize the internal buffer */ ns->buf.byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL); if (!ns->buf.byte) { NS_ERR("init_nandsim: unable to allocate %u bytes for the internal buffer\n", ns->geom.pgszoob); - ret = -ENOMEM; - goto error; + return -ENOMEM; } memset(ns->buf.byte, 0xFF, ns->geom.pgszoob); return 0; - -error: - free_device(ns); - - return ret; } /* -- cgit v1.1 From a11244c0b25b79d2a3b07df429268d66736e5b45 Mon Sep 17 00:00:00 2001 From: Sandeep Paulraj Date: Tue, 19 Aug 2014 15:31:54 +0300 Subject: nand: davinci: add support for 4K page size nand devices It is needed for k2l keystone2 EVM which uses NAND flash with 4K page size, hence add support for 4K page size nand devices. [Brian: similar work submitted by Murali Karicheri and Hao Zhang ] Signed-off-by: Sandeep Paulraj Signed-off-by: Ivan Khoronzhuk Signed-off-by: Brian Norris --- drivers/mtd/nand/davinci_nand.c | 42 ++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index feb6d18..b9080130 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -520,6 +520,32 @@ static struct nand_ecclayout hwecc4_2048 = { }, }; +/* + * An ECC layout for using 4-bit ECC with large-page (4096bytes) flash, + * storing ten ECC bytes plus the manufacturer's bad block marker byte, + * and not overlapping the default BBT markers. + */ +static struct nand_ecclayout hwecc4_4096 = { + .eccbytes = 80, + .eccpos = { + /* at the end of spare sector */ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + }, + .oobfree = { + /* 2 bytes at offset 0 hold manufacturer badblock markers */ + {.offset = 2, .length = 46, }, + /* 5 bytes at offset 8 hold BBT markers */ + /* 8 bytes at offset 16 hold JFFS2 clean markers */ + }, +}; + #if defined(CONFIG_OF) static const struct of_device_id davinci_nand_of_match[] = { {.compatible = "ti,davinci-nand", }, @@ -796,18 +822,12 @@ static int nand_davinci_probe(struct platform_device *pdev) info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST; goto syndrome_done; } + if (chunks == 8) { + info->ecclayout = hwecc4_4096; + info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST; + goto syndrome_done; + } - /* 4KiB page chips are not yet supported. The eccpos from - * nand_ecclayout cannot hold 80 bytes and change to eccpos[] - * breaks userspace ioctl interface with mtd-utils. Once we - * resolve this issue, NAND_ECC_HW_OOB_FIRST mode can be used - * for the 4KiB page chips. - * - * TODO: Note that nand_ecclayout has now been expanded and can - * hold plenty of OOB entries. - */ - dev_warn(&pdev->dev, "no 4-bit ECC support yet " - "for 4KiB-page NAND\n"); ret = -EIO; goto err; -- cgit v1.1 From cef1ed9c6bcf69245c0b9eb89b3f3a45049ba10c Mon Sep 17 00:00:00 2001 From: Nicolas Iooss Date: Sun, 5 Jul 2015 09:57:41 +0800 Subject: mtd: r852: make ecc_reg 32-bit in r852_ecc_correct r852_ecc_correct() reads a 32-bit register into a 16-bit variable, ecc_reg, but this variable is later used as if it was larger. This is reported by clang when building the kernel with many warnings: drivers/mtd/nand/r852.c:512:11: error: shift count >= width of type [-Werror,-Wshift-count-overflow] ecc_reg >>= 16; ^ ~~ Fix this by making ecc_reg 32-bit, like the return type of r852_read_reg_dword(). Signed-off-by: Nicolas Iooss Signed-off-by: Brian Norris --- drivers/mtd/nand/r852.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index 77e96d2..cc6bac5 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c @@ -466,7 +466,7 @@ static int r852_ecc_calculate(struct mtd_info *mtd, const uint8_t *dat, static int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc) { - uint16_t ecc_reg; + uint32_t ecc_reg; uint8_t ecc_status, err_byte; int i, error = 0; -- cgit v1.1 From 9c618292dba6aa9b82e8a2e4e6fe70f54bd87a81 Mon Sep 17 00:00:00 2001 From: Roy Spliet Date: Fri, 26 Jun 2015 11:00:10 +0200 Subject: mtd: nand: sunxi: Replace failsafe timing cfg with calculated value The TIMING_CFG register was previously statically set to a magic value (extracted from Allwinner's BSP) when initializing the NAND controller. Now that we have more details about the TIMING_CFG register layout (extracted from the A83 user manual) we can dynamically calculate the appropriate value for each NAND chip and set it when selecting the chip. Signed-off-by: Roy Spliet Acked-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/sunxi_nand.c | 73 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 5 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 6f93b29..663e331 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -99,6 +99,12 @@ NFC_CMD_INT_ENABLE | \ NFC_DMA_INT_ENABLE) +/* define NFC_TIMING_CFG register layout */ +#define NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD) \ + (((tWB) & 0x3) | (((tADL) & 0x3) << 2) | \ + (((tWHR) & 0x3) << 4) | (((tRHW) & 0x3) << 6) | \ + (((tCAD) & 0x7) << 8)) + /* define bit use in NFC_CMD */ #define NFC_CMD_LOW_BYTE GENMASK(7, 0) #define NFC_CMD_HIGH_BYTE GENMASK(15, 8) @@ -208,6 +214,7 @@ struct sunxi_nand_hw_ecc { * @nand: base NAND chip structure * @mtd: base MTD structure * @clk_rate: clk_rate required for this NAND chip + * @timing_cfg TIMING_CFG register value for this NAND chip * @selected: current active CS * @nsels: number of CS lines required by the NAND chip * @sels: array of CS lines descriptions @@ -217,6 +224,7 @@ struct sunxi_nand_chip { struct nand_chip nand; struct mtd_info mtd; unsigned long clk_rate; + u32 timing_cfg; int selected; int nsels; struct sunxi_nand_chip_sel sels[0]; @@ -403,6 +411,7 @@ static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip) } } + writel(sunxi_nand->timing_cfg, nfc->regs + NFC_REG_TIMING_CFG); writel(ctl, nfc->regs + NFC_REG_CTL); sunxi_nand->selected = chip; @@ -807,10 +816,33 @@ static int sunxi_nfc_hw_syndrome_ecc_write_page(struct mtd_info *mtd, return 0; } +static const s32 tWB_lut[] = {6, 12, 16, 20}; +static const s32 tRHW_lut[] = {4, 8, 12, 20}; + +static int _sunxi_nand_lookup_timing(const s32 *lut, int lut_size, u32 duration, + u32 clk_period) +{ + u32 clk_cycles = DIV_ROUND_UP(duration, clk_period); + int i; + + for (i = 0; i < lut_size; i++) { + if (clk_cycles <= lut[i]) + return i; + } + + /* Doesn't fit */ + return -EINVAL; +} + +#define sunxi_nand_lookup_timing(l, p, c) \ + _sunxi_nand_lookup_timing(l, ARRAY_SIZE(l), p, c) + static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip, const struct nand_sdr_timings *timings) { + struct sunxi_nfc *nfc = to_sunxi_nfc(chip->nand.controller); u32 min_clk_period = 0; + s32 tWB, tADL, tWHR, tRHW, tCAD; /* T1 <=> tCLS */ if (timings->tCLS_min > min_clk_period) @@ -872,6 +904,41 @@ static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip, if (timings->tWC_min > (min_clk_period * 2)) min_clk_period = DIV_ROUND_UP(timings->tWC_min, 2); + /* T16 - T19 + tCAD */ + tWB = sunxi_nand_lookup_timing(tWB_lut, timings->tWB_max, + min_clk_period); + if (tWB < 0) { + dev_err(nfc->dev, "unsupported tWB\n"); + return tWB; + } + + tADL = DIV_ROUND_UP(timings->tADL_min, min_clk_period) >> 3; + if (tADL > 3) { + dev_err(nfc->dev, "unsupported tADL\n"); + return -EINVAL; + } + + tWHR = DIV_ROUND_UP(timings->tWHR_min, min_clk_period) >> 3; + if (tWHR > 3) { + dev_err(nfc->dev, "unsupported tWHR\n"); + return -EINVAL; + } + + tRHW = sunxi_nand_lookup_timing(tRHW_lut, timings->tRHW_min, + min_clk_period); + if (tRHW < 0) { + dev_err(nfc->dev, "unsupported tRHW\n"); + return tRHW; + } + + /* + * TODO: according to ONFI specs this value only applies for DDR NAND, + * but Allwinner seems to set this to 0x7. Mimic them for now. + */ + tCAD = 0x7; + + /* TODO: A83 has some more bits for CDQSS, CS, CLHZ, CCS, WC */ + chip->timing_cfg = NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD); /* Convert min_clk_period from picoseconds to nanoseconds */ min_clk_period = DIV_ROUND_UP(min_clk_period, 1000); @@ -884,8 +951,6 @@ static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip, */ chip->clk_rate = (2 * NSEC_PER_SEC) / min_clk_period; - /* TODO: configure T16-T19 */ - return 0; } @@ -1377,11 +1442,9 @@ static int sunxi_nfc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, nfc); /* - * TODO: replace these magic values with proper flags as soon as we - * know what they are encoding. + * TODO: replace this magic value with EDO flag */ writel(0x100, nfc->regs + NFC_REG_TIMING_CTL); - writel(0x7ff, nfc->regs + NFC_REG_TIMING_CFG); ret = sunxi_nand_chips_init(dev, nfc); if (ret) { -- cgit v1.1 From d052e508a4069f0711ea68156f4b1565bf14c41c Mon Sep 17 00:00:00 2001 From: Roy Spliet Date: Fri, 26 Jun 2015 11:00:11 +0200 Subject: mtd: nand: sunxi: Set serial access mode correctly Replaces the hard coded "always use EDO" policy with that prescribed by the ONFI 3.1 specification that EDO mode should always be used if tRC is below 30ns. Signed-off-by: Roy Spliet Acked-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/sunxi_nand.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c index 663e331..f97a58d 100644 --- a/drivers/mtd/nand/sunxi_nand.c +++ b/drivers/mtd/nand/sunxi_nand.c @@ -99,6 +99,9 @@ NFC_CMD_INT_ENABLE | \ NFC_DMA_INT_ENABLE) +/* define bit use in NFC_TIMING_CTL */ +#define NFC_TIMING_CTL_EDO BIT(8) + /* define NFC_TIMING_CFG register layout */ #define NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD) \ (((tWB) & 0x3) | (((tADL) & 0x3) << 2) | \ @@ -225,6 +228,7 @@ struct sunxi_nand_chip { struct mtd_info mtd; unsigned long clk_rate; u32 timing_cfg; + u32 timing_ctl; int selected; int nsels; struct sunxi_nand_chip_sel sels[0]; @@ -411,6 +415,7 @@ static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip) } } + writel(sunxi_nand->timing_ctl, nfc->regs + NFC_REG_TIMING_CTL); writel(sunxi_nand->timing_cfg, nfc->regs + NFC_REG_TIMING_CFG); writel(ctl, nfc->regs + NFC_REG_CTL); @@ -940,6 +945,13 @@ static int sunxi_nand_chip_set_timings(struct sunxi_nand_chip *chip, /* TODO: A83 has some more bits for CDQSS, CS, CLHZ, CCS, WC */ chip->timing_cfg = NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD); + /* + * ONFI specification 3.1, paragraph 4.15.2 dictates that EDO data + * output cycle timings shall be used if the host drives tRC less than + * 30 ns. + */ + chip->timing_ctl = (timings->tRC_min < 30000) ? NFC_TIMING_CTL_EDO : 0; + /* Convert min_clk_period from picoseconds to nanoseconds */ min_clk_period = DIV_ROUND_UP(min_clk_period, 1000); @@ -1441,11 +1453,6 @@ static int sunxi_nfc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, nfc); - /* - * TODO: replace this magic value with EDO flag - */ - writel(0x100, nfc->regs + NFC_REG_TIMING_CTL); - ret = sunxi_nand_chips_init(dev, nfc); if (ret) { dev_err(dev, "failed to init nand chips\n"); -- cgit v1.1 From ddb2c42b677eb2883e532f0928e445fc205d0019 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 6 Aug 2015 12:29:37 +0800 Subject: mtd: brcmnand: Fix misuse of IS_ENABLED While IS_ENABLED() is perfectly fine for CONFIG_* symbols, it is not for other symbols such as __BIG_ENDIAN that is provided directly by the compiler. Switch to use CONFIG_CPU_BIG_ENDIAN instead of __BIG_ENDIAN. Fixes: 27c5b17cd1b1 ("mtd: nand: add NAND driver "library" for Broadcom STB NAND controller") Signed-off-by: Axel Lin Signed-off-by: Brian Norris --- drivers/mtd/nand/brcmnand/brcmnand.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/brcmnand/brcmnand.h b/drivers/mtd/nand/brcmnand/brcmnand.h index a20c736..169f99e 100644 --- a/drivers/mtd/nand/brcmnand/brcmnand.h +++ b/drivers/mtd/nand/brcmnand/brcmnand.h @@ -50,7 +50,7 @@ static inline u32 brcmnand_readl(void __iomem *addr) * Other architectures (e.g., ARM) either do not support big endian, or * else leave I/O in little endian mode. */ - if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(__BIG_ENDIAN)) + if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) return __raw_readl(addr); else return readl_relaxed(addr); @@ -59,7 +59,7 @@ static inline u32 brcmnand_readl(void __iomem *addr) static inline void brcmnand_writel(u32 val, void __iomem *addr) { /* See brcmnand_readl() comments */ - if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(__BIG_ENDIAN)) + if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) __raw_writel(val, addr); else writel_relaxed(val, addr); -- cgit v1.1 From c16340973fcb6461474a9f811f7f3ff2f946b24c Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 3 Aug 2015 11:31:26 -0300 Subject: nand: pxa3xx: Increase initial buffer size The initial buffer is used for the initial commands used to detect a flash device (STATUS, READID and PARAM). ONFI param page is 256 bytes, and there are three redundant copies to be read. JEDEC param page is 512 bytes, and there are also three redundant copies to be read. Hence this buffer should be at least 512 x 3. This commits rounds the buffer size to 2048. Signed-off-by: Ezequiel Garcia Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 1259cc5..9d973cd 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -45,10 +45,13 @@ /* * Define a buffer size for the initial command that detects the flash device: - * STATUS, READID and PARAM. The largest of these is the PARAM command, - * needing 256 bytes. + * STATUS, READID and PARAM. + * ONFI param page is 256 bytes, and there are three redundant copies + * to be read. JEDEC param page is 512 bytes, and there are also three + * redundant copies to be read. + * Hence this buffer should be at least 512 x 3. Let's pick 2048. */ -#define INIT_BUFFER_SIZE 256 +#define INIT_BUFFER_SIZE 2048 /* registers and bit definitions */ #define NDCR (0x00) /* Control register */ @@ -899,14 +902,14 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, break; case NAND_CMD_PARAM: - info->buf_count = 256; + info->buf_count = INIT_BUFFER_SIZE; info->ndcb0 |= NDCB0_CMD_TYPE(0) | NDCB0_ADDR_CYC(1) | NDCB0_LEN_OVRD | command; info->ndcb1 = (column & 0xFF); - info->ndcb3 = 256; - info->data_size = 256; + info->ndcb3 = INIT_BUFFER_SIZE; + info->data_size = INIT_BUFFER_SIZE; break; case NAND_CMD_READID: -- cgit v1.1 From 04868a67ed582e845bf14a5a7789f8bdb3faadd3 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 6 Aug 2015 16:04:21 +0300 Subject: mtd: denali: hide core part from user in Kconfig There is no need to user to see the core part of the driver. Signed-off-by: Andy Shevchenko Signed-off-by: Brian Norris --- drivers/mtd/nand/Kconfig | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 5b2806a..3324281 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -42,23 +42,20 @@ config MTD_SM_COMMON default n config MTD_NAND_DENALI - tristate "Support Denali NAND controller" - depends on HAS_DMA - help - Enable support for the Denali NAND controller. This should be - combined with either the PCI or platform drivers to provide device - registration. + tristate config MTD_NAND_DENALI_PCI tristate "Support Denali NAND controller on Intel Moorestown" - depends on PCI && MTD_NAND_DENALI + select MTD_NAND_DENALI + depends on HAS_DMA && PCI help Enable the driver for NAND flash on Intel Moorestown, using the Denali NAND controller core. config MTD_NAND_DENALI_DT tristate "Support Denali NAND controller as a DT device" - depends on HAVE_CLK && MTD_NAND_DENALI + select MTD_NAND_DENALI + depends on HAS_DMA && HAVE_CLK help Enable the driver for NAND flash on platforms using a Denali NAND controller as a DT device. -- cgit v1.1 From 2445d33d852320d4ce700b2428d60991f8cf478f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 6 Aug 2015 16:04:22 +0300 Subject: mtd: denali_pci: use module_pci_driver() macro Let's use module_pci_driver() macro to reduce code base of the driver. There is no functional change. Signed-off-by: Andy Shevchenko Signed-off-by: Brian Norris --- drivers/mtd/nand/denali_pci.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/denali_pci.c index 6e2f387..29e5d0c 100644 --- a/drivers/mtd/nand/denali_pci.c +++ b/drivers/mtd/nand/denali_pci.c @@ -129,14 +129,4 @@ static struct pci_driver denali_pci_driver = { .remove = denali_pci_remove, }; -static int denali_init_pci(void) -{ - return pci_register_driver(&denali_pci_driver); -} -module_init(denali_init_pci); - -static void denali_exit_pci(void) -{ - pci_unregister_driver(&denali_pci_driver); -} -module_exit(denali_exit_pci); +module_pci_driver(denali_pci_driver); -- cgit v1.1 From add243d5bc371eef66f81c9da4fd4b55a18dad23 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 6 Aug 2015 16:04:23 +0300 Subject: mtd: denali_pci: refactor driver using devres API In recent kernels we have a lot of helper functions, including devres API, to make life of device driver developer easy. Convert the driver using devm_kzalloc() and pcim_enable_device(). Signed-off-by: Andy Shevchenko Signed-off-by: Brian Norris --- drivers/mtd/nand/denali_pci.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/denali_pci.c index 29e5d0c..ad16e2e 100644 --- a/drivers/mtd/nand/denali_pci.c +++ b/drivers/mtd/nand/denali_pci.c @@ -30,19 +30,19 @@ MODULE_DEVICE_TABLE(pci, denali_pci_ids); static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { - int ret = -ENODEV; + int ret; resource_size_t csr_base, mem_base; unsigned long csr_len, mem_len; struct denali_nand_info *denali; - denali = kzalloc(sizeof(*denali), GFP_KERNEL); + denali = devm_kzalloc(&dev->dev, sizeof(*denali), GFP_KERNEL); if (!denali) return -ENOMEM; - ret = pci_enable_device(dev); + ret = pcim_enable_device(dev); if (ret) { pr_err("Spectra: pci_enable_device failed.\n"); - goto failed_alloc_memery; + return ret; } if (id->driver_data == INTEL_CE4100) { @@ -70,14 +70,13 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) ret = pci_request_regions(dev, DENALI_NAND_NAME); if (ret) { pr_err("Spectra: Unable to request memory regions\n"); - goto failed_enable_dev; + return ret; } denali->flash_reg = ioremap_nocache(csr_base, csr_len); if (!denali->flash_reg) { pr_err("Spectra: Unable to remap memory region\n"); - ret = -ENOMEM; - goto failed_req_regions; + return -ENOMEM; } denali->flash_mem = ioremap_nocache(mem_base, mem_len); @@ -99,13 +98,6 @@ failed_remap_mem: iounmap(denali->flash_mem); failed_remap_reg: iounmap(denali->flash_reg); -failed_req_regions: - pci_release_regions(dev); -failed_enable_dev: - pci_disable_device(dev); -failed_alloc_memery: - kfree(denali); - return ret; } @@ -117,9 +109,6 @@ static void denali_pci_remove(struct pci_dev *dev) denali_remove(denali); iounmap(denali->flash_reg); iounmap(denali->flash_mem); - pci_release_regions(dev); - pci_disable_device(dev); - kfree(denali); } static struct pci_driver denali_pci_driver = { -- cgit v1.1 From af83a67cad1452d48ecd77792f9218f26c445650 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 6 Aug 2015 16:04:24 +0300 Subject: mtd: denali_pci: switch to dev_err() It is better to have device name prefixed the actual error message. Signed-off-by: Andy Shevchenko Signed-off-by: Brian Norris --- drivers/mtd/nand/denali_pci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/denali_pci.c index ad16e2e..de31514 100644 --- a/drivers/mtd/nand/denali_pci.c +++ b/drivers/mtd/nand/denali_pci.c @@ -41,7 +41,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) ret = pcim_enable_device(dev); if (ret) { - pr_err("Spectra: pci_enable_device failed.\n"); + dev_err(&dev->dev, "Spectra: pci_enable_device failed.\n"); return ret; } @@ -69,19 +69,19 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) ret = pci_request_regions(dev, DENALI_NAND_NAME); if (ret) { - pr_err("Spectra: Unable to request memory regions\n"); + dev_err(&dev->dev, "Spectra: Unable to request memory regions\n"); return ret; } denali->flash_reg = ioremap_nocache(csr_base, csr_len); if (!denali->flash_reg) { - pr_err("Spectra: Unable to remap memory region\n"); + dev_err(&dev->dev, "Spectra: Unable to remap memory region\n"); return -ENOMEM; } denali->flash_mem = ioremap_nocache(mem_base, mem_len); if (!denali->flash_mem) { - pr_err("Spectra: ioremap_nocache failed!"); + dev_err(&dev->dev, "Spectra: ioremap_nocache failed!"); ret = -ENOMEM; goto failed_remap_reg; } -- cgit v1.1 From 0f0aca5d50ced8d8c18c7982a6b6332182b70e33 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 18 Aug 2015 21:03:13 +0800 Subject: mtd: omap_elm: Fix module alias Remove extra space after the "platform:" prefix and make the alias matches driver name. Signed-off-by: Axel Lin Acked-by: Roger Quadros Signed-off-by: Brian Norris --- drivers/mtd/nand/omap_elm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/omap_elm.c b/drivers/mtd/nand/omap_elm.c index 376bfe1..235ec79 100644 --- a/drivers/mtd/nand/omap_elm.c +++ b/drivers/mtd/nand/omap_elm.c @@ -574,5 +574,5 @@ module_platform_driver(elm_driver); MODULE_DESCRIPTION("ELM driver for BCH error correction"); MODULE_AUTHOR("Texas Instruments"); -MODULE_ALIAS("platform: elm"); +MODULE_ALIAS("platform:" DRIVER_NAME); MODULE_LICENSE("GPL v2"); -- cgit v1.1 From bc3e00f04cc1fe033a289c2fc2e5c73c0168d360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20T=C3=A9nart?= Date: Tue, 18 Aug 2015 10:59:10 +0200 Subject: mtd: pxa3xx_nand: add a default chunk size When keeping the configuration set by the bootloader (by using the marvell,nand-keep-config property), the pxa3xx_nand_detect_config() function is called and set the chunk size to 512 as a default value if NDCR_PAGE_SZ is not set. In the other case, when not keeping the bootloader configuration, no chunk size is set. Fix this by adding a default chunk size of 512. Fixes: 70ed85232a93 ("mtd: nand: pxa3xx: Introduce multiple page I/O support") Signed-off-by: Antoine Tenart Acked-by: Robert Jarzmik Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 9d973cd..baf3246 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1476,6 +1476,9 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) if (pdata->keep_config && !pxa3xx_nand_detect_config(info)) goto KEEP_CONFIG; + /* Set a default chunk size */ + info->chunk_size = 512; + ret = pxa3xx_nand_sensing(info); if (ret) { dev_info(&info->pdev->dev, "There is no chip on cs %d!\n", -- cgit v1.1 From 0b14392db2e998157d924085d7913e537ec26121 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Wed, 19 Aug 2015 20:30:14 +0200 Subject: mtd: nand: pxa3xx_nand: fix early spurious interrupt When the nand is first probe, and upon the first command start, the status bits should be cleared before the interrupts are unmasked. The bug is tricky : if the bootloader left a status bit set, the unmasking of interrupts does trigger the interrupt handler before the first command is issued, blocking the good behavior of the nand. The same would happen if in pxa3xx_nand code flow a status bit is left, and then a command is started. Signed-off-by: Robert Jarzmik Acked-by: Ezequiel Garcia Tested-by: Ezequiel Garcia Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index baf3246..faf056b 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -442,8 +442,8 @@ static void pxa3xx_nand_start(struct pxa3xx_nand_info *info) ndcr |= NDCR_ND_RUN; /* clear status bits and run */ - nand_writel(info, NDCR, 0); nand_writel(info, NDSR, NDSR_MASK); + nand_writel(info, NDCR, 0); nand_writel(info, NDCR, ndcr); } -- cgit v1.1 From 21fc0ef9652f0c809dc0d3e0a67f1e1bf6ff8255 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Wed, 19 Aug 2015 20:30:15 +0200 Subject: mtd: nand: pxa3xx-nand: fix random command timeouts When 2 commands are submitted in a row, and the second is very quick, the completion of the second command might never come. This happens especially if the second command is quick, such as a status read after an erase. The issue is that in the interrupt handler, the status bits are cleared after the new command is issued. There is a small temporal window where this happens : - the previous command has set the command done bit - the ready for a command bit is set - the handler submits the next command - just then, the command completes, and the command done bit is still set - the handler clears the "previous" command done bit - the handler exits In this flow, the "command done" of the next command will never trigger a new interrupt to finish the status command, as it was cleared for both commands. Fix this by clearing the status bit before submitting a new command. Signed-off-by: Robert Jarzmik Acked-by: Ezequiel Garcia Tested-by: Ezequiel Garcia Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index faf056b..51f8a58 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -678,8 +678,14 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) is_ready = 1; } + /* + * Clear all status bit before issuing the next command, which + * can and will alter the status bits and will deserve a new + * interrupt on its own. This lets the controller exit the IRQ + */ + nand_writel(info, NDSR, status); + if (status & NDSR_WRCMDREQ) { - nand_writel(info, NDSR, NDSR_WRCMDREQ); status &= ~NDSR_WRCMDREQ; info->state = STATE_CMD_HANDLE; @@ -700,8 +706,6 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) nand_writel(info, NDCB0, info->ndcb3); } - /* clear NDSR to let the controller exit the IRQ */ - nand_writel(info, NDSR, status); if (is_completed) complete(&info->cmd_complete); if (is_ready) -- cgit v1.1 From b226eca2088004622434cbcc27c6401b64f22d7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= Date: Wed, 19 Aug 2015 19:40:09 -0300 Subject: nand: pxa3xx: Increase READ_ID buffer and make the size static The read ID count should be made as large as the maximum READ_ID size, so there's no need to have dynamic size. This commit sets the hardware maximum read ID count, which should be more than enough on all cases. Also, we get rid of the read_id_bytes, and use a macro instead. Signed-off-by: Ezequiel Garcia Acked-by: Robert Jarzmik Signed-off-by: Brian Norris --- drivers/mtd/nand/pxa3xx_nand.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 51f8a58..740983a 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -129,6 +129,13 @@ #define EXT_CMD_TYPE_LAST_RW 1 /* Last naked read/write */ #define EXT_CMD_TYPE_MONO 0 /* Monolithic read/write */ +/* + * This should be large enough to read 'ONFI' and 'JEDEC'. + * Let's use 7 bytes, which is the maximum ID count supported + * by the controller (see NDCR_RD_ID_CNT_MASK). + */ +#define READ_ID_BYTES 7 + /* macros for registers read/write */ #define nand_writel(info, off, val) \ writel_relaxed((val), (info)->mmio_base + (off)) @@ -176,8 +183,6 @@ struct pxa3xx_nand_host { /* calculated from pxa3xx_nand_flash data */ unsigned int col_addr_cycles; unsigned int row_addr_cycles; - size_t read_id_bytes; - }; struct pxa3xx_nand_info { @@ -917,7 +922,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, break; case NAND_CMD_READID: - info->buf_count = host->read_id_bytes; + info->buf_count = READ_ID_BYTES; info->ndcb0 |= NDCB0_CMD_TYPE(3) | NDCB0_ADDR_CYC(1) | command; @@ -1254,9 +1259,6 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, return -EINVAL; } - /* calculate flash information */ - host->read_id_bytes = (f->page_size == 2048) ? 4 : 2; - /* calculate addressing information */ host->col_addr_cycles = (f->page_size == 2048) ? 2 : 1; @@ -1272,7 +1274,7 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0; ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0; - ndcr |= NDCR_RD_ID_CNT(host->read_id_bytes); + ndcr |= NDCR_RD_ID_CNT(READ_ID_BYTES); ndcr |= NDCR_SPARE_EN; /* enable spare by default */ info->reg_ndcr = ndcr; @@ -1283,23 +1285,10 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) { - /* - * We set 0 by hard coding here, for we don't support keep_config - * when there is more than one chip attached to the controller - */ - struct pxa3xx_nand_host *host = info->host[0]; uint32_t ndcr = nand_readl(info, NDCR); - if (ndcr & NDCR_PAGE_SZ) { - /* Controller's FIFO size */ - info->chunk_size = 2048; - host->read_id_bytes = 4; - } else { - info->chunk_size = 512; - host->read_id_bytes = 2; - } - /* Set an initial chunk size */ + info->chunk_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512; info->reg_ndcr = ndcr & ~NDCR_INT_MASK; info->ndtr0cs0 = nand_readl(info, NDTR0CS0); info->ndtr1cs0 = nand_readl(info, NDTR1CS0); -- cgit v1.1 From 0cb850486048ba4f64482a9d3e33dff47df34c79 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Wed, 31 Dec 2014 13:58:53 +0100 Subject: mtd: nand: add Toshiba TC58NVG0S3E to nand_ids table Add the full description of the Toshiba TC58NVG0S3E NAND chip in the nand_ids table so that we can later use the NAND ECC info and ONFI timing mode in controller drivers. Tested with asm9260_nand driver. [Brian: driver still under review] Signed-off-by: Oleksij Rempel Reviewed-by: Boris Brezillon Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_ids.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/mtd/nand') diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 7124400..a8804a3 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -29,6 +29,10 @@ struct nand_flash_dev nand_flash_ids[] = { * listed by full ID. We list them first so that we can easily identify * the most specific match. */ + {"TC58NVG0S3E 1G 3.3V 8-bit", + { .id = {0x98, 0xd1, 0x90, 0x15, 0x76, 0x14, 0x01, 0x00} }, + SZ_2K, SZ_128, SZ_128K, 0, 8, 64, NAND_ECC_INFO(1, SZ_512), + 2 }, {"TC58NVG2S0F 4G 3.3V 8-bit", { .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} }, SZ_4K, SZ_512, SZ_256K, 0, 8, 224, NAND_ECC_INFO(4, SZ_512) }, -- cgit v1.1