1 2#undef DEBUG 3 4#include <linux/kernel.h> 5#include <linux/errno.h> 6#include <linux/clk.h> 7#include <linux/io.h> 8 9#include <plat/clock.h> 10 11#include "clock.h" 12 13/* Private functions */ 14 15/** 16 * _get_clksel_by_parent() - return clksel struct for a given clk & parent 17 * @clk: OMAP struct clk ptr to inspect 18 * @src_clk: OMAP struct clk ptr of the parent clk to search for 19 * 20 * Scan the struct clksel array associated with the clock to find 21 * the element associated with the supplied parent clock address. 22 * Returns a pointer to the struct clksel on success or NULL on error. 23 */ 24static const struct clksel *_get_clksel_by_parent(struct clk *clk, 25 struct clk *src_clk) 26{ 27 const struct clksel *clks; 28 29 for (clks = clk->clksel; clks->parent; clks++) 30 if (clks->parent == src_clk) 31 break; /* Found the requested parent */ 32 33 if (!clks->parent) { 34 /* This indicates a data problem */ 35 WARN(1, "clock: Could not find parent clock %s in clksel array " 36 "of clock %s\n", src_clk->name, clk->name); 37 return NULL; 38 } 39 40 return clks; 41} 42 43/** 44 * _get_div_and_fieldval() - find the new clksel divisor and field value to use 45 * @src_clk: planned new parent struct clk * 46 * @clk: struct clk * that is being reparented 47 * @field_val: pointer to a u32 to contain the register data for the divisor 48 * 49 * Given an intended new parent struct clk * @src_clk, and the struct 50 * clk * @clk to the clock that is being reparented, find the 51 * appropriate rate divisor for the new clock (returned as the return 52 * value), and the corresponding register bitfield data to program to 53 * reach that divisor (returned in the u32 pointed to by @field_val). 54 * Returns 0 on error, or returns the newly-selected divisor upon 55 * success (in this latter case, the corresponding register bitfield 56 * value is passed back in the variable pointed to by @field_val) 57 */ 58static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk, 59 u32 *field_val) 60{ 61 const struct clksel *clks; 62 const struct clksel_rate *clkr, *max_clkr; 63 u8 max_div = 0; 64 65 clks = _get_clksel_by_parent(clk, src_clk); 66 if (!clks) 67 return 0; 68 69 for (clkr = clks->rates; clkr->div; clkr++) { 70 if (!(clkr->flags & cpu_mask)) 71 continue; 72 73 if (clkr->div > max_div) { 74 max_div = clkr->div; 75 max_clkr = clkr; 76 } 77 } 78 79 if (max_div == 0) { 80 /* This indicates an error in the clksel data */ 81 WARN(1, "clock: Could not find divisor for clock %s parent %s" 82 "\n", clk->name, src_clk->parent->name); 83 return 0; 84 } 85 86 *field_val = max_clkr->val; 87 88 return max_div; 89} 90 91/** 92 * _write_clksel_reg() - program a clock's clksel register in hardware 93 * @clk: struct clk * to program 94 * @v: clksel bitfield value to program (with LSB at bit 0) 95 * 96 * Shift the clksel register bitfield value @v to its appropriate 97 * location in the clksel register and write it in. This function 98 * will ensure that the write to the clksel_reg reaches its 99 * destination before returning -- important since PRM and CM register 100 * accesses can be quite slow compared to ARM cycles -- but does not 101 * take into account any time the hardware might take to switch the 102 * clock source. 103 */ 104static void _write_clksel_reg(struct clk *clk, u32 field_val) 105{ 106 u32 v; 107 108 v = __raw_readl(clk->clksel_reg); 109 v &= ~clk->clksel_mask; 110 v |= field_val << __ffs(clk->clksel_mask); 111 __raw_writel(v, clk->clksel_reg); 112 113 v = __raw_readl(clk->clksel_reg); /* OCP barrier */ 114} 115 116/** 117 * _clksel_to_divisor() - turn clksel field value into integer divider 118 * @clk: OMAP struct clk to use 119 * @field_val: register field value to find 120 * 121 * Given a struct clk of a rate-selectable clksel clock, and a register field 122 * value to search for, find the corresponding clock divisor. The register 123 * field value should be pre-masked and shifted down so the LSB is at bit 0 124 * before calling. Returns 0 on error or returns the actual integer divisor 125 * upon success. 126 */ 127static u32 _clksel_to_divisor(struct clk *clk, u32 field_val) 128{ 129 const struct clksel *clks; 130 const struct clksel_rate *clkr; 131 132 clks = _get_clksel_by_parent(clk, clk->parent); 133 if (!clks) 134 return 0; 135 136 for (clkr = clks->rates; clkr->div; clkr++) { 137 if (!(clkr->flags & cpu_mask)) 138 continue; 139 140 if (clkr->val == field_val) 141 break; 142 } 143 144 if (!clkr->div) { 145 /* This indicates a data error */ 146 WARN(1, "clock: Could not find fieldval %d for clock %s parent " 147 "%s\n", field_val, clk->name, clk->parent->name); 148 return 0; 149 } 150 151 return clkr->div; 152} 153 154/** 155 * _divisor_to_clksel() - turn clksel integer divisor into a field value 156 * @clk: OMAP struct clk to use 157 * @div: integer divisor to search for 158 * 159 * Given a struct clk of a rate-selectable clksel clock, and a clock 160 * divisor, find the corresponding register field value. Returns the 161 * register field value _before_ left-shifting (i.e., LSB is at bit 162 * 0); or returns 0xFFFFFFFF (~0) upon error. 163 */ 164static u32 _divisor_to_clksel(struct clk *clk, u32 div) 165{ 166 const struct clksel *clks; 167 const struct clksel_rate *clkr; 168 169 /* should never happen */ 170 WARN_ON(div == 0); 171 172 clks = _get_clksel_by_parent(clk, clk->parent); 173 if (!clks) 174 return ~0; 175 176 for (clkr = clks->rates; clkr->div; clkr++) { 177 if (!(clkr->flags & cpu_mask)) 178 continue; 179 180 if (clkr->div == div) 181 break; 182 } 183 184 if (!clkr->div) { 185 pr_err("clock: Could not find divisor %d for clock %s parent " 186 "%s\n", div, clk->name, clk->parent->name); 187 return ~0; 188 } 189 190 return clkr->val; 191} 192 193/** 194 * _read_divisor() - get current divisor applied to parent clock (from hdwr) 195 * @clk: OMAP struct clk to use. 196 * 197 * Read the current divisor register value for @clk that is programmed 198 * into the hardware, convert it into the actual divisor value, and 199 * return it; or return 0 on error. 200 */ 201static u32 _read_divisor(struct clk *clk) 202{ 203 u32 v; 204 205 if (!clk->clksel || !clk->clksel_mask) 206 return 0; 207 208 v = __raw_readl(clk->clksel_reg); 209 v &= clk->clksel_mask; 210 v >>= __ffs(clk->clksel_mask); 211 212 return _clksel_to_divisor(clk, v); 213} 214 215/* Public functions */ 216 217/** 218 * omap2_clksel_round_rate_div() - find divisor for the given clock and rate 219 * @clk: OMAP struct clk to use 220 * @target_rate: desired clock rate 221 * @new_div: ptr to where we should store the divisor 222 * 223 * Finds 'best' divider value in an array based on the source and target 224 * rates. The divider array must be sorted with smallest divider first. 225 * This function is also used by the DPLL3 M2 divider code. 226 * 227 * Returns the rounded clock rate or returns 0xffffffff on error. 228 */ 229u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate, 230 u32 *new_div) 231{ 232 unsigned long test_rate; 233 const struct clksel *clks; 234 const struct clksel_rate *clkr; 235 u32 last_div = 0; 236 237 if (!clk->clksel || !clk->clksel_mask) 238 return ~0; 239 240 pr_debug("clock: clksel_round_rate_div: %s target_rate %ld\n", 241 clk->name, target_rate); 242 243 *new_div = 1; 244 245 clks = _get_clksel_by_parent(clk, clk->parent); 246 if (!clks) 247 return ~0; 248 249 for (clkr = clks->rates; clkr->div; clkr++) { 250 if (!(clkr->flags & cpu_mask)) 251 continue; 252 253 /* Sanity check */ 254 if (clkr->div <= last_div) 255 pr_err("clock: clksel_rate table not sorted " 256 "for clock %s", clk->name); 257 258 last_div = clkr->div; 259 260 test_rate = clk->parent->rate / clkr->div; 261 262 if (test_rate <= target_rate) 263 break; /* found it */ 264 } 265 266 if (!clkr->div) { 267 pr_err("clock: Could not find divisor for target " 268 "rate %ld for clock %s parent %s\n", target_rate, 269 clk->name, clk->parent->name); 270 return ~0; 271 } 272 273 *new_div = clkr->div; 274 275 pr_debug("clock: new_div = %d, new_rate = %ld\n", *new_div, 276 (clk->parent->rate / clkr->div)); 277 278 return clk->parent->rate / clkr->div; 279} 280 281/* 282 * Clocktype interface functions to the OMAP clock code 283 * (i.e., those used in struct clk field function pointers, etc.) 284 */ 285 286/** 287 * omap2_init_clksel_parent() - set a clksel clk's parent field from the hdwr 288 * @clk: OMAP clock struct ptr to use 289 * 290 * Given a pointer @clk to a source-selectable struct clk, read the 291 * hardware register and determine what its parent is currently set 292 * to. Update @clk's .parent field with the appropriate clk ptr. No 293 * return value. 294 */ 295void omap2_init_clksel_parent(struct clk *clk) 296{ 297 const struct clksel *clks; 298 const struct clksel_rate *clkr; 299 u32 r, found = 0; 300 301 if (!clk->clksel || !clk->clksel_mask) 302 return; 303 304 r = __raw_readl(clk->clksel_reg) & clk->clksel_mask; 305 r >>= __ffs(clk->clksel_mask); 306 307 for (clks = clk->clksel; clks->parent && !found; clks++) { 308 for (clkr = clks->rates; clkr->div && !found; clkr++) { 309 if (!(clkr->flags & cpu_mask)) 310 continue; 311 312 if (clkr->val == r) { 313 if (clk->parent != clks->parent) { 314 pr_debug("clock: inited %s parent " 315 "to %s (was %s)\n", 316 clk->name, clks->parent->name, 317 ((clk->parent) ? 318 clk->parent->name : "NULL")); 319 clk_reparent(clk, clks->parent); 320 }; 321 found = 1; 322 } 323 } 324 } 325 326 /* This indicates a data error */ 327 WARN(!found, "clock: %s: init parent: could not find regval %0x\n", 328 clk->name, r); 329 330 return; 331} 332 333/** 334 * omap2_clksel_recalc() - function ptr to pass via struct clk .recalc field 335 * @clk: struct clk * 336 * 337 * This function is intended to be called only by the clock framework. 338 * Each clksel clock should have its struct clk .recalc field set to this 339 * function. Returns the clock's current rate, based on its parent's rate 340 * and its current divisor setting in the hardware. 341 */ 342unsigned long omap2_clksel_recalc(struct clk *clk) 343{ 344 unsigned long rate; 345 u32 div = 0; 346 347 div = _read_divisor(clk); 348 if (div == 0) 349 return clk->rate; 350 351 rate = clk->parent->rate / div; 352 353 pr_debug("clock: %s: recalc'd rate is %ld (div %d)\n", clk->name, 354 rate, div); 355 356 return rate; 357} 358 359/** 360 * omap2_clksel_round_rate() - find rounded rate for the given clock and rate 361 * @clk: OMAP struct clk to use 362 * @target_rate: desired clock rate 363 * 364 * This function is intended to be called only by the clock framework. 365 * Finds best target rate based on the source clock and possible dividers. 366 * rates. The divider array must be sorted with smallest divider first. 367 * 368 * Returns the rounded clock rate or returns 0xffffffff on error. 369 */ 370long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate) 371{ 372 u32 new_div; 373 374 return omap2_clksel_round_rate_div(clk, target_rate, &new_div); 375} 376 377/** 378 * omap2_clksel_set_rate() - program clock rate in hardware 379 * @clk: struct clk * to program rate 380 * @rate: target rate to program 381 * 382 * This function is intended to be called only by the clock framework. 383 * Program @clk's rate to @rate in the hardware. The clock can be 384 * either enabled or disabled when this happens, although if the clock 385 * is enabled, some downstream devices may glitch or behave 386 * unpredictably when the clock rate is changed - this depends on the 387 * hardware. This function does not currently check the usecount of 388 * the clock, so if multiple drivers are using the clock, and the rate 389 * is changed, they will all be affected without any notification. 390 * Returns -EINVAL upon error, or 0 upon success. 391 */ 392int omap2_clksel_set_rate(struct clk *clk, unsigned long rate) 393{ 394 u32 field_val, validrate, new_div = 0; 395 396 if (!clk->clksel || !clk->clksel_mask) 397 return -EINVAL; 398 399 validrate = omap2_clksel_round_rate_div(clk, rate, &new_div); 400 if (validrate != rate) 401 return -EINVAL; 402 403 field_val = _divisor_to_clksel(clk, new_div); 404 if (field_val == ~0) 405 return -EINVAL; 406 407 _write_clksel_reg(clk, field_val); 408 409 clk->rate = clk->parent->rate / new_div; 410 411 pr_debug("clock: %s: set rate to %ld\n", clk->name, clk->rate); 412 413 return 0; 414} 415 416/* 417 * Clksel parent setting function - not passed in struct clk function 418 * pointer - instead, the OMAP clock code currently assumes that any 419 * parent-setting clock is a clksel clock, and calls 420 * omap2_clksel_set_parent() by default 421 */ 422 423/** 424 * omap2_clksel_set_parent() - change a clock's parent clock 425 * @clk: struct clk * of the child clock 426 * @new_parent: struct clk * of the new parent clock 427 * 428 * This function is intended to be called only by the clock framework. 429 * Change the parent clock of clock @clk to @new_parent. This is 430 * intended to be used while @clk is disabled. This function does not 431 * currently check the usecount of the clock, so if multiple drivers 432 * are using the clock, and the parent is changed, they will all be 433 * affected without any notification. Returns -EINVAL upon error, or 434 * 0 upon success. 435 */ 436int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent) 437{ 438 u32 field_val = 0; 439 u32 parent_div; 440 441 if (!clk->clksel || !clk->clksel_mask) 442 return -EINVAL; 443 444 parent_div = _get_div_and_fieldval(new_parent, clk, &field_val); 445 if (!parent_div) 446 return -EINVAL; 447 448 _write_clksel_reg(clk, field_val); 449 450 clk_reparent(clk, new_parent); 451 452 /* CLKSEL clocks follow their parents' rates, divided by a divisor */ 453 clk->rate = new_parent->rate; 454 455 if (parent_div > 0) 456 clk->rate /= parent_div; 457 458 pr_debug("clock: %s: set parent to %s (new rate %ld)\n", 459 clk->name, clk->parent->name, clk->rate); 460 461 return 0; 462} 463