root/drivers/clk/at91/clk-system.c

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

DEFINITIONS

This source file includes following definitions.
  1. is_pck
  2. clk_system_ready
  3. clk_system_prepare
  4. clk_system_unprepare
  5. clk_system_is_prepared
  6. at91_clk_register_system

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
   4  */
   5 
   6 #include <linux/clk-provider.h>
   7 #include <linux/clkdev.h>
   8 #include <linux/clk/at91_pmc.h>
   9 #include <linux/of.h>
  10 #include <linux/mfd/syscon.h>
  11 #include <linux/regmap.h>
  12 
  13 #include "pmc.h"
  14 
  15 #define SYSTEM_MAX_ID           31
  16 
  17 #define SYSTEM_MAX_NAME_SZ      32
  18 
  19 #define to_clk_system(hw) container_of(hw, struct clk_system, hw)
  20 struct clk_system {
  21         struct clk_hw hw;
  22         struct regmap *regmap;
  23         u8 id;
  24 };
  25 
  26 static inline int is_pck(int id)
  27 {
  28         return (id >= 8) && (id <= 15);
  29 }
  30 
  31 static inline bool clk_system_ready(struct regmap *regmap, int id)
  32 {
  33         unsigned int status;
  34 
  35         regmap_read(regmap, AT91_PMC_SR, &status);
  36 
  37         return status & (1 << id) ? 1 : 0;
  38 }
  39 
  40 static int clk_system_prepare(struct clk_hw *hw)
  41 {
  42         struct clk_system *sys = to_clk_system(hw);
  43 
  44         regmap_write(sys->regmap, AT91_PMC_SCER, 1 << sys->id);
  45 
  46         if (!is_pck(sys->id))
  47                 return 0;
  48 
  49         while (!clk_system_ready(sys->regmap, sys->id))
  50                 cpu_relax();
  51 
  52         return 0;
  53 }
  54 
  55 static void clk_system_unprepare(struct clk_hw *hw)
  56 {
  57         struct clk_system *sys = to_clk_system(hw);
  58 
  59         regmap_write(sys->regmap, AT91_PMC_SCDR, 1 << sys->id);
  60 }
  61 
  62 static int clk_system_is_prepared(struct clk_hw *hw)
  63 {
  64         struct clk_system *sys = to_clk_system(hw);
  65         unsigned int status;
  66 
  67         regmap_read(sys->regmap, AT91_PMC_SCSR, &status);
  68 
  69         if (!(status & (1 << sys->id)))
  70                 return 0;
  71 
  72         if (!is_pck(sys->id))
  73                 return 1;
  74 
  75         regmap_read(sys->regmap, AT91_PMC_SR, &status);
  76 
  77         return status & (1 << sys->id) ? 1 : 0;
  78 }
  79 
  80 static const struct clk_ops system_ops = {
  81         .prepare = clk_system_prepare,
  82         .unprepare = clk_system_unprepare,
  83         .is_prepared = clk_system_is_prepared,
  84 };
  85 
  86 struct clk_hw * __init
  87 at91_clk_register_system(struct regmap *regmap, const char *name,
  88                          const char *parent_name, u8 id)
  89 {
  90         struct clk_system *sys;
  91         struct clk_hw *hw;
  92         struct clk_init_data init;
  93         int ret;
  94 
  95         if (!parent_name || id > SYSTEM_MAX_ID)
  96                 return ERR_PTR(-EINVAL);
  97 
  98         sys = kzalloc(sizeof(*sys), GFP_KERNEL);
  99         if (!sys)
 100                 return ERR_PTR(-ENOMEM);
 101 
 102         init.name = name;
 103         init.ops = &system_ops;
 104         init.parent_names = &parent_name;
 105         init.num_parents = 1;
 106         init.flags = CLK_SET_RATE_PARENT;
 107 
 108         sys->id = id;
 109         sys->hw.init = &init;
 110         sys->regmap = regmap;
 111 
 112         hw = &sys->hw;
 113         ret = clk_hw_register(NULL, &sys->hw);
 114         if (ret) {
 115                 kfree(sys);
 116                 hw = ERR_PTR(ret);
 117         }
 118 
 119         return hw;
 120 }

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