diff options
Diffstat (limited to 'drivers/usb/phy')
-rw-r--r-- | drivers/usb/phy/Kconfig | 16 | ||||
-rw-r--r-- | drivers/usb/phy/Makefile | 2 | ||||
-rw-r--r-- | drivers/usb/phy/phy-fsl-usb.c | 2 | ||||
-rw-r--r-- | drivers/usb/phy/phy-isp1301-omap.c | 2 | ||||
-rw-r--r-- | drivers/usb/phy/phy-msm-usb.c | 16 | ||||
-rw-r--r-- | drivers/usb/phy/phy-mxs-usb.c | 6 | ||||
-rw-r--r-- | drivers/usb/phy/phy-samsung-usb.c | 241 | ||||
-rw-r--r-- | drivers/usb/phy/phy-samsung-usb.h | 349 | ||||
-rw-r--r-- | drivers/usb/phy/phy-samsung-usb2.c | 541 | ||||
-rw-r--r-- | drivers/usb/phy/phy-samsung-usb3.c | 350 | ||||
-rw-r--r-- | drivers/usb/phy/phy-twl6030-usb.c | 2 |
11 files changed, 17 insertions, 1510 deletions
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index e253fa05be68..0cd1f44f0ee8 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig | |||
@@ -78,22 +78,6 @@ config SAMSUNG_USBPHY | |||
78 | This driver provides common interface to interact, for Samsung USB 2.0 PHY | 78 | This driver provides common interface to interact, for Samsung USB 2.0 PHY |
79 | driver and later for Samsung USB 3.0 PHY driver. | 79 | driver and later for Samsung USB 3.0 PHY driver. |
80 | 80 | ||
81 | config SAMSUNG_USB2PHY | ||
82 | tristate "Samsung USB 2.0 PHY controller Driver" | ||
83 | select SAMSUNG_USBPHY | ||
84 | select USB_PHY | ||
85 | help | ||
86 | Enable this to support Samsung USB 2.0 (High Speed) PHY controller | ||
87 | driver for Samsung SoCs. | ||
88 | |||
89 | config SAMSUNG_USB3PHY | ||
90 | tristate "Samsung USB 3.0 PHY controller Driver" | ||
91 | select SAMSUNG_USBPHY | ||
92 | select USB_PHY | ||
93 | help | ||
94 | Enable this to support Samsung USB 3.0 (Super Speed) phy controller | ||
95 | for samsung SoCs. | ||
96 | |||
97 | config TWL6030_USB | 81 | config TWL6030_USB |
98 | tristate "TWL6030 USB Transceiver Driver" | 82 | tristate "TWL6030 USB Transceiver Driver" |
99 | depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS | 83 | depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS |
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 24a91332d4ad..75f2bba58c84 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile | |||
@@ -15,8 +15,6 @@ obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o | |||
15 | obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o | 15 | obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o |
16 | obj-$(CONFIG_OMAP_OTG) += phy-omap-otg.o | 16 | obj-$(CONFIG_OMAP_OTG) += phy-omap-otg.o |
17 | obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o | 17 | obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o |
18 | obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o | ||
19 | obj-$(CONFIG_SAMSUNG_USB3PHY) += phy-samsung-usb3.o | ||
20 | obj-$(CONFIG_TWL6030_USB) += phy-twl6030-usb.o | 18 | obj-$(CONFIG_TWL6030_USB) += phy-twl6030-usb.o |
21 | obj-$(CONFIG_USB_EHCI_TEGRA) += phy-tegra-usb.o | 19 | obj-$(CONFIG_USB_EHCI_TEGRA) += phy-tegra-usb.o |
22 | obj-$(CONFIG_USB_GPIO_VBUS) += phy-gpio-vbus-usb.o | 20 | obj-$(CONFIG_USB_GPIO_VBUS) += phy-gpio-vbus-usb.o |
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c index 2b0f968d9325..f1ea5990a50a 100644 --- a/drivers/usb/phy/phy-fsl-usb.c +++ b/drivers/usb/phy/phy-fsl-usb.c | |||
@@ -609,7 +609,7 @@ static int fsl_otg_set_host(struct usb_otg *otg, struct usb_bus *host) | |||
609 | otg->host->otg_port = fsl_otg_initdata.otg_port; | 609 | otg->host->otg_port = fsl_otg_initdata.otg_port; |
610 | otg->host->is_b_host = otg_dev->fsm.id; | 610 | otg->host->is_b_host = otg_dev->fsm.id; |
611 | /* | 611 | /* |
612 | * must leave time for khubd to finish its thing | 612 | * must leave time for hub_wq to finish its thing |
613 | * before yanking the host driver out from under it, | 613 | * before yanking the host driver out from under it, |
614 | * so suspend the host after a short delay. | 614 | * so suspend the host after a short delay. |
615 | */ | 615 | */ |
diff --git a/drivers/usb/phy/phy-isp1301-omap.c b/drivers/usb/phy/phy-isp1301-omap.c index 69e49be8866b..8eea56d3ded6 100644 --- a/drivers/usb/phy/phy-isp1301-omap.c +++ b/drivers/usb/phy/phy-isp1301-omap.c | |||
@@ -1011,7 +1011,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) | |||
1011 | break; | 1011 | break; |
1012 | case OTG_STATE_A_WAIT_VFALL: | 1012 | case OTG_STATE_A_WAIT_VFALL: |
1013 | state = OTG_STATE_A_IDLE; | 1013 | state = OTG_STATE_A_IDLE; |
1014 | /* khubd may take a while to notice and | 1014 | /* hub_wq may take a while to notice and |
1015 | * handle this disconnect, so don't go | 1015 | * handle this disconnect, so don't go |
1016 | * to B_IDLE quite yet. | 1016 | * to B_IDLE quite yet. |
1017 | */ | 1017 | */ |
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index afc09087ec36..7843ef7dd0ff 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c | |||
@@ -281,7 +281,7 @@ static int msm_otg_phy_clk_reset(struct msm_otg *motg) | |||
281 | { | 281 | { |
282 | int ret = 0; | 282 | int ret = 0; |
283 | 283 | ||
284 | if (motg->pdata->phy_clk_reset && motg->phy_reset_clk) | 284 | if (motg->pdata->phy_clk_reset) |
285 | ret = motg->pdata->phy_clk_reset(motg->phy_reset_clk); | 285 | ret = motg->pdata->phy_clk_reset(motg->phy_reset_clk); |
286 | else if (motg->phy_rst) | 286 | else if (motg->phy_rst) |
287 | ret = reset_control_reset(motg->phy_rst); | 287 | ret = reset_control_reset(motg->phy_rst); |
@@ -1394,7 +1394,7 @@ out: | |||
1394 | return status; | 1394 | return status; |
1395 | } | 1395 | } |
1396 | 1396 | ||
1397 | const struct file_operations msm_otg_mode_fops = { | 1397 | static const struct file_operations msm_otg_mode_fops = { |
1398 | .open = msm_otg_mode_open, | 1398 | .open = msm_otg_mode_open, |
1399 | .read = seq_read, | 1399 | .read = seq_read, |
1400 | .write = msm_otg_mode_write, | 1400 | .write = msm_otg_mode_write, |
@@ -1554,11 +1554,14 @@ static int msm_otg_probe(struct platform_device *pdev) | |||
1554 | phy = &motg->phy; | 1554 | phy = &motg->phy; |
1555 | phy->dev = &pdev->dev; | 1555 | phy->dev = &pdev->dev; |
1556 | 1556 | ||
1557 | motg->phy_reset_clk = devm_clk_get(&pdev->dev, | 1557 | if (motg->pdata->phy_clk_reset) { |
1558 | motg->phy_reset_clk = devm_clk_get(&pdev->dev, | ||
1558 | np ? "phy" : "usb_phy_clk"); | 1559 | np ? "phy" : "usb_phy_clk"); |
1559 | if (IS_ERR(motg->phy_reset_clk)) { | 1560 | |
1560 | dev_err(&pdev->dev, "failed to get usb_phy_clk\n"); | 1561 | if (IS_ERR(motg->phy_reset_clk)) { |
1561 | motg->phy_reset_clk = NULL; | 1562 | dev_err(&pdev->dev, "failed to get usb_phy_clk\n"); |
1563 | return PTR_ERR(motg->phy_reset_clk); | ||
1564 | } | ||
1562 | } | 1565 | } |
1563 | 1566 | ||
1564 | motg->clk = devm_clk_get(&pdev->dev, np ? "core" : "usb_hs_clk"); | 1567 | motg->clk = devm_clk_get(&pdev->dev, np ? "core" : "usb_hs_clk"); |
@@ -1838,7 +1841,6 @@ static struct platform_driver msm_otg_driver = { | |||
1838 | .remove = msm_otg_remove, | 1841 | .remove = msm_otg_remove, |
1839 | .driver = { | 1842 | .driver = { |
1840 | .name = DRIVER_NAME, | 1843 | .name = DRIVER_NAME, |
1841 | .owner = THIS_MODULE, | ||
1842 | .pm = &msm_otg_dev_pm_ops, | 1844 | .pm = &msm_otg_dev_pm_ops, |
1843 | .of_match_table = msm_otg_dt_match, | 1845 | .of_match_table = msm_otg_dt_match, |
1844 | }, | 1846 | }, |
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index 00972eca04e7..0e0c41587a08 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c | |||
@@ -125,6 +125,11 @@ static const struct mxs_phy_data imx6sl_phy_data = { | |||
125 | MXS_PHY_NEED_IP_FIX, | 125 | MXS_PHY_NEED_IP_FIX, |
126 | }; | 126 | }; |
127 | 127 | ||
128 | static const struct mxs_phy_data vf610_phy_data = { | ||
129 | .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS | | ||
130 | MXS_PHY_NEED_IP_FIX, | ||
131 | }; | ||
132 | |||
128 | static const struct mxs_phy_data imx6sx_phy_data = { | 133 | static const struct mxs_phy_data imx6sx_phy_data = { |
129 | .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS | | 134 | .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS | |
130 | MXS_PHY_NEED_IP_FIX, | 135 | MXS_PHY_NEED_IP_FIX, |
@@ -135,6 +140,7 @@ static const struct of_device_id mxs_phy_dt_ids[] = { | |||
135 | { .compatible = "fsl,imx6sl-usbphy", .data = &imx6sl_phy_data, }, | 140 | { .compatible = "fsl,imx6sl-usbphy", .data = &imx6sl_phy_data, }, |
136 | { .compatible = "fsl,imx6q-usbphy", .data = &imx6q_phy_data, }, | 141 | { .compatible = "fsl,imx6q-usbphy", .data = &imx6q_phy_data, }, |
137 | { .compatible = "fsl,imx23-usbphy", .data = &imx23_phy_data, }, | 142 | { .compatible = "fsl,imx23-usbphy", .data = &imx23_phy_data, }, |
143 | { .compatible = "fsl,vf610-usbphy", .data = &vf610_phy_data, }, | ||
138 | { /* sentinel */ } | 144 | { /* sentinel */ } |
139 | }; | 145 | }; |
140 | MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids); | 146 | MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids); |
diff --git a/drivers/usb/phy/phy-samsung-usb.c b/drivers/usb/phy/phy-samsung-usb.c deleted file mode 100644 index ac025ca08425..000000000000 --- a/drivers/usb/phy/phy-samsung-usb.c +++ /dev/null | |||
@@ -1,241 +0,0 @@ | |||
1 | /* linux/drivers/usb/phy/phy-samsung-usb.c | ||
2 | * | ||
3 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Author: Praveen Paneri <p.paneri@samsung.com> | ||
7 | * | ||
8 | * Samsung USB-PHY helper driver with common function calls; | ||
9 | * interacts with Samsung USB 2.0 PHY controller driver and later | ||
10 | * with Samsung USB 3.0 PHY driver. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/clk.h> | ||
25 | #include <linux/device.h> | ||
26 | #include <linux/err.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/of.h> | ||
29 | #include <linux/of_address.h> | ||
30 | #include <linux/usb/samsung_usb_phy.h> | ||
31 | |||
32 | #include "phy-samsung-usb.h" | ||
33 | |||
34 | int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy) | ||
35 | { | ||
36 | struct device_node *usbphy_sys; | ||
37 | |||
38 | /* Getting node for system controller interface for usb-phy */ | ||
39 | usbphy_sys = of_get_child_by_name(sphy->dev->of_node, "usbphy-sys"); | ||
40 | if (!usbphy_sys) { | ||
41 | dev_err(sphy->dev, "No sys-controller interface for usb-phy\n"); | ||
42 | return -ENODEV; | ||
43 | } | ||
44 | |||
45 | sphy->pmuregs = of_iomap(usbphy_sys, 0); | ||
46 | |||
47 | if (sphy->pmuregs == NULL) { | ||
48 | dev_err(sphy->dev, "Can't get usb-phy pmu control register\n"); | ||
49 | goto err0; | ||
50 | } | ||
51 | |||
52 | sphy->sysreg = of_iomap(usbphy_sys, 1); | ||
53 | |||
54 | /* | ||
55 | * Not returning error code here, since this situation is not fatal. | ||
56 | * Few SoCs may not have this switch available | ||
57 | */ | ||
58 | if (sphy->sysreg == NULL) | ||
59 | dev_warn(sphy->dev, "Can't get usb-phy sysreg cfg register\n"); | ||
60 | |||
61 | of_node_put(usbphy_sys); | ||
62 | |||
63 | return 0; | ||
64 | |||
65 | err0: | ||
66 | of_node_put(usbphy_sys); | ||
67 | return -ENXIO; | ||
68 | } | ||
69 | EXPORT_SYMBOL_GPL(samsung_usbphy_parse_dt); | ||
70 | |||
71 | /* | ||
72 | * Set isolation here for phy. | ||
73 | * Here 'on = true' would mean USB PHY block is isolated, hence | ||
74 | * de-activated and vice-versa. | ||
75 | */ | ||
76 | void samsung_usbphy_set_isolation_4210(struct samsung_usbphy *sphy, bool on) | ||
77 | { | ||
78 | void __iomem *reg = NULL; | ||
79 | u32 reg_val; | ||
80 | u32 en_mask = 0; | ||
81 | |||
82 | if (!sphy->pmuregs) { | ||
83 | dev_warn(sphy->dev, "Can't set pmu isolation\n"); | ||
84 | return; | ||
85 | } | ||
86 | |||
87 | if (sphy->phy_type == USB_PHY_TYPE_DEVICE) { | ||
88 | reg = sphy->pmuregs + sphy->drv_data->devphy_reg_offset; | ||
89 | en_mask = sphy->drv_data->devphy_en_mask; | ||
90 | } else if (sphy->phy_type == USB_PHY_TYPE_HOST) { | ||
91 | reg = sphy->pmuregs + sphy->drv_data->hostphy_reg_offset; | ||
92 | en_mask = sphy->drv_data->hostphy_en_mask; | ||
93 | } | ||
94 | |||
95 | reg_val = readl(reg); | ||
96 | |||
97 | if (on) | ||
98 | reg_val &= ~en_mask; | ||
99 | else | ||
100 | reg_val |= en_mask; | ||
101 | |||
102 | writel(reg_val, reg); | ||
103 | |||
104 | if (sphy->drv_data->cpu_type == TYPE_EXYNOS4X12) { | ||
105 | writel(reg_val, sphy->pmuregs + EXYNOS4X12_PHY_HSIC_CTRL0); | ||
106 | writel(reg_val, sphy->pmuregs + EXYNOS4X12_PHY_HSIC_CTRL1); | ||
107 | } | ||
108 | } | ||
109 | EXPORT_SYMBOL_GPL(samsung_usbphy_set_isolation_4210); | ||
110 | |||
111 | /* | ||
112 | * Configure the mode of working of usb-phy here: HOST/DEVICE. | ||
113 | */ | ||
114 | void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy) | ||
115 | { | ||
116 | u32 reg; | ||
117 | |||
118 | if (!sphy->sysreg) { | ||
119 | dev_warn(sphy->dev, "Can't configure specified phy mode\n"); | ||
120 | return; | ||
121 | } | ||
122 | |||
123 | reg = readl(sphy->sysreg); | ||
124 | |||
125 | if (sphy->phy_type == USB_PHY_TYPE_DEVICE) | ||
126 | reg &= ~EXYNOS_USB20PHY_CFG_HOST_LINK; | ||
127 | else if (sphy->phy_type == USB_PHY_TYPE_HOST) | ||
128 | reg |= EXYNOS_USB20PHY_CFG_HOST_LINK; | ||
129 | |||
130 | writel(reg, sphy->sysreg); | ||
131 | } | ||
132 | EXPORT_SYMBOL_GPL(samsung_usbphy_cfg_sel); | ||
133 | |||
134 | /* | ||
135 | * PHYs are different for USB Device and USB Host. | ||
136 | * This make sure that correct PHY type is selected before | ||
137 | * any operation on PHY. | ||
138 | */ | ||
139 | int samsung_usbphy_set_type(struct usb_phy *phy, | ||
140 | enum samsung_usb_phy_type phy_type) | ||
141 | { | ||
142 | struct samsung_usbphy *sphy = phy_to_sphy(phy); | ||
143 | |||
144 | sphy->phy_type = phy_type; | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | EXPORT_SYMBOL_GPL(samsung_usbphy_set_type); | ||
149 | |||
150 | int samsung_usbphy_rate_to_clksel_64xx(struct samsung_usbphy *sphy, | ||
151 | unsigned long rate) | ||
152 | { | ||
153 | unsigned int clksel; | ||
154 | |||
155 | switch (rate) { | ||
156 | case 12 * MHZ: | ||
157 | clksel = PHYCLK_CLKSEL_12M; | ||
158 | break; | ||
159 | case 24 * MHZ: | ||
160 | clksel = PHYCLK_CLKSEL_24M; | ||
161 | break; | ||
162 | case 48 * MHZ: | ||
163 | clksel = PHYCLK_CLKSEL_48M; | ||
164 | break; | ||
165 | default: | ||
166 | dev_err(sphy->dev, | ||
167 | "Invalid reference clock frequency: %lu\n", rate); | ||
168 | return -EINVAL; | ||
169 | } | ||
170 | |||
171 | return clksel; | ||
172 | } | ||
173 | EXPORT_SYMBOL_GPL(samsung_usbphy_rate_to_clksel_64xx); | ||
174 | |||
175 | int samsung_usbphy_rate_to_clksel_4x12(struct samsung_usbphy *sphy, | ||
176 | unsigned long rate) | ||
177 | { | ||
178 | unsigned int clksel; | ||
179 | |||
180 | switch (rate) { | ||
181 | case 9600 * KHZ: | ||
182 | clksel = FSEL_CLKSEL_9600K; | ||
183 | break; | ||
184 | case 10 * MHZ: | ||
185 | clksel = FSEL_CLKSEL_10M; | ||
186 | break; | ||
187 | case 12 * MHZ: | ||
188 | clksel = FSEL_CLKSEL_12M; | ||
189 | break; | ||
190 | case 19200 * KHZ: | ||
191 | clksel = FSEL_CLKSEL_19200K; | ||
192 | break; | ||
193 | case 20 * MHZ: | ||
194 | clksel = FSEL_CLKSEL_20M; | ||
195 | break; | ||
196 | case 24 * MHZ: | ||
197 | clksel = FSEL_CLKSEL_24M; | ||
198 | break; | ||
199 | case 50 * MHZ: | ||
200 | clksel = FSEL_CLKSEL_50M; | ||
201 | break; | ||
202 | default: | ||
203 | dev_err(sphy->dev, | ||
204 | "Invalid reference clock frequency: %lu\n", rate); | ||
205 | return -EINVAL; | ||
206 | } | ||
207 | |||
208 | return clksel; | ||
209 | } | ||
210 | EXPORT_SYMBOL_GPL(samsung_usbphy_rate_to_clksel_4x12); | ||
211 | |||
212 | /* | ||
213 | * Returns reference clock frequency selection value | ||
214 | */ | ||
215 | int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy) | ||
216 | { | ||
217 | struct clk *ref_clk; | ||
218 | unsigned long rate; | ||
219 | int refclk_freq; | ||
220 | |||
221 | /* | ||
222 | * In exynos5250 USB host and device PHY use | ||
223 | * external crystal clock XXTI | ||
224 | */ | ||
225 | if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) | ||
226 | ref_clk = clk_get(sphy->dev, "ext_xtal"); | ||
227 | else | ||
228 | ref_clk = clk_get(sphy->dev, "xusbxti"); | ||
229 | if (IS_ERR(ref_clk)) { | ||
230 | dev_err(sphy->dev, "Failed to get reference clock\n"); | ||
231 | return PTR_ERR(ref_clk); | ||
232 | } | ||
233 | |||
234 | rate = clk_get_rate(ref_clk); | ||
235 | refclk_freq = sphy->drv_data->rate_to_clksel(sphy, rate); | ||
236 | |||
237 | clk_put(ref_clk); | ||
238 | |||
239 | return refclk_freq; | ||
240 | } | ||
241 | EXPORT_SYMBOL_GPL(samsung_usbphy_get_refclk_freq); | ||
diff --git a/drivers/usb/phy/phy-samsung-usb.h b/drivers/usb/phy/phy-samsung-usb.h deleted file mode 100644 index 80eedd45a20a..000000000000 --- a/drivers/usb/phy/phy-samsung-usb.h +++ /dev/null | |||
@@ -1,349 +0,0 @@ | |||
1 | /* linux/drivers/usb/phy/phy-samsung-usb.h | ||
2 | * | ||
3 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Samsung USB-PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and | ||
7 | * OHCI-EXYNOS controllers. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | */ | ||
18 | |||
19 | #include <linux/usb/phy.h> | ||
20 | |||
21 | /* Register definitions */ | ||
22 | |||
23 | #define SAMSUNG_PHYPWR (0x00) | ||
24 | |||
25 | #define PHYPWR_NORMAL_MASK (0x19 << 0) | ||
26 | #define PHYPWR_OTG_DISABLE (0x1 << 4) | ||
27 | #define PHYPWR_ANALOG_POWERDOWN (0x1 << 3) | ||
28 | #define PHYPWR_FORCE_SUSPEND (0x1 << 1) | ||
29 | /* For Exynos4 */ | ||
30 | #define PHYPWR_NORMAL_MASK_PHY0 (0x39 << 0) | ||
31 | #define PHYPWR_SLEEP_PHY0 (0x1 << 5) | ||
32 | |||
33 | #define SAMSUNG_PHYCLK (0x04) | ||
34 | |||
35 | #define PHYCLK_MODE_USB11 (0x1 << 6) | ||
36 | #define PHYCLK_EXT_OSC (0x1 << 5) | ||
37 | #define PHYCLK_COMMON_ON_N (0x1 << 4) | ||
38 | #define PHYCLK_ID_PULL (0x1 << 2) | ||
39 | #define PHYCLK_CLKSEL_MASK (0x3 << 0) | ||
40 | #define PHYCLK_CLKSEL_48M (0x0 << 0) | ||
41 | #define PHYCLK_CLKSEL_12M (0x2 << 0) | ||
42 | #define PHYCLK_CLKSEL_24M (0x3 << 0) | ||
43 | |||
44 | #define SAMSUNG_RSTCON (0x08) | ||
45 | |||
46 | #define RSTCON_PHYLINK_SWRST (0x1 << 2) | ||
47 | #define RSTCON_HLINK_SWRST (0x1 << 1) | ||
48 | #define RSTCON_SWRST (0x1 << 0) | ||
49 | |||
50 | /* EXYNOS4X12 */ | ||
51 | #define EXYNOS4X12_PHY_HSIC_CTRL0 (0x04) | ||
52 | #define EXYNOS4X12_PHY_HSIC_CTRL1 (0x08) | ||
53 | |||
54 | #define PHYPWR_NORMAL_MASK_HSIC1 (0x7 << 12) | ||
55 | #define PHYPWR_NORMAL_MASK_HSIC0 (0x7 << 9) | ||
56 | #define PHYPWR_NORMAL_MASK_PHY1 (0x7 << 6) | ||
57 | |||
58 | #define RSTCON_HOSTPHY_SWRST (0xf << 3) | ||
59 | |||
60 | /* EXYNOS5 */ | ||
61 | #define EXYNOS5_PHY_HOST_CTRL0 (0x00) | ||
62 | |||
63 | #define HOST_CTRL0_PHYSWRSTALL (0x1 << 31) | ||
64 | |||
65 | #define HOST_CTRL0_REFCLKSEL_MASK (0x3 << 19) | ||
66 | #define HOST_CTRL0_REFCLKSEL_XTAL (0x0 << 19) | ||
67 | #define HOST_CTRL0_REFCLKSEL_EXTL (0x1 << 19) | ||
68 | #define HOST_CTRL0_REFCLKSEL_CLKCORE (0x2 << 19) | ||
69 | |||
70 | #define HOST_CTRL0_FSEL_MASK (0x7 << 16) | ||
71 | #define HOST_CTRL0_FSEL(_x) ((_x) << 16) | ||
72 | |||
73 | #define FSEL_CLKSEL_50M (0x7) | ||
74 | #define FSEL_CLKSEL_24M (0x5) | ||
75 | #define FSEL_CLKSEL_20M (0x4) | ||
76 | #define FSEL_CLKSEL_19200K (0x3) | ||
77 | #define FSEL_CLKSEL_12M (0x2) | ||
78 | #define FSEL_CLKSEL_10M (0x1) | ||
79 | #define FSEL_CLKSEL_9600K (0x0) | ||
80 | |||
81 | #define HOST_CTRL0_TESTBURNIN (0x1 << 11) | ||
82 | #define HOST_CTRL0_RETENABLE (0x1 << 10) | ||
83 | #define HOST_CTRL0_COMMONON_N (0x1 << 9) | ||
84 | #define HOST_CTRL0_SIDDQ (0x1 << 6) | ||
85 | #define HOST_CTRL0_FORCESLEEP (0x1 << 5) | ||
86 | #define HOST_CTRL0_FORCESUSPEND (0x1 << 4) | ||
87 | #define HOST_CTRL0_WORDINTERFACE (0x1 << 3) | ||
88 | #define HOST_CTRL0_UTMISWRST (0x1 << 2) | ||
89 | #define HOST_CTRL0_LINKSWRST (0x1 << 1) | ||
90 | #define HOST_CTRL0_PHYSWRST (0x1 << 0) | ||
91 | |||
92 | #define EXYNOS5_PHY_HOST_TUNE0 (0x04) | ||
93 | |||
94 | #define EXYNOS5_PHY_HSIC_CTRL1 (0x10) | ||
95 | |||
96 | #define EXYNOS5_PHY_HSIC_TUNE1 (0x14) | ||
97 | |||
98 | #define EXYNOS5_PHY_HSIC_CTRL2 (0x20) | ||
99 | |||
100 | #define EXYNOS5_PHY_HSIC_TUNE2 (0x24) | ||
101 | |||
102 | #define HSIC_CTRL_REFCLKSEL_MASK (0x3 << 23) | ||
103 | #define HSIC_CTRL_REFCLKSEL (0x2 << 23) | ||
104 | |||
105 | #define HSIC_CTRL_REFCLKDIV_MASK (0x7f << 16) | ||
106 | #define HSIC_CTRL_REFCLKDIV(_x) ((_x) << 16) | ||
107 | #define HSIC_CTRL_REFCLKDIV_12 (0x24 << 16) | ||
108 | #define HSIC_CTRL_REFCLKDIV_15 (0x1c << 16) | ||
109 | #define HSIC_CTRL_REFCLKDIV_16 (0x1a << 16) | ||
110 | #define HSIC_CTRL_REFCLKDIV_19_2 (0x15 << 16) | ||
111 | #define HSIC_CTRL_REFCLKDIV_20 (0x14 << 16) | ||
112 | |||
113 | #define HSIC_CTRL_SIDDQ (0x1 << 6) | ||
114 | #define HSIC_CTRL_FORCESLEEP (0x1 << 5) | ||
115 | #define HSIC_CTRL_FORCESUSPEND (0x1 << 4) | ||
116 | #define HSIC_CTRL_WORDINTERFACE (0x1 << 3) | ||
117 | #define HSIC_CTRL_UTMISWRST (0x1 << 2) | ||
118 | #define HSIC_CTRL_PHYSWRST (0x1 << 0) | ||
119 | |||
120 | #define EXYNOS5_PHY_HOST_EHCICTRL (0x30) | ||
121 | |||
122 | #define HOST_EHCICTRL_ENAINCRXALIGN (0x1 << 29) | ||
123 | #define HOST_EHCICTRL_ENAINCR4 (0x1 << 28) | ||
124 | #define HOST_EHCICTRL_ENAINCR8 (0x1 << 27) | ||
125 | #define HOST_EHCICTRL_ENAINCR16 (0x1 << 26) | ||
126 | |||
127 | #define EXYNOS5_PHY_HOST_OHCICTRL (0x34) | ||
128 | |||
129 | #define HOST_OHCICTRL_SUSPLGCY (0x1 << 3) | ||
130 | #define HOST_OHCICTRL_APPSTARTCLK (0x1 << 2) | ||
131 | #define HOST_OHCICTRL_CNTSEL (0x1 << 1) | ||
132 | #define HOST_OHCICTRL_CLKCKTRST (0x1 << 0) | ||
133 | |||
134 | #define EXYNOS5_PHY_OTG_SYS (0x38) | ||
135 | |||
136 | #define OTG_SYS_PHYLINK_SWRESET (0x1 << 14) | ||
137 | #define OTG_SYS_LINKSWRST_UOTG (0x1 << 13) | ||
138 | #define OTG_SYS_PHY0_SWRST (0x1 << 12) | ||
139 | |||
140 | #define OTG_SYS_REFCLKSEL_MASK (0x3 << 9) | ||
141 | #define OTG_SYS_REFCLKSEL_XTAL (0x0 << 9) | ||
142 | #define OTG_SYS_REFCLKSEL_EXTL (0x1 << 9) | ||
143 | #define OTG_SYS_REFCLKSEL_CLKCORE (0x2 << 9) | ||
144 | |||
145 | #define OTG_SYS_IDPULLUP_UOTG (0x1 << 8) | ||
146 | #define OTG_SYS_COMMON_ON (0x1 << 7) | ||
147 | |||
148 | #define OTG_SYS_FSEL_MASK (0x7 << 4) | ||
149 | #define OTG_SYS_FSEL(_x) ((_x) << 4) | ||
150 | |||
151 | #define OTG_SYS_FORCESLEEP (0x1 << 3) | ||
152 | #define OTG_SYS_OTGDISABLE (0x1 << 2) | ||
153 | #define OTG_SYS_SIDDQ_UOTG (0x1 << 1) | ||
154 | #define OTG_SYS_FORCESUSPEND (0x1 << 0) | ||
155 | |||
156 | #define EXYNOS5_PHY_OTG_TUNE (0x40) | ||
157 | |||
158 | /* EXYNOS5: USB 3.0 DRD */ | ||
159 | #define EXYNOS5_DRD_LINKSYSTEM (0x04) | ||
160 | |||
161 | #define LINKSYSTEM_FLADJ_MASK (0x3f << 1) | ||
162 | #define LINKSYSTEM_FLADJ(_x) ((_x) << 1) | ||
163 | #define LINKSYSTEM_XHCI_VERSION_CONTROL (0x1 << 27) | ||
164 | |||
165 | #define EXYNOS5_DRD_PHYUTMI (0x08) | ||
166 | |||
167 | #define PHYUTMI_OTGDISABLE (0x1 << 6) | ||
168 | #define PHYUTMI_FORCESUSPEND (0x1 << 1) | ||
169 | #define PHYUTMI_FORCESLEEP (0x1 << 0) | ||
170 | |||
171 | #define EXYNOS5_DRD_PHYPIPE (0x0c) | ||
172 | |||
173 | #define EXYNOS5_DRD_PHYCLKRST (0x10) | ||
174 | |||
175 | #define PHYCLKRST_SSC_REFCLKSEL_MASK (0xff << 23) | ||
176 | #define PHYCLKRST_SSC_REFCLKSEL(_x) ((_x) << 23) | ||
177 | |||
178 | #define PHYCLKRST_SSC_RANGE_MASK (0x03 << 21) | ||
179 | #define PHYCLKRST_SSC_RANGE(_x) ((_x) << 21) | ||
180 | |||
181 | #define PHYCLKRST_SSC_EN (0x1 << 20) | ||
182 | #define PHYCLKRST_REF_SSP_EN (0x1 << 19) | ||
183 | #define PHYCLKRST_REF_CLKDIV2 (0x1 << 18) | ||
184 | |||
185 | #define PHYCLKRST_MPLL_MULTIPLIER_MASK (0x7f << 11) | ||
186 | #define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF (0x19 << 11) | ||
187 | #define PHYCLKRST_MPLL_MULTIPLIER_50M_REF (0x02 << 11) | ||
188 | #define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF (0x68 << 11) | ||
189 | #define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF (0x7d << 11) | ||
190 | #define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF (0x02 << 11) | ||
191 | |||
192 | #define PHYCLKRST_FSEL_MASK (0x3f << 5) | ||
193 | #define PHYCLKRST_FSEL(_x) ((_x) << 5) | ||
194 | #define PHYCLKRST_FSEL_PAD_100MHZ (0x27 << 5) | ||
195 | #define PHYCLKRST_FSEL_PAD_24MHZ (0x2a << 5) | ||
196 | #define PHYCLKRST_FSEL_PAD_20MHZ (0x31 << 5) | ||
197 | #define PHYCLKRST_FSEL_PAD_19_2MHZ (0x38 << 5) | ||
198 | |||
199 | #define PHYCLKRST_RETENABLEN (0x1 << 4) | ||
200 | |||
201 | #define PHYCLKRST_REFCLKSEL_MASK (0x03 << 2) | ||
202 | #define PHYCLKRST_REFCLKSEL_PAD_REFCLK (0x2 << 2) | ||
203 | #define PHYCLKRST_REFCLKSEL_EXT_REFCLK (0x3 << 2) | ||
204 | |||
205 | #define PHYCLKRST_PORTRESET (0x1 << 1) | ||
206 | #define PHYCLKRST_COMMONONN (0x1 << 0) | ||
207 | |||
208 | #define EXYNOS5_DRD_PHYREG0 (0x14) | ||
209 | #define EXYNOS5_DRD_PHYREG1 (0x18) | ||
210 | |||
211 | #define EXYNOS5_DRD_PHYPARAM0 (0x1c) | ||
212 | |||
213 | #define PHYPARAM0_REF_USE_PAD (0x1 << 31) | ||
214 | #define PHYPARAM0_REF_LOSLEVEL_MASK (0x1f << 26) | ||
215 | #define PHYPARAM0_REF_LOSLEVEL (0x9 << 26) | ||
216 | |||
217 | #define EXYNOS5_DRD_PHYPARAM1 (0x20) | ||
218 | |||
219 | #define PHYPARAM1_PCS_TXDEEMPH_MASK (0x3f << 0) | ||
220 | #define PHYPARAM1_PCS_TXDEEMPH (0x1c) | ||
221 | |||
222 | #define EXYNOS5_DRD_PHYTERM (0x24) | ||
223 | |||
224 | #define EXYNOS5_DRD_PHYTEST (0x28) | ||
225 | |||
226 | #define PHYTEST_POWERDOWN_SSP (0x1 << 3) | ||
227 | #define PHYTEST_POWERDOWN_HSP (0x1 << 2) | ||
228 | |||
229 | #define EXYNOS5_DRD_PHYADP (0x2c) | ||
230 | |||
231 | #define EXYNOS5_DRD_PHYBATCHG (0x30) | ||
232 | |||
233 | #define PHYBATCHG_UTMI_CLKSEL (0x1 << 2) | ||
234 | |||
235 | #define EXYNOS5_DRD_PHYRESUME (0x34) | ||
236 | #define EXYNOS5_DRD_LINKPORT (0x44) | ||
237 | |||
238 | #ifndef MHZ | ||
239 | #define MHZ (1000*1000) | ||
240 | #endif | ||
241 | |||
242 | #ifndef KHZ | ||
243 | #define KHZ (1000) | ||
244 | #endif | ||
245 | |||
246 | #define EXYNOS_USBHOST_PHY_CTRL_OFFSET (0x4) | ||
247 | #define S3C64XX_USBPHY_ENABLE (0x1 << 16) | ||
248 | #define EXYNOS_USBPHY_ENABLE (0x1 << 0) | ||
249 | #define EXYNOS_USB20PHY_CFG_HOST_LINK (0x1 << 0) | ||
250 | |||
251 | enum samsung_cpu_type { | ||
252 | TYPE_S3C64XX, | ||
253 | TYPE_EXYNOS4210, | ||
254 | TYPE_EXYNOS4X12, | ||
255 | TYPE_EXYNOS5250, | ||
256 | }; | ||
257 | |||
258 | struct samsung_usbphy; | ||
259 | |||
260 | /* | ||
261 | * struct samsung_usbphy_drvdata - driver data for various SoC variants | ||
262 | * @cpu_type: machine identifier | ||
263 | * @devphy_en_mask: device phy enable mask for PHY CONTROL register | ||
264 | * @hostphy_en_mask: host phy enable mask for PHY CONTROL register | ||
265 | * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from | ||
266 | * mapped address of system controller. | ||
267 | * @hostphy_reg_offset: offset to HOST PHY CONTROL register from | ||
268 | * mapped address of system controller. | ||
269 | * | ||
270 | * Here we have a separate mask for device type phy. | ||
271 | * Having different masks for host and device type phy helps | ||
272 | * in setting independent masks in case of SoCs like S5PV210, | ||
273 | * in which PHY0 and PHY1 enable bits belong to same register | ||
274 | * placed at position 0 and 1 respectively. | ||
275 | * Although for newer SoCs like exynos these bits belong to | ||
276 | * different registers altogether placed at position 0. | ||
277 | */ | ||
278 | struct samsung_usbphy_drvdata { | ||
279 | int cpu_type; | ||
280 | int devphy_en_mask; | ||
281 | int hostphy_en_mask; | ||
282 | u32 devphy_reg_offset; | ||
283 | u32 hostphy_reg_offset; | ||
284 | int (*rate_to_clksel)(struct samsung_usbphy *, unsigned long); | ||
285 | void (*set_isolation)(struct samsung_usbphy *, bool); | ||
286 | void (*phy_enable)(struct samsung_usbphy *); | ||
287 | void (*phy_disable)(struct samsung_usbphy *); | ||
288 | }; | ||
289 | |||
290 | /* | ||
291 | * struct samsung_usbphy - transceiver driver state | ||
292 | * @phy: transceiver structure | ||
293 | * @plat: platform data | ||
294 | * @dev: The parent device supplied to the probe function | ||
295 | * @clk: usb phy clock | ||
296 | * @regs: usb phy controller registers memory base | ||
297 | * @pmuregs: USB device PHY_CONTROL register memory base | ||
298 | * @sysreg: USB2.0 PHY_CFG register memory base | ||
299 | * @ref_clk_freq: reference clock frequency selection | ||
300 | * @drv_data: driver data available for different SoCs | ||
301 | * @phy_type: Samsung SoCs specific phy types: #HOST | ||
302 | * #DEVICE | ||
303 | * @phy_usage: usage count for phy | ||
304 | * @lock: lock for phy operations | ||
305 | */ | ||
306 | struct samsung_usbphy { | ||
307 | struct usb_phy phy; | ||
308 | struct samsung_usbphy_data *plat; | ||
309 | struct device *dev; | ||
310 | struct clk *clk; | ||
311 | void __iomem *regs; | ||
312 | void __iomem *pmuregs; | ||
313 | void __iomem *sysreg; | ||
314 | int ref_clk_freq; | ||
315 | const struct samsung_usbphy_drvdata *drv_data; | ||
316 | enum samsung_usb_phy_type phy_type; | ||
317 | atomic_t phy_usage; | ||
318 | spinlock_t lock; | ||
319 | }; | ||
320 | |||
321 | #define phy_to_sphy(x) container_of((x), struct samsung_usbphy, phy) | ||
322 | |||
323 | static const struct of_device_id samsung_usbphy_dt_match[]; | ||
324 | |||
325 | static inline const struct samsung_usbphy_drvdata | ||
326 | *samsung_usbphy_get_driver_data(struct platform_device *pdev) | ||
327 | { | ||
328 | if (pdev->dev.of_node) { | ||
329 | const struct of_device_id *match; | ||
330 | match = of_match_node(samsung_usbphy_dt_match, | ||
331 | pdev->dev.of_node); | ||
332 | return match->data; | ||
333 | } | ||
334 | |||
335 | return (struct samsung_usbphy_drvdata *) | ||
336 | platform_get_device_id(pdev)->driver_data; | ||
337 | } | ||
338 | |||
339 | extern int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy); | ||
340 | extern void samsung_usbphy_set_isolation_4210(struct samsung_usbphy *sphy, | ||
341 | bool on); | ||
342 | extern void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy); | ||
343 | extern int samsung_usbphy_set_type(struct usb_phy *phy, | ||
344 | enum samsung_usb_phy_type phy_type); | ||
345 | extern int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy); | ||
346 | extern int samsung_usbphy_rate_to_clksel_64xx(struct samsung_usbphy *sphy, | ||
347 | unsigned long rate); | ||
348 | extern int samsung_usbphy_rate_to_clksel_4x12(struct samsung_usbphy *sphy, | ||
349 | unsigned long rate); | ||
diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c deleted file mode 100644 index b3ba86627b72..000000000000 --- a/drivers/usb/phy/phy-samsung-usb2.c +++ /dev/null | |||
@@ -1,541 +0,0 @@ | |||
1 | /* linux/drivers/usb/phy/phy-samsung-usb2.c | ||
2 | * | ||
3 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Author: Praveen Paneri <p.paneri@samsung.com> | ||
7 | * | ||
8 | * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and | ||
9 | * OHCI-EXYNOS controllers. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/clk.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/device.h> | ||
26 | #include <linux/err.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/of.h> | ||
29 | #include <linux/usb/otg.h> | ||
30 | #include <linux/usb/samsung_usb_phy.h> | ||
31 | #include <linux/platform_data/samsung-usbphy.h> | ||
32 | |||
33 | #include "phy-samsung-usb.h" | ||
34 | |||
35 | static int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host) | ||
36 | { | ||
37 | if (!otg) | ||
38 | return -ENODEV; | ||
39 | |||
40 | if (!otg->host) | ||
41 | otg->host = host; | ||
42 | |||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | static bool exynos5_phyhost_is_on(void __iomem *regs) | ||
47 | { | ||
48 | u32 reg; | ||
49 | |||
50 | reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0); | ||
51 | |||
52 | return !(reg & HOST_CTRL0_SIDDQ); | ||
53 | } | ||
54 | |||
55 | static void samsung_exynos5_usb2phy_enable(struct samsung_usbphy *sphy) | ||
56 | { | ||
57 | void __iomem *regs = sphy->regs; | ||
58 | u32 phyclk = sphy->ref_clk_freq; | ||
59 | u32 phyhost; | ||
60 | u32 phyotg; | ||
61 | u32 phyhsic; | ||
62 | u32 ehcictrl; | ||
63 | u32 ohcictrl; | ||
64 | |||
65 | /* | ||
66 | * phy_usage helps in keeping usage count for phy | ||
67 | * so that the first consumer enabling the phy is also | ||
68 | * the last consumer to disable it. | ||
69 | */ | ||
70 | |||
71 | atomic_inc(&sphy->phy_usage); | ||
72 | |||
73 | if (exynos5_phyhost_is_on(regs)) { | ||
74 | dev_info(sphy->dev, "Already power on PHY\n"); | ||
75 | return; | ||
76 | } | ||
77 | |||
78 | /* Host configuration */ | ||
79 | phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0); | ||
80 | |||
81 | /* phy reference clock configuration */ | ||
82 | phyhost &= ~HOST_CTRL0_FSEL_MASK; | ||
83 | phyhost |= HOST_CTRL0_FSEL(phyclk); | ||
84 | |||
85 | /* host phy reset */ | ||
86 | phyhost &= ~(HOST_CTRL0_PHYSWRST | | ||
87 | HOST_CTRL0_PHYSWRSTALL | | ||
88 | HOST_CTRL0_SIDDQ | | ||
89 | /* Enable normal mode of operation */ | ||
90 | HOST_CTRL0_FORCESUSPEND | | ||
91 | HOST_CTRL0_FORCESLEEP); | ||
92 | |||
93 | /* Link reset */ | ||
94 | phyhost |= (HOST_CTRL0_LINKSWRST | | ||
95 | HOST_CTRL0_UTMISWRST | | ||
96 | /* COMMON Block configuration during suspend */ | ||
97 | HOST_CTRL0_COMMONON_N); | ||
98 | writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0); | ||
99 | udelay(10); | ||
100 | phyhost &= ~(HOST_CTRL0_LINKSWRST | | ||
101 | HOST_CTRL0_UTMISWRST); | ||
102 | writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0); | ||
103 | |||
104 | /* OTG configuration */ | ||
105 | phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS); | ||
106 | |||
107 | /* phy reference clock configuration */ | ||
108 | phyotg &= ~OTG_SYS_FSEL_MASK; | ||
109 | phyotg |= OTG_SYS_FSEL(phyclk); | ||
110 | |||
111 | /* Enable normal mode of operation */ | ||
112 | phyotg &= ~(OTG_SYS_FORCESUSPEND | | ||
113 | OTG_SYS_SIDDQ_UOTG | | ||
114 | OTG_SYS_FORCESLEEP | | ||
115 | OTG_SYS_REFCLKSEL_MASK | | ||
116 | /* COMMON Block configuration during suspend */ | ||
117 | OTG_SYS_COMMON_ON); | ||
118 | |||
119 | /* OTG phy & link reset */ | ||
120 | phyotg |= (OTG_SYS_PHY0_SWRST | | ||
121 | OTG_SYS_LINKSWRST_UOTG | | ||
122 | OTG_SYS_PHYLINK_SWRESET | | ||
123 | OTG_SYS_OTGDISABLE | | ||
124 | /* Set phy refclk */ | ||
125 | OTG_SYS_REFCLKSEL_CLKCORE); | ||
126 | |||
127 | writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS); | ||
128 | udelay(10); | ||
129 | phyotg &= ~(OTG_SYS_PHY0_SWRST | | ||
130 | OTG_SYS_LINKSWRST_UOTG | | ||
131 | OTG_SYS_PHYLINK_SWRESET); | ||
132 | writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS); | ||
133 | |||
134 | /* HSIC phy configuration */ | ||
135 | phyhsic = (HSIC_CTRL_REFCLKDIV_12 | | ||
136 | HSIC_CTRL_REFCLKSEL | | ||
137 | HSIC_CTRL_PHYSWRST); | ||
138 | writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1); | ||
139 | writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2); | ||
140 | udelay(10); | ||
141 | phyhsic &= ~HSIC_CTRL_PHYSWRST; | ||
142 | writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1); | ||
143 | writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2); | ||
144 | |||
145 | udelay(80); | ||
146 | |||
147 | /* enable EHCI DMA burst */ | ||
148 | ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL); | ||
149 | ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN | | ||
150 | HOST_EHCICTRL_ENAINCR4 | | ||
151 | HOST_EHCICTRL_ENAINCR8 | | ||
152 | HOST_EHCICTRL_ENAINCR16); | ||
153 | writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL); | ||
154 | |||
155 | /* set ohci_suspend_on_n */ | ||
156 | ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL); | ||
157 | ohcictrl |= HOST_OHCICTRL_SUSPLGCY; | ||
158 | writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL); | ||
159 | } | ||
160 | |||
161 | static void samsung_usb2phy_enable(struct samsung_usbphy *sphy) | ||
162 | { | ||
163 | void __iomem *regs = sphy->regs; | ||
164 | u32 phypwr; | ||
165 | u32 phyclk; | ||
166 | u32 rstcon; | ||
167 | |||
168 | /* set clock frequency for PLL */ | ||
169 | phyclk = sphy->ref_clk_freq; | ||
170 | phypwr = readl(regs + SAMSUNG_PHYPWR); | ||
171 | rstcon = readl(regs + SAMSUNG_RSTCON); | ||
172 | |||
173 | switch (sphy->drv_data->cpu_type) { | ||
174 | case TYPE_S3C64XX: | ||
175 | phyclk &= ~PHYCLK_COMMON_ON_N; | ||
176 | phypwr &= ~PHYPWR_NORMAL_MASK; | ||
177 | rstcon |= RSTCON_SWRST; | ||
178 | break; | ||
179 | case TYPE_EXYNOS4X12: | ||
180 | phypwr &= ~(PHYPWR_NORMAL_MASK_HSIC0 | | ||
181 | PHYPWR_NORMAL_MASK_HSIC1 | | ||
182 | PHYPWR_NORMAL_MASK_PHY1); | ||
183 | rstcon |= RSTCON_HOSTPHY_SWRST; | ||
184 | case TYPE_EXYNOS4210: | ||
185 | phypwr &= ~PHYPWR_NORMAL_MASK_PHY0; | ||
186 | rstcon |= RSTCON_SWRST; | ||
187 | default: | ||
188 | break; | ||
189 | } | ||
190 | |||
191 | writel(phyclk, regs + SAMSUNG_PHYCLK); | ||
192 | /* Configure PHY0 for normal operation*/ | ||
193 | writel(phypwr, regs + SAMSUNG_PHYPWR); | ||
194 | /* reset all ports of PHY and Link */ | ||
195 | writel(rstcon, regs + SAMSUNG_RSTCON); | ||
196 | udelay(10); | ||
197 | if (sphy->drv_data->cpu_type == TYPE_EXYNOS4X12) | ||
198 | rstcon &= ~RSTCON_HOSTPHY_SWRST; | ||
199 | rstcon &= ~RSTCON_SWRST; | ||
200 | writel(rstcon, regs + SAMSUNG_RSTCON); | ||
201 | } | ||
202 | |||
203 | static void samsung_exynos5_usb2phy_disable(struct samsung_usbphy *sphy) | ||
204 | { | ||
205 | void __iomem *regs = sphy->regs; | ||
206 | u32 phyhost; | ||
207 | u32 phyotg; | ||
208 | u32 phyhsic; | ||
209 | |||
210 | if (atomic_dec_return(&sphy->phy_usage) > 0) { | ||
211 | dev_info(sphy->dev, "still being used\n"); | ||
212 | return; | ||
213 | } | ||
214 | |||
215 | phyhsic = (HSIC_CTRL_REFCLKDIV_12 | | ||
216 | HSIC_CTRL_REFCLKSEL | | ||
217 | HSIC_CTRL_SIDDQ | | ||
218 | HSIC_CTRL_FORCESLEEP | | ||
219 | HSIC_CTRL_FORCESUSPEND); | ||
220 | writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1); | ||
221 | writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2); | ||
222 | |||
223 | phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0); | ||
224 | phyhost |= (HOST_CTRL0_SIDDQ | | ||
225 | HOST_CTRL0_FORCESUSPEND | | ||
226 | HOST_CTRL0_FORCESLEEP | | ||
227 | HOST_CTRL0_PHYSWRST | | ||
228 | HOST_CTRL0_PHYSWRSTALL); | ||
229 | writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0); | ||
230 | |||
231 | phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS); | ||
232 | phyotg |= (OTG_SYS_FORCESUSPEND | | ||
233 | OTG_SYS_SIDDQ_UOTG | | ||
234 | OTG_SYS_FORCESLEEP); | ||
235 | writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS); | ||
236 | } | ||
237 | |||
238 | static void samsung_usb2phy_disable(struct samsung_usbphy *sphy) | ||
239 | { | ||
240 | void __iomem *regs = sphy->regs; | ||
241 | u32 phypwr; | ||
242 | |||
243 | phypwr = readl(regs + SAMSUNG_PHYPWR); | ||
244 | |||
245 | switch (sphy->drv_data->cpu_type) { | ||
246 | case TYPE_S3C64XX: | ||
247 | phypwr |= PHYPWR_NORMAL_MASK; | ||
248 | break; | ||
249 | case TYPE_EXYNOS4X12: | ||
250 | phypwr |= (PHYPWR_NORMAL_MASK_HSIC0 | | ||
251 | PHYPWR_NORMAL_MASK_HSIC1 | | ||
252 | PHYPWR_NORMAL_MASK_PHY1); | ||
253 | case TYPE_EXYNOS4210: | ||
254 | phypwr |= PHYPWR_NORMAL_MASK_PHY0; | ||
255 | default: | ||
256 | break; | ||
257 | } | ||
258 | |||
259 | /* Disable analog and otg block power */ | ||
260 | writel(phypwr, regs + SAMSUNG_PHYPWR); | ||
261 | } | ||
262 | |||
263 | /* | ||
264 | * The function passed to the usb driver for phy initialization | ||
265 | */ | ||
266 | static int samsung_usb2phy_init(struct usb_phy *phy) | ||
267 | { | ||
268 | struct samsung_usbphy *sphy; | ||
269 | struct usb_bus *host = NULL; | ||
270 | unsigned long flags; | ||
271 | int ret = 0; | ||
272 | |||
273 | sphy = phy_to_sphy(phy); | ||
274 | |||
275 | host = phy->otg->host; | ||
276 | |||
277 | /* Enable the phy clock */ | ||
278 | ret = clk_prepare_enable(sphy->clk); | ||
279 | if (ret) { | ||
280 | dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__); | ||
281 | return ret; | ||
282 | } | ||
283 | |||
284 | spin_lock_irqsave(&sphy->lock, flags); | ||
285 | |||
286 | if (host) { | ||
287 | /* setting default phy-type for USB 2.0 */ | ||
288 | if (!strstr(dev_name(host->controller), "ehci") || | ||
289 | !strstr(dev_name(host->controller), "ohci")) | ||
290 | samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST); | ||
291 | } else { | ||
292 | samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); | ||
293 | } | ||
294 | |||
295 | /* Disable phy isolation */ | ||
296 | if (sphy->plat && sphy->plat->pmu_isolation) | ||
297 | sphy->plat->pmu_isolation(false); | ||
298 | else if (sphy->drv_data->set_isolation) | ||
299 | sphy->drv_data->set_isolation(sphy, false); | ||
300 | |||
301 | /* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */ | ||
302 | samsung_usbphy_cfg_sel(sphy); | ||
303 | |||
304 | /* Initialize usb phy registers */ | ||
305 | sphy->drv_data->phy_enable(sphy); | ||
306 | |||
307 | spin_unlock_irqrestore(&sphy->lock, flags); | ||
308 | |||
309 | /* Disable the phy clock */ | ||
310 | clk_disable_unprepare(sphy->clk); | ||
311 | |||
312 | return ret; | ||
313 | } | ||
314 | |||
315 | /* | ||
316 | * The function passed to the usb driver for phy shutdown | ||
317 | */ | ||
318 | static void samsung_usb2phy_shutdown(struct usb_phy *phy) | ||
319 | { | ||
320 | struct samsung_usbphy *sphy; | ||
321 | struct usb_bus *host = NULL; | ||
322 | unsigned long flags; | ||
323 | |||
324 | sphy = phy_to_sphy(phy); | ||
325 | |||
326 | host = phy->otg->host; | ||
327 | |||
328 | if (clk_prepare_enable(sphy->clk)) { | ||
329 | dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__); | ||
330 | return; | ||
331 | } | ||
332 | |||
333 | spin_lock_irqsave(&sphy->lock, flags); | ||
334 | |||
335 | if (host) { | ||
336 | /* setting default phy-type for USB 2.0 */ | ||
337 | if (!strstr(dev_name(host->controller), "ehci") || | ||
338 | !strstr(dev_name(host->controller), "ohci")) | ||
339 | samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST); | ||
340 | } else { | ||
341 | samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); | ||
342 | } | ||
343 | |||
344 | /* De-initialize usb phy registers */ | ||
345 | sphy->drv_data->phy_disable(sphy); | ||
346 | |||
347 | /* Enable phy isolation */ | ||
348 | if (sphy->plat && sphy->plat->pmu_isolation) | ||
349 | sphy->plat->pmu_isolation(true); | ||
350 | else if (sphy->drv_data->set_isolation) | ||
351 | sphy->drv_data->set_isolation(sphy, true); | ||
352 | |||
353 | spin_unlock_irqrestore(&sphy->lock, flags); | ||
354 | |||
355 | clk_disable_unprepare(sphy->clk); | ||
356 | } | ||
357 | |||
358 | static int samsung_usb2phy_probe(struct platform_device *pdev) | ||
359 | { | ||
360 | struct samsung_usbphy *sphy; | ||
361 | struct usb_otg *otg; | ||
362 | struct samsung_usbphy_data *pdata = dev_get_platdata(&pdev->dev); | ||
363 | const struct samsung_usbphy_drvdata *drv_data; | ||
364 | struct device *dev = &pdev->dev; | ||
365 | struct resource *phy_mem; | ||
366 | void __iomem *phy_base; | ||
367 | struct clk *clk; | ||
368 | int ret; | ||
369 | |||
370 | phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
371 | phy_base = devm_ioremap_resource(dev, phy_mem); | ||
372 | if (IS_ERR(phy_base)) | ||
373 | return PTR_ERR(phy_base); | ||
374 | |||
375 | sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL); | ||
376 | if (!sphy) | ||
377 | return -ENOMEM; | ||
378 | |||
379 | otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL); | ||
380 | if (!otg) | ||
381 | return -ENOMEM; | ||
382 | |||
383 | drv_data = samsung_usbphy_get_driver_data(pdev); | ||
384 | |||
385 | if (drv_data->cpu_type == TYPE_EXYNOS5250) | ||
386 | clk = devm_clk_get(dev, "usbhost"); | ||
387 | else | ||
388 | clk = devm_clk_get(dev, "otg"); | ||
389 | |||
390 | if (IS_ERR(clk)) { | ||
391 | dev_err(dev, "Failed to get usbhost/otg clock\n"); | ||
392 | return PTR_ERR(clk); | ||
393 | } | ||
394 | |||
395 | sphy->dev = dev; | ||
396 | |||
397 | if (dev->of_node) { | ||
398 | ret = samsung_usbphy_parse_dt(sphy); | ||
399 | if (ret < 0) | ||
400 | return ret; | ||
401 | } else { | ||
402 | if (!pdata) { | ||
403 | dev_err(dev, "no platform data specified\n"); | ||
404 | return -EINVAL; | ||
405 | } | ||
406 | } | ||
407 | |||
408 | sphy->plat = pdata; | ||
409 | sphy->regs = phy_base; | ||
410 | sphy->clk = clk; | ||
411 | sphy->drv_data = drv_data; | ||
412 | sphy->phy.dev = sphy->dev; | ||
413 | sphy->phy.label = "samsung-usb2phy"; | ||
414 | sphy->phy.type = USB_PHY_TYPE_USB2; | ||
415 | sphy->phy.init = samsung_usb2phy_init; | ||
416 | sphy->phy.shutdown = samsung_usb2phy_shutdown; | ||
417 | |||
418 | sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy); | ||
419 | if (sphy->ref_clk_freq < 0) | ||
420 | return -EINVAL; | ||
421 | |||
422 | sphy->phy.otg = otg; | ||
423 | sphy->phy.otg->phy = &sphy->phy; | ||
424 | sphy->phy.otg->set_host = samsung_usbphy_set_host; | ||
425 | |||
426 | spin_lock_init(&sphy->lock); | ||
427 | |||
428 | platform_set_drvdata(pdev, sphy); | ||
429 | |||
430 | return usb_add_phy_dev(&sphy->phy); | ||
431 | } | ||
432 | |||
433 | static int samsung_usb2phy_remove(struct platform_device *pdev) | ||
434 | { | ||
435 | struct samsung_usbphy *sphy = platform_get_drvdata(pdev); | ||
436 | |||
437 | usb_remove_phy(&sphy->phy); | ||
438 | |||
439 | if (sphy->pmuregs) | ||
440 | iounmap(sphy->pmuregs); | ||
441 | if (sphy->sysreg) | ||
442 | iounmap(sphy->sysreg); | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | static const struct samsung_usbphy_drvdata usb2phy_s3c64xx = { | ||
448 | .cpu_type = TYPE_S3C64XX, | ||
449 | .devphy_en_mask = S3C64XX_USBPHY_ENABLE, | ||
450 | .rate_to_clksel = samsung_usbphy_rate_to_clksel_64xx, | ||
451 | .set_isolation = NULL, /* TODO */ | ||
452 | .phy_enable = samsung_usb2phy_enable, | ||
453 | .phy_disable = samsung_usb2phy_disable, | ||
454 | }; | ||
455 | |||
456 | static const struct samsung_usbphy_drvdata usb2phy_exynos4 = { | ||
457 | .cpu_type = TYPE_EXYNOS4210, | ||
458 | .devphy_en_mask = EXYNOS_USBPHY_ENABLE, | ||
459 | .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, | ||
460 | .rate_to_clksel = samsung_usbphy_rate_to_clksel_64xx, | ||
461 | .set_isolation = samsung_usbphy_set_isolation_4210, | ||
462 | .phy_enable = samsung_usb2phy_enable, | ||
463 | .phy_disable = samsung_usb2phy_disable, | ||
464 | }; | ||
465 | |||
466 | static const struct samsung_usbphy_drvdata usb2phy_exynos4x12 = { | ||
467 | .cpu_type = TYPE_EXYNOS4X12, | ||
468 | .devphy_en_mask = EXYNOS_USBPHY_ENABLE, | ||
469 | .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, | ||
470 | .rate_to_clksel = samsung_usbphy_rate_to_clksel_4x12, | ||
471 | .set_isolation = samsung_usbphy_set_isolation_4210, | ||
472 | .phy_enable = samsung_usb2phy_enable, | ||
473 | .phy_disable = samsung_usb2phy_disable, | ||
474 | }; | ||
475 | |||
476 | static struct samsung_usbphy_drvdata usb2phy_exynos5 = { | ||
477 | .cpu_type = TYPE_EXYNOS5250, | ||
478 | .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, | ||
479 | .hostphy_reg_offset = EXYNOS_USBHOST_PHY_CTRL_OFFSET, | ||
480 | .rate_to_clksel = samsung_usbphy_rate_to_clksel_4x12, | ||
481 | .set_isolation = samsung_usbphy_set_isolation_4210, | ||
482 | .phy_enable = samsung_exynos5_usb2phy_enable, | ||
483 | .phy_disable = samsung_exynos5_usb2phy_disable, | ||
484 | }; | ||
485 | |||
486 | #ifdef CONFIG_OF | ||
487 | static const struct of_device_id samsung_usbphy_dt_match[] = { | ||
488 | { | ||
489 | .compatible = "samsung,s3c64xx-usb2phy", | ||
490 | .data = &usb2phy_s3c64xx, | ||
491 | }, { | ||
492 | .compatible = "samsung,exynos4210-usb2phy", | ||
493 | .data = &usb2phy_exynos4, | ||
494 | }, { | ||
495 | .compatible = "samsung,exynos4x12-usb2phy", | ||
496 | .data = &usb2phy_exynos4x12, | ||
497 | }, { | ||
498 | .compatible = "samsung,exynos5250-usb2phy", | ||
499 | .data = &usb2phy_exynos5 | ||
500 | }, | ||
501 | {}, | ||
502 | }; | ||
503 | MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match); | ||
504 | #endif | ||
505 | |||
506 | static struct platform_device_id samsung_usbphy_driver_ids[] = { | ||
507 | { | ||
508 | .name = "s3c64xx-usb2phy", | ||
509 | .driver_data = (unsigned long)&usb2phy_s3c64xx, | ||
510 | }, { | ||
511 | .name = "exynos4210-usb2phy", | ||
512 | .driver_data = (unsigned long)&usb2phy_exynos4, | ||
513 | }, { | ||
514 | .name = "exynos4x12-usb2phy", | ||
515 | .driver_data = (unsigned long)&usb2phy_exynos4x12, | ||
516 | }, { | ||
517 | .name = "exynos5250-usb2phy", | ||
518 | .driver_data = (unsigned long)&usb2phy_exynos5, | ||
519 | }, | ||
520 | {}, | ||
521 | }; | ||
522 | |||
523 | MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids); | ||
524 | |||
525 | static struct platform_driver samsung_usb2phy_driver = { | ||
526 | .probe = samsung_usb2phy_probe, | ||
527 | .remove = samsung_usb2phy_remove, | ||
528 | .id_table = samsung_usbphy_driver_ids, | ||
529 | .driver = { | ||
530 | .name = "samsung-usb2phy", | ||
531 | .owner = THIS_MODULE, | ||
532 | .of_match_table = of_match_ptr(samsung_usbphy_dt_match), | ||
533 | }, | ||
534 | }; | ||
535 | |||
536 | module_platform_driver(samsung_usb2phy_driver); | ||
537 | |||
538 | MODULE_DESCRIPTION("Samsung USB 2.0 phy controller"); | ||
539 | MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>"); | ||
540 | MODULE_LICENSE("GPL"); | ||
541 | MODULE_ALIAS("platform:samsung-usb2phy"); | ||
diff --git a/drivers/usb/phy/phy-samsung-usb3.c b/drivers/usb/phy/phy-samsung-usb3.c deleted file mode 100644 index cc0819248acf..000000000000 --- a/drivers/usb/phy/phy-samsung-usb3.c +++ /dev/null | |||
@@ -1,350 +0,0 @@ | |||
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 void 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 | |||
138 | static void samsung_exynos5_usb3phy_disable(struct samsung_usbphy *sphy) | ||
139 | { | ||
140 | u32 phyutmi; | ||
141 | u32 phyclkrst; | ||
142 | u32 phytest; | ||
143 | void __iomem *regs = sphy->regs; | ||
144 | |||
145 | phyutmi = PHYUTMI_OTGDISABLE | | ||
146 | PHYUTMI_FORCESUSPEND | | ||
147 | PHYUTMI_FORCESLEEP; | ||
148 | writel(phyutmi, regs + EXYNOS5_DRD_PHYUTMI); | ||
149 | |||
150 | /* Resetting the PHYCLKRST enable bits to reduce leakage current */ | ||
151 | phyclkrst = readl(regs + EXYNOS5_DRD_PHYCLKRST); | ||
152 | phyclkrst &= ~(PHYCLKRST_REF_SSP_EN | | ||
153 | PHYCLKRST_SSC_EN | | ||
154 | PHYCLKRST_COMMONONN); | ||
155 | writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST); | ||
156 | |||
157 | /* Control PHYTEST to remove leakage current */ | ||
158 | phytest = readl(regs + EXYNOS5_DRD_PHYTEST); | ||
159 | phytest |= (PHYTEST_POWERDOWN_SSP | | ||
160 | PHYTEST_POWERDOWN_HSP); | ||
161 | writel(phytest, regs + EXYNOS5_DRD_PHYTEST); | ||
162 | } | ||
163 | |||
164 | static int samsung_usb3phy_init(struct usb_phy *phy) | ||
165 | { | ||
166 | struct samsung_usbphy *sphy; | ||
167 | unsigned long flags; | ||
168 | int ret = 0; | ||
169 | |||
170 | sphy = phy_to_sphy(phy); | ||
171 | |||
172 | /* Enable the phy clock */ | ||
173 | ret = clk_prepare_enable(sphy->clk); | ||
174 | if (ret) { | ||
175 | dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__); | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | spin_lock_irqsave(&sphy->lock, flags); | ||
180 | |||
181 | /* setting default phy-type for USB 3.0 */ | ||
182 | samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); | ||
183 | |||
184 | /* Disable phy isolation */ | ||
185 | if (sphy->drv_data->set_isolation) | ||
186 | sphy->drv_data->set_isolation(sphy, false); | ||
187 | |||
188 | /* Initialize usb phy registers */ | ||
189 | sphy->drv_data->phy_enable(sphy); | ||
190 | |||
191 | spin_unlock_irqrestore(&sphy->lock, flags); | ||
192 | |||
193 | /* Disable the phy clock */ | ||
194 | clk_disable_unprepare(sphy->clk); | ||
195 | |||
196 | return ret; | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | * The function passed to the usb driver for phy shutdown | ||
201 | */ | ||
202 | static void samsung_usb3phy_shutdown(struct usb_phy *phy) | ||
203 | { | ||
204 | struct samsung_usbphy *sphy; | ||
205 | unsigned long flags; | ||
206 | |||
207 | sphy = phy_to_sphy(phy); | ||
208 | |||
209 | if (clk_prepare_enable(sphy->clk)) { | ||
210 | dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__); | ||
211 | return; | ||
212 | } | ||
213 | |||
214 | spin_lock_irqsave(&sphy->lock, flags); | ||
215 | |||
216 | /* setting default phy-type for USB 3.0 */ | ||
217 | samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); | ||
218 | |||
219 | /* De-initialize usb phy registers */ | ||
220 | sphy->drv_data->phy_disable(sphy); | ||
221 | |||
222 | /* Enable phy isolation */ | ||
223 | if (sphy->drv_data->set_isolation) | ||
224 | sphy->drv_data->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 = dev_get_platdata(&pdev->dev); | ||
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 | phy_base = devm_ioremap_resource(dev, phy_mem); | ||
243 | if (IS_ERR(phy_base)) | ||
244 | return PTR_ERR(phy_base); | ||
245 | |||
246 | sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL); | ||
247 | if (!sphy) | ||
248 | return -ENOMEM; | ||
249 | |||
250 | clk = devm_clk_get(dev, "usbdrd30"); | ||
251 | if (IS_ERR(clk)) { | ||
252 | dev_err(dev, "Failed to get device clock\n"); | ||
253 | return PTR_ERR(clk); | ||
254 | } | ||
255 | |||
256 | sphy->dev = dev; | ||
257 | |||
258 | if (dev->of_node) { | ||
259 | ret = samsung_usbphy_parse_dt(sphy); | ||
260 | if (ret < 0) | ||
261 | return ret; | ||
262 | } else { | ||
263 | if (!pdata) { | ||
264 | dev_err(dev, "no platform data specified\n"); | ||
265 | return -EINVAL; | ||
266 | } | ||
267 | } | ||
268 | |||
269 | sphy->plat = pdata; | ||
270 | sphy->regs = phy_base; | ||
271 | sphy->clk = clk; | ||
272 | sphy->phy.dev = sphy->dev; | ||
273 | sphy->phy.label = "samsung-usb3phy"; | ||
274 | sphy->phy.type = USB_PHY_TYPE_USB3; | ||
275 | sphy->phy.init = samsung_usb3phy_init; | ||
276 | sphy->phy.shutdown = samsung_usb3phy_shutdown; | ||
277 | sphy->drv_data = samsung_usbphy_get_driver_data(pdev); | ||
278 | |||
279 | sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy); | ||
280 | if (sphy->ref_clk_freq < 0) | ||
281 | return -EINVAL; | ||
282 | |||
283 | spin_lock_init(&sphy->lock); | ||
284 | |||
285 | platform_set_drvdata(pdev, sphy); | ||
286 | |||
287 | return usb_add_phy_dev(&sphy->phy); | ||
288 | } | ||
289 | |||
290 | static int samsung_usb3phy_remove(struct platform_device *pdev) | ||
291 | { | ||
292 | struct samsung_usbphy *sphy = platform_get_drvdata(pdev); | ||
293 | |||
294 | usb_remove_phy(&sphy->phy); | ||
295 | |||
296 | if (sphy->pmuregs) | ||
297 | iounmap(sphy->pmuregs); | ||
298 | if (sphy->sysreg) | ||
299 | iounmap(sphy->sysreg); | ||
300 | |||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | static struct samsung_usbphy_drvdata usb3phy_exynos5 = { | ||
305 | .cpu_type = TYPE_EXYNOS5250, | ||
306 | .devphy_en_mask = EXYNOS_USBPHY_ENABLE, | ||
307 | .rate_to_clksel = samsung_usbphy_rate_to_clksel_4x12, | ||
308 | .set_isolation = samsung_usbphy_set_isolation_4210, | ||
309 | .phy_enable = samsung_exynos5_usb3phy_enable, | ||
310 | .phy_disable = samsung_exynos5_usb3phy_disable, | ||
311 | }; | ||
312 | |||
313 | #ifdef CONFIG_OF | ||
314 | static const struct of_device_id samsung_usbphy_dt_match[] = { | ||
315 | { | ||
316 | .compatible = "samsung,exynos5250-usb3phy", | ||
317 | .data = &usb3phy_exynos5 | ||
318 | }, | ||
319 | {}, | ||
320 | }; | ||
321 | MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match); | ||
322 | #endif | ||
323 | |||
324 | static struct platform_device_id samsung_usbphy_driver_ids[] = { | ||
325 | { | ||
326 | .name = "exynos5250-usb3phy", | ||
327 | .driver_data = (unsigned long)&usb3phy_exynos5, | ||
328 | }, | ||
329 | {}, | ||
330 | }; | ||
331 | |||
332 | MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids); | ||
333 | |||
334 | static struct platform_driver samsung_usb3phy_driver = { | ||
335 | .probe = samsung_usb3phy_probe, | ||
336 | .remove = samsung_usb3phy_remove, | ||
337 | .id_table = samsung_usbphy_driver_ids, | ||
338 | .driver = { | ||
339 | .name = "samsung-usb3phy", | ||
340 | .owner = THIS_MODULE, | ||
341 | .of_match_table = of_match_ptr(samsung_usbphy_dt_match), | ||
342 | }, | ||
343 | }; | ||
344 | |||
345 | module_platform_driver(samsung_usb3phy_driver); | ||
346 | |||
347 | MODULE_DESCRIPTION("Samsung USB 3.0 phy controller"); | ||
348 | MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>"); | ||
349 | MODULE_LICENSE("GPL"); | ||
350 | MODULE_ALIAS("platform:samsung-usb3phy"); | ||
diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c index 04778cf80d60..44ea082e40dc 100644 --- a/drivers/usb/phy/phy-twl6030-usb.c +++ b/drivers/usb/phy/phy-twl6030-usb.c | |||
@@ -104,7 +104,6 @@ struct twl6030_usb { | |||
104 | int irq2; | 104 | int irq2; |
105 | enum omap_musb_vbus_id_status linkstat; | 105 | enum omap_musb_vbus_id_status linkstat; |
106 | u8 asleep; | 106 | u8 asleep; |
107 | bool irq_enabled; | ||
108 | bool vbus_enable; | 107 | bool vbus_enable; |
109 | const char *regulator; | 108 | const char *regulator; |
110 | }; | 109 | }; |
@@ -373,7 +372,6 @@ static int twl6030_usb_probe(struct platform_device *pdev) | |||
373 | 372 | ||
374 | INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); | 373 | INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); |
375 | 374 | ||
376 | twl->irq_enabled = true; | ||
377 | status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq, | 375 | status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq, |
378 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | 376 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, |
379 | "twl6030_usb", twl); | 377 | "twl6030_usb", twl); |