diff options
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/Kconfig | 6 | ||||
-rw-r--r-- | drivers/mtd/nand/Makefile | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/ams-delta.c | 238 |
3 files changed, 245 insertions, 0 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index b1f807980b79..2d0ebad55a49 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -49,6 +49,12 @@ config MTD_NAND_SPIA | |||
49 | help | 49 | help |
50 | If you had to ask, you don't have one. Say 'N'. | 50 | If you had to ask, you don't have one. Say 'N'. |
51 | 51 | ||
52 | config MTD_NAND_AMS_DELTA | ||
53 | tristate "NAND Flash device on Amstrad E3" | ||
54 | depends on MACH_AMS_DELTA && MTD_NAND | ||
55 | help | ||
56 | Support for NAND flash on Amstrad E3 (Delta). | ||
57 | |||
52 | config MTD_NAND_TOTO | 58 | config MTD_NAND_TOTO |
53 | tristate "NAND Flash device on TOTO board" | 59 | tristate "NAND Flash device on TOTO board" |
54 | depends on ARCH_OMAP && MTD_NAND | 60 | depends on ARCH_OMAP && MTD_NAND |
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 0741d739cb87..33475087dbff 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile | |||
@@ -7,6 +7,7 @@ obj-$(CONFIG_MTD_NAND) += nand.o nand_ecc.o | |||
7 | obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o | 7 | obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o |
8 | 8 | ||
9 | obj-$(CONFIG_MTD_NAND_SPIA) += spia.o | 9 | obj-$(CONFIG_MTD_NAND_SPIA) += spia.o |
10 | obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o | ||
10 | obj-$(CONFIG_MTD_NAND_TOTO) += toto.o | 11 | obj-$(CONFIG_MTD_NAND_TOTO) += toto.o |
11 | obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o | 12 | obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o |
12 | obj-$(CONFIG_MTD_NAND_EDB7312) += edb7312.o | 13 | obj-$(CONFIG_MTD_NAND_EDB7312) += edb7312.o |
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c new file mode 100644 index 000000000000..5a349eb316f5 --- /dev/null +++ b/drivers/mtd/nand/ams-delta.c | |||
@@ -0,0 +1,238 @@ | |||
1 | /* | ||
2 | * drivers/mtd/nand/ams-delta.c | ||
3 | * | ||
4 | * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li> | ||
5 | * | ||
6 | * Derived from drivers/mtd/toto.c | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * Overview: | ||
13 | * This is a device driver for the NAND flash device found on the | ||
14 | * Amstrad E3 (Delta). | ||
15 | */ | ||
16 | |||
17 | #include <linux/slab.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/mtd/mtd.h> | ||
22 | #include <linux/mtd/nand.h> | ||
23 | #include <linux/mtd/partitions.h> | ||
24 | #include <asm/io.h> | ||
25 | #include <asm/arch/hardware.h> | ||
26 | #include <asm/sizes.h> | ||
27 | #include <asm/arch/gpio.h> | ||
28 | #include <asm/arch/board-ams-delta.h> | ||
29 | |||
30 | /* | ||
31 | * MTD structure for E3 (Delta) | ||
32 | */ | ||
33 | static struct mtd_info *ams_delta_mtd = NULL; | ||
34 | |||
35 | #define NAND_MASK (AMS_DELTA_LATCH2_NAND_NRE | AMS_DELTA_LATCH2_NAND_NWE | AMS_DELTA_LATCH2_NAND_CLE | AMS_DELTA_LATCH2_NAND_ALE | AMS_DELTA_LATCH2_NAND_NCE | AMS_DELTA_LATCH2_NAND_NWP) | ||
36 | |||
37 | #define T_NAND_CTL_CLRALE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_ALE, 0) | ||
38 | #define T_NAND_CTL_SETALE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_ALE, AMS_DELTA_LATCH2_NAND_ALE) | ||
39 | #define T_NAND_CTL_CLRCLE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE, 0) | ||
40 | #define T_NAND_CTL_SETCLE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE, AMS_DELTA_LATCH2_NAND_CLE) | ||
41 | #define T_NAND_CTL_SETNCE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NCE, 0) | ||
42 | #define T_NAND_CTL_CLRNCE(iob) ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NCE, AMS_DELTA_LATCH2_NAND_NCE) | ||
43 | |||
44 | /* | ||
45 | * Define partitions for flash devices | ||
46 | */ | ||
47 | |||
48 | static struct mtd_partition partition_info[] = { | ||
49 | { .name = "Kernel", | ||
50 | .offset = 0, | ||
51 | .size = 3 * SZ_1M + SZ_512K }, | ||
52 | { .name = "u-boot", | ||
53 | .offset = 3 * SZ_1M + SZ_512K, | ||
54 | .size = SZ_256K }, | ||
55 | { .name = "u-boot params", | ||
56 | .offset = 3 * SZ_1M + SZ_512K + SZ_256K, | ||
57 | .size = SZ_256K }, | ||
58 | { .name = "Amstrad LDR", | ||
59 | .offset = 4 * SZ_1M, | ||
60 | .size = SZ_256K }, | ||
61 | { .name = "File system", | ||
62 | .offset = 4 * SZ_1M + 1 * SZ_256K, | ||
63 | .size = 27 * SZ_1M }, | ||
64 | { .name = "PBL reserved", | ||
65 | .offset = 32 * SZ_1M - 3 * SZ_256K, | ||
66 | .size = 3 * SZ_256K }, | ||
67 | }; | ||
68 | |||
69 | /* | ||
70 | * hardware specific access to control-lines | ||
71 | */ | ||
72 | |||
73 | static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd) | ||
74 | { | ||
75 | switch (cmd) { | ||
76 | |||
77 | case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break; | ||
78 | case NAND_CTL_CLRCLE: T_NAND_CTL_CLRCLE(cmd); break; | ||
79 | |||
80 | case NAND_CTL_SETALE: T_NAND_CTL_SETALE(cmd); break; | ||
81 | case NAND_CTL_CLRALE: T_NAND_CTL_CLRALE(cmd); break; | ||
82 | |||
83 | case NAND_CTL_SETNCE: T_NAND_CTL_SETNCE(cmd); break; | ||
84 | case NAND_CTL_CLRNCE: T_NAND_CTL_CLRNCE(cmd); break; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte) | ||
89 | { | ||
90 | struct nand_chip *this = mtd->priv; | ||
91 | |||
92 | omap_writew(0, (OMAP_MPUIO_BASE + OMAP_MPUIO_IO_CNTL)); | ||
93 | omap_writew(byte, this->IO_ADDR_W); | ||
94 | ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE, 0); | ||
95 | ndelay(40); | ||
96 | ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE, | ||
97 | AMS_DELTA_LATCH2_NAND_NWE); | ||
98 | } | ||
99 | |||
100 | static u_char ams_delta_read_byte(struct mtd_info *mtd) | ||
101 | { | ||
102 | u_char res; | ||
103 | struct nand_chip *this = mtd->priv; | ||
104 | |||
105 | ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE, 0); | ||
106 | ndelay(40); | ||
107 | omap_writew(~0, (OMAP_MPUIO_BASE + OMAP_MPUIO_IO_CNTL)); | ||
108 | res = omap_readw(this->IO_ADDR_R); | ||
109 | ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE, | ||
110 | AMS_DELTA_LATCH2_NAND_NRE); | ||
111 | |||
112 | return res; | ||
113 | } | ||
114 | |||
115 | static void ams_delta_write_buf(struct mtd_info *mtd, const u_char *buf, | ||
116 | int len) | ||
117 | { | ||
118 | int i; | ||
119 | |||
120 | for (i=0; i<len; i++) | ||
121 | ams_delta_write_byte(mtd, buf[i]); | ||
122 | } | ||
123 | |||
124 | static void ams_delta_read_buf(struct mtd_info *mtd, u_char *buf, int len) | ||
125 | { | ||
126 | int i; | ||
127 | |||
128 | for (i=0; i<len; i++) | ||
129 | buf[i] = ams_delta_read_byte(mtd); | ||
130 | } | ||
131 | |||
132 | static int ams_delta_verify_buf(struct mtd_info *mtd, const u_char *buf, | ||
133 | int len) | ||
134 | { | ||
135 | int i; | ||
136 | |||
137 | for (i=0; i<len; i++) | ||
138 | if (buf[i] != ams_delta_read_byte(mtd)) | ||
139 | return -EFAULT; | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int ams_delta_nand_ready(struct mtd_info *mtd) | ||
145 | { | ||
146 | return omap_get_gpio_datain(AMS_DELTA_GPIO_PIN_NAND_RB); | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * Main initialization routine | ||
151 | */ | ||
152 | static int __init ams_delta_init(void) | ||
153 | { | ||
154 | struct nand_chip *this; | ||
155 | int err = 0; | ||
156 | |||
157 | /* Allocate memory for MTD device structure and private data */ | ||
158 | ams_delta_mtd = kmalloc(sizeof(struct mtd_info) + | ||
159 | sizeof(struct nand_chip), GFP_KERNEL); | ||
160 | if (!ams_delta_mtd) { | ||
161 | printk (KERN_WARNING "Unable to allocate E3 NAND MTD device structure.\n"); | ||
162 | err = -ENOMEM; | ||
163 | goto out; | ||
164 | } | ||
165 | |||
166 | ams_delta_mtd->owner = THIS_MODULE; | ||
167 | |||
168 | /* Get pointer to private data */ | ||
169 | this = (struct nand_chip *) (&ams_delta_mtd[1]); | ||
170 | |||
171 | /* Initialize structures */ | ||
172 | memset(ams_delta_mtd, 0, sizeof(struct mtd_info)); | ||
173 | memset(this, 0, sizeof(struct nand_chip)); | ||
174 | |||
175 | /* Link the private data with the MTD structure */ | ||
176 | ams_delta_mtd->priv = this; | ||
177 | |||
178 | /* Set address of NAND IO lines */ | ||
179 | this->IO_ADDR_R = (OMAP_MPUIO_BASE + OMAP_MPUIO_INPUT_LATCH); | ||
180 | this->IO_ADDR_W = (OMAP_MPUIO_BASE + OMAP_MPUIO_OUTPUT); | ||
181 | this->read_byte = ams_delta_read_byte; | ||
182 | this->write_byte = ams_delta_write_byte; | ||
183 | this->write_buf = ams_delta_write_buf; | ||
184 | this->read_buf = ams_delta_read_buf; | ||
185 | this->verify_buf = ams_delta_verify_buf; | ||
186 | this->hwcontrol = ams_delta_hwcontrol; | ||
187 | if (!omap_request_gpio(AMS_DELTA_GPIO_PIN_NAND_RB)) { | ||
188 | this->dev_ready = ams_delta_nand_ready; | ||
189 | } else { | ||
190 | this->dev_ready = NULL; | ||
191 | printk(KERN_NOTICE "Couldn't request gpio for Delta NAND ready.\n"); | ||
192 | } | ||
193 | /* 25 us command delay time */ | ||
194 | this->chip_delay = 30; | ||
195 | this->eccmode = NAND_ECC_SOFT; | ||
196 | |||
197 | /* Set chip enabled, but */ | ||
198 | ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE | | ||
199 | AMS_DELTA_LATCH2_NAND_NWE | | ||
200 | AMS_DELTA_LATCH2_NAND_NCE | | ||
201 | AMS_DELTA_LATCH2_NAND_NWP); | ||
202 | |||
203 | /* Scan to find existance of the device */ | ||
204 | if (nand_scan(ams_delta_mtd, 1)) { | ||
205 | err = -ENXIO; | ||
206 | goto out_mtd; | ||
207 | } | ||
208 | |||
209 | /* Register the partitions */ | ||
210 | add_mtd_partitions(ams_delta_mtd, partition_info, | ||
211 | ARRAY_SIZE(partition_info)); | ||
212 | |||
213 | goto out; | ||
214 | |||
215 | out_mtd: | ||
216 | kfree(ams_delta_mtd); | ||
217 | out: | ||
218 | return err; | ||
219 | } | ||
220 | |||
221 | module_init(ams_delta_init); | ||
222 | |||
223 | /* | ||
224 | * Clean up routine | ||
225 | */ | ||
226 | static void __exit ams_delta_cleanup(void) | ||
227 | { | ||
228 | /* Release resources, unregister device */ | ||
229 | nand_release(ams_delta_mtd); | ||
230 | |||
231 | /* Free the MTD device structure */ | ||
232 | kfree(ams_delta_mtd); | ||
233 | } | ||
234 | module_exit(ams_delta_cleanup); | ||
235 | |||
236 | MODULE_LICENSE("GPL"); | ||
237 | MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>"); | ||
238 | MODULE_DESCRIPTION("Glue layer for NAND flash on Amstrad E3 (Delta)"); | ||