Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/mips/pic32/pic32mzda/early_clk.c
26583 views
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
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
}
99
100