clk-impd1.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * Clock driver for the ARM Integrator/IM-PD1 board
  3. * Copyright (C) 2012-2013 Linus Walleij
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. */
  9. #include <linux/clk-provider.h>
  10. #include <linux/clkdev.h>
  11. #include <linux/err.h>
  12. #include <linux/io.h>
  13. #include <linux/platform_data/clk-integrator.h>
  14. #include "clk-icst.h"
  15. #define IMPD1_OSC1 0x00
  16. #define IMPD1_OSC2 0x04
  17. #define IMPD1_LOCK 0x08
  18. struct impd1_clk {
  19. char *pclkname;
  20. struct clk *pclk;
  21. char *vco1name;
  22. struct clk *vco1clk;
  23. char *vco2name;
  24. struct clk *vco2clk;
  25. struct clk *mmciclk;
  26. char *uartname;
  27. struct clk *uartclk;
  28. char *spiname;
  29. struct clk *spiclk;
  30. char *scname;
  31. struct clk *scclk;
  32. struct clk_lookup *clks[15];
  33. };
  34. /* One entry for each connected IM-PD1 LM */
  35. static struct impd1_clk impd1_clks[4];
  36. /*
  37. * There are two VCO's on the IM-PD1
  38. */
  39. static const struct icst_params impd1_vco1_params = {
  40. .ref = 24000000, /* 24 MHz */
  41. .vco_max = ICST525_VCO_MAX_3V,
  42. .vco_min = ICST525_VCO_MIN,
  43. .vd_min = 12,
  44. .vd_max = 519,
  45. .rd_min = 3,
  46. .rd_max = 120,
  47. .s2div = icst525_s2div,
  48. .idx2s = icst525_idx2s,
  49. };
  50. static const struct clk_icst_desc impd1_icst1_desc = {
  51. .params = &impd1_vco1_params,
  52. .vco_offset = IMPD1_OSC1,
  53. .lock_offset = IMPD1_LOCK,
  54. };
  55. static const struct icst_params impd1_vco2_params = {
  56. .ref = 24000000, /* 24 MHz */
  57. .vco_max = ICST525_VCO_MAX_3V,
  58. .vco_min = ICST525_VCO_MIN,
  59. .vd_min = 12,
  60. .vd_max = 519,
  61. .rd_min = 3,
  62. .rd_max = 120,
  63. .s2div = icst525_s2div,
  64. .idx2s = icst525_idx2s,
  65. };
  66. static const struct clk_icst_desc impd1_icst2_desc = {
  67. .params = &impd1_vco2_params,
  68. .vco_offset = IMPD1_OSC2,
  69. .lock_offset = IMPD1_LOCK,
  70. };
  71. /**
  72. * integrator_impd1_clk_init() - set up the integrator clock tree
  73. * @base: base address of the logic module (LM)
  74. * @id: the ID of this LM
  75. */
  76. void integrator_impd1_clk_init(void __iomem *base, unsigned int id)
  77. {
  78. struct impd1_clk *imc;
  79. struct clk *clk;
  80. struct clk *pclk;
  81. int i;
  82. if (id > 3) {
  83. pr_crit("no more than 4 LMs can be attached\n");
  84. return;
  85. }
  86. imc = &impd1_clks[id];
  87. /* Register the fixed rate PCLK */
  88. imc->pclkname = kasprintf(GFP_KERNEL, "lm%x-pclk", id);
  89. pclk = clk_register_fixed_rate(NULL, imc->pclkname, NULL, 0, 0);
  90. imc->pclk = pclk;
  91. imc->vco1name = kasprintf(GFP_KERNEL, "lm%x-vco1", id);
  92. clk = icst_clk_register(NULL, &impd1_icst1_desc, imc->vco1name, NULL,
  93. base);
  94. imc->vco1clk = clk;
  95. imc->clks[0] = clkdev_alloc(pclk, "apb_pclk", "lm%x:01000", id);
  96. imc->clks[1] = clkdev_alloc(clk, NULL, "lm%x:01000", id);
  97. /* VCO2 is also called "CLK2" */
  98. imc->vco2name = kasprintf(GFP_KERNEL, "lm%x-vco2", id);
  99. clk = icst_clk_register(NULL, &impd1_icst2_desc, imc->vco2name, NULL,
  100. base);
  101. imc->vco2clk = clk;
  102. /* MMCI uses CLK2 right off */
  103. imc->clks[2] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00700", id);
  104. imc->clks[3] = clkdev_alloc(clk, NULL, "lm%x:00700", id);
  105. /* UART reference clock divides CLK2 by a fixed factor 4 */
  106. imc->uartname = kasprintf(GFP_KERNEL, "lm%x-uartclk", id);
  107. clk = clk_register_fixed_factor(NULL, imc->uartname, imc->vco2name,
  108. CLK_IGNORE_UNUSED, 1, 4);
  109. imc->uartclk = clk;
  110. imc->clks[4] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00100", id);
  111. imc->clks[5] = clkdev_alloc(clk, NULL, "lm%x:00100", id);
  112. imc->clks[6] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00200", id);
  113. imc->clks[7] = clkdev_alloc(clk, NULL, "lm%x:00200", id);
  114. /* SPI PL022 clock divides CLK2 by a fixed factor 64 */
  115. imc->spiname = kasprintf(GFP_KERNEL, "lm%x-spiclk", id);
  116. clk = clk_register_fixed_factor(NULL, imc->spiname, imc->vco2name,
  117. CLK_IGNORE_UNUSED, 1, 64);
  118. imc->clks[8] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00300", id);
  119. imc->clks[9] = clkdev_alloc(clk, NULL, "lm%x:00300", id);
  120. /* The GPIO blocks and AACI have only PCLK */
  121. imc->clks[10] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00400", id);
  122. imc->clks[11] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00500", id);
  123. imc->clks[12] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00800", id);
  124. /* Smart Card clock divides CLK2 by a fixed factor 4 */
  125. imc->scname = kasprintf(GFP_KERNEL, "lm%x-scclk", id);
  126. clk = clk_register_fixed_factor(NULL, imc->scname, imc->vco2name,
  127. CLK_IGNORE_UNUSED, 1, 4);
  128. imc->scclk = clk;
  129. imc->clks[13] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00600", id);
  130. imc->clks[14] = clkdev_alloc(clk, NULL, "lm%x:00600", id);
  131. for (i = 0; i < ARRAY_SIZE(imc->clks); i++)
  132. clkdev_add(imc->clks[i]);
  133. }
  134. EXPORT_SYMBOL_GPL(integrator_impd1_clk_init);
  135. void integrator_impd1_clk_exit(unsigned int id)
  136. {
  137. int i;
  138. struct impd1_clk *imc;
  139. if (id > 3)
  140. return;
  141. imc = &impd1_clks[id];
  142. for (i = 0; i < ARRAY_SIZE(imc->clks); i++)
  143. clkdev_drop(imc->clks[i]);
  144. clk_unregister(imc->spiclk);
  145. clk_unregister(imc->uartclk);
  146. clk_unregister(imc->vco2clk);
  147. clk_unregister(imc->vco1clk);
  148. clk_unregister(imc->pclk);
  149. kfree(imc->scname);
  150. kfree(imc->spiname);
  151. kfree(imc->uartname);
  152. kfree(imc->vco2name);
  153. kfree(imc->vco1name);
  154. kfree(imc->pclkname);
  155. }
  156. EXPORT_SYMBOL_GPL(integrator_impd1_clk_exit);