1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // Spreadtrum gate clock driver 4 // 5 // Copyright (C) 2017 Spreadtrum, Inc. 6 // Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com> 7 8 #include <linux/clk-provider.h> 9 #include <linux/regmap.h> 10 11 #include "gate.h" 12 13 static void clk_gate_toggle(const struct sprd_gate *sg, bool en) 14 { 15 const struct sprd_clk_common *common = &sg->common; 16 unsigned int reg; 17 bool set = sg->flags & CLK_GATE_SET_TO_DISABLE ? true : false; 18 19 set ^= en; 20 21 regmap_read(common->regmap, common->reg, ®); 22 23 if (set) 24 reg |= sg->enable_mask; 25 else 26 reg &= ~sg->enable_mask; 27 28 regmap_write(common->regmap, common->reg, reg); 29 } 30 31 static void clk_sc_gate_toggle(const struct sprd_gate *sg, bool en) 32 { 33 const struct sprd_clk_common *common = &sg->common; 34 bool set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; 35 unsigned int offset; 36 37 set ^= en; 38 39 /* 40 * Each set/clear gate clock has three registers: 41 * common->reg - base register 42 * common->reg + offset - set register 43 * common->reg + 2 * offset - clear register 44 */ 45 offset = set ? sg->sc_offset : sg->sc_offset * 2; 46 47 regmap_write(common->regmap, common->reg + offset, 48 sg->enable_mask); 49 } 50 51 static void sprd_gate_disable(struct clk_hw *hw) 52 { 53 struct sprd_gate *sg = hw_to_sprd_gate(hw); 54 55 clk_gate_toggle(sg, false); 56 } 57 58 static int sprd_gate_enable(struct clk_hw *hw) 59 { 60 struct sprd_gate *sg = hw_to_sprd_gate(hw); 61 62 clk_gate_toggle(sg, true); 63 64 return 0; 65 } 66 67 static void sprd_sc_gate_disable(struct clk_hw *hw) 68 { 69 struct sprd_gate *sg = hw_to_sprd_gate(hw); 70 71 clk_sc_gate_toggle(sg, false); 72 } 73 74 static int sprd_sc_gate_enable(struct clk_hw *hw) 75 { 76 struct sprd_gate *sg = hw_to_sprd_gate(hw); 77 78 clk_sc_gate_toggle(sg, true); 79 80 return 0; 81 } 82 static int sprd_gate_is_enabled(struct clk_hw *hw) 83 { 84 struct sprd_gate *sg = hw_to_sprd_gate(hw); 85 struct sprd_clk_common *common = &sg->common; 86 unsigned int reg; 87 88 regmap_read(common->regmap, common->reg, ®); 89 90 if (sg->flags & CLK_GATE_SET_TO_DISABLE) 91 reg ^= sg->enable_mask; 92 93 reg &= sg->enable_mask; 94 95 return reg ? 1 : 0; 96 } 97 98 const struct clk_ops sprd_gate_ops = { 99 .disable = sprd_gate_disable, 100 .enable = sprd_gate_enable, 101 .is_enabled = sprd_gate_is_enabled, 102 }; 103 EXPORT_SYMBOL_GPL(sprd_gate_ops); 104 105 const struct clk_ops sprd_sc_gate_ops = { 106 .disable = sprd_sc_gate_disable, 107 .enable = sprd_sc_gate_enable, 108 .is_enabled = sprd_gate_is_enabled, 109 }; 110 EXPORT_SYMBOL_GPL(sprd_sc_gate_ops); 111 112