reset-simple.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-11-26 GuEe-GUI first version
  9. */
  10. #include "reset-simple.h"
  11. struct reset_simple_data
  12. {
  13. rt_uint32_t reg_offset;
  14. rt_bool_t active_low;
  15. rt_bool_t status_active_low;
  16. };
  17. #define raw_to_reset_simple(raw) rt_container_of(raw, struct reset_simple, parent)
  18. static rt_err_t reset_simple_update(struct reset_simple *rsts, int id, rt_bool_t assert)
  19. {
  20. rt_uint32_t reg;
  21. rt_ubase_t level;
  22. int reg_width = sizeof(rt_uint32_t);
  23. int bank = id / (reg_width * 8);
  24. int offset = id % (reg_width * 8);
  25. level = rt_spin_lock_irqsave(&rsts->lock);
  26. reg = HWREG32(rsts->mmio_base + (bank * reg_width));
  27. if (assert ^ rsts->active_low)
  28. {
  29. reg |= RT_BIT(offset);
  30. }
  31. else
  32. {
  33. reg &= ~RT_BIT(offset);
  34. }
  35. HWREG32(rsts->mmio_base + (bank * reg_width)) = reg;
  36. rt_spin_unlock_irqrestore(&rsts->lock, level);
  37. return RT_EOK;
  38. }
  39. static rt_err_t reset_simple_assert(struct rt_reset_control *rstc)
  40. {
  41. struct reset_simple *rsts = raw_to_reset_simple(rstc);
  42. return reset_simple_update(rsts, rstc->id, RT_TRUE);
  43. }
  44. static rt_err_t reset_simple_deassert(struct rt_reset_control *rstc)
  45. {
  46. struct reset_simple *rsts = raw_to_reset_simple(rstc);
  47. return reset_simple_update(rsts, rstc->id, RT_FALSE);
  48. }
  49. static rt_err_t reset_simple_reset(struct rt_reset_control *rstc)
  50. {
  51. rt_err_t err;
  52. struct reset_simple *rsts = raw_to_reset_simple(rstc);
  53. if (!rsts->reset_us)
  54. {
  55. return -RT_ENOSYS;
  56. }
  57. if ((err = reset_simple_assert(rstc)))
  58. {
  59. return err;
  60. }
  61. rt_hw_us_delay(rsts->reset_us + (rsts->reset_us >> 1));
  62. return reset_simple_deassert(rstc);
  63. }
  64. static int reset_simple_status(struct rt_reset_control *rstc)
  65. {
  66. rt_uint32_t value;
  67. int reg_width = sizeof(rt_uint32_t);
  68. int bank = rstc->id / (reg_width * 8);
  69. int offset = rstc->id % (reg_width * 8);
  70. struct reset_simple *rsts = raw_to_reset_simple(rstc);
  71. value = HWREG32(rsts->mmio_base + (bank * reg_width));
  72. return !(value & RT_BIT(offset)) ^ !rsts->status_active_low;
  73. }
  74. const struct rt_reset_control_ops reset_simple_ops =
  75. {
  76. .reset = reset_simple_reset,
  77. .assert = reset_simple_assert,
  78. .deassert = reset_simple_deassert,
  79. .status = reset_simple_status,
  80. };
  81. static rt_err_t reset_simple_probe(struct rt_platform_device *pdev)
  82. {
  83. rt_err_t err;
  84. struct rt_reset_controller *rstcer;
  85. struct rt_device *dev = &pdev->parent;
  86. const struct reset_simple_data *rsts_data = pdev->id->data;
  87. struct reset_simple *rsts = rt_calloc(1, sizeof(*rsts));
  88. if (!rsts)
  89. {
  90. return -RT_ENOMEM;
  91. }
  92. rsts->mmio_base = rt_dm_dev_iomap(dev, 0);
  93. if (!rsts->mmio_base)
  94. {
  95. err = -RT_EIO;
  96. goto _fail;
  97. }
  98. rt_spin_lock_init(&rsts->lock);
  99. rstcer = &rsts->parent;
  100. rstcer->priv = rsts;
  101. rstcer->ofw_node = dev->ofw_node;
  102. rstcer->ops = &reset_simple_ops;
  103. if ((err = rt_reset_controller_register(rstcer)))
  104. {
  105. goto _fail;
  106. }
  107. if (rsts_data)
  108. {
  109. rsts->mmio_base += rsts_data->reg_offset;
  110. rsts->active_low = rsts_data->active_low;
  111. rsts->status_active_low = rsts_data->status_active_low;
  112. }
  113. return RT_EOK;
  114. _fail:
  115. if (rsts->mmio_base)
  116. {
  117. rt_iounmap(rsts->mmio_base);
  118. }
  119. rt_free(rsts);
  120. return err;
  121. }
  122. static const struct reset_simple_data reset_simple_socfpga =
  123. {
  124. .reg_offset = 0x20,
  125. .status_active_low = RT_TRUE,
  126. };
  127. static const struct reset_simple_data reset_simple_active_low =
  128. {
  129. .active_low = RT_TRUE,
  130. .status_active_low = RT_TRUE,
  131. };
  132. static const struct rt_ofw_node_id reset_simple_ofw_ids[] =
  133. {
  134. { .compatible = "altr,stratix10-rst-mgr", .data = &reset_simple_socfpga },
  135. { .compatible = "st,stm32-rcc", },
  136. { .compatible = "allwinner,sun6i-a31-clock-reset", .data = &reset_simple_active_low },
  137. { .compatible = "zte,zx296718-reset", .data = &reset_simple_active_low },
  138. { .compatible = "aspeed,ast2400-lpc-reset" },
  139. { .compatible = "aspeed,ast2500-lpc-reset" },
  140. { .compatible = "aspeed,ast2600-lpc-reset" },
  141. { .compatible = "bitmain,bm1880-reset", .data = &reset_simple_active_low },
  142. { .compatible = "brcm,bcm4908-misc-pcie-reset", .data = &reset_simple_active_low },
  143. { .compatible = "snps,dw-high-reset" },
  144. { .compatible = "snps,dw-low-reset", .data = &reset_simple_active_low },
  145. { .compatible = "sophgo,sg2042-reset", .data = &reset_simple_active_low },
  146. { /* sentinel */ }
  147. };
  148. static struct rt_platform_driver reset_simple_driver =
  149. {
  150. .name = "reset-simple",
  151. .ids = reset_simple_ofw_ids,
  152. .probe = reset_simple_probe,
  153. };
  154. static int reset_simple_register(void)
  155. {
  156. rt_platform_driver_register(&reset_simple_driver);
  157. return 0;
  158. }
  159. INIT_SUBSYS_EXPORT(reset_simple_register);