diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-tegra/tegra2_clocks.c | 64 |
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 */ | ||
1056 | static 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 | |||
1062 | static 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 | |||
1075 | static 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 | |||
1094 | static 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 */ |
1055 | static void tegra2_clk_double_init(struct clk *c) | 1105 | static 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 | ||
2001 | static 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 | ||
2120 | static void tegra2_init_one_clock(struct clk *c) | 2182 | static void tegra2_init_one_clock(struct clk *c) |