mirror of
https://github.com/torvalds/linux.git
synced 2024-11-29 23:51:37 +00:00
Raw NAND core changes:
* Drop obsolete dependencies on COMPILE_TEST * MAINTAINERS: rectify entry for MESON NAND controller bindings * Drop EXPORT_SYMBOL_GPL for nanddev_erase() Raw NAND driver changes: * marvell: Enable NFC/DEVBUS arbiter * gpmi: Use pm_runtime_resume_and_get instead of pm_runtime_get_sync * mpc5121: Replace NO_IRQ by 0 * lpc32xx_{slc,mlc}: - Switch to using pm_ptr() - Switch to using gpiod API * lpc32xx_mlc: Switch to using pm_ptr() * cadence: Support 64-bit slave dma interface * rockchip: Describe rk3128-nfc in the bindings * brcmnand: Update interrupts description in the bindings SPI-NAND driver changes: * winbond: - Add Winbond W25N02KV flash support - Fix flash identification -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEE9HuaYnbmDhq/XIDIJWrqGEe9VoQFAmOGGfIACgkQJWrqGEe9 VoSZVQgAmew5RtMegFus/AXflUsGYCvZKfV1LVnxmSoGIKBrJr3yjzh6mFuLyzaP qt2KljEJ4dblk2M3efosX5YeAkz7A7evm218NHGeKWHMPCDimSE1ptAyBhhMmsVi cgCgu3LXh369dK9OAm7ZVR4hOdDuK5rpYIcXA4mUh0yqiFxfxsuuNY7QBDVrN+qt SNmZkTBbCgGRxo7RRanN2ljnSm31p6TyhngUDKG89puMka9gGA9yWLbWFDpwM5SS L0Tr2ZOHctzz/X/1s2yPcnN6ZPpqsc1wLnGyLOWlhkm7oo7aiT59rlHj9GHbp82h 7lXf7MeWxSNSVr9PMHHUR7XDqlLaOw== =aOZ+ -----END PGP SIGNATURE----- Merge tag 'nand/for-6.2' into mtd/next Raw NAND core changes: * Drop obsolete dependencies on COMPILE_TEST * MAINTAINERS: rectify entry for MESON NAND controller bindings * Drop EXPORT_SYMBOL_GPL for nanddev_erase() Raw NAND driver changes: * marvell: Enable NFC/DEVBUS arbiter * gpmi: Use pm_runtime_resume_and_get instead of pm_runtime_get_sync * mpc5121: Replace NO_IRQ by 0 * lpc32xx_{slc,mlc}: - Switch to using pm_ptr() - Switch to using gpiod API * lpc32xx_mlc: Switch to using pm_ptr() * cadence: Support 64-bit slave dma interface * rockchip: Describe rk3128-nfc in the bindings * brcmnand: Update interrupts description in the bindings SPI-NAND driver changes: * winbond: - Add Winbond W25N02KV flash support - Fix flash identification Fix merge conflict with mtd tree regarding the brcm bindings. Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
This commit is contained in:
commit
1d46f1ae82
@ -86,15 +86,15 @@ properties:
|
||||
minItems: 1
|
||||
items:
|
||||
- description: NAND CTLRDY interrupt
|
||||
- description: FLASH_DMA_DONE if flash DMA is available
|
||||
- description: FLASH_EDU_DONE if EDU is available
|
||||
- description: FLASH_DMA_DONE (if flash DMA is available) or FLASH_EDU_DONE (if EDU is available)
|
||||
|
||||
interrupt-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: nand_ctlrdy
|
||||
- const: flash_dma_done
|
||||
- const: flash_edu_done
|
||||
- enum:
|
||||
- flash_dma_done
|
||||
- flash_edu_done
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
@ -173,6 +173,13 @@ allOf:
|
||||
- const: nand
|
||||
- const: iproc-idm
|
||||
- const: iproc-ext
|
||||
- if:
|
||||
properties:
|
||||
interrupts:
|
||||
minItems: 2
|
||||
then:
|
||||
required:
|
||||
- interrupt-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
@ -190,6 +197,7 @@ examples:
|
||||
reg-names = "nand", "flash-dma";
|
||||
interrupt-parent = <&hif_intr2_intc>;
|
||||
interrupts = <24>, <4>;
|
||||
interrupt-names = "nand_ctlrdy", "flash_dma_done";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -19,7 +19,9 @@ properties:
|
||||
- const: rockchip,rk2928-nfc
|
||||
- const: rockchip,rv1108-nfc
|
||||
- items:
|
||||
- const: rockchip,rk3036-nfc
|
||||
- enum:
|
||||
- rockchip,rk3036-nfc
|
||||
- rockchip,rk3128-nfc
|
||||
- const: rockchip,rk2928-nfc
|
||||
- items:
|
||||
- const: rockchip,rk3308-nfc
|
||||
|
@ -13382,7 +13382,7 @@ MESON NAND CONTROLLER DRIVER FOR AMLOGIC SOCS
|
||||
M: Liang Yang <liang.yang@amlogic.com>
|
||||
L: linux-mtd@lists.infradead.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/mtd/amlogic,meson-nand.txt
|
||||
F: Documentation/devicetree/bindings/mtd/amlogic,meson-nand.yaml
|
||||
F: drivers/mtd/nand/raw/meson_*
|
||||
|
||||
MESON VIDEO DECODER DRIVER FOR AMLOGIC SOCS
|
||||
|
@ -126,7 +126,7 @@ EXPORT_SYMBOL_GPL(nanddev_isreserved);
|
||||
*
|
||||
* Return: 0 in case of success, a negative error code otherwise.
|
||||
*/
|
||||
int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos)
|
||||
static int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos)
|
||||
{
|
||||
if (nanddev_isbad(nand, pos) || nanddev_isreserved(nand, pos)) {
|
||||
pr_warn("attempt to erase a bad/reserved block @%llx\n",
|
||||
@ -136,7 +136,6 @@ int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos)
|
||||
|
||||
return nand->ops->erase(nand, pos);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nanddev_erase);
|
||||
|
||||
/**
|
||||
* nanddev_mtd_erase() - Generic mtd->_erase() implementation for NAND devices
|
||||
|
@ -415,7 +415,7 @@ config MTD_NAND_PLATFORM
|
||||
|
||||
config MTD_NAND_CADENCE
|
||||
tristate "Support Cadence NAND (HPNFC) controller"
|
||||
depends on (OF || COMPILE_TEST) && HAS_IOMEM
|
||||
depends on OF && HAS_IOMEM
|
||||
help
|
||||
Enable the driver for NAND flash on platforms using a Cadence NAND
|
||||
controller.
|
||||
@ -430,7 +430,7 @@ config MTD_NAND_ARASAN
|
||||
|
||||
config MTD_NAND_INTEL_LGM
|
||||
tristate "Support for NAND controller on Intel LGM SoC"
|
||||
depends on OF || COMPILE_TEST
|
||||
depends on OF
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
Enables support for NAND Flash chips on Intel's LGM SoC.
|
||||
@ -450,7 +450,7 @@ config MTD_NAND_ROCKCHIP
|
||||
|
||||
config MTD_NAND_PL35X
|
||||
tristate "ARM PL35X NAND controller"
|
||||
depends on OF || COMPILE_TEST
|
||||
depends on OF
|
||||
depends on PL353_SMC
|
||||
help
|
||||
Enables support for PrimeCell SMC PL351 and PL353 NAND
|
||||
|
@ -1184,6 +1184,14 @@ static int cadence_nand_hw_init(struct cdns_nand_ctrl *cdns_ctrl)
|
||||
if (cadence_nand_read_bch_caps(cdns_ctrl))
|
||||
return -EIO;
|
||||
|
||||
#ifndef CONFIG_64BIT
|
||||
if (cdns_ctrl->caps2.data_dma_width == 8) {
|
||||
dev_err(cdns_ctrl->dev,
|
||||
"cannot access 64-bit dma on !64-bit architectures");
|
||||
return -EIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set IO width access to 8.
|
||||
* It is because during SW device discovering width access
|
||||
@ -1882,17 +1890,36 @@ static int cadence_nand_read_buf(struct cdns_nand_ctrl *cdns_ctrl,
|
||||
return status;
|
||||
|
||||
if (!cdns_ctrl->caps1->has_dma) {
|
||||
int len_in_words = len >> 2;
|
||||
u8 data_dma_width = cdns_ctrl->caps2.data_dma_width;
|
||||
|
||||
int len_in_words = (data_dma_width == 4) ? len >> 2 : len >> 3;
|
||||
|
||||
/* read alingment data */
|
||||
ioread32_rep(cdns_ctrl->io.virt, buf, len_in_words);
|
||||
if (data_dma_width == 4)
|
||||
ioread32_rep(cdns_ctrl->io.virt, buf, len_in_words);
|
||||
#ifdef CONFIG_64BIT
|
||||
else
|
||||
readsq(cdns_ctrl->io.virt, buf, len_in_words);
|
||||
#endif
|
||||
|
||||
if (sdma_size > len) {
|
||||
int read_bytes = (data_dma_width == 4) ?
|
||||
len_in_words << 2 : len_in_words << 3;
|
||||
|
||||
/* read rest data from slave DMA interface if any */
|
||||
ioread32_rep(cdns_ctrl->io.virt, cdns_ctrl->buf,
|
||||
sdma_size / 4 - len_in_words);
|
||||
if (data_dma_width == 4)
|
||||
ioread32_rep(cdns_ctrl->io.virt,
|
||||
cdns_ctrl->buf,
|
||||
sdma_size / 4 - len_in_words);
|
||||
#ifdef CONFIG_64BIT
|
||||
else
|
||||
readsq(cdns_ctrl->io.virt, cdns_ctrl->buf,
|
||||
sdma_size / 8 - len_in_words);
|
||||
#endif
|
||||
|
||||
/* copy rest of data */
|
||||
memcpy(buf + (len_in_words << 2), cdns_ctrl->buf,
|
||||
len - (len_in_words << 2));
|
||||
memcpy(buf + read_bytes, cdns_ctrl->buf,
|
||||
len - read_bytes);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1936,16 +1963,35 @@ static int cadence_nand_write_buf(struct cdns_nand_ctrl *cdns_ctrl,
|
||||
return status;
|
||||
|
||||
if (!cdns_ctrl->caps1->has_dma) {
|
||||
int len_in_words = len >> 2;
|
||||
u8 data_dma_width = cdns_ctrl->caps2.data_dma_width;
|
||||
|
||||
int len_in_words = (data_dma_width == 4) ? len >> 2 : len >> 3;
|
||||
|
||||
if (data_dma_width == 4)
|
||||
iowrite32_rep(cdns_ctrl->io.virt, buf, len_in_words);
|
||||
#ifdef CONFIG_64BIT
|
||||
else
|
||||
writesq(cdns_ctrl->io.virt, buf, len_in_words);
|
||||
#endif
|
||||
|
||||
iowrite32_rep(cdns_ctrl->io.virt, buf, len_in_words);
|
||||
if (sdma_size > len) {
|
||||
int written_bytes = (data_dma_width == 4) ?
|
||||
len_in_words << 2 : len_in_words << 3;
|
||||
|
||||
/* copy rest of data */
|
||||
memcpy(cdns_ctrl->buf, buf + (len_in_words << 2),
|
||||
len - (len_in_words << 2));
|
||||
memcpy(cdns_ctrl->buf, buf + written_bytes,
|
||||
len - written_bytes);
|
||||
|
||||
/* write all expected by nand controller data */
|
||||
iowrite32_rep(cdns_ctrl->io.virt, cdns_ctrl->buf,
|
||||
sdma_size / 4 - len_in_words);
|
||||
if (data_dma_width == 4)
|
||||
iowrite32_rep(cdns_ctrl->io.virt,
|
||||
cdns_ctrl->buf,
|
||||
sdma_size / 4 - len_in_words);
|
||||
#ifdef CONFIG_64BIT
|
||||
else
|
||||
writesq(cdns_ctrl->io.virt, cdns_ctrl->buf,
|
||||
sdma_size / 8 - len_in_words);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -148,11 +148,9 @@ static int gpmi_init(struct gpmi_nand_data *this)
|
||||
struct resources *r = &this->resources;
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_get_sync(this->dev);
|
||||
if (ret < 0) {
|
||||
pm_runtime_put_noidle(this->dev);
|
||||
ret = pm_runtime_resume_and_get(this->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpmi_reset_block(r->gpmi_regs, false);
|
||||
if (ret)
|
||||
@ -2504,11 +2502,9 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip,
|
||||
for (i = 0; i < GPMI_MAX_TRANSFERS; i++)
|
||||
this->transfers[i].direction = DMA_NONE;
|
||||
|
||||
ret = pm_runtime_get_sync(this->dev);
|
||||
if (ret < 0) {
|
||||
pm_runtime_put_noidle(this->dev);
|
||||
ret = pm_runtime_resume_and_get(this->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This driver currently supports only one NAND chip. Plus, dies share
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include <linux/completion.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/mtd/lpc32xx_mlc.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mm.h>
|
||||
@ -122,7 +122,6 @@ struct lpc32xx_nand_cfg_mlc {
|
||||
uint32_t rd_low;
|
||||
uint32_t wr_high;
|
||||
uint32_t wr_low;
|
||||
int wp_gpio;
|
||||
struct mtd_partition *parts;
|
||||
unsigned num_parts;
|
||||
};
|
||||
@ -177,6 +176,7 @@ struct lpc32xx_nand_host {
|
||||
struct nand_chip nand_chip;
|
||||
struct lpc32xx_mlc_platform_data *pdata;
|
||||
struct clk *clk;
|
||||
struct gpio_desc *wp_gpio;
|
||||
void __iomem *io_base;
|
||||
int irq;
|
||||
struct lpc32xx_nand_cfg_mlc *ncfg;
|
||||
@ -370,8 +370,8 @@ static int lpc32xx_waitfunc(struct nand_chip *chip)
|
||||
*/
|
||||
static void lpc32xx_wp_enable(struct lpc32xx_nand_host *host)
|
||||
{
|
||||
if (gpio_is_valid(host->ncfg->wp_gpio))
|
||||
gpio_set_value(host->ncfg->wp_gpio, 0);
|
||||
if (host->wp_gpio)
|
||||
gpiod_set_value_cansleep(host->wp_gpio, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -379,8 +379,8 @@ static void lpc32xx_wp_enable(struct lpc32xx_nand_host *host)
|
||||
*/
|
||||
static void lpc32xx_wp_disable(struct lpc32xx_nand_host *host)
|
||||
{
|
||||
if (gpio_is_valid(host->ncfg->wp_gpio))
|
||||
gpio_set_value(host->ncfg->wp_gpio, 1);
|
||||
if (host->wp_gpio)
|
||||
gpiod_set_value_cansleep(host->wp_gpio, 0);
|
||||
}
|
||||
|
||||
static void lpc32xx_dma_complete_func(void *completion)
|
||||
@ -636,8 +636,6 @@ static struct lpc32xx_nand_cfg_mlc *lpc32xx_parse_dt(struct device *dev)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ncfg->wp_gpio = of_get_named_gpio(np, "gpios", 0);
|
||||
|
||||
return ncfg;
|
||||
}
|
||||
|
||||
@ -713,14 +711,18 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
|
||||
"Missing or bad NAND config from device tree\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
if (host->ncfg->wp_gpio == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
if (gpio_is_valid(host->ncfg->wp_gpio) &&
|
||||
gpio_request(host->ncfg->wp_gpio, "NAND WP")) {
|
||||
dev_err(&pdev->dev, "GPIO not available\n");
|
||||
return -EBUSY;
|
||||
|
||||
/* Start with WP disabled, if available */
|
||||
host->wp_gpio = gpiod_get_optional(&pdev->dev, NULL, GPIOD_OUT_LOW);
|
||||
res = PTR_ERR_OR_ZERO(host->wp_gpio);
|
||||
if (res) {
|
||||
if (res != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev, "WP GPIO is not available: %d\n",
|
||||
res);
|
||||
return res;
|
||||
}
|
||||
lpc32xx_wp_disable(host);
|
||||
|
||||
gpiod_set_consumer_name(host->wp_gpio, "NAND WP");
|
||||
|
||||
host->pdata = dev_get_platdata(&pdev->dev);
|
||||
|
||||
@ -817,7 +819,7 @@ put_clk:
|
||||
clk_put(host->clk);
|
||||
free_gpio:
|
||||
lpc32xx_wp_enable(host);
|
||||
gpio_free(host->ncfg->wp_gpio);
|
||||
gpiod_put(host->wp_gpio);
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -843,12 +845,11 @@ static int lpc32xx_nand_remove(struct platform_device *pdev)
|
||||
clk_put(host->clk);
|
||||
|
||||
lpc32xx_wp_enable(host);
|
||||
gpio_free(host->ncfg->wp_gpio);
|
||||
gpiod_put(host->wp_gpio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int lpc32xx_nand_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
|
||||
@ -880,11 +881,6 @@ static int lpc32xx_nand_suspend(struct platform_device *pdev, pm_message_t pm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#define lpc32xx_nand_resume NULL
|
||||
#define lpc32xx_nand_suspend NULL
|
||||
#endif
|
||||
|
||||
static const struct of_device_id lpc32xx_nand_match[] = {
|
||||
{ .compatible = "nxp,lpc3220-mlc" },
|
||||
{ /* sentinel */ },
|
||||
@ -894,8 +890,8 @@ MODULE_DEVICE_TABLE(of, lpc32xx_nand_match);
|
||||
static struct platform_driver lpc32xx_nand_driver = {
|
||||
.probe = lpc32xx_nand_probe,
|
||||
.remove = lpc32xx_nand_remove,
|
||||
.resume = lpc32xx_nand_resume,
|
||||
.suspend = lpc32xx_nand_suspend,
|
||||
.resume = pm_ptr(lpc32xx_nand_resume),
|
||||
.suspend = pm_ptr(lpc32xx_nand_suspend),
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = lpc32xx_nand_match,
|
||||
|
@ -23,9 +23,8 @@
|
||||
#include <linux/mm.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/mtd/lpc32xx_slc.h>
|
||||
|
||||
#define LPC32XX_MODNAME "lpc32xx-nand"
|
||||
@ -208,7 +207,6 @@ struct lpc32xx_nand_cfg_slc {
|
||||
uint32_t rwidth;
|
||||
uint32_t rhold;
|
||||
uint32_t rsetup;
|
||||
int wp_gpio;
|
||||
struct mtd_partition *parts;
|
||||
unsigned num_parts;
|
||||
};
|
||||
@ -217,6 +215,7 @@ struct lpc32xx_nand_host {
|
||||
struct nand_chip nand_chip;
|
||||
struct lpc32xx_slc_platform_data *pdata;
|
||||
struct clk *clk;
|
||||
struct gpio_desc *wp_gpio;
|
||||
void __iomem *io_base;
|
||||
struct lpc32xx_nand_cfg_slc *ncfg;
|
||||
|
||||
@ -309,8 +308,8 @@ static int lpc32xx_nand_device_ready(struct nand_chip *chip)
|
||||
*/
|
||||
static void lpc32xx_wp_enable(struct lpc32xx_nand_host *host)
|
||||
{
|
||||
if (gpio_is_valid(host->ncfg->wp_gpio))
|
||||
gpio_set_value(host->ncfg->wp_gpio, 0);
|
||||
if (host->wp_gpio)
|
||||
gpiod_set_value_cansleep(host->wp_gpio, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -318,8 +317,8 @@ static void lpc32xx_wp_enable(struct lpc32xx_nand_host *host)
|
||||
*/
|
||||
static void lpc32xx_wp_disable(struct lpc32xx_nand_host *host)
|
||||
{
|
||||
if (gpio_is_valid(host->ncfg->wp_gpio))
|
||||
gpio_set_value(host->ncfg->wp_gpio, 1);
|
||||
if (host->wp_gpio)
|
||||
gpiod_set_value_cansleep(host->wp_gpio, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -764,8 +763,6 @@ static struct lpc32xx_nand_cfg_slc *lpc32xx_parse_dt(struct device *dev)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ncfg->wp_gpio = of_get_named_gpio(np, "gpios", 0);
|
||||
|
||||
return ncfg;
|
||||
}
|
||||
|
||||
@ -852,14 +849,18 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
|
||||
"Missing or bad NAND config from device tree\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
if (host->ncfg->wp_gpio == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
if (gpio_is_valid(host->ncfg->wp_gpio) && devm_gpio_request(&pdev->dev,
|
||||
host->ncfg->wp_gpio, "NAND WP")) {
|
||||
dev_err(&pdev->dev, "GPIO not available\n");
|
||||
return -EBUSY;
|
||||
|
||||
/* Start with WP disabled, if available */
|
||||
host->wp_gpio = gpiod_get_optional(&pdev->dev, NULL, GPIOD_OUT_LOW);
|
||||
res = PTR_ERR_OR_ZERO(host->wp_gpio);
|
||||
if (res) {
|
||||
if (res != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev, "WP GPIO is not available: %d\n",
|
||||
res);
|
||||
return res;
|
||||
}
|
||||
lpc32xx_wp_disable(host);
|
||||
|
||||
gpiod_set_consumer_name(host->wp_gpio, "NAND WP");
|
||||
|
||||
host->pdata = dev_get_platdata(&pdev->dev);
|
||||
|
||||
@ -968,7 +969,6 @@ static int lpc32xx_nand_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int lpc32xx_nand_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
|
||||
@ -1007,11 +1007,6 @@ static int lpc32xx_nand_suspend(struct platform_device *pdev, pm_message_t pm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#define lpc32xx_nand_resume NULL
|
||||
#define lpc32xx_nand_suspend NULL
|
||||
#endif
|
||||
|
||||
static const struct of_device_id lpc32xx_nand_match[] = {
|
||||
{ .compatible = "nxp,lpc3220-slc" },
|
||||
{ /* sentinel */ },
|
||||
@ -1021,8 +1016,8 @@ MODULE_DEVICE_TABLE(of, lpc32xx_nand_match);
|
||||
static struct platform_driver lpc32xx_nand_driver = {
|
||||
.probe = lpc32xx_nand_probe,
|
||||
.remove = lpc32xx_nand_remove,
|
||||
.resume = lpc32xx_nand_resume,
|
||||
.suspend = lpc32xx_nand_suspend,
|
||||
.resume = pm_ptr(lpc32xx_nand_resume),
|
||||
.suspend = pm_ptr(lpc32xx_nand_suspend),
|
||||
.driver = {
|
||||
.name = LPC32XX_MODNAME,
|
||||
.of_match_table = lpc32xx_nand_match,
|
||||
|
@ -114,6 +114,7 @@
|
||||
#define GENCONF_SOC_DEVICE_MUX_ECC_CLK_RST BIT(20)
|
||||
#define GENCONF_SOC_DEVICE_MUX_ECC_CORE_RST BIT(21)
|
||||
#define GENCONF_SOC_DEVICE_MUX_NFC_INT_EN BIT(25)
|
||||
#define GENCONF_SOC_DEVICE_MUX_NFC_DEVBUS_ARB_EN BIT(27)
|
||||
#define GENCONF_CLK_GATING_CTRL 0x220
|
||||
#define GENCONF_CLK_GATING_CTRL_ND_GATE BIT(2)
|
||||
#define GENCONF_ND_CLK_CTRL 0x700
|
||||
@ -2880,7 +2881,8 @@ static int marvell_nfc_init(struct marvell_nfc *nfc)
|
||||
GENCONF_SOC_DEVICE_MUX_NFC_EN |
|
||||
GENCONF_SOC_DEVICE_MUX_ECC_CLK_RST |
|
||||
GENCONF_SOC_DEVICE_MUX_ECC_CORE_RST |
|
||||
GENCONF_SOC_DEVICE_MUX_NFC_INT_EN);
|
||||
GENCONF_SOC_DEVICE_MUX_NFC_INT_EN |
|
||||
GENCONF_SOC_DEVICE_MUX_NFC_DEVBUS_ARB_EN);
|
||||
|
||||
regmap_update_bits(sysctrl_base, GENCONF_CLK_GATING_CTRL,
|
||||
GENCONF_CLK_GATING_CTRL_ND_GATE,
|
||||
|
@ -663,7 +663,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
|
||||
}
|
||||
|
||||
prv->irq = irq_of_parse_and_map(dn, 0);
|
||||
if (prv->irq == NO_IRQ) {
|
||||
if (!prv->irq) {
|
||||
dev_err(dev, "Error mapping IRQ!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -74,9 +74,75 @@ static int w25m02gv_select_target(struct spinand_device *spinand,
|
||||
return spi_mem_exec_op(spinand->spimem, &op);
|
||||
}
|
||||
|
||||
static int w25n02kv_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *region)
|
||||
{
|
||||
if (section > 3)
|
||||
return -ERANGE;
|
||||
|
||||
region->offset = 64 + (16 * section);
|
||||
region->length = 13;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int w25n02kv_ooblayout_free(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *region)
|
||||
{
|
||||
if (section > 3)
|
||||
return -ERANGE;
|
||||
|
||||
region->offset = (16 * section) + 2;
|
||||
region->length = 14;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct mtd_ooblayout_ops w25n02kv_ooblayout = {
|
||||
.ecc = w25n02kv_ooblayout_ecc,
|
||||
.free = w25n02kv_ooblayout_free,
|
||||
};
|
||||
|
||||
static int w25n02kv_ecc_get_status(struct spinand_device *spinand,
|
||||
u8 status)
|
||||
{
|
||||
struct nand_device *nand = spinand_to_nand(spinand);
|
||||
u8 mbf = 0;
|
||||
struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf);
|
||||
|
||||
switch (status & STATUS_ECC_MASK) {
|
||||
case STATUS_ECC_NO_BITFLIPS:
|
||||
return 0;
|
||||
|
||||
case STATUS_ECC_UNCOR_ERROR:
|
||||
return -EBADMSG;
|
||||
|
||||
case STATUS_ECC_HAS_BITFLIPS:
|
||||
/*
|
||||
* Let's try to retrieve the real maximum number of bitflips
|
||||
* in order to avoid forcing the wear-leveling layer to move
|
||||
* data around if it's not necessary.
|
||||
*/
|
||||
if (spi_mem_exec_op(spinand->spimem, &op))
|
||||
return nanddev_get_ecc_conf(nand)->strength;
|
||||
|
||||
mbf >>= 4;
|
||||
|
||||
if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf))
|
||||
return nanddev_get_ecc_conf(nand)->strength;
|
||||
|
||||
return mbf;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct spinand_info winbond_spinand_table[] = {
|
||||
SPINAND_INFO("W25M02GV",
|
||||
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab),
|
||||
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab, 0x21),
|
||||
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2),
|
||||
NAND_ECCREQ(1, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
@ -86,7 +152,7 @@ static const struct spinand_info winbond_spinand_table[] = {
|
||||
SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
|
||||
SPINAND_SELECT_TARGET(w25m02gv_select_target)),
|
||||
SPINAND_INFO("W25N01GV",
|
||||
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa),
|
||||
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x21),
|
||||
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
|
||||
NAND_ECCREQ(1, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
@ -94,6 +160,15 @@ static const struct spinand_info winbond_spinand_table[] = {
|
||||
&update_cache_variants),
|
||||
0,
|
||||
SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
|
||||
SPINAND_INFO("W25N02KV",
|
||||
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x22),
|
||||
NAND_MEMORG(1, 2048, 128, 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(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)),
|
||||
};
|
||||
|
||||
static int winbond_spinand_init(struct spinand_device *spinand)
|
||||
|
@ -999,7 +999,6 @@ static inline bool nanddev_io_iter_end(struct nand_device *nand,
|
||||
|
||||
bool nanddev_isbad(struct nand_device *nand, const struct nand_pos *pos);
|
||||
bool nanddev_isreserved(struct nand_device *nand, const struct nand_pos *pos);
|
||||
int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos);
|
||||
int nanddev_markbad(struct nand_device *nand, const struct nand_pos *pos);
|
||||
|
||||
/* ECC related functions */
|
||||
|
Loading…
Reference in New Issue
Block a user