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/mfd/dbx500-prcmu.h> 12 #include <linux/slab.h> 13 #include <linux/io.h> 14 #include <linux/err.h> 15 #include "clk.h" 16 17 #define to_clk_prcmu(_hw) container_of(_hw, struct clk_prcmu, hw) 18 19 struct clk_prcmu { 20 struct clk_hw hw; 21 u8 cg_sel; 22 int is_prepared; 23 int is_enabled; 24 int opp_requested; 25 }; 26 27 /* PRCMU clock operations. */ 28 29 static int clk_prcmu_prepare(struct clk_hw *hw) 30 { 31 int ret; 32 struct clk_prcmu *clk = to_clk_prcmu(hw); 33 34 ret = prcmu_request_clock(clk->cg_sel, true); 35 if (!ret) 36 clk->is_prepared = 1; 37 38 return ret; 39 } 40 41 static void clk_prcmu_unprepare(struct clk_hw *hw) 42 { 43 struct clk_prcmu *clk = to_clk_prcmu(hw); 44 if (prcmu_request_clock(clk->cg_sel, false)) 45 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, 46 clk_hw_get_name(hw)); 47 else 48 clk->is_prepared = 0; 49 } 50 51 static int clk_prcmu_is_prepared(struct clk_hw *hw) 52 { 53 struct clk_prcmu *clk = to_clk_prcmu(hw); 54 return clk->is_prepared; 55 } 56 57 static int clk_prcmu_enable(struct clk_hw *hw) 58 { 59 struct clk_prcmu *clk = to_clk_prcmu(hw); 60 clk->is_enabled = 1; 61 return 0; 62 } 63 64 static void clk_prcmu_disable(struct clk_hw *hw) 65 { 66 struct clk_prcmu *clk = to_clk_prcmu(hw); 67 clk->is_enabled = 0; 68 } 69 70 static int clk_prcmu_is_enabled(struct clk_hw *hw) 71 { 72 struct clk_prcmu *clk = to_clk_prcmu(hw); 73 return clk->is_enabled; 74 } 75 76 static unsigned long clk_prcmu_recalc_rate(struct clk_hw *hw, 77 unsigned long parent_rate) 78 { 79 struct clk_prcmu *clk = to_clk_prcmu(hw); 80 return prcmu_clock_rate(clk->cg_sel); 81 } 82 83 static long clk_prcmu_round_rate(struct clk_hw *hw, unsigned long rate, 84 unsigned long *parent_rate) 85 { 86 struct clk_prcmu *clk = to_clk_prcmu(hw); 87 return prcmu_round_clock_rate(clk->cg_sel, rate); 88 } 89 90 static int clk_prcmu_set_rate(struct clk_hw *hw, unsigned long rate, 91 unsigned long parent_rate) 92 { 93 struct clk_prcmu *clk = to_clk_prcmu(hw); 94 return prcmu_set_clock_rate(clk->cg_sel, rate); 95 } 96 97 static int clk_prcmu_opp_prepare(struct clk_hw *hw) 98 { 99 int err; 100 struct clk_prcmu *clk = to_clk_prcmu(hw); 101 102 if (!clk->opp_requested) { 103 err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, 104 (char *)clk_hw_get_name(hw), 105 100); 106 if (err) { 107 pr_err("clk_prcmu: %s fail req APE OPP for %s.\n", 108 __func__, clk_hw_get_name(hw)); 109 return err; 110 } 111 clk->opp_requested = 1; 112 } 113 114 err = prcmu_request_clock(clk->cg_sel, true); 115 if (err) { 116 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, 117 (char *)clk_hw_get_name(hw)); 118 clk->opp_requested = 0; 119 return err; 120 } 121 122 clk->is_prepared = 1; 123 return 0; 124 } 125 126 static void clk_prcmu_opp_unprepare(struct clk_hw *hw) 127 { 128 struct clk_prcmu *clk = to_clk_prcmu(hw); 129 130 if (prcmu_request_clock(clk->cg_sel, false)) { 131 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, 132 clk_hw_get_name(hw)); 133 return; 134 } 135 136 if (clk->opp_requested) { 137 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, 138 (char *)clk_hw_get_name(hw)); 139 clk->opp_requested = 0; 140 } 141 142 clk->is_prepared = 0; 143 } 144 145 static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw) 146 { 147 int err; 148 struct clk_prcmu *clk = to_clk_prcmu(hw); 149 150 if (!clk->opp_requested) { 151 err = prcmu_request_ape_opp_100_voltage(true); 152 if (err) { 153 pr_err("clk_prcmu: %s fail req APE OPP VOLT for %s.\n", 154 __func__, clk_hw_get_name(hw)); 155 return err; 156 } 157 clk->opp_requested = 1; 158 } 159 160 err = prcmu_request_clock(clk->cg_sel, true); 161 if (err) { 162 prcmu_request_ape_opp_100_voltage(false); 163 clk->opp_requested = 0; 164 return err; 165 } 166 167 clk->is_prepared = 1; 168 return 0; 169 } 170 171 static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw) 172 { 173 struct clk_prcmu *clk = to_clk_prcmu(hw); 174 175 if (prcmu_request_clock(clk->cg_sel, false)) { 176 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, 177 clk_hw_get_name(hw)); 178 return; 179 } 180 181 if (clk->opp_requested) { 182 prcmu_request_ape_opp_100_voltage(false); 183 clk->opp_requested = 0; 184 } 185 186 clk->is_prepared = 0; 187 } 188 189 static const struct clk_ops clk_prcmu_scalable_ops = { 190 .prepare = clk_prcmu_prepare, 191 .unprepare = clk_prcmu_unprepare, 192 .is_prepared = clk_prcmu_is_prepared, 193 .enable = clk_prcmu_enable, 194 .disable = clk_prcmu_disable, 195 .is_enabled = clk_prcmu_is_enabled, 196 .recalc_rate = clk_prcmu_recalc_rate, 197 .round_rate = clk_prcmu_round_rate, 198 .set_rate = clk_prcmu_set_rate, 199 }; 200 201 static const struct clk_ops clk_prcmu_gate_ops = { 202 .prepare = clk_prcmu_prepare, 203 .unprepare = clk_prcmu_unprepare, 204 .is_prepared = clk_prcmu_is_prepared, 205 .enable = clk_prcmu_enable, 206 .disable = clk_prcmu_disable, 207 .is_enabled = clk_prcmu_is_enabled, 208 .recalc_rate = clk_prcmu_recalc_rate, 209 }; 210 211 static const struct clk_ops clk_prcmu_scalable_rate_ops = { 212 .is_enabled = clk_prcmu_is_enabled, 213 .recalc_rate = clk_prcmu_recalc_rate, 214 .round_rate = clk_prcmu_round_rate, 215 .set_rate = clk_prcmu_set_rate, 216 }; 217 218 static const struct clk_ops clk_prcmu_rate_ops = { 219 .is_enabled = clk_prcmu_is_enabled, 220 .recalc_rate = clk_prcmu_recalc_rate, 221 }; 222 223 static const struct clk_ops clk_prcmu_opp_gate_ops = { 224 .prepare = clk_prcmu_opp_prepare, 225 .unprepare = clk_prcmu_opp_unprepare, 226 .is_prepared = clk_prcmu_is_prepared, 227 .enable = clk_prcmu_enable, 228 .disable = clk_prcmu_disable, 229 .is_enabled = clk_prcmu_is_enabled, 230 .recalc_rate = clk_prcmu_recalc_rate, 231 }; 232 233 static const struct clk_ops clk_prcmu_opp_volt_scalable_ops = { 234 .prepare = clk_prcmu_opp_volt_prepare, 235 .unprepare = clk_prcmu_opp_volt_unprepare, 236 .is_prepared = clk_prcmu_is_prepared, 237 .enable = clk_prcmu_enable, 238 .disable = clk_prcmu_disable, 239 .is_enabled = clk_prcmu_is_enabled, 240 .recalc_rate = clk_prcmu_recalc_rate, 241 .round_rate = clk_prcmu_round_rate, 242 .set_rate = clk_prcmu_set_rate, 243 }; 244 245 static struct clk *clk_reg_prcmu(const char *name, 246 const char *parent_name, 247 u8 cg_sel, 248 unsigned long rate, 249 unsigned long flags, 250 const struct clk_ops *clk_prcmu_ops) 251 { 252 struct clk_prcmu *clk; 253 struct clk_init_data clk_prcmu_init; 254 struct clk *clk_reg; 255 256 if (!name) { 257 pr_err("clk_prcmu: %s invalid arguments passed\n", __func__); 258 return ERR_PTR(-EINVAL); 259 } 260 261 clk = kzalloc(sizeof(*clk), GFP_KERNEL); 262 if (!clk) 263 return ERR_PTR(-ENOMEM); 264 265 clk->cg_sel = cg_sel; 266 clk->is_prepared = 1; 267 clk->is_enabled = 1; 268 clk->opp_requested = 0; 269 /* "rate" can be used for changing the initial frequency */ 270 if (rate) 271 prcmu_set_clock_rate(cg_sel, rate); 272 273 clk_prcmu_init.name = name; 274 clk_prcmu_init.ops = clk_prcmu_ops; 275 clk_prcmu_init.flags = flags; 276 clk_prcmu_init.parent_names = (parent_name ? &parent_name : NULL); 277 clk_prcmu_init.num_parents = (parent_name ? 1 : 0); 278 clk->hw.init = &clk_prcmu_init; 279 280 clk_reg = clk_register(NULL, &clk->hw); 281 if (IS_ERR_OR_NULL(clk_reg)) 282 goto free_clk; 283 284 return clk_reg; 285 286 free_clk: 287 kfree(clk); 288 pr_err("clk_prcmu: %s failed to register clk\n", __func__); 289 return ERR_PTR(-ENOMEM); 290 } 291 292 struct clk *clk_reg_prcmu_scalable(const char *name, 293 const char *parent_name, 294 u8 cg_sel, 295 unsigned long rate, 296 unsigned long flags) 297 { 298 return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags, 299 &clk_prcmu_scalable_ops); 300 } 301 302 struct clk *clk_reg_prcmu_gate(const char *name, 303 const char *parent_name, 304 u8 cg_sel, 305 unsigned long flags) 306 { 307 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags, 308 &clk_prcmu_gate_ops); 309 } 310 311 struct clk *clk_reg_prcmu_scalable_rate(const char *name, 312 const char *parent_name, 313 u8 cg_sel, 314 unsigned long rate, 315 unsigned long flags) 316 { 317 return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags, 318 &clk_prcmu_scalable_rate_ops); 319 } 320 321 struct clk *clk_reg_prcmu_rate(const char *name, 322 const char *parent_name, 323 u8 cg_sel, 324 unsigned long flags) 325 { 326 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags, 327 &clk_prcmu_rate_ops); 328 } 329 330 struct clk *clk_reg_prcmu_opp_gate(const char *name, 331 const char *parent_name, 332 u8 cg_sel, 333 unsigned long flags) 334 { 335 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags, 336 &clk_prcmu_opp_gate_ops); 337 } 338 339 struct clk *clk_reg_prcmu_opp_volt_scalable(const char *name, 340 const char *parent_name, 341 u8 cg_sel, 342 unsigned long rate, 343 unsigned long flags) 344 { 345 return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags, 346 &clk_prcmu_opp_volt_scalable_ops); 347 } 348