Re: [PATCH 1/4] Clockdomains: add base OMAP2/3 clockdomain code

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

 



* Paul Walmsley <paul@xxxxxxxxx> [080410 10:18]:
> This patch adds an interface to the clockdomain registers in the
> PRM/CM modules on OMAP2/3.  This interface is intended to be used by
> PM code, e.g., pm.c; not by device drivers directly.
> 
> The patch also adds clockdomain usecount tracking.  This is intended
> to be called whenever the first clock in a clockdomain is enabled, or
> when the last enabled clock in a clockdomain is disabled.  If the
> clockdomain is in software-supervised mode, the code will force-wakeup
> or force-sleep the clockdomain.  If the clockdomain is in
> hardware-supervised mode, the first clock enable will add sleep and
> wakeup dependencies on a user-selectable set of parent domains (usually
> MPU & IVA2), and the disable will remove them.
> 
> Each clockdomain will be defined in later patches as static
> structures.  The clockdomain structures are linked into a list at boot
> by clkdm_register(), similar to the OMAP clock code.
> 
> The patch adds a Kconfig option, CONFIG_OMAP_DEBUG_CLOCKDOMAIN, which
> when enabled will emit verbose debug messages via pr_debug().
> 
> Signed-off-by: Paul Walmsley <paul@xxxxxxxxx>
> 
> ---
>  arch/arm/mach-omap2/Makefile            |    3 
>  arch/arm/mach-omap2/clockdomain.c       |  579 ++++++++++++++++++++++++++++++++
>  arch/arm/plat-omap/Kconfig              |   12 
>  include/asm-arm/arch-omap/clockdomain.h |  105 +++++
>  4 files changed, 698 insertions(+), 1 deletion(-)
> 
> Index: linux-omap/arch/arm/mach-omap2/Makefile
> ===================================================================
> --- linux-omap.orig/arch/arm/mach-omap2/Makefile	2008-04-10 08:00:58.000000000 -0600
> +++ linux-omap/arch/arm/mach-omap2/Makefile	2008-04-10 08:01:12.000000000 -0600
> @@ -4,7 +4,8 @@
>  
>  # Common support
>  obj-y := irq.o id.o io.o memory.o control.o prcm.o clock.o mux.o \
> -		devices.o serial.o gpmc.o timer-gp.o powerdomain.o
> +		devices.o serial.o gpmc.o timer-gp.o powerdomain.o \
> +		clockdomain.o
>  
>  # Functions loaded to SRAM
>  obj-$(CONFIG_ARCH_OMAP2)		+= sram24xx.o
> Index: linux-omap/arch/arm/mach-omap2/clockdomain.c
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ linux-omap/arch/arm/mach-omap2/clockdomain.c	2008-04-10 08:04:34.000000000 -0600
> @@ -0,0 +1,579 @@
> +/*
> + * OMAP2/3 clockdomain framework functions
> + *
> + * Copyright (C) 2008 Texas Instruments, Inc.
> + * Copyright (C) 2008 Nokia Corporation
> + *
> + * Written by Paul Walmsley and Jouni Högander
> + *
> + * 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.
> + */
> +#ifdef CONFIG_OMAP_DEBUG_CLOCKDOMAIN
> +#  define DEBUG
> +#endif
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/device.h>
> +#include <linux/list.h>
> +#include <linux/errno.h>
> +#include <linux/delay.h>
> +#include <linux/clk.h>
> +#include <linux/limits.h>
> +
> +#include <linux/io.h>
> +
> +#include <linux/bitops.h>
> +
> +#include <asm/arch/clock.h>
> +
> +#include "prm.h"
> +#include "prm-regbits-24xx.h"
> +#include "cm.h"
> +
> +#include <asm/arch/powerdomain.h>
> +#include <asm/arch/clockdomain.h>
> +
> +/* clkdm_list contains all registered struct clockdomains */
> +static LIST_HEAD(clkdm_list);
> +
> +/* clkdm_mutex protects clkdm_list add and del ops */
> +static DEFINE_MUTEX(clkdm_mutex);
> +
> +/* array of powerdomain deps to be added/removed when clkdm in hwsup mode */
> +static struct clkdm_pwrdm_autodep *autodeps;
> +
> +
> +/* Private functions */
> +
> +/*
> + * _autodep_lookup - resolve autodep pwrdm names to pwrdm pointers; store
> + * @autodep: struct clkdm_pwrdm_autodep * to resolve
> + *
> + * Resolve autodep powerdomain names to powerdomain pointers via
> + * pwrdm_lookup() and store the pointers in the autodep structure.  An
> + * "autodep" is a powerdomain sleep/wakeup dependency that is
> + * automatically added and removed whenever clocks in the associated
> + * clockdomain are enabled or disabled (respectively) when the
> + * clockdomain is in hardware-supervised mode.	Meant to be called
> + * once at clockdomain layer initialization, since these should remain
> + * fixed for a particular architecture.	 No return value.
> + */

