linux-mtd.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: Christophe Kerello <christophe.kerello@st.com>
To: <miquel.raynal@bootlin.com>, <richard@nod.at>, <vigneshr@ti.com>,
	<lee.jones@linaro.org>, <robh+dt@kernel.org>,
	<mark.rutland@arm.com>, <tony@atomide.com>
Cc: marex@denx.de, Christophe Kerello <christophe.kerello@st.com>,
	linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org,
	linux-stm32@st-md-mailman.stormreply.com
Subject: [11/12] mtd: rawnand: stm32_fmc2: use stm32_fmc2 structure in nfc controller
Date: Mon, 23 Mar 2020 15:58:51 +0100	[thread overview]
Message-ID: <1584975532-8038-12-git-send-email-christophe.kerello@st.com> (raw)
In-Reply-To: <1584975532-8038-1-git-send-email-christophe.kerello@st.com>

This patch moves common used resources (registers base, clocks, ...)
in stm32_fmc2 structure.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
 drivers/mtd/nand/raw/Kconfig           |   1 +
 drivers/mtd/nand/raw/stm32_fmc2_nand.c | 218 ++++++++++++++++++++++-----------
 2 files changed, 150 insertions(+), 69 deletions(-)

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 12b715a..ad7d887 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -421,6 +421,7 @@ config MTD_NAND_STM32_FMC2
 	depends on MACH_STM32MP157 || COMPILE_TEST
 	select REGMAP
 	select REGMAP_MMIO
+	select MFD_STM32_FMC2
 	help
 	  Enables support for NAND Flash chips on SoCs containing the FMC2
 	  NAND controller. This controller is found on STM32MP SoCs.
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index bc16614..1dc568f 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -97,14 +97,12 @@ static inline struct stm32_fmc2_nand *to_fmc2_nand(struct nand_chip *chip)
 struct stm32_fmc2_nfc {
 	struct nand_controller base;
 	struct stm32_fmc2_nand nand;
+	struct stm32_fmc2 *fmc2;
 	struct device *dev;
-	struct regmap *regmap;
 	void __iomem *data_base[FMC2_MAX_CE];
 	void __iomem *cmd_base[FMC2_MAX_CE];
 	void __iomem *addr_base[FMC2_MAX_CE];
-	phys_addr_t io_phys_addr;
 	phys_addr_t data_phys_addr[FMC2_MAX_CE];
-	struct clk *clk;
 	u8 irq_state;
 
 	struct dma_chan *dma_tx_ch;
@@ -133,10 +131,11 @@ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
 	struct stm32_fmc2_timings *timings = &nand->timings;
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	u32 pmem, patt;
 
 	/* Set tclr/tar timings */
-	regmap_update_bits(nfc->regmap, FMC2_PCR,
+	regmap_update_bits(fmc2->regmap, FMC2_PCR,
 			   FMC2_PCR_TCLR | FMC2_PCR_TAR,
 			   FIELD_PREP(FMC2_PCR_TCLR, timings->tclr) |
 			   FIELD_PREP(FMC2_PCR_TAR, timings->tar));
@@ -146,19 +145,20 @@ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
 	pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
 	pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
 	pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
-	regmap_write(nfc->regmap, FMC2_PMEM, pmem);
+	regmap_write(fmc2->regmap, FMC2_PMEM, pmem);
 
 	/* Set tset/twait/thold/thiz timings in attribut bank */
 	patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
 	patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
 	patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
 	patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
-	regmap_write(nfc->regmap, FMC2_PATT, patt);
+	regmap_write(fmc2->regmap, FMC2_PATT, patt);
 }
 
 static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	u32 pcr = 0, pcr_mask;
 
 	/* Configure ECC algorithm (default configuration is Hamming) */
@@ -180,13 +180,14 @@ static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
 	pcr_mask |= FMC2_PCR_ECCSS;
 	pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
 
-	regmap_update_bits(nfc->regmap, FMC2_PCR, pcr_mask, pcr);
+	regmap_update_bits(fmc2->regmap, FMC2_PCR, pcr_mask, pcr);
 }
 
 static int stm32_fmc2_nfc_select_chip(struct nand_chip *chip, int chipnr)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	struct dma_slave_config dma_cfg;
 	int ret;
 
