Re: [PATCH V4] clk: vc5: Add support for IDT VersaClock 5P49V5923 and 5P49V5933

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

 



On 01/11/2017 04:41 PM, Laurent Pinchart wrote:
> Hi Marek,

Hi!

> Thank you for the patch.
> 
> On Wednesday 11 Jan 2017 15:37:11 Marek Vasut wrote:
>> On 01/10/2017 07:50 PM, Marek Vasut wrote:
>>> Add driver for IDT VersaClock 5 5P49V5923 and 5P49V5933 chips. These
>>> chips have two clock inputs, XTAL or CLK, which are muxed into single
>>> PLL/VCO input. In case of 5P49V5923, the XTAL in built into the chip
>>> while the 5P49V5923 requires external XTAL.
>>>
>>> The PLL feeds two fractional dividers. Each fractional divider feeds
>>> output mux, which allows selecting between clock from the fractional
>>> divider itself or from output mux on output N-1. In case of output
>>> mux 0, the output N-1 is instead connected to the output from the mux
>>> feeding the PLL.
>>>
>>> The driver thus far supports only the 5P49V5923 and 5P49V5933, while
>>> it should be easily extensible to the whole 5P49V59xx family of chips
>>> as they are all pretty similar.
>>>
>>> Signed-off-by: Marek Vasut <marek.vasut@xxxxxxxxx>
>>> Cc: Michael Turquette <mturquette@xxxxxxxxxxxx>
>>> Cc: Stephen Boyd <sboyd@xxxxxxxxxxxxxx>
>>
>> +Cc Laurent, linux-renesas
>>
>>> ---
>>> V2: - Drop address-cells and size-cells from the binding
>>>     - Add clock-names to the binding
>>>     - Drop vc5_input_names
>>>     - Fix assortment of spelling mistakes
>>>     - Switch div_frc and div_int datatype to uXX
>>>     - Switch f_in to u32
>>>     - Add missing remove
>>>     - Define macros for handling XIN and CLKIN
>>>     - Rework the FOD fractional divider calculation, this was wrong
>>>       and made the output clock be off considerably under certain
>>>       circumstances (when the fractional part was large).
>>>
>>> V3: - Rework the MUX frequency recalculation and divider configration
>>>       so that it fits into the clock framework
>>>     - Add support for 5P49V5933 chip to lay groundwork for adding more
>>>       chips easily.
>>>     - Export the OUT0_SEL_I2CB output into the clock framework, so it
>>>       can be accessed from DT as well. WARNING: This does change the
>>>       bindings, clock0 is now the OUT0_SEL_I2CB, clock1 is OUT1 and
>>>       clock2 is OUT2 (or OUT4 on the 5P49V5933).
>>>     - Drop unnecessary caching of pin_*_name clock name and clk_hw
>>>       structures in driver data.
>>>     - Add missing MAINTAINERS entry
>>>
>>> V4: - Support also 5P49V5923A by dropping the B from the bindings and
>>>       code. According to the update notice, the chips are identical
>>>       except for disabling the VCO monitoring, which is internal
>>>       factory-defined bit and has no impact on silicon performance.
>>>
>>> ---
>>>
>>>  .../devicetree/bindings/clock/idt,versaclock5.txt  |  43 ++
> 
> If you decide to split the bindings in a separate patch as often requested by 
> the DT reviewers,
> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx>
> 
> for them. Please see below for more comments.
> 
>>>  MAINTAINERS                                        |   5 +
>>>  drivers/clk/Kconfig                                |  10 +
>>>  drivers/clk/Makefile                               |   1 +
>>>  drivers/clk/clk-versaclock5.c                      | 821 ++++++++++++++++
>>>  5 files changed, 880 insertions(+)
>>>  create mode 100644
>>>  Documentation/devicetree/bindings/clock/idt,versaclock5.txt create mode
>>>  100644 drivers/clk/clk-versaclock5.c
> 
> [snip]
> 
>>> diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c
>>> new file mode 100644
>>> index 000000000000..14f518e84d6d
>>> --- /dev/null
>>> +++ b/drivers/clk/clk-versaclock5.c
> 
> [snip]
> 
>>> +/*
>>> + * VersaClock5 i2c regmap
>>> + */
>>> +static bool vc5_regmap_is_writeable(struct device *dev, unsigned int reg)
>>> +{
>>> +	/* Factory reserved regs, make them read-only */
>>> +	if (reg >= 0 && reg <= 0xf)
> 
> reg is unsigned, it will always be >= 0. You can drop the first part of the 
> condition.

Fixed

>>> +		return false;
>>> +
>>> +	/* Factory reserved regs, make them read-only */
>>> +	if (reg == 0x14 || reg == 0x1c || reg == 0x1d)
>>> +		return false;
>>> +
>>> +	return true;
>>> +}
> 
> [snip]
> 
>>> +static long vc5_mux_round_rate(struct clk_hw *hw, unsigned long rate,
>>> +			       unsigned long *parent_rate)
>>> +{
>>> +	unsigned long idiv;
>>> +
>>> +	/* PLL cannot operate with input clock above 50 MHz. */
>>> +	if (rate > 50000000)
>>> +		return -EINVAL;
> 
> As this is a PLL constraint, shouldn't it be enforced by vc5_pll_round_rate() 
> instead ?

vc5_pll_round_rate can only enforce PLL output frequency, not input
frequency AFAICT .

>>> +	/* CLKIN within range of PLL input, feed directly to PLL. */
>>> +	if (*parent_rate <= 50000000)
>>> +		return *parent_rate;
>>> +
>>> +	idiv = DIV_ROUND_UP(*parent_rate, rate);
>>> +	if (idiv > 127)
>>> +		return -EINVAL;
>>> +
>>> +	return *parent_rate / idiv;
>>> +}

