aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2010-11-22 21:37:54 -0500
committerColin Cross <ccross@android.com>2011-02-21 03:16:45 -0500
commit6d2968284f63efa1d1849165f9e3a80402509212 (patch)
treea7976141d9c595d2becbfc14cfe99f719ec3a4c7 /arch
parentefdf72ad5c42b529286a1991f51badb030043719 (diff)
ARM: tegra: clocks: Add emc scaling
Add clock ops on the emc peripheral clock that call into the emc driver to update the memory controller registers for the new frequency. Tegra has an interlock between the clock controller and the memory controller that prevents the new register values from taking effect until the clock frequency update occurs. Acked-by: Olof Johansson <olof@lixom.net> Signed-off-by: Colin Cross <ccross@android.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c64
1 files changed, 63 insertions, 1 deletions
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index f6f685c4f339..7f7068714049 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -31,6 +31,7 @@
31 31
32#include "clock.h" 32#include "clock.h"
33#include "fuse.h" 33#include "fuse.h"
34#include "tegra2_emc.h"
34 35
35#define RST_DEVICES 0x004 36#define RST_DEVICES 0x004
36#define RST_DEVICES_SET 0x300 37#define RST_DEVICES_SET 0x300
@@ -1051,6 +1052,55 @@ static struct clk_ops tegra_periph_clk_ops = {
1051 .reset = &tegra2_periph_clk_reset, 1052 .reset = &tegra2_periph_clk_reset,
1052}; 1053};
1053 1054
1055/* External memory controller clock ops */
1056static void tegra2_emc_clk_init(struct clk *c)
1057{
1058 tegra2_periph_clk_init(c);
1059 c->max_rate = clk_get_rate_locked(c);
1060}
1061
1062static long tegra2_emc_clk_round_rate(struct clk *c, unsigned long rate)
1063{
1064 long new_rate = rate;
1065
1066 new_rate = tegra_emc_round_rate(new_rate);
1067 if (new_rate < 0)
1068 return c->max_rate;
1069
1070 BUG_ON(new_rate != tegra2_periph_clk_round_rate(c, new_rate));
1071
1072 return new_rate;
1073}
1074
1075static int tegra2_emc_clk_set_rate(struct clk *c, unsigned long rate)
1076{
1077 int ret;
1078 /*
1079 * The Tegra2 memory controller has an interlock with the clock
1080 * block that allows memory shadowed registers to be updated,
1081 * and then transfer them to the main registers at the same
1082 * time as the clock update without glitches.
1083 */
1084 ret = tegra_emc_set_rate(rate);
1085 if (ret < 0)
1086 return ret;
1087
1088 ret = tegra2_periph_clk_set_rate(c, rate);
1089 udelay(1);
1090
1091 return ret;
1092}
1093
1094static struct clk_ops tegra_emc_clk_ops = {
1095 .init = &tegra2_emc_clk_init,
1096 .enable = &tegra2_periph_clk_enable,
1097 .disable = &tegra2_periph_clk_disable,
1098 .set_parent = &tegra2_periph_clk_set_parent,
1099 .set_rate = &tegra2_emc_clk_set_rate,
1100 .round_rate = &tegra2_emc_clk_round_rate,
1101 .reset = &tegra2_periph_clk_reset,
1102};
1103
1054/* Clock doubler ops */ 1104/* Clock doubler ops */
1055static void tegra2_clk_double_init(struct clk *c) 1105static void tegra2_clk_double_init(struct clk *c)
1056{ 1106{
@@ -1948,6 +1998,18 @@ static struct clk_mux_sel mux_pclk[] = {
1948 { 0, 0}, 1998 { 0, 0},
1949}; 1999};
1950 2000
2001static struct clk tegra_clk_emc = {
2002 .name = "emc",
2003 .ops = &tegra_emc_clk_ops,
2004 .reg = 0x19c,
2005 .max_rate = 800000000,
2006 .inputs = mux_pllm_pllc_pllp_clkm,
2007 .flags = MUX | DIV_U71 | PERIPH_EMC_ENB,
2008 .u.periph = {
2009 .clk_num = 57,
2010 },
2011};
2012
1951#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \ 2013#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \
1952 { \ 2014 { \
1953 .name = _name, \ 2015 .name = _name, \
@@ -2039,7 +2101,6 @@ struct clk tegra_list_clks[] = {
2039 PERIPH_CLK("usbd", "fsl-tegra-udc", NULL, 22, 0, 480000000, mux_clk_m, 0), /* requires min voltage */ 2101 PERIPH_CLK("usbd", "fsl-tegra-udc", NULL, 22, 0, 480000000, mux_clk_m, 0), /* requires min voltage */
2040 PERIPH_CLK("usb2", "tegra-ehci.1", NULL, 58, 0, 480000000, mux_clk_m, 0), /* requires min voltage */ 2102 PERIPH_CLK("usb2", "tegra-ehci.1", NULL, 58, 0, 480000000, mux_clk_m, 0), /* requires min voltage */
2041 PERIPH_CLK("usb3", "tegra-ehci.2", NULL, 59, 0, 480000000, mux_clk_m, 0), /* requires min voltage */ 2103 PERIPH_CLK("usb3", "tegra-ehci.2", NULL, 59, 0, 480000000, mux_clk_m, 0), /* requires min voltage */
2042 PERIPH_CLK("emc", "emc", NULL, 57, 0x19c, 800000000, mux_pllm_pllc_pllp_clkm, MUX | DIV_U71 | PERIPH_EMC_ENB),
2043 PERIPH_CLK("dsi", "dsi", NULL, 48, 0, 500000000, mux_plld, 0), /* scales with voltage */ 2104 PERIPH_CLK("dsi", "dsi", NULL, 48, 0, 500000000, mux_plld, 0), /* scales with voltage */
2044 PERIPH_CLK("csi", "tegra_camera", "csi", 52, 0, 72000000, mux_pllp_out3, 0), 2105 PERIPH_CLK("csi", "tegra_camera", "csi", 52, 0, 72000000, mux_pllp_out3, 0),
2045 PERIPH_CLK("isp", "tegra_camera", "isp", 23, 0, 150000000, mux_clk_m, 0), /* same frequency as VI */ 2106 PERIPH_CLK("isp", "tegra_camera", "isp", 23, 0, 150000000, mux_clk_m, 0), /* same frequency as VI */
@@ -2115,6 +2176,7 @@ struct clk *tegra_ptr_clks[] = {
2115 &tegra_dev2_clk, 2176 &tegra_dev2_clk,
2116 &tegra_clk_virtual_cpu, 2177 &tegra_clk_virtual_cpu,
2117 &tegra_clk_blink, 2178 &tegra_clk_blink,
2179 &tegra_clk_emc,
2118}; 2180};
2119 2181
2120static void tegra2_init_one_clock(struct clk *c) 2182static void tegra2_init_one_clock(struct clk *c)