Linux Audio

Check our new training course

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