.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * ST Microelectronics |
---|
3 | 4 | * Flexible Static Memory Controller (FSMC) |
---|
.. | .. |
---|
10 | 11 | * Based on drivers/mtd/nand/nomadik_nand.c (removed in v3.8) |
---|
11 | 12 | * Copyright © 2007 STMicroelectronics Pvt. Ltd. |
---|
12 | 13 | * Copyright © 2009 Alessandro Rubini |
---|
13 | | - * |
---|
14 | | - * This file is licensed under the terms of the GNU General Public |
---|
15 | | - * License version 2. This program is licensed "as is" without any |
---|
16 | | - * warranty of any kind, whether express or implied. |
---|
17 | 14 | */ |
---|
18 | 15 | |
---|
19 | 16 | #include <linux/clk.h> |
---|
.. | .. |
---|
42 | 39 | /* fsmc controller registers for NOR flash */ |
---|
43 | 40 | #define CTRL 0x0 |
---|
44 | 41 | /* ctrl register definitions */ |
---|
45 | | - #define BANK_ENABLE (1 << 0) |
---|
46 | | - #define MUXED (1 << 1) |
---|
| 42 | + #define BANK_ENABLE BIT(0) |
---|
| 43 | + #define MUXED BIT(1) |
---|
47 | 44 | #define NOR_DEV (2 << 2) |
---|
48 | | - #define WIDTH_8 (0 << 4) |
---|
49 | | - #define WIDTH_16 (1 << 4) |
---|
50 | | - #define RSTPWRDWN (1 << 6) |
---|
51 | | - #define WPROT (1 << 7) |
---|
52 | | - #define WRT_ENABLE (1 << 12) |
---|
53 | | - #define WAIT_ENB (1 << 13) |
---|
| 45 | + #define WIDTH_16 BIT(4) |
---|
| 46 | + #define RSTPWRDWN BIT(6) |
---|
| 47 | + #define WPROT BIT(7) |
---|
| 48 | + #define WRT_ENABLE BIT(12) |
---|
| 49 | + #define WAIT_ENB BIT(13) |
---|
54 | 50 | |
---|
55 | 51 | #define CTRL_TIM 0x4 |
---|
56 | 52 | /* ctrl_tim register definitions */ |
---|
.. | .. |
---|
58 | 54 | #define FSMC_NOR_BANK_SZ 0x8 |
---|
59 | 55 | #define FSMC_NOR_REG_SIZE 0x40 |
---|
60 | 56 | |
---|
61 | | -#define FSMC_NOR_REG(base, bank, reg) (base + \ |
---|
62 | | - FSMC_NOR_BANK_SZ * (bank) + \ |
---|
63 | | - reg) |
---|
| 57 | +#define FSMC_NOR_REG(base, bank, reg) ((base) + \ |
---|
| 58 | + (FSMC_NOR_BANK_SZ * (bank)) + \ |
---|
| 59 | + (reg)) |
---|
64 | 60 | |
---|
65 | 61 | /* fsmc controller registers for NAND flash */ |
---|
66 | 62 | #define FSMC_PC 0x00 |
---|
67 | 63 | /* pc register definitions */ |
---|
68 | | - #define FSMC_RESET (1 << 0) |
---|
69 | | - #define FSMC_WAITON (1 << 1) |
---|
70 | | - #define FSMC_ENABLE (1 << 2) |
---|
71 | | - #define FSMC_DEVTYPE_NAND (1 << 3) |
---|
72 | | - #define FSMC_DEVWID_8 (0 << 4) |
---|
73 | | - #define FSMC_DEVWID_16 (1 << 4) |
---|
74 | | - #define FSMC_ECCEN (1 << 6) |
---|
75 | | - #define FSMC_ECCPLEN_512 (0 << 7) |
---|
76 | | - #define FSMC_ECCPLEN_256 (1 << 7) |
---|
77 | | - #define FSMC_TCLR_1 (1) |
---|
| 64 | + #define FSMC_RESET BIT(0) |
---|
| 65 | + #define FSMC_WAITON BIT(1) |
---|
| 66 | + #define FSMC_ENABLE BIT(2) |
---|
| 67 | + #define FSMC_DEVTYPE_NAND BIT(3) |
---|
| 68 | + #define FSMC_DEVWID_16 BIT(4) |
---|
| 69 | + #define FSMC_ECCEN BIT(6) |
---|
| 70 | + #define FSMC_ECCPLEN_256 BIT(7) |
---|
78 | 71 | #define FSMC_TCLR_SHIFT (9) |
---|
79 | 72 | #define FSMC_TCLR_MASK (0xF) |
---|
80 | | - #define FSMC_TAR_1 (1) |
---|
81 | 73 | #define FSMC_TAR_SHIFT (13) |
---|
82 | 74 | #define FSMC_TAR_MASK (0xF) |
---|
83 | 75 | #define STS 0x04 |
---|
84 | 76 | /* sts register definitions */ |
---|
85 | | - #define FSMC_CODE_RDY (1 << 15) |
---|
| 77 | + #define FSMC_CODE_RDY BIT(15) |
---|
86 | 78 | #define COMM 0x08 |
---|
87 | 79 | /* comm register definitions */ |
---|
88 | | - #define FSMC_TSET_0 0 |
---|
89 | 80 | #define FSMC_TSET_SHIFT 0 |
---|
90 | 81 | #define FSMC_TSET_MASK 0xFF |
---|
91 | | - #define FSMC_TWAIT_6 6 |
---|
92 | 82 | #define FSMC_TWAIT_SHIFT 8 |
---|
93 | 83 | #define FSMC_TWAIT_MASK 0xFF |
---|
94 | | - #define FSMC_THOLD_4 4 |
---|
95 | 84 | #define FSMC_THOLD_SHIFT 16 |
---|
96 | 85 | #define FSMC_THOLD_MASK 0xFF |
---|
97 | | - #define FSMC_THIZ_1 1 |
---|
98 | 86 | #define FSMC_THIZ_SHIFT 24 |
---|
99 | 87 | #define FSMC_THIZ_MASK 0xFF |
---|
100 | 88 | #define ATTRIB 0x0C |
---|
.. | .. |
---|
106 | 94 | |
---|
107 | 95 | #define FSMC_BUSY_WAIT_TIMEOUT (1 * HZ) |
---|
108 | 96 | |
---|
| 97 | +/* |
---|
| 98 | + * According to SPEAr300 Reference Manual (RM0082) |
---|
| 99 | + * TOUDEL = 7ns (Output delay from the flip-flops to the board) |
---|
| 100 | + * TINDEL = 5ns (Input delay from the board to the flipflop) |
---|
| 101 | + */ |
---|
| 102 | +#define TOUTDEL 7000 |
---|
| 103 | +#define TINDEL 5000 |
---|
| 104 | + |
---|
109 | 105 | struct fsmc_nand_timings { |
---|
110 | | - uint8_t tclr; |
---|
111 | | - uint8_t tar; |
---|
112 | | - uint8_t thiz; |
---|
113 | | - uint8_t thold; |
---|
114 | | - uint8_t twait; |
---|
115 | | - uint8_t tset; |
---|
| 106 | + u8 tclr; |
---|
| 107 | + u8 tar; |
---|
| 108 | + u8 thiz; |
---|
| 109 | + u8 thold; |
---|
| 110 | + u8 twait; |
---|
| 111 | + u8 tset; |
---|
116 | 112 | }; |
---|
117 | 113 | |
---|
118 | 114 | enum access_mode { |
---|
.. | .. |
---|
123 | 119 | /** |
---|
124 | 120 | * struct fsmc_nand_data - structure for FSMC NAND device state |
---|
125 | 121 | * |
---|
| 122 | + * @base: Inherit from the nand_controller struct |
---|
126 | 123 | * @pid: Part ID on the AMBA PrimeCell format |
---|
127 | | - * @mtd: MTD info for a NAND flash. |
---|
128 | 124 | * @nand: Chip related info for a NAND flash. |
---|
129 | | - * @partitions: Partition info for a NAND Flash. |
---|
130 | | - * @nr_partitions: Total number of partition of a NAND flash. |
---|
131 | 125 | * |
---|
132 | 126 | * @bank: Bank number for probed device. |
---|
| 127 | + * @dev: Parent device |
---|
| 128 | + * @mode: Access mode |
---|
133 | 129 | * @clk: Clock structure for FSMC. |
---|
134 | 130 | * |
---|
135 | 131 | * @read_dma_chan: DMA channel for read access |
---|
136 | 132 | * @write_dma_chan: DMA channel for write access to NAND |
---|
137 | 133 | * @dma_access_complete: Completion structure |
---|
| 134 | + * |
---|
| 135 | + * @dev_timings: NAND timings |
---|
138 | 136 | * |
---|
139 | 137 | * @data_pa: NAND Physical port for Data. |
---|
140 | 138 | * @data_va: NAND port for Data. |
---|
.. | .. |
---|
143 | 141 | * @regs_va: Registers base address for a given bank. |
---|
144 | 142 | */ |
---|
145 | 143 | struct fsmc_nand_data { |
---|
| 144 | + struct nand_controller base; |
---|
146 | 145 | u32 pid; |
---|
147 | 146 | struct nand_chip nand; |
---|
148 | 147 | |
---|
.. | .. |
---|
249 | 248 | .free = fsmc_ecc4_ooblayout_free, |
---|
250 | 249 | }; |
---|
251 | 250 | |
---|
252 | | -static inline struct fsmc_nand_data *mtd_to_fsmc(struct mtd_info *mtd) |
---|
| 251 | +static inline struct fsmc_nand_data *nand_to_fsmc(struct nand_chip *chip) |
---|
253 | 252 | { |
---|
254 | | - return container_of(mtd_to_nand(mtd), struct fsmc_nand_data, nand); |
---|
| 253 | + return container_of(chip, struct fsmc_nand_data, nand); |
---|
255 | 254 | } |
---|
256 | 255 | |
---|
257 | 256 | /* |
---|
.. | .. |
---|
263 | 262 | static void fsmc_nand_setup(struct fsmc_nand_data *host, |
---|
264 | 263 | struct fsmc_nand_timings *tims) |
---|
265 | 264 | { |
---|
266 | | - uint32_t value = FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON; |
---|
267 | | - uint32_t tclr, tar, thiz, thold, twait, tset; |
---|
| 265 | + u32 value = FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON; |
---|
| 266 | + u32 tclr, tar, thiz, thold, twait, tset; |
---|
268 | 267 | |
---|
269 | 268 | tclr = (tims->tclr & FSMC_TCLR_MASK) << FSMC_TCLR_SHIFT; |
---|
270 | 269 | tar = (tims->tar & FSMC_TAR_MASK) << FSMC_TAR_SHIFT; |
---|
.. | .. |
---|
274 | 273 | tset = (tims->tset & FSMC_TSET_MASK) << FSMC_TSET_SHIFT; |
---|
275 | 274 | |
---|
276 | 275 | if (host->nand.options & NAND_BUSWIDTH_16) |
---|
277 | | - writel_relaxed(value | FSMC_DEVWID_16, |
---|
278 | | - host->regs_va + FSMC_PC); |
---|
279 | | - else |
---|
280 | | - writel_relaxed(value | FSMC_DEVWID_8, host->regs_va + FSMC_PC); |
---|
| 276 | + value |= FSMC_DEVWID_16; |
---|
281 | 277 | |
---|
282 | | - writel_relaxed(readl(host->regs_va + FSMC_PC) | tclr | tar, |
---|
283 | | - host->regs_va + FSMC_PC); |
---|
| 278 | + writel_relaxed(value | tclr | tar, host->regs_va + FSMC_PC); |
---|
284 | 279 | writel_relaxed(thiz | thold | twait | tset, host->regs_va + COMM); |
---|
285 | 280 | writel_relaxed(thiz | thold | twait | tset, host->regs_va + ATTRIB); |
---|
286 | 281 | } |
---|
.. | .. |
---|
291 | 286 | { |
---|
292 | 287 | unsigned long hclk = clk_get_rate(host->clk); |
---|
293 | 288 | unsigned long hclkn = NSEC_PER_SEC / hclk; |
---|
294 | | - uint32_t thiz, thold, twait, tset; |
---|
| 289 | + u32 thiz, thold, twait, tset, twait_min; |
---|
295 | 290 | |
---|
296 | 291 | if (sdrt->tRC_min < 30000) |
---|
297 | 292 | return -EOPNOTSUPP; |
---|
.. | .. |
---|
323 | 318 | else if (tims->thold > FSMC_THOLD_MASK) |
---|
324 | 319 | tims->thold = FSMC_THOLD_MASK; |
---|
325 | 320 | |
---|
326 | | - twait = max(sdrt->tRP_min, sdrt->tWP_min); |
---|
327 | | - tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1; |
---|
328 | | - if (tims->twait == 0) |
---|
329 | | - tims->twait = 1; |
---|
330 | | - else if (tims->twait > FSMC_TWAIT_MASK) |
---|
331 | | - tims->twait = FSMC_TWAIT_MASK; |
---|
332 | | - |
---|
333 | 321 | tset = max(sdrt->tCS_min - sdrt->tWP_min, |
---|
334 | 322 | sdrt->tCEA_max - sdrt->tREA_max); |
---|
335 | 323 | tims->tset = DIV_ROUND_UP(tset / 1000, hclkn) - 1; |
---|
.. | .. |
---|
338 | 326 | else if (tims->tset > FSMC_TSET_MASK) |
---|
339 | 327 | tims->tset = FSMC_TSET_MASK; |
---|
340 | 328 | |
---|
| 329 | + /* |
---|
| 330 | + * According to SPEAr300 Reference Manual (RM0082) which gives more |
---|
| 331 | + * information related to FSMSC timings than the SPEAr600 one (RM0305), |
---|
| 332 | + * twait >= tCEA - (tset * TCLK) + TOUTDEL + TINDEL |
---|
| 333 | + */ |
---|
| 334 | + twait_min = sdrt->tCEA_max - ((tims->tset + 1) * hclkn * 1000) |
---|
| 335 | + + TOUTDEL + TINDEL; |
---|
| 336 | + twait = max3(sdrt->tRP_min, sdrt->tWP_min, twait_min); |
---|
| 337 | + |
---|
| 338 | + tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1; |
---|
| 339 | + if (tims->twait == 0) |
---|
| 340 | + tims->twait = 1; |
---|
| 341 | + else if (tims->twait > FSMC_TWAIT_MASK) |
---|
| 342 | + tims->twait = FSMC_TWAIT_MASK; |
---|
| 343 | + |
---|
341 | 344 | return 0; |
---|
342 | 345 | } |
---|
343 | 346 | |
---|
344 | | -static int fsmc_setup_data_interface(struct mtd_info *mtd, int csline, |
---|
345 | | - const struct nand_data_interface *conf) |
---|
| 347 | +static int fsmc_setup_interface(struct nand_chip *nand, int csline, |
---|
| 348 | + const struct nand_interface_config *conf) |
---|
346 | 349 | { |
---|
347 | | - struct nand_chip *nand = mtd_to_nand(mtd); |
---|
348 | | - struct fsmc_nand_data *host = nand_get_controller_data(nand); |
---|
| 350 | + struct fsmc_nand_data *host = nand_to_fsmc(nand); |
---|
349 | 351 | struct fsmc_nand_timings tims; |
---|
350 | 352 | const struct nand_sdr_timings *sdrt; |
---|
351 | 353 | int ret; |
---|
.. | .. |
---|
369 | 371 | /* |
---|
370 | 372 | * fsmc_enable_hwecc - Enables Hardware ECC through FSMC registers |
---|
371 | 373 | */ |
---|
372 | | -static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode) |
---|
| 374 | +static void fsmc_enable_hwecc(struct nand_chip *chip, int mode) |
---|
373 | 375 | { |
---|
374 | | - struct fsmc_nand_data *host = mtd_to_fsmc(mtd); |
---|
| 376 | + struct fsmc_nand_data *host = nand_to_fsmc(chip); |
---|
375 | 377 | |
---|
376 | 378 | writel_relaxed(readl(host->regs_va + FSMC_PC) & ~FSMC_ECCPLEN_256, |
---|
377 | 379 | host->regs_va + FSMC_PC); |
---|
.. | .. |
---|
386 | 388 | * FSMC. ECC is 13 bytes for 512 bytes of data (supports error correction up to |
---|
387 | 389 | * max of 8-bits) |
---|
388 | 390 | */ |
---|
389 | | -static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data, |
---|
390 | | - uint8_t *ecc) |
---|
| 391 | +static int fsmc_read_hwecc_ecc4(struct nand_chip *chip, const u8 *data, |
---|
| 392 | + u8 *ecc) |
---|
391 | 393 | { |
---|
392 | | - struct fsmc_nand_data *host = mtd_to_fsmc(mtd); |
---|
393 | | - uint32_t ecc_tmp; |
---|
| 394 | + struct fsmc_nand_data *host = nand_to_fsmc(chip); |
---|
| 395 | + u32 ecc_tmp; |
---|
394 | 396 | unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT; |
---|
395 | 397 | |
---|
396 | 398 | do { |
---|
397 | 399 | if (readl_relaxed(host->regs_va + STS) & FSMC_CODE_RDY) |
---|
398 | 400 | break; |
---|
399 | | - else |
---|
400 | | - cond_resched(); |
---|
| 401 | + |
---|
| 402 | + cond_resched(); |
---|
401 | 403 | } while (!time_after_eq(jiffies, deadline)); |
---|
402 | 404 | |
---|
403 | 405 | if (time_after_eq(jiffies, deadline)) { |
---|
.. | .. |
---|
406 | 408 | } |
---|
407 | 409 | |
---|
408 | 410 | ecc_tmp = readl_relaxed(host->regs_va + ECC1); |
---|
409 | | - ecc[0] = (uint8_t) (ecc_tmp >> 0); |
---|
410 | | - ecc[1] = (uint8_t) (ecc_tmp >> 8); |
---|
411 | | - ecc[2] = (uint8_t) (ecc_tmp >> 16); |
---|
412 | | - ecc[3] = (uint8_t) (ecc_tmp >> 24); |
---|
| 411 | + ecc[0] = ecc_tmp; |
---|
| 412 | + ecc[1] = ecc_tmp >> 8; |
---|
| 413 | + ecc[2] = ecc_tmp >> 16; |
---|
| 414 | + ecc[3] = ecc_tmp >> 24; |
---|
413 | 415 | |
---|
414 | 416 | ecc_tmp = readl_relaxed(host->regs_va + ECC2); |
---|
415 | | - ecc[4] = (uint8_t) (ecc_tmp >> 0); |
---|
416 | | - ecc[5] = (uint8_t) (ecc_tmp >> 8); |
---|
417 | | - ecc[6] = (uint8_t) (ecc_tmp >> 16); |
---|
418 | | - ecc[7] = (uint8_t) (ecc_tmp >> 24); |
---|
| 417 | + ecc[4] = ecc_tmp; |
---|
| 418 | + ecc[5] = ecc_tmp >> 8; |
---|
| 419 | + ecc[6] = ecc_tmp >> 16; |
---|
| 420 | + ecc[7] = ecc_tmp >> 24; |
---|
419 | 421 | |
---|
420 | 422 | ecc_tmp = readl_relaxed(host->regs_va + ECC3); |
---|
421 | | - ecc[8] = (uint8_t) (ecc_tmp >> 0); |
---|
422 | | - ecc[9] = (uint8_t) (ecc_tmp >> 8); |
---|
423 | | - ecc[10] = (uint8_t) (ecc_tmp >> 16); |
---|
424 | | - ecc[11] = (uint8_t) (ecc_tmp >> 24); |
---|
| 423 | + ecc[8] = ecc_tmp; |
---|
| 424 | + ecc[9] = ecc_tmp >> 8; |
---|
| 425 | + ecc[10] = ecc_tmp >> 16; |
---|
| 426 | + ecc[11] = ecc_tmp >> 24; |
---|
425 | 427 | |
---|
426 | 428 | ecc_tmp = readl_relaxed(host->regs_va + STS); |
---|
427 | | - ecc[12] = (uint8_t) (ecc_tmp >> 16); |
---|
| 429 | + ecc[12] = ecc_tmp >> 16; |
---|
428 | 430 | |
---|
429 | 431 | return 0; |
---|
430 | 432 | } |
---|
.. | .. |
---|
434 | 436 | * FSMC. ECC is 3 bytes for 512 bytes of data (supports error correction up to |
---|
435 | 437 | * max of 1-bit) |
---|
436 | 438 | */ |
---|
437 | | -static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data, |
---|
438 | | - uint8_t *ecc) |
---|
| 439 | +static int fsmc_read_hwecc_ecc1(struct nand_chip *chip, const u8 *data, |
---|
| 440 | + u8 *ecc) |
---|
439 | 441 | { |
---|
440 | | - struct fsmc_nand_data *host = mtd_to_fsmc(mtd); |
---|
441 | | - uint32_t ecc_tmp; |
---|
| 442 | + struct fsmc_nand_data *host = nand_to_fsmc(chip); |
---|
| 443 | + u32 ecc_tmp; |
---|
442 | 444 | |
---|
443 | 445 | ecc_tmp = readl_relaxed(host->regs_va + ECC1); |
---|
444 | | - ecc[0] = (uint8_t) (ecc_tmp >> 0); |
---|
445 | | - ecc[1] = (uint8_t) (ecc_tmp >> 8); |
---|
446 | | - ecc[2] = (uint8_t) (ecc_tmp >> 16); |
---|
| 446 | + ecc[0] = ecc_tmp; |
---|
| 447 | + ecc[1] = ecc_tmp >> 8; |
---|
| 448 | + ecc[2] = ecc_tmp >> 16; |
---|
447 | 449 | |
---|
448 | 450 | return 0; |
---|
449 | 451 | } |
---|
450 | 452 | |
---|
451 | 453 | /* Count the number of 0's in buff upto a max of max_bits */ |
---|
452 | | -static int count_written_bits(uint8_t *buff, int size, int max_bits) |
---|
| 454 | +static int count_written_bits(u8 *buff, int size, int max_bits) |
---|
453 | 455 | { |
---|
454 | 456 | int k, written_bits = 0; |
---|
455 | 457 | |
---|
.. | .. |
---|
470 | 472 | } |
---|
471 | 473 | |
---|
472 | 474 | static int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len, |
---|
473 | | - enum dma_data_direction direction) |
---|
| 475 | + enum dma_data_direction direction) |
---|
474 | 476 | { |
---|
475 | 477 | struct dma_chan *chan; |
---|
476 | 478 | struct dma_device *dma_dev; |
---|
.. | .. |
---|
521 | 523 | |
---|
522 | 524 | time_left = |
---|
523 | 525 | wait_for_completion_timeout(&host->dma_access_complete, |
---|
524 | | - msecs_to_jiffies(3000)); |
---|
| 526 | + msecs_to_jiffies(3000)); |
---|
525 | 527 | if (time_left == 0) { |
---|
526 | 528 | dmaengine_terminate_all(chan); |
---|
527 | 529 | dev_err(host->dev, "wait_for_completion_timeout\n"); |
---|
.. | .. |
---|
539 | 541 | |
---|
540 | 542 | /* |
---|
541 | 543 | * fsmc_write_buf - write buffer to chip |
---|
542 | | - * @mtd: MTD device structure |
---|
| 544 | + * @host: FSMC NAND controller |
---|
543 | 545 | * @buf: data buffer |
---|
544 | 546 | * @len: number of bytes to write |
---|
545 | 547 | */ |
---|
546 | | -static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) |
---|
| 548 | +static void fsmc_write_buf(struct fsmc_nand_data *host, const u8 *buf, |
---|
| 549 | + int len) |
---|
547 | 550 | { |
---|
548 | | - struct fsmc_nand_data *host = mtd_to_fsmc(mtd); |
---|
549 | 551 | int i; |
---|
550 | 552 | |
---|
551 | | - if (IS_ALIGNED((uintptr_t)buf, sizeof(uint32_t)) && |
---|
552 | | - IS_ALIGNED(len, sizeof(uint32_t))) { |
---|
553 | | - uint32_t *p = (uint32_t *)buf; |
---|
| 553 | + if (IS_ALIGNED((uintptr_t)buf, sizeof(u32)) && |
---|
| 554 | + IS_ALIGNED(len, sizeof(u32))) { |
---|
| 555 | + u32 *p = (u32 *)buf; |
---|
| 556 | + |
---|
554 | 557 | len = len >> 2; |
---|
555 | 558 | for (i = 0; i < len; i++) |
---|
556 | 559 | writel_relaxed(p[i], host->data_va); |
---|
.. | .. |
---|
562 | 565 | |
---|
563 | 566 | /* |
---|
564 | 567 | * fsmc_read_buf - read chip data into buffer |
---|
565 | | - * @mtd: MTD device structure |
---|
| 568 | + * @host: FSMC NAND controller |
---|
566 | 569 | * @buf: buffer to store date |
---|
567 | 570 | * @len: number of bytes to read |
---|
568 | 571 | */ |
---|
569 | | -static void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) |
---|
| 572 | +static void fsmc_read_buf(struct fsmc_nand_data *host, u8 *buf, int len) |
---|
570 | 573 | { |
---|
571 | | - struct fsmc_nand_data *host = mtd_to_fsmc(mtd); |
---|
572 | 574 | int i; |
---|
573 | 575 | |
---|
574 | | - if (IS_ALIGNED((uintptr_t)buf, sizeof(uint32_t)) && |
---|
575 | | - IS_ALIGNED(len, sizeof(uint32_t))) { |
---|
576 | | - uint32_t *p = (uint32_t *)buf; |
---|
| 576 | + if (IS_ALIGNED((uintptr_t)buf, sizeof(u32)) && |
---|
| 577 | + IS_ALIGNED(len, sizeof(u32))) { |
---|
| 578 | + u32 *p = (u32 *)buf; |
---|
| 579 | + |
---|
577 | 580 | len = len >> 2; |
---|
578 | 581 | for (i = 0; i < len; i++) |
---|
579 | 582 | p[i] = readl_relaxed(host->data_va); |
---|
.. | .. |
---|
585 | 588 | |
---|
586 | 589 | /* |
---|
587 | 590 | * fsmc_read_buf_dma - read chip data into buffer |
---|
588 | | - * @mtd: MTD device structure |
---|
| 591 | + * @host: FSMC NAND controller |
---|
589 | 592 | * @buf: buffer to store date |
---|
590 | 593 | * @len: number of bytes to read |
---|
591 | 594 | */ |
---|
592 | | -static void fsmc_read_buf_dma(struct mtd_info *mtd, uint8_t *buf, int len) |
---|
| 595 | +static void fsmc_read_buf_dma(struct fsmc_nand_data *host, u8 *buf, |
---|
| 596 | + int len) |
---|
593 | 597 | { |
---|
594 | | - struct fsmc_nand_data *host = mtd_to_fsmc(mtd); |
---|
595 | | - |
---|
596 | 598 | dma_xfer(host, buf, len, DMA_FROM_DEVICE); |
---|
597 | 599 | } |
---|
598 | 600 | |
---|
599 | 601 | /* |
---|
600 | 602 | * fsmc_write_buf_dma - write buffer to chip |
---|
601 | | - * @mtd: MTD device structure |
---|
| 603 | + * @host: FSMC NAND controller |
---|
602 | 604 | * @buf: data buffer |
---|
603 | 605 | * @len: number of bytes to write |
---|
604 | 606 | */ |
---|
605 | | -static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf, |
---|
606 | | - int len) |
---|
| 607 | +static void fsmc_write_buf_dma(struct fsmc_nand_data *host, const u8 *buf, |
---|
| 608 | + int len) |
---|
607 | 609 | { |
---|
608 | | - struct fsmc_nand_data *host = mtd_to_fsmc(mtd); |
---|
609 | | - |
---|
610 | 610 | dma_xfer(host, (void *)buf, len, DMA_TO_DEVICE); |
---|
611 | | -} |
---|
612 | | - |
---|
613 | | -/* fsmc_select_chip - assert or deassert nCE */ |
---|
614 | | -static void fsmc_select_chip(struct mtd_info *mtd, int chipnr) |
---|
615 | | -{ |
---|
616 | | - struct fsmc_nand_data *host = mtd_to_fsmc(mtd); |
---|
617 | | - u32 pc; |
---|
618 | | - |
---|
619 | | - /* Support only one CS */ |
---|
620 | | - if (chipnr > 0) |
---|
621 | | - return; |
---|
622 | | - |
---|
623 | | - pc = readl(host->regs_va + FSMC_PC); |
---|
624 | | - if (chipnr < 0) |
---|
625 | | - writel_relaxed(pc & ~FSMC_ENABLE, host->regs_va + FSMC_PC); |
---|
626 | | - else |
---|
627 | | - writel_relaxed(pc | FSMC_ENABLE, host->regs_va + FSMC_PC); |
---|
628 | | - |
---|
629 | | - /* nCE line must be asserted before starting any operation */ |
---|
630 | | - mb(); |
---|
631 | 611 | } |
---|
632 | 612 | |
---|
633 | 613 | /* |
---|
.. | .. |
---|
639 | 619 | static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op, |
---|
640 | 620 | bool check_only) |
---|
641 | 621 | { |
---|
642 | | - struct mtd_info *mtd = nand_to_mtd(chip); |
---|
643 | | - struct fsmc_nand_data *host = mtd_to_fsmc(mtd); |
---|
| 622 | + struct fsmc_nand_data *host = nand_to_fsmc(chip); |
---|
644 | 623 | const struct nand_op_instr *instr = NULL; |
---|
645 | 624 | int ret = 0; |
---|
646 | 625 | unsigned int op_id; |
---|
647 | 626 | int i; |
---|
648 | 627 | |
---|
| 628 | + if (check_only) |
---|
| 629 | + return 0; |
---|
| 630 | + |
---|
649 | 631 | pr_debug("Executing operation [%d instructions]:\n", op->ninstrs); |
---|
| 632 | + |
---|
650 | 633 | for (op_id = 0; op_id < op->ninstrs; op_id++) { |
---|
651 | 634 | instr = &op->instrs[op_id]; |
---|
652 | 635 | |
---|
| 636 | + nand_op_trace(" ", instr); |
---|
| 637 | + |
---|
653 | 638 | switch (instr->type) { |
---|
654 | 639 | case NAND_OP_CMD_INSTR: |
---|
655 | | - pr_debug(" ->CMD [0x%02x]\n", |
---|
656 | | - instr->ctx.cmd.opcode); |
---|
657 | | - |
---|
658 | 640 | writeb_relaxed(instr->ctx.cmd.opcode, host->cmd_va); |
---|
659 | 641 | break; |
---|
660 | 642 | |
---|
661 | 643 | case NAND_OP_ADDR_INSTR: |
---|
662 | | - pr_debug(" ->ADDR [%d cyc]", |
---|
663 | | - instr->ctx.addr.naddrs); |
---|
664 | | - |
---|
665 | 644 | for (i = 0; i < instr->ctx.addr.naddrs; i++) |
---|
666 | 645 | writeb_relaxed(instr->ctx.addr.addrs[i], |
---|
667 | 646 | host->addr_va); |
---|
668 | 647 | break; |
---|
669 | 648 | |
---|
670 | 649 | case NAND_OP_DATA_IN_INSTR: |
---|
671 | | - pr_debug(" ->DATA_IN [%d B%s]\n", instr->ctx.data.len, |
---|
672 | | - instr->ctx.data.force_8bit ? |
---|
673 | | - ", force 8-bit" : ""); |
---|
674 | | - |
---|
675 | 650 | if (host->mode == USE_DMA_ACCESS) |
---|
676 | | - fsmc_read_buf_dma(mtd, instr->ctx.data.buf.in, |
---|
| 651 | + fsmc_read_buf_dma(host, instr->ctx.data.buf.in, |
---|
677 | 652 | instr->ctx.data.len); |
---|
678 | 653 | else |
---|
679 | | - fsmc_read_buf(mtd, instr->ctx.data.buf.in, |
---|
| 654 | + fsmc_read_buf(host, instr->ctx.data.buf.in, |
---|
680 | 655 | instr->ctx.data.len); |
---|
681 | 656 | break; |
---|
682 | 657 | |
---|
683 | 658 | case NAND_OP_DATA_OUT_INSTR: |
---|
684 | | - pr_debug(" ->DATA_OUT [%d B%s]\n", instr->ctx.data.len, |
---|
685 | | - instr->ctx.data.force_8bit ? |
---|
686 | | - ", force 8-bit" : ""); |
---|
687 | | - |
---|
688 | 659 | if (host->mode == USE_DMA_ACCESS) |
---|
689 | | - fsmc_write_buf_dma(mtd, instr->ctx.data.buf.out, |
---|
| 660 | + fsmc_write_buf_dma(host, |
---|
| 661 | + instr->ctx.data.buf.out, |
---|
690 | 662 | instr->ctx.data.len); |
---|
691 | 663 | else |
---|
692 | | - fsmc_write_buf(mtd, instr->ctx.data.buf.out, |
---|
| 664 | + fsmc_write_buf(host, instr->ctx.data.buf.out, |
---|
693 | 665 | instr->ctx.data.len); |
---|
694 | 666 | break; |
---|
695 | 667 | |
---|
696 | 668 | case NAND_OP_WAITRDY_INSTR: |
---|
697 | | - pr_debug(" ->WAITRDY [max %d ms]\n", |
---|
698 | | - instr->ctx.waitrdy.timeout_ms); |
---|
699 | | - |
---|
700 | 669 | ret = nand_soft_waitrdy(chip, |
---|
701 | 670 | instr->ctx.waitrdy.timeout_ms); |
---|
702 | 671 | break; |
---|
.. | .. |
---|
711 | 680 | |
---|
712 | 681 | /* |
---|
713 | 682 | * fsmc_read_page_hwecc |
---|
714 | | - * @mtd: mtd info structure |
---|
715 | 683 | * @chip: nand chip info structure |
---|
716 | 684 | * @buf: buffer to store read data |
---|
717 | 685 | * @oob_required: caller expects OOB data read to chip->oob_poi |
---|
.. | .. |
---|
723 | 691 | * After this read, fsmc hardware generates and reports error data bits(up to a |
---|
724 | 692 | * max of 8 bits) |
---|
725 | 693 | */ |
---|
726 | | -static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, |
---|
727 | | - uint8_t *buf, int oob_required, int page) |
---|
| 694 | +static int fsmc_read_page_hwecc(struct nand_chip *chip, u8 *buf, |
---|
| 695 | + int oob_required, int page) |
---|
728 | 696 | { |
---|
| 697 | + struct mtd_info *mtd = nand_to_mtd(chip); |
---|
729 | 698 | int i, j, s, stat, eccsize = chip->ecc.size; |
---|
730 | 699 | int eccbytes = chip->ecc.bytes; |
---|
731 | 700 | int eccsteps = chip->ecc.steps; |
---|
732 | | - uint8_t *p = buf; |
---|
733 | | - uint8_t *ecc_calc = chip->ecc.calc_buf; |
---|
734 | | - uint8_t *ecc_code = chip->ecc.code_buf; |
---|
735 | | - int off, len, group = 0; |
---|
| 701 | + u8 *p = buf; |
---|
| 702 | + u8 *ecc_calc = chip->ecc.calc_buf; |
---|
| 703 | + u8 *ecc_code = chip->ecc.code_buf; |
---|
| 704 | + int off, len, ret, group = 0; |
---|
736 | 705 | /* |
---|
737 | | - * ecc_oob is intentionally taken as uint16_t. In 16bit devices, we |
---|
| 706 | + * ecc_oob is intentionally taken as u16. In 16bit devices, we |
---|
738 | 707 | * end up reading 14 bytes (7 words) from oob. The local array is |
---|
739 | 708 | * to maintain word alignment |
---|
740 | 709 | */ |
---|
741 | | - uint16_t ecc_oob[7]; |
---|
742 | | - uint8_t *oob = (uint8_t *)&ecc_oob[0]; |
---|
| 710 | + u16 ecc_oob[7]; |
---|
| 711 | + u8 *oob = (u8 *)&ecc_oob[0]; |
---|
743 | 712 | unsigned int max_bitflips = 0; |
---|
744 | 713 | |
---|
745 | 714 | for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) { |
---|
746 | 715 | nand_read_page_op(chip, page, s * eccsize, NULL, 0); |
---|
747 | | - chip->ecc.hwctl(mtd, NAND_ECC_READ); |
---|
748 | | - nand_read_data_op(chip, p, eccsize, false); |
---|
| 716 | + chip->ecc.hwctl(chip, NAND_ECC_READ); |
---|
| 717 | + ret = nand_read_data_op(chip, p, eccsize, false, false); |
---|
| 718 | + if (ret) |
---|
| 719 | + return ret; |
---|
749 | 720 | |
---|
750 | 721 | for (j = 0; j < eccbytes;) { |
---|
751 | 722 | struct mtd_oob_region oobregion; |
---|
752 | | - int ret; |
---|
753 | 723 | |
---|
754 | 724 | ret = mtd_ooblayout_ecc(mtd, group++, &oobregion); |
---|
755 | 725 | if (ret) |
---|
.. | .. |
---|
771 | 741 | } |
---|
772 | 742 | |
---|
773 | 743 | memcpy(&ecc_code[i], oob, chip->ecc.bytes); |
---|
774 | | - chip->ecc.calculate(mtd, p, &ecc_calc[i]); |
---|
| 744 | + chip->ecc.calculate(chip, p, &ecc_calc[i]); |
---|
775 | 745 | |
---|
776 | | - stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); |
---|
| 746 | + stat = chip->ecc.correct(chip, p, &ecc_code[i], &ecc_calc[i]); |
---|
777 | 747 | if (stat < 0) { |
---|
778 | 748 | mtd->ecc_stats.failed++; |
---|
779 | 749 | } else { |
---|
.. | .. |
---|
793 | 763 | * @calc_ecc: ecc calculated from read data |
---|
794 | 764 | * |
---|
795 | 765 | * calc_ecc is a 104 bit information containing maximum of 8 error |
---|
796 | | - * offset informations of 13 bits each in 512 bytes of read data. |
---|
| 766 | + * offset information of 13 bits each in 512 bytes of read data. |
---|
797 | 767 | */ |
---|
798 | | -static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat, |
---|
799 | | - uint8_t *read_ecc, uint8_t *calc_ecc) |
---|
| 768 | +static int fsmc_bch8_correct_data(struct nand_chip *chip, u8 *dat, |
---|
| 769 | + u8 *read_ecc, u8 *calc_ecc) |
---|
800 | 770 | { |
---|
801 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
---|
802 | | - struct fsmc_nand_data *host = mtd_to_fsmc(mtd); |
---|
803 | | - uint32_t err_idx[8]; |
---|
804 | | - uint32_t num_err, i; |
---|
805 | | - uint32_t ecc1, ecc2, ecc3, ecc4; |
---|
| 771 | + struct fsmc_nand_data *host = nand_to_fsmc(chip); |
---|
| 772 | + u32 err_idx[8]; |
---|
| 773 | + u32 num_err, i; |
---|
| 774 | + u32 ecc1, ecc2, ecc3, ecc4; |
---|
806 | 775 | |
---|
807 | 776 | num_err = (readl_relaxed(host->regs_va + STS) >> 10) & 0xF; |
---|
808 | 777 | |
---|
.. | .. |
---|
843 | 812 | * |---idx[7]--|--.....-----|---idx[2]--||---idx[1]--||---idx[0]--| |
---|
844 | 813 | * |
---|
845 | 814 | * calc_ecc is a 104 bit information containing maximum of 8 error |
---|
846 | | - * offset informations of 13 bits each. calc_ecc is copied into a |
---|
847 | | - * uint64_t array and error offset indexes are populated in err_idx |
---|
| 815 | + * offset information of 13 bits each. calc_ecc is copied into a |
---|
| 816 | + * u64 array and error offset indexes are populated in err_idx |
---|
848 | 817 | * array |
---|
849 | 818 | */ |
---|
850 | 819 | ecc1 = readl_relaxed(host->regs_va + ECC1); |
---|
.. | .. |
---|
863 | 832 | |
---|
864 | 833 | i = 0; |
---|
865 | 834 | while (num_err--) { |
---|
866 | | - change_bit(0, (unsigned long *)&err_idx[i]); |
---|
867 | | - change_bit(1, (unsigned long *)&err_idx[i]); |
---|
| 835 | + err_idx[i] ^= 3; |
---|
868 | 836 | |
---|
869 | 837 | if (err_idx[i] < chip->ecc.size * 8) { |
---|
870 | | - change_bit(err_idx[i], (unsigned long *)dat); |
---|
| 838 | + int err = err_idx[i]; |
---|
| 839 | + |
---|
| 840 | + dat[err >> 3] ^= BIT(err & 7); |
---|
871 | 841 | i++; |
---|
872 | 842 | } |
---|
873 | 843 | } |
---|
.. | .. |
---|
903 | 873 | nand->options |= NAND_SKIP_BBTSCAN; |
---|
904 | 874 | |
---|
905 | 875 | host->dev_timings = devm_kzalloc(&pdev->dev, |
---|
906 | | - sizeof(*host->dev_timings), GFP_KERNEL); |
---|
| 876 | + sizeof(*host->dev_timings), |
---|
| 877 | + GFP_KERNEL); |
---|
907 | 878 | if (!host->dev_timings) |
---|
908 | 879 | return -ENOMEM; |
---|
| 880 | + |
---|
909 | 881 | ret = of_property_read_u8_array(np, "timings", (u8 *)host->dev_timings, |
---|
910 | | - sizeof(*host->dev_timings)); |
---|
| 882 | + sizeof(*host->dev_timings)); |
---|
911 | 883 | if (ret) |
---|
912 | 884 | host->dev_timings = NULL; |
---|
913 | 885 | |
---|
.. | .. |
---|
926 | 898 | static int fsmc_nand_attach_chip(struct nand_chip *nand) |
---|
927 | 899 | { |
---|
928 | 900 | struct mtd_info *mtd = nand_to_mtd(nand); |
---|
929 | | - struct fsmc_nand_data *host = mtd_to_fsmc(mtd); |
---|
| 901 | + struct fsmc_nand_data *host = nand_to_fsmc(nand); |
---|
| 902 | + |
---|
| 903 | + if (nand->ecc.engine_type == NAND_ECC_ENGINE_TYPE_INVALID) |
---|
| 904 | + nand->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; |
---|
| 905 | + |
---|
| 906 | + if (!nand->ecc.size) |
---|
| 907 | + nand->ecc.size = 512; |
---|
| 908 | + |
---|
| 909 | + if (AMBA_REV_BITS(host->pid) >= 8) { |
---|
| 910 | + nand->ecc.read_page = fsmc_read_page_hwecc; |
---|
| 911 | + nand->ecc.calculate = fsmc_read_hwecc_ecc4; |
---|
| 912 | + nand->ecc.correct = fsmc_bch8_correct_data; |
---|
| 913 | + nand->ecc.bytes = 13; |
---|
| 914 | + nand->ecc.strength = 8; |
---|
| 915 | + } |
---|
930 | 916 | |
---|
931 | 917 | if (AMBA_REV_BITS(host->pid) >= 8) { |
---|
932 | 918 | switch (mtd->oobsize) { |
---|
.. | .. |
---|
948 | 934 | return 0; |
---|
949 | 935 | } |
---|
950 | 936 | |
---|
951 | | - switch (nand->ecc.mode) { |
---|
952 | | - case NAND_ECC_HW: |
---|
| 937 | + switch (nand->ecc.engine_type) { |
---|
| 938 | + case NAND_ECC_ENGINE_TYPE_ON_HOST: |
---|
953 | 939 | dev_info(host->dev, "Using 1-bit HW ECC scheme\n"); |
---|
954 | 940 | nand->ecc.calculate = fsmc_read_hwecc_ecc1; |
---|
955 | 941 | nand->ecc.correct = nand_correct_data; |
---|
| 942 | + nand->ecc.hwctl = fsmc_enable_hwecc; |
---|
956 | 943 | nand->ecc.bytes = 3; |
---|
957 | 944 | nand->ecc.strength = 1; |
---|
| 945 | + nand->ecc.options |= NAND_ECC_SOFT_HAMMING_SM_ORDER; |
---|
958 | 946 | break; |
---|
959 | 947 | |
---|
960 | | - case NAND_ECC_SOFT: |
---|
961 | | - if (nand->ecc.algo == NAND_ECC_BCH) { |
---|
| 948 | + case NAND_ECC_ENGINE_TYPE_SOFT: |
---|
| 949 | + if (nand->ecc.algo == NAND_ECC_ALGO_BCH) { |
---|
962 | 950 | dev_info(host->dev, |
---|
963 | 951 | "Using 4-bit SW BCH ECC scheme\n"); |
---|
964 | 952 | break; |
---|
965 | 953 | } |
---|
966 | 954 | |
---|
967 | | - case NAND_ECC_ON_DIE: |
---|
| 955 | + case NAND_ECC_ENGINE_TYPE_ON_DIE: |
---|
968 | 956 | break; |
---|
969 | 957 | |
---|
970 | 958 | default: |
---|
.. | .. |
---|
976 | 964 | * Don't set layout for BCH4 SW ECC. This will be |
---|
977 | 965 | * generated later in nand_bch_init() later. |
---|
978 | 966 | */ |
---|
979 | | - if (nand->ecc.mode == NAND_ECC_HW) { |
---|
| 967 | + if (nand->ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST) { |
---|
980 | 968 | switch (mtd->oobsize) { |
---|
981 | 969 | case 16: |
---|
982 | 970 | case 64: |
---|
.. | .. |
---|
997 | 985 | |
---|
998 | 986 | static const struct nand_controller_ops fsmc_nand_controller_ops = { |
---|
999 | 987 | .attach_chip = fsmc_nand_attach_chip, |
---|
| 988 | + .exec_op = fsmc_exec_op, |
---|
| 989 | + .setup_interface = fsmc_setup_interface, |
---|
1000 | 990 | }; |
---|
| 991 | + |
---|
| 992 | +/** |
---|
| 993 | + * fsmc_nand_disable() - Disables the NAND bank |
---|
| 994 | + * @host: The instance to disable |
---|
| 995 | + */ |
---|
| 996 | +static void fsmc_nand_disable(struct fsmc_nand_data *host) |
---|
| 997 | +{ |
---|
| 998 | + u32 val; |
---|
| 999 | + |
---|
| 1000 | + val = readl(host->regs_va + FSMC_PC); |
---|
| 1001 | + val &= ~FSMC_ENABLE; |
---|
| 1002 | + writel(val, host->regs_va + FSMC_PC); |
---|
| 1003 | +} |
---|
1001 | 1004 | |
---|
1002 | 1005 | /* |
---|
1003 | 1006 | * fsmc_nand_probe - Probe function |
---|
.. | .. |
---|
1066 | 1069 | * AMBA PrimeCell bus. However it is not a PrimeCell. |
---|
1067 | 1070 | */ |
---|
1068 | 1071 | for (pid = 0, i = 0; i < 4; i++) |
---|
1069 | | - pid |= (readl(base + resource_size(res) - 0x20 + 4 * i) & 255) << (i * 8); |
---|
| 1072 | + pid |= (readl(base + resource_size(res) - 0x20 + 4 * i) & |
---|
| 1073 | + 255) << (i * 8); |
---|
| 1074 | + |
---|
1070 | 1075 | host->pid = pid; |
---|
1071 | | - dev_info(&pdev->dev, "FSMC device partno %03x, manufacturer %02x, " |
---|
1072 | | - "revision %02x, config %02x\n", |
---|
| 1076 | + |
---|
| 1077 | + dev_info(&pdev->dev, |
---|
| 1078 | + "FSMC device partno %03x, manufacturer %02x, revision %02x, config %02x\n", |
---|
1073 | 1079 | AMBA_PART_BITS(pid), AMBA_MANF_BITS(pid), |
---|
1074 | 1080 | AMBA_REV_BITS(pid), AMBA_CONFIG_BITS(pid)); |
---|
1075 | 1081 | |
---|
.. | .. |
---|
1080 | 1086 | |
---|
1081 | 1087 | /* Link all private pointers */ |
---|
1082 | 1088 | mtd = nand_to_mtd(&host->nand); |
---|
1083 | | - nand_set_controller_data(nand, host); |
---|
1084 | 1089 | nand_set_flash_node(nand, pdev->dev.of_node); |
---|
1085 | 1090 | |
---|
1086 | 1091 | mtd->dev.parent = &pdev->dev; |
---|
1087 | | - nand->exec_op = fsmc_exec_op; |
---|
1088 | | - nand->select_chip = fsmc_select_chip; |
---|
1089 | | - nand->chip_delay = 30; |
---|
1090 | 1092 | |
---|
1091 | | - /* |
---|
1092 | | - * Setup default ECC mode. nand_dt_init() called from nand_scan_ident() |
---|
1093 | | - * can overwrite this value if the DT provides a different value. |
---|
1094 | | - */ |
---|
1095 | | - nand->ecc.mode = NAND_ECC_HW; |
---|
1096 | | - nand->ecc.hwctl = fsmc_enable_hwecc; |
---|
1097 | | - nand->ecc.size = 512; |
---|
1098 | 1093 | nand->badblockbits = 7; |
---|
1099 | 1094 | |
---|
1100 | 1095 | if (host->mode == USE_DMA_ACCESS) { |
---|
.. | .. |
---|
1114 | 1109 | } |
---|
1115 | 1110 | } |
---|
1116 | 1111 | |
---|
1117 | | - if (host->dev_timings) |
---|
| 1112 | + if (host->dev_timings) { |
---|
1118 | 1113 | fsmc_nand_setup(host, host->dev_timings); |
---|
1119 | | - else |
---|
1120 | | - nand->setup_data_interface = fsmc_setup_data_interface; |
---|
1121 | | - |
---|
1122 | | - if (AMBA_REV_BITS(host->pid) >= 8) { |
---|
1123 | | - nand->ecc.read_page = fsmc_read_page_hwecc; |
---|
1124 | | - nand->ecc.calculate = fsmc_read_hwecc_ecc4; |
---|
1125 | | - nand->ecc.correct = fsmc_bch8_correct_data; |
---|
1126 | | - nand->ecc.bytes = 13; |
---|
1127 | | - nand->ecc.strength = 8; |
---|
| 1114 | + nand->options |= NAND_KEEP_TIMINGS; |
---|
1128 | 1115 | } |
---|
| 1116 | + |
---|
| 1117 | + nand_controller_init(&host->base); |
---|
| 1118 | + host->base.ops = &fsmc_nand_controller_ops; |
---|
| 1119 | + nand->controller = &host->base; |
---|
1129 | 1120 | |
---|
1130 | 1121 | /* |
---|
1131 | 1122 | * Scan to find existence of the device |
---|
1132 | 1123 | */ |
---|
1133 | | - nand->dummy_controller.ops = &fsmc_nand_controller_ops; |
---|
1134 | 1124 | ret = nand_scan(nand, 1); |
---|
1135 | 1125 | if (ret) |
---|
1136 | 1126 | goto release_dma_write_chan; |
---|
.. | .. |
---|
1154 | 1144 | if (host->mode == USE_DMA_ACCESS) |
---|
1155 | 1145 | dma_release_channel(host->read_dma_chan); |
---|
1156 | 1146 | disable_clk: |
---|
| 1147 | + fsmc_nand_disable(host); |
---|
1157 | 1148 | clk_disable_unprepare(host->clk); |
---|
1158 | 1149 | |
---|
1159 | 1150 | return ret; |
---|
.. | .. |
---|
1167 | 1158 | struct fsmc_nand_data *host = platform_get_drvdata(pdev); |
---|
1168 | 1159 | |
---|
1169 | 1160 | if (host) { |
---|
1170 | | - nand_release(&host->nand); |
---|
| 1161 | + struct nand_chip *chip = &host->nand; |
---|
| 1162 | + int ret; |
---|
| 1163 | + |
---|
| 1164 | + ret = mtd_device_unregister(nand_to_mtd(chip)); |
---|
| 1165 | + WARN_ON(ret); |
---|
| 1166 | + nand_cleanup(chip); |
---|
| 1167 | + fsmc_nand_disable(host); |
---|
1171 | 1168 | |
---|
1172 | 1169 | if (host->mode == USE_DMA_ACCESS) { |
---|
1173 | 1170 | dma_release_channel(host->write_dma_chan); |
---|
.. | .. |
---|
1183 | 1180 | static int fsmc_nand_suspend(struct device *dev) |
---|
1184 | 1181 | { |
---|
1185 | 1182 | struct fsmc_nand_data *host = dev_get_drvdata(dev); |
---|
| 1183 | + |
---|
1186 | 1184 | if (host) |
---|
1187 | 1185 | clk_disable_unprepare(host->clk); |
---|
| 1186 | + |
---|
1188 | 1187 | return 0; |
---|
1189 | 1188 | } |
---|
1190 | 1189 | |
---|
1191 | 1190 | static int fsmc_nand_resume(struct device *dev) |
---|
1192 | 1191 | { |
---|
1193 | 1192 | struct fsmc_nand_data *host = dev_get_drvdata(dev); |
---|
| 1193 | + int ret; |
---|
| 1194 | + |
---|
1194 | 1195 | if (host) { |
---|
1195 | | - clk_prepare_enable(host->clk); |
---|
| 1196 | + ret = clk_prepare_enable(host->clk); |
---|
| 1197 | + if (ret) { |
---|
| 1198 | + dev_err(dev, "failed to enable clk\n"); |
---|
| 1199 | + return ret; |
---|
| 1200 | + } |
---|
1196 | 1201 | if (host->dev_timings) |
---|
1197 | 1202 | fsmc_nand_setup(host, host->dev_timings); |
---|
| 1203 | + nand_reset(&host->nand, 0); |
---|
1198 | 1204 | } |
---|
| 1205 | + |
---|
1199 | 1206 | return 0; |
---|
1200 | 1207 | } |
---|
1201 | 1208 | #endif |
---|
.. | .. |
---|
1220 | 1227 | |
---|
1221 | 1228 | module_platform_driver_probe(fsmc_nand_driver, fsmc_nand_probe); |
---|
1222 | 1229 | |
---|
1223 | | -MODULE_LICENSE("GPL"); |
---|
| 1230 | +MODULE_LICENSE("GPL v2"); |
---|
1224 | 1231 | MODULE_AUTHOR("Vipin Kumar <vipin.kumar@st.com>, Ashish Priyadarshi"); |
---|
1225 | 1232 | MODULE_DESCRIPTION("NAND driver for SPEAr Platforms"); |
---|