diff options
| author | Stefan Roese <sr@denx.de> | 2012-03-16 06:42:11 -0400 |
|---|---|---|
| committer | David Woodhouse <David.Woodhouse@intel.com> | 2012-03-26 20:01:21 -0400 |
| commit | 6551ab5d30d6bf0cea0c6cb294686ce3c7fc6042 (patch) | |
| tree | ba88add42bc6bf9d72feeb142afd601782051cdc | |
| parent | f7e3dd8f48faad24334f7bea048ea59a2c766587 (diff) | |
mtd: add device-tree support to spear_smi
This patch adds support to configure the SPEAr SMI driver via
device-tree instead of platform_data.
Signed-off-by: Stefan Roese <sr@denx.de>
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/mtd/spear_smi.txt | 31 | ||||
| -rw-r--r-- | drivers/mtd/devices/spear_smi.c | 111 | ||||
| -rw-r--r-- | include/linux/mtd/spear_smi.h | 5 |
3 files changed, 135 insertions, 12 deletions
diff --git a/Documentation/devicetree/bindings/mtd/spear_smi.txt b/Documentation/devicetree/bindings/mtd/spear_smi.txt new file mode 100644 index 000000000000..7248aadd89e4 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/spear_smi.txt | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | * SPEAr SMI | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible : "st,spear600-smi" | ||
| 5 | - reg : Address range of the mtd chip | ||
| 6 | - #address-cells, #size-cells : Must be present if the device has sub-nodes | ||
| 7 | representing partitions. | ||
| 8 | - interrupt-parent: Should be the phandle for the interrupt controller | ||
| 9 | that services interrupts for this device | ||
| 10 | - interrupts: Should contain the STMMAC interrupts | ||
| 11 | - clock-rate : Functional clock rate of SMI in Hz | ||
| 12 | |||
| 13 | Optional properties: | ||
| 14 | - st,smi-fast-mode : Flash supports read in fast mode | ||
| 15 | |||
| 16 | Example: | ||
| 17 | |||
| 18 | smi: flash@fc000000 { | ||
| 19 | compatible = "st,spear600-smi"; | ||
| 20 | #address-cells = <1>; | ||
| 21 | #size-cells = <1>; | ||
| 22 | reg = <0xfc000000 0x1000>; | ||
| 23 | interrupt-parent = <&vic1>; | ||
| 24 | interrupts = <12>; | ||
| 25 | clock-rate = <50000000>; /* 50MHz */ | ||
| 26 | |||
| 27 | flash@f8000000 { | ||
| 28 | st,smi-fast-mode; | ||
| 29 | ... | ||
| 30 | }; | ||
| 31 | }; | ||
diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c index f7f34fd1a3e5..797d43cd3550 100644 --- a/drivers/mtd/devices/spear_smi.c +++ b/drivers/mtd/devices/spear_smi.c | |||
| @@ -33,9 +33,8 @@ | |||
| 33 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
| 34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
| 35 | #include <linux/wait.h> | 35 | #include <linux/wait.h> |
| 36 | 36 | #include <linux/of.h> | |
| 37 | /* max possible slots for serial-nor flash chip in the SMI controller */ | 37 | #include <linux/of_address.h> |
| 38 | #define MAX_NUM_FLASH_CHIP 4 | ||
| 39 | 38 | ||
| 40 | /* SMI clock rate */ | 39 | /* SMI clock rate */ |
| 41 | #define SMI_MAX_CLOCK_FREQ 50000000 /* 50 MHz */ | 40 | #define SMI_MAX_CLOCK_FREQ 50000000 /* 50 MHz */ |
| @@ -748,9 +747,63 @@ err_probe: | |||
| 748 | return ret; | 747 | return ret; |
| 749 | } | 748 | } |
| 750 | 749 | ||
| 751 | static int spear_smi_setup_banks(struct platform_device *pdev, u32 bank) | 750 | |
| 751 | #ifdef CONFIG_OF | ||
| 752 | static int __devinit spear_smi_probe_config_dt(struct platform_device *pdev, | ||
| 753 | struct device_node *np) | ||
| 754 | { | ||
| 755 | struct spear_smi_plat_data *pdata = dev_get_platdata(&pdev->dev); | ||
| 756 | struct device_node *pp = NULL; | ||
| 757 | const __be32 *addr; | ||
| 758 | u32 val; | ||
| 759 | int len; | ||
| 760 | int i = 0; | ||
| 761 | |||
| 762 | if (!np) | ||
| 763 | return -ENODEV; | ||
| 764 | |||
| 765 | of_property_read_u32(np, "clock-rate", &val); | ||
| 766 | pdata->clk_rate = val; | ||
| 767 | |||
| 768 | pdata->board_flash_info = devm_kzalloc(&pdev->dev, | ||
| 769 | sizeof(*pdata->board_flash_info), | ||
| 770 | GFP_KERNEL); | ||
| 771 | |||
| 772 | /* Fill structs for each subnode (flash device) */ | ||
| 773 | while ((pp = of_get_next_child(np, pp))) { | ||
| 774 | struct spear_smi_flash_info *flash_info; | ||
| 775 | |||
| 776 | flash_info = &pdata->board_flash_info[i]; | ||
| 777 | pdata->np[i] = pp; | ||
| 778 | |||
| 779 | /* Read base-addr and size from DT */ | ||
| 780 | addr = of_get_property(pp, "reg", &len); | ||
| 781 | pdata->board_flash_info->mem_base = be32_to_cpup(&addr[0]); | ||
| 782 | pdata->board_flash_info->size = be32_to_cpup(&addr[1]); | ||
| 783 | |||
| 784 | if (of_get_property(pp, "st,smi-fast-mode", NULL)) | ||
| 785 | pdata->board_flash_info->fast_mode = 1; | ||
| 786 | |||
| 787 | i++; | ||
| 788 | } | ||
| 789 | |||
| 790 | pdata->num_flashes = i; | ||
| 791 | |||
| 792 | return 0; | ||
| 793 | } | ||
| 794 | #else | ||
| 795 | static int __devinit spear_smi_probe_config_dt(struct platform_device *pdev, | ||
| 796 | struct device_node *np) | ||
| 797 | { | ||
| 798 | return -ENOSYS; | ||
| 799 | } | ||
| 800 | #endif | ||
| 801 | |||
| 802 | static int spear_smi_setup_banks(struct platform_device *pdev, | ||
| 803 | u32 bank, struct device_node *np) | ||
| 752 | { | 804 | { |
| 753 | struct spear_smi *dev = platform_get_drvdata(pdev); | 805 | struct spear_smi *dev = platform_get_drvdata(pdev); |
| 806 | struct mtd_part_parser_data ppdata = {}; | ||
| 754 | struct spear_smi_flash_info *flash_info; | 807 | struct spear_smi_flash_info *flash_info; |
| 755 | struct spear_smi_plat_data *pdata; | 808 | struct spear_smi_plat_data *pdata; |
| 756 | struct spear_snor_flash *flash; | 809 | struct spear_snor_flash *flash; |
| @@ -816,11 +869,16 @@ static int spear_smi_setup_banks(struct platform_device *pdev, u32 bank) | |||
| 816 | dev_info(&dev->pdev->dev, ".erasesize = 0x%x(%uK)\n", | 869 | dev_info(&dev->pdev->dev, ".erasesize = 0x%x(%uK)\n", |
| 817 | flash->mtd.erasesize, flash->mtd.erasesize / 1024); | 870 | flash->mtd.erasesize, flash->mtd.erasesize / 1024); |
| 818 | 871 | ||
| 872 | #ifndef CONFIG_OF | ||
| 819 | if (flash_info->partitions) { | 873 | if (flash_info->partitions) { |
| 820 | parts = flash_info->partitions; | 874 | parts = flash_info->partitions; |
| 821 | count = flash_info->nr_partitions; | 875 | count = flash_info->nr_partitions; |
| 822 | } | 876 | } |
| 823 | ret = mtd_device_parse_register(&flash->mtd, NULL, NULL, parts, count); | 877 | #endif |
| 878 | ppdata.of_node = np; | ||
| 879 | |||
| 880 | ret = mtd_device_parse_register(&flash->mtd, NULL, &ppdata, parts, | ||
| 881 | count); | ||
| 824 | if (ret) { | 882 | if (ret) { |
| 825 | dev_err(&dev->pdev->dev, "Err MTD partition=%d\n", ret); | 883 | dev_err(&dev->pdev->dev, "Err MTD partition=%d\n", ret); |
| 826 | goto err_map; | 884 | goto err_map; |
| @@ -847,17 +905,34 @@ err_probe: | |||
| 847 | */ | 905 | */ |
| 848 | static int __devinit spear_smi_probe(struct platform_device *pdev) | 906 | static int __devinit spear_smi_probe(struct platform_device *pdev) |
| 849 | { | 907 | { |
| 850 | struct spear_smi_plat_data *pdata; | 908 | struct device_node *np = pdev->dev.of_node; |
| 909 | struct spear_smi_plat_data *pdata = NULL; | ||
| 851 | struct spear_smi *dev; | 910 | struct spear_smi *dev; |
| 852 | struct resource *smi_base; | 911 | struct resource *smi_base; |
| 853 | int irq, ret = 0; | 912 | int irq, ret = 0; |
| 854 | int i; | 913 | int i; |
| 855 | 914 | ||
| 856 | pdata = dev_get_platdata(&pdev->dev); | 915 | if (np) { |
| 857 | if (pdata < 0) { | 916 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
| 858 | ret = -ENODEV; | 917 | if (!pdata) { |
| 859 | dev_err(&pdev->dev, "no platform data\n"); | 918 | pr_err("%s: ERROR: no memory", __func__); |
| 860 | goto err; | 919 | ret = -ENOMEM; |
| 920 | goto err; | ||
| 921 | } | ||
| 922 | pdev->dev.platform_data = pdata; | ||
| 923 | ret = spear_smi_probe_config_dt(pdev, np); | ||
| 924 | if (ret) { | ||
| 925 | ret = -ENODEV; | ||
| 926 | dev_err(&pdev->dev, "no platform data\n"); | ||
| 927 | goto err; | ||
| 928 | } | ||
| 929 | } else { | ||
| 930 | pdata = dev_get_platdata(&pdev->dev); | ||
| 931 | if (pdata < 0) { | ||
| 932 | ret = -ENODEV; | ||
| 933 | dev_err(&pdev->dev, "no platform data\n"); | ||
| 934 | goto err; | ||
| 935 | } | ||
| 861 | } | 936 | } |
| 862 | 937 | ||
| 863 | smi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 938 | smi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| @@ -932,7 +1007,7 @@ static int __devinit spear_smi_probe(struct platform_device *pdev) | |||
| 932 | 1007 | ||
| 933 | /* loop for each serial nor-flash which is connected to smi */ | 1008 | /* loop for each serial nor-flash which is connected to smi */ |
| 934 | for (i = 0; i < dev->num_flashes; i++) { | 1009 | for (i = 0; i < dev->num_flashes; i++) { |
| 935 | ret = spear_smi_setup_banks(pdev, i); | 1010 | ret = spear_smi_setup_banks(pdev, i, pdata->np[i]); |
| 936 | if (ret) { | 1011 | if (ret) { |
| 937 | dev_err(&dev->pdev->dev, "bank setup failed\n"); | 1012 | dev_err(&dev->pdev->dev, "bank setup failed\n"); |
| 938 | goto err_bank_setup; | 1013 | goto err_bank_setup; |
| @@ -967,6 +1042,7 @@ err: | |||
| 967 | static int __devexit spear_smi_remove(struct platform_device *pdev) | 1042 | static int __devexit spear_smi_remove(struct platform_device *pdev) |
| 968 | { | 1043 | { |
| 969 | struct spear_smi *dev; | 1044 | struct spear_smi *dev; |
| 1045 | struct spear_smi_plat_data *pdata; | ||
| 970 | struct spear_snor_flash *flash; | 1046 | struct spear_snor_flash *flash; |
| 971 | struct resource *smi_base; | 1047 | struct resource *smi_base; |
| 972 | int ret; | 1048 | int ret; |
| @@ -978,6 +1054,8 @@ static int __devexit spear_smi_remove(struct platform_device *pdev) | |||
| 978 | return -ENODEV; | 1054 | return -ENODEV; |
| 979 | } | 1055 | } |
| 980 | 1056 | ||
| 1057 | pdata = dev_get_platdata(&pdev->dev); | ||
| 1058 | |||
| 981 | /* clean up for all nor flash */ | 1059 | /* clean up for all nor flash */ |
| 982 | for (i = 0; i < dev->num_flashes; i++) { | 1060 | for (i = 0; i < dev->num_flashes; i++) { |
| 983 | flash = dev->flash[i]; | 1061 | flash = dev->flash[i]; |
| @@ -1031,11 +1109,20 @@ int spear_smi_resume(struct platform_device *pdev) | |||
| 1031 | return ret; | 1109 | return ret; |
| 1032 | } | 1110 | } |
| 1033 | 1111 | ||
| 1112 | #ifdef CONFIG_OF | ||
| 1113 | static const struct of_device_id spear_smi_id_table[] = { | ||
| 1114 | { .compatible = "st,spear600-smi" }, | ||
| 1115 | {} | ||
| 1116 | }; | ||
| 1117 | MODULE_DEVICE_TABLE(of, spear_smi_id_table); | ||
| 1118 | #endif | ||
| 1119 | |||
| 1034 | static struct platform_driver spear_smi_driver = { | 1120 | static struct platform_driver spear_smi_driver = { |
| 1035 | .driver = { | 1121 | .driver = { |
| 1036 | .name = "smi", | 1122 | .name = "smi", |
| 1037 | .bus = &platform_bus_type, | 1123 | .bus = &platform_bus_type, |
| 1038 | .owner = THIS_MODULE, | 1124 | .owner = THIS_MODULE, |
| 1125 | .of_match_table = of_match_ptr(spear_smi_id_table), | ||
| 1039 | }, | 1126 | }, |
| 1040 | .probe = spear_smi_probe, | 1127 | .probe = spear_smi_probe, |
| 1041 | .remove = __devexit_p(spear_smi_remove), | 1128 | .remove = __devexit_p(spear_smi_remove), |
diff --git a/include/linux/mtd/spear_smi.h b/include/linux/mtd/spear_smi.h index 4e26b4e38da3..8ae1726044c3 100644 --- a/include/linux/mtd/spear_smi.h +++ b/include/linux/mtd/spear_smi.h | |||
| @@ -14,6 +14,10 @@ | |||
| 14 | #include <linux/mtd/mtd.h> | 14 | #include <linux/mtd/mtd.h> |
| 15 | #include <linux/mtd/partitions.h> | 15 | #include <linux/mtd/partitions.h> |
| 16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| 17 | #include <linux/of.h> | ||
| 18 | |||
| 19 | /* max possible slots for serial-nor flash chip in the SMI controller */ | ||
| 20 | #define MAX_NUM_FLASH_CHIP 4 | ||
| 17 | 21 | ||
| 18 | /* macro to define partitions for flash devices */ | 22 | /* macro to define partitions for flash devices */ |
| 19 | #define DEFINE_PARTS(n, of, s) \ | 23 | #define DEFINE_PARTS(n, of, s) \ |
| @@ -55,6 +59,7 @@ struct spear_smi_plat_data { | |||
| 55 | unsigned long clk_rate; | 59 | unsigned long clk_rate; |
| 56 | int num_flashes; | 60 | int num_flashes; |
| 57 | struct spear_smi_flash_info *board_flash_info; | 61 | struct spear_smi_flash_info *board_flash_info; |
| 62 | struct device_node *np[MAX_NUM_FLASH_CHIP]; | ||
| 58 | }; | 63 | }; |
| 59 | 64 | ||
| 60 | #endif /* __MTD_SPEAR_SMI_H */ | 65 | #endif /* __MTD_SPEAR_SMI_H */ |
