All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jacky Huang <ychuang570808@gmail.com>
To: Stephen Boyd <sboyd@kernel.org>,
	gregkh@linuxfoundation.org, jirislaby@kernel.org,
	krzysztof.kozlowski+dt@linaro.org, lee@kernel.org,
	mturquette@baylibre.com, p.zabel@pengutronix.de,
	robh+dt@kernel.org
Cc: devicetree@vger.kernel.org, linux-clk@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org,
	schung@nuvoton.com, Jacky Huang <ychuang3@nuvoton.com>
Subject: Re: [PATCH 12/15] clk: nuvoton: Add clock driver for ma35d1 clock controller
Date: Fri, 17 Mar 2023 11:07:34 +0800	[thread overview]
Message-ID: <493c9c33-5ad9-e3f3-501c-d9f27b4d54d5@gmail.com> (raw)
In-Reply-To: <33aa6111d09fa7a75d0e603c3fd3ac11.sboyd@kernel.org>

Dear Stephen,

Thanks for your review.


On 2023/3/16 上午 06:30, Stephen Boyd wrote:
> Quoting Jacky Huang (2023-03-15 00:28:59)
>> diff --git a/drivers/clk/nuvoton/clk-ma35d1-divider.c b/drivers/clk/nuvoton/clk-ma35d1-divider.c
>> new file mode 100644
>> index 000000000000..5f4791531e47
>> --- /dev/null
>> +++ b/drivers/clk/nuvoton/clk-ma35d1-divider.c
>> @@ -0,0 +1,144 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (C) 2023 Nuvoton Technology Corp.
>> + * Author: Chi-Fang Li <cfli0@nuvoton.com>
>> + */
>> +
>> +#include <linux/clk-provider.h>
>> +#include <linux/slab.h>
>> +#include <linux/io.h>
>> +#include <linux/err.h>
>> +#include <linux/spinlock.h>
>> +
>> +#include "clk-ma35d1.h"
>> +
>> +#define div_mask(width)                ((1 << (width)) - 1)
> This is clk_div_mask()

OK, I will rename div_mask() as clk_div_mask().

>
>> +
>> +struct ma35d1_adc_clk_divider {
>> +       struct clk_hw hw;
>> +       void __iomem *reg;
>> +       u8 shift;
>> +       u8 width;
>> +       u32 mask;
>> +       const struct clk_div_table *table;
>> +       spinlock_t *lock;
>> +};
>> +
>> +#define to_ma35d1_adc_clk_divider(_hw) \
>> +       container_of(_hw, struct ma35d1_adc_clk_divider, hw)
>> +
>> +static unsigned long ma35d1_clkdiv_recalc_rate(struct clk_hw *hw,
>> +                                              unsigned long parent_rate)
>> +{
>> +       unsigned int val;
>> +       struct ma35d1_adc_clk_divider *dclk = to_ma35d1_adc_clk_divider(hw);
>> +
>> +       val = readl_relaxed(dclk->reg) >> dclk->shift;
>> +       val &= div_mask(dclk->width);
>> +       val += 1;
>> +       return divider_recalc_rate(hw, parent_rate, val, dclk->table,
>> +                                  CLK_DIVIDER_ROUND_CLOSEST, dclk->width);
>> +}
>> +
>> +static long ma35d1_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
>> +                                    unsigned long *prate)
>> +{
>> +       struct ma35d1_adc_clk_divider *dclk = to_ma35d1_adc_clk_divider(hw);
>> +
>> +       return divider_round_rate(hw, rate, prate, dclk->table,
>> +                                 dclk->width, CLK_DIVIDER_ROUND_CLOSEST);
>> +}
>> +
>> +static int ma35d1_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
>> +                                 unsigned long parent_rate)
>> +{
>> +       int value;
>> +       unsigned long flags = 0;
>> +       u32 data;
>> +       struct ma35d1_adc_clk_divider *dclk = to_ma35d1_adc_clk_divider(hw);
>> +
>> +       value = divider_get_val(rate, parent_rate, dclk->table,
>> +                               dclk->width, CLK_DIVIDER_ROUND_CLOSEST);
>> +
>> +       if (dclk->lock)
>> +               spin_lock_irqsave(dclk->lock, flags);
>> +
>> +       data = readl_relaxed(dclk->reg);
>> +       data &= ~(div_mask(dclk->width) << dclk->shift);
>> +       data |= (value - 1) << dclk->shift;
>> +       data |= dclk->mask;
>> +
>> +       writel_relaxed(data, dclk->reg);
>> +
>> +       if (dclk->lock)
>> +               spin_unlock_irqrestore(dclk->lock, flags);
>> +
>> +       return 0;
>> +}
>> +
>> +static const struct clk_ops ma35d1_adc_clkdiv_ops = {
>> +       .recalc_rate = ma35d1_clkdiv_recalc_rate,
>> +       .round_rate = ma35d1_clkdiv_round_rate,
>> +       .set_rate = ma35d1_clkdiv_set_rate,
>> +};
>> +
>> +struct clk_hw *ma35d1_reg_adc_clkdiv(struct device *dev, const char *name,
>> +                                    const char *parent_name,
>> +                                    unsigned long flags, void __iomem *reg,
>> +                                    u8 shift, u8 width, u32 mask_bit)
>> +{
>> +       struct ma35d1_adc_clk_divider *div;
>> +       struct clk_init_data init;
>> +       struct clk_div_table *table;
>> +       u32 max_div, min_div;
>> +       struct clk_hw *hw;
>> +       int ret;
>> +       int i;
>> +
>> +       /* allocate the divider */
> Please remove useless comment.
>
>> +       div = kzalloc(sizeof(*div), GFP_KERNEL);
>> +       if (!div)
>> +               return ERR_PTR(-ENOMEM);
>> +
>> +       /* Init the divider table */
> Please remove useless comment.

I will remove all useless comments.

>
>> +       max_div = div_mask(width) + 1;
>> +       min_div = 1;
>> +
>> +       table = kcalloc(max_div + 1, sizeof(*table), GFP_KERNEL);
> Use devm_ allocations please.

OK, I will use devm_kzallloc() instead.

>> +       if (!table) {
>> +               kfree(div);
>> +               return ERR_PTR(-ENOMEM);
>> +       }
>> +
>> +       for (i = 0; i < max_div; i++) {
>> +               table[i].val = (min_div + i);
>> +               table[i].div = 2 * table[i].val;
>> +       }
>> +       table[max_div].val = 0;
>> +       table[max_div].div = 0;
>> +
>> +       init.name = name;
>> +       init.ops = &ma35d1_adc_clkdiv_ops;
>> +       init.flags |= flags;
>> +       init.parent_names = parent_name ? &parent_name : NULL;
>> +       init.num_parents = parent_name ? 1 : 0;
>> +
>> +       /* struct ma35d1_adc_clk_divider assignments */
> Please remove useless comment.
>
>> +       div->reg = reg;
>> +       div->shift = shift;
>> +       div->width = width;
>> +       div->mask = mask_bit ? BIT(mask_bit) : 0;
>> +       div->lock = &ma35d1_lock;
>> +       div->hw.init = &init;
>> +       div->table = table;
>> +
>> +       /* Register the clock */
> Please remove useless comment.
>
>> +       hw = &div->hw;
>> +       ret = clk_hw_register(NULL, hw);
> Use devm_clk_hw_register()

I will use devm_clk_hw_registers() instead.

>
>> +       if (ret) {
>> +               kfree(table);
>> +               kfree(div);
>> +               return ERR_PTR(ret);
>> +       }
>> +       return hw;
>> +}
>> diff --git a/drivers/clk/nuvoton/clk-ma35d1-pll.c b/drivers/clk/nuvoton/clk-ma35d1-pll.c
>> new file mode 100644
>> index 000000000000..79e724b148fa
>> --- /dev/null
>> +++ b/drivers/clk/nuvoton/clk-ma35d1-pll.c
>> @@ -0,0 +1,534 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (C) 2023 Nuvoton Technology Corp.
>> + * Author: Chi-Fang Li <cfli0@nuvoton.com>
>> + */
>> +
>> +#include <linux/clk.h>
> Do you need to include this header?

I remove it and compile passed. It is not used here.
I will remove it in the next version.

>
>> +#include <linux/clk-provider.h>
>> +#include <linux/io.h>
>> +#include <linux/slab.h>
>> +#include <linux/bitfield.h>
>> +
>> +#include "clk-ma35d1.h"
>> +
>> +#define to_ma35d1_clk_pll(clk) \
>> +       (container_of(clk, struct ma35d1_clk_pll, clk))
>> +
>> +#define PLL0CTL0_FBDIV_MSK     GENMASK(7, 0)
>> +#define PLL0CTL0_INDIV_MSK     GENMASK(11, 8)
>> +#define PLL0CTL0_OUTDIV_MSK    GENMASK(13, 12)
>> +#define PLL0CTL0_PD_MSK                BIT(16)
>> +#define PLL0CTL0_BP_MSK                BIT(17)
>> +#define PLLXCTL0_FBDIV_MSK     GENMASK(10, 0)
>> +#define PLLXCTL0_INDIV_MSK     GENMASK(17, 12)
>> +#define PLLXCTL0_MODE_MSK      GENMASK(19, 18)
>> +#define PLLXCTL0_SSRATE_MSK    GENMASK(30, 20)
>> +#define PLLXCTL1_PD_MSK                BIT(0)
>> +#define PLLXCTL1_BP_MSK                BIT(1)
>> +#define PLLXCTL1_OUTDIV_MSK    GENMASK(6, 4)
>> +#define PLLXCTL1_FRAC_MSK      GENMASK(31, 8)
>> +#define PLLXCTL2_SLOPE_MSK     GENMASK(23, 0)
>> +
>> +struct ma35d1_clk_pll {
>> +       struct clk_hw hw;
>> +       u8 type;
>> +       u8 mode;
>> +       unsigned long rate;
>> +       void __iomem *ctl0_base;
>> +       void __iomem *ctl1_base;
>> +       void __iomem *ctl2_base;
>> +       struct regmap *regmap;
>> +};
>> +
>> +struct vsipll_freq_conf_reg_tbl {
>> +       unsigned long freq;
>> +       u8 mode;
>> +       u32 ctl0_reg;
>> +       u32 ctl1_reg;
>> +       u32 ctl2_reg;
>> +};
>> +
>> +static const struct vsipll_freq_conf_reg_tbl ma35d1pll_freq[] = {
>> +       { 1000000000, VSIPLL_INTEGER_MODE, 0x307d, 0x10, 0 },
>> +       { 884736000, VSIPLL_FRACTIONAL_MODE, 0x41024, 0xdd2f1b11, 0 },
>> +       { 533000000, VSIPLL_SS_MODE, 0x12b8102c, 0x6aaaab20, 0x12317 },
>> +       { }
>> +};
>> +
>> +static void CLK_UnLockReg(struct ma35d1_clk_pll *pll)
> Please don't use a mix of upper and lower case function names.
> Everything should be lower case. Maybe the name should be
>
> 	ma35d1_clk_pll_unlock_reg()

