.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2012, 2013, 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> |
---|
.. | .. |
---|
28 | 17 | #define OSC_CTRL 0x50 |
---|
29 | 18 | #define OSC_CTRL_OSC_FREQ_SHIFT 28 |
---|
30 | 19 | #define OSC_CTRL_PLL_REF_DIV_SHIFT 26 |
---|
| 20 | +#define OSC_CTRL_MASK (0x3f2 | \ |
---|
| 21 | + (0xf << OSC_CTRL_OSC_FREQ_SHIFT)) |
---|
| 22 | + |
---|
| 23 | +static u32 osc_ctrl_ctx; |
---|
31 | 24 | |
---|
32 | 25 | int __init tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *clks, |
---|
33 | 26 | unsigned long *input_freqs, unsigned int num, |
---|
.. | .. |
---|
40 | 33 | unsigned osc_idx; |
---|
41 | 34 | |
---|
42 | 35 | val = readl_relaxed(clk_base + OSC_CTRL); |
---|
| 36 | + osc_ctrl_ctx = val & OSC_CTRL_MASK; |
---|
43 | 37 | osc_idx = val >> OSC_CTRL_OSC_FREQ_SHIFT; |
---|
44 | 38 | |
---|
45 | 39 | if (osc_idx < num) |
---|
.. | .. |
---|
52 | 46 | return -EINVAL; |
---|
53 | 47 | } |
---|
54 | 48 | |
---|
| 49 | + dt_clk = tegra_lookup_dt_id(tegra_clk_osc, clks); |
---|
| 50 | + if (!dt_clk) |
---|
| 51 | + return 0; |
---|
| 52 | + |
---|
55 | 53 | osc = clk_register_fixed_rate(NULL, "osc", NULL, 0, *osc_freq); |
---|
| 54 | + *dt_clk = osc; |
---|
| 55 | + |
---|
| 56 | + /* osc_div2 */ |
---|
| 57 | + dt_clk = tegra_lookup_dt_id(tegra_clk_osc_div2, clks); |
---|
| 58 | + if (dt_clk) { |
---|
| 59 | + clk = clk_register_fixed_factor(NULL, "osc_div2", "osc", |
---|
| 60 | + 0, 1, 2); |
---|
| 61 | + *dt_clk = clk; |
---|
| 62 | + } |
---|
| 63 | + |
---|
| 64 | + /* osc_div4 */ |
---|
| 65 | + dt_clk = tegra_lookup_dt_id(tegra_clk_osc_div4, clks); |
---|
| 66 | + if (dt_clk) { |
---|
| 67 | + clk = clk_register_fixed_factor(NULL, "osc_div4", "osc", |
---|
| 68 | + 0, 1, 4); |
---|
| 69 | + *dt_clk = clk; |
---|
| 70 | + } |
---|
56 | 71 | |
---|
57 | 72 | dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m, clks); |
---|
58 | 73 | if (!dt_clk) |
---|
.. | .. |
---|
90 | 105 | clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, 0, 32768); |
---|
91 | 106 | *dt_clk = clk; |
---|
92 | 107 | } |
---|
| 108 | +} |
---|
93 | 109 | |
---|
94 | | - /* clk_m_div2 */ |
---|
95 | | - dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m_div2, tegra_clks); |
---|
96 | | - if (dt_clk) { |
---|
97 | | - clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m", |
---|
98 | | - CLK_SET_RATE_PARENT, 1, 2); |
---|
99 | | - *dt_clk = clk; |
---|
100 | | - } |
---|
| 110 | +void tegra_clk_osc_resume(void __iomem *clk_base) |
---|
| 111 | +{ |
---|
| 112 | + u32 val; |
---|
101 | 113 | |
---|
102 | | - /* clk_m_div4 */ |
---|
103 | | - dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m_div4, tegra_clks); |
---|
104 | | - if (dt_clk) { |
---|
105 | | - clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m", |
---|
106 | | - CLK_SET_RATE_PARENT, 1, 4); |
---|
107 | | - *dt_clk = clk; |
---|
108 | | - } |
---|
| 114 | + val = readl_relaxed(clk_base + OSC_CTRL) & ~OSC_CTRL_MASK; |
---|
| 115 | + val |= osc_ctrl_ctx; |
---|
| 116 | + writel_relaxed(val, clk_base + OSC_CTRL); |
---|
| 117 | + fence_udelay(2, clk_base); |
---|
109 | 118 | } |
---|