Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e909d62a authored by Paul Walmsley's avatar Paul Walmsley
Browse files

OMAP clockdomain/powerdomain: remove runtime register/unregister



OMAP clockdomains and powerdomains are currently defined statically,
only registered at boot, and never unregistered, so we can remove the
unregister function and the locking.   A variant of this was originally
suggested a while ago by Dmitry Baryshkov <dbaryshkov@gmail.com>.
This version of this patch contains an additional fix from Kevin Hilman
<khilman@deeprootsystems.com> to address one of the pwrdm_for_each_nolock()
users in mach-omap2/pm-debug.c.   Thanks Kevin.

Signed-off-by: default avatarPaul Walmsley <paul@pwsan.com>
Cc: Dmitry Baryshkov <dbaryshkov@gmail.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
parent 3d309cde
Loading
Loading
Loading
Loading
+40 −78
Original line number Diff line number Diff line
@@ -39,9 +39,6 @@
/* 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 clockdomain deps to be added/removed when clkdm in hwsup mode */
static struct clkdm_autodep *autodeps;

@@ -67,6 +64,45 @@ static struct clockdomain *_clkdm_lookup(const char *name)
	return clkdm;
}

/**
 * _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.
 */
static int _clkdm_register(struct clockdomain *clkdm)
{
	struct powerdomain *pwrdm;

	if (!clkdm || !clkdm->name)
		return -EINVAL;

	if (!omap_chip_is(clkdm->omap_chip))
		return -EINVAL;

	pwrdm = pwrdm_lookup(clkdm->pwrdm.name);
	if (!pwrdm) {
		pr_err("clockdomain: %s: powerdomain %s does not exist\n",
			clkdm->name, clkdm->pwrdm.name);
		return -EINVAL;
	}
	clkdm->pwrdm.ptr = pwrdm;

	/* Verify that the clockdomain is not already registered */
	if (_clkdm_lookup(clkdm->name))
		return -EEXIST;

	list_add(&clkdm->node, &clkdm_list);

	pwrdm_add_clkdm(pwrdm, clkdm);

	pr_debug("clockdomain: registered %s\n", clkdm->name);

	return 0;
}

/* _clkdm_deps_lookup - look up the specified clockdomain in a clkdm list */
static struct clkdm_dep *_clkdm_deps_lookup(struct clockdomain *clkdm,
					    struct clkdm_dep *deps)
@@ -240,7 +276,7 @@ void clkdm_init(struct clockdomain **clkdms,

	if (clkdms)
		for (c = clkdms; *c; c++)
			clkdm_register(*c);
			_clkdm_register(*c);

	autodeps = init_autodeps;
	if (autodeps)
@@ -248,76 +284,6 @@ void clkdm_init(struct clockdomain **clkdms,
			_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)
{
	int ret = -EINVAL;
	struct powerdomain *pwrdm;

	if (!clkdm || !clkdm->name)
		return -EINVAL;

	if (!omap_chip_is(clkdm->omap_chip))
		return -EINVAL;

	pwrdm = pwrdm_lookup(clkdm->pwrdm.name);
	if (!pwrdm) {
		pr_err("clockdomain: %s: powerdomain %s does not exist\n",
			clkdm->name, clkdm->pwrdm.name);
		return -EINVAL;
	}
	clkdm->pwrdm.ptr = pwrdm;

	mutex_lock(&clkdm_mutex);
	/* Verify that the clockdomain is not already registered */
	if (_clkdm_lookup(clkdm->name)) {
		ret = -EEXIST;
		goto cr_unlock;
	}

	list_add(&clkdm->node, &clkdm_list);

	pwrdm_add_clkdm(pwrdm, clkdm);

	pr_debug("clockdomain: registered %s\n", clkdm->name);
	ret = 0;

cr_unlock:
	mutex_unlock(&clkdm_mutex);

	return ret;
}

/**
 * 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;

	pwrdm_del_clkdm(clkdm->pwrdm.ptr, clkdm);

	mutex_lock(&clkdm_mutex);
	list_del(&clkdm->node);
	mutex_unlock(&clkdm_mutex);

	pr_debug("clockdomain: unregistered %s\n", clkdm->name);

	return 0;
}

/**
 * clkdm_lookup - look up a clockdomain by name, return a pointer
 * @name: name of clockdomain
@@ -334,14 +300,12 @@ struct clockdomain *clkdm_lookup(const char *name)

	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;
}
@@ -369,13 +333,11 @@ int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
	if (!fn)
		return -EINVAL;

	mutex_lock(&clkdm_mutex);
	list_for_each_entry(clkdm, &clkdm_list, node) {
		ret = (*fn)(clkdm, user);
		if (ret)
			break;
	}
	mutex_unlock(&clkdm_mutex);

	return ret;
}
+1 −1
Original line number Diff line number Diff line
@@ -577,7 +577,7 @@ static int __init pm_dbg_init(void)
	(void) debugfs_create_file("time", S_IRUGO,
		d, (void *)DEBUG_FILE_TIMERS, &debug_fops);

	pwrdm_for_each_nolock(pwrdms_setup, (void *)d);
	pwrdm_for_each(pwrdms_setup, (void *)d);

	pm_dbg_dir = debugfs_create_dir("registers", d);
	if (IS_ERR(pm_dbg_dir))
+45 −133
Original line number Diff line number Diff line
@@ -80,13 +80,6 @@ static u16 pwrstst_reg_offs;
/* pwrdm_list contains all registered struct powerdomains */
static LIST_HEAD(pwrdm_list);

/*
 * pwrdm_rwlock protects pwrdm_list add and del ops - also reused to
 * protect pwrdm_clkdms[] during clkdm add/del ops
 */
static DEFINE_RWLOCK(pwrdm_rwlock);


/* Private functions */

static struct powerdomain *_pwrdm_lookup(const char *name)
@@ -105,6 +98,42 @@ static struct powerdomain *_pwrdm_lookup(const char *name)
	return pwrdm;
}

