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.c (10367B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
      4 */
      5
      6#include <linux/clkdev.h>
      7#include <linux/clk.h>
      8#include <linux/clk-provider.h>
      9#include <linux/delay.h>
     10#include <linux/io.h>
     11#include <linux/of.h>
     12#include <linux/of_device.h>
     13#include <linux/clk/tegra.h>
     14#include <linux/platform_device.h>
     15#include <linux/pm_runtime.h>
     16#include <linux/reset-controller.h>
     17#include <linux/string.h>
     18
     19#include <soc/tegra/fuse.h>
     20
     21#include "clk.h"
     22
     23/* Global data of Tegra CPU CAR ops */
     24static struct device_node *tegra_car_np;
     25static struct tegra_cpu_car_ops dummy_car_ops;
     26struct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops;
     27
     28int *periph_clk_enb_refcnt;
     29static int periph_banks;
     30static u32 *periph_state_ctx;
     31static struct clk **clks;
     32static int clk_num;
     33static struct clk_onecell_data clk_data;
     34
     35/* Handlers for SoC-specific reset lines */
     36static int (*special_reset_assert)(unsigned long);
     37static int (*special_reset_deassert)(unsigned long);
     38static unsigned int num_special_reset;
     39
     40static const struct tegra_clk_periph_regs periph_regs[] = {
     41	[0] = {
     42		.enb_reg = CLK_OUT_ENB_L,
     43		.enb_set_reg = CLK_OUT_ENB_SET_L,
     44		.enb_clr_reg = CLK_OUT_ENB_CLR_L,
     45		.rst_reg = RST_DEVICES_L,
     46		.rst_set_reg = RST_DEVICES_SET_L,
     47		.rst_clr_reg = RST_DEVICES_CLR_L,
     48	},
     49	[1] = {
     50		.enb_reg = CLK_OUT_ENB_H,
     51		.enb_set_reg = CLK_OUT_ENB_SET_H,
     52		.enb_clr_reg = CLK_OUT_ENB_CLR_H,
     53		.rst_reg = RST_DEVICES_H,
     54		.rst_set_reg = RST_DEVICES_SET_H,
     55		.rst_clr_reg = RST_DEVICES_CLR_H,
     56	},
     57	[2] = {
     58		.enb_reg = CLK_OUT_ENB_U,
     59		.enb_set_reg = CLK_OUT_ENB_SET_U,
     60		.enb_clr_reg = CLK_OUT_ENB_CLR_U,
     61		.rst_reg = RST_DEVICES_U,
     62		.rst_set_reg = RST_DEVICES_SET_U,
     63		.rst_clr_reg = RST_DEVICES_CLR_U,
     64	},
     65	[3] = {
     66		.enb_reg = CLK_OUT_ENB_V,
     67		.enb_set_reg = CLK_OUT_ENB_SET_V,
     68		.enb_clr_reg = CLK_OUT_ENB_CLR_V,
     69		.rst_reg = RST_DEVICES_V,
     70		.rst_set_reg = RST_DEVICES_SET_V,
     71		.rst_clr_reg = RST_DEVICES_CLR_V,
     72	},
     73	[4] = {
     74		.enb_reg = CLK_OUT_ENB_W,
     75		.enb_set_reg = CLK_OUT_ENB_SET_W,
     76		.enb_clr_reg = CLK_OUT_ENB_CLR_W,
     77		.rst_reg = RST_DEVICES_W,
     78		.rst_set_reg = RST_DEVICES_SET_W,
     79		.rst_clr_reg = RST_DEVICES_CLR_W,
     80	},
     81	[5] = {
     82		.enb_reg = CLK_OUT_ENB_X,
     83		.enb_set_reg = CLK_OUT_ENB_SET_X,
     84		.enb_clr_reg = CLK_OUT_ENB_CLR_X,
     85		.rst_reg = RST_DEVICES_X,
     86		.rst_set_reg = RST_DEVICES_SET_X,
     87		.rst_clr_reg = RST_DEVICES_CLR_X,
     88	},
     89	[6] = {
     90		.enb_reg = CLK_OUT_ENB_Y,
     91		.enb_set_reg = CLK_OUT_ENB_SET_Y,
     92		.enb_clr_reg = CLK_OUT_ENB_CLR_Y,
     93		.rst_reg = RST_DEVICES_Y,
     94		.rst_set_reg = RST_DEVICES_SET_Y,
     95		.rst_clr_reg = RST_DEVICES_CLR_Y,
     96	},
     97};
     98
     99static void __iomem *clk_base;
    100
    101static int tegra_clk_rst_assert(struct reset_controller_dev *rcdev,
    102		unsigned long id)
    103{
    104	/*
    105	 * If peripheral is on the APB bus then we must read the APB bus to
    106	 * flush the write operation in apb bus. This will avoid peripheral
    107	 * access after disabling clock. Since the reset driver has no
    108	 * knowledge of which reset IDs represent which devices, simply do
    109	 * this all the time.
    110	 */
    111	tegra_read_chipid();
    112
    113	if (id < periph_banks * 32) {
    114		writel_relaxed(BIT(id % 32),
    115			       clk_base + periph_regs[id / 32].rst_set_reg);
    116		return 0;
    117	} else if (id < periph_banks * 32 + num_special_reset) {
    118		return special_reset_assert(id);
    119	}
    120
    121	return -EINVAL;
    122}
    123
    124static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev,
    125		unsigned long id)
    126{
    127	if (id < periph_banks * 32) {
    128		writel_relaxed(BIT(id % 32),
    129			       clk_base + periph_regs[id / 32].rst_clr_reg);
    130		return 0;
    131	} else if (id < periph_banks * 32 + num_special_reset) {
    132		return special_reset_deassert(id);
    133	}
    134
    135	return -EINVAL;
    136}
    137
    138static int tegra_clk_rst_reset(struct reset_controller_dev *rcdev,
    139		unsigned long id)
    140{
    141	int err;
    142
    143	err = tegra_clk_rst_assert(rcdev, id);
    144	if (err)
    145		return err;
    146
    147	udelay(1);
    148
    149	return tegra_clk_rst_deassert(rcdev, id);
    150}
    151
    152const struct tegra_clk_periph_regs *get_reg_bank(int clkid)
    153{
    154	int reg_bank = clkid / 32;
    155
    156	if (reg_bank < periph_banks)
    157		return &periph_regs[reg_bank];
    158	else {
    159		WARN_ON(1);
    160		return NULL;
    161	}
    162}
    163
    164void tegra_clk_set_pllp_out_cpu(bool enable)
    165{
    166	u32 val;
    167
    168	val = readl_relaxed(clk_base + CLK_OUT_ENB_Y);
    169	if (enable)
    170		val |= CLK_ENB_PLLP_OUT_CPU;
    171	else
    172		val &= ~CLK_ENB_PLLP_OUT_CPU;
    173
    174	writel_relaxed(val, clk_base + CLK_OUT_ENB_Y);
    175}
    176
    177void tegra_clk_periph_suspend(void)
    178{
    179	unsigned int i, idx;
    180
    181	idx = 0;
    182	for (i = 0; i < periph_banks; i++, idx++)
    183		periph_state_ctx[idx] =
    184			readl_relaxed(clk_base + periph_regs[i].enb_reg);
    185
    186	for (i = 0; i < periph_banks; i++, idx++)
    187		periph_state_ctx[idx] =
    188			readl_relaxed(clk_base + periph_regs[i].rst_reg);
    189}
    190
    191void tegra_clk_periph_resume(void)
    192{
    193	unsigned int i, idx;
    194
    195	idx = 0;
    196	for (i = 0; i < periph_banks; i++, idx++)
    197		writel_relaxed(periph_state_ctx[idx],
    198			       clk_base + periph_regs[i].enb_reg);
    199	/*
    200	 * All non-boot peripherals will be in reset state on resume.
    201	 * Wait for 5us of reset propagation delay before de-asserting
    202	 * the peripherals based on the saved context.
    203	 */
    204	fence_udelay(5, clk_base);
    205
    206	for (i = 0; i < periph_banks; i++, idx++)
    207		writel_relaxed(periph_state_ctx[idx],
    208			       clk_base + periph_regs[i].rst_reg);
    209
    210	fence_udelay(2, clk_base);
    211}
    212
    213static int tegra_clk_periph_ctx_init(int banks)
    214{
    215	periph_state_ctx = kcalloc(2 * banks, sizeof(*periph_state_ctx),
    216				   GFP_KERNEL);
    217	if (!periph_state_ctx)
    218		return -ENOMEM;
    219
    220	return 0;
    221}
    222
    223struct clk ** __init tegra_clk_init(void __iomem *regs, int num, int banks)
    224{
    225	clk_base = regs;
    226
    227	if (WARN_ON(banks > ARRAY_SIZE(periph_regs)))
    228		return NULL;
    229
    230	periph_clk_enb_refcnt = kcalloc(32 * banks,
    231					sizeof(*periph_clk_enb_refcnt),
    232					GFP_KERNEL);
    233	if (!periph_clk_enb_refcnt)
    234		return NULL;
    235
    236	periph_banks = banks;
    237
    238	clks = kcalloc(num, sizeof(struct clk *), GFP_KERNEL);
    239	if (!clks) {
    240		kfree(periph_clk_enb_refcnt);
    241		return NULL;
    242	}
    243
    244	clk_num = num;
    245
    246	if (IS_ENABLED(CONFIG_PM_SLEEP)) {
    247		if (tegra_clk_periph_ctx_init(banks)) {
    248			kfree(periph_clk_enb_refcnt);
    249			kfree(clks);
    250			return NULL;
    251		}
    252	}
    253
    254	return clks;
    255}
    256
    257void __init tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
    258				struct clk *clks[], int clk_max)
    259{
    260	struct clk *clk;
    261
    262	for (; dup_list->clk_id < clk_max; dup_list++) {
    263		clk = clks[dup_list->clk_id];
    264		dup_list->lookup.clk = clk;
    265		clkdev_add(&dup_list->lookup);
    266	}
    267}
    268
    269void tegra_init_from_table(struct tegra_clk_init_table *tbl,
    270			   struct clk *clks[], int clk_max)
    271{
    272	struct clk *clk;
    273
    274	for (; tbl->clk_id < clk_max; tbl++) {
    275		clk = clks[tbl->clk_id];
    276		if (IS_ERR_OR_NULL(clk)) {
    277			pr_err("%s: invalid entry %ld in clks array for id %d\n",
    278			       __func__, PTR_ERR(clk), tbl->clk_id);
    279			WARN_ON(1);
    280
    281			continue;
    282		}
    283
    284		if (tbl->parent_id < clk_max) {
    285			struct clk *parent = clks[tbl->parent_id];
    286			if (clk_set_parent(clk, parent)) {
    287				pr_err("%s: Failed to set parent %s of %s\n",
    288				       __func__, __clk_get_name(parent),
    289				       __clk_get_name(clk));
    290				WARN_ON(1);
    291			}
    292		}
    293
    294		if (tbl->rate)
    295			if (clk_set_rate(clk, tbl->rate)) {
    296				pr_err("%s: Failed to set rate %lu of %s\n",
    297				       __func__, tbl->rate,
    298				       __clk_get_name(clk));
    299				WARN_ON(1);
    300			}
    301
    302		if (tbl->state)
    303			if (clk_prepare_enable(clk)) {
    304				pr_err("%s: Failed to enable %s\n", __func__,
    305				       __clk_get_name(clk));
    306				WARN_ON(1);
    307			}
    308	}
    309}
    310
    311static const struct reset_control_ops rst_ops = {
    312	.assert = tegra_clk_rst_assert,
    313	.deassert = tegra_clk_rst_deassert,
    314	.reset = tegra_clk_rst_reset,
    315};
    316
    317static struct reset_controller_dev rst_ctlr = {
    318	.ops = &rst_ops,
    319	.owner = THIS_MODULE,
    320	.of_reset_n_cells = 1,
    321};
    322
    323void __init tegra_add_of_provider(struct device_node *np,
    324				  void *clk_src_onecell_get)
    325{
    326	int i;
    327
    328	tegra_car_np = np;
    329
    330	for (i = 0; i < clk_num; i++) {
    331		if (IS_ERR(clks[i])) {
    332			pr_err
    333			    ("Tegra clk %d: register failed with %ld\n",
    334			     i, PTR_ERR(clks[i]));
    335		}
    336		if (!clks[i])
    337			clks[i] = ERR_PTR(-EINVAL);
    338	}
    339
    340	clk_data.clks = clks;
    341	clk_data.clk_num = clk_num;
    342	of_clk_add_provider(np, clk_src_onecell_get, &clk_data);
    343
    344	rst_ctlr.of_node = np;
    345	rst_ctlr.nr_resets = periph_banks * 32 + num_special_reset;
    346	reset_controller_register(&rst_ctlr);
    347}
    348
    349void __init tegra_init_special_resets(unsigned int num,
    350				      int (*assert)(unsigned long),
    351				      int (*deassert)(unsigned long))
    352{
    353	num_special_reset = num;
    354	special_reset_assert = assert;
    355	special_reset_deassert = deassert;
    356}
    357
    358void tegra_register_devclks(struct tegra_devclk *dev_clks, int num)
    359{
    360	int i;
    361
    362	for (i = 0; i < num; i++, dev_clks++)
    363		clk_register_clkdev(clks[dev_clks->dt_id], dev_clks->con_id,
    364				dev_clks->dev_id);
    365
    366	for (i = 0; i < clk_num; i++) {
    367		if (!IS_ERR_OR_NULL(clks[i]))
    368			clk_register_clkdev(clks[i], __clk_get_name(clks[i]),
    369				"tegra-clk-debug");
    370	}
    371}
    372
    373struct clk ** __init tegra_lookup_dt_id(int clk_id,
    374					struct tegra_clk *tegra_clk)
    375{
    376	if (tegra_clk[clk_id].present)
    377		return &clks[tegra_clk[clk_id].dt_id];
    378	else
    379		return NULL;
    380}
    381
    382static struct device_node *tegra_clk_get_of_node(struct clk_hw *hw)
    383{
    384	struct device_node *np;
    385	char *node_name;
    386
    387	node_name = kstrdup(hw->init->name, GFP_KERNEL);
    388	if (!node_name)
    389		return NULL;
    390
    391	strreplace(node_name, '_', '-');
    392
    393	for_each_child_of_node(tegra_car_np, np) {
    394		if (!strcmp(np->name, node_name))
    395			break;
    396	}
    397
    398	kfree(node_name);
    399
    400	return np;
    401}
    402
    403struct clk *tegra_clk_dev_register(struct clk_hw *hw)
    404{
    405	struct platform_device *pdev, *parent;
    406	const char *dev_name = NULL;
    407	struct device *dev = NULL;
    408	struct device_node *np;
    409
    410	np = tegra_clk_get_of_node(hw);
    411
    412	if (!of_device_is_available(np))
    413		goto put_node;
    414
    415	dev_name = kasprintf(GFP_KERNEL, "tegra_clk_%s", hw->init->name);
    416	if (!dev_name)
    417		goto put_node;
    418
    419	parent = of_find_device_by_node(tegra_car_np);
    420	if (parent) {
    421		pdev = of_platform_device_create(np, dev_name, &parent->dev);
    422		put_device(&parent->dev);
    423
    424		if (!pdev) {
    425			pr_err("%s: failed to create device for %pOF\n",
    426			       __func__, np);
    427			goto free_name;
    428		}
    429
    430		dev = &pdev->dev;
    431		pm_runtime_enable(dev);
    432	} else {
    433		WARN(1, "failed to find device for %pOF\n", tegra_car_np);
    434	}
    435
    436free_name:
    437	kfree(dev_name);
    438put_node:
    439	of_node_put(np);
    440
    441	return clk_register(dev, hw);
    442}
    443
    444tegra_clk_apply_init_table_func tegra_clk_apply_init_table;
    445
    446static int __init tegra_clocks_apply_init_table(void)
    447{
    448	if (!tegra_clk_apply_init_table)
    449		return 0;
    450
    451	tegra_clk_apply_init_table();
    452
    453	return 0;
    454}
    455arch_initcall(tegra_clocks_apply_init_table);