cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

clk-tegra-fixed.c (2674B)


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