/**
 * _pwrdm_register - register a powerdomain
 * @pwrdm: struct powerdomain * to register
 *
 * Adds a powerdomain to the internal powerdomain list.  Returns
 * -EINVAL if given a null pointer, -EEXIST if a powerdomain is
 * already registered by the provided name, or 0 upon success.
 */
static int _pwrdm_register(struct powerdomain *pwrdm)
{
	int i;

	if (!pwrdm)
		return -EINVAL;

	if (!omap_chip_is(pwrdm->omap_chip))
		return -EINVAL;

	if (_pwrdm_lookup(pwrdm->name))
		return -EEXIST;

	list_add(&pwrdm->node, &pwrdm_list);

	/* Initialize the powerdomain's state counter */
	for (i = 0; i < 4; i++)
		pwrdm->state_counter[i] = 0;

	pwrdm_wait_transition(pwrdm);
	pwrdm->state = pwrdm_read_pwrst(pwrdm);
	pwrdm->state_counter[pwrdm->state] = 1;

	pr_debug("powerdomain: registered %s\n", pwrdm->name);

	return 0;
}

static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
{

@@ -152,19 +181,6 @@ static int _pwrdm_post_transition_cb(struct powerdomain *pwrdm, void *unused)
	return 0;
}

static __init void _pwrdm_setup(struct powerdomain *pwrdm)
{
	int i;

	for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
		pwrdm->state_counter[i] = 0;

	pwrdm_wait_transition(pwrdm);
	pwrdm->state = pwrdm_read_pwrst(pwrdm);
	pwrdm->state_counter[pwrdm->state] = 1;

}

/* Public functions */

/**
@@ -192,70 +208,9 @@ void pwrdm_init(struct powerdomain **pwrdm_list)
	}

	if (pwrdm_list) {
		for (p = pwrdm_list; *p; p++) {
			pwrdm_register(*p);
			_pwrdm_setup(*p);
		}
	}
}

/**
 * pwrdm_register - register a powerdomain
 * @pwrdm: struct powerdomain * to register
 *
 * Adds a powerdomain to the internal powerdomain list.  Returns
 * -EINVAL if given a null pointer, -EEXIST if a powerdomain is
 * already registered by the provided name, or 0 upon success.
 */
int pwrdm_register(struct powerdomain *pwrdm)
{
	unsigned long flags;
	int ret = -EINVAL;

	if (!pwrdm)
		return -EINVAL;

	if (!omap_chip_is(pwrdm->omap_chip))
		return -EINVAL;

	write_lock_irqsave(&pwrdm_rwlock, flags);
	if (_pwrdm_lookup(pwrdm->name)) {
		ret = -EEXIST;
		goto pr_unlock;
		for (p = pwrdm_list; *p; p++)
			_pwrdm_register(*p);
	}

	list_add(&pwrdm->node, &pwrdm_list);

	pr_debug("powerdomain: registered %s\n", pwrdm->name);
	ret = 0;

pr_unlock:
	write_unlock_irqrestore(&pwrdm_rwlock, flags);

	return ret;
}

/**
 * pwrdm_unregister - unregister a powerdomain
 * @pwrdm: struct powerdomain * to unregister
 *
 * Removes a powerdomain from the internal powerdomain list.  Returns
 * -EINVAL if pwrdm argument is NULL.
 */
int pwrdm_unregister(struct powerdomain *pwrdm)
{
	unsigned long flags;

	if (!pwrdm)
		return -EINVAL;

	write_lock_irqsave(&pwrdm_rwlock, flags);
	list_del(&pwrdm->node);
	write_unlock_irqrestore(&pwrdm_rwlock, flags);

	pr_debug("powerdomain: unregistered %s\n", pwrdm->name);

	return 0;
}

