xref: /linux/drivers/mtd/nand/raw/stm32_fmc2_nand.c (revision c3bdd5e65185f46150b3bac103b3854040487857)
12cd457f3SChristophe Kerello // SPDX-License-Identifier: GPL-2.0
22cd457f3SChristophe Kerello /*
32cd457f3SChristophe Kerello  * Copyright (C) STMicroelectronics 2018
42cd457f3SChristophe Kerello  * Author: Christophe Kerello <christophe.kerello@st.com>
52cd457f3SChristophe Kerello  */
62cd457f3SChristophe Kerello 
72cd457f3SChristophe Kerello #include <linux/clk.h>
82cd457f3SChristophe Kerello #include <linux/dmaengine.h>
92cd457f3SChristophe Kerello #include <linux/dma-mapping.h>
102cd457f3SChristophe Kerello #include <linux/errno.h>
112cd457f3SChristophe Kerello #include <linux/interrupt.h>
122cd457f3SChristophe Kerello #include <linux/iopoll.h>
132cd457f3SChristophe Kerello #include <linux/module.h>
142cd457f3SChristophe Kerello #include <linux/mtd/rawnand.h>
152cd457f3SChristophe Kerello #include <linux/pinctrl/consumer.h>
162cd457f3SChristophe Kerello #include <linux/platform_device.h>
172cd457f3SChristophe Kerello #include <linux/reset.h>
182cd457f3SChristophe Kerello 
192cd457f3SChristophe Kerello /* Bad block marker length */
202cd457f3SChristophe Kerello #define FMC2_BBM_LEN			2
212cd457f3SChristophe Kerello 
222cd457f3SChristophe Kerello /* ECC step size */
232cd457f3SChristophe Kerello #define FMC2_ECC_STEP_SIZE		512
242cd457f3SChristophe Kerello 
252cd457f3SChristophe Kerello /* BCHDSRx registers length */
262cd457f3SChristophe Kerello #define FMC2_BCHDSRS_LEN		20
272cd457f3SChristophe Kerello 
282cd457f3SChristophe Kerello /* HECCR length */
292cd457f3SChristophe Kerello #define FMC2_HECCR_LEN			4
302cd457f3SChristophe Kerello 
312cd457f3SChristophe Kerello /* Max requests done for a 8k nand page size */
322cd457f3SChristophe Kerello #define FMC2_MAX_SG			16
332cd457f3SChristophe Kerello 
342cd457f3SChristophe Kerello /* Max chip enable */
352cd457f3SChristophe Kerello #define FMC2_MAX_CE			2
362cd457f3SChristophe Kerello 
372cd457f3SChristophe Kerello /* Max ECC buffer length */
382cd457f3SChristophe Kerello #define FMC2_MAX_ECC_BUF_LEN		(FMC2_BCHDSRS_LEN * FMC2_MAX_SG)
392cd457f3SChristophe Kerello 
402cd457f3SChristophe Kerello /* Timings */
412cd457f3SChristophe Kerello #define FMC2_THIZ			1
422cd457f3SChristophe Kerello #define FMC2_TIO			8000
432cd457f3SChristophe Kerello #define FMC2_TSYNC			3000
442cd457f3SChristophe Kerello #define FMC2_PCR_TIMING_MASK		0xf
452cd457f3SChristophe Kerello #define FMC2_PMEM_PATT_TIMING_MASK	0xff
462cd457f3SChristophe Kerello 
472cd457f3SChristophe Kerello /* FMC2 Controller Registers */
482cd457f3SChristophe Kerello #define FMC2_BCR1			0x0
492cd457f3SChristophe Kerello #define FMC2_PCR			0x80
502cd457f3SChristophe Kerello #define FMC2_SR				0x84
512cd457f3SChristophe Kerello #define FMC2_PMEM			0x88
522cd457f3SChristophe Kerello #define FMC2_PATT			0x8c
532cd457f3SChristophe Kerello #define FMC2_HECCR			0x94
542cd457f3SChristophe Kerello #define FMC2_CSQCR			0x200
552cd457f3SChristophe Kerello #define FMC2_CSQCFGR1			0x204
562cd457f3SChristophe Kerello #define FMC2_CSQCFGR2			0x208
572cd457f3SChristophe Kerello #define FMC2_CSQCFGR3			0x20c
582cd457f3SChristophe Kerello #define FMC2_CSQAR1			0x210
592cd457f3SChristophe Kerello #define FMC2_CSQAR2			0x214
602cd457f3SChristophe Kerello #define FMC2_CSQIER			0x220
612cd457f3SChristophe Kerello #define FMC2_CSQISR			0x224
622cd457f3SChristophe Kerello #define FMC2_CSQICR			0x228
632cd457f3SChristophe Kerello #define FMC2_CSQEMSR			0x230
642cd457f3SChristophe Kerello #define FMC2_BCHIER			0x250
652cd457f3SChristophe Kerello #define FMC2_BCHISR			0x254
662cd457f3SChristophe Kerello #define FMC2_BCHICR			0x258
672cd457f3SChristophe Kerello #define FMC2_BCHPBR1			0x260
682cd457f3SChristophe Kerello #define FMC2_BCHPBR2			0x264
692cd457f3SChristophe Kerello #define FMC2_BCHPBR3			0x268
702cd457f3SChristophe Kerello #define FMC2_BCHPBR4			0x26c
712cd457f3SChristophe Kerello #define FMC2_BCHDSR0			0x27c
722cd457f3SChristophe Kerello #define FMC2_BCHDSR1			0x280
732cd457f3SChristophe Kerello #define FMC2_BCHDSR2			0x284
742cd457f3SChristophe Kerello #define FMC2_BCHDSR3			0x288
752cd457f3SChristophe Kerello #define FMC2_BCHDSR4			0x28c
762cd457f3SChristophe Kerello 
772cd457f3SChristophe Kerello /* Register: FMC2_BCR1 */
782cd457f3SChristophe Kerello #define FMC2_BCR1_FMC2EN		BIT(31)
792cd457f3SChristophe Kerello 
802cd457f3SChristophe Kerello /* Register: FMC2_PCR */
812cd457f3SChristophe Kerello #define FMC2_PCR_PWAITEN		BIT(1)
822cd457f3SChristophe Kerello #define FMC2_PCR_PBKEN			BIT(2)
832cd457f3SChristophe Kerello #define FMC2_PCR_PWID_MASK		GENMASK(5, 4)
842cd457f3SChristophe Kerello #define FMC2_PCR_PWID(x)		(((x) & 0x3) << 4)
852cd457f3SChristophe Kerello #define FMC2_PCR_PWID_BUSWIDTH_8	0
862cd457f3SChristophe Kerello #define FMC2_PCR_PWID_BUSWIDTH_16	1
872cd457f3SChristophe Kerello #define FMC2_PCR_ECCEN			BIT(6)
882cd457f3SChristophe Kerello #define FMC2_PCR_ECCALG			BIT(8)
892cd457f3SChristophe Kerello #define FMC2_PCR_TCLR_MASK		GENMASK(12, 9)
902cd457f3SChristophe Kerello #define FMC2_PCR_TCLR(x)		(((x) & 0xf) << 9)
912cd457f3SChristophe Kerello #define FMC2_PCR_TCLR_DEFAULT		0xf
922cd457f3SChristophe Kerello #define FMC2_PCR_TAR_MASK		GENMASK(16, 13)
932cd457f3SChristophe Kerello #define FMC2_PCR_TAR(x)			(((x) & 0xf) << 13)
942cd457f3SChristophe Kerello #define FMC2_PCR_TAR_DEFAULT		0xf
952cd457f3SChristophe Kerello #define FMC2_PCR_ECCSS_MASK		GENMASK(19, 17)
962cd457f3SChristophe Kerello #define FMC2_PCR_ECCSS(x)		(((x) & 0x7) << 17)
972cd457f3SChristophe Kerello #define FMC2_PCR_ECCSS_512		1
982cd457f3SChristophe Kerello #define FMC2_PCR_ECCSS_2048		3
992cd457f3SChristophe Kerello #define FMC2_PCR_BCHECC			BIT(24)
1002cd457f3SChristophe Kerello #define FMC2_PCR_WEN			BIT(25)
1012cd457f3SChristophe Kerello 
1022cd457f3SChristophe Kerello /* Register: FMC2_SR */
1032cd457f3SChristophe Kerello #define FMC2_SR_NWRF			BIT(6)
1042cd457f3SChristophe Kerello 
1052cd457f3SChristophe Kerello /* Register: FMC2_PMEM */
1062cd457f3SChristophe Kerello #define FMC2_PMEM_MEMSET(x)		(((x) & 0xff) << 0)
1072cd457f3SChristophe Kerello #define FMC2_PMEM_MEMWAIT(x)		(((x) & 0xff) << 8)
1082cd457f3SChristophe Kerello #define FMC2_PMEM_MEMHOLD(x)		(((x) & 0xff) << 16)
1092cd457f3SChristophe Kerello #define FMC2_PMEM_MEMHIZ(x)		(((x) & 0xff) << 24)
1102cd457f3SChristophe Kerello #define FMC2_PMEM_DEFAULT		0x0a0a0a0a
1112cd457f3SChristophe Kerello 
1122cd457f3SChristophe Kerello /* Register: FMC2_PATT */
1132cd457f3SChristophe Kerello #define FMC2_PATT_ATTSET(x)		(((x) & 0xff) << 0)
1142cd457f3SChristophe Kerello #define FMC2_PATT_ATTWAIT(x)		(((x) & 0xff) << 8)
1152cd457f3SChristophe Kerello #define FMC2_PATT_ATTHOLD(x)		(((x) & 0xff) << 16)
1162cd457f3SChristophe Kerello #define FMC2_PATT_ATTHIZ(x)		(((x) & 0xff) << 24)
1172cd457f3SChristophe Kerello #define FMC2_PATT_DEFAULT		0x0a0a0a0a
1182cd457f3SChristophe Kerello 
1192cd457f3SChristophe Kerello /* Register: FMC2_CSQCR */
1202cd457f3SChristophe Kerello #define FMC2_CSQCR_CSQSTART		BIT(0)
1212cd457f3SChristophe Kerello 
1222cd457f3SChristophe Kerello /* Register: FMC2_CSQCFGR1 */
1232cd457f3SChristophe Kerello #define FMC2_CSQCFGR1_CMD2EN		BIT(1)
1242cd457f3SChristophe Kerello #define FMC2_CSQCFGR1_DMADEN		BIT(2)
1252cd457f3SChristophe Kerello #define FMC2_CSQCFGR1_ACYNBR(x)		(((x) & 0x7) << 4)
1262cd457f3SChristophe Kerello #define FMC2_CSQCFGR1_CMD1(x)		(((x) & 0xff) << 8)
1272cd457f3SChristophe Kerello #define FMC2_CSQCFGR1_CMD2(x)		(((x) & 0xff) << 16)
1282cd457f3SChristophe Kerello #define FMC2_CSQCFGR1_CMD1T		BIT(24)
1292cd457f3SChristophe Kerello #define FMC2_CSQCFGR1_CMD2T		BIT(25)
1302cd457f3SChristophe Kerello 
1312cd457f3SChristophe Kerello /* Register: FMC2_CSQCFGR2 */
1322cd457f3SChristophe Kerello #define FMC2_CSQCFGR2_SQSDTEN		BIT(0)
1332cd457f3SChristophe Kerello #define FMC2_CSQCFGR2_RCMD2EN		BIT(1)
1342cd457f3SChristophe Kerello #define FMC2_CSQCFGR2_DMASEN		BIT(2)
1352cd457f3SChristophe Kerello #define FMC2_CSQCFGR2_RCMD1(x)		(((x) & 0xff) << 8)
1362cd457f3SChristophe Kerello #define FMC2_CSQCFGR2_RCMD2(x)		(((x) & 0xff) << 16)
1372cd457f3SChristophe Kerello #define FMC2_CSQCFGR2_RCMD1T		BIT(24)
1382cd457f3SChristophe Kerello #define FMC2_CSQCFGR2_RCMD2T		BIT(25)
1392cd457f3SChristophe Kerello 
1402cd457f3SChristophe Kerello /* Register: FMC2_CSQCFGR3 */
1412cd457f3SChristophe Kerello #define FMC2_CSQCFGR3_SNBR(x)		(((x) & 0x1f) << 8)
1422cd457f3SChristophe Kerello #define FMC2_CSQCFGR3_AC1T		BIT(16)
1432cd457f3SChristophe Kerello #define FMC2_CSQCFGR3_AC2T		BIT(17)
1442cd457f3SChristophe Kerello #define FMC2_CSQCFGR3_AC3T		BIT(18)
1452cd457f3SChristophe Kerello #define FMC2_CSQCFGR3_AC4T		BIT(19)
1462cd457f3SChristophe Kerello #define FMC2_CSQCFGR3_AC5T		BIT(20)
1472cd457f3SChristophe Kerello #define FMC2_CSQCFGR3_SDT		BIT(21)
1482cd457f3SChristophe Kerello #define FMC2_CSQCFGR3_RAC1T		BIT(22)
1492cd457f3SChristophe Kerello #define FMC2_CSQCFGR3_RAC2T		BIT(23)
1502cd457f3SChristophe Kerello 
1512cd457f3SChristophe Kerello /* Register: FMC2_CSQCAR1 */
1522cd457f3SChristophe Kerello #define FMC2_CSQCAR1_ADDC1(x)		(((x) & 0xff) << 0)
1532cd457f3SChristophe Kerello #define FMC2_CSQCAR1_ADDC2(x)		(((x) & 0xff) << 8)
1542cd457f3SChristophe Kerello #define FMC2_CSQCAR1_ADDC3(x)		(((x) & 0xff) << 16)
1552cd457f3SChristophe Kerello #define FMC2_CSQCAR1_ADDC4(x)		(((x) & 0xff) << 24)
1562cd457f3SChristophe Kerello 
1572cd457f3SChristophe Kerello /* Register: FMC2_CSQCAR2 */
1582cd457f3SChristophe Kerello #define FMC2_CSQCAR2_ADDC5(x)		(((x) & 0xff) << 0)
1592cd457f3SChristophe Kerello #define FMC2_CSQCAR2_NANDCEN(x)		(((x) & 0x3) << 10)
1602cd457f3SChristophe Kerello #define FMC2_CSQCAR2_SAO(x)		(((x) & 0xffff) << 16)
1612cd457f3SChristophe Kerello 
1622cd457f3SChristophe Kerello /* Register: FMC2_CSQIER */
1632cd457f3SChristophe Kerello #define FMC2_CSQIER_TCIE		BIT(0)
1642cd457f3SChristophe Kerello 
1652cd457f3SChristophe Kerello /* Register: FMC2_CSQICR */
1662cd457f3SChristophe Kerello #define FMC2_CSQICR_CLEAR_IRQ		GENMASK(4, 0)
1672cd457f3SChristophe Kerello 
1682cd457f3SChristophe Kerello /* Register: FMC2_CSQEMSR */
1692cd457f3SChristophe Kerello #define FMC2_CSQEMSR_SEM		GENMASK(15, 0)
1702cd457f3SChristophe Kerello 
1712cd457f3SChristophe Kerello /* Register: FMC2_BCHIER */
1722cd457f3SChristophe Kerello #define FMC2_BCHIER_DERIE		BIT(1)
1732cd457f3SChristophe Kerello #define FMC2_BCHIER_EPBRIE		BIT(4)
1742cd457f3SChristophe Kerello 
1752cd457f3SChristophe Kerello /* Register: FMC2_BCHICR */
1762cd457f3SChristophe Kerello #define FMC2_BCHICR_CLEAR_IRQ		GENMASK(4, 0)
1772cd457f3SChristophe Kerello 
1782cd457f3SChristophe Kerello /* Register: FMC2_BCHDSR0 */
1792cd457f3SChristophe Kerello #define FMC2_BCHDSR0_DUE		BIT(0)
1802cd457f3SChristophe Kerello #define FMC2_BCHDSR0_DEF		BIT(1)
1812cd457f3SChristophe Kerello #define FMC2_BCHDSR0_DEN_MASK		GENMASK(7, 4)
1822cd457f3SChristophe Kerello #define FMC2_BCHDSR0_DEN_SHIFT		4
1832cd457f3SChristophe Kerello 
1842cd457f3SChristophe Kerello /* Register: FMC2_BCHDSR1 */
1852cd457f3SChristophe Kerello #define FMC2_BCHDSR1_EBP1_MASK		GENMASK(12, 0)
1862cd457f3SChristophe Kerello #define FMC2_BCHDSR1_EBP2_MASK		GENMASK(28, 16)
1872cd457f3SChristophe Kerello #define FMC2_BCHDSR1_EBP2_SHIFT		16
1882cd457f3SChristophe Kerello 
1892cd457f3SChristophe Kerello /* Register: FMC2_BCHDSR2 */
1902cd457f3SChristophe Kerello #define FMC2_BCHDSR2_EBP3_MASK		GENMASK(12, 0)
1912cd457f3SChristophe Kerello #define FMC2_BCHDSR2_EBP4_MASK		GENMASK(28, 16)
1922cd457f3SChristophe Kerello #define FMC2_BCHDSR2_EBP4_SHIFT		16
1932cd457f3SChristophe Kerello 
1942cd457f3SChristophe Kerello /* Register: FMC2_BCHDSR3 */
1952cd457f3SChristophe Kerello #define FMC2_BCHDSR3_EBP5_MASK		GENMASK(12, 0)
1962cd457f3SChristophe Kerello #define FMC2_BCHDSR3_EBP6_MASK		GENMASK(28, 16)
1972cd457f3SChristophe Kerello #define FMC2_BCHDSR3_EBP6_SHIFT		16
1982cd457f3SChristophe Kerello 
1992cd457f3SChristophe Kerello /* Register: FMC2_BCHDSR4 */
2002cd457f3SChristophe Kerello #define FMC2_BCHDSR4_EBP7_MASK		GENMASK(12, 0)
2012cd457f3SChristophe Kerello #define FMC2_BCHDSR4_EBP8_MASK		GENMASK(28, 16)
2022cd457f3SChristophe Kerello #define FMC2_BCHDSR4_EBP8_SHIFT		16
2032cd457f3SChristophe Kerello 
2042cd457f3SChristophe Kerello enum stm32_fmc2_ecc {
2052cd457f3SChristophe Kerello 	FMC2_ECC_HAM = 1,
2062cd457f3SChristophe Kerello 	FMC2_ECC_BCH4 = 4,
2072cd457f3SChristophe Kerello 	FMC2_ECC_BCH8 = 8
2082cd457f3SChristophe Kerello };
2092cd457f3SChristophe Kerello 
210*33c8cf42SChristophe Kerello enum stm32_fmc2_irq_state {
211*33c8cf42SChristophe Kerello 	FMC2_IRQ_UNKNOWN = 0,
212*33c8cf42SChristophe Kerello 	FMC2_IRQ_BCH,
213*33c8cf42SChristophe Kerello 	FMC2_IRQ_SEQ
214*33c8cf42SChristophe Kerello };
215*33c8cf42SChristophe Kerello 
2162cd457f3SChristophe Kerello struct stm32_fmc2_timings {
2172cd457f3SChristophe Kerello 	u8 tclr;
2182cd457f3SChristophe Kerello 	u8 tar;
2192cd457f3SChristophe Kerello 	u8 thiz;
2202cd457f3SChristophe Kerello 	u8 twait;
2212cd457f3SChristophe Kerello 	u8 thold_mem;
2222cd457f3SChristophe Kerello 	u8 tset_mem;
2232cd457f3SChristophe Kerello 	u8 thold_att;
2242cd457f3SChristophe Kerello 	u8 tset_att;
2252cd457f3SChristophe Kerello };
2262cd457f3SChristophe Kerello 
2272cd457f3SChristophe Kerello struct stm32_fmc2_nand {
2282cd457f3SChristophe Kerello 	struct nand_chip chip;
2292cd457f3SChristophe Kerello 	struct stm32_fmc2_timings timings;
2302cd457f3SChristophe Kerello 	int ncs;
2312cd457f3SChristophe Kerello 	int cs_used[FMC2_MAX_CE];
2322cd457f3SChristophe Kerello };
2332cd457f3SChristophe Kerello 
2342cd457f3SChristophe Kerello static inline struct stm32_fmc2_nand *to_fmc2_nand(struct nand_chip *chip)
2352cd457f3SChristophe Kerello {
2362cd457f3SChristophe Kerello 	return container_of(chip, struct stm32_fmc2_nand, chip);
2372cd457f3SChristophe Kerello }
2382cd457f3SChristophe Kerello 
2392cd457f3SChristophe Kerello struct stm32_fmc2_nfc {
2402cd457f3SChristophe Kerello 	struct nand_controller base;
2412cd457f3SChristophe Kerello 	struct stm32_fmc2_nand nand;
2422cd457f3SChristophe Kerello 	struct device *dev;
2432cd457f3SChristophe Kerello 	void __iomem *io_base;
2442cd457f3SChristophe Kerello 	void __iomem *data_base[FMC2_MAX_CE];
2452cd457f3SChristophe Kerello 	void __iomem *cmd_base[FMC2_MAX_CE];
2462cd457f3SChristophe Kerello 	void __iomem *addr_base[FMC2_MAX_CE];
2472cd457f3SChristophe Kerello 	phys_addr_t io_phys_addr;
2482cd457f3SChristophe Kerello 	phys_addr_t data_phys_addr[FMC2_MAX_CE];
2492cd457f3SChristophe Kerello 	struct clk *clk;
250*33c8cf42SChristophe Kerello 	u8 irq_state;
2512cd457f3SChristophe Kerello 
2522cd457f3SChristophe Kerello 	struct dma_chan *dma_tx_ch;
2532cd457f3SChristophe Kerello 	struct dma_chan *dma_rx_ch;
2542cd457f3SChristophe Kerello 	struct dma_chan *dma_ecc_ch;
2552cd457f3SChristophe Kerello 	struct sg_table dma_data_sg;
2562cd457f3SChristophe Kerello 	struct sg_table dma_ecc_sg;
2572cd457f3SChristophe Kerello 	u8 *ecc_buf;
2582cd457f3SChristophe Kerello 	int dma_ecc_len;
2592cd457f3SChristophe Kerello 
2602cd457f3SChristophe Kerello 	struct completion complete;
2612cd457f3SChristophe Kerello 	struct completion dma_data_complete;
2622cd457f3SChristophe Kerello 	struct completion dma_ecc_complete;
2632cd457f3SChristophe Kerello 
2642cd457f3SChristophe Kerello 	u8 cs_assigned;
2652cd457f3SChristophe Kerello 	int cs_sel;
2662cd457f3SChristophe Kerello };
2672cd457f3SChristophe Kerello 
2682cd457f3SChristophe Kerello static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_controller *base)
2692cd457f3SChristophe Kerello {
2702cd457f3SChristophe Kerello 	return container_of(base, struct stm32_fmc2_nfc, base);
2712cd457f3SChristophe Kerello }
2722cd457f3SChristophe Kerello 
2732cd457f3SChristophe Kerello /* Timings configuration */
2742cd457f3SChristophe Kerello static void stm32_fmc2_timings_init(struct nand_chip *chip)
2752cd457f3SChristophe Kerello {
2762cd457f3SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
2772cd457f3SChristophe Kerello 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
2782cd457f3SChristophe Kerello 	struct stm32_fmc2_timings *timings = &nand->timings;
2792cd457f3SChristophe Kerello 	u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
2802cd457f3SChristophe Kerello 	u32 pmem, patt;
2812cd457f3SChristophe Kerello 
2822cd457f3SChristophe Kerello 	/* Set tclr/tar timings */
2832cd457f3SChristophe Kerello 	pcr &= ~FMC2_PCR_TCLR_MASK;
2842cd457f3SChristophe Kerello 	pcr |= FMC2_PCR_TCLR(timings->tclr);
2852cd457f3SChristophe Kerello 	pcr &= ~FMC2_PCR_TAR_MASK;
2862cd457f3SChristophe Kerello 	pcr |= FMC2_PCR_TAR(timings->tar);
2872cd457f3SChristophe Kerello 
2882cd457f3SChristophe Kerello 	/* Set tset/twait/thold/thiz timings in common bank */
2892cd457f3SChristophe Kerello 	pmem = FMC2_PMEM_MEMSET(timings->tset_mem);
2902cd457f3SChristophe Kerello 	pmem |= FMC2_PMEM_MEMWAIT(timings->twait);
2912cd457f3SChristophe Kerello 	pmem |= FMC2_PMEM_MEMHOLD(timings->thold_mem);
2922cd457f3SChristophe Kerello 	pmem |= FMC2_PMEM_MEMHIZ(timings->thiz);
2932cd457f3SChristophe Kerello 
2942cd457f3SChristophe Kerello 	/* Set tset/twait/thold/thiz timings in attribut bank */
2952cd457f3SChristophe Kerello 	patt = FMC2_PATT_ATTSET(timings->tset_att);
2962cd457f3SChristophe Kerello 	patt |= FMC2_PATT_ATTWAIT(timings->twait);
2972cd457f3SChristophe Kerello 	patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
2982cd457f3SChristophe Kerello 	patt |= FMC2_PATT_ATTHIZ(timings->thiz);
2992cd457f3SChristophe Kerello 
3002cd457f3SChristophe Kerello 	writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
3012cd457f3SChristophe Kerello 	writel_relaxed(pmem, fmc2->io_base + FMC2_PMEM);
3022cd457f3SChristophe Kerello 	writel_relaxed(patt, fmc2->io_base + FMC2_PATT);
3032cd457f3SChristophe Kerello }
3042cd457f3SChristophe Kerello 
3052cd457f3SChristophe Kerello /* Controller configuration */
3062cd457f3SChristophe Kerello static void stm32_fmc2_setup(struct nand_chip *chip)
3072cd457f3SChristophe Kerello {
3082cd457f3SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
3092cd457f3SChristophe Kerello 	u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
3102cd457f3SChristophe Kerello 
3112cd457f3SChristophe Kerello 	/* Configure ECC algorithm (default configuration is Hamming) */
3122cd457f3SChristophe Kerello 	pcr &= ~FMC2_PCR_ECCALG;
3132cd457f3SChristophe Kerello 	pcr &= ~FMC2_PCR_BCHECC;
3142cd457f3SChristophe Kerello 	if (chip->ecc.strength == FMC2_ECC_BCH8) {
3152cd457f3SChristophe Kerello 		pcr |= FMC2_PCR_ECCALG;
3162cd457f3SChristophe Kerello 		pcr |= FMC2_PCR_BCHECC;
3172cd457f3SChristophe Kerello 	} else if (chip->ecc.strength == FMC2_ECC_BCH4) {
3182cd457f3SChristophe Kerello 		pcr |= FMC2_PCR_ECCALG;
3192cd457f3SChristophe Kerello 	}
3202cd457f3SChristophe Kerello 
3212cd457f3SChristophe Kerello 	/* Set buswidth */
3222cd457f3SChristophe Kerello 	pcr &= ~FMC2_PCR_PWID_MASK;
3232cd457f3SChristophe Kerello 	if (chip->options & NAND_BUSWIDTH_16)
3242cd457f3SChristophe Kerello 		pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
3252cd457f3SChristophe Kerello 
3262cd457f3SChristophe Kerello 	/* Set ECC sector size */
3272cd457f3SChristophe Kerello 	pcr &= ~FMC2_PCR_ECCSS_MASK;
3282cd457f3SChristophe Kerello 	pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
3292cd457f3SChristophe Kerello 
3302cd457f3SChristophe Kerello 	writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
3312cd457f3SChristophe Kerello }
3322cd457f3SChristophe Kerello 
3332cd457f3SChristophe Kerello /* Select target */
3342cd457f3SChristophe Kerello static int stm32_fmc2_select_chip(struct nand_chip *chip, int chipnr)
3352cd457f3SChristophe Kerello {
3362cd457f3SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
3372cd457f3SChristophe Kerello 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
3382cd457f3SChristophe Kerello 	struct dma_slave_config dma_cfg;
3392cd457f3SChristophe Kerello 	int ret;
3402cd457f3SChristophe Kerello 
3412cd457f3SChristophe Kerello 	if (nand->cs_used[chipnr] == fmc2->cs_sel)
3422cd457f3SChristophe Kerello 		return 0;
3432cd457f3SChristophe Kerello 
3442cd457f3SChristophe Kerello 	fmc2->cs_sel = nand->cs_used[chipnr];
3452cd457f3SChristophe Kerello 
3462cd457f3SChristophe Kerello 	/* FMC2 setup routine */
3472cd457f3SChristophe Kerello 	stm32_fmc2_setup(chip);
3482cd457f3SChristophe Kerello 
3492cd457f3SChristophe Kerello 	/* Apply timings */
3502cd457f3SChristophe Kerello 	stm32_fmc2_timings_init(chip);
3512cd457f3SChristophe Kerello 
3522cd457f3SChristophe Kerello 	if (fmc2->dma_tx_ch && fmc2->dma_rx_ch) {
3532cd457f3SChristophe Kerello 		memset(&dma_cfg, 0, sizeof(dma_cfg));
3542cd457f3SChristophe Kerello 		dma_cfg.src_addr = fmc2->data_phys_addr[fmc2->cs_sel];
3552cd457f3SChristophe Kerello 		dma_cfg.dst_addr = fmc2->data_phys_addr[fmc2->cs_sel];
3562cd457f3SChristophe Kerello 		dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
3572cd457f3SChristophe Kerello 		dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
3582cd457f3SChristophe Kerello 		dma_cfg.src_maxburst = 32;
3592cd457f3SChristophe Kerello 		dma_cfg.dst_maxburst = 32;
3602cd457f3SChristophe Kerello 
3612cd457f3SChristophe Kerello 		ret = dmaengine_slave_config(fmc2->dma_tx_ch, &dma_cfg);
3622cd457f3SChristophe Kerello 		if (ret) {
3632cd457f3SChristophe Kerello 			dev_err(fmc2->dev, "tx DMA engine slave config failed\n");
3642cd457f3SChristophe Kerello 			return ret;
3652cd457f3SChristophe Kerello 		}
3662cd457f3SChristophe Kerello 
3672cd457f3SChristophe Kerello 		ret = dmaengine_slave_config(fmc2->dma_rx_ch, &dma_cfg);
3682cd457f3SChristophe Kerello 		if (ret) {
3692cd457f3SChristophe Kerello 			dev_err(fmc2->dev, "rx DMA engine slave config failed\n");
3702cd457f3SChristophe Kerello 			return ret;
3712cd457f3SChristophe Kerello 		}
3722cd457f3SChristophe Kerello 	}
3732cd457f3SChristophe Kerello 
3742cd457f3SChristophe Kerello 	if (fmc2->dma_ecc_ch) {
3752cd457f3SChristophe Kerello 		/*
3762cd457f3SChristophe Kerello 		 * Hamming: we read HECCR register
3772cd457f3SChristophe Kerello 		 * BCH4/BCH8: we read BCHDSRSx registers
3782cd457f3SChristophe Kerello 		 */
3792cd457f3SChristophe Kerello 		memset(&dma_cfg, 0, sizeof(dma_cfg));
3802cd457f3SChristophe Kerello 		dma_cfg.src_addr = fmc2->io_phys_addr;
3812cd457f3SChristophe Kerello 		dma_cfg.src_addr += chip->ecc.strength == FMC2_ECC_HAM ?
3822cd457f3SChristophe Kerello 				    FMC2_HECCR : FMC2_BCHDSR0;
3832cd457f3SChristophe Kerello 		dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
3842cd457f3SChristophe Kerello 
3852cd457f3SChristophe Kerello 		ret = dmaengine_slave_config(fmc2->dma_ecc_ch, &dma_cfg);
3862cd457f3SChristophe Kerello 		if (ret) {
3872cd457f3SChristophe Kerello 			dev_err(fmc2->dev, "ECC DMA engine slave config failed\n");
3882cd457f3SChristophe Kerello 			return ret;
3892cd457f3SChristophe Kerello 		}
3902cd457f3SChristophe Kerello 
3912cd457f3SChristophe Kerello 		/* Calculate ECC length needed for one sector */
3922cd457f3SChristophe Kerello 		fmc2->dma_ecc_len = chip->ecc.strength == FMC2_ECC_HAM ?
3932cd457f3SChristophe Kerello 				    FMC2_HECCR_LEN : FMC2_BCHDSRS_LEN;
3942cd457f3SChristophe Kerello 	}
3952cd457f3SChristophe Kerello 
3962cd457f3SChristophe Kerello 	return 0;
3972cd457f3SChristophe Kerello }
3982cd457f3SChristophe Kerello 
3992cd457f3SChristophe Kerello /* Set bus width to 16-bit or 8-bit */
4002cd457f3SChristophe Kerello static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
4012cd457f3SChristophe Kerello {
4022cd457f3SChristophe Kerello 	u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
4032cd457f3SChristophe Kerello 
4042cd457f3SChristophe Kerello 	pcr &= ~FMC2_PCR_PWID_MASK;
4052cd457f3SChristophe Kerello 	if (set)
4062cd457f3SChristophe Kerello 		pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
4072cd457f3SChristophe Kerello 	writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
4082cd457f3SChristophe Kerello }
4092cd457f3SChristophe Kerello 
410*33c8cf42SChristophe Kerello /* Enable/disable ECC */
411*33c8cf42SChristophe Kerello static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
412*33c8cf42SChristophe Kerello {
413*33c8cf42SChristophe Kerello 	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
414*33c8cf42SChristophe Kerello 
415*33c8cf42SChristophe Kerello 	pcr &= ~FMC2_PCR_ECCEN;
416*33c8cf42SChristophe Kerello 	if (enable)
417*33c8cf42SChristophe Kerello 		pcr |= FMC2_PCR_ECCEN;
418*33c8cf42SChristophe Kerello 	writel(pcr, fmc2->io_base + FMC2_PCR);
419*33c8cf42SChristophe Kerello }
420*33c8cf42SChristophe Kerello 
4212cd457f3SChristophe Kerello /* Enable irq sources in case of the sequencer is used */
4222cd457f3SChristophe Kerello static inline void stm32_fmc2_enable_seq_irq(struct stm32_fmc2_nfc *fmc2)
4232cd457f3SChristophe Kerello {
4242cd457f3SChristophe Kerello 	u32 csqier = readl_relaxed(fmc2->io_base + FMC2_CSQIER);
4252cd457f3SChristophe Kerello 
4262cd457f3SChristophe Kerello 	csqier |= FMC2_CSQIER_TCIE;
4272cd457f3SChristophe Kerello 
428*33c8cf42SChristophe Kerello 	fmc2->irq_state = FMC2_IRQ_SEQ;
429*33c8cf42SChristophe Kerello 
4302cd457f3SChristophe Kerello 	writel_relaxed(csqier, fmc2->io_base + FMC2_CSQIER);
4312cd457f3SChristophe Kerello }
4322cd457f3SChristophe Kerello 
4332cd457f3SChristophe Kerello /* Disable irq sources in case of the sequencer is used */
4342cd457f3SChristophe Kerello static inline void stm32_fmc2_disable_seq_irq(struct stm32_fmc2_nfc *fmc2)
4352cd457f3SChristophe Kerello {
4362cd457f3SChristophe Kerello 	u32 csqier = readl_relaxed(fmc2->io_base + FMC2_CSQIER);
4372cd457f3SChristophe Kerello 
4382cd457f3SChristophe Kerello 	csqier &= ~FMC2_CSQIER_TCIE;
4392cd457f3SChristophe Kerello 
4402cd457f3SChristophe Kerello 	writel_relaxed(csqier, fmc2->io_base + FMC2_CSQIER);
441*33c8cf42SChristophe Kerello 
442*33c8cf42SChristophe Kerello 	fmc2->irq_state = FMC2_IRQ_UNKNOWN;
4432cd457f3SChristophe Kerello }
4442cd457f3SChristophe Kerello 
4452cd457f3SChristophe Kerello /* Clear irq sources in case of the sequencer is used */
4462cd457f3SChristophe Kerello static inline void stm32_fmc2_clear_seq_irq(struct stm32_fmc2_nfc *fmc2)
4472cd457f3SChristophe Kerello {
4482cd457f3SChristophe Kerello 	writel_relaxed(FMC2_CSQICR_CLEAR_IRQ, fmc2->io_base + FMC2_CSQICR);
4492cd457f3SChristophe Kerello }
4502cd457f3SChristophe Kerello 
451*33c8cf42SChristophe Kerello /* Enable irq sources in case of bch is used */
452*33c8cf42SChristophe Kerello static inline void stm32_fmc2_enable_bch_irq(struct stm32_fmc2_nfc *fmc2,
453*33c8cf42SChristophe Kerello 					     int mode)
454*33c8cf42SChristophe Kerello {
455*33c8cf42SChristophe Kerello 	u32 bchier = readl_relaxed(fmc2->io_base + FMC2_BCHIER);
456*33c8cf42SChristophe Kerello 
457*33c8cf42SChristophe Kerello 	if (mode == NAND_ECC_WRITE)
458*33c8cf42SChristophe Kerello 		bchier |= FMC2_BCHIER_EPBRIE;
459*33c8cf42SChristophe Kerello 	else
460*33c8cf42SChristophe Kerello 		bchier |= FMC2_BCHIER_DERIE;
461*33c8cf42SChristophe Kerello 
462*33c8cf42SChristophe Kerello 	fmc2->irq_state = FMC2_IRQ_BCH;
463*33c8cf42SChristophe Kerello 
464*33c8cf42SChristophe Kerello 	writel_relaxed(bchier, fmc2->io_base + FMC2_BCHIER);
465*33c8cf42SChristophe Kerello }
466*33c8cf42SChristophe Kerello 
467*33c8cf42SChristophe Kerello /* Disable irq sources in case of bch is used */
468*33c8cf42SChristophe Kerello static inline void stm32_fmc2_disable_bch_irq(struct stm32_fmc2_nfc *fmc2)
469*33c8cf42SChristophe Kerello {
470*33c8cf42SChristophe Kerello 	u32 bchier = readl_relaxed(fmc2->io_base + FMC2_BCHIER);
471*33c8cf42SChristophe Kerello 
472*33c8cf42SChristophe Kerello 	bchier &= ~FMC2_BCHIER_DERIE;
473*33c8cf42SChristophe Kerello 	bchier &= ~FMC2_BCHIER_EPBRIE;
474*33c8cf42SChristophe Kerello 
475*33c8cf42SChristophe Kerello 	writel_relaxed(bchier, fmc2->io_base + FMC2_BCHIER);
476*33c8cf42SChristophe Kerello 
477*33c8cf42SChristophe Kerello 	fmc2->irq_state = FMC2_IRQ_UNKNOWN;
478*33c8cf42SChristophe Kerello }
479*33c8cf42SChristophe Kerello 
480*33c8cf42SChristophe Kerello /* Clear irq sources in case of bch is used */
481*33c8cf42SChristophe Kerello static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
482*33c8cf42SChristophe Kerello {
483*33c8cf42SChristophe Kerello 	writel_relaxed(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
484*33c8cf42SChristophe Kerello }
485*33c8cf42SChristophe Kerello 
486*33c8cf42SChristophe Kerello /*
487*33c8cf42SChristophe Kerello  * Enable ECC logic and reset syndrome/parity bits previously calculated
488*33c8cf42SChristophe Kerello  * Syndrome/parity bits is cleared by setting the ECCEN bit to 0
489*33c8cf42SChristophe Kerello  */
490*33c8cf42SChristophe Kerello static void stm32_fmc2_hwctl(struct nand_chip *chip, int mode)
491*33c8cf42SChristophe Kerello {
492*33c8cf42SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
493*33c8cf42SChristophe Kerello 
494*33c8cf42SChristophe Kerello 	stm32_fmc2_set_ecc(fmc2, false);
495*33c8cf42SChristophe Kerello 
496*33c8cf42SChristophe Kerello 	if (chip->ecc.strength != FMC2_ECC_HAM) {
497*33c8cf42SChristophe Kerello 		u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
498*33c8cf42SChristophe Kerello 
499*33c8cf42SChristophe Kerello 		if (mode == NAND_ECC_WRITE)
500*33c8cf42SChristophe Kerello 			pcr |= FMC2_PCR_WEN;
501*33c8cf42SChristophe Kerello 		else
502*33c8cf42SChristophe Kerello 			pcr &= ~FMC2_PCR_WEN;
503*33c8cf42SChristophe Kerello 		writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
504*33c8cf42SChristophe Kerello 
505*33c8cf42SChristophe Kerello 		reinit_completion(&fmc2->complete);
506*33c8cf42SChristophe Kerello 		stm32_fmc2_clear_bch_irq(fmc2);
507*33c8cf42SChristophe Kerello 		stm32_fmc2_enable_bch_irq(fmc2, mode);
508*33c8cf42SChristophe Kerello 	}
509*33c8cf42SChristophe Kerello 
510*33c8cf42SChristophe Kerello 	stm32_fmc2_set_ecc(fmc2, true);
511*33c8cf42SChristophe Kerello }
512*33c8cf42SChristophe Kerello 
5132cd457f3SChristophe Kerello /*
5142cd457f3SChristophe Kerello  * ECC Hamming calculation
5152cd457f3SChristophe Kerello  * ECC is 3 bytes for 512 bytes of data (supports error correction up to
5162cd457f3SChristophe Kerello  * max of 1-bit)
5172cd457f3SChristophe Kerello  */
5182cd457f3SChristophe Kerello static inline void stm32_fmc2_ham_set_ecc(const u32 ecc_sta, u8 *ecc)
5192cd457f3SChristophe Kerello {
5202cd457f3SChristophe Kerello 	ecc[0] = ecc_sta;
5212cd457f3SChristophe Kerello 	ecc[1] = ecc_sta >> 8;
5222cd457f3SChristophe Kerello 	ecc[2] = ecc_sta >> 16;
5232cd457f3SChristophe Kerello }
5242cd457f3SChristophe Kerello 
525*33c8cf42SChristophe Kerello static int stm32_fmc2_ham_calculate(struct nand_chip *chip, const u8 *data,
526*33c8cf42SChristophe Kerello 				    u8 *ecc)
527*33c8cf42SChristophe Kerello {
528*33c8cf42SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
529*33c8cf42SChristophe Kerello 	u32 sr, heccr;
530*33c8cf42SChristophe Kerello 	int ret;
531*33c8cf42SChristophe Kerello 
532*33c8cf42SChristophe Kerello 	ret = readl_relaxed_poll_timeout(fmc2->io_base + FMC2_SR,
533*33c8cf42SChristophe Kerello 					 sr, sr & FMC2_SR_NWRF, 10, 1000);
534*33c8cf42SChristophe Kerello 	if (ret) {
535*33c8cf42SChristophe Kerello 		dev_err(fmc2->dev, "ham timeout\n");
536*33c8cf42SChristophe Kerello 		return ret;
537*33c8cf42SChristophe Kerello 	}
538*33c8cf42SChristophe Kerello 
539*33c8cf42SChristophe Kerello 	heccr = readl_relaxed(fmc2->io_base + FMC2_HECCR);
540*33c8cf42SChristophe Kerello 
541*33c8cf42SChristophe Kerello 	stm32_fmc2_ham_set_ecc(heccr, ecc);
542*33c8cf42SChristophe Kerello 
543*33c8cf42SChristophe Kerello 	/* Disable ECC */
544*33c8cf42SChristophe Kerello 	stm32_fmc2_set_ecc(fmc2, false);
545*33c8cf42SChristophe Kerello 
546*33c8cf42SChristophe Kerello 	return 0;
547*33c8cf42SChristophe Kerello }
548*33c8cf42SChristophe Kerello 
5492cd457f3SChristophe Kerello static int stm32_fmc2_ham_correct(struct nand_chip *chip, u8 *dat,
5502cd457f3SChristophe Kerello 				  u8 *read_ecc, u8 *calc_ecc)
5512cd457f3SChristophe Kerello {
5522cd457f3SChristophe Kerello 	u8 bit_position = 0, b0, b1, b2;
5532cd457f3SChristophe Kerello 	u32 byte_addr = 0, b;
5542cd457f3SChristophe Kerello 	u32 i, shifting = 1;
5552cd457f3SChristophe Kerello 
5562cd457f3SChristophe Kerello 	/* Indicate which bit and byte is faulty (if any) */
5572cd457f3SChristophe Kerello 	b0 = read_ecc[0] ^ calc_ecc[0];
5582cd457f3SChristophe Kerello 	b1 = read_ecc[1] ^ calc_ecc[1];
5592cd457f3SChristophe Kerello 	b2 = read_ecc[2] ^ calc_ecc[2];
5602cd457f3SChristophe Kerello 	b = b0 | (b1 << 8) | (b2 << 16);
5612cd457f3SChristophe Kerello 
5622cd457f3SChristophe Kerello 	/* No errors */
5632cd457f3SChristophe Kerello 	if (likely(!b))
5642cd457f3SChristophe Kerello 		return 0;
5652cd457f3SChristophe Kerello 
5662cd457f3SChristophe Kerello 	/* Calculate bit position */
5672cd457f3SChristophe Kerello 	for (i = 0; i < 3; i++) {
5682cd457f3SChristophe Kerello 		switch (b % 4) {
5692cd457f3SChristophe Kerello 		case 2:
5702cd457f3SChristophe Kerello 			bit_position += shifting;
5712cd457f3SChristophe Kerello 		case 1:
5722cd457f3SChristophe Kerello 			break;
5732cd457f3SChristophe Kerello 		default:
5742cd457f3SChristophe Kerello 			return -EBADMSG;
5752cd457f3SChristophe Kerello 		}
5762cd457f3SChristophe Kerello 		shifting <<= 1;
5772cd457f3SChristophe Kerello 		b >>= 2;
5782cd457f3SChristophe Kerello 	}
5792cd457f3SChristophe Kerello 
5802cd457f3SChristophe Kerello 	/* Calculate byte position */
5812cd457f3SChristophe Kerello 	shifting = 1;
5822cd457f3SChristophe Kerello 	for (i = 0; i < 9; i++) {
5832cd457f3SChristophe Kerello 		switch (b % 4) {
5842cd457f3SChristophe Kerello 		case 2:
5852cd457f3SChristophe Kerello 			byte_addr += shifting;
5862cd457f3SChristophe Kerello 		case 1:
5872cd457f3SChristophe Kerello 			break;
5882cd457f3SChristophe Kerello 		default:
5892cd457f3SChristophe Kerello 			return -EBADMSG;
5902cd457f3SChristophe Kerello 		}
5912cd457f3SChristophe Kerello 		shifting <<= 1;
5922cd457f3SChristophe Kerello 		b >>= 2;
5932cd457f3SChristophe Kerello 	}
5942cd457f3SChristophe Kerello 
5952cd457f3SChristophe Kerello 	/* Flip the bit */
5962cd457f3SChristophe Kerello 	dat[byte_addr] ^= (1 << bit_position);
5972cd457f3SChristophe Kerello 
5982cd457f3SChristophe Kerello 	return 1;
5992cd457f3SChristophe Kerello }
6002cd457f3SChristophe Kerello 
601*33c8cf42SChristophe Kerello /*
602*33c8cf42SChristophe Kerello  * ECC BCH calculation and correction
603*33c8cf42SChristophe Kerello  * ECC is 7/13 bytes for 512 bytes of data (supports error correction up to
604*33c8cf42SChristophe Kerello  * max of 4-bit/8-bit)
605*33c8cf42SChristophe Kerello  */
606*33c8cf42SChristophe Kerello static int stm32_fmc2_bch_calculate(struct nand_chip *chip, const u8 *data,
607*33c8cf42SChristophe Kerello 				    u8 *ecc)
608*33c8cf42SChristophe Kerello {
609*33c8cf42SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
610*33c8cf42SChristophe Kerello 	u32 bchpbr;
611*33c8cf42SChristophe Kerello 
612*33c8cf42SChristophe Kerello 	/* Wait until the BCH code is ready */
613*33c8cf42SChristophe Kerello 	if (!wait_for_completion_timeout(&fmc2->complete,
614*33c8cf42SChristophe Kerello 					 msecs_to_jiffies(1000))) {
615*33c8cf42SChristophe Kerello 		dev_err(fmc2->dev, "bch timeout\n");
616*33c8cf42SChristophe Kerello 		stm32_fmc2_disable_bch_irq(fmc2);
617*33c8cf42SChristophe Kerello 		return -ETIMEDOUT;
618*33c8cf42SChristophe Kerello 	}
619*33c8cf42SChristophe Kerello 
620*33c8cf42SChristophe Kerello 	/* Read parity bits */
621*33c8cf42SChristophe Kerello 	bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR1);
622*33c8cf42SChristophe Kerello 	ecc[0] = bchpbr;
623*33c8cf42SChristophe Kerello 	ecc[1] = bchpbr >> 8;
624*33c8cf42SChristophe Kerello 	ecc[2] = bchpbr >> 16;
625*33c8cf42SChristophe Kerello 	ecc[3] = bchpbr >> 24;
626*33c8cf42SChristophe Kerello 
627*33c8cf42SChristophe Kerello 	bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR2);
628*33c8cf42SChristophe Kerello 	ecc[4] = bchpbr;
629*33c8cf42SChristophe Kerello 	ecc[5] = bchpbr >> 8;
630*33c8cf42SChristophe Kerello 	ecc[6] = bchpbr >> 16;
631*33c8cf42SChristophe Kerello 
632*33c8cf42SChristophe Kerello 	if (chip->ecc.strength == FMC2_ECC_BCH8) {
633*33c8cf42SChristophe Kerello 		ecc[7] = bchpbr >> 24;
634*33c8cf42SChristophe Kerello 
635*33c8cf42SChristophe Kerello 		bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR3);
636*33c8cf42SChristophe Kerello 		ecc[8] = bchpbr;
637*33c8cf42SChristophe Kerello 		ecc[9] = bchpbr >> 8;
638*33c8cf42SChristophe Kerello 		ecc[10] = bchpbr >> 16;
639*33c8cf42SChristophe Kerello 		ecc[11] = bchpbr >> 24;
640*33c8cf42SChristophe Kerello 
641*33c8cf42SChristophe Kerello 		bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR4);
642*33c8cf42SChristophe Kerello 		ecc[12] = bchpbr;
643*33c8cf42SChristophe Kerello 	}
644*33c8cf42SChristophe Kerello 
645*33c8cf42SChristophe Kerello 	/* Disable ECC */
646*33c8cf42SChristophe Kerello 	stm32_fmc2_set_ecc(fmc2, false);
647*33c8cf42SChristophe Kerello 
648*33c8cf42SChristophe Kerello 	return 0;
649*33c8cf42SChristophe Kerello }
650*33c8cf42SChristophe Kerello 
6512cd457f3SChristophe Kerello /* BCH algorithm correction */
6522cd457f3SChristophe Kerello static int stm32_fmc2_bch_decode(int eccsize, u8 *dat, u32 *ecc_sta)
6532cd457f3SChristophe Kerello {
6542cd457f3SChristophe Kerello 	u32 bchdsr0 = ecc_sta[0];
6552cd457f3SChristophe Kerello 	u32 bchdsr1 = ecc_sta[1];
6562cd457f3SChristophe Kerello 	u32 bchdsr2 = ecc_sta[2];
6572cd457f3SChristophe Kerello 	u32 bchdsr3 = ecc_sta[3];
6582cd457f3SChristophe Kerello 	u32 bchdsr4 = ecc_sta[4];
6592cd457f3SChristophe Kerello 	u16 pos[8];
6602cd457f3SChristophe Kerello 	int i, den;
6612cd457f3SChristophe Kerello 	unsigned int nb_errs = 0;
6622cd457f3SChristophe Kerello 
6632cd457f3SChristophe Kerello 	/* No errors found */
6642cd457f3SChristophe Kerello 	if (likely(!(bchdsr0 & FMC2_BCHDSR0_DEF)))
6652cd457f3SChristophe Kerello 		return 0;
6662cd457f3SChristophe Kerello 
6672cd457f3SChristophe Kerello 	/* Too many errors detected */
6682cd457f3SChristophe Kerello 	if (unlikely(bchdsr0 & FMC2_BCHDSR0_DUE))
6692cd457f3SChristophe Kerello 		return -EBADMSG;
6702cd457f3SChristophe Kerello 
6712cd457f3SChristophe Kerello 	pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK;
6722cd457f3SChristophe Kerello 	pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT;
6732cd457f3SChristophe Kerello 	pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK;
6742cd457f3SChristophe Kerello 	pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT;
6752cd457f3SChristophe Kerello 	pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK;
6762cd457f3SChristophe Kerello 	pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT;
6772cd457f3SChristophe Kerello 	pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK;
6782cd457f3SChristophe Kerello 	pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT;
6792cd457f3SChristophe Kerello 
6802cd457f3SChristophe Kerello 	den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT;
6812cd457f3SChristophe Kerello 	for (i = 0; i < den; i++) {
6822cd457f3SChristophe Kerello 		if (pos[i] < eccsize * 8) {
6832cd457f3SChristophe Kerello 			change_bit(pos[i], (unsigned long *)dat);
6842cd457f3SChristophe Kerello 			nb_errs++;
6852cd457f3SChristophe Kerello 		}
6862cd457f3SChristophe Kerello 	}
6872cd457f3SChristophe Kerello 
6882cd457f3SChristophe Kerello 	return nb_errs;
6892cd457f3SChristophe Kerello }
6902cd457f3SChristophe Kerello 
691*33c8cf42SChristophe Kerello static int stm32_fmc2_bch_correct(struct nand_chip *chip, u8 *dat,
692*33c8cf42SChristophe Kerello 				  u8 *read_ecc, u8 *calc_ecc)
693*33c8cf42SChristophe Kerello {
694*33c8cf42SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
695*33c8cf42SChristophe Kerello 	u32 ecc_sta[5];
696*33c8cf42SChristophe Kerello 
697*33c8cf42SChristophe Kerello 	/* Wait until the decoding error is ready */
698*33c8cf42SChristophe Kerello 	if (!wait_for_completion_timeout(&fmc2->complete,
699*33c8cf42SChristophe Kerello 					 msecs_to_jiffies(1000))) {
700*33c8cf42SChristophe Kerello 		dev_err(fmc2->dev, "bch timeout\n");
701*33c8cf42SChristophe Kerello 		stm32_fmc2_disable_bch_irq(fmc2);
702*33c8cf42SChristophe Kerello 		return -ETIMEDOUT;
703*33c8cf42SChristophe Kerello 	}
704*33c8cf42SChristophe Kerello 
705*33c8cf42SChristophe Kerello 	ecc_sta[0] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR0);
706*33c8cf42SChristophe Kerello 	ecc_sta[1] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR1);
707*33c8cf42SChristophe Kerello 	ecc_sta[2] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR2);
708*33c8cf42SChristophe Kerello 	ecc_sta[3] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR3);
709*33c8cf42SChristophe Kerello 	ecc_sta[4] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR4);
710*33c8cf42SChristophe Kerello 
711*33c8cf42SChristophe Kerello 	/* Disable ECC */
712*33c8cf42SChristophe Kerello 	stm32_fmc2_set_ecc(fmc2, false);
713*33c8cf42SChristophe Kerello 
714*33c8cf42SChristophe Kerello 	return stm32_fmc2_bch_decode(chip->ecc.size, dat, ecc_sta);
715*33c8cf42SChristophe Kerello }
716*33c8cf42SChristophe Kerello 
717*33c8cf42SChristophe Kerello static int stm32_fmc2_read_page(struct nand_chip *chip, u8 *buf,
718*33c8cf42SChristophe Kerello 				int oob_required, int page)
719*33c8cf42SChristophe Kerello {
720*33c8cf42SChristophe Kerello 	struct mtd_info *mtd = nand_to_mtd(chip);
721*33c8cf42SChristophe Kerello 	int ret, i, s, stat, eccsize = chip->ecc.size;
722*33c8cf42SChristophe Kerello 	int eccbytes = chip->ecc.bytes;
723*33c8cf42SChristophe Kerello 	int eccsteps = chip->ecc.steps;
724*33c8cf42SChristophe Kerello 	int eccstrength = chip->ecc.strength;
725*33c8cf42SChristophe Kerello 	u8 *p = buf;
726*33c8cf42SChristophe Kerello 	u8 *ecc_calc = chip->ecc.calc_buf;
727*33c8cf42SChristophe Kerello 	u8 *ecc_code = chip->ecc.code_buf;
728*33c8cf42SChristophe Kerello 	unsigned int max_bitflips = 0;
729*33c8cf42SChristophe Kerello 
730*33c8cf42SChristophe Kerello 	ret = nand_read_page_op(chip, page, 0, NULL, 0);
731*33c8cf42SChristophe Kerello 	if (ret)
732*33c8cf42SChristophe Kerello 		return ret;
733*33c8cf42SChristophe Kerello 
734*33c8cf42SChristophe Kerello 	for (i = mtd->writesize + FMC2_BBM_LEN, s = 0; s < eccsteps;
735*33c8cf42SChristophe Kerello 	     s++, i += eccbytes, p += eccsize) {
736*33c8cf42SChristophe Kerello 		chip->ecc.hwctl(chip, NAND_ECC_READ);
737*33c8cf42SChristophe Kerello 
738*33c8cf42SChristophe Kerello 		/* Read the nand page sector (512 bytes) */
739*33c8cf42SChristophe Kerello 		ret = nand_change_read_column_op(chip, s * eccsize, p,
740*33c8cf42SChristophe Kerello 						 eccsize, false);
741*33c8cf42SChristophe Kerello 		if (ret)
742*33c8cf42SChristophe Kerello 			return ret;
743*33c8cf42SChristophe Kerello 
744*33c8cf42SChristophe Kerello 		/* Read the corresponding ECC bytes */
745*33c8cf42SChristophe Kerello 		ret = nand_change_read_column_op(chip, i, ecc_code,
746*33c8cf42SChristophe Kerello 						 eccbytes, false);
747*33c8cf42SChristophe Kerello 		if (ret)
748*33c8cf42SChristophe Kerello 			return ret;
749*33c8cf42SChristophe Kerello 
750*33c8cf42SChristophe Kerello 		/* Correct the data */
751*33c8cf42SChristophe Kerello 		stat = chip->ecc.correct(chip, p, ecc_code, ecc_calc);
752*33c8cf42SChristophe Kerello 		if (stat == -EBADMSG)
753*33c8cf42SChristophe Kerello 			/* Check for empty pages with bitflips */
754*33c8cf42SChristophe Kerello 			stat = nand_check_erased_ecc_chunk(p, eccsize,
755*33c8cf42SChristophe Kerello 							   ecc_code, eccbytes,
756*33c8cf42SChristophe Kerello 							   NULL, 0,
757*33c8cf42SChristophe Kerello 							   eccstrength);
758*33c8cf42SChristophe Kerello 
759*33c8cf42SChristophe Kerello 		if (stat < 0) {
760*33c8cf42SChristophe Kerello 			mtd->ecc_stats.failed++;
761*33c8cf42SChristophe Kerello 		} else {
762*33c8cf42SChristophe Kerello 			mtd->ecc_stats.corrected += stat;
763*33c8cf42SChristophe Kerello 			max_bitflips = max_t(unsigned int, max_bitflips, stat);
764*33c8cf42SChristophe Kerello 		}
765*33c8cf42SChristophe Kerello 	}
766*33c8cf42SChristophe Kerello 
767*33c8cf42SChristophe Kerello 	/* Read oob */
768*33c8cf42SChristophe Kerello 	if (oob_required) {
769*33c8cf42SChristophe Kerello 		ret = nand_change_read_column_op(chip, mtd->writesize,
770*33c8cf42SChristophe Kerello 						 chip->oob_poi, mtd->oobsize,
771*33c8cf42SChristophe Kerello 						 false);
772*33c8cf42SChristophe Kerello 		if (ret)
773*33c8cf42SChristophe Kerello 			return ret;
774*33c8cf42SChristophe Kerello 	}
775*33c8cf42SChristophe Kerello 
776*33c8cf42SChristophe Kerello 	return max_bitflips;
777*33c8cf42SChristophe Kerello }
778*33c8cf42SChristophe Kerello 
7792cd457f3SChristophe Kerello /* Sequencer read/write configuration */
7802cd457f3SChristophe Kerello static void stm32_fmc2_rw_page_init(struct nand_chip *chip, int page,
7812cd457f3SChristophe Kerello 				    int raw, bool write_data)
7822cd457f3SChristophe Kerello {
7832cd457f3SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
7842cd457f3SChristophe Kerello 	struct mtd_info *mtd = nand_to_mtd(chip);
7852cd457f3SChristophe Kerello 	u32 csqcfgr1, csqcfgr2, csqcfgr3;
7862cd457f3SChristophe Kerello 	u32 csqar1, csqar2;
7872cd457f3SChristophe Kerello 	u32 ecc_offset = mtd->writesize + FMC2_BBM_LEN;
7882cd457f3SChristophe Kerello 	u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
7892cd457f3SChristophe Kerello 
7902cd457f3SChristophe Kerello 	if (write_data)
7912cd457f3SChristophe Kerello 		pcr |= FMC2_PCR_WEN;
7922cd457f3SChristophe Kerello 	else
7932cd457f3SChristophe Kerello 		pcr &= ~FMC2_PCR_WEN;
7942cd457f3SChristophe Kerello 	writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
7952cd457f3SChristophe Kerello 
7962cd457f3SChristophe Kerello 	/*
7972cd457f3SChristophe Kerello 	 * - Set Program Page/Page Read command
7982cd457f3SChristophe Kerello 	 * - Enable DMA request data
7992cd457f3SChristophe Kerello 	 * - Set timings
8002cd457f3SChristophe Kerello 	 */
8012cd457f3SChristophe Kerello 	csqcfgr1 = FMC2_CSQCFGR1_DMADEN | FMC2_CSQCFGR1_CMD1T;
8022cd457f3SChristophe Kerello 	if (write_data)
8032cd457f3SChristophe Kerello 		csqcfgr1 |= FMC2_CSQCFGR1_CMD1(NAND_CMD_SEQIN);
8042cd457f3SChristophe Kerello 	else
8052cd457f3SChristophe Kerello 		csqcfgr1 |= FMC2_CSQCFGR1_CMD1(NAND_CMD_READ0) |
8062cd457f3SChristophe Kerello 			    FMC2_CSQCFGR1_CMD2EN |
8072cd457f3SChristophe Kerello 			    FMC2_CSQCFGR1_CMD2(NAND_CMD_READSTART) |
8082cd457f3SChristophe Kerello 			    FMC2_CSQCFGR1_CMD2T;
8092cd457f3SChristophe Kerello 
8102cd457f3SChristophe Kerello 	/*
8112cd457f3SChristophe Kerello 	 * - Set Random Data Input/Random Data Read command
8122cd457f3SChristophe Kerello 	 * - Enable the sequencer to access the Spare data area
8132cd457f3SChristophe Kerello 	 * - Enable  DMA request status decoding for read
8142cd457f3SChristophe Kerello 	 * - Set timings
8152cd457f3SChristophe Kerello 	 */
8162cd457f3SChristophe Kerello 	if (write_data)
8172cd457f3SChristophe Kerello 		csqcfgr2 = FMC2_CSQCFGR2_RCMD1(NAND_CMD_RNDIN);
8182cd457f3SChristophe Kerello 	else
8192cd457f3SChristophe Kerello 		csqcfgr2 = FMC2_CSQCFGR2_RCMD1(NAND_CMD_RNDOUT) |
8202cd457f3SChristophe Kerello 			   FMC2_CSQCFGR2_RCMD2EN |
8212cd457f3SChristophe Kerello 			   FMC2_CSQCFGR2_RCMD2(NAND_CMD_RNDOUTSTART) |
8222cd457f3SChristophe Kerello 			   FMC2_CSQCFGR2_RCMD1T |
8232cd457f3SChristophe Kerello 			   FMC2_CSQCFGR2_RCMD2T;
8242cd457f3SChristophe Kerello 	if (!raw) {
8252cd457f3SChristophe Kerello 		csqcfgr2 |= write_data ? 0 : FMC2_CSQCFGR2_DMASEN;
8262cd457f3SChristophe Kerello 		csqcfgr2 |= FMC2_CSQCFGR2_SQSDTEN;
8272cd457f3SChristophe Kerello 	}
8282cd457f3SChristophe Kerello 
8292cd457f3SChristophe Kerello 	/*
8302cd457f3SChristophe Kerello 	 * - Set the number of sectors to be written
8312cd457f3SChristophe Kerello 	 * - Set timings
8322cd457f3SChristophe Kerello 	 */
8332cd457f3SChristophe Kerello 	csqcfgr3 = FMC2_CSQCFGR3_SNBR(chip->ecc.steps - 1);
8342cd457f3SChristophe Kerello 	if (write_data) {
8352cd457f3SChristophe Kerello 		csqcfgr3 |= FMC2_CSQCFGR3_RAC2T;
8362cd457f3SChristophe Kerello 		if (chip->options & NAND_ROW_ADDR_3)
8372cd457f3SChristophe Kerello 			csqcfgr3 |= FMC2_CSQCFGR3_AC5T;
8382cd457f3SChristophe Kerello 		else
8392cd457f3SChristophe Kerello 			csqcfgr3 |= FMC2_CSQCFGR3_AC4T;
8402cd457f3SChristophe Kerello 	}
8412cd457f3SChristophe Kerello 
8422cd457f3SChristophe Kerello 	/*
8432cd457f3SChristophe Kerello 	 * Set the fourth first address cycles
8442cd457f3SChristophe Kerello 	 * Byte 1 and byte 2 => column, we start at 0x0
8452cd457f3SChristophe Kerello 	 * Byte 3 and byte 4 => page
8462cd457f3SChristophe Kerello 	 */
8472cd457f3SChristophe Kerello 	csqar1 = FMC2_CSQCAR1_ADDC3(page);
8482cd457f3SChristophe Kerello 	csqar1 |= FMC2_CSQCAR1_ADDC4(page >> 8);
8492cd457f3SChristophe Kerello 
8502cd457f3SChristophe Kerello 	/*
8512cd457f3SChristophe Kerello 	 * - Set chip enable number
8522cd457f3SChristophe Kerello 	 * - Set ECC byte offset in the spare area
8532cd457f3SChristophe Kerello 	 * - Calculate the number of address cycles to be issued
8542cd457f3SChristophe Kerello 	 * - Set byte 5 of address cycle if needed
8552cd457f3SChristophe Kerello 	 */
8562cd457f3SChristophe Kerello 	csqar2 = FMC2_CSQCAR2_NANDCEN(fmc2->cs_sel);
8572cd457f3SChristophe Kerello 	if (chip->options & NAND_BUSWIDTH_16)
8582cd457f3SChristophe Kerello 		csqar2 |= FMC2_CSQCAR2_SAO(ecc_offset >> 1);
8592cd457f3SChristophe Kerello 	else
8602cd457f3SChristophe Kerello 		csqar2 |= FMC2_CSQCAR2_SAO(ecc_offset);
8612cd457f3SChristophe Kerello 	if (chip->options & NAND_ROW_ADDR_3) {
8622cd457f3SChristophe Kerello 		csqcfgr1 |= FMC2_CSQCFGR1_ACYNBR(5);
8632cd457f3SChristophe Kerello 		csqar2 |= FMC2_CSQCAR2_ADDC5(page >> 16);
8642cd457f3SChristophe Kerello 	} else {
8652cd457f3SChristophe Kerello 		csqcfgr1 |= FMC2_CSQCFGR1_ACYNBR(4);
8662cd457f3SChristophe Kerello 	}
8672cd457f3SChristophe Kerello 
8682cd457f3SChristophe Kerello 	writel_relaxed(csqcfgr1, fmc2->io_base + FMC2_CSQCFGR1);
8692cd457f3SChristophe Kerello 	writel_relaxed(csqcfgr2, fmc2->io_base + FMC2_CSQCFGR2);
8702cd457f3SChristophe Kerello 	writel_relaxed(csqcfgr3, fmc2->io_base + FMC2_CSQCFGR3);
8712cd457f3SChristophe Kerello 	writel_relaxed(csqar1, fmc2->io_base + FMC2_CSQAR1);
8722cd457f3SChristophe Kerello 	writel_relaxed(csqar2, fmc2->io_base + FMC2_CSQAR2);
8732cd457f3SChristophe Kerello }
8742cd457f3SChristophe Kerello 
8752cd457f3SChristophe Kerello static void stm32_fmc2_dma_callback(void *arg)
8762cd457f3SChristophe Kerello {
8772cd457f3SChristophe Kerello 	complete((struct completion *)arg);
8782cd457f3SChristophe Kerello }
8792cd457f3SChristophe Kerello 
8802cd457f3SChristophe Kerello /* Read/write data from/to a page */
8812cd457f3SChristophe Kerello static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf,
8822cd457f3SChristophe Kerello 			   int raw, bool write_data)
8832cd457f3SChristophe Kerello {
8842cd457f3SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
8852cd457f3SChristophe Kerello 	struct dma_async_tx_descriptor *desc_data, *desc_ecc;
8862cd457f3SChristophe Kerello 	struct scatterlist *sg;
8872cd457f3SChristophe Kerello 	struct dma_chan *dma_ch = fmc2->dma_rx_ch;
8882cd457f3SChristophe Kerello 	enum dma_data_direction dma_data_dir = DMA_FROM_DEVICE;
8892cd457f3SChristophe Kerello 	enum dma_transfer_direction dma_transfer_dir = DMA_DEV_TO_MEM;
8902cd457f3SChristophe Kerello 	u32 csqcr = readl_relaxed(fmc2->io_base + FMC2_CSQCR);
8912cd457f3SChristophe Kerello 	int eccsteps = chip->ecc.steps;
8922cd457f3SChristophe Kerello 	int eccsize = chip->ecc.size;
8932cd457f3SChristophe Kerello 	const u8 *p = buf;
8942cd457f3SChristophe Kerello 	int s, ret;
8952cd457f3SChristophe Kerello 
8962cd457f3SChristophe Kerello 	/* Configure DMA data */
8972cd457f3SChristophe Kerello 	if (write_data) {
8982cd457f3SChristophe Kerello 		dma_data_dir = DMA_TO_DEVICE;
8992cd457f3SChristophe Kerello 		dma_transfer_dir = DMA_MEM_TO_DEV;
9002cd457f3SChristophe Kerello 		dma_ch = fmc2->dma_tx_ch;
9012cd457f3SChristophe Kerello 	}
9022cd457f3SChristophe Kerello 
9032cd457f3SChristophe Kerello 	for_each_sg(fmc2->dma_data_sg.sgl, sg, eccsteps, s) {
9042cd457f3SChristophe Kerello 		sg_set_buf(sg, p, eccsize);
9052cd457f3SChristophe Kerello 		p += eccsize;
9062cd457f3SChristophe Kerello 	}
9072cd457f3SChristophe Kerello 
9082cd457f3SChristophe Kerello 	ret = dma_map_sg(fmc2->dev, fmc2->dma_data_sg.sgl,
9092cd457f3SChristophe Kerello 			 eccsteps, dma_data_dir);
9102cd457f3SChristophe Kerello 	if (ret < 0)
9112cd457f3SChristophe Kerello 		return ret;
9122cd457f3SChristophe Kerello 
9132cd457f3SChristophe Kerello 	desc_data = dmaengine_prep_slave_sg(dma_ch, fmc2->dma_data_sg.sgl,
9142cd457f3SChristophe Kerello 					    eccsteps, dma_transfer_dir,
9152cd457f3SChristophe Kerello 					    DMA_PREP_INTERRUPT);
9162cd457f3SChristophe Kerello 	if (!desc_data) {
9172cd457f3SChristophe Kerello 		ret = -ENOMEM;
9182cd457f3SChristophe Kerello 		goto err_unmap_data;
9192cd457f3SChristophe Kerello 	}
9202cd457f3SChristophe Kerello 
9212cd457f3SChristophe Kerello 	reinit_completion(&fmc2->dma_data_complete);
9222cd457f3SChristophe Kerello 	reinit_completion(&fmc2->complete);
9232cd457f3SChristophe Kerello 	desc_data->callback = stm32_fmc2_dma_callback;
9242cd457f3SChristophe Kerello 	desc_data->callback_param = &fmc2->dma_data_complete;
9252cd457f3SChristophe Kerello 	ret = dma_submit_error(dmaengine_submit(desc_data));
9262cd457f3SChristophe Kerello 	if (ret)
9272cd457f3SChristophe Kerello 		goto err_unmap_data;
9282cd457f3SChristophe Kerello 
9292cd457f3SChristophe Kerello 	dma_async_issue_pending(dma_ch);
9302cd457f3SChristophe Kerello 
9312cd457f3SChristophe Kerello 	if (!write_data && !raw) {
9322cd457f3SChristophe Kerello 		/* Configure DMA ECC status */
9332cd457f3SChristophe Kerello 		p = fmc2->ecc_buf;
9342cd457f3SChristophe Kerello 		for_each_sg(fmc2->dma_ecc_sg.sgl, sg, eccsteps, s) {
9352cd457f3SChristophe Kerello 			sg_set_buf(sg, p, fmc2->dma_ecc_len);
9362cd457f3SChristophe Kerello 			p += fmc2->dma_ecc_len;
9372cd457f3SChristophe Kerello 		}
9382cd457f3SChristophe Kerello 
9392cd457f3SChristophe Kerello 		ret = dma_map_sg(fmc2->dev, fmc2->dma_ecc_sg.sgl,
9402cd457f3SChristophe Kerello 				 eccsteps, dma_data_dir);
9412cd457f3SChristophe Kerello 		if (ret < 0)
9422cd457f3SChristophe Kerello 			goto err_unmap_data;
9432cd457f3SChristophe Kerello 
9442cd457f3SChristophe Kerello 		desc_ecc = dmaengine_prep_slave_sg(fmc2->dma_ecc_ch,
9452cd457f3SChristophe Kerello 						   fmc2->dma_ecc_sg.sgl,
9462cd457f3SChristophe Kerello 						   eccsteps, dma_transfer_dir,
9472cd457f3SChristophe Kerello 						   DMA_PREP_INTERRUPT);
9482cd457f3SChristophe Kerello 		if (!desc_ecc) {
9492cd457f3SChristophe Kerello 			ret = -ENOMEM;
9502cd457f3SChristophe Kerello 			goto err_unmap_ecc;
9512cd457f3SChristophe Kerello 		}
9522cd457f3SChristophe Kerello 
9532cd457f3SChristophe Kerello 		reinit_completion(&fmc2->dma_ecc_complete);
9542cd457f3SChristophe Kerello 		desc_ecc->callback = stm32_fmc2_dma_callback;
9552cd457f3SChristophe Kerello 		desc_ecc->callback_param = &fmc2->dma_ecc_complete;
9562cd457f3SChristophe Kerello 		ret = dma_submit_error(dmaengine_submit(desc_ecc));
9572cd457f3SChristophe Kerello 		if (ret)
9582cd457f3SChristophe Kerello 			goto err_unmap_ecc;
9592cd457f3SChristophe Kerello 
9602cd457f3SChristophe Kerello 		dma_async_issue_pending(fmc2->dma_ecc_ch);
9612cd457f3SChristophe Kerello 	}
9622cd457f3SChristophe Kerello 
9632cd457f3SChristophe Kerello 	stm32_fmc2_clear_seq_irq(fmc2);
9642cd457f3SChristophe Kerello 	stm32_fmc2_enable_seq_irq(fmc2);
9652cd457f3SChristophe Kerello 
9662cd457f3SChristophe Kerello 	/* Start the transfer */
9672cd457f3SChristophe Kerello 	csqcr |= FMC2_CSQCR_CSQSTART;
9682cd457f3SChristophe Kerello 	writel_relaxed(csqcr, fmc2->io_base + FMC2_CSQCR);
9692cd457f3SChristophe Kerello 
9702cd457f3SChristophe Kerello 	/* Wait end of sequencer transfer */
9712cd457f3SChristophe Kerello 	if (!wait_for_completion_timeout(&fmc2->complete,
9722cd457f3SChristophe Kerello 					 msecs_to_jiffies(1000))) {
9732cd457f3SChristophe Kerello 		dev_err(fmc2->dev, "seq timeout\n");
9742cd457f3SChristophe Kerello 		stm32_fmc2_disable_seq_irq(fmc2);
9752cd457f3SChristophe Kerello 		dmaengine_terminate_all(dma_ch);
9762cd457f3SChristophe Kerello 		if (!write_data && !raw)
9772cd457f3SChristophe Kerello 			dmaengine_terminate_all(fmc2->dma_ecc_ch);
9782cd457f3SChristophe Kerello 		ret = -ETIMEDOUT;
9792cd457f3SChristophe Kerello 		goto err_unmap_ecc;
9802cd457f3SChristophe Kerello 	}
9812cd457f3SChristophe Kerello 
9822cd457f3SChristophe Kerello 	/* Wait DMA data transfer completion */
9832cd457f3SChristophe Kerello 	if (!wait_for_completion_timeout(&fmc2->dma_data_complete,
9842cd457f3SChristophe Kerello 					 msecs_to_jiffies(100))) {
9852cd457f3SChristophe Kerello 		dev_err(fmc2->dev, "data DMA timeout\n");
9862cd457f3SChristophe Kerello 		dmaengine_terminate_all(dma_ch);
9872cd457f3SChristophe Kerello 		ret = -ETIMEDOUT;
9882cd457f3SChristophe Kerello 	}
9892cd457f3SChristophe Kerello 
9902cd457f3SChristophe Kerello 	/* Wait DMA ECC transfer completion */
9912cd457f3SChristophe Kerello 	if (!write_data && !raw) {
9922cd457f3SChristophe Kerello 		if (!wait_for_completion_timeout(&fmc2->dma_ecc_complete,
9932cd457f3SChristophe Kerello 						 msecs_to_jiffies(100))) {
9942cd457f3SChristophe Kerello 			dev_err(fmc2->dev, "ECC DMA timeout\n");
9952cd457f3SChristophe Kerello 			dmaengine_terminate_all(fmc2->dma_ecc_ch);
9962cd457f3SChristophe Kerello 			ret = -ETIMEDOUT;
9972cd457f3SChristophe Kerello 		}
9982cd457f3SChristophe Kerello 	}
9992cd457f3SChristophe Kerello 
10002cd457f3SChristophe Kerello err_unmap_ecc:
10012cd457f3SChristophe Kerello 	if (!write_data && !raw)
10022cd457f3SChristophe Kerello 		dma_unmap_sg(fmc2->dev, fmc2->dma_ecc_sg.sgl,
10032cd457f3SChristophe Kerello 			     eccsteps, dma_data_dir);
10042cd457f3SChristophe Kerello 
10052cd457f3SChristophe Kerello err_unmap_data:
10062cd457f3SChristophe Kerello 	dma_unmap_sg(fmc2->dev, fmc2->dma_data_sg.sgl, eccsteps, dma_data_dir);
10072cd457f3SChristophe Kerello 
10082cd457f3SChristophe Kerello 	return ret;
10092cd457f3SChristophe Kerello }
10102cd457f3SChristophe Kerello 
10112cd457f3SChristophe Kerello static int stm32_fmc2_sequencer_write(struct nand_chip *chip,
10122cd457f3SChristophe Kerello 				      const u8 *buf, int oob_required,
10132cd457f3SChristophe Kerello 				      int page, int raw)
10142cd457f3SChristophe Kerello {
10152cd457f3SChristophe Kerello 	struct mtd_info *mtd = nand_to_mtd(chip);
10162cd457f3SChristophe Kerello 	int ret;
10172cd457f3SChristophe Kerello 
10182cd457f3SChristophe Kerello 	/* Configure the sequencer */
10192cd457f3SChristophe Kerello 	stm32_fmc2_rw_page_init(chip, page, raw, true);
10202cd457f3SChristophe Kerello 
10212cd457f3SChristophe Kerello 	/* Write the page */
10222cd457f3SChristophe Kerello 	ret = stm32_fmc2_xfer(chip, buf, raw, true);
10232cd457f3SChristophe Kerello 	if (ret)
10242cd457f3SChristophe Kerello 		return ret;
10252cd457f3SChristophe Kerello 
10262cd457f3SChristophe Kerello 	/* Write oob */
10272cd457f3SChristophe Kerello 	if (oob_required) {
10282cd457f3SChristophe Kerello 		ret = nand_change_write_column_op(chip, mtd->writesize,
10292cd457f3SChristophe Kerello 						  chip->oob_poi, mtd->oobsize,
10302cd457f3SChristophe Kerello 						  false);
10312cd457f3SChristophe Kerello 		if (ret)
10322cd457f3SChristophe Kerello 			return ret;
10332cd457f3SChristophe Kerello 	}
10342cd457f3SChristophe Kerello 
10352cd457f3SChristophe Kerello 	return nand_prog_page_end_op(chip);
10362cd457f3SChristophe Kerello }
10372cd457f3SChristophe Kerello 
10382cd457f3SChristophe Kerello static int stm32_fmc2_sequencer_write_page(struct nand_chip *chip,
10392cd457f3SChristophe Kerello 					   const u8 *buf,
10402cd457f3SChristophe Kerello 					   int oob_required,
10412cd457f3SChristophe Kerello 					   int page)
10422cd457f3SChristophe Kerello {
10432cd457f3SChristophe Kerello 	int ret;
10442cd457f3SChristophe Kerello 
10452cd457f3SChristophe Kerello 	/* Select the target */
10462cd457f3SChristophe Kerello 	ret = stm32_fmc2_select_chip(chip, chip->cur_cs);
10472cd457f3SChristophe Kerello 	if (ret)
10482cd457f3SChristophe Kerello 		return ret;
10492cd457f3SChristophe Kerello 
10502cd457f3SChristophe Kerello 	return stm32_fmc2_sequencer_write(chip, buf, oob_required, page, false);
10512cd457f3SChristophe Kerello }
10522cd457f3SChristophe Kerello 
10532cd457f3SChristophe Kerello static int stm32_fmc2_sequencer_write_page_raw(struct nand_chip *chip,
10542cd457f3SChristophe Kerello 					       const u8 *buf,
10552cd457f3SChristophe Kerello 					       int oob_required,
10562cd457f3SChristophe Kerello 					       int page)
10572cd457f3SChristophe Kerello {
10582cd457f3SChristophe Kerello 	int ret;
10592cd457f3SChristophe Kerello 
10602cd457f3SChristophe Kerello 	/* Select the target */
10612cd457f3SChristophe Kerello 	ret = stm32_fmc2_select_chip(chip, chip->cur_cs);
10622cd457f3SChristophe Kerello 	if (ret)
10632cd457f3SChristophe Kerello 		return ret;
10642cd457f3SChristophe Kerello 
10652cd457f3SChristophe Kerello 	return stm32_fmc2_sequencer_write(chip, buf, oob_required, page, true);
10662cd457f3SChristophe Kerello }
10672cd457f3SChristophe Kerello 
10682cd457f3SChristophe Kerello /* Get a status indicating which sectors have errors */
10692cd457f3SChristophe Kerello static inline u16 stm32_fmc2_get_mapping_status(struct stm32_fmc2_nfc *fmc2)
10702cd457f3SChristophe Kerello {
10712cd457f3SChristophe Kerello 	u32 csqemsr = readl_relaxed(fmc2->io_base + FMC2_CSQEMSR);
10722cd457f3SChristophe Kerello 
10732cd457f3SChristophe Kerello 	return csqemsr & FMC2_CSQEMSR_SEM;
10742cd457f3SChristophe Kerello }
10752cd457f3SChristophe Kerello 
10762cd457f3SChristophe Kerello static int stm32_fmc2_sequencer_correct(struct nand_chip *chip, u8 *dat,
10772cd457f3SChristophe Kerello 					u8 *read_ecc, u8 *calc_ecc)
10782cd457f3SChristophe Kerello {
10792cd457f3SChristophe Kerello 	struct mtd_info *mtd = nand_to_mtd(chip);
10802cd457f3SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
10812cd457f3SChristophe Kerello 	int eccbytes = chip->ecc.bytes;
10822cd457f3SChristophe Kerello 	int eccsteps = chip->ecc.steps;
10832cd457f3SChristophe Kerello 	int eccstrength = chip->ecc.strength;
10842cd457f3SChristophe Kerello 	int i, s, eccsize = chip->ecc.size;
10852cd457f3SChristophe Kerello 	u32 *ecc_sta = (u32 *)fmc2->ecc_buf;
10862cd457f3SChristophe Kerello 	u16 sta_map = stm32_fmc2_get_mapping_status(fmc2);
10872cd457f3SChristophe Kerello 	unsigned int max_bitflips = 0;
10882cd457f3SChristophe Kerello 
10892cd457f3SChristophe Kerello 	for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, dat += eccsize) {
10902cd457f3SChristophe Kerello 		int stat = 0;
10912cd457f3SChristophe Kerello 
10922cd457f3SChristophe Kerello 		if (eccstrength == FMC2_ECC_HAM) {
10932cd457f3SChristophe Kerello 			/* Ecc_sta = FMC2_HECCR */
10942cd457f3SChristophe Kerello 			if (sta_map & BIT(s)) {
10952cd457f3SChristophe Kerello 				stm32_fmc2_ham_set_ecc(*ecc_sta, &calc_ecc[i]);
10962cd457f3SChristophe Kerello 				stat = stm32_fmc2_ham_correct(chip, dat,
10972cd457f3SChristophe Kerello 							      &read_ecc[i],
10982cd457f3SChristophe Kerello 							      &calc_ecc[i]);
10992cd457f3SChristophe Kerello 			}
11002cd457f3SChristophe Kerello 			ecc_sta++;
11012cd457f3SChristophe Kerello 		} else {
11022cd457f3SChristophe Kerello 			/*
11032cd457f3SChristophe Kerello 			 * Ecc_sta[0] = FMC2_BCHDSR0
11042cd457f3SChristophe Kerello 			 * Ecc_sta[1] = FMC2_BCHDSR1
11052cd457f3SChristophe Kerello 			 * Ecc_sta[2] = FMC2_BCHDSR2
11062cd457f3SChristophe Kerello 			 * Ecc_sta[3] = FMC2_BCHDSR3
11072cd457f3SChristophe Kerello 			 * Ecc_sta[4] = FMC2_BCHDSR4
11082cd457f3SChristophe Kerello 			 */
11092cd457f3SChristophe Kerello 			if (sta_map & BIT(s))
11102cd457f3SChristophe Kerello 				stat = stm32_fmc2_bch_decode(eccsize, dat,
11112cd457f3SChristophe Kerello 							     ecc_sta);
11122cd457f3SChristophe Kerello 			ecc_sta += 5;
11132cd457f3SChristophe Kerello 		}
11142cd457f3SChristophe Kerello 
11152cd457f3SChristophe Kerello 		if (stat == -EBADMSG)
11162cd457f3SChristophe Kerello 			/* Check for empty pages with bitflips */
11172cd457f3SChristophe Kerello 			stat = nand_check_erased_ecc_chunk(dat, eccsize,
11182cd457f3SChristophe Kerello 							   &read_ecc[i],
11192cd457f3SChristophe Kerello 							   eccbytes,
11202cd457f3SChristophe Kerello 							   NULL, 0,
11212cd457f3SChristophe Kerello 							   eccstrength);
11222cd457f3SChristophe Kerello 
11232cd457f3SChristophe Kerello 		if (stat < 0) {
11242cd457f3SChristophe Kerello 			mtd->ecc_stats.failed++;
11252cd457f3SChristophe Kerello 		} else {
11262cd457f3SChristophe Kerello 			mtd->ecc_stats.corrected += stat;
11272cd457f3SChristophe Kerello 			max_bitflips = max_t(unsigned int, max_bitflips, stat);
11282cd457f3SChristophe Kerello 		}
11292cd457f3SChristophe Kerello 	}
11302cd457f3SChristophe Kerello 
11312cd457f3SChristophe Kerello 	return max_bitflips;
11322cd457f3SChristophe Kerello }
11332cd457f3SChristophe Kerello 
11342cd457f3SChristophe Kerello static int stm32_fmc2_sequencer_read_page(struct nand_chip *chip, u8 *buf,
11352cd457f3SChristophe Kerello 					  int oob_required, int page)
11362cd457f3SChristophe Kerello {
11372cd457f3SChristophe Kerello 	struct mtd_info *mtd = nand_to_mtd(chip);
11382cd457f3SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
11392cd457f3SChristophe Kerello 	u8 *ecc_calc = chip->ecc.calc_buf;
11402cd457f3SChristophe Kerello 	u8 *ecc_code = chip->ecc.code_buf;
11412cd457f3SChristophe Kerello 	u16 sta_map;
11422cd457f3SChristophe Kerello 	int ret;
11432cd457f3SChristophe Kerello 
11442cd457f3SChristophe Kerello 	/* Select the target */
11452cd457f3SChristophe Kerello 	ret = stm32_fmc2_select_chip(chip, chip->cur_cs);
11462cd457f3SChristophe Kerello 	if (ret)
11472cd457f3SChristophe Kerello 		return ret;
11482cd457f3SChristophe Kerello 
11492cd457f3SChristophe Kerello 	/* Configure the sequencer */
11502cd457f3SChristophe Kerello 	stm32_fmc2_rw_page_init(chip, page, 0, false);
11512cd457f3SChristophe Kerello 
11522cd457f3SChristophe Kerello 	/* Read the page */
11532cd457f3SChristophe Kerello 	ret = stm32_fmc2_xfer(chip, buf, 0, false);
11542cd457f3SChristophe Kerello 	if (ret)
11552cd457f3SChristophe Kerello 		return ret;
11562cd457f3SChristophe Kerello 
11572cd457f3SChristophe Kerello 	sta_map = stm32_fmc2_get_mapping_status(fmc2);
11582cd457f3SChristophe Kerello 
11592cd457f3SChristophe Kerello 	/* Check if errors happen */
11602cd457f3SChristophe Kerello 	if (likely(!sta_map)) {
11612cd457f3SChristophe Kerello 		if (oob_required)
11622cd457f3SChristophe Kerello 			return nand_change_read_column_op(chip, mtd->writesize,
11632cd457f3SChristophe Kerello 							  chip->oob_poi,
11642cd457f3SChristophe Kerello 							  mtd->oobsize, false);
11652cd457f3SChristophe Kerello 
11662cd457f3SChristophe Kerello 		return 0;
11672cd457f3SChristophe Kerello 	}
11682cd457f3SChristophe Kerello 
11692cd457f3SChristophe Kerello 	/* Read oob */
11702cd457f3SChristophe Kerello 	ret = nand_change_read_column_op(chip, mtd->writesize,
11712cd457f3SChristophe Kerello 					 chip->oob_poi, mtd->oobsize, false);
11722cd457f3SChristophe Kerello 	if (ret)
11732cd457f3SChristophe Kerello 		return ret;
11742cd457f3SChristophe Kerello 
11752cd457f3SChristophe Kerello 	ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
11762cd457f3SChristophe Kerello 					 chip->ecc.total);
11772cd457f3SChristophe Kerello 	if (ret)
11782cd457f3SChristophe Kerello 		return ret;
11792cd457f3SChristophe Kerello 
11802cd457f3SChristophe Kerello 	/* Correct data */
11812cd457f3SChristophe Kerello 	return chip->ecc.correct(chip, buf, ecc_code, ecc_calc);
11822cd457f3SChristophe Kerello }
11832cd457f3SChristophe Kerello 
11842cd457f3SChristophe Kerello static int stm32_fmc2_sequencer_read_page_raw(struct nand_chip *chip, u8 *buf,
11852cd457f3SChristophe Kerello 					      int oob_required, int page)
11862cd457f3SChristophe Kerello {
11872cd457f3SChristophe Kerello 	struct mtd_info *mtd = nand_to_mtd(chip);
11882cd457f3SChristophe Kerello 	int ret;
11892cd457f3SChristophe Kerello 
11902cd457f3SChristophe Kerello 	/* Select the target */
11912cd457f3SChristophe Kerello 	ret = stm32_fmc2_select_chip(chip, chip->cur_cs);
11922cd457f3SChristophe Kerello 	if (ret)
11932cd457f3SChristophe Kerello 		return ret;
11942cd457f3SChristophe Kerello 
11952cd457f3SChristophe Kerello 	/* Configure the sequencer */
11962cd457f3SChristophe Kerello 	stm32_fmc2_rw_page_init(chip, page, 1, false);
11972cd457f3SChristophe Kerello 
11982cd457f3SChristophe Kerello 	/* Read the page */
11992cd457f3SChristophe Kerello 	ret = stm32_fmc2_xfer(chip, buf, 1, false);
12002cd457f3SChristophe Kerello 	if (ret)
12012cd457f3SChristophe Kerello 		return ret;
12022cd457f3SChristophe Kerello 
12032cd457f3SChristophe Kerello 	/* Read oob */
12042cd457f3SChristophe Kerello 	if (oob_required)
12052cd457f3SChristophe Kerello 		return nand_change_read_column_op(chip, mtd->writesize,
12062cd457f3SChristophe Kerello 						  chip->oob_poi, mtd->oobsize,
12072cd457f3SChristophe Kerello 						  false);
12082cd457f3SChristophe Kerello 
12092cd457f3SChristophe Kerello 	return 0;
12102cd457f3SChristophe Kerello }
12112cd457f3SChristophe Kerello 
12122cd457f3SChristophe Kerello static irqreturn_t stm32_fmc2_irq(int irq, void *dev_id)
12132cd457f3SChristophe Kerello {
12142cd457f3SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = (struct stm32_fmc2_nfc *)dev_id;
12152cd457f3SChristophe Kerello 
1216*33c8cf42SChristophe Kerello 	if (fmc2->irq_state == FMC2_IRQ_SEQ)
1217*33c8cf42SChristophe Kerello 		/* Sequencer is used */
12182cd457f3SChristophe Kerello 		stm32_fmc2_disable_seq_irq(fmc2);
1219*33c8cf42SChristophe Kerello 	else if (fmc2->irq_state == FMC2_IRQ_BCH)
1220*33c8cf42SChristophe Kerello 		/* BCH is used */
1221*33c8cf42SChristophe Kerello 		stm32_fmc2_disable_bch_irq(fmc2);
12222cd457f3SChristophe Kerello 
12232cd457f3SChristophe Kerello 	complete(&fmc2->complete);
12242cd457f3SChristophe Kerello 
12252cd457f3SChristophe Kerello 	return IRQ_HANDLED;
12262cd457f3SChristophe Kerello }
12272cd457f3SChristophe Kerello 
12282cd457f3SChristophe Kerello static void stm32_fmc2_read_data(struct nand_chip *chip, void *buf,
12292cd457f3SChristophe Kerello 				 unsigned int len, bool force_8bit)
12302cd457f3SChristophe Kerello {
12312cd457f3SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
12322cd457f3SChristophe Kerello 	void __iomem *io_addr_r = fmc2->data_base[fmc2->cs_sel];
12332cd457f3SChristophe Kerello 
12342cd457f3SChristophe Kerello 	if (force_8bit && chip->options & NAND_BUSWIDTH_16)
12352cd457f3SChristophe Kerello 		/* Reconfigure bus width to 8-bit */
12362cd457f3SChristophe Kerello 		stm32_fmc2_set_buswidth_16(fmc2, false);
12372cd457f3SChristophe Kerello 
12382cd457f3SChristophe Kerello 	if (!IS_ALIGNED((uintptr_t)buf, sizeof(u32))) {
12392cd457f3SChristophe Kerello 		if (!IS_ALIGNED((uintptr_t)buf, sizeof(u16)) && len) {
12402cd457f3SChristophe Kerello 			*(u8 *)buf = readb_relaxed(io_addr_r);
12412cd457f3SChristophe Kerello 			buf += sizeof(u8);
12422cd457f3SChristophe Kerello 			len -= sizeof(u8);
12432cd457f3SChristophe Kerello 		}
12442cd457f3SChristophe Kerello 
12452cd457f3SChristophe Kerello 		if (!IS_ALIGNED((uintptr_t)buf, sizeof(u32)) &&
12462cd457f3SChristophe Kerello 		    len >= sizeof(u16)) {
12472cd457f3SChristophe Kerello 			*(u16 *)buf = readw_relaxed(io_addr_r);
12482cd457f3SChristophe Kerello 			buf += sizeof(u16);
12492cd457f3SChristophe Kerello 			len -= sizeof(u16);
12502cd457f3SChristophe Kerello 		}
12512cd457f3SChristophe Kerello 	}
12522cd457f3SChristophe Kerello 
12532cd457f3SChristophe Kerello 	/* Buf is aligned */
12542cd457f3SChristophe Kerello 	while (len >= sizeof(u32)) {
12552cd457f3SChristophe Kerello 		*(u32 *)buf = readl_relaxed(io_addr_r);
12562cd457f3SChristophe Kerello 		buf += sizeof(u32);
12572cd457f3SChristophe Kerello 		len -= sizeof(u32);
12582cd457f3SChristophe Kerello 	}
12592cd457f3SChristophe Kerello 
12602cd457f3SChristophe Kerello 	/* Read remaining bytes */
12612cd457f3SChristophe Kerello 	if (len >= sizeof(u16)) {
12622cd457f3SChristophe Kerello 		*(u16 *)buf = readw_relaxed(io_addr_r);
12632cd457f3SChristophe Kerello 		buf += sizeof(u16);
12642cd457f3SChristophe Kerello 		len -= sizeof(u16);
12652cd457f3SChristophe Kerello 	}
12662cd457f3SChristophe Kerello 
12672cd457f3SChristophe Kerello 	if (len)
12682cd457f3SChristophe Kerello 		*(u8 *)buf = readb_relaxed(io_addr_r);
12692cd457f3SChristophe Kerello 
12702cd457f3SChristophe Kerello 	if (force_8bit && chip->options & NAND_BUSWIDTH_16)
12712cd457f3SChristophe Kerello 		/* Reconfigure bus width to 16-bit */
12722cd457f3SChristophe Kerello 		stm32_fmc2_set_buswidth_16(fmc2, true);
12732cd457f3SChristophe Kerello }
12742cd457f3SChristophe Kerello 
12752cd457f3SChristophe Kerello static void stm32_fmc2_write_data(struct nand_chip *chip, const void *buf,
12762cd457f3SChristophe Kerello 				  unsigned int len, bool force_8bit)
12772cd457f3SChristophe Kerello {
12782cd457f3SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
12792cd457f3SChristophe Kerello 	void __iomem *io_addr_w = fmc2->data_base[fmc2->cs_sel];
12802cd457f3SChristophe Kerello 
12812cd457f3SChristophe Kerello 	if (force_8bit && chip->options & NAND_BUSWIDTH_16)
12822cd457f3SChristophe Kerello 		/* Reconfigure bus width to 8-bit */
12832cd457f3SChristophe Kerello 		stm32_fmc2_set_buswidth_16(fmc2, false);
12842cd457f3SChristophe Kerello 
12852cd457f3SChristophe Kerello 	if (!IS_ALIGNED((uintptr_t)buf, sizeof(u32))) {
12862cd457f3SChristophe Kerello 		if (!IS_ALIGNED((uintptr_t)buf, sizeof(u16)) && len) {
12872cd457f3SChristophe Kerello 			writeb_relaxed(*(u8 *)buf, io_addr_w);
12882cd457f3SChristophe Kerello 			buf += sizeof(u8);
12892cd457f3SChristophe Kerello 			len -= sizeof(u8);
12902cd457f3SChristophe Kerello 		}
12912cd457f3SChristophe Kerello 
12922cd457f3SChristophe Kerello 		if (!IS_ALIGNED((uintptr_t)buf, sizeof(u32)) &&
12932cd457f3SChristophe Kerello 		    len >= sizeof(u16)) {
12942cd457f3SChristophe Kerello 			writew_relaxed(*(u16 *)buf, io_addr_w);
12952cd457f3SChristophe Kerello 			buf += sizeof(u16);
12962cd457f3SChristophe Kerello 			len -= sizeof(u16);
12972cd457f3SChristophe Kerello 		}
12982cd457f3SChristophe Kerello 	}
12992cd457f3SChristophe Kerello 
13002cd457f3SChristophe Kerello 	/* Buf is aligned */
13012cd457f3SChristophe Kerello 	while (len >= sizeof(u32)) {
13022cd457f3SChristophe Kerello 		writel_relaxed(*(u32 *)buf, io_addr_w);
13032cd457f3SChristophe Kerello 		buf += sizeof(u32);
13042cd457f3SChristophe Kerello 		len -= sizeof(u32);
13052cd457f3SChristophe Kerello 	}
13062cd457f3SChristophe Kerello 
13072cd457f3SChristophe Kerello 	/* Write remaining bytes */
13082cd457f3SChristophe Kerello 	if (len >= sizeof(u16)) {
13092cd457f3SChristophe Kerello 		writew_relaxed(*(u16 *)buf, io_addr_w);
13102cd457f3SChristophe Kerello 		buf += sizeof(u16);
13112cd457f3SChristophe Kerello 		len -= sizeof(u16);
13122cd457f3SChristophe Kerello 	}
13132cd457f3SChristophe Kerello 
13142cd457f3SChristophe Kerello 	if (len)
13152cd457f3SChristophe Kerello 		writeb_relaxed(*(u8 *)buf, io_addr_w);
13162cd457f3SChristophe Kerello 
13172cd457f3SChristophe Kerello 	if (force_8bit && chip->options & NAND_BUSWIDTH_16)
13182cd457f3SChristophe Kerello 		/* Reconfigure bus width to 16-bit */
13192cd457f3SChristophe Kerello 		stm32_fmc2_set_buswidth_16(fmc2, true);
13202cd457f3SChristophe Kerello }
13212cd457f3SChristophe Kerello 
13222cd457f3SChristophe Kerello static int stm32_fmc2_exec_op(struct nand_chip *chip,
13232cd457f3SChristophe Kerello 			      const struct nand_operation *op,
13242cd457f3SChristophe Kerello 			      bool check_only)
13252cd457f3SChristophe Kerello {
13262cd457f3SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
13272cd457f3SChristophe Kerello 	const struct nand_op_instr *instr = NULL;
13282cd457f3SChristophe Kerello 	unsigned int op_id, i;
13292cd457f3SChristophe Kerello 	int ret;
13302cd457f3SChristophe Kerello 
13312cd457f3SChristophe Kerello 	ret = stm32_fmc2_select_chip(chip, op->cs);
13322cd457f3SChristophe Kerello 	if (ret)
13332cd457f3SChristophe Kerello 		return ret;
13342cd457f3SChristophe Kerello 
13352cd457f3SChristophe Kerello 	if (check_only)
13362cd457f3SChristophe Kerello 		return ret;
13372cd457f3SChristophe Kerello 
13382cd457f3SChristophe Kerello 	for (op_id = 0; op_id < op->ninstrs; op_id++) {
13392cd457f3SChristophe Kerello 		instr = &op->instrs[op_id];
13402cd457f3SChristophe Kerello 
13412cd457f3SChristophe Kerello 		switch (instr->type) {
13422cd457f3SChristophe Kerello 		case NAND_OP_CMD_INSTR:
13432cd457f3SChristophe Kerello 			writeb_relaxed(instr->ctx.cmd.opcode,
13442cd457f3SChristophe Kerello 				       fmc2->cmd_base[fmc2->cs_sel]);
13452cd457f3SChristophe Kerello 			break;
13462cd457f3SChristophe Kerello 
13472cd457f3SChristophe Kerello 		case NAND_OP_ADDR_INSTR:
13482cd457f3SChristophe Kerello 			for (i = 0; i < instr->ctx.addr.naddrs; i++)
13492cd457f3SChristophe Kerello 				writeb_relaxed(instr->ctx.addr.addrs[i],
13502cd457f3SChristophe Kerello 					       fmc2->addr_base[fmc2->cs_sel]);
13512cd457f3SChristophe Kerello 			break;
13522cd457f3SChristophe Kerello 
13532cd457f3SChristophe Kerello 		case NAND_OP_DATA_IN_INSTR:
13542cd457f3SChristophe Kerello 			stm32_fmc2_read_data(chip, instr->ctx.data.buf.in,
13552cd457f3SChristophe Kerello 					     instr->ctx.data.len,
13562cd457f3SChristophe Kerello 					     instr->ctx.data.force_8bit);
13572cd457f3SChristophe Kerello 			break;
13582cd457f3SChristophe Kerello 
13592cd457f3SChristophe Kerello 		case NAND_OP_DATA_OUT_INSTR:
13602cd457f3SChristophe Kerello 			stm32_fmc2_write_data(chip, instr->ctx.data.buf.out,
13612cd457f3SChristophe Kerello 					      instr->ctx.data.len,
13622cd457f3SChristophe Kerello 					      instr->ctx.data.force_8bit);
13632cd457f3SChristophe Kerello 			break;
13642cd457f3SChristophe Kerello 
13652cd457f3SChristophe Kerello 		case NAND_OP_WAITRDY_INSTR:
13662cd457f3SChristophe Kerello 			ret = nand_soft_waitrdy(chip,
13672cd457f3SChristophe Kerello 						instr->ctx.waitrdy.timeout_ms);
13682cd457f3SChristophe Kerello 			break;
13692cd457f3SChristophe Kerello 		}
13702cd457f3SChristophe Kerello 	}
13712cd457f3SChristophe Kerello 
13722cd457f3SChristophe Kerello 	return ret;
13732cd457f3SChristophe Kerello }
13742cd457f3SChristophe Kerello 
13752cd457f3SChristophe Kerello /* Controller initialization */
13762cd457f3SChristophe Kerello static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
13772cd457f3SChristophe Kerello {
13782cd457f3SChristophe Kerello 	u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
13792cd457f3SChristophe Kerello 	u32 bcr1 = readl_relaxed(fmc2->io_base + FMC2_BCR1);
13802cd457f3SChristophe Kerello 
13812cd457f3SChristophe Kerello 	/* Set CS used to undefined */
13822cd457f3SChristophe Kerello 	fmc2->cs_sel = -1;
13832cd457f3SChristophe Kerello 
13842cd457f3SChristophe Kerello 	/* Enable wait feature and nand flash memory bank */
13852cd457f3SChristophe Kerello 	pcr |= FMC2_PCR_PWAITEN;
13862cd457f3SChristophe Kerello 	pcr |= FMC2_PCR_PBKEN;
13872cd457f3SChristophe Kerello 
13882cd457f3SChristophe Kerello 	/* Set buswidth to 8 bits mode for identification */
13892cd457f3SChristophe Kerello 	pcr &= ~FMC2_PCR_PWID_MASK;
13902cd457f3SChristophe Kerello 
13912cd457f3SChristophe Kerello 	/* ECC logic is disabled */
13922cd457f3SChristophe Kerello 	pcr &= ~FMC2_PCR_ECCEN;
13932cd457f3SChristophe Kerello 
13942cd457f3SChristophe Kerello 	/* Default mode */
13952cd457f3SChristophe Kerello 	pcr &= ~FMC2_PCR_ECCALG;
13962cd457f3SChristophe Kerello 	pcr &= ~FMC2_PCR_BCHECC;
13972cd457f3SChristophe Kerello 	pcr &= ~FMC2_PCR_WEN;
13982cd457f3SChristophe Kerello 
13992cd457f3SChristophe Kerello 	/* Set default ECC sector size */
14002cd457f3SChristophe Kerello 	pcr &= ~FMC2_PCR_ECCSS_MASK;
14012cd457f3SChristophe Kerello 	pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048);
14022cd457f3SChristophe Kerello 
14032cd457f3SChristophe Kerello 	/* Set default tclr/tar timings */
14042cd457f3SChristophe Kerello 	pcr &= ~FMC2_PCR_TCLR_MASK;
14052cd457f3SChristophe Kerello 	pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT);
14062cd457f3SChristophe Kerello 	pcr &= ~FMC2_PCR_TAR_MASK;
14072cd457f3SChristophe Kerello 	pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT);
14082cd457f3SChristophe Kerello 
14092cd457f3SChristophe Kerello 	/* Enable FMC2 controller */
14102cd457f3SChristophe Kerello 	bcr1 |= FMC2_BCR1_FMC2EN;
14112cd457f3SChristophe Kerello 
14122cd457f3SChristophe Kerello 	writel_relaxed(bcr1, fmc2->io_base + FMC2_BCR1);
14132cd457f3SChristophe Kerello 	writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
14142cd457f3SChristophe Kerello 	writel_relaxed(FMC2_PMEM_DEFAULT, fmc2->io_base + FMC2_PMEM);
14152cd457f3SChristophe Kerello 	writel_relaxed(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
14162cd457f3SChristophe Kerello }
14172cd457f3SChristophe Kerello 
14182cd457f3SChristophe Kerello /* Controller timings */
14192cd457f3SChristophe Kerello static void stm32_fmc2_calc_timings(struct nand_chip *chip,
14202cd457f3SChristophe Kerello 				    const struct nand_sdr_timings *sdrt)
14212cd457f3SChristophe Kerello {
14222cd457f3SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
14232cd457f3SChristophe Kerello 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
14242cd457f3SChristophe Kerello 	struct stm32_fmc2_timings *tims = &nand->timings;
14252cd457f3SChristophe Kerello 	unsigned long hclk = clk_get_rate(fmc2->clk);
14262cd457f3SChristophe Kerello 	unsigned long hclkp = NSEC_PER_SEC / (hclk / 1000);
14272cd457f3SChristophe Kerello 	int tar, tclr, thiz, twait, tset_mem, tset_att, thold_mem, thold_att;
14282cd457f3SChristophe Kerello 
14292cd457f3SChristophe Kerello 	tar = hclkp;
14302cd457f3SChristophe Kerello 	if (tar < sdrt->tAR_min)
14312cd457f3SChristophe Kerello 		tar = sdrt->tAR_min;
14322cd457f3SChristophe Kerello 	tims->tar = DIV_ROUND_UP(tar, hclkp) - 1;
14332cd457f3SChristophe Kerello 	if (tims->tar > FMC2_PCR_TIMING_MASK)
14342cd457f3SChristophe Kerello 		tims->tar = FMC2_PCR_TIMING_MASK;
14352cd457f3SChristophe Kerello 
14362cd457f3SChristophe Kerello 	tclr = hclkp;
14372cd457f3SChristophe Kerello 	if (tclr < sdrt->tCLR_min)
14382cd457f3SChristophe Kerello 		tclr = sdrt->tCLR_min;
14392cd457f3SChristophe Kerello 	tims->tclr = DIV_ROUND_UP(tclr, hclkp) - 1;
14402cd457f3SChristophe Kerello 	if (tims->tclr > FMC2_PCR_TIMING_MASK)
14412cd457f3SChristophe Kerello 		tims->tclr = FMC2_PCR_TIMING_MASK;
14422cd457f3SChristophe Kerello 
14432cd457f3SChristophe Kerello 	tims->thiz = FMC2_THIZ;
14442cd457f3SChristophe Kerello 	thiz = (tims->thiz + 1) * hclkp;
14452cd457f3SChristophe Kerello 
14462cd457f3SChristophe Kerello 	/*
14472cd457f3SChristophe Kerello 	 * tWAIT > tRP
14482cd457f3SChristophe Kerello 	 * tWAIT > tWP
14492cd457f3SChristophe Kerello 	 * tWAIT > tREA + tIO
14502cd457f3SChristophe Kerello 	 */
14512cd457f3SChristophe Kerello 	twait = hclkp;
14522cd457f3SChristophe Kerello 	if (twait < sdrt->tRP_min)
14532cd457f3SChristophe Kerello 		twait = sdrt->tRP_min;
14542cd457f3SChristophe Kerello 	if (twait < sdrt->tWP_min)
14552cd457f3SChristophe Kerello 		twait = sdrt->tWP_min;
14562cd457f3SChristophe Kerello 	if (twait < sdrt->tREA_max + FMC2_TIO)
14572cd457f3SChristophe Kerello 		twait = sdrt->tREA_max + FMC2_TIO;
14582cd457f3SChristophe Kerello 	tims->twait = DIV_ROUND_UP(twait, hclkp);
14592cd457f3SChristophe Kerello 	if (tims->twait == 0)
14602cd457f3SChristophe Kerello 		tims->twait = 1;
14612cd457f3SChristophe Kerello 	else if (tims->twait > FMC2_PMEM_PATT_TIMING_MASK)
14622cd457f3SChristophe Kerello 		tims->twait = FMC2_PMEM_PATT_TIMING_MASK;
14632cd457f3SChristophe Kerello 
14642cd457f3SChristophe Kerello 	/*
14652cd457f3SChristophe Kerello 	 * tSETUP_MEM > tCS - tWAIT
14662cd457f3SChristophe Kerello 	 * tSETUP_MEM > tALS - tWAIT
14672cd457f3SChristophe Kerello 	 * tSETUP_MEM > tDS - (tWAIT - tHIZ)
14682cd457f3SChristophe Kerello 	 */
14692cd457f3SChristophe Kerello 	tset_mem = hclkp;
14702cd457f3SChristophe Kerello 	if (sdrt->tCS_min > twait && (tset_mem < sdrt->tCS_min - twait))
14712cd457f3SChristophe Kerello 		tset_mem = sdrt->tCS_min - twait;
14722cd457f3SChristophe Kerello 	if (sdrt->tALS_min > twait && (tset_mem < sdrt->tALS_min - twait))
14732cd457f3SChristophe Kerello 		tset_mem = sdrt->tALS_min - twait;
14742cd457f3SChristophe Kerello 	if (twait > thiz && (sdrt->tDS_min > twait - thiz) &&
14752cd457f3SChristophe Kerello 	    (tset_mem < sdrt->tDS_min - (twait - thiz)))
14762cd457f3SChristophe Kerello 		tset_mem = sdrt->tDS_min - (twait - thiz);
14772cd457f3SChristophe Kerello 	tims->tset_mem = DIV_ROUND_UP(tset_mem, hclkp);
14782cd457f3SChristophe Kerello 	if (tims->tset_mem == 0)
14792cd457f3SChristophe Kerello 		tims->tset_mem = 1;
14802cd457f3SChristophe Kerello 	else if (tims->tset_mem > FMC2_PMEM_PATT_TIMING_MASK)
14812cd457f3SChristophe Kerello 		tims->tset_mem = FMC2_PMEM_PATT_TIMING_MASK;
14822cd457f3SChristophe Kerello 
14832cd457f3SChristophe Kerello 	/*
14842cd457f3SChristophe Kerello 	 * tHOLD_MEM > tCH
14852cd457f3SChristophe Kerello 	 * tHOLD_MEM > tREH - tSETUP_MEM
14862cd457f3SChristophe Kerello 	 * tHOLD_MEM > max(tRC, tWC) - (tSETUP_MEM + tWAIT)
14872cd457f3SChristophe Kerello 	 */
14882cd457f3SChristophe Kerello 	thold_mem = hclkp;
14892cd457f3SChristophe Kerello 	if (thold_mem < sdrt->tCH_min)
14902cd457f3SChristophe Kerello 		thold_mem = sdrt->tCH_min;
14912cd457f3SChristophe Kerello 	if (sdrt->tREH_min > tset_mem &&
14922cd457f3SChristophe Kerello 	    (thold_mem < sdrt->tREH_min - tset_mem))
14932cd457f3SChristophe Kerello 		thold_mem = sdrt->tREH_min - tset_mem;
14942cd457f3SChristophe Kerello 	if ((sdrt->tRC_min > tset_mem + twait) &&
14952cd457f3SChristophe Kerello 	    (thold_mem < sdrt->tRC_min - (tset_mem + twait)))
14962cd457f3SChristophe Kerello 		thold_mem = sdrt->tRC_min - (tset_mem + twait);
14972cd457f3SChristophe Kerello 	if ((sdrt->tWC_min > tset_mem + twait) &&
14982cd457f3SChristophe Kerello 	    (thold_mem < sdrt->tWC_min - (tset_mem + twait)))
14992cd457f3SChristophe Kerello 		thold_mem = sdrt->tWC_min - (tset_mem + twait);
15002cd457f3SChristophe Kerello 	tims->thold_mem = DIV_ROUND_UP(thold_mem, hclkp);
15012cd457f3SChristophe Kerello 	if (tims->thold_mem == 0)
15022cd457f3SChristophe Kerello 		tims->thold_mem = 1;
15032cd457f3SChristophe Kerello 	else if (tims->thold_mem > FMC2_PMEM_PATT_TIMING_MASK)
15042cd457f3SChristophe Kerello 		tims->thold_mem = FMC2_PMEM_PATT_TIMING_MASK;
15052cd457f3SChristophe Kerello 
15062cd457f3SChristophe Kerello 	/*
15072cd457f3SChristophe Kerello 	 * tSETUP_ATT > tCS - tWAIT
15082cd457f3SChristophe Kerello 	 * tSETUP_ATT > tCLS - tWAIT
15092cd457f3SChristophe Kerello 	 * tSETUP_ATT > tALS - tWAIT
15102cd457f3SChristophe Kerello 	 * tSETUP_ATT > tRHW - tHOLD_MEM
15112cd457f3SChristophe Kerello 	 * tSETUP_ATT > tDS - (tWAIT - tHIZ)
15122cd457f3SChristophe Kerello 	 */
15132cd457f3SChristophe Kerello 	tset_att = hclkp;
15142cd457f3SChristophe Kerello 	if (sdrt->tCS_min > twait && (tset_att < sdrt->tCS_min - twait))
15152cd457f3SChristophe Kerello 		tset_att = sdrt->tCS_min - twait;
15162cd457f3SChristophe Kerello 	if (sdrt->tCLS_min > twait && (tset_att < sdrt->tCLS_min - twait))
15172cd457f3SChristophe Kerello 		tset_att = sdrt->tCLS_min - twait;
15182cd457f3SChristophe Kerello 	if (sdrt->tALS_min > twait && (tset_att < sdrt->tALS_min - twait))
15192cd457f3SChristophe Kerello 		tset_att = sdrt->tALS_min - twait;
15202cd457f3SChristophe Kerello 	if (sdrt->tRHW_min > thold_mem &&
15212cd457f3SChristophe Kerello 	    (tset_att < sdrt->tRHW_min - thold_mem))
15222cd457f3SChristophe Kerello 		tset_att = sdrt->tRHW_min - thold_mem;
15232cd457f3SChristophe Kerello 	if (twait > thiz && (sdrt->tDS_min > twait - thiz) &&
15242cd457f3SChristophe Kerello 	    (tset_att < sdrt->tDS_min - (twait - thiz)))
15252cd457f3SChristophe Kerello 		tset_att = sdrt->tDS_min - (twait - thiz);
15262cd457f3SChristophe Kerello 	tims->tset_att = DIV_ROUND_UP(tset_att, hclkp);
15272cd457f3SChristophe Kerello 	if (tims->tset_att == 0)
15282cd457f3SChristophe Kerello 		tims->tset_att = 1;
15292cd457f3SChristophe Kerello 	else if (tims->tset_att > FMC2_PMEM_PATT_TIMING_MASK)
15302cd457f3SChristophe Kerello 		tims->tset_att = FMC2_PMEM_PATT_TIMING_MASK;
15312cd457f3SChristophe Kerello 
15322cd457f3SChristophe Kerello 	/*
15332cd457f3SChristophe Kerello 	 * tHOLD_ATT > tALH
15342cd457f3SChristophe Kerello 	 * tHOLD_ATT > tCH
15352cd457f3SChristophe Kerello 	 * tHOLD_ATT > tCLH
15362cd457f3SChristophe Kerello 	 * tHOLD_ATT > tCOH
15372cd457f3SChristophe Kerello 	 * tHOLD_ATT > tDH
15382cd457f3SChristophe Kerello 	 * tHOLD_ATT > tWB + tIO + tSYNC - tSETUP_MEM
15392cd457f3SChristophe Kerello 	 * tHOLD_ATT > tADL - tSETUP_MEM
15402cd457f3SChristophe Kerello 	 * tHOLD_ATT > tWH - tSETUP_MEM
15412cd457f3SChristophe Kerello 	 * tHOLD_ATT > tWHR - tSETUP_MEM
15422cd457f3SChristophe Kerello 	 * tHOLD_ATT > tRC - (tSETUP_ATT + tWAIT)
15432cd457f3SChristophe Kerello 	 * tHOLD_ATT > tWC - (tSETUP_ATT + tWAIT)
15442cd457f3SChristophe Kerello 	 */
15452cd457f3SChristophe Kerello 	thold_att = hclkp;
15462cd457f3SChristophe Kerello 	if (thold_att < sdrt->tALH_min)
15472cd457f3SChristophe Kerello 		thold_att = sdrt->tALH_min;
15482cd457f3SChristophe Kerello 	if (thold_att < sdrt->tCH_min)
15492cd457f3SChristophe Kerello 		thold_att = sdrt->tCH_min;
15502cd457f3SChristophe Kerello 	if (thold_att < sdrt->tCLH_min)
15512cd457f3SChristophe Kerello 		thold_att = sdrt->tCLH_min;
15522cd457f3SChristophe Kerello 	if (thold_att < sdrt->tCOH_min)
15532cd457f3SChristophe Kerello 		thold_att = sdrt->tCOH_min;
15542cd457f3SChristophe Kerello 	if (thold_att < sdrt->tDH_min)
15552cd457f3SChristophe Kerello 		thold_att = sdrt->tDH_min;
15562cd457f3SChristophe Kerello 	if ((sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC > tset_mem) &&
15572cd457f3SChristophe Kerello 	    (thold_att < sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC - tset_mem))
15582cd457f3SChristophe Kerello 		thold_att = sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC - tset_mem;
15592cd457f3SChristophe Kerello 	if (sdrt->tADL_min > tset_mem &&
15602cd457f3SChristophe Kerello 	    (thold_att < sdrt->tADL_min - tset_mem))
15612cd457f3SChristophe Kerello 		thold_att = sdrt->tADL_min - tset_mem;
15622cd457f3SChristophe Kerello 	if (sdrt->tWH_min > tset_mem &&
15632cd457f3SChristophe Kerello 	    (thold_att < sdrt->tWH_min - tset_mem))
15642cd457f3SChristophe Kerello 		thold_att = sdrt->tWH_min - tset_mem;
15652cd457f3SChristophe Kerello 	if (sdrt->tWHR_min > tset_mem &&
15662cd457f3SChristophe Kerello 	    (thold_att < sdrt->tWHR_min - tset_mem))
15672cd457f3SChristophe Kerello 		thold_att = sdrt->tWHR_min - tset_mem;
15682cd457f3SChristophe Kerello 	if ((sdrt->tRC_min > tset_att + twait) &&
15692cd457f3SChristophe Kerello 	    (thold_att < sdrt->tRC_min - (tset_att + twait)))
15702cd457f3SChristophe Kerello 		thold_att = sdrt->tRC_min - (tset_att + twait);
15712cd457f3SChristophe Kerello 	if ((sdrt->tWC_min > tset_att + twait) &&
15722cd457f3SChristophe Kerello 	    (thold_att < sdrt->tWC_min - (tset_att + twait)))
15732cd457f3SChristophe Kerello 		thold_att = sdrt->tWC_min - (tset_att + twait);
15742cd457f3SChristophe Kerello 	tims->thold_att = DIV_ROUND_UP(thold_att, hclkp);
15752cd457f3SChristophe Kerello 	if (tims->thold_att == 0)
15762cd457f3SChristophe Kerello 		tims->thold_att = 1;
15772cd457f3SChristophe Kerello 	else if (tims->thold_att > FMC2_PMEM_PATT_TIMING_MASK)
15782cd457f3SChristophe Kerello 		tims->thold_att = FMC2_PMEM_PATT_TIMING_MASK;
15792cd457f3SChristophe Kerello }
15802cd457f3SChristophe Kerello 
15812cd457f3SChristophe Kerello static int stm32_fmc2_setup_interface(struct nand_chip *chip, int chipnr,
15822cd457f3SChristophe Kerello 				      const struct nand_data_interface *conf)
15832cd457f3SChristophe Kerello {
15842cd457f3SChristophe Kerello 	const struct nand_sdr_timings *sdrt;
15852cd457f3SChristophe Kerello 
15862cd457f3SChristophe Kerello 	sdrt = nand_get_sdr_timings(conf);
15872cd457f3SChristophe Kerello 	if (IS_ERR(sdrt))
15882cd457f3SChristophe Kerello 		return PTR_ERR(sdrt);
15892cd457f3SChristophe Kerello 
15902cd457f3SChristophe Kerello 	if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
15912cd457f3SChristophe Kerello 		return 0;
15922cd457f3SChristophe Kerello 
15932cd457f3SChristophe Kerello 	stm32_fmc2_calc_timings(chip, sdrt);
15942cd457f3SChristophe Kerello 
15952cd457f3SChristophe Kerello 	/* Apply timings */
15962cd457f3SChristophe Kerello 	stm32_fmc2_timings_init(chip);
15972cd457f3SChristophe Kerello 
15982cd457f3SChristophe Kerello 	return 0;
15992cd457f3SChristophe Kerello }
16002cd457f3SChristophe Kerello 
16012cd457f3SChristophe Kerello /* DMA configuration */
16022cd457f3SChristophe Kerello static int stm32_fmc2_dma_setup(struct stm32_fmc2_nfc *fmc2)
16032cd457f3SChristophe Kerello {
16042cd457f3SChristophe Kerello 	int ret;
16052cd457f3SChristophe Kerello 
16062cd457f3SChristophe Kerello 	fmc2->dma_tx_ch = dma_request_slave_channel(fmc2->dev, "tx");
16072cd457f3SChristophe Kerello 	fmc2->dma_rx_ch = dma_request_slave_channel(fmc2->dev, "rx");
16082cd457f3SChristophe Kerello 	fmc2->dma_ecc_ch = dma_request_slave_channel(fmc2->dev, "ecc");
16092cd457f3SChristophe Kerello 
1610*33c8cf42SChristophe Kerello 	if (!fmc2->dma_tx_ch || !fmc2->dma_rx_ch || !fmc2->dma_ecc_ch) {
1611*33c8cf42SChristophe Kerello 		dev_warn(fmc2->dev, "DMAs not defined in the device tree, polling mode is used\n");
1612*33c8cf42SChristophe Kerello 		return 0;
1613*33c8cf42SChristophe Kerello 	}
1614*33c8cf42SChristophe Kerello 
1615*33c8cf42SChristophe Kerello 	ret = sg_alloc_table(&fmc2->dma_ecc_sg, FMC2_MAX_SG, GFP_KERNEL);
16162cd457f3SChristophe Kerello 	if (ret)
16172cd457f3SChristophe Kerello 		return ret;
16182cd457f3SChristophe Kerello 
16192cd457f3SChristophe Kerello 	/* Allocate a buffer to store ECC status registers */
1620*33c8cf42SChristophe Kerello 	fmc2->ecc_buf = devm_kzalloc(fmc2->dev, FMC2_MAX_ECC_BUF_LEN,
16212cd457f3SChristophe Kerello 				     GFP_KERNEL);
16222cd457f3SChristophe Kerello 	if (!fmc2->ecc_buf)
16232cd457f3SChristophe Kerello 		return -ENOMEM;
16242cd457f3SChristophe Kerello 
1625*33c8cf42SChristophe Kerello 	ret = sg_alloc_table(&fmc2->dma_data_sg, FMC2_MAX_SG, GFP_KERNEL);
16262cd457f3SChristophe Kerello 	if (ret)
16272cd457f3SChristophe Kerello 		return ret;
16282cd457f3SChristophe Kerello 
16292cd457f3SChristophe Kerello 	init_completion(&fmc2->dma_data_complete);
16302cd457f3SChristophe Kerello 	init_completion(&fmc2->dma_ecc_complete);
16312cd457f3SChristophe Kerello 
16322cd457f3SChristophe Kerello 	return 0;
16332cd457f3SChristophe Kerello }
16342cd457f3SChristophe Kerello 
16352cd457f3SChristophe Kerello /* NAND callbacks setup */
16362cd457f3SChristophe Kerello static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
16372cd457f3SChristophe Kerello {
1638*33c8cf42SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
1639*33c8cf42SChristophe Kerello 
1640*33c8cf42SChristophe Kerello 	/*
1641*33c8cf42SChristophe Kerello 	 * Specific callbacks to read/write a page depending on
1642*33c8cf42SChristophe Kerello 	 * the mode (polling/sequencer) and the algo used (Hamming, BCH).
1643*33c8cf42SChristophe Kerello 	 */
1644*33c8cf42SChristophe Kerello 	if (fmc2->dma_tx_ch && fmc2->dma_rx_ch && fmc2->dma_ecc_ch) {
1645*33c8cf42SChristophe Kerello 		/* DMA => use sequencer mode callbacks */
16462cd457f3SChristophe Kerello 		chip->ecc.correct = stm32_fmc2_sequencer_correct;
16472cd457f3SChristophe Kerello 		chip->ecc.write_page = stm32_fmc2_sequencer_write_page;
16482cd457f3SChristophe Kerello 		chip->ecc.read_page = stm32_fmc2_sequencer_read_page;
16492cd457f3SChristophe Kerello 		chip->ecc.write_page_raw = stm32_fmc2_sequencer_write_page_raw;
16502cd457f3SChristophe Kerello 		chip->ecc.read_page_raw = stm32_fmc2_sequencer_read_page_raw;
1651*33c8cf42SChristophe Kerello 	} else {
1652*33c8cf42SChristophe Kerello 		/* No DMA => use polling mode callbacks */
1653*33c8cf42SChristophe Kerello 		chip->ecc.hwctl = stm32_fmc2_hwctl;
1654*33c8cf42SChristophe Kerello 		if (chip->ecc.strength == FMC2_ECC_HAM) {
1655*33c8cf42SChristophe Kerello 			/* Hamming is used */
1656*33c8cf42SChristophe Kerello 			chip->ecc.calculate = stm32_fmc2_ham_calculate;
1657*33c8cf42SChristophe Kerello 			chip->ecc.correct = stm32_fmc2_ham_correct;
1658*33c8cf42SChristophe Kerello 			chip->ecc.options |= NAND_ECC_GENERIC_ERASED_CHECK;
1659*33c8cf42SChristophe Kerello 		} else {
1660*33c8cf42SChristophe Kerello 			/* BCH is used */
1661*33c8cf42SChristophe Kerello 			chip->ecc.calculate = stm32_fmc2_bch_calculate;
1662*33c8cf42SChristophe Kerello 			chip->ecc.correct = stm32_fmc2_bch_correct;
1663*33c8cf42SChristophe Kerello 			chip->ecc.read_page = stm32_fmc2_read_page;
1664*33c8cf42SChristophe Kerello 		}
1665*33c8cf42SChristophe Kerello 	}
16662cd457f3SChristophe Kerello 
16672cd457f3SChristophe Kerello 	/* Specific configurations depending on the algo used */
16682cd457f3SChristophe Kerello 	if (chip->ecc.strength == FMC2_ECC_HAM)
16692cd457f3SChristophe Kerello 		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 4 : 3;
16702cd457f3SChristophe Kerello 	else if (chip->ecc.strength == FMC2_ECC_BCH8)
16712cd457f3SChristophe Kerello 		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 14 : 13;
16722cd457f3SChristophe Kerello 	else
16732cd457f3SChristophe Kerello 		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
16742cd457f3SChristophe Kerello }
16752cd457f3SChristophe Kerello 
16762cd457f3SChristophe Kerello /* FMC2 layout */
16772cd457f3SChristophe Kerello static int stm32_fmc2_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
16782cd457f3SChristophe Kerello 					 struct mtd_oob_region *oobregion)
16792cd457f3SChristophe Kerello {
16802cd457f3SChristophe Kerello 	struct nand_chip *chip = mtd_to_nand(mtd);
16812cd457f3SChristophe Kerello 	struct nand_ecc_ctrl *ecc = &chip->ecc;
16822cd457f3SChristophe Kerello 
16832cd457f3SChristophe Kerello 	if (section)
16842cd457f3SChristophe Kerello 		return -ERANGE;
16852cd457f3SChristophe Kerello 
16862cd457f3SChristophe Kerello 	oobregion->length = ecc->total;
16872cd457f3SChristophe Kerello 	oobregion->offset = FMC2_BBM_LEN;
16882cd457f3SChristophe Kerello 
16892cd457f3SChristophe Kerello 	return 0;
16902cd457f3SChristophe Kerello }
16912cd457f3SChristophe Kerello 
16922cd457f3SChristophe Kerello static int stm32_fmc2_nand_ooblayout_free(struct mtd_info *mtd, int section,
16932cd457f3SChristophe Kerello 					  struct mtd_oob_region *oobregion)
16942cd457f3SChristophe Kerello {
16952cd457f3SChristophe Kerello 	struct nand_chip *chip = mtd_to_nand(mtd);
16962cd457f3SChristophe Kerello 	struct nand_ecc_ctrl *ecc = &chip->ecc;
16972cd457f3SChristophe Kerello 
16982cd457f3SChristophe Kerello 	if (section)
16992cd457f3SChristophe Kerello 		return -ERANGE;
17002cd457f3SChristophe Kerello 
17012cd457f3SChristophe Kerello 	oobregion->length = mtd->oobsize - ecc->total - FMC2_BBM_LEN;
17022cd457f3SChristophe Kerello 	oobregion->offset = ecc->total + FMC2_BBM_LEN;
17032cd457f3SChristophe Kerello 
17042cd457f3SChristophe Kerello 	return 0;
17052cd457f3SChristophe Kerello }
17062cd457f3SChristophe Kerello 
17072cd457f3SChristophe Kerello static const struct mtd_ooblayout_ops stm32_fmc2_nand_ooblayout_ops = {
17082cd457f3SChristophe Kerello 	.ecc = stm32_fmc2_nand_ooblayout_ecc,
17092cd457f3SChristophe Kerello 	.free = stm32_fmc2_nand_ooblayout_free,
17102cd457f3SChristophe Kerello };
17112cd457f3SChristophe Kerello 
17122cd457f3SChristophe Kerello /* FMC2 caps */
17132cd457f3SChristophe Kerello static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
17142cd457f3SChristophe Kerello {
17152cd457f3SChristophe Kerello 	/* Hamming */
17162cd457f3SChristophe Kerello 	if (strength == FMC2_ECC_HAM)
17172cd457f3SChristophe Kerello 		return 4;
17182cd457f3SChristophe Kerello 
17192cd457f3SChristophe Kerello 	/* BCH8 */
17202cd457f3SChristophe Kerello 	if (strength == FMC2_ECC_BCH8)
17212cd457f3SChristophe Kerello 		return 14;
17222cd457f3SChristophe Kerello 
17232cd457f3SChristophe Kerello 	/* BCH4 */
17242cd457f3SChristophe Kerello 	return 8;
17252cd457f3SChristophe Kerello }
17262cd457f3SChristophe Kerello 
17272cd457f3SChristophe Kerello NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes,
17282cd457f3SChristophe Kerello 		     FMC2_ECC_STEP_SIZE,
17292cd457f3SChristophe Kerello 		     FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
17302cd457f3SChristophe Kerello 
17312cd457f3SChristophe Kerello /* FMC2 controller ops */
17322cd457f3SChristophe Kerello static int stm32_fmc2_attach_chip(struct nand_chip *chip)
17332cd457f3SChristophe Kerello {
17342cd457f3SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
17352cd457f3SChristophe Kerello 	struct mtd_info *mtd = nand_to_mtd(chip);
17362cd457f3SChristophe Kerello 	int ret;
17372cd457f3SChristophe Kerello 
17382cd457f3SChristophe Kerello 	/*
17392cd457f3SChristophe Kerello 	 * Only NAND_ECC_HW mode is actually supported
17402cd457f3SChristophe Kerello 	 * Hamming => ecc.strength = 1
17412cd457f3SChristophe Kerello 	 * BCH4 => ecc.strength = 4
17422cd457f3SChristophe Kerello 	 * BCH8 => ecc.strength = 8
17432cd457f3SChristophe Kerello 	 * ECC sector size = 512
17442cd457f3SChristophe Kerello 	 */
17452cd457f3SChristophe Kerello 	if (chip->ecc.mode != NAND_ECC_HW) {
17462cd457f3SChristophe Kerello 		dev_err(fmc2->dev, "nand_ecc_mode is not well defined in the DT\n");
17472cd457f3SChristophe Kerello 		return -EINVAL;
17482cd457f3SChristophe Kerello 	}
17492cd457f3SChristophe Kerello 
17502cd457f3SChristophe Kerello 	ret = nand_ecc_choose_conf(chip, &stm32_fmc2_ecc_caps,
17512cd457f3SChristophe Kerello 				   mtd->oobsize - FMC2_BBM_LEN);
17522cd457f3SChristophe Kerello 	if (ret) {
17532cd457f3SChristophe Kerello 		dev_err(fmc2->dev, "no valid ECC settings set\n");
17542cd457f3SChristophe Kerello 		return ret;
17552cd457f3SChristophe Kerello 	}
17562cd457f3SChristophe Kerello 
17572cd457f3SChristophe Kerello 	if (mtd->writesize / chip->ecc.size > FMC2_MAX_SG) {
17582cd457f3SChristophe Kerello 		dev_err(fmc2->dev, "nand page size is not supported\n");
17592cd457f3SChristophe Kerello 		return -EINVAL;
17602cd457f3SChristophe Kerello 	}
17612cd457f3SChristophe Kerello 
17622cd457f3SChristophe Kerello 	if (chip->bbt_options & NAND_BBT_USE_FLASH)
17632cd457f3SChristophe Kerello 		chip->bbt_options |= NAND_BBT_NO_OOB;
17642cd457f3SChristophe Kerello 
17652cd457f3SChristophe Kerello 	/* NAND callbacks setup */
17662cd457f3SChristophe Kerello 	stm32_fmc2_nand_callbacks_setup(chip);
17672cd457f3SChristophe Kerello 
17682cd457f3SChristophe Kerello 	/* Define ECC layout */
17692cd457f3SChristophe Kerello 	mtd_set_ooblayout(mtd, &stm32_fmc2_nand_ooblayout_ops);
17702cd457f3SChristophe Kerello 
17712cd457f3SChristophe Kerello 	/* Configure bus width to 16-bit */
17722cd457f3SChristophe Kerello 	if (chip->options & NAND_BUSWIDTH_16)
17732cd457f3SChristophe Kerello 		stm32_fmc2_set_buswidth_16(fmc2, true);
17742cd457f3SChristophe Kerello 
17752cd457f3SChristophe Kerello 	return 0;
17762cd457f3SChristophe Kerello }
17772cd457f3SChristophe Kerello 
17782cd457f3SChristophe Kerello static const struct nand_controller_ops stm32_fmc2_nand_controller_ops = {
17792cd457f3SChristophe Kerello 	.attach_chip = stm32_fmc2_attach_chip,
17802cd457f3SChristophe Kerello 	.exec_op = stm32_fmc2_exec_op,
17812cd457f3SChristophe Kerello 	.setup_data_interface = stm32_fmc2_setup_interface,
17822cd457f3SChristophe Kerello };
17832cd457f3SChristophe Kerello 
17842cd457f3SChristophe Kerello /* FMC2 probe */
17852cd457f3SChristophe Kerello static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
17862cd457f3SChristophe Kerello 				  struct device_node *dn)
17872cd457f3SChristophe Kerello {
17882cd457f3SChristophe Kerello 	struct stm32_fmc2_nand *nand = &fmc2->nand;
17892cd457f3SChristophe Kerello 	u32 cs;
17902cd457f3SChristophe Kerello 	int ret, i;
17912cd457f3SChristophe Kerello 
17922cd457f3SChristophe Kerello 	if (!of_get_property(dn, "reg", &nand->ncs))
17932cd457f3SChristophe Kerello 		return -EINVAL;
17942cd457f3SChristophe Kerello 
17952cd457f3SChristophe Kerello 	nand->ncs /= sizeof(u32);
17962cd457f3SChristophe Kerello 	if (!nand->ncs) {
17972cd457f3SChristophe Kerello 		dev_err(fmc2->dev, "invalid reg property size\n");
17982cd457f3SChristophe Kerello 		return -EINVAL;
17992cd457f3SChristophe Kerello 	}
18002cd457f3SChristophe Kerello 
18012cd457f3SChristophe Kerello 	for (i = 0; i < nand->ncs; i++) {
18022cd457f3SChristophe Kerello 		ret = of_property_read_u32_index(dn, "reg", i, &cs);
18032cd457f3SChristophe Kerello 		if (ret) {
18042cd457f3SChristophe Kerello 			dev_err(fmc2->dev, "could not retrieve reg property: %d\n",
18052cd457f3SChristophe Kerello 				ret);
18062cd457f3SChristophe Kerello 			return ret;
18072cd457f3SChristophe Kerello 		}
18082cd457f3SChristophe Kerello 
18092cd457f3SChristophe Kerello 		if (cs > FMC2_MAX_CE) {
18102cd457f3SChristophe Kerello 			dev_err(fmc2->dev, "invalid reg value: %d\n", cs);
18112cd457f3SChristophe Kerello 			return -EINVAL;
18122cd457f3SChristophe Kerello 		}
18132cd457f3SChristophe Kerello 
18142cd457f3SChristophe Kerello 		if (fmc2->cs_assigned & BIT(cs)) {
18152cd457f3SChristophe Kerello 			dev_err(fmc2->dev, "cs already assigned: %d\n", cs);
18162cd457f3SChristophe Kerello 			return -EINVAL;
18172cd457f3SChristophe Kerello 		}
18182cd457f3SChristophe Kerello 
18192cd457f3SChristophe Kerello 		fmc2->cs_assigned |= BIT(cs);
18202cd457f3SChristophe Kerello 		nand->cs_used[i] = cs;
18212cd457f3SChristophe Kerello 	}
18222cd457f3SChristophe Kerello 
18232cd457f3SChristophe Kerello 	nand_set_flash_node(&nand->chip, dn);
18242cd457f3SChristophe Kerello 
18252cd457f3SChristophe Kerello 	return 0;
18262cd457f3SChristophe Kerello }
18272cd457f3SChristophe Kerello 
18282cd457f3SChristophe Kerello static int stm32_fmc2_parse_dt(struct stm32_fmc2_nfc *fmc2)
18292cd457f3SChristophe Kerello {
18302cd457f3SChristophe Kerello 	struct device_node *dn = fmc2->dev->of_node;
18312cd457f3SChristophe Kerello 	struct device_node *child;
18322cd457f3SChristophe Kerello 	int nchips = of_get_child_count(dn);
18332cd457f3SChristophe Kerello 	int ret = 0;
18342cd457f3SChristophe Kerello 
18352cd457f3SChristophe Kerello 	if (!nchips) {
18362cd457f3SChristophe Kerello 		dev_err(fmc2->dev, "NAND chip not defined\n");
18372cd457f3SChristophe Kerello 		return -EINVAL;
18382cd457f3SChristophe Kerello 	}
18392cd457f3SChristophe Kerello 
18402cd457f3SChristophe Kerello 	if (nchips > 1) {
18412cd457f3SChristophe Kerello 		dev_err(fmc2->dev, "too many NAND chips defined\n");
18422cd457f3SChristophe Kerello 		return -EINVAL;
18432cd457f3SChristophe Kerello 	}
18442cd457f3SChristophe Kerello 
18452cd457f3SChristophe Kerello 	for_each_child_of_node(dn, child) {
18462cd457f3SChristophe Kerello 		ret = stm32_fmc2_parse_child(fmc2, child);
18472cd457f3SChristophe Kerello 		if (ret < 0) {
18482cd457f3SChristophe Kerello 			of_node_put(child);
18492cd457f3SChristophe Kerello 			return ret;
18502cd457f3SChristophe Kerello 		}
18512cd457f3SChristophe Kerello 	}
18522cd457f3SChristophe Kerello 
18532cd457f3SChristophe Kerello 	return ret;
18542cd457f3SChristophe Kerello }
18552cd457f3SChristophe Kerello 
18562cd457f3SChristophe Kerello static int stm32_fmc2_probe(struct platform_device *pdev)
18572cd457f3SChristophe Kerello {
18582cd457f3SChristophe Kerello 	struct device *dev = &pdev->dev;
18592cd457f3SChristophe Kerello 	struct reset_control *rstc;
18602cd457f3SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2;
18612cd457f3SChristophe Kerello 	struct stm32_fmc2_nand *nand;
18622cd457f3SChristophe Kerello 	struct resource *res;
18632cd457f3SChristophe Kerello 	struct mtd_info *mtd;
18642cd457f3SChristophe Kerello 	struct nand_chip *chip;
18652cd457f3SChristophe Kerello 	int chip_cs, mem_region, ret, irq;
18662cd457f3SChristophe Kerello 
18672cd457f3SChristophe Kerello 	fmc2 = devm_kzalloc(dev, sizeof(*fmc2), GFP_KERNEL);
18682cd457f3SChristophe Kerello 	if (!fmc2)
18692cd457f3SChristophe Kerello 		return -ENOMEM;
18702cd457f3SChristophe Kerello 
18712cd457f3SChristophe Kerello 	fmc2->dev = dev;
18722cd457f3SChristophe Kerello 	nand_controller_init(&fmc2->base);
18732cd457f3SChristophe Kerello 	fmc2->base.ops = &stm32_fmc2_nand_controller_ops;
18742cd457f3SChristophe Kerello 
18752cd457f3SChristophe Kerello 	ret = stm32_fmc2_parse_dt(fmc2);
18762cd457f3SChristophe Kerello 	if (ret)
18772cd457f3SChristophe Kerello 		return ret;
18782cd457f3SChristophe Kerello 
18792cd457f3SChristophe Kerello 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
18802cd457f3SChristophe Kerello 	fmc2->io_base = devm_ioremap_resource(dev, res);
18812cd457f3SChristophe Kerello 	if (IS_ERR(fmc2->io_base))
18822cd457f3SChristophe Kerello 		return PTR_ERR(fmc2->io_base);
18832cd457f3SChristophe Kerello 
18842cd457f3SChristophe Kerello 	fmc2->io_phys_addr = res->start;
18852cd457f3SChristophe Kerello 
18862cd457f3SChristophe Kerello 	for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
18872cd457f3SChristophe Kerello 	     chip_cs++, mem_region += 3) {
18882cd457f3SChristophe Kerello 		if (!(fmc2->cs_assigned & BIT(chip_cs)))
18892cd457f3SChristophe Kerello 			continue;
18902cd457f3SChristophe Kerello 
18912cd457f3SChristophe Kerello 		res = platform_get_resource(pdev, IORESOURCE_MEM, mem_region);
18922cd457f3SChristophe Kerello 		fmc2->data_base[chip_cs] = devm_ioremap_resource(dev, res);
18932cd457f3SChristophe Kerello 		if (IS_ERR(fmc2->data_base[chip_cs]))
18942cd457f3SChristophe Kerello 			return PTR_ERR(fmc2->data_base[chip_cs]);
18952cd457f3SChristophe Kerello 
18962cd457f3SChristophe Kerello 		fmc2->data_phys_addr[chip_cs] = res->start;
18972cd457f3SChristophe Kerello 
18982cd457f3SChristophe Kerello 		res = platform_get_resource(pdev, IORESOURCE_MEM,
18992cd457f3SChristophe Kerello 					    mem_region + 1);
19002cd457f3SChristophe Kerello 		fmc2->cmd_base[chip_cs] = devm_ioremap_resource(dev, res);
19012cd457f3SChristophe Kerello 		if (IS_ERR(fmc2->cmd_base[chip_cs]))
19022cd457f3SChristophe Kerello 			return PTR_ERR(fmc2->cmd_base[chip_cs]);
19032cd457f3SChristophe Kerello 
19042cd457f3SChristophe Kerello 		res = platform_get_resource(pdev, IORESOURCE_MEM,
19052cd457f3SChristophe Kerello 					    mem_region + 2);
19062cd457f3SChristophe Kerello 		fmc2->addr_base[chip_cs] = devm_ioremap_resource(dev, res);
19072cd457f3SChristophe Kerello 		if (IS_ERR(fmc2->addr_base[chip_cs]))
19082cd457f3SChristophe Kerello 			return PTR_ERR(fmc2->addr_base[chip_cs]);
19092cd457f3SChristophe Kerello 	}
19102cd457f3SChristophe Kerello 
19112cd457f3SChristophe Kerello 	irq = platform_get_irq(pdev, 0);
19122cd457f3SChristophe Kerello 	ret = devm_request_irq(dev, irq, stm32_fmc2_irq, 0,
19132cd457f3SChristophe Kerello 			       dev_name(dev), fmc2);
19142cd457f3SChristophe Kerello 	if (ret) {
19152cd457f3SChristophe Kerello 		dev_err(dev, "failed to request irq\n");
19162cd457f3SChristophe Kerello 		return ret;
19172cd457f3SChristophe Kerello 	}
19182cd457f3SChristophe Kerello 
19192cd457f3SChristophe Kerello 	init_completion(&fmc2->complete);
19202cd457f3SChristophe Kerello 
19212cd457f3SChristophe Kerello 	fmc2->clk = devm_clk_get(dev, NULL);
19222cd457f3SChristophe Kerello 	if (IS_ERR(fmc2->clk))
19232cd457f3SChristophe Kerello 		return PTR_ERR(fmc2->clk);
19242cd457f3SChristophe Kerello 
19252cd457f3SChristophe Kerello 	ret = clk_prepare_enable(fmc2->clk);
19262cd457f3SChristophe Kerello 	if (ret) {
19272cd457f3SChristophe Kerello 		dev_err(dev, "can not enable the clock\n");
19282cd457f3SChristophe Kerello 		return ret;
19292cd457f3SChristophe Kerello 	}
19302cd457f3SChristophe Kerello 
19312cd457f3SChristophe Kerello 	rstc = devm_reset_control_get(dev, NULL);
19322cd457f3SChristophe Kerello 	if (!IS_ERR(rstc)) {
19332cd457f3SChristophe Kerello 		reset_control_assert(rstc);
19342cd457f3SChristophe Kerello 		reset_control_deassert(rstc);
19352cd457f3SChristophe Kerello 	}
19362cd457f3SChristophe Kerello 
19372cd457f3SChristophe Kerello 	/* DMA setup */
19382cd457f3SChristophe Kerello 	ret = stm32_fmc2_dma_setup(fmc2);
19392cd457f3SChristophe Kerello 	if (ret)
19402cd457f3SChristophe Kerello 		return ret;
19412cd457f3SChristophe Kerello 
19422cd457f3SChristophe Kerello 	/* FMC2 init routine */
19432cd457f3SChristophe Kerello 	stm32_fmc2_init(fmc2);
19442cd457f3SChristophe Kerello 
19452cd457f3SChristophe Kerello 	nand = &fmc2->nand;
19462cd457f3SChristophe Kerello 	chip = &nand->chip;
19472cd457f3SChristophe Kerello 	mtd = nand_to_mtd(chip);
19482cd457f3SChristophe Kerello 	mtd->dev.parent = dev;
19492cd457f3SChristophe Kerello 
19502cd457f3SChristophe Kerello 	chip->controller = &fmc2->base;
19512cd457f3SChristophe Kerello 	chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE |
19522cd457f3SChristophe Kerello 			 NAND_USE_BOUNCE_BUFFER;
19532cd457f3SChristophe Kerello 
19542cd457f3SChristophe Kerello 	/* Default ECC settings */
19552cd457f3SChristophe Kerello 	chip->ecc.mode = NAND_ECC_HW;
19562cd457f3SChristophe Kerello 	chip->ecc.size = FMC2_ECC_STEP_SIZE;
19572cd457f3SChristophe Kerello 	chip->ecc.strength = FMC2_ECC_BCH8;
19582cd457f3SChristophe Kerello 
19592cd457f3SChristophe Kerello 	/* Scan to find existence of the device */
19602cd457f3SChristophe Kerello 	ret = nand_scan(chip, nand->ncs);
19612cd457f3SChristophe Kerello 	if (ret)
19622cd457f3SChristophe Kerello 		goto err_scan;
19632cd457f3SChristophe Kerello 
19642cd457f3SChristophe Kerello 	ret = mtd_device_register(mtd, NULL, 0);
19652cd457f3SChristophe Kerello 	if (ret)
19662cd457f3SChristophe Kerello 		goto err_device_register;
19672cd457f3SChristophe Kerello 
19682cd457f3SChristophe Kerello 	platform_set_drvdata(pdev, fmc2);
19692cd457f3SChristophe Kerello 
19702cd457f3SChristophe Kerello 	return 0;
19712cd457f3SChristophe Kerello 
19722cd457f3SChristophe Kerello err_device_register:
19732cd457f3SChristophe Kerello 	nand_cleanup(chip);
19742cd457f3SChristophe Kerello 
19752cd457f3SChristophe Kerello err_scan:
19762cd457f3SChristophe Kerello 	if (fmc2->dma_ecc_ch)
19772cd457f3SChristophe Kerello 		dma_release_channel(fmc2->dma_ecc_ch);
19782cd457f3SChristophe Kerello 	if (fmc2->dma_tx_ch)
19792cd457f3SChristophe Kerello 		dma_release_channel(fmc2->dma_tx_ch);
19802cd457f3SChristophe Kerello 	if (fmc2->dma_rx_ch)
19812cd457f3SChristophe Kerello 		dma_release_channel(fmc2->dma_rx_ch);
19822cd457f3SChristophe Kerello 
19832cd457f3SChristophe Kerello 	sg_free_table(&fmc2->dma_data_sg);
19842cd457f3SChristophe Kerello 	sg_free_table(&fmc2->dma_ecc_sg);
19852cd457f3SChristophe Kerello 
19862cd457f3SChristophe Kerello 	clk_disable_unprepare(fmc2->clk);
19872cd457f3SChristophe Kerello 
19882cd457f3SChristophe Kerello 	return ret;
19892cd457f3SChristophe Kerello }
19902cd457f3SChristophe Kerello 
19912cd457f3SChristophe Kerello static int stm32_fmc2_remove(struct platform_device *pdev)
19922cd457f3SChristophe Kerello {
19932cd457f3SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = platform_get_drvdata(pdev);
19942cd457f3SChristophe Kerello 	struct stm32_fmc2_nand *nand = &fmc2->nand;
19952cd457f3SChristophe Kerello 
19962cd457f3SChristophe Kerello 	nand_release(&nand->chip);
19972cd457f3SChristophe Kerello 
19982cd457f3SChristophe Kerello 	if (fmc2->dma_ecc_ch)
19992cd457f3SChristophe Kerello 		dma_release_channel(fmc2->dma_ecc_ch);
20002cd457f3SChristophe Kerello 	if (fmc2->dma_tx_ch)
20012cd457f3SChristophe Kerello 		dma_release_channel(fmc2->dma_tx_ch);
20022cd457f3SChristophe Kerello 	if (fmc2->dma_rx_ch)
20032cd457f3SChristophe Kerello 		dma_release_channel(fmc2->dma_rx_ch);
20042cd457f3SChristophe Kerello 
20052cd457f3SChristophe Kerello 	sg_free_table(&fmc2->dma_data_sg);
20062cd457f3SChristophe Kerello 	sg_free_table(&fmc2->dma_ecc_sg);
20072cd457f3SChristophe Kerello 
20082cd457f3SChristophe Kerello 	clk_disable_unprepare(fmc2->clk);
20092cd457f3SChristophe Kerello 
20102cd457f3SChristophe Kerello 	return 0;
20112cd457f3SChristophe Kerello }
20122cd457f3SChristophe Kerello 
20132cd457f3SChristophe Kerello static int __maybe_unused stm32_fmc2_suspend(struct device *dev)
20142cd457f3SChristophe Kerello {
20152cd457f3SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = dev_get_drvdata(dev);
20162cd457f3SChristophe Kerello 
20172cd457f3SChristophe Kerello 	clk_disable_unprepare(fmc2->clk);
20182cd457f3SChristophe Kerello 
20192cd457f3SChristophe Kerello 	pinctrl_pm_select_sleep_state(dev);
20202cd457f3SChristophe Kerello 
20212cd457f3SChristophe Kerello 	return 0;
20222cd457f3SChristophe Kerello }
20232cd457f3SChristophe Kerello 
20242cd457f3SChristophe Kerello static int __maybe_unused stm32_fmc2_resume(struct device *dev)
20252cd457f3SChristophe Kerello {
20262cd457f3SChristophe Kerello 	struct stm32_fmc2_nfc *fmc2 = dev_get_drvdata(dev);
20272cd457f3SChristophe Kerello 	struct stm32_fmc2_nand *nand = &fmc2->nand;
20282cd457f3SChristophe Kerello 	int chip_cs, ret;
20292cd457f3SChristophe Kerello 
20302cd457f3SChristophe Kerello 	pinctrl_pm_select_default_state(dev);
20312cd457f3SChristophe Kerello 
20322cd457f3SChristophe Kerello 	ret = clk_prepare_enable(fmc2->clk);
20332cd457f3SChristophe Kerello 	if (ret) {
20342cd457f3SChristophe Kerello 		dev_err(dev, "can not enable the clock\n");
20352cd457f3SChristophe Kerello 		return ret;
20362cd457f3SChristophe Kerello 	}
20372cd457f3SChristophe Kerello 
20382cd457f3SChristophe Kerello 	stm32_fmc2_init(fmc2);
20392cd457f3SChristophe Kerello 
20402cd457f3SChristophe Kerello 	for (chip_cs = 0; chip_cs < FMC2_MAX_CE; chip_cs++) {
20412cd457f3SChristophe Kerello 		if (!(fmc2->cs_assigned & BIT(chip_cs)))
20422cd457f3SChristophe Kerello 			continue;
20432cd457f3SChristophe Kerello 
20442cd457f3SChristophe Kerello 		nand_reset(&nand->chip, chip_cs);
20452cd457f3SChristophe Kerello 	}
20462cd457f3SChristophe Kerello 
20472cd457f3SChristophe Kerello 	return 0;
20482cd457f3SChristophe Kerello }
20492cd457f3SChristophe Kerello 
20502cd457f3SChristophe Kerello static SIMPLE_DEV_PM_OPS(stm32_fmc2_pm_ops, stm32_fmc2_suspend,
20512cd457f3SChristophe Kerello 			 stm32_fmc2_resume);
20522cd457f3SChristophe Kerello 
20532cd457f3SChristophe Kerello static const struct of_device_id stm32_fmc2_match[] = {
20542cd457f3SChristophe Kerello 	{.compatible = "st,stm32mp15-fmc2"},
20552cd457f3SChristophe Kerello 	{}
20562cd457f3SChristophe Kerello };
20572cd457f3SChristophe Kerello MODULE_DEVICE_TABLE(of, stm32_fmc2_match);
20582cd457f3SChristophe Kerello 
20592cd457f3SChristophe Kerello static struct platform_driver stm32_fmc2_driver = {
20602cd457f3SChristophe Kerello 	.probe	= stm32_fmc2_probe,
20612cd457f3SChristophe Kerello 	.remove	= stm32_fmc2_remove,
20622cd457f3SChristophe Kerello 	.driver	= {
20632cd457f3SChristophe Kerello 		.name = "stm32_fmc2_nand",
20642cd457f3SChristophe Kerello 		.of_match_table = stm32_fmc2_match,
20652cd457f3SChristophe Kerello 		.pm = &stm32_fmc2_pm_ops,
20662cd457f3SChristophe Kerello 	},
20672cd457f3SChristophe Kerello };
20682cd457f3SChristophe Kerello module_platform_driver(stm32_fmc2_driver);
20692cd457f3SChristophe Kerello 
20702cd457f3SChristophe Kerello MODULE_ALIAS("platform:stm32_fmc2_nand");
20712cd457f3SChristophe Kerello MODULE_AUTHOR("Christophe Kerello <christophe.kerello@st.com>");
20722cd457f3SChristophe Kerello MODULE_DESCRIPTION("STMicroelectronics STM32 FMC2 nand driver");
20732cd457f3SChristophe Kerello MODULE_LICENSE("GPL v2");
2074