clk-impd1.c 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. * Clock driver for the ARM Integrator/IM-PD1 board
  3. * Copyright (C) 2012 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/clk.h>
  11. #include <linux/clkdev.h>
  12. #include <linux/err.h>
  13. #include <linux/io.h>
  14. #include <linux/platform_data/clk-integrator.h>
  15. #include <mach/impd1.h>
  16. #include "clk-icst.h"
  17. struct impd1_clk {
  18. struct clk *vcoclk;
  19. struct clk *uartclk;
  20. struct clk_lookup *clks[3];
  21. };
  22. static struct impd1_clk impd1_clks[4];
  23. /*
  24. * There are two VCO's on the IM-PD1 but only one is used by the
  25. * kernel, that is why we are only implementing the control of
  26. * IMPD1_OSC1 here.
  27. */
  28. static const struct icst_params impd1_vco_params = {
  29. .ref = 24000000, /* 24 MHz */
  30. .vco_max = ICST525_VCO_MAX_3V,
  31. .vco_min = ICST525_VCO_MIN,
  32. .vd_min = 12,
  33. .vd_max = 519,
  34. .rd_min = 3,
  35. .rd_max = 120,
  36. .s2div = icst525_s2div,
  37. .idx2s = icst525_idx2s,
  38. };
  39. static const struct clk_icst_desc impd1_icst1_desc = {
  40. .params = &impd1_vco_params,
  41. .vco_offset = IMPD1_OSC1,
  42. .lock_offset = IMPD1_LOCK,
  43. };
  44. /**
  45. * integrator_impd1_clk_init() - set up the integrator clock tree
  46. * @base: base address of the logic module (LM)
  47. * @id: the ID of this LM
  48. */
  49. void integrator_impd1_clk_init(void __iomem *base, unsigned int id)
  50. {
  51. struct impd1_clk *imc;
  52. struct clk *clk;
  53. int i;
  54. if (id > 3) {
  55. pr_crit("no more than 4 LMs can be attached\n");
  56. return;
  57. }
  58. imc = &impd1_clks[id];
  59. clk = icst_clk_register(NULL, &impd1_icst1_desc, base);
  60. imc->vcoclk = clk;
  61. imc->clks[0] = clkdev_alloc(clk, NULL, "lm%x:01000", id);
  62. /* UART reference clock */
  63. clk = clk_register_fixed_rate(NULL, "uartclk", NULL, CLK_IS_ROOT,
  64. 14745600);
  65. imc->uartclk = clk;
  66. imc->clks[1] = clkdev_alloc(clk, NULL, "lm%x:00100", id);
  67. imc->clks[2] = clkdev_alloc(clk, NULL, "lm%x:00200", id);
  68. for (i = 0; i < ARRAY_SIZE(imc->clks); i++)
  69. clkdev_add(imc->clks[i]);
  70. }
  71. void integrator_impd1_clk_exit(unsigned int id)
  72. {
  73. int i;
  74. struct impd1_clk *imc;
  75. if (id > 3)
  76. return;
  77. imc = &impd1_clks[id];
  78. for (i = 0; i < ARRAY_SIZE(imc->clks); i++)
  79. clkdev_drop(imc->clks[i]);
  80. clk_unregister(imc->uartclk);
  81. clk_unregister(imc->vcoclk);
  82. }