diff options
Diffstat (limited to 'arch/arm/mach-exynos/setup-usb-phy.c')
-rw-r--r-- | arch/arm/mach-exynos/setup-usb-phy.c | 100 |
1 files changed, 72 insertions, 28 deletions
diff --git a/arch/arm/mach-exynos/setup-usb-phy.c b/arch/arm/mach-exynos/setup-usb-phy.c index 41743d21e8c..1af0a7f44e0 100644 --- a/arch/arm/mach-exynos/setup-usb-phy.c +++ b/arch/arm/mach-exynos/setup-usb-phy.c @@ -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; } |