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

Commit 4bd5259e authored by Paul Walmsley's avatar Paul Walmsley
Browse files

ARM: OMAP2/3: clockdomain/PRM/CM: move the low-level clockdomain functions into PRM/CM



Move the low-level SoC-specific clockdomain control functions into
cm*.c and prm*.c.  For example, OMAP2xxx low-level clockdomain
functions go into cm2xxx.c.  Then remove the unnecessary
clockdomain*xxx*.c files.

The objective is to centralize low-level CM and PRM register accesses
into the cm*.[ch] and prm*.[ch] files, and then to export an OMAP
SoC-independent API to higher-level OMAP power management code.

Signed-off-by: default avatarPaul Walmsley <paul@pwsan.com>
Cc: Rajendra Nayak <rnayak@ti.com>
Cc: Vaibhav Hiremath <hvaibhav@ti.com>
Acked-by: default avatarRajendra Nayak <rnayak@ti.com>
Reviewed-by: default avatarRuss Dill <Russ.Dill@ti.com>
Acked-by: default avatarSantosh Shilimkar <santosh.shilimkar@ti.com>
parent ff4ae5d9
Loading
Loading
Loading
Loading
+0 −5
Original line number Original line Diff line number Diff line
@@ -133,22 +133,17 @@ obj-$(CONFIG_SOC_OMAP5) += $(powerdomain-common)
# PRCM clockdomain control
# PRCM clockdomain control
clockdomain-common			+= clockdomain.o
clockdomain-common			+= clockdomain.o
obj-$(CONFIG_ARCH_OMAP2)		+= $(clockdomain-common)
obj-$(CONFIG_ARCH_OMAP2)		+= $(clockdomain-common)
obj-$(CONFIG_ARCH_OMAP2)		+= clockdomain2xxx_3xxx.o
obj-$(CONFIG_ARCH_OMAP2)		+= clockdomains2xxx_3xxx_data.o
obj-$(CONFIG_ARCH_OMAP2)		+= clockdomains2xxx_3xxx_data.o
obj-$(CONFIG_SOC_OMAP2420)		+= clockdomains2420_data.o
obj-$(CONFIG_SOC_OMAP2420)		+= clockdomains2420_data.o
obj-$(CONFIG_SOC_OMAP2430)		+= clockdomains2430_data.o
obj-$(CONFIG_SOC_OMAP2430)		+= clockdomains2430_data.o
obj-$(CONFIG_ARCH_OMAP3)		+= $(clockdomain-common)
obj-$(CONFIG_ARCH_OMAP3)		+= $(clockdomain-common)
obj-$(CONFIG_ARCH_OMAP3)		+= clockdomain2xxx_3xxx.o
obj-$(CONFIG_ARCH_OMAP3)		+= clockdomains2xxx_3xxx_data.o
obj-$(CONFIG_ARCH_OMAP3)		+= clockdomains2xxx_3xxx_data.o
obj-$(CONFIG_ARCH_OMAP3)		+= clockdomains3xxx_data.o
obj-$(CONFIG_ARCH_OMAP3)		+= clockdomains3xxx_data.o
obj-$(CONFIG_ARCH_OMAP4)		+= $(clockdomain-common)
obj-$(CONFIG_ARCH_OMAP4)		+= $(clockdomain-common)
obj-$(CONFIG_ARCH_OMAP4)		+= clockdomain44xx.o
obj-$(CONFIG_ARCH_OMAP4)		+= clockdomains44xx_data.o
obj-$(CONFIG_ARCH_OMAP4)		+= clockdomains44xx_data.o
obj-$(CONFIG_SOC_AM33XX)		+= $(clockdomain-common)
obj-$(CONFIG_SOC_AM33XX)		+= $(clockdomain-common)
obj-$(CONFIG_SOC_AM33XX)		+= clockdomain33xx.o
obj-$(CONFIG_SOC_AM33XX)		+= clockdomains33xx_data.o
obj-$(CONFIG_SOC_AM33XX)		+= clockdomains33xx_data.o
obj-$(CONFIG_SOC_OMAP5)			+= $(clockdomain-common)
obj-$(CONFIG_SOC_OMAP5)			+= $(clockdomain-common)
obj-$(CONFIG_SOC_OMAP5)			+= clockdomain44xx.o


