0001
0002
0003
0004
0005
0006 #include <linux/clk-provider.h>
0007 #include <linux/err.h>
0008 #include <linux/io.h>
0009 #include <linux/slab.h>
0010 #include "clk.h"
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 struct clk_gate_exclusive {
0025 struct clk_gate gate;
0026 u32 exclusive_mask;
0027 };
0028
0029 static int clk_gate_exclusive_enable(struct clk_hw *hw)
0030 {
0031 struct clk_gate *gate = to_clk_gate(hw);
0032 struct clk_gate_exclusive *exgate = container_of(gate,
0033 struct clk_gate_exclusive, gate);
0034 u32 val = readl(gate->reg);
0035
0036 if (val & exgate->exclusive_mask)
0037 return -EBUSY;
0038
0039 return clk_gate_ops.enable(hw);
0040 }
0041
0042 static void clk_gate_exclusive_disable(struct clk_hw *hw)
0043 {
0044 clk_gate_ops.disable(hw);
0045 }
0046
0047 static int clk_gate_exclusive_is_enabled(struct clk_hw *hw)
0048 {
0049 return clk_gate_ops.is_enabled(hw);
0050 }
0051
0052 static const struct clk_ops clk_gate_exclusive_ops = {
0053 .enable = clk_gate_exclusive_enable,
0054 .disable = clk_gate_exclusive_disable,
0055 .is_enabled = clk_gate_exclusive_is_enabled,
0056 };
0057
0058 struct clk_hw *imx_clk_hw_gate_exclusive(const char *name, const char *parent,
0059 void __iomem *reg, u8 shift, u32 exclusive_mask)
0060 {
0061 struct clk_gate_exclusive *exgate;
0062 struct clk_gate *gate;
0063 struct clk_hw *hw;
0064 struct clk_init_data init;
0065 int ret;
0066
0067 if (exclusive_mask == 0)
0068 return ERR_PTR(-EINVAL);
0069
0070 exgate = kzalloc(sizeof(*exgate), GFP_KERNEL);
0071 if (!exgate)
0072 return ERR_PTR(-ENOMEM);
0073 gate = &exgate->gate;
0074
0075 init.name = name;
0076 init.ops = &clk_gate_exclusive_ops;
0077 init.flags = CLK_SET_RATE_PARENT;
0078 init.parent_names = parent ? &parent : NULL;
0079 init.num_parents = parent ? 1 : 0;
0080
0081 gate->reg = reg;
0082 gate->bit_idx = shift;
0083 gate->lock = &imx_ccm_lock;
0084 gate->hw.init = &init;
0085 exgate->exclusive_mask = exclusive_mask;
0086
0087 hw = &gate->hw;
0088
0089 ret = clk_hw_register(NULL, hw);
0090 if (ret) {
0091 kfree(gate);
0092 return ERR_PTR(ret);
0093 }
0094
0095 return hw;
0096 }