107 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			107 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Joshua Henderson <joshua.henderson@microchip.com>
 | |
|  * Copyright (C) 2015 Microchip Technology Inc.  All rights reserved.
 | |
|  *
 | |
|  *  This program is free software; you can distribute it and/or modify it
 | |
|  *  under the terms of the GNU General Public License (Version 2) as
 | |
|  *  published by the Free Software Foundation.
 | |
|  *
 | |
|  *  This program is distributed in the hope it will be useful, but WITHOUT
 | |
|  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | |
|  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 | |
|  *  for more details.
 | |
|  */
 | |
| #include <asm/mach-pic32/pic32.h>
 | |
| 
 | |
| #include "pic32mzda.h"
 | |
| 
 | |
| /* Oscillators, PLL & clocks */
 | |
| #define ICLK_MASK	0x00000080
 | |
| #define PLLDIV_MASK	0x00000007
 | |
| #define CUROSC_MASK	0x00000007
 | |
| #define PLLMUL_MASK	0x0000007F
 | |
| #define PB_MASK		0x00000007
 | |
| #define FRC1		0
 | |
| #define FRC2		7
 | |
| #define SPLL		1
 | |
| #define POSC		2
 | |
| #define FRC_CLK		8000000
 | |
| 
 | |
| #define PIC32_POSC_FREQ	24000000
 | |
| 
 | |
| #define OSCCON		0x0000
 | |
| #define SPLLCON		0x0020
 | |
| #define PB1DIV		0x0140
 | |
| 
 | |
| u32 pic32_get_sysclk(void)
 | |
| {
 | |
| 	u32 osc_freq = 0;
 | |
| 	u32 pllclk;
 | |
| 	u32 frcdivn;
 | |
| 	u32 osccon;
 | |
| 	u32 spllcon;
 | |
| 	int curr_osc;
 | |
| 
 | |
| 	u32 plliclk;
 | |
| 	u32 pllidiv;
 | |
| 	u32 pllodiv;
 | |
| 	u32 pllmult;
 | |
| 	u32 frcdiv;
 | |
| 
 | |
| 	void __iomem *osc_base = ioremap(PIC32_BASE_OSC, 0x200);
 | |
| 
 | |
| 	osccon = __raw_readl(osc_base + OSCCON);
 | |
| 	spllcon = __raw_readl(osc_base + SPLLCON);
 | |
| 
 | |
| 	plliclk = (spllcon & ICLK_MASK);
 | |
| 	pllidiv = ((spllcon >> 8) & PLLDIV_MASK) + 1;
 | |
| 	pllodiv = ((spllcon >> 24) & PLLDIV_MASK);
 | |
| 	pllmult = ((spllcon >> 16) & PLLMUL_MASK) + 1;
 | |
| 	frcdiv = ((osccon >> 24) & PLLDIV_MASK);
 | |
| 
 | |
| 	pllclk = plliclk ? FRC_CLK : PIC32_POSC_FREQ;
 | |
| 	frcdivn = ((1 << frcdiv) + 1) + (128 * (frcdiv == 7));
 | |
| 
 | |
| 	if (pllodiv < 2)
 | |
| 		pllodiv = 2;
 | |
| 	else if (pllodiv < 5)
 | |
| 		pllodiv = (1 << pllodiv);
 | |
| 	else
 | |
| 		pllodiv = 32;
 | |
| 
 | |
| 	curr_osc = (int)((osccon >> 12) & CUROSC_MASK);
 | |
| 
 | |
| 	switch (curr_osc) {
 | |
| 	case FRC1:
 | |
| 	case FRC2:
 | |
| 		osc_freq = FRC_CLK / frcdivn;
 | |
| 		break;
 | |
| 	case SPLL:
 | |
| 		osc_freq = ((pllclk / pllidiv) * pllmult) / pllodiv;
 | |
| 		break;
 | |
| 	case POSC:
 | |
| 		osc_freq = PIC32_POSC_FREQ;
 | |
| 		break;
 | |
| 	default:
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	iounmap(osc_base);
 | |
| 
 | |
| 	return osc_freq;
 | |
| }
 | |
| 
 | |
| u32 pic32_get_pbclk(int bus)
 | |
| {
 | |
| 	u32 clk_freq;
 | |
| 	void __iomem *osc_base = ioremap(PIC32_BASE_OSC, 0x200);
 | |
| 	u32 pbxdiv = PB1DIV + ((bus - 1) * 0x10);
 | |
| 	u32 pbdiv = (__raw_readl(osc_base + pbxdiv) & PB_MASK) + 1;
 | |
| 
 | |
| 	iounmap(osc_base);
 | |
| 
 | |
| 	clk_freq = pic32_get_sysclk();
 | |
| 
 | |
| 	return clk_freq / pbdiv;
 | |
| }
 | 
