diff options
-rw-r--r-- | Documentation/devicetree/bindings/mtd/atmel-nand.txt | 41 | ||||
-rw-r--r-- | arch/arm/boot/dts/at91sam9g20.dtsi | 16 | ||||
-rw-r--r-- | arch/arm/boot/dts/at91sam9g45.dtsi | 16 | ||||
-rw-r--r-- | arch/arm/boot/dts/at91sam9m10g45ek.dts | 25 | ||||
-rw-r--r-- | arch/arm/boot/dts/usb_a9g20.dts | 44 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9x5.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-dt.c | 51 | ||||
-rw-r--r-- | drivers/mtd/nand/atmel_nand.c | 113 |
8 files changed, 233 insertions, 78 deletions
diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt new file mode 100644 index 000000000000..5903ecf6e895 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt | |||
@@ -0,0 +1,41 @@ | |||
1 | Atmel NAND flash | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : "atmel,at91rm9200-nand". | ||
5 | - reg : should specify localbus address and size used for the chip, | ||
6 | and if availlable the ECC. | ||
7 | - atmel,nand-addr-offset : offset for the address latch. | ||
8 | - atmel,nand-cmd-offset : offset for the command latch. | ||
9 | - #address-cells, #size-cells : Must be present if the device has sub-nodes | ||
10 | representing partitions. | ||
11 | |||
12 | - gpios : specifies the gpio pins to control the NAND device. detect is an | ||
13 | optional gpio and may be set to 0 if not present. | ||
14 | |||
15 | Optional properties: | ||
16 | - nand-ecc-mode : String, operation mode of the NAND ecc mode, soft by default. | ||
17 | Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first", | ||
18 | "soft_bch". | ||
19 | - nand-bus-width : 8 or 16 bus width if not present 8 | ||
20 | - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false | ||
21 | |||
22 | Examples: | ||
23 | nand0: nand@40000000,0 { | ||
24 | compatible = "atmel,at91rm9200-nand"; | ||
25 | #address-cells = <1>; | ||
26 | #size-cells = <1>; | ||
27 | reg = <0x40000000 0x10000000 | ||
28 | 0xffffe800 0x200 | ||
29 | >; | ||
30 | atmel,nand-addr-offset = <21>; | ||
31 | atmel,nand-cmd-offset = <22>; | ||
32 | nand-on-flash-bbt; | ||
33 | nand-ecc-mode = "soft"; | ||
34 | gpios = <&pioC 13 0 | ||
35 | &pioC 14 0 | ||
36 | 0 | ||
37 | >; | ||
38 | partition@0 { | ||
39 | ... | ||
40 | }; | ||
41 | }; | ||
diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi index a100db03ec90..4b0dc99b9319 100644 --- a/arch/arm/boot/dts/at91sam9g20.dtsi +++ b/arch/arm/boot/dts/at91sam9g20.dtsi | |||
@@ -172,5 +172,21 @@ | |||
172 | status = "disabled"; | 172 | status = "disabled"; |
173 | }; | 173 | }; |
174 | }; | 174 | }; |
175 | |||
176 | nand0: nand@40000000 { | ||
177 | compatible = "atmel,at91rm9200-nand"; | ||
178 | #address-cells = <1>; | ||
179 | #size-cells = <1>; | ||
180 | reg = <0x40000000 0x10000000 | ||
181 | 0xffffe800 0x200 | ||
182 | >; | ||
183 | atmel,nand-addr-offset = <21>; | ||
184 | atmel,nand-cmd-offset = <22>; | ||
185 | gpios = <&pioC 13 0 | ||
186 | &pioC 14 0 | ||
187 | 0 | ||
188 | >; | ||
189 | status = "disabled"; | ||
190 | }; | ||
175 | }; | 191 | }; |
176 | }; | 192 | }; |
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index f779667159b1..d79021b831c4 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi | |||
@@ -180,5 +180,21 @@ | |||
180 | status = "disabled"; | 180 | status = "disabled"; |
181 | }; | 181 | }; |
182 | }; | 182 | }; |
183 | |||
184 | nand0: nand@40000000 { | ||
185 | compatible = "atmel,at91rm9200-nand"; | ||
186 | #address-cells = <1>; | ||
187 | #size-cells = <1>; | ||
188 | reg = <0x40000000 0x10000000 | ||
189 | 0xffffe200 0x200 | ||
190 | >; | ||
191 | atmel,nand-addr-offset = <21>; | ||
192 | atmel,nand-cmd-offset = <22>; | ||
193 | gpios = <&pioC 8 0 | ||
194 | &pioC 14 0 | ||
195 | 0 | ||
196 | >; | ||
197 | status = "disabled"; | ||
198 | }; | ||
183 | }; | 199 | }; |
184 | }; | 200 | }; |
diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts index 15e25f903cad..fd4531135431 100644 --- a/arch/arm/boot/dts/at91sam9m10g45ek.dts +++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts | |||
@@ -14,7 +14,7 @@ | |||
14 | compatible = "atmel,at91sam9m10g45ek", "atmel,at91sam9g45", "atmel,at91sam9"; | 14 | compatible = "atmel,at91sam9m10g45ek", "atmel,at91sam9g45", "atmel,at91sam9"; |
15 | 15 | ||
16 | chosen { | 16 | chosen { |
17 | bootargs = "mem=64M console=ttyS0,115200 mtdparts=atmel_nand:4M(bootstrap/uboot/kernel)ro,60M(rootfs),-(data) root=/dev/mtdblock1 rw rootfstype=jffs2"; | 17 | bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2"; |
18 | }; | 18 | }; |
19 | 19 | ||
20 | memory@70000000 { | 20 | memory@70000000 { |
@@ -36,6 +36,29 @@ | |||
36 | status = "okay"; | 36 | status = "okay"; |
37 | }; | 37 | }; |
38 | }; | 38 | }; |
39 | |||
40 | nand0: nand@40000000 { | ||
41 | nand-bus-width = <8>; | ||
42 | nand-ecc-mode = "soft"; | ||
43 | nand-on-flash-bbt; | ||
44 | status = "okay"; | ||
45 | |||
46 | boot@0 { | ||
47 | label = "bootstrap/uboot/kernel"; | ||
48 | reg = <0x0 0x400000>; | ||
49 | }; | ||
50 | |||
51 | rootfs@400000 { | ||
52 | label = "rootfs"; | ||
53 | reg = <0x400000 0x3C00000>; | ||
54 | }; | ||
55 | |||
56 | data@4000000 { | ||
57 | label = "data"; | ||
58 | reg = <0x4000000 0xC000000>; | ||
59 | }; | ||
60 | |||
61 | }; | ||
39 | }; | 62 | }; |
40 | 63 | ||
41 | leds { | 64 | leds { |
diff --git a/arch/arm/boot/dts/usb_a9g20.dts b/arch/arm/boot/dts/usb_a9g20.dts index d74545a2a77c..71d83ef316df 100644 --- a/arch/arm/boot/dts/usb_a9g20.dts +++ b/arch/arm/boot/dts/usb_a9g20.dts | |||
@@ -13,7 +13,7 @@ | |||
13 | compatible = "calao,usb-a9g20", "atmel,at91sam9g20", "atmel,at91sam9"; | 13 | compatible = "calao,usb-a9g20", "atmel,at91sam9g20", "atmel,at91sam9"; |
14 | 14 | ||
15 | chosen { | 15 | chosen { |
16 | bootargs = "mem=64M console=ttyS0,115200 mtdparts=atmel_nand:128k(at91bootstrap),256k(barebox)ro,128k(bareboxenv),128k(bareboxenv2),4M(kernel),120M(rootfs),-(data) root=/dev/mtdblock5 rw rootfstype=ubifs"; | 16 | bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs"; |
17 | }; | 17 | }; |
18 | 18 | ||
19 | memory@20000000 { | 19 | memory@20000000 { |
@@ -31,6 +31,48 @@ | |||
31 | status = "okay"; | 31 | status = "okay"; |
32 | }; | 32 | }; |
33 | }; | 33 | }; |
34 | |||
35 | nand0: nand@40000000 { | ||
36 | nand-bus-width = <8>; | ||
37 | nand-ecc-mode = "soft"; | ||
38 | nand-on-flash-bbt; | ||
39 | status = "okay"; | ||
40 | |||
41 | at91bootstrap@0 { | ||
42 | label = "at91bootstrap"; | ||
43 | reg = <0x0 0x20000>; | ||
44 | }; | ||
45 | |||
46 | barebox@20000 { | ||
47 | label = "barebox"; | ||
48 | reg = <0x20000 0x40000>; | ||
49 | }; | ||
50 | |||
51 | bareboxenv@60000 { | ||
52 | label = "bareboxenv"; | ||
53 | reg = <0x60000 0x20000>; | ||
54 | }; | ||
55 | |||
56 | bareboxenv2@80000 { | ||
57 | label = "bareboxenv2"; | ||
58 | reg = <0x80000 0x20000>; | ||
59 | }; | ||
60 | |||
61 | kernel@a0000 { | ||
62 | label = "kernel"; | ||
63 | reg = <0xa0000 0x400000>; | ||
64 | }; | ||
65 | |||
66 | rootfs@4a0000 { | ||
67 | label = "rootfs"; | ||
68 | reg = <0x4a0000 0x7800000>; | ||
69 | }; | ||
70 | |||
71 | data@7ca0000 { | ||
72 | label = "data"; | ||
73 | reg = <0x7ca0000 0x8360000>; | ||
74 | }; | ||
75 | }; | ||
34 | }; | 76 | }; |
35 | 77 | ||
36 | leds { | 78 | leds { |
diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c index a34d96afa746..7bec5a40d01a 100644 --- a/arch/arm/mach-at91/at91sam9x5.c +++ b/arch/arm/mach-at91/at91sam9x5.c | |||
@@ -314,11 +314,6 @@ void __init at91sam9x5_initialize(void) | |||
314 | } | 314 | } |
315 | 315 | ||
316 | /* -------------------------------------------------------------------- | 316 | /* -------------------------------------------------------------------- |
317 | * AT91SAM9x5 devices (temporary before modification of code) | ||
318 | * -------------------------------------------------------------------- */ | ||
319 | void __init at91_add_device_nand(struct atmel_nand_data *data) {} | ||
320 | |||
321 | /* -------------------------------------------------------------------- | ||
322 | * Interrupt initialization | 317 | * Interrupt initialization |
323 | * -------------------------------------------------------------------- */ | 318 | * -------------------------------------------------------------------- */ |
324 | /* | 319 | /* |
diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c index 2eb294b2cc0e..9f729d6c8942 100644 --- a/arch/arm/mach-at91/board-dt.c +++ b/arch/arm/mach-at91/board-dt.c | |||
@@ -19,10 +19,7 @@ | |||
19 | #include <linux/of_irq.h> | 19 | #include <linux/of_irq.h> |
20 | #include <linux/of_platform.h> | 20 | #include <linux/of_platform.h> |
21 | 21 | ||
22 | #include <mach/hardware.h> | ||
23 | #include <mach/board.h> | 22 | #include <mach/board.h> |
24 | #include <mach/system_rev.h> | ||
25 | #include <mach/at91sam9_smc.h> | ||
26 | 23 | ||
27 | #include <asm/setup.h> | 24 | #include <asm/setup.h> |
28 | #include <asm/irq.h> | 25 | #include <asm/irq.h> |
@@ -30,7 +27,6 @@ | |||
30 | #include <asm/mach/map.h> | 27 | #include <asm/mach/map.h> |
31 | #include <asm/mach/irq.h> | 28 | #include <asm/mach/irq.h> |
32 | 29 | ||
33 | #include "sam9_smc.h" | ||
34 | #include "generic.h" | 30 | #include "generic.h" |
35 | 31 | ||
36 | 32 | ||
@@ -40,50 +36,6 @@ static void __init ek_init_early(void) | |||
40 | at91_initialize(12000000); | 36 | at91_initialize(12000000); |
41 | } | 37 | } |
42 | 38 | ||
43 | /* det_pin is not connected */ | ||
44 | static struct atmel_nand_data __initdata ek_nand_data = { | ||
45 | .ale = 21, | ||
46 | .cle = 22, | ||
47 | .det_pin = -EINVAL, | ||
48 | .rdy_pin = AT91_PIN_PC8, | ||
49 | .enable_pin = AT91_PIN_PC14, | ||
50 | .ecc_mode = NAND_ECC_SOFT, | ||
51 | .on_flash_bbt = 1, | ||
52 | }; | ||
53 | |||
54 | static struct sam9_smc_config __initdata ek_nand_smc_config = { | ||
55 | .ncs_read_setup = 0, | ||
56 | .nrd_setup = 2, | ||
57 | .ncs_write_setup = 0, | ||
58 | .nwe_setup = 2, | ||
59 | |||
60 | .ncs_read_pulse = 4, | ||
61 | .nrd_pulse = 4, | ||
62 | .ncs_write_pulse = 4, | ||
63 | .nwe_pulse = 4, | ||
64 | |||
65 | .read_cycle = 7, | ||
66 | .write_cycle = 7, | ||
67 | |||
68 | .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE, | ||
69 | .tdf_cycles = 3, | ||
70 | }; | ||
71 | |||
72 | static void __init ek_add_device_nand(void) | ||
73 | { | ||
74 | ek_nand_data.bus_width_16 = board_have_nand_16bit(); | ||
75 | /* setup bus-width (8 or 16) */ | ||
76 | if (ek_nand_data.bus_width_16) | ||
77 | ek_nand_smc_config.mode |= AT91_SMC_DBW_16; | ||
78 | else | ||
79 | ek_nand_smc_config.mode |= AT91_SMC_DBW_8; | ||
80 | |||
81 | /* configure chip-select 3 (NAND) */ | ||
82 | sam9_smc_configure(0, 3, &ek_nand_smc_config); | ||
83 | |||
84 | at91_add_device_nand(&ek_nand_data); | ||
85 | } | ||
86 | |||
87 | static const struct of_device_id irq_of_match[] __initconst = { | 39 | static const struct of_device_id irq_of_match[] __initconst = { |
88 | 40 | ||
89 | { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init }, | 41 | { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init }, |
@@ -100,9 +52,6 @@ static void __init at91_dt_init_irq(void) | |||
100 | static void __init at91_dt_device_init(void) | 52 | static void __init at91_dt_device_init(void) |
101 | { | 53 | { |
102 | of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); | 54 | of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); |
103 | |||
104 | /* NAND */ | ||
105 | ek_add_device_nand(); | ||
106 | } | 55 | } |
107 | 56 | ||
108 | static const char *at91_dt_board_compat[] __initdata = { | 57 | static const char *at91_dt_board_compat[] __initdata = { |
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 045d174b8277..ae7e37d9ac17 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c | |||
@@ -27,6 +27,10 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
29 | #include <linux/platform_device.h> | 29 | #include <linux/platform_device.h> |
30 | #include <linux/of.h> | ||
31 | #include <linux/of_device.h> | ||
32 | #include <linux/of_gpio.h> | ||
33 | #include <linux/of_mtd.h> | ||
30 | #include <linux/mtd/mtd.h> | 34 | #include <linux/mtd/mtd.h> |
31 | #include <linux/mtd/nand.h> | 35 | #include <linux/mtd/nand.h> |
32 | #include <linux/mtd/partitions.h> | 36 | #include <linux/mtd/partitions.h> |
@@ -83,7 +87,7 @@ struct atmel_nand_host { | |||
83 | struct mtd_info mtd; | 87 | struct mtd_info mtd; |
84 | void __iomem *io_base; | 88 | void __iomem *io_base; |
85 | dma_addr_t io_phys; | 89 | dma_addr_t io_phys; |
86 | struct atmel_nand_data *board; | 90 | struct atmel_nand_data board; |
87 | struct device *dev; | 91 | struct device *dev; |
88 | void __iomem *ecc; | 92 | void __iomem *ecc; |
89 | 93 | ||
@@ -101,8 +105,8 @@ static int cpu_has_dma(void) | |||
101 | */ | 105 | */ |
102 | static void atmel_nand_enable(struct atmel_nand_host *host) | 106 | static void atmel_nand_enable(struct atmel_nand_host *host) |
103 | { | 107 | { |
104 | if (gpio_is_valid(host->board->enable_pin)) | 108 | if (gpio_is_valid(host->board.enable_pin)) |
105 | gpio_set_value(host->board->enable_pin, 0); | 109 | gpio_set_value(host->board.enable_pin, 0); |
106 | } | 110 | } |
107 | 111 | ||
108 | /* | 112 | /* |
@@ -110,8 +114,8 @@ static void atmel_nand_enable(struct atmel_nand_host *host) | |||
110 | */ | 114 | */ |
111 | static void atmel_nand_disable(struct atmel_nand_host *host) | 115 | static void atmel_nand_disable(struct atmel_nand_host *host) |
112 | { | 116 | { |
113 | if (gpio_is_valid(host->board->enable_pin)) | 117 | if (gpio_is_valid(host->board.enable_pin)) |
114 | gpio_set_value(host->board->enable_pin, 1); | 118 | gpio_set_value(host->board.enable_pin, 1); |
115 | } | 119 | } |
116 | 120 | ||
117 | /* | 121 | /* |
@@ -132,9 +136,9 @@ static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl | |||
132 | return; | 136 | return; |
133 | 137 | ||
134 | if (ctrl & NAND_CLE) | 138 | if (ctrl & NAND_CLE) |
135 | writeb(cmd, host->io_base + (1 << host->board->cle)); | 139 | writeb(cmd, host->io_base + (1 << host->board.cle)); |
136 | else | 140 | else |
137 | writeb(cmd, host->io_base + (1 << host->board->ale)); | 141 | writeb(cmd, host->io_base + (1 << host->board.ale)); |
138 | } | 142 | } |
139 | 143 | ||
140 | /* | 144 | /* |
@@ -145,8 +149,8 @@ static int atmel_nand_device_ready(struct mtd_info *mtd) | |||
145 | struct nand_chip *nand_chip = mtd->priv; | 149 | struct nand_chip *nand_chip = mtd->priv; |
146 | struct atmel_nand_host *host = nand_chip->priv; | 150 | struct atmel_nand_host *host = nand_chip->priv; |
147 | 151 | ||
148 | return gpio_get_value(host->board->rdy_pin) ^ | 152 | return gpio_get_value(host->board.rdy_pin) ^ |
149 | !!host->board->rdy_pin_active_low; | 153 | !!host->board.rdy_pin_active_low; |
150 | } | 154 | } |
151 | 155 | ||
152 | /* | 156 | /* |
@@ -261,7 +265,7 @@ static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) | |||
261 | if (atmel_nand_dma_op(mtd, buf, len, 1) == 0) | 265 | if (atmel_nand_dma_op(mtd, buf, len, 1) == 0) |
262 | return; | 266 | return; |
263 | 267 | ||
264 | if (host->board->bus_width_16) | 268 | if (host->board.bus_width_16) |
265 | atmel_read_buf16(mtd, buf, len); | 269 | atmel_read_buf16(mtd, buf, len); |
266 | else | 270 | else |
267 | atmel_read_buf8(mtd, buf, len); | 271 | atmel_read_buf8(mtd, buf, len); |
@@ -277,7 +281,7 @@ static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | |||
277 | if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0) | 281 | if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0) |
278 | return; | 282 | return; |
279 | 283 | ||
280 | if (host->board->bus_width_16) | 284 | if (host->board.bus_width_16) |
281 | atmel_write_buf16(mtd, buf, len); | 285 | atmel_write_buf16(mtd, buf, len); |
282 | else | 286 | else |
283 | atmel_write_buf8(mtd, buf, len); | 287 | atmel_write_buf8(mtd, buf, len); |
@@ -469,6 +473,56 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) | |||
469 | } | 473 | } |
470 | } | 474 | } |
471 | 475 | ||
476 | #if defined(CONFIG_OF) | ||
477 | static int __devinit atmel_of_init_port(struct atmel_nand_host *host, | ||
478 | struct device_node *np) | ||
479 | { | ||
480 | u32 val; | ||
481 | int ecc_mode; | ||
482 | struct atmel_nand_data *board = &host->board; | ||
483 | enum of_gpio_flags flags; | ||
484 | |||
485 | if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) { | ||
486 | if (val >= 32) { | ||
487 | dev_err(host->dev, "invalid addr-offset %u\n", val); | ||
488 | return -EINVAL; | ||
489 | } | ||
490 | board->ale = val; | ||
491 | } | ||
492 | |||
493 | if (of_property_read_u32(np, "atmel,nand-cmd-offset", &val) == 0) { | ||
494 | if (val >= 32) { | ||
495 | dev_err(host->dev, "invalid cmd-offset %u\n", val); | ||
496 | return -EINVAL; | ||
497 | } | ||
498 | board->cle = val; | ||
499 | } | ||
500 | |||
501 | ecc_mode = of_get_nand_ecc_mode(np); | ||
502 | |||
503 | board->ecc_mode = ecc_mode < 0 ? NAND_ECC_SOFT : ecc_mode; | ||
504 | |||
505 | board->on_flash_bbt = of_get_nand_on_flash_bbt(np); | ||
506 | |||
507 | if (of_get_nand_bus_width(np) == 16) | ||
508 | board->bus_width_16 = 1; | ||
509 | |||
510 | board->rdy_pin = of_get_gpio_flags(np, 0, &flags); | ||
511 | board->rdy_pin_active_low = (flags == OF_GPIO_ACTIVE_LOW); | ||
512 | |||
513 | board->enable_pin = of_get_gpio(np, 1); | ||
514 | board->det_pin = of_get_gpio(np, 2); | ||
515 | |||
516 | return 0; | ||
517 | } | ||
518 | #else | ||
519 | static int __devinit atmel_of_init_port(struct atmel_nand_host *host, | ||
520 | struct device_node *np) | ||
521 | { | ||
522 | return -EINVAL; | ||
523 | } | ||
524 | #endif | ||
525 | |||
472 | /* | 526 | /* |
473 | * Probe for the NAND device. | 527 | * Probe for the NAND device. |
474 | */ | 528 | */ |
@@ -479,6 +533,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
479 | struct nand_chip *nand_chip; | 533 | struct nand_chip *nand_chip; |
480 | struct resource *regs; | 534 | struct resource *regs; |
481 | struct resource *mem; | 535 | struct resource *mem; |
536 | struct mtd_part_parser_data ppdata = {}; | ||
482 | int res; | 537 | int res; |
483 | 538 | ||
484 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 539 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -505,8 +560,15 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
505 | 560 | ||
506 | mtd = &host->mtd; | 561 | mtd = &host->mtd; |
507 | nand_chip = &host->nand_chip; | 562 | nand_chip = &host->nand_chip; |
508 | host->board = pdev->dev.platform_data; | ||
509 | host->dev = &pdev->dev; | 563 | host->dev = &pdev->dev; |
564 | if (pdev->dev.of_node) { | ||
565 | res = atmel_of_init_port(host, pdev->dev.of_node); | ||
566 | if (res) | ||
567 | goto err_nand_ioremap; | ||
568 | } else { | ||
569 | memcpy(&host->board, pdev->dev.platform_data, | ||
570 | sizeof(struct atmel_nand_data)); | ||
571 | } | ||
510 | 572 | ||
511 | nand_chip->priv = host; /* link the private data structures */ | 573 | nand_chip->priv = host; /* link the private data structures */ |
512 | mtd->priv = nand_chip; | 574 | mtd->priv = nand_chip; |
@@ -517,10 +579,10 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
517 | nand_chip->IO_ADDR_W = host->io_base; | 579 | nand_chip->IO_ADDR_W = host->io_base; |
518 | nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl; | 580 | nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl; |
519 | 581 | ||
520 | if (gpio_is_valid(host->board->rdy_pin)) | 582 | if (gpio_is_valid(host->board.rdy_pin)) |
521 | nand_chip->dev_ready = atmel_nand_device_ready; | 583 | nand_chip->dev_ready = atmel_nand_device_ready; |
522 | 584 | ||
523 | nand_chip->ecc.mode = host->board->ecc_mode; | 585 | nand_chip->ecc.mode = host->board.ecc_mode; |
524 | 586 | ||
525 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 587 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
526 | if (!regs && nand_chip->ecc.mode == NAND_ECC_HW) { | 588 | if (!regs && nand_chip->ecc.mode == NAND_ECC_HW) { |
@@ -545,7 +607,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
545 | 607 | ||
546 | nand_chip->chip_delay = 20; /* 20us command delay time */ | 608 | nand_chip->chip_delay = 20; /* 20us command delay time */ |
547 | 609 | ||
548 | if (host->board->bus_width_16) /* 16-bit bus width */ | 610 | if (host->board.bus_width_16) /* 16-bit bus width */ |
549 | nand_chip->options |= NAND_BUSWIDTH_16; | 611 | nand_chip->options |= NAND_BUSWIDTH_16; |
550 | 612 | ||
551 | nand_chip->read_buf = atmel_read_buf; | 613 | nand_chip->read_buf = atmel_read_buf; |
@@ -554,15 +616,15 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
554 | platform_set_drvdata(pdev, host); | 616 | platform_set_drvdata(pdev, host); |
555 | atmel_nand_enable(host); | 617 | atmel_nand_enable(host); |
556 | 618 | ||
557 | if (gpio_is_valid(host->board->det_pin)) { | 619 | if (gpio_is_valid(host->board.det_pin)) { |
558 | if (gpio_get_value(host->board->det_pin)) { | 620 | if (gpio_get_value(host->board.det_pin)) { |
559 | printk(KERN_INFO "No SmartMedia card inserted.\n"); | 621 | printk(KERN_INFO "No SmartMedia card inserted.\n"); |
560 | res = -ENXIO; | 622 | res = -ENXIO; |
561 | goto err_no_card; | 623 | goto err_no_card; |
562 | } | 624 | } |
563 | } | 625 | } |
564 | 626 | ||
565 | if (host->board->on_flash_bbt || on_flash_bbt) { | 627 | if (host->board.on_flash_bbt || on_flash_bbt) { |
566 | printk(KERN_INFO "atmel_nand: Use On Flash BBT\n"); | 628 | printk(KERN_INFO "atmel_nand: Use On Flash BBT\n"); |
567 | nand_chip->bbt_options |= NAND_BBT_USE_FLASH; | 629 | nand_chip->bbt_options |= NAND_BBT_USE_FLASH; |
568 | } | 630 | } |
@@ -637,8 +699,9 @@ static int __init atmel_nand_probe(struct platform_device *pdev) | |||
637 | } | 699 | } |
638 | 700 | ||
639 | mtd->name = "atmel_nand"; | 701 | mtd->name = "atmel_nand"; |
640 | res = mtd_device_parse_register(mtd, NULL, 0, | 702 | ppdata.of_node = pdev->dev.of_node; |
641 | host->board->parts, host->board->num_parts); | 703 | res = mtd_device_parse_register(mtd, NULL, &ppdata, |
704 | host->board.parts, host->board.num_parts); | ||
642 | if (!res) | 705 | if (!res) |
643 | return res; | 706 | return res; |
644 | 707 | ||
@@ -682,11 +745,21 @@ static int __exit atmel_nand_remove(struct platform_device *pdev) | |||
682 | return 0; | 745 | return 0; |
683 | } | 746 | } |
684 | 747 | ||
748 | #if defined(CONFIG_OF) | ||
749 | static const struct of_device_id atmel_nand_dt_ids[] = { | ||
750 | { .compatible = "atmel,at91rm9200-nand" }, | ||
751 | { /* sentinel */ } | ||
752 | }; | ||
753 | |||
754 | MODULE_DEVICE_TABLE(of, atmel_nand_dt_ids); | ||
755 | #endif | ||
756 | |||
685 | static struct platform_driver atmel_nand_driver = { | 757 | static struct platform_driver atmel_nand_driver = { |
686 | .remove = __exit_p(atmel_nand_remove), | 758 | .remove = __exit_p(atmel_nand_remove), |
687 | .driver = { | 759 | .driver = { |
688 | .name = "atmel_nand", | 760 | .name = "atmel_nand", |
689 | .owner = THIS_MODULE, | 761 | .owner = THIS_MODULE, |
762 | .of_match_table = of_match_ptr(atmel_nand_dt_ids), | ||
690 | }, | 763 | }, |
691 | }; | 764 | }; |
692 | 765 | ||