clk.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/clk.h>
  3. #include <linux/err.h>
  4. #include <linux/of.h>
  5. #include <linux/slab.h>
  6. #include <linux/spinlock.h>
  7. #include "clk.h"
  8. DEFINE_SPINLOCK(imx_ccm_lock);
  9. void __init imx_check_clocks(struct clk *clks[], unsigned int count)
  10. {
  11. unsigned i;
  12. for (i = 0; i < count; i++)
  13. if (IS_ERR(clks[i]))
  14. pr_err("i.MX clk %u: register failed with %ld\n",
  15. i, PTR_ERR(clks[i]));
  16. }
  17. static struct clk * __init imx_obtain_fixed_clock_from_dt(const char *name)
  18. {
  19. struct of_phandle_args phandle;
  20. struct clk *clk = ERR_PTR(-ENODEV);
  21. char *path;
  22. path = kasprintf(GFP_KERNEL, "/clocks/%s", name);
  23. if (!path)
  24. return ERR_PTR(-ENOMEM);
  25. phandle.np = of_find_node_by_path(path);
  26. kfree(path);
  27. if (phandle.np) {
  28. clk = of_clk_get_from_provider(&phandle);
  29. of_node_put(phandle.np);
  30. }
  31. return clk;
  32. }
  33. struct clk * __init imx_obtain_fixed_clock(
  34. const char *name, unsigned long rate)
  35. {
  36. struct clk *clk;
  37. clk = imx_obtain_fixed_clock_from_dt(name);
  38. if (IS_ERR(clk))
  39. clk = imx_clk_fixed(name, rate);
  40. return clk;
  41. }
  42. /*
  43. * This fixups the register CCM_CSCMR1 write value.
  44. * The write/read/divider values of the aclk_podf field
  45. * of that register have the relationship described by
  46. * the following table:
  47. *
  48. * write value read value divider
  49. * 3b'000 3b'110 7
  50. * 3b'001 3b'111 8
  51. * 3b'010 3b'100 5
  52. * 3b'011 3b'101 6
  53. * 3b'100 3b'010 3
  54. * 3b'101 3b'011 4
  55. * 3b'110 3b'000 1
  56. * 3b'111 3b'001 2(default)
  57. *
  58. * That's why we do the xor operation below.
  59. */
  60. #define CSCMR1_FIXUP 0x00600000
  61. void imx_cscmr1_fixup(u32 *val)
  62. {
  63. *val ^= CSCMR1_FIXUP;
  64. return;
  65. }
  66. static int imx_keep_uart_clocks __initdata;
  67. static struct clk ** const *imx_uart_clocks __initdata;
  68. static int __init imx_keep_uart_clocks_param(char *str)
  69. {
  70. imx_keep_uart_clocks = 1;
  71. return 0;
  72. }
  73. __setup_param("earlycon", imx_keep_uart_earlycon,
  74. imx_keep_uart_clocks_param, 0);
  75. __setup_param("earlyprintk", imx_keep_uart_earlyprintk,
  76. imx_keep_uart_clocks_param, 0);
  77. void __init imx_register_uart_clocks(struct clk ** const clks[])
  78. {
  79. if (imx_keep_uart_clocks) {
  80. int i;
  81. imx_uart_clocks = clks;
  82. for (i = 0; imx_uart_clocks[i]; i++)
  83. clk_prepare_enable(*imx_uart_clocks[i]);
  84. }
  85. }
  86. static int __init imx_clk_disable_uart(void)
  87. {
  88. if (imx_keep_uart_clocks && imx_uart_clocks) {
  89. int i;
  90. for (i = 0; imx_uart_clocks[i]; i++)
  91. clk_disable_unprepare(*imx_uart_clocks[i]);
  92. }
  93. return 0;
  94. }
  95. late_initcall_sync(imx_clk_disable_uart);