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


      1// SPDX-License-Identifier: GPL-2.0
      2// Copyright (c) 2018, The Linux Foundation. All rights reserved.
      3
      4#include <linux/kernel.h>
      5#include <linux/module.h>
      6#include <linux/init.h>
      7#include <linux/io.h>
      8#include <linux/delay.h>
      9#include <linux/err.h>
     10#include <linux/clk-provider.h>
     11#include <linux/spinlock.h>
     12
     13#include <asm/krait-l2-accessors.h>
     14
     15#include "clk-krait.h"
     16
     17/* Secondary and primary muxes share the same cp15 register */
     18static DEFINE_SPINLOCK(krait_clock_reg_lock);
     19
     20#define LPL_SHIFT	8
     21static void __krait_mux_set_sel(struct krait_mux_clk *mux, int sel)
     22{
     23	unsigned long flags;
     24	u32 regval;
     25
     26	spin_lock_irqsave(&krait_clock_reg_lock, flags);
     27	regval = krait_get_l2_indirect_reg(mux->offset);
     28	regval &= ~(mux->mask << mux->shift);
     29	regval |= (sel & mux->mask) << mux->shift;
     30	if (mux->lpl) {
     31		regval &= ~(mux->mask << (mux->shift + LPL_SHIFT));
     32		regval |= (sel & mux->mask) << (mux->shift + LPL_SHIFT);
     33	}
     34	krait_set_l2_indirect_reg(mux->offset, regval);
     35	spin_unlock_irqrestore(&krait_clock_reg_lock, flags);
     36
     37	/* Wait for switch to complete. */
     38	mb();
     39	udelay(1);
     40}
     41
     42static int krait_mux_set_parent(struct clk_hw *hw, u8 index)
     43{
     44	struct krait_mux_clk *mux = to_krait_mux_clk(hw);
     45	u32 sel;
     46
     47	sel = clk_mux_index_to_val(mux->parent_map, 0, index);
     48	mux->en_mask = sel;
     49	/* Don't touch mux if CPU is off as it won't work */
     50	if (__clk_is_enabled(hw->clk))
     51		__krait_mux_set_sel(mux, sel);
     52
     53	mux->reparent = true;
     54
     55	return 0;
     56}
     57
     58static u8 krait_mux_get_parent(struct clk_hw *hw)
     59{
     60	struct krait_mux_clk *mux = to_krait_mux_clk(hw);
     61	u32 sel;
     62
     63	sel = krait_get_l2_indirect_reg(mux->offset);
     64	sel >>= mux->shift;
     65	sel &= mux->mask;
     66	mux->en_mask = sel;
     67
     68	return clk_mux_val_to_index(hw, mux->parent_map, 0, sel);
     69}
     70
     71const struct clk_ops krait_mux_clk_ops = {
     72	.set_parent = krait_mux_set_parent,
     73	.get_parent = krait_mux_get_parent,
     74	.determine_rate = __clk_mux_determine_rate_closest,
     75};
     76EXPORT_SYMBOL_GPL(krait_mux_clk_ops);
     77
     78/* The divider can divide by 2, 4, 6 and 8. But we only really need div-2. */
     79static long krait_div2_round_rate(struct clk_hw *hw, unsigned long rate,
     80				  unsigned long *parent_rate)
     81{
     82	*parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), rate * 2);
     83	return DIV_ROUND_UP(*parent_rate, 2);
     84}
     85
     86static int krait_div2_set_rate(struct clk_hw *hw, unsigned long rate,
     87			       unsigned long parent_rate)
     88{
     89	struct krait_div2_clk *d = to_krait_div2_clk(hw);
     90	unsigned long flags;
     91	u32 val;
     92	u32 mask = BIT(d->width) - 1;
     93
     94	if (d->lpl)
     95		mask = mask << (d->shift + LPL_SHIFT) | mask << d->shift;
     96
     97	spin_lock_irqsave(&krait_clock_reg_lock, flags);
     98	val = krait_get_l2_indirect_reg(d->offset);
     99	val &= ~mask;
    100	krait_set_l2_indirect_reg(d->offset, val);
    101	spin_unlock_irqrestore(&krait_clock_reg_lock, flags);
    102
    103	return 0;
    104}
    105
    106static unsigned long
    107krait_div2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
    108{
    109	struct krait_div2_clk *d = to_krait_div2_clk(hw);
    110	u32 mask = BIT(d->width) - 1;
    111	u32 div;
    112
    113	div = krait_get_l2_indirect_reg(d->offset);
    114	div >>= d->shift;
    115	div &= mask;
    116	div = (div + 1) * 2;
    117
    118	return DIV_ROUND_UP(parent_rate, div);
    119}
    120
    121const struct clk_ops krait_div2_clk_ops = {
    122	.round_rate = krait_div2_round_rate,
    123	.set_rate = krait_div2_set_rate,
    124	.recalc_rate = krait_div2_recalc_rate,
    125};
    126EXPORT_SYMBOL_GPL(krait_div2_clk_ops);