1 /*==============================================================================*/
3 /* This module is derived from the 2.4 driver shipped by Microtik for their */
4 /* Routerboard 1xx and 5xx series boards. It provides support for the built in */
5 /* NAND flash on the Routerboard 1xx series boards for Linux 2.6.19+. */
6 /* Licence: Original Microtik code seems not to have a licence. */
7 /* Rewritten code all GPL V2. */
8 /* Copyright(C) 2007 david.goodenough@linkchoose.co.uk (for rewriten code) */
9 /*==============================================================================*/
12 #include <linux/module.h>
13 #include <linux/platform_device.h>
14 #include <linux/mtd/nand.h>
15 #include <linux/mtd/mtd.h>
16 #include <linux/mtd/partitions.h>
17 #include <linux/delay.h>
21 #include <asm/bootinfo.h>
22 #include <asm/mach-adm5120/adm5120_info.h>
23 #include <asm/mach-adm5120/adm5120_defs.h>
25 #define SMEM1(x) (*((volatile unsigned char *) (KSEG1ADDR(ADM5120_SRAM1_BASE) + x)))
27 #define NAND_RW_REG 0x0 //data register
28 #define NAND_SET_CEn 0x1 //CE# low
29 #define NAND_CLR_CEn 0x2 //CE# high
30 #define NAND_CLR_CLE 0x3 //CLE low
31 #define NAND_SET_CLE 0x4 //CLE high
32 #define NAND_CLR_ALE 0x5 //ALE low
33 #define NAND_SET_ALE 0x6 //ALE high
34 #define NAND_SET_SPn 0x7 //SP# low (use spare area)
35 #define NAND_CLR_SPn 0x8 //SP# high (do not use spare area)
36 #define NAND_SET_WPn 0x9 //WP# low
37 #define NAND_CLR_WPn 0xA //WP# high
38 #define NAND_STS_REG 0xB //Status register
40 #define MEM32(x) *((volatile unsigned *) (x))
42 static struct mtd_partition partition_info
[] = {
44 name
: "RouterBoard NAND Boot",
50 offset
: MTDPART_OFS_NXTBLK
,
51 size
: MTDPART_SIZ_FULL
55 static struct nand_ecclayout rb_ecclayout
= {
57 .eccpos
= { 8, 9, 10, 13, 14, 15 },
59 .oobfree
= { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1} }
62 struct adm5120_nand_info
{
63 struct nand_chip chip
;
65 void __iomem
*io_base
;
66 #ifdef CONFIG_MTD_PARTITIONS
68 struct mtd_partition
*parts
;
73 static int rb100_dev_ready(struct mtd_info
*mtd
)
75 return SMEM1(NAND_STS_REG
) & 0x80;
78 static void rbmips_hwcontrol100(struct mtd_info
*mtd
, int cmd
, unsigned int ctrl
)
80 struct nand_chip
*chip
= mtd
->priv
;
81 if (ctrl
& NAND_CTRL_CHANGE
)
83 SMEM1((( ctrl
& NAND_CLE
) ? NAND_SET_CLE
: NAND_CLR_CLE
)) = 0x01;
84 SMEM1((( ctrl
& NAND_ALE
) ? NAND_SET_ALE
: NAND_CLR_ALE
)) = 0x01;
85 SMEM1((( ctrl
& NAND_NCE
) ? NAND_SET_CEn
: NAND_CLR_CEn
)) = 0x01;
87 if (cmd
!= NAND_CMD_NONE
)
88 writeb( cmd
, chip
->IO_ADDR_W
);
91 /*========================================================================*/
92 /* We need to use the OLD Yaffs-1 OOB layout, otherwise the RB bootloader */
93 /* will not be able to find the kernel that we load. So set the oobinfo */
94 /* when creating the partitions. */
95 /*========================================================================*/
98 unsigned get_rbnand_block_size(struct adm5120_nand_info
*data
)
100 return data
->init_ok
? data
->mtd
.writesize
: 0;
103 EXPORT_SYMBOL(get_rbnand_block_size
);
105 static int rbmips_probe(struct platform_device
*pdev
)
107 struct adm5120_nand_info
*data
;
110 /* Allocate memory for the nand_chip structure */
111 data
= kzalloc(sizeof(*data
), GFP_KERNEL
);
113 dev_err(&pdev
->dev
, "Failed to allocate device structure\n");
118 data
->io_base
= ioremap(pdev
->resource
[0].start
, pdev
->resource
[0].end
- pdev
->resource
[0].start
+ 1);
120 if (data
->io_base
== NULL
) {
121 dev_err(&pdev
->dev
, "ioremap failed\n");
126 MEM32(0xB2000064) = 0x100;
127 MEM32(0xB2000008) = 0x1;
128 SMEM1(NAND_SET_SPn
) = 0x01;
129 SMEM1(NAND_CLR_WPn
) = 0x01;
131 data
->chip
.priv
= &data
;
132 data
->mtd
.priv
= &data
->chip
;
133 data
->mtd
.owner
= THIS_MODULE
;
136 data
->chip
.IO_ADDR_R
= (unsigned char *)KSEG1ADDR(ADM5120_SRAM1_BASE
);
137 data
->chip
.IO_ADDR_W
= data
->chip
.IO_ADDR_R
;
138 data
->chip
.cmd_ctrl
= rbmips_hwcontrol100
;
139 data
->chip
.dev_ready
= rb100_dev_ready
;
140 data
->chip
.ecc
.mode
= NAND_ECC_SOFT
;
141 data
->chip
.ecc
.layout
= &rb_ecclayout
;
142 data
->chip
.chip_delay
= 25;
143 data
->chip
.options
|= NAND_NO_AUTOINCR
;
145 platform_set_drvdata(pdev
, data
);
147 /* Why do we need to scan 4 times ? */
148 if (nand_scan(&data
->mtd
, 1) && nand_scan(&data
->mtd
, 1) && nand_scan(&data
->mtd
, 1) && nand_scan(&data
->mtd
, 1)) {
149 printk(KERN_INFO
"RB1xxx nand device not found\n");
154 add_mtd_partitions(&data
->mtd
, partition_info
, 2);
157 res
= add_mtd_device(&data
->mtd
);
161 nand_release(&data
->mtd
);
163 platform_set_drvdata(pdev
, NULL
);
164 iounmap(data
->io_base
);
169 static int __devexit
rbmips_remove(struct platform_device
*pdev
)
171 struct adm5120_nand_info
*data
= platform_get_drvdata(pdev
);
173 nand_release(&data
->mtd
);
174 iounmap(data
->io_base
);
180 static struct platform_driver adm5120_nand_driver
= {
181 .probe
= rbmips_probe
,
182 .remove
= rbmips_remove
,
184 .name
= "adm5120-nand",
185 .owner
= THIS_MODULE
,
189 static int __init
adm5120_nand_init(void)
192 err
= platform_driver_register(&adm5120_nand_driver
);
196 static void __exit
adm5120_nand_exit(void)
198 platform_driver_unregister(&adm5120_nand_driver
);
201 module_init(adm5120_nand_init
);
202 module_exit(adm5120_nand_exit
);
204 MODULE_LICENSE("GPL");
205 MODULE_AUTHOR("David Goodenough, Florian Fainelli");
206 MODULE_DESCRIPTION("RouterBOARD 100 NAND driver");