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/bug.h> 9 #include <linux/delay.h> 10 11 #include "flash_com.h" 12 #include "rkflash_debug.h" 13 #include "rk_sftl.h" 14 #include "sfc.h" 15 #include "sfc_nand.h" 16 17 static u32 sfc_nand_get_ecc_status0(void); 18 static u32 sfc_nand_get_ecc_status1(void); 19 static u32 sfc_nand_get_ecc_status2(void); 20 static u32 sfc_nand_get_ecc_status3(void); 21 static u32 sfc_nand_get_ecc_status4(void); 22 static u32 sfc_nand_get_ecc_status5(void); 23 static u32 sfc_nand_get_ecc_status6(void); 24 static u32 sfc_nand_get_ecc_status7(void); 25 static u32 sfc_nand_get_ecc_status8(void); 26 static u32 sfc_nand_get_ecc_status9(void); 27 static u32 sfc_nand_get_ecc_status10(void); 28 29 static struct nand_info spi_nand_tbl[] = { 30 /* TC58CVG0S0HxAIx */ 31 { 0x98, 0xC2, 0x00, 4, 0x40, 1, 1024, 0x00, 18, 0x8, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 32 /* TC58CVG1S0HxAIx */ 33 { 0x98, 0xCB, 0x00, 4, 0x40, 2, 1024, 0x00, 19, 0x8, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 34 /* TC58CVG2S0HRAIJ */ 35 { 0x98, 0xED, 0x00, 8, 0x40, 1, 2048, 0x0C, 20, 0x8, 0, { 0x04, 0x0C, 0x08, 0x10 }, &sfc_nand_get_ecc_status0 }, 36 /* TC58CVG1S3HRAIJ */ 37 { 0x98, 0xEB, 0x00, 4, 0x40, 1, 2048, 0x0C, 19, 0x8, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 38 /* TC58CVG0S3HRAIJ */ 39 { 0x98, 0xE2, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 40 41 /* MX35LF1GE4AB */ 42 { 0xC2, 0x12, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 43 /* MX35LF2GE4AB */ 44 { 0xC2, 0x22, 0x00, 4, 0x40, 2, 1024, 0x0C, 19, 0x4, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 45 /* MX35LF2GE4AD */ 46 { 0xC2, 0x26, 0x00, 4, 0x40, 1, 2048, 0x0C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 47 /* MX35LF4GE4AD */ 48 { 0xC2, 0x37, 0x00, 8, 0x40, 1, 2048, 0x0C, 20, 0x8, 1, { 0x04, 0x08, 0x14, 0x18 }, &sfc_nand_get_ecc_status0 }, 49 /* MX35UF1GE4AC */ 50 { 0xC2, 0x92, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 51 /* MX35UF2GE4AC */ 52 { 0xC2, 0xA2, 0x00, 4, 0x40, 1, 2048, 0x0C, 19, 0x4, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 53 /* MX35UF1GE4AD */ 54 { 0xC2, 0x96, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 55 /* MX35UF2GE4AD */ 56 { 0xC2, 0xA6, 0x00, 4, 0x40, 1, 2048, 0x0C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 57 /* MX35UF4GE4AD */ 58 { 0xC2, 0xB7, 0x00, 8, 0x40, 1, 2048, 0x0C, 20, 0x8, 1, { 0x04, 0x08, 0x14, 0x18 }, &sfc_nand_get_ecc_status0 }, 59 60 /* GD5F1GQ4UAYIG */ 61 { 0xC8, 0xF1, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 62 /* GD5F1GQ4RB9IGR */ 63 { 0xC8, 0xD1, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 }, 64 /* GD5F2GQ40BY2GR */ 65 { 0xC8, 0xD2, 0x00, 4, 0x40, 2, 1024, 0x0C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 }, 66 /* GD5F1GQ5UEYIG */ 67 { 0xC8, 0x51, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status2 }, 68 /* GD5F2GQ5UEYIG */ 69 { 0xC8, 0x52, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status2 }, 70 /* GD5F1GQ4R */ 71 { 0xC8, 0xC1, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 }, 72 /* GD5F4GQ6RExxG 1*4096 */ 73 { 0xC8, 0x45, 0x00, 4, 0x40, 2, 2048, 0x4C, 20, 0x4, 1, { 0x04, 0x08, 0x14, 0x18 }, &sfc_nand_get_ecc_status2 }, 74 /* GD5F4GQ6UExxG 1*4096 */ 75 { 0xC8, 0x55, 0x00, 4, 0x40, 2, 2048, 0x4C, 20, 0x4, 1, { 0x04, 0x08, 0x14, 0x18 }, &sfc_nand_get_ecc_status2 }, 76 /* GD5F1GQ4UExxH */ 77 { 0xC8, 0xD9, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 }, 78 /* GD5F1GQ5REYIG Add 3rd code to distingush with F50L2G41KA */ 79 { 0xC8, 0x41, 0xC8, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status2 }, 80 /* GD5F2GQ5REYIG */ 81 { 0xC8, 0x42, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status2 }, 82 /* GD5F2GM7RxG */ 83 { 0xC8, 0x82, 0x00, 4, 0x40, 1, 2048, 0x0C, 19, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 }, 84 /* GD5F2GM7UxG */ 85 { 0xC8, 0x92, 0x00, 4, 0x40, 1, 2048, 0x0C, 19, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 }, 86 /* GD5F1GM7UxG */ 87 { 0xC8, 0x91, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 }, 88 /* GD5F4GQ4UAYIG 1*4096 */ 89 { 0xC8, 0xF4, 0x00, 4, 0x40, 2, 2048, 0x0C, 20, 0x8, 1, { 0x04, 0x08, 0x14, 0x18 }, &sfc_nand_get_ecc_status0 }, 90 /* GD5F1GM7REYIGR */ 91 { 0xC8, 0x81, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 }, 92 /* GD5F4GM8UEYIGR */ 93 { 0xC8, 0x95, 0x00, 4, 0x40, 1, 4096, 0x4C, 20, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 }, 94 95 /* W25N01GV */ 96 { 0xEF, 0xAA, 0x21, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 0, { 0x04, 0x14, 0x24, 0xFF }, &sfc_nand_get_ecc_status1 }, 97 /* W25N02KVZEIR */ 98 { 0xEF, 0xAA, 0x22, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 0, { 0x04, 0x14, 0x24, 0xFF }, &sfc_nand_get_ecc_status0 }, 99 /* W25N04KVZEIR */ 100 { 0xEF, 0xAA, 0x23, 4, 0x40, 1, 4096, 0x4C, 20, 0x8, 0, { 0x04, 0x14, 0x24, 0x34 }, &sfc_nand_get_ecc_status0 }, 101 /* W25N01GW */ 102 { 0xEF, 0xBA, 0x21, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 0, { 0x04, 0x14, 0x24, 0xFF }, &sfc_nand_get_ecc_status1 }, 103 /* W25N02KW */ 104 { 0xEF, 0xBA, 0x22, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 0, { 0x04, 0x14, 0x24, 0xFF }, &sfc_nand_get_ecc_status0 }, 105 /* W25N512GVEIG */ 106 { 0xEF, 0xAA, 0x20, 4, 0x40, 1, 512, 0x4C, 17, 0x1, 0, { 0x04, 0x14, 0x24, 0xFF }, &sfc_nand_get_ecc_status1 }, 107 /* W25N01KV */ 108 { 0xEF, 0xAE, 0x21, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 0, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 109 /* W25N01JWZEIG */ 110 { 0xEF, 0xBC, 0x21, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 111 /* W25N01KWZPIG */ 112 { 0xEF, 0xBE, 0x21, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 113 114 /* HYF2GQ4UAACAE */ 115 { 0xC9, 0x52, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0xE, 1, { 0x04, 0x24, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 116 /* HYF1GQ4UDACAE */ 117 { 0xC9, 0x21, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 118 /* HYF1GQ4UPACAE */ 119 { 0xC9, 0xA1, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 120 /* HYF2GQ4UDACAE */ 121 { 0xC9, 0x22, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 122 /* HYF2GQ4UHCCAE */ 123 { 0xC9, 0x5A, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0xE, 1, { 0x04, 0x24, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 124 /* HYF4GQ4UAACBE */ 125 { 0xC9, 0xD4, 0x00, 8, 0x40, 1, 2048, 0x4C, 20, 0xE, 1, { 0x20, 0x40, 0x24, 0x44 }, &sfc_nand_get_ecc_status0 }, 126 /* HYF2GQ4IAACAE */ 127 { 0xC9, 0x82, 0x00, 4, 0x40, 1, 2048, 0x4C, 20, 0xE, 1, { 0x04, 0x24, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 128 /* HYF1GQ4IDACAE */ 129 { 0xC9, 0x81, 0x00, 4, 0x40, 1, 1024, 0x4C, 20, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 130 131 /* FS35ND01G-S1 */ 132 { 0xCD, 0xB1, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x10, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status5 }, 133 /* FS35ND02G-S2 */ 134 { 0xCD, 0xA2, 0x00, 4, 0x40, 1, 2048, 0x00, 19, 0x4, 0, { 0x10, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status5 }, 135 /* FS35ND01G-S1Y2 */ 136 { 0xCD, 0xEA, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 137 /* FS35ND02G-S3Y2 */ 138 { 0xCD, 0xEB, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 139 /* FS35ND04G-S2Y2 1*4096 */ 140 { 0xCD, 0xEC, 0x00, 4, 0x40, 2, 2048, 0x4C, 20, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 141 /* F35SQA001G */ 142 { 0xCD, 0x71, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 143 /* F35SQA002G */ 144 { 0xCD, 0x72, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 145 /* F35SQA512M */ 146 { 0xCD, 0x70, 0x00, 4, 0x40, 1, 512, 0x4C, 17, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 147 /* F35UQA512M */ 148 { 0xCD, 0x60, 0x00, 4, 0x40, 1, 512, 0x4C, 17, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 149 /* F35UQA002G-WWT */ 150 { 0xCD, 0x62, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 151 /* F35SQB004G-WWT */ 152 { 0xCD, 0x61, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 153 /* F35SQB004G */ 154 { 0xCD, 0x53, 0x00, 8, 0x40, 1, 2048, 0x0C, 20, 0x8, 1, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status10 }, 155 /* F35SQB002G */ 156 { 0xCD, 0x52, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status10 }, 157 158 /* DS35Q1GA-IB */ 159 { 0xE5, 0x71, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 160 /* DS35Q2GA-IB */ 161 { 0xE5, 0x72, 0x00, 4, 0x40, 2, 1024, 0x0C, 19, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 162 /* DS35M1GA-1B */ 163 { 0xE5, 0x21, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 164 /* DS35M2GA-IB */ 165 { 0xE5, 0x22, 0x00, 4, 0x40, 2, 1024, 0x0C, 19, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 166 /* DS35Q1GB-IB */ 167 { 0xE5, 0xF1, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 168 /* DS35Q2GB-IB */ 169 { 0xE5, 0xF2, 0x00, 4, 0x40, 2, 1024, 0x0C, 19, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 170 /* DS35Q4GM */ 171 { 0xE5, 0xF4, 0x00, 4, 0x40, 2, 2048, 0x0C, 20, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 172 /* DS35M1GB-IB */ 173 { 0xE5, 0xA1, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 174 /* DS35Q12B-IB */ 175 { 0xE5, 0xF5, 0x00, 4, 0x40, 1, 512, 0x0C, 17, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 176 /* DS35M12B-IB */ 177 { 0xE5, 0xA5, 0x00, 4, 0x40, 1, 512, 0x0C, 17, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 178 /* DS35Q1GD-IB */ 179 { 0xE5, 0x51, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 180 /* DS35M4GB-IB */ 181 { 0xE5, 0x64, 0x00, 4, 0x40, 1, 4096, 0x4C, 20, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 182 /* DS35Q4GB-IB */ 183 { 0xE5, 0xB4, 0x00, 4, 0x40, 1, 4096, 0x4C, 20, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 184 /* DS35M12C-IB */ 185 { 0xE5, 0x25, 0x00, 4, 0x40, 1, 512, 0x4C, 17, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 186 /* DS35Q12C-IB */ 187 { 0xE5, 0x75, 0x00, 4, 0x40, 1, 512, 0x4C, 17, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 188 /* DS35Q2GBS */ 189 { 0xE5, 0xB2, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 190 191 /* EM73C044VCC-H */ 192 { 0xD5, 0x22, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 193 /* EM73D044VCE-H */ 194 { 0xD5, 0x20, 0x00, 4, 0x40, 1, 2048, 0x0C, 19, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 195 /* EM73E044SNA-G */ 196 { 0xD5, 0x03, 0x00, 8, 0x40, 1, 2048, 0x4C, 20, 0x8, 1, { 0x04, 0x28, 0x08, 0x2C }, &sfc_nand_get_ecc_status0 }, 197 /* EM73C044VCF-H */ 198 { 0xD5, 0x25, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 199 200 /* XT26G02A */ 201 { 0x0B, 0xE2, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status4 }, 202 /* XT26G01A */ 203 { 0x0B, 0xE1, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status4 }, 204 /* XT26G04A */ 205 { 0x0B, 0xE3, 0x00, 4, 0x80, 1, 2048, 0x4C, 20, 0x8, 1, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status4 }, 206 /* XT26G01B */ 207 { 0x0B, 0xF1, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status4 }, 208 /* XT26G02B */ 209 { 0x0B, 0xF2, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x4, 1, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status5 }, 210 /* XT26G01C */ 211 { 0x0B, 0x11, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status7 }, 212 /* XT26G02C */ 213 { 0x0B, 0x12, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status7 }, 214 /* XT26G04C */ 215 { 0x0B, 0x13, 0x00, 8, 0x40, 1, 2048, 0x4C, 20, 0x8, 1, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status7 }, 216 /* XT26G11C */ 217 { 0x0B, 0x15, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 218 /* XT26Q02DWSIGA */ 219 { 0x0B, 0x52, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 220 /* XT26Q01DWSIGA */ 221 { 0x0B, 0x51, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 222 /* XT26Q04DWSIGA */ 223 { 0x0B, 0x53, 0x00, 8, 0x40, 1, 2048, 0x4C, 20, 0x8, 1, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status0 }, 224 /* XT26G01DWSIGA */ 225 { 0x0B, 0x31, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 226 /* XT26G02DWSIGA */ 227 { 0x0B, 0x32, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 228 /* XT26G04DWSIGA */ 229 { 0x0B, 0x33, 0x00, 8, 0x40, 1, 2048, 0x4C, 20, 0x8, 1, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status0 }, 230 /* XT26Q04DWSIGT-B */ 231 { 0x0B, 0x53, 0x00, 8, 0x40, 1, 2048, 0x4C, 20, 0x14, 1, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status0 }, 232 /* XT26Q01DWSIGA */ 233 { 0x0B, 0x51, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 234 235 /* MT29F2G01ABA, XT26G02E, F50L2G41XA */ 236 { 0x2C, 0x24, 0x00, 4, 0x40, 2, 1024, 0x4C, 19, 0x8, 0, { 0x20, 0x24, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 237 /* MT29F1G01ABA, F50L1G41XA */ 238 { 0x2C, 0x14, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 0, { 0x20, 0x24, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 239 240 /* FM25S01 */ 241 { 0xA1, 0xA1, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 0, { 0x00, 0x04, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 242 /* FM25S01A */ 243 { 0xA1, 0xE4, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 244 /* FM25S02A */ 245 { 0xA1, 0xE5, 0x00, 4, 0x40, 2, 1024, 0x4C, 19, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 246 /* FM25LS01 */ 247 { 0xA1, 0xA5, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 248 /* FM25S01BI3 */ 249 { 0xA1, 0xD4, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 250 /* FM25G02BI3 */ 251 { 0xA1, 0xD2, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 252 /* FM25S02BI3-DND-A-G3 */ 253 { 0xA1, 0xD6, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 254 /* FM25G02D */ 255 { 0xA1, 0xF2, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status5 }, 256 257 /* IS37SML01G1 */ 258 { 0xC8, 0x21, 0x00, 4, 0x40, 1, 1024, 0x00, 18, 0x1, 0, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 259 /* F50L1G41LB */ 260 { 0xC8, 0x01, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 0, { 0x14, 0x24, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 261 /* F50L2G41KA */ 262 { 0xC8, 0x41, 0x7F, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 263 264 /* UM19A1HISW */ 265 { 0xB0, 0x24, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 266 /* UM19A0HCSW */ 267 { 0xB0, 0x14, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 268 /* UM19A0LCSW */ 269 { 0xB0, 0x15, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 270 /* UM19A1LISW */ 271 { 0xB0, 0x25, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, 272 /* UM19A9LISW */ 273 { 0xB0, 0x0D, 0x00, 4, 0x40, 1, 512, 0x4C, 17, 0x4, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 274 /* UM19A9HISW */ 275 { 0xB0, 0x0C, 0x00, 4, 0x40, 1, 512, 0x4C, 17, 0x4, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 276 277 /* ATO25D1GA */ 278 { 0x9B, 0x12, 0x00, 4, 0x40, 1, 1024, 0x40, 18, 0x1, 1, { 0x14, 0x24, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 279 /* BWJX08K-2Gb */ 280 { 0xBC, 0xB3, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x10, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 281 /* JS28U1GQSCAHG-83 */ 282 { 0xBF, 0x21, 0x00, 4, 0x40, 1, 1024, 0x40, 18, 0x4, 1, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status8 }, 283 /* SGM7000I-S24W1GH */ 284 { 0xEA, 0xC1, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 285 /* TX25G01 */ 286 { 0xA1, 0xF1, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status8 }, 287 288 /* S35ML01G3, ANV1GCP0CLG, HYF1GQ4UTXCAE, YX25G1E, GSS01GSAM0 */ 289 { 0x01, 0x15, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status9 }, 290 /* S35ML02G3, ANV2GCP0CLG, HYF2GQ4UTXCAE, YX25G2E */ 291 { 0x01, 0x25, 0x00, 4, 0x40, 2, 1024, 0x4C, 19, 0x4, 0, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status9 }, 292 /* S35ML04G3 */ 293 { 0x01, 0x35, 0x00, 4, 0x40, 2, 2048, 0x4C, 20, 0x4, 0, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status9 }, 294 295 /* GSS01GSAK1 */ 296 { 0x52, 0xBA, 0x13, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 297 /* GSS02GSAK1 */ 298 { 0x52, 0xBA, 0x23, 4, 0x40, 1, 2048, 0x4C, 19, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 299 /* GSS02GSAX1 */ 300 { 0x52, 0xCA, 0x23, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 301 /* GSS01GSAX1 */ 302 { 0x52, 0xCA, 0x13, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 303 304 /* XCSP2AAPK */ 305 { 0x8C, 0xA1, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 306 /* XCSP1AAPK */ 307 { 0x8C, 0x01, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, 308 /* F50L1G41LC */ 309 { 0x8C, 0x2C, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x1, 0, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 310 311 /* ZB35Q01BYIG */ 312 { 0x5E, 0xA1, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 313 /* ZB35Q04BYIG */ 314 { 0x5E, 0xA3, 0x00, 4, 0x80, 1, 2048, 0x4C, 20, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 315 316 /* HSESYHDSW2G */ 317 { 0x3C, 0xD2, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, 318 }; 319 320 static struct nand_info *p_nand_info; 321 static u32 gp_page_buf[SFC_NAND_PAGE_MAX_SIZE / 4]; 322 static struct SFNAND_DEV sfc_nand_dev; 323 324 static struct nand_info *sfc_nand_get_info(u8 *nand_id) 325 { 326 u32 i; 327 328 for (i = 0; i < ARRAY_SIZE(spi_nand_tbl); i++) { 329 if (spi_nand_tbl[i].id0 == nand_id[0] && 330 spi_nand_tbl[i].id1 == nand_id[1]) { 331 if (spi_nand_tbl[i].id2 && 332 spi_nand_tbl[i].id2 != nand_id[2]) 333 continue; 334 335 return &spi_nand_tbl[i]; 336 } 337 } 338 339 return NULL; 340 } 341 342 static int sfc_nand_write_en(void) 343 { 344 int ret; 345 struct rk_sfc_op op; 346 347 op.sfcmd.d32 = 0; 348 op.sfcmd.b.cmd = CMD_WRITE_EN; 349 350 op.sfctrl.d32 = 0; 351 352 ret = sfc_request(&op, 0, NULL, 0); 353 return ret; 354 } 355 356 static int sfc_nand_rw_preset(void) 357 { 358 int ret; 359 struct rk_sfc_op op; 360 361 op.sfcmd.d32 = 0; 362 op.sfcmd.b.cmd = 0xff; 363 op.sfcmd.b.cs = 2; 364 365 op.sfctrl.d32 = 0; 366 op.sfctrl.b.datalines = 2; 367 op.sfctrl.b.cmdlines = 2; 368 op.sfctrl.b.addrlines = 2; 369 370 ret = sfc_request(&op, 0, NULL, 0); 371 return ret; 372 } 373 374 static int sfc_nand_read_feature(u8 addr, u8 *data) 375 { 376 int ret; 377 struct rk_sfc_op op; 378 379 op.sfcmd.d32 = 0; 380 op.sfcmd.b.cmd = 0x0F; 381 op.sfcmd.b.addrbits = SFC_ADDR_XBITS; 382 383 op.sfctrl.d32 = 0; 384 op.sfctrl.b.addrbits = 8; 385 386 *data = 0; 387 388 ret = sfc_request(&op, addr, data, 1); 389 390 if (ret != SFC_OK) 391 return ret; 392 393 return SFC_OK; 394 } 395 396 static int sfc_nand_write_feature(u32 addr, u8 status) 397 { 398 int ret; 399 struct rk_sfc_op op; 400 401 sfc_nand_write_en(); 402 403 op.sfcmd.d32 = 0; 404 op.sfcmd.b.cmd = 0x1F; 405 op.sfcmd.b.addrbits = SFC_ADDR_XBITS; 406 op.sfcmd.b.rw = SFC_WRITE; 407 408 op.sfctrl.d32 = 0; 409 op.sfctrl.b.addrbits = 8; 410 411 ret = sfc_request(&op, addr, &status, 1); 412 413 if (ret != SFC_OK) 414 return ret; 415 416 return ret; 417 } 418 419 static int sfc_nand_wait_busy(u8 *data, int timeout) 420 { 421 int ret; 422 int i; 423 u8 status; 424 425 *data = 0; 426 427 for (i = 0; i < timeout; i++) { 428 ret = sfc_nand_read_feature(0xC0, &status); 429 430 if (ret != SFC_OK) 431 return ret; 432 433 *data = status; 434 435 if (!(status & (1 << 0))) 436 return SFC_OK; 437 438 sfc_delay(1); 439 } 440 441 return SFC_NAND_WAIT_TIME_OUT; 442 } 443 444 /* 445 * ecc default: 446 * ecc bits: 0xC0[4,5] 447 * 0b00, No bit errors were detected 448 * 0b01, Bit errors were detected and corrected. 449 * 0b10, Multiple bit errors were detected and not corrected. 450 * 0b11, Bits errors were detected and corrected, bit error count 451 * reach the bit flip detection threshold 452 */ 453 static u32 sfc_nand_get_ecc_status0(void) 454 { 455 u32 ret; 456 u32 i; 457 u8 ecc; 458 u8 status; 459 u32 timeout = 1000 * 1000; 460 461 for (i = 0; i < timeout; i++) { 462 ret = sfc_nand_read_feature(0xC0, &status); 463 464 if (ret != SFC_OK) 465 return SFC_NAND_ECC_ERROR; 466 467 if (!(status & (1 << 0))) 468 break; 469 470 sfc_delay(1); 471 } 472 473 ecc = (status >> 4) & 0x03; 474 475 if (ecc <= 1) 476 ret = SFC_NAND_ECC_OK; 477 else if (ecc == 2) 478 ret = (u32)SFC_NAND_ECC_ERROR; 479 else 480 ret = SFC_NAND_ECC_REFRESH; 481 482 return ret; 483 } 484 485 /* 486 * ecc spectial type1: 487 * ecc bits: 0xC0[4,5] 488 * 0b00, No bit errors were detected; 489 * 0b01, Bits errors were detected and corrected, bit error count 490 * may reach the bit flip detection threshold; 491 * 0b10, Multiple bit errors were detected and not corrected; 492 * 0b11, Reserved. 493 */ 494 static u32 sfc_nand_get_ecc_status1(void) 495 { 496 u32 ret; 497 u32 i; 498 u8 ecc; 499 u8 status; 500 u32 timeout = 1000 * 1000; 501 502 for (i = 0; i < timeout; i++) { 503 ret = sfc_nand_read_feature(0xC0, &status); 504 505 if (ret != SFC_OK) 506 return SFC_NAND_ECC_ERROR; 507 508 if (!(status & (1 << 0))) 509 break; 510 511 sfc_delay(1); 512 } 513 514 ecc = (status >> 4) & 0x03; 515 516 if (ecc == 0) 517 ret = SFC_NAND_ECC_OK; 518 else if (ecc == 1) 519 ret = SFC_NAND_ECC_REFRESH; 520 else 521 ret = (u32)SFC_NAND_ECC_ERROR; 522 523 return ret; 524 } 525 526 /* 527 * ecc spectial type2: 528 * ecc bits: 0xC0[4,5] 0xF0[4,5] 529 * [0b0000, 0b0011], No bit errors were detected; 530 * [0b0100, 0b0111], Bit errors were detected and corrected. Not 531 * reach Flipping Bits; 532 * [0b1000, 0b1011], Multiple bit errors were detected and 533 * not corrected. 534 * [0b1100, 0b1111], reserved. 535 */ 536 static u32 sfc_nand_get_ecc_status2(void) 537 { 538 u32 ret; 539 u32 i; 540 u8 ecc; 541 u8 status, status1; 542 u32 timeout = 1000 * 1000; 543 544 for (i = 0; i < timeout; i++) { 545 ret = sfc_nand_read_feature(0xC0, &status); 546 547 if (ret != SFC_OK) 548 return SFC_NAND_ECC_ERROR; 549 550 ret = sfc_nand_read_feature(0xF0, &status1); 551 552 if (ret != SFC_OK) 553 return SFC_NAND_ECC_ERROR; 554 555 if (!(status & (1 << 0))) 556 break; 557 558 sfc_delay(1); 559 } 560 561 ecc = (status >> 4) & 0x03; 562 ecc = (ecc << 2) | ((status1 >> 4) & 0x03); 563 564 if (ecc < 7) 565 ret = SFC_NAND_ECC_OK; 566 else if (ecc == 7) 567 ret = SFC_NAND_ECC_REFRESH; 568 else 569 ret = (u32)SFC_NAND_ECC_ERROR; 570 571 return ret; 572 } 573 574 /* 575 * ecc spectial type3: 576 * ecc bits: 0xC0[4,5] 0xF0[4,5] 577 * [0b0000, 0b0011], No bit errors were detected; 578 * [0b0100, 0b0111], Bit errors were detected and corrected. Not 579 * reach Flipping Bits; 580 * [0b1000, 0b1011], Multiple bit errors were detected and 581 * not corrected. 582 * [0b1100, 0b1111], Bit error count equals the bit flip 583 * detectio nthreshold 584 */ 585 static u32 sfc_nand_get_ecc_status3(void) 586 { 587 u32 ret; 588 u32 i; 589 u8 ecc; 590 u8 status, status1; 591 u32 timeout = 1000 * 1000; 592 593 for (i = 0; i < timeout; i++) { 594 ret = sfc_nand_read_feature(0xC0, &status); 595 596 if (ret != SFC_OK) 597 return SFC_NAND_ECC_ERROR; 598 599 ret = sfc_nand_read_feature(0xF0, &status1); 600 601 if (ret != SFC_OK) 602 return SFC_NAND_ECC_ERROR; 603 604 if (!(status & (1 << 0))) 605 break; 606 607 sfc_delay(1); 608 } 609 610 ecc = (status >> 4) & 0x03; 611 ecc = (ecc << 2) | ((status1 >> 4) & 0x03); 612 613 if (ecc < 7) 614 ret = SFC_NAND_ECC_OK; 615 else if (ecc == 7 || ecc >= 12) 616 ret = SFC_NAND_ECC_REFRESH; 617 else 618 ret = (u32)SFC_NAND_ECC_ERROR; 619 620 return ret; 621 } 622 623 /* 624 * ecc spectial type4: 625 * ecc bits: 0xC0[2,5] 626 * [0b0000], No bit errors were detected; 627 * [0b0001, 0b0111], Bit errors were detected and corrected. Not 628 * reach Flipping Bits; 629 * [0b1000], Multiple bit errors were detected and 630 * not corrected. 631 * [0b1100], Bit error count equals the bit flip 632 * detection threshold 633 * else, reserved 634 */ 635 static u32 sfc_nand_get_ecc_status4(void) 636 { 637 u32 ret; 638 u32 i; 639 u8 ecc; 640 u8 status; 641 u32 timeout = 1000 * 1000; 642 643 for (i = 0; i < timeout; i++) { 644 ret = sfc_nand_read_feature(0xC0, &status); 645 646 if (ret != SFC_OK) 647 return SFC_NAND_ECC_ERROR; 648 649 if (!(status & (1 << 0))) 650 break; 651 652 sfc_delay(1); 653 } 654 655 ecc = (status >> 2) & 0x0f; 656 657 if (ecc < 7) 658 ret = SFC_NAND_ECC_OK; 659 else if (ecc == 7 || ecc == 12) 660 ret = SFC_NAND_ECC_REFRESH; 661 else 662 ret = (u32)SFC_NAND_ECC_ERROR; 663 664 return ret; 665 } 666 667 /* 668 * ecc spectial type5: 669 * ecc bits: 0xC0[4,6] 670 * [0b000], No bit errors were detected; 671 * [0b001, 0b011], Bit errors were detected and corrected. Not 672 * reach Flipping Bits; 673 * [0b100], Bit error count equals the bit flip 674 * detection threshold 675 * [0b101, 0b110], Reserved; 676 * [0b111], Multiple bit errors were detected and 677 * not corrected. 678 */ 679 static u32 sfc_nand_get_ecc_status5(void) 680 { 681 u32 ret; 682 u32 i; 683 u8 ecc; 684 u8 status; 685 u32 timeout = 1000 * 1000; 686 687 for (i = 0; i < timeout; i++) { 688 ret = sfc_nand_read_feature(0xC0, &status); 689 690 if (ret != SFC_OK) 691 return SFC_NAND_ECC_ERROR; 692 693 if (!(status & (1 << 0))) 694 break; 695 696 sfc_delay(1); 697 } 698 699 ecc = (status >> 4) & 0x07; 700 701 if (ecc < 4) 702 ret = SFC_NAND_ECC_OK; 703 else if (ecc == 4) 704 ret = SFC_NAND_ECC_REFRESH; 705 else 706 ret = (u32)SFC_NAND_ECC_ERROR; 707 708 return ret; 709 } 710 711 /* 712 * ecc spectial type6: 713 * ecc bits: 0xC0[4,6] 714 * [0b000], No bit errors were detected; 715 * [0b001], 1-3 Bit errors were detected and corrected. Not 716 * reach Flipping Bits; 717 * [0b010], Multiple bit errors were detected and 718 * not corrected. 719 * [0b011], 4-6 Bit errors were detected and corrected. Not 720 * reach Flipping Bits; 721 * [0b101], Bit error count equals the bit flip 722 * detectionthreshold 723 * others, Reserved. 724 */ 725 static u32 sfc_nand_get_ecc_status6(void) 726 { 727 u32 ret; 728 u32 i; 729 u8 ecc; 730 u8 status; 731 u32 timeout = 1000 * 1000; 732 733 for (i = 0; i < timeout; i++) { 734 ret = sfc_nand_read_feature(0xC0, &status); 735 736 if (ret != SFC_OK) 737 return SFC_NAND_ECC_ERROR; 738 739 if (!(status & (1 << 0))) 740 break; 741 742 sfc_delay(1); 743 } 744 745 ecc = (status >> 4) & 0x07; 746 747 if (ecc == 0 || ecc == 1 || ecc == 3) 748 ret = SFC_NAND_ECC_OK; 749 else if (ecc == 5) 750 ret = SFC_NAND_ECC_REFRESH; 751 else 752 ret = (u32)SFC_NAND_ECC_ERROR; 753 754 return ret; 755 } 756 757 /* 758 * ecc spectial type7: 759 * ecc bits: 0xC0[4,7] 760 * [0b0000], No bit errors were detected; 761 * [0b0001, 0b0111], 1-7 Bit errors were detected and corrected. Not 762 * reach Flipping Bits; 763 * [0b1000], 8 Bit errors were detected and corrected. Bit error count 764 * equals the bit flip detectionthreshold; 765 * [0b1111], Bit errors greater than ECC capability(8 bits) and not corrected; 766 * others, Reserved. 767 */ 768 static u32 sfc_nand_get_ecc_status7(void) 769 { 770 u32 ret; 771 u32 i; 772 u8 ecc; 773 u8 status; 774 u32 timeout = 1000 * 1000; 775 776 for (i = 0; i < timeout; i++) { 777 ret = sfc_nand_read_feature(0xC0, &status); 778 779 if (ret != SFC_OK) 780 return SFC_NAND_ECC_ERROR; 781 782 if (!(status & (1 << 0))) 783 break; 784 785 sfc_delay(1); 786 } 787 788 ecc = (status >> 4) & 0xf; 789 790 if (ecc < 7) 791 ret = SFC_NAND_ECC_OK; 792 else if (ecc == 7 || ecc == 8) 793 ret = SFC_NAND_ECC_REFRESH; 794 else 795 ret = (u32)SFC_NAND_ECC_ERROR; 796 797 return ret; 798 } 799 800 /* 801 * ecc spectial type8: 802 * ecc bits: 0xC0[4,6] 803 * [0b000], No bit errors were detected; 804 * [0b001, 0b011], 1~3 Bit errors were detected and corrected. Not 805 * reach Flipping Bits; 806 * [0b100], Bit error count equals the bit flip 807 * detection threshold 808 * others, Reserved. 809 */ 810 static u32 sfc_nand_get_ecc_status8(void) 811 { 812 u32 ret; 813 u32 i; 814 u8 ecc; 815 u8 status; 816 u32 timeout = 1000 * 1000; 817 818 for (i = 0; i < timeout; i++) { 819 ret = sfc_nand_read_feature(0xC0, &status); 820 821 if (ret != SFC_OK) 822 return SFC_NAND_ECC_ERROR; 823 824 if (!(status & (1 << 0))) 825 break; 826 827 sfc_delay(1); 828 } 829 830 ecc = (status >> 4) & 0x07; 831 832 if (ecc < 4) 833 ret = SFC_NAND_ECC_OK; 834 else if (ecc == 4) 835 ret = SFC_NAND_ECC_REFRESH; 836 else 837 ret = (u32)SFC_NAND_ECC_ERROR; 838 839 return ret; 840 } 841 842 /* 843 * ecc spectial type9: 844 * ecc bits: 0xC0[4,5] 845 * 0b00, No bit errors were detected 846 * 0b01, 1-2Bit errors were detected and corrected. 847 * 0b10, 3-4Bit errors were detected and corrected. 848 * 0b11, 11 can be used as uncorrectable 849 */ 850 static u32 sfc_nand_get_ecc_status9(void) 851 { 852 u32 ret; 853 u32 i; 854 u8 ecc; 855 u8 status; 856 u32 timeout = 1000 * 1000; 857 858 for (i = 0; i < timeout; i++) { 859 ret = sfc_nand_read_feature(0xC0, &status); 860 861 if (ret != SFC_OK) 862 return SFC_NAND_ECC_ERROR; 863 864 if (!(status & (1 << 0))) 865 break; 866 867 sfc_delay(1); 868 } 869 870 ecc = (status >> 4) & 0x03; 871 872 if (ecc <= 1) 873 ret = SFC_NAND_ECC_OK; 874 else if (ecc == 2) 875 ret = SFC_NAND_ECC_REFRESH; 876 else 877 ret = (u32)SFC_NAND_ECC_ERROR; 878 879 return ret; 880 } 881 882 /* 883 * ecc spectial type8: 884 * ecc bits: 0xC0[4,6] 885 * [0b000], No bit errors were detected; 886 * [0b001, 0b101], 3~7 Bit errors were detected and corrected. Not 887 * reach Flipping Bits; 888 * [0b110], Bit error count equals the bit flip detection threshold 889 * [0b111], Bit errors greater than ECC capability(8 bits) and not corrected; 890 */ 891 static u32 sfc_nand_get_ecc_status10(void) 892 { 893 u32 ret; 894 u32 i; 895 u8 ecc; 896 u8 status; 897 u32 timeout = 1000 * 1000; 898 899 for (i = 0; i < timeout; i++) { 900 ret = sfc_nand_read_feature(0xC0, &status); 901 902 if (ret != SFC_OK) 903 return SFC_NAND_ECC_ERROR; 904 905 if (!(status & (1 << 0))) 906 break; 907 908 sfc_delay(1); 909 } 910 911 ecc = (status >> 4) & 0x07; 912 913 if (ecc < 6) 914 ret = SFC_NAND_ECC_OK; 915 else if (ecc == 6) 916 ret = SFC_NAND_ECC_REFRESH; 917 else 918 ret = (u32)SFC_NAND_ECC_ERROR; 919 920 return ret; 921 } 922 923 u32 sfc_nand_erase_block(u8 cs, u32 addr) 924 { 925 int ret; 926 struct rk_sfc_op op; 927 u8 status; 928 929 rkflash_print_dio("%s %x\n", __func__, addr); 930 op.sfcmd.d32 = 0; 931 op.sfcmd.b.cmd = 0xd8; 932 op.sfcmd.b.addrbits = SFC_ADDR_24BITS; 933 op.sfcmd.b.rw = SFC_WRITE; 934 935 op.sfctrl.d32 = 0; 936 937 sfc_nand_write_en(); 938 ret = sfc_request(&op, addr, NULL, 0); 939 940 if (ret != SFC_OK) 941 return ret; 942 943 ret = sfc_nand_wait_busy(&status, 1000 * 1000); 944 945 if (status & (1 << 2)) 946 return SFC_NAND_PROG_ERASE_ERROR; 947 948 return ret; 949 } 950 951 static u32 sfc_nand_read_cache(u32 row, u32 *p_page_buf, u32 column, u32 len) 952 { 953 int ret; 954 u32 plane; 955 struct rk_sfc_op op; 956 957 op.sfcmd.d32 = 0; 958 op.sfcmd.b.cmd = sfc_nand_dev.page_read_cmd; 959 op.sfcmd.b.addrbits = SFC_ADDR_XBITS; 960 op.sfcmd.b.dummybits = 8; 961 962 op.sfctrl.d32 = 0; 963 op.sfctrl.b.datalines = sfc_nand_dev.read_lines; 964 op.sfctrl.b.addrbits = 16; 965 966 plane = p_nand_info->plane_per_die == 2 ? ((row >> 6) & 0x1) << 12 : 0; 967 968 ret = sfc_request(&op, plane | column, p_page_buf, len); 969 if (ret != SFC_OK) 970 return SFC_NAND_HW_ERROR; 971 972 return ret; 973 } 974 975 u32 sfc_nand_prog_page_raw(u8 cs, u32 addr, u32 *p_page_buf) 976 { 977 int ret; 978 u32 plane; 979 struct rk_sfc_op op; 980 u8 status; 981 u32 page_size = SFC_NAND_SECTOR_FULL_SIZE * p_nand_info->sec_per_page; 982 u32 data_area_size = SFC_NAND_SECTOR_SIZE * p_nand_info->sec_per_page; 983 984 rkflash_print_dio("%s %x %x\n", __func__, addr, p_page_buf[0]); 985 sfc_nand_write_en(); 986 987 if (sfc_nand_dev.prog_lines == DATA_LINES_X4 && 988 p_nand_info->feature & FEA_SOFT_QOP_BIT && 989 sfc_get_version() < SFC_VER_3) 990 sfc_nand_rw_preset(); 991 992 op.sfcmd.d32 = 0; 993 op.sfcmd.b.cmd = sfc_nand_dev.page_prog_cmd; 994 op.sfcmd.b.addrbits = SFC_ADDR_XBITS; 995 op.sfcmd.b.rw = SFC_WRITE; 996 997 op.sfctrl.d32 = 0; 998 op.sfctrl.b.datalines = sfc_nand_dev.prog_lines; 999 op.sfctrl.b.addrbits = 16; 1000 plane = p_nand_info->plane_per_die == 2 ? ((addr >> 6) & 0x1) << 12 : 0; 1001 sfc_request(&op, plane, p_page_buf, page_size); 1002 1003 /* 1004 * At the moment of power lost or dev running in harsh environment, flash 1005 * maybe work in a unkonw state and result in bit flip, when this situation 1006 * is detected by cache recheck, it's better to wait a second for a reliable 1007 * hardware environment to avoid abnormal data written to flash array. 1008 */ 1009 if (p_nand_info->id0 == MID_GIGADEV) { 1010 sfc_nand_read_cache(addr, (u32 *)sfc_nand_dev.recheck_buffer, 0, data_area_size); 1011 if (memcmp(sfc_nand_dev.recheck_buffer, p_page_buf, data_area_size)) { 1012 rkflash_print_error("%s %x cache bitflip\n", __func__, addr); 1013 mdelay(1000); 1014 sfc_request(&op, plane, p_page_buf, page_size); 1015 } 1016 } 1017 1018 op.sfcmd.d32 = 0; 1019 op.sfcmd.b.cmd = 0x10; 1020 op.sfcmd.b.addrbits = SFC_ADDR_24BITS; 1021 op.sfcmd.b.rw = SFC_WRITE; 1022 1023 op.sfctrl.d32 = 0; 1024 ret = sfc_request(&op, addr, p_page_buf, 0); 1025 1026 if (ret != SFC_OK) 1027 return ret; 1028 1029 ret = sfc_nand_wait_busy(&status, 1000 * 1000); 1030 if (status & (1 << 3)) 1031 return SFC_NAND_PROG_ERASE_ERROR; 1032 1033 return ret; 1034 } 1035 1036 u32 sfc_nand_prog_page(u8 cs, u32 addr, u32 *p_data, u32 *p_spare) 1037 { 1038 int ret; 1039 u32 sec_per_page = p_nand_info->sec_per_page; 1040 u32 data_size = sec_per_page * SFC_NAND_SECTOR_SIZE; 1041 struct nand_mega_area *meta = &p_nand_info->meta; 1042 1043 memcpy(gp_page_buf, p_data, data_size); 1044 memset(&gp_page_buf[data_size / 4], 0xff, sec_per_page * 16); 1045 gp_page_buf[(data_size + meta->off0) / 4] = p_spare[0]; 1046 gp_page_buf[(data_size + meta->off1) / 4] = p_spare[1]; 1047 1048 if (sec_per_page == 8) { 1049 gp_page_buf[(data_size + meta->off2) / 4] = p_spare[2]; 1050 gp_page_buf[(data_size + meta->off3) / 4] = p_spare[3]; 1051 } 1052 1053 ret = sfc_nand_prog_page_raw(cs, addr, gp_page_buf); 1054 1055 return ret; 1056 } 1057 1058 u32 sfc_nand_read(u32 row, u32 *p_page_buf, u32 column, u32 len) 1059 { 1060 int ret; 1061 u32 plane; 1062 struct rk_sfc_op op; 1063 u32 ecc_result; 1064 u8 status; 1065 1066 op.sfcmd.d32 = 0; 1067 op.sfcmd.b.cmd = 0x13; 1068 op.sfcmd.b.rw = SFC_WRITE; 1069 op.sfcmd.b.addrbits = SFC_ADDR_24BITS; 1070 1071 op.sfctrl.d32 = 0; 1072 1073 sfc_request(&op, row, p_page_buf, 0); 1074 1075 if (sfc_nand_dev.read_lines == DATA_LINES_X4 && 1076 p_nand_info->feature & FEA_SOFT_QOP_BIT && 1077 sfc_get_version() < SFC_VER_3) 1078 sfc_nand_rw_preset(); 1079 1080 sfc_nand_wait_busy(&status, 1000 * 1000); 1081 if (sfc_nand_dev.manufacturer == 0x01 && status) 1082 sfc_nand_wait_busy(&status, 1000 * 1000); 1083 1084 ecc_result = p_nand_info->ecc_status(); 1085 1086 op.sfcmd.d32 = 0; 1087 op.sfcmd.b.cmd = sfc_nand_dev.page_read_cmd; 1088 op.sfcmd.b.addrbits = SFC_ADDR_XBITS; 1089 op.sfcmd.b.dummybits = 8; 1090 1091 op.sfctrl.d32 = 0; 1092 op.sfctrl.b.datalines = sfc_nand_dev.read_lines; 1093 op.sfctrl.b.addrbits = 16; 1094 1095 plane = p_nand_info->plane_per_die == 2 ? ((row >> 6) & 0x1) << 12 : 0; 1096 ret = sfc_request(&op, plane | column, p_page_buf, len); 1097 rkflash_print_dio("%s %x %x\n", __func__, row, p_page_buf[0]); 1098 1099 if (ret != SFC_OK) 1100 return SFC_NAND_HW_ERROR; 1101 1102 return ecc_result; 1103 } 1104 1105 u32 sfc_nand_read_page_raw(u8 cs, u32 addr, u32 *p_page_buf) 1106 { 1107 u32 page_size = SFC_NAND_SECTOR_FULL_SIZE * p_nand_info->sec_per_page; 1108 1109 return sfc_nand_read(addr, p_page_buf, 0, page_size); 1110 } 1111 1112 u32 sfc_nand_read_page(u8 cs, u32 addr, u32 *p_data, u32 *p_spare) 1113 { 1114 u32 ret; 1115 u32 sec_per_page = p_nand_info->sec_per_page; 1116 u32 data_size = sec_per_page * SFC_NAND_SECTOR_SIZE; 1117 struct nand_mega_area *meta = &p_nand_info->meta; 1118 1119 ret = sfc_nand_read_page_raw(cs, addr, gp_page_buf); 1120 memcpy(p_data, gp_page_buf, data_size); 1121 p_spare[0] = gp_page_buf[(data_size + meta->off0) / 4]; 1122 p_spare[1] = gp_page_buf[(data_size + meta->off1) / 4]; 1123 1124 if (p_nand_info->sec_per_page == 8) { 1125 p_spare[2] = gp_page_buf[(data_size + meta->off2) / 4]; 1126 p_spare[3] = gp_page_buf[(data_size + meta->off3) / 4]; 1127 } 1128 1129 if (ret == SFC_NAND_HW_ERROR) 1130 ret = SFC_NAND_ECC_ERROR; 1131 1132 if (ret != SFC_NAND_ECC_OK) { 1133 rkflash_print_error("%s[0x%x], ret=0x%x\n", __func__, addr, ret); 1134 1135 if (p_data) 1136 rkflash_print_hex("data:", p_data, 4, 8); 1137 1138 if (p_spare) 1139 rkflash_print_hex("spare:", p_spare, 4, 2); 1140 } 1141 1142 return ret; 1143 } 1144 1145 u32 sfc_nand_check_bad_block(u8 cs, u32 addr) 1146 { 1147 u32 ret; 1148 u32 data_size = p_nand_info->sec_per_page * SFC_NAND_SECTOR_SIZE; 1149 u32 marker = 0; 1150 1151 ret = sfc_nand_read(addr, &marker, data_size, 2); 1152 1153 /* unify with mtd framework */ 1154 if (ret == SFC_NAND_ECC_ERROR || (u16)marker != 0xffff) 1155 rkflash_print_error("%s page= %x ret= %x spare= %x\n", 1156 __func__, addr, ret, marker); 1157 1158 /* Original bad block */ 1159 if ((u16)marker != 0xffff) 1160 return true; 1161 1162 return false; 1163 } 1164 1165 u32 sfc_nand_mark_bad_block(u8 cs, u32 addr) 1166 { 1167 u32 ret; 1168 u32 data_size = p_nand_info->sec_per_page * SFC_NAND_SECTOR_SIZE; 1169 1170 ret = sfc_nand_read_page_raw(cs, addr, gp_page_buf); 1171 1172 if (ret) 1173 return SFC_NAND_HW_ERROR; 1174 1175 gp_page_buf[data_size / 4] = 0x0; 1176 ret = sfc_nand_prog_page_raw(cs, addr, gp_page_buf); 1177 1178 if (ret) 1179 return SFC_NAND_HW_ERROR; 1180 1181 return ret; 1182 } 1183 1184 int sfc_nand_read_id(u8 *data) 1185 { 1186 int ret; 1187 struct rk_sfc_op op; 1188 1189 op.sfcmd.d32 = 0; 1190 op.sfcmd.b.cmd = CMD_READ_JEDECID; 1191 op.sfcmd.b.addrbits = SFC_ADDR_XBITS; 1192 1193 op.sfctrl.d32 = 0; 1194 op.sfctrl.b.addrbits = 8; 1195 1196 ret = sfc_request(&op, 0, data, 3); 1197 1198 return ret; 1199 } 1200 1201 /* 1202 * Read the 1st page's 1st byte of a phy_blk 1203 * If not FF, it's bad blk 1204 */ 1205 static int sfc_nand_get_bad_block_list(u16 *table, u32 die) 1206 { 1207 u32 bad_cnt, page; 1208 u32 blk_per_die; 1209 u16 blk; 1210 1211 rkflash_print_info("%s\n", __func__); 1212 1213 bad_cnt = 0; 1214 blk_per_die = p_nand_info->plane_per_die * 1215 p_nand_info->blk_per_plane; 1216 1217 for (blk = 0; blk < blk_per_die; blk++) { 1218 page = (blk + blk_per_die * die) * 1219 p_nand_info->page_per_blk; 1220 1221 if (sfc_nand_check_bad_block(die, page)) { 1222 table[bad_cnt++] = blk; 1223 rkflash_print_error("die[%d], bad_blk[%d]\n", die, blk); 1224 } 1225 } 1226 1227 return (int)bad_cnt; 1228 } 1229 1230 void sfc_nand_ftl_ops_init(void) 1231 { 1232 /* para init */ 1233 g_nand_phy_info.nand_type = 1; 1234 g_nand_phy_info.die_num = 1; 1235 g_nand_phy_info.plane_per_die = p_nand_info->plane_per_die; 1236 g_nand_phy_info.blk_per_plane = p_nand_info->blk_per_plane; 1237 g_nand_phy_info.page_per_blk = p_nand_info->page_per_blk; 1238 g_nand_phy_info.page_per_slc_blk = p_nand_info->page_per_blk; 1239 g_nand_phy_info.byte_per_sec = SFC_NAND_SECTOR_SIZE; 1240 g_nand_phy_info.sec_per_page = p_nand_info->sec_per_page; 1241 g_nand_phy_info.sec_per_blk = p_nand_info->sec_per_page * 1242 p_nand_info->page_per_blk; 1243 g_nand_phy_info.reserved_blk = 8; 1244 g_nand_phy_info.blk_per_die = p_nand_info->plane_per_die * 1245 p_nand_info->blk_per_plane; 1246 g_nand_phy_info.ecc_bits = p_nand_info->max_ecc_bits; 1247 1248 /* driver register */ 1249 g_nand_ops.get_bad_blk_list = sfc_nand_get_bad_block_list; 1250 g_nand_ops.erase_blk = sfc_nand_erase_block; 1251 g_nand_ops.prog_page = sfc_nand_prog_page; 1252 g_nand_ops.read_page = sfc_nand_read_page; 1253 g_nand_ops.bch_sel = NULL; 1254 } 1255 1256 static int sfc_nand_enable_QE(void) 1257 { 1258 int ret = SFC_OK; 1259 u8 status; 1260 1261 ret = sfc_nand_read_feature(0xB0, &status); 1262 1263 if (ret != SFC_OK) 1264 return ret; 1265 1266 if (status & 1) /* is QE bit set */ 1267 return SFC_OK; 1268 1269 status |= 1; 1270 1271 return sfc_nand_write_feature(0xB0, status); 1272 } 1273 1274 u32 sfc_nand_init(void) 1275 { 1276 u8 status, id_byte[8]; 1277 1278 sfc_nand_read_id(id_byte); 1279 rkflash_print_error("sfc_nand id: %x %x %x\n", 1280 id_byte[0], id_byte[1], id_byte[2]); 1281 1282 if (id_byte[0] == 0xFF || id_byte[0] == 0x00) 1283 return (u32)FTL_NO_FLASH; 1284 1285 p_nand_info = sfc_nand_get_info(id_byte); 1286 1287 if (!p_nand_info) { 1288 pr_err("The device not support yet!\n"); 1289 1290 return (u32)FTL_UNSUPPORTED_FLASH; 1291 } 1292 1293 sfc_nand_dev.manufacturer = id_byte[0]; 1294 sfc_nand_dev.mem_type = id_byte[1]; 1295 sfc_nand_dev.capacity = p_nand_info->density; 1296 sfc_nand_dev.block_size = p_nand_info->page_per_blk * p_nand_info->sec_per_page; 1297 sfc_nand_dev.page_size = p_nand_info->sec_per_page; 1298 1299 /* disable block lock */ 1300 sfc_nand_write_feature(0xA0, 0); 1301 sfc_nand_dev.read_lines = DATA_LINES_X1; 1302 sfc_nand_dev.prog_lines = DATA_LINES_X1; 1303 sfc_nand_dev.page_read_cmd = 0x03; 1304 sfc_nand_dev.page_prog_cmd = 0x02; 1305 sfc_nand_dev.recheck_buffer = ftl_malloc(SFC_NAND_PAGE_MAX_SIZE); 1306 if (!sfc_nand_dev.recheck_buffer) { 1307 rkflash_print_error("%s recheck_buffer alloc failed\n", __func__); 1308 return -1; 1309 } 1310 1311 if (p_nand_info->feature & FEA_4BIT_READ) { 1312 if ((p_nand_info->has_qe_bits && sfc_nand_enable_QE() == SFC_OK) || 1313 !p_nand_info->has_qe_bits) { 1314 sfc_nand_dev.read_lines = DATA_LINES_X4; 1315 sfc_nand_dev.page_read_cmd = 0x6b; 1316 } 1317 } 1318 1319 if (p_nand_info->feature & FEA_4BIT_PROG && 1320 sfc_nand_dev.read_lines == DATA_LINES_X4) { 1321 sfc_nand_dev.prog_lines = DATA_LINES_X4; 1322 sfc_nand_dev.page_prog_cmd = 0x32; 1323 } 1324 1325 sfc_nand_read_feature(0xA0, &status); 1326 rkflash_print_info("sfc_nand A0 = 0x%x\n", status); 1327 sfc_nand_read_feature(0xB0, &status); 1328 rkflash_print_info("sfc_nand B0 = 0x%x\n", status); 1329 rkflash_print_info("read_lines = %x\n", sfc_nand_dev.read_lines); 1330 rkflash_print_info("prog_lines = %x\n", sfc_nand_dev.prog_lines); 1331 rkflash_print_info("page_read_cmd = %x\n", sfc_nand_dev.page_read_cmd); 1332 rkflash_print_info("page_prog_cmd = %x\n", sfc_nand_dev.page_prog_cmd); 1333 1334 return SFC_OK; 1335 } 1336 1337 void sfc_nand_deinit(void) 1338 { 1339 /* to-do */ 1340 kfree(sfc_nand_dev.recheck_buffer); 1341 } 1342 1343 struct SFNAND_DEV *sfc_nand_get_private_dev(void) 1344 { 1345 return &sfc_nand_dev; 1346 } 1347 1348