Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57ceb4b0 authored by Ganesan Ramalingam's avatar Ganesan Ramalingam Committed by Ralf Baechle
Browse files

MIPS: Netlogic: XLP2XX CPU and PIC frequency



Add code to calculate the CPU and PIC frequency for XLP2XX SoCs.

Since the PIC frequency on XLP2XX can be configured, add a new macro
pic_timer_freq() to be used in netlogic/common/time.c.

Signed-off-by: default avatarJayachandran C <jchandra@broadcom.com>
Cc: linux-mips@linux-mips.org
Cc: Ganesan Ramalingam <ganesanr@broadcom.com>
Patchwork: http://patchwork.linux-mips.org/patch/5701/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 5b6ff35d
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -208,13 +208,14 @@
#define PIC_LOCAL_SCHEDULING		1
#define PIC_GLOBAL_SCHEDULING		0

#define PIC_CLK_HZ			133333333

#define nlm_read_pic_reg(b, r)	nlm_read_reg64(b, r)
#define nlm_write_pic_reg(b, r, v) nlm_write_reg64(b, r, v)
#define nlm_get_pic_pcibase(node) nlm_pcicfg_base(XLP_IO_PIC_OFFSET(node))
#define nlm_get_pic_regbase(node) (nlm_get_pic_pcibase(node) + XLP_IO_PCI_HDRSZ)

/* We use PIC on node 0 as a timer */
#define pic_timer_freq()		nlm_get_pic_frequency(0)

/* IRT and h/w interrupt routines */
static inline int
nlm_pic_read_irt(uint64_t base, int irt_index)
+31 −0
Original line number Diff line number Diff line
@@ -117,6 +117,36 @@
#define SYS_SCRTCH2				0x4b
#define SYS_SCRTCH3				0x4c

/* PLL registers XLP2XX */
#define SYS_PLL_CTRL0				0x240
#define SYS_PLL_CTRL1				0x241
#define SYS_PLL_CTRL2				0x242
#define SYS_PLL_CTRL3				0x243
#define SYS_DMC_PLL_CTRL0			0x244
#define SYS_DMC_PLL_CTRL1			0x245
#define SYS_DMC_PLL_CTRL2			0x246
#define SYS_DMC_PLL_CTRL3			0x247

#define SYS_PLL_CTRL0_DEVX(x)			(0x248 + (x) * 4)
#define SYS_PLL_CTRL1_DEVX(x)			(0x249 + (x) * 4)
#define SYS_PLL_CTRL2_DEVX(x)			(0x24a + (x) * 4)
#define SYS_PLL_CTRL3_DEVX(x)			(0x24b + (x) * 4)

#define SYS_CPU_PLL_CHG_CTRL			0x288
#define SYS_PLL_CHG_CTRL			0x289
#define SYS_CLK_DEV_DIS				0x28a
#define SYS_CLK_DEV_SEL				0x28b
#define SYS_CLK_DEV_DIV				0x28c
#define SYS_CLK_DEV_CHG				0x28d
#define SYS_CLK_DEV_SEL_REG			0x28e
#define SYS_CLK_DEV_DIV_REG			0x28f
#define SYS_CPU_PLL_LOCK			0x29f
#define SYS_SYS_PLL_LOCK			0x2a0
#define SYS_PLL_MEM_CMD				0x2a1
#define SYS_CPU_PLL_MEM_REQ			0x2a2
#define SYS_SYS_PLL_MEM_REQ			0x2a3
#define SYS_PLL_MEM_STAT			0x2a4

#ifndef __ASSEMBLY__

#define nlm_read_sys_reg(b, r)		nlm_read_reg(b, r)
@@ -124,5 +154,6 @@
#define nlm_get_sys_pcibase(node) nlm_pcicfg_base(XLP_IO_SYS_OFFSET(node))
#define nlm_get_sys_regbase(node) (nlm_get_sys_pcibase(node) + XLP_IO_PCI_HDRSZ)

unsigned int nlm_get_pic_frequency(int node);
#endif
#endif
+2 −0
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@
#define _ASM_NLM_XLR_PIC_H

#define PIC_CLK_HZ			66666666
#define pic_timer_freq()		PIC_CLK_HZ

/* PIC hardware interrupt numbers */
#define PIC_IRT_WD_INDEX		0
#define PIC_IRT_TIMER_0_INDEX		1
+2 −1
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@
#if defined(CONFIG_CPU_XLP)
#include <asm/netlogic/xlp-hal/iomap.h>
#include <asm/netlogic/xlp-hal/xlp.h>
#include <asm/netlogic/xlp-hal/sys.h>
#include <asm/netlogic/xlp-hal/pic.h>
#elif defined(CONFIG_CPU_XLR)
#include <asm/netlogic/xlr/iomap.h>
@@ -91,7 +92,7 @@ static void nlm_init_pic_timer(void)
		csrc_pic.read	= nlm_get_pic_timer;
	}
	csrc_pic.rating = 1000;
	clocksource_register_hz(&csrc_pic, PIC_CLK_HZ);
	clocksource_register_hz(&csrc_pic, pic_timer_freq());
}

void __init plat_time_init(void)
+115 −8
Original line number Diff line number Diff line
@@ -127,6 +127,10 @@ unsigned int nlm_get_core_frequency(int node, int core)

	sysbase = nlm_get_node(node)->sysbase;
	rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG);
	if (cpu_is_xlpii()) {
		num = 1000000ULL * (400 * 3 + 100 * (rstval >> 26));
		denom = 3;
	} else {
		dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE);
		pll_divf = ((rstval >> 10) & 0x7f) + 1;
		pll_divr = ((rstval >> 8)  & 0x3) + 1;
@@ -135,10 +139,113 @@ unsigned int nlm_get_core_frequency(int node, int core)

		num = 800000000ULL * pll_divf;
		denom = 3 * pll_divr * ext_div * dfs_div;
	}
	do_div(num, denom);
	return (unsigned int)num;
}

/* Calculate Frequency to the PIC from PLL.
 * freq_out = ( ref_freq/2 * (6 + ctrl2[7:0]) + ctrl2[20:8]/2^13 ) /
 * ((2^ctrl0[7:5]) * Table(ctrl0[26:24]))
 */
static unsigned int nlm_2xx_get_pic_frequency(int node)
{
	u32 ctrl_val0, ctrl_val2, vco_post_div, pll_post_div;
	u32 mdiv, fdiv, pll_out_freq_den, reg_select, ref_div, pic_div;
	u64 ref_clk, sysbase, pll_out_freq_num, ref_clk_select;

	sysbase = nlm_get_node(node)->sysbase;

	/* Find ref_clk_base */
	ref_clk_select =
		(nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG) >> 18) & 0x3;
	switch (ref_clk_select) {
	case 0:
		ref_clk = 200000000ULL;
		ref_div = 3;
		break;
	case 1:
		ref_clk = 100000000ULL;
		ref_div = 1;
		break;
	case 2:
		ref_clk = 125000000ULL;
		ref_div = 1;
		break;
	case 3:
		ref_clk = 400000000ULL;
		ref_div = 3;
		break;
	}

	/* Find the clock source PLL device for PIC */
	reg_select = (nlm_read_sys_reg(sysbase, SYS_CLK_DEV_SEL) >> 22) & 0x3;
	switch (reg_select) {
	case 0:
		ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0);
		ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2);
		break;
	case 1:
		ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(0));
		ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(0));
		break;
	case 2:
		ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(1));
		ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(1));
		break;
	case 3:
		ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(2));
		ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(2));
		break;
	}

	vco_post_div = (ctrl_val0 >> 5) & 0x7;
	pll_post_div = (ctrl_val0 >> 24) & 0x7;
	mdiv = ctrl_val2 & 0xff;
	fdiv = (ctrl_val2 >> 8) & 0xfff;

	/* Find PLL post divider value */
	switch (pll_post_div) {
	case 1:
		pll_post_div = 2;
		break;
	case 3:
		pll_post_div = 4;
		break;
	case 7:
		pll_post_div = 8;
		break;
	case 6:
		pll_post_div = 16;
		break;
	case 0:
	default:
		pll_post_div = 1;
		break;
	}

	fdiv = fdiv/(1 << 13);
	pll_out_freq_num = ((ref_clk >> 1) * (6 + mdiv)) + fdiv;
	pll_out_freq_den = (1 << vco_post_div) * pll_post_div * 3;

	if (pll_out_freq_den > 0)
		do_div(pll_out_freq_num, pll_out_freq_den);

	/* PIC post divider, which happens after PLL */
	pic_div = (nlm_read_sys_reg(sysbase, SYS_CLK_DEV_DIV) >> 22) & 0x3;
	do_div(pll_out_freq_num, 1 << pic_div);

	return pll_out_freq_num;
}

unsigned int nlm_get_pic_frequency(int node)
{
	if (cpu_is_xlpii())
		return nlm_2xx_get_pic_frequency(node);
	else
		return 133333333;
}

unsigned int nlm_get_cpu_frequency(void)
{
	return nlm_get_core_frequency(0, 0);