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>
23 #include <linux/clk.h>
27 #define pll_out_enb(p) (BIT(p->enb_bit_idx))
28 #define pll_out_rst(p) (BIT(p->rst_bit_idx))
30 static int clk_pll_out_is_enabled(struct clk_hw
*hw
)
32 struct tegra_clk_pll_out
*pll_out
= to_clk_pll_out(hw
);
33 u32 val
= readl_relaxed(pll_out
->reg
);
36 state
= (val
& pll_out_enb(pll_out
)) ? 1 : 0;
37 if (!(val
& (pll_out_rst(pll_out
))))
42 static int clk_pll_out_enable(struct clk_hw
*hw
)
44 struct tegra_clk_pll_out
*pll_out
= to_clk_pll_out(hw
);
45 unsigned long flags
= 0;
49 spin_lock_irqsave(pll_out
->lock
, flags
);
51 val
= readl_relaxed(pll_out
->reg
);
53 val
|= (pll_out_enb(pll_out
) | pll_out_rst(pll_out
));
55 writel_relaxed(val
, pll_out
->reg
);
59 spin_unlock_irqrestore(pll_out
->lock
, flags
);
64 static void clk_pll_out_disable(struct clk_hw
*hw
)
66 struct tegra_clk_pll_out
*pll_out
= to_clk_pll_out(hw
);
67 unsigned long flags
= 0;
71 spin_lock_irqsave(pll_out
->lock
, flags
);
73 val
= readl_relaxed(pll_out
->reg
);
75 val
&= ~(pll_out_enb(pll_out
) | pll_out_rst(pll_out
));
77 writel_relaxed(val
, pll_out
->reg
);
81 spin_unlock_irqrestore(pll_out
->lock
, flags
);
84 const struct clk_ops tegra_clk_pll_out_ops
= {
85 .is_enabled
= clk_pll_out_is_enabled
,
86 .enable
= clk_pll_out_enable
,
87 .disable
= clk_pll_out_disable
,
90 struct clk
*tegra_clk_register_pll_out(const char *name
,
91 const char *parent_name
, void __iomem
*reg
, u8 enb_bit_idx
,
92 u8 rst_bit_idx
, unsigned long flags
, u8 pll_out_flags
,
95 struct tegra_clk_pll_out
*pll_out
;
97 struct clk_init_data init
;
99 pll_out
= kzalloc(sizeof(*pll_out
), GFP_KERNEL
);
101 return ERR_PTR(-ENOMEM
);
104 init
.ops
= &tegra_clk_pll_out_ops
;
105 init
.parent_names
= (parent_name
? &parent_name
: NULL
);
106 init
.num_parents
= (parent_name
? 1 : 0);
110 pll_out
->enb_bit_idx
= enb_bit_idx
;
111 pll_out
->rst_bit_idx
= rst_bit_idx
;
112 pll_out
->flags
= pll_out_flags
;
113 pll_out
->lock
= lock
;
115 /* Data in .init is copied by clk_register(), so stack variable OK */
116 pll_out
->hw
.init
= &init
;
118 clk
= clk_register(NULL
, &pll_out
->hw
);