aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/mtd/spear_smi.txt31
-rw-r--r--drivers/mtd/devices/spear_smi.c111
-rw-r--r--include/linux/mtd/spear_smi.h5
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
3Required 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
13Optional properties:
14- st,smi-fast-mode : Flash supports read in fast mode
15
16Example:
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
751static int spear_smi_setup_banks(struct platform_device *pdev, u32 bank) 750
751#ifdef CONFIG_OF
752static 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
795static int __devinit spear_smi_probe_config_dt(struct platform_device *pdev,
796 struct device_node *np)
797{
798 return -ENOSYS;
799}
800#endif
801
802static 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 */
848static int __devinit spear_smi_probe(struct platform_device *pdev) 906static 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:
967static int __devexit spear_smi_remove(struct platform_device *pdev) 1042static 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
1113static const struct of_device_id spear_smi_id_table[] = {
1114 { .compatible = "st,spear600-smi" },
1115 {}
1116};
1117MODULE_DEVICE_TABLE(of, spear_smi_id_table);
1118#endif
1119
1034static struct platform_driver spear_smi_driver = { 1120static 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 */