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) | |||
26 | return (readl(EXYNOS4_PHYPWR) & PHY1_STD_ANALOG_POWERDOWN) ? 0 : 1; | 26 | return (readl(EXYNOS4_PHYPWR) & PHY1_STD_ANALOG_POWERDOWN) ? 0 : 1; |
27 | } | 27 | } |
28 | 28 | ||
29 | static int exynos4_usb_phy1_init(struct platform_device *pdev) | 29 | static void exynos4210_usb_phy_clkset(struct platform_device *pdev) |
30 | { | 30 | { |
31 | struct clk *otg_clk; | ||
32 | struct clk *xusbxti_clk; | 31 | struct clk *xusbxti_clk; |
33 | u32 phyclk; | 32 | u32 phyclk; |
33 | |||
34 | /* set clock frequency for PLL */ | ||
35 | phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK; | ||
36 | |||
37 | xusbxti_clk = clk_get(&pdev->dev, "xusbxti"); | ||
38 | if (xusbxti_clk && !IS_ERR(xusbxti_clk)) { | ||
39 | switch (clk_get_rate(xusbxti_clk)) { | ||
40 | case 12 * MHZ: | ||
41 | phyclk |= CLKSEL_12M; | ||
42 | break; | ||
43 | case 24 * MHZ: | ||
44 | phyclk |= CLKSEL_24M; | ||
45 | break; | ||
46 | default: | ||
47 | case 48 * MHZ: | ||
48 | /* default reference clock */ | ||
49 | break; | ||
50 | } | ||
51 | clk_put(xusbxti_clk); | ||
52 | } | ||
53 | |||
54 | writel(phyclk, EXYNOS4_PHYCLK); | ||
55 | } | ||
56 | |||
57 | static int exynos4210_usb_phy0_init(struct platform_device *pdev) | ||
58 | { | ||
59 | u32 rstcon; | ||
60 | |||
61 | writel(readl(S5P_USBDEVICE_PHY_CONTROL) | S5P_USBDEVICE_PHY_ENABLE, | ||
62 | S5P_USBDEVICE_PHY_CONTROL); | ||
63 | |||
64 | exynos4210_usb_phy_clkset(pdev); | ||
65 | |||
66 | /* set to normal PHY0 */ | ||
67 | writel((readl(EXYNOS4_PHYPWR) & ~PHY0_NORMAL_MASK), EXYNOS4_PHYPWR); | ||
68 | |||
69 | /* reset PHY0 and Link */ | ||
70 | rstcon = readl(EXYNOS4_RSTCON) | PHY0_SWRST_MASK; | ||
71 | writel(rstcon, EXYNOS4_RSTCON); | ||
72 | udelay(10); | ||
73 | |||
74 | rstcon &= ~PHY0_SWRST_MASK; | ||
75 | writel(rstcon, EXYNOS4_RSTCON); | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static int exynos4210_usb_phy0_exit(struct platform_device *pdev) | ||
81 | { | ||
82 | writel((readl(EXYNOS4_PHYPWR) | PHY0_ANALOG_POWERDOWN | | ||
83 | PHY0_OTG_DISABLE), EXYNOS4_PHYPWR); | ||
84 | |||
85 | writel(readl(S5P_USBDEVICE_PHY_CONTROL) & ~S5P_USBDEVICE_PHY_ENABLE, | ||
86 | S5P_USBDEVICE_PHY_CONTROL); | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static int exynos4210_usb_phy1_init(struct platform_device *pdev) | ||
92 | { | ||
93 | struct clk *otg_clk; | ||
34 | u32 rstcon; | 94 | u32 rstcon; |
35 | int err; | 95 | int err; |
36 | 96 | ||
@@ -54,27 +114,7 @@ static int exynos4_usb_phy1_init(struct platform_device *pdev) | |||
54 | writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE, | 114 | writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE, |
55 | S5P_USBHOST_PHY_CONTROL); | 115 | S5P_USBHOST_PHY_CONTROL); |
56 | 116 | ||
57 | /* set clock frequency for PLL */ | 117 | exynos4210_usb_phy_clkset(pdev); |
58 | phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK; | ||
59 | |||
60 | xusbxti_clk = clk_get(&pdev->dev, "xusbxti"); | ||
61 | if (xusbxti_clk && !IS_ERR(xusbxti_clk)) { | ||
62 | switch (clk_get_rate(xusbxti_clk)) { | ||
63 | case 12 * MHZ: | ||
64 | phyclk |= CLKSEL_12M; | ||
65 | break; | ||
66 | case 24 * MHZ: | ||
67 | phyclk |= CLKSEL_24M; | ||
68 | break; | ||
69 | default: | ||
70 | case 48 * MHZ: | ||
71 | /* default reference clock */ | ||
72 | break; | ||
73 | } | ||
74 | clk_put(xusbxti_clk); | ||
75 | } | ||
76 | |||
77 | writel(phyclk, EXYNOS4_PHYCLK); | ||
78 | 118 | ||
79 | /* floating prevention logic: disable */ | 119 | /* floating prevention logic: disable */ |
80 | writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON); | 120 | writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON); |
@@ -102,7 +142,7 @@ static int exynos4_usb_phy1_init(struct platform_device *pdev) | |||
102 | return 0; | 142 | return 0; |
103 | } | 143 | } |
104 | 144 | ||
105 | static int exynos4_usb_phy1_exit(struct platform_device *pdev) | 145 | static int exynos4210_usb_phy1_exit(struct platform_device *pdev) |
106 | { | 146 | { |
107 | struct clk *otg_clk; | 147 | struct clk *otg_clk; |
108 | int err; | 148 | int err; |
@@ -136,16 +176,20 @@ static int exynos4_usb_phy1_exit(struct platform_device *pdev) | |||
136 | 176 | ||
137 | int s5p_usb_phy_init(struct platform_device *pdev, int type) | 177 | int s5p_usb_phy_init(struct platform_device *pdev, int type) |
138 | { | 178 | { |
139 | if (type == S5P_USB_PHY_HOST) | 179 | if (type == S5P_USB_PHY_DEVICE) |
140 | return exynos4_usb_phy1_init(pdev); | 180 | return exynos4210_usb_phy0_init(pdev); |
181 | else if (type == S5P_USB_PHY_HOST) | ||
182 | return exynos4210_usb_phy1_init(pdev); | ||
141 | 183 | ||
142 | return -EINVAL; | 184 | return -EINVAL; |
143 | } | 185 | } |
144 | 186 | ||
145 | int s5p_usb_phy_exit(struct platform_device *pdev, int type) | 187 | int s5p_usb_phy_exit(struct platform_device *pdev, int type) |
146 | { | 188 | { |
147 | if (type == S5P_USB_PHY_HOST) | 189 | if (type == S5P_USB_PHY_DEVICE) |
148 | return exynos4_usb_phy1_exit(pdev); | 190 | return exynos4210_usb_phy0_exit(pdev); |
191 | else if (type == S5P_USB_PHY_HOST) | ||
192 | return exynos4210_usb_phy1_exit(pdev); | ||
149 | 193 | ||
150 | return -EINVAL; | 194 | return -EINVAL; |
151 | } | 195 | } |