clock.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. *
  3. * Copyright (C) 2010 Google, Inc.
  4. * Copyright (c) 2012 NVIDIA CORPORATION. All rights reserved.
  5. *
  6. * Author:
  7. * Colin Cross <ccross@google.com>
  8. *
  9. * This software is licensed under the terms of the GNU General Public
  10. * License version 2, as published by the Free Software Foundation, and
  11. * may be copied, distributed, and modified under those terms.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. */
  19. #include <linux/kernel.h>
  20. #include <linux/clk.h>
  21. #include <linux/clkdev.h>
  22. #include <linux/init.h>
  23. #include <linux/list.h>
  24. #include <linux/module.h>
  25. #include <linux/sched.h>
  26. #include <linux/seq_file.h>
  27. #include <linux/slab.h>
  28. #include <mach/clk.h>
  29. #include "board.h"
  30. #include "clock.h"
  31. #include "tegra_cpu_car.h"
  32. /* Global data of Tegra CPU CAR ops */
  33. struct tegra_cpu_car_ops *tegra_cpu_car_ops;
  34. /*
  35. * Locking:
  36. *
  37. * An additional mutex, clock_list_lock, is used to protect the list of all
  38. * clocks.
  39. *
  40. */
  41. static DEFINE_MUTEX(clock_list_lock);
  42. static LIST_HEAD(clocks);
  43. void tegra_clk_add(struct clk *clk)
  44. {
  45. struct clk_tegra *c = to_clk_tegra(__clk_get_hw(clk));
  46. mutex_lock(&clock_list_lock);
  47. list_add(&c->node, &clocks);
  48. mutex_unlock(&clock_list_lock);
  49. }
  50. struct clk *tegra_get_clock_by_name(const char *name)
  51. {
  52. struct clk_tegra *c;
  53. struct clk *ret = NULL;
  54. mutex_lock(&clock_list_lock);
  55. list_for_each_entry(c, &clocks, node) {
  56. if (strcmp(__clk_get_name(c->hw.clk), name) == 0) {
  57. ret = c->hw.clk;
  58. break;
  59. }
  60. }
  61. mutex_unlock(&clock_list_lock);
  62. return ret;
  63. }
  64. static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table)
  65. {
  66. struct clk *c;
  67. struct clk *p;
  68. struct clk *parent;
  69. int ret = 0;
  70. c = tegra_get_clock_by_name(table->name);
  71. if (!c) {
  72. pr_warn("Unable to initialize clock %s\n",
  73. table->name);
  74. return -ENODEV;
  75. }
  76. parent = clk_get_parent(c);
  77. if (table->parent) {
  78. p = tegra_get_clock_by_name(table->parent);
  79. if (!p) {
  80. pr_warn("Unable to find parent %s of clock %s\n",
  81. table->parent, table->name);
  82. return -ENODEV;
  83. }
  84. if (parent != p) {
  85. ret = clk_set_parent(c, p);
  86. if (ret) {
  87. pr_warn("Unable to set parent %s of clock %s: %d\n",
  88. table->parent, table->name, ret);
  89. return -EINVAL;
  90. }
  91. }
  92. }
  93. if (table->rate && table->rate != clk_get_rate(c)) {
  94. ret = clk_set_rate(c, table->rate);
  95. if (ret) {
  96. pr_warn("Unable to set clock %s to rate %lu: %d\n",
  97. table->name, table->rate, ret);
  98. return -EINVAL;
  99. }
  100. }
  101. if (table->enabled) {
  102. ret = clk_prepare_enable(c);
  103. if (ret) {
  104. pr_warn("Unable to enable clock %s: %d\n",
  105. table->name, ret);
  106. return -EINVAL;
  107. }
  108. }
  109. return 0;
  110. }
  111. void tegra_clk_init_from_table(struct tegra_clk_init_table *table)
  112. {
  113. for (; table->name; table++)
  114. tegra_clk_init_one_from_table(table);
  115. }
  116. void tegra_periph_reset_deassert(struct clk *c)
  117. {
  118. struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c));
  119. BUG_ON(!clk->reset);
  120. clk->reset(__clk_get_hw(c), false);
  121. }
  122. EXPORT_SYMBOL(tegra_periph_reset_deassert);
  123. void tegra_periph_reset_assert(struct clk *c)
  124. {
  125. struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c));
  126. BUG_ON(!clk->reset);
  127. clk->reset(__clk_get_hw(c), true);
  128. }
  129. EXPORT_SYMBOL(tegra_periph_reset_assert);
  130. /* Several extended clock configuration bits (e.g., clock routing, clock
  131. * phase control) are included in PLL and peripheral clock source
  132. * registers. */
  133. int tegra_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
  134. {
  135. int ret = 0;
  136. struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c));
  137. if (!clk->clk_cfg_ex) {
  138. ret = -ENOSYS;
  139. goto out;
  140. }
  141. ret = clk->clk_cfg_ex(__clk_get_hw(c), p, setting);
  142. out:
  143. return ret;
  144. }