Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0 2 : : /* 3 : : * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com> 4 : : * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org> 5 : : * 6 : : * Gated clock implementation 7 : : */ 8 : : 9 : : #include <linux/clk-provider.h> 10 : : #include <linux/module.h> 11 : : #include <linux/slab.h> 12 : : #include <linux/io.h> 13 : : #include <linux/err.h> 14 : : #include <linux/string.h> 15 : : 16 : : /** 17 : : * DOC: basic gatable clock which can gate and ungate it's ouput 18 : : * 19 : : * Traits of this clock: 20 : : * prepare - clk_(un)prepare only ensures parent is (un)prepared 21 : : * enable - clk_enable and clk_disable are functional & control gating 22 : : * rate - inherits rate from parent. No clk_set_rate support 23 : : * parent - fixed parent. No clk_set_parent support 24 : : */ 25 : : 26 : : static inline u32 clk_gate_readl(struct clk_gate *gate) 27 : : { 28 : 3 : if (gate->flags & CLK_GATE_BIG_ENDIAN) 29 : 0 : return ioread32be(gate->reg); 30 : : 31 : 3 : return readl(gate->reg); 32 : : } 33 : : 34 : : static inline void clk_gate_writel(struct clk_gate *gate, u32 val) 35 : : { 36 : 1 : if (gate->flags & CLK_GATE_BIG_ENDIAN) 37 : 0 : iowrite32be(val, gate->reg); 38 : : else 39 : 1 : writel(val, gate->reg); 40 : : } 41 : : 42 : : /* 43 : : * It works on following logic: 44 : : * 45 : : * For enabling clock, enable = 1 46 : : * set2dis = 1 -> clear bit -> set = 0 47 : : * set2dis = 0 -> set bit -> set = 1 48 : : * 49 : : * For disabling clock, enable = 0 50 : : * set2dis = 1 -> set bit -> set = 1 51 : : * set2dis = 0 -> clear bit -> set = 0 52 : : * 53 : : * So, result is always: enable xor set2dis. 54 : : */ 55 : 1 : static void clk_gate_endisable(struct clk_hw *hw, int enable) 56 : : { 57 : : struct clk_gate *gate = to_clk_gate(hw); 58 : 1 : int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; 59 : : unsigned long uninitialized_var(flags); 60 : : u32 reg; 61 : : 62 : 1 : set ^= enable; 63 : : 64 : 1 : if (gate->lock) 65 : 0 : spin_lock_irqsave(gate->lock, flags); 66 : : else 67 : : __acquire(gate->lock); 68 : : 69 : 1 : if (gate->flags & CLK_GATE_HIWORD_MASK) { 70 : 0 : reg = BIT(gate->bit_idx + 16); 71 : 0 : if (set) 72 : 0 : reg |= BIT(gate->bit_idx); 73 : : } else { 74 : : reg = clk_gate_readl(gate); 75 : : 76 : 1 : if (set) 77 : 0 : reg |= BIT(gate->bit_idx); 78 : : else 79 : 1 : reg &= ~BIT(gate->bit_idx); 80 : : } 81 : : 82 : : clk_gate_writel(gate, reg); 83 : : 84 : 1 : if (gate->lock) 85 : : spin_unlock_irqrestore(gate->lock, flags); 86 : : else 87 : : __release(gate->lock); 88 : 1 : } 89 : : 90 : 0 : static int clk_gate_enable(struct clk_hw *hw) 91 : : { 92 : 0 : clk_gate_endisable(hw, 1); 93 : : 94 : 0 : return 0; 95 : : } 96 : : 97 : 1 : static void clk_gate_disable(struct clk_hw *hw) 98 : : { 99 : 1 : clk_gate_endisable(hw, 0); 100 : 1 : } 101 : : 102 : 3 : int clk_gate_is_enabled(struct clk_hw *hw) 103 : : { 104 : : u32 reg; 105 : : struct clk_gate *gate = to_clk_gate(hw); 106 : : 107 : : reg = clk_gate_readl(gate); 108 : : 109 : : /* if a set bit disables this clk, flip it before masking */ 110 : 3 : if (gate->flags & CLK_GATE_SET_TO_DISABLE) 111 : 0 : reg ^= BIT(gate->bit_idx); 112 : : 113 : 3 : reg &= BIT(gate->bit_idx); 114 : : 115 : 3 : return reg ? 1 : 0; 116 : : } 117 : : EXPORT_SYMBOL_GPL(clk_gate_is_enabled); 118 : : 119 : : const struct clk_ops clk_gate_ops = { 120 : : .enable = clk_gate_enable, 121 : : .disable = clk_gate_disable, 122 : : .is_enabled = clk_gate_is_enabled, 123 : : }; 124 : : EXPORT_SYMBOL_GPL(clk_gate_ops); 125 : : 126 : : /** 127 : : * clk_hw_register_gate - register a gate clock with the clock framework 128 : : * @dev: device that is registering this clock 129 : : * @name: name of this clock 130 : : * @parent_name: name of this clock's parent 131 : : * @flags: framework-specific flags for this clock 132 : : * @reg: register address to control gating of this clock 133 : : * @bit_idx: which bit in the register controls gating of this clock 134 : : * @clk_gate_flags: gate-specific flags for this clock 135 : : * @lock: shared register lock for this clock 136 : : */ 137 : 3 : struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name, 138 : : const char *parent_name, unsigned long flags, 139 : : void __iomem *reg, u8 bit_idx, 140 : : u8 clk_gate_flags, spinlock_t *lock) 141 : : { 142 : : struct clk_gate *gate; 143 : : struct clk_hw *hw; 144 : : struct clk_init_data init; 145 : : int ret; 146 : : 147 : 3 : if (clk_gate_flags & CLK_GATE_HIWORD_MASK) { 148 : 0 : if (bit_idx > 15) { 149 : 0 : pr_err("gate bit exceeds LOWORD field\n"); 150 : 0 : return ERR_PTR(-EINVAL); 151 : : } 152 : : } 153 : : 154 : : /* allocate the gate */ 155 : 3 : gate = kzalloc(sizeof(*gate), GFP_KERNEL); 156 : 3 : if (!gate) 157 : : return ERR_PTR(-ENOMEM); 158 : : 159 : 3 : init.name = name; 160 : 3 : init.ops = &clk_gate_ops; 161 : 3 : init.flags = flags; 162 : 3 : init.parent_names = parent_name ? &parent_name : NULL; 163 : 3 : init.num_parents = parent_name ? 1 : 0; 164 : : 165 : : /* struct clk_gate assignments */ 166 : 3 : gate->reg = reg; 167 : 3 : gate->bit_idx = bit_idx; 168 : 3 : gate->flags = clk_gate_flags; 169 : 3 : gate->lock = lock; 170 : 3 : gate->hw.init = &init; 171 : : 172 : 3 : hw = &gate->hw; 173 : 3 : ret = clk_hw_register(dev, hw); 174 : 3 : if (ret) { 175 : 0 : kfree(gate); 176 : : hw = ERR_PTR(ret); 177 : : } 178 : : 179 : 3 : return hw; 180 : : } 181 : : EXPORT_SYMBOL_GPL(clk_hw_register_gate); 182 : : 183 : 0 : struct clk *clk_register_gate(struct device *dev, const char *name, 184 : : const char *parent_name, unsigned long flags, 185 : : void __iomem *reg, u8 bit_idx, 186 : : u8 clk_gate_flags, spinlock_t *lock) 187 : : { 188 : : struct clk_hw *hw; 189 : : 190 : 0 : hw = clk_hw_register_gate(dev, name, parent_name, flags, reg, 191 : : bit_idx, clk_gate_flags, lock); 192 : 0 : if (IS_ERR(hw)) 193 : : return ERR_CAST(hw); 194 : 0 : return hw->clk; 195 : : } 196 : : EXPORT_SYMBOL_GPL(clk_register_gate); 197 : : 198 : 0 : void clk_unregister_gate(struct clk *clk) 199 : : { 200 : : struct clk_gate *gate; 201 : : struct clk_hw *hw; 202 : : 203 : 0 : hw = __clk_get_hw(clk); 204 : 0 : if (!hw) 205 : 0 : return; 206 : : 207 : : gate = to_clk_gate(hw); 208 : : 209 : 0 : clk_unregister(clk); 210 : 0 : kfree(gate); 211 : : } 212 : : EXPORT_SYMBOL_GPL(clk_unregister_gate); 213 : : 214 : 0 : void clk_hw_unregister_gate(struct clk_hw *hw) 215 : : { 216 : : struct clk_gate *gate; 217 : : 218 : : gate = to_clk_gate(hw); 219 : : 220 : 0 : clk_hw_unregister(hw); 221 : 0 : kfree(gate); 222 : 0 : } 223 : : EXPORT_SYMBOL_GPL(clk_hw_unregister_gate);