// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright © 2004-2008 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*
* Samsung S3C2410/S3C2440/S3C2412 NAND driver
*/
#define pr_fmt(fmt) "nand-s3c2410: " fmt
#ifdef CONFIG_MTD_NAND_S3C2410_DEBUG
#define DEBUG
#endif
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/cpufreq.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
#include <linux/platform_data/mtd-nand-s3c2410.h>
#define S3C2410_NFREG(x) (x)
#define S3C2410_NFCONF S3C2410_NFREG(0x00)
#define S3C2410_NFCMD S3C2410_NFREG(0x04)
#define S3C2410_NFADDR S3C2410_NFREG(0x08)
#define S3C2410_NFDATA S3C2410_NFREG(0x0C)
#define S3C2410_NFSTAT S3C2410_NFREG(0x10)
#define S3C2410_NFECC S3C2410_NFREG(0x14)
#define S3C2440_NFCONT S3C2410_NFREG(0x04)
#define S3C2440_NFCMD S3C2410_NFREG(0x08)
#define S3C2440_NFADDR S3C2410_NFREG(0x0C)
#define S3C2440_NFDATA S3C2410_NFREG(0x10)
#define S3C2440_NFSTAT S3C2410_NFREG(0x20)
#define S3C2440_NFMECC0 S3C2410_NFREG(0x2C)
#define S3C2412_NFSTAT S3C2410_NFREG(0x28)
#define S3C2412_NFMECC0 S3C2410_NFREG(0x34)
#define S3C2410_NFCONF_EN (1<<15)
#define S3C2410_NFCONF_INITECC (1<<12)
#define S3C2410_NFCONF_nFCE (1<<11)
#define S3C2410_NFCONF_TACLS(x) ((x)<<8)
#define S3C2410_NFCONF_TWRPH0(x) ((x)<<4)
#define S3C2410_NFCONF_TWRPH1(x) ((x)<<0)
#define S3C2410_NFSTAT_BUSY (1<<0)
#define S3C2440_NFCONF_TACLS(x) ((x)<<12)
#define S3C2440_NFCONF_TWRPH0(x) ((x)<<8)
#define S3C2440_NFCONF_TWRPH1(x) ((x)<<4)
#define S3C2440_NFCONT_INITECC (1<<4)
#define S3C2440_NFCONT_nFCE (1<<1)
#define S3C2440_NFCONT_ENABLE (1<<0)
#define S3C2440_NFSTAT_READY (1<<0)
#define S3C2412_NFCONF_NANDBOOT (1<<31)
#define S3C2412_NFCONT_INIT_MAIN_ECC (1<<5)
#define S3C2412_NFCONT_nFCE0 (1<<1)
#define S3C2412_NFSTAT_READY (1<<0)
/* new oob placement block for use with hardware ecc generation
*/
static int s3c2410_ooblayout_ecc(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
if (section)
return -ERANGE;
oobregion->offset = 0;
oobregion->length = 3;
return 0;
}
static int s3c2410_ooblayout_free(struct mtd_info *mtd, int section,
struct mtd_oob_region *oobregion)
{
if (section)
return -ERANGE;
oobregion->offset = 8;
oobregion->length = 8;
return 0;
}
static const struct mtd_ooblayout_ops s3c2410_ooblayout_ops = {
.ecc = s3c2410_ooblayout_ecc,
.free = s3c2410_ooblayout_free,
};
/* controller and mtd information */
struct s3c2410_nand_info;
/**
* struct s3c2410_nand_mtd - driver MTD structure
* @mtd: The MTD instance to pass to the MTD layer.
* @chip: The NAND chip information.
* @set: The platform information supplied for this set of NAND chips.
* @info: Link back to the hardware information.
*/
struct s3c2410_nand_mtd {
struct nand_chip chip;
struct s3c2410_nand_set *set;
struct s3c2410_nand_info *info;
};
enum s3c_cpu_type {
TYPE_S3C2410,
TYPE_S3C2412,
TYPE_S3C2440,
};
enum s3c_nand_clk_state {
CLOCK_DISABLE = 0,
CLOCK_ENABLE,
CLOCK_SUSPEND,
};
/* overview of the s3c2410 nand state */
/**
* struct s3c2410_nand_info - NAND controller state.
* @mtds: An array of MTD instances on this controoler.
* @platform: The platform data for this board.
* @device: The platform device we bound to.
* @clk: The clock resource for this controll