Sure, we will review all the macros and API to have all lower case naming.

>> +{
>> +       int ret;
>> +
>> +       /* Unlock PLL registers */
>> +       do {
>> +               regmap_write(pll->regmap, REG_SYS_RLKTZNS, 0x59);
>> +               regmap_write(pll->regmap, REG_SYS_RLKTZNS, 0x16);
>> +               regmap_write(pll->regmap, REG_SYS_RLKTZNS, 0x88);
>> +               regmap_read(pll->regmap, REG_SYS_RLKTZNS, &ret);
>> +       } while (ret == 0);
>> +}
>> +
>> +static void CLK_LockReg(struct ma35d1_clk_pll *pll)
>> +{
> 	ma35d1_clk_pll_lock_reg()
>
>> +       /* Lock PLL registers */
> Remove these worthless comments.
>
>> +       regmap_write(pll->regmap, REG_SYS_RLKTZNS, 0x0);
>> +}
>> +
>> +/* SMIC PLL for CAPLL */
>> +unsigned long CLK_GetPLLFreq_SMICPLL(struct ma35d1_clk_pll *pll,
>> +                                    unsigned long PllSrcClk)
>> +{
>> +       u32 u32M, u32N, u32P, u32OutDiv;
> Variable names should not have the type in them. 'm', 'n', 'p', 'div'
> should suffice.

OK, we review all variables naming and modify them to linux coding style.

>> +       u32 val;
>> +       unsigned long u64PllClk;
>> +       u32 clk_div_table[] = { 1, 2, 4, 8};
>> +
>> +       val = __raw_readl(pll->ctl0_base);
> Why do you need to use __raw_readl()? Just use readl() here.

OK, I will modify all __raw_real() to raw_read().

>> +
>> +       u32N = FIELD_GET(PLL0CTL0_FBDIV_MSK, val);
>> +       u32M = FIELD_GET(PLL0CTL0_INDIV_MSK, val);
>> +       u32P = FIELD_GET(PLL0CTL0_OUTDIV_MSK, val);
>> +       u32OutDiv = clk_div_table[u32P];
>> +
>> +       if (val & PLL0CTL0_BP_MSK) {
>> +               u64PllClk = PllSrcClk;
>> +       } else {
>> +               u64PllClk = PllSrcClk * u32N;
>> +               do_div(u64PllClk, u32M * u32OutDiv);
>> +       }
> Add a newline here.
>
>> +       return u64PllClk;
>> +}
>> +
>> +/* VSI-PLL: INTEGER_MODE */
> I have no idea what this means.

The PLL has 3 operation modes, and integer mode in one of them.
We will add descriptions about PLL to comments.

