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


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2014 Lucas Stach <l.stach@pengutronix.de>, Pengutronix
      4 */
      5
      6#include <linux/clk.h>
      7#include <linux/clk-provider.h>
      8#include <linux/export.h>
      9#include <linux/slab.h>
     10#include "clk.h"
     11
     12struct clk_cpu {
     13	struct clk_hw	hw;
     14	struct clk	*div;
     15	struct clk	*mux;
     16	struct clk	*pll;
     17	struct clk	*step;
     18};
     19
     20static inline struct clk_cpu *to_clk_cpu(struct clk_hw *hw)
     21{
     22	return container_of(hw, struct clk_cpu, hw);
     23}
     24
     25static unsigned long clk_cpu_recalc_rate(struct clk_hw *hw,
     26					 unsigned long parent_rate)
     27{
     28	struct clk_cpu *cpu = to_clk_cpu(hw);
     29
     30	return clk_get_rate(cpu->div);
     31}
     32
     33static long clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
     34			       unsigned long *prate)
     35{
     36	struct clk_cpu *cpu = to_clk_cpu(hw);
     37
     38	return clk_round_rate(cpu->pll, rate);
     39}
     40
     41static int clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
     42			    unsigned long parent_rate)
     43{
     44	struct clk_cpu *cpu = to_clk_cpu(hw);
     45	int ret;
     46
     47	/* switch to PLL bypass clock */
     48	ret = clk_set_parent(cpu->mux, cpu->step);
     49	if (ret)
     50		return ret;
     51
     52	/* reprogram PLL */
     53	ret = clk_set_rate(cpu->pll, rate);
     54	if (ret) {
     55		clk_set_parent(cpu->mux, cpu->pll);
     56		return ret;
     57	}
     58	/* switch back to PLL clock */
     59	clk_set_parent(cpu->mux, cpu->pll);
     60
     61	/* Ensure the divider is what we expect */
     62	clk_set_rate(cpu->div, rate);
     63
     64	return 0;
     65}
     66
     67static const struct clk_ops clk_cpu_ops = {
     68	.recalc_rate	= clk_cpu_recalc_rate,
     69	.round_rate	= clk_cpu_round_rate,
     70	.set_rate	= clk_cpu_set_rate,
     71};
     72
     73struct clk_hw *imx_clk_hw_cpu(const char *name, const char *parent_name,
     74		struct clk *div, struct clk *mux, struct clk *pll,
     75		struct clk *step)
     76{
     77	struct clk_cpu *cpu;
     78	struct clk_hw *hw;
     79	struct clk_init_data init;
     80	int ret;
     81
     82	cpu = kzalloc(sizeof(*cpu), GFP_KERNEL);
     83	if (!cpu)
     84		return ERR_PTR(-ENOMEM);
     85
     86	cpu->div = div;
     87	cpu->mux = mux;
     88	cpu->pll = pll;
     89	cpu->step = step;
     90
     91	init.name = name;
     92	init.ops = &clk_cpu_ops;
     93	init.flags = CLK_IS_CRITICAL;
     94	init.parent_names = &parent_name;
     95	init.num_parents = 1;
     96
     97	cpu->hw.init = &init;
     98	hw = &cpu->hw;
     99
    100	ret = clk_hw_register(NULL, hw);
    101	if (ret) {
    102		kfree(cpu);
    103		return ERR_PTR(ret);
    104	}
    105
    106	return hw;
    107}
    108EXPORT_SYMBOL_GPL(imx_clk_hw_cpu);