clk-frac.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * Copyright 2012 Freescale Semiconductor, Inc.
  3. *
  4. * The code contained herein is licensed under the GNU General Public
  5. * License. You may obtain a copy of the GNU General Public License
  6. * Version 2 or later at the following locations:
  7. *
  8. * http://www.opensource.org/licenses/gpl-license.html
  9. * http://www.gnu.org/copyleft/gpl.html
  10. */
  11. #include <linux/clk.h>
  12. #include <linux/clk-provider.h>
  13. #include <linux/err.h>
  14. #include <linux/io.h>
  15. #include <linux/slab.h>
  16. #include "clk.h"
  17. /**
  18. * struct clk_frac - mxs fractional divider clock
  19. * @hw: clk_hw for the fractional divider clock
  20. * @reg: register address
  21. * @shift: the divider bit shift
  22. * @width: the divider bit width
  23. * @busy: busy bit shift
  24. *
  25. * The clock is an adjustable fractional divider with a busy bit to wait
  26. * when the divider is adjusted.
  27. */
  28. struct clk_frac {
  29. struct clk_hw hw;
  30. void __iomem *reg;
  31. u8 shift;
  32. u8 width;
  33. u8 busy;
  34. };
  35. #define to_clk_frac(_hw) container_of(_hw, struct clk_frac, hw)
  36. static unsigned long clk_frac_recalc_rate(struct clk_hw *hw,
  37. unsigned long parent_rate)
  38. {
  39. struct clk_frac *frac = to_clk_frac(hw);
  40. u32 div;
  41. div = readl_relaxed(frac->reg) >> frac->shift;
  42. div &= (1 << frac->width) - 1;
  43. return (parent_rate >> frac->width) * div;
  44. }
  45. static long clk_frac_round_rate(struct clk_hw *hw, unsigned long rate,
  46. unsigned long *prate)
  47. {
  48. struct clk_frac *frac = to_clk_frac(hw);
  49. unsigned long parent_rate = *prate;
  50. u32 div;
  51. u64 tmp;
  52. if (rate > parent_rate)
  53. return -EINVAL;
  54. tmp = rate;
  55. tmp <<= frac->width;
  56. do_div(tmp, parent_rate);
  57. div = tmp;
  58. if (!div)
  59. return -EINVAL;
  60. return (parent_rate >> frac->width) * div;
  61. }
  62. static int clk_frac_set_rate(struct clk_hw *hw, unsigned long rate,
  63. unsigned long parent_rate)
  64. {
  65. struct clk_frac *frac = to_clk_frac(hw);
  66. unsigned long flags;
  67. u32 div, val;
  68. u64 tmp;
  69. if (rate > parent_rate)
  70. return -EINVAL;
  71. tmp = rate;
  72. tmp <<= frac->width;
  73. do_div(tmp, parent_rate);
  74. div = tmp;
  75. if (!div)
  76. return -EINVAL;
  77. spin_lock_irqsave(&mxs_lock, flags);
  78. val = readl_relaxed(frac->reg);
  79. val &= ~(((1 << frac->width) - 1) << frac->shift);
  80. val |= div << frac->shift;
  81. writel_relaxed(val, frac->reg);
  82. spin_unlock_irqrestore(&mxs_lock, flags);
  83. return mxs_clk_wait(frac->reg, frac->busy);
  84. }
  85. static struct clk_ops clk_frac_ops = {
  86. .recalc_rate = clk_frac_recalc_rate,
  87. .round_rate = clk_frac_round_rate,
  88. .set_rate = clk_frac_set_rate,
  89. };
  90. struct clk *mxs_clk_frac(const char *name, const char *parent_name,
  91. void __iomem *reg, u8 shift, u8 width, u8 busy)
  92. {
  93. struct clk_frac *frac;
  94. struct clk *clk;
  95. struct clk_init_data init;
  96. frac = kzalloc(sizeof(*frac), GFP_KERNEL);
  97. if (!frac)
  98. return ERR_PTR(-ENOMEM);
  99. init.name = name;
  100. init.ops = &clk_frac_ops;
  101. init.flags = CLK_SET_RATE_PARENT;
  102. init.parent_names = (parent_name ? &parent_name: NULL);
  103. init.num_parents = (parent_name ? 1 : 0);
  104. frac->reg = reg;
  105. frac->shift = shift;
  106. frac->width = width;
  107. frac->busy = busy;
  108. frac->hw.init = &init;
  109. clk = clk_register(NULL, &frac->hw);
  110. if (IS_ERR(clk))
  111. kfree(frac);
  112. return clk;
  113. }