clk-generated.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. * Copyright (C) 2016 Atmel Corporation
  3. * Wenyou.Yang <wenyou.yang@atmel.com>
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <clk-uclass.h>
  9. #include <dm/device.h>
  10. #include <linux/io.h>
  11. #include <mach/at91_pmc.h>
  12. #include "pmc.h"
  13. DECLARE_GLOBAL_DATA_PTR;
  14. #define GENERATED_SOURCE_MAX 6
  15. #define GENERATED_MAX_DIV 255
  16. /**
  17. * generated_clk_bind() - for the generated clock driver
  18. * Recursively bind its children as clk devices.
  19. *
  20. * @return: 0 on success, or negative error code on failure
  21. */
  22. static int generated_clk_bind(struct udevice *dev)
  23. {
  24. return at91_clk_sub_device_bind(dev, "generic-clk");
  25. }
  26. static const struct udevice_id generated_clk_match[] = {
  27. { .compatible = "atmel,sama5d2-clk-generated" },
  28. {}
  29. };
  30. U_BOOT_DRIVER(generated_clk) = {
  31. .name = "generated-clk",
  32. .id = UCLASS_MISC,
  33. .of_match = generated_clk_match,
  34. .bind = generated_clk_bind,
  35. };
  36. /*-------------------------------------------------------------*/
  37. struct generic_clk_priv {
  38. u32 num_parents;
  39. };
  40. static ulong generic_clk_get_rate(struct clk *clk)
  41. {
  42. struct pmc_platdata *plat = dev_get_platdata(clk->dev);
  43. struct at91_pmc *pmc = plat->reg_base;
  44. struct clk parent;
  45. ulong clk_rate;
  46. u32 tmp, gckdiv;
  47. u8 parent_id;
  48. int ret;
  49. writel(clk->id & AT91_PMC_PCR_PID_MASK, &pmc->pcr);
  50. tmp = readl(&pmc->pcr);
  51. parent_id = (tmp >> AT91_PMC_PCR_GCKCSS_OFFSET) &
  52. AT91_PMC_PCR_GCKCSS_MASK;
  53. gckdiv = (tmp >> AT91_PMC_PCR_GCKDIV_OFFSET) & AT91_PMC_PCR_GCKDIV_MASK;
  54. ret = clk_get_by_index(dev_get_parent(clk->dev), parent_id, &parent);
  55. if (ret)
  56. return 0;
  57. clk_rate = clk_get_rate(&parent) / (gckdiv + 1);
  58. clk_free(&parent);
  59. return clk_rate;
  60. }
  61. static ulong generic_clk_set_rate(struct clk *clk, ulong rate)
  62. {
  63. struct pmc_platdata *plat = dev_get_platdata(clk->dev);
  64. struct at91_pmc *pmc = plat->reg_base;
  65. struct generic_clk_priv *priv = dev_get_priv(clk->dev);
  66. struct clk parent, best_parent;
  67. ulong tmp_rate, best_rate = rate, parent_rate;
  68. int tmp_diff, best_diff = -1;
  69. u32 div, best_div = 0;
  70. u8 best_parent_id = 0;
  71. u8 i;
  72. u32 tmp;
  73. int ret;
  74. for (i = 0; i < priv->num_parents; i++) {
  75. ret = clk_get_by_index(dev_get_parent(clk->dev), i, &parent);
  76. if (ret)
  77. return ret;
  78. parent_rate = clk_get_rate(&parent);
  79. if (IS_ERR_VALUE(parent_rate))
  80. return parent_rate;
  81. for (div = 1; div < GENERATED_MAX_DIV + 2; div++) {
  82. tmp_rate = DIV_ROUND_CLOSEST(parent_rate, div);
  83. if (rate < tmp_rate)
  84. continue;
  85. tmp_diff = rate - tmp_rate;
  86. if (best_diff < 0 || best_diff > tmp_diff) {
  87. best_rate = tmp_rate;
  88. best_diff = tmp_diff;
  89. best_div = div - 1;
  90. best_parent = parent;
  91. best_parent_id = i;
  92. }
  93. if (!best_diff || tmp_rate < rate)
  94. break;
  95. }
  96. if (!best_diff)
  97. break;
  98. }
  99. debug("GCK: best parent: %s, best_rate = %ld, best_div = %d\n",
  100. best_parent.dev->name, best_rate, best_div);
  101. ret = clk_enable(&best_parent);
  102. if (ret)
  103. return ret;
  104. writel(clk->id & AT91_PMC_PCR_PID_MASK, &pmc->pcr);
  105. tmp = readl(&pmc->pcr);
  106. tmp &= ~(AT91_PMC_PCR_GCKDIV | AT91_PMC_PCR_GCKCSS);
  107. tmp |= AT91_PMC_PCR_GCKCSS_(best_parent_id) |
  108. AT91_PMC_PCR_CMD_WRITE |
  109. AT91_PMC_PCR_GCKDIV_(best_div) |
  110. AT91_PMC_PCR_GCKEN;
  111. writel(tmp, &pmc->pcr);
  112. while (!(readl(&pmc->sr) & AT91_PMC_GCKRDY))
  113. ;
  114. return 0;
  115. }
  116. static struct clk_ops generic_clk_ops = {
  117. .of_xlate = at91_clk_of_xlate,
  118. .get_rate = generic_clk_get_rate,
  119. .set_rate = generic_clk_set_rate,
  120. };
  121. static int generic_clk_ofdata_to_platdata(struct udevice *dev)
  122. {
  123. struct generic_clk_priv *priv = dev_get_priv(dev);
  124. u32 cells[GENERATED_SOURCE_MAX];
  125. u32 num_parents;
  126. num_parents = fdtdec_get_int_array_count(gd->fdt_blob,
  127. dev_get_parent(dev)->of_offset,
  128. "clocks", cells,
  129. GENERATED_SOURCE_MAX);
  130. if (!num_parents)
  131. return -1;
  132. priv->num_parents = num_parents;
  133. return 0;
  134. }
  135. U_BOOT_DRIVER(generic_clk) = {
  136. .name = "generic-clk",
  137. .id = UCLASS_CLK,
  138. .probe = at91_clk_probe,
  139. .ofdata_to_platdata = generic_clk_ofdata_to_platdata,
  140. .priv_auto_alloc_size = sizeof(struct generic_clk_priv),
  141. .platdata_auto_alloc_size = sizeof(struct pmc_platdata),
  142. .ops = &generic_clk_ops,
  143. };