reset-stm32.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) STMicroelectronics 2022 - All Rights Reserved
  4. * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics.
  5. */
  6. #include <linux/of.h>
  7. #include <linux/platform_device.h>
  8. #include <linux/regmap.h>
  9. #include <linux/reset-controller.h>
  10. #include <linux/slab.h>
  11. #include <linux/spinlock.h>
  12. #include "reset-stm32.h"
  13. struct stm32_reset_data {
  14. /* reset lock */
  15. spinlock_t lock;
  16. struct reset_controller_dev rcdev;
  17. void __iomem *membase;
  18. u32 clear_offset;
  19. const struct stm32_reset_cfg **reset_lines;
  20. };
  21. static inline struct stm32_reset_data *
  22. to_stm32_reset_data(struct reset_controller_dev *rcdev)
  23. {
  24. return container_of(rcdev, struct stm32_reset_data, rcdev);
  25. }
  26. static const struct stm32_reset_cfg *stm32_get_reset_line(struct reset_controller_dev *rcdev,
  27. unsigned long id,
  28. struct stm32_reset_cfg *line)
  29. {
  30. struct stm32_reset_data *data = to_stm32_reset_data(rcdev);
  31. if (!data->reset_lines) {
  32. int reg_width = sizeof(u32);
  33. int bank = id / (reg_width * BITS_PER_BYTE);
  34. int offset = id % (reg_width * BITS_PER_BYTE);
  35. line->offset = bank * reg_width;
  36. line->bit_idx = offset;
  37. line->set_clr = (data->clear_offset ? true : false);
  38. return line;
  39. }
  40. return data->reset_lines[id];
  41. }
  42. static int stm32_reset_update(struct reset_controller_dev *rcdev,
  43. unsigned long id, bool assert)
  44. {
  45. struct stm32_reset_data *data = to_stm32_reset_data(rcdev);
  46. struct stm32_reset_cfg line_reset;
  47. const struct stm32_reset_cfg *ptr_line;
  48. ptr_line = stm32_get_reset_line(rcdev, id, &line_reset);
  49. if (!ptr_line)
  50. return -EPERM;
  51. if (ptr_line->set_clr) {
  52. void __iomem *addr;
  53. addr = data->membase + ptr_line->offset;
  54. if (!assert)
  55. addr += data->clear_offset;
  56. writel(BIT(ptr_line->bit_idx), addr);
  57. } else {
  58. unsigned long flags;
  59. u32 reg;
  60. spin_lock_irqsave(&data->lock, flags);
  61. reg = readl(data->membase + ptr_line->offset);
  62. if (assert)
  63. reg |= BIT(ptr_line->bit_idx);
  64. else
  65. reg &= ~BIT(ptr_line->bit_idx);
  66. writel(reg, data->membase + ptr_line->offset);
  67. spin_unlock_irqrestore(&data->lock, flags);
  68. }
  69. return 0;
  70. }
  71. static int stm32_reset_assert(struct reset_controller_dev *rcdev,
  72. unsigned long id)
  73. {
  74. return stm32_reset_update(rcdev, id, true);
  75. }
  76. static int stm32_reset_deassert(struct reset_controller_dev *rcdev,
  77. unsigned long id)
  78. {
  79. return stm32_reset_update(rcdev, id, false);
  80. }
  81. static int stm32_reset_status(struct reset_controller_dev *rcdev,
  82. unsigned long id)
  83. {
  84. struct stm32_reset_data *data = to_stm32_reset_data(rcdev);
  85. struct stm32_reset_cfg line_reset;
  86. const struct stm32_reset_cfg *ptr_line;
  87. u32 reg;
  88. ptr_line = stm32_get_reset_line(rcdev, id, &line_reset);
  89. if (!ptr_line)
  90. return -EPERM;
  91. reg = readl(data->membase + ptr_line->offset);
  92. return !!(reg & BIT(ptr_line->bit_idx));
  93. }
  94. static const struct reset_control_ops stm32_reset_ops = {
  95. .assert = stm32_reset_assert,
  96. .deassert = stm32_reset_deassert,
  97. .status = stm32_reset_status,
  98. };
  99. int stm32_rcc_reset_init(struct device *dev, struct clk_stm32_reset_data *data,
  100. void __iomem *base)
  101. {
  102. struct stm32_reset_data *reset_data;
  103. reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
  104. if (!reset_data)
  105. return -ENOMEM;
  106. spin_lock_init(&reset_data->lock);
  107. reset_data->membase = base;
  108. reset_data->rcdev.owner = THIS_MODULE;
  109. reset_data->rcdev.ops = &stm32_reset_ops;
  110. reset_data->rcdev.of_node = dev_of_node(dev);
  111. reset_data->rcdev.nr_resets = data->nr_lines;
  112. reset_data->reset_lines = data->reset_lines;
  113. reset_data->clear_offset = data->clear_offset;
  114. return reset_controller_register(&reset_data->rcdev);
  115. }