1
0

144-usb-ehci-plat-support-multiple-reset-ctrllines.patch 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. From 957e8f96c67052ca843ea9ffc5223662b973e5de Mon Sep 17 00:00:00 2001
  2. From: Reinder de Haan <patchesrdh@mveas.com>
  3. Date: Sun, 15 Nov 2015 14:24:46 +0100
  4. Subject: [PATCH] ehci-platform: Add support for controllers with multiple
  5. reset lines
  6. At least the EHCI/OHCI found on the Allwinnner H3 SoC needs multiple
  7. reset lines, the controller will not initialize while the reset for
  8. its companion is still asserted, which means we need to de-assert
  9. 2 resets for the controller to work.
  10. Signed-off-by: Reinder de Haan <patchesrdh@mveas.com>
  11. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  12. ---
  13. Changes in v2:
  14. -Use the new reset_control_[de]assert_shared reset-controller functions
  15. ---
  16. Documentation/devicetree/bindings/usb/usb-ehci.txt | 2 +-
  17. drivers/usb/host/ehci-platform.c | 47 +++++++++++++---------
  18. 2 files changed, 30 insertions(+), 19 deletions(-)
  19. --- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
  20. +++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
  21. @@ -18,7 +18,7 @@ Optional properties:
  22. - clocks : a list of phandle + clock specifier pairs
  23. - phys : phandle + phy specifier pair
  24. - phy-names : "usb"
  25. - - resets : phandle + reset specifier pair
  26. + - resets : a list of phandle + reset specifier pairs
  27. Example (Sequoia 440EPx):
  28. ehci@e0000300 {
  29. --- a/drivers/usb/host/ehci-platform.c
  30. +++ b/drivers/usb/host/ehci-platform.c
  31. @@ -39,11 +39,12 @@
  32. #define DRIVER_DESC "EHCI generic platform driver"
  33. #define EHCI_MAX_CLKS 3
  34. +#define EHCI_MAX_RESETS 2
  35. #define hcd_to_ehci_priv(h) ((struct ehci_platform_priv *)hcd_to_ehci(h)->priv)
  36. struct ehci_platform_priv {
  37. struct clk *clks[EHCI_MAX_CLKS];
  38. - struct reset_control *rst;
  39. + struct reset_control *resets[EHCI_MAX_RESETS];
  40. struct phy **phys;
  41. int num_phys;
  42. bool reset_on_resume;
  43. @@ -149,7 +150,7 @@ static int ehci_platform_probe(struct pl
  44. struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
  45. struct ehci_platform_priv *priv;
  46. struct ehci_hcd *ehci;
  47. - int err, irq, phy_num, clk = 0;
  48. + int err, irq, phy_num, clk = 0, rst = 0;
  49. if (usb_disabled())
  50. return -ENODEV;
  51. @@ -232,18 +233,24 @@ static int ehci_platform_probe(struct pl
  52. break;
  53. }
  54. }
  55. - }
  56. - priv->rst = devm_reset_control_get_optional(&dev->dev, NULL);
  57. - if (IS_ERR(priv->rst)) {
  58. - err = PTR_ERR(priv->rst);
  59. - if (err == -EPROBE_DEFER)
  60. - goto err_put_clks;
  61. - priv->rst = NULL;
  62. - } else {
  63. - err = reset_control_deassert(priv->rst);
  64. - if (err)
  65. - goto err_put_clks;
  66. + for (rst = 0; rst < EHCI_MAX_RESETS; rst++) {
  67. + priv->resets[rst] =
  68. + of_reset_control_get_by_index(dev->dev.of_node,
  69. + rst);
  70. + if (IS_ERR(priv->resets[rst])) {
  71. + err = PTR_ERR(priv->resets[rst]);
  72. + if (err == -EPROBE_DEFER)
  73. + goto err_reset;
  74. + priv->resets[rst] = NULL;
  75. + break;
  76. + }
  77. + err = reset_control_deassert_shared(priv->resets[rst]);
  78. + if (err) {
  79. + reset_control_put(priv->resets[rst]);
  80. + goto err_reset;
  81. + }
  82. + }
  83. }
  84. if (pdata->big_endian_desc)
  85. @@ -302,8 +309,10 @@ err_power:
  86. if (pdata->power_off)
  87. pdata->power_off(dev);
  88. err_reset:
  89. - if (priv->rst)
  90. - reset_control_assert(priv->rst);
  91. + while (--rst >= 0) {
  92. + reset_control_assert_shared(priv->resets[rst]);
  93. + reset_control_put(priv->resets[rst]);
  94. + }
  95. err_put_clks:
  96. while (--clk >= 0)
  97. clk_put(priv->clks[clk]);
  98. @@ -321,15 +330,17 @@ static int ehci_platform_remove(struct p
  99. struct usb_hcd *hcd = platform_get_drvdata(dev);
  100. struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev);
  101. struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
  102. - int clk;
  103. + int clk, rst;
  104. usb_remove_hcd(hcd);
  105. if (pdata->power_off)
  106. pdata->power_off(dev);
  107. - if (priv->rst)
  108. - reset_control_assert(priv->rst);
  109. + for (rst = 0; rst < EHCI_MAX_RESETS && priv->resets[rst]; rst++) {
  110. + reset_control_assert_shared(priv->resets[rst]);
  111. + reset_control_put(priv->resets[rst]);
  112. + }
  113. for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++)
  114. clk_put(priv->clks[clk]);