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 19struct 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 29static 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 41static 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_get_name(hw->clk)); 47 else 48 clk->is_prepared = 0; 49} 50 51static 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 57static 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 64static 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 70static 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 76static 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 83static 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 90static 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 97static 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_get_name(hw->clk), 105 100); 106 if (err) { 107 pr_err("clk_prcmu: %s fail req APE OPP for %s.\n", 108 __func__, __clk_get_name(hw->clk)); 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_get_name(hw->clk)); 118 clk->opp_requested = 0; 119 return err; 120 } 121 122 clk->is_prepared = 1; 123 return 0; 124} 125 126static 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_get_name(hw->clk)); 133 return; 134 } 135 136 if (clk->opp_requested) { 137 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, 138 (char *)__clk_get_name(hw->clk)); 139 clk->opp_requested = 0; 140 } 141 142 clk->is_prepared = 0; 143} 144 145static 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_get_name(hw->clk)); 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 171static 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_get_name(hw->clk)); 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 189static 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 201static 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 211static 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 218static struct clk_ops clk_prcmu_rate_ops = { 219 .is_enabled = clk_prcmu_is_enabled, 220 .recalc_rate = clk_prcmu_recalc_rate, 221}; 222 223static 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 233static 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 245static 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 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(struct clk_prcmu), GFP_KERNEL); 262 if (!clk) { 263 pr_err("clk_prcmu: %s could not allocate clk\n", __func__); 264 return ERR_PTR(-ENOMEM); 265 } 266 267 clk->cg_sel = cg_sel; 268 clk->is_prepared = 1; 269 clk->is_enabled = 1; 270 clk->opp_requested = 0; 271 /* "rate" can be used for changing the initial frequency */ 272 if (rate) 273 prcmu_set_clock_rate(cg_sel, rate); 274 275 clk_prcmu_init.name = name; 276 clk_prcmu_init.ops = clk_prcmu_ops; 277 clk_prcmu_init.flags = flags; 278 clk_prcmu_init.parent_names = (parent_name ? &parent_name : NULL); 279 clk_prcmu_init.num_parents = (parent_name ? 1 : 0); 280 clk->hw.init = &clk_prcmu_init; 281 282 clk_reg = clk_register(NULL, &clk->hw); 283 if (IS_ERR_OR_NULL(clk_reg)) 284 goto free_clk; 285 286 return clk_reg; 287 288free_clk: 289 kfree(clk); 290 pr_err("clk_prcmu: %s failed to register clk\n", __func__); 291 return ERR_PTR(-ENOMEM); 292} 293 294struct clk *clk_reg_prcmu_scalable(const char *name, 295 const char *parent_name, 296 u8 cg_sel, 297 unsigned long rate, 298 unsigned long flags) 299{ 300 return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags, 301 &clk_prcmu_scalable_ops); 302} 303 304struct clk *clk_reg_prcmu_gate(const char *name, 305 const char *parent_name, 306 u8 cg_sel, 307 unsigned long flags) 308{ 309 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags, 310 &clk_prcmu_gate_ops); 311} 312 313struct clk *clk_reg_prcmu_scalable_rate(const char *name, 314 const char *parent_name, 315 u8 cg_sel, 316 unsigned long rate, 317 unsigned long flags) 318{ 319 return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags, 320 &clk_prcmu_scalable_rate_ops); 321} 322 323struct clk *clk_reg_prcmu_rate(const char *name, 324 const char *parent_name, 325 u8 cg_sel, 326 unsigned long flags) 327{ 328 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags, 329 &clk_prcmu_rate_ops); 330} 331 332struct clk *clk_reg_prcmu_opp_gate(const char *name, 333 const char *parent_name, 334 u8 cg_sel, 335 unsigned long flags) 336{ 337 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags, 338 &clk_prcmu_opp_gate_ops); 339} 340 341struct clk *clk_reg_prcmu_opp_volt_scalable(const char *name, 342 const char *parent_name, 343 u8 cg_sel, 344 unsigned long rate, 345 unsigned long flags) 346{ 347 return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags, 348 &clk_prcmu_opp_volt_scalable_ops); 349} 350