@@ -225,7 +226,7 @@ static int stm32_fmc2_nfc_select_chip(struct nand_chip *chip, int chipnr)
 		 * BCH4/BCH8: we read BCHDSRSx registers
 		 */
 		memset(&dma_cfg, 0, sizeof(dma_cfg));
-		dma_cfg.src_addr = nfc->io_phys_addr;
+		dma_cfg.src_addr = fmc2->reg_phys_addr;
 		dma_cfg.src_addr += chip->ecc.strength == FMC2_ECC_HAM ?
 				    FMC2_HECCR : FMC2_BCHDSR0;
 		dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -246,55 +247,68 @@ static int stm32_fmc2_nfc_select_chip(struct nand_chip *chip, int chipnr)
 
 static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc, bool set)
 {
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	u32 pcr;
 
 	pcr = set ? FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16) :
 		    FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_8);
 
-	regmap_update_bits(nfc->regmap, FMC2_PCR, FMC2_PCR_PWID, pcr);
+	regmap_update_bits(fmc2->regmap, FMC2_PCR, FMC2_PCR_PWID, pcr);
 }
 
 static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
 {
-	regmap_update_bits(nfc->regmap, FMC2_PCR, FMC2_PCR_ECCEN,
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
+
+	regmap_update_bits(fmc2->regmap, FMC2_PCR, FMC2_PCR_ECCEN,
 			   enable ? FMC2_PCR_ECCEN : 0);
 }
 
 static void stm32_fmc2_nfc_enable_seq_irq(struct stm32_fmc2_nfc *nfc)
 {
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
+
 	nfc->irq_state = FMC2_IRQ_SEQ;
 
-	regmap_update_bits(nfc->regmap, FMC2_CSQIER,
+	regmap_update_bits(fmc2->regmap, FMC2_CSQIER,
 			   FMC2_CSQIER_TCIE, FMC2_CSQIER_TCIE);
 }
 
 static void stm32_fmc2_nfc_disable_seq_irq(struct stm32_fmc2_nfc *nfc)
 {
-	regmap_update_bits(nfc->regmap, FMC2_CSQIER, FMC2_CSQIER_TCIE, 0);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
+
+	regmap_update_bits(fmc2->regmap, FMC2_CSQIER, FMC2_CSQIER_TCIE, 0);
 
 	nfc->irq_state = FMC2_IRQ_UNKNOWN;
 }
 
 static void stm32_fmc2_nfc_clear_seq_irq(struct stm32_fmc2_nfc *nfc)
 {
-	regmap_write(nfc->regmap, FMC2_CSQICR, FMC2_CSQICR_CLEAR_IRQ);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
+
+	regmap_write(fmc2->regmap, FMC2_CSQICR, FMC2_CSQICR_CLEAR_IRQ);
 }
 
 static void stm32_fmc2_nfc_enable_bch_irq(struct stm32_fmc2_nfc *nfc, int mode)
 {
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
+
 	nfc->irq_state = FMC2_IRQ_BCH;
 
 	if (mode == NAND_ECC_WRITE)
-		regmap_update_bits(nfc->regmap, FMC2_BCHIER,
+		regmap_update_bits(fmc2->regmap, FMC2_BCHIER,
 				   FMC2_BCHIER_EPBRIE, FMC2_BCHIER_EPBRIE);
 	else
-		regmap_update_bits(nfc->regmap, FMC2_BCHIER,
+		regmap_update_bits(fmc2->regmap, FMC2_BCHIER,
 				   FMC2_BCHIER_DERIE, FMC2_BCHIER_DERIE);
 }
 
 static void stm32_fmc2_nfc_disable_bch_irq(struct stm32_fmc2_nfc *nfc)
 {
-	regmap_update_bits(nfc->regmap, FMC2_BCHIER,
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
+
+	regmap_update_bits(fmc2->regmap, FMC2_BCHIER,
 			   FMC2_BCHIER_DERIE | FMC2_BCHIER_EPBRIE, 0);
 
 	nfc->irq_state = FMC2_IRQ_UNKNOWN;
@@ -302,7 +316,9 @@ static void stm32_fmc2_nfc_disable_bch_irq(struct stm32_fmc2_nfc *nfc)
 
 static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
 {
-	regmap_write(nfc->regmap, FMC2_BCHICR, FMC2_BCHICR_CLEAR_IRQ);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
+
+	regmap_write(fmc2->regmap, FMC2_BCHICR, FMC2_BCHICR_CLEAR_IRQ);
 }
 
 /*
@@ -312,11 +328,12 @@ static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
 static void stm32_fmc2_nfc_hwctl(struct nand_chip *chip, int mode)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 
 	stm32_fmc2_nfc_set_ecc(nfc, false);
 
 	if (chip->ecc.strength != FMC2_ECC_HAM) {
-		regmap_update_bits(nfc->regmap, FMC2_PCR, FMC2_PCR_WEN,
+		regmap_update_bits(fmc2->regmap, FMC2_PCR, FMC2_PCR_WEN,
 				   mode == NAND_ECC_WRITE ? FMC2_PCR_WEN : 0);
 
 		reinit_completion(&nfc->complete);
@@ -343,10 +360,11 @@ static int stm32_fmc2_nfc_ham_calculate(struct nand_chip *chip, const u8 *data,
 					u8 *ecc)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	u32 sr, heccr;
 	int ret;
 
-	ret = regmap_read_poll_timeout(nfc->regmap, FMC2_SR, sr,
+	ret = regmap_read_poll_timeout(fmc2->regmap, FMC2_SR, sr,
 				       sr & FMC2_SR_NWRF, 1,
 				       1000 * FMC2_TIMEOUT_MS);
 	if (ret) {
@@ -354,7 +372,7 @@ static int stm32_fmc2_nfc_ham_calculate(struct nand_chip *chip, const u8 *data,
 		return ret;
 	}
 
-	regmap_read(nfc->regmap, FMC2_HECCR, &heccr);
+	regmap_read(fmc2->regmap, FMC2_HECCR, &heccr);
 	stm32_fmc2_nfc_ham_set_ecc(heccr, ecc);
 	stm32_fmc2_nfc_set_ecc(nfc, false);
 
@@ -422,6 +440,7 @@ static int stm32_fmc2_nfc_bch_calculate(struct nand_chip *chip, const u8 *data,
 					u8 *ecc)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	u32 bchpbr;
 
 	/* Wait until the BCH code is ready */
@@ -433,13 +452,13 @@ static int stm32_fmc2_nfc_bch_calculate(struct nand_chip *chip, const u8 *data,
 	}
 
 	/* Read parity bits */
-	regmap_read(nfc->regmap, FMC2_BCHPBR1, &bchpbr);
+	regmap_read(fmc2->regmap, FMC2_BCHPBR1, &bchpbr);
 	ecc[0] = bchpbr;
 	ecc[1] = bchpbr >> 8;
 	ecc[2] = bchpbr >> 16;
 	ecc[3] = bchpbr >> 24;
 
-	regmap_read(nfc->regmap, FMC2_BCHPBR2, &bchpbr);
+	regmap_read(fmc2->regmap, FMC2_BCHPBR2, &bchpbr);
 	ecc[4] = bchpbr;
 	ecc[5] = bchpbr >> 8;
 	ecc[6] = bchpbr >> 16;
@@ -447,13 +466,13 @@ static int stm32_fmc2_nfc_bch_calculate(struct nand_chip *chip, const u8 *data,
 	if (chip->ecc.strength == FMC2_ECC_BCH8) {
 		ecc[7] = bchpbr >> 24;
 
-		regmap_read(nfc->regmap, FMC2_BCHPBR3, &bchpbr);
+		regmap_read(fmc2->regmap, FMC2_BCHPBR3, &bchpbr);
 		ecc[8] = bchpbr;
 		ecc[9] = bchpbr >> 8;
 		ecc[10] = bchpbr >> 16;
 		ecc[11] = bchpbr >> 24;
 
-		regmap_read(nfc->regmap, FMC2_BCHPBR4, &bchpbr);
+		regmap_read(fmc2->regmap, FMC2_BCHPBR4, &bchpbr);
 		ecc[12] = bchpbr;
 	}
 
@@ -505,6 +524,7 @@ static int stm32_fmc2_nfc_bch_correct(struct nand_chip *chip, u8 *dat,
 				      u8 *read_ecc, u8 *calc_ecc)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	u32 ecc_sta[5];
 
 	/* Wait until the decoding error is ready */
@@ -515,11 +535,11 @@ static int stm32_fmc2_nfc_bch_correct(struct nand_chip *chip, u8 *dat,
 		return -ETIMEDOUT;
 	}
 
-	regmap_read(nfc->regmap, FMC2_BCHDSR0, &ecc_sta[0]);
-	regmap_read(nfc->regmap, FMC2_BCHDSR1, &ecc_sta[1]);
-	regmap_read(nfc->regmap, FMC2_BCHDSR2, &ecc_sta[2]);
-	regmap_read(nfc->regmap, FMC2_BCHDSR3, &ecc_sta[3]);
-	regmap_read(nfc->regmap, FMC2_BCHDSR4, &ecc_sta[4]);
+	regmap_read(fmc2->regmap, FMC2_BCHDSR0, &ecc_sta[0]);
+	regmap_read(fmc2->regmap, FMC2_BCHDSR1, &ecc_sta[1]);
+	regmap_read(fmc2->regmap, FMC2_BCHDSR2, &ecc_sta[2]);
+	regmap_read(fmc2->regmap, FMC2_BCHDSR3, &ecc_sta[3]);
+	regmap_read(fmc2->regmap, FMC2_BCHDSR4, &ecc_sta[4]);
 
 	stm32_fmc2_nfc_set_ecc(nfc, false);
 
@@ -593,12 +613,13 @@ static void stm32_fmc2_nfc_rw_page_init(struct nand_chip *chip, int page,
 					int raw, bool write_data)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	u32 csqcfgr1, csqcfgr2, csqcfgr3;
 	u32 csqar1, csqar2;
 	u32 ecc_offset = mtd->writesize + FMC2_BBM_LEN;
 
-	regmap_update_bits(nfc->regmap, FMC2_PCR, FMC2_PCR_WEN,
+	regmap_update_bits(fmc2->regmap, FMC2_PCR, FMC2_PCR_WEN,
 			   write_data ? FMC2_PCR_WEN : 0);
 
 	/*
@@ -674,11 +695,11 @@ static void stm32_fmc2_nfc_rw_page_init(struct nand_chip *chip, int page,
 		csqcfgr1 |= FIELD_PREP(FMC2_CSQCFGR1_ACYNBR, 4);
 	}
 
-	regmap_write(nfc->regmap, FMC2_CSQCFGR1, csqcfgr1);
-	regmap_write(nfc->regmap, FMC2_CSQCFGR2, csqcfgr2);
-	regmap_write(nfc->regmap, FMC2_CSQCFGR3, csqcfgr3);
-	regmap_write(nfc->regmap, FMC2_CSQAR1, csqar1);
-	regmap_write(nfc->regmap, FMC2_CSQAR2, csqar2);
+	regmap_write(fmc2->regmap, FMC2_CSQCFGR1, csqcfgr1);
+	regmap_write(fmc2->regmap, FMC2_CSQCFGR2, csqcfgr2);
+	regmap_write(fmc2->regmap, FMC2_CSQCFGR3, csqcfgr3);
+	regmap_write(fmc2->regmap, FMC2_CSQAR1, csqar1);
+	regmap_write(fmc2->regmap, FMC2_CSQAR2, csqar2);
 }
 
 static void stm32_fmc2_nfc_dma_callback(void *arg)
@@ -691,6 +712,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
 			       int raw, bool write_data)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	struct dma_async_tx_descriptor *desc_data, *desc_ecc;
 	struct scatterlist *sg;
 	struct dma_chan *dma_ch = nfc->dma_rx_ch;
@@ -773,7 +795,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
 	stm32_fmc2_nfc_enable_seq_irq(nfc);
 
 	/* Start the transfer */
-	regmap_update_bits(nfc->regmap, FMC2_CSQCR,
+	regmap_update_bits(fmc2->regmap, FMC2_CSQCR,
 			   FMC2_CSQCR_CSQSTART, FMC2_CSQCR_CSQSTART);
 
 	/* Wait end of sequencer transfer */
@@ -869,9 +891,10 @@ static int stm32_fmc2_nfc_seq_write_page_raw(struct nand_chip *chip,
 /* Get a status indicating which sectors have errors */
 static u16 stm32_fmc2_nfc_get_mapping_status(struct stm32_fmc2_nfc *nfc)
 {
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	u32 csqemsr;
 
-	regmap_read(nfc->regmap, FMC2_CSQEMSR, &csqemsr);
+	regmap_read(fmc2->regmap, FMC2_CSQEMSR, &csqemsr);
 
 	return FIELD_GET(FMC2_CSQEMSR_SEM, csqemsr);
 }
@@ -1125,11 +1148,12 @@ static int stm32_fmc2_nfc_waitrdy(struct nand_chip *chip,
 				  unsigned long timeout_ms)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	const struct nand_sdr_timings *timings;
 	u32 isr, sr;
 
 	/* Check if there is no pending requests to the NAND flash */
-	if (regmap_read_poll_timeout(nfc->regmap, FMC2_SR, sr,
+	if (regmap_read_poll_timeout(fmc2->regmap, FMC2_SR, sr,
 				     sr & FMC2_SR_NWRF, 1,
 				     1000 * FMC2_TIMEOUT_MS))
 		dev_warn(nfc->dev, "Waitrdy timeout\n");
@@ -1139,10 +1163,10 @@ static int stm32_fmc2_nfc_waitrdy(struct nand_chip *chip,
 	ndelay(PSEC_TO_NSEC(timings->tWB_max));
 
 	/* R/B# signal is low, clear high level flag */
-	regmap_write(nfc->regmap, FMC2_ICR, FMC2_ICR_CIHLF);
+	regmap_write(fmc2->regmap, FMC2_ICR, FMC2_ICR_CIHLF);
 
 	/* Wait R/B# signal is high */
-	return regmap_read_poll_timeout(nfc->regmap, FMC2_ISR, isr,
+	return regmap_read_poll_timeout(fmc2->regmap, FMC2_ISR, isr,
 					isr & FMC2_ISR_IHLF, 5,
 					1000 * FMC2_TIMEOUT_MS);
 }
@@ -1202,9 +1226,10 @@ static int stm32_fmc2_nfc_exec_op(struct nand_chip *chip,
 
 static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
 {
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	u32 pcr;
 
-	regmap_read(nfc->regmap, FMC2_PCR, &pcr);
+	regmap_read(fmc2->regmap, FMC2_PCR, &pcr);
 
 	/* Set CS used to undefined */
 	nfc->cs_sel = -1;
@@ -1234,13 +1259,9 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
 	pcr &= ~FMC2_PCR_TAR;
 	pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
 
-	/* Enable FMC2 controller */
-	regmap_update_bits(nfc->regmap, FMC2_BCR1,
-			   FMC2_BCR1_FMC2EN, FMC2_BCR1_FMC2EN);
-
-	regmap_write(nfc->regmap, FMC2_PCR, pcr);
-	regmap_write(nfc->regmap, FMC2_PMEM, FMC2_PMEM_DEFAULT);
-	regmap_write(nfc->regmap, FMC2_PATT, FMC2_PATT_DEFAULT);
+	regmap_write(fmc2->regmap, FMC2_PCR, pcr);
+	regmap_write(fmc2->regmap, FMC2_PMEM, FMC2_PMEM_DEFAULT);
+	regmap_write(fmc2->regmap, FMC2_PATT, FMC2_PATT_DEFAULT);
 }
 
 static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip,
@@ -1249,7 +1270,8 @@ static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip,
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
 	struct stm32_fmc2_timings *tims = &nand->timings;
-	unsigned long hclk = clk_get_rate(nfc->clk);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
+	unsigned long hclk = clk_get_rate(fmc2->clk);
 	unsigned long hclkp = NSEC_PER_SEC / (hclk / 1000);
 	unsigned long timing, tar, tclr, thiz, twait;
 	unsigned long tset_mem, tset_att, thold_mem, thold_att;
@@ -1666,17 +1688,57 @@ static int stm32_fmc2_nfc_parse_dt(struct stm32_fmc2_nfc *nfc)
 	return ret;
 }
 
+static void stm32_fmc2_nfc_enable(struct stm32_fmc2 *fmc2)
+{
+	regmap_update_bits(fmc2->regmap, FMC2_BCR1,
+			   FMC2_BCR1_FMC2EN, FMC2_BCR1_FMC2EN);
+}
+
+static void stm32_fmc2_nfc_disable(struct stm32_fmc2 *fmc2)
+{
+	regmap_update_bits(fmc2->regmap, FMC2_BCR1, FMC2_BCR1_FMC2EN, 0);
+}
+
+static int stm32_fmc2_nfc_set_mmio_clk(struct platform_device *pdev,
+				       struct stm32_fmc2 *fmc2)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	void __iomem *mmio;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mmio = devm_ioremap_resource(dev, res);
+	if (IS_ERR(mmio))
+		return PTR_ERR(mmio);
+
+	fmc2->regmap = devm_regmap_init_mmio(dev, mmio, &stm32_fmc2_regmap_cfg);
+	if (IS_ERR(fmc2->regmap))
+		return PTR_ERR(fmc2->regmap);
+
+	fmc2->reg_phys_addr = res->start;
+
+	fmc2->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(fmc2->clk))
+		return PTR_ERR(fmc2->clk);
+
+	fmc2->enable = stm32_fmc2_nfc_enable;
+	fmc2->disable = stm32_fmc2_nfc_disable;
+
+	return 0;
+}
+
 static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct reset_control *rstc;
+	struct stm32_fmc2 *fmc2;
 	struct stm32_fmc2_nfc *nfc;
 	struct stm32_fmc2_nand *nand;
 	struct resource *res;
 	struct mtd_info *mtd;
 	struct nand_chip *chip;
-	void __iomem *mmio;
 	int chip_cs, mem_region, ret, irq;
+	int num_region = 0;
 
 	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
 	if (!nfc)
@@ -1690,18 +1752,27 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	mmio = devm_ioremap_resource(dev, res);
-	if (IS_ERR(mmio))
-		return PTR_ERR(mmio);
+	fmc2 = dev_get_drvdata(dev->parent);
+	if (!fmc2) {
+		num_region = 1;
 
-	nfc->regmap = devm_regmap_init_mmio(dev, mmio, &stm32_fmc2_regmap_cfg);
-	if (IS_ERR(nfc->regmap))
-		return PTR_ERR(nfc->regmap);
+		fmc2 = devm_kzalloc(dev, sizeof(*fmc2), GFP_KERNEL);
+		if (!fmc2)
+			return -ENOMEM;
 
-	nfc->io_phys_addr = res->start;
+		ret = stm32_fmc2_nfc_set_mmio_clk(pdev, fmc2);
+		if (ret)
+			return ret;
+	}
+	nfc->fmc2 = fmc2;
 
-	for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
+	if (atomic_inc_return(&fmc2->nwait_is_used) > 1) {
+		dev_err(dev, "NWAIT signal in used by a FMC controller\n");
+		atomic_dec(&fmc2->nwait_is_used);
+		return -EINVAL;
+	}
+
+	for (chip_cs = 0, mem_region = num_region; chip_cs < FMC2_MAX_CE;
 	     chip_cs++, mem_region += 3) {
 		if (!(nfc->cs_assigned & BIT(chip_cs)))
 			continue;
@@ -1739,11 +1810,7 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 
 	init_completion(&nfc->complete);
 
-	nfc->clk = devm_clk_get(dev, NULL);
-	if (IS_ERR(nfc->clk))
-		return PTR_ERR(nfc->clk);
-
-	ret = clk_prepare_enable(nfc->clk);
+	ret = clk_prepare_enable(fmc2->clk);
 	if (ret) {
 		dev_err(dev, "can not enable the clock\n");
 		return ret;
@@ -1763,6 +1830,7 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_dma_setup;
 
+	fmc2->enable(fmc2);
 	stm32_fmc2_nfc_init(nfc);
 
 	nand = &nfc->nand;
@@ -1782,7 +1850,7 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 	/* Scan to find existence of the device */
 	ret = nand_scan(chip, nand->ncs);
 	if (ret)
-		goto err_dma_setup;
+		goto err_nand_scan;
 
 	ret = mtd_device_register(mtd, NULL, 0);
 	if (ret)
@@ -1795,6 +1863,10 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 err_device_register:
 	nand_cleanup(chip);
 
+err_nand_scan:
+	regmap_update_bits(fmc2->regmap, FMC2_PCR, FMC2_PCR_PBKEN, 0);
+	fmc2->disable(fmc2);
+
 err_dma_setup:
 	if (nfc->dma_ecc_ch)
 		dma_release_channel(nfc->dma_ecc_ch);
@@ -1807,7 +1879,7 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 	sg_free_table(&nfc->dma_ecc_sg);
 
 err_clk_disable:
-	clk_disable_unprepare(nfc->clk);
+	clk_disable_unprepare(fmc2->clk);
 
 	return ret;
 }
@@ -1816,7 +1888,11 @@ static int stm32_fmc2_nfc_remove(struct platform_device *pdev)
 {
 	struct stm32_fmc2_nfc *nfc = platform_get_drvdata(pdev);
 	struct stm32_fmc2_nand *nand = &nfc->nand;
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 
+	regmap_update_bits(fmc2->regmap, FMC2_PCR, FMC2_PCR_PBKEN, 0);
+	atomic_dec(&fmc2->nwait_is_used);
+	fmc2->disable(fmc2);
 	nand_release(&nand->chip);
 
 	if (nfc->dma_ecc_ch)
@@ -1829,7 +1905,7 @@ static int stm32_fmc2_nfc_remove(struct platform_device *pdev)
 	sg_free_table(&nfc->dma_data_sg);
 	sg_free_table(&nfc->dma_ecc_sg);
 
-	clk_disable_unprepare(nfc->clk);
+	clk_disable_unprepare(fmc2->clk);
 
 	return 0;
 }
@@ -1837,8 +1913,10 @@ static int stm32_fmc2_nfc_remove(struct platform_device *pdev)
 static int __maybe_unused stm32_fmc2_nfc_suspend(struct device *dev)
 {
 	struct stm32_fmc2_nfc *nfc = dev_get_drvdata(dev);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 
-	clk_disable_unprepare(nfc->clk);
+	fmc2->disable(fmc2);
+	clk_disable_unprepare(fmc2->clk);
 
 	pinctrl_pm_select_sleep_state(dev);
 
@@ -1849,16 +1927,18 @@ static int __maybe_unused stm32_fmc2_nfc_resume(struct device *dev)
 {
 	struct stm32_fmc2_nfc *nfc = dev_get_drvdata(dev);
 	struct stm32_fmc2_nand *nand = &nfc->nand;
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	int chip_cs, ret;
 
 	pinctrl_pm_select_default_state(dev);
 
-	ret = clk_prepare_enable(nfc->clk);
+	ret = clk_prepare_enable(fmc2->clk);
 	if (ret) {
 		dev_err(dev, "can not enable the clock\n");
 		return ret;
 	}
 
+	fmc2->enable(fmc2);
 	stm32_fmc2_nfc_init(nfc);
 
 	for (chip_cs = 0; chip_cs < FMC2_MAX_CE; chip_cs++) {
-- 
1.9.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

  parent reply	other threads:[~2020-03-23 15:03 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-23 14:58 [00/12] add STM32 FMC2 controller drivers Christophe Kerello
2020-03-23 14:58 ` [01/12] dt-bindings: mfd: stm32-fmc2: add STM32 FMC2 controller documentation Christophe Kerello
2020-03-23 14:58 ` [02/12] mfd: stm32-fmc2: add STM32 FMC2 controller driver Christophe Kerello
2020-03-29 23:36   ` Marek Vasut
2020-03-30  9:18     ` Christophe Kerello
2020-03-23 14:58 ` [03/12] bus: stm32-fmc2-ebi: add STM32 FMC2 EBI " Christophe Kerello
2020-03-30  1:24   ` Marek Vasut
2020-03-30  9:19     ` Christophe Kerello
2020-03-30  9:30       ` Marek Vasut
2020-03-23 14:58 ` [04/12] mtd: rawnand: stm32_fmc2: manage all errors cases at probe time Christophe Kerello
2020-03-23 14:58 ` [05/12] mtd: rawnand: stm32_fmc2: remove useless inline comments Christophe Kerello
2020-03-23 14:58 ` [06/12] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_MS for timeouts Christophe Kerello
2020-03-23 14:58 ` [07/12] mtd: rawnand: stm32_fmc2: cleanup Christophe Kerello
2020-03-23 14:58 ` [08/12] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros Christophe Kerello
2020-03-23 14:58 ` [09/12] mtd: rawnand: stm32_fmc2: move all registers Christophe Kerello
2020-03-23 14:58 ` [10/12] mtd: rawnand: stm32_fmc2: use regmap APIs Christophe Kerello
2020-03-24  0:44   ` Marek Vasut
2020-03-24 10:38     ` Christophe Kerello
2020-03-23 14:58 ` Christophe Kerello [this message]
2020-03-23 14:58 ` [12/12] mtd: rawnand: stm32_fmc2: add new MP1 compatible string Christophe Kerello
2020-03-24  0:37 ` [00/12] add STM32 FMC2 controller drivers Marek Vasut
2020-03-24  7:36   ` Christophe Kerello
2020-03-24 13:27     ` Marek Vasut
2020-03-24 13:37       ` Christophe Kerello

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1584975532-8038-12-git-send-email-christophe.kerello@st.com \
    --to=christophe.kerello@st.com \
    --cc=lee.jones@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=linux-stm32@st-md-mailman.stormreply.com \
    --cc=marex@denx.de \
    --cc=mark.rutland@arm.com \
    --cc=miquel.raynal@bootlin.com \
    --cc=richard@nod.at \
    --cc=robh+dt@kernel.org \
    --cc=tony@atomide.com \
    --cc=vigneshr@ti.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).