hwspinlock-rockchip.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-09-23 GuEe-GUI first version
  9. */
  10. #include "hwspinlock_dm.h"
  11. #define HWSPINLOCK_NUMBER 64
  12. #define HWSPINLOCK_STATUS_OFFSET(x) (0x4 * (x))
  13. #define HWSPINLOCK_OWNER_ID 0x1
  14. struct rockchip_hwspinlock
  15. {
  16. struct rt_hwspinlock_bank parent;
  17. void *regs;
  18. };
  19. static rt_err_t rockchip_hwspinlock_trylock(struct rt_hwspinlock *hwlock)
  20. {
  21. void *lock_regs = hwlock->priv;
  22. HWREG32(lock_regs) = HWSPINLOCK_OWNER_ID;
  23. /*
  24. * Get only first 4bits and compare to HWSPINLOCK_OWNER_ID:
  25. * when 4bits is 0, 4bits can be written with new value.
  26. * when 4bits is not 0, 4bits cannot be written.
  27. * when write data is 0x0000, 4bits clean to 0.
  28. */
  29. return ((HWREG32(lock_regs) & 0xf) == HWSPINLOCK_OWNER_ID);
  30. }
  31. static void rockchip_hwspinlock_unlock(struct rt_hwspinlock *hwlock)
  32. {
  33. void *lock_regs = hwlock->priv;
  34. HWREG32(lock_regs) = 0;
  35. }
  36. static const struct rt_hwspinlock_ops rk_hwspinlock_ops =
  37. {
  38. .trylock = rockchip_hwspinlock_trylock,
  39. .unlock = rockchip_hwspinlock_unlock,
  40. };
  41. static rt_err_t rockchip_hwspinlock_probe(struct rt_platform_device *pdev)
  42. {
  43. rt_err_t err;
  44. struct rt_hwspinlock *hwlock;
  45. struct rt_hwspinlock_bank *bank;
  46. struct rt_device *dev = &pdev->parent;
  47. struct rockchip_hwspinlock *rk_hwspinlock;
  48. rk_hwspinlock = hwspinlock_bank_alloc(rk_hwspinlock, HWSPINLOCK_NUMBER);
  49. if (!rk_hwspinlock)
  50. {
  51. return -RT_ENOMEM;
  52. }
  53. rk_hwspinlock->regs = rt_dm_dev_iomap(dev, 0);
  54. if (!rk_hwspinlock->regs)
  55. {
  56. err = -RT_EIO;
  57. goto _fail;
  58. }
  59. bank = &rk_hwspinlock->parent;
  60. hwlock = &bank->locks[0];
  61. for (int i = 0; i < HWSPINLOCK_NUMBER; ++i, ++hwlock)
  62. {
  63. hwlock->priv = rk_hwspinlock->regs + HWSPINLOCK_STATUS_OFFSET(i);
  64. }
  65. bank->dev = dev;
  66. bank->ops = &rk_hwspinlock_ops;
  67. bank->locks_nr = HWSPINLOCK_NUMBER;
  68. if ((err = rt_hwspinlock_bank_register(bank)))
  69. {
  70. goto _fail;
  71. }
  72. dev->user_data = rk_hwspinlock;
  73. return RT_EOK;
  74. _fail:
  75. if (rk_hwspinlock->regs)
  76. {
  77. rt_iounmap(rk_hwspinlock->regs);
  78. }
  79. rt_free(rk_hwspinlock);
  80. return err;
  81. }
  82. static rt_err_t rockchip_hwspinlock_remove(struct rt_platform_device *pdev)
  83. {
  84. struct rockchip_hwspinlock *rk_hwspinlock = pdev->parent.user_data;
  85. rt_hwspinlock_bank_unregister(&rk_hwspinlock->parent);
  86. rt_iounmap(rk_hwspinlock->regs);
  87. rt_free(rk_hwspinlock);
  88. return RT_EOK;
  89. }
  90. static const struct rt_ofw_node_id rockchip_hwspinlock_ofw_ids[] =
  91. {
  92. { .compatible = "rockchip,hwspinlock" },
  93. { /* sentinel */ }
  94. };
  95. static struct rt_platform_driver rockchip_hwspinlock_driver =
  96. {
  97. .name = "hwspinlock-rockchip",
  98. .ids = rockchip_hwspinlock_ofw_ids,
  99. .probe = rockchip_hwspinlock_probe,
  100. .remove = rockchip_hwspinlock_remove,
  101. };
  102. RT_PLATFORM_DRIVER_EXPORT(rockchip_hwspinlock_driver);