On 7.5.2018 03:20, James Kelly wrote:
> The CCF clock providers that are currently used by the driver are not
> capable of supporting the Clocking Wizard IP register interface for
> fractional ratios, nor are they able to enforce constraints require to
> ensure the PLL will always lock.
> 
> None of the common CCF clock providers seem to be a good fit so we
> implement a new CCF clock provider within the driver that can be expanded
> upon in subsequent patches.  The initial implementation supports multiply
> or divide by fixed integer ratios.
> 
> The CCF clock provider uses:
> - devm kernel APIs for clock registration to simplify error recovery and
>   module unloading.
> - regmap kernel APIs for memory mapped I/O. Regmap is also able to manage
>   prepare/enable/disable/unprepare of the AXI clock for us.
> 
> Note that use of the new CCF clock provider is deferred to a subsequent
> patch.
> 
> Signed-off-by: James Kelly <jamespeterke...@gmail.com>
> ---
>  .../clocking-wizard/clk-xlnx-clock-wizard.c        | 164 
> +++++++++++++++++++++
>  1 file changed, 164 insertions(+)
> 
> diff --git a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c 
> b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c
> index 3b66ac3b5ed0..ba9b1dc93d50 100644
> --- a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c
> +++ b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c
> @@ -3,6 +3,7 @@
>   * Xilinx 'Clocking Wizard' driver
>   *
>   *  Copyright (C) 2013 - 2014 Xilinx
> + *  Copyright (C) 2018 James Kelly
>   *
>   *  Sören Brinkmann <soren.brinkm...@xilinx.com>
>   *
> @@ -67,11 +68,13 @@
>  #include <linux/of.h>
>  #include <linux/module.h>
>  #include <linux/err.h>
> +#include <linux/regmap.h>
>  
>  #define WZRD_NUM_OUTPUTS     7
>  #define WZRD_ACLK_MAX_FREQ   250000000UL
>  #define WZRD_CLKNAME_AXI     "s_axi_aclk"
>  #define WZRD_CLKNAME_IN1     "clk_in1"
> +#define WZRD_FLAG_MULTIPLY   BIT(0)
>  
>  #define WZRD_CLK_CFG_REG(n)  (0x200 + 4 * (n))
>  
> @@ -91,28 +94,90 @@ enum clk_wzrd_int_clks {
>       wzrd_clk_int_max
>  };
>  
> +enum clk_wzrd_clk {
> +     WZRD_CLK_DIV,
> +     WZRD_CLK_PLL,
> +     WZRD_CLK_OUT,
> +     WZRD_CLK_COUNT
> +};
> +
> +/*
> + * Register map extracted from Xilinx document listed below.
> + *
> + * PG065 Clocking Wizard v6.0 LogiCORE IP Product Guide
> + */
> +static const struct regmap_config clk_wzrd_regmap_config = {
> +     .reg_bits = 32,
> +     .reg_stride = 4,
> +     .val_bits = 32
> +};
> +
> +static const struct reg_field clk_wzrd_status_locked = REG_FIELD(0x004,  0,  
> 0);
> +static const struct reg_field clk_wzrd_divclk_divide = REG_FIELD(0x200,  0,  
> 7);
> +static const struct reg_field clk_wzrd_clkfbout_mult = REG_FIELD(0x200,  8, 
> 15);
> +static const struct reg_field clk_wzrd_clkfbout_frac = REG_FIELD(0x200, 16, 
> 25);
> +static const struct reg_field clk_wzrd_clkout_divide[WZRD_NUM_OUTPUTS] = {
> +     REG_FIELD(0x208, 0, 7),
> +     REG_FIELD(0x214, 0, 7),
> +     REG_FIELD(0x220, 0, 7),
> +     REG_FIELD(0x22C, 0, 7),
> +     REG_FIELD(0x238, 0, 7),
> +     REG_FIELD(0x244, 0, 7),
> +     REG_FIELD(0x250, 0, 7)
> +};
> +
> +static const struct reg_field clk_wzrd_clkout0_frac = REG_FIELD(0x208, 8, 
> 17);
> +static const struct reg_field clk_wzrd_reconfig     = REG_FIELD(0x25C, 0,  
> 1);
> +
> +/**
> + * struct clk_wzrd_clk_data - Clocking Wizard component clock provider data
> + *
> + * @hw:                      handle between common and hardware-specific 
> interfaces
> + * @flags:           hardware specific flags
> + * @int_field:               pointer to regmap field for integer part
> + *
> + * Flags:
> + * WZRD_FLAG_MULTIPLY        Clock is a multiplier rather than a divider
> + */
> +struct clk_wzrd_clk_data {
> +     struct clk_hw                   hw;
> +     unsigned long                   flags;
> +     struct regmap_field             *int_field;
> +};
> +
> +#define to_clk_wzrd_clk_data(_hw) \
> +             container_of(_hw, struct clk_wzrd_clk_data, hw)
> +
>  /**
>   * struct clk_wzrd:
>   * @clk_data:                Clock data
>   * @nb:                      Notifier block
>   * @base:            Memory base
> + * @regmap:          Register map for hardware
>   * @clk_in1:         Handle to input clock 'clk_in1'
>   * @axi_clk:         Handle to input clock 's_axi_aclk'
>   * @clks_internal:   Internal clocks
>   * @clkout:          Output clocks
>   * @speed_grade:     Speed grade of the device
>   * @suspended:               Flag indicating power state of the device
> + * @div:             Divider internal clock provider data
> + * @pll:             Phase locked loop internal clock provider data
> + * @clkout_data:     Array of output clock provider data
>   */
>  struct clk_wzrd {
>       struct clk_onecell_data         clk_data;
>       struct notifier_block           nb;
>       void __iomem                    *base;
> +     struct regmap                   *regmap;
>       struct clk                      *clk_in1;
>       struct clk                      *axi_clk;
>       struct clk                      *clks_internal[wzrd_clk_int_max];
>       struct clk                      *clkout[WZRD_NUM_OUTPUTS];
>       unsigned int                    speed_grade;
>       bool                            suspended;
> +     struct clk_wzrd_clk_data        div_data;
> +     struct clk_wzrd_clk_data        pll_data;

Names don't fit with what it is added to kernel-doc above.

drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c:152: info:
Scanning doc for struct
drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c:181: warning:
Function parameter or member 'div_data' not described in 'clk_wzrd'
drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c:181: warning:
Function parameter or member 'pll_data' not described in 'clk_wzrd'

Anyway. Shubhrajyoti is going to test this series that's why please give
us some time for it.

Thanks,
Michal

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to