Watch
1
Fork
You've already forked kernel_a52xq
0
mirror of https://github.com/a52xq-dev/kernel.git synced 2026-10-18 21:58:11 +07:00

mtd: nand: move raw NAND related code to the raw/ subdir

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@bootlin.com>
This commit is contained in:
Boris Brezillon 2018-02-05 23:02:04 +01:00
commit 93db446a42
98 changed files with 669 additions and 665 deletions

View file

@ -46,7 +46,7 @@ NAND
----
The NAND hardware is similar to the S3C2440, and is supported by the
s3c2410 driver in the drivers/mtd/nand directory.
s3c2410 driver in the drivers/mtd/nand/raw directory.
USB Host

View file

@ -967,10 +967,10 @@ API functions which are exported. Each function has a short description
which is marked with an [XXX] identifier. See the chapter "Documentation
hints" for an explanation.
.. kernel-doc:: drivers/mtd/nand/nand_base.c
.. kernel-doc:: drivers/mtd/nand/raw/nand_base.c
:export:
.. kernel-doc:: drivers/mtd/nand/nand_ecc.c
.. kernel-doc:: drivers/mtd/nand/raw/nand_ecc.c
:export:
Internal Functions Provided
@ -982,10 +982,10 @@ marked with an [XXX] identifier. See the chapter "Documentation hints"
for an explanation. The functions marked with [DEFAULT] might be
relevant for a board driver developer.
.. kernel-doc:: drivers/mtd/nand/nand_base.c
.. kernel-doc:: drivers/mtd/nand/raw/nand_base.c
:internal:
.. kernel-doc:: drivers/mtd/nand/nand_bbt.c
.. kernel-doc:: drivers/mtd/nand/raw/nand_bbt.c
:internal:
Credits

View file

@ -74,8 +74,8 @@ hardware descriptions such as device tree or ACPI:
it from 1-to-0-to-1. If that hardware does not receive its "ping"
periodically, it will reset the system.
- gpio-nand: drivers/mtd/nand/gpio.c is used to connect a NAND flash chip to
a set of simple GPIO lines: RDY, NCE, ALE, CLE, NWP. It interacts with the
- gpio-nand: drivers/mtd/nand/raw/gpio.c is used to connect a NAND flash chip
to a set of simple GPIO lines: RDY, NCE, ALE, CLE, NWP. It interacts with the
NAND flash MTD subsystem and provides chip access and partition parsing like
any other NAND driving hardware.

View file

