reset-ti-sci.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Texas Instruments System Control Interface (TI SCI) reset driver
  4. *
  5. * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
  6. * Andreas Dannenberg <dannenberg@ti.com>
  7. *
  8. * Loosely based on Linux kernel reset-ti-sci.c...
  9. */
  10. #include <common.h>
  11. #include <dm.h>
  12. #include <errno.h>
  13. #include <log.h>
  14. #include <malloc.h>
  15. #include <reset-uclass.h>
  16. #include <dm/device_compat.h>
  17. #include <linux/err.h>
  18. #include <linux/soc/ti/ti_sci_protocol.h>
  19. /**
  20. * struct ti_sci_reset_data - reset controller information structure
  21. * @sci: TI SCI handle used for communication with system controller
  22. */
  23. struct ti_sci_reset_data {
  24. const struct ti_sci_handle *sci;
  25. };
  26. static int ti_sci_reset_probe(struct udevice *dev)
  27. {
  28. struct ti_sci_reset_data *data = dev_get_priv(dev);
  29. debug("%s(dev=%p)\n", __func__, dev);
  30. if (!data)
  31. return -ENOMEM;
  32. /* Store handle for communication with the system controller */
  33. data->sci = ti_sci_get_handle(dev);
  34. if (IS_ERR(data->sci))
  35. return PTR_ERR(data->sci);
  36. return 0;
  37. }
  38. static int ti_sci_reset_of_xlate(struct reset_ctl *rst,
  39. struct ofnode_phandle_args *args)
  40. {
  41. debug("%s(rst=%p, args_count=%d)\n", __func__, rst, args->args_count);
  42. if (args->args_count != 2) {
  43. debug("Invalid args_count: %d\n", args->args_count);
  44. return -EINVAL;
  45. }
  46. /*
  47. * On TI SCI-based devices, the reset provider id field is used as a
  48. * device ID, and the data field is used as the associated reset mask.
  49. */
  50. rst->id = args->args[0];
  51. rst->data = args->args[1];
  52. return 0;
  53. }
  54. static int ti_sci_reset_request(struct reset_ctl *rst)
  55. {
  56. debug("%s(rst=%p)\n", __func__, rst);
  57. return 0;
  58. }
  59. static int ti_sci_reset_free(struct reset_ctl *rst)
  60. {
  61. debug("%s(rst=%p)\n", __func__, rst);
  62. return 0;
  63. }
  64. /**
  65. * ti_sci_reset_set() - program a device's reset
  66. * @rst: Handle to a single reset signal
  67. * @assert: boolean flag to indicate assert or deassert
  68. *
  69. * This is a common internal function used to assert or deassert a device's
  70. * reset using the TI SCI protocol. The device's reset is asserted if the
  71. * @assert argument is true, or deasserted if @assert argument is false.
  72. * The mechanism itself is a read-modify-write procedure, the current device
  73. * reset register is read using a TI SCI device operation, the new value is
  74. * set or un-set using the reset's mask, and the new reset value written by
  75. * using another TI SCI device operation.
  76. *
  77. * Return: 0 for successful request, else a corresponding error value
  78. */
  79. static int ti_sci_reset_set(struct reset_ctl *rst, bool assert)
  80. {
  81. struct ti_sci_reset_data *data = dev_get_priv(rst->dev);
  82. const struct ti_sci_handle *sci = data->sci;
  83. const struct ti_sci_dev_ops *dops = &sci->ops.dev_ops;
  84. u32 reset_state;
  85. int ret;
  86. ret = dops->get_device_resets(sci, rst->id, &reset_state);
  87. if (ret) {
  88. dev_err(rst->dev, "%s: get_device_resets failed (%d)\n",
  89. __func__, ret);
  90. return ret;
  91. }
  92. if (assert)
  93. reset_state |= rst->data;
  94. else
  95. reset_state &= ~rst->data;
  96. ret = dops->set_device_resets(sci, rst->id, reset_state);
  97. if (ret) {
  98. dev_err(rst->dev, "%s: set_device_resets failed (%d)\n",
  99. __func__, ret);
  100. return ret;
  101. }
  102. return 0;
  103. }
  104. /**
  105. * ti_sci_reset_assert() - assert device reset
  106. * @rst: Handle to a single reset signal
  107. *
  108. * This function implements the reset driver op to assert a device's reset
  109. * using the TI SCI protocol. This invokes the function ti_sci_reset_set()
  110. * with the corresponding parameters as passed in, but with the @assert
  111. * argument set to true for asserting the reset.
  112. *
  113. * Return: 0 for successful request, else a corresponding error value
  114. */
  115. static int ti_sci_reset_assert(struct reset_ctl *rst)
  116. {
  117. debug("%s(rst=%p)\n", __func__, rst);
  118. return ti_sci_reset_set(rst, true);
  119. }
  120. /**
  121. * ti_sci_reset_deassert() - deassert device reset
  122. * @rst: Handle to a single reset signal
  123. *
  124. * This function implements the reset driver op to deassert a device's reset
  125. * using the TI SCI protocol. This invokes the function ti_sci_reset_set()
  126. * with the corresponding parameters as passed in, but with the @assert
  127. * argument set to false for deasserting the reset.
  128. *
  129. * Return: 0 for successful request, else a corresponding error value
  130. */
  131. static int ti_sci_reset_deassert(struct reset_ctl *rst)
  132. {
  133. debug("%s(rst=%p)\n", __func__, rst);
  134. return ti_sci_reset_set(rst, false);
  135. }
  136. /**
  137. * ti_sci_reset_status() - check device reset status
  138. * @rst: Handle to a single reset signal
  139. *
  140. * This function implements the reset driver op to return the status of a
  141. * device's reset using the TI SCI protocol. The reset register value is read
  142. * by invoking the TI SCI device operation .get_device_resets(), and the
  143. * status of the specific reset is extracted and returned using this reset's
  144. * reset mask.
  145. *
  146. * Return: 0 if reset is deasserted, or a non-zero value if reset is asserted
  147. */
  148. static int ti_sci_reset_status(struct reset_ctl *rst)
  149. {
  150. struct ti_sci_reset_data *data = dev_get_priv(rst->dev);
  151. const struct ti_sci_handle *sci = data->sci;
  152. const struct ti_sci_dev_ops *dops = &sci->ops.dev_ops;
  153. u32 reset_state;
  154. int ret;
  155. debug("%s(rst=%p)\n", __func__, rst);
  156. ret = dops->get_device_resets(sci, rst->id, &reset_state);
  157. if (ret) {
  158. dev_err(rst->dev, "%s: get_device_resets failed (%d)\n",
  159. __func__, ret);
  160. return ret;
  161. }
  162. return reset_state & rst->data;
  163. }
  164. static const struct udevice_id ti_sci_reset_of_match[] = {
  165. { .compatible = "ti,sci-reset", },
  166. { /* sentinel */ },
  167. };
  168. static struct reset_ops ti_sci_reset_ops = {
  169. .of_xlate = ti_sci_reset_of_xlate,
  170. .request = ti_sci_reset_request,
  171. .rfree = ti_sci_reset_free,
  172. .rst_assert = ti_sci_reset_assert,
  173. .rst_deassert = ti_sci_reset_deassert,
  174. .rst_status = ti_sci_reset_status,
  175. };
  176. U_BOOT_DRIVER(ti_sci_reset) = {
  177. .name = "ti-sci-reset",
  178. .id = UCLASS_RESET,
  179. .of_match = ti_sci_reset_of_match,
  180. .probe = ti_sci_reset_probe,
  181. .priv_auto_alloc_size = sizeof(struct ti_sci_reset_data),
  182. .ops = &ti_sci_reset_ops,
  183. };