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

clk: allow a clk divider with max divisor when zero

This commit allows certain Broadcom STB clock dividers to be used with
clk-divider.c. It allows for a clock whose field value is the equal
to the divisor, execpt when the field value is zero, in which case the
divisor is 2^width. For example, consider a divisor clock with a two
bit field:

value divisor
0 4
1 1
2 2
3 3

Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>

authored by

Jim Quinlan and committed by
Stephen Boyd
afe76c8f 25d4d341

+15 -5
+11 -5
drivers/clk/clk-divider.c
··· 78 78 } 79 79 80 80 static unsigned int _get_div(const struct clk_div_table *table, 81 - unsigned int val, unsigned long flags) 81 + unsigned int val, unsigned long flags, u8 width) 82 82 { 83 83 if (flags & CLK_DIVIDER_ONE_BASED) 84 84 return val; 85 85 if (flags & CLK_DIVIDER_POWER_OF_TWO) 86 86 return 1 << val; 87 + if (flags & CLK_DIVIDER_MAX_AT_ZERO) 88 + return val ? val : div_mask(width) + 1; 87 89 if (table) 88 90 return _get_table_div(table, val); 89 91 return val + 1; ··· 103 101 } 104 102 105 103 static unsigned int _get_val(const struct clk_div_table *table, 106 - unsigned int div, unsigned long flags) 104 + unsigned int div, unsigned long flags, u8 width) 107 105 { 108 106 if (flags & CLK_DIVIDER_ONE_BASED) 109 107 return div; 110 108 if (flags & CLK_DIVIDER_POWER_OF_TWO) 111 109 return __ffs(div); 110 + if (flags & CLK_DIVIDER_MAX_AT_ZERO) 111 + return (div == div_mask(width) + 1) ? 0 : div; 112 112 if (table) 113 113 return _get_table_val(table, div); 114 114 return div - 1; ··· 121 117 const struct clk_div_table *table, 122 118 unsigned long flags) 123 119 { 120 + struct clk_divider *divider = to_clk_divider(hw); 124 121 unsigned int div; 125 122 126 - div = _get_div(table, val, flags); 123 + div = _get_div(table, val, flags, divider->width); 127 124 if (!div) { 128 125 WARN(!(flags & CLK_DIVIDER_ALLOW_ZERO), 129 126 "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n", ··· 356 351 if (divider->flags & CLK_DIVIDER_READ_ONLY) { 357 352 bestdiv = readl(divider->reg) >> divider->shift; 358 353 bestdiv &= div_mask(divider->width); 359 - bestdiv = _get_div(divider->table, bestdiv, divider->flags); 354 + bestdiv = _get_div(divider->table, bestdiv, divider->flags, 355 + divider->width); 360 356 return DIV_ROUND_UP(*prate, bestdiv); 361 357 } 362 358 ··· 376 370 if (!_is_valid_div(table, div, flags)) 377 371 return -EINVAL; 378 372 379 - value = _get_val(table, div, flags); 373 + value = _get_val(table, div, flags, width); 380 374 381 375 return min_t(unsigned int, value, div_mask(width)); 382 376 }
+4
include/linux/clk-provider.h
··· 361 361 * to the closest integer instead of the up one. 362 362 * CLK_DIVIDER_READ_ONLY - The divider settings are preconfigured and should 363 363 * not be changed by the clock framework. 364 + * CLK_DIVIDER_MAX_AT_ZERO - For dividers which are like CLK_DIVIDER_ONE_BASED 365 + * except when the value read from the register is zero, the divisor is 366 + * 2^width of the field. 364 367 */ 365 368 struct clk_divider { 366 369 struct clk_hw hw; ··· 381 378 #define CLK_DIVIDER_HIWORD_MASK BIT(3) 382 379 #define CLK_DIVIDER_ROUND_CLOSEST BIT(4) 383 380 #define CLK_DIVIDER_READ_ONLY BIT(5) 381 + #define CLK_DIVIDER_MAX_AT_ZERO BIT(6) 384 382 385 383 extern const struct clk_ops clk_divider_ops; 386 384