early_clk.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /*
  2. * Joshua Henderson <joshua.henderson@microchip.com>
  3. * Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
  4. *
  5. * This program is free software; you can distribute it and/or modify it
  6. * under the terms of the GNU General Public License (Version 2) as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  12. * for more details.
  13. */
  14. #include <asm/mach-pic32/pic32.h>
  15. #include "pic32mzda.h"
  16. /* Oscillators, PLL & clocks */
  17. #define ICLK_MASK 0x00000080
  18. #define PLLDIV_MASK 0x00000007
  19. #define CUROSC_MASK 0x00000007
  20. #define PLLMUL_MASK 0x0000007F
  21. #define PB_MASK 0x00000007
  22. #define FRC1 0
  23. #define FRC2 7
  24. #define SPLL 1
  25. #define POSC 2
  26. #define FRC_CLK 8000000
  27. #define PIC32_POSC_FREQ 24000000
  28. #define OSCCON 0x0000
  29. #define SPLLCON 0x0020
  30. #define PB1DIV 0x0140
  31. u32 pic32_get_sysclk(void)
  32. {
  33. u32 osc_freq = 0;
  34. u32 pllclk;
  35. u32 frcdivn;
  36. u32 osccon;
  37. u32 spllcon;
  38. int curr_osc;
  39. u32 plliclk;
  40. u32 pllidiv;
  41. u32 pllodiv;
  42. u32 pllmult;
  43. u32 frcdiv;
  44. void __iomem *osc_base = ioremap(PIC32_BASE_OSC, 0x200);
  45. osccon = __raw_readl(osc_base + OSCCON);
  46. spllcon = __raw_readl(osc_base + SPLLCON);
  47. plliclk = (spllcon & ICLK_MASK);
  48. pllidiv = ((spllcon >> 8) & PLLDIV_MASK) + 1;
  49. pllodiv = ((spllcon >> 24) & PLLDIV_MASK);
  50. pllmult = ((spllcon >> 16) & PLLMUL_MASK) + 1;
  51. frcdiv = ((osccon >> 24) & PLLDIV_MASK);
  52. pllclk = plliclk ? FRC_CLK : PIC32_POSC_FREQ;
  53. frcdivn = ((1 << frcdiv) + 1) + (128 * (frcdiv == 7));
  54. if (pllodiv < 2)
  55. pllodiv = 2;
  56. else if (pllodiv < 5)
  57. pllodiv = (1 << pllodiv);
  58. else
  59. pllodiv = 32;
  60. curr_osc = (int)((osccon >> 12) & CUROSC_MASK);
  61. switch (curr_osc) {
  62. case FRC1:
  63. case FRC2:
  64. osc_freq = FRC_CLK / frcdivn;
  65. break;
  66. case SPLL:
  67. osc_freq = ((pllclk / pllidiv) * pllmult) / pllodiv;
  68. break;
  69. case POSC:
  70. osc_freq = PIC32_POSC_FREQ;
  71. break;
  72. default:
  73. break;
  74. }
  75. iounmap(osc_base);
  76. return osc_freq;
  77. }
  78. u32 pic32_get_pbclk(int bus)
  79. {
  80. u32 clk_freq;
  81. void __iomem *osc_base = ioremap(PIC32_BASE_OSC, 0x200);
  82. u32 pbxdiv = PB1DIV + ((bus - 1) * 0x10);
  83. u32 pbdiv = (__raw_readl(osc_base + pbxdiv) & PB_MASK) + 1;
  84. iounmap(osc_base);
  85. clk_freq = pic32_get_sysclk();
  86. return clk_freq / pbdiv;
  87. }