clk-vexpress.c 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /*
  2. * This program is free software; you can redistribute it and/or modify
  3. * it under the terms of the GNU General Public License version 2 as
  4. * published by the Free Software Foundation.
  5. *
  6. * This program is distributed in the hope that it will be useful,
  7. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. * GNU General Public License for more details.
  10. *
  11. * Copyright (C) 2012 ARM Limited
  12. */
  13. #include <linux/amba/sp810.h>
  14. #include <linux/clkdev.h>
  15. #include <linux/clk-provider.h>
  16. #include <linux/err.h>
  17. #include <linux/vexpress.h>
  18. static struct clk *vexpress_sp810_timerclken[4];
  19. static DEFINE_SPINLOCK(vexpress_sp810_lock);
  20. static void __init vexpress_sp810_init(void __iomem *base)
  21. {
  22. int i;
  23. if (WARN_ON(!base))
  24. return;
  25. for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++) {
  26. char name[12];
  27. const char *parents[] = {
  28. "v2m:refclk32khz", /* REFCLK */
  29. "v2m:refclk1mhz" /* TIMCLK */
  30. };
  31. snprintf(name, ARRAY_SIZE(name), "timerclken%d", i);
  32. vexpress_sp810_timerclken[i] = clk_register_mux(NULL, name,
  33. parents, 2, 0, base + SCCTRL,
  34. SCCTRL_TIMERENnSEL_SHIFT(i), 1,
  35. 0, &vexpress_sp810_lock);
  36. if (WARN_ON(IS_ERR(vexpress_sp810_timerclken[i])))
  37. break;
  38. }
  39. }
  40. static const char * const vexpress_clk_24mhz_periphs[] __initconst = {
  41. "mb:uart0", "mb:uart1", "mb:uart2", "mb:uart3",
  42. "mb:mmci", "mb:kmi0", "mb:kmi1"
  43. };
  44. void __init vexpress_clk_init(void __iomem *sp810_base)
  45. {
  46. struct clk *clk;
  47. int i;
  48. clk = clk_register_fixed_rate(NULL, "dummy_apb_pclk", NULL,
  49. CLK_IS_ROOT, 0);
  50. WARN_ON(clk_register_clkdev(clk, "apb_pclk", NULL));
  51. clk = clk_register_fixed_rate(NULL, "v2m:clk_24mhz", NULL,
  52. CLK_IS_ROOT, 24000000);
  53. for (i = 0; i < ARRAY_SIZE(vexpress_clk_24mhz_periphs); i++)
  54. WARN_ON(clk_register_clkdev(clk, NULL,
  55. vexpress_clk_24mhz_periphs[i]));
  56. clk = clk_register_fixed_rate(NULL, "v2m:refclk32khz", NULL,
  57. CLK_IS_ROOT, 32768);
  58. WARN_ON(clk_register_clkdev(clk, NULL, "v2m:wdt"));
  59. clk = clk_register_fixed_rate(NULL, "v2m:refclk1mhz", NULL,
  60. CLK_IS_ROOT, 1000000);
  61. vexpress_sp810_init(sp810_base);
  62. for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++)
  63. WARN_ON(clk_set_parent(vexpress_sp810_timerclken[i], clk));
  64. WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[0],
  65. "v2m-timer0", "sp804"));
  66. WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[1],
  67. "v2m-timer1", "sp804"));
  68. }