clock.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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. /*
  32. * Locking:
  33. *
  34. * An additional mutex, clock_list_lock, is used to protect the list of all
  35. * clocks.
  36. *
  37. */
  38. static DEFINE_MUTEX(clock_list_lock);
  39. static LIST_HEAD(clocks);
  40. void tegra_clk_add(struct clk *clk)
  41. {
  42. struct clk_tegra *c = to_clk_tegra(__clk_get_hw(clk));
  43. mutex_lock(&clock_list_lock);
  44. list_add(&c->node, &clocks);
  45. mutex_unlock(&clock_list_lock);
  46. }
  47. struct clk *tegra_get_clock_by_name(const char *name)
  48. {
  49. struct clk_tegra *c;
  50. struct clk *ret = NULL;
  51. mutex_lock(&clock_list_lock);
  52. list_for_each_entry(c, &clocks, node) {
  53. if (strcmp(__clk_get_name(c->hw.clk), name) == 0) {
  54. ret = c->hw.clk;
  55. break;
  56. }
  57. }
  58. mutex_unlock(&clock_list_lock);
  59. return ret;
  60. }
  61. static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table)
  62. {
  63. struct clk *c;
  64. struct clk *p;
  65. struct clk *parent;
  66. int ret = 0;
  67. c = tegra_get_clock_by_name(table->name);
  68. if (!c) {
  69. pr_warn("Unable to initialize clock %s\n",
  70. table->name);
  71. return -ENODEV;
  72. }
  73. parent = clk_get_parent(c);
  74. if (table->parent) {
  75. p = tegra_get_clock_by_name(table->parent);
  76. if (!p) {
  77. pr_warn("Unable to find parent %s of clock %s\n",
  78. table->parent, table->name);
  79. return -ENODEV;
  80. }
  81. if (parent != p) {
  82. ret = clk_set_parent(c, p);
  83. if (ret) {
  84. pr_warn("Unable to set parent %s of clock %s: %d\n",
  85. table->parent, table->name, ret);
  86. return -EINVAL;
  87. }
  88. }
  89. }
  90. if (table->rate && table->rate != clk_get_rate(c)) {
  91. ret = clk_set_rate(c, table->rate);
  92. if (ret) {
  93. pr_warn("Unable to set clock %s to rate %lu: %d\n",
  94. table->name, table->rate, ret);
  95. return -EINVAL;
  96. }
  97. }
  98. if (table->enabled) {
  99. ret = clk_prepare_enable(c);
  100. if (ret) {
  101. pr_warn("Unable to enable clock %s: %d\n",
  102. table->name, ret);
  103. return -EINVAL;
  104. }
  105. }
  106. return 0;
  107. }
  108. void tegra_clk_init_from_table(struct tegra_clk_init_table *table)
  109. {
  110. for (; table->name; table++)
  111. tegra_clk_init_one_from_table(table);
  112. }
  113. void tegra_periph_reset_deassert(struct clk *c)
  114. {
  115. struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c));
  116. BUG_ON(!clk->reset);
  117. clk->reset(__clk_get_hw(c), false);
  118. }
  119. EXPORT_SYMBOL(tegra_periph_reset_deassert);
  120. void tegra_periph_reset_assert(struct clk *c)
  121. {
  122. struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c));
  123. BUG_ON(!clk->reset);
  124. clk->reset(__clk_get_hw(c), true);
  125. }
  126. EXPORT_SYMBOL(tegra_periph_reset_assert);
  127. /* Several extended clock configuration bits (e.g., clock routing, clock
  128. * phase control) are included in PLL and peripheral clock source
  129. * registers. */
  130. int tegra_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
  131. {
  132. int ret = 0;
  133. struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c));
  134. if (!clk->clk_cfg_ex) {
  135. ret = -ENOSYS;
  136. goto out;
  137. }
  138. ret = clk->clk_cfg_ex(__clk_get_hw(c), p, setting);
  139. out:
  140. return ret;
  141. }