diff mbox

[U-Boot,2/6] ARM: tegra: Implement clk_m

Message ID 1440063743-22838-2-git-send-email-thierry.reding@gmail.com
State Accepted
Delegated to: Tom Warren
Headers show

Commit Message

Thierry Reding Aug. 20, 2015, 9:42 a.m. UTC
From: Thierry Reding <treding@nvidia.com>

On currently supported SoCs, clk_m always runs at the same frequency as
the oscillator input. However newer SoC generations such as Tegra210 no
longer have that restriction. Prepare for that by separating clk_m from
the oscillator clock and allow SoC code to override the clk_m rate.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 arch/arm/include/asm/arch-tegra/clock.h           |  3 +++
 arch/arm/include/asm/arch-tegra114/clock-tables.h |  1 +
 arch/arm/include/asm/arch-tegra124/clock-tables.h |  1 +
 arch/arm/include/asm/arch-tegra20/clock-tables.h  |  1 +
 arch/arm/include/asm/arch-tegra210/clock-tables.h |  1 +
 arch/arm/include/asm/arch-tegra30/clock-tables.h  |  1 +
 arch/arm/mach-tegra/clock.c                       | 10 ++++++++++
 arch/arm/mach-tegra/tegra210/clock.c              | 11 +++++++++++
 8 files changed, 29 insertions(+)

Comments

Stephen Warren Aug. 20, 2015, 2:58 p.m. UTC | #1
On 08/20/2015 03:42 AM, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> On currently supported SoCs, clk_m always runs at the same frequency as
> the oscillator input. However newer SoC generations such as Tegra210 no
> longer have that restriction. Prepare for that by separating clk_m from
> the oscillator clock and allow SoC code to override the clk_m rate.

> diff --git a/arch/arm/include/asm/arch-tegra114/clock-tables.h b/arch/arm/include/asm/arch-tegra114/clock-tables.h
> index d8fa0e1d2cee..3f910f5ae8b9 100644
> --- a/arch/arm/include/asm/arch-tegra114/clock-tables.h
> +++ b/arch/arm/include/asm/arch-tegra114/clock-tables.h
> @@ -38,6 +38,7 @@ enum clock_id {
>   	/* These are the base clocks (inputs to the Tegra SOC) */
>   	CLOCK_ID_32KHZ,
>   	CLOCK_ID_OSC,
> +	CLOCK_ID_CLK_M,
>
>   	CLOCK_ID_COUNT,	/* number of PLLs */
>   	CLOCK_ID_DISPLAY2,	/* placeholder */

clock.h contains the following:

/* Number of PLL-based clocks (i.e. not OSC or 32KHz) */
#define CLOCK_ID_PLL_COUNT	(CLOCK_ID_COUNT - 2)

... which would need to be updated. Related, see internal bug number 
1676978 to see if any of the other gotchas there affect this patch.
diff mbox

Patch

diff --git a/arch/arm/include/asm/arch-tegra/clock.h b/arch/arm/include/asm/arch-tegra/clock.h
index d570d7f134a8..eb07c4a07522 100644
--- a/arch/arm/include/asm/arch-tegra/clock.h
+++ b/arch/arm/include/asm/arch-tegra/clock.h
@@ -44,6 +44,9 @@  enum {
 /* return the current oscillator clock frequency */
 enum clock_osc_freq clock_get_osc_freq(void);
 
+/* return the clk_m frequency */
+unsigned int clk_m_get_rate(unsigned int parent_rate);
+
 /**
  * Start PLL using the provided configuration parameters.
  *
diff --git a/arch/arm/include/asm/arch-tegra114/clock-tables.h b/arch/arm/include/asm/arch-tegra114/clock-tables.h
index d8fa0e1d2cee..3f910f5ae8b9 100644
--- a/arch/arm/include/asm/arch-tegra114/clock-tables.h
+++ b/arch/arm/include/asm/arch-tegra114/clock-tables.h
@@ -38,6 +38,7 @@  enum clock_id {
 	/* These are the base clocks (inputs to the Tegra SOC) */
 	CLOCK_ID_32KHZ,
 	CLOCK_ID_OSC,
+	CLOCK_ID_CLK_M,
 
 	CLOCK_ID_COUNT,	/* number of PLLs */
 	CLOCK_ID_DISPLAY2,	/* placeholder */
diff --git a/arch/arm/include/asm/arch-tegra124/clock-tables.h b/arch/arm/include/asm/arch-tegra124/clock-tables.h
index 3c67e72afe89..9466b4ffb33e 100644
--- a/arch/arm/include/asm/arch-tegra124/clock-tables.h
+++ b/arch/arm/include/asm/arch-tegra124/clock-tables.h
@@ -30,6 +30,7 @@  enum clock_id {
 	/* These are the base clocks (inputs to the Tegra SoC) */
 	CLOCK_ID_32KHZ,
 	CLOCK_ID_OSC,
+	CLOCK_ID_CLK_M,
 
 	CLOCK_ID_COUNT,	/* number of PLLs */
 
diff --git a/arch/arm/include/asm/arch-tegra20/clock-tables.h b/arch/arm/include/asm/arch-tegra20/clock-tables.h
index 894be088cde2..812e8760d0cd 100644
--- a/arch/arm/include/asm/arch-tegra20/clock-tables.h
+++ b/arch/arm/include/asm/arch-tegra20/clock-tables.h
@@ -29,6 +29,7 @@  enum clock_id {
 	/* These are the base clocks (inputs to the Tegra SOC) */
 	CLOCK_ID_32KHZ,
 	CLOCK_ID_OSC,
+	CLOCK_ID_CLK_M,
 
 	CLOCK_ID_COUNT,	/* number of clocks */
 	CLOCK_ID_NONE = -1,
diff --git a/arch/arm/include/asm/arch-tegra210/clock-tables.h b/arch/arm/include/asm/arch-tegra210/clock-tables.h
index 175040dae618..a612485d8e23 100644
--- a/arch/arm/include/asm/arch-tegra210/clock-tables.h
+++ b/arch/arm/include/asm/arch-tegra210/clock-tables.h
@@ -30,6 +30,7 @@  enum clock_id {
 	/* These are the base clocks (inputs to the Tegra SoC) */
 	CLOCK_ID_32KHZ,
 	CLOCK_ID_OSC,
+	CLOCK_ID_CLK_M,
 
 	CLOCK_ID_COUNT,	/* number of PLLs */
 
diff --git a/arch/arm/include/asm/arch-tegra30/clock-tables.h b/arch/arm/include/asm/arch-tegra30/clock-tables.h
index cb619f1f2d61..f7c7af80faaf 100644
--- a/arch/arm/include/asm/arch-tegra30/clock-tables.h
+++ b/arch/arm/include/asm/arch-tegra30/clock-tables.h
@@ -38,6 +38,7 @@  enum clock_id {
 	/* These are the base clocks (inputs to the Tegra SOC) */
 	CLOCK_ID_32KHZ,
 	CLOCK_ID_OSC,
+	CLOCK_ID_CLK_M,
 
 	CLOCK_ID_COUNT,	/* number of PLLs */
 	CLOCK_ID_DISPLAY2,	/* Tegra3, placeholder */
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index f9dfcd04115a..41e7de95a2e3 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -461,6 +461,11 @@  void reset_cmplx_set_enable(int cpu, int which, int reset)
 		writel(mask, &clkrst->crc_cpu_cmplx_clr);
 }
 
+unsigned int __weak clk_m_get_rate(unsigned int parent_rate)
+{
+	return parent_rate;
+}
+
 unsigned clock_get_rate(enum clock_id clkid)
 {
 	struct clk_pll *pll;
@@ -472,6 +477,9 @@  unsigned clock_get_rate(enum clock_id clkid)
 	if (clkid == CLOCK_ID_OSC)
 		return parent_rate;
 
+	if (clkid == CLOCK_ID_CLK_M)
+		return clk_m_get_rate(parent_rate);
+
 	pll = get_pll(clkid);
 	if (!pll)
 		return 0;
@@ -613,8 +621,10 @@  void clock_init(void)
 	pll_rate[CLOCK_ID_XCPU] = clock_get_rate(CLOCK_ID_XCPU);
 	pll_rate[CLOCK_ID_SFROM32KHZ] = 32768;
 	pll_rate[CLOCK_ID_OSC] = clock_get_rate(CLOCK_ID_OSC);
+	pll_rate[CLOCK_ID_CLK_M] = clock_get_rate(CLOCK_ID_CLK_M);
 
 	debug("Osc = %d\n", pll_rate[CLOCK_ID_OSC]);
+	debug("CLKM = %d\n", pll_rate[CLOCK_ID_CLK_M]);
 	debug("PLLC = %d\n", pll_rate[CLOCK_ID_CGENERAL]);
 	debug("PLLM = %d\n", pll_rate[CLOCK_ID_MEMORY]);
 	debug("PLLP = %d\n", pll_rate[CLOCK_ID_PERIPH]);
diff --git a/arch/arm/mach-tegra/tegra210/clock.c b/arch/arm/mach-tegra/tegra210/clock.c
index 830a33ffc938..146bb6453a19 100644
--- a/arch/arm/mach-tegra/tegra210/clock.c
+++ b/arch/arm/mach-tegra/tegra210/clock.c
@@ -998,6 +998,17 @@  void clock_early_init(void)
 	udelay(2);
 }
 
+unsigned int clk_m_get_rate(unsigned parent_rate)
+{
+	struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+	u32 value, div;
+
+	value = readl(&clkrst->crc_spare_reg0);
+	div = ((value >> 2) & 0x3) + 1;
+
+	return parent_rate / div;
+}
+
 void arch_timer_init(void)
 {
 	struct sysctr_ctlr *sysctr = (struct sysctr_ctlr *)NV_PA_TSC_BASE;