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

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

DEFINITIONS

This source file includes following definitions.
  1. clk_utmi_ready
  2. clk_utmi_prepare
  3. clk_utmi_is_prepared
  4. clk_utmi_unprepare
  5. clk_utmi_recalc_rate
  6. at91_clk_register_utmi

   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 #include <soc/at91/atmel-sfr.h>
  13 
  14 #include "pmc.h"
  15 
  16 /*
  17  * The purpose of this clock is to generate a 480 MHz signal. A different
  18  * rate can't be configured.
  19  */
  20 #define UTMI_RATE       480000000
  21 
  22 struct clk_utmi {
  23         struct clk_hw hw;
  24         struct regmap *regmap_pmc;
  25         struct regmap *regmap_sfr;
  26 };
  27 
  28 #define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw)
  29 
  30 static inline bool clk_utmi_ready(struct regmap *regmap)
  31 {
  32         unsigned int status;
  33 
  34         regmap_read(regmap, AT91_PMC_SR, &status);
  35 
  36         return status & AT91_PMC_LOCKU;
  37 }
  38 
  39 static int clk_utmi_prepare(struct clk_hw *hw)
  40 {
  41         struct clk_hw *hw_parent;
  42         struct clk_utmi *utmi = to_clk_utmi(hw);
  43         unsigned int uckr = AT91_PMC_UPLLEN | AT91_PMC_UPLLCOUNT |
  44                             AT91_PMC_BIASEN;
  45         unsigned int utmi_ref_clk_freq;
  46         unsigned long parent_rate;
  47 
  48         /*
  49          * If mainck rate is different from 12 MHz, we have to configure the
  50          * FREQ field of the SFR_UTMICKTRIM register to generate properly
  51          * the utmi clock.
  52          */
  53         hw_parent = clk_hw_get_parent(hw);
  54         parent_rate = clk_hw_get_rate(hw_parent);
  55 
  56         switch (parent_rate) {
  57         case 12000000:
  58                 utmi_ref_clk_freq = 0;
  59                 break;
  60         case 16000000:
  61                 utmi_ref_clk_freq = 1;
  62                 break;
  63         case 24000000:
  64                 utmi_ref_clk_freq = 2;
  65                 break;
  66         /*
  67          * Not supported on SAMA5D2 but it's not an issue since MAINCK
  68          * maximum value is 24 MHz.
  69          */
  70         case 48000000:
  71                 utmi_ref_clk_freq = 3;
  72                 break;
  73         default:
  74                 pr_err("UTMICK: unsupported mainck rate\n");
  75                 return -EINVAL;
  76         }
  77 
  78         if (utmi->regmap_sfr) {
  79                 regmap_update_bits(utmi->regmap_sfr, AT91_SFR_UTMICKTRIM,
  80                                    AT91_UTMICKTRIM_FREQ, utmi_ref_clk_freq);
  81         } else if (utmi_ref_clk_freq) {
  82                 pr_err("UTMICK: sfr node required\n");
  83                 return -EINVAL;
  84         }
  85 
  86         regmap_update_bits(utmi->regmap_pmc, AT91_CKGR_UCKR, uckr, uckr);
  87 
  88         while (!clk_utmi_ready(utmi->regmap_pmc))
  89                 cpu_relax();
  90 
  91         return 0;
  92 }
  93 
  94 static int clk_utmi_is_prepared(struct clk_hw *hw)
  95 {
  96         struct clk_utmi *utmi = to_clk_utmi(hw);
  97 
  98         return clk_utmi_ready(utmi->regmap_pmc);
  99 }
 100 
 101 static void clk_utmi_unprepare(struct clk_hw *hw)
 102 {
 103         struct clk_utmi *utmi = to_clk_utmi(hw);
 104 
 105         regmap_update_bits(utmi->regmap_pmc, AT91_CKGR_UCKR,
 106                            AT91_PMC_UPLLEN, 0);
 107 }
 108 
 109 static unsigned long clk_utmi_recalc_rate(struct clk_hw *hw,
 110                                           unsigned long parent_rate)
 111 {
 112         /* UTMI clk rate is fixed. */
 113         return UTMI_RATE;
 114 }
 115 
 116 static const struct clk_ops utmi_ops = {
 117         .prepare = clk_utmi_prepare,
 118         .unprepare = clk_utmi_unprepare,
 119         .is_prepared = clk_utmi_is_prepared,
 120         .recalc_rate = clk_utmi_recalc_rate,
 121 };
 122 
 123 struct clk_hw * __init
 124 at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
 125                        const char *name, const char *parent_name)
 126 {
 127         struct clk_utmi *utmi;
 128         struct clk_hw *hw;
 129         struct clk_init_data init;
 130         int ret;
 131 
 132         utmi = kzalloc(sizeof(*utmi), GFP_KERNEL);
 133         if (!utmi)
 134                 return ERR_PTR(-ENOMEM);
 135 
 136         init.name = name;
 137         init.ops = &utmi_ops;
 138         init.parent_names = parent_name ? &parent_name : NULL;
 139         init.num_parents = parent_name ? 1 : 0;
 140         init.flags = CLK_SET_RATE_GATE;
 141 
 142         utmi->hw.init = &init;
 143         utmi->regmap_pmc = regmap_pmc;
 144         utmi->regmap_sfr = regmap_sfr;
 145 
 146         hw = &utmi->hw;
 147         ret = clk_hw_register(NULL, &utmi->hw);
 148         if (ret) {
 149                 kfree(utmi);
 150                 hw = ERR_PTR(ret);
 151         }
 152 
 153         return hw;
 154 }

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