[POWERPC] FSL: enet device tree cleanups
[pandora-kernel.git] / arch / powerpc / sysdev / fsl_soc.c
index 727453d..4baad80 100644 (file)
@@ -22,7 +22,9 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #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>
@@ -51,13 +53,13 @@ phys_addr_t get_immrbase(void)
 
        soc = of_find_node_by_type(NULL, "soc");
        if (soc) {
-               unsigned int size;
+               int size;
                const void *prop = of_get_property(soc, "reg", &size);
 
                if (prop)
                        immrbase = of_translate_address(soc, prop);
                of_node_put(soc);
-       };
+       }
 
        return immrbase;
 }
@@ -71,20 +73,31 @@ static u32 brgfreq = -1;
 u32 get_brgfreq(void)
 {
        struct device_node *node;
+       const unsigned int *prop;
+       int size;
 
        if (brgfreq != -1)
                return brgfreq;
 
-       node = of_find_node_by_type(NULL, "cpm");
+       node = of_find_compatible_node(NULL, NULL, "fsl,cpm-brg");
        if (node) {
-               unsigned int size;
-               const unsigned int *prop = of_get_property(node,
-                                       "brg-frequency", &size);
+               prop = of_get_property(node, "clock-frequency", &size);
+               if (prop && size == 4)
+                       brgfreq = *prop;
 
-               if (prop)
+               of_node_put(node);
+               return brgfreq;
+       }
+
+       /* Legacy device binding -- will go away when no users are left. */
+       node = of_find_node_by_type(NULL, "cpm");
+       if (node) {
+               prop = of_get_property(node, "brg-frequency", &size);
+               if (prop && size == 4)
                        brgfreq = *prop;
+
                of_node_put(node);
-       };
+       }
 
        return brgfreq;
 }
@@ -102,14 +115,14 @@ u32 get_baudrate(void)
 
        node = of_find_node_by_type(NULL, "serial");
        if (node) {
-               unsigned int size;
+               int size;
                const unsigned int *prop = of_get_property(node,
                                "current-speed", &size);
 
                if (prop)
                        fs_baudrate = *prop;
                of_node_put(node);
-       };
+       }
 
        return fs_baudrate;
 }
@@ -119,15 +132,18 @@ EXPORT_SYMBOL(get_baudrate);
 
 static int __init gfar_mdio_of_init(void)
 {
-       struct device_node *np;
-       unsigned int i;
+       struct device_node *np = NULL;
        struct platform_device *mdio_dev;
        struct resource res;
        int ret;
 
-       for (np = NULL, i = 0;
-            (np = of_find_compatible_node(np, "mdio", "gianfar")) != NULL;
-            i++) {
+       np = of_find_compatible_node(np, NULL, "fsl,gianfar-mdio");
+
+       /* try the deprecated version */
+       if (!np)
+               np = of_find_compatible_node(np, "mdio", "gianfar");
+
+       if (np) {
                int k;
                struct device_node *child = NULL;
                struct gianfar_mdio_data mdio_data;
@@ -166,11 +182,13 @@ static int __init gfar_mdio_of_init(void)
                        goto unreg;
        }
 
+       of_node_put(np);
        return 0;
 
 unreg:
        platform_device_unregister(mdio_dev);
 err:
+       of_node_put(np);
        return ret;
 }
 
@@ -318,34 +336,46 @@ static struct i2c_driver_device i2c_devices[] __initdata = {
        {"ricoh,rs5c372b", "rtc-rs5c372", "rs5c372b",},
        {"ricoh,rv5c386",  "rtc-rs5c372", "rv5c386",},
        {"ricoh,rv5c387a", "rtc-rs5c372", "rv5c387a",},
+       {"dallas,ds1307",  "rtc-ds1307",  "ds1307",},
+       {"dallas,ds1337",  "rtc-ds1307",  "ds1337",},
+       {"dallas,ds1338",  "rtc-ds1307",  "ds1338",},
+       {"dallas,ds1339",  "rtc-ds1307",  "ds1339",},
+       {"dallas,ds1340",  "rtc-ds1307",  "ds1340",},
+       {"stm,m41t00",     "rtc-ds1307",  "m41t00"},
+       {"dallas,ds1374",  "rtc-ds1374",  "rtc-ds1374",},
 };
 
-static int __init of_find_i2c_driver(struct device_node *node, struct i2c_board_info *info)
+static int __init of_find_i2c_driver(struct device_node *node,
+                                    struct i2c_board_info *info)
 {
        int i;
 
        for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) {
                if (!of_device_is_compatible(node, i2c_devices[i].of_device))
                        continue;
-               strncpy(info->driver_name, i2c_devices[i].i2c_driver, KOBJ_NAME_LEN);
-               strncpy(info->type, i2c_devices[i].i2c_type, I2C_NAME_SIZE);
+               if (strlcpy(info->driver_name, i2c_devices[i].i2c_driver,
+                           KOBJ_NAME_LEN) >= KOBJ_NAME_LEN ||
+                   strlcpy(info->type, i2c_devices[i].i2c_type,
+                           I2C_NAME_SIZE) >= I2C_NAME_SIZE)
+                       return -ENOMEM;
                return 0;
        }
        return -ENODEV;
 }
 
