move drivers/nand to drivers/mtd/nand
[barebox-mini2440.git] / drivers / mtd / nand / nand_omap_gpmc.c
blobc6647e56ede65766725d658d8aa3504b330307af
1 /**
2 * @file
3 * @brief Provide Generic GPMC NAND implementation for OMAP platforms
5 * FileName: arch/arm/mach-omap/gpmc_nand.c
7 * GPMC has a NAND controller inbuilt. This provides a generic implementation
8 * for board files to register a nand device. drivers/nand/nand_base.c takes
9 * care of identifing the type of device, size etc.
11 * A typical device registration is as follows:
13 * @code
14 * static struct device_d my_nand_device = {
15 * .name = "gpmc_nand",
16 * .id = some identifier you need to show.. e.g. "gpmc_nand0"
17 * .map_base = GPMC base address
18 * .size = GPMC address map size.
19 * .platform_data = platform data - required - explained below
20 * };
21 * platform data required:
22 * static struct gpmc_nand_platform_data nand_plat = {
23 * .cs = give the chip select of the device
24 * .device_width = what is the width of the device 8 or 16?
25 * .max_timeout = delay desired for operation
26 * .wait_mon_pin = do you use wait monitoring? if so wait pin
27 * .plat_options = platform options.
28 * NAND_HWECC_ENABLE/DISABLE - hw ecc enable/disable
29 * NAND_WAITPOL_LOW/HIGH - wait pin polarity
30 * .oob = if you would like to replace oob with a custom OOB.
31 * .nand_setup = if you would like a special setup function to be called
32 * .priv = any params you'd like to save(e.g. like nand_setup to use)
33 *};
34 * then in your code, you'd device_register(&my_nand_device);
35 * @endcode
37 * Note:
38 * @li Enable CONFIG_NAND_OMAP_GPMC_HWECC in menuconfig to get H/w ECC support
39 * @li You may choose to register two "devices" for the same CS to get BOTH
40 * hwecc and swecc devices.
41 * @li You can choose to have your own OOB definition for compliance with ROM
42 * code organization - only if you dont want to use NAND's default oob layout.
43 * see GPMC_NAND_ECC_LP_x8_LAYOUT etc..
45 * @see gpmc_nand_platform_data
46 * @warning Remember to initialize GPMC before initializing the nand dev.
49 * (C) Copyright 2008
50 * Texas Instruments, <www.ti.com>
51 * Nishanth Menon <x0nishan@ti.com>
53 * Based on:
54 * drivers/mtd/nand/omap2.c from linux kernel
56 * Copyright (c) 2004 Texas Instruments, Jian Zhang <jzhang@ti.com>
57 * Copyright (c) 2004 Micron Technology Inc.
58 * Copyright (c) 2004 David Brownell
60 * This program is free software; you can redistribute it and/or modify
61 * it under the terms of the GNU General Public License version 2 as
62 * published by the Free Software Foundation.
65 #include <common.h>
66 #include <errno.h>
67 #include <init.h>
68 #include <driver.h>
69 #include <malloc.h>
70 #include <clock.h>
71 #include <linux/mtd/mtd.h>
72 #include <linux/mtd/nand.h>
73 #include <linux/mtd/nand_ecc.h>
74 #include <asm/io.h>
75 #include <mach/silicon.h>
76 #include <mach/gpmc.h>
77 #include <mach/gpmc_nand.h>
79 /* Enable me to get tons of debug messages -for use without jtag */
80 #if 0
81 #define gpmcnand_dbg(FORMAT, ARGS...) fprintf(stdout,\
82 "gpmc_nand:%s:%d:Entry:"FORMAT"\n",\
83 __func__, __LINE__, ARGS)
84 #else
85 #define gpmcnand_dbg(FORMAT, ARGS...)
86 #endif
87 #define gpmcnand_err(ARGS...) fprintf(stderr, "omapnand: " ARGS);
89 /** internal structure maintained for nand information */
90 struct gpmc_nand_info {
91 struct nand_hw_control controller;
92 struct device_d *pdev;
93 struct gpmc_nand_platform_data *pdata;
94 struct nand_chip nand;
95 struct mtd_info minfo;
96 int gpmc_cs;
97 void *gpmc_command;
98 void *gpmc_address;
99 void *gpmc_data;
100 unsigned long gpmc_base;
101 unsigned char wait_mon_mask;
102 uint64_t timeout;
103 unsigned inuse:1;
104 unsigned wait_pol:1;
105 #ifdef CONFIG_NAND_OMAP_GPMC_HWECC
106 unsigned char ecc_parity_pairs;
107 unsigned int ecc_config;
108 #endif
112 * @brief calls the platform specific dev_ready functionds
114 * @param mtd - mtd info structure
116 * @return
118 static int omap_dev_ready(struct mtd_info *mtd)
120 struct nand_chip *nand = (struct nand_chip *)(mtd->priv);
121 struct gpmc_nand_info *oinfo = (struct gpmc_nand_info *)(nand->priv);
122 uint64_t start = get_time_ns();
123 unsigned long comp;
125 gpmcnand_dbg("mtd=%x", (unsigned int)mtd);
126 /* What do we mean by assert and de-assert? */
127 comp = (oinfo->wait_pol == NAND_WAITPOL_HIGH) ?
128 oinfo->wait_mon_mask : 0x0;
129 while (1) {
130 /* Breakout condition */
131 if (is_timeout(start, oinfo->timeout)) {
132 gpmcnand_err("timedout\n");
133 return -ETIMEDOUT;
135 /* if the wait is released, we are good to go */
136 if (comp ==
137 (readl(oinfo->gpmc_base + GPMC_STATUS) &&
138 oinfo->wait_mon_mask))
139 break;
141 return 0;
145 * @brief This function will enable or disable the Write Protect feature on
146 * NAND device. GPMC has a single WP bit for all CS devices..
148 * @param oinfo omap nand info
149 * @param mode 0-disable else enable
151 * @return none
153 static void gpmc_nand_wp(struct gpmc_nand_info *oinfo, int mode)
155 unsigned long config = readl(oinfo->gpmc_base + GPMC_CFG);
157 gpmcnand_dbg("mode=%x", mode);
158 if (mode)
159 config &= ~(NAND_WP_BIT); /* WP is ON */
160 else
161 config |= (NAND_WP_BIT); /* WP is OFF */
163 writel(config, oinfo->gpmc_base + GPMC_CFG);
167 * @brief respond to hw event change request
169 * MTD layer uses NAND_CTRL_CLE etc to control selection of the latch
170 * we hoodwink by changing the R and W registers according to the state
171 * we are requested.
173 * @param mtd - mtd info structure
174 * @param cmd command mtd layer is requesting
176 * @return none
178 static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
180 struct nand_chip *nand = (struct nand_chip *)(mtd->priv);
181 struct gpmc_nand_info *oinfo = (struct gpmc_nand_info *)(nand->priv);
182 gpmcnand_dbg("mtd=%x nand=%x cmd=%x ctrl = %x", (unsigned int)mtd, nand,
183 cmd, ctrl);
184 switch (ctrl) {
185 case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
186 nand->IO_ADDR_W = oinfo->gpmc_command;
187 nand->IO_ADDR_R = oinfo->gpmc_data;
188 break;
190 case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
191 nand->IO_ADDR_W = oinfo->gpmc_address;
192 nand->IO_ADDR_R = oinfo->gpmc_data;
193 break;
195 case NAND_CTRL_CHANGE | NAND_NCE:
196 nand->IO_ADDR_W = oinfo->gpmc_data;
197 nand->IO_ADDR_R = oinfo->gpmc_data;
198 break;
201 if (cmd != NAND_CMD_NONE)
202 writeb(cmd, nand->IO_ADDR_W);
203 return;
206 #ifdef CONFIG_NAND_OMAP_GPMC_HWECC
209 * @brief This function will generate true ECC value, which can be used
210 * when correcting data read from NAND flash memory core
212 * @param ecc_buf buffer to store ecc code
214 * @return re-formatted ECC value
216 static unsigned int gen_true_ecc(u8 *ecc_buf)
218 gpmcnand_dbg("ecc_buf=%x 1, 2 3 = %x %x %x", (unsigned int)ecc_buf,
219 ecc_buf[0], ecc_buf[1], ecc_buf[2]);
220 return ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xF0) << 20) |
221 ((ecc_buf[2] & 0x0F) << 8);
225 * @brief Compares the ecc read from nand spare area with ECC
226 * registers values and corrects one bit error if it has occured
227 * Further details can be had from OMAP TRM and the following selected links:
228 * http://en.wikipedia.org/wiki/Hamming_code
229 * http://www.cs.utexas.edu/users/plaxton/c/337/05f/slides/ErrorCorrection-4.pdf
231 * @param mtd - mtd info structure
232 * @param dat page data
233 * @param read_ecc ecc readback
234 * @param calc_ecc calculated ecc (from reg)
236 * @return 0 if data is OK or corrected, else returns -1
238 static int omap_correct_data(struct mtd_info *mtd, uint8_t *dat,
239 uint8_t *read_ecc, uint8_t *calc_ecc)
241 unsigned int orig_ecc, new_ecc, res, hm;
242 unsigned short parity_bits, byte;
243 unsigned char bit;
244 struct nand_chip *nand = (struct nand_chip *)(mtd->priv);
245 struct gpmc_nand_info *oinfo = (struct gpmc_nand_info *)(nand->priv);
247 gpmcnand_dbg("mtd=%x dat=%x read_ecc=%x calc_ecc=%x", (unsigned int)mtd,
248 (unsigned int)dat, (unsigned int)read_ecc,
249 (unsigned int)calc_ecc);
251 /* Regenerate the orginal ECC */
252 orig_ecc = gen_true_ecc(read_ecc);
253 new_ecc = gen_true_ecc(calc_ecc);
254 /* Get the XOR of real ecc */
255 res = orig_ecc ^ new_ecc;
256 if (res) {
257 /* Get the hamming width */
258 hm = hweight32(res);
259 /* Single bit errors can be corrected! */
260 if (hm == oinfo->ecc_parity_pairs) {
261 /* Correctable data! */
262 parity_bits = res >> 16;
263 bit = (parity_bits & 0x7);
264 byte = (parity_bits >> 3) & 0x1FF;
265 /* Flip the bit to correct */
266 dat[byte] ^= (0x1 << bit);
268 } else if (hm == 1) {
269 gpmcnand_err("Ecc is wrong\n");
270 /* ECC itself is corrupted */
271 return 2;
272 } else {
273 gpmcnand_err("bad compare! failed\n");
274 /* detected 2 bit error */
275 return -1;
278 return 0;
282 * @brief Using noninverted ECC can be considered ugly since writing a blank
283 * page ie. padding will clear the ECC bytes. This is no problem as long
284 * nobody is trying to write data on the seemingly unused page. Reading
285 * an erased page will produce an ECC mismatch between generated and read
286 * ECC bytes that has to be dealt with separately.
288 * @param mtd - mtd info structure
289 * @param dat data being written
290 * @param ecc_code ecc code returned back to nand layer
292 * @return 0
294 static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
295 uint8_t *ecc_code)
297 struct nand_chip *nand = (struct nand_chip *)(mtd->priv);
298 struct gpmc_nand_info *oinfo = (struct gpmc_nand_info *)(nand->priv);
299 unsigned int val;
300 gpmcnand_dbg("mtd=%x dat=%x ecc_code=%x", (unsigned int)mtd,
301 (unsigned int)dat, (unsigned int)ecc_code);
302 debug("ecc 0 1 2 = %x %x %x", ecc_code[0], ecc_code[1], ecc_code[2]);
304 /* Since we smartly tell mtd driver to use eccsize of 512, only
305 * ECC Reg1 will be used.. we just read that */
306 val = readl(oinfo->gpmc_base + GPMC_ECC1_RESULT);
307 ecc_code[0] = val & 0xFF;
308 ecc_code[1] = (val >> 16) & 0xFF;
309 ecc_code[2] = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
311 /* Stop reading anymore ECC vals and clear old results
312 * enable will be called if more reads are required */
313 writel(0x000, oinfo->gpmc_base + GPMC_ECC_CONFIG);
314 return 0;
318 * omap_enable_ecc - This function enables the hardware ecc functionality
319 * @param mtd - mtd info structure
320 * @param mode - Read/Write mode
322 static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
324 struct nand_chip *nand = (struct nand_chip *)(mtd->priv);
325 struct gpmc_nand_info *oinfo = (struct gpmc_nand_info *)(nand->priv);
326 gpmcnand_dbg("mtd=%x mode=%x", (unsigned int)mtd, mode);
327 switch (mode) {
328 case NAND_ECC_READ:
329 case NAND_ECC_WRITE:
330 /* Clear the ecc result registers
331 * select ecc reg as 1
333 writel(0x101, oinfo->gpmc_base + GPMC_ECC_CONTROL);
334 /* Size 0 = 0xFF, Size1 is 0xFF - both are 512 bytes
335 * tell all regs to generate size0 sized regs
336 * we just have a single ECC engine for all CS
338 writel(0x3FCFF000, oinfo->gpmc_base +
339 GPMC_ECC_SIZE_CONFIG);
340 writel(oinfo->ecc_config, oinfo->gpmc_base +
341 GPMC_ECC_CONFIG);
342 break;
343 default:
344 gpmcnand_err("Error: Unrecognized Mode[%d]!\n", mode);
345 break;
348 #endif /* CONFIG_NAND_OMAP_GPMC_HWECC */
351 * @brief nand device probe.
353 * @param pdev -matching device
355 * @return -failure reason or give 0
357 static int gpmc_nand_probe(struct device_d *pdev)
359 struct gpmc_nand_info *oinfo;
360 struct gpmc_nand_platform_data *pdata;
361 struct nand_chip *nand;
362 struct mtd_info *minfo;
363 unsigned long cs_base;
364 int err;
366 gpmcnand_dbg("pdev=%x", (unsigned int)pdev);
367 pdata = (struct gpmc_nand_platform_data *)pdev->platform_data;
368 if (pdata == NULL) {
369 gpmcnand_err("platform data missing\n");
370 return -ENODEV;
373 oinfo = calloc(1, sizeof(struct gpmc_nand_info));
374 if (!oinfo) {
375 gpmcnand_err("oinfo alloc failed!\n");
376 return -ENOMEM;
379 /* fill up my data structures */
380 oinfo->pdev = pdev;
381 oinfo->pdata = pdata;
382 pdev->platform_data = (void *)oinfo;
384 nand = &oinfo->nand;
385 nand->priv = (void *)oinfo;
387 minfo = &oinfo->minfo;
388 minfo->priv = (void *)nand;
390 if (pdata->cs >= GPMC_NUM_CS) {
391 gpmcnand_err("Invalid CS!\n");
392 err = -EINVAL;
393 goto out_release_mem;
395 /* Setup register specific data */
396 oinfo->gpmc_cs = pdata->cs;
397 oinfo->gpmc_base = pdev->map_base;
398 cs_base = oinfo->gpmc_base + GPMC_CONFIG1_0 +
399 (pdata->cs * GPMC_CONFIG_CS_SIZE);
400 oinfo->gpmc_command = (void *)(cs_base + GPMC_CS_NAND_COMMAND);
401 oinfo->gpmc_address = (void *)(cs_base + GPMC_CS_NAND_ADDRESS);
402 oinfo->gpmc_data = (void *)(cs_base + GPMC_CS_NAND_DATA);
403 oinfo->timeout = pdata->max_timeout;
404 debug("GPMC Details:\n"
405 "GPMC BASE=%x\n"
406 "CMD=%x\n"
407 "ADDRESS=%x\n"
408 "DATA=%x\n"
409 "CS_BASE=%x\n",
410 oinfo->gpmc_base, oinfo->gpmc_command,
411 oinfo->gpmc_address, oinfo->gpmc_data, cs_base);
413 /* If we are 16 bit dev, our gpmc config tells us that */
414 if ((readl(cs_base) & 0x3000) == 0x1000) {
415 debug("16 bit dev\n");
416 nand->options |= NAND_BUSWIDTH_16;
419 /* Same data register for in and out */
420 nand->IO_ADDR_W = nand->IO_ADDR_R = (void *)oinfo->gpmc_data;
422 * If RDY/BSY line is connected to OMAP then use the omap ready
423 * function and the generic nand_wait function which reads the
424 * status register after monitoring the RDY/BSY line. Otherwise
425 * use a standard chip delay which is slightly more than tR
426 * (AC Timing) of the NAND device and read the status register
427 * until you get a failure or success
429 if (pdata->wait_mon_pin > 4) {
430 gpmcnand_err("Invalid wait monitoring pin\n");
431 err = -EINVAL;
432 goto out_release_mem;
434 if (pdata->wait_mon_pin) {
435 /* Set up the wait monitoring mask
436 * This is GPMC_STATUS reg relevant */
437 oinfo->wait_mon_mask = (0x1 << (pdata->wait_mon_pin - 1)) << 8;
438 oinfo->wait_pol = (pdata->plat_options & NAND_WAITPOL_MASK);
439 nand->dev_ready = omap_dev_ready;
440 nand->chip_delay = 0;
441 } else {
442 /* use the default nand_wait function */
443 nand->chip_delay = 50;
446 /* Use default cmdfunc */
447 /* nand cmd control */
448 nand->cmd_ctrl = omap_hwcontrol;
450 /* Dont do a bbt scan at the start */
451 nand->options |= NAND_SKIP_BBTSCAN;
453 /* State my controller */
454 nand->controller = &oinfo->controller;
456 /* if a different placement scheme is requested */
457 if (pdata->oob)
458 nand->ecc.layout = pdata->oob;
460 #ifdef CONFIG_NAND_OMAP_GPMC_HWECC
461 if (pdata->plat_options & NAND_HWECC_ENABLE) {
462 /* Program how many columns we expect+
463 * enable the cs we want and enable the engine
465 oinfo->ecc_config = (pdata->cs << 1) |
466 ((nand->options & NAND_BUSWIDTH_16) ?
467 (0x1 << 7) : 0x0) | 0x1;
468 nand->ecc.hwctl = omap_enable_hwecc;
469 nand->ecc.calculate = omap_calculate_ecc;
470 nand->ecc.correct = omap_correct_data;
471 nand->ecc.mode = NAND_ECC_HW;
472 nand->ecc.size = 512;
473 nand->ecc.bytes = 3;
474 nand->ecc.steps = nand->ecc.layout->eccbytes / nand->ecc.bytes;
475 oinfo->ecc_parity_pairs = 12;
476 } else
477 #endif
478 nand->ecc.mode = NAND_ECC_SOFT;
480 /* All information is ready.. now lets call setup, if present */
481 if (pdata->nand_setup) {
482 err = pdata->nand_setup(pdata);
483 if (err) {
484 gpmcnand_err("pdataform setup failed\n");
485 goto out_release_mem;
488 /* Remove write protection */
489 gpmc_nand_wp(oinfo, 0);
491 /* we do not know what state of device we have is, so
492 * Send a reset to the device
493 * 8 bit write will work on 16 and 8 bit devices
495 writeb(NAND_CMD_RESET, oinfo->gpmc_command);
496 mdelay(1);
498 /* In normal mode, we scan to get just the device
499 * presence and then to get the device geometry
501 if (nand_scan(minfo, 1)) {
502 gpmcnand_err("device scan failed\n");
503 err = -ENXIO;
504 goto out_release_mem;
507 /* We are all set to register with the system now! */
508 err = add_mtd_device(minfo);
509 if (err) {
510 gpmcnand_err("device registration failed\n");
511 goto out_release_mem;
513 return 0;
515 out_release_mem:
516 if (oinfo)
517 free(oinfo);
519 gpmcnand_err("Failed!!\n");
520 return err;
523 /** GMPC nand driver -> device registered by platforms */
524 static struct driver_d gpmc_nand_driver = {
525 .name = "gpmc_nand",
526 .probe = gpmc_nand_probe,
529 static int gpmc_nand_init(void)
531 return register_driver(&gpmc_nand_driver);
534 device_initcall(gpmc_nand_init);