@ -1710,7 +1710,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
@ -3014,7 +3014,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 DPFE DRIVER
M: Markus Mayer <mmayer@broadcom.com>
@ -4116,7 +4116,7 @@ DENALI NAND DRIVER
M: Masahiro Yamada <yamada.masahiro@socionext.com>
L: linux-mtd@lists.infradead.org
S: Supported
F: drivers/mtd/nand/denali*
F: drivers/mtd/nand/raw/denali*
DESIGNWARE USB2 DRD IP DRIVER
M: John Youn <johnyoun@synopsys.com>
@ -5646,7 +5646,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>
@ -6955,7 +6955,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_*
INOTIFY
M: Jan Kara <jack@suse.cz>
@ -8474,7 +8474,7 @@ MARVELL NAND CONTROLLER DRIVER
M: Miquel Raynal <miquel.raynal@free-electrons.com>
L: linux-mtd@lists.infradead.org
S: Maintained
F: drivers/mtd/nand/marvell_nand.c
F: drivers/mtd/nand/raw/marvell_nand.c
F: Documentation/devicetree/bindings/mtd/marvell-nand.txt
MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
@ -9136,7 +9136,7 @@ M: Wenyou Yang <wenyou.yang@microchip.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/*
F: Documentation/devicetree/bindings/mtd/atmel-nand.txt
MICROCHIP KSZ SERIES ETHERNET SWITCH DRIVER
@ -11331,7 +11331,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
QAT DRIVER
M: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
@ -11815,8 +11815,8 @@ F: drivers/memstick/host/r592.*
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
RISC-V ARCHITECTURE
M: Palmer Dabbelt <palmer@sifive.com>
@ -14635,7 +14635,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>

View file

@ -1,580 +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
select MFD_ATMEL_SMC
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 !MTD_NAND_MARVELL
depends on PXA3xx || ARCH_MMP || PLAT_ORION || ARCH_MVEBU
help
This enables the driver for the NAND flash device found on
PXA3xx processors (NFCv1) and also on 32-bit Armada
platforms (XP, 370, 375, 38x, 39x) and 64-bit Armada
platforms (7K, 8K) (NFCv2).
config MTD_NAND_MARVELL
tristate "NAND controller support on Marvell boards"
depends on PXA3xx || ARCH_MMP || PLAT_ORION || ARCH_MVEBU || \
COMPILE_TEST
depends on HAS_IOMEM
help
This enables the NAND flash controller driver for Marvell boards,
including:
- PXA3xx processors (NFCv1)
- 32-bit Armada platforms (XP, 37x, 38x, 39x) (NFCv2)
- 64-bit Aramda platforms (7k, 8k) (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.
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"

View file

@ -1,68 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
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_MARVELL) += marvell_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_ecc.o mtk_nand.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/

View file

@ -0,0 +1,580 @@
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
select MFD_ATMEL_SMC
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 !MTD_NAND_MARVELL
depends on PXA3xx || ARCH_MMP || PLAT_ORION || ARCH_MVEBU
help
This enables the driver for the NAND flash device found on
PXA3xx processors (NFCv1) and also on 32-bit Armada
platforms (XP, 370, 375, 38x, 39x) and 64-bit Armada
platforms (7K, 8K) (NFCv2).
config MTD_NAND_MARVELL
tristate "NAND controller support on Marvell boards"
depends on PXA3xx || ARCH_MMP || PLAT_ORION || ARCH_MVEBU || \
COMPILE_TEST
depends on HAS_IOMEM
help
This enables the NAND flash controller driver for Marvell boards,
including:
- PXA3xx processors (NFCv1)
- 32-bit Armada platforms (XP, 37x, 38x, 39x) (NFCv2)
- 64-bit Aramda platforms (7k, 8k) (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.
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

View file

@ -0,0 +1,68 @@
# SPDX-License-Identifier: GPL-2.0
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_MARVELL) += marvell_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_ecc.o mtk_nand.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

View file

@ -0,0 +1,291 @@
/*
* Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
*
* Derived from drivers/mtd/nand/toto.c (removed in v2.6.28)
* Copyright (c) 2003 Texas Instruments
* Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
*
* Converted to platform driver by Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
* Partially stolen from plat_nand.c
*
* 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.
*
* Overview:
* This is a device driver for the NAND flash device found on the
* Amstrad E3 (Delta).
*/
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/gpio.h>
#include <linux/platform_data/gpio-omap.h>
#include <asm/io.h>
#include <asm/sizes.h>
#include <mach/board-ams-delta.h>
#include <mach/hardware.h>
/*
* MTD structure for E3 (Delta)
*/
static struct mtd_info *ams_delta_mtd = NULL;
/*
* Define partitions for flash devices
*/
static const struct mtd_partition partition_info[] = {
{ .name = "Kernel",
.offset = 0,
.size = 3 * SZ_1M + SZ_512K },
{ .name = "u-boot",
.offset = 3 * SZ_1M + SZ_512K,
.size = SZ_256K },
{ .name = "u-boot params",
.offset = 3 * SZ_1M + SZ_512K + SZ_256K,
.size = SZ_256K },
{ .name = "Amstrad LDR",
.offset = 4 * SZ_1M,
.size = SZ_256K },
{ .name = "File system",
.offset = 4 * SZ_1M + 1 * SZ_256K,
.size = 27 * SZ_1M },
{ .name = "PBL reserved",
.offset = 32 * SZ_1M - 3 * SZ_256K,
.size = 3 * SZ_256K },
};
static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
{
struct nand_chip *this = mtd_to_nand(mtd);
void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
writew(0, io_base + OMAP_MPUIO_IO_CNTL);
writew(byte, this->IO_ADDR_W);
gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 0);
ndelay(40);
gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 1);
}
static u_char ams_delta_read_byte(struct mtd_info *mtd)
{
u_char res;
struct nand_chip *this = mtd_to_nand(mtd);
void __iomem *io_base = (void __iomem *)nand_get_controller_data(this);
gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 0);
ndelay(40);
writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
res = readw(this->IO_ADDR_R);
gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 1);
return res;
}
static void ams_delta_write_buf(struct mtd_info *mtd, const u_char *buf,
int len)
{
int i;
for (i=0; i<len; i++)
ams_delta_write_byte(mtd, buf[i]);
}
static void ams_delta_read_buf(struct mtd_info *mtd, u_char *buf, int len)
{
int i;
for (i=0; i<len; i++)
buf[i] = ams_delta_read_byte(mtd);
}
/*
* Command control function
*
* ctrl:
* NAND_NCE: bit 0 -> bit 2
* NAND_CLE: bit 1 -> bit 7
* NAND_ALE: bit 2 -> bit 6
*/
static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
{
if (ctrl & NAND_CTRL_CHANGE) {
gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NCE,
(ctrl & NAND_NCE) == 0);
gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_CLE,
(ctrl & NAND_CLE) != 0);
gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_ALE,
(ctrl & NAND_ALE) != 0);
}
if (cmd != NAND_CMD_NONE)
ams_delta_write_byte(mtd, cmd);
}
static int ams_delta_nand_ready(struct mtd_info *mtd)
{
return gpio_get_value(AMS_DELTA_GPIO_PIN_NAND_RB);
}
static const struct gpio _mandatory_gpio[] = {
{
.gpio = AMS_DELTA_GPIO_PIN_NAND_NCE,
.flags = GPIOF_OUT_INIT_HIGH,
.label = "nand_nce",
},
{
.gpio = AMS_DELTA_GPIO_PIN_NAND_NRE,
.flags = GPIOF_OUT_INIT_HIGH,
.label = "nand_nre",
},
{
.gpio = AMS_DELTA_GPIO_PIN_NAND_NWP,
.flags = GPIOF_OUT_INIT_HIGH,
.label = "nand_nwp",
},
{
.gpio = AMS_DELTA_GPIO_PIN_NAND_NWE,
.flags = GPIOF_OUT_INIT_HIGH,
.label = "nand_nwe",
},
{
.gpio = AMS_DELTA_GPIO_PIN_NAND_ALE,
.flags = GPIOF_OUT_INIT_LOW,
.label = "nand_ale",
},
{
.gpio = AMS_DELTA_GPIO_PIN_NAND_CLE,
.flags = GPIOF_OUT_INIT_LOW,
.label = "nand_cle",
},
};
/*
* Main initialization routine
*/
static int ams_delta_init(struct platform_device *pdev)
{
struct nand_chip *this;
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
void __iomem *io_base;
int err = 0;
if (!res)
return -ENXIO;
/* Allocate memory for MTD device structure and private data */
this = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
if (!this) {
printk (KERN_WARNING "Unable to allocate E3 NAND MTD device structure.\n");
err = -ENOMEM;
goto out;
}
ams_delta_mtd = nand_to_mtd(this);
ams_delta_mtd->owner = THIS_MODULE;
/*
* Don't try to request the memory region from here,
* it should have been already requested from the
* gpio-omap driver and requesting it again would fail.
*/
io_base = ioremap(res->start, resource_size(res));
if (io_base == NULL) {
dev_err(&pdev->dev, "ioremap failed\n");
err = -EIO;
goto out_free;
}
nand_set_controller_data(this, (void *)io_base);
/* Set address of NAND IO lines */
this->IO_ADDR_R = io_base + OMAP_MPUIO_INPUT_LATCH;
this->IO_ADDR_W = io_base + OMAP_MPUIO_OUTPUT;
this->read_byte = ams_delta_read_byte;
this->write_buf = ams_delta_write_buf;
this->read_buf = ams_delta_read_buf;
this->cmd_ctrl = ams_delta_hwcontrol;
if (gpio_request(AMS_DELTA_GPIO_PIN_NAND_RB, "nand_rdy") == 0) {
this->dev_ready = ams_delta_nand_ready;
} else {
this->dev_ready = NULL;
printk(KERN_NOTICE "Couldn't request gpio for Delta NAND ready.\n");
}
/* 25 us command delay time */
this->chip_delay = 30;
this->ecc.mode = NAND_ECC_SOFT;
this->ecc.algo = NAND_ECC_HAMMING;
platform_set_drvdata(pdev, io_base);
/* Set chip enabled, but */
err = gpio_request_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio));
if (err)
goto out_gpio;
/* Scan to find existence of the device */
err = nand_scan(ams_delta_mtd, 1);
if (err)
goto out_mtd;
/* Register the partitions */
mtd_device_register(ams_delta_mtd, partition_info,
ARRAY_SIZE(partition_info));
goto out;
out_mtd:
gpio_free_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio));
out_gpio:
gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB);
iounmap(io_base);
out_free:
kfree(this);
out:
return err;
}
/*
* Clean up routine
*/
static int ams_delta_cleanup(struct platform_device *pdev)
{
void __iomem *io_base = platform_get_drvdata(pdev);
/* Release resources, unregister device */
nand_release(ams_delta_mtd);
gpio_free_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio));
gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB);
iounmap(io_base);
/* Free the MTD device structure */
kfree(mtd_to_nand(ams_delta_mtd));
return 0;
}
static struct platform_driver ams_delta_nand_driver = {
.probe = ams_delta_init,
.remove = ams_delta_cleanup,
.driver = {
.name = "ams-delta-nand",
},
};
module_platform_driver(ams_delta_nand_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
MODULE_DESCRIPTION("Glue layer for NAND flash on Amstrad E3 (Delta)");

View file

@ -0,0 +1,4 @@
obj-$(CONFIG_MTD_NAND_ATMEL) += atmel-nand-controller.o atmel-pmecc.o
atmel-nand-controller-objs := nand-controller.o
atmel-pmecc-objs := pmecc.o

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,74 @@
/*
* © Copyright 2016 ATMEL
* © Copyright 2016 Free Electrons
*
* Author: Boris Brezillon <boris.brezillon@free-electrons.com>
*
* Derived from the atmel_nand.c driver which contained the following
* copyrights:
*
* Copyright © 2003 Rick Bronson
*
* Derived from drivers/mtd/nand/autcpu12.c (removed in v3.8)
* Copyright © 2001 Thomas Gleixner (gleixner@autronix.de)
*
* Derived from drivers/mtd/spia.c (removed in v3.8)
* Copyright © 2000 Steven J. Hill (sjhill@cotw.com)
*
*
* Add Hardware ECC support for AT91SAM9260 / AT91SAM9263
* Richard Genoud (richard.genoud@gmail.com), Adeneo Copyright © 2007
*
* Derived from Das U-Boot source code
* (u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c)
* © Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
*
* Add Programmable Multibit ECC support for various AT91 SoC
* © Copyright 2012 ATMEL, Hong Xu
*
* Add Nand Flash Controller support for SAMA5 SoC
* © Copyright 2013 ATMEL, Josh Wu (josh.wu@atmel.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 ATMEL_PMECC_H
#define ATMEL_PMECC_H
#define ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH 0
#define ATMEL_PMECC_SECTOR_SIZE_AUTO 0
#define ATMEL_PMECC_OOBOFFSET_AUTO -1
struct atmel_pmecc_user_req {
int pagesize;
int oobsize;
struct {
int strength;
int bytes;
int sectorsize;
int nsectors;
int ooboffset;
} ecc;
};
struct atmel_pmecc *devm_atmel_pmecc_get(struct device *dev);
struct atmel_pmecc_user *
atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
struct atmel_pmecc_user_req *req);
void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user);
void atmel_pmecc_reset(struct atmel_pmecc *pmecc);
int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op);
void atmel_pmecc_disable(struct atmel_pmecc_user *user);
int atmel_pmecc_wait_rdy(struct atmel_pmecc_user *user);
int atmel_pmecc_correct_sector(struct atmel_pmecc_user *user, int sector,
void *data, void *ecc);
bool atmel_pmecc_correct_erased_chunks(struct atmel_pmecc_user *user);
void atmel_pmecc_get_generated_eccbytes(struct atmel_pmecc_user *user,
int sector, void *ecc);
#endif /* ATMEL_PMECC_H */

View file

@ -0,0 +1,515 @@
/*
* Copyright (C) 2004 Embedded Edge, LLC
*
* 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.
*
*/
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-au1x00/au1550nd.h>
struct au1550nd_ctx {
struct nand_chip chip;
int cs;
void __iomem *base;
void (*write_byte)(struct mtd_info *, u_char);
};
/**
* au_read_byte - read one byte from the chip
* @mtd: MTD device structure
*
* read function for 8bit buswidth
*/
static u_char au_read_byte(struct mtd_info *mtd)
{
struct nand_chip *this = mtd_to_nand(mtd);
u_char ret = readb(this->IO_ADDR_R);
wmb(); /* drain writebuffer */
return ret;
}
/**
* au_write_byte - write one byte to the chip
* @mtd: MTD device structure
* @byte: pointer to data byte to write
*
* write function for 8it buswidth
*/
static void au_write_byte(struct mtd_info *mtd, u_char byte)
{
struct nand_chip *this = mtd_to_nand(mtd);
writeb(byte, this->IO_ADDR_W);
wmb(); /* drain writebuffer */
}
/**
* au_read_byte16 - read one byte endianness aware from the chip
* @mtd: MTD device structure
*
* read function for 16bit buswidth with endianness conversion
*/
static u_char au_read_byte16(struct mtd_info *mtd)
{
struct nand_chip *this = mtd_to_nand(mtd);
u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
wmb(); /* drain writebuffer */
return ret;
}
/**
* au_write_byte16 - write one byte endianness aware to the chip
* @mtd: MTD device structure
* @byte: pointer to data byte to write
*
* write function for 16bit buswidth with endianness conversion
*/
static void au_write_byte16(struct mtd_info *mtd, u_char byte)
{
struct nand_chip *this = mtd_to_nand(mtd);
writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
wmb(); /* drain writebuffer */
}
/**
* au_read_word - read one word from the chip
* @mtd: MTD device structure
*
* read function for 16bit buswidth without endianness conversion
*/
static u16 au_read_word(struct mtd_info *mtd)
{
struct nand_chip *this = mtd_to_nand(mtd);
u16 ret = readw(this->IO_ADDR_R);
wmb(); /* drain writebuffer */
return ret;
}
/**
* au_write_buf - write buffer to chip
* @mtd: MTD device structure
* @buf: data buffer
* @len: number of bytes to write
*
* write function for 8bit buswidth
*/
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);
for (i = 0; i < len; i++) {
writeb(buf[i], this->IO_ADDR_W);
wmb(); /* drain writebuffer */
}
}
/**
* au_read_buf - read chip data into buffer
* @mtd: MTD device structure
* @buf: buffer to store date
* @len: number of bytes to read
*
* read function for 8bit buswidth
*/
static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
{
int i;
struct nand_chip *this = mtd_to_nand(mtd);
for (i = 0; i < len; i++) {
buf[i] = readb(this->IO_ADDR_R);
wmb(); /* drain writebuffer */
}
}
/**
* au_write_buf16 - write buffer to chip
* @mtd: MTD device structure
* @buf: data buffer
* @len: number of bytes to write
*
* write function for 16bit buswidth
*/
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);
u16 *p = (u16 *) buf;
len >>= 1;
for (i = 0; i < len; i++) {
writew(p[i], this->IO_ADDR_W);
wmb(); /* drain writebuffer */
}
}
/**
* au_read_buf16 - read chip data into buffer
* @mtd: MTD device structure
* @buf: buffer to store date
* @len: number of bytes to read
*
* read function for 16bit buswidth
*/
static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
{
int i;
struct nand_chip *this = mtd_to_nand(mtd);
u16 *p = (u16 *) buf;
len >>= 1;
for (i = 0; i < len; i++) {
p[i] = readw(this->IO_ADDR_R);
wmb(); /* drain writebuffer */
}
}
/* Select the chip by setting nCE to low */
#define NAND_CTL_SETNCE 1
/* Deselect the chip by setting nCE to high */
#define NAND_CTL_CLRNCE 2
/* Select the command latch by setting CLE to high */
#define NAND_CTL_SETCLE 3
/* Deselect the command latch by setting CLE to low */
#define NAND_CTL_CLRCLE 4
/* Select the address latch by setting ALE to high */
#define NAND_CTL_SETALE 5
/* Deselect the address latch by setting ALE to low */
#define NAND_CTL_CLRALE 6
static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct au1550nd_ctx *ctx = container_of(this, struct au1550nd_ctx,
chip);
switch (cmd) {
case NAND_CTL_SETCLE:
this->IO_ADDR_W = ctx->base + MEM_STNAND_CMD;
break;
case NAND_CTL_CLRCLE:
this->IO_ADDR_W = ctx->base + MEM_STNAND_DATA;
break;
case NAND_CTL_SETALE:
this->IO_ADDR_W = ctx->base + MEM_STNAND_ADDR;
break;
case NAND_CTL_CLRALE:
this->IO_ADDR_W = ctx->base + MEM_STNAND_DATA;
/* FIXME: Nobody knows why this is necessary,
* but it works only that way */
udelay(1);
break;
case NAND_CTL_SETNCE:
/* assert (force assert) chip enable */
alchemy_wrsmem((1 << (4 + ctx->cs)), AU1000_MEM_STNDCTL);
break;
case NAND_CTL_CLRNCE:
/* deassert chip enable */
alchemy_wrsmem(0, AU1000_MEM_STNDCTL);
break;
}
this->IO_ADDR_R = this->IO_ADDR_W;
wmb(); /* Drain the writebuffer */
}
int au1550_device_ready(struct mtd_info *mtd)
{
return (alchemy_rdsmem(AU1000_MEM_STSTAT) & 0x1) ? 1 : 0;
}
/**
* au1550_select_chip - control -CE line
* Forbid driving -CE manually permitting the NAND controller to do this.
* Keeping -CE asserted during the whole sector reads interferes with the
* NOR flash and PCMCIA drivers as it causes contention on the static bus.
* We only have to hold -CE low for the NAND read commands since the flash
* chip needs it to be asserted during chip not ready time but the NAND
* controller keeps it released.
*
* @mtd: MTD device structure
* @chip: chipnumber to select, -1 for deselect
*/
static void au1550_select_chip(struct mtd_info *mtd, int chip)
{
}
/**
* au1550_command - Send command to NAND device
* @mtd: MTD device structure
* @command: the command to be sent
* @column: the column address for this command, -1 if none
* @page_addr: the page address for this command, -1 if none
*/
static void au1550_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct au1550nd_ctx *ctx = container_of(this, struct au1550nd_ctx,
chip);
int ce_override = 0, i;
unsigned long flags = 0;
/* Begin command latch cycle */
au1550_hwcontrol(mtd, NAND_CTL_SETCLE);
/*
* Write out the command to the device.
*/
if (command == NAND_CMD_SEQIN) {
int readcmd;
if (column >= mtd->writesize) {
/* OOB area */
column -= mtd->writesize;
readcmd = NAND_CMD_READOOB;
} else if (column < 256) {
/* First 256 bytes --> READ0 */
readcmd = NAND_CMD_READ0;
} else {
column -= 256;
readcmd = NAND_CMD_READ1;
}
ctx->write_byte(mtd, readcmd);
}
ctx->write_byte(mtd, command);
/* Set ALE and clear CLE to start address cycle */
au1550_hwcontrol(mtd, NAND_CTL_CLRCLE);
if (column != -1 || page_addr != -1) {
au1550_hwcontrol(mtd, NAND_CTL_SETALE);
/* Serially input address */
if (column != -1) {
/* Adjust columns for 16 bit buswidth */
if (this->options & NAND_BUSWIDTH_16 &&
!nand_opcode_8bits(command))
column >>= 1;
ctx->write_byte(mtd, column);
}
if (page_addr != -1) {
ctx->write_byte(mtd, (u8)(page_addr & 0xff));
if (command == NAND_CMD_READ0 ||
command == NAND_CMD_READ1 ||
command == NAND_CMD_READOOB) {
/*
* NAND controller will release -CE after
* the last address byte is written, so we'll
* have to forcibly assert it. No interrupts
* are allowed while we do this as we don't
* want the NOR flash or PCMCIA drivers to
* steal our precious bytes of data...
*/
ce_override = 1;
local_irq_save(flags);
au1550_hwcontrol(mtd, NAND_CTL_SETNCE);
}
ctx->write_byte(mtd, (u8)(page_addr >> 8));
if (this->options & NAND_ROW_ADDR_3)
ctx->write_byte(mtd,
((page_addr >> 16) & 0x0f));
}
/* Latch in address */
au1550_hwcontrol(mtd, NAND_CTL_CLRALE);
}
/*
* Program and erase have their own busy handlers.
* Status and sequential in need no delay.
*/
switch (command) {
case NAND_CMD_PAGEPROG:
case NAND_CMD_ERASE1:
case NAND_CMD_ERASE2:
case NAND_CMD_SEQIN:
case NAND_CMD_STATUS:
return;
case NAND_CMD_RESET:
break;
case NAND_CMD_READ0:
case NAND_CMD_READ1:
case NAND_CMD_READOOB:
/* Check if we're really driving -CE low (just in case) */
if (unlikely(!ce_override))
break;
/* Apply a short delay always to ensure that we do wait tWB. */
ndelay(100);
/* Wait for a chip to become ready... */
for (i = this->chip_delay; !this->dev_ready(mtd) && i > 0; --i)
udelay(1);
/* Release -CE and re-enable interrupts. */
au1550_hwcontrol(mtd, NAND_CTL_CLRNCE);
local_irq_restore(flags);
return;
}
/* Apply this short delay always to ensure that we do wait tWB. */
ndelay(100);
while(!this->dev_ready(mtd));
}
static int find_nand_cs(unsigned long nand_base)
{
void __iomem *base =
(void __iomem *)KSEG1ADDR(AU1000_STATIC_MEM_PHYS_ADDR);
unsigned long addr, staddr, start, mask, end;
int i;
for (i = 0; i < 4; i++) {
addr = 0x1000 + (i * 0x10); /* CSx */
staddr = __raw_readl(base + addr + 0x08); /* STADDRx */
/* figure out the decoded range of this CS */
start = (staddr << 4) & 0xfffc0000;
mask = (staddr << 18) & 0xfffc0000;
end = (start | (start - 1)) & ~(start ^ mask);
if ((nand_base >= start) && (nand_base < end))
return i;
}
return -ENODEV;
}
static int au1550nd_probe(struct platform_device *pdev)
{
struct au1550nd_platdata *pd;
struct au1550nd_ctx *ctx;
struct nand_chip *this;
struct mtd_info *mtd;
struct resource *r;
int ret, cs;
pd = dev_get_platdata(&pdev->dev);
if (!pd) {
dev_err(&pdev->dev, "missing platform data\n");
return -ENODEV;
}
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r) {
dev_err(&pdev->dev, "no NAND memory resource\n");
ret = -ENODEV;
goto out1;
}
if (request_mem_region(r->start, resource_size(r), "au1550-nand")) {
dev_err(&pdev->dev, "cannot claim NAND memory area\n");
ret = -ENOMEM;
goto out1;
}
ctx->base = ioremap_nocache(r->start, 0x1000);
if (!ctx->base) {
dev_err(&pdev->dev, "cannot remap NAND memory area\n");
ret = -ENODEV;
goto out2;
}
this = &ctx->chip;
mtd = nand_to_mtd(this);
mtd->dev.parent = &pdev->dev;
/* figure out which CS# r->start belongs to */
cs = find_nand_cs(r->start);
if (cs < 0) {
dev_err(&pdev->dev, "cannot detect NAND chipselect\n");
ret = -ENODEV;
goto out3;
}
ctx->cs = cs;
this->dev_ready = au1550_device_ready;
this->select_chip = au1550_select_chip;
this->cmdfunc = au1550_command;
/* 30 us command delay time */
this->chip_delay = 30;
this->ecc.mode = NAND_ECC_SOFT;
this->ecc.algo = NAND_ECC_HAMMING;
if (pd->devwidth)
this->options |= NAND_BUSWIDTH_16;
this->read_byte = (pd->devwidth) ? au_read_byte16 : au_read_byte;
ctx->write_byte = (pd->devwidth) ? au_write_byte16 : au_write_byte;
this->read_word = au_read_word;
this->write_buf = (pd->devwidth) ? au_write_buf16 : au_write_buf;
this->read_buf = (pd->devwidth) ? au_read_buf16 : au_read_buf;
ret = nand_scan(mtd, 1);
if (ret) {
dev_err(&pdev->dev, "NAND scan failed with %d\n", ret);
goto out3;
}
mtd_device_register(mtd, pd->parts, pd->num_parts);
platform_set_drvdata(pdev, ctx);
return 0;
out3:
iounmap(ctx->base);
out2:
release_mem_region(r->start, resource_size(r));
out1:
kfree(ctx);
return ret;
}
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));
iounmap(ctx->base);
release_mem_region(r->start, 0x1000);
kfree(ctx);
return 0;
}
static struct platform_driver au1550nd_driver = {
.driver = {
.name = "au1550-nand",
},
.probe = au1550nd_probe,
.remove = au1550nd_remove,
};
module_platform_driver(au1550nd_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Embedded Edge, LLC");
MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on Pb1550 board");

View file

@ -0,0 +1,4 @@
bcm47xxnflash-y += main.o
bcm47xxnflash-y += ops_bcm4706.o
obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash.o

View file

@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __BCM47XXNFLASH_H
#define __BCM47XXNFLASH_H
#ifndef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#endif
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
struct bcm47xxnflash {
struct bcma_drv_cc *cc;
struct nand_chip nand_chip;
unsigned curr_command;
int curr_page_addr;
int curr_column;
u8 id_data[8];
};
int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n);
#endif /* BCM47XXNFLASH */

