Merge branch 'master' of git://git.kernel.org/pub/scm/fs/xfs/xfs
[pandora-kernel.git] / arch / powerpc / platforms / 83xx / usb.c
index b45160f..11e1fac 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <linux/of.h>
 
 #include <asm/io.h>
 #include <asm/prom.h>
@@ -22,7 +23,7 @@
 #include "mpc83xx.h"
 
 
-#ifdef CONFIG_MPC834x
+#ifdef CONFIG_PPC_MPC834x
 int mpc834x_usb_cfg(void)
 {
        unsigned long sccr, sicrl, sicrh;
@@ -41,7 +42,7 @@ int mpc834x_usb_cfg(void)
        sicrl = in_be32(immap + MPC83XX_SICRL_OFFS) & ~MPC834X_SICRL_USB_MASK;
        sicrh = in_be32(immap + MPC83XX_SICRH_OFFS) & ~MPC834X_SICRH_USB_UTMI;
 
-       np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr");
+       np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr");
        if (np) {
                sccr |= MPC83XX_SCCR_USB_DRCM_11;  /* 1:3 */
 
@@ -67,7 +68,7 @@ int mpc834x_usb_cfg(void)
                port0_is_dr = 1;
                of_node_put(np);
        }
-       np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph");
+       np = of_find_compatible_node(NULL, NULL, "fsl-usb2-mph");
        if (np) {
                sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */
 
@@ -96,7 +97,7 @@ int mpc834x_usb_cfg(void)
        iounmap(immap);
        return 0;
 }
-#endif /* CONFIG_MPC834x */
+#endif /* CONFIG_PPC_MPC834x */
 
 #ifdef CONFIG_PPC_MPC831x
 int mpc831x_usb_cfg(void)
@@ -104,6 +105,7 @@ int mpc831x_usb_cfg(void)
        u32 temp;
        void __iomem *immap, *usb_regs;
        struct device_node *np = NULL;
+       struct device_node *immr_node = NULL;
        const void *prop;
        struct resource res;
        int ret = 0;
@@ -111,7 +113,7 @@ int mpc831x_usb_cfg(void)
        const void *dr_mode;
 #endif
 
-       np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr");
+       np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr");
        if (!np)
                return -ENODEV;
        prop = of_get_property(np, "phy_type", NULL);
@@ -124,26 +126,40 @@ int mpc831x_usb_cfg(void)
        }
 
        /* Configure clock */
-       temp = in_be32(immap + MPC83XX_SCCR_OFFS);
-       temp &= ~MPC83XX_SCCR_USB_MASK;
-       temp |= MPC83XX_SCCR_USB_DRCM_11;  /* 1:3 */
-       out_be32(immap + MPC83XX_SCCR_OFFS, temp);
+       immr_node = of_get_parent(np);
+       if (immr_node && of_device_is_compatible(immr_node, "fsl,mpc8315-immr"))
+               clrsetbits_be32(immap + MPC83XX_SCCR_OFFS,
+                               MPC8315_SCCR_USB_MASK,
+                               MPC8315_SCCR_USB_DRCM_01);
+       else
+               clrsetbits_be32(immap + MPC83XX_SCCR_OFFS,
+                               MPC83XX_SCCR_USB_MASK,
+                               MPC83XX_SCCR_USB_DRCM_11);
 
        /* Configure pin mux for ULPI.  There is no pin mux for UTMI */
        if (prop && !strcmp(prop, "ulpi")) {
-               temp = in_be32(immap + MPC83XX_SICRL_OFFS);
-               temp &= ~MPC831X_SICRL_USB_MASK;
-               temp |= MPC831X_SICRL_USB_ULPI;
-               out_be32(immap + MPC83XX_SICRL_OFFS, temp);
-
-               temp = in_be32(immap + MPC83XX_SICRH_OFFS);
-               temp &= ~MPC831X_SICRH_USB_MASK;
-               temp |= MPC831X_SICRH_USB_ULPI;
-               out_be32(immap + MPC83XX_SICRH_OFFS, temp);
+               if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr")) {
+                       clrsetbits_be32(immap + MPC83XX_SICRL_OFFS,
+                                       MPC8315_SICRL_USB_MASK,
+                                       MPC8315_SICRL_USB_ULPI);
+                       clrsetbits_be32(immap + MPC83XX_SICRH_OFFS,
+                                       MPC8315_SICRH_USB_MASK,
+                                       MPC8315_SICRH_USB_ULPI);
+               } else {
+                       clrsetbits_be32(immap + MPC83XX_SICRL_OFFS,
+                                       MPC831X_SICRL_USB_MASK,
+                                       MPC831X_SICRL_USB_ULPI);
+                       clrsetbits_be32(immap + MPC83XX_SICRH_OFFS,
+                                       MPC831X_SICRH_USB_MASK,
+                                       MPC831X_SICRH_USB_ULPI);
+               }
        }
 
        iounmap(immap);
 
