1*fcaf2036SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
223b5e15aSShawn Guo /*
323b5e15aSShawn Guo * Copyright 2012 Freescale Semiconductor, Inc.
423b5e15aSShawn Guo */
523b5e15aSShawn Guo
623b5e15aSShawn Guo #include <linux/clk-provider.h>
723b5e15aSShawn Guo #include <linux/delay.h>
823b5e15aSShawn Guo #include <linux/err.h>
923b5e15aSShawn Guo #include <linux/io.h>
1023b5e15aSShawn Guo #include <linux/slab.h>
1123b5e15aSShawn Guo #include "clk.h"
1223b5e15aSShawn Guo
1323b5e15aSShawn Guo /**
1423b5e15aSShawn Guo * struct clk_pll - mxs pll clock
1523b5e15aSShawn Guo * @hw: clk_hw for the pll
1623b5e15aSShawn Guo * @base: base address of the pll
1723b5e15aSShawn Guo * @power: the shift of power bit
1823b5e15aSShawn Guo * @rate: the clock rate of the pll
1923b5e15aSShawn Guo *
2023b5e15aSShawn Guo * The mxs pll is a fixed rate clock with power and gate control,
2123b5e15aSShawn Guo * and the shift of gate bit is always 31.
2223b5e15aSShawn Guo */
2323b5e15aSShawn Guo struct clk_pll {
2423b5e15aSShawn Guo struct clk_hw hw;
2523b5e15aSShawn Guo void __iomem *base;
2623b5e15aSShawn Guo u8 power;
2723b5e15aSShawn Guo unsigned long rate;
2823b5e15aSShawn Guo };
2923b5e15aSShawn Guo
3023b5e15aSShawn Guo #define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw)
3123b5e15aSShawn Guo
clk_pll_prepare(struct clk_hw * hw)3223b5e15aSShawn Guo static int clk_pll_prepare(struct clk_hw *hw)
3323b5e15aSShawn Guo {
3423b5e15aSShawn Guo struct clk_pll *pll = to_clk_pll(hw);
3523b5e15aSShawn Guo
3623b5e15aSShawn Guo writel_relaxed(1 << pll->power, pll->base + SET);
3723b5e15aSShawn Guo
3823b5e15aSShawn Guo udelay(10);
3923b5e15aSShawn Guo
4023b5e15aSShawn Guo return 0;
4123b5e15aSShawn Guo }
4223b5e15aSShawn Guo
clk_pll_unprepare(struct clk_hw * hw)4323b5e15aSShawn Guo static void clk_pll_unprepare(struct clk_hw *hw)
4423b5e15aSShawn Guo {
4523b5e15aSShawn Guo struct clk_pll *pll = to_clk_pll(hw);
4623b5e15aSShawn Guo
4723b5e15aSShawn Guo writel_relaxed(1 << pll->power, pll->base + CLR);
4823b5e15aSShawn Guo }
4923b5e15aSShawn Guo
clk_pll_enable(struct clk_hw * hw)5023b5e15aSShawn Guo static int clk_pll_enable(struct clk_hw *hw)
5123b5e15aSShawn Guo {
5223b5e15aSShawn Guo struct clk_pll *pll = to_clk_pll(hw);
5323b5e15aSShawn Guo
5423b5e15aSShawn Guo writel_relaxed(1 << 31, pll->base + CLR);
5523b5e15aSShawn Guo
5623b5e15aSShawn Guo return 0;
5723b5e15aSShawn Guo }
5823b5e15aSShawn Guo
clk_pll_disable(struct clk_hw * hw)5923b5e15aSShawn Guo static void clk_pll_disable(struct clk_hw *hw)
6023b5e15aSShawn Guo {
6123b5e15aSShawn Guo struct clk_pll *pll = to_clk_pll(hw);
6223b5e15aSShawn Guo
6323b5e15aSShawn Guo writel_relaxed(1 << 31, pll->base + SET);
6423b5e15aSShawn Guo }
6523b5e15aSShawn Guo
clk_pll_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)6623b5e15aSShawn Guo static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
6723b5e15aSShawn Guo unsigned long parent_rate)
6823b5e15aSShawn Guo {
6923b5e15aSShawn Guo struct clk_pll *pll = to_clk_pll(hw);
7023b5e15aSShawn Guo
7123b5e15aSShawn Guo return pll->rate;
7223b5e15aSShawn Guo }
7323b5e15aSShawn Guo
7423b5e15aSShawn Guo static const struct clk_ops clk_pll_ops = {
7523b5e15aSShawn Guo .prepare = clk_pll_prepare,
7623b5e15aSShawn Guo .unprepare = clk_pll_unprepare,
7723b5e15aSShawn Guo .enable = clk_pll_enable,
7823b5e15aSShawn Guo .disable = clk_pll_disable,
7923b5e15aSShawn Guo .recalc_rate = clk_pll_recalc_rate,
8023b5e15aSShawn Guo };
8123b5e15aSShawn Guo
mxs_clk_pll(const char * name,const char * parent_name,void __iomem * base,u8 power,unsigned long rate)8223b5e15aSShawn Guo struct clk *mxs_clk_pll(const char *name, const char *parent_name,
8323b5e15aSShawn Guo void __iomem *base, u8 power, unsigned long rate)
8423b5e15aSShawn Guo {
8523b5e15aSShawn Guo struct clk_pll *pll;
8623b5e15aSShawn Guo struct clk *clk;
8723b5e15aSShawn Guo struct clk_init_data init;
8823b5e15aSShawn Guo
8923b5e15aSShawn Guo pll = kzalloc(sizeof(*pll), GFP_KERNEL);
9023b5e15aSShawn Guo if (!pll)
9123b5e15aSShawn Guo return ERR_PTR(-ENOMEM);
9223b5e15aSShawn Guo
9323b5e15aSShawn Guo init.name = name;
9423b5e15aSShawn Guo init.ops = &clk_pll_ops;
9523b5e15aSShawn Guo init.flags = 0;
9623b5e15aSShawn Guo init.parent_names = (parent_name ? &parent_name: NULL);
9723b5e15aSShawn Guo init.num_parents = (parent_name ? 1 : 0);
9823b5e15aSShawn Guo
9923b5e15aSShawn Guo pll->base = base;
10023b5e15aSShawn Guo pll->rate = rate;
10123b5e15aSShawn Guo pll->power = power;
10223b5e15aSShawn Guo pll->hw.init = &init;
10323b5e15aSShawn Guo
10423b5e15aSShawn Guo clk = clk_register(NULL, &pll->hw);
10523b5e15aSShawn Guo if (IS_ERR(clk))
10623b5e15aSShawn Guo kfree(pll);
10723b5e15aSShawn Guo
10823b5e15aSShawn Guo return clk;
10923b5e15aSShawn Guo }
110