diff options
| author | Heiko Schocher <hs@denx.de> | 2012-07-30 03:22:24 -0400 |
|---|---|---|
| committer | David Woodhouse <David.Woodhouse@intel.com> | 2012-09-29 09:59:04 -0400 |
| commit | cdeadd712f52b16a9285386d61ee26fd14eb4085 (patch) | |
| tree | b02e5aa17567fdac6bdc22033c7c9fd8a5aaeb98 | |
| parent | a445f784ae5558a3da680aa6b39ed53c95a551c1 (diff) | |
mtd: nand: davinci: add OF support for davinci nand controller
add OF support for the davinci nand controller.
Signed-off-by: Heiko Schocher <hs@denx.de>
Acked-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
| -rw-r--r-- | Documentation/devicetree/bindings/arm/davinci/nand.txt | 51 | ||||
| -rw-r--r-- | drivers/mtd/nand/davinci_nand.c | 72 |
2 files changed, 122 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/arm/davinci/nand.txt b/Documentation/devicetree/bindings/arm/davinci/nand.txt new file mode 100644 index 00000000000..e37241f1fdd --- /dev/null +++ b/Documentation/devicetree/bindings/arm/davinci/nand.txt | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | * Texas Instruments Davinci NAND | ||
| 2 | |||
| 3 | This file provides information, what the device node for the | ||
| 4 | davinci nand interface contain. | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | - compatible: "ti,davinci-nand"; | ||
| 8 | - reg : contain 2 offset/length values: | ||
| 9 | - offset and length for the access window | ||
| 10 | - offset and length for accessing the aemif control registers | ||
| 11 | - ti,davinci-chipselect: Indicates on the davinci_nand driver which | ||
| 12 | chipselect is used for accessing the nand. | ||
| 13 | |||
| 14 | Recommended properties : | ||
| 15 | - ti,davinci-mask-ale: mask for ale | ||
| 16 | - ti,davinci-mask-cle: mask for cle | ||
| 17 | - ti,davinci-mask-chipsel: mask for chipselect | ||
| 18 | - ti,davinci-ecc-mode: ECC mode valid values for davinci driver: | ||
| 19 | - "none" | ||
| 20 | - "soft" | ||
| 21 | - "hw" | ||
| 22 | - ti,davinci-ecc-bits: used ECC bits, currently supported 1 or 4. | ||
| 23 | - ti,davinci-nand-buswidth: buswidth 8 or 16 | ||
| 24 | - ti,davinci-nand-use-bbt: use flash based bad block table support. | ||
| 25 | |||
| 26 | Example (enbw_cmc board): | ||
| 27 | aemif@60000000 { | ||
| 28 | compatible = "ti,davinci-aemif"; | ||
| 29 | #address-cells = <2>; | ||
| 30 | #size-cells = <1>; | ||
| 31 | reg = <0x68000000 0x80000>; | ||
| 32 | ranges = <2 0 0x60000000 0x02000000 | ||
| 33 | 3 0 0x62000000 0x02000000 | ||
| 34 | 4 0 0x64000000 0x02000000 | ||
| 35 | 5 0 0x66000000 0x02000000 | ||
| 36 | 6 0 0x68000000 0x02000000>; | ||
| 37 | nand@3,0 { | ||
| 38 | compatible = "ti,davinci-nand"; | ||
| 39 | reg = <3 0x0 0x807ff | ||
| 40 | 6 0x0 0x8000>; | ||
| 41 | #address-cells = <1>; | ||
| 42 | #size-cells = <1>; | ||
| 43 | ti,davinci-chipselect = <1>; | ||
| 44 | ti,davinci-mask-ale = <0>; | ||
| 45 | ti,davinci-mask-cle = <0>; | ||
| 46 | ti,davinci-mask-chipsel = <0>; | ||
| 47 | ti,davinci-ecc-mode = "hw"; | ||
| 48 | ti,davinci-ecc-bits = <4>; | ||
| 49 | ti,davinci-nand-use-bbt; | ||
| 50 | }; | ||
| 51 | }; | ||
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index d94b03c207a..f386b3c5503 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/mtd/nand.h> | 33 | #include <linux/mtd/nand.h> |
| 34 | #include <linux/mtd/partitions.h> | 34 | #include <linux/mtd/partitions.h> |
| 35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
| 36 | #include <linux/of_device.h> | ||
| 36 | 37 | ||
| 37 | #include <mach/nand.h> | 38 | #include <mach/nand.h> |
| 38 | #include <mach/aemif.h> | 39 | #include <mach/aemif.h> |
| @@ -518,9 +519,75 @@ static struct nand_ecclayout hwecc4_2048 __initconst = { | |||
| 518 | }, | 519 | }, |
| 519 | }; | 520 | }; |
| 520 | 521 | ||
| 522 | #if defined(CONFIG_OF) | ||
| 523 | static const struct of_device_id davinci_nand_of_match[] = { | ||
| 524 | {.compatible = "ti,davinci-nand", }, | ||
| 525 | {}, | ||
| 526 | } | ||
| 527 | MODULE_DEVICE_TABLE(of, davinci_nand_of_match); | ||
| 528 | |||
| 529 | static struct davinci_nand_pdata | ||
| 530 | *nand_davinci_get_pdata(struct platform_device *pdev) | ||
| 531 | { | ||
| 532 | if (!pdev->dev.platform_data && pdev->dev.of_node) { | ||
| 533 | struct davinci_nand_pdata *pdata; | ||
| 534 | const char *mode; | ||
| 535 | u32 prop; | ||
| 536 | int len; | ||
| 537 | |||
| 538 | pdata = devm_kzalloc(&pdev->dev, | ||
| 539 | sizeof(struct davinci_nand_pdata), | ||
| 540 | GFP_KERNEL); | ||
| 541 | pdev->dev.platform_data = pdata; | ||
| 542 | if (!pdata) | ||
| 543 | return NULL; | ||
| 544 | if (!of_property_read_u32(pdev->dev.of_node, | ||
| 545 | "ti,davinci-chipselect", &prop)) | ||
| 546 | pdev->id = prop; | ||
| 547 | if (!of_property_read_u32(pdev->dev.of_node, | ||
| 548 | "ti,davinci-mask-ale", &prop)) | ||
| 549 | pdata->mask_ale = prop; | ||
| 550 | if (!of_property_read_u32(pdev->dev.of_node, | ||
| 551 | "ti,davinci-mask-cle", &prop)) | ||
| 552 | pdata->mask_cle = prop; | ||
| 553 | if (!of_property_read_u32(pdev->dev.of_node, | ||
| 554 | "ti,davinci-mask-chipsel", &prop)) | ||
| 555 | pdata->mask_chipsel = prop; | ||
| 556 | if (!of_property_read_string(pdev->dev.of_node, | ||
| 557 | "ti,davinci-ecc-mode", &mode)) { | ||
| 558 | if (!strncmp("none", mode, 4)) | ||
| 559 | pdata->ecc_mode = NAND_ECC_NONE; | ||
| 560 | if (!strncmp("soft", mode, 4)) | ||
| 561 | pdata->ecc_mode = NAND_ECC_SOFT; | ||
| 562 | if (!strncmp("hw", mode, 2)) | ||
| 563 | pdata->ecc_mode = NAND_ECC_HW; | ||
| 564 | } | ||
| 565 | if (!of_property_read_u32(pdev->dev.of_node, | ||
| 566 | "ti,davinci-ecc-bits", &prop)) | ||
| 567 | pdata->ecc_bits = prop; | ||
| 568 | if (!of_property_read_u32(pdev->dev.of_node, | ||
| 569 | "ti,davinci-nand-buswidth", &prop)) | ||
| 570 | if (prop == 16) | ||
| 571 | pdata->options |= NAND_BUSWIDTH_16; | ||
| 572 | if (of_find_property(pdev->dev.of_node, | ||
| 573 | "ti,davinci-nand-use-bbt", &len)) | ||
| 574 | pdata->bbt_options = NAND_BBT_USE_FLASH; | ||
| 575 | } | ||
| 576 | |||
| 577 | return pdev->dev.platform_data; | ||
| 578 | } | ||
| 579 | #else | ||
| 580 | #define davinci_nand_of_match NULL | ||
| 581 | static struct davinci_nand_pdata | ||
| 582 | *nand_davinci_get_pdata(struct platform_device *pdev) | ||
| 583 | { | ||
| 584 | return pdev->dev.platform_data; | ||
| 585 | } | ||
| 586 | #endif | ||
| 587 | |||
| 521 | static int __init nand_davinci_probe(struct platform_device *pdev) | 588 | static int __init nand_davinci_probe(struct platform_device *pdev) |
| 522 | { | 589 | { |
| 523 | struct davinci_nand_pdata *pdata = pdev->dev.platform_data; | 590 | struct davinci_nand_pdata *pdata; |
| 524 | struct davinci_nand_info *info; | 591 | struct davinci_nand_info *info; |
| 525 | struct resource *res1; | 592 | struct resource *res1; |
| 526 | struct resource *res2; | 593 | struct resource *res2; |
| @@ -530,6 +597,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev) | |||
| 530 | uint32_t val; | 597 | uint32_t val; |
| 531 | nand_ecc_modes_t ecc_mode; | 598 | nand_ecc_modes_t ecc_mode; |
| 532 | 599 | ||
| 600 | pdata = nand_davinci_get_pdata(pdev); | ||
| 533 | /* insist on board-specific configuration */ | 601 | /* insist on board-specific configuration */ |
| 534 | if (!pdata) | 602 | if (!pdata) |
| 535 | return -ENODEV; | 603 | return -ENODEV; |
| @@ -816,6 +884,8 @@ static struct platform_driver nand_davinci_driver = { | |||
| 816 | .remove = __exit_p(nand_davinci_remove), | 884 | .remove = __exit_p(nand_davinci_remove), |
| 817 | .driver = { | 885 | .driver = { |
| 818 | .name = "davinci_nand", | 886 | .name = "davinci_nand", |
| 887 | .owner = THIS_MODULE, | ||
| 888 | .of_match_table = davinci_nand_of_match, | ||
| 819 | }, | 889 | }, |
| 820 | }; | 890 | }; |
| 821 | MODULE_ALIAS("platform:davinci_nand"); | 891 | MODULE_ALIAS("platform:davinci_nand"); |