# Clock framework
# Clock framework
obj-$(CONFIG_ARCH_OMAP2)		+= $(clock-common) clock2xxx.o
obj-$(CONFIG_ARCH_OMAP2)		+= $(clock-common) clock2xxx.o
+0 −340
Original line number Original line Diff line number Diff line
/*
 * OMAP2 and OMAP3 clockdomain control
 *
 * Copyright (C) 2008-2010 Texas Instruments, Inc.
 * Copyright (C) 2008-2010 Nokia Corporation
 *
 * Derived from mach-omap2/clockdomain.c written by Paul Walmsley
 * Rajendra Nayak <rnayak@ti.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.
 */

#include <linux/types.h>
#include <plat/prcm.h>
#include "prm.h"
#include "prm2xxx_3xxx.h"
#include "cm.h"
#include "cm2xxx.h"
#include "cm3xxx.h"
#include "cm-regbits-24xx.h"
#include "cm-regbits-34xx.h"
#include "prm-regbits-24xx.h"
#include "clockdomain.h"

static int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1,
						struct clockdomain *clkdm2)
{
	omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
				clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
	return 0;
}

static int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1,
						 struct clockdomain *clkdm2)
{
	omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
				clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
	return 0;
}

static int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1,
						 struct clockdomain *clkdm2)
{
	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
				PM_WKDEP, (1 << clkdm2->dep_bit));
}

static int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
{
	struct clkdm_dep *cd;
	u32 mask = 0;

	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
		if (!cd->clkdm)
			continue; /* only happens if data is erroneous */

		/* PRM accesses are slow, so minimize them */
		mask |= 1 << cd->clkdm->dep_bit;
		atomic_set(&cd->wkdep_usecount, 0);
	}

	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
				 PM_WKDEP);
	return 0;
}

static int omap3_clkdm_add_sleepdep(struct clockdomain *clkdm1,
						 struct clockdomain *clkdm2)
{
	omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
				clkdm1->pwrdm.ptr->prcm_offs,
				OMAP3430_CM_SLEEPDEP);
	return 0;
}

static int omap3_clkdm_del_sleepdep(struct clockdomain *clkdm1,
						 struct clockdomain *clkdm2)
{
	omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
				clkdm1->pwrdm.ptr->prcm_offs,
				OMAP3430_CM_SLEEPDEP);
	return 0;
}

static int omap3_clkdm_read_sleepdep(struct clockdomain *clkdm1,
						 struct clockdomain *clkdm2)
{
	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
				OMAP3430_CM_SLEEPDEP, (1 << clkdm2->dep_bit));
}

static int omap3_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
{
	struct clkdm_dep *cd;
	u32 mask = 0;

	for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
		if (!cd->clkdm)
			continue; /* only happens if data is erroneous */

		/* PRM accesses are slow, so minimize them */
		mask |= 1 << cd->clkdm->dep_bit;
		atomic_set(&cd->sleepdep_usecount, 0);
	}
	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
				OMAP3430_CM_SLEEPDEP);
	return 0;
}

static int omap2_clkdm_sleep(struct clockdomain *clkdm)
{
	omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
				clkdm->pwrdm.ptr->prcm_offs,
				OMAP2_PM_PWSTCTRL);
	return 0;
}

static int omap2_clkdm_wakeup(struct clockdomain *clkdm)
{
	omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
				clkdm->pwrdm.ptr->prcm_offs,
				OMAP2_PM_PWSTCTRL);
	return 0;
}

static void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
{
	if (atomic_read(&clkdm->usecount) > 0)
		_clkdm_add_autodeps(clkdm);

	omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
				clkdm->clktrctrl_mask);
}

static void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
{
	omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
				clkdm->clktrctrl_mask);

	if (atomic_read(&clkdm->usecount) > 0)
		_clkdm_del_autodeps(clkdm);
}