/**
@@ -268,20 +223,17 @@ int pwrdm_unregister(struct powerdomain *pwrdm)
struct powerdomain *pwrdm_lookup(const char *name)
{
	struct powerdomain *pwrdm;
	unsigned long flags;

	if (!name)
		return NULL;

	read_lock_irqsave(&pwrdm_rwlock, flags);
	pwrdm = _pwrdm_lookup(name);
	read_unlock_irqrestore(&pwrdm_rwlock, flags);

	return pwrdm;
}

/**
 * pwrdm_for_each_nolock - call function on each registered clockdomain
 * pwrdm_for_each - call function on each registered clockdomain
 * @fn: callback function *
 *
 * Call the supplied function for each registered powerdomain.  The
@@ -290,7 +242,7 @@ struct powerdomain *pwrdm_lookup(const char *name)
 * should be 0 for success or anything else to indicate failure; or -EINVAL if
 * the function pointer is null.
 */
int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
		   void *user)
{
	struct powerdomain *temp_pwrdm;
@@ -308,28 +260,6 @@ int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user),
	return ret;
}

/**
 * pwrdm_for_each - call function on each registered clockdomain
 * @fn: callback function *
 *
 * This function is the same as 'pwrdm_for_each_nolock()', but keeps the
 * &pwrdm_rwlock locked for reading, so no powerdomain structure manipulation
 * functions should be called from the callback, although hardware powerdomain
 * control functions are fine.
 */
int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
			void *user)
{
	unsigned long flags;
	int ret;

	read_lock_irqsave(&pwrdm_rwlock, flags);
	ret = pwrdm_for_each_nolock(fn, user);
	read_unlock_irqrestore(&pwrdm_rwlock, flags);

	return ret;
}

/**
 * pwrdm_add_clkdm - add a clockdomain to a powerdomain
 * @pwrdm: struct powerdomain * to add the clockdomain to
@@ -342,7 +272,6 @@ int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
 */
int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
{
	unsigned long flags;
	int i;
	int ret = -EINVAL;

@@ -352,8 +281,6 @@ int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
	pr_debug("powerdomain: associating clockdomain %s with powerdomain "
		 "%s\n", clkdm->name, pwrdm->name);

	write_lock_irqsave(&pwrdm_rwlock, flags);

	for (i = 0; i < PWRDM_MAX_CLKDMS; i++) {
		if (!pwrdm->pwrdm_clkdms[i])
			break;
@@ -378,8 +305,6 @@ int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
	ret = 0;

pac_exit:
	write_unlock_irqrestore(&pwrdm_rwlock, flags);

	return ret;
}

@@ -395,7 +320,6 @@ int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
 */
int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
{
	unsigned long flags;
	int ret = -EINVAL;
	int i;

@@ -405,8 +329,6 @@ int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
	pr_debug("powerdomain: dissociating clockdomain %s from powerdomain "
		 "%s\n", clkdm->name, pwrdm->name);

	write_lock_irqsave(&pwrdm_rwlock, flags);

	for (i = 0; i < PWRDM_MAX_CLKDMS; i++)
		if (pwrdm->pwrdm_clkdms[i] == clkdm)
			break;
@@ -423,8 +345,6 @@ int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
	ret = 0;

pdc_exit:
	write_unlock_irqrestore(&pwrdm_rwlock, flags);

	return ret;
}

@@ -435,32 +355,24 @@ int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
 *
 * Call the supplied function for each clockdomain in the powerdomain
 * 'pwrdm'.  The callback function can return anything but 0 to bail
 * out early from the iterator.  The callback function is called with
 * the pwrdm_rwlock held for reading, so no powerdomain structure
 * manipulation functions should be called from the callback, although
 * hardware powerdomain control functions are fine.  Returns -EINVAL
 * if presented with invalid pointers; or passes along the last return
 * value of the callback function, which should be 0 for success or
 * anything else to indicate failure.
 * out early from the iterator.  Returns -EINVAL if presented with
 * invalid pointers; or passes along the last return value of the
 * callback function, which should be 0 for success or anything else
 * to indicate failure.
 */
int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
			 int (*fn)(struct powerdomain *pwrdm,
				   struct clockdomain *clkdm))
{
	unsigned long flags;
	int ret = 0;
	int i;

	if (!fn)
		return -EINVAL;

	read_lock_irqsave(&pwrdm_rwlock, flags);

	for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++)
		ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]);

	read_unlock_irqrestore(&pwrdm_rwlock, flags);

	return ret;
}

+0 −2
Original line number Diff line number Diff line
@@ -117,8 +117,6 @@ struct clockdomain {
};

void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps);
int clkdm_register(struct clockdomain *clkdm);
int clkdm_unregister(struct clockdomain *clkdm);
struct clockdomain *clkdm_lookup(const char *name);

int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
+0 −2
Original line number Diff line number Diff line
@@ -114,8 +114,6 @@ struct powerdomain {

void pwrdm_init(struct powerdomain **pwrdm_list);

int pwrdm_register(struct powerdomain *pwrdm);
int pwrdm_unregister(struct powerdomain *pwrdm);
struct powerdomain *pwrdm_lookup(const char *name);

int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),