diff options
Diffstat (limited to 'arch/mips/pic32/pic32mzda/early_clk.c')
-rw-r--r-- | arch/mips/pic32/pic32mzda/early_clk.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/arch/mips/pic32/pic32mzda/early_clk.c b/arch/mips/pic32/pic32mzda/early_clk.c new file mode 100644 index 000000000..6001e507d --- /dev/null +++ b/arch/mips/pic32/pic32mzda/early_clk.c | |||
@@ -0,0 +1,98 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /* | ||
3 | * Joshua Henderson <joshua.henderson@microchip.com> | ||
4 | * Copyright (C) 2015 Microchip Technology Inc. All rights reserved. | ||
5 | */ | ||
6 | #include <asm/mach-pic32/pic32.h> | ||
7 | |||
8 | #include "pic32mzda.h" | ||
9 | |||
10 | /* Oscillators, PLL & clocks */ | ||
11 | #define ICLK_MASK 0x00000080 | ||
12 | #define PLLDIV_MASK 0x00000007 | ||
13 | #define CUROSC_MASK 0x00000007 | ||
14 | #define PLLMUL_MASK 0x0000007F | ||
15 | #define PB_MASK 0x00000007 | ||
16 | #define FRC1 0 | ||
17 | #define FRC2 7 | ||
18 | #define SPLL 1 | ||
19 | #define POSC 2 | ||
20 | #define FRC_CLK 8000000 | ||
21 | |||
22 | #define PIC32_POSC_FREQ 24000000 | ||
23 | |||
24 | #define OSCCON 0x0000 | ||
25 | #define SPLLCON 0x0020 | ||
26 | #define PB1DIV 0x0140 | ||
27 | |||
28 | u32 pic32_get_sysclk(void) | ||
29 | { | ||
30 | u32 osc_freq = 0; | ||
31 | u32 pllclk; | ||
32 | u32 frcdivn; | ||
33 | u32 osccon; | ||
34 | u32 spllcon; | ||
35 | int curr_osc; | ||
36 | |||
37 | u32 plliclk; | ||
38 | u32 pllidiv; | ||
39 | u32 pllodiv; | ||
40 | u32 pllmult; | ||
41 | u32 frcdiv; | ||
42 | |||
43 | void __iomem *osc_base = ioremap(PIC32_BASE_OSC, 0x200); | ||
44 | |||
45 | osccon = __raw_readl(osc_base + OSCCON); | ||
46 | spllcon = __raw_readl(osc_base + SPLLCON); | ||
47 | |||
48 | plliclk = (spllcon & ICLK_MASK); | ||
49 | pllidiv = ((spllcon >> 8) & PLLDIV_MASK) + 1; | ||
50 | pllodiv = ((spllcon >> 24) & PLLDIV_MASK); | ||
51 | pllmult = ((spllcon >> 16) & PLLMUL_MASK) + 1; | ||
52 | frcdiv = ((osccon >> 24) & PLLDIV_MASK); | ||
53 | |||
54 | pllclk = plliclk ? FRC_CLK : PIC32_POSC_FREQ; | ||
55 | frcdivn = ((1 << frcdiv) + 1) + (128 * (frcdiv == 7)); | ||
56 | |||
57 | if (pllodiv < 2) | ||
58 | pllodiv = 2; | ||
59 | else if (pllodiv < 5) | ||
60 | pllodiv = (1 << pllodiv); | ||
61 | else | ||
62 | pllodiv = 32; | ||
63 | |||
64 | curr_osc = (int)((osccon >> 12) & CUROSC_MASK); | ||
65 | |||
66 | switch (curr_osc) { | ||
67 | case FRC1: | ||
68 | case FRC2: | ||
69 | osc_freq = FRC_CLK / frcdivn; | ||
70 | break; | ||
71 | case SPLL: | ||
72 | osc_freq = ((pllclk / pllidiv) * pllmult) / pllodiv; | ||
73 | break; | ||
74 | case POSC: | ||
75 | osc_freq = PIC32_POSC_FREQ; | ||
76 | break; | ||
77 | default: | ||
78 | break; | ||
79 | } | ||
80 | |||
81 | iounmap(osc_base); | ||
82 | |||
83 | return osc_freq; | ||
84 | } | ||
85 | |||
86 | u32 pic32_get_pbclk(int bus) | ||
87 | { | ||
88 | u32 clk_freq; | ||
89 | void __iomem *osc_base = ioremap(PIC32_BASE_OSC, 0x200); | ||
90 | u32 pbxdiv = PB1DIV + ((bus - 1) * 0x10); | ||
91 | u32 pbdiv = (__raw_readl(osc_base + pbxdiv) & PB_MASK) + 1; | ||
92 | |||
93 | iounmap(osc_base); | ||
94 | |||
95 | clk_freq = pic32_get_sysclk(); | ||
96 | |||
97 | return clk_freq / pbdiv; | ||
98 | } | ||