static void _enable_hwsup(struct clockdomain *clkdm)
{
	if (cpu_is_omap24xx())
		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
					       clkdm->clktrctrl_mask);
	else if (cpu_is_omap34xx())
		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
					       clkdm->clktrctrl_mask);
}

static void _disable_hwsup(struct clockdomain *clkdm)
{
	if (cpu_is_omap24xx())
		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
						clkdm->clktrctrl_mask);
	else if (cpu_is_omap34xx())
		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
						clkdm->clktrctrl_mask);
}

static int omap3_clkdm_sleep(struct clockdomain *clkdm)
{
	omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
				clkdm->clktrctrl_mask);
	return 0;
}

static int omap3_clkdm_wakeup(struct clockdomain *clkdm)
{
	omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
				clkdm->clktrctrl_mask);
	return 0;
}

static int omap2xxx_clkdm_clk_enable(struct clockdomain *clkdm)
{
	bool hwsup = false;

	if (!clkdm->clktrctrl_mask)
		return 0;

	hwsup = omap3xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
					      clkdm->clktrctrl_mask);

	if (hwsup) {
		/* Disable HW transitions when we are changing deps */
		_disable_hwsup(clkdm);
		_clkdm_add_autodeps(clkdm);
		_enable_hwsup(clkdm);
	} else {
		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
			omap2_clkdm_wakeup(clkdm);
	}

	return 0;
}

static int omap2xxx_clkdm_clk_disable(struct clockdomain *clkdm)
{
	bool hwsup = false;

	if (!clkdm->clktrctrl_mask)
		return 0;

	hwsup = omap3xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
					      clkdm->clktrctrl_mask);

	if (hwsup) {
		/* Disable HW transitions when we are changing deps */
		_disable_hwsup(clkdm);
		_clkdm_del_autodeps(clkdm);
		_enable_hwsup(clkdm);
	} else {
		if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
			omap2_clkdm_sleep(clkdm);
	}

	return 0;
}

static void omap3_clkdm_allow_idle(struct clockdomain *clkdm)
{
	if (atomic_read(&clkdm->usecount) > 0)
		_clkdm_add_autodeps(clkdm);

	omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
				clkdm->clktrctrl_mask);
}

static void omap3_clkdm_deny_idle(struct clockdomain *clkdm)
{
	omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
				clkdm->clktrctrl_mask);

	if (atomic_read(&clkdm->usecount) > 0)
		_clkdm_del_autodeps(clkdm);
}

static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm)
{
	bool hwsup = false;

	if (!clkdm->clktrctrl_mask)
		return 0;

	/*
	 * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
	 * more details on the unpleasant problem this is working
	 * around
	 */
	if ((clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) &&
	    (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) {
		omap3_clkdm_wakeup(clkdm);
		return 0;
	}

	hwsup = omap2xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
					      clkdm->clktrctrl_mask);

	if (hwsup) {
		/* Disable HW transitions when we are changing deps */
		_disable_hwsup(clkdm);
		_clkdm_add_autodeps(clkdm);
		_enable_hwsup(clkdm);
	} else {
		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
			omap3_clkdm_wakeup(clkdm);
	}

	return 0;
}

static int omap3xxx_clkdm_clk_disable(struct clockdomain *clkdm)
{
	bool hwsup = false;

	if (!clkdm->clktrctrl_mask)
		return 0;

	/*
	 * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
	 * more details on the unpleasant problem this is working
	 * around
	 */
	if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING &&
	    !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
		_enable_hwsup(clkdm);
		return 0;
	}

	hwsup = omap2xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
					      clkdm->clktrctrl_mask);

	if (hwsup) {
		/* Disable HW transitions when we are changing deps */
		_disable_hwsup(clkdm);
		_clkdm_del_autodeps(clkdm);
		_enable_hwsup(clkdm);
	} else {
		if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
			omap3_clkdm_sleep(clkdm);
	}

	return 0;
}

