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

ccu_gate.c (2968B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (C) 2016 Maxime Ripard
      4 * Maxime Ripard <maxime.ripard@free-electrons.com>
      5 */
      6
      7#include <linux/clk-provider.h>
      8#include <linux/io.h>
      9
     10#include "ccu_gate.h"
     11
     12void ccu_gate_helper_disable(struct ccu_common *common, u32 gate)
     13{
     14	unsigned long flags;
     15	u32 reg;
     16
     17	if (!gate)
     18		return;
     19
     20	spin_lock_irqsave(common->lock, flags);
     21
     22	reg = readl(common->base + common->reg);
     23	writel(reg & ~gate, common->base + common->reg);
     24
     25	spin_unlock_irqrestore(common->lock, flags);
     26}
     27EXPORT_SYMBOL_NS_GPL(ccu_gate_helper_disable, SUNXI_CCU);
     28
     29static void ccu_gate_disable(struct clk_hw *hw)
     30{
     31	struct ccu_gate *cg = hw_to_ccu_gate(hw);
     32
     33	return ccu_gate_helper_disable(&cg->common, cg->enable);
     34}
     35
     36int ccu_gate_helper_enable(struct ccu_common *common, u32 gate)
     37{
     38	unsigned long flags;
     39	u32 reg;
     40
     41	if (!gate)
     42		return 0;
     43
     44	spin_lock_irqsave(common->lock, flags);
     45
     46	reg = readl(common->base + common->reg);
     47	writel(reg | gate, common->base + common->reg);
     48
     49	spin_unlock_irqrestore(common->lock, flags);
     50
     51	return 0;
     52}
     53EXPORT_SYMBOL_NS_GPL(ccu_gate_helper_enable, SUNXI_CCU);
     54
     55static int ccu_gate_enable(struct clk_hw *hw)
     56{
     57	struct ccu_gate *cg = hw_to_ccu_gate(hw);
     58
     59	return ccu_gate_helper_enable(&cg->common, cg->enable);
     60}
     61
     62int ccu_gate_helper_is_enabled(struct ccu_common *common, u32 gate)
     63{
     64	if (!gate)
     65		return 1;
     66
     67	return readl(common->base + common->reg) & gate;
     68}
     69EXPORT_SYMBOL_NS_GPL(ccu_gate_helper_is_enabled, SUNXI_CCU);
     70
     71static int ccu_gate_is_enabled(struct clk_hw *hw)
     72{
     73	struct ccu_gate *cg = hw_to_ccu_gate(hw);
     74
     75	return ccu_gate_helper_is_enabled(&cg->common, cg->enable);
     76}
     77
     78static unsigned long ccu_gate_recalc_rate(struct clk_hw *hw,
     79					  unsigned long parent_rate)
     80{
     81	struct ccu_gate *cg = hw_to_ccu_gate(hw);
     82	unsigned long rate = parent_rate;
     83
     84	if (cg->common.features & CCU_FEATURE_ALL_PREDIV)
     85		rate /= cg->common.prediv;
     86
     87	return rate;
     88}
     89
     90static long ccu_gate_round_rate(struct clk_hw *hw, unsigned long rate,
     91				unsigned long *prate)
     92{
     93	struct ccu_gate *cg = hw_to_ccu_gate(hw);
     94	int div = 1;
     95
     96	if (cg->common.features & CCU_FEATURE_ALL_PREDIV)
     97		div = cg->common.prediv;
     98
     99	if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
    100		unsigned long best_parent = rate;
    101
    102		if (cg->common.features & CCU_FEATURE_ALL_PREDIV)
    103			best_parent *= div;
    104		*prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
    105	}
    106
    107	return *prate / div;
    108}
    109
    110static int ccu_gate_set_rate(struct clk_hw *hw, unsigned long rate,
    111			     unsigned long parent_rate)
    112{
    113	/*
    114	 * We must report success but we can do so unconditionally because
    115	 * clk_factor_round_rate returns values that ensure this call is a
    116	 * nop.
    117	 */
    118
    119	return 0;
    120}
    121
    122const struct clk_ops ccu_gate_ops = {
    123	.disable	= ccu_gate_disable,
    124	.enable		= ccu_gate_enable,
    125	.is_enabled	= ccu_gate_is_enabled,
    126	.round_rate	= ccu_gate_round_rate,
    127	.set_rate	= ccu_gate_set_rate,
    128	.recalc_rate	= ccu_gate_recalc_rate,
    129};
    130EXPORT_SYMBOL_NS_GPL(ccu_gate_ops, SUNXI_CCU);