View file

@ -0,0 +1,81 @@
/*
* BCM47XX NAND flash driver
*
* Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.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.
*
*/
#include "bcm47xxnflash.h"
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/bcma/bcma.h>
MODULE_DESCRIPTION("NAND flash driver for BCMA bus");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rafał Miłecki");
static const char *probes[] = { "bcm47xxpart", NULL };
static int bcm47xxnflash_probe(struct platform_device *pdev)
{
struct bcma_nflash *nflash = dev_get_platdata(&pdev->dev);
struct bcm47xxnflash *b47n;
struct mtd_info *mtd;
int err = 0;
b47n = devm_kzalloc(&pdev->dev, sizeof(*b47n), GFP_KERNEL);
if (!b47n)
return -ENOMEM;
nand_set_controller_data(&b47n->nand_chip, b47n);
mtd = nand_to_mtd(&b47n->nand_chip);
mtd->dev.parent = &pdev->dev;
b47n->cc = container_of(nflash, struct bcma_drv_cc, nflash);
if (b47n->cc->core->bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
err = bcm47xxnflash_ops_bcm4706_init(b47n);
} else {
pr_err("Device not supported\n");
err = -ENOTSUPP;
}
if (err) {
pr_err("Initialization failed: %d\n", err);
return err;
}
platform_set_drvdata(pdev, b47n);
err = mtd_device_parse_register(mtd, probes, NULL, NULL, 0);
if (err) {
pr_err("Failed to register MTD device: %d\n", err);
return err;
}
return 0;
}
static int bcm47xxnflash_remove(struct platform_device *pdev)
{
struct bcm47xxnflash *nflash = platform_get_drvdata(pdev);
nand_release(nand_to_mtd(&nflash->nand_chip));
return 0;
}
static struct platform_driver bcm47xxnflash_driver = {
.probe = bcm47xxnflash_probe,
.remove = bcm47xxnflash_remove,
.driver = {
.name = "bcma_nflash",
},
};
module_platform_driver(bcm47xxnflash_driver);

