clk-sun8i-mbus.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  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-provider.h>
  17. #include <linux/clkdev.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. .table = &sun8i_a23_mbus_config,
  52. .getter = sun8i_a23_get_mbus_factors,
  53. };
  54. static DEFINE_SPINLOCK(sun8i_a23_mbus_lock);
  55. static void __init sun8i_a23_mbus_setup(struct device_node *node)
  56. {
  57. struct clk *mbus = sunxi_factors_register(node, &sun8i_a23_mbus_data,
  58. &sun8i_a23_mbus_lock);
  59. /* The MBUS clocks needs to be always enabled */
  60. __clk_get(mbus);
  61. clk_prepare_enable(mbus);
  62. }
  63. CLK_OF_DECLARE(sun8i_a23_mbus, "allwinner,sun8i-a23-mbus-clk", sun8i_a23_mbus_setup);