mtd: rawnand: stm32_fmc2: add MP25 support
FMC2 IP supports up to 4 chip select. On MP1 SoC, only 2 of them are available when on MP25 SoC, the 4 chip select are available. Let's use a platform data structure for parameters that will differ. 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/20240219140505.85794-4-christophe.kerello@foss.st.com
This commit is contained in:
parent
a9ae475cc6
commit
0bfad3b356
@ -16,6 +16,7 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mtd/rawnand.h>
|
#include <linux/mtd/rawnand.h>
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
#include <linux/pinctrl/consumer.h>
|
#include <linux/pinctrl/consumer.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/regmap.h>
|
#include <linux/regmap.h>
|
||||||
@ -37,7 +38,7 @@
|
|||||||
#define FMC2_MAX_SG 16
|
#define FMC2_MAX_SG 16
|
||||||
|
|
||||||
/* Max chip enable */
|
/* Max chip enable */
|
||||||
#define FMC2_MAX_CE 2
|
#define FMC2_MAX_CE 4
|
||||||
|
|
||||||
/* Max ECC buffer length */
|
/* Max ECC buffer length */
|
||||||
#define FMC2_MAX_ECC_BUF_LEN (FMC2_BCHDSRS_LEN * FMC2_MAX_SG)
|
#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);
|
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 stm32_fmc2_nfc {
|
||||||
struct nand_controller base;
|
struct nand_controller base;
|
||||||
struct stm32_fmc2_nand nand;
|
struct stm32_fmc2_nand nand;
|
||||||
@ -256,6 +264,7 @@ struct stm32_fmc2_nfc {
|
|||||||
phys_addr_t data_phys_addr[FMC2_MAX_CE];
|
phys_addr_t data_phys_addr[FMC2_MAX_CE];
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
u8 irq_state;
|
u8 irq_state;
|
||||||
|
const struct stm32_fmc2_nfc_data *data;
|
||||||
|
|
||||||
struct dma_chan *dma_tx_ch;
|
struct dma_chan *dma_tx_ch;
|
||||||
struct dma_chan *dma_rx_ch;
|
struct dma_chan *dma_rx_ch;
|
||||||
@ -1809,7 +1818,7 @@ static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cs >= FMC2_MAX_CE) {
|
if (cs >= nfc->data->max_ncs) {
|
||||||
dev_err(nfc->dev, "invalid reg value: %d\n", cs);
|
dev_err(nfc->dev, "invalid reg value: %d\n", cs);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -1915,9 +1924,17 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
|
|||||||
nand_controller_init(&nfc->base);
|
nand_controller_init(&nfc->base);
|
||||||
nfc->base.ops = &stm32_fmc2_nfc_controller_ops;
|
nfc->base.ops = &stm32_fmc2_nfc_controller_ops;
|
||||||
|
|
||||||
ret = stm32_fmc2_nfc_set_cdev(nfc);
|
nfc->data = of_device_get_match_data(dev);
|
||||||
if (ret)
|
if (!nfc->data)
|
||||||
return ret;
|
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);
|
ret = stm32_fmc2_nfc_parse_dt(nfc);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -1936,7 +1953,7 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
|
|||||||
if (nfc->dev == nfc->cdev)
|
if (nfc->dev == nfc->cdev)
|
||||||
start_region = 1;
|
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) {
|
chip_cs++, mem_region += 3) {
|
||||||
if (!(nfc->cs_assigned & BIT(chip_cs)))
|
if (!(nfc->cs_assigned & BIT(chip_cs)))
|
||||||
continue;
|
continue;
|
||||||
@ -2092,7 +2109,7 @@ static int __maybe_unused stm32_fmc2_nfc_resume(struct device *dev)
|
|||||||
|
|
||||||
stm32_fmc2_nfc_wp_disable(nand);
|
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)))
|
if (!(nfc->cs_assigned & BIT(chip_cs)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -2105,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,
|
static SIMPLE_DEV_PM_OPS(stm32_fmc2_nfc_pm_ops, stm32_fmc2_nfc_suspend,
|
||||||
stm32_fmc2_nfc_resume);
|
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[] = {
|
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);
|
MODULE_DEVICE_TABLE(of, stm32_fmc2_nfc_match);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user