1 // SPDX-License-Identifier: GPL-2.0-only
3 * mmp gate clock operation source file
5 * Copyright (C) 2014 Marvell
6 * Chao Xie <chao.xie@marvell.com>
9 #include <linux/clk-provider.h>
10 #include <linux/slab.h>
12 #include <linux/err.h>
13 #include <linux/delay.h>
18 * Some clocks will have mutiple bits to enable the clocks, and
19 * the bits to disable the clock is not same as enabling bits.
22 #define to_clk_mmp_gate(hw) container_of(hw, struct mmp_clk_gate, hw)
24 static int mmp_clk_gate_enable(struct clk_hw
*hw
)
26 struct mmp_clk_gate
*gate
= to_clk_mmp_gate(hw
);
27 unsigned long flags
= 0;
32 spin_lock_irqsave(gate
->lock
, flags
);
34 tmp
= readl(gate
->reg
);
36 tmp
|= gate
->val_enable
;
37 writel(tmp
, gate
->reg
);
40 spin_unlock_irqrestore(gate
->lock
, flags
);
42 if (gate
->flags
& MMP_CLK_GATE_NEED_DELAY
) {
43 rate
= clk_hw_get_rate(hw
);
44 /* Need delay 2 cycles. */
51 static void mmp_clk_gate_disable(struct clk_hw
*hw
)
53 struct mmp_clk_gate
*gate
= to_clk_mmp_gate(hw
);
54 unsigned long flags
= 0;
58 spin_lock_irqsave(gate
->lock
, flags
);
60 tmp
= readl(gate
->reg
);
62 tmp
|= gate
->val_disable
;
63 writel(tmp
, gate
->reg
);
66 spin_unlock_irqrestore(gate
->lock
, flags
);
69 static int mmp_clk_gate_is_enabled(struct clk_hw
*hw
)
71 struct mmp_clk_gate
*gate
= to_clk_mmp_gate(hw
);
72 unsigned long flags
= 0;
76 spin_lock_irqsave(gate
->lock
, flags
);
78 tmp
= readl(gate
->reg
);
81 spin_unlock_irqrestore(gate
->lock
, flags
);
83 return (tmp
& gate
->mask
) == gate
->val_enable
;
86 const struct clk_ops mmp_clk_gate_ops
= {
87 .enable
= mmp_clk_gate_enable
,
88 .disable
= mmp_clk_gate_disable
,
89 .is_enabled
= mmp_clk_gate_is_enabled
,
92 struct clk
*mmp_clk_register_gate(struct device
*dev
, const char *name
,
93 const char *parent_name
, unsigned long flags
,
94 void __iomem
*reg
, u32 mask
, u32 val_enable
, u32 val_disable
,
95 unsigned int gate_flags
, spinlock_t
*lock
)
97 struct mmp_clk_gate
*gate
;
99 struct clk_init_data init
;
101 /* allocate the gate */
102 gate
= kzalloc(sizeof(*gate
), GFP_KERNEL
);
104 return ERR_PTR(-ENOMEM
);
107 init
.ops
= &mmp_clk_gate_ops
;
109 init
.parent_names
= (parent_name
? &parent_name
: NULL
);
110 init
.num_parents
= (parent_name
? 1 : 0);
112 /* struct clk_gate assignments */
115 gate
->val_enable
= val_enable
;
116 gate
->val_disable
= val_disable
;
117 gate
->flags
= gate_flags
;
119 gate
->hw
.init
= &init
;
121 clk
= clk_register(dev
, &gate
->hw
);