1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <errno.h> 9*91f16700Schasinglulu #include <limits.h> 10*91f16700Schasinglulu #include <stdint.h> 11*91f16700Schasinglulu 12*91f16700Schasinglulu #include <common/debug.h> 13*91f16700Schasinglulu #include <drivers/clk.h> 14*91f16700Schasinglulu #include <drivers/delay_timer.h> 15*91f16700Schasinglulu #include <drivers/raw_nand.h> 16*91f16700Schasinglulu #include <drivers/st/stm32_fmc2_nand.h> 17*91f16700Schasinglulu #include <drivers/st/stm32_gpio.h> 18*91f16700Schasinglulu #include <drivers/st/stm32mp_reset.h> 19*91f16700Schasinglulu #include <lib/mmio.h> 20*91f16700Schasinglulu #include <lib/utils_def.h> 21*91f16700Schasinglulu #include <libfdt.h> 22*91f16700Schasinglulu 23*91f16700Schasinglulu #include <platform_def.h> 24*91f16700Schasinglulu 25*91f16700Schasinglulu /* Timeout for device interface reset */ 26*91f16700Schasinglulu #define TIMEOUT_US_1_MS 1000U 27*91f16700Schasinglulu 28*91f16700Schasinglulu /* FMC2 Compatibility */ 29*91f16700Schasinglulu #define DT_FMC2_EBI_COMPAT "st,stm32mp1-fmc2-ebi" 30*91f16700Schasinglulu #define DT_FMC2_NFC_COMPAT "st,stm32mp1-fmc2-nfc" 31*91f16700Schasinglulu #define MAX_CS 2U 32*91f16700Schasinglulu #define MAX_BANK 5U 33*91f16700Schasinglulu 34*91f16700Schasinglulu /* FMC2 Controller Registers */ 35*91f16700Schasinglulu #define FMC2_BCR1 0x00U 36*91f16700Schasinglulu #define FMC2_PCR 0x80U 37*91f16700Schasinglulu #define FMC2_SR 0x84U 38*91f16700Schasinglulu #define FMC2_PMEM 0x88U 39*91f16700Schasinglulu #define FMC2_PATT 0x8CU 40*91f16700Schasinglulu #define FMC2_HECCR 0x94U 41*91f16700Schasinglulu #define FMC2_BCHISR 0x254U 42*91f16700Schasinglulu #define FMC2_BCHICR 0x258U 43*91f16700Schasinglulu #define FMC2_BCHDSR0 0x27CU 44*91f16700Schasinglulu #define FMC2_BCHDSR1 0x280U 45*91f16700Schasinglulu #define FMC2_BCHDSR2 0x284U 46*91f16700Schasinglulu #define FMC2_BCHDSR3 0x288U 47*91f16700Schasinglulu #define FMC2_BCHDSR4 0x28CU 48*91f16700Schasinglulu 49*91f16700Schasinglulu /* FMC2_BCR1 register */ 50*91f16700Schasinglulu #define FMC2_BCR1_FMC2EN BIT(31) 51*91f16700Schasinglulu /* FMC2_PCR register */ 52*91f16700Schasinglulu #define FMC2_PCR_PWAITEN BIT(1) 53*91f16700Schasinglulu #define FMC2_PCR_PBKEN BIT(2) 54*91f16700Schasinglulu #define FMC2_PCR_PWID_MASK GENMASK_32(5, 4) 55*91f16700Schasinglulu #define FMC2_PCR_PWID(x) (((x) << 4) & FMC2_PCR_PWID_MASK) 56*91f16700Schasinglulu #define FMC2_PCR_PWID_8 0x0U 57*91f16700Schasinglulu #define FMC2_PCR_PWID_16 0x1U 58*91f16700Schasinglulu #define FMC2_PCR_ECCEN BIT(6) 59*91f16700Schasinglulu #define FMC2_PCR_ECCALG BIT(8) 60*91f16700Schasinglulu #define FMC2_PCR_TCLR_MASK GENMASK_32(12, 9) 61*91f16700Schasinglulu #define FMC2_PCR_TCLR(x) (((x) << 9) & FMC2_PCR_TCLR_MASK) 62*91f16700Schasinglulu #define FMC2_PCR_TCLR_DEFAULT 0xFU 63*91f16700Schasinglulu #define FMC2_PCR_TAR_MASK GENMASK_32(16, 13) 64*91f16700Schasinglulu #define FMC2_PCR_TAR(x) (((x) << 13) & FMC2_PCR_TAR_MASK) 65*91f16700Schasinglulu #define FMC2_PCR_TAR_DEFAULT 0xFU 66*91f16700Schasinglulu #define FMC2_PCR_ECCSS_MASK GENMASK_32(19, 17) 67*91f16700Schasinglulu #define FMC2_PCR_ECCSS(x) (((x) << 17) & FMC2_PCR_ECCSS_MASK) 68*91f16700Schasinglulu #define FMC2_PCR_ECCSS_512 0x1U 69*91f16700Schasinglulu #define FMC2_PCR_ECCSS_2048 0x3U 70*91f16700Schasinglulu #define FMC2_PCR_BCHECC BIT(24) 71*91f16700Schasinglulu #define FMC2_PCR_WEN BIT(25) 72*91f16700Schasinglulu /* FMC2_SR register */ 73*91f16700Schasinglulu #define FMC2_SR_NWRF BIT(6) 74*91f16700Schasinglulu /* FMC2_PMEM register*/ 75*91f16700Schasinglulu #define FMC2_PMEM_MEMSET(x) (((x) & GENMASK_32(7, 0)) << 0) 76*91f16700Schasinglulu #define FMC2_PMEM_MEMWAIT(x) (((x) & GENMASK_32(7, 0)) << 8) 77*91f16700Schasinglulu #define FMC2_PMEM_MEMHOLD(x) (((x) & GENMASK_32(7, 0)) << 16) 78*91f16700Schasinglulu #define FMC2_PMEM_MEMHIZ(x) (((x) & GENMASK_32(7, 0)) << 24) 79*91f16700Schasinglulu #define FMC2_PMEM_DEFAULT 0x0A0A0A0AU 80*91f16700Schasinglulu /* FMC2_PATT register */ 81*91f16700Schasinglulu #define FMC2_PATT_ATTSET(x) (((x) & GENMASK_32(7, 0)) << 0) 82*91f16700Schasinglulu #define FMC2_PATT_ATTWAIT(x) (((x) & GENMASK_32(7, 0)) << 8) 83*91f16700Schasinglulu #define FMC2_PATT_ATTHOLD(x) (((x) & GENMASK_32(7, 0)) << 16) 84*91f16700Schasinglulu #define FMC2_PATT_ATTHIZ(x) (((x) & GENMASK_32(7, 0)) << 24) 85*91f16700Schasinglulu #define FMC2_PATT_DEFAULT 0x0A0A0A0AU 86*91f16700Schasinglulu /* FMC2_BCHISR register */ 87*91f16700Schasinglulu #define FMC2_BCHISR_DERF BIT(1) 88*91f16700Schasinglulu /* FMC2_BCHICR register */ 89*91f16700Schasinglulu #define FMC2_BCHICR_CLEAR_IRQ GENMASK_32(4, 0) 90*91f16700Schasinglulu /* FMC2_BCHDSR0 register */ 91*91f16700Schasinglulu #define FMC2_BCHDSR0_DUE BIT(0) 92*91f16700Schasinglulu #define FMC2_BCHDSR0_DEF BIT(1) 93*91f16700Schasinglulu #define FMC2_BCHDSR0_DEN_MASK GENMASK_32(7, 4) 94*91f16700Schasinglulu #define FMC2_BCHDSR0_DEN_SHIFT 4U 95*91f16700Schasinglulu /* FMC2_BCHDSR1 register */ 96*91f16700Schasinglulu #define FMC2_BCHDSR1_EBP1_MASK GENMASK_32(12, 0) 97*91f16700Schasinglulu #define FMC2_BCHDSR1_EBP2_MASK GENMASK_32(28, 16) 98*91f16700Schasinglulu #define FMC2_BCHDSR1_EBP2_SHIFT 16U 99*91f16700Schasinglulu /* FMC2_BCHDSR2 register */ 100*91f16700Schasinglulu #define FMC2_BCHDSR2_EBP3_MASK GENMASK_32(12, 0) 101*91f16700Schasinglulu #define FMC2_BCHDSR2_EBP4_MASK GENMASK_32(28, 16) 102*91f16700Schasinglulu #define FMC2_BCHDSR2_EBP4_SHIFT 16U 103*91f16700Schasinglulu /* FMC2_BCHDSR3 register */ 104*91f16700Schasinglulu #define FMC2_BCHDSR3_EBP5_MASK GENMASK_32(12, 0) 105*91f16700Schasinglulu #define FMC2_BCHDSR3_EBP6_MASK GENMASK_32(28, 16) 106*91f16700Schasinglulu #define FMC2_BCHDSR3_EBP6_SHIFT 16U 107*91f16700Schasinglulu /* FMC2_BCHDSR4 register */ 108*91f16700Schasinglulu #define FMC2_BCHDSR4_EBP7_MASK GENMASK_32(12, 0) 109*91f16700Schasinglulu #define FMC2_BCHDSR4_EBP8_MASK GENMASK_32(28, 16) 110*91f16700Schasinglulu #define FMC2_BCHDSR4_EBP8_SHIFT 16U 111*91f16700Schasinglulu 112*91f16700Schasinglulu /* Timings */ 113*91f16700Schasinglulu #define FMC2_THIZ 0x01U 114*91f16700Schasinglulu #define FMC2_TIO 8000U 115*91f16700Schasinglulu #define FMC2_TSYNC 3000U 116*91f16700Schasinglulu #define FMC2_PCR_TIMING_MASK GENMASK_32(3, 0) 117*91f16700Schasinglulu #define FMC2_PMEM_PATT_TIMING_MASK GENMASK_32(7, 0) 118*91f16700Schasinglulu 119*91f16700Schasinglulu #define FMC2_BBM_LEN 2U 120*91f16700Schasinglulu #define FMC2_MAX_ECC_BYTES 14U 121*91f16700Schasinglulu #define TIMEOUT_US_10_MS 10000U 122*91f16700Schasinglulu #define FMC2_PSEC_PER_MSEC (1000UL * 1000UL * 1000UL) 123*91f16700Schasinglulu 124*91f16700Schasinglulu enum stm32_fmc2_ecc { 125*91f16700Schasinglulu FMC2_ECC_HAM = 1U, 126*91f16700Schasinglulu FMC2_ECC_BCH4 = 4U, 127*91f16700Schasinglulu FMC2_ECC_BCH8 = 8U 128*91f16700Schasinglulu }; 129*91f16700Schasinglulu 130*91f16700Schasinglulu struct stm32_fmc2_cs_reg { 131*91f16700Schasinglulu uintptr_t data_base; 132*91f16700Schasinglulu uintptr_t cmd_base; 133*91f16700Schasinglulu uintptr_t addr_base; 134*91f16700Schasinglulu }; 135*91f16700Schasinglulu 136*91f16700Schasinglulu struct stm32_fmc2_nand_timings { 137*91f16700Schasinglulu uint8_t tclr; 138*91f16700Schasinglulu uint8_t tar; 139*91f16700Schasinglulu uint8_t thiz; 140*91f16700Schasinglulu uint8_t twait; 141*91f16700Schasinglulu uint8_t thold_mem; 142*91f16700Schasinglulu uint8_t tset_mem; 143*91f16700Schasinglulu uint8_t thold_att; 144*91f16700Schasinglulu uint8_t tset_att; 145*91f16700Schasinglulu }; 146*91f16700Schasinglulu 147*91f16700Schasinglulu struct stm32_fmc2_nfc { 148*91f16700Schasinglulu uintptr_t reg_base; 149*91f16700Schasinglulu struct stm32_fmc2_cs_reg cs[MAX_CS]; 150*91f16700Schasinglulu unsigned long clock_id; 151*91f16700Schasinglulu unsigned int reset_id; 152*91f16700Schasinglulu uint8_t cs_sel; 153*91f16700Schasinglulu }; 154*91f16700Schasinglulu 155*91f16700Schasinglulu static struct stm32_fmc2_nfc stm32_fmc2; 156*91f16700Schasinglulu 157*91f16700Schasinglulu static uintptr_t fmc2_base(void) 158*91f16700Schasinglulu { 159*91f16700Schasinglulu return stm32_fmc2.reg_base; 160*91f16700Schasinglulu } 161*91f16700Schasinglulu 162*91f16700Schasinglulu static void stm32_fmc2_nand_setup_timing(void) 163*91f16700Schasinglulu { 164*91f16700Schasinglulu struct stm32_fmc2_nand_timings tims; 165*91f16700Schasinglulu unsigned long hclk = clk_get_rate(stm32_fmc2.clock_id); 166*91f16700Schasinglulu unsigned long hclkp = FMC2_PSEC_PER_MSEC / (hclk / 1000U); 167*91f16700Schasinglulu unsigned long timing, tar, tclr, thiz, twait; 168*91f16700Schasinglulu unsigned long tset_mem, tset_att, thold_mem, thold_att; 169*91f16700Schasinglulu uint32_t pcr, pmem, patt; 170*91f16700Schasinglulu 171*91f16700Schasinglulu tar = MAX(hclkp, NAND_TAR_MIN); 172*91f16700Schasinglulu timing = div_round_up(tar, hclkp) - 1U; 173*91f16700Schasinglulu tims.tar = MIN(timing, (unsigned long)FMC2_PCR_TIMING_MASK); 174*91f16700Schasinglulu 175*91f16700Schasinglulu tclr = MAX(hclkp, NAND_TCLR_MIN); 176*91f16700Schasinglulu timing = div_round_up(tclr, hclkp) - 1U; 177*91f16700Schasinglulu tims.tclr = MIN(timing, (unsigned long)FMC2_PCR_TIMING_MASK); 178*91f16700Schasinglulu 179*91f16700Schasinglulu tims.thiz = FMC2_THIZ; 180*91f16700Schasinglulu thiz = (tims.thiz + 1U) * hclkp; 181*91f16700Schasinglulu 182*91f16700Schasinglulu /* 183*91f16700Schasinglulu * tWAIT > tRP 184*91f16700Schasinglulu * tWAIT > tWP 185*91f16700Schasinglulu * tWAIT > tREA + tIO 186*91f16700Schasinglulu */ 187*91f16700Schasinglulu twait = MAX(hclkp, NAND_TRP_MIN); 188*91f16700Schasinglulu twait = MAX(twait, NAND_TWP_MIN); 189*91f16700Schasinglulu twait = MAX(twait, NAND_TREA_MAX + FMC2_TIO); 190*91f16700Schasinglulu timing = div_round_up(twait, hclkp); 191*91f16700Schasinglulu tims.twait = CLAMP(timing, 1UL, 192*91f16700Schasinglulu (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); 193*91f16700Schasinglulu 194*91f16700Schasinglulu /* 195*91f16700Schasinglulu * tSETUP_MEM > tCS - tWAIT 196*91f16700Schasinglulu * tSETUP_MEM > tALS - tWAIT 197*91f16700Schasinglulu * tSETUP_MEM > tDS - (tWAIT - tHIZ) 198*91f16700Schasinglulu */ 199*91f16700Schasinglulu tset_mem = hclkp; 200*91f16700Schasinglulu if ((twait < NAND_TCS_MIN) && (tset_mem < (NAND_TCS_MIN - twait))) { 201*91f16700Schasinglulu tset_mem = NAND_TCS_MIN - twait; 202*91f16700Schasinglulu } 203*91f16700Schasinglulu if ((twait > thiz) && ((twait - thiz) < NAND_TDS_MIN) && 204*91f16700Schasinglulu (tset_mem < (NAND_TDS_MIN - (twait - thiz)))) { 205*91f16700Schasinglulu tset_mem = NAND_TDS_MIN - (twait - thiz); 206*91f16700Schasinglulu } 207*91f16700Schasinglulu timing = div_round_up(tset_mem, hclkp); 208*91f16700Schasinglulu tims.tset_mem = CLAMP(timing, 1UL, 209*91f16700Schasinglulu (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); 210*91f16700Schasinglulu 211*91f16700Schasinglulu /* 212*91f16700Schasinglulu * tHOLD_MEM > tCH 213*91f16700Schasinglulu * tHOLD_MEM > tREH - tSETUP_MEM 214*91f16700Schasinglulu * tHOLD_MEM > max(tRC, tWC) - (tSETUP_MEM + tWAIT) 215*91f16700Schasinglulu */ 216*91f16700Schasinglulu thold_mem = MAX(hclkp, NAND_TCH_MIN); 217*91f16700Schasinglulu if ((tset_mem < NAND_TREH_MIN) && 218*91f16700Schasinglulu (thold_mem < (NAND_TREH_MIN - tset_mem))) { 219*91f16700Schasinglulu thold_mem = NAND_TREH_MIN - tset_mem; 220*91f16700Schasinglulu } 221*91f16700Schasinglulu if (((tset_mem + twait) < NAND_TRC_MIN) && 222*91f16700Schasinglulu (thold_mem < (NAND_TRC_MIN - (tset_mem + twait)))) { 223*91f16700Schasinglulu thold_mem = NAND_TRC_MIN - (tset_mem + twait); 224*91f16700Schasinglulu } 225*91f16700Schasinglulu if (((tset_mem + twait) < NAND_TWC_MIN) && 226*91f16700Schasinglulu (thold_mem < (NAND_TWC_MIN - (tset_mem + twait)))) { 227*91f16700Schasinglulu thold_mem = NAND_TWC_MIN - (tset_mem + twait); 228*91f16700Schasinglulu } 229*91f16700Schasinglulu timing = div_round_up(thold_mem, hclkp); 230*91f16700Schasinglulu tims.thold_mem = CLAMP(timing, 1UL, 231*91f16700Schasinglulu (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); 232*91f16700Schasinglulu 233*91f16700Schasinglulu /* 234*91f16700Schasinglulu * tSETUP_ATT > tCS - tWAIT 235*91f16700Schasinglulu * tSETUP_ATT > tCLS - tWAIT 236*91f16700Schasinglulu * tSETUP_ATT > tALS - tWAIT 237*91f16700Schasinglulu * tSETUP_ATT > tRHW - tHOLD_MEM 238*91f16700Schasinglulu * tSETUP_ATT > tDS - (tWAIT - tHIZ) 239*91f16700Schasinglulu */ 240*91f16700Schasinglulu tset_att = hclkp; 241*91f16700Schasinglulu if ((twait < NAND_TCS_MIN) && (tset_att < (NAND_TCS_MIN - twait))) { 242*91f16700Schasinglulu tset_att = NAND_TCS_MIN - twait; 243*91f16700Schasinglulu } 244*91f16700Schasinglulu if ((thold_mem < NAND_TRHW_MIN) && 245*91f16700Schasinglulu (tset_att < (NAND_TRHW_MIN - thold_mem))) { 246*91f16700Schasinglulu tset_att = NAND_TRHW_MIN - thold_mem; 247*91f16700Schasinglulu } 248*91f16700Schasinglulu if ((twait > thiz) && ((twait - thiz) < NAND_TDS_MIN) && 249*91f16700Schasinglulu (tset_att < (NAND_TDS_MIN - (twait - thiz)))) { 250*91f16700Schasinglulu tset_att = NAND_TDS_MIN - (twait - thiz); 251*91f16700Schasinglulu } 252*91f16700Schasinglulu timing = div_round_up(tset_att, hclkp); 253*91f16700Schasinglulu tims.tset_att = CLAMP(timing, 1UL, 254*91f16700Schasinglulu (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); 255*91f16700Schasinglulu 256*91f16700Schasinglulu /* 257*91f16700Schasinglulu * tHOLD_ATT > tALH 258*91f16700Schasinglulu * tHOLD_ATT > tCH 259*91f16700Schasinglulu * tHOLD_ATT > tCLH 260*91f16700Schasinglulu * tHOLD_ATT > tCOH 261*91f16700Schasinglulu * tHOLD_ATT > tDH 262*91f16700Schasinglulu * tHOLD_ATT > tWB + tIO + tSYNC - tSETUP_MEM 263*91f16700Schasinglulu * tHOLD_ATT > tADL - tSETUP_MEM 264*91f16700Schasinglulu * tHOLD_ATT > tWH - tSETUP_MEM 265*91f16700Schasinglulu * tHOLD_ATT > tWHR - tSETUP_MEM 266*91f16700Schasinglulu * tHOLD_ATT > tRC - (tSETUP_ATT + tWAIT) 267*91f16700Schasinglulu * tHOLD_ATT > tWC - (tSETUP_ATT + tWAIT) 268*91f16700Schasinglulu */ 269*91f16700Schasinglulu thold_att = MAX(hclkp, NAND_TALH_MIN); 270*91f16700Schasinglulu thold_att = MAX(thold_att, NAND_TCH_MIN); 271*91f16700Schasinglulu thold_att = MAX(thold_att, NAND_TCLH_MIN); 272*91f16700Schasinglulu thold_att = MAX(thold_att, NAND_TCOH_MIN); 273*91f16700Schasinglulu thold_att = MAX(thold_att, NAND_TDH_MIN); 274*91f16700Schasinglulu if (((NAND_TWB_MAX + FMC2_TIO + FMC2_TSYNC) > tset_mem) && 275*91f16700Schasinglulu (thold_att < (NAND_TWB_MAX + FMC2_TIO + FMC2_TSYNC - tset_mem))) { 276*91f16700Schasinglulu thold_att = NAND_TWB_MAX + FMC2_TIO + FMC2_TSYNC - tset_mem; 277*91f16700Schasinglulu } 278*91f16700Schasinglulu if ((tset_mem < NAND_TADL_MIN) && 279*91f16700Schasinglulu (thold_att < (NAND_TADL_MIN - tset_mem))) { 280*91f16700Schasinglulu thold_att = NAND_TADL_MIN - tset_mem; 281*91f16700Schasinglulu } 282*91f16700Schasinglulu if ((tset_mem < NAND_TWH_MIN) && 283*91f16700Schasinglulu (thold_att < (NAND_TWH_MIN - tset_mem))) { 284*91f16700Schasinglulu thold_att = NAND_TWH_MIN - tset_mem; 285*91f16700Schasinglulu } 286*91f16700Schasinglulu if ((tset_mem < NAND_TWHR_MIN) && 287*91f16700Schasinglulu (thold_att < (NAND_TWHR_MIN - tset_mem))) { 288*91f16700Schasinglulu thold_att = NAND_TWHR_MIN - tset_mem; 289*91f16700Schasinglulu } 290*91f16700Schasinglulu if (((tset_att + twait) < NAND_TRC_MIN) && 291*91f16700Schasinglulu (thold_att < (NAND_TRC_MIN - (tset_att + twait)))) { 292*91f16700Schasinglulu thold_att = NAND_TRC_MIN - (tset_att + twait); 293*91f16700Schasinglulu } 294*91f16700Schasinglulu if (((tset_att + twait) < NAND_TWC_MIN) && 295*91f16700Schasinglulu (thold_att < (NAND_TWC_MIN - (tset_att + twait)))) { 296*91f16700Schasinglulu thold_att = NAND_TWC_MIN - (tset_att + twait); 297*91f16700Schasinglulu } 298*91f16700Schasinglulu timing = div_round_up(thold_att, hclkp); 299*91f16700Schasinglulu tims.thold_att = CLAMP(timing, 1UL, 300*91f16700Schasinglulu (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); 301*91f16700Schasinglulu 302*91f16700Schasinglulu VERBOSE("NAND timings: %u - %u - %u - %u - %u - %u - %u - %u\n", 303*91f16700Schasinglulu tims.tclr, tims.tar, tims.thiz, tims.twait, 304*91f16700Schasinglulu tims.thold_mem, tims.tset_mem, 305*91f16700Schasinglulu tims.thold_att, tims.tset_att); 306*91f16700Schasinglulu 307*91f16700Schasinglulu /* Set tclr/tar timings */ 308*91f16700Schasinglulu pcr = mmio_read_32(fmc2_base() + FMC2_PCR); 309*91f16700Schasinglulu pcr &= ~FMC2_PCR_TCLR_MASK; 310*91f16700Schasinglulu pcr |= FMC2_PCR_TCLR(tims.tclr); 311*91f16700Schasinglulu pcr &= ~FMC2_PCR_TAR_MASK; 312*91f16700Schasinglulu pcr |= FMC2_PCR_TAR(tims.tar); 313*91f16700Schasinglulu 314*91f16700Schasinglulu /* Set tset/twait/thold/thiz timings in common bank */ 315*91f16700Schasinglulu pmem = FMC2_PMEM_MEMSET(tims.tset_mem); 316*91f16700Schasinglulu pmem |= FMC2_PMEM_MEMWAIT(tims.twait); 317*91f16700Schasinglulu pmem |= FMC2_PMEM_MEMHOLD(tims.thold_mem); 318*91f16700Schasinglulu pmem |= FMC2_PMEM_MEMHIZ(tims.thiz); 319*91f16700Schasinglulu 320*91f16700Schasinglulu /* Set tset/twait/thold/thiz timings in attribute bank */ 321*91f16700Schasinglulu patt = FMC2_PATT_ATTSET(tims.tset_att); 322*91f16700Schasinglulu patt |= FMC2_PATT_ATTWAIT(tims.twait); 323*91f16700Schasinglulu patt |= FMC2_PATT_ATTHOLD(tims.thold_att); 324*91f16700Schasinglulu patt |= FMC2_PATT_ATTHIZ(tims.thiz); 325*91f16700Schasinglulu 326*91f16700Schasinglulu mmio_write_32(fmc2_base() + FMC2_PCR, pcr); 327*91f16700Schasinglulu mmio_write_32(fmc2_base() + FMC2_PMEM, pmem); 328*91f16700Schasinglulu mmio_write_32(fmc2_base() + FMC2_PATT, patt); 329*91f16700Schasinglulu } 330*91f16700Schasinglulu 331*91f16700Schasinglulu static void stm32_fmc2_set_buswidth_16(bool set) 332*91f16700Schasinglulu { 333*91f16700Schasinglulu mmio_clrsetbits_32(fmc2_base() + FMC2_PCR, FMC2_PCR_PWID_MASK, 334*91f16700Schasinglulu (set ? FMC2_PCR_PWID(FMC2_PCR_PWID_16) : 0U)); 335*91f16700Schasinglulu } 336*91f16700Schasinglulu 337*91f16700Schasinglulu static void stm32_fmc2_set_ecc(bool enable) 338*91f16700Schasinglulu { 339*91f16700Schasinglulu mmio_clrsetbits_32(fmc2_base() + FMC2_PCR, FMC2_PCR_ECCEN, 340*91f16700Schasinglulu (enable ? FMC2_PCR_ECCEN : 0U)); 341*91f16700Schasinglulu } 342*91f16700Schasinglulu 343*91f16700Schasinglulu static int stm32_fmc2_ham_correct(uint8_t *buffer, uint8_t *eccbuffer, 344*91f16700Schasinglulu uint8_t *ecc) 345*91f16700Schasinglulu { 346*91f16700Schasinglulu uint8_t xor_ecc_ones; 347*91f16700Schasinglulu uint16_t xor_ecc_1b, xor_ecc_2b, xor_ecc_3b; 348*91f16700Schasinglulu union { 349*91f16700Schasinglulu uint32_t val; 350*91f16700Schasinglulu uint8_t bytes[4]; 351*91f16700Schasinglulu } xor_ecc; 352*91f16700Schasinglulu 353*91f16700Schasinglulu /* Page size--------ECC_Code Size 354*91f16700Schasinglulu * 256---------------22 bits LSB (ECC_CODE & 0x003FFFFF) 355*91f16700Schasinglulu * 512---------------24 bits (ECC_CODE & 0x00FFFFFF) 356*91f16700Schasinglulu * 1024--------------26 bits (ECC_CODE & 0x03FFFFFF) 357*91f16700Schasinglulu * 2048--------------28 bits (ECC_CODE & 0x0FFFFFFF) 358*91f16700Schasinglulu * 4096--------------30 bits (ECC_CODE & 0x3FFFFFFF) 359*91f16700Schasinglulu * 8192--------------32 bits (ECC_CODE & 0xFFFFFFFF) 360*91f16700Schasinglulu */ 361*91f16700Schasinglulu 362*91f16700Schasinglulu /* For Page size 512, ECC_Code size 24 bits */ 363*91f16700Schasinglulu xor_ecc_1b = ecc[0] ^ eccbuffer[0]; 364*91f16700Schasinglulu xor_ecc_2b = ecc[1] ^ eccbuffer[1]; 365*91f16700Schasinglulu xor_ecc_3b = ecc[2] ^ eccbuffer[2]; 366*91f16700Schasinglulu 367*91f16700Schasinglulu xor_ecc.val = 0U; 368*91f16700Schasinglulu xor_ecc.bytes[2] = xor_ecc_3b; 369*91f16700Schasinglulu xor_ecc.bytes[1] = xor_ecc_2b; 370*91f16700Schasinglulu xor_ecc.bytes[0] = xor_ecc_1b; 371*91f16700Schasinglulu 372*91f16700Schasinglulu if (xor_ecc.val == 0U) { 373*91f16700Schasinglulu return 0; /* No Error */ 374*91f16700Schasinglulu } 375*91f16700Schasinglulu 376*91f16700Schasinglulu xor_ecc_ones = __builtin_popcount(xor_ecc.val); 377*91f16700Schasinglulu if (xor_ecc_ones < 23U) { 378*91f16700Schasinglulu if (xor_ecc_ones == 12U) { 379*91f16700Schasinglulu uint16_t bit_address, byte_address; 380*91f16700Schasinglulu 381*91f16700Schasinglulu /* Correctable ERROR */ 382*91f16700Schasinglulu bit_address = ((xor_ecc_1b >> 1) & BIT(0)) | 383*91f16700Schasinglulu ((xor_ecc_1b >> 2) & BIT(1)) | 384*91f16700Schasinglulu ((xor_ecc_1b >> 3) & BIT(2)); 385*91f16700Schasinglulu 386*91f16700Schasinglulu byte_address = ((xor_ecc_1b >> 7) & BIT(0)) | 387*91f16700Schasinglulu ((xor_ecc_2b) & BIT(1)) | 388*91f16700Schasinglulu ((xor_ecc_2b >> 1) & BIT(2)) | 389*91f16700Schasinglulu ((xor_ecc_2b >> 2) & BIT(3)) | 390*91f16700Schasinglulu ((xor_ecc_2b >> 3) & BIT(4)) | 391*91f16700Schasinglulu ((xor_ecc_3b << 4) & BIT(5)) | 392*91f16700Schasinglulu ((xor_ecc_3b << 3) & BIT(6)) | 393*91f16700Schasinglulu ((xor_ecc_3b << 2) & BIT(7)) | 394*91f16700Schasinglulu ((xor_ecc_3b << 1) & BIT(8)); 395*91f16700Schasinglulu 396*91f16700Schasinglulu /* Correct bit error in the data */ 397*91f16700Schasinglulu buffer[byte_address] = 398*91f16700Schasinglulu buffer[byte_address] ^ BIT(bit_address); 399*91f16700Schasinglulu VERBOSE("Hamming: 1 ECC error corrected\n"); 400*91f16700Schasinglulu 401*91f16700Schasinglulu return 0; 402*91f16700Schasinglulu } 403*91f16700Schasinglulu 404*91f16700Schasinglulu /* Non Correctable ERROR */ 405*91f16700Schasinglulu ERROR("%s: Uncorrectable ECC Errors\n", __func__); 406*91f16700Schasinglulu return -1; 407*91f16700Schasinglulu } 408*91f16700Schasinglulu 409*91f16700Schasinglulu /* ECC ERROR */ 410*91f16700Schasinglulu ERROR("%s: Hamming correction error\n", __func__); 411*91f16700Schasinglulu return -1; 412*91f16700Schasinglulu } 413*91f16700Schasinglulu 414*91f16700Schasinglulu 415*91f16700Schasinglulu static int stm32_fmc2_ham_calculate(uint8_t *buffer, uint8_t *ecc) 416*91f16700Schasinglulu { 417*91f16700Schasinglulu uint32_t heccr; 418*91f16700Schasinglulu uint64_t timeout = timeout_init_us(TIMEOUT_US_10_MS); 419*91f16700Schasinglulu 420*91f16700Schasinglulu while ((mmio_read_32(fmc2_base() + FMC2_SR) & FMC2_SR_NWRF) == 0U) { 421*91f16700Schasinglulu if (timeout_elapsed(timeout)) { 422*91f16700Schasinglulu return -ETIMEDOUT; 423*91f16700Schasinglulu } 424*91f16700Schasinglulu } 425*91f16700Schasinglulu 426*91f16700Schasinglulu heccr = mmio_read_32(fmc2_base() + FMC2_HECCR); 427*91f16700Schasinglulu 428*91f16700Schasinglulu ecc[0] = heccr; 429*91f16700Schasinglulu ecc[1] = heccr >> 8; 430*91f16700Schasinglulu ecc[2] = heccr >> 16; 431*91f16700Schasinglulu 432*91f16700Schasinglulu /* Disable ECC */ 433*91f16700Schasinglulu stm32_fmc2_set_ecc(false); 434*91f16700Schasinglulu 435*91f16700Schasinglulu return 0; 436*91f16700Schasinglulu } 437*91f16700Schasinglulu 438*91f16700Schasinglulu static int stm32_fmc2_bch_correct(uint8_t *buffer, unsigned int eccsize) 439*91f16700Schasinglulu { 440*91f16700Schasinglulu uint32_t bchdsr0, bchdsr1, bchdsr2, bchdsr3, bchdsr4; 441*91f16700Schasinglulu uint16_t pos[8]; 442*91f16700Schasinglulu int i, den; 443*91f16700Schasinglulu uint64_t timeout = timeout_init_us(TIMEOUT_US_10_MS); 444*91f16700Schasinglulu 445*91f16700Schasinglulu while ((mmio_read_32(fmc2_base() + FMC2_BCHISR) & 446*91f16700Schasinglulu FMC2_BCHISR_DERF) == 0U) { 447*91f16700Schasinglulu if (timeout_elapsed(timeout)) { 448*91f16700Schasinglulu return -ETIMEDOUT; 449*91f16700Schasinglulu } 450*91f16700Schasinglulu } 451*91f16700Schasinglulu 452*91f16700Schasinglulu bchdsr0 = mmio_read_32(fmc2_base() + FMC2_BCHDSR0); 453*91f16700Schasinglulu bchdsr1 = mmio_read_32(fmc2_base() + FMC2_BCHDSR1); 454*91f16700Schasinglulu bchdsr2 = mmio_read_32(fmc2_base() + FMC2_BCHDSR2); 455*91f16700Schasinglulu bchdsr3 = mmio_read_32(fmc2_base() + FMC2_BCHDSR3); 456*91f16700Schasinglulu bchdsr4 = mmio_read_32(fmc2_base() + FMC2_BCHDSR4); 457*91f16700Schasinglulu 458*91f16700Schasinglulu /* Disable ECC */ 459*91f16700Schasinglulu stm32_fmc2_set_ecc(false); 460*91f16700Schasinglulu 461*91f16700Schasinglulu /* No error found */ 462*91f16700Schasinglulu if ((bchdsr0 & FMC2_BCHDSR0_DEF) == 0U) { 463*91f16700Schasinglulu return 0; 464*91f16700Schasinglulu } 465*91f16700Schasinglulu 466*91f16700Schasinglulu /* Too many errors detected */ 467*91f16700Schasinglulu if ((bchdsr0 & FMC2_BCHDSR0_DUE) != 0U) { 468*91f16700Schasinglulu return -EBADMSG; 469*91f16700Schasinglulu } 470*91f16700Schasinglulu 471*91f16700Schasinglulu pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK; 472*91f16700Schasinglulu pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT; 473*91f16700Schasinglulu pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK; 474*91f16700Schasinglulu pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT; 475*91f16700Schasinglulu pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK; 476*91f16700Schasinglulu pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT; 477*91f16700Schasinglulu pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK; 478*91f16700Schasinglulu pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT; 479*91f16700Schasinglulu 480*91f16700Schasinglulu den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT; 481*91f16700Schasinglulu for (i = 0; i < den; i++) { 482*91f16700Schasinglulu if (pos[i] < (eccsize * 8U)) { 483*91f16700Schasinglulu uint8_t bitmask = BIT(pos[i] % 8U); 484*91f16700Schasinglulu uint32_t offset = pos[i] / 8U; 485*91f16700Schasinglulu 486*91f16700Schasinglulu *(buffer + offset) ^= bitmask; 487*91f16700Schasinglulu } 488*91f16700Schasinglulu } 489*91f16700Schasinglulu 490*91f16700Schasinglulu return 0; 491*91f16700Schasinglulu } 492*91f16700Schasinglulu 493*91f16700Schasinglulu static void stm32_fmc2_hwctl(struct nand_device *nand) 494*91f16700Schasinglulu { 495*91f16700Schasinglulu stm32_fmc2_set_ecc(false); 496*91f16700Schasinglulu 497*91f16700Schasinglulu if (nand->ecc.max_bit_corr != FMC2_ECC_HAM) { 498*91f16700Schasinglulu mmio_clrbits_32(fmc2_base() + FMC2_PCR, FMC2_PCR_WEN); 499*91f16700Schasinglulu mmio_write_32(fmc2_base() + FMC2_BCHICR, FMC2_BCHICR_CLEAR_IRQ); 500*91f16700Schasinglulu } 501*91f16700Schasinglulu 502*91f16700Schasinglulu stm32_fmc2_set_ecc(true); 503*91f16700Schasinglulu } 504*91f16700Schasinglulu 505*91f16700Schasinglulu static int stm32_fmc2_read_page(struct nand_device *nand, 506*91f16700Schasinglulu unsigned int page, uintptr_t buffer) 507*91f16700Schasinglulu { 508*91f16700Schasinglulu unsigned int eccsize = nand->ecc.size; 509*91f16700Schasinglulu unsigned int eccbytes = nand->ecc.bytes; 510*91f16700Schasinglulu unsigned int eccsteps = nand->page_size / eccsize; 511*91f16700Schasinglulu uint8_t ecc_corr[FMC2_MAX_ECC_BYTES]; 512*91f16700Schasinglulu uint8_t ecc_cal[FMC2_MAX_ECC_BYTES] = {0U}; 513*91f16700Schasinglulu uint8_t *p; 514*91f16700Schasinglulu unsigned int i; 515*91f16700Schasinglulu unsigned int s; 516*91f16700Schasinglulu int ret; 517*91f16700Schasinglulu 518*91f16700Schasinglulu VERBOSE(">%s page %u buffer %lx\n", __func__, page, buffer); 519*91f16700Schasinglulu 520*91f16700Schasinglulu ret = nand_read_page_cmd(page, 0U, 0U, 0U); 521*91f16700Schasinglulu if (ret != 0) { 522*91f16700Schasinglulu return ret; 523*91f16700Schasinglulu } 524*91f16700Schasinglulu 525*91f16700Schasinglulu for (s = 0U, i = nand->page_size + FMC2_BBM_LEN, p = (uint8_t *)buffer; 526*91f16700Schasinglulu s < eccsteps; 527*91f16700Schasinglulu s++, i += eccbytes, p += eccsize) { 528*91f16700Schasinglulu stm32_fmc2_hwctl(nand); 529*91f16700Schasinglulu 530*91f16700Schasinglulu /* Read the NAND page sector (512 bytes) */ 531*91f16700Schasinglulu ret = nand_change_read_column_cmd(s * eccsize, (uintptr_t)p, 532*91f16700Schasinglulu eccsize); 533*91f16700Schasinglulu if (ret != 0) { 534*91f16700Schasinglulu return ret; 535*91f16700Schasinglulu } 536*91f16700Schasinglulu 537*91f16700Schasinglulu if (nand->ecc.max_bit_corr == FMC2_ECC_HAM) { 538*91f16700Schasinglulu ret = stm32_fmc2_ham_calculate(p, ecc_cal); 539*91f16700Schasinglulu if (ret != 0) { 540*91f16700Schasinglulu return ret; 541*91f16700Schasinglulu } 542*91f16700Schasinglulu } 543*91f16700Schasinglulu 544*91f16700Schasinglulu /* Read the corresponding ECC bytes */ 545*91f16700Schasinglulu ret = nand_change_read_column_cmd(i, (uintptr_t)ecc_corr, 546*91f16700Schasinglulu eccbytes); 547*91f16700Schasinglulu if (ret != 0) { 548*91f16700Schasinglulu return ret; 549*91f16700Schasinglulu } 550*91f16700Schasinglulu 551*91f16700Schasinglulu /* Correct the data */ 552*91f16700Schasinglulu if (nand->ecc.max_bit_corr == FMC2_ECC_HAM) { 553*91f16700Schasinglulu ret = stm32_fmc2_ham_correct(p, ecc_corr, ecc_cal); 554*91f16700Schasinglulu } else { 555*91f16700Schasinglulu ret = stm32_fmc2_bch_correct(p, eccsize); 556*91f16700Schasinglulu } 557*91f16700Schasinglulu 558*91f16700Schasinglulu if (ret != 0) { 559*91f16700Schasinglulu return ret; 560*91f16700Schasinglulu } 561*91f16700Schasinglulu } 562*91f16700Schasinglulu 563*91f16700Schasinglulu return 0; 564*91f16700Schasinglulu } 565*91f16700Schasinglulu 566*91f16700Schasinglulu static void stm32_fmc2_read_data(struct nand_device *nand, 567*91f16700Schasinglulu uint8_t *buff, unsigned int length, 568*91f16700Schasinglulu bool use_bus8) 569*91f16700Schasinglulu { 570*91f16700Schasinglulu uintptr_t data_base = stm32_fmc2.cs[stm32_fmc2.cs_sel].data_base; 571*91f16700Schasinglulu 572*91f16700Schasinglulu if (use_bus8 && (nand->buswidth == NAND_BUS_WIDTH_16)) { 573*91f16700Schasinglulu stm32_fmc2_set_buswidth_16(false); 574*91f16700Schasinglulu } 575*91f16700Schasinglulu 576*91f16700Schasinglulu if ((((uintptr_t)buff & BIT(0)) != 0U) && (length != 0U)) { 577*91f16700Schasinglulu *buff = mmio_read_8(data_base); 578*91f16700Schasinglulu buff += sizeof(uint8_t); 579*91f16700Schasinglulu length -= sizeof(uint8_t); 580*91f16700Schasinglulu } 581*91f16700Schasinglulu 582*91f16700Schasinglulu if ((((uintptr_t)buff & GENMASK_32(1, 0)) != 0U) && 583*91f16700Schasinglulu (length >= sizeof(uint16_t))) { 584*91f16700Schasinglulu *(uint16_t *)buff = mmio_read_16(data_base); 585*91f16700Schasinglulu buff += sizeof(uint16_t); 586*91f16700Schasinglulu length -= sizeof(uint16_t); 587*91f16700Schasinglulu } 588*91f16700Schasinglulu 589*91f16700Schasinglulu /* 32bit aligned */ 590*91f16700Schasinglulu while (length >= sizeof(uint32_t)) { 591*91f16700Schasinglulu *(uint32_t *)buff = mmio_read_32(data_base); 592*91f16700Schasinglulu buff += sizeof(uint32_t); 593*91f16700Schasinglulu length -= sizeof(uint32_t); 594*91f16700Schasinglulu } 595*91f16700Schasinglulu 596*91f16700Schasinglulu /* Read remaining bytes */ 597*91f16700Schasinglulu if (length >= sizeof(uint16_t)) { 598*91f16700Schasinglulu *(uint16_t *)buff = mmio_read_16(data_base); 599*91f16700Schasinglulu buff += sizeof(uint16_t); 600*91f16700Schasinglulu length -= sizeof(uint16_t); 601*91f16700Schasinglulu } 602*91f16700Schasinglulu 603*91f16700Schasinglulu if (length != 0U) { 604*91f16700Schasinglulu *buff = mmio_read_8(data_base); 605*91f16700Schasinglulu } 606*91f16700Schasinglulu 607*91f16700Schasinglulu if (use_bus8 && (nand->buswidth == NAND_BUS_WIDTH_16)) { 608*91f16700Schasinglulu /* Reconfigure bus width to 16-bit */ 609*91f16700Schasinglulu stm32_fmc2_set_buswidth_16(true); 610*91f16700Schasinglulu } 611*91f16700Schasinglulu } 612*91f16700Schasinglulu 613*91f16700Schasinglulu static void stm32_fmc2_write_data(struct nand_device *nand, 614*91f16700Schasinglulu uint8_t *buff, unsigned int length, 615*91f16700Schasinglulu bool use_bus8) 616*91f16700Schasinglulu { 617*91f16700Schasinglulu uintptr_t data_base = stm32_fmc2.cs[stm32_fmc2.cs_sel].data_base; 618*91f16700Schasinglulu 619*91f16700Schasinglulu if (use_bus8 && (nand->buswidth == NAND_BUS_WIDTH_16)) { 620*91f16700Schasinglulu /* Reconfigure bus width to 8-bit */ 621*91f16700Schasinglulu stm32_fmc2_set_buswidth_16(false); 622*91f16700Schasinglulu } 623*91f16700Schasinglulu 624*91f16700Schasinglulu if ((((uintptr_t)buff & BIT(0)) != 0U) && (length != 0U)) { 625*91f16700Schasinglulu mmio_write_8(data_base, *buff); 626*91f16700Schasinglulu buff += sizeof(uint8_t); 627*91f16700Schasinglulu length -= sizeof(uint8_t); 628*91f16700Schasinglulu } 629*91f16700Schasinglulu 630*91f16700Schasinglulu if ((((uintptr_t)buff & GENMASK_32(1, 0)) != 0U) && 631*91f16700Schasinglulu (length >= sizeof(uint16_t))) { 632*91f16700Schasinglulu mmio_write_16(data_base, *(uint16_t *)buff); 633*91f16700Schasinglulu buff += sizeof(uint16_t); 634*91f16700Schasinglulu length -= sizeof(uint16_t); 635*91f16700Schasinglulu } 636*91f16700Schasinglulu 637*91f16700Schasinglulu /* 32bits aligned */ 638*91f16700Schasinglulu while (length >= sizeof(uint32_t)) { 639*91f16700Schasinglulu mmio_write_32(data_base, *(uint32_t *)buff); 640*91f16700Schasinglulu buff += sizeof(uint32_t); 641*91f16700Schasinglulu length -= sizeof(uint32_t); 642*91f16700Schasinglulu } 643*91f16700Schasinglulu 644*91f16700Schasinglulu /* Read remaining bytes */ 645*91f16700Schasinglulu if (length >= sizeof(uint16_t)) { 646*91f16700Schasinglulu mmio_write_16(data_base, *(uint16_t *)buff); 647*91f16700Schasinglulu buff += sizeof(uint16_t); 648*91f16700Schasinglulu length -= sizeof(uint16_t); 649*91f16700Schasinglulu } 650*91f16700Schasinglulu 651*91f16700Schasinglulu if (length != 0U) { 652*91f16700Schasinglulu mmio_write_8(data_base, *buff); 653*91f16700Schasinglulu } 654*91f16700Schasinglulu 655*91f16700Schasinglulu if (use_bus8 && (nand->buswidth == NAND_BUS_WIDTH_16)) { 656*91f16700Schasinglulu /* Reconfigure bus width to 16-bit */ 657*91f16700Schasinglulu stm32_fmc2_set_buswidth_16(true); 658*91f16700Schasinglulu } 659*91f16700Schasinglulu } 660*91f16700Schasinglulu 661*91f16700Schasinglulu static void stm32_fmc2_ctrl_init(void) 662*91f16700Schasinglulu { 663*91f16700Schasinglulu uint32_t pcr = mmio_read_32(fmc2_base() + FMC2_PCR); 664*91f16700Schasinglulu uint32_t bcr1 = mmio_read_32(fmc2_base() + FMC2_BCR1); 665*91f16700Schasinglulu 666*91f16700Schasinglulu /* Enable wait feature and NAND flash memory bank */ 667*91f16700Schasinglulu pcr |= FMC2_PCR_PWAITEN; 668*91f16700Schasinglulu pcr |= FMC2_PCR_PBKEN; 669*91f16700Schasinglulu 670*91f16700Schasinglulu /* Set buswidth to 8 bits mode for identification */ 671*91f16700Schasinglulu pcr &= ~FMC2_PCR_PWID_MASK; 672*91f16700Schasinglulu 673*91f16700Schasinglulu /* ECC logic is disabled */ 674*91f16700Schasinglulu pcr &= ~FMC2_PCR_ECCEN; 675*91f16700Schasinglulu 676*91f16700Schasinglulu /* Default mode */ 677*91f16700Schasinglulu pcr &= ~FMC2_PCR_ECCALG; 678*91f16700Schasinglulu pcr &= ~FMC2_PCR_BCHECC; 679*91f16700Schasinglulu pcr &= ~FMC2_PCR_WEN; 680*91f16700Schasinglulu 681*91f16700Schasinglulu /* Set default ECC sector size */ 682*91f16700Schasinglulu pcr &= ~FMC2_PCR_ECCSS_MASK; 683*91f16700Schasinglulu pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048); 684*91f16700Schasinglulu 685*91f16700Schasinglulu /* Set default TCLR/TAR timings */ 686*91f16700Schasinglulu pcr &= ~FMC2_PCR_TCLR_MASK; 687*91f16700Schasinglulu pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT); 688*91f16700Schasinglulu pcr &= ~FMC2_PCR_TAR_MASK; 689*91f16700Schasinglulu pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT); 690*91f16700Schasinglulu 691*91f16700Schasinglulu /* Enable FMC2 controller */ 692*91f16700Schasinglulu bcr1 |= FMC2_BCR1_FMC2EN; 693*91f16700Schasinglulu 694*91f16700Schasinglulu mmio_write_32(fmc2_base() + FMC2_BCR1, bcr1); 695*91f16700Schasinglulu mmio_write_32(fmc2_base() + FMC2_PCR, pcr); 696*91f16700Schasinglulu mmio_write_32(fmc2_base() + FMC2_PMEM, FMC2_PMEM_DEFAULT); 697*91f16700Schasinglulu mmio_write_32(fmc2_base() + FMC2_PATT, FMC2_PATT_DEFAULT); 698*91f16700Schasinglulu } 699*91f16700Schasinglulu 700*91f16700Schasinglulu static int stm32_fmc2_exec(struct nand_req *req) 701*91f16700Schasinglulu { 702*91f16700Schasinglulu int ret = 0; 703*91f16700Schasinglulu 704*91f16700Schasinglulu switch (req->type & NAND_REQ_MASK) { 705*91f16700Schasinglulu case NAND_REQ_CMD: 706*91f16700Schasinglulu VERBOSE("Write CMD %x\n", (uint8_t)req->type); 707*91f16700Schasinglulu mmio_write_8(stm32_fmc2.cs[stm32_fmc2.cs_sel].cmd_base, 708*91f16700Schasinglulu (uint8_t)req->type); 709*91f16700Schasinglulu break; 710*91f16700Schasinglulu case NAND_REQ_ADDR: 711*91f16700Schasinglulu VERBOSE("Write ADDR %x\n", *(req->addr)); 712*91f16700Schasinglulu mmio_write_8(stm32_fmc2.cs[stm32_fmc2.cs_sel].addr_base, 713*91f16700Schasinglulu *(req->addr)); 714*91f16700Schasinglulu break; 715*91f16700Schasinglulu case NAND_REQ_DATAIN: 716*91f16700Schasinglulu VERBOSE("Read data\n"); 717*91f16700Schasinglulu stm32_fmc2_read_data(req->nand, req->addr, req->length, 718*91f16700Schasinglulu ((req->type & NAND_REQ_BUS_WIDTH_8) != 719*91f16700Schasinglulu 0U)); 720*91f16700Schasinglulu break; 721*91f16700Schasinglulu case NAND_REQ_DATAOUT: 722*91f16700Schasinglulu VERBOSE("Write data\n"); 723*91f16700Schasinglulu stm32_fmc2_write_data(req->nand, req->addr, req->length, 724*91f16700Schasinglulu ((req->type & NAND_REQ_BUS_WIDTH_8) != 725*91f16700Schasinglulu 0U)); 726*91f16700Schasinglulu break; 727*91f16700Schasinglulu case NAND_REQ_WAIT: 728*91f16700Schasinglulu VERBOSE("WAIT Ready\n"); 729*91f16700Schasinglulu ret = nand_wait_ready(req->delay_ms); 730*91f16700Schasinglulu break; 731*91f16700Schasinglulu default: 732*91f16700Schasinglulu ret = -EINVAL; 733*91f16700Schasinglulu break; 734*91f16700Schasinglulu }; 735*91f16700Schasinglulu 736*91f16700Schasinglulu return ret; 737*91f16700Schasinglulu } 738*91f16700Schasinglulu 739*91f16700Schasinglulu static void stm32_fmc2_setup(struct nand_device *nand) 740*91f16700Schasinglulu { 741*91f16700Schasinglulu uint32_t pcr = mmio_read_32(fmc2_base() + FMC2_PCR); 742*91f16700Schasinglulu 743*91f16700Schasinglulu /* Set buswidth */ 744*91f16700Schasinglulu pcr &= ~FMC2_PCR_PWID_MASK; 745*91f16700Schasinglulu if (nand->buswidth == NAND_BUS_WIDTH_16) { 746*91f16700Schasinglulu pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_16); 747*91f16700Schasinglulu } 748*91f16700Schasinglulu 749*91f16700Schasinglulu if (nand->ecc.mode == NAND_ECC_HW) { 750*91f16700Schasinglulu nand->mtd_read_page = stm32_fmc2_read_page; 751*91f16700Schasinglulu 752*91f16700Schasinglulu pcr &= ~FMC2_PCR_ECCALG; 753*91f16700Schasinglulu pcr &= ~FMC2_PCR_BCHECC; 754*91f16700Schasinglulu 755*91f16700Schasinglulu pcr &= ~FMC2_PCR_ECCSS_MASK; 756*91f16700Schasinglulu pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512); 757*91f16700Schasinglulu 758*91f16700Schasinglulu switch (nand->ecc.max_bit_corr) { 759*91f16700Schasinglulu case FMC2_ECC_HAM: 760*91f16700Schasinglulu nand->ecc.bytes = 3; 761*91f16700Schasinglulu break; 762*91f16700Schasinglulu case FMC2_ECC_BCH8: 763*91f16700Schasinglulu pcr |= FMC2_PCR_ECCALG; 764*91f16700Schasinglulu pcr |= FMC2_PCR_BCHECC; 765*91f16700Schasinglulu nand->ecc.bytes = 13; 766*91f16700Schasinglulu break; 767*91f16700Schasinglulu default: 768*91f16700Schasinglulu /* Use FMC2 ECC BCH4 */ 769*91f16700Schasinglulu pcr |= FMC2_PCR_ECCALG; 770*91f16700Schasinglulu nand->ecc.bytes = 7; 771*91f16700Schasinglulu break; 772*91f16700Schasinglulu } 773*91f16700Schasinglulu 774*91f16700Schasinglulu if ((nand->buswidth & NAND_BUS_WIDTH_16) != 0) { 775*91f16700Schasinglulu nand->ecc.bytes++; 776*91f16700Schasinglulu } 777*91f16700Schasinglulu } 778*91f16700Schasinglulu 779*91f16700Schasinglulu mmio_write_32(stm32_fmc2.reg_base + FMC2_PCR, pcr); 780*91f16700Schasinglulu } 781*91f16700Schasinglulu 782*91f16700Schasinglulu static const struct nand_ctrl_ops ctrl_ops = { 783*91f16700Schasinglulu .setup = stm32_fmc2_setup, 784*91f16700Schasinglulu .exec = stm32_fmc2_exec 785*91f16700Schasinglulu }; 786*91f16700Schasinglulu 787*91f16700Schasinglulu int stm32_fmc2_init(void) 788*91f16700Schasinglulu { 789*91f16700Schasinglulu int fmc_ebi_node; 790*91f16700Schasinglulu int fmc_nfc_node; 791*91f16700Schasinglulu int fmc_flash_node = 0; 792*91f16700Schasinglulu int nchips = 0; 793*91f16700Schasinglulu unsigned int i; 794*91f16700Schasinglulu void *fdt = NULL; 795*91f16700Schasinglulu const fdt32_t *cuint; 796*91f16700Schasinglulu struct dt_node_info info; 797*91f16700Schasinglulu uintptr_t bank_address[MAX_BANK] = { 0, 0, 0, 0, 0 }; 798*91f16700Schasinglulu uint8_t bank_assigned = 0; 799*91f16700Schasinglulu uint8_t bank; 800*91f16700Schasinglulu int ret; 801*91f16700Schasinglulu 802*91f16700Schasinglulu if (fdt_get_address(&fdt) == 0) { 803*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 804*91f16700Schasinglulu } 805*91f16700Schasinglulu 806*91f16700Schasinglulu fmc_ebi_node = dt_get_node(&info, -1, DT_FMC2_EBI_COMPAT); 807*91f16700Schasinglulu if (fmc_ebi_node < 0) { 808*91f16700Schasinglulu return fmc_ebi_node; 809*91f16700Schasinglulu } 810*91f16700Schasinglulu 811*91f16700Schasinglulu if (info.status == DT_DISABLED) { 812*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 813*91f16700Schasinglulu } 814*91f16700Schasinglulu 815*91f16700Schasinglulu stm32_fmc2.reg_base = info.base; 816*91f16700Schasinglulu 817*91f16700Schasinglulu if ((info.clock < 0) || (info.reset < 0)) { 818*91f16700Schasinglulu return -FDT_ERR_BADVALUE; 819*91f16700Schasinglulu } 820*91f16700Schasinglulu 821*91f16700Schasinglulu stm32_fmc2.clock_id = (unsigned long)info.clock; 822*91f16700Schasinglulu stm32_fmc2.reset_id = (unsigned int)info.reset; 823*91f16700Schasinglulu 824*91f16700Schasinglulu cuint = fdt_getprop(fdt, fmc_ebi_node, "ranges", NULL); 825*91f16700Schasinglulu if (cuint == NULL) { 826*91f16700Schasinglulu return -FDT_ERR_BADVALUE; 827*91f16700Schasinglulu } 828*91f16700Schasinglulu 829*91f16700Schasinglulu for (i = 0U; i < MAX_BANK; i++) { 830*91f16700Schasinglulu bank = fdt32_to_cpu(*cuint); 831*91f16700Schasinglulu if ((bank >= MAX_BANK) || ((bank_assigned & BIT(bank)) != 0U)) { 832*91f16700Schasinglulu return -FDT_ERR_BADVALUE; 833*91f16700Schasinglulu } 834*91f16700Schasinglulu bank_assigned |= BIT(bank); 835*91f16700Schasinglulu bank_address[bank] = fdt32_to_cpu(*(cuint + 2)); 836*91f16700Schasinglulu cuint += 4; 837*91f16700Schasinglulu } 838*91f16700Schasinglulu 839*91f16700Schasinglulu /* Pinctrl initialization */ 840*91f16700Schasinglulu if (dt_set_pinctrl_config(fmc_ebi_node) != 0) { 841*91f16700Schasinglulu return -FDT_ERR_BADVALUE; 842*91f16700Schasinglulu } 843*91f16700Schasinglulu 844*91f16700Schasinglulu /* Parse NFC controller node */ 845*91f16700Schasinglulu fmc_nfc_node = fdt_node_offset_by_compatible(fdt, fmc_ebi_node, 846*91f16700Schasinglulu DT_FMC2_NFC_COMPAT); 847*91f16700Schasinglulu if (fmc_nfc_node < 0) { 848*91f16700Schasinglulu return fmc_nfc_node; 849*91f16700Schasinglulu } 850*91f16700Schasinglulu 851*91f16700Schasinglulu if (fdt_get_status(fmc_nfc_node) == DT_DISABLED) { 852*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 853*91f16700Schasinglulu } 854*91f16700Schasinglulu 855*91f16700Schasinglulu cuint = fdt_getprop(fdt, fmc_nfc_node, "reg", NULL); 856*91f16700Schasinglulu if (cuint == NULL) { 857*91f16700Schasinglulu return -FDT_ERR_BADVALUE; 858*91f16700Schasinglulu } 859*91f16700Schasinglulu 860*91f16700Schasinglulu for (i = 0U; i < MAX_CS; i++) { 861*91f16700Schasinglulu bank = fdt32_to_cpu(*cuint); 862*91f16700Schasinglulu if (bank >= MAX_BANK) { 863*91f16700Schasinglulu return -FDT_ERR_BADVALUE; 864*91f16700Schasinglulu } 865*91f16700Schasinglulu stm32_fmc2.cs[i].data_base = fdt32_to_cpu(*(cuint + 1)) + 866*91f16700Schasinglulu bank_address[bank]; 867*91f16700Schasinglulu 868*91f16700Schasinglulu bank = fdt32_to_cpu(*(cuint + 3)); 869*91f16700Schasinglulu if (bank >= MAX_BANK) { 870*91f16700Schasinglulu return -FDT_ERR_BADVALUE; 871*91f16700Schasinglulu } 872*91f16700Schasinglulu stm32_fmc2.cs[i].cmd_base = fdt32_to_cpu(*(cuint + 4)) + 873*91f16700Schasinglulu bank_address[bank]; 874*91f16700Schasinglulu 875*91f16700Schasinglulu bank = fdt32_to_cpu(*(cuint + 6)); 876*91f16700Schasinglulu if (bank >= MAX_BANK) { 877*91f16700Schasinglulu return -FDT_ERR_BADVALUE; 878*91f16700Schasinglulu } 879*91f16700Schasinglulu stm32_fmc2.cs[i].addr_base = fdt32_to_cpu(*(cuint + 7)) + 880*91f16700Schasinglulu bank_address[bank]; 881*91f16700Schasinglulu 882*91f16700Schasinglulu cuint += 9; 883*91f16700Schasinglulu } 884*91f16700Schasinglulu 885*91f16700Schasinglulu /* Parse flash nodes */ 886*91f16700Schasinglulu fdt_for_each_subnode(fmc_flash_node, fdt, fmc_nfc_node) { 887*91f16700Schasinglulu nchips++; 888*91f16700Schasinglulu } 889*91f16700Schasinglulu 890*91f16700Schasinglulu if (nchips != 1) { 891*91f16700Schasinglulu WARN("Only one SLC NAND device supported\n"); 892*91f16700Schasinglulu return -FDT_ERR_BADVALUE; 893*91f16700Schasinglulu } 894*91f16700Schasinglulu 895*91f16700Schasinglulu fdt_for_each_subnode(fmc_flash_node, fdt, fmc_nfc_node) { 896*91f16700Schasinglulu /* Get chip select */ 897*91f16700Schasinglulu cuint = fdt_getprop(fdt, fmc_flash_node, "reg", NULL); 898*91f16700Schasinglulu if (cuint == NULL) { 899*91f16700Schasinglulu WARN("Chip select not well defined\n"); 900*91f16700Schasinglulu return -FDT_ERR_BADVALUE; 901*91f16700Schasinglulu } 902*91f16700Schasinglulu 903*91f16700Schasinglulu stm32_fmc2.cs_sel = fdt32_to_cpu(*cuint); 904*91f16700Schasinglulu if (stm32_fmc2.cs_sel >= MAX_CS) { 905*91f16700Schasinglulu return -FDT_ERR_BADVALUE; 906*91f16700Schasinglulu } 907*91f16700Schasinglulu 908*91f16700Schasinglulu VERBOSE("NAND CS %i\n", stm32_fmc2.cs_sel); 909*91f16700Schasinglulu } 910*91f16700Schasinglulu 911*91f16700Schasinglulu /* Enable Clock */ 912*91f16700Schasinglulu clk_enable(stm32_fmc2.clock_id); 913*91f16700Schasinglulu 914*91f16700Schasinglulu /* Reset IP */ 915*91f16700Schasinglulu ret = stm32mp_reset_assert(stm32_fmc2.reset_id, TIMEOUT_US_1_MS); 916*91f16700Schasinglulu if (ret != 0) { 917*91f16700Schasinglulu panic(); 918*91f16700Schasinglulu } 919*91f16700Schasinglulu ret = stm32mp_reset_deassert(stm32_fmc2.reset_id, TIMEOUT_US_1_MS); 920*91f16700Schasinglulu if (ret != 0) { 921*91f16700Schasinglulu panic(); 922*91f16700Schasinglulu } 923*91f16700Schasinglulu 924*91f16700Schasinglulu /* Setup default IP registers */ 925*91f16700Schasinglulu stm32_fmc2_ctrl_init(); 926*91f16700Schasinglulu 927*91f16700Schasinglulu /* Setup default timings */ 928*91f16700Schasinglulu stm32_fmc2_nand_setup_timing(); 929*91f16700Schasinglulu 930*91f16700Schasinglulu /* Init NAND RAW framework */ 931*91f16700Schasinglulu nand_raw_ctrl_init(&ctrl_ops); 932*91f16700Schasinglulu 933*91f16700Schasinglulu return 0; 934*91f16700Schasinglulu } 935