Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright 2012 Freescale Semiconductor, Inc.
0004  */
0005 
0006 #include <linux/clk-provider.h>
0007 #include <linux/delay.h>
0008 #include <linux/err.h>
0009 #include <linux/io.h>
0010 #include <linux/slab.h>
0011 #include "clk.h"
0012 
0013 /**
0014  * struct clk_pll - mxs pll clock
0015  * @hw: clk_hw for the pll
0016  * @base: base address of the pll
0017  * @power: the shift of power bit
0018  * @rate: the clock rate of the pll
0019  *
0020  * The mxs pll is a fixed rate clock with power and gate control,
0021  * and the shift of gate bit is always 31.
0022  */
0023 struct clk_pll {
0024     struct clk_hw hw;
0025     void __iomem *base;
0026     u8 power;
0027     unsigned long rate;
0028 };
0029 
0030 #define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw)
0031 
0032 static int clk_pll_prepare(struct clk_hw *hw)
0033 {
0034     struct clk_pll *pll = to_clk_pll(hw);
0035 
0036     writel_relaxed(1 << pll->power, pll->base + SET);
0037 
0038     udelay(10);
0039 
0040     return 0;
0041 }
0042 
0043 static void clk_pll_unprepare(struct clk_hw *hw)
0044 {
0045     struct clk_pll *pll = to_clk_pll(hw);
0046 
0047     writel_relaxed(1 << pll->power, pll->base + CLR);
0048 }
0049 
0050 static int clk_pll_enable(struct clk_hw *hw)
0051 {
0052     struct clk_pll *pll = to_clk_pll(hw);
0053 
0054     writel_relaxed(1 << 31, pll->base + CLR);
0055 
0056     return 0;
0057 }
0058 
0059 static void clk_pll_disable(struct clk_hw *hw)
0060 {
0061     struct clk_pll *pll = to_clk_pll(hw);
0062 
0063     writel_relaxed(1 << 31, pll->base + SET);
0064 }
0065 
0066 static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
0067                      unsigned long parent_rate)
0068 {
0069     struct clk_pll *pll = to_clk_pll(hw);
0070 
0071     return pll->rate;
0072 }
0073 
0074 static const struct clk_ops clk_pll_ops = {
0075     .prepare = clk_pll_prepare,
0076     .unprepare = clk_pll_unprepare,
0077     .enable = clk_pll_enable,
0078     .disable = clk_pll_disable,
0079     .recalc_rate = clk_pll_recalc_rate,
0080 };
0081 
0082 struct clk *mxs_clk_pll(const char *name, const char *parent_name,
0083             void __iomem *base, u8 power, unsigned long rate)
0084 {
0085     struct clk_pll *pll;
0086     struct clk *clk;
0087     struct clk_init_data init;
0088 
0089     pll = kzalloc(sizeof(*pll), GFP_KERNEL);
0090     if (!pll)
0091         return ERR_PTR(-ENOMEM);
0092 
0093     init.name = name;
0094     init.ops = &clk_pll_ops;
0095     init.flags = 0;
0096     init.parent_names = (parent_name ? &parent_name: NULL);
0097     init.num_parents = (parent_name ? 1 : 0);
0098 
0099     pll->base = base;
0100     pll->rate = rate;
0101     pll->power = power;
0102     pll->hw.init = &init;
0103 
0104     clk = clk_register(NULL, &pll->hw);
0105     if (IS_ERR(clk))
0106         kfree(pll);
0107 
0108     return clk;
0109 }