/*
 * drivers/mtd/nand/sharpsl.c
 *
 *  Copyright (C) 2004 Richard Purdie
 *
 *  $Id: sharpsl.c,v 1.7 2005/11/07 11:14:31 gleixner Exp $
 *
 *  Based on Sharp's NAND driver sharp_sl.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.
 *
 */

#include <linux/genhd.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>

static void __iomem *sharpsl_io_base;
static int sharpsl_phys_base = 0x0C000000;

/* register offset */
#define ECCLPLB	 	sharpsl_io_base+0x00	/* line parity 7 - 0 bit */
#define ECCLPUB	 	sharpsl_io_base+0x04	/* line parity 15 - 8 bit */
#define ECCCP	   	sharpsl_io_base+0x08	/* column parity 5 - 0 bit */
#define ECCCNTR	 	sharpsl_io_base+0x0C	/* ECC byte counter */
#define ECCCLRR	 	sharpsl_io_base+0x10	/* cleare ECC */
#define FLASHIO	 	sharpsl_io_base+0x14	/* Flash I/O */
#define FLASHCTL	sharpsl_io_base+0x18	/* Flash Control */

/* Flash control bit */
#define FLRYBY		(1 << 5)
#define FLCE1		(1 << 4)
#define FLWP		(1 << 3)
#define FLALE		(1 << 2)
#define FLCLE		(1 << 1)
#define FLCE0		(1 << 0)


/*
 * MTD structure for SharpSL
 */
static struct mtd_info *sharpsl_mtd = NULL;

/*
 * Define partitions for flash device
 */
#define DEFAULT_NUM_PARTITIONS 3

static int nr_partitions;
static struct mtd_partition sharpsl_nand_default_partition_info[] = {
	{
	.name = "System Area",
	.offset = 0,
	.size = 7 * 1024 * 1024,
	},
	{
	.name = "Root Filesystem",
	.offset = 7 * 1024 * 1024,
	.size = 30 * 1024 * 1024,
	},
	{
	.name = "Home Filesystem",
	.offset = MTDPART_OFS_APPEND ,
	.size = MTDPART_SIZ_FULL ,
	},
};

/*
 *	hardware specific access to control-lines
 */
static void
sharpsl_nand_hwcontrol(struct mtd_info* mtd, int cmd)
{
	switch (cmd) {
	case NAND_CTL_SETCLE:
		writeb(readb(FLASHCTL) | FLCLE, FLASHCTL);
		break;
	case NAND_CTL_CLRCLE:
		writeb(readb(FLASHCTL) & ~FLCLE, FLASHCTL);
		break;

	case NAND_CTL_SETALE:
		writeb(readb(FLASHCTL) | FLALE, FLASHCTL);
		break;
	case NAND_CTL_CLRALE:
		writeb(readb(FLASHCTL) & ~FLALE, FLASHCTL);
		break;

	case NAND_CTL_SETNCE:
		writeb(readb(FLASHCTL) & ~(FLCE0|FLCE1), FLASHCTL);
		break;
	case NAND_CTL_CLRNCE:
		writeb(readb(FLASHCTL) | (FLCE0|FLCE1), FLASHCTL);
		break;
	}
}

static uint8_t scan_ff_pattern[] = { 0xff, 0xff };

static struct nand_bbt_descr sharpsl_bbt = {
	.options = 0,
	.offs = 4,
	.len = 2,
	.pattern = scan_ff_pattern
};

static struct nand_bbt_descr sharpsl_akita_bbt = {
	.options = 0,
	.offs = 4,
	.len = 1,
	.pattern = scan_ff_pattern
};

static struct nand_oobinfo akita_oobinfo = {
	.useecc = MTD_NANDECC_AUTOPLACE,
	.eccbytes = 24,
	.eccpos = {
		0x5,  0x1,  0x2,  0x3,  0x6,  0x7,  0x15, 0x11,
		0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23,
		0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37},
	.oobfree = { {0x08, 0x09} }
};

static int
sharpsl_nand_dev_ready(struct mtd_info* mtd)
{
	return !((readb(FLASHCTL) & FLRYBY) == 0);
}

static void
sharpsl_nand_enable_hwecc(struct mtd_info* mtd, int mode)
{
	writeb(0 ,ECCCLRR);
}

static int
sharpsl_nand_calculate_ecc(struct mtd_info* mtd, const u_char* dat,
				u_char* ecc_code)
{
	ecc_code[0] = ~readb(ECCLPUB);
	ecc_code[1] = ~readb(ECCLPLB);
	ecc_code[2] = (~readb(ECCCP) << 2) | 0x03;
	return readb(ECCCNTR) != 0;
}


