.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright 2004-2008 Freescale Semiconductor, Inc. |
---|
3 | 4 | * Copyright 2009 Semihalf. |
---|
.. | .. |
---|
8 | 9 | * Based on original driver from Freescale Semiconductor |
---|
9 | 10 | * written by John Rigby <jrigby@freescale.com> on basis of mxc_nand.c. |
---|
10 | 11 | * Reworked and extended by Piotr Ziecik <kosmo@semihalf.com>. |
---|
11 | | - * |
---|
12 | | - * This program is free software; you can redistribute it and/or |
---|
13 | | - * modify it under the terms of the GNU General Public License |
---|
14 | | - * as published by the Free Software Foundation; either version 2 |
---|
15 | | - * of the License, or (at your option) any later version. |
---|
16 | | - * This program is distributed in the hope that it will be useful, |
---|
17 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
18 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
19 | | - * GNU General Public License for more details. |
---|
20 | | - * |
---|
21 | | - * You should have received a copy of the GNU General Public License |
---|
22 | | - * along with this program; if not, write to the Free Software |
---|
23 | | - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
---|
24 | | - * MA 02110-1301, USA. |
---|
25 | 12 | */ |
---|
26 | 13 | |
---|
27 | 14 | #include <linux/module.h> |
---|
.. | .. |
---|
117 | 104 | #define NFC_TIMEOUT (HZ / 10) /* 1/10 s */ |
---|
118 | 105 | |
---|
119 | 106 | struct mpc5121_nfc_prv { |
---|
| 107 | + struct nand_controller controller; |
---|
120 | 108 | struct nand_chip chip; |
---|
121 | 109 | int irq; |
---|
122 | 110 | void __iomem *regs; |
---|
.. | .. |
---|
263 | 251 | } |
---|
264 | 252 | |
---|
265 | 253 | /* Control chip select signals */ |
---|
266 | | -static void mpc5121_nfc_select_chip(struct mtd_info *mtd, int chip) |
---|
| 254 | +static void mpc5121_nfc_select_chip(struct nand_chip *nand, int chip) |
---|
267 | 255 | { |
---|
| 256 | + struct mtd_info *mtd = nand_to_mtd(nand); |
---|
| 257 | + |
---|
268 | 258 | if (chip < 0) { |
---|
269 | 259 | nfc_clear(mtd, NFC_CONFIG1, NFC_CE); |
---|
270 | 260 | return; |
---|
.. | .. |
---|
299 | 289 | } |
---|
300 | 290 | |
---|
301 | 291 | /* Control chips select signal on ADS5121 board */ |
---|
302 | | -static void ads5121_select_chip(struct mtd_info *mtd, int chip) |
---|
| 292 | +static void ads5121_select_chip(struct nand_chip *nand, int chip) |
---|
303 | 293 | { |
---|
304 | | - struct nand_chip *nand = mtd_to_nand(mtd); |
---|
305 | 294 | struct mpc5121_nfc_prv *prv = nand_get_controller_data(nand); |
---|
306 | 295 | u8 v; |
---|
307 | 296 | |
---|
.. | .. |
---|
309 | 298 | v |= 0x0F; |
---|
310 | 299 | |
---|
311 | 300 | if (chip >= 0) { |
---|
312 | | - mpc5121_nfc_select_chip(mtd, 0); |
---|
| 301 | + mpc5121_nfc_select_chip(nand, 0); |
---|
313 | 302 | v &= ~(1 << chip); |
---|
314 | 303 | } else |
---|
315 | | - mpc5121_nfc_select_chip(mtd, -1); |
---|
| 304 | + mpc5121_nfc_select_chip(nand, -1); |
---|
316 | 305 | |
---|
317 | 306 | out_8(prv->csreg, v); |
---|
318 | 307 | } |
---|
319 | 308 | |
---|
320 | 309 | /* Read NAND Ready/Busy signal */ |
---|
321 | | -static int mpc5121_nfc_dev_ready(struct mtd_info *mtd) |
---|
| 310 | +static int mpc5121_nfc_dev_ready(struct nand_chip *nand) |
---|
322 | 311 | { |
---|
323 | 312 | /* |
---|
324 | 313 | * NFC handles ready/busy signal internally. Therefore, this function |
---|
.. | .. |
---|
328 | 317 | } |
---|
329 | 318 | |
---|
330 | 319 | /* Write command to NAND flash */ |
---|
331 | | -static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command, |
---|
332 | | - int column, int page) |
---|
| 320 | +static void mpc5121_nfc_command(struct nand_chip *chip, unsigned command, |
---|
| 321 | + int column, int page) |
---|
333 | 322 | { |
---|
334 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
---|
| 323 | + struct mtd_info *mtd = nand_to_mtd(chip); |
---|
335 | 324 | struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip); |
---|
336 | 325 | |
---|
337 | 326 | prv->column = (column >= 0) ? column : 0; |
---|
.. | .. |
---|
362 | 351 | break; |
---|
363 | 352 | |
---|
364 | 353 | case NAND_CMD_SEQIN: |
---|
365 | | - mpc5121_nfc_command(mtd, NAND_CMD_READ0, column, page); |
---|
| 354 | + mpc5121_nfc_command(chip, NAND_CMD_READ0, column, page); |
---|
366 | 355 | column = 0; |
---|
367 | 356 | break; |
---|
368 | 357 | |
---|
.. | .. |
---|
449 | 438 | buffer += blksize; |
---|
450 | 439 | offset += blksize; |
---|
451 | 440 | size -= blksize; |
---|
452 | | - }; |
---|
| 441 | + } |
---|
453 | 442 | } |
---|
454 | 443 | |
---|
455 | 444 | /* Copy data from/to NFC main and spare buffers */ |
---|
.. | .. |
---|
493 | 482 | } |
---|
494 | 483 | |
---|
495 | 484 | /* Read data from NFC buffers */ |
---|
496 | | -static void mpc5121_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len) |
---|
| 485 | +static void mpc5121_nfc_read_buf(struct nand_chip *chip, u_char *buf, int len) |
---|
497 | 486 | { |
---|
498 | | - mpc5121_nfc_buf_copy(mtd, buf, len, 0); |
---|
| 487 | + mpc5121_nfc_buf_copy(nand_to_mtd(chip), buf, len, 0); |
---|
499 | 488 | } |
---|
500 | 489 | |
---|
501 | 490 | /* Write data to NFC buffers */ |
---|
502 | | -static void mpc5121_nfc_write_buf(struct mtd_info *mtd, |
---|
503 | | - const u_char *buf, int len) |
---|
| 491 | +static void mpc5121_nfc_write_buf(struct nand_chip *chip, const u_char *buf, |
---|
| 492 | + int len) |
---|
504 | 493 | { |
---|
505 | | - mpc5121_nfc_buf_copy(mtd, (u_char *)buf, len, 1); |
---|
| 494 | + mpc5121_nfc_buf_copy(nand_to_mtd(chip), (u_char *)buf, len, 1); |
---|
506 | 495 | } |
---|
507 | 496 | |
---|
508 | 497 | /* Read byte from NFC buffers */ |
---|
509 | | -static u8 mpc5121_nfc_read_byte(struct mtd_info *mtd) |
---|
| 498 | +static u8 mpc5121_nfc_read_byte(struct nand_chip *chip) |
---|
510 | 499 | { |
---|
511 | 500 | u8 tmp; |
---|
512 | 501 | |
---|
513 | | - mpc5121_nfc_read_buf(mtd, &tmp, sizeof(tmp)); |
---|
514 | | - |
---|
515 | | - return tmp; |
---|
516 | | -} |
---|
517 | | - |
---|
518 | | -/* Read word from NFC buffers */ |
---|
519 | | -static u16 mpc5121_nfc_read_word(struct mtd_info *mtd) |
---|
520 | | -{ |
---|
521 | | - u16 tmp; |
---|
522 | | - |
---|
523 | | - mpc5121_nfc_read_buf(mtd, (u_char *)&tmp, sizeof(tmp)); |
---|
| 502 | + mpc5121_nfc_read_buf(chip, &tmp, sizeof(tmp)); |
---|
524 | 503 | |
---|
525 | 504 | return tmp; |
---|
526 | 505 | } |
---|
.. | .. |
---|
623 | 602 | iounmap(prv->csreg); |
---|
624 | 603 | } |
---|
625 | 604 | |
---|
| 605 | +static int mpc5121_nfc_attach_chip(struct nand_chip *chip) |
---|
| 606 | +{ |
---|
| 607 | + if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT && |
---|
| 608 | + chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) |
---|
| 609 | + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; |
---|
| 610 | + |
---|
| 611 | + return 0; |
---|
| 612 | +} |
---|
| 613 | + |
---|
| 614 | +static const struct nand_controller_ops mpc5121_nfc_ops = { |
---|
| 615 | + .attach_chip = mpc5121_nfc_attach_chip, |
---|
| 616 | +}; |
---|
| 617 | + |
---|
626 | 618 | static int mpc5121_nfc_probe(struct platform_device *op) |
---|
627 | 619 | { |
---|
628 | 620 | struct device_node *dn = op->dev.of_node; |
---|
.. | .. |
---|
654 | 646 | |
---|
655 | 647 | chip = &prv->chip; |
---|
656 | 648 | mtd = nand_to_mtd(chip); |
---|
| 649 | + |
---|
| 650 | + nand_controller_init(&prv->controller); |
---|
| 651 | + prv->controller.ops = &mpc5121_nfc_ops; |
---|
| 652 | + chip->controller = &prv->controller; |
---|
657 | 653 | |
---|
658 | 654 | mtd->dev.parent = dev; |
---|
659 | 655 | nand_set_controller_data(chip, prv); |
---|
.. | .. |
---|
700 | 696 | } |
---|
701 | 697 | |
---|
702 | 698 | mtd->name = "MPC5121 NAND"; |
---|
703 | | - chip->dev_ready = mpc5121_nfc_dev_ready; |
---|
704 | | - chip->cmdfunc = mpc5121_nfc_command; |
---|
705 | | - chip->read_byte = mpc5121_nfc_read_byte; |
---|
706 | | - chip->read_word = mpc5121_nfc_read_word; |
---|
707 | | - chip->read_buf = mpc5121_nfc_read_buf; |
---|
708 | | - chip->write_buf = mpc5121_nfc_write_buf; |
---|
709 | | - chip->select_chip = mpc5121_nfc_select_chip; |
---|
710 | | - chip->set_features = nand_get_set_features_notsupp; |
---|
711 | | - chip->get_features = nand_get_set_features_notsupp; |
---|
| 699 | + chip->legacy.dev_ready = mpc5121_nfc_dev_ready; |
---|
| 700 | + chip->legacy.cmdfunc = mpc5121_nfc_command; |
---|
| 701 | + chip->legacy.read_byte = mpc5121_nfc_read_byte; |
---|
| 702 | + chip->legacy.read_buf = mpc5121_nfc_read_buf; |
---|
| 703 | + chip->legacy.write_buf = mpc5121_nfc_write_buf; |
---|
| 704 | + chip->legacy.select_chip = mpc5121_nfc_select_chip; |
---|
| 705 | + chip->legacy.set_features = nand_get_set_features_notsupp; |
---|
| 706 | + chip->legacy.get_features = nand_get_set_features_notsupp; |
---|
712 | 707 | chip->bbt_options = NAND_BBT_USE_FLASH; |
---|
713 | | - chip->ecc.mode = NAND_ECC_SOFT; |
---|
714 | | - chip->ecc.algo = NAND_ECC_HAMMING; |
---|
715 | 708 | |
---|
716 | 709 | /* Support external chip-select logic on ADS5121 board */ |
---|
717 | 710 | if (of_machine_is_compatible("fsl,mpc5121ads")) { |
---|
.. | .. |
---|
721 | 714 | return retval; |
---|
722 | 715 | } |
---|
723 | 716 | |
---|
724 | | - chip->select_chip = ads5121_select_chip; |
---|
| 717 | + chip->legacy.select_chip = ads5121_select_chip; |
---|
725 | 718 | } |
---|
726 | 719 | |
---|
727 | 720 | /* Enable NFC clock */ |
---|
.. | .. |
---|
777 | 770 | goto error; |
---|
778 | 771 | } |
---|
779 | 772 | |
---|
| 773 | + /* |
---|
| 774 | + * This driver assumes that the default ECC engine should be TYPE_SOFT. |
---|
| 775 | + * Set ->engine_type before registering the NAND devices in order to |
---|
| 776 | + * provide a driver specific default value. |
---|
| 777 | + */ |
---|
| 778 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; |
---|
| 779 | + |
---|
780 | 780 | /* Detect NAND chips */ |
---|
781 | 781 | retval = nand_scan(chip, be32_to_cpup(chips_no)); |
---|
782 | 782 | if (retval) { |
---|
.. | .. |
---|
827 | 827 | { |
---|
828 | 828 | struct device *dev = &op->dev; |
---|
829 | 829 | struct mtd_info *mtd = dev_get_drvdata(dev); |
---|
| 830 | + int ret; |
---|
830 | 831 | |
---|
831 | | - nand_release(mtd_to_nand(mtd)); |
---|
| 832 | + ret = mtd_device_unregister(mtd); |
---|
| 833 | + WARN_ON(ret); |
---|
| 834 | + nand_cleanup(mtd_to_nand(mtd)); |
---|
832 | 835 | mpc5121_nfc_free(dev, mtd); |
---|
833 | 836 | |
---|
834 | 837 | return 0; |
---|