mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-19 03:16:11 +07:00
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: Paul Walmsley <paul@pwsan.com> Cc: Rajendra Nayak <rnayak@ti.com> Cc: Vaibhav Hiremath <hvaibhav@ti.com> Acked-by: Rajendra Nayak <rnayak@ti.com> Reviewed-by: Russ Dill <Russ.Dill@ti.com> Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
This commit is contained in:
parent
ff4ae5d931
commit
4bd5259e53
@ -133,22 +133,17 @@ obj-$(CONFIG_SOC_OMAP5) += $(powerdomain-common)
|
||||
# PRCM clockdomain control
|
||||
clockdomain-common += clockdomain.o
|
||||
obj-$(CONFIG_ARCH_OMAP2) += $(clockdomain-common)
|
||||
obj-$(CONFIG_ARCH_OMAP2) += clockdomain2xxx_3xxx.o
|
||||
obj-$(CONFIG_ARCH_OMAP2) += clockdomains2xxx_3xxx_data.o
|
||||
obj-$(CONFIG_SOC_OMAP2420) += clockdomains2420_data.o
|
||||
obj-$(CONFIG_SOC_OMAP2430) += clockdomains2430_data.o
|
||||
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) += clockdomains3xxx_data.o
|
||||
obj-$(CONFIG_ARCH_OMAP4) += $(clockdomain-common)
|
||||
obj-$(CONFIG_ARCH_OMAP4) += clockdomain44xx.o
|
||||
obj-$(CONFIG_ARCH_OMAP4) += clockdomains44xx_data.o
|
||||
obj-$(CONFIG_SOC_AM33XX) += $(clockdomain-common)
|
||||
obj-$(CONFIG_SOC_AM33XX) += clockdomain33xx.o
|
||||
obj-$(CONFIG_SOC_AM33XX) += clockdomains33xx_data.o
|
||||
obj-$(CONFIG_SOC_OMAP5) += $(clockdomain-common)
|
||||
obj-$(CONFIG_SOC_OMAP5) += clockdomain44xx.o
|
||||
|
||||
# Clock framework
|
||||
obj-$(CONFIG_ARCH_OMAP2) += $(clock-common) clock2xxx.o
|
||||
|
@ -1,340 +0,0 @@
|
||||
/*
|
||||
* 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,
|
||||
};
|
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* 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,
|
||||
};
|
@ -1,151 +0,0 @@
|
||||
/*
|
||||
* 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,
|
||||
};
|
@ -2,8 +2,9 @@
|
||||
* OMAP2xxx CM module functions
|
||||
*
|
||||
* Copyright (C) 2009 Nokia Corporation
|
||||
* Copyright (C) 2012 Texas Instruments, Inc.
|
||||
* Copyright (C) 2008-2010, 2012 Texas Instruments, Inc.
|
||||
* 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
|
||||
@ -20,9 +21,11 @@
|
||||
#include "soc.h"
|
||||
#include "iomap.h"
|
||||
#include "common.h"
|
||||
#include "prm2xxx.h"
|
||||
#include "cm.h"
|
||||
#include "cm2xxx.h"
|
||||
#include "cm-regbits-24xx.h"
|
||||
#include "clockdomain.h"
|
||||
|
||||
/* CM_AUTOIDLE_PLL.AUTO_* bit values for DPLLs */
|
||||
#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;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
};
|
||||
|
||||
|
@ -74,6 +74,18 @@ static inline u32 omap2_cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module,
|
||||
return v;
|
||||
}
|
||||
|
||||
/* Read a CM register, AND it, and shift the result down to bit 0 */
|
||||
static inline u32 omap2_cm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
v = omap2_cm_read_mod_reg(domain, idx);
|
||||
v &= mask;
|
||||
v >>= __ffs(mask);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline u32 omap2_cm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
|
||||
{
|
||||
return omap2_cm_rmw_mod_reg_bits(bits, bits, module, idx);
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <plat/common.h>
|
||||
|
||||
#include "clockdomain.h"
|
||||
#include "cm.h"
|
||||
#include "cm33xx.h"
|
||||
#include "cm-regbits-34xx.h"
|
||||
@ -311,3 +312,58 @@ void am33xx_cm_module_disable(u16 inst, s16 cdoffs, u16 clkctrl_offs)
|
||||
v &= ~AM33XX_MODULEMODE_MASK;
|
||||
am33xx_cm_write_reg(v, inst, clkctrl_offs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clockdomain low-level functions
|
||||
*/
|
||||
|
||||
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,
|
||||
};
|
||||
|
@ -1,9 +1,10 @@
|
||||
/*
|
||||
* OMAP2/3 CM module functions
|
||||
* OMAP3xxx CM module functions
|
||||
*
|
||||
* Copyright (C) 2009 Nokia Corporation
|
||||
* Copyright (C) 2012 Texas Instruments, Inc.
|
||||
* Copyright (C) 2008-2010, 2012 Texas Instruments, Inc.
|
||||
* 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
|
||||
@ -20,9 +21,11 @@
|
||||
#include "soc.h"
|
||||
#include "iomap.h"
|
||||
#include "common.h"
|
||||
#include "prm2xxx_3xxx.h"
|
||||
#include "cm.h"
|
||||
#include "cm3xxx.h"
|
||||
#include "cm-regbits-34xx.h"
|
||||
#include "clockdomain.h"
|
||||
|
||||
static const u8 omap3xxx_cm_idlest_offs[] = {
|
||||
CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3
|
||||
@ -107,6 +110,173 @@ int omap3xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
|
||||
return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
|
||||
}
|
||||
|
||||
/* Clockdomain low-level operations */
|
||||
|
||||
static int omap3xxx_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 omap3xxx_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 omap3xxx_clkdm_read_sleepdep(struct clockdomain *clkdm1,
|
||||
struct clockdomain *clkdm2)
|
||||
{
|
||||
return omap2_cm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
|
||||
OMAP3430_CM_SLEEPDEP,
|
||||
(1 << clkdm2->dep_bit));
|
||||
}
|
||||
|
||||
static int omap3xxx_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 */
|
||||
|
||||
mask |= 1 << cd->clkdm->dep_bit;
|
||||
atomic_set(&cd->sleepdep_usecount, 0);
|
||||
}
|
||||
omap2_cm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
|
||||
OMAP3430_CM_SLEEPDEP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int omap3xxx_clkdm_sleep(struct clockdomain *clkdm)
|
||||
{
|
||||
omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
|
||||
clkdm->clktrctrl_mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int omap3xxx_clkdm_wakeup(struct clockdomain *clkdm)
|
||||
{
|
||||
omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
|
||||
clkdm->clktrctrl_mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void omap3xxx_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 omap3xxx_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)) {
|
||||
omap3xxx_clkdm_wakeup(clkdm);
|
||||
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 */
|
||||
omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
|
||||
clkdm->clktrctrl_mask);
|
||||
_clkdm_add_autodeps(clkdm);
|
||||
omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
|
||||
clkdm->clktrctrl_mask);
|
||||
} else {
|
||||
if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
|
||||
omap3xxx_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)) {
|
||||
omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
|
||||
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 */
|
||||
omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
|
||||
clkdm->clktrctrl_mask);
|
||||
_clkdm_del_autodeps(clkdm);
|
||||
omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
|
||||
clkdm->clktrctrl_mask);
|
||||
} else {
|
||||
if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
|
||||
omap3xxx_clkdm_sleep(clkdm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 = omap3xxx_clkdm_add_sleepdep,
|
||||
.clkdm_del_sleepdep = omap3xxx_clkdm_del_sleepdep,
|
||||
.clkdm_read_sleepdep = omap3xxx_clkdm_read_sleepdep,
|
||||
.clkdm_clear_all_sleepdeps = omap3xxx_clkdm_clear_all_sleepdeps,
|
||||
.clkdm_sleep = omap3xxx_clkdm_sleep,
|
||||
.clkdm_wakeup = omap3xxx_clkdm_wakeup,
|
||||
.clkdm_allow_idle = omap3xxx_clkdm_allow_idle,
|
||||
.clkdm_deny_idle = omap3xxx_clkdm_deny_idle,
|
||||
.clkdm_clk_enable = omap3xxx_clkdm_clk_enable,
|
||||
.clkdm_clk_disable = omap3xxx_clkdm_clk_disable,
|
||||
};
|
||||
|
||||
/*
|
||||
* Context save/restore code - OMAP3 only
|
||||
*/
|
||||
|
@ -2,8 +2,9 @@
|
||||
* OMAP4 CM instance functions
|
||||
*
|
||||
* Copyright (C) 2009 Nokia Corporation
|
||||
* Copyright (C) 2011 Texas Instruments, Inc.
|
||||
* Copyright (C) 2008-2011 Texas Instruments, Inc.
|
||||
* 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
|
||||
@ -22,6 +23,7 @@
|
||||
|
||||
#include "iomap.h"
|
||||
#include "common.h"
|
||||
#include "clockdomain.h"
|
||||
#include "cm.h"
|
||||
#include "cm1_44xx.h"
|
||||
#include "cm2_44xx.h"
|
||||
@ -343,3 +345,141 @@ void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs,
|
||||
v &= ~OMAP4430_MODULEMODE_MASK;
|
||||
omap4_cminst_write_inst_reg(v, part, inst, clkctrl_offs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clockdomain low-level functions
|
||||
*/
|
||||
|
||||
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,
|
||||
};
|
||||
|
@ -24,10 +24,27 @@
|
||||
|
||||
#include "vp.h"
|
||||
#include "powerdomain.h"
|
||||
#include "clockdomain.h"
|
||||
#include "prm2xxx.h"
|
||||
#include "cm2xxx_3xxx.h"
|
||||
#include "prm-regbits-24xx.h"
|
||||
|
||||
int omap2xxx_clkdm_sleep(struct clockdomain *clkdm)
|
||||
{
|
||||
omap2_prm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
|
||||
clkdm->pwrdm.ptr->prcm_offs,
|
||||
OMAP2_PM_PWSTCTRL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm)
|
||||
{
|
||||
omap2_prm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
|
||||
clkdm->pwrdm.ptr->prcm_offs,
|
||||
OMAP2_PM_PWSTCTRL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct pwrdm_ops omap2_pwrdm_operations = {
|
||||
.pwrdm_set_next_pwrst = omap2_pwrdm_set_next_pwrst,
|
||||
.pwrdm_read_next_pwrst = omap2_pwrdm_read_next_pwrst,
|
||||
|
@ -119,4 +119,10 @@
|
||||
#define OMAP24XX_PRCM_IRQSTATUS_IVA 0x00f8
|
||||
#define OMAP24XX_PRCM_IRQENABLE_IVA 0x00fc
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
/* Function prototypes */
|
||||
extern int omap2xxx_clkdm_sleep(struct clockdomain *clkdm);
|
||||
extern int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "powerdomain.h"
|
||||
#include "prm2xxx_3xxx.h"
|
||||
#include "prm-regbits-24xx.h"
|
||||
#include "clockdomain.h"
|
||||
|
||||
/**
|
||||
* omap2_prm_is_hardreset_asserted - read the HW reset line state of
|
||||
@ -208,3 +209,45 @@ int omap2_pwrdm_wait_transition(struct powerdomain *pwrdm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -116,6 +116,14 @@ extern int omap2_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank);
|
||||
extern int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
|
||||
extern int omap2_pwrdm_wait_transition(struct powerdomain *pwrdm);
|
||||
|
||||
extern int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1,
|
||||
struct clockdomain *clkdm2);
|
||||
extern int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1,
|
||||
struct clockdomain *clkdm2);
|
||||
extern int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1,
|
||||
struct clockdomain *clkdm2);
|
||||
extern int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm);
|
||||
|
||||
#endif /* __ASSEMBLER */
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user