diff options
author | Len Brown <len.brown@intel.com> | 2010-08-15 01:06:31 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2010-08-15 01:06:31 -0400 |
commit | 95ee46aa8698f2000647dfb362400fadbb5807cf (patch) | |
tree | e5a05c7297f997e191c73091934e42e3195c0e40 /drivers/mtd/nand/mxc_nand.c | |
parent | cfa806f059801dbe7e435745eb2e187c8bfe1e7f (diff) | |
parent | 92fa5bd9a946b6e7aab6764e7312e4e3d9bed295 (diff) |
Merge branch 'linus' into release
Conflicts:
drivers/acpi/debug.c
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/mtd/nand/mxc_nand.c')
-rw-r--r-- | drivers/mtd/nand/mxc_nand.c | 633 |
1 files changed, 432 insertions, 201 deletions
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 82e94389824e..fcf8ceb277d4 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
@@ -39,60 +39,96 @@ | |||
39 | 39 | ||
40 | #define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35()) | 40 | #define nfc_is_v21() (cpu_is_mx25() || cpu_is_mx35()) |
41 | #define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21()) | 41 | #define nfc_is_v1() (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21()) |
42 | #define nfc_is_v3_2() cpu_is_mx51() | ||
43 | #define nfc_is_v3() nfc_is_v3_2() | ||
42 | 44 | ||
43 | /* Addresses for NFC registers */ | 45 | /* Addresses for NFC registers */ |
44 | #define NFC_BUF_SIZE 0xE00 | 46 | #define NFC_V1_V2_BUF_SIZE (host->regs + 0x00) |
45 | #define NFC_BUF_ADDR 0xE04 | 47 | #define NFC_V1_V2_BUF_ADDR (host->regs + 0x04) |
46 | #define NFC_FLASH_ADDR 0xE06 | 48 | #define NFC_V1_V2_FLASH_ADDR (host->regs + 0x06) |
47 | #define NFC_FLASH_CMD 0xE08 | 49 | #define NFC_V1_V2_FLASH_CMD (host->regs + 0x08) |
48 | #define NFC_CONFIG 0xE0A | 50 | #define NFC_V1_V2_CONFIG (host->regs + 0x0a) |
49 | #define NFC_ECC_STATUS_RESULT 0xE0C | 51 | #define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c) |
50 | #define NFC_RSLTMAIN_AREA 0xE0E | 52 | #define NFC_V1_V2_RSLTMAIN_AREA (host->regs + 0x0e) |
51 | #define NFC_RSLTSPARE_AREA 0xE10 | 53 | #define NFC_V1_V2_RSLTSPARE_AREA (host->regs + 0x10) |
52 | #define NFC_WRPROT 0xE12 | 54 | #define NFC_V1_V2_WRPROT (host->regs + 0x12) |
53 | #define NFC_V1_UNLOCKSTART_BLKADDR 0xe14 | 55 | #define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14) |
54 | #define NFC_V1_UNLOCKEND_BLKADDR 0xe16 | 56 | #define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16) |
55 | #define NFC_V21_UNLOCKSTART_BLKADDR 0xe20 | 57 | #define NFC_V21_UNLOCKSTART_BLKADDR (host->regs + 0x20) |
56 | #define NFC_V21_UNLOCKEND_BLKADDR 0xe22 | 58 | #define NFC_V21_UNLOCKEND_BLKADDR (host->regs + 0x22) |
57 | #define NFC_NF_WRPRST 0xE18 | 59 | #define NFC_V1_V2_NF_WRPRST (host->regs + 0x18) |
58 | #define NFC_CONFIG1 0xE1A | 60 | #define NFC_V1_V2_CONFIG1 (host->regs + 0x1a) |
59 | #define NFC_CONFIG2 0xE1C | 61 | #define NFC_V1_V2_CONFIG2 (host->regs + 0x1c) |
60 | 62 | ||
61 | /* Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register | 63 | #define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0) |
62 | * for Command operation */ | 64 | #define NFC_V1_V2_CONFIG1_SP_EN (1 << 2) |
63 | #define NFC_CMD 0x1 | 65 | #define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3) |
64 | 66 | #define NFC_V1_V2_CONFIG1_INT_MSK (1 << 4) | |
65 | /* Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register | 67 | #define NFC_V1_V2_CONFIG1_BIG (1 << 5) |
66 | * for Address operation */ | 68 | #define NFC_V1_V2_CONFIG1_RST (1 << 6) |
67 | #define NFC_ADDR 0x2 | 69 | #define NFC_V1_V2_CONFIG1_CE (1 << 7) |
68 | 70 | #define NFC_V1_V2_CONFIG1_ONE_CYCLE (1 << 8) | |
69 | /* Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register | 71 | |
70 | * for Input operation */ | 72 | #define NFC_V1_V2_CONFIG2_INT (1 << 15) |
71 | #define NFC_INPUT 0x4 | 73 | |
72 | 74 | /* | |
73 | /* Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register | 75 | * Operation modes for the NFC. Valid for v1, v2 and v3 |
74 | * for Data Output operation */ | 76 | * type controllers. |
75 | #define NFC_OUTPUT 0x8 | 77 | */ |
76 | 78 | #define NFC_CMD (1 << 0) | |
77 | /* Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register | 79 | #define NFC_ADDR (1 << 1) |
78 | * for Read ID operation */ | 80 | #define NFC_INPUT (1 << 2) |
79 | #define NFC_ID 0x10 | 81 | #define NFC_OUTPUT (1 << 3) |
80 | 82 | #define NFC_ID (1 << 4) | |
81 | /* Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register | 83 | #define NFC_STATUS (1 << 5) |
82 | * for Read Status operation */ | 84 | |
83 | #define NFC_STATUS 0x20 | 85 | #define NFC_V3_FLASH_CMD (host->regs_axi + 0x00) |
84 | 86 | #define NFC_V3_FLASH_ADDR0 (host->regs_axi + 0x04) | |
85 | /* Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read | 87 | |
86 | * Status operation */ | 88 | #define NFC_V3_CONFIG1 (host->regs_axi + 0x34) |
87 | #define NFC_INT 0x8000 | 89 | #define NFC_V3_CONFIG1_SP_EN (1 << 0) |
88 | 90 | #define NFC_V3_CONFIG1_RBA(x) (((x) & 0x7 ) << 4) | |
89 | #define NFC_SP_EN (1 << 2) | 91 | |
90 | #define NFC_ECC_EN (1 << 3) | 92 | #define NFC_V3_ECC_STATUS_RESULT (host->regs_axi + 0x38) |
91 | #define NFC_INT_MSK (1 << 4) | 93 | |
92 | #define NFC_BIG (1 << 5) | 94 | #define NFC_V3_LAUNCH (host->regs_axi + 0x40) |
93 | #define NFC_RST (1 << 6) | 95 | |
94 | #define NFC_CE (1 << 7) | 96 | #define NFC_V3_WRPROT (host->regs_ip + 0x0) |
95 | #define NFC_ONE_CYCLE (1 << 8) | 97 | #define NFC_V3_WRPROT_LOCK_TIGHT (1 << 0) |
98 | #define NFC_V3_WRPROT_LOCK (1 << 1) | ||
99 | #define NFC_V3_WRPROT_UNLOCK (1 << 2) | ||
100 | #define NFC_V3_WRPROT_BLS_UNLOCK (2 << 6) | ||
101 | |||
102 | #define NFC_V3_WRPROT_UNLOCK_BLK_ADD0 (host->regs_ip + 0x04) | ||
103 | |||
104 | #define NFC_V3_CONFIG2 (host->regs_ip + 0x24) | ||
105 | #define NFC_V3_CONFIG2_PS_512 (0 << 0) | ||
106 | #define NFC_V3_CONFIG2_PS_2048 (1 << 0) | ||
107 | #define NFC_V3_CONFIG2_PS_4096 (2 << 0) | ||
108 | #define NFC_V3_CONFIG2_ONE_CYCLE (1 << 2) | ||
109 | #define NFC_V3_CONFIG2_ECC_EN (1 << 3) | ||
110 | #define NFC_V3_CONFIG2_2CMD_PHASES (1 << 4) | ||
111 | #define NFC_V3_CONFIG2_NUM_ADDR_PHASE0 (1 << 5) | ||
112 | #define NFC_V3_CONFIG2_ECC_MODE_8 (1 << 6) | ||
113 | #define NFC_V3_CONFIG2_PPB(x) (((x) & 0x3) << 7) | ||
114 | #define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x) (((x) & 0x3) << 12) | ||
115 | #define NFC_V3_CONFIG2_INT_MSK (1 << 15) | ||
116 | #define NFC_V3_CONFIG2_ST_CMD(x) (((x) & 0xff) << 24) | ||
117 | #define NFC_V3_CONFIG2_SPAS(x) (((x) & 0xff) << 16) | ||
118 | |||
119 | #define NFC_V3_CONFIG3 (host->regs_ip + 0x28) | ||
120 | #define NFC_V3_CONFIG3_ADD_OP(x) (((x) & 0x3) << 0) | ||
121 | #define NFC_V3_CONFIG3_FW8 (1 << 3) | ||
122 | #define NFC_V3_CONFIG3_SBB(x) (((x) & 0x7) << 8) | ||
123 | #define NFC_V3_CONFIG3_NUM_OF_DEVICES(x) (((x) & 0x7) << 12) | ||
124 | #define NFC_V3_CONFIG3_RBB_MODE (1 << 15) | ||
125 | #define NFC_V3_CONFIG3_NO_SDMA (1 << 20) | ||
126 | |||
127 | #define NFC_V3_IPC (host->regs_ip + 0x2C) | ||
128 | #define NFC_V3_IPC_CREQ (1 << 0) | ||
129 | #define NFC_V3_IPC_INT (1 << 31) | ||
130 | |||
131 | #define NFC_V3_DELAY_LINE (host->regs_ip + 0x34) | ||
96 | 132 | ||
97 | struct mxc_nand_host { | 133 | struct mxc_nand_host { |
98 | struct mtd_info mtd; | 134 | struct mtd_info mtd; |
@@ -102,20 +138,30 @@ struct mxc_nand_host { | |||
102 | 138 | ||
103 | void *spare0; | 139 | void *spare0; |
104 | void *main_area0; | 140 | void *main_area0; |
105 | void *main_area1; | ||
106 | 141 | ||
107 | void __iomem *base; | 142 | void __iomem *base; |
108 | void __iomem *regs; | 143 | void __iomem *regs; |
144 | void __iomem *regs_axi; | ||
145 | void __iomem *regs_ip; | ||
109 | int status_request; | 146 | int status_request; |
110 | struct clk *clk; | 147 | struct clk *clk; |
111 | int clk_act; | 148 | int clk_act; |
112 | int irq; | 149 | int irq; |
150 | int eccsize; | ||
113 | 151 | ||
114 | wait_queue_head_t irq_waitq; | 152 | wait_queue_head_t irq_waitq; |
115 | 153 | ||
116 | uint8_t *data_buf; | 154 | uint8_t *data_buf; |
117 | unsigned int buf_start; | 155 | unsigned int buf_start; |
118 | int spare_len; | 156 | int spare_len; |
157 | |||
158 | void (*preset)(struct mtd_info *); | ||
159 | void (*send_cmd)(struct mxc_nand_host *, uint16_t, int); | ||
160 | void (*send_addr)(struct mxc_nand_host *, uint16_t, int); | ||
161 | void (*send_page)(struct mtd_info *, unsigned int); | ||
162 | void (*send_read_id)(struct mxc_nand_host *); | ||
163 | uint16_t (*get_dev_status)(struct mxc_nand_host *); | ||
164 | int (*check_int)(struct mxc_nand_host *); | ||
119 | }; | 165 | }; |
120 | 166 | ||
121 | /* OOB placement block for use with hardware ecc generation */ | 167 | /* OOB placement block for use with hardware ecc generation */ |
@@ -175,34 +221,52 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) | |||
175 | return IRQ_HANDLED; | 221 | return IRQ_HANDLED; |
176 | } | 222 | } |
177 | 223 | ||
224 | static int check_int_v3(struct mxc_nand_host *host) | ||
225 | { | ||
226 | uint32_t tmp; | ||
227 | |||
228 | tmp = readl(NFC_V3_IPC); | ||
229 | if (!(tmp & NFC_V3_IPC_INT)) | ||
230 | return 0; | ||
231 | |||
232 | tmp &= ~NFC_V3_IPC_INT; | ||
233 | writel(tmp, NFC_V3_IPC); | ||
234 | |||
235 | return 1; | ||
236 | } | ||
237 | |||
238 | static int check_int_v1_v2(struct mxc_nand_host *host) | ||
239 | { | ||
240 | uint32_t tmp; | ||
241 | |||
242 | tmp = readw(NFC_V1_V2_CONFIG2); | ||
243 | if (!(tmp & NFC_V1_V2_CONFIG2_INT)) | ||
244 | return 0; | ||
245 | |||
246 | writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2); | ||
247 | |||
248 | return 1; | ||
249 | } | ||
250 | |||
178 | /* This function polls the NANDFC to wait for the basic operation to | 251 | /* This function polls the NANDFC to wait for the basic operation to |
179 | * complete by checking the INT bit of config2 register. | 252 | * complete by checking the INT bit of config2 register. |
180 | */ | 253 | */ |
181 | static void wait_op_done(struct mxc_nand_host *host, int useirq) | 254 | static void wait_op_done(struct mxc_nand_host *host, int useirq) |
182 | { | 255 | { |
183 | uint16_t tmp; | ||
184 | int max_retries = 8000; | 256 | int max_retries = 8000; |
185 | 257 | ||
186 | if (useirq) { | 258 | if (useirq) { |
187 | if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) { | 259 | if (!host->check_int(host)) { |
188 | 260 | ||
189 | enable_irq(host->irq); | 261 | enable_irq(host->irq); |
190 | 262 | ||
191 | wait_event(host->irq_waitq, | 263 | wait_event(host->irq_waitq, host->check_int(host)); |
192 | readw(host->regs + NFC_CONFIG2) & NFC_INT); | ||
193 | |||
194 | tmp = readw(host->regs + NFC_CONFIG2); | ||
195 | tmp &= ~NFC_INT; | ||
196 | writew(tmp, host->regs + NFC_CONFIG2); | ||
197 | } | 264 | } |
198 | } else { | 265 | } else { |
199 | while (max_retries-- > 0) { | 266 | while (max_retries-- > 0) { |
200 | if (readw(host->regs + NFC_CONFIG2) & NFC_INT) { | 267 | if (host->check_int(host)) |
201 | tmp = readw(host->regs + NFC_CONFIG2); | ||
202 | tmp &= ~NFC_INT; | ||
203 | writew(tmp, host->regs + NFC_CONFIG2); | ||
204 | break; | 268 | break; |
205 | } | 269 | |
206 | udelay(1); | 270 | udelay(1); |
207 | } | 271 | } |
208 | if (max_retries < 0) | 272 | if (max_retries < 0) |
@@ -211,21 +275,33 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq) | |||
211 | } | 275 | } |
212 | } | 276 | } |
213 | 277 | ||
278 | static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq) | ||
279 | { | ||
280 | /* fill command */ | ||
281 | writel(cmd, NFC_V3_FLASH_CMD); | ||
282 | |||
283 | /* send out command */ | ||
284 | writel(NFC_CMD, NFC_V3_LAUNCH); | ||
285 | |||
286 | /* Wait for operation to complete */ | ||
287 | wait_op_done(host, useirq); | ||
288 | } | ||
289 | |||
214 | /* This function issues the specified command to the NAND device and | 290 | /* This function issues the specified command to the NAND device and |
215 | * waits for completion. */ | 291 | * waits for completion. */ |
216 | static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq) | 292 | static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq) |
217 | { | 293 | { |
218 | DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq); | 294 | DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq); |
219 | 295 | ||
220 | writew(cmd, host->regs + NFC_FLASH_CMD); | 296 | writew(cmd, NFC_V1_V2_FLASH_CMD); |
221 | writew(NFC_CMD, host->regs + NFC_CONFIG2); | 297 | writew(NFC_CMD, NFC_V1_V2_CONFIG2); |
222 | 298 | ||
223 | if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) { | 299 | if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) { |
224 | int max_retries = 100; | 300 | int max_retries = 100; |
225 | /* Reset completion is indicated by NFC_CONFIG2 */ | 301 | /* Reset completion is indicated by NFC_CONFIG2 */ |
226 | /* being set to 0 */ | 302 | /* being set to 0 */ |
227 | while (max_retries-- > 0) { | 303 | while (max_retries-- > 0) { |
228 | if (readw(host->regs + NFC_CONFIG2) == 0) { | 304 | if (readw(NFC_V1_V2_CONFIG2) == 0) { |
229 | break; | 305 | break; |
230 | } | 306 | } |
231 | udelay(1); | 307 | udelay(1); |
@@ -239,21 +315,48 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq) | |||
239 | } | 315 | } |
240 | } | 316 | } |
241 | 317 | ||
318 | static void send_addr_v3(struct mxc_nand_host *host, uint16_t addr, int islast) | ||
319 | { | ||
320 | /* fill address */ | ||
321 | writel(addr, NFC_V3_FLASH_ADDR0); | ||
322 | |||
323 | /* send out address */ | ||
324 | writel(NFC_ADDR, NFC_V3_LAUNCH); | ||
325 | |||
326 | wait_op_done(host, 0); | ||
327 | } | ||
328 | |||
242 | /* This function sends an address (or partial address) to the | 329 | /* This function sends an address (or partial address) to the |
243 | * NAND device. The address is used to select the source/destination for | 330 | * NAND device. The address is used to select the source/destination for |
244 | * a NAND command. */ | 331 | * a NAND command. */ |
245 | static void send_addr(struct mxc_nand_host *host, uint16_t addr, int islast) | 332 | static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast) |
246 | { | 333 | { |
247 | DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast); | 334 | DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast); |
248 | 335 | ||
249 | writew(addr, host->regs + NFC_FLASH_ADDR); | 336 | writew(addr, NFC_V1_V2_FLASH_ADDR); |
250 | writew(NFC_ADDR, host->regs + NFC_CONFIG2); | 337 | writew(NFC_ADDR, NFC_V1_V2_CONFIG2); |
251 | 338 | ||
252 | /* Wait for operation to complete */ | 339 | /* Wait for operation to complete */ |
253 | wait_op_done(host, islast); | 340 | wait_op_done(host, islast); |
254 | } | 341 | } |
255 | 342 | ||
256 | static void send_page(struct mtd_info *mtd, unsigned int ops) | 343 | static void send_page_v3(struct mtd_info *mtd, unsigned int ops) |
344 | { | ||
345 | struct nand_chip *nand_chip = mtd->priv; | ||
346 | struct mxc_nand_host *host = nand_chip->priv; | ||
347 | uint32_t tmp; | ||
348 | |||
349 | tmp = readl(NFC_V3_CONFIG1); | ||
350 | tmp &= ~(7 << 4); | ||
351 | writel(tmp, NFC_V3_CONFIG1); | ||
352 | |||
353 | /* transfer data from NFC ram to nand */ | ||
354 | writel(ops, NFC_V3_LAUNCH); | ||
355 | |||
356 | wait_op_done(host, false); | ||
357 | } | ||
358 | |||
359 | static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops) | ||
257 | { | 360 | { |
258 | struct nand_chip *nand_chip = mtd->priv; | 361 | struct nand_chip *nand_chip = mtd->priv; |
259 | struct mxc_nand_host *host = nand_chip->priv; | 362 | struct mxc_nand_host *host = nand_chip->priv; |
@@ -267,24 +370,34 @@ static void send_page(struct mtd_info *mtd, unsigned int ops) | |||
267 | for (i = 0; i < bufs; i++) { | 370 | for (i = 0; i < bufs; i++) { |
268 | 371 | ||
269 | /* NANDFC buffer 0 is used for page read/write */ | 372 | /* NANDFC buffer 0 is used for page read/write */ |
270 | writew(i, host->regs + NFC_BUF_ADDR); | 373 | writew(i, NFC_V1_V2_BUF_ADDR); |
271 | 374 | ||
272 | writew(ops, host->regs + NFC_CONFIG2); | 375 | writew(ops, NFC_V1_V2_CONFIG2); |
273 | 376 | ||
274 | /* Wait for operation to complete */ | 377 | /* Wait for operation to complete */ |
275 | wait_op_done(host, true); | 378 | wait_op_done(host, true); |
276 | } | 379 | } |
277 | } | 380 | } |
278 | 381 | ||
382 | static void send_read_id_v3(struct mxc_nand_host *host) | ||
383 | { | ||
384 | /* Read ID into main buffer */ | ||
385 | writel(NFC_ID, NFC_V3_LAUNCH); | ||
386 | |||
387 | wait_op_done(host, true); | ||
388 | |||
389 | memcpy(host->data_buf, host->main_area0, 16); | ||
390 | } | ||
391 | |||
279 | /* Request the NANDFC to perform a read of the NAND device ID. */ | 392 | /* Request the NANDFC to perform a read of the NAND device ID. */ |
280 | static void send_read_id(struct mxc_nand_host *host) | 393 | static void send_read_id_v1_v2(struct mxc_nand_host *host) |
281 | { | 394 | { |
282 | struct nand_chip *this = &host->nand; | 395 | struct nand_chip *this = &host->nand; |
283 | 396 | ||
284 | /* NANDFC buffer 0 is used for device ID output */ | 397 | /* NANDFC buffer 0 is used for device ID output */ |
285 | writew(0x0, host->regs + NFC_BUF_ADDR); | 398 | writew(0x0, NFC_V1_V2_BUF_ADDR); |
286 | 399 | ||
287 | writew(NFC_ID, host->regs + NFC_CONFIG2); | 400 | writew(NFC_ID, NFC_V1_V2_CONFIG2); |
288 | 401 | ||
289 | /* Wait for operation to complete */ | 402 | /* Wait for operation to complete */ |
290 | wait_op_done(host, true); | 403 | wait_op_done(host, true); |
@@ -301,29 +414,36 @@ static void send_read_id(struct mxc_nand_host *host) | |||
301 | memcpy(host->data_buf, host->main_area0, 16); | 414 | memcpy(host->data_buf, host->main_area0, 16); |
302 | } | 415 | } |
303 | 416 | ||
417 | static uint16_t get_dev_status_v3(struct mxc_nand_host *host) | ||
418 | { | ||
419 | writew(NFC_STATUS, NFC_V3_LAUNCH); | ||
420 | wait_op_done(host, true); | ||
421 | |||
422 | return readl(NFC_V3_CONFIG1) >> 16; | ||
423 | } | ||
424 | |||
304 | /* This function requests the NANDFC to perform a read of the | 425 | /* This function requests the NANDFC to perform a read of the |
305 | * NAND device status and returns the current status. */ | 426 | * NAND device status and returns the current status. */ |
306 | static uint16_t get_dev_status(struct mxc_nand_host *host) | 427 | static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host) |
307 | { | 428 | { |
308 | void __iomem *main_buf = host->main_area1; | 429 | void __iomem *main_buf = host->main_area0; |
309 | uint32_t store; | 430 | uint32_t store; |
310 | uint16_t ret; | 431 | uint16_t ret; |
311 | /* Issue status request to NAND device */ | ||
312 | 432 | ||
313 | /* store the main area1 first word, later do recovery */ | 433 | writew(0x0, NFC_V1_V2_BUF_ADDR); |
314 | store = readl(main_buf); | ||
315 | /* NANDFC buffer 1 is used for device status to prevent | ||
316 | * corruption of read/write buffer on status requests. */ | ||
317 | writew(1, host->regs + NFC_BUF_ADDR); | ||
318 | 434 | ||
319 | writew(NFC_STATUS, host->regs + NFC_CONFIG2); | 435 | /* |
436 | * The device status is stored in main_area0. To | ||
437 | * prevent corruption of the buffer save the value | ||
438 | * and restore it afterwards. | ||
439 | */ | ||
440 | store = readl(main_buf); | ||
320 | 441 | ||
321 | /* Wait for operation to complete */ | 442 | writew(NFC_STATUS, NFC_V1_V2_CONFIG2); |
322 | wait_op_done(host, true); | 443 | wait_op_done(host, true); |
323 | 444 | ||
324 | /* Status is placed in first word of main buffer */ | ||
325 | /* get status, then recovery area 1 data */ | ||
326 | ret = readw(main_buf); | 445 | ret = readw(main_buf); |
446 | |||
327 | writel(store, main_buf); | 447 | writel(store, main_buf); |
328 | 448 | ||
329 | return ret; | 449 | return ret; |
@@ -347,7 +467,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode) | |||
347 | */ | 467 | */ |
348 | } | 468 | } |
349 | 469 | ||
350 | static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, | 470 | static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat, |
351 | u_char *read_ecc, u_char *calc_ecc) | 471 | u_char *read_ecc, u_char *calc_ecc) |
352 | { | 472 | { |
353 | struct nand_chip *nand_chip = mtd->priv; | 473 | struct nand_chip *nand_chip = mtd->priv; |
@@ -358,7 +478,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, | |||
358 | * additional correction. 2-Bit errors cannot be corrected by | 478 | * additional correction. 2-Bit errors cannot be corrected by |
359 | * HW ECC, so we need to return failure | 479 | * HW ECC, so we need to return failure |
360 | */ | 480 | */ |
361 | uint16_t ecc_status = readw(host->regs + NFC_ECC_STATUS_RESULT); | 481 | uint16_t ecc_status = readw(NFC_V1_V2_ECC_STATUS_RESULT); |
362 | 482 | ||
363 | if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { | 483 | if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) { |
364 | DEBUG(MTD_DEBUG_LEVEL0, | 484 | DEBUG(MTD_DEBUG_LEVEL0, |
@@ -369,6 +489,43 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, | |||
369 | return 0; | 489 | return 0; |
370 | } | 490 | } |
371 | 491 | ||
492 | static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat, | ||
493 | u_char *read_ecc, u_char *calc_ecc) | ||
494 | { | ||
495 | struct nand_chip *nand_chip = mtd->priv; | ||
496 | struct mxc_nand_host *host = nand_chip->priv; | ||
497 | u32 ecc_stat, err; | ||
498 | int no_subpages = 1; | ||
499 | int ret = 0; | ||
500 | u8 ecc_bit_mask, err_limit; | ||
501 | |||
502 | ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf; | ||
503 | err_limit = (host->eccsize == 4) ? 0x4 : 0x8; | ||
504 | |||
505 | no_subpages = mtd->writesize >> 9; | ||
506 | |||
507 | if (nfc_is_v21()) | ||
508 | ecc_stat = readl(NFC_V1_V2_ECC_STATUS_RESULT); | ||
509 | else | ||
510 | ecc_stat = readl(NFC_V3_ECC_STATUS_RESULT); | ||
511 | |||
512 | do { | ||
513 | err = ecc_stat & ecc_bit_mask; | ||
514 | if (err > err_limit) { | ||
515 | printk(KERN_WARNING "UnCorrectable RS-ECC Error\n"); | ||
516 | return -1; | ||
517 | } else { | ||
518 | ret += err; | ||
519 | } | ||
520 | ecc_stat >>= 4; | ||
521 | } while (--no_subpages); | ||
522 | |||
523 | mtd->ecc_stats.corrected += ret; | ||
524 | pr_debug("%d Symbol Correctable RS-ECC Error\n", ret); | ||
525 | |||
526 | return ret; | ||
527 | } | ||
528 | |||
372 | static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, | 529 | static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, |
373 | u_char *ecc_code) | 530 | u_char *ecc_code) |
374 | { | 531 | { |
@@ -383,7 +540,7 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd) | |||
383 | 540 | ||
384 | /* Check for status request */ | 541 | /* Check for status request */ |
385 | if (host->status_request) | 542 | if (host->status_request) |
386 | return get_dev_status(host) & 0xFF; | 543 | return host->get_dev_status(host) & 0xFF; |
387 | 544 | ||
388 | ret = *(uint8_t *)(host->data_buf + host->buf_start); | 545 | ret = *(uint8_t *)(host->data_buf + host->buf_start); |
389 | host->buf_start++; | 546 | host->buf_start++; |
@@ -519,71 +676,163 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr) | |||
519 | * we will used the saved column address to index into | 676 | * we will used the saved column address to index into |
520 | * the full page. | 677 | * the full page. |
521 | */ | 678 | */ |
522 | send_addr(host, 0, page_addr == -1); | 679 | host->send_addr(host, 0, page_addr == -1); |
523 | if (mtd->writesize > 512) | 680 | if (mtd->writesize > 512) |
524 | /* another col addr cycle for 2k page */ | 681 | /* another col addr cycle for 2k page */ |
525 | send_addr(host, 0, false); | 682 | host->send_addr(host, 0, false); |
526 | } | 683 | } |
527 | 684 | ||
528 | /* Write out page address, if necessary */ | 685 | /* Write out page address, if necessary */ |
529 | if (page_addr != -1) { | 686 | if (page_addr != -1) { |
530 | /* paddr_0 - p_addr_7 */ | 687 | /* paddr_0 - p_addr_7 */ |
531 | send_addr(host, (page_addr & 0xff), false); | 688 | host->send_addr(host, (page_addr & 0xff), false); |
532 | 689 | ||
533 | if (mtd->writesize > 512) { | 690 | if (mtd->writesize > 512) { |
534 | if (mtd->size >= 0x10000000) { | 691 | if (mtd->size >= 0x10000000) { |
535 | /* paddr_8 - paddr_15 */ | 692 | /* paddr_8 - paddr_15 */ |
536 | send_addr(host, (page_addr >> 8) & 0xff, false); | 693 | host->send_addr(host, (page_addr >> 8) & 0xff, false); |
537 | send_addr(host, (page_addr >> 16) & 0xff, true); | 694 | host->send_addr(host, (page_addr >> 16) & 0xff, true); |
538 | } else | 695 | } else |
539 | /* paddr_8 - paddr_15 */ | 696 | /* paddr_8 - paddr_15 */ |
540 | send_addr(host, (page_addr >> 8) & 0xff, true); | 697 | host->send_addr(host, (page_addr >> 8) & 0xff, true); |
541 | } else { | 698 | } else { |
542 | /* One more address cycle for higher density devices */ | 699 | /* One more address cycle for higher density devices */ |
543 | if (mtd->size >= 0x4000000) { | 700 | if (mtd->size >= 0x4000000) { |
544 | /* paddr_8 - paddr_15 */ | 701 | /* paddr_8 - paddr_15 */ |
545 | send_addr(host, (page_addr >> 8) & 0xff, false); | 702 | host->send_addr(host, (page_addr >> 8) & 0xff, false); |
546 | send_addr(host, (page_addr >> 16) & 0xff, true); | 703 | host->send_addr(host, (page_addr >> 16) & 0xff, true); |
547 | } else | 704 | } else |
548 | /* paddr_8 - paddr_15 */ | 705 | /* paddr_8 - paddr_15 */ |
549 | send_addr(host, (page_addr >> 8) & 0xff, true); | 706 | host->send_addr(host, (page_addr >> 8) & 0xff, true); |
550 | } | 707 | } |
551 | } | 708 | } |
552 | } | 709 | } |
553 | 710 | ||
554 | static void preset(struct mtd_info *mtd) | 711 | /* |
712 | * v2 and v3 type controllers can do 4bit or 8bit ecc depending | ||
713 | * on how much oob the nand chip has. For 8bit ecc we need at least | ||
714 | * 26 bytes of oob data per 512 byte block. | ||
715 | */ | ||
716 | static int get_eccsize(struct mtd_info *mtd) | ||
717 | { | ||
718 | int oobbytes_per_512 = 0; | ||
719 | |||
720 | oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize; | ||
721 | |||
722 | if (oobbytes_per_512 < 26) | ||
723 | return 4; | ||
724 | else | ||
725 | return 8; | ||
726 | } | ||
727 | |||
728 | static void preset_v1_v2(struct mtd_info *mtd) | ||
555 | { | 729 | { |
556 | struct nand_chip *nand_chip = mtd->priv; | 730 | struct nand_chip *nand_chip = mtd->priv; |
557 | struct mxc_nand_host *host = nand_chip->priv; | 731 | struct mxc_nand_host *host = nand_chip->priv; |
558 | uint16_t tmp; | 732 | uint16_t tmp; |
559 | 733 | ||
560 | /* enable interrupt, disable spare enable */ | 734 | /* enable interrupt, disable spare enable */ |
561 | tmp = readw(host->regs + NFC_CONFIG1); | 735 | tmp = readw(NFC_V1_V2_CONFIG1); |
562 | tmp &= ~NFC_INT_MSK; | 736 | tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK; |
563 | tmp &= ~NFC_SP_EN; | 737 | tmp &= ~NFC_V1_V2_CONFIG1_SP_EN; |
564 | if (nand_chip->ecc.mode == NAND_ECC_HW) { | 738 | if (nand_chip->ecc.mode == NAND_ECC_HW) { |
565 | tmp |= NFC_ECC_EN; | 739 | tmp |= NFC_V1_V2_CONFIG1_ECC_EN; |
740 | } else { | ||
741 | tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN; | ||
742 | } | ||
743 | |||
744 | if (nfc_is_v21() && mtd->writesize) { | ||
745 | host->eccsize = get_eccsize(mtd); | ||
746 | if (host->eccsize == 4) | ||
747 | tmp |= NFC_V2_CONFIG1_ECC_MODE_4; | ||
566 | } else { | 748 | } else { |
567 | tmp &= ~NFC_ECC_EN; | 749 | host->eccsize = 1; |
568 | } | 750 | } |
569 | writew(tmp, host->regs + NFC_CONFIG1); | 751 | |
752 | writew(tmp, NFC_V1_V2_CONFIG1); | ||
570 | /* preset operation */ | 753 | /* preset operation */ |
571 | 754 | ||
572 | /* Unlock the internal RAM Buffer */ | 755 | /* Unlock the internal RAM Buffer */ |
573 | writew(0x2, host->regs + NFC_CONFIG); | 756 | writew(0x2, NFC_V1_V2_CONFIG); |
574 | 757 | ||
575 | /* Blocks to be unlocked */ | 758 | /* Blocks to be unlocked */ |
576 | if (nfc_is_v21()) { | 759 | if (nfc_is_v21()) { |
577 | writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR); | 760 | writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR); |
578 | writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR); | 761 | writew(0xffff, NFC_V21_UNLOCKEND_BLKADDR); |
579 | } else if (nfc_is_v1()) { | 762 | } else if (nfc_is_v1()) { |
580 | writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR); | 763 | writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR); |
581 | writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR); | 764 | writew(0x4000, NFC_V1_UNLOCKEND_BLKADDR); |
582 | } else | 765 | } else |
583 | BUG(); | 766 | BUG(); |
584 | 767 | ||
585 | /* Unlock Block Command for given address range */ | 768 | /* Unlock Block Command for given address range */ |
586 | writew(0x4, host->regs + NFC_WRPROT); | 769 | writew(0x4, NFC_V1_V2_WRPROT); |
770 | } | ||
771 | |||
772 | static void preset_v3(struct mtd_info *mtd) | ||
773 | { | ||
774 | struct nand_chip *chip = mtd->priv; | ||
775 | struct mxc_nand_host *host = chip->priv; | ||
776 | uint32_t config2, config3; | ||
777 | int i, addr_phases; | ||
778 | |||
779 | writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1); | ||
780 | writel(NFC_V3_IPC_CREQ, NFC_V3_IPC); | ||
781 | |||
782 | /* Unlock the internal RAM Buffer */ | ||
783 | writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK, | ||
784 | NFC_V3_WRPROT); | ||
785 | |||
786 | /* Blocks to be unlocked */ | ||
787 | for (i = 0; i < NAND_MAX_CHIPS; i++) | ||
788 | writel(0x0 | (0xffff << 16), | ||
789 | NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2)); | ||
790 | |||
791 | writel(0, NFC_V3_IPC); | ||
792 | |||
793 | config2 = NFC_V3_CONFIG2_ONE_CYCLE | | ||
794 | NFC_V3_CONFIG2_2CMD_PHASES | | ||
795 | NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) | | ||
796 | NFC_V3_CONFIG2_ST_CMD(0x70) | | ||
797 | NFC_V3_CONFIG2_NUM_ADDR_PHASE0; | ||
798 | |||
799 | if (chip->ecc.mode == NAND_ECC_HW) | ||
800 | config2 |= NFC_V3_CONFIG2_ECC_EN; | ||
801 | |||
802 | addr_phases = fls(chip->pagemask) >> 3; | ||
803 | |||
804 | if (mtd->writesize == 2048) { | ||
805 | config2 |= NFC_V3_CONFIG2_PS_2048; | ||
806 | config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases); | ||
807 | } else if (mtd->writesize == 4096) { | ||
808 | config2 |= NFC_V3_CONFIG2_PS_4096; | ||
809 | config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases); | ||
810 | } else { | ||
811 | config2 |= NFC_V3_CONFIG2_PS_512; | ||
812 | config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1); | ||
813 | } | ||
814 | |||
815 | if (mtd->writesize) { | ||
816 | config2 |= NFC_V3_CONFIG2_PPB(ffs(mtd->erasesize / mtd->writesize) - 6); | ||
817 | host->eccsize = get_eccsize(mtd); | ||
818 | if (host->eccsize == 8) | ||
819 | config2 |= NFC_V3_CONFIG2_ECC_MODE_8; | ||
820 | } | ||
821 | |||
822 | writel(config2, NFC_V3_CONFIG2); | ||
823 | |||
824 | config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) | | ||
825 | NFC_V3_CONFIG3_NO_SDMA | | ||
826 | NFC_V3_CONFIG3_RBB_MODE | | ||
827 | NFC_V3_CONFIG3_SBB(6) | /* Reset default */ | ||
828 | NFC_V3_CONFIG3_ADD_OP(0); | ||
829 | |||
830 | if (!(chip->options & NAND_BUSWIDTH_16)) | ||
831 | config3 |= NFC_V3_CONFIG3_FW8; | ||
832 | |||
833 | writel(config3, NFC_V3_CONFIG3); | ||
834 | |||
835 | writel(0, NFC_V3_DELAY_LINE); | ||
587 | } | 836 | } |
588 | 837 | ||
589 | /* Used by the upper layer to write command to NAND Flash for | 838 | /* Used by the upper layer to write command to NAND Flash for |
@@ -604,15 +853,15 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
604 | /* Command pre-processing step */ | 853 | /* Command pre-processing step */ |
605 | switch (command) { | 854 | switch (command) { |
606 | case NAND_CMD_RESET: | 855 | case NAND_CMD_RESET: |
607 | send_cmd(host, command, false); | 856 | host->preset(mtd); |
608 | preset(mtd); | 857 | host->send_cmd(host, command, false); |
609 | break; | 858 | break; |
610 | 859 | ||
611 | case NAND_CMD_STATUS: | 860 | case NAND_CMD_STATUS: |
612 | host->buf_start = 0; | 861 | host->buf_start = 0; |
613 | host->status_request = true; | 862 | host->status_request = true; |
614 | 863 | ||
615 | send_cmd(host, command, true); | 864 | host->send_cmd(host, command, true); |
616 | mxc_do_addr_cycle(mtd, column, page_addr); | 865 | mxc_do_addr_cycle(mtd, column, page_addr); |
617 | break; | 866 | break; |
618 | 867 | ||
@@ -623,70 +872,49 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
623 | else | 872 | else |
624 | host->buf_start = column + mtd->writesize; | 873 | host->buf_start = column + mtd->writesize; |
625 | 874 | ||
626 | if (mtd->writesize > 512) | 875 | command = NAND_CMD_READ0; /* only READ0 is valid */ |
627 | command = NAND_CMD_READ0; /* only READ0 is valid */ | ||
628 | 876 | ||
629 | send_cmd(host, command, false); | 877 | host->send_cmd(host, command, false); |
630 | mxc_do_addr_cycle(mtd, column, page_addr); | 878 | mxc_do_addr_cycle(mtd, column, page_addr); |
631 | 879 | ||
632 | if (mtd->writesize > 512) | 880 | if (mtd->writesize > 512) |
633 | send_cmd(host, NAND_CMD_READSTART, true); | 881 | host->send_cmd(host, NAND_CMD_READSTART, true); |
634 | 882 | ||
635 | send_page(mtd, NFC_OUTPUT); | 883 | host->send_page(mtd, NFC_OUTPUT); |
636 | 884 | ||
637 | memcpy(host->data_buf, host->main_area0, mtd->writesize); | 885 | memcpy(host->data_buf, host->main_area0, mtd->writesize); |
638 | copy_spare(mtd, true); | 886 | copy_spare(mtd, true); |
639 | break; | 887 | break; |
640 | 888 | ||
641 | case NAND_CMD_SEQIN: | 889 | case NAND_CMD_SEQIN: |
642 | if (column >= mtd->writesize) { | 890 | if (column >= mtd->writesize) |
643 | /* | 891 | /* call ourself to read a page */ |
644 | * FIXME: before send SEQIN command for write OOB, | 892 | mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr); |
645 | * We must read one page out. | ||
646 | * For K9F1GXX has no READ1 command to set current HW | ||
647 | * pointer to spare area, we must write the whole page | ||
648 | * including OOB together. | ||
649 | */ | ||
650 | if (mtd->writesize > 512) | ||
651 | /* call ourself to read a page */ | ||
652 | mxc_nand_command(mtd, NAND_CMD_READ0, 0, | ||
653 | page_addr); | ||
654 | |||
655 | host->buf_start = column; | ||
656 | |||
657 | /* Set program pointer to spare region */ | ||
658 | if (mtd->writesize == 512) | ||
659 | send_cmd(host, NAND_CMD_READOOB, false); | ||
660 | } else { | ||
661 | host->buf_start = column; | ||
662 | 893 | ||
663 | /* Set program pointer to page start */ | 894 | host->buf_start = column; |
664 | if (mtd->writesize == 512) | ||
665 | send_cmd(host, NAND_CMD_READ0, false); | ||
666 | } | ||
667 | 895 | ||
668 | send_cmd(host, command, false); | 896 | host->send_cmd(host, command, false); |
669 | mxc_do_addr_cycle(mtd, column, page_addr); | 897 | mxc_do_addr_cycle(mtd, column, page_addr); |
670 | break; | 898 | break; |
671 | 899 | ||
672 | case NAND_CMD_PAGEPROG: | 900 | case NAND_CMD_PAGEPROG: |
673 | memcpy(host->main_area0, host->data_buf, mtd->writesize); | 901 | memcpy(host->main_area0, host->data_buf, mtd->writesize); |
674 | copy_spare(mtd, false); | 902 | copy_spare(mtd, false); |
675 | send_page(mtd, NFC_INPUT); | 903 | host->send_page(mtd, NFC_INPUT); |
676 | send_cmd(host, command, true); | 904 | host->send_cmd(host, command, true); |
677 | mxc_do_addr_cycle(mtd, column, page_addr); | 905 | mxc_do_addr_cycle(mtd, column, page_addr); |
678 | break; | 906 | break; |
679 | 907 | ||
680 | case NAND_CMD_READID: | 908 | case NAND_CMD_READID: |
681 | send_cmd(host, command, true); | 909 | host->send_cmd(host, command, true); |
682 | mxc_do_addr_cycle(mtd, column, page_addr); | 910 | mxc_do_addr_cycle(mtd, column, page_addr); |
683 | send_read_id(host); | 911 | host->send_read_id(host); |
684 | host->buf_start = column; | 912 | host->buf_start = column; |
685 | break; | 913 | break; |
686 | 914 | ||
687 | case NAND_CMD_ERASE1: | 915 | case NAND_CMD_ERASE1: |
688 | case NAND_CMD_ERASE2: | 916 | case NAND_CMD_ERASE2: |
689 | send_cmd(host, command, false); | 917 | host->send_cmd(host, command, false); |
690 | mxc_do_addr_cycle(mtd, column, page_addr); | 918 | mxc_do_addr_cycle(mtd, column, page_addr); |
691 | 919 | ||
692 | break; | 920 | break; |
@@ -782,22 +1010,55 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
782 | } | 1010 | } |
783 | 1011 | ||
784 | host->main_area0 = host->base; | 1012 | host->main_area0 = host->base; |
785 | host->main_area1 = host->base + 0x200; | 1013 | |
1014 | if (nfc_is_v1() || nfc_is_v21()) { | ||
1015 | host->preset = preset_v1_v2; | ||
1016 | host->send_cmd = send_cmd_v1_v2; | ||
1017 | host->send_addr = send_addr_v1_v2; | ||
1018 | host->send_page = send_page_v1_v2; | ||
1019 | host->send_read_id = send_read_id_v1_v2; | ||
1020 | host->get_dev_status = get_dev_status_v1_v2; | ||
1021 | host->check_int = check_int_v1_v2; | ||
1022 | } | ||
786 | 1023 | ||
787 | if (nfc_is_v21()) { | 1024 | if (nfc_is_v21()) { |
788 | host->regs = host->base + 0x1000; | 1025 | host->regs = host->base + 0x1e00; |
789 | host->spare0 = host->base + 0x1000; | 1026 | host->spare0 = host->base + 0x1000; |
790 | host->spare_len = 64; | 1027 | host->spare_len = 64; |
791 | oob_smallpage = &nandv2_hw_eccoob_smallpage; | 1028 | oob_smallpage = &nandv2_hw_eccoob_smallpage; |
792 | oob_largepage = &nandv2_hw_eccoob_largepage; | 1029 | oob_largepage = &nandv2_hw_eccoob_largepage; |
793 | this->ecc.bytes = 9; | 1030 | this->ecc.bytes = 9; |
794 | } else if (nfc_is_v1()) { | 1031 | } else if (nfc_is_v1()) { |
795 | host->regs = host->base; | 1032 | host->regs = host->base + 0xe00; |
796 | host->spare0 = host->base + 0x800; | 1033 | host->spare0 = host->base + 0x800; |
797 | host->spare_len = 16; | 1034 | host->spare_len = 16; |
798 | oob_smallpage = &nandv1_hw_eccoob_smallpage; | 1035 | oob_smallpage = &nandv1_hw_eccoob_smallpage; |
799 | oob_largepage = &nandv1_hw_eccoob_largepage; | 1036 | oob_largepage = &nandv1_hw_eccoob_largepage; |
800 | this->ecc.bytes = 3; | 1037 | this->ecc.bytes = 3; |
1038 | host->eccsize = 1; | ||
1039 | } else if (nfc_is_v3_2()) { | ||
1040 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
1041 | if (!res) { | ||
1042 | err = -ENODEV; | ||
1043 | goto eirq; | ||
1044 | } | ||
1045 | host->regs_ip = ioremap(res->start, resource_size(res)); | ||
1046 | if (!host->regs_ip) { | ||
1047 | err = -ENOMEM; | ||
1048 | goto eirq; | ||
1049 | } | ||
1050 | host->regs_axi = host->base + 0x1e00; | ||
1051 | host->spare0 = host->base + 0x1000; | ||
1052 | host->spare_len = 64; | ||
1053 | host->preset = preset_v3; | ||
1054 | host->send_cmd = send_cmd_v3; | ||
1055 | host->send_addr = send_addr_v3; | ||
1056 | host->send_page = send_page_v3; | ||
1057 | host->send_read_id = send_read_id_v3; | ||
1058 | host->check_int = check_int_v3; | ||
1059 | host->get_dev_status = get_dev_status_v3; | ||
1060 | oob_smallpage = &nandv2_hw_eccoob_smallpage; | ||
1061 | oob_largepage = &nandv2_hw_eccoob_largepage; | ||
801 | } else | 1062 | } else |
802 | BUG(); | 1063 | BUG(); |
803 | 1064 | ||
@@ -807,7 +1068,10 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
807 | if (pdata->hw_ecc) { | 1068 | if (pdata->hw_ecc) { |
808 | this->ecc.calculate = mxc_nand_calculate_ecc; | 1069 | this->ecc.calculate = mxc_nand_calculate_ecc; |
809 | this->ecc.hwctl = mxc_nand_enable_hwecc; | 1070 | this->ecc.hwctl = mxc_nand_enable_hwecc; |
810 | this->ecc.correct = mxc_nand_correct_data; | 1071 | if (nfc_is_v1()) |
1072 | this->ecc.correct = mxc_nand_correct_data_v1; | ||
1073 | else | ||
1074 | this->ecc.correct = mxc_nand_correct_data_v2_v3; | ||
811 | this->ecc.mode = NAND_ECC_HW; | 1075 | this->ecc.mode = NAND_ECC_HW; |
812 | } else { | 1076 | } else { |
813 | this->ecc.mode = NAND_ECC_SOFT; | 1077 | this->ecc.mode = NAND_ECC_SOFT; |
@@ -838,6 +1102,9 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
838 | goto escan; | 1102 | goto escan; |
839 | } | 1103 | } |
840 | 1104 | ||
1105 | /* Call preset again, with correct writesize this time */ | ||
1106 | host->preset(mtd); | ||
1107 | |||
841 | if (mtd->writesize == 2048) | 1108 | if (mtd->writesize == 2048) |
842 | this->ecc.layout = oob_largepage; | 1109 | this->ecc.layout = oob_largepage; |
843 | 1110 | ||
@@ -853,6 +1120,8 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
853 | parse_mtd_partitions(mtd, part_probes, &host->parts, 0); | 1120 | parse_mtd_partitions(mtd, part_probes, &host->parts, 0); |
854 | if (nr_parts > 0) | 1121 | if (nr_parts > 0) |
855 | add_mtd_partitions(mtd, host->parts, nr_parts); | 1122 | add_mtd_partitions(mtd, host->parts, nr_parts); |
1123 | else if (pdata->parts) | ||
1124 | add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); | ||
856 | else | 1125 | else |
857 | #endif | 1126 | #endif |
858 | { | 1127 | { |
@@ -867,6 +1136,8 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
867 | escan: | 1136 | escan: |
868 | free_irq(host->irq, host); | 1137 | free_irq(host->irq, host); |
869 | eirq: | 1138 | eirq: |
1139 | if (host->regs_ip) | ||
1140 | iounmap(host->regs_ip); | ||
870 | iounmap(host->base); | 1141 | iounmap(host->base); |
871 | eres: | 1142 | eres: |
872 | clk_put(host->clk); | 1143 | clk_put(host->clk); |
@@ -886,59 +1157,19 @@ static int __devexit mxcnd_remove(struct platform_device *pdev) | |||
886 | 1157 | ||
887 | nand_release(&host->mtd); | 1158 | nand_release(&host->mtd); |
888 | free_irq(host->irq, host); | 1159 | free_irq(host->irq, host); |
1160 | if (host->regs_ip) | ||
1161 | iounmap(host->regs_ip); | ||
889 | iounmap(host->base); | 1162 | iounmap(host->base); |
890 | kfree(host); | 1163 | kfree(host); |
891 | 1164 | ||
892 | return 0; | 1165 | return 0; |
893 | } | 1166 | } |
894 | 1167 | ||
895 | #ifdef CONFIG_PM | ||
896 | static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state) | ||
897 | { | ||
898 | struct mtd_info *mtd = platform_get_drvdata(pdev); | ||
899 | struct nand_chip *nand_chip = mtd->priv; | ||
900 | struct mxc_nand_host *host = nand_chip->priv; | ||
901 | int ret = 0; | ||
902 | |||
903 | DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND suspend\n"); | ||
904 | |||
905 | ret = mtd->suspend(mtd); | ||
906 | |||
907 | /* | ||
908 | * nand_suspend locks the device for exclusive access, so | ||
909 | * the clock must already be off. | ||
910 | */ | ||
911 | BUG_ON(!ret && host->clk_act); | ||
912 | |||
913 | return ret; | ||
914 | } | ||
915 | |||
916 | static int mxcnd_resume(struct platform_device *pdev) | ||
917 | { | ||
918 | struct mtd_info *mtd = platform_get_drvdata(pdev); | ||
919 | struct nand_chip *nand_chip = mtd->priv; | ||
920 | struct mxc_nand_host *host = nand_chip->priv; | ||
921 | int ret = 0; | ||
922 | |||
923 | DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND resume\n"); | ||
924 | |||
925 | mtd->resume(mtd); | ||
926 | |||
927 | return ret; | ||
928 | } | ||
929 | |||
930 | #else | ||
931 | # define mxcnd_suspend NULL | ||
932 | # define mxcnd_resume NULL | ||
933 | #endif /* CONFIG_PM */ | ||
934 | |||
935 | static struct platform_driver mxcnd_driver = { | 1168 | static struct platform_driver mxcnd_driver = { |
936 | .driver = { | 1169 | .driver = { |
937 | .name = DRIVER_NAME, | 1170 | .name = DRIVER_NAME, |
938 | }, | 1171 | }, |
939 | .remove = __devexit_p(mxcnd_remove), | 1172 | .remove = __devexit_p(mxcnd_remove), |
940 | .suspend = mxcnd_suspend, | ||
941 | .resume = mxcnd_resume, | ||
942 | }; | 1173 | }; |
943 | 1174 | ||
944 | static int __init mxc_nd_init(void) | 1175 | static int __init mxc_nd_init(void) |