Commit c3c1acaf authored by Richard Weinberger's avatar Richard Weinberger

Merge tag 'nand/for-5.4' of...

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

NAND core
* Fixing typos
* Adding missing of_node_put() in various drivers

Raw NAND controller drivers:
* Macronix: new controller driver
* Omap2: Fixing the number of bitflips returned
* Brcmnand: Fix a pointer not iterating over all the page chunks
* W90x900: Driver removed
* Onenand: Fix a memory leak
* Sharpsl: Missing include guard
* STM32: Avoid warnings when building with W=1
* Ingenic: Fix a coccinelle warning
* r852: Call a helper to simplify the code
parents 089cf7f6 f480b969
Macronix Raw NAND Controller Device Tree Bindings
-------------------------------------------------
Required properties:
- compatible: should be "mxic,multi-itfc-v009-nand-controller"
- reg: should contain 1 entry for the registers
- #address-cells: should be set to 1
- #size-cells: should be set to 0
- interrupts: interrupt line connected to this raw NAND controller
- clock-names: should contain "ps", "send" and "send_dly"
- clocks: should contain 3 phandles for the "ps", "send" and
"send_dly" clocks
Children nodes:
- children nodes represent the available NAND chips.
See Documentation/devicetree/bindings/mtd/nand-controller.yaml
for more details on generic bindings.
Example:
nand: nand-controller@43c30000 {
compatible = "mxic,multi-itfc-v009-nand-controller";
reg = <0x43c30000 0x10000>;
#address-cells = <1>;
#size-cells = <0>;
interrupts = <GIC_SPI 0x1d IRQ_TYPE_EDGE_RISING>;
clocks = <&clkwizard 0>, <&clkwizard 1>, <&clkc 15>;
clock-names = "send", "send_dly", "ps";
nand@0 {
reg = <0>;
nand-ecc-mode = "soft";
nand-ecc-algo = "bch";
};
};
...@@ -3880,6 +3880,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) ...@@ -3880,6 +3880,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
if (!this->oob_buf) { if (!this->oob_buf) {
if (this->options & ONENAND_PAGEBUF_ALLOC) { if (this->options & ONENAND_PAGEBUF_ALLOC) {
this->options &= ~ONENAND_PAGEBUF_ALLOC; this->options &= ~ONENAND_PAGEBUF_ALLOC;
#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
kfree(this->verify_buf);
#endif
kfree(this->page_buf); kfree(this->page_buf);
} }
return -ENOMEM; return -ENOMEM;
......
...@@ -351,14 +351,6 @@ config MTD_NAND_SOCRATES ...@@ -351,14 +351,6 @@ config MTD_NAND_SOCRATES
help help
Enables support for NAND Flash chips wired onto Socrates board. Enables support for NAND Flash chips wired onto Socrates board.
config MTD_NAND_NUC900
tristate "Nuvoton NUC9xx/w90p910 NAND controller"
depends on ARCH_W90X900 || COMPILE_TEST
depends on HAS_IOMEM
help
This enables the driver for the NAND Flash on evaluation board based
on w90p910 / NUC9xx.
source "drivers/mtd/nand/raw/ingenic/Kconfig" source "drivers/mtd/nand/raw/ingenic/Kconfig"
config MTD_NAND_FSMC config MTD_NAND_FSMC
...@@ -407,6 +399,12 @@ config MTD_NAND_MTK ...@@ -407,6 +399,12 @@ config MTD_NAND_MTK
Enables support for NAND controller on MTK SoCs. Enables support for NAND controller on MTK SoCs.
This controller is found on mt27xx, mt81xx, mt65xx SoCs. This controller is found on mt27xx, mt81xx, mt65xx SoCs.
config MTD_NAND_MXIC
tristate "Macronix raw NAND controller"
depends on HAS_IOMEM || COMPILE_TEST
help
This selects the Macronix raw NAND controller driver.
config MTD_NAND_TEGRA config MTD_NAND_TEGRA
tristate "NVIDIA Tegra NAND controller" tristate "NVIDIA Tegra NAND controller"
depends on ARCH_TEGRA || COMPILE_TEST depends on ARCH_TEGRA || COMPILE_TEST
......
...@@ -41,7 +41,6 @@ obj-$(CONFIG_MTD_NAND_SH_FLCTL) += sh_flctl.o ...@@ -41,7 +41,6 @@ obj-$(CONFIG_MTD_NAND_SH_FLCTL) += sh_flctl.o
obj-$(CONFIG_MTD_NAND_MXC) += mxc_nand.o obj-$(CONFIG_MTD_NAND_MXC) += mxc_nand.o
obj-$(CONFIG_MTD_NAND_SOCRATES) += socrates_nand.o obj-$(CONFIG_MTD_NAND_SOCRATES) += socrates_nand.o
obj-$(CONFIG_MTD_NAND_TXX9NDFMC) += txx9ndfmc.o obj-$(CONFIG_MTD_NAND_TXX9NDFMC) += txx9ndfmc.o
obj-$(CONFIG_MTD_NAND_NUC900) += nuc900_nand.o
obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o
obj-$(CONFIG_MTD_NAND_VF610_NFC) += vf610_nfc.o obj-$(CONFIG_MTD_NAND_VF610_NFC) += vf610_nfc.o
obj-$(CONFIG_MTD_NAND_RICOH) += r852.o obj-$(CONFIG_MTD_NAND_RICOH) += r852.o
...@@ -54,6 +53,7 @@ obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o ...@@ -54,6 +53,7 @@ obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/ obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/
obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o
obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o
obj-$(CONFIG_MTD_NAND_MXIC) += mxic_nand.o
obj-$(CONFIG_MTD_NAND_TEGRA) += tegra_nand.o obj-$(CONFIG_MTD_NAND_TEGRA) += tegra_nand.o
obj-$(CONFIG_MTD_NAND_STM32_FMC2) += stm32_fmc2_nand.o obj-$(CONFIG_MTD_NAND_STM32_FMC2) += stm32_fmc2_nand.o
obj-$(CONFIG_MTD_NAND_MESON) += meson_nand.o obj-$(CONFIG_MTD_NAND_MESON) += meson_nand.o
......
...@@ -1792,6 +1792,7 @@ static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd, ...@@ -1792,6 +1792,7 @@ static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd,
int bitflips = 0; int bitflips = 0;
int page = addr >> chip->page_shift; int page = addr >> chip->page_shift;
int ret; int ret;
void *ecc_chunk;
if (!buf) if (!buf)
buf = nand_get_data_buf(chip); buf = nand_get_data_buf(chip);
...@@ -1804,7 +1805,9 @@ static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd, ...@@ -1804,7 +1805,9 @@ static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd,
return ret; return ret;
for (i = 0; i < chip->ecc.steps; i++, oob += sas) { for (i = 0; i < chip->ecc.steps; i++, oob += sas) {
ret = nand_check_erased_ecc_chunk(buf, chip->ecc.size, ecc_chunk = buf + chip->ecc.size * i;
ret = nand_check_erased_ecc_chunk(ecc_chunk,
chip->ecc.size,
oob, sas, NULL, 0, oob, sas, NULL, 0,
chip->ecc.strength); chip->ecc.strength);
if (ret < 0) if (ret < 0)
......
...@@ -310,7 +310,6 @@ static int ingenic_nand_init_chip(struct platform_device *pdev, ...@@ -310,7 +310,6 @@ static int ingenic_nand_init_chip(struct platform_device *pdev,
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct ingenic_nand *nand; struct ingenic_nand *nand;
struct ingenic_nand_cs *cs; struct ingenic_nand_cs *cs;
struct resource *res;
struct nand_chip *chip; struct nand_chip *chip;
struct mtd_info *mtd; struct mtd_info *mtd;
const __be32 *reg; const __be32 *reg;
...@@ -326,8 +325,7 @@ static int ingenic_nand_init_chip(struct platform_device *pdev, ...@@ -326,8 +325,7 @@ static int ingenic_nand_init_chip(struct platform_device *pdev,
jz4780_nemc_set_type(nfc->dev, cs->bank, JZ4780_NEMC_BANK_NAND); jz4780_nemc_set_type(nfc->dev, cs->bank, JZ4780_NEMC_BANK_NAND);
res = platform_get_resource(pdev, IORESOURCE_MEM, chipnr); cs->base = devm_platform_ioremap_resource(pdev, chipnr);
cs->base = devm_ioremap_resource(dev, res);
if (IS_ERR(cs->base)) if (IS_ERR(cs->base))
return PTR_ERR(cs->base); return PTR_ERR(cs->base);
...@@ -418,6 +416,7 @@ static int ingenic_nand_init_chips(struct ingenic_nfc *nfc, ...@@ -418,6 +416,7 @@ static int ingenic_nand_init_chips(struct ingenic_nfc *nfc,
ret = ingenic_nand_init_chip(pdev, nfc, np, i); ret = ingenic_nand_init_chip(pdev, nfc, np, i);
if (ret) { if (ret) {
ingenic_nand_cleanup_chips(nfc); ingenic_nand_cleanup_chips(nfc);
of_node_put(np);
return ret; return ret;
} }
......
...@@ -1320,6 +1320,7 @@ static int meson_nfc_nand_chips_init(struct device *dev, ...@@ -1320,6 +1320,7 @@ static int meson_nfc_nand_chips_init(struct device *dev,
ret = meson_nfc_nand_chip_init(dev, nfc, nand_np); ret = meson_nfc_nand_chip_init(dev, nfc, nand_np);
if (ret) { if (ret) {
meson_nfc_nand_chip_cleanup(nfc); meson_nfc_nand_chip_cleanup(nfc);
of_node_put(nand_np);
return ret; return ret;
} }
} }
......
This diff is collapsed.
...@@ -4112,7 +4112,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to, ...@@ -4112,7 +4112,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
struct mtd_oob_ops *ops) struct mtd_oob_ops *ops)
{ {
struct nand_chip *chip = mtd_to_nand(mtd); struct nand_chip *chip = mtd_to_nand(mtd);
int ret = -ENOTSUPP; int ret;
ops->retlen = 0; ops->retlen = 0;
......
...@@ -1232,7 +1232,7 @@ static int nand_scan_bbt(struct nand_chip *this, struct nand_bbt_descr *bd) ...@@ -1232,7 +1232,7 @@ static int nand_scan_bbt(struct nand_chip *this, struct nand_bbt_descr *bd)
if (!td) { if (!td) {
if ((res = nand_memory_bbt(this, bd))) { if ((res = nand_memory_bbt(this, bd))) {
pr_err("nand_bbt: can't scan flash and build the RAM-based BBT\n"); pr_err("nand_bbt: can't scan flash and build the RAM-based BBT\n");
goto err; goto err_free_bbt;
} }
return 0; return 0;
} }
...@@ -1245,7 +1245,7 @@ static int nand_scan_bbt(struct nand_chip *this, struct nand_bbt_descr *bd) ...@@ -1245,7 +1245,7 @@ static int nand_scan_bbt(struct nand_chip *this, struct nand_bbt_descr *bd)
buf = vmalloc(len); buf = vmalloc(len);
if (!buf) { if (!buf) {
res = -ENOMEM; res = -ENOMEM;
goto err; goto err_free_bbt;
} }
/* Is the bbt at a given page? */ /* Is the bbt at a given page? */
...@@ -1258,7 +1258,7 @@ static int nand_scan_bbt(struct nand_chip *this, struct nand_bbt_descr *bd) ...@@ -1258,7 +1258,7 @@ static int nand_scan_bbt(struct nand_chip *this, struct nand_bbt_descr *bd)
res = check_create(this, buf, bd); res = check_create(this, buf, bd);
if (res) if (res)
goto err; goto err_free_buf;
/* Prevent the bbt regions from erasing / writing */ /* Prevent the bbt regions from erasing / writing */
mark_bbt_region(this, td); mark_bbt_region(this, td);
...@@ -1268,7 +1268,9 @@ static int nand_scan_bbt(struct nand_chip *this, struct nand_bbt_descr *bd) ...@@ -1268,7 +1268,9 @@ static int nand_scan_bbt(struct nand_chip *this, struct nand_bbt_descr *bd)
vfree(buf); vfree(buf);
return 0; return 0;
err: err_free_buf:
vfree(buf);
err_free_bbt:
kfree(this->bbt); kfree(this->bbt);
this->bbt = NULL; this->bbt = NULL;
return res; return res;
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright © 2009 Nuvoton technology corporation.
*
* Wan ZongShun <mcuos.com@gmail.com>
*/
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#define REG_FMICSR 0x00
#define REG_SMCSR 0xa0
#define REG_SMISR 0xac
#define REG_SMCMD 0xb0
#define REG_SMADDR 0xb4
#define REG_SMDATA 0xb8
#define RESET_FMI 0x01
#define NAND_EN 0x08
#define READYBUSY (0x01 << 18)
#define SWRST 0x01
#define PSIZE (0x01 << 3)
#define DMARWEN (0x03 << 1)
#define BUSWID (0x01 << 4)
#define ECC4EN (0x01 << 5)
#define WP (0x01 << 24)
#define NANDCS (0x01 << 25)
#define ENDADDR (0x01 << 31)
#define read_data_reg(dev) \
__raw_readl((dev)->reg + REG_SMDATA)
#define write_data_reg(dev, val) \
__raw_writel((val), (dev)->reg + REG_SMDATA)
#define write_cmd_reg(dev, val) \
__raw_writel((val), (dev)->reg + REG_SMCMD)
#define write_addr_reg(dev, val) \
__raw_writel((val), (dev)->reg + REG_SMADDR)
struct nuc900_nand {
struct nand_chip chip;
void __iomem *reg;
struct clk *clk;
spinlock_t lock;
};
static inline struct nuc900_nand *mtd_to_nuc900(struct mtd_info *mtd)
{
return container_of(mtd_to_nand(mtd), struct nuc900_nand, chip);
}
static const struct mtd_partition partitions[] = {
{
.name = "NAND FS 0",
.offset = 0,
.size = 8 * 1024 * 1024
},
{
.name = "NAND FS 1",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL
}
};
static unsigned char nuc900_nand_read_byte(struct nand_chip *chip)
{
unsigned char ret;
struct nuc900_nand *nand = mtd_to_nuc900(nand_to_mtd(chip));
ret = (unsigned char)read_data_reg(nand);
return ret;
}
static void nuc900_nand_read_buf(struct nand_chip *chip,
unsigned char *buf, int len)
{
int i;
struct nuc900_nand *nand = mtd_to_nuc900(nand_to_mtd(chip));
for (i = 0; i < len; i++)
buf[i] = (unsigned char)read_data_reg(nand);
}
static void nuc900_nand_write_buf(struct nand_chip *chip,
const unsigned char *buf, int len)
{
int i;
struct nuc900_nand *nand = mtd_to_nuc900(nand_to_mtd(chip));
for (i = 0; i < len; i++)
write_data_reg(nand, buf[i]);
}
static int nuc900_check_rb(struct nuc900_nand *nand)
{
unsigned int val;
spin_lock(&nand->lock);
val = __raw_readl(nand->reg + REG_SMISR);
val &= READYBUSY;
spin_unlock(&nand->lock);
return val;
}
static int nuc900_nand_devready(struct nand_chip *chip)
{
struct nuc900_nand *nand = mtd_to_nuc900(nand_to_mtd(chip));
int ready;
ready = (nuc900_check_rb(nand)) ? 1 : 0;
return ready;
}
static void nuc900_nand_command_lp(struct nand_chip *chip,
unsigned int command,
int column, int page_addr)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct nuc900_nand *nand = mtd_to_nuc900(mtd);
if (command == NAND_CMD_READOOB) {
column += mtd->writesize;
command = NAND_CMD_READ0;
}
write_cmd_reg(nand, command & 0xff);
if (column != -1 || page_addr != -1) {
if (column != -1) {
if (chip->options & NAND_BUSWIDTH_16 &&
!nand_opcode_8bits(command))
column >>= 1;
write_addr_reg(nand, column);
write_addr_reg(nand, column >> 8 | ENDADDR);
}
if (page_addr != -1) {
write_addr_reg(nand, page_addr);
if (chip->options & NAND_ROW_ADDR_3) {
write_addr_reg(nand, page_addr >> 8);
write_addr_reg(nand, page_addr >> 16 | ENDADDR);
} else {
write_addr_reg(nand, page_addr >> 8 | ENDADDR);
}
}
}
switch (command) {
case NAND_CMD_CACHEDPROG:
case NAND_CMD_PAGEPROG:
case NAND_CMD_ERASE1:
case NAND_CMD_ERASE2:
case NAND_CMD_SEQIN:
case NAND_CMD_RNDIN:
case NAND_CMD_STATUS:
return;
case NAND_CMD_RESET:
if (chip->legacy.dev_ready)
break;
udelay(chip->legacy.chip_delay);
write_cmd_reg(nand, NAND_CMD_STATUS);
write_cmd_reg(nand, command);
while (!nuc900_check_rb(nand))
;
return;
case NAND_CMD_RNDOUT:
write_cmd_reg(nand, NAND_CMD_RNDOUTSTART);
return;
case NAND_CMD_READ0:
write_cmd_reg(nand, NAND_CMD_READSTART);
/* fall through */
default:
if (!chip->legacy.dev_ready) {
udelay(chip->legacy.chip_delay);
return;
}
}
/* Apply this short delay always to ensure that we do wait tWB in
* any case on any machine. */
ndelay(100);
while (!chip->legacy.dev_ready(chip))
;
}
static void nuc900_nand_enable(struct nuc900_nand *nand)
{
unsigned int val;
spin_lock(&nand->lock);
__raw_writel(RESET_FMI, (nand->reg + REG_FMICSR));
val = __raw_readl(nand->reg + REG_FMICSR);
if (!(val & NAND_EN))
__raw_writel(val | NAND_EN, nand->reg + REG_FMICSR);
val = __raw_readl(nand->reg + REG_SMCSR);
val &= ~(SWRST|PSIZE|DMARWEN|BUSWID|ECC4EN|NANDCS);
val |= WP;
__raw_writel(val, nand->reg + REG_SMCSR);
spin_unlock(&nand->lock);
}
static int nuc900_nand_probe(struct platform_device *pdev)
{
struct nuc900_nand *nuc900_nand;
struct nand_chip *chip;
struct mtd_info *mtd;
struct resource *res;
nuc900_nand = devm_kzalloc(&pdev->dev, sizeof(struct nuc900_nand),
GFP_KERNEL);
if (!nuc900_nand)
return -ENOMEM;
chip = &(nuc900_nand->chip);
mtd = nand_to_mtd(chip);
mtd->dev.parent = &pdev->dev;
spin_lock_init(&nuc900_nand->lock);
nuc900_nand->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(nuc900_nand->clk))
return -ENOENT;
clk_enable(nuc900_nand->clk);
chip->legacy.cmdfunc = nuc900_nand_command_lp;
chip->legacy.dev_ready = nuc900_nand_devready;
chip->legacy.read_byte = nuc900_nand_read_byte;
chip->legacy.write_buf = nuc900_nand_write_buf;
chip->legacy.read_buf = nuc900_nand_read_buf;
chip->legacy.chip_delay = 50;
chip->options = 0;
chip->ecc.mode = NAND_ECC_SOFT;
chip->ecc.algo = NAND_ECC_HAMMING;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
nuc900_nand->reg = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(nuc900_nand->reg))
return PTR_ERR(nuc900_nand->reg);
nuc900_nand_enable(nuc900_nand);
if (nand_scan(chip, 1))
return -ENXIO;
mtd_device_register(mtd, partitions, ARRAY_SIZE(partitions));
platform_set_drvdata(pdev, nuc900_nand);
return 0;
}
static int nuc900_nand_remove(struct platform_device *pdev)
{
struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev);
nand_release(&nuc900_nand->chip);
clk_disable(nuc900_nand->clk);
return 0;
}
static struct platform_driver nuc900_nand_driver = {
.probe = nuc900_nand_probe,
.remove = nuc900_nand_remove,
.driver = {
.name = "nuc900-fmi",
},
};
module_platform_driver(nuc900_nand_driver);
MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
MODULE_DESCRIPTION("w90p910/NUC9xx nand driver!");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:nuc900-fmi");
...@@ -1501,7 +1501,7 @@ static int omap_elm_correct_data(struct nand_chip *chip, u_char *data, ...@@ -1501,7 +1501,7 @@ static int omap_elm_correct_data(struct nand_chip *chip, u_char *data,
} }
/* Update number of correctable errors */ /* Update number of correctable errors */
stat += err_vec[i].error_count; stat = max_t(unsigned int, stat, err_vec[i].error_count);
/* Update page data with sector size */ /* Update page data with sector size */
data += ecc->size; data += ecc->size;
......
...@@ -116,7 +116,7 @@ static int oxnas_nand_probe(struct platform_device *pdev) ...@@ -116,7 +116,7 @@ static int oxnas_nand_probe(struct platform_device *pdev)
GFP_KERNEL); GFP_KERNEL);
if (!chip) { if (!chip) {
err = -ENOMEM; err = -ENOMEM;
goto err_clk_unprepare; goto err_release_child;
} }
chip->controller = &oxnas->base; chip->controller = &oxnas->base;
...@@ -137,12 +137,12 @@ static int oxnas_nand_probe(struct platform_device *pdev) ...@@ -137,12 +137,12 @@ static int oxnas_nand_probe(struct platform_device *pdev)
/* Scan to find existence of the device */ /* Scan to find existence of the device */
err = nand_scan(chip, 1); err = nand_scan(chip, 1);
if (err) if (err)
goto err_clk_unprepare; goto err_release_child;
err = mtd_device_register(mtd, NULL, 0); err = mtd_device_register(mtd, NULL, 0);
if (err) { if (err) {
nand_release(chip); nand_release(chip);
goto err_clk_unprepare; goto err_release_child;
} }
oxnas->chips[nchips] = chip; oxnas->chips[nchips] = chip;
...@@ -159,6 +159,8 @@ static int oxnas_nand_probe(struct platform_device *pdev) ...@@ -159,6 +159,8 @@ static int oxnas_nand_probe(struct platform_device *pdev)
return 0; return 0;
err_release_child:
of_node_put(nand_np);
err_clk_unprepare: err_clk_unprepare:
clk_disable_unprepare(oxnas->clk); clk_disable_unprepare(oxnas->clk);
return err; return err;
......
...@@ -998,7 +998,7 @@ static void r852_shutdown(struct pci_dev *pci_dev) ...@@ -998,7 +998,7 @@ static void r852_shutdown(struct pci_dev *pci_dev)
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int r852_suspend(struct device *device) static int r852_suspend(struct device *device)
{ {
struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); struct r852_device *dev = dev_get_drvdata(device);
if (dev->ctlreg & R852_CTL_CARDENABLE) if (dev->ctlreg & R852_CTL_CARDENABLE)
return -EBUSY; return -EBUSY;
...@@ -1019,7 +1019,7 @@ static int r852_suspend(struct device *device) ...@@ -1019,7 +1019,7 @@ static int r852_suspend(struct device *device)
static int r852_resume(struct device *device) static int r852_resume(struct device *device)
{ {
struct r852_device *dev = pci_get_drvdata(to_pci_dev(device)); struct r852_device *dev = dev_get_drvdata(device);
r852_disable_irqs(dev); r852_disable_irqs(dev);
r852_card_update_present(dev); r852_card_update_present(dev);
......
...@@ -1427,21 +1427,16 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip, ...@@ -1427,21 +1427,16 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
struct stm32_fmc2_timings *tims = &nand->timings; struct stm32_fmc2_timings *tims = &nand->timings;
unsigned long hclk = clk_get_rate(fmc2->clk); unsigned long hclk = clk_get_rate(fmc2->clk);
unsigned long hclkp = NSEC_PER_SEC / (hclk / 1000); unsigned long hclkp = NSEC_PER_SEC / (hclk / 1000);
int tar, tclr, thiz, twait, tset_mem, tset_att, thold_mem, thold_att; unsigned long timing, tar, tclr, thiz, twait;
unsigned long tset_mem, tset_att, thold_mem, thold_att;
tar = hclkp;
if (tar < sdrt->tAR_min) tar = max_t(unsigned long, hclkp, sdrt->tAR_min);
tar = sdrt->tAR_min; timing = DIV_ROUND_UP(tar, hclkp) - 1;
tims->tar = DIV_ROUND_UP(tar, hclkp) - 1; tims->tar = min_t(unsigned long, timing, FMC2_PCR_TIMING_MASK);
if (tims->tar > FMC2_PCR_TIMING_MASK)
tims->tar = FMC2_PCR_TIMING_MASK; tclr = max_t(unsigned long, hclkp, sdrt->tCLR_min);
timing = DIV_ROUND_UP(tclr, hclkp) - 1;
tclr = hclkp; tims->tclr = min_t(unsigned long, timing, FMC2_PCR_TIMING_MASK);
if (tclr < sdrt->tCLR_min)
tclr = sdrt->tCLR_min;
tims->tclr = DIV_ROUND_UP(tclr, hclkp) - 1;
if (tims->tclr > FMC2_PCR_TIMING_MASK)
tims->tclr = FMC2_PCR_TIMING_MASK;
tims->thiz = FMC2_THIZ; tims->thiz = FMC2_THIZ;
thiz = (tims->thiz + 1) * hclkp; thiz = (tims->thiz + 1) * hclkp;
...@@ -1451,18 +1446,11 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip, ...@@ -1451,18 +1446,11 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
* tWAIT > tWP * tWAIT > tWP
* tWAIT > tREA + tIO * tWAIT > tREA + tIO
*/ */
twait = hclkp; twait = max_t(unsigned long, hclkp, sdrt->tRP_min);
if (twait < sdrt->tRP_min) twait = max_t(unsigned long, twait, sdrt->tWP_min);
twait = sdrt->tRP_min; twait = max_t(unsigned long, twait, sdrt->tREA_max + FMC2_TIO);
if (twait < sdrt->tWP_min) timing = DIV_ROUND_UP(twait, hclkp);
twait = sdrt->tWP_min; tims->twait = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
if (twait < sdrt->tREA_max + FMC2_TIO)
twait = sdrt->tREA_max + FMC2_TIO;
tims->twait = DIV_ROUND_UP(twait, hclkp);
if (tims->twait == 0)
tims->twait = 1;
else if (tims->twait > FMC2_PMEM_PATT_TIMING_MASK)
tims->twait = FMC2_PMEM_PATT_TIMING_MASK;
/* /*
* tSETUP_MEM > tCS - tWAIT * tSETUP_MEM > tCS - tWAIT
...@@ -1477,20 +1465,15 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip, ...@@ -1477,20 +1465,15 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
if (twait > thiz && (sdrt->tDS_min > twait - thiz) && if (twait > thiz && (sdrt->tDS_min > twait - thiz) &&
(tset_mem < sdrt->tDS_min - (twait - thiz))) (tset_mem < sdrt->tDS_min - (twait - thiz)))
tset_mem = sdrt->tDS_min - (twait - thiz); tset_mem = sdrt->tDS_min - (twait - thiz);
tims->tset_mem = DIV_ROUND_UP(tset_mem, hclkp); timing = DIV_ROUND_UP(tset_mem, hclkp);
if (tims->tset_mem == 0) tims->tset_mem = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
tims->tset_mem = 1;
else if (tims->tset_mem > FMC2_PMEM_PATT_TIMING_MASK)
tims->tset_mem = FMC2_PMEM_PATT_TIMING_MASK;
/* /*
* tHOLD_MEM > tCH * tHOLD_MEM > tCH
* tHOLD_MEM > tREH - tSETUP_MEM * tHOLD_MEM > tREH - tSETUP_MEM
* tHOLD_MEM > max(tRC, tWC) - (tSETUP_MEM + tWAIT) * tHOLD_MEM > max(tRC, tWC) - (tSETUP_MEM + tWAIT)
*/ */
thold_mem = hclkp; thold_mem = max_t(unsigned long, hclkp, sdrt->tCH_min);
if (thold_mem < sdrt->tCH_min)
thold_mem = sdrt->tCH_min;
if (sdrt->tREH_min > tset_mem && if (sdrt->tREH_min > tset_mem &&
(thold_mem < sdrt->tREH_min - tset_mem)) (thold_mem < sdrt->tREH_min - tset_mem))
thold_mem = sdrt->tREH_min - tset_mem; thold_mem = sdrt->tREH_min - tset_mem;
...@@ -1500,11 +1483,8 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip, ...@@ -1500,11 +1483,8 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
if ((sdrt->tWC_min > tset_mem + twait) && if ((sdrt->tWC_min > tset_mem + twait) &&
(thold_mem < sdrt->tWC_min - (tset_mem + twait))) (thold_mem < sdrt->tWC_min - (tset_mem + twait)))
thold_mem = sdrt->tWC_min - (tset_mem + twait); thold_mem = sdrt->tWC_min - (tset_mem + twait);
tims->thold_mem = DIV_ROUND_UP(thold_mem, hclkp); timing = DIV_ROUND_UP(thold_mem, hclkp);
if (tims->thold_mem == 0) tims->thold_mem = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
tims->thold_mem = 1;
else if (tims->thold_mem > FMC2_PMEM_PATT_TIMING_MASK)
tims->thold_mem = FMC2_PMEM_PATT_TIMING_MASK;
/* /*
* tSETUP_ATT > tCS - tWAIT * tSETUP_ATT > tCS - tWAIT
...@@ -1526,11 +1506,8 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip, ...@@ -1526,11 +1506,8 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
if (twait > thiz && (sdrt->tDS_min > twait - thiz) && if (twait > thiz && (sdrt->tDS_min > twait - thiz) &&
(tset_att < sdrt->tDS_min - (twait - thiz))) (tset_att < sdrt->tDS_min - (twait - thiz)))
tset_att = sdrt->tDS_min - (twait - thiz); tset_att = sdrt->tDS_min - (twait - thiz);
tims->tset_att = DIV_ROUND_UP(tset_att, hclkp); timing = DIV_ROUND_UP(tset_att, hclkp);
if (tims->tset_att == 0) tims->tset_att = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
tims->tset_att = 1;
else if (tims->tset_att > FMC2_PMEM_PATT_TIMING_MASK)
tims->tset_att = FMC2_PMEM_PATT_TIMING_MASK;
/* /*
* tHOLD_ATT > tALH * tHOLD_ATT > tALH
...@@ -1545,17 +1522,11 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip, ...@@ -1545,17 +1522,11 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
* tHOLD_ATT > tRC - (tSETUP_ATT + tWAIT) * tHOLD_ATT > tRC - (tSETUP_ATT + tWAIT)
* tHOLD_ATT > tWC - (tSETUP_ATT + tWAIT) * tHOLD_ATT > tWC - (tSETUP_ATT + tWAIT)
*/ */
thold_att = hclkp; thold_att = max_t(unsigned long, hclkp, sdrt->tALH_min);
if (thold_att < sdrt->tALH_min) thold_att = max_t(unsigned long, thold_att, sdrt->tCH_min);
thold_att = sdrt->tALH_min; thold_att = max_t(unsigned long, thold_att, sdrt->tCLH_min);
if (thold_att < sdrt->tCH_min) thold_att = max_t(unsigned long, thold_att, sdrt->tCOH_min);
thold_att = sdrt->tCH_min; thold_att = max_t(unsigned long, thold_att, sdrt->tDH_min);
if (thold_att < sdrt->tCLH_min)
thold_att = sdrt->tCLH_min;
if (thold_att < sdrt->tCOH_min)
thold_att = sdrt->tCOH_min;
if (thold_att < sdrt->tDH_min)
thold_att = sdrt->tDH_min;
if ((sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC > tset_mem) && if ((sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC > tset_mem) &&
(thold_att < sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC - tset_mem)) (thold_att < sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC - tset_mem))
thold_att = sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC - tset_mem; thold_att = sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC - tset_mem;
...@@ -1574,11 +1545,8 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip, ...@@ -1574,11 +1545,8 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
if ((sdrt->tWC_min > tset_att + twait) && if ((sdrt->tWC_min > tset_att + twait) &&
(thold_att < sdrt->tWC_min - (tset_att + twait))) (thold_att < sdrt->tWC_min - (tset_att + twait)))
thold_att = sdrt->tWC_min - (tset_att + twait); thold_att = sdrt->tWC_min - (tset_att + twait);
tims->thold_att = DIV_ROUND_UP(thold_att, hclkp); timing = DIV_ROUND_UP(thold_att, hclkp);
if (tims->thold_att == 0) tims->thold_att = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
tims->thold_att = 1;
else if (tims->thold_att > FMC2_PMEM_PATT_TIMING_MASK)
tims->thold_att = FMC2_PMEM_PATT_TIMING_MASK;
} }
static int stm32_fmc2_setup_interface(struct nand_chip *chip, int chipnr, static int stm32_fmc2_setup_interface(struct nand_chip *chip, int chipnr,
......
...@@ -659,6 +659,7 @@ static int tango_nand_probe(struct platform_device *pdev) ...@@ -659,6 +659,7 @@ static int tango_nand_probe(struct platform_device *pdev)
err = chip_init(&pdev->dev, np); err = chip_init(&pdev->dev, np);
if (err) { if (err) {
tango_nand_remove(pdev); tango_nand_remove(pdev);
of_node_put(np);
return err; return err;
} }
} }
......
...@@ -862,6 +862,7 @@ static int vf610_nfc_probe(struct platform_device *pdev) ...@@ -862,6 +862,7 @@ static int vf610_nfc_probe(struct platform_device *pdev)
dev_err(nfc->dev, dev_err(nfc->dev,
"Only one NAND chip supported!\n"); "Only one NAND chip supported!\n");
err = -EINVAL; err = -EINVAL;
of_node_put(child);
goto err_disable_clk; goto err_disable_clk;
} }
......
...@@ -346,7 +346,7 @@ static inline unsigned int nanddev_ntargets(const struct nand_device *nand) ...@@ -346,7 +346,7 @@ static inline unsigned int nanddev_ntargets(const struct nand_device *nand)
} }
/** /**
* nanddev_neraseblocks() - Get the total number of erasablocks * nanddev_neraseblocks() - Get the total number of eraseblocks
* @nand: NAND device * @nand: NAND device
* *
* Return: the total number of eraseblocks exposed by @nand. * Return: the total number of eraseblocks exposed by @nand.
......
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
* Copyright (C) 2008 Dmitry Baryshkov * Copyright (C) 2008 Dmitry Baryshkov
*/ */
#ifndef _MTD_SHARPSL_H
#define _MTD_SHARPSL_H
#include <linux/mtd/rawnand.h> #include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_ecc.h> #include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
...@@ -16,3 +19,5 @@ struct sharpsl_nand_platform_data { ...@@ -16,3 +19,5 @@ struct sharpsl_nand_platform_data {
unsigned int nr_partitions; unsigned int nr_partitions;
const char *const *part_parsers; const char *const *part_parsers;
}; };
#endif /* _MTD_SHARPSL_H */
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