[...]

>>> +static struct clk_hw *
>>> +vc5_of_clk_get(struct of_phandle_args *clkspec, void *data)
>>> +{
>>> +	struct vc5_driver_data *vc5 = data;
>>> +	unsigned int idx = clkspec->args[0];
>>> +
>>> +	if (idx > 2) {
>>> +		pr_err("%s: invalid index %u\n", __func__, idx);
> 
> Does this deserve an error message ?

I think it does, the driver will yell if you use incorrect index in the
bindings.

>>> +		return ERR_PTR(-EINVAL);
>>> +	}
>>> +
>>> +	return &vc5->clk_out[idx].hw;
>>> +}
>>> +
>>> +static int vc5_map_index_to_output(const enum vc5_model model,
>>> +				   const unsigned int n)
>>> +{
>>> +	switch (model) {
>>> +	case IDT_VC5_5P49V5923:
>>> +		if (n == 0)	/* OUT1 */
>>> +			return 0;
>>> +		if (n == 1)	/* OUT2 */
>>> +			return 1;
>>> +		break;
>>> +	case IDT_VC5_5P49V5933:
>>> +		if (n == 0)	/* OUT1 */
>>> +			return 0;
>>> +		if (n == 1)	/* OUT4 */
>>> +			return 3;
>>> +		break;
>>> +	}
>>> +
>>> +	/*
>>> +	 * If we got here, there is certainly a bug in the driver,
>>> +	 * but we shouldn't crash the kernel.
>>> +	 */
>>> +	WARN_ON("Invalid clock index!\n");
>>> +	return -EINVAL;
> 
> I don't think that's needed. The function is called from two locations only, 
> and they're both very easy to audit. You can just return n in the 
> IDT_VC5_5P49V5923 case and return n == 0 ? 0 : 3 in the other case.

OK, dropped and fixed.

>>> +}
> 
> [snip]
> 
>>> +static int vc5_probe(struct i2c_client *client,
>>> +                  const struct i2c_device_id *id)
>>> +{
>>> +     const struct of_device_id *of_id =
>>> +             of_match_device(clk_vc5_of_match, &client->dev);
>>> +     struct vc5_driver_data *vc5;
>>> +     struct clk_init_data init;
>>> +     const char *parent_names[2];
>>> +     unsigned int n, idx;
>>> +     int ret;
>>> +
>>> +     vc5 = devm_kzalloc(&client->dev, sizeof(*vc5), GFP_KERNEL);
>>> +     if (vc5 == NULL)
>>> +             return -ENOMEM;
>>> +
>>> +     i2c_set_clientdata(client, vc5);
>>> +     vc5->client = client;
>>> +     vc5->model = (enum vc5_model)of_id->data;
>>> +
>>> +     vc5->pin_xin = devm_clk_get(&client->dev, "xin");
>>> +     if (PTR_ERR(vc5->pin_xin) == -EPROBE_DEFER)
>>> +             return -EPROBE_DEFER;
>>> +
>>> +     vc5->pin_clkin = devm_clk_get(&client->dev, "clkin");
>>> +     if (PTR_ERR(vc5->pin_clkin) == -EPROBE_DEFER)
>>> +             return -EPROBE_DEFER;
>>> +
>>> +     vc5->regmap = devm_regmap_init_i2c(client, &vc5_regmap_config);
>>> +     if (IS_ERR(vc5->regmap)) {
>>> +             dev_err(&client->dev, "failed to allocate register map\n");
>>> +             return PTR_ERR(vc5->regmap);
>>> +     }
>>> +
>>> +     /* Register clock input mux */
>>> +     memset(&init, 0, sizeof(init));
>>> +
>>> +     if (!IS_ERR(vc5->pin_xin)) {
>>> +             clk_prepare_enable(vc5->pin_xin);
> 
> Given that the CCF core will take care of enabling/disabling parents as 
> needed, do you need this ?

It should, so, dropped.

[...]

-- 
Best regards,
Marek Vasut



[Index of Archives]     [Linux Samsung SOC]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux