2 * drivers/mtd/tx4925ndfmc.c
5 * This is a device driver for the NAND flash device found on the
6 * Toshiba RBTX4925 reference board, which is a SmartMediaCard. It supports
7 * 16MiB, 32MiB and 64MiB cards.
9 * Author: MontaVista Software, Inc. source@mvista.com
11 * Derived from drivers/mtd/autcpu12.c
12 * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
14 * $Id: tx4925ndfmc.c,v 1.5 2004/10/05 13:50:20 gleixner Exp $
16 * Copyright (C) 2001 Toshiba Corporation
18 * 2003 (c) MontaVista Software, Inc. This file is licensed under
19 * the terms of the GNU General Public License version 2. This program
20 * is licensed "as is" without any warranty of any kind, whether express
25 #include <linux/slab.h>
26 #include <linux/init.h>
27 #include <linux/module.h>
28 #include <linux/mtd/mtd.h>
29 #include <linux/mtd/nand.h>
30 #include <linux/mtd/partitions.h>
31 #include <linux/delay.h>
33 #include <asm/tx4925/tx4925_nand.h>
35 extern struct nand_oobinfo jffs2_oobinfo
;
38 * MTD structure for RBTX4925 board
40 static struct mtd_info
*tx4925ndfmc_mtd
= NULL
;
43 * Define partitions for flash devices
46 static struct mtd_partition partition_info16k
[] = {
47 { .name
= "RBTX4925 flash partition 1",
49 .size
= 8 * 0x00100000 },
50 { .name
= "RBTX4925 flash partition 2",
51 .offset
= 8 * 0x00100000,
52 .size
= 8 * 0x00100000 },
55 static struct mtd_partition partition_info32k
[] = {
56 { .name
= "RBTX4925 flash partition 1",
58 .size
= 8 * 0x00100000 },
59 { .name
= "RBTX4925 flash partition 2",
60 .offset
= 8 * 0x00100000,
61 .size
= 24 * 0x00100000 },
64 static struct mtd_partition partition_info64k
[] = {
67 .size
= 16 * 0x00100000 },
68 { .name
= "RBTX4925 flash partition 2",
69 .offset
= 16 * 0x00100000,
70 .size
= 48 * 0x00100000},
73 static struct mtd_partition partition_info128k
[] = {
74 { .name
= "Skip bad section",
76 .size
= 16 * 0x00100000 },
78 .offset
= 16 * 0x00100000,
79 .size
= 112 * 0x00100000 },
81 #define NUM_PARTITIONS16K 2
82 #define NUM_PARTITIONS32K 2
83 #define NUM_PARTITIONS64K 2
84 #define NUM_PARTITIONS128K 2
87 * hardware specific access to control-lines
89 static void tx4925ndfmc_hwcontrol(struct mtd_info
*mtd
, int cmd
)
95 tx4925_ndfmcptr
->mcr
|= TX4925_NDFMCR_CLE
;
98 tx4925_ndfmcptr
->mcr
&= ~TX4925_NDFMCR_CLE
;
100 case NAND_CTL_SETALE
:
101 tx4925_ndfmcptr
->mcr
|= TX4925_NDFMCR_ALE
;
103 case NAND_CTL_CLRALE
:
104 tx4925_ndfmcptr
->mcr
&= ~TX4925_NDFMCR_ALE
;
106 case NAND_CTL_SETNCE
:
107 tx4925_ndfmcptr
->mcr
|= TX4925_NDFMCR_CE
;
109 case NAND_CTL_CLRNCE
:
110 tx4925_ndfmcptr
->mcr
&= ~TX4925_NDFMCR_CE
;
113 tx4925_ndfmcptr
->mcr
|= TX4925_NDFMCR_WE
;
116 tx4925_ndfmcptr
->mcr
&= ~TX4925_NDFMCR_WE
;
122 * read device ready pin
124 static int tx4925ndfmc_device_ready(struct mtd_info
*mtd
)
127 ready
= (tx4925_ndfmcptr
->sr
& TX4925_NDSFR_BUSY
) ? 0 : 1;
130 void tx4925ndfmc_enable_hwecc(struct mtd_info
*mtd
, int mode
)
133 tx4925_ndfmcptr
->mcr
|= TX4925_NDFMCR_ECC_CNTL_MASK
;
134 tx4925_ndfmcptr
->mcr
&= ~TX4925_NDFMCR_ECC_CNTL_MASK
;
135 tx4925_ndfmcptr
->mcr
|= TX4925_NDFMCR_ECC_CNTL_ENAB
;
137 static void tx4925ndfmc_disable_ecc(void)
139 tx4925_ndfmcptr
->mcr
&= ~TX4925_NDFMCR_ECC_CNTL_MASK
;
141 static void tx4925ndfmc_enable_read_ecc(void)
143 tx4925_ndfmcptr
->mcr
&= ~TX4925_NDFMCR_ECC_CNTL_MASK
;
144 tx4925_ndfmcptr
->mcr
|= TX4925_NDFMCR_ECC_CNTL_READ
;
146 void tx4925ndfmc_readecc(struct mtd_info
*mtd
, const u_char
*dat
, u_char
*ecc_code
){
148 u_char
*ecc
= ecc_code
;
149 tx4925ndfmc_enable_read_ecc();
150 for (i
= 0;i
< 6;i
++,ecc
++)
151 *ecc
= tx4925_read_nfmc(&(tx4925_ndfmcptr
->dtr
));
152 tx4925ndfmc_disable_ecc();
154 void tx4925ndfmc_device_setup(void)
157 *(unsigned char *)0xbb005000 &= ~0x08;
160 tx4925_ndfmcptr
->rstr
|= TX4925_NDFRSTR_RST
;
161 while (tx4925_ndfmcptr
->rstr
& TX4925_NDFRSTR_RST
);
163 /* setup BusSeparete, Hold Time, Strobe Pulse Width */
164 tx4925_ndfmcptr
->mcr
= TX4925_BSPRT
? TX4925_NDFMCR_BSPRT
: 0;
165 tx4925_ndfmcptr
->spr
= TX4925_HOLD
<< 4 | TX4925_SPW
;
167 static u_char
tx4925ndfmc_nand_read_byte(struct mtd_info
*mtd
)
169 struct nand_chip
*this = mtd
->priv
;
170 return tx4925_read_nfmc(this->IO_ADDR_R
);
173 static void tx4925ndfmc_nand_write_byte(struct mtd_info
*mtd
, u_char byte
)
175 struct nand_chip
*this = mtd
->priv
;
176 tx4925_write_nfmc(byte
, this->IO_ADDR_W
);
179 static void tx4925ndfmc_nand_write_buf(struct mtd_info
*mtd
, const u_char
*buf
, int len
)
182 struct nand_chip
*this = mtd
->priv
;
184 for (i
=0; i
<len
; i
++)
185 tx4925_write_nfmc(buf
[i
], this->IO_ADDR_W
);
188 static void tx4925ndfmc_nand_read_buf(struct mtd_info
*mtd
, u_char
*buf
, int len
)
191 struct nand_chip
*this = mtd
->priv
;
193 for (i
=0; i
<len
; i
++)
194 buf
[i
] = tx4925_read_nfmc(this->IO_ADDR_R
);
197 static int tx4925ndfmc_nand_verify_buf(struct mtd_info
*mtd
, const u_char
*buf
, int len
)
200 struct nand_chip
*this = mtd
->priv
;
202 for (i
=0; i
<len
; i
++)
203 if (buf
[i
] != tx4925_read_nfmc(this->IO_ADDR_R
))
210 * Send command to NAND device
212 static void tx4925ndfmc_nand_command (struct mtd_info
*mtd
, unsigned command
, int column
, int page_addr
)
214 register struct nand_chip
*this = mtd
->priv
;
216 /* Begin command latch cycle */
217 this->hwcontrol(mtd
, NAND_CTL_SETCLE
);
219 * Write out the command to the device.
221 if (command
== NAND_CMD_SEQIN
) {
224 if (column
>= mtd
->oobblock
) {
226 column
-= mtd
->oobblock
;
227 readcmd
= NAND_CMD_READOOB
;
228 } else if (column
< 256) {
229 /* First 256 bytes --> READ0 */
230 readcmd
= NAND_CMD_READ0
;
233 readcmd
= NAND_CMD_READ1
;
235 this->write_byte(mtd
, readcmd
);
237 this->write_byte(mtd
, command
);
239 /* Set ALE and clear CLE to start address cycle */
240 this->hwcontrol(mtd
, NAND_CTL_CLRCLE
);
242 if (column
!= -1 || page_addr
!= -1) {
243 this->hwcontrol(mtd
, NAND_CTL_SETALE
);
245 /* Serially input address */
247 this->write_byte(mtd
, column
);
248 if (page_addr
!= -1) {
249 this->write_byte(mtd
, (unsigned char) (page_addr
& 0xff));
250 this->write_byte(mtd
, (unsigned char) ((page_addr
>> 8) & 0xff));
251 /* One more address cycle for higher density devices */
252 if (mtd
->size
& 0x0c000000)
253 this->write_byte(mtd
, (unsigned char) ((page_addr
>> 16) & 0x0f));
255 /* Latch in address */
256 this->hwcontrol(mtd
, NAND_CTL_CLRALE
);
260 * program and erase have their own busy handlers
261 * status and sequential in needs no delay
265 case NAND_CMD_PAGEPROG
:
267 this->hwcontrol (mtd
, NAND_CTL_CLRWP
);
272 this->hwcontrol (mtd
, NAND_CTL_SETWP
);
275 case NAND_CMD_ERASE1
:
276 case NAND_CMD_ERASE2
:
277 case NAND_CMD_STATUS
:
283 this->hwcontrol(mtd
, NAND_CTL_SETCLE
);
284 this->write_byte(mtd
, NAND_CMD_STATUS
);
285 this->hwcontrol(mtd
, NAND_CTL_CLRCLE
);
286 while ( !(this->read_byte(mtd
) & 0x40));
289 /* This applies to read commands */
292 * If we don't have access to the busy pin, we apply the given
295 if (!this->dev_ready
) {
296 udelay (this->chip_delay
);
301 /* wait until command is processed */
302 while (!this->dev_ready(mtd
));
305 #ifdef CONFIG_MTD_CMDLINE_PARTS
306 extern int parse_cmdline_partitions(struct mtd_info
*master
, struct mtd_partitio
311 * Main initialization routine
313 extern int nand_correct_data(struct mtd_info
*mtd
, u_char
*dat
, u_char
*read_ecc
, u_char
*calc_ecc
);
314 int __init
tx4925ndfmc_init (void)
316 struct nand_chip
*this;
319 /* Allocate memory for MTD device structure and private data */
320 tx4925ndfmc_mtd
= kmalloc (sizeof(struct mtd_info
) + sizeof (struct nand_chip
),
322 if (!tx4925ndfmc_mtd
) {
323 printk ("Unable to allocate RBTX4925 NAND MTD device structure.\n");
328 tx4925ndfmc_device_setup();
330 /* io is indirect via a register so don't need to ioremap address */
332 /* Get pointer to private data */
333 this = (struct nand_chip
*) (&tx4925ndfmc_mtd
[1]);
335 /* Initialize structures */
336 memset((char *) tx4925ndfmc_mtd
, 0, sizeof(struct mtd_info
));
337 memset((char *) this, 0, sizeof(struct nand_chip
));
339 /* Link the private data with the MTD structure */
340 tx4925ndfmc_mtd
->priv
= this;
342 /* Set address of NAND IO lines */
343 this->IO_ADDR_R
= (void __iomem
*)&(tx4925_ndfmcptr
->dtr
);
344 this->IO_ADDR_W
= (void __iomem
*)&(tx4925_ndfmcptr
->dtr
);
345 this->hwcontrol
= tx4925ndfmc_hwcontrol
;
346 this->enable_hwecc
= tx4925ndfmc_enable_hwecc
;
347 this->calculate_ecc
= tx4925ndfmc_readecc
;
348 this->correct_data
= nand_correct_data
;
349 this->eccmode
= NAND_ECC_HW6_512
;
350 this->dev_ready
= tx4925ndfmc_device_ready
;
351 /* 20 us command delay time */
352 this->chip_delay
= 20;
353 this->read_byte
= tx4925ndfmc_nand_read_byte
;
354 this->write_byte
= tx4925ndfmc_nand_write_byte
;
355 this->cmdfunc
= tx4925ndfmc_nand_command
;
356 this->write_buf
= tx4925ndfmc_nand_write_buf
;
357 this->read_buf
= tx4925ndfmc_nand_read_buf
;
358 this->verify_buf
= tx4925ndfmc_nand_verify_buf
;
360 /* Scan to find existance of the device */
361 if (nand_scan (tx4925ndfmc_mtd
, 1)) {
366 /* Register the partitions */
367 #ifdef CONFIG_MTD_CMDLINE_PARTS
369 int mtd_parts_nb
= 0;
370 struct mtd_partition
*mtd_parts
= 0;
371 mtd_parts_nb
= parse_cmdline_partitions(tx4925ndfmc_mtd
, &mtd_parts
, "tx4925ndfmc");
372 if (mtd_parts_nb
> 0)
373 add_mtd_partitions(tx4925ndfmc_mtd
, mtd_parts
, mtd_parts_nb
);
375 add_mtd_device(tx4925ndfmc_mtd
);
377 #else /* ifdef CONFIG_MTD_CMDLINE_PARTS */
378 switch(tx4925ndfmc_mtd
->size
){
379 case 0x01000000: add_mtd_partitions(tx4925ndfmc_mtd
, partition_info16k
, NUM_PARTITIONS16K
); break;
380 case 0x02000000: add_mtd_partitions(tx4925ndfmc_mtd
, partition_info32k
, NUM_PARTITIONS32K
); break;
381 case 0x04000000: add_mtd_partitions(tx4925ndfmc_mtd
, partition_info64k
, NUM_PARTITIONS64K
); break;
382 case 0x08000000: add_mtd_partitions(tx4925ndfmc_mtd
, partition_info128k
, NUM_PARTITIONS128K
); break;
384 printk ("Unsupported SmartMedia device\n");
389 #endif /* ifdef CONFIG_MTD_CMDLINE_PARTS */
397 module_init(tx4925ndfmc_init
);
403 static void __exit
tx4925ndfmc_cleanup (void)
405 /* Release resources, unregister device */
406 nand_release (tx4925ndfmc_mtd
);
408 /* Free the MTD device structure */
409 kfree (tx4925ndfmc_mtd
);
411 module_exit(tx4925ndfmc_cleanup
);
414 MODULE_LICENSE("GPL");
415 MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>");
416 MODULE_DESCRIPTION("Glue layer for SmartMediaCard on Toshiba RBTX4925");