>
>> +unsigned long CLK_CalPLLFreq_Mode0(unsigned long PllSrcClk,
>> +                                  unsigned long u64PllFreq, u32 *u32Reg)
> Again, don't put types into the variable name.
>
>> +{
>> +       u32 u32TmpM, u32TmpN, u32TmpP;
>> +       u32 u32RngMinN, u32RngMinM, u32RngMinP;
>> +       u32 u32RngMaxN, u32RngMaxM, u32RngMaxP;
>> +       u32 u32Tmp, u32Min, u32MinN, u32MinM, u32MinP;
>> +       unsigned long u64PllClk;
>> +       unsigned long u64Con1, u64Con2, u64Con3;
> My eyes! Seriously, kernel style is not this way. Did checkpatch.pl pass
> on this?

We will completely rewrite this function to make it readable.

>> +
>> +       u64PllClk = 0;
>> +       u32Min = (u32) -1;
>> +
>> +       if (!((u64PllFreq >= VSIPLL_FCLKO_MIN_FREQ) &&
>> +           (u64PllFreq <= VSIPLL_FCLKO_MAX_FREQ))) {
>> +               u32Reg[0] = ma35d1pll_freq[0].ctl0_reg;
>> +               u32Reg[1] = ma35d1pll_freq[0].ctl1_reg;
>> +               u64PllClk = ma35d1pll_freq[0].freq;
>> +               return u64PllClk;
>> +       }
>> +
>> +       u32RngMinM = 1UL;
>> +       u32RngMaxM = 63UL;
>> +       u32RngMinM = ((PllSrcClk / VSIPLL_FREFDIVM_MAX_FREQ) > 1) ?
>> +                    (PllSrcClk / VSIPLL_FREFDIVM_MAX_FREQ) : 1;
>> +       u32RngMaxM = ((PllSrcClk / VSIPLL_FREFDIVM_MIN_FREQ0) < u32RngMaxM) ?
>> +                    (PllSrcClk / VSIPLL_FREFDIVM_MIN_FREQ0) : u32RngMaxM;
>> +
>> +       for (u32TmpM = u32RngMinM; u32TmpM < (u32RngMaxM + 1); u32TmpM++) {
>> +               u64Con1 = PllSrcClk / u32TmpM;
>> +               u32RngMinN = 16UL;
>> +               u32RngMaxN = 2047UL;
>> +               u32RngMinN = ((VSIPLL_FCLK_MIN_FREQ / u64Con1) > u32RngMinN) ?
>> +                            (VSIPLL_FCLK_MIN_FREQ / u64Con1) : u32RngMinN;
>> +               u32RngMaxN = ((VSIPLL_FCLK_MAX_FREQ / u64Con1) < u32RngMaxN) ?
>> +                            (VSIPLL_FCLK_MAX_FREQ / u64Con1) : u32RngMaxN;
> Is this clamp()?
>
>> +
>> +               for (u32TmpN = u32RngMinN; u32TmpN < (u32RngMaxN + 1);
>> +                    u32TmpN++) {
>> +                       u64Con2 = u64Con1 * u32TmpN;
>> +                       u32RngMinP = 1UL;
>> +                       u32RngMaxP = 7UL;
>> +                       u32RngMinP = ((u64Con2 / VSIPLL_FCLKO_MAX_FREQ) > 1) ?
>> +                                     (u64Con2 / VSIPLL_FCLKO_MAX_FREQ) : 1;
> Is this clamp()?
>
>> +                       u32RngMaxP = ((u64Con2 / VSIPLL_FCLKO_MIN_FREQ) <
>> +                                     u32RngMaxP) ?
>> +                                     (u64Con2 / VSIPLL_FCLKO_MIN_FREQ) :
>> +                                     u32RngMaxP;
>> +                       for (u32TmpP = u32RngMinP; u32TmpP < (u32RngMaxP + 1);
>> +                            u32TmpP++) {
>> +                               u64Con3 = u64Con2 / u32TmpP;
>> +                               if (u64Con3 > u64PllFreq)
>> +                                       u32Tmp = u64Con3 - u64PllFreq;
>> +                               else
>> +                                       u32Tmp = u64PllFreq - u64Con3;
>> +
>> +                               if (u32Tmp < u32Min) {
>> +                                       u32Min = u32Tmp;
>> +                                       u32MinM = u32TmpM;
>> +                                       u32MinN = u32TmpN;
>> +                                       u32MinP = u32TmpP;
>> +
>> +                                       if (u32Min == 0UL) {
>> +                                               u32Reg[0] = (u32MinM << 12) |
>> +                                                           (u32MinN);
>> +                                               u32Reg[1] = (u32MinP << 4);
>> +                                               return ((PllSrcClk * u32MinN) /
>> +                                                       (u32MinP * u32MinM));
>> +                                       }
>> +                               }
>> +                       }
>> +               }
>> +       }
> It's too hard to read this code.

We will completely rewrite this function to make it readable.
And add formula descriptions to comments.

>> +
>> +       u32Reg[0] = (u32MinM << 12) | (u32MinN);
> FIELD_PREP?
>
>> +       u32Reg[1] = (u32MinP << 4);
> ditto?
>
>> +       u64PllClk = (PllSrcClk * u32MinN) / (u32MinP * u32MinM);
>> +       return u64PllClk;
>> +}
>> +
>> +/* VSI-PLL: FRACTIONAL_MODE */
>> +unsigned long CLK_CalPLLFreq_Mode1(unsigned long PllSrcClk,
>> +                                  unsigned long u64PllFreq, u32 *u32Reg)
>> +{
>> +       unsigned long u64X, u64N, u64M, u64P, u64tmp;
>> +       unsigned long u64PllClk, u64FCLKO;
>> +       u32 u32FRAC;
>> +
>> +       if (u64PllFreq > VSIPLL_FCLKO_MAX_FREQ) {
>> +               u32Reg[0] = ma35d1pll_freq[1].ctl0_reg;
>> +               u32Reg[1] = ma35d1pll_freq[1].ctl1_reg;
>> +               u64PllClk = ma35d1pll_freq[1].freq;
>> +               return u64PllClk;
>> +       }
>> +
>> +       if (u64PllFreq > (VSIPLL_FCLKO_MIN_FREQ/(100-1))) {
> Use a local variable for the right hand side of the comparison.

We will completely rewrite this function to make it readable.
And add formula descriptions to comments.


>> +               u64FCLKO = u64PllFreq * ((VSIPLL_FCLKO_MIN_FREQ / u64PllFreq) +
>> +                          ((VSIPLL_FCLKO_MIN_FREQ % u64PllFreq) ? 1 : 0));
> Is this DIV_ROUND_UP() or something like that?
>
>> +       } else {
>> +               pr_err("Failed to set rate %ld\n", u64PllFreq);
>> +               return 0;
>> +       }
>> +
>> +       u64P = (u64FCLKO >= VSIPLL_FCLK_MIN_FREQ) ? 1 :
>> +              ((VSIPLL_FCLK_MIN_FREQ / u64FCLKO) +
>> +               ((VSIPLL_FCLK_MIN_FREQ % u64FCLKO) ? 1 : 0));
>> +
>> +       if ((PllSrcClk > (VSIPLL_FREFDIVM_MAX_FREQ * (64-1))) ||
>> +           (PllSrcClk < VSIPLL_FREFDIVM_MIN_FREQ1))
>> +               return 0;
>> +
> [...]
>> +               break;
>> +       }
>> +
>> +       return pllfreq;
>> +}
>> +
>> +static long ma35d1_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
>> +                                     unsigned long *prate)
>> +{
>> +       return rate;
> This needs to do actual math and figure out that some rate will not
> work and calculate what the rate will actually be if clk_set_rate() is
> called with 'rate'.

Got it. We will add clock rate check here.

>> +}
>> +
>> +static int ma35d1_clk_pll_is_prepared(struct clk_hw *hw)
>> +{
>> +       struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw);
>> +       u32 val = __raw_readl(pll->ctl1_base);
>> +
>> +       return (val & VSIPLLCTL1_PD_MSK) ? 0 : 1;
>> +}
>> +
>> +static int ma35d1_clk_pll_prepare(struct clk_hw *hw)
>> +{
>> +       struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw);
>> +       u32 val;
>> +
>> +       if ((pll->type == MA35D1_CAPLL) || (pll->type == MA35D1_DDRPLL)) {
>> +               pr_warn("Nuvoton MA35D1 CAPLL/DDRPLL is read only.\n");
>> +               return -EACCES;
>> +       }
>> +
>> +       CLK_UnLockReg(pll);
>> +       val = __raw_readl(pll->ctl1_base);
>> +       val &= ~VSIPLLCTL1_PD_MSK;
>> +       __raw_writel(val, pll->ctl1_base);
>> +       CLK_LockReg(pll);
>> +       return 0;
>> +}
>> +
>> +static void ma35d1_clk_pll_unprepare(struct clk_hw *hw)
>> +{
>> +       struct ma35d1_clk_pll *pll = to_ma35d1_clk_pll(hw);
>> +       u32 val;
>> +
>> +       if ((pll->type == MA35D1_CAPLL) || (pll->type == MA35D1_DDRPLL)) {
>> +               pr_warn("Nuvoton MA35D1 CAPLL/DDRPLL is read only.\n");
>> +       } else {
>> +               val = __raw_readl(pll->ctl1_base);
>> +               val |= VSIPLLCTL1_PD_MSK;
>> +               __raw_writel(val, pll->ctl1_base);
>> +       }
>> +}
>> +
>> +static const struct clk_ops ma35d1_clk_pll_ops = {
>> +       .is_prepared = ma35d1_clk_pll_is_prepared,
>> +       .prepare = ma35d1_clk_pll_prepare,
>> +       .unprepare = ma35d1_clk_pll_unprepare,
>> +       .set_rate = ma35d1_clk_pll_set_rate,
>> +       .recalc_rate = ma35d1_clk_pll_recalc_rate,
>> +       .round_rate = ma35d1_clk_pll_round_rate,
>> +};
>> +
>> +struct clk_hw *ma35d1_reg_clk_pll(enum ma35d1_pll_type type,
>> +                                 u8 u8mode, const char *name,
>> +                                 const char *parent,
>> +                                 unsigned long targetFreq,
>> +                                 void __iomem *base,
>> +                                 struct regmap *regmap)
>> +{
>> +       struct ma35d1_clk_pll *pll;
>> +       struct clk_hw *hw;
>> +       struct clk_init_data init;
>> +       int ret;
>> +
>> +       pll = kmalloc(sizeof(*pll), GFP_KERNEL);
>> +       if (!pll)
>> +               return ERR_PTR(-ENOMEM);
>> +
>> +       pll->type = type;
>> +       pll->mode = u8mode;
>> +       pll->rate = targetFreq;
>> +       pll->ctl0_base = base + VSIPLL_CTL0;
>> +       pll->ctl1_base = base + VSIPLL_CTL1;
>> +       pll->ctl2_base = base + VSIPLL_CTL2;
>> +       pll->regmap = regmap;
>> +
>> +       init.name = name;
>> +       init.flags = 0;
>> +       init.parent_names = &parent;
>> +       init.num_parents = 1;
>> +       init.ops = &ma35d1_clk_pll_ops;
>> +       pll->hw.init = &init;
>> +       hw = &pll->hw;
>> +
>> +       ret = clk_hw_register(NULL, hw);
>> +       if (ret) {
>> +               pr_err("failed to register vsi-pll clock!!!\n");
>> +               kfree(pll);
>> +               return ERR_PTR(ret);
>> +       }
>> +       return hw;
>> +}
>> diff --git a/drivers/clk/nuvoton/clk-ma35d1.c b/drivers/clk/nuvoton/clk-ma35d1.c
>> new file mode 100644
>> index 000000000000..ac8154458b81
>> --- /dev/null
>> +++ b/drivers/clk/nuvoton/clk-ma35d1.c
>> @@ -0,0 +1,970 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (C) 2023 Nuvoton Technology Corp.
>> + * Author: Chi-Fang Li <cfli0@nuvoton.com>
>> + */
>> +
>> +#include <linux/clk.h>
> I don't see any clk consumer usage. Please remove.
+#include <linux/clk-provider.h>
>> +#include <linux/clkdev.h>
> I don't see any clkdev usage. Please remove.