#ifdef CONFIG_MTD_PARTITIONS
const char *part_probes[] = { "cmdlinepart", NULL };
#endif


/*
 * Main initialization routine
 */
int __init
sharpsl_nand_init(void)
{
	struct nand_chip *this;
	struct mtd_partition* sharpsl_partition_info;
	int err = 0;

	/* Allocate memory for MTD device structure and private data */
	sharpsl_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip),
				GFP_KERNEL);
	if (!sharpsl_mtd) {
		printk ("Unable to allocate SharpSL NAND MTD device structure.\n");
		return -ENOMEM;
	}

	/* map physical adress */
	sharpsl_io_base = ioremap(sharpsl_phys_base, 0x1000);
	if(!sharpsl_io_base){
		printk("ioremap to access Sharp SL NAND chip failed\n");
		kfree(sharpsl_mtd);
		return -EIO;
	}

	/* Get pointer to private data */
	this = (struct nand_chip *) (&sharpsl_mtd[1]);

	/* Initialize structures */
	memset((char *) sharpsl_mtd, 0, sizeof(struct mtd_info));
	memset((char *) this, 0, sizeof(struct nand_chip));

	/* Link the private data with the MTD structure */
	sharpsl_mtd->priv = this;

	/*
	 * PXA initialize
	 */
	writeb(readb(FLASHCTL) | FLWP, FLASHCTL);

	/* Set address of NAND IO lines */
	this->IO_ADDR_R = FLASHIO;
	this->IO_ADDR_W = FLASHIO;
	/* Set address of hardware control function */
	this->hwcontrol = sharpsl_nand_hwcontrol;
	this->dev_ready = sharpsl_nand_dev_ready;
	/* 15 us command delay time */
	this->chip_delay = 15;
	/* set eccmode using hardware ECC */
	this->eccmode = NAND_ECC_HW3_256;
	this->badblock_pattern = &sharpsl_bbt;
	if (machine_is_akita() || machine_is_borzoi()) {
		this->badblock_pattern = &sharpsl_akita_bbt;
		this->autooob = &akita_oobinfo;
	}
	this->enable_hwecc = sharpsl_nand_enable_hwecc;
	this->calculate_ecc = sharpsl_nand_calculate_ecc;
	this->correct_data = nand_correct_data;

	/* Scan to find existence of the device */
	err=nand_scan(sharpsl_mtd,1);
	if (err) {
		iounmap(sharpsl_io_base);
		kfree(sharpsl_mtd);
		return err;
	}

	/* Register the partitions */
	sharpsl_mtd->name = "sharpsl-nand";
	nr_partitions = parse_mtd_partitions(sharpsl_mtd, part_probes,
						&sharpsl_partition_info, 0);

	if (nr_partitions <= 0) {
		nr_partitions = DEFAULT_NUM_PARTITIONS;
		sharpsl_partition_info = sharpsl_nand_default_partition_info;
		if (machine_is_poodle()) {
			sharpsl_partition_info[1].size=30 * 1024 * 1024;
		} else if (machine_is_corgi() || machine_is_shepherd()) {
			sharpsl_partition_info[1].size=25 * 1024 * 1024;
		} else if (machine_is_husky()) {
			sharpsl_partition_info[1].size=53 * 1024 * 1024;
		} else if (machine_is_spitz()) {
			sharpsl_partition_info[1].size=5 * 1024 * 1024;
		} else if (machine_is_akita()) {
			sharpsl_partition_info[1].size=58 * 1024 * 1024;
		} else if (machine_is_borzoi()) {
			sharpsl_partition_info[1].size=32 * 1024 * 1024;
		}
	}

	if (machine_is_husky() || machine_is_borzoi() || machine_is_akita()) {
		/* Need to use small eraseblock size for backward compatibility */
		sharpsl_mtd->flags |= MTD_NO_VIRTBLOCKS;
	}

	add_mtd_partitions(sharpsl_mtd, sharpsl_partition_info, nr_partitions);

	/* Return happy */
	return 0;
}
module_init(sharpsl_nand_init);

/*
 * Clean up routine
 */
#ifdef MODULE
static void __exit sharpsl_nand_cleanup(void)
{
	struct nand_chip *this = (struct nand_chip *) &sharpsl_mtd[1];

	/* Release resources, unregister device */
	nand_release(sharpsl_mtd);

	iounmap(sharpsl_io_base);

	/* Free the MTD device structure */
	kfree(sharpsl_mtd);
}
module_exit(sharpsl_nand_cleanup);
#endif

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
MODULE_DESCRIPTION("Device specific logic for NAND flash on Sharp SL-C7xx Series");
