softrst.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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-3-08 GuEe-GUI the first version
  9. */
  10. #include "clk-rk.h"
  11. struct rockchip_softrst
  12. {
  13. const int *lut;
  14. void *regs;
  15. int num_per_reg;
  16. rt_uint8_t flags;
  17. struct rt_spinlock lock;
  18. };
  19. static rt_err_t rockchip_softrst_assert(struct rt_reset_control *rstc)
  20. {
  21. int id = rstc->id, bank, offset;
  22. struct rockchip_softrst *softrst = rstc->rstcer->priv;
  23. if (softrst->lut)
  24. {
  25. id = softrst->lut[id];
  26. }
  27. bank = id / softrst->num_per_reg;
  28. offset = id % softrst->num_per_reg;
  29. if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK)
  30. {
  31. HWREG32(softrst->regs + (bank * 4)) = RT_BIT(offset) | (RT_BIT(offset) << 16);
  32. }
  33. else
  34. {
  35. rt_uint32_t reg;
  36. rt_ubase_t level;
  37. level = rt_spin_lock_irqsave(&softrst->lock);
  38. reg = HWREG32(softrst->regs + (bank * 4));
  39. HWREG32(softrst->regs + (bank * 4)) = reg | RT_BIT(offset);
  40. rt_spin_unlock_irqrestore(&softrst->lock, level);
  41. }
  42. return RT_EOK;
  43. }
  44. static rt_err_t rockchip_softrst_deassert(struct rt_reset_control *rstc)
  45. {
  46. int id = rstc->id, bank, offset;
  47. struct rockchip_softrst *softrst = rstc->rstcer->priv;
  48. if (softrst->lut)
  49. {
  50. id = softrst->lut[id];
  51. }
  52. bank = id / softrst->num_per_reg;
  53. offset = id % softrst->num_per_reg;
  54. if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK)
  55. {
  56. HWREG32(softrst->regs + (bank * 4)) = RT_BIT(offset) << 16;
  57. }
  58. else
  59. {
  60. rt_uint32_t reg;
  61. rt_ubase_t level;
  62. level = rt_spin_lock_irqsave(&softrst->lock);
  63. reg = HWREG32(softrst->regs + (bank * 4));
  64. HWREG32(softrst->regs + (bank * 4)) = reg & ~RT_BIT(offset);
  65. rt_spin_unlock_irqrestore(&softrst->lock, level);
  66. }
  67. return RT_EOK;
  68. }
  69. static const struct rt_reset_control_ops rockchip_softrst_ops =
  70. {
  71. .assert = rockchip_softrst_assert,
  72. .deassert = rockchip_softrst_deassert,
  73. };
  74. rt_err_t rockchip_register_softrst(struct rt_reset_controller *rstcer,
  75. struct rt_ofw_node *np, const int *lookup_table, void *regs, rt_uint8_t flags)
  76. {
  77. rt_err_t err;
  78. struct rockchip_softrst *softrst = rt_calloc(1, sizeof(*softrst));
  79. if (!softrst)
  80. {
  81. return -RT_ENOMEM;
  82. }
  83. softrst->lut = lookup_table;
  84. softrst->regs = regs;
  85. softrst->flags = flags;
  86. softrst->num_per_reg = (flags & ROCKCHIP_SOFTRST_HIWORD_MASK) ? 16 : 32;
  87. rt_spin_lock_init(&softrst->lock);
  88. rstcer->priv = softrst;
  89. rstcer->ops = &rockchip_softrst_ops;
  90. rstcer->ofw_node = np;
  91. if ((err = rt_reset_controller_register(rstcer)))
  92. {
  93. rt_free(softrst);
  94. }
  95. return err;
  96. }