linux/drivers/clk/actions/owl-composite.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2//
   3// OWL composite clock driver
   4//
   5// Copyright (c) 2014 Actions Semi Inc.
   6// Author: David Liu <liuwei@actions-semi.com>
   7//
   8// Copyright (c) 2018 Linaro Ltd.
   9// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
  10
  11#include <linux/clk-provider.h>
  12#include <linux/regmap.h>
  13
  14#include "owl-composite.h"
  15
  16static u8 owl_comp_get_parent(struct clk_hw *hw)
  17{
  18        struct owl_composite *comp = hw_to_owl_comp(hw);
  19
  20        return owl_mux_helper_get_parent(&comp->common, &comp->mux_hw);
  21}
  22
  23static int owl_comp_set_parent(struct clk_hw *hw, u8 index)
  24{
  25        struct owl_composite *comp = hw_to_owl_comp(hw);
  26
  27        return owl_mux_helper_set_parent(&comp->common, &comp->mux_hw, index);
  28}
  29
  30static void owl_comp_disable(struct clk_hw *hw)
  31{
  32        struct owl_composite *comp = hw_to_owl_comp(hw);
  33        struct owl_clk_common *common = &comp->common;
  34
  35        owl_gate_set(common, &comp->gate_hw, false);
  36}
  37
  38static int owl_comp_enable(struct clk_hw *hw)
  39{
  40        struct owl_composite *comp = hw_to_owl_comp(hw);
  41        struct owl_clk_common *common = &comp->common;
  42
  43        owl_gate_set(common, &comp->gate_hw, true);
  44
  45        return 0;
  46}
  47
  48static int owl_comp_is_enabled(struct clk_hw *hw)
  49{
  50        struct owl_composite *comp = hw_to_owl_comp(hw);
  51        struct owl_clk_common *common = &comp->common;
  52
  53        return owl_gate_clk_is_enabled(common, &comp->gate_hw);
  54}
  55
  56static long owl_comp_div_round_rate(struct clk_hw *hw, unsigned long rate,
  57                                unsigned long *parent_rate)
  58{
  59        struct owl_composite *comp = hw_to_owl_comp(hw);
  60
  61        return owl_divider_helper_round_rate(&comp->common, &comp->rate.div_hw,
  62                                        rate, parent_rate);
  63}
  64
  65static unsigned long owl_comp_div_recalc_rate(struct clk_hw *hw,
  66                                          unsigned long parent_rate)
  67{
  68        struct owl_composite *comp = hw_to_owl_comp(hw);
  69
  70        return owl_divider_helper_recalc_rate(&comp->common, &comp->rate.div_hw,
  71                                        parent_rate);
  72}
  73
  74static int owl_comp_div_set_rate(struct clk_hw *hw, unsigned long rate,
  75                                unsigned long parent_rate)
  76{
  77        struct owl_composite *comp = hw_to_owl_comp(hw);
  78
  79        return owl_divider_helper_set_rate(&comp->common, &comp->rate.div_hw,
  80                                        rate, parent_rate);
  81}
  82
  83static long owl_comp_fact_round_rate(struct clk_hw *hw, unsigned long rate,
  84                        unsigned long *parent_rate)
  85{
  86        struct owl_composite *comp = hw_to_owl_comp(hw);
  87
  88        return owl_factor_helper_round_rate(&comp->common,
  89                                        &comp->rate.factor_hw,
  90                                        rate, parent_rate);
  91}
  92
  93static unsigned long owl_comp_fact_recalc_rate(struct clk_hw *hw,
  94                        unsigned long parent_rate)
  95{
  96        struct owl_composite *comp = hw_to_owl_comp(hw);
  97
  98        return owl_factor_helper_recalc_rate(&comp->common,
  99                                        &comp->rate.factor_hw,
 100                                        parent_rate);
 101}
 102
 103static int owl_comp_fact_set_rate(struct clk_hw *hw, unsigned long rate,
 104                        unsigned long parent_rate)
 105{
 106        struct owl_composite *comp = hw_to_owl_comp(hw);
 107
 108        return owl_factor_helper_set_rate(&comp->common,
 109                                        &comp->rate.factor_hw,
 110                                        rate, parent_rate);
 111}
 112
 113static long owl_comp_fix_fact_round_rate(struct clk_hw *hw, unsigned long rate,
 114                        unsigned long *parent_rate)
 115{
 116        struct owl_composite *comp = hw_to_owl_comp(hw);
 117        struct clk_fixed_factor *fix_fact_hw = &comp->rate.fix_fact_hw;
 118
 119        return comp->fix_fact_ops->round_rate(&fix_fact_hw->hw, rate, parent_rate);
 120}
 121
 122static unsigned long owl_comp_fix_fact_recalc_rate(struct clk_hw *hw,
 123                        unsigned long parent_rate)
 124{
 125        struct owl_composite *comp = hw_to_owl_comp(hw);
 126        struct clk_fixed_factor *fix_fact_hw = &comp->rate.fix_fact_hw;
 127
 128        return comp->fix_fact_ops->recalc_rate(&fix_fact_hw->hw, parent_rate);
 129
 130}
 131
 132static int owl_comp_fix_fact_set_rate(struct clk_hw *hw, unsigned long rate,
 133                        unsigned long parent_rate)
 134{
 135        /*
 136         * We must report success but we can do so unconditionally because
 137         * owl_comp_fix_fact_round_rate returns values that ensure this call is
 138         * a nop.
 139         */
 140
 141        return 0;
 142}
 143
 144const struct clk_ops owl_comp_div_ops = {
 145        /* mux_ops */
 146        .get_parent     = owl_comp_get_parent,
 147        .set_parent     = owl_comp_set_parent,
 148
 149        /* gate_ops */
 150        .disable        = owl_comp_disable,
 151        .enable         = owl_comp_enable,
 152        .is_enabled     = owl_comp_is_enabled,
 153
 154        /* div_ops */
 155        .round_rate     = owl_comp_div_round_rate,
 156        .recalc_rate    = owl_comp_div_recalc_rate,
 157        .set_rate       = owl_comp_div_set_rate,
 158};
 159
 160
 161const struct clk_ops owl_comp_fact_ops = {
 162        /* mux_ops */
 163        .get_parent     = owl_comp_get_parent,
 164        .set_parent     = owl_comp_set_parent,
 165
 166        /* gate_ops */
 167        .disable        = owl_comp_disable,
 168        .enable         = owl_comp_enable,
 169        .is_enabled     = owl_comp_is_enabled,
 170
 171        /* fact_ops */
 172        .round_rate     = owl_comp_fact_round_rate,
 173        .recalc_rate    = owl_comp_fact_recalc_rate,
 174        .set_rate       = owl_comp_fact_set_rate,
 175};
 176
 177const struct clk_ops owl_comp_fix_fact_ops = {
 178        /* gate_ops */
 179        .disable        = owl_comp_disable,
 180        .enable         = owl_comp_enable,
 181        .is_enabled     = owl_comp_is_enabled,
 182
 183        /* fix_fact_ops */
 184        .round_rate     = owl_comp_fix_fact_round_rate,
 185        .recalc_rate    = owl_comp_fix_fact_recalc_rate,
 186        .set_rate       = owl_comp_fix_fact_set_rate,
 187};
 188
 189
 190const struct clk_ops owl_comp_pass_ops = {
 191        /* mux_ops */
 192        .get_parent     = owl_comp_get_parent,
 193        .set_parent     = owl_comp_set_parent,
 194
 195        /* gate_ops */
 196        .disable        = owl_comp_disable,
 197        .enable         = owl_comp_enable,
 198        .is_enabled     = owl_comp_is_enabled,
 199};
 200