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


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * PRCC clock implementation for ux500 platform.
      4 *
      5 * Copyright (C) 2012 ST-Ericsson SA
      6 * Author: Ulf Hansson <ulf.hansson@linaro.org>
      7 */
      8
      9#include <linux/clk-provider.h>
     10#include <linux/slab.h>
     11#include <linux/io.h>
     12#include <linux/err.h>
     13#include <linux/types.h>
     14
     15#include "clk.h"
     16
     17#define PRCC_PCKEN			0x000
     18#define PRCC_PCKDIS			0x004
     19#define PRCC_KCKEN			0x008
     20#define PRCC_KCKDIS			0x00C
     21#define PRCC_PCKSR			0x010
     22#define PRCC_KCKSR			0x014
     23
     24#define to_clk_prcc(_hw) container_of(_hw, struct clk_prcc, hw)
     25
     26struct clk_prcc {
     27	struct clk_hw hw;
     28	void __iomem *base;
     29	u32 cg_sel;
     30	int is_enabled;
     31};
     32
     33/* PRCC clock operations. */
     34
     35static int clk_prcc_pclk_enable(struct clk_hw *hw)
     36{
     37	struct clk_prcc *clk = to_clk_prcc(hw);
     38
     39	writel(clk->cg_sel, (clk->base + PRCC_PCKEN));
     40	while (!(readl(clk->base + PRCC_PCKSR) & clk->cg_sel))
     41		cpu_relax();
     42
     43	clk->is_enabled = 1;
     44	return 0;
     45}
     46
     47static void clk_prcc_pclk_disable(struct clk_hw *hw)
     48{
     49	struct clk_prcc *clk = to_clk_prcc(hw);
     50
     51	writel(clk->cg_sel, (clk->base + PRCC_PCKDIS));
     52	clk->is_enabled = 0;
     53}
     54
     55static int clk_prcc_kclk_enable(struct clk_hw *hw)
     56{
     57	struct clk_prcc *clk = to_clk_prcc(hw);
     58
     59	writel(clk->cg_sel, (clk->base + PRCC_KCKEN));
     60	while (!(readl(clk->base + PRCC_KCKSR) & clk->cg_sel))
     61		cpu_relax();
     62
     63	clk->is_enabled = 1;
     64	return 0;
     65}
     66
     67static void clk_prcc_kclk_disable(struct clk_hw *hw)
     68{
     69	struct clk_prcc *clk = to_clk_prcc(hw);
     70
     71	writel(clk->cg_sel, (clk->base + PRCC_KCKDIS));
     72	clk->is_enabled = 0;
     73}
     74
     75static int clk_prcc_is_enabled(struct clk_hw *hw)
     76{
     77	struct clk_prcc *clk = to_clk_prcc(hw);
     78	return clk->is_enabled;
     79}
     80
     81static const struct clk_ops clk_prcc_pclk_ops = {
     82	.enable = clk_prcc_pclk_enable,
     83	.disable = clk_prcc_pclk_disable,
     84	.is_enabled = clk_prcc_is_enabled,
     85};
     86
     87static const struct clk_ops clk_prcc_kclk_ops = {
     88	.enable = clk_prcc_kclk_enable,
     89	.disable = clk_prcc_kclk_disable,
     90	.is_enabled = clk_prcc_is_enabled,
     91};
     92
     93static struct clk *clk_reg_prcc(const char *name,
     94				const char *parent_name,
     95				resource_size_t phy_base,
     96				u32 cg_sel,
     97				unsigned long flags,
     98				const struct clk_ops *clk_prcc_ops)
     99{
    100	struct clk_prcc *clk;
    101	struct clk_init_data clk_prcc_init;
    102	struct clk *clk_reg;
    103
    104	if (!name) {
    105		pr_err("clk_prcc: %s invalid arguments passed\n", __func__);
    106		return ERR_PTR(-EINVAL);
    107	}
    108
    109	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
    110	if (!clk)
    111		return ERR_PTR(-ENOMEM);
    112
    113	clk->base = ioremap(phy_base, SZ_4K);
    114	if (!clk->base)
    115		goto free_clk;
    116
    117	clk->cg_sel = cg_sel;
    118	clk->is_enabled = 1;
    119
    120	clk_prcc_init.name = name;
    121	clk_prcc_init.ops = clk_prcc_ops;
    122	clk_prcc_init.flags = flags;
    123	clk_prcc_init.parent_names = (parent_name ? &parent_name : NULL);
    124	clk_prcc_init.num_parents = (parent_name ? 1 : 0);
    125	clk->hw.init = &clk_prcc_init;
    126
    127	clk_reg = clk_register(NULL, &clk->hw);
    128	if (IS_ERR_OR_NULL(clk_reg))
    129		goto unmap_clk;
    130
    131	return clk_reg;
    132
    133unmap_clk:
    134	iounmap(clk->base);
    135free_clk:
    136	kfree(clk);
    137	pr_err("clk_prcc: %s failed to register clk\n", __func__);
    138	return ERR_PTR(-ENOMEM);
    139}
    140
    141struct clk *clk_reg_prcc_pclk(const char *name,
    142			      const char *parent_name,
    143			      resource_size_t phy_base,
    144			      u32 cg_sel,
    145			      unsigned long flags)
    146{
    147	return clk_reg_prcc(name, parent_name, phy_base, cg_sel, flags,
    148			&clk_prcc_pclk_ops);
    149}
    150
    151struct clk *clk_reg_prcc_kclk(const char *name,
    152			      const char *parent_name,
    153			      resource_size_t phy_base,
    154			      u32 cg_sel,
    155			      unsigned long flags)
    156{
    157	return clk_reg_prcc(name, parent_name, phy_base, cg_sel, flags,
    158			&clk_prcc_kclk_ops);
    159}