All of lore.kernel.org
 help / color / mirror / Atom feed
* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01  9:11 ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-01  9:11 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

> I suggested that clk_prepare() be callable only from non-atomic contexts,
> and do whatever's required to ensure that the clock is available.  That
> may end up enabling the clock as a result.

I think that clk_prepare/clk_unprepare looks like the most promising solution, 
so will try to get some preliminary patches done. Here's what I'm planning:

-----

The changes to the API are essentially:

1) Document clk_enable/clk_disable as callable from atomic contexts, and
   so clock implementations must not sleep within this function.

2) For clock implementations that may sleep to turn on a clock, we add a
   new pair of functions to the clock API: clk_prepare and clk_unprepare.

   These will provide hooks for the clock implmentation to do any sleepable
   work (eg, wait for PLLs to settle) in preparation for a later clk_enable.

   For the most common clock implemntation cases (where clocks can be enabled 
   atomically), these functions will be a no-op, and all of the enable/disable
   work can be done in clk_enable/clk_disable.

   For implementations where clocks require blocking on enable/disable, most
   of the work will be done in clk_prepare/clk_unprepare. The clk_enable
   and clk_disable functions may be no-ops.

For drivers, this means that clk_prepare must be called (and have returned) 
before calling clk_enable.

= Enable/Prepare counts =

I intend to do the enable and prepare "counting" in the core clock API, 
meaning that that the clk_ops callbacks will only invoked on the first 
prepare/enable and the last unprepare/disable.

= Concurrency =

Splitting the prepare and enable stages introduces the concurrency 
requirements:

1) clk_enable must not return before the clock is outputting a valid clock 
   signal.

2) clk_prepare must not return before the clock is fully prepared (ie, it is 
   safe to call clk_enable).

It is not possible for clk_enable to wait for the clock to be prepared, 
because that would require synchronisation with clk_prepare, which may then 
require blocking. Therefore:

3) The clock consumer *must* respect the proper ordering of clk_prepare and 
   clk_enable. For example, drivers that call clk_enable during an interrupt 
   must ensure that the interrupt handler will not be invoked until 
   clk_prepare has returned.

= Other considerations =

The time that a clock spends "prepared" is a superset of the the time that a 
clock spends "enabled". Therefore, clocks that are switched on during 
clk_prepare (ie, non-atomic clocks) will be running for a larger amount of 
time. In some cases, this can be mitigated by moving some of the final 
(atomic) switching functionality to the clk_enable function.

= Implementation =

Basically:

struct clk {
	const struct clk_ops *ops
	int                  enable_count;
	spinlock_t           enable_lock;
	int                  prepare_count;
	struct mutex         prepare_lock;
};

int clk_enable(struct clk *clk)
{
	int ret = 0;

	spin_lock(&clk->enable_lock);
	if (!clk->enable_count)
		ret = clk->ops->enable(clk);

	if (!ret)
		clk->enable_count++;
	spin_unlock(&clk->enable_lock);

	return ret;
}

int clk_prepare(struct clk *clk)
{
	int ret = 0;

	mutex_lock(&clk->prepare_lock);
	if (!clk->prepare_count)
		ret = clk->ops->prepare(clk);

	if (!ret)
		clk->prepare_count++;
	mutex_unlock(&clk->prepare_lock);

	return ret;
}

-----

Comments welcome, code coming soon.

Cheers,


Jeremy


^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01  9:11 ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-01  9:11 UTC (permalink / raw)
  To: Russell King
  Cc: Dima Zavin, Saravana Kannan, Lorenzo Pieralisi, linux-sh,
	Ben Herrenschmidt, Sascha Hauer, linux-kernel, Paul Mundt,
	Ben Dooks, Uwe Kleine-König, Vincent Guittot, Jeremy Kerr,
	linux-arm-kernel, Nicolas Pitre

Hi all,

> I suggested that clk_prepare() be callable only from non-atomic contexts,
> and do whatever's required to ensure that the clock is available.  That
> may end up enabling the clock as a result.

I think that clk_prepare/clk_unprepare looks like the most promising solution, 
so will try to get some preliminary patches done. Here's what I'm planning:

-----

The changes to the API are essentially:

1) Document clk_enable/clk_disable as callable from atomic contexts, and
   so clock implementations must not sleep within this function.

2) For clock implementations that may sleep to turn on a clock, we add a
   new pair of functions to the clock API: clk_prepare and clk_unprepare.

   These will provide hooks for the clock implmentation to do any sleepable
   work (eg, wait for PLLs to settle) in preparation for a later clk_enable.

   For the most common clock implemntation cases (where clocks can be enabled 
   atomically), these functions will be a no-op, and all of the enable/disable
   work can be done in clk_enable/clk_disable.

   For implementations where clocks require blocking on enable/disable, most
   of the work will be done in clk_prepare/clk_unprepare. The clk_enable
   and clk_disable functions may be no-ops.

For drivers, this means that clk_prepare must be called (and have returned) 
before calling clk_enable.

== Enable/Prepare counts ==

I intend to do the enable and prepare "counting" in the core clock API, 
meaning that that the clk_ops callbacks will only invoked on the first 
prepare/enable and the last unprepare/disable.

== Concurrency ==

Splitting the prepare and enable stages introduces the concurrency 
requirements:

1) clk_enable must not return before the clock is outputting a valid clock 
   signal.

2) clk_prepare must not return before the clock is fully prepared (ie, it is 
   safe to call clk_enable).

It is not possible for clk_enable to wait for the clock to be prepared, 
because that would require synchronisation with clk_prepare, which may then 
require blocking. Therefore:

3) The clock consumer *must* respect the proper ordering of clk_prepare and 
   clk_enable. For example, drivers that call clk_enable during an interrupt 
   must ensure that the interrupt handler will not be invoked until 
   clk_prepare has returned.

== Other considerations ==

The time that a clock spends "prepared" is a superset of the the time that a 
clock spends "enabled". Therefore, clocks that are switched on during 
clk_prepare (ie, non-atomic clocks) will be running for a larger amount of 
time. In some cases, this can be mitigated by moving some of the final 
(atomic) switching functionality to the clk_enable function.

== Implementation ==

Basically:

struct clk {
	const struct clk_ops *ops
	int                  enable_count;
	spinlock_t           enable_lock;
	int                  prepare_count;
	struct mutex         prepare_lock;
};

int clk_enable(struct clk *clk)
{
	int ret = 0;

	spin_lock(&clk->enable_lock);
	if (!clk->enable_count)
		ret = clk->ops->enable(clk);

	if (!ret)
		clk->enable_count++;
	spin_unlock(&clk->enable_lock);

	return ret;
}

int clk_prepare(struct clk *clk)
{
	int ret = 0;

	mutex_lock(&clk->prepare_lock);
	if (!clk->prepare_count)
		ret = clk->ops->prepare(clk);

	if (!ret)
		clk->prepare_count++;
	mutex_unlock(&clk->prepare_lock);

	return ret;
}

-----

Comments welcome, code coming soon.

Cheers,


Jeremy


^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01  9:11 ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-01  9:11 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

> I suggested that clk_prepare() be callable only from non-atomic contexts,
> and do whatever's required to ensure that the clock is available.  That
> may end up enabling the clock as a result.

I think that clk_prepare/clk_unprepare looks like the most promising solution, 
so will try to get some preliminary patches done. Here's what I'm planning:

-----

The changes to the API are essentially:

1) Document clk_enable/clk_disable as callable from atomic contexts, and
   so clock implementations must not sleep within this function.

2) For clock implementations that may sleep to turn on a clock, we add a
   new pair of functions to the clock API: clk_prepare and clk_unprepare.

   These will provide hooks for the clock implmentation to do any sleepable
   work (eg, wait for PLLs to settle) in preparation for a later clk_enable.

   For the most common clock implemntation cases (where clocks can be enabled 
   atomically), these functions will be a no-op, and all of the enable/disable
   work can be done in clk_enable/clk_disable.

   For implementations where clocks require blocking on enable/disable, most
   of the work will be done in clk_prepare/clk_unprepare. The clk_enable
   and clk_disable functions may be no-ops.

For drivers, this means that clk_prepare must be called (and have returned) 
before calling clk_enable.

== Enable/Prepare counts ==

I intend to do the enable and prepare "counting" in the core clock API, 
meaning that that the clk_ops callbacks will only invoked on the first 
prepare/enable and the last unprepare/disable.

== Concurrency ==

Splitting the prepare and enable stages introduces the concurrency 
requirements:

1) clk_enable must not return before the clock is outputting a valid clock 
   signal.

2) clk_prepare must not return before the clock is fully prepared (ie, it is 
   safe to call clk_enable).

It is not possible for clk_enable to wait for the clock to be prepared, 
because that would require synchronisation with clk_prepare, which may then 
require blocking. Therefore:

3) The clock consumer *must* respect the proper ordering of clk_prepare and 
   clk_enable. For example, drivers that call clk_enable during an interrupt 
   must ensure that the interrupt handler will not be invoked until 
   clk_prepare has returned.

== Other considerations ==

The time that a clock spends "prepared" is a superset of the the time that a 
clock spends "enabled". Therefore, clocks that are switched on during 
clk_prepare (ie, non-atomic clocks) will be running for a larger amount of 
time. In some cases, this can be mitigated by moving some of the final 
(atomic) switching functionality to the clk_enable function.

== Implementation ==

Basically:

struct clk {
	const struct clk_ops *ops
	int                  enable_count;
	spinlock_t           enable_lock;
	int                  prepare_count;
	struct mutex         prepare_lock;
};

int clk_enable(struct clk *clk)
{
	int ret = 0;

	spin_lock(&clk->enable_lock);
	if (!clk->enable_count)
		ret = clk->ops->enable(clk);

	if (!ret)
		clk->enable_count++;
	spin_unlock(&clk->enable_lock);

	return ret;
}

int clk_prepare(struct clk *clk)
{
	int ret = 0;

	mutex_lock(&clk->prepare_lock);
	if (!clk->prepare_count)
		ret = clk->ops->prepare(clk);

	if (!ret)
		clk->prepare_count++;
	mutex_unlock(&clk->prepare_lock);

	return ret;
}

-----

Comments welcome, code coming soon.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01  9:11 ` Jeremy Kerr
  (?)
@ 2011-02-01 10:54   ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-01 10:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Jeremy,

On Tue, Feb 01, 2011 at 05:11:29PM +0800, Jeremy Kerr wrote:
> > I suggested that clk_prepare() be callable only from non-atomic contexts,
> > and do whatever's required to ensure that the clock is available.  That
> > may end up enabling the clock as a result.
> 
> I think that clk_prepare/clk_unprepare looks like the most promising solution, 
> so will try to get some preliminary patches done. Here's what I'm planning:
> 
> -----
> 
> The changes to the API are essentially:
> 
> 1) Document clk_enable/clk_disable as callable from atomic contexts, and
>    so clock implementations must not sleep within this function.
> 
> 2) For clock implementations that may sleep to turn on a clock, we add a
>    new pair of functions to the clock API: clk_prepare and clk_unprepare.
> 
>    These will provide hooks for the clock implmentation to do any sleepable
>    work (eg, wait for PLLs to settle) in preparation for a later clk_enable.
> 
>    For the most common clock implemntation cases (where clocks can be enabled 
>    atomically), these functions will be a no-op, and all of the enable/disable
>    work can be done in clk_enable/clk_disable.
> 
>    For implementations where clocks require blocking on enable/disable, most
>    of the work will be done in clk_prepare/clk_unprepare. The clk_enable
>    and clk_disable functions may be no-ops.
> 
> For drivers, this means that clk_prepare must be called (and have returned) 
> before calling clk_enable.
> 
> = Enable/Prepare counts =
> 
> I intend to do the enable and prepare "counting" in the core clock API, 
> meaning that that the clk_ops callbacks will only invoked on the first 
> prepare/enable and the last unprepare/disable.
> 
> = Concurrency =
> 
> Splitting the prepare and enable stages introduces the concurrency 
> requirements:
> 
> 1) clk_enable must not return before the clock is outputting a valid clock 
>    signal.
> 
> 2) clk_prepare must not return before the clock is fully prepared (ie, it is 
>    safe to call clk_enable).
> 
> It is not possible for clk_enable to wait for the clock to be prepared, 
> because that would require synchronisation with clk_prepare, which may then 
> require blocking. Therefore:
> 
> 3) The clock consumer *must* respect the proper ordering of clk_prepare and 
>    clk_enable. For example, drivers that call clk_enable during an interrupt 
>    must ensure that the interrupt handler will not be invoked until 
>    clk_prepare has returned.
> 
> = Other considerations =
> 
> The time that a clock spends "prepared" is a superset of the the time that a 
> clock spends "enabled". Therefore, clocks that are switched on during 
> clk_prepare (ie, non-atomic clocks) will be running for a larger amount of 
> time. In some cases, this can be mitigated by moving some of the final 
> (atomic) switching functionality to the clk_enable function.
> 
> = Implementation =
> 
> Basically:
> 
> struct clk {
> 	const struct clk_ops *ops
> 	int                  enable_count;
> 	spinlock_t           enable_lock;
> 	int                  prepare_count;
> 	struct mutex         prepare_lock;
> };
> 
> int clk_enable(struct clk *clk)
> {
> 	int ret = 0;
> 
> 	spin_lock(&clk->enable_lock);
> 	if (!clk->enable_count)
> 		ret = clk->ops->enable(clk);
> 
> 	if (!ret)
> 		clk->enable_count++;
> 	spin_unlock(&clk->enable_lock);
> 
> 	return ret;
> }
> 
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0;
> 
> 	mutex_lock(&clk->prepare_lock);
> 	if (!clk->prepare_count)
> 		ret = clk->ops->prepare(clk);
> 
> 	if (!ret)
> 		clk->prepare_count++;
> 	mutex_unlock(&clk->prepare_lock);
> 
> 	return ret;
> }
> 
> -----
> 
> Comments welcome, code coming soon.
Do you plan to handle the case that clk_enable is called while prepare
isn't completed (considering the special case "not called at all")?
Maybe BUG_ON(clk->ops->prepare && !clk->prepare_count)?

Alternatively don't force the sleep in clk_prepare (e.g. by protecting
prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
before calling clk->ops->enable?

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 10:54   ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-01 10:54 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: Russell King, Dima Zavin, Saravana Kannan, Lorenzo Pieralisi,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, linux-kernel,
	Paul Mundt, Ben Dooks, Vincent Guittot, linux-arm-kernel,
	Nicolas Pitre

Hello Jeremy,

On Tue, Feb 01, 2011 at 05:11:29PM +0800, Jeremy Kerr wrote:
> > I suggested that clk_prepare() be callable only from non-atomic contexts,
> > and do whatever's required to ensure that the clock is available.  That
> > may end up enabling the clock as a result.
> 
> I think that clk_prepare/clk_unprepare looks like the most promising solution, 
> so will try to get some preliminary patches done. Here's what I'm planning:
> 
> -----
> 
> The changes to the API are essentially:
> 
> 1) Document clk_enable/clk_disable as callable from atomic contexts, and
>    so clock implementations must not sleep within this function.
> 
> 2) For clock implementations that may sleep to turn on a clock, we add a
>    new pair of functions to the clock API: clk_prepare and clk_unprepare.
> 
>    These will provide hooks for the clock implmentation to do any sleepable
>    work (eg, wait for PLLs to settle) in preparation for a later clk_enable.
> 
>    For the most common clock implemntation cases (where clocks can be enabled 
>    atomically), these functions will be a no-op, and all of the enable/disable
>    work can be done in clk_enable/clk_disable.
> 
>    For implementations where clocks require blocking on enable/disable, most
>    of the work will be done in clk_prepare/clk_unprepare. The clk_enable
>    and clk_disable functions may be no-ops.
> 
> For drivers, this means that clk_prepare must be called (and have returned) 
> before calling clk_enable.
> 
> == Enable/Prepare counts ==
> 
> I intend to do the enable and prepare "counting" in the core clock API, 
> meaning that that the clk_ops callbacks will only invoked on the first 
> prepare/enable and the last unprepare/disable.
> 
> == Concurrency ==
> 
> Splitting the prepare and enable stages introduces the concurrency 
> requirements:
> 
> 1) clk_enable must not return before the clock is outputting a valid clock 
>    signal.
> 
> 2) clk_prepare must not return before the clock is fully prepared (ie, it is 
>    safe to call clk_enable).
> 
> It is not possible for clk_enable to wait for the clock to be prepared, 
> because that would require synchronisation with clk_prepare, which may then 
> require blocking. Therefore:
> 
> 3) The clock consumer *must* respect the proper ordering of clk_prepare and 
>    clk_enable. For example, drivers that call clk_enable during an interrupt 
>    must ensure that the interrupt handler will not be invoked until 
>    clk_prepare has returned.
> 
> == Other considerations ==
> 
> The time that a clock spends "prepared" is a superset of the the time that a 
> clock spends "enabled". Therefore, clocks that are switched on during 
> clk_prepare (ie, non-atomic clocks) will be running for a larger amount of 
> time. In some cases, this can be mitigated by moving some of the final 
> (atomic) switching functionality to the clk_enable function.
> 
> == Implementation ==
> 
> Basically:
> 
> struct clk {
> 	const struct clk_ops *ops
> 	int                  enable_count;
> 	spinlock_t           enable_lock;
> 	int                  prepare_count;
> 	struct mutex         prepare_lock;
> };
> 
> int clk_enable(struct clk *clk)
> {
> 	int ret = 0;
> 
> 	spin_lock(&clk->enable_lock);
> 	if (!clk->enable_count)
> 		ret = clk->ops->enable(clk);
> 
> 	if (!ret)
> 		clk->enable_count++;
> 	spin_unlock(&clk->enable_lock);
> 
> 	return ret;
> }
> 
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0;
> 
> 	mutex_lock(&clk->prepare_lock);
> 	if (!clk->prepare_count)
> 		ret = clk->ops->prepare(clk);
> 
> 	if (!ret)
> 		clk->prepare_count++;
> 	mutex_unlock(&clk->prepare_lock);
> 
> 	return ret;
> }
> 
> -----
> 
> Comments welcome, code coming soon.
Do you plan to handle the case that clk_enable is called while prepare
isn't completed (considering the special case "not called at all")?
Maybe BUG_ON(clk->ops->prepare && !clk->prepare_count)?

Alternatively don't force the sleep in clk_prepare (e.g. by protecting
prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
before calling clk->ops->enable?

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 10:54   ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-01 10:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Jeremy,

On Tue, Feb 01, 2011 at 05:11:29PM +0800, Jeremy Kerr wrote:
> > I suggested that clk_prepare() be callable only from non-atomic contexts,
> > and do whatever's required to ensure that the clock is available.  That
> > may end up enabling the clock as a result.
> 
> I think that clk_prepare/clk_unprepare looks like the most promising solution, 
> so will try to get some preliminary patches done. Here's what I'm planning:
> 
> -----
> 
> The changes to the API are essentially:
> 
> 1) Document clk_enable/clk_disable as callable from atomic contexts, and
>    so clock implementations must not sleep within this function.
> 
> 2) For clock implementations that may sleep to turn on a clock, we add a
>    new pair of functions to the clock API: clk_prepare and clk_unprepare.
> 
>    These will provide hooks for the clock implmentation to do any sleepable
>    work (eg, wait for PLLs to settle) in preparation for a later clk_enable.
> 
>    For the most common clock implemntation cases (where clocks can be enabled 
>    atomically), these functions will be a no-op, and all of the enable/disable
>    work can be done in clk_enable/clk_disable.
> 
>    For implementations where clocks require blocking on enable/disable, most
>    of the work will be done in clk_prepare/clk_unprepare. The clk_enable
>    and clk_disable functions may be no-ops.
> 
> For drivers, this means that clk_prepare must be called (and have returned) 
> before calling clk_enable.
> 
> == Enable/Prepare counts ==
> 
> I intend to do the enable and prepare "counting" in the core clock API, 
> meaning that that the clk_ops callbacks will only invoked on the first 
> prepare/enable and the last unprepare/disable.
> 
> == Concurrency ==
> 
> Splitting the prepare and enable stages introduces the concurrency 
> requirements:
> 
> 1) clk_enable must not return before the clock is outputting a valid clock 
>    signal.
> 
> 2) clk_prepare must not return before the clock is fully prepared (ie, it is 
>    safe to call clk_enable).
> 
> It is not possible for clk_enable to wait for the clock to be prepared, 
> because that would require synchronisation with clk_prepare, which may then 
> require blocking. Therefore:
> 
> 3) The clock consumer *must* respect the proper ordering of clk_prepare and 
>    clk_enable. For example, drivers that call clk_enable during an interrupt 
>    must ensure that the interrupt handler will not be invoked until 
>    clk_prepare has returned.
> 
> == Other considerations ==
> 
> The time that a clock spends "prepared" is a superset of the the time that a 
> clock spends "enabled". Therefore, clocks that are switched on during 
> clk_prepare (ie, non-atomic clocks) will be running for a larger amount of 
> time. In some cases, this can be mitigated by moving some of the final 
> (atomic) switching functionality to the clk_enable function.
> 
> == Implementation ==
> 
> Basically:
> 
> struct clk {
> 	const struct clk_ops *ops
> 	int                  enable_count;
> 	spinlock_t           enable_lock;
> 	int                  prepare_count;
> 	struct mutex         prepare_lock;
> };
> 
> int clk_enable(struct clk *clk)
> {
> 	int ret = 0;
> 
> 	spin_lock(&clk->enable_lock);
> 	if (!clk->enable_count)
> 		ret = clk->ops->enable(clk);
> 
> 	if (!ret)
> 		clk->enable_count++;
> 	spin_unlock(&clk->enable_lock);
> 
> 	return ret;
> }
> 
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0;
> 
> 	mutex_lock(&clk->prepare_lock);
> 	if (!clk->prepare_count)
> 		ret = clk->ops->prepare(clk);
> 
> 	if (!ret)
> 		clk->prepare_count++;
> 	mutex_unlock(&clk->prepare_lock);
> 
> 	return ret;
> }
> 
> -----
> 
> Comments welcome, code coming soon.
Do you plan to handle the case that clk_enable is called while prepare
isn't completed (considering the special case "not called at all")?
Maybe BUG_ON(clk->ops->prepare && !clk->prepare_count)?

Alternatively don't force the sleep in clk_prepare (e.g. by protecting
prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
before calling clk->ops->enable?

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 10:54   ` Uwe Kleine-König
  (?)
@ 2011-02-01 13:05     ` Jassi Brar
  -1 siblings, 0 replies; 383+ messages in thread
From: Jassi Brar @ 2011-02-01 13:05 UTC (permalink / raw)
  To: linux-arm-kernel

2011/2/1 Uwe Kleine-König <u.kleine-koenig@pengutronix.de>:

.....

> Do you plan to handle the case that clk_enable is called while prepare
> isn't completed (considering the special case "not called at all")?
> Maybe BUG_ON(clk->ops->prepare && !clk->prepare_count)?
Sounds better than the second option.

> Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> before calling clk->ops->enable?
That might result in a driver working on some platforms(those have
atomic clk_prepare)
and not on others(those have sleeping).


Njoi!

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 13:05     ` Jassi Brar
  0 siblings, 0 replies; 383+ messages in thread
From: Jassi Brar @ 2011-02-01 13:05 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Jeremy Kerr, Nicolas Pitre, Lorenzo Pieralisi, Russell King,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	linux-kernel, Dima Zavin, Saravana Kannan, Ben Dooks,
	Vincent Guittot, linux-arm-kernel

2011/2/1 Uwe Kleine-König <u.kleine-koenig@pengutronix.de>:

.....

> Do you plan to handle the case that clk_enable is called while prepare
> isn't completed (considering the special case "not called at all")?
> Maybe BUG_ON(clk->ops->prepare && !clk->prepare_count)?
Sounds better than the second option.

> Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> before calling clk->ops->enable?
That might result in a driver working on some platforms(those have
atomic clk_prepare)
and not on others(those have sleeping).


Njoi!

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 13:05     ` Jassi Brar
  0 siblings, 0 replies; 383+ messages in thread
From: Jassi Brar @ 2011-02-01 13:05 UTC (permalink / raw)
  To: linux-arm-kernel

2011/2/1 Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>:

.....

> Do you plan to handle the case that clk_enable is called while prepare
> isn't completed (considering the special case "not called at all")?
> Maybe BUG_ON(clk->ops->prepare && !clk->prepare_count)?
Sounds better than the second option.

> Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> before calling clk->ops->enable?
That might result in a driver working on some platforms(those have
atomic clk_prepare)
and not on others(those have sleeping).


Njoi!

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 10:54   ` Uwe Kleine-König
  (?)
@ 2011-02-01 13:15     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 13:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 11:54:49AM +0100, Uwe Kleine-König wrote:
> Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> before calling clk->ops->enable?

That's a completely bad idea.  I assume you haven't thought about this
very much.

There's two ways I can think of doing what you're suggesting:

int clk_prepare(struct clk *clk)
{
	unsigned long flags;
	int ret = 0;

	might_sleep();

	spin_lock_irqsave(&clk->enable_lock, flags);
	if (clk->prepare_count++ = 0)
		ret = clk->ops->prepare(clk);
	spin_unlock_irqrestore(&clk->enable_clock, flags);

	return ret;
}

The problem is that clk->ops->prepare() is called in a non-sleepable
context.  So this breaks the whole idea of clk_prepare(), and so isn't
a solution.

The other solution is:

int clk_prepare(struct clk *clk)
{
	unsigned long flags;
	int ret = 0;
	bool first;

	might_sleep();

	spin_lock_irqsave(clk->enable_lock, flags);
	first = clk->prepare_count++ = 0;
	spin_unlock_irqrestore(clk->enable_clock, flags);

	if (first)
		ret = clk->ops->prepare(clk);

	return ret;
}

The problem with this is that you now don't have any sane locking on
the prepare callback, and the circumstances under which it's called
are very indefinite.  For example, consider a preempt-enabled system:

	thread 1		thread 2		prepare_count
	clk_prepare					0
	clk->prepare_count++				1
	<thread switch>
				clk_prepare		1
				clk->prepare_count++	2
				clk_prepare returns	2

				clk_enable		2
				<explodes as clock is not prepared>
				<thread switch>
	clk->ops->prepare(clk)

So really, what you're suggesting is completely broken.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 13:15     ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 13:15 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Jeremy Kerr, Dima Zavin, Saravana Kannan, Lorenzo Pieralisi,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, linux-kernel,
	Paul Mundt, Ben Dooks, Vincent Guittot, linux-arm-kernel,
	Nicolas Pitre

On Tue, Feb 01, 2011 at 11:54:49AM +0100, Uwe Kleine-König wrote:
> Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> before calling clk->ops->enable?

That's a completely bad idea.  I assume you haven't thought about this
very much.

There's two ways I can think of doing what you're suggesting:

int clk_prepare(struct clk *clk)
{
	unsigned long flags;
	int ret = 0;

	might_sleep();

	spin_lock_irqsave(&clk->enable_lock, flags);
	if (clk->prepare_count++ == 0)
		ret = clk->ops->prepare(clk);
	spin_unlock_irqrestore(&clk->enable_clock, flags);

	return ret;
}

The problem is that clk->ops->prepare() is called in a non-sleepable
context.  So this breaks the whole idea of clk_prepare(), and so isn't
a solution.

The other solution is:

int clk_prepare(struct clk *clk)
{
	unsigned long flags;
	int ret = 0;
	bool first;

	might_sleep();

	spin_lock_irqsave(clk->enable_lock, flags);
	first = clk->prepare_count++ == 0;
	spin_unlock_irqrestore(clk->enable_clock, flags);

	if (first)
		ret = clk->ops->prepare(clk);

	return ret;
}

The problem with this is that you now don't have any sane locking on
the prepare callback, and the circumstances under which it's called
are very indefinite.  For example, consider a preempt-enabled system:

	thread 1		thread 2		prepare_count
	clk_prepare					0
	clk->prepare_count++				1
	<thread switch>
				clk_prepare		1
				clk->prepare_count++	2
				clk_prepare returns	2

				clk_enable		2
				<explodes as clock is not prepared>
				<thread switch>
	clk->ops->prepare(clk)

So really, what you're suggesting is completely broken.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 13:15     ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 13:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 11:54:49AM +0100, Uwe Kleine-K?nig wrote:
> Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> before calling clk->ops->enable?

That's a completely bad idea.  I assume you haven't thought about this
very much.

There's two ways I can think of doing what you're suggesting:

int clk_prepare(struct clk *clk)
{
	unsigned long flags;
	int ret = 0;

	might_sleep();

	spin_lock_irqsave(&clk->enable_lock, flags);
	if (clk->prepare_count++ == 0)
		ret = clk->ops->prepare(clk);
	spin_unlock_irqrestore(&clk->enable_clock, flags);

	return ret;
}

The problem is that clk->ops->prepare() is called in a non-sleepable
context.  So this breaks the whole idea of clk_prepare(), and so isn't
a solution.

The other solution is:

int clk_prepare(struct clk *clk)
{
	unsigned long flags;
	int ret = 0;
	bool first;

	might_sleep();

	spin_lock_irqsave(clk->enable_lock, flags);
	first = clk->prepare_count++ == 0;
	spin_unlock_irqrestore(clk->enable_clock, flags);

	if (first)
		ret = clk->ops->prepare(clk);

	return ret;
}

The problem with this is that you now don't have any sane locking on
the prepare callback, and the circumstances under which it's called
are very indefinite.  For example, consider a preempt-enabled system:

	thread 1		thread 2		prepare_count
	clk_prepare					0
	clk->prepare_count++				1
	<thread switch>
				clk_prepare		1
				clk->prepare_count++	2
				clk_prepare returns	2

				clk_enable		2
				<explodes as clock is not prepared>
				<thread switch>
	clk->ops->prepare(clk)

So really, what you're suggesting is completely broken.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 13:05     ` Jassi Brar
  (?)
@ 2011-02-01 14:00       ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-01 14:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 10:05:56PM +0900, Jassi Brar wrote:
> 2011/2/1 Uwe Kleine-König <u.kleine-koenig@pengutronix.de>:
> 
> .....
> 
> > Do you plan to handle the case that clk_enable is called while prepare
> > isn't completed (considering the special case "not called at all")?
> > Maybe BUG_ON(clk->ops->prepare && !clk->prepare_count)?
> Sounds better than the second option.
> 
> > Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> > prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> > before calling clk->ops->enable?
> That might result in a driver working on some platforms(those have
> atomic clk_prepare)
> and not on others(those have sleeping).
The first option has the same result.  E.g. on some platforms
clk->ops->prepare might be NULL, on others it's not.

Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 14:00       ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-01 14:00 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Jeremy Kerr, Nicolas Pitre, Lorenzo Pieralisi, Russell King,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	linux-kernel, Dima Zavin, Saravana Kannan, Ben Dooks,
	Vincent Guittot, linux-arm-kernel

On Tue, Feb 01, 2011 at 10:05:56PM +0900, Jassi Brar wrote:
> 2011/2/1 Uwe Kleine-König <u.kleine-koenig@pengutronix.de>:
> 
> .....
> 
> > Do you plan to handle the case that clk_enable is called while prepare
> > isn't completed (considering the special case "not called at all")?
> > Maybe BUG_ON(clk->ops->prepare && !clk->prepare_count)?
> Sounds better than the second option.
> 
> > Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> > prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> > before calling clk->ops->enable?
> That might result in a driver working on some platforms(those have
> atomic clk_prepare)
> and not on others(those have sleeping).
The first option has the same result.  E.g. on some platforms
clk->ops->prepare might be NULL, on others it's not.

Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 14:00       ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-01 14:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 10:05:56PM +0900, Jassi Brar wrote:
> 2011/2/1 Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>:
> 
> .....
> 
> > Do you plan to handle the case that clk_enable is called while prepare
> > isn't completed (considering the special case "not called at all")?
> > Maybe BUG_ON(clk->ops->prepare && !clk->prepare_count)?
> Sounds better than the second option.
> 
> > Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> > prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> > before calling clk->ops->enable?
> That might result in a driver working on some platforms(those have
> atomic clk_prepare)
> and not on others(those have sleeping).
The first option has the same result.  E.g. on some platforms
clk->ops->prepare might be NULL, on others it's not.

Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 13:15     ` Russell King - ARM Linux
  (?)
@ 2011-02-01 14:18       ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-01 14:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 01:15:12PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 11:54:49AM +0100, Uwe Kleine-König wrote:
> > Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> > prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> > before calling clk->ops->enable?
> 
> That's a completely bad idea.  I assume you haven't thought about this
> very much.
Right, but I thought it a bit further than you did.  Like the following:
 
int clk_prepare(struct clk *clk)
{
	int ret = 0, first;
	unsigned long flags;

	spin_lock_irqsave(&clk->enable_lock, flags);
	if (clk->flags & CLK_BUSY) {
		/* 
		 * this must not happen, please serialize calls to
		 * clk_prepare/clk_enable
		 */
		ret = -EBUSY;
		goto out_unlock;
	}
	first = clk->prepare_count++ = 0;
	if (first)
		clk->flags |= CLK_BUSY;
	spin_unlock_irqrestore(&clk->enable_lock, flags);

	if (!first)
		return 0;

	if (clk->ops->prepare) {
		might_sleep();
		ret = clk->ops->prepare(clk);
	}

	spin_lock_irqsave(&clk->enable_lock, flags);
	clk->flags &= ~CLK_BUSY;
	if (ret)
		clk->prepare_count--;
out_unlock:
	spin_unlock_irqrestore(&clk->enable_lock, flags);

	return ret;
}

If you now find a problem with that you can blame me not having thought
it to an end.

And note, this is only a suggestion.  I.e. I don't know what is the best
to do in the case where I implemented returning -EBUSY above.  BUG?
Wait for CLK_BUSY to be cleared?

I'm not sure I like "clk_prepare sleeps iff unprepared but preparable".
Still I think the approach is worth to be discussed.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 14:18       ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-01 14:18 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Jeremy Kerr, Dima Zavin, Saravana Kannan, Lorenzo Pieralisi,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, linux-kernel,
	Paul Mundt, Ben Dooks, Vincent Guittot, linux-arm-kernel,
	Nicolas Pitre

On Tue, Feb 01, 2011 at 01:15:12PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 11:54:49AM +0100, Uwe Kleine-König wrote:
> > Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> > prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> > before calling clk->ops->enable?
> 
> That's a completely bad idea.  I assume you haven't thought about this
> very much.
Right, but I thought it a bit further than you did.  Like the following:
 
int clk_prepare(struct clk *clk)
{
	int ret = 0, first;
	unsigned long flags;

	spin_lock_irqsave(&clk->enable_lock, flags);
	if (clk->flags & CLK_BUSY) {
		/* 
		 * this must not happen, please serialize calls to
		 * clk_prepare/clk_enable
		 */
		ret = -EBUSY;
		goto out_unlock;
	}
	first = clk->prepare_count++ == 0;
	if (first)
		clk->flags |= CLK_BUSY;
	spin_unlock_irqrestore(&clk->enable_lock, flags);

	if (!first)
		return 0;

	if (clk->ops->prepare) {
		might_sleep();
		ret = clk->ops->prepare(clk);
	}

	spin_lock_irqsave(&clk->enable_lock, flags);
	clk->flags &= ~CLK_BUSY;
	if (ret)
		clk->prepare_count--;
out_unlock:
	spin_unlock_irqrestore(&clk->enable_lock, flags);

	return ret;
}

If you now find a problem with that you can blame me not having thought
it to an end.

And note, this is only a suggestion.  I.e. I don't know what is the best
to do in the case where I implemented returning -EBUSY above.  BUG?
Wait for CLK_BUSY to be cleared?

I'm not sure I like "clk_prepare sleeps iff unprepared but preparable".
Still I think the approach is worth to be discussed.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 14:18       ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-01 14:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 01:15:12PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 11:54:49AM +0100, Uwe Kleine-K?nig wrote:
> > Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> > prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> > before calling clk->ops->enable?
> 
> That's a completely bad idea.  I assume you haven't thought about this
> very much.
Right, but I thought it a bit further than you did.  Like the following:
 
int clk_prepare(struct clk *clk)
{
	int ret = 0, first;
	unsigned long flags;

	spin_lock_irqsave(&clk->enable_lock, flags);
	if (clk->flags & CLK_BUSY) {
		/* 
		 * this must not happen, please serialize calls to
		 * clk_prepare/clk_enable
		 */
		ret = -EBUSY;
		goto out_unlock;
	}
	first = clk->prepare_count++ == 0;
	if (first)
		clk->flags |= CLK_BUSY;
	spin_unlock_irqrestore(&clk->enable_lock, flags);

	if (!first)
		return 0;

	if (clk->ops->prepare) {
		might_sleep();
		ret = clk->ops->prepare(clk);
	}

	spin_lock_irqsave(&clk->enable_lock, flags);
	clk->flags &= ~CLK_BUSY;
	if (ret)
		clk->prepare_count--;
out_unlock:
	spin_unlock_irqrestore(&clk->enable_lock, flags);

	return ret;
}

If you now find a problem with that you can blame me not having thought
it to an end.

And note, this is only a suggestion.  I.e. I don't know what is the best
to do in the case where I implemented returning -EBUSY above.  BUG?
Wait for CLK_BUSY to be cleared?

I'm not sure I like "clk_prepare sleeps iff unprepared but preparable".
Still I think the approach is worth to be discussed.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 14:18       ` Uwe Kleine-König
  (?)
@ 2011-02-01 14:39         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 14:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 03:18:37PM +0100, Uwe Kleine-König wrote:
> On Tue, Feb 01, 2011 at 01:15:12PM +0000, Russell King - ARM Linux wrote:
> > On Tue, Feb 01, 2011 at 11:54:49AM +0100, Uwe Kleine-König wrote:
> > > Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> > > prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> > > before calling clk->ops->enable?
> > 
> > That's a completely bad idea.  I assume you haven't thought about this
> > very much.
> Right, but I thought it a bit further than you did.  Like the following:
>  
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0, first;
> 	unsigned long flags;
> 
> 	spin_lock_irqsave(&clk->enable_lock, flags);
> 	if (clk->flags & CLK_BUSY) {
> 		/* 
> 		 * this must not happen, please serialize calls to
> 		 * clk_prepare/clk_enable
> 		 */

How do different drivers serialize calls to clk_prepare?  Are you
really suggesting that we should have a global mutex somewhere to
prevent this?

> 		ret = -EBUSY;
> 		goto out_unlock;
> 	}
> 	first = clk->prepare_count++ = 0;
> 	if (first)
> 		clk->flags |= CLK_BUSY;
> 	spin_unlock_irqrestore(&clk->enable_lock, flags);
> 
> 	if (!first)
> 		return 0;
> 
> 	if (clk->ops->prepare) {
> 		might_sleep();
> 		ret = clk->ops->prepare(clk);
> 	}
> 
> 	spin_lock_irqsave(&clk->enable_lock, flags);
> 	clk->flags &= ~CLK_BUSY;
> 	if (ret)
> 		clk->prepare_count--;
> out_unlock:
> 	spin_unlock_irqrestore(&clk->enable_lock, flags);
> 
> 	return ret;
> }
> 
> If you now find a problem with that you can blame me not having thought
> it to an end.
> 
> And note, this is only a suggestion.  I.e. I don't know what is the best
> to do in the case where I implemented returning -EBUSY above.  BUG?
> Wait for CLK_BUSY to be cleared?

So what're you proposing that a driver writer should do when he sees
-EBUSY returned from this function?  Abandon the probe() returning -EBUSY
and hope the user retries later?  Or maybe:

	do {
		err = clk_prepare(clk);
	} while (err = -EBUSY);

?

I don't think that's reasonable to offload this onto driver writers, who
already have a big enough problem already.  The less complexity that
driver writers have to deal with, the better.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 14:39         ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 14:39 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Jeremy Kerr, Dima Zavin, Saravana Kannan, Lorenzo Pieralisi,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, linux-kernel,
	Paul Mundt, Ben Dooks, Vincent Guittot, linux-arm-kernel,
	Nicolas Pitre

On Tue, Feb 01, 2011 at 03:18:37PM +0100, Uwe Kleine-König wrote:
> On Tue, Feb 01, 2011 at 01:15:12PM +0000, Russell King - ARM Linux wrote:
> > On Tue, Feb 01, 2011 at 11:54:49AM +0100, Uwe Kleine-König wrote:
> > > Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> > > prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> > > before calling clk->ops->enable?
> > 
> > That's a completely bad idea.  I assume you haven't thought about this
> > very much.
> Right, but I thought it a bit further than you did.  Like the following:
>  
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0, first;
> 	unsigned long flags;
> 
> 	spin_lock_irqsave(&clk->enable_lock, flags);
> 	if (clk->flags & CLK_BUSY) {
> 		/* 
> 		 * this must not happen, please serialize calls to
> 		 * clk_prepare/clk_enable
> 		 */

How do different drivers serialize calls to clk_prepare?  Are you
really suggesting that we should have a global mutex somewhere to
prevent this?

> 		ret = -EBUSY;
> 		goto out_unlock;
> 	}
> 	first = clk->prepare_count++ == 0;
> 	if (first)
> 		clk->flags |= CLK_BUSY;
> 	spin_unlock_irqrestore(&clk->enable_lock, flags);
> 
> 	if (!first)
> 		return 0;
> 
> 	if (clk->ops->prepare) {
> 		might_sleep();
> 		ret = clk->ops->prepare(clk);
> 	}
> 
> 	spin_lock_irqsave(&clk->enable_lock, flags);
> 	clk->flags &= ~CLK_BUSY;
> 	if (ret)
> 		clk->prepare_count--;
> out_unlock:
> 	spin_unlock_irqrestore(&clk->enable_lock, flags);
> 
> 	return ret;
> }
> 
> If you now find a problem with that you can blame me not having thought
> it to an end.
> 
> And note, this is only a suggestion.  I.e. I don't know what is the best
> to do in the case where I implemented returning -EBUSY above.  BUG?
> Wait for CLK_BUSY to be cleared?

So what're you proposing that a driver writer should do when he sees
-EBUSY returned from this function?  Abandon the probe() returning -EBUSY
and hope the user retries later?  Or maybe:

	do {
		err = clk_prepare(clk);
	} while (err == -EBUSY);

?

I don't think that's reasonable to offload this onto driver writers, who
already have a big enough problem already.  The less complexity that
driver writers have to deal with, the better.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 14:39         ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 14:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 03:18:37PM +0100, Uwe Kleine-K?nig wrote:
> On Tue, Feb 01, 2011 at 01:15:12PM +0000, Russell King - ARM Linux wrote:
> > On Tue, Feb 01, 2011 at 11:54:49AM +0100, Uwe Kleine-K?nig wrote:
> > > Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> > > prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> > > before calling clk->ops->enable?
> > 
> > That's a completely bad idea.  I assume you haven't thought about this
> > very much.
> Right, but I thought it a bit further than you did.  Like the following:
>  
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0, first;
> 	unsigned long flags;
> 
> 	spin_lock_irqsave(&clk->enable_lock, flags);
> 	if (clk->flags & CLK_BUSY) {
> 		/* 
> 		 * this must not happen, please serialize calls to
> 		 * clk_prepare/clk_enable
> 		 */

How do different drivers serialize calls to clk_prepare?  Are you
really suggesting that we should have a global mutex somewhere to
prevent this?

> 		ret = -EBUSY;
> 		goto out_unlock;
> 	}
> 	first = clk->prepare_count++ == 0;
> 	if (first)
> 		clk->flags |= CLK_BUSY;
> 	spin_unlock_irqrestore(&clk->enable_lock, flags);
> 
> 	if (!first)
> 		return 0;
> 
> 	if (clk->ops->prepare) {
> 		might_sleep();
> 		ret = clk->ops->prepare(clk);
> 	}
> 
> 	spin_lock_irqsave(&clk->enable_lock, flags);
> 	clk->flags &= ~CLK_BUSY;
> 	if (ret)
> 		clk->prepare_count--;
> out_unlock:
> 	spin_unlock_irqrestore(&clk->enable_lock, flags);
> 
> 	return ret;
> }
> 
> If you now find a problem with that you can blame me not having thought
> it to an end.
> 
> And note, this is only a suggestion.  I.e. I don't know what is the best
> to do in the case where I implemented returning -EBUSY above.  BUG?
> Wait for CLK_BUSY to be cleared?

So what're you proposing that a driver writer should do when he sees
-EBUSY returned from this function?  Abandon the probe() returning -EBUSY
and hope the user retries later?  Or maybe:

	do {
		err = clk_prepare(clk);
	} while (err == -EBUSY);

?

I don't think that's reasonable to offload this onto driver writers, who
already have a big enough problem already.  The less complexity that
driver writers have to deal with, the better.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 14:18       ` Uwe Kleine-König
  (?)
@ 2011-02-01 14:40         ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-01 14:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Uwe,

Thanks for the feedback, I'm not sure I like the more complex approach though:

> Right, but I thought it a bit further than you did.  Like the following:
> 
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0, first;
> 	unsigned long flags;
> 
> 	spin_lock_irqsave(&clk->enable_lock, flags);
> 	if (clk->flags & CLK_BUSY) {
> 		/*
> 		 * this must not happen, please serialize calls to
> 		 * clk_prepare/clk_enable
> 		 */
> 		ret = -EBUSY;
> 		goto out_unlock;

Why is this an error? Two separate drivers may be clk_prepare()-ing at the 
same time, which should be acceptable. Both calls should block until the 
prepare is complete.

> 	}
> 	first = clk->prepare_count++ = 0;
> 	if (first)
> 		clk->flags |= CLK_BUSY;
> 	spin_unlock_irqrestore(&clk->enable_lock, flags);
> 
> 	if (!first)
> 		return 0;
> 
> 	if (clk->ops->prepare) {
> 		might_sleep();
> 		ret = clk->ops->prepare(clk);
> 	}
> 
> 	spin_lock_irqsave(&clk->enable_lock, flags);
> 	clk->flags &= ~CLK_BUSY;
> 	if (ret)
> 		clk->prepare_count--;
> out_unlock:
> 	spin_unlock_irqrestore(&clk->enable_lock, flags);
> 
> 	return ret;
> }

Cheers,


Jeremy


^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 14:40         ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-01 14:40 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Russell King - ARM Linux, Dima Zavin, Saravana Kannan,
	Lorenzo Pieralisi, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	linux-kernel, Paul Mundt, Ben Dooks, Vincent Guittot,
	linux-arm-kernel, Nicolas Pitre

Hi Uwe,

Thanks for the feedback, I'm not sure I like the more complex approach though:

> Right, but I thought it a bit further than you did.  Like the following:
> 
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0, first;
> 	unsigned long flags;
> 
> 	spin_lock_irqsave(&clk->enable_lock, flags);
> 	if (clk->flags & CLK_BUSY) {
> 		/*
> 		 * this must not happen, please serialize calls to
> 		 * clk_prepare/clk_enable
> 		 */
> 		ret = -EBUSY;
> 		goto out_unlock;

Why is this an error? Two separate drivers may be clk_prepare()-ing at the 
same time, which should be acceptable. Both calls should block until the 
prepare is complete.

> 	}
> 	first = clk->prepare_count++ == 0;
> 	if (first)
> 		clk->flags |= CLK_BUSY;
> 	spin_unlock_irqrestore(&clk->enable_lock, flags);
> 
> 	if (!first)
> 		return 0;
> 
> 	if (clk->ops->prepare) {
> 		might_sleep();
> 		ret = clk->ops->prepare(clk);
> 	}
> 
> 	spin_lock_irqsave(&clk->enable_lock, flags);
> 	clk->flags &= ~CLK_BUSY;
> 	if (ret)
> 		clk->prepare_count--;
> out_unlock:
> 	spin_unlock_irqrestore(&clk->enable_lock, flags);
> 
> 	return ret;
> }

Cheers,


Jeremy


^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 14:40         ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-01 14:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Uwe,

Thanks for the feedback, I'm not sure I like the more complex approach though:

> Right, but I thought it a bit further than you did.  Like the following:
> 
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0, first;
> 	unsigned long flags;
> 
> 	spin_lock_irqsave(&clk->enable_lock, flags);
> 	if (clk->flags & CLK_BUSY) {
> 		/*
> 		 * this must not happen, please serialize calls to
> 		 * clk_prepare/clk_enable
> 		 */
> 		ret = -EBUSY;
> 		goto out_unlock;

Why is this an error? Two separate drivers may be clk_prepare()-ing at the 
same time, which should be acceptable. Both calls should block until the 
prepare is complete.

> 	}
> 	first = clk->prepare_count++ == 0;
> 	if (first)
> 		clk->flags |= CLK_BUSY;
> 	spin_unlock_irqrestore(&clk->enable_lock, flags);
> 
> 	if (!first)
> 		return 0;
> 
> 	if (clk->ops->prepare) {
> 		might_sleep();
> 		ret = clk->ops->prepare(clk);
> 	}
> 
> 	spin_lock_irqsave(&clk->enable_lock, flags);
> 	clk->flags &= ~CLK_BUSY;
> 	if (ret)
> 		clk->prepare_count--;
> out_unlock:
> 	spin_unlock_irqrestore(&clk->enable_lock, flags);
> 
> 	return ret;
> }

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 14:00       ` Uwe Kleine-König
  (?)
@ 2011-02-01 15:14         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 15:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 03:00:24PM +0100, Uwe Kleine-König wrote:
> On Tue, Feb 01, 2011 at 10:05:56PM +0900, Jassi Brar wrote:
> > 2011/2/1 Uwe Kleine-König <u.kleine-koenig@pengutronix.de>:
> > 
> > .....
> > 
> > > Do you plan to handle the case that clk_enable is called while prepare
> > > isn't completed (considering the special case "not called at all")?
> > > Maybe BUG_ON(clk->ops->prepare && !clk->prepare_count)?
> > Sounds better than the second option.
> > 
> > > Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> > > prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> > > before calling clk->ops->enable?
> > That might result in a driver working on some platforms(those have
> > atomic clk_prepare)
> > and not on others(those have sleeping).
> The first option has the same result.  E.g. on some platforms
> clk->ops->prepare might be NULL, on others it's not.

If clk->ops->prepare is NULL, then clk_prepare() better return success
as it should mean "no preparation necessary", not "someone didn't
implement it so its an error".

Calling clk->ops->enable() with a spinlock held will ensure that no one
tries to make that method sleep, so if people want sleeping stuff they
have to use the clk_prepare() stuff.  It's a self-enforcing API which
ensures that we don't get sleeping stuff inside clk_enable().

And with a check in clk_enable() for a preparation, it helps to ensure
that drivers do call clk_prepare() before clk_enable() - though it can't
guarantee it in every case.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 15:14         ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 15:14 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Jassi Brar, Jeremy Kerr, Nicolas Pitre, Lorenzo Pieralisi,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	linux-kernel, Dima Zavin, Saravana Kannan, Ben Dooks,
	Vincent Guittot, linux-arm-kernel

On Tue, Feb 01, 2011 at 03:00:24PM +0100, Uwe Kleine-König wrote:
> On Tue, Feb 01, 2011 at 10:05:56PM +0900, Jassi Brar wrote:
> > 2011/2/1 Uwe Kleine-König <u.kleine-koenig@pengutronix.de>:
> > 
> > .....
> > 
> > > Do you plan to handle the case that clk_enable is called while prepare
> > > isn't completed (considering the special case "not called at all")?
> > > Maybe BUG_ON(clk->ops->prepare && !clk->prepare_count)?
> > Sounds better than the second option.
> > 
> > > Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> > > prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> > > before calling clk->ops->enable?
> > That might result in a driver working on some platforms(those have
> > atomic clk_prepare)
> > and not on others(those have sleeping).
> The first option has the same result.  E.g. on some platforms
> clk->ops->prepare might be NULL, on others it's not.

If clk->ops->prepare is NULL, then clk_prepare() better return success
as it should mean "no preparation necessary", not "someone didn't
implement it so its an error".

Calling clk->ops->enable() with a spinlock held will ensure that no one
tries to make that method sleep, so if people want sleeping stuff they
have to use the clk_prepare() stuff.  It's a self-enforcing API which
ensures that we don't get sleeping stuff inside clk_enable().

And with a check in clk_enable() for a preparation, it helps to ensure
that drivers do call clk_prepare() before clk_enable() - though it can't
guarantee it in every case.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 15:14         ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 15:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 03:00:24PM +0100, Uwe Kleine-K?nig wrote:
> On Tue, Feb 01, 2011 at 10:05:56PM +0900, Jassi Brar wrote:
> > 2011/2/1 Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>:
> > 
> > .....
> > 
> > > Do you plan to handle the case that clk_enable is called while prepare
> > > isn't completed (considering the special case "not called at all")?
> > > Maybe BUG_ON(clk->ops->prepare && !clk->prepare_count)?
> > Sounds better than the second option.
> > 
> > > Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> > > prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> > > before calling clk->ops->enable?
> > That might result in a driver working on some platforms(those have
> > atomic clk_prepare)
> > and not on others(those have sleeping).
> The first option has the same result.  E.g. on some platforms
> clk->ops->prepare might be NULL, on others it's not.

If clk->ops->prepare is NULL, then clk_prepare() better return success
as it should mean "no preparation necessary", not "someone didn't
implement it so its an error".

Calling clk->ops->enable() with a spinlock held will ensure that no one
tries to make that method sleep, so if people want sleeping stuff they
have to use the clk_prepare() stuff.  It's a self-enforcing API which
ensures that we don't get sleeping stuff inside clk_enable().

And with a check in clk_enable() for a preparation, it helps to ensure
that drivers do call clk_prepare() before clk_enable() - though it can't
guarantee it in every case.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 14:39         ` Russell King - ARM Linux
  (?)
@ 2011-02-01 15:18           ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-01 15:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 02:39:32PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 03:18:37PM +0100, Uwe Kleine-König wrote:
> > On Tue, Feb 01, 2011 at 01:15:12PM +0000, Russell King - ARM Linux wrote:
> > > On Tue, Feb 01, 2011 at 11:54:49AM +0100, Uwe Kleine-König wrote:
> > > > Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> > > > prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> > > > before calling clk->ops->enable?
> > > 
> > > That's a completely bad idea.  I assume you haven't thought about this
> > > very much.
> > Right, but I thought it a bit further than you did.  Like the following:
> >  
> > int clk_prepare(struct clk *clk)
> > {
> > 	int ret = 0, first;
> > 	unsigned long flags;
> > 
> > 	spin_lock_irqsave(&clk->enable_lock, flags);
> > 	if (clk->flags & CLK_BUSY) {
> > 		/* 
> > 		 * this must not happen, please serialize calls to
> > 		 * clk_prepare/clk_enable
> > 		 */
> 
> How do different drivers serialize calls to clk_prepare?  Are you
> really suggesting that we should have a global mutex somewhere to
> prevent this?
yeah, didn't thought about multiple consumers, so (as Jeremy suggested)
the right thing is to sleep until CLK_BUSY is cleared.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 15:18           ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-01 15:18 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Jeremy Kerr, Dima Zavin, Saravana Kannan, Lorenzo Pieralisi,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, linux-kernel,
	Paul Mundt, Ben Dooks, Vincent Guittot, linux-arm-kernel,
	Nicolas Pitre

On Tue, Feb 01, 2011 at 02:39:32PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 03:18:37PM +0100, Uwe Kleine-König wrote:
> > On Tue, Feb 01, 2011 at 01:15:12PM +0000, Russell King - ARM Linux wrote:
> > > On Tue, Feb 01, 2011 at 11:54:49AM +0100, Uwe Kleine-König wrote:
> > > > Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> > > > prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> > > > before calling clk->ops->enable?
> > > 
> > > That's a completely bad idea.  I assume you haven't thought about this
> > > very much.
> > Right, but I thought it a bit further than you did.  Like the following:
> >  
> > int clk_prepare(struct clk *clk)
> > {
> > 	int ret = 0, first;
> > 	unsigned long flags;
> > 
> > 	spin_lock_irqsave(&clk->enable_lock, flags);
> > 	if (clk->flags & CLK_BUSY) {
> > 		/* 
> > 		 * this must not happen, please serialize calls to
> > 		 * clk_prepare/clk_enable
> > 		 */
> 
> How do different drivers serialize calls to clk_prepare?  Are you
> really suggesting that we should have a global mutex somewhere to
> prevent this?
yeah, didn't thought about multiple consumers, so (as Jeremy suggested)
the right thing is to sleep until CLK_BUSY is cleared.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 15:18           ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-01 15:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 02:39:32PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 03:18:37PM +0100, Uwe Kleine-K?nig wrote:
> > On Tue, Feb 01, 2011 at 01:15:12PM +0000, Russell King - ARM Linux wrote:
> > > On Tue, Feb 01, 2011 at 11:54:49AM +0100, Uwe Kleine-K?nig wrote:
> > > > Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> > > > prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> > > > before calling clk->ops->enable?
> > > 
> > > That's a completely bad idea.  I assume you haven't thought about this
> > > very much.
> > Right, but I thought it a bit further than you did.  Like the following:
> >  
> > int clk_prepare(struct clk *clk)
> > {
> > 	int ret = 0, first;
> > 	unsigned long flags;
> > 
> > 	spin_lock_irqsave(&clk->enable_lock, flags);
> > 	if (clk->flags & CLK_BUSY) {
> > 		/* 
> > 		 * this must not happen, please serialize calls to
> > 		 * clk_prepare/clk_enable
> > 		 */
> 
> How do different drivers serialize calls to clk_prepare?  Are you
> really suggesting that we should have a global mutex somewhere to
> prevent this?
yeah, didn't thought about multiple consumers, so (as Jeremy suggested)
the right thing is to sleep until CLK_BUSY is cleared.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 15:14         ` Russell King - ARM Linux
  (?)
@ 2011-02-01 15:22           ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-01 15:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 03:14:18PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 03:00:24PM +0100, Uwe Kleine-König wrote:
> > On Tue, Feb 01, 2011 at 10:05:56PM +0900, Jassi Brar wrote:
> > > 2011/2/1 Uwe Kleine-König <u.kleine-koenig@pengutronix.de>:
> > > 
> > > .....
> > > 
> > > > Do you plan to handle the case that clk_enable is called while prepare
> > > > isn't completed (considering the special case "not called at all")?
> > > > Maybe BUG_ON(clk->ops->prepare && !clk->prepare_count)?
> > > Sounds better than the second option.
> > > 
> > > > Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> > > > prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> > > > before calling clk->ops->enable?
> > > That might result in a driver working on some platforms(those have
> > > atomic clk_prepare)
> > > and not on others(those have sleeping).
> > The first option has the same result.  E.g. on some platforms
> > clk->ops->prepare might be NULL, on others it's not.
> 
> If clk->ops->prepare is NULL, then clk_prepare() better return success
> as it should mean "no preparation necessary", not "someone didn't
> implement it so its an error".
> 
> Calling clk->ops->enable() with a spinlock held will ensure that no one
> tries to make that method sleep, so if people want sleeping stuff they
> have to use the clk_prepare() stuff.  It's a self-enforcing API which
> ensures that we don't get sleeping stuff inside clk_enable().
> 
> And with a check in clk_enable() for a preparation, it helps to ensure
> that drivers do call clk_prepare() before clk_enable() - though it can't
> guarantee it in every case.
Full ack.  (I wonder if you misunderstood me or wanted to put my
statement into more words.  Jassi didn't like that a clk_enable without
a previous clk_prepare worked on some platforms and on others it
doesn't.  With BUG_ON(clk->ops->prepare && !clk->prepare_count) in
clk_enable we have exactly this situation.)

Best regards
Uwe


-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 15:22           ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-01 15:22 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Jassi Brar, Jeremy Kerr, Nicolas Pitre, Lorenzo Pieralisi,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	linux-kernel, Dima Zavin, Saravana Kannan, Ben Dooks,
	Vincent Guittot, linux-arm-kernel

On Tue, Feb 01, 2011 at 03:14:18PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 03:00:24PM +0100, Uwe Kleine-König wrote:
> > On Tue, Feb 01, 2011 at 10:05:56PM +0900, Jassi Brar wrote:
> > > 2011/2/1 Uwe Kleine-König <u.kleine-koenig@pengutronix.de>:
> > > 
> > > .....
> > > 
> > > > Do you plan to handle the case that clk_enable is called while prepare
> > > > isn't completed (considering the special case "not called at all")?
> > > > Maybe BUG_ON(clk->ops->prepare && !clk->prepare_count)?
> > > Sounds better than the second option.
> > > 
> > > > Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> > > > prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> > > > before calling clk->ops->enable?
> > > That might result in a driver working on some platforms(those have
> > > atomic clk_prepare)
> > > and not on others(those have sleeping).
> > The first option has the same result.  E.g. on some platforms
> > clk->ops->prepare might be NULL, on others it's not.
> 
> If clk->ops->prepare is NULL, then clk_prepare() better return success
> as it should mean "no preparation necessary", not "someone didn't
> implement it so its an error".
> 
> Calling clk->ops->enable() with a spinlock held will ensure that no one
> tries to make that method sleep, so if people want sleeping stuff they
> have to use the clk_prepare() stuff.  It's a self-enforcing API which
> ensures that we don't get sleeping stuff inside clk_enable().
> 
> And with a check in clk_enable() for a preparation, it helps to ensure
> that drivers do call clk_prepare() before clk_enable() - though it can't
> guarantee it in every case.
Full ack.  (I wonder if you misunderstood me or wanted to put my
statement into more words.  Jassi didn't like that a clk_enable without
a previous clk_prepare worked on some platforms and on others it
doesn't.  With BUG_ON(clk->ops->prepare && !clk->prepare_count) in
clk_enable we have exactly this situation.)

Best regards
Uwe


-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 15:22           ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-01 15:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 03:14:18PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 03:00:24PM +0100, Uwe Kleine-K?nig wrote:
> > On Tue, Feb 01, 2011 at 10:05:56PM +0900, Jassi Brar wrote:
> > > 2011/2/1 Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>:
> > > 
> > > .....
> > > 
> > > > Do you plan to handle the case that clk_enable is called while prepare
> > > > isn't completed (considering the special case "not called at all")?
> > > > Maybe BUG_ON(clk->ops->prepare && !clk->prepare_count)?
> > > Sounds better than the second option.
> > > 
> > > > Alternatively don't force the sleep in clk_prepare (e.g. by protecting
> > > > prepare_count by a spinlock (probably enable_lock)) and call clk_prepare
> > > > before calling clk->ops->enable?
> > > That might result in a driver working on some platforms(those have
> > > atomic clk_prepare)
> > > and not on others(those have sleeping).
> > The first option has the same result.  E.g. on some platforms
> > clk->ops->prepare might be NULL, on others it's not.
> 
> If clk->ops->prepare is NULL, then clk_prepare() better return success
> as it should mean "no preparation necessary", not "someone didn't
> implement it so its an error".
> 
> Calling clk->ops->enable() with a spinlock held will ensure that no one
> tries to make that method sleep, so if people want sleeping stuff they
> have to use the clk_prepare() stuff.  It's a self-enforcing API which
> ensures that we don't get sleeping stuff inside clk_enable().
> 
> And with a check in clk_enable() for a preparation, it helps to ensure
> that drivers do call clk_prepare() before clk_enable() - though it can't
> guarantee it in every case.
Full ack.  (I wonder if you misunderstood me or wanted to put my
statement into more words.  Jassi didn't like that a clk_enable without
a previous clk_prepare worked on some platforms and on others it
doesn't.  With BUG_ON(clk->ops->prepare && !clk->prepare_count) in
clk_enable we have exactly this situation.)

Best regards
Uwe


-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 15:18           ` Uwe Kleine-König
  (?)
@ 2011-02-01 15:24             ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 04:18:46PM +0100, Uwe Kleine-König wrote:
> yeah, didn't thought about multiple consumers, so (as Jeremy suggested)
> the right thing is to sleep until CLK_BUSY is cleared.

A simpler way to write this is:

int clk_prepare(struct clk *clk)
{
	int ret = 0;

	mutex_lock(&clk->mutex);
	if (clk->prepared = 0)
		ret = clk->ops->prepare(clk);
	if (ret = 0)
		clk->prepared++;
	mutex_unlock(&clk->mutex);

	return ret;
}

I think we want to take a common mutex not only for clk_prepare(), but
also for clk_set_rate().  If prepare() is waiting for a PLL to lock,
we don't want a set_rate() interfering with that.

I'd also be tempted at this stage to build-in a no-op dummy clock,
that being the NULL clk:

int clk_prepare(struct clk *clk)
{
	int ret = 0;

	if (clk) {
		mutex_lock(&clk->mutex);
		if (clk->prepared = 0)
			ret = clk->ops->prepare(clk);
		if (ret = 0)
			clk->prepared++;
		mutex_unlock(&clk->mutex);
	}

	return ret;
}

as we have various platforms defining a dummy struct clk as a way of
satisfying various driver requirements.  These dummy clocks are exactly
that - they're complete no-ops.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 15:24             ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 15:24 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Jeremy Kerr, Dima Zavin, Saravana Kannan, Lorenzo Pieralisi,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, linux-kernel,
	Paul Mundt, Ben Dooks, Vincent Guittot, linux-arm-kernel,
	Nicolas Pitre

On Tue, Feb 01, 2011 at 04:18:46PM +0100, Uwe Kleine-König wrote:
> yeah, didn't thought about multiple consumers, so (as Jeremy suggested)
> the right thing is to sleep until CLK_BUSY is cleared.

A simpler way to write this is:

int clk_prepare(struct clk *clk)
{
	int ret = 0;

	mutex_lock(&clk->mutex);
	if (clk->prepared == 0)
		ret = clk->ops->prepare(clk);
	if (ret == 0)
		clk->prepared++;
	mutex_unlock(&clk->mutex);

	return ret;
}

I think we want to take a common mutex not only for clk_prepare(), but
also for clk_set_rate().  If prepare() is waiting for a PLL to lock,
we don't want a set_rate() interfering with that.

I'd also be tempted at this stage to build-in a no-op dummy clock,
that being the NULL clk:

int clk_prepare(struct clk *clk)
{
	int ret = 0;

	if (clk) {
		mutex_lock(&clk->mutex);
		if (clk->prepared == 0)
			ret = clk->ops->prepare(clk);
		if (ret == 0)
			clk->prepared++;
		mutex_unlock(&clk->mutex);
	}

	return ret;
}

as we have various platforms defining a dummy struct clk as a way of
satisfying various driver requirements.  These dummy clocks are exactly
that - they're complete no-ops.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 15:24             ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 04:18:46PM +0100, Uwe Kleine-K?nig wrote:
> yeah, didn't thought about multiple consumers, so (as Jeremy suggested)
> the right thing is to sleep until CLK_BUSY is cleared.

A simpler way to write this is:

int clk_prepare(struct clk *clk)
{
	int ret = 0;

	mutex_lock(&clk->mutex);
	if (clk->prepared == 0)
		ret = clk->ops->prepare(clk);
	if (ret == 0)
		clk->prepared++;
	mutex_unlock(&clk->mutex);

	return ret;
}

I think we want to take a common mutex not only for clk_prepare(), but
also for clk_set_rate().  If prepare() is waiting for a PLL to lock,
we don't want a set_rate() interfering with that.

I'd also be tempted at this stage to build-in a no-op dummy clock,
that being the NULL clk:

int clk_prepare(struct clk *clk)
{
	int ret = 0;

	if (clk) {
		mutex_lock(&clk->mutex);
		if (clk->prepared == 0)
			ret = clk->ops->prepare(clk);
		if (ret == 0)
			clk->prepared++;
		mutex_unlock(&clk->mutex);
	}

	return ret;
}

as we have various platforms defining a dummy struct clk as a way of
satisfying various driver requirements.  These dummy clocks are exactly
that - they're complete no-ops.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 15:22           ` Uwe Kleine-König
  (?)
@ 2011-02-01 15:28             ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 15:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 04:22:03PM +0100, Uwe Kleine-König wrote:
> Full ack.  (I wonder if you misunderstood me or wanted to put my
> statement into more words.  Jassi didn't like that a clk_enable without
> a previous clk_prepare worked on some platforms and on others it
> doesn't.  With BUG_ON(clk->ops->prepare && !clk->prepare_count) in
> clk_enable we have exactly this situation.)

Even with a NULL clk->ops->prepare function, we still want drivers to
have called clk_prepare().  So we can do something like:

	if (WARN_ON(clk->prepare_count = 0))
		return -EINVAL;

in clk_enable() should be sufficient and noisy enough not to be missed.

I'd avoid BUG_ON() here as that will take the system down, which may
increase the chances of getting useful bug reports.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 15:28             ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 15:28 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Jassi Brar, Jeremy Kerr, Nicolas Pitre, Lorenzo Pieralisi,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	linux-kernel, Dima Zavin, Saravana Kannan, Ben Dooks,
	Vincent Guittot, linux-arm-kernel

On Tue, Feb 01, 2011 at 04:22:03PM +0100, Uwe Kleine-König wrote:
> Full ack.  (I wonder if you misunderstood me or wanted to put my
> statement into more words.  Jassi didn't like that a clk_enable without
> a previous clk_prepare worked on some platforms and on others it
> doesn't.  With BUG_ON(clk->ops->prepare && !clk->prepare_count) in
> clk_enable we have exactly this situation.)

Even with a NULL clk->ops->prepare function, we still want drivers to
have called clk_prepare().  So we can do something like:

	if (WARN_ON(clk->prepare_count == 0))
		return -EINVAL;

in clk_enable() should be sufficient and noisy enough not to be missed.

I'd avoid BUG_ON() here as that will take the system down, which may
increase the chances of getting useful bug reports.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 15:28             ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 15:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 04:22:03PM +0100, Uwe Kleine-K?nig wrote:
> Full ack.  (I wonder if you misunderstood me or wanted to put my
> statement into more words.  Jassi didn't like that a clk_enable without
> a previous clk_prepare worked on some platforms and on others it
> doesn't.  With BUG_ON(clk->ops->prepare && !clk->prepare_count) in
> clk_enable we have exactly this situation.)

Even with a NULL clk->ops->prepare function, we still want drivers to
have called clk_prepare().  So we can do something like:

	if (WARN_ON(clk->prepare_count == 0))
		return -EINVAL;

in clk_enable() should be sufficient and noisy enough not to be missed.

I'd avoid BUG_ON() here as that will take the system down, which may
increase the chances of getting useful bug reports.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 15:24             ` Russell King - ARM Linux
  (?)
@ 2011-02-01 15:53               ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-01 15:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 03:24:58PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 04:18:46PM +0100, Uwe Kleine-König wrote:
> > yeah, didn't thought about multiple consumers, so (as Jeremy suggested)
> > the right thing is to sleep until CLK_BUSY is cleared.
> 
> A simpler way to write this is:
> 
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0;
> 
> 	mutex_lock(&clk->mutex);
> 	if (clk->prepared = 0)
> 		ret = clk->ops->prepare(clk);
> 	if (ret = 0)
> 		clk->prepared++;
> 	mutex_unlock(&clk->mutex);
> 
> 	return ret;
> }
But you cannot call this in atomic context when you know the clock is
already prepared.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 15:53               ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-01 15:53 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Jeremy Kerr, Dima Zavin, Saravana Kannan, Lorenzo Pieralisi,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, linux-kernel,
	Paul Mundt, Ben Dooks, Vincent Guittot, linux-arm-kernel,
	Nicolas Pitre

On Tue, Feb 01, 2011 at 03:24:58PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 04:18:46PM +0100, Uwe Kleine-König wrote:
> > yeah, didn't thought about multiple consumers, so (as Jeremy suggested)
> > the right thing is to sleep until CLK_BUSY is cleared.
> 
> A simpler way to write this is:
> 
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0;
> 
> 	mutex_lock(&clk->mutex);
> 	if (clk->prepared == 0)
> 		ret = clk->ops->prepare(clk);
> 	if (ret == 0)
> 		clk->prepared++;
> 	mutex_unlock(&clk->mutex);
> 
> 	return ret;
> }
But you cannot call this in atomic context when you know the clock is
already prepared.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 15:53               ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-01 15:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 03:24:58PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 04:18:46PM +0100, Uwe Kleine-K?nig wrote:
> > yeah, didn't thought about multiple consumers, so (as Jeremy suggested)
> > the right thing is to sleep until CLK_BUSY is cleared.
> 
> A simpler way to write this is:
> 
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0;
> 
> 	mutex_lock(&clk->mutex);
> 	if (clk->prepared == 0)
> 		ret = clk->ops->prepare(clk);
> 	if (ret == 0)
> 		clk->prepared++;
> 	mutex_unlock(&clk->mutex);
> 
> 	return ret;
> }
But you cannot call this in atomic context when you know the clock is
already prepared.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 15:53               ` Uwe Kleine-König
  (?)
@ 2011-02-01 17:06                 ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 17:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 04:53:44PM +0100, Uwe Kleine-König wrote:
> On Tue, Feb 01, 2011 at 03:24:58PM +0000, Russell King - ARM Linux wrote:
> > On Tue, Feb 01, 2011 at 04:18:46PM +0100, Uwe Kleine-König wrote:
> > > yeah, didn't thought about multiple consumers, so (as Jeremy suggested)
> > > the right thing is to sleep until CLK_BUSY is cleared.
> > 
> > A simpler way to write this is:
> > 
> > int clk_prepare(struct clk *clk)
> > {
> > 	int ret = 0;
> > 
> > 	mutex_lock(&clk->mutex);
> > 	if (clk->prepared = 0)
> > 		ret = clk->ops->prepare(clk);
> > 	if (ret = 0)
> > 		clk->prepared++;
> > 	mutex_unlock(&clk->mutex);
> > 
> > 	return ret;
> > }
> But you cannot call this in atomic context when you know the clock is
> already prepared.

So?  You're not _supposed_ to call it from any atomic context ever.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 17:06                 ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 17:06 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Jeremy Kerr, Dima Zavin, Saravana Kannan, Lorenzo Pieralisi,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, linux-kernel,
	Paul Mundt, Ben Dooks, Vincent Guittot, linux-arm-kernel,
	Nicolas Pitre

On Tue, Feb 01, 2011 at 04:53:44PM +0100, Uwe Kleine-König wrote:
> On Tue, Feb 01, 2011 at 03:24:58PM +0000, Russell King - ARM Linux wrote:
> > On Tue, Feb 01, 2011 at 04:18:46PM +0100, Uwe Kleine-König wrote:
> > > yeah, didn't thought about multiple consumers, so (as Jeremy suggested)
> > > the right thing is to sleep until CLK_BUSY is cleared.
> > 
> > A simpler way to write this is:
> > 
> > int clk_prepare(struct clk *clk)
> > {
> > 	int ret = 0;
> > 
> > 	mutex_lock(&clk->mutex);
> > 	if (clk->prepared == 0)
> > 		ret = clk->ops->prepare(clk);
> > 	if (ret == 0)
> > 		clk->prepared++;
> > 	mutex_unlock(&clk->mutex);
> > 
> > 	return ret;
> > }
> But you cannot call this in atomic context when you know the clock is
> already prepared.

So?  You're not _supposed_ to call it from any atomic context ever.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 17:06                 ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 17:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 04:53:44PM +0100, Uwe Kleine-K?nig wrote:
> On Tue, Feb 01, 2011 at 03:24:58PM +0000, Russell King - ARM Linux wrote:
> > On Tue, Feb 01, 2011 at 04:18:46PM +0100, Uwe Kleine-K?nig wrote:
> > > yeah, didn't thought about multiple consumers, so (as Jeremy suggested)
> > > the right thing is to sleep until CLK_BUSY is cleared.
> > 
> > A simpler way to write this is:
> > 
> > int clk_prepare(struct clk *clk)
> > {
> > 	int ret = 0;
> > 
> > 	mutex_lock(&clk->mutex);
> > 	if (clk->prepared == 0)
> > 		ret = clk->ops->prepare(clk);
> > 	if (ret == 0)
> > 		clk->prepared++;
> > 	mutex_unlock(&clk->mutex);
> > 
> > 	return ret;
> > }
> But you cannot call this in atomic context when you know the clock is
> already prepared.

So?  You're not _supposed_ to call it from any atomic context ever.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 17:06                 ` Russell King - ARM Linux
  (?)
@ 2011-02-01 19:32                   ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-01 19:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 05:06:37PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 04:53:44PM +0100, Uwe Kleine-König wrote:
> > On Tue, Feb 01, 2011 at 03:24:58PM +0000, Russell King - ARM Linux wrote:
> > > On Tue, Feb 01, 2011 at 04:18:46PM +0100, Uwe Kleine-König wrote:
> > > > yeah, didn't thought about multiple consumers, so (as Jeremy suggested)
> > > > the right thing is to sleep until CLK_BUSY is cleared.
> > > 
> > > A simpler way to write this is:
> > > 
> > > int clk_prepare(struct clk *clk)
> > > {
> > > 	int ret = 0;
> > > 
> > > 	mutex_lock(&clk->mutex);
> > > 	if (clk->prepared = 0)
> > > 		ret = clk->ops->prepare(clk);
> > > 	if (ret = 0)
> > > 		clk->prepared++;
> > > 	mutex_unlock(&clk->mutex);
> > > 
> > > 	return ret;
> > > }
> > But you cannot call this in atomic context when you know the clock is
> > already prepared.
> 
> So?  You're not _supposed_ to call it from any atomic context ever.
My motivation for a more complicated clk_prepare was to make clk_prepare
atomic when that's possible (i.e. when the clk is already prepared) and
call it before the enable callback in clk_enable.  Then everything
behaves nicely even if clk_enable is called from atomic context provided
that the clock was prepared before (or doesn't need to).

If a driver writer doesn't know that a certain clock might need to sleep
at some point he runs into an atomic might_sleep with your approach and
with mine.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 19:32                   ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-01 19:32 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Nicolas Pitre, Lorenzo Pieralisi, Saravana Kannan, linux-sh,
	Ben Herrenschmidt, Sascha Hauer, Paul Mundt, linux-kernel,
	Dima Zavin, Ben Dooks, Vincent Guittot, Jeremy Kerr,
	linux-arm-kernel

On Tue, Feb 01, 2011 at 05:06:37PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 04:53:44PM +0100, Uwe Kleine-König wrote:
> > On Tue, Feb 01, 2011 at 03:24:58PM +0000, Russell King - ARM Linux wrote:
> > > On Tue, Feb 01, 2011 at 04:18:46PM +0100, Uwe Kleine-König wrote:
> > > > yeah, didn't thought about multiple consumers, so (as Jeremy suggested)
> > > > the right thing is to sleep until CLK_BUSY is cleared.
> > > 
> > > A simpler way to write this is:
> > > 
> > > int clk_prepare(struct clk *clk)
> > > {
> > > 	int ret = 0;
> > > 
> > > 	mutex_lock(&clk->mutex);
> > > 	if (clk->prepared == 0)
> > > 		ret = clk->ops->prepare(clk);
> > > 	if (ret == 0)
> > > 		clk->prepared++;
> > > 	mutex_unlock(&clk->mutex);
> > > 
> > > 	return ret;
> > > }
> > But you cannot call this in atomic context when you know the clock is
> > already prepared.
> 
> So?  You're not _supposed_ to call it from any atomic context ever.
My motivation for a more complicated clk_prepare was to make clk_prepare
atomic when that's possible (i.e. when the clk is already prepared) and
call it before the enable callback in clk_enable.  Then everything
behaves nicely even if clk_enable is called from atomic context provided
that the clock was prepared before (or doesn't need to).

If a driver writer doesn't know that a certain clock might need to sleep
at some point he runs into an atomic might_sleep with your approach and
with mine.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 19:32                   ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-01 19:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 05:06:37PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 04:53:44PM +0100, Uwe Kleine-K?nig wrote:
> > On Tue, Feb 01, 2011 at 03:24:58PM +0000, Russell King - ARM Linux wrote:
> > > On Tue, Feb 01, 2011 at 04:18:46PM +0100, Uwe Kleine-K?nig wrote:
> > > > yeah, didn't thought about multiple consumers, so (as Jeremy suggested)
> > > > the right thing is to sleep until CLK_BUSY is cleared.
> > > 
> > > A simpler way to write this is:
> > > 
> > > int clk_prepare(struct clk *clk)
> > > {
> > > 	int ret = 0;
> > > 
> > > 	mutex_lock(&clk->mutex);
> > > 	if (clk->prepared == 0)
> > > 		ret = clk->ops->prepare(clk);
> > > 	if (ret == 0)
> > > 		clk->prepared++;
> > > 	mutex_unlock(&clk->mutex);
> > > 
> > > 	return ret;
> > > }
> > But you cannot call this in atomic context when you know the clock is
> > already prepared.
> 
> So?  You're not _supposed_ to call it from any atomic context ever.
My motivation for a more complicated clk_prepare was to make clk_prepare
atomic when that's possible (i.e. when the clk is already prepared) and
call it before the enable callback in clk_enable.  Then everything
behaves nicely even if clk_enable is called from atomic context provided
that the clock was prepared before (or doesn't need to).

If a driver writer doesn't know that a certain clock might need to sleep
at some point he runs into an atomic might_sleep with your approach and
with mine.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 19:32                   ` Uwe Kleine-König
  (?)
@ 2011-02-01 19:56                     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 19:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 08:32:01PM +0100, Uwe Kleine-König wrote:
> On Tue, Feb 01, 2011 at 05:06:37PM +0000, Russell King - ARM Linux wrote:
> > So?  You're not _supposed_ to call it from any atomic context ever.
>
> My motivation for a more complicated clk_prepare was to make clk_prepare
> atomic when that's possible (i.e. when the clk is already prepared) and
> call it before the enable callback in clk_enable.  Then everything
> behaves nicely even if clk_enable is called from atomic context provided
> that the clock was prepared before (or doesn't need to).

You really don't get the point of clk_prepare() do you.  I'm not
going to bother trying to educate you anymore.

Hopefully someone with more patience can give you the necessary
teaching to make you understand.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 19:56                     ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 19:56 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Nicolas Pitre, Lorenzo Pieralisi, Saravana Kannan, linux-sh,
	Ben Herrenschmidt, Sascha Hauer, Paul Mundt, linux-kernel,
	Dima Zavin, Ben Dooks, Vincent Guittot, Jeremy Kerr,
	linux-arm-kernel

On Tue, Feb 01, 2011 at 08:32:01PM +0100, Uwe Kleine-König wrote:
> On Tue, Feb 01, 2011 at 05:06:37PM +0000, Russell King - ARM Linux wrote:
> > So?  You're not _supposed_ to call it from any atomic context ever.
>
> My motivation for a more complicated clk_prepare was to make clk_prepare
> atomic when that's possible (i.e. when the clk is already prepared) and
> call it before the enable callback in clk_enable.  Then everything
> behaves nicely even if clk_enable is called from atomic context provided
> that the clock was prepared before (or doesn't need to).

You really don't get the point of clk_prepare() do you.  I'm not
going to bother trying to educate you anymore.

Hopefully someone with more patience can give you the necessary
teaching to make you understand.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 19:56                     ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 19:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 08:32:01PM +0100, Uwe Kleine-K?nig wrote:
> On Tue, Feb 01, 2011 at 05:06:37PM +0000, Russell King - ARM Linux wrote:
> > So?  You're not _supposed_ to call it from any atomic context ever.
>
> My motivation for a more complicated clk_prepare was to make clk_prepare
> atomic when that's possible (i.e. when the clk is already prepared) and
> call it before the enable callback in clk_enable.  Then everything
> behaves nicely even if clk_enable is called from atomic context provided
> that the clock was prepared before (or doesn't need to).

You really don't get the point of clk_prepare() do you.  I'm not
going to bother trying to educate you anymore.

Hopefully someone with more patience can give you the necessary
teaching to make you understand.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 19:32                   ` Uwe Kleine-König
  (?)
@ 2011-02-01 20:06                     ` Nicolas Pitre
  -1 siblings, 0 replies; 383+ messages in thread
From: Nicolas Pitre @ 2011-02-01 20:06 UTC (permalink / raw)
  To: linux-arm-kernel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 589 bytes --]

On Tue, 1 Feb 2011, Uwe Kleine-König wrote:

> My motivation for a more complicated clk_prepare was to make clk_prepare
> atomic when that's possible (i.e. when the clk is already prepared) and
> call it before the enable callback in clk_enable.  Then everything
> behaves nicely even if clk_enable is called from atomic context provided
> that the clock was prepared before (or doesn't need to).

NOOOOOOOOO!!!

We _do_ want drivers to _always_ call clk_prepare() in sleepable 
context, and _then_ always call clk_enable() in whatever context they 
wish.  Period.


Nicolas

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 20:06                     ` Nicolas Pitre
  0 siblings, 0 replies; 383+ messages in thread
From: Nicolas Pitre @ 2011-02-01 20:06 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Russell King - ARM Linux, Lorenzo Pieralisi, Saravana Kannan,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	linux-kernel, Dima Zavin, Ben Dooks, Vincent Guittot,
	Jeremy Kerr, linux-arm-kernel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 574 bytes --]

On Tue, 1 Feb 2011, Uwe Kleine-König wrote:

> My motivation for a more complicated clk_prepare was to make clk_prepare
> atomic when that's possible (i.e. when the clk is already prepared) and
> call it before the enable callback in clk_enable.  Then everything
> behaves nicely even if clk_enable is called from atomic context provided
> that the clock was prepared before (or doesn't need to).

NOOOOOOOOO!!!

We _do_ want drivers to _always_ call clk_prepare() in sleepable 
context, and _then_ always call clk_enable() in whatever context they 
wish.  Period.


Nicolas

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 20:06                     ` Nicolas Pitre
  0 siblings, 0 replies; 383+ messages in thread
From: Nicolas Pitre @ 2011-02-01 20:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 1 Feb 2011, Uwe Kleine-K?nig wrote:

> My motivation for a more complicated clk_prepare was to make clk_prepare
> atomic when that's possible (i.e. when the clk is already prepared) and
> call it before the enable callback in clk_enable.  Then everything
> behaves nicely even if clk_enable is called from atomic context provided
> that the clock was prepared before (or doesn't need to).

NOOOOOOOOO!!!

We _do_ want drivers to _always_ call clk_prepare() in sleepable 
context, and _then_ always call clk_enable() in whatever context they 
wish.  Period.


Nicolas

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 19:56                     ` Russell King - ARM Linux
  (?)
@ 2011-02-01 20:21                       ` Saravana Kannan
  -1 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-01 20:21 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/01/2011 11:56 AM, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 08:32:01PM +0100, Uwe Kleine-König wrote:
>> On Tue, Feb 01, 2011 at 05:06:37PM +0000, Russell King - ARM Linux wrote:
>>> So?  You're not _supposed_ to call it from any atomic context ever.
>>
>> My motivation for a more complicated clk_prepare was to make clk_prepare
>> atomic when that's possible (i.e. when the clk is already prepared) and
>> call it before the enable callback in clk_enable.  Then everything
>> behaves nicely even if clk_enable is called from atomic context provided
>> that the clock was prepared before (or doesn't need to).
>
> You really don't get the point of clk_prepare() do you.  I'm not
> going to bother trying to educate you anymore.
>
> Hopefully someone with more patience can give you the necessary
> teaching to make you understand.

Uwe,

If the driver is calling clk_prepare() right next to clk_enable() 
knowing it's been already prepared and will hence be "atomic" (this is 
actually not true), then by your description, it's pointless to call 
clk_prepare().

If you want the driver to call clk_prepare() in atomic context because 
it will be atomic in most cases -- well, that's wrong. It's either 
atomic or is NOT atomic. There is no in between. If a call is NOT 
atomic, it can't be called in atomic context. Long story short, if you 
expect clk_prepare() to be atomic under any circumstance, it beats the 
point of introducing clk_prepare().

Hope I helped.

-Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 20:21                       ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-01 20:21 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Uwe Kleine-König, Nicolas Pitre, Dima Zavin,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Sascha Hauer, Paul Mundt, linux-kernel, Ben Dooks, Jeremy Kerr,
	linux-arm-kernel

On 02/01/2011 11:56 AM, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 08:32:01PM +0100, Uwe Kleine-König wrote:
>> On Tue, Feb 01, 2011 at 05:06:37PM +0000, Russell King - ARM Linux wrote:
>>> So?  You're not _supposed_ to call it from any atomic context ever.
>>
>> My motivation for a more complicated clk_prepare was to make clk_prepare
>> atomic when that's possible (i.e. when the clk is already prepared) and
>> call it before the enable callback in clk_enable.  Then everything
>> behaves nicely even if clk_enable is called from atomic context provided
>> that the clock was prepared before (or doesn't need to).
>
> You really don't get the point of clk_prepare() do you.  I'm not
> going to bother trying to educate you anymore.
>
> Hopefully someone with more patience can give you the necessary
> teaching to make you understand.

Uwe,

If the driver is calling clk_prepare() right next to clk_enable() 
knowing it's been already prepared and will hence be "atomic" (this is 
actually not true), then by your description, it's pointless to call 
clk_prepare().

If you want the driver to call clk_prepare() in atomic context because 
it will be atomic in most cases -- well, that's wrong. It's either 
atomic or is NOT atomic. There is no in between. If a call is NOT 
atomic, it can't be called in atomic context. Long story short, if you 
expect clk_prepare() to be atomic under any circumstance, it beats the 
point of introducing clk_prepare().

Hope I helped.

-Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 20:21                       ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-01 20:21 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/01/2011 11:56 AM, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 08:32:01PM +0100, Uwe Kleine-K?nig wrote:
>> On Tue, Feb 01, 2011 at 05:06:37PM +0000, Russell King - ARM Linux wrote:
>>> So?  You're not _supposed_ to call it from any atomic context ever.
>>
>> My motivation for a more complicated clk_prepare was to make clk_prepare
>> atomic when that's possible (i.e. when the clk is already prepared) and
>> call it before the enable callback in clk_enable.  Then everything
>> behaves nicely even if clk_enable is called from atomic context provided
>> that the clock was prepared before (or doesn't need to).
>
> You really don't get the point of clk_prepare() do you.  I'm not
> going to bother trying to educate you anymore.
>
> Hopefully someone with more patience can give you the necessary
> teaching to make you understand.

Uwe,

If the driver is calling clk_prepare() right next to clk_enable() 
knowing it's been already prepared and will hence be "atomic" (this is 
actually not true), then by your description, it's pointless to call 
clk_prepare().

If you want the driver to call clk_prepare() in atomic context because 
it will be atomic in most cases -- well, that's wrong. It's either 
atomic or is NOT atomic. There is no in between. If a call is NOT 
atomic, it can't be called in atomic context. Long story short, if you 
expect clk_prepare() to be atomic under any circumstance, it beats the 
point of introducing clk_prepare().

Hope I helped.

-Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 15:24             ` Russell King - ARM Linux
  (?)
@ 2011-02-01 20:33               ` Saravana Kannan
  -1 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-01 20:33 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/01/2011 07:24 AM, Russell King - ARM Linux wrote:
> A simpler way to write this is:
>
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0;
>
> 	mutex_lock(&clk->mutex);
> 	if (clk->prepared = 0)
> 		ret = clk->ops->prepare(clk);
> 	if (ret = 0)
> 		clk->prepared++;
> 	mutex_unlock(&clk->mutex);
>
> 	return ret;
> }
>
> I think we want to take a common mutex not only for clk_prepare(), but
> also for clk_set_rate().  If prepare() is waiting for a PLL to lock,
> we don't want a set_rate() interfering with that.

Looks like this is the best acknowledgment/response I can expect to get 
from Russell on this point that I raised.

Jeremy,

When you update the comments/doc to indicate clk_prepare/unprepare is 
not atomic, can you also update the comment for set_rate() and mark it 
as non-atomic?

Thanks for starting this thread. My efforts to reignite the other thread 
didn't go anywhere. Glad to see it's moving forward.

> I'd also be tempted at this stage to build-in a no-op dummy clock,
> that being the NULL clk:
>[snip]
> as we have various platforms defining a dummy struct clk as a way of
> satisfying various driver requirements.  These dummy clocks are exactly
> that - they're complete no-ops.

Unrelated to this thread, but I Ack this request too.

-Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 20:33               ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-01 20:33 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Uwe Kleine-König, Nicolas Pitre, Lorenzo Pieralisi,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	linux-kernel, Dima Zavin, Ben Dooks, Vincent Guittot,
	Jeremy Kerr, linux-arm-kernel

On 02/01/2011 07:24 AM, Russell King - ARM Linux wrote:
> A simpler way to write this is:
>
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0;
>
> 	mutex_lock(&clk->mutex);
> 	if (clk->prepared == 0)
> 		ret = clk->ops->prepare(clk);
> 	if (ret == 0)
> 		clk->prepared++;
> 	mutex_unlock(&clk->mutex);
>
> 	return ret;
> }
>
> I think we want to take a common mutex not only for clk_prepare(), but
> also for clk_set_rate().  If prepare() is waiting for a PLL to lock,
> we don't want a set_rate() interfering with that.

Looks like this is the best acknowledgment/response I can expect to get 
from Russell on this point that I raised.

Jeremy,

When you update the comments/doc to indicate clk_prepare/unprepare is 
not atomic, can you also update the comment for set_rate() and mark it 
as non-atomic?

Thanks for starting this thread. My efforts to reignite the other thread 
didn't go anywhere. Glad to see it's moving forward.

> I'd also be tempted at this stage to build-in a no-op dummy clock,
> that being the NULL clk:
>[snip]
> as we have various platforms defining a dummy struct clk as a way of
> satisfying various driver requirements.  These dummy clocks are exactly
> that - they're complete no-ops.

Unrelated to this thread, but I Ack this request too.

-Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 20:33               ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-01 20:33 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/01/2011 07:24 AM, Russell King - ARM Linux wrote:
> A simpler way to write this is:
>
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0;
>
> 	mutex_lock(&clk->mutex);
> 	if (clk->prepared == 0)
> 		ret = clk->ops->prepare(clk);
> 	if (ret == 0)
> 		clk->prepared++;
> 	mutex_unlock(&clk->mutex);
>
> 	return ret;
> }
>
> I think we want to take a common mutex not only for clk_prepare(), but
> also for clk_set_rate().  If prepare() is waiting for a PLL to lock,
> we don't want a set_rate() interfering with that.

Looks like this is the best acknowledgment/response I can expect to get 
from Russell on this point that I raised.

Jeremy,

When you update the comments/doc to indicate clk_prepare/unprepare is 
not atomic, can you also update the comment for set_rate() and mark it 
as non-atomic?

Thanks for starting this thread. My efforts to reignite the other thread 
didn't go anywhere. Glad to see it's moving forward.

> I'd also be tempted at this stage to build-in a no-op dummy clock,
> that being the NULL clk:
>[snip]
> as we have various platforms defining a dummy struct clk as a way of
> satisfying various driver requirements.  These dummy clocks are exactly
> that - they're complete no-ops.

Unrelated to this thread, but I Ack this request too.

-Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 20:33               ` Saravana Kannan
  (?)
@ 2011-02-01 20:36                 ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 20:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 12:33:12PM -0800, Saravana Kannan wrote:
> Looks like this is the best acknowledgment/response I can expect to get  
> from Russell on this point that I raised.

Sorry, I've been up to my eyeballs with other stuff over the last few
weeks.  Yes, I think clk_set_rate() needs to be sleep-able too.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 20:36                 ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 20:36 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: Uwe Kleine-König, Nicolas Pitre, Lorenzo Pieralisi,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	linux-kernel, Dima Zavin, Ben Dooks, Vincent Guittot,
	Jeremy Kerr, linux-arm-kernel

On Tue, Feb 01, 2011 at 12:33:12PM -0800, Saravana Kannan wrote:
> Looks like this is the best acknowledgment/response I can expect to get  
> from Russell on this point that I raised.

Sorry, I've been up to my eyeballs with other stuff over the last few
weeks.  Yes, I think clk_set_rate() needs to be sleep-able too.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 20:36                 ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 20:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 12:33:12PM -0800, Saravana Kannan wrote:
> Looks like this is the best acknowledgment/response I can expect to get  
> from Russell on this point that I raised.

Sorry, I've been up to my eyeballs with other stuff over the last few
weeks.  Yes, I think clk_set_rate() needs to be sleep-able too.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 20:21                       ` Saravana Kannan
  (?)
@ 2011-02-01 20:43                         ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-01 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

On Tue, Feb 01, 2011 at 12:21:45PM -0800, Saravana Kannan wrote:
> If the driver is calling clk_prepare() right next to clk_enable()
> knowing it's been already prepared and will hence be "atomic" (this
> is actually not true), then by your description, it's pointless to
> call clk_prepare().
Well not completely, as it increases the reference count.  The advantage
would be that clk_enable counts addionally as prepare, so it would be
impossible to unprepare an enabled clock.  And the other way round an
unprepared clock would never be enabled.
 
> If you want the driver to call clk_prepare() in atomic context
> because it will be atomic in most cases -- well, that's wrong. It's
> either atomic or is NOT atomic. There is no in between. If a call is
> NOT atomic, it can't be called in atomic context. Long story short,
> if you expect clk_prepare() to be atomic under any circumstance, it
> beats the point of introducing clk_prepare().
Well, with my suggestion it's atomic when certain precondions are given.
IMHO that's better than "atomic in most cases" because the caller can
assert that everything goes smooth.
These preconditions are asserted when the driver writer is careful
enough to stick to the API.

Either my idea is bad or I'm unable to sell it appropriately.  Be it as
it is, I will stop to make a case for it.

Best regards and thanks for your try,
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 20:43                         ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-01 20:43 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: Russell King - ARM Linux, Nicolas Pitre, Dima Zavin,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Sascha Hauer, Paul Mundt, linux-kernel, Ben Dooks, Jeremy Kerr,
	linux-arm-kernel

Hello,

On Tue, Feb 01, 2011 at 12:21:45PM -0800, Saravana Kannan wrote:
> If the driver is calling clk_prepare() right next to clk_enable()
> knowing it's been already prepared and will hence be "atomic" (this
> is actually not true), then by your description, it's pointless to
> call clk_prepare().
Well not completely, as it increases the reference count.  The advantage
would be that clk_enable counts addionally as prepare, so it would be
impossible to unprepare an enabled clock.  And the other way round an
unprepared clock would never be enabled.
 
> If you want the driver to call clk_prepare() in atomic context
> because it will be atomic in most cases -- well, that's wrong. It's
> either atomic or is NOT atomic. There is no in between. If a call is
> NOT atomic, it can't be called in atomic context. Long story short,
> if you expect clk_prepare() to be atomic under any circumstance, it
> beats the point of introducing clk_prepare().
Well, with my suggestion it's atomic when certain precondions are given.
IMHO that's better than "atomic in most cases" because the caller can
assert that everything goes smooth.
These preconditions are asserted when the driver writer is careful
enough to stick to the API.

Either my idea is bad or I'm unable to sell it appropriately.  Be it as
it is, I will stop to make a case for it.

Best regards and thanks for your try,
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 20:43                         ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-01 20:43 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

On Tue, Feb 01, 2011 at 12:21:45PM -0800, Saravana Kannan wrote:
> If the driver is calling clk_prepare() right next to clk_enable()
> knowing it's been already prepared and will hence be "atomic" (this
> is actually not true), then by your description, it's pointless to
> call clk_prepare().
Well not completely, as it increases the reference count.  The advantage
would be that clk_enable counts addionally as prepare, so it would be
impossible to unprepare an enabled clock.  And the other way round an
unprepared clock would never be enabled.
 
> If you want the driver to call clk_prepare() in atomic context
> because it will be atomic in most cases -- well, that's wrong. It's
> either atomic or is NOT atomic. There is no in between. If a call is
> NOT atomic, it can't be called in atomic context. Long story short,
> if you expect clk_prepare() to be atomic under any circumstance, it
> beats the point of introducing clk_prepare().
Well, with my suggestion it's atomic when certain precondions are given.
IMHO that's better than "atomic in most cases" because the caller can
assert that everything goes smooth.
These preconditions are asserted when the driver writer is careful
enough to stick to the API.

Either my idea is bad or I'm unable to sell it appropriately.  Be it as
it is, I will stop to make a case for it.

Best regards and thanks for your try,
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 15:28             ` Russell King - ARM Linux
  (?)
@ 2011-02-01 20:57               ` Saravana Kannan
  -1 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-01 20:57 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/01/2011 07:28 AM, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 04:22:03PM +0100, Uwe Kleine-König wrote:
>> Full ack.  (I wonder if you misunderstood me or wanted to put my
>> statement into more words.  Jassi didn't like that a clk_enable without
>> a previous clk_prepare worked on some platforms and on others it
>> doesn't.  With BUG_ON(clk->ops->prepare&&  !clk->prepare_count) in
>> clk_enable we have exactly this situation.)
>
> Even with a NULL clk->ops->prepare function, we still want drivers to
> have called clk_prepare().  So we can do something like:
>
> 	if (WARN_ON(clk->prepare_count = 0))
> 		return -EINVAL;
>
> in clk_enable() should be sufficient and noisy enough not to be missed.

This code will only catch the error when it actually happens and will 
even miss catching some of them (if timed right -- unprepare happens in 
the other core after this check is executed).

I really wish there was something better we could do to help driver devs 
catch errors of calling enable without calling prepare(). Some thing 
like spin lock debug, or the might_sleeps() inside mutexes, etc.

Hmm... Jeremy, how about doing a similar check in the unprepare code? 
You could WARN/BUG ON the prepare count going to zero when the enable 
count is still non-zero?

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 20:57               ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-01 20:57 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Uwe Kleine-König, Nicolas Pitre, Dima Zavin,
	Lorenzo Pieralisi, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Jassi Brar, linux-kernel, Paul Mundt, Ben Dooks, Vincent Guittot,
	Jeremy Kerr, linux-arm-kernel

On 02/01/2011 07:28 AM, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 04:22:03PM +0100, Uwe Kleine-König wrote:
>> Full ack.  (I wonder if you misunderstood me or wanted to put my
>> statement into more words.  Jassi didn't like that a clk_enable without
>> a previous clk_prepare worked on some platforms and on others it
>> doesn't.  With BUG_ON(clk->ops->prepare&&  !clk->prepare_count) in
>> clk_enable we have exactly this situation.)
>
> Even with a NULL clk->ops->prepare function, we still want drivers to
> have called clk_prepare().  So we can do something like:
>
> 	if (WARN_ON(clk->prepare_count == 0))
> 		return -EINVAL;
>
> in clk_enable() should be sufficient and noisy enough not to be missed.

This code will only catch the error when it actually happens and will 
even miss catching some of them (if timed right -- unprepare happens in 
the other core after this check is executed).

I really wish there was something better we could do to help driver devs 
catch errors of calling enable without calling prepare(). Some thing 
like spin lock debug, or the might_sleeps() inside mutexes, etc.

Hmm... Jeremy, how about doing a similar check in the unprepare code? 
You could WARN/BUG ON the prepare count going to zero when the enable 
count is still non-zero?

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 20:57               ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-01 20:57 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/01/2011 07:28 AM, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 04:22:03PM +0100, Uwe Kleine-K?nig wrote:
>> Full ack.  (I wonder if you misunderstood me or wanted to put my
>> statement into more words.  Jassi didn't like that a clk_enable without
>> a previous clk_prepare worked on some platforms and on others it
>> doesn't.  With BUG_ON(clk->ops->prepare&&  !clk->prepare_count) in
>> clk_enable we have exactly this situation.)
>
> Even with a NULL clk->ops->prepare function, we still want drivers to
> have called clk_prepare().  So we can do something like:
>
> 	if (WARN_ON(clk->prepare_count == 0))
> 		return -EINVAL;
>
> in clk_enable() should be sufficient and noisy enough not to be missed.

This code will only catch the error when it actually happens and will 
even miss catching some of them (if timed right -- unprepare happens in 
the other core after this check is executed).

I really wish there was something better we could do to help driver devs 
catch errors of calling enable without calling prepare(). Some thing 
like spin lock debug, or the might_sleeps() inside mutexes, etc.

Hmm... Jeremy, how about doing a similar check in the unprepare code? 
You could WARN/BUG ON the prepare count going to zero when the enable 
count is still non-zero?

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 15:24             ` Russell King - ARM Linux
  (?)
@ 2011-02-01 20:59               ` Stephen Boyd
  -1 siblings, 0 replies; 383+ messages in thread
From: Stephen Boyd @ 2011-02-01 20:59 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/01/2011 07:24 AM, Russell King - ARM Linux wrote:
>
> I'd also be tempted at this stage to build-in a no-op dummy clock,
> that being the NULL clk:
>
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0;
>
> 	if (clk) {
> 		mutex_lock(&clk->mutex);
> 		if (clk->prepared = 0)
> 			ret = clk->ops->prepare(clk);
> 		if (ret = 0)
> 			clk->prepared++;
> 		mutex_unlock(&clk->mutex);
> 	}
>
> 	return ret;
> }

I'm afraid this will hide enable/disable imbalances on some targets and
then expose them on others. Maybe its not a big problem though since
this also elegantly handles the root(s) of the tree.

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 20:59               ` Stephen Boyd
  0 siblings, 0 replies; 383+ messages in thread
From: Stephen Boyd @ 2011-02-01 20:59 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Uwe Kleine-König, Nicolas Pitre, Lorenzo Pieralisi,
	Saravana Kannan, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, linux-kernel, Dima Zavin, Ben Dooks, Vincent Guittot,
	Jeremy Kerr, linux-arm-kernel

On 02/01/2011 07:24 AM, Russell King - ARM Linux wrote:
>
> I'd also be tempted at this stage to build-in a no-op dummy clock,
> that being the NULL clk:
>
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0;
>
> 	if (clk) {
> 		mutex_lock(&clk->mutex);
> 		if (clk->prepared == 0)
> 			ret = clk->ops->prepare(clk);
> 		if (ret == 0)
> 			clk->prepared++;
> 		mutex_unlock(&clk->mutex);
> 	}
>
> 	return ret;
> }

I'm afraid this will hide enable/disable imbalances on some targets and
then expose them on others. Maybe its not a big problem though since
this also elegantly handles the root(s) of the tree.

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 20:59               ` Stephen Boyd
  0 siblings, 0 replies; 383+ messages in thread
From: Stephen Boyd @ 2011-02-01 20:59 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/01/2011 07:24 AM, Russell King - ARM Linux wrote:
>
> I'd also be tempted at this stage to build-in a no-op dummy clock,
> that being the NULL clk:
>
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0;
>
> 	if (clk) {
> 		mutex_lock(&clk->mutex);
> 		if (clk->prepared == 0)
> 			ret = clk->ops->prepare(clk);
> 		if (ret == 0)
> 			clk->prepared++;
> 		mutex_unlock(&clk->mutex);
> 	}
>
> 	return ret;
> }

I'm afraid this will hide enable/disable imbalances on some targets and
then expose them on others. Maybe its not a big problem though since
this also elegantly handles the root(s) of the tree.

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 20:59               ` Stephen Boyd
  (?)
@ 2011-02-01 21:24                 ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 21:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 12:59:11PM -0800, Stephen Boyd wrote:
> On 02/01/2011 07:24 AM, Russell King - ARM Linux wrote:
> > I'd also be tempted at this stage to build-in a no-op dummy clock,
> > that being the NULL clk:
> >
> > int clk_prepare(struct clk *clk)
> > {
> > 	int ret = 0;
> >
> > 	if (clk) {
> > 		mutex_lock(&clk->mutex);
> > 		if (clk->prepared = 0)
> > 			ret = clk->ops->prepare(clk);
> > 		if (ret = 0)
> > 			clk->prepared++;
> > 		mutex_unlock(&clk->mutex);
> > 	}
> >
> > 	return ret;
> > }
> 
> I'm afraid this will hide enable/disable imbalances on some targets and
> then expose them on others. Maybe its not a big problem though since
> this also elegantly handles the root(s) of the tree.

You can't catch enable/disable imbalances in the prepare code, and you
can't really catch them in the unprepare code either.

Consider two drivers sharing the same struct clk.  When the second driver
prepares the clock, the enable count could well be non-zero, caused by
the first driver.  Ditto for when the second driver is removed, and it
calls unprepare - the enable count may well be non-zero.

The only thing you can check is that when the prepare count is zero,
the enable count is also zero.  You can also check in clk_enable() and
clk_disable() that the prepare count is non-zero.

If you want tigher checking than that, you need to somehow identify and
match up the clk_prepare/clk_enable/clk_disable/clk_unprepare calls from
a particular driver instance.  Addresses of the functions don't work as
you can't be certain that driver code will be co-located within a certain
range.  Adding an additional argument to these functions which is driver
instance specific seems to be horrible too.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 21:24                 ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 21:24 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Uwe Kleine-König, Nicolas Pitre, Lorenzo Pieralisi,
	Saravana Kannan, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, linux-kernel, Dima Zavin, Ben Dooks, Vincent Guittot,
	Jeremy Kerr, linux-arm-kernel

On Tue, Feb 01, 2011 at 12:59:11PM -0800, Stephen Boyd wrote:
> On 02/01/2011 07:24 AM, Russell King - ARM Linux wrote:
> > I'd also be tempted at this stage to build-in a no-op dummy clock,
> > that being the NULL clk:
> >
> > int clk_prepare(struct clk *clk)
> > {
> > 	int ret = 0;
> >
> > 	if (clk) {
> > 		mutex_lock(&clk->mutex);
> > 		if (clk->prepared == 0)
> > 			ret = clk->ops->prepare(clk);
> > 		if (ret == 0)
> > 			clk->prepared++;
> > 		mutex_unlock(&clk->mutex);
> > 	}
> >
> > 	return ret;
> > }
> 
> I'm afraid this will hide enable/disable imbalances on some targets and
> then expose them on others. Maybe its not a big problem though since
> this also elegantly handles the root(s) of the tree.

You can't catch enable/disable imbalances in the prepare code, and you
can't really catch them in the unprepare code either.

Consider two drivers sharing the same struct clk.  When the second driver
prepares the clock, the enable count could well be non-zero, caused by
the first driver.  Ditto for when the second driver is removed, and it
calls unprepare - the enable count may well be non-zero.

The only thing you can check is that when the prepare count is zero,
the enable count is also zero.  You can also check in clk_enable() and
clk_disable() that the prepare count is non-zero.

If you want tigher checking than that, you need to somehow identify and
match up the clk_prepare/clk_enable/clk_disable/clk_unprepare calls from
a particular driver instance.  Addresses of the functions don't work as
you can't be certain that driver code will be co-located within a certain
range.  Adding an additional argument to these functions which is driver
instance specific seems to be horrible too.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-01 21:24                 ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-01 21:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 12:59:11PM -0800, Stephen Boyd wrote:
> On 02/01/2011 07:24 AM, Russell King - ARM Linux wrote:
> > I'd also be tempted at this stage to build-in a no-op dummy clock,
> > that being the NULL clk:
> >
> > int clk_prepare(struct clk *clk)
> > {
> > 	int ret = 0;
> >
> > 	if (clk) {
> > 		mutex_lock(&clk->mutex);
> > 		if (clk->prepared == 0)
> > 			ret = clk->ops->prepare(clk);
> > 		if (ret == 0)
> > 			clk->prepared++;
> > 		mutex_unlock(&clk->mutex);
> > 	}
> >
> > 	return ret;
> > }
> 
> I'm afraid this will hide enable/disable imbalances on some targets and
> then expose them on others. Maybe its not a big problem though since
> this also elegantly handles the root(s) of the tree.

You can't catch enable/disable imbalances in the prepare code, and you
can't really catch them in the unprepare code either.

Consider two drivers sharing the same struct clk.  When the second driver
prepares the clock, the enable count could well be non-zero, caused by
the first driver.  Ditto for when the second driver is removed, and it
calls unprepare - the enable count may well be non-zero.

The only thing you can check is that when the prepare count is zero,
the enable count is also zero.  You can also check in clk_enable() and
clk_disable() that the prepare count is non-zero.

If you want tigher checking than that, you need to somehow identify and
match up the clk_prepare/clk_enable/clk_disable/clk_unprepare calls from
a particular driver instance.  Addresses of the functions don't work as
you can't be certain that driver code will be co-located within a certain
range.  Adding an additional argument to these functions which is driver
instance specific seems to be horrible too.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 15:28             ` Russell King - ARM Linux
  (?)
@ 2011-02-02  2:31               ` Jassi Brar
  -1 siblings, 0 replies; 383+ messages in thread
From: Jassi Brar @ 2011-02-02  2:31 UTC (permalink / raw)
  To: linux-arm-kernel

2011/2/2 Russell King - ARM Linux <linux@arm.linux.org.uk>:
> On Tue, Feb 01, 2011 at 04:22:03PM +0100, Uwe Kleine-König wrote:
>> Full ack.  (I wonder if you misunderstood me or wanted to put my
>> statement into more words.  Jassi didn't like that a clk_enable without
>> a previous clk_prepare worked on some platforms and on others it
>> doesn't.  With BUG_ON(clk->ops->prepare && !clk->prepare_count) in
>> clk_enable we have exactly this situation.)
>
> Even with a NULL clk->ops->prepare function, we still want drivers to
> have called clk_prepare().  So we can do something like:
>
>        if (WARN_ON(clk->prepare_count = 0))
>                return -EINVAL;
>
> in clk_enable() should be sufficient and noisy enough not to be missed.
>
> I'd avoid BUG_ON() here as that will take the system down, which may
> increase the chances of getting useful bug reports.

Having thought about it, I think it's not necessary to immediately catch
drivers that work on some platforms and not on others -- a mere comment
'please add clk_prepare' during code review or a patch adding 'clk_prepare'
later upon stumbling across a platform on which the driver doesn't work,
should be OK. Let us not fret about it.

That leaves us with only having to ensure that :-
a) No two calls to clk_prepare/unprepare _hooks_ are consecutive.
b) clk_prepare is done on the clock (not necessarily by the driver
    under consideration) before calls to clk_enable.

I think (a) is already easily managed by having the prepare_count,
and (b) can be reasonably managed by what Russell suggests above.

So, FWIW, I am for the idea.

Njoi!

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-02  2:31               ` Jassi Brar
  0 siblings, 0 replies; 383+ messages in thread
From: Jassi Brar @ 2011-02-02  2:31 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Uwe Kleine-König, Jeremy Kerr, Nicolas Pitre,
	Lorenzo Pieralisi, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, linux-kernel, Dima Zavin, Saravana Kannan, Ben Dooks,
	Vincent Guittot, linux-arm-kernel

2011/2/2 Russell King - ARM Linux <linux@arm.linux.org.uk>:
> On Tue, Feb 01, 2011 at 04:22:03PM +0100, Uwe Kleine-König wrote:
>> Full ack.  (I wonder if you misunderstood me or wanted to put my
>> statement into more words.  Jassi didn't like that a clk_enable without
>> a previous clk_prepare worked on some platforms and on others it
>> doesn't.  With BUG_ON(clk->ops->prepare && !clk->prepare_count) in
>> clk_enable we have exactly this situation.)
>
> Even with a NULL clk->ops->prepare function, we still want drivers to
> have called clk_prepare().  So we can do something like:
>
>        if (WARN_ON(clk->prepare_count == 0))
>                return -EINVAL;
>
> in clk_enable() should be sufficient and noisy enough not to be missed.
>
> I'd avoid BUG_ON() here as that will take the system down, which may
> increase the chances of getting useful bug reports.

Having thought about it, I think it's not necessary to immediately catch
drivers that work on some platforms and not on others -- a mere comment
'please add clk_prepare' during code review or a patch adding 'clk_prepare'
later upon stumbling across a platform on which the driver doesn't work,
should be OK. Let us not fret about it.

That leaves us with only having to ensure that :-
a) No two calls to clk_prepare/unprepare _hooks_ are consecutive.
b) clk_prepare is done on the clock (not necessarily by the driver
    under consideration) before calls to clk_enable.

I think (a) is already easily managed by having the prepare_count,
and (b) can be reasonably managed by what Russell suggests above.

So, FWIW, I am for the idea.

Njoi!

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-02  2:31               ` Jassi Brar
  0 siblings, 0 replies; 383+ messages in thread
From: Jassi Brar @ 2011-02-02  2:31 UTC (permalink / raw)
  To: linux-arm-kernel

2011/2/2 Russell King - ARM Linux <linux@arm.linux.org.uk>:
> On Tue, Feb 01, 2011 at 04:22:03PM +0100, Uwe Kleine-K?nig wrote:
>> Full ack. ?(I wonder if you misunderstood me or wanted to put my
>> statement into more words. ?Jassi didn't like that a clk_enable without
>> a previous clk_prepare worked on some platforms and on others it
>> doesn't. ?With BUG_ON(clk->ops->prepare && !clk->prepare_count) in
>> clk_enable we have exactly this situation.)
>
> Even with a NULL clk->ops->prepare function, we still want drivers to
> have called clk_prepare(). ?So we can do something like:
>
> ? ? ? ?if (WARN_ON(clk->prepare_count == 0))
> ? ? ? ? ? ? ? ?return -EINVAL;
>
> in clk_enable() should be sufficient and noisy enough not to be missed.
>
> I'd avoid BUG_ON() here as that will take the system down, which may
> increase the chances of getting useful bug reports.

Having thought about it, I think it's not necessary to immediately catch
drivers that work on some platforms and not on others -- a mere comment
'please add clk_prepare' during code review or a patch adding 'clk_prepare'
later upon stumbling across a platform on which the driver doesn't work,
should be OK. Let us not fret about it.

That leaves us with only having to ensure that :-
a) No two calls to clk_prepare/unprepare _hooks_ are consecutive.
b) clk_prepare is done on the clock (not necessarily by the driver
    under consideration) before calls to clk_enable.

I think (a) is already easily managed by having the prepare_count,
and (b) can be reasonably managed by what Russell suggests above.

So, FWIW, I am for the idea.

Njoi!

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 20:43                         ` Uwe Kleine-König
  (?)
@ 2011-02-04  9:33                           ` Richard Zhao
  -1 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-04  9:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 09:43:31PM +0100, Uwe Kleine-König wrote:
> Hello,
> 
> On Tue, Feb 01, 2011 at 12:21:45PM -0800, Saravana Kannan wrote:
> > If the driver is calling clk_prepare() right next to clk_enable()
> > knowing it's been already prepared and will hence be "atomic" (this
> > is actually not true), then by your description, it's pointless to
> > call clk_prepare().
> Well not completely, as it increases the reference count.  The advantage
> would be that clk_enable counts addionally as prepare, so it would be
> impossible to unprepare an enabled clock.  And the other way round an
> unprepared clock would never be enabled.
>  
> > If you want the driver to call clk_prepare() in atomic context
> > because it will be atomic in most cases -- well, that's wrong. It's
> > either atomic or is NOT atomic. There is no in between. If a call is
> > NOT atomic, it can't be called in atomic context. Long story short,
> > if you expect clk_prepare() to be atomic under any circumstance, it
> > beats the point of introducing clk_prepare().
> Well, with my suggestion it's atomic when certain precondions are given.
> IMHO that's better than "atomic in most cases" because the caller can
> assert that everything goes smooth.
> These preconditions are asserted when the driver writer is careful
> enough to stick to the API.
IMHO, clk_prepare is always called in non-atomic context, so it doesn't matter
whether it's really atomic or not. We don't have to make it as atomic as
possible.

Thanks
Richard
> 
> Either my idea is bad or I'm unable to sell it appropriately.  Be it as
> it is, I will stop to make a case for it.
> 
> Best regards and thanks for your try,
> Uwe
> 
> -- 
> Pengutronix e.K.                           | Uwe Kleine-König            |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04  9:33                           ` Richard Zhao
  0 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-04  9:33 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Saravana Kannan, Nicolas Pitre, Lorenzo Pieralisi,
	Russell King - ARM Linux, linux-sh, Ben Herrenschmidt,
	Sascha Hauer, Paul Mundt, linux-kernel, Dima Zavin, Ben Dooks,
	Vincent Guittot, Jeremy Kerr, linux-arm-kernel

On Tue, Feb 01, 2011 at 09:43:31PM +0100, Uwe Kleine-König wrote:
> Hello,
> 
> On Tue, Feb 01, 2011 at 12:21:45PM -0800, Saravana Kannan wrote:
> > If the driver is calling clk_prepare() right next to clk_enable()
> > knowing it's been already prepared and will hence be "atomic" (this
> > is actually not true), then by your description, it's pointless to
> > call clk_prepare().
> Well not completely, as it increases the reference count.  The advantage
> would be that clk_enable counts addionally as prepare, so it would be
> impossible to unprepare an enabled clock.  And the other way round an
> unprepared clock would never be enabled.
>  
> > If you want the driver to call clk_prepare() in atomic context
> > because it will be atomic in most cases -- well, that's wrong. It's
> > either atomic or is NOT atomic. There is no in between. If a call is
> > NOT atomic, it can't be called in atomic context. Long story short,
> > if you expect clk_prepare() to be atomic under any circumstance, it
> > beats the point of introducing clk_prepare().
> Well, with my suggestion it's atomic when certain precondions are given.
> IMHO that's better than "atomic in most cases" because the caller can
> assert that everything goes smooth.
> These preconditions are asserted when the driver writer is careful
> enough to stick to the API.
IMHO, clk_prepare is always called in non-atomic context, so it doesn't matter
whether it's really atomic or not. We don't have to make it as atomic as
possible.

Thanks
Richard
> 
> Either my idea is bad or I'm unable to sell it appropriately.  Be it as
> it is, I will stop to make a case for it.
> 
> Best regards and thanks for your try,
> Uwe
> 
> -- 
> Pengutronix e.K.                           | Uwe Kleine-König            |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04  9:33                           ` Richard Zhao
  0 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-04  9:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 09:43:31PM +0100, Uwe Kleine-K?nig wrote:
> Hello,
> 
> On Tue, Feb 01, 2011 at 12:21:45PM -0800, Saravana Kannan wrote:
> > If the driver is calling clk_prepare() right next to clk_enable()
> > knowing it's been already prepared and will hence be "atomic" (this
> > is actually not true), then by your description, it's pointless to
> > call clk_prepare().
> Well not completely, as it increases the reference count.  The advantage
> would be that clk_enable counts addionally as prepare, so it would be
> impossible to unprepare an enabled clock.  And the other way round an
> unprepared clock would never be enabled.
>  
> > If you want the driver to call clk_prepare() in atomic context
> > because it will be atomic in most cases -- well, that's wrong. It's
> > either atomic or is NOT atomic. There is no in between. If a call is
> > NOT atomic, it can't be called in atomic context. Long story short,
> > if you expect clk_prepare() to be atomic under any circumstance, it
> > beats the point of introducing clk_prepare().
> Well, with my suggestion it's atomic when certain precondions are given.
> IMHO that's better than "atomic in most cases" because the caller can
> assert that everything goes smooth.
> These preconditions are asserted when the driver writer is careful
> enough to stick to the API.
IMHO, clk_prepare is always called in non-atomic context, so it doesn't matter
whether it's really atomic or not. We don't have to make it as atomic as
possible.

Thanks
Richard
> 
> Either my idea is bad or I'm unable to sell it appropriately.  Be it as
> it is, I will stop to make a case for it.
> 
> Best regards and thanks for your try,
> Uwe
> 
> -- 
> Pengutronix e.K.                           | Uwe Kleine-K?nig            |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01 21:24                 ` Russell King - ARM Linux
  (?)
@ 2011-02-04  9:54                   ` Richard Zhao
  -1 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-04  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 09:24:09PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 12:59:11PM -0800, Stephen Boyd wrote:
> > On 02/01/2011 07:24 AM, Russell King - ARM Linux wrote:
> > > I'd also be tempted at this stage to build-in a no-op dummy clock,
> > > that being the NULL clk:
> > >
> > > int clk_prepare(struct clk *clk)
> > > {
> > > 	int ret = 0;
> > >
> > > 	if (clk) {
> > > 		mutex_lock(&clk->mutex);
> > > 		if (clk->prepared = 0)
> > > 			ret = clk->ops->prepare(clk);
> > > 		if (ret = 0)
> > > 			clk->prepared++;
> > > 		mutex_unlock(&clk->mutex);
> > > 	}
> > >
> > > 	return ret;
> > > }
> > 
> > I'm afraid this will hide enable/disable imbalances on some targets and
> > then expose them on others. Maybe its not a big problem though since
> > this also elegantly handles the root(s) of the tree.
> 
> You can't catch enable/disable imbalances in the prepare code, and you
> can't really catch them in the unprepare code either.
> 
> Consider two drivers sharing the same struct clk.  When the second driver
> prepares the clock, the enable count could well be non-zero, caused by
> the first driver.  Ditto for when the second driver is removed, and it
> calls unprepare - the enable count may well be non-zero.
> 
> The only thing you can check is that when the prepare count is zero,
> the enable count is also zero.  You can also check in clk_enable() and
> clk_disable() that the prepare count is non-zero.
but how can we check prepare count without mutex lock? Even if prepare count
is atomic_t, it can not guarantee the clock is actually prepared or unprepared.
So it's important for driver writer to maintain the call sequence.

Thanks
Richard
> 
> If you want tigher checking than that, you need to somehow identify and
> match up the clk_prepare/clk_enable/clk_disable/clk_unprepare calls from
> a particular driver instance.  Addresses of the functions don't work as
> you can't be certain that driver code will be co-located within a certain
> range.  Adding an additional argument to these functions which is driver
> instance specific seems to be horrible too.
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04  9:54                   ` Richard Zhao
  0 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-04  9:54 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Stephen Boyd, Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, linux-kernel, Saravana Kannan, Ben Dooks,
	Uwe Kleine-König, Jeremy Kerr, linux-arm-kernel

On Tue, Feb 01, 2011 at 09:24:09PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 12:59:11PM -0800, Stephen Boyd wrote:
> > On 02/01/2011 07:24 AM, Russell King - ARM Linux wrote:
> > > I'd also be tempted at this stage to build-in a no-op dummy clock,
> > > that being the NULL clk:
> > >
> > > int clk_prepare(struct clk *clk)
> > > {
> > > 	int ret = 0;
> > >
> > > 	if (clk) {
> > > 		mutex_lock(&clk->mutex);
> > > 		if (clk->prepared == 0)
> > > 			ret = clk->ops->prepare(clk);
> > > 		if (ret == 0)
> > > 			clk->prepared++;
> > > 		mutex_unlock(&clk->mutex);
> > > 	}
> > >
> > > 	return ret;
> > > }
> > 
> > I'm afraid this will hide enable/disable imbalances on some targets and
> > then expose them on others. Maybe its not a big problem though since
> > this also elegantly handles the root(s) of the tree.
> 
> You can't catch enable/disable imbalances in the prepare code, and you
> can't really catch them in the unprepare code either.
> 
> Consider two drivers sharing the same struct clk.  When the second driver
> prepares the clock, the enable count could well be non-zero, caused by
> the first driver.  Ditto for when the second driver is removed, and it
> calls unprepare - the enable count may well be non-zero.
> 
> The only thing you can check is that when the prepare count is zero,
> the enable count is also zero.  You can also check in clk_enable() and
> clk_disable() that the prepare count is non-zero.
but how can we check prepare count without mutex lock? Even if prepare count
is atomic_t, it can not guarantee the clock is actually prepared or unprepared.
So it's important for driver writer to maintain the call sequence.

Thanks
Richard
> 
> If you want tigher checking than that, you need to somehow identify and
> match up the clk_prepare/clk_enable/clk_disable/clk_unprepare calls from
> a particular driver instance.  Addresses of the functions don't work as
> you can't be certain that driver code will be co-located within a certain
> range.  Adding an additional argument to these functions which is driver
> instance specific seems to be horrible too.
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04  9:54                   ` Richard Zhao
  0 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-04  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 09:24:09PM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 01, 2011 at 12:59:11PM -0800, Stephen Boyd wrote:
> > On 02/01/2011 07:24 AM, Russell King - ARM Linux wrote:
> > > I'd also be tempted at this stage to build-in a no-op dummy clock,
> > > that being the NULL clk:
> > >
> > > int clk_prepare(struct clk *clk)
> > > {
> > > 	int ret = 0;
> > >
> > > 	if (clk) {
> > > 		mutex_lock(&clk->mutex);
> > > 		if (clk->prepared == 0)
> > > 			ret = clk->ops->prepare(clk);
> > > 		if (ret == 0)
> > > 			clk->prepared++;
> > > 		mutex_unlock(&clk->mutex);
> > > 	}
> > >
> > > 	return ret;
> > > }
> > 
> > I'm afraid this will hide enable/disable imbalances on some targets and
> > then expose them on others. Maybe its not a big problem though since
> > this also elegantly handles the root(s) of the tree.
> 
> You can't catch enable/disable imbalances in the prepare code, and you
> can't really catch them in the unprepare code either.
> 
> Consider two drivers sharing the same struct clk.  When the second driver
> prepares the clock, the enable count could well be non-zero, caused by
> the first driver.  Ditto for when the second driver is removed, and it
> calls unprepare - the enable count may well be non-zero.
> 
> The only thing you can check is that when the prepare count is zero,
> the enable count is also zero.  You can also check in clk_enable() and
> clk_disable() that the prepare count is non-zero.
but how can we check prepare count without mutex lock? Even if prepare count
is atomic_t, it can not guarantee the clock is actually prepared or unprepared.
So it's important for driver writer to maintain the call sequence.

Thanks
Richard
> 
> If you want tigher checking than that, you need to somehow identify and
> match up the clk_prepare/clk_enable/clk_disable/clk_unprepare calls from
> a particular driver instance.  Addresses of the functions don't work as
> you can't be certain that driver code will be co-located within a certain
> range.  Adding an additional argument to these functions which is driver
> instance specific seems to be horrible too.
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-04  9:54                   ` Richard Zhao
  (?)
@ 2011-02-04 10:21                     ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-04 10:21 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Richard,

On Fri, Feb 04, 2011 at 05:54:24PM +0800, Richard Zhao wrote:
> On Tue, Feb 01, 2011 at 09:24:09PM +0000, Russell King - ARM Linux wrote:
> > On Tue, Feb 01, 2011 at 12:59:11PM -0800, Stephen Boyd wrote:
> > > On 02/01/2011 07:24 AM, Russell King - ARM Linux wrote:
> > > > I'd also be tempted at this stage to build-in a no-op dummy clock,
> > > > that being the NULL clk:
> > > >
> > > > int clk_prepare(struct clk *clk)
> > > > {
> > > > 	int ret = 0;
> > > >
> > > > 	if (clk) {
> > > > 		mutex_lock(&clk->mutex);
> > > > 		if (clk->prepared = 0)
> > > > 			ret = clk->ops->prepare(clk);
> > > > 		if (ret = 0)
> > > > 			clk->prepared++;
> > > > 		mutex_unlock(&clk->mutex);
> > > > 	}
> > > >
> > > > 	return ret;
> > > > }
> > > 
> > > I'm afraid this will hide enable/disable imbalances on some targets and
> > > then expose them on others. Maybe its not a big problem though since
> > > this also elegantly handles the root(s) of the tree.
> > 
> > You can't catch enable/disable imbalances in the prepare code, and you
> > can't really catch them in the unprepare code either.
> > 
> > Consider two drivers sharing the same struct clk.  When the second driver
> > prepares the clock, the enable count could well be non-zero, caused by
> > the first driver.  Ditto for when the second driver is removed, and it
> > calls unprepare - the enable count may well be non-zero.
> > 
> > The only thing you can check is that when the prepare count is zero,
> > the enable count is also zero.  You can also check in clk_enable() and
> > clk_disable() that the prepare count is non-zero.
> but how can we check prepare count without mutex lock? Even if prepare count
> is atomic_t, it can not guarantee the clock is actually prepared or unprepared.
> So it's important for driver writer to maintain the call sequence.
I happily point out that the prepare_count needs to be protected by a
spinlock and you need a flag that signals a prepare or unprepare is
currently running.

SCNR
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04 10:21                     ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-04 10:21 UTC (permalink / raw)
  To: Richard Zhao
  Cc: Russell King - ARM Linux, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, Stephen Boyd, linux-kernel, Dima Zavin,
	Saravana Kannan, Ben Dooks, Jeremy Kerr, linux-arm-kernel

Hello Richard,

On Fri, Feb 04, 2011 at 05:54:24PM +0800, Richard Zhao wrote:
> On Tue, Feb 01, 2011 at 09:24:09PM +0000, Russell King - ARM Linux wrote:
> > On Tue, Feb 01, 2011 at 12:59:11PM -0800, Stephen Boyd wrote:
> > > On 02/01/2011 07:24 AM, Russell King - ARM Linux wrote:
> > > > I'd also be tempted at this stage to build-in a no-op dummy clock,
> > > > that being the NULL clk:
> > > >
> > > > int clk_prepare(struct clk *clk)
> > > > {
> > > > 	int ret = 0;
> > > >
> > > > 	if (clk) {
> > > > 		mutex_lock(&clk->mutex);
> > > > 		if (clk->prepared == 0)
> > > > 			ret = clk->ops->prepare(clk);
> > > > 		if (ret == 0)
> > > > 			clk->prepared++;
> > > > 		mutex_unlock(&clk->mutex);
> > > > 	}
> > > >
> > > > 	return ret;
> > > > }
> > > 
> > > I'm afraid this will hide enable/disable imbalances on some targets and
> > > then expose them on others. Maybe its not a big problem though since
> > > this also elegantly handles the root(s) of the tree.
> > 
> > You can't catch enable/disable imbalances in the prepare code, and you
> > can't really catch them in the unprepare code either.
> > 
> > Consider two drivers sharing the same struct clk.  When the second driver
> > prepares the clock, the enable count could well be non-zero, caused by
> > the first driver.  Ditto for when the second driver is removed, and it
> > calls unprepare - the enable count may well be non-zero.
> > 
> > The only thing you can check is that when the prepare count is zero,
> > the enable count is also zero.  You can also check in clk_enable() and
> > clk_disable() that the prepare count is non-zero.
> but how can we check prepare count without mutex lock? Even if prepare count
> is atomic_t, it can not guarantee the clock is actually prepared or unprepared.
> So it's important for driver writer to maintain the call sequence.
I happily point out that the prepare_count needs to be protected by a
spinlock and you need a flag that signals a prepare or unprepare is
currently running.

SCNR
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04 10:21                     ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-04 10:21 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Richard,

On Fri, Feb 04, 2011 at 05:54:24PM +0800, Richard Zhao wrote:
> On Tue, Feb 01, 2011 at 09:24:09PM +0000, Russell King - ARM Linux wrote:
> > On Tue, Feb 01, 2011 at 12:59:11PM -0800, Stephen Boyd wrote:
> > > On 02/01/2011 07:24 AM, Russell King - ARM Linux wrote:
> > > > I'd also be tempted at this stage to build-in a no-op dummy clock,
> > > > that being the NULL clk:
> > > >
> > > > int clk_prepare(struct clk *clk)
> > > > {
> > > > 	int ret = 0;
> > > >
> > > > 	if (clk) {
> > > > 		mutex_lock(&clk->mutex);
> > > > 		if (clk->prepared == 0)
> > > > 			ret = clk->ops->prepare(clk);
> > > > 		if (ret == 0)
> > > > 			clk->prepared++;
> > > > 		mutex_unlock(&clk->mutex);
> > > > 	}
> > > >
> > > > 	return ret;
> > > > }
> > > 
> > > I'm afraid this will hide enable/disable imbalances on some targets and
> > > then expose them on others. Maybe its not a big problem though since
> > > this also elegantly handles the root(s) of the tree.
> > 
> > You can't catch enable/disable imbalances in the prepare code, and you
> > can't really catch them in the unprepare code either.
> > 
> > Consider two drivers sharing the same struct clk.  When the second driver
> > prepares the clock, the enable count could well be non-zero, caused by
> > the first driver.  Ditto for when the second driver is removed, and it
> > calls unprepare - the enable count may well be non-zero.
> > 
> > The only thing you can check is that when the prepare count is zero,
> > the enable count is also zero.  You can also check in clk_enable() and
> > clk_disable() that the prepare count is non-zero.
> but how can we check prepare count without mutex lock? Even if prepare count
> is atomic_t, it can not guarantee the clock is actually prepared or unprepared.
> So it's important for driver writer to maintain the call sequence.
I happily point out that the prepare_count needs to be protected by a
spinlock and you need a flag that signals a prepare or unprepare is
currently running.

SCNR
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-04  9:54                   ` Richard Zhao
  (?)
@ 2011-02-04 10:48                     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-04 10:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 04, 2011 at 05:54:24PM +0800, Richard Zhao wrote:
> On Tue, Feb 01, 2011 at 09:24:09PM +0000, Russell King - ARM Linux wrote:
> > You can't catch enable/disable imbalances in the prepare code, and you
> > can't really catch them in the unprepare code either.
> > 
> > Consider two drivers sharing the same struct clk.  When the second driver
> > prepares the clock, the enable count could well be non-zero, caused by
> > the first driver.  Ditto for when the second driver is removed, and it
> > calls unprepare - the enable count may well be non-zero.
> > 
> > The only thing you can check is that when the prepare count is zero,
> > the enable count is also zero.  You can also check in clk_enable() and
> > clk_disable() that the prepare count is non-zero.
>
> but how can we check prepare count without mutex lock? Even if prepare count
> is atomic_t, it can not guarantee the clock is actually prepared or unprepared.
> So it's important for driver writer to maintain the call sequence.

Forget atomic_t - it's the most abused type in the kernel.  Just because
something says its atomic doesn't make it so.  In a use like this,
atomic_t just buys you additional needless complexity with no benefit.

Of course we can check the prepared count.  What we can't do is check
that it doesn't change concurrently - but that's something we can't do
anyway.

int clk_enable(struct clk *clk)
{
	unsigned long flags;
	int ret = 0;

	if (clk) {
		if (WARN_ON(!clk->prepare_count))
			return -EINVAL;

		spin_lock_irqsave(&clk->lock, flags);
		if (clk->enable_count++ = 0)
			ret = clk->ops->enable(clk);
		spin_unlock_irqrestore(&clk->lock, flags);
	}
	return ret;
}

is entirely sufficient to catch the case of a single-use clock not being
prepared before clk_enable() is called.

We're after detecting drivers missing calls to clk_prepare(), we're not
after detecting concurrent calls to clk_prepare()/clk_unprepare().

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04 10:48                     ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-04 10:48 UTC (permalink / raw)
  To: Richard Zhao
  Cc: Stephen Boyd, Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, linux-kernel, Saravana Kannan, Ben Dooks,
	Uwe Kleine-König, Jeremy Kerr, linux-arm-kernel

On Fri, Feb 04, 2011 at 05:54:24PM +0800, Richard Zhao wrote:
> On Tue, Feb 01, 2011 at 09:24:09PM +0000, Russell King - ARM Linux wrote:
> > You can't catch enable/disable imbalances in the prepare code, and you
> > can't really catch them in the unprepare code either.
> > 
> > Consider two drivers sharing the same struct clk.  When the second driver
> > prepares the clock, the enable count could well be non-zero, caused by
> > the first driver.  Ditto for when the second driver is removed, and it
> > calls unprepare - the enable count may well be non-zero.
> > 
> > The only thing you can check is that when the prepare count is zero,
> > the enable count is also zero.  You can also check in clk_enable() and
> > clk_disable() that the prepare count is non-zero.
>
> but how can we check prepare count without mutex lock? Even if prepare count
> is atomic_t, it can not guarantee the clock is actually prepared or unprepared.
> So it's important for driver writer to maintain the call sequence.

Forget atomic_t - it's the most abused type in the kernel.  Just because
something says its atomic doesn't make it so.  In a use like this,
atomic_t just buys you additional needless complexity with no benefit.

Of course we can check the prepared count.  What we can't do is check
that it doesn't change concurrently - but that's something we can't do
anyway.

int clk_enable(struct clk *clk)
{
	unsigned long flags;
	int ret = 0;

	if (clk) {
		if (WARN_ON(!clk->prepare_count))
			return -EINVAL;

		spin_lock_irqsave(&clk->lock, flags);
		if (clk->enable_count++ == 0)
			ret = clk->ops->enable(clk);
		spin_unlock_irqrestore(&clk->lock, flags);
	}
	return ret;
}

is entirely sufficient to catch the case of a single-use clock not being
prepared before clk_enable() is called.

We're after detecting drivers missing calls to clk_prepare(), we're not
after detecting concurrent calls to clk_prepare()/clk_unprepare().

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04 10:48                     ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-04 10:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 04, 2011 at 05:54:24PM +0800, Richard Zhao wrote:
> On Tue, Feb 01, 2011 at 09:24:09PM +0000, Russell King - ARM Linux wrote:
> > You can't catch enable/disable imbalances in the prepare code, and you
> > can't really catch them in the unprepare code either.
> > 
> > Consider two drivers sharing the same struct clk.  When the second driver
> > prepares the clock, the enable count could well be non-zero, caused by
> > the first driver.  Ditto for when the second driver is removed, and it
> > calls unprepare - the enable count may well be non-zero.
> > 
> > The only thing you can check is that when the prepare count is zero,
> > the enable count is also zero.  You can also check in clk_enable() and
> > clk_disable() that the prepare count is non-zero.
>
> but how can we check prepare count without mutex lock? Even if prepare count
> is atomic_t, it can not guarantee the clock is actually prepared or unprepared.
> So it's important for driver writer to maintain the call sequence.

Forget atomic_t - it's the most abused type in the kernel.  Just because
something says its atomic doesn't make it so.  In a use like this,
atomic_t just buys you additional needless complexity with no benefit.

Of course we can check the prepared count.  What we can't do is check
that it doesn't change concurrently - but that's something we can't do
anyway.

int clk_enable(struct clk *clk)
{
	unsigned long flags;
	int ret = 0;

	if (clk) {
		if (WARN_ON(!clk->prepare_count))
			return -EINVAL;

		spin_lock_irqsave(&clk->lock, flags);
		if (clk->enable_count++ == 0)
			ret = clk->ops->enable(clk);
		spin_unlock_irqrestore(&clk->lock, flags);
	}
	return ret;
}

is entirely sufficient to catch the case of a single-use clock not being
prepared before clk_enable() is called.

We're after detecting drivers missing calls to clk_prepare(), we're not
after detecting concurrent calls to clk_prepare()/clk_unprepare().

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-04 10:21                     ` Uwe Kleine-König
  (?)
@ 2011-02-04 10:57                       ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-04 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 04, 2011 at 11:21:20AM +0100, Uwe Kleine-König wrote:
> I happily point out that the prepare_count needs to be protected by a
> spinlock and you need a flag that signals a prepare or unprepare is
> currently running.

It's really simple.  You don't use a struct clk pointer in any way until
you've called a clk_get() to get a pointer.  So what's the problem with
ensuring that you do clk_prepare() on it before you register whatever
services may end up calling clk_enable().

That is good practice.  It's precisely the same practice which says that
you shall not register device drivers with subsystems, thereby making
them visible, until you're absolutely ready in the driver to start taking
requests to use your driver.  Precisely the same thing applies here.

In other words, to go back to the UART console driver case, in the
UART console setup function, you do this:

	clk = clk_get(...);
	if (IS_ERR(clk))
		return PTR_ERR(clk);

	err = clk_prepare(clk);
	if (err) {
		clk_put(clk);
		return err;
	}

	rate = clk_get_rate(clk);
	... setup UART, setup baud rate according to rate ...

	return 0;

So, this means that clk_enable() in the console write function will not
be called until after the initialization function has finished - by which
time clk_prepare() will have completed.

There is no need for any kind of spinlocking, atomic types or other such
crap for the prepare count.  We do not care about concurrent clk_enables().

The only time you'd need such games as you're suggesting is if you're still
promoting your idea about calling clk_prepare() from clk_enable() "in case
driver writers forget it", which is soo broken it's untrue.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04 10:57                       ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-04 10:57 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Richard Zhao, Nicolas Pitre, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	Stephen Boyd, linux-kernel, Dima Zavin, Saravana Kannan,
	Ben Dooks, Jeremy Kerr, linux-arm-kernel

On Fri, Feb 04, 2011 at 11:21:20AM +0100, Uwe Kleine-König wrote:
> I happily point out that the prepare_count needs to be protected by a
> spinlock and you need a flag that signals a prepare or unprepare is
> currently running.

It's really simple.  You don't use a struct clk pointer in any way until
you've called a clk_get() to get a pointer.  So what's the problem with
ensuring that you do clk_prepare() on it before you register whatever
services may end up calling clk_enable().

That is good practice.  It's precisely the same practice which says that
you shall not register device drivers with subsystems, thereby making
them visible, until you're absolutely ready in the driver to start taking
requests to use your driver.  Precisely the same thing applies here.

In other words, to go back to the UART console driver case, in the
UART console setup function, you do this:

	clk = clk_get(...);
	if (IS_ERR(clk))
		return PTR_ERR(clk);

	err = clk_prepare(clk);
	if (err) {
		clk_put(clk);
		return err;
	}

	rate = clk_get_rate(clk);
	... setup UART, setup baud rate according to rate ...

	return 0;

So, this means that clk_enable() in the console write function will not
be called until after the initialization function has finished - by which
time clk_prepare() will have completed.

There is no need for any kind of spinlocking, atomic types or other such
crap for the prepare count.  We do not care about concurrent clk_enables().

The only time you'd need such games as you're suggesting is if you're still
promoting your idea about calling clk_prepare() from clk_enable() "in case
driver writers forget it", which is soo broken it's untrue.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04 10:57                       ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-04 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 04, 2011 at 11:21:20AM +0100, Uwe Kleine-K?nig wrote:
> I happily point out that the prepare_count needs to be protected by a
> spinlock and you need a flag that signals a prepare or unprepare is
> currently running.

It's really simple.  You don't use a struct clk pointer in any way until
you've called a clk_get() to get a pointer.  So what's the problem with
ensuring that you do clk_prepare() on it before you register whatever
services may end up calling clk_enable().

That is good practice.  It's precisely the same practice which says that
you shall not register device drivers with subsystems, thereby making
them visible, until you're absolutely ready in the driver to start taking
requests to use your driver.  Precisely the same thing applies here.

In other words, to go back to the UART console driver case, in the
UART console setup function, you do this:

	clk = clk_get(...);
	if (IS_ERR(clk))
		return PTR_ERR(clk);

	err = clk_prepare(clk);
	if (err) {
		clk_put(clk);
		return err;
	}

	rate = clk_get_rate(clk);
	... setup UART, setup baud rate according to rate ...

	return 0;

So, this means that clk_enable() in the console write function will not
be called until after the initialization function has finished - by which
time clk_prepare() will have completed.

There is no need for any kind of spinlocking, atomic types or other such
crap for the prepare count.  We do not care about concurrent clk_enables().

The only time you'd need such games as you're suggesting is if you're still
promoting your idea about calling clk_prepare() from clk_enable() "in case
driver writers forget it", which is soo broken it's untrue.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-04 10:48                     ` Russell King - ARM Linux
  (?)
@ 2011-02-04 11:04                       ` Jassi Brar
  -1 siblings, 0 replies; 383+ messages in thread
From: Jassi Brar @ 2011-02-04 11:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 4, 2011 at 7:48 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:

> int clk_enable(struct clk *clk)
> {
>        unsigned long flags;
>        int ret = 0;
>
>        if (clk) {
>                if (WARN_ON(!clk->prepare_count))
>                        return -EINVAL;
>
>                spin_lock_irqsave(&clk->lock, flags);
>                if (clk->enable_count++ = 0)
>                        ret = clk->ops->enable(clk);
>                spin_unlock_irqrestore(&clk->lock, flags);
>        }
>        return ret;
> }
>
> is entirely sufficient to catch the case of a single-use clock not being
> prepared before clk_enable() is called.
>
> We're after detecting drivers missing calls to clk_prepare(), we're not
> after detecting concurrent calls to clk_prepare()/clk_unprepare().

I hope you mean 'making sure the clock is prepared before it's enabled
' rather than
'catching a driver that doesn't do clk_prepare before clk_enable'.
Because, the above implementation still doesn't catch a driver that
doesn't call clk_prepare
but simply uses a clock that happens to have been already prepare'd by
some other
driver or the platform.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04 11:04                       ` Jassi Brar
  0 siblings, 0 replies; 383+ messages in thread
From: Jassi Brar @ 2011-02-04 11:04 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Richard Zhao, Nicolas Pitre, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	Stephen Boyd, linux-kernel, Dima Zavin, Saravana Kannan,
	Ben Dooks, Uwe Kleine-König, Jeremy Kerr, linux-arm-kernel

On Fri, Feb 4, 2011 at 7:48 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:

> int clk_enable(struct clk *clk)
> {
>        unsigned long flags;
>        int ret = 0;
>
>        if (clk) {
>                if (WARN_ON(!clk->prepare_count))
>                        return -EINVAL;
>
>                spin_lock_irqsave(&clk->lock, flags);
>                if (clk->enable_count++ == 0)
>                        ret = clk->ops->enable(clk);
>                spin_unlock_irqrestore(&clk->lock, flags);
>        }
>        return ret;
> }
>
> is entirely sufficient to catch the case of a single-use clock not being
> prepared before clk_enable() is called.
>
> We're after detecting drivers missing calls to clk_prepare(), we're not
> after detecting concurrent calls to clk_prepare()/clk_unprepare().

I hope you mean 'making sure the clock is prepared before it's enabled
' rather than
'catching a driver that doesn't do clk_prepare before clk_enable'.
Because, the above implementation still doesn't catch a driver that
doesn't call clk_prepare
but simply uses a clock that happens to have been already prepare'd by
some other
driver or the platform.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04 11:04                       ` Jassi Brar
  0 siblings, 0 replies; 383+ messages in thread
From: Jassi Brar @ 2011-02-04 11:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 4, 2011 at 7:48 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:

> int clk_enable(struct clk *clk)
> {
> ? ? ? ?unsigned long flags;
> ? ? ? ?int ret = 0;
>
> ? ? ? ?if (clk) {
> ? ? ? ? ? ? ? ?if (WARN_ON(!clk->prepare_count))
> ? ? ? ? ? ? ? ? ? ? ? ?return -EINVAL;
>
> ? ? ? ? ? ? ? ?spin_lock_irqsave(&clk->lock, flags);
> ? ? ? ? ? ? ? ?if (clk->enable_count++ == 0)
> ? ? ? ? ? ? ? ? ? ? ? ?ret = clk->ops->enable(clk);
> ? ? ? ? ? ? ? ?spin_unlock_irqrestore(&clk->lock, flags);
> ? ? ? ?}
> ? ? ? ?return ret;
> }
>
> is entirely sufficient to catch the case of a single-use clock not being
> prepared before clk_enable() is called.
>
> We're after detecting drivers missing calls to clk_prepare(), we're not
> after detecting concurrent calls to clk_prepare()/clk_unprepare().

I hope you mean 'making sure the clock is prepared before it's enabled
' rather than
'catching a driver that doesn't do clk_prepare before clk_enable'.
Because, the above implementation still doesn't catch a driver that
doesn't call clk_prepare
but simply uses a clock that happens to have been already prepare'd by
some other
driver or the platform.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-04 11:04                       ` Jassi Brar
  (?)
@ 2011-02-04 11:18                         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-04 11:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 04, 2011 at 08:04:03PM +0900, Jassi Brar wrote:
> On Fri, Feb 4, 2011 at 7:48 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> 
> > int clk_enable(struct clk *clk)
> > {
> >        unsigned long flags;
> >        int ret = 0;
> >
> >        if (clk) {
> >                if (WARN_ON(!clk->prepare_count))
> >                        return -EINVAL;
> >
> >                spin_lock_irqsave(&clk->lock, flags);
> >                if (clk->enable_count++ = 0)
> >                        ret = clk->ops->enable(clk);
> >                spin_unlock_irqrestore(&clk->lock, flags);
> >        }
> >        return ret;
> > }
> >
> > is entirely sufficient to catch the case of a single-use clock not being
> > prepared before clk_enable() is called.
> >
> > We're after detecting drivers missing calls to clk_prepare(), we're not
> > after detecting concurrent calls to clk_prepare()/clk_unprepare().
> 
> I hope you mean 'making sure the clock is prepared before it's enabled
> ' rather than
> 'catching a driver that doesn't do clk_prepare before clk_enable'.
> Because, the above implementation still doesn't catch a driver that
> doesn't call clk_prepare
> but simply uses a clock that happens to have been already prepare'd by
> some other
> driver or the platform.

No, I mean what I said.

The only way to do what you're asking is to attach a list of identifiers
which have prepared a clock to the struct clk, where each identifier is
unique to each driver instance.

So what that becomes is:

struct prepared_instance {
	struct list_head node;
	void *driver_id;
};

int clk_prepare(struct clk *clk, void *driver_id)
{
	struct prepared_instance *inst;
	int ret = 0;

	if (clk) {
		inst = kmalloc(sizeof(*inst), GFP_KERNEL);
		if (!inst)
			return -ENOMEM;

		inst->driver_id = driver_id;

		mutex_lock(&clk->mutex);
		if (clk->prepare_count++ = 0)
			ret = clk->ops->prepare(clk);

		if (ret = 0) {
			spin_lock_irqsave(&clk->lock, flags);
			list_add(&inst->node, &clk->prepare_list);
			spin_unlock_irqrestore(&clk->lock, flags);
		} else
			clk->prepare_count--;
		mutex_unlock(&clk->mutex);
	}
	return ret;
}

int clk_enable(struct clk *clk, void *driver_id)
{
	unsigned long flags;
	int ret = 0;

	if (clk) {
		struct prepare_instance *inst;

		spin_lock_irqsave(&clk->lock, flags);
		list_for_each_entry(inst, &clk->prepare_list, node)
			if (inst = driver_id)
				ret = -EINVAL;

		if (ret = 0 && clk->enable_count++ = 0) {
			ret = clk->ops->enable(clk);
			if (ret)
				clk->enable_count--;
		}
		spin_unlock_irqrestore(&clk->lock, flags);
	}
	return ret;
}

I think that's going completely over the top, and adds needless complexity
to drivers, which now have to pass an instance specific cookie into every
clk API call.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04 11:18                         ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-04 11:18 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Richard Zhao, Nicolas Pitre, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	Stephen Boyd, linux-kernel, Dima Zavin, Saravana Kannan,
	Ben Dooks, Uwe Kleine-König, Jeremy Kerr, linux-arm-kernel

On Fri, Feb 04, 2011 at 08:04:03PM +0900, Jassi Brar wrote:
> On Fri, Feb 4, 2011 at 7:48 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> 
> > int clk_enable(struct clk *clk)
> > {
> >        unsigned long flags;
> >        int ret = 0;
> >
> >        if (clk) {
> >                if (WARN_ON(!clk->prepare_count))
> >                        return -EINVAL;
> >
> >                spin_lock_irqsave(&clk->lock, flags);
> >                if (clk->enable_count++ == 0)
> >                        ret = clk->ops->enable(clk);
> >                spin_unlock_irqrestore(&clk->lock, flags);
> >        }
> >        return ret;
> > }
> >
> > is entirely sufficient to catch the case of a single-use clock not being
> > prepared before clk_enable() is called.
> >
> > We're after detecting drivers missing calls to clk_prepare(), we're not
> > after detecting concurrent calls to clk_prepare()/clk_unprepare().
> 
> I hope you mean 'making sure the clock is prepared before it's enabled
> ' rather than
> 'catching a driver that doesn't do clk_prepare before clk_enable'.
> Because, the above implementation still doesn't catch a driver that
> doesn't call clk_prepare
> but simply uses a clock that happens to have been already prepare'd by
> some other
> driver or the platform.

No, I mean what I said.

The only way to do what you're asking is to attach a list of identifiers
which have prepared a clock to the struct clk, where each identifier is
unique to each driver instance.

So what that becomes is:

struct prepared_instance {
	struct list_head node;
	void *driver_id;
};

int clk_prepare(struct clk *clk, void *driver_id)
{
	struct prepared_instance *inst;
	int ret = 0;

	if (clk) {
		inst = kmalloc(sizeof(*inst), GFP_KERNEL);
		if (!inst)
			return -ENOMEM;

		inst->driver_id = driver_id;

		mutex_lock(&clk->mutex);
		if (clk->prepare_count++ == 0)
			ret = clk->ops->prepare(clk);

		if (ret == 0) {
			spin_lock_irqsave(&clk->lock, flags);
			list_add(&inst->node, &clk->prepare_list);
			spin_unlock_irqrestore(&clk->lock, flags);
		} else
			clk->prepare_count--;
		mutex_unlock(&clk->mutex);
	}
	return ret;
}

int clk_enable(struct clk *clk, void *driver_id)
{
	unsigned long flags;
	int ret = 0;

	if (clk) {
		struct prepare_instance *inst;

		spin_lock_irqsave(&clk->lock, flags);
		list_for_each_entry(inst, &clk->prepare_list, node)
			if (inst == driver_id)
				ret = -EINVAL;

		if (ret == 0 && clk->enable_count++ == 0) {
			ret = clk->ops->enable(clk);
			if (ret)
				clk->enable_count--;
		}
		spin_unlock_irqrestore(&clk->lock, flags);
	}
	return ret;
}

I think that's going completely over the top, and adds needless complexity
to drivers, which now have to pass an instance specific cookie into every
clk API call.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04 11:18                         ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-04 11:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 04, 2011 at 08:04:03PM +0900, Jassi Brar wrote:
> On Fri, Feb 4, 2011 at 7:48 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> 
> > int clk_enable(struct clk *clk)
> > {
> > ? ? ? ?unsigned long flags;
> > ? ? ? ?int ret = 0;
> >
> > ? ? ? ?if (clk) {
> > ? ? ? ? ? ? ? ?if (WARN_ON(!clk->prepare_count))
> > ? ? ? ? ? ? ? ? ? ? ? ?return -EINVAL;
> >
> > ? ? ? ? ? ? ? ?spin_lock_irqsave(&clk->lock, flags);
> > ? ? ? ? ? ? ? ?if (clk->enable_count++ == 0)
> > ? ? ? ? ? ? ? ? ? ? ? ?ret = clk->ops->enable(clk);
> > ? ? ? ? ? ? ? ?spin_unlock_irqrestore(&clk->lock, flags);
> > ? ? ? ?}
> > ? ? ? ?return ret;
> > }
> >
> > is entirely sufficient to catch the case of a single-use clock not being
> > prepared before clk_enable() is called.
> >
> > We're after detecting drivers missing calls to clk_prepare(), we're not
> > after detecting concurrent calls to clk_prepare()/clk_unprepare().
> 
> I hope you mean 'making sure the clock is prepared before it's enabled
> ' rather than
> 'catching a driver that doesn't do clk_prepare before clk_enable'.
> Because, the above implementation still doesn't catch a driver that
> doesn't call clk_prepare
> but simply uses a clock that happens to have been already prepare'd by
> some other
> driver or the platform.

No, I mean what I said.

The only way to do what you're asking is to attach a list of identifiers
which have prepared a clock to the struct clk, where each identifier is
unique to each driver instance.

So what that becomes is:

struct prepared_instance {
	struct list_head node;
	void *driver_id;
};

int clk_prepare(struct clk *clk, void *driver_id)
{
	struct prepared_instance *inst;
	int ret = 0;

	if (clk) {
		inst = kmalloc(sizeof(*inst), GFP_KERNEL);
		if (!inst)
			return -ENOMEM;

		inst->driver_id = driver_id;

		mutex_lock(&clk->mutex);
		if (clk->prepare_count++ == 0)
			ret = clk->ops->prepare(clk);

		if (ret == 0) {
			spin_lock_irqsave(&clk->lock, flags);
			list_add(&inst->node, &clk->prepare_list);
			spin_unlock_irqrestore(&clk->lock, flags);
		} else
			clk->prepare_count--;
		mutex_unlock(&clk->mutex);
	}
	return ret;
}

int clk_enable(struct clk *clk, void *driver_id)
{
	unsigned long flags;
	int ret = 0;

	if (clk) {
		struct prepare_instance *inst;

		spin_lock_irqsave(&clk->lock, flags);
		list_for_each_entry(inst, &clk->prepare_list, node)
			if (inst == driver_id)
				ret = -EINVAL;

		if (ret == 0 && clk->enable_count++ == 0) {
			ret = clk->ops->enable(clk);
			if (ret)
				clk->enable_count--;
		}
		spin_unlock_irqrestore(&clk->lock, flags);
	}
	return ret;
}

I think that's going completely over the top, and adds needless complexity
to drivers, which now have to pass an instance specific cookie into every
clk API call.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-04 11:18                         ` Russell King - ARM Linux
  (?)
@ 2011-02-04 11:51                           ` Jassi Brar
  -1 siblings, 0 replies; 383+ messages in thread
From: Jassi Brar @ 2011-02-04 11:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 4, 2011 at 8:18 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Fri, Feb 04, 2011 at 08:04:03PM +0900, Jassi Brar wrote:
>> On Fri, Feb 4, 2011 at 7:48 PM, Russell King - ARM Linux
>> <linux@arm.linux.org.uk> wrote:
>>
>> > int clk_enable(struct clk *clk)
>> > {
>> >        unsigned long flags;
>> >        int ret = 0;
>> >
>> >        if (clk) {
>> >                if (WARN_ON(!clk->prepare_count))
>> >                        return -EINVAL;
>> >
>> >                spin_lock_irqsave(&clk->lock, flags);
>> >                if (clk->enable_count++ = 0)
>> >                        ret = clk->ops->enable(clk);
>> >                spin_unlock_irqrestore(&clk->lock, flags);
>> >        }
>> >        return ret;
>> > }
>> >
>> > is entirely sufficient to catch the case of a single-use clock not being
>> > prepared before clk_enable() is called.
>> >
>> > We're after detecting drivers missing calls to clk_prepare(), we're not
>> > after detecting concurrent calls to clk_prepare()/clk_unprepare().
>>
>> I hope you mean 'making sure the clock is prepared before it's enabled
>> ' rather than
>> 'catching a driver that doesn't do clk_prepare before clk_enable'.
>> Because, the above implementation still doesn't catch a driver that
>> doesn't call clk_prepare
>> but simply uses a clock that happens to have been already prepare'd by
>> some other
>> driver or the platform.
>
> No, I mean what I said.
Then, how does that function catch a driver that, say, doesn't do clk_prepare
but share the clk with another already active driver?
Because you said - "We're after detecting drivers missing calls to
clk_prepare()"

The point is, there is difference between detecting drivers that miss
the clk_prepare
and ensuring clk_prepare has been called before any call to
clk_enable. And making
that clear helps get rid of lots of confusion/misunderstanding. Uwe
seems to have
had similar confusions.


> The only way to do what you're asking is to attach a list of identifiers
> which have prepared a clock to the struct clk, where each identifier is
> unique to each driver instance.
I am not asking what you think.
In my second last post, I am rather asking the other way around - that
let us not worry
about drivers missing the clk_prepare and not try to catch those by the new API.


> I think that's going completely over the top, and adds needless complexity
> to drivers, which now have to pass an instance specific cookie into every
> clk API call.
Exactly.
All we need is to ensure clk_prepare has been called atleast once before
any call to clk_enable.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04 11:51                           ` Jassi Brar
  0 siblings, 0 replies; 383+ messages in thread
From: Jassi Brar @ 2011-02-04 11:51 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Richard Zhao, Nicolas Pitre, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	Stephen Boyd, linux-kernel, Dima Zavin, Saravana Kannan,
	Ben Dooks, Uwe Kleine-König, Jeremy Kerr, linux-arm-kernel

On Fri, Feb 4, 2011 at 8:18 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Fri, Feb 04, 2011 at 08:04:03PM +0900, Jassi Brar wrote:
>> On Fri, Feb 4, 2011 at 7:48 PM, Russell King - ARM Linux
>> <linux@arm.linux.org.uk> wrote:
>>
>> > int clk_enable(struct clk *clk)
>> > {
>> >        unsigned long flags;
>> >        int ret = 0;
>> >
>> >        if (clk) {
>> >                if (WARN_ON(!clk->prepare_count))
>> >                        return -EINVAL;
>> >
>> >                spin_lock_irqsave(&clk->lock, flags);
>> >                if (clk->enable_count++ == 0)
>> >                        ret = clk->ops->enable(clk);
>> >                spin_unlock_irqrestore(&clk->lock, flags);
>> >        }
>> >        return ret;
>> > }
>> >
>> > is entirely sufficient to catch the case of a single-use clock not being
>> > prepared before clk_enable() is called.
>> >
>> > We're after detecting drivers missing calls to clk_prepare(), we're not
>> > after detecting concurrent calls to clk_prepare()/clk_unprepare().
>>
>> I hope you mean 'making sure the clock is prepared before it's enabled
>> ' rather than
>> 'catching a driver that doesn't do clk_prepare before clk_enable'.
>> Because, the above implementation still doesn't catch a driver that
>> doesn't call clk_prepare
>> but simply uses a clock that happens to have been already prepare'd by
>> some other
>> driver or the platform.
>
> No, I mean what I said.
Then, how does that function catch a driver that, say, doesn't do clk_prepare
but share the clk with another already active driver?
Because you said - "We're after detecting drivers missing calls to
clk_prepare()"

The point is, there is difference between detecting drivers that miss
the clk_prepare
and ensuring clk_prepare has been called before any call to
clk_enable. And making
that clear helps get rid of lots of confusion/misunderstanding. Uwe
seems to have
had similar confusions.


> The only way to do what you're asking is to attach a list of identifiers
> which have prepared a clock to the struct clk, where each identifier is
> unique to each driver instance.
I am not asking what you think.
In my second last post, I am rather asking the other way around - that
let us not worry
about drivers missing the clk_prepare and not try to catch those by the new API.


> I think that's going completely over the top, and adds needless complexity
> to drivers, which now have to pass an instance specific cookie into every
> clk API call.
Exactly.
All we need is to ensure clk_prepare has been called atleast once before
any call to clk_enable.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04 11:51                           ` Jassi Brar
  0 siblings, 0 replies; 383+ messages in thread
From: Jassi Brar @ 2011-02-04 11:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 4, 2011 at 8:18 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Fri, Feb 04, 2011 at 08:04:03PM +0900, Jassi Brar wrote:
>> On Fri, Feb 4, 2011 at 7:48 PM, Russell King - ARM Linux
>> <linux@arm.linux.org.uk> wrote:
>>
>> > int clk_enable(struct clk *clk)
>> > {
>> > ? ? ? ?unsigned long flags;
>> > ? ? ? ?int ret = 0;
>> >
>> > ? ? ? ?if (clk) {
>> > ? ? ? ? ? ? ? ?if (WARN_ON(!clk->prepare_count))
>> > ? ? ? ? ? ? ? ? ? ? ? ?return -EINVAL;
>> >
>> > ? ? ? ? ? ? ? ?spin_lock_irqsave(&clk->lock, flags);
>> > ? ? ? ? ? ? ? ?if (clk->enable_count++ == 0)
>> > ? ? ? ? ? ? ? ? ? ? ? ?ret = clk->ops->enable(clk);
>> > ? ? ? ? ? ? ? ?spin_unlock_irqrestore(&clk->lock, flags);
>> > ? ? ? ?}
>> > ? ? ? ?return ret;
>> > }
>> >
>> > is entirely sufficient to catch the case of a single-use clock not being
>> > prepared before clk_enable() is called.
>> >
>> > We're after detecting drivers missing calls to clk_prepare(), we're not
>> > after detecting concurrent calls to clk_prepare()/clk_unprepare().
>>
>> I hope you mean 'making sure the clock is prepared before it's enabled
>> ' rather than
>> 'catching a driver that doesn't do clk_prepare before clk_enable'.
>> Because, the above implementation still doesn't catch a driver that
>> doesn't call clk_prepare
>> but simply uses a clock that happens to have been already prepare'd by
>> some other
>> driver or the platform.
>
> No, I mean what I said.
Then, how does that function catch a driver that, say, doesn't do clk_prepare
but share the clk with another already active driver?
Because you said - "We're after detecting drivers missing calls to
clk_prepare()"

The point is, there is difference between detecting drivers that miss
the clk_prepare
and ensuring clk_prepare has been called before any call to
clk_enable. And making
that clear helps get rid of lots of confusion/misunderstanding. Uwe
seems to have
had similar confusions.


> The only way to do what you're asking is to attach a list of identifiers
> which have prepared a clock to the struct clk, where each identifier is
> unique to each driver instance.
I am not asking what you think.
In my second last post, I am rather asking the other way around - that
let us not worry
about drivers missing the clk_prepare and not try to catch those by the new API.


> I think that's going completely over the top, and adds needless complexity
> to drivers, which now have to pass an instance specific cookie into every
> clk API call.
Exactly.
All we need is to ensure clk_prepare has been called atleast once before
any call to clk_enable.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-04 11:51                           ` Jassi Brar
  (?)
@ 2011-02-04 12:05                             ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-04 12:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 04, 2011 at 08:51:15PM +0900, Jassi Brar wrote:
> On Fri, Feb 4, 2011 at 8:18 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> > On Fri, Feb 04, 2011 at 08:04:03PM +0900, Jassi Brar wrote:
> >> On Fri, Feb 4, 2011 at 7:48 PM, Russell King - ARM Linux
> >> <linux@arm.linux.org.uk> wrote:
> >>
> >> > int clk_enable(struct clk *clk)
> >> > {
> >> >        unsigned long flags;
> >> >        int ret = 0;
> >> >
> >> >        if (clk) {
> >> >                if (WARN_ON(!clk->prepare_count))
> >> >                        return -EINVAL;
> >> >
> >> >                spin_lock_irqsave(&clk->lock, flags);
> >> >                if (clk->enable_count++ = 0)
> >> >                        ret = clk->ops->enable(clk);
> >> >                spin_unlock_irqrestore(&clk->lock, flags);
> >> >        }
> >> >        return ret;
> >> > }
> >> >
> >> > is entirely sufficient to catch the case of a single-use clock not being
> >> > prepared before clk_enable() is called.
> >> >
> >> > We're after detecting drivers missing calls to clk_prepare(), we're not
> >> > after detecting concurrent calls to clk_prepare()/clk_unprepare().
> >>
> >> I hope you mean 'making sure the clock is prepared before it's enabled
> >> ' rather than
> >> 'catching a driver that doesn't do clk_prepare before clk_enable'.
> >> Because, the above implementation still doesn't catch a driver that
> >> doesn't call clk_prepare
> >> but simply uses a clock that happens to have been already prepare'd by
> >> some other
> >> driver or the platform.
> >
> > No, I mean what I said.
> Then, how does that function catch a driver that, say, doesn't do clk_prepare
> but share the clk with another already active driver?

As per the code I just supplied!

> Because you said - "We're after detecting drivers missing calls to
> clk_prepare()"
> 
> The point is, there is difference between detecting drivers that miss
> the clk_prepare
> and ensuring clk_prepare has been called before any call to
> clk_enable. And making
> that clear helps get rid of lots of confusion/misunderstanding. Uwe
> seems to have
> had similar confusions.

As I said on the 1st February.

> > The only way to do what you're asking is to attach a list of identifiers
> > which have prepared a clock to the struct clk, where each identifier is
> > unique to each driver instance.
> I am not asking what you think.
> In my second last post, I am rather asking the other way around - that
> let us not worry
> about drivers missing the clk_prepare and not try to catch those by the
> new API.

No.  That means we have no way to flag a call to clk_enable on an
unprepared clock, and will lead to unexplained system lockups.  What
I've been suggesting all along is the "best efforts" approach.  I'm
sorry you can't see that, but that's really not my problem.

> > I think that's going completely over the top, and adds needless complexity
> > to drivers, which now have to pass an instance specific cookie into every
> > clk API call.
> Exactly.
> All we need is to ensure clk_prepare has been called atleast once before
> any call to clk_enable.

I described this fully in my reply to Stephen Boyd on 1st February,
which is a parent to this sub-thread.


^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04 12:05                             ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-04 12:05 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Richard Zhao, Nicolas Pitre, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	Stephen Boyd, linux-kernel, Dima Zavin, Saravana Kannan,
	Ben Dooks, Uwe Kleine-König, Jeremy Kerr, linux-arm-kernel

On Fri, Feb 04, 2011 at 08:51:15PM +0900, Jassi Brar wrote:
> On Fri, Feb 4, 2011 at 8:18 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> > On Fri, Feb 04, 2011 at 08:04:03PM +0900, Jassi Brar wrote:
> >> On Fri, Feb 4, 2011 at 7:48 PM, Russell King - ARM Linux
> >> <linux@arm.linux.org.uk> wrote:
> >>
> >> > int clk_enable(struct clk *clk)
> >> > {
> >> >        unsigned long flags;
> >> >        int ret = 0;
> >> >
> >> >        if (clk) {
> >> >                if (WARN_ON(!clk->prepare_count))
> >> >                        return -EINVAL;
> >> >
> >> >                spin_lock_irqsave(&clk->lock, flags);
> >> >                if (clk->enable_count++ == 0)
> >> >                        ret = clk->ops->enable(clk);
> >> >                spin_unlock_irqrestore(&clk->lock, flags);
> >> >        }
> >> >        return ret;
> >> > }
> >> >
> >> > is entirely sufficient to catch the case of a single-use clock not being
> >> > prepared before clk_enable() is called.
> >> >
> >> > We're after detecting drivers missing calls to clk_prepare(), we're not
> >> > after detecting concurrent calls to clk_prepare()/clk_unprepare().
> >>
> >> I hope you mean 'making sure the clock is prepared before it's enabled
> >> ' rather than
> >> 'catching a driver that doesn't do clk_prepare before clk_enable'.
> >> Because, the above implementation still doesn't catch a driver that
> >> doesn't call clk_prepare
> >> but simply uses a clock that happens to have been already prepare'd by
> >> some other
> >> driver or the platform.
> >
> > No, I mean what I said.
> Then, how does that function catch a driver that, say, doesn't do clk_prepare
> but share the clk with another already active driver?

As per the code I just supplied!

> Because you said - "We're after detecting drivers missing calls to
> clk_prepare()"
> 
> The point is, there is difference between detecting drivers that miss
> the clk_prepare
> and ensuring clk_prepare has been called before any call to
> clk_enable. And making
> that clear helps get rid of lots of confusion/misunderstanding. Uwe
> seems to have
> had similar confusions.

As I said on the 1st February.

> > The only way to do what you're asking is to attach a list of identifiers
> > which have prepared a clock to the struct clk, where each identifier is
> > unique to each driver instance.
> I am not asking what you think.
> In my second last post, I am rather asking the other way around - that
> let us not worry
> about drivers missing the clk_prepare and not try to catch those by the
> new API.

No.  That means we have no way to flag a call to clk_enable on an
unprepared clock, and will lead to unexplained system lockups.  What
I've been suggesting all along is the "best efforts" approach.  I'm
sorry you can't see that, but that's really not my problem.

> > I think that's going completely over the top, and adds needless complexity
> > to drivers, which now have to pass an instance specific cookie into every
> > clk API call.
> Exactly.
> All we need is to ensure clk_prepare has been called atleast once before
> any call to clk_enable.

I described this fully in my reply to Stephen Boyd on 1st February,
which is a parent to this sub-thread.


^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04 12:05                             ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-04 12:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 04, 2011 at 08:51:15PM +0900, Jassi Brar wrote:
> On Fri, Feb 4, 2011 at 8:18 PM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> > On Fri, Feb 04, 2011 at 08:04:03PM +0900, Jassi Brar wrote:
> >> On Fri, Feb 4, 2011 at 7:48 PM, Russell King - ARM Linux
> >> <linux@arm.linux.org.uk> wrote:
> >>
> >> > int clk_enable(struct clk *clk)
> >> > {
> >> > ? ? ? ?unsigned long flags;
> >> > ? ? ? ?int ret = 0;
> >> >
> >> > ? ? ? ?if (clk) {
> >> > ? ? ? ? ? ? ? ?if (WARN_ON(!clk->prepare_count))
> >> > ? ? ? ? ? ? ? ? ? ? ? ?return -EINVAL;
> >> >
> >> > ? ? ? ? ? ? ? ?spin_lock_irqsave(&clk->lock, flags);
> >> > ? ? ? ? ? ? ? ?if (clk->enable_count++ == 0)
> >> > ? ? ? ? ? ? ? ? ? ? ? ?ret = clk->ops->enable(clk);
> >> > ? ? ? ? ? ? ? ?spin_unlock_irqrestore(&clk->lock, flags);
> >> > ? ? ? ?}
> >> > ? ? ? ?return ret;
> >> > }
> >> >
> >> > is entirely sufficient to catch the case of a single-use clock not being
> >> > prepared before clk_enable() is called.
> >> >
> >> > We're after detecting drivers missing calls to clk_prepare(), we're not
> >> > after detecting concurrent calls to clk_prepare()/clk_unprepare().
> >>
> >> I hope you mean 'making sure the clock is prepared before it's enabled
> >> ' rather than
> >> 'catching a driver that doesn't do clk_prepare before clk_enable'.
> >> Because, the above implementation still doesn't catch a driver that
> >> doesn't call clk_prepare
> >> but simply uses a clock that happens to have been already prepare'd by
> >> some other
> >> driver or the platform.
> >
> > No, I mean what I said.
> Then, how does that function catch a driver that, say, doesn't do clk_prepare
> but share the clk with another already active driver?

As per the code I just supplied!

> Because you said - "We're after detecting drivers missing calls to
> clk_prepare()"
> 
> The point is, there is difference between detecting drivers that miss
> the clk_prepare
> and ensuring clk_prepare has been called before any call to
> clk_enable. And making
> that clear helps get rid of lots of confusion/misunderstanding. Uwe
> seems to have
> had similar confusions.

As I said on the 1st February.

> > The only way to do what you're asking is to attach a list of identifiers
> > which have prepared a clock to the struct clk, where each identifier is
> > unique to each driver instance.
> I am not asking what you think.
> In my second last post, I am rather asking the other way around - that
> let us not worry
> about drivers missing the clk_prepare and not try to catch those by the
> new API.

No.  That means we have no way to flag a call to clk_enable on an
unprepared clock, and will lead to unexplained system lockups.  What
I've been suggesting all along is the "best efforts" approach.  I'm
sorry you can't see that, but that's really not my problem.

> > I think that's going completely over the top, and adds needless complexity
> > to drivers, which now have to pass an instance specific cookie into every
> > clk API call.
> Exactly.
> All we need is to ensure clk_prepare has been called atleast once before
> any call to clk_enable.

I described this fully in my reply to Stephen Boyd on 1st February,
which is a parent to this sub-thread.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-01  9:11 ` Jeremy Kerr
  (?)
@ 2011-02-04 12:45   ` Richard Zhao
  -1 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-04 12:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 05:11:29PM +0800, Jeremy Kerr wrote:
> Hi all,
> 
> > I suggested that clk_prepare() be callable only from non-atomic contexts,
> > and do whatever's required to ensure that the clock is available.  That
> > may end up enabling the clock as a result.
> 
> I think that clk_prepare/clk_unprepare looks like the most promising solution, 
> so will try to get some preliminary patches done. Here's what I'm planning:
> 
> -----
> 
> The changes to the API are essentially:
> 
> 1) Document clk_enable/clk_disable as callable from atomic contexts, and
>    so clock implementations must not sleep within this function.
> 
> 2) For clock implementations that may sleep to turn on a clock, we add a
>    new pair of functions to the clock API: clk_prepare and clk_unprepare.
> 
>    These will provide hooks for the clock implmentation to do any sleepable
>    work (eg, wait for PLLs to settle) in preparation for a later clk_enable.
> 
>    For the most common clock implemntation cases (where clocks can be enabled 
>    atomically), these functions will be a no-op, and all of the enable/disable
>    work can be done in clk_enable/clk_disable.
> 
>    For implementations where clocks require blocking on enable/disable, most
>    of the work will be done in clk_prepare/clk_unprepare. The clk_enable
>    and clk_disable functions may be no-ops.
> 
> For drivers, this means that clk_prepare must be called (and have returned) 
> before calling clk_enable.
> 
> = Enable/Prepare counts =
> 
> I intend to do the enable and prepare "counting" in the core clock API, 
> meaning that that the clk_ops callbacks will only invoked on the first 
> prepare/enable and the last unprepare/disable.
> 
> = Concurrency =
> 
> Splitting the prepare and enable stages introduces the concurrency 
> requirements:
> 
> 1) clk_enable must not return before the clock is outputting a valid clock 
>    signal.
> 
> 2) clk_prepare must not return before the clock is fully prepared (ie, it is 
>    safe to call clk_enable).
> 
> It is not possible for clk_enable to wait for the clock to be prepared, 
> because that would require synchronisation with clk_prepare, which may then 
> require blocking. Therefore:
> 
> 3) The clock consumer *must* respect the proper ordering of clk_prepare and 
>    clk_enable. For example, drivers that call clk_enable during an interrupt 
>    must ensure that the interrupt handler will not be invoked until 
>    clk_prepare has returned.
> 
> = Other considerations =
> 
> The time that a clock spends "prepared" is a superset of the the time that a 
> clock spends "enabled". Therefore, clocks that are switched on during 
> clk_prepare (ie, non-atomic clocks) will be running for a larger amount of 
> time. In some cases, this can be mitigated by moving some of the final 
> (atomic) switching functionality to the clk_enable function.
> 
> = Implementation =
> 
> Basically:
> 
> struct clk {
> 	const struct clk_ops *ops
> 	int                  enable_count;
> 	spinlock_t           enable_lock;
> 	int                  prepare_count;
> 	struct mutex         prepare_lock;
> };
> 
> int clk_enable(struct clk *clk)
> {
> 	int ret = 0;
> 
> 	spin_lock(&clk->enable_lock);
> 	if (!clk->enable_count)
> 		ret = clk->ops->enable(clk);
> 
> 	if (!ret)
> 		clk->enable_count++;
> 	spin_unlock(&clk->enable_lock);
> 
> 	return ret;
> }
Why do we not call parent's clk_enable in this function? For flexible? How many
different cases is causing us to move the effert to platform clock driver?
> 
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0;
> 
> 	mutex_lock(&clk->prepare_lock);
> 	if (!clk->prepare_count)
> 		ret = clk->ops->prepare(clk);
> 
> 	if (!ret)
> 		clk->prepare_count++;
> 	mutex_unlock(&clk->prepare_lock);
> 
> 	return ret;
> }
Same as above.
And for most clocks, prepare/unprepare may be NULL. So in such case, is it
better to call parent's prepare and increase its own prepare_count here?

Thanks
Richard
> 
> -----
> 
> Comments welcome, code coming soon.
> 
> Cheers,
> 
> 
> Jeremy
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04 12:45   ` Richard Zhao
  0 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-04 12:45 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: Russell King, Nicolas Pitre, Lorenzo Pieralisi, Saravana Kannan,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	linux-kernel, Dima Zavin, Ben Dooks, Uwe Kleine-König,
	Vincent Guittot, linux-arm-kernel

On Tue, Feb 01, 2011 at 05:11:29PM +0800, Jeremy Kerr wrote:
> Hi all,
> 
> > I suggested that clk_prepare() be callable only from non-atomic contexts,
> > and do whatever's required to ensure that the clock is available.  That
> > may end up enabling the clock as a result.
> 
> I think that clk_prepare/clk_unprepare looks like the most promising solution, 
> so will try to get some preliminary patches done. Here's what I'm planning:
> 
> -----
> 
> The changes to the API are essentially:
> 
> 1) Document clk_enable/clk_disable as callable from atomic contexts, and
>    so clock implementations must not sleep within this function.
> 
> 2) For clock implementations that may sleep to turn on a clock, we add a
>    new pair of functions to the clock API: clk_prepare and clk_unprepare.
> 
>    These will provide hooks for the clock implmentation to do any sleepable
>    work (eg, wait for PLLs to settle) in preparation for a later clk_enable.
> 
>    For the most common clock implemntation cases (where clocks can be enabled 
>    atomically), these functions will be a no-op, and all of the enable/disable
>    work can be done in clk_enable/clk_disable.
> 
>    For implementations where clocks require blocking on enable/disable, most
>    of the work will be done in clk_prepare/clk_unprepare. The clk_enable
>    and clk_disable functions may be no-ops.
> 
> For drivers, this means that clk_prepare must be called (and have returned) 
> before calling clk_enable.
> 
> == Enable/Prepare counts ==
> 
> I intend to do the enable and prepare "counting" in the core clock API, 
> meaning that that the clk_ops callbacks will only invoked on the first 
> prepare/enable and the last unprepare/disable.
> 
> == Concurrency ==
> 
> Splitting the prepare and enable stages introduces the concurrency 
> requirements:
> 
> 1) clk_enable must not return before the clock is outputting a valid clock 
>    signal.
> 
> 2) clk_prepare must not return before the clock is fully prepared (ie, it is 
>    safe to call clk_enable).
> 
> It is not possible for clk_enable to wait for the clock to be prepared, 
> because that would require synchronisation with clk_prepare, which may then 
> require blocking. Therefore:
> 
> 3) The clock consumer *must* respect the proper ordering of clk_prepare and 
>    clk_enable. For example, drivers that call clk_enable during an interrupt 
>    must ensure that the interrupt handler will not be invoked until 
>    clk_prepare has returned.
> 
> == Other considerations ==
> 
> The time that a clock spends "prepared" is a superset of the the time that a 
> clock spends "enabled". Therefore, clocks that are switched on during 
> clk_prepare (ie, non-atomic clocks) will be running for a larger amount of 
> time. In some cases, this can be mitigated by moving some of the final 
> (atomic) switching functionality to the clk_enable function.
> 
> == Implementation ==
> 
> Basically:
> 
> struct clk {
> 	const struct clk_ops *ops
> 	int                  enable_count;
> 	spinlock_t           enable_lock;
> 	int                  prepare_count;
> 	struct mutex         prepare_lock;
> };
> 
> int clk_enable(struct clk *clk)
> {
> 	int ret = 0;
> 
> 	spin_lock(&clk->enable_lock);
> 	if (!clk->enable_count)
> 		ret = clk->ops->enable(clk);
> 
> 	if (!ret)
> 		clk->enable_count++;
> 	spin_unlock(&clk->enable_lock);
> 
> 	return ret;
> }
Why do we not call parent's clk_enable in this function? For flexible? How many
different cases is causing us to move the effert to platform clock driver?
> 
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0;
> 
> 	mutex_lock(&clk->prepare_lock);
> 	if (!clk->prepare_count)
> 		ret = clk->ops->prepare(clk);
> 
> 	if (!ret)
> 		clk->prepare_count++;
> 	mutex_unlock(&clk->prepare_lock);
> 
> 	return ret;
> }
Same as above.
And for most clocks, prepare/unprepare may be NULL. So in such case, is it
better to call parent's prepare and increase its own prepare_count here?

Thanks
Richard
> 
> -----
> 
> Comments welcome, code coming soon.
> 
> Cheers,
> 
> 
> Jeremy
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04 12:45   ` Richard Zhao
  0 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-04 12:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 01, 2011 at 05:11:29PM +0800, Jeremy Kerr wrote:
> Hi all,
> 
> > I suggested that clk_prepare() be callable only from non-atomic contexts,
> > and do whatever's required to ensure that the clock is available.  That
> > may end up enabling the clock as a result.
> 
> I think that clk_prepare/clk_unprepare looks like the most promising solution, 
> so will try to get some preliminary patches done. Here's what I'm planning:
> 
> -----
> 
> The changes to the API are essentially:
> 
> 1) Document clk_enable/clk_disable as callable from atomic contexts, and
>    so clock implementations must not sleep within this function.
> 
> 2) For clock implementations that may sleep to turn on a clock, we add a
>    new pair of functions to the clock API: clk_prepare and clk_unprepare.
> 
>    These will provide hooks for the clock implmentation to do any sleepable
>    work (eg, wait for PLLs to settle) in preparation for a later clk_enable.
> 
>    For the most common clock implemntation cases (where clocks can be enabled 
>    atomically), these functions will be a no-op, and all of the enable/disable
>    work can be done in clk_enable/clk_disable.
> 
>    For implementations where clocks require blocking on enable/disable, most
>    of the work will be done in clk_prepare/clk_unprepare. The clk_enable
>    and clk_disable functions may be no-ops.
> 
> For drivers, this means that clk_prepare must be called (and have returned) 
> before calling clk_enable.
> 
> == Enable/Prepare counts ==
> 
> I intend to do the enable and prepare "counting" in the core clock API, 
> meaning that that the clk_ops callbacks will only invoked on the first 
> prepare/enable and the last unprepare/disable.
> 
> == Concurrency ==
> 
> Splitting the prepare and enable stages introduces the concurrency 
> requirements:
> 
> 1) clk_enable must not return before the clock is outputting a valid clock 
>    signal.
> 
> 2) clk_prepare must not return before the clock is fully prepared (ie, it is 
>    safe to call clk_enable).
> 
> It is not possible for clk_enable to wait for the clock to be prepared, 
> because that would require synchronisation with clk_prepare, which may then 
> require blocking. Therefore:
> 
> 3) The clock consumer *must* respect the proper ordering of clk_prepare and 
>    clk_enable. For example, drivers that call clk_enable during an interrupt 
>    must ensure that the interrupt handler will not be invoked until 
>    clk_prepare has returned.
> 
> == Other considerations ==
> 
> The time that a clock spends "prepared" is a superset of the the time that a 
> clock spends "enabled". Therefore, clocks that are switched on during 
> clk_prepare (ie, non-atomic clocks) will be running for a larger amount of 
> time. In some cases, this can be mitigated by moving some of the final 
> (atomic) switching functionality to the clk_enable function.
> 
> == Implementation ==
> 
> Basically:
> 
> struct clk {
> 	const struct clk_ops *ops
> 	int                  enable_count;
> 	spinlock_t           enable_lock;
> 	int                  prepare_count;
> 	struct mutex         prepare_lock;
> };
> 
> int clk_enable(struct clk *clk)
> {
> 	int ret = 0;
> 
> 	spin_lock(&clk->enable_lock);
> 	if (!clk->enable_count)
> 		ret = clk->ops->enable(clk);
> 
> 	if (!ret)
> 		clk->enable_count++;
> 	spin_unlock(&clk->enable_lock);
> 
> 	return ret;
> }
Why do we not call parent's clk_enable in this function? For flexible? How many
different cases is causing us to move the effert to platform clock driver?
> 
> int clk_prepare(struct clk *clk)
> {
> 	int ret = 0;
> 
> 	mutex_lock(&clk->prepare_lock);
> 	if (!clk->prepare_count)
> 		ret = clk->ops->prepare(clk);
> 
> 	if (!ret)
> 		clk->prepare_count++;
> 	mutex_unlock(&clk->prepare_lock);
> 
> 	return ret;
> }
Same as above.
And for most clocks, prepare/unprepare may be NULL. So in such case, is it
better to call parent's prepare and increase its own prepare_count here?

Thanks
Richard
> 
> -----
> 
> Comments welcome, code coming soon.
> 
> Cheers,
> 
> 
> Jeremy
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
  2011-02-04 12:45   ` Richard Zhao
  (?)
@ 2011-02-04 13:20     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-04 13:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 04, 2011 at 08:45:34PM +0800, Richard Zhao wrote:
> > = Implementation =
> > 
> > Basically:
> > 
> > struct clk {
> > 	const struct clk_ops *ops
> > 	int                  enable_count;
> > 	spinlock_t           enable_lock;
> > 	int                  prepare_count;
> > 	struct mutex         prepare_lock;
> > };
> > 
> > int clk_enable(struct clk *clk)
> > {
> > 	int ret = 0;
> > 
> > 	spin_lock(&clk->enable_lock);
> > 	if (!clk->enable_count)
> > 		ret = clk->ops->enable(clk);
> > 
> > 	if (!ret)
> > 		clk->enable_count++;
> > 	spin_unlock(&clk->enable_lock);
> > 
> > 	return ret;
> > }
> Why do we not call parent's clk_enable in this function? For flexible? How many
> different cases is causing us to move the effert to platform clock driver?

You may notice that struct clk above doesn't have a parent.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04 13:20     ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-04 13:20 UTC (permalink / raw)
  To: Richard Zhao
  Cc: Jeremy Kerr, Nicolas Pitre, Lorenzo Pieralisi, Saravana Kannan,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	linux-kernel, Dima Zavin, Ben Dooks, Uwe Kleine-König,
	Vincent Guittot, linux-arm-kernel

On Fri, Feb 04, 2011 at 08:45:34PM +0800, Richard Zhao wrote:
> > == Implementation ==
> > 
> > Basically:
> > 
> > struct clk {
> > 	const struct clk_ops *ops
> > 	int                  enable_count;
> > 	spinlock_t           enable_lock;
> > 	int                  prepare_count;
> > 	struct mutex         prepare_lock;
> > };
> > 
> > int clk_enable(struct clk *clk)
> > {
> > 	int ret = 0;
> > 
> > 	spin_lock(&clk->enable_lock);
> > 	if (!clk->enable_count)
> > 		ret = clk->ops->enable(clk);
> > 
> > 	if (!ret)
> > 		clk->enable_count++;
> > 	spin_unlock(&clk->enable_lock);
> > 
> > 	return ret;
> > }
> Why do we not call parent's clk_enable in this function? For flexible? How many
> different cases is causing us to move the effert to platform clock driver?

You may notice that struct clk above doesn't have a parent.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Locking in the clk API, part 2: clk_prepare/clk_unprepare
@ 2011-02-04 13:20     ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-04 13:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 04, 2011 at 08:45:34PM +0800, Richard Zhao wrote:
> > == Implementation ==
> > 
> > Basically:
> > 
> > struct clk {
> > 	const struct clk_ops *ops
> > 	int                  enable_count;
> > 	spinlock_t           enable_lock;
> > 	int                  prepare_count;
> > 	struct mutex         prepare_lock;
> > };
> > 
> > int clk_enable(struct clk *clk)
> > {
> > 	int ret = 0;
> > 
> > 	spin_lock(&clk->enable_lock);
> > 	if (!clk->enable_count)
> > 		ret = clk->ops->enable(clk);
> > 
> > 	if (!ret)
> > 		clk->enable_count++;
> > 	spin_unlock(&clk->enable_lock);
> > 
> > 	return ret;
> > }
> Why do we not call parent's clk_enable in this function? For flexible? How many
> different cases is causing us to move the effert to platform clock driver?

You may notice that struct clk above doesn't have a parent.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
  2011-02-01  9:11 ` Jeremy Kerr
  (?)
@ 2011-02-07  6:07   ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  6:07 UTC (permalink / raw)
  To: linux-arm-kernel

Since most platforms will need a fixed-rate clock, add one. This will
also serve as a basic example of an implementation of struct clk.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/clk.c   |   14 ++++++++++++++
 include/linux/clk.h |   16 ++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 12e0daf..51dbd33 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -132,3 +132,17 @@ struct clk *clk_get_parent(struct clk *clk)
 	return ERR_PTR(-ENOSYS);
 }
 EXPORT_SYMBOL_GPL(clk_get_parent);
+
+/* clk_fixed support */
+
+#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
+
+static unsigned long clk_fixed_get_rate(struct clk *clk)
+{
+	return to_clk_fixed(clk)->rate;
+}
+
+struct clk_ops clk_fixed_ops = {
+	.get_rate = clk_fixed_get_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index e081ca1..daa2d5a 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -176,6 +176,22 @@ static inline void clk_common_init(struct clk *clk)
 	mutex_init(&clk->prepare_lock);
 }
 
+/* Simple fixed-rate clock */
+struct clk_fixed {
+	struct clk	clk;
+	unsigned long	rate;
+};
+
+extern struct clk_ops clk_fixed_ops;
+
+#define INIT_CLK_FIXED(name, r) { \
+	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
+	.rate = (r) \
+}
+
+#define DEFINE_CLK_FIXED(name, r) \
+	struct clk_fixed name = INIT_CLK_FIXED(name, r)
+
 #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
  2011-02-01  9:11 ` Jeremy Kerr
  (?)
@ 2011-02-07  6:07   ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  6:07 UTC (permalink / raw)
  To: linux-arm-kernel

We currently have ~21 definitions of struct clk in the ARM architecture,
each defined on a per-platform basis. This makes it difficult to define
platform- (or architecture-) independent clock sources without making
assumptions about struct clk, and impossible to compile two
platforms with different struct clks into a single image.

This change is an effort to unify struct clk where possible, by defining
a common struct clk, containing a set of clock operations. Different
clock implementations can set their own operations, and have a standard
interface for generic code. The callback interface is exposed to the
kernel proper, while the clock implementations only need to be seen by
the platform internals.

This allows us to share clock code among platforms, and makes it
possible to dynamically create clock devices in platform-independent
code.

Platforms can enable the generic struct clock through
CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
consists of a common struct clk:

struct clk {
	const struct clk_ops	*ops;
	unsigned int		enable_count;
	unsigned int		prepare_count;
	spinlock_t		enable_lock;
	struct mutex		prepare_lock;
};

And a set of clock operations (defined per type of clock):

struct clk_ops {
	int             (*enable)(struct clk *);
	void            (*disable)(struct clk *);
	unsigned long   (*get_rate)(struct clk *);
	[...]
};

To define a hardware-specific clock, machine code can "subclass" the
struct clock into a new struct (adding any device-specific data), and
provide a set of operations:

struct clk_foo {
	struct clk	clk;
	void __iomem	*some_register;
};

struct clk_ops clk_foo_ops = {
	.get_rate = clk_foo_get_rate,
};

The common clock definitions are based on a development patch from Ben
Herrenschmidt <benh@kernel.crashing.org>.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/Kconfig  |    3 
 drivers/clk/Makefile |    1 
 drivers/clk/clk.c    |  134 +++++++++++++++++++++++++++++++
 drivers/clk/clkdev.c |    5 +
 include/linux/clk.h  |  184 ++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 318 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 4168c88..6e3ae54 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -2,3 +2,6 @@
 config CLKDEV_LOOKUP
 	bool
 	select HAVE_CLK
+
+config USE_COMMON_STRUCT_CLK
+	bool
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 07613fa..a1a06d3 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,2 +1,3 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
+obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
new file mode 100644
index 0000000..12e0daf
--- /dev/null
+++ b/drivers/clk/clk.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+
+int clk_prepare(struct clk *clk)
+{
+	int ret = 0;
+
+	if (!clk->ops->prepare)
+		return 0;
+
+	mutex_lock(&clk->prepare_lock);
+	if (clk->prepare_count = 0)
+		ret = clk->ops->prepare(clk);
+
+	if (!ret)
+		clk->prepare_count++;
+	mutex_unlock(&clk->prepare_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(clk_prepare);
+
+void clk_unprepare(struct clk *clk)
+{
+	if (!clk->ops->unprepare)
+		return;
+
+	mutex_lock(&clk->prepare_lock);
+	if (--clk->prepare_count = 0)
+		clk->ops->unprepare(clk);
+
+	mutex_unlock(&clk->prepare_lock);
+}
+EXPORT_SYMBOL_GPL(clk_unprepare);
+
+int clk_enable(struct clk *clk)
+{
+	int ret = 0;
+
+	if (!clk->ops->enable)
+		return 0;
+
+	spin_lock(&clk->enable_lock);
+	if (!clk->enable_count)
+		ret = clk->ops->enable(clk);
+
+	if (!ret)
+		clk->enable_count++;
+	spin_unlock(&clk->enable_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	if (!clk->ops->disable)
+		return;
+
+	spin_lock(&clk->enable_lock);
+
+	WARN_ON(!clk->enable_count);
+
+	if (!--clk->enable_count)
+		clk->ops->disable(clk);
+
+	spin_unlock(&clk->enable_lock);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk->ops->get_rate)
+		return clk->ops->get_rate(clk);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+int __clk_get(struct clk *clk)
+{
+	if (clk->ops->get)
+		return clk->ops->get(clk);
+	return 1;
+}
+EXPORT_SYMBOL_GPL(__clk_get);
+
+void clk_put(struct clk *clk)
+{
+	if (clk->ops->put)
+		clk->ops->put(clk);
+}
+EXPORT_SYMBOL_GPL(clk_put);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->round_rate)
+		return clk->ops->round_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->set_rate)
+		return clk->ops->set_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (clk->ops->set_parent)
+		return clk->ops->set_parent(clk, parent);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	if (clk->ops->get_parent)
+		return clk->ops->get_parent(clk);
+	return ERR_PTR(-ENOSYS);
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 0fc0a79..17619c7 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -84,12 +84,17 @@ struct clk *clk_get(struct device *dev, const char *con_id)
 }
 EXPORT_SYMBOL(clk_get);
 
+#ifndef CONFIG_USE_COMMON_STRUCT_CLK
+/* For the common struct clk case, clk_put is provided by clk.c */
+
 void clk_put(struct clk *clk)
 {
 	__clk_put(clk);
 }
 EXPORT_SYMBOL(clk_put);
 
+#endif
+
 void clkdev_add(struct clk_lookup *cl)
 {
 	mutex_lock(&clocks_mutex);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1d37f42..e081ca1 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2004 ARM Limited.
  *  Written by Deep Blue Solutions Limited.
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,18 +12,189 @@
 #ifndef __LINUX_CLK_H
 #define __LINUX_CLK_H
 
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
 struct device;
 
-/*
- * The base API.
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+
+/* If we're using the common struct clk, we define the base clk object here */
+
+/**
+ * struct clk - hardware independent clock structure
+ * @ops:		implementation-specific ops for this clock
+ * @enable_count:	count of clk_enable() calls active on this clock
+ * @flags:		platform-independent flags
+ * @lock:		lock for enable/disable or other HW-specific ops
+ *
+ * The base clock object, used by drivers for hardware-independent manipulation
+ * of clock lines. This will be 'subclassed' by device-specific implementations,
+ * which add device-specific data to struct clk. For example:
+ *
+ *  struct clk_foo {
+ *      struct clk;
+ *      [device specific fields]
+ *  };
+ *
+ * The clock driver code will manage the device-specific data, and pass
+ * clk_foo.clk to the common clock code. The clock driver will be called
+ * through the @ops callbacks.
+ *
+ * The @lock member provides either a spinlock or a mutex to protect (at least)
+ * @enable_count. The type of lock used will depend on @flags; if CLK_ATOMIC is
+ * set, then the core clock code will use a spinlock, otherwise a mutex. This
+ * lock will be acquired during clk_enable and clk_disable, so for atomic
+ * clocks, these ops callbacks must not sleep.
+ *
+ * The choice of atomic or non-atomic clock depends on how the clock is enabled.
+ * Typically, you'll want to use a non-atomic clock. For clocks that need to be
+ * enabled/disabled in interrupt context, use CLK_ATOMIC. Note that atomic
+ * clocks with parents will typically cascade enable/disable operations to
+ * their parent, so the parent of an atomic clock *must* be atomic too.
  */
+struct clk {
+	const struct clk_ops	*ops;
+	unsigned int		enable_count;
+	unsigned int		prepare_count;
+	spinlock_t		enable_lock;
+	struct mutex		prepare_lock;
+};
+
+/* static initialiser for non-atomic clocks */
+#define INIT_CLK(name, o) {						\
+	.ops		= &o,						\
+	.enable_count	= 0,						\
+	.prepare_count	= 0,						\
+	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
+	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
+}
 
+/**
+ * struct clk_ops -  Callback operations for clocks; these are to be provided
+ * by the clock implementation, and will be called by drivers through the clk_*
+ * API.
+ *
+ * @prepare:	Prepare the clock for enabling. This must not return until
+ *		the clock is fully prepared, and it's safe to call clk_enable.
+ *		This callback is intended to allow clock implementations to
+ *		do any initialisation that may block. Called with
+ *		clk->prepare_lock held.
+ *
+ * @unprepare:	Release the clock from its prepared state. This will typically
+ *		undo any work done in the @prepare callback. Called with
+ *		clk->prepare_lock held.
+ *
+ * @enable:	Enable the clock atomically. This must not return until the
+ *		clock is generating a valid clock signal, usable by consumer
+ *		devices. Called with clk->enable_lock held.
+ *
+ * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
+ *
+ * @get:	Called by the core clock code when a device driver acquires a
+ *		clock via clk_get(). Optional.
+ *
+ * @put:	Called by the core clock code when a devices driver releases a
+ *		clock via clk_put(). Optional.
+ *
+ * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
+ * implementations to split any work between atomic (enable) and sleepable
+ * (prepare) contexts.  If a clock requires blocking code to be turned on, this
+ * should be done in clk_prepare. Switching that will not block should be done
+ * in clk_enable.
+ *
+ * Typically, drivers will call clk_prepare when a clock may be needed later
+ * (eg. when a device is opened), and clk_enable when the clock is actually
+ * required (eg. from an interrupt).
+ *
+ * For other callbacks, see the corresponding clk_* functions. Parameters and
+ * return values are passed directly from/to these API functions, or
+ * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
+ * is NULL, see kernel/clk.c for implementation details. All are optional.
+ */
+struct clk_ops {
+	int		(*prepare)(struct clk *);
+	void		(*unprepare)(struct clk *);
+	int		(*enable)(struct clk *);
+	void		(*disable)(struct clk *);
+	int		(*get)(struct clk *);
+	void		(*put)(struct clk *);
+	unsigned long	(*get_rate)(struct clk *);
+	long		(*round_rate)(struct clk *, unsigned long);
+	int		(*set_rate)(struct clk *, unsigned long);
+	int		(*set_parent)(struct clk *, struct clk *);
+	struct clk *	(*get_parent)(struct clk *);
+};
+
+/**
+ * __clk_get - update clock-specific refcounter
+ *
+ * @clk: The clock to refcount
+ *
+ * Before a clock is returned from clk_get, this function should be called
+ * to update any clock-specific refcounting.
+ *
+ * Returns non-zero on success, zero on failure.
+ *
+ * Drivers should not need this function; it is only needed by the
+ * arch-specific clk_get() implementations.
+ */
+int __clk_get(struct clk *clk);
+
+/**
+ * clk_prepare - prepare clock for atomic enabling.
+ *
+ * @clk: The clock to prepare
+ *
+ * Do any blocking initialisation on @clk, allowing the clock to be later
+ * enabled atomically (via clk_enable). This function may sleep.
+ */
+int clk_prepare(struct clk *clk);
+
+/**
+ * clk_unprepare - release clock from prepared state
+ *
+ * @clk: The clock to release
+ *
+ * Do any (possbly blocking) cleanup on clk. This function may sleep.
+ */
+void clk_unprepare(struct clk *clk);
+
+/**
+ * clk_common_init - initialise a clock for driver usage
+ *
+ * @clk: The clock to initialise
+ *
+ * Used for runtime intialization of clocks; you don't need to call this
+ * if your clock has been (statically) initialized with INIT_CLK.
+ */
+static inline void clk_common_init(struct clk *clk)
+{
+	clk->enable_count = clk->prepare_count = 0;
+	spin_lock_init(&clk->enable_lock);
+	mutex_init(&clk->prepare_lock);
+}
+
+#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*
- * struct clk - an machine class defined object / cookie.
+ * Global clock object, actual structure is declared per-machine
  */
 struct clk;
 
+static inline void clk_common_init(struct clk *clk) { }
+
+/*
+ * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
+ * requirements for clk_enable/clk_disable, so the prepare and unprepare
+ * functions are no-ops
+ */
+int clk_prepare(struct clk *clk) { return 0; }
+void clk_unprepare(struct clk *clk) { }
+
+#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
+
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
  * @dev: device for clock "consumer"
@@ -83,12 +255,6 @@ unsigned long clk_get_rate(struct clk *clk);
  */
 void clk_put(struct clk *clk);
 
-
-/*
- * The remaining APIs are optional for machine class support.
- */
-
-
 /**
  * clk_round_rate - adjust a rate to the exact rate a clock can provide
  * @clk: clock source

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [RFC,PATCH 0/3] Common struct clk implementation, v11
  2011-02-01  9:11 ` Jeremy Kerr
  (?)
@ 2011-02-07  6:07   ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  6:07 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

These patches are an attempt to allow platforms to share clock code. At
present, the definitions of 'struct clk' are local to platform code,
which makes allocating and initialising cross-platform clock sources
difficult, and makes it impossible to compile a single image containing
support for two ARM platforms with different struct clks.

The three patches are for the architecture-independent kernel code,
introducing the common clk infrastructure. The changelog for the first
patch includes details about the new clock definitions.

Ben Herrenschmidt is looking at using common struct clk code for powerpc
too, hence the kernel-wide approach.

Many thanks to the following for their input:
 * Ben Dooks <ben-linux@fluff.org>
 * Baruch Siach <baruch@tkos.co.il>
 * Russell King <linux@arm.linux.org.uk>
 * Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 * Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
 * Vincent Guittot <vincent.guittot@linaro.org>
 * Sascha Hauer <s.hauer@pengutronix.de>

Cheers,


Jeremy

--
v11:
 * add prepare/unprepare for non-atomic switching, document atomicity
 * move to drivers/clk/

v10:
 * comment fixups, from Uwe's review
 * added DEFINE_CLK_FIXED

v9:
 * comment improvements
 * kerneldoc fixups
 * add WARN_ON to clk_disable

v8:
 * add atomic clocks, and locking wrappers
 * expand comments on clk and clk_ops

v7:
 * change CLK_INIT to initialise clk->mutex statically

v6:
 * fixed up references to 'clk_operations' in the changelog

v5:
 * uninline main API, and share definitions with !USE_COMMON_STRUCT_CLK
 * add __clk_get
 * delay mutex init
 * kerneldoc for struct clk

v4:
 * use mutex for enable/disable locking
 * DEFINE_CLK -> INIT_CLK, and pass the clk name for mutex init
 * struct clk_operations -> struct clk_ops

v3:
 * do clock usage refcounting in common code
 * provide sample port

v2:
 * no longer ARM-specific
 * use clk_operations

---
Jeremy Kerr (3):
      Add a common struct clk
      clk: Generic support for fixed-rate clocks
      clk: add warnings for incorrect enable/prepare semantics


^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,
  2011-02-01  9:11 ` Jeremy Kerr
  (?)
@ 2011-02-07  6:07   ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  6:07 UTC (permalink / raw)
  To: linux-arm-kernel

This change adds warnings to check for:

 1) enabling a clock that hasn't been prepared; and

 2) unpreparing a clock that is still enabled

While the correctness can't be guaranteed, these warnings should cover
most situations.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/clk.c |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 51dbd33..2369959 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -35,6 +35,8 @@ void clk_unprepare(struct clk *clk)
 	if (!clk->ops->unprepare)
 		return;
 
+	WARN_ON(clk->enable_count);
+
 	mutex_lock(&clk->prepare_lock);
 	if (--clk->prepare_count = 0)
 		clk->ops->unprepare(clk);
@@ -50,6 +52,8 @@ int clk_enable(struct clk *clk)
 	if (!clk->ops->enable)
 		return 0;
 
+	WARN_ON(clk->ops->prepare && clk->prepare_count);
+
 	spin_lock(&clk->enable_lock);
 	if (!clk->enable_count)
 		ret = clk->ops->enable(clk);

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-07  6:07   ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  6:07 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Uwe Kleine-König, Sascha Hauer,
	Paul Mundt, Saravana Kannan, Ben Dooks, Jeremy Kerr,
	Russell King

We currently have ~21 definitions of struct clk in the ARM architecture,
each defined on a per-platform basis. This makes it difficult to define
platform- (or architecture-) independent clock sources without making
assumptions about struct clk, and impossible to compile two
platforms with different struct clks into a single image.

This change is an effort to unify struct clk where possible, by defining
a common struct clk, containing a set of clock operations. Different
clock implementations can set their own operations, and have a standard
interface for generic code. The callback interface is exposed to the
kernel proper, while the clock implementations only need to be seen by
the platform internals.

This allows us to share clock code among platforms, and makes it
possible to dynamically create clock devices in platform-independent
code.

Platforms can enable the generic struct clock through
CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
consists of a common struct clk:

struct clk {
	const struct clk_ops	*ops;
	unsigned int		enable_count;
	unsigned int		prepare_count;
	spinlock_t		enable_lock;
	struct mutex		prepare_lock;
};

And a set of clock operations (defined per type of clock):

struct clk_ops {
	int             (*enable)(struct clk *);
	void            (*disable)(struct clk *);
	unsigned long   (*get_rate)(struct clk *);
	[...]
};

To define a hardware-specific clock, machine code can "subclass" the
struct clock into a new struct (adding any device-specific data), and
provide a set of operations:

struct clk_foo {
	struct clk	clk;
	void __iomem	*some_register;
};

struct clk_ops clk_foo_ops = {
	.get_rate = clk_foo_get_rate,
};

The common clock definitions are based on a development patch from Ben
Herrenschmidt <benh@kernel.crashing.org>.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/Kconfig  |    3 
 drivers/clk/Makefile |    1 
 drivers/clk/clk.c    |  134 +++++++++++++++++++++++++++++++
 drivers/clk/clkdev.c |    5 +
 include/linux/clk.h  |  184 ++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 318 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 4168c88..6e3ae54 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -2,3 +2,6 @@
 config CLKDEV_LOOKUP
 	bool
 	select HAVE_CLK
+
+config USE_COMMON_STRUCT_CLK
+	bool
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 07613fa..a1a06d3 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,2 +1,3 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
+obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
new file mode 100644
index 0000000..12e0daf
--- /dev/null
+++ b/drivers/clk/clk.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+
+int clk_prepare(struct clk *clk)
+{
+	int ret = 0;
+
+	if (!clk->ops->prepare)
+		return 0;
+
+	mutex_lock(&clk->prepare_lock);
+	if (clk->prepare_count == 0)
+		ret = clk->ops->prepare(clk);
+
+	if (!ret)
+		clk->prepare_count++;
+	mutex_unlock(&clk->prepare_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(clk_prepare);
+
+void clk_unprepare(struct clk *clk)
+{
+	if (!clk->ops->unprepare)
+		return;
+
+	mutex_lock(&clk->prepare_lock);
+	if (--clk->prepare_count == 0)
+		clk->ops->unprepare(clk);
+
+	mutex_unlock(&clk->prepare_lock);
+}
+EXPORT_SYMBOL_GPL(clk_unprepare);
+
+int clk_enable(struct clk *clk)
+{
+	int ret = 0;
+
+	if (!clk->ops->enable)
+		return 0;
+
+	spin_lock(&clk->enable_lock);
+	if (!clk->enable_count)
+		ret = clk->ops->enable(clk);
+
+	if (!ret)
+		clk->enable_count++;
+	spin_unlock(&clk->enable_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	if (!clk->ops->disable)
+		return;
+
+	spin_lock(&clk->enable_lock);
+
+	WARN_ON(!clk->enable_count);
+
+	if (!--clk->enable_count)
+		clk->ops->disable(clk);
+
+	spin_unlock(&clk->enable_lock);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk->ops->get_rate)
+		return clk->ops->get_rate(clk);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+int __clk_get(struct clk *clk)
+{
+	if (clk->ops->get)
+		return clk->ops->get(clk);
+	return 1;
+}
+EXPORT_SYMBOL_GPL(__clk_get);
+
+void clk_put(struct clk *clk)
+{
+	if (clk->ops->put)
+		clk->ops->put(clk);
+}
+EXPORT_SYMBOL_GPL(clk_put);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->round_rate)
+		return clk->ops->round_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->set_rate)
+		return clk->ops->set_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (clk->ops->set_parent)
+		return clk->ops->set_parent(clk, parent);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	if (clk->ops->get_parent)
+		return clk->ops->get_parent(clk);
+	return ERR_PTR(-ENOSYS);
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 0fc0a79..17619c7 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -84,12 +84,17 @@ struct clk *clk_get(struct device *dev, const char *con_id)
 }
 EXPORT_SYMBOL(clk_get);
 
+#ifndef CONFIG_USE_COMMON_STRUCT_CLK
+/* For the common struct clk case, clk_put is provided by clk.c */
+
 void clk_put(struct clk *clk)
 {
 	__clk_put(clk);
 }
 EXPORT_SYMBOL(clk_put);
 
+#endif
+
 void clkdev_add(struct clk_lookup *cl)
 {
 	mutex_lock(&clocks_mutex);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1d37f42..e081ca1 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2004 ARM Limited.
  *  Written by Deep Blue Solutions Limited.
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,18 +12,189 @@
 #ifndef __LINUX_CLK_H
 #define __LINUX_CLK_H
 
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
 struct device;
 
-/*
- * The base API.
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+
+/* If we're using the common struct clk, we define the base clk object here */
+
+/**
+ * struct clk - hardware independent clock structure
+ * @ops:		implementation-specific ops for this clock
+ * @enable_count:	count of clk_enable() calls active on this clock
+ * @flags:		platform-independent flags
+ * @lock:		lock for enable/disable or other HW-specific ops
+ *
+ * The base clock object, used by drivers for hardware-independent manipulation
+ * of clock lines. This will be 'subclassed' by device-specific implementations,
+ * which add device-specific data to struct clk. For example:
+ *
+ *  struct clk_foo {
+ *      struct clk;
+ *      [device specific fields]
+ *  };
+ *
+ * The clock driver code will manage the device-specific data, and pass
+ * clk_foo.clk to the common clock code. The clock driver will be called
+ * through the @ops callbacks.
+ *
+ * The @lock member provides either a spinlock or a mutex to protect (at least)
+ * @enable_count. The type of lock used will depend on @flags; if CLK_ATOMIC is
+ * set, then the core clock code will use a spinlock, otherwise a mutex. This
+ * lock will be acquired during clk_enable and clk_disable, so for atomic
+ * clocks, these ops callbacks must not sleep.
+ *
+ * The choice of atomic or non-atomic clock depends on how the clock is enabled.
+ * Typically, you'll want to use a non-atomic clock. For clocks that need to be
+ * enabled/disabled in interrupt context, use CLK_ATOMIC. Note that atomic
+ * clocks with parents will typically cascade enable/disable operations to
+ * their parent, so the parent of an atomic clock *must* be atomic too.
  */
+struct clk {
+	const struct clk_ops	*ops;
+	unsigned int		enable_count;
+	unsigned int		prepare_count;
+	spinlock_t		enable_lock;
+	struct mutex		prepare_lock;
+};
+
+/* static initialiser for non-atomic clocks */
+#define INIT_CLK(name, o) {						\
+	.ops		= &o,						\
+	.enable_count	= 0,						\
+	.prepare_count	= 0,						\
+	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
+	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
+}
 
+/**
+ * struct clk_ops -  Callback operations for clocks; these are to be provided
+ * by the clock implementation, and will be called by drivers through the clk_*
+ * API.
+ *
+ * @prepare:	Prepare the clock for enabling. This must not return until
+ *		the clock is fully prepared, and it's safe to call clk_enable.
+ *		This callback is intended to allow clock implementations to
+ *		do any initialisation that may block. Called with
+ *		clk->prepare_lock held.
+ *
+ * @unprepare:	Release the clock from its prepared state. This will typically
+ *		undo any work done in the @prepare callback. Called with
+ *		clk->prepare_lock held.
+ *
+ * @enable:	Enable the clock atomically. This must not return until the
+ *		clock is generating a valid clock signal, usable by consumer
+ *		devices. Called with clk->enable_lock held.
+ *
+ * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
+ *
+ * @get:	Called by the core clock code when a device driver acquires a
+ *		clock via clk_get(). Optional.
+ *
+ * @put:	Called by the core clock code when a devices driver releases a
+ *		clock via clk_put(). Optional.
+ *
+ * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
+ * implementations to split any work between atomic (enable) and sleepable
+ * (prepare) contexts.  If a clock requires blocking code to be turned on, this
+ * should be done in clk_prepare. Switching that will not block should be done
+ * in clk_enable.
+ *
+ * Typically, drivers will call clk_prepare when a clock may be needed later
+ * (eg. when a device is opened), and clk_enable when the clock is actually
+ * required (eg. from an interrupt).
+ *
+ * For other callbacks, see the corresponding clk_* functions. Parameters and
+ * return values are passed directly from/to these API functions, or
+ * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
+ * is NULL, see kernel/clk.c for implementation details. All are optional.
+ */
+struct clk_ops {
+	int		(*prepare)(struct clk *);
+	void		(*unprepare)(struct clk *);
+	int		(*enable)(struct clk *);
+	void		(*disable)(struct clk *);
+	int		(*get)(struct clk *);
+	void		(*put)(struct clk *);
+	unsigned long	(*get_rate)(struct clk *);
+	long		(*round_rate)(struct clk *, unsigned long);
+	int		(*set_rate)(struct clk *, unsigned long);
+	int		(*set_parent)(struct clk *, struct clk *);
+	struct clk *	(*get_parent)(struct clk *);
+};
+
+/**
+ * __clk_get - update clock-specific refcounter
+ *
+ * @clk: The clock to refcount
+ *
+ * Before a clock is returned from clk_get, this function should be called
+ * to update any clock-specific refcounting.
+ *
+ * Returns non-zero on success, zero on failure.
+ *
+ * Drivers should not need this function; it is only needed by the
+ * arch-specific clk_get() implementations.
+ */
+int __clk_get(struct clk *clk);
+
+/**
+ * clk_prepare - prepare clock for atomic enabling.
+ *
+ * @clk: The clock to prepare
+ *
+ * Do any blocking initialisation on @clk, allowing the clock to be later
+ * enabled atomically (via clk_enable). This function may sleep.
+ */
+int clk_prepare(struct clk *clk);
+
+/**
+ * clk_unprepare - release clock from prepared state
+ *
+ * @clk: The clock to release
+ *
+ * Do any (possbly blocking) cleanup on clk. This function may sleep.
+ */
+void clk_unprepare(struct clk *clk);
+
+/**
+ * clk_common_init - initialise a clock for driver usage
+ *
+ * @clk: The clock to initialise
+ *
+ * Used for runtime intialization of clocks; you don't need to call this
+ * if your clock has been (statically) initialized with INIT_CLK.
+ */
+static inline void clk_common_init(struct clk *clk)
+{
+	clk->enable_count = clk->prepare_count = 0;
+	spin_lock_init(&clk->enable_lock);
+	mutex_init(&clk->prepare_lock);
+}
+
+#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*
- * struct clk - an machine class defined object / cookie.
+ * Global clock object, actual structure is declared per-machine
  */
 struct clk;
 
+static inline void clk_common_init(struct clk *clk) { }
+
+/*
+ * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
+ * requirements for clk_enable/clk_disable, so the prepare and unprepare
+ * functions are no-ops
+ */
+int clk_prepare(struct clk *clk) { return 0; }
+void clk_unprepare(struct clk *clk) { }
+
+#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
+
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
  * @dev: device for clock "consumer"
@@ -83,12 +255,6 @@ unsigned long clk_get_rate(struct clk *clk);
  */
 void clk_put(struct clk *clk);
 
-
-/*
- * The remaining APIs are optional for machine class support.
- */
-
-
 /**
  * clk_round_rate - adjust a rate to the exact rate a clock can provide
  * @clk: clock source

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [RFC,PATCH 0/3] Common struct clk implementation, v11
@ 2011-02-07  6:07   ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  6:07 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Uwe Kleine-König, Sascha Hauer,
	Paul Mundt, Saravana Kannan, Ben Dooks, Jeremy Kerr,
	Russell King

Hi all,

These patches are an attempt to allow platforms to share clock code. At
present, the definitions of 'struct clk' are local to platform code,
which makes allocating and initialising cross-platform clock sources
difficult, and makes it impossible to compile a single image containing
support for two ARM platforms with different struct clks.

The three patches are for the architecture-independent kernel code,
introducing the common clk infrastructure. The changelog for the first
patch includes details about the new clock definitions.

Ben Herrenschmidt is looking at using common struct clk code for powerpc
too, hence the kernel-wide approach.

Many thanks to the following for their input:
 * Ben Dooks <ben-linux@fluff.org>
 * Baruch Siach <baruch@tkos.co.il>
 * Russell King <linux@arm.linux.org.uk>
 * Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 * Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
 * Vincent Guittot <vincent.guittot@linaro.org>
 * Sascha Hauer <s.hauer@pengutronix.de>

Cheers,


Jeremy

--
v11:
 * add prepare/unprepare for non-atomic switching, document atomicity
 * move to drivers/clk/

v10:
 * comment fixups, from Uwe's review
 * added DEFINE_CLK_FIXED

v9:
 * comment improvements
 * kerneldoc fixups
 * add WARN_ON to clk_disable

v8:
 * add atomic clocks, and locking wrappers
 * expand comments on clk and clk_ops

v7:
 * change CLK_INIT to initialise clk->mutex statically

v6:
 * fixed up references to 'clk_operations' in the changelog

v5:
 * uninline main API, and share definitions with !USE_COMMON_STRUCT_CLK
 * add __clk_get
 * delay mutex init
 * kerneldoc for struct clk

v4:
 * use mutex for enable/disable locking
 * DEFINE_CLK -> INIT_CLK, and pass the clk name for mutex init
 * struct clk_operations -> struct clk_ops

v3:
 * do clock usage refcounting in common code
 * provide sample port

v2:
 * no longer ARM-specific
 * use clk_operations

---
Jeremy Kerr (3):
      Add a common struct clk
      clk: Generic support for fixed-rate clocks
      clk: add warnings for incorrect enable/prepare semantics


^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
@ 2011-02-07  6:07   ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  6:07 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Uwe Kleine-König, Sascha Hauer,
	Paul Mundt, Saravana Kannan, Ben Dooks, Jeremy Kerr,
	Russell King

Since most platforms will need a fixed-rate clock, add one. This will
also serve as a basic example of an implementation of struct clk.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/clk.c   |   14 ++++++++++++++
 include/linux/clk.h |   16 ++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 12e0daf..51dbd33 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -132,3 +132,17 @@ struct clk *clk_get_parent(struct clk *clk)
 	return ERR_PTR(-ENOSYS);
 }
 EXPORT_SYMBOL_GPL(clk_get_parent);
+
+/* clk_fixed support */
+
+#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
+
+static unsigned long clk_fixed_get_rate(struct clk *clk)
+{
+	return to_clk_fixed(clk)->rate;
+}
+
+struct clk_ops clk_fixed_ops = {
+	.get_rate = clk_fixed_get_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index e081ca1..daa2d5a 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -176,6 +176,22 @@ static inline void clk_common_init(struct clk *clk)
 	mutex_init(&clk->prepare_lock);
 }
 
+/* Simple fixed-rate clock */
+struct clk_fixed {
+	struct clk	clk;
+	unsigned long	rate;
+};
+
+extern struct clk_ops clk_fixed_ops;
+
+#define INIT_CLK_FIXED(name, r) { \
+	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
+	.rate = (r) \
+}
+
+#define DEFINE_CLK_FIXED(name, r) \
+	struct clk_fixed name = INIT_CLK_FIXED(name, r)
+
 #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-07  6:07   ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  6:07 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Uwe Kleine-König, Sascha Hauer,
	Paul Mundt, Saravana Kannan, Ben Dooks, Jeremy Kerr,
	Russell King

This change adds warnings to check for:

 1) enabling a clock that hasn't been prepared; and

 2) unpreparing a clock that is still enabled

While the correctness can't be guaranteed, these warnings should cover
most situations.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/clk.c |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 51dbd33..2369959 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -35,6 +35,8 @@ void clk_unprepare(struct clk *clk)
 	if (!clk->ops->unprepare)
 		return;
 
+	WARN_ON(clk->enable_count);
+
 	mutex_lock(&clk->prepare_lock);
 	if (--clk->prepare_count == 0)
 		clk->ops->unprepare(clk);
@@ -50,6 +52,8 @@ int clk_enable(struct clk *clk)
 	if (!clk->ops->enable)
 		return 0;
 
+	WARN_ON(clk->ops->prepare && clk->prepare_count);
+
 	spin_lock(&clk->enable_lock);
 	if (!clk->enable_count)
 		ret = clk->ops->enable(clk);

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [RFC,PATCH 0/3] Common struct clk implementation, v11
@ 2011-02-07  6:07   ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  6:07 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

These patches are an attempt to allow platforms to share clock code. At
present, the definitions of 'struct clk' are local to platform code,
which makes allocating and initialising cross-platform clock sources
difficult, and makes it impossible to compile a single image containing
support for two ARM platforms with different struct clks.

The three patches are for the architecture-independent kernel code,
introducing the common clk infrastructure. The changelog for the first
patch includes details about the new clock definitions.

Ben Herrenschmidt is looking at using common struct clk code for powerpc
too, hence the kernel-wide approach.

Many thanks to the following for their input:
 * Ben Dooks <ben-linux@fluff.org>
 * Baruch Siach <baruch@tkos.co.il>
 * Russell King <linux@arm.linux.org.uk>
 * Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
 * Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
 * Vincent Guittot <vincent.guittot@linaro.org>
 * Sascha Hauer <s.hauer@pengutronix.de>

Cheers,


Jeremy

--
v11:
 * add prepare/unprepare for non-atomic switching, document atomicity
 * move to drivers/clk/

v10:
 * comment fixups, from Uwe's review
 * added DEFINE_CLK_FIXED

v9:
 * comment improvements
 * kerneldoc fixups
 * add WARN_ON to clk_disable

v8:
 * add atomic clocks, and locking wrappers
 * expand comments on clk and clk_ops

v7:
 * change CLK_INIT to initialise clk->mutex statically

v6:
 * fixed up references to 'clk_operations' in the changelog

v5:
 * uninline main API, and share definitions with !USE_COMMON_STRUCT_CLK
 * add __clk_get
 * delay mutex init
 * kerneldoc for struct clk

v4:
 * use mutex for enable/disable locking
 * DEFINE_CLK -> INIT_CLK, and pass the clk name for mutex init
 * struct clk_operations -> struct clk_ops

v3:
 * do clock usage refcounting in common code
 * provide sample port

v2:
 * no longer ARM-specific
 * use clk_operations

---
Jeremy Kerr (3):
      Add a common struct clk
      clk: Generic support for fixed-rate clocks
      clk: add warnings for incorrect enable/prepare semantics

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-07  6:07   ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  6:07 UTC (permalink / raw)
  To: linux-arm-kernel

We currently have ~21 definitions of struct clk in the ARM architecture,
each defined on a per-platform basis. This makes it difficult to define
platform- (or architecture-) independent clock sources without making
assumptions about struct clk, and impossible to compile two
platforms with different struct clks into a single image.

This change is an effort to unify struct clk where possible, by defining
a common struct clk, containing a set of clock operations. Different
clock implementations can set their own operations, and have a standard
interface for generic code. The callback interface is exposed to the
kernel proper, while the clock implementations only need to be seen by
the platform internals.

This allows us to share clock code among platforms, and makes it
possible to dynamically create clock devices in platform-independent
code.

Platforms can enable the generic struct clock through
CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
consists of a common struct clk:

struct clk {
	const struct clk_ops	*ops;
	unsigned int		enable_count;
	unsigned int		prepare_count;
	spinlock_t		enable_lock;
	struct mutex		prepare_lock;
};

And a set of clock operations (defined per type of clock):

struct clk_ops {
	int             (*enable)(struct clk *);
	void            (*disable)(struct clk *);
	unsigned long   (*get_rate)(struct clk *);
	[...]
};

To define a hardware-specific clock, machine code can "subclass" the
struct clock into a new struct (adding any device-specific data), and
provide a set of operations:

struct clk_foo {
	struct clk	clk;
	void __iomem	*some_register;
};

struct clk_ops clk_foo_ops = {
	.get_rate = clk_foo_get_rate,
};

The common clock definitions are based on a development patch from Ben
Herrenschmidt <benh@kernel.crashing.org>.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/Kconfig  |    3 
 drivers/clk/Makefile |    1 
 drivers/clk/clk.c    |  134 +++++++++++++++++++++++++++++++
 drivers/clk/clkdev.c |    5 +
 include/linux/clk.h  |  184 ++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 318 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 4168c88..6e3ae54 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -2,3 +2,6 @@
 config CLKDEV_LOOKUP
 	bool
 	select HAVE_CLK
+
+config USE_COMMON_STRUCT_CLK
+	bool
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 07613fa..a1a06d3 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,2 +1,3 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
+obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
new file mode 100644
index 0000000..12e0daf
--- /dev/null
+++ b/drivers/clk/clk.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+
+int clk_prepare(struct clk *clk)
+{
+	int ret = 0;
+
+	if (!clk->ops->prepare)
+		return 0;
+
+	mutex_lock(&clk->prepare_lock);
+	if (clk->prepare_count == 0)
+		ret = clk->ops->prepare(clk);
+
+	if (!ret)
+		clk->prepare_count++;
+	mutex_unlock(&clk->prepare_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(clk_prepare);
+
+void clk_unprepare(struct clk *clk)
+{
+	if (!clk->ops->unprepare)
+		return;
+
+	mutex_lock(&clk->prepare_lock);
+	if (--clk->prepare_count == 0)
+		clk->ops->unprepare(clk);
+
+	mutex_unlock(&clk->prepare_lock);
+}
+EXPORT_SYMBOL_GPL(clk_unprepare);
+
+int clk_enable(struct clk *clk)
+{
+	int ret = 0;
+
+	if (!clk->ops->enable)
+		return 0;
+
+	spin_lock(&clk->enable_lock);
+	if (!clk->enable_count)
+		ret = clk->ops->enable(clk);
+
+	if (!ret)
+		clk->enable_count++;
+	spin_unlock(&clk->enable_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	if (!clk->ops->disable)
+		return;
+
+	spin_lock(&clk->enable_lock);
+
+	WARN_ON(!clk->enable_count);
+
+	if (!--clk->enable_count)
+		clk->ops->disable(clk);
+
+	spin_unlock(&clk->enable_lock);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk->ops->get_rate)
+		return clk->ops->get_rate(clk);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+int __clk_get(struct clk *clk)
+{
+	if (clk->ops->get)
+		return clk->ops->get(clk);
+	return 1;
+}
+EXPORT_SYMBOL_GPL(__clk_get);
+
+void clk_put(struct clk *clk)
+{
+	if (clk->ops->put)
+		clk->ops->put(clk);
+}
+EXPORT_SYMBOL_GPL(clk_put);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->round_rate)
+		return clk->ops->round_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->set_rate)
+		return clk->ops->set_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (clk->ops->set_parent)
+		return clk->ops->set_parent(clk, parent);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	if (clk->ops->get_parent)
+		return clk->ops->get_parent(clk);
+	return ERR_PTR(-ENOSYS);
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 0fc0a79..17619c7 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -84,12 +84,17 @@ struct clk *clk_get(struct device *dev, const char *con_id)
 }
 EXPORT_SYMBOL(clk_get);
 
+#ifndef CONFIG_USE_COMMON_STRUCT_CLK
+/* For the common struct clk case, clk_put is provided by clk.c */
+
 void clk_put(struct clk *clk)
 {
 	__clk_put(clk);
 }
 EXPORT_SYMBOL(clk_put);
 
+#endif
+
 void clkdev_add(struct clk_lookup *cl)
 {
 	mutex_lock(&clocks_mutex);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1d37f42..e081ca1 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2004 ARM Limited.
  *  Written by Deep Blue Solutions Limited.
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,18 +12,189 @@
 #ifndef __LINUX_CLK_H
 #define __LINUX_CLK_H
 
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
 struct device;
 
-/*
- * The base API.
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+
+/* If we're using the common struct clk, we define the base clk object here */
+
+/**
+ * struct clk - hardware independent clock structure
+ * @ops:		implementation-specific ops for this clock
+ * @enable_count:	count of clk_enable() calls active on this clock
+ * @flags:		platform-independent flags
+ * @lock:		lock for enable/disable or other HW-specific ops
+ *
+ * The base clock object, used by drivers for hardware-independent manipulation
+ * of clock lines. This will be 'subclassed' by device-specific implementations,
+ * which add device-specific data to struct clk. For example:
+ *
+ *  struct clk_foo {
+ *      struct clk;
+ *      [device specific fields]
+ *  };
+ *
+ * The clock driver code will manage the device-specific data, and pass
+ * clk_foo.clk to the common clock code. The clock driver will be called
+ * through the @ops callbacks.
+ *
+ * The @lock member provides either a spinlock or a mutex to protect (at least)
+ * @enable_count. The type of lock used will depend on @flags; if CLK_ATOMIC is
+ * set, then the core clock code will use a spinlock, otherwise a mutex. This
+ * lock will be acquired during clk_enable and clk_disable, so for atomic
+ * clocks, these ops callbacks must not sleep.
+ *
+ * The choice of atomic or non-atomic clock depends on how the clock is enabled.
+ * Typically, you'll want to use a non-atomic clock. For clocks that need to be
+ * enabled/disabled in interrupt context, use CLK_ATOMIC. Note that atomic
+ * clocks with parents will typically cascade enable/disable operations to
+ * their parent, so the parent of an atomic clock *must* be atomic too.
  */
+struct clk {
+	const struct clk_ops	*ops;
+	unsigned int		enable_count;
+	unsigned int		prepare_count;
+	spinlock_t		enable_lock;
+	struct mutex		prepare_lock;
+};
+
+/* static initialiser for non-atomic clocks */
+#define INIT_CLK(name, o) {						\
+	.ops		= &o,						\
+	.enable_count	= 0,						\
+	.prepare_count	= 0,						\
+	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
+	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
+}
 
+/**
+ * struct clk_ops -  Callback operations for clocks; these are to be provided
+ * by the clock implementation, and will be called by drivers through the clk_*
+ * API.
+ *
+ * @prepare:	Prepare the clock for enabling. This must not return until
+ *		the clock is fully prepared, and it's safe to call clk_enable.
+ *		This callback is intended to allow clock implementations to
+ *		do any initialisation that may block. Called with
+ *		clk->prepare_lock held.
+ *
+ * @unprepare:	Release the clock from its prepared state. This will typically
+ *		undo any work done in the @prepare callback. Called with
+ *		clk->prepare_lock held.
+ *
+ * @enable:	Enable the clock atomically. This must not return until the
+ *		clock is generating a valid clock signal, usable by consumer
+ *		devices. Called with clk->enable_lock held.
+ *
+ * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
+ *
+ * @get:	Called by the core clock code when a device driver acquires a
+ *		clock via clk_get(). Optional.
+ *
+ * @put:	Called by the core clock code when a devices driver releases a
+ *		clock via clk_put(). Optional.
+ *
+ * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
+ * implementations to split any work between atomic (enable) and sleepable
+ * (prepare) contexts.  If a clock requires blocking code to be turned on, this
+ * should be done in clk_prepare. Switching that will not block should be done
+ * in clk_enable.
+ *
+ * Typically, drivers will call clk_prepare when a clock may be needed later
+ * (eg. when a device is opened), and clk_enable when the clock is actually
+ * required (eg. from an interrupt).
+ *
+ * For other callbacks, see the corresponding clk_* functions. Parameters and
+ * return values are passed directly from/to these API functions, or
+ * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
+ * is NULL, see kernel/clk.c for implementation details. All are optional.
+ */
+struct clk_ops {
+	int		(*prepare)(struct clk *);
+	void		(*unprepare)(struct clk *);
+	int		(*enable)(struct clk *);
+	void		(*disable)(struct clk *);
+	int		(*get)(struct clk *);
+	void		(*put)(struct clk *);
+	unsigned long	(*get_rate)(struct clk *);
+	long		(*round_rate)(struct clk *, unsigned long);
+	int		(*set_rate)(struct clk *, unsigned long);
+	int		(*set_parent)(struct clk *, struct clk *);
+	struct clk *	(*get_parent)(struct clk *);
+};
+
+/**
+ * __clk_get - update clock-specific refcounter
+ *
+ * @clk: The clock to refcount
+ *
+ * Before a clock is returned from clk_get, this function should be called
+ * to update any clock-specific refcounting.
+ *
+ * Returns non-zero on success, zero on failure.
+ *
+ * Drivers should not need this function; it is only needed by the
+ * arch-specific clk_get() implementations.
+ */
+int __clk_get(struct clk *clk);
+
+/**
+ * clk_prepare - prepare clock for atomic enabling.
+ *
+ * @clk: The clock to prepare
+ *
+ * Do any blocking initialisation on @clk, allowing the clock to be later
+ * enabled atomically (via clk_enable). This function may sleep.
+ */
+int clk_prepare(struct clk *clk);
+
+/**
+ * clk_unprepare - release clock from prepared state
+ *
+ * @clk: The clock to release
+ *
+ * Do any (possbly blocking) cleanup on clk. This function may sleep.
+ */
+void clk_unprepare(struct clk *clk);
+
+/**
+ * clk_common_init - initialise a clock for driver usage
+ *
+ * @clk: The clock to initialise
+ *
+ * Used for runtime intialization of clocks; you don't need to call this
+ * if your clock has been (statically) initialized with INIT_CLK.
+ */
+static inline void clk_common_init(struct clk *clk)
+{
+	clk->enable_count = clk->prepare_count = 0;
+	spin_lock_init(&clk->enable_lock);
+	mutex_init(&clk->prepare_lock);
+}
+
+#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*
- * struct clk - an machine class defined object / cookie.
+ * Global clock object, actual structure is declared per-machine
  */
 struct clk;
 
+static inline void clk_common_init(struct clk *clk) { }
+
+/*
+ * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
+ * requirements for clk_enable/clk_disable, so the prepare and unprepare
+ * functions are no-ops
+ */
+int clk_prepare(struct clk *clk) { return 0; }
+void clk_unprepare(struct clk *clk) { }
+
+#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
+
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
  * @dev: device for clock "consumer"
@@ -83,12 +255,6 @@ unsigned long clk_get_rate(struct clk *clk);
  */
 void clk_put(struct clk *clk);
 
-
-/*
- * The remaining APIs are optional for machine class support.
- */
-
-
 /**
  * clk_round_rate - adjust a rate to the exact rate a clock can provide
  * @clk: clock source

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-07  6:07   ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  6:07 UTC (permalink / raw)
  To: linux-arm-kernel

This change adds warnings to check for:

 1) enabling a clock that hasn't been prepared; and

 2) unpreparing a clock that is still enabled

While the correctness can't be guaranteed, these warnings should cover
most situations.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/clk.c |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 51dbd33..2369959 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -35,6 +35,8 @@ void clk_unprepare(struct clk *clk)
 	if (!clk->ops->unprepare)
 		return;
 
+	WARN_ON(clk->enable_count);
+
 	mutex_lock(&clk->prepare_lock);
 	if (--clk->prepare_count == 0)
 		clk->ops->unprepare(clk);
@@ -50,6 +52,8 @@ int clk_enable(struct clk *clk)
 	if (!clk->ops->enable)
 		return 0;
 
+	WARN_ON(clk->ops->prepare && clk->prepare_count);
+
 	spin_lock(&clk->enable_lock);
 	if (!clk->enable_count)
 		ret = clk->ops->enable(clk);

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
@ 2011-02-07  6:07   ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  6:07 UTC (permalink / raw)
  To: linux-arm-kernel

Since most platforms will need a fixed-rate clock, add one. This will
also serve as a basic example of an implementation of struct clk.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/clk.c   |   14 ++++++++++++++
 include/linux/clk.h |   16 ++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 12e0daf..51dbd33 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -132,3 +132,17 @@ struct clk *clk_get_parent(struct clk *clk)
 	return ERR_PTR(-ENOSYS);
 }
 EXPORT_SYMBOL_GPL(clk_get_parent);
+
+/* clk_fixed support */
+
+#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
+
+static unsigned long clk_fixed_get_rate(struct clk *clk)
+{
+	return to_clk_fixed(clk)->rate;
+}
+
+struct clk_ops clk_fixed_ops = {
+	.get_rate = clk_fixed_get_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index e081ca1..daa2d5a 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -176,6 +176,22 @@ static inline void clk_common_init(struct clk *clk)
 	mutex_init(&clk->prepare_lock);
 }
 
+/* Simple fixed-rate clock */
+struct clk_fixed {
+	struct clk	clk;
+	unsigned long	rate;
+};
+
+extern struct clk_ops clk_fixed_ops;
+
+#define INIT_CLK_FIXED(name, r) { \
+	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
+	.rate = (r) \
+}
+
+#define DEFINE_CLK_FIXED(name, r) \
+	struct clk_fixed name = INIT_CLK_FIXED(name, r)
+
 #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* Re: [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
  2011-02-07  6:07   ` Jeremy Kerr
  (?)
@ 2011-02-07  6:29     ` Jassi Brar
  -1 siblings, 0 replies; 383+ messages in thread
From: Jassi Brar @ 2011-02-07  6:29 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 7, 2011 at 3:07 PM, Jeremy Kerr <jeremy.kerr@canonical.com> wrote:
> This change adds warnings to check for:
>
>  1) enabling a clock that hasn't been prepared; and
>
>  2) unpreparing a clock that is still enabled
>
> While the correctness can't be guaranteed, these warnings should cover
> most situations.
>
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
>
> ---
>  drivers/clk/clk.c |    4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 51dbd33..2369959 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -35,6 +35,8 @@ void clk_unprepare(struct clk *clk)
>        if (!clk->ops->unprepare)
>                return;
>
> +       WARN_ON(clk->enable_count);
> +
>        mutex_lock(&clk->prepare_lock);
>        if (--clk->prepare_count = 0)
>                clk->ops->unprepare(clk);
> @@ -50,6 +52,8 @@ int clk_enable(struct clk *clk)
>        if (!clk->ops->enable)
>                return 0;
>
> +       WARN_ON(clk->ops->prepare && clk->prepare_count);
> +

Shouldn't the prepare_count be checked against 0 ?

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-07  6:29     ` Jassi Brar
  0 siblings, 0 replies; 383+ messages in thread
From: Jassi Brar @ 2011-02-07  6:29 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, Dima Zavin, Saravana Kannan, Ben Dooks,
	Uwe Kleine-König, Russell King

On Mon, Feb 7, 2011 at 3:07 PM, Jeremy Kerr <jeremy.kerr@canonical.com> wrote:
> This change adds warnings to check for:
>
>  1) enabling a clock that hasn't been prepared; and
>
>  2) unpreparing a clock that is still enabled
>
> While the correctness can't be guaranteed, these warnings should cover
> most situations.
>
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
>
> ---
>  drivers/clk/clk.c |    4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 51dbd33..2369959 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -35,6 +35,8 @@ void clk_unprepare(struct clk *clk)
>        if (!clk->ops->unprepare)
>                return;
>
> +       WARN_ON(clk->enable_count);
> +
>        mutex_lock(&clk->prepare_lock);
>        if (--clk->prepare_count == 0)
>                clk->ops->unprepare(clk);
> @@ -50,6 +52,8 @@ int clk_enable(struct clk *clk)
>        if (!clk->ops->enable)
>                return 0;
>
> +       WARN_ON(clk->ops->prepare && clk->prepare_count);
> +

Shouldn't the prepare_count be checked against 0 ?

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-07  6:29     ` Jassi Brar
  0 siblings, 0 replies; 383+ messages in thread
From: Jassi Brar @ 2011-02-07  6:29 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 7, 2011 at 3:07 PM, Jeremy Kerr <jeremy.kerr@canonical.com> wrote:
> This change adds warnings to check for:
>
> ?1) enabling a clock that hasn't been prepared; and
>
> ?2) unpreparing a clock that is still enabled
>
> While the correctness can't be guaranteed, these warnings should cover
> most situations.
>
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
>
> ---
> ?drivers/clk/clk.c | ? ?4 ++++
> ?1 file changed, 4 insertions(+)
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 51dbd33..2369959 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -35,6 +35,8 @@ void clk_unprepare(struct clk *clk)
> ? ? ? ?if (!clk->ops->unprepare)
> ? ? ? ? ? ? ? ?return;
>
> + ? ? ? WARN_ON(clk->enable_count);
> +
> ? ? ? ?mutex_lock(&clk->prepare_lock);
> ? ? ? ?if (--clk->prepare_count == 0)
> ? ? ? ? ? ? ? ?clk->ops->unprepare(clk);
> @@ -50,6 +52,8 @@ int clk_enable(struct clk *clk)
> ? ? ? ?if (!clk->ops->enable)
> ? ? ? ? ? ? ? ?return 0;
>
> + ? ? ? WARN_ON(clk->ops->prepare && clk->prepare_count);
> +

Shouldn't the prepare_count be checked against 0 ?

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
  2011-02-07  6:29     ` Jassi Brar
  (?)
@ 2011-02-07  7:00       ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  7:00 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jassi,

> Shouldn't the prepare_count be checked against 0 ?

Yes, you're right, it should be clk->prepare_count = 0.

Will update for the next revision.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-07  7:00       ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  7:00 UTC (permalink / raw)
  To: Jassi Brar
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, Dima Zavin, Saravana Kannan, Ben Dooks,
	Uwe Kleine-König, Russell King

Hi Jassi,

> Shouldn't the prepare_count be checked against 0 ?

Yes, you're right, it should be clk->prepare_count == 0.

Will update for the next revision.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-07  7:00       ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  7:00 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jassi,

> Shouldn't the prepare_count be checked against 0 ?

Yes, you're right, it should be clk->prepare_count == 0.

Will update for the next revision.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-07  6:07   ` Jeremy Kerr
  (?)
@ 2011-02-07  7:05     ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-07  7:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 07, 2011 at 02:07:57PM +0800, Jeremy Kerr wrote:
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, containing a set of clock operations. Different
> clock implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
> 
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
> 
> And a set of clock operations (defined per type of clock):
> 
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
> 
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
> 
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
> 
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/Kconfig  |    3 
>  drivers/clk/Makefile |    1 
>  drivers/clk/clk.c    |  134 +++++++++++++++++++++++++++++++
>  drivers/clk/clkdev.c |    5 +
>  include/linux/clk.h  |  184 ++++++++++++++++++++++++++++++++++++++++---
>  5 files changed, 318 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4168c88..6e3ae54 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -2,3 +2,6 @@
>  config CLKDEV_LOOKUP
>  	bool
>  	select HAVE_CLK
> +
> +config USE_COMMON_STRUCT_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..a1a06d3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..12e0daf
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,134 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk->ops->prepare)
> +		return 0;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (clk->prepare_count = 0)
> +		ret = clk->ops->prepare(clk);
> +
> +	if (!ret)
> +		clk->prepare_count++;
> +	mutex_unlock(&clk->prepare_lock);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	if (!clk->ops->unprepare)
> +		return;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (--clk->prepare_count = 0)
> +		clk->ops->unprepare(clk);
> +
> +	mutex_unlock(&clk->prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +int clk_enable(struct clk *clk)
> +{
> +	int ret = 0;
> +
Did we want to check for prepare_count > 0 here?  Russell's suggestion
was to do that without holding any lock.
(To make this a tad safer, you could use
ACCESS_ONCE(clk->enable_count)++ below. (Suggested by paulmck on irc.))

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-07  7:05     ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-07  7:05 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Dima Zavin,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Sascha Hauer, Paul Mundt, Saravana Kannan, Ben Dooks,
	Russell King

On Mon, Feb 07, 2011 at 02:07:57PM +0800, Jeremy Kerr wrote:
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, containing a set of clock operations. Different
> clock implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
> 
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
> 
> And a set of clock operations (defined per type of clock):
> 
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
> 
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
> 
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
> 
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/Kconfig  |    3 
>  drivers/clk/Makefile |    1 
>  drivers/clk/clk.c    |  134 +++++++++++++++++++++++++++++++
>  drivers/clk/clkdev.c |    5 +
>  include/linux/clk.h  |  184 ++++++++++++++++++++++++++++++++++++++++---
>  5 files changed, 318 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4168c88..6e3ae54 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -2,3 +2,6 @@
>  config CLKDEV_LOOKUP
>  	bool
>  	select HAVE_CLK
> +
> +config USE_COMMON_STRUCT_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..a1a06d3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..12e0daf
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,134 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk->ops->prepare)
> +		return 0;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (clk->prepare_count == 0)
> +		ret = clk->ops->prepare(clk);
> +
> +	if (!ret)
> +		clk->prepare_count++;
> +	mutex_unlock(&clk->prepare_lock);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	if (!clk->ops->unprepare)
> +		return;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (--clk->prepare_count == 0)
> +		clk->ops->unprepare(clk);
> +
> +	mutex_unlock(&clk->prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +int clk_enable(struct clk *clk)
> +{
> +	int ret = 0;
> +
Did we want to check for prepare_count > 0 here?  Russell's suggestion
was to do that without holding any lock.
(To make this a tad safer, you could use
ACCESS_ONCE(clk->enable_count)++ below. (Suggested by paulmck on irc.))

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-07  7:05     ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-07  7:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 07, 2011 at 02:07:57PM +0800, Jeremy Kerr wrote:
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, containing a set of clock operations. Different
> clock implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
> 
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
> 
> And a set of clock operations (defined per type of clock):
> 
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
> 
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
> 
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
> 
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/Kconfig  |    3 
>  drivers/clk/Makefile |    1 
>  drivers/clk/clk.c    |  134 +++++++++++++++++++++++++++++++
>  drivers/clk/clkdev.c |    5 +
>  include/linux/clk.h  |  184 ++++++++++++++++++++++++++++++++++++++++---
>  5 files changed, 318 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4168c88..6e3ae54 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -2,3 +2,6 @@
>  config CLKDEV_LOOKUP
>  	bool
>  	select HAVE_CLK
> +
> +config USE_COMMON_STRUCT_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..a1a06d3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..12e0daf
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,134 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk->ops->prepare)
> +		return 0;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (clk->prepare_count == 0)
> +		ret = clk->ops->prepare(clk);
> +
> +	if (!ret)
> +		clk->prepare_count++;
> +	mutex_unlock(&clk->prepare_lock);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	if (!clk->ops->unprepare)
> +		return;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (--clk->prepare_count == 0)
> +		clk->ops->unprepare(clk);
> +
> +	mutex_unlock(&clk->prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +int clk_enable(struct clk *clk)
> +{
> +	int ret = 0;
> +
Did we want to check for prepare_count > 0 here?  Russell's suggestion
was to do that without holding any lock.
(To make this a tad safer, you could use
ACCESS_ONCE(clk->enable_count)++ below. (Suggested by paulmck on irc.))

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-07  6:07   ` Jeremy Kerr
                     ` (2 preceding siblings ...)
  (?)
@ 2011-02-07  7:09   ` 
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-07  7:09 UTC (permalink / raw)
  To: linux-sh

On Mon, Feb 07, 2011 at 08:05:24AM +0100, Uwe Kleine-König wrote:
> On Mon, Feb 07, 2011 at 02:07:57PM +0800, Jeremy Kerr wrote:
> > We currently have ~21 definitions of struct clk in the ARM architecture,
> > each defined on a per-platform basis. This makes it difficult to define
> > platform- (or architecture-) independent clock sources without making
> > assumptions about struct clk, and impossible to compile two
> > platforms with different struct clks into a single image.
> > 
> > This change is an effort to unify struct clk where possible, by defining
> > a common struct clk, containing a set of clock operations. Different
> > clock implementations can set their own operations, and have a standard
> > interface for generic code. The callback interface is exposed to the
> > kernel proper, while the clock implementations only need to be seen by
> > the platform internals.
> > 
> > This allows us to share clock code among platforms, and makes it
> > possible to dynamically create clock devices in platform-independent
> > code.
> > 
> > Platforms can enable the generic struct clock through
> > CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> > consists of a common struct clk:
> > 
> > struct clk {
> > 	const struct clk_ops	*ops;
> > 	unsigned int		enable_count;
> > 	unsigned int		prepare_count;
> > 	spinlock_t		enable_lock;
> > 	struct mutex		prepare_lock;
> > };
> > 
> > And a set of clock operations (defined per type of clock):
> > 
> > struct clk_ops {
> > 	int             (*enable)(struct clk *);
> > 	void            (*disable)(struct clk *);
> > 	unsigned long   (*get_rate)(struct clk *);
> > 	[...]
> > };
> > 
> > To define a hardware-specific clock, machine code can "subclass" the
> > struct clock into a new struct (adding any device-specific data), and
> > provide a set of operations:
> > 
> > struct clk_foo {
> > 	struct clk	clk;
> > 	void __iomem	*some_register;
> > };
> > 
> > struct clk_ops clk_foo_ops = {
> > 	.get_rate = clk_foo_get_rate,
> > };
> > 
> > The common clock definitions are based on a development patch from Ben
> > Herrenschmidt <benh@kernel.crashing.org>.
> > 
> > Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> > 
> > ---
> >  drivers/clk/Kconfig  |    3 
> >  drivers/clk/Makefile |    1 
> >  drivers/clk/clk.c    |  134 +++++++++++++++++++++++++++++++
> >  drivers/clk/clkdev.c |    5 +
> >  include/linux/clk.h  |  184 ++++++++++++++++++++++++++++++++++++++++---
> >  5 files changed, 318 insertions(+), 9 deletions(-)
> > 
> > diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> > index 4168c88..6e3ae54 100644
> > --- a/drivers/clk/Kconfig
> > +++ b/drivers/clk/Kconfig
> > @@ -2,3 +2,6 @@
> >  config CLKDEV_LOOKUP
> >  	bool
> >  	select HAVE_CLK
> > +
> > +config USE_COMMON_STRUCT_CLK
> > +	bool
> > diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> > index 07613fa..a1a06d3 100644
> > --- a/drivers/clk/Makefile
> > +++ b/drivers/clk/Makefile
> > @@ -1,2 +1,3 @@
> >  
> >  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> > +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > new file mode 100644
> > index 0000000..12e0daf
> > --- /dev/null
> > +++ b/drivers/clk/clk.c
> > @@ -0,0 +1,134 @@
> > +/*
> > + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * Standard functionality for the common clock API.
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/module.h>
> > +
> > +int clk_prepare(struct clk *clk)
> > +{
> > +	int ret = 0;
> > +
> > +	if (!clk->ops->prepare)
> > +		return 0;
> > +
> > +	mutex_lock(&clk->prepare_lock);
> > +	if (clk->prepare_count = 0)
> > +		ret = clk->ops->prepare(clk);
> > +
> > +	if (!ret)
> > +		clk->prepare_count++;
> > +	mutex_unlock(&clk->prepare_lock);
> > +
> > +	return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(clk_prepare);
> > +
> > +void clk_unprepare(struct clk *clk)
> > +{
> > +	if (!clk->ops->unprepare)
> > +		return;
> > +
> > +	mutex_lock(&clk->prepare_lock);
> > +	if (--clk->prepare_count = 0)
> > +		clk->ops->unprepare(clk);
> > +
> > +	mutex_unlock(&clk->prepare_lock);
> > +}
> > +EXPORT_SYMBOL_GPL(clk_unprepare);
> > +
> > +int clk_enable(struct clk *clk)
> > +{
> > +	int ret = 0;
> > +
> Did we want to check for prepare_count > 0 here?  Russell's suggestion
> was to do that without holding any lock.
> (To make this a tad safer, you could use
> ACCESS_ONCE(clk->enable_count)++ below. (Suggested by paulmck on irc.))
s/enable_count/prepare_count/ of course.  And I saw I was to quick, you
added that check in patch 3.  Sorry

Uwe
-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC, PATCH 3/3] clk: add warnings for incorrect
  2011-02-07  6:07   ` Jeremy Kerr
  (?)
@ 2011-02-07  8:05     ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-07  8:05 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Jeremy,

On Mon, Feb 07, 2011 at 02:07:57PM +0800, Jeremy Kerr wrote:
> This change adds warnings to check for:
> 
>  1) enabling a clock that hasn't been prepared; and
> 
>  2) unpreparing a clock that is still enabled
> 
> While the correctness can't be guaranteed, these warnings should cover
> most situations.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/clk.c |    4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 51dbd33..2369959 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -35,6 +35,8 @@ void clk_unprepare(struct clk *clk)
>  	if (!clk->ops->unprepare)
>  		return;
>  
> +	WARN_ON(clk->enable_count);
> +
>  	mutex_lock(&clk->prepare_lock);
>  	if (--clk->prepare_count = 0)
>  		clk->ops->unprepare(clk);
> @@ -50,6 +52,8 @@ int clk_enable(struct clk *clk)
>  	if (!clk->ops->enable)
>  		return 0;
>  
> +	WARN_ON(clk->ops->prepare && clk->prepare_count);
> +
This implies the warning is only issued on clocks that have a prepare
callback.  If we want to enforce the new API the warning here shouldn't
depend on clk->ops->prepare.  (clk_prepare and clk_unprepare need to
be changed then to adapt the prepare_count even in the absence of
clk->ops->prepare.)

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-07  8:05     ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-07  8:05 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, Dima Zavin, Saravana Kannan, Ben Dooks, Russell King

Hello Jeremy,

On Mon, Feb 07, 2011 at 02:07:57PM +0800, Jeremy Kerr wrote:
> This change adds warnings to check for:
> 
>  1) enabling a clock that hasn't been prepared; and
> 
>  2) unpreparing a clock that is still enabled
> 
> While the correctness can't be guaranteed, these warnings should cover
> most situations.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/clk.c |    4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 51dbd33..2369959 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -35,6 +35,8 @@ void clk_unprepare(struct clk *clk)
>  	if (!clk->ops->unprepare)
>  		return;
>  
> +	WARN_ON(clk->enable_count);
> +
>  	mutex_lock(&clk->prepare_lock);
>  	if (--clk->prepare_count == 0)
>  		clk->ops->unprepare(clk);
> @@ -50,6 +52,8 @@ int clk_enable(struct clk *clk)
>  	if (!clk->ops->enable)
>  		return 0;
>  
> +	WARN_ON(clk->ops->prepare && clk->prepare_count);
> +
This implies the warning is only issued on clocks that have a prepare
callback.  If we want to enforce the new API the warning here shouldn't
depend on clk->ops->prepare.  (clk_prepare and clk_unprepare need to
be changed then to adapt the prepare_count even in the absence of
clk->ops->prepare.)

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-07  8:05     ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-07  8:05 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Jeremy,

On Mon, Feb 07, 2011 at 02:07:57PM +0800, Jeremy Kerr wrote:
> This change adds warnings to check for:
> 
>  1) enabling a clock that hasn't been prepared; and
> 
>  2) unpreparing a clock that is still enabled
> 
> While the correctness can't be guaranteed, these warnings should cover
> most situations.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/clk.c |    4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 51dbd33..2369959 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -35,6 +35,8 @@ void clk_unprepare(struct clk *clk)
>  	if (!clk->ops->unprepare)
>  		return;
>  
> +	WARN_ON(clk->enable_count);
> +
>  	mutex_lock(&clk->prepare_lock);
>  	if (--clk->prepare_count == 0)
>  		clk->ops->unprepare(clk);
> @@ -50,6 +52,8 @@ int clk_enable(struct clk *clk)
>  	if (!clk->ops->enable)
>  		return 0;
>  
> +	WARN_ON(clk->ops->prepare && clk->prepare_count);
> +
This implies the warning is only issued on clocks that have a prepare
callback.  If we want to enforce the new API the warning here shouldn't
depend on clk->ops->prepare.  (clk_prepare and clk_unprepare need to
be changed then to adapt the prepare_count even in the absence of
clk->ops->prepare.)

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-07  6:07   ` Jeremy Kerr
  (?)
@ 2011-02-07  8:08     ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-07  8:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 07, 2011 at 02:07:57PM +0800, Jeremy Kerr wrote:
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, containing a set of clock operations. Different
> clock implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
> 
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
> 
> And a set of clock operations (defined per type of clock):
> 
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
> 
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
> 
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
> 
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/Kconfig  |    3 
>  drivers/clk/Makefile |    1 
>  drivers/clk/clk.c    |  134 +++++++++++++++++++++++++++++++
>  drivers/clk/clkdev.c |    5 +
>  include/linux/clk.h  |  184 ++++++++++++++++++++++++++++++++++++++++---
>  5 files changed, 318 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4168c88..6e3ae54 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -2,3 +2,6 @@
>  config CLKDEV_LOOKUP
>  	bool
>  	select HAVE_CLK
> +
> +config USE_COMMON_STRUCT_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..a1a06d3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..12e0daf
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,134 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk->ops->prepare)
> +		return 0;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (clk->prepare_count = 0)
> +		ret = clk->ops->prepare(clk);
> +
> +	if (!ret)
> +		clk->prepare_count++;
> +	mutex_unlock(&clk->prepare_lock);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	if (!clk->ops->unprepare)
> +		return;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (--clk->prepare_count = 0)
> +		clk->ops->unprepare(clk);
> +
> +	mutex_unlock(&clk->prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +int clk_enable(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk->ops->enable)
> +		return 0;
> +
> +	spin_lock(&clk->enable_lock);
> +	if (!clk->enable_count)
> +		ret = clk->ops->enable(clk);
> +
> +	if (!ret)
> +		clk->enable_count++;
> +	spin_unlock(&clk->enable_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +void clk_disable(struct clk *clk)
> +{
> +	if (!clk->ops->disable)
> +		return;
> +
> +	spin_lock(&clk->enable_lock);
> +
> +	WARN_ON(!clk->enable_count);
> +
> +	if (!--clk->enable_count)
> +		clk->ops->disable(clk);
> +
> +	spin_unlock(&clk->enable_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	if (clk->ops->get_rate)
> +		return clk->ops->get_rate(clk);
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +int __clk_get(struct clk *clk)
> +{
> +	if (clk->ops->get)
> +		return clk->ops->get(clk);
> +	return 1;
> +}
> +EXPORT_SYMBOL_GPL(__clk_get);
> +
> +void clk_put(struct clk *clk)
> +{
> +	if (clk->ops->put)
> +		clk->ops->put(clk);
> +}
> +EXPORT_SYMBOL_GPL(clk_put);
> +
> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->round_rate)
> +		return clk->ops->round_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->set_rate)
> +		return clk->ops->set_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	if (clk->ops->set_parent)
> +		return clk->ops->set_parent(clk, parent);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	if (clk->ops->get_parent)
> +		return clk->ops->get_parent(clk);
> +	return ERR_PTR(-ENOSYS);
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> index 0fc0a79..17619c7 100644
> --- a/drivers/clk/clkdev.c
> +++ b/drivers/clk/clkdev.c
> @@ -84,12 +84,17 @@ struct clk *clk_get(struct device *dev, const char *con_id)
>  }
>  EXPORT_SYMBOL(clk_get);
>  
> +#ifndef CONFIG_USE_COMMON_STRUCT_CLK
> +/* For the common struct clk case, clk_put is provided by clk.c */
> +
>  void clk_put(struct clk *clk)
>  {
>  	__clk_put(clk);
>  }
>  EXPORT_SYMBOL(clk_put);
>  
> +#endif
> +
>  void clkdev_add(struct clk_lookup *cl)
>  {
>  	mutex_lock(&clocks_mutex);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..e081ca1 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@
>   *
>   *  Copyright (C) 2004 ARM Limited.
>   *  Written by Deep Blue Solutions Limited.
> + *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
> @@ -11,18 +12,189 @@
>  #ifndef __LINUX_CLK_H
>  #define __LINUX_CLK_H
>  
> +#include <linux/err.h>
> +#include <linux/mutex.h>
> +#include <linux/spinlock.h>
> +
>  struct device;
>  
> -/*
> - * The base API.
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> +
> +/* If we're using the common struct clk, we define the base clk object here */
> +
> +/**
> + * struct clk - hardware independent clock structure
> + * @ops:		implementation-specific ops for this clock
> + * @enable_count:	count of clk_enable() calls active on this clock
> + * @flags:		platform-independent flags
> + * @lock:		lock for enable/disable or other HW-specific ops
> + *
> + * The base clock object, used by drivers for hardware-independent manipulation
> + * of clock lines. This will be 'subclassed' by device-specific implementations,
> + * which add device-specific data to struct clk. For example:
> + *
> + *  struct clk_foo {
> + *      struct clk;
> + *      [device specific fields]
> + *  };
> + *
> + * The clock driver code will manage the device-specific data, and pass
> + * clk_foo.clk to the common clock code. The clock driver will be called
> + * through the @ops callbacks.
> + *
> + * The @lock member provides either a spinlock or a mutex to protect (at least)
> + * @enable_count. The type of lock used will depend on @flags; if CLK_ATOMIC is
> + * set, then the core clock code will use a spinlock, otherwise a mutex. This
> + * lock will be acquired during clk_enable and clk_disable, so for atomic
> + * clocks, these ops callbacks must not sleep.
> + *
> + * The choice of atomic or non-atomic clock depends on how the clock is enabled.
> + * Typically, you'll want to use a non-atomic clock. For clocks that need to be
> + * enabled/disabled in interrupt context, use CLK_ATOMIC. Note that atomic
> + * clocks with parents will typically cascade enable/disable operations to
> + * their parent, so the parent of an atomic clock *must* be atomic too.
>   */
This comment needs a general overhaul.

(I had this comment already in my first mail, but I must have deleted it
when removing the unrealted quotes.)

> +struct clk {
> +	const struct clk_ops	*ops;
> +	unsigned int		enable_count;
> +	unsigned int		prepare_count;
> +	spinlock_t		enable_lock;
> +	struct mutex		prepare_lock;
> +};

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-07  8:08     ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-07  8:08 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, Dima Zavin, Saravana Kannan, Ben Dooks, Russell King

On Mon, Feb 07, 2011 at 02:07:57PM +0800, Jeremy Kerr wrote:
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, containing a set of clock operations. Different
> clock implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
> 
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
> 
> And a set of clock operations (defined per type of clock):
> 
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
> 
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
> 
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
> 
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/Kconfig  |    3 
>  drivers/clk/Makefile |    1 
>  drivers/clk/clk.c    |  134 +++++++++++++++++++++++++++++++
>  drivers/clk/clkdev.c |    5 +
>  include/linux/clk.h  |  184 ++++++++++++++++++++++++++++++++++++++++---
>  5 files changed, 318 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4168c88..6e3ae54 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -2,3 +2,6 @@
>  config CLKDEV_LOOKUP
>  	bool
>  	select HAVE_CLK
> +
> +config USE_COMMON_STRUCT_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..a1a06d3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..12e0daf
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,134 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk->ops->prepare)
> +		return 0;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (clk->prepare_count == 0)
> +		ret = clk->ops->prepare(clk);
> +
> +	if (!ret)
> +		clk->prepare_count++;
> +	mutex_unlock(&clk->prepare_lock);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	if (!clk->ops->unprepare)
> +		return;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (--clk->prepare_count == 0)
> +		clk->ops->unprepare(clk);
> +
> +	mutex_unlock(&clk->prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +int clk_enable(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk->ops->enable)
> +		return 0;
> +
> +	spin_lock(&clk->enable_lock);
> +	if (!clk->enable_count)
> +		ret = clk->ops->enable(clk);
> +
> +	if (!ret)
> +		clk->enable_count++;
> +	spin_unlock(&clk->enable_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +void clk_disable(struct clk *clk)
> +{
> +	if (!clk->ops->disable)
> +		return;
> +
> +	spin_lock(&clk->enable_lock);
> +
> +	WARN_ON(!clk->enable_count);
> +
> +	if (!--clk->enable_count)
> +		clk->ops->disable(clk);
> +
> +	spin_unlock(&clk->enable_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	if (clk->ops->get_rate)
> +		return clk->ops->get_rate(clk);
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +int __clk_get(struct clk *clk)
> +{
> +	if (clk->ops->get)
> +		return clk->ops->get(clk);
> +	return 1;
> +}
> +EXPORT_SYMBOL_GPL(__clk_get);
> +
> +void clk_put(struct clk *clk)
> +{
> +	if (clk->ops->put)
> +		clk->ops->put(clk);
> +}
> +EXPORT_SYMBOL_GPL(clk_put);
> +
> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->round_rate)
> +		return clk->ops->round_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->set_rate)
> +		return clk->ops->set_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	if (clk->ops->set_parent)
> +		return clk->ops->set_parent(clk, parent);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	if (clk->ops->get_parent)
> +		return clk->ops->get_parent(clk);
> +	return ERR_PTR(-ENOSYS);
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> index 0fc0a79..17619c7 100644
> --- a/drivers/clk/clkdev.c
> +++ b/drivers/clk/clkdev.c
> @@ -84,12 +84,17 @@ struct clk *clk_get(struct device *dev, const char *con_id)
>  }
>  EXPORT_SYMBOL(clk_get);
>  
> +#ifndef CONFIG_USE_COMMON_STRUCT_CLK
> +/* For the common struct clk case, clk_put is provided by clk.c */
> +
>  void clk_put(struct clk *clk)
>  {
>  	__clk_put(clk);
>  }
>  EXPORT_SYMBOL(clk_put);
>  
> +#endif
> +
>  void clkdev_add(struct clk_lookup *cl)
>  {
>  	mutex_lock(&clocks_mutex);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..e081ca1 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@
>   *
>   *  Copyright (C) 2004 ARM Limited.
>   *  Written by Deep Blue Solutions Limited.
> + *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
> @@ -11,18 +12,189 @@
>  #ifndef __LINUX_CLK_H
>  #define __LINUX_CLK_H
>  
> +#include <linux/err.h>
> +#include <linux/mutex.h>
> +#include <linux/spinlock.h>
> +
>  struct device;
>  
> -/*
> - * The base API.
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> +
> +/* If we're using the common struct clk, we define the base clk object here */
> +
> +/**
> + * struct clk - hardware independent clock structure
> + * @ops:		implementation-specific ops for this clock
> + * @enable_count:	count of clk_enable() calls active on this clock
> + * @flags:		platform-independent flags
> + * @lock:		lock for enable/disable or other HW-specific ops
> + *
> + * The base clock object, used by drivers for hardware-independent manipulation
> + * of clock lines. This will be 'subclassed' by device-specific implementations,
> + * which add device-specific data to struct clk. For example:
> + *
> + *  struct clk_foo {
> + *      struct clk;
> + *      [device specific fields]
> + *  };
> + *
> + * The clock driver code will manage the device-specific data, and pass
> + * clk_foo.clk to the common clock code. The clock driver will be called
> + * through the @ops callbacks.
> + *
> + * The @lock member provides either a spinlock or a mutex to protect (at least)
> + * @enable_count. The type of lock used will depend on @flags; if CLK_ATOMIC is
> + * set, then the core clock code will use a spinlock, otherwise a mutex. This
> + * lock will be acquired during clk_enable and clk_disable, so for atomic
> + * clocks, these ops callbacks must not sleep.
> + *
> + * The choice of atomic or non-atomic clock depends on how the clock is enabled.
> + * Typically, you'll want to use a non-atomic clock. For clocks that need to be
> + * enabled/disabled in interrupt context, use CLK_ATOMIC. Note that atomic
> + * clocks with parents will typically cascade enable/disable operations to
> + * their parent, so the parent of an atomic clock *must* be atomic too.
>   */
This comment needs a general overhaul.

(I had this comment already in my first mail, but I must have deleted it
when removing the unrealted quotes.)

> +struct clk {
> +	const struct clk_ops	*ops;
> +	unsigned int		enable_count;
> +	unsigned int		prepare_count;
> +	spinlock_t		enable_lock;
> +	struct mutex		prepare_lock;
> +};

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-07  8:08     ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-07  8:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 07, 2011 at 02:07:57PM +0800, Jeremy Kerr wrote:
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, containing a set of clock operations. Different
> clock implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
> 
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
> 
> And a set of clock operations (defined per type of clock):
> 
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
> 
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
> 
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
> 
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/Kconfig  |    3 
>  drivers/clk/Makefile |    1 
>  drivers/clk/clk.c    |  134 +++++++++++++++++++++++++++++++
>  drivers/clk/clkdev.c |    5 +
>  include/linux/clk.h  |  184 ++++++++++++++++++++++++++++++++++++++++---
>  5 files changed, 318 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4168c88..6e3ae54 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -2,3 +2,6 @@
>  config CLKDEV_LOOKUP
>  	bool
>  	select HAVE_CLK
> +
> +config USE_COMMON_STRUCT_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..a1a06d3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..12e0daf
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,134 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk->ops->prepare)
> +		return 0;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (clk->prepare_count == 0)
> +		ret = clk->ops->prepare(clk);
> +
> +	if (!ret)
> +		clk->prepare_count++;
> +	mutex_unlock(&clk->prepare_lock);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	if (!clk->ops->unprepare)
> +		return;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (--clk->prepare_count == 0)
> +		clk->ops->unprepare(clk);
> +
> +	mutex_unlock(&clk->prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +int clk_enable(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk->ops->enable)
> +		return 0;
> +
> +	spin_lock(&clk->enable_lock);
> +	if (!clk->enable_count)
> +		ret = clk->ops->enable(clk);
> +
> +	if (!ret)
> +		clk->enable_count++;
> +	spin_unlock(&clk->enable_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +void clk_disable(struct clk *clk)
> +{
> +	if (!clk->ops->disable)
> +		return;
> +
> +	spin_lock(&clk->enable_lock);
> +
> +	WARN_ON(!clk->enable_count);
> +
> +	if (!--clk->enable_count)
> +		clk->ops->disable(clk);
> +
> +	spin_unlock(&clk->enable_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	if (clk->ops->get_rate)
> +		return clk->ops->get_rate(clk);
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +int __clk_get(struct clk *clk)
> +{
> +	if (clk->ops->get)
> +		return clk->ops->get(clk);
> +	return 1;
> +}
> +EXPORT_SYMBOL_GPL(__clk_get);
> +
> +void clk_put(struct clk *clk)
> +{
> +	if (clk->ops->put)
> +		clk->ops->put(clk);
> +}
> +EXPORT_SYMBOL_GPL(clk_put);
> +
> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->round_rate)
> +		return clk->ops->round_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->set_rate)
> +		return clk->ops->set_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	if (clk->ops->set_parent)
> +		return clk->ops->set_parent(clk, parent);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	if (clk->ops->get_parent)
> +		return clk->ops->get_parent(clk);
> +	return ERR_PTR(-ENOSYS);
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> index 0fc0a79..17619c7 100644
> --- a/drivers/clk/clkdev.c
> +++ b/drivers/clk/clkdev.c
> @@ -84,12 +84,17 @@ struct clk *clk_get(struct device *dev, const char *con_id)
>  }
>  EXPORT_SYMBOL(clk_get);
>  
> +#ifndef CONFIG_USE_COMMON_STRUCT_CLK
> +/* For the common struct clk case, clk_put is provided by clk.c */
> +
>  void clk_put(struct clk *clk)
>  {
>  	__clk_put(clk);
>  }
>  EXPORT_SYMBOL(clk_put);
>  
> +#endif
> +
>  void clkdev_add(struct clk_lookup *cl)
>  {
>  	mutex_lock(&clocks_mutex);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..e081ca1 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@
>   *
>   *  Copyright (C) 2004 ARM Limited.
>   *  Written by Deep Blue Solutions Limited.
> + *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
> @@ -11,18 +12,189 @@
>  #ifndef __LINUX_CLK_H
>  #define __LINUX_CLK_H
>  
> +#include <linux/err.h>
> +#include <linux/mutex.h>
> +#include <linux/spinlock.h>
> +
>  struct device;
>  
> -/*
> - * The base API.
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> +
> +/* If we're using the common struct clk, we define the base clk object here */
> +
> +/**
> + * struct clk - hardware independent clock structure
> + * @ops:		implementation-specific ops for this clock
> + * @enable_count:	count of clk_enable() calls active on this clock
> + * @flags:		platform-independent flags
> + * @lock:		lock for enable/disable or other HW-specific ops
> + *
> + * The base clock object, used by drivers for hardware-independent manipulation
> + * of clock lines. This will be 'subclassed' by device-specific implementations,
> + * which add device-specific data to struct clk. For example:
> + *
> + *  struct clk_foo {
> + *      struct clk;
> + *      [device specific fields]
> + *  };
> + *
> + * The clock driver code will manage the device-specific data, and pass
> + * clk_foo.clk to the common clock code. The clock driver will be called
> + * through the @ops callbacks.
> + *
> + * The @lock member provides either a spinlock or a mutex to protect (at least)
> + * @enable_count. The type of lock used will depend on @flags; if CLK_ATOMIC is
> + * set, then the core clock code will use a spinlock, otherwise a mutex. This
> + * lock will be acquired during clk_enable and clk_disable, so for atomic
> + * clocks, these ops callbacks must not sleep.
> + *
> + * The choice of atomic or non-atomic clock depends on how the clock is enabled.
> + * Typically, you'll want to use a non-atomic clock. For clocks that need to be
> + * enabled/disabled in interrupt context, use CLK_ATOMIC. Note that atomic
> + * clocks with parents will typically cascade enable/disable operations to
> + * their parent, so the parent of an atomic clock *must* be atomic too.
>   */
This comment needs a general overhaul.

(I had this comment already in my first mail, but I must have deleted it
when removing the unrealted quotes.)

> +struct clk {
> +	const struct clk_ops	*ops;
> +	unsigned int		enable_count;
> +	unsigned int		prepare_count;
> +	spinlock_t		enable_lock;
> +	struct mutex		prepare_lock;
> +};

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
  2011-02-07  8:05     ` Uwe Kleine-König
  (?)
@ 2011-02-07  8:08       ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  8:08 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Uwe,

> This implies the warning is only issued on clocks that have a prepare
> callback.  If we want to enforce the new API the warning here shouldn't
> depend on clk->ops->prepare.  (clk_prepare and clk_unprepare need to
> be changed then to adapt the prepare_count even in the absence of
> clk->ops->prepare.)

Yeah, it's a decision about either adding a small cost to all clk_prepare()s 
(ie, adding cost when there is no prepare callback), or checking for the 
correct prepare/enable semantics for all clocks (even when it doesn't matter 
for that particular clock). I chose the first as more important, but happy to 
go either way here.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-07  8:08       ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  8:08 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, Dima Zavin, Saravana Kannan, Ben Dooks, Russell King

Hi Uwe,

> This implies the warning is only issued on clocks that have a prepare
> callback.  If we want to enforce the new API the warning here shouldn't
> depend on clk->ops->prepare.  (clk_prepare and clk_unprepare need to
> be changed then to adapt the prepare_count even in the absence of
> clk->ops->prepare.)

Yeah, it's a decision about either adding a small cost to all clk_prepare()s 
(ie, adding cost when there is no prepare callback), or checking for the 
correct prepare/enable semantics for all clocks (even when it doesn't matter 
for that particular clock). I chose the first as more important, but happy to 
go either way here.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-07  8:08       ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  8:08 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Uwe,

> This implies the warning is only issued on clocks that have a prepare
> callback.  If we want to enforce the new API the warning here shouldn't
> depend on clk->ops->prepare.  (clk_prepare and clk_unprepare need to
> be changed then to adapt the prepare_count even in the absence of
> clk->ops->prepare.)

Yeah, it's a decision about either adding a small cost to all clk_prepare()s 
(ie, adding cost when there is no prepare callback), or checking for the 
correct prepare/enable semantics for all clocks (even when it doesn't matter 
for that particular clock). I chose the first as more important, but happy to 
go either way here.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
  2011-02-07  6:07   ` Jeremy Kerr
                     ` (4 preceding siblings ...)
  (?)
@ 2011-02-07  8:21   ` Dima Zavin
  2011-02-07  8:22       ` Jeremy Kerr
  -1 siblings, 1 reply; 383+ messages in thread
From: Dima Zavin @ 2011-02-07  8:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Feb 6, 2011 10:08 PM, "Jeremy Kerr" <jeremy.kerr@canonical.com> wrote:
>
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
>
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, containing a set of clock operations. Different
> clock implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
>
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
>
> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
>
> struct clk {
>        const struct clk_ops    *ops;
>        unsigned int            enable_count;
>        unsigned int            prepare_count;
>        spinlock_t              enable_lock;
>        struct mutex            prepare_lock;
> };
>
> And a set of clock operations (defined per type of clock):
>
> struct clk_ops {
>        int             (*enable)(struct clk *);
>        void            (*disable)(struct clk *);
>        unsigned long   (*get_rate)(struct clk *);
>        [...]
> };
>
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
>
> struct clk_foo {
>        struct clk      clk;
>        void __iomem    *some_register;
> };
>
> struct clk_ops clk_foo_ops = {
>        .get_rate = clk_foo_get_rate,
> };
>
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
>
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
>
> ---
>  drivers/clk/Kconfig  |    3
>  drivers/clk/Makefile |    1
>  drivers/clk/clk.c    |  134 +++++++++++++++++++++++++++++++
>  drivers/clk/clkdev.c |    5 +
>  include/linux/clk.h  |  184 ++++++++++++++++++++++++++++++++++++++++---
>  5 files changed, 318 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4168c88..6e3ae54 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -2,3 +2,6 @@
>  config CLKDEV_LOOKUP
>        bool
>        select HAVE_CLK
> +
> +config USE_COMMON_STRUCT_CLK
> +       bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..a1a06d3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>
>  obj-$(CONFIG_CLKDEV_LOOKUP)    += clkdev.o
> +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..12e0daf
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,134 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +
> +int clk_prepare(struct clk *clk)
> +{
> +       int ret = 0;
> +
> +       if (!clk->ops->prepare)
> +               return 0;
> +
> +       mutex_lock(&clk->prepare_lock);
> +       if (clk->prepare_count == 0)
> +               ret = clk->ops->prepare(clk);
> +
> +       if (!ret)
> +               clk->prepare_count++;
> +       mutex_unlock(&clk->prepare_lock);
> +
> +       return 0;

return ret;

> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +       if (!clk->ops->unprepare)
> +               return;
> +
> +       mutex_lock(&clk->prepare_lock);
> +       if (--clk->prepare_count == 0)
> +               clk->ops->unprepare(clk);
> +
> +       mutex_unlock(&clk->prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +int clk_enable(struct clk *clk)
> +{
> +       int ret = 0;
> +
> +       if (!clk->ops->enable)
> +               return 0;
> +
> +       spin_lock(&clk->enable_lock);
> +       if (!clk->enable_count)
> +               ret = clk->ops->enable(clk);
> +
> +       if (!ret)
> +               clk->enable_count++;
> +       spin_unlock(&clk->enable_lock);
> +
> +       return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +void clk_disable(struct clk *clk)
> +{
> +       if (!clk->ops->disable)
> +               return;
> +
> +       spin_lock(&clk->enable_lock);
> +
> +       WARN_ON(!clk->enable_count);
> +
> +       if (!--clk->enable_count)
> +               clk->ops->disable(clk);
> +
> +       spin_unlock(&clk->enable_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +       if (clk->ops->get_rate)
> +               return clk->ops->get_rate(clk);
> +       return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +int __clk_get(struct clk *clk)
> +{
> +       if (clk->ops->get)
> +               return clk->ops->get(clk);
> +       return 1;
> +}
> +EXPORT_SYMBOL_GPL(__clk_get);
> +
> +void clk_put(struct clk *clk)
> +{
> +       if (clk->ops->put)
> +               clk->ops->put(clk);
> +}
> +EXPORT_SYMBOL_GPL(clk_put);
> +
> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +       if (clk->ops->round_rate)
> +               return clk->ops->round_rate(clk, rate);
> +       return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +       if (clk->ops->set_rate)
> +               return clk->ops->set_rate(clk, rate);
> +       return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +       if (clk->ops->set_parent)
> +               return clk->ops->set_parent(clk, parent);
> +       return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +       if (clk->ops->get_parent)
> +               return clk->ops->get_parent(clk);
> +       return ERR_PTR(-ENOSYS);
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> index 0fc0a79..17619c7 100644
> --- a/drivers/clk/clkdev.c
> +++ b/drivers/clk/clkdev.c
> @@ -84,12 +84,17 @@ struct clk *clk_get(struct device *dev, const char
*con_id)
>  }
>  EXPORT_SYMBOL(clk_get);
>
> +#ifndef CONFIG_USE_COMMON_STRUCT_CLK
> +/* For the common struct clk case, clk_put is provided by clk.c */
> +
>  void clk_put(struct clk *clk)
>  {
>        __clk_put(clk);
>  }
>  EXPORT_SYMBOL(clk_put);
>
> +#endif
> +
>  void clkdev_add(struct clk_lookup *cl)
>  {
>        mutex_lock(&clocks_mutex);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..e081ca1 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@
>  *
>  *  Copyright (C) 2004 ARM Limited.
>  *  Written by Deep Blue Solutions Limited.
> + *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
>  *
>  * This program is free software; you can redistribute it and/or modify
>  * it under the terms of the GNU General Public License version 2 as
> @@ -11,18 +12,189 @@
>  #ifndef __LINUX_CLK_H
>  #define __LINUX_CLK_H
>
> +#include <linux/err.h>
> +#include <linux/mutex.h>
> +#include <linux/spinlock.h>
> +
>  struct device;
>
> -/*
> - * The base API.
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> +
> +/* If we're using the common struct clk, we define the base clk object
here */
> +
> +/**
> + * struct clk - hardware independent clock structure
> + * @ops:               implementation-specific ops for this clock
> + * @enable_count:      count of clk_enable() calls active on this clock
> + * @flags:             platform-independent flags
> + * @lock:              lock for enable/disable or other HW-specific ops
> + *
> + * The base clock object, used by drivers for hardware-independent
manipulation
> + * of clock lines. This will be 'subclassed' by device-specific
implementations,
> + * which add device-specific data to struct clk. For example:
> + *
> + *  struct clk_foo {
> + *      struct clk;
> + *      [device specific fields]
> + *  };
> + *
> + * The clock driver code will manage the device-specific data, and pass
> + * clk_foo.clk to the common clock code. The clock driver will be called
> + * through the @ops callbacks.
> + *
> + * The @lock member provides either a spinlock or a mutex to protect (at
least)
> + * @enable_count. The type of lock used will depend on @flags; if
CLK_ATOMIC is
> + * set, then the core clock code will use a spinlock, otherwise a mutex.
This
> + * lock will be acquired during clk_enable and clk_disable, so for atomic
> + * clocks, these ops callbacks must not sleep.
> + *
> + * The choice of atomic or non-atomic clock depends on how the clock is
enabled.
> + * Typically, you'll want to use a non-atomic clock. For clocks that need
to be
> + * enabled/disabled in interrupt context, use CLK_ATOMIC. Note that
atomic
> + * clocks with parents will typically cascade enable/disable operations
to
> + * their parent, so the parent of an atomic clock *must* be atomic too.
>  */
> +struct clk {
> +       const struct clk_ops    *ops;
> +       unsigned int            enable_count;
> +       unsigned int            prepare_count;
> +       spinlock_t              enable_lock;
> +       struct mutex            prepare_lock;
> +};
> +
> +/* static initialiser for non-atomic clocks */
> +#define INIT_CLK(name, o) {                                            \
> +       .ops            = &o,                                           \
> +       .enable_count   = 0,                                            \
> +       .prepare_count  = 0,                                            \
> +       .enable_lock    = __SPIN_LOCK_UNLOCKED(name.enable_lock),       \
> +       .prepare_lock   = __MUTEX_INITIALIZER(name.prepare_lock),       \
> +}
>
> +/**
> + * struct clk_ops -  Callback operations for clocks; these are to be
provided
> + * by the clock implementation, and will be called by drivers through the
clk_*
> + * API.
> + *
> + * @prepare:   Prepare the clock for enabling. This must not return until
> + *             the clock is fully prepared, and it's safe to call
clk_enable.
> + *             This callback is intended to allow clock implementations
to
> + *             do any initialisation that may block. Called with
> + *             clk->prepare_lock held.
> + *
> + * @unprepare: Release the clock from its prepared state. This will
typically
> + *             undo any work done in the @prepare callback. Called with
> + *             clk->prepare_lock held.
> + *
> + * @enable:    Enable the clock atomically. This must not return until
the
> + *             clock is generating a valid clock signal, usable by
consumer
> + *             devices. Called with clk->enable_lock held.
> + *
> + * @disable:   Disable the clock atomically. Called with clk->enable_lock
held.
> + *
> + * @get:       Called by the core clock code when a device driver
acquires a
> + *             clock via clk_get(). Optional.
> + *
> + * @put:       Called by the core clock code when a devices driver
releases a
> + *             clock via clk_put(). Optional.
> + *
> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> + * implementations to split any work between atomic (enable) and
sleepable
> + * (prepare) contexts.  If a clock requires blocking code to be turned
on, this
> + * should be done in clk_prepare. Switching that will not block should be
done
> + * in clk_enable.
> + *
> + * Typically, drivers will call clk_prepare when a clock may be needed
later
> + * (eg. when a device is opened), and clk_enable when the clock is
actually
> + * required (eg. from an interrupt).
> + *
> + * For other callbacks, see the corresponding clk_* functions. Parameters
and
> + * return values are passed directly from/to these API functions, or
> + * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the
callback
> + * is NULL, see kernel/clk.c for implementation details. All are
optional.
> + */
> +struct clk_ops {
> +       int             (*prepare)(struct clk *);
> +       void            (*unprepare)(struct clk *);
> +       int             (*enable)(struct clk *);
> +       void            (*disable)(struct clk *);
> +       int             (*get)(struct clk *);
> +       void            (*put)(struct clk *);
> +       unsigned long   (*get_rate)(struct clk *);
> +       long            (*round_rate)(struct clk *, unsigned long);
> +       int             (*set_rate)(struct clk *, unsigned long);
> +       int             (*set_parent)(struct clk *, struct clk *);
> +       struct clk *    (*get_parent)(struct clk *);
> +};
> +
> +/**
> + * __clk_get - update clock-specific refcounter
> + *
> + * @clk: The clock to refcount
> + *
> + * Before a clock is returned from clk_get, this function should be
called
> + * to update any clock-specific refcounting.
> + *
> + * Returns non-zero on success, zero on failure.
> + *
> + * Drivers should not need this function; it is only needed by the
> + * arch-specific clk_get() implementations.
> + */
> +int __clk_get(struct clk *clk);
> +
> +/**
> + * clk_prepare - prepare clock for atomic enabling.
> + *
> + * @clk: The clock to prepare
> + *
> + * Do any blocking initialisation on @clk, allowing the clock to be later
> + * enabled atomically (via clk_enable). This function may sleep.
> + */
> +int clk_prepare(struct clk *clk);
> +
> +/**
> + * clk_unprepare - release clock from prepared state
> + *
> + * @clk: The clock to release
> + *
> + * Do any (possbly blocking) cleanup on clk. This function may sleep.
> + */
> +void clk_unprepare(struct clk *clk);
> +
> +/**
> + * clk_common_init - initialise a clock for driver usage
> + *
> + * @clk: The clock to initialise
> + *
> + * Used for runtime intialization of clocks; you don't need to call this
> + * if your clock has been (statically) initialized with INIT_CLK.
> + */
> +static inline void clk_common_init(struct clk *clk)
> +{
> +       clk->enable_count = clk->prepare_count = 0;
> +       spin_lock_init(&clk->enable_lock);
> +       mutex_init(&clk->prepare_lock);
> +}
> +
> +#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
>
>  /*
> - * struct clk - an machine class defined object / cookie.
> + * Global clock object, actual structure is declared per-machine
>  */
>  struct clk;
>
> +static inline void clk_common_init(struct clk *clk) { }
> +
> +/*
> + * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
> + * requirements for clk_enable/clk_disable, so the prepare and unprepare
> + * functions are no-ops
> + */
> +int clk_prepare(struct clk *clk) { return 0; }
> +void clk_unprepare(struct clk *clk) { }
> +
> +#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
> +
>  /**
>  * clk_get - lookup and obtain a reference to a clock producer.
>  * @dev: device for clock "consumer"
> @@ -83,12 +255,6 @@ unsigned long clk_get_rate(struct clk *clk);
>  */
>  void clk_put(struct clk *clk);
>
> -
> -/*
> - * The remaining APIs are optional for machine class support.
> - */
> -
> -
>  /**
>  * clk_round_rate - adjust a rate to the exact rate a clock can provide
>  * @clk: clock source
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110207/fe46bca5/attachment-0001.html>

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-07  8:21   ` Dima Zavin
  2011-02-07  8:22       ` Jeremy Kerr
@ 2011-02-07  8:22       ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  8:22 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Dima,

> > +int clk_prepare(struct clk *clk)
> > +{
> > +       int ret = 0;
> > +
> > +       if (!clk->ops->prepare)
> > +               return 0;
> > +
> > +       mutex_lock(&clk->prepare_lock);
> > +       if (clk->prepare_count = 0)
> > +               ret = clk->ops->prepare(clk);
> > +
> > +       if (!ret)
> > +               clk->prepare_count++;
> > +       mutex_unlock(&clk->prepare_lock);
> > +
> > +       return 0;
> 
> return ret;

Good catch, thanks.


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-07  8:22       ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  8:22 UTC (permalink / raw)
  To: Dima Zavin
  Cc: Ben Dooks, Russell King, Vincent Guittot, Ben Herrenschmidt,
	Paul Mundt, Nicolas Pitre, Lorenzo Pieralisi,
	Uwe Kleine-König, linux-arm-kernel, Saravana Kannan,
	Sascha Hauer, linux-sh, linux-kernel

Hi Dima,

> > +int clk_prepare(struct clk *clk)
> > +{
> > +       int ret = 0;
> > +
> > +       if (!clk->ops->prepare)
> > +               return 0;
> > +
> > +       mutex_lock(&clk->prepare_lock);
> > +       if (clk->prepare_count == 0)
> > +               ret = clk->ops->prepare(clk);
> > +
> > +       if (!ret)
> > +               clk->prepare_count++;
> > +       mutex_unlock(&clk->prepare_lock);
> > +
> > +       return 0;
> 
> return ret;

Good catch, thanks.


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-07  8:22       ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-07  8:22 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Dima,

> > +int clk_prepare(struct clk *clk)
> > +{
> > +       int ret = 0;
> > +
> > +       if (!clk->ops->prepare)
> > +               return 0;
> > +
> > +       mutex_lock(&clk->prepare_lock);
> > +       if (clk->prepare_count == 0)
> > +               ret = clk->ops->prepare(clk);
> > +
> > +       if (!ret)
> > +               clk->prepare_count++;
> > +       mutex_unlock(&clk->prepare_lock);
> > +
> > +       return 0;
> 
> return ret;

Good catch, thanks.


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare
  2011-02-07  8:08       ` Jeremy Kerr
  (?)
@ 2011-02-07 14:24         ` Nicolas Pitre
  -1 siblings, 0 replies; 383+ messages in thread
From: Nicolas Pitre @ 2011-02-07 14:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 7 Feb 2011, Jeremy Kerr wrote:

> Hi Uwe,
> 
> > This implies the warning is only issued on clocks that have a prepare
> > callback.  If we want to enforce the new API the warning here shouldn't
> > depend on clk->ops->prepare.  (clk_prepare and clk_unprepare need to
> > be changed then to adapt the prepare_count even in the absence of
> > clk->ops->prepare.)
> 
> Yeah, it's a decision about either adding a small cost to all clk_prepare()s 
> (ie, adding cost when there is no prepare callback), or checking for the 
> correct prepare/enable semantics for all clocks (even when it doesn't matter 
> for that particular clock). I chose the first as more important, but happy to 
> go either way here.

The prepare method being called from non-atomic context cannot be 
considered to be in a speed critical path.  Most of the time, this is 
going to be called on driver initialization or the like, and that's a 
relatively rare event. Therefore this really small cost to clk_prepare() 
is definitively worth it to help proper usage of the API.  If this ever 
becomes a problem then this could be confined to some CONFIG_CLK_DEBUG 
or the like.  But when introducing a new API it is best to be more 
strict to help people get its usage right (without going overboard with 
it of course).


Nicolas

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-07 14:24         ` Nicolas Pitre
  0 siblings, 0 replies; 383+ messages in thread
From: Nicolas Pitre @ 2011-02-07 14:24 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: Uwe Kleine-König, linux-kernel, linux-arm-kernel,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Sascha Hauer, Paul Mundt, Dima Zavin, Saravana Kannan, Ben Dooks,
	Russell King

On Mon, 7 Feb 2011, Jeremy Kerr wrote:

> Hi Uwe,
> 
> > This implies the warning is only issued on clocks that have a prepare
> > callback.  If we want to enforce the new API the warning here shouldn't
> > depend on clk->ops->prepare.  (clk_prepare and clk_unprepare need to
> > be changed then to adapt the prepare_count even in the absence of
> > clk->ops->prepare.)
> 
> Yeah, it's a decision about either adding a small cost to all clk_prepare()s 
> (ie, adding cost when there is no prepare callback), or checking for the 
> correct prepare/enable semantics for all clocks (even when it doesn't matter 
> for that particular clock). I chose the first as more important, but happy to 
> go either way here.

The prepare method being called from non-atomic context cannot be 
considered to be in a speed critical path.  Most of the time, this is 
going to be called on driver initialization or the like, and that's a 
relatively rare event. Therefore this really small cost to clk_prepare() 
is definitively worth it to help proper usage of the API.  If this ever 
becomes a problem then this could be confined to some CONFIG_CLK_DEBUG 
or the like.  But when introducing a new API it is best to be more 
strict to help people get its usage right (without going overboard with 
it of course).


Nicolas

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-07 14:24         ` Nicolas Pitre
  0 siblings, 0 replies; 383+ messages in thread
From: Nicolas Pitre @ 2011-02-07 14:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 7 Feb 2011, Jeremy Kerr wrote:

> Hi Uwe,
> 
> > This implies the warning is only issued on clocks that have a prepare
> > callback.  If we want to enforce the new API the warning here shouldn't
> > depend on clk->ops->prepare.  (clk_prepare and clk_unprepare need to
> > be changed then to adapt the prepare_count even in the absence of
> > clk->ops->prepare.)
> 
> Yeah, it's a decision about either adding a small cost to all clk_prepare()s 
> (ie, adding cost when there is no prepare callback), or checking for the 
> correct prepare/enable semantics for all clocks (even when it doesn't matter 
> for that particular clock). I chose the first as more important, but happy to 
> go either way here.

The prepare method being called from non-atomic context cannot be 
considered to be in a speed critical path.  Most of the time, this is 
going to be called on driver initialization or the like, and that's a 
relatively rare event. Therefore this really small cost to clk_prepare() 
is definitively worth it to help proper usage of the API.  If this ever 
becomes a problem then this could be confined to some CONFIG_CLK_DEBUG 
or the like.  But when introducing a new API it is best to be more 
strict to help people get its usage right (without going overboard with 
it of course).


Nicolas

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-07  6:07   ` Jeremy Kerr
  (?)
@ 2011-02-07 19:59     ` Colin Cross
  -1 siblings, 0 replies; 383+ messages in thread
From: Colin Cross @ 2011-02-07 19:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Feb 6, 2011 at 10:07 PM, Jeremy Kerr <jeremy.kerr@canonical.com> wrote:
<snip>

> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..12e0daf
> --- /dev/null
> +++ b/drivers/clk/clk.c

<snip>

> +int clk_enable(struct clk *clk)
> +{
> +       int ret = 0;
> +
> +       if (!clk->ops->enable)
> +               return 0;
> +
> +       spin_lock(&clk->enable_lock);

spin_lock_irqsave/spin_unlock_irqrestore.  This could get called with
irqs on or off.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-07 19:59     ` Colin Cross
  0 siblings, 0 replies; 383+ messages in thread
From: Colin Cross @ 2011-02-07 19:59 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, Dima Zavin, Saravana Kannan, Ben Dooks,
	Uwe Kleine-König, Russell King

On Sun, Feb 6, 2011 at 10:07 PM, Jeremy Kerr <jeremy.kerr@canonical.com> wrote:
<snip>

> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..12e0daf
> --- /dev/null
> +++ b/drivers/clk/clk.c

<snip>

> +int clk_enable(struct clk *clk)
> +{
> +       int ret = 0;
> +
> +       if (!clk->ops->enable)
> +               return 0;
> +
> +       spin_lock(&clk->enable_lock);

spin_lock_irqsave/spin_unlock_irqrestore.  This could get called with
irqs on or off.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-07 19:59     ` Colin Cross
  0 siblings, 0 replies; 383+ messages in thread
From: Colin Cross @ 2011-02-07 19:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Feb 6, 2011 at 10:07 PM, Jeremy Kerr <jeremy.kerr@canonical.com> wrote:
<snip>

> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..12e0daf
> --- /dev/null
> +++ b/drivers/clk/clk.c

<snip>

> +int clk_enable(struct clk *clk)
> +{
> + ? ? ? int ret = 0;
> +
> + ? ? ? if (!clk->ops->enable)
> + ? ? ? ? ? ? ? return 0;
> +
> + ? ? ? spin_lock(&clk->enable_lock);

spin_lock_irqsave/spin_unlock_irqrestore.  This could get called with
irqs on or off.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-07  6:07   ` Jeremy Kerr
  (?)
@ 2011-02-07 20:20     ` Ryan Mallon
  -1 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-07 20:20 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/07/2011 07:07 PM, Jeremy Kerr wrote:
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, containing a set of clock operations. Different
> clock implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.

Hi Jeremy,

Quick review below.

~Ryan

> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
> 
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
> 
> And a set of clock operations (defined per type of clock):
> 
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
> 
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
> 
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
> 
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/Kconfig  |    3 
>  drivers/clk/Makefile |    1 
>  drivers/clk/clk.c    |  134 +++++++++++++++++++++++++++++++
>  drivers/clk/clkdev.c |    5 +
>  include/linux/clk.h  |  184 ++++++++++++++++++++++++++++++++++++++++---
>  5 files changed, 318 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4168c88..6e3ae54 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -2,3 +2,6 @@
>  config CLKDEV_LOOKUP
>  	bool
>  	select HAVE_CLK
> +
> +config USE_COMMON_STRUCT_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..a1a06d3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..12e0daf
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,134 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk->ops->prepare)
> +		return 0;

If there is no ops->prepare function then we never increment
prepare_count, which means that driver writers can get sloppy if they
know that ops->prepare is no-op on their platform since they will not
get warned for omitting clk_prepare.

Also, why are the warnings added in a separate patch rather than being
rolled into this patch?

> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (clk->prepare_count = 0)
> +		ret = clk->ops->prepare(clk);
> +
> +	if (!ret)
> +		clk->prepare_count++;
> +	mutex_unlock(&clk->prepare_lock);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	if (!clk->ops->unprepare)
> +		return;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (--clk->prepare_count = 0)
> +		clk->ops->unprepare(clk);
> +
> +	mutex_unlock(&clk->prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +int clk_enable(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk->ops->enable)
> +		return 0;

Again, you should still increment enable_count even if ops->enabled is a
no-op since it provides valuable warnings when clk_enable/disable calls
are not matched correctly.

> +
> +	spin_lock(&clk->enable_lock);
> +	if (!clk->enable_count)
> +		ret = clk->ops->enable(clk);
> +
> +	if (!ret)
> +		clk->enable_count++;
> +	spin_unlock(&clk->enable_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +void clk_disable(struct clk *clk)
> +{
> +	if (!clk->ops->disable)
> +		return;
> +
> +	spin_lock(&clk->enable_lock);
> +
> +	WARN_ON(!clk->enable_count);
> +
> +	if (!--clk->enable_count)
> +		clk->ops->disable(clk);
> +
> +	spin_unlock(&clk->enable_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	if (clk->ops->get_rate)
> +		return clk->ops->get_rate(clk);

Possibly we should shadow the clock rate if ops->get_rate is no-op? So
clock initialisation and clk_set_rate store the rate in the shadow
field, and then do:

	if (clk->ops->get_rate)
		return clk->ops->get_rate(clk);
	return clk->shadow_rate;

Because the API is generic, driver writers should reasonably expect that
clk_get_rate will return something valid without having to know the
platform implementation details. It may also be worth having a warning
to let the user know that the returned rate may be approximate.

> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +int __clk_get(struct clk *clk)
> +{
> +	if (clk->ops->get)
> +		return clk->ops->get(clk);
> +	return 1;
> +}
> +EXPORT_SYMBOL_GPL(__clk_get);
> +
> +void clk_put(struct clk *clk)
> +{
> +	if (clk->ops->put)
> +		clk->ops->put(clk);
> +}
> +EXPORT_SYMBOL_GPL(clk_put);

This has probably been covered, and I have probably missed it, but why
don't the generic clk_get/put functions do ref-counting? Drivers must
have matched clk_get/put calls so it should work like enable/prepare
counting right?

> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->round_rate)
> +		return clk->ops->round_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->set_rate)
> +		return clk->ops->set_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	if (clk->ops->set_parent)
> +		return clk->ops->set_parent(clk, parent);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	if (clk->ops->get_parent)
> +		return clk->ops->get_parent(clk);
> +	return ERR_PTR(-ENOSYS);
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> index 0fc0a79..17619c7 100644
> --- a/drivers/clk/clkdev.c
> +++ b/drivers/clk/clkdev.c
> @@ -84,12 +84,17 @@ struct clk *clk_get(struct device *dev, const char *con_id)
>  }
>  EXPORT_SYMBOL(clk_get);
>  
> +#ifndef CONFIG_USE_COMMON_STRUCT_CLK
> +/* For the common struct clk case, clk_put is provided by clk.c */
> +
>  void clk_put(struct clk *clk)
>  {
>  	__clk_put(clk);
>  }
>  EXPORT_SYMBOL(clk_put);
>  
> +#endif
> +
>  void clkdev_add(struct clk_lookup *cl)
>  {
>  	mutex_lock(&clocks_mutex);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..e081ca1 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@
>   *
>   *  Copyright (C) 2004 ARM Limited.
>   *  Written by Deep Blue Solutions Limited.
> + *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
> @@ -11,18 +12,189 @@
>  #ifndef __LINUX_CLK_H
>  #define __LINUX_CLK_H
>  
> +#include <linux/err.h>
> +#include <linux/mutex.h>
> +#include <linux/spinlock.h>
> +
>  struct device;
>  
> -/*
> - * The base API.
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> +
> +/* If we're using the common struct clk, we define the base clk object here */
> +
> +/**
> + * struct clk - hardware independent clock structure
> + * @ops:		implementation-specific ops for this clock
> + * @enable_count:	count of clk_enable() calls active on this clock
> + * @flags:		platform-independent flags
> + * @lock:		lock for enable/disable or other HW-specific ops
> + *
> + * The base clock object, used by drivers for hardware-independent manipulation
> + * of clock lines. This will be 'subclassed' by device-specific implementations,
> + * which add device-specific data to struct clk. For example:
> + *
> + *  struct clk_foo {
> + *      struct clk;
> + *      [device specific fields]
> + *  };
> + *
> + * The clock driver code will manage the device-specific data, and pass
> + * clk_foo.clk to the common clock code. The clock driver will be called
> + * through the @ops callbacks.
> + *
> + * The @lock member provides either a spinlock or a mutex to protect (at least)
> + * @enable_count. The type of lock used will depend on @flags; if CLK_ATOMIC is
> + * set, then the core clock code will use a spinlock, otherwise a mutex. This
> + * lock will be acquired during clk_enable and clk_disable, so for atomic
> + * clocks, these ops callbacks must not sleep.
> + *
> + * The choice of atomic or non-atomic clock depends on how the clock is enabled.
> + * Typically, you'll want to use a non-atomic clock. For clocks that need to be
> + * enabled/disabled in interrupt context, use CLK_ATOMIC. Note that atomic
> + * clocks with parents will typically cascade enable/disable operations to
> + * their parent, so the parent of an atomic clock *must* be atomic too.

This comment seems out of date now that we have the prepare/enable
semantics?

>   */
> +struct clk {
> +	const struct clk_ops	*ops;
> +	unsigned int		enable_count;
> +	unsigned int		prepare_count;
> +	spinlock_t		enable_lock;
> +	struct mutex		prepare_lock;
> +};
> +
> +/* static initialiser for non-atomic clocks */
> +#define INIT_CLK(name, o) {						\
> +	.ops		= &o,						\
> +	.enable_count	= 0,						\
> +	.prepare_count	= 0,						\
> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
> +}
>  
> +/**
> + * struct clk_ops -  Callback operations for clocks; these are to be provided
> + * by the clock implementation, and will be called by drivers through the clk_*
> + * API.
> + *
> + * @prepare:	Prepare the clock for enabling. This must not return until
> + *		the clock is fully prepared, and it's safe to call clk_enable.
> + *		This callback is intended to allow clock implementations to
> + *		do any initialisation that may block. Called with
> + *		clk->prepare_lock held.
> + *
> + * @unprepare:	Release the clock from its prepared state. This will typically
> + *		undo any work done in the @prepare callback. Called with
> + *		clk->prepare_lock held.

I think you need to make it more clear the prepare/unprepare must be
called from a sleepable context.

> + * @enable:	Enable the clock atomically. This must not return until the
> + *		clock is generating a valid clock signal, usable by consumer
> + *		devices. Called with clk->enable_lock held.
> + *
> + * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
> + *
> + * @get:	Called by the core clock code when a device driver acquires a
> + *		clock via clk_get(). Optional.
> + *
> + * @put:	Called by the core clock code when a devices driver releases a
> + *		clock via clk_put(). Optional.
> + *
> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> + * implementations to split any work between atomic (enable) and sleepable
> + * (prepare) contexts.  If a clock requires blocking code to be turned on, this
> + * should be done in clk_prepare. Switching that will not block should be done
> + * in clk_enable.
> + *
> + * Typically, drivers will call clk_prepare when a clock may be needed later
> + * (eg. when a device is opened), and clk_enable when the clock is actually
> + * required (eg. from an interrupt).

Drivers _must_ call clk_prepare before clk_enable (not typically)?

> + *
> + * For other callbacks, see the corresponding clk_* functions. Parameters and
> + * return values are passed directly from/to these API functions, or
> + * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
> + * is NULL, see kernel/clk.c for implementation details. All are optional.
> + */
> +struct clk_ops {
> +	int		(*prepare)(struct clk *);
> +	void		(*unprepare)(struct clk *);
> +	int		(*enable)(struct clk *);
> +	void		(*disable)(struct clk *);
> +	int		(*get)(struct clk *);
> +	void		(*put)(struct clk *);
> +	unsigned long	(*get_rate)(struct clk *);
> +	long		(*round_rate)(struct clk *, unsigned long);
> +	int		(*set_rate)(struct clk *, unsigned long);
> +	int		(*set_parent)(struct clk *, struct clk *);
> +	struct clk *	(*get_parent)(struct clk *);
> +};
> +
> +/**
> + * __clk_get - update clock-specific refcounter
> + *
> + * @clk: The clock to refcount
> + *
> + * Before a clock is returned from clk_get, this function should be called
> + * to update any clock-specific refcounting.
> + *
> + * Returns non-zero on success, zero on failure.
> + *
> + * Drivers should not need this function; it is only needed by the
> + * arch-specific clk_get() implementations.
> + */
> +int __clk_get(struct clk *clk);

I don't understand this. Are architectures supposed to provide a
function called clk_get? Doesn't this break the whole idea of having a
common struct clk?

> +/**
> + * clk_prepare - prepare clock for atomic enabling.
> + *
> + * @clk: The clock to prepare
> + *
> + * Do any blocking initialisation on @clk, allowing the clock to be later
> + * enabled atomically (via clk_enable). This function may sleep.
> + */
> +int clk_prepare(struct clk *clk);
> +
> +/**
> + * clk_unprepare - release clock from prepared state
> + *
> + * @clk: The clock to release
> + *
> + * Do any (possbly blocking) cleanup on clk. This function may sleep.
> + */
> +void clk_unprepare(struct clk *clk);
> +
> +/**
> + * clk_common_init - initialise a clock for driver usage
> + *
> + * @clk: The clock to initialise
> + *
> + * Used for runtime intialization of clocks; you don't need to call this
> + * if your clock has been (statically) initialized with INIT_CLK.
> + */
> +static inline void clk_common_init(struct clk *clk)
> +{
> +	clk->enable_count = clk->prepare_count = 0;
> +	spin_lock_init(&clk->enable_lock);
> +	mutex_init(&clk->prepare_lock);
> +}
> +
> +#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
>  
>  /*
> - * struct clk - an machine class defined object / cookie.
> + * Global clock object, actual structure is declared per-machine
>   */
>  struct clk;
>  
> +static inline void clk_common_init(struct clk *clk) { }
> +
> +/*
> + * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
> + * requirements for clk_enable/clk_disable, so the prepare and unprepare
> + * functions are no-ops
> + */
> +int clk_prepare(struct clk *clk) { return 0; }
> +void clk_unprepare(struct clk *clk) { }
> +
> +#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
> +
>  /**
>   * clk_get - lookup and obtain a reference to a clock producer.
>   * @dev: device for clock "consumer"
> @@ -83,12 +255,6 @@ unsigned long clk_get_rate(struct clk *clk);
>   */
>  void clk_put(struct clk *clk);
>  
> -
> -/*
> - * The remaining APIs are optional for machine class support.
> - */
> -
> -
>  /**
>   * clk_round_rate - adjust a rate to the exact rate a clock can provide
>   * @clk: clock source
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan@bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-07 20:20     ` Ryan Mallon
  0 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-07 20:20 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Dima Zavin,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Uwe Kleine-König, Sascha Hauer, Paul Mundt, Saravana Kannan,
	Ben Dooks, Russell King

On 02/07/2011 07:07 PM, Jeremy Kerr wrote:
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, containing a set of clock operations. Different
> clock implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.

Hi Jeremy,

Quick review below.

~Ryan

> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
> 
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
> 
> And a set of clock operations (defined per type of clock):
> 
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
> 
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
> 
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
> 
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/Kconfig  |    3 
>  drivers/clk/Makefile |    1 
>  drivers/clk/clk.c    |  134 +++++++++++++++++++++++++++++++
>  drivers/clk/clkdev.c |    5 +
>  include/linux/clk.h  |  184 ++++++++++++++++++++++++++++++++++++++++---
>  5 files changed, 318 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4168c88..6e3ae54 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -2,3 +2,6 @@
>  config CLKDEV_LOOKUP
>  	bool
>  	select HAVE_CLK
> +
> +config USE_COMMON_STRUCT_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..a1a06d3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..12e0daf
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,134 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk->ops->prepare)
> +		return 0;

If there is no ops->prepare function then we never increment
prepare_count, which means that driver writers can get sloppy if they
know that ops->prepare is no-op on their platform since they will not
get warned for omitting clk_prepare.

Also, why are the warnings added in a separate patch rather than being
rolled into this patch?

> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (clk->prepare_count == 0)
> +		ret = clk->ops->prepare(clk);
> +
> +	if (!ret)
> +		clk->prepare_count++;
> +	mutex_unlock(&clk->prepare_lock);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	if (!clk->ops->unprepare)
> +		return;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (--clk->prepare_count == 0)
> +		clk->ops->unprepare(clk);
> +
> +	mutex_unlock(&clk->prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +int clk_enable(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk->ops->enable)
> +		return 0;

Again, you should still increment enable_count even if ops->enabled is a
no-op since it provides valuable warnings when clk_enable/disable calls
are not matched correctly.

> +
> +	spin_lock(&clk->enable_lock);
> +	if (!clk->enable_count)
> +		ret = clk->ops->enable(clk);
> +
> +	if (!ret)
> +		clk->enable_count++;
> +	spin_unlock(&clk->enable_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +void clk_disable(struct clk *clk)
> +{
> +	if (!clk->ops->disable)
> +		return;
> +
> +	spin_lock(&clk->enable_lock);
> +
> +	WARN_ON(!clk->enable_count);
> +
> +	if (!--clk->enable_count)
> +		clk->ops->disable(clk);
> +
> +	spin_unlock(&clk->enable_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	if (clk->ops->get_rate)
> +		return clk->ops->get_rate(clk);

Possibly we should shadow the clock rate if ops->get_rate is no-op? So
clock initialisation and clk_set_rate store the rate in the shadow
field, and then do:

	if (clk->ops->get_rate)
		return clk->ops->get_rate(clk);
	return clk->shadow_rate;

Because the API is generic, driver writers should reasonably expect that
clk_get_rate will return something valid without having to know the
platform implementation details. It may also be worth having a warning
to let the user know that the returned rate may be approximate.

> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +int __clk_get(struct clk *clk)
> +{
> +	if (clk->ops->get)
> +		return clk->ops->get(clk);
> +	return 1;
> +}
> +EXPORT_SYMBOL_GPL(__clk_get);
> +
> +void clk_put(struct clk *clk)
> +{
> +	if (clk->ops->put)
> +		clk->ops->put(clk);
> +}
> +EXPORT_SYMBOL_GPL(clk_put);

This has probably been covered, and I have probably missed it, but why
don't the generic clk_get/put functions do ref-counting? Drivers must
have matched clk_get/put calls so it should work like enable/prepare
counting right?

> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->round_rate)
> +		return clk->ops->round_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->set_rate)
> +		return clk->ops->set_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	if (clk->ops->set_parent)
> +		return clk->ops->set_parent(clk, parent);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	if (clk->ops->get_parent)
> +		return clk->ops->get_parent(clk);
> +	return ERR_PTR(-ENOSYS);
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> index 0fc0a79..17619c7 100644
> --- a/drivers/clk/clkdev.c
> +++ b/drivers/clk/clkdev.c
> @@ -84,12 +84,17 @@ struct clk *clk_get(struct device *dev, const char *con_id)
>  }
>  EXPORT_SYMBOL(clk_get);
>  
> +#ifndef CONFIG_USE_COMMON_STRUCT_CLK
> +/* For the common struct clk case, clk_put is provided by clk.c */
> +
>  void clk_put(struct clk *clk)
>  {
>  	__clk_put(clk);
>  }
>  EXPORT_SYMBOL(clk_put);
>  
> +#endif
> +
>  void clkdev_add(struct clk_lookup *cl)
>  {
>  	mutex_lock(&clocks_mutex);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..e081ca1 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@
>   *
>   *  Copyright (C) 2004 ARM Limited.
>   *  Written by Deep Blue Solutions Limited.
> + *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
> @@ -11,18 +12,189 @@
>  #ifndef __LINUX_CLK_H
>  #define __LINUX_CLK_H
>  
> +#include <linux/err.h>
> +#include <linux/mutex.h>
> +#include <linux/spinlock.h>
> +
>  struct device;
>  
> -/*
> - * The base API.
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> +
> +/* If we're using the common struct clk, we define the base clk object here */
> +
> +/**
> + * struct clk - hardware independent clock structure
> + * @ops:		implementation-specific ops for this clock
> + * @enable_count:	count of clk_enable() calls active on this clock
> + * @flags:		platform-independent flags
> + * @lock:		lock for enable/disable or other HW-specific ops
> + *
> + * The base clock object, used by drivers for hardware-independent manipulation
> + * of clock lines. This will be 'subclassed' by device-specific implementations,
> + * which add device-specific data to struct clk. For example:
> + *
> + *  struct clk_foo {
> + *      struct clk;
> + *      [device specific fields]
> + *  };
> + *
> + * The clock driver code will manage the device-specific data, and pass
> + * clk_foo.clk to the common clock code. The clock driver will be called
> + * through the @ops callbacks.
> + *
> + * The @lock member provides either a spinlock or a mutex to protect (at least)
> + * @enable_count. The type of lock used will depend on @flags; if CLK_ATOMIC is
> + * set, then the core clock code will use a spinlock, otherwise a mutex. This
> + * lock will be acquired during clk_enable and clk_disable, so for atomic
> + * clocks, these ops callbacks must not sleep.
> + *
> + * The choice of atomic or non-atomic clock depends on how the clock is enabled.
> + * Typically, you'll want to use a non-atomic clock. For clocks that need to be
> + * enabled/disabled in interrupt context, use CLK_ATOMIC. Note that atomic
> + * clocks with parents will typically cascade enable/disable operations to
> + * their parent, so the parent of an atomic clock *must* be atomic too.

This comment seems out of date now that we have the prepare/enable
semantics?

>   */
> +struct clk {
> +	const struct clk_ops	*ops;
> +	unsigned int		enable_count;
> +	unsigned int		prepare_count;
> +	spinlock_t		enable_lock;
> +	struct mutex		prepare_lock;
> +};
> +
> +/* static initialiser for non-atomic clocks */
> +#define INIT_CLK(name, o) {						\
> +	.ops		= &o,						\
> +	.enable_count	= 0,						\
> +	.prepare_count	= 0,						\
> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
> +}
>  
> +/**
> + * struct clk_ops -  Callback operations for clocks; these are to be provided
> + * by the clock implementation, and will be called by drivers through the clk_*
> + * API.
> + *
> + * @prepare:	Prepare the clock for enabling. This must not return until
> + *		the clock is fully prepared, and it's safe to call clk_enable.
> + *		This callback is intended to allow clock implementations to
> + *		do any initialisation that may block. Called with
> + *		clk->prepare_lock held.
> + *
> + * @unprepare:	Release the clock from its prepared state. This will typically
> + *		undo any work done in the @prepare callback. Called with
> + *		clk->prepare_lock held.

I think you need to make it more clear the prepare/unprepare must be
called from a sleepable context.

> + * @enable:	Enable the clock atomically. This must not return until the
> + *		clock is generating a valid clock signal, usable by consumer
> + *		devices. Called with clk->enable_lock held.
> + *
> + * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
> + *
> + * @get:	Called by the core clock code when a device driver acquires a
> + *		clock via clk_get(). Optional.
> + *
> + * @put:	Called by the core clock code when a devices driver releases a
> + *		clock via clk_put(). Optional.
> + *
> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> + * implementations to split any work between atomic (enable) and sleepable
> + * (prepare) contexts.  If a clock requires blocking code to be turned on, this
> + * should be done in clk_prepare. Switching that will not block should be done
> + * in clk_enable.
> + *
> + * Typically, drivers will call clk_prepare when a clock may be needed later
> + * (eg. when a device is opened), and clk_enable when the clock is actually
> + * required (eg. from an interrupt).

Drivers _must_ call clk_prepare before clk_enable (not typically)?

> + *
> + * For other callbacks, see the corresponding clk_* functions. Parameters and
> + * return values are passed directly from/to these API functions, or
> + * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
> + * is NULL, see kernel/clk.c for implementation details. All are optional.
> + */
> +struct clk_ops {
> +	int		(*prepare)(struct clk *);
> +	void		(*unprepare)(struct clk *);
> +	int		(*enable)(struct clk *);
> +	void		(*disable)(struct clk *);
> +	int		(*get)(struct clk *);
> +	void		(*put)(struct clk *);
> +	unsigned long	(*get_rate)(struct clk *);
> +	long		(*round_rate)(struct clk *, unsigned long);
> +	int		(*set_rate)(struct clk *, unsigned long);
> +	int		(*set_parent)(struct clk *, struct clk *);
> +	struct clk *	(*get_parent)(struct clk *);
> +};
> +
> +/**
> + * __clk_get - update clock-specific refcounter
> + *
> + * @clk: The clock to refcount
> + *
> + * Before a clock is returned from clk_get, this function should be called
> + * to update any clock-specific refcounting.
> + *
> + * Returns non-zero on success, zero on failure.
> + *
> + * Drivers should not need this function; it is only needed by the
> + * arch-specific clk_get() implementations.
> + */
> +int __clk_get(struct clk *clk);

I don't understand this. Are architectures supposed to provide a
function called clk_get? Doesn't this break the whole idea of having a
common struct clk?

> +/**
> + * clk_prepare - prepare clock for atomic enabling.
> + *
> + * @clk: The clock to prepare
> + *
> + * Do any blocking initialisation on @clk, allowing the clock to be later
> + * enabled atomically (via clk_enable). This function may sleep.
> + */
> +int clk_prepare(struct clk *clk);
> +
> +/**
> + * clk_unprepare - release clock from prepared state
> + *
> + * @clk: The clock to release
> + *
> + * Do any (possbly blocking) cleanup on clk. This function may sleep.
> + */
> +void clk_unprepare(struct clk *clk);
> +
> +/**
> + * clk_common_init - initialise a clock for driver usage
> + *
> + * @clk: The clock to initialise
> + *
> + * Used for runtime intialization of clocks; you don't need to call this
> + * if your clock has been (statically) initialized with INIT_CLK.
> + */
> +static inline void clk_common_init(struct clk *clk)
> +{
> +	clk->enable_count = clk->prepare_count = 0;
> +	spin_lock_init(&clk->enable_lock);
> +	mutex_init(&clk->prepare_lock);
> +}
> +
> +#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
>  
>  /*
> - * struct clk - an machine class defined object / cookie.
> + * Global clock object, actual structure is declared per-machine
>   */
>  struct clk;
>  
> +static inline void clk_common_init(struct clk *clk) { }
> +
> +/*
> + * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
> + * requirements for clk_enable/clk_disable, so the prepare and unprepare
> + * functions are no-ops
> + */
> +int clk_prepare(struct clk *clk) { return 0; }
> +void clk_unprepare(struct clk *clk) { }
> +
> +#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
> +
>  /**
>   * clk_get - lookup and obtain a reference to a clock producer.
>   * @dev: device for clock "consumer"
> @@ -83,12 +255,6 @@ unsigned long clk_get_rate(struct clk *clk);
>   */
>  void clk_put(struct clk *clk);
>  
> -
> -/*
> - * The remaining APIs are optional for machine class support.
> - */
> -
> -
>  /**
>   * clk_round_rate - adjust a rate to the exact rate a clock can provide
>   * @clk: clock source
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan@bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-07 20:20     ` Ryan Mallon
  0 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-07 20:20 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/07/2011 07:07 PM, Jeremy Kerr wrote:
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, containing a set of clock operations. Different
> clock implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.

Hi Jeremy,

Quick review below.

~Ryan

> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
> 
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
> 
> And a set of clock operations (defined per type of clock):
> 
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
> 
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
> 
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
> 
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/Kconfig  |    3 
>  drivers/clk/Makefile |    1 
>  drivers/clk/clk.c    |  134 +++++++++++++++++++++++++++++++
>  drivers/clk/clkdev.c |    5 +
>  include/linux/clk.h  |  184 ++++++++++++++++++++++++++++++++++++++++---
>  5 files changed, 318 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4168c88..6e3ae54 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -2,3 +2,6 @@
>  config CLKDEV_LOOKUP
>  	bool
>  	select HAVE_CLK
> +
> +config USE_COMMON_STRUCT_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..a1a06d3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..12e0daf
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,134 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk->ops->prepare)
> +		return 0;

If there is no ops->prepare function then we never increment
prepare_count, which means that driver writers can get sloppy if they
know that ops->prepare is no-op on their platform since they will not
get warned for omitting clk_prepare.

Also, why are the warnings added in a separate patch rather than being
rolled into this patch?

> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (clk->prepare_count == 0)
> +		ret = clk->ops->prepare(clk);
> +
> +	if (!ret)
> +		clk->prepare_count++;
> +	mutex_unlock(&clk->prepare_lock);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	if (!clk->ops->unprepare)
> +		return;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (--clk->prepare_count == 0)
> +		clk->ops->unprepare(clk);
> +
> +	mutex_unlock(&clk->prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +int clk_enable(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk->ops->enable)
> +		return 0;

Again, you should still increment enable_count even if ops->enabled is a
no-op since it provides valuable warnings when clk_enable/disable calls
are not matched correctly.

> +
> +	spin_lock(&clk->enable_lock);
> +	if (!clk->enable_count)
> +		ret = clk->ops->enable(clk);
> +
> +	if (!ret)
> +		clk->enable_count++;
> +	spin_unlock(&clk->enable_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +void clk_disable(struct clk *clk)
> +{
> +	if (!clk->ops->disable)
> +		return;
> +
> +	spin_lock(&clk->enable_lock);
> +
> +	WARN_ON(!clk->enable_count);
> +
> +	if (!--clk->enable_count)
> +		clk->ops->disable(clk);
> +
> +	spin_unlock(&clk->enable_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	if (clk->ops->get_rate)
> +		return clk->ops->get_rate(clk);

Possibly we should shadow the clock rate if ops->get_rate is no-op? So
clock initialisation and clk_set_rate store the rate in the shadow
field, and then do:

	if (clk->ops->get_rate)
		return clk->ops->get_rate(clk);
	return clk->shadow_rate;

Because the API is generic, driver writers should reasonably expect that
clk_get_rate will return something valid without having to know the
platform implementation details. It may also be worth having a warning
to let the user know that the returned rate may be approximate.

> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +int __clk_get(struct clk *clk)
> +{
> +	if (clk->ops->get)
> +		return clk->ops->get(clk);
> +	return 1;
> +}
> +EXPORT_SYMBOL_GPL(__clk_get);
> +
> +void clk_put(struct clk *clk)
> +{
> +	if (clk->ops->put)
> +		clk->ops->put(clk);
> +}
> +EXPORT_SYMBOL_GPL(clk_put);

This has probably been covered, and I have probably missed it, but why
don't the generic clk_get/put functions do ref-counting? Drivers must
have matched clk_get/put calls so it should work like enable/prepare
counting right?

> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->round_rate)
> +		return clk->ops->round_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->set_rate)
> +		return clk->ops->set_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	if (clk->ops->set_parent)
> +		return clk->ops->set_parent(clk, parent);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	if (clk->ops->get_parent)
> +		return clk->ops->get_parent(clk);
> +	return ERR_PTR(-ENOSYS);
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> index 0fc0a79..17619c7 100644
> --- a/drivers/clk/clkdev.c
> +++ b/drivers/clk/clkdev.c
> @@ -84,12 +84,17 @@ struct clk *clk_get(struct device *dev, const char *con_id)
>  }
>  EXPORT_SYMBOL(clk_get);
>  
> +#ifndef CONFIG_USE_COMMON_STRUCT_CLK
> +/* For the common struct clk case, clk_put is provided by clk.c */
> +
>  void clk_put(struct clk *clk)
>  {
>  	__clk_put(clk);
>  }
>  EXPORT_SYMBOL(clk_put);
>  
> +#endif
> +
>  void clkdev_add(struct clk_lookup *cl)
>  {
>  	mutex_lock(&clocks_mutex);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..e081ca1 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@
>   *
>   *  Copyright (C) 2004 ARM Limited.
>   *  Written by Deep Blue Solutions Limited.
> + *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
> @@ -11,18 +12,189 @@
>  #ifndef __LINUX_CLK_H
>  #define __LINUX_CLK_H
>  
> +#include <linux/err.h>
> +#include <linux/mutex.h>
> +#include <linux/spinlock.h>
> +
>  struct device;
>  
> -/*
> - * The base API.
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> +
> +/* If we're using the common struct clk, we define the base clk object here */
> +
> +/**
> + * struct clk - hardware independent clock structure
> + * @ops:		implementation-specific ops for this clock
> + * @enable_count:	count of clk_enable() calls active on this clock
> + * @flags:		platform-independent flags
> + * @lock:		lock for enable/disable or other HW-specific ops
> + *
> + * The base clock object, used by drivers for hardware-independent manipulation
> + * of clock lines. This will be 'subclassed' by device-specific implementations,
> + * which add device-specific data to struct clk. For example:
> + *
> + *  struct clk_foo {
> + *      struct clk;
> + *      [device specific fields]
> + *  };
> + *
> + * The clock driver code will manage the device-specific data, and pass
> + * clk_foo.clk to the common clock code. The clock driver will be called
> + * through the @ops callbacks.
> + *
> + * The @lock member provides either a spinlock or a mutex to protect (at least)
> + * @enable_count. The type of lock used will depend on @flags; if CLK_ATOMIC is
> + * set, then the core clock code will use a spinlock, otherwise a mutex. This
> + * lock will be acquired during clk_enable and clk_disable, so for atomic
> + * clocks, these ops callbacks must not sleep.
> + *
> + * The choice of atomic or non-atomic clock depends on how the clock is enabled.
> + * Typically, you'll want to use a non-atomic clock. For clocks that need to be
> + * enabled/disabled in interrupt context, use CLK_ATOMIC. Note that atomic
> + * clocks with parents will typically cascade enable/disable operations to
> + * their parent, so the parent of an atomic clock *must* be atomic too.

This comment seems out of date now that we have the prepare/enable
semantics?

>   */
> +struct clk {
> +	const struct clk_ops	*ops;
> +	unsigned int		enable_count;
> +	unsigned int		prepare_count;
> +	spinlock_t		enable_lock;
> +	struct mutex		prepare_lock;
> +};
> +
> +/* static initialiser for non-atomic clocks */
> +#define INIT_CLK(name, o) {						\
> +	.ops		= &o,						\
> +	.enable_count	= 0,						\
> +	.prepare_count	= 0,						\
> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
> +}
>  
> +/**
> + * struct clk_ops -  Callback operations for clocks; these are to be provided
> + * by the clock implementation, and will be called by drivers through the clk_*
> + * API.
> + *
> + * @prepare:	Prepare the clock for enabling. This must not return until
> + *		the clock is fully prepared, and it's safe to call clk_enable.
> + *		This callback is intended to allow clock implementations to
> + *		do any initialisation that may block. Called with
> + *		clk->prepare_lock held.
> + *
> + * @unprepare:	Release the clock from its prepared state. This will typically
> + *		undo any work done in the @prepare callback. Called with
> + *		clk->prepare_lock held.

I think you need to make it more clear the prepare/unprepare must be
called from a sleepable context.

> + * @enable:	Enable the clock atomically. This must not return until the
> + *		clock is generating a valid clock signal, usable by consumer
> + *		devices. Called with clk->enable_lock held.
> + *
> + * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
> + *
> + * @get:	Called by the core clock code when a device driver acquires a
> + *		clock via clk_get(). Optional.
> + *
> + * @put:	Called by the core clock code when a devices driver releases a
> + *		clock via clk_put(). Optional.
> + *
> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> + * implementations to split any work between atomic (enable) and sleepable
> + * (prepare) contexts.  If a clock requires blocking code to be turned on, this
> + * should be done in clk_prepare. Switching that will not block should be done
> + * in clk_enable.
> + *
> + * Typically, drivers will call clk_prepare when a clock may be needed later
> + * (eg. when a device is opened), and clk_enable when the clock is actually
> + * required (eg. from an interrupt).

Drivers _must_ call clk_prepare before clk_enable (not typically)?

> + *
> + * For other callbacks, see the corresponding clk_* functions. Parameters and
> + * return values are passed directly from/to these API functions, or
> + * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
> + * is NULL, see kernel/clk.c for implementation details. All are optional.
> + */
> +struct clk_ops {
> +	int		(*prepare)(struct clk *);
> +	void		(*unprepare)(struct clk *);
> +	int		(*enable)(struct clk *);
> +	void		(*disable)(struct clk *);
> +	int		(*get)(struct clk *);
> +	void		(*put)(struct clk *);
> +	unsigned long	(*get_rate)(struct clk *);
> +	long		(*round_rate)(struct clk *, unsigned long);
> +	int		(*set_rate)(struct clk *, unsigned long);
> +	int		(*set_parent)(struct clk *, struct clk *);
> +	struct clk *	(*get_parent)(struct clk *);
> +};
> +
> +/**
> + * __clk_get - update clock-specific refcounter
> + *
> + * @clk: The clock to refcount
> + *
> + * Before a clock is returned from clk_get, this function should be called
> + * to update any clock-specific refcounting.
> + *
> + * Returns non-zero on success, zero on failure.
> + *
> + * Drivers should not need this function; it is only needed by the
> + * arch-specific clk_get() implementations.
> + */
> +int __clk_get(struct clk *clk);

I don't understand this. Are architectures supposed to provide a
function called clk_get? Doesn't this break the whole idea of having a
common struct clk?

> +/**
> + * clk_prepare - prepare clock for atomic enabling.
> + *
> + * @clk: The clock to prepare
> + *
> + * Do any blocking initialisation on @clk, allowing the clock to be later
> + * enabled atomically (via clk_enable). This function may sleep.
> + */
> +int clk_prepare(struct clk *clk);
> +
> +/**
> + * clk_unprepare - release clock from prepared state
> + *
> + * @clk: The clock to release
> + *
> + * Do any (possbly blocking) cleanup on clk. This function may sleep.
> + */
> +void clk_unprepare(struct clk *clk);
> +
> +/**
> + * clk_common_init - initialise a clock for driver usage
> + *
> + * @clk: The clock to initialise
> + *
> + * Used for runtime intialization of clocks; you don't need to call this
> + * if your clock has been (statically) initialized with INIT_CLK.
> + */
> +static inline void clk_common_init(struct clk *clk)
> +{
> +	clk->enable_count = clk->prepare_count = 0;
> +	spin_lock_init(&clk->enable_lock);
> +	mutex_init(&clk->prepare_lock);
> +}
> +
> +#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
>  
>  /*
> - * struct clk - an machine class defined object / cookie.
> + * Global clock object, actual structure is declared per-machine
>   */
>  struct clk;
>  
> +static inline void clk_common_init(struct clk *clk) { }
> +
> +/*
> + * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
> + * requirements for clk_enable/clk_disable, so the prepare and unprepare
> + * functions are no-ops
> + */
> +int clk_prepare(struct clk *clk) { return 0; }
> +void clk_unprepare(struct clk *clk) { }
> +
> +#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
> +
>  /**
>   * clk_get - lookup and obtain a reference to a clock producer.
>   * @dev: device for clock "consumer"
> @@ -83,12 +255,6 @@ unsigned long clk_get_rate(struct clk *clk);
>   */
>  void clk_put(struct clk *clk);
>  
> -
> -/*
> - * The remaining APIs are optional for machine class support.
> - */
> -
> -
>  /**
>   * clk_round_rate - adjust a rate to the exact rate a clock can provide
>   * @clk: clock source
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-07 19:59     ` Colin Cross
  (?)
@ 2011-02-08  1:40       ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-08  1:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ryan,

> > +int clk_enable(struct clk *clk)
> > +{
> > +       int ret = 0;
> > +
> > +       if (!clk->ops->enable)
> > +               return 0;
> > +
> > +       spin_lock(&clk->enable_lock);
> 
> spin_lock_irqsave/spin_unlock_irqrestore.  This could get called with
> irqs on or off.

Ah, I had planned to change this but (obviously) didn't get to it. Thanks for 
the reminder, I'll include this in the next revision.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-08  1:40       ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-08  1:40 UTC (permalink / raw)
  To: Colin Cross
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, Dima Zavin, Saravana Kannan, Ben Dooks,
	Uwe Kleine-König, Russell King

Hi Ryan,

> > +int clk_enable(struct clk *clk)
> > +{
> > +       int ret = 0;
> > +
> > +       if (!clk->ops->enable)
> > +               return 0;
> > +
> > +       spin_lock(&clk->enable_lock);
> 
> spin_lock_irqsave/spin_unlock_irqrestore.  This could get called with
> irqs on or off.

Ah, I had planned to change this but (obviously) didn't get to it. Thanks for 
the reminder, I'll include this in the next revision.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-08  1:40       ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-08  1:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ryan,

> > +int clk_enable(struct clk *clk)
> > +{
> > +       int ret = 0;
> > +
> > +       if (!clk->ops->enable)
> > +               return 0;
> > +
> > +       spin_lock(&clk->enable_lock);
> 
> spin_lock_irqsave/spin_unlock_irqrestore.  This could get called with
> irqs on or off.

Ah, I had planned to change this but (obviously) didn't get to it. Thanks for 
the reminder, I'll include this in the next revision.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-07 20:20     ` Ryan Mallon
  (?)
@ 2011-02-08  2:54       ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-08  2:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ryan,

> > +int clk_prepare(struct clk *clk)
> > +{
> > +	int ret = 0;
> > +
> > +	if (!clk->ops->prepare)
> > +		return 0;
> 
> If there is no ops->prepare function then we never increment
> prepare_count, which means that driver writers can get sloppy if they
> know that ops->prepare is no-op on their platform since they will not
> get warned for omitting clk_prepare.

Yeah, as discussed in other replies, it's probably best that we do the 
counting unconditionally. I've removed these optimisations - I think we'd best 
enforce the checking here, at least at the introduction of this API.
 
> Also, why are the warnings added in a separate patch rather than being
> rolled into this patch?

Just splitting things up; the warnings were the most discussed issue 
previously, so I wanted to separate that discussion from the API side.

> Again, you should still increment enable_count even if ops->enabled is a
> no-op since it provides valuable warnings when clk_enable/disable calls
> are not matched correctly.

Yep, as above.

> > +unsigned long clk_get_rate(struct clk *clk)
> > +{
> > +	if (clk->ops->get_rate)
> > +		return clk->ops->get_rate(clk);
> 
> Possibly we should shadow the clock rate if ops->get_rate is no-op? So
> clock initialisation and clk_set_rate store the rate in the shadow
> field, and then do:
> 
> 	if (clk->ops->get_rate)
> 		return clk->ops->get_rate(clk);
> 	return clk->shadow_rate;
> 
> Because the API is generic, driver writers should reasonably expect that
> clk_get_rate will return something valid without having to know the
> platform implementation details. It may also be worth having a warning
> to let the user know that the returned rate may be approximate.

I'd prefer to require that get_rate is implemented as an op, rather than 
allowing two methods for retrieving the rate of the clock.

> > +	return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(clk_get_rate);
> > +
> > +int __clk_get(struct clk *clk)
> > +{
> > +	if (clk->ops->get)
> > +		return clk->ops->get(clk);
> > +	return 1;
> > +}
> > +EXPORT_SYMBOL_GPL(__clk_get);
> > +
> > +void clk_put(struct clk *clk)
> > +{
> > +	if (clk->ops->put)
> > +		clk->ops->put(clk);
> > +}
> > +EXPORT_SYMBOL_GPL(clk_put);
> 
> This has probably been covered, and I have probably missed it, but why
> don't the generic clk_get/put functions do ref-counting? Drivers must
> have matched clk_get/put calls so it should work like enable/prepare
> counting right?

clk_get is used to find a clock; most implementations will not use this for 
refcounting.

However, for the case where clocks are dynamically allocated, we need clk_put 
to do any possible freeing. There's an existing API for this type of reference 
counting (kref), so for the cases where this matters, the clock 
implementations can use that.

> > + * The choice of atomic or non-atomic clock depends on how the clock is
> > enabled. + * Typically, you'll want to use a non-atomic clock. For
> > clocks that need to be + * enabled/disabled in interrupt context, use
> > CLK_ATOMIC. Note that atomic + * clocks with parents will typically
> > cascade enable/disable operations to + * their parent, so the parent of
> > an atomic clock *must* be atomic too.
> 
> This comment seems out of date now that we have the prepare/enable
> semantics?

Yep, will update.

> > + * @unprepare:	Release the clock from its prepared state. This will
> > typically + *		undo any work done in the @prepare callback. Called 
> > with + *		clk->prepare_lock held.
> 
> I think you need to make it more clear the prepare/unprepare must be
> called from a sleepable context.

The documentation on clk_ops is intended for the clock implementor, so it's 
not really the right place to descibe the caller's requirements.

Indeed, the documentation for clk_prepare & clk_unprepare describe the 
caller's requirements for these (and contain the words "This function may 
sleep").

> > + * Typically, drivers will call clk_prepare when a clock may be needed
> > later + * (eg. when a device is opened), and clk_enable when the clock
> > is actually + * required (eg. from an interrupt).
> 
> Drivers _must_ call clk_prepare before clk_enable (not typically)?

This 'typically' is about the actual placement of the clk_prepare and 
clk_enable calls in the driver code, but I will clarify.

> > +/**
> > + * __clk_get - update clock-specific refcounter
> > + *
> > + * @clk: The clock to refcount
> > + *
> > + * Before a clock is returned from clk_get, this function should be
> > called + * to update any clock-specific refcounting.
> > + *
> > + * Returns non-zero on success, zero on failure.
> > + *
> > + * Drivers should not need this function; it is only needed by the
> > + * arch-specific clk_get() implementations.
> > + */
> > +int __clk_get(struct clk *clk);
> 
> I don't understand this. Are architectures supposed to provide a
> function called clk_get? Doesn't this break the whole idea of having a
> common struct clk?

clk_get() is now provided in drivers/clk/clkdev.c; the arch-specific part of 
this comment is old (I'll remove it).

Thanks for taking the time to review, I appreciate it.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-08  2:54       ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-08  2:54 UTC (permalink / raw)
  To: Ryan Mallon
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Dima Zavin,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Uwe Kleine-König, Sascha Hauer, Paul Mundt, Saravana Kannan,
	Ben Dooks, Russell King

Hi Ryan,

> > +int clk_prepare(struct clk *clk)
> > +{
> > +	int ret = 0;
> > +
> > +	if (!clk->ops->prepare)
> > +		return 0;
> 
> If there is no ops->prepare function then we never increment
> prepare_count, which means that driver writers can get sloppy if they
> know that ops->prepare is no-op on their platform since they will not
> get warned for omitting clk_prepare.

Yeah, as discussed in other replies, it's probably best that we do the 
counting unconditionally. I've removed these optimisations - I think we'd best 
enforce the checking here, at least at the introduction of this API.
 
> Also, why are the warnings added in a separate patch rather than being
> rolled into this patch?

Just splitting things up; the warnings were the most discussed issue 
previously, so I wanted to separate that discussion from the API side.

> Again, you should still increment enable_count even if ops->enabled is a
> no-op since it provides valuable warnings when clk_enable/disable calls
> are not matched correctly.

Yep, as above.

> > +unsigned long clk_get_rate(struct clk *clk)
> > +{
> > +	if (clk->ops->get_rate)
> > +		return clk->ops->get_rate(clk);
> 
> Possibly we should shadow the clock rate if ops->get_rate is no-op? So
> clock initialisation and clk_set_rate store the rate in the shadow
> field, and then do:
> 
> 	if (clk->ops->get_rate)
> 		return clk->ops->get_rate(clk);
> 	return clk->shadow_rate;
> 
> Because the API is generic, driver writers should reasonably expect that
> clk_get_rate will return something valid without having to know the
> platform implementation details. It may also be worth having a warning
> to let the user know that the returned rate may be approximate.

I'd prefer to require that get_rate is implemented as an op, rather than 
allowing two methods for retrieving the rate of the clock.

> > +	return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(clk_get_rate);
> > +
> > +int __clk_get(struct clk *clk)
> > +{
> > +	if (clk->ops->get)
> > +		return clk->ops->get(clk);
> > +	return 1;
> > +}
> > +EXPORT_SYMBOL_GPL(__clk_get);
> > +
> > +void clk_put(struct clk *clk)
> > +{
> > +	if (clk->ops->put)
> > +		clk->ops->put(clk);
> > +}
> > +EXPORT_SYMBOL_GPL(clk_put);
> 
> This has probably been covered, and I have probably missed it, but why
> don't the generic clk_get/put functions do ref-counting? Drivers must
> have matched clk_get/put calls so it should work like enable/prepare
> counting right?

clk_get is used to find a clock; most implementations will not use this for 
refcounting.

However, for the case where clocks are dynamically allocated, we need clk_put 
to do any possible freeing. There's an existing API for this type of reference 
counting (kref), so for the cases where this matters, the clock 
implementations can use that.

> > + * The choice of atomic or non-atomic clock depends on how the clock is
> > enabled. + * Typically, you'll want to use a non-atomic clock. For
> > clocks that need to be + * enabled/disabled in interrupt context, use
> > CLK_ATOMIC. Note that atomic + * clocks with parents will typically
> > cascade enable/disable operations to + * their parent, so the parent of
> > an atomic clock *must* be atomic too.
> 
> This comment seems out of date now that we have the prepare/enable
> semantics?

Yep, will update.

> > + * @unprepare:	Release the clock from its prepared state. This will
> > typically + *		undo any work done in the @prepare callback. Called 
> > with + *		clk->prepare_lock held.
> 
> I think you need to make it more clear the prepare/unprepare must be
> called from a sleepable context.

The documentation on clk_ops is intended for the clock implementor, so it's 
not really the right place to descibe the caller's requirements.

Indeed, the documentation for clk_prepare & clk_unprepare describe the 
caller's requirements for these (and contain the words "This function may 
sleep").

> > + * Typically, drivers will call clk_prepare when a clock may be needed
> > later + * (eg. when a device is opened), and clk_enable when the clock
> > is actually + * required (eg. from an interrupt).
> 
> Drivers _must_ call clk_prepare before clk_enable (not typically)?

This 'typically' is about the actual placement of the clk_prepare and 
clk_enable calls in the driver code, but I will clarify.

> > +/**
> > + * __clk_get - update clock-specific refcounter
> > + *
> > + * @clk: The clock to refcount
> > + *
> > + * Before a clock is returned from clk_get, this function should be
> > called + * to update any clock-specific refcounting.
> > + *
> > + * Returns non-zero on success, zero on failure.
> > + *
> > + * Drivers should not need this function; it is only needed by the
> > + * arch-specific clk_get() implementations.
> > + */
> > +int __clk_get(struct clk *clk);
> 
> I don't understand this. Are architectures supposed to provide a
> function called clk_get? Doesn't this break the whole idea of having a
> common struct clk?

clk_get() is now provided in drivers/clk/clkdev.c; the arch-specific part of 
this comment is old (I'll remove it).

Thanks for taking the time to review, I appreciate it.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-08  2:54       ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-08  2:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ryan,

> > +int clk_prepare(struct clk *clk)
> > +{
> > +	int ret = 0;
> > +
> > +	if (!clk->ops->prepare)
> > +		return 0;
> 
> If there is no ops->prepare function then we never increment
> prepare_count, which means that driver writers can get sloppy if they
> know that ops->prepare is no-op on their platform since they will not
> get warned for omitting clk_prepare.

Yeah, as discussed in other replies, it's probably best that we do the 
counting unconditionally. I've removed these optimisations - I think we'd best 
enforce the checking here, at least at the introduction of this API.
 
> Also, why are the warnings added in a separate patch rather than being
> rolled into this patch?

Just splitting things up; the warnings were the most discussed issue 
previously, so I wanted to separate that discussion from the API side.

> Again, you should still increment enable_count even if ops->enabled is a
> no-op since it provides valuable warnings when clk_enable/disable calls
> are not matched correctly.

Yep, as above.

> > +unsigned long clk_get_rate(struct clk *clk)
> > +{
> > +	if (clk->ops->get_rate)
> > +		return clk->ops->get_rate(clk);
> 
> Possibly we should shadow the clock rate if ops->get_rate is no-op? So
> clock initialisation and clk_set_rate store the rate in the shadow
> field, and then do:
> 
> 	if (clk->ops->get_rate)
> 		return clk->ops->get_rate(clk);
> 	return clk->shadow_rate;
> 
> Because the API is generic, driver writers should reasonably expect that
> clk_get_rate will return something valid without having to know the
> platform implementation details. It may also be worth having a warning
> to let the user know that the returned rate may be approximate.

I'd prefer to require that get_rate is implemented as an op, rather than 
allowing two methods for retrieving the rate of the clock.

> > +	return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(clk_get_rate);
> > +
> > +int __clk_get(struct clk *clk)
> > +{
> > +	if (clk->ops->get)
> > +		return clk->ops->get(clk);
> > +	return 1;
> > +}
> > +EXPORT_SYMBOL_GPL(__clk_get);
> > +
> > +void clk_put(struct clk *clk)
> > +{
> > +	if (clk->ops->put)
> > +		clk->ops->put(clk);
> > +}
> > +EXPORT_SYMBOL_GPL(clk_put);
> 
> This has probably been covered, and I have probably missed it, but why
> don't the generic clk_get/put functions do ref-counting? Drivers must
> have matched clk_get/put calls so it should work like enable/prepare
> counting right?

clk_get is used to find a clock; most implementations will not use this for 
refcounting.

However, for the case where clocks are dynamically allocated, we need clk_put 
to do any possible freeing. There's an existing API for this type of reference 
counting (kref), so for the cases where this matters, the clock 
implementations can use that.

> > + * The choice of atomic or non-atomic clock depends on how the clock is
> > enabled. + * Typically, you'll want to use a non-atomic clock. For
> > clocks that need to be + * enabled/disabled in interrupt context, use
> > CLK_ATOMIC. Note that atomic + * clocks with parents will typically
> > cascade enable/disable operations to + * their parent, so the parent of
> > an atomic clock *must* be atomic too.
> 
> This comment seems out of date now that we have the prepare/enable
> semantics?

Yep, will update.

> > + * @unprepare:	Release the clock from its prepared state. This will
> > typically + *		undo any work done in the @prepare callback. Called 
> > with + *		clk->prepare_lock held.
> 
> I think you need to make it more clear the prepare/unprepare must be
> called from a sleepable context.

The documentation on clk_ops is intended for the clock implementor, so it's 
not really the right place to descibe the caller's requirements.

Indeed, the documentation for clk_prepare & clk_unprepare describe the 
caller's requirements for these (and contain the words "This function may 
sleep").

> > + * Typically, drivers will call clk_prepare when a clock may be needed
> > later + * (eg. when a device is opened), and clk_enable when the clock
> > is actually + * required (eg. from an interrupt).
> 
> Drivers _must_ call clk_prepare before clk_enable (not typically)?

This 'typically' is about the actual placement of the clk_prepare and 
clk_enable calls in the driver code, but I will clarify.

> > +/**
> > + * __clk_get - update clock-specific refcounter
> > + *
> > + * @clk: The clock to refcount
> > + *
> > + * Before a clock is returned from clk_get, this function should be
> > called + * to update any clock-specific refcounting.
> > + *
> > + * Returns non-zero on success, zero on failure.
> > + *
> > + * Drivers should not need this function; it is only needed by the
> > + * arch-specific clk_get() implementations.
> > + */
> > +int __clk_get(struct clk *clk);
> 
> I don't understand this. Are architectures supposed to provide a
> function called clk_get? Doesn't this break the whole idea of having a
> common struct clk?

clk_get() is now provided in drivers/clk/clkdev.c; the arch-specific part of 
this comment is old (I'll remove it).

Thanks for taking the time to review, I appreciate it.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-08  2:54       ` Jeremy Kerr
  (?)
@ 2011-02-08  3:30         ` Ryan Mallon
  -1 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-08  3:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/08/2011 03:54 PM, Jeremy Kerr wrote:
> Hi Ryan,
> 
>>> +unsigned long clk_get_rate(struct clk *clk)
>>> +{
>>> +	if (clk->ops->get_rate)
>>> +		return clk->ops->get_rate(clk);
>>
>> Possibly we should shadow the clock rate if ops->get_rate is no-op? So
>> clock initialisation and clk_set_rate store the rate in the shadow
>> field, and then do:
>>
>> 	if (clk->ops->get_rate)
>> 		return clk->ops->get_rate(clk);
>> 	return clk->shadow_rate;
>>
>> Because the API is generic, driver writers should reasonably expect that
>> clk_get_rate will return something valid without having to know the
>> platform implementation details. It may also be worth having a warning
>> to let the user know that the returned rate may be approximate.
> 
> I'd prefer to require that get_rate is implemented as an op, rather than 
> allowing two methods for retrieving the rate of the clock.

If a platform does not provide ops->get_rate and a driver writer does
not know this, they could naively use the 0 return from clk_get_rate in
calculations, which is especially bad if they ever divide by the rate.
At the very least the documentation for clk_get_rate should state that
the return value needs to be checked and that 0 means the rate is unknown.

> 
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(clk_get_rate);
>>> +
>>> +int __clk_get(struct clk *clk)
>>> +{
>>> +	if (clk->ops->get)
>>> +		return clk->ops->get(clk);
>>> +	return 1;
>>> +}
>>> +EXPORT_SYMBOL_GPL(__clk_get);
>>> +
>>> +void clk_put(struct clk *clk)
>>> +{
>>> +	if (clk->ops->put)
>>> +		clk->ops->put(clk);
>>> +}
>>> +EXPORT_SYMBOL_GPL(clk_put);
>>
>> This has probably been covered, and I have probably missed it, but why
>> don't the generic clk_get/put functions do ref-counting? Drivers must
>> have matched clk_get/put calls so it should work like enable/prepare
>> counting right?
> 
> clk_get is used to find a clock; most implementations will not use this for 
> refcounting.
> 
> However, for the case where clocks are dynamically allocated, we need clk_put 
> to do any possible freeing. There's an existing API for this type of reference 
> counting (kref), so for the cases where this matters, the clock 
> implementations can use that.

Ah, I see how the clkdev part fits in now. You are correct, the ref
counting is only needed/useful for dynamic allocation of clocks and
should therefore be done in the platform specific code.

We do currently have the slightly indirect route to getting a clock of
doing: clk_get -> __clk_get -> clk->ops->get. I'm guessing that the long
term goal is to remove the middle step once everything is using the
common clock api?

Also, how come you decided to keep the clk_get -> __clk_get call in
clkdev.c, but ifdef'ed clk_put? If you just leave clk_put as is in
clkdev.c and change clk_put to __clk_put in the generic clock code then
you need zero changes to clkdev.c

> 
>>> + * The choice of atomic or non-atomic clock depends on how the clock is
>>> enabled. + * Typically, you'll want to use a non-atomic clock. For
>>> clocks that need to be + * enabled/disabled in interrupt context, use
>>> CLK_ATOMIC. Note that atomic + * clocks with parents will typically
>>> cascade enable/disable operations to + * their parent, so the parent of
>>> an atomic clock *must* be atomic too.
>>
>> This comment seems out of date now that we have the prepare/enable
>> semantics?
> 
> Yep, will update.
> 
>>> + * @unprepare:	Release the clock from its prepared state. This will
>>> typically + *		undo any work done in the @prepare callback. Called 
>>> with + *		clk->prepare_lock held.
>>
>> I think you need to make it more clear the prepare/unprepare must be
>> called from a sleepable context.
> 
> The documentation on clk_ops is intended for the clock implementor, so it's 
> not really the right place to descibe the caller's requirements.
> 
> Indeed, the documentation for clk_prepare & clk_unprepare describe the 
> caller's requirements for these (and contain the words "This function may 
> sleep").

Okay. Should we document for the implementer that clk_enable/disable
must not sleep then? I don't think atomically is necessarily the right
word to use here. For example Documentation/serial/driver uses "This
call must not sleep".

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan@bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-08  3:30         ` Ryan Mallon
  0 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-08  3:30 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Dima Zavin,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Uwe Kleine-König, Sascha Hauer, Paul Mundt, Saravana Kannan,
	Ben Dooks, Russell King

On 02/08/2011 03:54 PM, Jeremy Kerr wrote:
> Hi Ryan,
> 
>>> +unsigned long clk_get_rate(struct clk *clk)
>>> +{
>>> +	if (clk->ops->get_rate)
>>> +		return clk->ops->get_rate(clk);
>>
>> Possibly we should shadow the clock rate if ops->get_rate is no-op? So
>> clock initialisation and clk_set_rate store the rate in the shadow
>> field, and then do:
>>
>> 	if (clk->ops->get_rate)
>> 		return clk->ops->get_rate(clk);
>> 	return clk->shadow_rate;
>>
>> Because the API is generic, driver writers should reasonably expect that
>> clk_get_rate will return something valid without having to know the
>> platform implementation details. It may also be worth having a warning
>> to let the user know that the returned rate may be approximate.
> 
> I'd prefer to require that get_rate is implemented as an op, rather than 
> allowing two methods for retrieving the rate of the clock.

If a platform does not provide ops->get_rate and a driver writer does
not know this, they could naively use the 0 return from clk_get_rate in
calculations, which is especially bad if they ever divide by the rate.
At the very least the documentation for clk_get_rate should state that
the return value needs to be checked and that 0 means the rate is unknown.

> 
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(clk_get_rate);
>>> +
>>> +int __clk_get(struct clk *clk)
>>> +{
>>> +	if (clk->ops->get)
>>> +		return clk->ops->get(clk);
>>> +	return 1;
>>> +}
>>> +EXPORT_SYMBOL_GPL(__clk_get);
>>> +
>>> +void clk_put(struct clk *clk)
>>> +{
>>> +	if (clk->ops->put)
>>> +		clk->ops->put(clk);
>>> +}
>>> +EXPORT_SYMBOL_GPL(clk_put);
>>
>> This has probably been covered, and I have probably missed it, but why
>> don't the generic clk_get/put functions do ref-counting? Drivers must
>> have matched clk_get/put calls so it should work like enable/prepare
>> counting right?
> 
> clk_get is used to find a clock; most implementations will not use this for 
> refcounting.
> 
> However, for the case where clocks are dynamically allocated, we need clk_put 
> to do any possible freeing. There's an existing API for this type of reference 
> counting (kref), so for the cases where this matters, the clock 
> implementations can use that.

Ah, I see how the clkdev part fits in now. You are correct, the ref
counting is only needed/useful for dynamic allocation of clocks and
should therefore be done in the platform specific code.

We do currently have the slightly indirect route to getting a clock of
doing: clk_get -> __clk_get -> clk->ops->get. I'm guessing that the long
term goal is to remove the middle step once everything is using the
common clock api?

Also, how come you decided to keep the clk_get -> __clk_get call in
clkdev.c, but ifdef'ed clk_put? If you just leave clk_put as is in
clkdev.c and change clk_put to __clk_put in the generic clock code then
you need zero changes to clkdev.c

> 
>>> + * The choice of atomic or non-atomic clock depends on how the clock is
>>> enabled. + * Typically, you'll want to use a non-atomic clock. For
>>> clocks that need to be + * enabled/disabled in interrupt context, use
>>> CLK_ATOMIC. Note that atomic + * clocks with parents will typically
>>> cascade enable/disable operations to + * their parent, so the parent of
>>> an atomic clock *must* be atomic too.
>>
>> This comment seems out of date now that we have the prepare/enable
>> semantics?
> 
> Yep, will update.
> 
>>> + * @unprepare:	Release the clock from its prepared state. This will
>>> typically + *		undo any work done in the @prepare callback. Called 
>>> with + *		clk->prepare_lock held.
>>
>> I think you need to make it more clear the prepare/unprepare must be
>> called from a sleepable context.
> 
> The documentation on clk_ops is intended for the clock implementor, so it's 
> not really the right place to descibe the caller's requirements.
> 
> Indeed, the documentation for clk_prepare & clk_unprepare describe the 
> caller's requirements for these (and contain the words "This function may 
> sleep").

Okay. Should we document for the implementer that clk_enable/disable
must not sleep then? I don't think atomically is necessarily the right
word to use here. For example Documentation/serial/driver uses "This
call must not sleep".

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan@bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-08  3:30         ` Ryan Mallon
  0 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-08  3:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/08/2011 03:54 PM, Jeremy Kerr wrote:
> Hi Ryan,
> 
>>> +unsigned long clk_get_rate(struct clk *clk)
>>> +{
>>> +	if (clk->ops->get_rate)
>>> +		return clk->ops->get_rate(clk);
>>
>> Possibly we should shadow the clock rate if ops->get_rate is no-op? So
>> clock initialisation and clk_set_rate store the rate in the shadow
>> field, and then do:
>>
>> 	if (clk->ops->get_rate)
>> 		return clk->ops->get_rate(clk);
>> 	return clk->shadow_rate;
>>
>> Because the API is generic, driver writers should reasonably expect that
>> clk_get_rate will return something valid without having to know the
>> platform implementation details. It may also be worth having a warning
>> to let the user know that the returned rate may be approximate.
> 
> I'd prefer to require that get_rate is implemented as an op, rather than 
> allowing two methods for retrieving the rate of the clock.

If a platform does not provide ops->get_rate and a driver writer does
not know this, they could naively use the 0 return from clk_get_rate in
calculations, which is especially bad if they ever divide by the rate.
At the very least the documentation for clk_get_rate should state that
the return value needs to be checked and that 0 means the rate is unknown.

> 
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(clk_get_rate);
>>> +
>>> +int __clk_get(struct clk *clk)
>>> +{
>>> +	if (clk->ops->get)
>>> +		return clk->ops->get(clk);
>>> +	return 1;
>>> +}
>>> +EXPORT_SYMBOL_GPL(__clk_get);
>>> +
>>> +void clk_put(struct clk *clk)
>>> +{
>>> +	if (clk->ops->put)
>>> +		clk->ops->put(clk);
>>> +}
>>> +EXPORT_SYMBOL_GPL(clk_put);
>>
>> This has probably been covered, and I have probably missed it, but why
>> don't the generic clk_get/put functions do ref-counting? Drivers must
>> have matched clk_get/put calls so it should work like enable/prepare
>> counting right?
> 
> clk_get is used to find a clock; most implementations will not use this for 
> refcounting.
> 
> However, for the case where clocks are dynamically allocated, we need clk_put 
> to do any possible freeing. There's an existing API for this type of reference 
> counting (kref), so for the cases where this matters, the clock 
> implementations can use that.

Ah, I see how the clkdev part fits in now. You are correct, the ref
counting is only needed/useful for dynamic allocation of clocks and
should therefore be done in the platform specific code.

We do currently have the slightly indirect route to getting a clock of
doing: clk_get -> __clk_get -> clk->ops->get. I'm guessing that the long
term goal is to remove the middle step once everything is using the
common clock api?

Also, how come you decided to keep the clk_get -> __clk_get call in
clkdev.c, but ifdef'ed clk_put? If you just leave clk_put as is in
clkdev.c and change clk_put to __clk_put in the generic clock code then
you need zero changes to clkdev.c

> 
>>> + * The choice of atomic or non-atomic clock depends on how the clock is
>>> enabled. + * Typically, you'll want to use a non-atomic clock. For
>>> clocks that need to be + * enabled/disabled in interrupt context, use
>>> CLK_ATOMIC. Note that atomic + * clocks with parents will typically
>>> cascade enable/disable operations to + * their parent, so the parent of
>>> an atomic clock *must* be atomic too.
>>
>> This comment seems out of date now that we have the prepare/enable
>> semantics?
> 
> Yep, will update.
> 
>>> + * @unprepare:	Release the clock from its prepared state. This will
>>> typically + *		undo any work done in the @prepare callback. Called 
>>> with + *		clk->prepare_lock held.
>>
>> I think you need to make it more clear the prepare/unprepare must be
>> called from a sleepable context.
> 
> The documentation on clk_ops is intended for the clock implementor, so it's 
> not really the right place to descibe the caller's requirements.
> 
> Indeed, the documentation for clk_prepare & clk_unprepare describe the 
> caller's requirements for these (and contain the words "This function may 
> sleep").

Okay. Should we document for the implementer that clk_enable/disable
must not sleep then? I don't think atomically is necessarily the right
word to use here. For example Documentation/serial/driver uses "This
call must not sleep".

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-08  3:30         ` Ryan Mallon
  (?)
@ 2011-02-08  7:28           ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-08  7:28 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ryan,

> If a platform does not provide ops->get_rate and a driver writer does
> not know this, they could naively use the 0 return from clk_get_rate in
> calculations, which is especially bad if they ever divide by the rate.

This would be fairly evident on first boot though :)

> At the very least the documentation for clk_get_rate should state that
> the return value needs to be checked and that 0 means the rate is unknown.

Yes, sounds good. I was hesitant to change the documentation for parts of the 
API that are unchanged, but since we're formalising this 'return 0' behaviour, 
it seems reasonable to update the comment in this case.

> We do currently have the slightly indirect route to getting a clock of
> doing: clk_get -> __clk_get -> clk->ops->get. I'm guessing that the long
> term goal is to remove the middle step once everything is using the
> common clock api?

That may never happen; I imagine that some platforms won't be converted at 
all.

 __clk_get has previously been used as a platform-specific hook to do 
refcounting, which is exactly what we're doing here (via ops->get), so thought 
it was best to use the existing __clk_get name to do this.

> Also, how come you decided to keep the clk_get -> __clk_get call in
> clkdev.c, but ifdef'ed clk_put? If you just leave clk_put as is in
> clkdev.c and change clk_put to __clk_put in the generic clock code then
> you need zero changes to clkdev.c

Yep, makes sense, I'll look at doing this.

> Okay. Should we document for the implementer that clk_enable/disable
> must not sleep then? I don't think atomically is necessarily the right
> word to use here. For example Documentation/serial/driver uses "This
> call must not sleep".

OK, I'll clarify the comment.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-08  7:28           ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-08  7:28 UTC (permalink / raw)
  To: Ryan Mallon
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Dima Zavin,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Uwe Kleine-König, Sascha Hauer, Paul Mundt, Saravana Kannan,
	Ben Dooks, Russell King

Hi Ryan,

> If a platform does not provide ops->get_rate and a driver writer does
> not know this, they could naively use the 0 return from clk_get_rate in
> calculations, which is especially bad if they ever divide by the rate.

This would be fairly evident on first boot though :)

> At the very least the documentation for clk_get_rate should state that
> the return value needs to be checked and that 0 means the rate is unknown.

Yes, sounds good. I was hesitant to change the documentation for parts of the 
API that are unchanged, but since we're formalising this 'return 0' behaviour, 
it seems reasonable to update the comment in this case.

> We do currently have the slightly indirect route to getting a clock of
> doing: clk_get -> __clk_get -> clk->ops->get. I'm guessing that the long
> term goal is to remove the middle step once everything is using the
> common clock api?

That may never happen; I imagine that some platforms won't be converted at 
all.

 __clk_get has previously been used as a platform-specific hook to do 
refcounting, which is exactly what we're doing here (via ops->get), so thought 
it was best to use the existing __clk_get name to do this.

> Also, how come you decided to keep the clk_get -> __clk_get call in
> clkdev.c, but ifdef'ed clk_put? If you just leave clk_put as is in
> clkdev.c and change clk_put to __clk_put in the generic clock code then
> you need zero changes to clkdev.c

Yep, makes sense, I'll look at doing this.

> Okay. Should we document for the implementer that clk_enable/disable
> must not sleep then? I don't think atomically is necessarily the right
> word to use here. For example Documentation/serial/driver uses "This
> call must not sleep".

OK, I'll clarify the comment.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-08  7:28           ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-08  7:28 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ryan,

> If a platform does not provide ops->get_rate and a driver writer does
> not know this, they could naively use the 0 return from clk_get_rate in
> calculations, which is especially bad if they ever divide by the rate.

This would be fairly evident on first boot though :)

> At the very least the documentation for clk_get_rate should state that
> the return value needs to be checked and that 0 means the rate is unknown.

Yes, sounds good. I was hesitant to change the documentation for parts of the 
API that are unchanged, but since we're formalising this 'return 0' behaviour, 
it seems reasonable to update the comment in this case.

> We do currently have the slightly indirect route to getting a clock of
> doing: clk_get -> __clk_get -> clk->ops->get. I'm guessing that the long
> term goal is to remove the middle step once everything is using the
> common clock api?

That may never happen; I imagine that some platforms won't be converted at 
all.

 __clk_get has previously been used as a platform-specific hook to do 
refcounting, which is exactly what we're doing here (via ops->get), so thought 
it was best to use the existing __clk_get name to do this.

> Also, how come you decided to keep the clk_get -> __clk_get call in
> clkdev.c, but ifdef'ed clk_put? If you just leave clk_put as is in
> clkdev.c and change clk_put to __clk_put in the generic clock code then
> you need zero changes to clkdev.c

Yep, makes sense, I'll look at doing this.

> Okay. Should we document for the implementer that clk_enable/disable
> must not sleep then? I don't think atomically is necessarily the right
> word to use here. For example Documentation/serial/driver uses "This
> call must not sleep".

OK, I'll clarify the comment.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
  2011-02-09  6:41   ` Jeremy Kerr
  (?)
@ 2011-02-09  6:41     ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-09  6:41 UTC (permalink / raw)
  To: linux-arm-kernel

Since most platforms will need a fixed-rate clock, add one. This will
also serve as a basic example of an implementation of struct clk.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/clk.c   |   14 ++++++++++++++
 include/linux/clk.h |   16 ++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index c35478a..bbbdb0d 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -124,3 +124,17 @@ void __clk_put(struct clk *clk)
 	if (clk->ops->put)
 		clk->ops->put(clk);
 }
+
+/* clk_fixed support */
+
+#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
+
+static unsigned long clk_fixed_get_rate(struct clk *clk)
+{
+	return to_clk_fixed(clk)->rate;
+}
+
+struct clk_ops clk_fixed_ops = {
+	.get_rate = clk_fixed_get_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index fe806b7..e67fdb0 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -185,6 +185,22 @@ static inline void clk_common_init(struct clk *clk)
 	mutex_init(&clk->prepare_lock);
 }
 
+/* Simple fixed-rate clock */
+struct clk_fixed {
+	struct clk	clk;
+	unsigned long	rate;
+};
+
+extern struct clk_ops clk_fixed_ops;
+
+#define INIT_CLK_FIXED(name, r) { \
+	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
+	.rate = (r) \
+}
+
+#define DEFINE_CLK_FIXED(name, r) \
+	struct clk_fixed name = INIT_CLK_FIXED(name, r)
+
 #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
  2011-02-09  6:41   ` Jeremy Kerr
  (?)
@ 2011-02-09  6:41     ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-09  6:41 UTC (permalink / raw)
  To: linux-arm-kernel

We currently have ~21 definitions of struct clk in the ARM architecture,
each defined on a per-platform basis. This makes it difficult to define
platform- (or architecture-) independent clock sources without making
assumptions about struct clk, and impossible to compile two
platforms with different struct clks into a single image.

This change is an effort to unify struct clk where possible, by defining
a common struct clk, containing a set of clock operations. Different
clock implementations can set their own operations, and have a standard
interface for generic code. The callback interface is exposed to the
kernel proper, while the clock implementations only need to be seen by
the platform internals.

This allows us to share clock code among platforms, and makes it
possible to dynamically create clock devices in platform-independent
code.

Platforms can enable the generic struct clock through
CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
consists of a common struct clk:

struct clk {
	const struct clk_ops	*ops;
	unsigned int		enable_count;
	unsigned int		prepare_count;
	spinlock_t		enable_lock;
	struct mutex		prepare_lock;
};

And a set of clock operations (defined per type of clock):

struct clk_ops {
	int             (*enable)(struct clk *);
	void            (*disable)(struct clk *);
	unsigned long   (*get_rate)(struct clk *);
	[...]
};

To define a hardware-specific clock, machine code can "subclass" the
struct clock into a new struct (adding any device-specific data), and
provide a set of operations:

struct clk_foo {
	struct clk	clk;
	void __iomem	*some_register;
};

struct clk_ops clk_foo_ops = {
	.get_rate = clk_foo_get_rate,
};

The common clock definitions are based on a development patch from Ben
Herrenschmidt <benh@kernel.crashing.org>.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/Kconfig  |    3 
 drivers/clk/Makefile |    1 
 drivers/clk/clk.c    |  126 +++++++++++++++++++++++++++
 include/linux/clk.h  |  194 +++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 315 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 4168c88..6e3ae54 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -2,3 +2,6 @@
 config CLKDEV_LOOKUP
 	bool
 	select HAVE_CLK
+
+config USE_COMMON_STRUCT_CLK
+	bool
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 07613fa..a1a06d3 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,2 +1,3 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
+obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
new file mode 100644
index 0000000..c35478a
--- /dev/null
+++ b/drivers/clk/clk.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+
+int clk_prepare(struct clk *clk)
+{
+	int ret = 0;
+
+	mutex_lock(&clk->prepare_lock);
+	if (clk->prepare_count = 0 && clk->ops->prepare)
+		ret = clk->ops->prepare(clk);
+
+	if (!ret)
+		clk->prepare_count++;
+	mutex_unlock(&clk->prepare_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_prepare);
+
+void clk_unprepare(struct clk *clk)
+{
+	mutex_lock(&clk->prepare_lock);
+
+	WARN_ON(clk->prepare_count = 0);
+
+	if (--clk->prepare_count = 0 && clk->ops->unprepare)
+		clk->ops->unprepare(clk);
+
+	mutex_unlock(&clk->prepare_lock);
+}
+EXPORT_SYMBOL_GPL(clk_unprepare);
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+	if (clk->enable_count = 0 && clk->ops->enable)
+		ret = clk->ops->enable(clk);
+
+	if (!ret)
+		clk->enable_count++;
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+
+	WARN_ON(clk->enable_count = 0);
+
+	if (!--clk->enable_count = 0 && clk->ops->disable)
+		clk->ops->disable(clk);
+
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk->ops->get_rate)
+		return clk->ops->get_rate(clk);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->round_rate)
+		return clk->ops->round_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->set_rate)
+		return clk->ops->set_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (clk->ops->set_parent)
+		return clk->ops->set_parent(clk, parent);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	if (clk->ops->get_parent)
+		return clk->ops->get_parent(clk);
+	return ERR_PTR(-ENOSYS);
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
+
+int __clk_get(struct clk *clk)
+{
+	if (clk->ops->get)
+		return clk->ops->get(clk);
+	return 1;
+}
+
+void __clk_put(struct clk *clk)
+{
+	if (clk->ops->put)
+		clk->ops->put(clk);
+}
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1d37f42..fe806b7 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2004 ARM Limited.
  *  Written by Deep Blue Solutions Limited.
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,18 +12,198 @@
 #ifndef __LINUX_CLK_H
 #define __LINUX_CLK_H
 
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
 struct device;
 
-/*
- * The base API.
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+
+/* If we're using the common struct clk, we define the base clk object here */
+
+/**
+ * struct clk - hardware independent clock structure
+ * @ops:		implementation-specific ops for this clock
+ * @enable_count:	count of clk_enable() calls active on this clock
+ * @enable_lock:	lock for atomic enable
+ * @prepare_count:	count of clk_prepare() calls active on this clock
+ * @prepare_lock:	lock for sleepable prepare
+ *
+ * The base clock object, used by drivers for hardware-independent manipulation
+ * of clock lines. This will be 'subclassed' by device-specific implementations,
+ * which add device-specific data to struct clk. For example:
+ *
+ *  struct clk_foo {
+ *      struct clk;
+ *      [device specific fields]
+ *  };
+ *
+ * The clock driver code will manage the device-specific data, and pass
+ * clk_foo.clk to the common clock code. The clock driver will be called
+ * through the @ops callbacks.
+ *
+ * The @enable_lock and @prepare_lock members are used to serialise accesses
+ * to the ops->enable and ops->prepare functions (and the corresponding
+ * ops->disable and ops->unprepare functions).
+ */
+struct clk {
+	const struct clk_ops	*ops;
+	unsigned int		enable_count;
+	unsigned int		prepare_count;
+	spinlock_t		enable_lock;
+	struct mutex		prepare_lock;
+};
+
+/* static initialiser for clocks */
+#define INIT_CLK(name, o) {						\
+	.ops		= &o,						\
+	.enable_count	= 0,						\
+	.prepare_count	= 0,						\
+	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
+	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
+}
+
+/**
+ * struct clk_ops -  Callback operations for clocks; these are to be provided
+ * by the clock implementation, and will be called by drivers through the clk_*
+ * API.
+ *
+ * @prepare:	Prepare the clock for enabling. This must not return until
+ *		the clock is fully prepared, and it's safe to call clk_enable.
+ *		This callback is intended to allow clock implementations to
+ *		do any initialisation that may block. Called with
+ *		clk->prepare_lock held.
+ *
+ * @unprepare:	Release the clock from its prepared state. This will typically
+ *		undo any work done in the @prepare callback. Called with
+ *		clk->prepare_lock held.
+ *
+ * @enable:	Enable the clock atomically. This must not return until the
+ *		clock is generating a valid clock signal, usable by consumer
+ *		devices. Called with clk->enable_lock held. This function
+ *		must not sleep.
+ *
+ * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
+ *		This function must not sleep.
+ *
+ * @get:	Called by the core clock code when a device driver acquires a
+ *		clock via clk_get(). Optional.
+ *
+ * @put:	Called by the core clock code when a devices driver releases a
+ *		clock via clk_put(). Optional.
+ *
+ * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
+ * implementations to split any work between atomic (enable) and sleepable
+ * (prepare) contexts.  If a clock requires blocking code to be turned on, this
+ * should be done in clk_prepare. Switching that will not block should be done
+ * in clk_enable.
+ *
+ * Typically, drivers will call clk_prepare when a clock may be needed later
+ * (eg. when a device is opened), and clk_enable when the clock is actually
+ * required (eg. from an interrupt). Note that clk_prepare *must* have been
+ * called before clk_enable.
+ *
+ * For other callbacks, see the corresponding clk_* functions. Parameters and
+ * return values are passed directly from/to these API functions, or
+ * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
+ * is NULL, see kernel/clk.c for implementation details. All are optional.
+ */
+struct clk_ops {
+	int		(*prepare)(struct clk *);
+	void		(*unprepare)(struct clk *);
+	int		(*enable)(struct clk *);
+	void		(*disable)(struct clk *);
+	int		(*get)(struct clk *);
+	void		(*put)(struct clk *);
+	unsigned long	(*get_rate)(struct clk *);
+	long		(*round_rate)(struct clk *, unsigned long);
+	int		(*set_rate)(struct clk *, unsigned long);
+	int		(*set_parent)(struct clk *, struct clk *);
+	struct clk *	(*get_parent)(struct clk *);
+};
+
+/**
+ * __clk_get - acquire a reference to a clock
+ *
+ * @clk: The clock to refcount
+ *
+ * Before a clock is returned from clk_get, this function should be called
+ * to update any clock-specific refcounting.
+ *
+ * Returns non-zero on success, zero on failure.
+ *
+ * Drivers should not need this function, it is called by the common clock
+ * infrastructure.
+ */
+int __clk_get(struct clk *clk);
+
+/**
+ * __clk_put - release reference to a clock
+ *
+ * @clk: The clock to release
+ *
+ * Called by clock infrastructure code to indicate that a clock consumer
+ * has released a clock, to update any clock-specific refcounting.
+ *
+ * Drivers should not need this function, it is called by the common clock
+ * infrastructure.
+ */
+void __clk_put(struct clk *clk);
+
+/**
+ * clk_prepare - prepare clock for atomic enabling.
+ *
+ * @clk: The clock to prepare
+ *
+ * Do any blocking initialisation on @clk, allowing the clock to be later
+ * enabled atomically (via clk_enable). This function may sleep.
+ */
+int clk_prepare(struct clk *clk);
+
+/**
+ * clk_unprepare - release clock from prepared state
+ *
+ * @clk: The clock to release
+ *
+ * Do any (possbly blocking) cleanup on clk. This function may sleep.
  */
+void clk_unprepare(struct clk *clk);
 
+/**
+ * clk_common_init - initialise a clock for driver usage
+ *
+ * @clk: The clock to initialise
+ *
+ * Used for runtime intialization of clocks; you don't need to call this
+ * if your clock has been (statically) initialized with INIT_CLK.
+ */
+static inline void clk_common_init(struct clk *clk)
+{
+	clk->enable_count = clk->prepare_count = 0;
+	spin_lock_init(&clk->enable_lock);
+	mutex_init(&clk->prepare_lock);
+}
+
+#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*
- * struct clk - an machine class defined object / cookie.
+ * Global clock object, actual structure is declared per-machine
  */
 struct clk;
 
+static inline void clk_common_init(struct clk *clk) { }
+
+/*
+ * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
+ * requirements for clk_enable/clk_disable, so the prepare and unprepare
+ * functions are no-ops
+ */
+int clk_prepare(struct clk *clk) { return 0; }
+void clk_unprepare(struct clk *clk) { }
+
+#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
+
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
  * @dev: device for clock "consumer"
@@ -67,6 +248,7 @@ void clk_disable(struct clk *clk);
 /**
  * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *		  This is only valid once the clock source has been enabled.
+ *		  Returns zero if the clock rate is unknown.
  * @clk: clock source
  */
 unsigned long clk_get_rate(struct clk *clk);
@@ -83,12 +265,6 @@ unsigned long clk_get_rate(struct clk *clk);
  */
 void clk_put(struct clk *clk);
 
-
-/*
- * The remaining APIs are optional for machine class support.
- */
-
-
 /**
  * clk_round_rate - adjust a rate to the exact rate a clock can provide
  * @clk: clock source

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [RFC,PATCH 0/3] Common struct clk implementation, v12
  2011-02-01  9:11 ` Jeremy Kerr
  (?)
@ 2011-02-09  6:41   ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-09  6:41 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

These patches are an attempt to allow platforms to share clock code. At
present, the definitions of 'struct clk' are local to platform code,
which makes allocating and initialising cross-platform clock sources
difficult, and makes it impossible to compile a single image containing
support for two ARM platforms with different struct clks.

The three patches are for the architecture-independent kernel code,
introducing the common clk infrastructure. The changelog for the first
patch includes details about the new clock definitions.

Ben Herrenschmidt is looking at using common struct clk code for powerpc
too, hence the kernel-wide approach.

Many thanks to the following for their input:
 * Ben Dooks <ben-linux@fluff.org>
 * Baruch Siach <baruch@tkos.co.il>
 * Russell King <linux@arm.linux.org.uk>
 * Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 * Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
 * Vincent Guittot <vincent.guittot@linaro.org>
 * Sascha Hauer <s.hauer@pengutronix.de>
 * Ryan Mallon <ryan@bluewatersys.com>
 * Colin Cross <ccross@google.com>
 * Jassi Brar <jassisinghbrar@gmail.com>

Cheers,


Jeremy

--
v12:
 * Always refcount, even when enable/prepare ops are NULL
 * Unify prepare & enable count checking
 * Update comments for prepare/unprepare
 * Use spin_{lock,unlock}_irqsave
 * Change clk_put to __clk_put, and use the shared clk_put

v11:
 * add prepare/unprepare for non-atomic switching, document atomicity
 * move to drivers/clk/

v10:
 * comment fixups, from Uwe's review
 * added DEFINE_CLK_FIXED

v9:
 * comment improvements
 * kerneldoc fixups
 * add WARN_ON to clk_disable

v8:
 * add atomic clocks, and locking wrappers
 * expand comments on clk and clk_ops

v7:
 * change CLK_INIT to initialise clk->mutex statically

v6:
 * fixed up references to 'clk_operations' in the changelog

v5:
 * uninline main API, and share definitions with !USE_COMMON_STRUCT_CLK
 * add __clk_get
 * delay mutex init
 * kerneldoc for struct clk

v4:
 * use mutex for enable/disable locking
 * DEFINE_CLK -> INIT_CLK, and pass the clk name for mutex init
 * struct clk_operations -> struct clk_ops

v3:
 * do clock usage refcounting in common code
 * provide sample port

v2:
 * no longer ARM-specific
 * use clk_operations

---
Jeremy Kerr (3):
      Add a common struct clk
      clk: Generic support for fixed-rate clocks
      clk: add warnings for incorrect enable/prepare semantics


^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,
  2011-02-09  6:41   ` Jeremy Kerr
  (?)
@ 2011-02-09  6:41     ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-09  6:41 UTC (permalink / raw)
  To: linux-arm-kernel

This change adds warnings to check for:

 1) enabling a clock that hasn't been prepared; and

 2) unpreparing a clock that is still enabled

While the correctness can't be guaranteed, the warnings should cover
most situations, and won't indicate false positives.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/clk.c |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index bbbdb0d..8c96623 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -29,6 +29,8 @@ EXPORT_SYMBOL_GPL(clk_prepare);
 
 void clk_unprepare(struct clk *clk)
 {
+	WARN_ON(clk->enable_count != 0);
+
 	mutex_lock(&clk->prepare_lock);
 
 	WARN_ON(clk->prepare_count = 0);
@@ -45,6 +47,8 @@ int clk_enable(struct clk *clk)
 	unsigned long flags;
 	int ret = 0;
 
+	WARN_ON(clk->prepare_count = 0);
+
 	spin_lock_irqsave(&clk->enable_lock, flags);
 	if (clk->enable_count = 0 && clk->ops->enable)
 		ret = clk->ops->enable(clk);

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-09  6:41     ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-09  6:41 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Uwe Kleine-König, Sascha Hauer,
	Paul Mundt, Saravana Kannan, Ben Dooks, Jeremy Kerr,
	Russell King

This change adds warnings to check for:

 1) enabling a clock that hasn't been prepared; and

 2) unpreparing a clock that is still enabled

While the correctness can't be guaranteed, the warnings should cover
most situations, and won't indicate false positives.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/clk.c |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index bbbdb0d..8c96623 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -29,6 +29,8 @@ EXPORT_SYMBOL_GPL(clk_prepare);
 
 void clk_unprepare(struct clk *clk)
 {
+	WARN_ON(clk->enable_count != 0);
+
 	mutex_lock(&clk->prepare_lock);
 
 	WARN_ON(clk->prepare_count == 0);
@@ -45,6 +47,8 @@ int clk_enable(struct clk *clk)
 	unsigned long flags;
 	int ret = 0;
 
+	WARN_ON(clk->prepare_count == 0);
+
 	spin_lock_irqsave(&clk->enable_lock, flags);
 	if (clk->enable_count == 0 && clk->ops->enable)
 		ret = clk->ops->enable(clk);

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-09  6:41     ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-09  6:41 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Uwe Kleine-König, Sascha Hauer,
	Paul Mundt, Saravana Kannan, Ben Dooks, Jeremy Kerr,
	Russell King

We currently have ~21 definitions of struct clk in the ARM architecture,
each defined on a per-platform basis. This makes it difficult to define
platform- (or architecture-) independent clock sources without making
assumptions about struct clk, and impossible to compile two
platforms with different struct clks into a single image.

This change is an effort to unify struct clk where possible, by defining
a common struct clk, containing a set of clock operations. Different
clock implementations can set their own operations, and have a standard
interface for generic code. The callback interface is exposed to the
kernel proper, while the clock implementations only need to be seen by
the platform internals.

This allows us to share clock code among platforms, and makes it
possible to dynamically create clock devices in platform-independent
code.

Platforms can enable the generic struct clock through
CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
consists of a common struct clk:

struct clk {
	const struct clk_ops	*ops;
	unsigned int		enable_count;
	unsigned int		prepare_count;
	spinlock_t		enable_lock;
	struct mutex		prepare_lock;
};

And a set of clock operations (defined per type of clock):

struct clk_ops {
	int             (*enable)(struct clk *);
	void            (*disable)(struct clk *);
	unsigned long   (*get_rate)(struct clk *);
	[...]
};

To define a hardware-specific clock, machine code can "subclass" the
struct clock into a new struct (adding any device-specific data), and
provide a set of operations:

struct clk_foo {
	struct clk	clk;
	void __iomem	*some_register;
};

struct clk_ops clk_foo_ops = {
	.get_rate = clk_foo_get_rate,
};

The common clock definitions are based on a development patch from Ben
Herrenschmidt <benh@kernel.crashing.org>.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/Kconfig  |    3 
 drivers/clk/Makefile |    1 
 drivers/clk/clk.c    |  126 +++++++++++++++++++++++++++
 include/linux/clk.h  |  194 +++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 315 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 4168c88..6e3ae54 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -2,3 +2,6 @@
 config CLKDEV_LOOKUP
 	bool
 	select HAVE_CLK
+
+config USE_COMMON_STRUCT_CLK
+	bool
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 07613fa..a1a06d3 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,2 +1,3 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
+obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
new file mode 100644
index 0000000..c35478a
--- /dev/null
+++ b/drivers/clk/clk.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+
+int clk_prepare(struct clk *clk)
+{
+	int ret = 0;
+
+	mutex_lock(&clk->prepare_lock);
+	if (clk->prepare_count == 0 && clk->ops->prepare)
+		ret = clk->ops->prepare(clk);
+
+	if (!ret)
+		clk->prepare_count++;
+	mutex_unlock(&clk->prepare_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_prepare);
+
+void clk_unprepare(struct clk *clk)
+{
+	mutex_lock(&clk->prepare_lock);
+
+	WARN_ON(clk->prepare_count == 0);
+
+	if (--clk->prepare_count == 0 && clk->ops->unprepare)
+		clk->ops->unprepare(clk);
+
+	mutex_unlock(&clk->prepare_lock);
+}
+EXPORT_SYMBOL_GPL(clk_unprepare);
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+	if (clk->enable_count == 0 && clk->ops->enable)
+		ret = clk->ops->enable(clk);
+
+	if (!ret)
+		clk->enable_count++;
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+
+	WARN_ON(clk->enable_count == 0);
+
+	if (!--clk->enable_count == 0 && clk->ops->disable)
+		clk->ops->disable(clk);
+
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk->ops->get_rate)
+		return clk->ops->get_rate(clk);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->round_rate)
+		return clk->ops->round_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->set_rate)
+		return clk->ops->set_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (clk->ops->set_parent)
+		return clk->ops->set_parent(clk, parent);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	if (clk->ops->get_parent)
+		return clk->ops->get_parent(clk);
+	return ERR_PTR(-ENOSYS);
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
+
+int __clk_get(struct clk *clk)
+{
+	if (clk->ops->get)
+		return clk->ops->get(clk);
+	return 1;
+}
+
+void __clk_put(struct clk *clk)
+{
+	if (clk->ops->put)
+		clk->ops->put(clk);
+}
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1d37f42..fe806b7 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2004 ARM Limited.
  *  Written by Deep Blue Solutions Limited.
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,18 +12,198 @@
 #ifndef __LINUX_CLK_H
 #define __LINUX_CLK_H
 
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
 struct device;
 
-/*
- * The base API.
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+
+/* If we're using the common struct clk, we define the base clk object here */
+
+/**
+ * struct clk - hardware independent clock structure
+ * @ops:		implementation-specific ops for this clock
+ * @enable_count:	count of clk_enable() calls active on this clock
+ * @enable_lock:	lock for atomic enable
+ * @prepare_count:	count of clk_prepare() calls active on this clock
+ * @prepare_lock:	lock for sleepable prepare
+ *
+ * The base clock object, used by drivers for hardware-independent manipulation
+ * of clock lines. This will be 'subclassed' by device-specific implementations,
+ * which add device-specific data to struct clk. For example:
+ *
+ *  struct clk_foo {
+ *      struct clk;
+ *      [device specific fields]
+ *  };
+ *
+ * The clock driver code will manage the device-specific data, and pass
+ * clk_foo.clk to the common clock code. The clock driver will be called
+ * through the @ops callbacks.
+ *
+ * The @enable_lock and @prepare_lock members are used to serialise accesses
+ * to the ops->enable and ops->prepare functions (and the corresponding
+ * ops->disable and ops->unprepare functions).
+ */
+struct clk {
+	const struct clk_ops	*ops;
+	unsigned int		enable_count;
+	unsigned int		prepare_count;
+	spinlock_t		enable_lock;
+	struct mutex		prepare_lock;
+};
+
+/* static initialiser for clocks */
+#define INIT_CLK(name, o) {						\
+	.ops		= &o,						\
+	.enable_count	= 0,						\
+	.prepare_count	= 0,						\
+	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
+	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
+}
+
+/**
+ * struct clk_ops -  Callback operations for clocks; these are to be provided
+ * by the clock implementation, and will be called by drivers through the clk_*
+ * API.
+ *
+ * @prepare:	Prepare the clock for enabling. This must not return until
+ *		the clock is fully prepared, and it's safe to call clk_enable.
+ *		This callback is intended to allow clock implementations to
+ *		do any initialisation that may block. Called with
+ *		clk->prepare_lock held.
+ *
+ * @unprepare:	Release the clock from its prepared state. This will typically
+ *		undo any work done in the @prepare callback. Called with
+ *		clk->prepare_lock held.
+ *
+ * @enable:	Enable the clock atomically. This must not return until the
+ *		clock is generating a valid clock signal, usable by consumer
+ *		devices. Called with clk->enable_lock held. This function
+ *		must not sleep.
+ *
+ * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
+ *		This function must not sleep.
+ *
+ * @get:	Called by the core clock code when a device driver acquires a
+ *		clock via clk_get(). Optional.
+ *
+ * @put:	Called by the core clock code when a devices driver releases a
+ *		clock via clk_put(). Optional.
+ *
+ * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
+ * implementations to split any work between atomic (enable) and sleepable
+ * (prepare) contexts.  If a clock requires blocking code to be turned on, this
+ * should be done in clk_prepare. Switching that will not block should be done
+ * in clk_enable.
+ *
+ * Typically, drivers will call clk_prepare when a clock may be needed later
+ * (eg. when a device is opened), and clk_enable when the clock is actually
+ * required (eg. from an interrupt). Note that clk_prepare *must* have been
+ * called before clk_enable.
+ *
+ * For other callbacks, see the corresponding clk_* functions. Parameters and
+ * return values are passed directly from/to these API functions, or
+ * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
+ * is NULL, see kernel/clk.c for implementation details. All are optional.
+ */
+struct clk_ops {
+	int		(*prepare)(struct clk *);
+	void		(*unprepare)(struct clk *);
+	int		(*enable)(struct clk *);
+	void		(*disable)(struct clk *);
+	int		(*get)(struct clk *);
+	void		(*put)(struct clk *);
+	unsigned long	(*get_rate)(struct clk *);
+	long		(*round_rate)(struct clk *, unsigned long);
+	int		(*set_rate)(struct clk *, unsigned long);
+	int		(*set_parent)(struct clk *, struct clk *);
+	struct clk *	(*get_parent)(struct clk *);
+};
+
+/**
+ * __clk_get - acquire a reference to a clock
+ *
+ * @clk: The clock to refcount
+ *
+ * Before a clock is returned from clk_get, this function should be called
+ * to update any clock-specific refcounting.
+ *
+ * Returns non-zero on success, zero on failure.
+ *
+ * Drivers should not need this function, it is called by the common clock
+ * infrastructure.
+ */
+int __clk_get(struct clk *clk);
+
+/**
+ * __clk_put - release reference to a clock
+ *
+ * @clk: The clock to release
+ *
+ * Called by clock infrastructure code to indicate that a clock consumer
+ * has released a clock, to update any clock-specific refcounting.
+ *
+ * Drivers should not need this function, it is called by the common clock
+ * infrastructure.
+ */
+void __clk_put(struct clk *clk);
+
+/**
+ * clk_prepare - prepare clock for atomic enabling.
+ *
+ * @clk: The clock to prepare
+ *
+ * Do any blocking initialisation on @clk, allowing the clock to be later
+ * enabled atomically (via clk_enable). This function may sleep.
+ */
+int clk_prepare(struct clk *clk);
+
+/**
+ * clk_unprepare - release clock from prepared state
+ *
+ * @clk: The clock to release
+ *
+ * Do any (possbly blocking) cleanup on clk. This function may sleep.
  */
+void clk_unprepare(struct clk *clk);
 
+/**
+ * clk_common_init - initialise a clock for driver usage
+ *
+ * @clk: The clock to initialise
+ *
+ * Used for runtime intialization of clocks; you don't need to call this
+ * if your clock has been (statically) initialized with INIT_CLK.
+ */
+static inline void clk_common_init(struct clk *clk)
+{
+	clk->enable_count = clk->prepare_count = 0;
+	spin_lock_init(&clk->enable_lock);
+	mutex_init(&clk->prepare_lock);
+}
+
+#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*
- * struct clk - an machine class defined object / cookie.
+ * Global clock object, actual structure is declared per-machine
  */
 struct clk;
 
+static inline void clk_common_init(struct clk *clk) { }
+
+/*
+ * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
+ * requirements for clk_enable/clk_disable, so the prepare and unprepare
+ * functions are no-ops
+ */
+int clk_prepare(struct clk *clk) { return 0; }
+void clk_unprepare(struct clk *clk) { }
+
+#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
+
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
  * @dev: device for clock "consumer"
@@ -67,6 +248,7 @@ void clk_disable(struct clk *clk);
 /**
  * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *		  This is only valid once the clock source has been enabled.
+ *		  Returns zero if the clock rate is unknown.
  * @clk: clock source
  */
 unsigned long clk_get_rate(struct clk *clk);
@@ -83,12 +265,6 @@ unsigned long clk_get_rate(struct clk *clk);
  */
 void clk_put(struct clk *clk);
 
-
-/*
- * The remaining APIs are optional for machine class support.
- */
-
-
 /**
  * clk_round_rate - adjust a rate to the exact rate a clock can provide
  * @clk: clock source

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [RFC,PATCH 0/3] Common struct clk implementation, v12
@ 2011-02-09  6:41   ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-09  6:41 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Uwe Kleine-König, Sascha Hauer,
	Paul Mundt, Saravana Kannan, Ben Dooks, Jeremy Kerr,
	Russell King

Hi all,

These patches are an attempt to allow platforms to share clock code. At
present, the definitions of 'struct clk' are local to platform code,
which makes allocating and initialising cross-platform clock sources
difficult, and makes it impossible to compile a single image containing
support for two ARM platforms with different struct clks.

The three patches are for the architecture-independent kernel code,
introducing the common clk infrastructure. The changelog for the first
patch includes details about the new clock definitions.

Ben Herrenschmidt is looking at using common struct clk code for powerpc
too, hence the kernel-wide approach.

Many thanks to the following for their input:
 * Ben Dooks <ben-linux@fluff.org>
 * Baruch Siach <baruch@tkos.co.il>
 * Russell King <linux@arm.linux.org.uk>
 * Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 * Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
 * Vincent Guittot <vincent.guittot@linaro.org>
 * Sascha Hauer <s.hauer@pengutronix.de>
 * Ryan Mallon <ryan@bluewatersys.com>
 * Colin Cross <ccross@google.com>
 * Jassi Brar <jassisinghbrar@gmail.com>

Cheers,


Jeremy

--
v12:
 * Always refcount, even when enable/prepare ops are NULL
 * Unify prepare & enable count checking
 * Update comments for prepare/unprepare
 * Use spin_{lock,unlock}_irqsave
 * Change clk_put to __clk_put, and use the shared clk_put

v11:
 * add prepare/unprepare for non-atomic switching, document atomicity
 * move to drivers/clk/

v10:
 * comment fixups, from Uwe's review
 * added DEFINE_CLK_FIXED

v9:
 * comment improvements
 * kerneldoc fixups
 * add WARN_ON to clk_disable

v8:
 * add atomic clocks, and locking wrappers
 * expand comments on clk and clk_ops

v7:
 * change CLK_INIT to initialise clk->mutex statically

v6:
 * fixed up references to 'clk_operations' in the changelog

v5:
 * uninline main API, and share definitions with !USE_COMMON_STRUCT_CLK
 * add __clk_get
 * delay mutex init
 * kerneldoc for struct clk

v4:
 * use mutex for enable/disable locking
 * DEFINE_CLK -> INIT_CLK, and pass the clk name for mutex init
 * struct clk_operations -> struct clk_ops

v3:
 * do clock usage refcounting in common code
 * provide sample port

v2:
 * no longer ARM-specific
 * use clk_operations

---
Jeremy Kerr (3):
      Add a common struct clk
      clk: Generic support for fixed-rate clocks
      clk: add warnings for incorrect enable/prepare semantics


^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
@ 2011-02-09  6:41     ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-09  6:41 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Uwe Kleine-König, Sascha Hauer,
	Paul Mundt, Saravana Kannan, Ben Dooks, Jeremy Kerr,
	Russell King

Since most platforms will need a fixed-rate clock, add one. This will
also serve as a basic example of an implementation of struct clk.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/clk.c   |   14 ++++++++++++++
 include/linux/clk.h |   16 ++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index c35478a..bbbdb0d 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -124,3 +124,17 @@ void __clk_put(struct clk *clk)
 	if (clk->ops->put)
 		clk->ops->put(clk);
 }
+
+/* clk_fixed support */
+
+#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
+
+static unsigned long clk_fixed_get_rate(struct clk *clk)
+{
+	return to_clk_fixed(clk)->rate;
+}
+
+struct clk_ops clk_fixed_ops = {
+	.get_rate = clk_fixed_get_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index fe806b7..e67fdb0 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -185,6 +185,22 @@ static inline void clk_common_init(struct clk *clk)
 	mutex_init(&clk->prepare_lock);
 }
 
+/* Simple fixed-rate clock */
+struct clk_fixed {
+	struct clk	clk;
+	unsigned long	rate;
+};
+
+extern struct clk_ops clk_fixed_ops;
+
+#define INIT_CLK_FIXED(name, r) { \
+	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
+	.rate = (r) \
+}
+
+#define DEFINE_CLK_FIXED(name, r) \
+	struct clk_fixed name = INIT_CLK_FIXED(name, r)
+
 #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-09  6:41     ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-09  6:41 UTC (permalink / raw)
  To: linux-arm-kernel

This change adds warnings to check for:

 1) enabling a clock that hasn't been prepared; and

 2) unpreparing a clock that is still enabled

While the correctness can't be guaranteed, the warnings should cover
most situations, and won't indicate false positives.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/clk.c |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index bbbdb0d..8c96623 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -29,6 +29,8 @@ EXPORT_SYMBOL_GPL(clk_prepare);
 
 void clk_unprepare(struct clk *clk)
 {
+	WARN_ON(clk->enable_count != 0);
+
 	mutex_lock(&clk->prepare_lock);
 
 	WARN_ON(clk->prepare_count == 0);
@@ -45,6 +47,8 @@ int clk_enable(struct clk *clk)
 	unsigned long flags;
 	int ret = 0;
 
+	WARN_ON(clk->prepare_count == 0);
+
 	spin_lock_irqsave(&clk->enable_lock, flags);
 	if (clk->enable_count == 0 && clk->ops->enable)
 		ret = clk->ops->enable(clk);

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [RFC,PATCH 0/3] Common struct clk implementation, v12
@ 2011-02-09  6:41   ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-09  6:41 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

These patches are an attempt to allow platforms to share clock code. At
present, the definitions of 'struct clk' are local to platform code,
which makes allocating and initialising cross-platform clock sources
difficult, and makes it impossible to compile a single image containing
support for two ARM platforms with different struct clks.

The three patches are for the architecture-independent kernel code,
introducing the common clk infrastructure. The changelog for the first
patch includes details about the new clock definitions.

Ben Herrenschmidt is looking at using common struct clk code for powerpc
too, hence the kernel-wide approach.

Many thanks to the following for their input:
 * Ben Dooks <ben-linux@fluff.org>
 * Baruch Siach <baruch@tkos.co.il>
 * Russell King <linux@arm.linux.org.uk>
 * Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
 * Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
 * Vincent Guittot <vincent.guittot@linaro.org>
 * Sascha Hauer <s.hauer@pengutronix.de>
 * Ryan Mallon <ryan@bluewatersys.com>
 * Colin Cross <ccross@google.com>
 * Jassi Brar <jassisinghbrar@gmail.com>

Cheers,


Jeremy

--
v12:
 * Always refcount, even when enable/prepare ops are NULL
 * Unify prepare & enable count checking
 * Update comments for prepare/unprepare
 * Use spin_{lock,unlock}_irqsave
 * Change clk_put to __clk_put, and use the shared clk_put

v11:
 * add prepare/unprepare for non-atomic switching, document atomicity
 * move to drivers/clk/

v10:
 * comment fixups, from Uwe's review
 * added DEFINE_CLK_FIXED

v9:
 * comment improvements
 * kerneldoc fixups
 * add WARN_ON to clk_disable

v8:
 * add atomic clocks, and locking wrappers
 * expand comments on clk and clk_ops

v7:
 * change CLK_INIT to initialise clk->mutex statically

v6:
 * fixed up references to 'clk_operations' in the changelog

v5:
 * uninline main API, and share definitions with !USE_COMMON_STRUCT_CLK
 * add __clk_get
 * delay mutex init
 * kerneldoc for struct clk

v4:
 * use mutex for enable/disable locking
 * DEFINE_CLK -> INIT_CLK, and pass the clk name for mutex init
 * struct clk_operations -> struct clk_ops

v3:
 * do clock usage refcounting in common code
 * provide sample port

v2:
 * no longer ARM-specific
 * use clk_operations

---
Jeremy Kerr (3):
      Add a common struct clk
      clk: Generic support for fixed-rate clocks
      clk: add warnings for incorrect enable/prepare semantics

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
@ 2011-02-09  6:41     ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-09  6:41 UTC (permalink / raw)
  To: linux-arm-kernel

Since most platforms will need a fixed-rate clock, add one. This will
also serve as a basic example of an implementation of struct clk.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/clk.c   |   14 ++++++++++++++
 include/linux/clk.h |   16 ++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index c35478a..bbbdb0d 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -124,3 +124,17 @@ void __clk_put(struct clk *clk)
 	if (clk->ops->put)
 		clk->ops->put(clk);
 }
+
+/* clk_fixed support */
+
+#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
+
+static unsigned long clk_fixed_get_rate(struct clk *clk)
+{
+	return to_clk_fixed(clk)->rate;
+}
+
+struct clk_ops clk_fixed_ops = {
+	.get_rate = clk_fixed_get_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index fe806b7..e67fdb0 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -185,6 +185,22 @@ static inline void clk_common_init(struct clk *clk)
 	mutex_init(&clk->prepare_lock);
 }
 
+/* Simple fixed-rate clock */
+struct clk_fixed {
+	struct clk	clk;
+	unsigned long	rate;
+};
+
+extern struct clk_ops clk_fixed_ops;
+
+#define INIT_CLK_FIXED(name, r) { \
+	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
+	.rate = (r) \
+}
+
+#define DEFINE_CLK_FIXED(name, r) \
+	struct clk_fixed name = INIT_CLK_FIXED(name, r)
+
 #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-09  6:41     ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-09  6:41 UTC (permalink / raw)
  To: linux-arm-kernel

We currently have ~21 definitions of struct clk in the ARM architecture,
each defined on a per-platform basis. This makes it difficult to define
platform- (or architecture-) independent clock sources without making
assumptions about struct clk, and impossible to compile two
platforms with different struct clks into a single image.

This change is an effort to unify struct clk where possible, by defining
a common struct clk, containing a set of clock operations. Different
clock implementations can set their own operations, and have a standard
interface for generic code. The callback interface is exposed to the
kernel proper, while the clock implementations only need to be seen by
the platform internals.

This allows us to share clock code among platforms, and makes it
possible to dynamically create clock devices in platform-independent
code.

Platforms can enable the generic struct clock through
CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
consists of a common struct clk:

struct clk {
	const struct clk_ops	*ops;
	unsigned int		enable_count;
	unsigned int		prepare_count;
	spinlock_t		enable_lock;
	struct mutex		prepare_lock;
};

And a set of clock operations (defined per type of clock):

struct clk_ops {
	int             (*enable)(struct clk *);
	void            (*disable)(struct clk *);
	unsigned long   (*get_rate)(struct clk *);
	[...]
};

To define a hardware-specific clock, machine code can "subclass" the
struct clock into a new struct (adding any device-specific data), and
provide a set of operations:

struct clk_foo {
	struct clk	clk;
	void __iomem	*some_register;
};

struct clk_ops clk_foo_ops = {
	.get_rate = clk_foo_get_rate,
};

The common clock definitions are based on a development patch from Ben
Herrenschmidt <benh@kernel.crashing.org>.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/Kconfig  |    3 
 drivers/clk/Makefile |    1 
 drivers/clk/clk.c    |  126 +++++++++++++++++++++++++++
 include/linux/clk.h  |  194 +++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 315 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 4168c88..6e3ae54 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -2,3 +2,6 @@
 config CLKDEV_LOOKUP
 	bool
 	select HAVE_CLK
+
+config USE_COMMON_STRUCT_CLK
+	bool
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 07613fa..a1a06d3 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,2 +1,3 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
+obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
new file mode 100644
index 0000000..c35478a
--- /dev/null
+++ b/drivers/clk/clk.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+
+int clk_prepare(struct clk *clk)
+{
+	int ret = 0;
+
+	mutex_lock(&clk->prepare_lock);
+	if (clk->prepare_count == 0 && clk->ops->prepare)
+		ret = clk->ops->prepare(clk);
+
+	if (!ret)
+		clk->prepare_count++;
+	mutex_unlock(&clk->prepare_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_prepare);
+
+void clk_unprepare(struct clk *clk)
+{
+	mutex_lock(&clk->prepare_lock);
+
+	WARN_ON(clk->prepare_count == 0);
+
+	if (--clk->prepare_count == 0 && clk->ops->unprepare)
+		clk->ops->unprepare(clk);
+
+	mutex_unlock(&clk->prepare_lock);
+}
+EXPORT_SYMBOL_GPL(clk_unprepare);
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+	if (clk->enable_count == 0 && clk->ops->enable)
+		ret = clk->ops->enable(clk);
+
+	if (!ret)
+		clk->enable_count++;
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+
+	WARN_ON(clk->enable_count == 0);
+
+	if (!--clk->enable_count == 0 && clk->ops->disable)
+		clk->ops->disable(clk);
+
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk->ops->get_rate)
+		return clk->ops->get_rate(clk);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->round_rate)
+		return clk->ops->round_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->set_rate)
+		return clk->ops->set_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (clk->ops->set_parent)
+		return clk->ops->set_parent(clk, parent);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	if (clk->ops->get_parent)
+		return clk->ops->get_parent(clk);
+	return ERR_PTR(-ENOSYS);
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
+
+int __clk_get(struct clk *clk)
+{
+	if (clk->ops->get)
+		return clk->ops->get(clk);
+	return 1;
+}
+
+void __clk_put(struct clk *clk)
+{
+	if (clk->ops->put)
+		clk->ops->put(clk);
+}
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1d37f42..fe806b7 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2004 ARM Limited.
  *  Written by Deep Blue Solutions Limited.
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,18 +12,198 @@
 #ifndef __LINUX_CLK_H
 #define __LINUX_CLK_H
 
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
 struct device;
 
-/*
- * The base API.
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+
+/* If we're using the common struct clk, we define the base clk object here */
+
+/**
+ * struct clk - hardware independent clock structure
+ * @ops:		implementation-specific ops for this clock
+ * @enable_count:	count of clk_enable() calls active on this clock
+ * @enable_lock:	lock for atomic enable
+ * @prepare_count:	count of clk_prepare() calls active on this clock
+ * @prepare_lock:	lock for sleepable prepare
+ *
+ * The base clock object, used by drivers for hardware-independent manipulation
+ * of clock lines. This will be 'subclassed' by device-specific implementations,
+ * which add device-specific data to struct clk. For example:
+ *
+ *  struct clk_foo {
+ *      struct clk;
+ *      [device specific fields]
+ *  };
+ *
+ * The clock driver code will manage the device-specific data, and pass
+ * clk_foo.clk to the common clock code. The clock driver will be called
+ * through the @ops callbacks.
+ *
+ * The @enable_lock and @prepare_lock members are used to serialise accesses
+ * to the ops->enable and ops->prepare functions (and the corresponding
+ * ops->disable and ops->unprepare functions).
+ */
+struct clk {
+	const struct clk_ops	*ops;
+	unsigned int		enable_count;
+	unsigned int		prepare_count;
+	spinlock_t		enable_lock;
+	struct mutex		prepare_lock;
+};
+
+/* static initialiser for clocks */
+#define INIT_CLK(name, o) {						\
+	.ops		= &o,						\
+	.enable_count	= 0,						\
+	.prepare_count	= 0,						\
+	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
+	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
+}
+
+/**
+ * struct clk_ops -  Callback operations for clocks; these are to be provided
+ * by the clock implementation, and will be called by drivers through the clk_*
+ * API.
+ *
+ * @prepare:	Prepare the clock for enabling. This must not return until
+ *		the clock is fully prepared, and it's safe to call clk_enable.
+ *		This callback is intended to allow clock implementations to
+ *		do any initialisation that may block. Called with
+ *		clk->prepare_lock held.
+ *
+ * @unprepare:	Release the clock from its prepared state. This will typically
+ *		undo any work done in the @prepare callback. Called with
+ *		clk->prepare_lock held.
+ *
+ * @enable:	Enable the clock atomically. This must not return until the
+ *		clock is generating a valid clock signal, usable by consumer
+ *		devices. Called with clk->enable_lock held. This function
+ *		must not sleep.
+ *
+ * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
+ *		This function must not sleep.
+ *
+ * @get:	Called by the core clock code when a device driver acquires a
+ *		clock via clk_get(). Optional.
+ *
+ * @put:	Called by the core clock code when a devices driver releases a
+ *		clock via clk_put(). Optional.
+ *
+ * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
+ * implementations to split any work between atomic (enable) and sleepable
+ * (prepare) contexts.  If a clock requires blocking code to be turned on, this
+ * should be done in clk_prepare. Switching that will not block should be done
+ * in clk_enable.
+ *
+ * Typically, drivers will call clk_prepare when a clock may be needed later
+ * (eg. when a device is opened), and clk_enable when the clock is actually
+ * required (eg. from an interrupt). Note that clk_prepare *must* have been
+ * called before clk_enable.
+ *
+ * For other callbacks, see the corresponding clk_* functions. Parameters and
+ * return values are passed directly from/to these API functions, or
+ * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
+ * is NULL, see kernel/clk.c for implementation details. All are optional.
+ */
+struct clk_ops {
+	int		(*prepare)(struct clk *);
+	void		(*unprepare)(struct clk *);
+	int		(*enable)(struct clk *);
+	void		(*disable)(struct clk *);
+	int		(*get)(struct clk *);
+	void		(*put)(struct clk *);
+	unsigned long	(*get_rate)(struct clk *);
+	long		(*round_rate)(struct clk *, unsigned long);
+	int		(*set_rate)(struct clk *, unsigned long);
+	int		(*set_parent)(struct clk *, struct clk *);
+	struct clk *	(*get_parent)(struct clk *);
+};
+
+/**
+ * __clk_get - acquire a reference to a clock
+ *
+ * @clk: The clock to refcount
+ *
+ * Before a clock is returned from clk_get, this function should be called
+ * to update any clock-specific refcounting.
+ *
+ * Returns non-zero on success, zero on failure.
+ *
+ * Drivers should not need this function, it is called by the common clock
+ * infrastructure.
+ */
+int __clk_get(struct clk *clk);
+
+/**
+ * __clk_put - release reference to a clock
+ *
+ * @clk: The clock to release
+ *
+ * Called by clock infrastructure code to indicate that a clock consumer
+ * has released a clock, to update any clock-specific refcounting.
+ *
+ * Drivers should not need this function, it is called by the common clock
+ * infrastructure.
+ */
+void __clk_put(struct clk *clk);
+
+/**
+ * clk_prepare - prepare clock for atomic enabling.
+ *
+ * @clk: The clock to prepare
+ *
+ * Do any blocking initialisation on @clk, allowing the clock to be later
+ * enabled atomically (via clk_enable). This function may sleep.
+ */
+int clk_prepare(struct clk *clk);
+
+/**
+ * clk_unprepare - release clock from prepared state
+ *
+ * @clk: The clock to release
+ *
+ * Do any (possbly blocking) cleanup on clk. This function may sleep.
  */
+void clk_unprepare(struct clk *clk);
 
+/**
+ * clk_common_init - initialise a clock for driver usage
+ *
+ * @clk: The clock to initialise
+ *
+ * Used for runtime intialization of clocks; you don't need to call this
+ * if your clock has been (statically) initialized with INIT_CLK.
+ */
+static inline void clk_common_init(struct clk *clk)
+{
+	clk->enable_count = clk->prepare_count = 0;
+	spin_lock_init(&clk->enable_lock);
+	mutex_init(&clk->prepare_lock);
+}
+
+#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*
- * struct clk - an machine class defined object / cookie.
+ * Global clock object, actual structure is declared per-machine
  */
 struct clk;
 
+static inline void clk_common_init(struct clk *clk) { }
+
+/*
+ * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
+ * requirements for clk_enable/clk_disable, so the prepare and unprepare
+ * functions are no-ops
+ */
+int clk_prepare(struct clk *clk) { return 0; }
+void clk_unprepare(struct clk *clk) { }
+
+#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
+
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
  * @dev: device for clock "consumer"
@@ -67,6 +248,7 @@ void clk_disable(struct clk *clk);
 /**
  * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *		  This is only valid once the clock source has been enabled.
+ *		  Returns zero if the clock rate is unknown.
  * @clk: clock source
  */
 unsigned long clk_get_rate(struct clk *clk);
@@ -83,12 +265,6 @@ unsigned long clk_get_rate(struct clk *clk);
  */
 void clk_put(struct clk *clk);
 
-
-/*
- * The remaining APIs are optional for machine class support.
- */
-
-
 /**
  * clk_round_rate - adjust a rate to the exact rate a clock can provide
  * @clk: clock source

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
  2011-02-09  6:41     ` Jeremy Kerr
  (?)
@ 2011-02-09  6:58       ` Fabio Giovagnini
  -1 siblings, 0 replies; 383+ messages in thread
From: Fabio Giovagnini @ 2011-02-09  6:58 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, guys,
is there a documentation about clk framework?
Or only to read the sources?

Thanks a lot, and best regards


On Wednesday 09 February 2011 07:41:33 Jeremy Kerr wrote:
> Since most platforms will need a fixed-rate clock, add one. This will
> also serve as a basic example of an implementation of struct clk.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/clk.c   |   14 ++++++++++++++
>  include/linux/clk.h |   16 ++++++++++++++++
>  2 files changed, 30 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index c35478a..bbbdb0d 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -124,3 +124,17 @@ void __clk_put(struct clk *clk)
>  	if (clk->ops->put)
>  		clk->ops->put(clk);
>  }
> +
> +/* clk_fixed support */
> +
> +#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
> +
> +static unsigned long clk_fixed_get_rate(struct clk *clk)
> +{
> +	return to_clk_fixed(clk)->rate;
> +}
> +
> +struct clk_ops clk_fixed_ops = {
> +	.get_rate = clk_fixed_get_rate,
> +};
> +EXPORT_SYMBOL_GPL(clk_fixed_ops);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index fe806b7..e67fdb0 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -185,6 +185,22 @@ static inline void clk_common_init(struct clk *clk)
>  	mutex_init(&clk->prepare_lock);
>  }
> 
> +/* Simple fixed-rate clock */
> +struct clk_fixed {
> +	struct clk	clk;
> +	unsigned long	rate;
> +};
> +
> +extern struct clk_ops clk_fixed_ops;
> +
> +#define INIT_CLK_FIXED(name, r) { \
> +	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
> +	.rate = (r) \
> +}
> +
> +#define DEFINE_CLK_FIXED(name, r) \
> +	struct clk_fixed name = INIT_CLK_FIXED(name, r)
> +
>  #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
> 
>  /*
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Ing. Fabio Giovagnini

Aurion s.r.l.
P.I e C.F.
00885711200
skype: aurion.giovagnini
Tel. +39.051.594.78.24
Fax. +39.051.082.14.49
Cell. +39.335.83.50.919
www.aurion-tech.com

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
@ 2011-02-09  6:58       ` Fabio Giovagnini
  0 siblings, 0 replies; 383+ messages in thread
From: Fabio Giovagnini @ 2011-02-09  6:58 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Dima Zavin,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Uwe Kleine-König, Sascha Hauer, Paul Mundt, Saravana Kannan,
	Ben Dooks, Russell King

Hi, guys,
is there a documentation about clk framework?
Or only to read the sources?

Thanks a lot, and best regards


On Wednesday 09 February 2011 07:41:33 Jeremy Kerr wrote:
> Since most platforms will need a fixed-rate clock, add one. This will
> also serve as a basic example of an implementation of struct clk.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/clk.c   |   14 ++++++++++++++
>  include/linux/clk.h |   16 ++++++++++++++++
>  2 files changed, 30 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index c35478a..bbbdb0d 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -124,3 +124,17 @@ void __clk_put(struct clk *clk)
>  	if (clk->ops->put)
>  		clk->ops->put(clk);
>  }
> +
> +/* clk_fixed support */
> +
> +#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
> +
> +static unsigned long clk_fixed_get_rate(struct clk *clk)
> +{
> +	return to_clk_fixed(clk)->rate;
> +}
> +
> +struct clk_ops clk_fixed_ops = {
> +	.get_rate = clk_fixed_get_rate,
> +};
> +EXPORT_SYMBOL_GPL(clk_fixed_ops);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index fe806b7..e67fdb0 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -185,6 +185,22 @@ static inline void clk_common_init(struct clk *clk)
>  	mutex_init(&clk->prepare_lock);
>  }
> 
> +/* Simple fixed-rate clock */
> +struct clk_fixed {
> +	struct clk	clk;
> +	unsigned long	rate;
> +};
> +
> +extern struct clk_ops clk_fixed_ops;
> +
> +#define INIT_CLK_FIXED(name, r) { \
> +	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
> +	.rate = (r) \
> +}
> +
> +#define DEFINE_CLK_FIXED(name, r) \
> +	struct clk_fixed name = INIT_CLK_FIXED(name, r)
> +
>  #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
> 
>  /*
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Ing. Fabio Giovagnini

Aurion s.r.l.
P.I e C.F.
00885711200
skype: aurion.giovagnini
Tel. +39.051.594.78.24
Fax. +39.051.082.14.49
Cell. +39.335.83.50.919
www.aurion-tech.com

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
@ 2011-02-09  6:58       ` Fabio Giovagnini
  0 siblings, 0 replies; 383+ messages in thread
From: Fabio Giovagnini @ 2011-02-09  6:58 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, guys,
is there a documentation about clk framework?
Or only to read the sources?

Thanks a lot, and best regards


On Wednesday 09 February 2011 07:41:33 Jeremy Kerr wrote:
> Since most platforms will need a fixed-rate clock, add one. This will
> also serve as a basic example of an implementation of struct clk.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/clk.c   |   14 ++++++++++++++
>  include/linux/clk.h |   16 ++++++++++++++++
>  2 files changed, 30 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index c35478a..bbbdb0d 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -124,3 +124,17 @@ void __clk_put(struct clk *clk)
>  	if (clk->ops->put)
>  		clk->ops->put(clk);
>  }
> +
> +/* clk_fixed support */
> +
> +#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
> +
> +static unsigned long clk_fixed_get_rate(struct clk *clk)
> +{
> +	return to_clk_fixed(clk)->rate;
> +}
> +
> +struct clk_ops clk_fixed_ops = {
> +	.get_rate = clk_fixed_get_rate,
> +};
> +EXPORT_SYMBOL_GPL(clk_fixed_ops);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index fe806b7..e67fdb0 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -185,6 +185,22 @@ static inline void clk_common_init(struct clk *clk)
>  	mutex_init(&clk->prepare_lock);
>  }
> 
> +/* Simple fixed-rate clock */
> +struct clk_fixed {
> +	struct clk	clk;
> +	unsigned long	rate;
> +};
> +
> +extern struct clk_ops clk_fixed_ops;
> +
> +#define INIT_CLK_FIXED(name, r) { \
> +	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
> +	.rate = (r) \
> +}
> +
> +#define DEFINE_CLK_FIXED(name, r) \
> +	struct clk_fixed name = INIT_CLK_FIXED(name, r)
> +
>  #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
> 
>  /*
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Ing. Fabio Giovagnini

Aurion s.r.l.
P.I e C.F.
00885711200
skype: aurion.giovagnini
Tel. +39.051.594.78.24
Fax. +39.051.082.14.49
Cell. +39.335.83.50.919
www.aurion-tech.com

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-09  6:41     ` Jeremy Kerr
  (?)
@ 2011-02-09  9:00       ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-09  9:00 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jeremy,

On Wed, Feb 09, 2011 at 02:41:33PM +0800, Jeremy Kerr wrote:
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, containing a set of clock operations. Different
> clock implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
> 
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
> 
> And a set of clock operations (defined per type of clock):
> 
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
> 
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
> 
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
> 
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/Kconfig  |    3 
>  drivers/clk/Makefile |    1 
>  drivers/clk/clk.c    |  126 +++++++++++++++++++++++++++
>  include/linux/clk.h  |  194 +++++++++++++++++++++++++++++++++++++++++--
>  4 files changed, 315 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4168c88..6e3ae54 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -2,3 +2,6 @@
>  config CLKDEV_LOOKUP
>  	bool
>  	select HAVE_CLK
> +
> +config USE_COMMON_STRUCT_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..a1a06d3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..c35478a
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,126 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (clk->prepare_count = 0 && clk->ops->prepare)
> +		ret = clk->ops->prepare(clk);
> +
> +	if (!ret)
> +		clk->prepare_count++;
> +	mutex_unlock(&clk->prepare_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	mutex_lock(&clk->prepare_lock);
> +
> +	WARN_ON(clk->prepare_count = 0);
> +
> +	if (--clk->prepare_count = 0 && clk->ops->unprepare)
> +		clk->ops->unprepare(clk);
> +
> +	mutex_unlock(&clk->prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +int clk_enable(struct clk *clk)
> +{
> +	unsigned long flags;
> +	int ret = 0;
> +
> +	spin_lock_irqsave(&clk->enable_lock, flags);
> +	if (clk->enable_count = 0 && clk->ops->enable)
> +		ret = clk->ops->enable(clk);
> +
> +	if (!ret)
> +		clk->enable_count++;
> +	spin_unlock_irqrestore(&clk->enable_lock, flags);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +void clk_disable(struct clk *clk)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&clk->enable_lock, flags);
> +
> +	WARN_ON(clk->enable_count = 0);
> +
> +	if (!--clk->enable_count = 0 && clk->ops->disable)
s/!//

> +		clk->ops->disable(clk);
> +
> +	spin_unlock_irqrestore(&clk->enable_lock, flags);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	if (clk->ops->get_rate)
> +		return clk->ops->get_rate(clk);
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->round_rate)
> +		return clk->ops->round_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->set_rate)
> +		return clk->ops->set_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	if (clk->ops->set_parent)
> +		return clk->ops->set_parent(clk, parent);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	if (clk->ops->get_parent)
> +		return clk->ops->get_parent(clk);
> +	return ERR_PTR(-ENOSYS);
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> +
> +int __clk_get(struct clk *clk)
> +{
> +	if (clk->ops->get)
> +		return clk->ops->get(clk);
> +	return 1;
> +}
> +
> +void __clk_put(struct clk *clk)
> +{
> +	if (clk->ops->put)
> +		clk->ops->put(clk);
> +}
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..fe806b7 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@
>   *
>   *  Copyright (C) 2004 ARM Limited.
>   *  Written by Deep Blue Solutions Limited.
> + *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
> @@ -11,18 +12,198 @@
>  #ifndef __LINUX_CLK_H
>  #define __LINUX_CLK_H
>  
> +#include <linux/err.h>
> +#include <linux/mutex.h>
> +#include <linux/spinlock.h>
> +
>  struct device;
>  
> -/*
> - * The base API.
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> +
> +/* If we're using the common struct clk, we define the base clk object here */
> +
> +/**
> + * struct clk - hardware independent clock structure
> + * @ops:		implementation-specific ops for this clock
> + * @enable_count:	count of clk_enable() calls active on this clock
> + * @enable_lock:	lock for atomic enable
> + * @prepare_count:	count of clk_prepare() calls active on this clock
> + * @prepare_lock:	lock for sleepable prepare
> + *
> + * The base clock object, used by drivers for hardware-independent manipulation
> + * of clock lines. This will be 'subclassed' by device-specific implementations,
> + * which add device-specific data to struct clk. For example:
> + *
> + *  struct clk_foo {
> + *      struct clk;
> + *      [device specific fields]
> + *  };
> + *
> + * The clock driver code will manage the device-specific data, and pass
> + * clk_foo.clk to the common clock code. The clock driver will be called
> + * through the @ops callbacks.
> + *
> + * The @enable_lock and @prepare_lock members are used to serialise accesses
> + * to the ops->enable and ops->prepare functions (and the corresponding
> + * ops->disable and ops->unprepare functions).
> + */
> +struct clk {
> +	const struct clk_ops	*ops;
> +	unsigned int		enable_count;
> +	unsigned int		prepare_count;
> +	spinlock_t		enable_lock;
> +	struct mutex		prepare_lock;
> +};
> +
> +/* static initialiser for clocks */
> +#define INIT_CLK(name, o) {						\
> +	.ops		= &o,						\
> +	.enable_count	= 0,						\
> +	.prepare_count	= 0,						\
> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
> +}
> +
> +/**
> + * struct clk_ops -  Callback operations for clocks; these are to be provided
> + * by the clock implementation, and will be called by drivers through the clk_*
> + * API.
> + *
> + * @prepare:	Prepare the clock for enabling. This must not return until
> + *		the clock is fully prepared, and it's safe to call clk_enable.
> + *		This callback is intended to allow clock implementations to
> + *		do any initialisation that may block. Called with
> + *		clk->prepare_lock held.
> + *
> + * @unprepare:	Release the clock from its prepared state. This will typically
> + *		undo any work done in the @prepare callback. Called with
> + *		clk->prepare_lock held.
> + *
> + * @enable:	Enable the clock atomically. This must not return until the
> + *		clock is generating a valid clock signal, usable by consumer
> + *		devices. Called with clk->enable_lock held. This function
> + *		must not sleep.
> + *
> + * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
> + *		This function must not sleep.
> + *
> + * @get:	Called by the core clock code when a device driver acquires a
> + *		clock via clk_get(). Optional.
> + *
> + * @put:	Called by the core clock code when a devices driver releases a
> + *		clock via clk_put(). Optional.
> + *
> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> + * implementations to split any work between atomic (enable) and sleepable
> + * (prepare) contexts.  If a clock requires blocking code to be turned on, this
> + * should be done in clk_prepare. Switching that will not block should be done
> + * in clk_enable.
> + *
> + * Typically, drivers will call clk_prepare when a clock may be needed later
> + * (eg. when a device is opened), and clk_enable when the clock is actually
> + * required (eg. from an interrupt). Note that clk_prepare *must* have been
> + * called before clk_enable.
> + *
> + * For other callbacks, see the corresponding clk_* functions. Parameters and
> + * return values are passed directly from/to these API functions, or
> + * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
> + * is NULL, see kernel/clk.c for implementation details. All are optional.
> + */
> +struct clk_ops {
> +	int		(*prepare)(struct clk *);
> +	void		(*unprepare)(struct clk *);
> +	int		(*enable)(struct clk *);
> +	void		(*disable)(struct clk *);
> +	int		(*get)(struct clk *);
> +	void		(*put)(struct clk *);
> +	unsigned long	(*get_rate)(struct clk *);
> +	long		(*round_rate)(struct clk *, unsigned long);
> +	int		(*set_rate)(struct clk *, unsigned long);
> +	int		(*set_parent)(struct clk *, struct clk *);
> +	struct clk *	(*get_parent)(struct clk *);
> +};
> +
> +/**
> + * __clk_get - acquire a reference to a clock
> + *
> + * @clk: The clock to refcount
> + *
> + * Before a clock is returned from clk_get, this function should be called
> + * to update any clock-specific refcounting.
> + *
> + * Returns non-zero on success, zero on failure.
> + *
> + * Drivers should not need this function, it is called by the common clock
> + * infrastructure.
> + */
> +int __clk_get(struct clk *clk);
> +
> +/**
> + * __clk_put - release reference to a clock
> + *
> + * @clk: The clock to release
> + *
> + * Called by clock infrastructure code to indicate that a clock consumer
> + * has released a clock, to update any clock-specific refcounting.
> + *
> + * Drivers should not need this function, it is called by the common clock
> + * infrastructure.
> + */
> +void __clk_put(struct clk *clk);
> +
> +/**
> + * clk_prepare - prepare clock for atomic enabling.
> + *
> + * @clk: The clock to prepare
> + *
> + * Do any blocking initialisation on @clk, allowing the clock to be later
> + * enabled atomically (via clk_enable). This function may sleep.
> + */
> +int clk_prepare(struct clk *clk);
> +
> +/**
> + * clk_unprepare - release clock from prepared state
> + *
> + * @clk: The clock to release
> + *
> + * Do any (possbly blocking) cleanup on clk. This function may sleep.
s/possbly/possibly/

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-09  9:00       ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-09  9:00 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Dima Zavin,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Sascha Hauer, Paul Mundt, Saravana Kannan, Ben Dooks,
	Russell King

Hi Jeremy,

On Wed, Feb 09, 2011 at 02:41:33PM +0800, Jeremy Kerr wrote:
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, containing a set of clock operations. Different
> clock implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
> 
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
> 
> And a set of clock operations (defined per type of clock):
> 
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
> 
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
> 
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
> 
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/Kconfig  |    3 
>  drivers/clk/Makefile |    1 
>  drivers/clk/clk.c    |  126 +++++++++++++++++++++++++++
>  include/linux/clk.h  |  194 +++++++++++++++++++++++++++++++++++++++++--
>  4 files changed, 315 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4168c88..6e3ae54 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -2,3 +2,6 @@
>  config CLKDEV_LOOKUP
>  	bool
>  	select HAVE_CLK
> +
> +config USE_COMMON_STRUCT_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..a1a06d3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..c35478a
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,126 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (clk->prepare_count == 0 && clk->ops->prepare)
> +		ret = clk->ops->prepare(clk);
> +
> +	if (!ret)
> +		clk->prepare_count++;
> +	mutex_unlock(&clk->prepare_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	mutex_lock(&clk->prepare_lock);
> +
> +	WARN_ON(clk->prepare_count == 0);
> +
> +	if (--clk->prepare_count == 0 && clk->ops->unprepare)
> +		clk->ops->unprepare(clk);
> +
> +	mutex_unlock(&clk->prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +int clk_enable(struct clk *clk)
> +{
> +	unsigned long flags;
> +	int ret = 0;
> +
> +	spin_lock_irqsave(&clk->enable_lock, flags);
> +	if (clk->enable_count == 0 && clk->ops->enable)
> +		ret = clk->ops->enable(clk);
> +
> +	if (!ret)
> +		clk->enable_count++;
> +	spin_unlock_irqrestore(&clk->enable_lock, flags);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +void clk_disable(struct clk *clk)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&clk->enable_lock, flags);
> +
> +	WARN_ON(clk->enable_count == 0);
> +
> +	if (!--clk->enable_count == 0 && clk->ops->disable)
s/!//

> +		clk->ops->disable(clk);
> +
> +	spin_unlock_irqrestore(&clk->enable_lock, flags);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	if (clk->ops->get_rate)
> +		return clk->ops->get_rate(clk);
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->round_rate)
> +		return clk->ops->round_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->set_rate)
> +		return clk->ops->set_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	if (clk->ops->set_parent)
> +		return clk->ops->set_parent(clk, parent);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	if (clk->ops->get_parent)
> +		return clk->ops->get_parent(clk);
> +	return ERR_PTR(-ENOSYS);
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> +
> +int __clk_get(struct clk *clk)
> +{
> +	if (clk->ops->get)
> +		return clk->ops->get(clk);
> +	return 1;
> +}
> +
> +void __clk_put(struct clk *clk)
> +{
> +	if (clk->ops->put)
> +		clk->ops->put(clk);
> +}
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..fe806b7 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@
>   *
>   *  Copyright (C) 2004 ARM Limited.
>   *  Written by Deep Blue Solutions Limited.
> + *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
> @@ -11,18 +12,198 @@
>  #ifndef __LINUX_CLK_H
>  #define __LINUX_CLK_H
>  
> +#include <linux/err.h>
> +#include <linux/mutex.h>
> +#include <linux/spinlock.h>
> +
>  struct device;
>  
> -/*
> - * The base API.
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> +
> +/* If we're using the common struct clk, we define the base clk object here */
> +
> +/**
> + * struct clk - hardware independent clock structure
> + * @ops:		implementation-specific ops for this clock
> + * @enable_count:	count of clk_enable() calls active on this clock
> + * @enable_lock:	lock for atomic enable
> + * @prepare_count:	count of clk_prepare() calls active on this clock
> + * @prepare_lock:	lock for sleepable prepare
> + *
> + * The base clock object, used by drivers for hardware-independent manipulation
> + * of clock lines. This will be 'subclassed' by device-specific implementations,
> + * which add device-specific data to struct clk. For example:
> + *
> + *  struct clk_foo {
> + *      struct clk;
> + *      [device specific fields]
> + *  };
> + *
> + * The clock driver code will manage the device-specific data, and pass
> + * clk_foo.clk to the common clock code. The clock driver will be called
> + * through the @ops callbacks.
> + *
> + * The @enable_lock and @prepare_lock members are used to serialise accesses
> + * to the ops->enable and ops->prepare functions (and the corresponding
> + * ops->disable and ops->unprepare functions).
> + */
> +struct clk {
> +	const struct clk_ops	*ops;
> +	unsigned int		enable_count;
> +	unsigned int		prepare_count;
> +	spinlock_t		enable_lock;
> +	struct mutex		prepare_lock;
> +};
> +
> +/* static initialiser for clocks */
> +#define INIT_CLK(name, o) {						\
> +	.ops		= &o,						\
> +	.enable_count	= 0,						\
> +	.prepare_count	= 0,						\
> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
> +}
> +
> +/**
> + * struct clk_ops -  Callback operations for clocks; these are to be provided
> + * by the clock implementation, and will be called by drivers through the clk_*
> + * API.
> + *
> + * @prepare:	Prepare the clock for enabling. This must not return until
> + *		the clock is fully prepared, and it's safe to call clk_enable.
> + *		This callback is intended to allow clock implementations to
> + *		do any initialisation that may block. Called with
> + *		clk->prepare_lock held.
> + *
> + * @unprepare:	Release the clock from its prepared state. This will typically
> + *		undo any work done in the @prepare callback. Called with
> + *		clk->prepare_lock held.
> + *
> + * @enable:	Enable the clock atomically. This must not return until the
> + *		clock is generating a valid clock signal, usable by consumer
> + *		devices. Called with clk->enable_lock held. This function
> + *		must not sleep.
> + *
> + * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
> + *		This function must not sleep.
> + *
> + * @get:	Called by the core clock code when a device driver acquires a
> + *		clock via clk_get(). Optional.
> + *
> + * @put:	Called by the core clock code when a devices driver releases a
> + *		clock via clk_put(). Optional.
> + *
> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> + * implementations to split any work between atomic (enable) and sleepable
> + * (prepare) contexts.  If a clock requires blocking code to be turned on, this
> + * should be done in clk_prepare. Switching that will not block should be done
> + * in clk_enable.
> + *
> + * Typically, drivers will call clk_prepare when a clock may be needed later
> + * (eg. when a device is opened), and clk_enable when the clock is actually
> + * required (eg. from an interrupt). Note that clk_prepare *must* have been
> + * called before clk_enable.
> + *
> + * For other callbacks, see the corresponding clk_* functions. Parameters and
> + * return values are passed directly from/to these API functions, or
> + * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
> + * is NULL, see kernel/clk.c for implementation details. All are optional.
> + */
> +struct clk_ops {
> +	int		(*prepare)(struct clk *);
> +	void		(*unprepare)(struct clk *);
> +	int		(*enable)(struct clk *);
> +	void		(*disable)(struct clk *);
> +	int		(*get)(struct clk *);
> +	void		(*put)(struct clk *);
> +	unsigned long	(*get_rate)(struct clk *);
> +	long		(*round_rate)(struct clk *, unsigned long);
> +	int		(*set_rate)(struct clk *, unsigned long);
> +	int		(*set_parent)(struct clk *, struct clk *);
> +	struct clk *	(*get_parent)(struct clk *);
> +};
> +
> +/**
> + * __clk_get - acquire a reference to a clock
> + *
> + * @clk: The clock to refcount
> + *
> + * Before a clock is returned from clk_get, this function should be called
> + * to update any clock-specific refcounting.
> + *
> + * Returns non-zero on success, zero on failure.
> + *
> + * Drivers should not need this function, it is called by the common clock
> + * infrastructure.
> + */
> +int __clk_get(struct clk *clk);
> +
> +/**
> + * __clk_put - release reference to a clock
> + *
> + * @clk: The clock to release
> + *
> + * Called by clock infrastructure code to indicate that a clock consumer
> + * has released a clock, to update any clock-specific refcounting.
> + *
> + * Drivers should not need this function, it is called by the common clock
> + * infrastructure.
> + */
> +void __clk_put(struct clk *clk);
> +
> +/**
> + * clk_prepare - prepare clock for atomic enabling.
> + *
> + * @clk: The clock to prepare
> + *
> + * Do any blocking initialisation on @clk, allowing the clock to be later
> + * enabled atomically (via clk_enable). This function may sleep.
> + */
> +int clk_prepare(struct clk *clk);
> +
> +/**
> + * clk_unprepare - release clock from prepared state
> + *
> + * @clk: The clock to release
> + *
> + * Do any (possbly blocking) cleanup on clk. This function may sleep.
s/possbly/possibly/

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-09  9:00       ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-09  9:00 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jeremy,

On Wed, Feb 09, 2011 at 02:41:33PM +0800, Jeremy Kerr wrote:
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, containing a set of clock operations. Different
> clock implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
> 
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
> 
> And a set of clock operations (defined per type of clock):
> 
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
> 
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
> 
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
> 
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/Kconfig  |    3 
>  drivers/clk/Makefile |    1 
>  drivers/clk/clk.c    |  126 +++++++++++++++++++++++++++
>  include/linux/clk.h  |  194 +++++++++++++++++++++++++++++++++++++++++--
>  4 files changed, 315 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4168c88..6e3ae54 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -2,3 +2,6 @@
>  config CLKDEV_LOOKUP
>  	bool
>  	select HAVE_CLK
> +
> +config USE_COMMON_STRUCT_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..a1a06d3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..c35478a
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,126 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (clk->prepare_count == 0 && clk->ops->prepare)
> +		ret = clk->ops->prepare(clk);
> +
> +	if (!ret)
> +		clk->prepare_count++;
> +	mutex_unlock(&clk->prepare_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	mutex_lock(&clk->prepare_lock);
> +
> +	WARN_ON(clk->prepare_count == 0);
> +
> +	if (--clk->prepare_count == 0 && clk->ops->unprepare)
> +		clk->ops->unprepare(clk);
> +
> +	mutex_unlock(&clk->prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +int clk_enable(struct clk *clk)
> +{
> +	unsigned long flags;
> +	int ret = 0;
> +
> +	spin_lock_irqsave(&clk->enable_lock, flags);
> +	if (clk->enable_count == 0 && clk->ops->enable)
> +		ret = clk->ops->enable(clk);
> +
> +	if (!ret)
> +		clk->enable_count++;
> +	spin_unlock_irqrestore(&clk->enable_lock, flags);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +void clk_disable(struct clk *clk)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&clk->enable_lock, flags);
> +
> +	WARN_ON(clk->enable_count == 0);
> +
> +	if (!--clk->enable_count == 0 && clk->ops->disable)
s/!//

> +		clk->ops->disable(clk);
> +
> +	spin_unlock_irqrestore(&clk->enable_lock, flags);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	if (clk->ops->get_rate)
> +		return clk->ops->get_rate(clk);
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->round_rate)
> +		return clk->ops->round_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->set_rate)
> +		return clk->ops->set_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	if (clk->ops->set_parent)
> +		return clk->ops->set_parent(clk, parent);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	if (clk->ops->get_parent)
> +		return clk->ops->get_parent(clk);
> +	return ERR_PTR(-ENOSYS);
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> +
> +int __clk_get(struct clk *clk)
> +{
> +	if (clk->ops->get)
> +		return clk->ops->get(clk);
> +	return 1;
> +}
> +
> +void __clk_put(struct clk *clk)
> +{
> +	if (clk->ops->put)
> +		clk->ops->put(clk);
> +}
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..fe806b7 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@
>   *
>   *  Copyright (C) 2004 ARM Limited.
>   *  Written by Deep Blue Solutions Limited.
> + *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
> @@ -11,18 +12,198 @@
>  #ifndef __LINUX_CLK_H
>  #define __LINUX_CLK_H
>  
> +#include <linux/err.h>
> +#include <linux/mutex.h>
> +#include <linux/spinlock.h>
> +
>  struct device;
>  
> -/*
> - * The base API.
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> +
> +/* If we're using the common struct clk, we define the base clk object here */
> +
> +/**
> + * struct clk - hardware independent clock structure
> + * @ops:		implementation-specific ops for this clock
> + * @enable_count:	count of clk_enable() calls active on this clock
> + * @enable_lock:	lock for atomic enable
> + * @prepare_count:	count of clk_prepare() calls active on this clock
> + * @prepare_lock:	lock for sleepable prepare
> + *
> + * The base clock object, used by drivers for hardware-independent manipulation
> + * of clock lines. This will be 'subclassed' by device-specific implementations,
> + * which add device-specific data to struct clk. For example:
> + *
> + *  struct clk_foo {
> + *      struct clk;
> + *      [device specific fields]
> + *  };
> + *
> + * The clock driver code will manage the device-specific data, and pass
> + * clk_foo.clk to the common clock code. The clock driver will be called
> + * through the @ops callbacks.
> + *
> + * The @enable_lock and @prepare_lock members are used to serialise accesses
> + * to the ops->enable and ops->prepare functions (and the corresponding
> + * ops->disable and ops->unprepare functions).
> + */
> +struct clk {
> +	const struct clk_ops	*ops;
> +	unsigned int		enable_count;
> +	unsigned int		prepare_count;
> +	spinlock_t		enable_lock;
> +	struct mutex		prepare_lock;
> +};
> +
> +/* static initialiser for clocks */
> +#define INIT_CLK(name, o) {						\
> +	.ops		= &o,						\
> +	.enable_count	= 0,						\
> +	.prepare_count	= 0,						\
> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
> +}
> +
> +/**
> + * struct clk_ops -  Callback operations for clocks; these are to be provided
> + * by the clock implementation, and will be called by drivers through the clk_*
> + * API.
> + *
> + * @prepare:	Prepare the clock for enabling. This must not return until
> + *		the clock is fully prepared, and it's safe to call clk_enable.
> + *		This callback is intended to allow clock implementations to
> + *		do any initialisation that may block. Called with
> + *		clk->prepare_lock held.
> + *
> + * @unprepare:	Release the clock from its prepared state. This will typically
> + *		undo any work done in the @prepare callback. Called with
> + *		clk->prepare_lock held.
> + *
> + * @enable:	Enable the clock atomically. This must not return until the
> + *		clock is generating a valid clock signal, usable by consumer
> + *		devices. Called with clk->enable_lock held. This function
> + *		must not sleep.
> + *
> + * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
> + *		This function must not sleep.
> + *
> + * @get:	Called by the core clock code when a device driver acquires a
> + *		clock via clk_get(). Optional.
> + *
> + * @put:	Called by the core clock code when a devices driver releases a
> + *		clock via clk_put(). Optional.
> + *
> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> + * implementations to split any work between atomic (enable) and sleepable
> + * (prepare) contexts.  If a clock requires blocking code to be turned on, this
> + * should be done in clk_prepare. Switching that will not block should be done
> + * in clk_enable.
> + *
> + * Typically, drivers will call clk_prepare when a clock may be needed later
> + * (eg. when a device is opened), and clk_enable when the clock is actually
> + * required (eg. from an interrupt). Note that clk_prepare *must* have been
> + * called before clk_enable.
> + *
> + * For other callbacks, see the corresponding clk_* functions. Parameters and
> + * return values are passed directly from/to these API functions, or
> + * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
> + * is NULL, see kernel/clk.c for implementation details. All are optional.
> + */
> +struct clk_ops {
> +	int		(*prepare)(struct clk *);
> +	void		(*unprepare)(struct clk *);
> +	int		(*enable)(struct clk *);
> +	void		(*disable)(struct clk *);
> +	int		(*get)(struct clk *);
> +	void		(*put)(struct clk *);
> +	unsigned long	(*get_rate)(struct clk *);
> +	long		(*round_rate)(struct clk *, unsigned long);
> +	int		(*set_rate)(struct clk *, unsigned long);
> +	int		(*set_parent)(struct clk *, struct clk *);
> +	struct clk *	(*get_parent)(struct clk *);
> +};
> +
> +/**
> + * __clk_get - acquire a reference to a clock
> + *
> + * @clk: The clock to refcount
> + *
> + * Before a clock is returned from clk_get, this function should be called
> + * to update any clock-specific refcounting.
> + *
> + * Returns non-zero on success, zero on failure.
> + *
> + * Drivers should not need this function, it is called by the common clock
> + * infrastructure.
> + */
> +int __clk_get(struct clk *clk);
> +
> +/**
> + * __clk_put - release reference to a clock
> + *
> + * @clk: The clock to release
> + *
> + * Called by clock infrastructure code to indicate that a clock consumer
> + * has released a clock, to update any clock-specific refcounting.
> + *
> + * Drivers should not need this function, it is called by the common clock
> + * infrastructure.
> + */
> +void __clk_put(struct clk *clk);
> +
> +/**
> + * clk_prepare - prepare clock for atomic enabling.
> + *
> + * @clk: The clock to prepare
> + *
> + * Do any blocking initialisation on @clk, allowing the clock to be later
> + * enabled atomically (via clk_enable). This function may sleep.
> + */
> +int clk_prepare(struct clk *clk);
> +
> +/**
> + * clk_unprepare - release clock from prepared state
> + *
> + * @clk: The clock to release
> + *
> + * Do any (possbly blocking) cleanup on clk. This function may sleep.
s/possbly/possibly/

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-09  6:41     ` Jeremy Kerr
  (?)
@ 2011-02-09 20:21       ` Ryan Mallon
  -1 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-09 20:21 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/09/2011 07:41 PM, Jeremy Kerr wrote:

Hi Jeremy,

Couple more comments below.

~Ryan

> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, containing a set of clock operations. Different
> clock implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
> 
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
> 
> And a set of clock operations (defined per type of clock):
> 
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
> 
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
> 
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
> 
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/Kconfig  |    3 
>  drivers/clk/Makefile |    1 
>  drivers/clk/clk.c    |  126 +++++++++++++++++++++++++++
>  include/linux/clk.h  |  194 +++++++++++++++++++++++++++++++++++++++++--
>  4 files changed, 315 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4168c88..6e3ae54 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -2,3 +2,6 @@
>  config CLKDEV_LOOKUP
>  	bool
>  	select HAVE_CLK
> +
> +config USE_COMMON_STRUCT_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..a1a06d3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..c35478a
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,126 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (clk->prepare_count = 0 && clk->ops->prepare)
> +		ret = clk->ops->prepare(clk);
> +
> +	if (!ret)
> +		clk->prepare_count++;
> +	mutex_unlock(&clk->prepare_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	mutex_lock(&clk->prepare_lock);
> +
> +	WARN_ON(clk->prepare_count = 0);
> +
> +	if (--clk->prepare_count = 0 && clk->ops->unprepare)
> +		clk->ops->unprepare(clk);
> +
> +	mutex_unlock(&clk->prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +int clk_enable(struct clk *clk)
> +{
> +	unsigned long flags;
> +	int ret = 0;
> +
> +	spin_lock_irqsave(&clk->enable_lock, flags);

	WARN_ON(clk->prepare_count = 0); ?

> +	if (clk->enable_count = 0 && clk->ops->enable)
> +		ret = clk->ops->enable(clk);

Does it make sense to have a clock with no enable function which still
returns success from clk_enable? Do we have any platforms which have
NULL clk_enable functions?

I think that for enable/disable at least we should require platforms to
provide functions and oops if they have failed to do so. In the rare
case that a platform doesn't need to do anything for enable/disable they
can just supply empty functions.

> +
> +	if (!ret)
> +		clk->enable_count++;
> +	spin_unlock_irqrestore(&clk->enable_lock, flags);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +void clk_disable(struct clk *clk)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&clk->enable_lock, flags);
> +
> +	WARN_ON(clk->enable_count = 0);
> +
> +	if (!--clk->enable_count = 0 && clk->ops->disable)
> +		clk->ops->disable(clk);
> +
> +	spin_unlock_irqrestore(&clk->enable_lock, flags);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	if (clk->ops->get_rate)
> +		return clk->ops->get_rate(clk);
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->round_rate)
> +		return clk->ops->round_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->set_rate)
> +		return clk->ops->set_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	if (clk->ops->set_parent)
> +		return clk->ops->set_parent(clk, parent);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	if (clk->ops->get_parent)
> +		return clk->ops->get_parent(clk);
> +	return ERR_PTR(-ENOSYS);
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> +
> +int __clk_get(struct clk *clk)
> +{
> +	if (clk->ops->get)
> +		return clk->ops->get(clk);
> +	return 1;
> +}
> +
> +void __clk_put(struct clk *clk)
> +{
> +	if (clk->ops->put)
> +		clk->ops->put(clk);
> +}
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..fe806b7 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@
>   *
>   *  Copyright (C) 2004 ARM Limited.
>   *  Written by Deep Blue Solutions Limited.
> + *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
> @@ -11,18 +12,198 @@
>  #ifndef __LINUX_CLK_H
>  #define __LINUX_CLK_H
>  
> +#include <linux/err.h>
> +#include <linux/mutex.h>
> +#include <linux/spinlock.h>
> +
>  struct device;
>  
> -/*
> - * The base API.
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> +
> +/* If we're using the common struct clk, we define the base clk object here */
> +
> +/**
> + * struct clk - hardware independent clock structure
> + * @ops:		implementation-specific ops for this clock
> + * @enable_count:	count of clk_enable() calls active on this clock
> + * @enable_lock:	lock for atomic enable
> + * @prepare_count:	count of clk_prepare() calls active on this clock
> + * @prepare_lock:	lock for sleepable prepare
> + *
> + * The base clock object, used by drivers for hardware-independent manipulation
> + * of clock lines. This will be 'subclassed' by device-specific implementations,
> + * which add device-specific data to struct clk. For example:
> + *
> + *  struct clk_foo {
> + *      struct clk;
> + *      [device specific fields]
> + *  };
> + *
> + * The clock driver code will manage the device-specific data, and pass
> + * clk_foo.clk to the common clock code. The clock driver will be called
> + * through the @ops callbacks.
> + *
> + * The @enable_lock and @prepare_lock members are used to serialise accesses
> + * to the ops->enable and ops->prepare functions (and the corresponding
> + * ops->disable and ops->unprepare functions).
> + */
> +struct clk {
> +	const struct clk_ops	*ops;
> +	unsigned int		enable_count;
> +	unsigned int		prepare_count;
> +	spinlock_t		enable_lock;
> +	struct mutex		prepare_lock;
> +};
> +
> +/* static initialiser for clocks */
> +#define INIT_CLK(name, o) {						\
> +	.ops		= &o,						\
> +	.enable_count	= 0,						\
> +	.prepare_count	= 0,						\
> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
> +}
> +
> +/**
> + * struct clk_ops -  Callback operations for clocks; these are to be provided
> + * by the clock implementation, and will be called by drivers through the clk_*
> + * API.
> + *
> + * @prepare:	Prepare the clock for enabling. This must not return until
> + *		the clock is fully prepared, and it's safe to call clk_enable.
> + *		This callback is intended to allow clock implementations to
> + *		do any initialisation that may block. Called with
> + *		clk->prepare_lock held.
> + *
> + * @unprepare:	Release the clock from its prepared state. This will typically
> + *		undo any work done in the @prepare callback. Called with
> + *		clk->prepare_lock held.
> + *
> + * @enable:	Enable the clock atomically. This must not return until the
> + *		clock is generating a valid clock signal, usable by consumer
> + *		devices. Called with clk->enable_lock held. This function
> + *		must not sleep.
> + *
> + * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
> + *		This function must not sleep.
> + *
> + * @get:	Called by the core clock code when a device driver acquires a
> + *		clock via clk_get(). Optional.
> + *
> + * @put:	Called by the core clock code when a devices driver releases a
> + *		clock via clk_put(). Optional.
> + *
> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> + * implementations to split any work between atomic (enable) and sleepable
> + * (prepare) contexts.  If a clock requires blocking code to be turned on, this
> + * should be done in clk_prepare. Switching that will not block should be done
> + * in clk_enable.
> + *
> + * Typically, drivers will call clk_prepare when a clock may be needed later
> + * (eg. when a device is opened), and clk_enable when the clock is actually
> + * required (eg. from an interrupt). Note that clk_prepare *must* have been
> + * called before clk_enable.
> + *
> + * For other callbacks, see the corresponding clk_* functions. Parameters and
> + * return values are passed directly from/to these API functions, or
> + * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
> + * is NULL, see kernel/clk.c for implementation details. All are optional.
> + */
> +struct clk_ops {
> +	int		(*prepare)(struct clk *);
> +	void		(*unprepare)(struct clk *);
> +	int		(*enable)(struct clk *);
> +	void		(*disable)(struct clk *);
> +	int		(*get)(struct clk *);
> +	void		(*put)(struct clk *);
> +	unsigned long	(*get_rate)(struct clk *);
> +	long		(*round_rate)(struct clk *, unsigned long);
> +	int		(*set_rate)(struct clk *, unsigned long);
> +	int		(*set_parent)(struct clk *, struct clk *);
> +	struct clk *	(*get_parent)(struct clk *);
> +};
> +
> +/**
> + * __clk_get - acquire a reference to a clock
> + *
> + * @clk: The clock to refcount
> + *
> + * Before a clock is returned from clk_get, this function should be called
> + * to update any clock-specific refcounting.

This is a bit misleading. It's not "should be called", it "is called". I
think you should just remove the documentation for __clk_get/__clk_put
or move it into clk.c since the functions are only used internally by
the common clock code.

> + *
> + * Returns non-zero on success, zero on failure.
> + *
> + * Drivers should not need this function, it is called by the common clock
> + * infrastructure.
> + */
> +int __clk_get(struct clk *clk);
> +
> +/**
> + * __clk_put - release reference to a clock
> + *
> + * @clk: The clock to release
> + *
> + * Called by clock infrastructure code to indicate that a clock consumer
> + * has released a clock, to update any clock-specific refcounting.
> + *
> + * Drivers should not need this function, it is called by the common clock
> + * infrastructure.
> + */
> +void __clk_put(struct clk *clk);
> +
> +/**
> + * clk_prepare - prepare clock for atomic enabling.
> + *
> + * @clk: The clock to prepare
> + *
> + * Do any blocking initialisation on @clk, allowing the clock to be later
> + * enabled atomically (via clk_enable). This function may sleep.

"Possibly blocking" as below?

> + */
> +int clk_prepare(struct clk *clk);
> +
> +/**
> + * clk_unprepare - release clock from prepared state
> + *
> + * @clk: The clock to release
> + *
> + * Do any (possbly blocking) cleanup on clk. This function may sleep.

Typo "possbly".

>   */
> +void clk_unprepare(struct clk *clk);
>  
> +/**
> + * clk_common_init - initialise a clock for driver usage
> + *
> + * @clk: The clock to initialise
> + *
> + * Used for runtime intialization of clocks; you don't need to call this
> + * if your clock has been (statically) initialized with INIT_CLK.
> + */
> +static inline void clk_common_init(struct clk *clk)
> +{
> +	clk->enable_count = clk->prepare_count = 0;
> +	spin_lock_init(&clk->enable_lock);
> +	mutex_init(&clk->prepare_lock);
> +}
> +
> +#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
>  
>  /*
> - * struct clk - an machine class defined object / cookie.
> + * Global clock object, actual structure is declared per-machine
>   */
>  struct clk;
>  
> +static inline void clk_common_init(struct clk *clk) { }
> +
> +/*
> + * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
> + * requirements for clk_enable/clk_disable, so the prepare and unprepare
> + * functions are no-ops
> + */
> +int clk_prepare(struct clk *clk) { return 0; }
> +void clk_unprepare(struct clk *clk) { }
> +
> +#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
> +
>  /**
>   * clk_get - lookup and obtain a reference to a clock producer.
>   * @dev: device for clock "consumer"
> @@ -67,6 +248,7 @@ void clk_disable(struct clk *clk);
>  /**
>   * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
>   *		  This is only valid once the clock source has been enabled.
> + *		  Returns zero if the clock rate is unknown.
>   * @clk: clock source
>   */
>  unsigned long clk_get_rate(struct clk *clk);
> @@ -83,12 +265,6 @@ unsigned long clk_get_rate(struct clk *clk);
>   */
>  void clk_put(struct clk *clk);
>  
> -
> -/*
> - * The remaining APIs are optional for machine class support.
> - */
> -
> -
>  /**
>   * clk_round_rate - adjust a rate to the exact rate a clock can provide
>   * @clk: clock source
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/


-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan@bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-09 20:21       ` Ryan Mallon
  0 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-09 20:21 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Dima Zavin,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Uwe Kleine-König, Sascha Hauer, Paul Mundt, Saravana Kannan,
	Ben Dooks, Russell King

On 02/09/2011 07:41 PM, Jeremy Kerr wrote:

Hi Jeremy,

Couple more comments below.

~Ryan

> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, containing a set of clock operations. Different
> clock implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
> 
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
> 
> And a set of clock operations (defined per type of clock):
> 
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
> 
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
> 
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
> 
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/Kconfig  |    3 
>  drivers/clk/Makefile |    1 
>  drivers/clk/clk.c    |  126 +++++++++++++++++++++++++++
>  include/linux/clk.h  |  194 +++++++++++++++++++++++++++++++++++++++++--
>  4 files changed, 315 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4168c88..6e3ae54 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -2,3 +2,6 @@
>  config CLKDEV_LOOKUP
>  	bool
>  	select HAVE_CLK
> +
> +config USE_COMMON_STRUCT_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..a1a06d3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..c35478a
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,126 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (clk->prepare_count == 0 && clk->ops->prepare)
> +		ret = clk->ops->prepare(clk);
> +
> +	if (!ret)
> +		clk->prepare_count++;
> +	mutex_unlock(&clk->prepare_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	mutex_lock(&clk->prepare_lock);
> +
> +	WARN_ON(clk->prepare_count == 0);
> +
> +	if (--clk->prepare_count == 0 && clk->ops->unprepare)
> +		clk->ops->unprepare(clk);
> +
> +	mutex_unlock(&clk->prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +int clk_enable(struct clk *clk)
> +{
> +	unsigned long flags;
> +	int ret = 0;
> +
> +	spin_lock_irqsave(&clk->enable_lock, flags);

	WARN_ON(clk->prepare_count == 0); ?

> +	if (clk->enable_count == 0 && clk->ops->enable)
> +		ret = clk->ops->enable(clk);

Does it make sense to have a clock with no enable function which still
returns success from clk_enable? Do we have any platforms which have
NULL clk_enable functions?

I think that for enable/disable at least we should require platforms to
provide functions and oops if they have failed to do so. In the rare
case that a platform doesn't need to do anything for enable/disable they
can just supply empty functions.

> +
> +	if (!ret)
> +		clk->enable_count++;
> +	spin_unlock_irqrestore(&clk->enable_lock, flags);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +void clk_disable(struct clk *clk)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&clk->enable_lock, flags);
> +
> +	WARN_ON(clk->enable_count == 0);
> +
> +	if (!--clk->enable_count == 0 && clk->ops->disable)
> +		clk->ops->disable(clk);
> +
> +	spin_unlock_irqrestore(&clk->enable_lock, flags);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	if (clk->ops->get_rate)
> +		return clk->ops->get_rate(clk);
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->round_rate)
> +		return clk->ops->round_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->set_rate)
> +		return clk->ops->set_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	if (clk->ops->set_parent)
> +		return clk->ops->set_parent(clk, parent);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	if (clk->ops->get_parent)
> +		return clk->ops->get_parent(clk);
> +	return ERR_PTR(-ENOSYS);
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> +
> +int __clk_get(struct clk *clk)
> +{
> +	if (clk->ops->get)
> +		return clk->ops->get(clk);
> +	return 1;
> +}
> +
> +void __clk_put(struct clk *clk)
> +{
> +	if (clk->ops->put)
> +		clk->ops->put(clk);
> +}
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..fe806b7 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@
>   *
>   *  Copyright (C) 2004 ARM Limited.
>   *  Written by Deep Blue Solutions Limited.
> + *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
> @@ -11,18 +12,198 @@
>  #ifndef __LINUX_CLK_H
>  #define __LINUX_CLK_H
>  
> +#include <linux/err.h>
> +#include <linux/mutex.h>
> +#include <linux/spinlock.h>
> +
>  struct device;
>  
> -/*
> - * The base API.
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> +
> +/* If we're using the common struct clk, we define the base clk object here */
> +
> +/**
> + * struct clk - hardware independent clock structure
> + * @ops:		implementation-specific ops for this clock
> + * @enable_count:	count of clk_enable() calls active on this clock
> + * @enable_lock:	lock for atomic enable
> + * @prepare_count:	count of clk_prepare() calls active on this clock
> + * @prepare_lock:	lock for sleepable prepare
> + *
> + * The base clock object, used by drivers for hardware-independent manipulation
> + * of clock lines. This will be 'subclassed' by device-specific implementations,
> + * which add device-specific data to struct clk. For example:
> + *
> + *  struct clk_foo {
> + *      struct clk;
> + *      [device specific fields]
> + *  };
> + *
> + * The clock driver code will manage the device-specific data, and pass
> + * clk_foo.clk to the common clock code. The clock driver will be called
> + * through the @ops callbacks.
> + *
> + * The @enable_lock and @prepare_lock members are used to serialise accesses
> + * to the ops->enable and ops->prepare functions (and the corresponding
> + * ops->disable and ops->unprepare functions).
> + */
> +struct clk {
> +	const struct clk_ops	*ops;
> +	unsigned int		enable_count;
> +	unsigned int		prepare_count;
> +	spinlock_t		enable_lock;
> +	struct mutex		prepare_lock;
> +};
> +
> +/* static initialiser for clocks */
> +#define INIT_CLK(name, o) {						\
> +	.ops		= &o,						\
> +	.enable_count	= 0,						\
> +	.prepare_count	= 0,						\
> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
> +}
> +
> +/**
> + * struct clk_ops -  Callback operations for clocks; these are to be provided
> + * by the clock implementation, and will be called by drivers through the clk_*
> + * API.
> + *
> + * @prepare:	Prepare the clock for enabling. This must not return until
> + *		the clock is fully prepared, and it's safe to call clk_enable.
> + *		This callback is intended to allow clock implementations to
> + *		do any initialisation that may block. Called with
> + *		clk->prepare_lock held.
> + *
> + * @unprepare:	Release the clock from its prepared state. This will typically
> + *		undo any work done in the @prepare callback. Called with
> + *		clk->prepare_lock held.
> + *
> + * @enable:	Enable the clock atomically. This must not return until the
> + *		clock is generating a valid clock signal, usable by consumer
> + *		devices. Called with clk->enable_lock held. This function
> + *		must not sleep.
> + *
> + * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
> + *		This function must not sleep.
> + *
> + * @get:	Called by the core clock code when a device driver acquires a
> + *		clock via clk_get(). Optional.
> + *
> + * @put:	Called by the core clock code when a devices driver releases a
> + *		clock via clk_put(). Optional.
> + *
> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> + * implementations to split any work between atomic (enable) and sleepable
> + * (prepare) contexts.  If a clock requires blocking code to be turned on, this
> + * should be done in clk_prepare. Switching that will not block should be done
> + * in clk_enable.
> + *
> + * Typically, drivers will call clk_prepare when a clock may be needed later
> + * (eg. when a device is opened), and clk_enable when the clock is actually
> + * required (eg. from an interrupt). Note that clk_prepare *must* have been
> + * called before clk_enable.
> + *
> + * For other callbacks, see the corresponding clk_* functions. Parameters and
> + * return values are passed directly from/to these API functions, or
> + * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
> + * is NULL, see kernel/clk.c for implementation details. All are optional.
> + */
> +struct clk_ops {
> +	int		(*prepare)(struct clk *);
> +	void		(*unprepare)(struct clk *);
> +	int		(*enable)(struct clk *);
> +	void		(*disable)(struct clk *);
> +	int		(*get)(struct clk *);
> +	void		(*put)(struct clk *);
> +	unsigned long	(*get_rate)(struct clk *);
> +	long		(*round_rate)(struct clk *, unsigned long);
> +	int		(*set_rate)(struct clk *, unsigned long);
> +	int		(*set_parent)(struct clk *, struct clk *);
> +	struct clk *	(*get_parent)(struct clk *);
> +};
> +
> +/**
> + * __clk_get - acquire a reference to a clock
> + *
> + * @clk: The clock to refcount
> + *
> + * Before a clock is returned from clk_get, this function should be called
> + * to update any clock-specific refcounting.

This is a bit misleading. It's not "should be called", it "is called". I
think you should just remove the documentation for __clk_get/__clk_put
or move it into clk.c since the functions are only used internally by
the common clock code.

> + *
> + * Returns non-zero on success, zero on failure.
> + *
> + * Drivers should not need this function, it is called by the common clock
> + * infrastructure.
> + */
> +int __clk_get(struct clk *clk);
> +
> +/**
> + * __clk_put - release reference to a clock
> + *
> + * @clk: The clock to release
> + *
> + * Called by clock infrastructure code to indicate that a clock consumer
> + * has released a clock, to update any clock-specific refcounting.
> + *
> + * Drivers should not need this function, it is called by the common clock
> + * infrastructure.
> + */
> +void __clk_put(struct clk *clk);
> +
> +/**
> + * clk_prepare - prepare clock for atomic enabling.
> + *
> + * @clk: The clock to prepare
> + *
> + * Do any blocking initialisation on @clk, allowing the clock to be later
> + * enabled atomically (via clk_enable). This function may sleep.

"Possibly blocking" as below?

> + */
> +int clk_prepare(struct clk *clk);
> +
> +/**
> + * clk_unprepare - release clock from prepared state
> + *
> + * @clk: The clock to release
> + *
> + * Do any (possbly blocking) cleanup on clk. This function may sleep.

Typo "possbly".

>   */
> +void clk_unprepare(struct clk *clk);
>  
> +/**
> + * clk_common_init - initialise a clock for driver usage
> + *
> + * @clk: The clock to initialise
> + *
> + * Used for runtime intialization of clocks; you don't need to call this
> + * if your clock has been (statically) initialized with INIT_CLK.
> + */
> +static inline void clk_common_init(struct clk *clk)
> +{
> +	clk->enable_count = clk->prepare_count = 0;
> +	spin_lock_init(&clk->enable_lock);
> +	mutex_init(&clk->prepare_lock);
> +}
> +
> +#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
>  
>  /*
> - * struct clk - an machine class defined object / cookie.
> + * Global clock object, actual structure is declared per-machine
>   */
>  struct clk;
>  
> +static inline void clk_common_init(struct clk *clk) { }
> +
> +/*
> + * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
> + * requirements for clk_enable/clk_disable, so the prepare and unprepare
> + * functions are no-ops
> + */
> +int clk_prepare(struct clk *clk) { return 0; }
> +void clk_unprepare(struct clk *clk) { }
> +
> +#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
> +
>  /**
>   * clk_get - lookup and obtain a reference to a clock producer.
>   * @dev: device for clock "consumer"
> @@ -67,6 +248,7 @@ void clk_disable(struct clk *clk);
>  /**
>   * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
>   *		  This is only valid once the clock source has been enabled.
> + *		  Returns zero if the clock rate is unknown.
>   * @clk: clock source
>   */
>  unsigned long clk_get_rate(struct clk *clk);
> @@ -83,12 +265,6 @@ unsigned long clk_get_rate(struct clk *clk);
>   */
>  void clk_put(struct clk *clk);
>  
> -
> -/*
> - * The remaining APIs are optional for machine class support.
> - */
> -
> -
>  /**
>   * clk_round_rate - adjust a rate to the exact rate a clock can provide
>   * @clk: clock source
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/


-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan@bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-09 20:21       ` Ryan Mallon
  0 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-09 20:21 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/09/2011 07:41 PM, Jeremy Kerr wrote:

Hi Jeremy,

Couple more comments below.

~Ryan

> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, containing a set of clock operations. Different
> clock implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
> 
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
> 
> And a set of clock operations (defined per type of clock):
> 
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
> 
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
> 
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
> 
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/Kconfig  |    3 
>  drivers/clk/Makefile |    1 
>  drivers/clk/clk.c    |  126 +++++++++++++++++++++++++++
>  include/linux/clk.h  |  194 +++++++++++++++++++++++++++++++++++++++++--
>  4 files changed, 315 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4168c88..6e3ae54 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -2,3 +2,6 @@
>  config CLKDEV_LOOKUP
>  	bool
>  	select HAVE_CLK
> +
> +config USE_COMMON_STRUCT_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..a1a06d3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..c35478a
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,126 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	mutex_lock(&clk->prepare_lock);
> +	if (clk->prepare_count == 0 && clk->ops->prepare)
> +		ret = clk->ops->prepare(clk);
> +
> +	if (!ret)
> +		clk->prepare_count++;
> +	mutex_unlock(&clk->prepare_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	mutex_lock(&clk->prepare_lock);
> +
> +	WARN_ON(clk->prepare_count == 0);
> +
> +	if (--clk->prepare_count == 0 && clk->ops->unprepare)
> +		clk->ops->unprepare(clk);
> +
> +	mutex_unlock(&clk->prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +int clk_enable(struct clk *clk)
> +{
> +	unsigned long flags;
> +	int ret = 0;
> +
> +	spin_lock_irqsave(&clk->enable_lock, flags);

	WARN_ON(clk->prepare_count == 0); ?

> +	if (clk->enable_count == 0 && clk->ops->enable)
> +		ret = clk->ops->enable(clk);

Does it make sense to have a clock with no enable function which still
returns success from clk_enable? Do we have any platforms which have
NULL clk_enable functions?

I think that for enable/disable at least we should require platforms to
provide functions and oops if they have failed to do so. In the rare
case that a platform doesn't need to do anything for enable/disable they
can just supply empty functions.

> +
> +	if (!ret)
> +		clk->enable_count++;
> +	spin_unlock_irqrestore(&clk->enable_lock, flags);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +void clk_disable(struct clk *clk)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&clk->enable_lock, flags);
> +
> +	WARN_ON(clk->enable_count == 0);
> +
> +	if (!--clk->enable_count == 0 && clk->ops->disable)
> +		clk->ops->disable(clk);
> +
> +	spin_unlock_irqrestore(&clk->enable_lock, flags);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	if (clk->ops->get_rate)
> +		return clk->ops->get_rate(clk);
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->round_rate)
> +		return clk->ops->round_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk->ops->set_rate)
> +		return clk->ops->set_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	if (clk->ops->set_parent)
> +		return clk->ops->set_parent(clk, parent);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	if (clk->ops->get_parent)
> +		return clk->ops->get_parent(clk);
> +	return ERR_PTR(-ENOSYS);
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> +
> +int __clk_get(struct clk *clk)
> +{
> +	if (clk->ops->get)
> +		return clk->ops->get(clk);
> +	return 1;
> +}
> +
> +void __clk_put(struct clk *clk)
> +{
> +	if (clk->ops->put)
> +		clk->ops->put(clk);
> +}
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..fe806b7 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@
>   *
>   *  Copyright (C) 2004 ARM Limited.
>   *  Written by Deep Blue Solutions Limited.
> + *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
> @@ -11,18 +12,198 @@
>  #ifndef __LINUX_CLK_H
>  #define __LINUX_CLK_H
>  
> +#include <linux/err.h>
> +#include <linux/mutex.h>
> +#include <linux/spinlock.h>
> +
>  struct device;
>  
> -/*
> - * The base API.
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> +
> +/* If we're using the common struct clk, we define the base clk object here */
> +
> +/**
> + * struct clk - hardware independent clock structure
> + * @ops:		implementation-specific ops for this clock
> + * @enable_count:	count of clk_enable() calls active on this clock
> + * @enable_lock:	lock for atomic enable
> + * @prepare_count:	count of clk_prepare() calls active on this clock
> + * @prepare_lock:	lock for sleepable prepare
> + *
> + * The base clock object, used by drivers for hardware-independent manipulation
> + * of clock lines. This will be 'subclassed' by device-specific implementations,
> + * which add device-specific data to struct clk. For example:
> + *
> + *  struct clk_foo {
> + *      struct clk;
> + *      [device specific fields]
> + *  };
> + *
> + * The clock driver code will manage the device-specific data, and pass
> + * clk_foo.clk to the common clock code. The clock driver will be called
> + * through the @ops callbacks.
> + *
> + * The @enable_lock and @prepare_lock members are used to serialise accesses
> + * to the ops->enable and ops->prepare functions (and the corresponding
> + * ops->disable and ops->unprepare functions).
> + */
> +struct clk {
> +	const struct clk_ops	*ops;
> +	unsigned int		enable_count;
> +	unsigned int		prepare_count;
> +	spinlock_t		enable_lock;
> +	struct mutex		prepare_lock;
> +};
> +
> +/* static initialiser for clocks */
> +#define INIT_CLK(name, o) {						\
> +	.ops		= &o,						\
> +	.enable_count	= 0,						\
> +	.prepare_count	= 0,						\
> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
> +}
> +
> +/**
> + * struct clk_ops -  Callback operations for clocks; these are to be provided
> + * by the clock implementation, and will be called by drivers through the clk_*
> + * API.
> + *
> + * @prepare:	Prepare the clock for enabling. This must not return until
> + *		the clock is fully prepared, and it's safe to call clk_enable.
> + *		This callback is intended to allow clock implementations to
> + *		do any initialisation that may block. Called with
> + *		clk->prepare_lock held.
> + *
> + * @unprepare:	Release the clock from its prepared state. This will typically
> + *		undo any work done in the @prepare callback. Called with
> + *		clk->prepare_lock held.
> + *
> + * @enable:	Enable the clock atomically. This must not return until the
> + *		clock is generating a valid clock signal, usable by consumer
> + *		devices. Called with clk->enable_lock held. This function
> + *		must not sleep.
> + *
> + * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
> + *		This function must not sleep.
> + *
> + * @get:	Called by the core clock code when a device driver acquires a
> + *		clock via clk_get(). Optional.
> + *
> + * @put:	Called by the core clock code when a devices driver releases a
> + *		clock via clk_put(). Optional.
> + *
> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> + * implementations to split any work between atomic (enable) and sleepable
> + * (prepare) contexts.  If a clock requires blocking code to be turned on, this
> + * should be done in clk_prepare. Switching that will not block should be done
> + * in clk_enable.
> + *
> + * Typically, drivers will call clk_prepare when a clock may be needed later
> + * (eg. when a device is opened), and clk_enable when the clock is actually
> + * required (eg. from an interrupt). Note that clk_prepare *must* have been
> + * called before clk_enable.
> + *
> + * For other callbacks, see the corresponding clk_* functions. Parameters and
> + * return values are passed directly from/to these API functions, or
> + * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
> + * is NULL, see kernel/clk.c for implementation details. All are optional.
> + */
> +struct clk_ops {
> +	int		(*prepare)(struct clk *);
> +	void		(*unprepare)(struct clk *);
> +	int		(*enable)(struct clk *);
> +	void		(*disable)(struct clk *);
> +	int		(*get)(struct clk *);
> +	void		(*put)(struct clk *);
> +	unsigned long	(*get_rate)(struct clk *);
> +	long		(*round_rate)(struct clk *, unsigned long);
> +	int		(*set_rate)(struct clk *, unsigned long);
> +	int		(*set_parent)(struct clk *, struct clk *);
> +	struct clk *	(*get_parent)(struct clk *);
> +};
> +
> +/**
> + * __clk_get - acquire a reference to a clock
> + *
> + * @clk: The clock to refcount
> + *
> + * Before a clock is returned from clk_get, this function should be called
> + * to update any clock-specific refcounting.

This is a bit misleading. It's not "should be called", it "is called". I
think you should just remove the documentation for __clk_get/__clk_put
or move it into clk.c since the functions are only used internally by
the common clock code.

> + *
> + * Returns non-zero on success, zero on failure.
> + *
> + * Drivers should not need this function, it is called by the common clock
> + * infrastructure.
> + */
> +int __clk_get(struct clk *clk);
> +
> +/**
> + * __clk_put - release reference to a clock
> + *
> + * @clk: The clock to release
> + *
> + * Called by clock infrastructure code to indicate that a clock consumer
> + * has released a clock, to update any clock-specific refcounting.
> + *
> + * Drivers should not need this function, it is called by the common clock
> + * infrastructure.
> + */
> +void __clk_put(struct clk *clk);
> +
> +/**
> + * clk_prepare - prepare clock for atomic enabling.
> + *
> + * @clk: The clock to prepare
> + *
> + * Do any blocking initialisation on @clk, allowing the clock to be later
> + * enabled atomically (via clk_enable). This function may sleep.

"Possibly blocking" as below?

> + */
> +int clk_prepare(struct clk *clk);
> +
> +/**
> + * clk_unprepare - release clock from prepared state
> + *
> + * @clk: The clock to release
> + *
> + * Do any (possbly blocking) cleanup on clk. This function may sleep.

Typo "possbly".

>   */
> +void clk_unprepare(struct clk *clk);
>  
> +/**
> + * clk_common_init - initialise a clock for driver usage
> + *
> + * @clk: The clock to initialise
> + *
> + * Used for runtime intialization of clocks; you don't need to call this
> + * if your clock has been (statically) initialized with INIT_CLK.
> + */
> +static inline void clk_common_init(struct clk *clk)
> +{
> +	clk->enable_count = clk->prepare_count = 0;
> +	spin_lock_init(&clk->enable_lock);
> +	mutex_init(&clk->prepare_lock);
> +}
> +
> +#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
>  
>  /*
> - * struct clk - an machine class defined object / cookie.
> + * Global clock object, actual structure is declared per-machine
>   */
>  struct clk;
>  
> +static inline void clk_common_init(struct clk *clk) { }
> +
> +/*
> + * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
> + * requirements for clk_enable/clk_disable, so the prepare and unprepare
> + * functions are no-ops
> + */
> +int clk_prepare(struct clk *clk) { return 0; }
> +void clk_unprepare(struct clk *clk) { }
> +
> +#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
> +
>  /**
>   * clk_get - lookup and obtain a reference to a clock producer.
>   * @dev: device for clock "consumer"
> @@ -67,6 +248,7 @@ void clk_disable(struct clk *clk);
>  /**
>   * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
>   *		  This is only valid once the clock source has been enabled.
> + *		  Returns zero if the clock rate is unknown.
>   * @clk: clock source
>   */
>  unsigned long clk_get_rate(struct clk *clk);
> @@ -83,12 +265,6 @@ unsigned long clk_get_rate(struct clk *clk);
>   */
>  void clk_put(struct clk *clk);
>  
> -
> -/*
> - * The remaining APIs are optional for machine class support.
> - */
> -
> -
>  /**
>   * clk_round_rate - adjust a rate to the exact rate a clock can provide
>   * @clk: clock source
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/


-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-09 20:21       ` Ryan Mallon
  (?)
@ 2011-02-09 20:39         ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-09 20:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ryan,

On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
> > +int clk_enable(struct clk *clk)
> > +{
> > +	unsigned long flags;
> > +	int ret = 0;
> > +
> > +	spin_lock_irqsave(&clk->enable_lock, flags);
> 
> 	WARN_ON(clk->prepare_count = 0); ?
This is added in patch 3/3

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-09 20:39         ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-09 20:39 UTC (permalink / raw)
  To: Ryan Mallon
  Cc: Jeremy Kerr, linux-kernel, linux-arm-kernel, Nicolas Pitre,
	Dima Zavin, Lorenzo Pieralisi, Vincent Guittot, linux-sh,
	Ben Herrenschmidt, Sascha Hauer, Paul Mundt, Saravana Kannan,
	Ben Dooks, Russell King

Hi Ryan,

On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
> > +int clk_enable(struct clk *clk)
> > +{
> > +	unsigned long flags;
> > +	int ret = 0;
> > +
> > +	spin_lock_irqsave(&clk->enable_lock, flags);
> 
> 	WARN_ON(clk->prepare_count == 0); ?
This is added in patch 3/3

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-09 20:39         ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-09 20:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ryan,

On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
> > +int clk_enable(struct clk *clk)
> > +{
> > +	unsigned long flags;
> > +	int ret = 0;
> > +
> > +	spin_lock_irqsave(&clk->enable_lock, flags);
> 
> 	WARN_ON(clk->prepare_count == 0); ?
This is added in patch 3/3

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-09 20:39         ` Uwe Kleine-König
  (?)
@ 2011-02-09 20:42           ` Ryan Mallon
  -1 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-09 20:42 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/10/2011 09:39 AM, Uwe Kleine-König wrote:
> Hi Ryan,
> 
> On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
>>> +int clk_enable(struct clk *clk)
>>> +{
>>> +	unsigned long flags;
>>> +	int ret = 0;
>>> +
>>> +	spin_lock_irqsave(&clk->enable_lock, flags);
>>
>> 	WARN_ON(clk->prepare_count = 0); ?
> This is added in patch 3/3

Ah, missed that. I still think that patch 3 should just be rolled into
patch 1. I don't see why we should add a new file in one patch and then
randomly add some warning code to it in another patch. It makes
reviewing harder for one thing :-).

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan@bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-09 20:42           ` Ryan Mallon
  0 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-09 20:42 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Jeremy Kerr, linux-kernel, linux-arm-kernel, Nicolas Pitre,
	Dima Zavin, Lorenzo Pieralisi, Vincent Guittot, linux-sh,
	Ben Herrenschmidt, Sascha Hauer, Paul Mundt, Saravana Kannan,
	Ben Dooks, Russell King

On 02/10/2011 09:39 AM, Uwe Kleine-König wrote:
> Hi Ryan,
> 
> On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
>>> +int clk_enable(struct clk *clk)
>>> +{
>>> +	unsigned long flags;
>>> +	int ret = 0;
>>> +
>>> +	spin_lock_irqsave(&clk->enable_lock, flags);
>>
>> 	WARN_ON(clk->prepare_count == 0); ?
> This is added in patch 3/3

Ah, missed that. I still think that patch 3 should just be rolled into
patch 1. I don't see why we should add a new file in one patch and then
randomly add some warning code to it in another patch. It makes
reviewing harder for one thing :-).

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan@bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-09 20:42           ` Ryan Mallon
  0 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-09 20:42 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/10/2011 09:39 AM, Uwe Kleine-K?nig wrote:
> Hi Ryan,
> 
> On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
>>> +int clk_enable(struct clk *clk)
>>> +{
>>> +	unsigned long flags;
>>> +	int ret = 0;
>>> +
>>> +	spin_lock_irqsave(&clk->enable_lock, flags);
>>
>> 	WARN_ON(clk->prepare_count == 0); ?
> This is added in patch 3/3

Ah, missed that. I still think that patch 3 should just be rolled into
patch 1. I don't see why we should add a new file in one patch and then
randomly add some warning code to it in another patch. It makes
reviewing harder for one thing :-).

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare
  2011-02-07 14:24         ` Nicolas Pitre
  (?)
@ 2011-02-10  4:26           ` Saravana Kannan
  -1 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-10  4:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/07/2011 06:24 AM, Nicolas Pitre wrote:
> On Mon, 7 Feb 2011, Jeremy Kerr wrote:
>
>> Hi Uwe,
>>
>>> This implies the warning is only issued on clocks that have a prepare
>>> callback.  If we want to enforce the new API the warning here shouldn't
>>> depend on clk->ops->prepare.  (clk_prepare and clk_unprepare need to
>>> be changed then to adapt the prepare_count even in the absence of
>>> clk->ops->prepare.)
>>
>> Yeah, it's a decision about either adding a small cost to all clk_prepare()s
>> (ie, adding cost when there is no prepare callback), or checking for the
>> correct prepare/enable semantics for all clocks (even when it doesn't matter
>> for that particular clock). I chose the first as more important, but happy to
>> go either way here.
>
> The prepare method being called from non-atomic context cannot be
> considered to be in a speed critical path.  Most of the time, this is
> going to be called on driver initialization or the like, and that's a
> relatively rare event. Therefore this really small cost to clk_prepare()
> is definitively worth it to help proper usage of the API.  If this ever
> becomes a problem then this could be confined to some CONFIG_CLK_DEBUG
> or the like.  But when introducing a new API it is best to be more
> strict to help people get its usage right (without going overboard with
> it of course).
>

Agree with Nicholas and Uwe. +1 for this request.

-Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-10  4:26           ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-10  4:26 UTC (permalink / raw)
  To: Nicolas Pitre
  Cc: Jeremy Kerr, Dima Zavin, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, linux-kernel,
	Paul Mundt, Ben Dooks, Uwe Kleine-König, Russell King,
	linux-arm-kernel

On 02/07/2011 06:24 AM, Nicolas Pitre wrote:
> On Mon, 7 Feb 2011, Jeremy Kerr wrote:
>
>> Hi Uwe,
>>
>>> This implies the warning is only issued on clocks that have a prepare
>>> callback.  If we want to enforce the new API the warning here shouldn't
>>> depend on clk->ops->prepare.  (clk_prepare and clk_unprepare need to
>>> be changed then to adapt the prepare_count even in the absence of
>>> clk->ops->prepare.)
>>
>> Yeah, it's a decision about either adding a small cost to all clk_prepare()s
>> (ie, adding cost when there is no prepare callback), or checking for the
>> correct prepare/enable semantics for all clocks (even when it doesn't matter
>> for that particular clock). I chose the first as more important, but happy to
>> go either way here.
>
> The prepare method being called from non-atomic context cannot be
> considered to be in a speed critical path.  Most of the time, this is
> going to be called on driver initialization or the like, and that's a
> relatively rare event. Therefore this really small cost to clk_prepare()
> is definitively worth it to help proper usage of the API.  If this ever
> becomes a problem then this could be confined to some CONFIG_CLK_DEBUG
> or the like.  But when introducing a new API it is best to be more
> strict to help people get its usage right (without going overboard with
> it of course).
>

Agree with Nicholas and Uwe. +1 for this request.

-Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-10  4:26           ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-10  4:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/07/2011 06:24 AM, Nicolas Pitre wrote:
> On Mon, 7 Feb 2011, Jeremy Kerr wrote:
>
>> Hi Uwe,
>>
>>> This implies the warning is only issued on clocks that have a prepare
>>> callback.  If we want to enforce the new API the warning here shouldn't
>>> depend on clk->ops->prepare.  (clk_prepare and clk_unprepare need to
>>> be changed then to adapt the prepare_count even in the absence of
>>> clk->ops->prepare.)
>>
>> Yeah, it's a decision about either adding a small cost to all clk_prepare()s
>> (ie, adding cost when there is no prepare callback), or checking for the
>> correct prepare/enable semantics for all clocks (even when it doesn't matter
>> for that particular clock). I chose the first as more important, but happy to
>> go either way here.
>
> The prepare method being called from non-atomic context cannot be
> considered to be in a speed critical path.  Most of the time, this is
> going to be called on driver initialization or the like, and that's a
> relatively rare event. Therefore this really small cost to clk_prepare()
> is definitively worth it to help proper usage of the API.  If this ever
> becomes a problem then this could be confined to some CONFIG_CLK_DEBUG
> or the like.  But when introducing a new API it is best to be more
> strict to help people get its usage right (without going overboard with
> it of course).
>

Agree with Nicholas and Uwe. +1 for this request.

-Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-09  6:41     ` Jeremy Kerr
  (?)
@ 2011-02-10  5:16       ` Saravana Kannan
  -1 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-10  5:16 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/08/2011 10:41 PM, Jeremy Kerr wrote:

[snip]

> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{

Shouldn't you be grabbing the prepare_lock here? Set rate and 
prepare/unprepare would be working on the same shared resource (say, 
PLL). That was the reason we are making set_rate() sleepable too.

As a nice side effect, it will also enforce the "might sleep" nature of 
this API.

You should probably rename the lock to something else since it's not 
limited to prepare/unprepare. How about resource_lock?

> +	if (clk->ops->set_rate)
> +		return clk->ops->set_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	if (clk->ops->set_parent)
> +		return clk->ops->set_parent(clk, parent);

I'm not sure on this one. If the prepare ops for a clock also calls the 
prepare ops on the parent, shouldn't we prevent changing the parent 
while the prepare/unprepare is going on?


> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +

> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..fe806b7 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@

[snip]

> +
> +/* static initialiser for clocks */
> +#define INIT_CLK(name, o) {						\
> +	.ops		=&o,						\
> +	.enable_count	= 0,						\
> +	.prepare_count	= 0,						\

Do we need these inits? Doesn't check patch complain about initing 
static/global to 0? If it's generally frowned upon, why the exception 
here. I realize that checkpatch won't catch this, but still...

> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\

After a long day, I'm not able to wrap my head around this. Probably a 
stupid question, but will this name.xxx thing prevent using this 
INIT_CLK macro to initialize an array of clocks? More specifically, 
prevent the sub class macro (like INIT_CLK_FIXED) from being used to 
initialize an array of clocks?

> +}
> +
> +/**
> + * struct clk_ops -  Callback operations for clocks; these are to be provided
> + * by the clock implementation, and will be called by drivers through the clk_*
> + * API.
> + *
> + * @prepare:	Prepare the clock for enabling. This must not return until
> + *		the clock is fully prepared, and it's safe to call clk_enable.
> + *		This callback is intended to allow clock implementations to
> + *		do any initialisation that may block. Called with
> + *		clk->prepare_lock held.
> + *
> + * @unprepare:	Release the clock from its prepared state. This will typically
> + *		undo any work done in the @prepare callback. Called with
> + *		clk->prepare_lock held.
> + *
> + * @enable:	Enable the clock atomically. This must not return until the
> + *		clock is generating a valid clock signal, usable by consumer
> + *		devices. Called with clk->enable_lock held. This function
> + *		must not sleep.
> + *
> + * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
> + *		This function must not sleep.
> + *
> + * @get:	Called by the core clock code when a device driver acquires a
> + *		clock via clk_get(). Optional.
> + *
> + * @put:	Called by the core clock code when a devices driver releases a
> + *		clock via clk_put(). Optional.
> + *
> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> + * implementations to split any work between atomic (enable) and sleepable
> + * (prepare) contexts.  If a clock requires blocking code to be turned on, this

Aren't all locks blocking? Shouldn't it be, "If turning on a clock 
requires code that might sleep, it should be done in clk_prepare"? 
Replace all "blocking" with "sleepable" or "sleeping" in the comments?

> + * should be done in clk_prepare. Switching that will not block should be done
> + * in clk_enable.
> + *
> + * Typically, drivers will call clk_prepare when a clock may be needed later
> + * (eg. when a device is opened), and clk_enable when the clock is actually
> + * required (eg. from an interrupt). Note that clk_prepare *must* have been
> + * called before clk_enable.
> + *
> + * For other callbacks, see the corresponding clk_* functions. Parameters and
> + * return values are passed directly from/to these API functions, or
> + * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
> + * is NULL, see kernel/clk.c for implementation details. All are optional.

is NULL. See kernel... ?
> + */
> +struct clk_ops {
> +	int		(*prepare)(struct clk *);
> +	void		(*unprepare)(struct clk *);
> +	int		(*enable)(struct clk *);
> +	void		(*disable)(struct clk *);
> +	int		(*get)(struct clk *);
> +	void		(*put)(struct clk *);
> +	unsigned long	(*get_rate)(struct clk *);
> +	long		(*round_rate)(struct clk *, unsigned long);
> +	int		(*set_rate)(struct clk *, unsigned long);
> +	int		(*set_parent)(struct clk *, struct clk *);
> +	struct clk *	(*get_parent)(struct clk *);
> +};
> +

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-10  5:16       ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-10  5:16 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, Dima Zavin, Ben Dooks, Uwe Kleine-König,
	Russell King

On 02/08/2011 10:41 PM, Jeremy Kerr wrote:

[snip]

> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{

Shouldn't you be grabbing the prepare_lock here? Set rate and 
prepare/unprepare would be working on the same shared resource (say, 
PLL). That was the reason we are making set_rate() sleepable too.

As a nice side effect, it will also enforce the "might sleep" nature of 
this API.

You should probably rename the lock to something else since it's not 
limited to prepare/unprepare. How about resource_lock?

> +	if (clk->ops->set_rate)
> +		return clk->ops->set_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	if (clk->ops->set_parent)
> +		return clk->ops->set_parent(clk, parent);

I'm not sure on this one. If the prepare ops for a clock also calls the 
prepare ops on the parent, shouldn't we prevent changing the parent 
while the prepare/unprepare is going on?


> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +

> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..fe806b7 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@

[snip]

> +
> +/* static initialiser for clocks */
> +#define INIT_CLK(name, o) {						\
> +	.ops		=&o,						\
> +	.enable_count	= 0,						\
> +	.prepare_count	= 0,						\

Do we need these inits? Doesn't check patch complain about initing 
static/global to 0? If it's generally frowned upon, why the exception 
here. I realize that checkpatch won't catch this, but still...

> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\

After a long day, I'm not able to wrap my head around this. Probably a 
stupid question, but will this name.xxx thing prevent using this 
INIT_CLK macro to initialize an array of clocks? More specifically, 
prevent the sub class macro (like INIT_CLK_FIXED) from being used to 
initialize an array of clocks?

> +}
> +
> +/**
> + * struct clk_ops -  Callback operations for clocks; these are to be provided
> + * by the clock implementation, and will be called by drivers through the clk_*
> + * API.
> + *
> + * @prepare:	Prepare the clock for enabling. This must not return until
> + *		the clock is fully prepared, and it's safe to call clk_enable.
> + *		This callback is intended to allow clock implementations to
> + *		do any initialisation that may block. Called with
> + *		clk->prepare_lock held.
> + *
> + * @unprepare:	Release the clock from its prepared state. This will typically
> + *		undo any work done in the @prepare callback. Called with
> + *		clk->prepare_lock held.
> + *
> + * @enable:	Enable the clock atomically. This must not return until the
> + *		clock is generating a valid clock signal, usable by consumer
> + *		devices. Called with clk->enable_lock held. This function
> + *		must not sleep.
> + *
> + * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
> + *		This function must not sleep.
> + *
> + * @get:	Called by the core clock code when a device driver acquires a
> + *		clock via clk_get(). Optional.
> + *
> + * @put:	Called by the core clock code when a devices driver releases a
> + *		clock via clk_put(). Optional.
> + *
> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> + * implementations to split any work between atomic (enable) and sleepable
> + * (prepare) contexts.  If a clock requires blocking code to be turned on, this

Aren't all locks blocking? Shouldn't it be, "If turning on a clock 
requires code that might sleep, it should be done in clk_prepare"? 
Replace all "blocking" with "sleepable" or "sleeping" in the comments?

> + * should be done in clk_prepare. Switching that will not block should be done
> + * in clk_enable.
> + *
> + * Typically, drivers will call clk_prepare when a clock may be needed later
> + * (eg. when a device is opened), and clk_enable when the clock is actually
> + * required (eg. from an interrupt). Note that clk_prepare *must* have been
> + * called before clk_enable.
> + *
> + * For other callbacks, see the corresponding clk_* functions. Parameters and
> + * return values are passed directly from/to these API functions, or
> + * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
> + * is NULL, see kernel/clk.c for implementation details. All are optional.

is NULL. See kernel... ?
> + */
> +struct clk_ops {
> +	int		(*prepare)(struct clk *);
> +	void		(*unprepare)(struct clk *);
> +	int		(*enable)(struct clk *);
> +	void		(*disable)(struct clk *);
> +	int		(*get)(struct clk *);
> +	void		(*put)(struct clk *);
> +	unsigned long	(*get_rate)(struct clk *);
> +	long		(*round_rate)(struct clk *, unsigned long);
> +	int		(*set_rate)(struct clk *, unsigned long);
> +	int		(*set_parent)(struct clk *, struct clk *);
> +	struct clk *	(*get_parent)(struct clk *);
> +};
> +

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-10  5:16       ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-10  5:16 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/08/2011 10:41 PM, Jeremy Kerr wrote:

[snip]

> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{

Shouldn't you be grabbing the prepare_lock here? Set rate and 
prepare/unprepare would be working on the same shared resource (say, 
PLL). That was the reason we are making set_rate() sleepable too.

As a nice side effect, it will also enforce the "might sleep" nature of 
this API.

You should probably rename the lock to something else since it's not 
limited to prepare/unprepare. How about resource_lock?

> +	if (clk->ops->set_rate)
> +		return clk->ops->set_rate(clk, rate);
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	if (clk->ops->set_parent)
> +		return clk->ops->set_parent(clk, parent);

I'm not sure on this one. If the prepare ops for a clock also calls the 
prepare ops on the parent, shouldn't we prevent changing the parent 
while the prepare/unprepare is going on?


> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +

> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..fe806b7 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@

[snip]

> +
> +/* static initialiser for clocks */
> +#define INIT_CLK(name, o) {						\
> +	.ops		=&o,						\
> +	.enable_count	= 0,						\
> +	.prepare_count	= 0,						\

Do we need these inits? Doesn't check patch complain about initing 
static/global to 0? If it's generally frowned upon, why the exception 
here. I realize that checkpatch won't catch this, but still...

> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\

After a long day, I'm not able to wrap my head around this. Probably a 
stupid question, but will this name.xxx thing prevent using this 
INIT_CLK macro to initialize an array of clocks? More specifically, 
prevent the sub class macro (like INIT_CLK_FIXED) from being used to 
initialize an array of clocks?

> +}
> +
> +/**
> + * struct clk_ops -  Callback operations for clocks; these are to be provided
> + * by the clock implementation, and will be called by drivers through the clk_*
> + * API.
> + *
> + * @prepare:	Prepare the clock for enabling. This must not return until
> + *		the clock is fully prepared, and it's safe to call clk_enable.
> + *		This callback is intended to allow clock implementations to
> + *		do any initialisation that may block. Called with
> + *		clk->prepare_lock held.
> + *
> + * @unprepare:	Release the clock from its prepared state. This will typically
> + *		undo any work done in the @prepare callback. Called with
> + *		clk->prepare_lock held.
> + *
> + * @enable:	Enable the clock atomically. This must not return until the
> + *		clock is generating a valid clock signal, usable by consumer
> + *		devices. Called with clk->enable_lock held. This function
> + *		must not sleep.
> + *
> + * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
> + *		This function must not sleep.
> + *
> + * @get:	Called by the core clock code when a device driver acquires a
> + *		clock via clk_get(). Optional.
> + *
> + * @put:	Called by the core clock code when a devices driver releases a
> + *		clock via clk_put(). Optional.
> + *
> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> + * implementations to split any work between atomic (enable) and sleepable
> + * (prepare) contexts.  If a clock requires blocking code to be turned on, this

Aren't all locks blocking? Shouldn't it be, "If turning on a clock 
requires code that might sleep, it should be done in clk_prepare"? 
Replace all "blocking" with "sleepable" or "sleeping" in the comments?

> + * should be done in clk_prepare. Switching that will not block should be done
> + * in clk_enable.
> + *
> + * Typically, drivers will call clk_prepare when a clock may be needed later
> + * (eg. when a device is opened), and clk_enable when the clock is actually
> + * required (eg. from an interrupt). Note that clk_prepare *must* have been
> + * called before clk_enable.
> + *
> + * For other callbacks, see the corresponding clk_* functions. Parameters and
> + * return values are passed directly from/to these API functions, or
> + * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
> + * is NULL, see kernel/clk.c for implementation details. All are optional.

is NULL. See kernel... ?
> + */
> +struct clk_ops {
> +	int		(*prepare)(struct clk *);
> +	void		(*unprepare)(struct clk *);
> +	int		(*enable)(struct clk *);
> +	void		(*disable)(struct clk *);
> +	int		(*get)(struct clk *);
> +	void		(*put)(struct clk *);
> +	unsigned long	(*get_rate)(struct clk *);
> +	long		(*round_rate)(struct clk *, unsigned long);
> +	int		(*set_rate)(struct clk *, unsigned long);
> +	int		(*set_parent)(struct clk *, struct clk *);
> +	struct clk *	(*get_parent)(struct clk *);
> +};
> +

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC, PATCH 3/3] clk: add warnings for incorrect
  2011-02-09  6:41     ` Jeremy Kerr
  (?)
@ 2011-02-10  9:37       ` Richard Zhao
  -1 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-10  9:37 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jeremy,

On Wed, Feb 09, 2011 at 02:41:33PM +0800, Jeremy Kerr wrote:
> This change adds warnings to check for:
> 
>  1) enabling a clock that hasn't been prepared; and
> 
>  2) unpreparing a clock that is still enabled
> 
> While the correctness can't be guaranteed, the warnings should cover
> most situations, and won't indicate false positives.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/clk.c |    4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index bbbdb0d..8c96623 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -29,6 +29,8 @@ EXPORT_SYMBOL_GPL(clk_prepare);
>  
>  void clk_unprepare(struct clk *clk)
>  {
> +	WARN_ON(clk->enable_count != 0);
> +
Other drivers may be using the clock and increased the enable_count.
This check may be moved to where we actually do unprepare.

Thanks
Richard
>  	mutex_lock(&clk->prepare_lock);
>  
>  	WARN_ON(clk->prepare_count = 0);
> @@ -45,6 +47,8 @@ int clk_enable(struct clk *clk)
>  	unsigned long flags;
>  	int ret = 0;
>  
> +	WARN_ON(clk->prepare_count = 0);
> +
>  	spin_lock_irqsave(&clk->enable_lock, flags);
>  	if (clk->enable_count = 0 && clk->ops->enable)
>  		ret = clk->ops->enable(clk);
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-10  9:37       ` Richard Zhao
  0 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-10  9:37 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, Dima Zavin, Saravana Kannan, Ben Dooks,
	Uwe Kleine-König, Russell King

Hi Jeremy,

On Wed, Feb 09, 2011 at 02:41:33PM +0800, Jeremy Kerr wrote:
> This change adds warnings to check for:
> 
>  1) enabling a clock that hasn't been prepared; and
> 
>  2) unpreparing a clock that is still enabled
> 
> While the correctness can't be guaranteed, the warnings should cover
> most situations, and won't indicate false positives.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/clk.c |    4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index bbbdb0d..8c96623 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -29,6 +29,8 @@ EXPORT_SYMBOL_GPL(clk_prepare);
>  
>  void clk_unprepare(struct clk *clk)
>  {
> +	WARN_ON(clk->enable_count != 0);
> +
Other drivers may be using the clock and increased the enable_count.
This check may be moved to where we actually do unprepare.

Thanks
Richard
>  	mutex_lock(&clk->prepare_lock);
>  
>  	WARN_ON(clk->prepare_count == 0);
> @@ -45,6 +47,8 @@ int clk_enable(struct clk *clk)
>  	unsigned long flags;
>  	int ret = 0;
>  
> +	WARN_ON(clk->prepare_count == 0);
> +
>  	spin_lock_irqsave(&clk->enable_lock, flags);
>  	if (clk->enable_count == 0 && clk->ops->enable)
>  		ret = clk->ops->enable(clk);
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-10  9:37       ` Richard Zhao
  0 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-10  9:37 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jeremy,

On Wed, Feb 09, 2011 at 02:41:33PM +0800, Jeremy Kerr wrote:
> This change adds warnings to check for:
> 
>  1) enabling a clock that hasn't been prepared; and
> 
>  2) unpreparing a clock that is still enabled
> 
> While the correctness can't be guaranteed, the warnings should cover
> most situations, and won't indicate false positives.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/clk.c |    4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index bbbdb0d..8c96623 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -29,6 +29,8 @@ EXPORT_SYMBOL_GPL(clk_prepare);
>  
>  void clk_unprepare(struct clk *clk)
>  {
> +	WARN_ON(clk->enable_count != 0);
> +
Other drivers may be using the clock and increased the enable_count.
This check may be moved to where we actually do unprepare.

Thanks
Richard
>  	mutex_lock(&clk->prepare_lock);
>  
>  	WARN_ON(clk->prepare_count == 0);
> @@ -45,6 +47,8 @@ int clk_enable(struct clk *clk)
>  	unsigned long flags;
>  	int ret = 0;
>  
> +	WARN_ON(clk->prepare_count == 0);
> +
>  	spin_lock_irqsave(&clk->enable_lock, flags);
>  	if (clk->enable_count == 0 && clk->ops->enable)
>  		ret = clk->ops->enable(clk);
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-09 20:21       ` Ryan Mallon
  (?)
@ 2011-02-10 10:03         ` Richard Zhao
  -1 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-10 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
> On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
> 
> Hi Jeremy,
> 
> Couple more comments below.
> 
> ~Ryan
> 
[...]
> > +int clk_enable(struct clk *clk)
> > +{
> > +     unsigned long flags;
> > +     int ret = 0;
> > +
> > +     spin_lock_irqsave(&clk->enable_lock, flags);
> 
>         WARN_ON(clk->prepare_count = 0); ?
> 
> > +     if (clk->enable_count = 0 && clk->ops->enable)
> > +             ret = clk->ops->enable(clk);
> 
> Does it make sense to have a clock with no enable function which still
> returns success from clk_enable? Do we have any platforms which have
> NULL clk_enable functions?
> 
> I think that for enable/disable at least we should require platforms to
> provide functions and oops if they have failed to do so. In the rare
> case that a platform doesn't need to do anything for enable/disable they
> can just supply empty functions.
It's possible to be NULL. So are set_rate/get_rate.
Ideally, if it's NULL: 
prepare/unprepare: only call parent's prepare/unprepare
enable/disable: only call parent's enable/disable
set_rate: fail
get_rate: reture parent's get_rate
set_parent: fail
get_parent: fail

Thanks
Richard
> 
> > +
> > +     if (!ret)
> > +             clk->enable_count++;
> > +     spin_unlock_irqrestore(&clk->enable_lock, flags);
> > +
> > +     return ret;
> > +}
> > +EXPORT_SYMBOL_GPL(clk_enable);
> > +


^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-10 10:03         ` Richard Zhao
  0 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-10 10:03 UTC (permalink / raw)
  To: Ryan Mallon
  Cc: Jeremy Kerr, Nicolas Pitre, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	linux-kernel, Dima Zavin, Saravana Kannan, Ben Dooks,
	Uwe Kleine-König, Russell King, linux-arm-kernel

On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
> On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
> 
> Hi Jeremy,
> 
> Couple more comments below.
> 
> ~Ryan
> 
[...]
> > +int clk_enable(struct clk *clk)
> > +{
> > +     unsigned long flags;
> > +     int ret = 0;
> > +
> > +     spin_lock_irqsave(&clk->enable_lock, flags);
> 
>         WARN_ON(clk->prepare_count == 0); ?
> 
> > +     if (clk->enable_count == 0 && clk->ops->enable)
> > +             ret = clk->ops->enable(clk);
> 
> Does it make sense to have a clock with no enable function which still
> returns success from clk_enable? Do we have any platforms which have
> NULL clk_enable functions?
> 
> I think that for enable/disable at least we should require platforms to
> provide functions and oops if they have failed to do so. In the rare
> case that a platform doesn't need to do anything for enable/disable they
> can just supply empty functions.
It's possible to be NULL. So are set_rate/get_rate.
Ideally, if it's NULL: 
prepare/unprepare: only call parent's prepare/unprepare
enable/disable: only call parent's enable/disable
set_rate: fail
get_rate: reture parent's get_rate
set_parent: fail
get_parent: fail

Thanks
Richard
> 
> > +
> > +     if (!ret)
> > +             clk->enable_count++;
> > +     spin_unlock_irqrestore(&clk->enable_lock, flags);
> > +
> > +     return ret;
> > +}
> > +EXPORT_SYMBOL_GPL(clk_enable);
> > +


^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-10 10:03         ` Richard Zhao
  0 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-10 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
> On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
> 
> Hi Jeremy,
> 
> Couple more comments below.
> 
> ~Ryan
> 
[...]
> > +int clk_enable(struct clk *clk)
> > +{
> > +     unsigned long flags;
> > +     int ret = 0;
> > +
> > +     spin_lock_irqsave(&clk->enable_lock, flags);
> 
>         WARN_ON(clk->prepare_count == 0); ?
> 
> > +     if (clk->enable_count == 0 && clk->ops->enable)
> > +             ret = clk->ops->enable(clk);
> 
> Does it make sense to have a clock with no enable function which still
> returns success from clk_enable? Do we have any platforms which have
> NULL clk_enable functions?
> 
> I think that for enable/disable at least we should require platforms to
> provide functions and oops if they have failed to do so. In the rare
> case that a platform doesn't need to do anything for enable/disable they
> can just supply empty functions.
It's possible to be NULL. So are set_rate/get_rate.
Ideally, if it's NULL: 
prepare/unprepare: only call parent's prepare/unprepare
enable/disable: only call parent's enable/disable
set_rate: fail
get_rate: reture parent's get_rate
set_parent: fail
get_parent: fail

Thanks
Richard
> 
> > +
> > +     if (!ret)
> > +             clk->enable_count++;
> > +     spin_unlock_irqrestore(&clk->enable_lock, flags);
> > +
> > +     return ret;
> > +}
> > +EXPORT_SYMBOL_GPL(clk_enable);
> > +

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-10 10:03         ` Richard Zhao
  (?)
@ 2011-02-10 10:10           ` Ryan Mallon
  -1 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-10 10:10 UTC (permalink / raw)
  To: linux-arm-kernel

On 10/02/11 23:03, Richard Zhao wrote:
> On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
>> On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
>>
>> Hi Jeremy,
>>
>> Couple more comments below.
>>
>> ~Ryan
>>
> [...]
>>> +int clk_enable(struct clk *clk)
>>> +{
>>> +     unsigned long flags;
>>> +     int ret = 0;
>>> +
>>> +     spin_lock_irqsave(&clk->enable_lock, flags);
>>          WARN_ON(clk->prepare_count = 0); ?
>>
>>> +     if (clk->enable_count = 0&&  clk->ops->enable)
>>> +             ret = clk->ops->enable(clk);
>> Does it make sense to have a clock with no enable function which still
>> returns success from clk_enable? Do we have any platforms which have
>> NULL clk_enable functions?
>>
>> I think that for enable/disable at least we should require platforms to
>> provide functions and oops if they have failed to do so. In the rare
>> case that a platform doesn't need to do anything for enable/disable they
>> can just supply empty functions.
> It's possible to be NULL. So are set_rate/get_rate.
> Ideally, if it's NULL:
> prepare/unprepare: only call parent's prepare/unprepare
> enable/disable: only call parent's enable/disable

No, the whole point of the generic framework is that _all_ clock users 
must call prepare/enable and disable/unprepare. Drivers, etc should not 
rely on underlying knowledge of a platform. This is why, for instance, 
clk_enable will warn if prepare count is zero.

However, I can see that a clock may be fully enabled by its prepare 
function and so the enable function is a no-op. User must still call 
both prepare and enable though. Perhaps this is what you meant?

~Ryan

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-10 10:10           ` Ryan Mallon
  0 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-10 10:10 UTC (permalink / raw)
  To: Richard Zhao
  Cc: Jeremy Kerr, Nicolas Pitre, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	linux-kernel, Dima Zavin, Saravana Kannan, Ben Dooks,
	Uwe Kleine-König, Russell King, linux-arm-kernel

On 10/02/11 23:03, Richard Zhao wrote:
> On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
>> On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
>>
>> Hi Jeremy,
>>
>> Couple more comments below.
>>
>> ~Ryan
>>
> [...]
>>> +int clk_enable(struct clk *clk)
>>> +{
>>> +     unsigned long flags;
>>> +     int ret = 0;
>>> +
>>> +     spin_lock_irqsave(&clk->enable_lock, flags);
>>          WARN_ON(clk->prepare_count == 0); ?
>>
>>> +     if (clk->enable_count == 0&&  clk->ops->enable)
>>> +             ret = clk->ops->enable(clk);
>> Does it make sense to have a clock with no enable function which still
>> returns success from clk_enable? Do we have any platforms which have
>> NULL clk_enable functions?
>>
>> I think that for enable/disable at least we should require platforms to
>> provide functions and oops if they have failed to do so. In the rare
>> case that a platform doesn't need to do anything for enable/disable they
>> can just supply empty functions.
> It's possible to be NULL. So are set_rate/get_rate.
> Ideally, if it's NULL:
> prepare/unprepare: only call parent's prepare/unprepare
> enable/disable: only call parent's enable/disable

No, the whole point of the generic framework is that _all_ clock users 
must call prepare/enable and disable/unprepare. Drivers, etc should not 
rely on underlying knowledge of a platform. This is why, for instance, 
clk_enable will warn if prepare count is zero.

However, I can see that a clock may be fully enabled by its prepare 
function and so the enable function is a no-op. User must still call 
both prepare and enable though. Perhaps this is what you meant?

~Ryan

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-10 10:10           ` Ryan Mallon
  0 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-10 10:10 UTC (permalink / raw)
  To: linux-arm-kernel

On 10/02/11 23:03, Richard Zhao wrote:
> On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
>> On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
>>
>> Hi Jeremy,
>>
>> Couple more comments below.
>>
>> ~Ryan
>>
> [...]
>>> +int clk_enable(struct clk *clk)
>>> +{
>>> +     unsigned long flags;
>>> +     int ret = 0;
>>> +
>>> +     spin_lock_irqsave(&clk->enable_lock, flags);
>>          WARN_ON(clk->prepare_count == 0); ?
>>
>>> +     if (clk->enable_count == 0&&  clk->ops->enable)
>>> +             ret = clk->ops->enable(clk);
>> Does it make sense to have a clock with no enable function which still
>> returns success from clk_enable? Do we have any platforms which have
>> NULL clk_enable functions?
>>
>> I think that for enable/disable at least we should require platforms to
>> provide functions and oops if they have failed to do so. In the rare
>> case that a platform doesn't need to do anything for enable/disable they
>> can just supply empty functions.
> It's possible to be NULL. So are set_rate/get_rate.
> Ideally, if it's NULL:
> prepare/unprepare: only call parent's prepare/unprepare
> enable/disable: only call parent's enable/disable

No, the whole point of the generic framework is that _all_ clock users 
must call prepare/enable and disable/unprepare. Drivers, etc should not 
rely on underlying knowledge of a platform. This is why, for instance, 
clk_enable will warn if prepare count is zero.

However, I can see that a clock may be fully enabled by its prepare 
function and so the enable function is a no-op. User must still call 
both prepare and enable though. Perhaps this is what you meant?

~Ryan

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-10 10:03         ` Richard Zhao
  (?)
@ 2011-02-10 10:46           ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-10 10:46 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

On Thu, Feb 10, 2011 at 06:03:19PM +0800, Richard Zhao wrote:
> On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
> > On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
> > 
> > Hi Jeremy,
> > 
> > Couple more comments below.
> > 
> > ~Ryan
> > 
> [...]
> > > +int clk_enable(struct clk *clk)
> > > +{
> > > +     unsigned long flags;
> > > +     int ret = 0;
> > > +
> > > +     spin_lock_irqsave(&clk->enable_lock, flags);
> > 
> >         WARN_ON(clk->prepare_count = 0); ?
> > 
> > > +     if (clk->enable_count = 0 && clk->ops->enable)
> > > +             ret = clk->ops->enable(clk);
> > 
> > Does it make sense to have a clock with no enable function which still
> > returns success from clk_enable? Do we have any platforms which have
> > NULL clk_enable functions?
> > 
> > I think that for enable/disable at least we should require platforms to
> > provide functions and oops if they have failed to do so. In the rare
> > case that a platform doesn't need to do anything for enable/disable they
> > can just supply empty functions.
> It's possible to be NULL. So are set_rate/get_rate.
> Ideally, if it's NULL: 
> prepare/unprepare: only call parent's prepare/unprepare
> enable/disable: only call parent's enable/disable
> set_rate: fail
> get_rate: reture parent's get_rate
> set_parent: fail
> get_parent: fail
I wouldn't hard-code the parents into the generic functions.  But I
suggest to provide generic callbacks to do this, e.g.

clk_get_rate_from_parent(struct clk *c)
{
	struct clk *parent = clk_get_parent(c);

	return clk_get_rate(parent);
}

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-10 10:46           ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-10 10:46 UTC (permalink / raw)
  To: Richard Zhao
  Cc: Ryan Mallon, Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	linux-kernel, Paul Mundt, Saravana Kannan, Ben Dooks,
	Russell King, Jeremy Kerr, linux-arm-kernel

Hello,

On Thu, Feb 10, 2011 at 06:03:19PM +0800, Richard Zhao wrote:
> On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
> > On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
> > 
> > Hi Jeremy,
> > 
> > Couple more comments below.
> > 
> > ~Ryan
> > 
> [...]
> > > +int clk_enable(struct clk *clk)
> > > +{
> > > +     unsigned long flags;
> > > +     int ret = 0;
> > > +
> > > +     spin_lock_irqsave(&clk->enable_lock, flags);
> > 
> >         WARN_ON(clk->prepare_count == 0); ?
> > 
> > > +     if (clk->enable_count == 0 && clk->ops->enable)
> > > +             ret = clk->ops->enable(clk);
> > 
> > Does it make sense to have a clock with no enable function which still
> > returns success from clk_enable? Do we have any platforms which have
> > NULL clk_enable functions?
> > 
> > I think that for enable/disable at least we should require platforms to
> > provide functions and oops if they have failed to do so. In the rare
> > case that a platform doesn't need to do anything for enable/disable they
> > can just supply empty functions.
> It's possible to be NULL. So are set_rate/get_rate.
> Ideally, if it's NULL: 
> prepare/unprepare: only call parent's prepare/unprepare
> enable/disable: only call parent's enable/disable
> set_rate: fail
> get_rate: reture parent's get_rate
> set_parent: fail
> get_parent: fail
I wouldn't hard-code the parents into the generic functions.  But I
suggest to provide generic callbacks to do this, e.g.

clk_get_rate_from_parent(struct clk *c)
{
	struct clk *parent = clk_get_parent(c);

	return clk_get_rate(parent);
}

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-10 10:46           ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-10 10:46 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

On Thu, Feb 10, 2011 at 06:03:19PM +0800, Richard Zhao wrote:
> On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
> > On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
> > 
> > Hi Jeremy,
> > 
> > Couple more comments below.
> > 
> > ~Ryan
> > 
> [...]
> > > +int clk_enable(struct clk *clk)
> > > +{
> > > +     unsigned long flags;
> > > +     int ret = 0;
> > > +
> > > +     spin_lock_irqsave(&clk->enable_lock, flags);
> > 
> >         WARN_ON(clk->prepare_count == 0); ?
> > 
> > > +     if (clk->enable_count == 0 && clk->ops->enable)
> > > +             ret = clk->ops->enable(clk);
> > 
> > Does it make sense to have a clock with no enable function which still
> > returns success from clk_enable? Do we have any platforms which have
> > NULL clk_enable functions?
> > 
> > I think that for enable/disable at least we should require platforms to
> > provide functions and oops if they have failed to do so. In the rare
> > case that a platform doesn't need to do anything for enable/disable they
> > can just supply empty functions.
> It's possible to be NULL. So are set_rate/get_rate.
> Ideally, if it's NULL: 
> prepare/unprepare: only call parent's prepare/unprepare
> enable/disable: only call parent's enable/disable
> set_rate: fail
> get_rate: reture parent's get_rate
> set_parent: fail
> get_parent: fail
I wouldn't hard-code the parents into the generic functions.  But I
suggest to provide generic callbacks to do this, e.g.

clk_get_rate_from_parent(struct clk *c)
{
	struct clk *parent = clk_get_parent(c);

	return clk_get_rate(parent);
}

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-10 10:10           ` Ryan Mallon
  (?)
@ 2011-02-10 12:45             ` Richard Zhao
  -1 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-10 12:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 10, 2011 at 11:10:52PM +1300, Ryan Mallon wrote:
> On 10/02/11 23:03, Richard Zhao wrote:
> >On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
> >>On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
> >>
> >>Hi Jeremy,
> >>
> >>Couple more comments below.
> >>
> >>~Ryan
> >>
> >[...]
> >>>+int clk_enable(struct clk *clk)
> >>>+{
> >>>+     unsigned long flags;
> >>>+     int ret = 0;
> >>>+
> >>>+     spin_lock_irqsave(&clk->enable_lock, flags);
> >>         WARN_ON(clk->prepare_count = 0); ?
> >>
> >>>+     if (clk->enable_count = 0&&  clk->ops->enable)
> >>>+             ret = clk->ops->enable(clk);
> >>Does it make sense to have a clock with no enable function which still
> >>returns success from clk_enable? Do we have any platforms which have
> >>NULL clk_enable functions?
> >>
> >>I think that for enable/disable at least we should require platforms to
> >>provide functions and oops if they have failed to do so. In the rare
> >>case that a platform doesn't need to do anything for enable/disable they
> >>can just supply empty functions.
> >It's possible to be NULL. So are set_rate/get_rate.
> >Ideally, if it's NULL:
> >prepare/unprepare: only call parent's prepare/unprepare
> >enable/disable: only call parent's enable/disable
> 
> No, the whole point of the generic framework is that _all_ clock
> users must call prepare/enable and disable/unprepare. Drivers, etc
> should not rely on underlying knowledge of a platform. This is why,
> for instance, clk_enable will warn if prepare count is zero.
> 
> However, I can see that a clock may be fully enabled by its prepare
> function and so the enable function is a no-op. User must still call
> both prepare and enable though. Perhaps this is what you meant?
I mean prepare/unprepare, enable/disable and get_rate ops null can be handled
in the common clock code. But it needs parent clock pointer.

Thanks
Richard
> 
> ~Ryan
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-10 12:45             ` Richard Zhao
  0 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-10 12:45 UTC (permalink / raw)
  To: Ryan Mallon
  Cc: Richard Zhao, Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	linux-kernel, Paul Mundt, Saravana Kannan, Ben Dooks,
	Uwe Kleine-König, Russell King, Jeremy Kerr,
	linux-arm-kernel

On Thu, Feb 10, 2011 at 11:10:52PM +1300, Ryan Mallon wrote:
> On 10/02/11 23:03, Richard Zhao wrote:
> >On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
> >>On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
> >>
> >>Hi Jeremy,
> >>
> >>Couple more comments below.
> >>
> >>~Ryan
> >>
> >[...]
> >>>+int clk_enable(struct clk *clk)
> >>>+{
> >>>+     unsigned long flags;
> >>>+     int ret = 0;
> >>>+
> >>>+     spin_lock_irqsave(&clk->enable_lock, flags);
> >>         WARN_ON(clk->prepare_count == 0); ?
> >>
> >>>+     if (clk->enable_count == 0&&  clk->ops->enable)
> >>>+             ret = clk->ops->enable(clk);
> >>Does it make sense to have a clock with no enable function which still
> >>returns success from clk_enable? Do we have any platforms which have
> >>NULL clk_enable functions?
> >>
> >>I think that for enable/disable at least we should require platforms to
> >>provide functions and oops if they have failed to do so. In the rare
> >>case that a platform doesn't need to do anything for enable/disable they
> >>can just supply empty functions.
> >It's possible to be NULL. So are set_rate/get_rate.
> >Ideally, if it's NULL:
> >prepare/unprepare: only call parent's prepare/unprepare
> >enable/disable: only call parent's enable/disable
> 
> No, the whole point of the generic framework is that _all_ clock
> users must call prepare/enable and disable/unprepare. Drivers, etc
> should not rely on underlying knowledge of a platform. This is why,
> for instance, clk_enable will warn if prepare count is zero.
> 
> However, I can see that a clock may be fully enabled by its prepare
> function and so the enable function is a no-op. User must still call
> both prepare and enable though. Perhaps this is what you meant?
I mean prepare/unprepare, enable/disable and get_rate ops null can be handled
in the common clock code. But it needs parent clock pointer.

Thanks
Richard
> 
> ~Ryan
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-10 12:45             ` Richard Zhao
  0 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-10 12:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 10, 2011 at 11:10:52PM +1300, Ryan Mallon wrote:
> On 10/02/11 23:03, Richard Zhao wrote:
> >On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
> >>On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
> >>
> >>Hi Jeremy,
> >>
> >>Couple more comments below.
> >>
> >>~Ryan
> >>
> >[...]
> >>>+int clk_enable(struct clk *clk)
> >>>+{
> >>>+     unsigned long flags;
> >>>+     int ret = 0;
> >>>+
> >>>+     spin_lock_irqsave(&clk->enable_lock, flags);
> >>         WARN_ON(clk->prepare_count == 0); ?
> >>
> >>>+     if (clk->enable_count == 0&&  clk->ops->enable)
> >>>+             ret = clk->ops->enable(clk);
> >>Does it make sense to have a clock with no enable function which still
> >>returns success from clk_enable? Do we have any platforms which have
> >>NULL clk_enable functions?
> >>
> >>I think that for enable/disable at least we should require platforms to
> >>provide functions and oops if they have failed to do so. In the rare
> >>case that a platform doesn't need to do anything for enable/disable they
> >>can just supply empty functions.
> >It's possible to be NULL. So are set_rate/get_rate.
> >Ideally, if it's NULL:
> >prepare/unprepare: only call parent's prepare/unprepare
> >enable/disable: only call parent's enable/disable
> 
> No, the whole point of the generic framework is that _all_ clock
> users must call prepare/enable and disable/unprepare. Drivers, etc
> should not rely on underlying knowledge of a platform. This is why,
> for instance, clk_enable will warn if prepare count is zero.
> 
> However, I can see that a clock may be fully enabled by its prepare
> function and so the enable function is a no-op. User must still call
> both prepare and enable though. Perhaps this is what you meant?
I mean prepare/unprepare, enable/disable and get_rate ops null can be handled
in the common clock code. But it needs parent clock pointer.

Thanks
Richard
> 
> ~Ryan
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-10 10:46           ` Uwe Kleine-König
  (?)
@ 2011-02-10 13:08             ` Richard Zhao
  -1 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-10 13:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 10, 2011 at 11:46:39AM +0100, Uwe Kleine-König wrote:
> Hello,
> 
> On Thu, Feb 10, 2011 at 06:03:19PM +0800, Richard Zhao wrote:
> > On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
> > > On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
> > > 
> > > Hi Jeremy,
> > > 
> > > Couple more comments below.
> > > 
> > > ~Ryan
> > > 
> > [...]
> > > > +int clk_enable(struct clk *clk)
> > > > +{
> > > > +     unsigned long flags;
> > > > +     int ret = 0;
> > > > +
> > > > +     spin_lock_irqsave(&clk->enable_lock, flags);
> > > 
> > >         WARN_ON(clk->prepare_count = 0); ?
> > > 
> > > > +     if (clk->enable_count = 0 && clk->ops->enable)
> > > > +             ret = clk->ops->enable(clk);
> > > 
> > > Does it make sense to have a clock with no enable function which still
> > > returns success from clk_enable? Do we have any platforms which have
> > > NULL clk_enable functions?
> > > 
> > > I think that for enable/disable at least we should require platforms to
> > > provide functions and oops if they have failed to do so. In the rare
> > > case that a platform doesn't need to do anything for enable/disable they
> > > can just supply empty functions.
> > It's possible to be NULL. So are set_rate/get_rate.
> > Ideally, if it's NULL: 
> > prepare/unprepare: only call parent's prepare/unprepare
> > enable/disable: only call parent's enable/disable
> > set_rate: fail
> > get_rate: reture parent's get_rate
> > set_parent: fail
> > get_parent: fail
> I wouldn't hard-code the parents into the generic functions.  But I
> suggest to provide generic callbacks to do this, e.g.
Why? what restriction will it cause to add parent in clk?
Two benifits at least I can see:
1. null ops handle, as I said above.
2. export clock tree to user level for debug. It's very helpfull.

Thanks
Richard
> 
> clk_get_rate_from_parent(struct clk *c)
> {
> 	struct clk *parent = clk_get_parent(c);
> 
> 	return clk_get_rate(parent);
> }
> 
> Best regards
> Uwe
> 
> -- 
> Pengutronix e.K.                           | Uwe Kleine-König            |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-10 13:08             ` Richard Zhao
  0 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-10 13:08 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Richard Zhao, Nicolas Pitre, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	linux-kernel, Ryan Mallon, Dima Zavin, Saravana Kannan,
	Ben Dooks, Russell King, Jeremy Kerr, linux-arm-kernel

On Thu, Feb 10, 2011 at 11:46:39AM +0100, Uwe Kleine-König wrote:
> Hello,
> 
> On Thu, Feb 10, 2011 at 06:03:19PM +0800, Richard Zhao wrote:
> > On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
> > > On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
> > > 
> > > Hi Jeremy,
> > > 
> > > Couple more comments below.
> > > 
> > > ~Ryan
> > > 
> > [...]
> > > > +int clk_enable(struct clk *clk)
> > > > +{
> > > > +     unsigned long flags;
> > > > +     int ret = 0;
> > > > +
> > > > +     spin_lock_irqsave(&clk->enable_lock, flags);
> > > 
> > >         WARN_ON(clk->prepare_count == 0); ?
> > > 
> > > > +     if (clk->enable_count == 0 && clk->ops->enable)
> > > > +             ret = clk->ops->enable(clk);
> > > 
> > > Does it make sense to have a clock with no enable function which still
> > > returns success from clk_enable? Do we have any platforms which have
> > > NULL clk_enable functions?
> > > 
> > > I think that for enable/disable at least we should require platforms to
> > > provide functions and oops if they have failed to do so. In the rare
> > > case that a platform doesn't need to do anything for enable/disable they
> > > can just supply empty functions.
> > It's possible to be NULL. So are set_rate/get_rate.
> > Ideally, if it's NULL: 
> > prepare/unprepare: only call parent's prepare/unprepare
> > enable/disable: only call parent's enable/disable
> > set_rate: fail
> > get_rate: reture parent's get_rate
> > set_parent: fail
> > get_parent: fail
> I wouldn't hard-code the parents into the generic functions.  But I
> suggest to provide generic callbacks to do this, e.g.
Why? what restriction will it cause to add parent in clk?
Two benifits at least I can see:
1. null ops handle, as I said above.
2. export clock tree to user level for debug. It's very helpfull.

Thanks
Richard
> 
> clk_get_rate_from_parent(struct clk *c)
> {
> 	struct clk *parent = clk_get_parent(c);
> 
> 	return clk_get_rate(parent);
> }
> 
> Best regards
> Uwe
> 
> -- 
> Pengutronix e.K.                           | Uwe Kleine-König            |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-10 13:08             ` Richard Zhao
  0 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-10 13:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 10, 2011 at 11:46:39AM +0100, Uwe Kleine-K?nig wrote:
> Hello,
> 
> On Thu, Feb 10, 2011 at 06:03:19PM +0800, Richard Zhao wrote:
> > On Thu, Feb 10, 2011 at 09:21:14AM +1300, Ryan Mallon wrote:
> > > On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
> > > 
> > > Hi Jeremy,
> > > 
> > > Couple more comments below.
> > > 
> > > ~Ryan
> > > 
> > [...]
> > > > +int clk_enable(struct clk *clk)
> > > > +{
> > > > +     unsigned long flags;
> > > > +     int ret = 0;
> > > > +
> > > > +     spin_lock_irqsave(&clk->enable_lock, flags);
> > > 
> > >         WARN_ON(clk->prepare_count == 0); ?
> > > 
> > > > +     if (clk->enable_count == 0 && clk->ops->enable)
> > > > +             ret = clk->ops->enable(clk);
> > > 
> > > Does it make sense to have a clock with no enable function which still
> > > returns success from clk_enable? Do we have any platforms which have
> > > NULL clk_enable functions?
> > > 
> > > I think that for enable/disable at least we should require platforms to
> > > provide functions and oops if they have failed to do so. In the rare
> > > case that a platform doesn't need to do anything for enable/disable they
> > > can just supply empty functions.
> > It's possible to be NULL. So are set_rate/get_rate.
> > Ideally, if it's NULL: 
> > prepare/unprepare: only call parent's prepare/unprepare
> > enable/disable: only call parent's enable/disable
> > set_rate: fail
> > get_rate: reture parent's get_rate
> > set_parent: fail
> > get_parent: fail
> I wouldn't hard-code the parents into the generic functions.  But I
> suggest to provide generic callbacks to do this, e.g.
Why? what restriction will it cause to add parent in clk?
Two benifits at least I can see:
1. null ops handle, as I said above.
2. export clock tree to user level for debug. It's very helpfull.

Thanks
Richard
> 
> clk_get_rate_from_parent(struct clk *c)
> {
> 	struct clk *parent = clk_get_parent(c);
> 
> 	return clk_get_rate(parent);
> }
> 
> Best regards
> Uwe
> 
> -- 
> Pengutronix e.K.                           | Uwe Kleine-K?nig            |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-10 13:08             ` Richard Zhao
  (?)
@ 2011-02-10 13:13               ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-10 13:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 10, 2011 at 09:08:00PM +0800, Richard Zhao wrote:
> Why? what restriction will it cause to add parent in clk?
> Two benifits at least I can see:
> 1. null ops handle, as I said above.
> 2. export clock tree to user level for debug. It's very helpfull.

Don't be tempted to expand what's done at the generic level.  Platforms
may need special handling at the current clock level before the parent
clock level is considered.  Also platforms may not have parents so it
becomes mere bloat.

The more complicated the generic level becomes, the more platforms won't
covert to it.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-10 13:13               ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-10 13:13 UTC (permalink / raw)
  To: Richard Zhao
  Cc: Uwe Kleine-König, Richard Zhao, Nicolas Pitre,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Sascha Hauer, Paul Mundt, linux-kernel, Ryan Mallon, Dima Zavin,
	Saravana Kannan, Ben Dooks, Jeremy Kerr, linux-arm-kernel

On Thu, Feb 10, 2011 at 09:08:00PM +0800, Richard Zhao wrote:
> Why? what restriction will it cause to add parent in clk?
> Two benifits at least I can see:
> 1. null ops handle, as I said above.
> 2. export clock tree to user level for debug. It's very helpfull.

Don't be tempted to expand what's done at the generic level.  Platforms
may need special handling at the current clock level before the parent
clock level is considered.  Also platforms may not have parents so it
becomes mere bloat.

The more complicated the generic level becomes, the more platforms won't
covert to it.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-10 13:13               ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-10 13:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 10, 2011 at 09:08:00PM +0800, Richard Zhao wrote:
> Why? what restriction will it cause to add parent in clk?
> Two benifits at least I can see:
> 1. null ops handle, as I said above.
> 2. export clock tree to user level for debug. It's very helpfull.

Don't be tempted to expand what's done at the generic level.  Platforms
may need special handling at the current clock level before the parent
clock level is considered.  Also platforms may not have parents so it
becomes mere bloat.

The more complicated the generic level becomes, the more platforms won't
covert to it.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
  2011-02-09  6:41     ` Jeremy Kerr
  (?)
@ 2011-02-10 23:23       ` Ryan Mallon
  -1 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-10 23:23 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
> Since most platforms will need a fixed-rate clock, add one. This will
> also serve as a basic example of an implementation of struct clk.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/clk.c   |   14 ++++++++++++++
>  include/linux/clk.h |   16 ++++++++++++++++
>  2 files changed, 30 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index c35478a..bbbdb0d 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -124,3 +124,17 @@ void __clk_put(struct clk *clk)
>  	if (clk->ops->put)
>  		clk->ops->put(clk);
>  }
> +
> +/* clk_fixed support */
> +
> +#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
> +
> +static unsigned long clk_fixed_get_rate(struct clk *clk)
> +{
> +	return to_clk_fixed(clk)->rate;
> +}
> +
> +struct clk_ops clk_fixed_ops = {
> +	.get_rate = clk_fixed_get_rate,
> +};
> +EXPORT_SYMBOL_GPL(clk_fixed_ops);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index fe806b7..e67fdb0 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -185,6 +185,22 @@ static inline void clk_common_init(struct clk *clk)
>  	mutex_init(&clk->prepare_lock);
>  }
>  
> +/* Simple fixed-rate clock */
> +struct clk_fixed {
> +	struct clk	clk;
> +	unsigned long	rate;
> +};
> +
> +extern struct clk_ops clk_fixed_ops;
> +
> +#define INIT_CLK_FIXED(name, r) { \
> +	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
> +	.rate = (r) \
> +}

A fixed clock may still have other operations such as enable/disable.
Maybe do something like this instead:

#define INIT_CLK_FIXED(name, ops, r) { 		\
	.clk = INIT_CLK(name.clk, ops, rate), 	\
	.clk.ops.get_rate = clk_fixed_get_rate, \
	.rate = (r),				\
}

That's untested though. I'm not sure if you can reliably assign
something twice in a struct initialiser?

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan@bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
@ 2011-02-10 23:23       ` Ryan Mallon
  0 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-10 23:23 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, Dima Zavin, Saravana Kannan, Ben Dooks,
	Uwe Kleine-König, Russell King

On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
> Since most platforms will need a fixed-rate clock, add one. This will
> also serve as a basic example of an implementation of struct clk.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/clk.c   |   14 ++++++++++++++
>  include/linux/clk.h |   16 ++++++++++++++++
>  2 files changed, 30 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index c35478a..bbbdb0d 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -124,3 +124,17 @@ void __clk_put(struct clk *clk)
>  	if (clk->ops->put)
>  		clk->ops->put(clk);
>  }
> +
> +/* clk_fixed support */
> +
> +#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
> +
> +static unsigned long clk_fixed_get_rate(struct clk *clk)
> +{
> +	return to_clk_fixed(clk)->rate;
> +}
> +
> +struct clk_ops clk_fixed_ops = {
> +	.get_rate = clk_fixed_get_rate,
> +};
> +EXPORT_SYMBOL_GPL(clk_fixed_ops);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index fe806b7..e67fdb0 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -185,6 +185,22 @@ static inline void clk_common_init(struct clk *clk)
>  	mutex_init(&clk->prepare_lock);
>  }
>  
> +/* Simple fixed-rate clock */
> +struct clk_fixed {
> +	struct clk	clk;
> +	unsigned long	rate;
> +};
> +
> +extern struct clk_ops clk_fixed_ops;
> +
> +#define INIT_CLK_FIXED(name, r) { \
> +	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
> +	.rate = (r) \
> +}

A fixed clock may still have other operations such as enable/disable.
Maybe do something like this instead:

#define INIT_CLK_FIXED(name, ops, r) { 		\
	.clk = INIT_CLK(name.clk, ops, rate), 	\
	.clk.ops.get_rate = clk_fixed_get_rate, \
	.rate = (r),				\
}

That's untested though. I'm not sure if you can reliably assign
something twice in a struct initialiser?

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan@bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
@ 2011-02-10 23:23       ` Ryan Mallon
  0 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-10 23:23 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/09/2011 07:41 PM, Jeremy Kerr wrote:
> Since most platforms will need a fixed-rate clock, add one. This will
> also serve as a basic example of an implementation of struct clk.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/clk.c   |   14 ++++++++++++++
>  include/linux/clk.h |   16 ++++++++++++++++
>  2 files changed, 30 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index c35478a..bbbdb0d 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -124,3 +124,17 @@ void __clk_put(struct clk *clk)
>  	if (clk->ops->put)
>  		clk->ops->put(clk);
>  }
> +
> +/* clk_fixed support */
> +
> +#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
> +
> +static unsigned long clk_fixed_get_rate(struct clk *clk)
> +{
> +	return to_clk_fixed(clk)->rate;
> +}
> +
> +struct clk_ops clk_fixed_ops = {
> +	.get_rate = clk_fixed_get_rate,
> +};
> +EXPORT_SYMBOL_GPL(clk_fixed_ops);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index fe806b7..e67fdb0 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -185,6 +185,22 @@ static inline void clk_common_init(struct clk *clk)
>  	mutex_init(&clk->prepare_lock);
>  }
>  
> +/* Simple fixed-rate clock */
> +struct clk_fixed {
> +	struct clk	clk;
> +	unsigned long	rate;
> +};
> +
> +extern struct clk_ops clk_fixed_ops;
> +
> +#define INIT_CLK_FIXED(name, r) { \
> +	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
> +	.rate = (r) \
> +}

A fixed clock may still have other operations such as enable/disable.
Maybe do something like this instead:

#define INIT_CLK_FIXED(name, ops, r) { 		\
	.clk = INIT_CLK(name.clk, ops, rate), 	\
	.clk.ops.get_rate = clk_fixed_get_rate, \
	.rate = (r),				\
}

That's untested though. I'm not sure if you can reliably assign
something twice in a struct initialiser?

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-09 20:21       ` Ryan Mallon
  (?)
@ 2011-02-15  1:36         ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  1:36 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ryan,

> > +int clk_enable(struct clk *clk)
> > +{
> > +	unsigned long flags;
> > +	int ret = 0;
> > +
> > +	spin_lock_irqsave(&clk->enable_lock, flags);
> 
> 	WARN_ON(clk->prepare_count = 0); ?

Added later, but yes.

> 
> > +	if (clk->enable_count = 0 && clk->ops->enable)
> > +		ret = clk->ops->enable(clk);
> 
> Does it make sense to have a clock with no enable function which still
> returns success from clk_enable? Do we have any platforms which have
> NULL clk_enable functions?

It does, yes. Driver code should be always be calling clk_enable before using 
a clock, regardless of the implementation (which it shouldn't have to care 
abut), and should abort their initialisation if the clk_enable() fails.

Some clocks are always running, so the enable op will be empty. This is not an 
error, so the driver is free to continue.

> I think that for enable/disable at least we should require platforms to
> provide functions and oops if they have failed to do so. In the rare
> case that a platform doesn't need to do anything for enable/disable they
> can just supply empty functions.

Sounds like useless boilerplate - it's not an error to not need 
enable/disable, so I don't see why we need to add extra effort to handle this 
case.

> > +/**
> > + * __clk_get - acquire a reference to a clock
> > + *
> > + * @clk: The clock to refcount
> > + *
> > + * Before a clock is returned from clk_get, this function should be
> > called + * to update any clock-specific refcounting.
> 
> This is a bit misleading. It's not "should be called", it "is called". I
> think you should just remove the documentation for __clk_get/__clk_put
> or move it into clk.c since the functions are only used internally by
> the common clock code.

It'd be nice to remove this from the header, but this means we'll need extern 
prototypes in clkdev.c. Might be a reasonable compromise though.


> > +/**
> > + * clk_prepare - prepare clock for atomic enabling.
> > + *
> > + * @clk: The clock to prepare
> > + *
> > + * Do any blocking initialisation on @clk, allowing the clock to be
> > later + * enabled atomically (via clk_enable). This function may sleep.
> 
> "Possibly blocking" as below?

Yep, will unify these (and spell "possibly" correctly :) )

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-15  1:36         ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  1:36 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Ryan Mallon, Nicolas Pitre, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	linux-kernel, Dima Zavin, Saravana Kannan, Ben Dooks,
	Uwe Kleine-König, Russell King

Hi Ryan,

> > +int clk_enable(struct clk *clk)
> > +{
> > +	unsigned long flags;
> > +	int ret = 0;
> > +
> > +	spin_lock_irqsave(&clk->enable_lock, flags);
> 
> 	WARN_ON(clk->prepare_count == 0); ?

Added later, but yes.

> 
> > +	if (clk->enable_count == 0 && clk->ops->enable)
> > +		ret = clk->ops->enable(clk);
> 
> Does it make sense to have a clock with no enable function which still
> returns success from clk_enable? Do we have any platforms which have
> NULL clk_enable functions?

It does, yes. Driver code should be always be calling clk_enable before using 
a clock, regardless of the implementation (which it shouldn't have to care 
abut), and should abort their initialisation if the clk_enable() fails.

Some clocks are always running, so the enable op will be empty. This is not an 
error, so the driver is free to continue.

> I think that for enable/disable at least we should require platforms to
> provide functions and oops if they have failed to do so. In the rare
> case that a platform doesn't need to do anything for enable/disable they
> can just supply empty functions.

Sounds like useless boilerplate - it's not an error to not need 
enable/disable, so I don't see why we need to add extra effort to handle this 
case.

> > +/**
> > + * __clk_get - acquire a reference to a clock
> > + *
> > + * @clk: The clock to refcount
> > + *
> > + * Before a clock is returned from clk_get, this function should be
> > called + * to update any clock-specific refcounting.
> 
> This is a bit misleading. It's not "should be called", it "is called". I
> think you should just remove the documentation for __clk_get/__clk_put
> or move it into clk.c since the functions are only used internally by
> the common clock code.

It'd be nice to remove this from the header, but this means we'll need extern 
prototypes in clkdev.c. Might be a reasonable compromise though.


> > +/**
> > + * clk_prepare - prepare clock for atomic enabling.
> > + *
> > + * @clk: The clock to prepare
> > + *
> > + * Do any blocking initialisation on @clk, allowing the clock to be
> > later + * enabled atomically (via clk_enable). This function may sleep.
> 
> "Possibly blocking" as below?

Yep, will unify these (and spell "possibly" correctly :) )

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-15  1:36         ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  1:36 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ryan,

> > +int clk_enable(struct clk *clk)
> > +{
> > +	unsigned long flags;
> > +	int ret = 0;
> > +
> > +	spin_lock_irqsave(&clk->enable_lock, flags);
> 
> 	WARN_ON(clk->prepare_count == 0); ?

Added later, but yes.

> 
> > +	if (clk->enable_count == 0 && clk->ops->enable)
> > +		ret = clk->ops->enable(clk);
> 
> Does it make sense to have a clock with no enable function which still
> returns success from clk_enable? Do we have any platforms which have
> NULL clk_enable functions?

It does, yes. Driver code should be always be calling clk_enable before using 
a clock, regardless of the implementation (which it shouldn't have to care 
abut), and should abort their initialisation if the clk_enable() fails.

Some clocks are always running, so the enable op will be empty. This is not an 
error, so the driver is free to continue.

> I think that for enable/disable at least we should require platforms to
> provide functions and oops if they have failed to do so. In the rare
> case that a platform doesn't need to do anything for enable/disable they
> can just supply empty functions.

Sounds like useless boilerplate - it's not an error to not need 
enable/disable, so I don't see why we need to add extra effort to handle this 
case.

> > +/**
> > + * __clk_get - acquire a reference to a clock
> > + *
> > + * @clk: The clock to refcount
> > + *
> > + * Before a clock is returned from clk_get, this function should be
> > called + * to update any clock-specific refcounting.
> 
> This is a bit misleading. It's not "should be called", it "is called". I
> think you should just remove the documentation for __clk_get/__clk_put
> or move it into clk.c since the functions are only used internally by
> the common clock code.

It'd be nice to remove this from the header, but this means we'll need extern 
prototypes in clkdev.c. Might be a reasonable compromise though.


> > +/**
> > + * clk_prepare - prepare clock for atomic enabling.
> > + *
> > + * @clk: The clock to prepare
> > + *
> > + * Do any blocking initialisation on @clk, allowing the clock to be
> > later + * enabled atomically (via clk_enable). This function may sleep.
> 
> "Possibly blocking" as below?

Yep, will unify these (and spell "possibly" correctly :) )

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
  2011-02-10 23:23       ` Ryan Mallon
  (?)
@ 2011-02-15  1:41         ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  1:41 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ryan,

> A fixed clock may still have other operations such as enable/disable.

Then it's not a fixed clock; I'd prefer this to be a separate type, as it's 
now hardware dependent.

> Maybe do something like this instead:
> #define INIT_CLK_FIXED(name, ops, r) { 		\
> 	.clk = INIT_CLK(name.clk, ops, rate), 	\
> 	.clk.ops.get_rate = clk_fixed_get_rate, \
> 	.rate = (r),				\
> }
> 
> That's untested though. I'm not sure if you can reliably assign
> something twice in a struct initialiser?

also, clk->ops is a const.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
@ 2011-02-15  1:41         ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  1:41 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Ryan Mallon, Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	linux-kernel, Paul Mundt, Saravana Kannan, Ben Dooks,
	Uwe Kleine-König, Russell King

Hi Ryan,

> A fixed clock may still have other operations such as enable/disable.

Then it's not a fixed clock; I'd prefer this to be a separate type, as it's 
now hardware dependent.

> Maybe do something like this instead:
> #define INIT_CLK_FIXED(name, ops, r) { 		\
> 	.clk = INIT_CLK(name.clk, ops, rate), 	\
> 	.clk.ops.get_rate = clk_fixed_get_rate, \
> 	.rate = (r),				\
> }
> 
> That's untested though. I'm not sure if you can reliably assign
> something twice in a struct initialiser?

also, clk->ops is a const.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
@ 2011-02-15  1:41         ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  1:41 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ryan,

> A fixed clock may still have other operations such as enable/disable.

Then it's not a fixed clock; I'd prefer this to be a separate type, as it's 
now hardware dependent.

> Maybe do something like this instead:
> #define INIT_CLK_FIXED(name, ops, r) { 		\
> 	.clk = INIT_CLK(name.clk, ops, rate), 	\
> 	.clk.ops.get_rate = clk_fixed_get_rate, \
> 	.rate = (r),				\
> }
> 
> That's untested though. I'm not sure if you can reliably assign
> something twice in a struct initialiser?

also, clk->ops is a const.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-15  1:36         ` Jeremy Kerr
  (?)
@ 2011-02-15  1:43           ` Ryan Mallon
  -1 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-15  1:43 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/15/2011 02:36 PM, Jeremy Kerr wrote:
> Hi Ryan,
> 
>>> +int clk_enable(struct clk *clk)
>>> +{
>>> +	unsigned long flags;
>>> +	int ret = 0;
>>> +
>>> +	spin_lock_irqsave(&clk->enable_lock, flags);
>>
>> 	WARN_ON(clk->prepare_count = 0); ?
> 
> Added later, but yes.

Okay, but still failing to understand why this isn't it the first patch.
You are introducing a new file after all.

>>
>>> +	if (clk->enable_count = 0 && clk->ops->enable)
>>> +		ret = clk->ops->enable(clk);
>>
>> Does it make sense to have a clock with no enable function which still
>> returns success from clk_enable? Do we have any platforms which have
>> NULL clk_enable functions?
> 
> It does, yes. Driver code should be always be calling clk_enable before using 
> a clock, regardless of the implementation (which it shouldn't have to care 
> abut), and should abort their initialisation if the clk_enable() fails.
> 
> Some clocks are always running, so the enable op will be empty. This is not an 
> error, so the driver is free to continue.
> 
>> I think that for enable/disable at least we should require platforms to
>> provide functions and oops if they have failed to do so. In the rare
>> case that a platform doesn't need to do anything for enable/disable they
>> can just supply empty functions.
> 
> Sounds like useless boilerplate - it's not an error to not need 
> enable/disable, so I don't see why we need to add extra effort to handle this 
> case.

I have been convinced that enable/prepare potentially being NULL
callbacks is valid :-).

> 
>>> +/**
>>> + * __clk_get - acquire a reference to a clock
>>> + *
>>> + * @clk: The clock to refcount
>>> + *
>>> + * Before a clock is returned from clk_get, this function should be
>>> called + * to update any clock-specific refcounting.
>>
>> This is a bit misleading. It's not "should be called", it "is called". I
>> think you should just remove the documentation for __clk_get/__clk_put
>> or move it into clk.c since the functions are only used internally by
>> the common clock code.
> 
> It'd be nice to remove this from the header, but this means we'll need extern 
> prototypes in clkdev.c. Might be a reasonable compromise though.

That's probably a better approach anyway, since that makes it blatantly
obvious that the __clk_get and __clk_put functions should not be called
from anywhere except clkdev.c.

> 
>>> +/**
>>> + * clk_prepare - prepare clock for atomic enabling.
>>> + *
>>> + * @clk: The clock to prepare
>>> + *
>>> + * Do any blocking initialisation on @clk, allowing the clock to be
>>> later + * enabled atomically (via clk_enable). This function may sleep.
>>
>> "Possibly blocking" as below?
> 
> Yep, will unify these (and spell "possibly" correctly :) )

:-)

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan@bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-15  1:43           ` Ryan Mallon
  0 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-15  1:43 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, linux-kernel, Dima Zavin, Saravana Kannan, Ben Dooks,
	Uwe Kleine-König, Russell King

On 02/15/2011 02:36 PM, Jeremy Kerr wrote:
> Hi Ryan,
> 
>>> +int clk_enable(struct clk *clk)
>>> +{
>>> +	unsigned long flags;
>>> +	int ret = 0;
>>> +
>>> +	spin_lock_irqsave(&clk->enable_lock, flags);
>>
>> 	WARN_ON(clk->prepare_count == 0); ?
> 
> Added later, but yes.

Okay, but still failing to understand why this isn't it the first patch.
You are introducing a new file after all.

>>
>>> +	if (clk->enable_count == 0 && clk->ops->enable)
>>> +		ret = clk->ops->enable(clk);
>>
>> Does it make sense to have a clock with no enable function which still
>> returns success from clk_enable? Do we have any platforms which have
>> NULL clk_enable functions?
> 
> It does, yes. Driver code should be always be calling clk_enable before using 
> a clock, regardless of the implementation (which it shouldn't have to care 
> abut), and should abort their initialisation if the clk_enable() fails.
> 
> Some clocks are always running, so the enable op will be empty. This is not an 
> error, so the driver is free to continue.
> 
>> I think that for enable/disable at least we should require platforms to
>> provide functions and oops if they have failed to do so. In the rare
>> case that a platform doesn't need to do anything for enable/disable they
>> can just supply empty functions.
> 
> Sounds like useless boilerplate - it's not an error to not need 
> enable/disable, so I don't see why we need to add extra effort to handle this 
> case.

I have been convinced that enable/prepare potentially being NULL
callbacks is valid :-).

> 
>>> +/**
>>> + * __clk_get - acquire a reference to a clock
>>> + *
>>> + * @clk: The clock to refcount
>>> + *
>>> + * Before a clock is returned from clk_get, this function should be
>>> called + * to update any clock-specific refcounting.
>>
>> This is a bit misleading. It's not "should be called", it "is called". I
>> think you should just remove the documentation for __clk_get/__clk_put
>> or move it into clk.c since the functions are only used internally by
>> the common clock code.
> 
> It'd be nice to remove this from the header, but this means we'll need extern 
> prototypes in clkdev.c. Might be a reasonable compromise though.

That's probably a better approach anyway, since that makes it blatantly
obvious that the __clk_get and __clk_put functions should not be called
from anywhere except clkdev.c.

> 
>>> +/**
>>> + * clk_prepare - prepare clock for atomic enabling.
>>> + *
>>> + * @clk: The clock to prepare
>>> + *
>>> + * Do any blocking initialisation on @clk, allowing the clock to be
>>> later + * enabled atomically (via clk_enable). This function may sleep.
>>
>> "Possibly blocking" as below?
> 
> Yep, will unify these (and spell "possibly" correctly :) )

:-)

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan@bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-15  1:43           ` Ryan Mallon
  0 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-15  1:43 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/15/2011 02:36 PM, Jeremy Kerr wrote:
> Hi Ryan,
> 
>>> +int clk_enable(struct clk *clk)
>>> +{
>>> +	unsigned long flags;
>>> +	int ret = 0;
>>> +
>>> +	spin_lock_irqsave(&clk->enable_lock, flags);
>>
>> 	WARN_ON(clk->prepare_count == 0); ?
> 
> Added later, but yes.

Okay, but still failing to understand why this isn't it the first patch.
You are introducing a new file after all.

>>
>>> +	if (clk->enable_count == 0 && clk->ops->enable)
>>> +		ret = clk->ops->enable(clk);
>>
>> Does it make sense to have a clock with no enable function which still
>> returns success from clk_enable? Do we have any platforms which have
>> NULL clk_enable functions?
> 
> It does, yes. Driver code should be always be calling clk_enable before using 
> a clock, regardless of the implementation (which it shouldn't have to care 
> abut), and should abort their initialisation if the clk_enable() fails.
> 
> Some clocks are always running, so the enable op will be empty. This is not an 
> error, so the driver is free to continue.
> 
>> I think that for enable/disable at least we should require platforms to
>> provide functions and oops if they have failed to do so. In the rare
>> case that a platform doesn't need to do anything for enable/disable they
>> can just supply empty functions.
> 
> Sounds like useless boilerplate - it's not an error to not need 
> enable/disable, so I don't see why we need to add extra effort to handle this 
> case.

I have been convinced that enable/prepare potentially being NULL
callbacks is valid :-).

> 
>>> +/**
>>> + * __clk_get - acquire a reference to a clock
>>> + *
>>> + * @clk: The clock to refcount
>>> + *
>>> + * Before a clock is returned from clk_get, this function should be
>>> called + * to update any clock-specific refcounting.
>>
>> This is a bit misleading. It's not "should be called", it "is called". I
>> think you should just remove the documentation for __clk_get/__clk_put
>> or move it into clk.c since the functions are only used internally by
>> the common clock code.
> 
> It'd be nice to remove this from the header, but this means we'll need extern 
> prototypes in clkdev.c. Might be a reasonable compromise though.

That's probably a better approach anyway, since that makes it blatantly
obvious that the __clk_get and __clk_put functions should not be called
from anywhere except clkdev.c.

> 
>>> +/**
>>> + * clk_prepare - prepare clock for atomic enabling.
>>> + *
>>> + * @clk: The clock to prepare
>>> + *
>>> + * Do any blocking initialisation on @clk, allowing the clock to be
>>> later + * enabled atomically (via clk_enable). This function may sleep.
>>
>> "Possibly blocking" as below?
> 
> Yep, will unify these (and spell "possibly" correctly :) )

:-)

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
  2011-02-10  9:37       ` Richard Zhao
  (?)
@ 2011-02-15  2:00         ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  2:00 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Richard,

> >  void clk_unprepare(struct clk *clk)
> >  {
> > 
> > +	WARN_ON(clk->enable_count != 0);
> > +
> 
> Other drivers may be using the clock and increased the enable_count.
> This check may be moved to where we actually do unprepare.

Of course, thanks. Will update the series.


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-15  2:00         ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  2:00 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Richard Zhao, Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	linux-kernel, Paul Mundt, Saravana Kannan, Ben Dooks,
	Uwe Kleine-König, Russell King

Hi Richard,

> >  void clk_unprepare(struct clk *clk)
> >  {
> > 
> > +	WARN_ON(clk->enable_count != 0);
> > +
> 
> Other drivers may be using the clock and increased the enable_count.
> This check may be moved to where we actually do unprepare.

Of course, thanks. Will update the series.


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics
@ 2011-02-15  2:00         ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  2:00 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Richard,

> >  void clk_unprepare(struct clk *clk)
> >  {
> > 
> > +	WARN_ON(clk->enable_count != 0);
> > +
> 
> Other drivers may be using the clock and increased the enable_count.
> This check may be moved to where we actually do unprepare.

Of course, thanks. Will update the series.


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-10  5:16       ` Saravana Kannan
  (?)
@ 2011-02-15  2:41         ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  2:41 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Saravana,

> Shouldn't you be grabbing the prepare_lock here?

This depends on semantics that (as far as I can tell) aren't defined yet. We 
may even want to disallow set_rate (and set_parent) when prepare_count is non-
zero.

Ideally, we should work out what the semantics are with regards to changing a 
clock's rate when it has multiple users and/or is enabled or prepared, but 
that's a separate issue, and we should *definitely* implement that as a 
separate change.

I'd prefer to enforce the 'sleepability' with might_sleep instead.

> You should probably rename the lock to something else since it's not
> limited to prepare/unprepare. How about resource_lock?

It's not, but that's the only thing it's protecting in the common code. I'm 
open for better names, but resource_lock is too generic.

> > +int clk_set_parent(struct clk *clk, struct clk *parent)
> > +{
> > +	if (clk->ops->set_parent)
> > +		return clk->ops->set_parent(clk, parent);
> 
> I'm not sure on this one. If the prepare ops for a clock also calls the
> prepare ops on the parent, shouldn't we prevent changing the parent
> while the prepare/unprepare is going on?

Again, this is related to set_rate during enable/disable or prepare/unprepare; 
we don't have defined semantics for this at present.

> > +
> > +/* static initialiser for clocks */
> > +#define INIT_CLK(name, o) {						\
> > +	.ops		=&o,						\
> > +	.enable_count	= 0,						\
> > +	.prepare_count	= 0,						\
> 
> Do we need these inits? Doesn't check patch complain about initing
> static/global to 0? If it's generally frowned upon, why the exception
> here. I realize that checkpatch won't catch this, but still...

This took some reading through c99, but yes, it looks like we can drop these 
zero initialisations.

However, the coding style convention for the implicit zeroing of static 
variables is to allow these variables to be put into the .bss section, 
reducing object size. In this case, the clock will never be able to go into 
.bss (it has non-zero elements too), and so this will have no change on object 
size. I prefer to be explicit here, and show that the counts are initialised 
to zero.

I'm happy to go either way. I have a preference for the explicit 
initialisation, but that may not be general style.

> 
> > +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> > +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
> 
> After a long day, I'm not able to wrap my head around this. Probably a
> stupid question, but will this name.xxx thing prevent using this
> INIT_CLK macro to initialize an array of clocks? More specifically,
> prevent the sub class macro (like INIT_CLK_FIXED) from being used to
> initialize an array of clocks?

That's correct. For an array of clocks, you'll have to use a different 
initialiser. We can add helpers for that that when (and if) the need arises.

> > + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> > + * implementations to split any work between atomic (enable) and
> > sleepable + * (prepare) contexts.  If a clock requires blocking code to
> > be turned on, this
> 
> Aren't all locks blocking? Shouldn't it be, "If turning on a clock
> requires code that might sleep, it should be done in clk_prepare"?
> Replace all "blocking" with "sleepable" or "sleeping" in the comments?

I think "blocking" is generally accepted as is intended in this case, but it's 
probably better to be explicit here.
> 
> > + * should be done in clk_prepare. Switching that will not block should
> > be done + * in clk_enable.
> > + *
> > + * Typically, drivers will call clk_prepare when a clock may be needed
> > later + * (eg. when a device is opened), and clk_enable when the clock
> > is actually + * required (eg. from an interrupt). Note that clk_prepare
> > *must* have been + * called before clk_enable.
> > + *
> > + * For other callbacks, see the corresponding clk_* functions.
> > Parameters and + * return values are passed directly from/to these API
> > functions, or + * -ENOSYS (or zero, in the case of clk_get_rate) is
> > returned if the callback + * is NULL, see kernel/clk.c for
> > implementation details. All are optional.
> 
> is NULL. See kernel... ?

Ah, yes, I'll update this.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-15  2:41         ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  2:41 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Saravana Kannan, Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	linux-kernel, Paul Mundt, Ben Dooks, Uwe Kleine-König,
	Russell King

Hi Saravana,

> Shouldn't you be grabbing the prepare_lock here?

This depends on semantics that (as far as I can tell) aren't defined yet. We 
may even want to disallow set_rate (and set_parent) when prepare_count is non-
zero.

Ideally, we should work out what the semantics are with regards to changing a 
clock's rate when it has multiple users and/or is enabled or prepared, but 
that's a separate issue, and we should *definitely* implement that as a 
separate change.

I'd prefer to enforce the 'sleepability' with might_sleep instead.

> You should probably rename the lock to something else since it's not
> limited to prepare/unprepare. How about resource_lock?

It's not, but that's the only thing it's protecting in the common code. I'm 
open for better names, but resource_lock is too generic.

> > +int clk_set_parent(struct clk *clk, struct clk *parent)
> > +{
> > +	if (clk->ops->set_parent)
> > +		return clk->ops->set_parent(clk, parent);
> 
> I'm not sure on this one. If the prepare ops for a clock also calls the
> prepare ops on the parent, shouldn't we prevent changing the parent
> while the prepare/unprepare is going on?

Again, this is related to set_rate during enable/disable or prepare/unprepare; 
we don't have defined semantics for this at present.

> > +
> > +/* static initialiser for clocks */
> > +#define INIT_CLK(name, o) {						\
> > +	.ops		=&o,						\
> > +	.enable_count	= 0,						\
> > +	.prepare_count	= 0,						\
> 
> Do we need these inits? Doesn't check patch complain about initing
> static/global to 0? If it's generally frowned upon, why the exception
> here. I realize that checkpatch won't catch this, but still...

This took some reading through c99, but yes, it looks like we can drop these 
zero initialisations.

However, the coding style convention for the implicit zeroing of static 
variables is to allow these variables to be put into the .bss section, 
reducing object size. In this case, the clock will never be able to go into 
.bss (it has non-zero elements too), and so this will have no change on object 
size. I prefer to be explicit here, and show that the counts are initialised 
to zero.

I'm happy to go either way. I have a preference for the explicit 
initialisation, but that may not be general style.

> 
> > +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> > +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
> 
> After a long day, I'm not able to wrap my head around this. Probably a
> stupid question, but will this name.xxx thing prevent using this
> INIT_CLK macro to initialize an array of clocks? More specifically,
> prevent the sub class macro (like INIT_CLK_FIXED) from being used to
> initialize an array of clocks?

That's correct. For an array of clocks, you'll have to use a different 
initialiser. We can add helpers for that that when (and if) the need arises.

> > + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> > + * implementations to split any work between atomic (enable) and
> > sleepable + * (prepare) contexts.  If a clock requires blocking code to
> > be turned on, this
> 
> Aren't all locks blocking? Shouldn't it be, "If turning on a clock
> requires code that might sleep, it should be done in clk_prepare"?
> Replace all "blocking" with "sleepable" or "sleeping" in the comments?

I think "blocking" is generally accepted as is intended in this case, but it's 
probably better to be explicit here.
> 
> > + * should be done in clk_prepare. Switching that will not block should
> > be done + * in clk_enable.
> > + *
> > + * Typically, drivers will call clk_prepare when a clock may be needed
> > later + * (eg. when a device is opened), and clk_enable when the clock
> > is actually + * required (eg. from an interrupt). Note that clk_prepare
> > *must* have been + * called before clk_enable.
> > + *
> > + * For other callbacks, see the corresponding clk_* functions.
> > Parameters and + * return values are passed directly from/to these API
> > functions, or + * -ENOSYS (or zero, in the case of clk_get_rate) is
> > returned if the callback + * is NULL, see kernel/clk.c for
> > implementation details. All are optional.
> 
> is NULL. See kernel... ?

Ah, yes, I'll update this.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-15  2:41         ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  2:41 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Saravana,

> Shouldn't you be grabbing the prepare_lock here?

This depends on semantics that (as far as I can tell) aren't defined yet. We 
may even want to disallow set_rate (and set_parent) when prepare_count is non-
zero.

Ideally, we should work out what the semantics are with regards to changing a 
clock's rate when it has multiple users and/or is enabled or prepared, but 
that's a separate issue, and we should *definitely* implement that as a 
separate change.

I'd prefer to enforce the 'sleepability' with might_sleep instead.

> You should probably rename the lock to something else since it's not
> limited to prepare/unprepare. How about resource_lock?

It's not, but that's the only thing it's protecting in the common code. I'm 
open for better names, but resource_lock is too generic.

> > +int clk_set_parent(struct clk *clk, struct clk *parent)
> > +{
> > +	if (clk->ops->set_parent)
> > +		return clk->ops->set_parent(clk, parent);
> 
> I'm not sure on this one. If the prepare ops for a clock also calls the
> prepare ops on the parent, shouldn't we prevent changing the parent
> while the prepare/unprepare is going on?

Again, this is related to set_rate during enable/disable or prepare/unprepare; 
we don't have defined semantics for this at present.

> > +
> > +/* static initialiser for clocks */
> > +#define INIT_CLK(name, o) {						\
> > +	.ops		=&o,						\
> > +	.enable_count	= 0,						\
> > +	.prepare_count	= 0,						\
> 
> Do we need these inits? Doesn't check patch complain about initing
> static/global to 0? If it's generally frowned upon, why the exception
> here. I realize that checkpatch won't catch this, but still...

This took some reading through c99, but yes, it looks like we can drop these 
zero initialisations.

However, the coding style convention for the implicit zeroing of static 
variables is to allow these variables to be put into the .bss section, 
reducing object size. In this case, the clock will never be able to go into 
.bss (it has non-zero elements too), and so this will have no change on object 
size. I prefer to be explicit here, and show that the counts are initialised 
to zero.

I'm happy to go either way. I have a preference for the explicit 
initialisation, but that may not be general style.

> 
> > +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> > +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
> 
> After a long day, I'm not able to wrap my head around this. Probably a
> stupid question, but will this name.xxx thing prevent using this
> INIT_CLK macro to initialize an array of clocks? More specifically,
> prevent the sub class macro (like INIT_CLK_FIXED) from being used to
> initialize an array of clocks?

That's correct. For an array of clocks, you'll have to use a different 
initialiser. We can add helpers for that that when (and if) the need arises.

> > + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> > + * implementations to split any work between atomic (enable) and
> > sleepable + * (prepare) contexts.  If a clock requires blocking code to
> > be turned on, this
> 
> Aren't all locks blocking? Shouldn't it be, "If turning on a clock
> requires code that might sleep, it should be done in clk_prepare"?
> Replace all "blocking" with "sleepable" or "sleeping" in the comments?

I think "blocking" is generally accepted as is intended in this case, but it's 
probably better to be explicit here.
> 
> > + * should be done in clk_prepare. Switching that will not block should
> > be done + * in clk_enable.
> > + *
> > + * Typically, drivers will call clk_prepare when a clock may be needed
> > later + * (eg. when a device is opened), and clk_enable when the clock
> > is actually + * required (eg. from an interrupt). Note that clk_prepare
> > *must* have been + * called before clk_enable.
> > + *
> > + * For other callbacks, see the corresponding clk_* functions.
> > Parameters and + * return values are passed directly from/to these API
> > functions, or + * -ENOSYS (or zero, in the case of clk_get_rate) is
> > returned if the callback + * is NULL, see kernel/clk.c for
> > implementation details. All are optional.
> 
> is NULL. See kernel... ?

Ah, yes, I'll update this.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
  2011-02-15  1:41         ` Jeremy Kerr
  (?)
@ 2011-02-15  4:51           ` Saravana Kannan
  -1 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-15  4:51 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/14/2011 05:41 PM, Jeremy Kerr wrote:
> Hi Ryan,
>
>> A fixed clock may still have other operations such as enable/disable.
>
> Then it's not a fixed clock; I'd prefer this to be a separate type, as it's
> now hardware dependent.
>

I'm confused. If a clock's rate can't be changed and it can't be enabled 
or disabled, then what's the point of representing that clock 
signal/line as a clock in the driver. Seems like a "nothing to see here, 
move along" type of clock. To express it differently, I find this 
similar to "if (1) { ... }". Obviously I'm missing something here. What 
is it?

-Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
@ 2011-02-15  4:51           ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-15  4:51 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, linux-kernel, Ryan Mallon, Dima Zavin, Ben Dooks,
	Uwe Kleine-König, Russell King

On 02/14/2011 05:41 PM, Jeremy Kerr wrote:
> Hi Ryan,
>
>> A fixed clock may still have other operations such as enable/disable.
>
> Then it's not a fixed clock; I'd prefer this to be a separate type, as it's
> now hardware dependent.
>

I'm confused. If a clock's rate can't be changed and it can't be enabled 
or disabled, then what's the point of representing that clock 
signal/line as a clock in the driver. Seems like a "nothing to see here, 
move along" type of clock. To express it differently, I find this 
similar to "if (1) { ... }". Obviously I'm missing something here. What 
is it?

-Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
@ 2011-02-15  4:51           ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-15  4:51 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/14/2011 05:41 PM, Jeremy Kerr wrote:
> Hi Ryan,
>
>> A fixed clock may still have other operations such as enable/disable.
>
> Then it's not a fixed clock; I'd prefer this to be a separate type, as it's
> now hardware dependent.
>

I'm confused. If a clock's rate can't be changed and it can't be enabled 
or disabled, then what's the point of representing that clock 
signal/line as a clock in the driver. Seems like a "nothing to see here, 
move along" type of clock. To express it differently, I find this 
similar to "if (1) { ... }". Obviously I'm missing something here. What 
is it?

-Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-15  2:41         ` Jeremy Kerr
  (?)
@ 2011-02-15  5:33           ` Saravana Kannan
  -1 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-15  5:33 UTC (permalink / raw)
  To: linux-arm-kernel


Russell, A question for you further down this email. Please take a look.

On 02/14/2011 06:41 PM, Jeremy Kerr wrote:
> Hi Saravana,
>
>> Shouldn't you be grabbing the prepare_lock here?
>
> This depends on semantics that (as far as I can tell) aren't defined yet.

Sure, one could argue that in some archs for a certain set of clocks the 
slow stuff in prepare/unprepare won't need to be done during set rate -- 
say, a simple clock that always runs off the same PLL but just has a 
integer divider to change the rate.

In those cases, not grabbing the prepare_lock would make the code less 
"locky".

> We
> may even want to disallow set_rate (and set_parent) when prepare_count is non-
> zero.

This is definitely not right. Changing the rate of a clock when it's 
already enabled/prepared is a very reasonable thing to do. It's only 
doing a set rate at the "same time" as a prepare/unprepare that's wrong 
for some clocks. We could have the specific implementation deal with the 
locking internally.

So essentially, the prepare_lock is just for the prepare_cnt and the 
call to the corresponding ops.

> Ideally, we should work out what the semantics are with regards to changing a
> clock's rate when it has multiple users and/or is enabled or prepared, but
> that's a separate issue, and we should *definitely* implement that as a
> separate change.

Agreed about having the semantics defined for setting the rate when 
there are multiple users. As for "is already enabled/prepared", I think 
clear that it needs to be supported/allowed. MSM drivers definitely do 
it all the time.

> I'd prefer to enforce the 'sleepability' with might_sleep instead.

Yeah, I realized this option after sending out my previous email. Please 
do add a might_sleep(). It will actually point out errors (per the new 
clarification) in some serial drivers.

>> You should probably rename the lock to something else since it's not
>> limited to prepare/unprepare. How about resource_lock?
>
> It's not, but that's the only thing it's protecting in the common code. I'm
> open for better names, but resource_lock is too generic.

We can get back to this later after we settle on the stuff below.

>>> +int clk_set_parent(struct clk *clk, struct clk *parent)
>>> +{
>>> +	if (clk->ops->set_parent)
>>> +		return clk->ops->set_parent(clk, parent);
>>
>> I'm not sure on this one. If the prepare ops for a clock also calls the
>> prepare ops on the parent, shouldn't we prevent changing the parent
>> while the prepare/unprepare is going on?
>
> Again, this is related to set_rate during enable/disable or prepare/unprepare;
> we don't have defined semantics for this at present.

After thinking about this the past couple of days, this looks like a 
location where the locking is more necessary than inside set rate. I 
always saw the parent clock as the clock that generates the clock signal 
from which this clock derives (divide, etc) it's clock signal from.

Assuming Russell and/or the community agrees on the semantics of 
"parent", without the generic implementation grabbing the prepare_lock 
while setting the parent, there is no way for the specific clock driver 
implementations to cleanly ensure correctness. The only option for them 
would be to peek into the generic clock struct and grab the prepare lock 
-- to me that would be an ugly hack and/or layering violation that would 
cause problems later on.

Russell/All,

What's the meaning of a parent clock? Do you agree with my definition -- 
"the parent clock is the clock that generates the clock signal from 
which the child clock derives (divide, etc) it's clock signal from."? Or 
is it open to interpretation by each implementation?

>>> +
>>> +/* static initialiser for clocks */
>>> +#define INIT_CLK(name, o) {						\
>>> +	.ops		=&o,						\
>>> +	.enable_count	= 0,						\
>>> +	.prepare_count	= 0,						\
>>
>> Do we need these inits? Doesn't check patch complain about initing
>> static/global to 0? If it's generally frowned upon, why the exception
>> here. I realize that checkpatch won't catch this, but still...
>
> This took some reading through c99, but yes, it looks like we can drop these
> zero initialisations.
>
> However, the coding style convention for the implicit zeroing of static
> variables is to allow these variables to be put into the .bss section,
> reducing object size. In this case, the clock will never be able to go into
> .bss (it has non-zero elements too), and so this will have no change on object
> size. I prefer to be explicit here, and show that the counts are initialised
> to zero.

I don't think the coding style convention was to make sure the variables 
end up in the BSS. I would be surprised if GCC wasn't intelligent enough 
to notice that we are initing a variable with zero and hence it can be 
safely put in the BSS. It think the coding style convention was chosen 
just to ensure "don't be redundant and add 'noisy' code".

> I'm happy to go either way. I have a preference for the explicit
> initialisation, but that may not be general style.

I don't have a strong opinion, but I thought I should point out the 
deviation from the usual coding style.

>>
>>> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
>>> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
>>
>> After a long day, I'm not able to wrap my head around this. Probably a
>> stupid question, but will this name.xxx thing prevent using this
>> INIT_CLK macro to initialize an array of clocks? More specifically,
>> prevent the sub class macro (like INIT_CLK_FIXED) from being used to
>> initialize an array of clocks?
>
> That's correct. For an array of clocks, you'll have to use a different
> initialiser. We can add helpers for that that when (and if) the need arises.

Would it even be possible to get this to work for an array? You don't 
have to change this in the patch, but I'm curious to know how to get 
this to work for an array without doing a run time init of the lock.

>>> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
>>> + * implementations to split any work between atomic (enable) and
>>> sleepable + * (prepare) contexts.  If a clock requires blocking code to
>>> be turned on, this
>>
>> Aren't all locks blocking? Shouldn't it be, "If turning on a clock
>> requires code that might sleep, it should be done in clk_prepare"?
>> Replace all "blocking" with "sleepable" or "sleeping" in the comments?
>
> I think "blocking" is generally accepted as is intended in this case, but it's
> probably better to be explicit here.

I obviously think what I suggested is clearer, but no strong opinion here.

Cheers,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-15  5:33           ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-15  5:33 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi, linux-sh,
	Ben Herrenschmidt, Sascha Hauer, Paul Mundt, linux-kernel,
	Russell King, Dima Zavin, Ben Dooks, Uwe Kleine-König,
	Vincent Guittot


Russell, A question for you further down this email. Please take a look.

On 02/14/2011 06:41 PM, Jeremy Kerr wrote:
> Hi Saravana,
>
>> Shouldn't you be grabbing the prepare_lock here?
>
> This depends on semantics that (as far as I can tell) aren't defined yet.

Sure, one could argue that in some archs for a certain set of clocks the 
slow stuff in prepare/unprepare won't need to be done during set rate -- 
say, a simple clock that always runs off the same PLL but just has a 
integer divider to change the rate.

In those cases, not grabbing the prepare_lock would make the code less 
"locky".

> We
> may even want to disallow set_rate (and set_parent) when prepare_count is non-
> zero.

This is definitely not right. Changing the rate of a clock when it's 
already enabled/prepared is a very reasonable thing to do. It's only 
doing a set rate at the "same time" as a prepare/unprepare that's wrong 
for some clocks. We could have the specific implementation deal with the 
locking internally.

So essentially, the prepare_lock is just for the prepare_cnt and the 
call to the corresponding ops.

> Ideally, we should work out what the semantics are with regards to changing a
> clock's rate when it has multiple users and/or is enabled or prepared, but
> that's a separate issue, and we should *definitely* implement that as a
> separate change.

Agreed about having the semantics defined for setting the rate when 
there are multiple users. As for "is already enabled/prepared", I think 
clear that it needs to be supported/allowed. MSM drivers definitely do 
it all the time.

> I'd prefer to enforce the 'sleepability' with might_sleep instead.

Yeah, I realized this option after sending out my previous email. Please 
do add a might_sleep(). It will actually point out errors (per the new 
clarification) in some serial drivers.

>> You should probably rename the lock to something else since it's not
>> limited to prepare/unprepare. How about resource_lock?
>
> It's not, but that's the only thing it's protecting in the common code. I'm
> open for better names, but resource_lock is too generic.

We can get back to this later after we settle on the stuff below.

>>> +int clk_set_parent(struct clk *clk, struct clk *parent)
>>> +{
>>> +	if (clk->ops->set_parent)
>>> +		return clk->ops->set_parent(clk, parent);
>>
>> I'm not sure on this one. If the prepare ops for a clock also calls the
>> prepare ops on the parent, shouldn't we prevent changing the parent
>> while the prepare/unprepare is going on?
>
> Again, this is related to set_rate during enable/disable or prepare/unprepare;
> we don't have defined semantics for this at present.

After thinking about this the past couple of days, this looks like a 
location where the locking is more necessary than inside set rate. I 
always saw the parent clock as the clock that generates the clock signal 
from which this clock derives (divide, etc) it's clock signal from.

Assuming Russell and/or the community agrees on the semantics of 
"parent", without the generic implementation grabbing the prepare_lock 
while setting the parent, there is no way for the specific clock driver 
implementations to cleanly ensure correctness. The only option for them 
would be to peek into the generic clock struct and grab the prepare lock 
-- to me that would be an ugly hack and/or layering violation that would 
cause problems later on.

Russell/All,

What's the meaning of a parent clock? Do you agree with my definition -- 
"the parent clock is the clock that generates the clock signal from 
which the child clock derives (divide, etc) it's clock signal from."? Or 
is it open to interpretation by each implementation?

>>> +
>>> +/* static initialiser for clocks */
>>> +#define INIT_CLK(name, o) {						\
>>> +	.ops		=&o,						\
>>> +	.enable_count	= 0,						\
>>> +	.prepare_count	= 0,						\
>>
>> Do we need these inits? Doesn't check patch complain about initing
>> static/global to 0? If it's generally frowned upon, why the exception
>> here. I realize that checkpatch won't catch this, but still...
>
> This took some reading through c99, but yes, it looks like we can drop these
> zero initialisations.
>
> However, the coding style convention for the implicit zeroing of static
> variables is to allow these variables to be put into the .bss section,
> reducing object size. In this case, the clock will never be able to go into
> .bss (it has non-zero elements too), and so this will have no change on object
> size. I prefer to be explicit here, and show that the counts are initialised
> to zero.

I don't think the coding style convention was to make sure the variables 
end up in the BSS. I would be surprised if GCC wasn't intelligent enough 
to notice that we are initing a variable with zero and hence it can be 
safely put in the BSS. It think the coding style convention was chosen 
just to ensure "don't be redundant and add 'noisy' code".

> I'm happy to go either way. I have a preference for the explicit
> initialisation, but that may not be general style.

I don't have a strong opinion, but I thought I should point out the 
deviation from the usual coding style.

>>
>>> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
>>> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
>>
>> After a long day, I'm not able to wrap my head around this. Probably a
>> stupid question, but will this name.xxx thing prevent using this
>> INIT_CLK macro to initialize an array of clocks? More specifically,
>> prevent the sub class macro (like INIT_CLK_FIXED) from being used to
>> initialize an array of clocks?
>
> That's correct. For an array of clocks, you'll have to use a different
> initialiser. We can add helpers for that that when (and if) the need arises.

Would it even be possible to get this to work for an array? You don't 
have to change this in the patch, but I'm curious to know how to get 
this to work for an array without doing a run time init of the lock.

>>> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
>>> + * implementations to split any work between atomic (enable) and
>>> sleepable + * (prepare) contexts.  If a clock requires blocking code to
>>> be turned on, this
>>
>> Aren't all locks blocking? Shouldn't it be, "If turning on a clock
>> requires code that might sleep, it should be done in clk_prepare"?
>> Replace all "blocking" with "sleepable" or "sleeping" in the comments?
>
> I think "blocking" is generally accepted as is intended in this case, but it's
> probably better to be explicit here.

I obviously think what I suggested is clearer, but no strong opinion here.

Cheers,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-15  5:33           ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-15  5:33 UTC (permalink / raw)
  To: linux-arm-kernel


Russell, A question for you further down this email. Please take a look.

On 02/14/2011 06:41 PM, Jeremy Kerr wrote:
> Hi Saravana,
>
>> Shouldn't you be grabbing the prepare_lock here?
>
> This depends on semantics that (as far as I can tell) aren't defined yet.

Sure, one could argue that in some archs for a certain set of clocks the 
slow stuff in prepare/unprepare won't need to be done during set rate -- 
say, a simple clock that always runs off the same PLL but just has a 
integer divider to change the rate.

In those cases, not grabbing the prepare_lock would make the code less 
"locky".

> We
> may even want to disallow set_rate (and set_parent) when prepare_count is non-
> zero.

This is definitely not right. Changing the rate of a clock when it's 
already enabled/prepared is a very reasonable thing to do. It's only 
doing a set rate at the "same time" as a prepare/unprepare that's wrong 
for some clocks. We could have the specific implementation deal with the 
locking internally.

So essentially, the prepare_lock is just for the prepare_cnt and the 
call to the corresponding ops.

> Ideally, we should work out what the semantics are with regards to changing a
> clock's rate when it has multiple users and/or is enabled or prepared, but
> that's a separate issue, and we should *definitely* implement that as a
> separate change.

Agreed about having the semantics defined for setting the rate when 
there are multiple users. As for "is already enabled/prepared", I think 
clear that it needs to be supported/allowed. MSM drivers definitely do 
it all the time.

> I'd prefer to enforce the 'sleepability' with might_sleep instead.

Yeah, I realized this option after sending out my previous email. Please 
do add a might_sleep(). It will actually point out errors (per the new 
clarification) in some serial drivers.

>> You should probably rename the lock to something else since it's not
>> limited to prepare/unprepare. How about resource_lock?
>
> It's not, but that's the only thing it's protecting in the common code. I'm
> open for better names, but resource_lock is too generic.

We can get back to this later after we settle on the stuff below.

>>> +int clk_set_parent(struct clk *clk, struct clk *parent)
>>> +{
>>> +	if (clk->ops->set_parent)
>>> +		return clk->ops->set_parent(clk, parent);
>>
>> I'm not sure on this one. If the prepare ops for a clock also calls the
>> prepare ops on the parent, shouldn't we prevent changing the parent
>> while the prepare/unprepare is going on?
>
> Again, this is related to set_rate during enable/disable or prepare/unprepare;
> we don't have defined semantics for this at present.

After thinking about this the past couple of days, this looks like a 
location where the locking is more necessary than inside set rate. I 
always saw the parent clock as the clock that generates the clock signal 
from which this clock derives (divide, etc) it's clock signal from.

Assuming Russell and/or the community agrees on the semantics of 
"parent", without the generic implementation grabbing the prepare_lock 
while setting the parent, there is no way for the specific clock driver 
implementations to cleanly ensure correctness. The only option for them 
would be to peek into the generic clock struct and grab the prepare lock 
-- to me that would be an ugly hack and/or layering violation that would 
cause problems later on.

Russell/All,

What's the meaning of a parent clock? Do you agree with my definition -- 
"the parent clock is the clock that generates the clock signal from 
which the child clock derives (divide, etc) it's clock signal from."? Or 
is it open to interpretation by each implementation?

>>> +
>>> +/* static initialiser for clocks */
>>> +#define INIT_CLK(name, o) {						\
>>> +	.ops		=&o,						\
>>> +	.enable_count	= 0,						\
>>> +	.prepare_count	= 0,						\
>>
>> Do we need these inits? Doesn't check patch complain about initing
>> static/global to 0? If it's generally frowned upon, why the exception
>> here. I realize that checkpatch won't catch this, but still...
>
> This took some reading through c99, but yes, it looks like we can drop these
> zero initialisations.
>
> However, the coding style convention for the implicit zeroing of static
> variables is to allow these variables to be put into the .bss section,
> reducing object size. In this case, the clock will never be able to go into
> .bss (it has non-zero elements too), and so this will have no change on object
> size. I prefer to be explicit here, and show that the counts are initialised
> to zero.

I don't think the coding style convention was to make sure the variables 
end up in the BSS. I would be surprised if GCC wasn't intelligent enough 
to notice that we are initing a variable with zero and hence it can be 
safely put in the BSS. It think the coding style convention was chosen 
just to ensure "don't be redundant and add 'noisy' code".

> I'm happy to go either way. I have a preference for the explicit
> initialisation, but that may not be general style.

I don't have a strong opinion, but I thought I should point out the 
deviation from the usual coding style.

>>
>>> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
>>> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
>>
>> After a long day, I'm not able to wrap my head around this. Probably a
>> stupid question, but will this name.xxx thing prevent using this
>> INIT_CLK macro to initialize an array of clocks? More specifically,
>> prevent the sub class macro (like INIT_CLK_FIXED) from being used to
>> initialize an array of clocks?
>
> That's correct. For an array of clocks, you'll have to use a different
> initialiser. We can add helpers for that that when (and if) the need arises.

Would it even be possible to get this to work for an array? You don't 
have to change this in the patch, but I'm curious to know how to get 
this to work for an array without doing a run time init of the lock.

>>> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
>>> + * implementations to split any work between atomic (enable) and
>>> sleepable + * (prepare) contexts.  If a clock requires blocking code to
>>> be turned on, this
>>
>> Aren't all locks blocking? Shouldn't it be, "If turning on a clock
>> requires code that might sleep, it should be done in clk_prepare"?
>> Replace all "blocking" with "sleepable" or "sleeping" in the comments?
>
> I think "blocking" is generally accepted as is intended in this case, but it's
> probably better to be explicit here.

I obviously think what I suggested is clearer, but no strong opinion here.

Cheers,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
  2011-02-15  4:51           ` Saravana Kannan
  (?)
@ 2011-02-15  6:18             ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  6:18 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Saravana,

> >> A fixed clock may still have other operations such as enable/disable.
> > 
> > Then it's not a fixed clock; I'd prefer this to be a separate type, as
> > it's now hardware dependent.
> 
> I'm confused. If a clock's rate can't be changed and it can't be enabled
> or disabled, then what's the point of representing that clock
> signal/line as a clock in the driver.

Because the drivers using this clock don't know that it's a fixed clock.

For example, a uart needs to know the rate of its clock source, so that it can 
set its internal divisors to get a valid baud rate. The uart driver will query  
the input rate using clk_get_rate(). The driver still needs to call 
clk_enable/clk_prepare/etc, because on some systems it may have a switchable 
clock.

Cheers,


Jeremy


^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
@ 2011-02-15  6:18             ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  6:18 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, linux-kernel, Ryan Mallon, Dima Zavin, Ben Dooks,
	Uwe Kleine-König, Russell King

Hi Saravana,

> >> A fixed clock may still have other operations such as enable/disable.
> > 
> > Then it's not a fixed clock; I'd prefer this to be a separate type, as
> > it's now hardware dependent.
> 
> I'm confused. If a clock's rate can't be changed and it can't be enabled
> or disabled, then what's the point of representing that clock
> signal/line as a clock in the driver.

Because the drivers using this clock don't know that it's a fixed clock.

For example, a uart needs to know the rate of its clock source, so that it can 
set its internal divisors to get a valid baud rate. The uart driver will query  
the input rate using clk_get_rate(). The driver still needs to call 
clk_enable/clk_prepare/etc, because on some systems it may have a switchable 
clock.

Cheers,


Jeremy


^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
@ 2011-02-15  6:18             ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  6:18 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Saravana,

> >> A fixed clock may still have other operations such as enable/disable.
> > 
> > Then it's not a fixed clock; I'd prefer this to be a separate type, as
> > it's now hardware dependent.
> 
> I'm confused. If a clock's rate can't be changed and it can't be enabled
> or disabled, then what's the point of representing that clock
> signal/line as a clock in the driver.

Because the drivers using this clock don't know that it's a fixed clock.

For example, a uart needs to know the rate of its clock source, so that it can 
set its internal divisors to get a valid baud rate. The uart driver will query  
the input rate using clk_get_rate(). The driver still needs to call 
clk_enable/clk_prepare/etc, because on some systems it may have a switchable 
clock.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
  2011-02-15  6:18             ` Jeremy Kerr
  (?)
@ 2011-02-15  6:31               ` Saravana Kannan
  -1 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-15  6:31 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/14/2011 10:18 PM, Jeremy Kerr wrote:

> Because the drivers using this clock don't know that it's a fixed clock.
>
> For example, a uart needs to know the rate of its clock source, so that it can
> set its internal divisors to get a valid baud rate. The uart driver will query
> the input rate using clk_get_rate(). The driver still needs to call
> clk_enable/clk_prepare/etc, because on some systems it may have a switchable
> clock.

Thanks. Makes sense.

-Saravana
-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
@ 2011-02-15  6:31               ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-15  6:31 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, linux-kernel,
	Ryan Mallon, Paul Mundt, Ben Dooks, Uwe Kleine-König,
	Russell King, linux-arm-kernel

On 02/14/2011 10:18 PM, Jeremy Kerr wrote:

> Because the drivers using this clock don't know that it's a fixed clock.
>
> For example, a uart needs to know the rate of its clock source, so that it can
> set its internal divisors to get a valid baud rate. The uart driver will query
> the input rate using clk_get_rate(). The driver still needs to call
> clk_enable/clk_prepare/etc, because on some systems it may have a switchable
> clock.

Thanks. Makes sense.

-Saravana
-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
@ 2011-02-15  6:31               ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-15  6:31 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/14/2011 10:18 PM, Jeremy Kerr wrote:

> Because the drivers using this clock don't know that it's a fixed clock.
>
> For example, a uart needs to know the rate of its clock source, so that it can
> set its internal divisors to get a valid baud rate. The uart driver will query
> the input rate using clk_get_rate(). The driver still needs to call
> clk_enable/clk_prepare/etc, because on some systems it may have a switchable
> clock.

Thanks. Makes sense.

-Saravana
-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-15  5:33           ` Saravana Kannan
  (?)
@ 2011-02-15  7:26             ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  7:26 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Saravana,

> Sure, one could argue that in some archs for a certain set of clocks the
> slow stuff in prepare/unprepare won't need to be done during set rate --
> say, a simple clock that always runs off the same PLL but just has a
> integer divider to change the rate.
> 
> In those cases, not grabbing the prepare_lock would make the code less
> "locky".
> 
> > We
> > may even want to disallow set_rate (and set_parent) when prepare_count is
> > non- zero.
> 
> This is definitely not right.

Why is that? Consider two devices using one clock; one does some 
initialisation based on the return value of clk_get_rate(), the other calls 
clk_set_rate() some time later. Now the first device is incorrectly 
initialised.

Regardless, this is definitely something to flag for a later discussion. I'm 
happy to return to that, but we should focus on one issue at a time here.

> Changing the rate of a clock when it's
> already enabled/prepared is a very reasonable thing to do. It's only
> doing a set rate at the "same time" as a prepare/unprepare that's wrong
> for some clocks. We could have the specific implementation deal with the
> locking internally.

Yes, hence leaving the locking here to the clock implementation.

> > I'd prefer to enforce the 'sleepability' with might_sleep instead.
> 
> Yeah, I realized this option after sending out my previous email. Please
> do add a might_sleep(). It will actually point out errors (per the new
> clarification) in some serial drivers.

Yep, will do.

> >>> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> >>> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
> >> 
> >> After a long day, I'm not able to wrap my head around this. Probably a
> >> stupid question, but will this name.xxx thing prevent using this
> >> INIT_CLK macro to initialize an array of clocks? More specifically,
> >> prevent the sub class macro (like INIT_CLK_FIXED) from being used to
> >> initialize an array of clocks?
> > 
> > That's correct. For an array of clocks, you'll have to use a different
> > initialiser. We can add helpers for that that when (and if) the need
> > arises.
> 
> Would it even be possible to get this to work for an array? You don't
> have to change this in the patch, but I'm curious to know how to get
> this to work for an array without doing a run time init of the lock.

I'd assume that you'd have to do this at run time, as with any other array of 
structs that contain a mutex or spinlock.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-15  7:26             ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  7:26 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi, linux-sh,
	Ben Herrenschmidt, Sascha Hauer, Paul Mundt, linux-kernel,
	Russell King, Dima Zavin, Ben Dooks, Uwe Kleine-König,
	Vincent Guittot

Hi Saravana,

> Sure, one could argue that in some archs for a certain set of clocks the
> slow stuff in prepare/unprepare won't need to be done during set rate --
> say, a simple clock that always runs off the same PLL but just has a
> integer divider to change the rate.
> 
> In those cases, not grabbing the prepare_lock would make the code less
> "locky".
> 
> > We
> > may even want to disallow set_rate (and set_parent) when prepare_count is
> > non- zero.
> 
> This is definitely not right.

Why is that? Consider two devices using one clock; one does some 
initialisation based on the return value of clk_get_rate(), the other calls 
clk_set_rate() some time later. Now the first device is incorrectly 
initialised.

Regardless, this is definitely something to flag for a later discussion. I'm 
happy to return to that, but we should focus on one issue at a time here.

> Changing the rate of a clock when it's
> already enabled/prepared is a very reasonable thing to do. It's only
> doing a set rate at the "same time" as a prepare/unprepare that's wrong
> for some clocks. We could have the specific implementation deal with the
> locking internally.

Yes, hence leaving the locking here to the clock implementation.

> > I'd prefer to enforce the 'sleepability' with might_sleep instead.
> 
> Yeah, I realized this option after sending out my previous email. Please
> do add a might_sleep(). It will actually point out errors (per the new
> clarification) in some serial drivers.

Yep, will do.

> >>> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> >>> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
> >> 
> >> After a long day, I'm not able to wrap my head around this. Probably a
> >> stupid question, but will this name.xxx thing prevent using this
> >> INIT_CLK macro to initialize an array of clocks? More specifically,
> >> prevent the sub class macro (like INIT_CLK_FIXED) from being used to
> >> initialize an array of clocks?
> > 
> > That's correct. For an array of clocks, you'll have to use a different
> > initialiser. We can add helpers for that that when (and if) the need
> > arises.
> 
> Would it even be possible to get this to work for an array? You don't
> have to change this in the patch, but I'm curious to know how to get
> this to work for an array without doing a run time init of the lock.

I'd assume that you'd have to do this at run time, as with any other array of 
structs that contain a mutex or spinlock.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-15  7:26             ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  7:26 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Saravana,

> Sure, one could argue that in some archs for a certain set of clocks the
> slow stuff in prepare/unprepare won't need to be done during set rate --
> say, a simple clock that always runs off the same PLL but just has a
> integer divider to change the rate.
> 
> In those cases, not grabbing the prepare_lock would make the code less
> "locky".
> 
> > We
> > may even want to disallow set_rate (and set_parent) when prepare_count is
> > non- zero.
> 
> This is definitely not right.

Why is that? Consider two devices using one clock; one does some 
initialisation based on the return value of clk_get_rate(), the other calls 
clk_set_rate() some time later. Now the first device is incorrectly 
initialised.

Regardless, this is definitely something to flag for a later discussion. I'm 
happy to return to that, but we should focus on one issue at a time here.

> Changing the rate of a clock when it's
> already enabled/prepared is a very reasonable thing to do. It's only
> doing a set rate at the "same time" as a prepare/unprepare that's wrong
> for some clocks. We could have the specific implementation deal with the
> locking internally.

Yes, hence leaving the locking here to the clock implementation.

> > I'd prefer to enforce the 'sleepability' with might_sleep instead.
> 
> Yeah, I realized this option after sending out my previous email. Please
> do add a might_sleep(). It will actually point out errors (per the new
> clarification) in some serial drivers.

Yep, will do.

> >>> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> >>> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
> >> 
> >> After a long day, I'm not able to wrap my head around this. Probably a
> >> stupid question, but will this name.xxx thing prevent using this
> >> INIT_CLK macro to initialize an array of clocks? More specifically,
> >> prevent the sub class macro (like INIT_CLK_FIXED) from being used to
> >> initialize an array of clocks?
> > 
> > That's correct. For an array of clocks, you'll have to use a different
> > initialiser. We can add helpers for that that when (and if) the need
> > arises.
> 
> Would it even be possible to get this to work for an array? You don't
> have to change this in the patch, but I'm curious to know how to get
> this to work for an array without doing a run time init of the lock.

I'd assume that you'd have to do this at run time, as with any other array of 
structs that contain a mutex or spinlock.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-15  7:26             ` Jeremy Kerr
  (?)
@ 2011-02-15  8:33               ` Saravana Kannan
  -1 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-15  8:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jeremy,

Sorry, if the formatting is weird. Using webmail client

On Mon, February 14, 2011 11:26 pm, Jeremy Kerr wrote:
>> > We
>> > may even want to disallow set_rate (and set_parent) when prepare_count
>> is
>> > non- zero.
>>
>> This is definitely not right.
>
> Why is that? Consider two devices using one clock; one does some
> initialisation based on the return value of clk_get_rate(), the other
> calls
> clk_set_rate() some time later. Now the first device is incorrectly
> initialised.

The case you describe is certainly something I consider as incorrect and
agree with you in that we should try to prevent it. But

(prepare_count != 0) != (two devices using one clock).

For one, prepare_count = 1 would be a normal case when a clock is enabled
and the MSM drivers certainly want to be able to set the rate when the
clock is enabled.

But (prepare_count > 1 || enable_count > 1) doesn't mean more than one
device/device driver using the clock either. A simple example would be a
driver wrapping all it's register accesses with a clk_enable/clk_disable
and not having to worry about if a clock is enabled during register access
when it has multiple execution paths (threads, interrupt handler, timers,
etc) that access registers. The driver would just do the enable/disable
around register accesses and let the clock code's ref counting dealing
with making sure a clock is never turned off when it's needed. In these
case both the prepare_count (less likely, but likely) and enable_count can
greater than 1.

Long story short, I support your desire to prevent one driver from
changing the rate from underneath another driver, but the condition you
chose to figure that out is not accurate.

> Regardless, this is definitely something to flag for a later discussion.
> I'm
> happy to return to that, but we should focus on one issue at a time here.

Sure, this discussion of set rate with count is non-zero can be reserved
for later. But I think the discussion of grabbing the lock during
set_parent should be discussed in the context of this patch.

Waiting to see how others feel about this.

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.



^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-15  8:33               ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-15  8:33 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: Saravana Kannan, Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi,
	Russell King, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	linux-kernel, Paul Mundt, Ben Dooks, Uwe Kleine-König,
	Vincent Guittot, linux-arm-kernel

Hi Jeremy,

Sorry, if the formatting is weird. Using webmail client

On Mon, February 14, 2011 11:26 pm, Jeremy Kerr wrote:
>> > We
>> > may even want to disallow set_rate (and set_parent) when prepare_count
>> is
>> > non- zero.
>>
>> This is definitely not right.
>
> Why is that? Consider two devices using one clock; one does some
> initialisation based on the return value of clk_get_rate(), the other
> calls
> clk_set_rate() some time later. Now the first device is incorrectly
> initialised.

The case you describe is certainly something I consider as incorrect and
agree with you in that we should try to prevent it. But

(prepare_count != 0) != (two devices using one clock).

For one, prepare_count == 1 would be a normal case when a clock is enabled
and the MSM drivers certainly want to be able to set the rate when the
clock is enabled.

But (prepare_count > 1 || enable_count > 1) doesn't mean more than one
device/device driver using the clock either. A simple example would be a
driver wrapping all it's register accesses with a clk_enable/clk_disable
and not having to worry about if a clock is enabled during register access
when it has multiple execution paths (threads, interrupt handler, timers,
etc) that access registers. The driver would just do the enable/disable
around register accesses and let the clock code's ref counting dealing
with making sure a clock is never turned off when it's needed. In these
case both the prepare_count (less likely, but likely) and enable_count can
greater than 1.

Long story short, I support your desire to prevent one driver from
changing the rate from underneath another driver, but the condition you
chose to figure that out is not accurate.

> Regardless, this is definitely something to flag for a later discussion.
> I'm
> happy to return to that, but we should focus on one issue at a time here.

Sure, this discussion of set rate with count is non-zero can be reserved
for later. But I think the discussion of grabbing the lock during
set_parent should be discussed in the context of this patch.

Waiting to see how others feel about this.

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.



^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-15  8:33               ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-15  8:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jeremy,

Sorry, if the formatting is weird. Using webmail client

On Mon, February 14, 2011 11:26 pm, Jeremy Kerr wrote:
>> > We
>> > may even want to disallow set_rate (and set_parent) when prepare_count
>> is
>> > non- zero.
>>
>> This is definitely not right.
>
> Why is that? Consider two devices using one clock; one does some
> initialisation based on the return value of clk_get_rate(), the other
> calls
> clk_set_rate() some time later. Now the first device is incorrectly
> initialised.

The case you describe is certainly something I consider as incorrect and
agree with you in that we should try to prevent it. But

(prepare_count != 0) != (two devices using one clock).

For one, prepare_count == 1 would be a normal case when a clock is enabled
and the MSM drivers certainly want to be able to set the rate when the
clock is enabled.

But (prepare_count > 1 || enable_count > 1) doesn't mean more than one
device/device driver using the clock either. A simple example would be a
driver wrapping all it's register accesses with a clk_enable/clk_disable
and not having to worry about if a clock is enabled during register access
when it has multiple execution paths (threads, interrupt handler, timers,
etc) that access registers. The driver would just do the enable/disable
around register accesses and let the clock code's ref counting dealing
with making sure a clock is never turned off when it's needed. In these
case both the prepare_count (less likely, but likely) and enable_count can
greater than 1.

Long story short, I support your desire to prevent one driver from
changing the rate from underneath another driver, but the condition you
chose to figure that out is not accurate.

> Regardless, this is definitely something to flag for a later discussion.
> I'm
> happy to return to that, but we should focus on one issue at a time here.

Sure, this discussion of set rate with count is non-zero can be reserved
for later. But I think the discussion of grabbing the lock during
set_parent should be discussed in the context of this patch.

Waiting to see how others feel about this.

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-15  7:26             ` Jeremy Kerr
  (?)
@ 2011-02-15  8:37               ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-15  8:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 15, 2011 at 03:26:53PM +0800, Jeremy Kerr wrote:
> Hi Saravana,
> 
> > Sure, one could argue that in some archs for a certain set of clocks the
> > slow stuff in prepare/unprepare won't need to be done during set rate --
> > say, a simple clock that always runs off the same PLL but just has a
> > integer divider to change the rate.
> > 
> > In those cases, not grabbing the prepare_lock would make the code less
> > "locky".
> > 
> > > We
> > > may even want to disallow set_rate (and set_parent) when prepare_count is
> > > non- zero.
> > 
> > This is definitely not right.
> 
> Why is that? Consider two devices using one clock; one does some 
> initialisation based on the return value of clk_get_rate(), the other calls 
> clk_set_rate() some time later. Now the first device is incorrectly 
> initialised.

What about a clock sourced from a PLL which provides the dotclock for a
framebuffer device?  On every mode set, should the clk have to be disabled,
unprepared, rate set, re-prepared and re-enabled?


^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-15  8:37               ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-15  8:37 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: Saravana Kannan, linux-arm-kernel, Nicolas Pitre,
	Lorenzo Pieralisi, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, linux-kernel, Dima Zavin, Ben Dooks,
	Uwe Kleine-König, Vincent Guittot

On Tue, Feb 15, 2011 at 03:26:53PM +0800, Jeremy Kerr wrote:
> Hi Saravana,
> 
> > Sure, one could argue that in some archs for a certain set of clocks the
> > slow stuff in prepare/unprepare won't need to be done during set rate --
> > say, a simple clock that always runs off the same PLL but just has a
> > integer divider to change the rate.
> > 
> > In those cases, not grabbing the prepare_lock would make the code less
> > "locky".
> > 
> > > We
> > > may even want to disallow set_rate (and set_parent) when prepare_count is
> > > non- zero.
> > 
> > This is definitely not right.
> 
> Why is that? Consider two devices using one clock; one does some 
> initialisation based on the return value of clk_get_rate(), the other calls 
> clk_set_rate() some time later. Now the first device is incorrectly 
> initialised.

What about a clock sourced from a PLL which provides the dotclock for a
framebuffer device?  On every mode set, should the clk have to be disabled,
unprepared, rate set, re-prepared and re-enabled?


^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-15  8:37               ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-15  8:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 15, 2011 at 03:26:53PM +0800, Jeremy Kerr wrote:
> Hi Saravana,
> 
> > Sure, one could argue that in some archs for a certain set of clocks the
> > slow stuff in prepare/unprepare won't need to be done during set rate --
> > say, a simple clock that always runs off the same PLL but just has a
> > integer divider to change the rate.
> > 
> > In those cases, not grabbing the prepare_lock would make the code less
> > "locky".
> > 
> > > We
> > > may even want to disallow set_rate (and set_parent) when prepare_count is
> > > non- zero.
> > 
> > This is definitely not right.
> 
> Why is that? Consider two devices using one clock; one does some 
> initialisation based on the return value of clk_get_rate(), the other calls 
> clk_set_rate() some time later. Now the first device is incorrectly 
> initialised.

What about a clock sourced from a PLL which provides the dotclock for a
framebuffer device?  On every mode set, should the clk have to be disabled,
unprepared, rate set, re-prepared and re-enabled?

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-15  8:37               ` Russell King - ARM Linux
  (?)
@ 2011-02-15  9:33                 ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  9:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Russell,

> > Why is that? Consider two devices using one clock; one does some
> > initialisation based on the return value of clk_get_rate(), the other
> > calls clk_set_rate() some time later. Now the first device is
> > incorrectly initialised.
> 
> What about a clock sourced from a PLL which provides the dotclock for a
> framebuffer device?  On every mode set, should the clk have to be disabled,
> unprepared, rate set, re-prepared and re-enabled?

Sounds heavy-handed, but I honestly have no idea if that's reasonable or not.

Other options are:

 * Require that the driver has called clk_prepare, and that prepare_count
   is 1 during the set_rate call (indicating that this is the only user); or

 * Leave the set_rate and set_parent semantics as-is and assume that anything
   calling either knows what it's doing (and that it won't affect other
   devices)

Are you OK if we address this separately to the API unification though?

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-15  9:33                 ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  9:33 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Saravana Kannan, linux-arm-kernel, Nicolas Pitre,
	Lorenzo Pieralisi, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, linux-kernel, Dima Zavin, Ben Dooks,
	Uwe Kleine-König, Vincent Guittot

Hi Russell,

> > Why is that? Consider two devices using one clock; one does some
> > initialisation based on the return value of clk_get_rate(), the other
> > calls clk_set_rate() some time later. Now the first device is
> > incorrectly initialised.
> 
> What about a clock sourced from a PLL which provides the dotclock for a
> framebuffer device?  On every mode set, should the clk have to be disabled,
> unprepared, rate set, re-prepared and re-enabled?

Sounds heavy-handed, but I honestly have no idea if that's reasonable or not.

Other options are:

 * Require that the driver has called clk_prepare, and that prepare_count
   is 1 during the set_rate call (indicating that this is the only user); or

 * Leave the set_rate and set_parent semantics as-is and assume that anything
   calling either knows what it's doing (and that it won't affect other
   devices)

Are you OK if we address this separately to the API unification though?

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-15  9:33                 ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-15  9:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Russell,

> > Why is that? Consider two devices using one clock; one does some
> > initialisation based on the return value of clk_get_rate(), the other
> > calls clk_set_rate() some time later. Now the first device is
> > incorrectly initialised.
> 
> What about a clock sourced from a PLL which provides the dotclock for a
> framebuffer device?  On every mode set, should the clk have to be disabled,
> unprepared, rate set, re-prepared and re-enabled?

Sounds heavy-handed, but I honestly have no idea if that's reasonable or not.

Other options are:

 * Require that the driver has called clk_prepare, and that prepare_count
   is 1 during the set_rate call (indicating that this is the only user); or

 * Leave the set_rate and set_parent semantics as-is and assume that anything
   calling either knows what it's doing (and that it won't affect other
   devices)

Are you OK if we address this separately to the API unification though?

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-15  9:33                 ` Jeremy Kerr
  (?)
@ 2011-02-15 14:13                   ` Richard Zhao
  -1 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-15 14:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 15, 2011 at 05:33:29PM +0800, Jeremy Kerr wrote:
> Hi Russell,
> 
> > > Why is that? Consider two devices using one clock; one does some
> > > initialisation based on the return value of clk_get_rate(), the other
> > > calls clk_set_rate() some time later. Now the first device is
> > > incorrectly initialised.
> > 
> > What about a clock sourced from a PLL which provides the dotclock for a
> > framebuffer device?  On every mode set, should the clk have to be disabled,
> > unprepared, rate set, re-prepared and re-enabled?
> 
> Sounds heavy-handed, but I honestly have no idea if that's reasonable or not.
> 
> Other options are:
> 
>  * Require that the driver has called clk_prepare, and that prepare_count
>    is 1 during the set_rate call (indicating that this is the only user); or
> 
>  * Leave the set_rate and set_parent semantics as-is and assume that anything
>    calling either knows what it's doing (and that it won't affect other
>    devices)
I vote the second option. Two reasons:
1. Has any mach specific clock restricted clk_set_rate use? I don't hear any.
2. In my opinion, clk_set_rate is not called very often by drivers, especially
for the clock which has child clocks. Leaf clock are seldom shared. Even if it's
shared, we can let drivers handle it case by case .

Thanks
Richard
> 
> Are you OK if we address this separately to the API unification though?
> 
> Cheers,
> 
> 
> Jeremy
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-15 14:13                   ` Richard Zhao
  0 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-15 14:13 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: Russell King - ARM Linux, Nicolas Pitre, Dima Zavin,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Sascha Hauer, Paul Mundt, linux-kernel, Saravana Kannan,
	Ben Dooks, Uwe Kleine-König, linux-arm-kernel

On Tue, Feb 15, 2011 at 05:33:29PM +0800, Jeremy Kerr wrote:
> Hi Russell,
> 
> > > Why is that? Consider two devices using one clock; one does some
> > > initialisation based on the return value of clk_get_rate(), the other
> > > calls clk_set_rate() some time later. Now the first device is
> > > incorrectly initialised.
> > 
> > What about a clock sourced from a PLL which provides the dotclock for a
> > framebuffer device?  On every mode set, should the clk have to be disabled,
> > unprepared, rate set, re-prepared and re-enabled?
> 
> Sounds heavy-handed, but I honestly have no idea if that's reasonable or not.
> 
> Other options are:
> 
>  * Require that the driver has called clk_prepare, and that prepare_count
>    is 1 during the set_rate call (indicating that this is the only user); or
> 
>  * Leave the set_rate and set_parent semantics as-is and assume that anything
>    calling either knows what it's doing (and that it won't affect other
>    devices)
I vote the second option. Two reasons:
1. Has any mach specific clock restricted clk_set_rate use? I don't hear any.
2. In my opinion, clk_set_rate is not called very often by drivers, especially
for the clock which has child clocks. Leaf clock are seldom shared. Even if it's
shared, we can let drivers handle it case by case .

Thanks
Richard
> 
> Are you OK if we address this separately to the API unification though?
> 
> Cheers,
> 
> 
> Jeremy
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-15 14:13                   ` Richard Zhao
  0 siblings, 0 replies; 383+ messages in thread
From: Richard Zhao @ 2011-02-15 14:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 15, 2011 at 05:33:29PM +0800, Jeremy Kerr wrote:
> Hi Russell,
> 
> > > Why is that? Consider two devices using one clock; one does some
> > > initialisation based on the return value of clk_get_rate(), the other
> > > calls clk_set_rate() some time later. Now the first device is
> > > incorrectly initialised.
> > 
> > What about a clock sourced from a PLL which provides the dotclock for a
> > framebuffer device?  On every mode set, should the clk have to be disabled,
> > unprepared, rate set, re-prepared and re-enabled?
> 
> Sounds heavy-handed, but I honestly have no idea if that's reasonable or not.
> 
> Other options are:
> 
>  * Require that the driver has called clk_prepare, and that prepare_count
>    is 1 during the set_rate call (indicating that this is the only user); or
> 
>  * Leave the set_rate and set_parent semantics as-is and assume that anything
>    calling either knows what it's doing (and that it won't affect other
>    devices)
I vote the second option. Two reasons:
1. Has any mach specific clock restricted clk_set_rate use? I don't hear any.
2. In my opinion, clk_set_rate is not called very often by drivers, especially
for the clock which has child clocks. Leaf clock are seldom shared. Even if it's
shared, we can let drivers handle it case by case .

Thanks
Richard
> 
> Are you OK if we address this separately to the API unification though?
> 
> Cheers,
> 
> 
> Jeremy
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-15  5:33           ` Saravana Kannan
  (?)
@ 2011-02-16  4:53             ` Saravana Kannan
  -1 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-16  4:53 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/14/2011 09:33 PM, Saravana Kannan wrote:
> Russell, A question for you further down this email. Please take a look.

Russell, Ping... I will snip the rest of the discussion so that it's 
easy to spot the question.

>>>> +int clk_set_parent(struct clk *clk, struct clk *parent)
>>>> +{
>>>> + if (clk->ops->set_parent)
>>>> + return clk->ops->set_parent(clk, parent);
>>>
>>> I'm not sure on this one. If the prepare ops for a clock also calls the
>>> prepare ops on the parent, shouldn't we prevent changing the parent
>>> while the prepare/unprepare is going on?
>>
>> Again, this is related to set_rate during enable/disable or
>> prepare/unprepare;
>> we don't have defined semantics for this at present.
>
> After thinking about this the past couple of days, this looks like a
> location where the locking is more necessary than inside set rate. I
> always saw the parent clock as the clock that generates the clock signal
> from which this clock derives (divide, etc) it's clock signal from.
>
> Assuming Russell and/or the community agrees on the semantics of
> "parent", without the generic implementation grabbing the prepare_lock
> while setting the parent, there is no way for the specific clock driver
> implementations to cleanly ensure correctness. The only option for them
> would be to peek into the generic clock struct and grab the prepare lock
> -- to me that would be an ugly hack and/or layering violation that would
> cause problems later on.
>
> Russell/All,
>
> What's the meaning of a parent clock? Do you agree with my definition --
> "the parent clock is the clock that generates the clock signal from
> which the child clock derives (divide, etc) it's clock signal from."? Or
> is it open to interpretation by each implementation?

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-16  4:53             ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-16  4:53 UTC (permalink / raw)
  To: Jeremy Kerr, Russell King
  Cc: Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi, linux-sh,
	Ben Herrenschmidt, Sascha Hauer, linux-kernel, Paul Mundt,
	Ben Dooks, Uwe Kleine-König, Vincent Guittot,
	linux-arm-kernel

On 02/14/2011 09:33 PM, Saravana Kannan wrote:
> Russell, A question for you further down this email. Please take a look.

Russell, Ping... I will snip the rest of the discussion so that it's 
easy to spot the question.

>>>> +int clk_set_parent(struct clk *clk, struct clk *parent)
>>>> +{
>>>> + if (clk->ops->set_parent)
>>>> + return clk->ops->set_parent(clk, parent);
>>>
>>> I'm not sure on this one. If the prepare ops for a clock also calls the
>>> prepare ops on the parent, shouldn't we prevent changing the parent
>>> while the prepare/unprepare is going on?
>>
>> Again, this is related to set_rate during enable/disable or
>> prepare/unprepare;
>> we don't have defined semantics for this at present.
>
> After thinking about this the past couple of days, this looks like a
> location where the locking is more necessary than inside set rate. I
> always saw the parent clock as the clock that generates the clock signal
> from which this clock derives (divide, etc) it's clock signal from.
>
> Assuming Russell and/or the community agrees on the semantics of
> "parent", without the generic implementation grabbing the prepare_lock
> while setting the parent, there is no way for the specific clock driver
> implementations to cleanly ensure correctness. The only option for them
> would be to peek into the generic clock struct and grab the prepare lock
> -- to me that would be an ugly hack and/or layering violation that would
> cause problems later on.
>
> Russell/All,
>
> What's the meaning of a parent clock? Do you agree with my definition --
> "the parent clock is the clock that generates the clock signal from
> which the child clock derives (divide, etc) it's clock signal from."? Or
> is it open to interpretation by each implementation?

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-16  4:53             ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-16  4:53 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/14/2011 09:33 PM, Saravana Kannan wrote:
> Russell, A question for you further down this email. Please take a look.

Russell, Ping... I will snip the rest of the discussion so that it's 
easy to spot the question.

>>>> +int clk_set_parent(struct clk *clk, struct clk *parent)
>>>> +{
>>>> + if (clk->ops->set_parent)
>>>> + return clk->ops->set_parent(clk, parent);
>>>
>>> I'm not sure on this one. If the prepare ops for a clock also calls the
>>> prepare ops on the parent, shouldn't we prevent changing the parent
>>> while the prepare/unprepare is going on?
>>
>> Again, this is related to set_rate during enable/disable or
>> prepare/unprepare;
>> we don't have defined semantics for this at present.
>
> After thinking about this the past couple of days, this looks like a
> location where the locking is more necessary than inside set rate. I
> always saw the parent clock as the clock that generates the clock signal
> from which this clock derives (divide, etc) it's clock signal from.
>
> Assuming Russell and/or the community agrees on the semantics of
> "parent", without the generic implementation grabbing the prepare_lock
> while setting the parent, there is no way for the specific clock driver
> implementations to cleanly ensure correctness. The only option for them
> would be to peek into the generic clock struct and grab the prepare lock
> -- to me that would be an ugly hack and/or layering violation that would
> cause problems later on.
>
> Russell/All,
>
> What's the meaning of a parent clock? Do you agree with my definition --
> "the parent clock is the clock that generates the clock signal from
> which the child clock derives (divide, etc) it's clock signal from."? Or
> is it open to interpretation by each implementation?

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-15  9:33                 ` Jeremy Kerr
  (?)
@ 2011-02-20 13:07                   ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-20 13:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 15, 2011 at 05:33:29PM +0800, Jeremy Kerr wrote:
> Hi Russell,
> 
> > > Why is that? Consider two devices using one clock; one does some
> > > initialisation based on the return value of clk_get_rate(), the other
> > > calls clk_set_rate() some time later. Now the first device is
> > > incorrectly initialised.
> > 
> > What about a clock sourced from a PLL which provides the dotclock for a
> > framebuffer device?  On every mode set, should the clk have to be disabled,
> > unprepared, rate set, re-prepared and re-enabled?
> 
> Sounds heavy-handed, but I honestly have no idea if that's reasonable or not.
> 
> Other options are:
> 
>  * Require that the driver has called clk_prepare, and that prepare_count
>    is 1 during the set_rate call (indicating that this is the only user); or
> 
>  * Leave the set_rate and set_parent semantics as-is and assume that anything
>    calling either knows what it's doing (and that it won't affect other
>    devices)
> 
> Are you OK if we address this separately to the API unification though?

Absolutely.  I think there's enough issues already without adding new
changes on top.  The unification step should do just that - unify.  It
should not introduce new restrictions that are not absolutely necessary
for the unification step.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-20 13:07                   ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-20 13:07 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: Saravana Kannan, linux-arm-kernel, Nicolas Pitre,
	Lorenzo Pieralisi, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, linux-kernel, Dima Zavin, Ben Dooks,
	Uwe Kleine-König, Vincent Guittot

On Tue, Feb 15, 2011 at 05:33:29PM +0800, Jeremy Kerr wrote:
> Hi Russell,
> 
> > > Why is that? Consider two devices using one clock; one does some
> > > initialisation based on the return value of clk_get_rate(), the other
> > > calls clk_set_rate() some time later. Now the first device is
> > > incorrectly initialised.
> > 
> > What about a clock sourced from a PLL which provides the dotclock for a
> > framebuffer device?  On every mode set, should the clk have to be disabled,
> > unprepared, rate set, re-prepared and re-enabled?
> 
> Sounds heavy-handed, but I honestly have no idea if that's reasonable or not.
> 
> Other options are:
> 
>  * Require that the driver has called clk_prepare, and that prepare_count
>    is 1 during the set_rate call (indicating that this is the only user); or
> 
>  * Leave the set_rate and set_parent semantics as-is and assume that anything
>    calling either knows what it's doing (and that it won't affect other
>    devices)
> 
> Are you OK if we address this separately to the API unification though?

Absolutely.  I think there's enough issues already without adding new
changes on top.  The unification step should do just that - unify.  It
should not introduce new restrictions that are not absolutely necessary
for the unification step.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-20 13:07                   ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-20 13:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 15, 2011 at 05:33:29PM +0800, Jeremy Kerr wrote:
> Hi Russell,
> 
> > > Why is that? Consider two devices using one clock; one does some
> > > initialisation based on the return value of clk_get_rate(), the other
> > > calls clk_set_rate() some time later. Now the first device is
> > > incorrectly initialised.
> > 
> > What about a clock sourced from a PLL which provides the dotclock for a
> > framebuffer device?  On every mode set, should the clk have to be disabled,
> > unprepared, rate set, re-prepared and re-enabled?
> 
> Sounds heavy-handed, but I honestly have no idea if that's reasonable or not.
> 
> Other options are:
> 
>  * Require that the driver has called clk_prepare, and that prepare_count
>    is 1 during the set_rate call (indicating that this is the only user); or
> 
>  * Leave the set_rate and set_parent semantics as-is and assume that anything
>    calling either knows what it's doing (and that it won't affect other
>    devices)
> 
> Are you OK if we address this separately to the API unification though?

Absolutely.  I think there's enough issues already without adding new
changes on top.  The unification step should do just that - unify.  It
should not introduce new restrictions that are not absolutely necessary
for the unification step.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
  2011-02-15  5:33           ` Saravana Kannan
  (?)
@ 2011-02-20 13:13             ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-20 13:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 14, 2011 at 09:33:03PM -0800, Saravana Kannan wrote:
> Assuming Russell and/or the community agrees on the semantics of  
> "parent", without the generic implementation grabbing the prepare_lock  
> while setting the parent, there is no way for the specific clock driver  
> implementations to cleanly ensure correctness. The only option for them  
> would be to peek into the generic clock struct and grab the prepare lock  
> -- to me that would be an ugly hack and/or layering violation that would  
> cause problems later on.
>
> Russell/All,
>
> What's the meaning of a parent clock? Do you agree with my definition --  
> "the parent clock is the clock that generates the clock signal from  
> which the child clock derives (divide, etc) it's clock signal from."? Or  
> is it open to interpretation by each implementation?

Your definition seems sane - I'm not sure what use a parent clock which
had nothing to do with a child would be.

As for the locking issue, I've no idea on that at the moment.  I don't
think implementations should grab the prepare lock, I think that's
something the generic code should take care of for clk_set_rate(),
clk_set_parent() etc.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-20 13:13             ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-20 13:13 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: Jeremy Kerr, linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	linux-sh, Ben Herrenschmidt, Sascha Hauer, Paul Mundt,
	linux-kernel, Dima Zavin, Ben Dooks, Uwe Kleine-König,
	Vincent Guittot

On Mon, Feb 14, 2011 at 09:33:03PM -0800, Saravana Kannan wrote:
> Assuming Russell and/or the community agrees on the semantics of  
> "parent", without the generic implementation grabbing the prepare_lock  
> while setting the parent, there is no way for the specific clock driver  
> implementations to cleanly ensure correctness. The only option for them  
> would be to peek into the generic clock struct and grab the prepare lock  
> -- to me that would be an ugly hack and/or layering violation that would  
> cause problems later on.
>
> Russell/All,
>
> What's the meaning of a parent clock? Do you agree with my definition --  
> "the parent clock is the clock that generates the clock signal from  
> which the child clock derives (divide, etc) it's clock signal from."? Or  
> is it open to interpretation by each implementation?

Your definition seems sane - I'm not sure what use a parent clock which
had nothing to do with a child would be.

As for the locking issue, I've no idea on that at the moment.  I don't
think implementations should grab the prepare lock, I think that's
something the generic code should take care of for clk_set_rate(),
clk_set_parent() etc.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC,PATCH 1/3] Add a common struct clk
@ 2011-02-20 13:13             ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-02-20 13:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 14, 2011 at 09:33:03PM -0800, Saravana Kannan wrote:
> Assuming Russell and/or the community agrees on the semantics of  
> "parent", without the generic implementation grabbing the prepare_lock  
> while setting the parent, there is no way for the specific clock driver  
> implementations to cleanly ensure correctness. The only option for them  
> would be to peek into the generic clock struct and grab the prepare lock  
> -- to me that would be an ugly hack and/or layering violation that would  
> cause problems later on.
>
> Russell/All,
>
> What's the meaning of a parent clock? Do you agree with my definition --  
> "the parent clock is the clock that generates the clock signal from  
> which the child clock derives (divide, etc) it's clock signal from."? Or  
> is it open to interpretation by each implementation?

Your definition seems sane - I'm not sure what use a parent clock which
had nothing to do with a child would be.

As for the locking issue, I've no idea on that at the moment.  I don't
think implementations should grab the prepare lock, I think that's
something the generic code should take care of for clk_set_rate(),
clk_set_parent() etc.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v13
  2011-02-01  9:11 ` Jeremy Kerr
  (?)
@ 2011-02-21  2:50   ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-21  2:50 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

These patches are an attempt to allow platforms to share clock code. At
present, the definitions of 'struct clk' are local to platform code,
which makes allocating and initialising cross-platform clock sources
difficult, and makes it impossible to compile a single image containing
support for two ARM platforms with different struct clks.

The three patches are for the architecture-independent kernel code,
introducing the common clk infrastructure. The changelog for the first
patch includes details about the new clock definitions.

Many thanks to the following for their input:
 * Benjamin Herrenschmidt <benh@kernel.crashing.org>
 * Ben Dooks <ben-linux@fluff.org>
 * Baruch Siach <baruch@tkos.co.il>
 * Russell King <linux@arm.linux.org.uk>
 * Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 * Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
 * Vincent Guittot <vincent.guittot@linaro.org>
 * Sascha Hauer <s.hauer@pengutronix.de>
 * Ryan Mallon <ryan@bluewatersys.com>
 * Colin Cross <ccross@google.com>
 * Jassi Brar <jassisinghbrar@gmail.com>
 * Saravana Kannan <skannan@codeaurora.org>

Cheers,


Jeremy

--
v13:
 * Don't expose __clk_get and clk_put - prototypes in clkdev.c instead
 * Add might_sleep to clk_set_rate
 * Comment clarifications & fixups
 * Remove zero initialisers
 * Fold warnings into main clk.c change

v12:
 * Always refcount, even when enable/prepare ops are NULL
 * Unify prepare & enable count checking
 * Update comments for prepare/unprepare
 * Use spin_{lock,unlock}_irqsave
 * Change clk_put to __clk_put, and use the shared clk_put

v11:
 * add prepare/unprepare for non-atomic switching, document atomicity
 * move to drivers/clk/

v10:
 * comment fixups, from Uwe's review
 * added DEFINE_CLK_FIXED

v9:
 * comment improvements
 * kerneldoc fixups
 * add WARN_ON to clk_disable

v8:
 * add atomic clocks, and locking wrappers
 * expand comments on clk and clk_ops

v7:
 * change CLK_INIT to initialise clk->mutex statically

v6:
 * fixed up references to 'clk_operations' in the changelog

v5:
 * uninline main API, and share definitions with !USE_COMMON_STRUCT_CLK
 * add __clk_get
 * delay mutex init
 * kerneldoc for struct clk

v4:
 * use mutex for enable/disable locking
 * DEFINE_CLK -> INIT_CLK, and pass the clk name for mutex init
 * struct clk_operations -> struct clk_ops

v3:
 * do clock usage refcounting in common code
 * provide sample port

v2:
 * no longer ARM-specific
 * use clk_operations

---
Jeremy Kerr (2):
      Add a common struct clk
      clk: Generic support for fixed-rate clocks


^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 1/2] Add a common struct clk
  2011-02-21  2:50   ` Jeremy Kerr
  (?)
@ 2011-02-21  2:50     ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-21  2:50 UTC (permalink / raw)
  To: linux-arm-kernel

We currently have ~21 definitions of struct clk in the ARM architecture,
each defined on a per-platform basis. This makes it difficult to define
platform- (or architecture-) independent clock sources without making
assumptions about struct clk, and impossible to compile two
platforms with different struct clks into a single image.

This change is an effort to unify struct clk where possible, by defining
a common struct clk, containing a set of clock operations. Different
clock implementations can set their own operations, and have a standard
interface for generic code. The callback interface is exposed to the
kernel proper, while the clock implementations only need to be seen by
the platform internals.

This allows us to share clock code among platforms, and makes it
possible to dynamically create clock devices in platform-independent
code.

Platforms can enable the generic struct clock through
CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
consists of a common struct clk:

struct clk {
	const struct clk_ops	*ops;
	unsigned int		enable_count;
	unsigned int		prepare_count;
	spinlock_t		enable_lock;
	struct mutex		prepare_lock;
};

And a set of clock operations (defined per type of clock):

struct clk_ops {
	int             (*enable)(struct clk *);
	void            (*disable)(struct clk *);
	unsigned long   (*get_rate)(struct clk *);
	[...]
};

To define a hardware-specific clock, machine code can "subclass" the
struct clock into a new struct (adding any device-specific data), and
provide a set of operations:

struct clk_foo {
	struct clk	clk;
	void __iomem	*some_register;
};

struct clk_ops clk_foo_ops = {
	.get_rate = clk_foo_get_rate,
};

The common clock definitions are based on a development patch from Ben
Herrenschmidt <benh@kernel.crashing.org>.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/Kconfig  |    3 
 drivers/clk/Makefile |    1 
 drivers/clk/clk.c    |  132 ++++++++++++++++++++++++++++++++++
 drivers/clk/clkdev.c |    7 +
 include/linux/clk.h  |  164 ++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 298 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 4168c88..6e3ae54 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -2,3 +2,6 @@
 config CLKDEV_LOOKUP
 	bool
 	select HAVE_CLK
+
+config USE_COMMON_STRUCT_CLK
+	bool
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 07613fa..a1a06d3 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,2 +1,3 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
+obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
new file mode 100644
index 0000000..0bc9c6f
--- /dev/null
+++ b/drivers/clk/clk.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+
+int clk_prepare(struct clk *clk)
+{
+	int ret = 0;
+
+	mutex_lock(&clk->prepare_lock);
+	if (clk->prepare_count = 0 && clk->ops->prepare)
+		ret = clk->ops->prepare(clk);
+
+	if (!ret)
+		clk->prepare_count++;
+	mutex_unlock(&clk->prepare_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_prepare);
+
+void clk_unprepare(struct clk *clk)
+{
+	mutex_lock(&clk->prepare_lock);
+
+	WARN_ON(clk->prepare_count = 0);
+
+	if (--clk->prepare_count = 0 && clk->ops->unprepare) {
+		WARN_ON(clk->enable_count != 0);
+		clk->ops->unprepare(clk);
+	}
+
+	mutex_unlock(&clk->prepare_lock);
+}
+EXPORT_SYMBOL_GPL(clk_unprepare);
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	WARN_ON(clk->prepare_count = 0);
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+	if (clk->enable_count = 0 && clk->ops->enable)
+		ret = clk->ops->enable(clk);
+
+	if (!ret)
+		clk->enable_count++;
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+
+	WARN_ON(clk->enable_count = 0);
+
+	if (!--clk->enable_count = 0 && clk->ops->disable)
+		clk->ops->disable(clk);
+
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk->ops->get_rate)
+		return clk->ops->get_rate(clk);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->round_rate)
+		return clk->ops->round_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	might_sleep();
+
+	if (clk->ops->set_rate)
+		return clk->ops->set_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (clk->ops->set_parent)
+		return clk->ops->set_parent(clk, parent);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	if (clk->ops->get_parent)
+		return clk->ops->get_parent(clk);
+	return ERR_PTR(-ENOSYS);
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
+
+int __clk_get(struct clk *clk)
+{
+	if (clk->ops->get)
+		return clk->ops->get(clk);
+	return 1;
+}
+
+void __clk_put(struct clk *clk)
+{
+	if (clk->ops->put)
+		clk->ops->put(clk);
+}
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 0fc0a79..a7999d2 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -23,6 +23,13 @@
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 
+/* For USE_COMMON_STRUCT_CLK, these are provided in clk.c, but not exported
+ * through other headers; we don't want them used anywhere but here. */
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+extern int __clk_get(struct clk *clk);
+extern void __clk_put(struct clk *clk);
+#endif
+
 /*
  * Find the correct struct clk for the device and connection ID.
  * We do slightly fuzzy matching here:
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1d37f42..604be74 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2004 ARM Limited.
  *  Written by Deep Blue Solutions Limited.
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,18 +12,168 @@
 #ifndef __LINUX_CLK_H
 #define __LINUX_CLK_H
 
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
 struct device;
 
-/*
- * The base API.
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+
+/* If we're using the common struct clk, we define the base clk object here */
+
+/**
+ * struct clk - hardware independent clock structure
+ * @ops:		implementation-specific ops for this clock
+ * @enable_count:	count of clk_enable() calls active on this clock
+ * @enable_lock:	lock for atomic enable
+ * @prepare_count:	count of clk_prepare() calls active on this clock
+ * @prepare_lock:	lock for sleepable prepare
+ *
+ * The base clock object, used by drivers for hardware-independent manipulation
+ * of clock lines. This will be 'subclassed' by device-specific implementations,
+ * which add device-specific data to struct clk. For example:
+ *
+ *  struct clk_foo {
+ *      struct clk;
+ *      [device specific fields]
+ *  };
+ *
+ * The clock driver code will manage the device-specific data, and pass
+ * clk_foo.clk to the common clock code. The clock driver will be called
+ * through the @ops callbacks.
+ *
+ * The @enable_lock and @prepare_lock members are used to serialise accesses
+ * to the ops->enable and ops->prepare functions (and the corresponding
+ * ops->disable and ops->unprepare functions).
  */
+struct clk {
+	const struct clk_ops	*ops;
+	unsigned int		enable_count;
+	unsigned int		prepare_count;
+	spinlock_t		enable_lock;
+	struct mutex		prepare_lock;
+};
 
+/* static initialiser for clocks. */
+#define INIT_CLK(name, o) {						\
+	.ops		= &o,						\
+	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
+	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
+}
+
+/**
+ * struct clk_ops -  Callback operations for clocks; these are to be provided
+ * by the clock implementation, and will be called by drivers through the clk_*
+ * API.
+ *
+ * @prepare:	Prepare the clock for enabling. This must not return until
+ *		the clock is fully prepared, and it's safe to call clk_enable.
+ *		This callback is intended to allow clock implementations to
+ *		do any initialisation that may sleep. Called with
+ *		clk->prepare_lock held.
+ *
+ * @unprepare:	Release the clock from its prepared state. This will typically
+ *		undo any work done in the @prepare callback. Called with
+ *		clk->prepare_lock held.
+ *
+ * @enable:	Enable the clock atomically. This must not return until the
+ *		clock is generating a valid clock signal, usable by consumer
+ *		devices. Called with clk->enable_lock held. This function
+ *		must not sleep.
+ *
+ * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
+ *		This function must not sleep.
+ *
+ * @get:	Called by the core clock code when a device driver acquires a
+ *		clock via clk_get(). Optional.
+ *
+ * @put:	Called by the core clock code when a devices driver releases a
+ *		clock via clk_put(). Optional.
+ *
+ * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
+ * implementations to split any work between atomic (enable) and sleepable
+ * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
+ * should be done in clk_prepare. Switching that will not sleep should be done
+ * in clk_enable.
+ *
+ * Typically, drivers will call clk_prepare when a clock may be needed later
+ * (eg. when a device is opened), and clk_enable when the clock is actually
+ * required (eg. from an interrupt). Note that clk_prepare *must* have been
+ * called before clk_enable.
+ *
+ * For other callbacks, see the corresponding clk_* functions. Parameters and
+ * return values are passed directly from/to these API functions, or
+ * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
+ * is NULL, see drivers/clk/clk.c for implementation details. All are optional.
+ */
+struct clk_ops {
+	int		(*prepare)(struct clk *);
+	void		(*unprepare)(struct clk *);
+	int		(*enable)(struct clk *);
+	void		(*disable)(struct clk *);
+	int		(*get)(struct clk *);
+	void		(*put)(struct clk *);
+	unsigned long	(*get_rate)(struct clk *);
+	long		(*round_rate)(struct clk *, unsigned long);
+	int		(*set_rate)(struct clk *, unsigned long);
+	int		(*set_parent)(struct clk *, struct clk *);
+	struct clk *	(*get_parent)(struct clk *);
+};
+
+/**
+ * clk_prepare - prepare clock for atomic enabling.
+ *
+ * @clk: The clock to prepare
+ *
+ * Do any possibly sleeping initialisation on @clk, allowing the clock to be
+ * later enabled atomically (via clk_enable). This function may sleep.
+ */
+int clk_prepare(struct clk *clk);
+
+/**
+ * clk_unprepare - release clock from prepared state
+ *
+ * @clk: The clock to release
+ *
+ * Do any (possibly sleeping) cleanup on clk. This function may sleep.
+ */
+void clk_unprepare(struct clk *clk);
+
+/**
+ * clk_common_init - initialise a clock for driver usage
+ *
+ * @clk: The clock to initialise
+ *
+ * Used for runtime intialization of clocks; you don't need to call this
+ * if your clock has been (statically) initialized with INIT_CLK.
+ */
+static inline void clk_common_init(struct clk *clk)
+{
+	clk->enable_count = clk->prepare_count = 0;
+	spin_lock_init(&clk->enable_lock);
+	mutex_init(&clk->prepare_lock);
+}
+
+#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*
- * struct clk - an machine class defined object / cookie.
+ * Global clock object, actual structure is declared per-machine
  */
 struct clk;
 
+static inline void clk_common_init(struct clk *clk) { }
+
+/*
+ * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
+ * requirements for clk_enable/clk_disable, so the prepare and unprepare
+ * functions are no-ops
+ */
+int clk_prepare(struct clk *clk) { return 0; }
+void clk_unprepare(struct clk *clk) { }
+
+#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
+
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
  * @dev: device for clock "consumer"
@@ -67,6 +218,7 @@ void clk_disable(struct clk *clk);
 /**
  * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *		  This is only valid once the clock source has been enabled.
+ *		  Returns zero if the clock rate is unknown.
  * @clk: clock source
  */
 unsigned long clk_get_rate(struct clk *clk);
@@ -83,12 +235,6 @@ unsigned long clk_get_rate(struct clk *clk);
  */
 void clk_put(struct clk *clk);
 
-
-/*
- * The remaining APIs are optional for machine class support.
- */
-
-
 /**
  * clk_round_rate - adjust a rate to the exact rate a clock can provide
  * @clk: clock source

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [PATCH 2/2] clk: Generic support for fixed-rate clocks
  2011-02-21  2:50   ` Jeremy Kerr
  (?)
@ 2011-02-21  2:50     ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-21  2:50 UTC (permalink / raw)
  To: linux-arm-kernel

Since most platforms will need a fixed-rate clock, add one. This will
also serve as a basic example of an implementation of struct clk.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/clk.c   |   14 ++++++++++++++
 include/linux/clk.h |   16 ++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0bc9c6f..0da0bb9 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -130,3 +130,17 @@ void __clk_put(struct clk *clk)
 	if (clk->ops->put)
 		clk->ops->put(clk);
 }
+
+/* clk_fixed support */
+
+#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
+
+static unsigned long clk_fixed_get_rate(struct clk *clk)
+{
+	return to_clk_fixed(clk)->rate;
+}
+
+struct clk_ops clk_fixed_ops = {
+	.get_rate = clk_fixed_get_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 604be74..7c0808c 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -155,6 +155,22 @@ static inline void clk_common_init(struct clk *clk)
 	mutex_init(&clk->prepare_lock);
 }
 
+/* Simple fixed-rate clock */
+struct clk_fixed {
+	struct clk	clk;
+	unsigned long	rate;
+};
+
+extern struct clk_ops clk_fixed_ops;
+
+#define INIT_CLK_FIXED(name, r) { \
+	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
+	.rate = (r) \
+}
+
+#define DEFINE_CLK_FIXED(name, r) \
+	struct clk_fixed name = INIT_CLK_FIXED(name, r)
+
 #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [PATCH 1/2] Add a common struct clk
@ 2011-02-21  2:50     ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-21  2:50 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenchmidt, Uwe Kleine-König, Sascha Hauer,
	Paul Mundt, Saravana Kannan, Ben Dooks, Jeremy Kerr,
	Russell King

We currently have ~21 definitions of struct clk in the ARM architecture,
each defined on a per-platform basis. This makes it difficult to define
platform- (or architecture-) independent clock sources without making
assumptions about struct clk, and impossible to compile two
platforms with different struct clks into a single image.

This change is an effort to unify struct clk where possible, by defining
a common struct clk, containing a set of clock operations. Different
clock implementations can set their own operations, and have a standard
interface for generic code. The callback interface is exposed to the
kernel proper, while the clock implementations only need to be seen by
the platform internals.

This allows us to share clock code among platforms, and makes it
possible to dynamically create clock devices in platform-independent
code.

Platforms can enable the generic struct clock through
CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
consists of a common struct clk:

struct clk {
	const struct clk_ops	*ops;
	unsigned int		enable_count;
	unsigned int		prepare_count;
	spinlock_t		enable_lock;
	struct mutex		prepare_lock;
};

And a set of clock operations (defined per type of clock):

struct clk_ops {
	int             (*enable)(struct clk *);
	void            (*disable)(struct clk *);
	unsigned long   (*get_rate)(struct clk *);
	[...]
};

To define a hardware-specific clock, machine code can "subclass" the
struct clock into a new struct (adding any device-specific data), and
provide a set of operations:

struct clk_foo {
	struct clk	clk;
	void __iomem	*some_register;
};

struct clk_ops clk_foo_ops = {
	.get_rate = clk_foo_get_rate,
};

The common clock definitions are based on a development patch from Ben
Herrenschmidt <benh@kernel.crashing.org>.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/Kconfig  |    3 
 drivers/clk/Makefile |    1 
 drivers/clk/clk.c    |  132 ++++++++++++++++++++++++++++++++++
 drivers/clk/clkdev.c |    7 +
 include/linux/clk.h  |  164 ++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 298 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 4168c88..6e3ae54 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -2,3 +2,6 @@
 config CLKDEV_LOOKUP
 	bool
 	select HAVE_CLK
+
+config USE_COMMON_STRUCT_CLK
+	bool
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 07613fa..a1a06d3 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,2 +1,3 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
+obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
new file mode 100644
index 0000000..0bc9c6f
--- /dev/null
+++ b/drivers/clk/clk.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+
+int clk_prepare(struct clk *clk)
+{
+	int ret = 0;
+
+	mutex_lock(&clk->prepare_lock);
+	if (clk->prepare_count == 0 && clk->ops->prepare)
+		ret = clk->ops->prepare(clk);
+
+	if (!ret)
+		clk->prepare_count++;
+	mutex_unlock(&clk->prepare_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_prepare);
+
+void clk_unprepare(struct clk *clk)
+{
+	mutex_lock(&clk->prepare_lock);
+
+	WARN_ON(clk->prepare_count == 0);
+
+	if (--clk->prepare_count == 0 && clk->ops->unprepare) {
+		WARN_ON(clk->enable_count != 0);
+		clk->ops->unprepare(clk);
+	}
+
+	mutex_unlock(&clk->prepare_lock);
+}
+EXPORT_SYMBOL_GPL(clk_unprepare);
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	WARN_ON(clk->prepare_count == 0);
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+	if (clk->enable_count == 0 && clk->ops->enable)
+		ret = clk->ops->enable(clk);
+
+	if (!ret)
+		clk->enable_count++;
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+
+	WARN_ON(clk->enable_count == 0);
+
+	if (!--clk->enable_count == 0 && clk->ops->disable)
+		clk->ops->disable(clk);
+
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk->ops->get_rate)
+		return clk->ops->get_rate(clk);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->round_rate)
+		return clk->ops->round_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	might_sleep();
+
+	if (clk->ops->set_rate)
+		return clk->ops->set_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (clk->ops->set_parent)
+		return clk->ops->set_parent(clk, parent);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	if (clk->ops->get_parent)
+		return clk->ops->get_parent(clk);
+	return ERR_PTR(-ENOSYS);
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
+
+int __clk_get(struct clk *clk)
+{
+	if (clk->ops->get)
+		return clk->ops->get(clk);
+	return 1;
+}
+
+void __clk_put(struct clk *clk)
+{
+	if (clk->ops->put)
+		clk->ops->put(clk);
+}
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 0fc0a79..a7999d2 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -23,6 +23,13 @@
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 
+/* For USE_COMMON_STRUCT_CLK, these are provided in clk.c, but not exported
+ * through other headers; we don't want them used anywhere but here. */
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+extern int __clk_get(struct clk *clk);
+extern void __clk_put(struct clk *clk);
+#endif
+
 /*
  * Find the correct struct clk for the device and connection ID.
  * We do slightly fuzzy matching here:
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1d37f42..604be74 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2004 ARM Limited.
  *  Written by Deep Blue Solutions Limited.
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,18 +12,168 @@
 #ifndef __LINUX_CLK_H
 #define __LINUX_CLK_H
 
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
 struct device;
 
-/*
- * The base API.
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+
+/* If we're using the common struct clk, we define the base clk object here */
+
+/**
+ * struct clk - hardware independent clock structure
+ * @ops:		implementation-specific ops for this clock
+ * @enable_count:	count of clk_enable() calls active on this clock
+ * @enable_lock:	lock for atomic enable
+ * @prepare_count:	count of clk_prepare() calls active on this clock
+ * @prepare_lock:	lock for sleepable prepare
+ *
+ * The base clock object, used by drivers for hardware-independent manipulation
+ * of clock lines. This will be 'subclassed' by device-specific implementations,
+ * which add device-specific data to struct clk. For example:
+ *
+ *  struct clk_foo {
+ *      struct clk;
+ *      [device specific fields]
+ *  };
+ *
+ * The clock driver code will manage the device-specific data, and pass
+ * clk_foo.clk to the common clock code. The clock driver will be called
+ * through the @ops callbacks.
+ *
+ * The @enable_lock and @prepare_lock members are used to serialise accesses
+ * to the ops->enable and ops->prepare functions (and the corresponding
+ * ops->disable and ops->unprepare functions).
  */
+struct clk {
+	const struct clk_ops	*ops;
+	unsigned int		enable_count;
+	unsigned int		prepare_count;
+	spinlock_t		enable_lock;
+	struct mutex		prepare_lock;
+};
 
+/* static initialiser for clocks. */
+#define INIT_CLK(name, o) {						\
+	.ops		= &o,						\
+	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
+	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
+}
+
+/**
+ * struct clk_ops -  Callback operations for clocks; these are to be provided
+ * by the clock implementation, and will be called by drivers through the clk_*
+ * API.
+ *
+ * @prepare:	Prepare the clock for enabling. This must not return until
+ *		the clock is fully prepared, and it's safe to call clk_enable.
+ *		This callback is intended to allow clock implementations to
+ *		do any initialisation that may sleep. Called with
+ *		clk->prepare_lock held.
+ *
+ * @unprepare:	Release the clock from its prepared state. This will typically
+ *		undo any work done in the @prepare callback. Called with
+ *		clk->prepare_lock held.
+ *
+ * @enable:	Enable the clock atomically. This must not return until the
+ *		clock is generating a valid clock signal, usable by consumer
+ *		devices. Called with clk->enable_lock held. This function
+ *		must not sleep.
+ *
+ * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
+ *		This function must not sleep.
+ *
+ * @get:	Called by the core clock code when a device driver acquires a
+ *		clock via clk_get(). Optional.
+ *
+ * @put:	Called by the core clock code when a devices driver releases a
+ *		clock via clk_put(). Optional.
+ *
+ * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
+ * implementations to split any work between atomic (enable) and sleepable
+ * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
+ * should be done in clk_prepare. Switching that will not sleep should be done
+ * in clk_enable.
+ *
+ * Typically, drivers will call clk_prepare when a clock may be needed later
+ * (eg. when a device is opened), and clk_enable when the clock is actually
+ * required (eg. from an interrupt). Note that clk_prepare *must* have been
+ * called before clk_enable.
+ *
+ * For other callbacks, see the corresponding clk_* functions. Parameters and
+ * return values are passed directly from/to these API functions, or
+ * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
+ * is NULL, see drivers/clk/clk.c for implementation details. All are optional.
+ */
+struct clk_ops {
+	int		(*prepare)(struct clk *);
+	void		(*unprepare)(struct clk *);
+	int		(*enable)(struct clk *);
+	void		(*disable)(struct clk *);
+	int		(*get)(struct clk *);
+	void		(*put)(struct clk *);
+	unsigned long	(*get_rate)(struct clk *);
+	long		(*round_rate)(struct clk *, unsigned long);
+	int		(*set_rate)(struct clk *, unsigned long);
+	int		(*set_parent)(struct clk *, struct clk *);
+	struct clk *	(*get_parent)(struct clk *);
+};
+
+/**
+ * clk_prepare - prepare clock for atomic enabling.
+ *
+ * @clk: The clock to prepare
+ *
+ * Do any possibly sleeping initialisation on @clk, allowing the clock to be
+ * later enabled atomically (via clk_enable). This function may sleep.
+ */
+int clk_prepare(struct clk *clk);
+
+/**
+ * clk_unprepare - release clock from prepared state
+ *
+ * @clk: The clock to release
+ *
+ * Do any (possibly sleeping) cleanup on clk. This function may sleep.
+ */
+void clk_unprepare(struct clk *clk);
+
+/**
+ * clk_common_init - initialise a clock for driver usage
+ *
+ * @clk: The clock to initialise
+ *
+ * Used for runtime intialization of clocks; you don't need to call this
+ * if your clock has been (statically) initialized with INIT_CLK.
+ */
+static inline void clk_common_init(struct clk *clk)
+{
+	clk->enable_count = clk->prepare_count = 0;
+	spin_lock_init(&clk->enable_lock);
+	mutex_init(&clk->prepare_lock);
+}
+
+#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*
- * struct clk - an machine class defined object / cookie.
+ * Global clock object, actual structure is declared per-machine
  */
 struct clk;
 
+static inline void clk_common_init(struct clk *clk) { }
+
+/*
+ * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
+ * requirements for clk_enable/clk_disable, so the prepare and unprepare
+ * functions are no-ops
+ */
+int clk_prepare(struct clk *clk) { return 0; }
+void clk_unprepare(struct clk *clk) { }
+
+#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
+
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
  * @dev: device for clock "consumer"
@@ -67,6 +218,7 @@ void clk_disable(struct clk *clk);
 /**
  * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *		  This is only valid once the clock source has been enabled.
+ *		  Returns zero if the clock rate is unknown.
  * @clk: clock source
  */
 unsigned long clk_get_rate(struct clk *clk);
@@ -83,12 +235,6 @@ unsigned long clk_get_rate(struct clk *clk);
  */
 void clk_put(struct clk *clk);
 
-
-/*
- * The remaining APIs are optional for machine class support.
- */
-
-
 /**
  * clk_round_rate - adjust a rate to the exact rate a clock can provide
  * @clk: clock source

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v13
@ 2011-02-21  2:50   ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-21  2:50 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenchmidt, Uwe Kleine-König, Sascha Hauer,
	Paul Mundt, Saravana Kannan, Ben Dooks, Jeremy Kerr,
	Russell King

Hi all,

These patches are an attempt to allow platforms to share clock code. At
present, the definitions of 'struct clk' are local to platform code,
which makes allocating and initialising cross-platform clock sources
difficult, and makes it impossible to compile a single image containing
support for two ARM platforms with different struct clks.

The three patches are for the architecture-independent kernel code,
introducing the common clk infrastructure. The changelog for the first
patch includes details about the new clock definitions.

Many thanks to the following for their input:
 * Benjamin Herrenschmidt <benh@kernel.crashing.org>
 * Ben Dooks <ben-linux@fluff.org>
 * Baruch Siach <baruch@tkos.co.il>
 * Russell King <linux@arm.linux.org.uk>
 * Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 * Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
 * Vincent Guittot <vincent.guittot@linaro.org>
 * Sascha Hauer <s.hauer@pengutronix.de>
 * Ryan Mallon <ryan@bluewatersys.com>
 * Colin Cross <ccross@google.com>
 * Jassi Brar <jassisinghbrar@gmail.com>
 * Saravana Kannan <skannan@codeaurora.org>

Cheers,


Jeremy

--
v13:
 * Don't expose __clk_get and clk_put - prototypes in clkdev.c instead
 * Add might_sleep to clk_set_rate
 * Comment clarifications & fixups
 * Remove zero initialisers
 * Fold warnings into main clk.c change

v12:
 * Always refcount, even when enable/prepare ops are NULL
 * Unify prepare & enable count checking
 * Update comments for prepare/unprepare
 * Use spin_{lock,unlock}_irqsave
 * Change clk_put to __clk_put, and use the shared clk_put

v11:
 * add prepare/unprepare for non-atomic switching, document atomicity
 * move to drivers/clk/

v10:
 * comment fixups, from Uwe's review
 * added DEFINE_CLK_FIXED

v9:
 * comment improvements
 * kerneldoc fixups
 * add WARN_ON to clk_disable

v8:
 * add atomic clocks, and locking wrappers
 * expand comments on clk and clk_ops

v7:
 * change CLK_INIT to initialise clk->mutex statically

v6:
 * fixed up references to 'clk_operations' in the changelog

v5:
 * uninline main API, and share definitions with !USE_COMMON_STRUCT_CLK
 * add __clk_get
 * delay mutex init
 * kerneldoc for struct clk

v4:
 * use mutex for enable/disable locking
 * DEFINE_CLK -> INIT_CLK, and pass the clk name for mutex init
 * struct clk_operations -> struct clk_ops

v3:
 * do clock usage refcounting in common code
 * provide sample port

v2:
 * no longer ARM-specific
 * use clk_operations

---
Jeremy Kerr (2):
      Add a common struct clk
      clk: Generic support for fixed-rate clocks


^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 2/2] clk: Generic support for fixed-rate clocks
@ 2011-02-21  2:50     ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-21  2:50 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenchmidt, Uwe Kleine-König, Sascha Hauer,
	Paul Mundt, Saravana Kannan, Ben Dooks, Jeremy Kerr,
	Russell King

Since most platforms will need a fixed-rate clock, add one. This will
also serve as a basic example of an implementation of struct clk.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/clk.c   |   14 ++++++++++++++
 include/linux/clk.h |   16 ++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0bc9c6f..0da0bb9 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -130,3 +130,17 @@ void __clk_put(struct clk *clk)
 	if (clk->ops->put)
 		clk->ops->put(clk);
 }
+
+/* clk_fixed support */
+
+#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
+
+static unsigned long clk_fixed_get_rate(struct clk *clk)
+{
+	return to_clk_fixed(clk)->rate;
+}
+
+struct clk_ops clk_fixed_ops = {
+	.get_rate = clk_fixed_get_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 604be74..7c0808c 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -155,6 +155,22 @@ static inline void clk_common_init(struct clk *clk)
 	mutex_init(&clk->prepare_lock);
 }
 
+/* Simple fixed-rate clock */
+struct clk_fixed {
+	struct clk	clk;
+	unsigned long	rate;
+};
+
+extern struct clk_ops clk_fixed_ops;
+
+#define INIT_CLK_FIXED(name, r) { \
+	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
+	.rate = (r) \
+}
+
+#define DEFINE_CLK_FIXED(name, r) \
+	struct clk_fixed name = INIT_CLK_FIXED(name, r)
+
 #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [PATCH 2/2] clk: Generic support for fixed-rate clocks
@ 2011-02-21  2:50     ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-21  2:50 UTC (permalink / raw)
  To: linux-arm-kernel

Since most platforms will need a fixed-rate clock, add one. This will
also serve as a basic example of an implementation of struct clk.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/clk.c   |   14 ++++++++++++++
 include/linux/clk.h |   16 ++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0bc9c6f..0da0bb9 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -130,3 +130,17 @@ void __clk_put(struct clk *clk)
 	if (clk->ops->put)
 		clk->ops->put(clk);
 }
+
+/* clk_fixed support */
+
+#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
+
+static unsigned long clk_fixed_get_rate(struct clk *clk)
+{
+	return to_clk_fixed(clk)->rate;
+}
+
+struct clk_ops clk_fixed_ops = {
+	.get_rate = clk_fixed_get_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 604be74..7c0808c 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -155,6 +155,22 @@ static inline void clk_common_init(struct clk *clk)
 	mutex_init(&clk->prepare_lock);
 }
 
+/* Simple fixed-rate clock */
+struct clk_fixed {
+	struct clk	clk;
+	unsigned long	rate;
+};
+
+extern struct clk_ops clk_fixed_ops;
+
+#define INIT_CLK_FIXED(name, r) { \
+	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
+	.rate = (r) \
+}
+
+#define DEFINE_CLK_FIXED(name, r) \
+	struct clk_fixed name = INIT_CLK_FIXED(name, r)
+
 #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v13
@ 2011-02-21  2:50   ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-21  2:50 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

These patches are an attempt to allow platforms to share clock code. At
present, the definitions of 'struct clk' are local to platform code,
which makes allocating and initialising cross-platform clock sources
difficult, and makes it impossible to compile a single image containing
support for two ARM platforms with different struct clks.

The three patches are for the architecture-independent kernel code,
introducing the common clk infrastructure. The changelog for the first
patch includes details about the new clock definitions.

Many thanks to the following for their input:
 * Benjamin Herrenschmidt <benh@kernel.crashing.org>
 * Ben Dooks <ben-linux@fluff.org>
 * Baruch Siach <baruch@tkos.co.il>
 * Russell King <linux@arm.linux.org.uk>
 * Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
 * Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
 * Vincent Guittot <vincent.guittot@linaro.org>
 * Sascha Hauer <s.hauer@pengutronix.de>
 * Ryan Mallon <ryan@bluewatersys.com>
 * Colin Cross <ccross@google.com>
 * Jassi Brar <jassisinghbrar@gmail.com>
 * Saravana Kannan <skannan@codeaurora.org>

Cheers,


Jeremy

--
v13:
 * Don't expose __clk_get and clk_put - prototypes in clkdev.c instead
 * Add might_sleep to clk_set_rate
 * Comment clarifications & fixups
 * Remove zero initialisers
 * Fold warnings into main clk.c change

v12:
 * Always refcount, even when enable/prepare ops are NULL
 * Unify prepare & enable count checking
 * Update comments for prepare/unprepare
 * Use spin_{lock,unlock}_irqsave
 * Change clk_put to __clk_put, and use the shared clk_put

v11:
 * add prepare/unprepare for non-atomic switching, document atomicity
 * move to drivers/clk/

v10:
 * comment fixups, from Uwe's review
 * added DEFINE_CLK_FIXED

v9:
 * comment improvements
 * kerneldoc fixups
 * add WARN_ON to clk_disable

v8:
 * add atomic clocks, and locking wrappers
 * expand comments on clk and clk_ops

v7:
 * change CLK_INIT to initialise clk->mutex statically

v6:
 * fixed up references to 'clk_operations' in the changelog

v5:
 * uninline main API, and share definitions with !USE_COMMON_STRUCT_CLK
 * add __clk_get
 * delay mutex init
 * kerneldoc for struct clk

v4:
 * use mutex for enable/disable locking
 * DEFINE_CLK -> INIT_CLK, and pass the clk name for mutex init
 * struct clk_operations -> struct clk_ops

v3:
 * do clock usage refcounting in common code
 * provide sample port

v2:
 * no longer ARM-specific
 * use clk_operations

---
Jeremy Kerr (2):
      Add a common struct clk
      clk: Generic support for fixed-rate clocks

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 1/2] Add a common struct clk
@ 2011-02-21  2:50     ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-21  2:50 UTC (permalink / raw)
  To: linux-arm-kernel

We currently have ~21 definitions of struct clk in the ARM architecture,
each defined on a per-platform basis. This makes it difficult to define
platform- (or architecture-) independent clock sources without making
assumptions about struct clk, and impossible to compile two
platforms with different struct clks into a single image.

This change is an effort to unify struct clk where possible, by defining
a common struct clk, containing a set of clock operations. Different
clock implementations can set their own operations, and have a standard
interface for generic code. The callback interface is exposed to the
kernel proper, while the clock implementations only need to be seen by
the platform internals.

This allows us to share clock code among platforms, and makes it
possible to dynamically create clock devices in platform-independent
code.

Platforms can enable the generic struct clock through
CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
consists of a common struct clk:

struct clk {
	const struct clk_ops	*ops;
	unsigned int		enable_count;
	unsigned int		prepare_count;
	spinlock_t		enable_lock;
	struct mutex		prepare_lock;
};

And a set of clock operations (defined per type of clock):

struct clk_ops {
	int             (*enable)(struct clk *);
	void            (*disable)(struct clk *);
	unsigned long   (*get_rate)(struct clk *);
	[...]
};

To define a hardware-specific clock, machine code can "subclass" the
struct clock into a new struct (adding any device-specific data), and
provide a set of operations:

struct clk_foo {
	struct clk	clk;
	void __iomem	*some_register;
};

struct clk_ops clk_foo_ops = {
	.get_rate = clk_foo_get_rate,
};

The common clock definitions are based on a development patch from Ben
Herrenschmidt <benh@kernel.crashing.org>.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/Kconfig  |    3 
 drivers/clk/Makefile |    1 
 drivers/clk/clk.c    |  132 ++++++++++++++++++++++++++++++++++
 drivers/clk/clkdev.c |    7 +
 include/linux/clk.h  |  164 ++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 298 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 4168c88..6e3ae54 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -2,3 +2,6 @@
 config CLKDEV_LOOKUP
 	bool
 	select HAVE_CLK
+
+config USE_COMMON_STRUCT_CLK
+	bool
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 07613fa..a1a06d3 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,2 +1,3 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
+obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
new file mode 100644
index 0000000..0bc9c6f
--- /dev/null
+++ b/drivers/clk/clk.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+
+int clk_prepare(struct clk *clk)
+{
+	int ret = 0;
+
+	mutex_lock(&clk->prepare_lock);
+	if (clk->prepare_count == 0 && clk->ops->prepare)
+		ret = clk->ops->prepare(clk);
+
+	if (!ret)
+		clk->prepare_count++;
+	mutex_unlock(&clk->prepare_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_prepare);
+
+void clk_unprepare(struct clk *clk)
+{
+	mutex_lock(&clk->prepare_lock);
+
+	WARN_ON(clk->prepare_count == 0);
+
+	if (--clk->prepare_count == 0 && clk->ops->unprepare) {
+		WARN_ON(clk->enable_count != 0);
+		clk->ops->unprepare(clk);
+	}
+
+	mutex_unlock(&clk->prepare_lock);
+}
+EXPORT_SYMBOL_GPL(clk_unprepare);
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	WARN_ON(clk->prepare_count == 0);
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+	if (clk->enable_count == 0 && clk->ops->enable)
+		ret = clk->ops->enable(clk);
+
+	if (!ret)
+		clk->enable_count++;
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+
+	WARN_ON(clk->enable_count == 0);
+
+	if (!--clk->enable_count == 0 && clk->ops->disable)
+		clk->ops->disable(clk);
+
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk->ops->get_rate)
+		return clk->ops->get_rate(clk);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->round_rate)
+		return clk->ops->round_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	might_sleep();
+
+	if (clk->ops->set_rate)
+		return clk->ops->set_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (clk->ops->set_parent)
+		return clk->ops->set_parent(clk, parent);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	if (clk->ops->get_parent)
+		return clk->ops->get_parent(clk);
+	return ERR_PTR(-ENOSYS);
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
+
+int __clk_get(struct clk *clk)
+{
+	if (clk->ops->get)
+		return clk->ops->get(clk);
+	return 1;
+}
+
+void __clk_put(struct clk *clk)
+{
+	if (clk->ops->put)
+		clk->ops->put(clk);
+}
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 0fc0a79..a7999d2 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -23,6 +23,13 @@
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 
+/* For USE_COMMON_STRUCT_CLK, these are provided in clk.c, but not exported
+ * through other headers; we don't want them used anywhere but here. */
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+extern int __clk_get(struct clk *clk);
+extern void __clk_put(struct clk *clk);
+#endif
+
 /*
  * Find the correct struct clk for the device and connection ID.
  * We do slightly fuzzy matching here:
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1d37f42..604be74 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2004 ARM Limited.
  *  Written by Deep Blue Solutions Limited.
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,18 +12,168 @@
 #ifndef __LINUX_CLK_H
 #define __LINUX_CLK_H
 
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
 struct device;
 
-/*
- * The base API.
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+
+/* If we're using the common struct clk, we define the base clk object here */
+
+/**
+ * struct clk - hardware independent clock structure
+ * @ops:		implementation-specific ops for this clock
+ * @enable_count:	count of clk_enable() calls active on this clock
+ * @enable_lock:	lock for atomic enable
+ * @prepare_count:	count of clk_prepare() calls active on this clock
+ * @prepare_lock:	lock for sleepable prepare
+ *
+ * The base clock object, used by drivers for hardware-independent manipulation
+ * of clock lines. This will be 'subclassed' by device-specific implementations,
+ * which add device-specific data to struct clk. For example:
+ *
+ *  struct clk_foo {
+ *      struct clk;
+ *      [device specific fields]
+ *  };
+ *
+ * The clock driver code will manage the device-specific data, and pass
+ * clk_foo.clk to the common clock code. The clock driver will be called
+ * through the @ops callbacks.
+ *
+ * The @enable_lock and @prepare_lock members are used to serialise accesses
+ * to the ops->enable and ops->prepare functions (and the corresponding
+ * ops->disable and ops->unprepare functions).
  */
+struct clk {
+	const struct clk_ops	*ops;
+	unsigned int		enable_count;
+	unsigned int		prepare_count;
+	spinlock_t		enable_lock;
+	struct mutex		prepare_lock;
+};
 
+/* static initialiser for clocks. */
+#define INIT_CLK(name, o) {						\
+	.ops		= &o,						\
+	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
+	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
+}
+
+/**
+ * struct clk_ops -  Callback operations for clocks; these are to be provided
+ * by the clock implementation, and will be called by drivers through the clk_*
+ * API.
+ *
+ * @prepare:	Prepare the clock for enabling. This must not return until
+ *		the clock is fully prepared, and it's safe to call clk_enable.
+ *		This callback is intended to allow clock implementations to
+ *		do any initialisation that may sleep. Called with
+ *		clk->prepare_lock held.
+ *
+ * @unprepare:	Release the clock from its prepared state. This will typically
+ *		undo any work done in the @prepare callback. Called with
+ *		clk->prepare_lock held.
+ *
+ * @enable:	Enable the clock atomically. This must not return until the
+ *		clock is generating a valid clock signal, usable by consumer
+ *		devices. Called with clk->enable_lock held. This function
+ *		must not sleep.
+ *
+ * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
+ *		This function must not sleep.
+ *
+ * @get:	Called by the core clock code when a device driver acquires a
+ *		clock via clk_get(). Optional.
+ *
+ * @put:	Called by the core clock code when a devices driver releases a
+ *		clock via clk_put(). Optional.
+ *
+ * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
+ * implementations to split any work between atomic (enable) and sleepable
+ * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
+ * should be done in clk_prepare. Switching that will not sleep should be done
+ * in clk_enable.
+ *
+ * Typically, drivers will call clk_prepare when a clock may be needed later
+ * (eg. when a device is opened), and clk_enable when the clock is actually
+ * required (eg. from an interrupt). Note that clk_prepare *must* have been
+ * called before clk_enable.
+ *
+ * For other callbacks, see the corresponding clk_* functions. Parameters and
+ * return values are passed directly from/to these API functions, or
+ * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
+ * is NULL, see drivers/clk/clk.c for implementation details. All are optional.
+ */
+struct clk_ops {
+	int		(*prepare)(struct clk *);
+	void		(*unprepare)(struct clk *);
+	int		(*enable)(struct clk *);
+	void		(*disable)(struct clk *);
+	int		(*get)(struct clk *);
+	void		(*put)(struct clk *);
+	unsigned long	(*get_rate)(struct clk *);
+	long		(*round_rate)(struct clk *, unsigned long);
+	int		(*set_rate)(struct clk *, unsigned long);
+	int		(*set_parent)(struct clk *, struct clk *);
+	struct clk *	(*get_parent)(struct clk *);
+};
+
+/**
+ * clk_prepare - prepare clock for atomic enabling.
+ *
+ * @clk: The clock to prepare
+ *
+ * Do any possibly sleeping initialisation on @clk, allowing the clock to be
+ * later enabled atomically (via clk_enable). This function may sleep.
+ */
+int clk_prepare(struct clk *clk);
+
+/**
+ * clk_unprepare - release clock from prepared state
+ *
+ * @clk: The clock to release
+ *
+ * Do any (possibly sleeping) cleanup on clk. This function may sleep.
+ */
+void clk_unprepare(struct clk *clk);
+
+/**
+ * clk_common_init - initialise a clock for driver usage
+ *
+ * @clk: The clock to initialise
+ *
+ * Used for runtime intialization of clocks; you don't need to call this
+ * if your clock has been (statically) initialized with INIT_CLK.
+ */
+static inline void clk_common_init(struct clk *clk)
+{
+	clk->enable_count = clk->prepare_count = 0;
+	spin_lock_init(&clk->enable_lock);
+	mutex_init(&clk->prepare_lock);
+}
+
+#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*
- * struct clk - an machine class defined object / cookie.
+ * Global clock object, actual structure is declared per-machine
  */
 struct clk;
 
+static inline void clk_common_init(struct clk *clk) { }
+
+/*
+ * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
+ * requirements for clk_enable/clk_disable, so the prepare and unprepare
+ * functions are no-ops
+ */
+int clk_prepare(struct clk *clk) { return 0; }
+void clk_unprepare(struct clk *clk) { }
+
+#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
+
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
  * @dev: device for clock "consumer"
@@ -67,6 +218,7 @@ void clk_disable(struct clk *clk);
 /**
  * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *		  This is only valid once the clock source has been enabled.
+ *		  Returns zero if the clock rate is unknown.
  * @clk: clock source
  */
 unsigned long clk_get_rate(struct clk *clk);
@@ -83,12 +235,6 @@ unsigned long clk_get_rate(struct clk *clk);
  */
 void clk_put(struct clk *clk);
 
-
-/*
- * The remaining APIs are optional for machine class support.
- */
-
-
 /**
  * clk_round_rate - adjust a rate to the exact rate a clock can provide
  * @clk: clock source

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* Re: [PATCH 2/2] clk: Generic support for fixed-rate clocks
  2011-02-21  2:50     ` Jeremy Kerr
  (?)
@ 2011-02-21 19:51       ` Ryan Mallon
  -1 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-21 19:51 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/21/2011 03:50 PM, Jeremy Kerr wrote:
> Since most platforms will need a fixed-rate clock, add one. This will
> also serve as a basic example of an implementation of struct clk.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/clk.c   |   14 ++++++++++++++
>  include/linux/clk.h |   16 ++++++++++++++++
>  2 files changed, 30 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 0bc9c6f..0da0bb9 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -130,3 +130,17 @@ void __clk_put(struct clk *clk)
>  	if (clk->ops->put)
>  		clk->ops->put(clk);
>  }
> +
> +/* clk_fixed support */
> +
> +#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
> +
> +static unsigned long clk_fixed_get_rate(struct clk *clk)
> +{
> +	return to_clk_fixed(clk)->rate;
> +}
> +
> +struct clk_ops clk_fixed_ops = {
> +	.get_rate = clk_fixed_get_rate,
> +};
> +EXPORT_SYMBOL_GPL(clk_fixed_ops);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 604be74..7c0808c 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -155,6 +155,22 @@ static inline void clk_common_init(struct clk *clk)
>  	mutex_init(&clk->prepare_lock);
>  }
>  
> +/* Simple fixed-rate clock */
> +struct clk_fixed {
> +	struct clk	clk;
> +	unsigned long	rate;

If we never need to dynamically create fixed clocks (which seems
unlikely) then rate can be const.

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan@bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 2/2] clk: Generic support for fixed-rate clocks
@ 2011-02-21 19:51       ` Ryan Mallon
  0 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-21 19:51 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Dima Zavin,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenchmidt,
	Uwe Kleine-König, Sascha Hauer, Paul Mundt, Saravana Kannan,
	Ben Dooks, Russell King

On 02/21/2011 03:50 PM, Jeremy Kerr wrote:
> Since most platforms will need a fixed-rate clock, add one. This will
> also serve as a basic example of an implementation of struct clk.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/clk.c   |   14 ++++++++++++++
>  include/linux/clk.h |   16 ++++++++++++++++
>  2 files changed, 30 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 0bc9c6f..0da0bb9 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -130,3 +130,17 @@ void __clk_put(struct clk *clk)
>  	if (clk->ops->put)
>  		clk->ops->put(clk);
>  }
> +
> +/* clk_fixed support */
> +
> +#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
> +
> +static unsigned long clk_fixed_get_rate(struct clk *clk)
> +{
> +	return to_clk_fixed(clk)->rate;
> +}
> +
> +struct clk_ops clk_fixed_ops = {
> +	.get_rate = clk_fixed_get_rate,
> +};
> +EXPORT_SYMBOL_GPL(clk_fixed_ops);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 604be74..7c0808c 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -155,6 +155,22 @@ static inline void clk_common_init(struct clk *clk)
>  	mutex_init(&clk->prepare_lock);
>  }
>  
> +/* Simple fixed-rate clock */
> +struct clk_fixed {
> +	struct clk	clk;
> +	unsigned long	rate;

If we never need to dynamically create fixed clocks (which seems
unlikely) then rate can be const.

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan@bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 2/2] clk: Generic support for fixed-rate clocks
@ 2011-02-21 19:51       ` Ryan Mallon
  0 siblings, 0 replies; 383+ messages in thread
From: Ryan Mallon @ 2011-02-21 19:51 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/21/2011 03:50 PM, Jeremy Kerr wrote:
> Since most platforms will need a fixed-rate clock, add one. This will
> also serve as a basic example of an implementation of struct clk.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> ---
>  drivers/clk/clk.c   |   14 ++++++++++++++
>  include/linux/clk.h |   16 ++++++++++++++++
>  2 files changed, 30 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 0bc9c6f..0da0bb9 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -130,3 +130,17 @@ void __clk_put(struct clk *clk)
>  	if (clk->ops->put)
>  		clk->ops->put(clk);
>  }
> +
> +/* clk_fixed support */
> +
> +#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
> +
> +static unsigned long clk_fixed_get_rate(struct clk *clk)
> +{
> +	return to_clk_fixed(clk)->rate;
> +}
> +
> +struct clk_ops clk_fixed_ops = {
> +	.get_rate = clk_fixed_get_rate,
> +};
> +EXPORT_SYMBOL_GPL(clk_fixed_ops);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 604be74..7c0808c 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -155,6 +155,22 @@ static inline void clk_common_init(struct clk *clk)
>  	mutex_init(&clk->prepare_lock);
>  }
>  
> +/* Simple fixed-rate clock */
> +struct clk_fixed {
> +	struct clk	clk;
> +	unsigned long	rate;

If we never need to dynamically create fixed clocks (which seems
unlikely) then rate can be const.

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan at bluewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 2/2] clk: Generic support for fixed-rate clocks
  2011-02-21 19:51       ` Ryan Mallon
  (?)
@ 2011-02-21 23:29         ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-21 23:29 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ryan,

> If we never need to dynamically create fixed clocks (which seems
> unlikely) then rate can be const.

There's been a few cases where I've needed to set the rate of a fixed clock 
during boot - for example when a clock rate varies between boards, it may be 
defined in a platform-wide file, but have the rate modified early (ie, 
clk_foo.rate = 32678) in a board file.

Also, if we're parsing clocks from the device tree (or any other discovery 
mechanism), we'll need to modify rate.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 2/2] clk: Generic support for fixed-rate clocks
@ 2011-02-21 23:29         ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-21 23:29 UTC (permalink / raw)
  To: Ryan Mallon
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Dima Zavin,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenchmidt,
	Uwe Kleine-König, Sascha Hauer, Paul Mundt, Saravana Kannan,
	Ben Dooks, Russell King

Hi Ryan,

> If we never need to dynamically create fixed clocks (which seems
> unlikely) then rate can be const.

There's been a few cases where I've needed to set the rate of a fixed clock 
during boot - for example when a clock rate varies between boards, it may be 
defined in a platform-wide file, but have the rate modified early (ie, 
clk_foo.rate = 32678) in a board file.

Also, if we're parsing clocks from the device tree (or any other discovery 
mechanism), we'll need to modify rate.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 2/2] clk: Generic support for fixed-rate clocks
@ 2011-02-21 23:29         ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-21 23:29 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ryan,

> If we never need to dynamically create fixed clocks (which seems
> unlikely) then rate can be const.

There's been a few cases where I've needed to set the rate of a fixed clock 
during boot - for example when a clock rate varies between boards, it may be 
defined in a platform-wide file, but have the rate modified early (ie, 
clk_foo.rate = 32678) in a board file.

Also, if we're parsing clocks from the device tree (or any other discovery 
mechanism), we'll need to modify rate.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 1/2] Add a common struct clk
  2011-02-21  2:50     ` Jeremy Kerr
  (?)
@ 2011-02-22 20:17       ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-22 20:17 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jeremy,

On Mon, Feb 21, 2011 at 10:50:58AM +0800, Jeremy Kerr wrote:
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..604be74 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -11,18 +12,168 @@
> ...
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> ...
> +#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
>  
>  /*
> - * struct clk - an machine class defined object / cookie.
> + * Global clock object, actual structure is declared per-machine
>   */
>  struct clk;
>  
> +static inline void clk_common_init(struct clk *clk) { }
> +
> +/*
> + * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
> + * requirements for clk_enable/clk_disable, so the prepare and unprepare
> + * functions are no-ops
> + */
> +int clk_prepare(struct clk *clk) { return 0; }
> +void clk_unprepare(struct clk *clk) { }
these should be static inline.  Otherwise these functions end up in many
files and so provoke a build failure.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 1/2] Add a common struct clk
@ 2011-02-22 20:17       ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-22 20:17 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenchmidt, Sascha Hauer,
	Paul Mundt, Dima Zavin, Saravana Kannan, Ben Dooks, Russell King

Hi Jeremy,

On Mon, Feb 21, 2011 at 10:50:58AM +0800, Jeremy Kerr wrote:
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..604be74 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -11,18 +12,168 @@
> ...
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> ...
> +#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
>  
>  /*
> - * struct clk - an machine class defined object / cookie.
> + * Global clock object, actual structure is declared per-machine
>   */
>  struct clk;
>  
> +static inline void clk_common_init(struct clk *clk) { }
> +
> +/*
> + * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
> + * requirements for clk_enable/clk_disable, so the prepare and unprepare
> + * functions are no-ops
> + */
> +int clk_prepare(struct clk *clk) { return 0; }
> +void clk_unprepare(struct clk *clk) { }
these should be static inline.  Otherwise these functions end up in many
files and so provoke a build failure.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 1/2] Add a common struct clk
@ 2011-02-22 20:17       ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-22 20:17 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jeremy,

On Mon, Feb 21, 2011 at 10:50:58AM +0800, Jeremy Kerr wrote:
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..604be74 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -11,18 +12,168 @@
> ...
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> ...
> +#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
>  
>  /*
> - * struct clk - an machine class defined object / cookie.
> + * Global clock object, actual structure is declared per-machine
>   */
>  struct clk;
>  
> +static inline void clk_common_init(struct clk *clk) { }
> +
> +/*
> + * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
> + * requirements for clk_enable/clk_disable, so the prepare and unprepare
> + * functions are no-ops
> + */
> +int clk_prepare(struct clk *clk) { return 0; }
> +void clk_unprepare(struct clk *clk) { }
these should be static inline.  Otherwise these functions end up in many
files and so provoke a build failure.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH] wip: convert imx27 to common struct clk
  2011-02-21  2:50   ` Jeremy Kerr
  (?)
@ 2011-02-22 23:33     ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-22 23:33 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
Hello,

on top of .38-rc6 + making the clk_{un,}prepare stubs static inline,
this patch makes use of Jeremy's common struct clk (v13) on a i.MX27 based
machine.

This is compile tested using mx21_defconfig and runtime tested using
mx27_defconfig.

I had to degrade one WARN_ON to WARN_ON_ONCE in drivers/clk/clk.c to
actually make it work.  Otherwise console output results in a warning
that results in console output ...

Best regards
Uwe

 arch/arm/mach-imx/Kconfig               |    1 +
 arch/arm/mach-imx/clock-imx27.c         |  186 ++++++++++++++++--------------
 arch/arm/plat-mxc/clock.c               |  127 +++++++++++++++++++++
 arch/arm/plat-mxc/include/mach/clkdev.h |    4 +
 arch/arm/plat-mxc/include/mach/clock.h  |   32 ++++--
 drivers/clk/clk.c                       |    2 +-
 6 files changed, 255 insertions(+), 97 deletions(-)

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 56684b5..f2d3708 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -30,6 +30,7 @@ config SOC_IMX27
 	select IMX_HAVE_DMA_V1
 	select IMX_HAVE_IOMUX_V1
 	select MXC_AVIC
+	select USE_COMMON_STRUCT_CLK
 
 if ARCH_MX1
 
diff --git a/arch/arm/mach-imx/clock-imx27.c b/arch/arm/mach-imx/clock-imx27.c
index 583f251..f413f7b 100644
--- a/arch/arm/mach-imx/clock-imx27.c
+++ b/arch/arm/mach-imx/clock-imx27.c
@@ -68,35 +68,35 @@
 #define CCM_SPCTL1_LF           (1 << 15)
 #define CCM_SPCTL1_BRMO         (1 << 6)
 
-static struct clk mpll_main1_clk, mpll_main2_clk;
+static struct clk_mxc mpll_main1_clk, mpll_main2_clk;
 
-static int clk_pccr_enable(struct clk *clk)
+static int clk_pccr_enable(struct clk_mxc *clk_mxc)
 {
 	unsigned long reg;
 
-	if (!clk->enable_reg)
+	if (!clk_mxc->enable_reg)
 		return 0;
 
-	reg = __raw_readl(clk->enable_reg);
-	reg |= 1 << clk->enable_shift;
-	__raw_writel(reg, clk->enable_reg);
+	reg = __raw_readl(clk_mxc->enable_reg);
+	reg |= 1 << clk_mxc->enable_shift;
+	__raw_writel(reg, clk_mxc->enable_reg);
 
 	return 0;
 }
 
-static void clk_pccr_disable(struct clk *clk)
+static void clk_pccr_disable(struct clk_mxc *clk_mxc)
 {
 	unsigned long reg;
 
-	if (!clk->enable_reg)
+	if (!clk_mxc->enable_reg)
 		return;
 
-	reg = __raw_readl(clk->enable_reg);
-	reg &= ~(1 << clk->enable_shift);
-	__raw_writel(reg, clk->enable_reg);
+	reg = __raw_readl(clk_mxc->enable_reg);
+	reg &= ~(1 << clk_mxc->enable_shift);
+	__raw_writel(reg, clk_mxc->enable_reg);
 }
 
-static int clk_spll_enable(struct clk *clk)
+static int clk_spll_enable(struct clk_mxc *clk_mxc)
 {
 	unsigned long reg;
 
@@ -109,7 +109,7 @@ static int clk_spll_enable(struct clk *clk)
 	return 0;
 }
 
-static void clk_spll_disable(struct clk *clk)
+static void clk_spll_disable(struct clk_mxc *clk_mxc)
 {
 	unsigned long reg;
 
@@ -118,11 +118,11 @@ static void clk_spll_disable(struct clk *clk)
 	__raw_writel(reg, CCM_CSCR);
 }
 
-static int clk_cpu_set_parent(struct clk *clk, struct clk *parent)
+static int clk_cpu_set_parent(struct clk_mxc *clk_mxc, struct clk_mxc *parent)
 {
 	int cscr = __raw_readl(CCM_CSCR);
 
-	if (clk->parent = parent)
+	if (clk_mxc->parent = parent)
 		return 0;
 
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
@@ -135,18 +135,18 @@ static int clk_cpu_set_parent(struct clk *clk, struct clk *parent)
 				return -EINVAL;
 		}
 		__raw_writel(cscr, CCM_CSCR);
-		clk->parent = parent;
+		clk_mxc->parent = parent;
 		return 0;
 	}
 	return -ENODEV;
 }
 
-static unsigned long round_rate_cpu(struct clk *clk, unsigned long rate)
+static unsigned long round_rate_cpu(struct clk_mxc *clk_mxc, unsigned long rate)
 {
 	int div;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	div = parent_rate / rate;
 	if (parent_rate % rate)
@@ -158,13 +158,13 @@ static unsigned long round_rate_cpu(struct clk *clk, unsigned long rate)
 	return parent_rate / div;
 }
 
-static int set_rate_cpu(struct clk *clk, unsigned long rate)
+static int set_rate_cpu(struct clk_mxc *clk_mxc, unsigned long rate)
 {
 	unsigned int div;
 	uint32_t reg;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	div = parent_rate / rate;
 
@@ -186,12 +186,12 @@ static int set_rate_cpu(struct clk *clk, unsigned long rate)
 	return 0;
 }
 
-static unsigned long round_rate_per(struct clk *clk, unsigned long rate)
+static unsigned long round_rate_per(struct clk_mxc *clk_mxc, unsigned long rate)
 {
 	u32 div;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	div = parent_rate / rate;
 	if (parent_rate % rate)
@@ -203,15 +203,15 @@ static unsigned long round_rate_per(struct clk *clk, unsigned long rate)
 	return parent_rate / div;
 }
 
-static int set_rate_per(struct clk *clk, unsigned long rate)
+static int set_rate_per(struct clk_mxc *clk_mxc, unsigned long rate)
 {
 	u32 reg;
 	u32 div;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
-	if (clk->id < 0 || clk->id > 3)
+	if (clk_mxc->id < 0 || clk_mxc->id > 3)
 		return -EINVAL;
 
 	div = parent_rate / rate;
@@ -219,30 +219,30 @@ static int set_rate_per(struct clk *clk, unsigned long rate)
 		return -EINVAL;
 	div--;
 
-	reg = __raw_readl(CCM_PCDR1) & ~(0x3f << (clk->id << 3));
-	reg |= div << (clk->id << 3);
+	reg = __raw_readl(CCM_PCDR1) & ~(0x3f << (clk_mxc->id << 3));
+	reg |= div << (clk_mxc->id << 3);
 	__raw_writel(reg, CCM_PCDR1);
 
 	return 0;
 }
 
-static unsigned long get_rate_usb(struct clk *clk)
+static unsigned long get_rate_usb(struct clk_mxc *clk_mxc)
 {
 	unsigned long usb_pdf;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	usb_pdf = (__raw_readl(CCM_CSCR) >> 28) & 0x7;
 
 	return parent_rate / (usb_pdf + 1U);
 }
 
-static unsigned long get_rate_ssix(struct clk *clk, unsigned long pdf)
+static unsigned long get_rate_ssix(struct clk_mxc *clk_mxc, unsigned long pdf)
 {
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
 		pdf += 4;  /* MX27 TO2+ */
@@ -252,22 +252,22 @@ static unsigned long get_rate_ssix(struct clk *clk, unsigned long pdf)
 	return 2UL * parent_rate / pdf;
 }
 
-static unsigned long get_rate_ssi1(struct clk *clk)
+static unsigned long get_rate_ssi1(struct clk_mxc *clk_mxc)
 {
-	return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 16) & 0x3f);
+	return get_rate_ssix(clk_mxc, (__raw_readl(CCM_PCDR0) >> 16) & 0x3f);
 }
 
-static unsigned long get_rate_ssi2(struct clk *clk)
+static unsigned long get_rate_ssi2(struct clk_mxc *clk_mxc)
 {
-	return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 26) & 0x3f);
+	return get_rate_ssix(clk_mxc, (__raw_readl(CCM_PCDR0) >> 26) & 0x3f);
 }
 
-static unsigned long get_rate_nfc(struct clk *clk)
+static unsigned long get_rate_nfc(struct clk_mxc *clk_mxc)
 {
 	unsigned long nfc_pdf;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
 		nfc_pdf = (__raw_readl(CCM_PCDR0) >> 6) & 0xf;
@@ -277,12 +277,12 @@ static unsigned long get_rate_nfc(struct clk *clk)
 	return parent_rate / (nfc_pdf + 1);
 }
 
-static unsigned long get_rate_vpu(struct clk *clk)
+static unsigned long get_rate_vpu(struct clk_mxc *clk_mxc)
 {
 	unsigned long vpu_pdf;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
 		vpu_pdf = (__raw_readl(CCM_PCDR0) >> 10) & 0x3f;
@@ -295,25 +295,25 @@ static unsigned long get_rate_vpu(struct clk *clk)
 	return 2UL * parent_rate / vpu_pdf;
 }
 
-static unsigned long round_rate_parent(struct clk *clk, unsigned long rate)
+static unsigned long round_rate_parent(struct clk_mxc *clk_mxc, unsigned long rate)
 {
-	return clk->parent->round_rate(clk->parent, rate);
+	return clk_round_rate(&clk_mxc->parent->clk, rate);
 }
 
-static unsigned long get_rate_parent(struct clk *clk)
+static unsigned long get_rate_parent(struct clk_mxc *clk_mxc)
 {
-	return clk_get_rate(clk->parent);
+	return clk_get_rate(&clk_mxc->parent->clk);
 }
 
-static int set_rate_parent(struct clk *clk, unsigned long rate)
+static int set_rate_parent(struct clk_mxc *clk_mxc, unsigned long rate)
 {
-	return clk->parent->set_rate(clk->parent, rate);
+	return clk_set_rate(&clk_mxc->parent->clk, rate);
 }
 
 /* in Hz */
 static unsigned long external_high_reference = 26000000;
 
-static unsigned long get_rate_high_reference(struct clk *clk)
+static unsigned long get_rate_high_reference(struct clk_mxc *clk)
 {
 	return external_high_reference;
 }
@@ -321,44 +321,44 @@ static unsigned long get_rate_high_reference(struct clk *clk)
 /* in Hz */
 static unsigned long external_low_reference = 32768;
 
-static unsigned long get_rate_low_reference(struct clk *clk)
+static unsigned long get_rate_low_reference(struct clk_mxc *clk_mxc)
 {
 	return external_low_reference;
 }
 
-static unsigned long get_rate_fpm(struct clk *clk)
+static unsigned long get_rate_fpm(struct clk_mxc *clk_mxc)
 {
-	return clk_get_rate(clk->parent) * 1024;
+	return clk_get_rate(&clk_mxc->parent->clk) * 1024;
 }
 
-static unsigned long get_rate_mpll(struct clk *clk)
+static unsigned long get_rate_mpll(struct clk_mxc *clk_mxc)
 {
 	return mxc_decode_pll(__raw_readl(CCM_MPCTL0),
-			clk_get_rate(clk->parent));
+			clk_get_rate(&clk_mxc->parent->clk));
 }
 
-static unsigned long get_rate_mpll_main(struct clk *clk)
+static unsigned long get_rate_mpll_main(struct clk_mxc *clk_mxc)
 {
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	/* i.MX27 TO2:
 	 * clk->id = 0: arm clock source path 1 which is from 2 * MPLL / 2
 	 * clk->id = 1: arm clock source path 2 which is from 2 * MPLL / 3
 	 */
-	if (mx27_revision() >= IMX_CHIP_REVISION_2_0 && clk->id = 1)
+	if (mx27_revision() >= IMX_CHIP_REVISION_2_0 && clk_mxc->id = 1)
 		return 2UL * parent_rate / 3UL;
 
 	return parent_rate;
 }
 
-static unsigned long get_rate_spll(struct clk *clk)
+static unsigned long get_rate_spll(struct clk_mxc *clk_mxc)
 {
 	uint32_t reg;
 	unsigned long rate;
 
-	rate = clk_get_rate(clk->parent);
+	rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	reg = __raw_readl(CCM_SPCTL0);
 
@@ -371,7 +371,7 @@ static unsigned long get_rate_spll(struct clk *clk)
 	return mxc_decode_pll(reg, rate);
 }
 
-static unsigned long get_rate_cpu(struct clk *clk)
+static unsigned long get_rate_cpu(struct clk_mxc *clk_mxc)
 {
 	u32 div;
 	unsigned long rate;
@@ -381,11 +381,11 @@ static unsigned long get_rate_cpu(struct clk *clk)
 	else
 		div = (__raw_readl(CCM_CSCR) >> 13) & 0x7;
 
-	rate = clk_get_rate(clk->parent);
+	rate = clk_get_rate(&clk_mxc->parent->clk);
 	return rate / (div + 1);
 }
 
-static unsigned long get_rate_ahb(struct clk *clk)
+static unsigned long get_rate_ahb(struct clk_mxc *clk_mxc)
 {
 	unsigned long rate, bclk_pdf;
 
@@ -394,33 +394,33 @@ static unsigned long get_rate_ahb(struct clk *clk)
 	else
 		bclk_pdf = (__raw_readl(CCM_CSCR) >> 9) & 0xf;
 
-	rate = clk_get_rate(clk->parent);
+	rate = clk_get_rate(&clk_mxc->parent->clk);
 	return rate / (bclk_pdf + 1);
 }
 
-static unsigned long get_rate_ipg(struct clk *clk)
+static unsigned long get_rate_ipg(struct clk_mxc *clk_mxc)
 {
 	unsigned long rate, ipg_pdf;
 
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
-		return clk_get_rate(clk->parent);
+		return clk_get_rate(&clk_mxc->parent->clk);
 	else
 		ipg_pdf = (__raw_readl(CCM_CSCR) >> 8) & 1;
 
-	rate = clk_get_rate(clk->parent);
+	rate = clk_get_rate(&clk_mxc->parent->clk);
 	return rate / (ipg_pdf + 1);
 }
 
-static unsigned long get_rate_per(struct clk *clk)
+static unsigned long get_rate_per(struct clk_mxc *clk_mxc)
 {
 	unsigned long perclk_pdf, parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
-	if (clk->id < 0 || clk->id > 3)
+	if (clk_mxc->id < 0 || clk_mxc->id > 3)
 		return 0;
 
-	perclk_pdf = (__raw_readl(CCM_PCDR1) >> (clk->id << 3)) & 0x3f;
+	perclk_pdf = (__raw_readl(CCM_PCDR1) >> (clk_mxc->id << 3)) & 0x3f;
 
 	return parent_rate / (perclk_pdf + 1);
 }
@@ -430,11 +430,13 @@ static unsigned long get_rate_per(struct clk *clk)
  * Default case is 26MHz. Could be changed at runtime
  * with a call to change_external_high_reference()
  */
-static struct clk ckih_clk = {
+static struct clk_mxc ckih_clk = {
+	.clk = INIT_CLK_MXC(ckih_clk),
 	.get_rate	= get_rate_high_reference,
 };
 
-static struct clk mpll_clk = {
+static struct clk_mxc mpll_clk = {
+	.clk = INIT_CLK_MXC(mpll_clk),
 	.parent		= &ckih_clk,
 	.get_rate	= get_rate_mpll,
 };
@@ -442,7 +444,8 @@ static struct clk mpll_clk = {
 /* For i.MX27 TO2, it is the MPLL path 1 of ARM core
  * It provides the clock source whose rate is same as MPLL
  */
-static struct clk mpll_main1_clk = {
+static struct clk_mxc mpll_main1_clk = {
+	.clk = INIT_CLK_MXC(mpll_main1_clk),
 	.id		= 0,
 	.parent		= &mpll_clk,
 	.get_rate	= get_rate_mpll_main,
@@ -451,23 +454,27 @@ static struct clk mpll_main1_clk = {
 /* For i.MX27 TO2, it is the MPLL path 2 of ARM core
  * It provides the clock source whose rate is same MPLL * 2 / 3
  */
-static struct clk mpll_main2_clk = {
+static struct clk_mxc mpll_main2_clk = {
+	.clk = INIT_CLK_MXC(mpll_main2_clk),
 	.id		= 1,
 	.parent		= &mpll_clk,
 	.get_rate	= get_rate_mpll_main,
 };
 
-static struct clk ahb_clk = {
+static struct clk_mxc ahb_clk = {
+	.clk = INIT_CLK_MXC(ahb_clk),
 	.parent		= &mpll_main2_clk,
 	.get_rate	= get_rate_ahb,
 };
 
-static struct clk ipg_clk = {
+static struct clk_mxc ipg_clk = {
+	.clk = INIT_CLK_MXC(ipg_clk),
 	.parent		= &ahb_clk,
 	.get_rate	= get_rate_ipg,
 };
 
-static struct clk cpu_clk = {
+static struct clk_mxc cpu_clk = {
+	.clk = INIT_CLK_MXC(cpu_clk),
 	.parent = &mpll_main2_clk,
 	.set_parent = clk_cpu_set_parent,
 	.round_rate = round_rate_cpu,
@@ -475,7 +482,8 @@ static struct clk cpu_clk = {
 	.set_rate = set_rate_cpu,
 };
 
-static struct clk spll_clk = {
+static struct clk_mxc spll_clk = {
+	.clk = INIT_CLK_MXC(spll_clk),
 	.parent = &ckih_clk,
 	.get_rate = get_rate_spll,
 	.enable = clk_spll_enable,
@@ -486,12 +494,14 @@ static struct clk spll_clk = {
  * the low frequency external clock reference
  * Default case is 32.768kHz.
  */
-static struct clk ckil_clk = {
+static struct clk_mxc ckil_clk = {
+	.clk = INIT_CLK_MXC(ckil_clk),
 	.get_rate = get_rate_low_reference,
 };
 
 /* Output of frequency pre multiplier */
-static struct clk fpm_clk = {
+static struct clk_mxc fpm_clk = {
+	.clk = INIT_CLK_MXC(fpm_clk),
 	.parent = &ckil_clk,
 	.get_rate = get_rate_fpm,
 };
@@ -500,7 +510,8 @@ static struct clk fpm_clk = {
 #define PCCR1 CCM_PCCR1
 
 #define DEFINE_CLOCK(name, i, er, es, gr, s, p)		\
-	static struct clk name = {			\
+	static struct clk_mxc name = {			\
+		.clk = INIT_CLK_MXC(name),		\
 		.id		= i,			\
 		.enable_reg	= er,			\
 		.enable_shift	= es,			\
@@ -512,7 +523,8 @@ static struct clk fpm_clk = {
 	}
 
 #define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p)	\
-	static struct clk name = {				\
+	static struct clk_mxc name = {				\
+		.clk = INIT_CLK_MXC(name),			\
 		.id		= i,				\
 		.enable_reg	= er,				\
 		.enable_shift	= es,				\
@@ -526,7 +538,7 @@ static struct clk fpm_clk = {
 	}
 
 /* Forward declaration to keep the following list in order */
-static struct clk slcdc_clk1, sahara2_clk1, rtic_clk1, fec_clk1, emma_clk1,
+static struct clk_mxc slcdc_clk1, sahara2_clk1, rtic_clk1, fec_clk1, emma_clk1,
 		  dma_clk1, lcdc_clk2, vpu_clk1;
 
 /* All clocks we can gate through PCCRx in the order of PCCRx bits */
@@ -620,7 +632,7 @@ DEFINE_CLOCK1(csi_clk,     0, NULL,   0, parent, &csi_clk1, &per4_clk);
 	{ \
 		.dev_id = d, \
 		.con_id = n, \
-		.clk = &c, \
+		.clk = &c.clk, \
 	},
 
 static struct clk_lookup lookups[] = {
@@ -746,16 +758,16 @@ int __init mx27_clocks_init(unsigned long fref)
 	spll_clk.disable(&spll_clk);
 
 	/* enable basic clocks */
-	clk_enable(&per1_clk);
-	clk_enable(&gpio_clk);
-	clk_enable(&emi_clk);
-	clk_enable(&iim_clk);
+	clk_enable(&per1_clk.clk);
+	clk_enable(&gpio_clk.clk);
+	clk_enable(&emi_clk.clk);
+	clk_enable(&iim_clk.clk);
 
 #if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
-	clk_enable(&uart1_clk);
+	clk_enable(&uart1_clk.clk);
 #endif
 
-	mxc_timer_init(&gpt1_clk, MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR),
+	mxc_timer_init(&gpt1_clk.clk, MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR),
 			MX27_INT_GPT1);
 
 	return 0;
diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c
index 2ed3ab1..3fc75dd 100644
--- a/arch/arm/plat-mxc/clock.c
+++ b/arch/arm/plat-mxc/clock.c
@@ -44,6 +44,131 @@
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+static int clk_mxc_enable(struct clk *clk)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+	int ret = 0;
+
+	if (clk_mxc->parent)
+		ret = clk_enable(&clk_mxc->parent->clk);
+
+	if (!ret && clk_mxc->secondary)
+		ret = clk_enable(&clk_mxc->secondary->clk);
+
+	if (!ret && clk_mxc->enable)
+		ret = clk_mxc->enable(clk_mxc);
+
+	return ret;
+}
+
+static void clk_mxc_disable(struct clk *clk)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+
+	if (clk_mxc->disable)
+		clk_mxc->disable(clk_mxc);
+
+	if (clk_mxc->secondary)
+		clk_disable(&clk_mxc->secondary->clk);
+
+	if (clk_mxc->parent)
+		clk_disable(&clk_mxc->parent->clk);
+}
+
+static unsigned long clk_mxc_get_rate(struct clk *clk)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+
+	if (clk_mxc->get_rate)
+		return clk_mxc->get_rate(clk_mxc);
+	else if (clk_mxc->parent)
+		return clk_get_rate(&clk_mxc->parent->clk);
+	else
+		return 0UL;
+}
+
+static long clk_mxc_round_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+
+	if (clk_mxc->round_rate)
+		return clk_mxc->round_rate(clk_mxc, rate);
+
+	return 0L;
+}
+
+static int clk_mxc_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+	int ret = -EINVAL;
+
+	if (clk_mxc->set_rate && rate != 0)
+		ret = clk_mxc->set_rate(clk_mxc, rate);
+
+	return ret;
+}
+
+static int clk_mxc_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+	struct clk *old_parent = parent;
+	struct clk_mxc *parent_mxc = to_clk_mxc(parent);
+	int ret;
+
+	if (!clk_mxc->set_parent)
+		return -EINVAL;
+
+	if (clk->prepare_count) {
+		ret = clk_prepare(parent);
+		if (ret)
+			goto err_prepare_parent;
+	}
+
+	if (clk->enable_count) {
+		ret = clk_enable(parent);
+		if (ret)
+			goto err_enable_parent;
+	}
+
+	ret = clk_mxc->set_parent(clk_mxc, parent_mxc);
+	if (ret = 0) {
+		old_parent = &clk_mxc->parent->clk;
+		clk_mxc->parent = to_clk_mxc(parent);
+	}
+
+	if (clk->enable_count)
+		clk_disable(old_parent);
+err_enable_parent:
+
+	if (clk->prepare_count)
+		clk_unprepare(old_parent);
+err_prepare_parent:
+
+	return ret;
+}
+
+static struct clk *clk_mxc_get_parent(struct clk *clk)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+
+	if (clk_mxc->parent)
+		return &clk_mxc->parent->clk;
+
+	return NULL;
+}
+
+const struct clk_ops clk_mxc_ops = {
+	.enable = clk_mxc_enable,
+	.disable = clk_mxc_disable,
+	.get_rate = clk_mxc_get_rate,
+	.round_rate = clk_mxc_round_rate,
+	.set_rate = clk_mxc_set_rate,
+	.set_parent = clk_mxc_set_parent,
+	.get_parent = clk_mxc_get_parent,
+};
+#else
+
 /*-------------------------------------------------------------------------
  * Standard clock functions defined in include/linux/clk.h
  *-------------------------------------------------------------------------*/
@@ -200,6 +325,8 @@ struct clk *clk_get_parent(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_get_parent);
 
+#endif
+
 /*
  * Get the resulting clock rate from a PLL register value and the input
  * frequency. PLLs with this register layout can at least be found on
diff --git a/arch/arm/plat-mxc/include/mach/clkdev.h b/arch/arm/plat-mxc/include/mach/clkdev.h
index 04b37a8..f663af3 100644
--- a/arch/arm/plat-mxc/include/mach/clkdev.h
+++ b/arch/arm/plat-mxc/include/mach/clkdev.h
@@ -1,7 +1,11 @@
 #ifndef __ASM_MACH_CLKDEV_H
 #define __ASM_MACH_CLKDEV_H
 
+#ifndef CONFIG_USE_COMMON_STRUCT_CLK
+
 #define __clk_get(clk) ({ 1; })
 #define __clk_put(clk) do { } while (0)
 
 #endif
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/clock.h b/arch/arm/plat-mxc/include/mach/clock.h
index 753a598..d8efa77 100644
--- a/arch/arm/plat-mxc/include/mach/clock.h
+++ b/arch/arm/plat-mxc/include/mach/clock.h
@@ -23,14 +23,24 @@
 #ifndef __ASSEMBLY__
 #include <linux/list.h>
 
+#include <linux/clk.h>
+
 struct module;
 
-struct clk {
+#ifndef CONFIG_USE_COMMON_STRUCT_CLK
+#define clk_mxc clk
+#endif
+
+struct clk_mxc {
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+	struct clk clk;
+#endif
+
 	int id;
 	/* Source clock this clk depends on */
-	struct clk *parent;
+	struct clk_mxc *parent;
 	/* Secondary clock to enable/disable with this clock */
-	struct clk *secondary;
+	struct clk_mxc *secondary;
 	/* Reference count of clock enable/disable */
 	__s8 usecount;
 	/* Register bit position for clock's enable/disable control. */
@@ -39,23 +49,27 @@ struct clk {
 	void __iomem *enable_reg;
 	u32 flags;
 	/* get the current clock rate (always a fresh value) */
-	unsigned long (*get_rate) (struct clk *);
+	unsigned long (*get_rate) (struct clk_mxc *);
 	/* Function ptr to set the clock to a new rate. The rate must match a
 	   supported rate returned from round_rate. Leave blank if clock is not
 	   programmable */
-	int (*set_rate) (struct clk *, unsigned long);
+	int (*set_rate) (struct clk_mxc *, unsigned long);
 	/* Function ptr to round the requested clock rate to the nearest
 	   supported rate that is less than or equal to the requested rate. */
-	unsigned long (*round_rate) (struct clk *, unsigned long);
+	unsigned long (*round_rate) (struct clk_mxc *, unsigned long);
 	/* Function ptr to enable the clock. Leave blank if clock can not
 	   be gated. */
-	int (*enable) (struct clk *);
+	int (*enable) (struct clk_mxc *);
 	/* Function ptr to disable the clock. Leave blank if clock can not
 	   be gated. */
-	void (*disable) (struct clk *);
+	void (*disable) (struct clk_mxc *);
 	/* Function ptr to set the parent clock of the clock. */
-	int (*set_parent) (struct clk *, struct clk *);
+	int (*set_parent) (struct clk_mxc *, struct clk_mxc *);
 };
+#define to_clk_mxc(_clk_mxc)        container_of(_clk_mxc, struct clk_mxc, clk)
+
+extern const struct clk_ops clk_mxc_ops;
+#define INIT_CLK_MXC(name)	INIT_CLK(name.clk, clk_mxc_ops)
 
 int clk_register(struct clk *clk);
 void clk_unregister(struct clk *clk);
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0da0bb9..fbafcb6 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -47,7 +47,7 @@ int clk_enable(struct clk *clk)
 	unsigned long flags;
 	int ret = 0;
 
-	WARN_ON(clk->prepare_count = 0);
+	WARN_ON_ONCE(clk->prepare_count = 0);
 
 	spin_lock_irqsave(&clk->enable_lock, flags);
 	if (clk->enable_count = 0 && clk->ops->enable)
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [PATCH] wip: convert imx27 to common struct clk
@ 2011-02-22 23:33     ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-22 23:33 UTC (permalink / raw)
  To: Jeremy Kerr, linux-kernel, linux-arm-kernel
  Cc: Nicolas Pitre, Lorenzo Pieralisi, Vincent Guittot, linux-sh,
	Ben Herrenschmidt, Sascha Hauer, Paul Mundt, Dima Zavin,
	Saravana Kannan, Ben Dooks, Russell King

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
Hello,

on top of .38-rc6 + making the clk_{un,}prepare stubs static inline,
this patch makes use of Jeremy's common struct clk (v13) on a i.MX27 based
machine.

This is compile tested using mx21_defconfig and runtime tested using
mx27_defconfig.

I had to degrade one WARN_ON to WARN_ON_ONCE in drivers/clk/clk.c to
actually make it work.  Otherwise console output results in a warning
that results in console output ...

Best regards
Uwe

 arch/arm/mach-imx/Kconfig               |    1 +
 arch/arm/mach-imx/clock-imx27.c         |  186 ++++++++++++++++--------------
 arch/arm/plat-mxc/clock.c               |  127 +++++++++++++++++++++
 arch/arm/plat-mxc/include/mach/clkdev.h |    4 +
 arch/arm/plat-mxc/include/mach/clock.h  |   32 ++++--
 drivers/clk/clk.c                       |    2 +-
 6 files changed, 255 insertions(+), 97 deletions(-)

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 56684b5..f2d3708 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -30,6 +30,7 @@ config SOC_IMX27
 	select IMX_HAVE_DMA_V1
 	select IMX_HAVE_IOMUX_V1
 	select MXC_AVIC
+	select USE_COMMON_STRUCT_CLK
 
 if ARCH_MX1
 
diff --git a/arch/arm/mach-imx/clock-imx27.c b/arch/arm/mach-imx/clock-imx27.c
index 583f251..f413f7b 100644
--- a/arch/arm/mach-imx/clock-imx27.c
+++ b/arch/arm/mach-imx/clock-imx27.c
@@ -68,35 +68,35 @@
 #define CCM_SPCTL1_LF           (1 << 15)
 #define CCM_SPCTL1_BRMO         (1 << 6)
 
-static struct clk mpll_main1_clk, mpll_main2_clk;
+static struct clk_mxc mpll_main1_clk, mpll_main2_clk;
 
-static int clk_pccr_enable(struct clk *clk)
+static int clk_pccr_enable(struct clk_mxc *clk_mxc)
 {
 	unsigned long reg;
 
-	if (!clk->enable_reg)
+	if (!clk_mxc->enable_reg)
 		return 0;
 
-	reg = __raw_readl(clk->enable_reg);
-	reg |= 1 << clk->enable_shift;
-	__raw_writel(reg, clk->enable_reg);
+	reg = __raw_readl(clk_mxc->enable_reg);
+	reg |= 1 << clk_mxc->enable_shift;
+	__raw_writel(reg, clk_mxc->enable_reg);
 
 	return 0;
 }
 
-static void clk_pccr_disable(struct clk *clk)
+static void clk_pccr_disable(struct clk_mxc *clk_mxc)
 {
 	unsigned long reg;
 
-	if (!clk->enable_reg)
+	if (!clk_mxc->enable_reg)
 		return;
 
-	reg = __raw_readl(clk->enable_reg);
-	reg &= ~(1 << clk->enable_shift);
-	__raw_writel(reg, clk->enable_reg);
+	reg = __raw_readl(clk_mxc->enable_reg);
+	reg &= ~(1 << clk_mxc->enable_shift);
+	__raw_writel(reg, clk_mxc->enable_reg);
 }
 
-static int clk_spll_enable(struct clk *clk)
+static int clk_spll_enable(struct clk_mxc *clk_mxc)
 {
 	unsigned long reg;
 
@@ -109,7 +109,7 @@ static int clk_spll_enable(struct clk *clk)
 	return 0;
 }
 
-static void clk_spll_disable(struct clk *clk)
+static void clk_spll_disable(struct clk_mxc *clk_mxc)
 {
 	unsigned long reg;
 
@@ -118,11 +118,11 @@ static void clk_spll_disable(struct clk *clk)
 	__raw_writel(reg, CCM_CSCR);
 }
 
-static int clk_cpu_set_parent(struct clk *clk, struct clk *parent)
+static int clk_cpu_set_parent(struct clk_mxc *clk_mxc, struct clk_mxc *parent)
 {
 	int cscr = __raw_readl(CCM_CSCR);
 
-	if (clk->parent == parent)
+	if (clk_mxc->parent == parent)
 		return 0;
 
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
@@ -135,18 +135,18 @@ static int clk_cpu_set_parent(struct clk *clk, struct clk *parent)
 				return -EINVAL;
 		}
 		__raw_writel(cscr, CCM_CSCR);
-		clk->parent = parent;
+		clk_mxc->parent = parent;
 		return 0;
 	}
 	return -ENODEV;
 }
 
-static unsigned long round_rate_cpu(struct clk *clk, unsigned long rate)
+static unsigned long round_rate_cpu(struct clk_mxc *clk_mxc, unsigned long rate)
 {
 	int div;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	div = parent_rate / rate;
 	if (parent_rate % rate)
@@ -158,13 +158,13 @@ static unsigned long round_rate_cpu(struct clk *clk, unsigned long rate)
 	return parent_rate / div;
 }
 
-static int set_rate_cpu(struct clk *clk, unsigned long rate)
+static int set_rate_cpu(struct clk_mxc *clk_mxc, unsigned long rate)
 {
 	unsigned int div;
 	uint32_t reg;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	div = parent_rate / rate;
 
@@ -186,12 +186,12 @@ static int set_rate_cpu(struct clk *clk, unsigned long rate)
 	return 0;
 }
 
-static unsigned long round_rate_per(struct clk *clk, unsigned long rate)
+static unsigned long round_rate_per(struct clk_mxc *clk_mxc, unsigned long rate)
 {
 	u32 div;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	div = parent_rate / rate;
 	if (parent_rate % rate)
@@ -203,15 +203,15 @@ static unsigned long round_rate_per(struct clk *clk, unsigned long rate)
 	return parent_rate / div;
 }
 
-static int set_rate_per(struct clk *clk, unsigned long rate)
+static int set_rate_per(struct clk_mxc *clk_mxc, unsigned long rate)
 {
 	u32 reg;
 	u32 div;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
-	if (clk->id < 0 || clk->id > 3)
+	if (clk_mxc->id < 0 || clk_mxc->id > 3)
 		return -EINVAL;
 
 	div = parent_rate / rate;
@@ -219,30 +219,30 @@ static int set_rate_per(struct clk *clk, unsigned long rate)
 		return -EINVAL;
 	div--;
 
-	reg = __raw_readl(CCM_PCDR1) & ~(0x3f << (clk->id << 3));
-	reg |= div << (clk->id << 3);
+	reg = __raw_readl(CCM_PCDR1) & ~(0x3f << (clk_mxc->id << 3));
+	reg |= div << (clk_mxc->id << 3);
 	__raw_writel(reg, CCM_PCDR1);
 
 	return 0;
 }
 
-static unsigned long get_rate_usb(struct clk *clk)
+static unsigned long get_rate_usb(struct clk_mxc *clk_mxc)
 {
 	unsigned long usb_pdf;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	usb_pdf = (__raw_readl(CCM_CSCR) >> 28) & 0x7;
 
 	return parent_rate / (usb_pdf + 1U);
 }
 
-static unsigned long get_rate_ssix(struct clk *clk, unsigned long pdf)
+static unsigned long get_rate_ssix(struct clk_mxc *clk_mxc, unsigned long pdf)
 {
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
 		pdf += 4;  /* MX27 TO2+ */
@@ -252,22 +252,22 @@ static unsigned long get_rate_ssix(struct clk *clk, unsigned long pdf)
 	return 2UL * parent_rate / pdf;
 }
 
-static unsigned long get_rate_ssi1(struct clk *clk)
+static unsigned long get_rate_ssi1(struct clk_mxc *clk_mxc)
 {
-	return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 16) & 0x3f);
+	return get_rate_ssix(clk_mxc, (__raw_readl(CCM_PCDR0) >> 16) & 0x3f);
 }
 
-static unsigned long get_rate_ssi2(struct clk *clk)
+static unsigned long get_rate_ssi2(struct clk_mxc *clk_mxc)
 {
-	return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 26) & 0x3f);
+	return get_rate_ssix(clk_mxc, (__raw_readl(CCM_PCDR0) >> 26) & 0x3f);
 }
 
-static unsigned long get_rate_nfc(struct clk *clk)
+static unsigned long get_rate_nfc(struct clk_mxc *clk_mxc)
 {
 	unsigned long nfc_pdf;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
 		nfc_pdf = (__raw_readl(CCM_PCDR0) >> 6) & 0xf;
@@ -277,12 +277,12 @@ static unsigned long get_rate_nfc(struct clk *clk)
 	return parent_rate / (nfc_pdf + 1);
 }
 
-static unsigned long get_rate_vpu(struct clk *clk)
+static unsigned long get_rate_vpu(struct clk_mxc *clk_mxc)
 {
 	unsigned long vpu_pdf;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
 		vpu_pdf = (__raw_readl(CCM_PCDR0) >> 10) & 0x3f;
@@ -295,25 +295,25 @@ static unsigned long get_rate_vpu(struct clk *clk)
 	return 2UL * parent_rate / vpu_pdf;
 }
 
-static unsigned long round_rate_parent(struct clk *clk, unsigned long rate)
+static unsigned long round_rate_parent(struct clk_mxc *clk_mxc, unsigned long rate)
 {
-	return clk->parent->round_rate(clk->parent, rate);
+	return clk_round_rate(&clk_mxc->parent->clk, rate);
 }
 
-static unsigned long get_rate_parent(struct clk *clk)
+static unsigned long get_rate_parent(struct clk_mxc *clk_mxc)
 {
-	return clk_get_rate(clk->parent);
+	return clk_get_rate(&clk_mxc->parent->clk);
 }
 
-static int set_rate_parent(struct clk *clk, unsigned long rate)
+static int set_rate_parent(struct clk_mxc *clk_mxc, unsigned long rate)
 {
-	return clk->parent->set_rate(clk->parent, rate);
+	return clk_set_rate(&clk_mxc->parent->clk, rate);
 }
 
 /* in Hz */
 static unsigned long external_high_reference = 26000000;
 
-static unsigned long get_rate_high_reference(struct clk *clk)
+static unsigned long get_rate_high_reference(struct clk_mxc *clk)
 {
 	return external_high_reference;
 }
@@ -321,44 +321,44 @@ static unsigned long get_rate_high_reference(struct clk *clk)
 /* in Hz */
 static unsigned long external_low_reference = 32768;
 
-static unsigned long get_rate_low_reference(struct clk *clk)
+static unsigned long get_rate_low_reference(struct clk_mxc *clk_mxc)
 {
 	return external_low_reference;
 }
 
-static unsigned long get_rate_fpm(struct clk *clk)
+static unsigned long get_rate_fpm(struct clk_mxc *clk_mxc)
 {
-	return clk_get_rate(clk->parent) * 1024;
+	return clk_get_rate(&clk_mxc->parent->clk) * 1024;
 }
 
-static unsigned long get_rate_mpll(struct clk *clk)
+static unsigned long get_rate_mpll(struct clk_mxc *clk_mxc)
 {
 	return mxc_decode_pll(__raw_readl(CCM_MPCTL0),
-			clk_get_rate(clk->parent));
+			clk_get_rate(&clk_mxc->parent->clk));
 }
 
-static unsigned long get_rate_mpll_main(struct clk *clk)
+static unsigned long get_rate_mpll_main(struct clk_mxc *clk_mxc)
 {
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	/* i.MX27 TO2:
 	 * clk->id == 0: arm clock source path 1 which is from 2 * MPLL / 2
 	 * clk->id == 1: arm clock source path 2 which is from 2 * MPLL / 3
 	 */
-	if (mx27_revision() >= IMX_CHIP_REVISION_2_0 && clk->id == 1)
+	if (mx27_revision() >= IMX_CHIP_REVISION_2_0 && clk_mxc->id == 1)
 		return 2UL * parent_rate / 3UL;
 
 	return parent_rate;
 }
 
-static unsigned long get_rate_spll(struct clk *clk)
+static unsigned long get_rate_spll(struct clk_mxc *clk_mxc)
 {
 	uint32_t reg;
 	unsigned long rate;
 
-	rate = clk_get_rate(clk->parent);
+	rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	reg = __raw_readl(CCM_SPCTL0);
 
@@ -371,7 +371,7 @@ static unsigned long get_rate_spll(struct clk *clk)
 	return mxc_decode_pll(reg, rate);
 }
 
-static unsigned long get_rate_cpu(struct clk *clk)
+static unsigned long get_rate_cpu(struct clk_mxc *clk_mxc)
 {
 	u32 div;
 	unsigned long rate;
@@ -381,11 +381,11 @@ static unsigned long get_rate_cpu(struct clk *clk)
 	else
 		div = (__raw_readl(CCM_CSCR) >> 13) & 0x7;
 
-	rate = clk_get_rate(clk->parent);
+	rate = clk_get_rate(&clk_mxc->parent->clk);
 	return rate / (div + 1);
 }
 
-static unsigned long get_rate_ahb(struct clk *clk)
+static unsigned long get_rate_ahb(struct clk_mxc *clk_mxc)
 {
 	unsigned long rate, bclk_pdf;
 
@@ -394,33 +394,33 @@ static unsigned long get_rate_ahb(struct clk *clk)
 	else
 		bclk_pdf = (__raw_readl(CCM_CSCR) >> 9) & 0xf;
 
-	rate = clk_get_rate(clk->parent);
+	rate = clk_get_rate(&clk_mxc->parent->clk);
 	return rate / (bclk_pdf + 1);
 }
 
-static unsigned long get_rate_ipg(struct clk *clk)
+static unsigned long get_rate_ipg(struct clk_mxc *clk_mxc)
 {
 	unsigned long rate, ipg_pdf;
 
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
-		return clk_get_rate(clk->parent);
+		return clk_get_rate(&clk_mxc->parent->clk);
 	else
 		ipg_pdf = (__raw_readl(CCM_CSCR) >> 8) & 1;
 
-	rate = clk_get_rate(clk->parent);
+	rate = clk_get_rate(&clk_mxc->parent->clk);
 	return rate / (ipg_pdf + 1);
 }
 
-static unsigned long get_rate_per(struct clk *clk)
+static unsigned long get_rate_per(struct clk_mxc *clk_mxc)
 {
 	unsigned long perclk_pdf, parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
-	if (clk->id < 0 || clk->id > 3)
+	if (clk_mxc->id < 0 || clk_mxc->id > 3)
 		return 0;
 
-	perclk_pdf = (__raw_readl(CCM_PCDR1) >> (clk->id << 3)) & 0x3f;
+	perclk_pdf = (__raw_readl(CCM_PCDR1) >> (clk_mxc->id << 3)) & 0x3f;
 
 	return parent_rate / (perclk_pdf + 1);
 }
@@ -430,11 +430,13 @@ static unsigned long get_rate_per(struct clk *clk)
  * Default case is 26MHz. Could be changed at runtime
  * with a call to change_external_high_reference()
  */
-static struct clk ckih_clk = {
+static struct clk_mxc ckih_clk = {
+	.clk = INIT_CLK_MXC(ckih_clk),
 	.get_rate	= get_rate_high_reference,
 };
 
-static struct clk mpll_clk = {
+static struct clk_mxc mpll_clk = {
+	.clk = INIT_CLK_MXC(mpll_clk),
 	.parent		= &ckih_clk,
 	.get_rate	= get_rate_mpll,
 };
@@ -442,7 +444,8 @@ static struct clk mpll_clk = {
 /* For i.MX27 TO2, it is the MPLL path 1 of ARM core
  * It provides the clock source whose rate is same as MPLL
  */
-static struct clk mpll_main1_clk = {
+static struct clk_mxc mpll_main1_clk = {
+	.clk = INIT_CLK_MXC(mpll_main1_clk),
 	.id		= 0,
 	.parent		= &mpll_clk,
 	.get_rate	= get_rate_mpll_main,
@@ -451,23 +454,27 @@ static struct clk mpll_main1_clk = {
 /* For i.MX27 TO2, it is the MPLL path 2 of ARM core
  * It provides the clock source whose rate is same MPLL * 2 / 3
  */
-static struct clk mpll_main2_clk = {
+static struct clk_mxc mpll_main2_clk = {
+	.clk = INIT_CLK_MXC(mpll_main2_clk),
 	.id		= 1,
 	.parent		= &mpll_clk,
 	.get_rate	= get_rate_mpll_main,
 };
 
-static struct clk ahb_clk = {
+static struct clk_mxc ahb_clk = {
+	.clk = INIT_CLK_MXC(ahb_clk),
 	.parent		= &mpll_main2_clk,
 	.get_rate	= get_rate_ahb,
 };
 
-static struct clk ipg_clk = {
+static struct clk_mxc ipg_clk = {
+	.clk = INIT_CLK_MXC(ipg_clk),
 	.parent		= &ahb_clk,
 	.get_rate	= get_rate_ipg,
 };
 
-static struct clk cpu_clk = {
+static struct clk_mxc cpu_clk = {
+	.clk = INIT_CLK_MXC(cpu_clk),
 	.parent = &mpll_main2_clk,
 	.set_parent = clk_cpu_set_parent,
 	.round_rate = round_rate_cpu,
@@ -475,7 +482,8 @@ static struct clk cpu_clk = {
 	.set_rate = set_rate_cpu,
 };
 
-static struct clk spll_clk = {
+static struct clk_mxc spll_clk = {
+	.clk = INIT_CLK_MXC(spll_clk),
 	.parent = &ckih_clk,
 	.get_rate = get_rate_spll,
 	.enable = clk_spll_enable,
@@ -486,12 +494,14 @@ static struct clk spll_clk = {
  * the low frequency external clock reference
  * Default case is 32.768kHz.
  */
-static struct clk ckil_clk = {
+static struct clk_mxc ckil_clk = {
+	.clk = INIT_CLK_MXC(ckil_clk),
 	.get_rate = get_rate_low_reference,
 };
 
 /* Output of frequency pre multiplier */
-static struct clk fpm_clk = {
+static struct clk_mxc fpm_clk = {
+	.clk = INIT_CLK_MXC(fpm_clk),
 	.parent = &ckil_clk,
 	.get_rate = get_rate_fpm,
 };
@@ -500,7 +510,8 @@ static struct clk fpm_clk = {
 #define PCCR1 CCM_PCCR1
 
 #define DEFINE_CLOCK(name, i, er, es, gr, s, p)		\
-	static struct clk name = {			\
+	static struct clk_mxc name = {			\
+		.clk = INIT_CLK_MXC(name),		\
 		.id		= i,			\
 		.enable_reg	= er,			\
 		.enable_shift	= es,			\
@@ -512,7 +523,8 @@ static struct clk fpm_clk = {
 	}
 
 #define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p)	\
-	static struct clk name = {				\
+	static struct clk_mxc name = {				\
+		.clk = INIT_CLK_MXC(name),			\
 		.id		= i,				\
 		.enable_reg	= er,				\
 		.enable_shift	= es,				\
@@ -526,7 +538,7 @@ static struct clk fpm_clk = {
 	}
 
 /* Forward declaration to keep the following list in order */
-static struct clk slcdc_clk1, sahara2_clk1, rtic_clk1, fec_clk1, emma_clk1,
+static struct clk_mxc slcdc_clk1, sahara2_clk1, rtic_clk1, fec_clk1, emma_clk1,
 		  dma_clk1, lcdc_clk2, vpu_clk1;
 
 /* All clocks we can gate through PCCRx in the order of PCCRx bits */
@@ -620,7 +632,7 @@ DEFINE_CLOCK1(csi_clk,     0, NULL,   0, parent, &csi_clk1, &per4_clk);
 	{ \
 		.dev_id = d, \
 		.con_id = n, \
-		.clk = &c, \
+		.clk = &c.clk, \
 	},
 
 static struct clk_lookup lookups[] = {
@@ -746,16 +758,16 @@ int __init mx27_clocks_init(unsigned long fref)
 	spll_clk.disable(&spll_clk);
 
 	/* enable basic clocks */
-	clk_enable(&per1_clk);
-	clk_enable(&gpio_clk);
-	clk_enable(&emi_clk);
-	clk_enable(&iim_clk);
+	clk_enable(&per1_clk.clk);
+	clk_enable(&gpio_clk.clk);
+	clk_enable(&emi_clk.clk);
+	clk_enable(&iim_clk.clk);
 
 #if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
-	clk_enable(&uart1_clk);
+	clk_enable(&uart1_clk.clk);
 #endif
 
-	mxc_timer_init(&gpt1_clk, MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR),
+	mxc_timer_init(&gpt1_clk.clk, MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR),
 			MX27_INT_GPT1);
 
 	return 0;
diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c
index 2ed3ab1..3fc75dd 100644
--- a/arch/arm/plat-mxc/clock.c
+++ b/arch/arm/plat-mxc/clock.c
@@ -44,6 +44,131 @@
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+static int clk_mxc_enable(struct clk *clk)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+	int ret = 0;
+
+	if (clk_mxc->parent)
+		ret = clk_enable(&clk_mxc->parent->clk);
+
+	if (!ret && clk_mxc->secondary)
+		ret = clk_enable(&clk_mxc->secondary->clk);
+
+	if (!ret && clk_mxc->enable)
+		ret = clk_mxc->enable(clk_mxc);
+
+	return ret;
+}
+
+static void clk_mxc_disable(struct clk *clk)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+
+	if (clk_mxc->disable)
+		clk_mxc->disable(clk_mxc);
+
+	if (clk_mxc->secondary)
+		clk_disable(&clk_mxc->secondary->clk);
+
+	if (clk_mxc->parent)
+		clk_disable(&clk_mxc->parent->clk);
+}
+
+static unsigned long clk_mxc_get_rate(struct clk *clk)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+
+	if (clk_mxc->get_rate)
+		return clk_mxc->get_rate(clk_mxc);
+	else if (clk_mxc->parent)
+		return clk_get_rate(&clk_mxc->parent->clk);
+	else
+		return 0UL;
+}
+
+static long clk_mxc_round_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+
+	if (clk_mxc->round_rate)
+		return clk_mxc->round_rate(clk_mxc, rate);
+
+	return 0L;
+}
+
+static int clk_mxc_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+	int ret = -EINVAL;
+
+	if (clk_mxc->set_rate && rate != 0)
+		ret = clk_mxc->set_rate(clk_mxc, rate);
+
+	return ret;
+}
+
+static int clk_mxc_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+	struct clk *old_parent = parent;
+	struct clk_mxc *parent_mxc = to_clk_mxc(parent);
+	int ret;
+
+	if (!clk_mxc->set_parent)
+		return -EINVAL;
+
+	if (clk->prepare_count) {
+		ret = clk_prepare(parent);
+		if (ret)
+			goto err_prepare_parent;
+	}
+
+	if (clk->enable_count) {
+		ret = clk_enable(parent);
+		if (ret)
+			goto err_enable_parent;
+	}
+
+	ret = clk_mxc->set_parent(clk_mxc, parent_mxc);
+	if (ret == 0) {
+		old_parent = &clk_mxc->parent->clk;
+		clk_mxc->parent = to_clk_mxc(parent);
+	}
+
+	if (clk->enable_count)
+		clk_disable(old_parent);
+err_enable_parent:
+
+	if (clk->prepare_count)
+		clk_unprepare(old_parent);
+err_prepare_parent:
+
+	return ret;
+}
+
+static struct clk *clk_mxc_get_parent(struct clk *clk)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+
+	if (clk_mxc->parent)
+		return &clk_mxc->parent->clk;
+
+	return NULL;
+}
+
+const struct clk_ops clk_mxc_ops = {
+	.enable = clk_mxc_enable,
+	.disable = clk_mxc_disable,
+	.get_rate = clk_mxc_get_rate,
+	.round_rate = clk_mxc_round_rate,
+	.set_rate = clk_mxc_set_rate,
+	.set_parent = clk_mxc_set_parent,
+	.get_parent = clk_mxc_get_parent,
+};
+#else
+
 /*-------------------------------------------------------------------------
  * Standard clock functions defined in include/linux/clk.h
  *-------------------------------------------------------------------------*/
@@ -200,6 +325,8 @@ struct clk *clk_get_parent(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_get_parent);
 
+#endif
+
 /*
  * Get the resulting clock rate from a PLL register value and the input
  * frequency. PLLs with this register layout can at least be found on
diff --git a/arch/arm/plat-mxc/include/mach/clkdev.h b/arch/arm/plat-mxc/include/mach/clkdev.h
index 04b37a8..f663af3 100644
--- a/arch/arm/plat-mxc/include/mach/clkdev.h
+++ b/arch/arm/plat-mxc/include/mach/clkdev.h
@@ -1,7 +1,11 @@
 #ifndef __ASM_MACH_CLKDEV_H
 #define __ASM_MACH_CLKDEV_H
 
+#ifndef CONFIG_USE_COMMON_STRUCT_CLK
+
 #define __clk_get(clk) ({ 1; })
 #define __clk_put(clk) do { } while (0)
 
 #endif
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/clock.h b/arch/arm/plat-mxc/include/mach/clock.h
index 753a598..d8efa77 100644
--- a/arch/arm/plat-mxc/include/mach/clock.h
+++ b/arch/arm/plat-mxc/include/mach/clock.h
@@ -23,14 +23,24 @@
 #ifndef __ASSEMBLY__
 #include <linux/list.h>
 
+#include <linux/clk.h>
+
 struct module;
 
-struct clk {
+#ifndef CONFIG_USE_COMMON_STRUCT_CLK
+#define clk_mxc clk
+#endif
+
+struct clk_mxc {
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+	struct clk clk;
+#endif
+
 	int id;
 	/* Source clock this clk depends on */
-	struct clk *parent;
+	struct clk_mxc *parent;
 	/* Secondary clock to enable/disable with this clock */
-	struct clk *secondary;
+	struct clk_mxc *secondary;
 	/* Reference count of clock enable/disable */
 	__s8 usecount;
 	/* Register bit position for clock's enable/disable control. */
@@ -39,23 +49,27 @@ struct clk {
 	void __iomem *enable_reg;
 	u32 flags;
 	/* get the current clock rate (always a fresh value) */
-	unsigned long (*get_rate) (struct clk *);
+	unsigned long (*get_rate) (struct clk_mxc *);
 	/* Function ptr to set the clock to a new rate. The rate must match a
 	   supported rate returned from round_rate. Leave blank if clock is not
 	   programmable */
-	int (*set_rate) (struct clk *, unsigned long);
+	int (*set_rate) (struct clk_mxc *, unsigned long);
 	/* Function ptr to round the requested clock rate to the nearest
 	   supported rate that is less than or equal to the requested rate. */
-	unsigned long (*round_rate) (struct clk *, unsigned long);
+	unsigned long (*round_rate) (struct clk_mxc *, unsigned long);
 	/* Function ptr to enable the clock. Leave blank if clock can not
 	   be gated. */
-	int (*enable) (struct clk *);
+	int (*enable) (struct clk_mxc *);
 	/* Function ptr to disable the clock. Leave blank if clock can not
 	   be gated. */
-	void (*disable) (struct clk *);
+	void (*disable) (struct clk_mxc *);
 	/* Function ptr to set the parent clock of the clock. */
-	int (*set_parent) (struct clk *, struct clk *);
+	int (*set_parent) (struct clk_mxc *, struct clk_mxc *);
 };
+#define to_clk_mxc(_clk_mxc)        container_of(_clk_mxc, struct clk_mxc, clk)
+
+extern const struct clk_ops clk_mxc_ops;
+#define INIT_CLK_MXC(name)	INIT_CLK(name.clk, clk_mxc_ops)
 
 int clk_register(struct clk *clk);
 void clk_unregister(struct clk *clk);
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0da0bb9..fbafcb6 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -47,7 +47,7 @@ int clk_enable(struct clk *clk)
 	unsigned long flags;
 	int ret = 0;
 
-	WARN_ON(clk->prepare_count == 0);
+	WARN_ON_ONCE(clk->prepare_count == 0);
 
 	spin_lock_irqsave(&clk->enable_lock, flags);
 	if (clk->enable_count == 0 && clk->ops->enable)
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [PATCH] wip: convert imx27 to common struct clk
@ 2011-02-22 23:33     ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-22 23:33 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
Hello,

on top of .38-rc6 + making the clk_{un,}prepare stubs static inline,
this patch makes use of Jeremy's common struct clk (v13) on a i.MX27 based
machine.

This is compile tested using mx21_defconfig and runtime tested using
mx27_defconfig.

I had to degrade one WARN_ON to WARN_ON_ONCE in drivers/clk/clk.c to
actually make it work.  Otherwise console output results in a warning
that results in console output ...

Best regards
Uwe

 arch/arm/mach-imx/Kconfig               |    1 +
 arch/arm/mach-imx/clock-imx27.c         |  186 ++++++++++++++++--------------
 arch/arm/plat-mxc/clock.c               |  127 +++++++++++++++++++++
 arch/arm/plat-mxc/include/mach/clkdev.h |    4 +
 arch/arm/plat-mxc/include/mach/clock.h  |   32 ++++--
 drivers/clk/clk.c                       |    2 +-
 6 files changed, 255 insertions(+), 97 deletions(-)

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 56684b5..f2d3708 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -30,6 +30,7 @@ config SOC_IMX27
 	select IMX_HAVE_DMA_V1
 	select IMX_HAVE_IOMUX_V1
 	select MXC_AVIC
+	select USE_COMMON_STRUCT_CLK
 
 if ARCH_MX1
 
diff --git a/arch/arm/mach-imx/clock-imx27.c b/arch/arm/mach-imx/clock-imx27.c
index 583f251..f413f7b 100644
--- a/arch/arm/mach-imx/clock-imx27.c
+++ b/arch/arm/mach-imx/clock-imx27.c
@@ -68,35 +68,35 @@
 #define CCM_SPCTL1_LF           (1 << 15)
 #define CCM_SPCTL1_BRMO         (1 << 6)
 
-static struct clk mpll_main1_clk, mpll_main2_clk;
+static struct clk_mxc mpll_main1_clk, mpll_main2_clk;
 
-static int clk_pccr_enable(struct clk *clk)
+static int clk_pccr_enable(struct clk_mxc *clk_mxc)
 {
 	unsigned long reg;
 
-	if (!clk->enable_reg)
+	if (!clk_mxc->enable_reg)
 		return 0;
 
-	reg = __raw_readl(clk->enable_reg);
-	reg |= 1 << clk->enable_shift;
-	__raw_writel(reg, clk->enable_reg);
+	reg = __raw_readl(clk_mxc->enable_reg);
+	reg |= 1 << clk_mxc->enable_shift;
+	__raw_writel(reg, clk_mxc->enable_reg);
 
 	return 0;
 }
 
-static void clk_pccr_disable(struct clk *clk)
+static void clk_pccr_disable(struct clk_mxc *clk_mxc)
 {
 	unsigned long reg;
 
-	if (!clk->enable_reg)
+	if (!clk_mxc->enable_reg)
 		return;
 
-	reg = __raw_readl(clk->enable_reg);
-	reg &= ~(1 << clk->enable_shift);
-	__raw_writel(reg, clk->enable_reg);
+	reg = __raw_readl(clk_mxc->enable_reg);
+	reg &= ~(1 << clk_mxc->enable_shift);
+	__raw_writel(reg, clk_mxc->enable_reg);
 }
 
-static int clk_spll_enable(struct clk *clk)
+static int clk_spll_enable(struct clk_mxc *clk_mxc)
 {
 	unsigned long reg;
 
@@ -109,7 +109,7 @@ static int clk_spll_enable(struct clk *clk)
 	return 0;
 }
 
-static void clk_spll_disable(struct clk *clk)
+static void clk_spll_disable(struct clk_mxc *clk_mxc)
 {
 	unsigned long reg;
 
@@ -118,11 +118,11 @@ static void clk_spll_disable(struct clk *clk)
 	__raw_writel(reg, CCM_CSCR);
 }
 
-static int clk_cpu_set_parent(struct clk *clk, struct clk *parent)
+static int clk_cpu_set_parent(struct clk_mxc *clk_mxc, struct clk_mxc *parent)
 {
 	int cscr = __raw_readl(CCM_CSCR);
 
-	if (clk->parent == parent)
+	if (clk_mxc->parent == parent)
 		return 0;
 
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
@@ -135,18 +135,18 @@ static int clk_cpu_set_parent(struct clk *clk, struct clk *parent)
 				return -EINVAL;
 		}
 		__raw_writel(cscr, CCM_CSCR);
-		clk->parent = parent;
+		clk_mxc->parent = parent;
 		return 0;
 	}
 	return -ENODEV;
 }
 
-static unsigned long round_rate_cpu(struct clk *clk, unsigned long rate)
+static unsigned long round_rate_cpu(struct clk_mxc *clk_mxc, unsigned long rate)
 {
 	int div;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	div = parent_rate / rate;
 	if (parent_rate % rate)
@@ -158,13 +158,13 @@ static unsigned long round_rate_cpu(struct clk *clk, unsigned long rate)
 	return parent_rate / div;
 }
 
-static int set_rate_cpu(struct clk *clk, unsigned long rate)
+static int set_rate_cpu(struct clk_mxc *clk_mxc, unsigned long rate)
 {
 	unsigned int div;
 	uint32_t reg;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	div = parent_rate / rate;
 
@@ -186,12 +186,12 @@ static int set_rate_cpu(struct clk *clk, unsigned long rate)
 	return 0;
 }
 
-static unsigned long round_rate_per(struct clk *clk, unsigned long rate)
+static unsigned long round_rate_per(struct clk_mxc *clk_mxc, unsigned long rate)
 {
 	u32 div;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	div = parent_rate / rate;
 	if (parent_rate % rate)
@@ -203,15 +203,15 @@ static unsigned long round_rate_per(struct clk *clk, unsigned long rate)
 	return parent_rate / div;
 }
 
-static int set_rate_per(struct clk *clk, unsigned long rate)
+static int set_rate_per(struct clk_mxc *clk_mxc, unsigned long rate)
 {
 	u32 reg;
 	u32 div;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
-	if (clk->id < 0 || clk->id > 3)
+	if (clk_mxc->id < 0 || clk_mxc->id > 3)
 		return -EINVAL;
 
 	div = parent_rate / rate;
@@ -219,30 +219,30 @@ static int set_rate_per(struct clk *clk, unsigned long rate)
 		return -EINVAL;
 	div--;
 
-	reg = __raw_readl(CCM_PCDR1) & ~(0x3f << (clk->id << 3));
-	reg |= div << (clk->id << 3);
+	reg = __raw_readl(CCM_PCDR1) & ~(0x3f << (clk_mxc->id << 3));
+	reg |= div << (clk_mxc->id << 3);
 	__raw_writel(reg, CCM_PCDR1);
 
 	return 0;
 }
 
-static unsigned long get_rate_usb(struct clk *clk)
+static unsigned long get_rate_usb(struct clk_mxc *clk_mxc)
 {
 	unsigned long usb_pdf;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	usb_pdf = (__raw_readl(CCM_CSCR) >> 28) & 0x7;
 
 	return parent_rate / (usb_pdf + 1U);
 }
 
-static unsigned long get_rate_ssix(struct clk *clk, unsigned long pdf)
+static unsigned long get_rate_ssix(struct clk_mxc *clk_mxc, unsigned long pdf)
 {
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
 		pdf += 4;  /* MX27 TO2+ */
@@ -252,22 +252,22 @@ static unsigned long get_rate_ssix(struct clk *clk, unsigned long pdf)
 	return 2UL * parent_rate / pdf;
 }
 
-static unsigned long get_rate_ssi1(struct clk *clk)
+static unsigned long get_rate_ssi1(struct clk_mxc *clk_mxc)
 {
-	return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 16) & 0x3f);
+	return get_rate_ssix(clk_mxc, (__raw_readl(CCM_PCDR0) >> 16) & 0x3f);
 }
 
-static unsigned long get_rate_ssi2(struct clk *clk)
+static unsigned long get_rate_ssi2(struct clk_mxc *clk_mxc)
 {
-	return get_rate_ssix(clk, (__raw_readl(CCM_PCDR0) >> 26) & 0x3f);
+	return get_rate_ssix(clk_mxc, (__raw_readl(CCM_PCDR0) >> 26) & 0x3f);
 }
 
-static unsigned long get_rate_nfc(struct clk *clk)
+static unsigned long get_rate_nfc(struct clk_mxc *clk_mxc)
 {
 	unsigned long nfc_pdf;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
 		nfc_pdf = (__raw_readl(CCM_PCDR0) >> 6) & 0xf;
@@ -277,12 +277,12 @@ static unsigned long get_rate_nfc(struct clk *clk)
 	return parent_rate / (nfc_pdf + 1);
 }
 
-static unsigned long get_rate_vpu(struct clk *clk)
+static unsigned long get_rate_vpu(struct clk_mxc *clk_mxc)
 {
 	unsigned long vpu_pdf;
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
 		vpu_pdf = (__raw_readl(CCM_PCDR0) >> 10) & 0x3f;
@@ -295,25 +295,25 @@ static unsigned long get_rate_vpu(struct clk *clk)
 	return 2UL * parent_rate / vpu_pdf;
 }
 
-static unsigned long round_rate_parent(struct clk *clk, unsigned long rate)
+static unsigned long round_rate_parent(struct clk_mxc *clk_mxc, unsigned long rate)
 {
-	return clk->parent->round_rate(clk->parent, rate);
+	return clk_round_rate(&clk_mxc->parent->clk, rate);
 }
 
-static unsigned long get_rate_parent(struct clk *clk)
+static unsigned long get_rate_parent(struct clk_mxc *clk_mxc)
 {
-	return clk_get_rate(clk->parent);
+	return clk_get_rate(&clk_mxc->parent->clk);
 }
 
-static int set_rate_parent(struct clk *clk, unsigned long rate)
+static int set_rate_parent(struct clk_mxc *clk_mxc, unsigned long rate)
 {
-	return clk->parent->set_rate(clk->parent, rate);
+	return clk_set_rate(&clk_mxc->parent->clk, rate);
 }
 
 /* in Hz */
 static unsigned long external_high_reference = 26000000;
 
-static unsigned long get_rate_high_reference(struct clk *clk)
+static unsigned long get_rate_high_reference(struct clk_mxc *clk)
 {
 	return external_high_reference;
 }
@@ -321,44 +321,44 @@ static unsigned long get_rate_high_reference(struct clk *clk)
 /* in Hz */
 static unsigned long external_low_reference = 32768;
 
-static unsigned long get_rate_low_reference(struct clk *clk)
+static unsigned long get_rate_low_reference(struct clk_mxc *clk_mxc)
 {
 	return external_low_reference;
 }
 
-static unsigned long get_rate_fpm(struct clk *clk)
+static unsigned long get_rate_fpm(struct clk_mxc *clk_mxc)
 {
-	return clk_get_rate(clk->parent) * 1024;
+	return clk_get_rate(&clk_mxc->parent->clk) * 1024;
 }
 
-static unsigned long get_rate_mpll(struct clk *clk)
+static unsigned long get_rate_mpll(struct clk_mxc *clk_mxc)
 {
 	return mxc_decode_pll(__raw_readl(CCM_MPCTL0),
-			clk_get_rate(clk->parent));
+			clk_get_rate(&clk_mxc->parent->clk));
 }
 
-static unsigned long get_rate_mpll_main(struct clk *clk)
+static unsigned long get_rate_mpll_main(struct clk_mxc *clk_mxc)
 {
 	unsigned long parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	/* i.MX27 TO2:
 	 * clk->id == 0: arm clock source path 1 which is from 2 * MPLL / 2
 	 * clk->id == 1: arm clock source path 2 which is from 2 * MPLL / 3
 	 */
-	if (mx27_revision() >= IMX_CHIP_REVISION_2_0 && clk->id == 1)
+	if (mx27_revision() >= IMX_CHIP_REVISION_2_0 && clk_mxc->id == 1)
 		return 2UL * parent_rate / 3UL;
 
 	return parent_rate;
 }
 
-static unsigned long get_rate_spll(struct clk *clk)
+static unsigned long get_rate_spll(struct clk_mxc *clk_mxc)
 {
 	uint32_t reg;
 	unsigned long rate;
 
-	rate = clk_get_rate(clk->parent);
+	rate = clk_get_rate(&clk_mxc->parent->clk);
 
 	reg = __raw_readl(CCM_SPCTL0);
 
@@ -371,7 +371,7 @@ static unsigned long get_rate_spll(struct clk *clk)
 	return mxc_decode_pll(reg, rate);
 }
 
-static unsigned long get_rate_cpu(struct clk *clk)
+static unsigned long get_rate_cpu(struct clk_mxc *clk_mxc)
 {
 	u32 div;
 	unsigned long rate;
@@ -381,11 +381,11 @@ static unsigned long get_rate_cpu(struct clk *clk)
 	else
 		div = (__raw_readl(CCM_CSCR) >> 13) & 0x7;
 
-	rate = clk_get_rate(clk->parent);
+	rate = clk_get_rate(&clk_mxc->parent->clk);
 	return rate / (div + 1);
 }
 
-static unsigned long get_rate_ahb(struct clk *clk)
+static unsigned long get_rate_ahb(struct clk_mxc *clk_mxc)
 {
 	unsigned long rate, bclk_pdf;
 
@@ -394,33 +394,33 @@ static unsigned long get_rate_ahb(struct clk *clk)
 	else
 		bclk_pdf = (__raw_readl(CCM_CSCR) >> 9) & 0xf;
 
-	rate = clk_get_rate(clk->parent);
+	rate = clk_get_rate(&clk_mxc->parent->clk);
 	return rate / (bclk_pdf + 1);
 }
 
-static unsigned long get_rate_ipg(struct clk *clk)
+static unsigned long get_rate_ipg(struct clk_mxc *clk_mxc)
 {
 	unsigned long rate, ipg_pdf;
 
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
-		return clk_get_rate(clk->parent);
+		return clk_get_rate(&clk_mxc->parent->clk);
 	else
 		ipg_pdf = (__raw_readl(CCM_CSCR) >> 8) & 1;
 
-	rate = clk_get_rate(clk->parent);
+	rate = clk_get_rate(&clk_mxc->parent->clk);
 	return rate / (ipg_pdf + 1);
 }
 
-static unsigned long get_rate_per(struct clk *clk)
+static unsigned long get_rate_per(struct clk_mxc *clk_mxc)
 {
 	unsigned long perclk_pdf, parent_rate;
 
-	parent_rate = clk_get_rate(clk->parent);
+	parent_rate = clk_get_rate(&clk_mxc->parent->clk);
 
-	if (clk->id < 0 || clk->id > 3)
+	if (clk_mxc->id < 0 || clk_mxc->id > 3)
 		return 0;
 
-	perclk_pdf = (__raw_readl(CCM_PCDR1) >> (clk->id << 3)) & 0x3f;
+	perclk_pdf = (__raw_readl(CCM_PCDR1) >> (clk_mxc->id << 3)) & 0x3f;
 
 	return parent_rate / (perclk_pdf + 1);
 }
@@ -430,11 +430,13 @@ static unsigned long get_rate_per(struct clk *clk)
  * Default case is 26MHz. Could be changed@runtime
  * with a call to change_external_high_reference()
  */
-static struct clk ckih_clk = {
+static struct clk_mxc ckih_clk = {
+	.clk = INIT_CLK_MXC(ckih_clk),
 	.get_rate	= get_rate_high_reference,
 };
 
-static struct clk mpll_clk = {
+static struct clk_mxc mpll_clk = {
+	.clk = INIT_CLK_MXC(mpll_clk),
 	.parent		= &ckih_clk,
 	.get_rate	= get_rate_mpll,
 };
@@ -442,7 +444,8 @@ static struct clk mpll_clk = {
 /* For i.MX27 TO2, it is the MPLL path 1 of ARM core
  * It provides the clock source whose rate is same as MPLL
  */
-static struct clk mpll_main1_clk = {
+static struct clk_mxc mpll_main1_clk = {
+	.clk = INIT_CLK_MXC(mpll_main1_clk),
 	.id		= 0,
 	.parent		= &mpll_clk,
 	.get_rate	= get_rate_mpll_main,
@@ -451,23 +454,27 @@ static struct clk mpll_main1_clk = {
 /* For i.MX27 TO2, it is the MPLL path 2 of ARM core
  * It provides the clock source whose rate is same MPLL * 2 / 3
  */
-static struct clk mpll_main2_clk = {
+static struct clk_mxc mpll_main2_clk = {
+	.clk = INIT_CLK_MXC(mpll_main2_clk),
 	.id		= 1,
 	.parent		= &mpll_clk,
 	.get_rate	= get_rate_mpll_main,
 };
 
-static struct clk ahb_clk = {
+static struct clk_mxc ahb_clk = {
+	.clk = INIT_CLK_MXC(ahb_clk),
 	.parent		= &mpll_main2_clk,
 	.get_rate	= get_rate_ahb,
 };
 
-static struct clk ipg_clk = {
+static struct clk_mxc ipg_clk = {
+	.clk = INIT_CLK_MXC(ipg_clk),
 	.parent		= &ahb_clk,
 	.get_rate	= get_rate_ipg,
 };
 
-static struct clk cpu_clk = {
+static struct clk_mxc cpu_clk = {
+	.clk = INIT_CLK_MXC(cpu_clk),
 	.parent = &mpll_main2_clk,
 	.set_parent = clk_cpu_set_parent,
 	.round_rate = round_rate_cpu,
@@ -475,7 +482,8 @@ static struct clk cpu_clk = {
 	.set_rate = set_rate_cpu,
 };
 
-static struct clk spll_clk = {
+static struct clk_mxc spll_clk = {
+	.clk = INIT_CLK_MXC(spll_clk),
 	.parent = &ckih_clk,
 	.get_rate = get_rate_spll,
 	.enable = clk_spll_enable,
@@ -486,12 +494,14 @@ static struct clk spll_clk = {
  * the low frequency external clock reference
  * Default case is 32.768kHz.
  */
-static struct clk ckil_clk = {
+static struct clk_mxc ckil_clk = {
+	.clk = INIT_CLK_MXC(ckil_clk),
 	.get_rate = get_rate_low_reference,
 };
 
 /* Output of frequency pre multiplier */
-static struct clk fpm_clk = {
+static struct clk_mxc fpm_clk = {
+	.clk = INIT_CLK_MXC(fpm_clk),
 	.parent = &ckil_clk,
 	.get_rate = get_rate_fpm,
 };
@@ -500,7 +510,8 @@ static struct clk fpm_clk = {
 #define PCCR1 CCM_PCCR1
 
 #define DEFINE_CLOCK(name, i, er, es, gr, s, p)		\
-	static struct clk name = {			\
+	static struct clk_mxc name = {			\
+		.clk = INIT_CLK_MXC(name),		\
 		.id		= i,			\
 		.enable_reg	= er,			\
 		.enable_shift	= es,			\
@@ -512,7 +523,8 @@ static struct clk fpm_clk = {
 	}
 
 #define DEFINE_CLOCK1(name, i, er, es, getsetround, s, p)	\
-	static struct clk name = {				\
+	static struct clk_mxc name = {				\
+		.clk = INIT_CLK_MXC(name),			\
 		.id		= i,				\
 		.enable_reg	= er,				\
 		.enable_shift	= es,				\
@@ -526,7 +538,7 @@ static struct clk fpm_clk = {
 	}
 
 /* Forward declaration to keep the following list in order */
-static struct clk slcdc_clk1, sahara2_clk1, rtic_clk1, fec_clk1, emma_clk1,
+static struct clk_mxc slcdc_clk1, sahara2_clk1, rtic_clk1, fec_clk1, emma_clk1,
 		  dma_clk1, lcdc_clk2, vpu_clk1;
 
 /* All clocks we can gate through PCCRx in the order of PCCRx bits */
@@ -620,7 +632,7 @@ DEFINE_CLOCK1(csi_clk,     0, NULL,   0, parent, &csi_clk1, &per4_clk);
 	{ \
 		.dev_id = d, \
 		.con_id = n, \
-		.clk = &c, \
+		.clk = &c.clk, \
 	},
 
 static struct clk_lookup lookups[] = {
@@ -746,16 +758,16 @@ int __init mx27_clocks_init(unsigned long fref)
 	spll_clk.disable(&spll_clk);
 
 	/* enable basic clocks */
-	clk_enable(&per1_clk);
-	clk_enable(&gpio_clk);
-	clk_enable(&emi_clk);
-	clk_enable(&iim_clk);
+	clk_enable(&per1_clk.clk);
+	clk_enable(&gpio_clk.clk);
+	clk_enable(&emi_clk.clk);
+	clk_enable(&iim_clk.clk);
 
 #if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_ICEDCC)
-	clk_enable(&uart1_clk);
+	clk_enable(&uart1_clk.clk);
 #endif
 
-	mxc_timer_init(&gpt1_clk, MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR),
+	mxc_timer_init(&gpt1_clk.clk, MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR),
 			MX27_INT_GPT1);
 
 	return 0;
diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c
index 2ed3ab1..3fc75dd 100644
--- a/arch/arm/plat-mxc/clock.c
+++ b/arch/arm/plat-mxc/clock.c
@@ -44,6 +44,131 @@
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+static int clk_mxc_enable(struct clk *clk)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+	int ret = 0;
+
+	if (clk_mxc->parent)
+		ret = clk_enable(&clk_mxc->parent->clk);
+
+	if (!ret && clk_mxc->secondary)
+		ret = clk_enable(&clk_mxc->secondary->clk);
+
+	if (!ret && clk_mxc->enable)
+		ret = clk_mxc->enable(clk_mxc);
+
+	return ret;
+}
+
+static void clk_mxc_disable(struct clk *clk)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+
+	if (clk_mxc->disable)
+		clk_mxc->disable(clk_mxc);
+
+	if (clk_mxc->secondary)
+		clk_disable(&clk_mxc->secondary->clk);
+
+	if (clk_mxc->parent)
+		clk_disable(&clk_mxc->parent->clk);
+}
+
+static unsigned long clk_mxc_get_rate(struct clk *clk)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+
+	if (clk_mxc->get_rate)
+		return clk_mxc->get_rate(clk_mxc);
+	else if (clk_mxc->parent)
+		return clk_get_rate(&clk_mxc->parent->clk);
+	else
+		return 0UL;
+}
+
+static long clk_mxc_round_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+
+	if (clk_mxc->round_rate)
+		return clk_mxc->round_rate(clk_mxc, rate);
+
+	return 0L;
+}
+
+static int clk_mxc_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+	int ret = -EINVAL;
+
+	if (clk_mxc->set_rate && rate != 0)
+		ret = clk_mxc->set_rate(clk_mxc, rate);
+
+	return ret;
+}
+
+static int clk_mxc_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+	struct clk *old_parent = parent;
+	struct clk_mxc *parent_mxc = to_clk_mxc(parent);
+	int ret;
+
+	if (!clk_mxc->set_parent)
+		return -EINVAL;
+
+	if (clk->prepare_count) {
+		ret = clk_prepare(parent);
+		if (ret)
+			goto err_prepare_parent;
+	}
+
+	if (clk->enable_count) {
+		ret = clk_enable(parent);
+		if (ret)
+			goto err_enable_parent;
+	}
+
+	ret = clk_mxc->set_parent(clk_mxc, parent_mxc);
+	if (ret == 0) {
+		old_parent = &clk_mxc->parent->clk;
+		clk_mxc->parent = to_clk_mxc(parent);
+	}
+
+	if (clk->enable_count)
+		clk_disable(old_parent);
+err_enable_parent:
+
+	if (clk->prepare_count)
+		clk_unprepare(old_parent);
+err_prepare_parent:
+
+	return ret;
+}
+
+static struct clk *clk_mxc_get_parent(struct clk *clk)
+{
+	struct clk_mxc *clk_mxc = to_clk_mxc(clk);
+
+	if (clk_mxc->parent)
+		return &clk_mxc->parent->clk;
+
+	return NULL;
+}
+
+const struct clk_ops clk_mxc_ops = {
+	.enable = clk_mxc_enable,
+	.disable = clk_mxc_disable,
+	.get_rate = clk_mxc_get_rate,
+	.round_rate = clk_mxc_round_rate,
+	.set_rate = clk_mxc_set_rate,
+	.set_parent = clk_mxc_set_parent,
+	.get_parent = clk_mxc_get_parent,
+};
+#else
+
 /*-------------------------------------------------------------------------
  * Standard clock functions defined in include/linux/clk.h
  *-------------------------------------------------------------------------*/
@@ -200,6 +325,8 @@ struct clk *clk_get_parent(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_get_parent);
 
+#endif
+
 /*
  * Get the resulting clock rate from a PLL register value and the input
  * frequency. PLLs with this register layout can at least be found on
diff --git a/arch/arm/plat-mxc/include/mach/clkdev.h b/arch/arm/plat-mxc/include/mach/clkdev.h
index 04b37a8..f663af3 100644
--- a/arch/arm/plat-mxc/include/mach/clkdev.h
+++ b/arch/arm/plat-mxc/include/mach/clkdev.h
@@ -1,7 +1,11 @@
 #ifndef __ASM_MACH_CLKDEV_H
 #define __ASM_MACH_CLKDEV_H
 
+#ifndef CONFIG_USE_COMMON_STRUCT_CLK
+
 #define __clk_get(clk) ({ 1; })
 #define __clk_put(clk) do { } while (0)
 
 #endif
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/clock.h b/arch/arm/plat-mxc/include/mach/clock.h
index 753a598..d8efa77 100644
--- a/arch/arm/plat-mxc/include/mach/clock.h
+++ b/arch/arm/plat-mxc/include/mach/clock.h
@@ -23,14 +23,24 @@
 #ifndef __ASSEMBLY__
 #include <linux/list.h>
 
+#include <linux/clk.h>
+
 struct module;
 
-struct clk {
+#ifndef CONFIG_USE_COMMON_STRUCT_CLK
+#define clk_mxc clk
+#endif
+
+struct clk_mxc {
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+	struct clk clk;
+#endif
+
 	int id;
 	/* Source clock this clk depends on */
-	struct clk *parent;
+	struct clk_mxc *parent;
 	/* Secondary clock to enable/disable with this clock */
-	struct clk *secondary;
+	struct clk_mxc *secondary;
 	/* Reference count of clock enable/disable */
 	__s8 usecount;
 	/* Register bit position for clock's enable/disable control. */
@@ -39,23 +49,27 @@ struct clk {
 	void __iomem *enable_reg;
 	u32 flags;
 	/* get the current clock rate (always a fresh value) */
-	unsigned long (*get_rate) (struct clk *);
+	unsigned long (*get_rate) (struct clk_mxc *);
 	/* Function ptr to set the clock to a new rate. The rate must match a
 	   supported rate returned from round_rate. Leave blank if clock is not
 	   programmable */
-	int (*set_rate) (struct clk *, unsigned long);
+	int (*set_rate) (struct clk_mxc *, unsigned long);
 	/* Function ptr to round the requested clock rate to the nearest
 	   supported rate that is less than or equal to the requested rate. */
-	unsigned long (*round_rate) (struct clk *, unsigned long);
+	unsigned long (*round_rate) (struct clk_mxc *, unsigned long);
 	/* Function ptr to enable the clock. Leave blank if clock can not
 	   be gated. */
-	int (*enable) (struct clk *);
+	int (*enable) (struct clk_mxc *);
 	/* Function ptr to disable the clock. Leave blank if clock can not
 	   be gated. */
-	void (*disable) (struct clk *);
+	void (*disable) (struct clk_mxc *);
 	/* Function ptr to set the parent clock of the clock. */
-	int (*set_parent) (struct clk *, struct clk *);
+	int (*set_parent) (struct clk_mxc *, struct clk_mxc *);
 };
+#define to_clk_mxc(_clk_mxc)        container_of(_clk_mxc, struct clk_mxc, clk)
+
+extern const struct clk_ops clk_mxc_ops;
+#define INIT_CLK_MXC(name)	INIT_CLK(name.clk, clk_mxc_ops)
 
 int clk_register(struct clk *clk);
 void clk_unregister(struct clk *clk);
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0da0bb9..fbafcb6 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -47,7 +47,7 @@ int clk_enable(struct clk *clk)
 	unsigned long flags;
 	int ret = 0;
 
-	WARN_ON(clk->prepare_count == 0);
+	WARN_ON_ONCE(clk->prepare_count == 0);
 
 	spin_lock_irqsave(&clk->enable_lock, flags);
 	if (clk->enable_count == 0 && clk->ops->enable)
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* Re: [PATCH 1/2] Add a common struct clk
  2011-02-22 20:17       ` Uwe Kleine-König
  (?)
@ 2011-02-23  2:49         ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-23  2:49 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Uwe,

> > +static inline void clk_common_init(struct clk *clk) { }
> > +
> > +/*
> > + * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
> > + * requirements for clk_enable/clk_disable, so the prepare and unprepare
> > + * functions are no-ops
> > + */
> > +int clk_prepare(struct clk *clk) { return 0; }
> > +void clk_unprepare(struct clk *clk) { }
> 
> these should be static inline.  Otherwise these functions end up in many
> files and so provoke a build failure.

Ugh, brown paper bag time. Thanks for that, I'll update this patch.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 1/2] Add a common struct clk
@ 2011-02-23  2:49         ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-23  2:49 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenchmidt, Sascha Hauer,
	Paul Mundt, Dima Zavin, Saravana Kannan, Ben Dooks, Russell King

Hi Uwe,

> > +static inline void clk_common_init(struct clk *clk) { }
> > +
> > +/*
> > + * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
> > + * requirements for clk_enable/clk_disable, so the prepare and unprepare
> > + * functions are no-ops
> > + */
> > +int clk_prepare(struct clk *clk) { return 0; }
> > +void clk_unprepare(struct clk *clk) { }
> 
> these should be static inline.  Otherwise these functions end up in many
> files and so provoke a build failure.

Ugh, brown paper bag time. Thanks for that, I'll update this patch.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 1/2] Add a common struct clk
@ 2011-02-23  2:49         ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-02-23  2:49 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Uwe,

> > +static inline void clk_common_init(struct clk *clk) { }
> > +
> > +/*
> > + * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
> > + * requirements for clk_enable/clk_disable, so the prepare and unprepare
> > + * functions are no-ops
> > + */
> > +int clk_prepare(struct clk *clk) { return 0; }
> > +void clk_unprepare(struct clk *clk) { }
> 
> these should be static inline.  Otherwise these functions end up in many
> files and so provoke a build failure.

Ugh, brown paper bag time. Thanks for that, I'll update this patch.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH] wip: convert imx27 to common struct clk
  2011-02-22 23:33     ` Uwe Kleine-König
  (?)
@ 2011-02-23  4:17       ` Saravana Kannan
  -1 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-23  4:17 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/22/2011 03:33 PM, Uwe Kleine-König wrote:
> Signed-off-by: Uwe Kleine-König<u.kleine-koenig@pengutronix.de>
> ---
> Hello,
>
> on top of .38-rc6 + making the clk_{un,}prepare stubs static inline,
> this patch makes use of Jeremy's common struct clk (v13) on a i.MX27 based
> machine.
>
> This is compile tested using mx21_defconfig and runtime tested using
> mx27_defconfig.
>
> I had to degrade one WARN_ON to WARN_ON_ONCE in drivers/clk/clk.c to
> actually make it work.  Otherwise console output results in a warning
> that results in console output ...

You won't be able to do mainline the WARN_ON_ONCE because that will only 
warn for the first clock that violates whatever condition it's warning 
about.

Your probably need to fix your serial driver. What serial driver are you 
using?

-Saravana


^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH] wip: convert imx27 to common struct clk
@ 2011-02-23  4:17       ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-23  4:17 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Jeremy Kerr, linux-kernel, linux-arm-kernel, Nicolas Pitre,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Sascha Hauer, Paul Mundt, Dima Zavin, Ben Dooks, Russell King

On 02/22/2011 03:33 PM, Uwe Kleine-König wrote:
> Signed-off-by: Uwe Kleine-König<u.kleine-koenig@pengutronix.de>
> ---
> Hello,
>
> on top of .38-rc6 + making the clk_{un,}prepare stubs static inline,
> this patch makes use of Jeremy's common struct clk (v13) on a i.MX27 based
> machine.
>
> This is compile tested using mx21_defconfig and runtime tested using
> mx27_defconfig.
>
> I had to degrade one WARN_ON to WARN_ON_ONCE in drivers/clk/clk.c to
> actually make it work.  Otherwise console output results in a warning
> that results in console output ...

You won't be able to do mainline the WARN_ON_ONCE because that will only 
warn for the first clock that violates whatever condition it's warning 
about.

Your probably need to fix your serial driver. What serial driver are you 
using?

-Saravana


^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH] wip: convert imx27 to common struct clk
@ 2011-02-23  4:17       ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-02-23  4:17 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/22/2011 03:33 PM, Uwe Kleine-K?nig wrote:
> Signed-off-by: Uwe Kleine-K?nig<u.kleine-koenig@pengutronix.de>
> ---
> Hello,
>
> on top of .38-rc6 + making the clk_{un,}prepare stubs static inline,
> this patch makes use of Jeremy's common struct clk (v13) on a i.MX27 based
> machine.
>
> This is compile tested using mx21_defconfig and runtime tested using
> mx27_defconfig.
>
> I had to degrade one WARN_ON to WARN_ON_ONCE in drivers/clk/clk.c to
> actually make it work.  Otherwise console output results in a warning
> that results in console output ...

You won't be able to do mainline the WARN_ON_ONCE because that will only 
warn for the first clock that violates whatever condition it's warning 
about.

Your probably need to fix your serial driver. What serial driver are you 
using?

-Saravana

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH] wip: convert imx27 to common struct clk
  2011-02-23  4:17       ` Saravana Kannan
  (?)
@ 2011-02-23  8:15         ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-02-23  8:15 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Saravana,

On Tue, Feb 22, 2011 at 08:17:01PM -0800, Saravana Kannan wrote:
> On 02/22/2011 03:33 PM, Uwe Kleine-König wrote:
> >I had to degrade one WARN_ON to WARN_ON_ONCE in drivers/clk/clk.c to
> >actually make it work.  Otherwise console output results in a warning
> >that results in console output ...
> 
> You won't be able to do mainline the WARN_ON_ONCE because that will
> only warn for the first clock that violates whatever condition it's
> warning about.
I wonder if it is more sensible while the warning is new.  But I don't
care much because I'm going to fix the serial driver before switching.
 
Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH] wip: convert imx27 to common struct clk
@ 2011-02-23  8:15         ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-23  8:15 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: Jeremy Kerr, linux-kernel, linux-arm-kernel, Nicolas Pitre,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Sascha Hauer, Paul Mundt, Dima Zavin, Ben Dooks, Russell King

Hi Saravana,

On Tue, Feb 22, 2011 at 08:17:01PM -0800, Saravana Kannan wrote:
> On 02/22/2011 03:33 PM, Uwe Kleine-König wrote:
> >I had to degrade one WARN_ON to WARN_ON_ONCE in drivers/clk/clk.c to
> >actually make it work.  Otherwise console output results in a warning
> >that results in console output ...
> 
> You won't be able to do mainline the WARN_ON_ONCE because that will
> only warn for the first clock that violates whatever condition it's
> warning about.
I wonder if it is more sensible while the warning is new.  But I don't
care much because I'm going to fix the serial driver before switching.
 
Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH] wip: convert imx27 to common struct clk
@ 2011-02-23  8:15         ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-02-23  8:15 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Saravana,

On Tue, Feb 22, 2011 at 08:17:01PM -0800, Saravana Kannan wrote:
> On 02/22/2011 03:33 PM, Uwe Kleine-K?nig wrote:
> >I had to degrade one WARN_ON to WARN_ON_ONCE in drivers/clk/clk.c to
> >actually make it work.  Otherwise console output results in a warning
> >that results in console output ...
> 
> You won't be able to do mainline the WARN_ON_ONCE because that will
> only warn for the first clock that violates whatever condition it's
> warning about.
I wonder if it is more sensible while the warning is new.  But I don't
care much because I'm going to fix the serial driver before switching.
 
Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
  2011-02-01  9:11 ` Jeremy Kerr
  (?)
@ 2011-03-03  6:40   ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-03-03  6:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

These patches are an attempt to allow platforms to share clock code. At
present, the definitions of 'struct clk' are local to platform code,
which makes allocating and initialising cross-platform clock sources
difficult, and makes it impossible to compile a single image containing
support for two ARM platforms with different struct clks.

The three patches are for the architecture-independent kernel code,
introducing the common clk infrastructure. The changelog for the first
patch includes details about the new clock definitions.

Many thanks to the following for their input:
 * Benjamin Herrenschmidt <benh@kernel.crashing.org>
 * Ben Dooks <ben-linux@fluff.org>
 * Baruch Siach <baruch@tkos.co.il>
 * Russell King <linux@arm.linux.org.uk>
 * Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 * Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
 * Vincent Guittot <vincent.guittot@linaro.org>
 * Sascha Hauer <s.hauer@pengutronix.de>
 * Ryan Mallon <ryan@bluewatersys.com>
 * Colin Cross <ccross@google.com>
 * Jassi Brar <jassisinghbrar@gmail.com>
 * Saravana Kannan <skannan@codeaurora.org>

Cheers,


Jeremy

--
v14:
 * make empty clk_prepare & clk_unprepare static inline

v13:
 * Don't expose __clk_get and clk_put - prototypes in clkdev.c instead
 * Add might_sleep to clk_set_rate
 * Comment clarifications & fixups
 * Remove zero initialisers
 * Fold warnings into main clk.c change

v12:
 * Always refcount, even when enable/prepare ops are NULL
 * Unify prepare & enable count checking
 * Update comments for prepare/unprepare
 * Use spin_{lock,unlock}_irqsave
 * Change clk_put to __clk_put, and use the shared clk_put

v11:
 * add prepare/unprepare for non-atomic switching, document atomicity
 * move to drivers/clk/

v10:
 * comment fixups, from Uwe's review
 * added DEFINE_CLK_FIXED

v9:
 * comment improvements
 * kerneldoc fixups
 * add WARN_ON to clk_disable

v8:
 * add atomic clocks, and locking wrappers
 * expand comments on clk and clk_ops

v7:
 * change CLK_INIT to initialise clk->mutex statically

v6:
 * fixed up references to 'clk_operations' in the changelog

v5:
 * uninline main API, and share definitions with !USE_COMMON_STRUCT_CLK
 * add __clk_get
 * delay mutex init
 * kerneldoc for struct clk

v4:
 * use mutex for enable/disable locking
 * DEFINE_CLK -> INIT_CLK, and pass the clk name for mutex init
 * struct clk_operations -> struct clk_ops

v3:
 * do clock usage refcounting in common code
 * provide sample port

v2:
 * no longer ARM-specific
 * use clk_operations

---
Jeremy Kerr (2):
      Add a common struct clk
      clk: Generic support for fixed-rate clocks


^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 2/2] clk: Generic support for fixed-rate clocks
  2011-03-03  6:40   ` Jeremy Kerr
  (?)
@ 2011-03-03  6:40     ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-03-03  6:40 UTC (permalink / raw)
  To: linux-arm-kernel

Since most platforms will need a fixed-rate clock, add one. This will
also serve as a basic example of an implementation of struct clk.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/clk.c   |   14 ++++++++++++++
 include/linux/clk.h |   16 ++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0bc9c6f..0da0bb9 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -130,3 +130,17 @@ void __clk_put(struct clk *clk)
 	if (clk->ops->put)
 		clk->ops->put(clk);
 }
+
+/* clk_fixed support */
+
+#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
+
+static unsigned long clk_fixed_get_rate(struct clk *clk)
+{
+	return to_clk_fixed(clk)->rate;
+}
+
+struct clk_ops clk_fixed_ops = {
+	.get_rate = clk_fixed_get_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 7b406bd..d2f0db0 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -155,6 +155,22 @@ static inline void clk_common_init(struct clk *clk)
 	mutex_init(&clk->prepare_lock);
 }
 
+/* Simple fixed-rate clock */
+struct clk_fixed {
+	struct clk	clk;
+	unsigned long	rate;
+};
+
+extern struct clk_ops clk_fixed_ops;
+
+#define INIT_CLK_FIXED(name, r) { \
+	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
+	.rate = (r) \
+}
+
+#define DEFINE_CLK_FIXED(name, r) \
+	struct clk_fixed name = INIT_CLK_FIXED(name, r)
+
 #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [PATCH 1/2] Add a common struct clk
  2011-03-03  6:40   ` Jeremy Kerr
  (?)
@ 2011-03-03  6:40     ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-03-03  6:40 UTC (permalink / raw)
  To: linux-arm-kernel

We currently have ~21 definitions of struct clk in the ARM architecture,
each defined on a per-platform basis. This makes it difficult to define
platform- (or architecture-) independent clock sources without making
assumptions about struct clk, and impossible to compile two
platforms with different struct clks into a single image.

This change is an effort to unify struct clk where possible, by defining
a common struct clk, containing a set of clock operations. Different
clock implementations can set their own operations, and have a standard
interface for generic code. The callback interface is exposed to the
kernel proper, while the clock implementations only need to be seen by
the platform internals.

This allows us to share clock code among platforms, and makes it
possible to dynamically create clock devices in platform-independent
code.

Platforms can enable the generic struct clock through
CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
consists of a common struct clk:

struct clk {
	const struct clk_ops	*ops;
	unsigned int		enable_count;
	unsigned int		prepare_count;
	spinlock_t		enable_lock;
	struct mutex		prepare_lock;
};

And a set of clock operations (defined per type of clock):

struct clk_ops {
	int             (*enable)(struct clk *);
	void            (*disable)(struct clk *);
	unsigned long   (*get_rate)(struct clk *);
	[...]
};

To define a hardware-specific clock, machine code can "subclass" the
struct clock into a new struct (adding any device-specific data), and
provide a set of operations:

struct clk_foo {
	struct clk	clk;
	void __iomem	*some_register;
};

struct clk_ops clk_foo_ops = {
	.get_rate = clk_foo_get_rate,
};

The common clock definitions are based on a development patch from Ben
Herrenschmidt <benh@kernel.crashing.org>.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/Kconfig  |    3 
 drivers/clk/Makefile |    1 
 drivers/clk/clk.c    |  132 ++++++++++++++++++++++++++++++++++
 drivers/clk/clkdev.c |    7 +
 include/linux/clk.h  |  164 ++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 298 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 4168c88..6e3ae54 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -2,3 +2,6 @@
 config CLKDEV_LOOKUP
 	bool
 	select HAVE_CLK
+
+config USE_COMMON_STRUCT_CLK
+	bool
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 07613fa..a1a06d3 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,2 +1,3 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
+obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
new file mode 100644
index 0000000..0bc9c6f
--- /dev/null
+++ b/drivers/clk/clk.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+
+int clk_prepare(struct clk *clk)
+{
+	int ret = 0;
+
+	mutex_lock(&clk->prepare_lock);
+	if (clk->prepare_count = 0 && clk->ops->prepare)
+		ret = clk->ops->prepare(clk);
+
+	if (!ret)
+		clk->prepare_count++;
+	mutex_unlock(&clk->prepare_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_prepare);
+
+void clk_unprepare(struct clk *clk)
+{
+	mutex_lock(&clk->prepare_lock);
+
+	WARN_ON(clk->prepare_count = 0);
+
+	if (--clk->prepare_count = 0 && clk->ops->unprepare) {
+		WARN_ON(clk->enable_count != 0);
+		clk->ops->unprepare(clk);
+	}
+
+	mutex_unlock(&clk->prepare_lock);
+}
+EXPORT_SYMBOL_GPL(clk_unprepare);
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	WARN_ON(clk->prepare_count = 0);
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+	if (clk->enable_count = 0 && clk->ops->enable)
+		ret = clk->ops->enable(clk);
+
+	if (!ret)
+		clk->enable_count++;
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+
+	WARN_ON(clk->enable_count = 0);
+
+	if (!--clk->enable_count = 0 && clk->ops->disable)
+		clk->ops->disable(clk);
+
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk->ops->get_rate)
+		return clk->ops->get_rate(clk);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->round_rate)
+		return clk->ops->round_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	might_sleep();
+
+	if (clk->ops->set_rate)
+		return clk->ops->set_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (clk->ops->set_parent)
+		return clk->ops->set_parent(clk, parent);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	if (clk->ops->get_parent)
+		return clk->ops->get_parent(clk);
+	return ERR_PTR(-ENOSYS);
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
+
+int __clk_get(struct clk *clk)
+{
+	if (clk->ops->get)
+		return clk->ops->get(clk);
+	return 1;
+}
+
+void __clk_put(struct clk *clk)
+{
+	if (clk->ops->put)
+		clk->ops->put(clk);
+}
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 0fc0a79..a7999d2 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -23,6 +23,13 @@
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 
+/* For USE_COMMON_STRUCT_CLK, these are provided in clk.c, but not exported
+ * through other headers; we don't want them used anywhere but here. */
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+extern int __clk_get(struct clk *clk);
+extern void __clk_put(struct clk *clk);
+#endif
+
 /*
  * Find the correct struct clk for the device and connection ID.
  * We do slightly fuzzy matching here:
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1d37f42..7b406bd 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2004 ARM Limited.
  *  Written by Deep Blue Solutions Limited.
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,18 +12,168 @@
 #ifndef __LINUX_CLK_H
 #define __LINUX_CLK_H
 
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
 struct device;
 
-/*
- * The base API.
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+
+/* If we're using the common struct clk, we define the base clk object here */
+
+/**
+ * struct clk - hardware independent clock structure
+ * @ops:		implementation-specific ops for this clock
+ * @enable_count:	count of clk_enable() calls active on this clock
+ * @enable_lock:	lock for atomic enable
+ * @prepare_count:	count of clk_prepare() calls active on this clock
+ * @prepare_lock:	lock for sleepable prepare
+ *
+ * The base clock object, used by drivers for hardware-independent manipulation
+ * of clock lines. This will be 'subclassed' by device-specific implementations,
+ * which add device-specific data to struct clk. For example:
+ *
+ *  struct clk_foo {
+ *      struct clk;
+ *      [device specific fields]
+ *  };
+ *
+ * The clock driver code will manage the device-specific data, and pass
+ * clk_foo.clk to the common clock code. The clock driver will be called
+ * through the @ops callbacks.
+ *
+ * The @enable_lock and @prepare_lock members are used to serialise accesses
+ * to the ops->enable and ops->prepare functions (and the corresponding
+ * ops->disable and ops->unprepare functions).
  */
+struct clk {
+	const struct clk_ops	*ops;
+	unsigned int		enable_count;
+	unsigned int		prepare_count;
+	spinlock_t		enable_lock;
+	struct mutex		prepare_lock;
+};
 
+/* static initialiser for clocks. */
+#define INIT_CLK(name, o) {						\
+	.ops		= &o,						\
+	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
+	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
+}
+
+/**
+ * struct clk_ops -  Callback operations for clocks; these are to be provided
+ * by the clock implementation, and will be called by drivers through the clk_*
+ * API.
+ *
+ * @prepare:	Prepare the clock for enabling. This must not return until
+ *		the clock is fully prepared, and it's safe to call clk_enable.
+ *		This callback is intended to allow clock implementations to
+ *		do any initialisation that may sleep. Called with
+ *		clk->prepare_lock held.
+ *
+ * @unprepare:	Release the clock from its prepared state. This will typically
+ *		undo any work done in the @prepare callback. Called with
+ *		clk->prepare_lock held.
+ *
+ * @enable:	Enable the clock atomically. This must not return until the
+ *		clock is generating a valid clock signal, usable by consumer
+ *		devices. Called with clk->enable_lock held. This function
+ *		must not sleep.
+ *
+ * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
+ *		This function must not sleep.
+ *
+ * @get:	Called by the core clock code when a device driver acquires a
+ *		clock via clk_get(). Optional.
+ *
+ * @put:	Called by the core clock code when a devices driver releases a
+ *		clock via clk_put(). Optional.
+ *
+ * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
+ * implementations to split any work between atomic (enable) and sleepable
+ * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
+ * should be done in clk_prepare. Switching that will not sleep should be done
+ * in clk_enable.
+ *
+ * Typically, drivers will call clk_prepare when a clock may be needed later
+ * (eg. when a device is opened), and clk_enable when the clock is actually
+ * required (eg. from an interrupt). Note that clk_prepare *must* have been
+ * called before clk_enable.
+ *
+ * For other callbacks, see the corresponding clk_* functions. Parameters and
+ * return values are passed directly from/to these API functions, or
+ * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
+ * is NULL, see drivers/clk/clk.c for implementation details. All are optional.
+ */
+struct clk_ops {
+	int		(*prepare)(struct clk *);
+	void		(*unprepare)(struct clk *);
+	int		(*enable)(struct clk *);
+	void		(*disable)(struct clk *);
+	int		(*get)(struct clk *);
+	void		(*put)(struct clk *);
+	unsigned long	(*get_rate)(struct clk *);
+	long		(*round_rate)(struct clk *, unsigned long);
+	int		(*set_rate)(struct clk *, unsigned long);
+	int		(*set_parent)(struct clk *, struct clk *);
+	struct clk *	(*get_parent)(struct clk *);
+};
+
+/**
+ * clk_prepare - prepare clock for atomic enabling.
+ *
+ * @clk: The clock to prepare
+ *
+ * Do any possibly sleeping initialisation on @clk, allowing the clock to be
+ * later enabled atomically (via clk_enable). This function may sleep.
+ */
+int clk_prepare(struct clk *clk);
+
+/**
+ * clk_unprepare - release clock from prepared state
+ *
+ * @clk: The clock to release
+ *
+ * Do any (possibly sleeping) cleanup on clk. This function may sleep.
+ */
+void clk_unprepare(struct clk *clk);
+
+/**
+ * clk_common_init - initialise a clock for driver usage
+ *
+ * @clk: The clock to initialise
+ *
+ * Used for runtime intialization of clocks; you don't need to call this
+ * if your clock has been (statically) initialized with INIT_CLK.
+ */
+static inline void clk_common_init(struct clk *clk)
+{
+	clk->enable_count = clk->prepare_count = 0;
+	spin_lock_init(&clk->enable_lock);
+	mutex_init(&clk->prepare_lock);
+}
+
+#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*
- * struct clk - an machine class defined object / cookie.
+ * Global clock object, actual structure is declared per-machine
  */
 struct clk;
 
+static inline void clk_common_init(struct clk *clk) { }
+
+/*
+ * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
+ * requirements for clk_enable/clk_disable, so the prepare and unprepare
+ * functions are no-ops
+ */
+static inline int clk_prepare(struct clk *clk) { return 0; }
+static inline void clk_unprepare(struct clk *clk) { }
+
+#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
+
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
  * @dev: device for clock "consumer"
@@ -67,6 +218,7 @@ void clk_disable(struct clk *clk);
 /**
  * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *		  This is only valid once the clock source has been enabled.
+ *		  Returns zero if the clock rate is unknown.
  * @clk: clock source
  */
 unsigned long clk_get_rate(struct clk *clk);
@@ -83,12 +235,6 @@ unsigned long clk_get_rate(struct clk *clk);
  */
 void clk_put(struct clk *clk);
 
-
-/*
- * The remaining APIs are optional for machine class support.
- */
-
-
 /**
  * clk_round_rate - adjust a rate to the exact rate a clock can provide
  * @clk: clock source

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [PATCH 2/2] clk: Generic support for fixed-rate clocks
@ 2011-03-03  6:40     ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-03-03  6:40 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Uwe Kleine-König, Sascha Hauer,
	Paul Mundt, Saravana Kannan, Ben Dooks, Jeremy Kerr,
	Russell King

Since most platforms will need a fixed-rate clock, add one. This will
also serve as a basic example of an implementation of struct clk.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/clk.c   |   14 ++++++++++++++
 include/linux/clk.h |   16 ++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0bc9c6f..0da0bb9 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -130,3 +130,17 @@ void __clk_put(struct clk *clk)
 	if (clk->ops->put)
 		clk->ops->put(clk);
 }
+
+/* clk_fixed support */
+
+#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
+
+static unsigned long clk_fixed_get_rate(struct clk *clk)
+{
+	return to_clk_fixed(clk)->rate;
+}
+
+struct clk_ops clk_fixed_ops = {
+	.get_rate = clk_fixed_get_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 7b406bd..d2f0db0 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -155,6 +155,22 @@ static inline void clk_common_init(struct clk *clk)
 	mutex_init(&clk->prepare_lock);
 }
 
+/* Simple fixed-rate clock */
+struct clk_fixed {
+	struct clk	clk;
+	unsigned long	rate;
+};
+
+extern struct clk_ops clk_fixed_ops;
+
+#define INIT_CLK_FIXED(name, r) { \
+	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
+	.rate = (r) \
+}
+
+#define DEFINE_CLK_FIXED(name, r) \
+	struct clk_fixed name = INIT_CLK_FIXED(name, r)
+
 #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-03-03  6:40   ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-03-03  6:40 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Uwe Kleine-König, Sascha Hauer,
	Paul Mundt, Saravana Kannan, Ben Dooks, Jeremy Kerr,
	Russell King

Hi all,

These patches are an attempt to allow platforms to share clock code. At
present, the definitions of 'struct clk' are local to platform code,
which makes allocating and initialising cross-platform clock sources
difficult, and makes it impossible to compile a single image containing
support for two ARM platforms with different struct clks.

The three patches are for the architecture-independent kernel code,
introducing the common clk infrastructure. The changelog for the first
patch includes details about the new clock definitions.

Many thanks to the following for their input:
 * Benjamin Herrenschmidt <benh@kernel.crashing.org>
 * Ben Dooks <ben-linux@fluff.org>
 * Baruch Siach <baruch@tkos.co.il>
 * Russell King <linux@arm.linux.org.uk>
 * Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 * Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
 * Vincent Guittot <vincent.guittot@linaro.org>
 * Sascha Hauer <s.hauer@pengutronix.de>
 * Ryan Mallon <ryan@bluewatersys.com>
 * Colin Cross <ccross@google.com>
 * Jassi Brar <jassisinghbrar@gmail.com>
 * Saravana Kannan <skannan@codeaurora.org>

Cheers,


Jeremy

--
v14:
 * make empty clk_prepare & clk_unprepare static inline

v13:
 * Don't expose __clk_get and clk_put - prototypes in clkdev.c instead
 * Add might_sleep to clk_set_rate
 * Comment clarifications & fixups
 * Remove zero initialisers
 * Fold warnings into main clk.c change

v12:
 * Always refcount, even when enable/prepare ops are NULL
 * Unify prepare & enable count checking
 * Update comments for prepare/unprepare
 * Use spin_{lock,unlock}_irqsave
 * Change clk_put to __clk_put, and use the shared clk_put

v11:
 * add prepare/unprepare for non-atomic switching, document atomicity
 * move to drivers/clk/

v10:
 * comment fixups, from Uwe's review
 * added DEFINE_CLK_FIXED

v9:
 * comment improvements
 * kerneldoc fixups
 * add WARN_ON to clk_disable

v8:
 * add atomic clocks, and locking wrappers
 * expand comments on clk and clk_ops

v7:
 * change CLK_INIT to initialise clk->mutex statically

v6:
 * fixed up references to 'clk_operations' in the changelog

v5:
 * uninline main API, and share definitions with !USE_COMMON_STRUCT_CLK
 * add __clk_get
 * delay mutex init
 * kerneldoc for struct clk

v4:
 * use mutex for enable/disable locking
 * DEFINE_CLK -> INIT_CLK, and pass the clk name for mutex init
 * struct clk_operations -> struct clk_ops

v3:
 * do clock usage refcounting in common code
 * provide sample port

v2:
 * no longer ARM-specific
 * use clk_operations

---
Jeremy Kerr (2):
      Add a common struct clk
      clk: Generic support for fixed-rate clocks


^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 1/2] Add a common struct clk
@ 2011-03-03  6:40     ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-03-03  6:40 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel
  Cc: Nicolas Pitre, Dima Zavin, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Ben Herrenschmidt, Uwe Kleine-König, Sascha Hauer,
	Paul Mundt, Saravana Kannan, Ben Dooks, Jeremy Kerr,
	Russell King

We currently have ~21 definitions of struct clk in the ARM architecture,
each defined on a per-platform basis. This makes it difficult to define
platform- (or architecture-) independent clock sources without making
assumptions about struct clk, and impossible to compile two
platforms with different struct clks into a single image.

This change is an effort to unify struct clk where possible, by defining
a common struct clk, containing a set of clock operations. Different
clock implementations can set their own operations, and have a standard
interface for generic code. The callback interface is exposed to the
kernel proper, while the clock implementations only need to be seen by
the platform internals.

This allows us to share clock code among platforms, and makes it
possible to dynamically create clock devices in platform-independent
code.

Platforms can enable the generic struct clock through
CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
consists of a common struct clk:

struct clk {
	const struct clk_ops	*ops;
	unsigned int		enable_count;
	unsigned int		prepare_count;
	spinlock_t		enable_lock;
	struct mutex		prepare_lock;
};

And a set of clock operations (defined per type of clock):

struct clk_ops {
	int             (*enable)(struct clk *);
	void            (*disable)(struct clk *);
	unsigned long   (*get_rate)(struct clk *);
	[...]
};

To define a hardware-specific clock, machine code can "subclass" the
struct clock into a new struct (adding any device-specific data), and
provide a set of operations:

struct clk_foo {
	struct clk	clk;
	void __iomem	*some_register;
};

struct clk_ops clk_foo_ops = {
	.get_rate = clk_foo_get_rate,
};

The common clock definitions are based on a development patch from Ben
Herrenschmidt <benh@kernel.crashing.org>.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/Kconfig  |    3 
 drivers/clk/Makefile |    1 
 drivers/clk/clk.c    |  132 ++++++++++++++++++++++++++++++++++
 drivers/clk/clkdev.c |    7 +
 include/linux/clk.h  |  164 ++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 298 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 4168c88..6e3ae54 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -2,3 +2,6 @@
 config CLKDEV_LOOKUP
 	bool
 	select HAVE_CLK
+
+config USE_COMMON_STRUCT_CLK
+	bool
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 07613fa..a1a06d3 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,2 +1,3 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
+obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
new file mode 100644
index 0000000..0bc9c6f
--- /dev/null
+++ b/drivers/clk/clk.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+
+int clk_prepare(struct clk *clk)
+{
+	int ret = 0;
+
+	mutex_lock(&clk->prepare_lock);
+	if (clk->prepare_count == 0 && clk->ops->prepare)
+		ret = clk->ops->prepare(clk);
+
+	if (!ret)
+		clk->prepare_count++;
+	mutex_unlock(&clk->prepare_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_prepare);
+
+void clk_unprepare(struct clk *clk)
+{
+	mutex_lock(&clk->prepare_lock);
+
+	WARN_ON(clk->prepare_count == 0);
+
+	if (--clk->prepare_count == 0 && clk->ops->unprepare) {
+		WARN_ON(clk->enable_count != 0);
+		clk->ops->unprepare(clk);
+	}
+
+	mutex_unlock(&clk->prepare_lock);
+}
+EXPORT_SYMBOL_GPL(clk_unprepare);
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	WARN_ON(clk->prepare_count == 0);
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+	if (clk->enable_count == 0 && clk->ops->enable)
+		ret = clk->ops->enable(clk);
+
+	if (!ret)
+		clk->enable_count++;
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+
+	WARN_ON(clk->enable_count == 0);
+
+	if (!--clk->enable_count == 0 && clk->ops->disable)
+		clk->ops->disable(clk);
+
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk->ops->get_rate)
+		return clk->ops->get_rate(clk);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->round_rate)
+		return clk->ops->round_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	might_sleep();
+
+	if (clk->ops->set_rate)
+		return clk->ops->set_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (clk->ops->set_parent)
+		return clk->ops->set_parent(clk, parent);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	if (clk->ops->get_parent)
+		return clk->ops->get_parent(clk);
+	return ERR_PTR(-ENOSYS);
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
+
+int __clk_get(struct clk *clk)
+{
+	if (clk->ops->get)
+		return clk->ops->get(clk);
+	return 1;
+}
+
+void __clk_put(struct clk *clk)
+{
+	if (clk->ops->put)
+		clk->ops->put(clk);
+}
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 0fc0a79..a7999d2 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -23,6 +23,13 @@
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 
+/* For USE_COMMON_STRUCT_CLK, these are provided in clk.c, but not exported
+ * through other headers; we don't want them used anywhere but here. */
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+extern int __clk_get(struct clk *clk);
+extern void __clk_put(struct clk *clk);
+#endif
+
 /*
  * Find the correct struct clk for the device and connection ID.
  * We do slightly fuzzy matching here:
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1d37f42..7b406bd 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2004 ARM Limited.
  *  Written by Deep Blue Solutions Limited.
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,18 +12,168 @@
 #ifndef __LINUX_CLK_H
 #define __LINUX_CLK_H
 
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
 struct device;
 
-/*
- * The base API.
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+
+/* If we're using the common struct clk, we define the base clk object here */
+
+/**
+ * struct clk - hardware independent clock structure
+ * @ops:		implementation-specific ops for this clock
+ * @enable_count:	count of clk_enable() calls active on this clock
+ * @enable_lock:	lock for atomic enable
+ * @prepare_count:	count of clk_prepare() calls active on this clock
+ * @prepare_lock:	lock for sleepable prepare
+ *
+ * The base clock object, used by drivers for hardware-independent manipulation
+ * of clock lines. This will be 'subclassed' by device-specific implementations,
+ * which add device-specific data to struct clk. For example:
+ *
+ *  struct clk_foo {
+ *      struct clk;
+ *      [device specific fields]
+ *  };
+ *
+ * The clock driver code will manage the device-specific data, and pass
+ * clk_foo.clk to the common clock code. The clock driver will be called
+ * through the @ops callbacks.
+ *
+ * The @enable_lock and @prepare_lock members are used to serialise accesses
+ * to the ops->enable and ops->prepare functions (and the corresponding
+ * ops->disable and ops->unprepare functions).
  */
+struct clk {
+	const struct clk_ops	*ops;
+	unsigned int		enable_count;
+	unsigned int		prepare_count;
+	spinlock_t		enable_lock;
+	struct mutex		prepare_lock;
+};
 
+/* static initialiser for clocks. */
+#define INIT_CLK(name, o) {						\
+	.ops		= &o,						\
+	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
+	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
+}
+
+/**
+ * struct clk_ops -  Callback operations for clocks; these are to be provided
+ * by the clock implementation, and will be called by drivers through the clk_*
+ * API.
+ *
+ * @prepare:	Prepare the clock for enabling. This must not return until
+ *		the clock is fully prepared, and it's safe to call clk_enable.
+ *		This callback is intended to allow clock implementations to
+ *		do any initialisation that may sleep. Called with
+ *		clk->prepare_lock held.
+ *
+ * @unprepare:	Release the clock from its prepared state. This will typically
+ *		undo any work done in the @prepare callback. Called with
+ *		clk->prepare_lock held.
+ *
+ * @enable:	Enable the clock atomically. This must not return until the
+ *		clock is generating a valid clock signal, usable by consumer
+ *		devices. Called with clk->enable_lock held. This function
+ *		must not sleep.
+ *
+ * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
+ *		This function must not sleep.
+ *
+ * @get:	Called by the core clock code when a device driver acquires a
+ *		clock via clk_get(). Optional.
+ *
+ * @put:	Called by the core clock code when a devices driver releases a
+ *		clock via clk_put(). Optional.
+ *
+ * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
+ * implementations to split any work between atomic (enable) and sleepable
+ * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
+ * should be done in clk_prepare. Switching that will not sleep should be done
+ * in clk_enable.
+ *
+ * Typically, drivers will call clk_prepare when a clock may be needed later
+ * (eg. when a device is opened), and clk_enable when the clock is actually
+ * required (eg. from an interrupt). Note that clk_prepare *must* have been
+ * called before clk_enable.
+ *
+ * For other callbacks, see the corresponding clk_* functions. Parameters and
+ * return values are passed directly from/to these API functions, or
+ * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
+ * is NULL, see drivers/clk/clk.c for implementation details. All are optional.
+ */
+struct clk_ops {
+	int		(*prepare)(struct clk *);
+	void		(*unprepare)(struct clk *);
+	int		(*enable)(struct clk *);
+	void		(*disable)(struct clk *);
+	int		(*get)(struct clk *);
+	void		(*put)(struct clk *);
+	unsigned long	(*get_rate)(struct clk *);
+	long		(*round_rate)(struct clk *, unsigned long);
+	int		(*set_rate)(struct clk *, unsigned long);
+	int		(*set_parent)(struct clk *, struct clk *);
+	struct clk *	(*get_parent)(struct clk *);
+};
+
+/**
+ * clk_prepare - prepare clock for atomic enabling.
+ *
+ * @clk: The clock to prepare
+ *
+ * Do any possibly sleeping initialisation on @clk, allowing the clock to be
+ * later enabled atomically (via clk_enable). This function may sleep.
+ */
+int clk_prepare(struct clk *clk);
+
+/**
+ * clk_unprepare - release clock from prepared state
+ *
+ * @clk: The clock to release
+ *
+ * Do any (possibly sleeping) cleanup on clk. This function may sleep.
+ */
+void clk_unprepare(struct clk *clk);
+
+/**
+ * clk_common_init - initialise a clock for driver usage
+ *
+ * @clk: The clock to initialise
+ *
+ * Used for runtime intialization of clocks; you don't need to call this
+ * if your clock has been (statically) initialized with INIT_CLK.
+ */
+static inline void clk_common_init(struct clk *clk)
+{
+	clk->enable_count = clk->prepare_count = 0;
+	spin_lock_init(&clk->enable_lock);
+	mutex_init(&clk->prepare_lock);
+}
+
+#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*
- * struct clk - an machine class defined object / cookie.
+ * Global clock object, actual structure is declared per-machine
  */
 struct clk;
 
+static inline void clk_common_init(struct clk *clk) { }
+
+/*
+ * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
+ * requirements for clk_enable/clk_disable, so the prepare and unprepare
+ * functions are no-ops
+ */
+static inline int clk_prepare(struct clk *clk) { return 0; }
+static inline void clk_unprepare(struct clk *clk) { }
+
+#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
+
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
  * @dev: device for clock "consumer"
@@ -67,6 +218,7 @@ void clk_disable(struct clk *clk);
 /**
  * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *		  This is only valid once the clock source has been enabled.
+ *		  Returns zero if the clock rate is unknown.
  * @clk: clock source
  */
 unsigned long clk_get_rate(struct clk *clk);
@@ -83,12 +235,6 @@ unsigned long clk_get_rate(struct clk *clk);
  */
 void clk_put(struct clk *clk);
 
-
-/*
- * The remaining APIs are optional for machine class support.
- */
-
-
 /**
  * clk_round_rate - adjust a rate to the exact rate a clock can provide
  * @clk: clock source

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [PATCH 2/2] clk: Generic support for fixed-rate clocks
@ 2011-03-03  6:40     ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-03-03  6:40 UTC (permalink / raw)
  To: linux-arm-kernel

Since most platforms will need a fixed-rate clock, add one. This will
also serve as a basic example of an implementation of struct clk.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/clk.c   |   14 ++++++++++++++
 include/linux/clk.h |   16 ++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0bc9c6f..0da0bb9 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -130,3 +130,17 @@ void __clk_put(struct clk *clk)
 	if (clk->ops->put)
 		clk->ops->put(clk);
 }
+
+/* clk_fixed support */
+
+#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
+
+static unsigned long clk_fixed_get_rate(struct clk *clk)
+{
+	return to_clk_fixed(clk)->rate;
+}
+
+struct clk_ops clk_fixed_ops = {
+	.get_rate = clk_fixed_get_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 7b406bd..d2f0db0 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -155,6 +155,22 @@ static inline void clk_common_init(struct clk *clk)
 	mutex_init(&clk->prepare_lock);
 }
 
+/* Simple fixed-rate clock */
+struct clk_fixed {
+	struct clk	clk;
+	unsigned long	rate;
+};
+
+extern struct clk_ops clk_fixed_ops;
+
+#define INIT_CLK_FIXED(name, r) { \
+	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
+	.rate = (r) \
+}
+
+#define DEFINE_CLK_FIXED(name, r) \
+	struct clk_fixed name = INIT_CLK_FIXED(name, r)
+
 #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [PATCH 1/2] Add a common struct clk
@ 2011-03-03  6:40     ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-03-03  6:40 UTC (permalink / raw)
  To: linux-arm-kernel

We currently have ~21 definitions of struct clk in the ARM architecture,
each defined on a per-platform basis. This makes it difficult to define
platform- (or architecture-) independent clock sources without making
assumptions about struct clk, and impossible to compile two
platforms with different struct clks into a single image.

This change is an effort to unify struct clk where possible, by defining
a common struct clk, containing a set of clock operations. Different
clock implementations can set their own operations, and have a standard
interface for generic code. The callback interface is exposed to the
kernel proper, while the clock implementations only need to be seen by
the platform internals.

This allows us to share clock code among platforms, and makes it
possible to dynamically create clock devices in platform-independent
code.

Platforms can enable the generic struct clock through
CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
consists of a common struct clk:

struct clk {
	const struct clk_ops	*ops;
	unsigned int		enable_count;
	unsigned int		prepare_count;
	spinlock_t		enable_lock;
	struct mutex		prepare_lock;
};

And a set of clock operations (defined per type of clock):

struct clk_ops {
	int             (*enable)(struct clk *);
	void            (*disable)(struct clk *);
	unsigned long   (*get_rate)(struct clk *);
	[...]
};

To define a hardware-specific clock, machine code can "subclass" the
struct clock into a new struct (adding any device-specific data), and
provide a set of operations:

struct clk_foo {
	struct clk	clk;
	void __iomem	*some_register;
};

struct clk_ops clk_foo_ops = {
	.get_rate = clk_foo_get_rate,
};

The common clock definitions are based on a development patch from Ben
Herrenschmidt <benh@kernel.crashing.org>.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>

---
 drivers/clk/Kconfig  |    3 
 drivers/clk/Makefile |    1 
 drivers/clk/clk.c    |  132 ++++++++++++++++++++++++++++++++++
 drivers/clk/clkdev.c |    7 +
 include/linux/clk.h  |  164 ++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 298 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 4168c88..6e3ae54 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -2,3 +2,6 @@
 config CLKDEV_LOOKUP
 	bool
 	select HAVE_CLK
+
+config USE_COMMON_STRUCT_CLK
+	bool
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 07613fa..a1a06d3 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,2 +1,3 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
+obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
new file mode 100644
index 0000000..0bc9c6f
--- /dev/null
+++ b/drivers/clk/clk.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+
+int clk_prepare(struct clk *clk)
+{
+	int ret = 0;
+
+	mutex_lock(&clk->prepare_lock);
+	if (clk->prepare_count == 0 && clk->ops->prepare)
+		ret = clk->ops->prepare(clk);
+
+	if (!ret)
+		clk->prepare_count++;
+	mutex_unlock(&clk->prepare_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_prepare);
+
+void clk_unprepare(struct clk *clk)
+{
+	mutex_lock(&clk->prepare_lock);
+
+	WARN_ON(clk->prepare_count == 0);
+
+	if (--clk->prepare_count == 0 && clk->ops->unprepare) {
+		WARN_ON(clk->enable_count != 0);
+		clk->ops->unprepare(clk);
+	}
+
+	mutex_unlock(&clk->prepare_lock);
+}
+EXPORT_SYMBOL_GPL(clk_unprepare);
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	WARN_ON(clk->prepare_count == 0);
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+	if (clk->enable_count == 0 && clk->ops->enable)
+		ret = clk->ops->enable(clk);
+
+	if (!ret)
+		clk->enable_count++;
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+
+	WARN_ON(clk->enable_count == 0);
+
+	if (!--clk->enable_count == 0 && clk->ops->disable)
+		clk->ops->disable(clk);
+
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk->ops->get_rate)
+		return clk->ops->get_rate(clk);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->round_rate)
+		return clk->ops->round_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	might_sleep();
+
+	if (clk->ops->set_rate)
+		return clk->ops->set_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (clk->ops->set_parent)
+		return clk->ops->set_parent(clk, parent);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	if (clk->ops->get_parent)
+		return clk->ops->get_parent(clk);
+	return ERR_PTR(-ENOSYS);
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
+
+int __clk_get(struct clk *clk)
+{
+	if (clk->ops->get)
+		return clk->ops->get(clk);
+	return 1;
+}
+
+void __clk_put(struct clk *clk)
+{
+	if (clk->ops->put)
+		clk->ops->put(clk);
+}
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 0fc0a79..a7999d2 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -23,6 +23,13 @@
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 
+/* For USE_COMMON_STRUCT_CLK, these are provided in clk.c, but not exported
+ * through other headers; we don't want them used anywhere but here. */
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+extern int __clk_get(struct clk *clk);
+extern void __clk_put(struct clk *clk);
+#endif
+
 /*
  * Find the correct struct clk for the device and connection ID.
  * We do slightly fuzzy matching here:
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1d37f42..7b406bd 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2004 ARM Limited.
  *  Written by Deep Blue Solutions Limited.
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,18 +12,168 @@
 #ifndef __LINUX_CLK_H
 #define __LINUX_CLK_H
 
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
 struct device;
 
-/*
- * The base API.
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+
+/* If we're using the common struct clk, we define the base clk object here */
+
+/**
+ * struct clk - hardware independent clock structure
+ * @ops:		implementation-specific ops for this clock
+ * @enable_count:	count of clk_enable() calls active on this clock
+ * @enable_lock:	lock for atomic enable
+ * @prepare_count:	count of clk_prepare() calls active on this clock
+ * @prepare_lock:	lock for sleepable prepare
+ *
+ * The base clock object, used by drivers for hardware-independent manipulation
+ * of clock lines. This will be 'subclassed' by device-specific implementations,
+ * which add device-specific data to struct clk. For example:
+ *
+ *  struct clk_foo {
+ *      struct clk;
+ *      [device specific fields]
+ *  };
+ *
+ * The clock driver code will manage the device-specific data, and pass
+ * clk_foo.clk to the common clock code. The clock driver will be called
+ * through the @ops callbacks.
+ *
+ * The @enable_lock and @prepare_lock members are used to serialise accesses
+ * to the ops->enable and ops->prepare functions (and the corresponding
+ * ops->disable and ops->unprepare functions).
  */
+struct clk {
+	const struct clk_ops	*ops;
+	unsigned int		enable_count;
+	unsigned int		prepare_count;
+	spinlock_t		enable_lock;
+	struct mutex		prepare_lock;
+};
 
+/* static initialiser for clocks. */
+#define INIT_CLK(name, o) {						\
+	.ops		= &o,						\
+	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
+	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
+}
+
+/**
+ * struct clk_ops -  Callback operations for clocks; these are to be provided
+ * by the clock implementation, and will be called by drivers through the clk_*
+ * API.
+ *
+ * @prepare:	Prepare the clock for enabling. This must not return until
+ *		the clock is fully prepared, and it's safe to call clk_enable.
+ *		This callback is intended to allow clock implementations to
+ *		do any initialisation that may sleep. Called with
+ *		clk->prepare_lock held.
+ *
+ * @unprepare:	Release the clock from its prepared state. This will typically
+ *		undo any work done in the @prepare callback. Called with
+ *		clk->prepare_lock held.
+ *
+ * @enable:	Enable the clock atomically. This must not return until the
+ *		clock is generating a valid clock signal, usable by consumer
+ *		devices. Called with clk->enable_lock held. This function
+ *		must not sleep.
+ *
+ * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
+ *		This function must not sleep.
+ *
+ * @get:	Called by the core clock code when a device driver acquires a
+ *		clock via clk_get(). Optional.
+ *
+ * @put:	Called by the core clock code when a devices driver releases a
+ *		clock via clk_put(). Optional.
+ *
+ * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
+ * implementations to split any work between atomic (enable) and sleepable
+ * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
+ * should be done in clk_prepare. Switching that will not sleep should be done
+ * in clk_enable.
+ *
+ * Typically, drivers will call clk_prepare when a clock may be needed later
+ * (eg. when a device is opened), and clk_enable when the clock is actually
+ * required (eg. from an interrupt). Note that clk_prepare *must* have been
+ * called before clk_enable.
+ *
+ * For other callbacks, see the corresponding clk_* functions. Parameters and
+ * return values are passed directly from/to these API functions, or
+ * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
+ * is NULL, see drivers/clk/clk.c for implementation details. All are optional.
+ */
+struct clk_ops {
+	int		(*prepare)(struct clk *);
+	void		(*unprepare)(struct clk *);
+	int		(*enable)(struct clk *);
+	void		(*disable)(struct clk *);
+	int		(*get)(struct clk *);
+	void		(*put)(struct clk *);
+	unsigned long	(*get_rate)(struct clk *);
+	long		(*round_rate)(struct clk *, unsigned long);
+	int		(*set_rate)(struct clk *, unsigned long);
+	int		(*set_parent)(struct clk *, struct clk *);
+	struct clk *	(*get_parent)(struct clk *);
+};
+
+/**
+ * clk_prepare - prepare clock for atomic enabling.
+ *
+ * @clk: The clock to prepare
+ *
+ * Do any possibly sleeping initialisation on @clk, allowing the clock to be
+ * later enabled atomically (via clk_enable). This function may sleep.
+ */
+int clk_prepare(struct clk *clk);
+
+/**
+ * clk_unprepare - release clock from prepared state
+ *
+ * @clk: The clock to release
+ *
+ * Do any (possibly sleeping) cleanup on clk. This function may sleep.
+ */
+void clk_unprepare(struct clk *clk);
+
+/**
+ * clk_common_init - initialise a clock for driver usage
+ *
+ * @clk: The clock to initialise
+ *
+ * Used for runtime intialization of clocks; you don't need to call this
+ * if your clock has been (statically) initialized with INIT_CLK.
+ */
+static inline void clk_common_init(struct clk *clk)
+{
+	clk->enable_count = clk->prepare_count = 0;
+	spin_lock_init(&clk->enable_lock);
+	mutex_init(&clk->prepare_lock);
+}
+
+#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*
- * struct clk - an machine class defined object / cookie.
+ * Global clock object, actual structure is declared per-machine
  */
 struct clk;
 
+static inline void clk_common_init(struct clk *clk) { }
+
+/*
+ * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
+ * requirements for clk_enable/clk_disable, so the prepare and unprepare
+ * functions are no-ops
+ */
+static inline int clk_prepare(struct clk *clk) { return 0; }
+static inline void clk_unprepare(struct clk *clk) { }
+
+#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
+
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
  * @dev: device for clock "consumer"
@@ -67,6 +218,7 @@ void clk_disable(struct clk *clk);
 /**
  * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *		  This is only valid once the clock source has been enabled.
+ *		  Returns zero if the clock rate is unknown.
  * @clk: clock source
  */
 unsigned long clk_get_rate(struct clk *clk);
@@ -83,12 +235,6 @@ unsigned long clk_get_rate(struct clk *clk);
  */
 void clk_put(struct clk *clk);
 
-
-/*
- * The remaining APIs are optional for machine class support.
- */
-
-
 /**
  * clk_round_rate - adjust a rate to the exact rate a clock can provide
  * @clk: clock source

^ permalink raw reply related	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-03-03  6:40   ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-03-03  6:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

These patches are an attempt to allow platforms to share clock code. At
present, the definitions of 'struct clk' are local to platform code,
which makes allocating and initialising cross-platform clock sources
difficult, and makes it impossible to compile a single image containing
support for two ARM platforms with different struct clks.

The three patches are for the architecture-independent kernel code,
introducing the common clk infrastructure. The changelog for the first
patch includes details about the new clock definitions.

Many thanks to the following for their input:
 * Benjamin Herrenschmidt <benh@kernel.crashing.org>
 * Ben Dooks <ben-linux@fluff.org>
 * Baruch Siach <baruch@tkos.co.il>
 * Russell King <linux@arm.linux.org.uk>
 * Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
 * Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
 * Vincent Guittot <vincent.guittot@linaro.org>
 * Sascha Hauer <s.hauer@pengutronix.de>
 * Ryan Mallon <ryan@bluewatersys.com>
 * Colin Cross <ccross@google.com>
 * Jassi Brar <jassisinghbrar@gmail.com>
 * Saravana Kannan <skannan@codeaurora.org>

Cheers,


Jeremy

--
v14:
 * make empty clk_prepare & clk_unprepare static inline

v13:
 * Don't expose __clk_get and clk_put - prototypes in clkdev.c instead
 * Add might_sleep to clk_set_rate
 * Comment clarifications & fixups
 * Remove zero initialisers
 * Fold warnings into main clk.c change

v12:
 * Always refcount, even when enable/prepare ops are NULL
 * Unify prepare & enable count checking
 * Update comments for prepare/unprepare
 * Use spin_{lock,unlock}_irqsave
 * Change clk_put to __clk_put, and use the shared clk_put

v11:
 * add prepare/unprepare for non-atomic switching, document atomicity
 * move to drivers/clk/

v10:
 * comment fixups, from Uwe's review
 * added DEFINE_CLK_FIXED

v9:
 * comment improvements
 * kerneldoc fixups
 * add WARN_ON to clk_disable

v8:
 * add atomic clocks, and locking wrappers
 * expand comments on clk and clk_ops

v7:
 * change CLK_INIT to initialise clk->mutex statically

v6:
 * fixed up references to 'clk_operations' in the changelog

v5:
 * uninline main API, and share definitions with !USE_COMMON_STRUCT_CLK
 * add __clk_get
 * delay mutex init
 * kerneldoc for struct clk

v4:
 * use mutex for enable/disable locking
 * DEFINE_CLK -> INIT_CLK, and pass the clk name for mutex init
 * struct clk_operations -> struct clk_ops

v3:
 * do clock usage refcounting in common code
 * provide sample port

v2:
 * no longer ARM-specific
 * use clk_operations

---
Jeremy Kerr (2):
      Add a common struct clk
      clk: Generic support for fixed-rate clocks

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-03-03  6:40   ` Jeremy Kerr
  (?)
@ 2011-03-14 10:16     ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-03-14 10:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 03, 2011 at 02:40:29PM +0800, Jeremy Kerr wrote:
> Hi all,
> 
> These patches are an attempt to allow platforms to share clock code. At
> present, the definitions of 'struct clk' are local to platform code,
> which makes allocating and initialising cross-platform clock sources
> difficult, and makes it impossible to compile a single image containing
> support for two ARM platforms with different struct clks.
> 
> The three patches are for the architecture-independent kernel code,
> introducing the common clk infrastructure. The changelog for the first
> patch includes details about the new clock definitions.
> 
> Many thanks to the following for their input:
>  * Benjamin Herrenschmidt <benh@kernel.crashing.org>
>  * Ben Dooks <ben-linux@fluff.org>
>  * Baruch Siach <baruch@tkos.co.il>
>  * Russell King <linux@arm.linux.org.uk>
>  * Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
>  * Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
>  * Vincent Guittot <vincent.guittot@linaro.org>
>  * Sascha Hauer <s.hauer@pengutronix.de>
>  * Ryan Mallon <ryan@bluewatersys.com>
>  * Colin Cross <ccross@google.com>
>  * Jassi Brar <jassisinghbrar@gmail.com>
>  * Saravana Kannan <skannan@codeaurora.org>

Tested-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>

who is responsible to take this patch?  Russell?

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-03-14 10:16     ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-03-14 10:16 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, Dima Zavin, Saravana Kannan, Ben Dooks, Russell King

On Thu, Mar 03, 2011 at 02:40:29PM +0800, Jeremy Kerr wrote:
> Hi all,
> 
> These patches are an attempt to allow platforms to share clock code. At
> present, the definitions of 'struct clk' are local to platform code,
> which makes allocating and initialising cross-platform clock sources
> difficult, and makes it impossible to compile a single image containing
> support for two ARM platforms with different struct clks.
> 
> The three patches are for the architecture-independent kernel code,
> introducing the common clk infrastructure. The changelog for the first
> patch includes details about the new clock definitions.
> 
> Many thanks to the following for their input:
>  * Benjamin Herrenschmidt <benh@kernel.crashing.org>
>  * Ben Dooks <ben-linux@fluff.org>
>  * Baruch Siach <baruch@tkos.co.il>
>  * Russell King <linux@arm.linux.org.uk>
>  * Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
>  * Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
>  * Vincent Guittot <vincent.guittot@linaro.org>
>  * Sascha Hauer <s.hauer@pengutronix.de>
>  * Ryan Mallon <ryan@bluewatersys.com>
>  * Colin Cross <ccross@google.com>
>  * Jassi Brar <jassisinghbrar@gmail.com>
>  * Saravana Kannan <skannan@codeaurora.org>

Tested-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>

who is responsible to take this patch?  Russell?

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-03-14 10:16     ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-03-14 10:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 03, 2011 at 02:40:29PM +0800, Jeremy Kerr wrote:
> Hi all,
> 
> These patches are an attempt to allow platforms to share clock code. At
> present, the definitions of 'struct clk' are local to platform code,
> which makes allocating and initialising cross-platform clock sources
> difficult, and makes it impossible to compile a single image containing
> support for two ARM platforms with different struct clks.
> 
> The three patches are for the architecture-independent kernel code,
> introducing the common clk infrastructure. The changelog for the first
> patch includes details about the new clock definitions.
> 
> Many thanks to the following for their input:
>  * Benjamin Herrenschmidt <benh@kernel.crashing.org>
>  * Ben Dooks <ben-linux@fluff.org>
>  * Baruch Siach <baruch@tkos.co.il>
>  * Russell King <linux@arm.linux.org.uk>
>  * Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
>  * Lorenzo Pieralisi <Lorenzo.Pieralisi@arm.com>
>  * Vincent Guittot <vincent.guittot@linaro.org>
>  * Sascha Hauer <s.hauer@pengutronix.de>
>  * Ryan Mallon <ryan@bluewatersys.com>
>  * Colin Cross <ccross@google.com>
>  * Jassi Brar <jassisinghbrar@gmail.com>
>  * Saravana Kannan <skannan@codeaurora.org>

Tested-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>

who is responsible to take this patch?  Russell?

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-03-03  6:40   ` Jeremy Kerr
  (?)
@ 2011-03-15  4:31     ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-03-15  4:31 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Russell,

Any thughts on merging this? Would you like me to add to your patch tracking 
system, or would you prefer it to go through some other path?

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-03-15  4:31     ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-03-15  4:31 UTC (permalink / raw)
  To: Russell King
  Cc: linux-arm-kernel, linux-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, Dima Zavin, Saravana Kannan, Ben Dooks,
	Uwe Kleine-König

Hi Russell,

Any thughts on merging this? Would you like me to add to your patch tracking 
system, or would you prefer it to go through some other path?

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-03-15  4:31     ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-03-15  4:31 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Russell,

Any thughts on merging this? Would you like me to add to your patch tracking 
system, or would you prefer it to go through some other path?

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-03-15  4:31     ` Jeremy Kerr
  (?)
@ 2011-03-21  2:33       ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-03-21  2:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

> Any thughts on merging this? Would you like me to add to your patch
> tracking system, or would you prefer it to go through some other path?

I haven't heard anything yet, so have added these two to the patch-tracking 
system. Let me know if you'd prefer some other method of submission instead.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-03-21  2:33       ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-03-21  2:33 UTC (permalink / raw)
  To: Russell King
  Cc: linux-arm-kernel, linux-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, Dima Zavin, Saravana Kannan, Ben Dooks,
	Uwe Kleine-König

Hi all,

> Any thughts on merging this? Would you like me to add to your patch
> tracking system, or would you prefer it to go through some other path?

I haven't heard anything yet, so have added these two to the patch-tracking 
system. Let me know if you'd prefer some other method of submission instead.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-03-21  2:33       ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-03-21  2:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

> Any thughts on merging this? Would you like me to add to your patch
> tracking system, or would you prefer it to go through some other path?

I haven't heard anything yet, so have added these two to the patch-tracking 
system. Let me know if you'd prefer some other method of submission instead.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-03-03  6:40   ` Jeremy Kerr
  (?)
@ 2011-04-14  4:20     ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-04-14  4:20 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Russell,

Any updates on these patches? I've added to your patch-tracker, would
you expect these to make the next merge window, or are there changes
you'd like made first?

Reason I ask is that I have a few queries from platform maintainers that
would like to complete their clock ports to this API, but don't want to
commit until the interface has been accepted, in at least an initial
form.

Cheers,


Jeremy


^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14  4:20     ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-04-14  4:20 UTC (permalink / raw)
  To: Russell King
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Dima Zavin,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Uwe Kleine-König, Sascha Hauer, Paul Mundt, Saravana Kannan,
	Ben Dooks

Hi Russell,

Any updates on these patches? I've added to your patch-tracker, would
you expect these to make the next merge window, or are there changes
you'd like made first?

Reason I ask is that I have a few queries from platform maintainers that
would like to complete their clock ports to this API, but don't want to
commit until the interface has been accepted, in at least an initial
form.

Cheers,


Jeremy


^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14  4:20     ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-04-14  4:20 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Russell,

Any updates on these patches? I've added to your patch-tracker, would
you expect these to make the next merge window, or are there changes
you'd like made first?

Reason I ask is that I have a few queries from platform maintainers that
would like to complete their clock ports to this API, but don't want to
commit until the interface has been accepted, in at least an initial
form.

Cheers,


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-04-14  4:20     ` Jeremy Kerr
  (?)
@ 2011-04-14 10:00       ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-04-14 10:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 14, 2011 at 12:20:59PM +0800, Jeremy Kerr wrote:
> Any updates on these patches? I've added to your patch-tracker, would
> you expect these to make the next merge window, or are there changes
> you'd like made first?
> 
> Reason I ask is that I have a few queries from platform maintainers that
> would like to complete their clock ports to this API, but don't want to
> commit until the interface has been accepted, in at least an initial
> form.

I will take it, but at the moment I'm rather unhappy about the response
from the community to Linus' complaint.

If existing platform maintainers can show that moving over to this will
result in a net reduction of code under arch/arm, then that will be good.
What I don't want to see at the moment is arch/arm increasing in size as
a result of any change.  We desperately need to see a reduction for the
next merge window.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 10:00       ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-04-14 10:00 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Dima Zavin,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Uwe Kleine-König, Sascha Hauer, Paul Mundt, Saravana Kannan,
	Ben Dooks

On Thu, Apr 14, 2011 at 12:20:59PM +0800, Jeremy Kerr wrote:
> Any updates on these patches? I've added to your patch-tracker, would
> you expect these to make the next merge window, or are there changes
> you'd like made first?
> 
> Reason I ask is that I have a few queries from platform maintainers that
> would like to complete their clock ports to this API, but don't want to
> commit until the interface has been accepted, in at least an initial
> form.

I will take it, but at the moment I'm rather unhappy about the response
from the community to Linus' complaint.

If existing platform maintainers can show that moving over to this will
result in a net reduction of code under arch/arm, then that will be good.
What I don't want to see at the moment is arch/arm increasing in size as
a result of any change.  We desperately need to see a reduction for the
next merge window.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 10:00       ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-04-14 10:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 14, 2011 at 12:20:59PM +0800, Jeremy Kerr wrote:
> Any updates on these patches? I've added to your patch-tracker, would
> you expect these to make the next merge window, or are there changes
> you'd like made first?
> 
> Reason I ask is that I have a few queries from platform maintainers that
> would like to complete their clock ports to this API, but don't want to
> commit until the interface has been accepted, in at least an initial
> form.

I will take it, but at the moment I'm rather unhappy about the response
from the community to Linus' complaint.

If existing platform maintainers can show that moving over to this will
result in a net reduction of code under arch/arm, then that will be good.
What I don't want to see at the moment is arch/arm increasing in size as
a result of any change.  We desperately need to see a reduction for the
next merge window.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-04-14 10:00       ` Russell King - ARM Linux
  (?)
@ 2011-04-14 10:23         ` Jeremy Kerr
  -1 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-04-14 10:23 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Russell,

> We desperately need to see a reduction for the next merge window.

I can put it all on one line if you like :D


Jeremy


^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 10:23         ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-04-14 10:23 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Dima Zavin,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Uwe Kleine-König, Sascha Hauer, Paul Mundt, Saravana Kannan,
	Ben Dooks

Hi Russell,

> We desperately need to see a reduction for the next merge window.

I can put it all on one line if you like :D


Jeremy


^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 10:23         ` Jeremy Kerr
  0 siblings, 0 replies; 383+ messages in thread
From: Jeremy Kerr @ 2011-04-14 10:23 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Russell,

> We desperately need to see a reduction for the next merge window.

I can put it all on one line if you like :D


Jeremy

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-04-14 10:00       ` Russell King - ARM Linux
  (?)
@ 2011-04-14 10:25         ` Benjamin Herrenschmidt
  -1 siblings, 0 replies; 383+ messages in thread
From: Benjamin Herrenschmidt @ 2011-04-14 10:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2011-04-14 at 11:00 +0100, Russell King - ARM Linux wrote:
> 
> I will take it, but at the moment I'm rather unhappy about the response
> from the community to Linus' complaint.
> 
> If existing platform maintainers can show that moving over to this will
> result in a net reduction of code under arch/arm, then that will be good.
> What I don't want to see at the moment is arch/arm increasing in size as
> a result of any change.  We desperately need to see a reduction for the
> next merge window.

It's a chicken and egg... platform maintainers wait for you to take it
and you wait for them to take it :-)

It seems to me that this fits well into the category of "better common
abstractions" that was discussed in the thread initiated by Linus as one
of the ways to improve on the "clutter"...

Cheers,
Ben.



^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 10:25         ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 383+ messages in thread
From: Benjamin Herrenschmidt @ 2011-04-14 10:25 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Jeremy Kerr, Nicolas Pitre, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Sascha Hauer, Paul Mundt, linux-kernel, Dima Zavin,
	Saravana Kannan, Ben Dooks, Uwe Kleine-König,
	linux-arm-kernel

On Thu, 2011-04-14 at 11:00 +0100, Russell King - ARM Linux wrote:
> 
> I will take it, but at the moment I'm rather unhappy about the response
> from the community to Linus' complaint.
> 
> If existing platform maintainers can show that moving over to this will
> result in a net reduction of code under arch/arm, then that will be good.
> What I don't want to see at the moment is arch/arm increasing in size as
> a result of any change.  We desperately need to see a reduction for the
> next merge window.

It's a chicken and egg... platform maintainers wait for you to take it
and you wait for them to take it :-)

It seems to me that this fits well into the category of "better common
abstractions" that was discussed in the thread initiated by Linus as one
of the ways to improve on the "clutter"...

Cheers,
Ben.



^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 10:25         ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 383+ messages in thread
From: Benjamin Herrenschmidt @ 2011-04-14 10:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2011-04-14 at 11:00 +0100, Russell King - ARM Linux wrote:
> 
> I will take it, but at the moment I'm rather unhappy about the response
> from the community to Linus' complaint.
> 
> If existing platform maintainers can show that moving over to this will
> result in a net reduction of code under arch/arm, then that will be good.
> What I don't want to see at the moment is arch/arm increasing in size as
> a result of any change.  We desperately need to see a reduction for the
> next merge window.

It's a chicken and egg... platform maintainers wait for you to take it
and you wait for them to take it :-)

It seems to me that this fits well into the category of "better common
abstractions" that was discussed in the thread initiated by Linus as one
of the ways to improve on the "clutter"...

Cheers,
Ben.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-04-14 10:23         ` Jeremy Kerr
  (?)
@ 2011-04-14 10:26           ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-04-14 10:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 14, 2011 at 06:23:04PM +0800, Jeremy Kerr wrote:
> Hi Russell,
> 
> > We desperately need to see a reduction for the next merge window.
> 
> I can put it all on one line if you like :D

Yea, do that and send it to Linus for his review.  I suggest a visit your
local fire department to borrow some of their protective equipment first.
:-P

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 10:26           ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-04-14 10:26 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Dima Zavin,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Ben Herrenschmidt,
	Uwe Kleine-König, Sascha Hauer, Paul Mundt, Saravana Kannan,
	Ben Dooks

On Thu, Apr 14, 2011 at 06:23:04PM +0800, Jeremy Kerr wrote:
> Hi Russell,
> 
> > We desperately need to see a reduction for the next merge window.
> 
> I can put it all on one line if you like :D

Yea, do that and send it to Linus for his review.  I suggest a visit your
local fire department to borrow some of their protective equipment first.
:-P

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 10:26           ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-04-14 10:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 14, 2011 at 06:23:04PM +0800, Jeremy Kerr wrote:
> Hi Russell,
> 
> > We desperately need to see a reduction for the next merge window.
> 
> I can put it all on one line if you like :D

Yea, do that and send it to Linus for his review.  I suggest a visit your
local fire department to borrow some of their protective equipment first.
:-P

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-04-14 10:25         ` Benjamin Herrenschmidt
  (?)
@ 2011-04-14 10:32           ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-04-14 10:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 14, 2011 at 08:25:05PM +1000, Benjamin Herrenschmidt wrote:
> On Thu, 2011-04-14 at 11:00 +0100, Russell King - ARM Linux wrote:
> > 
> > I will take it, but at the moment I'm rather unhappy about the response
> > from the community to Linus' complaint.
> > 
> > If existing platform maintainers can show that moving over to this will
> > result in a net reduction of code under arch/arm, then that will be good.
> > What I don't want to see at the moment is arch/arm increasing in size as
> > a result of any change.  We desperately need to see a reduction for the
> > next merge window.
> 
> It's a chicken and egg... platform maintainers wait for you to take it
> and you wait for them to take it :-)
> 
> It seems to me that this fits well into the category of "better common
> abstractions" that was discussed in the thread initiated by Linus as one
> of the ways to improve on the "clutter"...

That depends - sometimes creating generic stuff results in a net increase
in the overall size, and that's something that Linus also complained about.

According to linux-next, where we are at the moment with arch/arm is a
net increase of 6000 lines since the close of the last merge window,
and arch/arm is responsible for almost 75% of arch/ changes.  It looks
very much like the same situation which Linus complained about.

Can arch/arm continue to increase in size?  I think not.  We desperately
need patches which reduce the size of arch/arm, and we desperately need
them *now*.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 10:32           ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-04-14 10:32 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Jeremy Kerr, Nicolas Pitre, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Sascha Hauer, Paul Mundt, linux-kernel, Dima Zavin,
	Saravana Kannan, Ben Dooks, Uwe Kleine-König,
	linux-arm-kernel

On Thu, Apr 14, 2011 at 08:25:05PM +1000, Benjamin Herrenschmidt wrote:
> On Thu, 2011-04-14 at 11:00 +0100, Russell King - ARM Linux wrote:
> > 
> > I will take it, but at the moment I'm rather unhappy about the response
> > from the community to Linus' complaint.
> > 
> > If existing platform maintainers can show that moving over to this will
> > result in a net reduction of code under arch/arm, then that will be good.
> > What I don't want to see at the moment is arch/arm increasing in size as
> > a result of any change.  We desperately need to see a reduction for the
> > next merge window.
> 
> It's a chicken and egg... platform maintainers wait for you to take it
> and you wait for them to take it :-)
> 
> It seems to me that this fits well into the category of "better common
> abstractions" that was discussed in the thread initiated by Linus as one
> of the ways to improve on the "clutter"...

That depends - sometimes creating generic stuff results in a net increase
in the overall size, and that's something that Linus also complained about.

According to linux-next, where we are at the moment with arch/arm is a
net increase of 6000 lines since the close of the last merge window,
and arch/arm is responsible for almost 75% of arch/ changes.  It looks
very much like the same situation which Linus complained about.

Can arch/arm continue to increase in size?  I think not.  We desperately
need patches which reduce the size of arch/arm, and we desperately need
them *now*.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 10:32           ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-04-14 10:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 14, 2011 at 08:25:05PM +1000, Benjamin Herrenschmidt wrote:
> On Thu, 2011-04-14 at 11:00 +0100, Russell King - ARM Linux wrote:
> > 
> > I will take it, but at the moment I'm rather unhappy about the response
> > from the community to Linus' complaint.
> > 
> > If existing platform maintainers can show that moving over to this will
> > result in a net reduction of code under arch/arm, then that will be good.
> > What I don't want to see at the moment is arch/arm increasing in size as
> > a result of any change.  We desperately need to see a reduction for the
> > next merge window.
> 
> It's a chicken and egg... platform maintainers wait for you to take it
> and you wait for them to take it :-)
> 
> It seems to me that this fits well into the category of "better common
> abstractions" that was discussed in the thread initiated by Linus as one
> of the ways to improve on the "clutter"...

That depends - sometimes creating generic stuff results in a net increase
in the overall size, and that's something that Linus also complained about.

According to linux-next, where we are at the moment with arch/arm is a
net increase of 6000 lines since the close of the last merge window,
and arch/arm is responsible for almost 75% of arch/ changes.  It looks
very much like the same situation which Linus complained about.

Can arch/arm continue to increase in size?  I think not.  We desperately
need patches which reduce the size of arch/arm, and we desperately need
them *now*.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-04-14 10:32           ` Russell King - ARM Linux
  (?)
@ 2011-04-14 11:59             ` Nicolas Pitre
  -1 siblings, 0 replies; 383+ messages in thread
From: Nicolas Pitre @ 2011-04-14 11:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 14 Apr 2011, Russell King - ARM Linux wrote:

> On Thu, Apr 14, 2011 at 08:25:05PM +1000, Benjamin Herrenschmidt wrote:
> > On Thu, 2011-04-14 at 11:00 +0100, Russell King - ARM Linux wrote:
> > > 
> > > I will take it, but at the moment I'm rather unhappy about the response
> > > from the community to Linus' complaint.
> > > 
> > > If existing platform maintainers can show that moving over to this will
> > > result in a net reduction of code under arch/arm, then that will be good.
> > > What I don't want to see at the moment is arch/arm increasing in size as
> > > a result of any change.  We desperately need to see a reduction for the
> > > next merge window.
> > 
> > It's a chicken and egg... platform maintainers wait for you to take it
> > and you wait for them to take it :-)
> > 
> > It seems to me that this fits well into the category of "better common
> > abstractions" that was discussed in the thread initiated by Linus as one
> > of the ways to improve on the "clutter"...
> 
> That depends - sometimes creating generic stuff results in a net increase
> in the overall size, and that's something that Linus also complained about.
> 
> According to linux-next, where we are at the moment with arch/arm is a
> net increase of 6000 lines since the close of the last merge window,
> and arch/arm is responsible for almost 75% of arch/ changes.  It looks
> very much like the same situation which Linus complained about.

Quoting Linus:

| Umm. The whole "number of lines of code" thing has become a total red
| herring.
| 
| THAT IS NOT WHY I STARTED TO COMPLAIN!
| 
| The reason I point out the number of lines of code is because it's one
| of the more obvious _symptoms_ of the problem.

So we need to work on infrastructure, and the clock API is exactly that.  
Obviously adding it will increase the number of lines of code initially, 
but eventually this will help _reduce_ them, and more importantly it 
will allow for the reduction of mindless duplication of code that was 
identified as being the actual problem causing maintenance pain.


Nicolas

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 11:59             ` Nicolas Pitre
  0 siblings, 0 replies; 383+ messages in thread
From: Nicolas Pitre @ 2011-04-14 11:59 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Benjamin Herrenschmidt, Jeremy Kerr, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Sascha Hauer, Paul Mundt, lkml,
	Dima Zavin, Saravana Kannan, Ben Dooks, Uwe Kleine-König,
	linux-arm-kernel

On Thu, 14 Apr 2011, Russell King - ARM Linux wrote:

> On Thu, Apr 14, 2011 at 08:25:05PM +1000, Benjamin Herrenschmidt wrote:
> > On Thu, 2011-04-14 at 11:00 +0100, Russell King - ARM Linux wrote:
> > > 
> > > I will take it, but at the moment I'm rather unhappy about the response
> > > from the community to Linus' complaint.
> > > 
> > > If existing platform maintainers can show that moving over to this will
> > > result in a net reduction of code under arch/arm, then that will be good.
> > > What I don't want to see at the moment is arch/arm increasing in size as
> > > a result of any change.  We desperately need to see a reduction for the
> > > next merge window.
> > 
> > It's a chicken and egg... platform maintainers wait for you to take it
> > and you wait for them to take it :-)
> > 
> > It seems to me that this fits well into the category of "better common
> > abstractions" that was discussed in the thread initiated by Linus as one
> > of the ways to improve on the "clutter"...
> 
> That depends - sometimes creating generic stuff results in a net increase
> in the overall size, and that's something that Linus also complained about.
> 
> According to linux-next, where we are at the moment with arch/arm is a
> net increase of 6000 lines since the close of the last merge window,
> and arch/arm is responsible for almost 75% of arch/ changes.  It looks
> very much like the same situation which Linus complained about.

Quoting Linus:

| Umm. The whole "number of lines of code" thing has become a total red
| herring.
| 
| THAT IS NOT WHY I STARTED TO COMPLAIN!
| 
| The reason I point out the number of lines of code is because it's one
| of the more obvious _symptoms_ of the problem.

So we need to work on infrastructure, and the clock API is exactly that.  
Obviously adding it will increase the number of lines of code initially, 
but eventually this will help _reduce_ them, and more importantly it 
will allow for the reduction of mindless duplication of code that was 
identified as being the actual problem causing maintenance pain.


Nicolas

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 11:59             ` Nicolas Pitre
  0 siblings, 0 replies; 383+ messages in thread
From: Nicolas Pitre @ 2011-04-14 11:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 14 Apr 2011, Russell King - ARM Linux wrote:

> On Thu, Apr 14, 2011 at 08:25:05PM +1000, Benjamin Herrenschmidt wrote:
> > On Thu, 2011-04-14 at 11:00 +0100, Russell King - ARM Linux wrote:
> > > 
> > > I will take it, but at the moment I'm rather unhappy about the response
> > > from the community to Linus' complaint.
> > > 
> > > If existing platform maintainers can show that moving over to this will
> > > result in a net reduction of code under arch/arm, then that will be good.
> > > What I don't want to see at the moment is arch/arm increasing in size as
> > > a result of any change.  We desperately need to see a reduction for the
> > > next merge window.
> > 
> > It's a chicken and egg... platform maintainers wait for you to take it
> > and you wait for them to take it :-)
> > 
> > It seems to me that this fits well into the category of "better common
> > abstractions" that was discussed in the thread initiated by Linus as one
> > of the ways to improve on the "clutter"...
> 
> That depends - sometimes creating generic stuff results in a net increase
> in the overall size, and that's something that Linus also complained about.
> 
> According to linux-next, where we are at the moment with arch/arm is a
> net increase of 6000 lines since the close of the last merge window,
> and arch/arm is responsible for almost 75% of arch/ changes.  It looks
> very much like the same situation which Linus complained about.

Quoting Linus:

| Umm. The whole "number of lines of code" thing has become a total red
| herring.
| 
| THAT IS NOT WHY I STARTED TO COMPLAIN!
| 
| The reason I point out the number of lines of code is because it's one
| of the more obvious _symptoms_ of the problem.

So we need to work on infrastructure, and the clock API is exactly that.  
Obviously adding it will increase the number of lines of code initially, 
but eventually this will help _reduce_ them, and more importantly it 
will allow for the reduction of mindless duplication of code that was 
identified as being the actual problem causing maintenance pain.


Nicolas

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-04-14 11:59             ` Nicolas Pitre
  (?)
@ 2011-04-14 12:09               ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-04-14 12:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 14, 2011 at 07:59:58AM -0400, Nicolas Pitre wrote:
> On Thu, 14 Apr 2011, Russell King - ARM Linux wrote:
> 
> > On Thu, Apr 14, 2011 at 08:25:05PM +1000, Benjamin Herrenschmidt wrote:
> > > On Thu, 2011-04-14 at 11:00 +0100, Russell King - ARM Linux wrote:
> > > > 
> > > > I will take it, but at the moment I'm rather unhappy about the response
> > > > from the community to Linus' complaint.
> > > > 
> > > > If existing platform maintainers can show that moving over to this will
> > > > result in a net reduction of code under arch/arm, then that will be good.
> > > > What I don't want to see at the moment is arch/arm increasing in size as
> > > > a result of any change.  We desperately need to see a reduction for the
> > > > next merge window.
> > > 
> > > It's a chicken and egg... platform maintainers wait for you to take it
> > > and you wait for them to take it :-)
> > > 
> > > It seems to me that this fits well into the category of "better common
> > > abstractions" that was discussed in the thread initiated by Linus as one
> > > of the ways to improve on the "clutter"...
> > 
> > That depends - sometimes creating generic stuff results in a net increase
> > in the overall size, and that's something that Linus also complained about.
> > 
> > According to linux-next, where we are at the moment with arch/arm is a
> > net increase of 6000 lines since the close of the last merge window,
> > and arch/arm is responsible for almost 75% of arch/ changes.  It looks
> > very much like the same situation which Linus complained about.
> 
> Quoting Linus:
> 
> | Umm. The whole "number of lines of code" thing has become a total red
> | herring.
> | 
> | THAT IS NOT WHY I STARTED TO COMPLAIN!
> | 
> | The reason I point out the number of lines of code is because it's one
> | of the more obvious _symptoms_ of the problem.
> 
> So we need to work on infrastructure, and the clock API is exactly that.  
> Obviously adding it will increase the number of lines of code initially, 
> but eventually this will help _reduce_ them, and more importantly it 
> will allow for the reduction of mindless duplication of code that was 
> identified as being the actual problem causing maintenance pain.

Adding it without anyone using it doesn't solve anything.  We need
people to commit to producing patches to use it for the next merge
window.

And if you think its not about lines of code - grab the current linux-next
tree and look at the diff between v2.6.39-rc1 and master for arch/arm, and
then tell me whether using LOC is unreasonable given the patch content.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 12:09               ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-04-14 12:09 UTC (permalink / raw)
  To: Nicolas Pitre
  Cc: Benjamin Herrenschmidt, Jeremy Kerr, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Sascha Hauer, Paul Mundt, lkml,
	Dima Zavin, Saravana Kannan, Ben Dooks, Uwe Kleine-König,
	linux-arm-kernel

On Thu, Apr 14, 2011 at 07:59:58AM -0400, Nicolas Pitre wrote:
> On Thu, 14 Apr 2011, Russell King - ARM Linux wrote:
> 
> > On Thu, Apr 14, 2011 at 08:25:05PM +1000, Benjamin Herrenschmidt wrote:
> > > On Thu, 2011-04-14 at 11:00 +0100, Russell King - ARM Linux wrote:
> > > > 
> > > > I will take it, but at the moment I'm rather unhappy about the response
> > > > from the community to Linus' complaint.
> > > > 
> > > > If existing platform maintainers can show that moving over to this will
> > > > result in a net reduction of code under arch/arm, then that will be good.
> > > > What I don't want to see at the moment is arch/arm increasing in size as
> > > > a result of any change.  We desperately need to see a reduction for the
> > > > next merge window.
> > > 
> > > It's a chicken and egg... platform maintainers wait for you to take it
> > > and you wait for them to take it :-)
> > > 
> > > It seems to me that this fits well into the category of "better common
> > > abstractions" that was discussed in the thread initiated by Linus as one
> > > of the ways to improve on the "clutter"...
> > 
> > That depends - sometimes creating generic stuff results in a net increase
> > in the overall size, and that's something that Linus also complained about.
> > 
> > According to linux-next, where we are at the moment with arch/arm is a
> > net increase of 6000 lines since the close of the last merge window,
> > and arch/arm is responsible for almost 75% of arch/ changes.  It looks
> > very much like the same situation which Linus complained about.
> 
> Quoting Linus:
> 
> | Umm. The whole "number of lines of code" thing has become a total red
> | herring.
> | 
> | THAT IS NOT WHY I STARTED TO COMPLAIN!
> | 
> | The reason I point out the number of lines of code is because it's one
> | of the more obvious _symptoms_ of the problem.
> 
> So we need to work on infrastructure, and the clock API is exactly that.  
> Obviously adding it will increase the number of lines of code initially, 
> but eventually this will help _reduce_ them, and more importantly it 
> will allow for the reduction of mindless duplication of code that was 
> identified as being the actual problem causing maintenance pain.

Adding it without anyone using it doesn't solve anything.  We need
people to commit to producing patches to use it for the next merge
window.

And if you think its not about lines of code - grab the current linux-next
tree and look at the diff between v2.6.39-rc1 and master for arch/arm, and
then tell me whether using LOC is unreasonable given the patch content.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 12:09               ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-04-14 12:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 14, 2011 at 07:59:58AM -0400, Nicolas Pitre wrote:
> On Thu, 14 Apr 2011, Russell King - ARM Linux wrote:
> 
> > On Thu, Apr 14, 2011 at 08:25:05PM +1000, Benjamin Herrenschmidt wrote:
> > > On Thu, 2011-04-14 at 11:00 +0100, Russell King - ARM Linux wrote:
> > > > 
> > > > I will take it, but at the moment I'm rather unhappy about the response
> > > > from the community to Linus' complaint.
> > > > 
> > > > If existing platform maintainers can show that moving over to this will
> > > > result in a net reduction of code under arch/arm, then that will be good.
> > > > What I don't want to see at the moment is arch/arm increasing in size as
> > > > a result of any change.  We desperately need to see a reduction for the
> > > > next merge window.
> > > 
> > > It's a chicken and egg... platform maintainers wait for you to take it
> > > and you wait for them to take it :-)
> > > 
> > > It seems to me that this fits well into the category of "better common
> > > abstractions" that was discussed in the thread initiated by Linus as one
> > > of the ways to improve on the "clutter"...
> > 
> > That depends - sometimes creating generic stuff results in a net increase
> > in the overall size, and that's something that Linus also complained about.
> > 
> > According to linux-next, where we are at the moment with arch/arm is a
> > net increase of 6000 lines since the close of the last merge window,
> > and arch/arm is responsible for almost 75% of arch/ changes.  It looks
> > very much like the same situation which Linus complained about.
> 
> Quoting Linus:
> 
> | Umm. The whole "number of lines of code" thing has become a total red
> | herring.
> | 
> | THAT IS NOT WHY I STARTED TO COMPLAIN!
> | 
> | The reason I point out the number of lines of code is because it's one
> | of the more obvious _symptoms_ of the problem.
> 
> So we need to work on infrastructure, and the clock API is exactly that.  
> Obviously adding it will increase the number of lines of code initially, 
> but eventually this will help _reduce_ them, and more importantly it 
> will allow for the reduction of mindless duplication of code that was 
> identified as being the actual problem causing maintenance pain.

Adding it without anyone using it doesn't solve anything.  We need
people to commit to producing patches to use it for the next merge
window.

And if you think its not about lines of code - grab the current linux-next
tree and look at the diff between v2.6.39-rc1 and master for arch/arm, and
then tell me whether using LOC is unreasonable given the patch content.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 1/2] Add a common struct clk
  2011-03-03  6:40     ` Jeremy Kerr
  (?)
@ 2011-04-14 12:49       ` Tony Lindgren
  -1 siblings, 0 replies; 383+ messages in thread
From: Tony Lindgren @ 2011-04-14 12:49 UTC (permalink / raw)
  To: linux-arm-kernel

* Jeremy Kerr <jeremy.kerr@canonical.com> [110303 08:39]:
> 
> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
> 
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
> 
> And a set of clock operations (defined per type of clock):
> 
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
> 
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
> 
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
> 
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };

Anybody looked into passing the clock register and type
from device tree?

To me it looks like the above would allow doing that
pretty easily while avoiding duplicating all the
data from devicetree into struct clk_foo.

Tony

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 1/2] Add a common struct clk
@ 2011-04-14 12:49       ` Tony Lindgren
  0 siblings, 0 replies; 383+ messages in thread
From: Tony Lindgren @ 2011-04-14 12:49 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: linux-kernel, linux-arm-kernel, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Ben Herrenschmidt, Sascha Hauer,
	Paul Mundt, Dima Zavin, Saravana Kannan, Ben Dooks,
	Uwe Kleine-König, Russell King, Paul Walmsley

* Jeremy Kerr <jeremy.kerr@canonical.com> [110303 08:39]:
> 
> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
> 
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
> 
> And a set of clock operations (defined per type of clock):
> 
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
> 
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
> 
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
> 
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };

Anybody looked into passing the clock register and type
from device tree?

To me it looks like the above would allow doing that
pretty easily while avoiding duplicating all the
data from devicetree into struct clk_foo.

Tony

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 1/2] Add a common struct clk
@ 2011-04-14 12:49       ` Tony Lindgren
  0 siblings, 0 replies; 383+ messages in thread
From: Tony Lindgren @ 2011-04-14 12:49 UTC (permalink / raw)
  To: linux-arm-kernel

* Jeremy Kerr <jeremy.kerr@canonical.com> [110303 08:39]:
> 
> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
> 
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
> 
> And a set of clock operations (defined per type of clock):
> 
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
> 
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
> 
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
> 
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };

Anybody looked into passing the clock register and type
from device tree?

To me it looks like the above would allow doing that
pretty easily while avoiding duplicating all the
data from devicetree into struct clk_foo.

Tony

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-04-14 12:09               ` Russell King - ARM Linux
  (?)
@ 2011-04-14 13:39                 ` Nicolas Pitre
  -1 siblings, 0 replies; 383+ messages in thread
From: Nicolas Pitre @ 2011-04-14 13:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 14 Apr 2011, Russell King - ARM Linux wrote:

> On Thu, Apr 14, 2011 at 07:59:58AM -0400, Nicolas Pitre wrote:
> > Quoting Linus:
> > 
> > | Umm. The whole "number of lines of code" thing has become a total red
> > | herring.
> > | 
> > | THAT IS NOT WHY I STARTED TO COMPLAIN!
> > | 
> > | The reason I point out the number of lines of code is because it's one
> > | of the more obvious _symptoms_ of the problem.
> > 
> > So we need to work on infrastructure, and the clock API is exactly that.  
> > Obviously adding it will increase the number of lines of code initially, 
> > but eventually this will help _reduce_ them, and more importantly it 
> > will allow for the reduction of mindless duplication of code that was 
> > identified as being the actual problem causing maintenance pain.
> 
> Adding it without anyone using it doesn't solve anything.  We need
> people to commit to producing patches to use it for the next merge
> window.

People are simply waiting for the API to hit some upstream tree (like 
yours) before committing to it.  You would be in a much better position 
if those patches are in your tree, so that you can tell people: "Here's 
the Git branch with the API in it, so now I'm expecting patches to 
convert clock users to it".

> And if you think its not about lines of code - grab the current linux-next
> tree and look at the diff between v2.6.39-rc1 and master for arch/arm, and
> then tell me whether using LOC is unreasonable given the patch content.

I might have a look later.  However it is clear that the ARM tree will 
_never_ be as small as, say, X86 or even PPC given the indisputable 
amount of hardware variations within the ARM landscape that is not to be 
seen anywhere else.  Until the ARM ecosystem converge towards a single 
whole-system architecture we won't be able to match X86 in terms of code 
reduction.  Anyone thinking otherwise is living in a different universe.

However we can and must do better in consolidation work in order to make 
the tree more maintainable of course.  _That_ is the real issue and 
_that_ is what the ARM tree sucks at.  The fact that this consolidation 
work might reduce the size of the ARM code is only a side effect, not 
the primary goal.  So let's not get too hung up about LOC but focus on 
improving the infrastructure instead.


Nicolas

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 13:39                 ` Nicolas Pitre
  0 siblings, 0 replies; 383+ messages in thread
From: Nicolas Pitre @ 2011-04-14 13:39 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Benjamin Herrenschmidt, Jeremy Kerr, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Sascha Hauer, Paul Mundt, lkml,
	Dima Zavin, Saravana Kannan, Ben Dooks, Uwe Kleine-König,
	linux-arm-kernel

On Thu, 14 Apr 2011, Russell King - ARM Linux wrote:

> On Thu, Apr 14, 2011 at 07:59:58AM -0400, Nicolas Pitre wrote:
> > Quoting Linus:
> > 
> > | Umm. The whole "number of lines of code" thing has become a total red
> > | herring.
> > | 
> > | THAT IS NOT WHY I STARTED TO COMPLAIN!
> > | 
> > | The reason I point out the number of lines of code is because it's one
> > | of the more obvious _symptoms_ of the problem.
> > 
> > So we need to work on infrastructure, and the clock API is exactly that.  
> > Obviously adding it will increase the number of lines of code initially, 
> > but eventually this will help _reduce_ them, and more importantly it 
> > will allow for the reduction of mindless duplication of code that was 
> > identified as being the actual problem causing maintenance pain.
> 
> Adding it without anyone using it doesn't solve anything.  We need
> people to commit to producing patches to use it for the next merge
> window.

People are simply waiting for the API to hit some upstream tree (like 
yours) before committing to it.  You would be in a much better position 
if those patches are in your tree, so that you can tell people: "Here's 
the Git branch with the API in it, so now I'm expecting patches to 
convert clock users to it".

> And if you think its not about lines of code - grab the current linux-next
> tree and look at the diff between v2.6.39-rc1 and master for arch/arm, and
> then tell me whether using LOC is unreasonable given the patch content.

I might have a look later.  However it is clear that the ARM tree will 
_never_ be as small as, say, X86 or even PPC given the indisputable 
amount of hardware variations within the ARM landscape that is not to be 
seen anywhere else.  Until the ARM ecosystem converge towards a single 
whole-system architecture we won't be able to match X86 in terms of code 
reduction.  Anyone thinking otherwise is living in a different universe.

However we can and must do better in consolidation work in order to make 
the tree more maintainable of course.  _That_ is the real issue and 
_that_ is what the ARM tree sucks at.  The fact that this consolidation 
work might reduce the size of the ARM code is only a side effect, not 
the primary goal.  So let's not get too hung up about LOC but focus on 
improving the infrastructure instead.


Nicolas

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 13:39                 ` Nicolas Pitre
  0 siblings, 0 replies; 383+ messages in thread
From: Nicolas Pitre @ 2011-04-14 13:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 14 Apr 2011, Russell King - ARM Linux wrote:

> On Thu, Apr 14, 2011 at 07:59:58AM -0400, Nicolas Pitre wrote:
> > Quoting Linus:
> > 
> > | Umm. The whole "number of lines of code" thing has become a total red
> > | herring.
> > | 
> > | THAT IS NOT WHY I STARTED TO COMPLAIN!
> > | 
> > | The reason I point out the number of lines of code is because it's one
> > | of the more obvious _symptoms_ of the problem.
> > 
> > So we need to work on infrastructure, and the clock API is exactly that.  
> > Obviously adding it will increase the number of lines of code initially, 
> > but eventually this will help _reduce_ them, and more importantly it 
> > will allow for the reduction of mindless duplication of code that was 
> > identified as being the actual problem causing maintenance pain.
> 
> Adding it without anyone using it doesn't solve anything.  We need
> people to commit to producing patches to use it for the next merge
> window.

People are simply waiting for the API to hit some upstream tree (like 
yours) before committing to it.  You would be in a much better position 
if those patches are in your tree, so that you can tell people: "Here's 
the Git branch with the API in it, so now I'm expecting patches to 
convert clock users to it".

> And if you think its not about lines of code - grab the current linux-next
> tree and look at the diff between v2.6.39-rc1 and master for arch/arm, and
> then tell me whether using LOC is unreasonable given the patch content.

I might have a look later.  However it is clear that the ARM tree will 
_never_ be as small as, say, X86 or even PPC given the indisputable 
amount of hardware variations within the ARM landscape that is not to be 
seen anywhere else.  Until the ARM ecosystem converge towards a single 
whole-system architecture we won't be able to match X86 in terms of code 
reduction.  Anyone thinking otherwise is living in a different universe.

However we can and must do better in consolidation work in order to make 
the tree more maintainable of course.  _That_ is the real issue and 
_that_ is what the ARM tree sucks at.  The fact that this consolidation 
work might reduce the size of the ARM code is only a side effect, not 
the primary goal.  So let's not get too hung up about LOC but focus on 
improving the infrastructure instead.


Nicolas

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-04-14 13:39                 ` Nicolas Pitre
  (?)
@ 2011-04-14 14:00                   ` Mark Brown
  -1 siblings, 0 replies; 383+ messages in thread
From: Mark Brown @ 2011-04-14 14:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 14, 2011 at 09:39:58AM -0400, Nicolas Pitre wrote:
> On Thu, 14 Apr 2011, Russell King - ARM Linux wrote:

> > Adding it without anyone using it doesn't solve anything.  We need
> > people to commit to producing patches to use it for the next merge
> > window.

> People are simply waiting for the API to hit some upstream tree (like 
> yours) before committing to it.  You would be in a much better position 
> if those patches are in your tree, so that you can tell people: "Here's 
> the Git branch with the API in it, so now I'm expecting patches to 
> convert clock users to it".

One way of doing this would be to apply the patches to a branch in your
tree which isn't merged into -next and request that architecture
maintainers wishing to make use of the branch pull it into their trees.
That way it'll go into -next with at least one user but multiple
architectures can still work on using it in the initial merge.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 14:00                   ` Mark Brown
  0 siblings, 0 replies; 383+ messages in thread
From: Mark Brown @ 2011-04-14 14:00 UTC (permalink / raw)
  To: Nicolas Pitre
  Cc: Russell King - ARM Linux, Dima Zavin, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Benjamin Herrenschmidt, Sascha Hauer,
	lkml, Paul Mundt, Saravana Kannan, Ben Dooks, Uwe Kleine-K?nig,
	Jeremy Kerr, linux-arm-kernel

On Thu, Apr 14, 2011 at 09:39:58AM -0400, Nicolas Pitre wrote:
> On Thu, 14 Apr 2011, Russell King - ARM Linux wrote:

> > Adding it without anyone using it doesn't solve anything.  We need
> > people to commit to producing patches to use it for the next merge
> > window.

> People are simply waiting for the API to hit some upstream tree (like 
> yours) before committing to it.  You would be in a much better position 
> if those patches are in your tree, so that you can tell people: "Here's 
> the Git branch with the API in it, so now I'm expecting patches to 
> convert clock users to it".

One way of doing this would be to apply the patches to a branch in your
tree which isn't merged into -next and request that architecture
maintainers wishing to make use of the branch pull it into their trees.
That way it'll go into -next with at least one user but multiple
architectures can still work on using it in the initial merge.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 14:00                   ` Mark Brown
  0 siblings, 0 replies; 383+ messages in thread
From: Mark Brown @ 2011-04-14 14:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 14, 2011 at 09:39:58AM -0400, Nicolas Pitre wrote:
> On Thu, 14 Apr 2011, Russell King - ARM Linux wrote:

> > Adding it without anyone using it doesn't solve anything.  We need
> > people to commit to producing patches to use it for the next merge
> > window.

> People are simply waiting for the API to hit some upstream tree (like 
> yours) before committing to it.  You would be in a much better position 
> if those patches are in your tree, so that you can tell people: "Here's 
> the Git branch with the API in it, so now I'm expecting patches to 
> convert clock users to it".

One way of doing this would be to apply the patches to a branch in your
tree which isn't merged into -next and request that architecture
maintainers wishing to make use of the branch pull it into their trees.
That way it'll go into -next with at least one user but multiple
architectures can still work on using it in the initial merge.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-04-14 13:39                 ` Nicolas Pitre
  (?)
@ 2011-04-14 15:38                   ` Russell King - ARM Linux
  -1 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-04-14 15:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 14, 2011 at 09:39:58AM -0400, Nicolas Pitre wrote:
> I might have a look later.  However it is clear that the ARM tree will 
> _never_ be as small as, say, X86 or even PPC given the indisputable 
> amount of hardware variations within the ARM landscape that is not to be 
> seen anywhere else.  Until the ARM ecosystem converge towards a single 
> whole-system architecture we won't be able to match X86 in terms of code 
> reduction.  Anyone thinking otherwise is living in a different universe.
> 
> However we can and must do better in consolidation work in order to make 
> the tree more maintainable of course.  _That_ is the real issue and 
> _that_ is what the ARM tree sucks at.  The fact that this consolidation 
> work might reduce the size of the ARM code is only a side effect, not 
> the primary goal.  So let's not get too hung up about LOC but focus on 
> improving the infrastructure instead.

Look, this is what is in amongst the 6K lines of new code - these are
the top two in the diffstat with the highest number of additional lines:

 arch/arm/mach-ux500/clock-db8500.c                 | 1291 +++++++++++++
 arch/arm/mach-ux500/prcmu-db8500.c                 | 2018 ++++++++++++++++++++

These comprise 50% of the 6K of new code.  clock-db8500.c is a mixture
of code and data declarations for individual clocks - which is essentially
what Linus picked up with his complaint on under OMAP.  That in itself
makes me worried.

Looking at the other file, prcmu-db8500.c seems to contain at least 5 sets
of mailbox support code.  Take a look at "Subject: [PATCH 9/9] mach-ux500:
add DB5500 PRCMU interface" from Linus Walleij on 31st March on this list
for the patch.  Are we sure that this couldn't be consolidated in some
way, at least at file level?

So while you can say about not getting hung up about LOC, LOC is a good
indication that things are still going wrong in much the same way.

On the positive note, it looks like MX3 is being merged into IMX stuff,
which is good news, and the mxc91231 has been dropped.  We need to ensure
that good work like this, which will make Linus happy, doesn't get
swamped by new stuff.

We must take Linus' complaint about 'churn' seriously - it's not something
new that he's just started to complain about in the last month.  It's
something which he's complained about on a number of occasions.  Feel free
to think what you may about that, but just bear in mind that Linus holds
the keys to the mainline kernel, and he can put us in a different universe.

Now, the next thing is that Linus hasn't been too happy about driver stuff
coming via my tree either - it's something which has been the subject of
concern in private email.  I've _already_ said something about that prior
to the recent merge window.  So should I take the clk API stuff which
touches the drivers subtree?  If yes, it needs to be kept entirely separate
from the rest of the ARM stuff so we don't end up mixing drivers stuff with
ARM stuff.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 15:38                   ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-04-14 15:38 UTC (permalink / raw)
  To: Nicolas Pitre
  Cc: Benjamin Herrenschmidt, Jeremy Kerr, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Sascha Hauer, Paul Mundt, lkml,
	Dima Zavin, Saravana Kannan, Ben Dooks, Uwe Kleine-König,
	linux-arm-kernel

On Thu, Apr 14, 2011 at 09:39:58AM -0400, Nicolas Pitre wrote:
> I might have a look later.  However it is clear that the ARM tree will 
> _never_ be as small as, say, X86 or even PPC given the indisputable 
> amount of hardware variations within the ARM landscape that is not to be 
> seen anywhere else.  Until the ARM ecosystem converge towards a single 
> whole-system architecture we won't be able to match X86 in terms of code 
> reduction.  Anyone thinking otherwise is living in a different universe.
> 
> However we can and must do better in consolidation work in order to make 
> the tree more maintainable of course.  _That_ is the real issue and 
> _that_ is what the ARM tree sucks at.  The fact that this consolidation 
> work might reduce the size of the ARM code is only a side effect, not 
> the primary goal.  So let's not get too hung up about LOC but focus on 
> improving the infrastructure instead.

Look, this is what is in amongst the 6K lines of new code - these are
the top two in the diffstat with the highest number of additional lines:

 arch/arm/mach-ux500/clock-db8500.c                 | 1291 +++++++++++++
 arch/arm/mach-ux500/prcmu-db8500.c                 | 2018 ++++++++++++++++++++

These comprise 50% of the 6K of new code.  clock-db8500.c is a mixture
of code and data declarations for individual clocks - which is essentially
what Linus picked up with his complaint on under OMAP.  That in itself
makes me worried.

Looking at the other file, prcmu-db8500.c seems to contain at least 5 sets
of mailbox support code.  Take a look at "Subject: [PATCH 9/9] mach-ux500:
add DB5500 PRCMU interface" from Linus Walleij on 31st March on this list
for the patch.  Are we sure that this couldn't be consolidated in some
way, at least at file level?

So while you can say about not getting hung up about LOC, LOC is a good
indication that things are still going wrong in much the same way.

On the positive note, it looks like MX3 is being merged into IMX stuff,
which is good news, and the mxc91231 has been dropped.  We need to ensure
that good work like this, which will make Linus happy, doesn't get
swamped by new stuff.

We must take Linus' complaint about 'churn' seriously - it's not something
new that he's just started to complain about in the last month.  It's
something which he's complained about on a number of occasions.  Feel free
to think what you may about that, but just bear in mind that Linus holds
the keys to the mainline kernel, and he can put us in a different universe.

Now, the next thing is that Linus hasn't been too happy about driver stuff
coming via my tree either - it's something which has been the subject of
concern in private email.  I've _already_ said something about that prior
to the recent merge window.  So should I take the clk API stuff which
touches the drivers subtree?  If yes, it needs to be kept entirely separate
from the rest of the ARM stuff so we don't end up mixing drivers stuff with
ARM stuff.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 15:38                   ` Russell King - ARM Linux
  0 siblings, 0 replies; 383+ messages in thread
From: Russell King - ARM Linux @ 2011-04-14 15:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 14, 2011 at 09:39:58AM -0400, Nicolas Pitre wrote:
> I might have a look later.  However it is clear that the ARM tree will 
> _never_ be as small as, say, X86 or even PPC given the indisputable 
> amount of hardware variations within the ARM landscape that is not to be 
> seen anywhere else.  Until the ARM ecosystem converge towards a single 
> whole-system architecture we won't be able to match X86 in terms of code 
> reduction.  Anyone thinking otherwise is living in a different universe.
> 
> However we can and must do better in consolidation work in order to make 
> the tree more maintainable of course.  _That_ is the real issue and 
> _that_ is what the ARM tree sucks at.  The fact that this consolidation 
> work might reduce the size of the ARM code is only a side effect, not 
> the primary goal.  So let's not get too hung up about LOC but focus on 
> improving the infrastructure instead.

Look, this is what is in amongst the 6K lines of new code - these are
the top two in the diffstat with the highest number of additional lines:

 arch/arm/mach-ux500/clock-db8500.c                 | 1291 +++++++++++++
 arch/arm/mach-ux500/prcmu-db8500.c                 | 2018 ++++++++++++++++++++

These comprise 50% of the 6K of new code.  clock-db8500.c is a mixture
of code and data declarations for individual clocks - which is essentially
what Linus picked up with his complaint on under OMAP.  That in itself
makes me worried.

Looking at the other file, prcmu-db8500.c seems to contain at least 5 sets
of mailbox support code.  Take a look at "Subject: [PATCH 9/9] mach-ux500:
add DB5500 PRCMU interface" from Linus Walleij on 31st March on this list
for the patch.  Are we sure that this couldn't be consolidated in some
way, at least at file level?

So while you can say about not getting hung up about LOC, LOC is a good
indication that things are still going wrong in much the same way.

On the positive note, it looks like MX3 is being merged into IMX stuff,
which is good news, and the mxc91231 has been dropped.  We need to ensure
that good work like this, which will make Linus happy, doesn't get
swamped by new stuff.

We must take Linus' complaint about 'churn' seriously - it's not something
new that he's just started to complain about in the last month.  It's
something which he's complained about on a number of occasions.  Feel free
to think what you may about that, but just bear in mind that Linus holds
the keys to the mainline kernel, and he can put us in a different universe.

Now, the next thing is that Linus hasn't been too happy about driver stuff
coming via my tree either - it's something which has been the subject of
concern in private email.  I've _already_ said something about that prior
to the recent merge window.  So should I take the clk API stuff which
touches the drivers subtree?  If yes, it needs to be kept entirely separate
from the rest of the ARM stuff so we don't end up mixing drivers stuff with
ARM stuff.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-04-14 15:38                   ` Russell King - ARM Linux
  (?)
@ 2011-04-14 16:06                     ` Nicolas Pitre
  -1 siblings, 0 replies; 383+ messages in thread
From: Nicolas Pitre @ 2011-04-14 16:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 14 Apr 2011, Russell King - ARM Linux wrote:

> On Thu, Apr 14, 2011 at 09:39:58AM -0400, Nicolas Pitre wrote:
> > However we can and must do better in consolidation work in order to make 
> > the tree more maintainable of course.  _That_ is the real issue and 
> > _that_ is what the ARM tree sucks at.  The fact that this consolidation 
> > work might reduce the size of the ARM code is only a side effect, not 
> > the primary goal.  So let's not get too hung up about LOC but focus on 
> > improving the infrastructure instead.
> 
> Look, this is what is in amongst the 6K lines of new code - these are
> the top two in the diffstat with the highest number of additional lines:
> 
>  arch/arm/mach-ux500/clock-db8500.c                 | 1291 +++++++++++++
>  arch/arm/mach-ux500/prcmu-db8500.c                 | 2018 ++++++++++++++++++++
> 
> These comprise 50% of the 6K of new code.  clock-db8500.c is a mixture
> of code and data declarations for individual clocks - which is essentially
> what Linus picked up with his complaint on under OMAP.  That in itself
> makes me worried.

Sure.  So... let's see what we can do about it.  Having 1300 lines only 
for clock stuff on only one platform certainly looks silly.  Either we 
can consolidate some of that stuff with another similar-enough platform, 
or we're stuck with the ST-E hardware being just too different from, 
say, the OMAP clock hardware for those to be consolidated.  In the 
former case we can work towards a solution and that code currently in 
next won't make it to mainline, or in the later case... well... we'll 
have to live with it.  If in doubt let's simply ask the opinion of those 
mainline people who said they're willing to help with advices.  If in 
the end they have no better solutions than what we have now then it will 
be harder for them to complain.

> Looking at the other file, prcmu-db8500.c seems to contain at least 5 sets
> of mailbox support code.  Take a look at "Subject: [PATCH 9/9] mach-ux500:
> add DB5500 PRCMU interface" from Linus Walleij on 31st March on this list
> for the patch.  Are we sure that this couldn't be consolidated in some
> way, at least at file level?
> 
> So while you can say about not getting hung up about LOC, LOC is a good
> indication that things are still going wrong in much the same way.

Agreed.  My point is, we shouldn't be afraid to add more code if that 
code is allowing for some consolidation to happen down the road, which 
should be the case with the initial subject of this thread.


Nicolas

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 16:06                     ` Nicolas Pitre
  0 siblings, 0 replies; 383+ messages in thread
From: Nicolas Pitre @ 2011-04-14 16:06 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Benjamin Herrenschmidt, Jeremy Kerr, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Sascha Hauer, Paul Mundt, lkml,
	Dima Zavin, Saravana Kannan, Ben Dooks, Uwe Kleine-König,
	linux-arm-kernel

On Thu, 14 Apr 2011, Russell King - ARM Linux wrote:

> On Thu, Apr 14, 2011 at 09:39:58AM -0400, Nicolas Pitre wrote:
> > However we can and must do better in consolidation work in order to make 
> > the tree more maintainable of course.  _That_ is the real issue and 
> > _that_ is what the ARM tree sucks at.  The fact that this consolidation 
> > work might reduce the size of the ARM code is only a side effect, not 
> > the primary goal.  So let's not get too hung up about LOC but focus on 
> > improving the infrastructure instead.
> 
> Look, this is what is in amongst the 6K lines of new code - these are
> the top two in the diffstat with the highest number of additional lines:
> 
>  arch/arm/mach-ux500/clock-db8500.c                 | 1291 +++++++++++++
>  arch/arm/mach-ux500/prcmu-db8500.c                 | 2018 ++++++++++++++++++++
> 
> These comprise 50% of the 6K of new code.  clock-db8500.c is a mixture
> of code and data declarations for individual clocks - which is essentially
> what Linus picked up with his complaint on under OMAP.  That in itself
> makes me worried.

Sure.  So... let's see what we can do about it.  Having 1300 lines only 
for clock stuff on only one platform certainly looks silly.  Either we 
can consolidate some of that stuff with another similar-enough platform, 
or we're stuck with the ST-E hardware being just too different from, 
say, the OMAP clock hardware for those to be consolidated.  In the 
former case we can work towards a solution and that code currently in 
next won't make it to mainline, or in the later case... well... we'll 
have to live with it.  If in doubt let's simply ask the opinion of those 
mainline people who said they're willing to help with advices.  If in 
the end they have no better solutions than what we have now then it will 
be harder for them to complain.

> Looking at the other file, prcmu-db8500.c seems to contain at least 5 sets
> of mailbox support code.  Take a look at "Subject: [PATCH 9/9] mach-ux500:
> add DB5500 PRCMU interface" from Linus Walleij on 31st March on this list
> for the patch.  Are we sure that this couldn't be consolidated in some
> way, at least at file level?
> 
> So while you can say about not getting hung up about LOC, LOC is a good
> indication that things are still going wrong in much the same way.

Agreed.  My point is, we shouldn't be afraid to add more code if that 
code is allowing for some consolidation to happen down the road, which 
should be the case with the initial subject of this thread.


Nicolas

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 16:06                     ` Nicolas Pitre
  0 siblings, 0 replies; 383+ messages in thread
From: Nicolas Pitre @ 2011-04-14 16:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 14 Apr 2011, Russell King - ARM Linux wrote:

> On Thu, Apr 14, 2011 at 09:39:58AM -0400, Nicolas Pitre wrote:
> > However we can and must do better in consolidation work in order to make 
> > the tree more maintainable of course.  _That_ is the real issue and 
> > _that_ is what the ARM tree sucks at.  The fact that this consolidation 
> > work might reduce the size of the ARM code is only a side effect, not 
> > the primary goal.  So let's not get too hung up about LOC but focus on 
> > improving the infrastructure instead.
> 
> Look, this is what is in amongst the 6K lines of new code - these are
> the top two in the diffstat with the highest number of additional lines:
> 
>  arch/arm/mach-ux500/clock-db8500.c                 | 1291 +++++++++++++
>  arch/arm/mach-ux500/prcmu-db8500.c                 | 2018 ++++++++++++++++++++
> 
> These comprise 50% of the 6K of new code.  clock-db8500.c is a mixture
> of code and data declarations for individual clocks - which is essentially
> what Linus picked up with his complaint on under OMAP.  That in itself
> makes me worried.

Sure.  So... let's see what we can do about it.  Having 1300 lines only 
for clock stuff on only one platform certainly looks silly.  Either we 
can consolidate some of that stuff with another similar-enough platform, 
or we're stuck with the ST-E hardware being just too different from, 
say, the OMAP clock hardware for those to be consolidated.  In the 
former case we can work towards a solution and that code currently in 
next won't make it to mainline, or in the later case... well... we'll 
have to live with it.  If in doubt let's simply ask the opinion of those 
mainline people who said they're willing to help with advices.  If in 
the end they have no better solutions than what we have now then it will 
be harder for them to complain.

> Looking at the other file, prcmu-db8500.c seems to contain at least 5 sets
> of mailbox support code.  Take a look at "Subject: [PATCH 9/9] mach-ux500:
> add DB5500 PRCMU interface" from Linus Walleij on 31st March on this list
> for the patch.  Are we sure that this couldn't be consolidated in some
> way, at least at file level?
> 
> So while you can say about not getting hung up about LOC, LOC is a good
> indication that things are still going wrong in much the same way.

Agreed.  My point is, we shouldn't be afraid to add more code if that 
code is allowing for some consolidation to happen down the road, which 
should be the case with the initial subject of this thread.


Nicolas

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-04-14 10:32           ` Russell King - ARM Linux
  (?)
@ 2011-04-14 16:08             ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-04-14 16:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 14, 2011 at 11:32:00AM +0100, Russell King - ARM Linux wrote:
> On Thu, Apr 14, 2011 at 08:25:05PM +1000, Benjamin Herrenschmidt wrote:
> > On Thu, 2011-04-14 at 11:00 +0100, Russell King - ARM Linux wrote:
> > > 
> > > I will take it, but at the moment I'm rather unhappy about the response
> > > from the community to Linus' complaint.
> > > 
> > > If existing platform maintainers can show that moving over to this will
> > > result in a net reduction of code under arch/arm, then that will be good.
> > > What I don't want to see at the moment is arch/arm increasing in size as
> > > a result of any change.  We desperately need to see a reduction for the
> > > next merge window.
> > 
> > It's a chicken and egg... platform maintainers wait for you to take it
> > and you wait for them to take it :-)
> > 
> > It seems to me that this fits well into the category of "better common
> > abstractions" that was discussed in the thread initiated by Linus as one
> > of the ways to improve on the "clutter"...
> 
> That depends - sometimes creating generic stuff results in a net increase
> in the overall size, and that's something that Linus also complained about.
> 
> According to linux-next, where we are at the moment with arch/arm is a
> net increase of 6000 lines since the close of the last merge window,
> and arch/arm is responsible for almost 75% of arch/ changes.  It looks
> very much like the same situation which Linus complained about.
Well, looking at the output of

	git diff --dirstat=3 linus/master...next/master -- arch

(with linus/master = 85f2e689a and next/master = 9e06a6ea7) I think
the main culprit is 12dc7eff5 that moved arch/arm/mach-mx3 to
arch/arm/mach-imx. (75 files changed, 9783 insertions(+), 9731
deletions(-)) That's a part of the effort to consolidate the i.MX
platforms and allow to compile more SoCs in a single image.

That commit accounts for more than the half of the (loc) changes in
arch/arm.

OK, this doesn't discuss away the 6000 added lines, but at least the
percentage thingy. And I think when you point out this commit Linus will
be much quiter when replying to your pull request.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 16:08             ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-04-14 16:08 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Benjamin Herrenschmidt, Jeremy Kerr, Nicolas Pitre,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Sascha Hauer,
	Paul Mundt, linux-kernel, Dima Zavin, Saravana Kannan, Ben Dooks,
	linux-arm-kernel

On Thu, Apr 14, 2011 at 11:32:00AM +0100, Russell King - ARM Linux wrote:
> On Thu, Apr 14, 2011 at 08:25:05PM +1000, Benjamin Herrenschmidt wrote:
> > On Thu, 2011-04-14 at 11:00 +0100, Russell King - ARM Linux wrote:
> > > 
> > > I will take it, but at the moment I'm rather unhappy about the response
> > > from the community to Linus' complaint.
> > > 
> > > If existing platform maintainers can show that moving over to this will
> > > result in a net reduction of code under arch/arm, then that will be good.
> > > What I don't want to see at the moment is arch/arm increasing in size as
> > > a result of any change.  We desperately need to see a reduction for the
> > > next merge window.
> > 
> > It's a chicken and egg... platform maintainers wait for you to take it
> > and you wait for them to take it :-)
> > 
> > It seems to me that this fits well into the category of "better common
> > abstractions" that was discussed in the thread initiated by Linus as one
> > of the ways to improve on the "clutter"...
> 
> That depends - sometimes creating generic stuff results in a net increase
> in the overall size, and that's something that Linus also complained about.
> 
> According to linux-next, where we are at the moment with arch/arm is a
> net increase of 6000 lines since the close of the last merge window,
> and arch/arm is responsible for almost 75% of arch/ changes.  It looks
> very much like the same situation which Linus complained about.
Well, looking at the output of

	git diff --dirstat=3 linus/master...next/master -- arch

(with linus/master == 85f2e689a and next/master == 9e06a6ea7) I think
the main culprit is 12dc7eff5 that moved arch/arm/mach-mx3 to
arch/arm/mach-imx. (75 files changed, 9783 insertions(+), 9731
deletions(-)) That's a part of the effort to consolidate the i.MX
platforms and allow to compile more SoCs in a single image.

That commit accounts for more than the half of the (loc) changes in
arch/arm.

OK, this doesn't discuss away the 6000 added lines, but at least the
percentage thingy. And I think when you point out this commit Linus will
be much quiter when replying to your pull request.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 16:08             ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-04-14 16:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 14, 2011 at 11:32:00AM +0100, Russell King - ARM Linux wrote:
> On Thu, Apr 14, 2011 at 08:25:05PM +1000, Benjamin Herrenschmidt wrote:
> > On Thu, 2011-04-14 at 11:00 +0100, Russell King - ARM Linux wrote:
> > > 
> > > I will take it, but at the moment I'm rather unhappy about the response
> > > from the community to Linus' complaint.
> > > 
> > > If existing platform maintainers can show that moving over to this will
> > > result in a net reduction of code under arch/arm, then that will be good.
> > > What I don't want to see at the moment is arch/arm increasing in size as
> > > a result of any change.  We desperately need to see a reduction for the
> > > next merge window.
> > 
> > It's a chicken and egg... platform maintainers wait for you to take it
> > and you wait for them to take it :-)
> > 
> > It seems to me that this fits well into the category of "better common
> > abstractions" that was discussed in the thread initiated by Linus as one
> > of the ways to improve on the "clutter"...
> 
> That depends - sometimes creating generic stuff results in a net increase
> in the overall size, and that's something that Linus also complained about.
> 
> According to linux-next, where we are at the moment with arch/arm is a
> net increase of 6000 lines since the close of the last merge window,
> and arch/arm is responsible for almost 75% of arch/ changes.  It looks
> very much like the same situation which Linus complained about.
Well, looking at the output of

	git diff --dirstat=3 linus/master...next/master -- arch

(with linus/master == 85f2e689a and next/master == 9e06a6ea7) I think
the main culprit is 12dc7eff5 that moved arch/arm/mach-mx3 to
arch/arm/mach-imx. (75 files changed, 9783 insertions(+), 9731
deletions(-)) That's a part of the effort to consolidate the i.MX
platforms and allow to compile more SoCs in a single image.

That commit accounts for more than the half of the (loc) changes in
arch/arm.

OK, this doesn't discuss away the 6000 added lines, but at least the
percentage thingy. And I think when you point out this commit Linus will
be much quiter when replying to your pull request.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-04-14 15:38                   ` Russell King - ARM Linux
  (?)
@ 2011-04-14 17:20                     ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-04-14 17:20 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

On Thu, Apr 14, 2011 at 04:38:14PM +0100, Russell King - ARM Linux wrote:
> On Thu, Apr 14, 2011 at 09:39:58AM -0400, Nicolas Pitre wrote:
> Now, the next thing is that Linus hasn't been too happy about driver stuff
> coming via my tree either - it's something which has been the subject of
> concern in private email.  I've _already_ said something about that prior
> to the recent merge window.  So should I take the clk API stuff which
> touches the drivers subtree?  If yes, it needs to be kept entirely separate
> from the rest of the ARM stuff so we don't end up mixing drivers stuff with
> ARM stuff.
OK, so the solution is to put this in a seperate branch. But then when
platform maintainers start working with it the resulting changes will
most probably go to arch/arm. So if Linus doesn't want to pull a tree
that touches both drivers/clk and arch/arm, then either he has to pull
the clk branch first or we have to wait for the next merge window until
we can use it.

I prefer the former.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 17:20                     ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-04-14 17:20 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Nicolas Pitre, Benjamin Herrenschmidt, Jeremy Kerr,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Sascha Hauer,
	Paul Mundt, lkml, Dima Zavin, Saravana Kannan, Ben Dooks,
	linux-arm-kernel

Hello,

On Thu, Apr 14, 2011 at 04:38:14PM +0100, Russell King - ARM Linux wrote:
> On Thu, Apr 14, 2011 at 09:39:58AM -0400, Nicolas Pitre wrote:
> Now, the next thing is that Linus hasn't been too happy about driver stuff
> coming via my tree either - it's something which has been the subject of
> concern in private email.  I've _already_ said something about that prior
> to the recent merge window.  So should I take the clk API stuff which
> touches the drivers subtree?  If yes, it needs to be kept entirely separate
> from the rest of the ARM stuff so we don't end up mixing drivers stuff with
> ARM stuff.
OK, so the solution is to put this in a seperate branch. But then when
platform maintainers start working with it the resulting changes will
most probably go to arch/arm. So if Linus doesn't want to pull a tree
that touches both drivers/clk and arch/arm, then either he has to pull
the clk branch first or we have to wait for the next merge window until
we can use it.

I prefer the former.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 17:20                     ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-04-14 17:20 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

On Thu, Apr 14, 2011 at 04:38:14PM +0100, Russell King - ARM Linux wrote:
> On Thu, Apr 14, 2011 at 09:39:58AM -0400, Nicolas Pitre wrote:
> Now, the next thing is that Linus hasn't been too happy about driver stuff
> coming via my tree either - it's something which has been the subject of
> concern in private email.  I've _already_ said something about that prior
> to the recent merge window.  So should I take the clk API stuff which
> touches the drivers subtree?  If yes, it needs to be kept entirely separate
> from the rest of the ARM stuff so we don't end up mixing drivers stuff with
> ARM stuff.
OK, so the solution is to put this in a seperate branch. But then when
platform maintainers start working with it the resulting changes will
most probably go to arch/arm. So if Linus doesn't want to pull a tree
that touches both drivers/clk and arch/arm, then either he has to pull
the clk branch first or we have to wait for the next merge window until
we can use it.

I prefer the former.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-04-14 12:09               ` Russell King - ARM Linux
  (?)
@ 2011-04-14 19:29                 ` Saravana Kannan
  -1 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-04-14 19:29 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/14/2011 05:09 AM, Russell King - ARM Linux wrote:
> On Thu, Apr 14, 2011 at 07:59:58AM -0400, Nicolas Pitre wrote:
>> On Thu, 14 Apr 2011, Russell King - ARM Linux wrote:
>>
>>> On Thu, Apr 14, 2011 at 08:25:05PM +1000, Benjamin Herrenschmidt wrote:
>>>> On Thu, 2011-04-14 at 11:00 +0100, Russell King - ARM Linux wrote:
>>>>>
>>>>> I will take it, but at the moment I'm rather unhappy about the response
>>>>> from the community to Linus' complaint.
>>>>>
>>>>> If existing platform maintainers can show that moving over to this will
>>>>> result in a net reduction of code under arch/arm, then that will be good.
>>>>> What I don't want to see at the moment is arch/arm increasing in size as
>>>>> a result of any change.  We desperately need to see a reduction for the
>>>>> next merge window.
>>>>
>>>> It's a chicken and egg... platform maintainers wait for you to take it
>>>> and you wait for them to take it :-)
>>>>
>>>> It seems to me that this fits well into the category of "better common
>>>> abstractions" that was discussed in the thread initiated by Linus as one
>>>> of the ways to improve on the "clutter"...
>>>
>>> That depends - sometimes creating generic stuff results in a net increase
>>> in the overall size, and that's something that Linus also complained about.
>>>
>>> According to linux-next, where we are at the moment with arch/arm is a
>>> net increase of 6000 lines since the close of the last merge window,
>>> and arch/arm is responsible for almost 75% of arch/ changes.  It looks
>>> very much like the same situation which Linus complained about.
>>
>> Quoting Linus:
>>
>> | Umm. The whole "number of lines of code" thing has become a total red
>> | herring.
>> |
>> | THAT IS NOT WHY I STARTED TO COMPLAIN!
>> |
>> | The reason I point out the number of lines of code is because it's one
>> | of the more obvious _symptoms_ of the problem.
>>
>> So we need to work on infrastructure, and the clock API is exactly that.
>> Obviously adding it will increase the number of lines of code initially,
>> but eventually this will help _reduce_ them, and more importantly it
>> will allow for the reduction of mindless duplication of code that was
>> identified as being the actual problem causing maintenance pain.
>
> Adding it without anyone using it doesn't solve anything.  We need
> people to commit to producing patches to use it for the next merge
> window.

Russell,

In your first reply to Jeremy you said this:
"I will take it, but at the moment I'm rather unhappy about the response
from the community to Linus' complaint."

So, if you are going to pull in his patches for the next merge, you can 
ignore this most of this email.

Talking for MSM, I'm waiting for some kind of certainty that these APIs 
will not be changed again before I rework our clock code to it. Even if 
I decide to move to this new framework without that certainty, it's 
going to be hard to convince driver teams to start using this new API if 
it's not already accepted upstream. At which point we would be back to 
square one -- "we need to see drivers (clock consumers) use these new 
APIs/rework before we pull it in".

Long story short, it's exactly the chicken and egg problem Nicolas was 
talking about and we need to break the egg :-)

Also, Jeremy's changes are more than just consolidation. They add 
clk_prepare/clk_unprepare APIs and those would be quite beneficial to 
quite a few machs/archs.

> And if you think its not about lines of code - grab the current linux-next
> tree and look at the diff between v2.6.39-rc1 and master for arch/arm, and
> then tell me whether using LOC is unreasonable given the patch content.

I'm sure lines of code is important, but saying we won't add any 
architectural improvements because it adds LOC seems backwards. If we go 
by that policy, the end result would be a freeze of the kernel.

Btw, what's your position on device tree for ARM? Device tree should 
help out a lot with clock data taking up too many LOCs.

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 19:29                 ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-04-14 19:29 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Nicolas Pitre, Benjamin Herrenschmidt, Jeremy Kerr,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Sascha Hauer,
	Paul Mundt, lkml, Dima Zavin, Ben Dooks, Uwe Kleine-König,
	linux-arm-kernel

On 04/14/2011 05:09 AM, Russell King - ARM Linux wrote:
> On Thu, Apr 14, 2011 at 07:59:58AM -0400, Nicolas Pitre wrote:
>> On Thu, 14 Apr 2011, Russell King - ARM Linux wrote:
>>
>>> On Thu, Apr 14, 2011 at 08:25:05PM +1000, Benjamin Herrenschmidt wrote:
>>>> On Thu, 2011-04-14 at 11:00 +0100, Russell King - ARM Linux wrote:
>>>>>
>>>>> I will take it, but at the moment I'm rather unhappy about the response
>>>>> from the community to Linus' complaint.
>>>>>
>>>>> If existing platform maintainers can show that moving over to this will
>>>>> result in a net reduction of code under arch/arm, then that will be good.
>>>>> What I don't want to see at the moment is arch/arm increasing in size as
>>>>> a result of any change.  We desperately need to see a reduction for the
>>>>> next merge window.
>>>>
>>>> It's a chicken and egg... platform maintainers wait for you to take it
>>>> and you wait for them to take it :-)
>>>>
>>>> It seems to me that this fits well into the category of "better common
>>>> abstractions" that was discussed in the thread initiated by Linus as one
>>>> of the ways to improve on the "clutter"...
>>>
>>> That depends - sometimes creating generic stuff results in a net increase
>>> in the overall size, and that's something that Linus also complained about.
>>>
>>> According to linux-next, where we are at the moment with arch/arm is a
>>> net increase of 6000 lines since the close of the last merge window,
>>> and arch/arm is responsible for almost 75% of arch/ changes.  It looks
>>> very much like the same situation which Linus complained about.
>>
>> Quoting Linus:
>>
>> | Umm. The whole "number of lines of code" thing has become a total red
>> | herring.
>> |
>> | THAT IS NOT WHY I STARTED TO COMPLAIN!
>> |
>> | The reason I point out the number of lines of code is because it's one
>> | of the more obvious _symptoms_ of the problem.
>>
>> So we need to work on infrastructure, and the clock API is exactly that.
>> Obviously adding it will increase the number of lines of code initially,
>> but eventually this will help _reduce_ them, and more importantly it
>> will allow for the reduction of mindless duplication of code that was
>> identified as being the actual problem causing maintenance pain.
>
> Adding it without anyone using it doesn't solve anything.  We need
> people to commit to producing patches to use it for the next merge
> window.

Russell,

In your first reply to Jeremy you said this:
"I will take it, but at the moment I'm rather unhappy about the response
from the community to Linus' complaint."

So, if you are going to pull in his patches for the next merge, you can 
ignore this most of this email.

Talking for MSM, I'm waiting for some kind of certainty that these APIs 
will not be changed again before I rework our clock code to it. Even if 
I decide to move to this new framework without that certainty, it's 
going to be hard to convince driver teams to start using this new API if 
it's not already accepted upstream. At which point we would be back to 
square one -- "we need to see drivers (clock consumers) use these new 
APIs/rework before we pull it in".

Long story short, it's exactly the chicken and egg problem Nicolas was 
talking about and we need to break the egg :-)

Also, Jeremy's changes are more than just consolidation. They add 
clk_prepare/clk_unprepare APIs and those would be quite beneficial to 
quite a few machs/archs.

> And if you think its not about lines of code - grab the current linux-next
> tree and look at the diff between v2.6.39-rc1 and master for arch/arm, and
> then tell me whether using LOC is unreasonable given the patch content.

I'm sure lines of code is important, but saying we won't add any 
architectural improvements because it adds LOC seems backwards. If we go 
by that policy, the end result would be a freeze of the kernel.

Btw, what's your position on device tree for ARM? Device tree should 
help out a lot with clock data taking up too many LOCs.

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-14 19:29                 ` Saravana Kannan
  0 siblings, 0 replies; 383+ messages in thread
From: Saravana Kannan @ 2011-04-14 19:29 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/14/2011 05:09 AM, Russell King - ARM Linux wrote:
> On Thu, Apr 14, 2011 at 07:59:58AM -0400, Nicolas Pitre wrote:
>> On Thu, 14 Apr 2011, Russell King - ARM Linux wrote:
>>
>>> On Thu, Apr 14, 2011 at 08:25:05PM +1000, Benjamin Herrenschmidt wrote:
>>>> On Thu, 2011-04-14 at 11:00 +0100, Russell King - ARM Linux wrote:
>>>>>
>>>>> I will take it, but at the moment I'm rather unhappy about the response
>>>>> from the community to Linus' complaint.
>>>>>
>>>>> If existing platform maintainers can show that moving over to this will
>>>>> result in a net reduction of code under arch/arm, then that will be good.
>>>>> What I don't want to see at the moment is arch/arm increasing in size as
>>>>> a result of any change.  We desperately need to see a reduction for the
>>>>> next merge window.
>>>>
>>>> It's a chicken and egg... platform maintainers wait for you to take it
>>>> and you wait for them to take it :-)
>>>>
>>>> It seems to me that this fits well into the category of "better common
>>>> abstractions" that was discussed in the thread initiated by Linus as one
>>>> of the ways to improve on the "clutter"...
>>>
>>> That depends - sometimes creating generic stuff results in a net increase
>>> in the overall size, and that's something that Linus also complained about.
>>>
>>> According to linux-next, where we are at the moment with arch/arm is a
>>> net increase of 6000 lines since the close of the last merge window,
>>> and arch/arm is responsible for almost 75% of arch/ changes.  It looks
>>> very much like the same situation which Linus complained about.
>>
>> Quoting Linus:
>>
>> | Umm. The whole "number of lines of code" thing has become a total red
>> | herring.
>> |
>> | THAT IS NOT WHY I STARTED TO COMPLAIN!
>> |
>> | The reason I point out the number of lines of code is because it's one
>> | of the more obvious _symptoms_ of the problem.
>>
>> So we need to work on infrastructure, and the clock API is exactly that.
>> Obviously adding it will increase the number of lines of code initially,
>> but eventually this will help _reduce_ them, and more importantly it
>> will allow for the reduction of mindless duplication of code that was
>> identified as being the actual problem causing maintenance pain.
>
> Adding it without anyone using it doesn't solve anything.  We need
> people to commit to producing patches to use it for the next merge
> window.

Russell,

In your first reply to Jeremy you said this:
"I will take it, but at the moment I'm rather unhappy about the response
from the community to Linus' complaint."

So, if you are going to pull in his patches for the next merge, you can 
ignore this most of this email.

Talking for MSM, I'm waiting for some kind of certainty that these APIs 
will not be changed again before I rework our clock code to it. Even if 
I decide to move to this new framework without that certainty, it's 
going to be hard to convince driver teams to start using this new API if 
it's not already accepted upstream. At which point we would be back to 
square one -- "we need to see drivers (clock consumers) use these new 
APIs/rework before we pull it in".

Long story short, it's exactly the chicken and egg problem Nicolas was 
talking about and we need to break the egg :-)

Also, Jeremy's changes are more than just consolidation. They add 
clk_prepare/clk_unprepare APIs and those would be quite beneficial to 
quite a few machs/archs.

> And if you think its not about lines of code - grab the current linux-next
> tree and look at the diff between v2.6.39-rc1 and master for arch/arm, and
> then tell me whether using LOC is unreasonable given the patch content.

I'm sure lines of code is important, but saying we won't add any 
architectural improvements because it adds LOC seems backwards. If we go 
by that policy, the end result would be a freeze of the kernel.

Btw, what's your position on device tree for ARM? Device tree should 
help out a lot with clock data taking up too many LOCs.

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-04-14 15:38                   ` Russell King - ARM Linux
  (?)
@ 2011-04-18 10:54                     ` Paul Mundt
  -1 siblings, 0 replies; 383+ messages in thread
From: Paul Mundt @ 2011-04-18 10:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 14, 2011 at 04:38:14PM +0100, Russell King - ARM Linux wrote:
> On Thu, Apr 14, 2011 at 09:39:58AM -0400, Nicolas Pitre wrote:
> > However we can and must do better in consolidation work in order to make 
> > the tree more maintainable of course.  _That_ is the real issue and 
> > _that_ is what the ARM tree sucks at.  The fact that this consolidation 
> > work might reduce the size of the ARM code is only a side effect, not 
> > the primary goal.  So let's not get too hung up about LOC but focus on 
> > improving the infrastructure instead.
> 
> Look, this is what is in amongst the 6K lines of new code - these are
> the top two in the diffstat with the highest number of additional lines:
> 
>  arch/arm/mach-ux500/clock-db8500.c                 | 1291 +++++++++++++
>  arch/arm/mach-ux500/prcmu-db8500.c                 | 2018 ++++++++++++++++++++
> 
> These comprise 50% of the 6K of new code.  clock-db8500.c is a mixture
> of code and data declarations for individual clocks - which is essentially
> what Linus picked up with his complaint on under OMAP.  That in itself
> makes me worried.
> 
A common struct clk implementation will at least allow you to whittle
this number down a bit, but it's obviously not possible to attempt to
work with the generic infrastructure prior to it being merged. Given that
there is nothing ARM-specific about the patch series it doesn't much
matter which tree it ultimately gets merged through, so long as it's in
place for people to build on top of for the next merge window.

> Now, the next thing is that Linus hasn't been too happy about driver stuff
> coming via my tree either - it's something which has been the subject of
> concern in private email.  I've _already_ said something about that prior
> to the recent merge window.  So should I take the clk API stuff which
> touches the drivers subtree?  If yes, it needs to be kept entirely separate
> from the rest of the ARM stuff so we don't end up mixing drivers stuff with
> ARM stuff.

ARM has been the defacto owner for the clock bits to date, but between
clkdev and a common struct clk it's certainly possible to move to a clock
tree and treat it the same as any other subsystem. Moving things out of
arch/arm and in to more generic maintenance paths certainly reduces the
chance for abuse -- and also provides a path for driver stuff.

SH and ARM-based SH/R-Mobile CPUs already share a clock framework, which
I've slowly been refactoring in preparation for Jeremy's common struct
clk. With that merged I'll be able to kill off a couple hundred lines
from the existing implementation at least.

If you'd prefer not to be the guinea pig for the clock bits going in to
.40 I'm certainly happy to take them in a topic branch, convert my
platforms on top of that and send the bits off to Linus early in the
merge window.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-18 10:54                     ` Paul Mundt
  0 siblings, 0 replies; 383+ messages in thread
From: Paul Mundt @ 2011-04-18 10:54 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Nicolas Pitre, Benjamin Herrenschmidt, Jeremy Kerr,
	Lorenzo Pieralisi, Vincent Guittot, linux-sh, Sascha Hauer, lkml,
	Dima Zavin, Saravana Kannan, Ben Dooks, Uwe Kleine-K?nig,
	linux-arm-kernel

On Thu, Apr 14, 2011 at 04:38:14PM +0100, Russell King - ARM Linux wrote:
> On Thu, Apr 14, 2011 at 09:39:58AM -0400, Nicolas Pitre wrote:
> > However we can and must do better in consolidation work in order to make 
> > the tree more maintainable of course.  _That_ is the real issue and 
> > _that_ is what the ARM tree sucks at.  The fact that this consolidation 
> > work might reduce the size of the ARM code is only a side effect, not 
> > the primary goal.  So let's not get too hung up about LOC but focus on 
> > improving the infrastructure instead.
> 
> Look, this is what is in amongst the 6K lines of new code - these are
> the top two in the diffstat with the highest number of additional lines:
> 
>  arch/arm/mach-ux500/clock-db8500.c                 | 1291 +++++++++++++
>  arch/arm/mach-ux500/prcmu-db8500.c                 | 2018 ++++++++++++++++++++
> 
> These comprise 50% of the 6K of new code.  clock-db8500.c is a mixture
> of code and data declarations for individual clocks - which is essentially
> what Linus picked up with his complaint on under OMAP.  That in itself
> makes me worried.
> 
A common struct clk implementation will at least allow you to whittle
this number down a bit, but it's obviously not possible to attempt to
work with the generic infrastructure prior to it being merged. Given that
there is nothing ARM-specific about the patch series it doesn't much
matter which tree it ultimately gets merged through, so long as it's in
place for people to build on top of for the next merge window.

> Now, the next thing is that Linus hasn't been too happy about driver stuff
> coming via my tree either - it's something which has been the subject of
> concern in private email.  I've _already_ said something about that prior
> to the recent merge window.  So should I take the clk API stuff which
> touches the drivers subtree?  If yes, it needs to be kept entirely separate
> from the rest of the ARM stuff so we don't end up mixing drivers stuff with
> ARM stuff.

ARM has been the defacto owner for the clock bits to date, but between
clkdev and a common struct clk it's certainly possible to move to a clock
tree and treat it the same as any other subsystem. Moving things out of
arch/arm and in to more generic maintenance paths certainly reduces the
chance for abuse -- and also provides a path for driver stuff.

SH and ARM-based SH/R-Mobile CPUs already share a clock framework, which
I've slowly been refactoring in preparation for Jeremy's common struct
clk. With that merged I'll be able to kill off a couple hundred lines
from the existing implementation at least.

If you'd prefer not to be the guinea pig for the clock bits going in to
.40 I'm certainly happy to take them in a topic branch, convert my
platforms on top of that and send the bits off to Linus early in the
merge window.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-18 10:54                     ` Paul Mundt
  0 siblings, 0 replies; 383+ messages in thread
From: Paul Mundt @ 2011-04-18 10:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 14, 2011 at 04:38:14PM +0100, Russell King - ARM Linux wrote:
> On Thu, Apr 14, 2011 at 09:39:58AM -0400, Nicolas Pitre wrote:
> > However we can and must do better in consolidation work in order to make 
> > the tree more maintainable of course.  _That_ is the real issue and 
> > _that_ is what the ARM tree sucks at.  The fact that this consolidation 
> > work might reduce the size of the ARM code is only a side effect, not 
> > the primary goal.  So let's not get too hung up about LOC but focus on 
> > improving the infrastructure instead.
> 
> Look, this is what is in amongst the 6K lines of new code - these are
> the top two in the diffstat with the highest number of additional lines:
> 
>  arch/arm/mach-ux500/clock-db8500.c                 | 1291 +++++++++++++
>  arch/arm/mach-ux500/prcmu-db8500.c                 | 2018 ++++++++++++++++++++
> 
> These comprise 50% of the 6K of new code.  clock-db8500.c is a mixture
> of code and data declarations for individual clocks - which is essentially
> what Linus picked up with his complaint on under OMAP.  That in itself
> makes me worried.
> 
A common struct clk implementation will at least allow you to whittle
this number down a bit, but it's obviously not possible to attempt to
work with the generic infrastructure prior to it being merged. Given that
there is nothing ARM-specific about the patch series it doesn't much
matter which tree it ultimately gets merged through, so long as it's in
place for people to build on top of for the next merge window.

> Now, the next thing is that Linus hasn't been too happy about driver stuff
> coming via my tree either - it's something which has been the subject of
> concern in private email.  I've _already_ said something about that prior
> to the recent merge window.  So should I take the clk API stuff which
> touches the drivers subtree?  If yes, it needs to be kept entirely separate
> from the rest of the ARM stuff so we don't end up mixing drivers stuff with
> ARM stuff.

ARM has been the defacto owner for the clock bits to date, but between
clkdev and a common struct clk it's certainly possible to move to a clock
tree and treat it the same as any other subsystem. Moving things out of
arch/arm and in to more generic maintenance paths certainly reduces the
chance for abuse -- and also provides a path for driver stuff.

SH and ARM-based SH/R-Mobile CPUs already share a clock framework, which
I've slowly been refactoring in preparation for Jeremy's common struct
clk. With that merged I'll be able to kill off a couple hundred lines
from the existing implementation at least.

If you'd prefer not to be the guinea pig for the clock bits going in to
.40 I'm certainly happy to take them in a topic branch, convert my
platforms on top of that and send the bits off to Linus early in the
merge window.

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-04-18 10:54                     ` Paul Mundt
  (?)
@ 2011-04-20 14:28                       ` Uwe Kleine-König
  -1 siblings, 0 replies; 383+ messages in thread
From:  @ 2011-04-20 14:28 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

On Mon, Apr 18, 2011 at 07:54:42PM +0900, Paul Mundt wrote:
> If you'd prefer not to be the guinea pig for the clock bits going in to
> .40 I'm certainly happy to take them in a topic branch, convert my
> platforms on top of that and send the bits off to Linus early in the
> merge window.
To get this forward I set up a branch with the generic bits sent to the
list so far. I really think this should be fixed better now than later
to give enough time for potential users of the new API to implement it
for their platform.

The following changes since commit f0e615c3cb72b42191b558c130409335812621d8:

  Linux 2.6.39-rc4 (2011-04-18 21:26:00 -0700)

are available in the git repository at:
  git://git.pengutronix.de/git/ukl/linux-2.6.git common-struct-clk

Jeremy Kerr (2):
      Add a common struct clk
      clk: Generic support for fixed-rate clocks

Russell King - ARM Linux (1):
      Fix clkdev return value for NULL clk case

Sascha Hauer (1):
      clk: Make NULL a valid clock again

 drivers/clk/Kconfig  |    3 +
 drivers/clk/Makefile |    1 +
 drivers/clk/clk.c    |  173 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/clkdev.c |   26 +++++---
 include/linux/clk.h  |  180 +++++++++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 364 insertions(+), 19 deletions(-)
 create mode 100644 drivers/clk/clk.c

I declare this to be stable, so assuming people are OK with it, you can
use that as a base to convert your platforms.

@Linus: I hope you're willing to pull this branch after .39?! (A public
"yes" might motivate one or the other maintainer to convert their
platform to it.)

There is a 2nd branch on that repository that also contains my RFC patch
just sent to this list in case you want to test it.

The following changes since commit 0ddb7f510fd51213801bf33194629fabf0818f39:

  clk: Make NULL a valid clock again (2011-04-20 16:02:29 +0200)

are available in the git repository at:
  git://git.pengutronix.de/git/ukl/linux-2.6.git common-struct-clk-wip

Uwe Kleine-König (1):
      [RFC] clk: add support for automatic parent handling

 drivers/clk/clk.c   |   43 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk.h |    8 ++++++++
 2 files changed, 51 insertions(+), 0 deletions(-)

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-20 14:28                       ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-04-20 14:28 UTC (permalink / raw)
  To: Paul Mundt
  Cc: Russell King - ARM Linux, Nicolas Pitre, Lorenzo Pieralisi,
	Vincent Guittot, linux-sh, Benjamin Herrenschmidt, Sascha Hauer,
	lkml, Dima Zavin, Saravana Kannan, Ben Dooks, Jeremy Kerr,
	linux-arm-kernel, Linus Torvalds

Hello,

On Mon, Apr 18, 2011 at 07:54:42PM +0900, Paul Mundt wrote:
> If you'd prefer not to be the guinea pig for the clock bits going in to
> .40 I'm certainly happy to take them in a topic branch, convert my
> platforms on top of that and send the bits off to Linus early in the
> merge window.
To get this forward I set up a branch with the generic bits sent to the
list so far. I really think this should be fixed better now than later
to give enough time for potential users of the new API to implement it
for their platform.

The following changes since commit f0e615c3cb72b42191b558c130409335812621d8:

  Linux 2.6.39-rc4 (2011-04-18 21:26:00 -0700)

are available in the git repository at:
  git://git.pengutronix.de/git/ukl/linux-2.6.git common-struct-clk

Jeremy Kerr (2):
      Add a common struct clk
      clk: Generic support for fixed-rate clocks

Russell King - ARM Linux (1):
      Fix clkdev return value for NULL clk case

Sascha Hauer (1):
      clk: Make NULL a valid clock again

 drivers/clk/Kconfig  |    3 +
 drivers/clk/Makefile |    1 +
 drivers/clk/clk.c    |  173 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/clkdev.c |   26 +++++---
 include/linux/clk.h  |  180 +++++++++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 364 insertions(+), 19 deletions(-)
 create mode 100644 drivers/clk/clk.c

I declare this to be stable, so assuming people are OK with it, you can
use that as a base to convert your platforms.

@Linus: I hope you're willing to pull this branch after .39?! (A public
"yes" might motivate one or the other maintainer to convert their
platform to it.)

There is a 2nd branch on that repository that also contains my RFC patch
just sent to this list in case you want to test it.

The following changes since commit 0ddb7f510fd51213801bf33194629fabf0818f39:

  clk: Make NULL a valid clock again (2011-04-20 16:02:29 +0200)

are available in the git repository at:
  git://git.pengutronix.de/git/ukl/linux-2.6.git common-struct-clk-wip

Uwe Kleine-König (1):
      [RFC] clk: add support for automatic parent handling

 drivers/clk/clk.c   |   43 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk.h |    8 ++++++++
 2 files changed, 51 insertions(+), 0 deletions(-)

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-20 14:28                       ` Uwe Kleine-König
  0 siblings, 0 replies; 383+ messages in thread
From: Uwe Kleine-König @ 2011-04-20 14:28 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

On Mon, Apr 18, 2011 at 07:54:42PM +0900, Paul Mundt wrote:
> If you'd prefer not to be the guinea pig for the clock bits going in to
> .40 I'm certainly happy to take them in a topic branch, convert my
> platforms on top of that and send the bits off to Linus early in the
> merge window.
To get this forward I set up a branch with the generic bits sent to the
list so far. I really think this should be fixed better now than later
to give enough time for potential users of the new API to implement it
for their platform.

The following changes since commit f0e615c3cb72b42191b558c130409335812621d8:

  Linux 2.6.39-rc4 (2011-04-18 21:26:00 -0700)

are available in the git repository at:
  git://git.pengutronix.de/git/ukl/linux-2.6.git common-struct-clk

Jeremy Kerr (2):
      Add a common struct clk
      clk: Generic support for fixed-rate clocks

Russell King - ARM Linux (1):
      Fix clkdev return value for NULL clk case

Sascha Hauer (1):
      clk: Make NULL a valid clock again

 drivers/clk/Kconfig  |    3 +
 drivers/clk/Makefile |    1 +
 drivers/clk/clk.c    |  173 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/clkdev.c |   26 +++++---
 include/linux/clk.h  |  180 +++++++++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 364 insertions(+), 19 deletions(-)
 create mode 100644 drivers/clk/clk.c

I declare this to be stable, so assuming people are OK with it, you can
use that as a base to convert your platforms.

@Linus: I hope you're willing to pull this branch after .39?! (A public
"yes" might motivate one or the other maintainer to convert their
platform to it.)

There is a 2nd branch on that repository that also contains my RFC patch
just sent to this list in case you want to test it.

The following changes since commit 0ddb7f510fd51213801bf33194629fabf0818f39:

  clk: Make NULL a valid clock again (2011-04-20 16:02:29 +0200)

are available in the git repository at:
  git://git.pengutronix.de/git/ukl/linux-2.6.git common-struct-clk-wip

Uwe Kleine-K?nig (1):
      [RFC] clk: add support for automatic parent handling

 drivers/clk/clk.c   |   43 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk.h |    8 ++++++++
 2 files changed, 51 insertions(+), 0 deletions(-)

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
  2011-04-20 14:28                       ` Uwe Kleine-König
  (?)
@ 2011-04-20 16:41                         ` Thomas Gleixner
  -1 siblings, 0 replies; 383+ messages in thread
From: Thomas Gleixner @ 2011-04-20 16:41 UTC (permalink / raw)
  To: linux-arm-kernel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 931 bytes --]

On Wed, 20 Apr 2011, Uwe Kleine-König wrote:
> I declare this to be stable, so assuming people are OK with it, you can
> use that as a base to convert your platforms.

You declare that stable? Interesting.
 
> There is a 2nd branch on that repository that also contains my RFC patch
> just sent to this list in case you want to test it.

Which is utter crap as I pointed out a few minutes ago.

Also that clk thing is neither stable nor complete. It's just designed
wrong. 

As long as it does not handle nested clocks proper and by default w/o
your tasteless add ons, it's just moving the status quo of ARM into a
common infrastructure file.

Yes, that's probably better than not having common infrastructure at
all, but trying to build up conversions on that lot would be a
complete waste of time and resources. Simply because you need to
convert the already converted stuff another time.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 383+ messages in thread

* Re: [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-20 16:41                         ` Thomas Gleixner
  0 siblings, 0 replies; 383+ messages in thread
From: Thomas Gleixner @ 2011-04-20 16:41 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Paul Mundt, Nicolas Pitre, Lorenzo Pieralisi, Vincent Guittot,
	linux-sh, Benjamin Herrenschmidt, Sascha Hauer, lkml, Dima Zavin,
	Saravana Kannan, Ben Dooks, Russell King - ARM Linux,
	Jeremy Kerr, Linus Torvalds, linux-arm-kernel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 906 bytes --]

On Wed, 20 Apr 2011, Uwe Kleine-König wrote:
> I declare this to be stable, so assuming people are OK with it, you can
> use that as a base to convert your platforms.

You declare that stable? Interesting.
 
> There is a 2nd branch on that repository that also contains my RFC patch
> just sent to this list in case you want to test it.

Which is utter crap as I pointed out a few minutes ago.

Also that clk thing is neither stable nor complete. It's just designed
wrong. 

As long as it does not handle nested clocks proper and by default w/o
your tasteless add ons, it's just moving the status quo of ARM into a
common infrastructure file.

Yes, that's probably better than not having common infrastructure at
all, but trying to build up conversions on that lot would be a
complete waste of time and resources. Simply because you need to
convert the already converted stuff another time.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
@ 2011-04-20 16:41                         ` Thomas Gleixner
  0 siblings, 0 replies; 383+ messages in thread
From: Thomas Gleixner @ 2011-04-20 16:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 20 Apr 2011, Uwe Kleine-K?nig wrote:
> I declare this to be stable, so assuming people are OK with it, you can
> use that as a base to convert your platforms.

You declare that stable? Interesting.
 
> There is a 2nd branch on that repository that also contains my RFC patch
> just sent to this list in case you want to test it.

Which is utter crap as I pointed out a few minutes ago.

Also that clk thing is neither stable nor complete. It's just designed
wrong. 

As long as it does not handle nested clocks proper and by default w/o
your tasteless add ons, it's just moving the status quo of ARM into a
common infrastructure file.

Yes, that's probably better than not having common infrastructure at
all, but trying to build up conversions on that lot would be a
complete waste of time and resources. Simply because you need to
convert the already converted stuff another time.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [PATCH 0/2] Common struct clk implementation, v14
  2011-04-20 16:41                         ` Thomas Gleixner
  (?)
  (?)
@ 2011-04-20 21:30                         ` Paul McKenney
  -1 siblings, 0 replies; 383+ messages in thread
From: Paul McKenney @ 2011-04-20 21:30 UTC (permalink / raw)
  To: linux-arm-kernel

2011/4/20 Thomas Gleixner <tglx@linutronix.de>

> On Wed, 20 Apr 2011, Uwe Kleine-K?nig wrote:
> > I declare this to be stable, so assuming people are OK with it, you can
> > use that as a base to convert your platforms.
>
> You declare that stable? Interesting.
>
> > There is a 2nd branch on that repository that also contains my RFC patch
> > just sent to this list in case you want to test it.
>
> Which is utter crap as I pointed out a few minutes ago.
>
> Also that clk thing is neither stable nor complete. It's just designed
> wrong.
>
> As long as it does not handle nested clocks proper and by default w/o
> your tasteless add ons, it's just moving the status quo of ARM into a
> common infrastructure file.
>
> Yes, that's probably better than not having common infrastructure at
> all, but trying to build up conversions on that lot would be a
> complete waste of time and resources. Simply because you need to
> convert the already converted stuff another time.
>

Hey, guys,

Thomas's words might seem a bit harsh, but he really does understand what
Linus's reaction will be.  And Thomas's words are much less harsh than the
ones that Linus would likely choose.  I wish we had a good example of a
common-clock structure elsewhere in the kernel, but the fact is that ARM has
a much wider variety of SoCs than pretty much any other architecture.  So we
might as well get something put in place to start with that will have a
decent chance of standing the test of time (and therefore being something
that Linus is likely to approve of).

Could you please take a look at what Thomas suggested (
http://lists.infradead.org/pipermail/linux-arm-kernel/2011-April/049013.html)
and give it a try?

                                                       Thanx, Paul
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110420/a84b1a97/attachment-0001.html>

^ permalink raw reply	[flat|nested] 383+ messages in thread

* RE: [RFC]
  2007-08-19 20:59 [RFC] Kirill Kuvaldin
@ 2007-08-20  4:47 ` Santos, Jose Renato G
  0 siblings, 0 replies; 383+ messages in thread
From: Santos, Jose Renato G @ 2007-08-20  4:47 UTC (permalink / raw)
  To: Kirill Kuvaldin, linux-cifs-client; +Cc: linux-fsdevel, oprofile-list

 

> -----Original Message-----
> From: oprofile-list-bounces@lists.sourceforge.net 
> [mailto:oprofile-list-bounces@lists.sourceforge.net] On 
> Behalf Of Kirill Kuvaldin
> Sent: Sunday, August 19, 2007 1:59 PM
> To: linux-cifs-client@lists.samba.org
> Cc: linux-fsdevel@vger.kernel.org; oprofile-list@lists.sourceforge.net
> Subject: [RFC]
> 
> Hi,
> 
> I tried running oprofile to identify performance bottlenecks 
> of the linux cifs client. I was actually doing the large read 
> from the samba server to the client machine over the gigabit 
> ethernet connection. The results of running oprofile 
> indicated that nearly 70% of samples were attributed to the 
> cifs_readpages() function:
> 
> of 0x00 (Unhalted core cycles) count 60000
> warning: could not check that the binary file /cifs has not 
> been modified since the profile was taken. Results may be inaccurate.
> samples  %        symbol name
> 17690    68.5951  cifs_readpages
> 1111      4.3080  cifs_demultiplex_thread
> 850       3.2960  cifs_writepages
> 768       2.9780  is_valid_oplock_break
> 747       2.8966  cifs_closedir
> 464       1.7992  SendReceive2
> 338       1.3106  sesInfoFree
> 255       0.9888  DeleteMidQEntry
> 255       0.9888  allocate_mid
> 237       0.9190  decode_negTokenInit
> 212       0.8221  SendReceive
> 212       0.8221  wait_for_response
> 184       0.7135  cifs_fsync
> 180       0.6980  header_assemble
> 168       0.6514  CIFSSMBRead
> 161       0.6243  cifs_close
> 139       0.5390  cifs_NTtimeToUnix
> ...
> 
> Looking further into "opannotate --assembly" results, I 
> noticed that virtually all sample hits were attributed to the 
> "rep movsl %ds:(%esi),%es:(%edi)" instruction
> 
>                :   129d9:       mov    0x40(%esp),%esi
>  17187 66.6447 :   129dd:       rep movsl %ds:(%esi),%es:(%edi)
>      4  0.0155 :   129df:       subl   $0x1000,0x44(%esp)
> 
> 
> which corresponds to the "memcpy(target, data, 
> PAGE_CACHE_SIZE);" line of the cifs_copy_cache_pages() 
> function, which was inlined by gcc.
> 
> What this seemed to mean was that we're doing memcpy most of 
> the cifs running time, copying the data from the temporary 
> buffer, allocated from cifs_demultiplex_thread, to the page cache.
> 
> My first thought was that if we managed to avoid doing this 
> unnecessary copy and read directly from the socket to the 
> page cache, there would be a performance boost on reads. I 
> tried modifying the cifs source code to eliminate that memcpy 
> -- in fact, I only commented out the memcpy line of
> cifs_copy_cache_pages() just to have an idea how big can be a 
> performance win if we would eliminate an unnecessary copy 
> without updating actual pages... Surprisingly enough, I 
> haven't noticed big differences between unmodified and 
> modified versions (the latter was about 3-5% faster) on 
> copying a big file on the same setup.
> 
> Are the results of oprofile inaccurate in some way or am I 
> missing something important?
> The only instruction (memcpy) taking the most of cifs running 
> time seems really odd...

Memory access instructions can take a long time if the access causes a
L3 cache miss or it can be much faster if the data is already on the L1
cache.(time will vary depending on which cache level the data is
located)
The high cost of your original memcpy() operation is probably due to
cache misses (probably L3 miss). Removing the memcpy() is probably
moving the cache misses to some point later in the code that access the
same data and which used to be faster because the data was already in
the cache (I am not sure where as I am not familiar with cifs code).
This would explain why removing the memcpy() does not provide big
savings. 
You can verify this hypothesis by profiling cache misses and confirming
where they happen in the modified and unmodfied code.
I hope this helps

Regards

Renato


-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/

^ permalink raw reply	[flat|nested] 383+ messages in thread

* [RFC]
@ 2007-08-19 20:59 Kirill Kuvaldin
  2007-08-20  4:47 ` [RFC] Santos, Jose Renato G
  0 siblings, 1 reply; 383+ messages in thread
From: Kirill Kuvaldin @ 2007-08-19 20:59 UTC (permalink / raw)
  To: linux-cifs-client; +Cc: oprofile-list, linux-fsdevel

Hi,

I tried running oprofile to identify performance bottlenecks of the linux
cifs client. I was actually doing the large read from the samba server to
the client machine over the gigabit ethernet connection. The results
of running oprofile indicated that nearly 70% of samples were attributed
to the cifs_readpages() function:

of 0x00 (Unhalted core cycles) count 60000
warning: could not check that the binary file /cifs has not been
modified since the profile was taken. Results may be inaccurate.
samples  %        symbol name
17690    68.5951  cifs_readpages
1111      4.3080  cifs_demultiplex_thread
850       3.2960  cifs_writepages
768       2.9780  is_valid_oplock_break
747       2.8966  cifs_closedir
464       1.7992  SendReceive2
338       1.3106  sesInfoFree
255       0.9888  DeleteMidQEntry
255       0.9888  allocate_mid
237       0.9190  decode_negTokenInit
212       0.8221  SendReceive
212       0.8221  wait_for_response
184       0.7135  cifs_fsync
180       0.6980  header_assemble
168       0.6514  CIFSSMBRead
161       0.6243  cifs_close
139       0.5390  cifs_NTtimeToUnix
...

Looking further into "opannotate --assembly" results, I noticed that
virtually all sample hits were attributed to
the "rep movsl %ds:(%esi),%es:(%edi)" instruction

               :   129d9:       mov    0x40(%esp),%esi
 17187 66.6447 :   129dd:       rep movsl %ds:(%esi),%es:(%edi)
     4  0.0155 :   129df:       subl   $0x1000,0x44(%esp)


which corresponds to the "memcpy(target, data, PAGE_CACHE_SIZE);" line of
the cifs_copy_cache_pages() function, which was inlined by gcc.

What this seemed to mean was that we're doing memcpy most of the cifs
running time, copying the data from the temporary buffer, allocated from
cifs_demultiplex_thread, to the page cache.

My first thought was that if we managed to avoid doing this unnecessary
copy and read directly from the socket to the page cache, there would be a
performance boost on reads. I tried modifying the cifs source code to
eliminate that memcpy -- in fact, I only commented out the memcpy line of
cifs_copy_cache_pages() just to have an idea how big can be a performance
win if we would eliminate an unnecessary copy without updating actual
pages... Surprisingly enough, I haven't noticed big differences between
unmodified and modified versions (the latter was about 3-5% faster)
on copying a big file on the same setup.

Are the results of oprofile inaccurate in some way or am I missing
something important?
The only instruction (memcpy) taking the most of cifs running time seems
really odd...


        Thanks,
        Kirill

^ permalink raw reply	[flat|nested] 383+ messages in thread

end of thread, other threads:[~2011-04-20 21:30 UTC | newest]

Thread overview: 383+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-02-01  9:11 Locking in the clk API, part 2: clk_prepare/clk_unprepare Jeremy Kerr
2011-02-01  9:11 ` Jeremy Kerr
2011-02-01  9:11 ` Jeremy Kerr
2011-02-01 10:54 ` 
2011-02-01 10:54   ` Uwe Kleine-König
2011-02-01 10:54   ` Uwe Kleine-König
2011-02-01 13:05   ` Jassi Brar
2011-02-01 13:05     ` Jassi Brar
2011-02-01 13:05     ` Jassi Brar
2011-02-01 14:00     ` 
2011-02-01 14:00       ` Uwe Kleine-König
2011-02-01 14:00       ` Uwe Kleine-König
2011-02-01 15:14       ` Russell King - ARM Linux
2011-02-01 15:14         ` Russell King - ARM Linux
2011-02-01 15:14         ` Russell King - ARM Linux
2011-02-01 15:22         ` 
2011-02-01 15:22           ` Uwe Kleine-König
2011-02-01 15:22           ` Uwe Kleine-König
2011-02-01 15:28           ` Russell King - ARM Linux
2011-02-01 15:28             ` Russell King - ARM Linux
2011-02-01 15:28             ` Russell King - ARM Linux
2011-02-01 20:57             ` Saravana Kannan
2011-02-01 20:57               ` Saravana Kannan
2011-02-01 20:57               ` Saravana Kannan
2011-02-02  2:31             ` Jassi Brar
2011-02-02  2:31               ` Jassi Brar
2011-02-02  2:31               ` Jassi Brar
2011-02-01 13:15   ` Russell King - ARM Linux
2011-02-01 13:15     ` Russell King - ARM Linux
2011-02-01 13:15     ` Russell King - ARM Linux
2011-02-01 14:18     ` 
2011-02-01 14:18       ` Uwe Kleine-König
2011-02-01 14:18       ` Uwe Kleine-König
2011-02-01 14:39       ` Russell King - ARM Linux
2011-02-01 14:39         ` Russell King - ARM Linux
2011-02-01 14:39         ` Russell King - ARM Linux
2011-02-01 15:18         ` 
2011-02-01 15:18           ` Uwe Kleine-König
2011-02-01 15:18           ` Uwe Kleine-König
2011-02-01 15:24           ` Russell King - ARM Linux
2011-02-01 15:24             ` Russell King - ARM Linux
2011-02-01 15:24             ` Russell King - ARM Linux
2011-02-01 15:53             ` 
2011-02-01 15:53               ` Uwe Kleine-König
2011-02-01 15:53               ` Uwe Kleine-König
2011-02-01 17:06               ` Russell King - ARM Linux
2011-02-01 17:06                 ` Russell King - ARM Linux
2011-02-01 17:06                 ` Russell King - ARM Linux
2011-02-01 19:32                 ` 
2011-02-01 19:32                   ` Uwe Kleine-König
2011-02-01 19:32                   ` Uwe Kleine-König
2011-02-01 19:56                   ` Russell King - ARM Linux
2011-02-01 19:56                     ` Russell King - ARM Linux
2011-02-01 19:56                     ` Russell King - ARM Linux
2011-02-01 20:21                     ` Saravana Kannan
2011-02-01 20:21                       ` Saravana Kannan
2011-02-01 20:21                       ` Saravana Kannan
2011-02-01 20:43                       ` 
2011-02-01 20:43                         ` Uwe Kleine-König
2011-02-01 20:43                         ` Uwe Kleine-König
2011-02-04  9:33                         ` Richard Zhao
2011-02-04  9:33                           ` Richard Zhao
2011-02-04  9:33                           ` Richard Zhao
2011-02-01 20:06                   ` Nicolas Pitre
2011-02-01 20:06                     ` Nicolas Pitre
2011-02-01 20:06                     ` Nicolas Pitre
2011-02-01 20:33             ` Saravana Kannan
2011-02-01 20:33               ` Saravana Kannan
2011-02-01 20:33               ` Saravana Kannan
2011-02-01 20:36               ` Russell King - ARM Linux
2011-02-01 20:36                 ` Russell King - ARM Linux
2011-02-01 20:36                 ` Russell King - ARM Linux
2011-02-01 20:59             ` Stephen Boyd
2011-02-01 20:59               ` Stephen Boyd
2011-02-01 20:59               ` Stephen Boyd
2011-02-01 21:24               ` Russell King - ARM Linux
2011-02-01 21:24                 ` Russell King - ARM Linux
2011-02-01 21:24                 ` Russell King - ARM Linux
2011-02-04  9:54                 ` Richard Zhao
2011-02-04  9:54                   ` Richard Zhao
2011-02-04  9:54                   ` Richard Zhao
2011-02-04 10:21                   ` 
2011-02-04 10:21                     ` Uwe Kleine-König
2011-02-04 10:21                     ` Uwe Kleine-König
2011-02-04 10:57                     ` Russell King - ARM Linux
2011-02-04 10:57                       ` Russell King - ARM Linux
2011-02-04 10:57                       ` Russell King - ARM Linux
2011-02-04 10:48                   ` Russell King - ARM Linux
2011-02-04 10:48                     ` Russell King - ARM Linux
2011-02-04 10:48                     ` Russell King - ARM Linux
2011-02-04 11:04                     ` Jassi Brar
2011-02-04 11:04                       ` Jassi Brar
2011-02-04 11:04                       ` Jassi Brar
2011-02-04 11:18                       ` Russell King - ARM Linux
2011-02-04 11:18                         ` Russell King - ARM Linux
2011-02-04 11:18                         ` Russell King - ARM Linux
2011-02-04 11:51                         ` Jassi Brar
2011-02-04 11:51                           ` Jassi Brar
2011-02-04 11:51                           ` Jassi Brar
2011-02-04 12:05                           ` Russell King - ARM Linux
2011-02-04 12:05                             ` Russell King - ARM Linux
2011-02-04 12:05                             ` Russell King - ARM Linux
2011-02-01 14:40       ` Jeremy Kerr
2011-02-01 14:40         ` Jeremy Kerr
2011-02-01 14:40         ` Jeremy Kerr
2011-02-04 12:45 ` Richard Zhao
2011-02-04 12:45   ` Richard Zhao
2011-02-04 12:45   ` Richard Zhao
2011-02-04 13:20   ` Russell King - ARM Linux
2011-02-04 13:20     ` Russell King - ARM Linux
2011-02-04 13:20     ` Russell King - ARM Linux
2011-02-07  6:07 ` [RFC,PATCH 1/3] Add a common struct clk Jeremy Kerr
2011-02-07  6:07   ` Jeremy Kerr
2011-02-07  6:07   ` Jeremy Kerr
2011-02-07  7:05   ` 
2011-02-07  7:05     ` Uwe Kleine-König
2011-02-07  7:05     ` Uwe Kleine-König
2011-02-07  7:09   ` 
2011-02-07  8:08   ` 
2011-02-07  8:08     ` Uwe Kleine-König
2011-02-07  8:08     ` Uwe Kleine-König
2011-02-07  8:21   ` Dima Zavin
2011-02-07  8:22     ` Jeremy Kerr
2011-02-07  8:22       ` Jeremy Kerr
2011-02-07  8:22       ` Jeremy Kerr
2011-02-07 19:59   ` Colin Cross
2011-02-07 19:59     ` Colin Cross
2011-02-07 19:59     ` Colin Cross
2011-02-08  1:40     ` Jeremy Kerr
2011-02-08  1:40       ` Jeremy Kerr
2011-02-08  1:40       ` Jeremy Kerr
2011-02-07 20:20   ` Ryan Mallon
2011-02-07 20:20     ` Ryan Mallon
2011-02-07 20:20     ` Ryan Mallon
2011-02-08  2:54     ` Jeremy Kerr
2011-02-08  2:54       ` Jeremy Kerr
2011-02-08  2:54       ` Jeremy Kerr
2011-02-08  3:30       ` Ryan Mallon
2011-02-08  3:30         ` Ryan Mallon
2011-02-08  3:30         ` Ryan Mallon
2011-02-08  7:28         ` Jeremy Kerr
2011-02-08  7:28           ` Jeremy Kerr
2011-02-08  7:28           ` Jeremy Kerr
2011-02-07  6:07 ` [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks Jeremy Kerr
2011-02-07  6:07   ` Jeremy Kerr
2011-02-07  6:07   ` Jeremy Kerr
2011-02-07  6:07 ` [RFC,PATCH 0/3] Common struct clk implementation, v11 Jeremy Kerr
2011-02-07  6:07   ` Jeremy Kerr
2011-02-07  6:07   ` Jeremy Kerr
2011-02-07  6:07 ` [RFC, Jeremy Kerr
2011-02-07  6:07   ` [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics Jeremy Kerr
2011-02-07  6:07   ` Jeremy Kerr
2011-02-07  6:29   ` Jassi Brar
2011-02-07  6:29     ` Jassi Brar
2011-02-07  6:29     ` Jassi Brar
2011-02-07  7:00     ` Jeremy Kerr
2011-02-07  7:00       ` Jeremy Kerr
2011-02-07  7:00       ` Jeremy Kerr
2011-02-07  8:05   ` [RFC, PATCH 3/3] clk: add warnings for incorrect 
2011-02-07  8:05     ` [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics Uwe Kleine-König
2011-02-07  8:05     ` Uwe Kleine-König
2011-02-07  8:08     ` Jeremy Kerr
2011-02-07  8:08       ` Jeremy Kerr
2011-02-07  8:08       ` Jeremy Kerr
2011-02-07 14:24       ` [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare Nicolas Pitre
2011-02-07 14:24         ` [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics Nicolas Pitre
2011-02-07 14:24         ` Nicolas Pitre
2011-02-10  4:26         ` [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare Saravana Kannan
2011-02-10  4:26           ` [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics Saravana Kannan
2011-02-10  4:26           ` Saravana Kannan
2011-02-09  6:41 ` [RFC,PATCH 0/3] Common struct clk implementation, v12 Jeremy Kerr
2011-02-09  6:41   ` Jeremy Kerr
2011-02-09  6:41   ` Jeremy Kerr
2011-02-09  6:41   ` [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks Jeremy Kerr
2011-02-09  6:41     ` Jeremy Kerr
2011-02-09  6:41     ` Jeremy Kerr
2011-02-09  6:58     ` Fabio Giovagnini
2011-02-09  6:58       ` Fabio Giovagnini
2011-02-09  6:58       ` Fabio Giovagnini
2011-02-10 23:23     ` Ryan Mallon
2011-02-10 23:23       ` Ryan Mallon
2011-02-10 23:23       ` Ryan Mallon
2011-02-15  1:41       ` Jeremy Kerr
2011-02-15  1:41         ` Jeremy Kerr
2011-02-15  1:41         ` Jeremy Kerr
2011-02-15  4:51         ` Saravana Kannan
2011-02-15  4:51           ` Saravana Kannan
2011-02-15  4:51           ` Saravana Kannan
2011-02-15  6:18           ` Jeremy Kerr
2011-02-15  6:18             ` Jeremy Kerr
2011-02-15  6:18             ` Jeremy Kerr
2011-02-15  6:31             ` Saravana Kannan
2011-02-15  6:31               ` Saravana Kannan
2011-02-15  6:31               ` Saravana Kannan
2011-02-09  6:41   ` [RFC, Jeremy Kerr
2011-02-09  6:41     ` [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics Jeremy Kerr
2011-02-09  6:41     ` Jeremy Kerr
2011-02-10  9:37     ` [RFC, PATCH 3/3] clk: add warnings for incorrect Richard Zhao
2011-02-10  9:37       ` [RFC, PATCH 3/3] clk: add warnings for incorrect enable/prepare semantics Richard Zhao
2011-02-10  9:37       ` Richard Zhao
2011-02-15  2:00       ` Jeremy Kerr
2011-02-15  2:00         ` Jeremy Kerr
2011-02-15  2:00         ` Jeremy Kerr
2011-02-09  6:41   ` [RFC,PATCH 1/3] Add a common struct clk Jeremy Kerr
2011-02-09  6:41     ` Jeremy Kerr
2011-02-09  6:41     ` Jeremy Kerr
2011-02-09  9:00     ` 
2011-02-09  9:00       ` Uwe Kleine-König
2011-02-09  9:00       ` Uwe Kleine-König
2011-02-09 20:21     ` Ryan Mallon
2011-02-09 20:21       ` Ryan Mallon
2011-02-09 20:21       ` Ryan Mallon
2011-02-09 20:39       ` 
2011-02-09 20:39         ` Uwe Kleine-König
2011-02-09 20:39         ` Uwe Kleine-König
2011-02-09 20:42         ` Ryan Mallon
2011-02-09 20:42           ` Ryan Mallon
2011-02-09 20:42           ` Ryan Mallon
2011-02-10 10:03       ` Richard Zhao
2011-02-10 10:03         ` Richard Zhao
2011-02-10 10:03         ` Richard Zhao
2011-02-10 10:10         ` Ryan Mallon
2011-02-10 10:10           ` Ryan Mallon
2011-02-10 10:10           ` Ryan Mallon
2011-02-10 12:45           ` Richard Zhao
2011-02-10 12:45             ` Richard Zhao
2011-02-10 12:45             ` Richard Zhao
2011-02-10 10:46         ` 
2011-02-10 10:46           ` Uwe Kleine-König
2011-02-10 10:46           ` Uwe Kleine-König
2011-02-10 13:08           ` Richard Zhao
2011-02-10 13:08             ` Richard Zhao
2011-02-10 13:08             ` Richard Zhao
2011-02-10 13:13             ` Russell King - ARM Linux
2011-02-10 13:13               ` Russell King - ARM Linux
2011-02-10 13:13               ` Russell King - ARM Linux
2011-02-15  1:36       ` Jeremy Kerr
2011-02-15  1:36         ` Jeremy Kerr
2011-02-15  1:36         ` Jeremy Kerr
2011-02-15  1:43         ` Ryan Mallon
2011-02-15  1:43           ` Ryan Mallon
2011-02-15  1:43           ` Ryan Mallon
2011-02-10  5:16     ` Saravana Kannan
2011-02-10  5:16       ` Saravana Kannan
2011-02-10  5:16       ` Saravana Kannan
2011-02-15  2:41       ` Jeremy Kerr
2011-02-15  2:41         ` Jeremy Kerr
2011-02-15  2:41         ` Jeremy Kerr
2011-02-15  5:33         ` Saravana Kannan
2011-02-15  5:33           ` Saravana Kannan
2011-02-15  5:33           ` Saravana Kannan
2011-02-15  7:26           ` Jeremy Kerr
2011-02-15  7:26             ` Jeremy Kerr
2011-02-15  7:26             ` Jeremy Kerr
2011-02-15  8:33             ` Saravana Kannan
2011-02-15  8:33               ` Saravana Kannan
2011-02-15  8:33               ` Saravana Kannan
2011-02-15  8:37             ` Russell King - ARM Linux
2011-02-15  8:37               ` Russell King - ARM Linux
2011-02-15  8:37               ` Russell King - ARM Linux
2011-02-15  9:33               ` Jeremy Kerr
2011-02-15  9:33                 ` Jeremy Kerr
2011-02-15  9:33                 ` Jeremy Kerr
2011-02-15 14:13                 ` Richard Zhao
2011-02-15 14:13                   ` Richard Zhao
2011-02-15 14:13                   ` Richard Zhao
2011-02-20 13:07                 ` Russell King - ARM Linux
2011-02-20 13:07                   ` Russell King - ARM Linux
2011-02-20 13:07                   ` Russell King - ARM Linux
2011-02-16  4:53           ` Saravana Kannan
2011-02-16  4:53             ` Saravana Kannan
2011-02-16  4:53             ` Saravana Kannan
2011-02-20 13:13           ` Russell King - ARM Linux
2011-02-20 13:13             ` Russell King - ARM Linux
2011-02-20 13:13             ` Russell King - ARM Linux
2011-02-21  2:50 ` [PATCH 0/2] Common struct clk implementation, v13 Jeremy Kerr
2011-02-21  2:50   ` Jeremy Kerr
2011-02-21  2:50   ` Jeremy Kerr
2011-02-21  2:50   ` [PATCH 1/2] Add a common struct clk Jeremy Kerr
2011-02-21  2:50     ` Jeremy Kerr
2011-02-21  2:50     ` Jeremy Kerr
2011-02-22 20:17     ` 
2011-02-22 20:17       ` Uwe Kleine-König
2011-02-22 20:17       ` Uwe Kleine-König
2011-02-23  2:49       ` Jeremy Kerr
2011-02-23  2:49         ` Jeremy Kerr
2011-02-23  2:49         ` Jeremy Kerr
2011-02-21  2:50   ` [PATCH 2/2] clk: Generic support for fixed-rate clocks Jeremy Kerr
2011-02-21  2:50     ` Jeremy Kerr
2011-02-21  2:50     ` Jeremy Kerr
2011-02-21 19:51     ` Ryan Mallon
2011-02-21 19:51       ` Ryan Mallon
2011-02-21 19:51       ` Ryan Mallon
2011-02-21 23:29       ` Jeremy Kerr
2011-02-21 23:29         ` Jeremy Kerr
2011-02-21 23:29         ` Jeremy Kerr
2011-02-22 23:33   ` [PATCH] wip: convert imx27 to common struct clk 
2011-02-22 23:33     ` Uwe Kleine-König
2011-02-22 23:33     ` Uwe Kleine-König
2011-02-23  4:17     ` Saravana Kannan
2011-02-23  4:17       ` Saravana Kannan
2011-02-23  4:17       ` Saravana Kannan
2011-02-23  8:15       ` 
2011-02-23  8:15         ` Uwe Kleine-König
2011-02-23  8:15         ` Uwe Kleine-König
2011-03-03  6:40 ` [PATCH 0/2] Common struct clk implementation, v14 Jeremy Kerr
2011-03-03  6:40   ` Jeremy Kerr
2011-03-03  6:40   ` Jeremy Kerr
2011-03-03  6:40   ` [PATCH 1/2] Add a common struct clk Jeremy Kerr
2011-03-03  6:40     ` Jeremy Kerr
2011-03-03  6:40     ` Jeremy Kerr
2011-04-14 12:49     ` Tony Lindgren
2011-04-14 12:49       ` Tony Lindgren
2011-04-14 12:49       ` Tony Lindgren
2011-03-03  6:40   ` [PATCH 2/2] clk: Generic support for fixed-rate clocks Jeremy Kerr
2011-03-03  6:40     ` Jeremy Kerr
2011-03-03  6:40     ` Jeremy Kerr
2011-03-14 10:16   ` [PATCH 0/2] Common struct clk implementation, v14 
2011-03-14 10:16     ` Uwe Kleine-König
2011-03-14 10:16     ` Uwe Kleine-König
2011-03-15  4:31   ` Jeremy Kerr
2011-03-15  4:31     ` Jeremy Kerr
2011-03-15  4:31     ` Jeremy Kerr
2011-03-21  2:33     ` Jeremy Kerr
2011-03-21  2:33       ` Jeremy Kerr
2011-03-21  2:33       ` Jeremy Kerr
2011-04-14  4:20   ` Jeremy Kerr
2011-04-14  4:20     ` Jeremy Kerr
2011-04-14  4:20     ` Jeremy Kerr
2011-04-14 10:00     ` Russell King - ARM Linux
2011-04-14 10:00       ` Russell King - ARM Linux
2011-04-14 10:00       ` Russell King - ARM Linux
2011-04-14 10:23       ` Jeremy Kerr
2011-04-14 10:23         ` Jeremy Kerr
2011-04-14 10:23         ` Jeremy Kerr
2011-04-14 10:26         ` Russell King - ARM Linux
2011-04-14 10:26           ` Russell King - ARM Linux
2011-04-14 10:26           ` Russell King - ARM Linux
2011-04-14 10:25       ` Benjamin Herrenschmidt
2011-04-14 10:25         ` Benjamin Herrenschmidt
2011-04-14 10:25         ` Benjamin Herrenschmidt
2011-04-14 10:32         ` Russell King - ARM Linux
2011-04-14 10:32           ` Russell King - ARM Linux
2011-04-14 10:32           ` Russell King - ARM Linux
2011-04-14 11:59           ` Nicolas Pitre
2011-04-14 11:59             ` Nicolas Pitre
2011-04-14 11:59             ` Nicolas Pitre
2011-04-14 12:09             ` Russell King - ARM Linux
2011-04-14 12:09               ` Russell King - ARM Linux
2011-04-14 12:09               ` Russell King - ARM Linux
2011-04-14 13:39               ` Nicolas Pitre
2011-04-14 13:39                 ` Nicolas Pitre
2011-04-14 13:39                 ` Nicolas Pitre
2011-04-14 14:00                 ` Mark Brown
2011-04-14 14:00                   ` Mark Brown
2011-04-14 14:00                   ` Mark Brown
2011-04-14 15:38                 ` Russell King - ARM Linux
2011-04-14 15:38                   ` Russell King - ARM Linux
2011-04-14 15:38                   ` Russell King - ARM Linux
2011-04-14 16:06                   ` Nicolas Pitre
2011-04-14 16:06                     ` Nicolas Pitre
2011-04-14 16:06                     ` Nicolas Pitre
2011-04-14 17:20                   ` 
2011-04-14 17:20                     ` Uwe Kleine-König
2011-04-14 17:20                     ` Uwe Kleine-König
2011-04-18 10:54                   ` Paul Mundt
2011-04-18 10:54                     ` Paul Mundt
2011-04-18 10:54                     ` Paul Mundt
2011-04-20 14:28                     ` 
2011-04-20 14:28                       ` Uwe Kleine-König
2011-04-20 14:28                       ` Uwe Kleine-König
2011-04-20 16:41                       ` Thomas Gleixner
2011-04-20 16:41                         ` Thomas Gleixner
2011-04-20 16:41                         ` Thomas Gleixner
2011-04-20 21:30                         ` Paul McKenney
2011-04-14 19:29               ` Saravana Kannan
2011-04-14 19:29                 ` Saravana Kannan
2011-04-14 19:29                 ` Saravana Kannan
2011-04-14 16:08           ` 
2011-04-14 16:08             ` Uwe Kleine-König
2011-04-14 16:08             ` Uwe Kleine-König
  -- strict thread matches above, loose matches on Subject: below --
2007-08-19 20:59 [RFC] Kirill Kuvaldin
2007-08-20  4:47 ` [RFC] Santos, Jose Renato G

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.