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