linux/drivers/clk/mxs/clk-pll.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright 2012 Freescale Semiconductor, Inc.
   4 */
   5
   6#include <linux/clk-provider.h>
   7#include <linux/delay.h>
   8#include <linux/err.h>
   9#include <linux/io.h>
  10#include <linux/slab.h>
  11#include "clk.h"
  12
  13/**
  14 * struct clk_pll - mxs pll clock
  15 * @hw: clk_hw for the pll
  16 * @base: base address of the pll
  17 * @power: the shift of power bit
  18 * @rate: the clock rate of the pll
  19 *
  20 * The mxs pll is a fixed rate clock with power and gate control,
  21 * and the shift of gate bit is always 31.
  22 */
  23struct clk_pll {
  24        struct clk_hw hw;
  25        void __iomem *base;
  26        u8 power;
  27        unsigned long rate;
  28};
  29
  30#define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw)
  31
  32static int clk_pll_prepare(struct clk_hw *hw)
  33{
  34        struct clk_pll *pll = to_clk_pll(hw);
  35
  36        writel_relaxed(1 << pll->power, pll->base + SET);
  37
  38        udelay(10);
  39
  40        return 0;
  41}
  42
  43static void clk_pll_unprepare(struct clk_hw *hw)
  44{
  45        struct clk_pll *pll = to_clk_pll(hw);
  46
  47        writel_relaxed(1 << pll->power, pll->base + CLR);
  48}
  49
  50static int clk_pll_enable(struct clk_hw *hw)
  51{
  52        struct clk_pll *pll = to_clk_pll(hw);
  53
  54        writel_relaxed(1 << 31, pll->base + CLR);
  55
  56        return 0;
  57}
  58
  59static void clk_pll_disable(struct clk_hw *hw)
  60{
  61        struct clk_pll *pll = to_clk_pll(hw);
  62
  63        writel_relaxed(1 << 31, pll->base + SET);
  64}
  65
  66static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
  67                                         unsigned long parent_rate)
  68{
  69        struct clk_pll *pll = to_clk_pll(hw);
  70
  71        return pll->rate;
  72}
  73
  74static const struct clk_ops clk_pll_ops = {
  75        .prepare = clk_pll_prepare,
  76        .unprepare = clk_pll_unprepare,
  77        .enable = clk_pll_enable,
  78        .disable = clk_pll_disable,
  79        .recalc_rate = clk_pll_recalc_rate,
  80};
  81
  82struct clk *mxs_clk_pll(const char *name, const char *parent_name,
  83                        void __iomem *base, u8 power, unsigned long rate)
  84{
  85        struct clk_pll *pll;
  86        struct clk *clk;
  87        struct clk_init_data init;
  88
  89        pll = kzalloc(sizeof(*pll), GFP_KERNEL);
  90        if (!pll)
  91                return ERR_PTR(-ENOMEM);
  92
  93        init.name = name;
  94        init.ops = &clk_pll_ops;
  95        init.flags = 0;
  96        init.parent_names = (parent_name ? &parent_name: NULL);
  97        init.num_parents = (parent_name ? 1 : 0);
  98
  99        pll->base = base;
 100        pll->rate = rate;
 101        pll->power = power;
 102        pll->hw.init = &init;
 103
 104        clk = clk_register(NULL, &pll->hw);
 105        if (IS_ERR(clk))
 106                kfree(pll);
 107
 108        return clk;
 109}
 110