reset-ti-sci.c 5.7 KB

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