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