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-super-gen4.c (7655B)


      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 PLLX_BASE 0xe0
     18#define PLLX_MISC 0xe4
     19#define PLLX_MISC2 0x514
     20#define PLLX_MISC3 0x518
     21
     22#define CCLKG_BURST_POLICY 0x368
     23#define CCLKLP_BURST_POLICY 0x370
     24#define SCLK_BURST_POLICY 0x028
     25#define SYSTEM_CLK_RATE 0x030
     26#define SCLK_DIVIDER 0x2c
     27
     28static DEFINE_SPINLOCK(sysrate_lock);
     29
     30enum tegra_super_gen {
     31	gen4 = 4,
     32	gen5,
     33};
     34
     35struct tegra_super_gen_info {
     36	enum tegra_super_gen gen;
     37	const char **sclk_parents;
     38	const char **cclk_g_parents;
     39	const char **cclk_lp_parents;
     40	int num_sclk_parents;
     41	int num_cclk_g_parents;
     42	int num_cclk_lp_parents;
     43};
     44
     45static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
     46			       "pll_p", "pll_p_out2", "unused",
     47			       "clk_32k", "pll_m_out1" };
     48
     49static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
     50					"pll_p", "pll_p_out4", "unused",
     51					"unused", "pll_x", "unused", "unused",
     52					"unused", "unused", "unused", "unused",
     53					"dfllCPU_out" };
     54
     55static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
     56					 "pll_p", "pll_p_out4", "unused",
     57					 "unused", "pll_x", "pll_x_out0" };
     58
     59static const struct tegra_super_gen_info tegra_super_gen_info_gen4 = {
     60	.gen = gen4,
     61	.sclk_parents = sclk_parents,
     62	.cclk_g_parents = cclk_g_parents,
     63	.cclk_lp_parents = cclk_lp_parents,
     64	.num_sclk_parents = ARRAY_SIZE(sclk_parents),
     65	.num_cclk_g_parents = ARRAY_SIZE(cclk_g_parents),
     66	.num_cclk_lp_parents = ARRAY_SIZE(cclk_lp_parents),
     67};
     68
     69static const char *sclk_parents_gen5[] = { "clk_m", "pll_c_out1", "pll_c4_out3",
     70			       "pll_p", "pll_p_out2", "pll_c4_out1",
     71			       "clk_32k", "pll_c4_out2" };
     72
     73static const char *cclk_g_parents_gen5[] = { "clk_m", "unused", "clk_32k", "unused",
     74					"pll_p", "pll_p_out4", "unused",
     75					"unused", "pll_x", "unused", "unused",
     76					"unused", "unused", "unused", "unused",
     77					"dfllCPU_out" };
     78
     79static const char *cclk_lp_parents_gen5[] = { "clk_m", "unused", "clk_32k", "unused",
     80					"pll_p", "pll_p_out4", "unused",
     81					"unused", "pll_x", "unused", "unused",
     82					"unused", "unused", "unused", "unused",
     83					"dfllCPU_out" };
     84
     85static const struct tegra_super_gen_info tegra_super_gen_info_gen5 = {
     86	.gen = gen5,
     87	.sclk_parents = sclk_parents_gen5,
     88	.cclk_g_parents = cclk_g_parents_gen5,
     89	.cclk_lp_parents = cclk_lp_parents_gen5,
     90	.num_sclk_parents = ARRAY_SIZE(sclk_parents_gen5),
     91	.num_cclk_g_parents = ARRAY_SIZE(cclk_g_parents_gen5),
     92	.num_cclk_lp_parents = ARRAY_SIZE(cclk_lp_parents_gen5),
     93};
     94
     95static void __init tegra_sclk_init(void __iomem *clk_base,
     96				struct tegra_clk *tegra_clks,
     97				const struct tegra_super_gen_info *gen_info)
     98{
     99	struct clk *clk;
    100	struct clk **dt_clk;
    101
    102	/* SCLK_MUX */
    103	dt_clk = tegra_lookup_dt_id(tegra_clk_sclk_mux, tegra_clks);
    104	if (dt_clk) {
    105		clk = tegra_clk_register_super_mux("sclk_mux",
    106						gen_info->sclk_parents,
    107						gen_info->num_sclk_parents,
    108						CLK_SET_RATE_PARENT,
    109						clk_base + SCLK_BURST_POLICY,
    110						0, 4, 0, 0, NULL);
    111		*dt_clk = clk;
    112
    113
    114		/* SCLK */
    115		dt_clk = tegra_lookup_dt_id(tegra_clk_sclk, tegra_clks);
    116		if (dt_clk) {
    117			clk = clk_register_divider(NULL, "sclk", "sclk_mux",
    118						CLK_IS_CRITICAL,
    119						clk_base + SCLK_DIVIDER, 0, 8,
    120						0, &sysrate_lock);
    121			*dt_clk = clk;
    122		}
    123	} else {
    124		/* SCLK */
    125		dt_clk = tegra_lookup_dt_id(tegra_clk_sclk, tegra_clks);
    126		if (dt_clk) {
    127			clk = tegra_clk_register_super_mux("sclk",
    128						gen_info->sclk_parents,
    129						gen_info->num_sclk_parents,
    130						CLK_SET_RATE_PARENT |
    131						CLK_IS_CRITICAL,
    132						clk_base + SCLK_BURST_POLICY,
    133						0, 4, 0, 0, NULL);
    134			*dt_clk = clk;
    135		}
    136	}
    137
    138	/* HCLK */
    139	dt_clk = tegra_lookup_dt_id(tegra_clk_hclk, tegra_clks);
    140	if (dt_clk) {
    141		clk = clk_register_divider(NULL, "hclk_div", "sclk", 0,
    142				   clk_base + SYSTEM_CLK_RATE, 4, 2, 0,
    143				   &sysrate_lock);
    144		clk = clk_register_gate(NULL, "hclk", "hclk_div",
    145				CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
    146				clk_base + SYSTEM_CLK_RATE,
    147				7, CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
    148		*dt_clk = clk;
    149	}
    150
    151	/* PCLK */
    152	dt_clk = tegra_lookup_dt_id(tegra_clk_pclk, tegra_clks);
    153	if (!dt_clk)
    154		return;
    155
    156	clk = clk_register_divider(NULL, "pclk_div", "hclk", 0,
    157				   clk_base + SYSTEM_CLK_RATE, 0, 2, 0,
    158				   &sysrate_lock);
    159	clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT |
    160				CLK_IS_CRITICAL, clk_base + SYSTEM_CLK_RATE,
    161				3, CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
    162	*dt_clk = clk;
    163}
    164
    165static void __init tegra_super_clk_init(void __iomem *clk_base,
    166				void __iomem *pmc_base,
    167				struct tegra_clk *tegra_clks,
    168				struct tegra_clk_pll_params *params,
    169				const struct tegra_super_gen_info *gen_info)
    170{
    171	struct clk *clk;
    172	struct clk **dt_clk;
    173
    174	/* CCLKG */
    175	dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_g, tegra_clks);
    176	if (dt_clk) {
    177		if (gen_info->gen == gen5) {
    178			clk = tegra_clk_register_super_mux("cclk_g",
    179					gen_info->cclk_g_parents,
    180					gen_info->num_cclk_g_parents,
    181					CLK_SET_RATE_PARENT,
    182					clk_base + CCLKG_BURST_POLICY,
    183					TEGRA210_CPU_CLK, 4, 8, 0, NULL);
    184		} else {
    185			clk = tegra_clk_register_super_mux("cclk_g",
    186					gen_info->cclk_g_parents,
    187					gen_info->num_cclk_g_parents,
    188					CLK_SET_RATE_PARENT,
    189					clk_base + CCLKG_BURST_POLICY,
    190					0, 4, 0, 0, NULL);
    191		}
    192		*dt_clk = clk;
    193	}
    194
    195	/* CCLKLP */
    196	dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_lp, tegra_clks);
    197	if (dt_clk) {
    198		if (gen_info->gen == gen5) {
    199			/*
    200			 * TEGRA210_CPU_CLK flag is not needed for cclk_lp as
    201			 * cluster switching is not currently supported on
    202			 * Tegra210 and also cpu_lp is not used.
    203			 */
    204			clk = tegra_clk_register_super_mux("cclk_lp",
    205					gen_info->cclk_lp_parents,
    206					gen_info->num_cclk_lp_parents,
    207					CLK_SET_RATE_PARENT,
    208					clk_base + CCLKLP_BURST_POLICY,
    209					0, 4, 8, 0, NULL);
    210		} else {
    211			clk = tegra_clk_register_super_mux("cclk_lp",
    212					gen_info->cclk_lp_parents,
    213					gen_info->num_cclk_lp_parents,
    214					CLK_SET_RATE_PARENT,
    215					clk_base + CCLKLP_BURST_POLICY,
    216					TEGRA_DIVIDER_2, 4, 8, 9, NULL);
    217		}
    218		*dt_clk = clk;
    219	}
    220
    221	tegra_sclk_init(clk_base, tegra_clks, gen_info);
    222
    223#if defined(CONFIG_ARCH_TEGRA_114_SOC) || \
    224    defined(CONFIG_ARCH_TEGRA_124_SOC) || \
    225    defined(CONFIG_ARCH_TEGRA_210_SOC)
    226	/* PLLX */
    227	dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x, tegra_clks);
    228	if (!dt_clk)
    229		return;
    230
    231#if defined(CONFIG_ARCH_TEGRA_210_SOC)
    232	if (gen_info->gen == gen5)
    233		clk = tegra_clk_register_pllc_tegra210("pll_x", "pll_ref",
    234			clk_base, pmc_base, CLK_IGNORE_UNUSED, params, NULL);
    235	else
    236#endif
    237		clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base,
    238				pmc_base, CLK_IGNORE_UNUSED, params, NULL);
    239
    240	*dt_clk = clk;
    241
    242	/* PLLX_OUT0 */
    243
    244	dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x_out0, tegra_clks);
    245	if (!dt_clk)
    246		return;
    247	clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x",
    248					CLK_SET_RATE_PARENT, 1, 2);
    249	*dt_clk = clk;
    250#endif
    251}
    252
    253void __init tegra_super_clk_gen4_init(void __iomem *clk_base,
    254				void __iomem *pmc_base,
    255				struct tegra_clk *tegra_clks,
    256				struct tegra_clk_pll_params *params)
    257{
    258	tegra_super_clk_init(clk_base, pmc_base, tegra_clks, params,
    259			     &tegra_super_gen_info_gen4);
    260}
    261
    262void __init tegra_super_clk_gen5_init(void __iomem *clk_base,
    263				void __iomem *pmc_base,
    264				struct tegra_clk *tegra_clks,
    265				struct tegra_clk_pll_params *params)
    266{
    267	tegra_super_clk_init(clk_base, pmc_base, tegra_clks, params,
    268			     &tegra_super_gen_info_gen5);
    269}