ARM: EXYNOS: Add usb otg phy control for EXYNOS4210
authorLukasz Majewski <l.majewski@samsung.com>
Sat, 12 May 2012 23:28:28 +0000 (08:28 +0900)
committerKukjin Kim <kgene.kim@samsung.com>
Wed, 16 May 2012 13:31:44 +0000 (22:31 +0900)
This patch supports to control usb otg phy of EXYNOS4210.

Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
[Rebased on the newest git/kgene/linux-samsung #for-next]
Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
[kgene.kim@samsung.com: squashed 2 patches together]
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
arch/arm/mach-exynos/include/mach/irqs.h
arch/arm/mach-exynos/include/mach/map.h
arch/arm/mach-exynos/include/mach/regs-pmu.h
arch/arm/mach-exynos/setup-usb-phy.c

index 591e785..c02dae7 100644 (file)
 #define IRQ_IIC7                       EXYNOS4_IRQ_IIC7
 
 #define IRQ_USB_HOST                   EXYNOS4_IRQ_USB_HOST
+#define IRQ_OTG                                EXYNOS4_IRQ_USB_HSOTG
 
 #define IRQ_HSMMC0                     EXYNOS4_IRQ_HSMMC0
 #define IRQ_HSMMC1                     EXYNOS4_IRQ_HSMMC1
index 6e6d11f..e009a66 100644 (file)
 #define EXYNOS4_PA_HSMMC(x)            (0x12510000 + ((x) * 0x10000))
 #define EXYNOS4_PA_DWMCI               0x12550000
 
+#define EXYNOS4_PA_HSOTG               0x12480000
+#define EXYNOS4_PA_USB_HSPHY           0x125B0000
+
 #define EXYNOS4_PA_SATA                        0x12560000
 #define EXYNOS4_PA_SATAPHY             0x125D0000
 #define EXYNOS4_PA_SATAPHY_CTRL                0x126B0000
 #define S3C_PA_SPI0                    EXYNOS4_PA_SPI0
 #define S3C_PA_SPI1                    EXYNOS4_PA_SPI1
 #define S3C_PA_SPI2                    EXYNOS4_PA_SPI2
+#define S3C_PA_USB_HSOTG               EXYNOS4_PA_HSOTG
 
 #define S5P_PA_EHCI                    EXYNOS4_PA_EHCI
 #define S5P_PA_FIMC0                   EXYNOS4_PA_FIMC0
index 4c53f38..d457d05 100644 (file)
 #define S5P_CHECK_SLEEP                                0x00000BAD
 
 /* Only for EXYNOS4210 */
+#define S5P_USBDEVICE_PHY_CONTROL      S5P_PMUREG(0x0704)
+#define S5P_USBDEVICE_PHY_ENABLE       (1 << 0)
+
 #define S5P_USBHOST_PHY_CONTROL                S5P_PMUREG(0x0708)
 #define S5P_USBHOST_PHY_ENABLE         (1 << 0)
 
index 41743d2..1af0a7f 100644 (file)
@@ -26,11 +26,71 @@ static int exynos4_usb_host_phy_is_on(void)
        return (readl(EXYNOS4_PHYPWR) & PHY1_STD_ANALOG_POWERDOWN) ? 0 : 1;
 }
 
