/* * Copyright 2012 Freescale Semiconductor, Inc. * * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License * Version 2 or later at the following locations: * * http://www.opensource.org/licenses/gpl-license.html * http://www.gnu.org/copyleft/gpl.html */ #include #include #include #include #include "clk.h" #define SET 0x4 #define CLR 0x8 /** * struct clk_pll - mxs pll clock * @hw: clk_hw for the pll * @base: base address of the pll * @power: the shift of power bit * @rate: the clock rate of the pll * * The mxs pll is a fixed rate clock with power and gate control, * and the shift of gate bit is always 31. */ struct clk_pll { struct clk clk; const char *parent; void __iomem *base; u8 power; unsigned long rate; }; #define to_clk_pll(_hw) container_of(_hw, struct clk_pll, clk) static int clk_pll_enable(struct clk *clk) { struct clk_pll *pll = to_clk_pll(clk); writel(1 << pll->power, pll->base + SET); udelay(10); writel(1 << 31, pll->base + CLR); return 0; } static void clk_pll_disable(struct clk *clk) { struct clk_pll *pll = to_clk_pll(clk); writel(1 << 31, pll->base + SET); writel(1 << pll->power, pll->base + CLR); } static int clk_pll_is_enabled(struct clk *clk) { struct clk_pll *pll = to_clk_pll(clk); u32 val; val = readl(pll->base); if (val & (1 << 31)) return 0; else return 1; } static unsigned long clk_pll_recalc_rate(struct clk *clk, unsigned long parent_rate) { struct clk_pll *pll = to_clk_pll(clk); return pll->rate; } static const struct clk_ops clk_pll_ops = { .enable = clk_pll_enable, .disable = clk_pll_disable, .recalc_rate = clk_pll_recalc_rate, .is_enabled = clk_pll_is_enabled, }; struct clk *mxs_clk_pll(const char *name, const char *parent_name, void __iomem *base, u8 power, unsigned long rate) { struct clk_pll *pll; int ret; pll = xzalloc(sizeof(*pll)); pll->parent = parent_name; pll->clk.name = name; pll->clk.ops = &clk_pll_ops; pll->clk.parent_names = &pll->parent; pll->clk.num_parents = 1; pll->base = base; pll->rate = rate; pll->power = power; ret = clk_register(&pll->clk); if (ret) ERR_PTR(ret); return &pll->clk; }