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 /drivers/mtd/devices | |
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>
Diffstat (limited to 'drivers/mtd/devices')
-rw-r--r-- | drivers/mtd/devices/spear_smi.c | 111 |
1 files changed, 99 insertions, 12 deletions
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), |