850-v6.8-bus-mhi-host-Add-a-separate-timeout-parameter-for-wa.patch 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. From 6ab3d50b106c9aea123a80551a6c9deace83b914 Mon Sep 17 00:00:00 2001
  2. From: Qiang Yu <[email protected]>
  3. Date: Tue, 7 Nov 2023 16:14:49 +0800
  4. Subject: [PATCH] bus: mhi: host: Add a separate timeout parameter for waiting
  5. ready
  6. Some devices(eg. SDX75) take longer than expected (default, 8 seconds) to
  7. set ready after reboot. Hence add optional ready timeout parameter and pass
  8. the appropriate timeout value to mhi_poll_reg_field() to wait enough for
  9. device ready as part of power up sequence.
  10. Signed-off-by: Qiang Yu <[email protected]>
  11. Reviewed-by: Manivannan Sadhasivam <[email protected]>
  12. Link: https://lore.kernel.org/r/[email protected]
  13. Signed-off-by: Manivannan Sadhasivam <[email protected]>
  14. ---
  15. drivers/bus/mhi/host/init.c | 1 +
  16. drivers/bus/mhi/host/internal.h | 2 +-
  17. drivers/bus/mhi/host/main.c | 5 +++--
  18. drivers/bus/mhi/host/pm.c | 24 +++++++++++++++++-------
  19. include/linux/mhi.h | 4 ++++
  20. 5 files changed, 26 insertions(+), 10 deletions(-)
  21. --- a/drivers/bus/mhi/host/init.c
  22. +++ b/drivers/bus/mhi/host/init.c
  23. @@ -881,6 +881,7 @@ static int parse_config(struct mhi_contr
  24. if (!mhi_cntrl->timeout_ms)
  25. mhi_cntrl->timeout_ms = MHI_TIMEOUT_MS;
  26. + mhi_cntrl->ready_timeout_ms = config->ready_timeout_ms;
  27. mhi_cntrl->bounce_buf = config->use_bounce_buf;
  28. mhi_cntrl->buffer_len = config->buf_len;
  29. if (!mhi_cntrl->buffer_len)
  30. --- a/drivers/bus/mhi/host/internal.h
  31. +++ b/drivers/bus/mhi/host/internal.h
  32. @@ -321,7 +321,7 @@ int __must_check mhi_read_reg_field(stru
  33. u32 *out);
  34. int __must_check mhi_poll_reg_field(struct mhi_controller *mhi_cntrl,
  35. void __iomem *base, u32 offset, u32 mask,
  36. - u32 val, u32 delayus);
  37. + u32 val, u32 delayus, u32 timeout_ms);
  38. void mhi_write_reg(struct mhi_controller *mhi_cntrl, void __iomem *base,
  39. u32 offset, u32 val);
  40. int __must_check mhi_write_reg_field(struct mhi_controller *mhi_cntrl,
  41. --- a/drivers/bus/mhi/host/main.c
  42. +++ b/drivers/bus/mhi/host/main.c
  43. @@ -40,10 +40,11 @@ int __must_check mhi_read_reg_field(stru
  44. int __must_check mhi_poll_reg_field(struct mhi_controller *mhi_cntrl,
  45. void __iomem *base, u32 offset,
  46. - u32 mask, u32 val, u32 delayus)
  47. + u32 mask, u32 val, u32 delayus,
  48. + u32 timeout_ms)
  49. {
  50. int ret;
  51. - u32 out, retry = (mhi_cntrl->timeout_ms * 1000) / delayus;
  52. + u32 out, retry = (timeout_ms * 1000) / delayus;
  53. while (retry--) {
  54. ret = mhi_read_reg_field(mhi_cntrl, base, offset, mask, &out);
  55. --- a/drivers/bus/mhi/host/pm.c
  56. +++ b/drivers/bus/mhi/host/pm.c
  57. @@ -163,6 +163,7 @@ int mhi_ready_state_transition(struct mh
  58. enum mhi_pm_state cur_state;
  59. struct device *dev = &mhi_cntrl->mhi_dev->dev;
  60. u32 interval_us = 25000; /* poll register field every 25 milliseconds */
  61. + u32 timeout_ms;
  62. int ret, i;
  63. /* Check if device entered error state */
  64. @@ -173,14 +174,18 @@ int mhi_ready_state_transition(struct mh
  65. /* Wait for RESET to be cleared and READY bit to be set by the device */
  66. ret = mhi_poll_reg_field(mhi_cntrl, mhi_cntrl->regs, MHICTRL,
  67. - MHICTRL_RESET_MASK, 0, interval_us);
  68. + MHICTRL_RESET_MASK, 0, interval_us,
  69. + mhi_cntrl->timeout_ms);
  70. if (ret) {
  71. dev_err(dev, "Device failed to clear MHI Reset\n");
  72. return ret;
  73. }
  74. + timeout_ms = mhi_cntrl->ready_timeout_ms ?
  75. + mhi_cntrl->ready_timeout_ms : mhi_cntrl->timeout_ms;
  76. ret = mhi_poll_reg_field(mhi_cntrl, mhi_cntrl->regs, MHISTATUS,
  77. - MHISTATUS_READY_MASK, 1, interval_us);
  78. + MHISTATUS_READY_MASK, 1, interval_us,
  79. + timeout_ms);
  80. if (ret) {
  81. dev_err(dev, "Device failed to enter MHI Ready\n");
  82. return ret;
  83. @@ -479,7 +484,7 @@ static void mhi_pm_disable_transition(st
  84. /* Wait for the reset bit to be cleared by the device */
  85. ret = mhi_poll_reg_field(mhi_cntrl, mhi_cntrl->regs, MHICTRL,
  86. - MHICTRL_RESET_MASK, 0, 25000);
  87. + MHICTRL_RESET_MASK, 0, 25000, mhi_cntrl->timeout_ms);
  88. if (ret)
  89. dev_err(dev, "Device failed to clear MHI Reset\n");
  90. @@ -492,8 +497,8 @@ static void mhi_pm_disable_transition(st
  91. if (!MHI_IN_PBL(mhi_get_exec_env(mhi_cntrl))) {
  92. /* wait for ready to be set */
  93. ret = mhi_poll_reg_field(mhi_cntrl, mhi_cntrl->regs,
  94. - MHISTATUS,
  95. - MHISTATUS_READY_MASK, 1, 25000);
  96. + MHISTATUS, MHISTATUS_READY_MASK,
  97. + 1, 25000, mhi_cntrl->timeout_ms);
  98. if (ret)
  99. dev_err(dev, "Device failed to enter READY state\n");
  100. }
  101. @@ -1111,7 +1116,8 @@ int mhi_async_power_up(struct mhi_contro
  102. if (state == MHI_STATE_SYS_ERR) {
  103. mhi_set_mhi_state(mhi_cntrl, MHI_STATE_RESET);
  104. ret = mhi_poll_reg_field(mhi_cntrl, mhi_cntrl->regs, MHICTRL,
  105. - MHICTRL_RESET_MASK, 0, interval_us);
  106. + MHICTRL_RESET_MASK, 0, interval_us,
  107. + mhi_cntrl->timeout_ms);
  108. if (ret) {
  109. dev_info(dev, "Failed to reset MHI due to syserr state\n");
  110. goto error_exit;
  111. @@ -1202,14 +1208,18 @@ EXPORT_SYMBOL_GPL(mhi_power_down);
  112. int mhi_sync_power_up(struct mhi_controller *mhi_cntrl)
  113. {
  114. int ret = mhi_async_power_up(mhi_cntrl);
  115. + u32 timeout_ms;
  116. if (ret)
  117. return ret;
  118. + /* Some devices need more time to set ready during power up */
  119. + timeout_ms = mhi_cntrl->ready_timeout_ms ?
  120. + mhi_cntrl->ready_timeout_ms : mhi_cntrl->timeout_ms;
  121. wait_event_timeout(mhi_cntrl->state_event,
  122. MHI_IN_MISSION_MODE(mhi_cntrl->ee) ||
  123. MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state),
  124. - msecs_to_jiffies(mhi_cntrl->timeout_ms));
  125. + msecs_to_jiffies(timeout_ms));
  126. ret = (MHI_IN_MISSION_MODE(mhi_cntrl->ee)) ? 0 : -ETIMEDOUT;
  127. if (ret)
  128. --- a/include/linux/mhi.h
  129. +++ b/include/linux/mhi.h
  130. @@ -266,6 +266,7 @@ struct mhi_event_config {
  131. * struct mhi_controller_config - Root MHI controller configuration
  132. * @max_channels: Maximum number of channels supported
  133. * @timeout_ms: Timeout value for operations. 0 means use default
  134. + * @ready_timeout_ms: Timeout value for waiting device to be ready (optional)
  135. * @buf_len: Size of automatically allocated buffers. 0 means use default
  136. * @num_channels: Number of channels defined in @ch_cfg
  137. * @ch_cfg: Array of defined channels
  138. @@ -277,6 +278,7 @@ struct mhi_event_config {
  139. struct mhi_controller_config {
  140. u32 max_channels;
  141. u32 timeout_ms;
  142. + u32 ready_timeout_ms;
  143. u32 buf_len;
  144. u32 num_channels;
  145. const struct mhi_channel_config *ch_cfg;
  146. @@ -330,6 +332,7 @@ struct mhi_controller_config {
  147. * @pm_mutex: Mutex for suspend/resume operation
  148. * @pm_lock: Lock for protecting MHI power management state
  149. * @timeout_ms: Timeout in ms for state transitions
  150. + * @ready_timeout_ms: Timeout in ms for waiting device to be ready (optional)
  151. * @pm_state: MHI power management state
  152. * @db_access: DB access states
  153. * @ee: MHI device execution environment
  154. @@ -419,6 +422,7 @@ struct mhi_controller {
  155. struct mutex pm_mutex;
  156. rwlock_t pm_lock;
  157. u32 timeout_ms;
  158. + u32 ready_timeout_ms;
  159. u32 pm_state;
  160. u32 db_access;
  161. enum mhi_ee_type ee;