Commit 0bfad3b3 authored by Christophe Kerello's avatar Christophe Kerello Committed by Miquel Raynal
Browse files

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: default avatarChristophe Kerello <christophe.kerello@foss.st.com>
Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20240219140505.85794-4-christophe.kerello@foss.st.com
parent a9ae475c
Loading
Loading
Loading
Loading
+45 −9
Original line number Diff line number Diff line
@@ -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;
@@ -1809,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;
		}
@@ -1915,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);
	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)
@@ -1936,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;
@@ -2092,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;

@@ -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,
			 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);