softrst.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (c) 2014 MundoReader S.L.
  4. * Author: Heiko Stuebner <[email protected]>
  5. */
  6. #include <linux/slab.h>
  7. #include <linux/io.h>
  8. #include <linux/reset-controller.h>
  9. #include <linux/spinlock.h>
  10. #include "clk.h"
  11. struct rockchip_softrst {
  12. struct reset_controller_dev rcdev;
  13. void __iomem *reg_base;
  14. int num_regs;
  15. int num_per_reg;
  16. u8 flags;
  17. spinlock_t lock;
  18. };
  19. static int rockchip_softrst_assert(struct reset_controller_dev *rcdev,
  20. unsigned long id)
  21. {
  22. struct rockchip_softrst *softrst = container_of(rcdev,
  23. struct rockchip_softrst,
  24. rcdev);
  25. int bank = id / softrst->num_per_reg;
  26. int offset = id % softrst->num_per_reg;
  27. if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {
  28. writel(BIT(offset) | (BIT(offset) << 16),
  29. softrst->reg_base + (bank * 4));
  30. } else {
  31. unsigned long flags;
  32. u32 reg;
  33. spin_lock_irqsave(&softrst->lock, flags);
  34. reg = readl(softrst->reg_base + (bank * 4));
  35. writel(reg | BIT(offset), softrst->reg_base + (bank * 4));
  36. spin_unlock_irqrestore(&softrst->lock, flags);
  37. }
  38. return 0;
  39. }
  40. static int rockchip_softrst_deassert(struct reset_controller_dev *rcdev,
  41. unsigned long id)
  42. {
  43. struct rockchip_softrst *softrst = container_of(rcdev,
  44. struct rockchip_softrst,
  45. rcdev);
  46. int bank = id / softrst->num_per_reg;
  47. int offset = id % softrst->num_per_reg;
  48. if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {
  49. writel((BIT(offset) << 16), softrst->reg_base + (bank * 4));
  50. } else {
  51. unsigned long flags;
  52. u32 reg;
  53. spin_lock_irqsave(&softrst->lock, flags);
  54. reg = readl(softrst->reg_base + (bank * 4));
  55. writel(reg & ~BIT(offset), softrst->reg_base + (bank * 4));
  56. spin_unlock_irqrestore(&softrst->lock, flags);
  57. }
  58. return 0;
  59. }
  60. static const struct reset_control_ops rockchip_softrst_ops = {
  61. .assert = rockchip_softrst_assert,
  62. .deassert = rockchip_softrst_deassert,
  63. };
  64. void rockchip_register_softrst(struct device_node *np,
  65. unsigned int num_regs,
  66. void __iomem *base, u8 flags)
  67. {
  68. struct rockchip_softrst *softrst;
  69. int ret;
  70. softrst = kzalloc(sizeof(*softrst), GFP_KERNEL);
  71. if (!softrst)
  72. return;
  73. spin_lock_init(&softrst->lock);
  74. softrst->reg_base = base;
  75. softrst->flags = flags;
  76. softrst->num_regs = num_regs;
  77. softrst->num_per_reg = (flags & ROCKCHIP_SOFTRST_HIWORD_MASK) ? 16
  78. : 32;
  79. softrst->rcdev.owner = THIS_MODULE;
  80. softrst->rcdev.nr_resets = num_regs * softrst->num_per_reg;
  81. softrst->rcdev.ops = &rockchip_softrst_ops;
  82. softrst->rcdev.of_node = np;
  83. ret = reset_controller_register(&softrst->rcdev);
  84. if (ret) {
  85. pr_err("%s: could not register reset controller, %d\n",
  86. __func__, ret);
  87. kfree(softrst);
  88. }
  89. };
  90. EXPORT_SYMBOL_GPL(rockchip_register_softrst);