toto.c 4.84 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 *  drivers/mtd/nand/toto.c
 *
 *  Copyright (c) 2003 Texas Instruments
 *
 *  Derived from drivers/mtd/autcpu12.c
 *
 *  Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
 *
 * 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.
 *
 *  Overview:
 *   This is a device driver for the NAND flash device found on the
 *   TI fido board. It supports 32MiB and 64MiB cards
 *
18
 * $Id: toto.c,v 1.5 2005/11/07 11:14:31 gleixner Exp $
Linus Torvalds's avatar
Linus Torvalds committed
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
 */

#include <linux/slab.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
#include <asm/sizes.h>
#include <asm/arch/toto.h>
#include <asm/arch-omap1510/hardware.h>
#include <asm/arch/gpio.h>

35 36
#define CONFIG_NAND_WORKAROUND 1

Linus Torvalds's avatar
Linus Torvalds committed
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
/*
 * MTD structure for TOTO board
 */
static struct mtd_info *toto_mtd = NULL;

static unsigned long toto_io_base = OMAP_FLASH_1_BASE;

/*
 * Define partitions for flash devices
 */

static struct mtd_partition partition_info64M[] = {
	{ .name =	"toto kernel partition 1",
	  .offset =	0,
	  .size	=	2 * SZ_1M },
	{ .name =	"toto file sys partition 2",
	  .offset =	2 * SZ_1M,
	  .size =	14 * SZ_1M },
	{ .name =	"toto user partition 3",
	  .offset =	16 * SZ_1M,
	  .size =	16 * SZ_1M },
	{ .name =	"toto devboard extra partition 4",
	  .offset =	32 * SZ_1M,
	  .size =	32 * SZ_1M },
};

static struct mtd_partition partition_info32M[] = {
	{ .name =	"toto kernel partition 1",
	  .offset =	0,
	  .size =	2 * SZ_1M },
	{ .name =	"toto file sys partition 2",
	  .offset =	2 * SZ_1M,
	  .size =	14 * SZ_1M },
	{ .name =	"toto user partition 3",
	  .offset =	16 * SZ_1M,
	  .size =	16 * SZ_1M },
};

#define NUM_PARTITIONS32M 3
#define NUM_PARTITIONS64M 4
77

78
/*
Linus Torvalds's avatar
Linus Torvalds committed
79
 *	hardware specific access to control-lines
80 81 82 83 84 85 86 87
 *
 *	ctrl:
 *	NAND_NCE: bit 0 -> bit 14 (0x4000)
 *	NAND_CLE: bit 1 -> bit 12 (0x1000)
 *	NAND_ALE: bit 2 -> bit 1  (0x0002)
 */
static void toto_hwcontrol(struct mtd_info *mtd, int cmd,
			   unsigned int ctrl)
Linus Torvalds's avatar
Linus Torvalds committed
88
{
89 90 91 92
	struct nand_chip *chip = mtd->priv;

	if (ctrl & NAND_CTRL_CHANGE) {
		unsigned long bits;
Linus Torvalds's avatar
Linus Torvalds committed
93

94 95
		/* hopefully enough time for tc make proceding write to clear */
		udelay(1);
Linus Torvalds's avatar
Linus Torvalds committed
96

97 98 99
		bits = (~ctrl & NAND_NCE) << 14;
		bits |= (ctrl & NAND_CLE) << 12;
		bits |= (ctrl & NAND_ALE) >> 1;
Linus Torvalds's avatar
Linus Torvalds committed
100

101 102 103 104 105 106 107 108 109
#warning Wild guess as gpiosetout() is nowhere defined in the kernel source - tglx
		gpiosetout(0x5002, bits);

#ifdef CONFIG_NAND_WORKAROUND
		/* "some" dev boards busted, blue wired to rts2 :( */
		rts2setout(2, (ctrl & NAND_CLE) << 1);
#endif
		/* allow time to ensure gpio state to over take memory write */
		udelay(1);
Linus Torvalds's avatar
Linus Torvalds committed
110
	}
111 112 113

	if (cmd != NAND_CMD_NONE)
		writeb(cmd, chip->IO_ADDR_W);
Linus Torvalds's avatar
Linus Torvalds committed
114 115 116 117 118
}

