aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoonyoung Shim <jy0922.shim@samsung.com>2011-04-08 00:22:10 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-04-13 19:50:44 -0400
commit8f1d169f999fea892c3fcbf5a79ae8525a477572 (patch)
treebd440582799dcacc4348121242b8e89cdf448053
parent3e112662129b48bf8571ee5f7c49a4dbb3b70f04 (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/Makefile2
-rw-r--r--arch/arm/mach-exynos4/cpu.c7
-rw-r--r--arch/arm/mach-exynos4/include/mach/map.h1
-rw-r--r--arch/arm/mach-exynos4/include/mach/regs-pmu.h3
-rw-r--r--arch/arm/mach-exynos4/include/mach/regs-usb-phy.h64
-rw-r--r--arch/arm/mach-exynos4/usb-phy.c136
-rw-r--r--arch/arm/plat-s5p/dev-ehci.c9
-rw-r--r--arch/arm/plat-s5p/include/plat/map-s5p.h2
-rw-r--r--arch/arm/plat-s5p/include/plat/usb-phy.h22
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
54obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD) += setup-keypad.o 54obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD) += setup-keypad.o
55obj-$(CONFIG_EXYNOS4_SETUP_SDHCI) += setup-sdhci.o 55obj-$(CONFIG_EXYNOS4_SETUP_SDHCI) += setup-sdhci.o
56obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o 56obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
57
58obj-$(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
103static void exynos4_idle(void) 108static 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
22static 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
93static 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
122int 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
130int 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
46void __init s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd) 46void __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
14enum s5p_usb_phy_type {
15 S5P_USB_PHY_DEVICE,
16 S5P_USB_PHY_HOST,
17};
18
19extern int s5p_usb_phy_init(struct platform_device *pdev, int type);
20extern int s5p_usb_phy_exit(struct platform_device *pdev, int type);
21
22#endif /* __PLAT_S5P_REGS_USB_PHY_H */