aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Osipenko <digetx@gmail.com>2018-04-09 18:02:58 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-04-23 03:50:57 -0400
commit143470368efd3f0fb4cbe81aa89f49de8048d8a9 (patch)
tree3be5a1e74b7d20059e37b8ccee62c503e87f0b0d
parentf59cd940051459f04eb5cbdf07cab27d628439cf (diff)
usb: tegra: Move utmi-pads reset from ehci-tegra to tegra-phy
UTMI pads are shared by USB controllers and reset of UTMI pads is shared with the reset of USB1 controller. Currently reset of UTMI pads is done by the EHCI driver and ChipIdea UDC works because EHCI driver always happen to be probed first. Move reset controls from ehci-tegra to tegra-phy in order to resolve the problem. Signed-off-by: Dmitry Osipenko <digetx@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/host/ehci-tegra.c87
-rw-r--r--drivers/usb/phy/phy-tegra-usb.c79
-rw-r--r--include/linux/usb/tegra_usb_phy.h2
3 files changed, 115 insertions, 53 deletions
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index a6f4389f7e88..4d2cdec4cb78 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -36,7 +36,6 @@
36#define DRV_NAME "tegra-ehci" 36#define DRV_NAME "tegra-ehci"
37 37
38static struct hc_driver __read_mostly tegra_ehci_hc_driver; 38static struct hc_driver __read_mostly tegra_ehci_hc_driver;
39static bool usb1_reset_attempted;
40 39
41struct tegra_ehci_soc_config { 40struct tegra_ehci_soc_config {
42 bool has_hostpc; 41 bool has_hostpc;
@@ -51,67 +50,54 @@ struct tegra_ehci_hcd {
51 enum tegra_usb_phy_port_speed port_speed; 50 enum tegra_usb_phy_port_speed port_speed;
52}; 51};
53 52
54/*
55 * The 1st USB controller contains some UTMI pad registers that are global for
56 * all the controllers on the chip. Those registers are also cleared when
57 * reset is asserted to the 1st controller. This means that the 1st controller
58 * can only be reset when no other controlled has finished probing. So we'll
59 * reset the 1st controller before doing any other setup on any of the
60 * controllers, and then never again.
61 *
62 * Since this is a PHY issue, the Tegra PHY driver should probably be doing
63 * the resetting of the USB controllers. But to keep compatibility with old
64 * device trees that don't have reset phandles in the PHYs, do it here.
65 * Those old DTs will be vulnerable to total USB breakage if the 1st EHCI
66 * device isn't the first one to finish probing, so warn them.
67 */
68static int tegra_reset_usb_controller(struct platform_device *pdev) 53static int tegra_reset_usb_controller(struct platform_device *pdev)
69{ 54{
70 struct device_node *phy_np; 55 struct device_node *phy_np;
71 struct usb_hcd *hcd = platform_get_drvdata(pdev); 56 struct usb_hcd *hcd = platform_get_drvdata(pdev);
72 struct tegra_ehci_hcd *tegra = 57 struct tegra_ehci_hcd *tegra =
73 (struct tegra_ehci_hcd *)hcd_to_ehci(hcd)->priv; 58 (struct tegra_ehci_hcd *)hcd_to_ehci(hcd)->priv;
74 bool has_utmi_pad_registers = false; 59 struct reset_control *rst;
60 int err;
75 61
76 phy_np = of_parse_phandle(pdev->dev.of_node, "nvidia,phy", 0); 62 phy_np = of_parse_phandle(pdev->dev.of_node, "nvidia,phy", 0);
77 if (!phy_np) 63 if (!phy_np)
78 return -ENOENT; 64 return -ENOENT;
79 65
80 if (of_property_read_bool(phy_np, "nvidia,has-utmi-pad-registers")) 66 /*
81 has_utmi_pad_registers = true; 67 * The 1st USB controller contains some UTMI pad registers that are
68 * global for all the controllers on the chip. Those registers are
69 * also cleared when reset is asserted to the 1st controller.
70 */
71 rst = of_reset_control_get_shared(phy_np, "utmi-pads");
72 if (IS_ERR(rst)) {
73 dev_warn(&pdev->dev,
74 "can't get utmi-pads reset from the PHY\n");
75 dev_warn(&pdev->dev,
76 "continuing, but please update your DT\n");
77 } else {
78 /*
79 * PHY driver performs UTMI-pads reset in a case of
80 * non-legacy DT.
81 */
82 reset_control_put(rst);
83 }
82 84
83 if (!usb1_reset_attempted) { 85 of_node_put(phy_np);
84 struct reset_control *usb1_reset;
85 86
86 if (!has_utmi_pad_registers) 87 /* reset control is shared, hence initialize it first */
87 usb1_reset = of_reset_control_get(phy_np, "utmi-pads"); 88 err = reset_control_deassert(tegra->rst);
88 else 89 if (err)
89 usb1_reset = tegra->rst; 90 return err;
90
91 if (IS_ERR(usb1_reset)) {
92 dev_warn(&pdev->dev,
93 "can't get utmi-pads reset from the PHY\n");
94 dev_warn(&pdev->dev,
95 "continuing, but please update your DT\n");
96 } else {
97 reset_control_assert(usb1_reset);
98 udelay(1);
99 reset_control_deassert(usb1_reset);
100
101 if (!has_utmi_pad_registers)
102 reset_control_put(usb1_reset);
103 }
104 91
105 usb1_reset_attempted = true; 92 err = reset_control_assert(tegra->rst);
106 } 93 if (err)
94 return err;
107 95
108 if (!has_utmi_pad_registers) { 96 udelay(1);
109 reset_control_assert(tegra->rst);
110 udelay(1);
111 reset_control_deassert(tegra->rst);
112 }
113 97
114 of_node_put(phy_np); 98 err = reset_control_deassert(tegra->rst);
99 if (err)
100 return err;
115 101
116 return 0; 102 return 0;
117} 103}
@@ -440,7 +426,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
440 goto cleanup_hcd_create; 426 goto cleanup_hcd_create;
441 } 427 }
442 428
443 tegra->rst = devm_reset_control_get(&pdev->dev, "usb"); 429 tegra->rst = devm_reset_control_get_shared(&pdev->dev, "usb");
444 if (IS_ERR(tegra->rst)) { 430 if (IS_ERR(tegra->rst)) {
445 dev_err(&pdev->dev, "Can't get ehci reset\n"); 431 dev_err(&pdev->dev, "Can't get ehci reset\n");
446 err = PTR_ERR(tegra->rst); 432 err = PTR_ERR(tegra->rst);
@@ -452,8 +438,10 @@ static int tegra_ehci_probe(struct platform_device *pdev)
452 goto cleanup_hcd_create; 438 goto cleanup_hcd_create;
453 439
454 err = tegra_reset_usb_controller(pdev); 440 err = tegra_reset_usb_controller(pdev);
455 if (err) 441 if (err) {
442 dev_err(&pdev->dev, "Failed to reset controller\n");
456 goto cleanup_clk_en; 443 goto cleanup_clk_en;
444 }
457 445
458 u_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "nvidia,phy", 0); 446 u_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "nvidia,phy", 0);
459 if (IS_ERR(u_phy)) { 447 if (IS_ERR(u_phy)) {
@@ -538,6 +526,9 @@ static int tegra_ehci_remove(struct platform_device *pdev)
538 usb_phy_shutdown(hcd->usb_phy); 526 usb_phy_shutdown(hcd->usb_phy);
539 usb_remove_hcd(hcd); 527 usb_remove_hcd(hcd);
540 528
529 reset_control_assert(tegra->rst);
530 udelay(1);
531
541 clk_disable_unprepare(tegra->clk); 532 clk_disable_unprepare(tegra->clk);
542 533
543 usb_put_hcd(hcd); 534 usb_put_hcd(hcd);
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index e46219e7fa93..ea7ef1dc0b42 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -236,17 +236,83 @@ static void set_phcd(struct tegra_usb_phy *phy, bool enable)
236 236
237static int utmip_pad_open(struct tegra_usb_phy *phy) 237static int utmip_pad_open(struct tegra_usb_phy *phy)
238{ 238{
239 int err; 239 int ret;
240 240
241 phy->pad_clk = devm_clk_get(phy->u_phy.dev, "utmi-pads"); 241 phy->pad_clk = devm_clk_get(phy->u_phy.dev, "utmi-pads");
242 if (IS_ERR(phy->pad_clk)) { 242 if (IS_ERR(phy->pad_clk)) {
243 err = PTR_ERR(phy->pad_clk); 243 ret = PTR_ERR(phy->pad_clk);
244 dev_err(phy->u_phy.dev, 244 dev_err(phy->u_phy.dev,
245 "Failed to get UTMIP pad clock: %d\n", err); 245 "Failed to get UTMIP pad clock: %d\n", ret);
246 return err; 246 return ret;
247 } 247 }
248 248
249 return 0; 249 phy->pad_rst = devm_reset_control_get_optional_shared(
250 phy->u_phy.dev, "utmi-pads");
251 if (IS_ERR(phy->pad_rst)) {
252 ret = PTR_ERR(phy->pad_rst);
253 dev_err(phy->u_phy.dev,
254 "Failed to get UTMI-pads reset: %d\n", ret);
255 return ret;
256 }
257
258 ret = clk_prepare_enable(phy->pad_clk);
259 if (ret) {
260 dev_err(phy->u_phy.dev,
261 "Failed to enable UTMI-pads clock: %d\n", ret);
262 return ret;
263 }
264
265 spin_lock(&utmip_pad_lock);
266
267 ret = reset_control_deassert(phy->pad_rst);
268 if (ret) {
269 dev_err(phy->u_phy.dev,
270 "Failed to initialize UTMI-pads reset: %d\n", ret);
271 goto unlock;
272 }
273
274 ret = reset_control_assert(phy->pad_rst);
275 if (ret) {
276 dev_err(phy->u_phy.dev,
277 "Failed to assert UTMI-pads reset: %d\n", ret);
278 goto unlock;
279 }
280
281 udelay(1);
282
283 ret = reset_control_deassert(phy->pad_rst);
284 if (ret)
285 dev_err(phy->u_phy.dev,
286 "Failed to deassert UTMI-pads reset: %d\n", ret);
287unlock:
288 spin_unlock(&utmip_pad_lock);
289
290 clk_disable_unprepare(phy->pad_clk);
291
292 return ret;
293}
294
295static int utmip_pad_close(struct tegra_usb_phy *phy)
296{
297 int ret;
298
299 ret = clk_prepare_enable(phy->pad_clk);
300 if (ret) {
301 dev_err(phy->u_phy.dev,
302 "Failed to enable UTMI-pads clock: %d\n", ret);
303 return ret;
304 }
305
306 ret = reset_control_assert(phy->pad_rst);
307 if (ret)
308 dev_err(phy->u_phy.dev,
309 "Failed to assert UTMI-pads reset: %d\n", ret);
310
311 udelay(1);
312
313 clk_disable_unprepare(phy->pad_clk);
314
315 return ret;
250} 316}
251 317
252static void utmip_pad_power_on(struct tegra_usb_phy *phy) 318static void utmip_pad_power_on(struct tegra_usb_phy *phy)
@@ -700,6 +766,9 @@ static void tegra_usb_phy_close(struct tegra_usb_phy *phy)
700 if (!IS_ERR(phy->vbus)) 766 if (!IS_ERR(phy->vbus))
701 regulator_disable(phy->vbus); 767 regulator_disable(phy->vbus);
702 768
769 if (!phy->is_ulpi_phy)
770 utmip_pad_close(phy);
771
703 clk_disable_unprepare(phy->pll_u); 772 clk_disable_unprepare(phy->pll_u);
704} 773}
705 774
diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h
index d641ea1660b7..0c5c3ea8b2d7 100644
--- a/include/linux/usb/tegra_usb_phy.h
+++ b/include/linux/usb/tegra_usb_phy.h
@@ -17,6 +17,7 @@
17#define __TEGRA_USB_PHY_H 17#define __TEGRA_USB_PHY_H
18 18
19#include <linux/clk.h> 19#include <linux/clk.h>
20#include <linux/reset.h>
20#include <linux/usb/otg.h> 21#include <linux/usb/otg.h>
21 22
22/* 23/*
@@ -76,6 +77,7 @@ struct tegra_usb_phy {
76 bool is_legacy_phy; 77 bool is_legacy_phy;
77 bool is_ulpi_phy; 78 bool is_ulpi_phy;
78 int reset_gpio; 79 int reset_gpio;
80 struct reset_control *pad_rst;
79}; 81};
80 82
81void tegra_usb_phy_preresume(struct usb_phy *phy); 83void tegra_usb_phy_preresume(struct usb_phy *phy);