.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or modify it |
---|
5 | | - * under the terms and conditions of the GNU General Public License, |
---|
6 | | - * version 2, as published by the Free Software Foundation. |
---|
7 | | - * |
---|
8 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
---|
9 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
10 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
11 | | - * more details. |
---|
12 | | - * |
---|
13 | | - * You should have received a copy of the GNU General Public License |
---|
14 | | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
15 | 4 | */ |
---|
16 | 5 | |
---|
17 | 6 | #include <linux/io.h> |
---|
.. | .. |
---|
162 | 151 | |
---|
163 | 152 | static DEFINE_SPINLOCK(cml_lock); |
---|
164 | 153 | static DEFINE_SPINLOCK(pll_d_lock); |
---|
165 | | -static DEFINE_SPINLOCK(emc_lock); |
---|
166 | 154 | |
---|
167 | 155 | #define TEGRA_INIT_DATA_MUX(_name, _parents, _offset, \ |
---|
168 | 156 | _clk_num, _gate_flags, _clk_id) \ |
---|
.. | .. |
---|
511 | 499 | .freq_table = pll_x_freq_table, |
---|
512 | 500 | .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_DCCON | |
---|
513 | 501 | TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE, |
---|
| 502 | + .pre_rate_change = tegra_cclk_pre_pllx_rate_change, |
---|
| 503 | + .post_rate_change = tegra_cclk_post_pllx_rate_change, |
---|
514 | 504 | }; |
---|
515 | 505 | |
---|
516 | 506 | static struct tegra_clk_pll_params pll_e_params __ro_after_init = { |
---|
.. | .. |
---|
581 | 571 | { .con_id = "audio3_2x", .dt_id = TEGRA30_CLK_AUDIO3_2X }, |
---|
582 | 572 | { .con_id = "audio4_2x", .dt_id = TEGRA30_CLK_AUDIO4_2X }, |
---|
583 | 573 | { .con_id = "spdif_2x", .dt_id = TEGRA30_CLK_SPDIF_2X }, |
---|
584 | | - { .con_id = "extern1", .dev_id = "clk_out_1", .dt_id = TEGRA30_CLK_EXTERN1 }, |
---|
585 | | - { .con_id = "extern2", .dev_id = "clk_out_2", .dt_id = TEGRA30_CLK_EXTERN2 }, |
---|
586 | | - { .con_id = "extern3", .dev_id = "clk_out_3", .dt_id = TEGRA30_CLK_EXTERN3 }, |
---|
587 | | - { .con_id = "blink", .dt_id = TEGRA30_CLK_BLINK }, |
---|
| 574 | + { .con_id = "extern1", .dt_id = TEGRA30_CLK_EXTERN1 }, |
---|
| 575 | + { .con_id = "extern2", .dt_id = TEGRA30_CLK_EXTERN2 }, |
---|
| 576 | + { .con_id = "extern3", .dt_id = TEGRA30_CLK_EXTERN3 }, |
---|
588 | 577 | { .con_id = "cclk_g", .dt_id = TEGRA30_CLK_CCLK_G }, |
---|
589 | 578 | { .con_id = "cclk_lp", .dt_id = TEGRA30_CLK_CCLK_LP }, |
---|
590 | 579 | { .con_id = "sclk", .dt_id = TEGRA30_CLK_SCLK }, |
---|
.. | .. |
---|
593 | 582 | { .con_id = "twd", .dt_id = TEGRA30_CLK_TWD }, |
---|
594 | 583 | { .con_id = "emc", .dt_id = TEGRA30_CLK_EMC }, |
---|
595 | 584 | { .con_id = "clk_32k", .dt_id = TEGRA30_CLK_CLK_32K }, |
---|
596 | | - { .con_id = "clk_m_div2", .dt_id = TEGRA30_CLK_CLK_M_DIV2 }, |
---|
597 | | - { .con_id = "clk_m_div4", .dt_id = TEGRA30_CLK_CLK_M_DIV4 }, |
---|
| 585 | + { .con_id = "osc", .dt_id = TEGRA30_CLK_OSC }, |
---|
| 586 | + { .con_id = "osc_div2", .dt_id = TEGRA30_CLK_OSC_DIV2 }, |
---|
| 587 | + { .con_id = "osc_div4", .dt_id = TEGRA30_CLK_OSC_DIV4 }, |
---|
598 | 588 | { .con_id = "cml0", .dt_id = TEGRA30_CLK_CML0 }, |
---|
599 | 589 | { .con_id = "cml1", .dt_id = TEGRA30_CLK_CML1 }, |
---|
600 | 590 | { .con_id = "clk_m", .dt_id = TEGRA30_CLK_CLK_M }, |
---|
.. | .. |
---|
695 | 685 | static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = { |
---|
696 | 686 | [tegra_clk_clk_32k] = { .dt_id = TEGRA30_CLK_CLK_32K, .present = true }, |
---|
697 | 687 | [tegra_clk_clk_m] = { .dt_id = TEGRA30_CLK_CLK_M, .present = true }, |
---|
698 | | - [tegra_clk_clk_m_div2] = { .dt_id = TEGRA30_CLK_CLK_M_DIV2, .present = true }, |
---|
699 | | - [tegra_clk_clk_m_div4] = { .dt_id = TEGRA30_CLK_CLK_M_DIV4, .present = true }, |
---|
| 688 | + [tegra_clk_osc] = { .dt_id = TEGRA30_CLK_OSC, .present = true }, |
---|
| 689 | + [tegra_clk_osc_div2] = { .dt_id = TEGRA30_CLK_OSC_DIV2, .present = true }, |
---|
| 690 | + [tegra_clk_osc_div4] = { .dt_id = TEGRA30_CLK_OSC_DIV4, .present = true }, |
---|
700 | 691 | [tegra_clk_pll_ref] = { .dt_id = TEGRA30_CLK_PLL_REF, .present = true }, |
---|
701 | 692 | [tegra_clk_spdif_in_sync] = { .dt_id = TEGRA30_CLK_SPDIF_IN_SYNC, .present = true }, |
---|
702 | 693 | [tegra_clk_i2s0_sync] = { .dt_id = TEGRA30_CLK_I2S0_SYNC, .present = true }, |
---|
.. | .. |
---|
723 | 714 | [tegra_clk_audio3_2x] = { .dt_id = TEGRA30_CLK_AUDIO3_2X, .present = true }, |
---|
724 | 715 | [tegra_clk_audio4_2x] = { .dt_id = TEGRA30_CLK_AUDIO4_2X, .present = true }, |
---|
725 | 716 | [tegra_clk_spdif_2x] = { .dt_id = TEGRA30_CLK_SPDIF_2X, .present = true }, |
---|
726 | | - [tegra_clk_clk_out_1] = { .dt_id = TEGRA30_CLK_CLK_OUT_1, .present = true }, |
---|
727 | | - [tegra_clk_clk_out_2] = { .dt_id = TEGRA30_CLK_CLK_OUT_2, .present = true }, |
---|
728 | | - [tegra_clk_clk_out_3] = { .dt_id = TEGRA30_CLK_CLK_OUT_3, .present = true }, |
---|
729 | | - [tegra_clk_blink] = { .dt_id = TEGRA30_CLK_BLINK, .present = true }, |
---|
730 | | - [tegra_clk_clk_out_1_mux] = { .dt_id = TEGRA30_CLK_CLK_OUT_1_MUX, .present = true }, |
---|
731 | | - [tegra_clk_clk_out_2_mux] = { .dt_id = TEGRA30_CLK_CLK_OUT_2_MUX, .present = true }, |
---|
732 | | - [tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA30_CLK_CLK_OUT_3_MUX, .present = true }, |
---|
733 | 717 | [tegra_clk_hclk] = { .dt_id = TEGRA30_CLK_HCLK, .present = true }, |
---|
734 | 718 | [tegra_clk_pclk] = { .dt_id = TEGRA30_CLK_PCLK, .present = true }, |
---|
735 | 719 | [tegra_clk_i2s0] = { .dt_id = TEGRA30_CLK_I2S0, .present = true }, |
---|
.. | .. |
---|
819 | 803 | [tegra_clk_pll_a] = { .dt_id = TEGRA30_CLK_PLL_A, .present = true }, |
---|
820 | 804 | [tegra_clk_pll_a_out0] = { .dt_id = TEGRA30_CLK_PLL_A_OUT0, .present = true }, |
---|
821 | 805 | [tegra_clk_cec] = { .dt_id = TEGRA30_CLK_CEC, .present = true }, |
---|
822 | | - [tegra_clk_emc] = { .dt_id = TEGRA30_CLK_EMC, .present = true }, |
---|
| 806 | + [tegra_clk_emc] = { .dt_id = TEGRA30_CLK_EMC, .present = false }, |
---|
823 | 807 | }; |
---|
824 | 808 | |
---|
825 | 809 | static const char *pll_e_parents[] = { "pll_ref", "pll_p" }; |
---|
.. | .. |
---|
944 | 928 | clk_register_clkdev(clk, "pll_p_out4_cclkg", NULL); |
---|
945 | 929 | |
---|
946 | 930 | /* CCLKG */ |
---|
947 | | - clk = tegra_clk_register_super_mux("cclk_g", cclk_g_parents, |
---|
| 931 | + clk = tegra_clk_register_super_cclk("cclk_g", cclk_g_parents, |
---|
948 | 932 | ARRAY_SIZE(cclk_g_parents), |
---|
949 | 933 | CLK_SET_RATE_PARENT, |
---|
950 | 934 | clk_base + CCLKG_BURST_POLICY, |
---|
951 | | - 0, 4, 0, 0, NULL); |
---|
| 935 | + 0, NULL); |
---|
952 | 936 | clks[TEGRA30_CLK_CCLK_G] = clk; |
---|
953 | 937 | |
---|
954 | 938 | /* |
---|
.. | .. |
---|
1006 | 990 | static const char *mux_pllacp_clkm[] = { "pll_a_out0", "unused", "pll_p", |
---|
1007 | 991 | "clk_m" }; |
---|
1008 | 992 | static const char *mux_pllpcm_clkm[] = { "pll_p", "pll_c", "pll_m", "clk_m" }; |
---|
1009 | | -static const char *mux_pllmcp_clkm[] = { "pll_m", "pll_c", "pll_p", "clk_m" }; |
---|
1010 | 993 | static const char *spdif_out_parents[] = { "pll_a_out0", "spdif_2x", "pll_p", |
---|
1011 | 994 | "clk_m" }; |
---|
1012 | 995 | static const char *mux_pllmcpa[] = { "pll_m", "pll_c", "pll_p", "pll_a_out0" }; |
---|
.. | .. |
---|
1055 | 1038 | clks[TEGRA30_CLK_AFI] = clk; |
---|
1056 | 1039 | |
---|
1057 | 1040 | /* emc */ |
---|
1058 | | - clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, |
---|
1059 | | - ARRAY_SIZE(mux_pllmcp_clkm), |
---|
1060 | | - CLK_SET_RATE_NO_REPARENT, |
---|
1061 | | - clk_base + CLK_SOURCE_EMC, |
---|
1062 | | - 30, 2, 0, &emc_lock); |
---|
| 1041 | + clk = tegra20_clk_register_emc(clk_base + CLK_SOURCE_EMC, true); |
---|
1063 | 1042 | |
---|
1064 | | - clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC, |
---|
1065 | | - &emc_lock); |
---|
| 1043 | + clks[TEGRA30_CLK_EMC] = clk; |
---|
| 1044 | + |
---|
| 1045 | + clk = tegra_clk_register_mc("mc", "emc", clk_base + CLK_SOURCE_EMC, |
---|
| 1046 | + NULL); |
---|
1066 | 1047 | clks[TEGRA30_CLK_MC] = clk; |
---|
1067 | 1048 | |
---|
1068 | 1049 | /* cml0 */ |
---|
.. | .. |
---|
1148 | 1129 | |
---|
1149 | 1130 | cpu_rst_status = readl(clk_base + |
---|
1150 | 1131 | TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS); |
---|
1151 | | - cpu_pwr_status = tegra_powergate_is_powered(TEGRA_POWERGATE_CPU1) || |
---|
1152 | | - tegra_powergate_is_powered(TEGRA_POWERGATE_CPU2) || |
---|
1153 | | - tegra_powergate_is_powered(TEGRA_POWERGATE_CPU3); |
---|
| 1132 | + cpu_pwr_status = tegra_pmc_cpu_is_powered(1) || |
---|
| 1133 | + tegra_pmc_cpu_is_powered(2) || |
---|
| 1134 | + tegra_pmc_cpu_is_powered(3); |
---|
1154 | 1135 | |
---|
1155 | 1136 | if (((cpu_rst_status & 0xE) != 0xE) || cpu_pwr_status) |
---|
1156 | 1137 | return false; |
---|
.. | .. |
---|
1178 | 1159 | static void tegra30_cpu_clock_resume(void) |
---|
1179 | 1160 | { |
---|
1180 | 1161 | unsigned int reg, policy; |
---|
| 1162 | + u32 misc, base; |
---|
1181 | 1163 | |
---|
1182 | 1164 | /* Is CPU complex already running on PLLX? */ |
---|
1183 | 1165 | reg = readl(clk_base + CLK_RESET_CCLK_BURST); |
---|
.. | .. |
---|
1191 | 1173 | BUG(); |
---|
1192 | 1174 | |
---|
1193 | 1175 | if (reg != CLK_RESET_CCLK_BURST_POLICY_PLLX) { |
---|
1194 | | - /* restore PLLX settings if CPU is on different PLL */ |
---|
1195 | | - writel(tegra30_cpu_clk_sctx.pllx_misc, |
---|
1196 | | - clk_base + CLK_RESET_PLLX_MISC); |
---|
1197 | | - writel(tegra30_cpu_clk_sctx.pllx_base, |
---|
1198 | | - clk_base + CLK_RESET_PLLX_BASE); |
---|
| 1176 | + misc = readl_relaxed(clk_base + CLK_RESET_PLLX_MISC); |
---|
| 1177 | + base = readl_relaxed(clk_base + CLK_RESET_PLLX_BASE); |
---|
1199 | 1178 | |
---|
1200 | | - /* wait for PLL stabilization if PLLX was enabled */ |
---|
1201 | | - if (tegra30_cpu_clk_sctx.pllx_base & (1 << 30)) |
---|
1202 | | - udelay(300); |
---|
| 1179 | + if (misc != tegra30_cpu_clk_sctx.pllx_misc || |
---|
| 1180 | + base != tegra30_cpu_clk_sctx.pllx_base) { |
---|
| 1181 | + /* restore PLLX settings if CPU is on different PLL */ |
---|
| 1182 | + writel(tegra30_cpu_clk_sctx.pllx_misc, |
---|
| 1183 | + clk_base + CLK_RESET_PLLX_MISC); |
---|
| 1184 | + writel(tegra30_cpu_clk_sctx.pllx_base, |
---|
| 1185 | + clk_base + CLK_RESET_PLLX_BASE); |
---|
| 1186 | + |
---|
| 1187 | + /* wait for PLL stabilization if PLLX was enabled */ |
---|
| 1188 | + if (tegra30_cpu_clk_sctx.pllx_base & (1 << 30)) |
---|
| 1189 | + udelay(300); |
---|
| 1190 | + } |
---|
1203 | 1191 | } |
---|
1204 | 1192 | |
---|
1205 | 1193 | /* |
---|
.. | .. |
---|
1235 | 1223 | { TEGRA30_CLK_UARTC, TEGRA30_CLK_PLL_P, 408000000, 0 }, |
---|
1236 | 1224 | { TEGRA30_CLK_UARTD, TEGRA30_CLK_PLL_P, 408000000, 0 }, |
---|
1237 | 1225 | { TEGRA30_CLK_UARTE, TEGRA30_CLK_PLL_P, 408000000, 0 }, |
---|
1238 | | - { TEGRA30_CLK_PLL_A, TEGRA30_CLK_CLK_MAX, 564480000, 1 }, |
---|
1239 | | - { TEGRA30_CLK_PLL_A_OUT0, TEGRA30_CLK_CLK_MAX, 11289600, 1 }, |
---|
1240 | | - { TEGRA30_CLK_EXTERN1, TEGRA30_CLK_PLL_A_OUT0, 0, 1 }, |
---|
1241 | | - { TEGRA30_CLK_CLK_OUT_1_MUX, TEGRA30_CLK_EXTERN1, 0, 0 }, |
---|
1242 | | - { TEGRA30_CLK_CLK_OUT_1, TEGRA30_CLK_CLK_MAX, 0, 1 }, |
---|
1243 | | - { TEGRA30_CLK_BLINK, TEGRA30_CLK_CLK_MAX, 0, 1 }, |
---|
| 1226 | + { TEGRA30_CLK_PLL_A, TEGRA30_CLK_CLK_MAX, 564480000, 0 }, |
---|
| 1227 | + { TEGRA30_CLK_PLL_A_OUT0, TEGRA30_CLK_CLK_MAX, 11289600, 0 }, |
---|
1244 | 1228 | { TEGRA30_CLK_I2S0, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 }, |
---|
1245 | 1229 | { TEGRA30_CLK_I2S1, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 }, |
---|
1246 | 1230 | { TEGRA30_CLK_I2S2, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 }, |
---|
.. | .. |
---|
1259 | 1243 | { TEGRA30_CLK_SBC6, TEGRA30_CLK_PLL_P, 100000000, 0 }, |
---|
1260 | 1244 | { TEGRA30_CLK_PLL_C, TEGRA30_CLK_CLK_MAX, 600000000, 0 }, |
---|
1261 | 1245 | { TEGRA30_CLK_HOST1X, TEGRA30_CLK_PLL_C, 150000000, 0 }, |
---|
1262 | | - { TEGRA30_CLK_DISP1, TEGRA30_CLK_PLL_P, 600000000, 0 }, |
---|
1263 | | - { TEGRA30_CLK_DISP2, TEGRA30_CLK_PLL_P, 600000000, 0 }, |
---|
1264 | 1246 | { TEGRA30_CLK_TWD, TEGRA30_CLK_CLK_MAX, 0, 1 }, |
---|
1265 | 1247 | { TEGRA30_CLK_GR2D, TEGRA30_CLK_PLL_C, 300000000, 0 }, |
---|
1266 | 1248 | { TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0 }, |
---|
1267 | 1249 | { TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0 }, |
---|
1268 | 1250 | { TEGRA30_CLK_PLL_U, TEGRA30_CLK_CLK_MAX, 480000000, 0 }, |
---|
1269 | | - { TEGRA30_CLK_VDE, TEGRA30_CLK_CLK_MAX, 600000000, 0 }, |
---|
| 1251 | + { TEGRA30_CLK_VDE, TEGRA30_CLK_PLL_C, 300000000, 0 }, |
---|
1270 | 1252 | { TEGRA30_CLK_SPDIF_IN_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 }, |
---|
1271 | 1253 | { TEGRA30_CLK_I2S0_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 }, |
---|
1272 | 1254 | { TEGRA30_CLK_I2S1_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 }, |
---|
.. | .. |
---|
1315 | 1297 | { "pll_a", &pll_a_params, tegra_clk_pll_a, "pll_p_out1" }, |
---|
1316 | 1298 | }; |
---|
1317 | 1299 | |
---|
| 1300 | +static struct clk *tegra30_clk_src_onecell_get(struct of_phandle_args *clkspec, |
---|
| 1301 | + void *data) |
---|
| 1302 | +{ |
---|
| 1303 | + struct clk_hw *hw; |
---|
| 1304 | + struct clk *clk; |
---|
| 1305 | + |
---|
| 1306 | + clk = of_clk_src_onecell_get(clkspec, data); |
---|
| 1307 | + if (IS_ERR(clk)) |
---|
| 1308 | + return clk; |
---|
| 1309 | + |
---|
| 1310 | + hw = __clk_get_hw(clk); |
---|
| 1311 | + |
---|
| 1312 | + if (clkspec->args[0] == TEGRA30_CLK_EMC) { |
---|
| 1313 | + if (!tegra20_clk_emc_driver_available(hw)) |
---|
| 1314 | + return ERR_PTR(-EPROBE_DEFER); |
---|
| 1315 | + } |
---|
| 1316 | + |
---|
| 1317 | + return clk; |
---|
| 1318 | +} |
---|
| 1319 | + |
---|
1318 | 1320 | static void __init tegra30_clock_init(struct device_node *np) |
---|
1319 | 1321 | { |
---|
1320 | 1322 | struct device_node *node; |
---|
.. | .. |
---|
1354 | 1356 | tegra_audio_clk_init(clk_base, pmc_base, tegra30_clks, |
---|
1355 | 1357 | tegra30_audio_plls, |
---|
1356 | 1358 | ARRAY_SIZE(tegra30_audio_plls), 24000000); |
---|
1357 | | - tegra_pmc_clk_init(pmc_base, tegra30_clks); |
---|
1358 | 1359 | |
---|
1359 | 1360 | tegra_init_dup_clks(tegra_clk_duplicates, clks, TEGRA30_CLK_CLK_MAX); |
---|
1360 | 1361 | |
---|
1361 | | - tegra_add_of_provider(np, of_clk_src_onecell_get); |
---|
| 1362 | + tegra_add_of_provider(np, tegra30_clk_src_onecell_get); |
---|
1362 | 1363 | tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); |
---|
1363 | 1364 | |
---|
1364 | 1365 | tegra_clk_apply_init_table = tegra30_clock_apply_init_table; |
---|