diff options
author | Mateusz Krawczuk <mat.krawczuk@gmail.com> | 2013-12-20 08:24:12 -0500 |
---|---|---|
committer | Kukjin Kim <kgene.kim@samsung.com> | 2014-07-18 15:25:09 -0400 |
commit | 949ccc3a93630ed61f0f38fbf76ee2667d11d3f7 (patch) | |
tree | c97d3444abf80ba8acd0a75dd0b6bec446f38927 /drivers/phy | |
parent | 9978f28f695adb63fa1726744a7f95e12920e8c9 (diff) |
phy: Add support for S5PV210 to the Exynos USB 2.0 PHY driver
Add support for the Samsung's S5PV210 SoC to the Exynos USB 2.0 PHY driver.
Signed-off-by: Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
[k.debski@samsung.com: cleanup and commit description]
[k.debski@samsung.com: make changes accordingly to the mailing list
comments]
Signed-off-by: Kamil Debski <k.debski@samsung.com>
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'drivers/phy')
-rw-r--r-- | drivers/phy/Kconfig | 10 | ||||
-rw-r--r-- | drivers/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/phy/phy-s5pv210-usb2.c | 187 | ||||
-rw-r--r-- | drivers/phy/phy-samsung-usb2.c | 6 | ||||
-rw-r--r-- | drivers/phy/phy-samsung-usb2.h | 1 |
5 files changed, 205 insertions, 0 deletions
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 64b98d242ea6..b0525e03782a 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig | |||
@@ -132,6 +132,16 @@ config PHY_SAMSUNG_USB2 | |||
132 | particular SoCs has to be enabled in addition to this driver. Number | 132 | particular SoCs has to be enabled in addition to this driver. Number |
133 | and type of supported phys depends on the SoC. | 133 | and type of supported phys depends on the SoC. |
134 | 134 | ||
135 | config PHY_S5PV210_USB2 | ||
136 | bool "Support for S5PV210" | ||
137 | depends on PHY_SAMSUNG_USB2 | ||
138 | depends on ARCH_S5PV210 | ||
139 | help | ||
140 | Enable USB PHY support for S5PV210. This option requires that Samsung | ||
141 | USB 2.0 PHY driver is enabled and means that support for this | ||
142 | particular SoC is compiled in the driver. In case of S5PV210 two phys | ||
143 | are available - device and host. | ||
144 | |||
135 | config PHY_EXYNOS4210_USB2 | 145 | config PHY_EXYNOS4210_USB2 |
136 | bool "Support for Exynos 4210" | 146 | bool "Support for Exynos 4210" |
137 | depends on PHY_SAMSUNG_USB2 | 147 | depends on PHY_SAMSUNG_USB2 |
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index b4f1d5770601..2983808e1626 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile | |||
@@ -18,5 +18,6 @@ phy-exynos-usb2-y += phy-samsung-usb2.o | |||
18 | phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o | 18 | phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o |
19 | phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o | 19 | phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o |
20 | phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o | 20 | phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o |
21 | phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o | ||
21 | obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o | 22 | obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o |
22 | obj-$(CONFIG_PHY_XGENE) += phy-xgene.o | 23 | obj-$(CONFIG_PHY_XGENE) += phy-xgene.o |
diff --git a/drivers/phy/phy-s5pv210-usb2.c b/drivers/phy/phy-s5pv210-usb2.c new file mode 100644 index 000000000000..004d320767e4 --- /dev/null +++ b/drivers/phy/phy-s5pv210-usb2.c | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | * Samsung SoC USB 1.1/2.0 PHY driver - S5PV210 support | ||
3 | * | ||
4 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
5 | * Authors: Kamil Debski <k.debski@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/delay.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/phy/phy.h> | ||
15 | #include "phy-samsung-usb2.h" | ||
16 | |||
17 | /* Exynos USB PHY registers */ | ||
18 | |||
19 | /* PHY power control */ | ||
20 | #define S5PV210_UPHYPWR 0x0 | ||
21 | |||
22 | #define S5PV210_UPHYPWR_PHY0_SUSPEND BIT(0) | ||
23 | #define S5PV210_UPHYPWR_PHY0_PWR BIT(3) | ||
24 | #define S5PV210_UPHYPWR_PHY0_OTG_PWR BIT(4) | ||
25 | #define S5PV210_UPHYPWR_PHY0 ( \ | ||
26 | S5PV210_UPHYPWR_PHY0_SUSPEND | \ | ||
27 | S5PV210_UPHYPWR_PHY0_PWR | \ | ||
28 | S5PV210_UPHYPWR_PHY0_OTG_PWR) | ||
29 | |||
30 | #define S5PV210_UPHYPWR_PHY1_SUSPEND BIT(6) | ||
31 | #define S5PV210_UPHYPWR_PHY1_PWR BIT(7) | ||
32 | #define S5PV210_UPHYPWR_PHY1 ( \ | ||
33 | S5PV210_UPHYPWR_PHY1_SUSPEND | \ | ||
34 | S5PV210_UPHYPWR_PHY1_PWR) | ||
35 | |||
36 | /* PHY clock control */ | ||
37 | #define S5PV210_UPHYCLK 0x4 | ||
38 | |||
39 | #define S5PV210_UPHYCLK_PHYFSEL_MASK (0x3 << 0) | ||
40 | #define S5PV210_UPHYCLK_PHYFSEL_48MHZ (0x0 << 0) | ||
41 | #define S5PV210_UPHYCLK_PHYFSEL_24MHZ (0x3 << 0) | ||
42 | #define S5PV210_UPHYCLK_PHYFSEL_12MHZ (0x2 << 0) | ||
43 | |||
44 | #define S5PV210_UPHYCLK_PHY0_ID_PULLUP BIT(2) | ||
45 | #define S5PV210_UPHYCLK_PHY0_COMMON_ON BIT(4) | ||
46 | #define S5PV210_UPHYCLK_PHY1_COMMON_ON BIT(7) | ||
47 | |||
48 | /* PHY reset control */ | ||
49 | #define S5PV210_UPHYRST 0x8 | ||
50 | |||
51 | #define S5PV210_URSTCON_PHY0 BIT(0) | ||
52 | #define S5PV210_URSTCON_OTG_HLINK BIT(1) | ||
53 | #define S5PV210_URSTCON_OTG_PHYLINK BIT(2) | ||
54 | #define S5PV210_URSTCON_PHY1_ALL BIT(3) | ||
55 | #define S5PV210_URSTCON_HOST_LINK_ALL BIT(4) | ||
56 | |||
57 | /* Isolation, configured in the power management unit */ | ||
58 | #define S5PV210_USB_ISOL_OFFSET 0x680c | ||
59 | #define S5PV210_USB_ISOL_DEVICE BIT(0) | ||
60 | #define S5PV210_USB_ISOL_HOST BIT(1) | ||
61 | |||
62 | |||
63 | enum s5pv210_phy_id { | ||
64 | S5PV210_DEVICE, | ||
65 | S5PV210_HOST, | ||
66 | S5PV210_NUM_PHYS, | ||
67 | }; | ||
68 | |||
69 | /* | ||
70 | * s5pv210_rate_to_clk() converts the supplied clock rate to the value that | ||
71 | * can be written to the phy register. | ||
72 | */ | ||
73 | static int s5pv210_rate_to_clk(unsigned long rate, u32 *reg) | ||
74 | { | ||
75 | switch (rate) { | ||
76 | case 12 * MHZ: | ||
77 | *reg = S5PV210_UPHYCLK_PHYFSEL_12MHZ; | ||
78 | break; | ||
79 | case 24 * MHZ: | ||
80 | *reg = S5PV210_UPHYCLK_PHYFSEL_24MHZ; | ||
81 | break; | ||
82 | case 48 * MHZ: | ||
83 | *reg = S5PV210_UPHYCLK_PHYFSEL_48MHZ; | ||
84 | break; | ||
85 | default: | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | |||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static void s5pv210_isol(struct samsung_usb2_phy_instance *inst, bool on) | ||
93 | { | ||
94 | struct samsung_usb2_phy_driver *drv = inst->drv; | ||
95 | u32 mask; | ||
96 | |||
97 | switch (inst->cfg->id) { | ||
98 | case S5PV210_DEVICE: | ||
99 | mask = S5PV210_USB_ISOL_DEVICE; | ||
100 | break; | ||
101 | case S5PV210_HOST: | ||
102 | mask = S5PV210_USB_ISOL_HOST; | ||
103 | break; | ||
104 | default: | ||
105 | return; | ||
106 | }; | ||
107 | |||
108 | regmap_update_bits(drv->reg_pmu, S5PV210_USB_ISOL_OFFSET, | ||
109 | mask, on ? 0 : mask); | ||
110 | } | ||
111 | |||
112 | static void s5pv210_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on) | ||
113 | { | ||
114 | struct samsung_usb2_phy_driver *drv = inst->drv; | ||
115 | u32 rstbits = 0; | ||
116 | u32 phypwr = 0; | ||
117 | u32 rst; | ||
118 | u32 pwr; | ||
119 | |||
120 | switch (inst->cfg->id) { | ||
121 | case S5PV210_DEVICE: | ||
122 | phypwr = S5PV210_UPHYPWR_PHY0; | ||
123 | rstbits = S5PV210_URSTCON_PHY0; | ||
124 | break; | ||
125 | case S5PV210_HOST: | ||
126 | phypwr = S5PV210_UPHYPWR_PHY1; | ||
127 | rstbits = S5PV210_URSTCON_PHY1_ALL | | ||
128 | S5PV210_URSTCON_HOST_LINK_ALL; | ||
129 | break; | ||
130 | }; | ||
131 | |||
132 | if (on) { | ||
133 | writel(drv->ref_reg_val, drv->reg_phy + S5PV210_UPHYCLK); | ||
134 | |||
135 | pwr = readl(drv->reg_phy + S5PV210_UPHYPWR); | ||
136 | pwr &= ~phypwr; | ||
137 | writel(pwr, drv->reg_phy + S5PV210_UPHYPWR); | ||
138 | |||
139 | rst = readl(drv->reg_phy + S5PV210_UPHYRST); | ||
140 | rst |= rstbits; | ||
141 | writel(rst, drv->reg_phy + S5PV210_UPHYRST); | ||
142 | udelay(10); | ||
143 | rst &= ~rstbits; | ||
144 | writel(rst, drv->reg_phy + S5PV210_UPHYRST); | ||
145 | } else { | ||
146 | pwr = readl(drv->reg_phy + S5PV210_UPHYPWR); | ||
147 | pwr |= phypwr; | ||
148 | writel(pwr, drv->reg_phy + S5PV210_UPHYPWR); | ||
149 | } | ||
150 | } | ||
151 | |||
152 | static int s5pv210_power_on(struct samsung_usb2_phy_instance *inst) | ||
153 | { | ||
154 | s5pv210_isol(inst, 0); | ||
155 | s5pv210_phy_pwr(inst, 1); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static int s5pv210_power_off(struct samsung_usb2_phy_instance *inst) | ||
161 | { | ||
162 | s5pv210_phy_pwr(inst, 0); | ||
163 | s5pv210_isol(inst, 1); | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static const struct samsung_usb2_common_phy s5pv210_phys[S5PV210_NUM_PHYS] = { | ||
169 | [S5PV210_DEVICE] = { | ||
170 | .label = "device", | ||
171 | .id = S5PV210_DEVICE, | ||
172 | .power_on = s5pv210_power_on, | ||
173 | .power_off = s5pv210_power_off, | ||
174 | }, | ||
175 | [S5PV210_HOST] = { | ||
176 | .label = "host", | ||
177 | .id = S5PV210_HOST, | ||
178 | .power_on = s5pv210_power_on, | ||
179 | .power_off = s5pv210_power_off, | ||
180 | }, | ||
181 | }; | ||
182 | |||
183 | const struct samsung_usb2_phy_config s5pv210_usb2_phy_config = { | ||
184 | .num_phys = ARRAY_SIZE(s5pv210_phys), | ||
185 | .phys = s5pv210_phys, | ||
186 | .rate_to_clk = s5pv210_rate_to_clk, | ||
187 | }; | ||
diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c index 1e69a32c221d..29e4ab987645 100644 --- a/drivers/phy/phy-samsung-usb2.c +++ b/drivers/phy/phy-samsung-usb2.c | |||
@@ -87,6 +87,12 @@ static struct phy *samsung_usb2_phy_xlate(struct device *dev, | |||
87 | } | 87 | } |
88 | 88 | ||
89 | static const struct of_device_id samsung_usb2_phy_of_match[] = { | 89 | static const struct of_device_id samsung_usb2_phy_of_match[] = { |
90 | #ifdef CONFIG_PHY_S5PV210_USB2 | ||
91 | { | ||
92 | .compatible = "samsung,s5pv210-usb2-phy", | ||
93 | .data = &s5pv210_usb2_phy_config, | ||
94 | }, | ||
95 | #endif | ||
90 | #ifdef CONFIG_PHY_EXYNOS4210_USB2 | 96 | #ifdef CONFIG_PHY_EXYNOS4210_USB2 |
91 | { | 97 | { |
92 | .compatible = "samsung,exynos4210-usb2-phy", | 98 | .compatible = "samsung,exynos4210-usb2-phy", |
diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/phy-samsung-usb2.h index 45b3170652bd..1c55795d4429 100644 --- a/drivers/phy/phy-samsung-usb2.h +++ b/drivers/phy/phy-samsung-usb2.h | |||
@@ -61,6 +61,7 @@ struct samsung_usb2_phy_config { | |||
61 | bool has_mode_switch; | 61 | bool has_mode_switch; |
62 | }; | 62 | }; |
63 | 63 | ||
64 | extern const struct samsung_usb2_phy_config s5pv210_usb2_phy_config; | ||
64 | extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config; | 65 | extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config; |
65 | extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config; | 66 | extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config; |
66 | extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config; | 67 | extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config; |