2 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include <linux/kernel.h>
19 #include <linux/err.h>
20 #include <linux/delay.h>
21 #include <linux/slab.h>
22 #include <linux/clk-provider.h>
26 #define pll_out_enb(p) (BIT(p->enb_bit_idx))
27 #define pll_out_rst(p) (BIT(p->rst_bit_idx))
29 static int clk_pll_out_is_enabled(struct clk_hw
*hw
)
31 struct tegra_clk_pll_out
*pll_out
= to_clk_pll_out(hw
);
32 u32 val
= readl_relaxed(pll_out
->reg
);
35 state
= (val
& pll_out_enb(pll_out
)) ? 1 : 0;
36 if (!(val
& (pll_out_rst(pll_out
))))
41 static int clk_pll_out_enable(struct clk_hw
*hw
)
43 struct tegra_clk_pll_out
*pll_out
= to_clk_pll_out(hw
);
44 unsigned long flags
= 0;
48 spin_lock_irqsave(pll_out
->lock
, flags
);
50 val
= readl_relaxed(pll_out
->reg
);
52 val
|= (pll_out_enb(pll_out
) | pll_out_rst(pll_out
));
54 writel_relaxed(val
, pll_out
->reg
);
58 spin_unlock_irqrestore(pll_out
->lock
, flags
);
63 static void clk_pll_out_disable(struct clk_hw
*hw
)
65 struct tegra_clk_pll_out
*pll_out
= to_clk_pll_out(hw
);
66 unsigned long flags
= 0;
70 spin_lock_irqsave(pll_out
->lock
, flags
);
72 val
= readl_relaxed(pll_out
->reg
);
74 val
&= ~(pll_out_enb(pll_out
) | pll_out_rst(pll_out
));
76 writel_relaxed(val
, pll_out
->reg
);
80 spin_unlock_irqrestore(pll_out
->lock
, flags
);
83 const struct clk_ops tegra_clk_pll_out_ops
= {
84 .is_enabled
= clk_pll_out_is_enabled
,
85 .enable
= clk_pll_out_enable
,
86 .disable
= clk_pll_out_disable
,
89 struct clk
*tegra_clk_register_pll_out(const char *name
,
90 const char *parent_name
, void __iomem
*reg
, u8 enb_bit_idx
,
91 u8 rst_bit_idx
, unsigned long flags
, u8 pll_out_flags
,
94 struct tegra_clk_pll_out
*pll_out
;
96 struct clk_init_data init
;
98 pll_out
= kzalloc(sizeof(*pll_out
), GFP_KERNEL
);
100 return ERR_PTR(-ENOMEM
);
103 init
.ops
= &tegra_clk_pll_out_ops
;
104 init
.parent_names
= (parent_name
? &parent_name
: NULL
);
105 init
.num_parents
= (parent_name
? 1 : 0);
109 pll_out
->enb_bit_idx
= enb_bit_idx
;
110 pll_out
->rst_bit_idx
= rst_bit_idx
;
111 pll_out
->flags
= pll_out_flags
;
112 pll_out
->lock
= lock
;
114 /* Data in .init is copied by clk_register(), so stack variable OK */
115 pll_out
->hw
.init
= &init
;
117 clk
= clk_register(NULL
, &pll_out
->hw
);