Few tabs in the comments above.


> +static void _autodep_lookup(struct clkdm_pwrdm_autodep *autodep)
> +{
> +	struct powerdomain *pwrdm;
> +
> +	if (!autodep)
> +		return;
> +
> +	if (!omap_chip_is(autodep->omap_chip))
> +		return;
> +
> +	pwrdm = pwrdm_lookup(autodep->pwrdm_name);
> +	if (!pwrdm) {
> +		pr_debug("clockdomain: _autodep_lookup: powerdomain %s "
> +			 "does not exist\n", autodep->pwrdm_name);
> +		WARN_ON(1);
> +		return;
> +	}
> +	autodep->pwrdm = pwrdm;
> +
> +	return;
> +}
> +
> +/*
> + * _clkdm_add_autodeps - add auto sleepdeps/wkdeps to clkdm upon clock enable
> + * @clkdm: struct clockdomain *
> + *
> + * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm'
> + * in hardware-supervised mode.	 Meant to be called from clock framework
> + * when a clock inside clockdomain 'clkdm' is enabled.	No return value.
> + */

Tabs here too.


> +static void _clkdm_add_autodeps(struct clockdomain *clkdm)
> +{
> +	struct clkdm_pwrdm_autodep *autodep;
> +
> +	for (autodep = autodeps; autodep->pwrdm_name; autodep++) {
> +		if (!autodep->pwrdm)
> +			continue;
> +
> +		pr_debug("clockdomain: adding %s sleepdep/wkdep for "
> +			 "pwrdm %s\n", autodep->pwrdm_name,
> +			 clkdm->pwrdm->name);
> +
> +		pwrdm_add_sleepdep(clkdm->pwrdm, autodep->pwrdm);
> +		pwrdm_add_wkdep(clkdm->pwrdm, autodep->pwrdm);
> +	}
> +}
> +
> +/*
> + * _clkdm_add_autodeps - remove auto sleepdeps/wkdeps from clkdm
> + * @clkdm: struct clockdomain *
> + *
> + * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm'
> + * in hardware-supervised mode.	 Meant to be called from clock framework
> + * when a clock inside clockdomain 'clkdm' is disabled.	 No return value.
> + */

Tabs here too, might be worth checking all the comments for tabs :)


