root/drivers/clk/meson/clk-regmap.c

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

DEFINITIONS

This source file includes following definitions.
  1. clk_regmap_gate_endisable
  2. clk_regmap_gate_enable
  3. clk_regmap_gate_disable
  4. clk_regmap_gate_is_enabled
  5. clk_regmap_div_recalc_rate
  6. clk_regmap_div_round_rate
  7. clk_regmap_div_set_rate
  8. clk_regmap_mux_get_parent
  9. clk_regmap_mux_set_parent
  10. clk_regmap_mux_determine_rate

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (c) 2018 BayLibre, SAS.
   4  * Author: Jerome Brunet <jbrunet@baylibre.com>
   5  */
   6 
   7 #include <linux/module.h>
   8 #include "clk-regmap.h"
   9 
  10 static int clk_regmap_gate_endisable(struct clk_hw *hw, int enable)
  11 {
  12         struct clk_regmap *clk = to_clk_regmap(hw);
  13         struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk);
  14         int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
  15 
  16         set ^= enable;
  17 
  18         return regmap_update_bits(clk->map, gate->offset, BIT(gate->bit_idx),
  19                                   set ? BIT(gate->bit_idx) : 0);
  20 }
  21 
  22 static int clk_regmap_gate_enable(struct clk_hw *hw)
  23 {
  24         return clk_regmap_gate_endisable(hw, 1);
  25 }
  26 
  27 static void clk_regmap_gate_disable(struct clk_hw *hw)
  28 {
  29         clk_regmap_gate_endisable(hw, 0);
  30 }
  31 
  32 static int clk_regmap_gate_is_enabled(struct clk_hw *hw)
  33 {
  34         struct clk_regmap *clk = to_clk_regmap(hw);
  35         struct clk_regmap_gate_data *gate = clk_get_regmap_gate_data(clk);
  36         unsigned int val;
  37 
  38         regmap_read(clk->map, gate->offset, &val);
  39         if (gate->flags & CLK_GATE_SET_TO_DISABLE)
  40                 val ^= BIT(gate->bit_idx);
  41 
  42         val &= BIT(gate->bit_idx);
  43 
  44         return val ? 1 : 0;
  45 }
  46 
  47 const struct clk_ops clk_regmap_gate_ops = {
  48         .enable = clk_regmap_gate_enable,
  49         .disable = clk_regmap_gate_disable,
  50         .is_enabled = clk_regmap_gate_is_enabled,
  51 };
  52 EXPORT_SYMBOL_GPL(clk_regmap_gate_ops);
  53 
  54 const struct clk_ops clk_regmap_gate_ro_ops = {
  55         .is_enabled = clk_regmap_gate_is_enabled,
  56 };
  57 EXPORT_SYMBOL_GPL(clk_regmap_gate_ro_ops);
  58 
  59 static unsigned long clk_regmap_div_recalc_rate(struct clk_hw *hw,
  60                                                 unsigned long prate)
  61 {
  62         struct clk_regmap *clk = to_clk_regmap(hw);
  63         struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk);
  64         unsigned int val;
  65         int ret;
  66 
  67         ret = regmap_read(clk->map, div->offset, &val);
  68         if (ret)
  69                 /* Gives a hint that something is wrong */
  70                 return 0;
  71 
  72         val >>= div->shift;
  73         val &= clk_div_mask(div->width);
  74         return divider_recalc_rate(hw, prate, val, div->table, div->flags,
  75                                    div->width);
  76 }
  77 
  78 static long clk_regmap_div_round_rate(struct clk_hw *hw, unsigned long rate,
  79                                       unsigned long *prate)
  80 {
  81         struct clk_regmap *clk = to_clk_regmap(hw);
  82         struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk);
  83         unsigned int val;
  84         int ret;
  85 
  86         /* if read only, just return current value */
  87         if (div->flags & CLK_DIVIDER_READ_ONLY) {
  88                 ret = regmap_read(clk->map, div->offset, &val);
  89                 if (ret)
  90                         /* Gives a hint that something is wrong */
  91                         return 0;
  92 
  93                 val >>= div->shift;
  94                 val &= clk_div_mask(div->width);
  95 
  96                 return divider_ro_round_rate(hw, rate, prate, div->table,
  97                                              div->width, div->flags, val);
  98         }
  99 
 100         return divider_round_rate(hw, rate, prate, div->table, div->width,
 101                                   div->flags);
 102 }
 103 
 104 static int clk_regmap_div_set_rate(struct clk_hw *hw, unsigned long rate,
 105                                    unsigned long parent_rate)
 106 {
 107         struct clk_regmap *clk = to_clk_regmap(hw);
 108         struct clk_regmap_div_data *div = clk_get_regmap_div_data(clk);
 109         unsigned int val;
 110         int ret;
 111 
 112         ret = divider_get_val(rate, parent_rate, div->table, div->width,
 113                               div->flags);
 114         if (ret < 0)
 115                 return ret;
 116 
 117         val = (unsigned int)ret << div->shift;
 118         return regmap_update_bits(clk->map, div->offset,
 119                                   clk_div_mask(div->width) << div->shift, val);
 120 };
 121 
 122 /* Would prefer clk_regmap_div_ro_ops but clashes with qcom */
 123 
 124 const struct clk_ops clk_regmap_divider_ops = {
 125         .recalc_rate = clk_regmap_div_recalc_rate,
 126         .round_rate = clk_regmap_div_round_rate,
 127         .set_rate = clk_regmap_div_set_rate,
 128 };
 129 EXPORT_SYMBOL_GPL(clk_regmap_divider_ops);
 130 
 131 const struct clk_ops clk_regmap_divider_ro_ops = {
 132         .recalc_rate = clk_regmap_div_recalc_rate,
 133         .round_rate = clk_regmap_div_round_rate,
 134 };
 135 EXPORT_SYMBOL_GPL(clk_regmap_divider_ro_ops);
 136 
 137 static u8 clk_regmap_mux_get_parent(struct clk_hw *hw)
 138 {
 139         struct clk_regmap *clk = to_clk_regmap(hw);
 140         struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk);
 141         unsigned int val;
 142         int ret;
 143 
 144         ret = regmap_read(clk->map, mux->offset, &val);
 145         if (ret)
 146                 return ret;
 147 
 148         val >>= mux->shift;
 149         val &= mux->mask;
 150         return clk_mux_val_to_index(hw, mux->table, mux->flags, val);
 151 }
 152 
 153 static int clk_regmap_mux_set_parent(struct clk_hw *hw, u8 index)
 154 {
 155         struct clk_regmap *clk = to_clk_regmap(hw);
 156         struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk);
 157         unsigned int val = clk_mux_index_to_val(mux->table, mux->flags, index);
 158 
 159         return regmap_update_bits(clk->map, mux->offset,
 160                                   mux->mask << mux->shift,
 161                                   val << mux->shift);
 162 }
 163 
 164 static int clk_regmap_mux_determine_rate(struct clk_hw *hw,
 165                                          struct clk_rate_request *req)
 166 {
 167         struct clk_regmap *clk = to_clk_regmap(hw);
 168         struct clk_regmap_mux_data *mux = clk_get_regmap_mux_data(clk);
 169 
 170         return clk_mux_determine_rate_flags(hw, req, mux->flags);
 171 }
 172 
 173 const struct clk_ops clk_regmap_mux_ops = {
 174         .get_parent = clk_regmap_mux_get_parent,
 175         .set_parent = clk_regmap_mux_set_parent,
 176         .determine_rate = clk_regmap_mux_determine_rate,
 177 };
 178 EXPORT_SYMBOL_GPL(clk_regmap_mux_ops);
 179 
 180 const struct clk_ops clk_regmap_mux_ro_ops = {
 181         .get_parent = clk_regmap_mux_get_parent,
 182 };
 183 EXPORT_SYMBOL_GPL(clk_regmap_mux_ro_ops);
 184 
 185 MODULE_DESCRIPTION("Amlogic regmap backed clock driver");
 186 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
 187 MODULE_LICENSE("GPL v2");

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