clk-sun8i-mbus.c 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /*
  2. * Copyright 2014 Chen-Yu Tsai
  3. *
  4. * Chen-Yu Tsai <wens@csie.org>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #include <linux/clk.h>
  17. #include <linux/clk-provider.h>
  18. #include <linux/of_address.h>
  19. #include "clk-factors.h"
  20. /**
  21. * sun8i_a23_get_mbus_factors() - calculates m factor for MBUS clocks
  22. * MBUS rate is calculated as follows
  23. * rate = parent_rate / (m + 1);
  24. */
  25. static void sun8i_a23_get_mbus_factors(u32 *freq, u32 parent_rate,
  26. u8 *n, u8 *k, u8 *m, u8 *p)
  27. {
  28. u8 div;
  29. /*
  30. * These clocks can only divide, so we will never be able to
  31. * achieve frequencies higher than the parent frequency
  32. */
  33. if (*freq > parent_rate)
  34. *freq = parent_rate;
  35. div = DIV_ROUND_UP(parent_rate, *freq);
  36. if (div > 8)
  37. div = 8;
  38. *freq = parent_rate / div;
  39. /* we were called to round the frequency, we can now return */
  40. if (m == NULL)
  41. return;
  42. *m = div - 1;
  43. }
  44. static struct clk_factors_config sun8i_a23_mbus_config = {
  45. .mshift = 0,
  46. .mwidth = 3,
  47. };
  48. static const struct factors_data sun8i_a23_mbus_data __initconst = {
  49. .enable = 31,
  50. .mux = 24,
  51. .muxmask = BIT(1) | BIT(0),
  52. .table = &sun8i_a23_mbus_config,
  53. .getter = sun8i_a23_get_mbus_factors,
  54. };
  55. static DEFINE_SPINLOCK(sun8i_a23_mbus_lock);
  56. static void __init sun8i_a23_mbus_setup(struct device_node *node)
  57. {
  58. struct clk *mbus;
  59. void __iomem *reg;
  60. reg = of_iomap(node, 0);
  61. if (!reg) {
  62. pr_err("Could not get registers for a23-mbus-clk\n");
  63. return;
  64. }
  65. mbus = sunxi_factors_register(node, &sun8i_a23_mbus_data,
  66. &sun8i_a23_mbus_lock, reg);
  67. /* The MBUS clocks needs to be always enabled */
  68. __clk_get(mbus);
  69. clk_prepare_enable(mbus);
  70. }
  71. CLK_OF_DECLARE(sun8i_a23_mbus, "allwinner,sun8i-a23-mbus-clk", sun8i_a23_mbus_setup);