-static int exynos4_usb_phy1_init(struct platform_device *pdev)
+static void exynos4210_usb_phy_clkset(struct platform_device *pdev)
 {
-       struct clk *otg_clk;
        struct clk *xusbxti_clk;
        u32 phyclk;
+
+       /* set clock frequency for PLL */
+       phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK;
+
+       xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
+       if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {
+               switch (clk_get_rate(xusbxti_clk)) {
+               case 12 * MHZ:
+                       phyclk |= CLKSEL_12M;
+                       break;
+               case 24 * MHZ:
+                       phyclk |= CLKSEL_24M;
+                       break;
+               default:
+               case 48 * MHZ:
+                       /* default reference clock */
+                       break;
+               }
+               clk_put(xusbxti_clk);
+       }
+
+       writel(phyclk, EXYNOS4_PHYCLK);
+}
+
+static int exynos4210_usb_phy0_init(struct platform_device *pdev)
+{
+       u32 rstcon;
+
+       writel(readl(S5P_USBDEVICE_PHY_CONTROL) | S5P_USBDEVICE_PHY_ENABLE,
+                       S5P_USBDEVICE_PHY_CONTROL);
+
+       exynos4210_usb_phy_clkset(pdev);
+
+       /* set to normal PHY0 */
+       writel((readl(EXYNOS4_PHYPWR) & ~PHY0_NORMAL_MASK), EXYNOS4_PHYPWR);
+
+       /* reset PHY0 and Link */
+       rstcon = readl(EXYNOS4_RSTCON) | PHY0_SWRST_MASK;
+       writel(rstcon, EXYNOS4_RSTCON);
+       udelay(10);
+
+       rstcon &= ~PHY0_SWRST_MASK;
+       writel(rstcon, EXYNOS4_RSTCON);
+
+       return 0;
+}
+
+static int exynos4210_usb_phy0_exit(struct platform_device *pdev)
+{
+       writel((readl(EXYNOS4_PHYPWR) | PHY0_ANALOG_POWERDOWN |
+                               PHY0_OTG_DISABLE), EXYNOS4_PHYPWR);
+
+       writel(readl(S5P_USBDEVICE_PHY_CONTROL) & ~S5P_USBDEVICE_PHY_ENABLE,
+                       S5P_USBDEVICE_PHY_CONTROL);
+
+       return 0;
+}
+
+static int exynos4210_usb_phy1_init(struct platform_device *pdev)
+{
+       struct clk *otg_clk;
        u32 rstcon;
        int err;
 
@@ -54,27 +114,7 @@ static int exynos4_usb_phy1_init(struct platform_device *pdev)
        writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE,
                        S5P_USBHOST_PHY_CONTROL);
 
-       /* set clock frequency for PLL */
-       phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK;
-
-       xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
-       if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {
-               switch (clk_get_rate(xusbxti_clk)) {
-               case 12 * MHZ:
-                       phyclk |= CLKSEL_12M;
-                       break;
-               case 24 * MHZ:
-                       phyclk |= CLKSEL_24M;
-                       break;
-               default:
-               case 48 * MHZ:
-                       /* default reference clock */
-                       break;
-               }
-               clk_put(xusbxti_clk);
-       }
-
-       writel(phyclk, EXYNOS4_PHYCLK);
+       exynos4210_usb_phy_clkset(pdev);
 
        /* floating prevention logic: disable */
        writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON);
@@ -102,7 +142,7 @@ static int exynos4_usb_phy1_init(struct platform_device *pdev)
        return 0;
 }
 
-static int exynos4_usb_phy1_exit(struct platform_device *pdev)
+static int exynos4210_usb_phy1_exit(struct platform_device *pdev)
 {
        struct clk *otg_clk;
        int err;
@@ -136,16 +176,20 @@ static int exynos4_usb_phy1_exit(struct platform_device *pdev)
 
 int s5p_usb_phy_init(struct platform_device *pdev, int type)
 {
-       if (type == S5P_USB_PHY_HOST)
-               return exynos4_usb_phy1_init(pdev);
+       if (type == S5P_USB_PHY_DEVICE)
+               return exynos4210_usb_phy0_init(pdev);
+       else if (type == S5P_USB_PHY_HOST)
+               return exynos4210_usb_phy1_init(pdev);
 
        return -EINVAL;
 }
 
 int s5p_usb_phy_exit(struct platform_device *pdev, int type)
 {
-       if (type == S5P_USB_PHY_HOST)
-               return exynos4_usb_phy1_exit(pdev);
+       if (type == S5P_USB_PHY_DEVICE)
+               return exynos4210_usb_phy0_exit(pdev);
+       else if (type == S5P_USB_PHY_HOST)
+               return exynos4210_usb_phy1_exit(pdev);
 
        return -EINVAL;
 }