struct clkdm_ops omap2_clkdm_operations = {
	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
	.clkdm_sleep		= omap2_clkdm_sleep,
	.clkdm_wakeup		= omap2_clkdm_wakeup,
	.clkdm_allow_idle	= omap2_clkdm_allow_idle,
	.clkdm_deny_idle	= omap2_clkdm_deny_idle,
	.clkdm_clk_enable	= omap2xxx_clkdm_clk_enable,
	.clkdm_clk_disable	= omap2xxx_clkdm_clk_disable,
};

struct clkdm_ops omap3_clkdm_operations = {
	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
	.clkdm_add_sleepdep	= omap3_clkdm_add_sleepdep,
	.clkdm_del_sleepdep	= omap3_clkdm_del_sleepdep,
	.clkdm_read_sleepdep	= omap3_clkdm_read_sleepdep,
	.clkdm_clear_all_sleepdeps	= omap3_clkdm_clear_all_sleepdeps,
	.clkdm_sleep		= omap3_clkdm_sleep,
	.clkdm_wakeup		= omap3_clkdm_wakeup,
	.clkdm_allow_idle	= omap3_clkdm_allow_idle,
	.clkdm_deny_idle	= omap3_clkdm_deny_idle,
	.clkdm_clk_enable	= omap3xxx_clkdm_clk_enable,
	.clkdm_clk_disable	= omap3xxx_clkdm_clk_disable,
};
+0 −74
Original line number Original line Diff line number Diff line
/*
 * AM33XX clockdomain control
 *
 * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
 * Vaibhav Hiremath <hvaibhav@ti.com>
 *
 * Derived from mach-omap2/clockdomain44xx.c written by Rajendra Nayak
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation version 2.
 *
 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
 * kind, whether express or implied; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/kernel.h>

#include "clockdomain.h"
#include "cm33xx.h"


static int am33xx_clkdm_sleep(struct clockdomain *clkdm)
{
	am33xx_cm_clkdm_force_sleep(clkdm->cm_inst, clkdm->clkdm_offs);
	return 0;
}

static int am33xx_clkdm_wakeup(struct clockdomain *clkdm)
{
	am33xx_cm_clkdm_force_wakeup(clkdm->cm_inst, clkdm->clkdm_offs);
	return 0;
}

static void am33xx_clkdm_allow_idle(struct clockdomain *clkdm)
{
	am33xx_cm_clkdm_enable_hwsup(clkdm->cm_inst, clkdm->clkdm_offs);
}

static void am33xx_clkdm_deny_idle(struct clockdomain *clkdm)
{
	am33xx_cm_clkdm_disable_hwsup(clkdm->cm_inst, clkdm->clkdm_offs);
}

static int am33xx_clkdm_clk_enable(struct clockdomain *clkdm)
{
	if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
		return am33xx_clkdm_wakeup(clkdm);

	return 0;
}

static int am33xx_clkdm_clk_disable(struct clockdomain *clkdm)
{
	bool hwsup = false;

	hwsup = am33xx_cm_is_clkdm_in_hwsup(clkdm->cm_inst, clkdm->clkdm_offs);

	if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP))
		am33xx_clkdm_sleep(clkdm);

	return 0;
}

struct clkdm_ops am33xx_clkdm_operations = {
	.clkdm_sleep		= am33xx_clkdm_sleep,
	.clkdm_wakeup		= am33xx_clkdm_wakeup,
	.clkdm_allow_idle	= am33xx_clkdm_allow_idle,
	.clkdm_deny_idle	= am33xx_clkdm_deny_idle,
	.clkdm_clk_enable	= am33xx_clkdm_clk_enable,
	.clkdm_clk_disable	= am33xx_clkdm_clk_disable,
};
+0 −151
Original line number Original line Diff line number Diff line
/*
 * OMAP4 clockdomain control
 *
 * Copyright (C) 2008-2010 Texas Instruments, Inc.
 * Copyright (C) 2008-2010 Nokia Corporation
 *
 * Derived from mach-omap2/clockdomain.c written by Paul Walmsley
 * Rajendra Nayak <rnayak@ti.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.
 */

#include <linux/kernel.h>
#include "clockdomain.h"
#include "cminst44xx.h"
#include "cm44xx.h"

