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