early_clk.c 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Joshua Henderson <[email protected]>
  4. * Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
  5. */
  6. #include <asm/mach-pic32/pic32.h>
  7. #include "pic32mzda.h"
  8. /* Oscillators, PLL & clocks */
  9. #define ICLK_MASK 0x00000080
  10. #define PLLDIV_MASK 0x00000007
  11. #define CUROSC_MASK 0x00000007
  12. #define PLLMUL_MASK 0x0000007F
  13. #define PB_MASK 0x00000007
  14. #define FRC1 0
  15. #define FRC2 7
  16. #define SPLL 1
  17. #define POSC 2
  18. #define FRC_CLK 8000000
  19. #define PIC32_POSC_FREQ 24000000
  20. #define OSCCON 0x0000
  21. #define SPLLCON 0x0020
  22. #define PB1DIV 0x0140
  23. u32 pic32_get_sysclk(void)
  24. {
  25. u32 osc_freq = 0;
  26. u32 pllclk;
  27. u32 frcdivn;
  28. u32 osccon;
  29. u32 spllcon;
  30. int curr_osc;
  31. u32 plliclk;
  32. u32 pllidiv;
  33. u32 pllodiv;
  34. u32 pllmult;
  35. u32 frcdiv;
  36. void __iomem *osc_base = ioremap(PIC32_BASE_OSC, 0x200);
  37. osccon = __raw_readl(osc_base + OSCCON);
  38. spllcon = __raw_readl(osc_base + SPLLCON);
  39. plliclk = (spllcon & ICLK_MASK);
  40. pllidiv = ((spllcon >> 8) & PLLDIV_MASK) + 1;
  41. pllodiv = ((spllcon >> 24) & PLLDIV_MASK);
  42. pllmult = ((spllcon >> 16) & PLLMUL_MASK) + 1;
  43. frcdiv = ((osccon >> 24) & PLLDIV_MASK);
  44. pllclk = plliclk ? FRC_CLK : PIC32_POSC_FREQ;
  45. frcdivn = ((1 << frcdiv) + 1) + (128 * (frcdiv == 7));
  46. if (pllodiv < 2)
  47. pllodiv = 2;
  48. else if (pllodiv < 5)
  49. pllodiv = (1 << pllodiv);
  50. else
  51. pllodiv = 32;
  52. curr_osc = (int)((osccon >> 12) & CUROSC_MASK);
  53. switch (curr_osc) {
  54. case FRC1:
  55. case FRC2:
  56. osc_freq = FRC_CLK / frcdivn;
  57. break;
  58. case SPLL:
  59. osc_freq = ((pllclk / pllidiv) * pllmult) / pllodiv;
  60. break;
  61. case POSC:
  62. osc_freq = PIC32_POSC_FREQ;
  63. break;
  64. default:
  65. break;
  66. }
  67. iounmap(osc_base);
  68. return osc_freq;
  69. }
  70. u32 pic32_get_pbclk(int bus)
  71. {
  72. u32 clk_freq;
  73. void __iomem *osc_base = ioremap(PIC32_BASE_OSC, 0x200);
  74. u32 pbxdiv = PB1DIV + ((bus - 1) * 0x10);
  75. u32 pbdiv = (__raw_readl(osc_base + pbxdiv) & PB_MASK) + 1;
  76. iounmap(osc_base);
  77. clk_freq = pic32_get_sysclk();
  78. return clk_freq / pbdiv;
  79. }