+       if (immr_node)
+               of_node_put(immr_node);
+
        /* Map USB SOC space */
        ret = of_address_to_resource(np, 0, &res);
        if (ret) {
@@ -155,9 +171,15 @@ int mpc831x_usb_cfg(void)
        /* Using on-chip PHY */
        if (prop && (!strcmp(prop, "utmi_wide") ||
                     !strcmp(prop, "utmi"))) {
-               /* Set UTMI_PHY_EN, REFSEL to 48MHZ */
+               u32 refsel;
+
+               if (of_device_is_compatible(immr_node, "fsl,mpc8315-immr"))
+                       refsel = CONTROL_REFSEL_24MHZ;
+               else
+                       refsel = CONTROL_REFSEL_48MHZ;
+               /* Set UTMI_PHY_EN and REFSEL */
                out_be32(usb_regs + FSL_USB2_CONTROL_OFFS,
-                               CONTROL_UTMI_PHY_EN | CONTROL_REFSEL_48MHZ);
+                               CONTROL_UTMI_PHY_EN | refsel);
        /* Using external UPLI PHY */
        } else if (prop && !strcmp(prop, "ulpi")) {
                /* Set PHY_CLK_SEL to ULPI */
@@ -179,3 +201,43 @@ int mpc831x_usb_cfg(void)
        return ret;
 }
 #endif /* CONFIG_PPC_MPC831x */
+
+#ifdef CONFIG_PPC_MPC837x
+int mpc837x_usb_cfg(void)
+{
+       void __iomem *immap;
+       struct device_node *np = NULL;
+       const void *prop;
+       int ret = 0;
+
+       np = of_find_compatible_node(NULL, NULL, "fsl-usb2-dr");
+       if (!np || !of_device_is_available(np))
+               return -ENODEV;
+       prop = of_get_property(np, "phy_type", NULL);
+
+       if (!prop || (strcmp(prop, "ulpi") && strcmp(prop, "serial"))) {
+               printk(KERN_WARNING "837x USB PHY type not supported\n");
+               of_node_put(np);
+               return -EINVAL;
+       }
+
+       /* Map IMMR space for pin and clock settings */
+       immap = ioremap(get_immrbase(), 0x1000);
+       if (!immap) {
+               of_node_put(np);
+               return -ENOMEM;
+       }
+
+       /* Configure clock */
+       clrsetbits_be32(immap + MPC83XX_SCCR_OFFS, MPC837X_SCCR_USB_DRCM_11,
+                       MPC837X_SCCR_USB_DRCM_11);
+
+       /* Configure pin mux for ULPI/serial */
+       clrsetbits_be32(immap + MPC83XX_SICRL_OFFS, MPC837X_SICRL_USB_MASK,
+                       MPC837X_SICRL_USB_ULPI);
+
+       iounmap(immap);
+       of_node_put(np);
+       return ret;
+}
+#endif /* CONFIG_PPC_MPC837x */