Yes, clk.h and clkdev.h are not used here. I will remove them.


>> +#include <linux/io.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/spinlock.h>
>> +#include <dt-bindings/clock/nuvoton,ma35d1-clk.h>
>> +
>> +#include "clk-ma35d1.h"
>> +
>> +DEFINE_SPINLOCK(ma35d1_lock);
> Why not static?

ma35d1_lock is used in clk-ma35d1-divider.c only.
I will move it form clk-ma35d1.c to clk-ma35d1-divider.c as add static.

>
>> +
>> +static const char *const ca35clk_sel_clks[] = {
>> +       "hxt", "capll", "ddrpll", "dummy"
> Are these parent mappings? Please use 'struct clk_parent_data' instead
> if so.
>
>> +};
>> +
>> +static const char *const sysclk0_sel_clks[] = {
>> +       "epll_div2", "syspll"
>> +};
>> +
> [...]
>> +
>> +static struct clk_hw **hws;
>> +static struct clk_hw_onecell_data *ma35d1_hw_data;
> Any reason to make these global pointers vs local pointers during probe?

We will consider about using devm_of_clk_add_hw_provider() and remove 
these global pointers.

>
>> +
>> +static int ma35d1_clocks_probe(struct platform_device *pdev)
>> +{
>> +       int ret;
>> +       struct device *dev = &pdev->dev;
>> +       struct device_node *clk_node = dev->of_node;
>> +       void __iomem *clk_base;
>> +       struct regmap *regmap;
>> +       u32 pllmode[5] = { 0, 0, 0, 0, 0 };
>> +       u32 pllfreq[5] = { 0, 0, 0, 0, 0 };
>> +
>> +       dev_info(&pdev->dev, "Nuvoton MA35D1 Clock Driver\n");
> Drop this banner message please.

OK, I will remove it.

>
>> +       ma35d1_hw_data = devm_kzalloc(&pdev->dev, struct_size(ma35d1_hw_data,
>> +                                     hws, CLK_MAX_IDX), GFP_KERNEL);
>> +
>> +       if (WARN_ON(!ma35d1_hw_data))
>> +               return -ENOMEM;
>> +
>> +       ma35d1_hw_data->num = CLK_MAX_IDX;
>> +       hws = ma35d1_hw_data->hws;
>> +
>> +       clk_node = of_find_compatible_node(NULL, NULL, "nuvoton,ma35d1-clk");
>> +       clk_base = of_iomap(clk_node, 0);
> Use platform_device APIs as you have a platform device here ('pdev').

OK, I will fix it.

>> +       of_node_put(clk_node);
>> +       if (!clk_base) {
>> +               pr_err("%s: could not map region\n", __func__);
>> +               return -ENOMEM;
>> +       }
>> +       regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
>> +                                                "nuvoton,sys");
> Why is it a syscon?
>
>> +       if (IS_ERR(regmap))
>> +               pr_warn("%s: Unable to get syscon\n", __func__);
> How can we continue without the regmap?

