2 * Copyright 2014 Freescale Semiconductor, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
9 #include <linux/clk-provider.h>
10 #include <linux/err.h>
12 #include <linux/slab.h>
16 * struct clk_gate_exclusive - i.MX specific gate clock which is mutually
17 * exclusive with other gate clocks
19 * @gate: the parent class
20 * @exclusive_mask: mask of gate bits which are mutually exclusive to this
23 * The imx exclusive gate clock is a subclass of basic clk_gate
24 * with an addtional mask to indicate which other gate bits in the same
25 * register is mutually exclusive to this gate clock.
27 struct clk_gate_exclusive
{
32 static int clk_gate_exclusive_enable(struct clk_hw
*hw
)
34 struct clk_gate
*gate
= to_clk_gate(hw
);
35 struct clk_gate_exclusive
*exgate
= container_of(gate
,
36 struct clk_gate_exclusive
, gate
);
37 u32 val
= readl(gate
->reg
);
39 if (val
& exgate
->exclusive_mask
)
42 return clk_gate_ops
.enable(hw
);
45 static void clk_gate_exclusive_disable(struct clk_hw
*hw
)
47 clk_gate_ops
.disable(hw
);
50 static int clk_gate_exclusive_is_enabled(struct clk_hw
*hw
)
52 return clk_gate_ops
.is_enabled(hw
);
55 static const struct clk_ops clk_gate_exclusive_ops
= {
56 .enable
= clk_gate_exclusive_enable
,
57 .disable
= clk_gate_exclusive_disable
,
58 .is_enabled
= clk_gate_exclusive_is_enabled
,
61 struct clk
*imx_clk_gate_exclusive(const char *name
, const char *parent
,
62 void __iomem
*reg
, u8 shift
, u32 exclusive_mask
)
64 struct clk_gate_exclusive
*exgate
;
65 struct clk_gate
*gate
;
67 struct clk_init_data init
;
69 if (exclusive_mask
== 0)
70 return ERR_PTR(-EINVAL
);
72 exgate
= kzalloc(sizeof(*exgate
), GFP_KERNEL
);
74 return ERR_PTR(-ENOMEM
);
78 init
.ops
= &clk_gate_exclusive_ops
;
79 init
.flags
= CLK_SET_RATE_PARENT
;
80 init
.parent_names
= parent
? &parent
: NULL
;
81 init
.num_parents
= parent
? 1 : 0;
84 gate
->bit_idx
= shift
;
85 gate
->lock
= &imx_ccm_lock
;
86 gate
->hw
.init
= &init
;
87 exgate
->exclusive_mask
= exclusive_mask
;
89 clk
= clk_register(NULL
, &gate
->hw
);