root/drivers/clk/meson/clk-cpu-dyndiv.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. meson_clk_cpu_dyndiv_data
  2. meson_clk_cpu_dyndiv_recalc_rate
  3. meson_clk_cpu_dyndiv_round_rate
  4. meson_clk_cpu_dyndiv_set_rate

   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 
  13 static inline struct meson_clk_cpu_dyndiv_data *
  14 meson_clk_cpu_dyndiv_data(struct clk_regmap *clk)
  15 {
  16         return (struct meson_clk_cpu_dyndiv_data *)clk->data;
  17 }
  18 
  19 static 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 
  30 static 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 
  40 static 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 
  64 const 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 };
  69 EXPORT_SYMBOL_GPL(meson_clk_cpu_dyndiv_ops);
  70 
  71 MODULE_DESCRIPTION("Amlogic CPU Dynamic Clock divider");
  72 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
  73 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */