diff options
author | Vivek Gautam <gautam.vivek@samsung.com> | 2013-03-14 06:29:11 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2013-03-18 05:18:15 -0400 |
commit | b52767581765d3d1a1ba7106674791e540574704 (patch) | |
tree | 95823207cf8cf597ffa444b7efc9a953e76a7eeb /drivers/usb/phy | |
parent | dc2377d0b0a298ec9d7d232c0d757f462dedcca2 (diff) |
usb: phy: samsung: Add PHY support for USB 3.0 controller
Adding PHY driver support for USB 3.0 controller for Samsung's
SoCs.
Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/phy')
-rw-r--r-- | drivers/usb/phy/Kconfig | 7 | ||||
-rw-r--r-- | drivers/usb/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/phy/phy-samsung-usb.h | 80 | ||||
-rw-r--r-- | drivers/usb/phy/phy-samsung-usb3.c | 349 |
4 files changed, 437 insertions, 0 deletions
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index e8cd52ac5c05..7e8fe0f0b8c6 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig | |||
@@ -99,6 +99,13 @@ config SAMSUNG_USB2PHY | |||
99 | Enable this to support Samsung USB 2.0 (High Speed) PHY controller | 99 | Enable this to support Samsung USB 2.0 (High Speed) PHY controller |
100 | driver for Samsung SoCs. | 100 | driver for Samsung SoCs. |
101 | 101 | ||
102 | config SAMSUNG_USB3PHY | ||
103 | tristate "Samsung USB 3.0 PHY controller Driver" | ||
104 | select SAMSUNG_USBPHY | ||
105 | help | ||
106 | Enable this to support Samsung USB 3.0 (Super Speed) phy controller | ||
107 | for samsung SoCs. | ||
108 | |||
102 | config TWL4030_USB | 109 | config TWL4030_USB |
103 | tristate "TWL4030 USB Transceiver Driver" | 110 | tristate "TWL4030 USB Transceiver Driver" |
104 | depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS | 111 | depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS |
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 8cd355f051f6..33863c09f3dc 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile | |||
@@ -19,6 +19,7 @@ obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o | |||
19 | obj-$(CONFIG_OMAP_USB3) += phy-omap-usb3.o | 19 | obj-$(CONFIG_OMAP_USB3) += phy-omap-usb3.o |
20 | obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o | 20 | obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o |
21 | obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o | 21 | obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o |
22 | obj-$(CONFIG_SAMSUNG_USB3PHY) += phy-samsung-usb3.o | ||
22 | obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o | 23 | obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o |
23 | obj-$(CONFIG_TWL6030_USB) += phy-twl6030-usb.o | 24 | obj-$(CONFIG_TWL6030_USB) += phy-twl6030-usb.o |
24 | obj-$(CONFIG_USB_EHCI_TEGRA) += phy-tegra-usb.o | 25 | obj-$(CONFIG_USB_EHCI_TEGRA) += phy-tegra-usb.o |
diff --git a/drivers/usb/phy/phy-samsung-usb.h b/drivers/usb/phy/phy-samsung-usb.h index 481737d743d5..70a9cae5e37f 100644 --- a/drivers/usb/phy/phy-samsung-usb.h +++ b/drivers/usb/phy/phy-samsung-usb.h | |||
@@ -145,6 +145,86 @@ | |||
145 | 145 | ||
146 | #define EXYNOS5_PHY_OTG_TUNE (0x40) | 146 | #define EXYNOS5_PHY_OTG_TUNE (0x40) |
147 | 147 | ||
148 | /* EXYNOS5: USB 3.0 DRD */ | ||
149 | #define EXYNOS5_DRD_LINKSYSTEM (0x04) | ||
150 | |||
151 | #define LINKSYSTEM_FLADJ_MASK (0x3f << 1) | ||
152 | #define LINKSYSTEM_FLADJ(_x) ((_x) << 1) | ||
153 | #define LINKSYSTEM_XHCI_VERSION_CONTROL (0x1 << 27) | ||
154 | |||
155 | #define EXYNOS5_DRD_PHYUTMI (0x08) | ||
156 | |||
157 | #define PHYUTMI_OTGDISABLE (0x1 << 6) | ||
158 | #define PHYUTMI_FORCESUSPEND (0x1 << 1) | ||
159 | #define PHYUTMI_FORCESLEEP (0x1 << 0) | ||
160 | |||
161 | #define EXYNOS5_DRD_PHYPIPE (0x0c) | ||
162 | |||
163 | #define EXYNOS5_DRD_PHYCLKRST (0x10) | ||
164 | |||
165 | #define PHYCLKRST_SSC_REFCLKSEL_MASK (0xff << 23) | ||
166 | #define PHYCLKRST_SSC_REFCLKSEL(_x) ((_x) << 23) | ||
167 | |||
168 | #define PHYCLKRST_SSC_RANGE_MASK (0x03 << 21) | ||
169 | #define PHYCLKRST_SSC_RANGE(_x) ((_x) << 21) | ||
170 | |||
171 | #define PHYCLKRST_SSC_EN (0x1 << 20) | ||
172 | #define PHYCLKRST_REF_SSP_EN (0x1 << 19) | ||
173 | #define PHYCLKRST_REF_CLKDIV2 (0x1 << 18) | ||
174 | |||
175 | #define PHYCLKRST_MPLL_MULTIPLIER_MASK (0x7f << 11) | ||
176 | #define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF (0x19 << 11) | ||
177 | #define PHYCLKRST_MPLL_MULTIPLIER_50M_REF (0x02 << 11) | ||
178 | #define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF (0x68 << 11) | ||
179 | #define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF (0x7d << 11) | ||
180 | #define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF (0x02 << 11) | ||
181 | |||
182 | #define PHYCLKRST_FSEL_MASK (0x3f << 5) | ||
183 | #define PHYCLKRST_FSEL(_x) ((_x) << 5) | ||
184 | #define PHYCLKRST_FSEL_PAD_100MHZ (0x27 << 5) | ||
185 | #define PHYCLKRST_FSEL_PAD_24MHZ (0x2a << 5) | ||
186 | #define PHYCLKRST_FSEL_PAD_20MHZ (0x31 << 5) | ||
187 | #define PHYCLKRST_FSEL_PAD_19_2MHZ (0x38 << 5) | ||
188 | |||
189 | #define PHYCLKRST_RETENABLEN (0x1 << 4) | ||
190 | |||
191 | #define PHYCLKRST_REFCLKSEL_MASK (0x03 << 2) | ||
192 | #define PHYCLKRST_REFCLKSEL_PAD_REFCLK (0x2 << 2) | ||
193 | #define PHYCLKRST_REFCLKSEL_EXT_REFCLK (0x3 << 2) | ||
194 | |||
195 | #define PHYCLKRST_PORTRESET (0x1 << 1) | ||
196 | #define PHYCLKRST_COMMONONN (0x1 << 0) | ||
197 | |||
198 | #define EXYNOS5_DRD_PHYREG0 (0x14) | ||
199 | #define EXYNOS5_DRD_PHYREG1 (0x18) | ||
200 | |||
201 | #define EXYNOS5_DRD_PHYPARAM0 (0x1c) | ||
202 | |||
203 | #define PHYPARAM0_REF_USE_PAD (0x1 << 31) | ||
204 | #define PHYPARAM0_REF_LOSLEVEL_MASK (0x1f << 26) | ||
205 | #define PHYPARAM0_REF_LOSLEVEL (0x9 << 26) | ||
206 | |||
207 | #define EXYNOS5_DRD_PHYPARAM1 (0x20) | ||
208 | |||
209 | #define PHYPARAM1_PCS_TXDEEMPH_MASK (0x1f << 0) | ||
210 | #define PHYPARAM1_PCS_TXDEEMPH (0x1c) | ||
211 | |||
212 | #define EXYNOS5_DRD_PHYTERM (0x24) | ||
213 | |||
214 | #define EXYNOS5_DRD_PHYTEST (0x28) | ||
215 | |||
216 | #define PHYTEST_POWERDOWN_SSP (0x1 << 3) | ||
217 | #define PHYTEST_POWERDOWN_HSP (0x1 << 2) | ||
218 | |||
219 | #define EXYNOS5_DRD_PHYADP (0x2c) | ||
220 | |||
221 | #define EXYNOS5_DRD_PHYBATCHG (0x30) | ||
222 | |||
223 | #define PHYBATCHG_UTMI_CLKSEL (0x1 << 2) | ||
224 | |||
225 | #define EXYNOS5_DRD_PHYRESUME (0x34) | ||
226 | #define EXYNOS5_DRD_LINKPORT (0x44) | ||
227 | |||
148 | #ifndef MHZ | 228 | #ifndef MHZ |
149 | #define MHZ (1000*1000) | 229 | #define MHZ (1000*1000) |
150 | #endif | 230 | #endif |
diff --git a/drivers/usb/phy/phy-samsung-usb3.c b/drivers/usb/phy/phy-samsung-usb3.c new file mode 100644 index 000000000000..54f641860f9e --- /dev/null +++ b/drivers/usb/phy/phy-samsung-usb3.c | |||
@@ -0,0 +1,349 @@ | |||
1 | /* linux/drivers/usb/phy/phy-samsung-usb3.c | ||
2 | * | ||
3 | * Copyright (c) 2013 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Author: Vivek Gautam <gautam.vivek@samsung.com> | ||
7 | * | ||
8 | * Samsung USB 3.0 PHY transceiver; talks to DWC3 controller. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/clk.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/io.h> | ||
26 | #include <linux/of.h> | ||
27 | #include <linux/usb/samsung_usb_phy.h> | ||
28 | #include <linux/platform_data/samsung-usbphy.h> | ||
29 | |||
30 | #include "phy-samsung-usb.h" | ||
31 | |||
32 | /* | ||
33 | * Sets the phy clk as EXTREFCLK (XXTI) which is internal clock from clock core. | ||
34 | */ | ||
35 | static u32 samsung_usb3phy_set_refclk(struct samsung_usbphy *sphy) | ||
36 | { | ||
37 | u32 reg; | ||
38 | u32 refclk; | ||
39 | |||
40 | refclk = sphy->ref_clk_freq; | ||
41 | |||
42 | reg = PHYCLKRST_REFCLKSEL_EXT_REFCLK | | ||
43 | PHYCLKRST_FSEL(refclk); | ||
44 | |||
45 | switch (refclk) { | ||
46 | case FSEL_CLKSEL_50M: | ||
47 | reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF | | ||
48 | PHYCLKRST_SSC_REFCLKSEL(0x00)); | ||
49 | break; | ||
50 | case FSEL_CLKSEL_20M: | ||
51 | reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF | | ||
52 | PHYCLKRST_SSC_REFCLKSEL(0x00)); | ||
53 | break; | ||
54 | case FSEL_CLKSEL_19200K: | ||
55 | reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF | | ||
56 | PHYCLKRST_SSC_REFCLKSEL(0x88)); | ||
57 | break; | ||
58 | case FSEL_CLKSEL_24M: | ||
59 | default: | ||
60 | reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF | | ||
61 | PHYCLKRST_SSC_REFCLKSEL(0x88)); | ||
62 | break; | ||
63 | } | ||
64 | |||
65 | return reg; | ||
66 | } | ||
67 | |||
68 | static int samsung_exynos5_usb3phy_enable(struct samsung_usbphy *sphy) | ||
69 | { | ||
70 | void __iomem *regs = sphy->regs; | ||
71 | u32 phyparam0; | ||
72 | u32 phyparam1; | ||
73 | u32 linksystem; | ||
74 | u32 phybatchg; | ||
75 | u32 phytest; | ||
76 | u32 phyclkrst; | ||
77 | |||
78 | /* Reset USB 3.0 PHY */ | ||
79 | writel(0x0, regs + EXYNOS5_DRD_PHYREG0); | ||
80 | |||
81 | phyparam0 = readl(regs + EXYNOS5_DRD_PHYPARAM0); | ||
82 | /* Select PHY CLK source */ | ||
83 | phyparam0 &= ~PHYPARAM0_REF_USE_PAD; | ||
84 | /* Set Loss-of-Signal Detector sensitivity */ | ||
85 | phyparam0 &= ~PHYPARAM0_REF_LOSLEVEL_MASK; | ||
86 | phyparam0 |= PHYPARAM0_REF_LOSLEVEL; | ||
87 | writel(phyparam0, regs + EXYNOS5_DRD_PHYPARAM0); | ||
88 | |||
89 | writel(0x0, regs + EXYNOS5_DRD_PHYRESUME); | ||
90 | |||
91 | /* | ||
92 | * Setting the Frame length Adj value[6:1] to default 0x20 | ||
93 | * See xHCI 1.0 spec, 5.2.4 | ||
94 | */ | ||
95 | linksystem = LINKSYSTEM_XHCI_VERSION_CONTROL | | ||
96 | LINKSYSTEM_FLADJ(0x20); | ||
97 | writel(linksystem, regs + EXYNOS5_DRD_LINKSYSTEM); | ||
98 | |||
99 | phyparam1 = readl(regs + EXYNOS5_DRD_PHYPARAM1); | ||
100 | /* Set Tx De-Emphasis level */ | ||
101 | phyparam1 &= ~PHYPARAM1_PCS_TXDEEMPH_MASK; | ||
102 | phyparam1 |= PHYPARAM1_PCS_TXDEEMPH; | ||
103 | writel(phyparam1, regs + EXYNOS5_DRD_PHYPARAM1); | ||
104 | |||
105 | phybatchg = readl(regs + EXYNOS5_DRD_PHYBATCHG); | ||
106 | phybatchg |= PHYBATCHG_UTMI_CLKSEL; | ||
107 | writel(phybatchg, regs + EXYNOS5_DRD_PHYBATCHG); | ||
108 | |||
109 | /* PHYTEST POWERDOWN Control */ | ||
110 | phytest = readl(regs + EXYNOS5_DRD_PHYTEST); | ||
111 | phytest &= ~(PHYTEST_POWERDOWN_SSP | | ||
112 | PHYTEST_POWERDOWN_HSP); | ||
113 | writel(phytest, regs + EXYNOS5_DRD_PHYTEST); | ||
114 | |||
115 | /* UTMI Power Control */ | ||
116 | writel(PHYUTMI_OTGDISABLE, regs + EXYNOS5_DRD_PHYUTMI); | ||
117 | |||
118 | phyclkrst = samsung_usb3phy_set_refclk(sphy); | ||
119 | |||
120 | phyclkrst |= PHYCLKRST_PORTRESET | | ||
121 | /* Digital power supply in normal operating mode */ | ||
122 | PHYCLKRST_RETENABLEN | | ||
123 | /* Enable ref clock for SS function */ | ||
124 | PHYCLKRST_REF_SSP_EN | | ||
125 | /* Enable spread spectrum */ | ||
126 | PHYCLKRST_SSC_EN | | ||
127 | /* Power down HS Bias and PLL blocks in suspend mode */ | ||
128 | PHYCLKRST_COMMONONN; | ||
129 | |||
130 | writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST); | ||
131 | |||
132 | udelay(10); | ||
133 | |||
134 | phyclkrst &= ~(PHYCLKRST_PORTRESET); | ||
135 | writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST); | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static void samsung_exynos5_usb3phy_disable(struct samsung_usbphy *sphy) | ||
141 | { | ||
142 | u32 phyutmi; | ||
143 | u32 phyclkrst; | ||
144 | u32 phytest; | ||
145 | void __iomem *regs = sphy->regs; | ||
146 | |||
147 | phyutmi = PHYUTMI_OTGDISABLE | | ||
148 | PHYUTMI_FORCESUSPEND | | ||
149 | PHYUTMI_FORCESLEEP; | ||
150 | writel(phyutmi, regs + EXYNOS5_DRD_PHYUTMI); | ||
151 | |||
152 | /* Resetting the PHYCLKRST enable bits to reduce leakage current */ | ||
153 | phyclkrst = readl(regs + EXYNOS5_DRD_PHYCLKRST); | ||
154 | phyclkrst &= ~(PHYCLKRST_REF_SSP_EN | | ||
155 | PHYCLKRST_SSC_EN | | ||
156 | PHYCLKRST_COMMONONN); | ||
157 | writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST); | ||
158 | |||
159 | /* Control PHYTEST to remove leakage current */ | ||
160 | phytest = readl(regs + EXYNOS5_DRD_PHYTEST); | ||
161 | phytest |= (PHYTEST_POWERDOWN_SSP | | ||
162 | PHYTEST_POWERDOWN_HSP); | ||
163 | writel(phytest, regs + EXYNOS5_DRD_PHYTEST); | ||
164 | } | ||
165 | |||
166 | static int samsung_usb3phy_init(struct usb_phy *phy) | ||
167 | { | ||
168 | struct samsung_usbphy *sphy; | ||
169 | unsigned long flags; | ||
170 | int ret = 0; | ||
171 | |||
172 | sphy = phy_to_sphy(phy); | ||
173 | |||
174 | /* Enable the phy clock */ | ||
175 | ret = clk_prepare_enable(sphy->clk); | ||
176 | if (ret) { | ||
177 | dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__); | ||
178 | return ret; | ||
179 | } | ||
180 | |||
181 | spin_lock_irqsave(&sphy->lock, flags); | ||
182 | |||
183 | /* setting default phy-type for USB 3.0 */ | ||
184 | samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); | ||
185 | |||
186 | /* Disable phy isolation */ | ||
187 | samsung_usbphy_set_isolation(sphy, false); | ||
188 | |||
189 | /* Initialize usb phy registers */ | ||
190 | samsung_exynos5_usb3phy_enable(sphy); | ||
191 | |||
192 | spin_unlock_irqrestore(&sphy->lock, flags); | ||
193 | |||
194 | /* Disable the phy clock */ | ||
195 | clk_disable_unprepare(sphy->clk); | ||
196 | |||
197 | return ret; | ||
198 | } | ||
199 | |||
200 | /* | ||
201 | * The function passed to the usb driver for phy shutdown | ||
202 | */ | ||
203 | static void samsung_usb3phy_shutdown(struct usb_phy *phy) | ||
204 | { | ||
205 | struct samsung_usbphy *sphy; | ||
206 | unsigned long flags; | ||
207 | |||
208 | sphy = phy_to_sphy(phy); | ||
209 | |||
210 | if (clk_prepare_enable(sphy->clk)) { | ||
211 | dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__); | ||
212 | return; | ||
213 | } | ||
214 | |||
215 | spin_lock_irqsave(&sphy->lock, flags); | ||
216 | |||
217 | /* setting default phy-type for USB 3.0 */ | ||
218 | samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); | ||
219 | |||
220 | /* De-initialize usb phy registers */ | ||
221 | samsung_exynos5_usb3phy_disable(sphy); | ||
222 | |||
223 | /* Enable phy isolation */ | ||
224 | samsung_usbphy_set_isolation(sphy, true); | ||
225 | |||
226 | spin_unlock_irqrestore(&sphy->lock, flags); | ||
227 | |||
228 | clk_disable_unprepare(sphy->clk); | ||
229 | } | ||
230 | |||
231 | static int samsung_usb3phy_probe(struct platform_device *pdev) | ||
232 | { | ||
233 | struct samsung_usbphy *sphy; | ||
234 | struct samsung_usbphy_data *pdata = pdev->dev.platform_data; | ||
235 | struct device *dev = &pdev->dev; | ||
236 | struct resource *phy_mem; | ||
237 | void __iomem *phy_base; | ||
238 | struct clk *clk; | ||
239 | int ret; | ||
240 | |||
241 | phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
242 | if (!phy_mem) { | ||
243 | dev_err(dev, "%s: missing mem resource\n", __func__); | ||
244 | return -ENODEV; | ||
245 | } | ||
246 | |||
247 | phy_base = devm_request_and_ioremap(dev, phy_mem); | ||
248 | if (!phy_base) { | ||
249 | dev_err(dev, "%s: register mapping failed\n", __func__); | ||
250 | return -ENXIO; | ||
251 | } | ||
252 | |||
253 | sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL); | ||
254 | if (!sphy) | ||
255 | return -ENOMEM; | ||
256 | |||
257 | clk = devm_clk_get(dev, "usbdrd30"); | ||
258 | if (IS_ERR(clk)) { | ||
259 | dev_err(dev, "Failed to get device clock\n"); | ||
260 | return PTR_ERR(clk); | ||
261 | } | ||
262 | |||
263 | sphy->dev = dev; | ||
264 | |||
265 | if (dev->of_node) { | ||
266 | ret = samsung_usbphy_parse_dt(sphy); | ||
267 | if (ret < 0) | ||
268 | return ret; | ||
269 | } else { | ||
270 | if (!pdata) { | ||
271 | dev_err(dev, "no platform data specified\n"); | ||
272 | return -EINVAL; | ||
273 | } | ||
274 | } | ||
275 | |||
276 | sphy->plat = pdata; | ||
277 | sphy->regs = phy_base; | ||
278 | sphy->clk = clk; | ||
279 | sphy->phy.dev = sphy->dev; | ||
280 | sphy->phy.label = "samsung-usb3phy"; | ||
281 | sphy->phy.init = samsung_usb3phy_init; | ||
282 | sphy->phy.shutdown = samsung_usb3phy_shutdown; | ||
283 | sphy->drv_data = samsung_usbphy_get_driver_data(pdev); | ||
284 | sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy); | ||
285 | |||
286 | spin_lock_init(&sphy->lock); | ||
287 | |||
288 | platform_set_drvdata(pdev, sphy); | ||
289 | |||
290 | return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB3); | ||
291 | } | ||
292 | |||
293 | static int samsung_usb3phy_remove(struct platform_device *pdev) | ||
294 | { | ||
295 | struct samsung_usbphy *sphy = platform_get_drvdata(pdev); | ||
296 | |||
297 | usb_remove_phy(&sphy->phy); | ||
298 | |||
299 | if (sphy->pmuregs) | ||
300 | iounmap(sphy->pmuregs); | ||
301 | if (sphy->sysreg) | ||
302 | iounmap(sphy->sysreg); | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static struct samsung_usbphy_drvdata usb3phy_exynos5 = { | ||
308 | .cpu_type = TYPE_EXYNOS5250, | ||
309 | .devphy_en_mask = EXYNOS_USBPHY_ENABLE, | ||
310 | }; | ||
311 | |||
312 | #ifdef CONFIG_OF | ||
313 | static const struct of_device_id samsung_usbphy_dt_match[] = { | ||
314 | { | ||
315 | .compatible = "samsung,exynos5250-usb3phy", | ||
316 | .data = &usb3phy_exynos5 | ||
317 | }, | ||
318 | {}, | ||
319 | }; | ||
320 | MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match); | ||
321 | #endif | ||
322 | |||
323 | static struct platform_device_id samsung_usbphy_driver_ids[] = { | ||
324 | { | ||
325 | .name = "exynos5250-usb3phy", | ||
326 | .driver_data = (unsigned long)&usb3phy_exynos5, | ||
327 | }, | ||
328 | {}, | ||
329 | }; | ||
330 | |||
331 | MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids); | ||
332 | |||
333 | static struct platform_driver samsung_usb3phy_driver = { | ||
334 | .probe = samsung_usb3phy_probe, | ||
335 | .remove = samsung_usb3phy_remove, | ||
336 | .id_table = samsung_usbphy_driver_ids, | ||
337 | .driver = { | ||
338 | .name = "samsung-usb3phy", | ||
339 | .owner = THIS_MODULE, | ||
340 | .of_match_table = of_match_ptr(samsung_usbphy_dt_match), | ||
341 | }, | ||
342 | }; | ||
343 | |||
344 | module_platform_driver(samsung_usb3phy_driver); | ||
345 | |||
346 | MODULE_DESCRIPTION("Samsung USB 3.0 phy controller"); | ||
347 | MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>"); | ||
348 | MODULE_LICENSE("GPL"); | ||
349 | MODULE_ALIAS("platform:samsung-usb3phy"); | ||