145-usb-ohci-plat-support-multiple-reset-ctrllines.patch 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. From 5f0c864c1f207dba1db587747a58ec6b362dadf8 Mon Sep 17 00:00:00 2001
  2. From: Hans de Goede <hdegoede@redhat.com>
  3. Date: Sun, 29 Nov 2015 18:44:14 +0100
  4. Subject: [PATCH] ohci-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: Hans de Goede <hdegoede@redhat.com>
  11. ---
  12. Changes in v2:
  13. -New patch in v2 of this patch-set, to complement the identical patch for
  14. the ehci-platform code
  15. ---
  16. Documentation/devicetree/bindings/usb/usb-ohci.txt | 2 +-
  17. drivers/usb/host/ohci-platform.c | 49 +++++++++++++---------
  18. 2 files changed, 30 insertions(+), 21 deletions(-)
  19. --- a/Documentation/devicetree/bindings/usb/usb-ohci.txt
  20. +++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt
  21. @@ -14,7 +14,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:
  28. --- a/drivers/usb/host/ohci-platform.c
  29. +++ b/drivers/usb/host/ohci-platform.c
  30. @@ -33,11 +33,12 @@
  31. #define DRIVER_DESC "OHCI generic platform driver"
  32. #define OHCI_MAX_CLKS 3
  33. +#define OHCI_MAX_RESETS 2
  34. #define hcd_to_ohci_priv(h) ((struct ohci_platform_priv *)hcd_to_ohci(h)->priv)
  35. struct ohci_platform_priv {
  36. struct clk *clks[OHCI_MAX_CLKS];
  37. - struct reset_control *rst;
  38. + struct reset_control *resets[OHCI_MAX_RESETS];
  39. struct phy **phys;
  40. int num_phys;
  41. };
  42. @@ -117,7 +118,7 @@ static int ohci_platform_probe(struct pl
  43. struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
  44. struct ohci_platform_priv *priv;
  45. struct ohci_hcd *ohci;
  46. - int err, irq, phy_num, clk = 0;
  47. + int err, irq, phy_num, clk = 0, rst = 0;
  48. if (usb_disabled())
  49. return -ENODEV;
  50. @@ -195,19 +196,23 @@ static int ohci_platform_probe(struct pl
  51. break;
  52. }
  53. }
  54. -
  55. - }
  56. -
  57. - priv->rst = devm_reset_control_get_optional(&dev->dev, NULL);
  58. - if (IS_ERR(priv->rst)) {
  59. - err = PTR_ERR(priv->rst);
  60. - if (err == -EPROBE_DEFER)
  61. - goto err_put_clks;
  62. - priv->rst = NULL;
  63. - } else {
  64. - err = reset_control_deassert(priv->rst);
  65. - if (err)
  66. - goto err_put_clks;
  67. + for (rst = 0; rst < OHCI_MAX_RESETS; rst++) {
  68. + priv->resets[rst] =
  69. + of_reset_control_get_by_index(dev->dev.of_node,
  70. + rst);
  71. + if (IS_ERR(priv->resets[rst])) {
  72. + err = PTR_ERR(priv->resets[rst]);
  73. + if (err == -EPROBE_DEFER)
  74. + goto err_reset;
  75. + priv->resets[rst] = NULL;
  76. + break;
  77. + }
  78. + err = reset_control_deassert_shared(priv->resets[rst]);
  79. + if (err) {
  80. + reset_control_put(priv->resets[rst]);
  81. + goto err_reset;
  82. + }
  83. + }
  84. }
  85. if (pdata->big_endian_desc)
  86. @@ -265,8 +270,10 @@ err_power:
  87. if (pdata->power_off)
  88. pdata->power_off(dev);
  89. err_reset:
  90. - if (priv->rst)
  91. - reset_control_assert(priv->rst);
  92. + while (--rst >= 0) {
  93. + reset_control_assert_shared(priv->resets[rst]);
  94. + reset_control_put(priv->resets[rst]);
  95. + }
  96. err_put_clks:
  97. while (--clk >= 0)
  98. clk_put(priv->clks[clk]);
  99. @@ -284,15 +291,17 @@ static int ohci_platform_remove(struct p
  100. struct usb_hcd *hcd = platform_get_drvdata(dev);
  101. struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev);
  102. struct ohci_platform_priv *priv = hcd_to_ohci_priv(hcd);
  103. - int clk;
  104. + int clk, rst;
  105. usb_remove_hcd(hcd);
  106. if (pdata->power_off)
  107. pdata->power_off(dev);
  108. - if (priv->rst)
  109. - reset_control_assert(priv->rst);
  110. + for (rst = 0; rst < OHCI_MAX_RESETS && priv->resets[rst]; rst++) {
  111. + reset_control_assert_shared(priv->resets[rst]);
  112. + reset_control_put(priv->resets[rst]);
  113. + }
  114. for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++)
  115. clk_put(priv->clks[clk]);