I will make it return error here.

>
>> +
>> +       /* clock sources */
>> +       hws[HXT] = ma35d1_clk_fixed("hxt", 24000000);
> [...]
>> +       /* EADC */
>> +       hws[EADC_DIV] = ma35d1_clk_divider_table("eadc_div", "pclk2",
>> +                                                clk_base + REG_CLK_CLKDIV4,
>> +                                                0, 4, eadc_div_table);
>> +       hws[EADC_GATE] = ma35d1_clk_gate("eadc_gate", "eadc_div",
>> +                                        clk_base + REG_CLK_APBCLK2, 25);
>> +
>> +       ret = of_clk_add_hw_provider(clk_node, of_clk_hw_onecell_get,
> Use devm_ variant.

OK, I will fix it.

>
>> +                                    ma35d1_hw_data);
>> +       if (ret < 0) {
>> +               dev_err(dev, "failed to register hws for MA35D1\n");
>> +               iounmap(clk_base);
> Use devm mapping APIs to avoid unmapping on error path.

>> +       }
>> +       return ret;
>> +}
>> +
>> +static const struct of_device_id ma35d1_clk_of_match[] = {
>> +       { .compatible = "nuvoton,ma35d1-clk" },
>> +       { },
> Drop comma above so nothing can come after this.

I will remove the comma.

>
>> +};
>> +MODULE_DEVICE_TABLE(of, ma35d1_clk_of_match);
>> +
>> +static struct platform_driver ma35d1_clk_driver = {
>> +       .probe = ma35d1_clocks_probe,
>> +       .driver = {
>> +               .name = "ma35d1-clk",
>> +               .of_match_table = ma35d1_clk_of_match,
>> +       },
>> +};
>> +
>> +static int __init ma35d1_clocks_init(void)
>> +{
>> +       return platform_driver_register(&ma35d1_clk_driver);
>> +}
>> +
>> +postcore_initcall(ma35d1_clocks_init);
>> +
>> +MODULE_AUTHOR("Chi-Fang Li<cfli0@nuvoton.com>");
>> +MODULE_DESCRIPTION("NUVOTON MA35D1 Clock Driver");
>> +MODULE_LICENSE("GPL v2");
>> diff --git a/drivers/clk/nuvoton/clk-ma35d1.h b/drivers/clk/nuvoton/clk-ma35d1.h
>> new file mode 100644
>> index 000000000000..faae5a17e425
>> --- /dev/null
>> +++ b/drivers/clk/nuvoton/clk-ma35d1.h
>> @@ -0,0 +1,198 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Copyright (C) 2023 Nuvoton Technology Corp.
>> + * Author: Chi-Fang Li <cfli0@nuvoton.com>
>> + */
>> +
>> +#ifndef __DRV_CLK_NUVOTON_MA35D1_H
>> +#define __DRV_CLK_NUVOTON_MA35D1_H
>> +
>> +#include <linux/clk.h>
>> +#include <linux/clkdev.h>
> Are these includes used?

