aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/pic32/pic32mzda/early_clk.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/pic32/pic32mzda/early_clk.c')
-rw-r--r--arch/mips/pic32/pic32mzda/early_clk.c98
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
28u32 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
86u32 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}