[PATCH 1/8] clk: keystone: add Keystone PLL clock driver

Santosh Shilimkar santosh.shilimkar at ti.com
Tue Aug 13 12:01:59 EDT 2013


On Tuesday 13 August 2013 11:48 AM, Mark Rutland wrote:
> [Adding dt maintainers]
> 
> On Mon, Aug 05, 2013 at 05:12:20PM +0100, Santosh Shilimkar wrote:
>> Add the driver for the PLL IPs found on Keystone 2 devices. The main PLL
>> IP typically has a multiplier, and a divider. The addtional PLL IPs like
>> ARMPLL, DDRPLL and PAPLL are controlled by the memory mapped register where
>> as the Main PLL is controlled by a PLL controller and memory map registers.
>> This difference is handle using 'has_pll_cntrl' property.
>>
>> Cc: Mike Turquette <mturquette at linaro.org>
>>
>> Signed-off-by: Santosh Shilimkar <santosh.shilimkar at ti.com>
>> ---

Thanks for review Mark.

>>  .../devicetree/bindings/clock/keystone-pll.txt     |   36 ++++
>>  drivers/clk/keystone/pll.c                         |  197 ++++++++++++++++++++
>>  include/linux/clk/keystone.h                       |   18 ++
>>  3 files changed, 251 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/clock/keystone-pll.txt
>>  create mode 100644 drivers/clk/keystone/pll.c
>>  create mode 100644 include/linux/clk/keystone.h
>>
>> diff --git a/Documentation/devicetree/bindings/clock/keystone-pll.txt b/Documentation/devicetree/bindings/clock/keystone-pll.txt
>> new file mode 100644
>> index 0000000..58f6470
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/keystone-pll.txt
>> @@ -0,0 +1,36 @@
>> +Binding for keystone PLLs. The main PLL IP typically has a multiplier,
>> +a divider and a post divider. The additional PLL IPs like ARMPLL, DDRPLL
>> +and PAPLL are controlled by the memory mapped register where as the Main
>> +PLL is controlled by a PLL controller. This difference is handle using
>> +'pll_has_pllctrl' property.
>> +
>> +This binding uses the common clock binding[1].
>> +
>> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
>> +
>> +Required properties:
>> +- compatible : shall be "keystone,pll-clk".
> 
> Keystone isn't a vendor, and generally, bindings have used "clock"
> rather than "clk".
> 
> Perhaps "ti,keystone-pll-clock" ?
> 
Agree.

>> +- #clock-cells : from common clock binding; shall be set to 0.
>> +- clocks : parent clock phandle
>> +- reg - index 0 -  PLLCTRL PLLM register address
>> +- 	index 1 -  MAINPLL_CTL0 register address
> 
> Perhaps a reg-names would be useful?
> 
>> +- pll_has_pllctrl - PLL is controlled by controller or memory mapped register
> 
> Huh? I don't understand what that description means. What does the
> property tell you? Is having one of the registers optional? If so that
> should be described by a reg-names property associated with the reg, and
> should be noted in the binding.
> 
After re-reading it, yes I agree it not clear. The point is there
are two different types of IPs and pogramming model changes quite
a bit. Its not just 1 register optional.

>> +- pllm_lower_mask - pllm lower bit mask
>> +- pllm_upper_mask - pllm upper bit mask
>> +- plld_mask - plld mask
>> +- fixed_postdiv - fixed post divider value
> 
> Please use '-' rather than '_' in property names, it's a standard
> convention for dt and going against it just makes things unnecessarily
> complicated.
> 
> Why are these necessary? Are clocks sharing common registers, are there
> some sets of "keystone,pll-clk"s that have the same masks, or does this
> just vary wildly?
> 
This is mainly to take care of the programming model which varies between
IPs. Will try to make that bit more clear.

> Also, what types are these (presumably a single cell/u32)?
> 
u32