I remove them and compile passed, so I will will remove them in the next 
version.


>
>> +#include <linux/clk-provider.h>
>> +#include <linux/spinlock.h>
>> +#include <linux/regmap.h>
>> +#include <linux/mfd/syscon.h>
>> +#include <linux/mfd/ma35d1-sys.h>
> These probably aren't needed to be included here. Just forward declare
> structs you need and include the headers in the C file.

Sure, we will move all #include in clk-ma35d1.h, and only include 
required .h files in C file.

>> +
> [...]
>> +
>> +struct clk_hw *ma35d1_reg_adc_clkdiv(struct device *dev,
>> +                                   const char *name,
>> +                                   const char *parent_name,
>> +                                   unsigned long flags,
>> +                                   void __iomem *reg, u8 shift,
>> +                                   u8 width, u32 mask_bit);
>> +
>> +extern spinlock_t ma35d1_lock;
> Why?
I will remove all "extern" ma35d1_lock, as it will be static in 
clk-ma35d1-divider.c.


Best regards,

Jacky Huang



  reply	other threads:[~2023-03-17  3:09 UTC|newest]

Thread overview: 89+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-15  7:28 [PATCH 00/15] Introduce Nuvoton ma35d1 SoC Jacky Huang
2023-03-15  7:28 ` [PATCH 01/15] arm64: Kconfig.platforms: Add config for Nuvoton MA35 platform Jacky Huang
2023-03-15  7:28 ` [PATCH 02/15] arm64: defconfig: Add Nuvoton MA35 family support Jacky Huang
2023-03-16 14:23   ` Arnd Bergmann
2023-03-17  9:05     ` Jacky Huang
2023-03-15  7:28 ` [PATCH 03/15] mfd: Add the header file of Nuvoton ma35d1 system manager Jacky Huang
2023-03-16 13:30   ` Ilpo Järvinen
2023-03-17  6:51     ` Jacky Huang
2023-03-16 14:44   ` Arnd Bergmann
2023-03-17  9:28     ` Jacky Huang
2023-03-15  7:28 ` [PATCH 04/15] dt-bindings: clock: nuvoton: add binding for ma35d1 clock controller Jacky Huang
2023-03-16  7:31   ` Krzysztof Kozlowski
2023-03-16 13:35     ` Jacky Huang
2023-03-16 14:09       ` Krzysztof Kozlowski
2023-03-15  7:28 ` [PATCH 05/15] dt-bindings: reset: nuvoton: add binding for ma35d1 IP reset control Jacky Huang
2023-03-16  7:31   ` Krzysztof Kozlowski
2023-03-15  7:28 ` [PATCH 06/15] dt-bindings: mfd: syscon: Add nuvoton,ma35d1-sys compatible Jacky Huang
2023-03-16  7:31   ` Krzysztof Kozlowski
2023-03-17  1:03     ` Jacky Huang
2023-03-15  7:28 ` [PATCH 07/15] dt-bindings: arm: Add initial bindings for Nuvoton platform Jacky Huang
2023-03-16  7:33   ` Krzysztof Kozlowski
2023-03-16 14:32     ` Arnd Bergmann
2023-03-18  1:26       ` Jacky Huang
2023-03-15  7:28 ` [PATCH 08/15] dt-bindings: clock: Document ma35d1 clock controller bindings Jacky Huang
2023-03-15 21:59   ` Stephen Boyd
2023-03-16  3:24     ` Jacky Huang
2023-03-16  7:35   ` Krzysztof Kozlowski
2023-03-17  3:47     ` Jacky Huang
2023-03-17  9:13       ` Krzysztof Kozlowski
2023-03-17  9:52         ` Jacky Huang
2023-03-17 16:03           ` Krzysztof Kozlowski
2023-03-18  2:11             ` Jacky Huang
2023-03-15  7:28 ` [PATCH 09/15] dt-bindings: reset: Document ma35d1 reset " Jacky Huang
2023-03-16  7:37   ` Krzysztof Kozlowski
2023-03-16  7:39     ` Krzysztof Kozlowski
2023-03-18  4:30       ` Jacky Huang
2023-03-19 11:05         ` Krzysztof Kozlowski
2023-03-20  6:26           ` Jacky Huang
2023-03-15  7:28 ` [PATCH 10/15] dt-bindings: serial: Document ma35d1 uart " Jacky Huang
2023-03-16  7:40   ` Krzysztof Kozlowski
2023-03-17  4:18     ` Jacky Huang
2023-03-15  7:28 ` [PATCH 11/15] arm64: dts: nuvoton: Add initial ma35d1 device tree Jacky Huang
2023-03-16  7:45   ` Krzysztof Kozlowski
2023-03-18  6:07     ` Jacky Huang
2023-03-19 11:06       ` Krzysztof Kozlowski
2023-03-19 14:16         ` Jacky Huang
2023-03-16 14:17   ` Arnd Bergmann
2023-03-16 16:44     ` Lee Jones
2023-03-18 13:32       ` Jacky Huang
2023-03-18 13:17     ` Jacky Huang
2023-03-18 14:04       ` Arnd Bergmann
2023-03-20 15:38         ` Jacky Huang
2023-03-15  7:28 ` [PATCH 12/15] clk: nuvoton: Add clock driver for ma35d1 clock controller Jacky Huang
2023-03-15 22:07   ` kernel test robot
2023-03-15 22:30   ` Stephen Boyd
2023-03-17  3:07     ` Jacky Huang [this message]
2023-03-16  7:51   ` Krzysztof Kozlowski
2023-03-19  2:55     ` Jacky Huang
2023-03-16 15:56   ` Ilpo Järvinen
2023-03-19  5:16     ` Jacky Huang
2023-03-20 10:31       ` Ilpo Järvinen
2023-03-21 15:03         ` Jacky Huang
2023-03-15  7:29 ` [PATCH 13/15] reset: Add Nuvoton ma35d1 reset driver support Jacky Huang
2023-03-16  7:51   ` Krzysztof Kozlowski
2023-03-17  7:13     ` Jacky Huang
2023-03-16 15:05   ` Ilpo Järvinen
2023-03-19 13:10     ` Jacky Huang
2023-03-15  7:29 ` [PATCH 14/15] tty: serial: Add Nuvoton ma35d1 serial " Jacky Huang
2023-03-15  7:37   ` Greg KH
2023-03-15  9:40     ` Jacky Huang
2023-03-15  9:48   ` kernel test robot
2023-03-15 10:13   ` Jiri Slaby
2023-03-16 13:28     ` Jacky Huang
2023-03-16 14:54   ` Ilpo Järvinen
2023-03-20  8:23     ` Jacky Huang
2023-03-20 10:04       ` Ilpo Järvinen
2023-03-21 14:23         ` Jacky Huang
2023-03-15  7:29 ` [PATCH 15/15] MAINTAINERS: Add entry for NUVOTON MA35 Jacky Huang
2023-03-16 14:38   ` Arnd Bergmann
2023-03-19 12:01     ` Jacky Huang
2023-03-19 12:36       ` Tomer Maimon
2023-03-16  7:41 ` [PATCH 00/15] Introduce Nuvoton ma35d1 SoC Krzysztof Kozlowski
2023-03-16 14:05 ` Arnd Bergmann
2023-03-17  6:30   ` Jacky Huang
2023-03-17 13:21     ` Arnd Bergmann
2023-03-17 16:06       ` Krzysztof Kozlowski
2023-03-18  3:07         ` Jacky Huang
2023-03-18  9:07           ` Arnd Bergmann
2023-03-18  3:00       ` Jacky Huang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=493c9c33-5ad9-e3f3-501c-d9f27b4d54d5@gmail.com \
    --to=ychuang570808@gmail.com \
    --cc=devicetree@vger.kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=jirislaby@kernel.org \
    --cc=krzysztof.kozlowski+dt@linaro.org \
    --cc=lee@kernel.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-serial@vger.kernel.org \
    --cc=mturquette@baylibre.com \
    --cc=p.zabel@pengutronix.de \
    --cc=robh+dt@kernel.org \
    --cc=sboyd@kernel.org \
    --cc=schung@nuvoton.com \
    --cc=ychuang3@nuvoton.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.