root/drivers/clk/ux500/clk-prcmu.c

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

DEFINITIONS

This source file includes following definitions.
  1. clk_prcmu_prepare
  2. clk_prcmu_unprepare
  3. clk_prcmu_is_prepared
  4. clk_prcmu_enable
  5. clk_prcmu_disable
  6. clk_prcmu_is_enabled
  7. clk_prcmu_recalc_rate
  8. clk_prcmu_round_rate
  9. clk_prcmu_set_rate
  10. clk_prcmu_opp_prepare
  11. clk_prcmu_opp_unprepare
  12. clk_prcmu_opp_volt_prepare
  13. clk_prcmu_opp_volt_unprepare
  14. clk_reg_prcmu
  15. clk_reg_prcmu_scalable
  16. clk_reg_prcmu_gate
  17. clk_reg_prcmu_scalable_rate
  18. clk_reg_prcmu_rate
  19. clk_reg_prcmu_opp_gate
  20. clk_reg_prcmu_opp_volt_scalable

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * PRCMU clock implementation for ux500 platform.
   4  *
   5  * Copyright (C) 2012 ST-Ericsson SA
   6  * Author: Ulf Hansson <ulf.hansson@linaro.org>
   7  */
   8 
   9 #include <linux/clk-provider.h>
  10 #include <linux/mfd/dbx500-prcmu.h>
  11 #include <linux/slab.h>
  12 #include <linux/io.h>
  13 #include <linux/err.h>
  14 #include "clk.h"
  15 
  16 #define to_clk_prcmu(_hw) container_of(_hw, struct clk_prcmu, hw)
  17 
  18 struct clk_prcmu {
  19         struct clk_hw hw;
  20         u8 cg_sel;
  21         int is_prepared;
  22         int is_enabled;
  23         int opp_requested;
  24 };
  25 
  26 /* PRCMU clock operations. */
  27 
  28 static int clk_prcmu_prepare(struct clk_hw *hw)
  29 {
  30         int ret;
  31         struct clk_prcmu *clk = to_clk_prcmu(hw);
  32 
  33         ret = prcmu_request_clock(clk->cg_sel, true);
  34         if (!ret)
  35                 clk->is_prepared = 1;
  36 
  37         return ret;
  38 }
  39 
  40 static void clk_prcmu_unprepare(struct clk_hw *hw)
  41 {
  42         struct clk_prcmu *clk = to_clk_prcmu(hw);
  43         if (prcmu_request_clock(clk->cg_sel, false))
  44                 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
  45                         clk_hw_get_name(hw));
  46         else
  47                 clk->is_prepared = 0;
  48 }
  49 
  50 static int clk_prcmu_is_prepared(struct clk_hw *hw)
  51 {
  52         struct clk_prcmu *clk = to_clk_prcmu(hw);
  53         return clk->is_prepared;
  54 }
  55 
  56 static int clk_prcmu_enable(struct clk_hw *hw)
  57 {
  58         struct clk_prcmu *clk = to_clk_prcmu(hw);
  59         clk->is_enabled = 1;
  60         return 0;
  61 }
  62 
  63 static void clk_prcmu_disable(struct clk_hw *hw)
  64 {
  65         struct clk_prcmu *clk = to_clk_prcmu(hw);
  66         clk->is_enabled = 0;
  67 }
  68 
  69 static int clk_prcmu_is_enabled(struct clk_hw *hw)
  70 {
  71         struct clk_prcmu *clk = to_clk_prcmu(hw);
  72         return clk->is_enabled;
  73 }
  74 
  75 static unsigned long clk_prcmu_recalc_rate(struct clk_hw *hw,
  76                                            unsigned long parent_rate)
  77 {
  78         struct clk_prcmu *clk = to_clk_prcmu(hw);
  79         return prcmu_clock_rate(clk->cg_sel);
  80 }
  81 
  82 static long clk_prcmu_round_rate(struct clk_hw *hw, unsigned long rate,
  83                                  unsigned long *parent_rate)
  84 {
  85         struct clk_prcmu *clk = to_clk_prcmu(hw);
  86         return prcmu_round_clock_rate(clk->cg_sel, rate);
  87 }
  88 
  89 static int clk_prcmu_set_rate(struct clk_hw *hw, unsigned long rate,
  90                               unsigned long parent_rate)
  91 {
  92         struct clk_prcmu *clk = to_clk_prcmu(hw);
  93         return prcmu_set_clock_rate(clk->cg_sel, rate);
  94 }
  95 
  96 static int clk_prcmu_opp_prepare(struct clk_hw *hw)
  97 {
  98         int err;
  99         struct clk_prcmu *clk = to_clk_prcmu(hw);
 100 
 101         if (!clk->opp_requested) {
 102                 err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP,
 103                                                 (char *)clk_hw_get_name(hw),
 104                                                 100);
 105                 if (err) {
 106                         pr_err("clk_prcmu: %s fail req APE OPP for %s.\n",
 107                                 __func__, clk_hw_get_name(hw));
 108                         return err;
 109                 }
 110                 clk->opp_requested = 1;
 111         }
 112 
 113         err = prcmu_request_clock(clk->cg_sel, true);
 114         if (err) {
 115                 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
 116                                         (char *)clk_hw_get_name(hw));
 117                 clk->opp_requested = 0;
 118                 return err;
 119         }
 120 
 121         clk->is_prepared = 1;
 122         return 0;
 123 }
 124 
 125 static void clk_prcmu_opp_unprepare(struct clk_hw *hw)
 126 {
 127         struct clk_prcmu *clk = to_clk_prcmu(hw);
 128 
 129         if (prcmu_request_clock(clk->cg_sel, false)) {
 130                 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
 131                         clk_hw_get_name(hw));
 132                 return;
 133         }
 134 
 135         if (clk->opp_requested) {
 136                 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
 137                                         (char *)clk_hw_get_name(hw));
 138                 clk->opp_requested = 0;
 139         }
 140 
 141         clk->is_prepared = 0;
 142 }
 143 
 144 static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
 145 {
 146         int err;
 147         struct clk_prcmu *clk = to_clk_prcmu(hw);
 148 
 149         if (!clk->opp_requested) {
 150                 err = prcmu_request_ape_opp_100_voltage(true);
 151                 if (err) {
 152                         pr_err("clk_prcmu: %s fail req APE OPP VOLT for %s.\n",
 153                                 __func__, clk_hw_get_name(hw));
 154                         return err;
 155                 }
 156                 clk->opp_requested = 1;
 157         }
 158 
 159         err = prcmu_request_clock(clk->cg_sel, true);
 160         if (err) {
 161                 prcmu_request_ape_opp_100_voltage(false);
 162                 clk->opp_requested = 0;
 163                 return err;
 164         }
 165 
 166         clk->is_prepared = 1;
 167         return 0;
 168 }
 169 
 170 static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw)
 171 {
 172         struct clk_prcmu *clk = to_clk_prcmu(hw);
 173 
 174         if (prcmu_request_clock(clk->cg_sel, false)) {
 175                 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
 176                         clk_hw_get_name(hw));
 177                 return;
 178         }
 179 
 180         if (clk->opp_requested) {
 181                 prcmu_request_ape_opp_100_voltage(false);
 182                 clk->opp_requested = 0;
 183         }
 184 
 185         clk->is_prepared = 0;
 186 }
 187 
 188 static const struct clk_ops clk_prcmu_scalable_ops = {
 189         .prepare = clk_prcmu_prepare,
 190         .unprepare = clk_prcmu_unprepare,
 191         .is_prepared = clk_prcmu_is_prepared,
 192         .enable = clk_prcmu_enable,
 193         .disable = clk_prcmu_disable,
 194         .is_enabled = clk_prcmu_is_enabled,
 195         .recalc_rate = clk_prcmu_recalc_rate,
 196         .round_rate = clk_prcmu_round_rate,
 197         .set_rate = clk_prcmu_set_rate,
 198 };
 199 
 200 static const struct clk_ops clk_prcmu_gate_ops = {
 201         .prepare = clk_prcmu_prepare,
 202         .unprepare = clk_prcmu_unprepare,
 203         .is_prepared = clk_prcmu_is_prepared,
 204         .enable = clk_prcmu_enable,
 205         .disable = clk_prcmu_disable,
 206         .is_enabled = clk_prcmu_is_enabled,
 207         .recalc_rate = clk_prcmu_recalc_rate,
 208 };
 209 
 210 static const struct clk_ops clk_prcmu_scalable_rate_ops = {
 211         .is_enabled = clk_prcmu_is_enabled,
 212         .recalc_rate = clk_prcmu_recalc_rate,
 213         .round_rate = clk_prcmu_round_rate,
 214         .set_rate = clk_prcmu_set_rate,
 215 };
 216 
 217 static const struct clk_ops clk_prcmu_rate_ops = {
 218         .is_enabled = clk_prcmu_is_enabled,
 219         .recalc_rate = clk_prcmu_recalc_rate,
 220 };
 221 
 222 static const struct clk_ops clk_prcmu_opp_gate_ops = {
 223         .prepare = clk_prcmu_opp_prepare,
 224         .unprepare = clk_prcmu_opp_unprepare,
 225         .is_prepared = clk_prcmu_is_prepared,
 226         .enable = clk_prcmu_enable,
 227         .disable = clk_prcmu_disable,
 228         .is_enabled = clk_prcmu_is_enabled,
 229         .recalc_rate = clk_prcmu_recalc_rate,
 230 };
 231 
 232 static const struct clk_ops clk_prcmu_opp_volt_scalable_ops = {
 233         .prepare = clk_prcmu_opp_volt_prepare,
 234         .unprepare = clk_prcmu_opp_volt_unprepare,
 235         .is_prepared = clk_prcmu_is_prepared,
 236         .enable = clk_prcmu_enable,
 237         .disable = clk_prcmu_disable,
 238         .is_enabled = clk_prcmu_is_enabled,
 239         .recalc_rate = clk_prcmu_recalc_rate,
 240         .round_rate = clk_prcmu_round_rate,
 241         .set_rate = clk_prcmu_set_rate,
 242 };
 243 
 244 static struct clk *clk_reg_prcmu(const char *name,
 245                                  const char *parent_name,
 246                                  u8 cg_sel,
 247                                  unsigned long rate,
 248                                  unsigned long flags,
 249                                  const struct clk_ops *clk_prcmu_ops)
 250 {
 251         struct clk_prcmu *clk;
 252         struct clk_init_data clk_prcmu_init;
 253         struct clk *clk_reg;
 254 
 255         if (!name) {
 256                 pr_err("clk_prcmu: %s invalid arguments passed\n", __func__);
 257                 return ERR_PTR(-EINVAL);
 258         }
 259 
 260         clk = kzalloc(sizeof(*clk), GFP_KERNEL);
 261         if (!clk)
 262                 return ERR_PTR(-ENOMEM);
 263 
 264         clk->cg_sel = cg_sel;
 265         clk->is_prepared = 1;
 266         clk->is_enabled = 1;
 267         clk->opp_requested = 0;
 268         /* "rate" can be used for changing the initial frequency */
 269         if (rate)
 270                 prcmu_set_clock_rate(cg_sel, rate);
 271 
 272         clk_prcmu_init.name = name;
 273         clk_prcmu_init.ops = clk_prcmu_ops;
 274         clk_prcmu_init.flags = flags;
 275         clk_prcmu_init.parent_names = (parent_name ? &parent_name : NULL);
 276         clk_prcmu_init.num_parents = (parent_name ? 1 : 0);
 277         clk->hw.init = &clk_prcmu_init;
 278 
 279         clk_reg = clk_register(NULL, &clk->hw);
 280         if (IS_ERR_OR_NULL(clk_reg))
 281                 goto free_clk;
 282 
 283         return clk_reg;
 284 
 285 free_clk:
 286         kfree(clk);
 287         pr_err("clk_prcmu: %s failed to register clk\n", __func__);
 288         return ERR_PTR(-ENOMEM);
 289 }
 290 
 291 struct clk *clk_reg_prcmu_scalable(const char *name,
 292                                    const char *parent_name,
 293                                    u8 cg_sel,
 294                                    unsigned long rate,
 295                                    unsigned long flags)
 296 {
 297         return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
 298                         &clk_prcmu_scalable_ops);
 299 }
 300 
 301 struct clk *clk_reg_prcmu_gate(const char *name,
 302                                const char *parent_name,
 303                                u8 cg_sel,
 304                                unsigned long flags)
 305 {
 306         return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
 307                         &clk_prcmu_gate_ops);
 308 }
 309 
 310 struct clk *clk_reg_prcmu_scalable_rate(const char *name,
 311                                         const char *parent_name,
 312                                         u8 cg_sel,
 313                                         unsigned long rate,
 314                                         unsigned long flags)
 315 {
 316         return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
 317                         &clk_prcmu_scalable_rate_ops);
 318 }
 319 
 320 struct clk *clk_reg_prcmu_rate(const char *name,
 321                                const char *parent_name,
 322                                u8 cg_sel,
 323                                unsigned long flags)
 324 {
 325         return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
 326                         &clk_prcmu_rate_ops);
 327 }
 328 
 329 struct clk *clk_reg_prcmu_opp_gate(const char *name,
 330                                    const char *parent_name,
 331                                    u8 cg_sel,
 332                                    unsigned long flags)
 333 {
 334         return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
 335                         &clk_prcmu_opp_gate_ops);
 336 }
 337 
 338 struct clk *clk_reg_prcmu_opp_volt_scalable(const char *name,
 339                                             const char *parent_name,
 340                                             u8 cg_sel,
 341                                             unsigned long rate,
 342                                             unsigned long flags)
 343 {
 344         return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
 345                         &clk_prcmu_opp_volt_scalable_ops);
 346 }

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