| .. | .. |
|---|
| 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 | } |
|---|