0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/clk-provider.h>
0009 #include <linux/regmap.h>
0010
0011 #include "gate.h"
0012
0013 static void clk_gate_toggle(const struct sprd_gate *sg, bool en)
0014 {
0015 const struct sprd_clk_common *common = &sg->common;
0016 unsigned int reg;
0017 bool set = sg->flags & CLK_GATE_SET_TO_DISABLE ? true : false;
0018
0019 set ^= en;
0020
0021 regmap_read(common->regmap, common->reg, ®);
0022
0023 if (set)
0024 reg |= sg->enable_mask;
0025 else
0026 reg &= ~sg->enable_mask;
0027
0028 regmap_write(common->regmap, common->reg, reg);
0029 }
0030
0031 static void clk_sc_gate_toggle(const struct sprd_gate *sg, bool en)
0032 {
0033 const struct sprd_clk_common *common = &sg->common;
0034 bool set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
0035 unsigned int offset;
0036
0037 set ^= en;
0038
0039
0040
0041
0042
0043
0044
0045 offset = set ? sg->sc_offset : sg->sc_offset * 2;
0046
0047 regmap_write(common->regmap, common->reg + offset,
0048 sg->enable_mask);
0049 }
0050
0051 static void sprd_gate_disable(struct clk_hw *hw)
0052 {
0053 struct sprd_gate *sg = hw_to_sprd_gate(hw);
0054
0055 clk_gate_toggle(sg, false);
0056 }
0057
0058 static int sprd_gate_enable(struct clk_hw *hw)
0059 {
0060 struct sprd_gate *sg = hw_to_sprd_gate(hw);
0061
0062 clk_gate_toggle(sg, true);
0063
0064 return 0;
0065 }
0066
0067 static void sprd_sc_gate_disable(struct clk_hw *hw)
0068 {
0069 struct sprd_gate *sg = hw_to_sprd_gate(hw);
0070
0071 clk_sc_gate_toggle(sg, false);
0072 }
0073
0074 static int sprd_sc_gate_enable(struct clk_hw *hw)
0075 {
0076 struct sprd_gate *sg = hw_to_sprd_gate(hw);
0077
0078 clk_sc_gate_toggle(sg, true);
0079
0080 return 0;
0081 }
0082
0083 static int sprd_pll_sc_gate_prepare(struct clk_hw *hw)
0084 {
0085 struct sprd_gate *sg = hw_to_sprd_gate(hw);
0086
0087 clk_sc_gate_toggle(sg, true);
0088 udelay(sg->udelay);
0089
0090 return 0;
0091 }
0092
0093 static int sprd_gate_is_enabled(struct clk_hw *hw)
0094 {
0095 struct sprd_gate *sg = hw_to_sprd_gate(hw);
0096 struct sprd_clk_common *common = &sg->common;
0097 struct clk_hw *parent;
0098 unsigned int reg;
0099
0100 if (sg->flags & SPRD_GATE_NON_AON) {
0101 parent = clk_hw_get_parent(hw);
0102 if (!parent || !clk_hw_is_enabled(parent))
0103 return 0;
0104 }
0105
0106 regmap_read(common->regmap, common->reg, ®);
0107
0108 if (sg->flags & CLK_GATE_SET_TO_DISABLE)
0109 reg ^= sg->enable_mask;
0110
0111 reg &= sg->enable_mask;
0112
0113 return reg ? 1 : 0;
0114 }
0115
0116 const struct clk_ops sprd_gate_ops = {
0117 .disable = sprd_gate_disable,
0118 .enable = sprd_gate_enable,
0119 .is_enabled = sprd_gate_is_enabled,
0120 };
0121 EXPORT_SYMBOL_GPL(sprd_gate_ops);
0122
0123 const struct clk_ops sprd_sc_gate_ops = {
0124 .disable = sprd_sc_gate_disable,
0125 .enable = sprd_sc_gate_enable,
0126 .is_enabled = sprd_gate_is_enabled,
0127 };
0128 EXPORT_SYMBOL_GPL(sprd_sc_gate_ops);
0129
0130 const struct clk_ops sprd_pll_sc_gate_ops = {
0131 .unprepare = sprd_sc_gate_disable,
0132 .prepare = sprd_pll_sc_gate_prepare,
0133 .is_enabled = sprd_gate_is_enabled,
0134 };
0135 EXPORT_SYMBOL_GPL(sprd_pll_sc_gate_ops);