]> err.no Git - linux-2.6/blobdiff - arch/powerpc/sysdev/fsl_soc.c
[POWERPC] fsl_soc: add support for fsl_spi
[linux-2.6] / arch / powerpc / sysdev / fsl_soc.c
index 7012e51ae5c6eaa9bea0d3c0e0b2e11cce20227e..d028e8da027b1e479e6b6c151befb63499ff8aa9 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/platform_device.h>
 #include <linux/of_platform.h>
 #include <linux/phy.h>
+#include <linux/spi/spi.h>
 #include <linux/fsl_devices.h>
 #include <linux/fs_enet_pd.h>
 #include <linux/fs_uart_pd.h>
@@ -1199,3 +1200,89 @@ err:
 arch_initcall(cpm_smc_uart_of_init);
 
 #endif /* CONFIG_8xx */
+
+int __init fsl_spi_init(struct spi_board_info *board_infos,
+                       unsigned int num_board_infos,
+                       void (*activate_cs)(u8 cs, u8 polarity),
+                       void (*deactivate_cs)(u8 cs, u8 polarity))
+{
+       struct device_node *np;
+       unsigned int i;
+       const u32 *sysclk;
+
+       np = of_find_node_by_type(NULL, "qe");
+       if (!np)
+               return -ENODEV;
+
+       sysclk = of_get_property(np, "bus-frequency", NULL);
+       if (!sysclk)
+               return -ENODEV;
+
+       for (np = NULL, i = 1;
+            (np = of_find_compatible_node(np, "spi", "fsl_spi")) != NULL;
+            i++) {
+               int ret = 0;
+               unsigned int j;
+               const void *prop;
+               struct resource res[2];
+               struct platform_device *pdev;
+               struct fsl_spi_platform_data pdata = {
+                       .activate_cs = activate_cs,
+                       .deactivate_cs = deactivate_cs,
+               };
+
+               memset(res, 0, sizeof(res));
+
+               pdata.sysclk = *sysclk;
+
+               prop = of_get_property(np, "reg", NULL);
+               if (!prop)
+                       goto err;
+               pdata.bus_num = *(u32 *)prop;
+
+               prop = of_get_property(np, "mode", NULL);
+               if (prop && !strcmp(prop, "cpu-qe"))
+                       pdata.qe_mode = 1;
+
+               for (j = 0; j < num_board_infos; j++) {
+                       if (board_infos[j].bus_num == pdata.bus_num)
+                               pdata.max_chipselect++;
+               }
+
+               if (!pdata.max_chipselect)
+                       goto err;
+
+               ret = of_address_to_resource(np, 0, &res[0]);
+               if (ret)
+                       goto err;
+
+               ret = of_irq_to_resource(np, 0, &res[1]);
+               if (ret == NO_IRQ)
+                       goto err;
+
+               pdev = platform_device_alloc("mpc83xx_spi", i);
+               if (!pdev)
+                       goto err;
+
+               ret = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+               if (ret)
+                       goto unreg;
+
+               ret = platform_device_add_resources(pdev, res,
+                                                   ARRAY_SIZE(res));
+               if (ret)
+                       goto unreg;
+
+               ret = platform_device_register(pdev);
+               if (ret)
+                       goto unreg;
+
+               continue;
+unreg:
+               platform_device_del(pdev);
+err:
+               continue;
+       }
+
+       return spi_register_board_info(board_infos, num_board_infos);
+}