1 /* 2 * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0 5 */ 6 7 #include <common.h> 8 #include <linux/compat.h> 9 #include <linux/delay.h> 10 11 #include "flash.h" 12 #include "flash_com.h" 13 #include "nandc.h" 14 #include "typedef.h" 15 16 #define CPU_DELAY_NS(n) ndelay(n) 17 18 #define NANDC_MASTER_EN 19 20 void __iomem *nandc_base; 21 22 static u32 g_nandc_ecc_bits; 23 #ifdef NANDC_MASTER_EN 24 static struct MASTER_INFO_T master; 25 static u32 *g_master_temp_buf; 26 #endif 27 28 void nandc_init(void __iomem *nandc_addr) 29 { 30 union FM_CTL_T ctl_reg; 31 32 nandc_base = nandc_addr; 33 34 ctl_reg.d32 = 0; 35 ctl_reg.V6.wp = 1; 36 nandc_writel(ctl_reg.d32, NANDC_FMCTL); 37 nandc_writel(0, NANDC_RANDMZ_CFG); 38 nandc_time_cfg(40); 39 40 #ifdef NANDC_MASTER_EN 41 if (!g_master_temp_buf) 42 g_master_temp_buf = (u32 *)ftl_malloc(MAX_FLASH_PAGE_SIZE + 43 MAX_FLASH_PAGE_SIZE / 8); 44 master.page_buf = &g_master_temp_buf[0]; 45 master.spare_buf = &g_master_temp_buf[MAX_FLASH_PAGE_SIZE / 4]; 46 master.mapped = 0; 47 #endif 48 } 49 50 void nandc_flash_cs(u8 chip_sel) 51 { 52 union FM_CTL_T tmp; 53 54 tmp.d32 = nandc_readl(NANDC_FMCTL); 55 tmp.V6.cs = 0x01 << chip_sel; 56 nandc_writel(tmp.d32, NANDC_FMCTL); 57 } 58 59 void nandc_flash_de_cs(u8 chip_sel) 60 { 61 union FM_CTL_T tmp; 62 63 tmp.d32 = nandc_readl(NANDC_FMCTL); 64 tmp.V6.cs = 0; 65 tmp.V6.flash_abort_clear = 0; 66 nandc_writel(tmp.d32, NANDC_FMCTL); 67 } 68 69 u32 nandc_delayns(u32 count) 70 { 71 CPU_DELAY_NS(count); 72 return 0; 73 } 74 75 u32 nandc_wait_flash_ready(u8 chip_sel) 76 { 77 union FM_CTL_T tmp; 78 u32 status; 79 u32 i; 80 81 status = 0; 82 for (i = 0; i < 100000; i++) { 83 nandc_delayns(100); 84 tmp.d32 = nandc_readl(NANDC_FMCTL); 85 if (tmp.V6.rdy != 0) 86 break; 87 } 88 89 if (i >= 100000) 90 status = -1; 91 return status; 92 } 93 94 void nandc_randmz_sel(u8 chip_sel, u32 randmz_seed) 95 { 96 nandc_writel(randmz_seed, NANDC_RANDMZ_CFG); 97 } 98 99 void nandc_time_cfg(u32 ns) 100 { 101 if (ns < 36) 102 nandc_writel(0x1061, NANDC_FMWAIT); 103 else if (ns >= 100) 104 nandc_writel(0x2082, NANDC_FMWAIT); 105 else 106 nandc_writel(0x1081, NANDC_FMWAIT); 107 } 108 109 void nandc_bch_sel(u8 bits) 110 { 111 union BCH_CTL_T tmp; 112 union FL_CTL_T fl_reg; 113 114 fl_reg.d32 = 0; 115 fl_reg.V6.rst = 1; 116 nandc_writel(fl_reg.d32, NANDC_FLCTL); 117 g_nandc_ecc_bits = bits; 118 tmp.d32 = 0; 119 tmp.V6.addr = 0x10; 120 tmp.V6.bch_mode1 = 0; 121 if (bits == 16) { 122 tmp.V6.bch_mode = 0; 123 } else if (bits == 24) { 124 tmp.V6.bch_mode = 1; 125 } else { 126 tmp.V6.bch_mode1 = 1; 127 tmp.V6.bch_mode = 1; 128 if (bits == 40) 129 tmp.V6.bch_mode = 0; 130 } 131 tmp.V6.rst = 1; 132 nandc_writel(tmp.d32, NANDC_BCHCTL); 133 } 134 135 static void nandc_xfer_start(u8 chip_sel, 136 u8 dir, 137 u8 sector_count, 138 u8 st_buf, 139 u32 *p_data, 140 u32 *p_spare) 141 { 142 union BCH_CTL_T bch_reg; 143 union FL_CTL_T fl_reg; 144 u8 bus_mode = (p_spare || p_data); 145 u32 i; 146 union MTRANS_CFG_T master_reg; 147 u16 *p_spare_tmp = (u16 *)p_spare; 148 u64 vir_addr; 149 150 fl_reg.d32 = 0; 151 bch_reg.d32 = nandc_readl(NANDC_BCHCTL); 152 bch_reg.V6.addr = 0x10; 153 bch_reg.V6.power_down = 0; 154 bch_reg.V6.region = chip_sel; 155 156 fl_reg.V6.rdn = dir; 157 fl_reg.V6.dma = 1; 158 fl_reg.V6.tr_count = 1; 159 fl_reg.V6.async_tog_mix = 1; 160 fl_reg.V6.cor_en = 1; 161 fl_reg.V6.st_addr = st_buf / 2; 162 163 master_reg.d32 = nandc_readl(NANDC_MTRANS_CFG); 164 master_reg.V6.bus_mode = 0; 165 #ifdef NANDC_MASTER_EN 166 if (bus_mode != 0 && dir != 0) { 167 u32 spare_sz = 64; 168 169 for (i = 0; i < sector_count / 2; i++) { 170 if (p_spare) { 171 master.spare_buf[i * spare_sz / 4] = 172 (p_spare_tmp[0]) | ((u32)p_spare_tmp[1] << 16); 173 p_spare_tmp += 2; 174 } else{ 175 master.spare_buf[i * spare_sz / 4] = 176 0xffffffff; 177 } 178 } 179 } 180 fl_reg.V6.page_num = (sector_count + 1) / 2; 181 master.page_vir = (u32 *)((p_data == (u32 *)NULL) ? 182 master.page_buf : 183 (u32 *)p_data); 184 master.spare_vir = (u32 *)master.spare_buf; 185 186 master.page_phy = (u32)((unsigned long)master.page_vir); 187 master.spare_phy = (u32)((unsigned long)master.spare_vir); 188 vir_addr = ((unsigned long)master.page_phy); 189 flush_dcache_range(vir_addr & (~0x3FuL), 190 ((vir_addr + 63) & (~0x3FuL)) + 191 fl_reg.V6.page_num * 1024); 192 vir_addr = ((unsigned long)master.spare_phy); 193 flush_dcache_range(vir_addr & (~0x3FuL), 194 ((vir_addr + 63) & (~0x3FuL)) + 195 fl_reg.V6.page_num * 128); 196 master.mapped = 1; 197 nandc_writel(master.page_phy, NANDC_MTRANS_SADDR0); 198 nandc_writel(master.spare_phy, NANDC_MTRANS_SADDR1); 199 master_reg.d32 = 0; 200 master_reg.V6.incr_num = 16; 201 master_reg.V6.burst = 7; 202 if ((((unsigned long)p_data) & 0x03) == 0) 203 master_reg.V6.hsize = 2; 204 master_reg.V6.bus_mode = 1; 205 master_reg.V6.ahb_wr = !dir; 206 master_reg.V6.ahb_wr_st = 1; 207 #endif 208 209 nandc_writel(master_reg.d32, NANDC_MTRANS_CFG); 210 nandc_writel(bch_reg.d32, NANDC_BCHCTL); 211 nandc_writel(fl_reg.d32, NANDC_FLCTL); 212 fl_reg.V6.start = 1; 213 nandc_writel(fl_reg.d32, NANDC_FLCTL); 214 } 215 216 static void nandc_xfer_comp(u8 chip_sel) 217 { 218 union FL_CTL_T fl_reg; 219 union MTRANS_CFG_T master_reg; 220 221 master_reg.d32 = nandc_readl(NANDC_MTRANS_CFG); 222 if (master_reg.V6.bus_mode != 0) { 223 union MTRANS_STAT_T stat_reg; 224 225 if (master_reg.V6.ahb_wr != 0) { 226 do { 227 fl_reg.d32 = nandc_readl(NANDC_FLCTL); 228 stat_reg.d32 = nandc_readl(NANDC_MTRANS_STAT); 229 } while (stat_reg.V6.mtrans_cnt < fl_reg.V6.page_num); 230 } else { 231 do { 232 fl_reg.d32 = nandc_readl(NANDC_FLCTL); 233 } while (fl_reg.V6.tr_rdy == 0); 234 } 235 } else { 236 do { 237 fl_reg.d32 = nandc_readl(NANDC_FLCTL); 238 } while ((fl_reg.V6.tr_rdy == 0)); 239 } 240 } 241 242 u32 nandc_xfer_data(u8 chip_sel, u8 dir, u8 sector_count, 243 u32 *p_data, u32 *p_spare) 244 { 245 u32 status = NAND_STS_OK; 246 u32 i; 247 u32 spare[16]; 248 union BCH_ST_T bch_st_reg; 249 250 if (dir == NANDC_WRITE && !p_spare) { 251 p_spare = (u32 *)spare; 252 memset(spare, 0xFF, sizeof(spare)); 253 } 254 nandc_xfer_start(chip_sel, dir, sector_count, 0, p_data, p_spare); 255 nandc_xfer_comp(chip_sel); 256 if (dir == NANDC_READ) { 257 if (p_spare) { 258 u32 spare_sz = 64; 259 u32 temp_data; 260 u8 *p_spare_temp = (u8 *)p_spare; 261 262 for (i = 0; i < sector_count / 2; i++) { 263 temp_data = master.spare_buf[i * spare_sz / 4]; 264 *p_spare_temp++ = (u8)temp_data; 265 *p_spare_temp++ = (u8)(temp_data >> 8); 266 *p_spare_temp++ = (u8)(temp_data >> 16); 267 *p_spare_temp++ = (u8)(temp_data >> 24); 268 } 269 } 270 for (i = 0; i < sector_count / 4 ; i++) { 271 bch_st_reg.d32 = nandc_readl(NANDC_BCHST(i)); 272 if (bch_st_reg.V6.fail0 || bch_st_reg.V6.fail1) { 273 status = NAND_STS_ECC_ERR; 274 } else { 275 u32 tmp = 0; 276 277 tmp = 278 max(bch_st_reg.V6.err_bits0 | 279 ((u32)bch_st_reg.V6.err_bits0_5 << 5), 280 bch_st_reg.V6.err_bits1 | 281 ((u32)bch_st_reg.V6.err_bits1_5 << 5)); 282 status = max(tmp, status); 283 } 284 } 285 } 286 nandc_writel(0, NANDC_MTRANS_CFG); 287 return status; 288 } 289 290 void nandc_clean_irq(void) 291 { 292 } 293