1 /*
2  *  linux/drivers/mtd/nand/cmx270-nand.c
3  *
4  *  Copyright (C) 2006 Compulab, Ltd.
5  *  Mike Rapoport <mike@compulab.co.il>
6  *
7  *  Derived from drivers/mtd/nand/h1910.c
8  *       Copyright (C) 2002 Marius Gröger (mag@sysgo.de)
9  *       Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
10  *
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License version 2 as
14  * published by the Free Software Foundation.
15  *
16  *  Overview:
17  *   This is a device driver for the NAND flash device found on the
18  *   CM-X270 board.
19  */
20 
21 #include <linux/mtd/nand.h>
22 #include <linux/mtd/partitions.h>
23 #include <linux/slab.h>
24 #include <linux/gpio.h>
25 #include <linux/module.h>
26 
27 #include <asm/io.h>
28 #include <asm/irq.h>
29 #include <asm/mach-types.h>
30 
31 #include <mach/pxa2xx-regs.h>
32 
33 #define GPIO_NAND_CS	(11)
34 #define GPIO_NAND_RB	(89)
35 
36 /* MTD structure for CM-X270 board */
37 static struct mtd_info *cmx270_nand_mtd;
38 
39 /* remaped IO address of the device */
40 static void __iomem *cmx270_nand_io;
41 
42 /*
43  * Define static partitions for flash device
44  */
45 static struct mtd_partition partition_info[] = {
46 	[0] = {
47 		.name	= "cmx270-0",
48 		.offset	= 0,
49 		.size	= MTDPART_SIZ_FULL
50 	}
51 };
52 #define NUM_PARTITIONS (ARRAY_SIZE(partition_info))
53 
cmx270_read_byte(struct mtd_info * mtd)54 static u_char cmx270_read_byte(struct mtd_info *mtd)
55 {
56 	struct nand_chip *this = mtd->priv;
57 
58 	return (readl(this->IO_ADDR_R) >> 16);
59 }
60 
cmx270_write_buf(struct mtd_info * mtd,const u_char * buf,int len)61 static void cmx270_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
62 {
63 	int i;
64 	struct nand_chip *this = mtd->priv;
65 
66 	for (i=0; i<len; i++)
67 		writel((*buf++ << 16), this->IO_ADDR_W);
68 }
69 
cmx270_read_buf(struct mtd_info * mtd,u_char * buf,int len)70 static void cmx270_read_buf(struct mtd_info *mtd, u_char *buf, int len)
71 {
72 	int i;
73 	struct nand_chip *this = mtd->priv;
74 
75 	for (i=0; i<len; i++)
76 		*buf++ = readl(this->IO_ADDR_R) >> 16;
77 }
78 
cmx270_verify_buf(struct mtd_info * mtd,const u_char * buf,int len)79 static int cmx270_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
80 {
81 	int i;
82 	struct nand_chip *this = mtd->priv;
83 
84 	for (i=0; i<len; i++)
85 		if (buf[i] != (u_char)(readl(this->IO_ADDR_R) >> 16))
86 			return -EFAULT;
87 
88 	return 0;
89 }
90 
nand_cs_on(void)91 static inline void nand_cs_on(void)
92 {
93 	gpio_set_value(GPIO_NAND_CS, 0);
94 }
95 
nand_cs_off(void)96 static void nand_cs_off(void)
97 {
98 	dsb();
99 
100 	gpio_set_value(GPIO_NAND_CS, 1);
101 }
102 
103 /*
104  *	hardware specific access to control-lines
105  */
cmx270_hwcontrol(struct mtd_info * mtd,int dat,unsigned int ctrl)106 static void cmx270_hwcontrol(struct mtd_info *mtd, int dat,
107 			     unsigned int ctrl)
108 {
109 	struct nand_chip* this = mtd->priv;
110 	unsigned int nandaddr = (unsigned int)this->IO_ADDR_W;
111 
112 	dsb();
113 
114 	if (ctrl & NAND_CTRL_CHANGE) {
115 		if ( ctrl & NAND_ALE )
116 			nandaddr |=  (1 << 3);
117 		else
118 			nandaddr &= ~(1 << 3);
119 		if ( ctrl & NAND_CLE )
120 			nandaddr |=  (1 << 2);
121 		else
122 			nandaddr &= ~(1 << 2);
123 		if ( ctrl & NAND_NCE )
124 			nand_cs_on();
125 		else
126 			nand_cs_off();
127 	}
128 
129 	dsb();
130 	this->IO_ADDR_W = (void __iomem*)nandaddr;
131 	if (dat != NAND_CMD_NONE)
132 		writel((dat << 16), this->IO_ADDR_W);
133 
134 	dsb();
135 }
136 
137 /*
138  *	read device ready pin
139  */
cmx270_device_ready(struct mtd_info * mtd)140 static int cmx270_device_ready(struct mtd_info *mtd)
141 {
142 	dsb();
143 
144 	return (gpio_get_value(GPIO_NAND_RB));
145 }
146 
147 /*
148  * Main initialization routine
149  */
cmx270_init(void)150 static int __init cmx270_init(void)
151 {
152 	struct nand_chip *this;
153 	int ret;
154 
155 	if (!(machine_is_armcore() && cpu_is_pxa27x()))
156 		return -ENODEV;
157 
158 	ret = gpio_request(GPIO_NAND_CS, "NAND CS");
159 	if (ret) {
160 		pr_warning("CM-X270: failed to request NAND CS gpio\n");
161 		return ret;
162 	}
163 
164 	gpio_direction_output(GPIO_NAND_CS, 1);
165 
166 	ret = gpio_request(GPIO_NAND_RB, "NAND R/B");
167 	if (ret) {
168 		pr_warning("CM-X270: failed to request NAND R/B gpio\n");
169 		goto err_gpio_request;
170 	}
171 
172 	gpio_direction_input(GPIO_NAND_RB);
173 
174 	/* Allocate memory for MTD device structure and private data */
175 	cmx270_nand_mtd = kzalloc(sizeof(struct mtd_info) +
176 				  sizeof(struct nand_chip),
177 				  GFP_KERNEL);
178 	if (!cmx270_nand_mtd) {
179 		pr_debug("Unable to allocate CM-X270 NAND MTD device structure.\n");
180 		ret = -ENOMEM;
181 		goto err_kzalloc;
182 	}
183 
184 	cmx270_nand_io = ioremap(PXA_CS1_PHYS, 12);
185 	if (!cmx270_nand_io) {
186 		pr_debug("Unable to ioremap NAND device\n");
187 		ret = -EINVAL;
188 		goto err_ioremap;
189 	}
190 
191 	/* Get pointer to private data */
192 	this = (struct nand_chip *)(&cmx270_nand_mtd[1]);
193 
194 	/* Link the private data with the MTD structure */
195 	cmx270_nand_mtd->owner = THIS_MODULE;
196 	cmx270_nand_mtd->priv = this;
197 
198 	/* insert callbacks */
199 	this->IO_ADDR_R = cmx270_nand_io;
200 	this->IO_ADDR_W = cmx270_nand_io;
201 	this->cmd_ctrl = cmx270_hwcontrol;
202 	this->dev_ready = cmx270_device_ready;
203 
204 	/* 15 us command delay time */
205 	this->chip_delay = 20;
206 	this->ecc.mode = NAND_ECC_SOFT;
207 
208 	/* read/write functions */
209 	this->read_byte = cmx270_read_byte;
210 	this->read_buf = cmx270_read_buf;
211 	this->write_buf = cmx270_write_buf;
212 	this->verify_buf = cmx270_verify_buf;
213 
214 	/* Scan to find existence of the device */
215 	if (nand_scan (cmx270_nand_mtd, 1)) {
216 		pr_notice("No NAND device\n");
217 		ret = -ENXIO;
218 		goto err_scan;
219 	}
220 
221 	/* Register the partitions */
222 	ret = mtd_device_parse_register(cmx270_nand_mtd, NULL, 0,
223 					partition_info, NUM_PARTITIONS);
224 	if (ret)
225 		goto err_scan;
226 
227 	/* Return happy */
228 	return 0;
229 
230 err_scan:
231 	iounmap(cmx270_nand_io);
232 err_ioremap:
233 	kfree(cmx270_nand_mtd);
234 err_kzalloc:
235 	gpio_free(GPIO_NAND_RB);
236 err_gpio_request:
237 	gpio_free(GPIO_NAND_CS);
238 
239 	return ret;
240 
241 }
242 module_init(cmx270_init);
243 
244 /*
245  * Clean up routine
246  */
cmx270_cleanup(void)247 static void __exit cmx270_cleanup(void)
248 {
249 	/* Release resources, unregister device */
250 	nand_release(cmx270_nand_mtd);
251 
252 	gpio_free(GPIO_NAND_RB);
253 	gpio_free(GPIO_NAND_CS);
254 
255 	iounmap(cmx270_nand_io);
256 
257 	/* Free the MTD device structure */
258 	kfree (cmx270_nand_mtd);
259 }
260 module_exit(cmx270_cleanup);
261 
262 MODULE_LICENSE("GPL");
263 MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
264 MODULE_DESCRIPTION("NAND flash driver for Compulab CM-X270 Module");
265