diff options
Diffstat (limited to 'drivers/mtd/nand/cmx270_nand.c')
-rw-r--r-- | drivers/mtd/nand/cmx270_nand.c | 79 |
1 files changed, 47 insertions, 32 deletions
diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c index cb663ef245d5..fc8529bedfdf 100644 --- a/drivers/mtd/nand/cmx270_nand.c +++ b/drivers/mtd/nand/cmx270_nand.c | |||
@@ -20,9 +20,11 @@ | |||
20 | 20 | ||
21 | #include <linux/mtd/nand.h> | 21 | #include <linux/mtd/nand.h> |
22 | #include <linux/mtd/partitions.h> | 22 | #include <linux/mtd/partitions.h> |
23 | #include <linux/gpio.h> | ||
23 | 24 | ||
24 | #include <asm/io.h> | 25 | #include <asm/io.h> |
25 | #include <asm/irq.h> | 26 | #include <asm/irq.h> |
27 | #include <asm/mach-types.h> | ||
26 | 28 | ||
27 | #include <asm/arch/hardware.h> | 29 | #include <asm/arch/hardware.h> |
28 | #include <asm/arch/pxa-regs.h> | 30 | #include <asm/arch/pxa-regs.h> |
@@ -30,20 +32,6 @@ | |||
30 | #define GPIO_NAND_CS (11) | 32 | #define GPIO_NAND_CS (11) |
31 | #define GPIO_NAND_RB (89) | 33 | #define GPIO_NAND_RB (89) |
32 | 34 | ||
33 | /* This macro needed to ensure in-order operation of GPIO and local | ||
34 | * bus. Without both asm command and dummy uncached read there're | ||
35 | * states when NAND access is broken. I've looked for such macro(s) in | ||
36 | * include/asm-arm but found nothing approptiate. | ||
37 | * dmac_clean_range is close, but is makes cache invalidation | ||
38 | * unnecessary here and it cannot be used in module | ||
39 | */ | ||
40 | #define DRAIN_WB() \ | ||
41 | do { \ | ||
42 | unsigned char dummy; \ | ||
43 | asm volatile ("mcr p15, 0, r0, c7, c10, 4":::"r0"); \ | ||
44 | dummy=*((unsigned char*)UNCACHED_ADDR); \ | ||
45 | } while(0) | ||
46 | |||
47 | /* MTD structure for CM-X270 board */ | 35 | /* MTD structure for CM-X270 board */ |
48 | static struct mtd_info *cmx270_nand_mtd; | 36 | static struct mtd_info *cmx270_nand_mtd; |
49 | 37 | ||
@@ -103,14 +91,14 @@ static int cmx270_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) | |||
103 | 91 | ||
104 | static inline void nand_cs_on(void) | 92 | static inline void nand_cs_on(void) |
105 | { | 93 | { |
106 | GPCR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS); | 94 | gpio_set_value(GPIO_NAND_CS, 0); |
107 | } | 95 | } |
108 | 96 | ||
109 | static void nand_cs_off(void) | 97 | static void nand_cs_off(void) |
110 | { | 98 | { |
111 | DRAIN_WB(); | 99 | dsb(); |
112 | 100 | ||
113 | GPSR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS); | 101 | gpio_set_value(GPIO_NAND_CS, 1); |
114 | } | 102 | } |
115 | 103 | ||
116 | /* | 104 | /* |
@@ -122,7 +110,7 @@ static void cmx270_hwcontrol(struct mtd_info *mtd, int dat, | |||
122 | struct nand_chip* this = mtd->priv; | 110 | struct nand_chip* this = mtd->priv; |
123 | unsigned int nandaddr = (unsigned int)this->IO_ADDR_W; | 111 | unsigned int nandaddr = (unsigned int)this->IO_ADDR_W; |
124 | 112 | ||
125 | DRAIN_WB(); | 113 | dsb(); |
126 | 114 | ||
127 | if (ctrl & NAND_CTRL_CHANGE) { | 115 | if (ctrl & NAND_CTRL_CHANGE) { |
128 | if ( ctrl & NAND_ALE ) | 116 | if ( ctrl & NAND_ALE ) |
@@ -139,12 +127,12 @@ static void cmx270_hwcontrol(struct mtd_info *mtd, int dat, | |||
139 | nand_cs_off(); | 127 | nand_cs_off(); |
140 | } | 128 | } |
141 | 129 | ||
142 | DRAIN_WB(); | 130 | dsb(); |
143 | this->IO_ADDR_W = (void __iomem*)nandaddr; | 131 | this->IO_ADDR_W = (void __iomem*)nandaddr; |
144 | if (dat != NAND_CMD_NONE) | 132 | if (dat != NAND_CMD_NONE) |
145 | writel((dat << 16), this->IO_ADDR_W); | 133 | writel((dat << 16), this->IO_ADDR_W); |
146 | 134 | ||
147 | DRAIN_WB(); | 135 | dsb(); |
148 | } | 136 | } |
149 | 137 | ||
150 | /* | 138 | /* |
@@ -152,9 +140,9 @@ static void cmx270_hwcontrol(struct mtd_info *mtd, int dat, | |||
152 | */ | 140 | */ |
153 | static int cmx270_device_ready(struct mtd_info *mtd) | 141 | static int cmx270_device_ready(struct mtd_info *mtd) |
154 | { | 142 | { |
155 | DRAIN_WB(); | 143 | dsb(); |
156 | 144 | ||
157 | return (GPLR(GPIO_NAND_RB) & GPIO_bit(GPIO_NAND_RB)); | 145 | return (gpio_get_value(GPIO_NAND_RB)); |
158 | } | 146 | } |
159 | 147 | ||
160 | /* | 148 | /* |
@@ -168,20 +156,40 @@ static int cmx270_init(void) | |||
168 | int mtd_parts_nb = 0; | 156 | int mtd_parts_nb = 0; |
169 | int ret; | 157 | int ret; |
170 | 158 | ||
159 | if (!machine_is_armcore()) | ||
160 | return -ENODEV; | ||
161 | |||
162 | ret = gpio_request(GPIO_NAND_CS, "NAND CS"); | ||
163 | if (ret) { | ||
164 | pr_warning("CM-X270: failed to request NAND CS gpio\n"); | ||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | gpio_direction_output(GPIO_NAND_CS, 1); | ||
169 | |||
170 | ret = gpio_request(GPIO_NAND_RB, "NAND R/B"); | ||
171 | if (ret) { | ||
172 | pr_warning("CM-X270: failed to request NAND R/B gpio\n"); | ||
173 | goto err_gpio_request; | ||
174 | } | ||
175 | |||
176 | gpio_direction_input(GPIO_NAND_RB); | ||
177 | |||
171 | /* Allocate memory for MTD device structure and private data */ | 178 | /* Allocate memory for MTD device structure and private data */ |
172 | cmx270_nand_mtd = kzalloc(sizeof(struct mtd_info) + | 179 | cmx270_nand_mtd = kzalloc(sizeof(struct mtd_info) + |
173 | sizeof(struct nand_chip), | 180 | sizeof(struct nand_chip), |
174 | GFP_KERNEL); | 181 | GFP_KERNEL); |
175 | if (!cmx270_nand_mtd) { | 182 | if (!cmx270_nand_mtd) { |
176 | printk("Unable to allocate CM-X270 NAND MTD device structure.\n"); | 183 | pr_debug("Unable to allocate CM-X270 NAND MTD device structure.\n"); |
177 | return -ENOMEM; | 184 | ret = -ENOMEM; |
185 | goto err_kzalloc; | ||
178 | } | 186 | } |
179 | 187 | ||
180 | cmx270_nand_io = ioremap(PXA_CS1_PHYS, 12); | 188 | cmx270_nand_io = ioremap(PXA_CS1_PHYS, 12); |
181 | if (!cmx270_nand_io) { | 189 | if (!cmx270_nand_io) { |
182 | printk("Unable to ioremap NAND device\n"); | 190 | pr_debug("Unable to ioremap NAND device\n"); |
183 | ret = -EINVAL; | 191 | ret = -EINVAL; |
184 | goto err1; | 192 | goto err_ioremap; |
185 | } | 193 | } |
186 | 194 | ||
187 | /* Get pointer to private data */ | 195 | /* Get pointer to private data */ |
@@ -209,9 +217,9 @@ static int cmx270_init(void) | |||
209 | 217 | ||
210 | /* Scan to find existence of the device */ | 218 | /* Scan to find existence of the device */ |
211 | if (nand_scan (cmx270_nand_mtd, 1)) { | 219 | if (nand_scan (cmx270_nand_mtd, 1)) { |
212 | printk(KERN_NOTICE "No NAND device\n"); | 220 | pr_notice("No NAND device\n"); |
213 | ret = -ENXIO; | 221 | ret = -ENXIO; |
214 | goto err2; | 222 | goto err_scan; |
215 | } | 223 | } |
216 | 224 | ||
217 | #ifdef CONFIG_MTD_CMDLINE_PARTS | 225 | #ifdef CONFIG_MTD_CMDLINE_PARTS |
@@ -229,18 +237,22 @@ static int cmx270_init(void) | |||
229 | } | 237 | } |
230 | 238 | ||
231 | /* Register the partitions */ | 239 | /* Register the partitions */ |
232 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); | 240 | pr_notice("Using %s partition definition\n", part_type); |
233 | ret = add_mtd_partitions(cmx270_nand_mtd, mtd_parts, mtd_parts_nb); | 241 | ret = add_mtd_partitions(cmx270_nand_mtd, mtd_parts, mtd_parts_nb); |
234 | if (ret) | 242 | if (ret) |
235 | goto err2; | 243 | goto err_scan; |
236 | 244 | ||
237 | /* Return happy */ | 245 | /* Return happy */ |
238 | return 0; | 246 | return 0; |
239 | 247 | ||
240 | err2: | 248 | err_scan: |
241 | iounmap(cmx270_nand_io); | 249 | iounmap(cmx270_nand_io); |
242 | err1: | 250 | err_ioremap: |
243 | kfree(cmx270_nand_mtd); | 251 | kfree(cmx270_nand_mtd); |
252 | err_kzalloc: | ||
253 | gpio_free(GPIO_NAND_RB); | ||
254 | err_gpio_request: | ||
255 | gpio_free(GPIO_NAND_CS); | ||
244 | 256 | ||
245 | return ret; | 257 | return ret; |
246 | 258 | ||
@@ -255,6 +267,9 @@ static void cmx270_cleanup(void) | |||
255 | /* Release resources, unregister device */ | 267 | /* Release resources, unregister device */ |
256 | nand_release(cmx270_nand_mtd); | 268 | nand_release(cmx270_nand_mtd); |
257 | 269 | ||
270 | gpio_free(GPIO_NAND_RB); | ||
271 | gpio_free(GPIO_NAND_CS); | ||
272 | |||
258 | iounmap(cmx270_nand_io); | 273 | iounmap(cmx270_nand_io); |
259 | 274 | ||
260 | /* Free the MTD device structure */ | 275 | /* Free the MTD device structure */ |