/*
 *  drivers/mtd/nand/nomadik_nand.c
 *
 *  Overview:
 *  	Driver for on-board NAND flash on Nomadik Platforms
 *
 * Copyright © 2007 STMicroelectronics Pvt. Ltd.
 * Author: Sachin Verma <sachin.verma@st.com>
 *
 * Copyright © 2009 Alessandro Rubini
 *
 * 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.
 *
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/platform_device.h>
#include <linux/mtd/partitions.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <mach/nand.h>
#include <mach/fsmc.h>

#include <mtd/mtd-abi.h>

struct nomadik_nand_host {
	struct mtd_info		mtd;
	struct nand_chip	nand;
	void __iomem *data_va;
	void __iomem *cmd_va;
	void __iomem *addr_va;
	struct nand_bbt_descr *bbt_desc;
};

static struct nand_ecclayout nomadik_ecc_layout = {
	.eccbytes = 3 * 4,
	.eccpos = { /* each subpage has 16 bytes: pos 2,3,4 hosts ECC */
		0x02, 0x03, 0x04,
		0x12, 0x13, 0x14,
		0x22, 0x23, 0x24,
		0x32, 0x33, 0x34},
	/* let's keep bytes 5,6,7 for us, just in case we change ECC algo */
	.oobfree = { {0x08, 0x08}, {0x18, 0x08}, {0x28, 0x08}, {0x38, 0x08} },
};

static void nomadik_ecc_control(struct mtd_info *mtd, int mode)
{
	/* No need to enable hw ecc, it's on by default */
}

static void nomadik_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
	struct nand_chip *nand = mtd->priv;
	struct nomadik_nand_host *host = nand->priv;

	if (cmd == NAND_CMD_NONE)
		return;

	if (ctrl & NAND_CLE)
		writeb(cmd, host->cmd_va);
	else
		writeb(cmd, host->addr_va);
}

static int nomadik_nand_probe(struct platform_device *pdev)
{
	struct nomadik_nand_platform_data *pdata = pdev->dev.platform_data;
	struct nomadik_nand_host *host;
	struct mtd_info *mtd;
	struct nand_chip *nand;
	struct resource *res;
	int ret = 0;

	/* Allocate memory for the device structure (and zero it) */
	host = kzalloc(sizeof(struct nomadik_nand_host), GFP_KERNEL);
	if (!host) {
		dev_err(&pdev->dev, "Failed to allocate device structure.\n");
		return -ENOMEM;
	}

	/* Call the client's init function, if any */
	if (pdata->init)
		ret = pdata->init();
	if (ret < 0) {
		dev_err(&pdev->dev, "Init function failed\n");
		goto err;
	}

	/* ioremap three regions */
	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_addr");
	if (!res) {
		ret = -EIO;
		goto err_unmap;
	}
	host->addr_va = ioremap(res->start, resource_size(res));

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_data");
	if (!res) {
		ret = -EIO;
		goto err_unmap;
	}
	host->data_va = ioremap(res->start, resource_size(res));

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_cmd");
	if (!res) {
		ret = -EIO;
		goto err_unmap;
	}
	host->cmd_va = ioremap(res->start, resource_size(res));

	if (!host->addr_va || !host->data_va || !host->cmd_va) {
		ret = -ENOMEM;
		goto err_unmap;
	}

	/* Link all private pointers */
	mtd = &host->mtd;
	nand = &host->nand;
	mtd->priv = nand;
	nand->priv = host;

	host->mtd.owner = THIS_MODULE;
	nand->IO_ADDR_R = host->data_va;
	nand->IO_ADDR_W = host->data_va;
	nand->cmd_ctrl = nomadik_cmd_ctrl;

	/*
	 * This stanza declares ECC_HW but uses soft routines. It's because
	 * HW claims to make the calculation but not the correction. However,
	 * I haven't managed to get the desired data out of it until now.
	 */
	nand->ecc.mode = NAND_ECC_SOFT;
	nand->ecc.layout = &nomadik_ecc_layout;
	nand->ecc.hwctl = nomadik_ecc_control;
	nand->ecc.size = 512;
	nand->ecc.bytes = 3;

	nand->options = pdata->options;

	/*
	 * Scan to find existance of the device
	 */
	if (nand_scan(&host->mtd, 1)) {
		ret = -ENXIO;
		goto err_unmap;
	}

#ifdef CONFIG_MTD_PARTITIONS
	add_mtd_partitions(&host->mtd, pdata->parts, pdata->nparts);
#else
	pr_info("Registering %s as whole device\n", mtd->name);
	add_mtd_device(mtd);
#endif

	platform_set_drvdata(pdev, host);
	return 0;

 err_unmap:
	if (host->cmd_va)
		iounmap(host->cmd_va);
	if (host->data_va)
		iounmap(host->data_va);
	if (host->addr_va)
		iounmap(host->addr_va);
 err:
	kfree(host);
	return ret;
}

/*
 * Clean up routine
 */
static int nomadik_nand_remove(struct platform_device *pdev)
{
	struct nomadik_nand_host *host = platform_get_drvdata(pdev);
	struct nomadik_nand_platform_data *pdata = pdev->dev.platform_data;

	if (pdata->exit)
		pdata->exit();

	if (host) {
		iounmap(host->cmd_va);
		iounmap(host->data_va);
		iounmap(host->addr_va);
		kfree(host);
	}
	return 0;
}

static int nomadik_nand_suspend(struct device *dev)
{
	struct nomadik_nand_host *host = dev_get_drvdata(dev);
	int ret = 0;
	if (host)
		ret = host->mtd.suspend(&host->mtd);
	return ret;
}

static int nomadik_nand_resume(struct device *dev)
{
	struct nomadik_nand_host *host = dev_get_drvdata(dev);
	if (host)
		host->mtd.resume(&host->mtd);
	return 0;
}

static const struct dev_pm_ops nomadik_nand_pm_ops = {
	.suspend = nomadik_nand_suspend,
	.resume = nomadik_nand_resume,
};

static struct platform_driver nomadik_nand_driver = {
	.probe = nomadik_nand_probe,
	.remove = nomadik_nand_remove,
	.driver = {
		.owner = THIS_MODULE,
		.name = "nomadik_nand",
		.pm = &nomadik_nand_pm_ops,
	},
};

static int __init nand_nomadik_init(void)
{
	pr_info("Nomadik NAND driver\n");
	return platform_driver_register(&nomadik_nand_driver);
}

static void __exit nand_nomadik_exit(void)
{
	platform_driver_unregister(&nomadik_nand_driver);
}

module_init(nand_nomadik_init);
module_exit(nand_nomadik_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("ST Microelectronics (sachin.verma@st.com)");
MODULE_DESCRIPTION("NAND driver for Nomadik Platform");
