Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: OMAP2+: clk: remove obsolete clksel support code

The clksel clock type is no longer used for anything, it is rather
replaced with common clock divider code. Thus, remove the dead code
from kernel.

Signed-off-by: Tero Kristo <t-kristo@ti.com>

+1 -480
+1 -2
arch/arm/mach-omap2/Makefile
··· 12 12 13 13 hwmod-common = omap_hwmod.o omap_hwmod_reset.o \ 14 14 omap_hwmod_common_data.o 15 - clock-common = clock.o clock_common_data.o \ 16 - clkt_clksel.o 15 + clock-common = clock.o clock_common_data.o 17 16 secure-common = omap-smc.o omap-secure.o 18 17 19 18 obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
-466
arch/arm/mach-omap2/clkt_clksel.c
··· 1 - /* 2 - * clkt_clksel.c - OMAP2/3/4 clksel clock functions 3 - * 4 - * Copyright (C) 2005-2008 Texas Instruments, Inc. 5 - * Copyright (C) 2004-2010 Nokia Corporation 6 - * 7 - * Contacts: 8 - * Richard Woodruff <r-woodruff2@ti.com> 9 - * Paul Walmsley 10 - * 11 - * This program is free software; you can redistribute it and/or modify 12 - * it under the terms of the GNU General Public License version 2 as 13 - * published by the Free Software Foundation. 14 - * 15 - * 16 - * clksel clocks are clocks that do not have a fixed parent, or that 17 - * can divide their parent's rate, or possibly both at the same time, based 18 - * on the contents of a hardware register bitfield. 19 - * 20 - * All of the various mux and divider settings can be encoded into 21 - * struct clksel* data structures, and then these can be autogenerated 22 - * from some hardware database for each new chip generation. This 23 - * should avoid the need to write, review, and validate a lot of new 24 - * clock code for each new chip, since it can be exported from the SoC 25 - * design flow. This is now done on OMAP4. 26 - * 27 - * The fusion of mux and divider clocks is a software creation. In 28 - * hardware reality, the multiplexer (parent selection) and the 29 - * divider exist separately. XXX At some point these clksel clocks 30 - * should be split into "divider" clocks and "mux" clocks to better 31 - * match the hardware. 32 - * 33 - * (The name "clksel" comes from the name of the corresponding 34 - * register field in the OMAP2/3 family of SoCs.) 35 - * 36 - * XXX Currently these clocks are only used in the OMAP2/3/4 code, but 37 - * many of the OMAP1 clocks should be convertible to use this 38 - * mechanism. 39 - */ 40 - #undef DEBUG 41 - 42 - #include <linux/kernel.h> 43 - #include <linux/errno.h> 44 - #include <linux/clk-provider.h> 45 - #include <linux/io.h> 46 - #include <linux/bug.h> 47 - 48 - #include "clock.h" 49 - 50 - /* Private functions */ 51 - 52 - /** 53 - * _get_clksel_by_parent() - return clksel struct for a given clk & parent 54 - * @clk: OMAP struct clk ptr to inspect 55 - * @src_clk: OMAP struct clk ptr of the parent clk to search for 56 - * 57 - * Scan the struct clksel array associated with the clock to find 58 - * the element associated with the supplied parent clock address. 59 - * Returns a pointer to the struct clksel on success or NULL on error. 60 - */ 61 - static const struct clksel *_get_clksel_by_parent(struct clk_hw_omap *clk, 62 - struct clk *src_clk) 63 - { 64 - const struct clksel *clks; 65 - 66 - if (!src_clk) 67 - return NULL; 68 - 69 - for (clks = clk->clksel; clks->parent; clks++) 70 - if (clks->parent == src_clk) 71 - break; /* Found the requested parent */ 72 - 73 - if (!clks->parent) { 74 - /* This indicates a data problem */ 75 - WARN(1, "clock: %s: could not find parent clock %s in clksel array\n", 76 - __clk_get_name(clk->hw.clk), __clk_get_name(src_clk)); 77 - return NULL; 78 - } 79 - 80 - return clks; 81 - } 82 - 83 - /** 84 - * _write_clksel_reg() - program a clock's clksel register in hardware 85 - * @clk: struct clk * to program 86 - * @v: clksel bitfield value to program (with LSB at bit 0) 87 - * 88 - * Shift the clksel register bitfield value @v to its appropriate 89 - * location in the clksel register and write it in. This function 90 - * will ensure that the write to the clksel_reg reaches its 91 - * destination before returning -- important since PRM and CM register 92 - * accesses can be quite slow compared to ARM cycles -- but does not 93 - * take into account any time the hardware might take to switch the 94 - * clock source. 95 - */ 96 - static void _write_clksel_reg(struct clk_hw_omap *clk, u32 field_val) 97 - { 98 - u32 v; 99 - 100 - v = omap2_clk_readl(clk, clk->clksel_reg); 101 - v &= ~clk->clksel_mask; 102 - v |= field_val << __ffs(clk->clksel_mask); 103 - omap2_clk_writel(v, clk, clk->clksel_reg); 104 - 105 - v = omap2_clk_readl(clk, clk->clksel_reg); /* OCP barrier */ 106 - } 107 - 108 - /** 109 - * _clksel_to_divisor() - turn clksel field value into integer divider 110 - * @clk: OMAP struct clk to use 111 - * @field_val: register field value to find 112 - * 113 - * Given a struct clk of a rate-selectable clksel clock, and a register field 114 - * value to search for, find the corresponding clock divisor. The register 115 - * field value should be pre-masked and shifted down so the LSB is at bit 0 116 - * before calling. Returns 0 on error or returns the actual integer divisor 117 - * upon success. 118 - */ 119 - static u32 _clksel_to_divisor(struct clk_hw_omap *clk, u32 field_val) 120 - { 121 - const struct clksel *clks; 122 - const struct clksel_rate *clkr; 123 - struct clk *parent; 124 - 125 - parent = __clk_get_parent(clk->hw.clk); 126 - 127 - clks = _get_clksel_by_parent(clk, parent); 128 - if (!clks) 129 - return 0; 130 - 131 - for (clkr = clks->rates; clkr->div; clkr++) { 132 - if (!(clkr->flags & cpu_mask)) 133 - continue; 134 - 135 - if (clkr->val == field_val) 136 - break; 137 - } 138 - 139 - if (!clkr->div) { 140 - /* This indicates a data error */ 141 - WARN(1, "clock: %s: could not find fieldval %d for parent %s\n", 142 - __clk_get_name(clk->hw.clk), field_val, 143 - __clk_get_name(parent)); 144 - return 0; 145 - } 146 - 147 - return clkr->div; 148 - } 149 - 150 - /** 151 - * _divisor_to_clksel() - turn clksel integer divisor into a field value 152 - * @clk: OMAP struct clk to use 153 - * @div: integer divisor to search for 154 - * 155 - * Given a struct clk of a rate-selectable clksel clock, and a clock 156 - * divisor, find the corresponding register field value. Returns the 157 - * register field value _before_ left-shifting (i.e., LSB is at bit 158 - * 0); or returns 0xFFFFFFFF (~0) upon error. 159 - */ 160 - static u32 _divisor_to_clksel(struct clk_hw_omap *clk, u32 div) 161 - { 162 - const struct clksel *clks; 163 - const struct clksel_rate *clkr; 164 - struct clk *parent; 165 - 166 - /* should never happen */ 167 - WARN_ON(div == 0); 168 - 169 - parent = __clk_get_parent(clk->hw.clk); 170 - clks = _get_clksel_by_parent(clk, parent); 171 - if (!clks) 172 - return ~0; 173 - 174 - for (clkr = clks->rates; clkr->div; clkr++) { 175 - if (!(clkr->flags & cpu_mask)) 176 - continue; 177 - 178 - if (clkr->div == div) 179 - break; 180 - } 181 - 182 - if (!clkr->div) { 183 - pr_err("clock: %s: could not find divisor %d for parent %s\n", 184 - __clk_get_name(clk->hw.clk), div, 185 - __clk_get_name(parent)); 186 - return ~0; 187 - } 188 - 189 - return clkr->val; 190 - } 191 - 192 - /** 193 - * _read_divisor() - get current divisor applied to parent clock (from hdwr) 194 - * @clk: OMAP struct clk to use. 195 - * 196 - * Read the current divisor register value for @clk that is programmed 197 - * into the hardware, convert it into the actual divisor value, and 198 - * return it; or return 0 on error. 199 - */ 200 - static u32 _read_divisor(struct clk_hw_omap *clk) 201 - { 202 - u32 v; 203 - 204 - if (!clk->clksel || !clk->clksel_mask) 205 - return 0; 206 - 207 - v = omap2_clk_readl(clk, clk->clksel_reg); 208 - v &= clk->clksel_mask; 209 - v >>= __ffs(clk->clksel_mask); 210 - 211 - return _clksel_to_divisor(clk, v); 212 - } 213 - 214 - /* Public functions */ 215 - 216 - /** 217 - * omap2_clksel_round_rate_div() - find divisor for the given clock and rate 218 - * @clk: OMAP struct clk to use 219 - * @target_rate: desired clock rate 220 - * @new_div: ptr to where we should store the divisor 221 - * 222 - * Finds 'best' divider value in an array based on the source and target 223 - * rates. The divider array must be sorted with smallest divider first. 224 - * This function is also used by the DPLL3 M2 divider code. 225 - * 226 - * Returns the rounded clock rate or returns 0xffffffff on error. 227 - */ 228 - u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk, 229 - 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 - struct clk *parent; 237 - unsigned long parent_rate; 238 - const char *clk_name; 239 - 240 - parent = __clk_get_parent(clk->hw.clk); 241 - clk_name = __clk_get_name(clk->hw.clk); 242 - parent_rate = __clk_get_rate(parent); 243 - 244 - if (!clk->clksel || !clk->clksel_mask) 245 - return ~0; 246 - 247 - pr_debug("clock: clksel_round_rate_div: %s target_rate %ld\n", 248 - clk_name, target_rate); 249 - 250 - *new_div = 1; 251 - 252 - clks = _get_clksel_by_parent(clk, parent); 253 - if (!clks) 254 - return ~0; 255 - 256 - for (clkr = clks->rates; clkr->div; clkr++) { 257 - if (!(clkr->flags & cpu_mask)) 258 - continue; 259 - 260 - /* Sanity check */ 261 - if (clkr->div <= last_div) 262 - pr_err("clock: %s: clksel_rate table not sorted\n", 263 - clk_name); 264 - 265 - last_div = clkr->div; 266 - 267 - test_rate = parent_rate / clkr->div; 268 - 269 - if (test_rate <= target_rate) 270 - break; /* found it */ 271 - } 272 - 273 - if (!clkr->div) { 274 - pr_err("clock: %s: could not find divisor for target rate %ld for parent %s\n", 275 - clk_name, target_rate, __clk_get_name(parent)); 276 - return ~0; 277 - } 278 - 279 - *new_div = clkr->div; 280 - 281 - pr_debug("clock: new_div = %d, new_rate = %ld\n", *new_div, 282 - (parent_rate / clkr->div)); 283 - 284 - return parent_rate / clkr->div; 285 - } 286 - 287 - /* 288 - * Clocktype interface functions to the OMAP clock code 289 - * (i.e., those used in struct clk field function pointers, etc.) 290 - */ 291 - 292 - /** 293 - * omap2_clksel_find_parent_index() - return the array index of the current 294 - * hardware parent of @hw 295 - * @hw: struct clk_hw * to find the current hardware parent of 296 - * 297 - * Given a struct clk_hw pointer @hw to the 'hw' member of a struct 298 - * clk_hw_omap record representing a source-selectable hardware clock, 299 - * read the hardware register and determine what its parent is 300 - * currently set to. Intended to be called only by the common clock 301 - * framework struct clk_hw_ops.get_parent function pointer. Return 302 - * the array index of this parent clock upon success -- there is no 303 - * way to return an error, so if we encounter an error, just WARN() 304 - * and pretend that we know that we're doing. 305 - */ 306 - u8 omap2_clksel_find_parent_index(struct clk_hw *hw) 307 - { 308 - struct clk_hw_omap *clk = to_clk_hw_omap(hw); 309 - const struct clksel *clks; 310 - const struct clksel_rate *clkr; 311 - u32 r, found = 0; 312 - struct clk *parent; 313 - const char *clk_name; 314 - int ret = 0, f = 0; 315 - 316 - parent = __clk_get_parent(hw->clk); 317 - clk_name = __clk_get_name(hw->clk); 318 - 319 - /* XXX should be able to return an error */ 320 - WARN((!clk->clksel || !clk->clksel_mask), 321 - "clock: %s: attempt to call on a non-clksel clock", clk_name); 322 - 323 - r = omap2_clk_readl(clk, clk->clksel_reg) & clk->clksel_mask; 324 - r >>= __ffs(clk->clksel_mask); 325 - 326 - for (clks = clk->clksel; clks->parent && !found; clks++) { 327 - for (clkr = clks->rates; clkr->div && !found; clkr++) { 328 - if (!(clkr->flags & cpu_mask)) 329 - continue; 330 - 331 - if (clkr->val == r) { 332 - found = 1; 333 - ret = f; 334 - } 335 - } 336 - f++; 337 - } 338 - 339 - /* This indicates a data error */ 340 - WARN(!found, "clock: %s: init parent: could not find regval %0x\n", 341 - clk_name, r); 342 - 343 - return ret; 344 - } 345 - 346 - 347 - /** 348 - * omap2_clksel_recalc() - function ptr to pass via struct clk .recalc field 349 - * @clk: struct clk * 350 - * 351 - * This function is intended to be called only by the clock framework. 352 - * Each clksel clock should have its struct clk .recalc field set to this 353 - * function. Returns the clock's current rate, based on its parent's rate 354 - * and its current divisor setting in the hardware. 355 - */ 356 - unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate) 357 - { 358 - unsigned long rate; 359 - u32 div = 0; 360 - struct clk_hw_omap *clk = to_clk_hw_omap(hw); 361 - 362 - if (!parent_rate) 363 - return 0; 364 - 365 - div = _read_divisor(clk); 366 - if (!div) 367 - rate = parent_rate; 368 - else 369 - rate = parent_rate / div; 370 - 371 - pr_debug("%s: recalc'd %s's rate to %lu (div %d)\n", __func__, 372 - __clk_get_name(hw->clk), rate, div); 373 - 374 - return rate; 375 - } 376 - 377 - /** 378 - * omap2_clksel_round_rate() - find rounded rate for the given clock and rate 379 - * @clk: OMAP struct clk to use 380 - * @target_rate: desired clock rate 381 - * 382 - * This function is intended to be called only by the clock framework. 383 - * Finds best target rate based on the source clock and possible dividers. 384 - * rates. The divider array must be sorted with smallest divider first. 385 - * 386 - * Returns the rounded clock rate or returns 0xffffffff on error. 387 - */ 388 - long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate, 389 - unsigned long *parent_rate) 390 - { 391 - struct clk_hw_omap *clk = to_clk_hw_omap(hw); 392 - u32 new_div; 393 - 394 - return omap2_clksel_round_rate_div(clk, target_rate, &new_div); 395 - } 396 - 397 - /** 398 - * omap2_clksel_set_rate() - program clock rate in hardware 399 - * @clk: struct clk * to program rate 400 - * @rate: target rate to program 401 - * 402 - * This function is intended to be called only by the clock framework. 403 - * Program @clk's rate to @rate in the hardware. The clock can be 404 - * either enabled or disabled when this happens, although if the clock 405 - * is enabled, some downstream devices may glitch or behave 406 - * unpredictably when the clock rate is changed - this depends on the 407 - * hardware. This function does not currently check the usecount of 408 - * the clock, so if multiple drivers are using the clock, and the rate 409 - * is changed, they will all be affected without any notification. 410 - * Returns -EINVAL upon error, or 0 upon success. 411 - */ 412 - int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate, 413 - unsigned long parent_rate) 414 - { 415 - struct clk_hw_omap *clk = to_clk_hw_omap(hw); 416 - u32 field_val, validrate, new_div = 0; 417 - 418 - if (!clk->clksel || !clk->clksel_mask) 419 - return -EINVAL; 420 - 421 - validrate = omap2_clksel_round_rate_div(clk, rate, &new_div); 422 - if (validrate != rate) 423 - return -EINVAL; 424 - 425 - field_val = _divisor_to_clksel(clk, new_div); 426 - if (field_val == ~0) 427 - return -EINVAL; 428 - 429 - _write_clksel_reg(clk, field_val); 430 - 431 - pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(hw->clk), 432 - __clk_get_rate(hw->clk)); 433 - 434 - return 0; 435 - } 436 - 437 - /* 438 - * Clksel parent setting function - not passed in struct clk function 439 - * pointer - instead, the OMAP clock code currently assumes that any 440 - * parent-setting clock is a clksel clock, and calls 441 - * omap2_clksel_set_parent() by default 442 - */ 443 - 444 - /** 445 - * omap2_clksel_set_parent() - change a clock's parent clock 446 - * @clk: struct clk * of the child clock 447 - * @new_parent: struct clk * of the new parent clock 448 - * 449 - * This function is intended to be called only by the clock framework. 450 - * Change the parent clock of clock @clk to @new_parent. This is 451 - * intended to be used while @clk is disabled. This function does not 452 - * currently check the usecount of the clock, so if multiple drivers 453 - * are using the clock, and the parent is changed, they will all be 454 - * affected without any notification. Returns -EINVAL upon error, or 455 - * 0 upon success. 456 - */ 457 - int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val) 458 - { 459 - struct clk_hw_omap *clk = to_clk_hw_omap(hw); 460 - 461 - if (!clk->clksel || !clk->clksel_mask) 462 - return -EINVAL; 463 - 464 - _write_clksel_reg(clk, field_val); 465 - return 0; 466 - }
-12
arch/arm/mach-omap2/clock.h
··· 186 186 187 187 void __init omap2_clk_disable_clkdm_control(void); 188 188 189 - /* clkt_clksel.c public functions */ 190 - u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk, 191 - unsigned long target_rate, 192 - u32 *new_div); 193 - u8 omap2_clksel_find_parent_index(struct clk_hw *hw); 194 - unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate); 195 - long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate, 196 - unsigned long *parent_rate); 197 - int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate, 198 - unsigned long parent_rate); 199 - int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val); 200 - 201 189 int omap2_clk_enable_autoidle_all(void); 202 190 int omap2_clk_allow_idle(struct clk *clk); 203 191 int omap2_clk_deny_idle(struct clk *clk);