root/drivers/clk/imgtec/clk-boston.c

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

DEFINITIONS

This source file includes following definitions.
  1. ext_field
  2. clk_boston_setup

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright (C) 2016-2017 Imagination Technologies
   4  * Author: Paul Burton <paul.burton@mips.com>
   5  */
   6 
   7 #define pr_fmt(fmt) "clk-boston: " fmt
   8 
   9 #include <linux/clk-provider.h>
  10 #include <linux/kernel.h>
  11 #include <linux/of.h>
  12 #include <linux/regmap.h>
  13 #include <linux/slab.h>
  14 #include <linux/mfd/syscon.h>
  15 
  16 #include <dt-bindings/clock/boston-clock.h>
  17 
  18 #define BOSTON_PLAT_MMCMDIV             0x30
  19 # define BOSTON_PLAT_MMCMDIV_CLK0DIV    (0xff << 0)
  20 # define BOSTON_PLAT_MMCMDIV_INPUT      (0xff << 8)
  21 # define BOSTON_PLAT_MMCMDIV_MUL        (0xff << 16)
  22 # define BOSTON_PLAT_MMCMDIV_CLK1DIV    (0xff << 24)
  23 
  24 #define BOSTON_CLK_COUNT 3
  25 
  26 static u32 ext_field(u32 val, u32 mask)
  27 {
  28         return (val & mask) >> (ffs(mask) - 1);
  29 }
  30 
  31 static void __init clk_boston_setup(struct device_node *np)
  32 {
  33         unsigned long in_freq, cpu_freq, sys_freq;
  34         uint mmcmdiv, mul, cpu_div, sys_div;
  35         struct clk_hw_onecell_data *onecell;
  36         struct regmap *regmap;
  37         struct clk_hw *hw;
  38         int err;
  39 
  40         regmap = syscon_node_to_regmap(np->parent);
  41         if (IS_ERR(regmap)) {
  42                 pr_err("failed to find regmap\n");
  43                 return;
  44         }
  45 
  46         err = regmap_read(regmap, BOSTON_PLAT_MMCMDIV, &mmcmdiv);
  47         if (err) {
  48                 pr_err("failed to read mmcm_div register: %d\n", err);
  49                 return;
  50         }
  51 
  52         in_freq = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_INPUT) * 1000000;
  53         mul = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_MUL);
  54 
  55         sys_div = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_CLK0DIV);
  56         sys_freq = mult_frac(in_freq, mul, sys_div);
  57 
  58         cpu_div = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_CLK1DIV);
  59         cpu_freq = mult_frac(in_freq, mul, cpu_div);
  60 
  61         onecell = kzalloc(sizeof(*onecell) +
  62                           (BOSTON_CLK_COUNT * sizeof(struct clk_hw *)),
  63                           GFP_KERNEL);
  64         if (!onecell)
  65                 return;
  66 
  67         onecell->num = BOSTON_CLK_COUNT;
  68 
  69         hw = clk_hw_register_fixed_rate(NULL, "input", NULL, 0, in_freq);
  70         if (IS_ERR(hw)) {
  71                 pr_err("failed to register input clock: %ld\n", PTR_ERR(hw));
  72                 goto fail_input;
  73         }
  74         onecell->hws[BOSTON_CLK_INPUT] = hw;
  75 
  76         hw = clk_hw_register_fixed_rate(NULL, "sys", "input", 0, sys_freq);
  77         if (IS_ERR(hw)) {
  78                 pr_err("failed to register sys clock: %ld\n", PTR_ERR(hw));
  79                 goto fail_sys;
  80         }
  81         onecell->hws[BOSTON_CLK_SYS] = hw;
  82 
  83         hw = clk_hw_register_fixed_rate(NULL, "cpu", "input", 0, cpu_freq);
  84         if (IS_ERR(hw)) {
  85                 pr_err("failed to register cpu clock: %ld\n", PTR_ERR(hw));
  86                 goto fail_cpu;
  87         }
  88         onecell->hws[BOSTON_CLK_CPU] = hw;
  89 
  90         err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, onecell);
  91         if (err) {
  92                 pr_err("failed to add DT provider: %d\n", err);
  93                 goto fail_clk_add;
  94         }
  95 
  96         return;
  97 
  98 fail_clk_add:
  99         clk_hw_unregister_fixed_rate(onecell->hws[BOSTON_CLK_CPU]);
 100 fail_cpu:
 101         clk_hw_unregister_fixed_rate(onecell->hws[BOSTON_CLK_SYS]);
 102 fail_sys:
 103         clk_hw_unregister_fixed_rate(onecell->hws[BOSTON_CLK_INPUT]);
 104 fail_input:
 105         kfree(onecell);
 106 }
 107 
 108 /*
 109  * Use CLK_OF_DECLARE so that this driver is probed early enough to provide the
 110  * CPU frequency for use with the GIC or cop0 counters/timers.
 111  */
 112 CLK_OF_DECLARE(clk_boston, "img,boston-clock", clk_boston_setup);

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