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

div.c (2368B)


      1// SPDX-License-Identifier: GPL-2.0
      2//
      3// Spreadtrum divider clock driver
      4//
      5// Copyright (C) 2017 Spreadtrum, Inc.
      6// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
      7
      8#include <linux/clk-provider.h>
      9
     10#include "div.h"
     11
     12long sprd_div_helper_round_rate(struct sprd_clk_common *common,
     13				const struct sprd_div_internal *div,
     14				unsigned long rate,
     15				unsigned long *parent_rate)
     16{
     17	return divider_round_rate(&common->hw, rate, parent_rate,
     18				  NULL, div->width, 0);
     19}
     20EXPORT_SYMBOL_GPL(sprd_div_helper_round_rate);
     21
     22static long sprd_div_round_rate(struct clk_hw *hw, unsigned long rate,
     23				unsigned long *parent_rate)
     24{
     25	struct sprd_div *cd = hw_to_sprd_div(hw);
     26
     27	return sprd_div_helper_round_rate(&cd->common, &cd->div,
     28					  rate, parent_rate);
     29}
     30
     31unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common,
     32					  const struct sprd_div_internal *div,
     33					  unsigned long parent_rate)
     34{
     35	unsigned long val;
     36	unsigned int reg;
     37
     38	regmap_read(common->regmap, common->reg, &reg);
     39	val = reg >> div->shift;
     40	val &= (1 << div->width) - 1;
     41
     42	return divider_recalc_rate(&common->hw, parent_rate, val, NULL, 0,
     43				   div->width);
     44}
     45EXPORT_SYMBOL_GPL(sprd_div_helper_recalc_rate);
     46
     47static unsigned long sprd_div_recalc_rate(struct clk_hw *hw,
     48					  unsigned long parent_rate)
     49{
     50	struct sprd_div *cd = hw_to_sprd_div(hw);
     51
     52	return sprd_div_helper_recalc_rate(&cd->common, &cd->div, parent_rate);
     53}
     54
     55int sprd_div_helper_set_rate(const struct sprd_clk_common *common,
     56			     const struct sprd_div_internal *div,
     57			     unsigned long rate,
     58			     unsigned long parent_rate)
     59{
     60	unsigned long val;
     61	unsigned int reg;
     62
     63	val = divider_get_val(rate, parent_rate, NULL,
     64			      div->width, 0);
     65
     66	regmap_read(common->regmap, common->reg, &reg);
     67	reg &= ~GENMASK(div->width + div->shift - 1, div->shift);
     68
     69	regmap_write(common->regmap, common->reg,
     70			  reg | (val << div->shift));
     71
     72	return 0;
     73
     74}
     75EXPORT_SYMBOL_GPL(sprd_div_helper_set_rate);
     76
     77static int sprd_div_set_rate(struct clk_hw *hw, unsigned long rate,
     78			     unsigned long parent_rate)
     79{
     80	struct sprd_div *cd = hw_to_sprd_div(hw);
     81
     82	return sprd_div_helper_set_rate(&cd->common, &cd->div,
     83					rate, parent_rate);
     84}
     85
     86const struct clk_ops sprd_div_ops = {
     87	.recalc_rate = sprd_div_recalc_rate,
     88	.round_rate = sprd_div_round_rate,
     89	.set_rate = sprd_div_set_rate,
     90};
     91EXPORT_SYMBOL_GPL(sprd_div_ops);