diff options
author | Joonyoung Shim <jy0922.shim@samsung.com> | 2011-04-08 00:22:10 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-04-13 19:50:44 -0400 |
commit | 8f1d169f999fea892c3fcbf5a79ae8525a477572 (patch) | |
tree | bd440582799dcacc4348121242b8e89cdf448053 | |
parent | 3e112662129b48bf8571ee5f7c49a4dbb3b70f04 (diff) |
ARM: EXYNOS4: Add usb host phy control
EXYNOS4 has 2 phys for usb host and usb device. This patch supports to
control usb host phy of EXYNOS4.
Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | arch/arm/mach-exynos4/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-exynos4/cpu.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-exynos4/include/mach/map.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-exynos4/include/mach/regs-pmu.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-exynos4/include/mach/regs-usb-phy.h | 64 | ||||
-rw-r--r-- | arch/arm/mach-exynos4/usb-phy.c | 136 | ||||
-rw-r--r-- | arch/arm/plat-s5p/dev-ehci.c | 9 | ||||
-rw-r--r-- | arch/arm/plat-s5p/include/plat/map-s5p.h | 2 | ||||
-rw-r--r-- | arch/arm/plat-s5p/include/plat/usb-phy.h | 22 |
9 files changed, 243 insertions, 3 deletions
diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile index 9be104f63c0b..777897551e42 100644 --- a/arch/arm/mach-exynos4/Makefile +++ b/arch/arm/mach-exynos4/Makefile | |||
@@ -54,3 +54,5 @@ obj-$(CONFIG_EXYNOS4_SETUP_I2C7) += setup-i2c7.o | |||
54 | obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD) += setup-keypad.o | 54 | obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD) += setup-keypad.o |
55 | obj-$(CONFIG_EXYNOS4_SETUP_SDHCI) += setup-sdhci.o | 55 | obj-$(CONFIG_EXYNOS4_SETUP_SDHCI) += setup-sdhci.o |
56 | obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o | 56 | obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o |
57 | |||
58 | obj-$(CONFIG_USB_SUPPORT) += usb-phy.o | ||
diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c index 793011391943..08813a6f66b1 100644 --- a/arch/arm/mach-exynos4/cpu.c +++ b/arch/arm/mach-exynos4/cpu.c | |||
@@ -97,7 +97,12 @@ static struct map_desc exynos4_iodesc[] __initdata = { | |||
97 | .pfn = __phys_to_pfn(EXYNOS4_PA_SROMC), | 97 | .pfn = __phys_to_pfn(EXYNOS4_PA_SROMC), |
98 | .length = SZ_4K, | 98 | .length = SZ_4K, |
99 | .type = MT_DEVICE, | 99 | .type = MT_DEVICE, |
100 | }, | 100 | }, { |
101 | .virtual = (unsigned long)S5P_VA_USB_HSPHY, | ||
102 | .pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY), | ||
103 | .length = SZ_4K, | ||
104 | .type = MT_DEVICE, | ||
105 | } | ||
101 | }; | 106 | }; |
102 | 107 | ||
103 | static void exynos4_idle(void) | 108 | static void exynos4_idle(void) |
diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-exynos4/include/mach/map.h index 213c2a27d7ca..0009e77a05fc 100644 --- a/arch/arm/mach-exynos4/include/mach/map.h +++ b/arch/arm/mach-exynos4/include/mach/map.h | |||
@@ -102,6 +102,7 @@ | |||
102 | #define EXYNOS4_PA_SROMC 0x12570000 | 102 | #define EXYNOS4_PA_SROMC 0x12570000 |
103 | 103 | ||
104 | #define EXYNOS4_PA_EHCI 0x12580000 | 104 | #define EXYNOS4_PA_EHCI 0x12580000 |
105 | #define EXYNOS4_PA_HSPHY 0x125B0000 | ||
105 | 106 | ||
106 | #define EXYNOS4_PA_UART 0x13800000 | 107 | #define EXYNOS4_PA_UART 0x13800000 |
107 | 108 | ||
diff --git a/arch/arm/mach-exynos4/include/mach/regs-pmu.h b/arch/arm/mach-exynos4/include/mach/regs-pmu.h index 62b0014d05e0..a9643371f8e7 100644 --- a/arch/arm/mach-exynos4/include/mach/regs-pmu.h +++ b/arch/arm/mach-exynos4/include/mach/regs-pmu.h | |||
@@ -33,6 +33,9 @@ | |||
33 | #define S5P_EINT_WAKEUP_MASK S5P_PMUREG(0x0604) | 33 | #define S5P_EINT_WAKEUP_MASK S5P_PMUREG(0x0604) |
34 | #define S5P_WAKEUP_MASK S5P_PMUREG(0x0608) | 34 | #define S5P_WAKEUP_MASK S5P_PMUREG(0x0608) |
35 | 35 | ||
36 | #define S5P_USBHOST_PHY_CONTROL S5P_PMUREG(0x0708) | ||
37 | #define S5P_USBHOST_PHY_ENABLE (1 << 0) | ||
38 | |||
36 | #define S5P_MIPI_DPHY_CONTROL(n) S5P_PMUREG(0x0710 + (n) * 4) | 39 | #define S5P_MIPI_DPHY_CONTROL(n) S5P_PMUREG(0x0710 + (n) * 4) |
37 | #define S5P_MIPI_DPHY_ENABLE (1 << 0) | 40 | #define S5P_MIPI_DPHY_ENABLE (1 << 0) |
38 | #define S5P_MIPI_DPHY_SRESETN (1 << 1) | 41 | #define S5P_MIPI_DPHY_SRESETN (1 << 1) |
diff --git a/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h b/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h new file mode 100644 index 000000000000..703118d5173c --- /dev/null +++ b/arch/arm/mach-exynos4/include/mach/regs-usb-phy.h | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Samsung Electronics Co.Ltd | ||
3 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | */ | ||
10 | |||
11 | #ifndef __PLAT_S5P_REGS_USB_PHY_H | ||
12 | #define __PLAT_S5P_REGS_USB_PHY_H | ||
13 | |||
14 | #define EXYNOS4_HSOTG_PHYREG(x) ((x) + S5P_VA_USB_HSPHY) | ||
15 | |||
16 | #define EXYNOS4_PHYPWR EXYNOS4_HSOTG_PHYREG(0x00) | ||
17 | #define PHY1_HSIC_NORMAL_MASK (0xf << 9) | ||
18 | #define PHY1_HSIC1_SLEEP (1 << 12) | ||
19 | #define PHY1_HSIC1_FORCE_SUSPEND (1 << 11) | ||
20 | #define PHY1_HSIC0_SLEEP (1 << 10) | ||
21 | #define PHY1_HSIC0_FORCE_SUSPEND (1 << 9) | ||
22 | |||
23 | #define PHY1_STD_NORMAL_MASK (0x7 << 6) | ||
24 | #define PHY1_STD_SLEEP (1 << 8) | ||
25 | #define PHY1_STD_ANALOG_POWERDOWN (1 << 7) | ||
26 | #define PHY1_STD_FORCE_SUSPEND (1 << 6) | ||
27 | |||
28 | #define PHY0_NORMAL_MASK (0x39 << 0) | ||
29 | #define PHY0_SLEEP (1 << 5) | ||
30 | #define PHY0_OTG_DISABLE (1 << 4) | ||
31 | #define PHY0_ANALOG_POWERDOWN (1 << 3) | ||
32 | #define PHY0_FORCE_SUSPEND (1 << 0) | ||
33 | |||
34 | #define EXYNOS4_PHYCLK EXYNOS4_HSOTG_PHYREG(0x04) | ||
35 | #define PHY1_COMMON_ON_N (1 << 7) | ||
36 | #define PHY0_COMMON_ON_N (1 << 4) | ||
37 | #define PHY0_ID_PULLUP (1 << 2) | ||
38 | #define CLKSEL_MASK (0x3 << 0) | ||
39 | #define CLKSEL_SHIFT (0) | ||
40 | #define CLKSEL_48M (0x0 << 0) | ||
41 | #define CLKSEL_12M (0x2 << 0) | ||
42 | #define CLKSEL_24M (0x3 << 0) | ||
43 | |||
44 | #define EXYNOS4_RSTCON EXYNOS4_HSOTG_PHYREG(0x08) | ||
45 | #define HOST_LINK_PORT_SWRST_MASK (0xf << 6) | ||
46 | #define HOST_LINK_PORT2_SWRST (1 << 9) | ||
47 | #define HOST_LINK_PORT1_SWRST (1 << 8) | ||
48 | #define HOST_LINK_PORT0_SWRST (1 << 7) | ||
49 | #define HOST_LINK_ALL_SWRST (1 << 6) | ||
50 | |||
51 | #define PHY1_SWRST_MASK (0x7 << 3) | ||
52 | #define PHY1_HSIC_SWRST (1 << 5) | ||
53 | #define PHY1_STD_SWRST (1 << 4) | ||
54 | #define PHY1_ALL_SWRST (1 << 3) | ||
55 | |||
56 | #define PHY0_SWRST_MASK (0x7 << 0) | ||
57 | #define PHY0_PHYLINK_SWRST (1 << 2) | ||
58 | #define PHY0_HLINK_SWRST (1 << 1) | ||
59 | #define PHY0_SWRST (1 << 0) | ||
60 | |||
61 | #define EXYNOS4_PHY1CON EXYNOS4_HSOTG_PHYREG(0x34) | ||
62 | #define FPENABLEN (1 << 0) | ||
63 | |||
64 | #endif /* __PLAT_S5P_REGS_USB_PHY_H */ | ||
diff --git a/arch/arm/mach-exynos4/usb-phy.c b/arch/arm/mach-exynos4/usb-phy.c new file mode 100644 index 000000000000..0883c1b824b9 --- /dev/null +++ b/arch/arm/mach-exynos4/usb-phy.c | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Samsung Electronics Co.Ltd | ||
3 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <mach/regs-pmu.h> | ||
18 | #include <mach/regs-usb-phy.h> | ||
19 | #include <plat/cpu.h> | ||
20 | #include <plat/usb-phy.h> | ||
21 | |||
22 | static int exynos4_usb_phy1_init(struct platform_device *pdev) | ||
23 | { | ||
24 | struct clk *otg_clk; | ||
25 | struct clk *xusbxti_clk; | ||
26 | u32 phyclk; | ||
27 | u32 rstcon; | ||
28 | int err; | ||
29 | |||
30 | otg_clk = clk_get(&pdev->dev, "otg"); | ||
31 | if (IS_ERR(otg_clk)) { | ||
32 | dev_err(&pdev->dev, "Failed to get otg clock\n"); | ||
33 | return PTR_ERR(otg_clk); | ||
34 | } | ||
35 | |||
36 | err = clk_enable(otg_clk); | ||
37 | if (err) { | ||
38 | clk_put(otg_clk); | ||
39 | return err; | ||
40 | } | ||
41 | |||
42 | writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE, | ||
43 | S5P_USBHOST_PHY_CONTROL); | ||
44 | |||
45 | /* set clock frequency for PLL */ | ||
46 | phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK; | ||
47 | |||
48 | xusbxti_clk = clk_get(&pdev->dev, "xusbxti"); | ||
49 | if (xusbxti_clk && !IS_ERR(xusbxti_clk)) { | ||
50 | switch (clk_get_rate(xusbxti_clk)) { | ||
51 | case 12 * MHZ: | ||
52 | phyclk |= CLKSEL_12M; | ||
53 | break; | ||
54 | case 24 * MHZ: | ||
55 | phyclk |= CLKSEL_24M; | ||
56 | break; | ||
57 | default: | ||
58 | case 48 * MHZ: | ||
59 | /* default reference clock */ | ||
60 | break; | ||
61 | } | ||
62 | clk_put(xusbxti_clk); | ||
63 | } | ||
64 | |||
65 | writel(phyclk, EXYNOS4_PHYCLK); | ||
66 | |||
67 | /* floating prevention logic: disable */ | ||
68 | writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON); | ||
69 | |||
70 | /* set to normal HSIC 0 and 1 of PHY1 */ | ||
71 | writel((readl(EXYNOS4_PHYPWR) & ~PHY1_HSIC_NORMAL_MASK), | ||
72 | EXYNOS4_PHYPWR); | ||
73 | |||
74 | /* set to normal standard USB of PHY1 */ | ||
75 | writel((readl(EXYNOS4_PHYPWR) & ~PHY1_STD_NORMAL_MASK), EXYNOS4_PHYPWR); | ||
76 | |||
77 | /* reset all ports of both PHY and Link */ | ||
78 | rstcon = readl(EXYNOS4_RSTCON) | HOST_LINK_PORT_SWRST_MASK | | ||
79 | PHY1_SWRST_MASK; | ||
80 | writel(rstcon, EXYNOS4_RSTCON); | ||
81 | udelay(10); | ||
82 | |||
83 | rstcon &= ~(HOST_LINK_PORT_SWRST_MASK | PHY1_SWRST_MASK); | ||
84 | writel(rstcon, EXYNOS4_RSTCON); | ||
85 | udelay(50); | ||
86 | |||
87 | clk_disable(otg_clk); | ||
88 | clk_put(otg_clk); | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | static int exynos4_usb_phy1_exit(struct platform_device *pdev) | ||
94 | { | ||
95 | struct clk *otg_clk; | ||
96 | int err; | ||
97 | |||
98 | otg_clk = clk_get(&pdev->dev, "otg"); | ||
99 | if (IS_ERR(otg_clk)) { | ||
100 | dev_err(&pdev->dev, "Failed to get otg clock\n"); | ||
101 | return PTR_ERR(otg_clk); | ||
102 | } | ||
103 | |||
104 | err = clk_enable(otg_clk); | ||
105 | if (err) { | ||
106 | clk_put(otg_clk); | ||
107 | return err; | ||
108 | } | ||
109 | |||
110 | writel((readl(EXYNOS4_PHYPWR) | PHY1_STD_ANALOG_POWERDOWN), | ||
111 | EXYNOS4_PHYPWR); | ||
112 | |||
113 | writel(readl(S5P_USBHOST_PHY_CONTROL) & ~S5P_USBHOST_PHY_ENABLE, | ||
114 | S5P_USBHOST_PHY_CONTROL); | ||
115 | |||
116 | clk_disable(otg_clk); | ||
117 | clk_put(otg_clk); | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | int s5p_usb_phy_init(struct platform_device *pdev, int type) | ||
123 | { | ||
124 | if (type == S5P_USB_PHY_HOST) | ||
125 | return exynos4_usb_phy1_init(pdev); | ||
126 | |||
127 | return -EINVAL; | ||
128 | } | ||
129 | |||
130 | int s5p_usb_phy_exit(struct platform_device *pdev, int type) | ||
131 | { | ||
132 | if (type == S5P_USB_PHY_HOST) | ||
133 | return exynos4_usb_phy1_exit(pdev); | ||
134 | |||
135 | return -EINVAL; | ||
136 | } | ||
diff --git a/arch/arm/plat-s5p/dev-ehci.c b/arch/arm/plat-s5p/dev-ehci.c index a610e5c60964..94080fff9e9b 100644 --- a/arch/arm/plat-s5p/dev-ehci.c +++ b/arch/arm/plat-s5p/dev-ehci.c | |||
@@ -45,6 +45,13 @@ struct platform_device s5p_device_ehci = { | |||
45 | 45 | ||
46 | void __init s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd) | 46 | void __init s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd) |
47 | { | 47 | { |
48 | s3c_set_platdata(pd, sizeof(struct s5p_ehci_platdata), | 48 | struct s5p_ehci_platdata *npd; |
49 | |||
50 | npd = s3c_set_platdata(pd, sizeof(struct s5p_ehci_platdata), | ||
49 | &s5p_device_ehci); | 51 | &s5p_device_ehci); |
52 | |||
53 | if (!npd->phy_init) | ||
54 | npd->phy_init = s5p_usb_phy_init; | ||
55 | if (!npd->phy_exit) | ||
56 | npd->phy_exit = s5p_usb_phy_exit; | ||
50 | } | 57 | } |
diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h index d973d39666a3..a6c3d327ce72 100644 --- a/arch/arm/plat-s5p/include/plat/map-s5p.h +++ b/arch/arm/plat-s5p/include/plat/map-s5p.h | |||
@@ -39,7 +39,7 @@ | |||
39 | #define S5P_VA_TWD S5P_VA_COREPERI(0x600) | 39 | #define S5P_VA_TWD S5P_VA_COREPERI(0x600) |
40 | #define S5P_VA_GIC_DIST S5P_VA_COREPERI(0x1000) | 40 | #define S5P_VA_GIC_DIST S5P_VA_COREPERI(0x1000) |
41 | 41 | ||
42 | #define S3C_VA_USB_HSPHY S3C_ADDR(0x02900000) | 42 | #define S5P_VA_USB_HSPHY S3C_ADDR(0x02900000) |
43 | 43 | ||
44 | #define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000)) | 44 | #define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000)) |
45 | #define VA_VIC0 VA_VIC(0) | 45 | #define VA_VIC0 VA_VIC(0) |
diff --git a/arch/arm/plat-s5p/include/plat/usb-phy.h b/arch/arm/plat-s5p/include/plat/usb-phy.h new file mode 100644 index 000000000000..6dd6bcfca3ce --- /dev/null +++ b/arch/arm/plat-s5p/include/plat/usb-phy.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Samsung Electronics Co.Ltd | ||
3 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | */ | ||
10 | |||
11 | #ifndef __PLAT_S5P_USB_PHY_H | ||
12 | #define __PLAT_S5P_USB_PHY_H | ||
13 | |||
14 | enum s5p_usb_phy_type { | ||
15 | S5P_USB_PHY_DEVICE, | ||
16 | S5P_USB_PHY_HOST, | ||
17 | }; | ||
18 | |||
19 | extern int s5p_usb_phy_init(struct platform_device *pdev, int type); | ||
20 | extern int s5p_usb_phy_exit(struct platform_device *pdev, int type); | ||
21 | |||
22 | #endif /* __PLAT_S5P_REGS_USB_PHY_H */ | ||