1 /* 2 * PRCMU clock implementation for ux500 platform. 3 * 4 * Copyright (C) 2012 ST-Ericsson SA 5 * Author: Ulf Hansson <ulf.hansson@linaro.org> 6 * 7 * License terms: GNU General Public License (GPL) version 2 8 */ 9 10 #include <linux/clk-provider.h> 11 #include <linux/clk-private.h> 12 #include <linux/mfd/dbx500-prcmu.h> 13 #include <linux/slab.h> 14 #include <linux/io.h> 15 #include <linux/err.h> 16 #include "clk.h" 17 18 #define to_clk_prcmu(_hw) container_of(_hw, struct clk_prcmu, hw) 19 20 struct clk_prcmu { 21 struct clk_hw hw; 22 u8 cg_sel; 23 int is_enabled; 24 }; 25 26 /* PRCMU clock operations. */ 27 28 static int clk_prcmu_prepare(struct clk_hw *hw) 29 { 30 struct clk_prcmu *clk = to_clk_prcmu(hw); 31 return prcmu_request_clock(clk->cg_sel, true); 32 } 33 34 static void clk_prcmu_unprepare(struct clk_hw *hw) 35 { 36 struct clk_prcmu *clk = to_clk_prcmu(hw); 37 if (prcmu_request_clock(clk->cg_sel, false)) 38 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, 39 hw->init->name); 40 } 41 42 static int clk_prcmu_enable(struct clk_hw *hw) 43 { 44 struct clk_prcmu *clk = to_clk_prcmu(hw); 45 clk->is_enabled = 1; 46 return 0; 47 } 48 49 static void clk_prcmu_disable(struct clk_hw *hw) 50 { 51 struct clk_prcmu *clk = to_clk_prcmu(hw); 52 clk->is_enabled = 0; 53 } 54 55 static int clk_prcmu_is_enabled(struct clk_hw *hw) 56 { 57 struct clk_prcmu *clk = to_clk_prcmu(hw); 58 return clk->is_enabled; 59 } 60 61 static unsigned long clk_prcmu_recalc_rate(struct clk_hw *hw, 62 unsigned long parent_rate) 63 { 64 struct clk_prcmu *clk = to_clk_prcmu(hw); 65 return prcmu_clock_rate(clk->cg_sel); 66 } 67 68 static long clk_prcmu_round_rate(struct clk_hw *hw, unsigned long rate, 69 unsigned long *parent_rate) 70 { 71 struct clk_prcmu *clk = to_clk_prcmu(hw); 72 return prcmu_round_clock_rate(clk->cg_sel, rate); 73 } 74 75 static int clk_prcmu_set_rate(struct clk_hw *hw, unsigned long rate, 76 unsigned long parent_rate) 77 { 78 struct clk_prcmu *clk = to_clk_prcmu(hw); 79 return prcmu_set_clock_rate(clk->cg_sel, rate); 80 } 81 82 static int request_ape_opp100(bool enable) 83 { 84 static int reqs; 85 int err = 0; 86 87 if (enable) { 88 if (!reqs) 89 err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, 90 "clock", 100); 91 if (!err) 92 reqs++; 93 } else { 94 reqs--; 95 if (!reqs) 96 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, 97 "clock"); 98 } 99 return err; 100 } 101 102 static int clk_prcmu_opp_prepare(struct clk_hw *hw) 103 { 104 int err; 105 struct clk_prcmu *clk = to_clk_prcmu(hw); 106 107 err = request_ape_opp100(true); 108 if (err) { 109 pr_err("clk_prcmu: %s failed to request APE OPP100 for %s.\n", 110 __func__, hw->init->name); 111 return err; 112 } 113 114 err = prcmu_request_clock(clk->cg_sel, true); 115 if (err) 116 request_ape_opp100(false); 117 118 return err; 119 } 120 121 static void clk_prcmu_opp_unprepare(struct clk_hw *hw) 122 { 123 struct clk_prcmu *clk = to_clk_prcmu(hw); 124 125 if (prcmu_request_clock(clk->cg_sel, false)) 126 goto out_error; 127 if (request_ape_opp100(false)) 128 goto out_error; 129 return; 130 131 out_error: 132 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, 133 hw->init->name); 134 } 135 136 static struct clk_ops clk_prcmu_scalable_ops = { 137 .prepare = clk_prcmu_prepare, 138 .unprepare = clk_prcmu_unprepare, 139 .enable = clk_prcmu_enable, 140 .disable = clk_prcmu_disable, 141 .is_enabled = clk_prcmu_is_enabled, 142 .recalc_rate = clk_prcmu_recalc_rate, 143 .round_rate = clk_prcmu_round_rate, 144 .set_rate = clk_prcmu_set_rate, 145 }; 146 147 static struct clk_ops clk_prcmu_gate_ops = { 148 .prepare = clk_prcmu_prepare, 149 .unprepare = clk_prcmu_unprepare, 150 .enable = clk_prcmu_enable, 151 .disable = clk_prcmu_disable, 152 .is_enabled = clk_prcmu_is_enabled, 153 .recalc_rate = clk_prcmu_recalc_rate, 154 }; 155 156 static struct clk_ops clk_prcmu_rate_ops = { 157 .is_enabled = clk_prcmu_is_enabled, 158 .recalc_rate = clk_prcmu_recalc_rate, 159 }; 160 161 static struct clk_ops clk_prcmu_opp_gate_ops = { 162 .prepare = clk_prcmu_opp_prepare, 163 .unprepare = clk_prcmu_opp_unprepare, 164 .enable = clk_prcmu_enable, 165 .disable = clk_prcmu_disable, 166 .is_enabled = clk_prcmu_is_enabled, 167 .recalc_rate = clk_prcmu_recalc_rate, 168 }; 169 170 static struct clk *clk_reg_prcmu(const char *name, 171 const char *parent_name, 172 u8 cg_sel, 173 unsigned long rate, 174 unsigned long flags, 175 struct clk_ops *clk_prcmu_ops) 176 { 177 struct clk_prcmu *clk; 178 struct clk_init_data clk_prcmu_init; 179 struct clk *clk_reg; 180 181 if (!name) { 182 pr_err("clk_prcmu: %s invalid arguments passed\n", __func__); 183 return ERR_PTR(-EINVAL); 184 } 185 186 clk = kzalloc(sizeof(struct clk_prcmu), GFP_KERNEL); 187 if (!clk) { 188 pr_err("clk_prcmu: %s could not allocate clk\n", __func__); 189 return ERR_PTR(-ENOMEM); 190 } 191 192 clk->cg_sel = cg_sel; 193 clk->is_enabled = 1; 194 /* "rate" can be used for changing the initial frequency */ 195 if (rate) 196 prcmu_set_clock_rate(cg_sel, rate); 197 198 clk_prcmu_init.name = name; 199 clk_prcmu_init.ops = clk_prcmu_ops; 200 clk_prcmu_init.flags = flags; 201 clk_prcmu_init.parent_names = (parent_name ? &parent_name : NULL); 202 clk_prcmu_init.num_parents = (parent_name ? 1 : 0); 203 clk->hw.init = &clk_prcmu_init; 204 205 clk_reg = clk_register(NULL, &clk->hw); 206 if (IS_ERR_OR_NULL(clk_reg)) 207 goto free_clk; 208 209 return clk_reg; 210 211 free_clk: 212 kfree(clk); 213 pr_err("clk_prcmu: %s failed to register clk\n", __func__); 214 return ERR_PTR(-ENOMEM); 215 } 216 217 struct clk *clk_reg_prcmu_scalable(const char *name, 218 const char *parent_name, 219 u8 cg_sel, 220 unsigned long rate, 221 unsigned long flags) 222 { 223 return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags, 224 &clk_prcmu_scalable_ops); 225 } 226 227 struct clk *clk_reg_prcmu_gate(const char *name, 228 const char *parent_name, 229 u8 cg_sel, 230 unsigned long flags) 231 { 232 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags, 233 &clk_prcmu_gate_ops); 234 } 235 236 struct clk *clk_reg_prcmu_rate(const char *name, 237 const char *parent_name, 238 u8 cg_sel, 239 unsigned long flags) 240 { 241 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags, 242 &clk_prcmu_rate_ops); 243 } 244 245 struct clk *clk_reg_prcmu_opp_gate(const char *name, 246 const char *parent_name, 247 u8 cg_sel, 248 unsigned long flags) 249 { 250 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags, 251 &clk_prcmu_opp_gate_ops); 252 } 253