1 /*
2  *  drivers/mtd/autcpu12.c
3  *
4  *  Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
5  *
6  *  Derived from drivers/mtd/spia.c
7  *	 Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  *
13  *  Overview:
14  *   This is a device driver for the NAND flash device found on the
15  *   autronix autcpu12 board, which is a SmartMediaCard. It supports
16  *   16MiB, 32MiB and 64MiB cards.
17  *
18  *
19  *	02-12-2002 TG	Cleanup of module params
20  *
21  *	02-20-2002 TG	adjusted for different rd/wr address support
22  *			added support for read device ready/busy line
23  *			added page_cache
24  *
25  *	10-06-2002 TG	128K card support added
26  */
27 
28 #include <linux/slab.h>
29 #include <linux/init.h>
30 #include <linux/module.h>
31 #include <linux/mtd/mtd.h>
32 #include <linux/mtd/nand.h>
33 #include <linux/mtd/partitions.h>
34 #include <asm/io.h>
35 #include <mach/hardware.h>
36 #include <asm/sizes.h>
37 #include <mach/autcpu12.h>
38 
39 /*
40  * MTD structure for AUTCPU12 board
41  */
42 static struct mtd_info *autcpu12_mtd = NULL;
43 static void __iomem *autcpu12_fio_base;
44 
45 /*
46  * Define partitions for flash devices
47  */
48 static struct mtd_partition partition_info16k[] = {
49 	{ .name		= "AUTCPU12 flash partition 1",
50 	  .offset	= 0,
51 	  .size		= 8 * SZ_1M },
52 	{ .name		= "AUTCPU12 flash partition 2",
53 	  .offset	= 8 * SZ_1M,
54 	  .size		= 8 * SZ_1M },
55 };
56 
57 static struct mtd_partition partition_info32k[] = {
58 	{ .name		= "AUTCPU12 flash partition 1",
59 	  .offset	= 0,
60 	  .size		= 8 * SZ_1M },
61 	{ .name		= "AUTCPU12 flash partition 2",
62 	  .offset	= 8 * SZ_1M,
63 	  .size		= 24 * SZ_1M },
64 };
65 
66 static struct mtd_partition partition_info64k[] = {
67 	{ .name		= "AUTCPU12 flash partition 1",
68 	  .offset	= 0,
69 	  .size		= 16 * SZ_1M },
70 	{ .name		= "AUTCPU12 flash partition 2",
71 	  .offset	= 16 * SZ_1M,
72 	  .size		= 48 * SZ_1M },
73 };
74 
75 static struct mtd_partition partition_info128k[] = {
76 	{ .name		= "AUTCPU12 flash partition 1",
77 	  .offset	= 0,
78 	  .size		= 16 * SZ_1M },
79 	{ .name		= "AUTCPU12 flash partition 2",
80 	  .offset	= 16 * SZ_1M,
81 	  .size		= 112 * SZ_1M },
82 };
83 
84 #define NUM_PARTITIONS16K 2
85 #define NUM_PARTITIONS32K 2
86 #define NUM_PARTITIONS64K 2
87 #define NUM_PARTITIONS128K 2
88 /*
89  *	hardware specific access to control-lines
90  *
91  *	ALE bit 4 autcpu12_pedr
92  *	CLE bit 5 autcpu12_pedr
93  *	NCE bit 0 fio_ctrl
94  *
95  */
autcpu12_hwcontrol(struct mtd_info * mtd,int cmd,unsigned int ctrl)96 static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd,
97 			       unsigned int ctrl)
98 {
99 	struct nand_chip *chip = mtd->priv;
100 
101 	if (ctrl & NAND_CTRL_CHANGE) {
102 		void __iomem *addr;
103 		unsigned char bits;
104 
105 		addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET;
106 		bits = (ctrl & NAND_CLE) << 4;
107 		bits |= (ctrl & NAND_ALE) << 2;
108 		writeb((readb(addr) & ~0x30) | bits, addr);
109 
110 		addr = autcpu12_fio_base + AUTCPU12_SMC_SELECT_OFFSET;
111 		writeb((readb(addr) & ~0x1) | (ctrl & NAND_NCE), addr);
112 	}
113 
114 	if (cmd != NAND_CMD_NONE)
115 		writeb(cmd, chip->IO_ADDR_W);
116 }
117 
118 /*
119  *	read device ready pin
120  */
autcpu12_device_ready(struct mtd_info * mtd)121 int autcpu12_device_ready(struct mtd_info *mtd)
122 {
123 	void __iomem *addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET;
124 
125 	return readb(addr) & AUTCPU12_SMC_RDY;
126 }
127 
128 /*
129  * Main initialization routine
130  */
autcpu12_init(void)131 static int __init autcpu12_init(void)
132 {
133 	struct nand_chip *this;
134 	int err = 0;
135 
136 	/* Allocate memory for MTD device structure and private data */
137 	autcpu12_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip),
138 			       GFP_KERNEL);
139 	if (!autcpu12_mtd) {
140 		printk("Unable to allocate AUTCPU12 NAND MTD device structure.\n");
141 		err = -ENOMEM;
142 		goto out;
143 	}
144 
145 	/* map physical address */
146 	autcpu12_fio_base = ioremap(AUTCPU12_PHYS_SMC, SZ_1K);
147 	if (!autcpu12_fio_base) {
148 		printk("Ioremap autcpu12 SmartMedia Card failed\n");
149 		err = -EIO;
150 		goto out_mtd;
151 	}
152 
153 	/* Get pointer to private data */
154 	this = (struct nand_chip *)(&autcpu12_mtd[1]);
155 
156 	/* Initialize structures */
157 	memset(autcpu12_mtd, 0, sizeof(struct mtd_info));
158 	memset(this, 0, sizeof(struct nand_chip));
159 
160 	/* Link the private data with the MTD structure */
161 	autcpu12_mtd->priv = this;
162 	autcpu12_mtd->owner = THIS_MODULE;
163 
164 	/* Set address of NAND IO lines */
165 	this->IO_ADDR_R = autcpu12_fio_base;
166 	this->IO_ADDR_W = autcpu12_fio_base;
167 	this->cmd_ctrl = autcpu12_hwcontrol;
168 	this->dev_ready = autcpu12_device_ready;
169 	/* 20 us command delay time */
170 	this->chip_delay = 20;
171 	this->ecc.mode = NAND_ECC_SOFT;
172 
173 	/* Enable the following for a flash based bad block table */
174 	/*
175 	   this->options = NAND_USE_FLASH_BBT;
176 	 */
177 	this->options = NAND_USE_FLASH_BBT;
178 
179 	/* Scan to find existence of the device */
180 	if (nand_scan(autcpu12_mtd, 1)) {
181 		err = -ENXIO;
182 		goto out_ior;
183 	}
184 
185 	/* Register the partitions */
186 	switch (autcpu12_mtd->size) {
187 		case SZ_16M:
188 			add_mtd_partitions(autcpu12_mtd, partition_info16k,
189 					   NUM_PARTITIONS16K);
190 			break;
191 		case SZ_32M:
192 			add_mtd_partitions(autcpu12_mtd, partition_info32k,
193 					   NUM_PARTITIONS32K);
194 			break;
195 		case SZ_64M:
196 			add_mtd_partitions(autcpu12_mtd, partition_info64k,
197 					   NUM_PARTITIONS64K);
198 			break;
199 		case SZ_128M:
200 			add_mtd_partitions(autcpu12_mtd, partition_info128k,
201 					   NUM_PARTITIONS128K);
202 			break;
203 		default:
204 			printk("Unsupported SmartMedia device\n");
205 			err = -ENXIO;
206 			goto out_ior;
207 	}
208 	goto out;
209 
210  out_ior:
211 	iounmap(autcpu12_fio_base);
212  out_mtd:
213 	kfree(autcpu12_mtd);
214  out:
215 	return err;
216 }
217 
218 module_init(autcpu12_init);
219 
220 /*
221  * Clean up routine
222  */
autcpu12_cleanup(void)223 static void __exit autcpu12_cleanup(void)
224 {
225 	/* Release resources, unregister device */
226 	nand_release(autcpu12_mtd);
227 
228 	/* unmap physical address */
229 	iounmap(autcpu12_fio_base);
230 
231 	/* Free the MTD device structure */
232 	kfree(autcpu12_mtd);
233 }
234 
235 module_exit(autcpu12_cleanup);
236 
237 MODULE_LICENSE("GPL");
238 MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
239 MODULE_DESCRIPTION("Glue layer for SmartMediaCard on autronix autcpu12");
240