[PATCH 06/10] clk: sunxi: mod0 support
Emilio López
emilio at elopez.com.ar
Mon Sep 30 19:37:46 EDT 2013
Hi Maxime,
El 30/09/13 14:35, Maxime Ripard escribió:
> Hi Emilio,
>
> Overall, it looks fine, I just have a small question.
>
> On Sun, Sep 29, 2013 at 12:49:35AM -0300, Emilio López wrote:
>> This commit implements support for the "module 0" type of clocks, as
>> used by MMC, IR, NAND, SATA and other components.
>>
>> Signed-off-by: Emilio López <emilio at elopez.com.ar>
>> ---
>> Documentation/devicetree/bindings/clock/sunxi.txt | 1 +
>> drivers/clk/sunxi/clk-sunxi.c | 57 +++++++++++++++++++++++
>> 2 files changed, 58 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
>> index 773f3ae..ff3f61c 100644
>> --- a/Documentation/devicetree/bindings/clock/sunxi.txt
>> +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
>> @@ -35,6 +35,7 @@ Required properties:
>> "allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20
>> "allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31
>> "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
>> + "allwinner,sun4i-mod0-clk" - for the module 0 family of clocks
>>
>> Required properties for all clocks:
>> - reg : shall be the control register address for the clock.
>> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
>> index b1210f3..163a3d8 100644
>> --- a/drivers/clk/sunxi/clk-sunxi.c
>> +++ b/drivers/clk/sunxi/clk-sunxi.c
>> @@ -287,6 +287,47 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate,
>>
>>
>> /**
>> + * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
>> + * MMC rate is calculated as follows
>> + * rate = (parent_rate >> p) / (m + 1);
>> + */
>> +
>> +static void sun4i_get_mod0_factors(u32 *freq, u32 parent_rate,
>> + u8 *n, u8 *k, u8 *m, u8 *p)
>> +{
>> + u8 div, calcm, calcp;
>> +
>> + /* These clocks can only divide, so we will never be able to achieve
>> + * frequencies higher than the parent frequency */
>> + if (*freq > parent_rate)
>> + *freq = parent_rate;
>> +
>> + div = parent_rate / *freq;
>> +
>> + if (div < 16)
>> + calcp = 0;
>> + else if (div / 2 < 16)
>> + calcp = 1;
>> + else if (div / 4 < 16)
>> + calcp = 2;
>> + else
>> + calcp = 3;
>> +
>> + calcm = DIV_ROUND_UP(div, 1 << calcp);
>> +
>> + *freq = (parent_rate >> calcp) / calcm;
>> +
>> + /* we were called to round the frequency, we can now return */
>> + if (n == NULL)
>> + return;
>> +
>> + *m = calcm - 1;
>> + *p = calcp;
>> +}
>> +
>> +
>> +
>> +/**
>> * sunxi_factors_clk_setup() - Setup function for factor clocks
>> */
>>
>> @@ -333,6 +374,14 @@ static struct clk_factors_config sun4i_apb1_config = {
>> .pwidth = 2,
>> };
>>
>> +/* user manual says "n" but it's really "p" */
>> +static struct clk_factors_config sun4i_mod0_config = {
>> + .mshift = 0,
>> + .mwidth = 4,
>> + .pshift = 16,
>> + .pwidth = 2,
>> +};
>> +
>> static const struct factors_data sun4i_pll1_data __initconst = {
>> .enable = 31,
>> .table = &sun4i_pll1_config,
>> @@ -356,6 +405,13 @@ static const struct factors_data sun4i_apb1_data __initconst = {
>> .getter = sun4i_get_apb1_factors,
>> };
>>
>> +static const struct factors_data sun4i_mod0_data __initconst = {
>> + .enable = 31,
>> + .mux = 24,
>> + .table = &sun4i_mod0_config,
>> + .getter = sun4i_get_mod0_factors,
>> +};
>
> How are the parents handled here for the mux part? Do you expect the
> different parents in a precise order in the device tree, so that you
> have a direct mapping to the value to put in the muxing registers, or do
> you have a smarter way to do it?
Indeed, the parents must be indicated on the DT using the same order as
on the register. In other words, it works the same as all the other
muxes we have implemented so far. The clock corresponding to bits 00
goes first, then the one corresponding to 01, etc.
Cheers,
Emilio
More information about the linux-arm-kernel
mailing list