[PATCH v3 1/2] clk: divider: Add CLK_DIVIDER_EVEN flag support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Ping.... :)

On 2018/5/8 10:19, Shawn Lin wrote:
> Hi Michael and Stephen
> 
> Any chance to take a look at this patch? :)
> 
> On 2018/4/8 15:28, Shawn Lin wrote:
>> CLK_DIVIDER_EVEN is used for clock divders that should only
>> use even number in the div field.
>>
>> Two clock divder should consider to use this flag
>> (1) The divder is physically only support even div number to
>> generate 50% duty cycle clock rate.
>> (2) The divder's clock consumer request it to use even div number
>> to generate the most closest requested rate for whatever reason.
>>
>> In some platforms, for instance Rockchip, the eMMC/SDIO/SDMMC should
>> request divder to use even number when working at a high throughput
>> speed mode reliably. However, that wasn't guaranteed by clock framework.
>> So the previous tricky is to carefully assign magic clock rate to their
>> parents as well as consumer's clock rate when requesting. That works
>> bad in practice if folks change the parents clock rate or the clock
>> hierarchy randomly. That also work bad if the consumer's clock rate
>> came from the DT, which is changed so fraquent for different boards.
>>
>> To make it's less prone to make mistake and to make it really respect
>> the fact that the divder should use even number to the div field, we
>> need the clock framework's help. Now we have CLK_DIVIDER_POWER_OF_TWO,
>> which could guarantee the div field is even number, however, obviously
>> it skips the even numbers which isn't the power of 2, but maybe which is
>> the best div to generate closest clock rate for consumer.
>>
>> Look at the examples here when doing some random test on Rockchip's
>> platforms, by changing the requested clock rate from DT, namely
>> assigning different max-frquency for MMC node,
>>
>> when the mmc host driver requests 80MHz with CLK_DIVIDER_POWER_OF_TWO
>> flag for the clock divder, it shows the final clock rate is 61.44Mhz
>>
>> pll_vpll0??????? 1??????? 1 983039999???? 0?? 0
>> ??? vpll0??????? 4??????? 4 983039999???? 0?? 0
>> ????? clk_emmc_div?????? 1??????? 1 122880000???? 0?? 0
>> ????clk_emmc??? 1??????? 1 122880000???? 0?? 0
>> ????? emmc_sample??? 0??????? 0? 61440000??? 0 155
>> ????? emmc_drv??? 0??????? 0? 61440000??? 0 180
>>
>> With this patch and add CLK_DIVIDER_EVEN flag for clk_emmc_div, we get
>> the final clock rate, 67.7376MHz.
>>
>> pll_vpll1?????????????? 1??????? 1 812851199??? 0?? 0
>> ??? vpll1??????????????? 2??????? 2 812851199???? 0?? 0
>> ????? clk_emmc_div?????? 1??????? 1 135475200???? 0?? 0
>> ????clk_emmc??? 1??????? 1 135475200???? 0?? 0
>> ????? emmc_sample?? 0??????? 0? 67737600???? 0 113
>> ????? emmc_drv??? 0??????? 0? 67737600??? 0 180
>>
>> Apprently 67737600 is better than 61440000 when requesting 80MHz.
>> Of course, we could have more case that worsen the gap between
>> the desired rate and the actual rate if using CLK_DIVIDER_POWER_OF_TWO.
>>
>> Alternatively, clk_div_table could be resorted to handle different kinds
>> of div limilation, and it seems to be applied to irregular div 
>> calculation
>> in practice by current clock provider drivers, but even number for div
>> field is a rather common, regular and symmetrical requirement. So it is
>> worth to introduces CLK_DIVIDER_EVEN flag for clock framework to make
>> the best in this process.
>>
>> Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>
>>
>> ---
>>
>> Changes in v3:
>> - Fix a wrong if condition check
>>
>> Changes in v2:
>> - Avoid to use div 1 if (CLK_DIVIDER_EVEN | CLK_DIVIDER_POWER_OF_TWO)
>> ?? suggested by Heiko. And seems actually no other flags should be 
>> bothered
>> ?? by this newly added CLK_DIVIDER_EVEN.
>>
>> ? drivers/clk/clk-divider.c??? | 26 ++++++++++++++++++++++++--
>> ? include/linux/clk-provider.h |? 3 +++
>> ? 2 files changed, 27 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
>> index b6234a5..8f305f1 100644
>> --- a/drivers/clk/clk-divider.c
>> +++ b/drivers/clk/clk-divider.c
>> @@ -159,8 +159,17 @@ static bool _is_valid_table_div(const struct 
>> clk_div_table *table,
>> ? static bool _is_valid_div(const struct clk_div_table *table, 
>> unsigned int div,
>> ??????????????? unsigned long flags)
>> ? {
>> -??? if (flags & CLK_DIVIDER_POWER_OF_TWO)
>> -??????? return is_power_of_2(div);
>> +??? bool is_valid;
>> +
>> +??? if (flags & CLK_DIVIDER_POWER_OF_TWO) {
>> +??????? is_valid = is_power_of_2(div);
>> +??????? if (flags & CLK_DIVIDER_EVEN)
>> +??????????? return is_valid && (div != 1);
>> +??????? return is_valid;
>> +??? }
>> +
>> +??? if (flags & CLK_DIVIDER_EVEN)
>> +??????? return !(div % 2);
>> ????? if (table)
>> ????????? return _is_valid_table_div(table, div);
>> ????? return true;
>> @@ -208,6 +217,12 @@ static int _div_round_up(const struct 
>> clk_div_table *table,
>> ? {
>> ????? int div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
>> +??? /*
>> +???? * Check even before power of two to avoid div 1 if combination
>> +???? * happens, which applies to all the following similarities.
>> +???? */
>> +??? if (flags & CLK_DIVIDER_EVEN)
>> +??????? div = !(div % 2) ? div : (div + 1);
>> ????? if (flags & CLK_DIVIDER_POWER_OF_TWO)
>> ????????? div = __roundup_pow_of_two(div);
>> ????? if (table)
>> @@ -226,6 +241,11 @@ static int _div_round_closest(const struct 
>> clk_div_table *table,
>> ????? up = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
>> ????? down = parent_rate / rate;
>> +??? if (flags & CLK_DIVIDER_EVEN) {
>> +??????? up = !(up % 2) ? up : (up + 1);
>> +??????? down = !(down % 2) ? down : (down - 1);
>> +??? }
>> +
>> ????? if (flags & CLK_DIVIDER_POWER_OF_TWO) {
>> ????????? up = __roundup_pow_of_two(up);
>> ????????? down = __rounddown_pow_of_two(down);
>> @@ -264,6 +284,8 @@ static int _next_div(const struct clk_div_table 
>> *table, int div,
>> ? {
>> ????? div++;
>> +??? if (flags & CLK_DIVIDER_EVEN)
>> +??????? div = !(div % 2) ? div : (div + 1);
>> ????? if (flags & CLK_DIVIDER_POWER_OF_TWO)
>> ????????? return __roundup_pow_of_two(div);
>> ????? if (table)
>> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
>> index 210a890..7c59611 100644
>> --- a/include/linux/clk-provider.h
>> +++ b/include/linux/clk-provider.h
>> @@ -388,6 +388,8 @@ struct clk_div_table {
>> ?? * CLK_DIVIDER_MAX_AT_ZERO - For dividers which are like 
>> CLK_DIVIDER_ONE_BASED
>> ?? *??? except when the value read from the register is zero, the 
>> divisor is
>> ?? *??? 2^width of the field.
>> + * CLK_DIVIDER_EVEN - For the dividers which could only use even 
>> number in the
>> + *??? div field.
>> ?? */
>> ? struct clk_divider {
>> ????? struct clk_hw??? hw;
>> @@ -409,6 +411,7 @@ struct clk_divider {
>> ? #define CLK_DIVIDER_ROUND_CLOSEST??? BIT(4)
>> ? #define CLK_DIVIDER_READ_ONLY??????? BIT(5)
>> ? #define CLK_DIVIDER_MAX_AT_ZERO??????? BIT(6)
>> +#define CLK_DIVIDER_EVEN??????? BIT(7)
>> ? extern const struct clk_ops clk_divider_ops;
>> ? extern const struct clk_ops clk_divider_ro_ops;
>>
> 
> 
> 




[Index of Archives]     [LM Sensors]     [Linux Sound]     [ALSA Users]     [ALSA Devel]     [Linux Audio Users]     [Linux Media]     [Kernel]     [Gimp]     [Yosemite News]     [Linux Media]

  Powered by Linux