On 7.5.2018 03:20, James Kelly wrote:
> Replace existing CCF clock providers with new clock provider that can
> be enhanced to meet our needs.
> 
> AXI clock prepare/enable/disable/unprepare is now managed by regmap APIs.
> 
> Unregistering of clk instances now handled by devm APIs.
> 
> Drop warning that fractional ratios are not supported because it used
> undocumented register fields and it won't be needed anymore.
> 
> Signed-off-by: James Kelly <jamespeterke...@gmail.com>
> ---
>  .../clocking-wizard/clk-xlnx-clock-wizard.c        | 211 
> +++++++--------------
>  1 file changed, 71 insertions(+), 140 deletions(-)
> 
> diff --git a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c 
> b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c
> index ba9b1dc93d50..1dbeda92fb9a 100644
> --- a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c
> +++ b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c
> @@ -76,24 +76,6 @@
>  #define WZRD_CLKNAME_IN1     "clk_in1"
>  #define WZRD_FLAG_MULTIPLY   BIT(0)
>  
> -#define WZRD_CLK_CFG_REG(n)  (0x200 + 4 * (n))
> -
> -#define WZRD_CLKOUT0_FRAC_EN BIT(18)
> -#define WZRD_CLKFBOUT_FRAC_EN        BIT(26)
> -
> -#define WZRD_CLKFBOUT_MULT_SHIFT     8
> -#define WZRD_CLKFBOUT_MULT_MASK              (0xff << 
> WZRD_CLKFBOUT_MULT_SHIFT)
> -#define WZRD_DIVCLK_DIVIDE_SHIFT     0
> -#define WZRD_DIVCLK_DIVIDE_MASK              (0xff << 
> WZRD_DIVCLK_DIVIDE_SHIFT)
> -#define WZRD_CLKOUT_DIVIDE_SHIFT     0
> -#define WZRD_CLKOUT_DIVIDE_MASK              (0xff << 
> WZRD_DIVCLK_DIVIDE_SHIFT)
> -
> -enum clk_wzrd_int_clks {
> -     wzrd_clk_mul_div,
> -     wzrd_clk_mul,
> -     wzrd_clk_int_max
> -};
> -
>  enum clk_wzrd_clk {
>       WZRD_CLK_DIV,
>       WZRD_CLK_PLL,
> @@ -149,14 +131,13 @@ struct clk_wzrd_clk_data {
>               container_of(_hw, struct clk_wzrd_clk_data, hw)
>  
>  /**
> - * struct clk_wzrd:
> - * @clk_data:                Clock data
> + * struct clk_wzrd - Platform driver data for clocking wizard device
> + *
> + * @clk_data:                Clock data accessible to other devices via 
> device tree
>   * @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
> @@ -167,11 +148,9 @@ struct clk_wzrd_clk_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;
> @@ -179,7 +158,6 @@ struct clk_wzrd {
>       struct clk_wzrd_clk_data        pll_data;
>       struct clk_wzrd_clk_data        clkout_data[0];
>  };
> -
>  #define to_clk_wzrd(_nb) container_of(_nb, struct clk_wzrd, nb)
>  
>  /* maximum frequencies for input/output clocks per speed grade */
> @@ -321,7 +299,6 @@ static int __maybe_unused clk_wzrd_suspend(struct device 
> *dev)
>  {
>       struct clk_wzrd *cw = dev_get_drvdata(dev);
>  
> -     clk_disable_unprepare(cw->axi_clk);
>       cw->suspended = true;
>  
>       return 0;
> @@ -329,15 +306,8 @@ static int __maybe_unused clk_wzrd_suspend(struct device 
> *dev)
>  
>  static int __maybe_unused clk_wzrd_resume(struct device *dev)
>  {
> -     int ret;
>       struct clk_wzrd *cw = dev_get_drvdata(dev);
>  
> -     ret = clk_prepare_enable(cw->axi_clk);
> -     if (ret) {
> -             dev_err(dev, "unable to enable s_axi_aclk\n");
> -             return ret;
> -     }
> -
>       cw->suspended = false;
>  
>       return 0;
> @@ -348,17 +318,32 @@ static SIMPLE_DEV_PM_OPS(clk_wzrd_dev_pm_ops, 
> clk_wzrd_suspend,
>  
>  static int clk_wzrd_get_device_tree_data(struct device *dev)
>  {
> -     int ret;
> -     unsigned long rate;
> +     int num_outputs, ret;
>       struct clk_wzrd *cw;
> +     struct device_node *node = dev->of_node;
> +
> +     num_outputs = of_property_count_strings(node,
> +                                             "clock-output-names");
> +     if (num_outputs < 1) {
> +             dev_err(dev, "No clock output names in device tree\n");
> +             if (num_outputs < 0)
> +                     return num_outputs;
> +             else
> +                     return -EINVAL;
> +     }
> +     if (num_outputs > WZRD_NUM_OUTPUTS) {
> +             dev_warn(dev, "Too many clock output names in device tree\n");
> +             num_outputs = WZRD_NUM_OUTPUTS;
> +     }
>  
> -     cw = devm_kzalloc(dev, sizeof(*cw), GFP_KERNEL);
> +     cw = devm_kzalloc(dev, sizeof(*cw) + num_outputs *
> +                       sizeof(struct clk_wzrd_clk_data), GFP_KERNEL);
>       if (!cw)
>               return -ENOMEM;
>       dev_set_drvdata(dev, cw);
> +     cw->clk_data.clk_num = num_outputs;
>  
> -     ret = of_property_read_u32(dev->of_node, "speed-grade",
> -                                &cw->speed_grade);
> +     ret = of_property_read_u32(node, "speed-grade", &cw->speed_grade);
>       if (!ret) {
>               if (cw->speed_grade < 1 || cw->speed_grade > 3) {
>                       dev_warn(dev, "invalid speed grade '%d'\n",
> @@ -380,18 +365,12 @@ static int clk_wzrd_get_device_tree_data(struct device 
> *dev)
>                       dev_err(dev, "Clock %s not found\n", WZRD_CLKNAME_AXI);
>               return PTR_ERR(cw->axi_clk);
>       }
> -     ret = clk_prepare_enable(cw->axi_clk);
> +     ret = clk_set_max_rate(cw->axi_clk, WZRD_ACLK_MAX_FREQ);
>       if (ret) {
> -             dev_err(dev, "enabling %s failed\n", WZRD_CLKNAME_AXI);
> +             dev_err(dev, "Unable to set clock %s to valid range\n",
> +                     WZRD_CLKNAME_AXI);
>               return ret;
>       }
> -     rate = clk_get_rate(cw->axi_clk);
> -     if (rate > WZRD_ACLK_MAX_FREQ) {
> -             dev_err(dev, "%s frequency (%lu) too high\n", WZRD_CLKNAME_AXI,
> -                     rate);
> -             clk_disable_unprepare(cw->axi_clk);
> -             return -EINVAL;
> -     }
>  
>       return 0;
>  }
> @@ -399,12 +378,18 @@ static int clk_wzrd_get_device_tree_data(struct device 
> *dev)
>  static int clk_wzrd_regmap_alloc(struct device *dev)
>  {
>       struct resource *mem;
> +     void __iomem *base;
>       struct clk_wzrd *cw = dev_get_drvdata(dev);
>  
>       mem = platform_get_resource(to_platform_device(dev), IORESOURCE_MEM, 0);
> -     cw->base = devm_ioremap_resource(dev, mem);
> -     if (IS_ERR(cw->base))
> -             return PTR_ERR(cw->base);
> +     base = devm_ioremap_resource(dev, mem);
> +     if (IS_ERR(base))
> +             return PTR_ERR(base);
> +
> +     cw->regmap = devm_regmap_init_mmio_clk(dev, WZRD_CLKNAME_AXI,
> +                                            base, &clk_wzrd_regmap_config);
> +     if (IS_ERR(cw->regmap))
> +             return PTR_ERR(cw->regmap);
>  
>       return 0;
>  }
> @@ -412,115 +397,68 @@ static int clk_wzrd_regmap_alloc(struct device *dev)
>  static int clk_wzrd_register_ccf(struct device *dev)
>  {
>       int i, ret;
> -     u32 reg;
> -     const char *clk_name;
> +     const char *clk_div_name;
> +     const char *clk_pll_name;
> +
>       struct clk_wzrd *cw = dev_get_drvdata(dev);
>  
> -     /* we don't support fractional div/mul yet */
> -     reg = readl(cw->base + WZRD_CLK_CFG_REG(0)) &
> -                 WZRD_CLKFBOUT_FRAC_EN;
> -     reg |= readl(cw->base + WZRD_CLK_CFG_REG(2)) &
> -                  WZRD_CLKOUT0_FRAC_EN;
> -     if (reg)
> -             dev_warn(dev, "fractional div/mul not supported\n");
> -
> -     /* register div */
> -     reg = (readl(cw->base + WZRD_CLK_CFG_REG(0)) &
> -            WZRD_DIVCLK_DIVIDE_MASK) >> WZRD_DIVCLK_DIVIDE_SHIFT;
> -     clk_name = kasprintf(GFP_KERNEL, "%s_mul_div", dev_name(dev));
> -     if (!clk_name) {
> -             ret = -ENOMEM;
> -             goto err_disable_clk;
> -     }
> -     cw->clks_internal[wzrd_clk_mul_div] = clk_register_fixed_factor(
> -                     dev, clk_name,
> -                     __clk_get_name(cw->clk_in1),
> -                     0, 1, reg);
> -     kfree(clk_name);
> -     if (IS_ERR(cw->clks_internal[wzrd_clk_mul_div])) {
> -             dev_err(dev, "unable to register divider clock\n");
> -             ret = PTR_ERR(cw->clks_internal[wzrd_clk_mul_div]);
> -             goto err_disable_clk;
> -     }
> +     clk_div_name = kasprintf(GFP_KERNEL, "%s_div", dev_name(dev));
> +     if (!clk_div_name)
> +             return -ENOMEM;
> +     ret = clk_wzrd_register_clk(dev, clk_div_name, WZRD_CLK_DIV, 0, 0);
> +     if (ret)
> +             goto err_free_div_name;
>  
> -     /* register multiplier */
> -     reg = (readl(cw->base + WZRD_CLK_CFG_REG(0)) &
> -            WZRD_CLKFBOUT_MULT_MASK) >> WZRD_CLKFBOUT_MULT_SHIFT;
> -     clk_name = kasprintf(GFP_KERNEL, "%s_mul", dev_name(dev));
> -     if (!clk_name) {
> +     clk_pll_name = kasprintf(GFP_KERNEL, "%s_pll", dev_name(dev));
> +     if (!clk_pll_name) {
>               ret = -ENOMEM;
> -             goto err_rm_int_clk;
> -     }
> -     cw->clks_internal[wzrd_clk_mul] = clk_register_fixed_factor(
> -                     dev, clk_name,
> -                     __clk_get_name(cw->clks_internal[wzrd_clk_mul_div]),
> -                     0, reg, 1);
> -     if (IS_ERR(cw->clks_internal[wzrd_clk_mul])) {
> -             dev_err(dev, "unable to register fixed-factor clock\n");
> -             ret = PTR_ERR(cw->clks_internal[wzrd_clk_mul]);
> -             goto err_rm_int_clk;
> +             goto err_free_div_name;
>       }
> +     ret = clk_wzrd_register_clk(dev, clk_pll_name, WZRD_CLK_PLL, 0, 0);
> +     if (ret)
> +             goto err_free_pll_name;
>  
> -     /* register div per output */
> -     for (i = WZRD_NUM_OUTPUTS - 1; i >= 0 ; i--) {
> +     for (i = cw->clk_data.clk_num - 1; i >= 0 ; i--) {
>               const char *clkout_name;
>  
>               if (of_property_read_string_index(dev->of_node,
>                                                 "clock-output-names", i,
>                                                 &clkout_name)) {
> -                     dev_err(dev,
> -                             "clock output name not specified\n");
> +                     dev_err(dev, "clock output %d name not specified\n", i);
>                       ret = -EINVAL;
> -                     goto err_rm_int_clks;
> +                     goto err_free_pll_name;
>               }
> -             reg = readl(cw->base + WZRD_CLK_CFG_REG(2) + i * 12);
> -             reg &= WZRD_CLKOUT_DIVIDE_MASK;
> -             reg >>= WZRD_CLKOUT_DIVIDE_SHIFT;
> -             cw->clkout[i] = clk_register_fixed_factor(dev, clkout_name,
> -                                                       clk_name, 0, 1, reg);
> -             if (IS_ERR(cw->clkout[i])) {
> -                     int j;
> -
> -                     for (j = i + 1; j < WZRD_NUM_OUTPUTS; j++)
> -                             clk_unregister(cw->clkout[j]);
> -                     dev_err(dev,
> -                             "unable to register divider clock\n");
> -                     ret = PTR_ERR(cw->clkout[i]);
> -                     goto err_rm_int_clks;
> -             }
> -     }
>  
> -     kfree(clk_name);
> +             ret = clk_wzrd_register_clk(dev, clkout_name, WZRD_CLK_OUT,
> +                                         i, 0);
> +             if (ret)
> +                     goto err_free_pll_name;
> +
> +             cw->clkout[i] = cw->clkout_data[i].hw.clk;
> +     }
>  
>       cw->clk_data.clks = cw->clkout;
> -     cw->clk_data.clk_num = ARRAY_SIZE(cw->clkout);
>       of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
>                           &cw->clk_data);
>  
>       if (cw->speed_grade) {
>               cw->nb.notifier_call = clk_wzrd_clk_notifier;
>  
> -             ret = clk_notifier_register(cw->clk_in1,
> -                                         &cw->nb);
> -             if (ret)
> -                     dev_warn(dev,
> -                              "unable to register clock notifier\n");
> +             ret = clk_notifier_register(cw->clk_in1, &cw->nb);
> +                     if (ret)
> +                             dev_warn(dev, "Unable to register input clock 
> notifier\n");
>  
>               ret = clk_notifier_register(cw->axi_clk, &cw->nb);
> -             if (ret)
> -                     dev_warn(dev,
> -                              "unable to register clock notifier\n");
> +                     if (ret)
> +                             dev_warn(dev, "Unable to register AXI clock 
> notifier\n");
>       }
>  
> -     return 0;
> +     ret = 0;
>  
> -err_rm_int_clks:
> -     clk_unregister(cw->clks_internal[1]);
> -err_rm_int_clk:
> -     kfree(clk_name);
> -     clk_unregister(cw->clks_internal[0]);
> -err_disable_clk:
> -     clk_disable_unprepare(cw->axi_clk);
> +err_free_pll_name:
> +     kfree(clk_pll_name);
> +err_free_div_name:
> +     kfree(clk_div_name);
>  
>       return ret;
>  }
> @@ -547,23 +485,15 @@ static int clk_wzrd_probe(struct platform_device *pdev)
>  
>  static int clk_wzrd_remove(struct platform_device *pdev)
>  {
> -     int i;
>       struct clk_wzrd *cw = platform_get_drvdata(pdev);
>  
>       of_clk_del_provider(pdev->dev.of_node);
>  
> -     for (i = 0; i < WZRD_NUM_OUTPUTS; i++)
> -             clk_unregister(cw->clkout[i]);
> -     for (i = 0; i < wzrd_clk_int_max; i++)
> -             clk_unregister(cw->clks_internal[i]);
> -
>       if (cw->speed_grade) {
>               clk_notifier_unregister(cw->axi_clk, &cw->nb);
>               clk_notifier_unregister(cw->clk_in1, &cw->nb);
>       }
>  
> -     clk_disable_unprepare(cw->axi_clk);
> -
>       return 0;
>  }
>  
> @@ -577,6 +507,7 @@ static struct platform_driver clk_wzrd_driver = {
>       .driver = {
>               .name = "clk-wizard",
>               .of_match_table = clk_wzrd_ids,
> +             .owner = THIS_MODULE,

This is not needed and coccinelle check this.
drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c:510:3-8: No need
to set .owner here. The core will do it.


Also there is one more warning.
drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c:391:1-3:
WARNING: PTR_ERR_OR_ZERO can be used

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

Reply via email to