blob: 96c090e9d637feb57bd7ca95c720fb21fc186e33 [file] [log] [blame]
Joshua Henderson2572f002016-01-13 18:15:39 -07001/*
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
16#include "pic32mzda.h"
17
18/* Oscillators, PLL & clocks */
19#define ICLK_MASK 0x00000080
20#define PLLDIV_MASK 0x00000007
21#define CUROSC_MASK 0x00000007
22#define PLLMUL_MASK 0x0000007F
23#define PB_MASK 0x00000007
24#define FRC1 0
25#define FRC2 7
26#define SPLL 1
27#define POSC 2
28#define FRC_CLK 8000000
29
30#define PIC32_POSC_FREQ 24000000
31
32#define OSCCON 0x0000
33#define SPLLCON 0x0020
34#define PB1DIV 0x0140
35
36u32 pic32_get_sysclk(void)
37{
38 u32 osc_freq = 0;
39 u32 pllclk;
40 u32 frcdivn;
41 u32 osccon;
42 u32 spllcon;
43 int curr_osc;
44
45 u32 plliclk;
46 u32 pllidiv;
47 u32 pllodiv;
48 u32 pllmult;
49 u32 frcdiv;
50
51 void __iomem *osc_base = ioremap(PIC32_BASE_OSC, 0x200);
52
53 osccon = __raw_readl(osc_base + OSCCON);
54 spllcon = __raw_readl(osc_base + SPLLCON);
55
56 plliclk = (spllcon & ICLK_MASK);
57 pllidiv = ((spllcon >> 8) & PLLDIV_MASK) + 1;
58 pllodiv = ((spllcon >> 24) & PLLDIV_MASK);
59 pllmult = ((spllcon >> 16) & PLLMUL_MASK) + 1;
60 frcdiv = ((osccon >> 24) & PLLDIV_MASK);
61
62 pllclk = plliclk ? FRC_CLK : PIC32_POSC_FREQ;
63 frcdivn = ((1 << frcdiv) + 1) + (128 * (frcdiv == 7));
64
65 if (pllodiv < 2)
66 pllodiv = 2;
67 else if (pllodiv < 5)
68 pllodiv = (1 << pllodiv);
69 else
70 pllodiv = 32;
71
72 curr_osc = (int)((osccon >> 12) & CUROSC_MASK);
73
74 switch (curr_osc) {
75 case FRC1:
76 case FRC2:
77 osc_freq = FRC_CLK / frcdivn;
78 break;
79 case SPLL:
80 osc_freq = ((pllclk / pllidiv) * pllmult) / pllodiv;
81 break;
82 case POSC:
83 osc_freq = PIC32_POSC_FREQ;
84 break;
85 default:
86 break;
87 }
88
89 iounmap(osc_base);
90
91 return osc_freq;
92}
93
94u32 pic32_get_pbclk(int bus)
95{
96 u32 clk_freq;
97 void __iomem *osc_base = ioremap(PIC32_BASE_OSC, 0x200);
98 u32 pbxdiv = PB1DIV + ((bus - 1) * 0x10);
99 u32 pbdiv = (__raw_readl(osc_base + pbxdiv) & PB_MASK) + 1;
100
101 iounmap(osc_base);
102
103 clk_freq = pic32_get_sysclk();
104
105 return clk_freq / pbdiv;
106}