2 * drivers/mtd/nand/tx4938ndfmc.c
5 * This is a device driver for the NAND flash device connected to
6 * TX4938 internal NAND Memory Controller.
7 * TX4938 NDFMC is almost same as TX4925 NDFMC, but register size are 64 bit.
9 * Author: source@mvista.com
11 * Based on spia.c by Steven J. Hill
13 * $Id: tx4938ndfmc.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $
15 * Copyright (C) 2000-2001 Toshiba Corporation
17 * 2003 (c) MontaVista Software, Inc. This file is licensed under the
18 * terms of the GNU General Public License version 2. This program is
19 * licensed "as is" without any warranty of any kind, whether express
22 #include <linux/config.h>
23 #include <linux/slab.h>
24 #include <linux/init.h>
25 #include <linux/module.h>
26 #include <linux/mtd/mtd.h>
27 #include <linux/mtd/nand.h>
28 #include <linux/mtd/nand_ecc.h>
29 #include <linux/mtd/partitions.h>
31 #include <asm/bootinfo.h>
32 #include <linux/delay.h>
33 #include <asm/tx4938/rbtx4938.h>
35 extern struct nand_oobinfo jffs2_oobinfo
;
38 * MTD structure for TX4938 NDFMC
40 static struct mtd_info
*tx4938ndfmc_mtd
;
43 * Define partitions for flash device
45 #define flush_wb() (void)tx4938_ndfmcptr->mcr;
47 #define NUM_PARTITIONS 3
48 #define NUMBER_OF_CIS_BLOCKS 24
49 #define SIZE_OF_BLOCK 0x00004000
50 #define NUMBER_OF_BLOCK_PER_ZONE 1024
51 #define SIZE_OF_ZONE (NUMBER_OF_BLOCK_PER_ZONE * SIZE_OF_BLOCK)
52 #ifndef CONFIG_MTD_CMDLINE_PARTS
54 * You can use the following sample of MTD partitions
55 * on the NAND Flash Memory 32MB or more.
57 * The following figure shows the image of the sample partition on
58 * the 32MB NAND Flash Memory.
61 * 0 +-----------------------------+ ------
63 * 24 +-----------------------------+ |
64 * | kernel image | | Zone 0
66 * +-----------------------------+ |
67 * 1023 | unused area | v
68 * +-----------------------------+ ------
75 * 2047 +-----------------------------+ ------
78 static struct mtd_partition partition_info
[NUM_PARTITIONS
] = {
80 .name
= "RBTX4938 CIS Area",
82 .size
= (NUMBER_OF_CIS_BLOCKS
* SIZE_OF_BLOCK
),
83 .mask_flags
= MTD_WRITEABLE
/* This partition is NOT writable */
86 .name
= "RBTX4938 kernel image",
87 .offset
= MTDPART_OFS_APPEND
,
88 .size
= 8 * 0x00100000, /* 8MB (Depends on size of kernel image) */
89 .mask_flags
= MTD_WRITEABLE
/* This partition is NOT writable */
92 .name
= "Root FS (JFFS2)",
93 .offset
= (0 + SIZE_OF_ZONE
), /* start address of next zone */
94 .size
= MTDPART_SIZ_FULL
99 static void tx4938ndfmc_hwcontrol(struct mtd_info
*mtd
, int cmd
)
102 case NAND_CTL_SETCLE
:
103 tx4938_ndfmcptr
->mcr
|= TX4938_NDFMCR_CLE
;
105 case NAND_CTL_CLRCLE
:
106 tx4938_ndfmcptr
->mcr
&= ~TX4938_NDFMCR_CLE
;
108 case NAND_CTL_SETALE
:
109 tx4938_ndfmcptr
->mcr
|= TX4938_NDFMCR_ALE
;
111 case NAND_CTL_CLRALE
:
112 tx4938_ndfmcptr
->mcr
&= ~TX4938_NDFMCR_ALE
;
114 /* TX4938_NDFMCR_CE bit is 0:high 1:low */
115 case NAND_CTL_SETNCE
:
116 tx4938_ndfmcptr
->mcr
|= TX4938_NDFMCR_CE
;
118 case NAND_CTL_CLRNCE
:
119 tx4938_ndfmcptr
->mcr
&= ~TX4938_NDFMCR_CE
;
122 tx4938_ndfmcptr
->mcr
|= TX4938_NDFMCR_WE
;
125 tx4938_ndfmcptr
->mcr
&= ~TX4938_NDFMCR_WE
;
129 static int tx4938ndfmc_dev_ready(struct mtd_info
*mtd
)
132 return !(tx4938_ndfmcptr
->sr
& TX4938_NDFSR_BUSY
);
134 static void tx4938ndfmc_calculate_ecc(struct mtd_info
*mtd
, const u_char
*dat
, u_char
*ecc_code
)
136 u32 mcr
= tx4938_ndfmcptr
->mcr
;
137 mcr
&= ~TX4938_NDFMCR_ECC_ALL
;
138 tx4938_ndfmcptr
->mcr
= mcr
| TX4938_NDFMCR_ECC_OFF
;
139 tx4938_ndfmcptr
->mcr
= mcr
| TX4938_NDFMCR_ECC_READ
;
140 ecc_code
[1] = tx4938_ndfmcptr
->dtr
;
141 ecc_code
[0] = tx4938_ndfmcptr
->dtr
;
142 ecc_code
[2] = tx4938_ndfmcptr
->dtr
;
143 tx4938_ndfmcptr
->mcr
= mcr
| TX4938_NDFMCR_ECC_OFF
;
145 static void tx4938ndfmc_enable_hwecc(struct mtd_info
*mtd
, int mode
)
147 u32 mcr
= tx4938_ndfmcptr
->mcr
;
148 mcr
&= ~TX4938_NDFMCR_ECC_ALL
;
149 tx4938_ndfmcptr
->mcr
= mcr
| TX4938_NDFMCR_ECC_RESET
;
150 tx4938_ndfmcptr
->mcr
= mcr
| TX4938_NDFMCR_ECC_OFF
;
151 tx4938_ndfmcptr
->mcr
= mcr
| TX4938_NDFMCR_ECC_ON
;
154 static u_char
tx4938ndfmc_nand_read_byte(struct mtd_info
*mtd
)
156 struct nand_chip
*this = mtd
->priv
;
157 return tx4938_read_nfmc(this->IO_ADDR_R
);
160 static void tx4938ndfmc_nand_write_byte(struct mtd_info
*mtd
, u_char byte
)
162 struct nand_chip
*this = mtd
->priv
;
163 tx4938_write_nfmc(byte
, this->IO_ADDR_W
);
166 static void tx4938ndfmc_nand_write_buf(struct mtd_info
*mtd
, const u_char
*buf
, int len
)
169 struct nand_chip
*this = mtd
->priv
;
171 for (i
=0; i
<len
; i
++)
172 tx4938_write_nfmc(buf
[i
], this->IO_ADDR_W
);
175 static void tx4938ndfmc_nand_read_buf(struct mtd_info
*mtd
, u_char
*buf
, int len
)
178 struct nand_chip
*this = mtd
->priv
;
180 for (i
=0; i
<len
; i
++)
181 buf
[i
] = tx4938_read_nfmc(this->IO_ADDR_R
);
184 static int tx4938ndfmc_nand_verify_buf(struct mtd_info
*mtd
, const u_char
*buf
, int len
)
187 struct nand_chip
*this = mtd
->priv
;
189 for (i
=0; i
<len
; i
++)
190 if (buf
[i
] != tx4938_read_nfmc(this->IO_ADDR_R
))
197 * Send command to NAND device
199 static void tx4938ndfmc_nand_command (struct mtd_info
*mtd
, unsigned command
, int column
, int page_addr
)
201 register struct nand_chip
*this = mtd
->priv
;
203 /* Begin command latch cycle */
204 this->hwcontrol(mtd
, NAND_CTL_SETCLE
);
206 * Write out the command to the device.
208 if (command
== NAND_CMD_SEQIN
) {
211 if (column
>= mtd
->oobblock
) {
213 column
-= mtd
->oobblock
;
214 readcmd
= NAND_CMD_READOOB
;
215 } else if (column
< 256) {
216 /* First 256 bytes --> READ0 */
217 readcmd
= NAND_CMD_READ0
;
220 readcmd
= NAND_CMD_READ1
;
222 this->write_byte(mtd
, readcmd
);
224 this->write_byte(mtd
, command
);
226 /* Set ALE and clear CLE to start address cycle */
227 this->hwcontrol(mtd
, NAND_CTL_CLRCLE
);
229 if (column
!= -1 || page_addr
!= -1) {
230 this->hwcontrol(mtd
, NAND_CTL_SETALE
);
232 /* Serially input address */
234 this->write_byte(mtd
, column
);
235 if (page_addr
!= -1) {
236 this->write_byte(mtd
, (unsigned char) (page_addr
& 0xff));
237 this->write_byte(mtd
, (unsigned char) ((page_addr
>> 8) & 0xff));
238 /* One more address cycle for higher density devices */
239 if (mtd
->size
& 0x0c000000)
240 this->write_byte(mtd
, (unsigned char) ((page_addr
>> 16) & 0x0f));
242 /* Latch in address */
243 this->hwcontrol(mtd
, NAND_CTL_CLRALE
);
247 * program and erase have their own busy handlers
248 * status and sequential in needs no delay
252 case NAND_CMD_PAGEPROG
:
254 this->hwcontrol (mtd
, NAND_CTL_CLRWP
);
259 this->hwcontrol (mtd
, NAND_CTL_SETWP
);
262 case NAND_CMD_ERASE1
:
263 case NAND_CMD_ERASE2
:
264 case NAND_CMD_STATUS
:
270 this->hwcontrol(mtd
, NAND_CTL_SETCLE
);
271 this->write_byte(mtd
, NAND_CMD_STATUS
);
272 this->hwcontrol(mtd
, NAND_CTL_CLRCLE
);
273 while ( !(this->read_byte(mtd
) & 0x40));
276 /* This applies to read commands */
279 * If we don't have access to the busy pin, we apply the given
282 if (!this->dev_ready
) {
283 udelay (this->chip_delay
);
288 /* wait until command is processed */
289 while (!this->dev_ready(mtd
));
292 #ifdef CONFIG_MTD_CMDLINE_PARTS
293 extern int parse_cmdline_partitions(struct mtd_info
*master
, struct mtd_partition
**pparts
, char *);
296 * Main initialization routine
298 int __init
tx4938ndfmc_init (void)
300 struct nand_chip
*this;
301 int bsprt
= 0, hold
= 0xf, spw
= 0xf;
304 if ((*rbtx4938_piosel_ptr
& 0x0c) != 0x08) {
305 printk("TX4938 NDFMC: disabled by IOC PIOSEL\n");
310 spw
= 9 - 1; /* 8 GBUSCLK = 80ns (@ GBUSCLK 100MHz) */
312 if ((tx4938_ccfgptr
->pcfg
&
313 (TX4938_PCFG_ATA_SEL
|TX4938_PCFG_ISA_SEL
|TX4938_PCFG_NDF_SEL
))
314 != TX4938_PCFG_NDF_SEL
) {
315 printk("TX4938 NDFMC: disabled by PCFG.\n");
320 tx4938_ndfmcptr
->rstr
|= TX4938_NDFRSTR_RST
;
321 while (tx4938_ndfmcptr
->rstr
& TX4938_NDFRSTR_RST
)
323 /* setup BusSeparete, Hold Time, Strobe Pulse Width */
324 tx4938_ndfmcptr
->mcr
= bsprt
? TX4938_NDFMCR_BSPRT
: 0;
325 tx4938_ndfmcptr
->spr
= hold
<< 4 | spw
;
327 /* Allocate memory for MTD device structure and private data */
328 tx4938ndfmc_mtd
= kmalloc (sizeof(struct mtd_info
) + sizeof (struct nand_chip
),
330 if (!tx4938ndfmc_mtd
) {
331 printk ("Unable to allocate TX4938 NDFMC MTD device structure.\n");
335 /* Get pointer to private data */
336 this = (struct nand_chip
*) (&tx4938ndfmc_mtd
[1]);
338 /* Initialize structures */
339 memset((char *) tx4938ndfmc_mtd
, 0, sizeof(struct mtd_info
));
340 memset((char *) this, 0, sizeof(struct nand_chip
));
342 /* Link the private data with the MTD structure */
343 tx4938ndfmc_mtd
->priv
= this;
345 /* Set address of NAND IO lines */
346 this->IO_ADDR_R
= (unsigned long)&tx4938_ndfmcptr
->dtr
;
347 this->IO_ADDR_W
= (unsigned long)&tx4938_ndfmcptr
->dtr
;
348 this->hwcontrol
= tx4938ndfmc_hwcontrol
;
349 this->dev_ready
= tx4938ndfmc_dev_ready
;
350 this->calculate_ecc
= tx4938ndfmc_calculate_ecc
;
351 this->correct_data
= nand_correct_data
;
352 this->enable_hwecc
= tx4938ndfmc_enable_hwecc
;
353 this->eccmode
= NAND_ECC_HW3_256
;
354 this->chip_delay
= 100;
355 this->read_byte
= tx4938ndfmc_nand_read_byte
;
356 this->write_byte
= tx4938ndfmc_nand_write_byte
;
357 this->cmdfunc
= tx4938ndfmc_nand_command
;
358 this->write_buf
= tx4938ndfmc_nand_write_buf
;
359 this->read_buf
= tx4938ndfmc_nand_read_buf
;
360 this->verify_buf
= tx4938ndfmc_nand_verify_buf
;
362 /* Scan to find existance of the device */
363 if (nand_scan (tx4938ndfmc_mtd
, 1)) {
364 kfree (tx4938ndfmc_mtd
);
369 printk(KERN_INFO
"TX4938 NDFMC: write protected.\n");
370 tx4938ndfmc_mtd
->flags
&= ~(MTD_WRITEABLE
| MTD_ERASEABLE
);
373 #ifdef CONFIG_MTD_CMDLINE_PARTS
375 int mtd_parts_nb
= 0;
376 struct mtd_partition
*mtd_parts
= 0;
377 mtd_parts_nb
= parse_cmdline_partitions(tx4938ndfmc_mtd
, &mtd_parts
, "tx4938ndfmc");
378 if (mtd_parts_nb
> 0)
379 add_mtd_partitions(tx4938ndfmc_mtd
, mtd_parts
, mtd_parts_nb
);
381 add_mtd_device(tx4938ndfmc_mtd
);
384 add_mtd_partitions(tx4938ndfmc_mtd
, partition_info
, NUM_PARTITIONS
);
389 module_init(tx4938ndfmc_init
);
394 static void __exit
tx4938ndfmc_cleanup (void)
396 /* Release resources, unregister device */
397 nand_release (tx4938ndfmc_mtd
);
399 /* Free the MTD device structure */
400 kfree (tx4938ndfmc_mtd
);
402 module_exit(tx4938ndfmc_cleanup
);
404 MODULE_LICENSE("GPL");
405 MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>");
406 MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on TX4938 NDFMC");