linux/drivers/clk/at91/clk-utmi.c
<<
>>
Prefs
   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
  22struct 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
  30static 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
  39static 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
  94static 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
 101static 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
 109static 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
 116static 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
 123struct clk_hw * __init
 124at91_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}
 155