clk-utmi.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2016 Atmel Corporation
  4. * Wenyou.Yang <wenyou.yang@atmel.com>
  5. */
  6. #include <common.h>
  7. #include <clk-uclass.h>
  8. #include <dm.h>
  9. #include <syscon.h>
  10. #include <linux/io.h>
  11. #include <mach/at91_pmc.h>
  12. #include <mach/sama5_sfr.h>
  13. #include "pmc.h"
  14. /*
  15. * The purpose of this clock is to generate a 480 MHz signal. A different
  16. * rate can't be configured.
  17. */
  18. #define UTMI_RATE 480000000
  19. static int utmi_clk_enable(struct clk *clk)
  20. {
  21. struct pmc_platdata *plat = dev_get_platdata(clk->dev);
  22. struct at91_pmc *pmc = plat->reg_base;
  23. struct clk clk_dev;
  24. ulong clk_rate;
  25. u32 utmi_ref_clk_freq;
  26. u32 tmp;
  27. int err;
  28. int timeout = 2000000;
  29. if (readl(&pmc->sr) & AT91_PMC_LOCKU)
  30. return 0;
  31. /*
  32. * If mainck rate is different from 12 MHz, we have to configure the
  33. * FREQ field of the SFR_UTMICKTRIM register to generate properly
  34. * the utmi clock.
  35. */
  36. err = clk_get_by_index(clk->dev, 0, &clk_dev);
  37. if (err)
  38. return -EINVAL;
  39. clk_rate = clk_get_rate(&clk_dev);
  40. switch (clk_rate) {
  41. case 12000000:
  42. utmi_ref_clk_freq = 0;
  43. break;
  44. case 16000000:
  45. utmi_ref_clk_freq = 1;
  46. break;
  47. case 24000000:
  48. utmi_ref_clk_freq = 2;
  49. break;
  50. /*
  51. * Not supported on SAMA5D2 but it's not an issue since MAINCK
  52. * maximum value is 24 MHz.
  53. */
  54. case 48000000:
  55. utmi_ref_clk_freq = 3;
  56. break;
  57. default:
  58. printf("UTMICK: unsupported mainck rate\n");
  59. return -EINVAL;
  60. }
  61. if (plat->regmap_sfr) {
  62. err = regmap_read(plat->regmap_sfr, AT91_SFR_UTMICKTRIM, &tmp);
  63. if (err)
  64. return -EINVAL;
  65. tmp &= ~AT91_UTMICKTRIM_FREQ;
  66. tmp |= utmi_ref_clk_freq;
  67. err = regmap_write(plat->regmap_sfr, AT91_SFR_UTMICKTRIM, tmp);
  68. if (err)
  69. return -EINVAL;
  70. } else if (utmi_ref_clk_freq) {
  71. printf("UTMICK: sfr node required\n");
  72. return -EINVAL;
  73. }
  74. tmp = readl(&pmc->uckr);
  75. tmp |= AT91_PMC_UPLLEN |
  76. AT91_PMC_UPLLCOUNT |
  77. AT91_PMC_BIASEN;
  78. writel(tmp, &pmc->uckr);
  79. while ((--timeout) && !(readl(&pmc->sr) & AT91_PMC_LOCKU))
  80. ;
  81. if (!timeout) {
  82. printf("UTMICK: timeout waiting for UPLL lock\n");
  83. return -ETIMEDOUT;
  84. }
  85. return 0;
  86. }
  87. static ulong utmi_clk_get_rate(struct clk *clk)
  88. {
  89. /* UTMI clk rate is fixed. */
  90. return UTMI_RATE;
  91. }
  92. static struct clk_ops utmi_clk_ops = {
  93. .enable = utmi_clk_enable,
  94. .get_rate = utmi_clk_get_rate,
  95. };
  96. static int utmi_clk_ofdata_to_platdata(struct udevice *dev)
  97. {
  98. struct pmc_platdata *plat = dev_get_platdata(dev);
  99. struct udevice *syscon;
  100. uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
  101. "regmap-sfr", &syscon);
  102. if (syscon)
  103. plat->regmap_sfr = syscon_get_regmap(syscon);
  104. return 0;
  105. }
  106. static int utmi_clk_probe(struct udevice *dev)
  107. {
  108. return at91_pmc_core_probe(dev);
  109. }
  110. static const struct udevice_id utmi_clk_match[] = {
  111. { .compatible = "atmel,at91sam9x5-clk-utmi" },
  112. {}
  113. };
  114. U_BOOT_DRIVER(at91sam9x5_utmi_clk) = {
  115. .name = "at91sam9x5-utmi-clk",
  116. .id = UCLASS_CLK,
  117. .of_match = utmi_clk_match,
  118. .probe = utmi_clk_probe,
  119. .ofdata_to_platdata = utmi_clk_ofdata_to_platdata,
  120. .platdata_auto_alloc_size = sizeof(struct pmc_platdata),
  121. .ops = &utmi_clk_ops,
  122. };