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:
parent
7b6afee729
commit
93db446a42
98 changed files with 669 additions and 665 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
22
MAINTAINERS
22
MAINTAINERS
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
|
|||
580
drivers/mtd/nand/raw/Kconfig
Normal file
580
drivers/mtd/nand/raw/Kconfig
Normal 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
|
||||
68
drivers/mtd/nand/raw/Makefile
Normal file
68
drivers/mtd/nand/raw/Makefile
Normal 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
|
||||
291
drivers/mtd/nand/raw/ams-delta.c
Normal file
291
drivers/mtd/nand/raw/ams-delta.c
Normal 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)");
|
||||
4
drivers/mtd/nand/raw/atmel/Makefile
Normal file
4
drivers/mtd/nand/raw/atmel/Makefile
Normal 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
|
||||
2565
drivers/mtd/nand/raw/atmel/nand-controller.c
Normal file
2565
drivers/mtd/nand/raw/atmel/nand-controller.c
Normal file
File diff suppressed because it is too large
Load diff
1012
drivers/mtd/nand/raw/atmel/pmecc.c
Normal file
1012
drivers/mtd/nand/raw/atmel/pmecc.c
Normal file
File diff suppressed because it is too large
Load diff
74
drivers/mtd/nand/raw/atmel/pmecc.h
Normal file
74
drivers/mtd/nand/raw/atmel/pmecc.h
Normal 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 */
|
||||
515
drivers/mtd/nand/raw/au1550nd.c
Normal file
515
drivers/mtd/nand/raw/au1550nd.c
Normal 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");
|
||||
4
drivers/mtd/nand/raw/bcm47xxnflash/Makefile
Normal file
4
drivers/mtd/nand/raw/bcm47xxnflash/Makefile
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
bcm47xxnflash-y += main.o
|
||||
bcm47xxnflash-y += ops_bcm4706.o
|
||||
|
||||
obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash.o
|
||||
26
drivers/mtd/nand/raw/bcm47xxnflash/bcm47xxnflash.h
Normal file
26
drivers/mtd/nand/raw/bcm47xxnflash/bcm47xxnflash.h
Normal 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 */
|
||||
81
drivers/mtd/nand/raw/bcm47xxnflash/main.c
Normal file
81
drivers/mtd/nand/raw/bcm47xxnflash/main.c
Normal 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);
|
||||
456
drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c
Normal file
456
drivers/mtd/nand/raw/bcm47xxnflash/ops_bcm4706.c
Normal 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;
|
||||
}
|
||||
861
drivers/mtd/nand/raw/bf5xx_nand.c
Normal file
861
drivers/mtd/nand/raw/bf5xx_nand.c
Normal 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);
|
||||
8
drivers/mtd/nand/raw/brcmnand/Makefile
Normal file
8
drivers/mtd/nand/raw/brcmnand/Makefile
Normal 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
Loading…
Reference in a new issue