clk-gate.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * mmp gate clock operation source file
  4. *
  5. * Copyright (C) 2014 Marvell
  6. * Chao Xie <[email protected]>
  7. */
  8. #include <linux/clk-provider.h>
  9. #include <linux/slab.h>
  10. #include <linux/io.h>
  11. #include <linux/err.h>
  12. #include <linux/delay.h>
  13. #include "clk.h"
  14. /*
  15. * Some clocks will have mutiple bits to enable the clocks, and
  16. * the bits to disable the clock is not same as enabling bits.
  17. */
  18. #define to_clk_mmp_gate(hw) container_of(hw, struct mmp_clk_gate, hw)
  19. static int mmp_clk_gate_enable(struct clk_hw *hw)
  20. {
  21. struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
  22. unsigned long flags = 0;
  23. unsigned long rate;
  24. u32 tmp;
  25. if (gate->lock)
  26. spin_lock_irqsave(gate->lock, flags);
  27. tmp = readl(gate->reg);
  28. tmp &= ~gate->mask;
  29. tmp |= gate->val_enable;
  30. writel(tmp, gate->reg);
  31. if (gate->lock)
  32. spin_unlock_irqrestore(gate->lock, flags);
  33. if (gate->flags & MMP_CLK_GATE_NEED_DELAY) {
  34. rate = clk_hw_get_rate(hw);
  35. /* Need delay 2 cycles. */
  36. udelay(2000000/rate);
  37. }
  38. return 0;
  39. }
  40. static void mmp_clk_gate_disable(struct clk_hw *hw)
  41. {
  42. struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
  43. unsigned long flags = 0;
  44. u32 tmp;
  45. if (gate->lock)
  46. spin_lock_irqsave(gate->lock, flags);
  47. tmp = readl(gate->reg);
  48. tmp &= ~gate->mask;
  49. tmp |= gate->val_disable;
  50. writel(tmp, gate->reg);
  51. if (gate->lock)
  52. spin_unlock_irqrestore(gate->lock, flags);
  53. }
  54. static int mmp_clk_gate_is_enabled(struct clk_hw *hw)
  55. {
  56. struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
  57. unsigned long flags = 0;
  58. u32 tmp;
  59. if (gate->lock)
  60. spin_lock_irqsave(gate->lock, flags);
  61. tmp = readl(gate->reg);
  62. if (gate->lock)
  63. spin_unlock_irqrestore(gate->lock, flags);
  64. return (tmp & gate->mask) == gate->val_enable;
  65. }
  66. const struct clk_ops mmp_clk_gate_ops = {
  67. .enable = mmp_clk_gate_enable,
  68. .disable = mmp_clk_gate_disable,
  69. .is_enabled = mmp_clk_gate_is_enabled,
  70. };
  71. struct clk *mmp_clk_register_gate(struct device *dev, const char *name,
  72. const char *parent_name, unsigned long flags,
  73. void __iomem *reg, u32 mask, u32 val_enable, u32 val_disable,
  74. unsigned int gate_flags, spinlock_t *lock)
  75. {
  76. struct mmp_clk_gate *gate;
  77. struct clk *clk;
  78. struct clk_init_data init;
  79. /* allocate the gate */
  80. gate = kzalloc(sizeof(*gate), GFP_KERNEL);
  81. if (!gate)
  82. return ERR_PTR(-ENOMEM);
  83. init.name = name;
  84. init.ops = &mmp_clk_gate_ops;
  85. init.flags = flags;
  86. init.parent_names = (parent_name ? &parent_name : NULL);
  87. init.num_parents = (parent_name ? 1 : 0);
  88. /* struct clk_gate assignments */
  89. gate->reg = reg;
  90. gate->mask = mask;
  91. gate->val_enable = val_enable;
  92. gate->val_disable = val_disable;
  93. gate->flags = gate_flags;
  94. gate->lock = lock;
  95. gate->hw.init = &init;
  96. clk = clk_register(dev, &gate->hw);
  97. if (IS_ERR(clk))
  98. kfree(gate);
  99. return clk;
  100. }