static int omap4_clkdm_add_wkup_sleep_dep(struct clockdomain *clkdm1,
					struct clockdomain *clkdm2)
{
	omap4_cminst_set_inst_reg_bits((1 << clkdm2->dep_bit),
					clkdm1->prcm_partition,
					clkdm1->cm_inst, clkdm1->clkdm_offs +
					OMAP4_CM_STATICDEP);
	return 0;
}

static int omap4_clkdm_del_wkup_sleep_dep(struct clockdomain *clkdm1,
					struct clockdomain *clkdm2)
{
	omap4_cminst_clear_inst_reg_bits((1 << clkdm2->dep_bit),
					clkdm1->prcm_partition,
					clkdm1->cm_inst, clkdm1->clkdm_offs +
					OMAP4_CM_STATICDEP);
	return 0;
}

static int omap4_clkdm_read_wkup_sleep_dep(struct clockdomain *clkdm1,
					struct clockdomain *clkdm2)
{
	return omap4_cminst_read_inst_reg_bits(clkdm1->prcm_partition,
					clkdm1->cm_inst, clkdm1->clkdm_offs +
					OMAP4_CM_STATICDEP,
					(1 << clkdm2->dep_bit));
}

static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm)
{
	struct clkdm_dep *cd;
	u32 mask = 0;

	if (!clkdm->prcm_partition)
		return 0;

	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
		if (!cd->clkdm)
			continue; /* only happens if data is erroneous */

		mask |= 1 << cd->clkdm->dep_bit;
		atomic_set(&cd->wkdep_usecount, 0);
	}

	omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition,
					clkdm->cm_inst, clkdm->clkdm_offs +
					OMAP4_CM_STATICDEP);
	return 0;
}

static int omap4_clkdm_sleep(struct clockdomain *clkdm)
{
	omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition,
					clkdm->cm_inst, clkdm->clkdm_offs);
	return 0;
}

static int omap4_clkdm_wakeup(struct clockdomain *clkdm)
{
	omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition,
					clkdm->cm_inst, clkdm->clkdm_offs);
	return 0;
}

static void omap4_clkdm_allow_idle(struct clockdomain *clkdm)
{
	omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition,
					clkdm->cm_inst, clkdm->clkdm_offs);
}

static void omap4_clkdm_deny_idle(struct clockdomain *clkdm)
{
	if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
		omap4_clkdm_wakeup(clkdm);
	else
		omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition,
						 clkdm->cm_inst,
						 clkdm->clkdm_offs);
}

static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
{
	if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
		return omap4_clkdm_wakeup(clkdm);

	return 0;
}

static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
{
	bool hwsup = false;

	if (!clkdm->prcm_partition)
		return 0;

	/*
	 * The CLKDM_MISSING_IDLE_REPORTING flag documentation has
	 * more details on the unpleasant problem this is working
	 * around
	 */
	if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING &&
	    !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
		omap4_clkdm_allow_idle(clkdm);
		return 0;
	}

	hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
					clkdm->cm_inst, clkdm->clkdm_offs);

	if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP))
		omap4_clkdm_sleep(clkdm);

	return 0;
}

struct clkdm_ops omap4_clkdm_operations = {
	.clkdm_add_wkdep	= omap4_clkdm_add_wkup_sleep_dep,
	.clkdm_del_wkdep	= omap4_clkdm_del_wkup_sleep_dep,
	.clkdm_read_wkdep	= omap4_clkdm_read_wkup_sleep_dep,
	.clkdm_clear_all_wkdeps	= omap4_clkdm_clear_all_wkup_sleep_deps,
	.clkdm_add_sleepdep	= omap4_clkdm_add_wkup_sleep_dep,
	.clkdm_del_sleepdep	= omap4_clkdm_del_wkup_sleep_dep,
	.clkdm_read_sleepdep	= omap4_clkdm_read_wkup_sleep_dep,
	.clkdm_clear_all_sleepdeps	= omap4_clkdm_clear_all_wkup_sleep_deps,
	.clkdm_sleep		= omap4_clkdm_sleep,
	.clkdm_wakeup		= omap4_clkdm_wakeup,
	.clkdm_allow_idle	= omap4_clkdm_allow_idle,
	.clkdm_deny_idle	= omap4_clkdm_deny_idle,
	.clkdm_clk_enable	= omap4_clkdm_clk_enable,
	.clkdm_clk_disable	= omap4_clkdm_clk_disable,
};
+88 −1
Original line number Original line Diff line number Diff line
@@ -2,8 +2,9 @@
 * OMAP2xxx CM module functions
 * OMAP2xxx CM module functions
 *
 *
 * Copyright (C) 2009 Nokia Corporation
 * Copyright (C) 2009 Nokia Corporation
 * Copyright (C) 2012 Texas Instruments, Inc.
 * Copyright (C) 2008-2010, 2012 Texas Instruments, Inc.
 * Paul Walmsley
 * Paul Walmsley
 * Rajendra Nayak <rnayak@ti.com>
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * 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
 * it under the terms of the GNU General Public License version 2 as