-static void __init of_register_i2c_devices(struct device_node *adap_node, int bus_num)
+static void __init of_register_i2c_devices(struct device_node *adap_node,
+                                          int bus_num)
 {
        struct device_node *node = NULL;
 
        while ((node = of_get_next_child(adap_node, node))) {
-               struct i2c_board_info info;
+               struct i2c_board_info info = {};
                const u32 *addr;
                int len;
 
                addr = of_get_property(node, "reg", &len);
                if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) {
-                       printk(KERN_WARNING "fsl_ioc.c: invalid i2c device entry\n");
+                       printk(KERN_WARNING "fsl_soc.c: invalid i2c device entry\n");
                        continue;
                }
 
@@ -356,7 +386,6 @@ static void __init of_register_i2c_devices(struct device_node *adap_node, int bu
                if (of_find_i2c_driver(node, &info) < 0)
                        continue;
 
-               info.platform_data = NULL;
                info.addr = *addr;
 
                i2c_register_board_info(bus_num, &info, 1);
@@ -366,13 +395,11 @@ static void __init of_register_i2c_devices(struct device_node *adap_node, int bu
 static int __init fsl_i2c_of_init(void)
 {
        struct device_node *np;
-       unsigned int i;
+       unsigned int i = 0;
        struct platform_device *i2c_dev;
        int ret;
 
-       for (np = NULL, i = 0;
-            (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL;
-            i++) {
+       for_each_compatible_node(np, NULL, "fsl-i2c") {
                struct resource r[2];
                struct fsl_i2c_platform_data i2c_data;
                const unsigned char *flags = NULL;
@@ -408,7 +435,7 @@ static int __init fsl_i2c_of_init(void)
                if (ret)
                        goto unreg;
 
-               of_register_i2c_devices(np, i);
+               of_register_i2c_devices(np, i++);
        }
 
        return 0;
@@ -647,6 +674,7 @@ err:
 
 arch_initcall(fsl_usb_of_init);
 
+#ifndef CONFIG_PPC_CPM_NEW_BINDING
 #ifdef CONFIG_CPM2
 
 extern void init_scc_ioports(struct fs_uart_platform_info*);
@@ -1186,3 +1214,132 @@ err:
 arch_initcall(cpm_smc_uart_of_init);
 
 #endif /* CONFIG_8xx */
+#endif /* CONFIG_PPC_CPM_NEW_BINDING */
+
+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;
+
+       /* SPI controller is either clocked from QE or SoC clock */
+       np = of_find_node_by_type(NULL, "qe");
+       if (!np)
+               np = of_find_node_by_type(NULL, "soc");
+
+       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);
+}
+
+#if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx)
+static __be32 __iomem *rstcr;
+
+static int __init setup_rstcr(void)
+{
+       struct device_node *np;
+       np = of_find_node_by_name(NULL, "global-utilities");
+       if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) {
+               const u32 *prop = of_get_property(np, "reg", NULL);
+               if (prop) {
+                       /* map reset control register
+                        * 0xE00B0 is offset of reset control register
+                        */
+                       rstcr = ioremap(get_immrbase() + *prop + 0xB0, 0xff);
+                       if (!rstcr)
+                               printk (KERN_EMERG "Error: reset control "
+                                               "register not mapped!\n");
+               }
+       } else
+               printk (KERN_INFO "rstcr compatible register does not exist!\n");
+       if (np)
+               of_node_put(np);
+       return 0;
+}
+
+arch_initcall(setup_rstcr);
+
+void fsl_rstcr_restart(char *cmd)
+{
+       local_irq_disable();
+       if (rstcr)
+               /* set reset control register */
+               out_be32(rstcr, 0x2);   /* HRESET_REQ */
+
+       while (1) ;
+}
+#endif