at v5.6 111 lines 2.4 kB view raw
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 13static 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, &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 31static 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 51static 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 58static 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 67static 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 74static 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} 82static 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, &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 98const struct clk_ops sprd_gate_ops = { 99 .disable = sprd_gate_disable, 100 .enable = sprd_gate_enable, 101 .is_enabled = sprd_gate_is_enabled, 102}; 103EXPORT_SYMBOL_GPL(sprd_gate_ops); 104 105const 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}; 110EXPORT_SYMBOL_GPL(sprd_sc_gate_ops); 111