@@ -20,9 +21,11 @@
#include "soc.h"
#include "soc.h"
#include "iomap.h"
#include "iomap.h"
#include "common.h"
#include "common.h"
#include "prm2xxx.h"
#include "cm.h"
#include "cm.h"
#include "cm2xxx.h"
#include "cm2xxx.h"
#include "cm-regbits-24xx.h"
#include "cm-regbits-24xx.h"
#include "clockdomain.h"


/* CM_AUTOIDLE_PLL.AUTO_* bit values for DPLLs */
/* CM_AUTOIDLE_PLL.AUTO_* bit values for DPLLs */
#define DPLL_AUTOIDLE_DISABLE				0x0
#define DPLL_AUTOIDLE_DISABLE				0x0
@@ -166,3 +169,87 @@ int omap2xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)


	return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
	return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
}
}

/* Clockdomain low-level functions */

static void omap2xxx_clkdm_allow_idle(struct clockdomain *clkdm)
{
	if (atomic_read(&clkdm->usecount) > 0)
		_clkdm_add_autodeps(clkdm);

	omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
				       clkdm->clktrctrl_mask);
}

static void omap2xxx_clkdm_deny_idle(struct clockdomain *clkdm)
{
	omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
					clkdm->clktrctrl_mask);

	if (atomic_read(&clkdm->usecount) > 0)
		_clkdm_del_autodeps(clkdm);
}

static int omap2xxx_clkdm_clk_enable(struct clockdomain *clkdm)
{
	bool hwsup = false;

	if (!clkdm->clktrctrl_mask)
		return 0;

	hwsup = omap2xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
					      clkdm->clktrctrl_mask);

	if (hwsup) {
		/* Disable HW transitions when we are changing deps */
		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
						clkdm->clktrctrl_mask);
		_clkdm_add_autodeps(clkdm);
		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
					       clkdm->clktrctrl_mask);
	} else {
		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
			omap2xxx_clkdm_wakeup(clkdm);
	}

	return 0;
}

static int omap2xxx_clkdm_clk_disable(struct clockdomain *clkdm)
{
	bool hwsup = false;

	if (!clkdm->clktrctrl_mask)
		return 0;

	hwsup = omap2xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
					      clkdm->clktrctrl_mask);

	if (hwsup) {
		/* Disable HW transitions when we are changing deps */
		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
						clkdm->clktrctrl_mask);
		_clkdm_del_autodeps(clkdm);
		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
					       clkdm->clktrctrl_mask);
	} else {
		if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
			omap2xxx_clkdm_sleep(clkdm);
	}

	return 0;
}

struct clkdm_ops omap2_clkdm_operations = {
	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
	.clkdm_sleep		= omap2xxx_clkdm_sleep,
	.clkdm_wakeup		= omap2xxx_clkdm_wakeup,
	.clkdm_allow_idle	= omap2xxx_clkdm_allow_idle,
	.clkdm_deny_idle	= omap2xxx_clkdm_deny_idle,
	.clkdm_clk_enable	= omap2xxx_clkdm_clk_enable,
	.clkdm_clk_disable	= omap2xxx_clkdm_clk_disable,
};
Loading