reset-ti-sci.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  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. /**
  55. * ti_sci_reset_set() - program a device's reset
  56. * @rst: Handle to a single reset signal
  57. * @assert: boolean flag to indicate assert or deassert
  58. *
  59. * This is a common internal function used to assert or deassert a device's
  60. * reset using the TI SCI protocol. The device's reset is asserted if the
  61. * @assert argument is true, or deasserted if @assert argument is false.
  62. * The mechanism itself is a read-modify-write procedure, the current device
  63. * reset register is read using a TI SCI device operation, the new value is
  64. * set or un-set using the reset's mask, and the new reset value written by
  65. * using another TI SCI device operation.
  66. *
  67. * Return: 0 for successful request, else a corresponding error value
  68. */
  69. static int ti_sci_reset_set(struct reset_ctl *rst, bool assert)
  70. {
  71. struct ti_sci_reset_data *data = dev_get_priv(rst->dev);
  72. const struct ti_sci_handle *sci = data->sci;
  73. const struct ti_sci_dev_ops *dops = &sci->ops.dev_ops;
  74. u32 reset_state;
  75. int ret;
  76. ret = dops->get_device_resets(sci, rst->id, &reset_state);
  77. if (ret) {
  78. dev_err(rst->dev, "%s: get_device_resets failed (%d)\n",
  79. __func__, ret);
  80. return ret;
  81. }
  82. if (assert)
  83. reset_state |= rst->data;
  84. else
  85. reset_state &= ~rst->data;
  86. ret = dops->set_device_resets(sci, rst->id, reset_state);
  87. if (ret) {
  88. dev_err(rst->dev, "%s: set_device_resets failed (%d)\n",
  89. __func__, ret);
  90. return ret;
  91. }
  92. return 0;
  93. }
  94. /**
  95. * ti_sci_reset_assert() - assert device reset
  96. * @rst: Handle to a single reset signal
  97. *
  98. * This function implements the reset driver op to assert a device's reset
  99. * using the TI SCI protocol. This invokes the function ti_sci_reset_set()
  100. * with the corresponding parameters as passed in, but with the @assert
  101. * argument set to true for asserting the reset.
  102. *
  103. * Return: 0 for successful request, else a corresponding error value
  104. */
  105. static int ti_sci_reset_assert(struct reset_ctl *rst)
  106. {
  107. debug("%s(rst=%p)\n", __func__, rst);
  108. return ti_sci_reset_set(rst, true);
  109. }
  110. /**
  111. * ti_sci_reset_deassert() - deassert device reset
  112. * @rst: Handle to a single reset signal
  113. *
  114. * This function implements the reset driver op to deassert a device's reset
  115. * using the TI SCI protocol. This invokes the function ti_sci_reset_set()
  116. * with the corresponding parameters as passed in, but with the @assert
  117. * argument set to false for deasserting the reset.
  118. *
  119. * Return: 0 for successful request, else a corresponding error value
  120. */
  121. static int ti_sci_reset_deassert(struct reset_ctl *rst)
  122. {
  123. debug("%s(rst=%p)\n", __func__, rst);
  124. return ti_sci_reset_set(rst, false);
  125. }
  126. /**
  127. * ti_sci_reset_status() - check device reset status
  128. * @rst: Handle to a single reset signal
  129. *
  130. * This function implements the reset driver op to return the status of a
  131. * device's reset using the TI SCI protocol. The reset register value is read
  132. * by invoking the TI SCI device operation .get_device_resets(), and the
  133. * status of the specific reset is extracted and returned using this reset's
  134. * reset mask.
  135. *
  136. * Return: 0 if reset is deasserted, or a non-zero value if reset is asserted
  137. */
  138. static int ti_sci_reset_status(struct reset_ctl *rst)
  139. {
  140. struct ti_sci_reset_data *data = dev_get_priv(rst->dev);
  141. const struct ti_sci_handle *sci = data->sci;
  142. const struct ti_sci_dev_ops *dops = &sci->ops.dev_ops;
  143. u32 reset_state;
  144. int ret;
  145. debug("%s(rst=%p)\n", __func__, rst);
  146. ret = dops->get_device_resets(sci, rst->id, &reset_state);
  147. if (ret) {
  148. dev_err(rst->dev, "%s: get_device_resets failed (%d)\n",
  149. __func__, ret);
  150. return ret;
  151. }
  152. return reset_state & rst->data;
  153. }
  154. static const struct udevice_id ti_sci_reset_of_match[] = {
  155. { .compatible = "ti,sci-reset", },
  156. { /* sentinel */ },
  157. };
  158. static struct reset_ops ti_sci_reset_ops = {
  159. .of_xlate = ti_sci_reset_of_xlate,
  160. .rst_assert = ti_sci_reset_assert,
  161. .rst_deassert = ti_sci_reset_deassert,
  162. .rst_status = ti_sci_reset_status,
  163. };
  164. U_BOOT_DRIVER(ti_sci_reset) = {
  165. .name = "ti-sci-reset",
  166. .id = UCLASS_RESET,
  167. .of_match = ti_sci_reset_of_match,
  168. .probe = ti_sci_reset_probe,
  169. .priv_auto = sizeof(struct ti_sci_reset_data),
  170. .ops = &ti_sci_reset_ops,
  171. };