^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/clk/tegra.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "clk.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "clk-id.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define OSC_CTRL 0x50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define OSC_CTRL_OSC_FREQ_SHIFT 28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define OSC_CTRL_PLL_REF_DIV_SHIFT 26
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define OSC_CTRL_MASK (0x3f2 | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) (0xf << OSC_CTRL_OSC_FREQ_SHIFT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static u32 osc_ctrl_ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) int __init tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *clks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) unsigned long *input_freqs, unsigned int num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) unsigned int clk_m_div, unsigned long *osc_freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) unsigned long *pll_ref_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct clk *clk, *osc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct clk **dt_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) u32 val, pll_ref_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) unsigned osc_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) val = readl_relaxed(clk_base + OSC_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) osc_ctrl_ctx = val & OSC_CTRL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) osc_idx = val >> OSC_CTRL_OSC_FREQ_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (osc_idx < num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) *osc_freq = input_freqs[osc_idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *osc_freq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (!*osc_freq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) dt_clk = tegra_lookup_dt_id(tegra_clk_osc, clks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (!dt_clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) osc = clk_register_fixed_rate(NULL, "osc", NULL, 0, *osc_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) *dt_clk = osc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* osc_div2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) dt_clk = tegra_lookup_dt_id(tegra_clk_osc_div2, clks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (dt_clk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) clk = clk_register_fixed_factor(NULL, "osc_div2", "osc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) 0, 1, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) *dt_clk = clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* osc_div4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) dt_clk = tegra_lookup_dt_id(tegra_clk_osc_div4, clks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (dt_clk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) clk = clk_register_fixed_factor(NULL, "osc_div4", "osc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) 0, 1, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) *dt_clk = clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m, clks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (!dt_clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) clk = clk_register_fixed_factor(NULL, "clk_m", "osc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) 0, 1, clk_m_div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) *dt_clk = clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* pll_ref */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) pll_ref_div = 1 << val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) dt_clk = tegra_lookup_dt_id(tegra_clk_pll_ref, clks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (!dt_clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) clk = clk_register_fixed_factor(NULL, "pll_ref", "osc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) 0, 1, pll_ref_div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) *dt_clk = clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (pll_ref_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) *pll_ref_freq = *osc_freq / pll_ref_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) void __init tegra_fixed_clk_init(struct tegra_clk *tegra_clks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct clk **dt_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* clk_32k */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) dt_clk = tegra_lookup_dt_id(tegra_clk_clk_32k, tegra_clks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (dt_clk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, 0, 32768);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) *dt_clk = clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) void tegra_clk_osc_resume(void __iomem *clk_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) val = readl_relaxed(clk_base + OSC_CTRL) & ~OSC_CTRL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) val |= osc_ctrl_ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) writel_relaxed(val, clk_base + OSC_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) fence_udelay(2, clk_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }