gate.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Spreadtrum gate clock driver
  4. //
  5. // Copyright (C) 2017 Spreadtrum, Inc.
  6. // Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
  7. #include <linux/clk-provider.h>
  8. #include <linux/regmap.h>
  9. #include "gate.h"
  10. static void clk_gate_toggle(const struct sprd_gate *sg, bool en)
  11. {
  12. const struct sprd_clk_common *common = &sg->common;
  13. unsigned int reg;
  14. bool set = sg->flags & CLK_GATE_SET_TO_DISABLE ? true : false;
  15. set ^= en;
  16. regmap_read(common->regmap, common->reg, &reg);
  17. if (set)
  18. reg |= sg->enable_mask;
  19. else
  20. reg &= ~sg->enable_mask;
  21. regmap_write(common->regmap, common->reg, reg);
  22. }
  23. static void clk_sc_gate_toggle(const struct sprd_gate *sg, bool en)
  24. {
  25. const struct sprd_clk_common *common = &sg->common;
  26. bool set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
  27. unsigned int offset;
  28. set ^= en;
  29. /*
  30. * Each set/clear gate clock has three registers:
  31. * common->reg - base register
  32. * common->reg + offset - set register
  33. * common->reg + 2 * offset - clear register
  34. */
  35. offset = set ? sg->sc_offset : sg->sc_offset * 2;
  36. regmap_write(common->regmap, common->reg + offset,
  37. sg->enable_mask);
  38. }
  39. static void sprd_gate_disable(struct clk_hw *hw)
  40. {
  41. struct sprd_gate *sg = hw_to_sprd_gate(hw);
  42. clk_gate_toggle(sg, false);
  43. }
  44. static int sprd_gate_enable(struct clk_hw *hw)
  45. {
  46. struct sprd_gate *sg = hw_to_sprd_gate(hw);
  47. clk_gate_toggle(sg, true);
  48. return 0;
  49. }
  50. static void sprd_sc_gate_disable(struct clk_hw *hw)
  51. {
  52. struct sprd_gate *sg = hw_to_sprd_gate(hw);
  53. clk_sc_gate_toggle(sg, false);
  54. }
  55. static int sprd_sc_gate_enable(struct clk_hw *hw)
  56. {
  57. struct sprd_gate *sg = hw_to_sprd_gate(hw);
  58. clk_sc_gate_toggle(sg, true);
  59. return 0;
  60. }
  61. static int sprd_gate_is_enabled(struct clk_hw *hw)
  62. {
  63. struct sprd_gate *sg = hw_to_sprd_gate(hw);
  64. struct sprd_clk_common *common = &sg->common;
  65. unsigned int reg;
  66. regmap_read(common->regmap, common->reg, &reg);
  67. if (sg->flags & CLK_GATE_SET_TO_DISABLE)
  68. reg ^= sg->enable_mask;
  69. reg &= sg->enable_mask;
  70. return reg ? 1 : 0;
  71. }
  72. const struct clk_ops sprd_gate_ops = {
  73. .disable = sprd_gate_disable,
  74. .enable = sprd_gate_enable,
  75. .is_enabled = sprd_gate_is_enabled,
  76. };
  77. EXPORT_SYMBOL_GPL(sprd_gate_ops);
  78. const struct clk_ops sprd_sc_gate_ops = {
  79. .disable = sprd_sc_gate_disable,
  80. .enable = sprd_sc_gate_enable,
  81. .is_enabled = sprd_gate_is_enabled,
  82. };
  83. EXPORT_SYMBOL_GPL(sprd_sc_gate_ops);