/*
 * Main initialization routine
 */
119
static int __init toto_init(void)
Linus Torvalds's avatar
Linus Torvalds committed
120 121 122 123 124
{
	struct nand_chip *this;
	int err = 0;

	/* Allocate memory for MTD device structure and private data */
125
	toto_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
Linus Torvalds's avatar
Linus Torvalds committed
126
	if (!toto_mtd) {
127
		printk(KERN_WARNING "Unable to allocate toto NAND MTD device structure.\n");
Linus Torvalds's avatar
Linus Torvalds committed
128 129 130 131 132
		err = -ENOMEM;
		goto out;
	}

	/* Get pointer to private data */
133
	this = (struct nand_chip *)(&toto_mtd[1]);
Linus Torvalds's avatar
Linus Torvalds committed
134 135

	/* Initialize structures */
136 137
	memset(toto_mtd, 0, sizeof(struct mtd_info));
	memset(this, 0, sizeof(struct nand_chip));
Linus Torvalds's avatar
Linus Torvalds committed
138 139 140

	/* Link the private data with the MTD structure */
	toto_mtd->priv = this;
141
	toto_mtd->owner = THIS_MODULE;
Linus Torvalds's avatar
Linus Torvalds committed
142 143 144 145

	/* Set address of NAND IO lines */
	this->IO_ADDR_R = toto_io_base;
	this->IO_ADDR_W = toto_io_base;
146
	this->cmd_ctrl = toto_hwcontrol;
Linus Torvalds's avatar
Linus Torvalds committed
147 148
	this->dev_ready = NULL;
	/* 25 us command delay time */
149
	this->chip_delay = 30;
Thomas Gleixner's avatar
Thomas Gleixner committed
150
	this->ecc.mode = NAND_ECC_SOFT;
Linus Torvalds's avatar
Linus Torvalds committed
151

152 153
	/* Scan to find existance of the device */
	if (nand_scan(toto_mtd, 1)) {
Linus Torvalds's avatar
Linus Torvalds committed
154 155 156 157 158
		err = -ENXIO;
		goto out_mtd;
	}

	/* Register the partitions */
159 160 161 162 163 164 165 166 167
	switch (toto_mtd->size) {
	case SZ_64M:
		add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M);
		break;
	case SZ_32M:
		add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M);
		break;
	default:{
			printk(KERN_WARNING "Unsupported Nand device\n");
Linus Torvalds's avatar
Linus Torvalds committed
168 169 170 171 172
			err = -ENXIO;
			goto out_buf;
		}
	}

173 174
	gpioreserve(NAND_MASK);	/* claim our gpios */
	archflashwp(0, 0);	/* open up flash for writing */
Linus Torvalds's avatar
Linus Torvalds committed
175 176

	goto out;
177

178 179 180 181 182
 out_buf:
	kfree(this->data_buf);
 out_mtd:
	kfree(toto_mtd);
 out:
Linus Torvalds's avatar
Linus Torvalds committed
183 184 185 186 187 188 189 190
	return err;
}

module_init(toto_init);

/*
 * Clean up routine
 */
191
static void __exit toto_cleanup(void)
Linus Torvalds's avatar
Linus Torvalds committed
192 193
{
	/* Release resources, unregister device */
194
	nand_release(toto_mtd);
Linus Torvalds's avatar
Linus Torvalds committed
195 196

	/* Free the MTD device structure */
197
	kfree(toto_mtd);
Linus Torvalds's avatar
Linus Torvalds committed
198 199

	/* stop flash writes */
200
	archflashwp(0, 1);
201

Linus Torvalds's avatar
Linus Torvalds committed
202
	/* release gpios to system */
203
	gpiorelease(NAND_MASK);
Linus Torvalds's avatar
Linus Torvalds committed
204
}
205

Linus Torvalds's avatar
Linus Torvalds committed
206 207 208 209 210
module_exit(toto_cleanup);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Richard Woodruff <r-woodruff2@ti.com>");
MODULE_DESCRIPTION("Glue layer for NAND flash on toto board");