1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright 2014 Freescale Semiconductor, Inc.
6 #include <linux/clk-provider.h>
9 #include <linux/slab.h>
13 * struct clk_gate_exclusive - i.MX specific gate clock which is mutually
14 * exclusive with other gate clocks
16 * @gate: the parent class
17 * @exclusive_mask: mask of gate bits which are mutually exclusive to this
20 * The imx exclusive gate clock is a subclass of basic clk_gate
21 * with an addtional mask to indicate which other gate bits in the same
22 * register is mutually exclusive to this gate clock.
24 struct clk_gate_exclusive
{
29 static int clk_gate_exclusive_enable(struct clk_hw
*hw
)
31 struct clk_gate
*gate
= to_clk_gate(hw
);
32 struct clk_gate_exclusive
*exgate
= container_of(gate
,
33 struct clk_gate_exclusive
, gate
);
34 u32 val
= readl(gate
->reg
);
36 if (val
& exgate
->exclusive_mask
)
39 return clk_gate_ops
.enable(hw
);
42 static void clk_gate_exclusive_disable(struct clk_hw
*hw
)
44 clk_gate_ops
.disable(hw
);
47 static int clk_gate_exclusive_is_enabled(struct clk_hw
*hw
)
49 return clk_gate_ops
.is_enabled(hw
);
52 static const struct clk_ops clk_gate_exclusive_ops
= {
53 .enable
= clk_gate_exclusive_enable
,
54 .disable
= clk_gate_exclusive_disable
,
55 .is_enabled
= clk_gate_exclusive_is_enabled
,
58 struct clk_hw
*imx_clk_hw_gate_exclusive(const char *name
, const char *parent
,
59 void __iomem
*reg
, u8 shift
, u32 exclusive_mask
)
61 struct clk_gate_exclusive
*exgate
;
62 struct clk_gate
*gate
;
64 struct clk_init_data init
;
67 if (exclusive_mask
== 0)
68 return ERR_PTR(-EINVAL
);
70 exgate
= kzalloc(sizeof(*exgate
), GFP_KERNEL
);
72 return ERR_PTR(-ENOMEM
);
76 init
.ops
= &clk_gate_exclusive_ops
;
77 init
.flags
= CLK_SET_RATE_PARENT
;
78 init
.parent_names
= parent
? &parent
: NULL
;
79 init
.num_parents
= parent
? 1 : 0;
82 gate
->bit_idx
= shift
;
83 gate
->lock
= &imx_ccm_lock
;
84 gate
->hw
.init
= &init
;
85 exgate
->exclusive_mask
= exclusive_mask
;
89 ret
= clk_hw_register(NULL
, hw
);