xref: /openbmc/linux/drivers/clk/mxs/clk-pll.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
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