blob: da25a90af4a4df2ff1f731905d6dc11aac4a17b9 [file] [log] [blame]
Adrian Hunter36cd4fb2008-08-06 10:08:46 +03001/*
2 * linux/drivers/mtd/onenand/omap2.c
3 *
4 * OneNAND driver for OMAP2 / OMAP3
5 *
6 * Copyright © 2005-2006 Nokia Corporation
7 *
8 * Author: Jarkko Lavinen <jarkko.lavinen@nokia.com> and Juha Yrjölä
9 * IRQ and DMA support written by Timo Teras
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License version 2 as published by
13 * the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * more details.
19 *
20 * You should have received a copy of the GNU General Public License along with
21 * this program; see the file COPYING. If not, write to the Free Software
22 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 *
24 */
25
26#include <linux/device.h>
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/mtd/mtd.h>
30#include <linux/mtd/onenand.h>
31#include <linux/mtd/partitions.h>
32#include <linux/platform_device.h>
33#include <linux/interrupt.h>
34#include <linux/delay.h>
Adrian Huntercbbd6952008-11-24 14:44:36 +020035#include <linux/dma-mapping.h>
36#include <linux/io.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090037#include <linux/slab.h>
Adrian Hunter36cd4fb2008-08-06 10:08:46 +030038
Adrian Hunter36cd4fb2008-08-06 10:08:46 +030039#include <asm/mach/flash.h>
Tony Lindgrence491cf2009-10-20 09:40:47 -070040#include <plat/gpmc.h>
41#include <plat/onenand.h>
Adrian Hunterfe875352008-11-24 13:37:05 +020042#include <mach/gpio.h>
Adrian Hunter36cd4fb2008-08-06 10:08:46 +030043
Tony Lindgrence491cf2009-10-20 09:40:47 -070044#include <plat/dma.h>
Adrian Hunter36cd4fb2008-08-06 10:08:46 +030045
Tony Lindgrence491cf2009-10-20 09:40:47 -070046#include <plat/board.h>
Adrian Hunter36cd4fb2008-08-06 10:08:46 +030047
48#define DRIVER_NAME "omap2-onenand"
49
50#define ONENAND_IO_SIZE SZ_128K
51#define ONENAND_BUFRAM_SIZE (1024 * 5)
52
53struct omap2_onenand {
54 struct platform_device *pdev;
55 int gpmc_cs;
56 unsigned long phys_base;
57 int gpio_irq;
58 struct mtd_info mtd;
59 struct mtd_partition *parts;
60 struct onenand_chip onenand;
61 struct completion irq_done;
62 struct completion dma_done;
63 int dma_channel;
64 int freq;
65 int (*setup)(void __iomem *base, int freq);
66};
67
68static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
69{
70 struct omap2_onenand *c = data;
71
72 complete(&c->dma_done);
73}
74
75static irqreturn_t omap2_onenand_interrupt(int irq, void *dev_id)
76{
77 struct omap2_onenand *c = dev_id;
78
79 complete(&c->irq_done);
80
81 return IRQ_HANDLED;
82}
83
84static inline unsigned short read_reg(struct omap2_onenand *c, int reg)
85{
86 return readw(c->onenand.base + reg);
87}
88
89static inline void write_reg(struct omap2_onenand *c, unsigned short value,
90 int reg)
91{
92 writew(value, c->onenand.base + reg);
93}
94
95static void wait_err(char *msg, int state, unsigned int ctrl, unsigned int intr)
96{
97 printk(KERN_ERR "onenand_wait: %s! state %d ctrl 0x%04x intr 0x%04x\n",
98 msg, state, ctrl, intr);
99}
100
101static void wait_warn(char *msg, int state, unsigned int ctrl,
102 unsigned int intr)
103{
104 printk(KERN_WARNING "onenand_wait: %s! state %d ctrl 0x%04x "
105 "intr 0x%04x\n", msg, state, ctrl, intr);
106}
107
108static int omap2_onenand_wait(struct mtd_info *mtd, int state)
109{
110 struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
Roman Tereshonkovd19d7b42010-11-03 12:55:20 +0200111 struct onenand_chip *this = mtd->priv;
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300112 unsigned int intr = 0;
Roman Tereshonkovd19d7b42010-11-03 12:55:20 +0200113 unsigned int ctrl, ctrl_mask;
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300114 unsigned long timeout;
115 u32 syscfg;
116
Mika Korhonen72073022009-10-23 07:50:43 +0200117 if (state == FL_RESETING || state == FL_PREPARING_ERASE ||
118 state == FL_VERIFYING_ERASE) {
119 int i = 21;
120 unsigned int intr_flags = ONENAND_INT_MASTER;
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300121
Mika Korhonen72073022009-10-23 07:50:43 +0200122 switch (state) {
123 case FL_RESETING:
124 intr_flags |= ONENAND_INT_RESET;
125 break;
126 case FL_PREPARING_ERASE:
127 intr_flags |= ONENAND_INT_ERASE;
128 break;
129 case FL_VERIFYING_ERASE:
130 i = 101;
131 break;
132 }
133
134 while (--i) {
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300135 udelay(1);
136 intr = read_reg(c, ONENAND_REG_INTERRUPT);
137 if (intr & ONENAND_INT_MASTER)
138 break;
139 }
140 ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
141 if (ctrl & ONENAND_CTRL_ERROR) {
142 wait_err("controller error", state, ctrl, intr);
143 return -EIO;
144 }
Mika Korhonen72073022009-10-23 07:50:43 +0200145 if ((intr & intr_flags) != intr_flags) {
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300146 wait_err("timeout", state, ctrl, intr);
147 return -EIO;
148 }
149 return 0;
150 }
151
152 if (state != FL_READING) {
153 int result;
154
155 /* Turn interrupts on */
156 syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
Adrian Hunter782b7a32008-08-14 14:00:12 +0300157 if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) {
158 syscfg |= ONENAND_SYS_CFG1_IOBE;
159 write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
160 if (cpu_is_omap34xx())
161 /* Add a delay to let GPIO settle */
162 syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
163 }
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300164
165 INIT_COMPLETION(c->irq_done);
166 if (c->gpio_irq) {
David Brownell0b84b5c2008-12-10 17:35:25 -0800167 result = gpio_get_value(c->gpio_irq);
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300168 if (result == -1) {
169 ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
170 intr = read_reg(c, ONENAND_REG_INTERRUPT);
171 wait_err("gpio error", state, ctrl, intr);
172 return -EIO;
173 }
174 } else
175 result = 0;
176 if (result == 0) {
177 int retry_cnt = 0;
178retry:
179 result = wait_for_completion_timeout(&c->irq_done,
180 msecs_to_jiffies(20));
181 if (result == 0) {
182 /* Timeout after 20ms */
183 ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
Roman Tereshonkovd19d7b42010-11-03 12:55:20 +0200184 if (ctrl & ONENAND_CTRL_ONGO &&
185 !this->ongoing) {
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300186 /*
187 * The operation seems to be still going
188 * so give it some more time.
189 */
190 retry_cnt += 1;
191 if (retry_cnt < 3)
192 goto retry;
193 intr = read_reg(c,
194 ONENAND_REG_INTERRUPT);
195 wait_err("timeout", state, ctrl, intr);
196 return -EIO;
197 }
198 intr = read_reg(c, ONENAND_REG_INTERRUPT);
199 if ((intr & ONENAND_INT_MASTER) == 0)
200 wait_warn("timeout", state, ctrl, intr);
201 }
202 }
203 } else {
Adrian Hunter8afbc112008-08-25 12:01:31 +0300204 int retry_cnt = 0;
205
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300206 /* Turn interrupts off */
207 syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
208 syscfg &= ~ONENAND_SYS_CFG1_IOBE;
209 write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
210
211 timeout = jiffies + msecs_to_jiffies(20);
Adrian Hunter8afbc112008-08-25 12:01:31 +0300212 while (1) {
213 if (time_before(jiffies, timeout)) {
214 intr = read_reg(c, ONENAND_REG_INTERRUPT);
215 if (intr & ONENAND_INT_MASTER)
216 break;
217 } else {
218 /* Timeout after 20ms */
219 ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
220 if (ctrl & ONENAND_CTRL_ONGO) {
221 /*
222 * The operation seems to be still going
223 * so give it some more time.
224 */
225 retry_cnt += 1;
226 if (retry_cnt < 3) {
227 timeout = jiffies +
228 msecs_to_jiffies(20);
229 continue;
230 }
231 }
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300232 break;
Adrian Hunter8afbc112008-08-25 12:01:31 +0300233 }
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300234 }
235 }
236
237 intr = read_reg(c, ONENAND_REG_INTERRUPT);
238 ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
239
240 if (intr & ONENAND_INT_READ) {
241 int ecc = read_reg(c, ONENAND_REG_ECC_STATUS);
242
243 if (ecc) {
244 unsigned int addr1, addr8;
245
246 addr1 = read_reg(c, ONENAND_REG_START_ADDRESS1);
247 addr8 = read_reg(c, ONENAND_REG_START_ADDRESS8);
248 if (ecc & ONENAND_ECC_2BIT_ALL) {
249 printk(KERN_ERR "onenand_wait: ECC error = "
250 "0x%04x, addr1 %#x, addr8 %#x\n",
251 ecc, addr1, addr8);
252 mtd->ecc_stats.failed++;
253 return -EBADMSG;
254 } else if (ecc & ONENAND_ECC_1BIT_ALL) {
255 printk(KERN_NOTICE "onenand_wait: correctable "
256 "ECC error = 0x%04x, addr1 %#x, "
257 "addr8 %#x\n", ecc, addr1, addr8);
258 mtd->ecc_stats.corrected++;
259 }
260 }
261 } else if (state == FL_READING) {
262 wait_err("timeout", state, ctrl, intr);
263 return -EIO;
264 }
265
266 if (ctrl & ONENAND_CTRL_ERROR) {
267 wait_err("controller error", state, ctrl, intr);
268 if (ctrl & ONENAND_CTRL_LOCK)
269 printk(KERN_ERR "onenand_wait: "
270 "Device is write protected!!!\n");
271 return -EIO;
272 }
273
Roman Tereshonkovd19d7b42010-11-03 12:55:20 +0200274 ctrl_mask = 0xFE9F;
275 if (this->ongoing)
276 ctrl_mask &= ~0x8000;
277
278 if (ctrl & ctrl_mask)
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300279 wait_warn("unexpected controller status", state, ctrl, intr);
280
281 return 0;
282}
283
284static inline int omap2_onenand_bufferram_offset(struct mtd_info *mtd, int area)
285{
286 struct onenand_chip *this = mtd->priv;
287
288 if (ONENAND_CURRENT_BUFFERRAM(this)) {
289 if (area == ONENAND_DATARAM)
Mika Korhonen00acf4a2009-06-11 14:05:07 +0300290 return this->writesize;
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300291 if (area == ONENAND_SPARERAM)
292 return mtd->oobsize;
293 }
294
295 return 0;
296}
297
298#if defined(CONFIG_ARCH_OMAP3) || defined(MULTI_OMAP2)
299
300static int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
301 unsigned char *buffer, int offset,
302 size_t count)
303{
304 struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
305 struct onenand_chip *this = mtd->priv;
306 dma_addr_t dma_src, dma_dst;
307 int bram_offset;
308 unsigned long timeout;
309 void *buf = (void *)buffer;
310 size_t xtra;
311 volatile unsigned *done;
312
313 bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
314 if (bram_offset & 3 || (size_t)buf & 3 || count < 384)
315 goto out_copy;
316
Adrian Huntera29f2802009-03-23 14:57:38 +0200317 /* panic_write() may be in an interrupt context */
Aaro Koskinen932f5d22010-02-10 19:03:19 +0200318 if (in_interrupt() || oops_in_progress)
Adrian Huntera29f2802009-03-23 14:57:38 +0200319 goto out_copy;
320
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300321 if (buf >= high_memory) {
322 struct page *p1;
323
324 if (((size_t)buf & PAGE_MASK) !=
325 ((size_t)(buf + count - 1) & PAGE_MASK))
326 goto out_copy;
327 p1 = vmalloc_to_page(buf);
328 if (!p1)
329 goto out_copy;
330 buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK);
331 }
332
333 xtra = count & 3;
334 if (xtra) {
335 count -= xtra;
336 memcpy(buf + count, this->base + bram_offset + count, xtra);
337 }
338
339 dma_src = c->phys_base + bram_offset;
340 dma_dst = dma_map_single(&c->pdev->dev, buf, count, DMA_FROM_DEVICE);
341 if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
342 dev_err(&c->pdev->dev,
343 "Couldn't DMA map a %d byte buffer\n",
344 count);
345 goto out_copy;
346 }
347
348 omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S32,
349 count >> 2, 1, 0, 0, 0);
350 omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
351 dma_src, 0, 0);
352 omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
353 dma_dst, 0, 0);
354
355 INIT_COMPLETION(c->dma_done);
356 omap_start_dma(c->dma_channel);
357
358 timeout = jiffies + msecs_to_jiffies(20);
359 done = &c->dma_done.done;
360 while (time_before(jiffies, timeout))
361 if (*done)
362 break;
363
364 dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_FROM_DEVICE);
365
366 if (!*done) {
367 dev_err(&c->pdev->dev, "timeout waiting for DMA\n");
368 goto out_copy;
369 }
370
371 return 0;
372
373out_copy:
374 memcpy(buf, this->base + bram_offset, count);
375 return 0;
376}
377
378static int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
379 const unsigned char *buffer,
380 int offset, size_t count)
381{
382 struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
383 struct onenand_chip *this = mtd->priv;
384 dma_addr_t dma_src, dma_dst;
385 int bram_offset;
386 unsigned long timeout;
387 void *buf = (void *)buffer;
388 volatile unsigned *done;
389
390 bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
391 if (bram_offset & 3 || (size_t)buf & 3 || count < 384)
392 goto out_copy;
393
394 /* panic_write() may be in an interrupt context */
Aaro Koskinen932f5d22010-02-10 19:03:19 +0200395 if (in_interrupt() || oops_in_progress)
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300396 goto out_copy;
397
398 if (buf >= high_memory) {
399 struct page *p1;
400
401 if (((size_t)buf & PAGE_MASK) !=
402 ((size_t)(buf + count - 1) & PAGE_MASK))
403 goto out_copy;
404 p1 = vmalloc_to_page(buf);
405 if (!p1)
406 goto out_copy;
407 buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK);
408 }
409
410 dma_src = dma_map_single(&c->pdev->dev, buf, count, DMA_TO_DEVICE);
411 dma_dst = c->phys_base + bram_offset;
Mika Westerberg4a70b7d2010-03-24 12:10:48 +0200412 if (dma_mapping_error(&c->pdev->dev, dma_src)) {
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300413 dev_err(&c->pdev->dev,
414 "Couldn't DMA map a %d byte buffer\n",
415 count);
416 return -1;
417 }
418
419 omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S32,
420 count >> 2, 1, 0, 0, 0);
421 omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
422 dma_src, 0, 0);
423 omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
424 dma_dst, 0, 0);
425
426 INIT_COMPLETION(c->dma_done);
427 omap_start_dma(c->dma_channel);
428
429 timeout = jiffies + msecs_to_jiffies(20);
430 done = &c->dma_done.done;
431 while (time_before(jiffies, timeout))
432 if (*done)
433 break;
434
Mika Westerberg4a70b7d2010-03-24 12:10:48 +0200435 dma_unmap_single(&c->pdev->dev, dma_src, count, DMA_TO_DEVICE);
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300436
437 if (!*done) {
438 dev_err(&c->pdev->dev, "timeout waiting for DMA\n");
439 goto out_copy;
440 }
441
442 return 0;
443
444out_copy:
445 memcpy(this->base + bram_offset, buf, count);
446 return 0;
447}
448
449#else
450
451int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
452 unsigned char *buffer, int offset,
453 size_t count);
454
455int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
456 const unsigned char *buffer,
457 int offset, size_t count);
458
459#endif
460
461#if defined(CONFIG_ARCH_OMAP2) || defined(MULTI_OMAP2)
462
463static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
464 unsigned char *buffer, int offset,
465 size_t count)
466{
467 struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
468 struct onenand_chip *this = mtd->priv;
469 dma_addr_t dma_src, dma_dst;
470 int bram_offset;
471
472 bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
473 /* DMA is not used. Revisit PM requirements before enabling it. */
474 if (1 || (c->dma_channel < 0) ||
475 ((void *) buffer >= (void *) high_memory) || (bram_offset & 3) ||
476 (((unsigned int) buffer) & 3) || (count < 1024) || (count & 3)) {
477 memcpy(buffer, (__force void *)(this->base + bram_offset),
478 count);
479 return 0;
480 }
481
482 dma_src = c->phys_base + bram_offset;
483 dma_dst = dma_map_single(&c->pdev->dev, buffer, count,
484 DMA_FROM_DEVICE);
485 if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
486 dev_err(&c->pdev->dev,
487 "Couldn't DMA map a %d byte buffer\n",
488 count);
489 return -1;
490 }
491
492 omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S32,
493 count / 4, 1, 0, 0, 0);
494 omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
495 dma_src, 0, 0);
496 omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
497 dma_dst, 0, 0);
498
499 INIT_COMPLETION(c->dma_done);
500 omap_start_dma(c->dma_channel);
501 wait_for_completion(&c->dma_done);
502
503 dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_FROM_DEVICE);
504
505 return 0;
506}
507
508static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
509 const unsigned char *buffer,
510 int offset, size_t count)
511{
512 struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
513 struct onenand_chip *this = mtd->priv;
514 dma_addr_t dma_src, dma_dst;
515 int bram_offset;
516
517 bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
518 /* DMA is not used. Revisit PM requirements before enabling it. */
519 if (1 || (c->dma_channel < 0) ||
520 ((void *) buffer >= (void *) high_memory) || (bram_offset & 3) ||
521 (((unsigned int) buffer) & 3) || (count < 1024) || (count & 3)) {
522 memcpy((__force void *)(this->base + bram_offset), buffer,
523 count);
524 return 0;
525 }
526
527 dma_src = dma_map_single(&c->pdev->dev, (void *) buffer, count,
528 DMA_TO_DEVICE);
529 dma_dst = c->phys_base + bram_offset;
Mika Westerberg4a70b7d2010-03-24 12:10:48 +0200530 if (dma_mapping_error(&c->pdev->dev, dma_src)) {
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300531 dev_err(&c->pdev->dev,
532 "Couldn't DMA map a %d byte buffer\n",
533 count);
534 return -1;
535 }
536
537 omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S16,
538 count / 2, 1, 0, 0, 0);
539 omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
540 dma_src, 0, 0);
541 omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
542 dma_dst, 0, 0);
543
544 INIT_COMPLETION(c->dma_done);
545 omap_start_dma(c->dma_channel);
546 wait_for_completion(&c->dma_done);
547
Mika Westerberg4a70b7d2010-03-24 12:10:48 +0200548 dma_unmap_single(&c->pdev->dev, dma_src, count, DMA_TO_DEVICE);
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300549
550 return 0;
551}
552
553#else
554
555int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
556 unsigned char *buffer, int offset,
557 size_t count);
558
559int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
560 const unsigned char *buffer,
561 int offset, size_t count);
562
563#endif
564
565static struct platform_driver omap2_onenand_driver;
566
567static int __adjust_timing(struct device *dev, void *data)
568{
569 int ret = 0;
570 struct omap2_onenand *c;
571
572 c = dev_get_drvdata(dev);
573
574 BUG_ON(c->setup == NULL);
575
576 /* DMA is not in use so this is all that is needed */
577 /* Revisit for OMAP3! */
578 ret = c->setup(c->onenand.base, c->freq);
579
580 return ret;
581}
582
583int omap2_onenand_rephase(void)
584{
585 return driver_for_each_device(&omap2_onenand_driver.driver, NULL,
586 NULL, __adjust_timing);
587}
588
Mika Korhonend3412db2009-05-21 23:09:42 +0300589static void omap2_onenand_shutdown(struct platform_device *pdev)
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300590{
591 struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
592
593 /* With certain content in the buffer RAM, the OMAP boot ROM code
594 * can recognize the flash chip incorrectly. Zero it out before
595 * soft reset.
596 */
597 memset((__force void *)c->onenand.base, 0, ONENAND_BUFRAM_SIZE);
598}
599
600static int __devinit omap2_onenand_probe(struct platform_device *pdev)
601{
602 struct omap_onenand_platform_data *pdata;
603 struct omap2_onenand *c;
604 int r;
605
606 pdata = pdev->dev.platform_data;
607 if (pdata == NULL) {
608 dev_err(&pdev->dev, "platform data missing\n");
609 return -ENODEV;
610 }
611
612 c = kzalloc(sizeof(struct omap2_onenand), GFP_KERNEL);
613 if (!c)
614 return -ENOMEM;
615
616 init_completion(&c->irq_done);
617 init_completion(&c->dma_done);
618 c->gpmc_cs = pdata->cs;
619 c->gpio_irq = pdata->gpio_irq;
620 c->dma_channel = pdata->dma_channel;
621 if (c->dma_channel < 0) {
622 /* if -1, don't use DMA */
623 c->gpio_irq = 0;
624 }
625
626 r = gpmc_cs_request(c->gpmc_cs, ONENAND_IO_SIZE, &c->phys_base);
627 if (r < 0) {
628 dev_err(&pdev->dev, "Cannot request GPMC CS\n");
629 goto err_kfree;
630 }
631
632 if (request_mem_region(c->phys_base, ONENAND_IO_SIZE,
633 pdev->dev.driver->name) == NULL) {
634 dev_err(&pdev->dev, "Cannot reserve memory region at 0x%08lx, "
635 "size: 0x%x\n", c->phys_base, ONENAND_IO_SIZE);
636 r = -EBUSY;
637 goto err_free_cs;
638 }
639 c->onenand.base = ioremap(c->phys_base, ONENAND_IO_SIZE);
640 if (c->onenand.base == NULL) {
641 r = -ENOMEM;
642 goto err_release_mem_region;
643 }
644
645 if (pdata->onenand_setup != NULL) {
646 r = pdata->onenand_setup(c->onenand.base, c->freq);
647 if (r < 0) {
648 dev_err(&pdev->dev, "Onenand platform setup failed: "
649 "%d\n", r);
650 goto err_iounmap;
651 }
652 c->setup = pdata->onenand_setup;
653 }
654
655 if (c->gpio_irq) {
Jarkko Nikula73069e32009-01-15 13:09:52 +0200656 if ((r = gpio_request(c->gpio_irq, "OneNAND irq")) < 0) {
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300657 dev_err(&pdev->dev, "Failed to request GPIO%d for "
658 "OneNAND\n", c->gpio_irq);
659 goto err_iounmap;
660 }
David Brownell40e39252008-12-10 17:35:26 -0800661 gpio_direction_input(c->gpio_irq);
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300662
David Brownell15f74b02008-12-10 17:35:26 -0800663 if ((r = request_irq(gpio_to_irq(c->gpio_irq),
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300664 omap2_onenand_interrupt, IRQF_TRIGGER_RISING,
665 pdev->dev.driver->name, c)) < 0)
666 goto err_release_gpio;
667 }
668
669 if (c->dma_channel >= 0) {
670 r = omap_request_dma(0, pdev->dev.driver->name,
671 omap2_onenand_dma_cb, (void *) c,
672 &c->dma_channel);
673 if (r == 0) {
674 omap_set_dma_write_mode(c->dma_channel,
675 OMAP_DMA_WRITE_NON_POSTED);
676 omap_set_dma_src_data_pack(c->dma_channel, 1);
677 omap_set_dma_src_burst_mode(c->dma_channel,
678 OMAP_DMA_DATA_BURST_8);
679 omap_set_dma_dest_data_pack(c->dma_channel, 1);
680 omap_set_dma_dest_burst_mode(c->dma_channel,
681 OMAP_DMA_DATA_BURST_8);
682 } else {
683 dev_info(&pdev->dev,
684 "failed to allocate DMA for OneNAND, "
685 "using PIO instead\n");
686 c->dma_channel = -1;
687 }
688 }
689
690 dev_info(&pdev->dev, "initializing on CS%d, phys base 0x%08lx, virtual "
691 "base %p\n", c->gpmc_cs, c->phys_base,
692 c->onenand.base);
693
694 c->pdev = pdev;
Kay Sievers475b44c2009-01-06 10:44:38 -0800695 c->mtd.name = dev_name(&pdev->dev);
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300696 c->mtd.priv = &c->onenand;
697 c->mtd.owner = THIS_MODULE;
698
David Brownell87f39f02009-03-26 00:42:50 -0700699 c->mtd.dev.parent = &pdev->dev;
700
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300701 if (c->dma_channel >= 0) {
702 struct onenand_chip *this = &c->onenand;
703
704 this->wait = omap2_onenand_wait;
705 if (cpu_is_omap34xx()) {
706 this->read_bufferram = omap3_onenand_read_bufferram;
707 this->write_bufferram = omap3_onenand_write_bufferram;
708 } else {
709 this->read_bufferram = omap2_onenand_read_bufferram;
710 this->write_bufferram = omap2_onenand_write_bufferram;
711 }
712 }
713
714 if ((r = onenand_scan(&c->mtd, 1)) < 0)
715 goto err_release_dma;
716
717 switch ((c->onenand.version_id >> 4) & 0xf) {
718 case 0:
719 c->freq = 40;
720 break;
721 case 1:
722 c->freq = 54;
723 break;
724 case 2:
725 c->freq = 66;
726 break;
727 case 3:
728 c->freq = 83;
729 break;
730 }
731
732#ifdef CONFIG_MTD_PARTITIONS
733 if (pdata->parts != NULL)
734 r = add_mtd_partitions(&c->mtd, pdata->parts,
735 pdata->nr_parts);
736 else
737#endif
738 r = add_mtd_device(&c->mtd);
739 if (r < 0)
740 goto err_release_onenand;
741
742 platform_set_drvdata(pdev, c);
743
744 return 0;
745
746err_release_onenand:
747 onenand_release(&c->mtd);
748err_release_dma:
749 if (c->dma_channel != -1)
750 omap_free_dma(c->dma_channel);
751 if (c->gpio_irq)
David Brownell15f74b02008-12-10 17:35:26 -0800752 free_irq(gpio_to_irq(c->gpio_irq), c);
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300753err_release_gpio:
754 if (c->gpio_irq)
Jarkko Nikula73069e32009-01-15 13:09:52 +0200755 gpio_free(c->gpio_irq);
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300756err_iounmap:
757 iounmap(c->onenand.base);
758err_release_mem_region:
759 release_mem_region(c->phys_base, ONENAND_IO_SIZE);
760err_free_cs:
761 gpmc_cs_free(c->gpmc_cs);
762err_kfree:
763 kfree(c);
764
765 return r;
766}
767
768static int __devexit omap2_onenand_remove(struct platform_device *pdev)
769{
770 struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
771
772 BUG_ON(c == NULL);
773
774#ifdef CONFIG_MTD_PARTITIONS
775 if (c->parts)
776 del_mtd_partitions(&c->mtd);
777 else
778 del_mtd_device(&c->mtd);
779#else
780 del_mtd_device(&c->mtd);
781#endif
782
783 onenand_release(&c->mtd);
784 if (c->dma_channel != -1)
785 omap_free_dma(c->dma_channel);
786 omap2_onenand_shutdown(pdev);
787 platform_set_drvdata(pdev, NULL);
788 if (c->gpio_irq) {
David Brownell15f74b02008-12-10 17:35:26 -0800789 free_irq(gpio_to_irq(c->gpio_irq), c);
Jarkko Nikula73069e32009-01-15 13:09:52 +0200790 gpio_free(c->gpio_irq);
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300791 }
792 iounmap(c->onenand.base);
793 release_mem_region(c->phys_base, ONENAND_IO_SIZE);
Mika Korhonen3cae1cc2009-06-25 15:32:19 +0300794 gpmc_cs_free(c->gpmc_cs);
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300795 kfree(c);
796
797 return 0;
798}
799
800static struct platform_driver omap2_onenand_driver = {
801 .probe = omap2_onenand_probe,
Mika Korhonend3412db2009-05-21 23:09:42 +0300802 .remove = __devexit_p(omap2_onenand_remove),
Adrian Hunter36cd4fb2008-08-06 10:08:46 +0300803 .shutdown = omap2_onenand_shutdown,
804 .driver = {
805 .name = DRIVER_NAME,
806 .owner = THIS_MODULE,
807 },
808};
809
810static int __init omap2_onenand_init(void)
811{
812 printk(KERN_INFO "OneNAND driver initializing\n");
813 return platform_driver_register(&omap2_onenand_driver);
814}
815
816static void __exit omap2_onenand_exit(void)
817{
818 platform_driver_unregister(&omap2_onenand_driver);
819}
820
821module_init(omap2_onenand_init);
822module_exit(omap2_onenand_exit);
823
824MODULE_ALIAS(DRIVER_NAME);
825MODULE_LICENSE("GPL");
826MODULE_AUTHOR("Jarkko Lavinen <jarkko.lavinen@nokia.com>");
827MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP2 / OMAP3");