[PATCH 2/7 v4] Add the clock framework for Telechips TCC8xxx processors.

Russell King - ARM Linux linux at arm.linux.org.uk
Wed Apr 14 09:35:07 EDT 2010


On Wed, Mar 31, 2010 at 04:50:58PM +0200, Hans J. Koch wrote:
> +static void __clk_disable(struct clk *clk)
> +{
> +	if (!clk)
> +		return;
> +
> +	BUG_ON(clk->refcount == 0);
> +
> +	if (!(--clk->refcount) && clk->disable)
> +		clk->disable(clk);
> +	__clk_disable(clk->parent);
> +}
> +
> +static int __clk_enable(struct clk *clk)
> +{
> +	if (!clk)
> +		return -EINVAL;
> +
> +	__clk_enable(clk->parent);

Here, every enable of the child clock causes the parent to be enabled
one more time.  This is a bad idea in conjunction with...

> +
> +	if (clk->refcount++ == 0 && clk->enable)
> +		clk->enable(clk);
> +
> +	return 0;
> +}

> +/* Set the clock's parent to another clock source */
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	int ret = -EINVAL;
> +
> +	if (!clk)
> +		return ret;
> +	if (!clk->set_parent || !parent)
> +		return ret;
> +
> +	mutex_lock(&clocks_mutex);
> +	ret = clk->set_parent(clk, parent);
> +	if (ret == 0)
> +		clk->parent = parent;

... reparenting of clocks.

Reparenting is much easier to deal with if you only enable/disable the
parent clock on the first enable and last disable of the child clock.
Then you can do:

	if (clk->refcount)
		__clk_enable(parent);
	ret = clk->set_parent(clk, parent);
	if (ret == 0) {
		old = clk->parent;
		clk->parent = parent;
	} else {
		old = parent;
	}
	if (clk->refcount)
		__clk_disable(old);

here, which will keep the refcounts straight.

> +	mutex_unlock(&clocks_mutex);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);

>  /* Clock controller registers */
> -#define CKC_BASE		(APB1_PERI_BASE_VIRT + 0x6000)
> -#define CKC_BASE_PHYS		(APB1_PERI_BASE + 0x6000)
> +#define CKC_BASE	(void __iomem *)(APB1_PERI_BASE_VIRT + 0x6000)

This has the possibility of causing unexpected side effects.  With any
macro which is more than just a number, it's always worth adding a set
of parens around it to ensure that evaluation happens in the order you
expect.



More information about the linux-arm-kernel mailing list