1 // SPDX-License-Identifier: GPL-2.0-only
3 * Joshua Henderson <joshua.henderson@microchip.com>
4 * Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
6 #include <asm/mach-pic32/pic32.h>
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
20 #define FRC_CLK 8000000
22 #define PIC32_POSC_FREQ 24000000
25 #define SPLLCON 0x0020
28 u32 pic32_get_sysclk(void)
43 void __iomem *osc_base = ioremap(PIC32_BASE_OSC, 0x200);
45 osccon = __raw_readl(osc_base + OSCCON);
46 spllcon = __raw_readl(osc_base + SPLLCON);
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);
54 pllclk = plliclk ? FRC_CLK : PIC32_POSC_FREQ;
55 frcdivn = ((1 << frcdiv) + 1) + (128 * (frcdiv == 7));
60 pllodiv = (1 << pllodiv);
64 curr_osc = (int)((osccon >> 12) & CUROSC_MASK);
69 osc_freq = FRC_CLK / frcdivn;
72 osc_freq = ((pllclk / pllidiv) * pllmult) / pllodiv;
75 osc_freq = PIC32_POSC_FREQ;
86 u32 pic32_get_pbclk(int bus)
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;
95 clk_freq = pic32_get_sysclk();
97 return clk_freq / pbdiv;