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

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Peter Pan <peterpandong@micron.com>
Acked-by: Vladimir Zapolskiy <vz@mleia.com>
Acked-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
Acked-by: Wenyou Yang <wenyou.yang@microchip.com>
Acked-by: Krzysztof Kozlowski <krzk@kernel.org>
Acked-by: Han Xu <han.xu@nxp.com>
Acked-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Acked-by: Shawn Guo <shawnguo@kernel.org>
Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Acked-by: Neil Armstrong <narmstrong@baylibre.com>
Acked-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Acked-By: Harvey Hunt <harveyhuntnexus@gmail.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Acked-by: Krzysztof Halasa <khalasa@piap.pl>
2017-08-13 10:11:49 +02:00

178 lines
4.1 KiB
C

/*
* arch/cris/arch-v32/drivers/nandflash.c
*
* Copyright (c) 2007
*
* Derived from drivers/mtd/nand/spia.c
* Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.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 <linux/slab.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/partitions.h>
#include <arch/memmap.h>
#include <hwregs/reg_map.h>
#include <hwregs/reg_rdwr.h>
#include <hwregs/pio_defs.h>
#include <pinmux.h>
#include <asm/io.h>
#define MANUAL_ALE_CLE_CONTROL 1
#define regf_ALE a0
#define regf_CLE a1
#define regf_NCE ce0_n
#define CLE_BIT 10
#define ALE_BIT 11
#define CE_BIT 12
struct mtd_info_wrapper {
struct nand_chip chip;
};
/* Bitmask for control pins */
#define PIN_BITMASK ((1 << CE_BIT) | (1 << CLE_BIT) | (1 << ALE_BIT))
static struct mtd_info *crisv32_mtd;
/*
* hardware specific access to control-lines
*/
static void crisv32_hwcontrol(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
{
unsigned long flags;
reg_pio_rw_dout dout;
struct nand_chip *this = mtd_to_nand(mtd);
local_irq_save(flags);
/* control bits change */
if (ctrl & NAND_CTRL_CHANGE) {
dout = REG_RD(pio, regi_pio, rw_dout);
dout.regf_NCE = (ctrl & NAND_NCE) ? 0 : 1;
#if !MANUAL_ALE_CLE_CONTROL
if (ctrl & NAND_ALE) {
/* A0 = ALE high */
this->IO_ADDR_W = (void __iomem *)REG_ADDR(pio,
regi_pio, rw_io_access1);
} else if (ctrl & NAND_CLE) {
/* A1 = CLE high */
this->IO_ADDR_W = (void __iomem *)REG_ADDR(pio,
regi_pio, rw_io_access2);
} else {
/* A1 = CLE and A0 = ALE low */
this->IO_ADDR_W = (void __iomem *)REG_ADDR(pio,
regi_pio, rw_io_access0);
}
#else
dout.regf_CLE = (ctrl & NAND_CLE) ? 1 : 0;
dout.regf_ALE = (ctrl & NAND_ALE) ? 1 : 0;
#endif
REG_WR(pio, regi_pio, rw_dout, dout);
}
/* command to chip */
if (cmd != NAND_CMD_NONE)
writeb(cmd, this->IO_ADDR_W);
local_irq_restore(flags);
}
/*
* read device ready pin
*/
static int crisv32_device_ready(struct mtd_info *mtd)
{
reg_pio_r_din din = REG_RD(pio, regi_pio, r_din);
return din.rdy;
}
/*
* Main initialization routine
*/
struct mtd_info *__init crisv32_nand_flash_probe(void)
{
void __iomem *read_cs;
void __iomem *write_cs;
struct mtd_info_wrapper *wrapper;
struct nand_chip *this;
int err = 0;
reg_pio_rw_man_ctrl man_ctrl = {
.regf_NCE = regk_pio_yes,
#if MANUAL_ALE_CLE_CONTROL
.regf_ALE = regk_pio_yes,
.regf_CLE = regk_pio_yes
#endif
};
reg_pio_rw_oe oe = {
.regf_NCE = regk_pio_yes,
#if MANUAL_ALE_CLE_CONTROL
.regf_ALE = regk_pio_yes,
.regf_CLE = regk_pio_yes
#endif
};
reg_pio_rw_dout dout = { .regf_NCE = 1 };
/* Allocate pio pins to pio */
crisv32_pinmux_alloc_fixed(pinmux_pio);
/* Set up CE, ALE, CLE (ce0_n, a0, a1) for manual control and output */
REG_WR(pio, regi_pio, rw_man_ctrl, man_ctrl);
REG_WR(pio, regi_pio, rw_dout, dout);
REG_WR(pio, regi_pio, rw_oe, oe);
/* Allocate memory for MTD device structure and private data */
wrapper = kzalloc(sizeof(struct mtd_info_wrapper), GFP_KERNEL);
if (!wrapper) {
printk(KERN_ERR "Unable to allocate CRISv32 NAND MTD "
"device structure.\n");
err = -ENOMEM;
return NULL;
}
read_cs = write_cs = (void __iomem *)REG_ADDR(pio, regi_pio,
rw_io_access0);
/* Get pointer to private data */
this = &wrapper->chip;
crisv32_mtd = nand_to_mtd(this);
/* Set address of NAND IO lines */
this->IO_ADDR_R = read_cs;
this->IO_ADDR_W = write_cs;
this->cmd_ctrl = crisv32_hwcontrol;
this->dev_ready = crisv32_device_ready;
/* 20 us command delay time */
this->chip_delay = 20;
this->ecc.mode = NAND_ECC_SOFT;
this->ecc.algo = NAND_ECC_HAMMING;
/* Enable the following for a flash based bad block table */
/* this->bbt_options = NAND_BBT_USE_FLASH; */
/* Scan to find existence of the device */
if (nand_scan(crisv32_mtd, 1)) {
err = -ENXIO;
goto out_mtd;
}
return crisv32_mtd;
out_mtd:
kfree(wrapper);
return NULL;
}