diff options
author | Scott Williams <scwilliams@nvidia.com> | 2012-02-13 17:51:06 -0800 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-02-15 15:41:44 -0800 |
commit | 0b042c720db13bbd042dace487e2e918386a45d4 (patch) | |
tree | 47cb5b5b3040c68aa71ea7dcf40645735e65dc75 | |
parent | 54c4f5a5a87c2ea56f4b2677fe22dde39e6918b3 (diff) |
ARM: tegra: clocks: Consolidate input frequency measurements
Consolidate the functions used to measure the input frequency
into a single implementation and perform the measurement only
once.
Change-Id: I3d13e608a7256d154373542ca001cbda9c03c21b
Signed-off-by: Scott Williams <scwilliams@nvidia.com>
Reviewed-on: http://git-master/r/83613
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>
-rw-r--r-- | arch/arm/mach-tegra/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/clock-common.c | 73 | ||||
-rw-r--r-- | arch/arm/mach-tegra/clock.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra2_clocks.c | 30 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra3_clocks.c | 36 | ||||
-rw-r--r-- | arch/arm/mach-tegra/timer-t2.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/timer-t3.c | 2 |
7 files changed, 79 insertions, 67 deletions
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index b89d656a75f6..7400ee9ae6ec 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -9,6 +9,7 @@ obj-y += io.o obj-y += irq.o obj-$(CONFIG_TEGRA_GRHOST) += syncpt.o obj-y += clock.o +obj-y += clock-common.o obj-y += timer.o ifeq ($(CONFIG_ARCH_TEGRA_2x_SOC),y) obj-y += tegra2_clocks.o diff --git a/arch/arm/mach-tegra/clock-common.c b/arch/arm/mach-tegra/clock-common.c new file mode 100644 index 000000000000..67c5d51378ae --- /dev/null +++ b/arch/arm/mach-tegra/clock-common.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2010-2012 NVIDIA Corporation + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that 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 <linux/kernel.h> +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <linux/io.h> + +#include <mach/clk.h> +#include <mach/iomap.h> + +#include "clock.h" + +#define clk_writel(value, reg) \ + __raw_writel(value, (u32)reg_clk_base + (reg)) +#define clk_readl(reg) \ + __raw_readl((u32)reg_clk_base + (reg)) + +#define OSC_FREQ_DET 0x58 +#define OSC_FREQ_DET_TRIG (1<<31) + +#define OSC_FREQ_DET_STATUS 0x5C +#define OSC_FREQ_DET_BUSY (1<<31) +#define OSC_FREQ_DET_CNT_MASK 0xFFFF + +static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE); +static unsigned long osc_input_freq; + +unsigned long tegra_clk_measure_input_freq(void) +{ + u32 clock_autodetect; + + if (osc_input_freq) + return osc_input_freq; + + clk_writel(OSC_FREQ_DET_TRIG | 1, OSC_FREQ_DET); + do {} while (clk_readl(OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY); + clock_autodetect = clk_readl(OSC_FREQ_DET_STATUS); + + if (clock_autodetect >= 732 - 3 && clock_autodetect <= 732 + 3) + osc_input_freq = 12000000; + else if (clock_autodetect >= 794 - 3 && clock_autodetect <= 794 + 3) + osc_input_freq = 13000000; + else if (clock_autodetect >= 1172 - 3 && clock_autodetect <= 1172 + 3) + osc_input_freq = 19200000; + else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) + osc_input_freq = 26000000; +#ifndef CONFIG_ARCH_TEGRA_2x_SOC + else if (clock_autodetect >= 1025 - 3 && clock_autodetect <= 1025 + 3) + osc_input_freq = 16800000; + else if (clock_autodetect >= 2344 - 3 && clock_autodetect <= 2344 + 3) + osc_input_freq = 38400000; + else if (clock_autodetect >= 2928 - 3 && clock_autodetect <= 2928 + 3) + osc_input_freq = 48000000; +#endif + else { + pr_err("%s: Unexpected clock autodetect value %d", __func__, + clock_autodetect); + BUG(); + } + return osc_input_freq; +} diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h index 36ca521fd2ce..dde9e07292a7 100644 --- a/arch/arm/mach-tegra/clock.h +++ b/arch/arm/mach-tegra/clock.h @@ -231,7 +231,7 @@ void tegra_soc_init_clocks(void); void tegra_init_max_rate(struct clk *c, unsigned long max_rate); void clk_init(struct clk *clk); struct clk *tegra_get_clock_by_name(const char *name); -unsigned long clk_measure_input_freq(void); +unsigned long tegra_clk_measure_input_freq(void); int clk_reparent(struct clk *c, struct clk *parent); void tegra_clk_init_from_table(struct tegra_clk_init_table *table); void clk_set_cansleep(struct clk *c); diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c index a3d0585dff0d..e526c4c46e2e 100644 --- a/arch/arm/mach-tegra/tegra2_clocks.c +++ b/arch/arm/mach-tegra/tegra2_clocks.c @@ -59,13 +59,6 @@ #define OSC_CTRL_OSC_FREQ_26MHZ (3<<30) #define OSC_CTRL_MASK (0x3f2 | OSC_CTRL_OSC_FREQ_MASK) -#define OSC_FREQ_DET 0x58 -#define OSC_FREQ_DET_TRIG (1<<31) - -#define OSC_FREQ_DET_STATUS 0x5C -#define OSC_FREQ_DET_BUSY (1<<31) -#define OSC_FREQ_DET_CNT_MASK 0xFFFF - #define PERIPH_CLK_SOURCE_I2S1 0x100 #define PERIPH_CLK_SOURCE_EMC 0x19c #define PERIPH_CLK_SOURCE_OSC 0x1fc @@ -190,27 +183,6 @@ static int tegra_periph_clk_enable_refcount[3 * 32]; #define chipid_readl() \ __raw_readl((u32)misc_gp_hidrev_base + MISC_GP_HIDREV) -unsigned long clk_measure_input_freq(void) -{ - u32 clock_autodetect; - clk_writel(OSC_FREQ_DET_TRIG | 1, OSC_FREQ_DET); - do {} while (clk_readl(OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY); - clock_autodetect = clk_readl(OSC_FREQ_DET_STATUS); - if (clock_autodetect >= 732 - 3 && clock_autodetect <= 732 + 3) { - return 12000000; - } else if (clock_autodetect >= 794 - 3 && clock_autodetect <= 794 + 3) { - return 13000000; - } else if (clock_autodetect >= 1172 - 3 && clock_autodetect <= 1172 + 3) { - return 19200000; - } else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) { - return 26000000; - } else { - pr_err("%s: Unexpected clock autodetect value %d", __func__, clock_autodetect); - BUG(); - return 0; - } -} - static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate) { s64 divider_u71 = parent_rate * 2; @@ -253,7 +225,7 @@ static unsigned long tegra2_clk_m_autodetect_rate(struct clk *c) { u32 auto_clock_control = clk_readl(OSC_CTRL) & ~OSC_CTRL_OSC_FREQ_MASK; - c->rate = clk_measure_input_freq(); + c->rate = tegra_clk_measure_input_freq(); switch (c->rate) { case 12000000: auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ; diff --git a/arch/arm/mach-tegra/tegra3_clocks.c b/arch/arm/mach-tegra/tegra3_clocks.c index 4a54386c73dc..bbdf191ccd6d 100644 --- a/arch/arm/mach-tegra/tegra3_clocks.c +++ b/arch/arm/mach-tegra/tegra3_clocks.c @@ -100,13 +100,6 @@ #define OSC_CTRL_PLL_REF_DIV_2 (1<<26) #define OSC_CTRL_PLL_REF_DIV_4 (2<<26) -#define OSC_FREQ_DET 0x58 -#define OSC_FREQ_DET_TRIG (1<<31) - -#define OSC_FREQ_DET_STATUS 0x5C -#define OSC_FREQ_DET_BUSY (1<<31) -#define OSC_FREQ_DET_CNT_MASK 0xFFFF - #define PERIPH_CLK_SOURCE_I2S1 0x100 #define PERIPH_CLK_SOURCE_EMC 0x19c #define PERIPH_CLK_SOURCE_OSC 0x1fc @@ -405,33 +398,6 @@ static inline u32 periph_clk_to_reg( return reg; } -unsigned long clk_measure_input_freq(void) -{ - u32 clock_autodetect; - clk_writel(OSC_FREQ_DET_TRIG | 1, OSC_FREQ_DET); - do {} while (clk_readl(OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY); - clock_autodetect = clk_readl(OSC_FREQ_DET_STATUS); - if (clock_autodetect >= 732 - 3 && clock_autodetect <= 732 + 3) { - return 12000000; - } else if (clock_autodetect >= 794 - 3 && clock_autodetect <= 794 + 3) { - return 13000000; - } else if (clock_autodetect >= 1172 - 3 && clock_autodetect <= 1172 + 3) { - return 19200000; - } else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) { - return 26000000; - } else if (clock_autodetect >= 1025 - 3 && clock_autodetect <= 1025 + 3) { - return 16800000; - } else if (clock_autodetect >= 2344 - 3 && clock_autodetect <= 2344 + 3) { - return 38400000; - } else if (clock_autodetect >= 2928 - 3 && clock_autodetect <= 2928 + 3) { - return 48000000; - } else { - pr_err("%s: Unexpected clock autodetect value %d", __func__, clock_autodetect); - BUG(); - return 0; - } -} - static int clk_div_x1_get_divider(unsigned long parent_rate, unsigned long rate, u32 max_x, u32 flags, u32 round_mode) { @@ -498,7 +464,7 @@ static unsigned long tegra3_clk_m_autodetect_rate(struct clk *c) u32 auto_clock_control = osc_ctrl & ~OSC_CTRL_OSC_FREQ_MASK; u32 pll_ref_div = osc_ctrl & OSC_CTRL_PLL_REF_DIV_MASK; - c->rate = clk_measure_input_freq(); + c->rate = tegra_clk_measure_input_freq(); switch (c->rate) { case 12000000: auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ; diff --git a/arch/arm/mach-tegra/timer-t2.c b/arch/arm/mach-tegra/timer-t2.c index dff9abb76272..2d515abef16b 100644 --- a/arch/arm/mach-tegra/timer-t2.c +++ b/arch/arm/mach-tegra/timer-t2.c @@ -95,7 +95,7 @@ unsigned long tegra2_lp2_timer_remain(void) void __init tegra2_init_timer(u32 *offset, int *irq) { - unsigned long rate = clk_measure_input_freq(); + unsigned long rate = tegra_clk_measure_input_freq(); int ret; switch (rate) { diff --git a/arch/arm/mach-tegra/timer-t3.c b/arch/arm/mach-tegra/timer-t3.c index cc8d540bcdca..0f6afc831dd5 100644 --- a/arch/arm/mach-tegra/timer-t3.c +++ b/arch/arm/mach-tegra/timer-t3.c @@ -221,7 +221,7 @@ unsigned long tegra3_lp2_timer_remain(void) void __init tegra3_init_timer(u32 *offset, int *irq) { - unsigned long rate = clk_measure_input_freq(); + unsigned long rate = tegra_clk_measure_input_freq(); switch (rate) { case 12000000: |