ccu_reset.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2016 Maxime Ripard
  4. * Maxime Ripard <[email protected]>
  5. */
  6. #include <linux/delay.h>
  7. #include <linux/io.h>
  8. #include <linux/reset-controller.h>
  9. #include "ccu_reset.h"
  10. static int ccu_reset_assert(struct reset_controller_dev *rcdev,
  11. unsigned long id)
  12. {
  13. struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
  14. const struct ccu_reset_map *map = &ccu->reset_map[id];
  15. unsigned long flags;
  16. u32 reg;
  17. spin_lock_irqsave(ccu->lock, flags);
  18. reg = readl(ccu->base + map->reg);
  19. writel(reg & ~map->bit, ccu->base + map->reg);
  20. spin_unlock_irqrestore(ccu->lock, flags);
  21. return 0;
  22. }
  23. static int ccu_reset_deassert(struct reset_controller_dev *rcdev,
  24. unsigned long id)
  25. {
  26. struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
  27. const struct ccu_reset_map *map = &ccu->reset_map[id];
  28. unsigned long flags;
  29. u32 reg;
  30. spin_lock_irqsave(ccu->lock, flags);
  31. reg = readl(ccu->base + map->reg);
  32. writel(reg | map->bit, ccu->base + map->reg);
  33. spin_unlock_irqrestore(ccu->lock, flags);
  34. return 0;
  35. }
  36. static int ccu_reset_reset(struct reset_controller_dev *rcdev,
  37. unsigned long id)
  38. {
  39. ccu_reset_assert(rcdev, id);
  40. udelay(10);
  41. ccu_reset_deassert(rcdev, id);
  42. return 0;
  43. }
  44. static int ccu_reset_status(struct reset_controller_dev *rcdev,
  45. unsigned long id)
  46. {
  47. struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
  48. const struct ccu_reset_map *map = &ccu->reset_map[id];
  49. /*
  50. * The reset control API expects 0 if reset is not asserted,
  51. * which is the opposite of what our hardware uses.
  52. */
  53. return !(map->bit & readl(ccu->base + map->reg));
  54. }
  55. const struct reset_control_ops ccu_reset_ops = {
  56. .assert = ccu_reset_assert,
  57. .deassert = ccu_reset_deassert,
  58. .reset = ccu_reset_reset,
  59. .status = ccu_reset_status,
  60. };
  61. EXPORT_SYMBOL_NS_GPL(ccu_reset_ops, SUNXI_CCU);