>> +
>> +Example:
>> +	clock {
>> +		#clock-cells = <0>;
>> +		compatible = "keystone,pll-clk";
>> +		clocks = <&refclk>;
>> +		reg = <0x02310110 4	/* PLLCTRL PLLM */
>> +			0x02620328 4>;	/* MAINPLL_CTL0 */
>> +		pll_has_pllctrl;
>> +		pllm_lower_mask	= <0x3f>;
>> +		pllm_upper_mask = <0x7f000>;
>> +		pllm_upper_shift = <6>;
>> +		plld_mask = <0x3f>;
>> +		fixed_postdiv = <2>;
>> +	};
>> diff --git a/drivers/clk/keystone/pll.c b/drivers/clk/keystone/pll.c
>> new file mode 100644
>> index 0000000..1453eea
>> --- /dev/null
>> +++ b/drivers/clk/keystone/pll.c
>> @@ -0,0 +1,197 @@
>> +/*
>> + * Main PLL clk driver for Keystone devices
>> + *
>> + * Copyright (C) 2013 Texas Instruments Inc.
>> + *	Murali Karicheri <m-karicheri2 at ti.com>
>> + *	Santosh Shilimkar <santosh.shilimkar at ti.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + */
>> +#include <linux/clk.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/err.h>
>> +#include <linux/io.h>
>> +#include <linux/slab.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of.h>
>> +#include <linux/module.h>
>> +#include <linux/clk/keystone.h>
>> +
>> +/**
>> + * struct clk_pll_data - pll data structure
>> + * @has_pllctrl: If set to non zero, lower 6 bits of multiplier is in pllm
>> + *	register of pll controller, else it is in the pll_ctrl0((bit 11-6)
> 
> The description in the binding doesn't make that clear at all. The
> naming scheme is confusing -- because you've named the PLLCTRL PLLM
> register pllm and the MAINPLL_CTL0 register pll_ctl0, it makes it look
> like the logic around has_pllctrl is being used backwards throughout the
> entire driver.
>
This is due to difference in the IPs. Naming scheme can be improved
though. Was bit lazy to not do that firstplace.
 
>> + * @phy_pllm: Physical address of PLLM in pll controller. Used when
>> + *	has_pllctrl is non zero.
>> + * @phy_pll_ctl0: Physical address of PLL ctrl0. This could be that of
>> + *	Main PLL or any other PLLs in the device such as ARM PLL, DDR PLL
>> + *	or PA PLL available on keystone2. These PLLs are controlled by
>> + *	this register. Main PLL is controlled by a PLL controller.
>> + * @pllm: PLL register map address
>> + * @pll_ctl0: PLL controller map address
>> + * @pllm_lower_mask: multiplier lower mask
>> + * @pllm_upper_mask: multiplier upper mask
>> + * @pllm_upper_shift: multiplier upper shift
>> + * @plld_mask: divider mask
>> + * @fixed_postdiv: Post divider
>> + */
>> +struct clk_pll_data {
>> +	unsigned char has_pllctrl;
> 
> bool?
Yes

> 
>> +	u32 phy_pllm;
>> +	u32 phy_pll_ctl0;
>> +	void __iomem *pllm;
>> +	void __iomem *pll_ctl0;
>> +	u32 pllm_lower_mask;
>> +	u32 pllm_upper_mask;
>> +	u32 pllm_upper_shift;
>> +	u32 plld_mask;
>> +	u32 fixed_postdiv;
>> +};
> 
> [...]
> 
>> +/**
>> + * of_keystone_pll_clk_init - PLL initialisation via DT
>> + * @node: device tree node for this clock
>> + */
>> +void __init of_keystone_pll_clk_init(struct device_node *node)
>> +{
>> +	struct clk_pll_data *pll_data;
>> +	const char *parent_name;
>> +	struct clk *clk;
>> +	int temp;
>> +
>> +	pll_data = kzalloc(sizeof(*pll_data), GFP_KERNEL);
>> +	WARN_ON(!pll_data);
> 
> Why don't you return here, before dereferencing NULL below?
> 
>> +
>> +	parent_name = of_clk_get_parent_name(node, 0);
>> +
>> +	if (of_find_property(node, "pll_has_pllctrl", &temp)) {
> 
> of_property_read_bool?
> 
>> +		/* PLL is controlled by the pllctrl */
>> +		pll_data->has_pllctrl = 1;
>> +		pll_data->pllm = of_iomap(node, 0);
>> +		WARN_ON(!pll_data->pllm);
>> +
>> +		pll_data->pll_ctl0 = of_iomap(node, 1);
>> +		WARN_ON(!pll_data->pll_ctl0);
> 
> Why do you not bail out if you couldn't map the registers you need?
> 
>> +
>> +		if (of_property_read_u32(node, "pllm_lower_mask",
>> +				&pll_data->pllm_lower_mask))
>> +			goto out;
>> +
>> +	} else {
>> +		/* PLL is controlled by the ctrl register */
>> +		pll_data->has_pllctrl = 0;
>> +		pll_data->pll_ctl0 = of_iomap(node, 0);
> 
> Huh? That's in a different order to the above (where pll_ctl0 was index
> 1 in the reg). I think you need to use reg-names for this, and come up
> with a more scheme internal to the driver to minimise confusion.
> 
Agree. 

>> +	}
>> +
>> +	if (of_property_read_u32(node, "pllm_upper_mask",
>> +			&pll_data->pllm_upper_mask))
>> +		goto out;
>> +
>> +	if (of_property_read_u32(node, "pllm_upper_shift",
>> +			&pll_data->pllm_upper_shift))
>> +		goto out;
>> +
>> +	if (of_property_read_u32(node, "plld_mask", &pll_data->plld_mask))
>> +		goto out;
>> +
>> +	if (of_property_read_u32(node, "fixed_postdiv",
>> +					&pll_data->fixed_postdiv))
>> +		goto out;
>> +
>> +	clk = clk_register_pll(NULL, node->name, parent_name,
>> +					 pll_data);
>> +	if (clk) {
>> +		of_clk_add_provider(node, of_clk_src_simple_get, clk);
>> +		return;
>> +	}
>> +out:
>> +	pr_err("of_keystone_pll_clk_init - error initializing clk %s\n",
>> +		 node->name);
>> +	kfree(pll_data);
> 
> You haven't unmapped either of the registers you may have mapped on your
> way out, and you've thrown away your only reference to them.
> 
Yep.

Will address your comments in next version.

Regards,
Santosh



More information about the linux-arm-kernel mailing list