View file

@ -0,0 +1,456 @@
/*
* BCM47XX NAND flash driver
*
* Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.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.
*
*/
#include "bcm47xxnflash.h"
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/bcma/bcma.h>
/* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has
* shown ~1000 retries as maxiumum. */
#define NFLASH_READY_RETRIES 10000
#define NFLASH_SECTOR_SIZE 512
#define NCTL_CMD0 0x00010000
#define NCTL_COL 0x00020000 /* Update column with value from BCMA_CC_NFLASH_COL_ADDR */
#define NCTL_ROW 0x00040000 /* Update row (page) with value from BCMA_CC_NFLASH_ROW_ADDR */
#define NCTL_CMD1W 0x00080000
#define NCTL_READ 0x00100000
#define NCTL_WRITE 0x00200000
#define NCTL_SPECADDR 0x01000000
#define NCTL_READY 0x04000000
#define NCTL_ERR 0x08000000
#define NCTL_CSA 0x40000000
#define NCTL_START 0x80000000
/**************************************************
* Various helpers
**************************************************/
static inline u8 bcm47xxnflash_ops_bcm4706_ns_to_cycle(u16 ns, u16 clock)
{
return ((ns * 1000 * clock) / 1000000) + 1;
}
static int bcm47xxnflash_ops_bcm4706_ctl_cmd(struct bcma_drv_cc *cc, u32 code)
{
int i = 0;
bcma_cc_write32(cc, BCMA_CC_NFLASH_CTL, NCTL_START | code);
for (i = 0; i < NFLASH_READY_RETRIES; i++) {
if (!(bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_START)) {
i = 0;
break;
}
}
if (i) {
pr_err("NFLASH control command not ready!\n");
return -EBUSY;
}
return 0;
}
static int bcm47xxnflash_ops_bcm4706_poll(struct bcma_drv_cc *cc)
{
int i;
for (i = 0; i < NFLASH_READY_RETRIES; i++) {
if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_READY) {
if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) &
BCMA_CC_NFLASH_CTL_ERR) {
pr_err("Error on polling\n");
return -EBUSY;
} else {
return 0;
}
}
}
pr_err("Polling timeout!\n");
return -EBUSY;
}
/**************************************************
* R/W
**************************************************/
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 bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
u32 ctlcode;
u32 *dest = (u32 *)buf;
int i;
int toread;
BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask);
/* Don't validate column using nand_chip->page_shift, it may be bigger
* when accessing OOB */
while (len) {
/* We can read maximum of 0x200 bytes at once */
toread = min(len, 0x200);
/* Set page and column */
bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_COL_ADDR,
b47n->curr_column);
bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_ROW_ADDR,
b47n->curr_page_addr);
/* Prepare to read */
ctlcode = NCTL_CSA | NCTL_CMD1W | NCTL_ROW | NCTL_COL |
NCTL_CMD0;
ctlcode |= NAND_CMD_READSTART << 8;
if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode))
return;
if (bcm47xxnflash_ops_bcm4706_poll(b47n->cc))
return;
/* Eventually read some data :) */
for (i = 0; i < toread; i += 4, dest++) {
ctlcode = NCTL_CSA | 0x30000000 | NCTL_READ;
if (i == toread - 4) /* Last read goes without that */
ctlcode &= ~NCTL_CSA;
if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
ctlcode))
return;
*dest = bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA);
}
b47n->curr_column += toread;
len -= toread;
}
}
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 bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
struct bcma_drv_cc *cc = b47n->cc;
u32 ctlcode;
const u32 *data = (u32 *)buf;
int i;
BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask);
/* Don't validate column using nand_chip->page_shift, it may be bigger
* when accessing OOB */
for (i = 0; i < len; i += 4, data++) {
bcma_cc_write32(cc, BCMA_CC_NFLASH_DATA, *data);
ctlcode = NCTL_CSA | 0x30000000 | NCTL_WRITE;
if (i == len - 4) /* Last read goes without that */
ctlcode &= ~NCTL_CSA;
if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode)) {
pr_err("%s ctl_cmd didn't work!\n", __func__);
return;
}
}
b47n->curr_column += len;
}
/**************************************************
* NAND chip ops
**************************************************/
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 bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
u32 code = 0;
if (cmd == NAND_CMD_NONE)
return;
if (cmd & NAND_CTRL_CLE)
code = cmd | NCTL_CMD0;
/* nCS is not needed for reset command */
if (cmd != NAND_CMD_RESET)
code |= NCTL_CSA;
bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, code);
}
/* Default nand_select_chip calls cmd_ctrl, which is not used in BCM4706 */
static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd,
int chip)
{
return;
}
static int bcm47xxnflash_ops_bcm4706_dev_ready(struct mtd_info *mtd)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
return !!(bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_CTL) & NCTL_READY);
}
/*
* Default nand_command and nand_command_lp don't match BCM4706 hardware layout.
* For example, reading chip id is performed in a non-standard way.
* Setting column and page is also handled differently, we use a special
* registers of ChipCommon core. Hacking cmd_ctrl to understand and convert
* standard commands would be much more complicated.
*/
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 bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
struct bcma_drv_cc *cc = b47n->cc;
u32 ctlcode;
int i;
if (column != -1)
b47n->curr_column = column;
if (page_addr != -1)
b47n->curr_page_addr = page_addr;
switch (command) {
case NAND_CMD_RESET:
nand_chip->cmd_ctrl(mtd, command, NAND_CTRL_CLE);
ndelay(100);
nand_wait_ready(mtd);
break;
case NAND_CMD_READID:
ctlcode = NCTL_CSA | 0x01000000 | NCTL_CMD1W | NCTL_CMD0;
ctlcode |= NAND_CMD_READID;
if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode)) {
pr_err("READID error\n");
break;
}
/*
* Reading is specific, last one has to go without NCTL_CSA
* bit. We don't know how many reads NAND subsystem is going
* to perform, so cache everything.
*/
for (i = 0; i < ARRAY_SIZE(b47n->id_data); i++) {
ctlcode = NCTL_CSA | NCTL_READ;
if (i == ARRAY_SIZE(b47n->id_data) - 1)
ctlcode &= ~NCTL_CSA;
if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
ctlcode)) {
pr_err("READID error\n");
break;
}
b47n->id_data[i] =
bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA)
& 0xFF;
}
break;
case NAND_CMD_STATUS:
ctlcode = NCTL_CSA | NCTL_CMD0 | NAND_CMD_STATUS;
if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
pr_err("STATUS command error\n");
break;
case NAND_CMD_READ0:
break;
case NAND_CMD_READOOB:
if (page_addr != -1)
b47n->curr_column += mtd->writesize;
break;
case NAND_CMD_ERASE1:
bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
b47n->curr_page_addr);
ctlcode = NCTL_ROW | NCTL_CMD1W | NCTL_CMD0 |
NAND_CMD_ERASE1 | (NAND_CMD_ERASE2 << 8);
if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
pr_err("ERASE1 failed\n");
break;
case NAND_CMD_ERASE2:
break;
case NAND_CMD_SEQIN:
/* Set page and column */
bcma_cc_write32(cc, BCMA_CC_NFLASH_COL_ADDR,
b47n->curr_column);
bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
b47n->curr_page_addr);
/* Prepare to write */
ctlcode = 0x40000000 | NCTL_ROW | NCTL_COL | NCTL_CMD0;
ctlcode |= NAND_CMD_SEQIN;
if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
pr_err("SEQIN failed\n");
break;
case NAND_CMD_PAGEPROG:
if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, NCTL_CMD0 |
NAND_CMD_PAGEPROG))
pr_err("PAGEPROG failed\n");
if (bcm47xxnflash_ops_bcm4706_poll(cc))
pr_err("PAGEPROG not ready\n");
break;
default:
pr_err("Command 0x%X unsupported\n", command);
break;
}
b47n->curr_command = command;
}
static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd)
{
struct nand_chip *nand_chip = mtd_to_nand(mtd);
struct bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
struct bcma_drv_cc *cc = b47n->cc;
u32 tmp = 0;
switch (b47n->curr_command) {
case NAND_CMD_READID:
if (b47n->curr_column >= ARRAY_SIZE(b47n->id_data)) {
pr_err("Requested invalid id_data: %d\n",
b47n->curr_column);
return 0;
}
return b47n->id_data[b47n->curr_column++];
case NAND_CMD_STATUS:
if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, NCTL_READ))
return 0;
return bcma_cc_read32(cc, BCMA_CC_NFLASH_DATA) & 0xff;
case NAND_CMD_READOOB:
bcm47xxnflash_ops_bcm4706_read(mtd, (u8 *)&tmp, 4);
return tmp & 0xFF;
}
pr_err("Invalid command for byte read: 0x%X\n", b47n->curr_command);
return 0;
}
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 bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
switch (b47n->curr_command) {
case NAND_CMD_READ0:
case NAND_CMD_READOOB:
bcm47xxnflash_ops_bcm4706_read(mtd, buf, len);
return;
}
pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command);
}
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 bcm47xxnflash *b47n = nand_get_controller_data(nand_chip);
switch (b47n->curr_command) {
case NAND_CMD_SEQIN:
bcm47xxnflash_ops_bcm4706_write(mtd, buf, len);
return;
}
pr_err("Invalid command for buf write: 0x%X\n", b47n->curr_command);
}
/**************************************************
* Init
**************************************************/
int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
{
struct nand_chip *nand_chip = (struct nand_chip *)&b47n->nand_chip;
int err;
u32 freq;
u16 clock;
u8 w0, w1, w2, w3, w4;
unsigned long chipsize; /* MiB */
u8 tbits, col_bits, col_size, row_bits, row_bsize;
u32 val;
b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip;
nand_chip->cmd_ctrl = bcm47xxnflash_ops_bcm4706_cmd_ctrl;
nand_chip->dev_ready = bcm47xxnflash_ops_bcm4706_dev_ready;
b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc;
b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;
b47n->nand_chip.read_buf = bcm47xxnflash_ops_bcm4706_read_buf;
b47n->nand_chip.write_buf = bcm47xxnflash_ops_bcm4706_write_buf;
b47n->nand_chip.onfi_set_features = nand_onfi_get_set_features_notsupp;
b47n->nand_chip.onfi_get_features = nand_onfi_get_set_features_notsupp;
nand_chip->chip_delay = 50;
b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH;
b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */
/* Enable NAND flash access */
bcma_cc_set32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
BCMA_CC_4706_FLASHSCFG_NF1);
/* Configure wait counters */
if (b47n->cc->status & BCMA_CC_CHIPST_4706_PKG_OPTION) {
/* 400 MHz */
freq = 400000000 / 4;
} else {
freq = bcma_chipco_pll_read(b47n->cc, 4);
freq = (freq & 0xFFF) >> 3;
/* Fixed reference clock 25 MHz and m = 2 */
freq = (freq * 25000000 / 2) / 4;
}
clock = freq / 1000000;
w0 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(15, clock);
w1 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(20, clock);
w2 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
w3 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
w4 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(100, clock);
bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_WAITCNT0,
(w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0));
/* Scan NAND */
err = nand_scan(nand_to_mtd(&b47n->nand_chip), 1);
if (err) {
pr_err("Could not scan NAND flash: %d\n", err);
goto exit;
}
/* Configure FLASH */
chipsize = b47n->nand_chip.chipsize >> 20;
tbits = ffs(chipsize); /* find first bit set */
if (!tbits || tbits != fls(chipsize)) {
pr_err("Invalid flash size: 0x%lX\n", chipsize);
err = -ENOTSUPP;
goto exit;
}
tbits += 19; /* Broadcom increases *index* by 20, we increase *pos* */
col_bits = b47n->nand_chip.page_shift + 1;
col_size = (col_bits + 7) / 8;
row_bits = tbits - col_bits + 1;
row_bsize = (row_bits + 7) / 8;
val = ((row_bsize - 1) << 6) | ((col_size - 1) << 4) | 2;
bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_CONF, val);
exit:
if (err)
bcma_cc_mask32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
~BCMA_CC_4706_FLASHSCFG_NF1);
return err;
}

View file

@ -0,0 +1,861 @@
/*
* Copyright 2006-2008 Analog Devices Inc.
* http://blackfin.uclinux.org/
* Bryan Wu <bryan.wu@analog.com>
*
* Blackfin BF5xx on-chip NAND flash controller driver
*
* Derived from s3c2410.c
* Copyright (c) 2007 Ben Dooks <ben@simtec.co.uk>
*
* Derived from cafe.c
* Copyright © 2006 Red Hat, Inc.
* Copyright © 2006 David Woodhouse <dwmw2@infradead.org>
*
* Changelog:
* 12-Jun-2007 Bryan Wu: Initial version
* 18-Jul-2007 Bryan Wu:
* - ECC_HW and ECC_SW supported
* - DMA supported in ECC_HW
* - YAFFS tested as rootfs in both ECC_HW and ECC_SW
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/bitops.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
#include <asm/blackfin.h>
#include <asm/dma.h>
#include <asm/cacheflush.h>
#include <asm/nand.h>
#include <asm/portmux.h>
#define DRV_NAME "bf5xx-nand"
#define DRV_VERSION "1.2"
#define DRV_AUTHOR "Bryan Wu <bryan.wu@analog.com>"
#define DRV_DESC "BF5xx on-chip NAND FLash Controller Driver"
/* NFC_STAT Masks */
#define NBUSY 0x01 /* Not Busy */
#define WB_FULL 0x02 /* Write Buffer Full */
#define PG_WR_STAT 0x04 /* Page Write Pending */
#define PG_RD_STAT 0x08 /* Page Read Pending */
#define WB_EMPTY 0x10 /* Write Buffer Empty */
/* NFC_IRQSTAT Masks */
#define NBUSYIRQ 0x01 /* Not Busy IRQ */
#define WB_OVF 0x02 /* Write Buffer Overflow */
#define WB_EDGE 0x04 /* Write Buffer Edge Detect */
#define RD_RDY 0x08 /* Read Data Ready */
#define WR_DONE 0x10 /* Page Write Done */
/* NFC_RST Masks */
#define ECC_RST 0x01 /* ECC (and NFC counters) Reset */
/* NFC_PGCTL Masks */
#define PG_RD_START 0x01 /* Page Read Start */
#define PG_WR_START 0x02 /* Page Write Start */
#ifdef CONFIG_MTD_NAND_BF5XX_HWECC
static int hardware_ecc = 1;
#else
static int hardware_ecc;
#endif
static const unsigned short bfin_nfc_pin_req[] =
{P_NAND_CE,
P_NAND_RB,
P_NAND_D0,
P_NAND_D1,
P_NAND_D2,
P_NAND_D3,
P_NAND_D4,
P_NAND_D5,
P_NAND_D6,
P_NAND_D7,
P_NAND_WE,
P_NAND_RE,
P_NAND_CLE,
P_NAND_ALE,
0};
#ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC
static int bootrom_ooblayout_ecc(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
if (section > 7)
return -ERANGE;
oobregion->offset = section * 8;
oobregion->length = 3;
return 0;
}
static int bootrom_ooblayout_free(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
if (section > 7)
return -ERANGE;
oobregion->offset = (section * 8) + 3;
oobregion->length = 5;
return 0;
}
static const struct mtd_ooblayout_ops bootrom_ooblayout_ops = {
.ecc = bootrom_ooblayout_ecc,
.free = bootrom_ooblayout_free,
};
#endif
/*
* Data structures for bf5xx nand flash controller driver
*/
/* bf5xx nand info */
struct bf5xx_nand_info {
/* mtd info */
struct nand_hw_control controller;
struct nand_chip chip;
/* platform info */
struct bf5xx_nand_platform *platform;
/* device info */
struct device *device;
/* DMA stuff */
struct completion dma_completion;
};
/*
* Conversion functions
*/
static struct bf5xx_nand_info *mtd_to_nand_info(struct mtd_info *mtd)
{
return container_of(mtd_to_nand(mtd), struct bf5xx_nand_info,
chip);
}
static struct bf5xx_nand_info *to_nand_info(struct platform_device *pdev)
{
return platform_get_drvdata(pdev);
}
static struct bf5xx_nand_platform *to_nand_plat(struct platform_device *pdev)
{
return dev_get_platdata(&pdev->dev);
}
/*
* struct nand_chip interface function pointers
*/
/*
* bf5xx_nand_hwcontrol
*
* Issue command and address cycles to the chip
*/
static void bf5xx_nand_hwcontrol(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
{
if (cmd == NAND_CMD_NONE)
return;
while (bfin_read_NFC_STAT() & WB_FULL)
cpu_relax();
if (ctrl & NAND_CLE)
bfin_write_NFC_CMD(cmd);
else if (ctrl & NAND_ALE)
bfin_write_NFC_ADDR(cmd);
SSYNC();
}
/*
* bf5xx_nand_devready()
*
* returns 0 if the nand is busy, 1 if it is ready
*/
static int bf5xx_nand_devready(struct mtd_info *mtd)
{
unsigned short val = bfin_read_NFC_STAT();
if ((val & NBUSY) == NBUSY)
return 1;
else
return 0;
}
/*
* ECC functions
* These allow the bf5xx to use the controller's ECC
* generator block to ECC the data as it passes through
*/
/*
* ECC error correction function
*/
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);
u32 syndrome[5];
u32 calced, stored;
int i;
unsigned short failing_bit, failing_byte;
u_char data;
calced = calc_ecc[0] | (calc_ecc[1] << 8) | (calc_ecc[2] << 16);
stored = read_ecc[0] | (read_ecc[1] << 8) | (read_ecc[2] << 16);
syndrome[0] = (calced ^ stored);
/*
* syndrome 0: all zero
* No error in data
* No action
*/
if (!syndrome[0] || !calced || !stored)
return 0;
/*
* sysdrome 0: only one bit is one
* ECC data was incorrect
* No action
*/
if (hweight32(syndrome[0]) == 1) {
dev_err(info->device, "ECC data was incorrect!\n");
return -EBADMSG;
}
syndrome[1] = (calced & 0x7FF) ^ (stored & 0x7FF);
syndrome[2] = (calced & 0x7FF) ^ ((calced >> 11) & 0x7FF);
syndrome[3] = (stored & 0x7FF) ^ ((stored >> 11) & 0x7FF);
syndrome[4] = syndrome[2] ^ syndrome[3];
for (i = 0; i < 5; i++)
dev_info(info->device, "syndrome[%d] 0x%08x\n", i, syndrome[i]);
dev_info(info->device,
"calced[0x%08x], stored[0x%08x]\n",
calced, stored);
/*
* sysdrome 0: exactly 11 bits are one, each parity
* and parity' pair is 1 & 0 or 0 & 1.
* 1-bit correctable error
* Correct the error
*/
if (hweight32(syndrome[0]) == 11 && syndrome[4] == 0x7FF) {
dev_info(info->device,
"1-bit correctable error, correct it.\n");
dev_info(info->device,
"syndrome[1] 0x%08x\n", syndrome[1]);
failing_bit = syndrome[1] & 0x7;
failing_byte = syndrome[1] >> 0x3;
data = *(dat + failing_byte);
data = data ^ (0x1 << failing_bit);
*(dat + failing_byte) = data;
return 1;
}
/*
* sysdrome 0: random data
* More than 1-bit error, non-correctable error
* Discard data, mark bad block
*/
dev_err(info->device,
"More than 1-bit error, non-correctable error.\n");
dev_err(info->device,
"Please discard data, mark bad block\n");
return -EBADMSG;
}
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);
int ret, bitflips = 0;
ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
if (ret < 0)
return ret;
bitflips = ret;
/* If ecc size is 512, correct second 256 bytes */
if (chip->ecc.size == 512) {
dat += 256;
read_ecc += 3;
calc_ecc += 3;
ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
if (ret < 0)
return ret;
bitflips += ret;
}
return bitflips;
}
static void bf5xx_nand_enable_hwecc(struct mtd_info *mtd, int mode)
{
return;
}
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);
u16 ecc0, ecc1;
u32 code[2];
u8 *p;
/* first 3 bytes ECC code for 256 page size */
ecc0 = bfin_read_NFC_ECC0();
ecc1 = bfin_read_NFC_ECC1();
code[0] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11);
dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]);
p = (u8 *) code;
memcpy(ecc_code, p, 3);
/* second 3 bytes ECC code for 512 ecc size */
if (chip->ecc.size == 512) {
ecc0 = bfin_read_NFC_ECC2();
ecc1 = bfin_read_NFC_ECC3();
code[1] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11);
/* second 3 bytes in ecc_code for second 256
* bytes of 512 page size
*/
p = (u8 *) (code + 1);
memcpy((ecc_code + 3), p, 3);
dev_dbg(info->device, "returning ecc 0x%08x\n", code[1]);
}
return 0;
}
/*
* PIO mode for buffer writing and reading
*/
static void bf5xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
{
int i;
unsigned short val;
/*
* Data reads are requested by first writing to NFC_DATA_RD
* and then reading back from NFC_READ.
*/
for (i = 0; i < len; i++) {
while (bfin_read_NFC_STAT() & WB_FULL)
cpu_relax();
/* Contents do not matter */
bfin_write_NFC_DATA_RD(0x0000);
SSYNC();
while ((bfin_read_NFC_IRQSTAT() & RD_RDY) != RD_RDY)
cpu_relax();
buf[i] = bfin_read_NFC_READ();
val = bfin_read_NFC_IRQSTAT();
val |= RD_RDY;
bfin_write_NFC_IRQSTAT(val);
SSYNC();
}
}
static uint8_t bf5xx_nand_read_byte(struct mtd_info *mtd)
{
uint8_t val;
bf5xx_nand_read_buf(mtd, &val, 1);
return val;
}
static void bf5xx_nand_write_buf(struct mtd_info *mtd,
const uint8_t *buf, int len)
{
int i;
for (i = 0; i < len; i++) {
while (bfin_read_NFC_STAT() & WB_FULL)
cpu_relax();
bfin_write_NFC_DATA_WR(buf[i]);
SSYNC();
}
}
static void bf5xx_nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
{
int i;
u16 *p = (u16 *) buf;
len >>= 1;
/*
* Data reads are requested by first writing to NFC_DATA_RD
* and then reading back from NFC_READ.
*/
bfin_write_NFC_DATA_RD(0x5555);
SSYNC();
for (i = 0; i < len; i++)
p[i] = bfin_read_NFC_READ();
}
static void bf5xx_nand_write_buf16(struct mtd_info *mtd,
const uint8_t *buf, int len)
{
int i;
u16 *p = (u16 *) buf;
len >>= 1;
for (i = 0; i < len; i++)
bfin_write_NFC_DATA_WR(p[i]);
SSYNC();
}
/*
* DMA functions for buffer writing and reading
*/
static irqreturn_t bf5xx_nand_dma_irq(int irq, void *dev_id)
{
struct bf5xx_nand_info *info = dev_id;
clear_dma_irqstat(CH_NFC);
disable_dma(CH_NFC);
complete(&info->dma_completion);
return IRQ_HANDLED;
}
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);
unsigned short val;
dev_dbg(info->device, " mtd->%p, buf->%p, is_read %d\n",
mtd, buf, is_read);
/*
* Before starting a dma transfer, be sure to invalidate/flush
* the cache over the address range of your DMA buffer to
* prevent cache coherency problems. Otherwise very subtle bugs
* can be introduced to your driver.
*/
if (is_read)
invalidate_dcache_range((unsigned int)buf,
(unsigned int)(buf + chip->ecc.size));
else
flush_dcache_range((unsigned int)buf,
(unsigned int)(buf + chip->ecc.size));
/*
* This register must be written before each page is
* transferred to generate the correct ECC register
* values.
*/
bfin_write_NFC_RST(ECC_RST);
SSYNC();
while (bfin_read_NFC_RST() & ECC_RST)
cpu_relax();
disable_dma(CH_NFC);
clear_dma_irqstat(CH_NFC);
/* setup DMA register with Blackfin DMA API */
set_dma_config(CH_NFC, 0x0);
set_dma_start_addr(CH_NFC, (unsigned long) buf);
/* The DMAs have different size on BF52x and BF54x */
#ifdef CONFIG_BF52x
set_dma_x_count(CH_NFC, (chip->ecc.size >> 1));
set_dma_x_modify(CH_NFC, 2);
val = DI_EN | WDSIZE_16;
#endif
#ifdef CONFIG_BF54x
set_dma_x_count(CH_NFC, (chip->ecc.size >> 2));
set_dma_x_modify(CH_NFC, 4);
val = DI_EN | WDSIZE_32;
#endif
/* setup write or read operation */
if (is_read)
val |= WNR;
set_dma_config(CH_NFC, val);
enable_dma(CH_NFC);
/* Start PAGE read/write operation */
if (is_read)
bfin_write_NFC_PGCTL(PG_RD_START);
else
bfin_write_NFC_PGCTL(PG_WR_START);
wait_for_completion(&info->dma_completion);
}
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);
dev_dbg(info->device, "mtd->%p, buf->%p, int %d\n", mtd, buf, len);
if (len == chip->ecc.size)
bf5xx_nand_dma_rw(mtd, buf, 1);
else
bf5xx_nand_read_buf(mtd, buf, len);
}
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);
dev_dbg(info->device, "mtd->%p, buf->%p, len %d\n", mtd, buf, len);
if (len == chip->ecc.size)
bf5xx_nand_dma_rw(mtd, (uint8_t *)buf, 0);
else
bf5xx_nand_write_buf(mtd, buf, len);
}
static int bf5xx_nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
{
nand_read_page_op(chip, page, 0, NULL, 0);
bf5xx_nand_read_buf(mtd, buf, mtd->writesize);
bf5xx_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize);
return 0;
}
static int bf5xx_nand_write_page_raw(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf, int oob_required,
int page)
{
nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
return nand_prog_page_end_op(chip);
}
/*
* System initialization functions
*/
static int bf5xx_nand_dma_init(struct bf5xx_nand_info *info)
{
int ret;
/* Do not use dma */
if (!hardware_ecc)
return 0;
init_completion(&info->dma_completion);
/* Request NFC DMA channel */
ret = request_dma(CH_NFC, "BF5XX NFC driver");
if (ret < 0) {
dev_err(info->device, " unable to get DMA channel\n");
return ret;
}
#ifdef CONFIG_BF54x
/* Setup DMAC1 channel mux for NFC which shared with SDH */
bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() & ~1);
SSYNC();
#endif
set_dma_callback(CH_NFC, bf5xx_nand_dma_irq, info);
/* Turn off the DMA channel first */
disable_dma(CH_NFC);
return 0;
}
static void bf5xx_nand_dma_remove(struct bf5xx_nand_info *info)
{
/* Free NFC DMA channel */
if (hardware_ecc)
free_dma(CH_NFC);
}
/*
* BF5XX NFC hardware initialization
* - pin mux setup
* - clear interrupt status
*/
static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info)
{
int err = 0;
unsigned short val;
struct bf5xx_nand_platform *plat = info->platform;
/* setup NFC_CTL register */
dev_info(info->device,
"data_width=%d, wr_dly=%d, rd_dly=%d\n",
(plat->data_width ? 16 : 8),
plat->wr_dly, plat->rd_dly);
val = (1 << NFC_PG_SIZE_OFFSET) |
(plat->data_width << NFC_NWIDTH_OFFSET) |
(plat->rd_dly << NFC_RDDLY_OFFSET) |
(plat->wr_dly << NFC_WRDLY_OFFSET);
dev_dbg(info->device, "NFC_CTL is 0x%04x\n", val);
bfin_write_NFC_CTL(val);
SSYNC();
/* clear interrupt status */
bfin_write_NFC_IRQMASK(0x0);
SSYNC();
val = bfin_read_NFC_IRQSTAT();
bfin_write_NFC_IRQSTAT(val);
SSYNC();
/* DMA initialization */
if (bf5xx_nand_dma_init(info))
err = -ENXIO;
return err;
}
/*
* Device management interface
*/
static int bf5xx_nand_add_partition(struct bf5xx_nand_info *info)
{
struct mtd_info *mtd = nand_to_mtd(&info->chip);
struct mtd_partition *parts = info->platform->partitions;
int nr = info->platform->nr_partitions;
return mtd_device_register(mtd, parts, nr);
}
static int bf5xx_nand_remove(struct platform_device *pdev)
{
struct bf5xx_nand_info *info = to_nand_info(pdev);
/* first thing we need to do is release all our mtds
* and their partitions, then go through freeing the
* resources used
*/
nand_release(nand_to_mtd(&info->chip));
peripheral_free_list(bfin_nfc_pin_req);
bf5xx_nand_dma_remove(info);
return 0;
}
static int bf5xx_nand_scan(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd_to_nand(mtd);
int ret;
ret = nand_scan_ident(mtd, 1, NULL);
if (ret)
return ret;
if (hardware_ecc) {
/*
* for nand with page size > 512B, think it as several sections with 512B
*/
if (likely(mtd->writesize >= 512)) {
chip->ecc.size = 512;
chip->ecc.bytes = 6;
chip->ecc.strength = 2;
} else {
chip->ecc.size = 256;
chip->ecc.bytes = 3;
chip->ecc.strength = 1;
bfin_write_NFC_CTL(bfin_read_NFC_CTL() & ~(1 << NFC_PG_SIZE_OFFSET));
SSYNC();
}
}
return nand_scan_tail(mtd);
}
/*
* bf5xx_nand_probe
*
* called by device layer when it finds a device matching
* one our driver can handled. This code checks to see if
* it can allocate all necessary resources then calls the
* nand layer to look for devices
*/
static int bf5xx_nand_probe(struct platform_device *pdev)
{
struct bf5xx_nand_platform *plat = to_nand_plat(pdev);
struct bf5xx_nand_info *info = NULL;
struct nand_chip *chip = NULL;
struct mtd_info *mtd = NULL;
int err = 0;
dev_dbg(&pdev->dev, "(%p)\n", pdev);
if (!plat) {
dev_err(&pdev->dev, "no platform specific information\n");
return -EINVAL;
}
if (peripheral_request_list(bfin_nfc_pin_req, DRV_NAME)) {
dev_err(&pdev->dev, "requesting Peripherals failed\n");
return -EFAULT;
}
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (info == NULL) {
err = -ENOMEM;
goto out_err;
}
platform_set_drvdata(pdev, info);
nand_hw_control_init(&info->controller);
info->device = &pdev->dev;
info->platform = plat;
/* initialise chip data struct */
chip = &info->chip;
mtd = nand_to_mtd(&info->chip);
if (plat->data_width)
chip->options |= NAND_BUSWIDTH_16;
chip->options |= NAND_CACHEPRG | NAND_SKIP_BBTSCAN;
chip->read_buf = (plat->data_width) ?
bf5xx_nand_read_buf16 : bf5xx_nand_read_buf;
chip->write_buf = (plat->data_width) ?
bf5xx_nand_write_buf16 : bf5xx_nand_write_buf;
chip->read_byte = bf5xx_nand_read_byte;
chip->cmd_ctrl = bf5xx_nand_hwcontrol;
chip->dev_ready = bf5xx_nand_devready;
nand_set_controller_data(chip, mtd);
chip->controller = &info->controller;
chip->IO_ADDR_R = (void __iomem *) NFC_READ;
chip->IO_ADDR_W = (void __iomem *) NFC_DATA_WR;
chip->chip_delay = 0;
/* initialise mtd info data struct */
mtd->dev.parent = &pdev->dev;
/* initialise the hardware */
err = bf5xx_nand_hw_init(info);
if (err)
goto out_err;
/* setup hardware ECC data struct */
if (hardware_ecc) {
#ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC
mtd_set_ooblayout(mtd, &bootrom_ooblayout_ops);
#endif
chip->read_buf = bf5xx_nand_dma_read_buf;
chip->write_buf = bf5xx_nand_dma_write_buf;
chip->ecc.calculate = bf5xx_nand_calculate_ecc;
chip->ecc.correct = bf5xx_nand_correct_data;
chip->ecc.mode = NAND_ECC_HW;
chip->ecc.hwctl = bf5xx_nand_enable_hwecc;
chip->ecc.read_page_raw = bf5xx_nand_read_page_raw;
chip->ecc.write_page_raw = bf5xx_nand_write_page_raw;
} else {
chip->ecc.mode = NAND_ECC_SOFT;
chip->ecc.algo = NAND_ECC_HAMMING;
}
/* scan hardware nand chip and setup mtd info data struct */
if (bf5xx_nand_scan(mtd)) {
err = -ENXIO;
goto out_err_nand_scan;
}
#ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC
chip->badblockpos = 63;
#endif
/* add NAND partition */
bf5xx_nand_add_partition(info);
dev_dbg(&pdev->dev, "initialised ok\n");
return 0;
out_err_nand_scan:
bf5xx_nand_dma_remove(info);
out_err:
peripheral_free_list(bfin_nfc_pin_req);
return err;
}
/* driver device registration */
static struct platform_driver bf5xx_nand_driver = {
.probe = bf5xx_nand_probe,
.remove = bf5xx_nand_remove,
.driver = {
.name = DRV_NAME,
},
};
module_platform_driver(bf5xx_nand_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR(DRV_AUTHOR);
MODULE_DESCRIPTION(DRV_DESC);
MODULE_ALIAS("platform:" DRV_NAME);

View file

@ -0,0 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
# link order matters; don't link the more generic brcmstb_nand.o before the
# more specific iproc_nand.o, for instance
obj-$(CONFIG_MTD_NAND_BRCMNAND) += iproc_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63138_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm6368_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmstb_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o

Some files were not shown because too many files have changed in this diff Show more