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-dyndiv.c (2228B)


      1// SPDX-License-Identifier: (GPL-2.0 OR MIT)
      2/*
      3 * Copyright (c) 2019 BayLibre, SAS.
      4 * Author: Neil Armstrong <narmstrong@baylibre.com>
      5 */
      6
      7#include <linux/clk-provider.h>
      8#include <linux/module.h>
      9
     10#include "clk-regmap.h"
     11#include "clk-cpu-dyndiv.h"
     12
     13static inline struct meson_clk_cpu_dyndiv_data *
     14meson_clk_cpu_dyndiv_data(struct clk_regmap *clk)
     15{
     16	return (struct meson_clk_cpu_dyndiv_data *)clk->data;
     17}
     18
     19static unsigned long meson_clk_cpu_dyndiv_recalc_rate(struct clk_hw *hw,
     20						      unsigned long prate)
     21{
     22	struct clk_regmap *clk = to_clk_regmap(hw);
     23	struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk);
     24
     25	return divider_recalc_rate(hw, prate,
     26				   meson_parm_read(clk->map, &data->div),
     27				   NULL, 0, data->div.width);
     28}
     29
     30static long meson_clk_cpu_dyndiv_round_rate(struct clk_hw *hw,
     31					    unsigned long rate,
     32					    unsigned long *prate)
     33{
     34	struct clk_regmap *clk = to_clk_regmap(hw);
     35	struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk);
     36
     37	return divider_round_rate(hw, rate, prate, NULL, data->div.width, 0);
     38}
     39
     40static int meson_clk_cpu_dyndiv_set_rate(struct clk_hw *hw, unsigned long rate,
     41					  unsigned long parent_rate)
     42{
     43	struct clk_regmap *clk = to_clk_regmap(hw);
     44	struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk);
     45	unsigned int val;
     46	int ret;
     47
     48	ret = divider_get_val(rate, parent_rate, NULL, data->div.width, 0);
     49	if (ret < 0)
     50		return ret;
     51
     52	val = (unsigned int)ret << data->div.shift;
     53
     54	/* Write the SYS_CPU_DYN_ENABLE bit before changing the divider */
     55	meson_parm_write(clk->map, &data->dyn, 1);
     56
     57	/* Update the divider while removing the SYS_CPU_DYN_ENABLE bit */
     58	return regmap_update_bits(clk->map, data->div.reg_off,
     59				  SETPMASK(data->div.width, data->div.shift) |
     60				  SETPMASK(data->dyn.width, data->dyn.shift),
     61				  val);
     62};
     63
     64const struct clk_ops meson_clk_cpu_dyndiv_ops = {
     65	.recalc_rate = meson_clk_cpu_dyndiv_recalc_rate,
     66	.round_rate = meson_clk_cpu_dyndiv_round_rate,
     67	.set_rate = meson_clk_cpu_dyndiv_set_rate,
     68};
     69EXPORT_SYMBOL_GPL(meson_clk_cpu_dyndiv_ops);
     70
     71MODULE_DESCRIPTION("Amlogic CPU Dynamic Clock divider");
     72MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
     73MODULE_LICENSE("GPL v2");