Commit f88fc122 authored by Boris Brezillon's avatar Boris Brezillon

mtd: nand: Cleanup/rework the atmel_nand driver

This is a complete rewrite of the driver whose main purpose is to
support the new DT representation where the NAND controller node is now
really visible in the DT and appears under the EBI bus. With this new
representation, we can add other devices under the EBI bus without
risking pinmuxing conflicts (the NAND controller is under the EBI
bus logic and as such, share some of its pins with other devices
connected on this bus).

Even though the goal of this rework was not necessarily to add new
features, the new driver has been designed with this in mind. With a
clearer separation between the different blocks and different IP
revisions, adding new functionalities should be easier (we already
have plans to support SMC timing configuration so that we no longer
have to rely on the configuration done by the bootloader/bootstrap).

Also note that we no longer have a custom ->cmdfunc() implementation,
which means we can now benefit from new features added in the core
implementation for free (support for new NAND operations for example).

The last thing that we gain with this rework is support for multi-chips
and multi-dies chips, thanks to the clean NAND controller <-> NAND
devices representation.

During this transition we also dropped support for AVR32 SoCs which
should soon disappear from mainline (removal of the AVR32 arch is
planned for 4.12).

This new driver has been tested on several platforms (at91sam9261,
at91sam9g45, at91sam9x5, sama5d3 and sama5d4) to make sure it did not
introduce regressions, and it's worth mentioning that old bindings are
still supported (which partly explain the positive diffstat).
Signed-off-by: default avatarBoris Brezillon <boris.brezillon@free-electrons.com>
Acked-by: default avatarNicolas Ferre <nicolas.ferre@microchip.com>
parent ef980cf8
...@@ -2244,7 +2244,7 @@ M: Wenyou Yang <wenyou.yang@atmel.com> ...@@ -2244,7 +2244,7 @@ M: Wenyou Yang <wenyou.yang@atmel.com>
M: Josh Wu <rainyfeeling@outlook.com> M: Josh Wu <rainyfeeling@outlook.com>
L: linux-mtd@lists.infradead.org L: linux-mtd@lists.infradead.org
S: Supported S: Supported
F: drivers/mtd/nand/atmel_nand* F: drivers/mtd/nand/atmel/*
ATMEL SDMMC DRIVER ATMEL SDMMC DRIVER
M: Ludovic Desroches <ludovic.desroches@microchip.com> M: Ludovic Desroches <ludovic.desroches@microchip.com>
......
...@@ -306,11 +306,11 @@ config MTD_NAND_CS553X ...@@ -306,11 +306,11 @@ config MTD_NAND_CS553X
If you say "m", the module will be called cs553x_nand. If you say "m", the module will be called cs553x_nand.
config MTD_NAND_ATMEL config MTD_NAND_ATMEL
tristate "Support for NAND Flash / SmartMedia on AT91 and AVR32" tristate "Support for NAND Flash / SmartMedia on AT91"
depends on ARCH_AT91 || AVR32 depends on ARCH_AT91
help help
Enables support for NAND Flash / Smart Media Card interface Enables support for NAND Flash / Smart Media Card interface
on Atmel AT91 and AVR32 processors. on Atmel AT91 processors.
config MTD_NAND_PXA3xx config MTD_NAND_PXA3xx
tristate "NAND support on PXA3xx and Armada 370/XP" tristate "NAND support on PXA3xx and Armada 370/XP"
......
...@@ -24,7 +24,7 @@ obj-$(CONFIG_MTD_NAND_SHARPSL) += sharpsl.o ...@@ -24,7 +24,7 @@ obj-$(CONFIG_MTD_NAND_SHARPSL) += sharpsl.o
obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o
obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o obj-$(CONFIG_MTD_NAND_CS553X) += cs553x_nand.o
obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o
obj-$(CONFIG_MTD_NAND_ATMEL) += atmel_nand.o obj-$(CONFIG_MTD_NAND_ATMEL) += atmel/
obj-$(CONFIG_MTD_NAND_GPIO) += gpio.o obj-$(CONFIG_MTD_NAND_GPIO) += gpio.o
omap2_nand-objs := omap2.o omap2_nand-objs := omap2.o
obj-$(CONFIG_MTD_NAND_OMAP2) += omap2_nand.o obj-$(CONFIG_MTD_NAND_OMAP2) += omap2_nand.o
......
obj-$(CONFIG_MTD_NAND_ATMEL) += atmel-nand-controller.o atmel-pmecc.o
atmel-nand-controller-objs := nand-controller.o
atmel-pmecc-objs := pmecc.o
This diff is collapsed.
This diff is collapsed.
/*
* © 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
* Copyright © 2001 Thomas Gleixner (gleixner@autronix.de)
*
* Derived from drivers/mtd/spia.c
* 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);
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 */
This diff is collapsed.
/*
* Error Corrected Code Controller (ECC) - System peripherals regsters.
* Based on AT91SAM9260 datasheet revision B.
*
* Copyright (C) 2007 Andrew Victor
* Copyright (C) 2007 - 2012 Atmel Corporation.
*
* 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.
*/
#ifndef ATMEL_NAND_ECC_H
#define ATMEL_NAND_ECC_H
#define ATMEL_ECC_CR 0x00 /* Control register */
#define ATMEL_ECC_RST (1 << 0) /* Reset parity */
#define ATMEL_ECC_MR 0x04 /* Mode register */
#define ATMEL_ECC_PAGESIZE (3 << 0) /* Page Size */
#define ATMEL_ECC_PAGESIZE_528 (0)
#define ATMEL_ECC_PAGESIZE_1056 (1)
#define ATMEL_ECC_PAGESIZE_2112 (2)
#define ATMEL_ECC_PAGESIZE_4224 (3)
#define ATMEL_ECC_SR 0x08 /* Status register */
#define ATMEL_ECC_RECERR (1 << 0) /* Recoverable Error */
#define ATMEL_ECC_ECCERR (1 << 1) /* ECC Single Bit Error */
#define ATMEL_ECC_MULERR (1 << 2) /* Multiple Errors */
#define ATMEL_ECC_PR 0x0c /* Parity register */
#define ATMEL_ECC_BITADDR (0xf << 0) /* Bit Error Address */
#define ATMEL_ECC_WORDADDR (0xfff << 4) /* Word Error Address */
#define ATMEL_ECC_NPR 0x10 /* NParity register */
#define ATMEL_ECC_NPARITY (0xffff << 0) /* NParity */
/* PMECC Register Definitions */
#define ATMEL_PMECC_CFG 0x000 /* Configuration Register */
#define PMECC_CFG_BCH_ERR2 (0 << 0)
#define PMECC_CFG_BCH_ERR4 (1 << 0)
#define PMECC_CFG_BCH_ERR8 (2 << 0)
#define PMECC_CFG_BCH_ERR12 (3 << 0)
#define PMECC_CFG_BCH_ERR24 (4 << 0)
#define PMECC_CFG_BCH_ERR32 (5 << 0)
#define PMECC_CFG_SECTOR512 (0 << 4)
#define PMECC_CFG_SECTOR1024 (1 << 4)
#define PMECC_CFG_PAGE_1SECTOR (0 << 8)
#define PMECC_CFG_PAGE_2SECTORS (1 << 8)
#define PMECC_CFG_PAGE_4SECTORS (2 << 8)
#define PMECC_CFG_PAGE_8SECTORS (3 << 8)
#define PMECC_CFG_READ_OP (0 << 12)
#define PMECC_CFG_WRITE_OP (1 << 12)
#define PMECC_CFG_SPARE_ENABLE (1 << 16)
#define PMECC_CFG_SPARE_DISABLE (0 << 16)
#define PMECC_CFG_AUTO_ENABLE (1 << 20)
#define PMECC_CFG_AUTO_DISABLE (0 << 20)
#define ATMEL_PMECC_SAREA 0x004 /* Spare area size */
#define ATMEL_PMECC_SADDR 0x008 /* PMECC starting address */
#define ATMEL_PMECC_EADDR 0x00c /* PMECC ending address */
#define ATMEL_PMECC_CLK 0x010 /* PMECC clock control */
#define PMECC_CLK_133MHZ (2 << 0)
#define ATMEL_PMECC_CTRL 0x014 /* PMECC control register */
#define PMECC_CTRL_RST (1 << 0)
#define PMECC_CTRL_DATA (1 << 1)
#define PMECC_CTRL_USER (1 << 2)
#define PMECC_CTRL_ENABLE (1 << 4)
#define PMECC_CTRL_DISABLE (1 << 5)
#define ATMEL_PMECC_SR 0x018 /* PMECC status register */
#define PMECC_SR_BUSY (1 << 0)
#define PMECC_SR_ENABLE (1 << 4)
#define ATMEL_PMECC_IER 0x01c /* PMECC interrupt enable */
#define PMECC_IER_ENABLE (1 << 0)
#define ATMEL_PMECC_IDR 0x020 /* PMECC interrupt disable */
#define PMECC_IER_DISABLE (1 << 0)
#define ATMEL_PMECC_IMR 0x024 /* PMECC interrupt mask */
#define PMECC_IER_MASK (1 << 0)
#define ATMEL_PMECC_ISR 0x028 /* PMECC interrupt status */
#define ATMEL_PMECC_ECCx 0x040 /* PMECC ECC x */
#define ATMEL_PMECC_REMx 0x240 /* PMECC REM x */
/* PMERRLOC Register Definitions */
#define ATMEL_PMERRLOC_ELCFG 0x000 /* Error location config */
#define PMERRLOC_ELCFG_SECTOR_512 (0 << 0)
#define PMERRLOC_ELCFG_SECTOR_1024 (1 << 0)
#define PMERRLOC_ELCFG_NUM_ERRORS(n) ((n) << 16)
#define ATMEL_PMERRLOC_ELPRIM 0x004 /* Error location primitive */
#define ATMEL_PMERRLOC_ELEN 0x008 /* Error location enable */
#define ATMEL_PMERRLOC_ELDIS 0x00c /* Error location disable */
#define PMERRLOC_DISABLE (1 << 0)
#define ATMEL_PMERRLOC_ELSR 0x010 /* Error location status */
#define PMERRLOC_ELSR_BUSY (1 << 0)
#define ATMEL_PMERRLOC_ELIER 0x014 /* Error location int enable */
#define ATMEL_PMERRLOC_ELIDR 0x018 /* Error location int disable */
#define ATMEL_PMERRLOC_ELIMR 0x01c /* Error location int mask */
#define ATMEL_PMERRLOC_ELISR 0x020 /* Error location int status */
#define PMERRLOC_ERR_NUM_MASK (0x1f << 8)
#define PMERRLOC_CALC_DONE (1 << 0)
#define ATMEL_PMERRLOC_SIGMAx 0x028 /* Error location SIGMA x */
/*
* The ATMEL_PMERRLOC_ELx register location depends from the number of
* bits corrected by the PMECC controller. Do not use it.
*/
/* Register access macros for PMECC */
#define pmecc_readl_relaxed(addr, reg) \
readl_relaxed((addr) + ATMEL_PMECC_##reg)
#define pmecc_writel(addr, reg, value) \
writel((value), (addr) + ATMEL_PMECC_##reg)
#define pmecc_readb_ecc_relaxed(addr, sector, n) \
readb_relaxed((addr) + ATMEL_PMECC_ECCx + ((sector) * 0x40) + (n))
#define pmecc_readl_rem_relaxed(addr, sector, n) \
readl_relaxed((addr) + ATMEL_PMECC_REMx + ((sector) * 0x40) + ((n) * 4))
#define pmerrloc_readl_relaxed(addr, reg) \
readl_relaxed((addr) + ATMEL_PMERRLOC_##reg)
#define pmerrloc_writel(addr, reg, value) \
writel((value), (addr) + ATMEL_PMERRLOC_##reg)
#define pmerrloc_writel_sigma_relaxed(addr, n, value) \
writel_relaxed((value), (addr) + ATMEL_PMERRLOC_SIGMAx + ((n) * 4))
#define pmerrloc_readl_sigma_relaxed(addr, n) \
readl_relaxed((addr) + ATMEL_PMERRLOC_SIGMAx + ((n) * 4))
#define pmerrloc_readl_el_relaxed(addr, n) \
readl_relaxed((addr) + ((n) * 4))
/* Galois field dimension */
#define PMECC_GF_DIMENSION_13 13
#define PMECC_GF_DIMENSION_14 14
/* Primitive Polynomial used by PMECC */
#define PMECC_GF_13_PRIMITIVE_POLY 0x201b
#define PMECC_GF_14_PRIMITIVE_POLY 0x4443
#define PMECC_LOOKUP_TABLE_SIZE_512 0x2000
#define PMECC_LOOKUP_TABLE_SIZE_1024 0x4000
/* Time out value for reading PMECC status register */
#define PMECC_MAX_TIMEOUT_MS 100
/* Reserved bytes in oob area */
#define PMECC_OOB_RESERVED_BYTES 2
#endif
/*
* Atmel Nand Flash Controller (NFC) - System peripherals regsters.
* Based on SAMA5D3 datasheet.
*
* © Copyright 2013 Atmel Corporation.
*
* 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.
*/
#ifndef ATMEL_NAND_NFC_H
#define ATMEL_NAND_NFC_H
/*
* HSMC NFC registers
*/
#define ATMEL_HSMC_NFC_CFG 0x00 /* NFC Configuration Register */
#define NFC_CFG_PAGESIZE (7 << 0)
#define NFC_CFG_PAGESIZE_512 (0 << 0)
#define NFC_CFG_PAGESIZE_1024 (1 << 0)
#define NFC_CFG_PAGESIZE_2048 (2 << 0)
#define NFC_CFG_PAGESIZE_4096 (3 << 0)
#define NFC_CFG_PAGESIZE_8192 (4 << 0)
#define NFC_CFG_WSPARE (1 << 8)
#define NFC_CFG_RSPARE (1 << 9)
#define NFC_CFG_NFC_DTOCYC (0xf << 16)
#define NFC_CFG_NFC_DTOMUL (0x7 << 20)
#define NFC_CFG_NFC_SPARESIZE (0x7f << 24)
#define NFC_CFG_NFC_SPARESIZE_BIT_POS 24
#define ATMEL_HSMC_NFC_CTRL 0x04 /* NFC Control Register */
#define NFC_CTRL_ENABLE (1 << 0)
#define NFC_CTRL_DISABLE (1 << 1)
#define ATMEL_HSMC_NFC_SR 0x08 /* NFC Status Register */
#define NFC_SR_BUSY (1 << 8)
#define NFC_SR_XFR_DONE (1 << 16)
#define NFC_SR_CMD_DONE (1 << 17)
#define NFC_SR_DTOE (1 << 20)
#define NFC_SR_UNDEF (1 << 21)
#define NFC_SR_AWB (1 << 22)
#define NFC_SR_ASE (1 << 23)
#define NFC_SR_RB_EDGE (1 << 24)
#define ATMEL_HSMC_NFC_IER 0x0c
#define ATMEL_HSMC_NFC_IDR 0x10
#define ATMEL_HSMC_NFC_IMR 0x14
#define ATMEL_HSMC_NFC_CYCLE0 0x18 /* NFC Address Cycle Zero */
#define ATMEL_HSMC_NFC_ADDR_CYCLE0 (0xff)
#define ATMEL_HSMC_NFC_BANK 0x1c /* NFC Bank Register */
#define ATMEL_HSMC_NFC_BANK0 (0 << 0)
#define ATMEL_HSMC_NFC_BANK1 (1 << 0)
#define nfc_writel(addr, reg, value) \
writel((value), (addr) + ATMEL_HSMC_NFC_##reg)
#define nfc_readl(addr, reg) \
readl_relaxed((addr) + ATMEL_HSMC_NFC_##reg)
/*
* NFC Address Command definitions
*/
#define NFCADDR_CMD_CMD1 (0xff << 2) /* Command for Cycle 1 */
#define NFCADDR_CMD_CMD1_BIT_POS 2
#define NFCADDR_CMD_CMD2 (0xff << 10) /* Command for Cycle 2 */
#define NFCADDR_CMD_CMD2_BIT_POS 10
#define NFCADDR_CMD_VCMD2 (0x1 << 18) /* Valid Cycle 2 Command */
#define NFCADDR_CMD_ACYCLE (0x7 << 19) /* Number of Address required */
#define NFCADDR_CMD_ACYCLE_NONE (0x0 << 19)
#define NFCADDR_CMD_ACYCLE_1 (0x1 << 19)
#define NFCADDR_CMD_ACYCLE_2 (0x2 << 19)
#define NFCADDR_CMD_ACYCLE_3 (0x3 << 19)
#define NFCADDR_CMD_ACYCLE_4 (0x4 << 19)
#define NFCADDR_CMD_ACYCLE_5 (0x5 << 19)
#define NFCADDR_CMD_ACYCLE_BIT_POS 19
#define NFCADDR_CMD_CSID (0x7 << 22) /* Chip Select Identifier */
#define NFCADDR_CMD_CSID_0 (0x0 << 22)
#define NFCADDR_CMD_CSID_1 (0x1 << 22)
#define NFCADDR_CMD_CSID_2 (0x2 << 22)
#define NFCADDR_CMD_CSID_3 (0x3 << 22)
#define NFCADDR_CMD_CSID_4 (0x4 << 22)
#define NFCADDR_CMD_CSID_5 (0x5 << 22)
#define NFCADDR_CMD_CSID_6 (0x6 << 22)
#define NFCADDR_CMD_CSID_7 (0x7 << 22)
#define NFCADDR_CMD_DATAEN (0x1 << 25) /* Data Transfer Enable */
#define NFCADDR_CMD_DATADIS (0x0 << 25) /* Data Transfer Disable */
#define NFCADDR_CMD_NFCRD (0x0 << 26) /* NFC Read Enable */
#define NFCADDR_CMD_NFCWR (0x1 << 26) /* NFC Write Enable */
#define NFCADDR_CMD_NFCBUSY (0x1 << 27) /* NFC Busy */
#define nfc_cmd_addr1234_writel(cmd, addr1234, nfc_base) \
writel((addr1234), (cmd) + nfc_base)
#define nfc_cmd_readl(bitstatus, nfc_base) \
readl_relaxed((bitstatus) + nfc_base)
#define NFC_TIME_OUT_MS 100
#define NFC_SRAM_BANK1_OFFSET 0x1200
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment