clk-gate-exclusive.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright 2014 Freescale Semiconductor, Inc.
  4. */
  5. #include <linux/clk-provider.h>
  6. #include <linux/err.h>
  7. #include <linux/io.h>
  8. #include <linux/slab.h>
  9. #include "clk.h"
  10. /**
  11. * struct clk_gate_exclusive - i.MX specific gate clock which is mutually
  12. * exclusive with other gate clocks
  13. *
  14. * @gate: the parent class
  15. * @exclusive_mask: mask of gate bits which are mutually exclusive to this
  16. * gate clock
  17. *
  18. * The imx exclusive gate clock is a subclass of basic clk_gate
  19. * with an addtional mask to indicate which other gate bits in the same
  20. * register is mutually exclusive to this gate clock.
  21. */
  22. struct clk_gate_exclusive {
  23. struct clk_gate gate;
  24. u32 exclusive_mask;
  25. };
  26. static int clk_gate_exclusive_enable(struct clk_hw *hw)
  27. {
  28. struct clk_gate *gate = to_clk_gate(hw);
  29. struct clk_gate_exclusive *exgate = container_of(gate,
  30. struct clk_gate_exclusive, gate);
  31. u32 val = readl(gate->reg);
  32. if (val & exgate->exclusive_mask)
  33. return -EBUSY;
  34. return clk_gate_ops.enable(hw);
  35. }
  36. static void clk_gate_exclusive_disable(struct clk_hw *hw)
  37. {
  38. clk_gate_ops.disable(hw);
  39. }
  40. static int clk_gate_exclusive_is_enabled(struct clk_hw *hw)
  41. {
  42. return clk_gate_ops.is_enabled(hw);
  43. }
  44. static const struct clk_ops clk_gate_exclusive_ops = {
  45. .enable = clk_gate_exclusive_enable,
  46. .disable = clk_gate_exclusive_disable,
  47. .is_enabled = clk_gate_exclusive_is_enabled,
  48. };
  49. struct clk_hw *imx_clk_hw_gate_exclusive(const char *name, const char *parent,
  50. void __iomem *reg, u8 shift, u32 exclusive_mask)
  51. {
  52. struct clk_gate_exclusive *exgate;
  53. struct clk_gate *gate;
  54. struct clk_hw *hw;
  55. struct clk_init_data init;
  56. int ret;
  57. if (exclusive_mask == 0)
  58. return ERR_PTR(-EINVAL);
  59. exgate = kzalloc(sizeof(*exgate), GFP_KERNEL);
  60. if (!exgate)
  61. return ERR_PTR(-ENOMEM);
  62. gate = &exgate->gate;
  63. init.name = name;
  64. init.ops = &clk_gate_exclusive_ops;
  65. init.flags = CLK_SET_RATE_PARENT;
  66. init.parent_names = parent ? &parent : NULL;
  67. init.num_parents = parent ? 1 : 0;
  68. gate->reg = reg;
  69. gate->bit_idx = shift;
  70. gate->lock = &imx_ccm_lock;
  71. gate->hw.init = &init;
  72. exgate->exclusive_mask = exclusive_mask;
  73. hw = &gate->hw;
  74. ret = clk_hw_register(NULL, hw);
  75. if (ret) {
  76. kfree(gate);
  77. return ERR_PTR(ret);
  78. }
  79. return hw;
  80. }