clock-sh4.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * arch/sh/kernel/cpu/sh4/clock-sh4.c
  4. *
  5. * Generic SH-4 support for the clock framework
  6. *
  7. * Copyright (C) 2005 Paul Mundt
  8. *
  9. * FRQCR parsing hacked out of arch/sh/kernel/time.c
  10. *
  11. * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
  12. * Copyright (C) 2000 Philipp Rumpf <[email protected]>
  13. * Copyright (C) 2002, 2003, 2004 Paul Mundt
  14. * Copyright (C) 2002 M. R. Brown <[email protected]>
  15. */
  16. #include <linux/init.h>
  17. #include <linux/kernel.h>
  18. #include <asm/clock.h>
  19. #include <asm/freq.h>
  20. #include <asm/io.h>
  21. static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 1, 1 };
  22. #define bfc_divisors ifc_divisors /* Same */
  23. static int pfc_divisors[] = { 2, 3, 4, 6, 8, 2, 2, 2 };
  24. static void master_clk_init(struct clk *clk)
  25. {
  26. clk->rate *= pfc_divisors[__raw_readw(FRQCR) & 0x0007];
  27. }
  28. static struct sh_clk_ops sh4_master_clk_ops = {
  29. .init = master_clk_init,
  30. };
  31. static unsigned long module_clk_recalc(struct clk *clk)
  32. {
  33. int idx = (__raw_readw(FRQCR) & 0x0007);
  34. return clk->parent->rate / pfc_divisors[idx];
  35. }
  36. static struct sh_clk_ops sh4_module_clk_ops = {
  37. .recalc = module_clk_recalc,
  38. };
  39. static unsigned long bus_clk_recalc(struct clk *clk)
  40. {
  41. int idx = (__raw_readw(FRQCR) >> 3) & 0x0007;
  42. return clk->parent->rate / bfc_divisors[idx];
  43. }
  44. static struct sh_clk_ops sh4_bus_clk_ops = {
  45. .recalc = bus_clk_recalc,
  46. };
  47. static unsigned long cpu_clk_recalc(struct clk *clk)
  48. {
  49. int idx = (__raw_readw(FRQCR) >> 6) & 0x0007;
  50. return clk->parent->rate / ifc_divisors[idx];
  51. }
  52. static struct sh_clk_ops sh4_cpu_clk_ops = {
  53. .recalc = cpu_clk_recalc,
  54. };
  55. static struct sh_clk_ops *sh4_clk_ops[] = {
  56. &sh4_master_clk_ops,
  57. &sh4_module_clk_ops,
  58. &sh4_bus_clk_ops,
  59. &sh4_cpu_clk_ops,
  60. };
  61. void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
  62. {
  63. if (idx < ARRAY_SIZE(sh4_clk_ops))
  64. *ops = sh4_clk_ops[idx];
  65. }