mtd: rawnand: stm32_fmc2: Add NAND Write Protect support
This patch adds the support of the WP# signal. WP will be disabled in probe/resume callbacks and will be enabled in remove/suspend callbacks. Signed-off-by: Christophe Kerello <christophe.kerello@foss.st.com> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Link: https://lore.kernel.org/linux-mtd/20220217144755.270679-3-christophe.kerello@foss.st.com
This commit is contained in:
parent
cb57fae479
commit
ffb16c1c42
@ -9,6 +9,7 @@
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
@ -231,6 +232,7 @@ struct stm32_fmc2_timings {
|
||||
|
||||
struct stm32_fmc2_nand {
|
||||
struct nand_chip chip;
|
||||
struct gpio_desc *wp_gpio;
|
||||
struct stm32_fmc2_timings timings;
|
||||
int ncs;
|
||||
int cs_used[FMC2_MAX_CE];
|
||||
@ -1747,6 +1749,18 @@ static const struct nand_controller_ops stm32_fmc2_nfc_controller_ops = {
|
||||
.setup_interface = stm32_fmc2_nfc_setup_interface,
|
||||
};
|
||||
|
||||
static void stm32_fmc2_nfc_wp_enable(struct stm32_fmc2_nand *nand)
|
||||
{
|
||||
if (nand->wp_gpio)
|
||||
gpiod_set_value(nand->wp_gpio, 1);
|
||||
}
|
||||
|
||||
static void stm32_fmc2_nfc_wp_disable(struct stm32_fmc2_nand *nand)
|
||||
{
|
||||
if (nand->wp_gpio)
|
||||
gpiod_set_value(nand->wp_gpio, 0);
|
||||
}
|
||||
|
||||
static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc,
|
||||
struct device_node *dn)
|
||||
{
|
||||
@ -1785,6 +1799,18 @@ static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc,
|
||||
nand->cs_used[i] = cs;
|
||||
}
|
||||
|
||||
nand->wp_gpio = devm_gpiod_get_from_of_node(nfc->dev, dn,
|
||||
"wp-gpios", 0,
|
||||
GPIOD_OUT_HIGH, "wp");
|
||||
if (IS_ERR(nand->wp_gpio)) {
|
||||
ret = PTR_ERR(nand->wp_gpio);
|
||||
if (ret != -ENOENT)
|
||||
return dev_err_probe(nfc->dev, ret,
|
||||
"failed to request WP GPIO\n");
|
||||
|
||||
nand->wp_gpio = NULL;
|
||||
}
|
||||
|
||||
nand_set_flash_node(&nand->chip, dn);
|
||||
|
||||
return 0;
|
||||
@ -1956,10 +1982,12 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
|
||||
chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE |
|
||||
NAND_USES_DMA;
|
||||
|
||||
stm32_fmc2_nfc_wp_disable(nand);
|
||||
|
||||
/* Scan to find existence of the device */
|
||||
ret = nand_scan(chip, nand->ncs);
|
||||
if (ret)
|
||||
goto err_release_dma;
|
||||
goto err_wp_enable;
|
||||
|
||||
ret = mtd_device_register(mtd, NULL, 0);
|
||||
if (ret)
|
||||
@ -1972,6 +2000,9 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
|
||||
err_nand_cleanup:
|
||||
nand_cleanup(chip);
|
||||
|
||||
err_wp_enable:
|
||||
stm32_fmc2_nfc_wp_enable(nand);
|
||||
|
||||
err_release_dma:
|
||||
if (nfc->dma_ecc_ch)
|
||||
dma_release_channel(nfc->dma_ecc_ch);
|
||||
@ -2012,15 +2043,20 @@ static int stm32_fmc2_nfc_remove(struct platform_device *pdev)
|
||||
|
||||
clk_disable_unprepare(nfc->clk);
|
||||
|
||||
stm32_fmc2_nfc_wp_enable(nand);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused stm32_fmc2_nfc_suspend(struct device *dev)
|
||||
{
|
||||
struct stm32_fmc2_nfc *nfc = dev_get_drvdata(dev);
|
||||
struct stm32_fmc2_nand *nand = &nfc->nand;
|
||||
|
||||
clk_disable_unprepare(nfc->clk);
|
||||
|
||||
stm32_fmc2_nfc_wp_enable(nand);
|
||||
|
||||
pinctrl_pm_select_sleep_state(dev);
|
||||
|
||||
return 0;
|
||||
@ -2042,6 +2078,8 @@ static int __maybe_unused stm32_fmc2_nfc_resume(struct device *dev)
|
||||
|
||||
stm32_fmc2_nfc_init(nfc);
|
||||
|
||||
stm32_fmc2_nfc_wp_disable(nand);
|
||||
|
||||
for (chip_cs = 0; chip_cs < FMC2_MAX_CE; chip_cs++) {
|
||||
if (!(nfc->cs_assigned & BIT(chip_cs)))
|
||||
continue;
|
||||
|
Loading…
Reference in New Issue
Block a user