ccu-div.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright (C) 2020 BAIKAL ELECTRONICS, JSC
  4. *
  5. * Baikal-T1 CCU Dividers interface driver
  6. */
  7. #ifndef __CLK_BT1_CCU_DIV_H__
  8. #define __CLK_BT1_CCU_DIV_H__
  9. #include <linux/clk-provider.h>
  10. #include <linux/spinlock.h>
  11. #include <linux/regmap.h>
  12. #include <linux/bits.h>
  13. #include <linux/of.h>
  14. /*
  15. * CCU Divider private clock IDs
  16. * @CCU_SYS_SATA_CLK: CCU SATA internal clock
  17. * @CCU_SYS_XGMAC_CLK: CCU XGMAC internal clock
  18. */
  19. #define CCU_SYS_SATA_CLK -1
  20. #define CCU_SYS_XGMAC_CLK -2
  21. /*
  22. * CCU Divider private flags
  23. * @CCU_DIV_BASIC: Basic divider clock required by the kernel as early as
  24. * possible.
  25. * @CCU_DIV_SKIP_ONE: Due to some reason divider can't be set to 1.
  26. * It can be 0 though, which is functionally the same.
  27. * @CCU_DIV_SKIP_ONE_TO_THREE: For some reason divider can't be within [1,3].
  28. * It can be either 0 or greater than 3.
  29. * @CCU_DIV_LOCK_SHIFTED: Find lock-bit at non-standard position.
  30. * @CCU_DIV_RESET_DOMAIN: There is a clock domain reset handle.
  31. */
  32. #define CCU_DIV_BASIC BIT(0)
  33. #define CCU_DIV_SKIP_ONE BIT(1)
  34. #define CCU_DIV_SKIP_ONE_TO_THREE BIT(2)
  35. #define CCU_DIV_LOCK_SHIFTED BIT(3)
  36. #define CCU_DIV_RESET_DOMAIN BIT(4)
  37. /*
  38. * enum ccu_div_type - CCU Divider types
  39. * @CCU_DIV_VAR: Clocks gate with variable divider.
  40. * @CCU_DIV_GATE: Clocks gate with fixed divider.
  41. * @CCU_DIV_BUF: Clock gate with no divider.
  42. * @CCU_DIV_FIXED: Ungateable clock with fixed divider.
  43. */
  44. enum ccu_div_type {
  45. CCU_DIV_VAR,
  46. CCU_DIV_GATE,
  47. CCU_DIV_BUF,
  48. CCU_DIV_FIXED
  49. };
  50. /*
  51. * struct ccu_div_init_data - CCU Divider initialization data
  52. * @id: Clocks private identifier.
  53. * @name: Clocks name.
  54. * @parent_name: Parent clocks name in a fw node.
  55. * @base: Divider register base address with respect to the sys_regs base.
  56. * @sys_regs: Baikal-T1 System Controller registers map.
  57. * @np: Pointer to the node describing the CCU Dividers.
  58. * @type: CCU divider type (variable, fixed with and without gate).
  59. * @width: Divider width if it's variable.
  60. * @divider: Divider fixed value.
  61. * @flags: CCU Divider clock flags.
  62. * @features: CCU Divider private features.
  63. */
  64. struct ccu_div_init_data {
  65. unsigned int id;
  66. const char *name;
  67. const char *parent_name;
  68. unsigned int base;
  69. struct regmap *sys_regs;
  70. struct device_node *np;
  71. enum ccu_div_type type;
  72. union {
  73. unsigned int width;
  74. unsigned int divider;
  75. };
  76. unsigned long flags;
  77. unsigned long features;
  78. };
  79. /*
  80. * struct ccu_div - CCU Divider descriptor
  81. * @hw: clk_hw of the divider.
  82. * @id: Clock private identifier.
  83. * @reg_ctl: Divider control register base address.
  84. * @sys_regs: Baikal-T1 System Controller registers map.
  85. * @lock: Divider state change spin-lock.
  86. * @mask: Divider field mask.
  87. * @divider: Divider fixed value.
  88. * @flags: Divider clock flags.
  89. * @features: CCU Divider private features.
  90. */
  91. struct ccu_div {
  92. struct clk_hw hw;
  93. unsigned int id;
  94. unsigned int reg_ctl;
  95. struct regmap *sys_regs;
  96. spinlock_t lock;
  97. union {
  98. u32 mask;
  99. unsigned int divider;
  100. };
  101. unsigned long flags;
  102. unsigned long features;
  103. };
  104. #define to_ccu_div(_hw) container_of(_hw, struct ccu_div, hw)
  105. static inline struct clk_hw *ccu_div_get_clk_hw(struct ccu_div *div)
  106. {
  107. return div ? &div->hw : NULL;
  108. }
  109. struct ccu_div *ccu_div_hw_register(const struct ccu_div_init_data *init);
  110. void ccu_div_hw_unregister(struct ccu_div *div);
  111. #endif /* __CLK_BT1_CCU_DIV_H__ */