1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
6 #include <linux/kernel.h>
9 #include <linux/delay.h>
10 #include <linux/slab.h>
11 #include <linux/clk-provider.h>
15 #define pll_out_enb(p) (BIT(p->enb_bit_idx))
16 #define pll_out_rst(p) (BIT(p->rst_bit_idx))
18 static int clk_pll_out_is_enabled(struct clk_hw
*hw
)
20 struct tegra_clk_pll_out
*pll_out
= to_clk_pll_out(hw
);
21 u32 val
= readl_relaxed(pll_out
->reg
);
24 state
= (val
& pll_out_enb(pll_out
)) ? 1 : 0;
25 if (!(val
& (pll_out_rst(pll_out
))))
30 static int clk_pll_out_enable(struct clk_hw
*hw
)
32 struct tegra_clk_pll_out
*pll_out
= to_clk_pll_out(hw
);
33 unsigned long flags
= 0;
37 spin_lock_irqsave(pll_out
->lock
, flags
);
39 val
= readl_relaxed(pll_out
->reg
);
41 val
|= (pll_out_enb(pll_out
) | pll_out_rst(pll_out
));
43 writel_relaxed(val
, pll_out
->reg
);
47 spin_unlock_irqrestore(pll_out
->lock
, flags
);
52 static void clk_pll_out_disable(struct clk_hw
*hw
)
54 struct tegra_clk_pll_out
*pll_out
= to_clk_pll_out(hw
);
55 unsigned long flags
= 0;
59 spin_lock_irqsave(pll_out
->lock
, flags
);
61 val
= readl_relaxed(pll_out
->reg
);
63 val
&= ~(pll_out_enb(pll_out
) | pll_out_rst(pll_out
));
65 writel_relaxed(val
, pll_out
->reg
);
69 spin_unlock_irqrestore(pll_out
->lock
, flags
);
72 const struct clk_ops tegra_clk_pll_out_ops
= {
73 .is_enabled
= clk_pll_out_is_enabled
,
74 .enable
= clk_pll_out_enable
,
75 .disable
= clk_pll_out_disable
,
78 struct clk
*tegra_clk_register_pll_out(const char *name
,
79 const char *parent_name
, void __iomem
*reg
, u8 enb_bit_idx
,
80 u8 rst_bit_idx
, unsigned long flags
, u8 pll_out_flags
,
83 struct tegra_clk_pll_out
*pll_out
;
85 struct clk_init_data init
;
87 pll_out
= kzalloc(sizeof(*pll_out
), GFP_KERNEL
);
89 return ERR_PTR(-ENOMEM
);
92 init
.ops
= &tegra_clk_pll_out_ops
;
93 init
.parent_names
= (parent_name
? &parent_name
: NULL
);
94 init
.num_parents
= (parent_name
? 1 : 0);
98 pll_out
->enb_bit_idx
= enb_bit_idx
;
99 pll_out
->rst_bit_idx
= rst_bit_idx
;
100 pll_out
->flags
= pll_out_flags
;
101 pll_out
->lock
= lock
;
103 /* Data in .init is copied by clk_register(), so stack variable OK */
104 pll_out
->hw
.init
= &init
;
106 clk
= clk_register(NULL
, &pll_out
->hw
);