diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-07 13:11:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-07 13:11:27 +0000 |
commit | 34996e42f82bfd60bc2c191e5cae3c6ab233ec6c (patch) | |
tree | 62db60558cbf089714b48daeabca82bf2b20b20e /drivers/mtd/nand/raw/stm32_fmc2_nand.c | |
parent | Adding debian version 6.8.12-1. (diff) | |
download | linux-34996e42f82bfd60bc2c191e5cae3c6ab233ec6c.tar.xz linux-34996e42f82bfd60bc2c191e5cae3c6ab233ec6c.zip |
Merging upstream version 6.9.7.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/mtd/nand/raw/stm32_fmc2_nand.c')
-rw-r--r-- | drivers/mtd/nand/raw/stm32_fmc2_nand.c | 83 |
1 files changed, 69 insertions, 14 deletions
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c index 88811139aa..264556939a 100644 --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c @@ -16,6 +16,7 @@ #include <linux/module.h> #include <linux/mtd/rawnand.h> #include <linux/of_address.h> +#include <linux/of_device.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> #include <linux/regmap.h> @@ -37,7 +38,7 @@ #define FMC2_MAX_SG 16 /* Max chip enable */ -#define FMC2_MAX_CE 2 +#define FMC2_MAX_CE 4 /* Max ECC buffer length */ #define FMC2_MAX_ECC_BUF_LEN (FMC2_BCHDSRS_LEN * FMC2_MAX_SG) @@ -243,6 +244,13 @@ static inline struct stm32_fmc2_nand *to_fmc2_nand(struct nand_chip *chip) return container_of(chip, struct stm32_fmc2_nand, chip); } +struct stm32_fmc2_nfc; + +struct stm32_fmc2_nfc_data { + int max_ncs; + int (*set_cdev)(struct stm32_fmc2_nfc *nfc); +}; + struct stm32_fmc2_nfc { struct nand_controller base; struct stm32_fmc2_nand nand; @@ -256,6 +264,7 @@ struct stm32_fmc2_nfc { phys_addr_t data_phys_addr[FMC2_MAX_CE]; struct clk *clk; u8 irq_state; + const struct stm32_fmc2_nfc_data *data; struct dma_chan *dma_tx_ch; struct dma_chan *dma_rx_ch; @@ -264,6 +273,8 @@ struct stm32_fmc2_nfc { struct sg_table dma_ecc_sg; u8 *ecc_buf; int dma_ecc_len; + u32 tx_dma_max_burst; + u32 rx_dma_max_burst; struct completion complete; struct completion dma_data_complete; @@ -347,20 +358,26 @@ static int stm32_fmc2_nfc_select_chip(struct nand_chip *chip, int chipnr) stm32_fmc2_nfc_setup(chip); stm32_fmc2_nfc_timings_init(chip); - if (nfc->dma_tx_ch && nfc->dma_rx_ch) { + if (nfc->dma_tx_ch) { memset(&dma_cfg, 0, sizeof(dma_cfg)); - dma_cfg.src_addr = nfc->data_phys_addr[nfc->cs_sel]; dma_cfg.dst_addr = nfc->data_phys_addr[nfc->cs_sel]; - dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - dma_cfg.src_maxburst = 32; - dma_cfg.dst_maxburst = 32; + dma_cfg.dst_maxburst = nfc->tx_dma_max_burst / + dma_cfg.dst_addr_width; ret = dmaengine_slave_config(nfc->dma_tx_ch, &dma_cfg); if (ret) { dev_err(nfc->dev, "tx DMA engine slave config failed\n"); return ret; } + } + + if (nfc->dma_rx_ch) { + memset(&dma_cfg, 0, sizeof(dma_cfg)); + dma_cfg.src_addr = nfc->data_phys_addr[nfc->cs_sel]; + dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + dma_cfg.src_maxburst = nfc->rx_dma_max_burst / + dma_cfg.src_addr_width; ret = dmaengine_slave_config(nfc->dma_rx_ch, &dma_cfg); if (ret) { @@ -1545,6 +1562,7 @@ static int stm32_fmc2_nfc_setup_interface(struct nand_chip *chip, int chipnr, static int stm32_fmc2_nfc_dma_setup(struct stm32_fmc2_nfc *nfc) { + struct dma_slave_caps caps; int ret = 0; nfc->dma_tx_ch = dma_request_chan(nfc->dev, "tx"); @@ -1557,6 +1575,11 @@ static int stm32_fmc2_nfc_dma_setup(struct stm32_fmc2_nfc *nfc) goto err_dma; } + ret = dma_get_slave_caps(nfc->dma_tx_ch, &caps); + if (ret) + return ret; + nfc->tx_dma_max_burst = caps.max_burst; + nfc->dma_rx_ch = dma_request_chan(nfc->dev, "rx"); if (IS_ERR(nfc->dma_rx_ch)) { ret = PTR_ERR(nfc->dma_rx_ch); @@ -1567,6 +1590,11 @@ static int stm32_fmc2_nfc_dma_setup(struct stm32_fmc2_nfc *nfc) goto err_dma; } + ret = dma_get_slave_caps(nfc->dma_rx_ch, &caps); + if (ret) + return ret; + nfc->rx_dma_max_burst = caps.max_burst; + nfc->dma_ecc_ch = dma_request_chan(nfc->dev, "ecc"); if (IS_ERR(nfc->dma_ecc_ch)) { ret = PTR_ERR(nfc->dma_ecc_ch); @@ -1790,7 +1818,7 @@ static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc, return ret; } - if (cs >= FMC2_MAX_CE) { + if (cs >= nfc->data->max_ncs) { dev_err(nfc->dev, "invalid reg value: %d\n", cs); return -EINVAL; } @@ -1896,9 +1924,17 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev) nand_controller_init(&nfc->base); nfc->base.ops = &stm32_fmc2_nfc_controller_ops; - ret = stm32_fmc2_nfc_set_cdev(nfc); - if (ret) - return ret; + nfc->data = of_device_get_match_data(dev); + if (!nfc->data) + return -EINVAL; + + if (nfc->data->set_cdev) { + ret = nfc->data->set_cdev(nfc); + if (ret) + return ret; + } else { + nfc->cdev = dev->parent; + } ret = stm32_fmc2_nfc_parse_dt(nfc); if (ret) @@ -1917,7 +1953,7 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev) if (nfc->dev == nfc->cdev) start_region = 1; - for (chip_cs = 0, mem_region = start_region; chip_cs < FMC2_MAX_CE; + for (chip_cs = 0, mem_region = start_region; chip_cs < nfc->data->max_ncs; chip_cs++, mem_region += 3) { if (!(nfc->cs_assigned & BIT(chip_cs))) continue; @@ -2073,7 +2109,7 @@ static int __maybe_unused stm32_fmc2_nfc_resume(struct device *dev) stm32_fmc2_nfc_wp_disable(nand); - for (chip_cs = 0; chip_cs < FMC2_MAX_CE; chip_cs++) { + for (chip_cs = 0; chip_cs < nfc->data->max_ncs; chip_cs++) { if (!(nfc->cs_assigned & BIT(chip_cs))) continue; @@ -2086,9 +2122,28 @@ static int __maybe_unused stm32_fmc2_nfc_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(stm32_fmc2_nfc_pm_ops, stm32_fmc2_nfc_suspend, stm32_fmc2_nfc_resume); +static const struct stm32_fmc2_nfc_data stm32_fmc2_nfc_mp1_data = { + .max_ncs = 2, + .set_cdev = stm32_fmc2_nfc_set_cdev, +}; + +static const struct stm32_fmc2_nfc_data stm32_fmc2_nfc_mp25_data = { + .max_ncs = 4, +}; + static const struct of_device_id stm32_fmc2_nfc_match[] = { - {.compatible = "st,stm32mp15-fmc2"}, - {.compatible = "st,stm32mp1-fmc2-nfc"}, + { + .compatible = "st,stm32mp15-fmc2", + .data = &stm32_fmc2_nfc_mp1_data, + }, + { + .compatible = "st,stm32mp1-fmc2-nfc", + .data = &stm32_fmc2_nfc_mp1_data, + }, + { + .compatible = "st,stm32mp25-fmc2-nfc", + .data = &stm32_fmc2_nfc_mp25_data, + }, {} }; MODULE_DEVICE_TABLE(of, stm32_fmc2_nfc_match); |