All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
@ 2017-05-24  7:06 Peter Pan
  2017-05-24  7:06 ` [PATCH v6 01/15] mtd: nand: Rename nand.h into rawnand.h Peter Pan
                   ` (15 more replies)
  0 siblings, 16 replies; 65+ messages in thread
From: Peter Pan @ 2017-05-24  7:06 UTC (permalink / raw)
  To: boris.brezillon, richard, computersforpeace, arnaud.mouiche,
	thomas.petazzoni, marex, cyrille.pitchen, linux-mtd
  Cc: peterpandong, peterpansjtu, linshunquan1

First of all, thank Boris and Marek for your priceless comments
on v5 and thank everyone reviewed and tested on my previous series.
I can never be here without your help. This series comes to v6
and it becomes much better with your help.

SPI NAND is a new NAND family device with SPI protocol as
its interface. And its command set is totally different
with parallel NAND.

Our first attempt to SPI NAND was more than 2 years ago[1].
At that time, I didn't make BBT shareable and there were
too many duplicate code with parallel NAND, so that serie
stoped. But the discussion never stops. Now Boris has a plan
to make a generic NAND framework which can be shared with
both parallel and SPI NAND. Now the first step of the
new generic NAND framework is finished. And it is waiting
for a user. After discussion with Boris. We both think it's
time to rebuild SPI NAND framework based on the new NAND
framework and send out for reviewing.

This series includes two part. The first part (patch 1 to 9)
is a new generic NAND framework from Boris Brezillon, which
is from Biris's nand/generic branch[2]. The second part
(patch 10 to 15) introductes a SPI NAND framework based on
the new generic NAND framework.

This series only supports basic SPI NAND features and uses
generic spi controller for data transfer. ECC support is removed
since it's not in a good structure and more important, it should
be shared between different NAND devices, which means it should
be in new NAND core. Support different types of ECC and advanced
SPI NAND features is the next step.

This series is based on nand/next branch and is tested on
Xilinx Zedboard with Micron MT29F2G01ABAGDSF SPI NAND chip.


v6 changes:
- includes generic NAND framework patches in series
- rebase on nand/next (commit 6076fd1e9d879521f7082a5e22185b71e480b777)
- remove on-die ECC support
- remove devm_free() since everything allocated by devm_kmalloc() will be
  automatically freed when device is released
- add comment header for structs in spinand.h
- remove spinand_register()/unregister(), call spinand_detect() in
  spinand_init() and only expose spinand_init()/cleanup()
- add nand_release_bbt() in bbt.c and use it in nand_cleanup() and
  spinand_cleanup()
- use BIT(n) instead (1 << n) in macro of spinand.h
- rename spinand_alloc() to devm_spinand_alloc()
- name lables in better way
- fix some typos
- add empty lines between code blocks

v5 changes:
- rebase patch on nand/next with Boris's generic NAND framework patches[3]
- replace pr_xxx() with dev_xxx()
- replace kzalloc()i/kfree() with devm_kzalloc()/devm_kfree()
- rename spinand_op_init() to spinand_init_op() for consistency
- remove command opcode in function comments
- use BIT(n) instead (1 << n) in macro
- remove manufactures.c and put spinand_manufacturers table in core.c
- change spinand_write_reg() u8 *buf argument to u8 value,
  since the length is always 1
- remove spinand_manufacture->detect() check, since it is always != NULL
- alloc spinand_ecc_engine struct in vendor.c when using on-die ECC
  (for hardware ECC, it should be in controllers/*.c)
- add comment header for struct spinand_op
- fix timeout bug in spinand_wait(), thanks for Arnaud's debug
- make spinand_manufacturers const
- add ecc_engine_ops pointer in struct micron_spinand_info
- make controller->cap assignment right with SPI_TX/RX_QUAD/DUAL flag

v4 changes:
- initialize struct mtd_oob_ops to 0 in bbt.c
- rename new added helper in nand.h to nand_check_xxxx()
- add struct mtd_oob_ops consistency check in nand_check_oob_ops()
- add dataleft in struct nand_page_iter instead of offs
- remove spinand_manufacturers->ops->detect() check since it is mandatory
- remove spinand_set_manufacturer_ops() and do the job in
  spinand_manufacturer_detect()
- move .priv out of struct spinand_controller
- add spinand_alloc/free/register/unregister() and make
  spinand_detect/init() static
- make BBT be configured by device tree
- chip->id.data stores raw ID directly
- refine device info print message after detect success
- add struct mtd_layout_ops pointer in struct micron_spinand_info
- remove micron_spinand_init() and do its job in micron_spinand_detect()
- fix BBT block cannot be erased bug

v3 changes:
- rebase patch on 4.11-rc1[2]
- change read ID method. read 4 bytes ID out then let ->detect() of each
  manufacutre driver to decode ID and detect the device.
- make SPI NAND id table private to each manufacutre driver
- fix coding style to make checkpatch.pl happy
- update the MAINTAINERS file for spi nand code
- add nand_size() helper in nand.h
- use nand_for_each_page() helper in spinand_do_read/write_ops()
- create helper to check boundaries in generic NAND code and use it
  in SPI NAND core
- rename spinand_base.c to core.c
- manufactures' drivers expose spinand_manufacturer struct instead of
  spinand_manufacturer_ops struct to keep Manufacture ID macro in
  manufactures' drivers and rename spinand_ids.c to manufacture.c
- rename spinand_micron.c to micron.c
- rename chips/ directory to controllers/
- rename generic_spi.c to generic-spi.c
- replace ->build_column_addr() and ->get_dummy() hooks with ->prepare_op() in
  spinand_manufacturer_ops struct
- rename __spinand_erase() to spinand_erase()
- rename spinand_erase() to spinand_erase_skip_bbt()
- rename spinand_scan_ident() to spinand_detect()
- rename spinand_scan_tail() to spinand_init()
- move non detect related code from spinand_detect() to spinand_init()
- remove spinand_fill_nandd, assign nand->ops in spinand_detect()
- merge v2 patch 3(bad block support) and patch 4(BBT support)
- drop getchip parameter, remove spinand_get/remove_device(), take the lock
  by caller directly
- fix function comment headers
- use nand_bbt_is_initialized() helper
- replace spinand_ecc_engine and spinand_controller object in spinand_device
  struct with pointer
- replace struct spinand_manufacturer_ops pointer in spinand_device struct
  with spinand_manufacturer struct

v2 changes:
- replace "spi_nand" with "spinand".
- rename spi nand related structs for better understanding.
- introduce spi nand controller, manufacturer and ecc_engine struct.
- add spi nand manufacturer initialization function refer to Boris's
  manuf-init branch.
- remove NAND_SKIP_BBTSCAN from series. Add it later when enabling HW ECC.
- reorganize series according to Boris's suggestion.


[1]http://lists.infradead.org/pipermail/linux-mtd/2015-January/057223.html
[2]https://github.com/bbrezillon/linux-0day/tree/nand/generic
[3]https://github.com/peterpansjtu/linux/tree/nand/spinand


Boris Brezillon (8):
  mtd: nand: Rename nand.h into rawnand.h
  mtd: nand: move raw NAND related code to the raw/ subdir
  mtd: nand: add a nand.h file to expose basic NAND stuff
  mtd: nand: raw: prefix conflicting names with nandcchip instead of
    nand
  mtd: nand: raw: create struct rawnand_device
  mtd: nand: raw: make BBT code more generic
  mtd: nand: move BBT code to drivers/mtd/nand/
  mtd: nand: Add the page iterator concept

Peter Pan (7):
  mtd: nand: make sure mtd_oob_ops consistent in bbt
  nand: spi: add basic blocks for infrastructure
  nand: spi: add basic operations support
  nand: spi: Add bad block support
  nand: spi: add Micron spi nand support
  nand: spi: Add generic SPI controller support
  MAINTAINERS: Add SPI NAND entry

 Documentation/DocBook/mtdnand.tmpl                 |   12 +-
 MAINTAINERS                                        |   29 +-
 arch/arm/mach-davinci/board-da850-evm.c            |    2 +-
 arch/arm/mach-davinci/board-dm355-evm.c            |    2 +-
 arch/arm/mach-davinci/board-dm355-leopard.c        |    2 +-
 arch/arm/mach-davinci/board-dm365-evm.c            |    2 +-
 arch/arm/mach-davinci/board-dm644x-evm.c           |    2 +-
 arch/arm/mach-davinci/board-dm646x-evm.c           |    2 +-
 arch/arm/mach-davinci/board-sffsdr.c               |    2 +-
 arch/arm/mach-dove/dove-db-setup.c                 |    2 +-
 arch/arm/mach-ep93xx/snappercl15.c                 |    6 +-
 arch/arm/mach-ep93xx/ts72xx.c                      |    6 +-
 arch/arm/mach-imx/mach-qong.c                      |    4 +-
 arch/arm/mach-ixp4xx/ixdp425-setup.c               |    4 +-
 arch/arm/mach-mmp/aspenite.c                       |    2 +-
 arch/arm/mach-omap1/board-fsample.c                |    2 +-
 arch/arm/mach-omap1/board-h2.c                     |    2 +-
 arch/arm/mach-omap1/board-h3.c                     |    2 +-
 arch/arm/mach-omap1/board-nand.c                   |    4 +-
 arch/arm/mach-omap1/board-perseus2.c               |    2 +-
 arch/arm/mach-orion5x/db88f5281-setup.c            |    2 +-
 arch/arm/mach-orion5x/kurobox_pro-setup.c          |    2 +-
 arch/arm/mach-orion5x/ts209-setup.c                |    2 +-
 arch/arm/mach-orion5x/ts78xx-setup.c               |    8 +-
 arch/arm/mach-pxa/balloon3.c                       |    4 +-
 arch/arm/mach-pxa/em-x270.c                        |    4 +-
 arch/arm/mach-pxa/eseries.c                        |    2 +-
 arch/arm/mach-pxa/palmtx.c                         |    4 +-
 arch/arm/mach-pxa/tosa.c                           |    2 +-
 arch/arm/mach-s3c24xx/common-smdk.c                |    2 +-
 arch/arm/mach-s3c24xx/mach-anubis.c                |    2 +-
 arch/arm/mach-s3c24xx/mach-at2440evb.c             |    2 +-
 arch/arm/mach-s3c24xx/mach-bast.c                  |    2 +-
 arch/arm/mach-s3c24xx/mach-gta02.c                 |    2 +-
 arch/arm/mach-s3c24xx/mach-jive.c                  |    2 +-
 arch/arm/mach-s3c24xx/mach-mini2440.c              |    2 +-
 arch/arm/mach-s3c24xx/mach-osiris.c                |    2 +-
 arch/arm/mach-s3c24xx/mach-qt2410.c                |    2 +-
 arch/arm/mach-s3c24xx/mach-rx3715.c                |    2 +-
 arch/arm/mach-s3c24xx/mach-vstms.c                 |    2 +-
 arch/blackfin/mach-bf537/boards/dnp5370.c          |    2 +-
 arch/blackfin/mach-bf537/boards/stamp.c            |    4 +-
 arch/blackfin/mach-bf561/boards/acvilon.c          |    4 +-
 arch/cris/arch-v32/drivers/mach-a3/nandflash.c     |    6 +-
 arch/cris/arch-v32/drivers/mach-fs/nandflash.c     |    6 +-
 arch/mips/alchemy/devboards/db1200.c               |    4 +-
 arch/mips/alchemy/devboards/db1300.c               |    4 +-
 arch/mips/alchemy/devboards/db1550.c               |    4 +-
 arch/mips/include/asm/mach-jz4740/jz4740_nand.h    |    2 +-
 arch/mips/jz4740/board-qi_lb60.c                   |    2 +-
 arch/mips/netlogic/xlr/platform-flash.c            |    2 +-
 arch/mips/pnx833x/common/platform.c                |    4 +-
 arch/mips/rb532/devices.c                          |    4 +-
 arch/sh/boards/mach-migor/setup.c                  |    4 +-
 drivers/mtd/inftlcore.c                            |    2 +-
 drivers/mtd/nand/Kconfig                           |  566 +------
 drivers/mtd/nand/Makefile                          |   71 +-
 drivers/mtd/nand/{nand_bbt.c => bbt.c}             |  697 ++++----
 drivers/mtd/nand/raw/Kconfig                       |  566 +++++++
 drivers/mtd/nand/raw/Makefile                      |   69 +
 drivers/mtd/nand/{ => raw}/ams-delta.c             |   10 +-
 drivers/mtd/nand/{ => raw}/atmel/Makefile          |    0
 drivers/mtd/nand/{ => raw}/atmel/nand-controller.c |   52 +-
 drivers/mtd/nand/{ => raw}/atmel/pmecc.c           |    2 +-
 drivers/mtd/nand/{ => raw}/atmel/pmecc.h           |    0
 drivers/mtd/nand/{ => raw}/au1550nd.c              |   28 +-
 drivers/mtd/nand/{ => raw}/bcm47xxnflash/Makefile  |    0
 .../nand/{ => raw}/bcm47xxnflash/bcm47xxnflash.h   |    2 +-
 drivers/mtd/nand/{ => raw}/bcm47xxnflash/main.c    |    4 +-
 .../mtd/nand/{ => raw}/bcm47xxnflash/ops_bcm4706.c |   18 +-
 drivers/mtd/nand/{ => raw}/bf5xx_nand.c            |   34 +-
 drivers/mtd/nand/{ => raw}/brcmnand/Makefile       |    0
 .../mtd/nand/{ => raw}/brcmnand/bcm63138_nand.c    |    0
 drivers/mtd/nand/{ => raw}/brcmnand/bcm6368_nand.c |    0
 drivers/mtd/nand/{ => raw}/brcmnand/brcmnand.c     |   34 +-
 drivers/mtd/nand/{ => raw}/brcmnand/brcmnand.h     |    0
 drivers/mtd/nand/{ => raw}/brcmnand/brcmstb_nand.c |    0
 drivers/mtd/nand/{ => raw}/brcmnand/iproc_nand.c   |    0
 drivers/mtd/nand/{ => raw}/cafe_nand.c             |   26 +-
 drivers/mtd/nand/{ => raw}/cmx270_nand.c           |   14 +-
 drivers/mtd/nand/{ => raw}/cs553x_nand.c           |   22 +-
 drivers/mtd/nand/{ => raw}/davinci_nand.c          |   16 +-
 drivers/mtd/nand/{ => raw}/denali.c                |   14 +-
 drivers/mtd/nand/{ => raw}/denali.h                |    2 +-
 drivers/mtd/nand/{ => raw}/denali_dt.c             |    0
 drivers/mtd/nand/{ => raw}/denali_pci.c            |    0
 drivers/mtd/nand/{ => raw}/diskonchip.c            |   70 +-
 drivers/mtd/nand/{ => raw}/docg4.c                 |   45 +-
 drivers/mtd/nand/{ => raw}/fsl_elbc_nand.c         |   28 +-
 drivers/mtd/nand/{ => raw}/fsl_ifc_nand.c          |   30 +-
 drivers/mtd/nand/{ => raw}/fsl_upm.c               |   14 +-
 drivers/mtd/nand/{ => raw}/fsmc_nand.c             |   26 +-
 drivers/mtd/nand/{ => raw}/gpio.c                  |    8 +-
 drivers/mtd/nand/{ => raw}/gpmi-nand/Makefile      |    0
 drivers/mtd/nand/{ => raw}/gpmi-nand/bch-regs.h    |    0
 drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-lib.c    |    2 +-
 drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-nand.c   |   38 +-
 drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-nand.h   |    2 +-
 drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-regs.h   |    0
 drivers/mtd/nand/{ => raw}/hisi504_nand.c          |   26 +-
 drivers/mtd/nand/{ => raw}/jz4740_nand.c           |   14 +-
 drivers/mtd/nand/{ => raw}/jz4780_bch.c            |    0
 drivers/mtd/nand/{ => raw}/jz4780_bch.h            |    0
 drivers/mtd/nand/{ => raw}/jz4780_nand.c           |   10 +-
 drivers/mtd/nand/{ => raw}/lpc32xx_mlc.c           |   18 +-
 drivers/mtd/nand/{ => raw}/lpc32xx_slc.c           |   22 +-
 drivers/mtd/nand/{ => raw}/mpc5121_nfc.c           |   28 +-
 drivers/mtd/nand/{ => raw}/mtk_ecc.c               |    0
 drivers/mtd/nand/{ => raw}/mtk_ecc.h               |    0
 drivers/mtd/nand/{ => raw}/mtk_nand.c              |   40 +-
 drivers/mtd/nand/{ => raw}/mxc_nand.c              |   54 +-
 drivers/mtd/nand/{ => raw}/nand_amd.c              |    4 +-
 drivers/mtd/nand/{ => raw}/nand_base.c             |  272 +++-
 drivers/mtd/nand/{ => raw}/nand_bch.c              |    8 +-
 drivers/mtd/nand/{ => raw}/nand_ecc.c              |    6 +-
 drivers/mtd/nand/{ => raw}/nand_hynix.c            |   12 +-
 drivers/mtd/nand/{ => raw}/nand_ids.c              |    2 +-
 drivers/mtd/nand/{ => raw}/nand_macronix.c         |    2 +-
 drivers/mtd/nand/{ => raw}/nand_micron.c           |   12 +-
 drivers/mtd/nand/{ => raw}/nand_samsung.c          |    6 +-
 drivers/mtd/nand/{ => raw}/nand_timings.c          |    2 +-
 drivers/mtd/nand/{ => raw}/nand_toshiba.c          |    4 +-
 drivers/mtd/nand/{ => raw}/nandsim.c               |   24 +-
 drivers/mtd/nand/{ => raw}/ndfc.c                  |   20 +-
 drivers/mtd/nand/{ => raw}/nuc900_nand.c           |   10 +-
 drivers/mtd/nand/{ => raw}/omap2.c                 |   22 +-
 drivers/mtd/nand/{ => raw}/omap_elm.c              |    0
 drivers/mtd/nand/{ => raw}/orion_nand.c            |   10 +-
 drivers/mtd/nand/{ => raw}/oxnas_nand.c            |   14 +-
 drivers/mtd/nand/{ => raw}/pasemi_nand.c           |   12 +-
 drivers/mtd/nand/{ => raw}/plat_nand.c             |    6 +-
 drivers/mtd/nand/{ => raw}/pxa3xx_nand.c           |   38 +-
 drivers/mtd/nand/{ => raw}/qcom_nandc.c            |   30 +-
 drivers/mtd/nand/{ => raw}/r852.c                  |    8 +-
 drivers/mtd/nand/{ => raw}/r852.h                  |    2 +-
 drivers/mtd/nand/{ => raw}/s3c2410.c               |   18 +-
 drivers/mtd/nand/{ => raw}/sh_flctl.c              |   12 +-
 drivers/mtd/nand/{ => raw}/sharpsl.c               |   10 +-
 drivers/mtd/nand/{ => raw}/sm_common.c             |    4 +-
 drivers/mtd/nand/{ => raw}/sm_common.h             |    0
 drivers/mtd/nand/{ => raw}/socrates_nand.c         |   14 +-
 drivers/mtd/nand/{ => raw}/sunxi_nand.c            |   60 +-
 drivers/mtd/nand/{ => raw}/tango_nand.c            |   32 +-
 drivers/mtd/nand/{ => raw}/tmio_nand.c             |   10 +-
 drivers/mtd/nand/{ => raw}/txx9ndfmc.c             |   16 +-
 drivers/mtd/nand/{ => raw}/vf610_nfc.c             |    6 +-
 drivers/mtd/nand/{ => raw}/xway_nand.c             |   12 +-
 drivers/mtd/nand/spi/Kconfig                       |    7 +
 drivers/mtd/nand/spi/Makefile                      |    3 +
 drivers/mtd/nand/spi/controllers/Kconfig           |    5 +
 drivers/mtd/nand/spi/controllers/Makefile          |    1 +
 drivers/mtd/nand/spi/controllers/generic-spi.c     |  162 ++
 drivers/mtd/nand/spi/core.c                        | 1381 ++++++++++++++++
 drivers/mtd/nand/spi/micron.c                      |  157 ++
 drivers/mtd/nftlcore.c                             |    2 +-
 drivers/mtd/nftlmount.c                            |    2 +-
 drivers/mtd/sm_ftl.c                               |    2 +-
 drivers/mtd/ssfdc.c                                |    2 +-
 drivers/mtd/tests/nandbiterrs.c                    |    2 +-
 drivers/staging/mt29f_spinand/mt29f_spinand.c      |    8 +-
 fs/jffs2/wbuf.c                                    |    2 +-
 include/linux/mtd/nand-gpio.h                      |    2 +-
 include/linux/mtd/nand.h                           | 1667 +++++++-------------
 include/linux/mtd/rawnand.h                        | 1286 +++++++++++++++
 include/linux/mtd/sh_flctl.h                       |    4 +-
 include/linux/mtd/sharpsl.h                        |    2 +-
 include/linux/mtd/spinand.h                        |  272 ++++
 include/linux/platform_data/atmel.h                |    2 +-
 include/linux/platform_data/mtd-davinci.h          |    2 +-
 include/linux/platform_data/mtd-nand-s3c2410.h     |    2 +-
 170 files changed, 5708 insertions(+), 2906 deletions(-)
 rename drivers/mtd/nand/{nand_bbt.c => bbt.c} (69%)
 create mode 100644 drivers/mtd/nand/raw/Kconfig
 create mode 100644 drivers/mtd/nand/raw/Makefile
 rename drivers/mtd/nand/{ => raw}/ams-delta.c (97%)
 rename drivers/mtd/nand/{ => raw}/atmel/Makefile (100%)
 rename drivers/mtd/nand/{ => raw}/atmel/nand-controller.c (97%)
 rename drivers/mtd/nand/{ => raw}/atmel/pmecc.c (99%)
 rename drivers/mtd/nand/{ => raw}/atmel/pmecc.h (100%)
 rename drivers/mtd/nand/{ => raw}/au1550nd.c (95%)
 rename drivers/mtd/nand/{ => raw}/bcm47xxnflash/Makefile (100%)
 rename drivers/mtd/nand/{ => raw}/bcm47xxnflash/bcm47xxnflash.h (92%)
 rename drivers/mtd/nand/{ => raw}/bcm47xxnflash/main.c (95%)
 rename drivers/mtd/nand/{ => raw}/bcm47xxnflash/ops_bcm4706.c (96%)
 rename drivers/mtd/nand/{ => raw}/bf5xx_nand.c (95%)
 rename drivers/mtd/nand/{ => raw}/brcmnand/Makefile (100%)
 rename drivers/mtd/nand/{ => raw}/brcmnand/bcm63138_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/brcmnand/bcm6368_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/brcmnand/brcmnand.c (98%)
 rename drivers/mtd/nand/{ => raw}/brcmnand/brcmnand.h (100%)
 rename drivers/mtd/nand/{ => raw}/brcmnand/brcmstb_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/brcmnand/iproc_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/cafe_nand.c (97%)
 rename drivers/mtd/nand/{ => raw}/cmx270_nand.c (94%)
 rename drivers/mtd/nand/{ => raw}/cs553x_nand.c (95%)
 rename drivers/mtd/nand/{ => raw}/davinci_nand.c (98%)
 rename drivers/mtd/nand/{ => raw}/denali.c (99%)
 rename drivers/mtd/nand/{ => raw}/denali.h (99%)
 rename drivers/mtd/nand/{ => raw}/denali_dt.c (100%)
 rename drivers/mtd/nand/{ => raw}/denali_pci.c (100%)
 rename drivers/mtd/nand/{ => raw}/diskonchip.c (96%)
 rename drivers/mtd/nand/{ => raw}/docg4.c (97%)
 rename drivers/mtd/nand/{ => raw}/fsl_elbc_nand.c (97%)
 rename drivers/mtd/nand/{ => raw}/fsl_ifc_nand.c (97%)
 rename drivers/mtd/nand/{ => raw}/fsl_upm.c (95%)
 rename drivers/mtd/nand/{ => raw}/fsmc_nand.c (97%)
 rename drivers/mtd/nand/{ => raw}/gpio.c (97%)
 rename drivers/mtd/nand/{ => raw}/gpmi-nand/Makefile (100%)
 rename drivers/mtd/nand/{ => raw}/gpmi-nand/bch-regs.h (100%)
 rename drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-lib.c (99%)
 rename drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-nand.c (98%)
 rename drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-nand.h (99%)
 rename drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-regs.h (100%)
 rename drivers/mtd/nand/{ => raw}/hisi504_nand.c (97%)
 rename drivers/mtd/nand/{ => raw}/jz4740_nand.c (97%)
 rename drivers/mtd/nand/{ => raw}/jz4780_bch.c (100%)
 rename drivers/mtd/nand/{ => raw}/jz4780_bch.h (100%)
 rename drivers/mtd/nand/{ => raw}/jz4780_nand.c (97%)
 rename drivers/mtd/nand/{ => raw}/lpc32xx_mlc.c (98%)
 rename drivers/mtd/nand/{ => raw}/lpc32xx_slc.c (98%)
 rename drivers/mtd/nand/{ => raw}/mpc5121_nfc.c (96%)
 rename drivers/mtd/nand/{ => raw}/mtk_ecc.c (100%)
 rename drivers/mtd/nand/{ => raw}/mtk_ecc.h (100%)
 rename drivers/mtd/nand/{ => raw}/mtk_nand.c (97%)
 rename drivers/mtd/nand/{ => raw}/mxc_nand.c (97%)
 rename drivers/mtd/nand/{ => raw}/nand_amd.c (94%)
 rename drivers/mtd/nand/{ => raw}/nand_base.c (94%)
 rename drivers/mtd/nand/{ => raw}/nand_bch.c (97%)
 rename drivers/mtd/nand/{ => raw}/nand_ecc.c (99%)
 rename drivers/mtd/nand/{ => raw}/nand_hynix.c (98%)
 rename drivers/mtd/nand/{ => raw}/nand_ids.c (99%)
 rename drivers/mtd/nand/{ => raw}/nand_macronix.c (96%)
 rename drivers/mtd/nand/{ => raw}/nand_micron.c (96%)
 rename drivers/mtd/nand/{ => raw}/nand_samsung.c (95%)
 rename drivers/mtd/nand/{ => raw}/nand_timings.c (99%)
 rename drivers/mtd/nand/{ => raw}/nand_toshiba.c (95%)
 rename drivers/mtd/nand/{ => raw}/nandsim.c (99%)
 rename drivers/mtd/nand/{ => raw}/ndfc.c (93%)
 rename drivers/mtd/nand/{ => raw}/nuc900_nand.c (96%)
 rename drivers/mtd/nand/{ => raw}/omap2.c (99%)
 rename drivers/mtd/nand/{ => raw}/omap_elm.c (100%)
 rename drivers/mtd/nand/{ => raw}/orion_nand.c (96%)
 rename drivers/mtd/nand/{ => raw}/oxnas_nand.c (93%)
 rename drivers/mtd/nand/{ => raw}/pasemi_nand.c (95%)
 rename drivers/mtd/nand/{ => raw}/plat_nand.c (96%)
 rename drivers/mtd/nand/{ => raw}/pxa3xx_nand.c (98%)
 rename drivers/mtd/nand/{ => raw}/qcom_nandc.c (98%)
 rename drivers/mtd/nand/{ => raw}/r852.c (99%)
 rename drivers/mtd/nand/{ => raw}/r852.h (99%)
 rename drivers/mtd/nand/{ => raw}/s3c2410.c (98%)
 rename drivers/mtd/nand/{ => raw}/sh_flctl.c (99%)
 rename drivers/mtd/nand/{ => raw}/sharpsl.c (96%)
 rename drivers/mtd/nand/{ => raw}/sm_common.c (98%)
 rename drivers/mtd/nand/{ => raw}/sm_common.h (100%)
 rename drivers/mtd/nand/{ => raw}/socrates_nand.c (94%)
 rename drivers/mtd/nand/{ => raw}/sunxi_nand.c (97%)
 rename drivers/mtd/nand/{ => raw}/tango_nand.c (95%)
 rename drivers/mtd/nand/{ => raw}/tmio_nand.c (98%)
 rename drivers/mtd/nand/{ => raw}/txx9ndfmc.c (97%)
 rename drivers/mtd/nand/{ => raw}/vf610_nfc.c (99%)
 rename drivers/mtd/nand/{ => raw}/xway_nand.c (96%)
 create mode 100644 drivers/mtd/nand/spi/Kconfig
 create mode 100644 drivers/mtd/nand/spi/Makefile
 create mode 100644 drivers/mtd/nand/spi/controllers/Kconfig
 create mode 100644 drivers/mtd/nand/spi/controllers/Makefile
 create mode 100644 drivers/mtd/nand/spi/controllers/generic-spi.c
 create mode 100644 drivers/mtd/nand/spi/core.c
 create mode 100644 drivers/mtd/nand/spi/micron.c
 create mode 100644 include/linux/mtd/rawnand.h
 create mode 100644 include/linux/mtd/spinand.h

-- 
1.9.1

^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH v6 01/15] mtd: nand: Rename nand.h into rawnand.h
  2017-05-24  7:06 [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Peter Pan
@ 2017-05-24  7:06 ` Peter Pan
  2017-05-24  7:06 ` [PATCH v6 02/15] mtd: nand: move raw NAND related code to the raw/ subdir Peter Pan
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 65+ messages in thread
From: Peter Pan @ 2017-05-24  7:06 UTC (permalink / raw)
  To: boris.brezillon, richard, computersforpeace, arnaud.mouiche,
	thomas.petazzoni, marex, cyrille.pitchen, linux-mtd
  Cc: peterpandong, peterpansjtu, linshunquan1

From: Boris Brezillon <boris.brezillon@free-electrons.com>

We are planning to share more code between different NAND based
devices (SPI NAND, OneNAND and raw NANDs), but before doing that
we need to move the existing include/linux/mtd/nand.h file into
include/linux/mtd/rawnand.h so we can later create a nand.h header
containing all common structure and function prototypes.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Peter Pan <peterpandong@micron.com>
---
 Documentation/DocBook/mtdnand.tmpl              | 2 +-
 MAINTAINERS                                     | 2 +-
 arch/arm/mach-davinci/board-da850-evm.c         | 2 +-
 arch/arm/mach-davinci/board-dm355-evm.c         | 2 +-
 arch/arm/mach-davinci/board-dm355-leopard.c     | 2 +-
 arch/arm/mach-davinci/board-dm365-evm.c         | 2 +-
 arch/arm/mach-davinci/board-dm644x-evm.c        | 2 +-
 arch/arm/mach-davinci/board-dm646x-evm.c        | 2 +-
 arch/arm/mach-davinci/board-sffsdr.c            | 2 +-
 arch/arm/mach-dove/dove-db-setup.c              | 2 +-
 arch/arm/mach-ep93xx/snappercl15.c              | 2 +-
 arch/arm/mach-ep93xx/ts72xx.c                   | 2 +-
 arch/arm/mach-imx/mach-qong.c                   | 2 +-
 arch/arm/mach-ixp4xx/ixdp425-setup.c            | 2 +-
 arch/arm/mach-mmp/aspenite.c                    | 2 +-
 arch/arm/mach-omap1/board-fsample.c             | 2 +-
 arch/arm/mach-omap1/board-h2.c                  | 2 +-
 arch/arm/mach-omap1/board-h3.c                  | 2 +-
 arch/arm/mach-omap1/board-nand.c                | 2 +-
 arch/arm/mach-omap1/board-perseus2.c            | 2 +-
 arch/arm/mach-orion5x/db88f5281-setup.c         | 2 +-
 arch/arm/mach-orion5x/kurobox_pro-setup.c       | 2 +-
 arch/arm/mach-orion5x/ts209-setup.c             | 2 +-
 arch/arm/mach-orion5x/ts78xx-setup.c            | 2 +-
 arch/arm/mach-pxa/balloon3.c                    | 2 +-
 arch/arm/mach-pxa/em-x270.c                     | 2 +-
 arch/arm/mach-pxa/eseries.c                     | 2 +-
 arch/arm/mach-pxa/palmtx.c                      | 2 +-
 arch/arm/mach-pxa/tosa.c                        | 2 +-
 arch/arm/mach-s3c24xx/common-smdk.c             | 2 +-
 arch/arm/mach-s3c24xx/mach-anubis.c             | 2 +-
 arch/arm/mach-s3c24xx/mach-at2440evb.c          | 2 +-
 arch/arm/mach-s3c24xx/mach-bast.c               | 2 +-
 arch/arm/mach-s3c24xx/mach-gta02.c              | 2 +-
 arch/arm/mach-s3c24xx/mach-jive.c               | 2 +-
 arch/arm/mach-s3c24xx/mach-mini2440.c           | 2 +-
 arch/arm/mach-s3c24xx/mach-osiris.c             | 2 +-
 arch/arm/mach-s3c24xx/mach-qt2410.c             | 2 +-
 arch/arm/mach-s3c24xx/mach-rx3715.c             | 2 +-
 arch/arm/mach-s3c24xx/mach-vstms.c              | 2 +-
 arch/blackfin/mach-bf537/boards/dnp5370.c       | 2 +-
 arch/blackfin/mach-bf537/boards/stamp.c         | 2 +-
 arch/blackfin/mach-bf561/boards/acvilon.c       | 2 +-
 arch/cris/arch-v32/drivers/mach-a3/nandflash.c  | 2 +-
 arch/cris/arch-v32/drivers/mach-fs/nandflash.c  | 2 +-
 arch/mips/alchemy/devboards/db1200.c            | 2 +-
 arch/mips/alchemy/devboards/db1300.c            | 2 +-
 arch/mips/alchemy/devboards/db1550.c            | 2 +-
 arch/mips/include/asm/mach-jz4740/jz4740_nand.h | 2 +-
 arch/mips/netlogic/xlr/platform-flash.c         | 2 +-
 arch/mips/pnx833x/common/platform.c             | 2 +-
 arch/mips/rb532/devices.c                       | 2 +-
 arch/sh/boards/mach-migor/setup.c               | 2 +-
 drivers/mtd/inftlcore.c                         | 2 +-
 drivers/mtd/nand/ams-delta.c                    | 2 +-
 drivers/mtd/nand/atmel/nand-controller.c        | 2 +-
 drivers/mtd/nand/atmel/pmecc.c                  | 2 +-
 drivers/mtd/nand/au1550nd.c                     | 2 +-
 drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h  | 2 +-
 drivers/mtd/nand/bf5xx_nand.c                   | 2 +-
 drivers/mtd/nand/brcmnand/brcmnand.c            | 2 +-
 drivers/mtd/nand/cafe_nand.c                    | 2 +-
 drivers/mtd/nand/cmx270_nand.c                  | 2 +-
 drivers/mtd/nand/cs553x_nand.c                  | 2 +-
 drivers/mtd/nand/davinci_nand.c                 | 2 +-
 drivers/mtd/nand/denali.h                       | 2 +-
 drivers/mtd/nand/diskonchip.c                   | 2 +-
 drivers/mtd/nand/docg4.c                        | 2 +-
 drivers/mtd/nand/fsl_elbc_nand.c                | 2 +-
 drivers/mtd/nand/fsl_ifc_nand.c                 | 2 +-
 drivers/mtd/nand/fsl_upm.c                      | 2 +-
 drivers/mtd/nand/fsmc_nand.c                    | 2 +-
 drivers/mtd/nand/gpio.c                         | 2 +-
 drivers/mtd/nand/gpmi-nand/gpmi-nand.h          | 2 +-
 drivers/mtd/nand/hisi504_nand.c                 | 2 +-
 drivers/mtd/nand/jz4740_nand.c                  | 2 +-
 drivers/mtd/nand/jz4780_nand.c                  | 2 +-
 drivers/mtd/nand/lpc32xx_mlc.c                  | 2 +-
 drivers/mtd/nand/lpc32xx_slc.c                  | 2 +-
 drivers/mtd/nand/mpc5121_nfc.c                  | 2 +-
 drivers/mtd/nand/mtk_nand.c                     | 2 +-
 drivers/mtd/nand/mxc_nand.c                     | 2 +-
 drivers/mtd/nand/nand_amd.c                     | 2 +-
 drivers/mtd/nand/nand_base.c                    | 2 +-
 drivers/mtd/nand/nand_bbt.c                     | 2 +-
 drivers/mtd/nand/nand_bch.c                     | 2 +-
 drivers/mtd/nand/nand_ecc.c                     | 2 +-
 drivers/mtd/nand/nand_hynix.c                   | 2 +-
 drivers/mtd/nand/nand_ids.c                     | 2 +-
 drivers/mtd/nand/nand_macronix.c                | 2 +-
 drivers/mtd/nand/nand_micron.c                  | 2 +-
 drivers/mtd/nand/nand_samsung.c                 | 2 +-
 drivers/mtd/nand/nand_timings.c                 | 2 +-
 drivers/mtd/nand/nand_toshiba.c                 | 2 +-
 drivers/mtd/nand/nandsim.c                      | 2 +-
 drivers/mtd/nand/ndfc.c                         | 2 +-
 drivers/mtd/nand/nuc900_nand.c                  | 2 +-
 drivers/mtd/nand/omap2.c                        | 2 +-
 drivers/mtd/nand/orion_nand.c                   | 2 +-
 drivers/mtd/nand/oxnas_nand.c                   | 2 +-
 drivers/mtd/nand/pasemi_nand.c                  | 2 +-
 drivers/mtd/nand/plat_nand.c                    | 2 +-
 drivers/mtd/nand/pxa3xx_nand.c                  | 2 +-
 drivers/mtd/nand/qcom_nandc.c                   | 2 +-
 drivers/mtd/nand/r852.h                         | 2 +-
 drivers/mtd/nand/s3c2410.c                      | 2 +-
 drivers/mtd/nand/sh_flctl.c                     | 2 +-
 drivers/mtd/nand/sharpsl.c                      | 2 +-
 drivers/mtd/nand/sm_common.c                    | 2 +-
 drivers/mtd/nand/socrates_nand.c                | 2 +-
 drivers/mtd/nand/sunxi_nand.c                   | 2 +-
 drivers/mtd/nand/tango_nand.c                   | 2 +-
 drivers/mtd/nand/tmio_nand.c                    | 2 +-
 drivers/mtd/nand/txx9ndfmc.c                    | 2 +-
 drivers/mtd/nand/vf610_nfc.c                    | 2 +-
 drivers/mtd/nand/xway_nand.c                    | 2 +-
 drivers/mtd/nftlcore.c                          | 2 +-
 drivers/mtd/nftlmount.c                         | 2 +-
 drivers/mtd/ssfdc.c                             | 2 +-
 drivers/mtd/tests/nandbiterrs.c                 | 2 +-
 drivers/staging/mt29f_spinand/mt29f_spinand.c   | 2 +-
 fs/jffs2/wbuf.c                                 | 2 +-
 include/linux/mtd/nand-gpio.h                   | 2 +-
 include/linux/mtd/{nand.h => rawnand.h}         | 8 +++-----
 include/linux/mtd/sh_flctl.h                    | 2 +-
 include/linux/mtd/sharpsl.h                     | 2 +-
 include/linux/platform_data/atmel.h             | 2 +-
 include/linux/platform_data/mtd-davinci.h       | 2 +-
 include/linux/platform_data/mtd-nand-s3c2410.h  | 2 +-
 129 files changed, 131 insertions(+), 133 deletions(-)
 rename include/linux/mtd/{nand.h => rawnand.h} (99%)

diff --git a/Documentation/DocBook/mtdnand.tmpl b/Documentation/DocBook/mtdnand.tmpl
index b442921..35ec715 100644
--- a/Documentation/DocBook/mtdnand.tmpl
+++ b/Documentation/DocBook/mtdnand.tmpl
@@ -1239,7 +1239,7 @@ in this page</entry>
      struct member has a short description which is marked with an [XXX] identifier.
      See the chapter "Documentation hints" for an explanation.
      </para>
-!Iinclude/linux/mtd/nand.h
+!Iinclude/linux/mtd/rawnand.h
   </chapter>
 
   <chapter id="pubfunctions">
diff --git a/MAINTAINERS b/MAINTAINERS
index f7d568b..81bb063 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8760,7 +8760,7 @@ T:	git git://git.infradead.org/linux-mtd.git nand/fixes
 T:	git git://git.infradead.org/l2-mtd.git nand/next
 S:	Maintained
 F:	drivers/mtd/nand/
-F:	include/linux/mtd/nand*.h
+F:	include/linux/mtd/*nand*.h
 
 NATSEMI ETHERNET DRIVER (DP8381x)
 S:	Orphan
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index b5625d0..f544103 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -26,7 +26,7 @@
 #include <linux/input/tps6507x-ts.h>
 #include <linux/mfd/tps6507x.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/platform_device.h>
diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c
index 18296a9..62e7bc3 100644
--- a/arch/arm/mach-davinci/board-dm355-evm.c
+++ b/arch/arm/mach-davinci/board-dm355-evm.c
@@ -14,7 +14,7 @@
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/i2c.h>
 #include <linux/gpio.h>
 #include <linux/clk.h>
diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c
index 284ff27..be99724 100644
--- a/arch/arm/mach-davinci/board-dm355-leopard.c
+++ b/arch/arm/mach-davinci/board-dm355-leopard.c
@@ -13,7 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/i2c.h>
 #include <linux/gpio.h>
 #include <linux/clk.h>
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index 0464999..e75741f 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -23,7 +23,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/slab.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/input.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/eeprom.h>
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index 20f1874..1b05660 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -17,7 +17,7 @@
 #include <linux/i2c/pcf857x.h>
 #include <linux/platform_data/at24.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/phy.h>
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index cb17682..19d1eb2 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -29,7 +29,7 @@
 #include <media/i2c/adv7343.h>
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/clk.h>
 #include <linux/export.h>
diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c
index 41c7c96..d85accf 100644
--- a/arch/arm/mach-davinci/board-sffsdr.c
+++ b/arch/arm/mach-davinci/board-sffsdr.c
@@ -28,7 +28,7 @@
 #include <linux/i2c.h>
 #include <linux/platform_data/at24.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 
 #include <asm/mach-types.h>
diff --git a/arch/arm/mach-dove/dove-db-setup.c b/arch/arm/mach-dove/dove-db-setup.c
index bcb678f..8971c3c 100644
--- a/arch/arm/mach-dove/dove-db-setup.c
+++ b/arch/arm/mach-dove/dove-db-setup.c
@@ -13,7 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/irq.h>
 #include <linux/mtd/physmap.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/timer.h>
 #include <linux/ata_platform.h>
 #include <linux/mv643xx_eth.h>
diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c
index b2db791..8b29398 100644
--- a/arch/arm/mach-ep93xx/snappercl15.c
+++ b/arch/arm/mach-ep93xx/snappercl15.c
@@ -25,7 +25,7 @@
 #include <linux/fb.h>
 
 #include <linux/mtd/partitions.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 
 #include <mach/hardware.h>
 #include <linux/platform_data/video-ep93xx.h>
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index 55b186e..8745162 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -16,7 +16,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 
 #include <mach/hardware.h>
diff --git a/arch/arm/mach-imx/mach-qong.c b/arch/arm/mach-imx/mach-qong.c
index 8c2cbd6..42a7000 100644
--- a/arch/arm/mach-imx/mach-qong.c
+++ b/arch/arm/mach-imx/mach-qong.c
@@ -18,7 +18,7 @@
 #include <linux/memory.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/physmap.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/gpio.h>
 
 #include <asm/mach-types.h>
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index 508c2d7..93b89291 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -17,7 +17,7 @@
 #include <linux/i2c-gpio.h>
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index 5db0edf..d228300 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -16,7 +16,7 @@
 #include <linux/smc91x.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/interrupt.h>
 #include <linux/platform_data/mv_usb.h>
 
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index fad95b7..b93ad58 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -16,7 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/input.h>
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index 675254e..a444b13 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -24,7 +24,7 @@
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/input.h>
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index e62f9d4..a618a49 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -23,7 +23,7 @@
 #include <linux/workqueue.h>
 #include <linux/i2c.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/input.h>
diff --git a/arch/arm/mach-omap1/board-nand.c b/arch/arm/mach-omap1/board-nand.c
index 7684f92..1bffbb4 100644
--- a/arch/arm/mach-omap1/board-nand.c
+++ b/arch/arm/mach-omap1/board-nand.c
@@ -16,7 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 150b57b..e994a78 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -16,7 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/input.h>
diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c
index 12f74b4..3f5863d 100644
--- a/arch/arm/mach-orion5x/db88f5281-setup.c
+++ b/arch/arm/mach-orion5x/db88f5281-setup.c
@@ -16,7 +16,7 @@
 #include <linux/pci.h>
 #include <linux/irq.h>
 #include <linux/mtd/physmap.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/timer.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/i2c.h>
diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c
index 9dc3f59..83d43cf 100644
--- a/arch/arm/mach-orion5x/kurobox_pro-setup.c
+++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
@@ -15,7 +15,7 @@
 #include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/mtd/physmap.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/i2c.h>
 #include <linux/serial_reg.h>
diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c
index 7bd671b..0c31551 100644
--- a/arch/arm/mach-orion5x/ts209-setup.c
+++ b/arch/arm/mach-orion5x/ts209-setup.c
@@ -15,7 +15,7 @@
 #include <linux/pci.h>
 #include <linux/irq.h>
 #include <linux/mtd/physmap.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c
index 7ef80a8..9477873 100644
--- a/arch/arm/mach-orion5x/ts78xx-setup.c
+++ b/arch/arm/mach-orion5x/ts78xx-setup.c
@@ -16,7 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/ata_platform.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/timeriomem-rng.h>
 #include <asm/mach-types.h>
diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
index d452a49..33d7ef1 100644
--- a/arch/arm/mach-pxa/balloon3.c
+++ b/arch/arm/mach-pxa/balloon3.c
@@ -29,7 +29,7 @@
 #include <linux/types.h>
 #include <linux/i2c/pcf857x.h>
 #include <linux/i2c/pxa-i2c.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/physmap.h>
 #include <linux/regulator/max1586.h>
 
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index 811a731..6d28035 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -15,7 +15,7 @@
 
 #include <linux/dm9000.h>
 #include <linux/platform_data/rtc-v3020.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/input.h>
diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c
index fa9d71d..91f7c3e 100644
--- a/arch/arm/mach-pxa/eseries.c
+++ b/arch/arm/mach-pxa/eseries.c
@@ -20,7 +20,7 @@
 #include <linux/mfd/tc6387xb.h>
 #include <linux/mfd/tc6393xb.h>
 #include <linux/mfd/t7l66xb.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/usb/gpio_vbus.h>
 #include <linux/memblock.h>
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
index 3664697..47e3e38 100644
--- a/arch/arm/mach-pxa/palmtx.c
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -28,7 +28,7 @@
 #include <linux/wm97xx.h>
 #include <linux/power_supply.h>
 #include <linux/usb/gpio_vbus.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/physmap.h>
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 13de660..6a386fd 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -24,7 +24,7 @@
 #include <linux/mmc/host.h>
 #include <linux/mfd/tc6393xb.h>
 #include <linux/mfd/tmio.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/pm.h>
diff --git a/arch/arm/mach-s3c24xx/common-smdk.c b/arch/arm/mach-s3c24xx/common-smdk.c
index 9e0bc46..0e116c9 100644
--- a/arch/arm/mach-s3c24xx/common-smdk.c
+++ b/arch/arm/mach-s3c24xx/common-smdk.c
@@ -23,7 +23,7 @@
 #include <linux/platform_device.h>
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 #include <linux/io.h>
diff --git a/arch/arm/mach-s3c24xx/mach-anubis.c b/arch/arm/mach-s3c24xx/mach-anubis.c
index 029ef1b..c14cab3 100644
--- a/arch/arm/mach-s3c24xx/mach-anubis.c
+++ b/arch/arm/mach-s3c24xx/mach-anubis.c
@@ -40,7 +40,7 @@
 #include <linux/platform_data/i2c-s3c2410.h>
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
diff --git a/arch/arm/mach-s3c24xx/mach-at2440evb.c b/arch/arm/mach-s3c24xx/mach-at2440evb.c
index 7b28eb6..ebdbafb 100644
--- a/arch/arm/mach-s3c24xx/mach-at2440evb.c
+++ b/arch/arm/mach-s3c24xx/mach-at2440evb.c
@@ -41,7 +41,7 @@
 #include <linux/platform_data/i2c-s3c2410.h>
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
diff --git a/arch/arm/mach-s3c24xx/mach-bast.c b/arch/arm/mach-s3c24xx/mach-bast.c
index 5185036..704dc84 100644
--- a/arch/arm/mach-s3c24xx/mach-bast.c
+++ b/arch/arm/mach-s3c24xx/mach-bast.c
@@ -28,7 +28,7 @@
 #include <linux/serial_8250.h>
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
diff --git a/arch/arm/mach-s3c24xx/mach-gta02.c b/arch/arm/mach-s3c24xx/mach-gta02.c
index b0ed401..afe18ba 100644
--- a/arch/arm/mach-s3c24xx/mach-gta02.c
+++ b/arch/arm/mach-s3c24xx/mach-gta02.c
@@ -50,7 +50,7 @@
 #include <linux/mfd/pcf50633/pmic.h>
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
diff --git a/arch/arm/mach-s3c24xx/mach-jive.c b/arch/arm/mach-s3c24xx/mach-jive.c
index f5b5c49..1782197 100644
--- a/arch/arm/mach-s3c24xx/mach-jive.c
+++ b/arch/arm/mach-s3c24xx/mach-jive.c
@@ -43,7 +43,7 @@
 #include <asm/mach-types.h>
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
diff --git a/arch/arm/mach-s3c24xx/mach-mini2440.c b/arch/arm/mach-s3c24xx/mach-mini2440.c
index 71af8d2..15140d3 100644
--- a/arch/arm/mach-s3c24xx/mach-mini2440.c
+++ b/arch/arm/mach-s3c24xx/mach-mini2440.c
@@ -49,7 +49,7 @@
 #include <linux/platform_data/usb-s3c2410_udc.h>
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
diff --git a/arch/arm/mach-s3c24xx/mach-osiris.c b/arch/arm/mach-s3c24xx/mach-osiris.c
index 70b0eb7..a6657e7 100644
--- a/arch/arm/mach-s3c24xx/mach-osiris.c
+++ b/arch/arm/mach-s3c24xx/mach-osiris.c
@@ -36,7 +36,7 @@
 #include <linux/platform_data/i2c-s3c2410.h>
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
diff --git a/arch/arm/mach-s3c24xx/mach-qt2410.c b/arch/arm/mach-s3c24xx/mach-qt2410.c
index 868c820..84e3a9c 100644
--- a/arch/arm/mach-s3c24xx/mach-qt2410.c
+++ b/arch/arm/mach-s3c24xx/mach-qt2410.c
@@ -36,7 +36,7 @@
 #include <linux/spi/spi_gpio.h>
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
diff --git a/arch/arm/mach-s3c24xx/mach-rx3715.c b/arch/arm/mach-s3c24xx/mach-rx3715.c
index a39fb97..b5ba615 100644
--- a/arch/arm/mach-s3c24xx/mach-rx3715.c
+++ b/arch/arm/mach-s3c24xx/mach-rx3715.c
@@ -27,7 +27,7 @@
 #include <linux/serial.h>
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
diff --git a/arch/arm/mach-s3c24xx/mach-vstms.c b/arch/arm/mach-s3c24xx/mach-vstms.c
index f5e6322..1adc957 100644
--- a/arch/arm/mach-s3c24xx/mach-vstms.c
+++ b/arch/arm/mach-s3c24xx/mach-vstms.c
@@ -20,7 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 #include <linux/memblock.h>
diff --git a/arch/blackfin/mach-bf537/boards/dnp5370.c b/arch/blackfin/mach-bf537/boards/dnp5370.c
index e79b3b8..c4a8ffb 100644
--- a/arch/blackfin/mach-bf537/boards/dnp5370.c
+++ b/arch/blackfin/mach-bf537/boards/dnp5370.c
@@ -17,7 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/plat-ram.h>
 #include <linux/mtd/physmap.h>
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index eaec7b4..ab3034f 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -12,7 +12,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/plat-ram.h>
 #include <linux/mtd/physmap.h>
diff --git a/arch/blackfin/mach-bf561/boards/acvilon.c b/arch/blackfin/mach-bf561/boards/acvilon.c
index 37f8f25..696cc9d 100644
--- a/arch/blackfin/mach-bf561/boards/acvilon.c
+++ b/arch/blackfin/mach-bf561/boards/acvilon.c
@@ -38,7 +38,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/plat-ram.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
diff --git a/arch/cris/arch-v32/drivers/mach-a3/nandflash.c b/arch/cris/arch-v32/drivers/mach-a3/nandflash.c
index 3f646c7..925a98e 100644
--- a/arch/cris/arch-v32/drivers/mach-a3/nandflash.c
+++ b/arch/cris/arch-v32/drivers/mach-a3/nandflash.c
@@ -16,7 +16,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <arch/memmap.h>
 #include <hwregs/reg_map.h>
diff --git a/arch/cris/arch-v32/drivers/mach-fs/nandflash.c b/arch/cris/arch-v32/drivers/mach-fs/nandflash.c
index a745405..53b56a4 100644
--- a/arch/cris/arch-v32/drivers/mach-fs/nandflash.c
+++ b/arch/cris/arch-v32/drivers/mach-fs/nandflash.c
@@ -16,7 +16,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <arch/memmap.h>
 #include <hwregs/reg_map.h>
diff --git a/arch/mips/alchemy/devboards/db1200.c b/arch/mips/alchemy/devboards/db1200.c
index 992442a..8383100 100644
--- a/arch/mips/alchemy/devboards/db1200.c
+++ b/arch/mips/alchemy/devboards/db1200.c
@@ -29,7 +29,7 @@
 #include <linux/leds.h>
 #include <linux/mmc/host.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
diff --git a/arch/mips/alchemy/devboards/db1300.c b/arch/mips/alchemy/devboards/db1300.c
index a5504f5..3e7fbdb 100644
--- a/arch/mips/alchemy/devboards/db1300.c
+++ b/arch/mips/alchemy/devboards/db1300.c
@@ -18,7 +18,7 @@
 #include <linux/mmc/host.h>
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/platform_device.h>
 #include <linux/smsc911x.h>
diff --git a/arch/mips/alchemy/devboards/db1550.c b/arch/mips/alchemy/devboards/db1550.c
index 1c01d6e..421bd57 100644
--- a/arch/mips/alchemy/devboards/db1550.c
+++ b/arch/mips/alchemy/devboards/db1550.c
@@ -12,7 +12,7 @@
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
diff --git a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h
index 7f7b0fc..f381d46 100644
--- a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h
+++ b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h
@@ -16,7 +16,7 @@
 #ifndef __ASM_MACH_JZ4740_JZ4740_NAND_H__
 #define __ASM_MACH_JZ4740_JZ4740_NAND_H__
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 
 #define JZ_NAND_NUM_BANKS 4
diff --git a/arch/mips/netlogic/xlr/platform-flash.c b/arch/mips/netlogic/xlr/platform-flash.c
index f03131f..4d1b4c0 100644
--- a/arch/mips/netlogic/xlr/platform-flash.c
+++ b/arch/mips/netlogic/xlr/platform-flash.c
@@ -19,7 +19,7 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/physmap.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 
 #include <asm/netlogic/haldefs.h>
diff --git a/arch/mips/pnx833x/common/platform.c b/arch/mips/pnx833x/common/platform.c
index 7cf4eb5..a7a4e9f 100644
--- a/arch/mips/pnx833x/common/platform.c
+++ b/arch/mips/pnx833x/common/platform.c
@@ -30,7 +30,7 @@
 #include <linux/resource.h>
 #include <linux/serial.h>
 #include <linux/serial_pnx8xxx.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 
 #include <irq.h>
diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c
index 0966adc..32ea3e6 100644
--- a/arch/mips/rb532/devices.c
+++ b/arch/mips/rb532/devices.c
@@ -20,7 +20,7 @@
 #include <linux/ctype.h>
 #include <linux/string.h>
 #include <linux/platform_device.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/gpio.h>
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index 5de60a7..0bcbe58 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -15,7 +15,7 @@
 #include <linux/mmc/host.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mfd/tmio.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/i2c.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index 8db740d..57ef1fb 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -33,7 +33,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nftl.h>
 #include <linux/mtd/inftl.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/uaccess.h>
 #include <asm/errno.h>
 #include <asm/io.h>
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
index 5d6c26f..dcec9cf 100644
--- a/drivers/mtd/nand/ams-delta.c
+++ b/drivers/mtd/nand/ams-delta.c
@@ -20,7 +20,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/gpio.h>
 #include <linux/platform_data/gpio-omap.h>
diff --git a/drivers/mtd/nand/atmel/nand-controller.c b/drivers/mtd/nand/atmel/nand-controller.c
index 3b24468..9abfc5d 100644
--- a/drivers/mtd/nand/atmel/nand-controller.c
+++ b/drivers/mtd/nand/atmel/nand-controller.c
@@ -58,7 +58,7 @@
 #include <linux/mfd/syscon.h>
 #include <linux/mfd/syscon/atmel-matrix.h>
 #include <linux/module.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
diff --git a/drivers/mtd/nand/atmel/pmecc.c b/drivers/mtd/nand/atmel/pmecc.c
index 55a8ee5..27a969a 100644
--- a/drivers/mtd/nand/atmel/pmecc.c
+++ b/drivers/mtd/nand/atmel/pmecc.c
@@ -47,7 +47,7 @@
 #include <linux/genalloc.h>
 #include <linux/iopoll.h>
 #include <linux/module.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index 9bf6d99..9d4a28f 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -14,7 +14,7 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/platform_device.h>
 #include <asm/io.h>
diff --git a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
index 8ea7571..c883476 100644
--- a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
+++ b/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
@@ -6,7 +6,7 @@
 #endif
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 
 struct bcm47xxnflash {
 	struct bcma_drv_cc *cc;
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
index 3962f55..5655dca 100644
--- a/drivers/mtd/nand/bf5xx_nand.c
+++ b/drivers/mtd/nand/bf5xx_nand.c
@@ -49,7 +49,7 @@
 #include <linux/bitops.h>
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
index 7419c5c..e0eb51d 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -29,7 +29,7 @@
 #include <linux/bitops.h>
 #include <linux/mm.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index d40c32d..0541c64 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -13,7 +13,7 @@
 #include <linux/device.h>
 #undef DEBUG
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/rslib.h>
 #include <linux/pci.h>
diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c
index 949b940..1fc435f 100644
--- a/drivers/mtd/nand/cmx270_nand.c
+++ b/drivers/mtd/nand/cmx270_nand.c
@@ -18,7 +18,7 @@
  *   CM-X270 board.
  */
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
index 594b286..d488775 100644
--- a/drivers/mtd/nand/cs553x_nand.c
+++ b/drivers/mtd/nand/cs553x_nand.c
@@ -24,7 +24,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index 7b26e53..ccc8c43 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -29,7 +29,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index ec00485..a539360 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -21,7 +21,7 @@
 #define __DENALI_H__
 
 #include <linux/bitops.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 
 #define DEVICE_RESET				0x0
 #define     DEVICE_RESET__BANK0				0x0001
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index a023ab9..c3aa53c 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -27,7 +27,7 @@
 #include <linux/io.h>
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/doc2000.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/inftl.h>
diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c
index 7af2a3c..e038130 100644
--- a/drivers/mtd/nand/docg4.c
+++ b/drivers/mtd/nand/docg4.c
@@ -41,7 +41,7 @@
 #include <linux/bitops.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/bch.h>
 #include <linux/bitrev.h>
 #include <linux/jiffies.h>
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 113f76e..7d8453e 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -34,7 +34,7 @@
 #include <linux/interrupt.h>
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index d1570f5..b9b8534 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -26,7 +26,7 @@
 #include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/fsl_ifc.h>
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index d85fa25..a88e2cf 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -14,7 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/delay.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/mtd.h>
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index de57554..bab7064 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -28,7 +28,7 @@
 #include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c
index 85294f1..fd36489 100644
--- a/drivers/mtd/nand/gpio.c
+++ b/drivers/mtd/nand/gpio.c
@@ -26,7 +26,7 @@
 #include <linux/gpio.h>
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand-gpio.h>
 #include <linux/of.h>
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
index e88a45a..f3181a4 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h
@@ -17,7 +17,7 @@
 #ifndef __DRIVERS_MTD_NAND_GPMI_NAND_H
 #define __DRIVERS_MTD_NAND_GPMI_NAND_H
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
diff --git a/drivers/mtd/nand/hisi504_nand.c b/drivers/mtd/nand/hisi504_nand.c
index e40364e..d09df18 100644
--- a/drivers/mtd/nand/hisi504_nand.c
+++ b/drivers/mtd/nand/hisi504_nand.c
@@ -26,7 +26,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/partitions.h>
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
index 5551c36..e813ec1 100644
--- a/drivers/mtd/nand/jz4740_nand.c
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -20,7 +20,7 @@
 #include <linux/slab.h>
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 
 #include <linux/gpio.h>
diff --git a/drivers/mtd/nand/jz4780_nand.c b/drivers/mtd/nand/jz4780_nand.c
index 8bc835f..e69f6ae 100644
--- a/drivers/mtd/nand/jz4780_nand.c
+++ b/drivers/mtd/nand/jz4780_nand.c
@@ -20,7 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 
 #include <linux/jz4780-nemc.h>
diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c
index 846a66c..bffa01c 100644
--- a/drivers/mtd/nand/lpc32xx_mlc.c
+++ b/drivers/mtd/nand/lpc32xx_mlc.c
@@ -27,7 +27,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/clk.h>
 #include <linux/err.h>
diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c
index a0669a3..7c8402f 100644
--- a/drivers/mtd/nand/lpc32xx_slc.c
+++ b/drivers/mtd/nand/lpc32xx_slc.c
@@ -23,7 +23,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/clk.h>
 #include <linux/err.h>
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 6d6eaed..55f1d4a 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -33,7 +33,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
diff --git a/drivers/mtd/nand/mtk_nand.c b/drivers/mtd/nand/mtk_nand.c
index 6c517c6..3f4a98b 100644
--- a/drivers/mtd/nand/mtk_nand.c
+++ b/drivers/mtd/nand/mtk_nand.c
@@ -19,7 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/mtd.h>
 #include <linux/module.h>
 #include <linux/iopoll.h>
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 61ca020..42bff4a 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -22,7 +22,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
diff --git a/drivers/mtd/nand/nand_amd.c b/drivers/mtd/nand/nand_amd.c
index 170403a..22f060f 100644
--- a/drivers/mtd/nand/nand_amd.c
+++ b/drivers/mtd/nand/nand_amd.c
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 
 static void amd_nand_decode_id(struct nand_chip *chip)
 {
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 54a1dfa..730165b 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -39,7 +39,7 @@
 #include <linux/nmi.h>
 #include <linux/types.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/nand_bch.h>
 #include <linux/interrupt.h>
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 7695efe..2915b67 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -61,7 +61,7 @@
 #include <linux/types.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/bbm.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c
index 44763f8..505441c 100644
--- a/drivers/mtd/nand/nand_bch.c
+++ b/drivers/mtd/nand/nand_bch.c
@@ -25,7 +25,7 @@
 #include <linux/slab.h>
 #include <linux/bitops.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_bch.h>
 #include <linux/bch.h>
 
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index d1770b0..7613a03 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -43,7 +43,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <asm/byteorder.h>
 #else
diff --git a/drivers/mtd/nand/nand_hynix.c b/drivers/mtd/nand/nand_hynix.c
index b12dc73..b735cc8 100644
--- a/drivers/mtd/nand/nand_hynix.c
+++ b/drivers/mtd/nand/nand_hynix.c
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/sizes.h>
 #include <linux/slab.h>
 
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index 9d5ca0e..3e87adc 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -7,7 +7,7 @@
  *
  */
 #include <linux/module.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/sizes.h>
 
 #define LP_OPTIONS 0
diff --git a/drivers/mtd/nand/nand_macronix.c b/drivers/mtd/nand/nand_macronix.c
index 84855c3..d290ff2 100644
--- a/drivers/mtd/nand/nand_macronix.c
+++ b/drivers/mtd/nand/nand_macronix.c
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 
 static int macronix_nand_init(struct nand_chip *chip)
 {
diff --git a/drivers/mtd/nand/nand_micron.c b/drivers/mtd/nand/nand_micron.c
index 0987f32..02c4c1f 100644
--- a/drivers/mtd/nand/nand_micron.c
+++ b/drivers/mtd/nand/nand_micron.c
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 
 /*
  * Special Micron status bit that indicates when the block has been
diff --git a/drivers/mtd/nand/nand_samsung.c b/drivers/mtd/nand/nand_samsung.c
index 9cfc403..ca17b44 100644
--- a/drivers/mtd/nand/nand_samsung.c
+++ b/drivers/mtd/nand/nand_samsung.c
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 
 static void samsung_nand_decode_id(struct nand_chip *chip)
 {
diff --git a/drivers/mtd/nand/nand_timings.c b/drivers/mtd/nand/nand_timings.c
index f06312d..90228b9 100644
--- a/drivers/mtd/nand/nand_timings.c
+++ b/drivers/mtd/nand/nand_timings.c
@@ -11,7 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/err.h>
 #include <linux/export.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 
 static const struct nand_data_interface onfi_sdr_timings[] = {
 	/* Mode 0 */
diff --git a/drivers/mtd/nand/nand_toshiba.c b/drivers/mtd/nand/nand_toshiba.c
index fa787ba..57df857 100644
--- a/drivers/mtd/nand/nand_toshiba.c
+++ b/drivers/mtd/nand/nand_toshiba.c
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 
 static void toshiba_nand_decode_id(struct nand_chip *chip)
 {
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index 03a0d05..5ba4635 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -33,7 +33,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_bch.h>
 #include <linux/mtd/partitions.h>
 #include <linux/delay.h>
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 28e6118..d8a8068 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -22,7 +22,7 @@
  *
  */
 #include <linux/module.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/ndfc.h>
diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c
index 8f64011..7bb4d2e 100644
--- a/drivers/mtd/nand/nuc900_nand.c
+++ b/drivers/mtd/nand/nuc900_nand.c
@@ -19,7 +19,7 @@
 #include <linux/err.h>
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 
 #define REG_FMICSR   	0x00
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 084934a..54540c8 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -18,7 +18,7 @@
 #include <linux/jiffies.h>
 #include <linux/sched.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/omap-dma.h>
 #include <linux/io.h>
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index f8e463a..ae4c0be 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -15,7 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/clk.h>
 #include <linux/err.h>
diff --git a/drivers/mtd/nand/oxnas_nand.c b/drivers/mtd/nand/oxnas_nand.c
index 1b207aa..f14eec3 100644
--- a/drivers/mtd/nand/oxnas_nand.c
+++ b/drivers/mtd/nand/oxnas_nand.c
@@ -21,7 +21,7 @@
 #include <linux/clk.h>
 #include <linux/reset.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/of.h>
 
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c
index 074b8b0..a47a7e4 100644
--- a/drivers/mtd/nand/pasemi_nand.c
+++ b/drivers/mtd/nand/pasemi_nand.c
@@ -25,7 +25,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
index 791de3e..925a132 100644
--- a/drivers/mtd/nand/plat_nand.c
+++ b/drivers/mtd/nand/plat_nand.c
@@ -15,7 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 
 struct plat_nand_data {
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 649ba82..fc4d35e 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -21,7 +21,7 @@
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index 57d483a..a77c66f 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -17,7 +17,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
 #include <linux/module.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
diff --git a/drivers/mtd/nand/r852.h b/drivers/mtd/nand/r852.h
index d042ddb..8713c57 100644
--- a/drivers/mtd/nand/r852.h
+++ b/drivers/mtd/nand/r852.h
@@ -10,7 +10,7 @@
 #include <linux/pci.h>
 #include <linux/completion.h>
 #include <linux/workqueue.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/spinlock.h>
 
 
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index f0b030d..0b2314b 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -43,7 +43,7 @@
 #include <linux/of_device.h>
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index 442ce61..492705f 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -38,7 +38,7 @@
 #include <linux/string.h>
 
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/sh_flctl.h>
 
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 064ca17..737efe8 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -17,7 +17,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/sharpsl.h>
diff --git a/drivers/mtd/nand/sm_common.c b/drivers/mtd/nand/sm_common.c
index 5939dff..c378705 100644
--- a/drivers/mtd/nand/sm_common.c
+++ b/drivers/mtd/nand/sm_common.c
@@ -7,7 +7,7 @@
  * published by the Free Software Foundation.
  */
 #include <linux/kernel.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/module.h>
 #include <linux/sizes.h>
 #include "sm_common.h"
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index 72369bd..575997d 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -13,7 +13,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c
index 118a26f..214a9c7 100644
--- a/drivers/mtd/nand/sunxi_nand.c
+++ b/drivers/mtd/nand/sunxi_nand.c
@@ -31,7 +31,7 @@
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
diff --git a/drivers/mtd/nand/tango_nand.c b/drivers/mtd/nand/tango_nand.c
index 05b6e10..906fe0f 100644
--- a/drivers/mtd/nand/tango_nand.c
+++ b/drivers/mtd/nand/tango_nand.c
@@ -11,7 +11,7 @@
 #include <linux/clk.h>
 #include <linux/iopoll.h>
 #include <linux/module.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
index fc5e773..c9dd682 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -34,7 +34,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 #include <linux/slab.h>
diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c
index 0a14fda..b567d21 100644
--- a/drivers/mtd/nand/txx9ndfmc.c
+++ b/drivers/mtd/nand/txx9ndfmc.c
@@ -16,7 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 #include <linux/io.h>
diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c
index 3ea4bb1..1bc4b08 100644
--- a/drivers/mtd/nand/vf610_nfc.c
+++ b/drivers/mtd/nand/vf610_nfc.c
@@ -31,7 +31,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/of_device.h>
 #include <linux/pinctrl/consumer.h>
diff --git a/drivers/mtd/nand/xway_nand.c b/drivers/mtd/nand/xway_nand.c
index ddee400..9926b4e 100644
--- a/drivers/mtd/nand/xway_nand.c
+++ b/drivers/mtd/nand/xway_nand.c
@@ -7,7 +7,7 @@
  *  Copyright © 2016 Hauke Mehrtens <hauke@hauke-m.de>
  */
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/of_gpio.h>
 #include <linux/of_platform.h>
 
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index e211613..1f1a611 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -34,7 +34,7 @@
 
 #include <linux/kmod.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nftl.h>
 #include <linux/mtd/blktrans.h>
 
diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c
index a5dfbfb..184c8fb 100644
--- a/drivers/mtd/nftlmount.c
+++ b/drivers/mtd/nftlmount.c
@@ -25,7 +25,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nftl.h>
 
 #define SECTORSIZE 512
diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c
index 41b13d1..95f0bf9 100644
--- a/drivers/mtd/ssfdc.c
+++ b/drivers/mtd/ssfdc.c
@@ -16,7 +16,7 @@
 #include <linux/slab.h>
 #include <linux/hdreg.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/blktrans.h>
 
 struct ssfdcr_record {
diff --git a/drivers/mtd/tests/nandbiterrs.c b/drivers/mtd/tests/nandbiterrs.c
index f26dec8..5f03b8c 100644
--- a/drivers/mtd/tests/nandbiterrs.c
+++ b/drivers/mtd/tests/nandbiterrs.c
@@ -47,7 +47,7 @@
 #include <linux/moduleparam.h>
 #include <linux/mtd/mtd.h>
 #include <linux/err.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/slab.h>
 #include "mtd_test.h"
 
diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c
index e389009..f7f6edf 100644
--- a/drivers/staging/mt29f_spinand/mt29f_spinand.c
+++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c
@@ -18,7 +18,7 @@
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/spi/spi.h>
 
 #include "mt29f_spinand.h"
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index b25d28a..48d9522 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -17,7 +17,7 @@
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
 #include <linux/crc32.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/jiffies.h>
 #include <linux/sched.h>
 #include <linux/writeback.h>
diff --git a/include/linux/mtd/nand-gpio.h b/include/linux/mtd/nand-gpio.h
index 51534e5..be4f45d 100644
--- a/include/linux/mtd/nand-gpio.h
+++ b/include/linux/mtd/nand-gpio.h
@@ -1,7 +1,7 @@
 #ifndef __LINUX_MTD_NAND_GPIO_H
 #define __LINUX_MTD_NAND_GPIO_H
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 
 struct gpio_nand_platdata {
 	int	gpio_nce;
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/rawnand.h
similarity index 99%
rename from include/linux/mtd/nand.h
rename to include/linux/mtd/rawnand.h
index f019916..fc6ed95 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1,6 +1,4 @@
 /*
- *  linux/include/linux/mtd/nand.h
- *
  *  Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org>
  *                        Steven J. Hill <sjhill@realitydiluted.com>
  *		          Thomas Gleixner <tglx@linutronix.de>
@@ -15,8 +13,8 @@
  * Changelog:
  *	See git changelog.
  */
-#ifndef __LINUX_MTD_NAND_H
-#define __LINUX_MTD_NAND_H
+#ifndef __LINUX_MTD_RAWNAND_H
+#define __LINUX_MTD_RAWNAND_H
 
 #include <linux/wait.h>
 #include <linux/spinlock.h>
@@ -1277,4 +1275,4 @@ int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 
 /* Default extended ID decoding function */
 void nand_decode_ext_id(struct nand_chip *chip);
-#endif /* __LINUX_MTD_NAND_H */
+#endif /* __LINUX_MTD_RAWNAND_H */
diff --git a/include/linux/mtd/sh_flctl.h b/include/linux/mtd/sh_flctl.h
index 2251add..c759d40 100644
--- a/include/linux/mtd/sh_flctl.h
+++ b/include/linux/mtd/sh_flctl.h
@@ -22,7 +22,7 @@
 
 #include <linux/completion.h>
 #include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/pm_qos.h>
 
diff --git a/include/linux/mtd/sharpsl.h b/include/linux/mtd/sharpsl.h
index 65e91d0..72a79c7 100644
--- a/include/linux/mtd/sharpsl.h
+++ b/include/linux/mtd/sharpsl.h
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h
index 3c8825b..d9d886f 100644
--- a/include/linux/platform_data/atmel.h
+++ b/include/linux/platform_data/atmel.h
@@ -7,7 +7,7 @@
 #ifndef __ATMEL_H__
 #define __ATMEL_H__
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/serial.h>
 
diff --git a/include/linux/platform_data/mtd-davinci.h b/include/linux/platform_data/mtd-davinci.h
index 1cf555a..f1a2cf6 100644
--- a/include/linux/platform_data/mtd-davinci.h
+++ b/include/linux/platform_data/mtd-davinci.h
@@ -28,7 +28,7 @@
 #ifndef __ARCH_ARM_DAVINCI_NAND_H
 #define __ARCH_ARM_DAVINCI_NAND_H
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 
 #define NANDFCR_OFFSET		0x60
 #define NANDFSR_OFFSET		0x64
diff --git a/include/linux/platform_data/mtd-nand-s3c2410.h b/include/linux/platform_data/mtd-nand-s3c2410.h
index f016590..f8c553f 100644
--- a/include/linux/platform_data/mtd-nand-s3c2410.h
+++ b/include/linux/platform_data/mtd-nand-s3c2410.h
@@ -12,7 +12,7 @@
 #ifndef __MTD_NAND_S3C2410_H
 #define __MTD_NAND_S3C2410_H
 
-#include <linux/mtd/nand.h>
+#include <linux/mtd/rawnand.h>
 
 /**
  * struct s3c2410_nand_set - define a set of one or more nand chips
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 02/15] mtd: nand: move raw NAND related code to the raw/ subdir
  2017-05-24  7:06 [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Peter Pan
  2017-05-24  7:06 ` [PATCH v6 01/15] mtd: nand: Rename nand.h into rawnand.h Peter Pan
@ 2017-05-24  7:06 ` Peter Pan
  2017-05-24  7:06 ` [PATCH v6 03/15] mtd: nand: add a nand.h file to expose basic NAND stuff Peter Pan
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 65+ messages in thread
From: Peter Pan @ 2017-05-24  7:06 UTC (permalink / raw)
  To: boris.brezillon, richard, computersforpeace, arnaud.mouiche,
	thomas.petazzoni, marex, cyrille.pitchen, linux-mtd
  Cc: peterpandong, peterpansjtu, linshunquan1

From: Boris Brezillon <boris.brezillon@free-electrons.com>

As part of the process of sharing more code between different NAND
based devices, we need to move all raw NAND related code to the raw/
subdirectory.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Peter Pan <peterpandong@micron.com>
---
 MAINTAINERS                                        |  18 +-
 drivers/mtd/nand/Kconfig                           | 566 +--------------------
 drivers/mtd/nand/Makefile                          |  70 +--
 drivers/mtd/nand/raw/Kconfig                       | 565 ++++++++++++++++++++
 drivers/mtd/nand/raw/Makefile                      |  69 +++
 drivers/mtd/nand/{ => raw}/ams-delta.c             |   0
 drivers/mtd/nand/{ => raw}/atmel/Makefile          |   0
 drivers/mtd/nand/{ => raw}/atmel/nand-controller.c |   0
 drivers/mtd/nand/{ => raw}/atmel/pmecc.c           |   0
 drivers/mtd/nand/{ => raw}/atmel/pmecc.h           |   0
 drivers/mtd/nand/{ => raw}/au1550nd.c              |   0
 drivers/mtd/nand/{ => raw}/bcm47xxnflash/Makefile  |   0
 .../nand/{ => raw}/bcm47xxnflash/bcm47xxnflash.h   |   0
 drivers/mtd/nand/{ => raw}/bcm47xxnflash/main.c    |   0
 .../mtd/nand/{ => raw}/bcm47xxnflash/ops_bcm4706.c |   0
 drivers/mtd/nand/{ => raw}/bf5xx_nand.c            |   0
 drivers/mtd/nand/{ => raw}/brcmnand/Makefile       |   0
 .../mtd/nand/{ => raw}/brcmnand/bcm63138_nand.c    |   0
 drivers/mtd/nand/{ => raw}/brcmnand/bcm6368_nand.c |   0
 drivers/mtd/nand/{ => raw}/brcmnand/brcmnand.c     |   0
 drivers/mtd/nand/{ => raw}/brcmnand/brcmnand.h     |   0
 drivers/mtd/nand/{ => raw}/brcmnand/brcmstb_nand.c |   0
 drivers/mtd/nand/{ => raw}/brcmnand/iproc_nand.c   |   0
 drivers/mtd/nand/{ => raw}/cafe_nand.c             |   0
 drivers/mtd/nand/{ => raw}/cmx270_nand.c           |   0
 drivers/mtd/nand/{ => raw}/cs553x_nand.c           |   0
 drivers/mtd/nand/{ => raw}/davinci_nand.c          |   0
 drivers/mtd/nand/{ => raw}/denali.c                |   0
 drivers/mtd/nand/{ => raw}/denali.h                |   0
 drivers/mtd/nand/{ => raw}/denali_dt.c             |   0
 drivers/mtd/nand/{ => raw}/denali_pci.c            |   0
 drivers/mtd/nand/{ => raw}/diskonchip.c            |   0
 drivers/mtd/nand/{ => raw}/docg4.c                 |   0
 drivers/mtd/nand/{ => raw}/fsl_elbc_nand.c         |   0
 drivers/mtd/nand/{ => raw}/fsl_ifc_nand.c          |   0
 drivers/mtd/nand/{ => raw}/fsl_upm.c               |   0
 drivers/mtd/nand/{ => raw}/fsmc_nand.c             |   0
 drivers/mtd/nand/{ => raw}/gpio.c                  |   0
 drivers/mtd/nand/{ => raw}/gpmi-nand/Makefile      |   0
 drivers/mtd/nand/{ => raw}/gpmi-nand/bch-regs.h    |   0
 drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-lib.c    |   0
 drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-nand.c   |   0
 drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-nand.h   |   0
 drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-regs.h   |   0
 drivers/mtd/nand/{ => raw}/hisi504_nand.c          |   0
 drivers/mtd/nand/{ => raw}/jz4740_nand.c           |   0
 drivers/mtd/nand/{ => raw}/jz4780_bch.c            |   0
 drivers/mtd/nand/{ => raw}/jz4780_bch.h            |   0
 drivers/mtd/nand/{ => raw}/jz4780_nand.c           |   0
 drivers/mtd/nand/{ => raw}/lpc32xx_mlc.c           |   0
 drivers/mtd/nand/{ => raw}/lpc32xx_slc.c           |   0
 drivers/mtd/nand/{ => raw}/mpc5121_nfc.c           |   0
 drivers/mtd/nand/{ => raw}/mtk_ecc.c               |   0
 drivers/mtd/nand/{ => raw}/mtk_ecc.h               |   0
 drivers/mtd/nand/{ => raw}/mtk_nand.c              |   0
 drivers/mtd/nand/{ => raw}/mxc_nand.c              |   0
 drivers/mtd/nand/{ => raw}/nand_amd.c              |   0
 drivers/mtd/nand/{ => raw}/nand_base.c             |   0
 drivers/mtd/nand/{ => raw}/nand_bbt.c              |   0
 drivers/mtd/nand/{ => raw}/nand_bch.c              |   0
 drivers/mtd/nand/{ => raw}/nand_ecc.c              |   0
 drivers/mtd/nand/{ => raw}/nand_hynix.c            |   0
 drivers/mtd/nand/{ => raw}/nand_ids.c              |   0
 drivers/mtd/nand/{ => raw}/nand_macronix.c         |   0
 drivers/mtd/nand/{ => raw}/nand_micron.c           |   0
 drivers/mtd/nand/{ => raw}/nand_samsung.c          |   0
 drivers/mtd/nand/{ => raw}/nand_timings.c          |   0
 drivers/mtd/nand/{ => raw}/nand_toshiba.c          |   0
 drivers/mtd/nand/{ => raw}/nandsim.c               |   0
 drivers/mtd/nand/{ => raw}/ndfc.c                  |   0
 drivers/mtd/nand/{ => raw}/nuc900_nand.c           |   0
 drivers/mtd/nand/{ => raw}/omap2.c                 |   0
 drivers/mtd/nand/{ => raw}/omap_elm.c              |   0
 drivers/mtd/nand/{ => raw}/orion_nand.c            |   0
 drivers/mtd/nand/{ => raw}/oxnas_nand.c            |   0
 drivers/mtd/nand/{ => raw}/pasemi_nand.c           |   0
 drivers/mtd/nand/{ => raw}/plat_nand.c             |   0
 drivers/mtd/nand/{ => raw}/pxa3xx_nand.c           |   0
 drivers/mtd/nand/{ => raw}/qcom_nandc.c            |   0
 drivers/mtd/nand/{ => raw}/r852.c                  |   0
 drivers/mtd/nand/{ => raw}/r852.h                  |   0
 drivers/mtd/nand/{ => raw}/s3c2410.c               |   0
 drivers/mtd/nand/{ => raw}/sh_flctl.c              |   0
 drivers/mtd/nand/{ => raw}/sharpsl.c               |   0
 drivers/mtd/nand/{ => raw}/sm_common.c             |   0
 drivers/mtd/nand/{ => raw}/sm_common.h             |   0
 drivers/mtd/nand/{ => raw}/socrates_nand.c         |   0
 drivers/mtd/nand/{ => raw}/sunxi_nand.c            |   0
 drivers/mtd/nand/{ => raw}/tango_nand.c            |   0
 drivers/mtd/nand/{ => raw}/tmio_nand.c             |   0
 drivers/mtd/nand/{ => raw}/txx9ndfmc.c             |   0
 drivers/mtd/nand/{ => raw}/vf610_nfc.c             |   0
 drivers/mtd/nand/{ => raw}/xway_nand.c             |   0
 drivers/mtd/sm_ftl.c                               |   2 +-
 94 files changed, 646 insertions(+), 644 deletions(-)
 create mode 100644 drivers/mtd/nand/raw/Kconfig
 create mode 100644 drivers/mtd/nand/raw/Makefile
 rename drivers/mtd/nand/{ => raw}/ams-delta.c (100%)
 rename drivers/mtd/nand/{ => raw}/atmel/Makefile (100%)
 rename drivers/mtd/nand/{ => raw}/atmel/nand-controller.c (100%)
 rename drivers/mtd/nand/{ => raw}/atmel/pmecc.c (100%)
 rename drivers/mtd/nand/{ => raw}/atmel/pmecc.h (100%)
 rename drivers/mtd/nand/{ => raw}/au1550nd.c (100%)
 rename drivers/mtd/nand/{ => raw}/bcm47xxnflash/Makefile (100%)
 rename drivers/mtd/nand/{ => raw}/bcm47xxnflash/bcm47xxnflash.h (100%)
 rename drivers/mtd/nand/{ => raw}/bcm47xxnflash/main.c (100%)
 rename drivers/mtd/nand/{ => raw}/bcm47xxnflash/ops_bcm4706.c (100%)
 rename drivers/mtd/nand/{ => raw}/bf5xx_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/brcmnand/Makefile (100%)
 rename drivers/mtd/nand/{ => raw}/brcmnand/bcm63138_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/brcmnand/bcm6368_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/brcmnand/brcmnand.c (100%)
 rename drivers/mtd/nand/{ => raw}/brcmnand/brcmnand.h (100%)
 rename drivers/mtd/nand/{ => raw}/brcmnand/brcmstb_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/brcmnand/iproc_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/cafe_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/cmx270_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/cs553x_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/davinci_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/denali.c (100%)
 rename drivers/mtd/nand/{ => raw}/denali.h (100%)
 rename drivers/mtd/nand/{ => raw}/denali_dt.c (100%)
 rename drivers/mtd/nand/{ => raw}/denali_pci.c (100%)
 rename drivers/mtd/nand/{ => raw}/diskonchip.c (100%)
 rename drivers/mtd/nand/{ => raw}/docg4.c (100%)
 rename drivers/mtd/nand/{ => raw}/fsl_elbc_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/fsl_ifc_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/fsl_upm.c (100%)
 rename drivers/mtd/nand/{ => raw}/fsmc_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/gpio.c (100%)
 rename drivers/mtd/nand/{ => raw}/gpmi-nand/Makefile (100%)
 rename drivers/mtd/nand/{ => raw}/gpmi-nand/bch-regs.h (100%)
 rename drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-lib.c (100%)
 rename drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-nand.h (100%)
 rename drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-regs.h (100%)
 rename drivers/mtd/nand/{ => raw}/hisi504_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/jz4740_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/jz4780_bch.c (100%)
 rename drivers/mtd/nand/{ => raw}/jz4780_bch.h (100%)
 rename drivers/mtd/nand/{ => raw}/jz4780_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/lpc32xx_mlc.c (100%)
 rename drivers/mtd/nand/{ => raw}/lpc32xx_slc.c (100%)
 rename drivers/mtd/nand/{ => raw}/mpc5121_nfc.c (100%)
 rename drivers/mtd/nand/{ => raw}/mtk_ecc.c (100%)
 rename drivers/mtd/nand/{ => raw}/mtk_ecc.h (100%)
 rename drivers/mtd/nand/{ => raw}/mtk_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/mxc_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/nand_amd.c (100%)
 rename drivers/mtd/nand/{ => raw}/nand_base.c (100%)
 rename drivers/mtd/nand/{ => raw}/nand_bbt.c (100%)
 rename drivers/mtd/nand/{ => raw}/nand_bch.c (100%)
 rename drivers/mtd/nand/{ => raw}/nand_ecc.c (100%)
 rename drivers/mtd/nand/{ => raw}/nand_hynix.c (100%)
 rename drivers/mtd/nand/{ => raw}/nand_ids.c (100%)
 rename drivers/mtd/nand/{ => raw}/nand_macronix.c (100%)
 rename drivers/mtd/nand/{ => raw}/nand_micron.c (100%)
 rename drivers/mtd/nand/{ => raw}/nand_samsung.c (100%)
 rename drivers/mtd/nand/{ => raw}/nand_timings.c (100%)
 rename drivers/mtd/nand/{ => raw}/nand_toshiba.c (100%)
 rename drivers/mtd/nand/{ => raw}/nandsim.c (100%)
 rename drivers/mtd/nand/{ => raw}/ndfc.c (100%)
 rename drivers/mtd/nand/{ => raw}/nuc900_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/omap2.c (100%)
 rename drivers/mtd/nand/{ => raw}/omap_elm.c (100%)
 rename drivers/mtd/nand/{ => raw}/orion_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/oxnas_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/pasemi_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/plat_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/pxa3xx_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/qcom_nandc.c (100%)
 rename drivers/mtd/nand/{ => raw}/r852.c (100%)
 rename drivers/mtd/nand/{ => raw}/r852.h (100%)
 rename drivers/mtd/nand/{ => raw}/s3c2410.c (100%)
 rename drivers/mtd/nand/{ => raw}/sh_flctl.c (100%)
 rename drivers/mtd/nand/{ => raw}/sharpsl.c (100%)
 rename drivers/mtd/nand/{ => raw}/sm_common.c (100%)
 rename drivers/mtd/nand/{ => raw}/sm_common.h (100%)
 rename drivers/mtd/nand/{ => raw}/socrates_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/sunxi_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/tango_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/tmio_nand.c (100%)
 rename drivers/mtd/nand/{ => raw}/txx9ndfmc.c (100%)
 rename drivers/mtd/nand/{ => raw}/vf610_nfc.c (100%)
 rename drivers/mtd/nand/{ => raw}/xway_nand.c (100%)

diff --git a/MAINTAINERS b/MAINTAINERS
index 81bb063..fe4b69e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1899,7 +1899,7 @@ F:	drivers/input/keyboard/w90p910_keypad.c
 F:	drivers/input/touchscreen/w90p910_ts.c
 F:	drivers/watchdog/nuc900_wdt.c
 F:	drivers/net/ethernet/nuvoton/w90p910_ether.c
-F:	drivers/mtd/nand/nuc900_nand.c
+F:	drivers/mtd/nand/raw/nuc900_nand.c
 F:	drivers/rtc/rtc-nuc900.c
 F:	drivers/spi/spi-nuc900.c
 F:	drivers/usb/host/ehci-w90x900.c
@@ -2274,7 +2274,7 @@ M:	Wenyou Yang <wenyou.yang@atmel.com>
 M:	Josh Wu <rainyfeeling@outlook.com>
 L:	linux-mtd@lists.infradead.org
 S:	Supported
-F:	drivers/mtd/nand/atmel/*
+F:	drivers/mtd/nand/raw/atmel/*
 
 ATMEL SDMMC DRIVER
 M:	Ludovic Desroches <ludovic.desroches@microchip.com>
@@ -2854,7 +2854,7 @@ M:	Kamal Dasu <kdasu.kdev@gmail.com>
 L:	linux-mtd@lists.infradead.org
 L:	bcm-kernel-feedback-list@broadcom.com
 S:	Maintained
-F:	drivers/mtd/nand/brcmnand/
+F:	drivers/mtd/nand/raw/brcmnand/
 
 BROADCOM STB AVS CPUFREQ DRIVER
 M:	Markus Mayer <mmayer@broadcom.com>
@@ -5285,7 +5285,7 @@ FREESCALE GPMI NAND DRIVER
 M:	Han Xu <han.xu@nxp.com>
 L:	linux-mtd@lists.infradead.org
 S:	Maintained
-F:	drivers/mtd/nand/gpmi-nand/*
+F:	drivers/mtd/nand/raw/gpmi-nand/*
 
 FREESCALE I2C CPM DRIVER
 M:	Jochen Friedrich <jochen@scram.de>
@@ -6534,7 +6534,7 @@ INGENIC JZ4780 NAND DRIVER
 M:	Harvey Hunt <harveyhuntnexus@gmail.com>
 L:	linux-mtd@lists.infradead.org
 S:	Maintained
-F:	drivers/mtd/nand/jz4780_*
+F:	drivers/mtd/nand/raw/jz4780_*
 
 INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
 M:	Mimi Zohar <zohar@linux.vnet.ibm.com>
@@ -10430,7 +10430,7 @@ PXA3xx NAND FLASH DRIVER
 M:	Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
 L:	linux-mtd@lists.infradead.org
 S:	Maintained
-F:	drivers/mtd/nand/pxa3xx_nand.c
+F:	drivers/mtd/nand/raw/pxa3xx_nand.c
 
 MMP SUPPORT
 M:	Eric Miao <eric.y.miao@gmail.com>
@@ -10866,8 +10866,8 @@ F:	include/linux/rhashtable.h
 RICOH SMARTMEDIA/XD DRIVER
 M:	Maxim Levitsky <maximlevitsky@gmail.com>
 S:	Maintained
-F:	drivers/mtd/nand/r852.c
-F:	drivers/mtd/nand/r852.h
+F:	drivers/mtd/nand/raw/r852.c
+F:	drivers/mtd/nand/raw/r852.h
 
 RICOH R5C592 MEMORYSTICK DRIVER
 M:	Maxim Levitsky <maximlevitsky@gmail.com>
@@ -13472,7 +13472,7 @@ VF610 NAND DRIVER
 M:	Stefan Agner <stefan@agner.ch>
 L:	linux-mtd@lists.infradead.org
 S:	Supported
-F:	drivers/mtd/nand/vf610_nfc.c
+F:	drivers/mtd/nand/raw/vf610_nfc.c
 
 VFAT/FAT/MSDOS FILESYSTEM
 M:	OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 0bd2319..6d53734 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -1,565 +1 @@
-config MTD_NAND_ECC
-	tristate
-
-config MTD_NAND_ECC_SMC
-	bool "NAND ECC Smart Media byte order"
-	depends on MTD_NAND_ECC
-	default n
-	help
-	  Software ECC according to the Smart Media Specification.
-	  The original Linux implementation had byte 0 and 1 swapped.
-
-
-menuconfig MTD_NAND
-	tristate "NAND Device Support"
-	depends on MTD
-	select MTD_NAND_ECC
-	help
-	  This enables support for accessing all type of NAND flash
-	  devices. For further information see
-	  <http://www.linux-mtd.infradead.org/doc/nand.html>.
-
-if MTD_NAND
-
-config MTD_NAND_BCH
-	tristate
-	select BCH
-	depends on MTD_NAND_ECC_BCH
-	default MTD_NAND
-
-config MTD_NAND_ECC_BCH
-	bool "Support software BCH ECC"
-	default n
-	help
-	  This enables support for software BCH error correction. Binary BCH
-	  codes are more powerful and cpu intensive than traditional Hamming
-	  ECC codes. They are used with NAND devices requiring more than 1 bit
-	  of error correction.
-
-config MTD_SM_COMMON
-	tristate
-	default n
-
-config MTD_NAND_DENALI
-	tristate
-
-config MTD_NAND_DENALI_PCI
-        tristate "Support Denali NAND controller on Intel Moorestown"
-	select MTD_NAND_DENALI
-	depends on HAS_DMA && PCI
-        help
-          Enable the driver for NAND flash on Intel Moorestown, using the
-          Denali NAND controller core.
-
-config MTD_NAND_DENALI_DT
-	tristate "Support Denali NAND controller as a DT device"
-	select MTD_NAND_DENALI
-	depends on HAS_DMA && HAVE_CLK && OF
-	help
-	  Enable the driver for NAND flash on platforms using a Denali NAND
-	  controller as a DT device.
-
-config MTD_NAND_GPIO
-	tristate "GPIO assisted NAND Flash driver"
-	depends on GPIOLIB || COMPILE_TEST
-	depends on HAS_IOMEM
-	help
-	  This enables a NAND flash driver where control signals are
-	  connected to GPIO pins, and commands and data are communicated
-	  via a memory mapped interface.
-
-config MTD_NAND_AMS_DELTA
-	tristate "NAND Flash device on Amstrad E3"
-	depends on MACH_AMS_DELTA
-	default y
-	help
-	  Support for NAND flash on Amstrad E3 (Delta).
-
-config MTD_NAND_OMAP2
-	tristate "NAND Flash device on OMAP2, OMAP3, OMAP4 and Keystone"
-	depends on (ARCH_OMAP2PLUS || ARCH_KEYSTONE)
-	help
-          Support for NAND flash on Texas Instruments OMAP2, OMAP3, OMAP4
-	  and Keystone platforms.
-
-config MTD_NAND_OMAP_BCH
-	depends on MTD_NAND_OMAP2
-	bool "Support hardware based BCH error correction"
-	default n
-	select BCH
-	help
-	  This config enables the ELM hardware engine, which can be used to
-	  locate and correct errors when using BCH ECC scheme. This offloads
-	  the cpu from doing ECC error searching and correction. However some
-	  legacy OMAP families like OMAP2xxx, OMAP3xxx do not have ELM engine
-	  so this is optional for them.
-
-config MTD_NAND_OMAP_BCH_BUILD
-	def_tristate MTD_NAND_OMAP2 && MTD_NAND_OMAP_BCH
-
-config MTD_NAND_RICOH
-	tristate "Ricoh xD card reader"
-	default n
-	depends on PCI
-	select MTD_SM_COMMON
-	help
-	  Enable support for Ricoh R5C852 xD card reader
-	  You also need to enable ether
-	  NAND SSFDC (SmartMedia) read only translation layer' or new
-	  expermental, readwrite
-	  'SmartMedia/xD new translation layer'
-
-config MTD_NAND_AU1550
-	tristate "Au1550/1200 NAND support"
-	depends on MIPS_ALCHEMY
-	help
-	  This enables the driver for the NAND flash controller on the
-	  AMD/Alchemy 1550 SOC.
-
-config MTD_NAND_BF5XX
-	tristate "Blackfin on-chip NAND Flash Controller driver"
-	depends on BF54x || BF52x
-	help
-	  This enables the Blackfin on-chip NAND flash controller
-
-	  No board specific support is done by this driver, each board
-	  must advertise a platform_device for the driver to attach.
-
-	  This driver can also be built as a module. If so, the module
-	  will be called bf5xx-nand.
-
-config MTD_NAND_BF5XX_HWECC
-	bool "BF5XX NAND Hardware ECC"
-	default y
-	depends on MTD_NAND_BF5XX
-	help
-	  Enable the use of the BF5XX's internal ECC generator when
-	  using NAND.
-
-config MTD_NAND_BF5XX_BOOTROM_ECC
-	bool "Use Blackfin BootROM ECC Layout"
-	default n
-	depends on MTD_NAND_BF5XX_HWECC
-	help
-	  If you wish to modify NAND pages and allow the Blackfin on-chip
-	  BootROM to boot from them, say Y here.  This is only necessary
-	  if you are booting U-Boot out of NAND and you wish to update
-	  U-Boot from Linux' userspace.  Otherwise, you should say N here.
-
-	  If unsure, say N.
-
-config MTD_NAND_S3C2410
-	tristate "NAND Flash support for Samsung S3C SoCs"
-	depends on ARCH_S3C24XX || ARCH_S3C64XX
-	help
-	  This enables the NAND flash controller on the S3C24xx and S3C64xx
-	  SoCs
-
-	  No board specific support is done by this driver, each board
-	  must advertise a platform_device for the driver to attach.
-
-config MTD_NAND_S3C2410_DEBUG
-	bool "Samsung S3C NAND driver debug"
-	depends on MTD_NAND_S3C2410
-	help
-	  Enable debugging of the S3C NAND driver
-
-config MTD_NAND_NDFC
-	tristate "NDFC NanD Flash Controller"
-	depends on 4xx
-	select MTD_NAND_ECC_SMC
-	help
-	 NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs
-
-config MTD_NAND_S3C2410_CLKSTOP
-	bool "Samsung S3C NAND IDLE clock stop"
-	depends on MTD_NAND_S3C2410
-	default n
-	help
-	  Stop the clock to the NAND controller when there is no chip
-	  selected to save power. This will mean there is a small delay
-	  when the is NAND chip selected or released, but will save
-	  approximately 5mA of power when there is nothing happening.
-
-config MTD_NAND_TANGO
-	tristate "NAND Flash support for Tango chips"
-	depends on ARCH_TANGO || COMPILE_TEST
-	depends on HAS_DMA
-	help
-	  Enables the NAND Flash controller on Tango chips.
-
-config MTD_NAND_DISKONCHIP
-	tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation)"
-	depends on HAS_IOMEM
-	select REED_SOLOMON
-	select REED_SOLOMON_DEC16
-	help
-	  This is a reimplementation of M-Systems DiskOnChip 2000,
-	  Millennium and Millennium Plus as a standard NAND device driver,
-	  as opposed to the earlier self-contained MTD device drivers.
-	  This should enable, among other things, proper JFFS2 operation on
-	  these devices.
-
-config MTD_NAND_DISKONCHIP_PROBE_ADVANCED
-        bool "Advanced detection options for DiskOnChip"
-        depends on MTD_NAND_DISKONCHIP
-        help
-          This option allows you to specify nonstandard address at which to
-          probe for a DiskOnChip, or to change the detection options.  You
-          are unlikely to need any of this unless you are using LinuxBIOS.
-          Say 'N'.
-
-config MTD_NAND_DISKONCHIP_PROBE_ADDRESS
-        hex "Physical address of DiskOnChip" if MTD_NAND_DISKONCHIP_PROBE_ADVANCED
-        depends on MTD_NAND_DISKONCHIP
-        default "0"
-        ---help---
-        By default, the probe for DiskOnChip devices will look for a
-        DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
-        This option allows you to specify a single address at which to probe
-        for the device, which is useful if you have other devices in that
-        range which get upset when they are probed.
-
-        (Note that on PowerPC, the normal probe will only check at
-        0xE4000000.)
-
-        Normally, you should leave this set to zero, to allow the probe at
-        the normal addresses.
-
-config MTD_NAND_DISKONCHIP_PROBE_HIGH
-        bool "Probe high addresses"
-        depends on MTD_NAND_DISKONCHIP_PROBE_ADVANCED
-        help
-          By default, the probe for DiskOnChip devices will look for a
-          DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
-          This option changes to make it probe between 0xFFFC8000 and
-          0xFFFEE000.  Unless you are using LinuxBIOS, this is unlikely to be
-          useful to you.  Say 'N'.
-
-config MTD_NAND_DISKONCHIP_BBTWRITE
-	bool "Allow BBT writes on DiskOnChip Millennium and 2000TSOP"
-	depends on MTD_NAND_DISKONCHIP
-	help
-	  On DiskOnChip devices shipped with the INFTL filesystem (Millennium
-	  and 2000 TSOP/Alon), Linux reserves some space at the end of the
-	  device for the Bad Block Table (BBT).  If you have existing INFTL
-	  data on your device (created by non-Linux tools such as M-Systems'
-	  DOS drivers), your data might overlap the area Linux wants to use for
-	  the BBT.  If this is a concern for you, leave this option disabled and
-	  Linux will not write BBT data into this area.
-	  The downside of leaving this option disabled is that if bad blocks
-	  are detected by Linux, they will not be recorded in the BBT, which
-	  could cause future problems.
-	  Once you enable this option, new filesystems (INFTL or others, created
-	  in Linux or other operating systems) will not use the reserved area.
-	  The only reason not to enable this option is to prevent damage to
-	  preexisting filesystems.
-	  Even if you leave this disabled, you can enable BBT writes at module
-	  load time (assuming you build diskonchip as a module) with the module
-	  parameter "inftl_bbt_write=1".
-
-config MTD_NAND_DOCG4
-	tristate "Support for DiskOnChip G4"
-	depends on HAS_IOMEM
-	select BCH
-	select BITREVERSE
-	help
-	  Support for diskonchip G4 nand flash, found in various smartphones and
-	  PDAs, among them the Palm Treo680, HTC Prophet and Wizard, Toshiba
-	  Portege G900, Asus P526, and O2 XDA Zinc.
-
-	  With this driver you will be able to use UBI and create a ubifs on the
-	  device, so you may wish to consider enabling UBI and UBIFS as well.
-
-	  These devices ship with the Mys/Sandisk SAFTL formatting, for which
-	  there is currently no mtd parser, so you may want to use command line
-	  partitioning to segregate write-protected blocks. On the Treo680, the
-	  first five erase blocks (256KiB each) are write-protected, followed
-	  by the block containing the saftl partition table.  This is probably
-	  typical.
-
-config MTD_NAND_SHARPSL
-	tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
-	depends on ARCH_PXA
-
-config MTD_NAND_CAFE
-	tristate "NAND support for OLPC CAFÉ chip"
-	depends on PCI
-	select REED_SOLOMON
-	select REED_SOLOMON_DEC16
-	help
-	  Use NAND flash attached to the CAFÉ chip designed for the OLPC
-	  laptop.
-
-config MTD_NAND_CS553X
-	tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)"
-	depends on X86_32
-	depends on !UML && HAS_IOMEM
-	help
-	  The CS553x companion chips for the AMD Geode processor
-	  include NAND flash controllers with built-in hardware ECC
-	  capabilities; enabling this option will allow you to use
-	  these. The driver will check the MSRs to verify that the
-	  controller is enabled for NAND, and currently requires that
-	  the controller be in MMIO mode.
-
-	  If you say "m", the module will be called cs553x_nand.
-
-config MTD_NAND_ATMEL
-	tristate "Support for NAND Flash / SmartMedia on AT91"
-	depends on ARCH_AT91
-	help
-	  Enables support for NAND Flash / Smart Media Card interface
-	  on Atmel AT91 processors.
-
-config MTD_NAND_PXA3xx
-	tristate "NAND support on PXA3xx and Armada 370/XP"
-	depends on PXA3xx || ARCH_MMP || PLAT_ORION
-	help
-	  This enables the driver for the NAND flash device found on
-	  PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2).
-
-config MTD_NAND_SLC_LPC32XX
-	tristate "NXP LPC32xx SLC Controller"
-	depends on ARCH_LPC32XX
-	help
-	  Enables support for NXP's LPC32XX SLC (i.e. for Single Level Cell
-	  chips) NAND controller. This is the default for the PHYTEC 3250
-	  reference board which contains a NAND256R3A2CZA6 chip.
-
-	  Please check the actual NAND chip connected and its support
-	  by the SLC NAND controller.
-
-config MTD_NAND_MLC_LPC32XX
-	tristate "NXP LPC32xx MLC Controller"
-	depends on ARCH_LPC32XX
-	help
-	  Uses the LPC32XX MLC (i.e. for Multi Level Cell chips) NAND
-	  controller. This is the default for the WORK92105 controller
-	  board.
-
-	  Please check the actual NAND chip connected and its support
-	  by the MLC NAND controller.
-
-config MTD_NAND_CM_X270
-	tristate "Support for NAND Flash on CM-X270 modules"
-	depends on MACH_ARMCORE
-
-config MTD_NAND_PASEMI
-	tristate "NAND support for PA Semi PWRficient"
-	depends on PPC_PASEMI
-	help
-	  Enables support for NAND Flash interface on PA Semi PWRficient
-	  based boards
-
-config MTD_NAND_TMIO
-	tristate "NAND Flash device on Toshiba Mobile IO Controller"
-	depends on MFD_TMIO
-	help
-	  Support for NAND flash connected to a Toshiba Mobile IO
-	  Controller in some PDAs, including the Sharp SL6000x.
-
-config MTD_NAND_NANDSIM
-	tristate "Support for NAND Flash Simulator"
-	help
-	  The simulator may simulate various NAND flash chips for the
-	  MTD nand layer.
-
-config MTD_NAND_GPMI_NAND
-        tristate "GPMI NAND Flash Controller driver"
-        depends on MTD_NAND && MXS_DMA
-        help
-	 Enables NAND Flash support for IMX23, IMX28 or IMX6.
-	 The GPMI controller is very powerful, with the help of BCH
-	 module, it can do the hardware ECC. The GPMI supports several
-	 NAND flashs at the same time. The GPMI may conflicts with other
-	 block, such as SD card. So pay attention to it when you enable
-	 the GPMI.
-
-config MTD_NAND_BRCMNAND
-	tristate "Broadcom STB NAND controller"
-	depends on ARM || ARM64 || MIPS
-	help
-	  Enables the Broadcom NAND controller driver. The controller was
-	  originally designed for Set-Top Box but is used on various BCM7xxx,
-	  BCM3xxx, BCM63xxx, iProc/Cygnus and more.
-
-config MTD_NAND_BCM47XXNFLASH
-	tristate "Support for NAND flash on BCM4706 BCMA bus"
-	depends on BCMA_NFLASH
-	help
-	  BCMA bus can have various flash memories attached, they are
-	  registered by bcma as platform devices. This enables driver for
-	  NAND flash memories. For now only BCM4706 is supported.
-
-config MTD_NAND_PLATFORM
-	tristate "Support for generic platform NAND driver"
-	depends on HAS_IOMEM
-	help
-	  This implements a generic NAND driver for on-SOC platform
-	  devices. You will need to provide platform-specific functions
-	  via platform_data.
-
-config MTD_NAND_ORION
-	tristate "NAND Flash support for Marvell Orion SoC"
-	depends on PLAT_ORION
-	help
-	  This enables the NAND flash controller on Orion machines.
-
-	  No board specific support is done by this driver, each board
-	  must advertise a platform_device for the driver to attach.
-
-config MTD_NAND_OXNAS
-	tristate "NAND Flash support for Oxford Semiconductor SoC"
-	depends on ARCH_OXNAS || COMPILE_TEST
-	depends on HAS_IOMEM
-	help
-	  This enables the NAND flash controller on Oxford Semiconductor SoCs.
-
-config MTD_NAND_FSL_ELBC
-	tristate "NAND support for Freescale eLBC controllers"
-	depends on FSL_SOC
-	select FSL_LBC
-	help
-	  Various Freescale chips, including the 8313, include a NAND Flash
-	  Controller Module with built-in hardware ECC capabilities.
-	  Enabling this option will enable you to use this to control
-	  external NAND devices.
-
-config MTD_NAND_FSL_IFC
-	tristate "NAND support for Freescale IFC controller"
-	depends on FSL_SOC || ARCH_LAYERSCAPE || SOC_LS1021A
-	select FSL_IFC
-	select MEMORY
-	help
-	  Various Freescale chips e.g P1010, include a NAND Flash machine
-	  with built-in hardware ECC capabilities.
-	  Enabling this option will enable you to use this to control
-	  external NAND devices.
-
-config MTD_NAND_FSL_UPM
-	tristate "Support for NAND on Freescale UPM"
-	depends on PPC_83xx || PPC_85xx
-	select FSL_LBC
-	help
-	  Enables support for NAND Flash chips wired onto Freescale PowerPC
-	  processor localbus with User-Programmable Machine support.
-
-config MTD_NAND_MPC5121_NFC
-	tristate "MPC5121 built-in NAND Flash Controller support"
-	depends on PPC_MPC512x
-	help
-	  This enables the driver for the NAND flash controller on the
-	  MPC5121 SoC.
-
-config MTD_NAND_VF610_NFC
-	tristate "Support for Freescale NFC for VF610/MPC5125"
-	depends on (SOC_VF610 || COMPILE_TEST)
-	depends on HAS_IOMEM
-	help
-	  Enables support for NAND Flash Controller on some Freescale
-	  processors like the VF610, MPC5125, MCF54418 or Kinetis K70.
-	  The driver supports a maximum 2k page size. With 2k pages and
-	  64 bytes or more of OOB, hardware ECC with up to 32-bit error
-	  correction is supported. Hardware ECC is only enabled through
-	  device tree.
-
-config MTD_NAND_MXC
-	tristate "MXC NAND support"
-	depends on ARCH_MXC
-	help
-	  This enables the driver for the NAND flash controller on the
-	  MXC processors.
-
-config MTD_NAND_SH_FLCTL
-	tristate "Support for NAND on Renesas SuperH FLCTL"
-	depends on SUPERH || COMPILE_TEST
-	depends on HAS_IOMEM
-	depends on HAS_DMA
-	help
-	  Several Renesas SuperH CPU has FLCTL. This option enables support
-	  for NAND Flash using FLCTL.
-
-config MTD_NAND_DAVINCI
-        tristate "Support NAND on DaVinci/Keystone SoC"
-        depends on ARCH_DAVINCI || (ARCH_KEYSTONE && TI_AEMIF)
-        help
-	  Enable the driver for NAND flash chips on Texas Instruments
-	  DaVinci/Keystone processors.
-
-config MTD_NAND_TXX9NDFMC
-	tristate "NAND Flash support for TXx9 SoC"
-	depends on SOC_TX4938 || SOC_TX4939
-	help
-	  This enables the NAND flash controller on the TXx9 SoCs.
-
-config MTD_NAND_SOCRATES
-	tristate "Support for NAND on Socrates board"
-	depends on SOCRATES
-	help
-	  Enables support for NAND Flash chips wired onto Socrates board.
-
-config MTD_NAND_NUC900
-	tristate "Support for NAND on Nuvoton NUC9xx/w90p910 evaluation boards."
-	depends on ARCH_W90X900
-	help
-	  This enables the driver for the NAND Flash on evaluation board based
-	  on w90p910 / NUC9xx.
-
-config MTD_NAND_JZ4740
-	tristate "Support for JZ4740 SoC NAND controller"
-	depends on MACH_JZ4740
-	help
-		Enables support for NAND Flash on JZ4740 SoC based boards.
-
-config MTD_NAND_JZ4780
-	tristate "Support for NAND on JZ4780 SoC"
-	depends on MACH_JZ4780 && JZ4780_NEMC
-	help
-	  Enables support for NAND Flash connected to the NEMC on JZ4780 SoC
-	  based boards, using the BCH controller for hardware error correction.
-
-config MTD_NAND_FSMC
-	tristate "Support for NAND on ST Micros FSMC"
-	depends on OF
-	depends on PLAT_SPEAR || ARCH_NOMADIK || ARCH_U8500 || MACH_U300
-	help
-	  Enables support for NAND Flash chips on the ST Microelectronics
-	  Flexible Static Memory Controller (FSMC)
-
-config MTD_NAND_XWAY
-	bool "Support for NAND on Lantiq XWAY SoC"
-	depends on LANTIQ && SOC_TYPE_XWAY
-	help
-	  Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached
-	  to the External Bus Unit (EBU).
-
-config MTD_NAND_SUNXI
-	tristate "Support for NAND on Allwinner SoCs"
-	depends on ARCH_SUNXI
-	help
-	  Enables support for NAND Flash chips on Allwinner SoCs.
-
-config MTD_NAND_HISI504
-	tristate "Support for NAND controller on Hisilicon SoC Hip04"
-	depends on ARCH_HISI || COMPILE_TEST
-	depends on HAS_DMA
-	help
-	  Enables support for NAND controller on Hisilicon SoC Hip04.
-
-config MTD_NAND_QCOM
-	tristate "Support for NAND on QCOM SoCs"
-	depends on ARCH_QCOM
-	help
-	  Enables support for NAND flash chips on SoCs containing the EBI2 NAND
-	  controller. This controller is found on IPQ806x SoC.
-
-config MTD_NAND_MTK
-	tristate "Support for NAND controller on MTK SoCs"
-	depends on ARCH_MEDIATEK || COMPILE_TEST
-	depends on HAS_DMA
-	help
-	  Enables support for NAND controller on MTK SoCs.
-	  This controller is found on mt27xx, mt81xx, mt65xx SoCs.
-
-endif # MTD_NAND
+source "drivers/mtd/nand/raw/Kconfig"
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index ade5fc4..eee2f27 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -1,69 +1 @@
-#
-# linux/drivers/nand/Makefile
-#
-
-obj-$(CONFIG_MTD_NAND)			+= nand.o
-obj-$(CONFIG_MTD_NAND_ECC)		+= nand_ecc.o
-obj-$(CONFIG_MTD_NAND_BCH)		+= nand_bch.o
-obj-$(CONFIG_MTD_SM_COMMON) 		+= sm_common.o
-
-obj-$(CONFIG_MTD_NAND_CAFE)		+= cafe_nand.o
-obj-$(CONFIG_MTD_NAND_AMS_DELTA)	+= ams-delta.o
-obj-$(CONFIG_MTD_NAND_DENALI)		+= denali.o
-obj-$(CONFIG_MTD_NAND_DENALI_PCI)	+= denali_pci.o
-obj-$(CONFIG_MTD_NAND_DENALI_DT)	+= denali_dt.o
-obj-$(CONFIG_MTD_NAND_AU1550)		+= au1550nd.o
-obj-$(CONFIG_MTD_NAND_BF5XX)		+= bf5xx_nand.o
-obj-$(CONFIG_MTD_NAND_S3C2410)		+= s3c2410.o
-obj-$(CONFIG_MTD_NAND_TANGO)		+= tango_nand.o
-obj-$(CONFIG_MTD_NAND_DAVINCI)		+= davinci_nand.o
-obj-$(CONFIG_MTD_NAND_DISKONCHIP)	+= diskonchip.o
-obj-$(CONFIG_MTD_NAND_DOCG4)		+= docg4.o
-obj-$(CONFIG_MTD_NAND_FSMC)		+= fsmc_nand.o
-obj-$(CONFIG_MTD_NAND_SHARPSL)		+= sharpsl.o
-obj-$(CONFIG_MTD_NAND_NANDSIM)		+= nandsim.o
-obj-$(CONFIG_MTD_NAND_CS553X)		+= cs553x_nand.o
-obj-$(CONFIG_MTD_NAND_NDFC)		+= ndfc.o
-obj-$(CONFIG_MTD_NAND_ATMEL)		+= atmel/
-obj-$(CONFIG_MTD_NAND_GPIO)		+= gpio.o
-omap2_nand-objs := omap2.o
-obj-$(CONFIG_MTD_NAND_OMAP2) 		+= omap2_nand.o
-obj-$(CONFIG_MTD_NAND_OMAP_BCH_BUILD)	+= omap_elm.o
-obj-$(CONFIG_MTD_NAND_CM_X270)		+= cmx270_nand.o
-obj-$(CONFIG_MTD_NAND_PXA3xx)		+= pxa3xx_nand.o
-obj-$(CONFIG_MTD_NAND_TMIO)		+= tmio_nand.o
-obj-$(CONFIG_MTD_NAND_PLATFORM)		+= plat_nand.o
-obj-$(CONFIG_MTD_NAND_PASEMI)		+= pasemi_nand.o
-obj-$(CONFIG_MTD_NAND_ORION)		+= orion_nand.o
-obj-$(CONFIG_MTD_NAND_OXNAS)		+= oxnas_nand.o
-obj-$(CONFIG_MTD_NAND_FSL_ELBC)		+= fsl_elbc_nand.o
-obj-$(CONFIG_MTD_NAND_FSL_IFC)		+= fsl_ifc_nand.o
-obj-$(CONFIG_MTD_NAND_FSL_UPM)		+= fsl_upm.o
-obj-$(CONFIG_MTD_NAND_SLC_LPC32XX)      += lpc32xx_slc.o
-obj-$(CONFIG_MTD_NAND_MLC_LPC32XX)      += lpc32xx_mlc.o
-obj-$(CONFIG_MTD_NAND_SH_FLCTL)		+= sh_flctl.o
-obj-$(CONFIG_MTD_NAND_MXC)		+= mxc_nand.o
-obj-$(CONFIG_MTD_NAND_SOCRATES)		+= socrates_nand.o
-obj-$(CONFIG_MTD_NAND_TXX9NDFMC)	+= txx9ndfmc.o
-obj-$(CONFIG_MTD_NAND_NUC900)		+= nuc900_nand.o
-obj-$(CONFIG_MTD_NAND_MPC5121_NFC)	+= mpc5121_nfc.o
-obj-$(CONFIG_MTD_NAND_VF610_NFC)	+= vf610_nfc.o
-obj-$(CONFIG_MTD_NAND_RICOH)		+= r852.o
-obj-$(CONFIG_MTD_NAND_JZ4740)		+= jz4740_nand.o
-obj-$(CONFIG_MTD_NAND_JZ4780)		+= jz4780_nand.o jz4780_bch.o
-obj-$(CONFIG_MTD_NAND_GPMI_NAND)	+= gpmi-nand/
-obj-$(CONFIG_MTD_NAND_XWAY)		+= xway_nand.o
-obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH)	+= bcm47xxnflash/
-obj-$(CONFIG_MTD_NAND_SUNXI)		+= sunxi_nand.o
-obj-$(CONFIG_MTD_NAND_HISI504)	        += hisi504_nand.o
-obj-$(CONFIG_MTD_NAND_BRCMNAND)		+= brcmnand/
-obj-$(CONFIG_MTD_NAND_QCOM)		+= qcom_nandc.o
-obj-$(CONFIG_MTD_NAND_MTK)		+= mtk_nand.o mtk_ecc.o
-
-nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o
-nand-objs += nand_amd.o
-nand-objs += nand_hynix.o
-nand-objs += nand_macronix.o
-nand-objs += nand_micron.o
-nand-objs += nand_samsung.o
-nand-objs += nand_toshiba.o
+obj-y	+= raw/
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
new file mode 100644
index 0000000..0bd2319
--- /dev/null
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -0,0 +1,565 @@
+config MTD_NAND_ECC
+	tristate
+
+config MTD_NAND_ECC_SMC
+	bool "NAND ECC Smart Media byte order"
+	depends on MTD_NAND_ECC
+	default n
+	help
+	  Software ECC according to the Smart Media Specification.
+	  The original Linux implementation had byte 0 and 1 swapped.
+
+
+menuconfig MTD_NAND
+	tristate "NAND Device Support"
+	depends on MTD
+	select MTD_NAND_ECC
+	help
+	  This enables support for accessing all type of NAND flash
+	  devices. For further information see
+	  <http://www.linux-mtd.infradead.org/doc/nand.html>.
+
+if MTD_NAND
+
+config MTD_NAND_BCH
+	tristate
+	select BCH
+	depends on MTD_NAND_ECC_BCH
+	default MTD_NAND
+
+config MTD_NAND_ECC_BCH
+	bool "Support software BCH ECC"
+	default n
+	help
+	  This enables support for software BCH error correction. Binary BCH
+	  codes are more powerful and cpu intensive than traditional Hamming
+	  ECC codes. They are used with NAND devices requiring more than 1 bit
+	  of error correction.
+
+config MTD_SM_COMMON
+	tristate
+	default n
+
+config MTD_NAND_DENALI
+	tristate
+
+config MTD_NAND_DENALI_PCI
+        tristate "Support Denali NAND controller on Intel Moorestown"
+	select MTD_NAND_DENALI
+	depends on HAS_DMA && PCI
+        help
+          Enable the driver for NAND flash on Intel Moorestown, using the
+          Denali NAND controller core.
+
+config MTD_NAND_DENALI_DT
+	tristate "Support Denali NAND controller as a DT device"
+	select MTD_NAND_DENALI
+	depends on HAS_DMA && HAVE_CLK && OF
+	help
+	  Enable the driver for NAND flash on platforms using a Denali NAND
+	  controller as a DT device.
+
+config MTD_NAND_GPIO
+	tristate "GPIO assisted NAND Flash driver"
+	depends on GPIOLIB || COMPILE_TEST
+	depends on HAS_IOMEM
+	help
+	  This enables a NAND flash driver where control signals are
+	  connected to GPIO pins, and commands and data are communicated
+	  via a memory mapped interface.
+
+config MTD_NAND_AMS_DELTA
+	tristate "NAND Flash device on Amstrad E3"
+	depends on MACH_AMS_DELTA
+	default y
+	help
+	  Support for NAND flash on Amstrad E3 (Delta).
+
+config MTD_NAND_OMAP2
+	tristate "NAND Flash device on OMAP2, OMAP3, OMAP4 and Keystone"
+	depends on (ARCH_OMAP2PLUS || ARCH_KEYSTONE)
+	help
+          Support for NAND flash on Texas Instruments OMAP2, OMAP3, OMAP4
+	  and Keystone platforms.
+
+config MTD_NAND_OMAP_BCH
+	depends on MTD_NAND_OMAP2
+	bool "Support hardware based BCH error correction"
+	default n
+	select BCH
+	help
+	  This config enables the ELM hardware engine, which can be used to
+	  locate and correct errors when using BCH ECC scheme. This offloads
+	  the cpu from doing ECC error searching and correction. However some
+	  legacy OMAP families like OMAP2xxx, OMAP3xxx do not have ELM engine
+	  so this is optional for them.
+
+config MTD_NAND_OMAP_BCH_BUILD
+	def_tristate MTD_NAND_OMAP2 && MTD_NAND_OMAP_BCH
+
+config MTD_NAND_RICOH
+	tristate "Ricoh xD card reader"
+	default n
+	depends on PCI
+	select MTD_SM_COMMON
+	help
+	  Enable support for Ricoh R5C852 xD card reader
+	  You also need to enable ether
+	  NAND SSFDC (SmartMedia) read only translation layer' or new
+	  expermental, readwrite
+	  'SmartMedia/xD new translation layer'
+
+config MTD_NAND_AU1550
+	tristate "Au1550/1200 NAND support"
+	depends on MIPS_ALCHEMY
+	help
+	  This enables the driver for the NAND flash controller on the
+	  AMD/Alchemy 1550 SOC.
+
+config MTD_NAND_BF5XX
+	tristate "Blackfin on-chip NAND Flash Controller driver"
+	depends on BF54x || BF52x
+	help
+	  This enables the Blackfin on-chip NAND flash controller
+
+	  No board specific support is done by this driver, each board
+	  must advertise a platform_device for the driver to attach.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called bf5xx-nand.
+
+config MTD_NAND_BF5XX_HWECC
+	bool "BF5XX NAND Hardware ECC"
+	default y
+	depends on MTD_NAND_BF5XX
+	help
+	  Enable the use of the BF5XX's internal ECC generator when
+	  using NAND.
+
+config MTD_NAND_BF5XX_BOOTROM_ECC
+	bool "Use Blackfin BootROM ECC Layout"
+	default n
+	depends on MTD_NAND_BF5XX_HWECC
+	help
+	  If you wish to modify NAND pages and allow the Blackfin on-chip
+	  BootROM to boot from them, say Y here.  This is only necessary
+	  if you are booting U-Boot out of NAND and you wish to update
+	  U-Boot from Linux' userspace.  Otherwise, you should say N here.
+
+	  If unsure, say N.
+
+config MTD_NAND_S3C2410
+	tristate "NAND Flash support for Samsung S3C SoCs"
+	depends on ARCH_S3C24XX || ARCH_S3C64XX
+	help
+	  This enables the NAND flash controller on the S3C24xx and S3C64xx
+	  SoCs
+
+	  No board specific support is done by this driver, each board
+	  must advertise a platform_device for the driver to attach.
+
+config MTD_NAND_S3C2410_DEBUG
+	bool "Samsung S3C NAND driver debug"
+	depends on MTD_NAND_S3C2410
+	help
+	  Enable debugging of the S3C NAND driver
+
+config MTD_NAND_NDFC
+	tristate "NDFC NanD Flash Controller"
+	depends on 4xx
+	select MTD_NAND_ECC_SMC
+	help
+	 NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs
+
+config MTD_NAND_S3C2410_CLKSTOP
+	bool "Samsung S3C NAND IDLE clock stop"
+	depends on MTD_NAND_S3C2410
+	default n
+	help
+	  Stop the clock to the NAND controller when there is no chip
+	  selected to save power. This will mean there is a small delay
+	  when the is NAND chip selected or released, but will save
+	  approximately 5mA of power when there is nothing happening.
+
+config MTD_NAND_TANGO
+	tristate "NAND Flash support for Tango chips"
+	depends on ARCH_TANGO || COMPILE_TEST
+	depends on HAS_DMA
+	help
+	  Enables the NAND Flash controller on Tango chips.
+
+config MTD_NAND_DISKONCHIP
+	tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation)"
+	depends on HAS_IOMEM
+	select REED_SOLOMON
+	select REED_SOLOMON_DEC16
+	help
+	  This is a reimplementation of M-Systems DiskOnChip 2000,
+	  Millennium and Millennium Plus as a standard NAND device driver,
+	  as opposed to the earlier self-contained MTD device drivers.
+	  This should enable, among other things, proper JFFS2 operation on
+	  these devices.
+
+config MTD_NAND_DISKONCHIP_PROBE_ADVANCED
+        bool "Advanced detection options for DiskOnChip"
+        depends on MTD_NAND_DISKONCHIP
+        help
+          This option allows you to specify nonstandard address at which to
+          probe for a DiskOnChip, or to change the detection options.  You
+          are unlikely to need any of this unless you are using LinuxBIOS.
+          Say 'N'.
+
+config MTD_NAND_DISKONCHIP_PROBE_ADDRESS
+        hex "Physical address of DiskOnChip" if MTD_NAND_DISKONCHIP_PROBE_ADVANCED
+        depends on MTD_NAND_DISKONCHIP
+        default "0"
+        ---help---
+        By default, the probe for DiskOnChip devices will look for a
+        DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
+        This option allows you to specify a single address at which to probe
+        for the device, which is useful if you have other devices in that
+        range which get upset when they are probed.
+
+        (Note that on PowerPC, the normal probe will only check at
+        0xE4000000.)
+
+        Normally, you should leave this set to zero, to allow the probe at
+        the normal addresses.
+
+config MTD_NAND_DISKONCHIP_PROBE_HIGH
+        bool "Probe high addresses"
+        depends on MTD_NAND_DISKONCHIP_PROBE_ADVANCED
+        help
+          By default, the probe for DiskOnChip devices will look for a
+          DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
+          This option changes to make it probe between 0xFFFC8000 and
+          0xFFFEE000.  Unless you are using LinuxBIOS, this is unlikely to be
+          useful to you.  Say 'N'.
+
+config MTD_NAND_DISKONCHIP_BBTWRITE
+	bool "Allow BBT writes on DiskOnChip Millennium and 2000TSOP"
+	depends on MTD_NAND_DISKONCHIP
+	help
+	  On DiskOnChip devices shipped with the INFTL filesystem (Millennium
+	  and 2000 TSOP/Alon), Linux reserves some space at the end of the
+	  device for the Bad Block Table (BBT).  If you have existing INFTL
+	  data on your device (created by non-Linux tools such as M-Systems'
+	  DOS drivers), your data might overlap the area Linux wants to use for
+	  the BBT.  If this is a concern for you, leave this option disabled and
+	  Linux will not write BBT data into this area.
+	  The downside of leaving this option disabled is that if bad blocks
+	  are detected by Linux, they will not be recorded in the BBT, which
+	  could cause future problems.
+	  Once you enable this option, new filesystems (INFTL or others, created
+	  in Linux or other operating systems) will not use the reserved area.
+	  The only reason not to enable this option is to prevent damage to
+	  preexisting filesystems.
+	  Even if you leave this disabled, you can enable BBT writes at module
+	  load time (assuming you build diskonchip as a module) with the module
+	  parameter "inftl_bbt_write=1".
+
+config MTD_NAND_DOCG4
+	tristate "Support for DiskOnChip G4"
+	depends on HAS_IOMEM
+	select BCH
+	select BITREVERSE
+	help
+	  Support for diskonchip G4 nand flash, found in various smartphones and
+	  PDAs, among them the Palm Treo680, HTC Prophet and Wizard, Toshiba
+	  Portege G900, Asus P526, and O2 XDA Zinc.
+
+	  With this driver you will be able to use UBI and create a ubifs on the
+	  device, so you may wish to consider enabling UBI and UBIFS as well.
+
+	  These devices ship with the Mys/Sandisk SAFTL formatting, for which
+	  there is currently no mtd parser, so you may want to use command line
+	  partitioning to segregate write-protected blocks. On the Treo680, the
+	  first five erase blocks (256KiB each) are write-protected, followed
+	  by the block containing the saftl partition table.  This is probably
+	  typical.
+
+config MTD_NAND_SHARPSL
+	tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
+	depends on ARCH_PXA
+
+config MTD_NAND_CAFE
+	tristate "NAND support for OLPC CAFÉ chip"
+	depends on PCI
+	select REED_SOLOMON
+	select REED_SOLOMON_DEC16
+	help
+	  Use NAND flash attached to the CAFÉ chip designed for the OLPC
+	  laptop.
+
+config MTD_NAND_CS553X
+	tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)"
+	depends on X86_32
+	depends on !UML && HAS_IOMEM
+	help
+	  The CS553x companion chips for the AMD Geode processor
+	  include NAND flash controllers with built-in hardware ECC
+	  capabilities; enabling this option will allow you to use
+	  these. The driver will check the MSRs to verify that the
+	  controller is enabled for NAND, and currently requires that
+	  the controller be in MMIO mode.
+
+	  If you say "m", the module will be called cs553x_nand.
+
+config MTD_NAND_ATMEL
+	tristate "Support for NAND Flash / SmartMedia on AT91"
+	depends on ARCH_AT91
+	help
+	  Enables support for NAND Flash / Smart Media Card interface
+	  on Atmel AT91 processors.
+
+config MTD_NAND_PXA3xx
+	tristate "NAND support on PXA3xx and Armada 370/XP"
+	depends on PXA3xx || ARCH_MMP || PLAT_ORION
+	help
+	  This enables the driver for the NAND flash device found on
+	  PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2).
+
+config MTD_NAND_SLC_LPC32XX
+	tristate "NXP LPC32xx SLC Controller"
+	depends on ARCH_LPC32XX
+	help
+	  Enables support for NXP's LPC32XX SLC (i.e. for Single Level Cell
+	  chips) NAND controller. This is the default for the PHYTEC 3250
+	  reference board which contains a NAND256R3A2CZA6 chip.
+
+	  Please check the actual NAND chip connected and its support
+	  by the SLC NAND controller.
+
+config MTD_NAND_MLC_LPC32XX
+	tristate "NXP LPC32xx MLC Controller"
+	depends on ARCH_LPC32XX
+	help
+	  Uses the LPC32XX MLC (i.e. for Multi Level Cell chips) NAND
+	  controller. This is the default for the WORK92105 controller
+	  board.
+
+	  Please check the actual NAND chip connected and its support
+	  by the MLC NAND controller.
+
+config MTD_NAND_CM_X270
+	tristate "Support for NAND Flash on CM-X270 modules"
+	depends on MACH_ARMCORE
+
+config MTD_NAND_PASEMI
+	tristate "NAND support for PA Semi PWRficient"
+	depends on PPC_PASEMI
+	help
+	  Enables support for NAND Flash interface on PA Semi PWRficient
+	  based boards
+
+config MTD_NAND_TMIO
+	tristate "NAND Flash device on Toshiba Mobile IO Controller"
+	depends on MFD_TMIO
+	help
+	  Support for NAND flash connected to a Toshiba Mobile IO
+	  Controller in some PDAs, including the Sharp SL6000x.
+
+config MTD_NAND_NANDSIM
+	tristate "Support for NAND Flash Simulator"
+	help
+	  The simulator may simulate various NAND flash chips for the
+	  MTD nand layer.
+
+config MTD_NAND_GPMI_NAND
+        tristate "GPMI NAND Flash Controller driver"
+        depends on MTD_NAND && MXS_DMA
+        help
+	 Enables NAND Flash support for IMX23, IMX28 or IMX6.
+	 The GPMI controller is very powerful, with the help of BCH
+	 module, it can do the hardware ECC. The GPMI supports several
+	 NAND flashs at the same time. The GPMI may conflicts with other
+	 block, such as SD card. So pay attention to it when you enable
+	 the GPMI.
+
+config MTD_NAND_BRCMNAND
+	tristate "Broadcom STB NAND controller"
+	depends on ARM || ARM64 || MIPS
+	help
+	  Enables the Broadcom NAND controller driver. The controller was
+	  originally designed for Set-Top Box but is used on various BCM7xxx,
+	  BCM3xxx, BCM63xxx, iProc/Cygnus and more.
+
+config MTD_NAND_BCM47XXNFLASH
+	tristate "Support for NAND flash on BCM4706 BCMA bus"
+	depends on BCMA_NFLASH
+	help
+	  BCMA bus can have various flash memories attached, they are
+	  registered by bcma as platform devices. This enables driver for
+	  NAND flash memories. For now only BCM4706 is supported.
+
+config MTD_NAND_PLATFORM
+	tristate "Support for generic platform NAND driver"
+	depends on HAS_IOMEM
+	help
+	  This implements a generic NAND driver for on-SOC platform
+	  devices. You will need to provide platform-specific functions
+	  via platform_data.
+
+config MTD_NAND_ORION
+	tristate "NAND Flash support for Marvell Orion SoC"
+	depends on PLAT_ORION
+	help
+	  This enables the NAND flash controller on Orion machines.
+
+	  No board specific support is done by this driver, each board
+	  must advertise a platform_device for the driver to attach.
+
+config MTD_NAND_OXNAS
+	tristate "NAND Flash support for Oxford Semiconductor SoC"
+	depends on ARCH_OXNAS || COMPILE_TEST
+	depends on HAS_IOMEM
+	help
+	  This enables the NAND flash controller on Oxford Semiconductor SoCs.
+
+config MTD_NAND_FSL_ELBC
+	tristate "NAND support for Freescale eLBC controllers"
+	depends on FSL_SOC
+	select FSL_LBC
+	help
+	  Various Freescale chips, including the 8313, include a NAND Flash
+	  Controller Module with built-in hardware ECC capabilities.
+	  Enabling this option will enable you to use this to control
+	  external NAND devices.
+
+config MTD_NAND_FSL_IFC
+	tristate "NAND support for Freescale IFC controller"
+	depends on FSL_SOC || ARCH_LAYERSCAPE || SOC_LS1021A
+	select FSL_IFC
+	select MEMORY
+	help
+	  Various Freescale chips e.g P1010, include a NAND Flash machine
+	  with built-in hardware ECC capabilities.
+	  Enabling this option will enable you to use this to control
+	  external NAND devices.
+
+config MTD_NAND_FSL_UPM
+	tristate "Support for NAND on Freescale UPM"
+	depends on PPC_83xx || PPC_85xx
+	select FSL_LBC
+	help
+	  Enables support for NAND Flash chips wired onto Freescale PowerPC
+	  processor localbus with User-Programmable Machine support.
+
+config MTD_NAND_MPC5121_NFC
+	tristate "MPC5121 built-in NAND Flash Controller support"
+	depends on PPC_MPC512x
+	help
+	  This enables the driver for the NAND flash controller on the
+	  MPC5121 SoC.
+
+config MTD_NAND_VF610_NFC
+	tristate "Support for Freescale NFC for VF610/MPC5125"
+	depends on (SOC_VF610 || COMPILE_TEST)
+	depends on HAS_IOMEM
+	help
+	  Enables support for NAND Flash Controller on some Freescale
+	  processors like the VF610, MPC5125, MCF54418 or Kinetis K70.
+	  The driver supports a maximum 2k page size. With 2k pages and
+	  64 bytes or more of OOB, hardware ECC with up to 32-bit error
+	  correction is supported. Hardware ECC is only enabled through
+	  device tree.
+
+config MTD_NAND_MXC
+	tristate "MXC NAND support"
+	depends on ARCH_MXC
+	help
+	  This enables the driver for the NAND flash controller on the
+	  MXC processors.
+
+config MTD_NAND_SH_FLCTL
+	tristate "Support for NAND on Renesas SuperH FLCTL"
+	depends on SUPERH || COMPILE_TEST
+	depends on HAS_IOMEM
+	depends on HAS_DMA
+	help
+	  Several Renesas SuperH CPU has FLCTL. This option enables support
+	  for NAND Flash using FLCTL.
+
+config MTD_NAND_DAVINCI
+        tristate "Support NAND on DaVinci/Keystone SoC"
+        depends on ARCH_DAVINCI || (ARCH_KEYSTONE && TI_AEMIF)
+        help
+	  Enable the driver for NAND flash chips on Texas Instruments
+	  DaVinci/Keystone processors.
+
+config MTD_NAND_TXX9NDFMC
+	tristate "NAND Flash support for TXx9 SoC"
+	depends on SOC_TX4938 || SOC_TX4939
+	help
+	  This enables the NAND flash controller on the TXx9 SoCs.
+
+config MTD_NAND_SOCRATES
+	tristate "Support for NAND on Socrates board"
+	depends on SOCRATES
+	help
+	  Enables support for NAND Flash chips wired onto Socrates board.
+
+config MTD_NAND_NUC900
+	tristate "Support for NAND on Nuvoton NUC9xx/w90p910 evaluation boards."
+	depends on ARCH_W90X900
+	help
+	  This enables the driver for the NAND Flash on evaluation board based
+	  on w90p910 / NUC9xx.
+
+config MTD_NAND_JZ4740
+	tristate "Support for JZ4740 SoC NAND controller"
+	depends on MACH_JZ4740
+	help
+		Enables support for NAND Flash on JZ4740 SoC based boards.
+
+config MTD_NAND_JZ4780
+	tristate "Support for NAND on JZ4780 SoC"
+	depends on MACH_JZ4780 && JZ4780_NEMC
+	help
+	  Enables support for NAND Flash connected to the NEMC on JZ4780 SoC
+	  based boards, using the BCH controller for hardware error correction.
+
+config MTD_NAND_FSMC
+	tristate "Support for NAND on ST Micros FSMC"
+	depends on OF
+	depends on PLAT_SPEAR || ARCH_NOMADIK || ARCH_U8500 || MACH_U300
+	help
+	  Enables support for NAND Flash chips on the ST Microelectronics
+	  Flexible Static Memory Controller (FSMC)
+
+config MTD_NAND_XWAY
+	bool "Support for NAND on Lantiq XWAY SoC"
+	depends on LANTIQ && SOC_TYPE_XWAY
+	help
+	  Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached
+	  to the External Bus Unit (EBU).
+
+config MTD_NAND_SUNXI
+	tristate "Support for NAND on Allwinner SoCs"
+	depends on ARCH_SUNXI
+	help
+	  Enables support for NAND Flash chips on Allwinner SoCs.
+
+config MTD_NAND_HISI504
+	tristate "Support for NAND controller on Hisilicon SoC Hip04"
+	depends on ARCH_HISI || COMPILE_TEST
+	depends on HAS_DMA
+	help
+	  Enables support for NAND controller on Hisilicon SoC Hip04.
+
+config MTD_NAND_QCOM
+	tristate "Support for NAND on QCOM SoCs"
+	depends on ARCH_QCOM
+	help
+	  Enables support for NAND flash chips on SoCs containing the EBI2 NAND
+	  controller. This controller is found on IPQ806x SoC.
+
+config MTD_NAND_MTK
+	tristate "Support for NAND controller on MTK SoCs"
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	depends on HAS_DMA
+	help
+	  Enables support for NAND controller on MTK SoCs.
+	  This controller is found on mt27xx, mt81xx, mt65xx SoCs.
+
+endif # MTD_NAND
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
new file mode 100644
index 0000000..523d5c1
--- /dev/null
+++ b/drivers/mtd/nand/raw/Makefile
@@ -0,0 +1,69 @@
+#
+# linux/drivers/raw/nand/Makefile
+#
+
+obj-$(CONFIG_MTD_NAND)			+= nand.o
+obj-$(CONFIG_MTD_NAND_ECC)		+= nand_ecc.o
+obj-$(CONFIG_MTD_NAND_BCH)		+= nand_bch.o
+obj-$(CONFIG_MTD_SM_COMMON) 		+= sm_common.o
+
+obj-$(CONFIG_MTD_NAND_CAFE)		+= cafe_nand.o
+obj-$(CONFIG_MTD_NAND_AMS_DELTA)	+= ams-delta.o
+obj-$(CONFIG_MTD_NAND_DENALI)		+= denali.o
+obj-$(CONFIG_MTD_NAND_DENALI_PCI)	+= denali_pci.o
+obj-$(CONFIG_MTD_NAND_DENALI_DT)	+= denali_dt.o
+obj-$(CONFIG_MTD_NAND_AU1550)		+= au1550nd.o
+obj-$(CONFIG_MTD_NAND_BF5XX)		+= bf5xx_nand.o
+obj-$(CONFIG_MTD_NAND_S3C2410)		+= s3c2410.o
+obj-$(CONFIG_MTD_NAND_TANGO)		+= tango_nand.o
+obj-$(CONFIG_MTD_NAND_DAVINCI)		+= davinci_nand.o
+obj-$(CONFIG_MTD_NAND_DISKONCHIP)	+= diskonchip.o
+obj-$(CONFIG_MTD_NAND_DOCG4)		+= docg4.o
+obj-$(CONFIG_MTD_NAND_FSMC)		+= fsmc_nand.o
+obj-$(CONFIG_MTD_NAND_SHARPSL)		+= sharpsl.o
+obj-$(CONFIG_MTD_NAND_NANDSIM)		+= nandsim.o
+obj-$(CONFIG_MTD_NAND_CS553X)		+= cs553x_nand.o
+obj-$(CONFIG_MTD_NAND_NDFC)		+= ndfc.o
+obj-$(CONFIG_MTD_NAND_ATMEL)		+= atmel/
+obj-$(CONFIG_MTD_NAND_GPIO)		+= gpio.o
+omap2_nand-objs := omap2.o
+obj-$(CONFIG_MTD_NAND_OMAP2) 		+= omap2_nand.o
+obj-$(CONFIG_MTD_NAND_OMAP_BCH_BUILD)	+= omap_elm.o
+obj-$(CONFIG_MTD_NAND_CM_X270)		+= cmx270_nand.o
+obj-$(CONFIG_MTD_NAND_PXA3xx)		+= pxa3xx_nand.o
+obj-$(CONFIG_MTD_NAND_TMIO)		+= tmio_nand.o
+obj-$(CONFIG_MTD_NAND_PLATFORM)		+= plat_nand.o
+obj-$(CONFIG_MTD_NAND_PASEMI)		+= pasemi_nand.o
+obj-$(CONFIG_MTD_NAND_ORION)		+= orion_nand.o
+obj-$(CONFIG_MTD_NAND_OXNAS)		+= oxnas_nand.o
+obj-$(CONFIG_MTD_NAND_FSL_ELBC)		+= fsl_elbc_nand.o
+obj-$(CONFIG_MTD_NAND_FSL_IFC)		+= fsl_ifc_nand.o
+obj-$(CONFIG_MTD_NAND_FSL_UPM)		+= fsl_upm.o
+obj-$(CONFIG_MTD_NAND_SLC_LPC32XX)      += lpc32xx_slc.o
+obj-$(CONFIG_MTD_NAND_MLC_LPC32XX)      += lpc32xx_mlc.o
+obj-$(CONFIG_MTD_NAND_SH_FLCTL)		+= sh_flctl.o
+obj-$(CONFIG_MTD_NAND_MXC)		+= mxc_nand.o
+obj-$(CONFIG_MTD_NAND_SOCRATES)		+= socrates_nand.o
+obj-$(CONFIG_MTD_NAND_TXX9NDFMC)	+= txx9ndfmc.o
+obj-$(CONFIG_MTD_NAND_NUC900)		+= nuc900_nand.o
+obj-$(CONFIG_MTD_NAND_MPC5121_NFC)	+= mpc5121_nfc.o
+obj-$(CONFIG_MTD_NAND_VF610_NFC)	+= vf610_nfc.o
+obj-$(CONFIG_MTD_NAND_RICOH)		+= r852.o
+obj-$(CONFIG_MTD_NAND_JZ4740)		+= jz4740_nand.o
+obj-$(CONFIG_MTD_NAND_JZ4780)		+= jz4780_nand.o jz4780_bch.o
+obj-$(CONFIG_MTD_NAND_GPMI_NAND)	+= gpmi-nand/
+obj-$(CONFIG_MTD_NAND_XWAY)		+= xway_nand.o
+obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH)	+= bcm47xxnflash/
+obj-$(CONFIG_MTD_NAND_SUNXI)		+= sunxi_nand.o
+obj-$(CONFIG_MTD_NAND_HISI504)	        += hisi504_nand.o
+obj-$(CONFIG_MTD_NAND_BRCMNAND)		+= brcmnand/
+obj-$(CONFIG_MTD_NAND_QCOM)		+= qcom_nandc.o
+obj-$(CONFIG_MTD_NAND_MTK)		+= mtk_nand.o mtk_ecc.o
+
+nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o
+nand-objs += nand_amd.o
+nand-objs += nand_hynix.o
+nand-objs += nand_macronix.o
+nand-objs += nand_micron.o
+nand-objs += nand_samsung.o
+nand-objs += nand_toshiba.o
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
similarity index 100%
rename from drivers/mtd/nand/ams-delta.c
rename to drivers/mtd/nand/raw/ams-delta.c
diff --git a/drivers/mtd/nand/atmel/Makefile b/drivers/mtd/nand/raw/atmel/Makefile
similarity index 100%
rename from drivers/mtd/nand/atmel/Makefile
rename to drivers/mtd/nand/raw/atmel/Makefile
diff --git a/drivers/mtd/nand/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c
similarity index 100%
rename from drivers/mtd/nand/atmel/nand-controller.c
rename to drivers/mtd/nand/raw/atmel/nand-controller.c
diff --git a/drivers/mtd/nand/atmel/pmecc.c b/drivers/mtd/nand/raw/atmel/pmecc.c
similarity index 100%
rename from drivers/mtd/nand/atmel/pmecc.c
rename to drivers/mtd/nand/raw/atmel/pmecc.c
diff --git a/drivers/mtd/nand/atmel/pmecc.h b/drivers/mtd/nand/raw/atmel/pmecc.h
similarity index 100%
rename from drivers/mtd/nand/atmel/pmecc.h
rename to drivers/mtd/nand/raw/atmel/pmecc.h
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c
similarity index 100%
rename from drivers/mtd/nand/au1550nd.c
rename to drivers/mtd/nand/raw/au1550nd.c
diff --git a/drivers/mtd/nand/bcm47xxnflash/Makefile b/drivers/mtd/nand/raw/bcm47xxnflash/Makefile
similarity index 100%
rename from drivers/mtd/nand/bcm47xxnflash/Makefile
rename to drivers/mtd/nand/raw/bcm47xxnflash/Makefile
diff --git a/drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h b/drivers/mtd/nand/raw/bcm47xxnflash/bcm47xxnflash.h
similarity index 100%
rename from drivers/mtd/nand/bcm47xxnflash/bcm47xxnflash.h
rename to drivers/mtd/nand/raw/bcm47xxnflash/bcm47xxnflash.h
diff --git a/drivers/mtd/nand/bcm47xxnflash/main.c b/drivers/mtd/nand/raw/bcm47xxnflash/main.c
similarity index 100%
rename from drivers/mtd/nand/bcm47xxnflash/main.c
rename to drivers/mtd/nand/raw/bcm47xxnflash/main.c
diff --git a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c
similarity index 100%
rename from drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
rename to drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/raw/bf5xx_nand.c
similarity index 100%
rename from drivers/mtd/nand/bf5xx_nand.c
rename to drivers/mtd/nand/raw/bf5xx_nand.c
diff --git a/drivers/mtd/nand/brcmnand/Makefile b/drivers/mtd/nand/raw/brcmnand/Makefile
similarity index 100%
rename from drivers/mtd/nand/brcmnand/Makefile
rename to drivers/mtd/nand/raw/brcmnand/Makefile
diff --git a/drivers/mtd/nand/brcmnand/bcm63138_nand.c b/drivers/mtd/nand/raw/brcmnand/bcm63138_nand.c
similarity index 100%
rename from drivers/mtd/nand/brcmnand/bcm63138_nand.c
rename to drivers/mtd/nand/raw/brcmnand/bcm63138_nand.c
diff --git a/drivers/mtd/nand/brcmnand/bcm6368_nand.c b/drivers/mtd/nand/raw/brcmnand/bcm6368_nand.c
similarity index 100%
rename from drivers/mtd/nand/brcmnand/bcm6368_nand.c
rename to drivers/mtd/nand/raw/brcmnand/bcm6368_nand.c
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
similarity index 100%
rename from drivers/mtd/nand/brcmnand/brcmnand.c
rename to drivers/mtd/nand/raw/brcmnand/brcmnand.c
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.h b/drivers/mtd/nand/raw/brcmnand/brcmnand.h
similarity index 100%
rename from drivers/mtd/nand/brcmnand/brcmnand.h
rename to drivers/mtd/nand/raw/brcmnand/brcmnand.h
diff --git a/drivers/mtd/nand/brcmnand/brcmstb_nand.c b/drivers/mtd/nand/raw/brcmnand/brcmstb_nand.c
similarity index 100%
rename from drivers/mtd/nand/brcmnand/brcmstb_nand.c
rename to drivers/mtd/nand/raw/brcmnand/brcmstb_nand.c
diff --git a/drivers/mtd/nand/brcmnand/iproc_nand.c b/drivers/mtd/nand/raw/brcmnand/iproc_nand.c
similarity index 100%
rename from drivers/mtd/nand/brcmnand/iproc_nand.c
rename to drivers/mtd/nand/raw/brcmnand/iproc_nand.c
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
similarity index 100%
rename from drivers/mtd/nand/cafe_nand.c
rename to drivers/mtd/nand/raw/cafe_nand.c
diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/raw/cmx270_nand.c
similarity index 100%
rename from drivers/mtd/nand/cmx270_nand.c
rename to drivers/mtd/nand/raw/cmx270_nand.c
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c
similarity index 100%
rename from drivers/mtd/nand/cs553x_nand.c
rename to drivers/mtd/nand/raw/cs553x_nand.c
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
similarity index 100%
rename from drivers/mtd/nand/davinci_nand.c
rename to drivers/mtd/nand/raw/davinci_nand.c
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/raw/denali.c
similarity index 100%
rename from drivers/mtd/nand/denali.c
rename to drivers/mtd/nand/raw/denali.c
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/raw/denali.h
similarity index 100%
rename from drivers/mtd/nand/denali.h
rename to drivers/mtd/nand/raw/denali.h
diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/raw/denali_dt.c
similarity index 100%
rename from drivers/mtd/nand/denali_dt.c
rename to drivers/mtd/nand/raw/denali_dt.c
diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/raw/denali_pci.c
similarity index 100%
rename from drivers/mtd/nand/denali_pci.c
rename to drivers/mtd/nand/raw/denali_pci.c
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c
similarity index 100%
rename from drivers/mtd/nand/diskonchip.c
rename to drivers/mtd/nand/raw/diskonchip.c
diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/raw/docg4.c
similarity index 100%
rename from drivers/mtd/nand/docg4.c
rename to drivers/mtd/nand/raw/docg4.c
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c
similarity index 100%
rename from drivers/mtd/nand/fsl_elbc_nand.c
rename to drivers/mtd/nand/raw/fsl_elbc_nand.c
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c
similarity index 100%
rename from drivers/mtd/nand/fsl_ifc_nand.c
rename to drivers/mtd/nand/raw/fsl_ifc_nand.c
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c
similarity index 100%
rename from drivers/mtd/nand/fsl_upm.c
rename to drivers/mtd/nand/raw/fsl_upm.c
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c
similarity index 100%
rename from drivers/mtd/nand/fsmc_nand.c
rename to drivers/mtd/nand/raw/fsmc_nand.c
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/raw/gpio.c
similarity index 100%
rename from drivers/mtd/nand/gpio.c
rename to drivers/mtd/nand/raw/gpio.c
diff --git a/drivers/mtd/nand/gpmi-nand/Makefile b/drivers/mtd/nand/raw/gpmi-nand/Makefile
similarity index 100%
rename from drivers/mtd/nand/gpmi-nand/Makefile
rename to drivers/mtd/nand/raw/gpmi-nand/Makefile
diff --git a/drivers/mtd/nand/gpmi-nand/bch-regs.h b/drivers/mtd/nand/raw/gpmi-nand/bch-regs.h
similarity index 100%
rename from drivers/mtd/nand/gpmi-nand/bch-regs.h
rename to drivers/mtd/nand/raw/gpmi-nand/bch-regs.h
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
similarity index 100%
rename from drivers/mtd/nand/gpmi-nand/gpmi-lib.c
rename to drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
similarity index 100%
rename from drivers/mtd/nand/gpmi-nand/gpmi-nand.c
rename to drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h
similarity index 100%
rename from drivers/mtd/nand/gpmi-nand/gpmi-nand.h
rename to drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-regs.h b/drivers/mtd/nand/raw/gpmi-nand/gpmi-regs.h
similarity index 100%
rename from drivers/mtd/nand/gpmi-nand/gpmi-regs.h
rename to drivers/mtd/nand/raw/gpmi-nand/gpmi-regs.h
diff --git a/drivers/mtd/nand/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c
similarity index 100%
rename from drivers/mtd/nand/hisi504_nand.c
rename to drivers/mtd/nand/raw/hisi504_nand.c
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c
similarity index 100%
rename from drivers/mtd/nand/jz4740_nand.c
rename to drivers/mtd/nand/raw/jz4740_nand.c
diff --git a/drivers/mtd/nand/jz4780_bch.c b/drivers/mtd/nand/raw/jz4780_bch.c
similarity index 100%
rename from drivers/mtd/nand/jz4780_bch.c
rename to drivers/mtd/nand/raw/jz4780_bch.c
diff --git a/drivers/mtd/nand/jz4780_bch.h b/drivers/mtd/nand/raw/jz4780_bch.h
similarity index 100%
rename from drivers/mtd/nand/jz4780_bch.h
rename to drivers/mtd/nand/raw/jz4780_bch.h
diff --git a/drivers/mtd/nand/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c
similarity index 100%
rename from drivers/mtd/nand/jz4780_nand.c
rename to drivers/mtd/nand/raw/jz4780_nand.c
diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c
similarity index 100%
rename from drivers/mtd/nand/lpc32xx_mlc.c
rename to drivers/mtd/nand/raw/lpc32xx_mlc.c
diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c
similarity index 100%
rename from drivers/mtd/nand/lpc32xx_slc.c
rename to drivers/mtd/nand/raw/lpc32xx_slc.c
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c
similarity index 100%
rename from drivers/mtd/nand/mpc5121_nfc.c
rename to drivers/mtd/nand/raw/mpc5121_nfc.c
diff --git a/drivers/mtd/nand/mtk_ecc.c b/drivers/mtd/nand/raw/mtk_ecc.c
similarity index 100%
rename from drivers/mtd/nand/mtk_ecc.c
rename to drivers/mtd/nand/raw/mtk_ecc.c
diff --git a/drivers/mtd/nand/mtk_ecc.h b/drivers/mtd/nand/raw/mtk_ecc.h
similarity index 100%
rename from drivers/mtd/nand/mtk_ecc.h
rename to drivers/mtd/nand/raw/mtk_ecc.h
diff --git a/drivers/mtd/nand/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
similarity index 100%
rename from drivers/mtd/nand/mtk_nand.c
rename to drivers/mtd/nand/raw/mtk_nand.c
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c
similarity index 100%
rename from drivers/mtd/nand/mxc_nand.c
rename to drivers/mtd/nand/raw/mxc_nand.c
diff --git a/drivers/mtd/nand/nand_amd.c b/drivers/mtd/nand/raw/nand_amd.c
similarity index 100%
rename from drivers/mtd/nand/nand_amd.c
rename to drivers/mtd/nand/raw/nand_amd.c
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
similarity index 100%
rename from drivers/mtd/nand/nand_base.c
rename to drivers/mtd/nand/raw/nand_base.c
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
similarity index 100%
rename from drivers/mtd/nand/nand_bbt.c
rename to drivers/mtd/nand/raw/nand_bbt.c
diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/raw/nand_bch.c
similarity index 100%
rename from drivers/mtd/nand/nand_bch.c
rename to drivers/mtd/nand/raw/nand_bch.c
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/raw/nand_ecc.c
similarity index 100%
rename from drivers/mtd/nand/nand_ecc.c
rename to drivers/mtd/nand/raw/nand_ecc.c
diff --git a/drivers/mtd/nand/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
similarity index 100%
rename from drivers/mtd/nand/nand_hynix.c
rename to drivers/mtd/nand/raw/nand_hynix.c
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/raw/nand_ids.c
similarity index 100%
rename from drivers/mtd/nand/nand_ids.c
rename to drivers/mtd/nand/raw/nand_ids.c
diff --git a/drivers/mtd/nand/nand_macronix.c b/drivers/mtd/nand/raw/nand_macronix.c
similarity index 100%
rename from drivers/mtd/nand/nand_macronix.c
rename to drivers/mtd/nand/raw/nand_macronix.c
diff --git a/drivers/mtd/nand/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c
similarity index 100%
rename from drivers/mtd/nand/nand_micron.c
rename to drivers/mtd/nand/raw/nand_micron.c
diff --git a/drivers/mtd/nand/nand_samsung.c b/drivers/mtd/nand/raw/nand_samsung.c
similarity index 100%
rename from drivers/mtd/nand/nand_samsung.c
rename to drivers/mtd/nand/raw/nand_samsung.c
diff --git a/drivers/mtd/nand/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
similarity index 100%
rename from drivers/mtd/nand/nand_timings.c
rename to drivers/mtd/nand/raw/nand_timings.c
diff --git a/drivers/mtd/nand/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
similarity index 100%
rename from drivers/mtd/nand/nand_toshiba.c
rename to drivers/mtd/nand/raw/nand_toshiba.c
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/raw/nandsim.c
similarity index 100%
rename from drivers/mtd/nand/nandsim.c
rename to drivers/mtd/nand/raw/nandsim.c
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/raw/ndfc.c
similarity index 100%
rename from drivers/mtd/nand/ndfc.c
rename to drivers/mtd/nand/raw/ndfc.c
diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/raw/nuc900_nand.c
similarity index 100%
rename from drivers/mtd/nand/nuc900_nand.c
rename to drivers/mtd/nand/raw/nuc900_nand.c
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/raw/omap2.c
similarity index 100%
rename from drivers/mtd/nand/omap2.c
rename to drivers/mtd/nand/raw/omap2.c
diff --git a/drivers/mtd/nand/omap_elm.c b/drivers/mtd/nand/raw/omap_elm.c
similarity index 100%
rename from drivers/mtd/nand/omap_elm.c
rename to drivers/mtd/nand/raw/omap_elm.c
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/raw/orion_nand.c
similarity index 100%
rename from drivers/mtd/nand/orion_nand.c
rename to drivers/mtd/nand/raw/orion_nand.c
diff --git a/drivers/mtd/nand/oxnas_nand.c b/drivers/mtd/nand/raw/oxnas_nand.c
similarity index 100%
rename from drivers/mtd/nand/oxnas_nand.c
rename to drivers/mtd/nand/raw/oxnas_nand.c
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c
similarity index 100%
rename from drivers/mtd/nand/pasemi_nand.c
rename to drivers/mtd/nand/raw/pasemi_nand.c
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c
similarity index 100%
rename from drivers/mtd/nand/plat_nand.c
rename to drivers/mtd/nand/raw/plat_nand.c
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/raw/pxa3xx_nand.c
similarity index 100%
rename from drivers/mtd/nand/pxa3xx_nand.c
rename to drivers/mtd/nand/raw/pxa3xx_nand.c
diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c
similarity index 100%
rename from drivers/mtd/nand/qcom_nandc.c
rename to drivers/mtd/nand/raw/qcom_nandc.c
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/raw/r852.c
similarity index 100%
rename from drivers/mtd/nand/r852.c
rename to drivers/mtd/nand/raw/r852.c
diff --git a/drivers/mtd/nand/r852.h b/drivers/mtd/nand/raw/r852.h
similarity index 100%
rename from drivers/mtd/nand/r852.h
rename to drivers/mtd/nand/raw/r852.h
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c
similarity index 100%
rename from drivers/mtd/nand/s3c2410.c
rename to drivers/mtd/nand/raw/s3c2410.c
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c
similarity index 100%
rename from drivers/mtd/nand/sh_flctl.c
rename to drivers/mtd/nand/raw/sh_flctl.c
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c
similarity index 100%
rename from drivers/mtd/nand/sharpsl.c
rename to drivers/mtd/nand/raw/sharpsl.c
diff --git a/drivers/mtd/nand/sm_common.c b/drivers/mtd/nand/raw/sm_common.c
similarity index 100%
rename from drivers/mtd/nand/sm_common.c
rename to drivers/mtd/nand/raw/sm_common.c
diff --git a/drivers/mtd/nand/sm_common.h b/drivers/mtd/nand/raw/sm_common.h
similarity index 100%
rename from drivers/mtd/nand/sm_common.h
rename to drivers/mtd/nand/raw/sm_common.h
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c
similarity index 100%
rename from drivers/mtd/nand/socrates_nand.c
rename to drivers/mtd/nand/raw/socrates_nand.c
diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
similarity index 100%
rename from drivers/mtd/nand/sunxi_nand.c
rename to drivers/mtd/nand/raw/sunxi_nand.c
diff --git a/drivers/mtd/nand/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c
similarity index 100%
rename from drivers/mtd/nand/tango_nand.c
rename to drivers/mtd/nand/raw/tango_nand.c
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c
similarity index 100%
rename from drivers/mtd/nand/tmio_nand.c
rename to drivers/mtd/nand/raw/tmio_nand.c
diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c
similarity index 100%
rename from drivers/mtd/nand/txx9ndfmc.c
rename to drivers/mtd/nand/raw/txx9ndfmc.c
diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c
similarity index 100%
rename from drivers/mtd/nand/vf610_nfc.c
rename to drivers/mtd/nand/raw/vf610_nfc.c
diff --git a/drivers/mtd/nand/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c
similarity index 100%
rename from drivers/mtd/nand/xway_nand.c
rename to drivers/mtd/nand/raw/xway_nand.c
diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c
index 3692dd5..bcc851d 100644
--- a/drivers/mtd/sm_ftl.c
+++ b/drivers/mtd/sm_ftl.c
@@ -17,7 +17,7 @@
 #include <linux/bitops.h>
 #include <linux/slab.h>
 #include <linux/mtd/nand_ecc.h>
-#include "nand/sm_common.h"
+#include "nand/raw/sm_common.h"
 #include "sm_ftl.h"
 
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 03/15] mtd: nand: add a nand.h file to expose basic NAND stuff
  2017-05-24  7:06 [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Peter Pan
  2017-05-24  7:06 ` [PATCH v6 01/15] mtd: nand: Rename nand.h into rawnand.h Peter Pan
  2017-05-24  7:06 ` [PATCH v6 02/15] mtd: nand: move raw NAND related code to the raw/ subdir Peter Pan
@ 2017-05-24  7:06 ` Peter Pan
  2017-05-29 20:14   ` Boris Brezillon
  2017-05-24  7:07 ` [PATCH v6 04/15] mtd: nand: raw: prefix conflicting names with nandcchip instead of nand Peter Pan
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 65+ messages in thread
From: Peter Pan @ 2017-05-24  7:06 UTC (permalink / raw)
  To: boris.brezillon, richard, computersforpeace, arnaud.mouiche,
	thomas.petazzoni, marex, cyrille.pitchen, linux-mtd
  Cc: peterpandong, peterpansjtu, linshunquan1

From: Boris Brezillon <boris.brezillon@free-electrons.com>

Now that raw NAND header has been moved to rawnand.h, we can add a new
nand.h file and define the common nand stuff in there.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Peter Pan <peterpandong@micron.com>
---
 include/linux/mtd/nand.h | 569 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 569 insertions(+)
 create mode 100644 include/linux/mtd/nand.h

diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
new file mode 100644
index 0000000..446f941
--- /dev/null
+++ b/include/linux/mtd/nand.h
@@ -0,0 +1,569 @@
+/*
+ *  Copyright © 2016 - Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_MTD_NAND_H
+#define __LINUX_MTD_NAND_H
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/bbm.h>
+/**
+ * struct nand_memory_organization - memory organization structure
+ * @pagesize: page size
+ * @oobsize: OOB area size
+ * @eraseblocksize: erase block size
+ * @planesize: plane size
+ * @nplanes: number of planes embedded in a die
+ * @diesize: die size
+ * @ndies: number of dies embedded in the device
+ */
+struct nand_memory_organization {
+	int pagesize;
+	int oobsize;
+	int eraseblocksize;
+	size_t planesize;
+	int nplanes;
+	u64 diesize;
+	int ndies;
+};
+
+/**
+ * struct nand_bbt - bad block table structure
+ * @options: bad block specific options
+ * @td: bad block table descriptor for flash lookup.
+ * @md: bad block table mirror descriptor
+ * @bbp: bad block pattern
+ * @bbt: in memory BBT
+ */
+struct nand_bbt {
+	unsigned int options;
+	/*
+	 * Discourage new custom usages here; suggest usage of the
+	 * relevant NAND_BBT_* options instead
+	 */
+	struct nand_bbt_descr *td;
+	struct nand_bbt_descr *md;
+	struct nand_bbt_descr *bbp;
+	u8 *bbt;
+};
+
+struct nand_device;
+
+/**
+ * struct nand_ops - NAND operations
+ * @erase: erase the blocks covered by the erase_info description
+ */
+struct nand_ops {
+	int (*erase)(struct nand_device *nand, struct erase_info *einfo);
+	int (*markbad)(struct nand_device *mtd, int block);
+};
+
+/**
+ * struct nand_device - NAND device
+ * @mtd: MTD instance attached to the NAND device
+ * @memorg: memory layout
+ * @bbt: bad block table info
+ * @ops: NAND operations attached to the NAND device
+ */
+struct nand_device {
+	struct mtd_info mtd;
+	struct nand_memory_organization memorg;
+	struct nand_bbt bbt;
+
+	const struct nand_ops *ops;
+};
+
+/**
+ * mtd_to_nand - Get the NAND device attached to the MTD instance
+ * @mtd: MTD instance
+ *
+ * Returns the NAND device attached to @mtd.
+ */
+static inline struct nand_device *mtd_to_nand(struct mtd_info *mtd)
+{
+	return container_of(mtd, struct nand_device, mtd);
+}
+
+/**
+ * nand_to_mtd - Get the MTD device attached to a NAND device
+ * @nand: NAND device
+ *
+ * Returns the MTD device attached to @nand.
+ */
+static inline struct mtd_info *nand_to_mtd(struct nand_device *nand)
+{
+	return &nand->mtd;
+}
+
+/**
+ * nand_page_to_offs - Convert a page number to an absolute offset
+ * @nand: NAND device
+ * @page: page number
+ *
+ * Returns the offset pointing to the beginning of @page.
+ */
+static inline loff_t nand_page_to_offs(struct nand_device *nand, int page)
+{
+	return (loff_t)nand->memorg.pagesize * page;
+}
+
+/**
+ * nand_offs_to_page - Convert an absolute offset to a page offset
+ * @nand: NAND device
+ * @offs: absolute offset
+ *
+ * Returns the page number containing @offs.
+ */
+static inline int nand_offs_to_page(struct nand_device *nand, loff_t offs)
+{
+	u64 page = offs;
+
+	do_div(page, nand->memorg.pagesize);
+
+	return page;
+}
+
+/**
+ * nand_len_to_pages - Convert a length into a number of pages
+ * @nand: NAND device
+ * @len: length in bytes
+ *
+ * Returns the number of pages required to store @len bytes.
+ * This functions assumes your storing those data at a page-aligned offset.
+ */
+static inline int nand_len_to_pages(struct nand_device *nand, size_t len)
+{
+	return DIV_ROUND_UP(len, nand->memorg.pagesize);
+}
+
+/**
+ * nand_pages_to_len - Convert a number of pages into a length expressed in
+ *		       bytes
+ * @nand: NAND device
+ * @npages: number of pages
+ *
+ * Returns the size taken by @npages pages.
+ */
+static inline size_t nand_pages_to_len(struct nand_device *nand, int npages)
+{
+	return (size_t)npages * nand->memorg.pagesize;
+}
+
+/**
+ * nand_page_size - Get NAND page size
+ * @nand: NAND device
+ *
+ * Returns the page size.
+ */
+static inline size_t nand_page_size(struct nand_device *nand)
+{
+	return nand->memorg.pagesize;
+}
+
+/**
+ * nand_per_page_oobsize - Get NAND OOB size
+ * @nand: NAND device
+ *
+ * Returns the OOB size.
+ */
+static inline int nand_per_page_oobsize(struct nand_device *nand)
+{
+	return nand->memorg.oobsize;
+}
+
+/**
+ * nand_per_page_oobsize - Get NAND erase block size
+ * @nand: NAND device
+ *
+ * Returns the erase block size.
+ */
+static inline size_t nand_eraseblock_size(struct nand_device *nand)
+{
+	return nand->memorg.eraseblocksize;
+}
+
+/**
+ * nand_page_to_offs - Convert an eraseblock number to an absolute offset
+ * @nand: NAND device
+ * @block: eraseblock number
+ *
+ * Returns the offset pointing to the beginning of @block.
+ */
+static inline loff_t nand_eraseblock_to_offs(struct nand_device *nand,
+					     int block)
+{
+	return (loff_t)nand->memorg.eraseblocksize * block;
+}
+
+/**
+ * nand_offs_to_eraseblock - Convert an absolute offset to an eraseblock offset
+ * @nand: NAND device
+ * @offs: absolute offset
+ *
+ * Returns the eraseblock number containing @offs.
+ */
+static inline int nand_offs_to_eraseblock(struct nand_device *nand, loff_t offs)
+{
+	u64 block = offs;
+
+	do_div(block, nand->memorg.eraseblocksize);
+
+	return block;
+}
+
+/**
+ * nand_len_to_eraseblocks - Convert a length into a number of erablocks
+ * @nand: NAND device
+ * @len: length in bytes
+ *
+ * Returns the number of eraseblocks required to store @len bytes.
+ * This functions assumes your storing those data at an eraseblock-aligned
+ * offset.
+ */
+static inline int nand_len_to_eraseblocks(struct nand_device *nand, size_t len)
+{
+	return DIV_ROUND_UP(len, nand->memorg.eraseblocksize);
+}
+
+/**
+ * nand_eraseblocks_to_len - Convert a number of eraseblocks into a length
+ *			     expressed in bytes
+ * @nand: NAND device
+ * @nblocks: number of eraseblocks
+ *
+ * Returns the size taken by @nblock pages.
+ */
+static inline size_t nand_eraseblocks_to_len(struct nand_device *nand,
+					     int nblocks)
+{
+	return (size_t)nblocks * nand->memorg.eraseblocksize;
+}
+
+/**
+ * nand_per_eraseblock_oobsize - Get the amount of OOB bytes in an eraseblock
+ * @nand: NAND device
+ *
+ * Returns the OOB size per eraseblock.
+ */
+static inline int nand_per_eraseblock_oobsize(struct nand_device *nand)
+{
+	int pagesperblock = nand->memorg.eraseblocksize /
+			    nand->memorg.pagesize;
+
+	return nand->memorg.oobsize * pagesperblock;
+}
+
+/**
+ * nand_eraseblock_to_page - Convert an eraseblock number to a page number
+ * @nand: NAND device
+ * @block: eraseblock number
+ *
+ * Returns the page number assigned to the first page of @block eraseblock.
+ */
+static inline int nand_eraseblock_to_page(struct nand_device *nand, int block)
+{
+	int pagesperblock = nand->memorg.eraseblocksize /
+			    nand->memorg.pagesize;
+
+	return block * pagesperblock;
+}
+
+/**
+ * nand_page_to_eraseblock - Convert a page number to an eraseblock number
+ * @nand: NAND device
+ * @page: page number
+ *
+ * Returns the eraseblock number containing @page.
+ */
+static inline int nand_page_to_eraseblock(struct nand_device *nand, int page)
+{
+	int pagesperblock = nand->memorg.eraseblocksize /
+			    nand->memorg.pagesize;
+
+	return page / pagesperblock;
+}
+
+/**
+ * nand_eraseblocks_per_die - Get the number of eraseblocks per die
+ * @nand: NAND device
+ *
+ * Returns the number of eraseblocks per die.
+ */
+static inline int nand_eraseblocks_per_die(struct nand_device *nand)
+{
+	u64 nblocks = nand->memorg.diesize;
+
+	do_div(nblocks, nand->memorg.eraseblocksize);
+
+	return nblocks;
+}
+
+/**
+ * nand_eraseblocks_per_die - Get the number of eraseblocks per die
+ * @nand: NAND device
+ *
+ * Returns the number of eraseblocks per die.
+ */
+static inline u64 nand_diesize(struct nand_device *nand)
+{
+	return nand->memorg.diesize;
+}
+
+/**
+ * nand_ndies - Get the total of dies
+ * @nand: NAND device
+ *
+ * Returns the number of dies exposed by @nand.
+ */
+static inline int nand_ndies(struct nand_device *nand)
+{
+	return nand->memorg.ndies;
+}
+
+/**
+ * nand_die_to_offs - Convert a die number to an absolute offset
+ * @nand: NAND device
+ * @die: die number
+ *
+ * Returns the offset pointing to the beginning of @die.
+ */
+static inline loff_t nand_die_to_offs(struct nand_device *nand, int die)
+{
+	return (loff_t)nand->memorg.diesize * die;
+}
+
+/**
+ * nand_offs_to_die - Convert an absolute offset to a die number
+ * @nand: NAND device
+ * @offs: absolute offset
+ *
+ * Returns the die number containing @offs.
+ */
+static inline int nand_offs_to_die(struct nand_device *nand, loff_t offs)
+{
+	return div64_u64((u64)offs, nand->memorg.diesize);
+}
+
+/**
+ * nand_ndies - Get the total number of erasablocks
+ * @nand: NAND device
+ *
+ * Returns the number of eraseblocks exposed by @nand.
+ */
+static inline int nand_neraseblocks(struct nand_device *nand)
+{
+	u64 nblocks = nand->memorg.ndies * nand->memorg.diesize;
+
+	do_div(nblocks, nand->memorg.eraseblocksize);
+
+	return nblocks;
+}
+
+/**
+ * nand_size - Get NAND size
+ * @nand: NAND device
+ *
+ * Returns the total size exposed by @nand.
+ */
+static inline u64 nand_size(struct nand_device *nand)
+{
+	return nand->memorg.ndies * nand->memorg.diesize;
+}
+
+/**
+ * nand_check_address - check NAND address is valid or not
+ * @nand: NAND device
+ * @addr: address to check
+ *
+ * Returns 0 for valid address and -EINVAL for invalid address.
+ */
+static inline int nand_check_address(struct nand_device *nand, loff_t addr)
+{
+	return addr < nand_size(nand) ? 0 : -EINVAL;
+}
+
+/**
+ * nand_check_oob_ops - check mtd_oob_ops is valid or not
+ * @nand: NAND device
+ * @start: start address to check
+ * @ops: oob operation description struct
+ *
+ * Returns 0 for valid ops and -EINVAL for invalid ops.
+ */
+static inline int nand_check_oob_ops(struct nand_device *nand, loff_t start,
+				     struct mtd_oob_ops *ops)
+{
+	struct mtd_info *mtd = nand_to_mtd(nand);
+	int oobbytes_per_page = ops->mode == MTD_OPS_AUTO_OOB ?
+				mtd->oobavail : mtd->oobsize;
+	int pages = nand_len_to_pages(nand, nand_size(nand));
+	int max_pages = pages - nand_offs_to_page(nand, start);
+	int max_ooblen = max_pages * oobbytes_per_page;
+
+	if ((!!ops->datbuf != !!ops->len) ||
+	    (!!ops->oobbuf != !!ops->ooblen))
+		return -EINVAL;
+	if (ops->ooboffs >= oobbytes_per_page)
+		return -EINVAL;
+	if (ops->ooboffs + ops->ooblen > max_ooblen)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * nand_oob_ops_across_page - check oob operation across page or not
+ * @nand: NAND device
+ * @ops: oob operation description struct
+ *
+ * Returns true if oob operation across page and false when not.
+ */
+static inline bool nand_oob_ops_across_page(struct nand_device *nand,
+					    struct mtd_oob_ops *ops)
+{
+	struct mtd_info *mtd = nand_to_mtd(nand);
+	int oobbytes_per_page = ops->mode == MTD_OPS_AUTO_OOB ?
+				mtd->oobavail : mtd->oobsize;
+
+	return (ops->ooboffs + ops->ooblen) > oobbytes_per_page;
+}
+
+/**
+ * nand_check_erase_ops - check erase operation is valid or not
+ * @nand: NAND device
+ * @einfo: erase instruction
+ *
+ * Returns 0 for valid erase operation and -EINVAL for invalid.
+ */
+static inline int nand_check_erase_ops(struct nand_device *nand,
+				       struct erase_info *einfo)
+{
+	/* check address align on block boundary */
+	if (einfo->addr & (nand_eraseblock_size(nand) - 1))
+		return -EINVAL;
+	/* check lendth align on block boundary */
+	if (einfo->len & (nand_eraseblock_size(nand) - 1))
+		return -EINVAL;
+	/* Do not allow erase past end of device */
+	if ((einfo->addr + einfo->len) > nand_size(nand))
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * nand_register - Register a NAND device
+ * @nand: NAND device
+ *
+ * Register a NAND device.
+ * This function is just a wrapper around mtd_device_register()
+ * registering the MTD device attached to @nand.
+ */
+static inline int nand_register(struct nand_device *nand)
+{
+	return mtd_device_register(&nand->mtd, NULL, 0);
+}
+
+/**
+ * nand_unregister - Unregister a NAND device
+ * @nand: NAND device
+ *
+ * Unregister a NAND device.
+ * This function is just a wrapper around mtd_device_unregister()
+ * unregistering the MTD device attached to @nand.
+ */
+static inline int nand_unregister(struct nand_device *nand)
+{
+	return mtd_device_unregister(&nand->mtd);
+}
+
+/**
+ * nand_read - Read data from NAND
+ * @nand: NAND device
+ * @offs: offset you want to read data from
+ * @ops: options describing what you want to read (in-band/out-of-band data)
+ *	 and how (raw or normal mode)
+ *
+ * Read data from NAND.
+ */
+static inline int nand_read(struct nand_device *nand, loff_t offs,
+			    struct mtd_oob_ops *ops)
+{
+	return mtd_read_oob(&nand->mtd, offs, ops);
+}
+
+/**
+ * nand_write - Write data to NAND
+ * @nand: NAND device
+ * @offs: offset you want to write data to
+ * @ops: options describing what you want to write (in-band/out-of-band data)
+ *	 and how (raw or normal mode)
+ *
+ * Read data from NAND.
+ */
+static inline int nand_write(struct nand_device *nand, loff_t offs,
+			     struct mtd_oob_ops *ops)
+{
+	return mtd_write_oob(&nand->mtd, offs, ops);
+}
+
+/**
+ * nand_erase - Erase a NAND portion
+ * @nand: NAND device
+ * @einfo: erase information
+ * @force: whether bad or protected blocks should be erased or not
+ *
+ * Erase the NAND portion described by @einfo. If @force is passed, bad and
+ * reserved block checking is bypassed and the implementation is asked to
+ * force the erasure.
+ */
+static inline int nand_erase(struct nand_device *nand,
+			     struct erase_info *einfo,
+			     bool force)
+{
+	if (!force)
+		return mtd_erase(&nand->mtd, einfo);
+
+	return nand->ops->erase(nand, einfo);
+}
+
+/**
+ * nand_markbad - Write a bad block marker to a block
+ * @nand: NAND device
+ * @block: block to mark bad
+ *
+ * Mark a block bad. This function is not using the BBT.
+ */
+static inline int nand_markbad(struct nand_device *nand, int block)
+{
+	return nand->ops->markbad(nand, block);
+}
+
+/**
+ * nand_set_of_node - Attach a DT node to a NAND device
+ * @nand: NAND device
+ * @np: DT node
+ *
+ * Attach a DT node to a NAND device.
+ */
+static inline void nand_set_of_node(struct nand_device *nand,
+				    struct device_node *np)
+{
+	mtd_set_of_node(&nand->mtd, np);
+}
+
+/**
+ * nand_get_of_node - Retrieve the DT node attached a NAND device
+ * @nand: NAND device
+ *
+ * Returns the DT node attached to @nand.
+ */
+static inline struct device_node *nand_get_of_node(struct nand_device *nand)
+{
+	return mtd_get_of_node(&nand->mtd);
+}
+#endif /* __LINUX_MTD_NAND_H */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 04/15] mtd: nand: raw: prefix conflicting names with nandcchip instead of nand
  2017-05-24  7:06 [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Peter Pan
                   ` (2 preceding siblings ...)
  2017-05-24  7:06 ` [PATCH v6 03/15] mtd: nand: add a nand.h file to expose basic NAND stuff Peter Pan
@ 2017-05-24  7:07 ` Peter Pan
  2017-05-29 20:22   ` Boris Brezillon
  2017-05-24  7:07 ` [PATCH v6 05/15] mtd: nand: raw: create struct rawnand_device Peter Pan
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 65+ messages in thread
From: Peter Pan @ 2017-05-24  7:07 UTC (permalink / raw)
  To: boris.brezillon, richard, computersforpeace, arnaud.mouiche,
	thomas.petazzoni, marex, cyrille.pitchen, linux-mtd
  Cc: peterpandong, peterpansjtu, linshunquan1

From: Boris Brezillon <boris.brezillon@free-electrons.com>

Some raw NAND function names conflict with names defined in nand.h.
Prefix all those functions with nandchip instead of nand so we can
include nand.h from rawnand.h

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Peter Pan <peterpandong@micron.com>
---
 Documentation/DocBook/mtdnand.tmpl               |  10 +-
 arch/arm/mach-ep93xx/snappercl15.c               |   4 +-
 arch/arm/mach-ep93xx/ts72xx.c                    |   4 +-
 arch/arm/mach-imx/mach-qong.c                    |   2 +-
 arch/arm/mach-ixp4xx/ixdp425-setup.c             |   2 +-
 arch/arm/mach-omap1/board-nand.c                 |   2 +-
 arch/arm/mach-orion5x/ts78xx-setup.c             |   6 +-
 arch/arm/mach-pxa/balloon3.c                     |   2 +-
 arch/arm/mach-pxa/em-x270.c                      |   2 +-
 arch/arm/mach-pxa/palmtx.c                       |   2 +-
 arch/blackfin/mach-bf537/boards/stamp.c          |   2 +-
 arch/blackfin/mach-bf561/boards/acvilon.c        |   2 +-
 arch/cris/arch-v32/drivers/mach-a3/nandflash.c   |   4 +-
 arch/cris/arch-v32/drivers/mach-fs/nandflash.c   |   4 +-
 arch/mips/alchemy/devboards/db1200.c             |   2 +-
 arch/mips/alchemy/devboards/db1300.c             |   2 +-
 arch/mips/alchemy/devboards/db1550.c             |   2 +-
 arch/mips/jz4740/board-qi_lb60.c                 |   2 +-
 arch/mips/pnx833x/common/platform.c              |   2 +-
 arch/mips/rb532/devices.c                        |   2 +-
 arch/sh/boards/mach-migor/setup.c                |   2 +-
 drivers/mtd/nand/raw/ams-delta.c                 |   8 +-
 drivers/mtd/nand/raw/atmel/nand-controller.c     |  50 ++++----
 drivers/mtd/nand/raw/au1550nd.c                  |  26 ++---
 drivers/mtd/nand/raw/bcm47xxnflash/main.c        |   4 +-
 drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c |  18 +--
 drivers/mtd/nand/raw/bf5xx_nand.c                |  32 +++---
 drivers/mtd/nand/raw/brcmnand/brcmnand.c         |  32 +++---
 drivers/mtd/nand/raw/cafe_nand.c                 |  24 ++--
 drivers/mtd/nand/raw/cmx270_nand.c               |  12 +-
 drivers/mtd/nand/raw/cs553x_nand.c               |  20 ++--
 drivers/mtd/nand/raw/davinci_nand.c              |  14 +--
 drivers/mtd/nand/raw/denali.c                    |  14 +--
 drivers/mtd/nand/raw/diskonchip.c                |  68 +++++------
 drivers/mtd/nand/raw/docg4.c                     |  36 +++---
 drivers/mtd/nand/raw/fsl_elbc_nand.c             |  26 ++---
 drivers/mtd/nand/raw/fsl_ifc_nand.c              |  28 ++---
 drivers/mtd/nand/raw/fsl_upm.c                   |  12 +-
 drivers/mtd/nand/raw/fsmc_nand.c                 |  24 ++--
 drivers/mtd/nand/raw/gpio.c                      |   6 +-
 drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c        |   2 +-
 drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c       |  38 +++---
 drivers/mtd/nand/raw/hisi504_nand.c              |  24 ++--
 drivers/mtd/nand/raw/jz4740_nand.c               |  12 +-
 drivers/mtd/nand/raw/jz4780_nand.c               |   8 +-
 drivers/mtd/nand/raw/lpc32xx_mlc.c               |  16 +--
 drivers/mtd/nand/raw/lpc32xx_slc.c               |  20 ++--
 drivers/mtd/nand/raw/mpc5121_nfc.c               |  26 ++---
 drivers/mtd/nand/raw/mtk_nand.c                  |  38 +++---
 drivers/mtd/nand/raw/mxc_nand.c                  |  52 ++++-----
 drivers/mtd/nand/raw/nand_amd.c                  |   2 +-
 drivers/mtd/nand/raw/nand_base.c                 | 140 +++++++++++------------
 drivers/mtd/nand/raw/nand_bbt.c                  |  34 +++---
 drivers/mtd/nand/raw/nand_bch.c                  |   6 +-
 drivers/mtd/nand/raw/nand_ecc.c                  |   4 +-
 drivers/mtd/nand/raw/nand_hynix.c                |  10 +-
 drivers/mtd/nand/raw/nand_micron.c               |  10 +-
 drivers/mtd/nand/raw/nand_samsung.c              |   4 +-
 drivers/mtd/nand/raw/nand_toshiba.c              |   2 +-
 drivers/mtd/nand/raw/nandsim.c                   |  22 ++--
 drivers/mtd/nand/raw/ndfc.c                      |  18 +--
 drivers/mtd/nand/raw/nuc900_nand.c               |   8 +-
 drivers/mtd/nand/raw/omap2.c                     |  20 ++--
 drivers/mtd/nand/raw/orion_nand.c                |   8 +-
 drivers/mtd/nand/raw/oxnas_nand.c                |  12 +-
 drivers/mtd/nand/raw/pasemi_nand.c               |  10 +-
 drivers/mtd/nand/raw/plat_nand.c                 |   4 +-
 drivers/mtd/nand/raw/pxa3xx_nand.c               |  36 +++---
 drivers/mtd/nand/raw/qcom_nandc.c                |  28 ++---
 drivers/mtd/nand/raw/r852.c                      |   8 +-
 drivers/mtd/nand/raw/s3c2410.c                   |  16 +--
 drivers/mtd/nand/raw/sh_flctl.c                  |  10 +-
 drivers/mtd/nand/raw/sharpsl.c                   |   8 +-
 drivers/mtd/nand/raw/sm_common.c                 |   2 +-
 drivers/mtd/nand/raw/socrates_nand.c             |  12 +-
 drivers/mtd/nand/raw/sunxi_nand.c                |  58 +++++-----
 drivers/mtd/nand/raw/tango_nand.c                |  30 ++---
 drivers/mtd/nand/raw/tmio_nand.c                 |   8 +-
 drivers/mtd/nand/raw/txx9ndfmc.c                 |  14 +--
 drivers/mtd/nand/raw/vf610_nfc.c                 |   4 +-
 drivers/mtd/nand/raw/xway_nand.c                 |  10 +-
 drivers/staging/mt29f_spinand/mt29f_spinand.c    |   6 +-
 include/linux/mtd/rawnand.h                      |   4 +-
 include/linux/mtd/sh_flctl.h                     |   2 +-
 84 files changed, 661 insertions(+), 661 deletions(-)

diff --git a/Documentation/DocBook/mtdnand.tmpl b/Documentation/DocBook/mtdnand.tmpl
index 35ec715..5a3342c 100644
--- a/Documentation/DocBook/mtdnand.tmpl
+++ b/Documentation/DocBook/mtdnand.tmpl
@@ -169,7 +169,7 @@
 			The NAND chip structure embeds an mtd structure
 			which will be registered to the MTD subsystem.
 			You can extract a pointer to the mtd structure
-			from a nand_chip pointer using the nand_to_mtd()
+			from a nand_chip pointer using the nandchip_to_mtd()
 			helper.
 		</para>
 		<para>
@@ -237,7 +237,7 @@ static void board_hwcontrol(struct mtd_info *mtd, int cmd)
 		<programlisting>
 static void board_hwcontrol(struct mtd_info *mtd, int cmd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	switch(cmd){
 		case NAND_CTL_SETCLE: this->IO_ADDR_W |= CLE_ADRR_BIT;  break;
 		case NAND_CTL_CLRCLE: this->IO_ADDR_W &amp;= ~CLE_ADRR_BIT; break;
@@ -283,7 +283,7 @@ static int __init board_init (void)
 		goto out;
 	}
 
-	board_mtd = nand_to_mtd(this);
+	board_mtd = nandchip_to_mtd(this);
 
 	/* map physical address */
 	baseaddr = ioremap(CHIP_PHYSICAL_ADDRESS, 1024);
@@ -342,7 +342,7 @@ static void __exit board_cleanup (void)
 	iounmap(baseaddr);
 	
 	/* Free the MTD device structure */
-	kfree (mtd_to_nand(board_mtd));
+	kfree (mtd_to_nandchip(board_mtd));
 }
 module_exit(board_cleanup);
 #endif
@@ -398,7 +398,7 @@ static void board_select_chip (struct mtd_info *mtd, int chip)
 		<programlisting>
 static void board_select_chip (struct mtd_info *mtd, int chip)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	
 	/* Deselect all chips */
 	this->IO_ADDR_R &amp;= ~BOARD_NAND_ADDR_MASK;
diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c
index 8b29398..d6f6094 100644
--- a/arch/arm/mach-ep93xx/snappercl15.c
+++ b/arch/arm/mach-ep93xx/snappercl15.c
@@ -49,7 +49,7 @@
 static void snappercl15_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
 				      unsigned int ctrl)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	static u16 nand_state = SNAPPERCL15_NAND_WPN;
 	u16 set;
 
@@ -76,7 +76,7 @@ static void snappercl15_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
 
 static int snappercl15_nand_dev_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	return !!(__raw_readw(NAND_CTRL_ADDR(chip)) & SNAPPERCL15_NAND_RDY);
 }
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index 8745162..500ad463 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -63,7 +63,7 @@ static void __init ts72xx_map_io(void)
 static void ts72xx_nand_hwcontrol(struct mtd_info *mtd,
 				  int cmd, unsigned int ctrl)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (ctrl & NAND_CTRL_CHANGE) {
 		void __iomem *addr = chip->IO_ADDR_R;
@@ -85,7 +85,7 @@ static void ts72xx_nand_hwcontrol(struct mtd_info *mtd,
 
 static int ts72xx_nand_device_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	void __iomem *addr = chip->IO_ADDR_R;
 
 	addr += (1 << TS72XX_NAND_BUSY_ADDR_LINE);
diff --git a/arch/arm/mach-imx/mach-qong.c b/arch/arm/mach-imx/mach-qong.c
index 42a7000..eda2297 100644
--- a/arch/arm/mach-imx/mach-qong.c
+++ b/arch/arm/mach-imx/mach-qong.c
@@ -131,7 +131,7 @@ static void qong_init_nor_mtd(void)
  */
 static void qong_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 
 	if (cmd == NAND_CMD_NONE)
 		return;
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index 93b89291..33a07c7 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -76,7 +76,7 @@
 static void
 ixdp425_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int offset = (int)nand_get_controller_data(this);
 
 	if (ctrl & NAND_CTRL_CHANGE) {
diff --git a/arch/arm/mach-omap1/board-nand.c b/arch/arm/mach-omap1/board-nand.c
index 1bffbb4..617848c 100644
--- a/arch/arm/mach-omap1/board-nand.c
+++ b/arch/arm/mach-omap1/board-nand.c
@@ -22,7 +22,7 @@
 
 void omap1_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	unsigned long mask;
 
 	if (cmd == NAND_CMD_NONE)
diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c
index 9477873..23c5a69 100644
--- a/arch/arm/mach-orion5x/ts78xx-setup.c
+++ b/arch/arm/mach-orion5x/ts78xx-setup.c
@@ -134,7 +134,7 @@ static void ts78xx_ts_rtc_unload(void)
 static void ts78xx_ts_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
 			unsigned int ctrl)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 
 	if (ctrl & NAND_CTRL_CHANGE) {
 		unsigned char bits;
@@ -158,7 +158,7 @@ static int ts78xx_ts_nand_dev_ready(struct mtd_info *mtd)
 static void ts78xx_ts_nand_write_buf(struct mtd_info *mtd,
 			const uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	void __iomem *io_base = chip->IO_ADDR_W;
 	unsigned long off = ((unsigned long)buf & 3);
 	int sz;
@@ -185,7 +185,7 @@ static void ts78xx_ts_nand_write_buf(struct mtd_info *mtd,
 static void ts78xx_ts_nand_read_buf(struct mtd_info *mtd,
 			uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	void __iomem *io_base = chip->IO_ADDR_R;
 	unsigned long off = ((unsigned long)buf & 3);
 	int sz;
diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
index 33d7ef1..ea06411 100644
--- a/arch/arm/mach-pxa/balloon3.c
+++ b/arch/arm/mach-pxa/balloon3.c
@@ -573,7 +573,7 @@ static inline void balloon3_i2c_init(void) {}
 #if defined(CONFIG_MTD_NAND_PLATFORM)||defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
 static void balloon3_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	uint8_t balloon3_ctl_set = 0, balloon3_ctl_clr = 0;
 
 	if (ctrl & NAND_CTRL_CHANGE) {
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index 6d28035..e072cc7 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -288,7 +288,7 @@ static void nand_cs_off(void)
 static void em_x270_nand_cmd_ctl(struct mtd_info *mtd, int dat,
 				 unsigned int ctrl)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	unsigned long nandaddr = (unsigned long)this->IO_ADDR_W;
 
 	dsb();
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
index 47e3e38..7422e06 100644
--- a/arch/arm/mach-pxa/palmtx.c
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -250,7 +250,7 @@ static inline void palmtx_keys_init(void) {}
 static void palmtx_nand_cmd_ctl(struct mtd_info *mtd, int cmd,
 				 unsigned int ctrl)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	char __iomem *nandaddr = this->IO_ADDR_W;
 
 	if (cmd == NAND_CMD_NONE)
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index ab3034f..af8e8be 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -404,7 +404,7 @@ void sl811_port_power(struct device *dev, int is_on)
 #define BFIN_NAND_PLAT_ALE 1
 static void bfin_plat_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 
 	if (cmd == NAND_CMD_NONE)
 		return;
diff --git a/arch/blackfin/mach-bf561/boards/acvilon.c b/arch/blackfin/mach-bf561/boards/acvilon.c
index 696cc9d..763fa1f 100644
--- a/arch/blackfin/mach-bf561/boards/acvilon.c
+++ b/arch/blackfin/mach-bf561/boards/acvilon.c
@@ -267,7 +267,7 @@ struct i2c_pca9564_pf_platform_data pca9564_platform_data = {
 static void bfin_plat_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
 				    unsigned int ctrl)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 
 	if (cmd == NAND_CMD_NONE)
 		return;
diff --git a/arch/cris/arch-v32/drivers/mach-a3/nandflash.c b/arch/cris/arch-v32/drivers/mach-a3/nandflash.c
index 925a98e..eb22e7f 100644
--- a/arch/cris/arch-v32/drivers/mach-a3/nandflash.c
+++ b/arch/cris/arch-v32/drivers/mach-a3/nandflash.c
@@ -51,7 +51,7 @@ static void crisv32_hwcontrol(struct mtd_info *mtd, int cmd,
 {
 	unsigned long flags;
 	reg_pio_rw_dout dout;
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 
 	local_irq_save(flags);
 
@@ -147,7 +147,7 @@ struct mtd_info *__init crisv32_nand_flash_probe(void)
 
 	/* Get pointer to private data */
 	this = &wrapper->chip;
-	crisv32_mtd = nand_to_mtd(this);
+	crisv32_mtd = nandchip_to_mtd(this);
 
 	/* Set address of NAND IO lines */
 	this->IO_ADDR_R = read_cs;
diff --git a/arch/cris/arch-v32/drivers/mach-fs/nandflash.c b/arch/cris/arch-v32/drivers/mach-fs/nandflash.c
index 53b56a4..0f24c31 100644
--- a/arch/cris/arch-v32/drivers/mach-fs/nandflash.c
+++ b/arch/cris/arch-v32/drivers/mach-fs/nandflash.c
@@ -50,7 +50,7 @@ static void crisv32_hwcontrol(struct mtd_info *mtd, int cmd,
 {
 	unsigned long flags;
 	reg_gio_rw_pa_dout dout;
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 
 	local_irq_save(flags);
 
@@ -128,7 +128,7 @@ struct mtd_info *__init crisv32_nand_flash_probe(void)
 
 	/* Get pointer to private data */
 	this = &wrapper->chip;
-	crisv32_mtd = nand_to_mtd(this);
+	crisv32_mtd = nandchip_to_mtd(this);
 
 	pa_oe.oe |= 1 << CE_BIT;
 	pa_oe.oe |= 1 << ALE_BIT;
diff --git a/arch/mips/alchemy/devboards/db1200.c b/arch/mips/alchemy/devboards/db1200.c
index 8383100..c59401a 100644
--- a/arch/mips/alchemy/devboards/db1200.c
+++ b/arch/mips/alchemy/devboards/db1200.c
@@ -200,7 +200,7 @@ int __init db1200_board_setup(void)
 static void au1200_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
 				 unsigned int ctrl)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	unsigned long ioaddr = (unsigned long)this->IO_ADDR_W;
 
 	ioaddr &= 0xffffff00;
diff --git a/arch/mips/alchemy/devboards/db1300.c b/arch/mips/alchemy/devboards/db1300.c
index 3e7fbdb..0fefa40 100644
--- a/arch/mips/alchemy/devboards/db1300.c
+++ b/arch/mips/alchemy/devboards/db1300.c
@@ -151,7 +151,7 @@ static void __init db1300_gpio_config(void)
 static void au1300_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
 				 unsigned int ctrl)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	unsigned long ioaddr = (unsigned long)this->IO_ADDR_W;
 
 	ioaddr &= 0xffffff00;
diff --git a/arch/mips/alchemy/devboards/db1550.c b/arch/mips/alchemy/devboards/db1550.c
index 421bd57..28b7c33 100644
--- a/arch/mips/alchemy/devboards/db1550.c
+++ b/arch/mips/alchemy/devboards/db1550.c
@@ -128,7 +128,7 @@ int __init db1550_board_setup(void)
 static void au1550_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
 				 unsigned int ctrl)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	unsigned long ioaddr = (unsigned long)this->IO_ADDR_W;
 
 	ioaddr &= 0xffffff00;
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
index a5bd94b..712cf36 100644
--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -138,7 +138,7 @@ static void qi_lb60_nand_ident(struct platform_device *pdev,
 		struct mtd_info *mtd, struct mtd_partition **partitions,
 		int *num_partitions)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (chip->page_shift == 12) {
 		*partitions = qi_lb60_partitions_2gb;
diff --git a/arch/mips/pnx833x/common/platform.c b/arch/mips/pnx833x/common/platform.c
index a7a4e9f..4610f3f 100644
--- a/arch/mips/pnx833x/common/platform.c
+++ b/arch/mips/pnx833x/common/platform.c
@@ -180,7 +180,7 @@ struct pnx8xxx_port pnx8xxx_ports[] = {
 static void
 pnx833x_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	unsigned long nandaddr = (unsigned long)this->IO_ADDR_W;
 
 	if (cmd == NAND_CMD_NONE)
diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c
index 32ea3e6..b736745 100644
--- a/arch/mips/rb532/devices.c
+++ b/arch/mips/rb532/devices.c
@@ -148,7 +148,7 @@ static int rb532_dev_ready(struct mtd_info *mtd)
 
 static void rb532_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	unsigned char orbits, nandbits;
 
 	if (ctrl & NAND_CTRL_CHANGE) {
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index 0bcbe58..be81869 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -166,7 +166,7 @@
 static void migor_nand_flash_cmd_ctl(struct mtd_info *mtd, int cmd,
 				     unsigned int ctrl)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (cmd == NAND_CMD_NONE)
 		return;
diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
index dcec9cf..be6166c 100644
--- a/drivers/mtd/nand/raw/ams-delta.c
+++ b/drivers/mtd/nand/raw/ams-delta.c
@@ -64,7 +64,7 @@
 
 static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
 
 	writew(0, io_base + OMAP_MPUIO_IO_CNTL);
@@ -77,7 +77,7 @@ static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
 static u_char ams_delta_read_byte(struct mtd_info *mtd)
 {
 	u_char res;
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
 
 	gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 0);
@@ -190,7 +190,7 @@ static int ams_delta_init(struct platform_device *pdev)
 		goto out;
 	}
 
-	ams_delta_mtd = nand_to_mtd(this);
+	ams_delta_mtd = nandchip_to_mtd(this);
 	ams_delta_mtd->owner = THIS_MODULE;
 
 	/*
@@ -270,7 +270,7 @@ static int ams_delta_cleanup(struct platform_device *pdev)
 	iounmap(io_base);
 
 	/* Free the MTD device structure */
-	kfree(mtd_to_nand(ams_delta_mtd));
+	kfree(mtd_to_nandchip(ams_delta_mtd));
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c
index 9abfc5d..747bcd3 100644
--- a/drivers/mtd/nand/raw/atmel/nand-controller.c
+++ b/drivers/mtd/nand/raw/atmel/nand-controller.c
@@ -403,7 +403,7 @@ static int atmel_nand_dma_transfer(struct atmel_nand_controller *nc,
 
 static u8 atmel_nand_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct atmel_nand *nand = to_atmel_nand(chip);
 
 	return ioread8(nand->activecs->io.virt);
@@ -411,7 +411,7 @@ static u8 atmel_nand_read_byte(struct mtd_info *mtd)
 
 static u16 atmel_nand_read_word(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct atmel_nand *nand = to_atmel_nand(chip);
 
 	return ioread16(nand->activecs->io.virt);
@@ -419,7 +419,7 @@ static u16 atmel_nand_read_word(struct mtd_info *mtd)
 
 static void atmel_nand_write_byte(struct mtd_info *mtd, u8 byte)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct atmel_nand *nand = to_atmel_nand(chip);
 
 	if (chip->options & NAND_BUSWIDTH_16)
@@ -430,7 +430,7 @@ static void atmel_nand_write_byte(struct mtd_info *mtd, u8 byte)
 
 static void atmel_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct atmel_nand *nand = to_atmel_nand(chip);
 	struct atmel_nand_controller *nc;
 
@@ -455,7 +455,7 @@ static void atmel_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
 
 static void atmel_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct atmel_nand *nand = to_atmel_nand(chip);
 	struct atmel_nand_controller *nc;
 
@@ -480,7 +480,7 @@ static void atmel_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
 
 static int atmel_nand_dev_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct atmel_nand *nand = to_atmel_nand(chip);
 
 	return gpiod_get_value(nand->activecs->rb.gpio);
@@ -488,7 +488,7 @@ static int atmel_nand_dev_ready(struct mtd_info *mtd)
 
 static void atmel_nand_select_chip(struct mtd_info *mtd, int cs)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct atmel_nand *nand = to_atmel_nand(chip);
 
 	if (cs < 0 || cs >= nand->numcs) {
@@ -505,7 +505,7 @@ static void atmel_nand_select_chip(struct mtd_info *mtd, int cs)
 
 static int atmel_hsmc_nand_dev_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct atmel_nand *nand = to_atmel_nand(chip);
 	struct atmel_hsmc_nand_controller *nc;
 	u32 status;
@@ -519,7 +519,7 @@ static int atmel_hsmc_nand_dev_ready(struct mtd_info *mtd)
 
 static void atmel_hsmc_nand_select_chip(struct mtd_info *mtd, int cs)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct atmel_nand *nand = to_atmel_nand(chip);
 	struct atmel_hsmc_nand_controller *nc;
 
@@ -601,7 +601,7 @@ static int atmel_nfc_exec_op(struct atmel_hsmc_nand_controller *nc, bool poll)
 static void atmel_hsmc_nand_cmd_ctrl(struct mtd_info *mtd, int dat,
 				     unsigned int ctrl)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct atmel_nand *nand = to_atmel_nand(chip);
 	struct atmel_hsmc_nand_controller *nc;
 
@@ -628,7 +628,7 @@ static void atmel_hsmc_nand_cmd_ctrl(struct mtd_info *mtd, int dat,
 static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
 				unsigned int ctrl)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct atmel_nand *nand = to_atmel_nand(chip);
 	struct atmel_nand_controller *nc;
 
@@ -650,7 +650,7 @@ static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
 static void atmel_nfc_copy_to_sram(struct nand_chip *chip, const u8 *buf,
 				   bool oob_required)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct atmel_hsmc_nand_controller *nc;
 	int ret = -EIO;
 
@@ -673,7 +673,7 @@ static void atmel_nfc_copy_to_sram(struct nand_chip *chip, const u8 *buf,
 static void atmel_nfc_copy_from_sram(struct nand_chip *chip, u8 *buf,
 				     bool oob_required)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct atmel_hsmc_nand_controller *nc;
 	int ret = -EIO;
 
@@ -694,7 +694,7 @@ static void atmel_nfc_copy_from_sram(struct nand_chip *chip, u8 *buf,
 
 static void atmel_nfc_set_op_addr(struct nand_chip *chip, int page, int column)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct atmel_hsmc_nand_controller *nc;
 
 	nc = to_hsmc_nand_controller(chip->controller);
@@ -749,7 +749,7 @@ static void atmel_nand_pmecc_disable(struct nand_chip *chip, bool raw)
 static int atmel_nand_pmecc_generate_eccbytes(struct nand_chip *chip, bool raw)
 {
 	struct atmel_nand *nand = to_atmel_nand(chip);
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct atmel_nand_controller *nc;
 	struct mtd_oob_region oobregion;
 	void *eccbuf;
@@ -784,7 +784,7 @@ static int atmel_nand_pmecc_correct_data(struct nand_chip *chip, void *buf,
 					 bool raw)
 {
 	struct atmel_nand *nand = to_atmel_nand(chip);
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct atmel_nand_controller *nc;
 	struct mtd_oob_region oobregion;
 	int ret, i, max_bitflips = 0;
@@ -833,7 +833,7 @@ static int atmel_nand_pmecc_correct_data(struct nand_chip *chip, void *buf,
 static int atmel_nand_pmecc_write_pg(struct nand_chip *chip, const u8 *buf,
 				     bool oob_required, int page, bool raw)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct atmel_nand *nand = to_atmel_nand(chip);
 	int ret;
 
@@ -874,7 +874,7 @@ static int atmel_nand_pmecc_write_page_raw(struct mtd_info *mtd,
 static int atmel_nand_pmecc_read_pg(struct nand_chip *chip, u8 *buf,
 				    bool oob_required, int page, bool raw)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	int ret;
 
 	ret = atmel_nand_pmecc_enable(chip, NAND_ECC_READ, raw);
@@ -909,7 +909,7 @@ static int atmel_hsmc_nand_pmecc_write_pg(struct nand_chip *chip,
 					  const u8 *buf, bool oob_required,
 					  int page, bool raw)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct atmel_nand *nand = to_atmel_nand(chip);
 	struct atmel_hsmc_nand_controller *nc;
 	int ret;
@@ -979,7 +979,7 @@ static int atmel_hsmc_nand_pmecc_read_pg(struct nand_chip *chip, u8 *buf,
 					 bool oob_required, int page,
 					 bool raw)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct atmel_nand *nand = to_atmel_nand(chip);
 	struct atmel_hsmc_nand_controller *nc;
 	int ret;
@@ -1048,7 +1048,7 @@ static int atmel_hsmc_nand_pmecc_read_page_raw(struct mtd_info *mtd,
 
 static int atmel_nand_pmecc_init(struct nand_chip *chip)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct atmel_nand *nand = to_atmel_nand(chip);
 	struct atmel_nand_controller *nc;
 	struct atmel_pmecc_user_req req;
@@ -1179,7 +1179,7 @@ static void atmel_nand_init(struct atmel_nand_controller *nc,
 			    struct atmel_nand *nand)
 {
 	struct nand_chip *chip = &nand->base;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 
 	mtd->dev.parent = nc->dev;
 	nand->base.controller = &nc->base;
@@ -1241,7 +1241,7 @@ static void atmel_hsmc_nand_init(struct atmel_nand_controller *nc,
 static int atmel_nand_detect(struct atmel_nand *nand)
 {
 	struct nand_chip *chip = &nand->base;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct atmel_nand_controller *nc;
 	int ret;
 
@@ -1257,7 +1257,7 @@ static int atmel_nand_detect(struct atmel_nand *nand)
 static int atmel_nand_unregister(struct atmel_nand *nand)
 {
 	struct nand_chip *chip = &nand->base;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	int ret;
 
 	ret = mtd_device_unregister(mtd);
@@ -1273,7 +1273,7 @@ static int atmel_nand_unregister(struct atmel_nand *nand)
 static int atmel_nand_register(struct atmel_nand *nand)
 {
 	struct nand_chip *chip = &nand->base;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct atmel_nand_controller *nc;
 	int ret;
 
diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c
index 9d4a28f..f56ce91 100644
--- a/drivers/mtd/nand/raw/au1550nd.c
+++ b/drivers/mtd/nand/raw/au1550nd.c
@@ -38,7 +38,7 @@ struct au1550nd_ctx {
  */
 static u_char au_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	u_char ret = readb(this->IO_ADDR_R);
 	wmb(); /* drain writebuffer */
 	return ret;
@@ -53,7 +53,7 @@ static u_char au_read_byte(struct mtd_info *mtd)
  */
 static void au_write_byte(struct mtd_info *mtd, u_char byte)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	writeb(byte, this->IO_ADDR_W);
 	wmb(); /* drain writebuffer */
 }
@@ -66,7 +66,7 @@ static void au_write_byte(struct mtd_info *mtd, u_char byte)
  */
 static u_char au_read_byte16(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
 	wmb(); /* drain writebuffer */
 	return ret;
@@ -81,7 +81,7 @@ static u_char au_read_byte16(struct mtd_info *mtd)
  */
 static void au_write_byte16(struct mtd_info *mtd, u_char byte)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
 	wmb(); /* drain writebuffer */
 }
@@ -94,7 +94,7 @@ static void au_write_byte16(struct mtd_info *mtd, u_char byte)
  */
 static u16 au_read_word(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	u16 ret = readw(this->IO_ADDR_R);
 	wmb(); /* drain writebuffer */
 	return ret;
@@ -111,7 +111,7 @@ static u16 au_read_word(struct mtd_info *mtd)
 static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
 	int i;
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 
 	for (i = 0; i < len; i++) {
 		writeb(buf[i], this->IO_ADDR_W);
@@ -130,7 +130,7 @@ static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
 	int i;
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 
 	for (i = 0; i < len; i++) {
 		buf[i] = readb(this->IO_ADDR_R);
@@ -149,7 +149,7 @@ static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
 {
 	int i;
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	u16 *p = (u16 *) buf;
 	len >>= 1;
 
@@ -171,7 +171,7 @@ static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
 static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
 {
 	int i;
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	u16 *p = (u16 *) buf;
 	len >>= 1;
 
@@ -196,7 +196,7 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
 
 static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct au1550nd_ctx *ctx = container_of(this, struct au1550nd_ctx,
 						chip);
 
@@ -267,7 +267,7 @@ static void au1550_select_chip(struct mtd_info *mtd, int chip)
  */
 static void au1550_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct au1550nd_ctx *ctx = container_of(this, struct au1550nd_ctx,
 						chip);
 	int ce_override = 0, i;
@@ -440,7 +440,7 @@ static int au1550nd_probe(struct platform_device *pdev)
 	}
 
 	this = &ctx->chip;
-	mtd = nand_to_mtd(this);
+	mtd = nandchip_to_mtd(this);
 	mtd->dev.parent = &pdev->dev;
 
 	/* figure out which CS# r->start belongs to */
@@ -496,7 +496,7 @@ static int au1550nd_remove(struct platform_device *pdev)
 	struct au1550nd_ctx *ctx = platform_get_drvdata(pdev);
 	struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-	nand_release(nand_to_mtd(&ctx->chip));
+	nand_release(nandchip_to_mtd(&ctx->chip));
 	iounmap(ctx->base);
 	release_mem_region(r->start, 0x1000);
 	kfree(ctx);
diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/main.c b/drivers/mtd/nand/raw/bcm47xxnflash/main.c
index fb31429..564b53a 100644
--- a/drivers/mtd/nand/raw/bcm47xxnflash/main.c
+++ b/drivers/mtd/nand/raw/bcm47xxnflash/main.c
@@ -35,7 +35,7 @@ static int bcm47xxnflash_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	nand_set_controller_data(&b47n->nand_chip, b47n);
-	mtd = nand_to_mtd(&b47n->nand_chip);
+	mtd = nandchip_to_mtd(&b47n->nand_chip);
 	mtd->dev.parent = &pdev->dev;
 	b47n->cc = container_of(nflash, struct bcma_drv_cc, nflash);
 
@@ -65,7 +65,7 @@ static int bcm47xxnflash_remove(struct platform_device *pdev)
 {
 	struct bcm47xxnflash *nflash = platform_get_drvdata(pdev);
 
-	nand_release(nand_to_mtd(&nflash->nand_chip));
+	nand_release(nandchip_to_mtd(&nflash->nand_chip));
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c
index f1da4ea..78bfcdb 100644
--- a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c
+++ b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c
@@ -89,7 +89,7 @@ static int bcm47xxnflash_ops_bcm4706_poll(struct bcma_drv_cc *cc)
 static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf,
 					   int len)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
 
 	u32 ctlcode;
@@ -139,7 +139,7 @@ static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf,
 static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd,
 					    const uint8_t *buf, int len)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
 	struct bcma_drv_cc *cc = b47n->cc;
 
@@ -173,7 +173,7 @@ static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd,
 static void bcm47xxnflash_ops_bcm4706_cmd_ctrl(struct mtd_info *mtd, int cmd,
 					       unsigned int ctrl)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
 	u32 code = 0;
 
@@ -199,7 +199,7 @@ static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd,
 
 static int bcm47xxnflash_ops_bcm4706_dev_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
 
 	return !!(bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_CTL) & NCTL_READY);
@@ -216,7 +216,7 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
 					      unsigned command, int column,
 					      int page_addr)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
 	struct bcma_drv_cc *cc = b47n->cc;
 	u32 ctlcode;
@@ -312,7 +312,7 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
 
 static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
 	struct bcma_drv_cc *cc = b47n->cc;
 	u32 tmp = 0;
@@ -341,7 +341,7 @@ static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd)
 static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd,
 					       uint8_t *buf, int len)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
 
 	switch (b47n->curr_command) {
@@ -357,7 +357,7 @@ static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd,
 static void bcm47xxnflash_ops_bcm4706_write_buf(struct mtd_info *mtd,
 						const uint8_t *buf, int len)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
 
 	switch (b47n->curr_command) {
@@ -421,7 +421,7 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
 			(w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0));
 
 	/* Scan NAND */
-	err = nand_scan(nand_to_mtd(&b47n->nand_chip), 1);
+	err = nand_scan(nandchip_to_mtd(&b47n->nand_chip), 1);
 	if (err) {
 		pr_err("Could not scan NAND flash: %d\n", err);
 		goto exit;
diff --git a/drivers/mtd/nand/raw/bf5xx_nand.c b/drivers/mtd/nand/raw/bf5xx_nand.c
index 5655dca..790dbf6 100644
--- a/drivers/mtd/nand/raw/bf5xx_nand.c
+++ b/drivers/mtd/nand/raw/bf5xx_nand.c
@@ -162,9 +162,9 @@ struct bf5xx_nand_info {
 /*
  * Conversion functions
  */
-static struct bf5xx_nand_info *mtd_to_nand_info(struct mtd_info *mtd)
+static struct bf5xx_nand_info *mtd_to_nandchip_info(struct mtd_info *mtd)
 {
-	return container_of(mtd_to_nand(mtd), struct bf5xx_nand_info,
+	return container_of(mtd_to_nandchip(mtd), struct bf5xx_nand_info,
 			    chip);
 }
 
@@ -230,7 +230,7 @@ static int bf5xx_nand_devready(struct mtd_info *mtd)
 static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
 					u_char *read_ecc, u_char *calc_ecc)
 {
-	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
+	struct bf5xx_nand_info *info = mtd_to_nandchip_info(mtd);
 	u32 syndrome[5];
 	u32 calced, stored;
 	int i;
@@ -309,7 +309,7 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
 static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 					u_char *read_ecc, u_char *calc_ecc)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	int ret, bitflips = 0;
 
 	ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
@@ -341,8 +341,8 @@ static void bf5xx_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd,
 		const u_char *dat, u_char *ecc_code)
 {
-	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct bf5xx_nand_info *info = mtd_to_nandchip_info(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	u16 ecc0, ecc1;
 	u32 code[2];
 	u8 *p;
@@ -478,8 +478,8 @@ static irqreturn_t bf5xx_nand_dma_irq(int irq, void *dev_id)
 static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
 				uint8_t *buf, int is_read)
 {
-	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct bf5xx_nand_info *info = mtd_to_nandchip_info(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	unsigned short val;
 
 	dev_dbg(info->device, " mtd->%p, buf->%p, is_read %d\n",
@@ -544,8 +544,8 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
 static void bf5xx_nand_dma_read_buf(struct mtd_info *mtd,
 					uint8_t *buf, int len)
 {
-	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct bf5xx_nand_info *info = mtd_to_nandchip_info(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	dev_dbg(info->device, "mtd->%p, buf->%p, int %d\n", mtd, buf, len);
 
@@ -558,8 +558,8 @@ static void bf5xx_nand_dma_read_buf(struct mtd_info *mtd,
 static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd,
 				const uint8_t *buf, int len)
 {
-	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct bf5xx_nand_info *info = mtd_to_nandchip_info(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	dev_dbg(info->device, "mtd->%p, buf->%p, len %d\n", mtd, buf, len);
 
@@ -673,7 +673,7 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info)
  */
 static int bf5xx_nand_add_partition(struct bf5xx_nand_info *info)
 {
-	struct mtd_info *mtd = nand_to_mtd(&info->chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&info->chip);
 	struct mtd_partition *parts = info->platform->partitions;
 	int nr = info->platform->nr_partitions;
 
@@ -688,7 +688,7 @@ static int bf5xx_nand_remove(struct platform_device *pdev)
 	 * and their partitions, then go through freeing the
 	 * resources used
 	 */
-	nand_release(nand_to_mtd(&info->chip));
+	nand_release(nandchip_to_mtd(&info->chip));
 
 	peripheral_free_list(bfin_nfc_pin_req);
 	bf5xx_nand_dma_remove(info);
@@ -698,7 +698,7 @@ static int bf5xx_nand_remove(struct platform_device *pdev)
 
 static int bf5xx_nand_scan(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	int ret;
 
 	ret = nand_scan_ident(mtd, 1, NULL);
@@ -768,7 +768,7 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
 
 	/* initialise chip data struct */
 	chip = &info->chip;
-	mtd = nand_to_mtd(&info->chip);
+	mtd = nandchip_to_mtd(&info->chip);
 
 	if (plat->data_width)
 		chip->options |= NAND_BUSWIDTH_16;
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
index e0eb51d..c3c22ba 100644
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
@@ -872,7 +872,7 @@ static inline bool is_hamming_ecc(struct brcmnand_controller *ctrl,
 static int brcmnand_hamming_ooblayout_ecc(struct mtd_info *mtd, int section,
 					  struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct brcmnand_host *host = nand_get_controller_data(chip);
 	struct brcmnand_cfg *cfg = &host->hwcfg;
 	int sas = cfg->spare_area_size << cfg->sector_size_1k;
@@ -890,7 +890,7 @@ static int brcmnand_hamming_ooblayout_ecc(struct mtd_info *mtd, int section,
 static int brcmnand_hamming_ooblayout_free(struct mtd_info *mtd, int section,
 					   struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct brcmnand_host *host = nand_get_controller_data(chip);
 	struct brcmnand_cfg *cfg = &host->hwcfg;
 	int sas = cfg->spare_area_size << cfg->sector_size_1k;
@@ -930,7 +930,7 @@ static int brcmnand_hamming_ooblayout_free(struct mtd_info *mtd, int section,
 static int brcmnand_bch_ooblayout_ecc(struct mtd_info *mtd, int section,
 				      struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct brcmnand_host *host = nand_get_controller_data(chip);
 	struct brcmnand_cfg *cfg = &host->hwcfg;
 	int sas = cfg->spare_area_size << cfg->sector_size_1k;
@@ -948,7 +948,7 @@ static int brcmnand_bch_ooblayout_ecc(struct mtd_info *mtd, int section,
 static int brcmnand_bch_ooblayout_free_lp(struct mtd_info *mtd, int section,
 					  struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct brcmnand_host *host = nand_get_controller_data(chip);
 	struct brcmnand_cfg *cfg = &host->hwcfg;
 	int sas = cfg->spare_area_size << cfg->sector_size_1k;
@@ -974,7 +974,7 @@ static int brcmnand_bch_ooblayout_free_lp(struct mtd_info *mtd, int section,
 static int brcmnand_bch_ooblayout_free_sp(struct mtd_info *mtd, int section,
 					  struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct brcmnand_host *host = nand_get_controller_data(chip);
 	struct brcmnand_cfg *cfg = &host->hwcfg;
 	int sas = cfg->spare_area_size << cfg->sector_size_1k;
@@ -1007,7 +1007,7 @@ static int brcmnand_bch_ooblayout_free_sp(struct mtd_info *mtd, int section,
 static int brcmstb_choose_ecc_layout(struct brcmnand_host *host)
 {
 	struct brcmnand_cfg *p = &host->hwcfg;
-	struct mtd_info *mtd = nand_to_mtd(&host->chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&host->chip);
 	struct nand_ecc_ctrl *ecc = &host->chip.ecc;
 	unsigned int ecc_level = p->ecc_level;
 	int sas = p->spare_area_size << p->sector_size_1k;
@@ -1046,7 +1046,7 @@ static int brcmstb_choose_ecc_layout(struct brcmnand_host *host)
 
 static void brcmnand_wp(struct mtd_info *mtd, int wp)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct brcmnand_host *host = nand_get_controller_data(chip);
 	struct brcmnand_controller *ctrl = host->ctrl;
 
@@ -1239,7 +1239,7 @@ static void brcmnand_cmd_ctrl(struct mtd_info *mtd, int dat,
 
 static int brcmnand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct brcmnand_host *host = nand_get_controller_data(chip);
 	struct brcmnand_controller *ctrl = host->ctrl;
 	unsigned long timeo = msecs_to_jiffies(100);
@@ -1274,7 +1274,7 @@ static int brcmnand_low_level_op(struct brcmnand_host *host,
 				 enum brcmnand_llop_type type, u32 data,
 				 bool last_op)
 {
-	struct mtd_info *mtd = nand_to_mtd(&host->chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&host->chip);
 	struct nand_chip *chip = &host->chip;
 	struct brcmnand_controller *ctrl = host->ctrl;
 	u32 tmp;
@@ -1313,7 +1313,7 @@ static int brcmnand_low_level_op(struct brcmnand_host *host,
 static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command,
 			     int column, int page_addr)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct brcmnand_host *host = nand_get_controller_data(chip);
 	struct brcmnand_controller *ctrl = host->ctrl;
 	u64 addr = (u64)page_addr << chip->page_shift;
@@ -1419,7 +1419,7 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command,
 
 static uint8_t brcmnand_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct brcmnand_host *host = nand_get_controller_data(chip);
 	struct brcmnand_controller *ctrl = host->ctrl;
 	uint8_t ret = 0;
@@ -1486,7 +1486,7 @@ static void brcmnand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
 				   int len)
 {
 	int i;
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct brcmnand_host *host = nand_get_controller_data(chip);
 
 	switch (host->last_cmd) {
@@ -2083,7 +2083,7 @@ static inline int get_blk_adr_bytes(u64 size, u32 writesize)
 
 static int brcmnand_setup_dev(struct brcmnand_host *host)
 {
-	struct mtd_info *mtd = nand_to_mtd(&host->chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&host->chip);
 	struct nand_chip *chip = &host->chip;
 	struct brcmnand_controller *ctrl = host->ctrl;
 	struct brcmnand_cfg *cfg = &host->hwcfg;
@@ -2223,7 +2223,7 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn)
 		return -ENXIO;
 	}
 
-	mtd = nand_to_mtd(&host->chip);
+	mtd = nandchip_to_mtd(&host->chip);
 	chip = &host->chip;
 
 	nand_set_flash_node(chip, dn);
@@ -2369,7 +2369,7 @@ static int brcmnand_resume(struct device *dev)
 
 	list_for_each_entry(host, &ctrl->host_list, node) {
 		struct nand_chip *chip = &host->chip;
-		struct mtd_info *mtd = nand_to_mtd(chip);
+		struct mtd_info *mtd = nandchip_to_mtd(chip);
 
 		brcmnand_save_restore_cs_config(host, 1);
 
@@ -2601,7 +2601,7 @@ int brcmnand_remove(struct platform_device *pdev)
 	struct brcmnand_host *host;
 
 	list_for_each_entry(host, &ctrl->host_list, node)
-		nand_release(nand_to_mtd(&host->chip));
+		nand_release(nandchip_to_mtd(&host->chip));
 
 	clk_disable_unprepare(ctrl->clk);
 
diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index 0541c64..7b4bf88 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -101,7 +101,7 @@ struct cafe_priv {
 
 static int cafe_device_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 	int result = !!(cafe_readl(cafe, NAND_STATUS) & 0x40000000);
 	uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
@@ -118,7 +118,7 @@ static int cafe_device_ready(struct mtd_info *mtd)
 
 static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 
 	if (usedma)
@@ -134,7 +134,7 @@ static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 
 static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 
 	if (usedma)
@@ -149,7 +149,7 @@ static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 
 static uint8_t cafe_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 	uint8_t d;
 
@@ -162,7 +162,7 @@ static uint8_t cafe_read_byte(struct mtd_info *mtd)
 static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 			      int column, int page_addr)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 	int adrbytes = 0;
 	uint32_t ctl1;
@@ -318,7 +318,7 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 
 static void cafe_select_chip(struct mtd_info *mtd, int chipnr)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 
 	cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
@@ -334,7 +334,7 @@ static void cafe_select_chip(struct mtd_info *mtd, int chipnr)
 static irqreturn_t cafe_nand_interrupt(int irq, void *id)
 {
 	struct mtd_info *mtd = id;
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 	uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
 	cafe_writel(cafe, irqs & ~0x90000000, NAND_IRQ);
@@ -462,7 +462,7 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 static int cafe_ooblayout_ecc(struct mtd_info *mtd, int section,
 			      struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (section)
 		return -ERANGE;
@@ -476,7 +476,7 @@ static int cafe_ooblayout_ecc(struct mtd_info *mtd, int section,
 static int cafe_ooblayout_free(struct mtd_info *mtd, int section,
 			       struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (section)
 		return -ERANGE;
@@ -630,7 +630,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 	if (!cafe)
 		return  -ENOMEM;
 
-	mtd = nand_to_mtd(&cafe->nand);
+	mtd = nandchip_to_mtd(&cafe->nand);
 	mtd->dev.parent = &pdev->dev;
 	nand_set_controller_data(&cafe->nand, cafe);
 
@@ -818,7 +818,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 static void cafe_nand_remove(struct pci_dev *pdev)
 {
 	struct mtd_info *mtd = pci_get_drvdata(pdev);
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 
 	/* Disable NAND IRQ in global IRQ mask register */
@@ -846,7 +846,7 @@ static int cafe_nand_resume(struct pci_dev *pdev)
 {
 	uint32_t ctrl;
 	struct mtd_info *mtd = pci_get_drvdata(pdev);
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 
        /* Start off by resetting the NAND controller completely */
diff --git a/drivers/mtd/nand/raw/cmx270_nand.c b/drivers/mtd/nand/raw/cmx270_nand.c
index 1fc435f..b85ccab 100644
--- a/drivers/mtd/nand/raw/cmx270_nand.c
+++ b/drivers/mtd/nand/raw/cmx270_nand.c
@@ -53,7 +53,7 @@
 
 static u_char cmx270_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 
 	return (readl(this->IO_ADDR_R) >> 16);
 }
@@ -61,7 +61,7 @@ static u_char cmx270_read_byte(struct mtd_info *mtd)
 static void cmx270_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
 	int i;
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 
 	for (i=0; i<len; i++)
 		writel((*buf++ << 16), this->IO_ADDR_W);
@@ -70,7 +70,7 @@ static void cmx270_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 static void cmx270_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
 	int i;
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 
 	for (i=0; i<len; i++)
 		*buf++ = readl(this->IO_ADDR_R) >> 16;
@@ -94,7 +94,7 @@ static void nand_cs_off(void)
 static void cmx270_hwcontrol(struct mtd_info *mtd, int dat,
 			     unsigned int ctrl)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	unsigned int nandaddr = (unsigned int)this->IO_ADDR_W;
 
 	dsb();
@@ -173,7 +173,7 @@ static int __init cmx270_init(void)
 		goto err_ioremap;
 	}
 
-	cmx270_nand_mtd = nand_to_mtd(this);
+	cmx270_nand_mtd = nandchip_to_mtd(this);
 
 	/* Link the private data with the MTD structure */
 	cmx270_nand_mtd->owner = THIS_MODULE;
@@ -237,7 +237,7 @@ static void __exit cmx270_cleanup(void)
 
 	iounmap(cmx270_nand_io);
 
-	kfree(mtd_to_nand(cmx270_nand_mtd));
+	kfree(mtd_to_nandchip(cmx270_nand_mtd));
 }
 module_exit(cmx270_cleanup);
 
diff --git a/drivers/mtd/nand/raw/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c
index d488775..63149e2 100644
--- a/drivers/mtd/nand/raw/cs553x_nand.c
+++ b/drivers/mtd/nand/raw/cs553x_nand.c
@@ -97,7 +97,7 @@
 
 static void cs553x_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 
 	while (unlikely(len > 0x800)) {
 		memcpy_fromio(buf, this->IO_ADDR_R, 0x800);
@@ -109,7 +109,7 @@ static void cs553x_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 
 static void cs553x_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 
 	while (unlikely(len > 0x800)) {
 		memcpy_toio(this->IO_ADDR_R, buf, 0x800);
@@ -121,13 +121,13 @@ static void cs553x_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 
 static unsigned char cs553x_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	return readb(this->IO_ADDR_R);
 }
 
 static void cs553x_write_byte(struct mtd_info *mtd, u_char byte)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int i = 100000;
 
 	while (i && readb(this->IO_ADDR_R + MM_NAND_STS) & CS_NAND_CTLR_BUSY) {
@@ -140,7 +140,7 @@ static void cs553x_write_byte(struct mtd_info *mtd, u_char byte)
 static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd,
 			     unsigned int ctrl)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	void __iomem *mmio_base = this->IO_ADDR_R;
 	if (ctrl & NAND_CTRL_CHANGE) {
 		unsigned char ctl = (ctrl & ~NAND_CTRL_CHANGE ) ^ 0x01;
@@ -152,7 +152,7 @@ static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd,
 
 static int cs553x_device_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	void __iomem *mmio_base = this->IO_ADDR_R;
 	unsigned char foo = readb(mmio_base + MM_NAND_STS);
 
@@ -161,7 +161,7 @@ static int cs553x_device_ready(struct mtd_info *mtd)
 
 static void cs_enable_hwecc(struct mtd_info *mtd, int mode)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	void __iomem *mmio_base = this->IO_ADDR_R;
 
 	writeb(0x07, mmio_base + MM_NAND_ECC_CTL);
@@ -170,7 +170,7 @@ static void cs_enable_hwecc(struct mtd_info *mtd, int mode)
 static int cs_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
 {
 	uint32_t ecc;
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	void __iomem *mmio_base = this->IO_ADDR_R;
 
 	ecc = readl(mmio_base + MM_NAND_STS);
@@ -203,7 +203,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
 		goto out;
 	}
 
-	new_mtd = nand_to_mtd(this);
+	new_mtd = nandchip_to_mtd(this);
 
 	/* Link the private data with the MTD structure */
 	new_mtd->owner = THIS_MODULE;
@@ -334,7 +334,7 @@ static void __exit cs553x_cleanup(void)
 		if (!mtd)
 			continue;
 
-		this = mtd_to_nand(mtd);
+		this = mtd_to_nandchip(mtd);
 		mmio_base = this->IO_ADDR_R;
 
 		/* Release resources, unregister device */
diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
index ccc8c43..73b696a 100644
--- a/drivers/mtd/nand/raw/davinci_nand.c
+++ b/drivers/mtd/nand/raw/davinci_nand.c
@@ -79,7 +79,7 @@ struct davinci_nand_info {
 
 static inline struct davinci_nand_info *to_davinci_nand(struct mtd_info *mtd)
 {
-	return container_of(mtd_to_nand(mtd), struct davinci_nand_info, chip);
+	return container_of(mtd_to_nandchip(mtd), struct davinci_nand_info, chip);
 }
 
 static inline unsigned int davinci_nand_readl(struct davinci_nand_info *info,
@@ -105,7 +105,7 @@ static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd,
 {
 	struct davinci_nand_info	*info = to_davinci_nand(mtd);
 	uint32_t			addr = info->current_cs;
-	struct nand_chip		*nand = mtd_to_nand(mtd);
+	struct nand_chip		*nand = mtd_to_nandchip(mtd);
 
 	/* Did the control lines change? */
 	if (ctrl & NAND_CTRL_CHANGE) {
@@ -191,7 +191,7 @@ static int nand_davinci_calculate_1bit(struct mtd_info *mtd,
 static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat,
 				     u_char *read_ecc, u_char *calc_ecc)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	uint32_t eccNand = read_ecc[0] | (read_ecc[1] << 8) |
 					  (read_ecc[2] << 16);
 	uint32_t eccCalc = calc_ecc[0] | (calc_ecc[1] << 8) |
@@ -441,7 +441,7 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd,
  */
 static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if ((0x03 & ((unsigned)buf)) == 0 && (0x03 & len) == 0)
 		ioread32_rep(chip->IO_ADDR_R, buf, len >> 2);
@@ -454,7 +454,7 @@ static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 static void nand_davinci_write_buf(struct mtd_info *mtd,
 		const uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if ((0x03 & ((unsigned)buf)) == 0 && (0x03 & len) == 0)
 		iowrite32_rep(chip->IO_ADDR_R, buf, len >> 2);
@@ -665,7 +665,7 @@ static int nand_davinci_probe(struct platform_device *pdev)
 	info->base		= base;
 	info->vaddr		= vaddr;
 
-	mtd			= nand_to_mtd(&info->chip);
+	mtd			= nandchip_to_mtd(&info->chip);
 	mtd->dev.parent		= &pdev->dev;
 	nand_set_flash_node(&info->chip, pdev->dev.of_node);
 
@@ -854,7 +854,7 @@ static int nand_davinci_remove(struct platform_device *pdev)
 		ecc4_busy = false;
 	spin_unlock_irq(&davinci_nand_lock);
 
-	nand_release(nand_to_mtd(&info->chip));
+	nand_release(nandchip_to_mtd(&info->chip));
 
 	clk_disable_unprepare(info->clk);
 
diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c
index 16634df..2e19fb3 100644
--- a/drivers/mtd/nand/raw/denali.c
+++ b/drivers/mtd/nand/raw/denali.c
@@ -74,7 +74,7 @@
  */
 static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd)
 {
-	return container_of(mtd_to_nand(mtd), struct denali_nand_info, nand);
+	return container_of(mtd_to_nandchip(mtd), struct denali_nand_info, nand);
 }
 
 /*
@@ -855,7 +855,7 @@ static int denali_hw_ecc_fixup(struct mtd_info *mtd,
 			       struct denali_nand_info *denali,
 			       unsigned long *uncor_ecc_flags)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	int bank = denali->flash_bank;
 	uint32_t ecc_cor;
 	unsigned int max_bitflips;
@@ -1357,7 +1357,7 @@ static int denali_ooblayout_ecc(struct mtd_info *mtd, int section,
 				struct mtd_oob_region *oobregion)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (section)
 		return -ERANGE;
@@ -1372,7 +1372,7 @@ static int denali_ooblayout_free(struct mtd_info *mtd, int section,
 				 struct mtd_oob_region *oobregion)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (section)
 		return -ERANGE;
@@ -1436,7 +1436,7 @@ static void denali_drv_init(struct denali_nand_info *denali)
 static int denali_multidev_fixup(struct denali_nand_info *denali)
 {
 	struct nand_chip *chip = &denali->nand;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 
 	/*
 	 * Support for multi device:
@@ -1487,7 +1487,7 @@ static int denali_multidev_fixup(struct denali_nand_info *denali)
 int denali_init(struct denali_nand_info *denali)
 {
 	struct nand_chip *chip = &denali->nand;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&denali->nand);
 	int ret;
 
 	if (denali->platform == INTEL_CE4100) {
@@ -1647,7 +1647,7 @@ int denali_init(struct denali_nand_info *denali)
 /* driver exit point */
 void denali_remove(struct denali_nand_info *denali)
 {
-	struct mtd_info *mtd = nand_to_mtd(&denali->nand);
+	struct mtd_info *mtd = nandchip_to_mtd(&denali->nand);
 	/*
 	 * Pre-compute DMA buffer size to avoid any problems in case
 	 * nand_release() ever changes in a way that mtd->writesize and
diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c
index c3aa53c..5c2dc9b 100644
--- a/drivers/mtd/nand/raw/diskonchip.c
+++ b/drivers/mtd/nand/raw/diskonchip.c
@@ -295,7 +295,7 @@ static inline int DoC_WaitReady(struct doc_priv *doc)
 
 static void doc2000_write_byte(struct mtd_info *mtd, u_char datum)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 
@@ -307,7 +307,7 @@ static void doc2000_write_byte(struct mtd_info *mtd, u_char datum)
 
 static u_char doc2000_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 	u_char ret;
@@ -322,7 +322,7 @@ static u_char doc2000_read_byte(struct mtd_info *mtd)
 
 static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 	int i;
@@ -339,7 +339,7 @@ static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
 
 static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 	int i;
@@ -354,7 +354,7 @@ static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len)
 
 static void doc2000_readbuf_dword(struct mtd_info *mtd, u_char *buf, int len)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 	int i;
@@ -375,7 +375,7 @@ static void doc2000_readbuf_dword(struct mtd_info *mtd, u_char *buf, int len)
 
 static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	uint16_t ret;
 
@@ -421,7 +421,7 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
 
 static void __init doc2000_count_chips(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	uint16_t mfrid;
 	int i;
@@ -457,7 +457,7 @@ static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this)
 
 static void doc2001_write_byte(struct mtd_info *mtd, u_char datum)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 
@@ -468,7 +468,7 @@ static void doc2001_write_byte(struct mtd_info *mtd, u_char datum)
 
 static u_char doc2001_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 
@@ -482,7 +482,7 @@ static u_char doc2001_read_byte(struct mtd_info *mtd)
 
 static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 	int i;
@@ -495,7 +495,7 @@ static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
 
 static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 	int i;
@@ -512,7 +512,7 @@ static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len)
 
 static u_char doc2001plus_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 	u_char ret;
@@ -527,7 +527,7 @@ static u_char doc2001plus_read_byte(struct mtd_info *mtd)
 
 static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 	int i;
@@ -545,7 +545,7 @@ static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int le
 
 static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 	int i;
@@ -576,7 +576,7 @@ static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len)
 
 static void doc2001plus_select_chip(struct mtd_info *mtd, int chip)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 	int floor = 0;
@@ -603,7 +603,7 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip)
 
 static void doc200x_select_chip(struct mtd_info *mtd, int chip)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 	int floor = 0;
@@ -634,7 +634,7 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip)
 static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
 			      unsigned int ctrl)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 
@@ -657,7 +657,7 @@ static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
 
 static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 
@@ -763,7 +763,7 @@ static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int colu
 
 static int doc200x_dev_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 
@@ -803,7 +803,7 @@ static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs)
 
 static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 
@@ -822,7 +822,7 @@ static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode)
 
 static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 
@@ -842,7 +842,7 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode)
 /* This code is only called on write */
 static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, unsigned char *ecc_code)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 	int i;
@@ -903,7 +903,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,
 				u_char *read_ecc, u_char *isnull)
 {
 	int i, ret = 0;
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	void __iomem *docptr = doc->virtadr;
 	uint8_t calc_ecc[6];
@@ -1004,7 +1004,7 @@ static int doc200x_ooblayout_free(struct mtd_info *mtd, int section,
    mh1_page in the DOC private structure. */
 static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const char *id, int findmirror)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	unsigned offs;
 	int ret;
@@ -1047,7 +1047,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const ch
 
 static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	int ret = 0;
 	u_char *buf;
@@ -1149,7 +1149,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio
 /* This is a stripped-down copy of the code in inftlmount.c */
 static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	int ret = 0;
 	u_char *buf;
@@ -1269,7 +1269,7 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti
 static int __init nftl_scan_bbt(struct mtd_info *mtd)
 {
 	int ret, numparts;
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	struct mtd_partition parts[2];
 
@@ -1304,7 +1304,7 @@ static int __init nftl_scan_bbt(struct mtd_info *mtd)
 static int __init inftl_scan_bbt(struct mtd_info *mtd)
 {
 	int ret, numparts;
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 	struct mtd_partition parts[5];
 
@@ -1357,7 +1357,7 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd)
 
 static inline int __init doc2000_init(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 
 	this->read_byte = doc2000_read_byte;
@@ -1373,7 +1373,7 @@ static inline int __init doc2000_init(struct mtd_info *mtd)
 
 static inline int __init doc2001_init(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 
 	this->read_byte = doc2001_read_byte;
@@ -1403,7 +1403,7 @@ static inline int __init doc2001_init(struct mtd_info *mtd)
 
 static inline int __init doc2001plus_init(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
 
 	this->read_byte = doc2001plus_read_byte;
@@ -1520,7 +1520,7 @@ static int __init doc_probe(unsigned long physadr)
 	for (mtd = doclist; mtd; mtd = doc->nextdoc) {
 		unsigned char oldval;
 		unsigned char newval;
-		nand = mtd_to_nand(mtd);
+		nand = mtd_to_nandchip(mtd);
 		doc = nand_get_controller_data(nand);
 		/* Use the alias resolution register to determine if this is
 		   in fact the same DOC aliased to a new address.  If writes
@@ -1561,7 +1561,7 @@ static int __init doc_probe(unsigned long physadr)
 		goto fail;
 	}
 
-	mtd			= nand_to_mtd(nand);
+	mtd			= nandchip_to_mtd(nand);
 	doc			= (struct doc_priv *) (nand + 1);
 	nand->bbt_td		= (struct nand_bbt_descr *) (doc + 1);
 	nand->bbt_md		= nand->bbt_td + 1;
@@ -1640,7 +1640,7 @@ static void release_nanddoc(void)
 	struct doc_priv *doc;
 
 	for (mtd = doclist; mtd; mtd = nextmtd) {
-		nand = mtd_to_nand(mtd);
+		nand = mtd_to_nandchip(mtd);
 		doc = nand_get_controller_data(nand);
 
 		nextmtd = doc->nextdoc;
diff --git a/drivers/mtd/nand/raw/docg4.c b/drivers/mtd/nand/raw/docg4.c
index e038130..c4a4089 100644
--- a/drivers/mtd/nand/raw/docg4.c
+++ b/drivers/mtd/nand/raw/docg4.c
@@ -264,7 +264,7 @@ static inline void write_nop(void __iomem *docptr)
 static void docg4_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
 	int i;
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	uint16_t *p = (uint16_t *) buf;
 	len >>= 1;
 
@@ -275,7 +275,7 @@ static void docg4_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 static void docg4_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
 	int i;
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	uint16_t *p = (uint16_t *) buf;
 	len >>= 1;
 
@@ -340,7 +340,7 @@ static void docg4_select_chip(struct mtd_info *mtd, int chip)
 	 * Select among multiple cascaded chips ("floors").  Multiple floors are
 	 * not yet supported, so the only valid non-negative value is 0.
 	 */
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct docg4_priv *doc = nand_get_controller_data(nand);
 	void __iomem *docptr = doc->virtadr;
 
@@ -359,7 +359,7 @@ static void reset(struct mtd_info *mtd)
 {
 	/* full device reset */
 
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct docg4_priv *doc = nand_get_controller_data(nand);
 	void __iomem *docptr = doc->virtadr;
 
@@ -397,7 +397,7 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page)
 	 * Up to four bitflips can be corrected.
 	 */
 
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct docg4_priv *doc = nand_get_controller_data(nand);
 	void __iomem *docptr = doc->virtadr;
 	int i, numerrs, errpos[4];
@@ -486,7 +486,7 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page)
 
 static uint8_t docg4_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct docg4_priv *doc = nand_get_controller_data(nand);
 
 	dev_dbg(doc->dev, "%s\n", __func__);
@@ -567,7 +567,7 @@ static int pageprog(struct mtd_info *mtd)
 	 * internal buffer out to the flash array, or some such.
 	 */
 
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct docg4_priv *doc = nand_get_controller_data(nand);
 	void __iomem *docptr = doc->virtadr;
 	int retval = 0;
@@ -604,7 +604,7 @@ static void sequence_reset(struct mtd_info *mtd)
 {
 	/* common starting sequence for all operations */
 
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct docg4_priv *doc = nand_get_controller_data(nand);
 	void __iomem *docptr = doc->virtadr;
 
@@ -621,7 +621,7 @@ static void read_page_prologue(struct mtd_info *mtd, uint32_t docg4_addr)
 {
 	/* first step in reading a page */
 
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct docg4_priv *doc = nand_get_controller_data(nand);
 	void __iomem *docptr = doc->virtadr;
 
@@ -648,7 +648,7 @@ static void write_page_prologue(struct mtd_info *mtd, uint32_t docg4_addr)
 {
 	/* first step in writing a page */
 
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct docg4_priv *doc = nand_get_controller_data(nand);
 	void __iomem *docptr = doc->virtadr;
 
@@ -713,7 +713,7 @@ static void docg4_command(struct mtd_info *mtd, unsigned command, int column,
 {
 	/* handle standard nand commands */
 
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct docg4_priv *doc = nand_get_controller_data(nand);
 	uint32_t g4_addr = mtd_to_docg4_address(page_addr, column);
 
@@ -896,7 +896,7 @@ static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
 
 static int docg4_erase_block(struct mtd_info *mtd, int page)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct docg4_priv *doc = nand_get_controller_data(nand);
 	void __iomem *docptr = doc->virtadr;
 	uint16_t g4_page;
@@ -1038,7 +1038,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd)
 	 * update the memory-based bbt accordingly.
 	 */
 
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct docg4_priv *doc = nand_get_controller_data(nand);
 	uint32_t g4_addr = mtd_to_docg4_address(DOCG4_FACTORY_BBT_PAGE, 0);
 	uint8_t *buf;
@@ -1111,7 +1111,7 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs)
 
 	int ret, i;
 	uint8_t *buf;
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct docg4_priv *doc = nand_get_controller_data(nand);
 	struct nand_bbt_descr *bbtd = nand->badblock_pattern;
 	int page = (int)(ofs >> nand->page_shift);
@@ -1224,7 +1224,7 @@ static void __init init_mtd_structs(struct mtd_info *mtd)
 	 * things as well, such as call nand_set_defaults().
 	 */
 
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct docg4_priv *doc = nand_get_controller_data(nand);
 
 	mtd->size = DOCG4_CHIP_SIZE;
@@ -1282,7 +1282,7 @@ static void __init init_mtd_structs(struct mtd_info *mtd)
 
 static int __init read_id_reg(struct mtd_info *mtd)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct docg4_priv *doc = nand_get_controller_data(nand);
 	void __iomem *docptr = doc->virtadr;
 	uint16_t id1, id2;
@@ -1333,7 +1333,7 @@ static int __init probe_docg4(struct platform_device *pdev)
 		goto fail_unmap;
 	}
 
-	mtd = nand_to_mtd(nand);
+	mtd = nandchip_to_mtd(nand);
 	doc = (struct docg4_priv *) (nand + 1);
 	nand_set_controller_data(nand, doc);
 	mtd->dev.parent = &pdev->dev;
@@ -1389,7 +1389,7 @@ static int __exit cleanup_docg4(struct platform_device *pdev)
 	struct docg4_priv *doc = platform_get_drvdata(pdev);
 	nand_release(doc->mtd);
 	free_bch(doc->bch);
-	kfree(mtd_to_nand(doc->mtd));
+	kfree(mtd_to_nandchip(doc->mtd));
 	iounmap(doc->virtadr);
 	return 0;
 }
diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c
index 7d8453e..f0ea638 100644
--- a/drivers/mtd/nand/raw/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c
@@ -82,7 +82,7 @@ struct fsl_elbc_fcm_ctrl {
 static int fsl_elbc_ooblayout_ecc(struct mtd_info *mtd, int section,
 				  struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
 
 	if (section >= chip->ecc.steps)
@@ -100,7 +100,7 @@ static int fsl_elbc_ooblayout_ecc(struct mtd_info *mtd, int section,
 static int fsl_elbc_ooblayout_free(struct mtd_info *mtd, int section,
 				   struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
 
 	if (section > chip->ecc.steps)
@@ -164,7 +164,7 @@ static int fsl_elbc_ooblayout_free(struct mtd_info *mtd, int section,
  */
 static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
@@ -215,7 +215,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
  */
 static int fsl_elbc_run_command(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
@@ -320,7 +320,7 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
 static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
                              int column, int page_addr)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
@@ -545,7 +545,7 @@ static void fsl_elbc_select_chip(struct mtd_info *mtd, int chip)
  */
 static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 	unsigned int bufsize = mtd->writesize + mtd->oobsize;
@@ -583,7 +583,7 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
  */
 static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 
@@ -600,7 +600,7 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
  */
 static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 	int avail;
@@ -639,7 +639,7 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
 
 static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
@@ -754,7 +754,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
 	struct nand_chip *chip = &priv->chip;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 
 	dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
 
@@ -809,7 +809,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
 static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
 {
 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
-	struct mtd_info *mtd = nand_to_mtd(&priv->chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&priv->chip);
 
 	nand_release(mtd);
 
@@ -899,9 +899,9 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev)
 		goto err;
 	}
 
-	mtd = nand_to_mtd(&priv->chip);
+	mtd = nandchip_to_mtd(&priv->chip);
 	mtd->name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start);
-	if (!nand_to_mtd(&priv->chip)->name) {
+	if (!nandchip_to_mtd(&priv->chip)->name) {
 		ret = -ENOMEM;
 		goto err;
 	}
diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c
index b9b8534..09ae754 100644
--- a/drivers/mtd/nand/raw/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c
@@ -96,7 +96,7 @@ struct fsl_ifc_nand_ctrl {
 static int fsl_ifc_ooblayout_ecc(struct mtd_info *mtd, int section,
 				 struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (section)
 		return -ERANGE;
@@ -110,7 +110,7 @@ static int fsl_ifc_ooblayout_ecc(struct mtd_info *mtd, int section,
 static int fsl_ifc_ooblayout_free(struct mtd_info *mtd, int section,
 				  struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (section > 1)
 		return -ERANGE;
@@ -150,7 +150,7 @@ static int fsl_ifc_ooblayout_free(struct mtd_info *mtd, int section,
  */
 static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
 	struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs;
@@ -173,7 +173,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
 
 static int is_blank(struct mtd_info *mtd, unsigned int bufnum)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2);
 	u32 __iomem *mainarea = (u32 __iomem *)addr;
@@ -216,7 +216,7 @@ static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
  */
 static void fsl_ifc_run_command(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
 	struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl;
@@ -339,7 +339,7 @@ static void fsl_ifc_do_read(struct nand_chip *chip,
 /* cmdfunc send commands to the IFC NAND Machine */
 static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 			     int column, int page_addr) {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
 	struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs;
@@ -554,7 +554,7 @@ static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
  */
 static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	unsigned int bufsize = mtd->writesize + mtd->oobsize;
 
@@ -580,7 +580,7 @@ static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
  */
 static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	unsigned int offset;
 
@@ -603,7 +603,7 @@ static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd)
  */
 static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	uint16_t data;
 
@@ -626,7 +626,7 @@ static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
  */
 static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	int avail;
 
@@ -712,7 +712,7 @@ static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 
 static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 
 	dev_dbg(priv->dev, "%s: nand->numchips = %d\n", __func__,
@@ -811,7 +811,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
 	struct fsl_ifc_global __iomem *ifc_global = ctrl->gregs;
 	struct fsl_ifc_runtime __iomem *ifc_runtime = ctrl->rregs;
 	struct nand_chip *chip = &priv->chip;
-	struct mtd_info *mtd = nand_to_mtd(&priv->chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&priv->chip);
 	u32 csor;
 
 	/* Fill in fsl_ifc_mtd structure */
@@ -912,7 +912,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
 
 static int fsl_ifc_chip_remove(struct fsl_ifc_mtd *priv)
 {
-	struct mtd_info *mtd = nand_to_mtd(&priv->chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&priv->chip);
 
 	nand_release(mtd);
 
@@ -1024,7 +1024,7 @@ static int fsl_ifc_nand_probe(struct platform_device *dev)
 		  IFC_NAND_EVTER_INTR_WPERIR_EN,
 		  &ifc->ifc_nand.nand_evter_intr_en);
 
-	mtd = nand_to_mtd(&priv->chip);
+	mtd = nandchip_to_mtd(&priv->chip);
 	mtd->name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start);
 	if (!mtd->name) {
 		ret = -ENOMEM;
diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c
index a88e2cf..9715cdd 100644
--- a/drivers/mtd/nand/raw/fsl_upm.c
+++ b/drivers/mtd/nand/raw/fsl_upm.c
@@ -48,7 +48,7 @@ struct fsl_upm_nand {
 
 static inline struct fsl_upm_nand *to_fsl_upm_nand(struct mtd_info *mtdinfo)
 {
-	return container_of(mtd_to_nand(mtdinfo), struct fsl_upm_nand,
+	return container_of(mtd_to_nandchip(mtdinfo), struct fsl_upm_nand,
 			    chip);
 }
 
@@ -66,7 +66,7 @@ static int fun_chip_ready(struct mtd_info *mtd)
 static void fun_wait_rnb(struct fsl_upm_nand *fun)
 {
 	if (fun->rnb_gpio[fun->mchip_number] >= 0) {
-		struct mtd_info *mtd = nand_to_mtd(&fun->chip);
+		struct mtd_info *mtd = nandchip_to_mtd(&fun->chip);
 		int cnt = 1000000;
 
 		while (--cnt && !fun_chip_ready(mtd))
@@ -80,7 +80,7 @@ static void fun_wait_rnb(struct fsl_upm_nand *fun)
 
 static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
 	u32 mar;
 
@@ -110,7 +110,7 @@ static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 
 static void fun_select_chip(struct mtd_info *mtd, int mchip_nr)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
 
 	if (mchip_nr == -1) {
@@ -158,7 +158,7 @@ static int fun_chip_init(struct fsl_upm_nand *fun,
 			 const struct device_node *upm_np,
 			 const struct resource *io_res)
 {
-	struct mtd_info *mtd = nand_to_mtd(&fun->chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&fun->chip);
 	int ret;
 	struct device_node *flash_np;
 
@@ -323,7 +323,7 @@ static int fun_probe(struct platform_device *ofdev)
 static int fun_remove(struct platform_device *ofdev)
 {
 	struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev);
-	struct mtd_info *mtd = nand_to_mtd(&fun->chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&fun->chip);
 	int i;
 
 	nand_release(mtd);
diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c
index bab7064..3597b54 100644
--- a/drivers/mtd/nand/raw/fsmc_nand.c
+++ b/drivers/mtd/nand/raw/fsmc_nand.c
@@ -171,7 +171,7 @@ struct fsmc_nand_data {
 static int fsmc_ecc1_ooblayout_ecc(struct mtd_info *mtd, int section,
 				   struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (section >= chip->ecc.steps)
 		return -ERANGE;
@@ -185,7 +185,7 @@ static int fsmc_ecc1_ooblayout_ecc(struct mtd_info *mtd, int section,
 static int fsmc_ecc1_ooblayout_free(struct mtd_info *mtd, int section,
 				    struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (section >= chip->ecc.steps)
 		return -ERANGE;
@@ -214,7 +214,7 @@ static int fsmc_ecc1_ooblayout_free(struct mtd_info *mtd, int section,
 static int fsmc_ecc4_ooblayout_ecc(struct mtd_info *mtd, int section,
 				   struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (section >= chip->ecc.steps)
 		return -ERANGE;
@@ -232,7 +232,7 @@ static int fsmc_ecc4_ooblayout_ecc(struct mtd_info *mtd, int section,
 static int fsmc_ecc4_ooblayout_free(struct mtd_info *mtd, int section,
 				    struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (section >= chip->ecc.steps)
 		return -ERANGE;
@@ -254,7 +254,7 @@ static int fsmc_ecc4_ooblayout_free(struct mtd_info *mtd, int section,
 
 static inline struct fsmc_nand_data *mtd_to_fsmc(struct mtd_info *mtd)
 {
-	return container_of(mtd_to_nand(mtd), struct fsmc_nand_data, nand);
+	return container_of(mtd_to_nandchip(mtd), struct fsmc_nand_data, nand);
 }
 
 /*
@@ -263,7 +263,7 @@ static inline struct fsmc_nand_data *mtd_to_fsmc(struct mtd_info *mtd)
  */
 static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
 	void __iomem *regs = host->regs_va;
 	unsigned int bank = host->bank;
@@ -392,7 +392,7 @@ static int fsmc_setup_data_interface(struct mtd_info *mtd,
 				     const struct nand_data_interface *conf,
 				     bool check_only)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct fsmc_nand_data *host = nand_get_controller_data(nand);
 	struct fsmc_nand_timings tims;
 	const struct nand_sdr_timings *sdrt;
@@ -600,7 +600,7 @@ static int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len,
 static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
 	int i;
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) &&
 			IS_ALIGNED(len, sizeof(uint32_t))) {
@@ -623,7 +623,7 @@ static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 static void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
 	int i;
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) &&
 			IS_ALIGNED(len, sizeof(uint32_t))) {
@@ -754,7 +754,7 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
 static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
 			     uint8_t *read_ecc, uint8_t *calc_ecc)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
 	void __iomem *regs = host->regs_va;
 	unsigned int bank = host->bank;
@@ -957,7 +957,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 		init_completion(&host->dma_access_complete);
 
 	/* Link all private pointers */
-	mtd = nand_to_mtd(&host->nand);
+	mtd = nandchip_to_mtd(&host->nand);
 	nand_set_controller_data(nand, host);
 	nand_set_flash_node(nand, pdev->dev.of_node);
 
@@ -1119,7 +1119,7 @@ static int fsmc_nand_remove(struct platform_device *pdev)
 	struct fsmc_nand_data *host = platform_get_drvdata(pdev);
 
 	if (host) {
-		nand_release(nand_to_mtd(&host->nand));
+		nand_release(nandchip_to_mtd(&host->nand));
 
 		if (host->mode == USE_DMA_ACCESS) {
 			dma_release_channel(host->write_dma_chan);
diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c
index fd36489..8d5a9ca 100644
--- a/drivers/mtd/nand/raw/gpio.c
+++ b/drivers/mtd/nand/raw/gpio.c
@@ -41,7 +41,7 @@ struct gpiomtd {
 
 static inline struct gpiomtd *gpio_nand_getpriv(struct mtd_info *mtd)
 {
-	return container_of(mtd_to_nand(mtd), struct gpiomtd, nand_chip);
+	return container_of(mtd_to_nandchip(mtd), struct gpiomtd, nand_chip);
 }
 
 
@@ -199,7 +199,7 @@ static int gpio_nand_remove(struct platform_device *pdev)
 {
 	struct gpiomtd *gpiomtd = platform_get_drvdata(pdev);
 
-	nand_release(nand_to_mtd(&gpiomtd->nand_chip));
+	nand_release(nandchip_to_mtd(&gpiomtd->nand_chip));
 
 	if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
 		gpio_set_value(gpiomtd->plat.gpio_nwp, 0);
@@ -284,7 +284,7 @@ static int gpio_nand_probe(struct platform_device *pdev)
 	chip->chip_delay	= gpiomtd->plat.chip_delay;
 	chip->cmd_ctrl		= gpio_nand_cmd_ctrl;
 
-	mtd			= nand_to_mtd(chip);
+	mtd			= nandchip_to_mtd(chip);
 	mtd->dev.parent		= &pdev->dev;
 
 	platform_set_drvdata(pdev, gpiomtd);
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
index 141bd70..7217912 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
@@ -921,7 +921,7 @@ static int enable_edo_mode(struct gpmi_nand_data *this, int mode)
 {
 	struct resources  *r = &this->resources;
 	struct nand_chip *nand = &this->nand;
-	struct mtd_info	 *mtd = nand_to_mtd(nand);
+	struct mtd_info	 *mtd = nandchip_to_mtd(nand);
 	uint8_t *feature;
 	unsigned long rate;
 	int ret;
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index 50f8d4a..b736ea2 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -50,7 +50,7 @@
 static int gpmi_ooblayout_ecc(struct mtd_info *mtd, int section,
 			      struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct gpmi_nand_data *this = nand_get_controller_data(chip);
 	struct bch_geometry *geo = &this->bch_geometry;
 
@@ -66,7 +66,7 @@ static int gpmi_ooblayout_ecc(struct mtd_info *mtd, int section,
 static int gpmi_ooblayout_free(struct mtd_info *mtd, int section,
 			       struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct gpmi_nand_data *this = nand_get_controller_data(chip);
 	struct bch_geometry *geo = &this->bch_geometry;
 
@@ -169,7 +169,7 @@ static irqreturn_t bch_irq(int irq, void *cookie)
 static inline int get_ecc_strength(struct gpmi_nand_data *this)
 {
 	struct bch_geometry *geo = &this->bch_geometry;
-	struct mtd_info	*mtd = nand_to_mtd(&this->nand);
+	struct mtd_info	*mtd = nandchip_to_mtd(&this->nand);
 	int ecc_strength;
 
 	ecc_strength = ((mtd->oobsize - geo->metadata_size) * 8)
@@ -202,7 +202,7 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this)
 {
 	struct bch_geometry *geo = &this->bch_geometry;
 	struct nand_chip *chip = &this->nand;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	unsigned int block_mark_bit_offset;
 
 	if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
@@ -312,7 +312,7 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this)
 static int legacy_set_geometry(struct gpmi_nand_data *this)
 {
 	struct bch_geometry *geo = &this->bch_geometry;
-	struct mtd_info *mtd = nand_to_mtd(&this->nand);
+	struct mtd_info *mtd = nandchip_to_mtd(&this->nand);
 	unsigned int metadata_size;
 	unsigned int status_size;
 	unsigned int block_mark_bit_offset;
@@ -842,7 +842,7 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
 {
 	struct bch_geometry *geo = &this->bch_geometry;
 	struct device *dev = this->dev;
-	struct mtd_info *mtd = nand_to_mtd(&this->nand);
+	struct mtd_info *mtd = nandchip_to_mtd(&this->nand);
 
 	/* [1] Allocate a command buffer. PAGE_SIZE is enough. */
 	this->cmd_buffer = kzalloc(PAGE_SIZE, GFP_DMA | GFP_KERNEL);
@@ -894,7 +894,7 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
 
 static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct gpmi_nand_data *this = nand_get_controller_data(chip);
 	int ret;
 
@@ -928,7 +928,7 @@ static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
 
 static int gpmi_dev_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct gpmi_nand_data *this = nand_get_controller_data(chip);
 
 	return gpmi_is_ready(this, this->current_chip);
@@ -936,7 +936,7 @@ static int gpmi_dev_ready(struct mtd_info *mtd)
 
 static void gpmi_select_chip(struct mtd_info *mtd, int chipnr)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct gpmi_nand_data *this = nand_get_controller_data(chip);
 
 	if ((this->current_chip < 0) && (chipnr >= 0))
@@ -949,7 +949,7 @@ static void gpmi_select_chip(struct mtd_info *mtd, int chipnr)
 
 static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct gpmi_nand_data *this = nand_get_controller_data(chip);
 
 	dev_dbg(this->dev, "len is %d\n", len);
@@ -961,7 +961,7 @@ static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 
 static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct gpmi_nand_data *this = nand_get_controller_data(chip);
 
 	dev_dbg(this->dev, "len is %d\n", len);
@@ -973,7 +973,7 @@ static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 
 static uint8_t gpmi_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct gpmi_nand_data *this = nand_get_controller_data(chip);
 	uint8_t *buf = this->data_buffer_dma;
 
@@ -1645,7 +1645,7 @@ static int gpmi_ecc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
 
 static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct gpmi_nand_data *this = nand_get_controller_data(chip);
 	int ret = 0;
 	uint8_t *block_mark;
@@ -1708,7 +1708,7 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this)
 	struct boot_rom_geometry *rom_geo = &this->rom_geometry;
 	struct device *dev = this->dev;
 	struct nand_chip *chip = &this->nand;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	unsigned int search_area_size_in_strides;
 	unsigned int stride;
 	unsigned int page;
@@ -1763,7 +1763,7 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
 	struct device *dev = this->dev;
 	struct boot_rom_geometry *rom_geo = &this->rom_geometry;
 	struct nand_chip *chip = &this->nand;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	unsigned int block_size_in_pages;
 	unsigned int search_area_size_in_strides;
 	unsigned int search_area_size_in_pages;
@@ -1842,7 +1842,7 @@ static int mx23_boot_init(struct gpmi_nand_data  *this)
 {
 	struct device *dev = this->dev;
 	struct nand_chip *chip = &this->nand;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	unsigned int block_count;
 	unsigned int block;
 	int     chipnr;
@@ -1939,7 +1939,7 @@ static int gpmi_set_geometry(struct gpmi_nand_data *this)
 static int gpmi_init_last(struct gpmi_nand_data *this)
 {
 	struct nand_chip *chip = &this->nand;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 	struct bch_geometry *bch_geo = &this->bch_geometry;
 	int ret;
@@ -1988,7 +1988,7 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
 static int gpmi_nand_init(struct gpmi_nand_data *this)
 {
 	struct nand_chip *chip = &this->nand;
-	struct mtd_info  *mtd = nand_to_mtd(chip);
+	struct mtd_info  *mtd = nandchip_to_mtd(chip);
 	int ret;
 
 	/* init current chip */
@@ -2135,7 +2135,7 @@ static int gpmi_nand_remove(struct platform_device *pdev)
 {
 	struct gpmi_nand_data *this = platform_get_drvdata(pdev);
 
-	nand_release(nand_to_mtd(&this->nand));
+	nand_release(nandchip_to_mtd(&this->nand));
 	gpmi_free_dma_buffer(this);
 	release_resources(this);
 	return 0;
diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c
index d09df18..86dd423 100644
--- a/drivers/mtd/nand/raw/hisi504_nand.c
+++ b/drivers/mtd/nand/raw/hisi504_nand.c
@@ -188,7 +188,7 @@ static void wait_controller_finished(struct hinfc_host *host)
 static void hisi_nfc_dma_transfer(struct hinfc_host *host, int todev)
 {
 	struct nand_chip *chip = &host->chip;
-	struct mtd_info	*mtd = nand_to_mtd(chip);
+	struct mtd_info	*mtd = nandchip_to_mtd(chip);
 	unsigned long val;
 	int ret;
 
@@ -260,7 +260,7 @@ static int hisi_nfc_send_cmd_pageprog(struct hinfc_host *host)
 
 static int hisi_nfc_send_cmd_readstart(struct hinfc_host *host)
 {
-	struct mtd_info	*mtd = nand_to_mtd(&host->chip);
+	struct mtd_info	*mtd = nandchip_to_mtd(&host->chip);
 
 	if ((host->addr_value[0] == host->cache_addr_value[0]) &&
 	    (host->addr_value[1] == host->cache_addr_value[1]))
@@ -355,7 +355,7 @@ static int hisi_nfc_send_cmd_reset(struct hinfc_host *host, int chipselect)
 
 static void hisi_nfc_select_chip(struct mtd_info *mtd, int chipselect)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct hinfc_host *host = nand_get_controller_data(chip);
 
 	if (chipselect < 0)
@@ -366,7 +366,7 @@ static void hisi_nfc_select_chip(struct mtd_info *mtd, int chipselect)
 
 static uint8_t hisi_nfc_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct hinfc_host *host = nand_get_controller_data(chip);
 
 	if (host->command == NAND_CMD_STATUS)
@@ -382,7 +382,7 @@ static uint8_t hisi_nfc_read_byte(struct mtd_info *mtd)
 
 static u16 hisi_nfc_read_word(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct hinfc_host *host = nand_get_controller_data(chip);
 
 	host->offset += 2;
@@ -392,7 +392,7 @@ static u16 hisi_nfc_read_word(struct mtd_info *mtd)
 static void
 hisi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct hinfc_host *host = nand_get_controller_data(chip);
 
 	memcpy(host->buffer + host->offset, buf, len);
@@ -401,7 +401,7 @@ static u16 hisi_nfc_read_word(struct mtd_info *mtd)
 
 static void hisi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct hinfc_host *host = nand_get_controller_data(chip);
 
 	memcpy(buf, host->buffer + host->offset, len);
@@ -410,7 +410,7 @@ static void hisi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 
 static void set_addr(struct mtd_info *mtd, int column, int page_addr)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct hinfc_host *host = nand_get_controller_data(chip);
 	unsigned int command = host->command;
 
@@ -446,7 +446,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr)
 static void hisi_nfc_cmdfunc(struct mtd_info *mtd, unsigned command, int column,
 		int page_addr)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct hinfc_host *host = nand_get_controller_data(chip);
 	int is_cache_invalid = 1;
 	unsigned int flag = 0;
@@ -660,7 +660,7 @@ static int hisi_nfc_ecc_probe(struct hinfc_host *host)
 	int size, strength, ecc_bits;
 	struct device *dev = host->dev;
 	struct nand_chip *chip = &host->chip;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 
 	size = chip->ecc.size;
 	strength = chip->ecc.strength;
@@ -728,7 +728,7 @@ static int hisi_nfc_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, host);
 	chip = &host->chip;
-	mtd  = nand_to_mtd(chip);
+	mtd  = nandchip_to_mtd(chip);
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
@@ -829,7 +829,7 @@ static int hisi_nfc_probe(struct platform_device *pdev)
 static int hisi_nfc_remove(struct platform_device *pdev)
 {
 	struct hinfc_host *host = platform_get_drvdata(pdev);
-	struct mtd_info *mtd = nand_to_mtd(&host->chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&host->chip);
 
 	nand_release(mtd);
 
diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c
index e813ec1..c2d514e 100644
--- a/drivers/mtd/nand/raw/jz4740_nand.c
+++ b/drivers/mtd/nand/raw/jz4740_nand.c
@@ -75,13 +75,13 @@ struct jz_nand {
 
 static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd)
 {
-	return container_of(mtd_to_nand(mtd), struct jz_nand, chip);
+	return container_of(mtd_to_nandchip(mtd), struct jz_nand, chip);
 }
 
 static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr)
 {
 	struct jz_nand *nand = mtd_to_jz_nand(mtd);
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	uint32_t ctrl;
 	int banknr;
 
@@ -103,7 +103,7 @@ static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr)
 static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
 {
 	struct jz_nand *nand = mtd_to_jz_nand(mtd);
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	uint32_t reg;
 	void __iomem *bank_base = nand->bank_base[nand->selected_bank];
 
@@ -315,7 +315,7 @@ static int jz_nand_detect_bank(struct platform_device *pdev,
 	char res_name[6];
 	uint32_t ctrl;
 	struct nand_chip *chip = &nand->chip;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 
 	/* Request GPIO port. */
 	gpio = JZ_GPIO_MEM_CS0 + bank - 1;
@@ -413,7 +413,7 @@ static int jz_nand_probe(struct platform_device *pdev)
 	}
 
 	chip		= &nand->chip;
-	mtd		= nand_to_mtd(chip);
+	mtd		= nandchip_to_mtd(chip);
 	mtd->dev.parent = &pdev->dev;
 	mtd->name	= "jz4740-nand";
 
@@ -520,7 +520,7 @@ static int jz_nand_remove(struct platform_device *pdev)
 	struct jz_nand *nand = platform_get_drvdata(pdev);
 	size_t i;
 
-	nand_release(nand_to_mtd(&nand->chip));
+	nand_release(nandchip_to_mtd(&nand->chip));
 
 	/* Deassert and disable all chips */
 	writel(0, nand->base + JZ_REG_NAND_CTRL);
diff --git a/drivers/mtd/nand/raw/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c
index e69f6ae..2b3096d 100644
--- a/drivers/mtd/nand/raw/jz4780_nand.c
+++ b/drivers/mtd/nand/raw/jz4780_nand.c
@@ -62,7 +62,7 @@ struct jz4780_nand_chip {
 
 static inline struct jz4780_nand_chip *to_jz4780_nand_chip(struct mtd_info *mtd)
 {
-	return container_of(mtd_to_nand(mtd), struct jz4780_nand_chip, chip);
+	return container_of(mtd_to_nandchip(mtd), struct jz4780_nand_chip, chip);
 }
 
 static inline struct jz4780_nand_controller *to_jz4780_nand_controller(struct nand_hw_control *ctrl)
@@ -160,7 +160,7 @@ static int jz4780_nand_ecc_correct(struct mtd_info *mtd, u8 *dat,
 static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *dev)
 {
 	struct nand_chip *chip = &nand->chip;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(chip->controller);
 	int eccbytes;
 
@@ -262,7 +262,7 @@ static int jz4780_nand_init_chip(struct platform_device *pdev,
 	}
 
 	chip = &nand->chip;
-	mtd = nand_to_mtd(chip);
+	mtd = nandchip_to_mtd(chip);
 	mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%s.%d", dev_name(dev),
 				   cs->bank);
 	if (!mtd->name)
@@ -308,7 +308,7 @@ static void jz4780_nand_cleanup_chips(struct jz4780_nand_controller *nfc)
 
 	while (!list_empty(&nfc->chips)) {
 		chip = list_first_entry(&nfc->chips, struct jz4780_nand_chip, chip_list);
-		nand_release(nand_to_mtd(&chip->chip));
+		nand_release(nandchip_to_mtd(&chip->chip));
 		list_del(&chip->chip_list);
 	}
 }
diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c
index bffa01c..b5e3787 100644
--- a/drivers/mtd/nand/raw/lpc32xx_mlc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c
@@ -141,7 +141,7 @@ struct lpc32xx_nand_cfg_mlc {
 static int lpc32xx_ooblayout_ecc(struct mtd_info *mtd, int section,
 				 struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 
 	if (section >= nand_chip->ecc.steps)
 		return -ERANGE;
@@ -155,7 +155,7 @@ static int lpc32xx_ooblayout_ecc(struct mtd_info *mtd, int section,
 static int lpc32xx_ooblayout_free(struct mtd_info *mtd, int section,
 				  struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 
 	if (section >= nand_chip->ecc.steps)
 		return -ERANGE;
@@ -288,7 +288,7 @@ static void lpc32xx_nand_setup(struct lpc32xx_nand_host *host)
 static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
 				  unsigned int ctrl)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct lpc32xx_nand_host *host = nand_get_controller_data(nand_chip);
 
 	if (cmd != NAND_CMD_NONE) {
@@ -304,7 +304,7 @@ static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
  */
 static int lpc32xx_nand_device_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct lpc32xx_nand_host *host = nand_get_controller_data(nand_chip);
 
 	if ((readb(MLC_ISR(host->io_base)) &
@@ -402,7 +402,7 @@ static void lpc32xx_dma_complete_func(void *completion)
 static int lpc32xx_xmit_dma(struct mtd_info *mtd, void *mem, int len,
 			    enum dma_transfer_direction dir)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
 	struct dma_async_tx_descriptor *desc;
 	int flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
@@ -579,7 +579,7 @@ static void lpc32xx_ecc_enable(struct mtd_info *mtd, int mode)
 
 static int lpc32xx_dma_setup(struct lpc32xx_nand_host *host)
 {
-	struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&host->nand_chip);
 	dma_cap_mask_t mask;
 
 	if (!host->pdata || !host->pdata->dma_filter) {
@@ -674,7 +674,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
 	host->io_base_phy = rc->start;
 
 	nand_chip = &host->nand_chip;
-	mtd = nand_to_mtd(nand_chip);
+	mtd = nandchip_to_mtd(nand_chip);
 	if (pdev->dev.of_node)
 		host->ncfg = lpc32xx_parse_dt(&pdev->dev);
 	if (!host->ncfg) {
@@ -826,7 +826,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
 static int lpc32xx_nand_remove(struct platform_device *pdev)
 {
 	struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
-	struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&host->nand_chip);
 
 	nand_release(mtd);
 	free_irq(host->irq, host);
diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c
index 7c8402f..b47e3c0 100644
--- a/drivers/mtd/nand/raw/lpc32xx_slc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_slc.c
@@ -282,7 +282,7 @@ static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
 	unsigned int ctrl)
 {
 	uint32_t tmp;
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
 
 	/* Does CE state need to be changed? */
@@ -306,7 +306,7 @@ static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
  */
 static int lpc32xx_nand_device_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
 	int rdy = 0;
 
@@ -361,7 +361,7 @@ static int lpc32xx_nand_ecc_calculate(struct mtd_info *mtd,
  */
 static uint8_t lpc32xx_nand_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
 
 	return (uint8_t)readl(SLC_DATA(host->io_base));
@@ -372,7 +372,7 @@ static uint8_t lpc32xx_nand_read_byte(struct mtd_info *mtd)
  */
 static void lpc32xx_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
 
 	/* Direct device read with no ECC */
@@ -385,7 +385,7 @@ static void lpc32xx_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
  */
 static void lpc32xx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
 
 	/* Direct device write with no ECC */
@@ -450,7 +450,7 @@ static void lpc32xx_dma_complete_func(void *completion)
 static int lpc32xx_xmit_dma(struct mtd_info *mtd, dma_addr_t dma,
 			    void *mem, int len, enum dma_transfer_direction dir)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
 	struct dma_async_tx_descriptor *desc;
 	int flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
@@ -510,7 +510,7 @@ static int lpc32xx_xmit_dma(struct mtd_info *mtd, dma_addr_t dma,
 static int lpc32xx_xfer(struct mtd_info *mtd, uint8_t *buf, int eccsubpages,
 			int read)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
 	int i, status = 0;
 	unsigned long timeout;
@@ -736,7 +736,7 @@ static int lpc32xx_nand_write_page_raw_syndrome(struct mtd_info *mtd,
 
 static int lpc32xx_nand_dma_setup(struct lpc32xx_nand_host *host)
 {
-	struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&host->nand_chip);
 	dma_cap_mask_t mask;
 
 	if (!host->pdata || !host->pdata->dma_filter) {
@@ -827,7 +827,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
 	host->pdata = dev_get_platdata(&pdev->dev);
 
 	chip = &host->nand_chip;
-	mtd = nand_to_mtd(chip);
+	mtd = nandchip_to_mtd(chip);
 	nand_set_controller_data(chip, host);
 	nand_set_flash_node(chip, pdev->dev.of_node);
 	mtd->owner = THIS_MODULE;
@@ -952,7 +952,7 @@ static int lpc32xx_nand_remove(struct platform_device *pdev)
 {
 	uint32_t tmp;
 	struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
-	struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&host->nand_chip);
 
 	nand_release(mtd);
 	dma_release_channel(host->dma_chan);
diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c
index 55f1d4a..e6c510f 100644
--- a/drivers/mtd/nand/raw/mpc5121_nfc.c
+++ b/drivers/mtd/nand/raw/mpc5121_nfc.c
@@ -134,7 +134,7 @@ struct mpc5121_nfc_prv {
 /* Read NFC register */
 static inline u16 nfc_read(struct mtd_info *mtd, uint reg)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
 
 	return in_be16(prv->regs + reg);
@@ -143,7 +143,7 @@ static inline u16 nfc_read(struct mtd_info *mtd, uint reg)
 /* Write NFC register */
 static inline void nfc_write(struct mtd_info *mtd, uint reg, u16 val)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
 
 	out_be16(prv->regs + reg, val);
@@ -213,7 +213,7 @@ static inline void mpc5121_nfc_send_read_status(struct mtd_info *mtd)
 static irqreturn_t mpc5121_nfc_irq(int irq, void *data)
 {
 	struct mtd_info *mtd = data;
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
 
 	nfc_set(mtd, NFC_CONFIG1, NFC_INT_MASK);
@@ -225,7 +225,7 @@ static irqreturn_t mpc5121_nfc_irq(int irq, void *data)
 /* Wait for operation complete */
 static void mpc5121_nfc_done(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
 	int rv;
 
@@ -245,7 +245,7 @@ static void mpc5121_nfc_done(struct mtd_info *mtd)
 /* Do address cycle(s) */
 static void mpc5121_nfc_addr_cycle(struct mtd_info *mtd, int column, int page)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	u32 pagemask = chip->pagemask;
 
 	if (column != -1) {
@@ -280,7 +280,7 @@ static void mpc5121_nfc_select_chip(struct mtd_info *mtd, int chip)
 /* Init external chip select logic on ADS5121 board */
 static int ads5121_chipselect_init(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
 	struct device_node *dn;
 
@@ -302,7 +302,7 @@ static int ads5121_chipselect_init(struct mtd_info *mtd)
 /* Control chips select signal on ADS5121 board */
 static void ads5121_select_chip(struct mtd_info *mtd, int chip)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct mpc5121_nfc_prv *prv = nand_get_controller_data(nand);
 	u8 v;
 
@@ -332,7 +332,7 @@ static int mpc5121_nfc_dev_ready(struct mtd_info *mtd)
 static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command,
 							int column, int page)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
 
 	prv->column = (column >= 0) ? column : 0;
@@ -405,7 +405,7 @@ static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command,
 static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset,
 						u8 *buffer, uint size, int wr)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct mpc5121_nfc_prv *prv = nand_get_controller_data(nand);
 	uint o, s, sbsize, blksize;
 
@@ -457,7 +457,7 @@ static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset,
 static void mpc5121_nfc_buf_copy(struct mtd_info *mtd, u_char *buf, int len,
 									int wr)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
 	uint c = prv->column;
 	uint l;
@@ -535,7 +535,7 @@ static u16 mpc5121_nfc_read_word(struct mtd_info *mtd)
  */
 static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
 	struct mpc512x_reset_module *rm;
 	struct device_node *rmnode;
@@ -614,7 +614,7 @@ static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd)
 /* Free driver resources */
 static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
 
 	if (prv->clk)
@@ -654,7 +654,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
 		return -ENOMEM;
 
 	chip = &prv->chip;
-	mtd = nand_to_mtd(chip);
+	mtd = nandchip_to_mtd(chip);
 
 	mtd->dev.parent = dev;
 	nand_set_controller_data(chip, prv);
diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
index 3f4a98b..a0a7f6c 100644
--- a/drivers/mtd/nand/raw/mtk_nand.c
+++ b/drivers/mtd/nand/raw/mtk_nand.c
@@ -305,7 +305,7 @@ static int mtk_nfc_send_address(struct mtk_nfc *nfc, int addr)
 
 static int mtk_nfc_hw_runtime_config(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
 	struct mtk_nfc *nfc = nand_get_controller_data(chip);
 	u32 fmt, spare;
@@ -418,7 +418,7 @@ static int mtk_nfc_hw_runtime_config(struct mtd_info *mtd)
 
 static void mtk_nfc_select_chip(struct mtd_info *mtd, int chip)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct mtk_nfc *nfc = nand_get_controller_data(nand);
 	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(nand);
 
@@ -432,7 +432,7 @@ static void mtk_nfc_select_chip(struct mtd_info *mtd, int chip)
 
 static int mtk_nfc_dev_ready(struct mtd_info *mtd)
 {
-	struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd));
+	struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nandchip(mtd));
 
 	if (nfi_readl(nfc, NFI_STA) & STA_BUSY)
 		return 0;
@@ -442,7 +442,7 @@ static int mtk_nfc_dev_ready(struct mtd_info *mtd)
 
 static void mtk_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
 {
-	struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd));
+	struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nandchip(mtd));
 
 	if (ctrl & NAND_ALE) {
 		mtk_nfc_send_address(nfc, dat);
@@ -467,7 +467,7 @@ static inline void mtk_nfc_wait_ioready(struct mtk_nfc *nfc)
 
 static inline u8 mtk_nfc_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mtk_nfc *nfc = nand_get_controller_data(chip);
 	u32 reg;
 
@@ -504,7 +504,7 @@ static void mtk_nfc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
 
 static void mtk_nfc_write_byte(struct mtd_info *mtd, u8 byte)
 {
-	struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd));
+	struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nandchip(mtd));
 	u32 reg;
 
 	reg = nfi_readl(nfc, NFI_STA) & NFI_FSM_MASK;
@@ -550,7 +550,7 @@ static void mtk_nfc_no_bad_mark_swap(struct mtd_info *a, u8 *b, int c)
 
 static void mtk_nfc_bad_mark_swap(struct mtd_info *mtd, u8 *buf, int raw)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mtk_nfc_nand_chip *nand = to_mtk_nand(chip);
 	u32 bad_pos = nand->bad_mark.pos;
 
@@ -565,7 +565,7 @@ static void mtk_nfc_bad_mark_swap(struct mtd_info *mtd, u8 *buf, int raw)
 static int mtk_nfc_format_subpage(struct mtd_info *mtd, u32 offset,
 				  u32 len, const u8 *buf)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
 	struct mtk_nfc *nfc = nand_get_controller_data(chip);
 	struct mtk_nfc_fdm *fdm = &mtk_nand->fdm;
@@ -599,7 +599,7 @@ static int mtk_nfc_format_subpage(struct mtd_info *mtd, u32 offset,
 
 static void mtk_nfc_format_page(struct mtd_info *mtd, const u8 *buf)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
 	struct mtk_nfc *nfc = nand_get_controller_data(chip);
 	struct mtk_nfc_fdm *fdm = &mtk_nand->fdm;
@@ -812,7 +812,7 @@ static int mtk_nfc_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
 
 static int mtk_nfc_update_ecc_stats(struct mtd_info *mtd, u8 *buf, u32 sectors)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mtk_nfc *nfc = nand_get_controller_data(chip);
 	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
 	struct mtk_ecc_stats stats;
@@ -1063,7 +1063,7 @@ static void mtk_nfc_disable_clk(struct mtk_nfc_clk *clk)
 static int mtk_nfc_ooblayout_free(struct mtd_info *mtd, int section,
 				  struct mtd_oob_region *oob_region)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
 	struct mtk_nfc_fdm *fdm = &mtk_nand->fdm;
 	u32 eccsteps;
@@ -1082,7 +1082,7 @@ static int mtk_nfc_ooblayout_free(struct mtd_info *mtd, int section,
 static int mtk_nfc_ooblayout_ecc(struct mtd_info *mtd, int section,
 				 struct mtd_oob_region *oob_region)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
 	u32 eccsteps;
 
@@ -1103,7 +1103,7 @@ static int mtk_nfc_ooblayout_ecc(struct mtd_info *mtd, int section,
 
 static void mtk_nfc_set_fdm(struct mtk_nfc_fdm *fdm, struct mtd_info *mtd)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct mtk_nfc_nand_chip *chip = to_mtk_nand(nand);
 	u32 ecc_bytes;
 
@@ -1120,7 +1120,7 @@ static void mtk_nfc_set_fdm(struct mtk_nfc_fdm *fdm, struct mtd_info *mtd)
 static void mtk_nfc_set_bad_mark_ctl(struct mtk_nfc_bad_mark_ctl *bm_ctl,
 				     struct mtd_info *mtd)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 
 	if (mtd->writesize == 512) {
 		bm_ctl->bm_swap = mtk_nfc_no_bad_mark_swap;
@@ -1133,7 +1133,7 @@ static void mtk_nfc_set_bad_mark_ctl(struct mtk_nfc_bad_mark_ctl *bm_ctl,
 
 static void mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	u32 spare[] = {16, 26, 27, 28, 32, 36, 40, 44,
 			48, 49, 50, 51, 52, 62, 63, 64};
 	u32 eccsteps, i;
@@ -1163,7 +1163,7 @@ static void mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
 
 static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	u32 spare;
 	int free;
 
@@ -1287,7 +1287,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
 	nand->ecc.read_oob_raw = mtk_nfc_read_oob_std;
 	nand->ecc.read_oob = mtk_nfc_read_oob_std;
 
-	mtd = nand_to_mtd(nand);
+	mtd = nandchip_to_mtd(nand);
 	mtd->owner = THIS_MODULE;
 	mtd->dev.parent = dev;
 	mtd->name = MTK_NAME;
@@ -1450,7 +1450,7 @@ static int mtk_nfc_remove(struct platform_device *pdev)
 	while (!list_empty(&nfc->chips)) {
 		chip = list_first_entry(&nfc->chips, struct mtk_nfc_nand_chip,
 					node);
-		nand_release(nand_to_mtd(&chip->nand));
+		nand_release(nandchip_to_mtd(&chip->nand));
 		list_del(&chip->node);
 	}
 
@@ -1490,7 +1490,7 @@ static int mtk_nfc_resume(struct device *dev)
 	/* reset NAND chip if VCC was powered off */
 	list_for_each_entry(chip, &nfc->chips, node) {
 		nand = &chip->nand;
-		mtd = nand_to_mtd(nand);
+		mtd = nandchip_to_mtd(nand);
 		for (i = 0; i < chip->nsels; i++) {
 			nand->select_chip(mtd, i);
 			nand->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c
index 42bff4a..c50a850 100644
--- a/drivers/mtd/nand/raw/mxc_nand.c
+++ b/drivers/mtd/nand/raw/mxc_nand.c
@@ -466,7 +466,7 @@ static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islas
 
 static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 	uint32_t tmp;
 
@@ -482,7 +482,7 @@ static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
 
 static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 
 	/* NANDFC buffer 0 is used for page read/write */
@@ -496,7 +496,7 @@ static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
 
 static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 	int bufs, i;
 
@@ -597,7 +597,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
 				 u_char *read_ecc, u_char *calc_ecc)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 
 	/*
@@ -618,7 +618,7 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
 static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
 				 u_char *read_ecc, u_char *calc_ecc)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 	u32 ecc_stat, err;
 	int no_subpages = 1;
@@ -656,7 +656,7 @@ static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 
 static u_char mxc_nand_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 	uint8_t ret;
 
@@ -680,7 +680,7 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd)
 
 static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 	uint16_t ret;
 
@@ -696,7 +696,7 @@ static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
 static void mxc_nand_write_buf(struct mtd_info *mtd,
 				const u_char *buf, int len)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 	u16 col = host->buf_start;
 	int n = mtd->oobsize + mtd->writesize - col;
@@ -714,7 +714,7 @@ static void mxc_nand_write_buf(struct mtd_info *mtd,
  */
 static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 	u16 col = host->buf_start;
 	int n = mtd->oobsize + mtd->writesize - col;
@@ -730,7 +730,7 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
  * deselect of the NAND chip */
 static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 
 	if (chip == -1) {
@@ -751,7 +751,7 @@ static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
 
 static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 
 	if (chip == -1) {
@@ -784,7 +784,7 @@ static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
  */
 static void copy_spare(struct mtd_info *mtd, bool bfrom)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(this);
 	u16 i, oob_chunk_size;
 	u16 num_chunks = mtd->writesize / 512;
@@ -827,7 +827,7 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom)
  */
 static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 
 	/* Write out column address, if necessary */
@@ -880,7 +880,7 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
 static int mxc_v1_ooblayout_ecc(struct mtd_info *mtd, int section,
 				struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 
 	if (section >= nand_chip->ecc.steps)
 		return -ERANGE;
@@ -894,7 +894,7 @@ static int mxc_v1_ooblayout_ecc(struct mtd_info *mtd, int section,
 static int mxc_v1_ooblayout_free(struct mtd_info *mtd, int section,
 				 struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 
 	if (section > nand_chip->ecc.steps)
 		return -ERANGE;
@@ -928,7 +928,7 @@ static int mxc_v1_ooblayout_free(struct mtd_info *mtd, int section,
 static int mxc_v2_ooblayout_ecc(struct mtd_info *mtd, int section,
 				struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	int stepsize = nand_chip->ecc.bytes == 9 ? 16 : 26;
 
 	if (section >= nand_chip->ecc.steps)
@@ -943,7 +943,7 @@ static int mxc_v2_ooblayout_ecc(struct mtd_info *mtd, int section,
 static int mxc_v2_ooblayout_free(struct mtd_info *mtd, int section,
 				 struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	int stepsize = nand_chip->ecc.bytes == 9 ? 16 : 26;
 
 	if (section >= nand_chip->ecc.steps)
@@ -989,7 +989,7 @@ static int get_eccsize(struct mtd_info *mtd)
 
 static void preset_v1(struct mtd_info *mtd)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 	uint16_t config1 = 0;
 
@@ -1019,7 +1019,7 @@ static int mxc_nand_v2_setup_data_interface(struct mtd_info *mtd,
 					const struct nand_data_interface *conf,
 					bool check_only)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 	int tRC_min_ns, tRC_ps, ret;
 	unsigned long rate, rate_round;
@@ -1093,7 +1093,7 @@ static int mxc_nand_v2_setup_data_interface(struct mtd_info *mtd,
 
 static void preset_v2(struct mtd_info *mtd)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 	uint16_t config1 = 0;
 
@@ -1139,7 +1139,7 @@ static void preset_v2(struct mtd_info *mtd)
 
 static void preset_v3(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(chip);
 	uint32_t config2, config3;
 	int i, addr_phases;
@@ -1210,7 +1210,7 @@ static void preset_v3(struct mtd_info *mtd)
 static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
 				int column, int page_addr)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 
 	pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
@@ -1322,7 +1322,7 @@ static int mxc_nand_onfi_set_features(struct mtd_info *mtd,
 				      struct nand_chip *chip, int addr,
 				      u8 *subfeature_param)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 	int i;
 
@@ -1348,7 +1348,7 @@ static int mxc_nand_onfi_get_features(struct mtd_info *mtd,
 				      struct nand_chip *chip, int addr,
 				      u8 *subfeature_param)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 	int i;
 
@@ -1629,7 +1629,7 @@ static int mxcnd_probe(struct platform_device *pdev)
 	host->dev = &pdev->dev;
 	/* structures must be linked */
 	this = &host->nand;
-	mtd = nand_to_mtd(this);
+	mtd = nandchip_to_mtd(this);
 	mtd->dev.parent = &pdev->dev;
 	mtd->name = DRIVER_NAME;
 
@@ -1832,7 +1832,7 @@ static int mxcnd_remove(struct platform_device *pdev)
 {
 	struct mxc_nand_host *host = platform_get_drvdata(pdev);
 
-	nand_release(nand_to_mtd(&host->nand));
+	nand_release(nandchip_to_mtd(&host->nand));
 	if (host->clk_act)
 		clk_disable_unprepare(host->clk);
 
diff --git a/drivers/mtd/nand/raw/nand_amd.c b/drivers/mtd/nand/raw/nand_amd.c
index 22f060f..51e9ba7 100644
--- a/drivers/mtd/nand/raw/nand_amd.c
+++ b/drivers/mtd/nand/raw/nand_amd.c
@@ -19,7 +19,7 @@
 
 static void amd_nand_decode_id(struct nand_chip *chip)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 
 	nand_decode_ext_id(chip);
 
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 730165b..a113cfb 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -57,7 +57,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
 static int nand_ooblayout_ecc_sp(struct mtd_info *mtd, int section,
 				 struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 
 	if (section > 1)
@@ -106,7 +106,7 @@ static int nand_ooblayout_free_sp(struct mtd_info *mtd, int section,
 static int nand_ooblayout_ecc_lp(struct mtd_info *mtd, int section,
 				 struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 
 	if (section)
@@ -121,7 +121,7 @@ static int nand_ooblayout_ecc_lp(struct mtd_info *mtd, int section,
 static int nand_ooblayout_free_lp(struct mtd_info *mtd, int section,
 				  struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 
 	if (section)
@@ -146,7 +146,7 @@ static int nand_ooblayout_free_lp(struct mtd_info *mtd, int section,
 static int nand_ooblayout_ecc_lp_hamming(struct mtd_info *mtd, int section,
 					 struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 
 	if (section)
@@ -173,7 +173,7 @@ static int nand_ooblayout_ecc_lp_hamming(struct mtd_info *mtd, int section,
 static int nand_ooblayout_free_lp_hamming(struct mtd_info *mtd, int section,
 					  struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 	int ecc_offset = 0;
 
@@ -210,7 +210,7 @@ static int nand_ooblayout_free_lp_hamming(struct mtd_info *mtd, int section,
 static int check_offs_len(struct mtd_info *mtd,
 					loff_t ofs, uint64_t len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	int ret = 0;
 
 	/* Start address must align on block boundary */
@@ -236,7 +236,7 @@ static int check_offs_len(struct mtd_info *mtd,
  */
 static void nand_release_device(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	/* Release the controller and the chip */
 	spin_lock(&chip->controller->lock);
@@ -254,7 +254,7 @@ static void nand_release_device(struct mtd_info *mtd)
  */
 static uint8_t nand_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	return readb(chip->IO_ADDR_R);
 }
 
@@ -267,7 +267,7 @@ static uint8_t nand_read_byte(struct mtd_info *mtd)
  */
 static uint8_t nand_read_byte16(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R));
 }
 
@@ -279,7 +279,7 @@ static uint8_t nand_read_byte16(struct mtd_info *mtd)
  */
 static u16 nand_read_word(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	return readw(chip->IO_ADDR_R);
 }
 
@@ -292,7 +292,7 @@ static u16 nand_read_word(struct mtd_info *mtd)
  */
 static void nand_select_chip(struct mtd_info *mtd, int chipnr)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	switch (chipnr) {
 	case -1:
@@ -315,7 +315,7 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr)
  */
 static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	chip->write_buf(mtd, &byte, 1);
 }
@@ -329,7 +329,7 @@ static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
  */
 static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	uint16_t word = byte;
 
 	/*
@@ -361,7 +361,7 @@ static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte)
  */
 static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	iowrite8_rep(chip->IO_ADDR_W, buf, len);
 }
@@ -376,7 +376,7 @@ static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
  */
 static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	ioread8_rep(chip->IO_ADDR_R, buf, len);
 }
@@ -391,7 +391,7 @@ static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
  */
 static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	u16 *p = (u16 *) buf;
 
 	iowrite16_rep(chip->IO_ADDR_W, p, len >> 1);
@@ -407,7 +407,7 @@ static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
  */
 static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	u16 *p = (u16 *) buf;
 
 	ioread16_rep(chip->IO_ADDR_R, p, len >> 1);
@@ -423,7 +423,7 @@ static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
 static int nand_block_bad(struct mtd_info *mtd, loff_t ofs)
 {
 	int page, page_end, res;
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	u8 bad;
 
 	if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
@@ -461,7 +461,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs)
  */
 static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mtd_oob_ops ops;
 	uint8_t buf[2] = { 0, 0 };
 	int ret = 0, res, i = 0;
@@ -511,7 +511,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 */
 static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	int res, ret = 0;
 
 	if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) {
@@ -552,7 +552,7 @@ static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
  */
 static int nand_check_wp(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	/* Broken xD cards report WP despite being writable */
 	if (chip->options & NAND_BROKEN_XD)
@@ -572,7 +572,7 @@ static int nand_check_wp(struct mtd_info *mtd)
  */
 static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (!chip->bbt)
 		return 0;
@@ -591,7 +591,7 @@ static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs)
  */
 static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int allowbbt)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (!chip->bbt)
 		return chip->block_bad(mtd, ofs);
@@ -610,7 +610,7 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int allowbbt)
  */
 static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	int i;
 
 	/* Wait for the device to get ready */
@@ -630,7 +630,7 @@ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
  */
 void nand_wait_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	unsigned long timeo = 400;
 
 	if (in_interrupt() || oops_in_progress)
@@ -658,7 +658,7 @@ void nand_wait_ready(struct mtd_info *mtd)
  */
 static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo)
 {
-	register struct nand_chip *chip = mtd_to_nand(mtd);
+	register struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	timeo = jiffies + msecs_to_jiffies(timeo);
 	do {
@@ -681,7 +681,7 @@ static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo)
 static void nand_command(struct mtd_info *mtd, unsigned int command,
 			 int column, int page_addr)
 {
-	register struct nand_chip *chip = mtd_to_nand(mtd);
+	register struct nand_chip *chip = mtd_to_nandchip(mtd);
 	int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
 
 	/* Write out the command to the device */
@@ -805,7 +805,7 @@ static void nand_ccs_delay(struct nand_chip *chip)
 static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
 			    int column, int page_addr)
 {
-	register struct nand_chip *chip = mtd_to_nand(mtd);
+	register struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	/* Emulate NAND_CMD_READOOB */
 	if (command == NAND_CMD_READOOB) {
@@ -939,7 +939,7 @@ static void panic_nand_get_device(struct nand_chip *chip,
 static int
 nand_get_device(struct mtd_info *mtd, int new_state)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	spinlock_t *lock = &chip->controller->lock;
 	wait_queue_head_t *wq = &chip->controller->wq;
 	DECLARE_WAITQUEUE(wait, current);
@@ -1049,7 +1049,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
  */
 static int nand_reset_data_interface(struct nand_chip *chip)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	const struct nand_data_interface *conf;
 	int ret;
 
@@ -1092,7 +1092,7 @@ static int nand_reset_data_interface(struct nand_chip *chip)
  */
 static int nand_setup_data_interface(struct nand_chip *chip)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	int ret;
 
 	if (!chip->setup_data_interface || !chip->data_interface)
@@ -1135,7 +1135,7 @@ static int nand_setup_data_interface(struct nand_chip *chip)
  */
 static int nand_init_data_interface(struct nand_chip *chip)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	int modes, mode, ret;
 
 	if (!chip->setup_data_interface)
@@ -1190,7 +1190,7 @@ static void nand_release_data_interface(struct nand_chip *chip)
  */
 int nand_reset(struct nand_chip *chip, int chipnr)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	int ret;
 
 	ret = nand_reset_data_interface(chip);
@@ -1231,7 +1231,7 @@ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
 {
 	int ret = 0;
 	int status, page;
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	/* Submit address of first page to unlock */
 	page = ofs >> chip->page_shift;
@@ -1266,7 +1266,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
 	int ret = 0;
 	int chipnr;
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	pr_debug("%s: start = 0x%012llx, len = %llu\n",
 			__func__, (unsigned long long)ofs, len);
@@ -1329,7 +1329,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
 	int ret = 0;
 	int chipnr, status, page;
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	pr_debug("%s: start = 0x%012llx, len = %llu\n",
 			__func__, (unsigned long long)ofs, len);
@@ -1935,7 +1935,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
 static uint8_t *nand_transfer_oob(struct mtd_info *mtd, uint8_t *oob,
 				  struct mtd_oob_ops *ops, size_t len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	int ret;
 
 	switch (ops->mode) {
@@ -1968,7 +1968,7 @@ static uint8_t *nand_transfer_oob(struct mtd_info *mtd, uint8_t *oob,
  */
 static int nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	pr_debug("setting READ RETRY mode %d\n", retry_mode);
 
@@ -1993,7 +1993,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
 			    struct mtd_oob_ops *ops)
 {
 	int chipnr, page, realpage, col, bytes, aligned, oob_required;
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	int ret = 0;
 	uint32_t readlen = ops->len;
 	uint32_t oobreadlen = ops->ooblen;
@@ -2176,8 +2176,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
  *
  * Get hold of the chip and call nand_do_read.
  */
-static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
-		     size_t *retlen, uint8_t *buf)
+static int nandc_read(struct mtd_info *mtd, loff_t from, size_t len,
+		      size_t *retlen, uint8_t *buf)
 {
 	struct mtd_oob_ops ops;
 	int ret;
@@ -2340,7 +2340,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
 			    struct mtd_oob_ops *ops)
 {
 	int page, realpage, chipnr;
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mtd_ecc_stats stats;
 	int readlen = ops->ooblen;
 	int len;
@@ -2785,7 +2785,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
 			      struct mtd_oob_ops *ops)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	int ret;
 
 	/*
@@ -2827,7 +2827,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
 			     struct mtd_oob_ops *ops)
 {
 	int chipnr, realpage, page, blockmask, column;
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	uint32_t writelen = ops->len;
 
 	uint32_t oobwritelen = ops->ooblen;
@@ -2959,7 +2959,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
 static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
 			    size_t *retlen, const uint8_t *buf)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct mtd_oob_ops ops;
 	int ret;
 
@@ -2990,8 +2990,8 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
  *
  * NAND write with ECC.
  */
-static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
-			  size_t *retlen, const uint8_t *buf)
+static int nandc_write(struct mtd_info *mtd, loff_t to, size_t len,
+		       size_t *retlen, const uint8_t *buf)
 {
 	struct mtd_oob_ops ops;
 	int ret;
@@ -3019,7 +3019,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
 			     struct mtd_oob_ops *ops)
 {
 	int chipnr, page, status, len;
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	pr_debug("%s: to = 0x%08x, len = %i\n",
 			 __func__, (unsigned int)to, (int)ops->ooblen);
@@ -3142,7 +3142,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
  */
 static int single_erase(struct mtd_info *mtd, int page)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	/* Send commands to erase a block */
 	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
 	chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
@@ -3157,7 +3157,7 @@ static int single_erase(struct mtd_info *mtd, int page)
  *
  * Erase one ore more blocks.
  */
-static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
+static int nandc_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
 	return nand_erase_nand(mtd, instr, 0);
 }
@@ -3174,7 +3174,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 		    int allowbbt)
 {
 	int page, status, pages_per_block, ret, chipnr;
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	loff_t len;
 
 	pr_debug("%s: start = 0x%012llx, len = %llu\n",
@@ -3300,7 +3300,7 @@ static void nand_sync(struct mtd_info *mtd)
  */
 static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	int chipnr = (int)(offs >> chip->chip_shift);
 	int ret;
 
@@ -3344,7 +3344,7 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
  */
 static int nand_max_bad_blocks(struct mtd_info *mtd, loff_t ofs, size_t len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	u32 part_start_block;
 	u32 part_end_block;
 	u32 part_start_die;
@@ -3438,7 +3438,7 @@ static int nand_suspend(struct mtd_info *mtd)
  */
 static void nand_resume(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (chip->state == FL_PM_SUSPENDED)
 		nand_release_device(mtd);
@@ -3544,7 +3544,7 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
 static int nand_flash_detect_ext_param_page(struct nand_chip *chip,
 					    struct nand_onfi_params *p)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct onfi_ext_param_page *ep;
 	struct onfi_ext_section *s;
 	struct onfi_ext_ecc_info *ecc;
@@ -3617,7 +3617,7 @@ static int nand_flash_detect_ext_param_page(struct nand_chip *chip,
  */
 static int nand_flash_detect_onfi(struct nand_chip *chip)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct nand_onfi_params *p = &chip->onfi_params;
 	int i, j;
 	int val;
@@ -3719,7 +3719,7 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
  */
 static int nand_flash_detect_jedec(struct nand_chip *chip)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct nand_jedec_params *p = &chip->jedec_params;
 	struct jedec_ecc_info *ecc;
 	int val;
@@ -3869,7 +3869,7 @@ static int nand_get_bits_per_cell(u8 cellinfo)
  */
 void nand_decode_ext_id(struct nand_chip *chip)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	int extid;
 	u8 *id_data = chip->id.data;
 	/* The 3rd id byte holds MLC / multichip data */
@@ -3899,7 +3899,7 @@ void nand_decode_ext_id(struct nand_chip *chip)
  */
 static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 
 	mtd->erasesize = type->erasesize;
 	mtd->writesize = type->pagesize;
@@ -3916,7 +3916,7 @@ static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type)
  */
 static void nand_decode_bbm_options(struct nand_chip *chip)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 
 	/* Set the bad block position */
 	if (mtd->writesize > 512 || (chip->options & NAND_BUSWIDTH_16))
@@ -3933,7 +3933,7 @@ static inline bool is_full_id_nand(struct nand_flash_dev *type)
 static bool find_full_id_nand(struct nand_chip *chip,
 			      struct nand_flash_dev *type)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	u8 *id_data = chip->id.data;
 
 	if (!strncmp(type->id, id_data, type->id_len)) {
@@ -4010,7 +4010,7 @@ static void nand_manufacturer_cleanup(struct nand_chip *chip)
 static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
 {
 	const struct nand_manufacturer *manufacturer;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	int busw;
 	int i, ret;
 	u8 *id_data = chip->id.data;
@@ -4333,7 +4333,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
 		    struct nand_flash_dev *table)
 {
 	int i, nand_maf_id, nand_dev_id;
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	int ret;
 
 	ret = nand_dt_init(chip);
@@ -4415,7 +4415,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
 
 static int nand_set_ecc_soft_ops(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 
 	if (WARN_ON(ecc->mode != NAND_ECC_SOFT))
@@ -4525,7 +4525,7 @@ static int nand_set_ecc_soft_ops(struct mtd_info *mtd)
  */
 static bool nand_ecc_strength_good(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 	int corr, ds_corr;
 
@@ -4573,7 +4573,7 @@ static bool invalid_ecc_page_accessors(struct nand_chip *chip)
  */
 int nand_scan_tail(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 	struct nand_buffers *nbuf = NULL;
 	int ret;
@@ -4827,11 +4827,11 @@ int nand_scan_tail(struct mtd_info *mtd)
 	mtd->type = nand_is_slc(chip) ? MTD_NANDFLASH : MTD_MLCNANDFLASH;
 	mtd->flags = (chip->options & NAND_ROM) ? MTD_CAP_ROM :
 						MTD_CAP_NANDFLASH;
-	mtd->_erase = nand_erase;
+	mtd->_erase = nandc_erase;
 	mtd->_point = NULL;
 	mtd->_unpoint = NULL;
-	mtd->_read = nand_read;
-	mtd->_write = nand_write;
+	mtd->_read = nandc_read;
+	mtd->_write = nandc_write;
 	mtd->_panic_write = panic_nand_write;
 	mtd->_read_oob = nand_read_oob;
 	mtd->_write_oob = nand_write_oob;
@@ -4943,7 +4943,7 @@ void nand_cleanup(struct nand_chip *chip)
 void nand_release(struct mtd_info *mtd)
 {
 	mtd_device_unregister(mtd);
-	nand_cleanup(mtd_to_nand(mtd));
+	nand_cleanup(mtd_to_nandchip(mtd));
 }
 EXPORT_SYMBOL_GPL(nand_release);
 
diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
index 2915b67..396b248 100644
--- a/drivers/mtd/nand/raw/nand_bbt.c
+++ b/drivers/mtd/nand/raw/nand_bbt.c
@@ -172,7 +172,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 		struct nand_bbt_descr *td, int offs)
 {
 	int res, ret = 0, i, j, act = 0;
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	size_t retlen, len, totlen;
 	loff_t from;
 	int bits = td->options & NAND_BBT_NRBITS_MSK;
@@ -263,7 +263,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
  */
 static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int res = 0, i;
 
 	if (td->options & NAND_BBT_PERCHIP) {
@@ -388,7 +388,7 @@ static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td)
 static void read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
 			  struct nand_bbt_descr *td, struct nand_bbt_descr *md)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 
 	/* Read the primary version, if available */
 	if (td->options & NAND_BBT_VERSION) {
@@ -454,7 +454,7 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
 static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 	struct nand_bbt_descr *bd, int chip)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int i, numblocks, numpages;
 	int startblock;
 	loff_t from;
@@ -523,7 +523,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
  */
 static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int i, chips;
 	int startblock, block, dir;
 	int scanlen = mtd->writesize + mtd->oobsize;
@@ -683,7 +683,7 @@ static void mark_bbt_block_bad(struct nand_chip *this,
 			       struct nand_bbt_descr *td,
 			       int chip, int block)
 {
-	struct mtd_info *mtd = nand_to_mtd(this);
+	struct mtd_info *mtd = nandchip_to_mtd(this);
 	loff_t to;
 	int res;
 
@@ -712,7 +712,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 		     struct nand_bbt_descr *td, struct nand_bbt_descr *md,
 		     int chipsel)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct erase_info einfo;
 	int i, res, chip = 0;
 	int bits, page, offs, numblocks, sft, sftmsk;
@@ -896,7 +896,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
  */
 static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 
 	return create_bbt(mtd, this->buffers->databuf, bd, -1);
 }
@@ -915,7 +915,7 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b
 static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
 {
 	int i, chips, writeops, create, chipsel, res, res2;
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct nand_bbt_descr *td = this->bbt_td;
 	struct nand_bbt_descr *md = this->bbt_md;
 	struct nand_bbt_descr *rd, *rd2;
@@ -1039,7 +1039,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
  */
 static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int i, j, chips, block, nrblocks, update;
 	uint8_t oldval;
 
@@ -1099,7 +1099,7 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
  */
 static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	u32 pattern_len;
 	u32 bits;
 	u32 table_size;
@@ -1151,7 +1151,7 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
  */
 static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int len, res;
 	uint8_t *buf;
 	struct nand_bbt_descr *td = this->bbt_td;
@@ -1224,7 +1224,7 @@ static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
  */
 static int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int len, res = 0;
 	int chip, chipsel;
 	uint8_t *buf;
@@ -1358,7 +1358,7 @@ static int nand_create_badblock_pattern(struct nand_chip *this)
  */
 int nand_default_bbt(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int ret;
 
 	/* Is a flash based bad block table requested? */
@@ -1394,7 +1394,7 @@ int nand_default_bbt(struct mtd_info *mtd)
  */
 int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int block;
 
 	block = (int)(offs >> this->bbt_erase_shift);
@@ -1409,7 +1409,7 @@ int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs)
  */
 int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int block, res;
 
 	block = (int)(offs >> this->bbt_erase_shift);
@@ -1436,7 +1436,7 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
  */
 int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int block, ret = 0;
 
 	block = (int)(offs >> this->bbt_erase_shift);
diff --git a/drivers/mtd/nand/raw/nand_bch.c b/drivers/mtd/nand/raw/nand_bch.c
index 505441c..b1901d9 100644
--- a/drivers/mtd/nand/raw/nand_bch.c
+++ b/drivers/mtd/nand/raw/nand_bch.c
@@ -50,7 +50,7 @@ struct nand_bch_control {
 int nand_bch_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
 			   unsigned char *code)
 {
-	const struct nand_chip *chip = mtd_to_nand(mtd);
+	const struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nand_bch_control *nbc = chip->ecc.priv;
 	unsigned int i;
 
@@ -77,7 +77,7 @@ int nand_bch_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
 int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
 			  unsigned char *read_ecc, unsigned char *calc_ecc)
 {
-	const struct nand_chip *chip = mtd_to_nand(mtd);
+	const struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nand_bch_control *nbc = chip->ecc.priv;
 	unsigned int *errloc = nbc->errloc;
 	int i, count;
@@ -120,7 +120,7 @@ int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
  */
 struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	unsigned int m, t, eccsteps, i;
 	struct nand_bch_control *nbc = NULL;
 	unsigned char *erased_page;
diff --git a/drivers/mtd/nand/raw/nand_ecc.c b/drivers/mtd/nand/raw/nand_ecc.c
index 7613a03..741b68a 100644
--- a/drivers/mtd/nand/raw/nand_ecc.c
+++ b/drivers/mtd/nand/raw/nand_ecc.c
@@ -424,7 +424,7 @@ int nand_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
 		       unsigned char *code)
 {
 	__nand_calculate_ecc(buf,
-			mtd_to_nand(mtd)->ecc.size, code);
+			mtd_to_nandchip(mtd)->ecc.size, code);
 
 	return 0;
 }
@@ -524,7 +524,7 @@ int nand_correct_data(struct mtd_info *mtd, unsigned char *buf,
 		      unsigned char *read_ecc, unsigned char *calc_ecc)
 {
 	return __nand_correct_data(buf, read_ecc, calc_ecc,
-				   mtd_to_nand(mtd)->ecc.size);
+				   mtd_to_nandchip(mtd)->ecc.size);
 }
 EXPORT_SYMBOL(nand_correct_data);
 
diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
index b735cc8..b35a0a5 100644
--- a/drivers/mtd/nand/raw/nand_hynix.c
+++ b/drivers/mtd/nand/raw/nand_hynix.c
@@ -67,7 +67,7 @@ struct hynix_read_retry_otp {
 
 static bool hynix_nand_has_valid_jedecid(struct nand_chip *chip)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	u8 jedecid[6] = { };
 	int i = 0;
 
@@ -80,7 +80,7 @@ static bool hynix_nand_has_valid_jedecid(struct nand_chip *chip)
 
 static int hynix_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct hynix_nand *hynix = nand_get_manufacturer_data(chip);
 	const u8 *values;
 	int status;
@@ -172,7 +172,7 @@ static int hynix_read_rr_otp(struct nand_chip *chip,
 			     const struct hynix_read_retry_otp *info,
 			     void *buf)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	int i;
 
 	chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
@@ -365,7 +365,7 @@ static int hynix_nand_rr_init(struct nand_chip *chip)
 static void hynix_nand_extract_oobsize(struct nand_chip *chip,
 				       bool valid_jedecid)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	u8 oobsize;
 
 	oobsize = ((chip->id.data[3] >> 2) & 0x3) |
@@ -543,7 +543,7 @@ static void hynix_nand_extract_scrambling_requirements(struct nand_chip *chip,
 
 static void hynix_nand_decode_id(struct nand_chip *chip)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	bool valid_jedecid;
 	u8 tmp;
 
diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c
index 02c4c1f..6dd0876 100644
--- a/drivers/mtd/nand/raw/nand_micron.c
+++ b/drivers/mtd/nand/raw/nand_micron.c
@@ -45,7 +45,7 @@ struct nand_onfi_vendor_micron {
 
 static int micron_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode};
 
 	return chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY,
@@ -108,7 +108,7 @@ static int micron_nand_on_die_ecc_setup(struct nand_chip *chip, bool enable)
 	if (enable)
 		feature[0] |= ONFI_FEATURE_ON_DIE_ECC_EN;
 
-	return chip->onfi_set_features(nand_to_mtd(chip), chip,
+	return chip->onfi_set_features(nandchip_to_mtd(chip), chip,
 				       ONFI_FEATURE_ON_DIE_ECC, feature);
 }
 
@@ -229,7 +229,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
 	if (ret)
 		return MICRON_ON_DIE_UNSUPPORTED;
 
-	chip->onfi_get_features(nand_to_mtd(chip), chip,
+	chip->onfi_get_features(nandchip_to_mtd(chip), chip,
 				ONFI_FEATURE_ON_DIE_ECC, feature);
 	if ((feature[0] & ONFI_FEATURE_ON_DIE_ECC_EN) == 0)
 		return MICRON_ON_DIE_UNSUPPORTED;
@@ -238,7 +238,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
 	if (ret)
 		return MICRON_ON_DIE_UNSUPPORTED;
 
-	chip->onfi_get_features(nand_to_mtd(chip), chip,
+	chip->onfi_get_features(nandchip_to_mtd(chip), chip,
 				ONFI_FEATURE_ON_DIE_ECC, feature);
 	if (feature[0] & ONFI_FEATURE_ON_DIE_ECC_EN)
 		return MICRON_ON_DIE_MANDATORY;
@@ -255,7 +255,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
 
 static int micron_nand_init(struct nand_chip *chip)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	int ondie;
 	int ret;
 
diff --git a/drivers/mtd/nand/raw/nand_samsung.c b/drivers/mtd/nand/raw/nand_samsung.c
index ca17b44..bc54b578 100644
--- a/drivers/mtd/nand/raw/nand_samsung.c
+++ b/drivers/mtd/nand/raw/nand_samsung.c
@@ -19,7 +19,7 @@
 
 static void samsung_nand_decode_id(struct nand_chip *chip)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 
 	/* New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) */
 	if (chip->id.len == 6 && !nand_is_slc(chip) &&
@@ -93,7 +93,7 @@ static void samsung_nand_decode_id(struct nand_chip *chip)
 
 static int samsung_nand_init(struct nand_chip *chip)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 
 	if (mtd->writesize > 512)
 		chip->options |= NAND_SAMSUNG_LP_OPTIONS;
diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index 57df857..8a24ccc 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -19,7 +19,7 @@
 
 static void toshiba_nand_decode_id(struct nand_chip *chip)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 
 	nand_decode_ext_id(chip);
 
diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c
index 5ba4635..a0246fc 100644
--- a/drivers/mtd/nand/raw/nandsim.c
+++ b/drivers/mtd/nand/raw/nandsim.c
@@ -662,7 +662,7 @@ static char __init *get_partition_name(int i)
  */
 static int __init init_nandsim(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nandsim   *ns   = nand_get_controller_data(chip);
 	int i, ret = 0;
 	uint64_t remains;
@@ -1892,7 +1892,7 @@ static void switch_state(struct nandsim *ns)
 
 static u_char ns_nand_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nandsim *ns = nand_get_controller_data(chip);
 	u_char outb = 0x00;
 
@@ -1954,7 +1954,7 @@ static u_char ns_nand_read_byte(struct mtd_info *mtd)
 
 static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nandsim *ns = nand_get_controller_data(chip);
 
 	/* Sanity and correctness checks */
@@ -2109,7 +2109,7 @@ static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
 
 static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nandsim *ns = nand_get_controller_data(chip);
 
 	ns->lines.cle = bitmask & NAND_CLE ? 1 : 0;
@@ -2128,7 +2128,7 @@ static int ns_device_ready(struct mtd_info *mtd)
 
 static uint16_t ns_nand_read_word(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	NS_DBG("read_word\n");
 
@@ -2137,7 +2137,7 @@ static uint16_t ns_nand_read_word(struct mtd_info *mtd)
 
 static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nandsim *ns = nand_get_controller_data(chip);
 
 	/* Check that chip is expecting data input */
@@ -2165,7 +2165,7 @@ static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 
 static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nandsim *ns = nand_get_controller_data(chip);
 
 	/* Sanity and correctness checks */
@@ -2187,7 +2187,7 @@ static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 		int i;
 
 		for (i = 0; i < len; i++)
-			buf[i] = mtd_to_nand(mtd)->read_byte(mtd);
+			buf[i] = mtd_to_nandchip(mtd)->read_byte(mtd);
 
 		return;
 	}
@@ -2231,7 +2231,7 @@ static int __init ns_init_module(void)
 		NS_ERR("unable to allocate core structures.\n");
 		return -ENOMEM;
 	}
-	nsmtd       = nand_to_mtd(chip);
+	nsmtd       = nandchip_to_mtd(chip);
 	nand        = (struct nandsim *)(chip + 1);
 	nand_set_controller_data(chip, (void *)nand);
 
@@ -2391,7 +2391,7 @@ static int __init ns_init_module(void)
  */
 static void __exit ns_cleanup_module(void)
 {
-	struct nand_chip *chip = mtd_to_nand(nsmtd);
+	struct nand_chip *chip = mtd_to_nandchip(nsmtd);
 	struct nandsim *ns = nand_get_controller_data(chip);
 	int i;
 
@@ -2400,7 +2400,7 @@ static void __exit ns_cleanup_module(void)
 	nand_release(nsmtd); /* Unregister driver */
 	for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i)
 		kfree(ns->partitions[i].name);
-	kfree(mtd_to_nand(nsmtd));        /* Free other structures */
+	kfree(mtd_to_nandchip(nsmtd));        /* Free other structures */
 	free_lists();
 }
 
diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c
index d8a8068..3b9ecbe 100644
--- a/drivers/mtd/nand/raw/ndfc.c
+++ b/drivers/mtd/nand/raw/ndfc.c
@@ -47,7 +47,7 @@ struct ndfc_controller {
 static void ndfc_select_chip(struct mtd_info *mtd, int chip)
 {
 	uint32_t ccr;
-	struct nand_chip *nchip = mtd_to_nand(mtd);
+	struct nand_chip *nchip = mtd_to_nandchip(mtd);
 	struct ndfc_controller *ndfc = nand_get_controller_data(nchip);
 
 	ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
@@ -61,7 +61,7 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip)
 
 static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct ndfc_controller *ndfc = nand_get_controller_data(chip);
 
 	if (cmd == NAND_CMD_NONE)
@@ -75,7 +75,7 @@ static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 
 static int ndfc_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct ndfc_controller *ndfc = nand_get_controller_data(chip);
 
 	return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
@@ -84,7 +84,7 @@ static int ndfc_ready(struct mtd_info *mtd)
 static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
 {
 	uint32_t ccr;
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct ndfc_controller *ndfc = nand_get_controller_data(chip);
 
 	ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
@@ -96,7 +96,7 @@ static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
 static int ndfc_calculate_ecc(struct mtd_info *mtd,
 			      const u_char *dat, u_char *ecc_code)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct ndfc_controller *ndfc = nand_get_controller_data(chip);
 	uint32_t ecc;
 	uint8_t *p = (uint8_t *)&ecc;
@@ -120,7 +120,7 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd,
  */
 static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct ndfc_controller *ndfc = nand_get_controller_data(chip);
 	uint32_t *p = (uint32_t *) buf;
 
@@ -130,7 +130,7 @@ static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 
 static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct ndfc_controller *ndfc = nand_get_controller_data(chip);
 	uint32_t *p = (uint32_t *) buf;
 
@@ -146,7 +146,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
 {
 	struct device_node *flash_np;
 	struct nand_chip *chip = &ndfc->chip;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	int ret;
 
 	chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
@@ -256,7 +256,7 @@ static int ndfc_probe(struct platform_device *ofdev)
 static int ndfc_remove(struct platform_device *ofdev)
 {
 	struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev);
-	struct mtd_info *mtd = nand_to_mtd(&ndfc->chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&ndfc->chip);
 
 	nand_release(mtd);
 	kfree(mtd->name);
diff --git a/drivers/mtd/nand/raw/nuc900_nand.c b/drivers/mtd/nand/raw/nuc900_nand.c
index 7bb4d2e..2a2bfce 100644
--- a/drivers/mtd/nand/raw/nuc900_nand.c
+++ b/drivers/mtd/nand/raw/nuc900_nand.c
@@ -63,7 +63,7 @@ struct nuc900_nand {
 
 static inline struct nuc900_nand *mtd_to_nuc900(struct mtd_info *mtd)
 {
-	return container_of(mtd_to_nand(mtd), struct nuc900_nand, chip);
+	return container_of(mtd_to_nandchip(mtd), struct nuc900_nand, chip);
 }
 
 static const struct mtd_partition partitions[] = {
@@ -132,7 +132,7 @@ static int nuc900_nand_devready(struct mtd_info *mtd)
 static void nuc900_nand_command_lp(struct mtd_info *mtd, unsigned int command,
 				   int column, int page_addr)
 {
-	register struct nand_chip *chip = mtd_to_nand(mtd);
+	register struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nuc900_nand *nand = mtd_to_nuc900(mtd);
 
 	if (command == NAND_CMD_READOOB) {
@@ -243,7 +243,7 @@ static int nuc900_nand_probe(struct platform_device *pdev)
 	if (!nuc900_nand)
 		return -ENOMEM;
 	chip = &(nuc900_nand->chip);
-	mtd = nand_to_mtd(chip);
+	mtd = nandchip_to_mtd(chip);
 
 	mtd->dev.parent		= &pdev->dev;
 	spin_lock_init(&nuc900_nand->lock);
@@ -284,7 +284,7 @@ static int nuc900_nand_remove(struct platform_device *pdev)
 {
 	struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev);
 
-	nand_release(nand_to_mtd(&nuc900_nand->chip));
+	nand_release(nandchip_to_mtd(&nuc900_nand->chip));
 	clk_disable(nuc900_nand->clk);
 
 	return 0;
diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c
index 54540c8..d8ec8a3 100644
--- a/drivers/mtd/nand/raw/omap2.c
+++ b/drivers/mtd/nand/raw/omap2.c
@@ -184,7 +184,7 @@ struct omap_nand_info {
 
 static inline struct omap_nand_info *mtd_to_omap(struct mtd_info *mtd)
 {
-	return container_of(mtd_to_nand(mtd), struct omap_nand_info, nand);
+	return container_of(mtd_to_nandchip(mtd), struct omap_nand_info, nand);
 }
 
 /**
@@ -279,7 +279,7 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
  */
 static void omap_read_buf8(struct mtd_info *mtd, u_char *buf, int len)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 
 	ioread8_rep(nand->IO_ADDR_R, buf, len);
 }
@@ -313,7 +313,7 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
  */
 static void omap_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 
 	ioread16_rep(nand->IO_ADDR_R, buf, len / 2);
 }
@@ -944,7 +944,7 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
 {
 	struct omap_nand_info *info = mtd_to_omap(mtd);
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
 	u32 val;
 
@@ -990,7 +990,7 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
  */
 static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct omap_nand_info *info = mtd_to_omap(mtd);
 	unsigned long timeo = jiffies;
 	int status, state = this->state;
@@ -1042,7 +1042,7 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, int mode)
 	unsigned int dev_width, nsectors;
 	struct omap_nand_info *info = mtd_to_omap(mtd);
 	enum omap_ecc ecc_opt = info->ecc_opt;
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	u32 val, wr_mode;
 	unsigned int ecc_size1, ecc_size0;
 
@@ -1757,7 +1757,7 @@ static int omap_ooblayout_free(struct mtd_info *mtd, int section,
 static int omap_sw_ooblayout_ecc(struct mtd_info *mtd, int section,
 				 struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	int off = BADBLOCK_MARKER_LENGTH;
 
 	if (section >= chip->ecc.steps)
@@ -1776,7 +1776,7 @@ static int omap_sw_ooblayout_ecc(struct mtd_info *mtd, int section,
 static int omap_sw_ooblayout_free(struct mtd_info *mtd, int section,
 				  struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	int off = BADBLOCK_MARKER_LENGTH;
 
 	if (section)
@@ -1851,7 +1851,7 @@ static int omap_nand_probe(struct platform_device *pdev)
 	}
 
 	nand_chip		= &info->nand;
-	mtd			= nand_to_mtd(nand_chip);
+	mtd			= nandchip_to_mtd(nand_chip);
 	mtd->dev.parent		= &pdev->dev;
 	nand_chip->ecc.priv	= NULL;
 	nand_set_flash_node(nand_chip, dev->of_node);
@@ -2189,7 +2189,7 @@ static int omap_nand_probe(struct platform_device *pdev)
 static int omap_nand_remove(struct platform_device *pdev)
 {
 	struct mtd_info *mtd = platform_get_drvdata(pdev);
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct omap_nand_info *info = mtd_to_omap(mtd);
 	if (nand_chip->ecc.priv) {
 		nand_bch_free(nand_chip->ecc.priv);
diff --git a/drivers/mtd/nand/raw/orion_nand.c b/drivers/mtd/nand/raw/orion_nand.c
index ae4c0be..24f35fa 100644
--- a/drivers/mtd/nand/raw/orion_nand.c
+++ b/drivers/mtd/nand/raw/orion_nand.c
@@ -30,7 +30,7 @@ struct orion_nand_info {
 
 static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *nc = mtd_to_nand(mtd);
+	struct nand_chip *nc = mtd_to_nandchip(mtd);
 	struct orion_nand_data *board = nand_get_controller_data(nc);
 	u32 offs;
 
@@ -52,7 +52,7 @@ static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl
 
 static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	void __iomem *io_base = chip->IO_ADDR_R;
 	uint64_t *buf64;
 	int i = 0;
@@ -95,7 +95,7 @@ static int __init orion_nand_probe(struct platform_device *pdev)
 	if (!info)
 		return -ENOMEM;
 	nc = &info->chip;
-	mtd = nand_to_mtd(nc);
+	mtd = nandchip_to_mtd(nc);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	io_base = devm_ioremap_resource(&pdev->dev, res);
@@ -190,7 +190,7 @@ static int orion_nand_remove(struct platform_device *pdev)
 {
 	struct orion_nand_info *info = platform_get_drvdata(pdev);
 	struct nand_chip *chip = &info->chip;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 
 	nand_release(mtd);
 
diff --git a/drivers/mtd/nand/raw/oxnas_nand.c b/drivers/mtd/nand/raw/oxnas_nand.c
index f14eec3..27eeee3 100644
--- a/drivers/mtd/nand/raw/oxnas_nand.c
+++ b/drivers/mtd/nand/raw/oxnas_nand.c
@@ -40,7 +40,7 @@ struct oxnas_nand_ctrl {
 
 static uint8_t oxnas_nand_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
 
 	return readb(oxnas->io_base);
@@ -48,7 +48,7 @@ static uint8_t oxnas_nand_read_byte(struct mtd_info *mtd)
 
 static void oxnas_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
 
 	ioread8_rep(oxnas->io_base, buf, len);
@@ -56,7 +56,7 @@ static void oxnas_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
 
 static void oxnas_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
 
 	iowrite8_rep(oxnas->io_base, buf, len);
@@ -66,7 +66,7 @@ static void oxnas_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
 static void oxnas_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
 				unsigned int ctrl)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
 
 	if (ctrl & NAND_CLE)
@@ -126,7 +126,7 @@ static int oxnas_nand_probe(struct platform_device *pdev)
 		nand_set_flash_node(chip, nand_np);
 		nand_set_controller_data(chip, oxnas);
 
-		mtd = nand_to_mtd(chip);
+		mtd = nandchip_to_mtd(chip);
 		mtd->dev.parent = &pdev->dev;
 		mtd->priv = chip;
 
@@ -165,7 +165,7 @@ static int oxnas_nand_remove(struct platform_device *pdev)
 	struct oxnas_nand_ctrl *oxnas = platform_get_drvdata(pdev);
 
 	if (oxnas->chips[0])
-		nand_release(nand_to_mtd(oxnas->chips[0]));
+		nand_release(nandchip_to_mtd(oxnas->chips[0]));
 
 	clk_disable_unprepare(oxnas->clk);
 
diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c
index a47a7e4..7b69e3e 100644
--- a/drivers/mtd/nand/raw/pasemi_nand.c
+++ b/drivers/mtd/nand/raw/pasemi_nand.c
@@ -45,7 +45,7 @@
 
 static void pasemi_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	while (len > 0x800) {
 		memcpy_fromio(buf, chip->IO_ADDR_R, 0x800);
@@ -57,7 +57,7 @@ static void pasemi_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 
 static void pasemi_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	while (len > 0x800) {
 		memcpy_toio(chip->IO_ADDR_R, buf, 0x800);
@@ -70,7 +70,7 @@ static void pasemi_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 static void pasemi_hwcontrol(struct mtd_info *mtd, int cmd,
 			     unsigned int ctrl)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (cmd == NAND_CMD_NONE)
 		return;
@@ -117,7 +117,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev)
 		goto out;
 	}
 
-	pasemi_nand_mtd = nand_to_mtd(chip);
+	pasemi_nand_mtd = nandchip_to_mtd(chip);
 
 	/* Link the private data with the MTD structure */
 	pasemi_nand_mtd->dev.parent = dev;
@@ -188,7 +188,7 @@ static int pasemi_nand_remove(struct platform_device *ofdev)
 	if (!pasemi_nand_mtd)
 		return 0;
 
-	chip = mtd_to_nand(pasemi_nand_mtd);
+	chip = mtd_to_nandchip(pasemi_nand_mtd);
 
 	/* Release resources, unregister device */
 	nand_release(pasemi_nand_mtd);
diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c
index 925a132..ba10bb1 100644
--- a/drivers/mtd/nand/raw/plat_nand.c
+++ b/drivers/mtd/nand/raw/plat_nand.c
@@ -57,7 +57,7 @@ static int plat_nand_probe(struct platform_device *pdev)
 		return PTR_ERR(data->io_base);
 
 	nand_set_flash_node(&data->chip, pdev->dev.of_node);
-	mtd = nand_to_mtd(&data->chip);
+	mtd = nandchip_to_mtd(&data->chip);
 	mtd->dev.parent = &pdev->dev;
 
 	data->chip.IO_ADDR_R = data->io_base;
@@ -114,7 +114,7 @@ static int plat_nand_remove(struct platform_device *pdev)
 	struct plat_nand_data *data = platform_get_drvdata(pdev);
 	struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev);
 
-	nand_release(nand_to_mtd(&data->chip));
+	nand_release(nandchip_to_mtd(&data->chip));
 	if (pdata->ctrl.remove)
 		pdata->ctrl.remove(pdev);
 
diff --git a/drivers/mtd/nand/raw/pxa3xx_nand.c b/drivers/mtd/nand/raw/pxa3xx_nand.c
index fc4d35e..94d3976 100644
--- a/drivers/mtd/nand/raw/pxa3xx_nand.c
+++ b/drivers/mtd/nand/raw/pxa3xx_nand.c
@@ -326,7 +326,7 @@ struct pxa3xx_nand_flash {
 static int pxa3xx_ooblayout_ecc(struct mtd_info *mtd, int section,
 				struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 	int nchunks = mtd->writesize / info->chunk_size;
@@ -344,7 +344,7 @@ static int pxa3xx_ooblayout_ecc(struct mtd_info *mtd, int section,
 static int pxa3xx_ooblayout_free(struct mtd_info *mtd, int section,
 				 struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 	int nchunks = mtd->writesize / info->chunk_size;
@@ -509,7 +509,7 @@ static int pxa3xx_nand_init_timings_compat(struct pxa3xx_nand_host *host,
 	struct nand_chip *chip = &host->chip;
 	struct pxa3xx_nand_info *info = host->info_data;
 	const struct pxa3xx_nand_flash *f = NULL;
-	struct mtd_info *mtd = nand_to_mtd(&host->chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&host->chip);
 	int i, id, ntypes;
 
 	ntypes = ARRAY_SIZE(builtin_flash_types);
@@ -931,7 +931,7 @@ static void set_command_address(struct pxa3xx_nand_info *info,
 static void prepare_start_command(struct pxa3xx_nand_info *info, int command)
 {
 	struct pxa3xx_nand_host *host = info->host[info->cs];
-	struct mtd_info *mtd = nand_to_mtd(&host->chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&host->chip);
 
 	/* reset data and oob column point to handle data */
 	info->buf_start		= 0;
@@ -984,7 +984,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
 	struct mtd_info *mtd;
 
 	host = info->host[info->cs];
-	mtd = nand_to_mtd(&host->chip);
+	mtd = nandchip_to_mtd(&host->chip);
 	addr_cycle = 0;
 	exec_cmd = 1;
 
@@ -1168,7 +1168,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
 static void nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 			 int column, int page_addr)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 	int exec_cmd;
@@ -1217,7 +1217,7 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd,
 				  const unsigned command,
 				  int column, int page_addr)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 	int exec_cmd, ext_cmd_type;
@@ -1373,7 +1373,7 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
 
 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 	char retval = 0xFF;
@@ -1387,7 +1387,7 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 
 static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 	u16 retval = 0xFFFF;
@@ -1401,7 +1401,7 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
 
 static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
@@ -1413,7 +1413,7 @@ static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
 		const uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
@@ -1429,7 +1429,7 @@ static void pxa3xx_nand_select_chip(struct mtd_info *mtd, int chip)
 
 static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 
@@ -1480,7 +1480,7 @@ static void pxa3xx_nand_config_tail(struct pxa3xx_nand_info *info)
 {
 	struct pxa3xx_nand_host *host = info->host[info->cs];
 	struct nand_chip *chip = &host->chip;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 
 	info->reg_ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
 	info->reg_ndcr |= (chip->page_shift == 6) ? NDCR_PG_PER_BLK : 0;
@@ -1569,7 +1569,7 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info,
 			struct mtd_info *mtd,
 			int strength, int ecc_stepsize, int page_size)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 
 	if (strength == 1 && ecc_stepsize == 512 && page_size == 2048) {
@@ -1651,7 +1651,7 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info,
 
 static int pxa3xx_nand_scan(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 	struct platform_device *pdev = info->pdev;
@@ -1792,7 +1792,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
 		host = (void *)&info[1] + sizeof(*host) * cs;
 		chip = &host->chip;
 		nand_set_controller_data(chip, host);
-		mtd = nand_to_mtd(chip);
+		mtd = nandchip_to_mtd(chip);
 		info->host[cs] = host;
 		host->cs = cs;
 		host->info_data = info;
@@ -1912,7 +1912,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
 	clk_disable_unprepare(info->clk);
 
 	for (cs = 0; cs < pdata->num_cs; cs++)
-		nand_release(nand_to_mtd(&info->host[cs]->chip));
+		nand_release(nandchip_to_mtd(&info->host[cs]->chip));
 	return 0;
 }
 
@@ -1972,7 +1972,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 	info = platform_get_drvdata(pdev);
 	probe_success = 0;
 	for (cs = 0; cs < pdata->num_cs; cs++) {
-		struct mtd_info *mtd = nand_to_mtd(&info->host[cs]->chip);
+		struct mtd_info *mtd = nandchip_to_mtd(&info->host[cs]->chip);
 
 		/*
 		 * The mtd name matches the one used in 'mtdparts' kernel
diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c
index a77c66f..3b2d16b 100644
--- a/drivers/mtd/nand/raw/qcom_nandc.c
+++ b/drivers/mtd/nand/raw/qcom_nandc.c
@@ -873,7 +873,7 @@ static void post_command(struct qcom_nand_host *host, int command)
 static void qcom_nandc_command(struct mtd_info *mtd, unsigned int command,
 			       int column, int page_addr)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct qcom_nand_host *host = to_qcom_nand_host(chip);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
@@ -1008,7 +1008,7 @@ static int parse_read_errors(struct qcom_nand_host *host, u8 *data_buf,
 {
 	struct nand_chip *chip = &host->chip;
 	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 	unsigned int max_bitflips = 0;
 	struct read_stats *buf;
@@ -1481,7 +1481,7 @@ static int qcom_nandc_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
 
 static int qcom_nandc_block_bad(struct mtd_info *mtd, loff_t ofs)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct qcom_nand_host *host = to_qcom_nand_host(chip);
 	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
@@ -1521,7 +1521,7 @@ static int qcom_nandc_block_bad(struct mtd_info *mtd, loff_t ofs)
 
 static int qcom_nandc_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct qcom_nand_host *host = to_qcom_nand_host(chip);
 	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
@@ -1571,7 +1571,7 @@ static int qcom_nandc_block_markbad(struct mtd_info *mtd, loff_t ofs)
  */
 static uint8_t qcom_nandc_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct qcom_nand_host *host = to_qcom_nand_host(chip);
 	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
 	u8 *buf = nandc->data_buffer;
@@ -1593,7 +1593,7 @@ static uint8_t qcom_nandc_read_byte(struct mtd_info *mtd)
 
 static void qcom_nandc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
 	int real_len = min_t(size_t, len, nandc->buf_count - nandc->buf_start);
 
@@ -1604,7 +1604,7 @@ static void qcom_nandc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 static void qcom_nandc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
 				 int len)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
 	int real_len = min_t(size_t, len, nandc->buf_count - nandc->buf_start);
 
@@ -1616,7 +1616,7 @@ static void qcom_nandc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
 /* we support only one external chip for now */
 static void qcom_nandc_select_chip(struct mtd_info *mtd, int chipnr)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
 
 	if (chipnr <= 0)
@@ -1713,7 +1713,7 @@ static void qcom_nandc_select_chip(struct mtd_info *mtd, int chipnr)
 static int qcom_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
 				   struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct qcom_nand_host *host = to_qcom_nand_host(chip);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 
@@ -1735,7 +1735,7 @@ static int qcom_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
 static int qcom_nand_ooblayout_free(struct mtd_info *mtd, int section,
 				     struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct qcom_nand_host *host = to_qcom_nand_host(chip);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 
@@ -1756,7 +1756,7 @@ static int qcom_nand_ooblayout_free(struct mtd_info *mtd, int section,
 static int qcom_nand_host_setup(struct qcom_nand_host *host)
 {
 	struct nand_chip *chip = &host->chip;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
 	int cwperpage, bad_block_byte;
@@ -1988,7 +1988,7 @@ static int qcom_nand_host_init(struct qcom_nand_controller *nandc,
 			       struct device_node *dn)
 {
 	struct nand_chip *chip = &host->chip;
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	struct device *dev = nandc->dev;
 	int ret;
 
@@ -2152,7 +2152,7 @@ static int qcom_nandc_probe(struct platform_device *pdev)
 
 err_cs_init:
 	list_for_each_entry(host, &nandc->host_list, node)
-		nand_release(nand_to_mtd(&host->chip));
+		nand_release(nandchip_to_mtd(&host->chip));
 err_setup:
 	clk_disable_unprepare(nandc->aon_clk);
 err_aon_clk:
@@ -2169,7 +2169,7 @@ static int qcom_nandc_remove(struct platform_device *pdev)
 	struct qcom_nand_host *host;
 
 	list_for_each_entry(host, &nandc->host_list, node)
-		nand_release(nand_to_mtd(&host->chip));
+		nand_release(nandchip_to_mtd(&host->chip));
 
 	qcom_nandc_unalloc(nandc);
 
diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c
index fc9287a..6ac7b95 100644
--- a/drivers/mtd/nand/raw/r852.c
+++ b/drivers/mtd/nand/raw/r852.c
@@ -64,7 +64,7 @@ static inline void r852_write_reg_dword(struct r852_device *dev,
 /* returns pointer to our private structure */
 static inline struct r852_device *r852_get_dev(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	return nand_get_controller_data(chip);
 }
 
@@ -634,7 +634,7 @@ static void r852_update_media_status(struct r852_device *dev)
  */
 static int r852_register_nand_device(struct r852_device *dev)
 {
-	struct mtd_info *mtd = nand_to_mtd(dev->chip);
+	struct mtd_info *mtd = nandchip_to_mtd(dev->chip);
 
 	WARN_ON(dev->card_registred);
 
@@ -669,7 +669,7 @@ static int r852_register_nand_device(struct r852_device *dev)
 
 static void r852_unregister_nand_device(struct r852_device *dev)
 {
-	struct mtd_info *mtd = nand_to_mtd(dev->chip);
+	struct mtd_info *mtd = nandchip_to_mtd(dev->chip);
 
 	if (!dev->card_registred)
 		return;
@@ -1025,7 +1025,7 @@ static int r852_suspend(struct device *device)
 static int r852_resume(struct device *device)
 {
 	struct r852_device *dev = pci_get_drvdata(to_pci_dev(device));
-	struct mtd_info *mtd = nand_to_mtd(dev->chip);
+	struct mtd_info *mtd = nandchip_to_mtd(dev->chip);
 
 	r852_disable_irqs(dev);
 	r852_card_update_present(dev);
diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c
index 0b2314b..d6918b0 100644
--- a/drivers/mtd/nand/raw/s3c2410.c
+++ b/drivers/mtd/nand/raw/s3c2410.c
@@ -207,7 +207,7 @@ struct s3c24XX_nand_devtype_data {
 
 static struct s3c2410_nand_mtd *s3c2410_nand_mtd_toours(struct mtd_info *mtd)
 {
-	return container_of(mtd_to_nand(mtd), struct s3c2410_nand_mtd,
+	return container_of(mtd_to_nandchip(mtd), struct s3c2410_nand_mtd,
 			    chip);
 }
 
@@ -422,7 +422,7 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
 {
 	struct s3c2410_nand_info *info;
 	struct s3c2410_nand_mtd *nmtd;
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	unsigned long cur;
 
 	nmtd = nand_get_controller_data(this);
@@ -673,7 +673,7 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 
 static void s3c2410_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	readsb(this->IO_ADDR_R, buf, len);
 }
 
@@ -695,7 +695,7 @@ static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf,
 				   int len)
 {
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	writesb(this->IO_ADDR_W, buf, len);
 }
 
@@ -784,7 +784,7 @@ static int s3c24xx_nand_remove(struct platform_device *pdev)
 
 		for (mtdno = 0; mtdno < info->mtd_count; mtdno++, ptr++) {
 			pr_debug("releasing mtd %d (%p)\n", mtdno, ptr);
-			nand_release(nand_to_mtd(&ptr->chip));
+			nand_release(nandchip_to_mtd(&ptr->chip));
 		}
 	}
 
@@ -801,7 +801,7 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
 				      struct s3c2410_nand_set *set)
 {
 	if (set) {
-		struct mtd_info *mtdinfo = nand_to_mtd(&mtd->chip);
+		struct mtd_info *mtdinfo = nandchip_to_mtd(&mtd->chip);
 
 		mtdinfo->name = set->name;
 
@@ -984,7 +984,7 @@ static int s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
 		} else {
 			chip->ecc.size	    = 512;
 			chip->ecc.bytes	    = 3;
-			mtd_set_ooblayout(nand_to_mtd(chip),
+			mtd_set_ooblayout(nandchip_to_mtd(chip),
 					  &s3c2410_ooblayout_ops);
 		}
 
@@ -1157,7 +1157,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
 	nmtd = info->mtds;
 
 	for (setno = 0; setno < nr_sets; setno++, nmtd++) {
-		struct mtd_info *mtd = nand_to_mtd(&nmtd->chip);
+		struct mtd_info *mtd = nandchip_to_mtd(&nmtd->chip);
 
 		pr_debug("initialising set %d (%p, info %p)\n",
 			 setno, nmtd, info);
diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c
index 492705f..1525f15 100644
--- a/drivers/mtd/nand/raw/sh_flctl.c
+++ b/drivers/mtd/nand/raw/sh_flctl.c
@@ -45,7 +45,7 @@
 static int flctl_4secc_ooblayout_sp_ecc(struct mtd_info *mtd, int section,
 					struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (section)
 		return -ERANGE;
@@ -76,7 +76,7 @@ static int flctl_4secc_ooblayout_sp_free(struct mtd_info *mtd, int section,
 static int flctl_4secc_ooblayout_lp_ecc(struct mtd_info *mtd, int section,
 					struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (section >= chip->ecc.steps)
 		return -ERANGE;
@@ -90,7 +90,7 @@ static int flctl_4secc_ooblayout_lp_ecc(struct mtd_info *mtd, int section,
 static int flctl_4secc_ooblayout_lp_free(struct mtd_info *mtd, int section,
 					 struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (section >= chip->ecc.steps)
 		return -ERANGE;
@@ -1164,7 +1164,7 @@ static int flctl_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, flctl);
 	nand = &flctl->chip;
-	flctl_mtd = nand_to_mtd(nand);
+	flctl_mtd = nandchip_to_mtd(nand);
 	nand_set_flash_node(nand, pdev->dev.of_node);
 	flctl_mtd->dev.parent = &pdev->dev;
 	flctl->pdev = pdev;
@@ -1229,7 +1229,7 @@ static int flctl_remove(struct platform_device *pdev)
 	struct sh_flctl *flctl = platform_get_drvdata(pdev);
 
 	flctl_release_dma(flctl);
-	nand_release(nand_to_mtd(&flctl->chip));
+	nand_release(nandchip_to_mtd(&flctl->chip));
 	pm_runtime_disable(&pdev->dev);
 
 	return 0;
diff --git a/drivers/mtd/nand/raw/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c
index 737efe8..38c7fb3 100644
--- a/drivers/mtd/nand/raw/sharpsl.c
+++ b/drivers/mtd/nand/raw/sharpsl.c
@@ -36,7 +36,7 @@ struct sharpsl_nand {
 
 static inline struct sharpsl_nand *mtd_to_sharpsl(struct mtd_info *mtd)
 {
-	return container_of(mtd_to_nand(mtd), struct sharpsl_nand, chip);
+	return container_of(mtd_to_nandchip(mtd), struct sharpsl_nand, chip);
 }
 
 /* register offset */
@@ -68,7 +68,7 @@ static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd,
 				   unsigned int ctrl)
 {
 	struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd);
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (ctrl & NAND_CTRL_CHANGE) {
 		unsigned char bits = ctrl & 0x07;
@@ -146,7 +146,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
 	this = (struct nand_chip *)(&sharpsl->chip);
 
 	/* Link the private data with the MTD structure */
-	mtd = nand_to_mtd(this);
+	mtd = nandchip_to_mtd(this);
 	mtd->dev.parent = &pdev->dev;
 	mtd_set_ooblayout(mtd, data->ecc_layout);
 
@@ -210,7 +210,7 @@ static int sharpsl_nand_remove(struct platform_device *pdev)
 	struct sharpsl_nand *sharpsl = platform_get_drvdata(pdev);
 
 	/* Release resources, unregister device */
-	nand_release(nand_to_mtd(&sharpsl->chip));
+	nand_release(nandchip_to_mtd(&sharpsl->chip));
 
 	iounmap(sharpsl->io);
 
diff --git a/drivers/mtd/nand/raw/sm_common.c b/drivers/mtd/nand/raw/sm_common.c
index c378705..0e7e367 100644
--- a/drivers/mtd/nand/raw/sm_common.c
+++ b/drivers/mtd/nand/raw/sm_common.c
@@ -163,7 +163,7 @@ static int sm_block_markbad(struct mtd_info *mtd, loff_t ofs)
 
 int sm_register_device(struct mtd_info *mtd, int smartmedia)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	int ret;
 
 	chip->options |= NAND_SKIP_BBTSCAN;
diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c
index 575997d..c17a5f3 100644
--- a/drivers/mtd/nand/raw/socrates_nand.c
+++ b/drivers/mtd/nand/raw/socrates_nand.c
@@ -44,7 +44,7 @@ static void socrates_nand_write_buf(struct mtd_info *mtd,
 		const uint8_t *buf, int len)
 {
 	int i;
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct socrates_nand_host *host = nand_get_controller_data(this);
 
 	for (i = 0; i < len; i++) {
@@ -63,7 +63,7 @@ static void socrates_nand_write_buf(struct mtd_info *mtd,
 static void socrates_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
 	int i;
-	struct nand_chip *this = mtd_to_nand(mtd);
+	struct nand_chip *this = mtd_to_nandchip(mtd);
 	struct socrates_nand_host *host = nand_get_controller_data(this);
 	uint32_t val;
 
@@ -104,7 +104,7 @@ static uint16_t socrates_nand_read_word(struct mtd_info *mtd)
 static void socrates_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
 		unsigned int ctrl)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct socrates_nand_host *host = nand_get_controller_data(nand_chip);
 	uint32_t val;
 
@@ -129,7 +129,7 @@ static void socrates_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
  */
 static int socrates_nand_device_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
 	struct socrates_nand_host *host = nand_get_controller_data(nand_chip);
 
 	if (in_be32(host->io_base) & FPGA_NAND_BUSY)
@@ -159,7 +159,7 @@ static int socrates_nand_probe(struct platform_device *ofdev)
 	}
 
 	nand_chip = &host->nand_chip;
-	mtd = nand_to_mtd(nand_chip);
+	mtd = nandchip_to_mtd(nand_chip);
 	host->dev = &ofdev->dev;
 
 	/* link the private data structures */
@@ -208,7 +208,7 @@ static int socrates_nand_probe(struct platform_device *ofdev)
 static int socrates_nand_remove(struct platform_device *ofdev)
 {
 	struct socrates_nand_host *host = dev_get_drvdata(&ofdev->dev);
-	struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
+	struct mtd_info *mtd = nandchip_to_mtd(&host->nand_chip);
 
 	nand_release(mtd);
 
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 214a9c7..971978e 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -379,7 +379,7 @@ static int sunxi_nfc_dma_op_prepare(struct mtd_info *mtd, const void *buf,
 				    enum dma_data_direction ddir,
 				    struct scatterlist *sg)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
 	struct dma_async_tx_descriptor *dmad;
 	enum dma_transfer_direction tdir;
@@ -427,7 +427,7 @@ static void sunxi_nfc_dma_op_cleanup(struct mtd_info *mtd,
 				     enum dma_data_direction ddir,
 				     struct scatterlist *sg)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
 
 	dma_unmap_sg(nfc->dev, sg, 1, ddir);
@@ -437,7 +437,7 @@ static void sunxi_nfc_dma_op_cleanup(struct mtd_info *mtd,
 
 static int sunxi_nfc_dev_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
 	struct sunxi_nand_rb *rb;
@@ -468,7 +468,7 @@ static int sunxi_nfc_dev_ready(struct mtd_info *mtd)
 
 static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
 	struct sunxi_nand_chip_sel *sel;
@@ -513,7 +513,7 @@ static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip)
 
 static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
 	int ret;
@@ -552,7 +552,7 @@ static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 static void sunxi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
 				int len)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
 	int ret;
@@ -599,7 +599,7 @@ static uint8_t sunxi_nfc_read_byte(struct mtd_info *mtd)
 static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat,
 			       unsigned int ctrl)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
 	int ret;
@@ -756,7 +756,7 @@ static u16 sunxi_nfc_randomizer_state(struct mtd_info *mtd, int page, bool ecc)
 static void sunxi_nfc_randomizer_config(struct mtd_info *mtd,
 					int page, bool ecc)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
 	u32 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
 	u16 state;
@@ -772,7 +772,7 @@ static void sunxi_nfc_randomizer_config(struct mtd_info *mtd,
 
 static void sunxi_nfc_randomizer_enable(struct mtd_info *mtd)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
 
 	if (!(nand->options & NAND_NEED_SCRAMBLING))
@@ -784,7 +784,7 @@ static void sunxi_nfc_randomizer_enable(struct mtd_info *mtd)
 
 static void sunxi_nfc_randomizer_disable(struct mtd_info *mtd)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
 
 	if (!(nand->options & NAND_NEED_SCRAMBLING))
@@ -823,7 +823,7 @@ static void sunxi_nfc_randomizer_read_buf(struct mtd_info *mtd, uint8_t *buf,
 
 static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
 	struct sunxi_nand_hw_ecc *data = nand->ecc.priv;
 	u32 ecc_ctl;
@@ -842,7 +842,7 @@ static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd)
 
 static void sunxi_nfc_hw_ecc_disable(struct mtd_info *mtd)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
 
 	writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_ECC_EN,
@@ -865,7 +865,7 @@ static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf)
 static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct mtd_info *mtd, u8 *oob,
 						int step, bool bbm, int page)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
 
 	sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(step)),
@@ -880,7 +880,7 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct mtd_info *mtd,
 						const u8 *oob, int step,
 						bool bbm, int page)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
 	u8 user_data[4];
 
@@ -909,7 +909,7 @@ static void sunxi_nfc_hw_ecc_update_stats(struct mtd_info *mtd,
 static int sunxi_nfc_hw_ecc_correct(struct mtd_info *mtd, u8 *data, u8 *oob,
 				    int step, u32 status, bool *erased)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
 	struct nand_ecc_ctrl *ecc = &nand->ecc;
 	u32 tmp;
@@ -950,7 +950,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
 				       unsigned int *max_bitflips,
 				       bool bbm, bool oob_required, int page)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
 	struct nand_ecc_ctrl *ecc = &nand->ecc;
 	int raw_mode = 0;
@@ -1029,7 +1029,7 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd,
 					    u8 *oob, int *cur_off,
 					    bool randomize, int page)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct nand_ecc_ctrl *ecc = &nand->ecc;
 	int offset = ((ecc->bytes + 4) * ecc->steps);
 	int len = mtd->oobsize - offset;
@@ -1055,7 +1055,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf,
 					    int oob_required, int page,
 					    int nchunks)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	bool randomized = nand->options & NAND_NEED_SCRAMBLING;
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
 	struct nand_ecc_ctrl *ecc = &nand->ecc;
@@ -1181,7 +1181,7 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
 					int *cur_off, bool bbm,
 					int page)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
 	struct nand_ecc_ctrl *ecc = &nand->ecc;
 	int ret;
@@ -1219,7 +1219,7 @@ static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd,
 					     u8 *oob, int *cur_off,
 					     int page)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct nand_ecc_ctrl *ecc = &nand->ecc;
 	int offset = ((ecc->bytes + 4) * ecc->steps);
 	int len = mtd->oobsize - offset;
@@ -1410,7 +1410,7 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct mtd_info *mtd,
 					   int oob_required,
 					   int page)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
 	struct nand_ecc_ctrl *ecc = &nand->ecc;
 	struct scatterlist sg;
@@ -1596,7 +1596,7 @@ static int sunxi_nfc_setup_data_interface(struct mtd_info *mtd,
 					const struct nand_data_interface *conf,
 					bool check_only)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nand_chip *chip = to_sunxi_nand(nand);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(chip->nand.controller);
 	const struct nand_sdr_timings *timings;
@@ -1746,7 +1746,7 @@ static int sunxi_nfc_setup_data_interface(struct mtd_info *mtd,
 static int sunxi_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
 				    struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct nand_ecc_ctrl *ecc = &nand->ecc;
 
 	if (section >= ecc->steps)
@@ -1761,7 +1761,7 @@ static int sunxi_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
 static int sunxi_nand_ooblayout_free(struct mtd_info *mtd, int section,
 				     struct mtd_oob_region *oobregion)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct nand_ecc_ctrl *ecc = &nand->ecc;
 
 	if (section > ecc->steps)
@@ -1799,7 +1799,7 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
 					      struct device_node *np)
 {
 	static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
 	struct sunxi_nand_hw_ecc *data;
@@ -1898,7 +1898,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
 				       struct nand_ecc_ctrl *ecc,
 				       struct device_node *np)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
 	int ret;
@@ -1962,7 +1962,7 @@ static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc)
 static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc,
 			       struct device_node *np)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct nand_chip *nand = mtd_to_nandchip(mtd);
 	int ret;
 
 	if (!ecc->size) {
@@ -2088,7 +2088,7 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
 	nand->read_byte = sunxi_nfc_read_byte;
 	nand->setup_data_interface = sunxi_nfc_setup_data_interface;
 
-	mtd = nand_to_mtd(nand);
+	mtd = nandchip_to_mtd(nand);
 	mtd->dev.parent = dev;
 
 	ret = nand_scan_ident(mtd, nsels, NULL);
@@ -2157,7 +2157,7 @@ static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc)
 	while (!list_empty(&nfc->chips)) {
 		chip = list_first_entry(&nfc->chips, struct sunxi_nand_chip,
 					node);
-		nand_release(nand_to_mtd(&chip->nand));
+		nand_release(nandchip_to_mtd(&chip->nand));
 		sunxi_nand_ecc_cleanup(&chip->nand.ecc);
 		list_del(&chip->node);
 	}
diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c
index 906fe0f..8097e88 100644
--- a/drivers/mtd/nand/raw/tango_nand.c
+++ b/drivers/mtd/nand/raw/tango_nand.c
@@ -118,7 +118,7 @@ struct tango_chip {
 
 static void tango_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
 {
-	struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd));
+	struct tango_chip *tchip = to_tango_chip(mtd_to_nandchip(mtd));
 
 	if (ctrl & NAND_CLE)
 		writeb_relaxed(dat, tchip->base + PBUS_CMD);
@@ -129,7 +129,7 @@ static void tango_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
 
 static int tango_dev_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct tango_nfc *nfc = to_tango_nfc(chip->controller);
 
 	return readl_relaxed(nfc->pbus_base + PBUS_CS_CTRL) & PBUS_IORDY;
@@ -137,28 +137,28 @@ static int tango_dev_ready(struct mtd_info *mtd)
 
 static u8 tango_read_byte(struct mtd_info *mtd)
 {
-	struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd));
+	struct tango_chip *tchip = to_tango_chip(mtd_to_nandchip(mtd));
 
 	return readb_relaxed(tchip->base + PBUS_DATA);
 }
 
 static void tango_read_buf(struct mtd_info *mtd, u8 *buf, int len)
 {
-	struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd));
+	struct tango_chip *tchip = to_tango_chip(mtd_to_nandchip(mtd));
 
 	ioread8_rep(tchip->base + PBUS_DATA, buf, len);
 }
 
 static void tango_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
 {
-	struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd));
+	struct tango_chip *tchip = to_tango_chip(mtd_to_nandchip(mtd));
 
 	iowrite8_rep(tchip->base + PBUS_DATA, buf, len);
 }
 
 static void tango_select_chip(struct mtd_info *mtd, int idx)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct tango_nfc *nfc = to_tango_nfc(chip->controller);
 	struct tango_chip *tchip = to_tango_chip(chip);
 
@@ -179,7 +179,7 @@ static void tango_select_chip(struct mtd_info *mtd, int idx)
  */
 static int check_erased_page(struct nand_chip *chip, u8 *buf)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	u8 *meta = chip->oob_poi + BBM_SIZE;
 	u8 *ecc = chip->oob_poi + BBM_SIZE + METADATA_SIZE;
 	const int ecc_size = chip->ecc.bytes;
@@ -311,7 +311,7 @@ static int tango_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 
 static void aux_read(struct nand_chip *chip, u8 **buf, int len, int *pos)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 
 	*pos += len;
 
@@ -326,7 +326,7 @@ static void aux_read(struct nand_chip *chip, u8 **buf, int len, int *pos)
 
 static void aux_write(struct nand_chip *chip, const u8 **buf, int len, int *pos)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 
 	*pos += len;
 
@@ -360,7 +360,7 @@ static void aux_write(struct nand_chip *chip, const u8 **buf, int len, int *pos)
  */
 static void raw_read(struct nand_chip *chip, u8 *buf, u8 *oob)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	u8 *oob_orig = oob;
 	const int page_size = mtd->writesize;
 	const int ecc_size = chip->ecc.bytes;
@@ -387,7 +387,7 @@ static void raw_read(struct nand_chip *chip, u8 *buf, u8 *oob)
 
 static void raw_write(struct nand_chip *chip, const u8 *buf, const u8 *oob)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
 	const u8 *oob_orig = oob;
 	const int page_size = mtd->writesize;
 	const int ecc_size = chip->ecc.bytes;
@@ -449,7 +449,7 @@ static int tango_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
 
 static int oob_ecc(struct mtd_info *mtd, int idx, struct mtd_oob_region *res)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 
 	if (idx >= ecc->steps)
@@ -481,7 +481,7 @@ static int tango_set_timings(struct mtd_info *mtd,
 			     bool check_only)
 {
 	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(conf);
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct tango_nfc *nfc = to_tango_nfc(chip->controller);
 	struct tango_chip *tchip = to_tango_chip(chip);
 	u32 Trdy, Textw, Twc, Twpw, Tacc, Thold, Trpw, Textr;
@@ -539,7 +539,7 @@ static int chip_init(struct device *dev, struct device_node *np)
 
 	chip = &tchip->nand_chip;
 	ecc = &chip->ecc;
-	mtd = nand_to_mtd(chip);
+	mtd = nandchip_to_mtd(chip);
 
 	chip->read_byte = tango_read_byte;
 	chip->write_buf = tango_write_buf;
@@ -601,7 +601,7 @@ static int tango_nand_remove(struct platform_device *pdev)
 
 	for (cs = 0; cs < MAX_CS; ++cs) {
 		if (nfc->chips[cs])
-			nand_release(nand_to_mtd(&nfc->chips[cs]->nand_chip));
+			nand_release(nandchip_to_mtd(&nfc->chips[cs]->nand_chip));
 	}
 
 	return 0;
diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c
index c9dd682..5b1bb65 100644
--- a/drivers/mtd/nand/raw/tmio_nand.c
+++ b/drivers/mtd/nand/raw/tmio_nand.c
@@ -120,7 +120,7 @@ struct tmio_nand {
 
 static inline struct tmio_nand *mtd_to_tmio(struct mtd_info *mtd)
 {
-	return container_of(mtd_to_nand(mtd), struct tmio_nand, chip);
+	return container_of(mtd_to_nandchip(mtd), struct tmio_nand, chip);
 }
 
 
@@ -130,7 +130,7 @@ static void tmio_nand_hwcontrol(struct mtd_info *mtd, int cmd,
 				   unsigned int ctrl)
 {
 	struct tmio_nand *tmio = mtd_to_tmio(mtd);
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
 	if (ctrl & NAND_CTRL_CHANGE) {
 		u8 mode;
@@ -381,7 +381,7 @@ static int tmio_probe(struct platform_device *dev)
 
 	platform_set_drvdata(dev, tmio);
 	nand_chip = &tmio->chip;
-	mtd = nand_to_mtd(nand_chip);
+	mtd = nandchip_to_mtd(nand_chip);
 	mtd->name = "tmio-nand";
 	mtd->dev.parent = &dev->dev;
 
@@ -457,7 +457,7 @@ static int tmio_remove(struct platform_device *dev)
 {
 	struct tmio_nand *tmio = platform_get_drvdata(dev);
 
-	nand_release(nand_to_mtd(&tmio->chip));
+	nand_release(nandchip_to_mtd(&tmio->chip));
 	tmio_hw_stop(dev, tmio);
 	return 0;
 }
diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c
index b567d21..edb7cd0 100644
--- a/drivers/mtd/nand/raw/txx9ndfmc.c
+++ b/drivers/mtd/nand/raw/txx9ndfmc.c
@@ -78,7 +78,7 @@ struct txx9ndfmc_drvdata {
 
 static struct platform_device *mtd_to_platdev(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct txx9ndfmc_priv *txx9_priv = nand_get_controller_data(chip);
 	return txx9_priv->dev;
 }
@@ -134,7 +134,7 @@ static void txx9ndfmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 static void txx9ndfmc_cmd_ctrl(struct mtd_info *mtd, int cmd,
 			       unsigned int ctrl)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct txx9ndfmc_priv *txx9_priv = nand_get_controller_data(chip);
 	struct platform_device *dev = txx9_priv->dev;
 	struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);
@@ -174,7 +174,7 @@ static int txx9ndfmc_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
 				   uint8_t *ecc_code)
 {
 	struct platform_device *dev = mtd_to_platdev(mtd);
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	int eccbytes;
 	u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR);
 
@@ -194,7 +194,7 @@ static int txx9ndfmc_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
 static int txx9ndfmc_correct_data(struct mtd_info *mtd, unsigned char *buf,
 		unsigned char *read_ecc, unsigned char *calc_ecc)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	int eccsize;
 	int corrected = 0;
 	int stat;
@@ -256,7 +256,7 @@ static void txx9ndfmc_initialize(struct platform_device *dev)
 
 static int txx9ndfmc_nand_scan(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	int ret;
 
 	ret = nand_scan_ident(mtd, 1, NULL);
@@ -320,7 +320,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
 		if (!txx9_priv)
 			continue;
 		chip = &txx9_priv->chip;
-		mtd = nand_to_mtd(chip);
+		mtd = nandchip_to_mtd(chip);
 		mtd->dev.parent = &dev->dev;
 
 		chip->read_byte = txx9ndfmc_read_byte;
@@ -387,7 +387,7 @@ static int __exit txx9ndfmc_remove(struct platform_device *dev)
 
 		if (!mtd)
 			continue;
-		chip = mtd_to_nand(mtd);
+		chip = mtd_to_nandchip(mtd);
 		txx9_priv = nand_get_controller_data(chip);
 
 		nand_release(mtd);
diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c
index 1bc4b08..0baf986 100644
--- a/drivers/mtd/nand/raw/vf610_nfc.c
+++ b/drivers/mtd/nand/raw/vf610_nfc.c
@@ -171,7 +171,7 @@ struct vf610_nfc {
 
 static inline struct vf610_nfc *mtd_to_nfc(struct mtd_info *mtd)
 {
-	return container_of(mtd_to_nand(mtd), struct vf610_nfc, chip);
+	return container_of(mtd_to_nandchip(mtd), struct vf610_nfc, chip);
 }
 
 static inline u32 vf610_nfc_read(struct vf610_nfc *nfc, uint reg)
@@ -648,7 +648,7 @@ static int vf610_nfc_probe(struct platform_device *pdev)
 
 	nfc->dev = &pdev->dev;
 	chip = &nfc->chip;
-	mtd = nand_to_mtd(chip);
+	mtd = nandchip_to_mtd(chip);
 
 	mtd->owner = THIS_MODULE;
 	mtd->dev.parent = nfc->dev;
diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c
index 9926b4e..c3d4b0f 100644
--- a/drivers/mtd/nand/raw/xway_nand.c
+++ b/drivers/mtd/nand/raw/xway_nand.c
@@ -71,7 +71,7 @@ struct xway_nand_data {
 
 static u8 xway_readb(struct mtd_info *mtd, int op)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct xway_nand_data *data = nand_get_controller_data(chip);
 
 	return readb(data->nandaddr + op);
@@ -79,7 +79,7 @@ static u8 xway_readb(struct mtd_info *mtd, int op)
 
 static void xway_writeb(struct mtd_info *mtd, int op, u8 value)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct xway_nand_data *data = nand_get_controller_data(chip);
 
 	writeb(value, data->nandaddr + op);
@@ -87,7 +87,7 @@ static void xway_writeb(struct mtd_info *mtd, int op, u8 value)
 
 static void xway_select_chip(struct mtd_info *mtd, int select)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct xway_nand_data *data = nand_get_controller_data(chip);
 
 	switch (select) {
@@ -170,7 +170,7 @@ static int xway_nand_probe(struct platform_device *pdev)
 		return PTR_ERR(data->nandaddr);
 
 	nand_set_flash_node(&data->chip, pdev->dev.of_node);
-	mtd = nand_to_mtd(&data->chip);
+	mtd = nandchip_to_mtd(&data->chip);
 	mtd->dev.parent = &pdev->dev;
 
 	data->chip.cmd_ctrl = xway_cmd_ctrl;
@@ -223,7 +223,7 @@ static int xway_nand_remove(struct platform_device *pdev)
 {
 	struct xway_nand_data *data = platform_get_drvdata(pdev);
 
-	nand_release(nand_to_mtd(&data->chip));
+	nand_release(nandchip_to_mtd(&data->chip));
 
 	return 0;
 }
diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c
index f7f6edf..df5671a 100644
--- a/drivers/staging/mt29f_spinand/mt29f_spinand.c
+++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c
@@ -31,7 +31,7 @@
 
 static inline struct spinand_state *mtd_to_state(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct spinand_info *info = nand_get_controller_data(chip);
 	struct spinand_state *state = info->priv;
 
@@ -756,7 +756,7 @@ static void spinand_reset(struct spi_device *spi_nand)
 static void spinand_cmdfunc(struct mtd_info *mtd, unsigned int command,
 			    int column, int page)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
 	struct spinand_info *info = nand_get_controller_data(chip);
 	struct spinand_state *state = info->priv;
 
@@ -916,7 +916,7 @@ static int spinand_probe(struct spi_device *spi_nand)
 	chip->options	|= NAND_CACHEPRG;
 	chip->select_chip = spinand_select_chip;
 
-	mtd = nand_to_mtd(chip);
+	mtd = nandchip_to_mtd(chip);
 
 	dev_set_drvdata(&spi_nand->dev, mtd);
 
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index fc6ed95..aa43ec4 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -938,12 +938,12 @@ static inline struct device_node *nand_get_flash_node(struct nand_chip *chip)
 	return mtd_get_of_node(&chip->mtd);
 }
 
-static inline struct nand_chip *mtd_to_nand(struct mtd_info *mtd)
+static inline struct nand_chip *mtd_to_nandchip(struct mtd_info *mtd)
 {
 	return container_of(mtd, struct nand_chip, mtd);
 }
 
-static inline struct mtd_info *nand_to_mtd(struct nand_chip *chip)
+static inline struct mtd_info *nandchip_to_mtd(struct nand_chip *chip)
 {
 	return &chip->mtd;
 }
diff --git a/include/linux/mtd/sh_flctl.h b/include/linux/mtd/sh_flctl.h
index c759d40..0c1a4a9 100644
--- a/include/linux/mtd/sh_flctl.h
+++ b/include/linux/mtd/sh_flctl.h
@@ -186,7 +186,7 @@ struct sh_flctl_platform_data {
 
 static inline struct sh_flctl *mtd_to_flctl(struct mtd_info *mtdinfo)
 {
-	return container_of(mtd_to_nand(mtdinfo), struct sh_flctl, chip);
+	return container_of(mtd_to_nandchip(mtdinfo), struct sh_flctl, chip);
 }
 
 #endif	/* __SH_FLCTL_H__ */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 05/15] mtd: nand: raw: create struct rawnand_device
  2017-05-24  7:06 [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Peter Pan
                   ` (3 preceding siblings ...)
  2017-05-24  7:07 ` [PATCH v6 04/15] mtd: nand: raw: prefix conflicting names with nandcchip instead of nand Peter Pan
@ 2017-05-24  7:07 ` Peter Pan
  2017-05-29 21:05   ` Boris Brezillon
  2017-05-24  7:07 ` [PATCH v6 06/15] mtd: nand: raw: make BBT code more generic Peter Pan
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 65+ messages in thread
From: Peter Pan @ 2017-05-24  7:07 UTC (permalink / raw)
  To: boris.brezillon, richard, computersforpeace, arnaud.mouiche,
	thomas.petazzoni, marex, cyrille.pitchen, linux-mtd
  Cc: peterpandong, peterpansjtu, linshunquan1

From: Boris Brezillon <boris.brezillon@free-electrons.com>

Create the rawnand_device struct inheriting from nand_device and make
nand_chip inherit from this struct.

The rawnand_device object should be used for the new
rawnand-device/rawnand-controller model, and fields inside nand_chip
should progressively move to the future rawnand_controller or the existing
rawnand_device struct.

In the meantime, we make sure nand_device fields are properly initialized
by converting information stored in mtd_info and nand_chip into the
nand_memory_organization format.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Peter Pan <peterpandong@micron.com>
---
 drivers/mtd/nand/raw/nand_base.c | 40 ++++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/rawnand.h      | 26 ++++++++++++++++++++------
 2 files changed, 60 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index a113cfb..8f8df15 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -3957,6 +3957,43 @@ static bool find_full_id_nand(struct nand_chip *chip,
 	return false;
 }
 
+static int rawnand_erase(struct nand_device *nand, struct erase_info *einfo)
+{
+	struct mtd_info *mtd = nand_to_mtd(nand);
+
+	return nand_erase_nand(mtd, einfo, 1);
+}
+
+static int rawnand_markbad(struct nand_device *nand, int block)
+{
+	struct mtd_info *mtd = nand_to_mtd(nand);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
+	loff_t offs = nand_eraseblock_to_offs(nand, block);
+
+	return chip->block_markbad(mtd, offs);
+}
+
+static const struct nand_ops rawnand_ops = {
+	.erase = rawnand_erase,
+	.markbad = rawnand_markbad,
+};
+
+static void nandc_fill_nandd(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nandchip_to_mtd(chip);
+	struct nand_device *nand = mtd_to_nand(mtd);
+	struct nand_memory_organization *memorg = &nand->memorg;
+
+	memorg->pagesize = mtd->writesize;
+	memorg->oobsize = mtd->oobsize;
+	memorg->eraseblocksize = mtd->erasesize;
+	memorg->ndies = chip->numchips;
+	memorg->diesize = chip->chipsize;
+	/* TODO: fill ->planesize and ->nplanes */
+
+	nand->ops = &rawnand_ops;
+}
+
 /*
  * Manufacturer detection. Only used when the NAND is not ONFI or JEDEC
  * compliant and does not have a full-id or legacy-id entry in the nand_ids
@@ -4409,6 +4446,9 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
 	chip->numchips = i;
 	mtd->size = i * chip->chipsize;
 
+	/* Fill nand_device info */
+	nandc_fill_nandd(chip);
+
 	return 0;
 }
 EXPORT_SYMBOL(nand_scan_ident);
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index aa43ec4..750fac2 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -20,6 +20,7 @@
 #include <linux/spinlock.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/flashchip.h>
+#include <linux/mtd/nand.h>
 #include <linux/mtd/bbm.h>
 
 struct mtd_info;
@@ -727,8 +728,21 @@ struct nand_manufacturer_ops {
 };
 
 /**
+ * struct rawnand_device - raw NAND device structure
+ * @base: NAND device instance (inheritance)
+ *
+ * This structure describes a raw NAND device and should progressively
+ * replace the nand_chip struct.
+ *
+ * Note: do not blindly move nand_chip fields into rawnand_device.
+ */
+struct rawnand_device {
+	struct nand_device base;
+};
+
+/**
  * struct nand_chip - NAND Private Flash Chip Data
- * @mtd:		MTD device registered to the MTD framework
+ * @base:		raw NAND device instance (inheritance)
  * @IO_ADDR_R:		[BOARDSPECIFIC] address to read the 8 I/O lines of the
  *			flash device
  * @IO_ADDR_W:		[BOARDSPECIFIC] address to write the 8 I/O lines of the
@@ -834,7 +848,7 @@ struct nand_manufacturer_ops {
  */
 
 struct nand_chip {
-	struct mtd_info mtd;
+	struct rawnand_device base;
 	void __iomem *IO_ADDR_R;
 	void __iomem *IO_ADDR_W;
 
@@ -930,22 +944,22 @@ struct nand_chip {
 static inline void nand_set_flash_node(struct nand_chip *chip,
 				       struct device_node *np)
 {
-	mtd_set_of_node(&chip->mtd, np);
+	nand_set_of_node(&chip->base.base, np);
 }
 
 static inline struct device_node *nand_get_flash_node(struct nand_chip *chip)
 {
-	return mtd_get_of_node(&chip->mtd);
+	return nand_get_of_node(&chip->base.base);
 }
 
 static inline struct nand_chip *mtd_to_nandchip(struct mtd_info *mtd)
 {
-	return container_of(mtd, struct nand_chip, mtd);
+	return container_of(mtd_to_nand(mtd), struct nand_chip, base.base);
 }
 
 static inline struct mtd_info *nandchip_to_mtd(struct nand_chip *chip)
 {
-	return &chip->mtd;
+	return nand_to_mtd(&chip->base.base);
 }
 
 static inline void *nand_get_controller_data(struct nand_chip *chip)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 06/15] mtd: nand: raw: make BBT code more generic
  2017-05-24  7:06 [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Peter Pan
                   ` (4 preceding siblings ...)
  2017-05-24  7:07 ` [PATCH v6 05/15] mtd: nand: raw: create struct rawnand_device Peter Pan
@ 2017-05-24  7:07 ` Peter Pan
  2017-05-24  7:07 ` [PATCH v6 07/15] mtd: nand: move BBT code to drivers/mtd/nand/ Peter Pan
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 65+ messages in thread
From: Peter Pan @ 2017-05-24  7:07 UTC (permalink / raw)
  To: boris.brezillon, richard, computersforpeace, arnaud.mouiche,
	thomas.petazzoni, marex, cyrille.pitchen, linux-mtd
  Cc: peterpandong, peterpansjtu, linshunquan1

From: Boris Brezillon <boris.brezillon@free-electrons.com>

BBT support is currently tightly tied to raw NAND, though this is the kind
of code we could share across all NAND based devices, no matter what
physical interface is to communicate with the NAND chip.

Make BBT code interface agnostic by replacing all occurrence of
struct nand_chip by struct nand_device, and move functions that are
specific to raw NANDs to drivers/mtd/nand/rawnand/nand_base.c.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Peter Pan <peterpandong@micron.com>
---
 drivers/mtd/nand/raw/docg4.c     |   7 +-
 drivers/mtd/nand/raw/nand_base.c |  92 +++++-
 drivers/mtd/nand/raw/nand_bbt.c  | 683 +++++++++++++++++++--------------------
 include/linux/mtd/nand.h         |  23 ++
 include/linux/mtd/rawnand.h      |   6 -
 5 files changed, 443 insertions(+), 368 deletions(-)

diff --git a/drivers/mtd/nand/raw/docg4.c b/drivers/mtd/nand/raw/docg4.c
index c4a4089..013cb99 100644
--- a/drivers/mtd/nand/raw/docg4.c
+++ b/drivers/mtd/nand/raw/docg4.c
@@ -1059,7 +1059,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd)
 	 * operation after device power-up.  The above read ensures it never is.
 	 * Ugly, I know.
 	 */
-	if (nand->bbt == NULL)  /* no memory-based bbt */
+	if (!nand_bbt_is_initialized(mtd_to_nand(mtd)))
 		goto exit;
 
 	if (mtd->ecc_stats.failed > eccfailed_stats) {
@@ -1086,8 +1086,9 @@ static int __init read_factory_bbt(struct mtd_info *mtd)
 		unsigned long bits = ~buf[i];
 		for_each_set_bit(bitnum, &bits, 8) {
 			int badblock = block + 7 - bitnum;
-			nand->bbt[badblock / 4] |=
-				0x03 << ((badblock % 4) * 2);
+
+			nand_bbt_update_entry(mtd_to_nand(mtd), badblock,
+					      NAND_BBT_BLOCK_FACTORY_BAD);
 			mtd->ecc_stats.badblocks++;
 			dev_notice(doc->dev, "factory-marked bad block: %d\n",
 				   badblock);
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 8f8df15..8581c89 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -512,6 +512,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
 {
 	struct nand_chip *chip = mtd_to_nandchip(mtd);
+	struct nand_device *nand = mtd_to_nand(mtd);
 	int res, ret = 0;
 
 	if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) {
@@ -531,8 +532,8 @@ static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
 	}
 
 	/* Mark block bad in BBT */
-	if (chip->bbt) {
-		res = nand_markbad_bbt(mtd, ofs);
+	if (nand_bbt_is_initialized(nand)) {
+		res = nand_markbad_bbt(nand, ofs);
 		if (!ret)
 			ret = res;
 	}
@@ -572,12 +573,12 @@ static int nand_check_wp(struct mtd_info *mtd)
  */
 static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs)
 {
-	struct nand_chip *chip = mtd_to_nandchip(mtd);
+	struct nand_device *nand = mtd_to_nand(mtd);
 
-	if (!chip->bbt)
+	if (!nand_bbt_is_initialized(nand))
 		return 0;
 	/* Return info from the table */
-	return nand_isreserved_bbt(mtd, ofs);
+	return nand_isreserved_bbt(nand, ofs);
 }
 
 /**
@@ -591,13 +592,14 @@ static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs)
  */
 static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int allowbbt)
 {
+	struct nand_device *nand = mtd_to_nand(mtd);
 	struct nand_chip *chip = mtd_to_nandchip(mtd);
 
-	if (!chip->bbt)
+	if (!nand_bbt_is_initialized(nand))
 		return chip->block_bad(mtd, ofs);
 
 	/* Return info from the table */
-	return nand_isbad_bbt(mtd, ofs, allowbbt);
+	return nand_isbad_bbt(nand, ofs, allowbbt);
 }
 
 /**
@@ -3457,6 +3459,75 @@ static void nand_shutdown(struct mtd_info *mtd)
 	nand_get_device(mtd, FL_PM_SUSPENDED);
 }
 
+/*
+ * Define some generic bad / good block scan pattern which are used
+ * while scanning a device for factory marked good / bad blocks.
+ */
+static u8 scan_ff_pattern[] = { 0xff, 0xff };
+
+#define BADBLOCK_SCAN_MASK (~NAND_BBT_NO_OOB)
+
+/**
+ * nand_create_badblock_pattern - [INTERN] Creates a BBT descriptor structure
+ * @this: NAND chip to create descriptor for
+ *
+ * This function allocates and initializes a nand_bbt_descr for BBM detection
+ * based on the properties of @this. The new descriptor is stored in
+ * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when
+ * passed to this function.
+ */
+static int nand_create_badblock_pattern(struct nand_chip *chip)
+{
+	struct nand_device *this = &chip->base.base;
+	struct nand_bbt_descr *bd;
+
+	if (this->bbt.bbp) {
+		pr_warn("Bad block pattern already allocated; not replacing\n");
+		return -EINVAL;
+	}
+
+	bd = kzalloc(sizeof(*bd), GFP_KERNEL);
+	if (!bd)
+		return -ENOMEM;
+
+	bd->options = this->bbt.options & BADBLOCK_SCAN_MASK;
+	bd->offs = chip->badblockpos;
+	bd->len = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1;
+	bd->pattern = scan_ff_pattern;
+	bd->options |= NAND_BBT_DYNAMICSTRUCT;
+	this->bbt.bbp = bd;
+
+	return 0;
+}
+
+/**
+ * nand_default_bbt - Select a default bad block table for the device
+ * @mtd: MTD device structure
+ *
+ * This function selects the default bad block table support for the device and
+ * calls the nand_scan_bbt function.
+ */
+static int nand_default_bbt(struct mtd_info *mtd)
+{
+	struct nand_device *this = mtd_to_nand(mtd);
+	struct nand_chip *chip = mtd_to_nandchip(mtd);
+	int ret;
+
+	/* Initialize BBT config from nand_chip info */
+	this->bbt.options = chip->bbt_options;
+	this->bbt.td = chip->bbt_td;
+	this->bbt.md = chip->bbt_md;
+	this->bbt.bbp = chip->badblock_pattern;
+
+	if (!this->bbt.bbp) {
+		ret = nand_create_badblock_pattern(chip);
+		if (ret)
+			return ret;
+	}
+
+	return nand_scan_bbt(this);
+}
+
 /* Set default functions */
 static void nand_set_defaults(struct nand_chip *chip)
 {
@@ -4950,14 +5021,17 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
  */
 void nand_cleanup(struct nand_chip *chip)
 {
+	struct nand_device *nand = &chip->base.base;
+
 	if (chip->ecc.mode == NAND_ECC_SOFT &&
 	    chip->ecc.algo == NAND_ECC_BCH)
 		nand_bch_free((struct nand_bch_control *)chip->ecc.priv);
 
 	nand_release_data_interface(chip);
 
-	/* Free bad block table memory */
-	kfree(chip->bbt);
+	if (nand_bbt_is_initialized(nand))
+		nand_release_bbt(nand);
+
 	if (!(chip->options & NAND_OWN_BUFFERS) && chip->buffers) {
 		kfree(chip->buffers->databuf);
 		kfree(chip->buffers->ecccode);
diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
index 396b248..26f5c3f 100644
--- a/drivers/mtd/nand/raw/nand_bbt.c
+++ b/drivers/mtd/nand/raw/nand_bbt.c
@@ -61,35 +61,28 @@
 #include <linux/types.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/bbm.h>
-#include <linux/mtd/rawnand.h>
+#include <linux/mtd/nand.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
 #include <linux/export.h>
 #include <linux/string.h>
 
-#define BBT_BLOCK_GOOD		0x00
-#define BBT_BLOCK_WORN		0x01
-#define BBT_BLOCK_RESERVED	0x02
-#define BBT_BLOCK_FACTORY_BAD	0x03
-
 #define BBT_ENTRY_MASK		0x03
 #define BBT_ENTRY_SHIFT		2
 
-static int nand_update_bbt(struct mtd_info *mtd, loff_t offs);
-
-static inline uint8_t bbt_get_entry(struct nand_chip *chip, int block)
+static inline u8 bbt_get_entry(struct nand_device *chip, int block)
 {
-	uint8_t entry = chip->bbt[block >> BBT_ENTRY_SHIFT];
+	u8 entry = chip->bbt.bbt[block >> BBT_ENTRY_SHIFT];
 	entry >>= (block & BBT_ENTRY_MASK) * 2;
 	return entry & BBT_ENTRY_MASK;
 }
 
-static inline void bbt_mark_entry(struct nand_chip *chip, int block,
-		uint8_t mark)
+static inline void bbt_mark_entry(struct nand_device *chip, int block,
+				  u8 mark)
 {
 	uint8_t msk = (mark & BBT_ENTRY_MASK) << ((block & BBT_ENTRY_MASK) * 2);
-	chip->bbt[block >> BBT_ENTRY_SHIFT] |= msk;
+	chip->bbt.bbt[block >> BBT_ENTRY_SHIFT] |= msk;
 }
 
 static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td)
@@ -100,6 +93,23 @@ static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td)
 }
 
 /**
+ * nand_bbt_update_entry - Update an entry in the in-memory bad block table
+ * @this: NAND device
+ * @eraseblock: eraseblock entry to update
+ * @status: new status for this eraseblock
+ *
+ * Update the eraseblock status in the in-memory BBT.
+ * This function should not be used unless your controller wants to manually
+ * initialize the BBT.
+ */
+void nand_bbt_update_entry(struct nand_device *this, int eraseblock,
+			   enum nand_bbt_block_status status)
+{
+	bbt_mark_entry(this, eraseblock, status);
+}
+EXPORT_SYMBOL_GPL(nand_bbt_update_entry);
+
+/**
  * check_pattern - [GENERIC] check if a pattern is in the buffer
  * @buf: the buffer to search
  * @len: the length of buffer to search
@@ -159,7 +169,7 @@ static u32 add_marker_len(struct nand_bbt_descr *td)
 
 /**
  * read_bbt - [GENERIC] Read the bad block table starting from page
- * @mtd: MTD device structure
+ * @this: NAND device
  * @buf: temporary buffer
  * @page: the starting page
  * @num: the number of bbt descriptors to read
@@ -168,11 +178,11 @@ static u32 add_marker_len(struct nand_bbt_descr *td)
  *
  * Read the bad block table starting from page.
  */
-static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
-		struct nand_bbt_descr *td, int offs)
+static int read_bbt(struct nand_device *this, uint8_t *buf, int page, int num,
+		    struct nand_bbt_descr *td, int offs)
 {
+	struct mtd_info *mtd = nand_to_mtd(this);
 	int res, ret = 0, i, j, act = 0;
-	struct nand_chip *this = mtd_to_nandchip(mtd);
 	size_t retlen, len, totlen;
 	loff_t from;
 	int bits = td->options & NAND_BBT_NRBITS_MSK;
@@ -182,10 +192,10 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 
 	totlen = (num * bits) >> 3;
 	marker_len = add_marker_len(td);
-	from = ((loff_t)page) << this->page_shift;
+	from = nand_page_to_offs(this, page);
 
 	while (totlen) {
-		len = min(totlen, (size_t)(1 << this->bbt_erase_shift));
+		len = min(totlen, nand_eraseblock_size(this));
 		if (marker_len) {
 			/*
 			 * In case the BBT marker is not in the OOB area it
@@ -199,11 +209,11 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 		if (res < 0) {
 			if (mtd_is_eccerr(res)) {
 				pr_info("nand_bbt: ECC error in BBT at 0x%012llx\n",
-					from & ~mtd->writesize);
+					from & ~nand_page_size(this));
 				return res;
 			} else if (mtd_is_bitflip(res)) {
 				pr_info("nand_bbt: corrected error in BBT at 0x%012llx\n",
-					from & ~mtd->writesize);
+					from & ~nand_page_size(this));
 				ret = res;
 			} else {
 				pr_info("nand_bbt: error reading BBT\n");
@@ -220,10 +230,10 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 					continue;
 				if (reserved_block_code && (tmp == reserved_block_code)) {
 					pr_info("nand_read_bbt: reserved block at 0x%012llx\n",
-						 (loff_t)(offs + act) <<
-						 this->bbt_erase_shift);
+						nand_eraseblock_to_offs(this,
+								offs + act));
 					bbt_mark_entry(this, offs + act,
-							BBT_BLOCK_RESERVED);
+						NAND_BBT_BLOCK_RESERVED);
 					mtd->ecc_stats.bbtblocks++;
 					continue;
 				}
@@ -232,15 +242,15 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 				 * move this message to pr_debug.
 				 */
 				pr_info("nand_read_bbt: bad block at 0x%012llx\n",
-					 (loff_t)(offs + act) <<
-					 this->bbt_erase_shift);
+					nand_eraseblock_to_offs(this,
+								offs + act));
 				/* Factory marked bad or worn out? */
 				if (tmp == 0)
 					bbt_mark_entry(this, offs + act,
-							BBT_BLOCK_FACTORY_BAD);
+						NAND_BBT_BLOCK_FACTORY_BAD);
 				else
 					bbt_mark_entry(this, offs + act,
-							BBT_BLOCK_WORN);
+						       NAND_BBT_BLOCK_WORN);
 				mtd->ecc_stats.badblocks++;
 			}
 		}
@@ -252,7 +262,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 
 /**
  * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page
- * @mtd: MTD device structure
+ * @this: NAND device
  * @buf: temporary buffer
  * @td: descriptor for the bad block table
  * @chip: read the table for a specific chip, -1 read all chips; applies only if
@@ -261,25 +271,27 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
  * Read the bad block table for all chips starting at a given page. We assume
  * that the bbt bits are in consecutive order.
  */
-static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
+static int read_abs_bbt(struct nand_device *this, uint8_t *buf,
+			struct nand_bbt_descr *td, int chip)
 {
-	struct nand_chip *this = mtd_to_nandchip(mtd);
+	int ndies = nand_ndies(this);
 	int res = 0, i;
 
 	if (td->options & NAND_BBT_PERCHIP) {
-		int offs = 0;
-		for (i = 0; i < this->numchips; i++) {
+		int offs = 0, nbbd = nand_eraseblocks_per_die(this);
+
+		for (i = 0; i < ndies; i++) {
 			if (chip == -1 || chip == i)
-				res = read_bbt(mtd, buf, td->pages[i],
-					this->chipsize >> this->bbt_erase_shift,
-					td, offs);
+				res = read_bbt(this, buf, td->pages[i], nbbd,
+					       td, offs);
 			if (res)
 				return res;
-			offs += this->chipsize >> this->bbt_erase_shift;
+
+			offs += nbbd;
 		}
 	} else {
-		res = read_bbt(mtd, buf, td->pages[0],
-				mtd->size >> this->bbt_erase_shift, td, 0);
+		res = read_bbt(this, buf, td->pages[0],
+			       nand_neraseblocks(this), td, 0);
 		if (res)
 			return res;
 	}
@@ -287,9 +299,10 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 }
 
 /* BBT marker is in the first page, no OOB */
-static int scan_read_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
-			 struct nand_bbt_descr *td)
+static int scan_read_data(struct nand_device *this, uint8_t *buf, loff_t offs,
+			  struct nand_bbt_descr *td)
 {
+	struct mtd_info *mtd = nand_to_mtd(this);
 	size_t retlen;
 	size_t len;
 
@@ -302,7 +315,7 @@ static int scan_read_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
 
 /**
  * scan_read_oob - [GENERIC] Scan data+OOB region to buffer
- * @mtd: MTD device structure
+ * @this: NAND device
  * @buf: temporary buffer
  * @offs: offset at which to scan
  * @len: length of data region to read
@@ -311,19 +324,20 @@ static int scan_read_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
  * page,OOB,page,OOB,... in buf. Completes transfer and returns the "strongest"
  * ECC condition (error or bitflip). May quit on the first (non-ECC) error.
  */
-static int scan_read_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
+static int scan_read_oob(struct nand_device *this, uint8_t *buf, loff_t offs,
 			 size_t len)
 {
+	struct mtd_info *mtd = nand_to_mtd(this);
 	struct mtd_oob_ops ops;
 	int res, ret = 0;
 
 	ops.mode = MTD_OPS_PLACE_OOB;
 	ops.ooboffs = 0;
-	ops.ooblen = mtd->oobsize;
+	ops.ooblen = nand_per_page_oobsize(this);
 
 	while (len > 0) {
 		ops.datbuf = buf;
-		ops.len = min(len, (size_t)mtd->writesize);
+		ops.len = min(len, nand_page_size(this));
 		ops.oobbuf = buf + ops.len;
 
 		res = mtd_read_oob(mtd, offs, &ops);
@@ -334,31 +348,32 @@ static int scan_read_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
 				ret = res;
 		}
 
-		buf += mtd->oobsize + mtd->writesize;
-		len -= mtd->writesize;
-		offs += mtd->writesize;
+		buf += nand_per_page_oobsize(this) + nand_page_size(this);
+		len -= nand_page_size(this);
+		offs += nand_page_size(this);
 	}
 	return ret;
 }
 
-static int scan_read(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
-			 size_t len, struct nand_bbt_descr *td)
+static int scan_read(struct nand_device *this, uint8_t *buf, loff_t offs,
+		     size_t len, struct nand_bbt_descr *td)
 {
 	if (td->options & NAND_BBT_NO_OOB)
-		return scan_read_data(mtd, buf, offs, td);
+		return scan_read_data(this, buf, offs, td);
 	else
-		return scan_read_oob(mtd, buf, offs, len);
+		return scan_read_oob(this, buf, offs, len);
 }
 
 /* Scan write data with oob to flash */
-static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len,
+static int scan_write_bbt(struct nand_device *this, loff_t offs, size_t len,
 			  uint8_t *buf, uint8_t *oob)
 {
+	struct mtd_info *mtd = nand_to_mtd(this);
 	struct mtd_oob_ops ops;
 
 	ops.mode = MTD_OPS_PLACE_OOB;
 	ops.ooboffs = 0;
-	ops.ooblen = mtd->oobsize;
+	ops.ooblen = nand_per_page_oobsize(this);
 	ops.datbuf = buf;
 	ops.oobbuf = oob;
 	ops.len = len;
@@ -366,18 +381,19 @@ static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len,
 	return mtd_write_oob(mtd, offs, &ops);
 }
 
-static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td)
+static u32 bbt_get_ver_offs(struct nand_device *this,
+			    struct nand_bbt_descr *td)
 {
 	u32 ver_offs = td->veroffs;
 
 	if (!(td->options & NAND_BBT_NO_OOB))
-		ver_offs += mtd->writesize;
+		ver_offs += nand_page_size(this);
 	return ver_offs;
 }
 
 /**
  * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page
- * @mtd: MTD device structure
+ * @this: NAND device
  * @buf: temporary buffer
  * @td: descriptor for the bad block table
  * @md:	descriptor for the bad block table mirror
@@ -385,38 +401,37 @@ static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td)
  * Read the bad block table(s) for all chips starting at a given page. We
  * assume that the bbt bits are in consecutive order.
  */
-static void read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
+static void read_abs_bbts(struct nand_device *this, uint8_t *buf,
 			  struct nand_bbt_descr *td, struct nand_bbt_descr *md)
 {
-	struct nand_chip *this = mtd_to_nandchip(mtd);
-
 	/* Read the primary version, if available */
 	if (td->options & NAND_BBT_VERSION) {
-		scan_read(mtd, buf, (loff_t)td->pages[0] << this->page_shift,
-			      mtd->writesize, td);
-		td->version[0] = buf[bbt_get_ver_offs(mtd, td)];
+		scan_read(this, buf, nand_page_to_offs(this, td->pages[0]),
+			  nand_page_size(this), td);
+		td->version[0] = buf[bbt_get_ver_offs(this, td)];
 		pr_info("Bad block table at page %d, version 0x%02X\n",
 			 td->pages[0], td->version[0]);
 	}
 
 	/* Read the mirror version, if available */
 	if (md && (md->options & NAND_BBT_VERSION)) {
-		scan_read(mtd, buf, (loff_t)md->pages[0] << this->page_shift,
-			      mtd->writesize, md);
-		md->version[0] = buf[bbt_get_ver_offs(mtd, md)];
+		scan_read(this, buf, nand_page_to_offs(this, td->pages[0]),
+			  nand_page_size(this), md);
+		md->version[0] = buf[bbt_get_ver_offs(this, md)];
 		pr_info("Bad block table at page %d, version 0x%02X\n",
 			 md->pages[0], md->version[0]);
 	}
 }
 
 /* Scan a given block partially */
-static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
+static int scan_block_fast(struct nand_device *this, struct nand_bbt_descr *bd,
 			   loff_t offs, uint8_t *buf, int numpages)
 {
+	struct mtd_info *mtd = nand_to_mtd(this);
 	struct mtd_oob_ops ops;
 	int j, ret;
 
-	ops.ooblen = mtd->oobsize;
+	ops.ooblen = nand_per_page_oobsize(this);
 	ops.oobbuf = buf;
 	ops.ooboffs = 0;
 	ops.datbuf = NULL;
@@ -435,14 +450,14 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
 		if (check_short_pattern(buf, bd))
 			return 1;
 
-		offs += mtd->writesize;
+		offs += nand_page_size(this);
 	}
 	return 0;
 }
 
 /**
  * create_bbt - [GENERIC] Create a bad block table by scanning the device
- * @mtd: MTD device structure
+ * @this: NAND device
  * @buf: temporary buffer
  * @bd: descriptor for the good/bad block search pattern
  * @chip: create the table for a specific chip, -1 read all chips; applies only
@@ -451,10 +466,10 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
  * Create a bad block table by scanning the device for the given good/bad block
  * identify pattern.
  */
-static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
-	struct nand_bbt_descr *bd, int chip)
+static int create_bbt(struct nand_device *this, uint8_t *buf,
+		      struct nand_bbt_descr *bd, int chip)
 {
-	struct nand_chip *this = mtd_to_nandchip(mtd);
+	struct mtd_info *mtd = nand_to_mtd(this);
 	int i, numblocks, numpages;
 	int startblock;
 	loff_t from;
@@ -467,48 +482,49 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 		numpages = 1;
 
 	if (chip == -1) {
-		numblocks = mtd->size >> this->bbt_erase_shift;
+		numblocks = nand_neraseblocks(this);
 		startblock = 0;
 		from = 0;
 	} else {
-		if (chip >= this->numchips) {
+		if (chip >= nand_ndies(this)) {
 			pr_warn("create_bbt(): chipnr (%d) > available chips (%d)\n",
-			       chip + 1, this->numchips);
+			       chip + 1, nand_ndies(this));
 			return -EINVAL;
 		}
-		numblocks = this->chipsize >> this->bbt_erase_shift;
+		numblocks = nand_eraseblocks_per_die(this);
 		startblock = chip * numblocks;
 		numblocks += startblock;
-		from = (loff_t)startblock << this->bbt_erase_shift;
+		from = nand_eraseblock_to_offs(this, startblock);
 	}
 
-	if (this->bbt_options & NAND_BBT_SCANLASTPAGE)
-		from += mtd->erasesize - (mtd->writesize * numpages);
+	if (this->bbt.options & NAND_BBT_SCANLASTPAGE)
+		from += nand_eraseblock_size(this) -
+			(nand_page_size(this) * numpages);
 
 	for (i = startblock; i < numblocks; i++) {
 		int ret;
 
 		BUG_ON(bd->options & NAND_BBT_NO_OOB);
 
-		ret = scan_block_fast(mtd, bd, from, buf, numpages);
+		ret = scan_block_fast(this, bd, from, buf, numpages);
 		if (ret < 0)
 			return ret;
 
 		if (ret) {
-			bbt_mark_entry(this, i, BBT_BLOCK_FACTORY_BAD);
+			bbt_mark_entry(this, i, NAND_BBT_BLOCK_FACTORY_BAD);
 			pr_warn("Bad eraseblock %d at 0x%012llx\n",
 				i, (unsigned long long)from);
 			mtd->ecc_stats.badblocks++;
 		}
 
-		from += (1 << this->bbt_erase_shift);
+		from += nand_eraseblock_size(this);
 	}
 	return 0;
 }
 
 /**
  * search_bbt - [GENERIC] scan the device for a specific bad block table
- * @mtd: MTD device structure
+ * @this: NAND device
  * @buf: temporary buffer
  * @td: descriptor for the bad block table
  *
@@ -521,18 +537,17 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
  *
  * The bbt ident pattern resides in the oob area of the first page in a block.
  */
-static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
+static int search_bbt(struct nand_device *this, uint8_t *buf,
+		      struct nand_bbt_descr *td)
 {
-	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int i, chips;
 	int startblock, block, dir;
-	int scanlen = mtd->writesize + mtd->oobsize;
+	int scanlen = nand_page_size(this) + nand_per_page_oobsize(this);
 	int bbtblocks;
-	int blocktopage = this->bbt_erase_shift - this->page_shift;
 
 	/* Search direction top -> down? */
 	if (td->options & NAND_BBT_LASTBLOCK) {
-		startblock = (mtd->size >> this->bbt_erase_shift) - 1;
+		startblock = nand_neraseblocks(this) - 1;
 		dir = -1;
 	} else {
 		startblock = 0;
@@ -541,12 +556,12 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
 
 	/* Do we have a bbt per chip? */
 	if (td->options & NAND_BBT_PERCHIP) {
-		chips = this->numchips;
-		bbtblocks = this->chipsize >> this->bbt_erase_shift;
+		chips = nand_ndies(this);
+		bbtblocks = nand_eraseblocks_per_die(this);
 		startblock &= bbtblocks - 1;
 	} else {
 		chips = 1;
-		bbtblocks = mtd->size >> this->bbt_erase_shift;
+		bbtblocks = nand_neraseblocks(this);
 	}
 
 	for (i = 0; i < chips; i++) {
@@ -557,20 +572,22 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
 		for (block = 0; block < td->maxblocks; block++) {
 
 			int actblock = startblock + dir * block;
-			loff_t offs = (loff_t)actblock << this->bbt_erase_shift;
+			loff_t offs = nand_eraseblock_to_offs(this, actblock);
 
 			/* Read first page */
-			scan_read(mtd, buf, offs, mtd->writesize, td);
-			if (!check_pattern(buf, scanlen, mtd->writesize, td)) {
-				td->pages[i] = actblock << blocktopage;
+			scan_read(this, buf, offs, nand_page_size(this), td);
+			if (!check_pattern(buf, scanlen,
+					   nand_page_size(this), td)) {
+				td->pages[i] = nand_eraseblock_to_page(this,
+								  actblock);
 				if (td->options & NAND_BBT_VERSION) {
-					offs = bbt_get_ver_offs(mtd, td);
+					offs = bbt_get_ver_offs(this, td);
 					td->version[i] = buf[offs];
 				}
 				break;
 			}
 		}
-		startblock += this->chipsize >> this->bbt_erase_shift;
+		startblock += nand_eraseblocks_per_die(this);
 	}
 	/* Check, if we found a bbt for each requested chip */
 	for (i = 0; i < chips; i++) {
@@ -585,23 +602,23 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
 
 /**
  * search_read_bbts - [GENERIC] scan the device for bad block table(s)
- * @mtd: MTD device structure
+ * @this: NAND device
  * @buf: temporary buffer
  * @td: descriptor for the bad block table
  * @md: descriptor for the bad block table mirror
  *
  * Search and read the bad block table(s).
  */
-static void search_read_bbts(struct mtd_info *mtd, uint8_t *buf,
+static void search_read_bbts(struct nand_device *this, uint8_t *buf,
 			     struct nand_bbt_descr *td,
 			     struct nand_bbt_descr *md)
 {
 	/* Search the primary table */
-	search_bbt(mtd, buf, td);
+	search_bbt(this, buf, td);
 
 	/* Search the mirror table */
 	if (md)
-		search_bbt(mtd, buf, md);
+		search_bbt(this, buf, md);
 }
 
 /**
@@ -617,7 +634,7 @@ static void search_read_bbts(struct mtd_info *mtd, uint8_t *buf,
  * pointing to a valid block we re-use it, otherwise we search for the next
  * valid one.
  */
-static int get_bbt_block(struct nand_chip *this, struct nand_bbt_descr *td,
+static int get_bbt_block(struct nand_device *this, struct nand_bbt_descr *td,
 			 struct nand_bbt_descr *md, int chip)
 {
 	int startblock, dir, page, numblocks, i;
@@ -628,12 +645,11 @@ static int get_bbt_block(struct nand_chip *this, struct nand_bbt_descr *td,
 	 * td->pages.
 	 */
 	if (td->pages[chip] != -1)
-		return td->pages[chip] >>
-				(this->bbt_erase_shift - this->page_shift);
+		return nand_page_to_eraseblock(this, td->pages[chip]);
 
-	numblocks = (int)(this->chipsize >> this->bbt_erase_shift);
+	numblocks = nand_eraseblocks_per_die(this);
 	if (!(td->options & NAND_BBT_PERCHIP))
-		numblocks *= this->numchips;
+		numblocks *= nand_ndies(this);
 
 	/*
 	 * Automatic placement of the bad block table. Search direction
@@ -652,12 +668,12 @@ static int get_bbt_block(struct nand_chip *this, struct nand_bbt_descr *td,
 
 		/* Check, if the block is bad */
 		switch (bbt_get_entry(this, block)) {
-		case BBT_BLOCK_WORN:
-		case BBT_BLOCK_FACTORY_BAD:
+		case NAND_BBT_BLOCK_WORN:
+		case NAND_BBT_BLOCK_FACTORY_BAD:
 			continue;
 		}
 
-		page = block << (this->bbt_erase_shift - this->page_shift);
+		page = nand_eraseblock_to_page(this, block);
 
 		/* Check, if the block is used by the mirror table */
 		if (!md || md->pages[chip] != page)
@@ -679,18 +695,15 @@ static int get_bbt_block(struct nand_chip *this, struct nand_bbt_descr *td,
  * block as bad using a bad block marker and invalidating the associated
  * td->pages[] entry.
  */
-static void mark_bbt_block_bad(struct nand_chip *this,
+static void mark_bbt_block_bad(struct nand_device *this,
 			       struct nand_bbt_descr *td,
 			       int chip, int block)
 {
-	struct mtd_info *mtd = nandchip_to_mtd(this);
-	loff_t to;
 	int res;
 
-	bbt_mark_entry(this, block, BBT_BLOCK_WORN);
+	bbt_mark_entry(this, block, NAND_BBT_BLOCK_WORN);
 
-	to = (loff_t)block << this->bbt_erase_shift;
-	res = this->block_markbad(mtd, to);
+	res = nand_markbad(this, block);
 	if (res)
 		pr_warn("nand_bbt: error %d while marking block %d bad\n",
 			res, block);
@@ -700,7 +713,7 @@ static void mark_bbt_block_bad(struct nand_chip *this,
 
 /**
  * write_bbt - [GENERIC] (Re)write the bad block table
- * @mtd: MTD device structure
+ * @this: NAND device
  * @buf: temporary buffer
  * @td: descriptor for the bad block table
  * @md: descriptor for the bad block table mirror
@@ -708,11 +721,11 @@ static void mark_bbt_block_bad(struct nand_chip *this,
  *
  * (Re)write the bad block table.
  */
-static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
+static int write_bbt(struct nand_device *this, uint8_t *buf,
 		     struct nand_bbt_descr *td, struct nand_bbt_descr *md,
 		     int chipsel)
 {
-	struct nand_chip *this = mtd_to_nandchip(mtd);
+	struct mtd_info *mtd = nand_to_mtd(this);
 	struct erase_info einfo;
 	int i, res, chip = 0;
 	int bits, page, offs, numblocks, sft, sftmsk;
@@ -723,7 +736,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 	loff_t to;
 	struct mtd_oob_ops ops;
 
-	ops.ooblen = mtd->oobsize;
+	ops.ooblen = nand_per_page_oobsize(this);
 	ops.ooboffs = 0;
 	ops.datbuf = NULL;
 	ops.mode = MTD_OPS_PLACE_OOB;
@@ -732,16 +745,16 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 		rcode = 0xff;
 	/* Write bad block table per chip rather than per device? */
 	if (td->options & NAND_BBT_PERCHIP) {
-		numblocks = (int)(this->chipsize >> this->bbt_erase_shift);
+		numblocks = nand_eraseblocks_per_die(this);
 		/* Full device write or specific chip? */
 		if (chipsel == -1) {
-			nrchips = this->numchips;
+			nrchips = nand_ndies(this);
 		} else {
 			nrchips = chipsel + 1;
 			chip = chipsel;
 		}
 	} else {
-		numblocks = (int)(mtd->size >> this->bbt_erase_shift);
+		numblocks = nand_neraseblocks(this);
 		nrchips = 1;
 	}
 
@@ -760,7 +773,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 		 * get_bbt_block() returns a block number, shift the value to
 		 * get a page number.
 		 */
-		page = block << (this->bbt_erase_shift - this->page_shift);
+		page = nand_eraseblock_to_page(this, block);
 
 		/* Set up shift count and masks for the flash table */
 		bits = td->options & NAND_BBT_NRBITS_MSK;
@@ -781,13 +794,14 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 		default: return -EINVAL;
 		}
 
-		to = ((loff_t)page) << this->page_shift;
+		to = nand_page_to_offs(this, page);
 
 		/* Must we save the block contents? */
 		if (td->options & NAND_BBT_SAVECONTENT) {
 			/* Make it block aligned */
-			to &= ~(((loff_t)1 << this->bbt_erase_shift) - 1);
-			len = 1 << this->bbt_erase_shift;
+			to = nand_eraseblock_to_offs(this,
+					nand_page_to_eraseblock(this, page));
+			len = nand_eraseblock_size(this);
 			res = mtd_read(mtd, to, len, &retlen, buf);
 			if (res < 0) {
 				if (retlen != len) {
@@ -797,18 +811,21 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 				pr_warn("nand_bbt: ECC error while reading block for writing bad block table\n");
 			}
 			/* Read oob data */
-			ops.ooblen = (len >> this->page_shift) * mtd->oobsize;
+			ops.ooblen = nand_len_to_pages(this, len) *
+				     nand_per_page_oobsize(this);
 			ops.oobbuf = &buf[len];
-			res = mtd_read_oob(mtd, to + mtd->writesize, &ops);
+			res = mtd_read_oob(mtd, to + nand_page_size(this),
+					   &ops);
 			if (res < 0 || ops.oobretlen != ops.ooblen)
 				goto outerr;
 
 			/* Calc the byte offset in the buffer */
-			pageoffs = page - (int)(to >> this->page_shift);
-			offs = pageoffs << this->page_shift;
+			pageoffs = page - nand_offs_to_page(this, to);
+			offs = nand_page_to_offs(this, pageoffs);
 			/* Preset the bbt area with 0xff */
 			memset(&buf[offs], 0xff, (size_t)(numblocks >> sft));
-			ooboffs = len + (pageoffs * mtd->oobsize);
+			ooboffs = len +
+				  (pageoffs * nand_per_page_oobsize(this));
 
 		} else if (td->options & NAND_BBT_NO_OOB) {
 			ooboffs = 0;
@@ -820,7 +837,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 			len = (size_t)(numblocks >> sft);
 			len += offs;
 			/* Make it page aligned! */
-			len = ALIGN(len, mtd->writesize);
+			len = ALIGN(len, nand_page_size(this));
 			/* Preset the buffer with 0xff */
 			memset(buf, 0xff, len);
 			/* Pattern is located at the begin of first page */
@@ -829,10 +846,11 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 			/* Calc length */
 			len = (size_t)(numblocks >> sft);
 			/* Make it page aligned! */
-			len = ALIGN(len, mtd->writesize);
+			len = ALIGN(len, nand_page_size(this));
 			/* Preset the buffer with 0xff */
 			memset(buf, 0xff, len +
-			       (len >> this->page_shift)* mtd->oobsize);
+					  (nand_len_to_pages(this, len) *
+					   nand_per_page_oobsize(this)));
 			offs = 0;
 			ooboffs = len;
 			/* Pattern is located in oob area of first page */
@@ -854,8 +872,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 		memset(&einfo, 0, sizeof(einfo));
 		einfo.mtd = mtd;
 		einfo.addr = to;
-		einfo.len = 1 << this->bbt_erase_shift;
-		res = nand_erase_nand(mtd, &einfo, 1);
+		einfo.len = nand_eraseblock_size(this);
+		res = nand_erase(this, &einfo, 1);
 		if (res < 0) {
 			pr_warn("nand_bbt: error while erasing BBT block %d\n",
 				res);
@@ -863,9 +881,9 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 			continue;
 		}
 
-		res = scan_write_bbt(mtd, to, len, buf,
-				td->options & NAND_BBT_NO_OOB ? NULL :
-				&buf[len]);
+		res = scan_write_bbt(this, to, len, buf,
+				     td->options & NAND_BBT_NO_OOB ? NULL :
+				     &buf[len]);
 		if (res < 0) {
 			pr_warn("nand_bbt: error while writing BBT block %d\n",
 				res);
@@ -888,22 +906,31 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 
 /**
  * nand_memory_bbt - [GENERIC] create a memory based bad block table
- * @mtd: MTD device structure
+ * @this: NAND device
  * @bd: descriptor for the good/bad block search pattern
  *
  * The function creates a memory based bbt by scanning the device for
  * manufacturer / software marked good / bad blocks.
  */
-static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
+static inline int nand_memory_bbt(struct nand_device *this,
+				  struct nand_bbt_descr *bd)
 {
-	struct nand_chip *this = mtd_to_nandchip(mtd);
+	void *buffer;
+	int ret;
+
+	buffer = kmalloc(nand_page_size(this), GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
 
-	return create_bbt(mtd, this->buffers->databuf, bd, -1);
+	ret = create_bbt(this, buffer, bd, -1);
+	kfree(buffer);
+
+	return ret;
 }
 
 /**
  * check_create - [GENERIC] create and write bbt(s) if necessary
- * @mtd: MTD device structure
+ * @this: NAND device
  * @buf: temporary buffer
  * @bd: descriptor for the good/bad block search pattern
  *
@@ -912,17 +939,17 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b
  * for the chip/device. Update is necessary if one of the tables is missing or
  * the version nr. of one table is less than the other.
  */
-static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
+static int check_create(struct nand_device *this, uint8_t *buf,
+			struct nand_bbt_descr *bd)
 {
 	int i, chips, writeops, create, chipsel, res, res2;
-	struct nand_chip *this = mtd_to_nandchip(mtd);
-	struct nand_bbt_descr *td = this->bbt_td;
-	struct nand_bbt_descr *md = this->bbt_md;
+	struct nand_bbt_descr *td = this->bbt.td;
+	struct nand_bbt_descr *md = this->bbt.md;
 	struct nand_bbt_descr *rd, *rd2;
 
 	/* Do we have a bbt per chip? */
 	if (td->options & NAND_BBT_PERCHIP)
-		chips = this->numchips;
+		chips = nand_ndies(this);
 	else
 		chips = 1;
 
@@ -971,8 +998,8 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 				continue;
 
 			/* Create the table in memory by scanning the chip(s) */
-			if (!(this->bbt_options & NAND_BBT_CREATE_EMPTY))
-				create_bbt(mtd, buf, bd, chipsel);
+			if (!(this->bbt.options & NAND_BBT_CREATE_EMPTY))
+				create_bbt(this, buf, bd, chipsel);
 
 			td->version[i] = 1;
 			if (md)
@@ -981,7 +1008,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 
 		/* Read back first? */
 		if (rd) {
-			res = read_abs_bbt(mtd, buf, rd, chipsel);
+			res = read_abs_bbt(this, buf, rd, chipsel);
 			if (mtd_is_eccerr(res)) {
 				/* Mark table as invalid */
 				rd->pages[i] = -1;
@@ -992,7 +1019,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 		}
 		/* If they weren't versioned, read both */
 		if (rd2) {
-			res2 = read_abs_bbt(mtd, buf, rd2, chipsel);
+			res2 = read_abs_bbt(this, buf, rd2, chipsel);
 			if (mtd_is_eccerr(res2)) {
 				/* Mark table as invalid */
 				rd2->pages[i] = -1;
@@ -1014,14 +1041,14 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 
 		/* Write the bad block table to the device? */
 		if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
-			res = write_bbt(mtd, buf, td, md, chipsel);
+			res = write_bbt(this, buf, td, md, chipsel);
 			if (res < 0)
 				return res;
 		}
 
 		/* Write the mirror bad block table to the device? */
 		if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
-			res = write_bbt(mtd, buf, md, td, chipsel);
+			res = write_bbt(this, buf, md, td, chipsel);
 			if (res < 0)
 				return res;
 		}
@@ -1031,25 +1058,26 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 
 /**
  * mark_bbt_regions - [GENERIC] mark the bad block table regions
- * @mtd: MTD device structure
+ * @this: NAND device
  * @td: bad block table descriptor
  *
  * The bad block table regions are marked as "bad" to prevent accidental
  * erasures / writes. The regions are identified by the mark 0x02.
  */
-static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
+static void mark_bbt_region(struct nand_device *this,
+			    struct nand_bbt_descr *td)
 {
-	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int i, j, chips, block, nrblocks, update;
 	uint8_t oldval;
+	loff_t offs;
 
 	/* Do we have a bbt per chip? */
 	if (td->options & NAND_BBT_PERCHIP) {
-		chips = this->numchips;
-		nrblocks = (int)(this->chipsize >> this->bbt_erase_shift);
+		chips = nand_ndies(this);
+		nrblocks = nand_eraseblocks_per_die(this);
 	} else {
 		chips = 1;
-		nrblocks = (int)(mtd->size >> this->bbt_erase_shift);
+		nrblocks = nand_neraseblocks(this);
 	}
 
 	for (i = 0; i < chips; i++) {
@@ -1057,13 +1085,14 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
 		    !(td->options & NAND_BBT_WRITE)) {
 			if (td->pages[i] == -1)
 				continue;
-			block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);
+			block = nand_page_to_eraseblock(this, td->pages[i]);
 			oldval = bbt_get_entry(this, block);
-			bbt_mark_entry(this, block, BBT_BLOCK_RESERVED);
-			if ((oldval != BBT_BLOCK_RESERVED) &&
-					td->reserved_block_code)
-				nand_update_bbt(mtd, (loff_t)block <<
-						this->bbt_erase_shift);
+			bbt_mark_entry(this, block, NAND_BBT_BLOCK_RESERVED);
+			if ((oldval != NAND_BBT_BLOCK_RESERVED) &&
+			    td->reserved_block_code) {
+				offs = nand_eraseblock_to_offs(this, block);
+				nand_update_bbt(this, offs);
+			}
 			continue;
 		}
 		update = 0;
@@ -1073,8 +1102,8 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
 			block = i * nrblocks;
 		for (j = 0; j < td->maxblocks; j++) {
 			oldval = bbt_get_entry(this, block);
-			bbt_mark_entry(this, block, BBT_BLOCK_RESERVED);
-			if (oldval != BBT_BLOCK_RESERVED)
+			bbt_mark_entry(this, block, NAND_BBT_BLOCK_RESERVED);
+			if (oldval != NAND_BBT_BLOCK_RESERVED)
 				update = 1;
 			block++;
 		}
@@ -1083,23 +1112,24 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
 		 * new ones have been marked, then we need to update the stored
 		 * bbts.  This should only happen once.
 		 */
-		if (update && td->reserved_block_code)
-			nand_update_bbt(mtd, (loff_t)(block - 1) <<
-					this->bbt_erase_shift);
+		if (update && td->reserved_block_code) {
+			offs = nand_eraseblock_to_offs(this, block - 1);
+			nand_update_bbt(this, offs);
+		}
 	}
 }
 
 /**
  * verify_bbt_descr - verify the bad block description
- * @mtd: MTD device structure
+ * @this: NAND device
  * @bd: the table to verify
  *
  * This functions performs a few sanity checks on the bad block description
  * table.
  */
-static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
+static void verify_bbt_descr(struct nand_device *this,
+			     struct nand_bbt_descr *bd)
 {
-	struct nand_chip *this = mtd_to_nandchip(mtd);
 	u32 pattern_len;
 	u32 bits;
 	u32 table_size;
@@ -1110,16 +1140,16 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 	pattern_len = bd->len;
 	bits = bd->options & NAND_BBT_NRBITS_MSK;
 
-	BUG_ON((this->bbt_options & NAND_BBT_NO_OOB) &&
-			!(this->bbt_options & NAND_BBT_USE_FLASH));
+	BUG_ON((this->bbt.options & NAND_BBT_NO_OOB) &&
+	       !(this->bbt.options & NAND_BBT_USE_FLASH));
 	BUG_ON(!bits);
 
 	if (bd->options & NAND_BBT_VERSION)
 		pattern_len++;
 
 	if (bd->options & NAND_BBT_NO_OOB) {
-		BUG_ON(!(this->bbt_options & NAND_BBT_USE_FLASH));
-		BUG_ON(!(this->bbt_options & NAND_BBT_NO_OOB));
+		BUG_ON(!(this->bbt.options & NAND_BBT_USE_FLASH));
+		BUG_ON(!(this->bbt.options & NAND_BBT_NO_OOB));
 		BUG_ON(bd->offs);
 		if (bd->options & NAND_BBT_VERSION)
 			BUG_ON(bd->veroffs != bd->len);
@@ -1127,19 +1157,63 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 	}
 
 	if (bd->options & NAND_BBT_PERCHIP)
-		table_size = this->chipsize >> this->bbt_erase_shift;
+		table_size = nand_eraseblocks_per_die(this);
 	else
-		table_size = mtd->size >> this->bbt_erase_shift;
+		table_size = nand_neraseblocks(this);
 	table_size >>= 3;
 	table_size *= bits;
 	if (bd->options & NAND_BBT_NO_OOB)
 		table_size += pattern_len;
-	BUG_ON(table_size > (1 << this->bbt_erase_shift));
+	BUG_ON(table_size > nand_eraseblock_size(this));
 }
 
+/* Generic flash bbt descriptors */
+static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
+static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+	.offs =	8,
+	.len = 4,
+	.veroffs = 12,
+	.maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
+	.pattern = bbt_pattern
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+	.offs =	8,
+	.len = 4,
+	.veroffs = 12,
+	.maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
+	.pattern = mirror_pattern
+};
+
+static struct nand_bbt_descr bbt_main_no_oob_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP
+		| NAND_BBT_NO_OOB,
+	.len = 4,
+	.veroffs = 4,
+	.maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
+	.pattern = bbt_pattern
+};
+
+static struct nand_bbt_descr bbt_mirror_no_oob_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP
+		| NAND_BBT_NO_OOB,
+	.len = 4,
+	.veroffs = 4,
+	.maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
+	.pattern = mirror_pattern
+};
+
 /**
  * nand_scan_bbt - [NAND Interface] scan, find, read and maybe create bad block table(s)
- * @mtd: MTD device structure
+ * @this: NAND device
  * @bd: descriptor for the good/bad block search pattern
  *
  * The function checks, if a bad block table(s) is/are already available. If
@@ -1149,21 +1223,40 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
  * The bad block table memory is allocated here. It must be freed by calling
  * the nand_free_bbt function.
  */
-static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
+int nand_scan_bbt(struct nand_device *this)
 {
-	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int len, res;
 	uint8_t *buf;
-	struct nand_bbt_descr *td = this->bbt_td;
-	struct nand_bbt_descr *md = this->bbt_md;
+	struct nand_bbt_descr *td, *md, *bd;
+
+	/* Is a flash based bad block table requested? */
+	if (this->bbt.options & NAND_BBT_USE_FLASH) {
+		/* Use the default pattern descriptors */
+		if (!this->bbt.td) {
+			if (this->bbt.options & NAND_BBT_NO_OOB) {
+				this->bbt.td = &bbt_main_no_oob_descr;
+				this->bbt.md = &bbt_mirror_no_oob_descr;
+			} else {
+				this->bbt.td = &bbt_main_descr;
+				this->bbt.md = &bbt_mirror_descr;
+			}
+		}
+	} else {
+		this->bbt.td = NULL;
+		this->bbt.md = NULL;
+	}
+
+	td = this->bbt.td;
+	md = this->bbt.md;
+	bd = this->bbt.bbp;
 
-	len = (mtd->size >> (this->bbt_erase_shift + 2)) ? : 1;
 	/*
 	 * Allocate memory (2bit per block) and clear the memory bad block
 	 * table.
 	 */
-	this->bbt = kzalloc(len, GFP_KERNEL);
-	if (!this->bbt)
+	len = DIV_ROUND_UP(nand_neraseblocks(this) * 2, 8);
+	this->bbt.bbt = kzalloc(len, GFP_KERNEL);
+	if (!this->bbt.bbt)
 		return -ENOMEM;
 
 	/*
@@ -1171,18 +1264,19 @@ static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 	 * memory based bad block table.
 	 */
 	if (!td) {
-		if ((res = nand_memory_bbt(mtd, bd))) {
+		res = nand_memory_bbt(this, bd);
+		if (res) {
 			pr_err("nand_bbt: can't scan flash and build the RAM-based BBT\n");
 			goto err;
 		}
+
 		return 0;
 	}
-	verify_bbt_descr(mtd, td);
-	verify_bbt_descr(mtd, md);
+	verify_bbt_descr(this, td);
+	verify_bbt_descr(this, md);
 
 	/* Allocate a temporary buffer for one eraseblock incl. oob */
-	len = (1 << this->bbt_erase_shift);
-	len += (len >> this->page_shift) * mtd->oobsize;
+	len = nand_eraseblock_size(this) + nand_per_eraseblock_oobsize(this);
 	buf = vmalloc(len);
 	if (!buf) {
 		res = -ENOMEM;
@@ -1191,59 +1285,68 @@ static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 
 	/* Is the bbt at a given page? */
 	if (td->options & NAND_BBT_ABSPAGE) {
-		read_abs_bbts(mtd, buf, td, md);
+		read_abs_bbts(this, buf, td, md);
 	} else {
 		/* Search the bad block table using a pattern in oob */
-		search_read_bbts(mtd, buf, td, md);
+		search_read_bbts(this, buf, td, md);
 	}
 
-	res = check_create(mtd, buf, bd);
+	res = check_create(this, buf, bd);
 	if (res)
 		goto err;
 
 	/* Prevent the bbt regions from erasing / writing */
-	mark_bbt_region(mtd, td);
+	mark_bbt_region(this, td);
 	if (md)
-		mark_bbt_region(mtd, md);
+		mark_bbt_region(this, md);
 
 	vfree(buf);
 	return 0;
 
 err:
-	kfree(this->bbt);
-	this->bbt = NULL;
+	kfree(this->bbt.bbt);
+	this->bbt.bbt = NULL;
 	return res;
 }
 
 /**
+ * nand_release_bbt - release bad block table(s)
+ * @this: NAND device
+ *
+ * The function releases the bad block table(s).
+ */
+void nand_release_bbt(struct nand_device *this)
+{
+	kfree(this->bbt.bbt);
+}
+
+/**
  * nand_update_bbt - update bad block table(s)
- * @mtd: MTD device structure
+ * @this: NAND device
  * @offs: the offset of the newly marked block
  *
  * The function updates the bad block table(s).
  */
-static int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
+int nand_update_bbt(struct nand_device *this, loff_t offs)
 {
-	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int len, res = 0;
 	int chip, chipsel;
 	uint8_t *buf;
-	struct nand_bbt_descr *td = this->bbt_td;
-	struct nand_bbt_descr *md = this->bbt_md;
+	struct nand_bbt_descr *td = this->bbt.td;
+	struct nand_bbt_descr *md = this->bbt.md;
 
-	if (!this->bbt || !td)
+	if (!this->bbt.bbt || !td)
 		return -EINVAL;
 
 	/* Allocate a temporary buffer for one eraseblock incl. oob */
-	len = (1 << this->bbt_erase_shift);
-	len += (len >> this->page_shift) * mtd->oobsize;
+	len = nand_eraseblock_size(this) + nand_per_eraseblock_oobsize(this);
 	buf = kmalloc(len, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
 
 	/* Do we have a bbt per chip? */
 	if (td->options & NAND_BBT_PERCHIP) {
-		chip = (int)(offs >> this->chip_shift);
+		chip = nand_offs_to_die(this, offs);
 		chipsel = chip;
 	} else {
 		chip = 0;
@@ -1256,13 +1359,13 @@ static int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
 
 	/* Write the bad block table to the device? */
 	if (td->options & NAND_BBT_WRITE) {
-		res = write_bbt(mtd, buf, td, md, chipsel);
+		res = write_bbt(this, buf, td, md, chipsel);
 		if (res < 0)
 			goto out;
 	}
 	/* Write the mirror bad block table to the device? */
 	if (md && (md->options & NAND_BBT_WRITE)) {
-		res = write_bbt(mtd, buf, md, td, chipsel);
+		res = write_bbt(this, buf, md, td, chipsel);
 	}
 
  out:
@@ -1270,160 +1373,41 @@ static int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
 	return res;
 }
 
-/*
- * Define some generic bad / good block scan pattern which are used
- * while scanning a device for factory marked good / bad blocks.
- */
-static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
-
-/* Generic flash bbt descriptors */
-static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
-static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
-
-static struct nand_bbt_descr bbt_main_descr = {
-	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
-		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
-	.offs =	8,
-	.len = 4,
-	.veroffs = 12,
-	.maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
-	.pattern = bbt_pattern
-};
-
-static struct nand_bbt_descr bbt_mirror_descr = {
-	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
-		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
-	.offs =	8,
-	.len = 4,
-	.veroffs = 12,
-	.maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
-	.pattern = mirror_pattern
-};
-
-static struct nand_bbt_descr bbt_main_no_oob_descr = {
-	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
-		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP
-		| NAND_BBT_NO_OOB,
-	.len = 4,
-	.veroffs = 4,
-	.maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
-	.pattern = bbt_pattern
-};
-
-static struct nand_bbt_descr bbt_mirror_no_oob_descr = {
-	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
-		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP
-		| NAND_BBT_NO_OOB,
-	.len = 4,
-	.veroffs = 4,
-	.maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
-	.pattern = mirror_pattern
-};
-
-#define BADBLOCK_SCAN_MASK (~NAND_BBT_NO_OOB)
-/**
- * nand_create_badblock_pattern - [INTERN] Creates a BBT descriptor structure
- * @this: NAND chip to create descriptor for
- *
- * This function allocates and initializes a nand_bbt_descr for BBM detection
- * based on the properties of @this. The new descriptor is stored in
- * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when
- * passed to this function.
- */
-static int nand_create_badblock_pattern(struct nand_chip *this)
-{
-	struct nand_bbt_descr *bd;
-	if (this->badblock_pattern) {
-		pr_warn("Bad block pattern already allocated; not replacing\n");
-		return -EINVAL;
-	}
-	bd = kzalloc(sizeof(*bd), GFP_KERNEL);
-	if (!bd)
-		return -ENOMEM;
-	bd->options = this->bbt_options & BADBLOCK_SCAN_MASK;
-	bd->offs = this->badblockpos;
-	bd->len = (this->options & NAND_BUSWIDTH_16) ? 2 : 1;
-	bd->pattern = scan_ff_pattern;
-	bd->options |= NAND_BBT_DYNAMICSTRUCT;
-	this->badblock_pattern = bd;
-	return 0;
-}
-
-/**
- * nand_default_bbt - [NAND Interface] Select a default bad block table for the device
- * @mtd: MTD device structure
- *
- * This function selects the default bad block table support for the device and
- * calls the nand_scan_bbt function.
- */
-int nand_default_bbt(struct mtd_info *mtd)
-{
-	struct nand_chip *this = mtd_to_nandchip(mtd);
-	int ret;
-
-	/* Is a flash based bad block table requested? */
-	if (this->bbt_options & NAND_BBT_USE_FLASH) {
-		/* Use the default pattern descriptors */
-		if (!this->bbt_td) {
-			if (this->bbt_options & NAND_BBT_NO_OOB) {
-				this->bbt_td = &bbt_main_no_oob_descr;
-				this->bbt_md = &bbt_mirror_no_oob_descr;
-			} else {
-				this->bbt_td = &bbt_main_descr;
-				this->bbt_md = &bbt_mirror_descr;
-			}
-		}
-	} else {
-		this->bbt_td = NULL;
-		this->bbt_md = NULL;
-	}
-
-	if (!this->badblock_pattern) {
-		ret = nand_create_badblock_pattern(this);
-		if (ret)
-			return ret;
-	}
-
-	return nand_scan_bbt(mtd, this->badblock_pattern);
-}
-
 /**
  * nand_isreserved_bbt - [NAND Interface] Check if a block is reserved
- * @mtd: MTD device structure
+ * @this: NAND device
  * @offs: offset in the device
  */
-int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs)
+int nand_isreserved_bbt(struct nand_device *this, loff_t offs)
 {
-	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int block;
 
-	block = (int)(offs >> this->bbt_erase_shift);
-	return bbt_get_entry(this, block) == BBT_BLOCK_RESERVED;
+	block = nand_offs_to_eraseblock(this, offs);
+	return bbt_get_entry(this, block) == NAND_BBT_BLOCK_RESERVED;
 }
 
 /**
  * nand_isbad_bbt - [NAND Interface] Check if a block is bad
- * @mtd: MTD device structure
+ * @this: NAND device
  * @offs: offset in the device
  * @allowbbt: allow access to bad block table region
  */
-int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
+int nand_isbad_bbt(struct nand_device *this, loff_t offs, int allowbbt)
 {
-	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int block, res;
 
-	block = (int)(offs >> this->bbt_erase_shift);
+	block = nand_offs_to_eraseblock(this, offs);
 	res = bbt_get_entry(this, block);
 
 	pr_debug("nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
 		 (unsigned int)offs, block, res);
 
 	switch (res) {
-	case BBT_BLOCK_GOOD:
+	case NAND_BBT_BLOCK_GOOD:
 		return 0;
-	case BBT_BLOCK_WORN:
+	case NAND_BBT_BLOCK_WORN:
 		return 1;
-	case BBT_BLOCK_RESERVED:
+	case NAND_BBT_BLOCK_RESERVED:
 		return allowbbt ? 0 : 1;
 	}
 	return 1;
@@ -1431,22 +1415,21 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
 
 /**
  * nand_markbad_bbt - [NAND Interface] Mark a block bad in the BBT
- * @mtd: MTD device structure
+ * @this: NAND device
  * @offs: offset of the bad block
  */
-int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs)
+int nand_markbad_bbt(struct nand_device *this, loff_t offs)
 {
-	struct nand_chip *this = mtd_to_nandchip(mtd);
 	int block, ret = 0;
 
-	block = (int)(offs >> this->bbt_erase_shift);
+	block = nand_offs_to_eraseblock(this, offs);
 
 	/* Mark bad block in memory */
-	bbt_mark_entry(this, block, BBT_BLOCK_WORN);
+	bbt_mark_entry(this, block, NAND_BBT_BLOCK_WORN);
 
 	/* Update flash-based bad block table */
-	if (this->bbt_options & NAND_BBT_USE_FLASH)
-		ret = nand_update_bbt(mtd, offs);
+	if (this->bbt.options & NAND_BBT_USE_FLASH)
+		ret = nand_update_bbt(this, offs);
 
 	return ret;
 }
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 446f941..78931ff 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -566,4 +566,27 @@ static inline struct device_node *nand_get_of_node(struct nand_device *nand)
 {
 	return mtd_get_of_node(&nand->mtd);
 }
+
+/* BBT related functions */
+enum nand_bbt_block_status {
+	NAND_BBT_BLOCK_GOOD,
+	NAND_BBT_BLOCK_WORN,
+	NAND_BBT_BLOCK_RESERVED,
+	NAND_BBT_BLOCK_FACTORY_BAD,
+};
+
+int nand_scan_bbt(struct nand_device *this);
+void nand_release_bbt(struct nand_device *this);
+int nand_update_bbt(struct nand_device *this, loff_t offs);
+int nand_isreserved_bbt(struct nand_device *this, loff_t offs);
+int nand_isbad_bbt(struct nand_device *this, loff_t offs, int allowbbt);
+int nand_markbad_bbt(struct nand_device *this, loff_t offs);
+
+void nand_bbt_update_entry(struct nand_device *this, int eraseblock,
+			   enum nand_bbt_block_status status);
+static inline bool nand_bbt_is_initialized(struct nand_device *this)
+{
+	return !!this->bbt.bbt;
+}
+
 #endif /* __LINUX_MTD_NAND_H */
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 750fac2..04b0954 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -831,7 +831,6 @@ struct rawnand_device {
  * @onfi_set_features:	[REPLACEABLE] set the features for ONFI nand
  * @onfi_get_features:	[REPLACEABLE] get the features for ONFI nand
  * @setup_data_interface: [OPTIONAL] setup the data interface and timing
- * @bbt:		[INTERN] bad block table pointer
  * @bbt_td:		[REPLACEABLE] bad block table descriptor for flash
  *			lookup.
  * @bbt_md:		[REPLACEABLE] bad block table mirror descriptor
@@ -924,7 +923,6 @@ struct nand_chip {
 	unsigned long buf_align;
 	struct nand_hw_control hwcontrol;
 
-	uint8_t *bbt;
 	struct nand_bbt_descr *bbt_td;
 	struct nand_bbt_descr *bbt_md;
 
@@ -1114,10 +1112,6 @@ struct nand_manufacturer {
 extern const struct nand_manufacturer_ops amd_nand_manuf_ops;
 extern const struct nand_manufacturer_ops macronix_nand_manuf_ops;
 
-int nand_default_bbt(struct mtd_info *mtd);
-int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs);
-int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs);
-int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt);
 int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 		    int allowbbt);
 int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 07/15] mtd: nand: move BBT code to drivers/mtd/nand/
  2017-05-24  7:06 [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Peter Pan
                   ` (5 preceding siblings ...)
  2017-05-24  7:07 ` [PATCH v6 06/15] mtd: nand: raw: make BBT code more generic Peter Pan
@ 2017-05-24  7:07 ` Peter Pan
  2017-05-24  7:07 ` [PATCH v6 08/15] mtd: nand: Add the page iterator concept Peter Pan
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 65+ messages in thread
From: Peter Pan @ 2017-05-24  7:07 UTC (permalink / raw)
  To: boris.brezillon, richard, computersforpeace, arnaud.mouiche,
	thomas.petazzoni, marex, cyrille.pitchen, linux-mtd
  Cc: peterpandong, peterpansjtu, linshunquan1

From: Boris Brezillon <boris.brezillon@free-electrons.com>

Now that the BBT code is generic, we can move it to drivers/mtd/nand/.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Peter Pan <peterpandong@micron.com>
---
 drivers/mtd/nand/Kconfig                   | 3 +++
 drivers/mtd/nand/Makefile                  | 4 ++++
 drivers/mtd/nand/{raw/nand_bbt.c => bbt.c} | 5 +++++
 drivers/mtd/nand/raw/Kconfig               | 1 +
 drivers/mtd/nand/raw/Makefile              | 2 +-
 5 files changed, 14 insertions(+), 1 deletion(-)
 rename drivers/mtd/nand/{raw/nand_bbt.c => bbt.c} (99%)

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 6d53734..1c1a1f4 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -1 +1,4 @@
+config MTD_NAND_CORE
+	tristate
+
 source "drivers/mtd/nand/raw/Kconfig"
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index eee2f27..fe430d9 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -1 +1,5 @@
+obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
+
+nandcore-objs :=  bbt.o
+
 obj-y	+= raw/
diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/bbt.c
similarity index 99%
rename from drivers/mtd/nand/raw/nand_bbt.c
rename to drivers/mtd/nand/bbt.c
index 26f5c3f..56115d5 100644
--- a/drivers/mtd/nand/raw/nand_bbt.c
+++ b/drivers/mtd/nand/bbt.c
@@ -1308,6 +1308,7 @@ int nand_scan_bbt(struct nand_device *this)
 	this->bbt.bbt = NULL;
 	return res;
 }
+EXPORT_SYMBOL_GPL(nand_scan_bbt);
 
 /**
  * nand_release_bbt - release bad block table(s)
@@ -1372,6 +1373,7 @@ int nand_update_bbt(struct nand_device *this, loff_t offs)
 	kfree(buf);
 	return res;
 }
+EXPORT_SYMBOL_GPL(nand_update_bbt);
 
 /**
  * nand_isreserved_bbt - [NAND Interface] Check if a block is reserved
@@ -1385,6 +1387,7 @@ int nand_isreserved_bbt(struct nand_device *this, loff_t offs)
 	block = nand_offs_to_eraseblock(this, offs);
 	return bbt_get_entry(this, block) == NAND_BBT_BLOCK_RESERVED;
 }
+EXPORT_SYMBOL_GPL(nand_isreserved_bbt);
 
 /**
  * nand_isbad_bbt - [NAND Interface] Check if a block is bad
@@ -1412,6 +1415,7 @@ int nand_isbad_bbt(struct nand_device *this, loff_t offs, int allowbbt)
 	}
 	return 1;
 }
+EXPORT_SYMBOL_GPL(nand_isbad_bbt);
 
 /**
  * nand_markbad_bbt - [NAND Interface] Mark a block bad in the BBT
@@ -1433,3 +1437,4 @@ int nand_markbad_bbt(struct nand_device *this, loff_t offs)
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(nand_markbad_bbt);
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 0bd2319..d7c97f9 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -14,6 +14,7 @@ menuconfig MTD_NAND
 	tristate "NAND Device Support"
 	depends on MTD
 	select MTD_NAND_ECC
+	select MTD_NAND_CORE
 	help
 	  This enables support for accessing all type of NAND flash
 	  devices. For further information see
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 523d5c1..e9207e3 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -60,7 +60,7 @@ obj-$(CONFIG_MTD_NAND_BRCMNAND)		+= brcmnand/
 obj-$(CONFIG_MTD_NAND_QCOM)		+= qcom_nandc.o
 obj-$(CONFIG_MTD_NAND_MTK)		+= mtk_nand.o mtk_ecc.o
 
-nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o
+nand-objs := nand_base.o nand_timings.o nand_ids.o
 nand-objs += nand_amd.o
 nand-objs += nand_hynix.o
 nand-objs += nand_macronix.o
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 08/15] mtd: nand: Add the page iterator concept
  2017-05-24  7:06 [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Peter Pan
                   ` (6 preceding siblings ...)
  2017-05-24  7:07 ` [PATCH v6 07/15] mtd: nand: move BBT code to drivers/mtd/nand/ Peter Pan
@ 2017-05-24  7:07 ` Peter Pan
  2017-05-29 21:12   ` Boris Brezillon
  2017-05-24  7:07 ` [PATCH v6 09/15] mtd: nand: make sure mtd_oob_ops consistent in bbt Peter Pan
                   ` (7 subsequent siblings)
  15 siblings, 1 reply; 65+ messages in thread
From: Peter Pan @ 2017-05-24  7:07 UTC (permalink / raw)
  To: boris.brezillon, richard, computersforpeace, arnaud.mouiche,
	thomas.petazzoni, marex, cyrille.pitchen, linux-mtd
  Cc: peterpandong, peterpansjtu, linshunquan1

From: Boris Brezillon <boris.brezillon@free-electrons.com>

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Peter Pan <peterpandong@micron.com>
---
 include/linux/mtd/nand.h | 93 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 93 insertions(+)

diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 78931ff..479ff9f 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -78,6 +78,24 @@ struct nand_device {
 };
 
 /**
+ * struct nand_page_iter - NAND page iterator
+ * @page: the page
+ * @pageoffs: the offset within a page
+ * @dataleft: the left page data to read/write
+ * @ooboffs: the offset within page oob
+ * @oobleft: the left oob data to read/write
+ * @oobbytes_per_page: maximun oob bytes to read/write per page
+ */
+struct nand_page_iter {
+	int page;
+	int pageoffs;
+	size_t dataleft;
+	int ooboffs;
+	size_t oobleft;
+	int oobbytes_per_page;
+};
+
+/**
  * mtd_to_nand - Get the NAND device attached to the MTD instance
  * @mtd: MTD instance
  *
@@ -176,6 +194,81 @@ static inline int nand_per_page_oobsize(struct nand_device *nand)
 }
 
 /**
+ * nand_page_iter_init - Initialize a NAND page iterator
+ * @nand: NAND device
+ * @offs: absolute offset
+ * @len: page data length to read/write
+ * @ooboffs: oob offset within page
+ * @ooblen: oob data length to read/write
+ * @oobbytes_per_page: oob data can read/write per page
+ * @iter: page iterator
+ */
+static inline void nand_page_iter_init(struct nand_device *nand,
+				       loff_t offs, size_t len, u32 ooboffs,
+				       size_t ooblen, u32 oobbytes_per_page,
+				       struct nand_page_iter *iter)
+{
+	u64 page = offs;
+
+	iter->pageoffs = do_div(page, nand->memorg.pagesize);
+	iter->page = page;
+	iter->dataleft = len;
+	iter->ooboffs = ooboffs;
+	iter->oobleft = ooblen;
+	iter->oobbytes_per_page = oobbytes_per_page;
+}
+
+/**
+ * nand_page_iter_next - Move to the next page
+ * @nand: NAND device
+ * @iter: page iterator
+ */
+static inline void nand_page_iter_next(struct nand_device *nand,
+				       struct nand_page_iter *iter)
+{
+	iter->page++;
+	iter->pageoffs = 0;
+	if (iter->dataleft)
+		iter->dataleft -= min_t (int,
+					 nand_page_size(nand) - iter->pageoffs,
+					 iter->dataleft);
+	if (iter->oobleft)
+		iter->oobleft -= min_t(int,
+				       iter->oobbytes_per_page - iter->ooboffs,
+				       iter->oobleft);
+}
+
+/**
+ * nand_page_iter_end - Should end iteration or not
+ * @nand: NAND device
+ * @iter: page iterator
+ */
+static inline bool nand_page_iter_end(struct nand_device *nand,
+				      struct nand_page_iter *iter)
+{
+	if (iter->dataleft || iter->oobleft)
+		return false;
+	return true;
+}
+
+/**
+ * nand_for_each_page - Iterate nand pages
+ * @nand: NAND device
+ * @start: start address to read/write
+ * @len: page data length to read/write
+ * @ooboffs: oob offset within page
+ * @ooblen: oob data length to read/write
+ * @oobbytes_per_page: oob data can read/write per page
+ * @iter: page iterator
+ */
+#define nand_for_each_page(nand, start, len, ooboffs, ooblen,	\
+			   oobbytes_per_page, iter)	\
+	for (nand_page_iter_init(nand, start, len, ooboffs, ooblen,	\
+				 oobbytes_per_page, iter);	\
+	     !nand_page_iter_end(nand, iter);		\
+	     nand_page_iter_next(nand, iter))
+
+/**
  * nand_per_page_oobsize - Get NAND erase block size
  * @nand: NAND device
  *
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 09/15] mtd: nand: make sure mtd_oob_ops consistent in bbt
  2017-05-24  7:06 [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Peter Pan
                   ` (7 preceding siblings ...)
  2017-05-24  7:07 ` [PATCH v6 08/15] mtd: nand: Add the page iterator concept Peter Pan
@ 2017-05-24  7:07 ` Peter Pan
  2017-05-29 21:06   ` Boris Brezillon
  2017-05-24  7:07 ` [PATCH v6 10/15] nand: spi: add basic blocks for infrastructure Peter Pan
                   ` (6 subsequent siblings)
  15 siblings, 1 reply; 65+ messages in thread
From: Peter Pan @ 2017-05-24  7:07 UTC (permalink / raw)
  To: boris.brezillon, richard, computersforpeace, arnaud.mouiche,
	thomas.petazzoni, marex, cyrille.pitchen, linux-mtd
  Cc: peterpandong, peterpansjtu, linshunquan1

This commit makes sure struct mtd_oob_ops passed to mtd_read/write_ops()
is consistent, which means .datbuf = NULL and .len = 0 when not reading
page; .oobbuf = NULL and .ooblen = 0 when not reading oob. If no, (ie.
ops.datbuf = NULL, while ops.len != 0.), nand_for_each_page() will run
forever.

Signed-off-by: Peter Pan <peterpandong@micron.com>
---
 drivers/mtd/nand/bbt.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/bbt.c b/drivers/mtd/nand/bbt.c
index 56115d5..96d4e14 100644
--- a/drivers/mtd/nand/bbt.c
+++ b/drivers/mtd/nand/bbt.c
@@ -328,7 +328,7 @@ static int scan_read_oob(struct nand_device *this, uint8_t *buf, loff_t offs,
 			 size_t len)
 {
 	struct mtd_info *mtd = nand_to_mtd(this);
-	struct mtd_oob_ops ops;
+	struct mtd_oob_ops ops = {};
 	int res, ret = 0;
 
 	ops.mode = MTD_OPS_PLACE_OOB;
@@ -369,11 +369,12 @@ static int scan_write_bbt(struct nand_device *this, loff_t offs, size_t len,
 			  uint8_t *buf, uint8_t *oob)
 {
 	struct mtd_info *mtd = nand_to_mtd(this);
-	struct mtd_oob_ops ops;
+	struct mtd_oob_ops ops = {};
 
 	ops.mode = MTD_OPS_PLACE_OOB;
 	ops.ooboffs = 0;
-	ops.ooblen = nand_per_page_oobsize(this);
+	/* oob from caller may be NULL */
+	ops.ooblen = oob ? nand_per_page_oobsize(this) : 0;
 	ops.datbuf = buf;
 	ops.oobbuf = oob;
 	ops.len = len;
@@ -428,13 +429,12 @@ static int scan_block_fast(struct nand_device *this, struct nand_bbt_descr *bd,
 			   loff_t offs, uint8_t *buf, int numpages)
 {
 	struct mtd_info *mtd = nand_to_mtd(this);
-	struct mtd_oob_ops ops;
+	struct mtd_oob_ops ops = {};
 	int j, ret;
 
 	ops.ooblen = nand_per_page_oobsize(this);
 	ops.oobbuf = buf;
 	ops.ooboffs = 0;
-	ops.datbuf = NULL;
 	ops.mode = MTD_OPS_PLACE_OOB;
 
 	for (j = 0; j < numpages; j++) {
@@ -734,11 +734,10 @@ static int write_bbt(struct nand_device *this, uint8_t *buf,
 	uint8_t rcode = td->reserved_block_code;
 	size_t retlen, len = 0;
 	loff_t to;
-	struct mtd_oob_ops ops;
+	struct mtd_oob_ops ops = {};
 
 	ops.ooblen = nand_per_page_oobsize(this);
 	ops.ooboffs = 0;
-	ops.datbuf = NULL;
 	ops.mode = MTD_OPS_PLACE_OOB;
 
 	if (!rcode)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 10/15] nand: spi: add basic blocks for infrastructure
  2017-05-24  7:06 [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Peter Pan
                   ` (8 preceding siblings ...)
  2017-05-24  7:07 ` [PATCH v6 09/15] mtd: nand: make sure mtd_oob_ops consistent in bbt Peter Pan
@ 2017-05-24  7:07 ` Peter Pan
  2017-05-29 21:51   ` Boris Brezillon
  2017-05-31 21:45   ` Cyrille Pitchen
  2017-05-24  7:07 ` [PATCH v6 11/15] nand: spi: add basic operations support Peter Pan
                   ` (5 subsequent siblings)
  15 siblings, 2 replies; 65+ messages in thread
From: Peter Pan @ 2017-05-24  7:07 UTC (permalink / raw)
  To: boris.brezillon, richard, computersforpeace, arnaud.mouiche,
	thomas.petazzoni, marex, cyrille.pitchen, linux-mtd
  Cc: peterpandong, peterpansjtu, linshunquan1

This is the first commit for spi nand framkework.
This commit is to add add basic building blocks
for the SPI NAND infrastructure.

Signed-off-by: Peter Pan <peterpandong@micron.com>
---
 drivers/mtd/nand/Kconfig      |   1 +
 drivers/mtd/nand/Makefile     |   1 +
 drivers/mtd/nand/spi/Kconfig  |   5 +
 drivers/mtd/nand/spi/Makefile |   1 +
 drivers/mtd/nand/spi/core.c   | 419 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/spinand.h   | 267 +++++++++++++++++++++++++++
 6 files changed, 694 insertions(+)
 create mode 100644 drivers/mtd/nand/spi/Kconfig
 create mode 100644 drivers/mtd/nand/spi/Makefile
 create mode 100644 drivers/mtd/nand/spi/core.c
 create mode 100644 include/linux/mtd/spinand.h

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 1c1a1f4..7695fd8 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -2,3 +2,4 @@ config MTD_NAND_CORE
 	tristate
 
 source "drivers/mtd/nand/raw/Kconfig"
+source "drivers/mtd/nand/spi/Kconfig"
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index fe430d9..6221958 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
 nandcore-objs :=  bbt.o
 
 obj-y	+= raw/
+obj-$(CONFIG_MTD_SPI_NAND)	+= spi/
diff --git a/drivers/mtd/nand/spi/Kconfig b/drivers/mtd/nand/spi/Kconfig
new file mode 100644
index 0000000..d77c46e
--- /dev/null
+++ b/drivers/mtd/nand/spi/Kconfig
@@ -0,0 +1,5 @@
+menuconfig MTD_SPI_NAND
+	tristate "SPI NAND device Support"
+	depends on MTD_NAND
+	help
+	  This is the framework for the SPI NAND device drivers.
diff --git a/drivers/mtd/nand/spi/Makefile b/drivers/mtd/nand/spi/Makefile
new file mode 100644
index 0000000..a677a4d
--- /dev/null
+++ b/drivers/mtd/nand/spi/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MTD_SPI_NAND) += core.o
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
new file mode 100644
index 0000000..93ce212
--- /dev/null
+++ b/drivers/mtd/nand/spi/core.c
@@ -0,0 +1,419 @@
+/*
+ *
+ * Copyright (c) 2016-2017 Micron Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/mtd/spinand.h>
+#include <linux/slab.h>
+
+/**
+ * spinand_exec_op - execute SPI NAND operation by controller ->exec_op() hook
+ * @spinand: SPI NAND device structure
+ * @op: pointer to spinand_op struct
+ */
+static inline int spinand_exec_op(struct spinand_device *spinand,
+				  struct spinand_op *op)
+{
+	return spinand->controller.controller->ops->exec_op(spinand, op);
+}
+
+/**
+ * spinand_init_op - initialize spinand_op struct
+ * @op: pointer to spinand_op struct
+ */
+static inline void spinand_init_op(struct spinand_op *op)
+{
+	memset(op, 0, sizeof(struct spinand_op));
+	op->addr_nbits = 1;
+	op->data_nbits = 1;
+}
+
+/**
+ * spinand_read_reg - read SPI NAND register
+ * @spinand: SPI NAND device structure
+ * @reg; register to read
+ * @buf: buffer to store value
+ */
+static int spinand_read_reg(struct spinand_device *spinand, u8 reg, u8 *buf)
+{
+	struct spinand_op op;
+	int ret;
+
+	spinand_init_op(&op);
+	op.cmd = SPINAND_CMD_GET_FEATURE;
+	op.n_addr = 1;
+	op.addr[0] = reg;
+	op.n_rx = 1;
+	op.rx_buf = buf;
+
+	ret = spinand_exec_op(spinand, &op);
+	if (ret < 0)
+		dev_err(spinand->dev, "err: %d read register %d\n", ret, reg);
+
+	return ret;
+}
+
+/**
+ * spinand_write_reg - write SPI NAND register
+ * @spinand: SPI NAND device structure
+ * @reg; register to write
+ * @value: value to write
+ */
+static int spinand_write_reg(struct spinand_device *spinand, u8 reg, u8 value)
+{
+	struct spinand_op op;
+	int ret;
+
+	spinand_init_op(&op);
+	op.cmd = SPINAND_CMD_SET_FEATURE;
+	op.n_addr = 1;
+	op.addr[0] = reg;
+	op.n_tx = 1;
+	op.tx_buf = &value;
+
+	ret = spinand_exec_op(spinand, &op);
+	if (ret < 0)
+		dev_err(spinand->dev, "err: %d write register %d\n", ret, reg);
+
+	return ret;
+}
+
+/**
+ * spinand_read_status - get status register value
+ * @spinand: SPI NAND device structure
+ * @status: buffer to store value
+ * Description:
+ *   After read, write, or erase, the NAND device is expected to set the
+ *   busy status.
+ *   This function is to allow reading the status of the command: read,
+ *   write, and erase.
+ */
+static int spinand_read_status(struct spinand_device *spinand, u8 *status)
+{
+	return spinand_read_reg(spinand, REG_STATUS, status);
+}
+
+/**
+ * spinand_wait - wait until the command is done
+ * @spinand: SPI NAND device structure
+ * @s: buffer to store status register value (can be NULL)
+ */
+static int spinand_wait(struct spinand_device *spinand, u8 *s)
+{
+	unsigned long timeo =  jiffies + msecs_to_jiffies(400);
+	u8 status;
+
+	do {
+		spinand_read_status(spinand, &status);
+		if ((status & STATUS_OIP_MASK) == STATUS_READY)
+			goto out;
+	} while (time_before(jiffies, timeo));
+
+	/*
+	 * Extra read, just in case the STATUS_READY bit has changed
+	 * since our last check
+	 */
+	spinand_read_status(spinand, &status);
+out:
+	if (s)
+		*s = status;
+
+	return (status & STATUS_OIP_MASK) == STATUS_READY ? 0 :	-ETIMEDOUT;
+}
+
+/**
+ * spinand_read_id - read SPI NAND ID
+ * @spinand: SPI NAND device structure
+ * @buf: buffer to store id
+ * Description:
+ *   Manufacturers' read ID method is not unique. Some need a dummy before
+ *   reading, some's ID has three byte.
+ *   This function send one byte opcode (9Fh) and then read
+ *   SPINAND_MAX_ID_LEN (4 currently) bytes. Manufacturer's detect function
+ *   need to filter out real ID from the 4 bytes.
+ */
+static int spinand_read_id(struct spinand_device *spinand, u8 *buf)
+{
+	struct spinand_op op;
+
+	spinand_init_op(&op);
+	op.cmd = SPINAND_CMD_READ_ID;
+	op.n_rx = SPINAND_MAX_ID_LEN;
+	op.rx_buf = buf;
+
+	return spinand_exec_op(spinand, &op);
+}
+
+/**
+ * spinand_reset - reset SPI NAND device
+ * @spinand: SPI NAND device structure
+ */
+static int spinand_reset(struct spinand_device *spinand)
+{
+	struct spinand_op op;
+	int ret;
+
+	spinand_init_op(&op);
+	op.cmd = SPINAND_CMD_RESET;
+
+	ret = spinand_exec_op(spinand, &op);
+	if (ret < 0) {
+		dev_err(spinand->dev, "reset failed!\n");
+		goto out;
+	}
+
+	ret = spinand_wait(spinand, NULL);
+
+out:
+	return ret;
+}
+
+/**
+ * spinand_lock_block - write block lock register to lock/unlock device
+ * @spinand: SPI NAND device structure
+ * @lock: value to set to block lock register
+ */
+static int spinand_lock_block(struct spinand_device *spinand, u8 lock)
+{
+	return spinand_write_reg(spinand, REG_BLOCK_LOCK, lock);
+}
+
+/**
+ * spinand_set_rd_wr_op - choose the best read write command
+ * @spinand: SPI NAND device structure
+ * Description:
+ *   Chose the fastest r/w command according to spi controller's and
+ *   device's ability.
+ */
+static void spinand_set_rd_wr_op(struct spinand_device *spinand)
+{
+	u32 controller_cap = spinand->controller.controller->caps;
+	u32 rw_mode = spinand->rw_mode;
+
+	if ((controller_cap & SPINAND_CAP_RD_QUAD) &&
+	    (rw_mode & SPINAND_RD_QUAD))
+		spinand->read_cache_op = SPINAND_CMD_READ_FROM_CACHE_QUAD_IO;
+	else if ((controller_cap & SPINAND_CAP_RD_X4) &&
+		 (rw_mode & SPINAND_RD_X4))
+		spinand->read_cache_op = SPINAND_CMD_READ_FROM_CACHE_X4;
+	else if ((controller_cap & SPINAND_CAP_RD_DUAL) &&
+		 (rw_mode & SPINAND_RD_DUAL))
+		spinand->read_cache_op = SPINAND_CMD_READ_FROM_CACHE_DUAL_IO;
+	else if ((controller_cap & SPINAND_CAP_RD_X2) &&
+		 (rw_mode & SPINAND_RD_X2))
+		spinand->read_cache_op = SPINAND_CMD_READ_FROM_CACHE_X2;
+	else
+		spinand->read_cache_op = SPINAND_CMD_READ_FROM_CACHE_FAST;
+
+	if ((controller_cap & SPINAND_CAP_WR_X4) &&
+	    (rw_mode & SPINAND_WR_X4))
+		spinand->write_cache_op = SPINAND_CMD_PROG_LOAD_X4;
+	else
+		spinand->write_cache_op = SPINAND_CMD_PROG_LOAD;
+}
+
+static const struct spinand_manufacturer *spinand_manufacturers[] = {};
+
+/**
+ * spinand_manufacturer_detect - detect SPI NAND device by each manufacturer
+ * @spinand: SPI NAND device structure
+ *
+ * ->detect() should decode raw id in spinand->id.data and initialize device
+ * related part in spinand_device structure if it is the right device.
+ * ->detect() can not be NULL.
+ */
+static int spinand_manufacturer_detect(struct spinand_device *spinand)
+{
+	int i = 0;
+
+	for (; i < ARRAY_SIZE(spinand_manufacturers); i++) {
+		if (spinand_manufacturers[i]->ops->detect(spinand)) {
+			spinand->manufacturer.manu = spinand_manufacturers[i];
+
+			return 0;
+		}
+	}
+
+	return -ENODEV;
+}
+
+/**
+ * spinand_manufacturer_init - manufacturer initialization function.
+ * @spinand: SPI NAND device structure
+ *
+ * Manufacturer drivers should put all their specific initialization code in
+ * their ->init() hook.
+ */
+static int spinand_manufacturer_init(struct spinand_device *spinand)
+{
+	if (spinand->manufacturer.manu->ops->init)
+		return spinand->manufacturer.manu->ops->init(spinand);
+
+	return 0;
+}
+
+/**
+ * spinand_manufacturer_cleanup - manufacturer cleanup function.
+ * @spinand: SPI NAND device structure
+ *
+ * Manufacturer drivers should put all their specific cleanup code in their
+ * ->cleanup() hook.
+ */
+static void spinand_manufacturer_cleanup(struct spinand_device *spinand)
+{
+	/* Release manufacturer private data */
+	if (spinand->manufacturer.manu->ops->cleanup)
+		return spinand->manufacturer.manu->ops->cleanup(spinand);
+}
+
+/**
+ * spinand_detect - detect the SPI NAND device
+ * @spinand: SPI NAND device structure
+ */
+static int spinand_detect(struct spinand_device *spinand)
+{
+	struct nand_device *nand = &spinand->base;
+	int ret;
+
+	spinand_reset(spinand);
+	spinand_read_id(spinand, spinand->id.data);
+	spinand->id.len = SPINAND_MAX_ID_LEN;
+
+	ret = spinand_manufacturer_detect(spinand);
+	if (ret) {
+		dev_err(spinand->dev, "unknown raw ID %*phN\n",
+			SPINAND_MAX_ID_LEN, spinand->id.data);
+		goto failed;
+	}
+
+	dev_info(spinand->dev, "%s (%s) is found.\n", spinand->name,
+		 spinand->manufacturer.manu->name);
+	dev_info(spinand->dev,
+		 "%d MiB, block size: %d KiB, page size: %d, OOB size: %d\n",
+		 (int)(nand_size(nand) >> 20), nand_eraseblock_size(nand) >> 10,
+		 nand_page_size(nand), nand_per_page_oobsize(nand));
+
+failed:
+	return ret;
+}
+
+/**
+ * devm_spinand_alloc - [SPI NAND Interface] allocate SPI NAND device instance
+ * @dev: pointer to device model structure
+ */
+struct spinand_device *devm_spinand_alloc(struct device *dev)
+{
+	struct spinand_device *spinand;
+	struct mtd_info *mtd;
+
+	spinand = devm_kzalloc(dev, sizeof(*spinand), GFP_KERNEL);
+	if (!spinand)
+		return ERR_PTR(-ENOMEM);
+
+	spinand_set_of_node(spinand, dev->of_node);
+	mutex_init(&spinand->lock);
+	spinand->dev = dev;
+	mtd = spinand_to_mtd(spinand);
+	mtd->dev.parent = dev;
+
+	return spinand;
+}
+EXPORT_SYMBOL_GPL(devm_spinand_alloc);
+
+/**
+ * spinand_init - [SPI NAND Interface] initialize the SPI NAND device
+ * @spinand: SPI NAND device structure
+ */
+int spinand_init(struct spinand_device *spinand)
+{
+	struct mtd_info *mtd = spinand_to_mtd(spinand);
+	struct nand_device *nand = mtd_to_nand(mtd);
+	int ret;
+
+	ret = spinand_detect(spinand);
+	if (ret) {
+		dev_err(spinand->dev,
+			"Detect SPI NAND failed with error %d.\n", ret);
+		goto err_out;
+	}
+
+	spinand_set_rd_wr_op(spinand);
+
+	/*
+	 * Use kzalloc() instead of devm_kzalloc() here, beacause some drivers
+	 * may use this buffer for DMA access.
+	 * Memory allocated by devm_ does not guarantee DMA-safe alignment.
+	 */
+	spinand->buf = kzalloc(nand_page_size(nand) +
+			       nand_per_page_oobsize(nand),
+			       GFP_KERNEL);
+	if (!spinand->buf) {
+		ret = -ENOMEM;
+		goto err_out;
+	}
+
+	spinand->oobbuf = spinand->buf + nand_page_size(nand);
+
+	ret = spinand_manufacturer_init(spinand);
+	if (ret) {
+		dev_err(spinand->dev,
+			"Manufacurer init SPI NAND failed with err %d.\n",
+			ret);
+		goto err_free_buf;
+	}
+
+	mtd->name = spinand->name;
+	mtd->size = nand_size(nand);
+	mtd->erasesize = nand_eraseblock_size(nand);
+	mtd->writesize = nand_page_size(nand);
+	mtd->writebufsize = mtd->writesize;
+	mtd->owner = THIS_MODULE;
+	mtd->type = MTD_NANDFLASH;
+	mtd->flags = MTD_CAP_NANDFLASH;
+	mtd->oobsize = nand_per_page_oobsize(nand);
+	/*
+	 * Right now, we don't support ECC, so let the whole oob
+	 * area is available for user.
+	 */
+	mtd->oobavail = mtd->oobsize;
+
+	/* After power up, all blocks are locked, so unlock it here. */
+	spinand_lock_block(spinand, BL_ALL_UNLOCKED);
+
+	return 0;
+
+err_free_buf:
+	kfree(spinand->buf);
+err_out:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(spinand_init);
+
+/**
+ * spinand_cleanup - [SPI NAND Interface] clean SPI NAND device
+ * @spinand: SPI NAND device structure
+ */
+void spinand_cleanup(struct spinand_device *spinand)
+{
+	spinand_manufacturer_cleanup(spinand);
+	kfree(spinand->buf);
+}
+EXPORT_SYMBOL_GPL(spinand_cleanup);
+
+MODULE_DESCRIPTION("SPI NAND framework");
+MODULE_AUTHOR("Peter Pan<peterpandong@micron.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
new file mode 100644
index 0000000..dd9da71
--- /dev/null
+++ b/include/linux/mtd/spinand.h
@@ -0,0 +1,267 @@
+/*
+ *
+ * Copyright (c) 2016-2017 Micron Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __LINUX_MTD_SPINAND_H
+#define __LINUX_MTD_SPINAND_H
+
+#include <linux/mutex.h>
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+
+/**
+ * Standard SPI NAND flash commands
+ */
+#define SPINAND_CMD_RESET			0xff
+#define SPINAND_CMD_GET_FEATURE			0x0f
+#define SPINAND_CMD_SET_FEATURE			0x1f
+#define SPINAND_CMD_PAGE_READ			0x13
+#define SPINAND_CMD_READ_FROM_CACHE		0x03
+#define SPINAND_CMD_READ_FROM_CACHE_FAST	0x0b
+#define SPINAND_CMD_READ_FROM_CACHE_X2		0x3b
+#define SPINAND_CMD_READ_FROM_CACHE_DUAL_IO	0xbb
+#define SPINAND_CMD_READ_FROM_CACHE_X4		0x6b
+#define SPINAND_CMD_READ_FROM_CACHE_QUAD_IO	0xeb
+#define SPINAND_CMD_BLK_ERASE			0xd8
+#define SPINAND_CMD_PROG_EXC			0x10
+#define SPINAND_CMD_PROG_LOAD			0x02
+#define SPINAND_CMD_PROG_LOAD_RDM_DATA		0x84
+#define SPINAND_CMD_PROG_LOAD_X4		0x32
+#define SPINAND_CMD_PROG_LOAD_RDM_DATA_X4	0x34
+#define SPINAND_CMD_READ_ID			0x9f
+#define SPINAND_CMD_WR_DISABLE			0x04
+#define SPINAND_CMD_WR_ENABLE			0x06
+
+/* feature register */
+#define REG_BLOCK_LOCK		0xa0
+#define REG_CFG			0xb0
+#define REG_STATUS		0xc0
+
+/* status register */
+#define STATUS_OIP_MASK		BIT(0)
+#define STATUS_CRBSY_MASK	BIT(7)
+#define STATUS_READY		0
+#define STATUS_BUSY		BIT(0)
+
+#define STATUS_E_FAIL_MASK	BIT(2)
+#define STATUS_E_FAIL		BIT(2)
+
+#define STATUS_P_FAIL_MASK	BIT(3)
+#define STATUS_P_FAIL		BIT(3)
+
+/* configuration register */
+#define CFG_ECC_MASK		BIT(4)
+#define CFG_ECC_ENABLE		BIT(4)
+
+/* block lock register */
+#define BL_ALL_UNLOCKED		0X00
+
+struct spinand_op;
+struct spinand_device;
+
+#define SPINAND_MAX_ID_LEN	4
+
+/**
+ * struct spinand_id - SPI NAND id structure
+ * @data: buffer containing the id bytes. Currently 4 bytes large, but can
+ *	  be extended if required.
+ * @len: ID length
+ */
+struct spinand_id {
+	u8 data[SPINAND_MAX_ID_LEN];
+	int len;
+};
+
+/**
+ * struct spinand_controller_ops - SPI NAND controller operations
+ * @exec_op: executute SPI NAND operation
+ */
+struct spinand_controller_ops {
+	int (*exec_op)(struct spinand_device *spinand,
+		       struct spinand_op *op);
+};
+
+/**
+ * struct manufacurer_ops - SPI NAND manufacturer specified operations
+ * @detect: detect SPI NAND device, should bot be NULL.
+ *          ->detect() implementation for manufacturer A never sends
+ *          any manufacturer specific SPI command to a SPI NAND from
+ *          manufacturer B, so the proper way is to decode the raw id
+ *          data in spinand->id.data first, if manufacture ID dismatch,
+ *          return directly and let others to detect.
+ * @init: initialize SPI NAND device.
+ * @cleanup: clean SPI NAND device footprint.
+ */
+struct spinand_manufacturer_ops {
+	bool (*detect)(struct spinand_device *spinand);
+	int (*init)(struct spinand_device *spinand);
+	void (*cleanup)(struct spinand_device *spinand);
+};
+
+/**
+ * struct spinand_manufacturer - SPI NAND manufacturer instance
+ * @id: manufacturer ID
+ * @name: manufacturer name
+ * @ops: point to manufacturer operations
+ */
+struct spinand_manufacturer {
+	u8 id;
+	char *name;
+	const struct spinand_manufacturer_ops *ops;
+};
+
+#define SPINAND_CAP_RD_X1	BIT(0)
+#define SPINAND_CAP_RD_X2	BIT(1)
+#define SPINAND_CAP_RD_X4	BIT(2)
+#define SPINAND_CAP_RD_DUAL	BIT(3)
+#define SPINAND_CAP_RD_QUAD	BIT(4)
+#define SPINAND_CAP_WR_X1	BIT(5)
+#define SPINAND_CAP_WR_X2	BIT(6)
+#define SPINAND_CAP_WR_X4	BIT(7)
+#define SPINAND_CAP_WR_DUAL	BIT(8)
+#define SPINAND_CAP_WR_QUAD	BIT(9)
+
+/**
+ * struct spinand_controller - SPI NAND controller instance
+ * @ops: point to controller operations
+ * @caps: controller capabilities
+ */
+struct spinand_controller {
+	struct spinand_controller_ops *ops;
+	u32 caps;
+};
+
+/**
+ * struct spinand_device - SPI NAND device instance
+ * @base: NAND device instance
+ * @lock: protection lock
+ * @name: name of the device
+ * @dev: struct device pointer
+ * @id: ID structure
+ * @read_cache_op: Opcode of read from cache
+ * @write_cache_op: Opcode of program load
+ * @buf: buffer for read/write data
+ * @oobbuf: buffer for read/write oob
+ * @rw_mode: read/write mode of SPI NAND device
+ * @controller: SPI NAND controller instance
+ * @manufacturer: SPI NAND manufacturer instance, describe
+ *                manufacturer related objects
+ */
+struct spinand_device {
+	struct nand_device base;
+	struct mutex lock;
+	char *name;
+	struct device *dev;
+	struct spinand_id id;
+	u8 read_cache_op;
+	u8 write_cache_op;
+	u8 *buf;
+	u8 *oobbuf;
+	u32 rw_mode;
+	struct {
+		struct spinand_controller *controller;
+		void *priv;
+	} controller;
+	struct {
+		const struct spinand_manufacturer *manu;
+		void *priv;
+	} manufacturer;
+};
+
+/**
+ * mtd_to_spinand - Get the SPI NAND device attached to the MTD instance
+ * @mtd: MTD instance
+ *
+ * Returns the SPI NAND device attached to @mtd.
+ */
+static inline struct spinand_device *mtd_to_spinand(struct mtd_info *mtd)
+{
+	return container_of(mtd_to_nand(mtd), struct spinand_device, base);
+}
+
+/**
+ * spinand_to_mtd - Get the MTD device attached to the SPI NAND device
+ * @spinand: SPI NAND device
+ *
+ * Returns the MTD device attached to @spinand.
+ */
+static inline struct mtd_info *spinand_to_mtd(struct spinand_device *spinand)
+{
+	return nand_to_mtd(&spinand->base);
+}
+
+/**
+ * spinand_set_of_node - Attach a DT node to a SPI NAND device
+ * @spinand: SPI NAND device
+ * @np: DT node
+ *
+ * Attach a DT node to a SPI NAND device.
+ */
+static inline void spinand_set_of_node(struct spinand_device *spinand,
+				       struct device_node *np)
+{
+	nand_set_of_node(&spinand->base, np);
+}
+
+#define SPINAND_MAX_ADDR_LEN	4
+
+/**
+ * struct spinand_op - SPI NAND operation description
+ * @cmd: opcode to send
+ * @n_addr: address bytes
+ * @addr_nbits: number of bit used to transfer address
+ * @dummy_types: dummy bytes followed address
+ * @addr: buffer held address
+ * @n_tx: size of tx_buf
+ * @tx_buf: data to be written
+ * @n_rx: size of rx_buf
+ * @rx_buf: data to be read
+ * @data_nbits: number of bit used to transfer data
+ */
+struct spinand_op {
+	u8 cmd;
+	u8 n_addr;
+	u8 addr_nbits;
+	u8 dummy_bytes;
+	u8 addr[SPINAND_MAX_ADDR_LEN];
+	u32 n_tx;
+	const u8 *tx_buf;
+	u32 n_rx;
+	u8 *rx_buf;
+	u8 data_nbits;
+};
+
+/* SPI NAND supported OP mode */
+#define SPINAND_RD_X1		BIT(0)
+#define SPINAND_RD_X2		BIT(1)
+#define SPINAND_RD_X4		BIT(2)
+#define SPINAND_RD_DUAL		BIT(3)
+#define SPINAND_RD_QUAD		BIT(4)
+#define SPINAND_WR_X1		BIT(5)
+#define SPINAND_WR_X2		BIT(6)
+#define SPINAND_WR_X4		BIT(7)
+#define SPINAND_WR_DUAL		BIT(8)
+#define SPINAND_WR_QUAD		BIT(9)
+
+#define SPINAND_RD_COMMON	(SPINAND_RD_X1 | SPINAND_RD_X2 | \
+				 SPINAND_RD_X4 | SPINAND_RD_DUAL | \
+				 SPINAND_RD_QUAD)
+#define SPINAND_WR_COMMON	(SPINAND_WR_X1 | SPINAND_WR_X4)
+#define SPINAND_OP_COMMON	(SPINAND_RD_COMMON | SPINAND_WR_COMMON)
+
+struct spinand_device *devm_spinand_alloc(struct device *dev);
+int spinand_init(struct spinand_device *spinand);
+void spinand_cleanup(struct spinand_device *spinand);
+#endif /* __LINUX_MTD_SPINAND_H */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 11/15] nand: spi: add basic operations support
  2017-05-24  7:06 [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Peter Pan
                   ` (9 preceding siblings ...)
  2017-05-24  7:07 ` [PATCH v6 10/15] nand: spi: add basic blocks for infrastructure Peter Pan
@ 2017-05-24  7:07 ` Peter Pan
  2017-05-29 22:11   ` Boris Brezillon
  2017-10-11 13:35   ` Boris Brezillon
  2017-05-24  7:07 ` [PATCH v6 12/15] nand: spi: Add bad block support Peter Pan
                   ` (4 subsequent siblings)
  15 siblings, 2 replies; 65+ messages in thread
From: Peter Pan @ 2017-05-24  7:07 UTC (permalink / raw)
  To: boris.brezillon, richard, computersforpeace, arnaud.mouiche,
	thomas.petazzoni, marex, cyrille.pitchen, linux-mtd
  Cc: peterpandong, peterpansjtu, linshunquan1

This commit is to support read, readoob, write,
writeoob and erase operations in the new spi nand
framework. No ECC support right now.

Signed-off-by: Peter Pan <peterpandong@micron.com>
---
 drivers/mtd/nand/spi/core.c | 638 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/spinand.h |   3 +
 2 files changed, 641 insertions(+)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 93ce212..6251469 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -108,6 +108,222 @@ static int spinand_read_status(struct spinand_device *spinand, u8 *status)
 }
 
 /**
+ * spinand_get_cfg - get configuration register value
+ * @spinand: SPI NAND device structure
+ * @cfg: buffer to store value
+ * Description:
+ *   Configuration register includes OTP config, Lock Tight enable/disable
+ *   and Internal ECC enable/disable.
+ */
+static int spinand_get_cfg(struct spinand_device *spinand, u8 *cfg)
+{
+	return spinand_read_reg(spinand, REG_CFG, cfg);
+}
+
+/**
+ * spinand_set_cfg - set value to configuration register
+ * @spinand: SPI NAND device structure
+ * @cfg: value to set
+ * Description:
+ *   Configuration register includes OTP config, Lock Tight enable/disable
+ *   and Internal ECC enable/disable.
+ */
+static int spinand_set_cfg(struct spinand_device *spinand, u8 cfg)
+{
+	return spinand_write_reg(spinand, REG_CFG, cfg);
+}
+
+/**
+ * spinand_disable_ecc - disable internal ECC
+ * @spinand: SPI NAND device structure
+ */
+static void spinand_disable_ecc(struct spinand_device *spinand)
+{
+	u8 cfg = 0;
+
+	spinand_get_cfg(spinand, &cfg);
+
+	if ((cfg & CFG_ECC_MASK) == CFG_ECC_ENABLE) {
+		cfg &= ~CFG_ECC_ENABLE;
+		spinand_set_cfg(spinand, cfg);
+	}
+}
+
+/**
+ * spinand_write_enable - send command 06h to enable write or erase the
+ * NAND cells
+ * @spinand: SPI NAND device structure
+ */
+static int spinand_write_enable(struct spinand_device *spinand)
+{
+	struct spinand_op op;
+
+	spinand_init_op(&op);
+	op.cmd = SPINAND_CMD_WR_ENABLE;
+
+	return spinand_exec_op(spinand, &op);
+}
+
+/**
+ * spinand_read_page_to_cache - send command 13h to read data from NAND array
+ * to cache
+ * @spinand: SPI NAND device structure
+ * @page_addr: page to read
+ */
+static int spinand_read_page_to_cache(struct spinand_device *spinand,
+				      u32 page_addr)
+{
+	struct spinand_op op;
+
+	spinand_init_op(&op);
+	op.cmd = SPINAND_CMD_PAGE_READ;
+	op.n_addr = 3;
+	op.addr[0] = (u8)(page_addr >> 16);
+	op.addr[1] = (u8)(page_addr >> 8);
+	op.addr[2] = (u8)page_addr;
+
+	return spinand_exec_op(spinand, &op);
+}
+
+/**
+ * spinand_get_address_bits - return address should be transferred
+ * by how many bits
+ * @opcode: command's operation code
+ */
+static int spinand_get_address_bits(u8 opcode)
+{
+	switch (opcode) {
+	case SPINAND_CMD_READ_FROM_CACHE_QUAD_IO:
+		return 4;
+	case SPINAND_CMD_READ_FROM_CACHE_DUAL_IO:
+		return 2;
+	default:
+		return 1;
+	}
+}
+
+/**
+ * spinand_get_data_bits - return data should be transferred by how many bits
+ * @opcode: command's operation code
+ */
+static int spinand_get_data_bits(u8 opcode)
+{
+	switch (opcode) {
+	case SPINAND_CMD_READ_FROM_CACHE_QUAD_IO:
+	case SPINAND_CMD_READ_FROM_CACHE_X4:
+	case SPINAND_CMD_PROG_LOAD_X4:
+	case SPINAND_CMD_PROG_LOAD_RDM_DATA_X4:
+		return 4;
+	case SPINAND_CMD_READ_FROM_CACHE_DUAL_IO:
+	case SPINAND_CMD_READ_FROM_CACHE_X2:
+		return 2;
+	default:
+		return 1;
+	}
+}
+
+/**
+ * spinand_read_from_cache - read data out from cache register
+ * @spinand: SPI NAND device structure
+ * @page_addr: page to read
+ * @column: the location to read from the cache
+ * @len: number of bytes to read
+ * @rbuf: buffer held @len bytes
+ */
+static int spinand_read_from_cache(struct spinand_device *spinand,
+				   u32 page_addr, u32 column,
+				   size_t len, u8 *rbuf)
+{
+	struct spinand_op op;
+
+	spinand_init_op(&op);
+	op.cmd = spinand->read_cache_op;
+	op.n_addr = 2;
+	op.addr[0] = (u8)(column >> 8);
+	op.addr[1] = (u8)column;
+	op.addr_nbits = spinand_get_address_bits(spinand->read_cache_op);
+	op.n_rx = len;
+	op.rx_buf = rbuf;
+	op.data_nbits = spinand_get_data_bits(spinand->read_cache_op);
+
+	if (spinand->manufacturer.manu->ops->prepare_op)
+		spinand->manufacturer.manu->ops->prepare_op(spinand, &op,
+							    page_addr, column);
+
+	return spinand_exec_op(spinand, &op);
+}
+
+/**
+ * spinand_write_to_cache - write data to cache register
+ * @spinand: SPI NAND device structure
+ * @page_addr: page to write
+ * @column: the location to write to the cache
+ * @len: number of bytes to write
+ * @wrbuf: buffer held @len bytes
+ */
+static int spinand_write_to_cache(struct spinand_device *spinand, u32 page_addr,
+				  u32 column, size_t len, const u8 *wbuf)
+{
+	struct spinand_op op;
+
+	spinand_init_op(&op);
+	op.cmd = spinand->write_cache_op;
+	op.n_addr = 2;
+	op.addr[0] = (u8)(column >> 8);
+	op.addr[1] = (u8)column;
+	op.addr_nbits = spinand_get_address_bits(spinand->write_cache_op);
+	op.n_tx = len;
+	op.tx_buf = wbuf;
+	op.data_nbits = spinand_get_data_bits(spinand->write_cache_op);
+
+	if (spinand->manufacturer.manu->ops->prepare_op)
+		spinand->manufacturer.manu->ops->prepare_op(spinand, &op,
+							    page_addr, column);
+
+	return spinand_exec_op(spinand, &op);
+}
+
+/**
+ * spinand_program_execute - send command 10h to write a page from
+ * cache to the NAND array
+ * @spinand: SPI NAND device structure
+ * @page_addr: the physical page location to write the page.
+ */
+static int spinand_program_execute(struct spinand_device *spinand,
+				   u32 page_addr)
+{
+	struct spinand_op op;
+
+	spinand_init_op(&op);
+	op.cmd = SPINAND_CMD_PROG_EXC;
+	op.n_addr = 3;
+	op.addr[0] = (u8)(page_addr >> 16);
+	op.addr[1] = (u8)(page_addr >> 8);
+	op.addr[2] = (u8)page_addr;
+
+	return spinand_exec_op(spinand, &op);
+}
+
+/**
+ * spinand_erase_block_erase - send command D8h to erase a block
+ * @spinand: SPI NAND device structure
+ * @page_addr: the start page address of block to be erased.
+ */
+static int spinand_erase_block(struct spinand_device *spinand, u32 page_addr)
+{
+	struct spinand_op op;
+
+	spinand_init_op(&op);
+	op.cmd = SPINAND_CMD_BLK_ERASE;
+	op.n_addr = 3;
+	op.addr[0] = (u8)(page_addr >> 16);
+	op.addr[1] = (u8)(page_addr >> 8);
+	op.addr[2] = (u8)page_addr;
+
+	return spinand_exec_op(spinand, &op);
+}
+
+/**
  * spinand_wait - wait until the command is done
  * @spinand: SPI NAND device structure
  * @s: buffer to store status register value (can be NULL)
@@ -193,6 +409,415 @@ static int spinand_lock_block(struct spinand_device *spinand, u8 lock)
 }
 
 /**
+ * spinand_do_read_page - read page from device to buffer
+ * @mtd: MTD device structure
+ * @page_addr: page address/raw address
+ * @oob_only: read OOB only or the whole page
+ */
+static int spinand_do_read_page(struct mtd_info *mtd, u32 page_addr,
+				bool oob_only)
+{
+	struct spinand_device *spinand = mtd_to_spinand(mtd);
+	struct nand_device *nand = mtd_to_nand(mtd);
+	int ret;
+
+	spinand_read_page_to_cache(spinand, page_addr);
+
+	ret = spinand_wait(spinand, NULL);
+	if (ret < 0) {
+		dev_err(spinand->dev, "error %d waiting page 0x%x to cache\n",
+			ret, page_addr);
+		return ret;
+	}
+
+	if (!oob_only)
+		spinand_read_from_cache(spinand, page_addr, 0,
+					nand_page_size(nand) +
+					nand_per_page_oobsize(nand),
+					spinand->buf);
+	else
+		spinand_read_from_cache(spinand, page_addr,
+					nand_page_size(nand),
+					nand_per_page_oobsize(nand),
+					spinand->oobbuf);
+
+	return 0;
+}
+
+/**
+ * spinand_do_write_page - write data from buffer to device
+ * @mtd: MTD device structure
+ * @page_addr: page address/raw address
+ * @oob_only: write OOB only or the whole page
+ */
+static int spinand_do_write_page(struct mtd_info *mtd, u32 page_addr,
+				 bool oob_only)
+{
+	struct spinand_device *spinand = mtd_to_spinand(mtd);
+	struct nand_device *nand = mtd_to_nand(mtd);
+	u8 status;
+	int ret = 0;
+
+	spinand_write_enable(spinand);
+
+	if (!oob_only)
+		spinand_write_to_cache(spinand, page_addr, 0,
+				       nand_page_size(nand) +
+				       nand_per_page_oobsize(nand),
+				       spinand->buf);
+	else
+		spinand_write_to_cache(spinand, page_addr, nand_page_size(nand),
+				       nand_per_page_oobsize(nand),
+				       spinand->oobbuf);
+
+	spinand_program_execute(spinand, page_addr);
+
+	ret = spinand_wait(spinand, &status);
+	if (ret < 0) {
+		dev_err(spinand->dev, "error %d reading page 0x%x from cache\n",
+			ret, page_addr);
+		return ret;
+	}
+
+	if ((status & STATUS_P_FAIL_MASK) == STATUS_P_FAIL) {
+		dev_err(spinand->dev, "program page 0x%x failed\n", page_addr);
+		ret = -EIO;
+	}
+
+	return ret;
+}
+
+/**
+ * spinand_read_pages - read data from device to buffer
+ * @mtd: MTD device structure
+ * @from: offset to read from
+ * @ops: oob operations description structure
+ */
+static int spinand_read_pages(struct mtd_info *mtd, loff_t from,
+			      struct mtd_oob_ops *ops)
+{
+	struct spinand_device *spinand = mtd_to_spinand(mtd);
+	struct nand_device *nand = mtd_to_nand(mtd);
+	int size, ret;
+	int ooblen = mtd->oobsize;
+	bool oob_only = !ops->datbuf;
+	struct nand_page_iter iter;
+
+	ops->retlen = 0;
+	ops->oobretlen = 0;
+
+	nand_for_each_page(nand, from, ops->len, ops->ooboffs, ops->ooblen,
+			   ooblen, &iter) {
+		ret = spinand_do_read_page(mtd, iter.page, oob_only);
+		if (ret)
+			break;
+
+		if (ops->datbuf) {
+			size = min_t(int, iter.dataleft,
+				     nand_page_size(nand) - iter.pageoffs);
+			memcpy(ops->datbuf + ops->retlen,
+			       spinand->buf + iter.pageoffs, size);
+			ops->retlen += size;
+		}
+
+		if (ops->oobbuf) {
+			size = min_t(int, iter.oobleft, ooblen);
+			memcpy(ops->oobbuf + ops->oobretlen,
+			       spinand->oobbuf + ops->ooboffs, size);
+			ops->oobretlen += size;
+		}
+	}
+
+	return ret;
+}
+
+/**
+ * spinand_do_read_ops - read data from device to buffer
+ * @mtd: MTD device structure
+ * @from: offset to read from
+ * @ops: oob operations description structure
+ */
+static int spinand_do_read_ops(struct mtd_info *mtd, loff_t from,
+			       struct mtd_oob_ops *ops)
+{
+	struct spinand_device *spinand = mtd_to_spinand(mtd);
+	struct nand_device *nand = mtd_to_nand(mtd);
+	int ret;
+
+	ret = nand_check_address(nand, from);
+	if (ret) {
+		dev_err(spinand->dev, "%s: invalid read address\n", __func__);
+		return ret;
+	}
+
+	ret = nand_check_oob_ops(nand, from, ops);
+	if (ret) {
+		dev_err(spinand->dev,
+			"%s: invalid oob operation input\n", __func__);
+		return ret;
+	}
+
+	mutex_lock(&spinand->lock);
+	ret = spinand_read_pages(mtd, from, ops);
+	mutex_unlock(&spinand->lock);
+
+	return ret;
+}
+
+/**
+ * spinand_write_pages - write data from buffer to device
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @ops: oob operations description structure
+ */
+static int spinand_write_pages(struct mtd_info *mtd, loff_t to,
+			       struct mtd_oob_ops *ops)
+{
+	struct spinand_device *spinand = mtd_to_spinand(mtd);
+	struct nand_device *nand = mtd_to_nand(mtd);
+	int ret = 0;
+	int size = 0;
+	int oob_size = 0;
+	int ooblen = mtd->oobsize;
+	bool oob_only = !ops->datbuf;
+	struct nand_page_iter iter;
+
+	ops->retlen = 0;
+	ops->oobretlen = 0;
+
+	nand_for_each_page(nand, to, ops->len, ops->ooboffs, ops->ooblen,
+			   ooblen, &iter) {
+		memset(spinand->buf, 0xff,
+		       nand_page_size(nand) + nand_per_page_oobsize(nand));
+
+		if (ops->oobbuf) {
+			oob_size = min_t(int, iter.oobleft, ooblen);
+			memcpy(spinand->oobbuf + ops->ooboffs,
+			       ops->oobbuf + ops->oobretlen, oob_size);
+		}
+
+		if (ops->datbuf) {
+			size = min_t(int, iter.dataleft,
+				     nand_page_size(nand) - iter.pageoffs);
+			memcpy(spinand->buf + iter.pageoffs,
+			       ops->datbuf + ops->retlen, size);
+		}
+
+		ret = spinand_do_write_page(mtd, iter.page, oob_only);
+		if (ret) {
+			dev_err(spinand->dev, "error %d writing page 0x%x\n",
+				ret, iter.page);
+			return ret;
+		}
+
+		if (ops->datbuf)
+			ops->retlen += size;
+
+		if (ops->oobbuf)
+			ops->oobretlen += oob_size;
+	}
+
+	return ret;
+}
+
+/**
+ * spinand_do_write_ops - write data from buffer to device
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @ops: oob operations description structure
+ */
+static int spinand_do_write_ops(struct mtd_info *mtd, loff_t to,
+				struct mtd_oob_ops *ops)
+{
+	struct spinand_device *spinand = mtd_to_spinand(mtd);
+	struct nand_device *nand = mtd_to_nand(mtd);
+	int ret = 0;
+
+	ret = nand_check_address(nand, to);
+	if (ret) {
+		dev_err(spinand->dev, "%s: invalid write address\n", __func__);
+		return ret;
+	}
+
+	ret = nand_check_oob_ops(nand, to, ops);
+	if (ret) {
+		dev_err(spinand->dev,
+			"%s: invalid oob operation input\n", __func__);
+		return ret;
+	}
+
+	if (nand_oob_ops_across_page(mtd_to_nand(mtd), ops)) {
+		dev_err(spinand->dev,
+			"%s: try to across page when writing with OOB\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&spinand->lock);
+	ret = spinand_write_pages(mtd, to, ops);
+	mutex_unlock(&spinand->lock);
+
+	return ret;
+}
+
+/**
+ * spinand_read - [MTD Interface] read page data
+ * @mtd: MTD device structure
+ * @from: offset to read from
+ * @len: number of bytes to read
+ * @retlen: pointer to variable to store the number of read bytes
+ * @buf: the databuffer to put data
+ */
+static int spinand_read(struct mtd_info *mtd, loff_t from, size_t len,
+			size_t *retlen, u8 *buf)
+{
+	struct mtd_oob_ops ops;
+	int ret;
+
+	memset(&ops, 0, sizeof(ops));
+	ops.len = len;
+	ops.datbuf = buf;
+	ops.mode = MTD_OPS_PLACE_OOB;
+	ret = spinand_do_read_ops(mtd, from, &ops);
+	*retlen = ops.retlen;
+
+	return ret;
+}
+
+/**
+ * spinand_write - [MTD Interface] write page data
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @len: number of bytes to write
+ * @retlen: pointer to variable to store the number of written bytes
+ * @buf: the data to write
+ */
+static int spinand_write(struct mtd_info *mtd, loff_t to, size_t len,
+			 size_t *retlen, const u8 *buf)
+{
+	struct mtd_oob_ops ops;
+	int ret;
+
+	memset(&ops, 0, sizeof(ops));
+	ops.len = len;
+	ops.datbuf = (uint8_t *)buf;
+	ops.mode = MTD_OPS_PLACE_OOB;
+	ret =  spinand_do_write_ops(mtd, to, &ops);
+	*retlen = ops.retlen;
+
+	return ret;
+}
+
+/**
+ * spinand_read_oob - [MTD Interface] read page data and/or out-of-band
+ * @mtd: MTD device structure
+ * @from: offset to read from
+ * @ops: oob operation description structure
+ */
+static int spinand_read_oob(struct mtd_info *mtd, loff_t from,
+			    struct mtd_oob_ops *ops)
+{
+	int ret = -ENOTSUPP;
+
+	ops->retlen = 0;
+	switch (ops->mode) {
+	case MTD_OPS_PLACE_OOB:
+	case MTD_OPS_AUTO_OOB:
+	case MTD_OPS_RAW:
+		ret = spinand_do_read_ops(mtd, from, ops);
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * spinand_write_oob - [MTD Interface] write page data and/or out-of-band
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @ops: oob operation description structure
+ */
+static int spinand_write_oob(struct mtd_info *mtd, loff_t to,
+			     struct mtd_oob_ops *ops)
+{
+	int ret = -ENOTSUPP;
+
+	ops->retlen = 0;
+	switch (ops->mode) {
+	case MTD_OPS_PLACE_OOB:
+	case MTD_OPS_AUTO_OOB:
+	case MTD_OPS_RAW:
+		ret = spinand_do_write_ops(mtd, to, ops);
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * spinand_erase - [MTD Interface] erase block(s)
+ * @mtd: MTD device structure
+ * @einfo: erase instruction
+ */
+static int spinand_erase(struct mtd_info *mtd, struct erase_info *einfo)
+{
+	struct spinand_device *spinand = mtd_to_spinand(mtd);
+	struct nand_device *nand = mtd_to_nand(mtd);
+	loff_t offs = einfo->addr, len = einfo->len;
+	u8 status;
+	int ret;
+
+	ret = nand_check_erase_ops(nand, einfo);
+	if (ret) {
+		dev_err(spinand->dev, "invalid erase operation input\n");
+		return ret;
+	}
+
+	mutex_lock(&spinand->lock);
+	einfo->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
+	einfo->state = MTD_ERASING;
+
+	while (len) {
+		spinand_write_enable(spinand);
+		spinand_erase_block(spinand, nand_offs_to_page(nand, offs));
+
+		ret = spinand_wait(spinand, &status);
+		if (ret < 0) {
+			dev_err(spinand->dev,
+				"block erase command wait failed\n");
+			einfo->state = MTD_ERASE_FAILED;
+			goto erase_exit;
+		}
+
+		if ((status & STATUS_E_FAIL_MASK) == STATUS_E_FAIL) {
+			dev_err(spinand->dev,
+				"erase block 0x%012llx failed\n", offs);
+			einfo->state = MTD_ERASE_FAILED;
+			einfo->fail_addr = offs;
+			goto erase_exit;
+		}
+
+		/* Increment page address and decrement length */
+		len -= nand_eraseblock_size(nand);
+		offs += nand_eraseblock_size(nand);
+	}
+
+	einfo->state = MTD_ERASE_DONE;
+
+erase_exit:
+
+	ret = einfo->state == MTD_ERASE_DONE ? 0 : -EIO;
+
+	mutex_unlock(&spinand->lock);
+
+	/* Do call back function */
+	if (!ret)
+		mtd_erase_callback(einfo);
+
+	return ret;
+}
+
+/**
  * spinand_set_rd_wr_op - choose the best read write command
  * @spinand: SPI NAND device structure
  * Description:
@@ -390,9 +1015,22 @@ int spinand_init(struct spinand_device *spinand)
 	 * area is available for user.
 	 */
 	mtd->oobavail = mtd->oobsize;
+	mtd->_erase = spinand_erase;
+	/*
+	 * Since no ECC support right now, so for spinand_read(),
+	 * spinand_write(), spinand_read_oob() and spinand_write_oob()
+	 * both MTD_OPS_PLACE_OOB and MTD_OPS_AUTO_OOB are treated as
+	 * MTD_OPS_RAW.
+	 */
+	mtd->_read = spinand_read;
+	mtd->_write = spinand_write;
+	mtd->_read_oob = spinand_read_oob;
+	mtd->_write_oob = spinand_write_oob;
 
 	/* After power up, all blocks are locked, so unlock it here. */
 	spinand_lock_block(spinand, BL_ALL_UNLOCKED);
+	/* Right now, we don't support ECC, so disable on-die ECC */
+	spinand_disable_ecc(spinand);
 
 	return 0;
 
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index dd9da71..04ad1dd 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -103,11 +103,14 @@ struct spinand_controller_ops {
  *          return directly and let others to detect.
  * @init: initialize SPI NAND device.
  * @cleanup: clean SPI NAND device footprint.
+ * @prepare_op: prepara read/write operation.
  */
 struct spinand_manufacturer_ops {
 	bool (*detect)(struct spinand_device *spinand);
 	int (*init)(struct spinand_device *spinand);
 	void (*cleanup)(struct spinand_device *spinand);
+	void (*prepare_op)(struct spinand_device *spinand,
+			   struct spinand_op *op, u32 page, u32 column);
 };
 
 /**
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 12/15] nand: spi: Add bad block support
  2017-05-24  7:06 [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Peter Pan
                   ` (10 preceding siblings ...)
  2017-05-24  7:07 ` [PATCH v6 11/15] nand: spi: add basic operations support Peter Pan
@ 2017-05-24  7:07 ` Peter Pan
  2017-05-24  7:07 ` [PATCH v6 13/15] nand: spi: add Micron spi nand support Peter Pan
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 65+ messages in thread
From: Peter Pan @ 2017-05-24  7:07 UTC (permalink / raw)
  To: boris.brezillon, richard, computersforpeace, arnaud.mouiche,
	thomas.petazzoni, marex, cyrille.pitchen, linux-mtd
  Cc: peterpandong, peterpansjtu, linshunquan1

Add isbad and markbad support for SPI NAND. And do not
erase bad blocks in spi_nand_erase. BBT is also enabled
in this patch.

Signed-off-by: Peter Pan <peterpandong@micron.com>
---
 drivers/mtd/nand/spi/core.c | 328 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 325 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 6251469..345d04f 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -19,6 +19,10 @@
 #include <linux/jiffies.h>
 #include <linux/mtd/spinand.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+
+static int spinand_erase_skip_bbt(struct mtd_info *mtd,
+				  struct erase_info *einfo);
 
 /**
  * spinand_exec_op - execute SPI NAND operation by controller ->exec_op() hook
@@ -755,11 +759,154 @@ static int spinand_write_oob(struct mtd_info *mtd, loff_t to,
 }
 
 /**
- * spinand_erase - [MTD Interface] erase block(s)
+ * spinand_block_bad - check if block at offset is bad by bad block marker
+ * @mtd: MTD device structure
+ * @offs: offset from device start
+ */
+static int spinand_block_bad(struct mtd_info *mtd, loff_t offs)
+{
+	struct nand_device *nand = mtd_to_nand(mtd);
+	struct mtd_oob_ops ops = {0};
+	u32 block_addr;
+	u8 bad[2] = {0, 0};
+	u8 ret = 0;
+
+	block_addr = nand_offs_to_eraseblock(nand, offs);
+	ops.mode = MTD_OPS_PLACE_OOB;
+	ops.ooblen = 2;
+	ops.oobbuf = bad;
+	spinand_read_pages(mtd, nand_eraseblock_to_offs(nand, block_addr),
+			   &ops);
+
+	if (bad[0] != 0xFF || bad[1] != 0xFF)
+		ret =  1;
+
+	return ret;
+}
+
+/**
+ * spinand_block_checkbad - check if a block is marked bad
+ * @mtd: MTD device structure
+ * @offs: offset from device start
+ * @allowbbt: 1, if allowe to access the bbt area
+ * Description:
+ *   Check, if the block is bad. Either by reading the bad block table or
+ *   reading bad block marker.
+ */
+static int spinand_block_checkbad(struct mtd_info *mtd, loff_t offs,
+				  int allowbbt)
+{
+	struct nand_device *nand = mtd_to_nand(mtd);
+	int ret;
+
+	if (nand_bbt_is_initialized(nand))
+		ret = nand_isbad_bbt(nand, offs, allowbbt);
+	else
+		ret = spinand_block_bad(mtd, offs);
+
+	return ret;
+}
+
+/**
+ * spinand_block_isbad - [MTD Interface] check if block at offset is bad
+ * @mtd: MTD device structure
+ * @offs: offset from device start
+ */
+static int spinand_block_isbad(struct mtd_info *mtd, loff_t offs)
+{
+	struct spinand_device *spinand = mtd_to_spinand(mtd);
+	int ret;
+
+	mutex_lock(&spinand->lock);
+	ret = spinand_block_checkbad(mtd, offs, 0);
+	mutex_unlock(&spinand->lock);
+
+	return ret;
+}
+
+/**
+ * spinand_block_markbad_lowlevel - mark a block bad
+ * @mtd: MTD device structure
+ * @offs: offset from device start
+ *
+ * This function performs the generic bad block marking steps (i.e., bad
+ * block table(s) and/or marker(s)).
+ *
+ * We try operations in the following order:
+ *  (1) erase the affected block, to allow OOB marker to be written cleanly
+ *  (2) write bad block marker to OOB area of affected block (unless flag
+ *      NAND_BBT_NO_OOB_BBM is present)
+ *  (3) update the BBT
+ */
+static int spinand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t offs)
+{
+	struct nand_device *nand = mtd_to_nand(mtd);
+	struct mtd_oob_ops ops = {0};
+	struct erase_info einfo = {0};
+	u32 block_addr;
+	u8 buf[2] = {0, 0};
+	int res, ret = 0;
+
+	if (!nand_bbt_is_initialized(nand) ||
+	    !(nand->bbt.options & NAND_BBT_NO_OOB_BBM)) {
+		/*erase bad block before mark bad block*/
+		einfo.mtd = mtd;
+		einfo.addr = offs;
+		einfo.len = nand_eraseblock_size(nand);
+		spinand_erase_skip_bbt(mtd, &einfo);
+
+		block_addr = nand_offs_to_eraseblock(nand, offs);
+		ops.mode = MTD_OPS_PLACE_OOB;
+		ops.ooblen = 2;
+		ops.oobbuf = buf;
+		ret = spinand_do_write_ops(mtd,
+					   nand_eraseblock_to_offs(nand,
+								   block_addr),
+					   &ops);
+	}
+
+	/* Mark block bad in BBT */
+	if (nand_bbt_is_initialized(nand)) {
+		res = nand_markbad_bbt(nand, offs);
+		if (!ret)
+			ret = res;
+	}
+
+	if (!ret)
+		mtd->ecc_stats.badblocks++;
+
+	return ret;
+}
+
+/**
+ * spinand_block_markbad - [MTD Interface] mark block at the given offset
+ * as bad
+ * @mtd: MTD device structure
+ * @offs: offset relative to mtd start
+ */
+static int spinand_block_markbad(struct mtd_info *mtd, loff_t offs)
+{
+	int ret;
+
+	ret = spinand_block_isbad(mtd, offs);
+	if (ret) {
+		/* If it was bad already, return success and do nothing */
+		if (ret > 0)
+			return 0;
+		return ret;
+	}
+
+	return spinand_block_markbad_lowlevel(mtd, offs);
+}
+
+/**
+ * spinand_erase - erase block(s)
  * @mtd: MTD device structure
  * @einfo: erase instruction
+ * @allowbbt: allow to access bbt
  */
-static int spinand_erase(struct mtd_info *mtd, struct erase_info *einfo)
+static int spinand_erase(struct mtd_info *mtd, struct erase_info *einfo,
+			 int allowbbt)
 {
 	struct spinand_device *spinand = mtd_to_spinand(mtd);
 	struct nand_device *nand = mtd_to_nand(mtd);
@@ -778,6 +925,14 @@ static int spinand_erase(struct mtd_info *mtd, struct erase_info *einfo)
 	einfo->state = MTD_ERASING;
 
 	while (len) {
+		/* Check if we have a bad block, we do not erase bad blocks! */
+		if (spinand_block_checkbad(mtd, offs, allowbbt)) {
+			dev_warn(spinand->dev,
+				 "attempt to erase a bad block at 0x%012llx\n",
+				 offs);
+			einfo->state = MTD_ERASE_FAILED;
+			goto erase_exit;
+		}
 		spinand_write_enable(spinand);
 		spinand_erase_block(spinand, nand_offs_to_page(nand, offs));
 
@@ -818,6 +973,34 @@ static int spinand_erase(struct mtd_info *mtd, struct erase_info *einfo)
 }
 
 /**
+ * spinand_erase_skip_bbt - [MTD Interface] erase block(s) except BBT
+ * @mtd: MTD device structure
+ * @einfo: erase instruction
+ */
+static int spinand_erase_skip_bbt(struct mtd_info *mtd,
+				  struct erase_info *einfo)
+{
+	return spinand_erase(mtd, einfo, 0);
+}
+
+/**
+ * spinand_block_isreserved - [MTD Interface] check if a block is
+ * marked reserved.
+ * @mtd: MTD device structure
+ * @offs: offset from device start
+ */
+static int spinand_block_isreserved(struct mtd_info *mtd, loff_t offs)
+{
+	struct nand_device *nand = mtd_to_nand(mtd);
+
+	if (!nand_bbt_is_initialized(nand))
+		return 0;
+
+	/* Return info from the table */
+	return nand_isreserved_bbt(nand, offs);
+}
+
+/**
  * spinand_set_rd_wr_op - choose the best read write command
  * @spinand: SPI NAND device structure
  * Description:
@@ -851,6 +1034,101 @@ static void spinand_set_rd_wr_op(struct spinand_device *spinand)
 		spinand->write_cache_op = SPINAND_CMD_PROG_LOAD;
 }
 
+/*
+ * spinand_erase_bbt - erase block(s) including BBT
+ * @nand: nand device structure
+ * @einfo: erase instruction
+ */
+static int spinand_erase_bbt(struct nand_device *nand,
+			     struct erase_info *einfo)
+{
+	return spinand_erase(nand_to_mtd(nand), einfo, 1);
+}
+
+/*
+ * spinand_erase_bbt - write bad block marker to certain block
+ * @nand: nand device structure
+ * @block: block to mark bad
+ */
+static int spinand_markbad(struct nand_device *nand, int block)
+{
+	struct mtd_oob_ops ops = {0};
+	u8 buf[2] = {0, 0};
+
+	ops.mode = MTD_OPS_PLACE_OOB;
+	ops.ooboffs = 0;
+	ops.ooblen = 2;
+	ops.oobbuf = buf;
+
+	return spinand_do_write_ops(nand_to_mtd(nand),
+				    nand_eraseblock_to_offs(nand, block),
+				    &ops);
+}
+
+static const struct nand_ops spinand_ops = {
+	.erase = spinand_erase_bbt,
+	.markbad = spinand_markbad,
+};
+
+/*
+ * Define some generic bad/good block scan pattern which are used
+ * while scanning a device for factory marked good/bad blocks.
+ */
+static u8 scan_ff_pattern[] = { 0xff, 0xff };
+
+#define BADBLOCK_SCAN_MASK (~NAND_BBT_NO_OOB)
+
+/*
+ * spinand_create_badblock_pattern - creates a BBT descriptor structure
+ * @spinand: SPI NAND device structure
+ *
+ * This function allocates and initializes a nand_bbt_descr for BBM detection.
+ * The new descriptor is stored in nand->bbt.bbp. Thus, nand->bbt.bbp should
+ * be NULL when passed to this function.
+ */
+static int spinand_create_badblock_pattern(struct spinand_device *spinand)
+{
+	struct nand_device *nand = &spinand->base;
+	struct nand_bbt_descr *bd;
+
+	if (nand->bbt.bbp) {
+		dev_err(spinand->dev,
+			"Bad block pattern already allocated; not replacing\n");
+		return -EINVAL;
+	}
+
+	bd = devm_kzalloc(spinand->dev, sizeof(*bd), GFP_KERNEL);
+	if (!bd)
+		return -ENOMEM;
+
+	bd->options = nand->bbt.options & BADBLOCK_SCAN_MASK;
+	bd->offs = 0;
+	bd->len = 2;
+	bd->pattern = scan_ff_pattern;
+	nand->bbt.bbp = bd;
+
+	return 0;
+}
+
+/*
+ * spinand_scan_bbt - scan BBT in SPI NAND device
+ * @spinand: SPI NAND device structure
+ */
+static int spinand_scan_bbt(struct spinand_device *spinand)
+{
+	struct nand_device *nand = &spinand->base;
+	int ret;
+
+	nand->bbt.td = NULL;
+	nand->bbt.md = NULL;
+
+	ret = spinand_create_badblock_pattern(spinand);
+	if (ret)
+		return ret;
+
+	return nand_scan_bbt(nand);
+}
+
 static const struct spinand_manufacturer *spinand_manufacturers[] = {};
 
 /**
@@ -905,6 +1183,33 @@ static void spinand_manufacturer_cleanup(struct spinand_device *spinand)
 		return spinand->manufacturer.manu->ops->cleanup(spinand);
 }
 
+/*
+ * TODO: move of_get_nand_on_flash_bbt() to generic NAND core
+ */
+static bool of_get_nand_on_flash_bbt(struct device_node *np)
+{
+	return of_property_read_bool(np, "nand-on-flash-bbt");
+}
+
+/*
+ * spinand_dt_init - Initialize SPI NAND by device tree node
+ * @spinand: SPI NAND device structure
+ *
+ * TODO: put ecc_mode, ecc_strength, ecc_step, etc in here and move
+ * it in generic NAND core.
+ */
+static void spinand_dt_init(struct spinand_device *spinand)
+{
+	struct nand_device *nand = &spinand->base;
+	struct device_node *dn = nand_get_of_node(nand);
+
+	if (!dn)
+		return;
+
+	if (of_get_nand_on_flash_bbt(dn))
+		nand->bbt.options |= NAND_BBT_USE_FLASH;
+}
+
 /**
  * spinand_detect - detect the SPI NAND device
  * @spinand: SPI NAND device structure
@@ -976,6 +1281,7 @@ int spinand_init(struct spinand_device *spinand)
 		goto err_out;
 	}
 
+	spinand_dt_init(spinand);
 	spinand_set_rd_wr_op(spinand);
 
 	/*
@@ -1001,6 +1307,7 @@ int spinand_init(struct spinand_device *spinand)
 		goto err_free_buf;
 	}
 
+	nand->ops = &spinand_ops;
 	mtd->name = spinand->name;
 	mtd->size = nand_size(nand);
 	mtd->erasesize = nand_eraseblock_size(nand);
@@ -1015,7 +1322,7 @@ int spinand_init(struct spinand_device *spinand)
 	 * area is available for user.
 	 */
 	mtd->oobavail = mtd->oobsize;
-	mtd->_erase = spinand_erase;
+	mtd->_erase = spinand_erase_skip_bbt;
 	/*
 	 * Since no ECC support right now, so for spinand_read(),
 	 * spinand_write(), spinand_read_oob() and spinand_write_oob()
@@ -1026,12 +1333,22 @@ int spinand_init(struct spinand_device *spinand)
 	mtd->_write = spinand_write;
 	mtd->_read_oob = spinand_read_oob;
 	mtd->_write_oob = spinand_write_oob;
+	mtd->_block_isbad = spinand_block_isbad;
+	mtd->_block_markbad = spinand_block_markbad;
+	mtd->_block_isreserved = spinand_block_isreserved;
 
 	/* After power up, all blocks are locked, so unlock it here. */
 	spinand_lock_block(spinand, BL_ALL_UNLOCKED);
 	/* Right now, we don't support ECC, so disable on-die ECC */
 	spinand_disable_ecc(spinand);
 
+	/* Build bad block table */
+	ret = spinand_scan_bbt(spinand);
+	if (ret) {
+		dev_err(spinand->dev, "Scan Bad Block Table failed.\n");
+		goto err_free_buf;
+	}
+
 	return 0;
 
 err_free_buf:
@@ -1047,6 +1364,11 @@ int spinand_init(struct spinand_device *spinand)
  */
 void spinand_cleanup(struct spinand_device *spinand)
 {
+	struct nand_device *nand = &spinand->base;
+
+	if (nand_bbt_is_initialized(nand))
+		nand_release_bbt(nand);
+
 	spinand_manufacturer_cleanup(spinand);
 	kfree(spinand->buf);
 }
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 13/15] nand: spi: add Micron spi nand support
  2017-05-24  7:06 [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Peter Pan
                   ` (11 preceding siblings ...)
  2017-05-24  7:07 ` [PATCH v6 12/15] nand: spi: Add bad block support Peter Pan
@ 2017-05-24  7:07 ` Peter Pan
  2017-05-24  7:07 ` [PATCH v6 14/15] nand: spi: Add generic SPI controller support Peter Pan
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 65+ messages in thread
From: Peter Pan @ 2017-05-24  7:07 UTC (permalink / raw)
  To: boris.brezillon, richard, computersforpeace, arnaud.mouiche,
	thomas.petazzoni, marex, cyrille.pitchen, linux-mtd
  Cc: peterpandong, peterpansjtu, linshunquan1

This commit is to add support for Micron MT29F2G01ABAGD
spi nand chip.

Signed-off-by: Peter Pan <peterpandong@micron.com>
---
 drivers/mtd/nand/spi/Makefile |   1 +
 drivers/mtd/nand/spi/core.c   |   4 +-
 drivers/mtd/nand/spi/micron.c | 157 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/spinand.h   |   2 +
 4 files changed, 163 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mtd/nand/spi/micron.c

diff --git a/drivers/mtd/nand/spi/Makefile b/drivers/mtd/nand/spi/Makefile
index a677a4d..df6c2ea 100644
--- a/drivers/mtd/nand/spi/Makefile
+++ b/drivers/mtd/nand/spi/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_MTD_SPI_NAND) += core.o
+obj-$(CONFIG_MTD_SPI_NAND) += micron.o
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 345d04f..05610c6 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -1129,7 +1129,9 @@ static int spinand_scan_bbt(struct spinand_device *spinand)
 	return nand_scan_bbt(nand);
 }
 
-static const struct spinand_manufacturer *spinand_manufacturers[] = {};
+static const struct spinand_manufacturer *spinand_manufacturers[] = {
+	&micron_spinand_manufacturer
+};
 
 /**
  * spinand_manufacturer_detect - detect SPI NAND device by each manufacturer
diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c
new file mode 100644
index 0000000..43784db
--- /dev/null
+++ b/drivers/mtd/nand/spi/micron.c
@@ -0,0 +1,157 @@
+/*
+ *
+ * Copyright (c) 2016-2017 Micron Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/mtd/spinand.h>
+
+#define SPINAND_MFR_MICRON		0x2C
+
+struct micron_spinand_info {
+	char *name;
+	u8 dev_id;
+	u32 page_size;
+	u32 oob_size;
+	u32 pages_per_blk;
+	u32 blks_per_lun;
+	u32 luns_per_chip;
+	u32 ecc_strength;
+	u32 ecc_steps;
+	u32 rw_mode;
+};
+
+#define MICRON_SPI_NAND_INFO(nm, did, pagesz, oobsz, pg_per_blk,	\
+			     blk_per_lun, lun_per_chip, ecc_stren,	\
+			     ecc_stps, rwmode)		\
+	{	\
+		.name = (nm),	\
+		.dev_id = (did),	\
+		.page_size = (pagesz),	\
+		.oob_size = (oobsz),	\
+		.pages_per_blk = (pg_per_blk),	\
+		.blks_per_lun = (blk_per_lun),	\
+		.luns_per_chip = (lun_per_chip),\
+		.ecc_strength = (ecc_stren),	\
+		.ecc_steps = (ecc_stps),	\
+		.rw_mode = (rwmode)	\
+	}
+
+static const struct micron_spinand_info micron_spinand_table[] = {
+	MICRON_SPI_NAND_INFO("MT29F2G01ABAGD", 0x24, 2048, 128, 64, 2048, 1,
+			     8, 512, SPINAND_OP_COMMON),
+};
+
+static int micron_spinand_get_dummy(struct spinand_device *spinand,
+				    struct spinand_op *op)
+{
+	u8 opcode = op->cmd;
+
+	switch (opcode) {
+	case SPINAND_CMD_READ_FROM_CACHE:
+	case SPINAND_CMD_READ_FROM_CACHE_FAST:
+	case SPINAND_CMD_READ_FROM_CACHE_X2:
+	case SPINAND_CMD_READ_FROM_CACHE_DUAL_IO:
+	case SPINAND_CMD_READ_FROM_CACHE_X4:
+	case SPINAND_CMD_READ_ID:
+		return 1;
+
+	case SPINAND_CMD_READ_FROM_CACHE_QUAD_IO:
+		return 2;
+
+	default:
+		return 0;
+	}
+}
+
+/**
+ * micron_spinand_scan_id_table - scan SPI NAND info in id table
+ * @spinand: SPI NAND device structure
+ * @id: point to manufacture id and device id
+ * Description:
+ *   If found in id table, config device with table information.
+ */
+static bool micron_spinand_scan_id_table(struct spinand_device *spinand,
+					 u8 dev_id)
+{
+	struct mtd_info *mtd = spinand_to_mtd(spinand);
+	struct nand_device *nand = mtd_to_nand(mtd);
+	struct micron_spinand_info *item = NULL;
+	struct nand_memory_organization *memorg = &nand->memorg;
+	int i = 0;
+
+	for (; i < ARRAY_SIZE(micron_spinand_table); i++) {
+		item = (struct micron_spinand_info *)micron_spinand_table + i;
+		if (dev_id != item->dev_id)
+			continue;
+
+		spinand->name = item->name;
+		memorg->eraseblocksize = item->page_size * item->pages_per_blk;
+		memorg->pagesize = item->page_size;
+		memorg->oobsize = item->oob_size;
+		memorg->diesize = memorg->eraseblocksize * item->blks_per_lun;
+		memorg->ndies = item->luns_per_chip;
+		spinand->rw_mode = item->rw_mode;
+
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ * micron_spinand_detect - initialize device related part in spinand_device
+ * struct if it is Micron device.
+ * @spinand: SPI NAND device structure
+ */
+static bool micron_spinand_detect(struct spinand_device *spinand)
+{
+	u8 *id = spinand->id.data;
+
+	/*
+	 * Micron SPI NAND read ID need a dummy byte,
+	 * so the first byte in raw_id is dummy.
+	 */
+	if (id[1] != SPINAND_MFR_MICRON)
+		return false;
+
+	return micron_spinand_scan_id_table(spinand, id[2]);
+}
+
+/**
+ * micron_spinand_prepare_op - Fix address for cache operation.
+ * @spinand: SPI NAND device structure
+ * @op: pointer to spinand_op struct
+ * @page: page address
+ * @column: column address
+ */
+static void micron_spinand_prepare_op(struct spinand_device *spinand,
+				      struct spinand_op *op, u32 page,
+				      u32 column)
+{
+	op->addr[0] |= (u8)((nand_page_to_eraseblock(&spinand->base, page)
+			     & 0x1) << 4);
+	op->n_addr += micron_spinand_get_dummy(spinand, op);
+}
+
+static const struct spinand_manufacturer_ops micron_spinand_manuf_ops = {
+	.detect = micron_spinand_detect,
+	.prepare_op = micron_spinand_prepare_op,
+};
+
+const struct spinand_manufacturer micron_spinand_manufacturer = {
+	.id = SPINAND_MFR_MICRON,
+	.name = "Micron",
+	.ops = &micron_spinand_manuf_ops,
+};
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index 04ad1dd..8ef2c69 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -125,6 +125,8 @@ struct spinand_manufacturer {
 	const struct spinand_manufacturer_ops *ops;
 };
 
+extern const struct spinand_manufacturer micron_spinand_manufacturer;
+
 #define SPINAND_CAP_RD_X1	BIT(0)
 #define SPINAND_CAP_RD_X2	BIT(1)
 #define SPINAND_CAP_RD_X4	BIT(2)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 14/15] nand: spi: Add generic SPI controller support
  2017-05-24  7:06 [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Peter Pan
                   ` (12 preceding siblings ...)
  2017-05-24  7:07 ` [PATCH v6 13/15] nand: spi: add Micron spi nand support Peter Pan
@ 2017-05-24  7:07 ` Peter Pan
  2017-05-24  7:07 ` [PATCH v6 15/15] MAINTAINERS: Add SPI NAND entry Peter Pan
  2017-05-29 20:59 ` [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Boris Brezillon
  15 siblings, 0 replies; 65+ messages in thread
From: Peter Pan @ 2017-05-24  7:07 UTC (permalink / raw)
  To: boris.brezillon, richard, computersforpeace, arnaud.mouiche,
	thomas.petazzoni, marex, cyrille.pitchen, linux-mtd
  Cc: peterpandong, peterpansjtu, linshunquan1

This commit supports to use generic spi controller
as spi nand controller.

Signed-off-by: Peter Pan <peterpandong@micron.com>
---
 drivers/mtd/nand/spi/Kconfig                   |   2 +
 drivers/mtd/nand/spi/Makefile                  |   1 +
 drivers/mtd/nand/spi/controllers/Kconfig       |   5 +
 drivers/mtd/nand/spi/controllers/Makefile      |   1 +
 drivers/mtd/nand/spi/controllers/generic-spi.c | 162 +++++++++++++++++++++++++
 5 files changed, 171 insertions(+)
 create mode 100644 drivers/mtd/nand/spi/controllers/Kconfig
 create mode 100644 drivers/mtd/nand/spi/controllers/Makefile
 create mode 100644 drivers/mtd/nand/spi/controllers/generic-spi.c

diff --git a/drivers/mtd/nand/spi/Kconfig b/drivers/mtd/nand/spi/Kconfig
index d77c46e..6bd1c65 100644
--- a/drivers/mtd/nand/spi/Kconfig
+++ b/drivers/mtd/nand/spi/Kconfig
@@ -3,3 +3,5 @@ menuconfig MTD_SPI_NAND
 	depends on MTD_NAND
 	help
 	  This is the framework for the SPI NAND device drivers.
+
+source "drivers/mtd/nand/spi/controllers/Kconfig"
diff --git a/drivers/mtd/nand/spi/Makefile b/drivers/mtd/nand/spi/Makefile
index df6c2ea..822e48d 100644
--- a/drivers/mtd/nand/spi/Makefile
+++ b/drivers/mtd/nand/spi/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_MTD_SPI_NAND) += core.o
 obj-$(CONFIG_MTD_SPI_NAND) += micron.o
+obj-$(CONFIG_MTD_SPI_NAND) += controllers/
diff --git a/drivers/mtd/nand/spi/controllers/Kconfig b/drivers/mtd/nand/spi/controllers/Kconfig
new file mode 100644
index 0000000..8ab7023
--- /dev/null
+++ b/drivers/mtd/nand/spi/controllers/Kconfig
@@ -0,0 +1,5 @@
+config GENERIC_SPI_NAND
+	tristate "SPI NAND with generic SPI bus Support"
+	depends on MTD_SPI_NAND && SPI
+	help
+	  This is to support SPI NAND device with generic SPI bus.
diff --git a/drivers/mtd/nand/spi/controllers/Makefile b/drivers/mtd/nand/spi/controllers/Makefile
new file mode 100644
index 0000000..46cbf29
--- /dev/null
+++ b/drivers/mtd/nand/spi/controllers/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_GENERIC_SPI_NAND) += generic-spi.o
diff --git a/drivers/mtd/nand/spi/controllers/generic-spi.c b/drivers/mtd/nand/spi/controllers/generic-spi.c
new file mode 100644
index 0000000..93ccafc
--- /dev/null
+++ b/drivers/mtd/nand/spi/controllers/generic-spi.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2016-2017 Micron Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/mtd/spinand.h>
+#include <linux/mtd/mtd.h>
+
+struct gen_spi_spinand_controller {
+	struct spinand_controller ctrl;
+	struct spi_device *spi;
+};
+
+#define to_gen_spi_spinand_controller(c) \
+	container_of(c, struct gen_spi_spinand_controller, ctrl)
+
+/*
+ * gen_spi_spinand_exec_op - to process a command to send to the
+ * SPI NAND by generic SPI bus
+ * @spinand: SPI NAND device structure
+ * @op: SPI NAND operation descriptor
+ */
+static int gen_spi_spinand_exec_op(struct spinand_device *spinand,
+				   struct spinand_op *op)
+{
+	struct spi_message message;
+	struct spi_transfer x[3];
+	struct spinand_controller *spinand_controller;
+	struct gen_spi_spinand_controller *controller;
+
+	spinand_controller = spinand->controller.controller;
+	controller = to_gen_spi_spinand_controller(spinand_controller);
+	spi_message_init(&message);
+	memset(x, 0, sizeof(x));
+	x[0].len = 1;
+	x[0].tx_nbits = 1;
+	x[0].tx_buf = &op->cmd;
+	spi_message_add_tail(&x[0], &message);
+
+	if (op->n_addr + op->dummy_bytes) {
+		x[1].len = op->n_addr + op->dummy_bytes;
+		x[1].tx_nbits = op->addr_nbits;
+		x[1].tx_buf = op->addr;
+		spi_message_add_tail(&x[1], &message);
+	}
+
+	if (op->n_tx) {
+		x[2].len = op->n_tx;
+		x[2].tx_nbits = op->data_nbits;
+		x[2].tx_buf = op->tx_buf;
+		spi_message_add_tail(&x[2], &message);
+	} else if (op->n_rx) {
+		x[2].len = op->n_rx;
+		x[2].rx_nbits = op->data_nbits;
+		x[2].rx_buf = op->rx_buf;
+		spi_message_add_tail(&x[2], &message);
+	}
+
+	return spi_sync(controller->spi, &message);
+}
+
+static struct spinand_controller_ops gen_spi_spinand_ops = {
+	.exec_op = gen_spi_spinand_exec_op,
+};
+
+static int gen_spi_spinand_probe(struct spi_device *spi)
+{
+	struct spinand_device *spinand;
+	struct gen_spi_spinand_controller *controller;
+	struct spinand_controller *spinand_controller;
+	struct device *dev = &spi->dev;
+	u16 mode = spi->mode;
+	int ret;
+
+	spinand = devm_spinand_alloc(dev);
+	if (IS_ERR(spinand)) {
+		ret = PTR_ERR(spinand);
+		goto out;
+	}
+
+	controller = devm_kzalloc(dev, sizeof(*controller), GFP_KERNEL);
+	if (!controller) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	controller->spi = spi;
+	spinand_controller = &controller->ctrl;
+	spinand_controller->ops = &gen_spi_spinand_ops;
+	spinand_controller->caps = SPINAND_CAP_RD_X1 | SPINAND_CAP_WR_X1;
+
+	if ((mode & SPI_RX_QUAD) && (mode & SPI_TX_QUAD))
+		spinand_controller->caps |= SPINAND_CAP_RD_QUAD;
+
+	if ((mode & SPI_RX_DUAL) && (mode & SPI_TX_DUAL))
+		spinand_controller->caps |= SPINAND_CAP_RD_DUAL;
+
+	if (mode & SPI_RX_QUAD)
+		spinand_controller->caps |= SPINAND_CAP_RD_X4;
+
+	if (mode & SPI_RX_DUAL)
+		spinand_controller->caps |= SPINAND_CAP_RD_X2;
+
+	if (mode & SPI_TX_QUAD)
+		spinand_controller->caps |= SPINAND_CAP_WR_QUAD |
+					    SPINAND_CAP_WR_X4;
+
+	if (mode & SPI_TX_DUAL)
+		spinand_controller->caps |= SPINAND_CAP_WR_DUAL |
+					    SPINAND_CAP_WR_X2;
+
+	spinand->controller.controller = spinand_controller;
+	spi_set_drvdata(spi, spinand);
+
+	ret = spinand_init(spinand);
+	if (ret)
+		goto out;
+
+	ret = mtd_device_register(spinand_to_mtd(spinand), NULL, 0);
+
+out:
+	return ret;
+}
+
+static int gen_spi_spinand_remove(struct spi_device *spi)
+{
+	struct spinand_device *spinand = spi_get_drvdata(spi);
+	int ret;
+
+	ret = mtd_device_unregister(spinand_to_mtd(spinand));
+	if (ret)
+		return ret;
+
+	spinand_cleanup(spinand);
+
+	return 0;
+}
+
+static struct spi_driver gen_spi_spinand_driver = {
+	.driver = {
+		.name	= "generic_spinand",
+		.owner	= THIS_MODULE,
+	},
+	.probe	= gen_spi_spinand_probe,
+	.remove	= gen_spi_spinand_remove,
+};
+module_spi_driver(gen_spi_spinand_driver);
+
+MODULE_DESCRIPTION("Generic SPI controller to support SPI NAND");
+MODULE_AUTHOR("Peter Pan<peterpandong@micron.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 15/15] MAINTAINERS: Add SPI NAND entry
  2017-05-24  7:06 [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Peter Pan
                   ` (13 preceding siblings ...)
  2017-05-24  7:07 ` [PATCH v6 14/15] nand: spi: Add generic SPI controller support Peter Pan
@ 2017-05-24  7:07 ` Peter Pan
  2017-05-29 20:59 ` [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Boris Brezillon
  15 siblings, 0 replies; 65+ messages in thread
From: Peter Pan @ 2017-05-24  7:07 UTC (permalink / raw)
  To: boris.brezillon, richard, computersforpeace, arnaud.mouiche,
	thomas.petazzoni, marex, cyrille.pitchen, linux-mtd
  Cc: peterpandong, peterpansjtu, linshunquan1

Add maintainer information for SPI NAND.

Signed-off-by: Peter Pan <peterpandong@micron.com>
---
 MAINTAINERS | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index fe4b69e..e4edb75 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8762,6 +8762,15 @@ S:	Maintained
 F:	drivers/mtd/nand/
 F:	include/linux/mtd/*nand*.h
 
+SPI NAND FLASH DRIVER
+M:	Peter Pan <peterpandong@micron.com>
+L:	linux-mtd@lists.infradead.org
+W:	http://www.linux-mtd.infradead.org/
+Q:	http://patchwork.ozlabs.org/project/linux-mtd/list/
+S:	Maintained
+F:	drivers/mtd/nand/spi/
+F:	include/linux/mtd/spinand.h
+
 NATSEMI ETHERNET DRIVER (DP8381x)
 S:	Orphan
 F:	drivers/net/ethernet/natsemi/natsemi.c
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 03/15] mtd: nand: add a nand.h file to expose basic NAND stuff
  2017-05-24  7:06 ` [PATCH v6 03/15] mtd: nand: add a nand.h file to expose basic NAND stuff Peter Pan
@ 2017-05-29 20:14   ` Boris Brezillon
  0 siblings, 0 replies; 65+ messages in thread
From: Boris Brezillon @ 2017-05-29 20:14 UTC (permalink / raw)
  To: Peter Pan
  Cc: richard, computersforpeace, arnaud.mouiche, thomas.petazzoni,
	marex, cyrille.pitchen, linux-mtd, peterpansjtu, linshunquan1

On Wed, 24 May 2017 15:06:59 +0800
Peter Pan <peterpandong@micron.com> wrote:

> +
> +/**
> + * nand_check_oob_ops - check mtd_oob_ops is valid or not
> + * @nand: NAND device
> + * @start: start address to check
> + * @ops: oob operation description struct
> + *
> + * Returns 0 for valid ops and -EINVAL for invalid ops.
> + */
> +static inline int nand_check_oob_ops(struct nand_device *nand, loff_t start,
> +				     struct mtd_oob_ops *ops)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(nand);
> +	int oobbytes_per_page = ops->mode == MTD_OPS_AUTO_OOB ?
> +				mtd->oobavail : mtd->oobsize;
> +	int pages = nand_len_to_pages(nand, nand_size(nand));
> +	int max_pages = pages - nand_offs_to_page(nand, start);
> +	int max_ooblen = max_pages * oobbytes_per_page;
> +
> +	if ((!!ops->datbuf != !!ops->len) ||
> +	    (!!ops->oobbuf != !!ops->ooblen))
> +		return -EINVAL;

Can we make the test more obvious:

	if ((ops->len && !ops->datbuf) ||
	    (ops->ooblen && !ops->oobbuf))

> +	if (ops->ooboffs >= oobbytes_per_page)
> +		return -EINVAL;

Please add blank lines after each if () block.

> +	if (ops->ooboffs + ops->ooblen > max_ooblen)
> +		return -EINVAL;

I thought we agreed that these tests should go in mtdcore.c. That's
clearly generic and could benefit to everyone, not only NAND users.

> +
> +	return 0;
> +}
> +
> +/**
> + * nand_oob_ops_across_page - check oob operation across page or not

You mean cross, not across, right?

> + * @nand: NAND device
> + * @ops: oob operation description struct
> + *
> + * Returns true if oob operation across page and false when not.
> + */
> +static inline bool nand_oob_ops_across_page(struct nand_device *nand,
> +					    struct mtd_oob_ops *ops)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(nand);
> +	int oobbytes_per_page = ops->mode == MTD_OPS_AUTO_OOB ?
> +				mtd->oobavail : mtd->oobsize;
> +
> +	return (ops->ooboffs + ops->ooblen) > oobbytes_per_page;

Since mtd_oob_ops is actually not only about oob data, I guess we
should check in-band data as well. This implies passing the start
offset in argument of course.

	if (ops->ooboffs + ops->ooblen > oobbytes_per_page ||
	    ops->len > mtd->writesize ||
	    mtd_mod_by_ws(start_offs, mtd) + ops->len > mtd->writesize)
		return true;

	return false;

> +}

Again, this is completely generic, so probably something we should put
in mtd.h/mtdcore.c.

> +
> +/**
> + * nand_check_erase_ops - check erase operation is valid or not
> + * @nand: NAND device
> + * @einfo: erase instruction
> + *
> + * Returns 0 for valid erase operation and -EINVAL for invalid.
> + */
> +static inline int nand_check_erase_ops(struct nand_device *nand,
> +				       struct erase_info *einfo)
> +{
> +	/* check address align on block boundary */
> +	if (einfo->addr & (nand_eraseblock_size(nand) - 1))
> +		return -EINVAL;
> +	/* check lendth align on block boundary */
> +	if (einfo->len & (nand_eraseblock_size(nand) - 1))
> +		return -EINVAL;
> +	/* Do not allow erase past end of device */
> +	if ((einfo->addr + einfo->len) > nand_size(nand))
> +		return -EINVAL;
> +
> +	return 0;
> +}

And here again, this should be moved to mtdcore.c/mtd.h. Actually, the
last check you're doing here is already done in mtd_erase() [1].

[1]http://elixir.free-electrons.com/linux/latest/source/drivers/mtd/mtdcore.c#L958

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 04/15] mtd: nand: raw: prefix conflicting names with nandcchip instead of nand
  2017-05-24  7:07 ` [PATCH v6 04/15] mtd: nand: raw: prefix conflicting names with nandcchip instead of nand Peter Pan
@ 2017-05-29 20:22   ` Boris Brezillon
  0 siblings, 0 replies; 65+ messages in thread
From: Boris Brezillon @ 2017-05-29 20:22 UTC (permalink / raw)
  To: Peter Pan
  Cc: richard, computersforpeace, arnaud.mouiche, thomas.petazzoni,
	marex, cyrille.pitchen, linux-mtd, peterpansjtu, linshunquan1

On Wed, 24 May 2017 15:07:00 +0800
Peter Pan <peterpandong@micron.com> wrote:

There's a typo in the commit title, it's nandchip not nandcchip.

> From: Boris Brezillon <boris.brezillon@free-electrons.com>
> 
> Some raw NAND function names conflict with names defined in nand.h.
> Prefix all those functions with nandchip instead of nand so we can
> include nand.h from rawnand.h
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
> Signed-off-by: Peter Pan <peterpandong@micron.com>
> ---
>  Documentation/DocBook/mtdnand.tmpl               |  10 +-
>  arch/arm/mach-ep93xx/snappercl15.c               |   4 +-
>  arch/arm/mach-ep93xx/ts72xx.c                    |   4 +-
>  arch/arm/mach-imx/mach-qong.c                    |   2 +-
>  arch/arm/mach-ixp4xx/ixdp425-setup.c             |   2 +-
>  arch/arm/mach-omap1/board-nand.c                 |   2 +-
>  arch/arm/mach-orion5x/ts78xx-setup.c             |   6 +-
>  arch/arm/mach-pxa/balloon3.c                     |   2 +-
>  arch/arm/mach-pxa/em-x270.c                      |   2 +-
>  arch/arm/mach-pxa/palmtx.c                       |   2 +-
>  arch/blackfin/mach-bf537/boards/stamp.c          |   2 +-
>  arch/blackfin/mach-bf561/boards/acvilon.c        |   2 +-
>  arch/cris/arch-v32/drivers/mach-a3/nandflash.c   |   4 +-
>  arch/cris/arch-v32/drivers/mach-fs/nandflash.c   |   4 +-
>  arch/mips/alchemy/devboards/db1200.c             |   2 +-
>  arch/mips/alchemy/devboards/db1300.c             |   2 +-
>  arch/mips/alchemy/devboards/db1550.c             |   2 +-
>  arch/mips/jz4740/board-qi_lb60.c                 |   2 +-
>  arch/mips/pnx833x/common/platform.c              |   2 +-
>  arch/mips/rb532/devices.c                        |   2 +-
>  arch/sh/boards/mach-migor/setup.c                |   2 +-
>  drivers/mtd/nand/raw/ams-delta.c                 |   8 +-
>  drivers/mtd/nand/raw/atmel/nand-controller.c     |  50 ++++----
>  drivers/mtd/nand/raw/au1550nd.c                  |  26 ++---
>  drivers/mtd/nand/raw/bcm47xxnflash/main.c        |   4 +-
>  drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c |  18 +--
>  drivers/mtd/nand/raw/bf5xx_nand.c                |  32 +++---
>  drivers/mtd/nand/raw/brcmnand/brcmnand.c         |  32 +++---
>  drivers/mtd/nand/raw/cafe_nand.c                 |  24 ++--
>  drivers/mtd/nand/raw/cmx270_nand.c               |  12 +-
>  drivers/mtd/nand/raw/cs553x_nand.c               |  20 ++--
>  drivers/mtd/nand/raw/davinci_nand.c              |  14 +--
>  drivers/mtd/nand/raw/denali.c                    |  14 +--
>  drivers/mtd/nand/raw/diskonchip.c                |  68 +++++------
>  drivers/mtd/nand/raw/docg4.c                     |  36 +++---
>  drivers/mtd/nand/raw/fsl_elbc_nand.c             |  26 ++---
>  drivers/mtd/nand/raw/fsl_ifc_nand.c              |  28 ++---
>  drivers/mtd/nand/raw/fsl_upm.c                   |  12 +-
>  drivers/mtd/nand/raw/fsmc_nand.c                 |  24 ++--
>  drivers/mtd/nand/raw/gpio.c                      |   6 +-
>  drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c        |   2 +-
>  drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c       |  38 +++---
>  drivers/mtd/nand/raw/hisi504_nand.c              |  24 ++--
>  drivers/mtd/nand/raw/jz4740_nand.c               |  12 +-
>  drivers/mtd/nand/raw/jz4780_nand.c               |   8 +-
>  drivers/mtd/nand/raw/lpc32xx_mlc.c               |  16 +--
>  drivers/mtd/nand/raw/lpc32xx_slc.c               |  20 ++--
>  drivers/mtd/nand/raw/mpc5121_nfc.c               |  26 ++---
>  drivers/mtd/nand/raw/mtk_nand.c                  |  38 +++---
>  drivers/mtd/nand/raw/mxc_nand.c                  |  52 ++++-----
>  drivers/mtd/nand/raw/nand_amd.c                  |   2 +-
>  drivers/mtd/nand/raw/nand_base.c                 | 140 +++++++++++------------
>  drivers/mtd/nand/raw/nand_bbt.c                  |  34 +++---
>  drivers/mtd/nand/raw/nand_bch.c                  |   6 +-
>  drivers/mtd/nand/raw/nand_ecc.c                  |   4 +-
>  drivers/mtd/nand/raw/nand_hynix.c                |  10 +-
>  drivers/mtd/nand/raw/nand_micron.c               |  10 +-
>  drivers/mtd/nand/raw/nand_samsung.c              |   4 +-
>  drivers/mtd/nand/raw/nand_toshiba.c              |   2 +-
>  drivers/mtd/nand/raw/nandsim.c                   |  22 ++--
>  drivers/mtd/nand/raw/ndfc.c                      |  18 +--
>  drivers/mtd/nand/raw/nuc900_nand.c               |   8 +-
>  drivers/mtd/nand/raw/omap2.c                     |  20 ++--
>  drivers/mtd/nand/raw/orion_nand.c                |   8 +-
>  drivers/mtd/nand/raw/oxnas_nand.c                |  12 +-
>  drivers/mtd/nand/raw/pasemi_nand.c               |  10 +-
>  drivers/mtd/nand/raw/plat_nand.c                 |   4 +-
>  drivers/mtd/nand/raw/pxa3xx_nand.c               |  36 +++---
>  drivers/mtd/nand/raw/qcom_nandc.c                |  28 ++---
>  drivers/mtd/nand/raw/r852.c                      |   8 +-
>  drivers/mtd/nand/raw/s3c2410.c                   |  16 +--
>  drivers/mtd/nand/raw/sh_flctl.c                  |  10 +-
>  drivers/mtd/nand/raw/sharpsl.c                   |   8 +-
>  drivers/mtd/nand/raw/sm_common.c                 |   2 +-
>  drivers/mtd/nand/raw/socrates_nand.c             |  12 +-
>  drivers/mtd/nand/raw/sunxi_nand.c                |  58 +++++-----
>  drivers/mtd/nand/raw/tango_nand.c                |  30 ++---
>  drivers/mtd/nand/raw/tmio_nand.c                 |   8 +-
>  drivers/mtd/nand/raw/txx9ndfmc.c                 |  14 +--
>  drivers/mtd/nand/raw/vf610_nfc.c                 |   4 +-
>  drivers/mtd/nand/raw/xway_nand.c                 |  10 +-
>  drivers/staging/mt29f_spinand/mt29f_spinand.c    |   6 +-
>  include/linux/mtd/rawnand.h                      |   4 +-
>  include/linux/mtd/sh_flctl.h                     |   2 +-
>  84 files changed, 661 insertions(+), 661 deletions(-)
> 
> diff --git a/Documentation/DocBook/mtdnand.tmpl b/Documentation/DocBook/mtdnand.tmpl
> index 35ec715..5a3342c 100644
> --- a/Documentation/DocBook/mtdnand.tmpl
> +++ b/Documentation/DocBook/mtdnand.tmpl
> @@ -169,7 +169,7 @@
>  			The NAND chip structure embeds an mtd structure
>  			which will be registered to the MTD subsystem.
>  			You can extract a pointer to the mtd structure
> -			from a nand_chip pointer using the nand_to_mtd()
> +			from a nand_chip pointer using the nandchip_to_mtd()
>  			helper.
>  		</para>
>  		<para>
> @@ -237,7 +237,7 @@ static void board_hwcontrol(struct mtd_info *mtd, int cmd)
>  		<programlisting>
>  static void board_hwcontrol(struct mtd_info *mtd, int cmd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	switch(cmd){
>  		case NAND_CTL_SETCLE: this->IO_ADDR_W |= CLE_ADRR_BIT;  break;
>  		case NAND_CTL_CLRCLE: this->IO_ADDR_W &amp;= ~CLE_ADRR_BIT; break;
> @@ -283,7 +283,7 @@ static int __init board_init (void)
>  		goto out;
>  	}
>  
> -	board_mtd = nand_to_mtd(this);
> +	board_mtd = nandchip_to_mtd(this);
>  
>  	/* map physical address */
>  	baseaddr = ioremap(CHIP_PHYSICAL_ADDRESS, 1024);
> @@ -342,7 +342,7 @@ static void __exit board_cleanup (void)
>  	iounmap(baseaddr);
>  	
>  	/* Free the MTD device structure */
> -	kfree (mtd_to_nand(board_mtd));
> +	kfree (mtd_to_nandchip(board_mtd));
>  }
>  module_exit(board_cleanup);
>  #endif
> @@ -398,7 +398,7 @@ static void board_select_chip (struct mtd_info *mtd, int chip)
>  		<programlisting>
>  static void board_select_chip (struct mtd_info *mtd, int chip)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	
>  	/* Deselect all chips */
>  	this->IO_ADDR_R &amp;= ~BOARD_NAND_ADDR_MASK;
> diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c
> index 8b29398..d6f6094 100644
> --- a/arch/arm/mach-ep93xx/snappercl15.c
> +++ b/arch/arm/mach-ep93xx/snappercl15.c
> @@ -49,7 +49,7 @@
>  static void snappercl15_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
>  				      unsigned int ctrl)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	static u16 nand_state = SNAPPERCL15_NAND_WPN;
>  	u16 set;
>  
> @@ -76,7 +76,7 @@ static void snappercl15_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
>  
>  static int snappercl15_nand_dev_ready(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	return !!(__raw_readw(NAND_CTRL_ADDR(chip)) & SNAPPERCL15_NAND_RDY);
>  }
> diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
> index 8745162..500ad463 100644
> --- a/arch/arm/mach-ep93xx/ts72xx.c
> +++ b/arch/arm/mach-ep93xx/ts72xx.c
> @@ -63,7 +63,7 @@ static void __init ts72xx_map_io(void)
>  static void ts72xx_nand_hwcontrol(struct mtd_info *mtd,
>  				  int cmd, unsigned int ctrl)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (ctrl & NAND_CTRL_CHANGE) {
>  		void __iomem *addr = chip->IO_ADDR_R;
> @@ -85,7 +85,7 @@ static void ts72xx_nand_hwcontrol(struct mtd_info *mtd,
>  
>  static int ts72xx_nand_device_ready(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	void __iomem *addr = chip->IO_ADDR_R;
>  
>  	addr += (1 << TS72XX_NAND_BUSY_ADDR_LINE);
> diff --git a/arch/arm/mach-imx/mach-qong.c b/arch/arm/mach-imx/mach-qong.c
> index 42a7000..eda2297 100644
> --- a/arch/arm/mach-imx/mach-qong.c
> +++ b/arch/arm/mach-imx/mach-qong.c
> @@ -131,7 +131,7 @@ static void qong_init_nor_mtd(void)
>   */
>  static void qong_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  
>  	if (cmd == NAND_CMD_NONE)
>  		return;
> diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
> index 93b89291..33a07c7 100644
> --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
> +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
> @@ -76,7 +76,7 @@
>  static void
>  ixdp425_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	int offset = (int)nand_get_controller_data(this);
>  
>  	if (ctrl & NAND_CTRL_CHANGE) {
> diff --git a/arch/arm/mach-omap1/board-nand.c b/arch/arm/mach-omap1/board-nand.c
> index 1bffbb4..617848c 100644
> --- a/arch/arm/mach-omap1/board-nand.c
> +++ b/arch/arm/mach-omap1/board-nand.c
> @@ -22,7 +22,7 @@
>  
>  void omap1_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	unsigned long mask;
>  
>  	if (cmd == NAND_CMD_NONE)
> diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c
> index 9477873..23c5a69 100644
> --- a/arch/arm/mach-orion5x/ts78xx-setup.c
> +++ b/arch/arm/mach-orion5x/ts78xx-setup.c
> @@ -134,7 +134,7 @@ static void ts78xx_ts_rtc_unload(void)
>  static void ts78xx_ts_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
>  			unsigned int ctrl)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  
>  	if (ctrl & NAND_CTRL_CHANGE) {
>  		unsigned char bits;
> @@ -158,7 +158,7 @@ static int ts78xx_ts_nand_dev_ready(struct mtd_info *mtd)
>  static void ts78xx_ts_nand_write_buf(struct mtd_info *mtd,
>  			const uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	void __iomem *io_base = chip->IO_ADDR_W;
>  	unsigned long off = ((unsigned long)buf & 3);
>  	int sz;
> @@ -185,7 +185,7 @@ static void ts78xx_ts_nand_write_buf(struct mtd_info *mtd,
>  static void ts78xx_ts_nand_read_buf(struct mtd_info *mtd,
>  			uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	void __iomem *io_base = chip->IO_ADDR_R;
>  	unsigned long off = ((unsigned long)buf & 3);
>  	int sz;
> diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
> index 33d7ef1..ea06411 100644
> --- a/arch/arm/mach-pxa/balloon3.c
> +++ b/arch/arm/mach-pxa/balloon3.c
> @@ -573,7 +573,7 @@ static inline void balloon3_i2c_init(void) {}
>  #if defined(CONFIG_MTD_NAND_PLATFORM)||defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
>  static void balloon3_nand_cmd_ctl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	uint8_t balloon3_ctl_set = 0, balloon3_ctl_clr = 0;
>  
>  	if (ctrl & NAND_CTRL_CHANGE) {
> diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
> index 6d28035..e072cc7 100644
> --- a/arch/arm/mach-pxa/em-x270.c
> +++ b/arch/arm/mach-pxa/em-x270.c
> @@ -288,7 +288,7 @@ static void nand_cs_off(void)
>  static void em_x270_nand_cmd_ctl(struct mtd_info *mtd, int dat,
>  				 unsigned int ctrl)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	unsigned long nandaddr = (unsigned long)this->IO_ADDR_W;
>  
>  	dsb();
> diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
> index 47e3e38..7422e06 100644
> --- a/arch/arm/mach-pxa/palmtx.c
> +++ b/arch/arm/mach-pxa/palmtx.c
> @@ -250,7 +250,7 @@ static inline void palmtx_keys_init(void) {}
>  static void palmtx_nand_cmd_ctl(struct mtd_info *mtd, int cmd,
>  				 unsigned int ctrl)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	char __iomem *nandaddr = this->IO_ADDR_W;
>  
>  	if (cmd == NAND_CMD_NONE)
> diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
> index ab3034f..af8e8be 100644
> --- a/arch/blackfin/mach-bf537/boards/stamp.c
> +++ b/arch/blackfin/mach-bf537/boards/stamp.c
> @@ -404,7 +404,7 @@ void sl811_port_power(struct device *dev, int is_on)
>  #define BFIN_NAND_PLAT_ALE 1
>  static void bfin_plat_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  
>  	if (cmd == NAND_CMD_NONE)
>  		return;
> diff --git a/arch/blackfin/mach-bf561/boards/acvilon.c b/arch/blackfin/mach-bf561/boards/acvilon.c
> index 696cc9d..763fa1f 100644
> --- a/arch/blackfin/mach-bf561/boards/acvilon.c
> +++ b/arch/blackfin/mach-bf561/boards/acvilon.c
> @@ -267,7 +267,7 @@ struct i2c_pca9564_pf_platform_data pca9564_platform_data = {
>  static void bfin_plat_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
>  				    unsigned int ctrl)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  
>  	if (cmd == NAND_CMD_NONE)
>  		return;
> diff --git a/arch/cris/arch-v32/drivers/mach-a3/nandflash.c b/arch/cris/arch-v32/drivers/mach-a3/nandflash.c
> index 925a98e..eb22e7f 100644
> --- a/arch/cris/arch-v32/drivers/mach-a3/nandflash.c
> +++ b/arch/cris/arch-v32/drivers/mach-a3/nandflash.c
> @@ -51,7 +51,7 @@ static void crisv32_hwcontrol(struct mtd_info *mtd, int cmd,
>  {
>  	unsigned long flags;
>  	reg_pio_rw_dout dout;
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  
>  	local_irq_save(flags);
>  
> @@ -147,7 +147,7 @@ struct mtd_info *__init crisv32_nand_flash_probe(void)
>  
>  	/* Get pointer to private data */
>  	this = &wrapper->chip;
> -	crisv32_mtd = nand_to_mtd(this);
> +	crisv32_mtd = nandchip_to_mtd(this);
>  
>  	/* Set address of NAND IO lines */
>  	this->IO_ADDR_R = read_cs;
> diff --git a/arch/cris/arch-v32/drivers/mach-fs/nandflash.c b/arch/cris/arch-v32/drivers/mach-fs/nandflash.c
> index 53b56a4..0f24c31 100644
> --- a/arch/cris/arch-v32/drivers/mach-fs/nandflash.c
> +++ b/arch/cris/arch-v32/drivers/mach-fs/nandflash.c
> @@ -50,7 +50,7 @@ static void crisv32_hwcontrol(struct mtd_info *mtd, int cmd,
>  {
>  	unsigned long flags;
>  	reg_gio_rw_pa_dout dout;
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  
>  	local_irq_save(flags);
>  
> @@ -128,7 +128,7 @@ struct mtd_info *__init crisv32_nand_flash_probe(void)
>  
>  	/* Get pointer to private data */
>  	this = &wrapper->chip;
> -	crisv32_mtd = nand_to_mtd(this);
> +	crisv32_mtd = nandchip_to_mtd(this);
>  
>  	pa_oe.oe |= 1 << CE_BIT;
>  	pa_oe.oe |= 1 << ALE_BIT;
> diff --git a/arch/mips/alchemy/devboards/db1200.c b/arch/mips/alchemy/devboards/db1200.c
> index 8383100..c59401a 100644
> --- a/arch/mips/alchemy/devboards/db1200.c
> +++ b/arch/mips/alchemy/devboards/db1200.c
> @@ -200,7 +200,7 @@ int __init db1200_board_setup(void)
>  static void au1200_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
>  				 unsigned int ctrl)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	unsigned long ioaddr = (unsigned long)this->IO_ADDR_W;
>  
>  	ioaddr &= 0xffffff00;
> diff --git a/arch/mips/alchemy/devboards/db1300.c b/arch/mips/alchemy/devboards/db1300.c
> index 3e7fbdb..0fefa40 100644
> --- a/arch/mips/alchemy/devboards/db1300.c
> +++ b/arch/mips/alchemy/devboards/db1300.c
> @@ -151,7 +151,7 @@ static void __init db1300_gpio_config(void)
>  static void au1300_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
>  				 unsigned int ctrl)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	unsigned long ioaddr = (unsigned long)this->IO_ADDR_W;
>  
>  	ioaddr &= 0xffffff00;
> diff --git a/arch/mips/alchemy/devboards/db1550.c b/arch/mips/alchemy/devboards/db1550.c
> index 421bd57..28b7c33 100644
> --- a/arch/mips/alchemy/devboards/db1550.c
> +++ b/arch/mips/alchemy/devboards/db1550.c
> @@ -128,7 +128,7 @@ int __init db1550_board_setup(void)
>  static void au1550_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
>  				 unsigned int ctrl)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	unsigned long ioaddr = (unsigned long)this->IO_ADDR_W;
>  
>  	ioaddr &= 0xffffff00;
> diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
> index a5bd94b..712cf36 100644
> --- a/arch/mips/jz4740/board-qi_lb60.c
> +++ b/arch/mips/jz4740/board-qi_lb60.c
> @@ -138,7 +138,7 @@ static void qi_lb60_nand_ident(struct platform_device *pdev,
>  		struct mtd_info *mtd, struct mtd_partition **partitions,
>  		int *num_partitions)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (chip->page_shift == 12) {
>  		*partitions = qi_lb60_partitions_2gb;
> diff --git a/arch/mips/pnx833x/common/platform.c b/arch/mips/pnx833x/common/platform.c
> index a7a4e9f..4610f3f 100644
> --- a/arch/mips/pnx833x/common/platform.c
> +++ b/arch/mips/pnx833x/common/platform.c
> @@ -180,7 +180,7 @@ struct pnx8xxx_port pnx8xxx_ports[] = {
>  static void
>  pnx833x_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	unsigned long nandaddr = (unsigned long)this->IO_ADDR_W;
>  
>  	if (cmd == NAND_CMD_NONE)
> diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c
> index 32ea3e6..b736745 100644
> --- a/arch/mips/rb532/devices.c
> +++ b/arch/mips/rb532/devices.c
> @@ -148,7 +148,7 @@ static int rb532_dev_ready(struct mtd_info *mtd)
>  
>  static void rb532_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	unsigned char orbits, nandbits;
>  
>  	if (ctrl & NAND_CTRL_CHANGE) {
> diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
> index 0bcbe58..be81869 100644
> --- a/arch/sh/boards/mach-migor/setup.c
> +++ b/arch/sh/boards/mach-migor/setup.c
> @@ -166,7 +166,7 @@
>  static void migor_nand_flash_cmd_ctl(struct mtd_info *mtd, int cmd,
>  				     unsigned int ctrl)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (cmd == NAND_CMD_NONE)
>  		return;
> diff --git a/drivers/mtd/nand/raw/ams-delta.c b/drivers/mtd/nand/raw/ams-delta.c
> index dcec9cf..be6166c 100644
> --- a/drivers/mtd/nand/raw/ams-delta.c
> +++ b/drivers/mtd/nand/raw/ams-delta.c
> @@ -64,7 +64,7 @@
>  
>  static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
>  
>  	writew(0, io_base + OMAP_MPUIO_IO_CNTL);
> @@ -77,7 +77,7 @@ static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
>  static u_char ams_delta_read_byte(struct mtd_info *mtd)
>  {
>  	u_char res;
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
>  
>  	gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 0);
> @@ -190,7 +190,7 @@ static int ams_delta_init(struct platform_device *pdev)
>  		goto out;
>  	}
>  
> -	ams_delta_mtd = nand_to_mtd(this);
> +	ams_delta_mtd = nandchip_to_mtd(this);
>  	ams_delta_mtd->owner = THIS_MODULE;
>  
>  	/*
> @@ -270,7 +270,7 @@ static int ams_delta_cleanup(struct platform_device *pdev)
>  	iounmap(io_base);
>  
>  	/* Free the MTD device structure */
> -	kfree(mtd_to_nand(ams_delta_mtd));
> +	kfree(mtd_to_nandchip(ams_delta_mtd));
>  
>  	return 0;
>  }
> diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c
> index 9abfc5d..747bcd3 100644
> --- a/drivers/mtd/nand/raw/atmel/nand-controller.c
> +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c
> @@ -403,7 +403,7 @@ static int atmel_nand_dma_transfer(struct atmel_nand_controller *nc,
>  
>  static u8 atmel_nand_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct atmel_nand *nand = to_atmel_nand(chip);
>  
>  	return ioread8(nand->activecs->io.virt);
> @@ -411,7 +411,7 @@ static u8 atmel_nand_read_byte(struct mtd_info *mtd)
>  
>  static u16 atmel_nand_read_word(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct atmel_nand *nand = to_atmel_nand(chip);
>  
>  	return ioread16(nand->activecs->io.virt);
> @@ -419,7 +419,7 @@ static u16 atmel_nand_read_word(struct mtd_info *mtd)
>  
>  static void atmel_nand_write_byte(struct mtd_info *mtd, u8 byte)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct atmel_nand *nand = to_atmel_nand(chip);
>  
>  	if (chip->options & NAND_BUSWIDTH_16)
> @@ -430,7 +430,7 @@ static void atmel_nand_write_byte(struct mtd_info *mtd, u8 byte)
>  
>  static void atmel_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct atmel_nand *nand = to_atmel_nand(chip);
>  	struct atmel_nand_controller *nc;
>  
> @@ -455,7 +455,7 @@ static void atmel_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
>  
>  static void atmel_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct atmel_nand *nand = to_atmel_nand(chip);
>  	struct atmel_nand_controller *nc;
>  
> @@ -480,7 +480,7 @@ static void atmel_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
>  
>  static int atmel_nand_dev_ready(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct atmel_nand *nand = to_atmel_nand(chip);
>  
>  	return gpiod_get_value(nand->activecs->rb.gpio);
> @@ -488,7 +488,7 @@ static int atmel_nand_dev_ready(struct mtd_info *mtd)
>  
>  static void atmel_nand_select_chip(struct mtd_info *mtd, int cs)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct atmel_nand *nand = to_atmel_nand(chip);
>  
>  	if (cs < 0 || cs >= nand->numcs) {
> @@ -505,7 +505,7 @@ static void atmel_nand_select_chip(struct mtd_info *mtd, int cs)
>  
>  static int atmel_hsmc_nand_dev_ready(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct atmel_nand *nand = to_atmel_nand(chip);
>  	struct atmel_hsmc_nand_controller *nc;
>  	u32 status;
> @@ -519,7 +519,7 @@ static int atmel_hsmc_nand_dev_ready(struct mtd_info *mtd)
>  
>  static void atmel_hsmc_nand_select_chip(struct mtd_info *mtd, int cs)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct atmel_nand *nand = to_atmel_nand(chip);
>  	struct atmel_hsmc_nand_controller *nc;
>  
> @@ -601,7 +601,7 @@ static int atmel_nfc_exec_op(struct atmel_hsmc_nand_controller *nc, bool poll)
>  static void atmel_hsmc_nand_cmd_ctrl(struct mtd_info *mtd, int dat,
>  				     unsigned int ctrl)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct atmel_nand *nand = to_atmel_nand(chip);
>  	struct atmel_hsmc_nand_controller *nc;
>  
> @@ -628,7 +628,7 @@ static void atmel_hsmc_nand_cmd_ctrl(struct mtd_info *mtd, int dat,
>  static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
>  				unsigned int ctrl)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct atmel_nand *nand = to_atmel_nand(chip);
>  	struct atmel_nand_controller *nc;
>  
> @@ -650,7 +650,7 @@ static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
>  static void atmel_nfc_copy_to_sram(struct nand_chip *chip, const u8 *buf,
>  				   bool oob_required)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct atmel_hsmc_nand_controller *nc;
>  	int ret = -EIO;
>  
> @@ -673,7 +673,7 @@ static void atmel_nfc_copy_to_sram(struct nand_chip *chip, const u8 *buf,
>  static void atmel_nfc_copy_from_sram(struct nand_chip *chip, u8 *buf,
>  				     bool oob_required)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct atmel_hsmc_nand_controller *nc;
>  	int ret = -EIO;
>  
> @@ -694,7 +694,7 @@ static void atmel_nfc_copy_from_sram(struct nand_chip *chip, u8 *buf,
>  
>  static void atmel_nfc_set_op_addr(struct nand_chip *chip, int page, int column)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct atmel_hsmc_nand_controller *nc;
>  
>  	nc = to_hsmc_nand_controller(chip->controller);
> @@ -749,7 +749,7 @@ static void atmel_nand_pmecc_disable(struct nand_chip *chip, bool raw)
>  static int atmel_nand_pmecc_generate_eccbytes(struct nand_chip *chip, bool raw)
>  {
>  	struct atmel_nand *nand = to_atmel_nand(chip);
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct atmel_nand_controller *nc;
>  	struct mtd_oob_region oobregion;
>  	void *eccbuf;
> @@ -784,7 +784,7 @@ static int atmel_nand_pmecc_correct_data(struct nand_chip *chip, void *buf,
>  					 bool raw)
>  {
>  	struct atmel_nand *nand = to_atmel_nand(chip);
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct atmel_nand_controller *nc;
>  	struct mtd_oob_region oobregion;
>  	int ret, i, max_bitflips = 0;
> @@ -833,7 +833,7 @@ static int atmel_nand_pmecc_correct_data(struct nand_chip *chip, void *buf,
>  static int atmel_nand_pmecc_write_pg(struct nand_chip *chip, const u8 *buf,
>  				     bool oob_required, int page, bool raw)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct atmel_nand *nand = to_atmel_nand(chip);
>  	int ret;
>  
> @@ -874,7 +874,7 @@ static int atmel_nand_pmecc_write_page_raw(struct mtd_info *mtd,
>  static int atmel_nand_pmecc_read_pg(struct nand_chip *chip, u8 *buf,
>  				    bool oob_required, int page, bool raw)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	int ret;
>  
>  	ret = atmel_nand_pmecc_enable(chip, NAND_ECC_READ, raw);
> @@ -909,7 +909,7 @@ static int atmel_hsmc_nand_pmecc_write_pg(struct nand_chip *chip,
>  					  const u8 *buf, bool oob_required,
>  					  int page, bool raw)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct atmel_nand *nand = to_atmel_nand(chip);
>  	struct atmel_hsmc_nand_controller *nc;
>  	int ret;
> @@ -979,7 +979,7 @@ static int atmel_hsmc_nand_pmecc_read_pg(struct nand_chip *chip, u8 *buf,
>  					 bool oob_required, int page,
>  					 bool raw)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct atmel_nand *nand = to_atmel_nand(chip);
>  	struct atmel_hsmc_nand_controller *nc;
>  	int ret;
> @@ -1048,7 +1048,7 @@ static int atmel_hsmc_nand_pmecc_read_page_raw(struct mtd_info *mtd,
>  
>  static int atmel_nand_pmecc_init(struct nand_chip *chip)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct atmel_nand *nand = to_atmel_nand(chip);
>  	struct atmel_nand_controller *nc;
>  	struct atmel_pmecc_user_req req;
> @@ -1179,7 +1179,7 @@ static void atmel_nand_init(struct atmel_nand_controller *nc,
>  			    struct atmel_nand *nand)
>  {
>  	struct nand_chip *chip = &nand->base;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  
>  	mtd->dev.parent = nc->dev;
>  	nand->base.controller = &nc->base;
> @@ -1241,7 +1241,7 @@ static void atmel_hsmc_nand_init(struct atmel_nand_controller *nc,
>  static int atmel_nand_detect(struct atmel_nand *nand)
>  {
>  	struct nand_chip *chip = &nand->base;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct atmel_nand_controller *nc;
>  	int ret;
>  
> @@ -1257,7 +1257,7 @@ static int atmel_nand_detect(struct atmel_nand *nand)
>  static int atmel_nand_unregister(struct atmel_nand *nand)
>  {
>  	struct nand_chip *chip = &nand->base;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	int ret;
>  
>  	ret = mtd_device_unregister(mtd);
> @@ -1273,7 +1273,7 @@ static int atmel_nand_unregister(struct atmel_nand *nand)
>  static int atmel_nand_register(struct atmel_nand *nand)
>  {
>  	struct nand_chip *chip = &nand->base;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct atmel_nand_controller *nc;
>  	int ret;
>  
> diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c
> index 9d4a28f..f56ce91 100644
> --- a/drivers/mtd/nand/raw/au1550nd.c
> +++ b/drivers/mtd/nand/raw/au1550nd.c
> @@ -38,7 +38,7 @@ struct au1550nd_ctx {
>   */
>  static u_char au_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	u_char ret = readb(this->IO_ADDR_R);
>  	wmb(); /* drain writebuffer */
>  	return ret;
> @@ -53,7 +53,7 @@ static u_char au_read_byte(struct mtd_info *mtd)
>   */
>  static void au_write_byte(struct mtd_info *mtd, u_char byte)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	writeb(byte, this->IO_ADDR_W);
>  	wmb(); /* drain writebuffer */
>  }
> @@ -66,7 +66,7 @@ static void au_write_byte(struct mtd_info *mtd, u_char byte)
>   */
>  static u_char au_read_byte16(struct mtd_info *mtd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
>  	wmb(); /* drain writebuffer */
>  	return ret;
> @@ -81,7 +81,7 @@ static u_char au_read_byte16(struct mtd_info *mtd)
>   */
>  static void au_write_byte16(struct mtd_info *mtd, u_char byte)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
>  	wmb(); /* drain writebuffer */
>  }
> @@ -94,7 +94,7 @@ static void au_write_byte16(struct mtd_info *mtd, u_char byte)
>   */
>  static u16 au_read_word(struct mtd_info *mtd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	u16 ret = readw(this->IO_ADDR_R);
>  	wmb(); /* drain writebuffer */
>  	return ret;
> @@ -111,7 +111,7 @@ static u16 au_read_word(struct mtd_info *mtd)
>  static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
>  {
>  	int i;
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  
>  	for (i = 0; i < len; i++) {
>  		writeb(buf[i], this->IO_ADDR_W);
> @@ -130,7 +130,7 @@ static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
>  static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
>  {
>  	int i;
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  
>  	for (i = 0; i < len; i++) {
>  		buf[i] = readb(this->IO_ADDR_R);
> @@ -149,7 +149,7 @@ static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
>  static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
>  {
>  	int i;
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	u16 *p = (u16 *) buf;
>  	len >>= 1;
>  
> @@ -171,7 +171,7 @@ static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
>  static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
>  {
>  	int i;
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	u16 *p = (u16 *) buf;
>  	len >>= 1;
>  
> @@ -196,7 +196,7 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
>  
>  static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct au1550nd_ctx *ctx = container_of(this, struct au1550nd_ctx,
>  						chip);
>  
> @@ -267,7 +267,7 @@ static void au1550_select_chip(struct mtd_info *mtd, int chip)
>   */
>  static void au1550_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct au1550nd_ctx *ctx = container_of(this, struct au1550nd_ctx,
>  						chip);
>  	int ce_override = 0, i;
> @@ -440,7 +440,7 @@ static int au1550nd_probe(struct platform_device *pdev)
>  	}
>  
>  	this = &ctx->chip;
> -	mtd = nand_to_mtd(this);
> +	mtd = nandchip_to_mtd(this);
>  	mtd->dev.parent = &pdev->dev;
>  
>  	/* figure out which CS# r->start belongs to */
> @@ -496,7 +496,7 @@ static int au1550nd_remove(struct platform_device *pdev)
>  	struct au1550nd_ctx *ctx = platform_get_drvdata(pdev);
>  	struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>  
> -	nand_release(nand_to_mtd(&ctx->chip));
> +	nand_release(nandchip_to_mtd(&ctx->chip));
>  	iounmap(ctx->base);
>  	release_mem_region(r->start, 0x1000);
>  	kfree(ctx);
> diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/main.c b/drivers/mtd/nand/raw/bcm47xxnflash/main.c
> index fb31429..564b53a 100644
> --- a/drivers/mtd/nand/raw/bcm47xxnflash/main.c
> +++ b/drivers/mtd/nand/raw/bcm47xxnflash/main.c
> @@ -35,7 +35,7 @@ static int bcm47xxnflash_probe(struct platform_device *pdev)
>  		return -ENOMEM;
>  
>  	nand_set_controller_data(&b47n->nand_chip, b47n);
> -	mtd = nand_to_mtd(&b47n->nand_chip);
> +	mtd = nandchip_to_mtd(&b47n->nand_chip);
>  	mtd->dev.parent = &pdev->dev;
>  	b47n->cc = container_of(nflash, struct bcma_drv_cc, nflash);
>  
> @@ -65,7 +65,7 @@ static int bcm47xxnflash_remove(struct platform_device *pdev)
>  {
>  	struct bcm47xxnflash *nflash = platform_get_drvdata(pdev);
>  
> -	nand_release(nand_to_mtd(&nflash->nand_chip));
> +	nand_release(nandchip_to_mtd(&nflash->nand_chip));
>  
>  	return 0;
>  }
> diff --git a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c
> index f1da4ea..78bfcdb 100644
> --- a/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c
> +++ b/drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c
> @@ -89,7 +89,7 @@ static int bcm47xxnflash_ops_bcm4706_poll(struct bcma_drv_cc *cc)
>  static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf,
>  					   int len)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
>  
>  	u32 ctlcode;
> @@ -139,7 +139,7 @@ static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf,
>  static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd,
>  					    const uint8_t *buf, int len)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
>  	struct bcma_drv_cc *cc = b47n->cc;
>  
> @@ -173,7 +173,7 @@ static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd,
>  static void bcm47xxnflash_ops_bcm4706_cmd_ctrl(struct mtd_info *mtd, int cmd,
>  					       unsigned int ctrl)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
>  	u32 code = 0;
>  
> @@ -199,7 +199,7 @@ static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd,
>  
>  static int bcm47xxnflash_ops_bcm4706_dev_ready(struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
>  
>  	return !!(bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_CTL) & NCTL_READY);
> @@ -216,7 +216,7 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
>  					      unsigned command, int column,
>  					      int page_addr)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
>  	struct bcma_drv_cc *cc = b47n->cc;
>  	u32 ctlcode;
> @@ -312,7 +312,7 @@ static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
>  
>  static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
>  	struct bcma_drv_cc *cc = b47n->cc;
>  	u32 tmp = 0;
> @@ -341,7 +341,7 @@ static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd)
>  static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd,
>  					       uint8_t *buf, int len)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
>  
>  	switch (b47n->curr_command) {
> @@ -357,7 +357,7 @@ static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd,
>  static void bcm47xxnflash_ops_bcm4706_write_buf(struct mtd_info *mtd,
>  						const uint8_t *buf, int len)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
>  
>  	switch (b47n->curr_command) {
> @@ -421,7 +421,7 @@ int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
>  			(w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0));
>  
>  	/* Scan NAND */
> -	err = nand_scan(nand_to_mtd(&b47n->nand_chip), 1);
> +	err = nand_scan(nandchip_to_mtd(&b47n->nand_chip), 1);
>  	if (err) {
>  		pr_err("Could not scan NAND flash: %d\n", err);
>  		goto exit;
> diff --git a/drivers/mtd/nand/raw/bf5xx_nand.c b/drivers/mtd/nand/raw/bf5xx_nand.c
> index 5655dca..790dbf6 100644
> --- a/drivers/mtd/nand/raw/bf5xx_nand.c
> +++ b/drivers/mtd/nand/raw/bf5xx_nand.c
> @@ -162,9 +162,9 @@ struct bf5xx_nand_info {
>  /*
>   * Conversion functions
>   */
> -static struct bf5xx_nand_info *mtd_to_nand_info(struct mtd_info *mtd)
> +static struct bf5xx_nand_info *mtd_to_nandchip_info(struct mtd_info *mtd)
>  {
> -	return container_of(mtd_to_nand(mtd), struct bf5xx_nand_info,
> +	return container_of(mtd_to_nandchip(mtd), struct bf5xx_nand_info,
>  			    chip);
>  }
>  
> @@ -230,7 +230,7 @@ static int bf5xx_nand_devready(struct mtd_info *mtd)
>  static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
>  					u_char *read_ecc, u_char *calc_ecc)
>  {
> -	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
> +	struct bf5xx_nand_info *info = mtd_to_nandchip_info(mtd);
>  	u32 syndrome[5];
>  	u32 calced, stored;
>  	int i;
> @@ -309,7 +309,7 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
>  static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat,
>  					u_char *read_ecc, u_char *calc_ecc)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	int ret, bitflips = 0;
>  
>  	ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
> @@ -341,8 +341,8 @@ static void bf5xx_nand_enable_hwecc(struct mtd_info *mtd, int mode)
>  static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd,
>  		const u_char *dat, u_char *ecc_code)
>  {
> -	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct bf5xx_nand_info *info = mtd_to_nandchip_info(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	u16 ecc0, ecc1;
>  	u32 code[2];
>  	u8 *p;
> @@ -478,8 +478,8 @@ static irqreturn_t bf5xx_nand_dma_irq(int irq, void *dev_id)
>  static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
>  				uint8_t *buf, int is_read)
>  {
> -	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct bf5xx_nand_info *info = mtd_to_nandchip_info(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	unsigned short val;
>  
>  	dev_dbg(info->device, " mtd->%p, buf->%p, is_read %d\n",
> @@ -544,8 +544,8 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
>  static void bf5xx_nand_dma_read_buf(struct mtd_info *mtd,
>  					uint8_t *buf, int len)
>  {
> -	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct bf5xx_nand_info *info = mtd_to_nandchip_info(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	dev_dbg(info->device, "mtd->%p, buf->%p, int %d\n", mtd, buf, len);
>  
> @@ -558,8 +558,8 @@ static void bf5xx_nand_dma_read_buf(struct mtd_info *mtd,
>  static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd,
>  				const uint8_t *buf, int len)
>  {
> -	struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct bf5xx_nand_info *info = mtd_to_nandchip_info(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	dev_dbg(info->device, "mtd->%p, buf->%p, len %d\n", mtd, buf, len);
>  
> @@ -673,7 +673,7 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info)
>   */
>  static int bf5xx_nand_add_partition(struct bf5xx_nand_info *info)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(&info->chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&info->chip);
>  	struct mtd_partition *parts = info->platform->partitions;
>  	int nr = info->platform->nr_partitions;
>  
> @@ -688,7 +688,7 @@ static int bf5xx_nand_remove(struct platform_device *pdev)
>  	 * and their partitions, then go through freeing the
>  	 * resources used
>  	 */
> -	nand_release(nand_to_mtd(&info->chip));
> +	nand_release(nandchip_to_mtd(&info->chip));
>  
>  	peripheral_free_list(bfin_nfc_pin_req);
>  	bf5xx_nand_dma_remove(info);
> @@ -698,7 +698,7 @@ static int bf5xx_nand_remove(struct platform_device *pdev)
>  
>  static int bf5xx_nand_scan(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	int ret;
>  
>  	ret = nand_scan_ident(mtd, 1, NULL);
> @@ -768,7 +768,7 @@ static int bf5xx_nand_probe(struct platform_device *pdev)
>  
>  	/* initialise chip data struct */
>  	chip = &info->chip;
> -	mtd = nand_to_mtd(&info->chip);
> +	mtd = nandchip_to_mtd(&info->chip);
>  
>  	if (plat->data_width)
>  		chip->options |= NAND_BUSWIDTH_16;
> diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
> index e0eb51d..c3c22ba 100644
> --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
> +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
> @@ -872,7 +872,7 @@ static inline bool is_hamming_ecc(struct brcmnand_controller *ctrl,
>  static int brcmnand_hamming_ooblayout_ecc(struct mtd_info *mtd, int section,
>  					  struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct brcmnand_host *host = nand_get_controller_data(chip);
>  	struct brcmnand_cfg *cfg = &host->hwcfg;
>  	int sas = cfg->spare_area_size << cfg->sector_size_1k;
> @@ -890,7 +890,7 @@ static int brcmnand_hamming_ooblayout_ecc(struct mtd_info *mtd, int section,
>  static int brcmnand_hamming_ooblayout_free(struct mtd_info *mtd, int section,
>  					   struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct brcmnand_host *host = nand_get_controller_data(chip);
>  	struct brcmnand_cfg *cfg = &host->hwcfg;
>  	int sas = cfg->spare_area_size << cfg->sector_size_1k;
> @@ -930,7 +930,7 @@ static int brcmnand_hamming_ooblayout_free(struct mtd_info *mtd, int section,
>  static int brcmnand_bch_ooblayout_ecc(struct mtd_info *mtd, int section,
>  				      struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct brcmnand_host *host = nand_get_controller_data(chip);
>  	struct brcmnand_cfg *cfg = &host->hwcfg;
>  	int sas = cfg->spare_area_size << cfg->sector_size_1k;
> @@ -948,7 +948,7 @@ static int brcmnand_bch_ooblayout_ecc(struct mtd_info *mtd, int section,
>  static int brcmnand_bch_ooblayout_free_lp(struct mtd_info *mtd, int section,
>  					  struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct brcmnand_host *host = nand_get_controller_data(chip);
>  	struct brcmnand_cfg *cfg = &host->hwcfg;
>  	int sas = cfg->spare_area_size << cfg->sector_size_1k;
> @@ -974,7 +974,7 @@ static int brcmnand_bch_ooblayout_free_lp(struct mtd_info *mtd, int section,
>  static int brcmnand_bch_ooblayout_free_sp(struct mtd_info *mtd, int section,
>  					  struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct brcmnand_host *host = nand_get_controller_data(chip);
>  	struct brcmnand_cfg *cfg = &host->hwcfg;
>  	int sas = cfg->spare_area_size << cfg->sector_size_1k;
> @@ -1007,7 +1007,7 @@ static int brcmnand_bch_ooblayout_free_sp(struct mtd_info *mtd, int section,
>  static int brcmstb_choose_ecc_layout(struct brcmnand_host *host)
>  {
>  	struct brcmnand_cfg *p = &host->hwcfg;
> -	struct mtd_info *mtd = nand_to_mtd(&host->chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&host->chip);
>  	struct nand_ecc_ctrl *ecc = &host->chip.ecc;
>  	unsigned int ecc_level = p->ecc_level;
>  	int sas = p->spare_area_size << p->sector_size_1k;
> @@ -1046,7 +1046,7 @@ static int brcmstb_choose_ecc_layout(struct brcmnand_host *host)
>  
>  static void brcmnand_wp(struct mtd_info *mtd, int wp)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct brcmnand_host *host = nand_get_controller_data(chip);
>  	struct brcmnand_controller *ctrl = host->ctrl;
>  
> @@ -1239,7 +1239,7 @@ static void brcmnand_cmd_ctrl(struct mtd_info *mtd, int dat,
>  
>  static int brcmnand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct brcmnand_host *host = nand_get_controller_data(chip);
>  	struct brcmnand_controller *ctrl = host->ctrl;
>  	unsigned long timeo = msecs_to_jiffies(100);
> @@ -1274,7 +1274,7 @@ static int brcmnand_low_level_op(struct brcmnand_host *host,
>  				 enum brcmnand_llop_type type, u32 data,
>  				 bool last_op)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(&host->chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&host->chip);
>  	struct nand_chip *chip = &host->chip;
>  	struct brcmnand_controller *ctrl = host->ctrl;
>  	u32 tmp;
> @@ -1313,7 +1313,7 @@ static int brcmnand_low_level_op(struct brcmnand_host *host,
>  static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command,
>  			     int column, int page_addr)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct brcmnand_host *host = nand_get_controller_data(chip);
>  	struct brcmnand_controller *ctrl = host->ctrl;
>  	u64 addr = (u64)page_addr << chip->page_shift;
> @@ -1419,7 +1419,7 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command,
>  
>  static uint8_t brcmnand_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct brcmnand_host *host = nand_get_controller_data(chip);
>  	struct brcmnand_controller *ctrl = host->ctrl;
>  	uint8_t ret = 0;
> @@ -1486,7 +1486,7 @@ static void brcmnand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
>  				   int len)
>  {
>  	int i;
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct brcmnand_host *host = nand_get_controller_data(chip);
>  
>  	switch (host->last_cmd) {
> @@ -2083,7 +2083,7 @@ static inline int get_blk_adr_bytes(u64 size, u32 writesize)
>  
>  static int brcmnand_setup_dev(struct brcmnand_host *host)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(&host->chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&host->chip);
>  	struct nand_chip *chip = &host->chip;
>  	struct brcmnand_controller *ctrl = host->ctrl;
>  	struct brcmnand_cfg *cfg = &host->hwcfg;
> @@ -2223,7 +2223,7 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn)
>  		return -ENXIO;
>  	}
>  
> -	mtd = nand_to_mtd(&host->chip);
> +	mtd = nandchip_to_mtd(&host->chip);
>  	chip = &host->chip;
>  
>  	nand_set_flash_node(chip, dn);
> @@ -2369,7 +2369,7 @@ static int brcmnand_resume(struct device *dev)
>  
>  	list_for_each_entry(host, &ctrl->host_list, node) {
>  		struct nand_chip *chip = &host->chip;
> -		struct mtd_info *mtd = nand_to_mtd(chip);
> +		struct mtd_info *mtd = nandchip_to_mtd(chip);
>  
>  		brcmnand_save_restore_cs_config(host, 1);
>  
> @@ -2601,7 +2601,7 @@ int brcmnand_remove(struct platform_device *pdev)
>  	struct brcmnand_host *host;
>  
>  	list_for_each_entry(host, &ctrl->host_list, node)
> -		nand_release(nand_to_mtd(&host->chip));
> +		nand_release(nandchip_to_mtd(&host->chip));
>  
>  	clk_disable_unprepare(ctrl->clk);
>  
> diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
> index 0541c64..7b4bf88 100644
> --- a/drivers/mtd/nand/raw/cafe_nand.c
> +++ b/drivers/mtd/nand/raw/cafe_nand.c
> @@ -101,7 +101,7 @@ struct cafe_priv {
>  
>  static int cafe_device_ready(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct cafe_priv *cafe = nand_get_controller_data(chip);
>  	int result = !!(cafe_readl(cafe, NAND_STATUS) & 0x40000000);
>  	uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
> @@ -118,7 +118,7 @@ static int cafe_device_ready(struct mtd_info *mtd)
>  
>  static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct cafe_priv *cafe = nand_get_controller_data(chip);
>  
>  	if (usedma)
> @@ -134,7 +134,7 @@ static void cafe_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
>  
>  static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct cafe_priv *cafe = nand_get_controller_data(chip);
>  
>  	if (usedma)
> @@ -149,7 +149,7 @@ static void cafe_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  
>  static uint8_t cafe_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct cafe_priv *cafe = nand_get_controller_data(chip);
>  	uint8_t d;
>  
> @@ -162,7 +162,7 @@ static uint8_t cafe_read_byte(struct mtd_info *mtd)
>  static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
>  			      int column, int page_addr)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct cafe_priv *cafe = nand_get_controller_data(chip);
>  	int adrbytes = 0;
>  	uint32_t ctl1;
> @@ -318,7 +318,7 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
>  
>  static void cafe_select_chip(struct mtd_info *mtd, int chipnr)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct cafe_priv *cafe = nand_get_controller_data(chip);
>  
>  	cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
> @@ -334,7 +334,7 @@ static void cafe_select_chip(struct mtd_info *mtd, int chipnr)
>  static irqreturn_t cafe_nand_interrupt(int irq, void *id)
>  {
>  	struct mtd_info *mtd = id;
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct cafe_priv *cafe = nand_get_controller_data(chip);
>  	uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
>  	cafe_writel(cafe, irqs & ~0x90000000, NAND_IRQ);
> @@ -462,7 +462,7 @@ static int cafe_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
>  static int cafe_ooblayout_ecc(struct mtd_info *mtd, int section,
>  			      struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (section)
>  		return -ERANGE;
> @@ -476,7 +476,7 @@ static int cafe_ooblayout_ecc(struct mtd_info *mtd, int section,
>  static int cafe_ooblayout_free(struct mtd_info *mtd, int section,
>  			       struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (section)
>  		return -ERANGE;
> @@ -630,7 +630,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
>  	if (!cafe)
>  		return  -ENOMEM;
>  
> -	mtd = nand_to_mtd(&cafe->nand);
> +	mtd = nandchip_to_mtd(&cafe->nand);
>  	mtd->dev.parent = &pdev->dev;
>  	nand_set_controller_data(&cafe->nand, cafe);
>  
> @@ -818,7 +818,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
>  static void cafe_nand_remove(struct pci_dev *pdev)
>  {
>  	struct mtd_info *mtd = pci_get_drvdata(pdev);
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct cafe_priv *cafe = nand_get_controller_data(chip);
>  
>  	/* Disable NAND IRQ in global IRQ mask register */
> @@ -846,7 +846,7 @@ static int cafe_nand_resume(struct pci_dev *pdev)
>  {
>  	uint32_t ctrl;
>  	struct mtd_info *mtd = pci_get_drvdata(pdev);
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct cafe_priv *cafe = nand_get_controller_data(chip);
>  
>         /* Start off by resetting the NAND controller completely */
> diff --git a/drivers/mtd/nand/raw/cmx270_nand.c b/drivers/mtd/nand/raw/cmx270_nand.c
> index 1fc435f..b85ccab 100644
> --- a/drivers/mtd/nand/raw/cmx270_nand.c
> +++ b/drivers/mtd/nand/raw/cmx270_nand.c
> @@ -53,7 +53,7 @@
>  
>  static u_char cmx270_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  
>  	return (readl(this->IO_ADDR_R) >> 16);
>  }
> @@ -61,7 +61,7 @@ static u_char cmx270_read_byte(struct mtd_info *mtd)
>  static void cmx270_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
>  {
>  	int i;
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  
>  	for (i=0; i<len; i++)
>  		writel((*buf++ << 16), this->IO_ADDR_W);
> @@ -70,7 +70,7 @@ static void cmx270_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
>  static void cmx270_read_buf(struct mtd_info *mtd, u_char *buf, int len)
>  {
>  	int i;
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  
>  	for (i=0; i<len; i++)
>  		*buf++ = readl(this->IO_ADDR_R) >> 16;
> @@ -94,7 +94,7 @@ static void nand_cs_off(void)
>  static void cmx270_hwcontrol(struct mtd_info *mtd, int dat,
>  			     unsigned int ctrl)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	unsigned int nandaddr = (unsigned int)this->IO_ADDR_W;
>  
>  	dsb();
> @@ -173,7 +173,7 @@ static int __init cmx270_init(void)
>  		goto err_ioremap;
>  	}
>  
> -	cmx270_nand_mtd = nand_to_mtd(this);
> +	cmx270_nand_mtd = nandchip_to_mtd(this);
>  
>  	/* Link the private data with the MTD structure */
>  	cmx270_nand_mtd->owner = THIS_MODULE;
> @@ -237,7 +237,7 @@ static void __exit cmx270_cleanup(void)
>  
>  	iounmap(cmx270_nand_io);
>  
> -	kfree(mtd_to_nand(cmx270_nand_mtd));
> +	kfree(mtd_to_nandchip(cmx270_nand_mtd));
>  }
>  module_exit(cmx270_cleanup);
>  
> diff --git a/drivers/mtd/nand/raw/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c
> index d488775..63149e2 100644
> --- a/drivers/mtd/nand/raw/cs553x_nand.c
> +++ b/drivers/mtd/nand/raw/cs553x_nand.c
> @@ -97,7 +97,7 @@
>  
>  static void cs553x_read_buf(struct mtd_info *mtd, u_char *buf, int len)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  
>  	while (unlikely(len > 0x800)) {
>  		memcpy_fromio(buf, this->IO_ADDR_R, 0x800);
> @@ -109,7 +109,7 @@ static void cs553x_read_buf(struct mtd_info *mtd, u_char *buf, int len)
>  
>  static void cs553x_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  
>  	while (unlikely(len > 0x800)) {
>  		memcpy_toio(this->IO_ADDR_R, buf, 0x800);
> @@ -121,13 +121,13 @@ static void cs553x_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
>  
>  static unsigned char cs553x_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	return readb(this->IO_ADDR_R);
>  }
>  
>  static void cs553x_write_byte(struct mtd_info *mtd, u_char byte)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	int i = 100000;
>  
>  	while (i && readb(this->IO_ADDR_R + MM_NAND_STS) & CS_NAND_CTLR_BUSY) {
> @@ -140,7 +140,7 @@ static void cs553x_write_byte(struct mtd_info *mtd, u_char byte)
>  static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd,
>  			     unsigned int ctrl)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	void __iomem *mmio_base = this->IO_ADDR_R;
>  	if (ctrl & NAND_CTRL_CHANGE) {
>  		unsigned char ctl = (ctrl & ~NAND_CTRL_CHANGE ) ^ 0x01;
> @@ -152,7 +152,7 @@ static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd,
>  
>  static int cs553x_device_ready(struct mtd_info *mtd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	void __iomem *mmio_base = this->IO_ADDR_R;
>  	unsigned char foo = readb(mmio_base + MM_NAND_STS);
>  
> @@ -161,7 +161,7 @@ static int cs553x_device_ready(struct mtd_info *mtd)
>  
>  static void cs_enable_hwecc(struct mtd_info *mtd, int mode)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	void __iomem *mmio_base = this->IO_ADDR_R;
>  
>  	writeb(0x07, mmio_base + MM_NAND_ECC_CTL);
> @@ -170,7 +170,7 @@ static void cs_enable_hwecc(struct mtd_info *mtd, int mode)
>  static int cs_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
>  {
>  	uint32_t ecc;
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	void __iomem *mmio_base = this->IO_ADDR_R;
>  
>  	ecc = readl(mmio_base + MM_NAND_STS);
> @@ -203,7 +203,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
>  		goto out;
>  	}
>  
> -	new_mtd = nand_to_mtd(this);
> +	new_mtd = nandchip_to_mtd(this);
>  
>  	/* Link the private data with the MTD structure */
>  	new_mtd->owner = THIS_MODULE;
> @@ -334,7 +334,7 @@ static void __exit cs553x_cleanup(void)
>  		if (!mtd)
>  			continue;
>  
> -		this = mtd_to_nand(mtd);
> +		this = mtd_to_nandchip(mtd);
>  		mmio_base = this->IO_ADDR_R;
>  
>  		/* Release resources, unregister device */
> diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
> index ccc8c43..73b696a 100644
> --- a/drivers/mtd/nand/raw/davinci_nand.c
> +++ b/drivers/mtd/nand/raw/davinci_nand.c
> @@ -79,7 +79,7 @@ struct davinci_nand_info {
>  
>  static inline struct davinci_nand_info *to_davinci_nand(struct mtd_info *mtd)
>  {
> -	return container_of(mtd_to_nand(mtd), struct davinci_nand_info, chip);
> +	return container_of(mtd_to_nandchip(mtd), struct davinci_nand_info, chip);
>  }
>  
>  static inline unsigned int davinci_nand_readl(struct davinci_nand_info *info,
> @@ -105,7 +105,7 @@ static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd,
>  {
>  	struct davinci_nand_info	*info = to_davinci_nand(mtd);
>  	uint32_t			addr = info->current_cs;
> -	struct nand_chip		*nand = mtd_to_nand(mtd);
> +	struct nand_chip		*nand = mtd_to_nandchip(mtd);
>  
>  	/* Did the control lines change? */
>  	if (ctrl & NAND_CTRL_CHANGE) {
> @@ -191,7 +191,7 @@ static int nand_davinci_calculate_1bit(struct mtd_info *mtd,
>  static int nand_davinci_correct_1bit(struct mtd_info *mtd, u_char *dat,
>  				     u_char *read_ecc, u_char *calc_ecc)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	uint32_t eccNand = read_ecc[0] | (read_ecc[1] << 8) |
>  					  (read_ecc[2] << 16);
>  	uint32_t eccCalc = calc_ecc[0] | (calc_ecc[1] << 8) |
> @@ -441,7 +441,7 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd,
>   */
>  static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if ((0x03 & ((unsigned)buf)) == 0 && (0x03 & len) == 0)
>  		ioread32_rep(chip->IO_ADDR_R, buf, len >> 2);
> @@ -454,7 +454,7 @@ static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  static void nand_davinci_write_buf(struct mtd_info *mtd,
>  		const uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if ((0x03 & ((unsigned)buf)) == 0 && (0x03 & len) == 0)
>  		iowrite32_rep(chip->IO_ADDR_R, buf, len >> 2);
> @@ -665,7 +665,7 @@ static int nand_davinci_probe(struct platform_device *pdev)
>  	info->base		= base;
>  	info->vaddr		= vaddr;
>  
> -	mtd			= nand_to_mtd(&info->chip);
> +	mtd			= nandchip_to_mtd(&info->chip);
>  	mtd->dev.parent		= &pdev->dev;
>  	nand_set_flash_node(&info->chip, pdev->dev.of_node);
>  
> @@ -854,7 +854,7 @@ static int nand_davinci_remove(struct platform_device *pdev)
>  		ecc4_busy = false;
>  	spin_unlock_irq(&davinci_nand_lock);
>  
> -	nand_release(nand_to_mtd(&info->chip));
> +	nand_release(nandchip_to_mtd(&info->chip));
>  
>  	clk_disable_unprepare(info->clk);
>  
> diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c
> index 16634df..2e19fb3 100644
> --- a/drivers/mtd/nand/raw/denali.c
> +++ b/drivers/mtd/nand/raw/denali.c
> @@ -74,7 +74,7 @@
>   */
>  static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd)
>  {
> -	return container_of(mtd_to_nand(mtd), struct denali_nand_info, nand);
> +	return container_of(mtd_to_nandchip(mtd), struct denali_nand_info, nand);
>  }
>  
>  /*
> @@ -855,7 +855,7 @@ static int denali_hw_ecc_fixup(struct mtd_info *mtd,
>  			       struct denali_nand_info *denali,
>  			       unsigned long *uncor_ecc_flags)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	int bank = denali->flash_bank;
>  	uint32_t ecc_cor;
>  	unsigned int max_bitflips;
> @@ -1357,7 +1357,7 @@ static int denali_ooblayout_ecc(struct mtd_info *mtd, int section,
>  				struct mtd_oob_region *oobregion)
>  {
>  	struct denali_nand_info *denali = mtd_to_denali(mtd);
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (section)
>  		return -ERANGE;
> @@ -1372,7 +1372,7 @@ static int denali_ooblayout_free(struct mtd_info *mtd, int section,
>  				 struct mtd_oob_region *oobregion)
>  {
>  	struct denali_nand_info *denali = mtd_to_denali(mtd);
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (section)
>  		return -ERANGE;
> @@ -1436,7 +1436,7 @@ static void denali_drv_init(struct denali_nand_info *denali)
>  static int denali_multidev_fixup(struct denali_nand_info *denali)
>  {
>  	struct nand_chip *chip = &denali->nand;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  
>  	/*
>  	 * Support for multi device:
> @@ -1487,7 +1487,7 @@ static int denali_multidev_fixup(struct denali_nand_info *denali)
>  int denali_init(struct denali_nand_info *denali)
>  {
>  	struct nand_chip *chip = &denali->nand;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&denali->nand);
>  	int ret;
>  
>  	if (denali->platform == INTEL_CE4100) {
> @@ -1647,7 +1647,7 @@ int denali_init(struct denali_nand_info *denali)
>  /* driver exit point */
>  void denali_remove(struct denali_nand_info *denali)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(&denali->nand);
> +	struct mtd_info *mtd = nandchip_to_mtd(&denali->nand);
>  	/*
>  	 * Pre-compute DMA buffer size to avoid any problems in case
>  	 * nand_release() ever changes in a way that mtd->writesize and
> diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c
> index c3aa53c..5c2dc9b 100644
> --- a/drivers/mtd/nand/raw/diskonchip.c
> +++ b/drivers/mtd/nand/raw/diskonchip.c
> @@ -295,7 +295,7 @@ static inline int DoC_WaitReady(struct doc_priv *doc)
>  
>  static void doc2000_write_byte(struct mtd_info *mtd, u_char datum)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  
> @@ -307,7 +307,7 @@ static void doc2000_write_byte(struct mtd_info *mtd, u_char datum)
>  
>  static u_char doc2000_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  	u_char ret;
> @@ -322,7 +322,7 @@ static u_char doc2000_read_byte(struct mtd_info *mtd)
>  
>  static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  	int i;
> @@ -339,7 +339,7 @@ static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
>  
>  static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  	int i;
> @@ -354,7 +354,7 @@ static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len)
>  
>  static void doc2000_readbuf_dword(struct mtd_info *mtd, u_char *buf, int len)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  	int i;
> @@ -375,7 +375,7 @@ static void doc2000_readbuf_dword(struct mtd_info *mtd, u_char *buf, int len)
>  
>  static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	uint16_t ret;
>  
> @@ -421,7 +421,7 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
>  
>  static void __init doc2000_count_chips(struct mtd_info *mtd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	uint16_t mfrid;
>  	int i;
> @@ -457,7 +457,7 @@ static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this)
>  
>  static void doc2001_write_byte(struct mtd_info *mtd, u_char datum)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  
> @@ -468,7 +468,7 @@ static void doc2001_write_byte(struct mtd_info *mtd, u_char datum)
>  
>  static u_char doc2001_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  
> @@ -482,7 +482,7 @@ static u_char doc2001_read_byte(struct mtd_info *mtd)
>  
>  static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  	int i;
> @@ -495,7 +495,7 @@ static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
>  
>  static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  	int i;
> @@ -512,7 +512,7 @@ static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len)
>  
>  static u_char doc2001plus_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  	u_char ret;
> @@ -527,7 +527,7 @@ static u_char doc2001plus_read_byte(struct mtd_info *mtd)
>  
>  static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  	int i;
> @@ -545,7 +545,7 @@ static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int le
>  
>  static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  	int i;
> @@ -576,7 +576,7 @@ static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len)
>  
>  static void doc2001plus_select_chip(struct mtd_info *mtd, int chip)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  	int floor = 0;
> @@ -603,7 +603,7 @@ static void doc2001plus_select_chip(struct mtd_info *mtd, int chip)
>  
>  static void doc200x_select_chip(struct mtd_info *mtd, int chip)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  	int floor = 0;
> @@ -634,7 +634,7 @@ static void doc200x_select_chip(struct mtd_info *mtd, int chip)
>  static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
>  			      unsigned int ctrl)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  
> @@ -657,7 +657,7 @@ static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
>  
>  static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  
> @@ -763,7 +763,7 @@ static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int colu
>  
>  static int doc200x_dev_ready(struct mtd_info *mtd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  
> @@ -803,7 +803,7 @@ static int doc200x_block_bad(struct mtd_info *mtd, loff_t ofs)
>  
>  static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  
> @@ -822,7 +822,7 @@ static void doc200x_enable_hwecc(struct mtd_info *mtd, int mode)
>  
>  static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  
> @@ -842,7 +842,7 @@ static void doc2001plus_enable_hwecc(struct mtd_info *mtd, int mode)
>  /* This code is only called on write */
>  static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, unsigned char *ecc_code)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  	int i;
> @@ -903,7 +903,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,
>  				u_char *read_ecc, u_char *isnull)
>  {
>  	int i, ret = 0;
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	void __iomem *docptr = doc->virtadr;
>  	uint8_t calc_ecc[6];
> @@ -1004,7 +1004,7 @@ static int doc200x_ooblayout_free(struct mtd_info *mtd, int section,
>     mh1_page in the DOC private structure. */
>  static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const char *id, int findmirror)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	unsigned offs;
>  	int ret;
> @@ -1047,7 +1047,7 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const ch
>  
>  static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	int ret = 0;
>  	u_char *buf;
> @@ -1149,7 +1149,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio
>  /* This is a stripped-down copy of the code in inftlmount.c */
>  static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	int ret = 0;
>  	u_char *buf;
> @@ -1269,7 +1269,7 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti
>  static int __init nftl_scan_bbt(struct mtd_info *mtd)
>  {
>  	int ret, numparts;
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	struct mtd_partition parts[2];
>  
> @@ -1304,7 +1304,7 @@ static int __init nftl_scan_bbt(struct mtd_info *mtd)
>  static int __init inftl_scan_bbt(struct mtd_info *mtd)
>  {
>  	int ret, numparts;
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  	struct mtd_partition parts[5];
>  
> @@ -1357,7 +1357,7 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd)
>  
>  static inline int __init doc2000_init(struct mtd_info *mtd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  
>  	this->read_byte = doc2000_read_byte;
> @@ -1373,7 +1373,7 @@ static inline int __init doc2000_init(struct mtd_info *mtd)
>  
>  static inline int __init doc2001_init(struct mtd_info *mtd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  
>  	this->read_byte = doc2001_read_byte;
> @@ -1403,7 +1403,7 @@ static inline int __init doc2001_init(struct mtd_info *mtd)
>  
>  static inline int __init doc2001plus_init(struct mtd_info *mtd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct doc_priv *doc = nand_get_controller_data(this);
>  
>  	this->read_byte = doc2001plus_read_byte;
> @@ -1520,7 +1520,7 @@ static int __init doc_probe(unsigned long physadr)
>  	for (mtd = doclist; mtd; mtd = doc->nextdoc) {
>  		unsigned char oldval;
>  		unsigned char newval;
> -		nand = mtd_to_nand(mtd);
> +		nand = mtd_to_nandchip(mtd);
>  		doc = nand_get_controller_data(nand);
>  		/* Use the alias resolution register to determine if this is
>  		   in fact the same DOC aliased to a new address.  If writes
> @@ -1561,7 +1561,7 @@ static int __init doc_probe(unsigned long physadr)
>  		goto fail;
>  	}
>  
> -	mtd			= nand_to_mtd(nand);
> +	mtd			= nandchip_to_mtd(nand);
>  	doc			= (struct doc_priv *) (nand + 1);
>  	nand->bbt_td		= (struct nand_bbt_descr *) (doc + 1);
>  	nand->bbt_md		= nand->bbt_td + 1;
> @@ -1640,7 +1640,7 @@ static void release_nanddoc(void)
>  	struct doc_priv *doc;
>  
>  	for (mtd = doclist; mtd; mtd = nextmtd) {
> -		nand = mtd_to_nand(mtd);
> +		nand = mtd_to_nandchip(mtd);
>  		doc = nand_get_controller_data(nand);
>  
>  		nextmtd = doc->nextdoc;
> diff --git a/drivers/mtd/nand/raw/docg4.c b/drivers/mtd/nand/raw/docg4.c
> index e038130..c4a4089 100644
> --- a/drivers/mtd/nand/raw/docg4.c
> +++ b/drivers/mtd/nand/raw/docg4.c
> @@ -264,7 +264,7 @@ static inline void write_nop(void __iomem *docptr)
>  static void docg4_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  {
>  	int i;
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	uint16_t *p = (uint16_t *) buf;
>  	len >>= 1;
>  
> @@ -275,7 +275,7 @@ static void docg4_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  static void docg4_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
>  {
>  	int i;
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	uint16_t *p = (uint16_t *) buf;
>  	len >>= 1;
>  
> @@ -340,7 +340,7 @@ static void docg4_select_chip(struct mtd_info *mtd, int chip)
>  	 * Select among multiple cascaded chips ("floors").  Multiple floors are
>  	 * not yet supported, so the only valid non-negative value is 0.
>  	 */
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct docg4_priv *doc = nand_get_controller_data(nand);
>  	void __iomem *docptr = doc->virtadr;
>  
> @@ -359,7 +359,7 @@ static void reset(struct mtd_info *mtd)
>  {
>  	/* full device reset */
>  
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct docg4_priv *doc = nand_get_controller_data(nand);
>  	void __iomem *docptr = doc->virtadr;
>  
> @@ -397,7 +397,7 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page)
>  	 * Up to four bitflips can be corrected.
>  	 */
>  
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct docg4_priv *doc = nand_get_controller_data(nand);
>  	void __iomem *docptr = doc->virtadr;
>  	int i, numerrs, errpos[4];
> @@ -486,7 +486,7 @@ static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page)
>  
>  static uint8_t docg4_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct docg4_priv *doc = nand_get_controller_data(nand);
>  
>  	dev_dbg(doc->dev, "%s\n", __func__);
> @@ -567,7 +567,7 @@ static int pageprog(struct mtd_info *mtd)
>  	 * internal buffer out to the flash array, or some such.
>  	 */
>  
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct docg4_priv *doc = nand_get_controller_data(nand);
>  	void __iomem *docptr = doc->virtadr;
>  	int retval = 0;
> @@ -604,7 +604,7 @@ static void sequence_reset(struct mtd_info *mtd)
>  {
>  	/* common starting sequence for all operations */
>  
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct docg4_priv *doc = nand_get_controller_data(nand);
>  	void __iomem *docptr = doc->virtadr;
>  
> @@ -621,7 +621,7 @@ static void read_page_prologue(struct mtd_info *mtd, uint32_t docg4_addr)
>  {
>  	/* first step in reading a page */
>  
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct docg4_priv *doc = nand_get_controller_data(nand);
>  	void __iomem *docptr = doc->virtadr;
>  
> @@ -648,7 +648,7 @@ static void write_page_prologue(struct mtd_info *mtd, uint32_t docg4_addr)
>  {
>  	/* first step in writing a page */
>  
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct docg4_priv *doc = nand_get_controller_data(nand);
>  	void __iomem *docptr = doc->virtadr;
>  
> @@ -713,7 +713,7 @@ static void docg4_command(struct mtd_info *mtd, unsigned command, int column,
>  {
>  	/* handle standard nand commands */
>  
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct docg4_priv *doc = nand_get_controller_data(nand);
>  	uint32_t g4_addr = mtd_to_docg4_address(page_addr, column);
>  
> @@ -896,7 +896,7 @@ static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
>  
>  static int docg4_erase_block(struct mtd_info *mtd, int page)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct docg4_priv *doc = nand_get_controller_data(nand);
>  	void __iomem *docptr = doc->virtadr;
>  	uint16_t g4_page;
> @@ -1038,7 +1038,7 @@ static int __init read_factory_bbt(struct mtd_info *mtd)
>  	 * update the memory-based bbt accordingly.
>  	 */
>  
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct docg4_priv *doc = nand_get_controller_data(nand);
>  	uint32_t g4_addr = mtd_to_docg4_address(DOCG4_FACTORY_BBT_PAGE, 0);
>  	uint8_t *buf;
> @@ -1111,7 +1111,7 @@ static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs)
>  
>  	int ret, i;
>  	uint8_t *buf;
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct docg4_priv *doc = nand_get_controller_data(nand);
>  	struct nand_bbt_descr *bbtd = nand->badblock_pattern;
>  	int page = (int)(ofs >> nand->page_shift);
> @@ -1224,7 +1224,7 @@ static void __init init_mtd_structs(struct mtd_info *mtd)
>  	 * things as well, such as call nand_set_defaults().
>  	 */
>  
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct docg4_priv *doc = nand_get_controller_data(nand);
>  
>  	mtd->size = DOCG4_CHIP_SIZE;
> @@ -1282,7 +1282,7 @@ static void __init init_mtd_structs(struct mtd_info *mtd)
>  
>  static int __init read_id_reg(struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct docg4_priv *doc = nand_get_controller_data(nand);
>  	void __iomem *docptr = doc->virtadr;
>  	uint16_t id1, id2;
> @@ -1333,7 +1333,7 @@ static int __init probe_docg4(struct platform_device *pdev)
>  		goto fail_unmap;
>  	}
>  
> -	mtd = nand_to_mtd(nand);
> +	mtd = nandchip_to_mtd(nand);
>  	doc = (struct docg4_priv *) (nand + 1);
>  	nand_set_controller_data(nand, doc);
>  	mtd->dev.parent = &pdev->dev;
> @@ -1389,7 +1389,7 @@ static int __exit cleanup_docg4(struct platform_device *pdev)
>  	struct docg4_priv *doc = platform_get_drvdata(pdev);
>  	nand_release(doc->mtd);
>  	free_bch(doc->bch);
> -	kfree(mtd_to_nand(doc->mtd));
> +	kfree(mtd_to_nandchip(doc->mtd));
>  	iounmap(doc->virtadr);
>  	return 0;
>  }
> diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c
> index 7d8453e..f0ea638 100644
> --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c
> +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c
> @@ -82,7 +82,7 @@ struct fsl_elbc_fcm_ctrl {
>  static int fsl_elbc_ooblayout_ecc(struct mtd_info *mtd, int section,
>  				  struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
>  
>  	if (section >= chip->ecc.steps)
> @@ -100,7 +100,7 @@ static int fsl_elbc_ooblayout_ecc(struct mtd_info *mtd, int section,
>  static int fsl_elbc_ooblayout_free(struct mtd_info *mtd, int section,
>  				   struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
>  
>  	if (section > chip->ecc.steps)
> @@ -164,7 +164,7 @@ static int fsl_elbc_ooblayout_free(struct mtd_info *mtd, int section,
>   */
>  static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
>  	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
>  	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> @@ -215,7 +215,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
>   */
>  static int fsl_elbc_run_command(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
>  	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
>  	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
> @@ -320,7 +320,7 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
>  static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
>                               int column, int page_addr)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
>  	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
>  	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
> @@ -545,7 +545,7 @@ static void fsl_elbc_select_chip(struct mtd_info *mtd, int chip)
>   */
>  static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
>  	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
>  	unsigned int bufsize = mtd->writesize + mtd->oobsize;
> @@ -583,7 +583,7 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
>   */
>  static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
>  	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
>  
> @@ -600,7 +600,7 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
>   */
>  static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
>  	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
>  	int avail;
> @@ -639,7 +639,7 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
>  
>  static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
>  	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
>  	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> @@ -754,7 +754,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
>  	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
>  	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
>  	struct nand_chip *chip = &priv->chip;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  
>  	dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
>  
> @@ -809,7 +809,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
>  static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
>  {
>  	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
> -	struct mtd_info *mtd = nand_to_mtd(&priv->chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&priv->chip);
>  
>  	nand_release(mtd);
>  
> @@ -899,9 +899,9 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev)
>  		goto err;
>  	}
>  
> -	mtd = nand_to_mtd(&priv->chip);
> +	mtd = nandchip_to_mtd(&priv->chip);
>  	mtd->name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start);
> -	if (!nand_to_mtd(&priv->chip)->name) {
> +	if (!nandchip_to_mtd(&priv->chip)->name) {
>  		ret = -ENOMEM;
>  		goto err;
>  	}
> diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c
> index b9b8534..09ae754 100644
> --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c
> +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c
> @@ -96,7 +96,7 @@ struct fsl_ifc_nand_ctrl {
>  static int fsl_ifc_ooblayout_ecc(struct mtd_info *mtd, int section,
>  				 struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (section)
>  		return -ERANGE;
> @@ -110,7 +110,7 @@ static int fsl_ifc_ooblayout_ecc(struct mtd_info *mtd, int section,
>  static int fsl_ifc_ooblayout_free(struct mtd_info *mtd, int section,
>  				  struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (section > 1)
>  		return -ERANGE;
> @@ -150,7 +150,7 @@ static int fsl_ifc_ooblayout_free(struct mtd_info *mtd, int section,
>   */
>  static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
>  	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
>  	struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs;
> @@ -173,7 +173,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
>  
>  static int is_blank(struct mtd_info *mtd, unsigned int bufnum)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
>  	u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2);
>  	u32 __iomem *mainarea = (u32 __iomem *)addr;
> @@ -216,7 +216,7 @@ static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
>   */
>  static void fsl_ifc_run_command(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
>  	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
>  	struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl;
> @@ -339,7 +339,7 @@ static void fsl_ifc_do_read(struct nand_chip *chip,
>  /* cmdfunc send commands to the IFC NAND Machine */
>  static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
>  			     int column, int page_addr) {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
>  	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
>  	struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs;
> @@ -554,7 +554,7 @@ static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
>   */
>  static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
>  	unsigned int bufsize = mtd->writesize + mtd->oobsize;
>  
> @@ -580,7 +580,7 @@ static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
>   */
>  static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
>  	unsigned int offset;
>  
> @@ -603,7 +603,7 @@ static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd)
>   */
>  static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
>  	uint16_t data;
>  
> @@ -626,7 +626,7 @@ static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
>   */
>  static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
>  	int avail;
>  
> @@ -712,7 +712,7 @@ static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
>  
>  static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
>  
>  	dev_dbg(priv->dev, "%s: nand->numchips = %d\n", __func__,
> @@ -811,7 +811,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
>  	struct fsl_ifc_global __iomem *ifc_global = ctrl->gregs;
>  	struct fsl_ifc_runtime __iomem *ifc_runtime = ctrl->rregs;
>  	struct nand_chip *chip = &priv->chip;
> -	struct mtd_info *mtd = nand_to_mtd(&priv->chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&priv->chip);
>  	u32 csor;
>  
>  	/* Fill in fsl_ifc_mtd structure */
> @@ -912,7 +912,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
>  
>  static int fsl_ifc_chip_remove(struct fsl_ifc_mtd *priv)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(&priv->chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&priv->chip);
>  
>  	nand_release(mtd);
>  
> @@ -1024,7 +1024,7 @@ static int fsl_ifc_nand_probe(struct platform_device *dev)
>  		  IFC_NAND_EVTER_INTR_WPERIR_EN,
>  		  &ifc->ifc_nand.nand_evter_intr_en);
>  
> -	mtd = nand_to_mtd(&priv->chip);
> +	mtd = nandchip_to_mtd(&priv->chip);
>  	mtd->name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start);
>  	if (!mtd->name) {
>  		ret = -ENOMEM;
> diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c
> index a88e2cf..9715cdd 100644
> --- a/drivers/mtd/nand/raw/fsl_upm.c
> +++ b/drivers/mtd/nand/raw/fsl_upm.c
> @@ -48,7 +48,7 @@ struct fsl_upm_nand {
>  
>  static inline struct fsl_upm_nand *to_fsl_upm_nand(struct mtd_info *mtdinfo)
>  {
> -	return container_of(mtd_to_nand(mtdinfo), struct fsl_upm_nand,
> +	return container_of(mtd_to_nandchip(mtdinfo), struct fsl_upm_nand,
>  			    chip);
>  }
>  
> @@ -66,7 +66,7 @@ static int fun_chip_ready(struct mtd_info *mtd)
>  static void fun_wait_rnb(struct fsl_upm_nand *fun)
>  {
>  	if (fun->rnb_gpio[fun->mchip_number] >= 0) {
> -		struct mtd_info *mtd = nand_to_mtd(&fun->chip);
> +		struct mtd_info *mtd = nandchip_to_mtd(&fun->chip);
>  		int cnt = 1000000;
>  
>  		while (--cnt && !fun_chip_ready(mtd))
> @@ -80,7 +80,7 @@ static void fun_wait_rnb(struct fsl_upm_nand *fun)
>  
>  static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
>  	u32 mar;
>  
> @@ -110,7 +110,7 @@ static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
>  
>  static void fun_select_chip(struct mtd_info *mtd, int mchip_nr)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd);
>  
>  	if (mchip_nr == -1) {
> @@ -158,7 +158,7 @@ static int fun_chip_init(struct fsl_upm_nand *fun,
>  			 const struct device_node *upm_np,
>  			 const struct resource *io_res)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(&fun->chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&fun->chip);
>  	int ret;
>  	struct device_node *flash_np;
>  
> @@ -323,7 +323,7 @@ static int fun_probe(struct platform_device *ofdev)
>  static int fun_remove(struct platform_device *ofdev)
>  {
>  	struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev);
> -	struct mtd_info *mtd = nand_to_mtd(&fun->chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&fun->chip);
>  	int i;
>  
>  	nand_release(mtd);
> diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c
> index bab7064..3597b54 100644
> --- a/drivers/mtd/nand/raw/fsmc_nand.c
> +++ b/drivers/mtd/nand/raw/fsmc_nand.c
> @@ -171,7 +171,7 @@ struct fsmc_nand_data {
>  static int fsmc_ecc1_ooblayout_ecc(struct mtd_info *mtd, int section,
>  				   struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (section >= chip->ecc.steps)
>  		return -ERANGE;
> @@ -185,7 +185,7 @@ static int fsmc_ecc1_ooblayout_ecc(struct mtd_info *mtd, int section,
>  static int fsmc_ecc1_ooblayout_free(struct mtd_info *mtd, int section,
>  				    struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (section >= chip->ecc.steps)
>  		return -ERANGE;
> @@ -214,7 +214,7 @@ static int fsmc_ecc1_ooblayout_free(struct mtd_info *mtd, int section,
>  static int fsmc_ecc4_ooblayout_ecc(struct mtd_info *mtd, int section,
>  				   struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (section >= chip->ecc.steps)
>  		return -ERANGE;
> @@ -232,7 +232,7 @@ static int fsmc_ecc4_ooblayout_ecc(struct mtd_info *mtd, int section,
>  static int fsmc_ecc4_ooblayout_free(struct mtd_info *mtd, int section,
>  				    struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (section >= chip->ecc.steps)
>  		return -ERANGE;
> @@ -254,7 +254,7 @@ static int fsmc_ecc4_ooblayout_free(struct mtd_info *mtd, int section,
>  
>  static inline struct fsmc_nand_data *mtd_to_fsmc(struct mtd_info *mtd)
>  {
> -	return container_of(mtd_to_nand(mtd), struct fsmc_nand_data, nand);
> +	return container_of(mtd_to_nandchip(mtd), struct fsmc_nand_data, nand);
>  }
>  
>  /*
> @@ -263,7 +263,7 @@ static inline struct fsmc_nand_data *mtd_to_fsmc(struct mtd_info *mtd)
>   */
>  static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
>  	void __iomem *regs = host->regs_va;
>  	unsigned int bank = host->bank;
> @@ -392,7 +392,7 @@ static int fsmc_setup_data_interface(struct mtd_info *mtd,
>  				     const struct nand_data_interface *conf,
>  				     bool check_only)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct fsmc_nand_data *host = nand_get_controller_data(nand);
>  	struct fsmc_nand_timings tims;
>  	const struct nand_sdr_timings *sdrt;
> @@ -600,7 +600,7 @@ static int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len,
>  static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
>  {
>  	int i;
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) &&
>  			IS_ALIGNED(len, sizeof(uint32_t))) {
> @@ -623,7 +623,7 @@ static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
>  static void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  {
>  	int i;
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) &&
>  			IS_ALIGNED(len, sizeof(uint32_t))) {
> @@ -754,7 +754,7 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
>  static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
>  			     uint8_t *read_ecc, uint8_t *calc_ecc)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
>  	void __iomem *regs = host->regs_va;
>  	unsigned int bank = host->bank;
> @@ -957,7 +957,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
>  		init_completion(&host->dma_access_complete);
>  
>  	/* Link all private pointers */
> -	mtd = nand_to_mtd(&host->nand);
> +	mtd = nandchip_to_mtd(&host->nand);
>  	nand_set_controller_data(nand, host);
>  	nand_set_flash_node(nand, pdev->dev.of_node);
>  
> @@ -1119,7 +1119,7 @@ static int fsmc_nand_remove(struct platform_device *pdev)
>  	struct fsmc_nand_data *host = platform_get_drvdata(pdev);
>  
>  	if (host) {
> -		nand_release(nand_to_mtd(&host->nand));
> +		nand_release(nandchip_to_mtd(&host->nand));
>  
>  		if (host->mode == USE_DMA_ACCESS) {
>  			dma_release_channel(host->write_dma_chan);
> diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c
> index fd36489..8d5a9ca 100644
> --- a/drivers/mtd/nand/raw/gpio.c
> +++ b/drivers/mtd/nand/raw/gpio.c
> @@ -41,7 +41,7 @@ struct gpiomtd {
>  
>  static inline struct gpiomtd *gpio_nand_getpriv(struct mtd_info *mtd)
>  {
> -	return container_of(mtd_to_nand(mtd), struct gpiomtd, nand_chip);
> +	return container_of(mtd_to_nandchip(mtd), struct gpiomtd, nand_chip);
>  }
>  
>  
> @@ -199,7 +199,7 @@ static int gpio_nand_remove(struct platform_device *pdev)
>  {
>  	struct gpiomtd *gpiomtd = platform_get_drvdata(pdev);
>  
> -	nand_release(nand_to_mtd(&gpiomtd->nand_chip));
> +	nand_release(nandchip_to_mtd(&gpiomtd->nand_chip));
>  
>  	if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
>  		gpio_set_value(gpiomtd->plat.gpio_nwp, 0);
> @@ -284,7 +284,7 @@ static int gpio_nand_probe(struct platform_device *pdev)
>  	chip->chip_delay	= gpiomtd->plat.chip_delay;
>  	chip->cmd_ctrl		= gpio_nand_cmd_ctrl;
>  
> -	mtd			= nand_to_mtd(chip);
> +	mtd			= nandchip_to_mtd(chip);
>  	mtd->dev.parent		= &pdev->dev;
>  
>  	platform_set_drvdata(pdev, gpiomtd);
> diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> index 141bd70..7217912 100644
> --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> @@ -921,7 +921,7 @@ static int enable_edo_mode(struct gpmi_nand_data *this, int mode)
>  {
>  	struct resources  *r = &this->resources;
>  	struct nand_chip *nand = &this->nand;
> -	struct mtd_info	 *mtd = nand_to_mtd(nand);
> +	struct mtd_info	 *mtd = nandchip_to_mtd(nand);
>  	uint8_t *feature;
>  	unsigned long rate;
>  	int ret;
> diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> index 50f8d4a..b736ea2 100644
> --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> @@ -50,7 +50,7 @@
>  static int gpmi_ooblayout_ecc(struct mtd_info *mtd, int section,
>  			      struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct gpmi_nand_data *this = nand_get_controller_data(chip);
>  	struct bch_geometry *geo = &this->bch_geometry;
>  
> @@ -66,7 +66,7 @@ static int gpmi_ooblayout_ecc(struct mtd_info *mtd, int section,
>  static int gpmi_ooblayout_free(struct mtd_info *mtd, int section,
>  			       struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct gpmi_nand_data *this = nand_get_controller_data(chip);
>  	struct bch_geometry *geo = &this->bch_geometry;
>  
> @@ -169,7 +169,7 @@ static irqreturn_t bch_irq(int irq, void *cookie)
>  static inline int get_ecc_strength(struct gpmi_nand_data *this)
>  {
>  	struct bch_geometry *geo = &this->bch_geometry;
> -	struct mtd_info	*mtd = nand_to_mtd(&this->nand);
> +	struct mtd_info	*mtd = nandchip_to_mtd(&this->nand);
>  	int ecc_strength;
>  
>  	ecc_strength = ((mtd->oobsize - geo->metadata_size) * 8)
> @@ -202,7 +202,7 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this)
>  {
>  	struct bch_geometry *geo = &this->bch_geometry;
>  	struct nand_chip *chip = &this->nand;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	unsigned int block_mark_bit_offset;
>  
>  	if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
> @@ -312,7 +312,7 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this)
>  static int legacy_set_geometry(struct gpmi_nand_data *this)
>  {
>  	struct bch_geometry *geo = &this->bch_geometry;
> -	struct mtd_info *mtd = nand_to_mtd(&this->nand);
> +	struct mtd_info *mtd = nandchip_to_mtd(&this->nand);
>  	unsigned int metadata_size;
>  	unsigned int status_size;
>  	unsigned int block_mark_bit_offset;
> @@ -842,7 +842,7 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
>  {
>  	struct bch_geometry *geo = &this->bch_geometry;
>  	struct device *dev = this->dev;
> -	struct mtd_info *mtd = nand_to_mtd(&this->nand);
> +	struct mtd_info *mtd = nandchip_to_mtd(&this->nand);
>  
>  	/* [1] Allocate a command buffer. PAGE_SIZE is enough. */
>  	this->cmd_buffer = kzalloc(PAGE_SIZE, GFP_DMA | GFP_KERNEL);
> @@ -894,7 +894,7 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
>  
>  static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct gpmi_nand_data *this = nand_get_controller_data(chip);
>  	int ret;
>  
> @@ -928,7 +928,7 @@ static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
>  
>  static int gpmi_dev_ready(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct gpmi_nand_data *this = nand_get_controller_data(chip);
>  
>  	return gpmi_is_ready(this, this->current_chip);
> @@ -936,7 +936,7 @@ static int gpmi_dev_ready(struct mtd_info *mtd)
>  
>  static void gpmi_select_chip(struct mtd_info *mtd, int chipnr)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct gpmi_nand_data *this = nand_get_controller_data(chip);
>  
>  	if ((this->current_chip < 0) && (chipnr >= 0))
> @@ -949,7 +949,7 @@ static void gpmi_select_chip(struct mtd_info *mtd, int chipnr)
>  
>  static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct gpmi_nand_data *this = nand_get_controller_data(chip);
>  
>  	dev_dbg(this->dev, "len is %d\n", len);
> @@ -961,7 +961,7 @@ static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  
>  static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct gpmi_nand_data *this = nand_get_controller_data(chip);
>  
>  	dev_dbg(this->dev, "len is %d\n", len);
> @@ -973,7 +973,7 @@ static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
>  
>  static uint8_t gpmi_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct gpmi_nand_data *this = nand_get_controller_data(chip);
>  	uint8_t *buf = this->data_buffer_dma;
>  
> @@ -1645,7 +1645,7 @@ static int gpmi_ecc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
>  
>  static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct gpmi_nand_data *this = nand_get_controller_data(chip);
>  	int ret = 0;
>  	uint8_t *block_mark;
> @@ -1708,7 +1708,7 @@ static int mx23_check_transcription_stamp(struct gpmi_nand_data *this)
>  	struct boot_rom_geometry *rom_geo = &this->rom_geometry;
>  	struct device *dev = this->dev;
>  	struct nand_chip *chip = &this->nand;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	unsigned int search_area_size_in_strides;
>  	unsigned int stride;
>  	unsigned int page;
> @@ -1763,7 +1763,7 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this)
>  	struct device *dev = this->dev;
>  	struct boot_rom_geometry *rom_geo = &this->rom_geometry;
>  	struct nand_chip *chip = &this->nand;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	unsigned int block_size_in_pages;
>  	unsigned int search_area_size_in_strides;
>  	unsigned int search_area_size_in_pages;
> @@ -1842,7 +1842,7 @@ static int mx23_boot_init(struct gpmi_nand_data  *this)
>  {
>  	struct device *dev = this->dev;
>  	struct nand_chip *chip = &this->nand;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	unsigned int block_count;
>  	unsigned int block;
>  	int     chipnr;
> @@ -1939,7 +1939,7 @@ static int gpmi_set_geometry(struct gpmi_nand_data *this)
>  static int gpmi_init_last(struct gpmi_nand_data *this)
>  {
>  	struct nand_chip *chip = &this->nand;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
>  	struct bch_geometry *bch_geo = &this->bch_geometry;
>  	int ret;
> @@ -1988,7 +1988,7 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
>  static int gpmi_nand_init(struct gpmi_nand_data *this)
>  {
>  	struct nand_chip *chip = &this->nand;
> -	struct mtd_info  *mtd = nand_to_mtd(chip);
> +	struct mtd_info  *mtd = nandchip_to_mtd(chip);
>  	int ret;
>  
>  	/* init current chip */
> @@ -2135,7 +2135,7 @@ static int gpmi_nand_remove(struct platform_device *pdev)
>  {
>  	struct gpmi_nand_data *this = platform_get_drvdata(pdev);
>  
> -	nand_release(nand_to_mtd(&this->nand));
> +	nand_release(nandchip_to_mtd(&this->nand));
>  	gpmi_free_dma_buffer(this);
>  	release_resources(this);
>  	return 0;
> diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c
> index d09df18..86dd423 100644
> --- a/drivers/mtd/nand/raw/hisi504_nand.c
> +++ b/drivers/mtd/nand/raw/hisi504_nand.c
> @@ -188,7 +188,7 @@ static void wait_controller_finished(struct hinfc_host *host)
>  static void hisi_nfc_dma_transfer(struct hinfc_host *host, int todev)
>  {
>  	struct nand_chip *chip = &host->chip;
> -	struct mtd_info	*mtd = nand_to_mtd(chip);
> +	struct mtd_info	*mtd = nandchip_to_mtd(chip);
>  	unsigned long val;
>  	int ret;
>  
> @@ -260,7 +260,7 @@ static int hisi_nfc_send_cmd_pageprog(struct hinfc_host *host)
>  
>  static int hisi_nfc_send_cmd_readstart(struct hinfc_host *host)
>  {
> -	struct mtd_info	*mtd = nand_to_mtd(&host->chip);
> +	struct mtd_info	*mtd = nandchip_to_mtd(&host->chip);
>  
>  	if ((host->addr_value[0] == host->cache_addr_value[0]) &&
>  	    (host->addr_value[1] == host->cache_addr_value[1]))
> @@ -355,7 +355,7 @@ static int hisi_nfc_send_cmd_reset(struct hinfc_host *host, int chipselect)
>  
>  static void hisi_nfc_select_chip(struct mtd_info *mtd, int chipselect)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct hinfc_host *host = nand_get_controller_data(chip);
>  
>  	if (chipselect < 0)
> @@ -366,7 +366,7 @@ static void hisi_nfc_select_chip(struct mtd_info *mtd, int chipselect)
>  
>  static uint8_t hisi_nfc_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct hinfc_host *host = nand_get_controller_data(chip);
>  
>  	if (host->command == NAND_CMD_STATUS)
> @@ -382,7 +382,7 @@ static uint8_t hisi_nfc_read_byte(struct mtd_info *mtd)
>  
>  static u16 hisi_nfc_read_word(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct hinfc_host *host = nand_get_controller_data(chip);
>  
>  	host->offset += 2;
> @@ -392,7 +392,7 @@ static u16 hisi_nfc_read_word(struct mtd_info *mtd)
>  static void
>  hisi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct hinfc_host *host = nand_get_controller_data(chip);
>  
>  	memcpy(host->buffer + host->offset, buf, len);
> @@ -401,7 +401,7 @@ static u16 hisi_nfc_read_word(struct mtd_info *mtd)
>  
>  static void hisi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct hinfc_host *host = nand_get_controller_data(chip);
>  
>  	memcpy(buf, host->buffer + host->offset, len);
> @@ -410,7 +410,7 @@ static void hisi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  
>  static void set_addr(struct mtd_info *mtd, int column, int page_addr)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct hinfc_host *host = nand_get_controller_data(chip);
>  	unsigned int command = host->command;
>  
> @@ -446,7 +446,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr)
>  static void hisi_nfc_cmdfunc(struct mtd_info *mtd, unsigned command, int column,
>  		int page_addr)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct hinfc_host *host = nand_get_controller_data(chip);
>  	int is_cache_invalid = 1;
>  	unsigned int flag = 0;
> @@ -660,7 +660,7 @@ static int hisi_nfc_ecc_probe(struct hinfc_host *host)
>  	int size, strength, ecc_bits;
>  	struct device *dev = host->dev;
>  	struct nand_chip *chip = &host->chip;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  
>  	size = chip->ecc.size;
>  	strength = chip->ecc.strength;
> @@ -728,7 +728,7 @@ static int hisi_nfc_probe(struct platform_device *pdev)
>  
>  	platform_set_drvdata(pdev, host);
>  	chip = &host->chip;
> -	mtd  = nand_to_mtd(chip);
> +	mtd  = nandchip_to_mtd(chip);
>  
>  	irq = platform_get_irq(pdev, 0);
>  	if (irq < 0) {
> @@ -829,7 +829,7 @@ static int hisi_nfc_probe(struct platform_device *pdev)
>  static int hisi_nfc_remove(struct platform_device *pdev)
>  {
>  	struct hinfc_host *host = platform_get_drvdata(pdev);
> -	struct mtd_info *mtd = nand_to_mtd(&host->chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&host->chip);
>  
>  	nand_release(mtd);
>  
> diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c
> index e813ec1..c2d514e 100644
> --- a/drivers/mtd/nand/raw/jz4740_nand.c
> +++ b/drivers/mtd/nand/raw/jz4740_nand.c
> @@ -75,13 +75,13 @@ struct jz_nand {
>  
>  static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd)
>  {
> -	return container_of(mtd_to_nand(mtd), struct jz_nand, chip);
> +	return container_of(mtd_to_nandchip(mtd), struct jz_nand, chip);
>  }
>  
>  static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr)
>  {
>  	struct jz_nand *nand = mtd_to_jz_nand(mtd);
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	uint32_t ctrl;
>  	int banknr;
>  
> @@ -103,7 +103,7 @@ static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr)
>  static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
>  {
>  	struct jz_nand *nand = mtd_to_jz_nand(mtd);
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	uint32_t reg;
>  	void __iomem *bank_base = nand->bank_base[nand->selected_bank];
>  
> @@ -315,7 +315,7 @@ static int jz_nand_detect_bank(struct platform_device *pdev,
>  	char res_name[6];
>  	uint32_t ctrl;
>  	struct nand_chip *chip = &nand->chip;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  
>  	/* Request GPIO port. */
>  	gpio = JZ_GPIO_MEM_CS0 + bank - 1;
> @@ -413,7 +413,7 @@ static int jz_nand_probe(struct platform_device *pdev)
>  	}
>  
>  	chip		= &nand->chip;
> -	mtd		= nand_to_mtd(chip);
> +	mtd		= nandchip_to_mtd(chip);
>  	mtd->dev.parent = &pdev->dev;
>  	mtd->name	= "jz4740-nand";
>  
> @@ -520,7 +520,7 @@ static int jz_nand_remove(struct platform_device *pdev)
>  	struct jz_nand *nand = platform_get_drvdata(pdev);
>  	size_t i;
>  
> -	nand_release(nand_to_mtd(&nand->chip));
> +	nand_release(nandchip_to_mtd(&nand->chip));
>  
>  	/* Deassert and disable all chips */
>  	writel(0, nand->base + JZ_REG_NAND_CTRL);
> diff --git a/drivers/mtd/nand/raw/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c
> index e69f6ae..2b3096d 100644
> --- a/drivers/mtd/nand/raw/jz4780_nand.c
> +++ b/drivers/mtd/nand/raw/jz4780_nand.c
> @@ -62,7 +62,7 @@ struct jz4780_nand_chip {
>  
>  static inline struct jz4780_nand_chip *to_jz4780_nand_chip(struct mtd_info *mtd)
>  {
> -	return container_of(mtd_to_nand(mtd), struct jz4780_nand_chip, chip);
> +	return container_of(mtd_to_nandchip(mtd), struct jz4780_nand_chip, chip);
>  }
>  
>  static inline struct jz4780_nand_controller *to_jz4780_nand_controller(struct nand_hw_control *ctrl)
> @@ -160,7 +160,7 @@ static int jz4780_nand_ecc_correct(struct mtd_info *mtd, u8 *dat,
>  static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *dev)
>  {
>  	struct nand_chip *chip = &nand->chip;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(chip->controller);
>  	int eccbytes;
>  
> @@ -262,7 +262,7 @@ static int jz4780_nand_init_chip(struct platform_device *pdev,
>  	}
>  
>  	chip = &nand->chip;
> -	mtd = nand_to_mtd(chip);
> +	mtd = nandchip_to_mtd(chip);
>  	mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%s.%d", dev_name(dev),
>  				   cs->bank);
>  	if (!mtd->name)
> @@ -308,7 +308,7 @@ static void jz4780_nand_cleanup_chips(struct jz4780_nand_controller *nfc)
>  
>  	while (!list_empty(&nfc->chips)) {
>  		chip = list_first_entry(&nfc->chips, struct jz4780_nand_chip, chip_list);
> -		nand_release(nand_to_mtd(&chip->chip));
> +		nand_release(nandchip_to_mtd(&chip->chip));
>  		list_del(&chip->chip_list);
>  	}
>  }
> diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c
> index bffa01c..b5e3787 100644
> --- a/drivers/mtd/nand/raw/lpc32xx_mlc.c
> +++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c
> @@ -141,7 +141,7 @@ struct lpc32xx_nand_cfg_mlc {
>  static int lpc32xx_ooblayout_ecc(struct mtd_info *mtd, int section,
>  				 struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  
>  	if (section >= nand_chip->ecc.steps)
>  		return -ERANGE;
> @@ -155,7 +155,7 @@ static int lpc32xx_ooblayout_ecc(struct mtd_info *mtd, int section,
>  static int lpc32xx_ooblayout_free(struct mtd_info *mtd, int section,
>  				  struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  
>  	if (section >= nand_chip->ecc.steps)
>  		return -ERANGE;
> @@ -288,7 +288,7 @@ static void lpc32xx_nand_setup(struct lpc32xx_nand_host *host)
>  static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
>  				  unsigned int ctrl)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct lpc32xx_nand_host *host = nand_get_controller_data(nand_chip);
>  
>  	if (cmd != NAND_CMD_NONE) {
> @@ -304,7 +304,7 @@ static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
>   */
>  static int lpc32xx_nand_device_ready(struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct lpc32xx_nand_host *host = nand_get_controller_data(nand_chip);
>  
>  	if ((readb(MLC_ISR(host->io_base)) &
> @@ -402,7 +402,7 @@ static void lpc32xx_dma_complete_func(void *completion)
>  static int lpc32xx_xmit_dma(struct mtd_info *mtd, void *mem, int len,
>  			    enum dma_transfer_direction dir)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
>  	struct dma_async_tx_descriptor *desc;
>  	int flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
> @@ -579,7 +579,7 @@ static void lpc32xx_ecc_enable(struct mtd_info *mtd, int mode)
>  
>  static int lpc32xx_dma_setup(struct lpc32xx_nand_host *host)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&host->nand_chip);
>  	dma_cap_mask_t mask;
>  
>  	if (!host->pdata || !host->pdata->dma_filter) {
> @@ -674,7 +674,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
>  	host->io_base_phy = rc->start;
>  
>  	nand_chip = &host->nand_chip;
> -	mtd = nand_to_mtd(nand_chip);
> +	mtd = nandchip_to_mtd(nand_chip);
>  	if (pdev->dev.of_node)
>  		host->ncfg = lpc32xx_parse_dt(&pdev->dev);
>  	if (!host->ncfg) {
> @@ -826,7 +826,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
>  static int lpc32xx_nand_remove(struct platform_device *pdev)
>  {
>  	struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
> -	struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&host->nand_chip);
>  
>  	nand_release(mtd);
>  	free_irq(host->irq, host);
> diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c
> index 7c8402f..b47e3c0 100644
> --- a/drivers/mtd/nand/raw/lpc32xx_slc.c
> +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c
> @@ -282,7 +282,7 @@ static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
>  	unsigned int ctrl)
>  {
>  	uint32_t tmp;
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
>  
>  	/* Does CE state need to be changed? */
> @@ -306,7 +306,7 @@ static void lpc32xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
>   */
>  static int lpc32xx_nand_device_ready(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
>  	int rdy = 0;
>  
> @@ -361,7 +361,7 @@ static int lpc32xx_nand_ecc_calculate(struct mtd_info *mtd,
>   */
>  static uint8_t lpc32xx_nand_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
>  
>  	return (uint8_t)readl(SLC_DATA(host->io_base));
> @@ -372,7 +372,7 @@ static uint8_t lpc32xx_nand_read_byte(struct mtd_info *mtd)
>   */
>  static void lpc32xx_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
>  
>  	/* Direct device read with no ECC */
> @@ -385,7 +385,7 @@ static void lpc32xx_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
>   */
>  static void lpc32xx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
>  
>  	/* Direct device write with no ECC */
> @@ -450,7 +450,7 @@ static void lpc32xx_dma_complete_func(void *completion)
>  static int lpc32xx_xmit_dma(struct mtd_info *mtd, dma_addr_t dma,
>  			    void *mem, int len, enum dma_transfer_direction dir)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
>  	struct dma_async_tx_descriptor *desc;
>  	int flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
> @@ -510,7 +510,7 @@ static int lpc32xx_xmit_dma(struct mtd_info *mtd, dma_addr_t dma,
>  static int lpc32xx_xfer(struct mtd_info *mtd, uint8_t *buf, int eccsubpages,
>  			int read)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
>  	int i, status = 0;
>  	unsigned long timeout;
> @@ -736,7 +736,7 @@ static int lpc32xx_nand_write_page_raw_syndrome(struct mtd_info *mtd,
>  
>  static int lpc32xx_nand_dma_setup(struct lpc32xx_nand_host *host)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&host->nand_chip);
>  	dma_cap_mask_t mask;
>  
>  	if (!host->pdata || !host->pdata->dma_filter) {
> @@ -827,7 +827,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
>  	host->pdata = dev_get_platdata(&pdev->dev);
>  
>  	chip = &host->nand_chip;
> -	mtd = nand_to_mtd(chip);
> +	mtd = nandchip_to_mtd(chip);
>  	nand_set_controller_data(chip, host);
>  	nand_set_flash_node(chip, pdev->dev.of_node);
>  	mtd->owner = THIS_MODULE;
> @@ -952,7 +952,7 @@ static int lpc32xx_nand_remove(struct platform_device *pdev)
>  {
>  	uint32_t tmp;
>  	struct lpc32xx_nand_host *host = platform_get_drvdata(pdev);
> -	struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&host->nand_chip);
>  
>  	nand_release(mtd);
>  	dma_release_channel(host->dma_chan);
> diff --git a/drivers/mtd/nand/raw/mpc5121_nfc.c b/drivers/mtd/nand/raw/mpc5121_nfc.c
> index 55f1d4a..e6c510f 100644
> --- a/drivers/mtd/nand/raw/mpc5121_nfc.c
> +++ b/drivers/mtd/nand/raw/mpc5121_nfc.c
> @@ -134,7 +134,7 @@ struct mpc5121_nfc_prv {
>  /* Read NFC register */
>  static inline u16 nfc_read(struct mtd_info *mtd, uint reg)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
>  
>  	return in_be16(prv->regs + reg);
> @@ -143,7 +143,7 @@ static inline u16 nfc_read(struct mtd_info *mtd, uint reg)
>  /* Write NFC register */
>  static inline void nfc_write(struct mtd_info *mtd, uint reg, u16 val)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
>  
>  	out_be16(prv->regs + reg, val);
> @@ -213,7 +213,7 @@ static inline void mpc5121_nfc_send_read_status(struct mtd_info *mtd)
>  static irqreturn_t mpc5121_nfc_irq(int irq, void *data)
>  {
>  	struct mtd_info *mtd = data;
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
>  
>  	nfc_set(mtd, NFC_CONFIG1, NFC_INT_MASK);
> @@ -225,7 +225,7 @@ static irqreturn_t mpc5121_nfc_irq(int irq, void *data)
>  /* Wait for operation complete */
>  static void mpc5121_nfc_done(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
>  	int rv;
>  
> @@ -245,7 +245,7 @@ static void mpc5121_nfc_done(struct mtd_info *mtd)
>  /* Do address cycle(s) */
>  static void mpc5121_nfc_addr_cycle(struct mtd_info *mtd, int column, int page)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	u32 pagemask = chip->pagemask;
>  
>  	if (column != -1) {
> @@ -280,7 +280,7 @@ static void mpc5121_nfc_select_chip(struct mtd_info *mtd, int chip)
>  /* Init external chip select logic on ADS5121 board */
>  static int ads5121_chipselect_init(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
>  	struct device_node *dn;
>  
> @@ -302,7 +302,7 @@ static int ads5121_chipselect_init(struct mtd_info *mtd)
>  /* Control chips select signal on ADS5121 board */
>  static void ads5121_select_chip(struct mtd_info *mtd, int chip)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct mpc5121_nfc_prv *prv = nand_get_controller_data(nand);
>  	u8 v;
>  
> @@ -332,7 +332,7 @@ static int mpc5121_nfc_dev_ready(struct mtd_info *mtd)
>  static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command,
>  							int column, int page)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
>  
>  	prv->column = (column >= 0) ? column : 0;
> @@ -405,7 +405,7 @@ static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command,
>  static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset,
>  						u8 *buffer, uint size, int wr)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct mpc5121_nfc_prv *prv = nand_get_controller_data(nand);
>  	uint o, s, sbsize, blksize;
>  
> @@ -457,7 +457,7 @@ static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset,
>  static void mpc5121_nfc_buf_copy(struct mtd_info *mtd, u_char *buf, int len,
>  									int wr)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
>  	uint c = prv->column;
>  	uint l;
> @@ -535,7 +535,7 @@ static u16 mpc5121_nfc_read_word(struct mtd_info *mtd)
>   */
>  static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
>  	struct mpc512x_reset_module *rm;
>  	struct device_node *rmnode;
> @@ -614,7 +614,7 @@ static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd)
>  /* Free driver resources */
>  static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
>  
>  	if (prv->clk)
> @@ -654,7 +654,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
>  		return -ENOMEM;
>  
>  	chip = &prv->chip;
> -	mtd = nand_to_mtd(chip);
> +	mtd = nandchip_to_mtd(chip);
>  
>  	mtd->dev.parent = dev;
>  	nand_set_controller_data(chip, prv);
> diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
> index 3f4a98b..a0a7f6c 100644
> --- a/drivers/mtd/nand/raw/mtk_nand.c
> +++ b/drivers/mtd/nand/raw/mtk_nand.c
> @@ -305,7 +305,7 @@ static int mtk_nfc_send_address(struct mtk_nfc *nfc, int addr)
>  
>  static int mtk_nfc_hw_runtime_config(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
>  	struct mtk_nfc *nfc = nand_get_controller_data(chip);
>  	u32 fmt, spare;
> @@ -418,7 +418,7 @@ static int mtk_nfc_hw_runtime_config(struct mtd_info *mtd)
>  
>  static void mtk_nfc_select_chip(struct mtd_info *mtd, int chip)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct mtk_nfc *nfc = nand_get_controller_data(nand);
>  	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(nand);
>  
> @@ -432,7 +432,7 @@ static void mtk_nfc_select_chip(struct mtd_info *mtd, int chip)
>  
>  static int mtk_nfc_dev_ready(struct mtd_info *mtd)
>  {
> -	struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd));
> +	struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nandchip(mtd));
>  
>  	if (nfi_readl(nfc, NFI_STA) & STA_BUSY)
>  		return 0;
> @@ -442,7 +442,7 @@ static int mtk_nfc_dev_ready(struct mtd_info *mtd)
>  
>  static void mtk_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
>  {
> -	struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd));
> +	struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nandchip(mtd));
>  
>  	if (ctrl & NAND_ALE) {
>  		mtk_nfc_send_address(nfc, dat);
> @@ -467,7 +467,7 @@ static inline void mtk_nfc_wait_ioready(struct mtk_nfc *nfc)
>  
>  static inline u8 mtk_nfc_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mtk_nfc *nfc = nand_get_controller_data(chip);
>  	u32 reg;
>  
> @@ -504,7 +504,7 @@ static void mtk_nfc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
>  
>  static void mtk_nfc_write_byte(struct mtd_info *mtd, u8 byte)
>  {
> -	struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd));
> +	struct mtk_nfc *nfc = nand_get_controller_data(mtd_to_nandchip(mtd));
>  	u32 reg;
>  
>  	reg = nfi_readl(nfc, NFI_STA) & NFI_FSM_MASK;
> @@ -550,7 +550,7 @@ static void mtk_nfc_no_bad_mark_swap(struct mtd_info *a, u8 *b, int c)
>  
>  static void mtk_nfc_bad_mark_swap(struct mtd_info *mtd, u8 *buf, int raw)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mtk_nfc_nand_chip *nand = to_mtk_nand(chip);
>  	u32 bad_pos = nand->bad_mark.pos;
>  
> @@ -565,7 +565,7 @@ static void mtk_nfc_bad_mark_swap(struct mtd_info *mtd, u8 *buf, int raw)
>  static int mtk_nfc_format_subpage(struct mtd_info *mtd, u32 offset,
>  				  u32 len, const u8 *buf)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
>  	struct mtk_nfc *nfc = nand_get_controller_data(chip);
>  	struct mtk_nfc_fdm *fdm = &mtk_nand->fdm;
> @@ -599,7 +599,7 @@ static int mtk_nfc_format_subpage(struct mtd_info *mtd, u32 offset,
>  
>  static void mtk_nfc_format_page(struct mtd_info *mtd, const u8 *buf)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
>  	struct mtk_nfc *nfc = nand_get_controller_data(chip);
>  	struct mtk_nfc_fdm *fdm = &mtk_nand->fdm;
> @@ -812,7 +812,7 @@ static int mtk_nfc_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
>  
>  static int mtk_nfc_update_ecc_stats(struct mtd_info *mtd, u8 *buf, u32 sectors)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mtk_nfc *nfc = nand_get_controller_data(chip);
>  	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
>  	struct mtk_ecc_stats stats;
> @@ -1063,7 +1063,7 @@ static void mtk_nfc_disable_clk(struct mtk_nfc_clk *clk)
>  static int mtk_nfc_ooblayout_free(struct mtd_info *mtd, int section,
>  				  struct mtd_oob_region *oob_region)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
>  	struct mtk_nfc_fdm *fdm = &mtk_nand->fdm;
>  	u32 eccsteps;
> @@ -1082,7 +1082,7 @@ static int mtk_nfc_ooblayout_free(struct mtd_info *mtd, int section,
>  static int mtk_nfc_ooblayout_ecc(struct mtd_info *mtd, int section,
>  				 struct mtd_oob_region *oob_region)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
>  	u32 eccsteps;
>  
> @@ -1103,7 +1103,7 @@ static int mtk_nfc_ooblayout_ecc(struct mtd_info *mtd, int section,
>  
>  static void mtk_nfc_set_fdm(struct mtk_nfc_fdm *fdm, struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct mtk_nfc_nand_chip *chip = to_mtk_nand(nand);
>  	u32 ecc_bytes;
>  
> @@ -1120,7 +1120,7 @@ static void mtk_nfc_set_fdm(struct mtk_nfc_fdm *fdm, struct mtd_info *mtd)
>  static void mtk_nfc_set_bad_mark_ctl(struct mtk_nfc_bad_mark_ctl *bm_ctl,
>  				     struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  
>  	if (mtd->writesize == 512) {
>  		bm_ctl->bm_swap = mtk_nfc_no_bad_mark_swap;
> @@ -1133,7 +1133,7 @@ static void mtk_nfc_set_bad_mark_ctl(struct mtk_nfc_bad_mark_ctl *bm_ctl,
>  
>  static void mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	u32 spare[] = {16, 26, 27, 28, 32, 36, 40, 44,
>  			48, 49, 50, 51, 52, 62, 63, 64};
>  	u32 eccsteps, i;
> @@ -1163,7 +1163,7 @@ static void mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
>  
>  static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	u32 spare;
>  	int free;
>  
> @@ -1287,7 +1287,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
>  	nand->ecc.read_oob_raw = mtk_nfc_read_oob_std;
>  	nand->ecc.read_oob = mtk_nfc_read_oob_std;
>  
> -	mtd = nand_to_mtd(nand);
> +	mtd = nandchip_to_mtd(nand);
>  	mtd->owner = THIS_MODULE;
>  	mtd->dev.parent = dev;
>  	mtd->name = MTK_NAME;
> @@ -1450,7 +1450,7 @@ static int mtk_nfc_remove(struct platform_device *pdev)
>  	while (!list_empty(&nfc->chips)) {
>  		chip = list_first_entry(&nfc->chips, struct mtk_nfc_nand_chip,
>  					node);
> -		nand_release(nand_to_mtd(&chip->nand));
> +		nand_release(nandchip_to_mtd(&chip->nand));
>  		list_del(&chip->node);
>  	}
>  
> @@ -1490,7 +1490,7 @@ static int mtk_nfc_resume(struct device *dev)
>  	/* reset NAND chip if VCC was powered off */
>  	list_for_each_entry(chip, &nfc->chips, node) {
>  		nand = &chip->nand;
> -		mtd = nand_to_mtd(nand);
> +		mtd = nandchip_to_mtd(nand);
>  		for (i = 0; i < chip->nsels; i++) {
>  			nand->select_chip(mtd, i);
>  			nand->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
> diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c
> index 42bff4a..c50a850 100644
> --- a/drivers/mtd/nand/raw/mxc_nand.c
> +++ b/drivers/mtd/nand/raw/mxc_nand.c
> @@ -466,7 +466,7 @@ static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islas
>  
>  static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
>  	uint32_t tmp;
>  
> @@ -482,7 +482,7 @@ static void send_page_v3(struct mtd_info *mtd, unsigned int ops)
>  
>  static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
>  
>  	/* NANDFC buffer 0 is used for page read/write */
> @@ -496,7 +496,7 @@ static void send_page_v2(struct mtd_info *mtd, unsigned int ops)
>  
>  static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
>  	int bufs, i;
>  
> @@ -597,7 +597,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
>  static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
>  				 u_char *read_ecc, u_char *calc_ecc)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
>  
>  	/*
> @@ -618,7 +618,7 @@ static int mxc_nand_correct_data_v1(struct mtd_info *mtd, u_char *dat,
>  static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
>  				 u_char *read_ecc, u_char *calc_ecc)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
>  	u32 ecc_stat, err;
>  	int no_subpages = 1;
> @@ -656,7 +656,7 @@ static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
>  
>  static u_char mxc_nand_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
>  	uint8_t ret;
>  
> @@ -680,7 +680,7 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd)
>  
>  static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
>  	uint16_t ret;
>  
> @@ -696,7 +696,7 @@ static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
>  static void mxc_nand_write_buf(struct mtd_info *mtd,
>  				const u_char *buf, int len)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
>  	u16 col = host->buf_start;
>  	int n = mtd->oobsize + mtd->writesize - col;
> @@ -714,7 +714,7 @@ static void mxc_nand_write_buf(struct mtd_info *mtd,
>   */
>  static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
>  	u16 col = host->buf_start;
>  	int n = mtd->oobsize + mtd->writesize - col;
> @@ -730,7 +730,7 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
>   * deselect of the NAND chip */
>  static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
>  
>  	if (chip == -1) {
> @@ -751,7 +751,7 @@ static void mxc_nand_select_chip_v1_v3(struct mtd_info *mtd, int chip)
>  
>  static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
>  
>  	if (chip == -1) {
> @@ -784,7 +784,7 @@ static void mxc_nand_select_chip_v2(struct mtd_info *mtd, int chip)
>   */
>  static void copy_spare(struct mtd_info *mtd, bool bfrom)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(this);
>  	u16 i, oob_chunk_size;
>  	u16 num_chunks = mtd->writesize / 512;
> @@ -827,7 +827,7 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom)
>   */
>  static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
>  
>  	/* Write out column address, if necessary */
> @@ -880,7 +880,7 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
>  static int mxc_v1_ooblayout_ecc(struct mtd_info *mtd, int section,
>  				struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  
>  	if (section >= nand_chip->ecc.steps)
>  		return -ERANGE;
> @@ -894,7 +894,7 @@ static int mxc_v1_ooblayout_ecc(struct mtd_info *mtd, int section,
>  static int mxc_v1_ooblayout_free(struct mtd_info *mtd, int section,
>  				 struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  
>  	if (section > nand_chip->ecc.steps)
>  		return -ERANGE;
> @@ -928,7 +928,7 @@ static int mxc_v1_ooblayout_free(struct mtd_info *mtd, int section,
>  static int mxc_v2_ooblayout_ecc(struct mtd_info *mtd, int section,
>  				struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	int stepsize = nand_chip->ecc.bytes == 9 ? 16 : 26;
>  
>  	if (section >= nand_chip->ecc.steps)
> @@ -943,7 +943,7 @@ static int mxc_v2_ooblayout_ecc(struct mtd_info *mtd, int section,
>  static int mxc_v2_ooblayout_free(struct mtd_info *mtd, int section,
>  				 struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	int stepsize = nand_chip->ecc.bytes == 9 ? 16 : 26;
>  
>  	if (section >= nand_chip->ecc.steps)
> @@ -989,7 +989,7 @@ static int get_eccsize(struct mtd_info *mtd)
>  
>  static void preset_v1(struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
>  	uint16_t config1 = 0;
>  
> @@ -1019,7 +1019,7 @@ static int mxc_nand_v2_setup_data_interface(struct mtd_info *mtd,
>  					const struct nand_data_interface *conf,
>  					bool check_only)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
>  	int tRC_min_ns, tRC_ps, ret;
>  	unsigned long rate, rate_round;
> @@ -1093,7 +1093,7 @@ static int mxc_nand_v2_setup_data_interface(struct mtd_info *mtd,
>  
>  static void preset_v2(struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
>  	uint16_t config1 = 0;
>  
> @@ -1139,7 +1139,7 @@ static void preset_v2(struct mtd_info *mtd)
>  
>  static void preset_v3(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(chip);
>  	uint32_t config2, config3;
>  	int i, addr_phases;
> @@ -1210,7 +1210,7 @@ static void preset_v3(struct mtd_info *mtd)
>  static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
>  				int column, int page_addr)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
>  
>  	pr_debug("mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
> @@ -1322,7 +1322,7 @@ static int mxc_nand_onfi_set_features(struct mtd_info *mtd,
>  				      struct nand_chip *chip, int addr,
>  				      u8 *subfeature_param)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
>  	int i;
>  
> @@ -1348,7 +1348,7 @@ static int mxc_nand_onfi_get_features(struct mtd_info *mtd,
>  				      struct nand_chip *chip, int addr,
>  				      u8 *subfeature_param)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
>  	int i;
>  
> @@ -1629,7 +1629,7 @@ static int mxcnd_probe(struct platform_device *pdev)
>  	host->dev = &pdev->dev;
>  	/* structures must be linked */
>  	this = &host->nand;
> -	mtd = nand_to_mtd(this);
> +	mtd = nandchip_to_mtd(this);
>  	mtd->dev.parent = &pdev->dev;
>  	mtd->name = DRIVER_NAME;
>  
> @@ -1832,7 +1832,7 @@ static int mxcnd_remove(struct platform_device *pdev)
>  {
>  	struct mxc_nand_host *host = platform_get_drvdata(pdev);
>  
> -	nand_release(nand_to_mtd(&host->nand));
> +	nand_release(nandchip_to_mtd(&host->nand));
>  	if (host->clk_act)
>  		clk_disable_unprepare(host->clk);
>  
> diff --git a/drivers/mtd/nand/raw/nand_amd.c b/drivers/mtd/nand/raw/nand_amd.c
> index 22f060f..51e9ba7 100644
> --- a/drivers/mtd/nand/raw/nand_amd.c
> +++ b/drivers/mtd/nand/raw/nand_amd.c
> @@ -19,7 +19,7 @@
>  
>  static void amd_nand_decode_id(struct nand_chip *chip)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  
>  	nand_decode_ext_id(chip);
>  
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 730165b..a113cfb 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -57,7 +57,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
>  static int nand_ooblayout_ecc_sp(struct mtd_info *mtd, int section,
>  				 struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
>  
>  	if (section > 1)
> @@ -106,7 +106,7 @@ static int nand_ooblayout_free_sp(struct mtd_info *mtd, int section,
>  static int nand_ooblayout_ecc_lp(struct mtd_info *mtd, int section,
>  				 struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
>  
>  	if (section)
> @@ -121,7 +121,7 @@ static int nand_ooblayout_ecc_lp(struct mtd_info *mtd, int section,
>  static int nand_ooblayout_free_lp(struct mtd_info *mtd, int section,
>  				  struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
>  
>  	if (section)
> @@ -146,7 +146,7 @@ static int nand_ooblayout_free_lp(struct mtd_info *mtd, int section,
>  static int nand_ooblayout_ecc_lp_hamming(struct mtd_info *mtd, int section,
>  					 struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
>  
>  	if (section)
> @@ -173,7 +173,7 @@ static int nand_ooblayout_ecc_lp_hamming(struct mtd_info *mtd, int section,
>  static int nand_ooblayout_free_lp_hamming(struct mtd_info *mtd, int section,
>  					  struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
>  	int ecc_offset = 0;
>  
> @@ -210,7 +210,7 @@ static int nand_ooblayout_free_lp_hamming(struct mtd_info *mtd, int section,
>  static int check_offs_len(struct mtd_info *mtd,
>  					loff_t ofs, uint64_t len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	int ret = 0;
>  
>  	/* Start address must align on block boundary */
> @@ -236,7 +236,7 @@ static int check_offs_len(struct mtd_info *mtd,
>   */
>  static void nand_release_device(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	/* Release the controller and the chip */
>  	spin_lock(&chip->controller->lock);
> @@ -254,7 +254,7 @@ static void nand_release_device(struct mtd_info *mtd)
>   */
>  static uint8_t nand_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	return readb(chip->IO_ADDR_R);
>  }
>  
> @@ -267,7 +267,7 @@ static uint8_t nand_read_byte(struct mtd_info *mtd)
>   */
>  static uint8_t nand_read_byte16(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R));
>  }
>  
> @@ -279,7 +279,7 @@ static uint8_t nand_read_byte16(struct mtd_info *mtd)
>   */
>  static u16 nand_read_word(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	return readw(chip->IO_ADDR_R);
>  }
>  
> @@ -292,7 +292,7 @@ static u16 nand_read_word(struct mtd_info *mtd)
>   */
>  static void nand_select_chip(struct mtd_info *mtd, int chipnr)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	switch (chipnr) {
>  	case -1:
> @@ -315,7 +315,7 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr)
>   */
>  static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	chip->write_buf(mtd, &byte, 1);
>  }
> @@ -329,7 +329,7 @@ static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
>   */
>  static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	uint16_t word = byte;
>  
>  	/*
> @@ -361,7 +361,7 @@ static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte)
>   */
>  static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	iowrite8_rep(chip->IO_ADDR_W, buf, len);
>  }
> @@ -376,7 +376,7 @@ static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
>   */
>  static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	ioread8_rep(chip->IO_ADDR_R, buf, len);
>  }
> @@ -391,7 +391,7 @@ static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>   */
>  static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	u16 *p = (u16 *) buf;
>  
>  	iowrite16_rep(chip->IO_ADDR_W, p, len >> 1);
> @@ -407,7 +407,7 @@ static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
>   */
>  static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	u16 *p = (u16 *) buf;
>  
>  	ioread16_rep(chip->IO_ADDR_R, p, len >> 1);
> @@ -423,7 +423,7 @@ static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
>  static int nand_block_bad(struct mtd_info *mtd, loff_t ofs)
>  {
>  	int page, page_end, res;
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	u8 bad;
>  
>  	if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
> @@ -461,7 +461,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs)
>   */
>  static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mtd_oob_ops ops;
>  	uint8_t buf[2] = { 0, 0 };
>  	int ret = 0, res, i = 0;
> @@ -511,7 +511,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
>  */
>  static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	int res, ret = 0;
>  
>  	if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) {
> @@ -552,7 +552,7 @@ static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
>   */
>  static int nand_check_wp(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	/* Broken xD cards report WP despite being writable */
>  	if (chip->options & NAND_BROKEN_XD)
> @@ -572,7 +572,7 @@ static int nand_check_wp(struct mtd_info *mtd)
>   */
>  static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (!chip->bbt)
>  		return 0;
> @@ -591,7 +591,7 @@ static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs)
>   */
>  static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int allowbbt)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (!chip->bbt)
>  		return chip->block_bad(mtd, ofs);
> @@ -610,7 +610,7 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int allowbbt)
>   */
>  static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	int i;
>  
>  	/* Wait for the device to get ready */
> @@ -630,7 +630,7 @@ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
>   */
>  void nand_wait_ready(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	unsigned long timeo = 400;
>  
>  	if (in_interrupt() || oops_in_progress)
> @@ -658,7 +658,7 @@ void nand_wait_ready(struct mtd_info *mtd)
>   */
>  static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo)
>  {
> -	register struct nand_chip *chip = mtd_to_nand(mtd);
> +	register struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	timeo = jiffies + msecs_to_jiffies(timeo);
>  	do {
> @@ -681,7 +681,7 @@ static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo)
>  static void nand_command(struct mtd_info *mtd, unsigned int command,
>  			 int column, int page_addr)
>  {
> -	register struct nand_chip *chip = mtd_to_nand(mtd);
> +	register struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
>  
>  	/* Write out the command to the device */
> @@ -805,7 +805,7 @@ static void nand_ccs_delay(struct nand_chip *chip)
>  static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
>  			    int column, int page_addr)
>  {
> -	register struct nand_chip *chip = mtd_to_nand(mtd);
> +	register struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	/* Emulate NAND_CMD_READOOB */
>  	if (command == NAND_CMD_READOOB) {
> @@ -939,7 +939,7 @@ static void panic_nand_get_device(struct nand_chip *chip,
>  static int
>  nand_get_device(struct mtd_info *mtd, int new_state)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	spinlock_t *lock = &chip->controller->lock;
>  	wait_queue_head_t *wq = &chip->controller->wq;
>  	DECLARE_WAITQUEUE(wait, current);
> @@ -1049,7 +1049,7 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
>   */
>  static int nand_reset_data_interface(struct nand_chip *chip)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	const struct nand_data_interface *conf;
>  	int ret;
>  
> @@ -1092,7 +1092,7 @@ static int nand_reset_data_interface(struct nand_chip *chip)
>   */
>  static int nand_setup_data_interface(struct nand_chip *chip)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	int ret;
>  
>  	if (!chip->setup_data_interface || !chip->data_interface)
> @@ -1135,7 +1135,7 @@ static int nand_setup_data_interface(struct nand_chip *chip)
>   */
>  static int nand_init_data_interface(struct nand_chip *chip)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	int modes, mode, ret;
>  
>  	if (!chip->setup_data_interface)
> @@ -1190,7 +1190,7 @@ static void nand_release_data_interface(struct nand_chip *chip)
>   */
>  int nand_reset(struct nand_chip *chip, int chipnr)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	int ret;
>  
>  	ret = nand_reset_data_interface(chip);
> @@ -1231,7 +1231,7 @@ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
>  {
>  	int ret = 0;
>  	int status, page;
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	/* Submit address of first page to unlock */
>  	page = ofs >> chip->page_shift;
> @@ -1266,7 +1266,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
>  {
>  	int ret = 0;
>  	int chipnr;
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	pr_debug("%s: start = 0x%012llx, len = %llu\n",
>  			__func__, (unsigned long long)ofs, len);
> @@ -1329,7 +1329,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
>  {
>  	int ret = 0;
>  	int chipnr, status, page;
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	pr_debug("%s: start = 0x%012llx, len = %llu\n",
>  			__func__, (unsigned long long)ofs, len);
> @@ -1935,7 +1935,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
>  static uint8_t *nand_transfer_oob(struct mtd_info *mtd, uint8_t *oob,
>  				  struct mtd_oob_ops *ops, size_t len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	int ret;
>  
>  	switch (ops->mode) {
> @@ -1968,7 +1968,7 @@ static uint8_t *nand_transfer_oob(struct mtd_info *mtd, uint8_t *oob,
>   */
>  static int nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	pr_debug("setting READ RETRY mode %d\n", retry_mode);
>  
> @@ -1993,7 +1993,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
>  			    struct mtd_oob_ops *ops)
>  {
>  	int chipnr, page, realpage, col, bytes, aligned, oob_required;
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	int ret = 0;
>  	uint32_t readlen = ops->len;
>  	uint32_t oobreadlen = ops->ooblen;
> @@ -2176,8 +2176,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
>   *
>   * Get hold of the chip and call nand_do_read.
>   */
> -static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
> -		     size_t *retlen, uint8_t *buf)
> +static int nandc_read(struct mtd_info *mtd, loff_t from, size_t len,
> +		      size_t *retlen, uint8_t *buf)
>  {
>  	struct mtd_oob_ops ops;
>  	int ret;
> @@ -2340,7 +2340,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
>  			    struct mtd_oob_ops *ops)
>  {
>  	int page, realpage, chipnr;
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mtd_ecc_stats stats;
>  	int readlen = ops->ooblen;
>  	int len;
> @@ -2785,7 +2785,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
>  static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
>  			      struct mtd_oob_ops *ops)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	int ret;
>  
>  	/*
> @@ -2827,7 +2827,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
>  			     struct mtd_oob_ops *ops)
>  {
>  	int chipnr, realpage, page, blockmask, column;
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	uint32_t writelen = ops->len;
>  
>  	uint32_t oobwritelen = ops->ooblen;
> @@ -2959,7 +2959,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
>  static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
>  			    size_t *retlen, const uint8_t *buf)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct mtd_oob_ops ops;
>  	int ret;
>  
> @@ -2990,8 +2990,8 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
>   *
>   * NAND write with ECC.
>   */
> -static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
> -			  size_t *retlen, const uint8_t *buf)
> +static int nandc_write(struct mtd_info *mtd, loff_t to, size_t len,
> +		       size_t *retlen, const uint8_t *buf)
>  {
>  	struct mtd_oob_ops ops;
>  	int ret;
> @@ -3019,7 +3019,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
>  			     struct mtd_oob_ops *ops)
>  {
>  	int chipnr, page, status, len;
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	pr_debug("%s: to = 0x%08x, len = %i\n",
>  			 __func__, (unsigned int)to, (int)ops->ooblen);
> @@ -3142,7 +3142,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
>   */
>  static int single_erase(struct mtd_info *mtd, int page)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	/* Send commands to erase a block */
>  	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
>  	chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
> @@ -3157,7 +3157,7 @@ static int single_erase(struct mtd_info *mtd, int page)
>   *
>   * Erase one ore more blocks.
>   */
> -static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
> +static int nandc_erase(struct mtd_info *mtd, struct erase_info *instr)
>  {
>  	return nand_erase_nand(mtd, instr, 0);
>  }
> @@ -3174,7 +3174,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
>  		    int allowbbt)
>  {
>  	int page, status, pages_per_block, ret, chipnr;
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	loff_t len;
>  
>  	pr_debug("%s: start = 0x%012llx, len = %llu\n",
> @@ -3300,7 +3300,7 @@ static void nand_sync(struct mtd_info *mtd)
>   */
>  static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	int chipnr = (int)(offs >> chip->chip_shift);
>  	int ret;
>  
> @@ -3344,7 +3344,7 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
>   */
>  static int nand_max_bad_blocks(struct mtd_info *mtd, loff_t ofs, size_t len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	u32 part_start_block;
>  	u32 part_end_block;
>  	u32 part_start_die;
> @@ -3438,7 +3438,7 @@ static int nand_suspend(struct mtd_info *mtd)
>   */
>  static void nand_resume(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (chip->state == FL_PM_SUSPENDED)
>  		nand_release_device(mtd);
> @@ -3544,7 +3544,7 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
>  static int nand_flash_detect_ext_param_page(struct nand_chip *chip,
>  					    struct nand_onfi_params *p)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct onfi_ext_param_page *ep;
>  	struct onfi_ext_section *s;
>  	struct onfi_ext_ecc_info *ecc;
> @@ -3617,7 +3617,7 @@ static int nand_flash_detect_ext_param_page(struct nand_chip *chip,
>   */
>  static int nand_flash_detect_onfi(struct nand_chip *chip)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct nand_onfi_params *p = &chip->onfi_params;
>  	int i, j;
>  	int val;
> @@ -3719,7 +3719,7 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
>   */
>  static int nand_flash_detect_jedec(struct nand_chip *chip)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct nand_jedec_params *p = &chip->jedec_params;
>  	struct jedec_ecc_info *ecc;
>  	int val;
> @@ -3869,7 +3869,7 @@ static int nand_get_bits_per_cell(u8 cellinfo)
>   */
>  void nand_decode_ext_id(struct nand_chip *chip)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	int extid;
>  	u8 *id_data = chip->id.data;
>  	/* The 3rd id byte holds MLC / multichip data */
> @@ -3899,7 +3899,7 @@ void nand_decode_ext_id(struct nand_chip *chip)
>   */
>  static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  
>  	mtd->erasesize = type->erasesize;
>  	mtd->writesize = type->pagesize;
> @@ -3916,7 +3916,7 @@ static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type)
>   */
>  static void nand_decode_bbm_options(struct nand_chip *chip)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  
>  	/* Set the bad block position */
>  	if (mtd->writesize > 512 || (chip->options & NAND_BUSWIDTH_16))
> @@ -3933,7 +3933,7 @@ static inline bool is_full_id_nand(struct nand_flash_dev *type)
>  static bool find_full_id_nand(struct nand_chip *chip,
>  			      struct nand_flash_dev *type)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	u8 *id_data = chip->id.data;
>  
>  	if (!strncmp(type->id, id_data, type->id_len)) {
> @@ -4010,7 +4010,7 @@ static void nand_manufacturer_cleanup(struct nand_chip *chip)
>  static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
>  {
>  	const struct nand_manufacturer *manufacturer;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	int busw;
>  	int i, ret;
>  	u8 *id_data = chip->id.data;
> @@ -4333,7 +4333,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
>  		    struct nand_flash_dev *table)
>  {
>  	int i, nand_maf_id, nand_dev_id;
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	int ret;
>  
>  	ret = nand_dt_init(chip);
> @@ -4415,7 +4415,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
>  
>  static int nand_set_ecc_soft_ops(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
>  
>  	if (WARN_ON(ecc->mode != NAND_ECC_SOFT))
> @@ -4525,7 +4525,7 @@ static int nand_set_ecc_soft_ops(struct mtd_info *mtd)
>   */
>  static bool nand_ecc_strength_good(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
>  	int corr, ds_corr;
>  
> @@ -4573,7 +4573,7 @@ static bool invalid_ecc_page_accessors(struct nand_chip *chip)
>   */
>  int nand_scan_tail(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
>  	struct nand_buffers *nbuf = NULL;
>  	int ret;
> @@ -4827,11 +4827,11 @@ int nand_scan_tail(struct mtd_info *mtd)
>  	mtd->type = nand_is_slc(chip) ? MTD_NANDFLASH : MTD_MLCNANDFLASH;
>  	mtd->flags = (chip->options & NAND_ROM) ? MTD_CAP_ROM :
>  						MTD_CAP_NANDFLASH;
> -	mtd->_erase = nand_erase;
> +	mtd->_erase = nandc_erase;
>  	mtd->_point = NULL;
>  	mtd->_unpoint = NULL;
> -	mtd->_read = nand_read;
> -	mtd->_write = nand_write;
> +	mtd->_read = nandc_read;
> +	mtd->_write = nandc_write;
>  	mtd->_panic_write = panic_nand_write;
>  	mtd->_read_oob = nand_read_oob;
>  	mtd->_write_oob = nand_write_oob;
> @@ -4943,7 +4943,7 @@ void nand_cleanup(struct nand_chip *chip)
>  void nand_release(struct mtd_info *mtd)
>  {
>  	mtd_device_unregister(mtd);
> -	nand_cleanup(mtd_to_nand(mtd));
> +	nand_cleanup(mtd_to_nandchip(mtd));
>  }
>  EXPORT_SYMBOL_GPL(nand_release);
>  
> diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
> index 2915b67..396b248 100644
> --- a/drivers/mtd/nand/raw/nand_bbt.c
> +++ b/drivers/mtd/nand/raw/nand_bbt.c
> @@ -172,7 +172,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
>  		struct nand_bbt_descr *td, int offs)
>  {
>  	int res, ret = 0, i, j, act = 0;
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	size_t retlen, len, totlen;
>  	loff_t from;
>  	int bits = td->options & NAND_BBT_NRBITS_MSK;
> @@ -263,7 +263,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
>   */
>  static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	int res = 0, i;
>  
>  	if (td->options & NAND_BBT_PERCHIP) {
> @@ -388,7 +388,7 @@ static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td)
>  static void read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
>  			  struct nand_bbt_descr *td, struct nand_bbt_descr *md)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  
>  	/* Read the primary version, if available */
>  	if (td->options & NAND_BBT_VERSION) {
> @@ -454,7 +454,7 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
>  static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
>  	struct nand_bbt_descr *bd, int chip)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	int i, numblocks, numpages;
>  	int startblock;
>  	loff_t from;
> @@ -523,7 +523,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
>   */
>  static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	int i, chips;
>  	int startblock, block, dir;
>  	int scanlen = mtd->writesize + mtd->oobsize;
> @@ -683,7 +683,7 @@ static void mark_bbt_block_bad(struct nand_chip *this,
>  			       struct nand_bbt_descr *td,
>  			       int chip, int block)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(this);
> +	struct mtd_info *mtd = nandchip_to_mtd(this);
>  	loff_t to;
>  	int res;
>  
> @@ -712,7 +712,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
>  		     struct nand_bbt_descr *td, struct nand_bbt_descr *md,
>  		     int chipsel)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct erase_info einfo;
>  	int i, res, chip = 0;
>  	int bits, page, offs, numblocks, sft, sftmsk;
> @@ -896,7 +896,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
>   */
>  static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  
>  	return create_bbt(mtd, this->buffers->databuf, bd, -1);
>  }
> @@ -915,7 +915,7 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b
>  static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
>  {
>  	int i, chips, writeops, create, chipsel, res, res2;
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct nand_bbt_descr *td = this->bbt_td;
>  	struct nand_bbt_descr *md = this->bbt_md;
>  	struct nand_bbt_descr *rd, *rd2;
> @@ -1039,7 +1039,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
>   */
>  static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	int i, j, chips, block, nrblocks, update;
>  	uint8_t oldval;
>  
> @@ -1099,7 +1099,7 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
>   */
>  static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	u32 pattern_len;
>  	u32 bits;
>  	u32 table_size;
> @@ -1151,7 +1151,7 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
>   */
>  static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	int len, res;
>  	uint8_t *buf;
>  	struct nand_bbt_descr *td = this->bbt_td;
> @@ -1224,7 +1224,7 @@ static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
>   */
>  static int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	int len, res = 0;
>  	int chip, chipsel;
>  	uint8_t *buf;
> @@ -1358,7 +1358,7 @@ static int nand_create_badblock_pattern(struct nand_chip *this)
>   */
>  int nand_default_bbt(struct mtd_info *mtd)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	int ret;
>  
>  	/* Is a flash based bad block table requested? */
> @@ -1394,7 +1394,7 @@ int nand_default_bbt(struct mtd_info *mtd)
>   */
>  int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	int block;
>  
>  	block = (int)(offs >> this->bbt_erase_shift);
> @@ -1409,7 +1409,7 @@ int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs)
>   */
>  int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	int block, res;
>  
>  	block = (int)(offs >> this->bbt_erase_shift);
> @@ -1436,7 +1436,7 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
>   */
>  int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	int block, ret = 0;
>  
>  	block = (int)(offs >> this->bbt_erase_shift);
> diff --git a/drivers/mtd/nand/raw/nand_bch.c b/drivers/mtd/nand/raw/nand_bch.c
> index 505441c..b1901d9 100644
> --- a/drivers/mtd/nand/raw/nand_bch.c
> +++ b/drivers/mtd/nand/raw/nand_bch.c
> @@ -50,7 +50,7 @@ struct nand_bch_control {
>  int nand_bch_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
>  			   unsigned char *code)
>  {
> -	const struct nand_chip *chip = mtd_to_nand(mtd);
> +	const struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nand_bch_control *nbc = chip->ecc.priv;
>  	unsigned int i;
>  
> @@ -77,7 +77,7 @@ int nand_bch_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
>  int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
>  			  unsigned char *read_ecc, unsigned char *calc_ecc)
>  {
> -	const struct nand_chip *chip = mtd_to_nand(mtd);
> +	const struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nand_bch_control *nbc = chip->ecc.priv;
>  	unsigned int *errloc = nbc->errloc;
>  	int i, count;
> @@ -120,7 +120,7 @@ int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
>   */
>  struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	unsigned int m, t, eccsteps, i;
>  	struct nand_bch_control *nbc = NULL;
>  	unsigned char *erased_page;
> diff --git a/drivers/mtd/nand/raw/nand_ecc.c b/drivers/mtd/nand/raw/nand_ecc.c
> index 7613a03..741b68a 100644
> --- a/drivers/mtd/nand/raw/nand_ecc.c
> +++ b/drivers/mtd/nand/raw/nand_ecc.c
> @@ -424,7 +424,7 @@ int nand_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
>  		       unsigned char *code)
>  {
>  	__nand_calculate_ecc(buf,
> -			mtd_to_nand(mtd)->ecc.size, code);
> +			mtd_to_nandchip(mtd)->ecc.size, code);
>  
>  	return 0;
>  }
> @@ -524,7 +524,7 @@ int nand_correct_data(struct mtd_info *mtd, unsigned char *buf,
>  		      unsigned char *read_ecc, unsigned char *calc_ecc)
>  {
>  	return __nand_correct_data(buf, read_ecc, calc_ecc,
> -				   mtd_to_nand(mtd)->ecc.size);
> +				   mtd_to_nandchip(mtd)->ecc.size);
>  }
>  EXPORT_SYMBOL(nand_correct_data);
>  
> diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
> index b735cc8..b35a0a5 100644
> --- a/drivers/mtd/nand/raw/nand_hynix.c
> +++ b/drivers/mtd/nand/raw/nand_hynix.c
> @@ -67,7 +67,7 @@ struct hynix_read_retry_otp {
>  
>  static bool hynix_nand_has_valid_jedecid(struct nand_chip *chip)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	u8 jedecid[6] = { };
>  	int i = 0;
>  
> @@ -80,7 +80,7 @@ static bool hynix_nand_has_valid_jedecid(struct nand_chip *chip)
>  
>  static int hynix_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct hynix_nand *hynix = nand_get_manufacturer_data(chip);
>  	const u8 *values;
>  	int status;
> @@ -172,7 +172,7 @@ static int hynix_read_rr_otp(struct nand_chip *chip,
>  			     const struct hynix_read_retry_otp *info,
>  			     void *buf)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	int i;
>  
>  	chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
> @@ -365,7 +365,7 @@ static int hynix_nand_rr_init(struct nand_chip *chip)
>  static void hynix_nand_extract_oobsize(struct nand_chip *chip,
>  				       bool valid_jedecid)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	u8 oobsize;
>  
>  	oobsize = ((chip->id.data[3] >> 2) & 0x3) |
> @@ -543,7 +543,7 @@ static void hynix_nand_extract_scrambling_requirements(struct nand_chip *chip,
>  
>  static void hynix_nand_decode_id(struct nand_chip *chip)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	bool valid_jedecid;
>  	u8 tmp;
>  
> diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c
> index 02c4c1f..6dd0876 100644
> --- a/drivers/mtd/nand/raw/nand_micron.c
> +++ b/drivers/mtd/nand/raw/nand_micron.c
> @@ -45,7 +45,7 @@ struct nand_onfi_vendor_micron {
>  
>  static int micron_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode};
>  
>  	return chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY,
> @@ -108,7 +108,7 @@ static int micron_nand_on_die_ecc_setup(struct nand_chip *chip, bool enable)
>  	if (enable)
>  		feature[0] |= ONFI_FEATURE_ON_DIE_ECC_EN;
>  
> -	return chip->onfi_set_features(nand_to_mtd(chip), chip,
> +	return chip->onfi_set_features(nandchip_to_mtd(chip), chip,
>  				       ONFI_FEATURE_ON_DIE_ECC, feature);
>  }
>  
> @@ -229,7 +229,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
>  	if (ret)
>  		return MICRON_ON_DIE_UNSUPPORTED;
>  
> -	chip->onfi_get_features(nand_to_mtd(chip), chip,
> +	chip->onfi_get_features(nandchip_to_mtd(chip), chip,
>  				ONFI_FEATURE_ON_DIE_ECC, feature);
>  	if ((feature[0] & ONFI_FEATURE_ON_DIE_ECC_EN) == 0)
>  		return MICRON_ON_DIE_UNSUPPORTED;
> @@ -238,7 +238,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
>  	if (ret)
>  		return MICRON_ON_DIE_UNSUPPORTED;
>  
> -	chip->onfi_get_features(nand_to_mtd(chip), chip,
> +	chip->onfi_get_features(nandchip_to_mtd(chip), chip,
>  				ONFI_FEATURE_ON_DIE_ECC, feature);
>  	if (feature[0] & ONFI_FEATURE_ON_DIE_ECC_EN)
>  		return MICRON_ON_DIE_MANDATORY;
> @@ -255,7 +255,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
>  
>  static int micron_nand_init(struct nand_chip *chip)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	int ondie;
>  	int ret;
>  
> diff --git a/drivers/mtd/nand/raw/nand_samsung.c b/drivers/mtd/nand/raw/nand_samsung.c
> index ca17b44..bc54b578 100644
> --- a/drivers/mtd/nand/raw/nand_samsung.c
> +++ b/drivers/mtd/nand/raw/nand_samsung.c
> @@ -19,7 +19,7 @@
>  
>  static void samsung_nand_decode_id(struct nand_chip *chip)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  
>  	/* New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) */
>  	if (chip->id.len == 6 && !nand_is_slc(chip) &&
> @@ -93,7 +93,7 @@ static void samsung_nand_decode_id(struct nand_chip *chip)
>  
>  static int samsung_nand_init(struct nand_chip *chip)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  
>  	if (mtd->writesize > 512)
>  		chip->options |= NAND_SAMSUNG_LP_OPTIONS;
> diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
> index 57df857..8a24ccc 100644
> --- a/drivers/mtd/nand/raw/nand_toshiba.c
> +++ b/drivers/mtd/nand/raw/nand_toshiba.c
> @@ -19,7 +19,7 @@
>  
>  static void toshiba_nand_decode_id(struct nand_chip *chip)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  
>  	nand_decode_ext_id(chip);
>  
> diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c
> index 5ba4635..a0246fc 100644
> --- a/drivers/mtd/nand/raw/nandsim.c
> +++ b/drivers/mtd/nand/raw/nandsim.c
> @@ -662,7 +662,7 @@ static char __init *get_partition_name(int i)
>   */
>  static int __init init_nandsim(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nandsim   *ns   = nand_get_controller_data(chip);
>  	int i, ret = 0;
>  	uint64_t remains;
> @@ -1892,7 +1892,7 @@ static void switch_state(struct nandsim *ns)
>  
>  static u_char ns_nand_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nandsim *ns = nand_get_controller_data(chip);
>  	u_char outb = 0x00;
>  
> @@ -1954,7 +1954,7 @@ static u_char ns_nand_read_byte(struct mtd_info *mtd)
>  
>  static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nandsim *ns = nand_get_controller_data(chip);
>  
>  	/* Sanity and correctness checks */
> @@ -2109,7 +2109,7 @@ static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
>  
>  static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nandsim *ns = nand_get_controller_data(chip);
>  
>  	ns->lines.cle = bitmask & NAND_CLE ? 1 : 0;
> @@ -2128,7 +2128,7 @@ static int ns_device_ready(struct mtd_info *mtd)
>  
>  static uint16_t ns_nand_read_word(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	NS_DBG("read_word\n");
>  
> @@ -2137,7 +2137,7 @@ static uint16_t ns_nand_read_word(struct mtd_info *mtd)
>  
>  static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nandsim *ns = nand_get_controller_data(chip);
>  
>  	/* Check that chip is expecting data input */
> @@ -2165,7 +2165,7 @@ static void ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
>  
>  static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nandsim *ns = nand_get_controller_data(chip);
>  
>  	/* Sanity and correctness checks */
> @@ -2187,7 +2187,7 @@ static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
>  		int i;
>  
>  		for (i = 0; i < len; i++)
> -			buf[i] = mtd_to_nand(mtd)->read_byte(mtd);
> +			buf[i] = mtd_to_nandchip(mtd)->read_byte(mtd);
>  
>  		return;
>  	}
> @@ -2231,7 +2231,7 @@ static int __init ns_init_module(void)
>  		NS_ERR("unable to allocate core structures.\n");
>  		return -ENOMEM;
>  	}
> -	nsmtd       = nand_to_mtd(chip);
> +	nsmtd       = nandchip_to_mtd(chip);
>  	nand        = (struct nandsim *)(chip + 1);
>  	nand_set_controller_data(chip, (void *)nand);
>  
> @@ -2391,7 +2391,7 @@ static int __init ns_init_module(void)
>   */
>  static void __exit ns_cleanup_module(void)
>  {
> -	struct nand_chip *chip = mtd_to_nand(nsmtd);
> +	struct nand_chip *chip = mtd_to_nandchip(nsmtd);
>  	struct nandsim *ns = nand_get_controller_data(chip);
>  	int i;
>  
> @@ -2400,7 +2400,7 @@ static void __exit ns_cleanup_module(void)
>  	nand_release(nsmtd); /* Unregister driver */
>  	for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i)
>  		kfree(ns->partitions[i].name);
> -	kfree(mtd_to_nand(nsmtd));        /* Free other structures */
> +	kfree(mtd_to_nandchip(nsmtd));        /* Free other structures */
>  	free_lists();
>  }
>  
> diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c
> index d8a8068..3b9ecbe 100644
> --- a/drivers/mtd/nand/raw/ndfc.c
> +++ b/drivers/mtd/nand/raw/ndfc.c
> @@ -47,7 +47,7 @@ struct ndfc_controller {
>  static void ndfc_select_chip(struct mtd_info *mtd, int chip)
>  {
>  	uint32_t ccr;
> -	struct nand_chip *nchip = mtd_to_nand(mtd);
> +	struct nand_chip *nchip = mtd_to_nandchip(mtd);
>  	struct ndfc_controller *ndfc = nand_get_controller_data(nchip);
>  
>  	ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
> @@ -61,7 +61,7 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip)
>  
>  static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct ndfc_controller *ndfc = nand_get_controller_data(chip);
>  
>  	if (cmd == NAND_CMD_NONE)
> @@ -75,7 +75,7 @@ static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
>  
>  static int ndfc_ready(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct ndfc_controller *ndfc = nand_get_controller_data(chip);
>  
>  	return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
> @@ -84,7 +84,7 @@ static int ndfc_ready(struct mtd_info *mtd)
>  static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
>  {
>  	uint32_t ccr;
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct ndfc_controller *ndfc = nand_get_controller_data(chip);
>  
>  	ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
> @@ -96,7 +96,7 @@ static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
>  static int ndfc_calculate_ecc(struct mtd_info *mtd,
>  			      const u_char *dat, u_char *ecc_code)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct ndfc_controller *ndfc = nand_get_controller_data(chip);
>  	uint32_t ecc;
>  	uint8_t *p = (uint8_t *)&ecc;
> @@ -120,7 +120,7 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd,
>   */
>  static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct ndfc_controller *ndfc = nand_get_controller_data(chip);
>  	uint32_t *p = (uint32_t *) buf;
>  
> @@ -130,7 +130,7 @@ static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  
>  static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct ndfc_controller *ndfc = nand_get_controller_data(chip);
>  	uint32_t *p = (uint32_t *) buf;
>  
> @@ -146,7 +146,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
>  {
>  	struct device_node *flash_np;
>  	struct nand_chip *chip = &ndfc->chip;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	int ret;
>  
>  	chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
> @@ -256,7 +256,7 @@ static int ndfc_probe(struct platform_device *ofdev)
>  static int ndfc_remove(struct platform_device *ofdev)
>  {
>  	struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev);
> -	struct mtd_info *mtd = nand_to_mtd(&ndfc->chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&ndfc->chip);
>  
>  	nand_release(mtd);
>  	kfree(mtd->name);
> diff --git a/drivers/mtd/nand/raw/nuc900_nand.c b/drivers/mtd/nand/raw/nuc900_nand.c
> index 7bb4d2e..2a2bfce 100644
> --- a/drivers/mtd/nand/raw/nuc900_nand.c
> +++ b/drivers/mtd/nand/raw/nuc900_nand.c
> @@ -63,7 +63,7 @@ struct nuc900_nand {
>  
>  static inline struct nuc900_nand *mtd_to_nuc900(struct mtd_info *mtd)
>  {
> -	return container_of(mtd_to_nand(mtd), struct nuc900_nand, chip);
> +	return container_of(mtd_to_nandchip(mtd), struct nuc900_nand, chip);
>  }
>  
>  static const struct mtd_partition partitions[] = {
> @@ -132,7 +132,7 @@ static int nuc900_nand_devready(struct mtd_info *mtd)
>  static void nuc900_nand_command_lp(struct mtd_info *mtd, unsigned int command,
>  				   int column, int page_addr)
>  {
> -	register struct nand_chip *chip = mtd_to_nand(mtd);
> +	register struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nuc900_nand *nand = mtd_to_nuc900(mtd);
>  
>  	if (command == NAND_CMD_READOOB) {
> @@ -243,7 +243,7 @@ static int nuc900_nand_probe(struct platform_device *pdev)
>  	if (!nuc900_nand)
>  		return -ENOMEM;
>  	chip = &(nuc900_nand->chip);
> -	mtd = nand_to_mtd(chip);
> +	mtd = nandchip_to_mtd(chip);
>  
>  	mtd->dev.parent		= &pdev->dev;
>  	spin_lock_init(&nuc900_nand->lock);
> @@ -284,7 +284,7 @@ static int nuc900_nand_remove(struct platform_device *pdev)
>  {
>  	struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev);
>  
> -	nand_release(nand_to_mtd(&nuc900_nand->chip));
> +	nand_release(nandchip_to_mtd(&nuc900_nand->chip));
>  	clk_disable(nuc900_nand->clk);
>  
>  	return 0;
> diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c
> index 54540c8..d8ec8a3 100644
> --- a/drivers/mtd/nand/raw/omap2.c
> +++ b/drivers/mtd/nand/raw/omap2.c
> @@ -184,7 +184,7 @@ struct omap_nand_info {
>  
>  static inline struct omap_nand_info *mtd_to_omap(struct mtd_info *mtd)
>  {
> -	return container_of(mtd_to_nand(mtd), struct omap_nand_info, nand);
> +	return container_of(mtd_to_nandchip(mtd), struct omap_nand_info, nand);
>  }
>  
>  /**
> @@ -279,7 +279,7 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
>   */
>  static void omap_read_buf8(struct mtd_info *mtd, u_char *buf, int len)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  
>  	ioread8_rep(nand->IO_ADDR_R, buf, len);
>  }
> @@ -313,7 +313,7 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
>   */
>  static void omap_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  
>  	ioread16_rep(nand->IO_ADDR_R, buf, len / 2);
>  }
> @@ -944,7 +944,7 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
>  static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
>  {
>  	struct omap_nand_info *info = mtd_to_omap(mtd);
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
>  	u32 val;
>  
> @@ -990,7 +990,7 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
>   */
>  static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct omap_nand_info *info = mtd_to_omap(mtd);
>  	unsigned long timeo = jiffies;
>  	int status, state = this->state;
> @@ -1042,7 +1042,7 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, int mode)
>  	unsigned int dev_width, nsectors;
>  	struct omap_nand_info *info = mtd_to_omap(mtd);
>  	enum omap_ecc ecc_opt = info->ecc_opt;
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	u32 val, wr_mode;
>  	unsigned int ecc_size1, ecc_size0;
>  
> @@ -1757,7 +1757,7 @@ static int omap_ooblayout_free(struct mtd_info *mtd, int section,
>  static int omap_sw_ooblayout_ecc(struct mtd_info *mtd, int section,
>  				 struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	int off = BADBLOCK_MARKER_LENGTH;
>  
>  	if (section >= chip->ecc.steps)
> @@ -1776,7 +1776,7 @@ static int omap_sw_ooblayout_ecc(struct mtd_info *mtd, int section,
>  static int omap_sw_ooblayout_free(struct mtd_info *mtd, int section,
>  				  struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	int off = BADBLOCK_MARKER_LENGTH;
>  
>  	if (section)
> @@ -1851,7 +1851,7 @@ static int omap_nand_probe(struct platform_device *pdev)
>  	}
>  
>  	nand_chip		= &info->nand;
> -	mtd			= nand_to_mtd(nand_chip);
> +	mtd			= nandchip_to_mtd(nand_chip);
>  	mtd->dev.parent		= &pdev->dev;
>  	nand_chip->ecc.priv	= NULL;
>  	nand_set_flash_node(nand_chip, dev->of_node);
> @@ -2189,7 +2189,7 @@ static int omap_nand_probe(struct platform_device *pdev)
>  static int omap_nand_remove(struct platform_device *pdev)
>  {
>  	struct mtd_info *mtd = platform_get_drvdata(pdev);
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct omap_nand_info *info = mtd_to_omap(mtd);
>  	if (nand_chip->ecc.priv) {
>  		nand_bch_free(nand_chip->ecc.priv);
> diff --git a/drivers/mtd/nand/raw/orion_nand.c b/drivers/mtd/nand/raw/orion_nand.c
> index ae4c0be..24f35fa 100644
> --- a/drivers/mtd/nand/raw/orion_nand.c
> +++ b/drivers/mtd/nand/raw/orion_nand.c
> @@ -30,7 +30,7 @@ struct orion_nand_info {
>  
>  static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
>  {
> -	struct nand_chip *nc = mtd_to_nand(mtd);
> +	struct nand_chip *nc = mtd_to_nandchip(mtd);
>  	struct orion_nand_data *board = nand_get_controller_data(nc);
>  	u32 offs;
>  
> @@ -52,7 +52,7 @@ static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl
>  
>  static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	void __iomem *io_base = chip->IO_ADDR_R;
>  	uint64_t *buf64;
>  	int i = 0;
> @@ -95,7 +95,7 @@ static int __init orion_nand_probe(struct platform_device *pdev)
>  	if (!info)
>  		return -ENOMEM;
>  	nc = &info->chip;
> -	mtd = nand_to_mtd(nc);
> +	mtd = nandchip_to_mtd(nc);
>  
>  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>  	io_base = devm_ioremap_resource(&pdev->dev, res);
> @@ -190,7 +190,7 @@ static int orion_nand_remove(struct platform_device *pdev)
>  {
>  	struct orion_nand_info *info = platform_get_drvdata(pdev);
>  	struct nand_chip *chip = &info->chip;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  
>  	nand_release(mtd);
>  
> diff --git a/drivers/mtd/nand/raw/oxnas_nand.c b/drivers/mtd/nand/raw/oxnas_nand.c
> index f14eec3..27eeee3 100644
> --- a/drivers/mtd/nand/raw/oxnas_nand.c
> +++ b/drivers/mtd/nand/raw/oxnas_nand.c
> @@ -40,7 +40,7 @@ struct oxnas_nand_ctrl {
>  
>  static uint8_t oxnas_nand_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
>  
>  	return readb(oxnas->io_base);
> @@ -48,7 +48,7 @@ static uint8_t oxnas_nand_read_byte(struct mtd_info *mtd)
>  
>  static void oxnas_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
>  
>  	ioread8_rep(oxnas->io_base, buf, len);
> @@ -56,7 +56,7 @@ static void oxnas_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
>  
>  static void oxnas_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
>  
>  	iowrite8_rep(oxnas->io_base, buf, len);
> @@ -66,7 +66,7 @@ static void oxnas_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
>  static void oxnas_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
>  				unsigned int ctrl)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
>  
>  	if (ctrl & NAND_CLE)
> @@ -126,7 +126,7 @@ static int oxnas_nand_probe(struct platform_device *pdev)
>  		nand_set_flash_node(chip, nand_np);
>  		nand_set_controller_data(chip, oxnas);
>  
> -		mtd = nand_to_mtd(chip);
> +		mtd = nandchip_to_mtd(chip);
>  		mtd->dev.parent = &pdev->dev;
>  		mtd->priv = chip;
>  
> @@ -165,7 +165,7 @@ static int oxnas_nand_remove(struct platform_device *pdev)
>  	struct oxnas_nand_ctrl *oxnas = platform_get_drvdata(pdev);
>  
>  	if (oxnas->chips[0])
> -		nand_release(nand_to_mtd(oxnas->chips[0]));
> +		nand_release(nandchip_to_mtd(oxnas->chips[0]));
>  
>  	clk_disable_unprepare(oxnas->clk);
>  
> diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c
> index a47a7e4..7b69e3e 100644
> --- a/drivers/mtd/nand/raw/pasemi_nand.c
> +++ b/drivers/mtd/nand/raw/pasemi_nand.c
> @@ -45,7 +45,7 @@
>  
>  static void pasemi_read_buf(struct mtd_info *mtd, u_char *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	while (len > 0x800) {
>  		memcpy_fromio(buf, chip->IO_ADDR_R, 0x800);
> @@ -57,7 +57,7 @@ static void pasemi_read_buf(struct mtd_info *mtd, u_char *buf, int len)
>  
>  static void pasemi_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	while (len > 0x800) {
>  		memcpy_toio(chip->IO_ADDR_R, buf, 0x800);
> @@ -70,7 +70,7 @@ static void pasemi_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
>  static void pasemi_hwcontrol(struct mtd_info *mtd, int cmd,
>  			     unsigned int ctrl)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (cmd == NAND_CMD_NONE)
>  		return;
> @@ -117,7 +117,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev)
>  		goto out;
>  	}
>  
> -	pasemi_nand_mtd = nand_to_mtd(chip);
> +	pasemi_nand_mtd = nandchip_to_mtd(chip);
>  
>  	/* Link the private data with the MTD structure */
>  	pasemi_nand_mtd->dev.parent = dev;
> @@ -188,7 +188,7 @@ static int pasemi_nand_remove(struct platform_device *ofdev)
>  	if (!pasemi_nand_mtd)
>  		return 0;
>  
> -	chip = mtd_to_nand(pasemi_nand_mtd);
> +	chip = mtd_to_nandchip(pasemi_nand_mtd);
>  
>  	/* Release resources, unregister device */
>  	nand_release(pasemi_nand_mtd);
> diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c
> index 925a132..ba10bb1 100644
> --- a/drivers/mtd/nand/raw/plat_nand.c
> +++ b/drivers/mtd/nand/raw/plat_nand.c
> @@ -57,7 +57,7 @@ static int plat_nand_probe(struct platform_device *pdev)
>  		return PTR_ERR(data->io_base);
>  
>  	nand_set_flash_node(&data->chip, pdev->dev.of_node);
> -	mtd = nand_to_mtd(&data->chip);
> +	mtd = nandchip_to_mtd(&data->chip);
>  	mtd->dev.parent = &pdev->dev;
>  
>  	data->chip.IO_ADDR_R = data->io_base;
> @@ -114,7 +114,7 @@ static int plat_nand_remove(struct platform_device *pdev)
>  	struct plat_nand_data *data = platform_get_drvdata(pdev);
>  	struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev);
>  
> -	nand_release(nand_to_mtd(&data->chip));
> +	nand_release(nandchip_to_mtd(&data->chip));
>  	if (pdata->ctrl.remove)
>  		pdata->ctrl.remove(pdev);
>  
> diff --git a/drivers/mtd/nand/raw/pxa3xx_nand.c b/drivers/mtd/nand/raw/pxa3xx_nand.c
> index fc4d35e..94d3976 100644
> --- a/drivers/mtd/nand/raw/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/raw/pxa3xx_nand.c
> @@ -326,7 +326,7 @@ struct pxa3xx_nand_flash {
>  static int pxa3xx_ooblayout_ecc(struct mtd_info *mtd, int section,
>  				struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
>  	struct pxa3xx_nand_info *info = host->info_data;
>  	int nchunks = mtd->writesize / info->chunk_size;
> @@ -344,7 +344,7 @@ static int pxa3xx_ooblayout_ecc(struct mtd_info *mtd, int section,
>  static int pxa3xx_ooblayout_free(struct mtd_info *mtd, int section,
>  				 struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
>  	struct pxa3xx_nand_info *info = host->info_data;
>  	int nchunks = mtd->writesize / info->chunk_size;
> @@ -509,7 +509,7 @@ static int pxa3xx_nand_init_timings_compat(struct pxa3xx_nand_host *host,
>  	struct nand_chip *chip = &host->chip;
>  	struct pxa3xx_nand_info *info = host->info_data;
>  	const struct pxa3xx_nand_flash *f = NULL;
> -	struct mtd_info *mtd = nand_to_mtd(&host->chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&host->chip);
>  	int i, id, ntypes;
>  
>  	ntypes = ARRAY_SIZE(builtin_flash_types);
> @@ -931,7 +931,7 @@ static void set_command_address(struct pxa3xx_nand_info *info,
>  static void prepare_start_command(struct pxa3xx_nand_info *info, int command)
>  {
>  	struct pxa3xx_nand_host *host = info->host[info->cs];
> -	struct mtd_info *mtd = nand_to_mtd(&host->chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&host->chip);
>  
>  	/* reset data and oob column point to handle data */
>  	info->buf_start		= 0;
> @@ -984,7 +984,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
>  	struct mtd_info *mtd;
>  
>  	host = info->host[info->cs];
> -	mtd = nand_to_mtd(&host->chip);
> +	mtd = nandchip_to_mtd(&host->chip);
>  	addr_cycle = 0;
>  	exec_cmd = 1;
>  
> @@ -1168,7 +1168,7 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
>  static void nand_cmdfunc(struct mtd_info *mtd, unsigned command,
>  			 int column, int page_addr)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
>  	struct pxa3xx_nand_info *info = host->info_data;
>  	int exec_cmd;
> @@ -1217,7 +1217,7 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd,
>  				  const unsigned command,
>  				  int column, int page_addr)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
>  	struct pxa3xx_nand_info *info = host->info_data;
>  	int exec_cmd, ext_cmd_type;
> @@ -1373,7 +1373,7 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
>  
>  static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
>  	struct pxa3xx_nand_info *info = host->info_data;
>  	char retval = 0xFF;
> @@ -1387,7 +1387,7 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
>  
>  static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
>  	struct pxa3xx_nand_info *info = host->info_data;
>  	u16 retval = 0xFFFF;
> @@ -1401,7 +1401,7 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
>  
>  static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
>  	struct pxa3xx_nand_info *info = host->info_data;
>  	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
> @@ -1413,7 +1413,7 @@ static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
>  		const uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
>  	struct pxa3xx_nand_info *info = host->info_data;
>  	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
> @@ -1429,7 +1429,7 @@ static void pxa3xx_nand_select_chip(struct mtd_info *mtd, int chip)
>  
>  static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
>  	struct pxa3xx_nand_info *info = host->info_data;
>  
> @@ -1480,7 +1480,7 @@ static void pxa3xx_nand_config_tail(struct pxa3xx_nand_info *info)
>  {
>  	struct pxa3xx_nand_host *host = info->host[info->cs];
>  	struct nand_chip *chip = &host->chip;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  
>  	info->reg_ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
>  	info->reg_ndcr |= (chip->page_shift == 6) ? NDCR_PG_PER_BLK : 0;
> @@ -1569,7 +1569,7 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info,
>  			struct mtd_info *mtd,
>  			int strength, int ecc_stepsize, int page_size)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
>  
>  	if (strength == 1 && ecc_stepsize == 512 && page_size == 2048) {
> @@ -1651,7 +1651,7 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info,
>  
>  static int pxa3xx_nand_scan(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
>  	struct pxa3xx_nand_info *info = host->info_data;
>  	struct platform_device *pdev = info->pdev;
> @@ -1792,7 +1792,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
>  		host = (void *)&info[1] + sizeof(*host) * cs;
>  		chip = &host->chip;
>  		nand_set_controller_data(chip, host);
> -		mtd = nand_to_mtd(chip);
> +		mtd = nandchip_to_mtd(chip);
>  		info->host[cs] = host;
>  		host->cs = cs;
>  		host->info_data = info;
> @@ -1912,7 +1912,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
>  	clk_disable_unprepare(info->clk);
>  
>  	for (cs = 0; cs < pdata->num_cs; cs++)
> -		nand_release(nand_to_mtd(&info->host[cs]->chip));
> +		nand_release(nandchip_to_mtd(&info->host[cs]->chip));
>  	return 0;
>  }
>  
> @@ -1972,7 +1972,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
>  	info = platform_get_drvdata(pdev);
>  	probe_success = 0;
>  	for (cs = 0; cs < pdata->num_cs; cs++) {
> -		struct mtd_info *mtd = nand_to_mtd(&info->host[cs]->chip);
> +		struct mtd_info *mtd = nandchip_to_mtd(&info->host[cs]->chip);
>  
>  		/*
>  		 * The mtd name matches the one used in 'mtdparts' kernel
> diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c
> index a77c66f..3b2d16b 100644
> --- a/drivers/mtd/nand/raw/qcom_nandc.c
> +++ b/drivers/mtd/nand/raw/qcom_nandc.c
> @@ -873,7 +873,7 @@ static void post_command(struct qcom_nand_host *host, int command)
>  static void qcom_nandc_command(struct mtd_info *mtd, unsigned int command,
>  			       int column, int page_addr)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct qcom_nand_host *host = to_qcom_nand_host(chip);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
>  	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
> @@ -1008,7 +1008,7 @@ static int parse_read_errors(struct qcom_nand_host *host, u8 *data_buf,
>  {
>  	struct nand_chip *chip = &host->chip;
>  	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
>  	unsigned int max_bitflips = 0;
>  	struct read_stats *buf;
> @@ -1481,7 +1481,7 @@ static int qcom_nandc_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
>  
>  static int qcom_nandc_block_bad(struct mtd_info *mtd, loff_t ofs)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct qcom_nand_host *host = to_qcom_nand_host(chip);
>  	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
> @@ -1521,7 +1521,7 @@ static int qcom_nandc_block_bad(struct mtd_info *mtd, loff_t ofs)
>  
>  static int qcom_nandc_block_markbad(struct mtd_info *mtd, loff_t ofs)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct qcom_nand_host *host = to_qcom_nand_host(chip);
>  	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
> @@ -1571,7 +1571,7 @@ static int qcom_nandc_block_markbad(struct mtd_info *mtd, loff_t ofs)
>   */
>  static uint8_t qcom_nandc_read_byte(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct qcom_nand_host *host = to_qcom_nand_host(chip);
>  	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
>  	u8 *buf = nandc->data_buffer;
> @@ -1593,7 +1593,7 @@ static uint8_t qcom_nandc_read_byte(struct mtd_info *mtd)
>  
>  static void qcom_nandc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
>  	int real_len = min_t(size_t, len, nandc->buf_count - nandc->buf_start);
>  
> @@ -1604,7 +1604,7 @@ static void qcom_nandc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  static void qcom_nandc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
>  				 int len)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
>  	int real_len = min_t(size_t, len, nandc->buf_count - nandc->buf_start);
>  
> @@ -1616,7 +1616,7 @@ static void qcom_nandc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
>  /* we support only one external chip for now */
>  static void qcom_nandc_select_chip(struct mtd_info *mtd, int chipnr)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
>  
>  	if (chipnr <= 0)
> @@ -1713,7 +1713,7 @@ static void qcom_nandc_select_chip(struct mtd_info *mtd, int chipnr)
>  static int qcom_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
>  				   struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct qcom_nand_host *host = to_qcom_nand_host(chip);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
>  
> @@ -1735,7 +1735,7 @@ static int qcom_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
>  static int qcom_nand_ooblayout_free(struct mtd_info *mtd, int section,
>  				     struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct qcom_nand_host *host = to_qcom_nand_host(chip);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
>  
> @@ -1756,7 +1756,7 @@ static int qcom_nand_ooblayout_free(struct mtd_info *mtd, int section,
>  static int qcom_nand_host_setup(struct qcom_nand_host *host)
>  {
>  	struct nand_chip *chip = &host->chip;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
>  	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
>  	int cwperpage, bad_block_byte;
> @@ -1988,7 +1988,7 @@ static int qcom_nand_host_init(struct qcom_nand_controller *nandc,
>  			       struct device_node *dn)
>  {
>  	struct nand_chip *chip = &host->chip;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	struct device *dev = nandc->dev;
>  	int ret;
>  
> @@ -2152,7 +2152,7 @@ static int qcom_nandc_probe(struct platform_device *pdev)
>  
>  err_cs_init:
>  	list_for_each_entry(host, &nandc->host_list, node)
> -		nand_release(nand_to_mtd(&host->chip));
> +		nand_release(nandchip_to_mtd(&host->chip));
>  err_setup:
>  	clk_disable_unprepare(nandc->aon_clk);
>  err_aon_clk:
> @@ -2169,7 +2169,7 @@ static int qcom_nandc_remove(struct platform_device *pdev)
>  	struct qcom_nand_host *host;
>  
>  	list_for_each_entry(host, &nandc->host_list, node)
> -		nand_release(nand_to_mtd(&host->chip));
> +		nand_release(nandchip_to_mtd(&host->chip));
>  
>  	qcom_nandc_unalloc(nandc);
>  
> diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c
> index fc9287a..6ac7b95 100644
> --- a/drivers/mtd/nand/raw/r852.c
> +++ b/drivers/mtd/nand/raw/r852.c
> @@ -64,7 +64,7 @@ static inline void r852_write_reg_dword(struct r852_device *dev,
>  /* returns pointer to our private structure */
>  static inline struct r852_device *r852_get_dev(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	return nand_get_controller_data(chip);
>  }
>  
> @@ -634,7 +634,7 @@ static void r852_update_media_status(struct r852_device *dev)
>   */
>  static int r852_register_nand_device(struct r852_device *dev)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(dev->chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(dev->chip);
>  
>  	WARN_ON(dev->card_registred);
>  
> @@ -669,7 +669,7 @@ static int r852_register_nand_device(struct r852_device *dev)
>  
>  static void r852_unregister_nand_device(struct r852_device *dev)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(dev->chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(dev->chip);
>  
>  	if (!dev->card_registred)
>  		return;
> @@ -1025,7 +1025,7 @@ static int r852_suspend(struct device *device)
>  static int r852_resume(struct device *device)
>  {
>  	struct r852_device *dev = pci_get_drvdata(to_pci_dev(device));
> -	struct mtd_info *mtd = nand_to_mtd(dev->chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(dev->chip);
>  
>  	r852_disable_irqs(dev);
>  	r852_card_update_present(dev);
> diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c
> index 0b2314b..d6918b0 100644
> --- a/drivers/mtd/nand/raw/s3c2410.c
> +++ b/drivers/mtd/nand/raw/s3c2410.c
> @@ -207,7 +207,7 @@ struct s3c24XX_nand_devtype_data {
>  
>  static struct s3c2410_nand_mtd *s3c2410_nand_mtd_toours(struct mtd_info *mtd)
>  {
> -	return container_of(mtd_to_nand(mtd), struct s3c2410_nand_mtd,
> +	return container_of(mtd_to_nandchip(mtd), struct s3c2410_nand_mtd,
>  			    chip);
>  }
>  
> @@ -422,7 +422,7 @@ static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
>  {
>  	struct s3c2410_nand_info *info;
>  	struct s3c2410_nand_mtd *nmtd;
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	unsigned long cur;
>  
>  	nmtd = nand_get_controller_data(this);
> @@ -673,7 +673,7 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
>  
>  static void s3c2410_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	readsb(this->IO_ADDR_R, buf, len);
>  }
>  
> @@ -695,7 +695,7 @@ static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
>  static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf,
>  				   int len)
>  {
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	writesb(this->IO_ADDR_W, buf, len);
>  }
>  
> @@ -784,7 +784,7 @@ static int s3c24xx_nand_remove(struct platform_device *pdev)
>  
>  		for (mtdno = 0; mtdno < info->mtd_count; mtdno++, ptr++) {
>  			pr_debug("releasing mtd %d (%p)\n", mtdno, ptr);
> -			nand_release(nand_to_mtd(&ptr->chip));
> +			nand_release(nandchip_to_mtd(&ptr->chip));
>  		}
>  	}
>  
> @@ -801,7 +801,7 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
>  				      struct s3c2410_nand_set *set)
>  {
>  	if (set) {
> -		struct mtd_info *mtdinfo = nand_to_mtd(&mtd->chip);
> +		struct mtd_info *mtdinfo = nandchip_to_mtd(&mtd->chip);
>  
>  		mtdinfo->name = set->name;
>  
> @@ -984,7 +984,7 @@ static int s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
>  		} else {
>  			chip->ecc.size	    = 512;
>  			chip->ecc.bytes	    = 3;
> -			mtd_set_ooblayout(nand_to_mtd(chip),
> +			mtd_set_ooblayout(nandchip_to_mtd(chip),
>  					  &s3c2410_ooblayout_ops);
>  		}
>  
> @@ -1157,7 +1157,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
>  	nmtd = info->mtds;
>  
>  	for (setno = 0; setno < nr_sets; setno++, nmtd++) {
> -		struct mtd_info *mtd = nand_to_mtd(&nmtd->chip);
> +		struct mtd_info *mtd = nandchip_to_mtd(&nmtd->chip);
>  
>  		pr_debug("initialising set %d (%p, info %p)\n",
>  			 setno, nmtd, info);
> diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c
> index 492705f..1525f15 100644
> --- a/drivers/mtd/nand/raw/sh_flctl.c
> +++ b/drivers/mtd/nand/raw/sh_flctl.c
> @@ -45,7 +45,7 @@
>  static int flctl_4secc_ooblayout_sp_ecc(struct mtd_info *mtd, int section,
>  					struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (section)
>  		return -ERANGE;
> @@ -76,7 +76,7 @@ static int flctl_4secc_ooblayout_sp_free(struct mtd_info *mtd, int section,
>  static int flctl_4secc_ooblayout_lp_ecc(struct mtd_info *mtd, int section,
>  					struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (section >= chip->ecc.steps)
>  		return -ERANGE;
> @@ -90,7 +90,7 @@ static int flctl_4secc_ooblayout_lp_ecc(struct mtd_info *mtd, int section,
>  static int flctl_4secc_ooblayout_lp_free(struct mtd_info *mtd, int section,
>  					 struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (section >= chip->ecc.steps)
>  		return -ERANGE;
> @@ -1164,7 +1164,7 @@ static int flctl_probe(struct platform_device *pdev)
>  
>  	platform_set_drvdata(pdev, flctl);
>  	nand = &flctl->chip;
> -	flctl_mtd = nand_to_mtd(nand);
> +	flctl_mtd = nandchip_to_mtd(nand);
>  	nand_set_flash_node(nand, pdev->dev.of_node);
>  	flctl_mtd->dev.parent = &pdev->dev;
>  	flctl->pdev = pdev;
> @@ -1229,7 +1229,7 @@ static int flctl_remove(struct platform_device *pdev)
>  	struct sh_flctl *flctl = platform_get_drvdata(pdev);
>  
>  	flctl_release_dma(flctl);
> -	nand_release(nand_to_mtd(&flctl->chip));
> +	nand_release(nandchip_to_mtd(&flctl->chip));
>  	pm_runtime_disable(&pdev->dev);
>  
>  	return 0;
> diff --git a/drivers/mtd/nand/raw/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c
> index 737efe8..38c7fb3 100644
> --- a/drivers/mtd/nand/raw/sharpsl.c
> +++ b/drivers/mtd/nand/raw/sharpsl.c
> @@ -36,7 +36,7 @@ struct sharpsl_nand {
>  
>  static inline struct sharpsl_nand *mtd_to_sharpsl(struct mtd_info *mtd)
>  {
> -	return container_of(mtd_to_nand(mtd), struct sharpsl_nand, chip);
> +	return container_of(mtd_to_nandchip(mtd), struct sharpsl_nand, chip);
>  }
>  
>  /* register offset */
> @@ -68,7 +68,7 @@ static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd,
>  				   unsigned int ctrl)
>  {
>  	struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd);
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (ctrl & NAND_CTRL_CHANGE) {
>  		unsigned char bits = ctrl & 0x07;
> @@ -146,7 +146,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
>  	this = (struct nand_chip *)(&sharpsl->chip);
>  
>  	/* Link the private data with the MTD structure */
> -	mtd = nand_to_mtd(this);
> +	mtd = nandchip_to_mtd(this);
>  	mtd->dev.parent = &pdev->dev;
>  	mtd_set_ooblayout(mtd, data->ecc_layout);
>  
> @@ -210,7 +210,7 @@ static int sharpsl_nand_remove(struct platform_device *pdev)
>  	struct sharpsl_nand *sharpsl = platform_get_drvdata(pdev);
>  
>  	/* Release resources, unregister device */
> -	nand_release(nand_to_mtd(&sharpsl->chip));
> +	nand_release(nandchip_to_mtd(&sharpsl->chip));
>  
>  	iounmap(sharpsl->io);
>  
> diff --git a/drivers/mtd/nand/raw/sm_common.c b/drivers/mtd/nand/raw/sm_common.c
> index c378705..0e7e367 100644
> --- a/drivers/mtd/nand/raw/sm_common.c
> +++ b/drivers/mtd/nand/raw/sm_common.c
> @@ -163,7 +163,7 @@ static int sm_block_markbad(struct mtd_info *mtd, loff_t ofs)
>  
>  int sm_register_device(struct mtd_info *mtd, int smartmedia)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	int ret;
>  
>  	chip->options |= NAND_SKIP_BBTSCAN;
> diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c
> index 575997d..c17a5f3 100644
> --- a/drivers/mtd/nand/raw/socrates_nand.c
> +++ b/drivers/mtd/nand/raw/socrates_nand.c
> @@ -44,7 +44,7 @@ static void socrates_nand_write_buf(struct mtd_info *mtd,
>  		const uint8_t *buf, int len)
>  {
>  	int i;
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct socrates_nand_host *host = nand_get_controller_data(this);
>  
>  	for (i = 0; i < len; i++) {
> @@ -63,7 +63,7 @@ static void socrates_nand_write_buf(struct mtd_info *mtd,
>  static void socrates_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  {
>  	int i;
> -	struct nand_chip *this = mtd_to_nand(mtd);
> +	struct nand_chip *this = mtd_to_nandchip(mtd);
>  	struct socrates_nand_host *host = nand_get_controller_data(this);
>  	uint32_t val;
>  
> @@ -104,7 +104,7 @@ static uint16_t socrates_nand_read_word(struct mtd_info *mtd)
>  static void socrates_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
>  		unsigned int ctrl)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct socrates_nand_host *host = nand_get_controller_data(nand_chip);
>  	uint32_t val;
>  
> @@ -129,7 +129,7 @@ static void socrates_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
>   */
>  static int socrates_nand_device_ready(struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand_chip = mtd_to_nand(mtd);
> +	struct nand_chip *nand_chip = mtd_to_nandchip(mtd);
>  	struct socrates_nand_host *host = nand_get_controller_data(nand_chip);
>  
>  	if (in_be32(host->io_base) & FPGA_NAND_BUSY)
> @@ -159,7 +159,7 @@ static int socrates_nand_probe(struct platform_device *ofdev)
>  	}
>  
>  	nand_chip = &host->nand_chip;
> -	mtd = nand_to_mtd(nand_chip);
> +	mtd = nandchip_to_mtd(nand_chip);
>  	host->dev = &ofdev->dev;
>  
>  	/* link the private data structures */
> @@ -208,7 +208,7 @@ static int socrates_nand_probe(struct platform_device *ofdev)
>  static int socrates_nand_remove(struct platform_device *ofdev)
>  {
>  	struct socrates_nand_host *host = dev_get_drvdata(&ofdev->dev);
> -	struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(&host->nand_chip);
>  
>  	nand_release(mtd);
>  
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
> index 214a9c7..971978e 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand.c
> @@ -379,7 +379,7 @@ static int sunxi_nfc_dma_op_prepare(struct mtd_info *mtd, const void *buf,
>  				    enum dma_data_direction ddir,
>  				    struct scatterlist *sg)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
>  	struct dma_async_tx_descriptor *dmad;
>  	enum dma_transfer_direction tdir;
> @@ -427,7 +427,7 @@ static void sunxi_nfc_dma_op_cleanup(struct mtd_info *mtd,
>  				     enum dma_data_direction ddir,
>  				     struct scatterlist *sg)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
>  
>  	dma_unmap_sg(nfc->dev, sg, 1, ddir);
> @@ -437,7 +437,7 @@ static void sunxi_nfc_dma_op_cleanup(struct mtd_info *mtd,
>  
>  static int sunxi_nfc_dev_ready(struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
>  	struct sunxi_nand_rb *rb;
> @@ -468,7 +468,7 @@ static int sunxi_nfc_dev_ready(struct mtd_info *mtd)
>  
>  static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
>  	struct sunxi_nand_chip_sel *sel;
> @@ -513,7 +513,7 @@ static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip)
>  
>  static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
>  	int ret;
> @@ -552,7 +552,7 @@ static void sunxi_nfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  static void sunxi_nfc_write_buf(struct mtd_info *mtd, const uint8_t *buf,
>  				int len)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
>  	int ret;
> @@ -599,7 +599,7 @@ static uint8_t sunxi_nfc_read_byte(struct mtd_info *mtd)
>  static void sunxi_nfc_cmd_ctrl(struct mtd_info *mtd, int dat,
>  			       unsigned int ctrl)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
>  	int ret;
> @@ -756,7 +756,7 @@ static u16 sunxi_nfc_randomizer_state(struct mtd_info *mtd, int page, bool ecc)
>  static void sunxi_nfc_randomizer_config(struct mtd_info *mtd,
>  					int page, bool ecc)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
>  	u32 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
>  	u16 state;
> @@ -772,7 +772,7 @@ static void sunxi_nfc_randomizer_config(struct mtd_info *mtd,
>  
>  static void sunxi_nfc_randomizer_enable(struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
>  
>  	if (!(nand->options & NAND_NEED_SCRAMBLING))
> @@ -784,7 +784,7 @@ static void sunxi_nfc_randomizer_enable(struct mtd_info *mtd)
>  
>  static void sunxi_nfc_randomizer_disable(struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
>  
>  	if (!(nand->options & NAND_NEED_SCRAMBLING))
> @@ -823,7 +823,7 @@ static void sunxi_nfc_randomizer_read_buf(struct mtd_info *mtd, uint8_t *buf,
>  
>  static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
>  	struct sunxi_nand_hw_ecc *data = nand->ecc.priv;
>  	u32 ecc_ctl;
> @@ -842,7 +842,7 @@ static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd)
>  
>  static void sunxi_nfc_hw_ecc_disable(struct mtd_info *mtd)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
>  
>  	writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_ECC_EN,
> @@ -865,7 +865,7 @@ static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf)
>  static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct mtd_info *mtd, u8 *oob,
>  						int step, bool bbm, int page)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
>  
>  	sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(step)),
> @@ -880,7 +880,7 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct mtd_info *mtd,
>  						const u8 *oob, int step,
>  						bool bbm, int page)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
>  	u8 user_data[4];
>  
> @@ -909,7 +909,7 @@ static void sunxi_nfc_hw_ecc_update_stats(struct mtd_info *mtd,
>  static int sunxi_nfc_hw_ecc_correct(struct mtd_info *mtd, u8 *data, u8 *oob,
>  				    int step, u32 status, bool *erased)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
>  	struct nand_ecc_ctrl *ecc = &nand->ecc;
>  	u32 tmp;
> @@ -950,7 +950,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
>  				       unsigned int *max_bitflips,
>  				       bool bbm, bool oob_required, int page)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
>  	struct nand_ecc_ctrl *ecc = &nand->ecc;
>  	int raw_mode = 0;
> @@ -1029,7 +1029,7 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info *mtd,
>  					    u8 *oob, int *cur_off,
>  					    bool randomize, int page)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct nand_ecc_ctrl *ecc = &nand->ecc;
>  	int offset = ((ecc->bytes + 4) * ecc->steps);
>  	int len = mtd->oobsize - offset;
> @@ -1055,7 +1055,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf,
>  					    int oob_required, int page,
>  					    int nchunks)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	bool randomized = nand->options & NAND_NEED_SCRAMBLING;
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
>  	struct nand_ecc_ctrl *ecc = &nand->ecc;
> @@ -1181,7 +1181,7 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
>  					int *cur_off, bool bbm,
>  					int page)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
>  	struct nand_ecc_ctrl *ecc = &nand->ecc;
>  	int ret;
> @@ -1219,7 +1219,7 @@ static void sunxi_nfc_hw_ecc_write_extra_oob(struct mtd_info *mtd,
>  					     u8 *oob, int *cur_off,
>  					     int page)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct nand_ecc_ctrl *ecc = &nand->ecc;
>  	int offset = ((ecc->bytes + 4) * ecc->steps);
>  	int len = mtd->oobsize - offset;
> @@ -1410,7 +1410,7 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct mtd_info *mtd,
>  					   int oob_required,
>  					   int page)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
>  	struct nand_ecc_ctrl *ecc = &nand->ecc;
>  	struct scatterlist sg;
> @@ -1596,7 +1596,7 @@ static int sunxi_nfc_setup_data_interface(struct mtd_info *mtd,
>  					const struct nand_data_interface *conf,
>  					bool check_only)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nand_chip *chip = to_sunxi_nand(nand);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(chip->nand.controller);
>  	const struct nand_sdr_timings *timings;
> @@ -1746,7 +1746,7 @@ static int sunxi_nfc_setup_data_interface(struct mtd_info *mtd,
>  static int sunxi_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
>  				    struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct nand_ecc_ctrl *ecc = &nand->ecc;
>  
>  	if (section >= ecc->steps)
> @@ -1761,7 +1761,7 @@ static int sunxi_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
>  static int sunxi_nand_ooblayout_free(struct mtd_info *mtd, int section,
>  				     struct mtd_oob_region *oobregion)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct nand_ecc_ctrl *ecc = &nand->ecc;
>  
>  	if (section > ecc->steps)
> @@ -1799,7 +1799,7 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
>  					      struct device_node *np)
>  {
>  	static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
>  	struct sunxi_nand_hw_ecc *data;
> @@ -1898,7 +1898,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
>  				       struct nand_ecc_ctrl *ecc,
>  				       struct device_node *np)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
>  	int ret;
> @@ -1962,7 +1962,7 @@ static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc)
>  static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc,
>  			       struct device_node *np)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct nand_chip *nand = mtd_to_nandchip(mtd);
>  	int ret;
>  
>  	if (!ecc->size) {
> @@ -2088,7 +2088,7 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
>  	nand->read_byte = sunxi_nfc_read_byte;
>  	nand->setup_data_interface = sunxi_nfc_setup_data_interface;
>  
> -	mtd = nand_to_mtd(nand);
> +	mtd = nandchip_to_mtd(nand);
>  	mtd->dev.parent = dev;
>  
>  	ret = nand_scan_ident(mtd, nsels, NULL);
> @@ -2157,7 +2157,7 @@ static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc)
>  	while (!list_empty(&nfc->chips)) {
>  		chip = list_first_entry(&nfc->chips, struct sunxi_nand_chip,
>  					node);
> -		nand_release(nand_to_mtd(&chip->nand));
> +		nand_release(nandchip_to_mtd(&chip->nand));
>  		sunxi_nand_ecc_cleanup(&chip->nand.ecc);
>  		list_del(&chip->node);
>  	}
> diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c
> index 906fe0f..8097e88 100644
> --- a/drivers/mtd/nand/raw/tango_nand.c
> +++ b/drivers/mtd/nand/raw/tango_nand.c
> @@ -118,7 +118,7 @@ struct tango_chip {
>  
>  static void tango_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
>  {
> -	struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd));
> +	struct tango_chip *tchip = to_tango_chip(mtd_to_nandchip(mtd));
>  
>  	if (ctrl & NAND_CLE)
>  		writeb_relaxed(dat, tchip->base + PBUS_CMD);
> @@ -129,7 +129,7 @@ static void tango_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
>  
>  static int tango_dev_ready(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct tango_nfc *nfc = to_tango_nfc(chip->controller);
>  
>  	return readl_relaxed(nfc->pbus_base + PBUS_CS_CTRL) & PBUS_IORDY;
> @@ -137,28 +137,28 @@ static int tango_dev_ready(struct mtd_info *mtd)
>  
>  static u8 tango_read_byte(struct mtd_info *mtd)
>  {
> -	struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd));
> +	struct tango_chip *tchip = to_tango_chip(mtd_to_nandchip(mtd));
>  
>  	return readb_relaxed(tchip->base + PBUS_DATA);
>  }
>  
>  static void tango_read_buf(struct mtd_info *mtd, u8 *buf, int len)
>  {
> -	struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd));
> +	struct tango_chip *tchip = to_tango_chip(mtd_to_nandchip(mtd));
>  
>  	ioread8_rep(tchip->base + PBUS_DATA, buf, len);
>  }
>  
>  static void tango_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
>  {
> -	struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd));
> +	struct tango_chip *tchip = to_tango_chip(mtd_to_nandchip(mtd));
>  
>  	iowrite8_rep(tchip->base + PBUS_DATA, buf, len);
>  }
>  
>  static void tango_select_chip(struct mtd_info *mtd, int idx)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct tango_nfc *nfc = to_tango_nfc(chip->controller);
>  	struct tango_chip *tchip = to_tango_chip(chip);
>  
> @@ -179,7 +179,7 @@ static void tango_select_chip(struct mtd_info *mtd, int idx)
>   */
>  static int check_erased_page(struct nand_chip *chip, u8 *buf)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	u8 *meta = chip->oob_poi + BBM_SIZE;
>  	u8 *ecc = chip->oob_poi + BBM_SIZE + METADATA_SIZE;
>  	const int ecc_size = chip->ecc.bytes;
> @@ -311,7 +311,7 @@ static int tango_write_page(struct mtd_info *mtd, struct nand_chip *chip,
>  
>  static void aux_read(struct nand_chip *chip, u8 **buf, int len, int *pos)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  
>  	*pos += len;
>  
> @@ -326,7 +326,7 @@ static void aux_read(struct nand_chip *chip, u8 **buf, int len, int *pos)
>  
>  static void aux_write(struct nand_chip *chip, const u8 **buf, int len, int *pos)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  
>  	*pos += len;
>  
> @@ -360,7 +360,7 @@ static void aux_write(struct nand_chip *chip, const u8 **buf, int len, int *pos)
>   */
>  static void raw_read(struct nand_chip *chip, u8 *buf, u8 *oob)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	u8 *oob_orig = oob;
>  	const int page_size = mtd->writesize;
>  	const int ecc_size = chip->ecc.bytes;
> @@ -387,7 +387,7 @@ static void raw_read(struct nand_chip *chip, u8 *buf, u8 *oob)
>  
>  static void raw_write(struct nand_chip *chip, const u8 *buf, const u8 *oob)
>  {
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
>  	const u8 *oob_orig = oob;
>  	const int page_size = mtd->writesize;
>  	const int ecc_size = chip->ecc.bytes;
> @@ -449,7 +449,7 @@ static int tango_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
>  
>  static int oob_ecc(struct mtd_info *mtd, int idx, struct mtd_oob_region *res)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
>  
>  	if (idx >= ecc->steps)
> @@ -481,7 +481,7 @@ static int tango_set_timings(struct mtd_info *mtd,
>  			     bool check_only)
>  {
>  	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(conf);
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct tango_nfc *nfc = to_tango_nfc(chip->controller);
>  	struct tango_chip *tchip = to_tango_chip(chip);
>  	u32 Trdy, Textw, Twc, Twpw, Tacc, Thold, Trpw, Textr;
> @@ -539,7 +539,7 @@ static int chip_init(struct device *dev, struct device_node *np)
>  
>  	chip = &tchip->nand_chip;
>  	ecc = &chip->ecc;
> -	mtd = nand_to_mtd(chip);
> +	mtd = nandchip_to_mtd(chip);
>  
>  	chip->read_byte = tango_read_byte;
>  	chip->write_buf = tango_write_buf;
> @@ -601,7 +601,7 @@ static int tango_nand_remove(struct platform_device *pdev)
>  
>  	for (cs = 0; cs < MAX_CS; ++cs) {
>  		if (nfc->chips[cs])
> -			nand_release(nand_to_mtd(&nfc->chips[cs]->nand_chip));
> +			nand_release(nandchip_to_mtd(&nfc->chips[cs]->nand_chip));
>  	}
>  
>  	return 0;
> diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c
> index c9dd682..5b1bb65 100644
> --- a/drivers/mtd/nand/raw/tmio_nand.c
> +++ b/drivers/mtd/nand/raw/tmio_nand.c
> @@ -120,7 +120,7 @@ struct tmio_nand {
>  
>  static inline struct tmio_nand *mtd_to_tmio(struct mtd_info *mtd)
>  {
> -	return container_of(mtd_to_nand(mtd), struct tmio_nand, chip);
> +	return container_of(mtd_to_nandchip(mtd), struct tmio_nand, chip);
>  }
>  
>  
> @@ -130,7 +130,7 @@ static void tmio_nand_hwcontrol(struct mtd_info *mtd, int cmd,
>  				   unsigned int ctrl)
>  {
>  	struct tmio_nand *tmio = mtd_to_tmio(mtd);
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  
>  	if (ctrl & NAND_CTRL_CHANGE) {
>  		u8 mode;
> @@ -381,7 +381,7 @@ static int tmio_probe(struct platform_device *dev)
>  
>  	platform_set_drvdata(dev, tmio);
>  	nand_chip = &tmio->chip;
> -	mtd = nand_to_mtd(nand_chip);
> +	mtd = nandchip_to_mtd(nand_chip);
>  	mtd->name = "tmio-nand";
>  	mtd->dev.parent = &dev->dev;
>  
> @@ -457,7 +457,7 @@ static int tmio_remove(struct platform_device *dev)
>  {
>  	struct tmio_nand *tmio = platform_get_drvdata(dev);
>  
> -	nand_release(nand_to_mtd(&tmio->chip));
> +	nand_release(nandchip_to_mtd(&tmio->chip));
>  	tmio_hw_stop(dev, tmio);
>  	return 0;
>  }
> diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c
> index b567d21..edb7cd0 100644
> --- a/drivers/mtd/nand/raw/txx9ndfmc.c
> +++ b/drivers/mtd/nand/raw/txx9ndfmc.c
> @@ -78,7 +78,7 @@ struct txx9ndfmc_drvdata {
>  
>  static struct platform_device *mtd_to_platdev(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct txx9ndfmc_priv *txx9_priv = nand_get_controller_data(chip);
>  	return txx9_priv->dev;
>  }
> @@ -134,7 +134,7 @@ static void txx9ndfmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  static void txx9ndfmc_cmd_ctrl(struct mtd_info *mtd, int cmd,
>  			       unsigned int ctrl)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct txx9ndfmc_priv *txx9_priv = nand_get_controller_data(chip);
>  	struct platform_device *dev = txx9_priv->dev;
>  	struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);
> @@ -174,7 +174,7 @@ static int txx9ndfmc_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
>  				   uint8_t *ecc_code)
>  {
>  	struct platform_device *dev = mtd_to_platdev(mtd);
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	int eccbytes;
>  	u32 mcr = txx9ndfmc_read(dev, TXX9_NDFMCR);
>  
> @@ -194,7 +194,7 @@ static int txx9ndfmc_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
>  static int txx9ndfmc_correct_data(struct mtd_info *mtd, unsigned char *buf,
>  		unsigned char *read_ecc, unsigned char *calc_ecc)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	int eccsize;
>  	int corrected = 0;
>  	int stat;
> @@ -256,7 +256,7 @@ static void txx9ndfmc_initialize(struct platform_device *dev)
>  
>  static int txx9ndfmc_nand_scan(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	int ret;
>  
>  	ret = nand_scan_ident(mtd, 1, NULL);
> @@ -320,7 +320,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
>  		if (!txx9_priv)
>  			continue;
>  		chip = &txx9_priv->chip;
> -		mtd = nand_to_mtd(chip);
> +		mtd = nandchip_to_mtd(chip);
>  		mtd->dev.parent = &dev->dev;
>  
>  		chip->read_byte = txx9ndfmc_read_byte;
> @@ -387,7 +387,7 @@ static int __exit txx9ndfmc_remove(struct platform_device *dev)
>  
>  		if (!mtd)
>  			continue;
> -		chip = mtd_to_nand(mtd);
> +		chip = mtd_to_nandchip(mtd);
>  		txx9_priv = nand_get_controller_data(chip);
>  
>  		nand_release(mtd);
> diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c
> index 1bc4b08..0baf986 100644
> --- a/drivers/mtd/nand/raw/vf610_nfc.c
> +++ b/drivers/mtd/nand/raw/vf610_nfc.c
> @@ -171,7 +171,7 @@ struct vf610_nfc {
>  
>  static inline struct vf610_nfc *mtd_to_nfc(struct mtd_info *mtd)
>  {
> -	return container_of(mtd_to_nand(mtd), struct vf610_nfc, chip);
> +	return container_of(mtd_to_nandchip(mtd), struct vf610_nfc, chip);
>  }
>  
>  static inline u32 vf610_nfc_read(struct vf610_nfc *nfc, uint reg)
> @@ -648,7 +648,7 @@ static int vf610_nfc_probe(struct platform_device *pdev)
>  
>  	nfc->dev = &pdev->dev;
>  	chip = &nfc->chip;
> -	mtd = nand_to_mtd(chip);
> +	mtd = nandchip_to_mtd(chip);
>  
>  	mtd->owner = THIS_MODULE;
>  	mtd->dev.parent = nfc->dev;
> diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c
> index 9926b4e..c3d4b0f 100644
> --- a/drivers/mtd/nand/raw/xway_nand.c
> +++ b/drivers/mtd/nand/raw/xway_nand.c
> @@ -71,7 +71,7 @@ struct xway_nand_data {
>  
>  static u8 xway_readb(struct mtd_info *mtd, int op)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct xway_nand_data *data = nand_get_controller_data(chip);
>  
>  	return readb(data->nandaddr + op);
> @@ -79,7 +79,7 @@ static u8 xway_readb(struct mtd_info *mtd, int op)
>  
>  static void xway_writeb(struct mtd_info *mtd, int op, u8 value)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct xway_nand_data *data = nand_get_controller_data(chip);
>  
>  	writeb(value, data->nandaddr + op);
> @@ -87,7 +87,7 @@ static void xway_writeb(struct mtd_info *mtd, int op, u8 value)
>  
>  static void xway_select_chip(struct mtd_info *mtd, int select)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct xway_nand_data *data = nand_get_controller_data(chip);
>  
>  	switch (select) {
> @@ -170,7 +170,7 @@ static int xway_nand_probe(struct platform_device *pdev)
>  		return PTR_ERR(data->nandaddr);
>  
>  	nand_set_flash_node(&data->chip, pdev->dev.of_node);
> -	mtd = nand_to_mtd(&data->chip);
> +	mtd = nandchip_to_mtd(&data->chip);
>  	mtd->dev.parent = &pdev->dev;
>  
>  	data->chip.cmd_ctrl = xway_cmd_ctrl;
> @@ -223,7 +223,7 @@ static int xway_nand_remove(struct platform_device *pdev)
>  {
>  	struct xway_nand_data *data = platform_get_drvdata(pdev);
>  
> -	nand_release(nand_to_mtd(&data->chip));
> +	nand_release(nandchip_to_mtd(&data->chip));
>  
>  	return 0;
>  }
> diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c
> index f7f6edf..df5671a 100644
> --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c
> +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c
> @@ -31,7 +31,7 @@
>  
>  static inline struct spinand_state *mtd_to_state(struct mtd_info *mtd)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct spinand_info *info = nand_get_controller_data(chip);
>  	struct spinand_state *state = info->priv;
>  
> @@ -756,7 +756,7 @@ static void spinand_reset(struct spi_device *spi_nand)
>  static void spinand_cmdfunc(struct mtd_info *mtd, unsigned int command,
>  			    int column, int page)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_chip *chip = mtd_to_nandchip(mtd);
>  	struct spinand_info *info = nand_get_controller_data(chip);
>  	struct spinand_state *state = info->priv;
>  
> @@ -916,7 +916,7 @@ static int spinand_probe(struct spi_device *spi_nand)
>  	chip->options	|= NAND_CACHEPRG;
>  	chip->select_chip = spinand_select_chip;
>  
> -	mtd = nand_to_mtd(chip);
> +	mtd = nandchip_to_mtd(chip);
>  
>  	dev_set_drvdata(&spi_nand->dev, mtd);
>  
> diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> index fc6ed95..aa43ec4 100644
> --- a/include/linux/mtd/rawnand.h
> +++ b/include/linux/mtd/rawnand.h
> @@ -938,12 +938,12 @@ static inline struct device_node *nand_get_flash_node(struct nand_chip *chip)
>  	return mtd_get_of_node(&chip->mtd);
>  }
>  
> -static inline struct nand_chip *mtd_to_nand(struct mtd_info *mtd)
> +static inline struct nand_chip *mtd_to_nandchip(struct mtd_info *mtd)
>  {
>  	return container_of(mtd, struct nand_chip, mtd);
>  }
>  
> -static inline struct mtd_info *nand_to_mtd(struct nand_chip *chip)
> +static inline struct mtd_info *nandchip_to_mtd(struct nand_chip *chip)
>  {
>  	return &chip->mtd;
>  }
> diff --git a/include/linux/mtd/sh_flctl.h b/include/linux/mtd/sh_flctl.h
> index c759d40..0c1a4a9 100644
> --- a/include/linux/mtd/sh_flctl.h
> +++ b/include/linux/mtd/sh_flctl.h
> @@ -186,7 +186,7 @@ struct sh_flctl_platform_data {
>  
>  static inline struct sh_flctl *mtd_to_flctl(struct mtd_info *mtdinfo)
>  {
> -	return container_of(mtd_to_nand(mtdinfo), struct sh_flctl, chip);
> +	return container_of(mtd_to_nandchip(mtdinfo), struct sh_flctl, chip);
>  }
>  
>  #endif	/* __SH_FLCTL_H__ */

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-05-24  7:06 [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Peter Pan
                   ` (14 preceding siblings ...)
  2017-05-24  7:07 ` [PATCH v6 15/15] MAINTAINERS: Add SPI NAND entry Peter Pan
@ 2017-05-29 20:59 ` Boris Brezillon
  2017-12-04 13:32   ` Frieder Schrempf
  15 siblings, 1 reply; 65+ messages in thread
From: Boris Brezillon @ 2017-05-29 20:59 UTC (permalink / raw)
  To: Peter Pan, arnaud.mouiche
  Cc: richard, computersforpeace, thomas.petazzoni, marex,
	cyrille.pitchen, linux-mtd, peterpansjtu, linshunquan1

Hi Peter,

On Wed, 24 May 2017 15:06:56 +0800
Peter Pan <peterpandong@micron.com> wrote:

> First of all, thank Boris and Marek for your priceless comments
> on v5 and thank everyone reviewed and tested on my previous series.
> I can never be here without your help. This series comes to v6
> and it becomes much better with your help.
> 
> SPI NAND is a new NAND family device with SPI protocol as
> its interface. And its command set is totally different
> with parallel NAND.
> 
> Our first attempt to SPI NAND was more than 2 years ago[1].
> At that time, I didn't make BBT shareable and there were
> too many duplicate code with parallel NAND, so that serie
> stoped. But the discussion never stops. Now Boris has a plan
> to make a generic NAND framework which can be shared with
> both parallel and SPI NAND. Now the first step of the
> new generic NAND framework is finished. And it is waiting
> for a user. After discussion with Boris. We both think it's
> time to rebuild SPI NAND framework based on the new NAND
> framework and send out for reviewing.
> 
> This series includes two part. The first part (patch 1 to 9)
> is a new generic NAND framework from Boris Brezillon, which
> is from Biris's nand/generic branch[2]. The second part
> (patch 10 to 15) introductes a SPI NAND framework based on
> the new generic NAND framework.
> 
> This series only supports basic SPI NAND features and uses
> generic spi controller for data transfer. ECC support is removed
> since it's not in a good structure and more important, it should
> be shared between different NAND devices, which means it should
> be in new NAND core. Support different types of ECC and advanced
> SPI NAND features is the next step.
> 
> This series is based on nand/next branch and is tested on
> Xilinx Zedboard with Micron MT29F2G01ABAGDSF SPI NAND chip.

As you can see, I started to review this v6, but I don't expect you to
send a new version (at least not immediately).

Here is the plan: I'll finish reviewing the series, and while I'm
reviewing I'll try to address my own comments. Once the review/changes
are done, I'll push a nand/spi branch to the github repo [1] and ask
you and Arnaud to review/test the whole thing. If you're happy with
my changes (it should only be minor changes to your
initial implementation) I'll ask you to send a v7. I'll then wait for
4.13-rc1 to be out and apply everything to my nand/next branch (I
expect a few conflicting changes in the nand/mtd area caused by the
migration to the new doc format, that's why I'd like to wait one more
cycle).

If everything goes well, we should be good for 4.14, and the patches
will have spent enough time in linux-next to discover obvious bugs.

Let me know if you have a problem with this approach.

Thanks,

Boris

> 
> 
> v6 changes:
> - includes generic NAND framework patches in series
> - rebase on nand/next (commit 6076fd1e9d879521f7082a5e22185b71e480b777)
> - remove on-die ECC support
> - remove devm_free() since everything allocated by devm_kmalloc() will be
>   automatically freed when device is released
> - add comment header for structs in spinand.h
> - remove spinand_register()/unregister(), call spinand_detect() in
>   spinand_init() and only expose spinand_init()/cleanup()
> - add nand_release_bbt() in bbt.c and use it in nand_cleanup() and
>   spinand_cleanup()
> - use BIT(n) instead (1 << n) in macro of spinand.h
> - rename spinand_alloc() to devm_spinand_alloc()
> - name lables in better way
> - fix some typos
> - add empty lines between code blocks
> 
> v5 changes:
> - rebase patch on nand/next with Boris's generic NAND framework patches[3]
> - replace pr_xxx() with dev_xxx()
> - replace kzalloc()i/kfree() with devm_kzalloc()/devm_kfree()
> - rename spinand_op_init() to spinand_init_op() for consistency
> - remove command opcode in function comments
> - use BIT(n) instead (1 << n) in macro
> - remove manufactures.c and put spinand_manufacturers table in core.c
> - change spinand_write_reg() u8 *buf argument to u8 value,
>   since the length is always 1
> - remove spinand_manufacture->detect() check, since it is always != NULL
> - alloc spinand_ecc_engine struct in vendor.c when using on-die ECC
>   (for hardware ECC, it should be in controllers/*.c)
> - add comment header for struct spinand_op
> - fix timeout bug in spinand_wait(), thanks for Arnaud's debug
> - make spinand_manufacturers const
> - add ecc_engine_ops pointer in struct micron_spinand_info
> - make controller->cap assignment right with SPI_TX/RX_QUAD/DUAL flag
> 
> v4 changes:
> - initialize struct mtd_oob_ops to 0 in bbt.c
> - rename new added helper in nand.h to nand_check_xxxx()
> - add struct mtd_oob_ops consistency check in nand_check_oob_ops()
> - add dataleft in struct nand_page_iter instead of offs
> - remove spinand_manufacturers->ops->detect() check since it is mandatory
> - remove spinand_set_manufacturer_ops() and do the job in
>   spinand_manufacturer_detect()
> - move .priv out of struct spinand_controller
> - add spinand_alloc/free/register/unregister() and make
>   spinand_detect/init() static
> - make BBT be configured by device tree
> - chip->id.data stores raw ID directly
> - refine device info print message after detect success
> - add struct mtd_layout_ops pointer in struct micron_spinand_info
> - remove micron_spinand_init() and do its job in micron_spinand_detect()
> - fix BBT block cannot be erased bug
> 
> v3 changes:
> - rebase patch on 4.11-rc1[2]
> - change read ID method. read 4 bytes ID out then let ->detect() of each
>   manufacutre driver to decode ID and detect the device.
> - make SPI NAND id table private to each manufacutre driver
> - fix coding style to make checkpatch.pl happy
> - update the MAINTAINERS file for spi nand code
> - add nand_size() helper in nand.h
> - use nand_for_each_page() helper in spinand_do_read/write_ops()
> - create helper to check boundaries in generic NAND code and use it
>   in SPI NAND core
> - rename spinand_base.c to core.c
> - manufactures' drivers expose spinand_manufacturer struct instead of
>   spinand_manufacturer_ops struct to keep Manufacture ID macro in
>   manufactures' drivers and rename spinand_ids.c to manufacture.c
> - rename spinand_micron.c to micron.c
> - rename chips/ directory to controllers/
> - rename generic_spi.c to generic-spi.c
> - replace ->build_column_addr() and ->get_dummy() hooks with ->prepare_op() in
>   spinand_manufacturer_ops struct
> - rename __spinand_erase() to spinand_erase()
> - rename spinand_erase() to spinand_erase_skip_bbt()
> - rename spinand_scan_ident() to spinand_detect()
> - rename spinand_scan_tail() to spinand_init()
> - move non detect related code from spinand_detect() to spinand_init()
> - remove spinand_fill_nandd, assign nand->ops in spinand_detect()
> - merge v2 patch 3(bad block support) and patch 4(BBT support)
> - drop getchip parameter, remove spinand_get/remove_device(), take the lock
>   by caller directly
> - fix function comment headers
> - use nand_bbt_is_initialized() helper
> - replace spinand_ecc_engine and spinand_controller object in spinand_device
>   struct with pointer
> - replace struct spinand_manufacturer_ops pointer in spinand_device struct
>   with spinand_manufacturer struct
> 
> v2 changes:
> - replace "spi_nand" with "spinand".
> - rename spi nand related structs for better understanding.
> - introduce spi nand controller, manufacturer and ecc_engine struct.
> - add spi nand manufacturer initialization function refer to Boris's
>   manuf-init branch.
> - remove NAND_SKIP_BBTSCAN from series. Add it later when enabling HW ECC.
> - reorganize series according to Boris's suggestion.
> 
> 
> [1]http://lists.infradead.org/pipermail/linux-mtd/2015-January/057223.html
> [2]https://github.com/bbrezillon/linux-0day/tree/nand/generic
> [3]https://github.com/peterpansjtu/linux/tree/nand/spinand
> 
> 
> Boris Brezillon (8):
>   mtd: nand: Rename nand.h into rawnand.h
>   mtd: nand: move raw NAND related code to the raw/ subdir
>   mtd: nand: add a nand.h file to expose basic NAND stuff
>   mtd: nand: raw: prefix conflicting names with nandcchip instead of
>     nand
>   mtd: nand: raw: create struct rawnand_device
>   mtd: nand: raw: make BBT code more generic
>   mtd: nand: move BBT code to drivers/mtd/nand/
>   mtd: nand: Add the page iterator concept
> 
> Peter Pan (7):
>   mtd: nand: make sure mtd_oob_ops consistent in bbt
>   nand: spi: add basic blocks for infrastructure
>   nand: spi: add basic operations support
>   nand: spi: Add bad block support
>   nand: spi: add Micron spi nand support
>   nand: spi: Add generic SPI controller support
>   MAINTAINERS: Add SPI NAND entry
> 
>  Documentation/DocBook/mtdnand.tmpl                 |   12 +-
>  MAINTAINERS                                        |   29 +-
>  arch/arm/mach-davinci/board-da850-evm.c            |    2 +-
>  arch/arm/mach-davinci/board-dm355-evm.c            |    2 +-
>  arch/arm/mach-davinci/board-dm355-leopard.c        |    2 +-
>  arch/arm/mach-davinci/board-dm365-evm.c            |    2 +-
>  arch/arm/mach-davinci/board-dm644x-evm.c           |    2 +-
>  arch/arm/mach-davinci/board-dm646x-evm.c           |    2 +-
>  arch/arm/mach-davinci/board-sffsdr.c               |    2 +-
>  arch/arm/mach-dove/dove-db-setup.c                 |    2 +-
>  arch/arm/mach-ep93xx/snappercl15.c                 |    6 +-
>  arch/arm/mach-ep93xx/ts72xx.c                      |    6 +-
>  arch/arm/mach-imx/mach-qong.c                      |    4 +-
>  arch/arm/mach-ixp4xx/ixdp425-setup.c               |    4 +-
>  arch/arm/mach-mmp/aspenite.c                       |    2 +-
>  arch/arm/mach-omap1/board-fsample.c                |    2 +-
>  arch/arm/mach-omap1/board-h2.c                     |    2 +-
>  arch/arm/mach-omap1/board-h3.c                     |    2 +-
>  arch/arm/mach-omap1/board-nand.c                   |    4 +-
>  arch/arm/mach-omap1/board-perseus2.c               |    2 +-
>  arch/arm/mach-orion5x/db88f5281-setup.c            |    2 +-
>  arch/arm/mach-orion5x/kurobox_pro-setup.c          |    2 +-
>  arch/arm/mach-orion5x/ts209-setup.c                |    2 +-
>  arch/arm/mach-orion5x/ts78xx-setup.c               |    8 +-
>  arch/arm/mach-pxa/balloon3.c                       |    4 +-
>  arch/arm/mach-pxa/em-x270.c                        |    4 +-
>  arch/arm/mach-pxa/eseries.c                        |    2 +-
>  arch/arm/mach-pxa/palmtx.c                         |    4 +-
>  arch/arm/mach-pxa/tosa.c                           |    2 +-
>  arch/arm/mach-s3c24xx/common-smdk.c                |    2 +-
>  arch/arm/mach-s3c24xx/mach-anubis.c                |    2 +-
>  arch/arm/mach-s3c24xx/mach-at2440evb.c             |    2 +-
>  arch/arm/mach-s3c24xx/mach-bast.c                  |    2 +-
>  arch/arm/mach-s3c24xx/mach-gta02.c                 |    2 +-
>  arch/arm/mach-s3c24xx/mach-jive.c                  |    2 +-
>  arch/arm/mach-s3c24xx/mach-mini2440.c              |    2 +-
>  arch/arm/mach-s3c24xx/mach-osiris.c                |    2 +-
>  arch/arm/mach-s3c24xx/mach-qt2410.c                |    2 +-
>  arch/arm/mach-s3c24xx/mach-rx3715.c                |    2 +-
>  arch/arm/mach-s3c24xx/mach-vstms.c                 |    2 +-
>  arch/blackfin/mach-bf537/boards/dnp5370.c          |    2 +-
>  arch/blackfin/mach-bf537/boards/stamp.c            |    4 +-
>  arch/blackfin/mach-bf561/boards/acvilon.c          |    4 +-
>  arch/cris/arch-v32/drivers/mach-a3/nandflash.c     |    6 +-
>  arch/cris/arch-v32/drivers/mach-fs/nandflash.c     |    6 +-
>  arch/mips/alchemy/devboards/db1200.c               |    4 +-
>  arch/mips/alchemy/devboards/db1300.c               |    4 +-
>  arch/mips/alchemy/devboards/db1550.c               |    4 +-
>  arch/mips/include/asm/mach-jz4740/jz4740_nand.h    |    2 +-
>  arch/mips/jz4740/board-qi_lb60.c                   |    2 +-
>  arch/mips/netlogic/xlr/platform-flash.c            |    2 +-
>  arch/mips/pnx833x/common/platform.c                |    4 +-
>  arch/mips/rb532/devices.c                          |    4 +-
>  arch/sh/boards/mach-migor/setup.c                  |    4 +-
>  drivers/mtd/inftlcore.c                            |    2 +-
>  drivers/mtd/nand/Kconfig                           |  566 +------
>  drivers/mtd/nand/Makefile                          |   71 +-
>  drivers/mtd/nand/{nand_bbt.c => bbt.c}             |  697 ++++----
>  drivers/mtd/nand/raw/Kconfig                       |  566 +++++++
>  drivers/mtd/nand/raw/Makefile                      |   69 +
>  drivers/mtd/nand/{ => raw}/ams-delta.c             |   10 +-
>  drivers/mtd/nand/{ => raw}/atmel/Makefile          |    0
>  drivers/mtd/nand/{ => raw}/atmel/nand-controller.c |   52 +-
>  drivers/mtd/nand/{ => raw}/atmel/pmecc.c           |    2 +-
>  drivers/mtd/nand/{ => raw}/atmel/pmecc.h           |    0
>  drivers/mtd/nand/{ => raw}/au1550nd.c              |   28 +-
>  drivers/mtd/nand/{ => raw}/bcm47xxnflash/Makefile  |    0
>  .../nand/{ => raw}/bcm47xxnflash/bcm47xxnflash.h   |    2 +-
>  drivers/mtd/nand/{ => raw}/bcm47xxnflash/main.c    |    4 +-
>  .../mtd/nand/{ => raw}/bcm47xxnflash/ops_bcm4706.c |   18 +-
>  drivers/mtd/nand/{ => raw}/bf5xx_nand.c            |   34 +-
>  drivers/mtd/nand/{ => raw}/brcmnand/Makefile       |    0
>  .../mtd/nand/{ => raw}/brcmnand/bcm63138_nand.c    |    0
>  drivers/mtd/nand/{ => raw}/brcmnand/bcm6368_nand.c |    0
>  drivers/mtd/nand/{ => raw}/brcmnand/brcmnand.c     |   34 +-
>  drivers/mtd/nand/{ => raw}/brcmnand/brcmnand.h     |    0
>  drivers/mtd/nand/{ => raw}/brcmnand/brcmstb_nand.c |    0
>  drivers/mtd/nand/{ => raw}/brcmnand/iproc_nand.c   |    0
>  drivers/mtd/nand/{ => raw}/cafe_nand.c             |   26 +-
>  drivers/mtd/nand/{ => raw}/cmx270_nand.c           |   14 +-
>  drivers/mtd/nand/{ => raw}/cs553x_nand.c           |   22 +-
>  drivers/mtd/nand/{ => raw}/davinci_nand.c          |   16 +-
>  drivers/mtd/nand/{ => raw}/denali.c                |   14 +-
>  drivers/mtd/nand/{ => raw}/denali.h                |    2 +-
>  drivers/mtd/nand/{ => raw}/denali_dt.c             |    0
>  drivers/mtd/nand/{ => raw}/denali_pci.c            |    0
>  drivers/mtd/nand/{ => raw}/diskonchip.c            |   70 +-
>  drivers/mtd/nand/{ => raw}/docg4.c                 |   45 +-
>  drivers/mtd/nand/{ => raw}/fsl_elbc_nand.c         |   28 +-
>  drivers/mtd/nand/{ => raw}/fsl_ifc_nand.c          |   30 +-
>  drivers/mtd/nand/{ => raw}/fsl_upm.c               |   14 +-
>  drivers/mtd/nand/{ => raw}/fsmc_nand.c             |   26 +-
>  drivers/mtd/nand/{ => raw}/gpio.c                  |    8 +-
>  drivers/mtd/nand/{ => raw}/gpmi-nand/Makefile      |    0
>  drivers/mtd/nand/{ => raw}/gpmi-nand/bch-regs.h    |    0
>  drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-lib.c    |    2 +-
>  drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-nand.c   |   38 +-
>  drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-nand.h   |    2 +-
>  drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-regs.h   |    0
>  drivers/mtd/nand/{ => raw}/hisi504_nand.c          |   26 +-
>  drivers/mtd/nand/{ => raw}/jz4740_nand.c           |   14 +-
>  drivers/mtd/nand/{ => raw}/jz4780_bch.c            |    0
>  drivers/mtd/nand/{ => raw}/jz4780_bch.h            |    0
>  drivers/mtd/nand/{ => raw}/jz4780_nand.c           |   10 +-
>  drivers/mtd/nand/{ => raw}/lpc32xx_mlc.c           |   18 +-
>  drivers/mtd/nand/{ => raw}/lpc32xx_slc.c           |   22 +-
>  drivers/mtd/nand/{ => raw}/mpc5121_nfc.c           |   28 +-
>  drivers/mtd/nand/{ => raw}/mtk_ecc.c               |    0
>  drivers/mtd/nand/{ => raw}/mtk_ecc.h               |    0
>  drivers/mtd/nand/{ => raw}/mtk_nand.c              |   40 +-
>  drivers/mtd/nand/{ => raw}/mxc_nand.c              |   54 +-
>  drivers/mtd/nand/{ => raw}/nand_amd.c              |    4 +-
>  drivers/mtd/nand/{ => raw}/nand_base.c             |  272 +++-
>  drivers/mtd/nand/{ => raw}/nand_bch.c              |    8 +-
>  drivers/mtd/nand/{ => raw}/nand_ecc.c              |    6 +-
>  drivers/mtd/nand/{ => raw}/nand_hynix.c            |   12 +-
>  drivers/mtd/nand/{ => raw}/nand_ids.c              |    2 +-
>  drivers/mtd/nand/{ => raw}/nand_macronix.c         |    2 +-
>  drivers/mtd/nand/{ => raw}/nand_micron.c           |   12 +-
>  drivers/mtd/nand/{ => raw}/nand_samsung.c          |    6 +-
>  drivers/mtd/nand/{ => raw}/nand_timings.c          |    2 +-
>  drivers/mtd/nand/{ => raw}/nand_toshiba.c          |    4 +-
>  drivers/mtd/nand/{ => raw}/nandsim.c               |   24 +-
>  drivers/mtd/nand/{ => raw}/ndfc.c                  |   20 +-
>  drivers/mtd/nand/{ => raw}/nuc900_nand.c           |   10 +-
>  drivers/mtd/nand/{ => raw}/omap2.c                 |   22 +-
>  drivers/mtd/nand/{ => raw}/omap_elm.c              |    0
>  drivers/mtd/nand/{ => raw}/orion_nand.c            |   10 +-
>  drivers/mtd/nand/{ => raw}/oxnas_nand.c            |   14 +-
>  drivers/mtd/nand/{ => raw}/pasemi_nand.c           |   12 +-
>  drivers/mtd/nand/{ => raw}/plat_nand.c             |    6 +-
>  drivers/mtd/nand/{ => raw}/pxa3xx_nand.c           |   38 +-
>  drivers/mtd/nand/{ => raw}/qcom_nandc.c            |   30 +-
>  drivers/mtd/nand/{ => raw}/r852.c                  |    8 +-
>  drivers/mtd/nand/{ => raw}/r852.h                  |    2 +-
>  drivers/mtd/nand/{ => raw}/s3c2410.c               |   18 +-
>  drivers/mtd/nand/{ => raw}/sh_flctl.c              |   12 +-
>  drivers/mtd/nand/{ => raw}/sharpsl.c               |   10 +-
>  drivers/mtd/nand/{ => raw}/sm_common.c             |    4 +-
>  drivers/mtd/nand/{ => raw}/sm_common.h             |    0
>  drivers/mtd/nand/{ => raw}/socrates_nand.c         |   14 +-
>  drivers/mtd/nand/{ => raw}/sunxi_nand.c            |   60 +-
>  drivers/mtd/nand/{ => raw}/tango_nand.c            |   32 +-
>  drivers/mtd/nand/{ => raw}/tmio_nand.c             |   10 +-
>  drivers/mtd/nand/{ => raw}/txx9ndfmc.c             |   16 +-
>  drivers/mtd/nand/{ => raw}/vf610_nfc.c             |    6 +-
>  drivers/mtd/nand/{ => raw}/xway_nand.c             |   12 +-
>  drivers/mtd/nand/spi/Kconfig                       |    7 +
>  drivers/mtd/nand/spi/Makefile                      |    3 +
>  drivers/mtd/nand/spi/controllers/Kconfig           |    5 +
>  drivers/mtd/nand/spi/controllers/Makefile          |    1 +
>  drivers/mtd/nand/spi/controllers/generic-spi.c     |  162 ++
>  drivers/mtd/nand/spi/core.c                        | 1381 ++++++++++++++++
>  drivers/mtd/nand/spi/micron.c                      |  157 ++
>  drivers/mtd/nftlcore.c                             |    2 +-
>  drivers/mtd/nftlmount.c                            |    2 +-
>  drivers/mtd/sm_ftl.c                               |    2 +-
>  drivers/mtd/ssfdc.c                                |    2 +-
>  drivers/mtd/tests/nandbiterrs.c                    |    2 +-
>  drivers/staging/mt29f_spinand/mt29f_spinand.c      |    8 +-
>  fs/jffs2/wbuf.c                                    |    2 +-
>  include/linux/mtd/nand-gpio.h                      |    2 +-
>  include/linux/mtd/nand.h                           | 1667 +++++++-------------
>  include/linux/mtd/rawnand.h                        | 1286 +++++++++++++++
>  include/linux/mtd/sh_flctl.h                       |    4 +-
>  include/linux/mtd/sharpsl.h                        |    2 +-
>  include/linux/mtd/spinand.h                        |  272 ++++
>  include/linux/platform_data/atmel.h                |    2 +-
>  include/linux/platform_data/mtd-davinci.h          |    2 +-
>  include/linux/platform_data/mtd-nand-s3c2410.h     |    2 +-
>  170 files changed, 5708 insertions(+), 2906 deletions(-)
>  rename drivers/mtd/nand/{nand_bbt.c => bbt.c} (69%)
>  create mode 100644 drivers/mtd/nand/raw/Kconfig
>  create mode 100644 drivers/mtd/nand/raw/Makefile
>  rename drivers/mtd/nand/{ => raw}/ams-delta.c (97%)
>  rename drivers/mtd/nand/{ => raw}/atmel/Makefile (100%)
>  rename drivers/mtd/nand/{ => raw}/atmel/nand-controller.c (97%)
>  rename drivers/mtd/nand/{ => raw}/atmel/pmecc.c (99%)
>  rename drivers/mtd/nand/{ => raw}/atmel/pmecc.h (100%)
>  rename drivers/mtd/nand/{ => raw}/au1550nd.c (95%)
>  rename drivers/mtd/nand/{ => raw}/bcm47xxnflash/Makefile (100%)
>  rename drivers/mtd/nand/{ => raw}/bcm47xxnflash/bcm47xxnflash.h (92%)
>  rename drivers/mtd/nand/{ => raw}/bcm47xxnflash/main.c (95%)
>  rename drivers/mtd/nand/{ => raw}/bcm47xxnflash/ops_bcm4706.c (96%)
>  rename drivers/mtd/nand/{ => raw}/bf5xx_nand.c (95%)
>  rename drivers/mtd/nand/{ => raw}/brcmnand/Makefile (100%)
>  rename drivers/mtd/nand/{ => raw}/brcmnand/bcm63138_nand.c (100%)
>  rename drivers/mtd/nand/{ => raw}/brcmnand/bcm6368_nand.c (100%)
>  rename drivers/mtd/nand/{ => raw}/brcmnand/brcmnand.c (98%)
>  rename drivers/mtd/nand/{ => raw}/brcmnand/brcmnand.h (100%)
>  rename drivers/mtd/nand/{ => raw}/brcmnand/brcmstb_nand.c (100%)
>  rename drivers/mtd/nand/{ => raw}/brcmnand/iproc_nand.c (100%)
>  rename drivers/mtd/nand/{ => raw}/cafe_nand.c (97%)
>  rename drivers/mtd/nand/{ => raw}/cmx270_nand.c (94%)
>  rename drivers/mtd/nand/{ => raw}/cs553x_nand.c (95%)
>  rename drivers/mtd/nand/{ => raw}/davinci_nand.c (98%)
>  rename drivers/mtd/nand/{ => raw}/denali.c (99%)
>  rename drivers/mtd/nand/{ => raw}/denali.h (99%)
>  rename drivers/mtd/nand/{ => raw}/denali_dt.c (100%)
>  rename drivers/mtd/nand/{ => raw}/denali_pci.c (100%)
>  rename drivers/mtd/nand/{ => raw}/diskonchip.c (96%)
>  rename drivers/mtd/nand/{ => raw}/docg4.c (97%)
>  rename drivers/mtd/nand/{ => raw}/fsl_elbc_nand.c (97%)
>  rename drivers/mtd/nand/{ => raw}/fsl_ifc_nand.c (97%)
>  rename drivers/mtd/nand/{ => raw}/fsl_upm.c (95%)
>  rename drivers/mtd/nand/{ => raw}/fsmc_nand.c (97%)
>  rename drivers/mtd/nand/{ => raw}/gpio.c (97%)
>  rename drivers/mtd/nand/{ => raw}/gpmi-nand/Makefile (100%)
>  rename drivers/mtd/nand/{ => raw}/gpmi-nand/bch-regs.h (100%)
>  rename drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-lib.c (99%)
>  rename drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-nand.c (98%)
>  rename drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-nand.h (99%)
>  rename drivers/mtd/nand/{ => raw}/gpmi-nand/gpmi-regs.h (100%)
>  rename drivers/mtd/nand/{ => raw}/hisi504_nand.c (97%)
>  rename drivers/mtd/nand/{ => raw}/jz4740_nand.c (97%)
>  rename drivers/mtd/nand/{ => raw}/jz4780_bch.c (100%)
>  rename drivers/mtd/nand/{ => raw}/jz4780_bch.h (100%)
>  rename drivers/mtd/nand/{ => raw}/jz4780_nand.c (97%)
>  rename drivers/mtd/nand/{ => raw}/lpc32xx_mlc.c (98%)
>  rename drivers/mtd/nand/{ => raw}/lpc32xx_slc.c (98%)
>  rename drivers/mtd/nand/{ => raw}/mpc5121_nfc.c (96%)
>  rename drivers/mtd/nand/{ => raw}/mtk_ecc.c (100%)
>  rename drivers/mtd/nand/{ => raw}/mtk_ecc.h (100%)
>  rename drivers/mtd/nand/{ => raw}/mtk_nand.c (97%)
>  rename drivers/mtd/nand/{ => raw}/mxc_nand.c (97%)
>  rename drivers/mtd/nand/{ => raw}/nand_amd.c (94%)
>  rename drivers/mtd/nand/{ => raw}/nand_base.c (94%)
>  rename drivers/mtd/nand/{ => raw}/nand_bch.c (97%)
>  rename drivers/mtd/nand/{ => raw}/nand_ecc.c (99%)
>  rename drivers/mtd/nand/{ => raw}/nand_hynix.c (98%)
>  rename drivers/mtd/nand/{ => raw}/nand_ids.c (99%)
>  rename drivers/mtd/nand/{ => raw}/nand_macronix.c (96%)
>  rename drivers/mtd/nand/{ => raw}/nand_micron.c (96%)
>  rename drivers/mtd/nand/{ => raw}/nand_samsung.c (95%)
>  rename drivers/mtd/nand/{ => raw}/nand_timings.c (99%)
>  rename drivers/mtd/nand/{ => raw}/nand_toshiba.c (95%)
>  rename drivers/mtd/nand/{ => raw}/nandsim.c (99%)
>  rename drivers/mtd/nand/{ => raw}/ndfc.c (93%)
>  rename drivers/mtd/nand/{ => raw}/nuc900_nand.c (96%)
>  rename drivers/mtd/nand/{ => raw}/omap2.c (99%)
>  rename drivers/mtd/nand/{ => raw}/omap_elm.c (100%)
>  rename drivers/mtd/nand/{ => raw}/orion_nand.c (96%)
>  rename drivers/mtd/nand/{ => raw}/oxnas_nand.c (93%)
>  rename drivers/mtd/nand/{ => raw}/pasemi_nand.c (95%)
>  rename drivers/mtd/nand/{ => raw}/plat_nand.c (96%)
>  rename drivers/mtd/nand/{ => raw}/pxa3xx_nand.c (98%)
>  rename drivers/mtd/nand/{ => raw}/qcom_nandc.c (98%)
>  rename drivers/mtd/nand/{ => raw}/r852.c (99%)
>  rename drivers/mtd/nand/{ => raw}/r852.h (99%)
>  rename drivers/mtd/nand/{ => raw}/s3c2410.c (98%)
>  rename drivers/mtd/nand/{ => raw}/sh_flctl.c (99%)
>  rename drivers/mtd/nand/{ => raw}/sharpsl.c (96%)
>  rename drivers/mtd/nand/{ => raw}/sm_common.c (98%)
>  rename drivers/mtd/nand/{ => raw}/sm_common.h (100%)
>  rename drivers/mtd/nand/{ => raw}/socrates_nand.c (94%)
>  rename drivers/mtd/nand/{ => raw}/sunxi_nand.c (97%)
>  rename drivers/mtd/nand/{ => raw}/tango_nand.c (95%)
>  rename drivers/mtd/nand/{ => raw}/tmio_nand.c (98%)
>  rename drivers/mtd/nand/{ => raw}/txx9ndfmc.c (97%)
>  rename drivers/mtd/nand/{ => raw}/vf610_nfc.c (99%)
>  rename drivers/mtd/nand/{ => raw}/xway_nand.c (96%)
>  create mode 100644 drivers/mtd/nand/spi/Kconfig
>  create mode 100644 drivers/mtd/nand/spi/Makefile
>  create mode 100644 drivers/mtd/nand/spi/controllers/Kconfig
>  create mode 100644 drivers/mtd/nand/spi/controllers/Makefile
>  create mode 100644 drivers/mtd/nand/spi/controllers/generic-spi.c
>  create mode 100644 drivers/mtd/nand/spi/core.c
>  create mode 100644 drivers/mtd/nand/spi/micron.c
>  create mode 100644 include/linux/mtd/rawnand.h
>  create mode 100644 include/linux/mtd/spinand.h
> 

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 05/15] mtd: nand: raw: create struct rawnand_device
  2017-05-24  7:07 ` [PATCH v6 05/15] mtd: nand: raw: create struct rawnand_device Peter Pan
@ 2017-05-29 21:05   ` Boris Brezillon
  0 siblings, 0 replies; 65+ messages in thread
From: Boris Brezillon @ 2017-05-29 21:05 UTC (permalink / raw)
  To: Peter Pan
  Cc: richard, computersforpeace, arnaud.mouiche, thomas.petazzoni,
	marex, cyrille.pitchen, linux-mtd, peterpansjtu, linshunquan1

On Wed, 24 May 2017 15:07:01 +0800
Peter Pan <peterpandong@micron.com> wrote:

> From: Boris Brezillon <boris.brezillon@free-electrons.com>
> 
> Create the rawnand_device struct inheriting from nand_device and make
> nand_chip inherit from this struct.
> 
> The rawnand_device object should be used for the new
> rawnand-device/rawnand-controller model, and fields inside nand_chip
> should progressively move to the future rawnand_controller or the existing
> rawnand_device struct.
> 
> In the meantime, we make sure nand_device fields are properly initialized
> by converting information stored in mtd_info and nand_chip into the
> nand_memory_organization format.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
> Signed-off-by: Peter Pan <peterpandong@micron.com>
> ---
>  drivers/mtd/nand/raw/nand_base.c | 40 ++++++++++++++++++++++++++++++++++++++++
>  include/linux/mtd/rawnand.h      | 26 ++++++++++++++++++++------
>  2 files changed, 60 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index a113cfb..8f8df15 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -3957,6 +3957,43 @@ static bool find_full_id_nand(struct nand_chip *chip,
>  	return false;
>  }
>  

[...]

> +
> +static void nandc_fill_nandd(struct nand_chip *chip)

I'll probably rename this function nandchip_init_nanddev() to be
consistent with the nandchip prefix used in patch 4.

> +{
> +	struct mtd_info *mtd = nandchip_to_mtd(chip);
> +	struct nand_device *nand = mtd_to_nand(mtd);
> +	struct nand_memory_organization *memorg = &nand->memorg;
> +
> +	memorg->pagesize = mtd->writesize;
> +	memorg->oobsize = mtd->oobsize;
> +	memorg->eraseblocksize = mtd->erasesize;
> +	memorg->ndies = chip->numchips;
> +	memorg->diesize = chip->chipsize;
> +	/* TODO: fill ->planesize and ->nplanes */
> +
> +	nand->ops = &rawnand_ops;
> +}

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 09/15] mtd: nand: make sure mtd_oob_ops consistent in bbt
  2017-05-24  7:07 ` [PATCH v6 09/15] mtd: nand: make sure mtd_oob_ops consistent in bbt Peter Pan
@ 2017-05-29 21:06   ` Boris Brezillon
  0 siblings, 0 replies; 65+ messages in thread
From: Boris Brezillon @ 2017-05-29 21:06 UTC (permalink / raw)
  To: Peter Pan
  Cc: richard, computersforpeace, arnaud.mouiche, thomas.petazzoni,
	marex, cyrille.pitchen, linux-mtd, peterpansjtu, linshunquan1

On Wed, 24 May 2017 15:07:05 +0800
Peter Pan <peterpandong@micron.com> wrote:

> This commit makes sure struct mtd_oob_ops passed to mtd_read/write_ops()
> is consistent, which means .datbuf = NULL and .len = 0 when not reading
> page; .oobbuf = NULL and .ooblen = 0 when not reading oob. If no, (ie.
> ops.datbuf = NULL, while ops.len != 0.), nand_for_each_page() will run
> forever.

This should be done before making bbt core generic, and this is
something I can already apply in this release.

> 
> Signed-off-by: Peter Pan <peterpandong@micron.com>
> ---
>  drivers/mtd/nand/bbt.c | 13 ++++++-------
>  1 file changed, 6 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/mtd/nand/bbt.c b/drivers/mtd/nand/bbt.c
> index 56115d5..96d4e14 100644
> --- a/drivers/mtd/nand/bbt.c
> +++ b/drivers/mtd/nand/bbt.c
> @@ -328,7 +328,7 @@ static int scan_read_oob(struct nand_device *this, uint8_t *buf, loff_t offs,
>  			 size_t len)
>  {
>  	struct mtd_info *mtd = nand_to_mtd(this);
> -	struct mtd_oob_ops ops;
> +	struct mtd_oob_ops ops = {};
>  	int res, ret = 0;
>  
>  	ops.mode = MTD_OPS_PLACE_OOB;
> @@ -369,11 +369,12 @@ static int scan_write_bbt(struct nand_device *this, loff_t offs, size_t len,
>  			  uint8_t *buf, uint8_t *oob)
>  {
>  	struct mtd_info *mtd = nand_to_mtd(this);
> -	struct mtd_oob_ops ops;
> +	struct mtd_oob_ops ops = {};
>  
>  	ops.mode = MTD_OPS_PLACE_OOB;
>  	ops.ooboffs = 0;
> -	ops.ooblen = nand_per_page_oobsize(this);
> +	/* oob from caller may be NULL */
> +	ops.ooblen = oob ? nand_per_page_oobsize(this) : 0;
>  	ops.datbuf = buf;
>  	ops.oobbuf = oob;
>  	ops.len = len;
> @@ -428,13 +429,12 @@ static int scan_block_fast(struct nand_device *this, struct nand_bbt_descr *bd,
>  			   loff_t offs, uint8_t *buf, int numpages)
>  {
>  	struct mtd_info *mtd = nand_to_mtd(this);
> -	struct mtd_oob_ops ops;
> +	struct mtd_oob_ops ops = {};
>  	int j, ret;
>  
>  	ops.ooblen = nand_per_page_oobsize(this);
>  	ops.oobbuf = buf;
>  	ops.ooboffs = 0;
> -	ops.datbuf = NULL;
>  	ops.mode = MTD_OPS_PLACE_OOB;
>  
>  	for (j = 0; j < numpages; j++) {
> @@ -734,11 +734,10 @@ static int write_bbt(struct nand_device *this, uint8_t *buf,
>  	uint8_t rcode = td->reserved_block_code;
>  	size_t retlen, len = 0;
>  	loff_t to;
> -	struct mtd_oob_ops ops;
> +	struct mtd_oob_ops ops = {};
>  
>  	ops.ooblen = nand_per_page_oobsize(this);
>  	ops.ooboffs = 0;
> -	ops.datbuf = NULL;
>  	ops.mode = MTD_OPS_PLACE_OOB;
>  
>  	if (!rcode)

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 08/15] mtd: nand: Add the page iterator concept
  2017-05-24  7:07 ` [PATCH v6 08/15] mtd: nand: Add the page iterator concept Peter Pan
@ 2017-05-29 21:12   ` Boris Brezillon
  0 siblings, 0 replies; 65+ messages in thread
From: Boris Brezillon @ 2017-05-29 21:12 UTC (permalink / raw)
  To: Peter Pan
  Cc: richard, computersforpeace, arnaud.mouiche, thomas.petazzoni,
	marex, cyrille.pitchen, linux-mtd, peterpansjtu, linshunquan1

On Wed, 24 May 2017 15:07:04 +0800
Peter Pan <peterpandong@micron.com> wrote:

> From: Boris Brezillon <boris.brezillon@free-electrons.com>
> 

Please squash these changes int patch 3.

> Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
> Signed-off-by: Peter Pan <peterpandong@micron.com>
> ---
>  include/linux/mtd/nand.h | 93 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 93 insertions(+)
> 
> diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
> index 78931ff..479ff9f 100644
> --- a/include/linux/mtd/nand.h
> +++ b/include/linux/mtd/nand.h
> @@ -78,6 +78,24 @@ struct nand_device {
>  };
>  
>  /**
> + * struct nand_page_iter - NAND page iterator
> + * @page: the page
> + * @pageoffs: the offset within a page
> + * @dataleft: the left page data to read/write
> + * @ooboffs: the offset within page oob
> + * @oobleft: the left oob data to read/write
> + * @oobbytes_per_page: maximun oob bytes to read/write per page
> + */
> +struct nand_page_iter {
> +	int page;
> +	int pageoffs;
> +	size_t dataleft;
> +	int ooboffs;
> +	size_t oobleft;
> +	int oobbytes_per_page;
> +};
> +
> +/**
>   * mtd_to_nand - Get the NAND device attached to the MTD instance
>   * @mtd: MTD instance
>   *
> @@ -176,6 +194,81 @@ static inline int nand_per_page_oobsize(struct nand_device *nand)
>  }
>  
>  /**
> + * nand_page_iter_init - Initialize a NAND page iterator
> + * @nand: NAND device
> + * @offs: absolute offset
> + * @len: page data length to read/write
> + * @ooboffs: oob offset within page
> + * @ooblen: oob data length to read/write
> + * @oobbytes_per_page: oob data can read/write per page
> + * @iter: page iterator
> + */
> +static inline void nand_page_iter_init(struct nand_device *nand,
> +				       loff_t offs, size_t len, u32 ooboffs,
> +				       size_t ooblen, u32 oobbytes_per_page,
> +				       struct nand_page_iter *iter)
> +{
> +	u64 page = offs;
> +
> +	iter->pageoffs = do_div(page, nand->memorg.pagesize);
> +	iter->page = page;
> +	iter->dataleft = len;
> +	iter->ooboffs = ooboffs;
> +	iter->oobleft = ooblen;
> +	iter->oobbytes_per_page = oobbytes_per_page;
> +}
> +
> +/**
> + * nand_page_iter_next - Move to the next page
> + * @nand: NAND device
> + * @iter: page iterator
> + */
> +static inline void nand_page_iter_next(struct nand_device *nand,
> +				       struct nand_page_iter *iter)
> +{
> +	iter->page++;
> +	iter->pageoffs = 0;

Blank line.

> +	if (iter->dataleft)
> +		iter->dataleft -= min_t (int,
> +					 nand_page_size(nand) - iter->pageoffs,
> +					 iter->dataleft);

Ditto.

> +	if (iter->oobleft)
> +		iter->oobleft -= min_t(int,
> +				       iter->oobbytes_per_page - iter->ooboffs,
> +				       iter->oobleft);
> +}
> +
> +/**
> + * nand_page_iter_end - Should end iteration or not
> + * @nand: NAND device
> + * @iter: page iterator
> + */
> +static inline bool nand_page_iter_end(struct nand_device *nand,
> +				      struct nand_page_iter *iter)
> +{
> +	if (iter->dataleft || iter->oobleft)
> +		return false;

Ditto.

> +	return true;
> +}
> +
> +/**
> + * nand_for_each_page - Iterate nand pages
> + * @nand: NAND device
> + * @start: start address to read/write
> + * @len: page data length to read/write
> + * @ooboffs: oob offset within page
> + * @ooblen: oob data length to read/write
> + * @oobbytes_per_page: oob data can read/write per page
> + * @iter: page iterator
> + */
> +#define nand_for_each_page(nand, start, len, ooboffs, ooblen,	\
> +			   oobbytes_per_page, iter)	\
> +	for (nand_page_iter_init(nand, start, len, ooboffs, ooblen,	\
> +				 oobbytes_per_page, iter);	\
> +	     !nand_page_iter_end(nand, iter);		\
> +	     nand_page_iter_next(nand, iter))
> +
> +/**
>   * nand_per_page_oobsize - Get NAND erase block size
>   * @nand: NAND device
>   *

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 10/15] nand: spi: add basic blocks for infrastructure
  2017-05-24  7:07 ` [PATCH v6 10/15] nand: spi: add basic blocks for infrastructure Peter Pan
@ 2017-05-29 21:51   ` Boris Brezillon
  2017-05-31  7:02     ` Peter Pan 潘栋 (peterpandong)
  2017-05-31 21:45   ` Cyrille Pitchen
  1 sibling, 1 reply; 65+ messages in thread
From: Boris Brezillon @ 2017-05-29 21:51 UTC (permalink / raw)
  To: Peter Pan
  Cc: richard, computersforpeace, arnaud.mouiche, thomas.petazzoni,
	marex, cyrille.pitchen, linux-mtd, peterpansjtu, linshunquan1

On Wed, 24 May 2017 15:07:06 +0800
Peter Pan <peterpandong@micron.com> wrote:

> This is the first commit for spi nand framkework.

					^ framework

> This commit is to add add basic building blocks

	      is adding basic ...

> for the SPI NAND infrastructure.
> 
> Signed-off-by: Peter Pan <peterpandong@micron.com>
> ---

[...]

> +
> +/**
> + * devm_spinand_alloc - [SPI NAND Interface] allocate SPI NAND device instance

Let's drop those [SPI NAND Interface] specifier. It's pretty obvious
that this is part of the spi-nand API, since those symbols are exported.

> + * @dev: pointer to device model structure
> + */
> +struct spinand_device *devm_spinand_alloc(struct device *dev)

You can pass a pointer to the nand_controller object driving the
nand_device here.

> +{
> +	struct spinand_device *spinand;
> +	struct mtd_info *mtd;
> +
> +	spinand = devm_kzalloc(dev, sizeof(*spinand), GFP_KERNEL);
> +	if (!spinand)
> +		return ERR_PTR(-ENOMEM);
> +
> +	spinand_set_of_node(spinand, dev->of_node);
> +	mutex_init(&spinand->lock);
> +	spinand->dev = dev;

Hm, I don't think this is correct. The device here is likely to
represent the controller not the SPI NAND device. For the generic spi
nand controller, I agree, it's the same, but, in case you have one
controller that is attached several spi devices, it's not.

How about putting the struct device pointer in nand_controller and then
pass the controller to this spinand_alloc() function.

> +	mtd = spinand_to_mtd(spinand);
> +	mtd->dev.parent = dev;
> +
> +	return spinand;
> +}
> +EXPORT_SYMBOL_GPL(devm_spinand_alloc);
> +
> +/**
> + * spinand_init - [SPI NAND Interface] initialize the SPI NAND device
> + * @spinand: SPI NAND device structure
> + */
> +int spinand_init(struct spinand_device *spinand)
> +{
> +	struct mtd_info *mtd = spinand_to_mtd(spinand);
> +	struct nand_device *nand = mtd_to_nand(mtd);
> +	int ret;
> +
> +	ret = spinand_detect(spinand);
> +	if (ret) {
> +		dev_err(spinand->dev,
> +			"Detect SPI NAND failed with error %d.\n", ret);
> +		goto err_out;

		return ret;


> +	}

I'd still prefer to move the detection step out of this _init()
function even if this implies duplicating the _detect()+_init()
sequence in all drivers. Maybe you can provide a wrapper called
spinand_detect_and_init() to do both in one go.

> +
> +	spinand_set_rd_wr_op(spinand);
> +
> +	/*
> +	 * Use kzalloc() instead of devm_kzalloc() here, beacause some drivers
> +	 * may use this buffer for DMA access.
> +	 * Memory allocated by devm_ does not guarantee DMA-safe alignment.
> +	 */
> +	spinand->buf = kzalloc(nand_page_size(nand) +
> +			       nand_per_page_oobsize(nand),
> +			       GFP_KERNEL);
> +	if (!spinand->buf) {
> +		ret = -ENOMEM;
> +		goto err_out;

		return -ENOMEM;

> +	}
> +
> +	spinand->oobbuf = spinand->buf + nand_page_size(nand);
> +
> +	ret = spinand_manufacturer_init(spinand);
> +	if (ret) {
> +		dev_err(spinand->dev,
> +			"Manufacurer init SPI NAND failed with err %d.\n",
> +			ret);
> +		goto err_free_buf;
> +	}
> +
> +	mtd->name = spinand->name;
> +	mtd->size = nand_size(nand);
> +	mtd->erasesize = nand_eraseblock_size(nand);
> +	mtd->writesize = nand_page_size(nand);
> +	mtd->writebufsize = mtd->writesize;
> +	mtd->owner = THIS_MODULE;
> +	mtd->type = MTD_NANDFLASH;
> +	mtd->flags = MTD_CAP_NANDFLASH;
> +	mtd->oobsize = nand_per_page_oobsize(nand);
> +	/*
> +	 * Right now, we don't support ECC, so let the whole oob
> +	 * area is available for user.
> +	 */
> +	mtd->oobavail = mtd->oobsize;
> +
> +	/* After power up, all blocks are locked, so unlock it here. */
> +	spinand_lock_block(spinand, BL_ALL_UNLOCKED);
> +
> +	return 0;
> +
> +err_free_buf:
> +	kfree(spinand->buf);
> +err_out:

You can get rid of err_out.

> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(spinand_init);
> +

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 11/15] nand: spi: add basic operations support
  2017-05-24  7:07 ` [PATCH v6 11/15] nand: spi: add basic operations support Peter Pan
@ 2017-05-29 22:11   ` Boris Brezillon
  2017-05-31  6:51     ` Peter Pan 潘栋 (peterpandong)
  2017-10-11 13:35   ` Boris Brezillon
  1 sibling, 1 reply; 65+ messages in thread
From: Boris Brezillon @ 2017-05-29 22:11 UTC (permalink / raw)
  To: Peter Pan
  Cc: richard, computersforpeace, arnaud.mouiche, thomas.petazzoni,
	marex, cyrille.pitchen, linux-mtd, peterpansjtu, linshunquan1

On Wed, 24 May 2017 15:07:07 +0800
Peter Pan <peterpandong@micron.com> wrote:

> This commit is to support read, readoob, write,
> writeoob and erase operations in the new spi nand
> framework. No ECC support right now.

I still don't understand why patch 10 and 11 are separated. I'd prefer
to see one single patch adding basic spi-nand support, that is,
everything to support detection+initialization+read/write access.

> 
> Signed-off-by: Peter Pan <peterpandong@micron.com>
> ---
>  drivers/mtd/nand/spi/core.c | 638 ++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/mtd/spinand.h |   3 +
>  2 files changed, 641 insertions(+)
> 
> diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
> index 93ce212..6251469 100644
> --- a/drivers/mtd/nand/spi/core.c
> +++ b/drivers/mtd/nand/spi/core.c
> @@ -108,6 +108,222 @@ static int spinand_read_status(struct spinand_device *spinand, u8 *status)
>  }
>  
>  /**
> + * spinand_get_cfg - get configuration register value
> + * @spinand: SPI NAND device structure
> + * @cfg: buffer to store value
> + * Description:
> + *   Configuration register includes OTP config, Lock Tight enable/disable
> + *   and Internal ECC enable/disable.
> + */
> +static int spinand_get_cfg(struct spinand_device *spinand, u8 *cfg)
> +{
> +	return spinand_read_reg(spinand, REG_CFG, cfg);
> +}
> +
> +/**
> + * spinand_set_cfg - set value to configuration register
> + * @spinand: SPI NAND device structure
> + * @cfg: value to set
> + * Description:
> + *   Configuration register includes OTP config, Lock Tight enable/disable
> + *   and Internal ECC enable/disable.
> + */
> +static int spinand_set_cfg(struct spinand_device *spinand, u8 cfg)
> +{
> +	return spinand_write_reg(spinand, REG_CFG, cfg);
> +}
> +
> +/**
> + * spinand_disable_ecc - disable internal ECC
> + * @spinand: SPI NAND device structure
> + */
> +static void spinand_disable_ecc(struct spinand_device *spinand)
> +{
> +	u8 cfg = 0;
> +
> +	spinand_get_cfg(spinand, &cfg);
> +
> +	if ((cfg & CFG_ECC_MASK) == CFG_ECC_ENABLE) {
> +		cfg &= ~CFG_ECC_ENABLE;
> +		spinand_set_cfg(spinand, cfg);
> +	}

Is this really a generic (manufacturer-agnostic) feature??? I had the
feeling that is was only working for Micron. If that's the case, this
'disable-ecc' step should be done in spi/micron.c in a
micron_spinand_init() function.

> +}
> +
> +/**
> + * spinand_write_enable - send command 06h to enable write or erase the
> + * NAND cells
> + * @spinand: SPI NAND device structure
> + */
> +static int spinand_write_enable(struct spinand_device *spinand)
> +{
> +	struct spinand_op op;
> +
> +	spinand_init_op(&op);
> +	op.cmd = SPINAND_CMD_WR_ENABLE;
> +
> +	return spinand_exec_op(spinand, &op);
> +}
> +
> +/**
> + * spinand_read_page_to_cache - send command 13h to read data from NAND array
> + * to cache
> + * @spinand: SPI NAND device structure
> + * @page_addr: page to read
> + */
> +static int spinand_read_page_to_cache(struct spinand_device *spinand,
> +				      u32 page_addr)
> +{
> +	struct spinand_op op;
> +
> +	spinand_init_op(&op);
> +	op.cmd = SPINAND_CMD_PAGE_READ;
> +	op.n_addr = 3;
> +	op.addr[0] = (u8)(page_addr >> 16);
> +	op.addr[1] = (u8)(page_addr >> 8);
> +	op.addr[2] = (u8)page_addr;
> +
> +	return spinand_exec_op(spinand, &op);
> +}
> +
> +/**
> + * spinand_get_address_bits - return address should be transferred
> + * by how many bits
> + * @opcode: command's operation code
> + */
> +static int spinand_get_address_bits(u8 opcode)
> +{
> +	switch (opcode) {
> +	case SPINAND_CMD_READ_FROM_CACHE_QUAD_IO:
> +		return 4;
> +	case SPINAND_CMD_READ_FROM_CACHE_DUAL_IO:
> +		return 2;
> +	default:
> +		return 1;
> +	}
> +}
> +
> +/**
> + * spinand_get_data_bits - return data should be transferred by how many bits
> + * @opcode: command's operation code
> + */
> +static int spinand_get_data_bits(u8 opcode)
> +{
> +	switch (opcode) {
> +	case SPINAND_CMD_READ_FROM_CACHE_QUAD_IO:
> +	case SPINAND_CMD_READ_FROM_CACHE_X4:
> +	case SPINAND_CMD_PROG_LOAD_X4:
> +	case SPINAND_CMD_PROG_LOAD_RDM_DATA_X4:
> +		return 4;
> +	case SPINAND_CMD_READ_FROM_CACHE_DUAL_IO:
> +	case SPINAND_CMD_READ_FROM_CACHE_X2:
> +		return 2;
> +	default:
> +		return 1;
> +	}
> +}
> +
> +/**
> + * spinand_read_from_cache - read data out from cache register
> + * @spinand: SPI NAND device structure
> + * @page_addr: page to read
> + * @column: the location to read from the cache
> + * @len: number of bytes to read
> + * @rbuf: buffer held @len bytes
> + */
> +static int spinand_read_from_cache(struct spinand_device *spinand,
> +				   u32 page_addr, u32 column,
> +				   size_t len, u8 *rbuf)
> +{
> +	struct spinand_op op;
> +
> +	spinand_init_op(&op);
> +	op.cmd = spinand->read_cache_op;
> +	op.n_addr = 2;
> +	op.addr[0] = (u8)(column >> 8);
> +	op.addr[1] = (u8)column;

Casts are unneeded here.

> +	op.addr_nbits = spinand_get_address_bits(spinand->read_cache_op);
> +	op.n_rx = len;
> +	op.rx_buf = rbuf;
> +	op.data_nbits = spinand_get_data_bits(spinand->read_cache_op);
> +
> +	if (spinand->manufacturer.manu->ops->prepare_op)
> +		spinand->manufacturer.manu->ops->prepare_op(spinand, &op,
> +							    page_addr, column);
> +
> +	return spinand_exec_op(spinand, &op);
> +}
> +
> +/**
> + * spinand_write_to_cache - write data to cache register
> + * @spinand: SPI NAND device structure
> + * @page_addr: page to write
> + * @column: the location to write to the cache
> + * @len: number of bytes to write
> + * @wrbuf: buffer held @len bytes
> + */
> +static int spinand_write_to_cache(struct spinand_device *spinand, u32 page_addr,
> +				  u32 column, size_t len, const u8 *wbuf)
> +{
> +	struct spinand_op op;
> +
> +	spinand_init_op(&op);
> +	op.cmd = spinand->write_cache_op;
> +	op.n_addr = 2;
> +	op.addr[0] = (u8)(column >> 8);
> +	op.addr[1] = (u8)column;
> +	op.addr_nbits = spinand_get_address_bits(spinand->write_cache_op);
> +	op.n_tx = len;
> +	op.tx_buf = wbuf;
> +	op.data_nbits = spinand_get_data_bits(spinand->write_cache_op);
> +
> +	if (spinand->manufacturer.manu->ops->prepare_op)
> +		spinand->manufacturer.manu->ops->prepare_op(spinand, &op,
> +							    page_addr, column);
> +
> +	return spinand_exec_op(spinand, &op);
> +}
> +
> +/**
> + * spinand_program_execute - send command 10h to write a page from
> + * cache to the NAND array
> + * @spinand: SPI NAND device structure
> + * @page_addr: the physical page location to write the page.
> + */
> +static int spinand_program_execute(struct spinand_device *spinand,
> +				   u32 page_addr)
> +{
> +	struct spinand_op op;
> +
> +	spinand_init_op(&op);
> +	op.cmd = SPINAND_CMD_PROG_EXC;
> +	op.n_addr = 3;
> +	op.addr[0] = (u8)(page_addr >> 16);
> +	op.addr[1] = (u8)(page_addr >> 8);
> +	op.addr[2] = (u8)page_addr;

You don't need to adjust the number of dummy cycles here?

The usage of ->prepare_op() is really weird, maybe you should document
a bit more when it's supposed to be used.

> +
> +	return spinand_exec_op(spinand, &op);
> +}
> +

[...]

>  
> diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
> index dd9da71..04ad1dd 100644
> --- a/include/linux/mtd/spinand.h
> +++ b/include/linux/mtd/spinand.h
> @@ -103,11 +103,14 @@ struct spinand_controller_ops {
>   *          return directly and let others to detect.
>   * @init: initialize SPI NAND device.
>   * @cleanup: clean SPI NAND device footprint.
> + * @prepare_op: prepara read/write operation.

		   ^ prepare



>   */
>  struct spinand_manufacturer_ops {
>  	bool (*detect)(struct spinand_device *spinand);
>  	int (*init)(struct spinand_device *spinand);
>  	void (*cleanup)(struct spinand_device *spinand);
> +	void (*prepare_op)(struct spinand_device *spinand,
> +			   struct spinand_op *op, u32 page, u32 column);

It seems to be here to prepare read/write page operations, so I'd like
to rename this method ->prepare_page_op() if you don't mind.

>  };
>  
>  /**

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 11/15] nand: spi: add basic operations support
  2017-05-29 22:11   ` Boris Brezillon
@ 2017-05-31  6:51     ` Peter Pan 潘栋 (peterpandong)
  2017-05-31 10:02       ` Boris Brezillon
  2017-06-27 20:15       ` Boris Brezillon
  0 siblings, 2 replies; 65+ messages in thread
From: Peter Pan 潘栋 (peterpandong) @ 2017-05-31  6:51 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: richard, computersforpeace, arnaud.mouiche, thomas.petazzoni,
	marex, cyrille.pitchen, linux-mtd, peterpansjtu, linshunquan1

Hi Boris,

> On 30 May 2017, at 06:12, Boris Brezillon <boris.brezillon@free-electrons.com> wrote:
> 
> On Wed, 24 May 2017 15:07:07 +0800
> Peter Pan <peterpandong@micron.com> wrote:
> 
>> This commit is to support read, readoob, write,
>> writeoob and erase operations in the new spi nand
>> framework. No ECC support right now.
> 
> I still don't understand why patch 10 and 11 are separated. I'd prefer
> to see one single patch adding basic spi-nand support, that is,
> everything to support detection+initialization+read/write access.

Let' put patch 10 and 11 together in v7:)

>> 
>> Signed-off-by: Peter Pan <peterpandong@micron.com>
>> ---
>> drivers/mtd/nand/spi/core.c | 638 ++++++++++++++++++++++++++++++++++++++++++++
>> include/linux/mtd/spinand.h |   3 +
>> 2 files changed, 641 insertions(+)
>> 
>> diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
>> index 93ce212..6251469 100644
>> --- a/drivers/mtd/nand/spi/core.c
>> +++ b/drivers/mtd/nand/spi/core.c
>> @@ -108,6 +108,222 @@ static int spinand_read_status(struct spinand_device *spinand, u8 *status)
>> }
>> 
>> /**
>> + * spinand_get_cfg - get configuration register value
>> + * @spinand: SPI NAND device structure
>> + * @cfg: buffer to store value
>> + * Description:
>> + *   Configuration register includes OTP config, Lock Tight enable/disable
>> + *   and Internal ECC enable/disable.
>> + */
>> +static int spinand_get_cfg(struct spinand_device *spinand, u8 *cfg)
>> +{
>> +    return spinand_read_reg(spinand, REG_CFG, cfg);
>> +}
>> +
>> +/**
>> + * spinand_set_cfg - set value to configuration register
>> + * @spinand: SPI NAND device structure
>> + * @cfg: value to set
>> + * Description:
>> + *   Configuration register includes OTP config, Lock Tight enable/disable
>> + *   and Internal ECC enable/disable.
>> + */
>> +static int spinand_set_cfg(struct spinand_device *spinand, u8 cfg)
>> +{
>> +    return spinand_write_reg(spinand, REG_CFG, cfg);
>> +}
>> +
>> +/**
>> + * spinand_disable_ecc - disable internal ECC
>> + * @spinand: SPI NAND device structure
>> + */
>> +static void spinand_disable_ecc(struct spinand_device *spinand)
>> +{
>> +    u8 cfg = 0;
>> +
>> +    spinand_get_cfg(spinand, &cfg);
>> +
>> +    if ((cfg & CFG_ECC_MASK) == CFG_ECC_ENABLE) {
>> +        cfg &= ~CFG_ECC_ENABLE;
>> +        spinand_set_cfg(spinand, cfg);
>> +    }
> 
> Is this really a generic (manufacturer-agnostic) feature??? I had the
> feeling that is was only working for Micron. If that's the case, this
> 'disable-ecc' step should be done in spi/micron.c in a
> micron_spinand_init() function.

As far as I can see, Micron is not the only vendor to disable on die ecc 
by this way, actually all vendors I know use this . And this series 
doesn't support on die ecc, so IMO it is necessary to disable it during
initialization

> 
>> +}
>> +
>> +/**
>> + * spinand_write_enable - send command 06h to enable write or erase the
>> + * NAND cells
>> + * @spinand: SPI NAND device structure
>> + */
>> +static int spinand_write_enable(struct spinand_device *spinand)
>> +{
>> +    struct spinand_op op;
>> +
>> +    spinand_init_op(&op);
>> +    op.cmd = SPINAND_CMD_WR_ENABLE;
>> +
>> +    return spinand_exec_op(spinand, &op);
>> +}
>> +
>> +/**
>> + * spinand_read_page_to_cache - send command 13h to read data from NAND array
>> + * to cache
>> + * @spinand: SPI NAND device structure
>> + * @page_addr: page to read
>> + */
>> +static int spinand_read_page_to_cache(struct spinand_device *spinand,
>> +                      u32 page_addr)
>> +{
>> +    struct spinand_op op;
>> +
>> +    spinand_init_op(&op);
>> +    op.cmd = SPINAND_CMD_PAGE_READ;
>> +    op.n_addr = 3;
>> +    op.addr[0] = (u8)(page_addr >> 16);
>> +    op.addr[1] = (u8)(page_addr >> 8);
>> +    op.addr[2] = (u8)page_addr;
>> +
>> +    return spinand_exec_op(spinand, &op);
>> +}
>> +
>> +/**
>> + * spinand_get_address_bits - return address should be transferred
>> + * by how many bits
>> + * @opcode: command's operation code
>> + */
>> +static int spinand_get_address_bits(u8 opcode)
>> +{
>> +    switch (opcode) {
>> +    case SPINAND_CMD_READ_FROM_CACHE_QUAD_IO:
>> +        return 4;
>> +    case SPINAND_CMD_READ_FROM_CACHE_DUAL_IO:
>> +        return 2;
>> +    default:
>> +        return 1;
>> +    }
>> +}
>> +
>> +/**
>> + * spinand_get_data_bits - return data should be transferred by how many bits
>> + * @opcode: command's operation code
>> + */
>> +static int spinand_get_data_bits(u8 opcode)
>> +{
>> +    switch (opcode) {
>> +    case SPINAND_CMD_READ_FROM_CACHE_QUAD_IO:
>> +    case SPINAND_CMD_READ_FROM_CACHE_X4:
>> +    case SPINAND_CMD_PROG_LOAD_X4:
>> +    case SPINAND_CMD_PROG_LOAD_RDM_DATA_X4:
>> +        return 4;
>> +    case SPINAND_CMD_READ_FROM_CACHE_DUAL_IO:
>> +    case SPINAND_CMD_READ_FROM_CACHE_X2:
>> +        return 2;
>> +    default:
>> +        return 1;
>> +    }
>> +}
>> +
>> +/**
>> + * spinand_read_from_cache - read data out from cache register
>> + * @spinand: SPI NAND device structure
>> + * @page_addr: page to read
>> + * @column: the location to read from the cache
>> + * @len: number of bytes to read
>> + * @rbuf: buffer held @len bytes
>> + */
>> +static int spinand_read_from_cache(struct spinand_device *spinand,
>> +                   u32 page_addr, u32 column,
>> +                   size_t len, u8 *rbuf)
>> +{
>> +    struct spinand_op op;
>> +
>> +    spinand_init_op(&op);
>> +    op.cmd = spinand->read_cache_op;
>> +    op.n_addr = 2;
>> +    op.addr[0] = (u8)(column >> 8);
>> +    op.addr[1] = (u8)column;
> 
> Casts are unneeded here.

Yes you are right 
> 
>> +    op.addr_nbits = spinand_get_address_bits(spinand->read_cache_op);
>> +    op.n_rx = len;
>> +    op.rx_buf = rbuf;
>> +    op.data_nbits = spinand_get_data_bits(spinand->read_cache_op);
>> +
>> +    if (spinand->manufacturer.manu->ops->prepare_op)
>> +        spinand->manufacturer.manu->ops->prepare_op(spinand, &op,
>> +                                page_addr, column);
>> +
>> +    return spinand_exec_op(spinand, &op);
>> +}
>> +
>> +/**
>> + * spinand_write_to_cache - write data to cache register
>> + * @spinand: SPI NAND device structure
>> + * @page_addr: page to write
>> + * @column: the location to write to the cache
>> + * @len: number of bytes to write
>> + * @wrbuf: buffer held @len bytes
>> + */
>> +static int spinand_write_to_cache(struct spinand_device *spinand, u32 page_addr,
>> +                  u32 column, size_t len, const u8 *wbuf)
>> +{
>> +    struct spinand_op op;
>> +
>> +    spinand_init_op(&op);
>> +    op.cmd = spinand->write_cache_op;
>> +    op.n_addr = 2;
>> +    op.addr[0] = (u8)(column >> 8);
>> +    op.addr[1] = (u8)column;
>> +    op.addr_nbits = spinand_get_address_bits(spinand->write_cache_op);
>> +    op.n_tx = len;
>> +    op.tx_buf = wbuf;
>> +    op.data_nbits = spinand_get_data_bits(spinand->write_cache_op);
>> +
>> +    if (spinand->manufacturer.manu->ops->prepare_op)
>> +        spinand->manufacturer.manu->ops->prepare_op(spinand, &op,
>> +                                page_addr, column);
>> +
>> +    return spinand_exec_op(spinand, &op);
>> +}
>> +
>> +/**
>> + * spinand_program_execute - send command 10h to write a page from
>> + * cache to the NAND array
>> + * @spinand: SPI NAND device structure
>> + * @page_addr: the physical page location to write the page.
>> + */
>> +static int spinand_program_execute(struct spinand_device *spinand,
>> +                   u32 page_addr)
>> +{
>> +    struct spinand_op op;
>> +
>> +    spinand_init_op(&op);
>> +    op.cmd = SPINAND_CMD_PROG_EXC;
>> +    op.n_addr = 3;
>> +    op.addr[0] = (u8)(page_addr >> 16);
>> +    op.addr[1] = (u8)(page_addr >> 8);
>> +    op.addr[2] = (u8)page_addr;
> 
> You don't need to adjust the number of dummy cycles here?
> 
> The usage of ->prepare_op() is really weird, maybe you should document
> a bit more when it's supposed to be used.
> 
>> +
>> +    return spinand_exec_op(spinand, &op);
>> +}
>> +
> 
> [...]
> 
>> 
>> diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
>> index dd9da71..04ad1dd 100644
>> --- a/include/linux/mtd/spinand.h
>> +++ b/include/linux/mtd/spinand.h
>> @@ -103,11 +103,14 @@ struct spinand_controller_ops {
>>  *          return directly and let others to detect.
>>  * @init: initialize SPI NAND device.
>>  * @cleanup: clean SPI NAND device footprint.
>> + * @prepare_op: prepara read/write operation.
> 
>           ^ prepare
> 
> 
> 
>>  */
>> struct spinand_manufacturer_ops {
>>    bool (*detect)(struct spinand_device *spinand);
>>    int (*init)(struct spinand_device *spinand);
>>    void (*cleanup)(struct spinand_device *spinand);
>> +    void (*prepare_op)(struct spinand_device *spinand,
>> +               struct spinand_op *op, u32 page, u32 column);
> 
> It seems to be here to prepare read/write page operations, so I'd like
> to rename this method ->prepare_page_op() if you don't mind.

I'm ok with the new name 

Thanks 
Peter Pan 
> 
>> };
>> 
>> /**
> 

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 10/15] nand: spi: add basic blocks for infrastructure
  2017-05-29 21:51   ` Boris Brezillon
@ 2017-05-31  7:02     ` Peter Pan 潘栋 (peterpandong)
  0 siblings, 0 replies; 65+ messages in thread
From: Peter Pan 潘栋 (peterpandong) @ 2017-05-31  7:02 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: richard, computersforpeace, arnaud.mouiche, thomas.petazzoni,
	marex, cyrille.pitchen, linux-mtd, peterpansjtu, linshunquan1

Hi Boris,

> On 30 May 2017, at 05:51, Boris Brezillon <boris.brezillon@free-electrons.com> wrote:
> 
> On Wed, 24 May 2017 15:07:06 +0800
> Peter Pan <peterpandong@micron.com> wrote:
> 
>> This is the first commit for spi nand framkework.
> 
>                    ^ framework
> 
>> This commit is to add add basic building blocks
> 
>          is adding basic ...
> 
>> for the SPI NAND infrastructure.
>> 
>> Signed-off-by: Peter Pan <peterpandong@micron.com>
>> ---
> 
> [...]
> 
>> +
>> +/**
>> + * devm_spinand_alloc - [SPI NAND Interface] allocate SPI NAND device instance
> 
> Let's drop those [SPI NAND Interface] specifier. It's pretty obvious
> that this is part of the spi-nand API, since those symbols are exported.

Okay 

> 
>> + * @dev: pointer to device model structure
>> + */
>> +struct spinand_device *devm_spinand_alloc(struct device *dev)
> 
> You can pass a pointer to the nand_controller object driving the
> nand_device here.
> 
>> +{
>> +    struct spinand_device *spinand;
>> +    struct mtd_info *mtd;
>> +
>> +    spinand = devm_kzalloc(dev, sizeof(*spinand), GFP_KERNEL);
>> +    if (!spinand)
>> +        return ERR_PTR(-ENOMEM);
>> +
>> +    spinand_set_of_node(spinand, dev->of_node);
>> +    mutex_init(&spinand->lock);
>> +    spinand->dev = dev;
> 
> Hm, I don't think this is correct. The device here is likely to
> represent the controller not the SPI NAND device. For the generic spi
> nand controller, I agree, it's the same, but, in case you have one
> controller that is attached several spi devices, it's not.

Yes, you are right. I only thought about generic spi bus when I was
writing the code.

> 
> How about putting the struct device pointer in nand_controller and then
> pass the controller to this spinand_alloc() function.

Good solution

> 
>> +    mtd = spinand_to_mtd(spinand);
>> +    mtd->dev.parent = dev;
>> +
>> +    return spinand;
>> +}
>> +EXPORT_SYMBOL_GPL(devm_spinand_alloc);
>> +
>> +/**
>> + * spinand_init - [SPI NAND Interface] initialize the SPI NAND device
>> + * @spinand: SPI NAND device structure
>> + */
>> +int spinand_init(struct spinand_device *spinand)
>> +{
>> +    struct mtd_info *mtd = spinand_to_mtd(spinand);
>> +    struct nand_device *nand = mtd_to_nand(mtd);
>> +    int ret;
>> +
>> +    ret = spinand_detect(spinand);
>> +    if (ret) {
>> +        dev_err(spinand->dev,
>> +            "Detect SPI NAND failed with error %d.\n", ret);
>> +        goto err_out;
> 
>        return ret;
> 
> 
>> +    }
> 
> I'd still prefer to move the detection step out of this _init()
> function even if this implies duplicating the _detect()+_init()
> sequence in all drivers. Maybe you can provide a wrapper called
> spinand_detect_and_init() to do both in one go.

Okay for me 
> 
>> +
>> +    spinand_set_rd_wr_op(spinand);
>> +
>> +    /*
>> +     * Use kzalloc() instead of devm_kzalloc() here, beacause some drivers
>> +     * may use this buffer for DMA access.
>> +     * Memory allocated by devm_ does not guarantee DMA-safe alignment.
>> +     */
>> +    spinand->buf = kzalloc(nand_page_size(nand) +
>> +                   nand_per_page_oobsize(nand),
>> +                   GFP_KERNEL);
>> +    if (!spinand->buf) {
>> +        ret = -ENOMEM;
>> +        goto err_out;
> 
>        return -ENOMEM;
> 
>> +    }
>> +
>> +    spinand->oobbuf = spinand->buf + nand_page_size(nand);
>> +
>> +    ret = spinand_manufacturer_init(spinand);
>> +    if (ret) {
>> +        dev_err(spinand->dev,
>> +            "Manufacurer init SPI NAND failed with err %d.\n",
>> +            ret);
>> +        goto err_free_buf;
>> +    }
>> +
>> +    mtd->name = spinand->name;
>> +    mtd->size = nand_size(nand);
>> +    mtd->erasesize = nand_eraseblock_size(nand);
>> +    mtd->writesize = nand_page_size(nand);
>> +    mtd->writebufsize = mtd->writesize;
>> +    mtd->owner = THIS_MODULE;
>> +    mtd->type = MTD_NANDFLASH;
>> +    mtd->flags = MTD_CAP_NANDFLASH;
>> +    mtd->oobsize = nand_per_page_oobsize(nand);
>> +    /*
>> +     * Right now, we don't support ECC, so let the whole oob
>> +     * area is available for user.
>> +     */
>> +    mtd->oobavail = mtd->oobsize;
>> +
>> +    /* After power up, all blocks are locked, so unlock it here. */
>> +    spinand_lock_block(spinand, BL_ALL_UNLOCKED);
>> +
>> +    return 0;
>> +
>> +err_free_buf:
>> +    kfree(spinand->buf);
>> +err_out:
> 
> You can get rid of err_out.
> 

Okay

Thanks 
Peter Pan 
>> +    return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(spinand_init);
>> +
> 

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 11/15] nand: spi: add basic operations support
  2017-05-31  6:51     ` Peter Pan 潘栋 (peterpandong)
@ 2017-05-31 10:02       ` Boris Brezillon
  2017-06-27 20:15       ` Boris Brezillon
  1 sibling, 0 replies; 65+ messages in thread
From: Boris Brezillon @ 2017-05-31 10:02 UTC (permalink / raw)
  To: Peter Pan 潘栋 (peterpandong)
  Cc: richard, computersforpeace, arnaud.mouiche, thomas.petazzoni,
	marex, cyrille.pitchen, linux-mtd, peterpansjtu, linshunquan1

Hi Peter,

On Wed, 31 May 2017 06:51:34 +0000
Peter Pan 潘栋 (peterpandong) <peterpandong@micron.com> wrote:

> >> +/**
> >> + * spinand_disable_ecc - disable internal ECC
> >> + * @spinand: SPI NAND device structure
> >> + */
> >> +static void spinand_disable_ecc(struct spinand_device *spinand)
> >> +{
> >> +    u8 cfg = 0;
> >> +
> >> +    spinand_get_cfg(spinand, &cfg);
> >> +
> >> +    if ((cfg & CFG_ECC_MASK) == CFG_ECC_ENABLE) {
> >> +        cfg &= ~CFG_ECC_ENABLE;
> >> +        spinand_set_cfg(spinand, cfg);
> >> +    }  
> > 
> > Is this really a generic (manufacturer-agnostic) feature??? I had the
> > feeling that is was only working for Micron. If that's the case, this
> > 'disable-ecc' step should be done in spi/micron.c in a
> > micron_spinand_init() function.  
> 
> As far as I can see, Micron is not the only vendor to disable on die ecc 
> by this way, actually all vendors I know use this .

Hm, ok. I'm a bit skeptical (vendors tend to implement this kind of
feature with vendor specific commands, but maybe it has changed with SPI
NANDs), but I'll trust you on this one. 

> And this series 
> doesn't support on die ecc, so IMO it is necessary to disable it during
> initialization

Actually I was not arguing on the need to disable on-die ECC, just
wasn't sure this should be done in the core. If it's really generic,
then it's fine.

> 
> >   
> >> +}

[...]

> >> 
> >> diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
> >> index dd9da71..04ad1dd 100644
> >> --- a/include/linux/mtd/spinand.h
> >> +++ b/include/linux/mtd/spinand.h
> >> @@ -103,11 +103,14 @@ struct spinand_controller_ops {
> >>  *          return directly and let others to detect.
> >>  * @init: initialize SPI NAND device.
> >>  * @cleanup: clean SPI NAND device footprint.
> >> + * @prepare_op: prepara read/write operation.  
> > 
> >           ^ prepare
> > 
> > 
> >   
> >>  */
> >> struct spinand_manufacturer_ops {
> >>    bool (*detect)(struct spinand_device *spinand);
> >>    int (*init)(struct spinand_device *spinand);
> >>    void (*cleanup)(struct spinand_device *spinand);
> >> +    void (*prepare_op)(struct spinand_device *spinand,
> >> +               struct spinand_op *op, u32 page, u32 column);  
> > 
> > It seems to be here to prepare read/write page operations, so I'd like
> > to rename this method ->prepare_page_op() if you don't mind.  
> 
> I'm ok with the new name

Actually, in the mean time I asked Cyrille how dummy cycles were
handled in the spi-nor subsystem and how spi flash controllers are
dealing with such dummy cycles. It seems that some controllers are able
to handle those dummy cycles on their own (without any software
intervention to skip bits or move things around in output bufs.

I'll let Cyrille comment on this specific aspect, but I wonder if we
shouldn't just specify the number of dummy cycles and let the
controller handle that.

Regards,

Boris

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 10/15] nand: spi: add basic blocks for infrastructure
  2017-05-24  7:07 ` [PATCH v6 10/15] nand: spi: add basic blocks for infrastructure Peter Pan
  2017-05-29 21:51   ` Boris Brezillon
@ 2017-05-31 21:45   ` Cyrille Pitchen
  2017-06-01  7:24     ` Boris Brezillon
  1 sibling, 1 reply; 65+ messages in thread
From: Cyrille Pitchen @ 2017-05-31 21:45 UTC (permalink / raw)
  To: Peter Pan, boris.brezillon, richard, computersforpeace,
	arnaud.mouiche, thomas.petazzoni, marex, linux-mtd
  Cc: peterpansjtu, linshunquan1

Hi Peter,

Le 24/05/2017 à 09:07, Peter Pan a écrit :
> This is the first commit for spi nand framkework.
> This commit is to add add basic building blocks
> for the SPI NAND infrastructure.
> 
> Signed-off-by: Peter Pan <peterpandong@micron.com>
> ---
>  drivers/mtd/nand/Kconfig      |   1 +
>  drivers/mtd/nand/Makefile     |   1 +
>  drivers/mtd/nand/spi/Kconfig  |   5 +
>  drivers/mtd/nand/spi/Makefile |   1 +
>  drivers/mtd/nand/spi/core.c   | 419 ++++++++++++++++++++++++++++++++++++++++++
>  include/linux/mtd/spinand.h   | 267 +++++++++++++++++++++++++++
>  6 files changed, 694 insertions(+)
>  create mode 100644 drivers/mtd/nand/spi/Kconfig
>  create mode 100644 drivers/mtd/nand/spi/Makefile
>  create mode 100644 drivers/mtd/nand/spi/core.c
>  create mode 100644 include/linux/mtd/spinand.h
> 
[...]
> diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
> new file mode 100644
> index 0000000..dd9da71
> --- /dev/null
> +++ b/include/linux/mtd/spinand.h
> @@ -0,0 +1,267 @@
[...]
> +#define SPINAND_MAX_ADDR_LEN	4
> +
> +/**
> + * struct spinand_op - SPI NAND operation description
> + * @cmd: opcode to send
> + * @n_addr: address bytes
> + * @addr_nbits: number of bit used to transfer address
> + * @dummy_types: dummy bytes followed address
> + * @addr: buffer held address
> + * @n_tx: size of tx_buf
> + * @tx_buf: data to be written
> + * @n_rx: size of rx_buf
> + * @rx_buf: data to be read
> + * @data_nbits: number of bit used to transfer data
> + */
> +struct spinand_op {
> +	u8 cmd;
> +	u8 n_addr;
> +	u8 addr_nbits;
> +	u8 dummy_bytes;
> +	u8 addr[SPINAND_MAX_ADDR_LEN];

I think it would be better to use some integral type (maybe loff_t)
rather than an array of u8. Indeed integers are better suited to some
(Q)SPI controllers, especially those using some kind of memory area
mapped into the system bus.

For other SPI controllers, it would still be easy to build an array of
u8 if needed from a loff_t.


> +	u32 n_tx;
> +	const u8 *tx_buf;
> +	u32 n_rx;

just a detail but n_tx and n_rx could be merged into a single n_buf:
- at the spi-nor side, tx_buf and rx_buf can never be both != NULL
- at the spi-nand side, looking at the gen_spi_spinand_exec_op()
  function, this is still true.

> +	u8 *rx_buf;
> +	u8 data_nbits;
> +};

Besides, this structure is really close to
'struct spi_flash_read_message' from include/spi/spi.h.
So I think it would be interesting to rework a little bit the structure
from the SPI sub-system so it can fit your needs and support all kind of
SPI flash commands, not only read commands.
Then this structure could be used by both the spi-nand and spi-nor
sub-systems.

Hence 'struct spi_flash_read_message' could be renamed into 'struct
spi_flash_message', 'struct spi_flash_op' 'struct spi_flash_command' or
whatever... as long as we just remove the "read" part.

In the reworked structure, I propose to add some enum or flags to
provide the SPI controller with the kind of SPI flash command we want it
to execute, actually a SPI flash command type:
- SFLASH_TYPE_READ:  (Fast) Read (spi-nor) / Read From Cache (spi-nand)
- SFLASH_TYPE_WRITE:  Page Program (spi-nor) or Program Load (spi-nand)
- SFLASH_TYPE_ERASE: Sector/Block Erase
- SFLASH_TYPE_READ_REG: Read ID, Read Status, Page Read, ...
- SFLASH_TYPE_WRITE_REG: Write Enable, Write Status, ...

Based on my experience with SPI NOR memories, it's not reliable to guess
the type of the SPI flash command only from its instruction op code:
most of the instruction op codes are pretty standard but *really* often
many SPI flash manufacturers have their own quirks and use different and
unexpected op codes...

So providing the type of SPI flash command would clarify and allow the
(Q)SPI controller driver to tell the spi-nand/spi-nor frameworks whether
this SPI flash command is supported by spi_flash_command_exec() / exec_op().

That's why I suggest to add 2 new optional handlers in 'struct
spi_master' from the SPI sub-system:

bool (*spi_flash_is_command_supported)(struct spi_device *spi,
				       const struct spi_flash_command *)

and

int (*spi_flash_command_exec)(struct spi_device *spi,
			      const struct spi_flash_command *cmd);

For some (Q)SPI controllers, like those from Cadence and TI I guess,
spi_flash_is_command_supported() is likely to return true only for a SPI
flash command type of SFLASH_TYPE_READ.

Other (Q)SPI controllers, like the one from Atmel, would return true for
any command. Indeed, the regular spi_sync() API based on
'struct spi_message' and 'struct spi_transfer' is not suited at all for
the Atmel QSPI controller.

If spi_flash_is_command_supported() returns false or is not implemented
by the SPI controller driver, then you can use a default implementation
based on spi_sync(), actually the one you propose through your
gen_spi_spinand_exec_op() function.

The idea behind that is, in term, to replace the current
flash_read_supported() / spi_flash_read() functions by the more generic
spi_flash_is_command_supported() / spi_flash_command_exec().
We just want to extend the already existing SPI API to support more SPI
flash commands than the only (Fast) Read commands.

Also, if done at the SPI sub-system side, this API could be used by both
the spi-nand and spi-nor sub-systems, then we could imagine moving some
(Q)SPI controller drivers, like drivers/mtd/spi-nor/atmel-quadspi.c,
back into the SPI sub-system, where they should belong.

Currently, the Atmel QSPI driver dwells in the spi-nor sub-system simply
because, as I said, the spi-sync() API is not suited at all for the
hardware register interface. However with the proper SPI API, this
controller could also be used with SPI NAND memories.

Best regards,

Cyrille

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 10/15] nand: spi: add basic blocks for infrastructure
  2017-05-31 21:45   ` Cyrille Pitchen
@ 2017-06-01  7:24     ` Boris Brezillon
  0 siblings, 0 replies; 65+ messages in thread
From: Boris Brezillon @ 2017-06-01  7:24 UTC (permalink / raw)
  To: Cyrille Pitchen
  Cc: Peter Pan, richard, computersforpeace, arnaud.mouiche,
	thomas.petazzoni, marex, linux-mtd, peterpansjtu, linshunquan1

Hi Cyrille,

Le Wed, 31 May 2017 23:45:55 +0200,
Cyrille Pitchen <cyrille.pitchen@wedev4u.fr> a écrit :

> Hi Peter,
> 
> Le 24/05/2017 à 09:07, Peter Pan a écrit :
> > This is the first commit for spi nand framkework.
> > This commit is to add add basic building blocks
> > for the SPI NAND infrastructure.
> > 
> > Signed-off-by: Peter Pan <peterpandong@micron.com>
> > ---
> >  drivers/mtd/nand/Kconfig      |   1 +
> >  drivers/mtd/nand/Makefile     |   1 +
> >  drivers/mtd/nand/spi/Kconfig  |   5 +
> >  drivers/mtd/nand/spi/Makefile |   1 +
> >  drivers/mtd/nand/spi/core.c   | 419 ++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/mtd/spinand.h   | 267 +++++++++++++++++++++++++++
> >  6 files changed, 694 insertions(+)
> >  create mode 100644 drivers/mtd/nand/spi/Kconfig
> >  create mode 100644 drivers/mtd/nand/spi/Makefile
> >  create mode 100644 drivers/mtd/nand/spi/core.c
> >  create mode 100644 include/linux/mtd/spinand.h
> >   
> [...]
> > diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
> > new file mode 100644
> > index 0000000..dd9da71
> > --- /dev/null
> > +++ b/include/linux/mtd/spinand.h
> > @@ -0,0 +1,267 @@  
> [...]
> > +#define SPINAND_MAX_ADDR_LEN	4
> > +
> > +/**
> > + * struct spinand_op - SPI NAND operation description
> > + * @cmd: opcode to send
> > + * @n_addr: address bytes
> > + * @addr_nbits: number of bit used to transfer address
> > + * @dummy_types: dummy bytes followed address
> > + * @addr: buffer held address
> > + * @n_tx: size of tx_buf
> > + * @tx_buf: data to be written
> > + * @n_rx: size of rx_buf
> > + * @rx_buf: data to be read
> > + * @data_nbits: number of bit used to transfer data
> > + */
> > +struct spinand_op {
> > +	u8 cmd;
> > +	u8 n_addr;
> > +	u8 addr_nbits;
> > +	u8 dummy_bytes;
> > +	u8 addr[SPINAND_MAX_ADDR_LEN];  
> 
> I think it would be better to use some integral type (maybe loff_t)
> rather than an array of u8. Indeed integers are better suited to some
> (Q)SPI controllers, especially those using some kind of memory area
> mapped into the system bus.

I had a look at at least 2 SPI NAND datasheets and they all express the
number of addr cycles in bytes. I really think we should stay as
close as possible to the specs even if this implies a small penalty for
some controller drivers. BTW, I could argue that some controllers are
expecting an array of bytes and not an integer :-P. 

> 
> For other SPI controllers, it would still be easy to build an array of
> u8 if needed from a loff_t.

Just as easy as creating an loff_t from an array of bytes ;-).

> 
> 
> > +	u32 n_tx;
> > +	const u8 *tx_buf;
> > +	u32 n_rx;  
> 
> just a detail but n_tx and n_rx could be merged into a single n_buf:
> - at the spi-nor side, tx_buf and rx_buf can never be both != NULL
> - at the spi-nand side, looking at the gen_spi_spinand_exec_op()
>   function, this is still true.

Indeed. How about having a union to still enforce constness on the tx
buf and an extra variable to specify the direction.

	union {
		const u8 *tx;
		u8 *rx;
	} buf;

	u32 datalen;
	enum spinand_data_dir datadir;

> 
> > +	u8 *rx_buf;
> > +	u8 data_nbits;
> > +};
> 
> Besides, this structure is really close to
> 'struct spi_flash_read_message' from include/spi/spi.h.
> So I think it would be interesting to rework a little bit the structure
> from the SPI sub-system so it can fit your needs and support all kind of
> SPI flash commands, not only read commands.
> Then this structure could be used by both the spi-nand and spi-nor
> sub-systems.

I like this idea, but I'd like to get the SPI NAND framework merge
first. Peter has been working on this for several years and I think
it's time to get it merged even if it's not perfect. We can still
improve things afterwards.

> 
> Hence 'struct spi_flash_read_message' could be renamed into 'struct
> spi_flash_message', 'struct spi_flash_op' 'struct spi_flash_command' or
> whatever... as long as we just remove the "read" part.
> 
> In the reworked structure, I propose to add some enum or flags to
> provide the SPI controller with the kind of SPI flash command we want it
> to execute, actually a SPI flash command type:
> - SFLASH_TYPE_READ:  (Fast) Read (spi-nor) / Read From Cache (spi-nand)
> - SFLASH_TYPE_WRITE:  Page Program (spi-nor) or Program Load (spi-nand)
> - SFLASH_TYPE_ERASE: Sector/Block Erase
> - SFLASH_TYPE_READ_REG: Read ID, Read Status, Page Read, ...
> - SFLASH_TYPE_WRITE_REG: Write Enable, Write Status, ...

Why is this needed? The opcode[+addr-cycles][+data-cycles] sequence
should be enough.

> 
> Based on my experience with SPI NOR memories, it's not reliable to guess
> the type of the SPI flash command only from its instruction op code:
> most of the instruction op codes are pretty standard but *really* often
> many SPI flash manufacturers have their own quirks and use different and
> unexpected op codes...

SPI controllers (even if they're QSPI/flash oriented) should be able to
send any kind of command. A command (or operation) is a specific
sequence of opcode[+addr-cycles][+data-cycles].

Vendors can have their own private commands or even decide to adapt
the standard command sequence, but that's all flash specific, and the
controller code should not be impacted here. All the controller needs
to know is the sequence it's supposed to execute, and that's all.

> 
> So providing the type of SPI flash command would clarify and allow the
> (Q)SPI controller driver to tell the spi-nand/spi-nor frameworks whether
> this SPI flash command is supported by spi_flash_command_exec() / exec_op().
> 
> That's why I suggest to add 2 new optional handlers in 'struct
> spi_master' from the SPI sub-system:
> 
> bool (*spi_flash_is_command_supported)(struct spi_device *spi,
> 				       const struct spi_flash_command *)
> 
> and
> 
> int (*spi_flash_command_exec)(struct spi_device *spi,
> 			      const struct spi_flash_command *cmd);

I agree on this.

> 
> For some (Q)SPI controllers, like those from Cadence and TI I guess,
> spi_flash_is_command_supported() is likely to return true only for a SPI
> flash command type of SFLASH_TYPE_READ.

But why do you need those high-level definitions? With the full
sequence (including the datalen+datadir) + the number of lines
(quad/dual/single), you should be able to know whether the controller
supports the command/operation or not.

> 
> Other (Q)SPI controllers, like the one from Atmel, would return true for
> any command. Indeed, the regular spi_sync() API based on
> 'struct spi_message' and 'struct spi_transfer' is not suited at all for
> the Atmel QSPI controller.
> 
> If spi_flash_is_command_supported() returns false or is not implemented
> by the SPI controller driver, then you can use a default implementation
> based on spi_sync(), actually the one you propose through your
> gen_spi_spinand_exec_op() function.

I'm not sure I understand the purpose of
->spi_flash_is_command_supported() anymore. Is this about reporting
when the controller can optimize things, and if it returns false the
framework falls back to the less optimized spi_sync() approach, or is
this here to say 'no, I can't send this command, you should return
-ENOTSUPP to the caller'.

AFAICT, if you can fallback to spi_sync() that means you support all
commands except those that require Quad or Dual mode. Am I wrong?

> 
> The idea behind that is, in term, to replace the current
> flash_read_supported() / spi_flash_read() functions by the more generic
> spi_flash_is_command_supported() / spi_flash_command_exec().
> We just want to extend the already existing SPI API to support more SPI
> flash commands than the only (Fast) Read commands.
> 
> Also, if done at the SPI sub-system side, this API could be used by both
> the spi-nand and spi-nor sub-systems, then we could imagine moving some
> (Q)SPI controller drivers, like drivers/mtd/spi-nor/atmel-quadspi.c,
> back into the SPI sub-system, where they should belong.
> 
> Currently, the Atmel QSPI driver dwells in the spi-nor sub-system simply
> because, as I said, the spi-sync() API is not suited at all for the
> hardware register interface. However with the proper SPI API, this
> controller could also be used with SPI NAND memories.

Your solution sounds promising, but I'm focusing on short-term
solutions. I think we'll keep going with the current implementation
(with only minor modifications) and see how things evolve. Once your
generic solution is ready it should be pretty easy to adapt the
spi-nand framework.

Thanks for your inputs.

BTW, you didn't answer my questions on dummy-bits in address cycles,
but I think I got my answers by reading the datasheets ;-).

Boris

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 11/15] nand: spi: add basic operations support
  2017-05-31  6:51     ` Peter Pan 潘栋 (peterpandong)
  2017-05-31 10:02       ` Boris Brezillon
@ 2017-06-27 20:15       ` Boris Brezillon
  2017-06-28  9:41         ` Arnaud Mouiche
  2017-06-29  6:07         ` Peter Pan 潘栋 (peterpandong)
  1 sibling, 2 replies; 65+ messages in thread
From: Boris Brezillon @ 2017-06-27 20:15 UTC (permalink / raw)
  To: Peter Pan 潘栋 (peterpandong)
  Cc: richard, computersforpeace, arnaud.mouiche, thomas.petazzoni,
	marex, cyrille.pitchen, linux-mtd, peterpansjtu, linshunquan1

   
> >> 
> >> diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
> >> index dd9da71..04ad1dd 100644
> >> --- a/include/linux/mtd/spinand.h
> >> +++ b/include/linux/mtd/spinand.h
> >> @@ -103,11 +103,14 @@ struct spinand_controller_ops {
> >>  *          return directly and let others to detect.
> >>  * @init: initialize SPI NAND device.
> >>  * @cleanup: clean SPI NAND device footprint.
> >> + * @prepare_op: prepara read/write operation.  
> > 
> >           ^ prepare
> > 
> > 
> >   
> >>  */
> >> struct spinand_manufacturer_ops {
> >>    bool (*detect)(struct spinand_device *spinand);
> >>    int (*init)(struct spinand_device *spinand);
> >>    void (*cleanup)(struct spinand_device *spinand);
> >> +    void (*prepare_op)(struct spinand_device *spinand,
> >> +               struct spinand_op *op, u32 page, u32 column);  
> > 
> > It seems to be here to prepare read/write page operations, so I'd like
> > to rename this method ->prepare_page_op() if you don't mind.  
> 
> I'm ok with the new name

Hm, actually I wonder if this ->prepare_op() method is really what we
want. It seems to be here to set the proper plane number and the
number of dummy bytes after the address cycles.
I'd say deducing the plane from the page is something standard. Whether
we need it or not depends on the information provide in the memorg
object (->nplanes).

Regarding the dummy byte, do you have examples of SPI NANDs requiring
less or more dummy bytes in this read/write from/to cache use case?
If not, I'd prefer to keep it hardcoded in the core for know, and add
a hook when the need appears.

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 11/15] nand: spi: add basic operations support
  2017-06-27 20:15       ` Boris Brezillon
@ 2017-06-28  9:41         ` Arnaud Mouiche
  2017-06-28 11:32           ` Boris Brezillon
  2017-06-29  5:45           ` Peter Pan 潘栋 (peterpandong)
  2017-06-29  6:07         ` Peter Pan 潘栋 (peterpandong)
  1 sibling, 2 replies; 65+ messages in thread
From: Arnaud Mouiche @ 2017-06-28  9:41 UTC (permalink / raw)
  To: Boris Brezillon, Peter Pan 潘栋 (peterpandong)
  Cc: richard, computersforpeace, thomas.petazzoni, marex,
	cyrille.pitchen, linux-mtd, peterpansjtu, linshunquan1

Hello Boris,

On 27/06/2017 22:15, Boris Brezillon wrote:
>    
> Hm, actually I wonder if this ->prepare_op() method is really what we
> want. It seems to be here to set the proper plane number and the
> number of dummy bytes after the address cycles.
> I'd say deducing the plane from the page is something standard. Whether
> we need it or not depends on the information provide in the memorg
> object (->nplanes).
>
> Regarding the dummy byte, do you have examples of SPI NANDs requiring
> less or more dummy bytes in this read/write from/to cache use case?
> If not, I'd prefer to keep it hardcoded in the core for know, and add
> a hook when the need appears.
Here is the page read description for various devices I have:

MT29FxG01AAADD
- fetch to internal: CMD_READ (0x13) + (3 bytes page_id)
- read from internal: CMD_READ_RDM (0x03) + (2 bytes address + pane 
selection @ bit 12) + 1 dummy byte

GD5FxxQ4xC
- fetch to internal: CMD_READ (0x13) + (3 bytes page_id)
- read from internal: CMD_FAST_READ (0x0B) + 1 dummy byte + (2 bytes 
address) + 1 dummy byte

MX35LFxGE4AB
F50L1G41A
W25N01GVZEIG
- fetch to internal: CMD_READ (0x13) + (3 bytes page_id)
- read from internal: CMD_READ_RDM (0x03) + (2 bytes address) + 1 dummy byte

But you are right. It's time to have an adopted implementation for 
Micron as proposed by Peter, and we will adapt it later for others.

Arnaud

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 11/15] nand: spi: add basic operations support
  2017-06-28  9:41         ` Arnaud Mouiche
@ 2017-06-28 11:32           ` Boris Brezillon
  2017-06-29  5:45           ` Peter Pan 潘栋 (peterpandong)
  1 sibling, 0 replies; 65+ messages in thread
From: Boris Brezillon @ 2017-06-28 11:32 UTC (permalink / raw)
  To: Arnaud Mouiche
  Cc: Peter Pan 潘栋 (peterpandong),
	richard, computersforpeace, thomas.petazzoni, marex,
	cyrille.pitchen, linux-mtd, peterpansjtu, linshunquan1

Le Wed, 28 Jun 2017 11:41:03 +0200,
Arnaud Mouiche <arnaud.mouiche@gmail.com> a écrit :

> Hello Boris,
> 
> On 27/06/2017 22:15, Boris Brezillon wrote:
> >    
> > Hm, actually I wonder if this ->prepare_op() method is really what we
> > want. It seems to be here to set the proper plane number and the
> > number of dummy bytes after the address cycles.
> > I'd say deducing the plane from the page is something standard. Whether
> > we need it or not depends on the information provide in the memorg
> > object (->nplanes).
> >
> > Regarding the dummy byte, do you have examples of SPI NANDs requiring
> > less or more dummy bytes in this read/write from/to cache use case?
> > If not, I'd prefer to keep it hardcoded in the core for know, and add
> > a hook when the need appears.  
> Here is the page read description for various devices I have:
> 
> MT29FxG01AAADD
> - fetch to internal: CMD_READ (0x13) + (3 bytes page_id)
> - read from internal: CMD_READ_RDM (0x03) + (2 bytes address + pane 
> selection @ bit 12) + 1 dummy byte
> 
> GD5FxxQ4xC
> - fetch to internal: CMD_READ (0x13) + (3 bytes page_id)
> - read from internal: CMD_FAST_READ (0x0B) + 1 dummy byte + (2 bytes 
> address) + 1 dummy byte

Ok, so this is the one causing trouble :-). That's a good reason for
making the read-from-internal (or read-from-cache) operation
customizable.

> 
> MX35LFxGE4AB
> F50L1G41A
> W25N01GVZEIG
> - fetch to internal: CMD_READ (0x13) + (3 bytes page_id)
> - read from internal: CMD_READ_RDM (0x03) + (2 bytes address) + 1 dummy byte

Hm, I guess those NANDs only have one plane, so it should be compatible
with the MT29Fx logic.

> 
> But you are right. It's time to have an adopted implementation for 
> Micron as proposed by Peter, and we will adapt it later for others.

Ok.

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 11/15] nand: spi: add basic operations support
  2017-06-28  9:41         ` Arnaud Mouiche
  2017-06-28 11:32           ` Boris Brezillon
@ 2017-06-29  5:45           ` Peter Pan 潘栋 (peterpandong)
  1 sibling, 0 replies; 65+ messages in thread
From: Peter Pan 潘栋 (peterpandong) @ 2017-06-29  5:45 UTC (permalink / raw)
  To: Arnaud Mouiche
  Cc: Boris Brezillon, richard, computersforpeace, thomas.petazzoni,
	marex, cyrille.pitchen, linux-mtd, peterpansjtu, linshunquan1

Hi Arnaud,

> 在 2017年6月28日,17:48,Arnaud Mouiche <arnaud.mouiche@gmail.com> 写道:
> 
> Hello Boris,
> 
>> On 27/06/2017 22:15, Boris Brezillon wrote:
>>   Hm, actually I wonder if this ->prepare_op() method is really what we
>> want. It seems to be here to set the proper plane number and the
>> number of dummy bytes after the address cycles.
>> I'd say deducing the plane from the page is something standard. Whether
>> we need it or not depends on the information provide in the memorg
>> object (->nplanes).
>> 
>> Regarding the dummy byte, do you have examples of SPI NANDs requiring
>> less or more dummy bytes in this read/write from/to cache use case?
>> If not, I'd prefer to keep it hardcoded in the core for know, and add
>> a hook when the need appears.
> Here is the page read description for various devices I have:
> 
> MT29FxG01AAADD
> - fetch to internal: CMD_READ (0x13) + (3 bytes page_id)
> - read from internal: CMD_READ_RDM (0x03) + (2 bytes address + pane selection @ bit 12) + 1 dummy byte
> 
> GD5FxxQ4xC
> - fetch to internal: CMD_READ (0x13) + (3 bytes page_id)
> - read from internal: CMD_FAST_READ (0x0B) + 1 dummy byte + (2 bytes address) + 1 dummy byte
> 
> MX35LFxGE4AB
> F50L1G41A
> W25N01GVZEIG
> - fetch to internal: CMD_READ (0x13) + (3 bytes page_id)
> - read from internal: CMD_READ_RDM (0x03) + (2 bytes address) + 1 dummy byte
> 

You have much more information than me:) thanks for the sharing.

Thanks
Peter Pan

> But you are right. It's time to have an adopted implementation for Micron as proposed by Peter, and we will adapt it later for others.
> 
> Arnaud

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 11/15] nand: spi: add basic operations support
  2017-06-27 20:15       ` Boris Brezillon
  2017-06-28  9:41         ` Arnaud Mouiche
@ 2017-06-29  6:07         ` Peter Pan 潘栋 (peterpandong)
  2017-06-29  7:05           ` Arnaud Mouiche
  1 sibling, 1 reply; 65+ messages in thread
From: Peter Pan 潘栋 (peterpandong) @ 2017-06-29  6:07 UTC (permalink / raw)
  To: Boris Brezillon, Arnaud Mouiche
  Cc: richard, computersforpeace, thomas.petazzoni, marex,
	cyrille.pitchen, linux-mtd, peterpansjtu, linshunquan1

Hi Boris,

> 在 2017年6月28日,04:16,Boris Brezillon <boris.brezillon@free-electrons.com> 写道:
> 
> 
>>>> 
>>>> diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
>>>> index dd9da71..04ad1dd 100644
>>>> --- a/include/linux/mtd/spinand.h
>>>> +++ b/include/linux/mtd/spinand.h
>>>> @@ -103,11 +103,14 @@ struct spinand_controller_ops {
>>>> *          return directly and let others to detect.
>>>> * @init: initialize SPI NAND device.
>>>> * @cleanup: clean SPI NAND device footprint.
>>>> + * @prepare_op: prepara read/write operation.  
>>> 
>>>          ^ prepare
>>> 
>>> 
>>> 
>>>> */
>>>> struct spinand_manufacturer_ops {
>>>>   bool (*detect)(struct spinand_device *spinand);
>>>>   int (*init)(struct spinand_device *spinand);
>>>>   void (*cleanup)(struct spinand_device *spinand);
>>>> +    void (*prepare_op)(struct spinand_device *spinand,
>>>> +               struct spinand_op *op, u32 page, u32 column);  
>>> 
>>> It seems to be here to prepare read/write page operations, so I'd like
>>> to rename this method ->prepare_page_op() if you don't mind.  
>> 
>> I'm ok with the new name
> 
> Hm, actually I wonder if this ->prepare_op() method is really what we
> want. It seems to be here to set the proper plane number and the
> number of dummy bytes after the address cycles.
> I'd say deducing the plane from the page is something standard. Whether
> we need it or not depends on the information provide in the memorg
> object (->nplanes).

For Micron spi nand, it's true. But I don't know whether other vendors'
spi nand need set plane number when the chip has more than one
planes. The reason Micron spi nand need to set plane number is
internal cache register is per plane.

Arnaud,
Do you have info about this?

Thanks 
Peter Pan 

> 
> Regarding the dummy byte, do you have examples of SPI NANDs requiring
> less or more dummy bytes in this read/write from/to cache use case?
> If not, I'd prefer to keep it hardcoded in the core for know, and add
> a hook when the need appears.

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 11/15] nand: spi: add basic operations support
  2017-06-29  6:07         ` Peter Pan 潘栋 (peterpandong)
@ 2017-06-29  7:05           ` Arnaud Mouiche
  0 siblings, 0 replies; 65+ messages in thread
From: Arnaud Mouiche @ 2017-06-29  7:05 UTC (permalink / raw)
  To: Peter Pan 潘栋 (peterpandong), Boris Brezillon
  Cc: richard, computersforpeace, thomas.petazzoni, marex,
	cyrille.pitchen, linux-mtd, peterpansjtu, linshunquan1



On 29/06/2017 08:07, Peter Pan 潘栋 (peterpandong) wrote:
> Hi Boris,
>
>> 在 2017年6月28日,04:16,Boris Brezillon <boris.brezillon@free-electrons.com> 写道:
>>
>>
>>>>> diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
>>>>> index dd9da71..04ad1dd 100644
>>>>> --- a/include/linux/mtd/spinand.h
>>>>> +++ b/include/linux/mtd/spinand.h
>>>>> @@ -103,11 +103,14 @@ struct spinand_controller_ops {
>>>>> *          return directly and let others to detect.
>>>>> * @init: initialize SPI NAND device.
>>>>> * @cleanup: clean SPI NAND device footprint.
>>>>> + * @prepare_op: prepara read/write operation.
>>>>           ^ prepare
>>>>
>>>>
>>>>
>>>>> */
>>>>> struct spinand_manufacturer_ops {
>>>>>    bool (*detect)(struct spinand_device *spinand);
>>>>>    int (*init)(struct spinand_device *spinand);
>>>>>    void (*cleanup)(struct spinand_device *spinand);
>>>>> +    void (*prepare_op)(struct spinand_device *spinand,
>>>>> +               struct spinand_op *op, u32 page, u32 column);
>>>> It seems to be here to prepare read/write page operations, so I'd like
>>>> to rename this method ->prepare_page_op() if you don't mind.
>>> I'm ok with the new name
>> Hm, actually I wonder if this ->prepare_op() method is really what we
>> want. It seems to be here to set the proper plane number and the
>> number of dummy bytes after the address cycles.
>> I'd say deducing the plane from the page is something standard. Whether
>> we need it or not depends on the information provide in the memorg
>> object (->nplanes).
> For Micron spi nand, it's true. But I don't know whether other vendors'
> spi nand need set plane number when the chip has more than one
> planes. The reason Micron spi nand need to set plane number is
> internal cache register is per plane.
>
> Arnaud,
> Do you have info about this?
I don't know the internals, only the user side.
Up to now, Micron is the only one requiring a "pane bit" in the offset 
address.
Arnaud
>
> Thanks
> Peter Pan
>
>> Regarding the dummy byte, do you have examples of SPI NANDs requiring
>> less or more dummy bytes in this read/write from/to cache use case?
>> If not, I'd prefer to keep it hardcoded in the core for know, and add
>> a hook when the need appears.

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 11/15] nand: spi: add basic operations support
  2017-05-24  7:07 ` [PATCH v6 11/15] nand: spi: add basic operations support Peter Pan
  2017-05-29 22:11   ` Boris Brezillon
@ 2017-10-11 13:35   ` Boris Brezillon
  2017-10-12  1:28     ` Peter Pan
  1 sibling, 1 reply; 65+ messages in thread
From: Boris Brezillon @ 2017-10-11 13:35 UTC (permalink / raw)
  To: Peter Pan
  Cc: richard, computersforpeace, arnaud.mouiche, thomas.petazzoni,
	marex, cyrille.pitchen, linux-mtd, peterpansjtu, linshunquan1

Hi Peter,

I'm resurrecting this series, and I still have on question on this
patch (probably not my last question ;-)).

On Wed, 24 May 2017 15:07:07 +0800
Peter Pan <peterpandong@micron.com> wrote:



> +/**
> + * spinand_do_write_ops - write data from buffer to device
> + * @mtd: MTD device structure
> + * @to: offset to write to
> + * @ops: oob operations description structure
> + */
> +static int spinand_do_write_ops(struct mtd_info *mtd, loff_t to,
> +				struct mtd_oob_ops *ops)
> +{
> +	struct spinand_device *spinand = mtd_to_spinand(mtd);
> +	struct nand_device *nand = mtd_to_nand(mtd);
> +	int ret = 0;
> +
> +	ret = nand_check_address(nand, to);
> +	if (ret) {
> +		dev_err(spinand->dev, "%s: invalid write address\n", __func__);
> +		return ret;
> +	}
> +
> +	ret = nand_check_oob_ops(nand, to, ops);
> +	if (ret) {
> +		dev_err(spinand->dev,
> +			"%s: invalid oob operation input\n", __func__);
> +		return ret;
> +	}
> +
> +	if (nand_oob_ops_across_page(mtd_to_nand(mtd), ops)) {
> +		dev_err(spinand->dev,
> +			"%s: try to across page when writing with OOB\n",
> +			__func__);
> +		return -EINVAL;
> +	}

Why do you prevent writing more than one OOB region?

> +
> +	mutex_lock(&spinand->lock);
> +	ret = spinand_write_pages(mtd, to, ops);
> +	mutex_unlock(&spinand->lock);
> +
> +	return ret;
> +}

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 11/15] nand: spi: add basic operations support
  2017-10-11 13:35   ` Boris Brezillon
@ 2017-10-12  1:28     ` Peter Pan
  0 siblings, 0 replies; 65+ messages in thread
From: Peter Pan @ 2017-10-12  1:28 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Peter Pan, Richard Weinberger, Brian Norris, Arnaud Mouiche,
	Thomas Petazzoni, Marek Vasut, Cyrille Pitchen, linux-mtd,
	linshunquan (A)

Hi Boris,

On Wed, Oct 11, 2017 at 9:35 PM, Boris Brezillon
<boris.brezillon@free-electrons.com> wrote:
> Hi Peter,
>
> I'm resurrecting this series, and I still have on question on this
> patch (probably not my last question ;-)).

Please feel free to comment on it. :)

>
> On Wed, 24 May 2017 15:07:07 +0800
> Peter Pan <peterpandong@micron.com> wrote:
>
>
>
>> +/**
>> + * spinand_do_write_ops - write data from buffer to device
>> + * @mtd: MTD device structure
>> + * @to: offset to write to
>> + * @ops: oob operations description structure
>> + */
>> +static int spinand_do_write_ops(struct mtd_info *mtd, loff_t to,
>> +                             struct mtd_oob_ops *ops)
>> +{
>> +     struct spinand_device *spinand = mtd_to_spinand(mtd);
>> +     struct nand_device *nand = mtd_to_nand(mtd);
>> +     int ret = 0;
>> +
>> +     ret = nand_check_address(nand, to);
>> +     if (ret) {
>> +             dev_err(spinand->dev, "%s: invalid write address\n", __func__);
>> +             return ret;
>> +     }
>> +
>> +     ret = nand_check_oob_ops(nand, to, ops);
>> +     if (ret) {
>> +             dev_err(spinand->dev,
>> +                     "%s: invalid oob operation input\n", __func__);
>> +             return ret;
>> +     }
>> +
>> +     if (nand_oob_ops_across_page(mtd_to_nand(mtd), ops)) {
>> +             dev_err(spinand->dev,
>> +                     "%s: try to across page when writing with OOB\n",
>> +                     __func__);
>> +             return -EINVAL;
>> +     }
>
> Why do you prevent writing more than one OOB region?

Well, actually this is not my original intention. If we remove the across page
check, the mtd_oobtest.ko will failed in "write past end of device" test. And
I checked nand_base.c, I found that nand_do_write_oob() had this check.

An interesting thing is in part_read_oob() we have check for "read pass the
end of partition" while in part_write_oob() we don't have. I don't
know the history
so I just followed raw NAND code.

Thanks

Peter Pan

>
>> +
>> +     mutex_lock(&spinand->lock);
>> +     ret = spinand_write_pages(mtd, to, ops);
>> +     mutex_unlock(&spinand->lock);
>> +
>> +     return ret;
>> +}

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-05-29 20:59 ` [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Boris Brezillon
@ 2017-12-04 13:32   ` Frieder Schrempf
  2017-12-04 14:05     ` Boris Brezillon
  0 siblings, 1 reply; 65+ messages in thread
From: Frieder Schrempf @ 2017-12-04 13:32 UTC (permalink / raw)
  To: linux-mtd, boris.brezillon; +Cc: peterpandong

Hi Boris,

 > If everything goes well, we should be good for 4.14, and the patches
 > will have spent enough time in linux-next to discover obvious bugs.

What is the latest status of the SPI-NAND framework patches?

The reason I am asking is, that we have hardware based on the NXP 
i.MX6UL SOC with a serial NAND connected via QSPI interface.

We currently have a working implementation based on a 3.14 vendor kernel 
using a modified version of the "mt29f_spinand" staging driver, but for 
the future we plan to use a recent mainline kernel.

We also think about porting our implementation to the new framework to 
enable support for more SPI NAND chips (Winbond, Toshiba) and for the 
NXP QSPI-controller.

Therefore we would like to know about the current schedule for bringing 
the framework to mainline.

Thanks,

Frieder Schrempf

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-04 13:32   ` Frieder Schrempf
@ 2017-12-04 14:05     ` Boris Brezillon
  2017-12-05  1:35       ` Peter Pan 潘栋 (peterpandong)
  0 siblings, 1 reply; 65+ messages in thread
From: Boris Brezillon @ 2017-12-04 14:05 UTC (permalink / raw)
  To: Frieder Schrempf; +Cc: linux-mtd, peterpandong

Hi Frieder,

On Mon, 4 Dec 2017 14:32:14 +0100
Frieder Schrempf <frieder.schrempf@exceet.de> wrote:

> Hi Boris,
> 
>  > If everything goes well, we should be good for 4.14, and the patches
>  > will have spent enough time in linux-next to discover obvious bugs.  
> 
> What is the latest status of the SPI-NAND framework patches?
> 
> The reason I am asking is, that we have hardware based on the NXP 
> i.MX6UL SOC with a serial NAND connected via QSPI interface.
> 
> We currently have a working implementation based on a 3.14 vendor kernel 
> using a modified version of the "mt29f_spinand" staging driver, but for 
> the future we plan to use a recent mainline kernel.
> 
> We also think about porting our implementation to the new framework to 
> enable support for more SPI NAND chips (Winbond, Toshiba) and for the 
> NXP QSPI-controller.
> 
> Therefore we would like to know about the current schedule for bringing 
> the framework to mainline.

Sorry for the silence and the lack of progress on this front. I don't
have much time to work on this SPI-NAND framework (I do it on my spare
time), and last time I had a look and tried to address my own comments
on Peter's version, I realized I was not really happy with the
implementation, mainly because it copies some of the mistakes done in
the raw/parallel NAND framework.
So I ended up rewriting a lot of code, and didn't have time to test the
new implementation [1].

Note that it's mainly a rewrite of the generic NAND layer the SPI-NAND
framework is based on. I also re-considered the option of moving
existing BBT handling code in the generic layer, because again, I think
we should try to lighten the existing implementation instead of
quickly adapting it to the generic NAND layer. So, what's in [1] is
basic SPI-NAND support without BBT and ECC. Of course, this will be
extended later on, but I think we should start small, and take the time
to think about how we want to extend the generic layer so that some of
the code can be re-used by the parallel/raw NAND and OneNAND frameworks.

I'm really sorry to have blocked this initiative by not responding
and/or not spending the necessary time to rework the code, but I
really think we should have a strong base if we don't want to end up
with what he have in the parallel/raw NAND/OneNAND frameworks (a code
base that is hardly maintainable, with a lot of code duplication).

Anyway, any help is appreciated, so if you do have time to
review/test/enhance this code, feel free to do it.

Regards,

Boris

[1]https://github.com/bbrezillon/linux-0day/commits/nand/spi-nand

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-04 14:05     ` Boris Brezillon
@ 2017-12-05  1:35       ` Peter Pan 潘栋 (peterpandong)
  2017-12-05 12:58         ` Boris Brezillon
  0 siblings, 1 reply; 65+ messages in thread
From: Peter Pan 潘栋 (peterpandong) @ 2017-12-05  1:35 UTC (permalink / raw)
  To: Boris Brezillon; +Cc: Frieder Schrempf, linux-mtd, Peter Pan

Hi Boris,

在 2017年12月4日,22:05,Boris Brezillon <boris.brezillon@free-electrons.com<mailto:boris.brezillon@free-electrons.com>> 写道:

Hi Frieder,

On Mon, 4 Dec 2017 14:32:14 +0100
Frieder Schrempf <frieder.schrempf@exceet.de<mailto:frieder.schrempf@exceet.de>> wrote:

Hi Boris,

If everything goes well, we should be good for 4.14, and the patches
will have spent enough time in linux-next to discover obvious bugs.

What is the latest status of the SPI-NAND framework patches?

The reason I am asking is, that we have hardware based on the NXP
i.MX6UL SOC with a serial NAND connected via QSPI interface.

We currently have a working implementation based on a 3.14 vendor kernel
using a modified version of the "mt29f_spinand" staging driver, but for
the future we plan to use a recent mainline kernel.

We also think about porting our implementation to the new framework to
enable support for more SPI NAND chips (Winbond, Toshiba) and for the
NXP QSPI-controller.

Therefore we would like to know about the current schedule for bringing
the framework to mainline.

Sorry for the silence and the lack of progress on this front. I don't
have much time to work on this SPI-NAND framework (I do it on my spare
time), and last time I had a look and tried to address my own comments
on Peter's version, I realized I was not really happy with the
implementation, mainly because it copies some of the mistakes done in
the raw/parallel NAND framework.
So I ended up rewriting a lot of code, and didn't have time to test the
new implementation [1].

I’m still waiting for your git branch for spi NAND. Is this the branch I’m waiting for? I just took a quick look at it and I found you put more common code into new Nand core. This is cool. I thought we will do this job after spi NAND being merged. Anyway, do you want both spi and raw NAND code to be rebased on new NAND core or we just put spi NAND in? Anything I can help to speed the spi NAND merge up?

Thanks
Peter Pan


Note that it's mainly a rewrite of the generic NAND layer the SPI-NAND
framework is based on. I also re-considered the option of moving
existing BBT handling code in the generic layer, because again, I think
we should try to lighten the existing implementation instead of
quickly adapting it to the generic NAND layer. So, what's in [1] is
basic SPI-NAND support without BBT and ECC. Of course, this will be
extended later on, but I think we should start small, and take the time
to think about how we want to extend the generic layer so that some of
the code can be re-used by the parallel/raw NAND and OneNAND frameworks.

I'm really sorry to have blocked this initiative by not responding
and/or not spending the necessary time to rework the code, but I
really think we should have a strong base if we don't want to end up
with what he have in the parallel/raw NAND/OneNAND frameworks (a code
base that is hardly maintainable, with a lot of code duplication).

Anyway, any help is appreciated, so if you do have time to
review/test/enhance this code, feel free to do it.

Regards,

Boris

[1]https://github.com/bbrezillon/linux-0day/commits/nand/spi-nand

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-05  1:35       ` Peter Pan 潘栋 (peterpandong)
@ 2017-12-05 12:58         ` Boris Brezillon
  2017-12-05 13:03           ` Boris Brezillon
  0 siblings, 1 reply; 65+ messages in thread
From: Boris Brezillon @ 2017-12-05 12:58 UTC (permalink / raw)
  To: Peter Pan 潘栋 (peterpandong)
  Cc: Peter Pan, Frieder Schrempf, linux-mtd

Hi Peter,

Can you please try to fix your mailer so that we can distinguish what
is quoted from what you add?

On Tue, 5 Dec 2017 01:35:05 +0000
Peter Pan 潘栋 (peterpandong) <peterpandong@micron.com> wrote:

> 
> I’m still waiting for your git branch for spi NAND. Is this the branch
> I’m waiting for?

Yes, it's the branch I promised to share with you, but I didn't
communicate on it since it's not yet in a clean state (still have to
add kerneldoc headers, test everything, provide proper commit
message, fix authorship, ...).

> I just took a quick look at
> it and I found you put more common code into new Nand core. This is
> cool. I thought we will do this job after spi NAND being merged.

Well, I don't think there's more code than before, it's just that I
reworked the logic so that it could be more useful to other NAND
sub-layers.

> Anyway, do you want both spi and raw NAND code to be rebased on new
> NAND core or we just put spi NAND in?

That's another decision I took in this rework: I want to keep existing
raw/parallel NAND framework unchanged, because it's a real pain to
validate that everything works as expected when you do such invasive
changes as the bbt rework we had done in earlier versions of this
series.

> Anything I can help to speed the
> spi NAND merge up?

Testing and reviewing, as usual. I'd really like to get the preparation
patches (all patches touching mtd core code) in 4.16. For the rest, it
really depends how much time you and other contributors (including me)
can spend testing/reviewing/fixing/documenting the code.

I am totally aware that I'm the one blocking the progress on this
framework because of my constant hesitations on what the generic NAND
layer should look like, but I'm a bit more confident now that we
isolated the raw NAND code from the generic NAND changes (less risks of
breaking existing NAND users).

Regards,

Boris

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-05 12:58         ` Boris Brezillon
@ 2017-12-05 13:03           ` Boris Brezillon
  2017-12-12  9:58             ` Frieder Schrempf
  0 siblings, 1 reply; 65+ messages in thread
From: Boris Brezillon @ 2017-12-05 13:03 UTC (permalink / raw)
  To: Peter Pan 潘栋 (peterpandong)
  Cc: Peter Pan, Frieder Schrempf, linux-mtd

On Tue, 5 Dec 2017 13:58:04 +0100
Boris Brezillon <boris.brezillon@free-electrons.com> wrote:

> Hi Peter,
> 
> Can you please try to fix your mailer so that we can distinguish what
> is quoted from what you add?
> 
> On Tue, 5 Dec 2017 01:35:05 +0000
> Peter Pan 潘栋 (peterpandong) <peterpandong@micron.com> wrote:
> 
> > 
> > I’m still waiting for your git branch for spi NAND. Is this the branch
> > I’m waiting for?  
> 
> Yes, it's the branch I promised to share with you, but I didn't
> communicate on it since it's not yet in a clean state (still have to
> add kerneldoc headers, test everything, provide proper commit
> message, fix authorship, ...).
> 
> > I just took a quick look at
> > it and I found you put more common code into new Nand core. This is
> > cool. I thought we will do this job after spi NAND being merged.  
> 
> Well, I don't think there's more code than before, it's just that I
> reworked the logic so that it could be more useful to other NAND
> sub-layers.
> 
> > Anyway, do you want both spi and raw NAND code to be rebased on new
> > NAND core or we just put spi NAND in?  
> 
> That's another decision I took in this rework: I want to keep existing
> raw/parallel NAND framework unchanged, because it's a real pain to
> validate that everything works as expected when you do such invasive
> changes as the bbt rework we had done in earlier versions of this
> series.
> 
> > Anything I can help to speed the
> > spi NAND merge up?  
> 
> Testing and reviewing, as usual. I'd really like to get the preparation
> patches (all patches touching mtd core code) in 4.16. For the rest, it
> really depends how much time you and other contributors (including me)
> can spend testing/reviewing/fixing/documenting the code.
> 
> I am totally aware that I'm the one blocking the progress on this
> framework because of my constant hesitations on what the generic NAND
> layer should look like, but I'm a bit more confident now that we
> isolated the raw NAND code from the generic NAND changes (less risks of
> breaking existing NAND users).

Lastest version, with fixup patches squashed in original patches is
available here[1].

[1]https://github.com/bbrezillon/linux-0day/commits/nand/spi-nand-squashed

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-05 13:03           ` Boris Brezillon
@ 2017-12-12  9:58             ` Frieder Schrempf
  2017-12-13 21:27               ` Boris Brezillon
  0 siblings, 1 reply; 65+ messages in thread
From: Frieder Schrempf @ 2017-12-12  9:58 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Peter Pan 潘栋 (peterpandong), Peter Pan, linux-mtd

Hi Boris,

I spent some time looking at and working with your latest SPI NAND code.
In my previous mail I said, that we have some working code for our 3.14 
kernel based on the "mt29f_spinand" staging driver, but that was wrong 
as I got things mixed up in my head.
Actually our codebase was an early version of Peter's code, so the 
effort to port it to the latest framework code was not that big.

I forked your repo and you can find my working tree at [1].

What I did so far:

* Rebase your patches on latest Linux 4.14.5

* Add a driver for the Winbond W25M02GV SPI NAND chip, that we have on 
some of our boards.

* Add a driver for the Freescale QSPI controller, derived from the 
existing QSPI-NOR driver at drivers/mtd/spi-nor/fsl-quadspi.c.

* Add a setup and setup_late op to the controller layer (see [3]). I 
don't know if that makes sense, but at least the setup_late is needed 
for the FSL QSPI driver, as it needs to know the size of the flash to 
setup the memory mapping for the QSPI read operations.

* A bit of testing and fixing two small bugs, which look like copy and 
paste mistakes. See [2].

* Running nandtest successfully on our hardware (i.MX6UL -> FSL-QSPI -> 
W25M02GV)

I hope this is of use while moving on.
I guess you would like to have the basic framework with Micron support 
and generic SPI tested and stabilized first, before adding more code, 
but to be able to test with our hardware I need Micron and FSL QSPI.

Some questions/flaws that occurred to me:

* The W25M02GV chip has two dies of 128M each. My current driver only 
makes use of the first die. The chip expects a die-select command to 
switch between the two dies.
What would be the place to implement this?
Can I just add the command and issue it in 
winbond_spinand_adjust_cache_op if luns_per_target > 1?

* The FSL QSPI controller has a lookup table that needs to be filled 
with command sequences at the time of setup. Therefore the number of 
dummy bytes for each command is fixed and in my current implementation 
op->dummy_bytes is ignored.
That's not a problem if all chips need the same number of dummy bytes 
for each command, but I guess that's not the case, as there is a 
_spinand_get_dummy function.

* What is your plan for ECC and BBT? At least enabling the onchip ECC 
will be necessary to be able to use the flash properly (e.g. with UBI), 
or am I wrong?

* Do you have any special test cases? What do you usually do to test the 
code?

Thanks for your patience and best regards,

Frieder

[1] https://github.com/fschrempf/linux-0day/commits/spi-nand-exceet
[2] 
https://github.com/fschrempf/linux-0day/commit/213caf23a0467eba4002e3dd5832c48adbeee3f4
[3] 
https://github.com/fschrempf/linux-0day/commit/3f39780e7c7ca12aeab77963e6c7dc1c38f524b5

On 05.12.2017 14:03, Boris Brezillon wrote:
> On Tue, 5 Dec 2017 13:58:04 +0100
> Boris Brezillon <boris.brezillon@free-electrons.com> wrote:
> 
>> Testing and reviewing, as usual. I'd really like to get the preparation
>> patches (all patches touching mtd core code) in 4.16. For the rest, it
>> really depends how much time you and other contributors (including me)
>> can spend testing/reviewing/fixing/documenting the code.
>>
>> I am totally aware that I'm the one blocking the progress on this
>> framework because of my constant hesitations on what the generic NAND
>> layer should look like, but I'm a bit more confident now that we
>> isolated the raw NAND code from the generic NAND changes (less risks of
>> breaking existing NAND users).
> 
> Lastest version, with fixup patches squashed in original patches is
> available here[1].
> 
> [1]https://github.com/bbrezillon/linux-0day/commits/nand/spi-nand-squashed
> 

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-12  9:58             ` Frieder Schrempf
@ 2017-12-13 21:27               ` Boris Brezillon
  2017-12-14  6:15                 ` Peter Pan
  0 siblings, 1 reply; 65+ messages in thread
From: Boris Brezillon @ 2017-12-13 21:27 UTC (permalink / raw)
  To: Frieder Schrempf
  Cc: Peter Pan 潘栋 (peterpandong), Peter Pan, linux-mtd

Hi Frieder,

On Tue, 12 Dec 2017 10:58:10 +0100
Frieder Schrempf <frieder.schrempf@exceet.de> wrote:

> Hi Boris,
> 
> I spent some time looking at and working with your latest SPI NAND code.
> In my previous mail I said, that we have some working code for our 3.14 
> kernel based on the "mt29f_spinand" staging driver, but that was wrong 
> as I got things mixed up in my head.
> Actually our codebase was an early version of Peter's code, so the 
> effort to port it to the latest framework code was not that big.
> 
> I forked your repo and you can find my working tree at [1].

Great, I'll try to have a look.

> 
> What I did so far:
> 
> * Rebase your patches on latest Linux 4.14.5

Cool, rebasing on 4.15-rc1 would be even better, but I can do that if
you don't have the time.

> 
> * Add a driver for the Winbond W25M02GV SPI NAND chip, that we have on 
> some of our boards.

Okay, that's actually a good thing to have tested with another chip,
This way we can make sure the framework is generic enough.

> 
> * Add a driver for the Freescale QSPI controller, derived from the 
> existing QSPI-NOR driver at drivers/mtd/spi-nor/fsl-quadspi.c.

That's an interesting case as well, the generic NAND controller is
probably the easiest implementation, and that's a good thing to have
another controller.

> 
> * Add a setup and setup_late op to the controller layer (see [3]). I 
> don't know if that makes sense, but at least the setup_late is needed 
> for the FSL QSPI driver, as it needs to know the size of the flash to 
> setup the memory mapping for the QSPI read operations.

Hm, not sure what ->setup_late() is for, but I'll have a look.

> 
> * A bit of testing and fixing two small bugs, which look like copy and 
> paste mistakes. See [2].

Thanks, I'll squash the fixes in the original commit.

> 
> * Running nandtest successfully on our hardware (i.MX6UL -> FSL-QSPI -> 
> W25M02GV)
> 
> I hope this is of use while moving on.

Definitely. I'd also like to have a review on the framework code if
possible, but that can be done when posted on the ML.

> I guess you would like to have the basic framework with Micron support 
> and generic SPI tested and stabilized first, before adding more code, 
> but to be able to test with our hardware I need Micron and FSL QSPI.

I guess you mean Winbond not Micron. That's okay if those patches are
posted after the initial series. All I need is reviews and tests from
different parties, so that I'm less confident in merging the code.

> 
> Some questions/flaws that occurred to me:
> 
> * The W25M02GV chip has two dies of 128M each. My current driver only 
> makes use of the first die. The chip expects a die-select command to 
> switch between the two dies.
> What would be the place to implement this?
> Can I just add the command and issue it in 
> winbond_spinand_adjust_cache_op if luns_per_target > 1?

It really depends when the die selection happens. I guess it happens in
2 places: when preparing a program/read operation and when doing the
transfer to the in-chip cache. Anyway, the die information is already
passed in the nand_pos object, so all you'll have to do is create a new
hook to customize the SPI command when needed.

> 
> * The FSL QSPI controller has a lookup table that needs to be filled 
> with command sequences at the time of setup. Therefore the number of 
> dummy bytes for each command is fixed and in my current implementation 
> op->dummy_bytes is ignored.
> That's not a problem if all chips need the same number of dummy bytes 
> for each command, but I guess that's not the case, as there is a 
> _spinand_get_dummy function.

We should definitely expose that in a generic way, and on a
per-operation basis, so that, after the detection step, the NAND
controller can query this information.

> 
> * What is your plan for ECC and BBT? At least enabling the onchip ECC 
> will be necessary to be able to use the flash properly (e.g. with UBI), 
> or am I wrong?

Well, if all SPI NAND chips are supporting ECC the same way and
on-die ECC support is mandatory for SPI NANDs, then supporting that
directly in the core is probably the best option. If, on the other
hand, you have various implementations, and some SPI controllers have
their own ECC engine that you can use with SPI NANDs, then it's
probably a better idea to abstract ECC engine in the generic NAND layer.

For BBTs, I'd like to have a clean version of the nand_bbt logic that
uses all of the helpers exposed by the generic NAND layer. I'd also
like to simplify the code if possible.

> 
> * Do you have any special test cases? What do you usually do to test the 
> code?

Well, make sure all the mtd tests are passing (drivers/mtd/tests), and
then, the next step is to test it with UBI+UBIFS. But honestly, I'm not
so worried, this is new code, and we've isolated from the raw NAND
layer, so if it's buggy or instable at the beginning it's not a big
deal, it will be noticed and fixed for the next few releases.

> 
> Thanks for your patience and best regards,

No problem. Thanks for your work, and I'll try to be more active on
this topic (I promised that several times, and failed it :-/).

Regards,

Boris

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-13 21:27               ` Boris Brezillon
@ 2017-12-14  6:15                 ` Peter Pan
  2017-12-14  7:50                   ` Boris Brezillon
  0 siblings, 1 reply; 65+ messages in thread
From: Peter Pan @ 2017-12-14  6:15 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Frieder Schrempf, Peter Pan 潘栋 (peterpandong), linux-mtd

Hi Boris and Frieder,

On Thu, Dec 14, 2017 at 5:27 AM, Boris Brezillon
<boris.brezillon@free-electrons.com> wrote:
> Hi Frieder,
>
> On Tue, 12 Dec 2017 10:58:10 +0100
> Frieder Schrempf <frieder.schrempf@exceet.de> wrote:
>
>> Hi Boris,
>>
>> I spent some time looking at and working with your latest SPI NAND code.
>> In my previous mail I said, that we have some working code for our 3.14
>> kernel based on the "mt29f_spinand" staging driver, but that was wrong
>> as I got things mixed up in my head.
>> Actually our codebase was an early version of Peter's code, so the
>> effort to port it to the latest framework code was not that big.
>>
>> I forked your repo and you can find my working tree at [1].
>
> Great, I'll try to have a look.
>
>>
>> What I did so far:
>>
>> * Rebase your patches on latest Linux 4.14.5
>
> Cool, rebasing on 4.15-rc1 would be even better, but I can do that if
> you don't have the time.
>
>>
>> * Add a driver for the Winbond W25M02GV SPI NAND chip, that we have on
>> some of our boards.
>
> Okay, that's actually a good thing to have tested with another chip,
> This way we can make sure the framework is generic enough.
>
>>
>> * Add a driver for the Freescale QSPI controller, derived from the
>> existing QSPI-NOR driver at drivers/mtd/spi-nor/fsl-quadspi.c.
>
> That's an interesting case as well, the generic NAND controller is
> probably the easiest implementation, and that's a good thing to have
> another controller.
>
>>
>> * Add a setup and setup_late op to the controller layer (see [3]). I
>> don't know if that makes sense, but at least the setup_late is needed
>> for the FSL QSPI driver, as it needs to know the size of the flash to
>> setup the memory mapping for the QSPI read operations.
>
> Hm, not sure what ->setup_late() is for, but I'll have a look.
>
>>
>> * A bit of testing and fixing two small bugs, which look like copy and
>> paste mistakes. See [2].
>
> Thanks, I'll squash the fixes in the original commit.
>
>>
>> * Running nandtest successfully on our hardware (i.MX6UL -> FSL-QSPI ->
>> W25M02GV)
>>
>> I hope this is of use while moving on.
>
> Definitely. I'd also like to have a review on the framework code if
> possible, but that can be done when posted on the ML.
>
>> I guess you would like to have the basic framework with Micron support
>> and generic SPI tested and stabilized first, before adding more code,
>> but to be able to test with our hardware I need Micron and FSL QSPI.
>
> I guess you mean Winbond not Micron. That's okay if those patches are
> posted after the initial series. All I need is reviews and tests from
> different parties, so that I'm less confident in merging the code.
>
>>
>> Some questions/flaws that occurred to me:
>>
>> * The W25M02GV chip has two dies of 128M each. My current driver only
>> makes use of the first die. The chip expects a die-select command to
>> switch between the two dies.
>> What would be the place to implement this?
>> Can I just add the command and issue it in
>> winbond_spinand_adjust_cache_op if luns_per_target > 1?
>
> It really depends when the die selection happens. I guess it happens in
> 2 places: when preparing a program/read operation and when doing the
> transfer to the in-chip cache. Anyway, the die information is already
> passed in the nand_pos object, so all you'll have to do is create a new
> hook to customize the SPI command when needed.

I don't know whether we can do the the die switch in the generic NAND core
(drivers/mtd/nand/core.c). I'm not sure if chip->select_chip() in nand_base.c
does the same thing or not. If so, we can do the die switch before
read/write/erase
operation. And let spi nand core to implement a hook to support it.

>
>>
>> * The FSL QSPI controller has a lookup table that needs to be filled
>> with command sequences at the time of setup. Therefore the number of
>> dummy bytes for each command is fixed and in my current implementation
>> op->dummy_bytes is ignored.
>> That's not a problem if all chips need the same number of dummy bytes
>> for each command, but I guess that's not the case, as there is a
>> _spinand_get_dummy function.
>
> We should definitely expose that in a generic way, and on a
> per-operation basis, so that, after the detection step, the NAND
> controller can query this information.
>
>>
>> * What is your plan for ECC and BBT? At least enabling the onchip ECC
>> will be necessary to be able to use the flash properly (e.g. with UBI),
>> or am I wrong?
>
> Well, if all SPI NAND chips are supporting ECC the same way and
> on-die ECC support is mandatory for SPI NANDs, then supporting that
> directly in the core is probably the best option. If, on the other
> hand, you have various implementations, and some SPI controllers have
> their own ECC engine that you can use with SPI NANDs, then it's
> probably a better idea to abstract ECC engine in the generic NAND layer.

As far as I know, all the SPI NAND supports on-die ECC (at least all
the SPI NAND
I heard). But different chips may have different ECC layout in OOB
area. But I think
this cannot be a problem, we can handle this in vendor's file.

>
> For BBTs, I'd like to have a clean version of the nand_bbt logic that
> uses all of the helpers exposed by the generic NAND layer. I'd also
> like to simplify the code if possible.
>
>>
>> * Do you have any special test cases? What do you usually do to test the
>> code?
>
> Well, make sure all the mtd tests are passing (drivers/mtd/tests), and
> then, the next step is to test it with UBI+UBIFS. But honestly, I'm not
> so worried, this is new code, and we've isolated from the raw NAND
> layer, so if it's buggy or instable at the beginning it's not a big
> deal, it will be noticed and fixed for the next few releases.
>
>>
>> Thanks for your patience and best regards,
>
> No problem. Thanks for your work, and I'll try to be more active on
> this topic (I promised that several times, and failed it :-/).

Boris,

I think we need to move forward, MediaTek's engineer has already asked for
the status of the spi nand framework upstreaming, since they want to upstream
their SPI NAND controller driver. And Hisilicon also has a controller driver.
Since more and more platforms start to support SPI NAND, we'd better merge a
simple but well designed framework first. I will run your modified
version on Zedboard
with generic SPI controller this or next week.

Thanks,
Peter Pan

>
> Regards,
>
> Boris

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-14  6:15                 ` Peter Pan
@ 2017-12-14  7:50                   ` Boris Brezillon
  2017-12-14  8:06                     ` Peter Pan
  2017-12-15  2:35                     ` Peter Pan
  0 siblings, 2 replies; 65+ messages in thread
From: Boris Brezillon @ 2017-12-14  7:50 UTC (permalink / raw)
  To: Peter Pan
  Cc: Frieder Schrempf, Peter Pan 潘栋 (peterpandong), linux-mtd

Hi Peter,

On Thu, 14 Dec 2017 14:15:57 +0800
Peter Pan <peterpansjtu@gmail.com> wrote:

> Hi Boris and Frieder,
> 
> On Thu, Dec 14, 2017 at 5:27 AM, Boris Brezillon
> <boris.brezillon@free-electrons.com> wrote:
> > Hi Frieder,
> >
> > On Tue, 12 Dec 2017 10:58:10 +0100
> > Frieder Schrempf <frieder.schrempf@exceet.de> wrote:
> >  
> >> Hi Boris,
> >>
> >> I spent some time looking at and working with your latest SPI NAND code.
> >> In my previous mail I said, that we have some working code for our 3.14
> >> kernel based on the "mt29f_spinand" staging driver, but that was wrong
> >> as I got things mixed up in my head.
> >> Actually our codebase was an early version of Peter's code, so the
> >> effort to port it to the latest framework code was not that big.
> >>
> >> I forked your repo and you can find my working tree at [1].  
> >
> > Great, I'll try to have a look.
> >  
> >>
> >> What I did so far:
> >>
> >> * Rebase your patches on latest Linux 4.14.5  
> >
> > Cool, rebasing on 4.15-rc1 would be even better, but I can do that if
> > you don't have the time.
> >  
> >>
> >> * Add a driver for the Winbond W25M02GV SPI NAND chip, that we have on
> >> some of our boards.  
> >
> > Okay, that's actually a good thing to have tested with another chip,
> > This way we can make sure the framework is generic enough.
> >  
> >>
> >> * Add a driver for the Freescale QSPI controller, derived from the
> >> existing QSPI-NOR driver at drivers/mtd/spi-nor/fsl-quadspi.c.  
> >
> > That's an interesting case as well, the generic NAND controller is
> > probably the easiest implementation, and that's a good thing to have
> > another controller.
> >  
> >>
> >> * Add a setup and setup_late op to the controller layer (see [3]). I
> >> don't know if that makes sense, but at least the setup_late is needed
> >> for the FSL QSPI driver, as it needs to know the size of the flash to
> >> setup the memory mapping for the QSPI read operations.  
> >
> > Hm, not sure what ->setup_late() is for, but I'll have a look.
> >  
> >>
> >> * A bit of testing and fixing two small bugs, which look like copy and
> >> paste mistakes. See [2].  
> >
> > Thanks, I'll squash the fixes in the original commit.
> >  
> >>
> >> * Running nandtest successfully on our hardware (i.MX6UL -> FSL-QSPI ->
> >> W25M02GV)
> >>
> >> I hope this is of use while moving on.  
> >
> > Definitely. I'd also like to have a review on the framework code if
> > possible, but that can be done when posted on the ML.
> >  
> >> I guess you would like to have the basic framework with Micron support
> >> and generic SPI tested and stabilized first, before adding more code,
> >> but to be able to test with our hardware I need Micron and FSL QSPI.  
> >
> > I guess you mean Winbond not Micron. That's okay if those patches are
> > posted after the initial series. All I need is reviews and tests from
> > different parties, so that I'm less confident in merging the code.
> >  
> >>
> >> Some questions/flaws that occurred to me:
> >>
> >> * The W25M02GV chip has two dies of 128M each. My current driver only
> >> makes use of the first die. The chip expects a die-select command to
> >> switch between the two dies.
> >> What would be the place to implement this?
> >> Can I just add the command and issue it in
> >> winbond_spinand_adjust_cache_op if luns_per_target > 1?  
> >
> > It really depends when the die selection happens. I guess it happens in
> > 2 places: when preparing a program/read operation and when doing the
> > transfer to the in-chip cache. Anyway, the die information is already
> > passed in the nand_pos object, so all you'll have to do is create a new
> > hook to customize the SPI command when needed.  
> 
> I don't know whether we can do the the die switch in the generic NAND core
> (drivers/mtd/nand/core.c). I'm not sure if chip->select_chip() in nand_base.c
> does the same thing or not. If so, we can do the die switch before
> read/write/erase
> operation. And let spi nand core to implement a hook to support it.

Actually, I'm trying to move away from this ->select_chip() approach in
the raw NAND framework, simply because the controller might be able to
parallelize operations (like 2 erase on 2 different dies, or one erase
on one die, and a program on the other), and having this ->select_chip()
done early in the chain prevents this kind of optimization.

Anyway, the controller should now have all the necessary information to
know which die an operation should be executed on, and if a specific
command has to be sent to the device to select a specific die, it can
be done in the NAND vendor specific code.

> 
> >  
> >>
> >> * The FSL QSPI controller has a lookup table that needs to be filled
> >> with command sequences at the time of setup. Therefore the number of
> >> dummy bytes for each command is fixed and in my current implementation
> >> op->dummy_bytes is ignored.
> >> That's not a problem if all chips need the same number of dummy bytes
> >> for each command, but I guess that's not the case, as there is a
> >> _spinand_get_dummy function.  
> >
> > We should definitely expose that in a generic way, and on a
> > per-operation basis, so that, after the detection step, the NAND
> > controller can query this information.
> >  
> >>
> >> * What is your plan for ECC and BBT? At least enabling the onchip ECC
> >> will be necessary to be able to use the flash properly (e.g. with UBI),
> >> or am I wrong?  
> >
> > Well, if all SPI NAND chips are supporting ECC the same way and
> > on-die ECC support is mandatory for SPI NANDs, then supporting that
> > directly in the core is probably the best option. If, on the other
> > hand, you have various implementations, and some SPI controllers have
> > their own ECC engine that you can use with SPI NANDs, then it's
> > probably a better idea to abstract ECC engine in the generic NAND layer.  
> 
> As far as I know, all the SPI NAND supports on-die ECC (at least all
> the SPI NAND
> I heard). But different chips may have different ECC layout in OOB
> area. But I think
> this cannot be a problem, we can handle this in vendor's file.

Yep.

> 
> >
> > For BBTs, I'd like to have a clean version of the nand_bbt logic that
> > uses all of the helpers exposed by the generic NAND layer. I'd also
> > like to simplify the code if possible.
> >  
> >>
> >> * Do you have any special test cases? What do you usually do to test the
> >> code?  
> >
> > Well, make sure all the mtd tests are passing (drivers/mtd/tests), and
> > then, the next step is to test it with UBI+UBIFS. But honestly, I'm not
> > so worried, this is new code, and we've isolated from the raw NAND
> > layer, so if it's buggy or instable at the beginning it's not a big
> > deal, it will be noticed and fixed for the next few releases.
> >  
> >>
> >> Thanks for your patience and best regards,  
> >
> > No problem. Thanks for your work, and I'll try to be more active on
> > this topic (I promised that several times, and failed it :-/).  
> 
> Boris,
> 
> I think we need to move forward, MediaTek's engineer has already asked for
> the status of the spi nand framework upstreaming, since they want to upstream
> their SPI NAND controller driver. And Hisilicon also has a controller driver.
> Since more and more platforms start to support SPI NAND, we'd better merge a
> simple but well designed framework first. I will run your modified
> version on Zedboard
> with generic SPI controller this or next week.

Then why are they not spending time reviewing the SPI NAND framework?
You know I'm not paid to work on SPI NAND, unlike those engineers
working for SoC/NAND vendors. While I agree being a maintainer implies
doing part of the work on our spare time, what I don't like is when
people that did not invest time in a specific feature ask for this
feature to be implemented/released. This is not your case, you invested
a lot of time in it, and that's the reason I feel bad when I can't spend
the necessary time to make SPI NAND code ready for inclusion.

So here are the next set of things to do if you want to move forward:
1/ Re-submit the preparation patches (those touching MTD core) and
   review them (or find someone to review them)
2/ Add the missing doc to the code (I was planning on doing that, but
   if you're in hurry you can take care of it), and add real commit
   messages.
3/ Fix the authorship on patches (some were mainly written by you, but
   during my rework authorship has been lost)
4/ Ask others to test and review the patches

Regards,

Boris

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-14  7:50                   ` Boris Brezillon
@ 2017-12-14  8:06                     ` Peter Pan
  2017-12-14 14:39                       ` Frieder Schrempf
  2017-12-15  2:35                     ` Peter Pan
  1 sibling, 1 reply; 65+ messages in thread
From: Peter Pan @ 2017-12-14  8:06 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Frieder Schrempf, Peter Pan 潘栋 (peterpandong), linux-mtd

Hi Boris,

On Thu, Dec 14, 2017 at 3:50 PM, Boris Brezillon
<boris.brezillon@free-electrons.com> wrote:
> Hi Peter,
>
> On Thu, 14 Dec 2017 14:15:57 +0800
> Peter Pan <peterpansjtu@gmail.com> wrote:
>
>> Hi Boris and Frieder,
>>
>> On Thu, Dec 14, 2017 at 5:27 AM, Boris Brezillon
>> <boris.brezillon@free-electrons.com> wrote:
>> > Hi Frieder,
>> >
>> > On Tue, 12 Dec 2017 10:58:10 +0100
>> > Frieder Schrempf <frieder.schrempf@exceet.de> wrote:
>> >
>> >> Hi Boris,
>> >>
>> >> I spent some time looking at and working with your latest SPI NAND code.
>> >> In my previous mail I said, that we have some working code for our 3.14
>> >> kernel based on the "mt29f_spinand" staging driver, but that was wrong
>> >> as I got things mixed up in my head.
>> >> Actually our codebase was an early version of Peter's code, so the
>> >> effort to port it to the latest framework code was not that big.
>> >>
>> >> I forked your repo and you can find my working tree at [1].
>> >
>> > Great, I'll try to have a look.
>> >
>> >>
>> >> What I did so far:
>> >>
>> >> * Rebase your patches on latest Linux 4.14.5
>> >
>> > Cool, rebasing on 4.15-rc1 would be even better, but I can do that if
>> > you don't have the time.
>> >
>> >>
>> >> * Add a driver for the Winbond W25M02GV SPI NAND chip, that we have on
>> >> some of our boards.
>> >
>> > Okay, that's actually a good thing to have tested with another chip,
>> > This way we can make sure the framework is generic enough.
>> >
>> >>
>> >> * Add a driver for the Freescale QSPI controller, derived from the
>> >> existing QSPI-NOR driver at drivers/mtd/spi-nor/fsl-quadspi.c.
>> >
>> > That's an interesting case as well, the generic NAND controller is
>> > probably the easiest implementation, and that's a good thing to have
>> > another controller.
>> >
>> >>
>> >> * Add a setup and setup_late op to the controller layer (see [3]). I
>> >> don't know if that makes sense, but at least the setup_late is needed
>> >> for the FSL QSPI driver, as it needs to know the size of the flash to
>> >> setup the memory mapping for the QSPI read operations.
>> >
>> > Hm, not sure what ->setup_late() is for, but I'll have a look.
>> >
>> >>
>> >> * A bit of testing and fixing two small bugs, which look like copy and
>> >> paste mistakes. See [2].
>> >
>> > Thanks, I'll squash the fixes in the original commit.
>> >
>> >>
>> >> * Running nandtest successfully on our hardware (i.MX6UL -> FSL-QSPI ->
>> >> W25M02GV)
>> >>
>> >> I hope this is of use while moving on.
>> >
>> > Definitely. I'd also like to have a review on the framework code if
>> > possible, but that can be done when posted on the ML.
>> >
>> >> I guess you would like to have the basic framework with Micron support
>> >> and generic SPI tested and stabilized first, before adding more code,
>> >> but to be able to test with our hardware I need Micron and FSL QSPI.
>> >
>> > I guess you mean Winbond not Micron. That's okay if those patches are
>> > posted after the initial series. All I need is reviews and tests from
>> > different parties, so that I'm less confident in merging the code.
>> >
>> >>
>> >> Some questions/flaws that occurred to me:
>> >>
>> >> * The W25M02GV chip has two dies of 128M each. My current driver only
>> >> makes use of the first die. The chip expects a die-select command to
>> >> switch between the two dies.
>> >> What would be the place to implement this?
>> >> Can I just add the command and issue it in
>> >> winbond_spinand_adjust_cache_op if luns_per_target > 1?
>> >
>> > It really depends when the die selection happens. I guess it happens in
>> > 2 places: when preparing a program/read operation and when doing the
>> > transfer to the in-chip cache. Anyway, the die information is already
>> > passed in the nand_pos object, so all you'll have to do is create a new
>> > hook to customize the SPI command when needed.
>>
>> I don't know whether we can do the the die switch in the generic NAND core
>> (drivers/mtd/nand/core.c). I'm not sure if chip->select_chip() in nand_base.c
>> does the same thing or not. If so, we can do the die switch before
>> read/write/erase
>> operation. And let spi nand core to implement a hook to support it.
>
> Actually, I'm trying to move away from this ->select_chip() approach in
> the raw NAND framework, simply because the controller might be able to
> parallelize operations (like 2 erase on 2 different dies, or one erase
> on one die, and a program on the other), and having this ->select_chip()
> done early in the chain prevents this kind of optimization.
>
> Anyway, the controller should now have all the necessary information to
> know which die an operation should be executed on, and if a specific
> command has to be sent to the device to select a specific die, it can
> be done in the NAND vendor specific code.

Got your point. It makes sense.

>
>>
>> >
>> >>
>> >> * The FSL QSPI controller has a lookup table that needs to be filled
>> >> with command sequences at the time of setup. Therefore the number of
>> >> dummy bytes for each command is fixed and in my current implementation
>> >> op->dummy_bytes is ignored.
>> >> That's not a problem if all chips need the same number of dummy bytes
>> >> for each command, but I guess that's not the case, as there is a
>> >> _spinand_get_dummy function.
>> >
>> > We should definitely expose that in a generic way, and on a
>> > per-operation basis, so that, after the detection step, the NAND
>> > controller can query this information.
>> >
>> >>
>> >> * What is your plan for ECC and BBT? At least enabling the onchip ECC
>> >> will be necessary to be able to use the flash properly (e.g. with UBI),
>> >> or am I wrong?
>> >
>> > Well, if all SPI NAND chips are supporting ECC the same way and
>> > on-die ECC support is mandatory for SPI NANDs, then supporting that
>> > directly in the core is probably the best option. If, on the other
>> > hand, you have various implementations, and some SPI controllers have
>> > their own ECC engine that you can use with SPI NANDs, then it's
>> > probably a better idea to abstract ECC engine in the generic NAND layer.
>>
>> As far as I know, all the SPI NAND supports on-die ECC (at least all
>> the SPI NAND
>> I heard). But different chips may have different ECC layout in OOB
>> area. But I think
>> this cannot be a problem, we can handle this in vendor's file.
>
> Yep.
>
>>
>> >
>> > For BBTs, I'd like to have a clean version of the nand_bbt logic that
>> > uses all of the helpers exposed by the generic NAND layer. I'd also
>> > like to simplify the code if possible.
>> >
>> >>
>> >> * Do you have any special test cases? What do you usually do to test the
>> >> code?
>> >
>> > Well, make sure all the mtd tests are passing (drivers/mtd/tests), and
>> > then, the next step is to test it with UBI+UBIFS. But honestly, I'm not
>> > so worried, this is new code, and we've isolated from the raw NAND
>> > layer, so if it's buggy or instable at the beginning it's not a big
>> > deal, it will be noticed and fixed for the next few releases.
>> >
>> >>
>> >> Thanks for your patience and best regards,
>> >
>> > No problem. Thanks for your work, and I'll try to be more active on
>> > this topic (I promised that several times, and failed it :-/).
>>
>> Boris,
>>
>> I think we need to move forward, MediaTek's engineer has already asked for
>> the status of the spi nand framework upstreaming, since they want to upstream
>> their SPI NAND controller driver. And Hisilicon also has a controller driver.
>> Since more and more platforms start to support SPI NAND, we'd better merge a
>> simple but well designed framework first. I will run your modified
>> version on Zedboard
>> with generic SPI controller this or next week.
>
> Then why are they not spending time reviewing the SPI NAND framework?
> You know I'm not paid to work on SPI NAND, unlike those engineers
> working for SoC/NAND vendors. While I agree being a maintainer implies
> doing part of the work on our spare time, what I don't like is when
> people that did not invest time in a specific feature ask for this
> feature to be implemented/released. This is not your case, you invested
> a lot of time in it, and that's the reason I feel bad when I can't spend
> the necessary time to make SPI NAND code ready for inclusion.
>
> So here are the next set of things to do if you want to move forward:
> 1/ Re-submit the preparation patches (those touching MTD core) and
>    review them (or find someone to review them)
> 2/ Add the missing doc to the code (I was planning on doing that, but
>    if you're in hurry you can take care of it), and add real commit
>    messages.
> 3/ Fix the authorship on patches (some were mainly written by you, but
>    during my rework authorship has been lost)
> 4/ Ask others to test and review the patches

To be honest, I also feel bad to keep pushing you on this...
I will try to communicate with them to see if they can help us to do some review
or valudation task.
You already make the path clear, I will take the rest. If anything
unclear, I will come
back to discuss with you.

Thanks
Peter Pan


>
> Regards,
>
> Boris

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-14  8:06                     ` Peter Pan
@ 2017-12-14 14:39                       ` Frieder Schrempf
  2017-12-14 14:43                         ` Frieder Schrempf
  2017-12-14 15:38                         ` Boris Brezillon
  0 siblings, 2 replies; 65+ messages in thread
From: Frieder Schrempf @ 2017-12-14 14:39 UTC (permalink / raw)
  To: Peter Pan, Boris Brezillon
  Cc: Peter Pan 潘栋 (peterpandong), linux-mtd

Hello Peter, hello Boris

>>>>> What I did so far:
>>>>>
>>>>> * Rebase your patches on latest Linux 4.14.5
>>>>
>>>> Cool, rebasing on 4.15-rc1 would be even better, but I can do that if
>>>> you don't have the time.

I will try to rebase on 4.15-rc1. Can you give me a quick explanation on 
which patches are needed for SPI NAND + preparation, if I only want to 
add the generic NAND and the SPI NAND layer?
Previously I just rebased the whole branch, but I think you have some 
other pending patches in there?
Would this be the correct changeset: [1]
Or are there other preparation patches needed?

>>>>> I guess you would like to have the basic framework with Micron support
>>>>> and generic SPI tested and stabilized first, before adding more code,
>>>>> but to be able to test with our hardware I need Micron and FSL QSPI.
>>>>
>>>> I guess you mean Winbond not Micron. That's okay if those patches are
>>>> posted after the initial series. All I need is reviews and tests from
>>>> different parties, so that I'm less confident in merging the code.

Yeah I meant Winbond of course. And I guess you meant "more confident". 
Or that was just irony? Nevermind ;)

>>>>> Some questions/flaws that occurred to me:
>>>>>
>>>>> * The W25M02GV chip has two dies of 128M each. My current driver only
>>>>> makes use of the first die. The chip expects a die-select command to
>>>>> switch between the two dies.
>>>>> What would be the place to implement this?
>>>>> Can I just add the command and issue it in
>>>>> winbond_spinand_adjust_cache_op if luns_per_target > 1?
>>>>
>>>> It really depends when the die selection happens. I guess it happens in
>>>> 2 places: when preparing a program/read operation and when doing the
>>>> transfer to the in-chip cache. Anyway, the die information is already
>>>> passed in the nand_pos object, so all you'll have to do is create a new
>>>> hook to customize the SPI command when needed.

The die selection is a separate SPI command and not integrated into the 
program/read/erase sequence.
So I can't customize an existing op, but have to issue a new "die 
select" op.

>>>
>>> I don't know whether we can do the the die switch in the generic NAND core
>>> (drivers/mtd/nand/core.c). I'm not sure if chip->select_chip() in nand_base.c
>>> does the same thing or not. If so, we can do the die switch before
>>> read/write/erase
>>> operation. And let spi nand core to implement a hook to support it.
>>
>> Actually, I'm trying to move away from this ->select_chip() approach in
>> the raw NAND framework, simply because the controller might be able to
>> parallelize operations (like 2 erase on 2 different dies, or one erase
>> on one die, and a program on the other), and having this ->select_chip()
>> done early in the chain prevents this kind of optimization.
>>
>> Anyway, the controller should now have all the necessary information to
>> know which die an operation should be executed on, and if a specific
>> command has to be sent to the device to select a specific die, it can
>> be done in the NAND vendor specific code.

But needing a die select op is quite common for any multi-die chips, 
isn't it?
So shouldn't there be an spinand_die_select_op in the SPI NAND core that 
is executed when necessary and skipped if there's only one die.

> Got your point. It makes sense.
>>
>>>>> * The FSL QSPI controller has a lookup table that needs to be filled
>>>>> with command sequences at the time of setup. Therefore the number of
>>>>> dummy bytes for each command is fixed and in my current implementation
>>>>> op->dummy_bytes is ignored.
>>>>> That's not a problem if all chips need the same number of dummy bytes
>>>>> for each command, but I guess that's not the case, as there is a
>>>>> _spinand_get_dummy function.
>>>>
>>>> We should definitely expose that in a generic way, and on a
>>>> per-operation basis, so that, after the detection step, the NAND
>>>> controller can query this information.

Ok, I might try this and see where it leads me.

>>>>> * What is your plan for ECC and BBT? At least enabling the onchip ECC
>>>>> will be necessary to be able to use the flash properly (e.g. with UBI),
>>>>> or am I wrong?
>>>>
>>>> Well, if all SPI NAND chips are supporting ECC the same way and
>>>> on-die ECC support is mandatory for SPI NANDs, then supporting that
>>>> directly in the core is probably the best option. If, on the other
>>>> hand, you have various implementations, and some SPI controllers have
>>>> their own ECC engine that you can use with SPI NANDs, then it's
>>>> probably a better idea to abstract ECC engine in the generic NAND layer.
>>>
>>> As far as I know, all the SPI NAND supports on-die ECC (at least all
>>> the SPI NAND
>>> I heard). But different chips may have different ECC layout in OOB
>>> area. But I think
>>> this cannot be a problem, we can handle this in vendor's file.
>>
>> Yep.

Ok. If I have time I will think about how the ECC and OOB layout might 
be implemented. But I have not much experience here, so if anyone of you 
can propose something to get started, this would be great.

>>>> For BBTs, I'd like to have a clean version of the nand_bbt logic that
>>>> uses all of the helpers exposed by the generic NAND layer. I'd also
>>>> like to simplify the code if possible.
>>>>
>>>>>
>>>>> * Do you have any special test cases? What do you usually do to test the
>>>>> code?
>>>>
>>>> Well, make sure all the mtd tests are passing (drivers/mtd/tests), and
>>>> then, the next step is to test it with UBI+UBIFS. But honestly, I'm not
>>>> so worried, this is new code, and we've isolated from the raw NAND
>>>> layer, so if it's buggy or instable at the beginning it's not a big
>>>> deal, it will be noticed and fixed for the next few releases.
>>>>
>>>>>
>>>>> Thanks for your patience and best regards,
>>>>
>>>> No problem. Thanks for your work, and I'll try to be more active on
>>>> this topic (I promised that several times, and failed it :-/).

I hope, that as more people get interested in the topic, more people 
will join. Thanks in advance for your further work on this.

>> So here are the next set of things to do if you want to move forward:
>> 1/ Re-submit the preparation patches (those touching MTD core) and
>>     review them (or find someone to review them)
>> 2/ Add the missing doc to the code (I was planning on doing that, but
>>     if you're in hurry you can take care of it), and add real commit
>>     messages.
>> 3/ Fix the authorship on patches (some were mainly written by you, but
>>     during my rework authorship has been lost)
>> 4/ Ask others to test and review the patches
> 
> To be honest, I also feel bad to keep pushing you on this...
> I will try to communicate with them to see if they can help us to do some review
> or valudation task.
> You already make the path clear, I will take the rest. If anything
> unclear, I will come
> back to discuss with you.

I don't have any experience in reviewing kernel code and only little in 
submitting patches, but if I can be of any help let me know.

As I have a certain use case and the hardware, I will also be happy to 
help testing.

Thanks and regards

Frieder

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-14 14:39                       ` Frieder Schrempf
@ 2017-12-14 14:43                         ` Frieder Schrempf
  2017-12-14 15:38                         ` Boris Brezillon
  1 sibling, 0 replies; 65+ messages in thread
From: Frieder Schrempf @ 2017-12-14 14:43 UTC (permalink / raw)
  To: Peter Pan, Boris Brezillon
  Cc: Peter Pan 潘栋 (peterpandong), linux-mtd

Forgot the link: [1]: 
https://github.com/fschrempf/linux-0day/compare/374c97f3a6b8e83dd1b005a3aec64d7008259185...fschrempf:spi-nand-exceet

On 14.12.2017 15:39, Frieder Schrempf wrote:
> Hello Peter, hello Boris
> 
>>>>>> What I did so far:
>>>>>>
>>>>>> * Rebase your patches on latest Linux 4.14.5
>>>>>
>>>>> Cool, rebasing on 4.15-rc1 would be even better, but I can do that if
>>>>> you don't have the time.
> 
> I will try to rebase on 4.15-rc1. Can you give me a quick explanation on 
> which patches are needed for SPI NAND + preparation, if I only want to 
> add the generic NAND and the SPI NAND layer?
> Previously I just rebased the whole branch, but I think you have some 
> other pending patches in there?
> Would this be the correct changeset: [1]
> Or are there other preparation patches needed?
> 
>>>>>> I guess you would like to have the basic framework with Micron 
>>>>>> support
>>>>>> and generic SPI tested and stabilized first, before adding more code,
>>>>>> but to be able to test with our hardware I need Micron and FSL QSPI.
>>>>>
>>>>> I guess you mean Winbond not Micron. That's okay if those patches are
>>>>> posted after the initial series. All I need is reviews and tests from
>>>>> different parties, so that I'm less confident in merging the code.
> 
> Yeah I meant Winbond of course. And I guess you meant "more confident". 
> Or that was just irony? Nevermind ;)
> 
>>>>>> Some questions/flaws that occurred to me:
>>>>>>
>>>>>> * The W25M02GV chip has two dies of 128M each. My current driver only
>>>>>> makes use of the first die. The chip expects a die-select command to
>>>>>> switch between the two dies.
>>>>>> What would be the place to implement this?
>>>>>> Can I just add the command and issue it in
>>>>>> winbond_spinand_adjust_cache_op if luns_per_target > 1?
>>>>>
>>>>> It really depends when the die selection happens. I guess it 
>>>>> happens in
>>>>> 2 places: when preparing a program/read operation and when doing the
>>>>> transfer to the in-chip cache. Anyway, the die information is already
>>>>> passed in the nand_pos object, so all you'll have to do is create a 
>>>>> new
>>>>> hook to customize the SPI command when needed.
> 
> The die selection is a separate SPI command and not integrated into the 
> program/read/erase sequence.
> So I can't customize an existing op, but have to issue a new "die 
> select" op.
> 
>>>>
>>>> I don't know whether we can do the the die switch in the generic 
>>>> NAND core
>>>> (drivers/mtd/nand/core.c). I'm not sure if chip->select_chip() in 
>>>> nand_base.c
>>>> does the same thing or not. If so, we can do the die switch before
>>>> read/write/erase
>>>> operation. And let spi nand core to implement a hook to support it.
>>>
>>> Actually, I'm trying to move away from this ->select_chip() approach in
>>> the raw NAND framework, simply because the controller might be able to
>>> parallelize operations (like 2 erase on 2 different dies, or one erase
>>> on one die, and a program on the other), and having this ->select_chip()
>>> done early in the chain prevents this kind of optimization.
>>>
>>> Anyway, the controller should now have all the necessary information to
>>> know which die an operation should be executed on, and if a specific
>>> command has to be sent to the device to select a specific die, it can
>>> be done in the NAND vendor specific code.
> 
> But needing a die select op is quite common for any multi-die chips, 
> isn't it?
> So shouldn't there be an spinand_die_select_op in the SPI NAND core that 
> is executed when necessary and skipped if there's only one die.
> 
>> Got your point. It makes sense.
>>>
>>>>>> * The FSL QSPI controller has a lookup table that needs to be filled
>>>>>> with command sequences at the time of setup. Therefore the number of
>>>>>> dummy bytes for each command is fixed and in my current 
>>>>>> implementation
>>>>>> op->dummy_bytes is ignored.
>>>>>> That's not a problem if all chips need the same number of dummy bytes
>>>>>> for each command, but I guess that's not the case, as there is a
>>>>>> _spinand_get_dummy function.
>>>>>
>>>>> We should definitely expose that in a generic way, and on a
>>>>> per-operation basis, so that, after the detection step, the NAND
>>>>> controller can query this information.
> 
> Ok, I might try this and see where it leads me.
> 
>>>>>> * What is your plan for ECC and BBT? At least enabling the onchip ECC
>>>>>> will be necessary to be able to use the flash properly (e.g. with 
>>>>>> UBI),
>>>>>> or am I wrong?
>>>>>
>>>>> Well, if all SPI NAND chips are supporting ECC the same way and
>>>>> on-die ECC support is mandatory for SPI NANDs, then supporting that
>>>>> directly in the core is probably the best option. If, on the other
>>>>> hand, you have various implementations, and some SPI controllers have
>>>>> their own ECC engine that you can use with SPI NANDs, then it's
>>>>> probably a better idea to abstract ECC engine in the generic NAND 
>>>>> layer.
>>>>
>>>> As far as I know, all the SPI NAND supports on-die ECC (at least all
>>>> the SPI NAND
>>>> I heard). But different chips may have different ECC layout in OOB
>>>> area. But I think
>>>> this cannot be a problem, we can handle this in vendor's file.
>>>
>>> Yep.
> 
> Ok. If I have time I will think about how the ECC and OOB layout might 
> be implemented. But I have not much experience here, so if anyone of you 
> can propose something to get started, this would be great.
> 
>>>>> For BBTs, I'd like to have a clean version of the nand_bbt logic that
>>>>> uses all of the helpers exposed by the generic NAND layer. I'd also
>>>>> like to simplify the code if possible.
>>>>>
>>>>>>
>>>>>> * Do you have any special test cases? What do you usually do to 
>>>>>> test the
>>>>>> code?
>>>>>
>>>>> Well, make sure all the mtd tests are passing (drivers/mtd/tests), and
>>>>> then, the next step is to test it with UBI+UBIFS. But honestly, I'm 
>>>>> not
>>>>> so worried, this is new code, and we've isolated from the raw NAND
>>>>> layer, so if it's buggy or instable at the beginning it's not a big
>>>>> deal, it will be noticed and fixed for the next few releases.
>>>>>
>>>>>>
>>>>>> Thanks for your patience and best regards,
>>>>>
>>>>> No problem. Thanks for your work, and I'll try to be more active on
>>>>> this topic (I promised that several times, and failed it :-/).
> 
> I hope, that as more people get interested in the topic, more people 
> will join. Thanks in advance for your further work on this.
> 
>>> So here are the next set of things to do if you want to move forward:
>>> 1/ Re-submit the preparation patches (those touching MTD core) and
>>>     review them (or find someone to review them)
>>> 2/ Add the missing doc to the code (I was planning on doing that, but
>>>     if you're in hurry you can take care of it), and add real commit
>>>     messages.
>>> 3/ Fix the authorship on patches (some were mainly written by you, but
>>>     during my rework authorship has been lost)
>>> 4/ Ask others to test and review the patches
>>
>> To be honest, I also feel bad to keep pushing you on this...
>> I will try to communicate with them to see if they can help us to do 
>> some review
>> or valudation task.
>> You already make the path clear, I will take the rest. If anything
>> unclear, I will come
>> back to discuss with you.
> 
> I don't have any experience in reviewing kernel code and only little in 
> submitting patches, but if I can be of any help let me know.
> 
> As I have a certain use case and the hardware, I will also be happy to 
> help testing.
> 
> Thanks and regards
> 
> Frieder

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-14 14:39                       ` Frieder Schrempf
  2017-12-14 14:43                         ` Frieder Schrempf
@ 2017-12-14 15:38                         ` Boris Brezillon
  2017-12-15  1:08                           ` Peter Pan
  1 sibling, 1 reply; 65+ messages in thread
From: Boris Brezillon @ 2017-12-14 15:38 UTC (permalink / raw)
  To: Frieder Schrempf
  Cc: Peter Pan, Peter Pan 潘栋 (peterpandong), linux-mtd

On Thu, 14 Dec 2017 15:39:13 +0100
Frieder Schrempf <frieder.schrempf@exceet.de> wrote:

> Hello Peter, hello Boris
> 
> >>>>> What I did so far:
> >>>>>
> >>>>> * Rebase your patches on latest Linux 4.14.5  
> >>>>
> >>>> Cool, rebasing on 4.15-rc1 would be even better, but I can do that if
> >>>> you don't have the time.  
> 
> I will try to rebase on 4.15-rc1. Can you give me a quick explanation on 
> which patches are needed for SPI NAND + preparation, if I only want to 
> add the generic NAND and the SPI NAND layer?
> Previously I just rebased the whole branch, but I think you have some 
> other pending patches in there?
> Would this be the correct changeset: [1]
> Or are there other preparation patches needed?

Looks good. By preparation patches I meant

from:
"mtd: Do not allow MTD devices with inconsistent erase properties"
to
"mtd: nand: move raw NAND related code to the raw/ subdir"

so basically everything that touches existing code.

> 
> >>>>> I guess you would like to have the basic framework with Micron support
> >>>>> and generic SPI tested and stabilized first, before adding more code,
> >>>>> but to be able to test with our hardware I need Micron and FSL QSPI.  
> >>>>
> >>>> I guess you mean Winbond not Micron. That's okay if those patches are
> >>>> posted after the initial series. All I need is reviews and tests from
> >>>> different parties, so that I'm less confident in merging the code.  
> 
> Yeah I meant Winbond of course. And I guess you meant "more confident". 

Yep.

> Or that was just irony? Nevermind ;)
> 
> >>>>> Some questions/flaws that occurred to me:
> >>>>>
> >>>>> * The W25M02GV chip has two dies of 128M each. My current driver only
> >>>>> makes use of the first die. The chip expects a die-select command to
> >>>>> switch between the two dies.
> >>>>> What would be the place to implement this?
> >>>>> Can I just add the command and issue it in
> >>>>> winbond_spinand_adjust_cache_op if luns_per_target > 1?  
> >>>>
> >>>> It really depends when the die selection happens. I guess it happens in
> >>>> 2 places: when preparing a program/read operation and when doing the
> >>>> transfer to the in-chip cache. Anyway, the die information is already
> >>>> passed in the nand_pos object, so all you'll have to do is create a new
> >>>> hook to customize the SPI command when needed.  
> 
> The die selection is a separate SPI command and not integrated into the 
> program/read/erase sequence.
> So I can't customize an existing op, but have to issue a new "die 
> select" op.

Okay.

> 
> >>>
> >>> I don't know whether we can do the the die switch in the generic NAND core
> >>> (drivers/mtd/nand/core.c). I'm not sure if chip->select_chip() in nand_base.c
> >>> does the same thing or not. If so, we can do the die switch before
> >>> read/write/erase
> >>> operation. And let spi nand core to implement a hook to support it.  
> >>
> >> Actually, I'm trying to move away from this ->select_chip() approach in
> >> the raw NAND framework, simply because the controller might be able to
> >> parallelize operations (like 2 erase on 2 different dies, or one erase
> >> on one die, and a program on the other), and having this ->select_chip()
> >> done early in the chain prevents this kind of optimization.
> >>
> >> Anyway, the controller should now have all the necessary information to
> >> know which die an operation should be executed on, and if a specific
> >> command has to be sent to the device to select a specific die, it can
> >> be done in the NAND vendor specific code.  
> 
> But needing a die select op is quite common for any multi-die chips, 
> isn't it?

It is, it's just that some controllers are able to interleave
operations on multiple dies, so having  ->{select,unselect}_chip()
methods at the generic NAND level is not such a good idea, because that
means you'll have to serialize accesses, even if they could be done in
parallel.

> So shouldn't there be an spinand_die_select_op in the SPI NAND core that 
> is executed when necessary and skipped if there's only one die.

Sure, I was arguing against a ->select_chip() at the generic NAND
level. That's something you can add in the SPI NAND framework.

> 
> > Got your point. It makes sense.  
> >>  
> >>>>> * The FSL QSPI controller has a lookup table that needs to be filled
> >>>>> with command sequences at the time of setup. Therefore the number of
> >>>>> dummy bytes for each command is fixed and in my current implementation
> >>>>> op->dummy_bytes is ignored.
> >>>>> That's not a problem if all chips need the same number of dummy bytes
> >>>>> for each command, but I guess that's not the case, as there is a
> >>>>> _spinand_get_dummy function.  
> >>>>
> >>>> We should definitely expose that in a generic way, and on a
> >>>> per-operation basis, so that, after the detection step, the NAND
> >>>> controller can query this information.  
> 
> Ok, I might try this and see where it leads me.
> 
> >>>>> * What is your plan for ECC and BBT? At least enabling the onchip ECC
> >>>>> will be necessary to be able to use the flash properly (e.g. with UBI),
> >>>>> or am I wrong?  
> >>>>
> >>>> Well, if all SPI NAND chips are supporting ECC the same way and
> >>>> on-die ECC support is mandatory for SPI NANDs, then supporting that
> >>>> directly in the core is probably the best option. If, on the other
> >>>> hand, you have various implementations, and some SPI controllers have
> >>>> their own ECC engine that you can use with SPI NANDs, then it's
> >>>> probably a better idea to abstract ECC engine in the generic NAND layer.  
> >>>
> >>> As far as I know, all the SPI NAND supports on-die ECC (at least all
> >>> the SPI NAND
> >>> I heard). But different chips may have different ECC layout in OOB
> >>> area. But I think
> >>> this cannot be a problem, we can handle this in vendor's file.  
> >>
> >> Yep.  
> 
> Ok. If I have time I will think about how the ECC and OOB layout might 
> be implemented. But I have not much experience here, so if anyone of you 
> can propose something to get started, this would be great.

I can definitely help there, and Peter should be able to give some
insights as well.

> 
> >>>> For BBTs, I'd like to have a clean version of the nand_bbt logic that
> >>>> uses all of the helpers exposed by the generic NAND layer. I'd also
> >>>> like to simplify the code if possible.
> >>>>  
> >>>>>
> >>>>> * Do you have any special test cases? What do you usually do to test the
> >>>>> code?  
> >>>>
> >>>> Well, make sure all the mtd tests are passing (drivers/mtd/tests), and
> >>>> then, the next step is to test it with UBI+UBIFS. But honestly, I'm not
> >>>> so worried, this is new code, and we've isolated from the raw NAND
> >>>> layer, so if it's buggy or instable at the beginning it's not a big
> >>>> deal, it will be noticed and fixed for the next few releases.
> >>>>  
> >>>>>
> >>>>> Thanks for your patience and best regards,  
> >>>>
> >>>> No problem. Thanks for your work, and I'll try to be more active on
> >>>> this topic (I promised that several times, and failed it :-/).  
> 
> I hope, that as more people get interested in the topic, more people 
> will join. Thanks in advance for your further work on this.
> 
> >> So here are the next set of things to do if you want to move forward:
> >> 1/ Re-submit the preparation patches (those touching MTD core) and
> >>     review them (or find someone to review them)
> >> 2/ Add the missing doc to the code (I was planning on doing that, but
> >>     if you're in hurry you can take care of it), and add real commit
> >>     messages.
> >> 3/ Fix the authorship on patches (some were mainly written by you, but
> >>     during my rework authorship has been lost)
> >> 4/ Ask others to test and review the patches  
> > 
> > To be honest, I also feel bad to keep pushing you on this...
> > I will try to communicate with them to see if they can help us to do some review
> > or valudation task.
> > You already make the path clear, I will take the rest. If anything
> > unclear, I will come
> > back to discuss with you.  
> 
> I don't have any experience in reviewing kernel code and only little in 
> submitting patches, but if I can be of any help let me know.
> 
> As I have a certain use case and the hardware, I will also be happy to 
> help testing.

Testing and reporting issues is already helpful.

Thanks,

Boris

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-14 15:38                         ` Boris Brezillon
@ 2017-12-15  1:08                           ` Peter Pan
  2017-12-15  1:21                             ` Peter Pan
  0 siblings, 1 reply; 65+ messages in thread
From: Peter Pan @ 2017-12-15  1:08 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Frieder Schrempf, Peter Pan 潘栋 (peterpandong), linux-mtd

Hi Boris and Frieder

On Thu, Dec 14, 2017 at 11:38 PM, Boris Brezillon
<boris.brezillon@free-electrons.com> wrote:
> On Thu, 14 Dec 2017 15:39:13 +0100
> Frieder Schrempf <frieder.schrempf@exceet.de> wrote:
>
>> Hello Peter, hello Boris
>>
>> >>>>> What I did so far:
>> >>>>>
>> >>>>> * Rebase your patches on latest Linux 4.14.5
>> >>>>
>> >>>> Cool, rebasing on 4.15-rc1 would be even better, but I can do that if
>> >>>> you don't have the time.
>>
>> I will try to rebase on 4.15-rc1. Can you give me a quick explanation on
>> which patches are needed for SPI NAND + preparation, if I only want to
>> add the generic NAND and the SPI NAND layer?
>> Previously I just rebased the whole branch, but I think you have some
>> other pending patches in there?
>> Would this be the correct changeset: [1]
>> Or are there other preparation patches needed?
>
> Looks good. By preparation patches I meant
>
> from:
> "mtd: Do not allow MTD devices with inconsistent erase properties"
> to
> "mtd: nand: move raw NAND related code to the raw/ subdir"
>
> so basically everything that touches existing code.

I think "mtd: Add sanity checks in mtd_write/read_oob()" is also
included since I cannot
find it in nand/next branch of l2-mtd

>
>>
>> >>>>> I guess you would like to have the basic framework with Micron support
>> >>>>> and generic SPI tested and stabilized first, before adding more code,
>> >>>>> but to be able to test with our hardware I need Micron and FSL QSPI.
>> >>>>
>> >>>> I guess you mean Winbond not Micron. That's okay if those patches are
>> >>>> posted after the initial series. All I need is reviews and tests from
>> >>>> different parties, so that I'm less confident in merging the code.
>>
>> Yeah I meant Winbond of course. And I guess you meant "more confident".
>
> Yep.
>
>> Or that was just irony? Nevermind ;)
>>
>> >>>>> Some questions/flaws that occurred to me:
>> >>>>>
>> >>>>> * The W25M02GV chip has two dies of 128M each. My current driver only
>> >>>>> makes use of the first die. The chip expects a die-select command to
>> >>>>> switch between the two dies.
>> >>>>> What would be the place to implement this?
>> >>>>> Can I just add the command and issue it in
>> >>>>> winbond_spinand_adjust_cache_op if luns_per_target > 1?
>> >>>>
>> >>>> It really depends when the die selection happens. I guess it happens in
>> >>>> 2 places: when preparing a program/read operation and when doing the
>> >>>> transfer to the in-chip cache. Anyway, the die information is already
>> >>>> passed in the nand_pos object, so all you'll have to do is create a new
>> >>>> hook to customize the SPI command when needed.
>>
>> The die selection is a separate SPI command and not integrated into the
>> program/read/erase sequence.
>> So I can't customize an existing op, but have to issue a new "die
>> select" op.
>
> Okay.
>
>>
>> >>>
>> >>> I don't know whether we can do the the die switch in the generic NAND core
>> >>> (drivers/mtd/nand/core.c). I'm not sure if chip->select_chip() in nand_base.c
>> >>> does the same thing or not. If so, we can do the die switch before
>> >>> read/write/erase
>> >>> operation. And let spi nand core to implement a hook to support it.
>> >>
>> >> Actually, I'm trying to move away from this ->select_chip() approach in
>> >> the raw NAND framework, simply because the controller might be able to
>> >> parallelize operations (like 2 erase on 2 different dies, or one erase
>> >> on one die, and a program on the other), and having this ->select_chip()
>> >> done early in the chain prevents this kind of optimization.
>> >>
>> >> Anyway, the controller should now have all the necessary information to
>> >> know which die an operation should be executed on, and if a specific
>> >> command has to be sent to the device to select a specific die, it can
>> >> be done in the NAND vendor specific code.
>>
>> But needing a die select op is quite common for any multi-die chips,
>> isn't it?
>
> It is, it's just that some controllers are able to interleave
> operations on multiple dies, so having  ->{select,unselect}_chip()
> methods at the generic NAND level is not such a good idea, because that
> means you'll have to serialize accesses, even if they could be done in
> parallel.
>
>> So shouldn't there be an spinand_die_select_op in the SPI NAND core that
>> is executed when necessary and skipped if there's only one die.
>
> Sure, I was arguing against a ->select_chip() at the generic NAND
> level. That's something you can add in the SPI NAND framework.
>
>>
>> > Got your point. It makes sense.
>> >>
>> >>>>> * The FSL QSPI controller has a lookup table that needs to be filled
>> >>>>> with command sequences at the time of setup. Therefore the number of
>> >>>>> dummy bytes for each command is fixed and in my current implementation
>> >>>>> op->dummy_bytes is ignored.
>> >>>>> That's not a problem if all chips need the same number of dummy bytes
>> >>>>> for each command, but I guess that's not the case, as there is a
>> >>>>> _spinand_get_dummy function.
>> >>>>
>> >>>> We should definitely expose that in a generic way, and on a
>> >>>> per-operation basis, so that, after the detection step, the NAND
>> >>>> controller can query this information.
>>
>> Ok, I might try this and see where it leads me.
>>
>> >>>>> * What is your plan for ECC and BBT? At least enabling the onchip ECC
>> >>>>> will be necessary to be able to use the flash properly (e.g. with UBI),
>> >>>>> or am I wrong?
>> >>>>
>> >>>> Well, if all SPI NAND chips are supporting ECC the same way and
>> >>>> on-die ECC support is mandatory for SPI NANDs, then supporting that
>> >>>> directly in the core is probably the best option. If, on the other
>> >>>> hand, you have various implementations, and some SPI controllers have
>> >>>> their own ECC engine that you can use with SPI NANDs, then it's
>> >>>> probably a better idea to abstract ECC engine in the generic NAND layer.
>> >>>
>> >>> As far as I know, all the SPI NAND supports on-die ECC (at least all
>> >>> the SPI NAND
>> >>> I heard). But different chips may have different ECC layout in OOB
>> >>> area. But I think
>> >>> this cannot be a problem, we can handle this in vendor's file.
>> >>
>> >> Yep.
>>
>> Ok. If I have time I will think about how the ECC and OOB layout might
>> be implemented. But I have not much experience here, so if anyone of you
>> can propose something to get started, this would be great.
>
> I can definitely help there, and Peter should be able to give some
> insights as well.

Frieder.

Actually the v5 patchset of SPI NAND framework from me[1] includes on-die ECC.
You can have a reference (maybe patch 2 and patch 4 is enough).
Of course v5 is quite different with the latest code, but I think you
can get some idea from it.

>
>>
>> >>>> For BBTs, I'd like to have a clean version of the nand_bbt logic that
>> >>>> uses all of the helpers exposed by the generic NAND layer. I'd also
>> >>>> like to simplify the code if possible.
>> >>>>
>> >>>>>
>> >>>>> * Do you have any special test cases? What do you usually do to test the
>> >>>>> code?
>> >>>>
>> >>>> Well, make sure all the mtd tests are passing (drivers/mtd/tests), and
>> >>>> then, the next step is to test it with UBI+UBIFS. But honestly, I'm not
>> >>>> so worried, this is new code, and we've isolated from the raw NAND
>> >>>> layer, so if it's buggy or instable at the beginning it's not a big
>> >>>> deal, it will be noticed and fixed for the next few releases.
>> >>>>
>> >>>>>
>> >>>>> Thanks for your patience and best regards,
>> >>>>
>> >>>> No problem. Thanks for your work, and I'll try to be more active on
>> >>>> this topic (I promised that several times, and failed it :-/).
>>
>> I hope, that as more people get interested in the topic, more people
>> will join. Thanks in advance for your further work on this.
>>
>> >> So here are the next set of things to do if you want to move forward:
>> >> 1/ Re-submit the preparation patches (those touching MTD core) and
>> >>     review them (or find someone to review them)
>> >> 2/ Add the missing doc to the code (I was planning on doing that, but
>> >>     if you're in hurry you can take care of it), and add real commit
>> >>     messages.
>> >> 3/ Fix the authorship on patches (some were mainly written by you, but
>> >>     during my rework authorship has been lost)
>> >> 4/ Ask others to test and review the patches
>> >
>> > To be honest, I also feel bad to keep pushing you on this...
>> > I will try to communicate with them to see if they can help us to do some review
>> > or valudation task.
>> > You already make the path clear, I will take the rest. If anything
>> > unclear, I will come
>> > back to discuss with you.
>>
>> I don't have any experience in reviewing kernel code and only little in
>> submitting patches, but if I can be of any help let me know.
>>
>> As I have a certain use case and the hardware, I will also be happy to
>> help testing.
>
> Testing and reporting issues is already helpful.

I would like to thank you for your help in advance, Frieder.


Thanks,
Peter Pan

[1] http://patchwork.ozlabs.org/project/linux-mtd/list/?series=&submitter=65489&state=9&q=v5&archive=&delegate=

>
> Thanks,
>
> Boris

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-15  1:08                           ` Peter Pan
@ 2017-12-15  1:21                             ` Peter Pan
  2017-12-21 11:48                               ` Frieder Schrempf
  0 siblings, 1 reply; 65+ messages in thread
From: Peter Pan @ 2017-12-15  1:21 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Frieder Schrempf, Peter Pan 潘栋 (peterpandong), linux-mtd

Hi Boris,

On Fri, Dec 15, 2017 at 9:08 AM, Peter Pan <peterpansjtu@gmail.com> wrote:
> Hi Boris and Frieder
>
> On Thu, Dec 14, 2017 at 11:38 PM, Boris Brezillon
> <boris.brezillon@free-electrons.com> wrote:
>> On Thu, 14 Dec 2017 15:39:13 +0100
>> Frieder Schrempf <frieder.schrempf@exceet.de> wrote:
>>
>>> Hello Peter, hello Boris
>>>
>>> >>>>> What I did so far:
>>> >>>>>
>>> >>>>> * Rebase your patches on latest Linux 4.14.5
>>> >>>>
>>> >>>> Cool, rebasing on 4.15-rc1 would be even better, but I can do that if
>>> >>>> you don't have the time.
>>>
>>> I will try to rebase on 4.15-rc1. Can you give me a quick explanation on
>>> which patches are needed for SPI NAND + preparation, if I only want to
>>> add the generic NAND and the SPI NAND layer?
>>> Previously I just rebased the whole branch, but I think you have some
>>> other pending patches in there?
>>> Would this be the correct changeset: [1]
>>> Or are there other preparation patches needed?
>>
>> Looks good. By preparation patches I meant
>>
>> from:
>> "mtd: Do not allow MTD devices with inconsistent erase properties"
>> to
>> "mtd: nand: move raw NAND related code to the raw/ subdir"
>>
>> so basically everything that touches existing code.
>
> I think "mtd: Add sanity checks in mtd_write/read_oob()" is also
> included since I cannot
> find it in nand/next branch of l2-mtd

Sorry, my mistake. it is in nand/next.

>
>>
>>>
>>> >>>>> I guess you would like to have the basic framework with Micron support
>>> >>>>> and generic SPI tested and stabilized first, before adding more code,
>>> >>>>> but to be able to test with our hardware I need Micron and FSL QSPI.
>>> >>>>
>>> >>>> I guess you mean Winbond not Micron. That's okay if those patches are
>>> >>>> posted after the initial series. All I need is reviews and tests from
>>> >>>> different parties, so that I'm less confident in merging the code.
>>>
>>> Yeah I meant Winbond of course. And I guess you meant "more confident".
>>
>> Yep.
>>
>>> Or that was just irony? Nevermind ;)
>>>
>>> >>>>> Some questions/flaws that occurred to me:
>>> >>>>>
>>> >>>>> * The W25M02GV chip has two dies of 128M each. My current driver only
>>> >>>>> makes use of the first die. The chip expects a die-select command to
>>> >>>>> switch between the two dies.
>>> >>>>> What would be the place to implement this?
>>> >>>>> Can I just add the command and issue it in
>>> >>>>> winbond_spinand_adjust_cache_op if luns_per_target > 1?
>>> >>>>
>>> >>>> It really depends when the die selection happens. I guess it happens in
>>> >>>> 2 places: when preparing a program/read operation and when doing the
>>> >>>> transfer to the in-chip cache. Anyway, the die information is already
>>> >>>> passed in the nand_pos object, so all you'll have to do is create a new
>>> >>>> hook to customize the SPI command when needed.
>>>
>>> The die selection is a separate SPI command and not integrated into the
>>> program/read/erase sequence.
>>> So I can't customize an existing op, but have to issue a new "die
>>> select" op.
>>
>> Okay.
>>
>>>
>>> >>>
>>> >>> I don't know whether we can do the the die switch in the generic NAND core
>>> >>> (drivers/mtd/nand/core.c). I'm not sure if chip->select_chip() in nand_base.c
>>> >>> does the same thing or not. If so, we can do the die switch before
>>> >>> read/write/erase
>>> >>> operation. And let spi nand core to implement a hook to support it.
>>> >>
>>> >> Actually, I'm trying to move away from this ->select_chip() approach in
>>> >> the raw NAND framework, simply because the controller might be able to
>>> >> parallelize operations (like 2 erase on 2 different dies, or one erase
>>> >> on one die, and a program on the other), and having this ->select_chip()
>>> >> done early in the chain prevents this kind of optimization.
>>> >>
>>> >> Anyway, the controller should now have all the necessary information to
>>> >> know which die an operation should be executed on, and if a specific
>>> >> command has to be sent to the device to select a specific die, it can
>>> >> be done in the NAND vendor specific code.
>>>
>>> But needing a die select op is quite common for any multi-die chips,
>>> isn't it?
>>
>> It is, it's just that some controllers are able to interleave
>> operations on multiple dies, so having  ->{select,unselect}_chip()
>> methods at the generic NAND level is not such a good idea, because that
>> means you'll have to serialize accesses, even if they could be done in
>> parallel.
>>
>>> So shouldn't there be an spinand_die_select_op in the SPI NAND core that
>>> is executed when necessary and skipped if there's only one die.
>>
>> Sure, I was arguing against a ->select_chip() at the generic NAND
>> level. That's something you can add in the SPI NAND framework.
>>
>>>
>>> > Got your point. It makes sense.
>>> >>
>>> >>>>> * The FSL QSPI controller has a lookup table that needs to be filled
>>> >>>>> with command sequences at the time of setup. Therefore the number of
>>> >>>>> dummy bytes for each command is fixed and in my current implementation
>>> >>>>> op->dummy_bytes is ignored.
>>> >>>>> That's not a problem if all chips need the same number of dummy bytes
>>> >>>>> for each command, but I guess that's not the case, as there is a
>>> >>>>> _spinand_get_dummy function.
>>> >>>>
>>> >>>> We should definitely expose that in a generic way, and on a
>>> >>>> per-operation basis, so that, after the detection step, the NAND
>>> >>>> controller can query this information.
>>>
>>> Ok, I might try this and see where it leads me.
>>>
>>> >>>>> * What is your plan for ECC and BBT? At least enabling the onchip ECC
>>> >>>>> will be necessary to be able to use the flash properly (e.g. with UBI),
>>> >>>>> or am I wrong?
>>> >>>>
>>> >>>> Well, if all SPI NAND chips are supporting ECC the same way and
>>> >>>> on-die ECC support is mandatory for SPI NANDs, then supporting that
>>> >>>> directly in the core is probably the best option. If, on the other
>>> >>>> hand, you have various implementations, and some SPI controllers have
>>> >>>> their own ECC engine that you can use with SPI NANDs, then it's
>>> >>>> probably a better idea to abstract ECC engine in the generic NAND layer.
>>> >>>
>>> >>> As far as I know, all the SPI NAND supports on-die ECC (at least all
>>> >>> the SPI NAND
>>> >>> I heard). But different chips may have different ECC layout in OOB
>>> >>> area. But I think
>>> >>> this cannot be a problem, we can handle this in vendor's file.
>>> >>
>>> >> Yep.
>>>
>>> Ok. If I have time I will think about how the ECC and OOB layout might
>>> be implemented. But I have not much experience here, so if anyone of you
>>> can propose something to get started, this would be great.
>>
>> I can definitely help there, and Peter should be able to give some
>> insights as well.
>
> Frieder.
>
> Actually the v5 patchset of SPI NAND framework from me[1] includes on-die ECC.
> You can have a reference (maybe patch 2 and patch 4 is enough).
> Of course v5 is quite different with the latest code, but I think you
> can get some idea from it.
>
>>
>>>
>>> >>>> For BBTs, I'd like to have a clean version of the nand_bbt logic that
>>> >>>> uses all of the helpers exposed by the generic NAND layer. I'd also
>>> >>>> like to simplify the code if possible.
>>> >>>>
>>> >>>>>
>>> >>>>> * Do you have any special test cases? What do you usually do to test the
>>> >>>>> code?
>>> >>>>
>>> >>>> Well, make sure all the mtd tests are passing (drivers/mtd/tests), and
>>> >>>> then, the next step is to test it with UBI+UBIFS. But honestly, I'm not
>>> >>>> so worried, this is new code, and we've isolated from the raw NAND
>>> >>>> layer, so if it's buggy or instable at the beginning it's not a big
>>> >>>> deal, it will be noticed and fixed for the next few releases.
>>> >>>>
>>> >>>>>
>>> >>>>> Thanks for your patience and best regards,
>>> >>>>
>>> >>>> No problem. Thanks for your work, and I'll try to be more active on
>>> >>>> this topic (I promised that several times, and failed it :-/).
>>>
>>> I hope, that as more people get interested in the topic, more people
>>> will join. Thanks in advance for your further work on this.
>>>
>>> >> So here are the next set of things to do if you want to move forward:
>>> >> 1/ Re-submit the preparation patches (those touching MTD core) and
>>> >>     review them (or find someone to review them)
>>> >> 2/ Add the missing doc to the code (I was planning on doing that, but
>>> >>     if you're in hurry you can take care of it), and add real commit
>>> >>     messages.
>>> >> 3/ Fix the authorship on patches (some were mainly written by you, but
>>> >>     during my rework authorship has been lost)
>>> >> 4/ Ask others to test and review the patches
>>> >
>>> > To be honest, I also feel bad to keep pushing you on this...
>>> > I will try to communicate with them to see if they can help us to do some review
>>> > or valudation task.
>>> > You already make the path clear, I will take the rest. If anything
>>> > unclear, I will come
>>> > back to discuss with you.
>>>
>>> I don't have any experience in reviewing kernel code and only little in
>>> submitting patches, but if I can be of any help let me know.
>>>
>>> As I have a certain use case and the hardware, I will also be happy to
>>> help testing.
>>
>> Testing and reporting issues is already helpful.
>
> I would like to thank you for your help in advance, Frieder.
>
>
> Thanks,
> Peter Pan
>
> [1] http://patchwork.ozlabs.org/project/linux-mtd/list/?series=&submitter=65489&state=9&q=v5&archive=&delegate=
>
>>
>> Thanks,
>>
>> Boris

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-14  7:50                   ` Boris Brezillon
  2017-12-14  8:06                     ` Peter Pan
@ 2017-12-15  2:35                     ` Peter Pan
  2017-12-15 12:41                       ` Boris Brezillon
  1 sibling, 1 reply; 65+ messages in thread
From: Peter Pan @ 2017-12-15  2:35 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Frieder Schrempf, Peter Pan 潘栋 (peterpandong), linux-mtd

Hi Boris

On Thu, Dec 14, 2017 at 3:50 PM, Boris Brezillon
<boris.brezillon@free-electrons.com> wrote:
> Hi Peter,
>
> On Thu, 14 Dec 2017 14:15:57 +0800
> Peter Pan <peterpansjtu@gmail.com> wrote:
>
>> Hi Boris and Frieder,
>>
>> On Thu, Dec 14, 2017 at 5:27 AM, Boris Brezillon
>> <boris.brezillon@free-electrons.com> wrote:
>> > Hi Frieder,
>> >
>> > On Tue, 12 Dec 2017 10:58:10 +0100
>> > Frieder Schrempf <frieder.schrempf@exceet.de> wrote:
>> >
>> >> Hi Boris,
>> >>
>> >> I spent some time looking at and working with your latest SPI NAND code.
>> >> In my previous mail I said, that we have some working code for our 3.14
>> >> kernel based on the "mt29f_spinand" staging driver, but that was wrong
>> >> as I got things mixed up in my head.
>> >> Actually our codebase was an early version of Peter's code, so the
>> >> effort to port it to the latest framework code was not that big.
>> >>
>> >> I forked your repo and you can find my working tree at [1].
>> >
>> > Great, I'll try to have a look.
>> >
>> >>
>> >> What I did so far:
>> >>
>> >> * Rebase your patches on latest Linux 4.14.5
>> >
>> > Cool, rebasing on 4.15-rc1 would be even better, but I can do that if
>> > you don't have the time.
>> >
>> >>
>> >> * Add a driver for the Winbond W25M02GV SPI NAND chip, that we have on
>> >> some of our boards.
>> >
>> > Okay, that's actually a good thing to have tested with another chip,
>> > This way we can make sure the framework is generic enough.
>> >
>> >>
>> >> * Add a driver for the Freescale QSPI controller, derived from the
>> >> existing QSPI-NOR driver at drivers/mtd/spi-nor/fsl-quadspi.c.
>> >
>> > That's an interesting case as well, the generic NAND controller is
>> > probably the easiest implementation, and that's a good thing to have
>> > another controller.
>> >
>> >>
>> >> * Add a setup and setup_late op to the controller layer (see [3]). I
>> >> don't know if that makes sense, but at least the setup_late is needed
>> >> for the FSL QSPI driver, as it needs to know the size of the flash to
>> >> setup the memory mapping for the QSPI read operations.
>> >
>> > Hm, not sure what ->setup_late() is for, but I'll have a look.
>> >
>> >>
>> >> * A bit of testing and fixing two small bugs, which look like copy and
>> >> paste mistakes. See [2].
>> >
>> > Thanks, I'll squash the fixes in the original commit.
>> >
>> >>
>> >> * Running nandtest successfully on our hardware (i.MX6UL -> FSL-QSPI ->
>> >> W25M02GV)
>> >>
>> >> I hope this is of use while moving on.
>> >
>> > Definitely. I'd also like to have a review on the framework code if
>> > possible, but that can be done when posted on the ML.
>> >
>> >> I guess you would like to have the basic framework with Micron support
>> >> and generic SPI tested and stabilized first, before adding more code,
>> >> but to be able to test with our hardware I need Micron and FSL QSPI.
>> >
>> > I guess you mean Winbond not Micron. That's okay if those patches are
>> > posted after the initial series. All I need is reviews and tests from
>> > different parties, so that I'm less confident in merging the code.
>> >
>> >>
>> >> Some questions/flaws that occurred to me:
>> >>
>> >> * The W25M02GV chip has two dies of 128M each. My current driver only
>> >> makes use of the first die. The chip expects a die-select command to
>> >> switch between the two dies.
>> >> What would be the place to implement this?
>> >> Can I just add the command and issue it in
>> >> winbond_spinand_adjust_cache_op if luns_per_target > 1?
>> >
>> > It really depends when the die selection happens. I guess it happens in
>> > 2 places: when preparing a program/read operation and when doing the
>> > transfer to the in-chip cache. Anyway, the die information is already
>> > passed in the nand_pos object, so all you'll have to do is create a new
>> > hook to customize the SPI command when needed.
>>
>> I don't know whether we can do the the die switch in the generic NAND core
>> (drivers/mtd/nand/core.c). I'm not sure if chip->select_chip() in nand_base.c
>> does the same thing or not. If so, we can do the die switch before
>> read/write/erase
>> operation. And let spi nand core to implement a hook to support it.
>
> Actually, I'm trying to move away from this ->select_chip() approach in
> the raw NAND framework, simply because the controller might be able to
> parallelize operations (like 2 erase on 2 different dies, or one erase
> on one die, and a program on the other), and having this ->select_chip()
> done early in the chain prevents this kind of optimization.
>
> Anyway, the controller should now have all the necessary information to
> know which die an operation should be executed on, and if a specific
> command has to be sent to the device to select a specific die, it can
> be done in the NAND vendor specific code.
>
>>
>> >
>> >>
>> >> * The FSL QSPI controller has a lookup table that needs to be filled
>> >> with command sequences at the time of setup. Therefore the number of
>> >> dummy bytes for each command is fixed and in my current implementation
>> >> op->dummy_bytes is ignored.
>> >> That's not a problem if all chips need the same number of dummy bytes
>> >> for each command, but I guess that's not the case, as there is a
>> >> _spinand_get_dummy function.
>> >
>> > We should definitely expose that in a generic way, and on a
>> > per-operation basis, so that, after the detection step, the NAND
>> > controller can query this information.
>> >
>> >>
>> >> * What is your plan for ECC and BBT? At least enabling the onchip ECC
>> >> will be necessary to be able to use the flash properly (e.g. with UBI),
>> >> or am I wrong?
>> >
>> > Well, if all SPI NAND chips are supporting ECC the same way and
>> > on-die ECC support is mandatory for SPI NANDs, then supporting that
>> > directly in the core is probably the best option. If, on the other
>> > hand, you have various implementations, and some SPI controllers have
>> > their own ECC engine that you can use with SPI NANDs, then it's
>> > probably a better idea to abstract ECC engine in the generic NAND layer.
>>
>> As far as I know, all the SPI NAND supports on-die ECC (at least all
>> the SPI NAND
>> I heard). But different chips may have different ECC layout in OOB
>> area. But I think
>> this cannot be a problem, we can handle this in vendor's file.
>
> Yep.
>
>>
>> >
>> > For BBTs, I'd like to have a clean version of the nand_bbt logic that
>> > uses all of the helpers exposed by the generic NAND layer. I'd also
>> > like to simplify the code if possible.
>> >
>> >>
>> >> * Do you have any special test cases? What do you usually do to test the
>> >> code?
>> >
>> > Well, make sure all the mtd tests are passing (drivers/mtd/tests), and
>> > then, the next step is to test it with UBI+UBIFS. But honestly, I'm not
>> > so worried, this is new code, and we've isolated from the raw NAND
>> > layer, so if it's buggy or instable at the beginning it's not a big
>> > deal, it will be noticed and fixed for the next few releases.
>> >
>> >>
>> >> Thanks for your patience and best regards,
>> >
>> > No problem. Thanks for your work, and I'll try to be more active on
>> > this topic (I promised that several times, and failed it :-/).
>>
>> Boris,
>>
>> I think we need to move forward, MediaTek's engineer has already asked for
>> the status of the spi nand framework upstreaming, since they want to upstream
>> their SPI NAND controller driver. And Hisilicon also has a controller driver.
>> Since more and more platforms start to support SPI NAND, we'd better merge a
>> simple but well designed framework first. I will run your modified
>> version on Zedboard
>> with generic SPI controller this or next week.
>
> Then why are they not spending time reviewing the SPI NAND framework?
> You know I'm not paid to work on SPI NAND, unlike those engineers
> working for SoC/NAND vendors. While I agree being a maintainer implies
> doing part of the work on our spare time, what I don't like is when
> people that did not invest time in a specific feature ask for this
> feature to be implemented/released. This is not your case, you invested
> a lot of time in it, and that's the reason I feel bad when I can't spend
> the necessary time to make SPI NAND code ready for inclusion.
>
> So here are the next set of things to do if you want to move forward:
> 1/ Re-submit the preparation patches (those touching MTD core) and
>    review them (or find someone to review them)

I already finished the rebase of your preparation patches on l2-mtd
nand/next brach (v4.15-rc1). Should I send them as v3 or reset to v1?
I think we don't need to wait for SPI NAND code. These preparation
patches should be review ASAP. I'd like to review it after the sending,
since they are all your effort. What's your opinion?

Thanks
Peter Pan


> 2/ Add the missing doc to the code (I was planning on doing that, but
>    if you're in hurry you can take care of it), and add real commit
>    messages.
> 3/ Fix the authorship on patches (some were mainly written by you, but
>    during my rework authorship has been lost)
> 4/ Ask others to test and review the patches
>
> Regards,
>
> Boris

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-15  2:35                     ` Peter Pan
@ 2017-12-15 12:41                       ` Boris Brezillon
  0 siblings, 0 replies; 65+ messages in thread
From: Boris Brezillon @ 2017-12-15 12:41 UTC (permalink / raw)
  To: Peter Pan, Frieder Schrempf
  Cc: Peter Pan 潘栋 (peterpandong), linux-mtd

On Fri, 15 Dec 2017 10:35:16 +0800
Peter Pan <peterpansjtu@gmail.com> wrote:

> Hi Boris
> 
> On Thu, Dec 14, 2017 at 3:50 PM, Boris Brezillon
> <boris.brezillon@free-electrons.com> wrote:
> > Hi Peter,
> >
> > On Thu, 14 Dec 2017 14:15:57 +0800
> > Peter Pan <peterpansjtu@gmail.com> wrote:
> >  
> >> Hi Boris and Frieder,
> >>
> >> On Thu, Dec 14, 2017 at 5:27 AM, Boris Brezillon
> >> <boris.brezillon@free-electrons.com> wrote:  
> >> > Hi Frieder,
> >> >
> >> > On Tue, 12 Dec 2017 10:58:10 +0100
> >> > Frieder Schrempf <frieder.schrempf@exceet.de> wrote:
> >> >  
> >> >> Hi Boris,
> >> >>
> >> >> I spent some time looking at and working with your latest SPI NAND code.
> >> >> In my previous mail I said, that we have some working code for our 3.14
> >> >> kernel based on the "mt29f_spinand" staging driver, but that was wrong
> >> >> as I got things mixed up in my head.
> >> >> Actually our codebase was an early version of Peter's code, so the
> >> >> effort to port it to the latest framework code was not that big.
> >> >>
> >> >> I forked your repo and you can find my working tree at [1].  
> >> >
> >> > Great, I'll try to have a look.
> >> >  
> >> >>
> >> >> What I did so far:
> >> >>
> >> >> * Rebase your patches on latest Linux 4.14.5  
> >> >
> >> > Cool, rebasing on 4.15-rc1 would be even better, but I can do that if
> >> > you don't have the time.
> >> >  
> >> >>
> >> >> * Add a driver for the Winbond W25M02GV SPI NAND chip, that we have on
> >> >> some of our boards.  
> >> >
> >> > Okay, that's actually a good thing to have tested with another chip,
> >> > This way we can make sure the framework is generic enough.
> >> >  
> >> >>
> >> >> * Add a driver for the Freescale QSPI controller, derived from the
> >> >> existing QSPI-NOR driver at drivers/mtd/spi-nor/fsl-quadspi.c.  
> >> >
> >> > That's an interesting case as well, the generic NAND controller is
> >> > probably the easiest implementation, and that's a good thing to have
> >> > another controller.
> >> >  
> >> >>
> >> >> * Add a setup and setup_late op to the controller layer (see [3]). I
> >> >> don't know if that makes sense, but at least the setup_late is needed
> >> >> for the FSL QSPI driver, as it needs to know the size of the flash to
> >> >> setup the memory mapping for the QSPI read operations.  
> >> >
> >> > Hm, not sure what ->setup_late() is for, but I'll have a look.
> >> >  
> >> >>
> >> >> * A bit of testing and fixing two small bugs, which look like copy and
> >> >> paste mistakes. See [2].  
> >> >
> >> > Thanks, I'll squash the fixes in the original commit.
> >> >  
> >> >>
> >> >> * Running nandtest successfully on our hardware (i.MX6UL -> FSL-QSPI ->
> >> >> W25M02GV)
> >> >>
> >> >> I hope this is of use while moving on.  
> >> >
> >> > Definitely. I'd also like to have a review on the framework code if
> >> > possible, but that can be done when posted on the ML.
> >> >  
> >> >> I guess you would like to have the basic framework with Micron support
> >> >> and generic SPI tested and stabilized first, before adding more code,
> >> >> but to be able to test with our hardware I need Micron and FSL QSPI.  
> >> >
> >> > I guess you mean Winbond not Micron. That's okay if those patches are
> >> > posted after the initial series. All I need is reviews and tests from
> >> > different parties, so that I'm less confident in merging the code.
> >> >  
> >> >>
> >> >> Some questions/flaws that occurred to me:
> >> >>
> >> >> * The W25M02GV chip has two dies of 128M each. My current driver only
> >> >> makes use of the first die. The chip expects a die-select command to
> >> >> switch between the two dies.
> >> >> What would be the place to implement this?
> >> >> Can I just add the command and issue it in
> >> >> winbond_spinand_adjust_cache_op if luns_per_target > 1?  
> >> >
> >> > It really depends when the die selection happens. I guess it happens in
> >> > 2 places: when preparing a program/read operation and when doing the
> >> > transfer to the in-chip cache. Anyway, the die information is already
> >> > passed in the nand_pos object, so all you'll have to do is create a new
> >> > hook to customize the SPI command when needed.  
> >>
> >> I don't know whether we can do the the die switch in the generic NAND core
> >> (drivers/mtd/nand/core.c). I'm not sure if chip->select_chip() in nand_base.c
> >> does the same thing or not. If so, we can do the die switch before
> >> read/write/erase
> >> operation. And let spi nand core to implement a hook to support it.  
> >
> > Actually, I'm trying to move away from this ->select_chip() approach in
> > the raw NAND framework, simply because the controller might be able to
> > parallelize operations (like 2 erase on 2 different dies, or one erase
> > on one die, and a program on the other), and having this ->select_chip()
> > done early in the chain prevents this kind of optimization.
> >
> > Anyway, the controller should now have all the necessary information to
> > know which die an operation should be executed on, and if a specific
> > command has to be sent to the device to select a specific die, it can
> > be done in the NAND vendor specific code.
> >  
> >>  
> >> >  
> >> >>
> >> >> * The FSL QSPI controller has a lookup table that needs to be filled
> >> >> with command sequences at the time of setup. Therefore the number of
> >> >> dummy bytes for each command is fixed and in my current implementation
> >> >> op->dummy_bytes is ignored.
> >> >> That's not a problem if all chips need the same number of dummy bytes
> >> >> for each command, but I guess that's not the case, as there is a
> >> >> _spinand_get_dummy function.  
> >> >
> >> > We should definitely expose that in a generic way, and on a
> >> > per-operation basis, so that, after the detection step, the NAND
> >> > controller can query this information.
> >> >  
> >> >>
> >> >> * What is your plan for ECC and BBT? At least enabling the onchip ECC
> >> >> will be necessary to be able to use the flash properly (e.g. with UBI),
> >> >> or am I wrong?  
> >> >
> >> > Well, if all SPI NAND chips are supporting ECC the same way and
> >> > on-die ECC support is mandatory for SPI NANDs, then supporting that
> >> > directly in the core is probably the best option. If, on the other
> >> > hand, you have various implementations, and some SPI controllers have
> >> > their own ECC engine that you can use with SPI NANDs, then it's
> >> > probably a better idea to abstract ECC engine in the generic NAND layer.  
> >>
> >> As far as I know, all the SPI NAND supports on-die ECC (at least all
> >> the SPI NAND
> >> I heard). But different chips may have different ECC layout in OOB
> >> area. But I think
> >> this cannot be a problem, we can handle this in vendor's file.  
> >
> > Yep.
> >  
> >>  
> >> >
> >> > For BBTs, I'd like to have a clean version of the nand_bbt logic that
> >> > uses all of the helpers exposed by the generic NAND layer. I'd also
> >> > like to simplify the code if possible.
> >> >  
> >> >>
> >> >> * Do you have any special test cases? What do you usually do to test the
> >> >> code?  
> >> >
> >> > Well, make sure all the mtd tests are passing (drivers/mtd/tests), and
> >> > then, the next step is to test it with UBI+UBIFS. But honestly, I'm not
> >> > so worried, this is new code, and we've isolated from the raw NAND
> >> > layer, so if it's buggy or instable at the beginning it's not a big
> >> > deal, it will be noticed and fixed for the next few releases.
> >> >  
> >> >>
> >> >> Thanks for your patience and best regards,  
> >> >
> >> > No problem. Thanks for your work, and I'll try to be more active on
> >> > this topic (I promised that several times, and failed it :-/).  
> >>
> >> Boris,
> >>
> >> I think we need to move forward, MediaTek's engineer has already asked for
> >> the status of the spi nand framework upstreaming, since they want to upstream
> >> their SPI NAND controller driver. And Hisilicon also has a controller driver.
> >> Since more and more platforms start to support SPI NAND, we'd better merge a
> >> simple but well designed framework first. I will run your modified
> >> version on Zedboard
> >> with generic SPI controller this or next week.  
> >
> > Then why are they not spending time reviewing the SPI NAND framework?
> > You know I'm not paid to work on SPI NAND, unlike those engineers
> > working for SoC/NAND vendors. While I agree being a maintainer implies
> > doing part of the work on our spare time, what I don't like is when
> > people that did not invest time in a specific feature ask for this
> > feature to be implemented/released. This is not your case, you invested
> > a lot of time in it, and that's the reason I feel bad when I can't spend
> > the necessary time to make SPI NAND code ready for inclusion.
> >
> > So here are the next set of things to do if you want to move forward:
> > 1/ Re-submit the preparation patches (those touching MTD core) and
> >    review them (or find someone to review them)  
> 
> I already finished the rebase of your preparation patches on l2-mtd
> nand/next brach (v4.15-rc1). Should I send them as v3 or reset to v1?
> I think we don't need to wait for SPI NAND code. These preparation
> patches should be review ASAP. I'd like to review it after the sending,
> since they are all your effort. What's your opinion?

I just sent them on the ML. Feel free to review.

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-15  1:21                             ` Peter Pan
@ 2017-12-21 11:48                               ` Frieder Schrempf
  2017-12-21 13:01                                 ` Boris Brezillon
  2017-12-22  0:49                                 ` Peter Pan
  0 siblings, 2 replies; 65+ messages in thread
From: Frieder Schrempf @ 2017-12-21 11:48 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Peter Pan, Peter Pan 潘栋 (peterpandong), linux-mtd

Hello Boris,

>>>> So shouldn't there be an spinand_die_select_op in the SPI NAND core that
>>>> is executed when necessary and skipped if there's only one die.
>>>
>>> Sure, I was arguing against a ->select_chip() at the generic NAND
>>> level. That's something you can add in the SPI NAND framework.

I added an op to send the die selection command and call it, where I 
think it is needed: [1]

Accessing both dies on the Winbond SPI NAND works fine like this.

While running tests I came across some problems:

* On accessing the BBT in RAM via nanddev_bbt_[set/get]_block_status, 
the calculation of position and offset seems to be wrong.
My fix is here: [2]

* On calculating the row address for read/program/erase via 
nanddev_pos_to_row, it seems like the eraseblock_addr_shift is wrong.

* Also, I'm not sure if the LUN should be taken into account when 
calculating the row address. At least when you select the LUN by issuing 
a separate command, the row address sent to the chip should only contain 
the page address.
But I'm not sure if that's the case in general, or if some code is 
needed to differentiate.

See my changes of nanddev_pos_to_row here: [3]

* I run into a mutex deadlock, when spinand_write_page fails (e.g. 
because of a bad block) as the lock is not released in such cases. See 
my fix here: [4]

With these fixes applied and as far as I can tell everything seems to 
work fine. I'll do some tests with UBI next and look into the ECC topic.

Regards,

Frieder

[1]: 
https://github.com/fschrempf/linux-0day/compare/4f8472ea05f27d55ebb2e42eadc9ed59d7036f4c...fschrempf:2c5471c1f1e04fa91ff80c95276b4828b99c4f94

[2]: 
https://github.com/fschrempf/linux-0day/commit/937a16248570368fe05e15b1f70e753e202b6ae6

[3]: 
https://github.com/fschrempf/linux-0day/commit/8013696e0394960bfc36625d277f0d2425262939

[4]: 
https://github.com/fschrempf/linux-0day/commit/28ffc7211745dd124702358c24ddccff8e6f2d95

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-21 11:48                               ` Frieder Schrempf
@ 2017-12-21 13:01                                 ` Boris Brezillon
  2017-12-21 13:54                                   ` Frieder Schrempf
  2017-12-22  0:49                                 ` Peter Pan
  1 sibling, 1 reply; 65+ messages in thread
From: Boris Brezillon @ 2017-12-21 13:01 UTC (permalink / raw)
  To: Frieder Schrempf
  Cc: Peter Pan, Peter Pan 潘栋 (peterpandong), linux-mtd

Hi Frieder,

On Thu, 21 Dec 2017 12:48:16 +0100
Frieder Schrempf <frieder.schrempf@exceet.de> wrote:

> Hello Boris,
> 
> >>>> So shouldn't there be an spinand_die_select_op in the SPI NAND core that
> >>>> is executed when necessary and skipped if there's only one die.  
> >>>
> >>> Sure, I was arguing against a ->select_chip() at the generic NAND
> >>> level. That's something you can add in the SPI NAND framework.  
> 
> I added an op to send the die selection command and call it, where I 
> think it is needed: [1]
> 
> Accessing both dies on the Winbond SPI NAND works fine like this.

Okay, I'll have a look.

> 
> While running tests I came across some problems:
> 
> * On accessing the BBT in RAM via nanddev_bbt_[set/get]_block_status, 
> the calculation of position and offset seems to be wrong.
> My fix is here: [2]

Indeed.

> 
> * On calculating the row address for read/program/erase via 
> nanddev_pos_to_row, it seems like the eraseblock_addr_shift is wrong.

My version was incorrect, but yours is not good either :-), should
be:

	nand->rowconv.eraseblock_addr_shift =
				fls(memorg->pages_per_eraseblock - 1);

otherwise it doesn't work when the number of pages per block is not a
power of 2, and that can happen :-/.

> 
> * Also, I'm not sure if the LUN should be taken into account when 
> calculating the row address. At least when you select the LUN by issuing 
> a separate command, the row address sent to the chip should only contain 
> the page address.

The LUN id is part of the row address on parallel ONFI NANDs. Are you
sure what you're trying to access is actually a LUN?

The ONFI spec says:
"
LUN (logical unit number)
The minimum unit that can independently execute commands and report
status. There are one or more LUNs per NAND Target.
"

I suspect what you're trying to expose is a chip with 2 targets
(target is a synonym for die). If this is the case, then you should
have:

	luns_per_target = 1;
	ntargets = 2;	/* ntargets <=> number of dies */

> But I'm not sure if that's the case in general, or if some code is 
> needed to differentiate.
> 
> See my changes of nanddev_pos_to_row here: [3]
> 
> * I run into a mutex deadlock, when spinand_write_page fails (e.g. 
> because of a bad block) as the lock is not released in such cases. See 
> my fix here: [4]

This is a valid fix.

> 
> With these fixes applied and as far as I can tell everything seems to 
> work fine. I'll do some tests with UBI next and look into the ECC topic.

Okay cool.

I'll squash your fixes in the original commits and push an updated
version on my repo.

Thanks,

Boris

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-21 13:01                                 ` Boris Brezillon
@ 2017-12-21 13:54                                   ` Frieder Schrempf
  0 siblings, 0 replies; 65+ messages in thread
From: Frieder Schrempf @ 2017-12-21 13:54 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Peter Pan, Peter Pan 潘栋 (peterpandong), linux-mtd

Hi Boris,

On 21.12.2017 14:01, Boris Brezillon wrote:
> Hi Frieder,
> 
> On Thu, 21 Dec 2017 12:48:16 +0100
> Frieder Schrempf <frieder.schrempf@exceet.de> wrote:
>>
>> * On calculating the row address for read/program/erase via
>> nanddev_pos_to_row, it seems like the eraseblock_addr_shift is wrong.
> 
> My version was incorrect, but yours is not good either :-), should
> be:
> 
> 	nand->rowconv.eraseblock_addr_shift =
> 				fls(memorg->pages_per_eraseblock - 1);
> 
> otherwise it doesn't work when the number of pages per block is not a
> power of 2, and that can happen :-/.

Ok, makes sense.

>> * Also, I'm not sure if the LUN should be taken into account when
>> calculating the row address. At least when you select the LUN by issuing
>> a separate command, the row address sent to the chip should only contain
>> the page address.
> 
> The LUN id is part of the row address on parallel ONFI NANDs. Are you
> sure what you're trying to access is actually a LUN?
> 
> The ONFI spec says:
> "
> LUN (logical unit number)
> The minimum unit that can independently execute commands and report
> status. There are one or more LUNs per NAND Target.
> "
> 
> I suspect what you're trying to expose is a chip with 2 targets
> (target is a synonym for die). If this is the case, then you should
> have:
> 
> 	luns_per_target = 1;
> 	ntargets = 2;	/* ntargets <=> number of dies */

Indeed. It seems like I misunderstood the meaning of LUN.
Thank you for explaining.

I fixed my chip setup and refactored my die/target selection code 
accordingly.

> 
>> But I'm not sure if that's the case in general, or if some code is
>> needed to differentiate.
>>
>> See my changes of nanddev_pos_to_row here: [3]
>>
>> * I run into a mutex deadlock, when spinand_write_page fails (e.g.
>> because of a bad block) as the lock is not released in such cases. See
>> my fix here: [4]
> 
> This is a valid fix.
> 
>>
>> With these fixes applied and as far as I can tell everything seems to
>> work fine. I'll do some tests with UBI next and look into the ECC topic.
> 
> Okay cool.
> 
> I'll squash your fixes in the original commits and push an updated
> version on my repo.

Ok, great!

Thanks a lot,

Frieder

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-21 11:48                               ` Frieder Schrempf
  2017-12-21 13:01                                 ` Boris Brezillon
@ 2017-12-22  0:49                                 ` Peter Pan
  2017-12-22  6:37                                   ` Peter Pan
  1 sibling, 1 reply; 65+ messages in thread
From: Peter Pan @ 2017-12-22  0:49 UTC (permalink / raw)
  To: Frieder Schrempf
  Cc: Boris Brezillon, Peter Pan 潘栋 (peterpandong), linux-mtd

Hi Frieder,

On Thu, Dec 21, 2017 at 7:48 PM, Frieder Schrempf
<frieder.schrempf@exceet.de> wrote:
> Hello Boris,
>
>>>>> So shouldn't there be an spinand_die_select_op in the SPI NAND core
>>>>> that
>>>>> is executed when necessary and skipped if there's only one die.
>>>>
>>>>
>>>> Sure, I was arguing against a ->select_chip() at the generic NAND
>>>> level. That's something you can add in the SPI NAND framework.
>
>
> I added an op to send the die selection command and call it, where I think
> it is needed: [1]

I think we should add die_select_op in vendor's file and call a hook in core.c
since the die select command implementation is different by vendors.

Thanks
Peter Pan


>
> Accessing both dies on the Winbond SPI NAND works fine like this.
>
> While running tests I came across some problems:
>
> * On accessing the BBT in RAM via nanddev_bbt_[set/get]_block_status, the
> calculation of position and offset seems to be wrong.
> My fix is here: [2]
>
> * On calculating the row address for read/program/erase via
> nanddev_pos_to_row, it seems like the eraseblock_addr_shift is wrong.
>
> * Also, I'm not sure if the LUN should be taken into account when
> calculating the row address. At least when you select the LUN by issuing a
> separate command, the row address sent to the chip should only contain the
> page address.
> But I'm not sure if that's the case in general, or if some code is needed to
> differentiate.
>
> See my changes of nanddev_pos_to_row here: [3]
>
> * I run into a mutex deadlock, when spinand_write_page fails (e.g. because
> of a bad block) as the lock is not released in such cases. See my fix here:
> [4]
>
> With these fixes applied and as far as I can tell everything seems to work
> fine. I'll do some tests with UBI next and look into the ECC topic.
>
> Regards,
>
> Frieder
>
> [1]:
> https://github.com/fschrempf/linux-0day/compare/4f8472ea05f27d55ebb2e42eadc9ed59d7036f4c...fschrempf:2c5471c1f1e04fa91ff80c95276b4828b99c4f94
>
> [2]:
> https://github.com/fschrempf/linux-0day/commit/937a16248570368fe05e15b1f70e753e202b6ae6
>
> [3]:
> https://github.com/fschrempf/linux-0day/commit/8013696e0394960bfc36625d277f0d2425262939
>
> [4]:
> https://github.com/fschrempf/linux-0day/commit/28ffc7211745dd124702358c24ddccff8e6f2d95

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-22  0:49                                 ` Peter Pan
@ 2017-12-22  6:37                                   ` Peter Pan
  2017-12-22  8:28                                     ` Boris Brezillon
  2017-12-22 13:51                                     ` Boris Brezillon
  0 siblings, 2 replies; 65+ messages in thread
From: Peter Pan @ 2017-12-22  6:37 UTC (permalink / raw)
  To: Frieder Schrempf
  Cc: Boris Brezillon, Peter Pan 潘栋 (peterpandong), linux-mtd

Hi Boris and Frieder

On Fri, Dec 22, 2017 at 8:49 AM, Peter Pan <peterpansjtu@gmail.com> wrote:
> Hi Frieder,
>
> On Thu, Dec 21, 2017 at 7:48 PM, Frieder Schrempf
> <frieder.schrempf@exceet.de> wrote:
>> Hello Boris,
>>
>>>>>> So shouldn't there be an spinand_die_select_op in the SPI NAND core
>>>>>> that
>>>>>> is executed when necessary and skipped if there's only one die.
>>>>>
>>>>>
>>>>> Sure, I was arguing against a ->select_chip() at the generic NAND
>>>>> level. That's something you can add in the SPI NAND framework.
>>
>>
>> I added an op to send the die selection command and call it, where I think
>> it is needed: [1]
>
> I think we should add die_select_op in vendor's file and call a hook in core.c
> since the die select command implementation is different by vendors.
>
> Thanks
> Peter Pan
>
>
>>
>> Accessing both dies on the Winbond SPI NAND works fine like this.
>>
>> While running tests I came across some problems:
>>
>> * On accessing the BBT in RAM via nanddev_bbt_[set/get]_block_status, the
>> calculation of position and offset seems to be wrong.
>> My fix is here: [2]
>>
>> * On calculating the row address for read/program/erase via
>> nanddev_pos_to_row, it seems like the eraseblock_addr_shift is wrong.
>>
>> * Also, I'm not sure if the LUN should be taken into account when
>> calculating the row address. At least when you select the LUN by issuing a
>> separate command, the row address sent to the chip should only contain the
>> page address.
>> But I'm not sure if that's the case in general, or if some code is needed to
>> differentiate.
>>
>> See my changes of nanddev_pos_to_row here: [3]
>>
>> * I run into a mutex deadlock, when spinand_write_page fails (e.g. because
>> of a bad block) as the lock is not released in such cases. See my fix here:
>> [4]
>>
>> With these fixes applied and as far as I can tell everything seems to work
>> fine. I'll do some tests with UBI next and look into the ECC topic.

UBI attach failed since missing mtd->writebufsize assignment in nanddev_init()
After fixing it and with Frieder's fixing, UBIFS can be mounted successfully on
Zedboard with generic spi controller and Micron SPI NAND 2Gb device.

Also, the code now can pass mtd read and page test. 1 error found in oob test
since we don't have "past end of partition" check in part_write_oob() which I
mentioned in earlier mail. Since we don't support ECC right now, I didn't try
nandbiterror test.


@@ -195,6 +195,7 @@ int nanddev_init(struct nand_device *nand, const
struct nand_ops *ops,
        mtd->flags = MTD_CAP_NANDFLASH;
        mtd->erasesize = memorg->pagesize * memorg->pages_per_eraseblock;
        mtd->writesize = memorg->pagesize;
+       mtd->writebufsize = mtd->writesize;
        mtd->oobsize = memorg->oobsize;
        mtd->size = nanddev_size(nand);
        mtd->owner = owner;


Thanks
Peter Pan

>>
>> Regards,
>>
>> Frieder
>>
>> [1]:
>> https://github.com/fschrempf/linux-0day/compare/4f8472ea05f27d55ebb2e42eadc9ed59d7036f4c...fschrempf:2c5471c1f1e04fa91ff80c95276b4828b99c4f94
>>
>> [2]:
>> https://github.com/fschrempf/linux-0day/commit/937a16248570368fe05e15b1f70e753e202b6ae6
>>
>> [3]:
>> https://github.com/fschrempf/linux-0day/commit/8013696e0394960bfc36625d277f0d2425262939
>>
>> [4]:
>> https://github.com/fschrempf/linux-0day/commit/28ffc7211745dd124702358c24ddccff8e6f2d95

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-22  6:37                                   ` Peter Pan
@ 2017-12-22  8:28                                     ` Boris Brezillon
  2017-12-22 13:51                                     ` Boris Brezillon
  1 sibling, 0 replies; 65+ messages in thread
From: Boris Brezillon @ 2017-12-22  8:28 UTC (permalink / raw)
  To: Peter Pan
  Cc: Frieder Schrempf, Peter Pan 潘栋 (peterpandong), linux-mtd

On Fri, 22 Dec 2017 14:37:06 +0800
Peter Pan <peterpansjtu@gmail.com> wrote:

> Hi Boris and Frieder
> 
> On Fri, Dec 22, 2017 at 8:49 AM, Peter Pan <peterpansjtu@gmail.com> wrote:
> > Hi Frieder,
> >
> > On Thu, Dec 21, 2017 at 7:48 PM, Frieder Schrempf
> > <frieder.schrempf@exceet.de> wrote:  
> >> Hello Boris,
> >>  
> >>>>>> So shouldn't there be an spinand_die_select_op in the SPI NAND core
> >>>>>> that
> >>>>>> is executed when necessary and skipped if there's only one die.  
> >>>>>
> >>>>>
> >>>>> Sure, I was arguing against a ->select_chip() at the generic NAND
> >>>>> level. That's something you can add in the SPI NAND framework.  
> >>
> >>
> >> I added an op to send the die selection command and call it, where I think
> >> it is needed: [1]  
> >
> > I think we should add die_select_op in vendor's file and call a hook in core.c
> > since the die select command implementation is different by vendors.
> >
> > Thanks
> > Peter Pan
> >
> >  
> >>
> >> Accessing both dies on the Winbond SPI NAND works fine like this.
> >>
> >> While running tests I came across some problems:
> >>
> >> * On accessing the BBT in RAM via nanddev_bbt_[set/get]_block_status, the
> >> calculation of position and offset seems to be wrong.
> >> My fix is here: [2]
> >>
> >> * On calculating the row address for read/program/erase via
> >> nanddev_pos_to_row, it seems like the eraseblock_addr_shift is wrong.
> >>
> >> * Also, I'm not sure if the LUN should be taken into account when
> >> calculating the row address. At least when you select the LUN by issuing a
> >> separate command, the row address sent to the chip should only contain the
> >> page address.
> >> But I'm not sure if that's the case in general, or if some code is needed to
> >> differentiate.
> >>
> >> See my changes of nanddev_pos_to_row here: [3]
> >>
> >> * I run into a mutex deadlock, when spinand_write_page fails (e.g. because
> >> of a bad block) as the lock is not released in such cases. See my fix here:
> >> [4]
> >>
> >> With these fixes applied and as far as I can tell everything seems to work
> >> fine. I'll do some tests with UBI next and look into the ECC topic.  
> 
> UBI attach failed since missing mtd->writebufsize assignment in nanddev_init()
> After fixing it and with Frieder's fixing, UBIFS can be mounted successfully on
> Zedboard with generic spi controller and Micron SPI NAND 2Gb device.

I'll squash your fix, thanks.

> 
> Also, the code now can pass mtd read and page test. 1 error found in oob test
> since we don't have "past end of partition" check in part_write_oob() which I
> mentioned in earlier mail.

Still not sure about that one, but I'll reply in the other thread.

> Since we don't support ECC right now, I didn't try
> nandbiterror test.
> 
> 
> @@ -195,6 +195,7 @@ int nanddev_init(struct nand_device *nand, const
> struct nand_ops *ops,
>         mtd->flags = MTD_CAP_NANDFLASH;
>         mtd->erasesize = memorg->pagesize * memorg->pages_per_eraseblock;
>         mtd->writesize = memorg->pagesize;
> +       mtd->writebufsize = mtd->writesize;
>         mtd->oobsize = memorg->oobsize;
>         mtd->size = nanddev_size(nand);
>         mtd->owner = owner;
> 
> 
> Thanks
> Peter Pan
> 
> >>
> >> Regards,
> >>
> >> Frieder
> >>
> >> [1]:
> >> https://github.com/fschrempf/linux-0day/compare/4f8472ea05f27d55ebb2e42eadc9ed59d7036f4c...fschrempf:2c5471c1f1e04fa91ff80c95276b4828b99c4f94
> >>
> >> [2]:
> >> https://github.com/fschrempf/linux-0day/commit/937a16248570368fe05e15b1f70e753e202b6ae6
> >>
> >> [3]:
> >> https://github.com/fschrempf/linux-0day/commit/8013696e0394960bfc36625d277f0d2425262939
> >>
> >> [4]:
> >> https://github.com/fschrempf/linux-0day/commit/28ffc7211745dd124702358c24ddccff8e6f2d95  

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-22  6:37                                   ` Peter Pan
  2017-12-22  8:28                                     ` Boris Brezillon
@ 2017-12-22 13:51                                     ` Boris Brezillon
  2018-01-02  2:51                                       ` Peter Pan
  1 sibling, 1 reply; 65+ messages in thread
From: Boris Brezillon @ 2017-12-22 13:51 UTC (permalink / raw)
  To: Peter Pan
  Cc: Frieder Schrempf, Peter Pan 潘栋 (peterpandong), linux-mtd

On Fri, 22 Dec 2017 14:37:06 +0800
Peter Pan <peterpansjtu@gmail.com> wrote:

> Hi Boris and Frieder
> 
> On Fri, Dec 22, 2017 at 8:49 AM, Peter Pan <peterpansjtu@gmail.com> wrote:
> > Hi Frieder,
> >
> > On Thu, Dec 21, 2017 at 7:48 PM, Frieder Schrempf
> > <frieder.schrempf@exceet.de> wrote:  
> >> Hello Boris,
> >>  
> >>>>>> So shouldn't there be an spinand_die_select_op in the SPI NAND core
> >>>>>> that
> >>>>>> is executed when necessary and skipped if there's only one die.  
> >>>>>
> >>>>>
> >>>>> Sure, I was arguing against a ->select_chip() at the generic NAND
> >>>>> level. That's something you can add in the SPI NAND framework.  
> >>
> >>
> >> I added an op to send the die selection command and call it, where I think
> >> it is needed: [1]  
> >
> > I think we should add die_select_op in vendor's file and call a hook in core.c
> > since the die select command implementation is different by vendors.
> >
> > Thanks
> > Peter Pan
> >
> >  
> >>
> >> Accessing both dies on the Winbond SPI NAND works fine like this.
> >>
> >> While running tests I came across some problems:
> >>
> >> * On accessing the BBT in RAM via nanddev_bbt_[set/get]_block_status, the
> >> calculation of position and offset seems to be wrong.
> >> My fix is here: [2]
> >>
> >> * On calculating the row address for read/program/erase via
> >> nanddev_pos_to_row, it seems like the eraseblock_addr_shift is wrong.
> >>
> >> * Also, I'm not sure if the LUN should be taken into account when
> >> calculating the row address. At least when you select the LUN by issuing a
> >> separate command, the row address sent to the chip should only contain the
> >> page address.
> >> But I'm not sure if that's the case in general, or if some code is needed to
> >> differentiate.
> >>
> >> See my changes of nanddev_pos_to_row here: [3]
> >>
> >> * I run into a mutex deadlock, when spinand_write_page fails (e.g. because
> >> of a bad block) as the lock is not released in such cases. See my fix here:
> >> [4]
> >>
> >> With these fixes applied and as far as I can tell everything seems to work
> >> fine. I'll do some tests with UBI next and look into the ECC topic.  
> 
> UBI attach failed since missing mtd->writebufsize assignment in nanddev_init()
> After fixing it and with Frieder's fixing, UBIFS can be mounted successfully on
> Zedboard with generic spi controller and Micron SPI NAND 2Gb device.
> 
> Also, the code now can pass mtd read and page test. 1 error found in oob test
> since we don't have "past end of partition" check in part_write_oob() which I
> mentioned in earlier mail. Since we don't support ECC right now, I didn't try
> nandbiterror test.
> 

Peter, Frider, I just pushed a new version to my nand/spi-nand branch
[1] fixing the authorship, adding/fixing/removing comments where needed.

Can you please have a look at those changes (everything I changed
should appear as !fixup commits) and let me know if I did something
wrong.

We still need to make commit messages a bit more verbose.

This afternoon I'll have a look at the ->select_die() feature.

Regards,

Boris

[1]https://github.com/bbrezillon/linux-0day/commits/nand/spi-nand

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2017-12-22 13:51                                     ` Boris Brezillon
@ 2018-01-02  2:51                                       ` Peter Pan
  2018-01-03 16:46                                         ` Boris Brezillon
  0 siblings, 1 reply; 65+ messages in thread
From: Peter Pan @ 2018-01-02  2:51 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Frieder Schrempf, Peter Pan 潘栋 (peterpandong), linux-mtd

Hi Boris,


On Fri, Dec 22, 2017 at 9:51 PM, Boris Brezillon
<boris.brezillon@free-electrons.com> wrote:
> On Fri, 22 Dec 2017 14:37:06 +0800
> Peter Pan <peterpansjtu@gmail.com> wrote:
>
>> Hi Boris and Frieder
>>
>> On Fri, Dec 22, 2017 at 8:49 AM, Peter Pan <peterpansjtu@gmail.com> wrote:
>> > Hi Frieder,
>> >
>> > On Thu, Dec 21, 2017 at 7:48 PM, Frieder Schrempf
>> > <frieder.schrempf@exceet.de> wrote:
>> >> Hello Boris,
>> >>
>> >>>>>> So shouldn't there be an spinand_die_select_op in the SPI NAND core
>> >>>>>> that
>> >>>>>> is executed when necessary and skipped if there's only one die.
>> >>>>>
>> >>>>>
>> >>>>> Sure, I was arguing against a ->select_chip() at the generic NAND
>> >>>>> level. That's something you can add in the SPI NAND framework.
>> >>
>> >>
>> >> I added an op to send the die selection command and call it, where I think
>> >> it is needed: [1]
>> >
>> > I think we should add die_select_op in vendor's file and call a hook in core.c
>> > since the die select command implementation is different by vendors.
>> >
>> > Thanks
>> > Peter Pan
>> >
>> >
>> >>
>> >> Accessing both dies on the Winbond SPI NAND works fine like this.
>> >>
>> >> While running tests I came across some problems:
>> >>
>> >> * On accessing the BBT in RAM via nanddev_bbt_[set/get]_block_status, the
>> >> calculation of position and offset seems to be wrong.
>> >> My fix is here: [2]
>> >>
>> >> * On calculating the row address for read/program/erase via
>> >> nanddev_pos_to_row, it seems like the eraseblock_addr_shift is wrong.
>> >>
>> >> * Also, I'm not sure if the LUN should be taken into account when
>> >> calculating the row address. At least when you select the LUN by issuing a
>> >> separate command, the row address sent to the chip should only contain the
>> >> page address.
>> >> But I'm not sure if that's the case in general, or if some code is needed to
>> >> differentiate.
>> >>
>> >> See my changes of nanddev_pos_to_row here: [3]
>> >>
>> >> * I run into a mutex deadlock, when spinand_write_page fails (e.g. because
>> >> of a bad block) as the lock is not released in such cases. See my fix here:
>> >> [4]
>> >>
>> >> With these fixes applied and as far as I can tell everything seems to work
>> >> fine. I'll do some tests with UBI next and look into the ECC topic.
>>
>> UBI attach failed since missing mtd->writebufsize assignment in nanddev_init()
>> After fixing it and with Frieder's fixing, UBIFS can be mounted successfully on
>> Zedboard with generic spi controller and Micron SPI NAND 2Gb device.
>>
>> Also, the code now can pass mtd read and page test. 1 error found in oob test
>> since we don't have "past end of partition" check in part_write_oob() which I
>> mentioned in earlier mail. Since we don't support ECC right now, I didn't try
>> nandbiterror test.
>>
>
> Peter, Frider, I just pushed a new version to my nand/spi-nand branch
> [1] fixing the authorship, adding/fixing/removing comments where needed.
>
> Can you please have a look at those changes (everything I changed
> should appear as !fixup commits) and let me know if I did something
> wrong.

You forgot to initialize mtd->writebufsize and mtd->oobavail.
For mtd->writebufsize I think we can do it in nanddev_init() like below:

--- a/drivers/mtd/nand/core.c
+++ b/drivers/mtd/nand/core.c
@@ -196,7 +196,9 @@ int nanddev_init(struct nand_device *nand, const
struct nand_ops *ops,
        mtd->flags = MTD_CAP_NANDFLASH;
        mtd->erasesize = memorg->pagesize * memorg->pages_per_eraseblock;
        mtd->writesize = memorg->pagesize;
+       mtd->writebufsize = mtd->writesize;
        mtd->oobsize = memorg->oobsize;
        mtd->size = nanddev_size(nand);
        mtd->owner = owner;

For mtd->oobavail, I think we need to call some hooks in spinand_init(),
and implement on-die ECC layout in vendor's file and HW ECC layout in
controller's file.

What's your opinion?

With the two thing fixed, we can pass UBIFS mount and mtd test.

Thanks
Peter Pan

>
> We still need to make commit messages a bit more verbose.
>
> This afternoon I'll have a look at the ->select_die() feature.
>
> Regards,
>
> Boris
>
> [1]https://github.com/bbrezillon/linux-0day/commits/nand/spi-nand

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2018-01-02  2:51                                       ` Peter Pan
@ 2018-01-03 16:46                                         ` Boris Brezillon
  2018-01-04  2:01                                           ` Peter Pan
  0 siblings, 1 reply; 65+ messages in thread
From: Boris Brezillon @ 2018-01-03 16:46 UTC (permalink / raw)
  To: Peter Pan
  Cc: Frieder Schrempf, Peter Pan 潘栋 (peterpandong), linux-mtd

On Tue, 2 Jan 2018 10:51:25 +0800
Peter Pan <peterpansjtu@gmail.com> wrote:

> Hi Boris,
> 
> 
> On Fri, Dec 22, 2017 at 9:51 PM, Boris Brezillon
> <boris.brezillon@free-electrons.com> wrote:
> > On Fri, 22 Dec 2017 14:37:06 +0800
> > Peter Pan <peterpansjtu@gmail.com> wrote:
> >  
> >> Hi Boris and Frieder
> >>
> >> On Fri, Dec 22, 2017 at 8:49 AM, Peter Pan <peterpansjtu@gmail.com> wrote:  
> >> > Hi Frieder,
> >> >
> >> > On Thu, Dec 21, 2017 at 7:48 PM, Frieder Schrempf
> >> > <frieder.schrempf@exceet.de> wrote:  
> >> >> Hello Boris,
> >> >>  
> >> >>>>>> So shouldn't there be an spinand_die_select_op in the SPI NAND core
> >> >>>>>> that
> >> >>>>>> is executed when necessary and skipped if there's only one die.  
> >> >>>>>
> >> >>>>>
> >> >>>>> Sure, I was arguing against a ->select_chip() at the generic NAND
> >> >>>>> level. That's something you can add in the SPI NAND framework.  
> >> >>
> >> >>
> >> >> I added an op to send the die selection command and call it, where I think
> >> >> it is needed: [1]  
> >> >
> >> > I think we should add die_select_op in vendor's file and call a hook in core.c
> >> > since the die select command implementation is different by vendors.
> >> >
> >> > Thanks
> >> > Peter Pan
> >> >
> >> >  
> >> >>
> >> >> Accessing both dies on the Winbond SPI NAND works fine like this.
> >> >>
> >> >> While running tests I came across some problems:
> >> >>
> >> >> * On accessing the BBT in RAM via nanddev_bbt_[set/get]_block_status, the
> >> >> calculation of position and offset seems to be wrong.
> >> >> My fix is here: [2]
> >> >>
> >> >> * On calculating the row address for read/program/erase via
> >> >> nanddev_pos_to_row, it seems like the eraseblock_addr_shift is wrong.
> >> >>
> >> >> * Also, I'm not sure if the LUN should be taken into account when
> >> >> calculating the row address. At least when you select the LUN by issuing a
> >> >> separate command, the row address sent to the chip should only contain the
> >> >> page address.
> >> >> But I'm not sure if that's the case in general, or if some code is needed to
> >> >> differentiate.
> >> >>
> >> >> See my changes of nanddev_pos_to_row here: [3]
> >> >>
> >> >> * I run into a mutex deadlock, when spinand_write_page fails (e.g. because
> >> >> of a bad block) as the lock is not released in such cases. See my fix here:
> >> >> [4]
> >> >>
> >> >> With these fixes applied and as far as I can tell everything seems to work
> >> >> fine. I'll do some tests with UBI next and look into the ECC topic.  
> >>
> >> UBI attach failed since missing mtd->writebufsize assignment in nanddev_init()
> >> After fixing it and with Frieder's fixing, UBIFS can be mounted successfully on
> >> Zedboard with generic spi controller and Micron SPI NAND 2Gb device.
> >>
> >> Also, the code now can pass mtd read and page test. 1 error found in oob test
> >> since we don't have "past end of partition" check in part_write_oob() which I
> >> mentioned in earlier mail. Since we don't support ECC right now, I didn't try
> >> nandbiterror test.
> >>  
> >
> > Peter, Frider, I just pushed a new version to my nand/spi-nand branch
> > [1] fixing the authorship, adding/fixing/removing comments where needed.
> >
> > Can you please have a look at those changes (everything I changed
> > should appear as !fixup commits) and let me know if I did something
> > wrong.  
> 
> You forgot to initialize mtd->writebufsize and mtd->oobavail.
> For mtd->writebufsize I think we can do it in nanddev_init() like below:
> 
> --- a/drivers/mtd/nand/core.c
> +++ b/drivers/mtd/nand/core.c
> @@ -196,7 +196,9 @@ int nanddev_init(struct nand_device *nand, const
> struct nand_ops *ops,
>         mtd->flags = MTD_CAP_NANDFLASH;
>         mtd->erasesize = memorg->pagesize * memorg->pages_per_eraseblock;
>         mtd->writesize = memorg->pagesize;
> +       mtd->writebufsize = mtd->writesize;
>         mtd->oobsize = memorg->oobsize;
>         mtd->size = nanddev_size(nand);
>         mtd->owner = owner;

I fixed it already, see [1]. Note that I haven't squashed fixup commits
yet.

> 
> For mtd->oobavail, I think we need to call some hooks in spinand_init(),
> and implement on-die ECC layout in vendor's file and HW ECC layout in
> controller's file.
> 
> What's your opinion?

Hm, I'm not so sure. spinand_init() should be called just before
registering the MTD device, so by that time everything should have been
setup correctly by the upper layer. This being said, I'd like to keep a
clear separation between the MTD and NAND layers, and this means
preventing any NAND sub-layer from directly manipulating the MTD device
and its fields.

Really, I don't know yet how I want to abstract ECC stuff, so let's
keep it simple for now and expose the whole OOB area (I'll fix the core
to do that if you're okay).

> 
> With the two thing fixed, we can pass UBIFS mount and mtd test.

Do you still have the problem you reported earlier (OOB test)?

Thanks,

Boris

[1]https://github.com/bbrezillon/linux-0day/commit/32eeea1c35bfdc2ac0fcea599f6a926c94b835bb

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2018-01-03 16:46                                         ` Boris Brezillon
@ 2018-01-04  2:01                                           ` Peter Pan
  2018-01-08 22:07                                             ` Boris Brezillon
  0 siblings, 1 reply; 65+ messages in thread
From: Peter Pan @ 2018-01-04  2:01 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Frieder Schrempf, Peter Pan 潘栋 (peterpandong), linux-mtd

Boris,

On Thu, Jan 4, 2018 at 12:46 AM, Boris Brezillon
<boris.brezillon@free-electrons.com> wrote:
> On Tue, 2 Jan 2018 10:51:25 +0800
> Peter Pan <peterpansjtu@gmail.com> wrote:
>
>> Hi Boris,
>>
>>
>> On Fri, Dec 22, 2017 at 9:51 PM, Boris Brezillon
>> <boris.brezillon@free-electrons.com> wrote:
>> > On Fri, 22 Dec 2017 14:37:06 +0800
>> > Peter Pan <peterpansjtu@gmail.com> wrote:
>> >
>> >> Hi Boris and Frieder
>> >>
>> >> On Fri, Dec 22, 2017 at 8:49 AM, Peter Pan <peterpansjtu@gmail.com> wrote:
>> >> > Hi Frieder,
>> >> >
>> >> > On Thu, Dec 21, 2017 at 7:48 PM, Frieder Schrempf
>> >> > <frieder.schrempf@exceet.de> wrote:
>> >> >> Hello Boris,
>> >> >>
>> >> >>>>>> So shouldn't there be an spinand_die_select_op in the SPI NAND core
>> >> >>>>>> that
>> >> >>>>>> is executed when necessary and skipped if there's only one die.
>> >> >>>>>
>> >> >>>>>
>> >> >>>>> Sure, I was arguing against a ->select_chip() at the generic NAND
>> >> >>>>> level. That's something you can add in the SPI NAND framework.
>> >> >>
>> >> >>
>> >> >> I added an op to send the die selection command and call it, where I think
>> >> >> it is needed: [1]
>> >> >
>> >> > I think we should add die_select_op in vendor's file and call a hook in core.c
>> >> > since the die select command implementation is different by vendors.
>> >> >
>> >> > Thanks
>> >> > Peter Pan
>> >> >
>> >> >
>> >> >>
>> >> >> Accessing both dies on the Winbond SPI NAND works fine like this.
>> >> >>
>> >> >> While running tests I came across some problems:
>> >> >>
>> >> >> * On accessing the BBT in RAM via nanddev_bbt_[set/get]_block_status, the
>> >> >> calculation of position and offset seems to be wrong.
>> >> >> My fix is here: [2]
>> >> >>
>> >> >> * On calculating the row address for read/program/erase via
>> >> >> nanddev_pos_to_row, it seems like the eraseblock_addr_shift is wrong.
>> >> >>
>> >> >> * Also, I'm not sure if the LUN should be taken into account when
>> >> >> calculating the row address. At least when you select the LUN by issuing a
>> >> >> separate command, the row address sent to the chip should only contain the
>> >> >> page address.
>> >> >> But I'm not sure if that's the case in general, or if some code is needed to
>> >> >> differentiate.
>> >> >>
>> >> >> See my changes of nanddev_pos_to_row here: [3]
>> >> >>
>> >> >> * I run into a mutex deadlock, when spinand_write_page fails (e.g. because
>> >> >> of a bad block) as the lock is not released in such cases. See my fix here:
>> >> >> [4]
>> >> >>
>> >> >> With these fixes applied and as far as I can tell everything seems to work
>> >> >> fine. I'll do some tests with UBI next and look into the ECC topic.
>> >>
>> >> UBI attach failed since missing mtd->writebufsize assignment in nanddev_init()
>> >> After fixing it and with Frieder's fixing, UBIFS can be mounted successfully on
>> >> Zedboard with generic spi controller and Micron SPI NAND 2Gb device.
>> >>
>> >> Also, the code now can pass mtd read and page test. 1 error found in oob test
>> >> since we don't have "past end of partition" check in part_write_oob() which I
>> >> mentioned in earlier mail. Since we don't support ECC right now, I didn't try
>> >> nandbiterror test.
>> >>
>> >
>> > Peter, Frider, I just pushed a new version to my nand/spi-nand branch
>> > [1] fixing the authorship, adding/fixing/removing comments where needed.
>> >
>> > Can you please have a look at those changes (everything I changed
>> > should appear as !fixup commits) and let me know if I did something
>> > wrong.
>>
>> You forgot to initialize mtd->writebufsize and mtd->oobavail.
>> For mtd->writebufsize I think we can do it in nanddev_init() like below:
>>
>> --- a/drivers/mtd/nand/core.c
>> +++ b/drivers/mtd/nand/core.c
>> @@ -196,7 +196,9 @@ int nanddev_init(struct nand_device *nand, const
>> struct nand_ops *ops,
>>         mtd->flags = MTD_CAP_NANDFLASH;
>>         mtd->erasesize = memorg->pagesize * memorg->pages_per_eraseblock;
>>         mtd->writesize = memorg->pagesize;
>> +       mtd->writebufsize = mtd->writesize;
>>         mtd->oobsize = memorg->oobsize;
>>         mtd->size = nanddev_size(nand);
>>         mtd->owner = owner;
>
> I fixed it already, see [1]. Note that I haven't squashed fixup commits
> yet.

Noted.

>
>>
>> For mtd->oobavail, I think we need to call some hooks in spinand_init(),
>> and implement on-die ECC layout in vendor's file and HW ECC layout in
>> controller's file.
>>
>> What's your opinion?
>
> Hm, I'm not so sure. spinand_init() should be called just before
> registering the MTD device, so by that time everything should have been
> setup correctly by the upper layer. This being said, I'd like to keep a
> clear separation between the MTD and NAND layers, and this means
> preventing any NAND sub-layer from directly manipulating the MTD device
> and its fields.
>
> Really, I don't know yet how I want to abstract ECC stuff, so let's
> keep it simple for now and expose the whole OOB area (I'll fix the core
> to do that if you're okay).

OK.

>
>>
>> With the two thing fixed, we can pass UBIFS mount and mtd test.
>
> Do you still have the problem you reported earlier (OOB test)?

I forgot to reply that mail :(. Actually there is no problem because
mtd_write_oob() already has mtd_check_oob_ops() to check it.
That failure in OOB test occurs because mtd->oobavail is zero.

Thanks
Peter Pan

>
> Thanks,
>
> Boris
>
> [1]https://github.com/bbrezillon/linux-0day/commit/32eeea1c35bfdc2ac0fcea599f6a926c94b835bb
>

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/15] A SPI NAND framework under generic NAND framework
  2018-01-04  2:01                                           ` Peter Pan
@ 2018-01-08 22:07                                             ` Boris Brezillon
  0 siblings, 0 replies; 65+ messages in thread
From: Boris Brezillon @ 2018-01-08 22:07 UTC (permalink / raw)
  To: Peter Pan
  Cc: Frieder Schrempf, Peter Pan 潘栋 (peterpandong), linux-mtd

On Thu, 4 Jan 2018 10:01:57 +0800
Peter Pan <peterpansjtu@gmail.com> wrote:

> Boris,
> 
> On Thu, Jan 4, 2018 at 12:46 AM, Boris Brezillon
> <boris.brezillon@free-electrons.com> wrote:
> > On Tue, 2 Jan 2018 10:51:25 +0800
> > Peter Pan <peterpansjtu@gmail.com> wrote:
> >  
> >> Hi Boris,
> >>
> >>
> >> On Fri, Dec 22, 2017 at 9:51 PM, Boris Brezillon
> >> <boris.brezillon@free-electrons.com> wrote:  
> >> > On Fri, 22 Dec 2017 14:37:06 +0800
> >> > Peter Pan <peterpansjtu@gmail.com> wrote:
> >> >  
> >> >> Hi Boris and Frieder
> >> >>
> >> >> On Fri, Dec 22, 2017 at 8:49 AM, Peter Pan <peterpansjtu@gmail.com> wrote:  
> >> >> > Hi Frieder,
> >> >> >
> >> >> > On Thu, Dec 21, 2017 at 7:48 PM, Frieder Schrempf
> >> >> > <frieder.schrempf@exceet.de> wrote:  
> >> >> >> Hello Boris,
> >> >> >>  
> >> >> >>>>>> So shouldn't there be an spinand_die_select_op in the SPI NAND core
> >> >> >>>>>> that
> >> >> >>>>>> is executed when necessary and skipped if there's only one die.  
> >> >> >>>>>
> >> >> >>>>>
> >> >> >>>>> Sure, I was arguing against a ->select_chip() at the generic NAND
> >> >> >>>>> level. That's something you can add in the SPI NAND framework.  
> >> >> >>
> >> >> >>
> >> >> >> I added an op to send the die selection command and call it, where I think
> >> >> >> it is needed: [1]  
> >> >> >
> >> >> > I think we should add die_select_op in vendor's file and call a hook in core.c
> >> >> > since the die select command implementation is different by vendors.
> >> >> >
> >> >> > Thanks
> >> >> > Peter Pan
> >> >> >
> >> >> >  
> >> >> >>
> >> >> >> Accessing both dies on the Winbond SPI NAND works fine like this.
> >> >> >>
> >> >> >> While running tests I came across some problems:
> >> >> >>
> >> >> >> * On accessing the BBT in RAM via nanddev_bbt_[set/get]_block_status, the
> >> >> >> calculation of position and offset seems to be wrong.
> >> >> >> My fix is here: [2]
> >> >> >>
> >> >> >> * On calculating the row address for read/program/erase via
> >> >> >> nanddev_pos_to_row, it seems like the eraseblock_addr_shift is wrong.
> >> >> >>
> >> >> >> * Also, I'm not sure if the LUN should be taken into account when
> >> >> >> calculating the row address. At least when you select the LUN by issuing a
> >> >> >> separate command, the row address sent to the chip should only contain the
> >> >> >> page address.
> >> >> >> But I'm not sure if that's the case in general, or if some code is needed to
> >> >> >> differentiate.
> >> >> >>
> >> >> >> See my changes of nanddev_pos_to_row here: [3]
> >> >> >>
> >> >> >> * I run into a mutex deadlock, when spinand_write_page fails (e.g. because
> >> >> >> of a bad block) as the lock is not released in such cases. See my fix here:
> >> >> >> [4]
> >> >> >>
> >> >> >> With these fixes applied and as far as I can tell everything seems to work
> >> >> >> fine. I'll do some tests with UBI next and look into the ECC topic.  
> >> >>
> >> >> UBI attach failed since missing mtd->writebufsize assignment in nanddev_init()
> >> >> After fixing it and with Frieder's fixing, UBIFS can be mounted successfully on
> >> >> Zedboard with generic spi controller and Micron SPI NAND 2Gb device.
> >> >>
> >> >> Also, the code now can pass mtd read and page test. 1 error found in oob test
> >> >> since we don't have "past end of partition" check in part_write_oob() which I
> >> >> mentioned in earlier mail. Since we don't support ECC right now, I didn't try
> >> >> nandbiterror test.
> >> >>  
> >> >
> >> > Peter, Frider, I just pushed a new version to my nand/spi-nand branch
> >> > [1] fixing the authorship, adding/fixing/removing comments where needed.
> >> >
> >> > Can you please have a look at those changes (everything I changed
> >> > should appear as !fixup commits) and let me know if I did something
> >> > wrong.  
> >>
> >> You forgot to initialize mtd->writebufsize and mtd->oobavail.
> >> For mtd->writebufsize I think we can do it in nanddev_init() like below:
> >>
> >> --- a/drivers/mtd/nand/core.c
> >> +++ b/drivers/mtd/nand/core.c
> >> @@ -196,7 +196,9 @@ int nanddev_init(struct nand_device *nand, const
> >> struct nand_ops *ops,
> >>         mtd->flags = MTD_CAP_NANDFLASH;
> >>         mtd->erasesize = memorg->pagesize * memorg->pages_per_eraseblock;
> >>         mtd->writesize = memorg->pagesize;
> >> +       mtd->writebufsize = mtd->writesize;
> >>         mtd->oobsize = memorg->oobsize;
> >>         mtd->size = nanddev_size(nand);
> >>         mtd->owner = owner;  
> >
> > I fixed it already, see [1]. Note that I haven't squashed fixup commits
> > yet.  
> 
> Noted.
> 
> >  
> >>
> >> For mtd->oobavail, I think we need to call some hooks in spinand_init(),
> >> and implement on-die ECC layout in vendor's file and HW ECC layout in
> >> controller's file.
> >>
> >> What's your opinion?  
> >
> > Hm, I'm not so sure. spinand_init() should be called just before
> > registering the MTD device, so by that time everything should have been
> > setup correctly by the upper layer. This being said, I'd like to keep a
> > clear separation between the MTD and NAND layers, and this means
> > preventing any NAND sub-layer from directly manipulating the MTD device
> > and its fields.
> >
> > Really, I don't know yet how I want to abstract ECC stuff, so let's
> > keep it simple for now and expose the whole OOB area (I'll fix the core
> > to do that if you're okay).  
> 
> OK.
> 
> >  
> >>
> >> With the two thing fixed, we can pass UBIFS mount and mtd test.  
> >
> > Do you still have the problem you reported earlier (OOB test)?  
> 
> I forgot to reply that mail :(. Actually there is no problem because
> mtd_write_oob() already has mtd_check_oob_ops() to check it.
> That failure in OOB test occurs because mtd->oobavail is zero.

I reconsidered what I said earlier, and I think it's safer to set
->oobavail to 0 are for now, otherwise we might end up with setups that
start using some of it and we'll break things as soon as we'll add
support for ECC.

^ permalink raw reply	[flat|nested] 65+ messages in thread

end of thread, other threads:[~2018-01-08 22:07 UTC | newest]

Thread overview: 65+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-24  7:06 [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Peter Pan
2017-05-24  7:06 ` [PATCH v6 01/15] mtd: nand: Rename nand.h into rawnand.h Peter Pan
2017-05-24  7:06 ` [PATCH v6 02/15] mtd: nand: move raw NAND related code to the raw/ subdir Peter Pan
2017-05-24  7:06 ` [PATCH v6 03/15] mtd: nand: add a nand.h file to expose basic NAND stuff Peter Pan
2017-05-29 20:14   ` Boris Brezillon
2017-05-24  7:07 ` [PATCH v6 04/15] mtd: nand: raw: prefix conflicting names with nandcchip instead of nand Peter Pan
2017-05-29 20:22   ` Boris Brezillon
2017-05-24  7:07 ` [PATCH v6 05/15] mtd: nand: raw: create struct rawnand_device Peter Pan
2017-05-29 21:05   ` Boris Brezillon
2017-05-24  7:07 ` [PATCH v6 06/15] mtd: nand: raw: make BBT code more generic Peter Pan
2017-05-24  7:07 ` [PATCH v6 07/15] mtd: nand: move BBT code to drivers/mtd/nand/ Peter Pan
2017-05-24  7:07 ` [PATCH v6 08/15] mtd: nand: Add the page iterator concept Peter Pan
2017-05-29 21:12   ` Boris Brezillon
2017-05-24  7:07 ` [PATCH v6 09/15] mtd: nand: make sure mtd_oob_ops consistent in bbt Peter Pan
2017-05-29 21:06   ` Boris Brezillon
2017-05-24  7:07 ` [PATCH v6 10/15] nand: spi: add basic blocks for infrastructure Peter Pan
2017-05-29 21:51   ` Boris Brezillon
2017-05-31  7:02     ` Peter Pan 潘栋 (peterpandong)
2017-05-31 21:45   ` Cyrille Pitchen
2017-06-01  7:24     ` Boris Brezillon
2017-05-24  7:07 ` [PATCH v6 11/15] nand: spi: add basic operations support Peter Pan
2017-05-29 22:11   ` Boris Brezillon
2017-05-31  6:51     ` Peter Pan 潘栋 (peterpandong)
2017-05-31 10:02       ` Boris Brezillon
2017-06-27 20:15       ` Boris Brezillon
2017-06-28  9:41         ` Arnaud Mouiche
2017-06-28 11:32           ` Boris Brezillon
2017-06-29  5:45           ` Peter Pan 潘栋 (peterpandong)
2017-06-29  6:07         ` Peter Pan 潘栋 (peterpandong)
2017-06-29  7:05           ` Arnaud Mouiche
2017-10-11 13:35   ` Boris Brezillon
2017-10-12  1:28     ` Peter Pan
2017-05-24  7:07 ` [PATCH v6 12/15] nand: spi: Add bad block support Peter Pan
2017-05-24  7:07 ` [PATCH v6 13/15] nand: spi: add Micron spi nand support Peter Pan
2017-05-24  7:07 ` [PATCH v6 14/15] nand: spi: Add generic SPI controller support Peter Pan
2017-05-24  7:07 ` [PATCH v6 15/15] MAINTAINERS: Add SPI NAND entry Peter Pan
2017-05-29 20:59 ` [PATCH v6 00/15] A SPI NAND framework under generic NAND framework Boris Brezillon
2017-12-04 13:32   ` Frieder Schrempf
2017-12-04 14:05     ` Boris Brezillon
2017-12-05  1:35       ` Peter Pan 潘栋 (peterpandong)
2017-12-05 12:58         ` Boris Brezillon
2017-12-05 13:03           ` Boris Brezillon
2017-12-12  9:58             ` Frieder Schrempf
2017-12-13 21:27               ` Boris Brezillon
2017-12-14  6:15                 ` Peter Pan
2017-12-14  7:50                   ` Boris Brezillon
2017-12-14  8:06                     ` Peter Pan
2017-12-14 14:39                       ` Frieder Schrempf
2017-12-14 14:43                         ` Frieder Schrempf
2017-12-14 15:38                         ` Boris Brezillon
2017-12-15  1:08                           ` Peter Pan
2017-12-15  1:21                             ` Peter Pan
2017-12-21 11:48                               ` Frieder Schrempf
2017-12-21 13:01                                 ` Boris Brezillon
2017-12-21 13:54                                   ` Frieder Schrempf
2017-12-22  0:49                                 ` Peter Pan
2017-12-22  6:37                                   ` Peter Pan
2017-12-22  8:28                                     ` Boris Brezillon
2017-12-22 13:51                                     ` Boris Brezillon
2018-01-02  2:51                                       ` Peter Pan
2018-01-03 16:46                                         ` Boris Brezillon
2018-01-04  2:01                                           ` Peter Pan
2018-01-08 22:07                                             ` Boris Brezillon
2017-12-15  2:35                     ` Peter Pan
2017-12-15 12:41                       ` Boris Brezillon

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.