> +static void _clkdm_del_autodeps(struct clockdomain *clkdm)
> +{
> +	struct clkdm_pwrdm_autodep *autodep;
> +
> +	for (autodep = autodeps; autodep->pwrdm_name; autodep++) {
> +		if (!autodep->pwrdm)
> +			continue;
> +
> +		pr_debug("clockdomain: removing %s sleepdep/wkdep for "
> +			 "pwrdm %s\n", autodep->pwrdm_name,
> +			 clkdm->pwrdm->name);
> +
> +		pwrdm_del_sleepdep(clkdm->pwrdm, autodep->pwrdm);
> +		pwrdm_del_wkdep(clkdm->pwrdm, autodep->pwrdm);
> +	}
> +}
> +
> +/* Public functions */
> +
> +/**
> + * clkdm_init - set up the clockdomain layer
> + * @clkdms: optional pointer to an array of clockdomains to register
> + * @init_autodeps: optional pointer to an array of autodeps to register
> + *
> + * Set up internal state.  If a pointer to an array of clockdomains
> + * was supplied, loop through the list of clockdomains, register all
> + * that are available on the current platform.	Similarly, if a
> + * pointer to an array of clockdomain-powerdomain autodependencies was
> + * provided, register those.  No return value.
> + */
> +void clkdm_init(struct clockdomain **clkdms, struct clkdm_pwrdm_autodep *init_autodeps)
> +{
> +	struct clockdomain **c = NULL;
> +	struct clkdm_pwrdm_autodep *autodep = NULL;
> +
> +	if (clkdms)
> +		for (c = clkdms; *c; c++)
> +			clkdm_register(*c);
> +
> +	autodeps = init_autodeps;
> +	if (autodeps)
> +		for (autodep = autodeps; autodep->pwrdm_name; autodep++)
> +			_autodep_lookup(autodep);
> +}
> +
> +/**
> + * clkdm_register - register a clockdomain
> + * @clkdm: struct clockdomain * to register
> + *
> + * Adds a clockdomain to the internal clockdomain list.
> + * Returns -EINVAL if given a null pointer, -EEXIST if a clockdomain is
> + * already registered by the provided name, or 0 upon success.
> + */
> +int clkdm_register(struct clockdomain *clkdm)
> +{
> +	struct powerdomain *pwrdm;
> +
> +	if (!clkdm || !clkdm->name)
> +		return -EINVAL;
> +
> +	if (!omap_chip_is(clkdm->omap_chip))
> +		return -EINVAL;
> +
> +	/* Verify that the clockdomain is not already registered */
> +	if (clkdm_lookup(clkdm->name))
> +		return -EEXIST;
> +
> +	pwrdm = pwrdm_lookup(clkdm->pwrdm_name);
> +	if (!pwrdm) {
> +		pr_debug("clockdomain: clkdm_register %s: powerdomain %s "
> +			 "does not exist\n", clkdm->name, clkdm->pwrdm_name);
> +		return -EINVAL;
> +	}
> +	clkdm->pwrdm = pwrdm;
> +
> +	mutex_lock(&clkdm_mutex);
> +	list_add(&clkdm->node, &clkdm_list);
> +	mutex_unlock(&clkdm_mutex);
> +
> +	pr_debug("clockdomain: registered %s\n", clkdm->name);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(clkdm_register);

There might be the same chip added between clkdm_lookup and list_add
here too.


> +
> +/**
> + * clkdm_unregister - unregister a clockdomain
> + * @clkdm: struct clockdomain * to unregister
> + *
> + * Removes a clockdomain from the internal clockdomain list.  Returns
> + * -EINVAL if clkdm argument is NULL.
> + */
> +int clkdm_unregister(struct clockdomain *clkdm)
> +{
> +	if (!clkdm)
> +		return -EINVAL;
> +
> +	mutex_lock(&clkdm_mutex);
> +	list_del(&clkdm->node);
> +	mutex_unlock(&clkdm_mutex);
> +
> +	pr_debug("clockdomain: unregistered %s\n", clkdm->name);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(clkdm_unregister);
> +
> +/**
> + * clkdm_lookup - look up a clockdomain by name, return a pointer
> + * @name: name of clockdomain
> + *
> + * Find a registered clockdomain by its name.  Returns a pointer to the
> + * struct clockdomain if found, or NULL otherwise.
> + */
> +struct clockdomain *clkdm_lookup(const char *name)
> +{
> +	struct clockdomain *clkdm, *temp_clkdm;
> +
> +	if (!name)
> +		return NULL;
> +
> +	clkdm = NULL;
> +
> +	mutex_lock(&clkdm_mutex);
> +	list_for_each_entry(temp_clkdm, &clkdm_list, node) {
> +		if (!strcmp(name, temp_clkdm->name)) {
> +			clkdm = temp_clkdm;
> +			break;
> +		}
> +	}
> +	mutex_unlock(&clkdm_mutex);
> +
> +	return clkdm;
> +}
> +EXPORT_SYMBOL(clkdm_lookup);
> +
> +/**
> + * clkdm_for_each - call function on each registered clockdomain
> + * @fn: callback function *
> + *
> + * Call the supplied function for each registered clockdomain.
> + * The callback function can return anything but 0 to bail
> + * out early from the iterator.	 The callback function is called with
> + * the clkdm_mutex held, so no clockdomain structure manipulation
> + * functions should be called from the callback, although hardware
> + * clockdomain control functions are fine.  Returns the last return
> + * value of the callback function, which should be 0 for success or
> + * anything else to indicate failure; or -EINVAL if the function pointer
> + * is null.
> + */
> +int clkdm_for_each(int (*fn)(struct clockdomain *clkdm))
> +{
> +	struct clockdomain *clkdm;
> +	int ret = 0;
> +
> +	if (!fn)
> +		return -EINVAL;
> +
> +	mutex_lock(&clkdm_mutex);
> +	list_for_each_entry(clkdm, &clkdm_list, node) {
> +		ret = (*fn)(clkdm);
> +		if (ret)
> +			break;
> +	}
> +	mutex_unlock(&clkdm_mutex);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(clkdm_for_each);
> +
> +
> +/* Hardware clockdomain control */
> +
> +/**
> + * omap2_clkdm_clktrctrl_read - read the clkdm's current state transition mode
> + * @clk: struct clk * of a clockdomain
> + *
> + * Return the clockdomain's current state transition mode from the
> + * corresponding domain CM_CLKSTCTRL register.	Returns -EINVAL if clk
> + * is NULL or the current mode upon success.
> + */
> +static int omap2_clkdm_clktrctrl_read(struct clockdomain *clkdm)
> +{
> +	u32 v;
> +
> +	if (!clkdm)
> +		return -EINVAL;
> +
> +	v = cm_read_mod_reg(clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL);
> +	v &= clkdm->clktrctrl_mask;
> +	v >>= __ffs(clkdm->clktrctrl_mask);
> +
> +	return v;
> +}
> +
> +/**
> + * omap2_clkdm_sleep - force clockdomain sleep transition
> + * @clkdm: struct clockdomain *
> + *
> + * Instruct the CM to force a sleep transition on the specified
> + * clockdomain 'clkdm'.	 Returns -EINVAL if clk is NULL or if
> + * clockdomain does not support software-initiated sleep; 0 upon
> + * success.
> + */
> +int omap2_clkdm_sleep(struct clockdomain *clkdm)
> +{
> +	if (!clkdm)
> +		return -EINVAL;
> +
> +	if (!(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
> +		pr_debug("clockdomain: %s does not support forcing "
> +			 "sleep via software\n", clkdm->name);
> +		return -EINVAL;
> +	}
> +
> +	pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
> +
> +	if (cpu_is_omap24xx()) {
> +
> +		cm_set_mod_reg_bits(OMAP24XX_FORCESTATE,
> +				    clkdm->pwrdm->prcm_offs, PM_PWSTCTRL);
> +
> +	} else if (cpu_is_omap34xx()) {
> +
> +		u32 v = (OMAP34XX_CLKSTCTRL_FORCE_SLEEP <<
> +			 __ffs(clkdm->clktrctrl_mask));
> +
> +		cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v,
> +				    clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL);
> +
> +	} else {
> +		BUG();
> +	};
> +
> +	return 0;
> +}
> +
> +/**
> + * omap2_clkdm_wakeup - force clockdomain wakeup transition
> + * @clkdm: struct clockdomain *
> + *
> + * Instruct the CM to force a wakeup transition on the specified
> + * clockdomain 'clkdm'.	 Returns -EINVAL if clkdm is NULL or if the
> + * clockdomain does not support software-controlled wakeup; 0 upon
> + * success.
> + */
> +int omap2_clkdm_wakeup(struct clockdomain *clkdm)
> +{
> +	if (!clkdm)
> +		return -EINVAL;
> +
> +	if (!(clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) {
> +		pr_debug("clockdomain: %s does not support forcing "
> +			 "wakeup via software\n", clkdm->name);
> +		return -EINVAL;
> +	}
> +
> +	pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
> +
> +	if (cpu_is_omap24xx()) {
> +
> +		cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE,
> +				      clkdm->pwrdm->prcm_offs, PM_PWSTCTRL);
> +
> +	} else if (cpu_is_omap34xx()) {
> +
> +		u32 v = (OMAP34XX_CLKSTCTRL_FORCE_WAKEUP <<
> +			 __ffs(clkdm->clktrctrl_mask));
> +
> +		cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask, v,
> +				    clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL);
> +
> +	} else {
> +		BUG();
> +	};
> +
> +	return 0;
> +}
> +
> +/**
> + * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm
> + * @clkdm: struct clockdomain *
> + *
> + * Allow the hardware to automatically switch the clockdomain into
> + * active or idle states, as needed by downstream clocks.  If the
> + * clockdomain has any downstream clocks enabled in the clock
> + * framework, wkdep/sleepdep autodependencies are added; this is so
> + * device drivers can read and write to the device.  No return value.
> + */
> +void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
> +{
> +	u32 v;
> +
> +	if (!clkdm)
> +		return;
> +
> +	if (!(clkdm->flags & CLKDM_CAN_ENABLE_AUTO)) {
> +		pr_debug("clock: automatic idle transitions cannot be enabled "
> +			 "on clockdomain %s\n", clkdm->name);
> +		return;
> +	}
> +
> +	pr_debug("clockdomain: enabling automatic idle transitions for %s\n",
> +		 clkdm->name);
> +
> +	if (atomic_read(&clkdm->usecount) > 0)
> +		_clkdm_add_autodeps(clkdm);
> +
> +	if (cpu_is_omap24xx())
> +		v = OMAP24XX_CLKSTCTRL_ENABLE_AUTO;
> +	else if (cpu_is_omap34xx())
> +		v = OMAP34XX_CLKSTCTRL_ENABLE_AUTO;
> +	else
> +		BUG();
> +
> +
> +	cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask,
> +			    v << __ffs(clkdm->clktrctrl_mask),
> +			    clkdm->pwrdm->prcm_offs,
> +			    CM_CLKSTCTRL);
> +}
> +
> +/**
> + * omap2_clkdm_deny_idle - disable hwsup idle transitions for clkdm
> + * @clkdm: struct clockdomain *
> + *
> + * Prevent the hardware from automatically switching the clockdomain
> + * into inactive or idle states.  If the clockdomain has downstream
> + * clocks enabled in the clock framework, wkdep/sleepdep
> + * autodependencies are removed.  No return value.
> + */
> +void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
> +{
> +	u32 v;
> +
> +	if (!clkdm)
> +		return;
> +
> +	if (!(clkdm->flags & CLKDM_CAN_DISABLE_AUTO)) {
> +		pr_debug("clockdomain: automatic idle transitions cannot be "
> +			 "disabled on %s\n", clkdm->name);
> +		return;
> +	}
> +
> +	pr_debug("clockdomain: disabling automatic idle transitions for %s\n",
> +		 clkdm->name);
> +
> +	if (cpu_is_omap24xx())
> +		v = OMAP24XX_CLKSTCTRL_DISABLE_AUTO;
> +	else if (cpu_is_omap34xx())
> +		v = OMAP34XX_CLKSTCTRL_DISABLE_AUTO;
> +	else
> +		BUG();
> +
> +	cm_rmw_mod_reg_bits(clkdm->clktrctrl_mask,
> +			    v << __ffs(clkdm->clktrctrl_mask),
> +			    clkdm->pwrdm->prcm_offs, CM_CLKSTCTRL);
> +
> +	if (atomic_read(&clkdm->usecount) > 0)
> +		_clkdm_del_autodeps(clkdm);
> +}
> +
> +
> +/* Clockdomain-to-clock framework interface code */
> +
> +/**
> + * omap2_clkdm_clk_enable - add an enabled downstream clock to this clkdm
> + * @clkdm: struct clockdomain *
> + * @clk: struct clk * of the enabled downstream clock
> + *
> + * Increment the usecount of this clockdomain 'clkdm' and ensure that
> + * it is awake.	 Intended to be called by clk_enable() code.  If the
> + * clockdomain is in software-supervised idle mode, force the
> + * clockdomain to wake.	 If the clockdomain is in hardware-supervised
> + * idle mode, add clkdm-pwrdm autodependencies, to ensure that devices
> + * in the clockdomain can be read from/written to by on-chip processors.
> + * Returns -EINVAL if passed null pointers; returns 0 upon success or
> + * if the clockdomain is in hwsup idle mode.
> + */
> +int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
> +{
> +	int v;
> +
> +	/*
> +	 * XXX Rewrite this code to maintain a list of enabled
> +	 * downstream clocks for debugging purposes?
> +	 */
> +
> +	if (!clkdm || !clk)
> +		return -EINVAL;
> +
> +	if (atomic_inc_return(&clkdm->usecount) > 1)
> +		return 0;
> +
> +	/* Clockdomain now has one enabled downstream clock */
> +
> +	pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name,
> +		 clk->name);
> +
> +	v = omap2_clkdm_clktrctrl_read(clkdm);
> +
> +	if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||
> +	    (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO))
> +		_clkdm_add_autodeps(clkdm);
> +	else
> +		omap2_clkdm_wakeup(clkdm);
> +
> +	return 0;
> +}
> +
> +/**
> + * omap2_clkdm_clk_disable - remove an enabled downstream clock from this clkdm
> + * @clkdm: struct clockdomain *
> + * @clk: struct clk * of the disabled downstream clock
> + *
> + * Decrement the usecount of this clockdomain 'clkdm'. Intended to be
> + * called by clk_disable() code.  If the usecount goes to 0, put the
> + * clockdomain to sleep (software-supervised mode) or remove the
> + * clkdm-pwrdm autodependencies (hardware-supervised mode).  Returns
> + * -EINVAL if passed null pointers; -ERANGE if the clkdm usecount
> + * underflows and debugging is enabled; or returns 0 upon success or
> + * if the clockdomain is in hwsup idle mode.
> + */
> +int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
> +{
> +	int v;
> +
> +	/*
> +	 * XXX Rewrite this code to maintain a list of enabled
> +	 * downstream clocks for debugging purposes?
> +	 */
> +
> +	if (!clkdm || !clk)
> +		return -EINVAL;
> +
> +#ifdef DEBUG
> +	if (atomic_read(&clkdm->usecount) == 0) {
> +		WARN_ON(1); /* underflow */
> +		return -ERANGE;
> +	}
> +#endif
> +
> +	if (atomic_dec_return(&clkdm->usecount) > 0)
> +		return 0;
> +
> +	/* All downstream clocks of this clockdomain are now disabled */
> +
> +	pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name,
> +		 clk->name);
> +
> +	v = omap2_clkdm_clktrctrl_read(clkdm);
> +
> +	if ((cpu_is_omap34xx() && v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ||
> +	    (cpu_is_omap24xx() && v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO))
> +		_clkdm_del_autodeps(clkdm);
> +	else
> +		omap2_clkdm_sleep(clkdm);
> +
> +	return 0;
> +}
> +
> Index: linux-omap/arch/arm/plat-omap/Kconfig
> ===================================================================
> --- linux-omap.orig/arch/arm/plat-omap/Kconfig	2008-04-10 08:00:58.000000000 -0600
> +++ linux-omap/arch/arm/plat-omap/Kconfig	2008-04-10 08:01:12.000000000 -0600
> @@ -54,6 +54,18 @@
>  	  for every powerdomain register write.  However, the
>  	  extra detail costs some memory.
>  
> +config OMAP_DEBUG_CLOCKDOMAIN
> +	bool "Emit debug messages from clockdomain layer"
> +	depends on ARCH_OMAP2 || ARCH_OMAP3
> +	default n
> +	help
> +	  Say Y here if you want to compile in clockdomain layer
> +	  debugging messages for OMAP2/3.   These messages can
> +	  provide more detail as to why some clockdomain calls
> +	  may be failing, and will also emit a descriptive message
> +	  for every clockdomain register write.  However, the
> +	  extra detail costs some memory.
> +
>  config OMAP_RESET_CLOCKS
>  	bool "Reset unused clocks during boot"
>  	depends on ARCH_OMAP
> Index: linux-omap/include/asm-arm/arch-omap/clockdomain.h
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ linux-omap/include/asm-arm/arch-omap/clockdomain.h	2008-04-10 08:01:12.000000000 -0600
> @@ -0,0 +1,105 @@
> +/*
> + * linux/include/asm-arm/arch-omap/clockdomain.h
> + *
> + * OMAP2/3 clockdomain framework functions
> + *
> + * Copyright (C) 2008 Texas Instruments, Inc.
> + * Copyright (C) 2008 Nokia Corporation
> + *
> + * Written by Paul Walmsley
> + *
> + * 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.
> + */
> +
> +#ifndef __ASM_ARM_ARCH_OMAP_CLOCKDOMAIN_H
> +#define __ASM_ARM_ARCH_OMAP_CLOCKDOMAIN_H
> +
> +#include <asm/arch/powerdomain.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/cpu.h>
> +
> +/* Clockdomain capability flags */
> +#define CLKDM_CAN_FORCE_SLEEP			(1 << 0)
> +#define CLKDM_CAN_FORCE_WAKEUP			(1 << 1)
> +#define CLKDM_CAN_ENABLE_AUTO			(1 << 2)
> +#define CLKDM_CAN_DISABLE_AUTO			(1 << 3)
> +
> +#define CLKDM_CAN_HWSUP		(CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO)
> +#define CLKDM_CAN_SWSUP		(CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP)
> +#define CLKDM_CAN_HWSUP_SWSUP	(CLKDM_CAN_SWSUP | CLKDM_CAN_HWSUP)
> +
> +/* OMAP24XX CM_CLKSTCTRL_*.AUTOSTATE_* register bit values */
> +#define OMAP24XX_CLKSTCTRL_DISABLE_AUTO		0x0
> +#define OMAP24XX_CLKSTCTRL_ENABLE_AUTO		0x1
> +
> +/* OMAP3XXX CM_CLKSTCTRL_*.CLKTRCTRL_* register bit values */
> +#define OMAP34XX_CLKSTCTRL_DISABLE_AUTO		0x0
> +#define OMAP34XX_CLKSTCTRL_FORCE_SLEEP		0x1
> +#define OMAP34XX_CLKSTCTRL_FORCE_WAKEUP		0x2
> +#define OMAP34XX_CLKSTCTRL_ENABLE_AUTO		0x3
> +
> +/*
> + * struct clkdm_pwrdm_autodep - a powerdomain that should have wkdeps
> + * and sleepdeps added when a powerdomain should stay active in hwsup mode;
> + * and conversely, removed when the powerdomain should be allowed to go
> + * inactive in hwsup mode.
> + */
> +struct clkdm_pwrdm_autodep {
> +
> +	/* Name of the powerdomain to add a wkdep/sleepdep on */
> +	const char *pwrdm_name;
> +
> +	/* Powerdomain pointer (looked up at clkdm_init() time) */
> +	struct powerdomain *pwrdm;
> +
> +	/* OMAP chip types that this clockdomain dep is valid on */
> +	const omap_chip_t omap_chip;
> +
> +};
> +
> +struct clockdomain {
> +
> +	/* Clockdomain name */
> +	const char *name;
> +
> +	/* Powerdomain enclosing this clockdomain */
> +	const char *pwrdm_name;
> +
> +	/* CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg */
> +	const u8 clktrctrl_mask;
> +
> +	/* Clockdomain capability flags */
> +	const u8 flags;
> +
> +	/* OMAP chip types that this clockdomain is valid on */
> +	const omap_chip_t omap_chip;
> +
> +	/* Usecount tracking */
> +	atomic_t usecount;
> +
> +	/* Powerdomain pointer assigned at clkdm_register() */
> +	struct powerdomain *pwrdm;
> +
> +	struct list_head node;
> +
> +};
> +
> +void clkdm_init(struct clockdomain **clkdms, struct clkdm_pwrdm_autodep *autodeps);
> +int clkdm_register(struct clockdomain *clkdm);
> +int clkdm_unregister(struct clockdomain *clkdm);
> +struct clockdomain *clkdm_lookup(const char *name);
> +
> +void omap2_clkdm_allow_idle(struct clockdomain *clkdm);
> +void omap2_clkdm_deny_idle(struct clockdomain *clkdm);
> +
> +int omap2_clkdm_wakeup(struct clockdomain *clkdm);
> +int omap2_clkdm_sleep(struct clockdomain *clkdm);
> +
> +int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
> +int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
> +
> +int clkdm_for_each(int (*fn)(struct clockdomain *clkdm));
> +
> +#endif
> 
> -- 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux