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


      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#include <linux/spinlock.h>
     10
     11#include "ccu_frac.h"
     12
     13bool ccu_frac_helper_is_enabled(struct ccu_common *common,
     14				struct ccu_frac_internal *cf)
     15{
     16	if (!(common->features & CCU_FEATURE_FRACTIONAL))
     17		return false;
     18
     19	return !(readl(common->base + common->reg) & cf->enable);
     20}
     21EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_is_enabled, SUNXI_CCU);
     22
     23void ccu_frac_helper_enable(struct ccu_common *common,
     24			    struct ccu_frac_internal *cf)
     25{
     26	unsigned long flags;
     27	u32 reg;
     28
     29	if (!(common->features & CCU_FEATURE_FRACTIONAL))
     30		return;
     31
     32	spin_lock_irqsave(common->lock, flags);
     33	reg = readl(common->base + common->reg);
     34	writel(reg & ~cf->enable, common->base + common->reg);
     35	spin_unlock_irqrestore(common->lock, flags);
     36}
     37EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_enable, SUNXI_CCU);
     38
     39void ccu_frac_helper_disable(struct ccu_common *common,
     40			     struct ccu_frac_internal *cf)
     41{
     42	unsigned long flags;
     43	u32 reg;
     44
     45	if (!(common->features & CCU_FEATURE_FRACTIONAL))
     46		return;
     47
     48	spin_lock_irqsave(common->lock, flags);
     49	reg = readl(common->base + common->reg);
     50	writel(reg | cf->enable, common->base + common->reg);
     51	spin_unlock_irqrestore(common->lock, flags);
     52}
     53EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_disable, SUNXI_CCU);
     54
     55bool ccu_frac_helper_has_rate(struct ccu_common *common,
     56			      struct ccu_frac_internal *cf,
     57			      unsigned long rate)
     58{
     59	if (!(common->features & CCU_FEATURE_FRACTIONAL))
     60		return false;
     61
     62	return (cf->rates[0] == rate) || (cf->rates[1] == rate);
     63}
     64EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_has_rate, SUNXI_CCU);
     65
     66unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
     67					struct ccu_frac_internal *cf)
     68{
     69	u32 reg;
     70
     71	pr_debug("%s: Read fractional\n", clk_hw_get_name(&common->hw));
     72
     73	if (!(common->features & CCU_FEATURE_FRACTIONAL))
     74		return 0;
     75
     76	pr_debug("%s: clock is fractional (rates %lu and %lu)\n",
     77		 clk_hw_get_name(&common->hw), cf->rates[0], cf->rates[1]);
     78
     79	reg = readl(common->base + common->reg);
     80
     81	pr_debug("%s: clock reg is 0x%x (select is 0x%x)\n",
     82		 clk_hw_get_name(&common->hw), reg, cf->select);
     83
     84	return (reg & cf->select) ? cf->rates[1] : cf->rates[0];
     85}
     86EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_read_rate, SUNXI_CCU);
     87
     88int ccu_frac_helper_set_rate(struct ccu_common *common,
     89			     struct ccu_frac_internal *cf,
     90			     unsigned long rate, u32 lock)
     91{
     92	unsigned long flags;
     93	u32 reg, sel;
     94
     95	if (!(common->features & CCU_FEATURE_FRACTIONAL))
     96		return -EINVAL;
     97
     98	if (cf->rates[0] == rate)
     99		sel = 0;
    100	else if (cf->rates[1] == rate)
    101		sel = cf->select;
    102	else
    103		return -EINVAL;
    104
    105	spin_lock_irqsave(common->lock, flags);
    106	reg = readl(common->base + common->reg);
    107	reg &= ~cf->select;
    108	writel(reg | sel, common->base + common->reg);
    109	spin_unlock_irqrestore(common->lock, flags);
    110
    111	ccu_helper_wait_for_lock(common, lock);
    112
    113	return 0;
    114}
    115EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_set_rate, SUNXI_CCU);