Merge tag 'omap-cleanup-a-for-3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/pjw/omap-pending into omap-for-v3.8/cleanup-prcm
The first set of OMAP PRM/CM-related cleanup patches for 3.8. Prepares for the future move of the PRM/CM code to drivers/. Also includes some prcm.[ch] cleanup patches from the WDTIMER cleanup series that don't need external acks. Basic test logs for this branch on top of v3.7-rc2 are here: http://www.pwsan.com/omap/testlogs/prcm_cleanup_a_3.8/20121021123719/ But due to the number of unrelated regressions present in v3.7-rc[12], it's not particularly usable as a testing base. With reverts, fixes, and workarounds applied as documented in: http://www.pwsan.com/omap/testlogs/test_v3.7-rc2/20121020134755/README.txt the following test logs were obtained: http://www.pwsan.com/omap/testlogs/prcm_cleanup_a_3.8/20121020231757/ which indicate that the series tests cleanly. Conflicts: arch/arm/mach-omap2/Makefile arch/arm/mach-omap2/clockdomain2xxx_3xxx.c arch/arm/mach-omap2/pm24xx.c
This commit is contained in:
@@ -94,4 +94,6 @@ extern int ocpi_enable(void);
|
|||||||
static inline int ocpi_enable(void) { return 0; }
|
static inline int ocpi_enable(void) { return 0; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern int omap1_get_reset_sources(void);
|
||||||
|
|
||||||
#endif /* __ARCH_ARM_MACH_OMAP1_COMMON_H */
|
#endif /* __ARCH_ARM_MACH_OMAP1_COMMON_H */
|
||||||
|
|||||||
@@ -10,6 +10,19 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
/* ARM_SYSST bit shifts related to SoC reset sources */
|
||||||
|
#define ARM_SYSST_POR_SHIFT 5
|
||||||
|
#define ARM_SYSST_EXT_RST_SHIFT 4
|
||||||
|
#define ARM_SYSST_ARM_WDRST_SHIFT 2
|
||||||
|
#define ARM_SYSST_GLOB_SWRST_SHIFT 1
|
||||||
|
|
||||||
|
/* Standardized reset source bits (across all OMAP SoCs) */
|
||||||
|
#define OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT 0
|
||||||
|
#define OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT 1
|
||||||
|
#define OMAP_MPU_WD_RST_SRC_ID_SHIFT 3
|
||||||
|
#define OMAP_EXTWARM_RST_SRC_ID_SHIFT 5
|
||||||
|
|
||||||
|
|
||||||
void omap1_restart(char mode, const char *cmd)
|
void omap1_restart(char mode, const char *cmd)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -23,3 +36,28 @@ void omap1_restart(char mode, const char *cmd)
|
|||||||
|
|
||||||
omap_writew(1, ARM_RSTCT1);
|
omap_writew(1, ARM_RSTCT1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* omap1_get_reset_sources - return the source of the SoC's last reset
|
||||||
|
*
|
||||||
|
* Returns bits that represent the last reset source for the SoC. The
|
||||||
|
* format is standardized across OMAPs for use by the OMAP watchdog.
|
||||||
|
*/
|
||||||
|
int omap1_get_reset_sources(void)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
u16 rs;
|
||||||
|
|
||||||
|
rs = __raw_readw(ARM_SYSST);
|
||||||
|
|
||||||
|
if (rs & (1 << ARM_SYSST_POR_SHIFT))
|
||||||
|
ret |= 1 << OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT;
|
||||||
|
if (rs & (1 << ARM_SYSST_EXT_RST_SHIFT))
|
||||||
|
ret |= 1 << OMAP_EXTWARM_RST_SRC_ID_SHIFT;
|
||||||
|
if (rs & (1 << ARM_SYSST_ARM_WDRST_SHIFT))
|
||||||
|
ret |= 1 << OMAP_MPU_WD_RST_SRC_ID_SHIFT;
|
||||||
|
if (rs & (1 << ARM_SYSST_GLOB_SWRST_SHIFT))
|
||||||
|
ret |= 1 << OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,28 +7,34 @@ obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer.o pm.o \
|
|||||||
common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o \
|
common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o \
|
||||||
omap_device.o
|
omap_device.o
|
||||||
|
|
||||||
# INTCPS IP block support - XXX should be moved to drivers/
|
omap-2-3-common = irq.o
|
||||||
obj-$(CONFIG_ARCH_OMAP2) += irq.o
|
hwmod-common = omap_hwmod.o \
|
||||||
obj-$(CONFIG_ARCH_OMAP3) += irq.o
|
omap_hwmod_common_data.o
|
||||||
obj-$(CONFIG_SOC_AM33XX) += irq.o
|
clock-common = clock.o clock_common_data.o \
|
||||||
|
clkt_dpll.o clkt_clksel.o
|
||||||
|
secure-common = omap-smc.o omap-secure.o
|
||||||
|
|
||||||
# Secure monitor API support
|
obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
|
||||||
obj-$(CONFIG_ARCH_OMAP3) += omap-smc.o omap-secure.o
|
obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common)
|
||||||
obj-$(CONFIG_ARCH_OMAP4) += omap-smc.o omap-secure.o
|
obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common) $(secure-common)
|
||||||
obj-$(CONFIG_SOC_OMAP5) += omap-smc.o omap-secure.o
|
obj-$(CONFIG_SOC_AM33XX) += irq.o $(hwmod-common)
|
||||||
|
obj-$(CONFIG_SOC_OMAP5) += prm44xx.o $(hwmod-common) $(secure-common)
|
||||||
|
|
||||||
ifneq ($(CONFIG_SND_OMAP_SOC_MCBSP),)
|
ifneq ($(CONFIG_SND_OMAP_SOC_MCBSP),)
|
||||||
obj-y += mcbsp.o
|
obj-y += mcbsp.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
|
obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
|
||||||
|
obj-$(CONFIG_SOC_HAS_OMAP2_SDRC) += sdrc.o
|
||||||
|
|
||||||
# SMP support ONLY available for OMAP4
|
# SMP support ONLY available for OMAP4
|
||||||
|
|
||||||
obj-$(CONFIG_SMP) += omap-smp.o omap-headsmp.o
|
obj-$(CONFIG_SMP) += omap-smp.o omap-headsmp.o
|
||||||
obj-$(CONFIG_HOTPLUG_CPU) += omap-hotplug.o
|
obj-$(CONFIG_HOTPLUG_CPU) += omap-hotplug.o
|
||||||
obj-$(CONFIG_ARCH_OMAP4) += omap4-common.o omap-wakeupgen.o
|
omap-4-5-common = omap4-common.o omap-wakeupgen.o \
|
||||||
obj-$(CONFIG_SOC_OMAP5) += omap4-common.o omap-wakeupgen.o
|
sleep44xx.o
|
||||||
|
obj-$(CONFIG_ARCH_OMAP4) += $(omap-4-5-common)
|
||||||
|
obj-$(CONFIG_SOC_OMAP5) += $(omap-4-5-common)
|
||||||
|
|
||||||
plus_sec := $(call as-instr,.arch_extension sec,+sec)
|
plus_sec := $(call as-instr,.arch_extension sec,+sec)
|
||||||
AFLAGS_omap-headsmp.o :=-Wa,-march=armv7-a$(plus_sec)
|
AFLAGS_omap-headsmp.o :=-Wa,-march=armv7-a$(plus_sec)
|
||||||
@@ -53,7 +59,6 @@ obj-$(CONFIG_ARCH_OMAP4) += mux44xx.o
|
|||||||
# SMS/SDRC
|
# SMS/SDRC
|
||||||
obj-$(CONFIG_ARCH_OMAP2) += sdrc2xxx.o
|
obj-$(CONFIG_ARCH_OMAP2) += sdrc2xxx.o
|
||||||
# obj-$(CONFIG_ARCH_OMAP3) += sdrc3xxx.o
|
# obj-$(CONFIG_ARCH_OMAP3) += sdrc3xxx.o
|
||||||
obj-$(CONFIG_SOC_HAS_OMAP2_SDRC) += sdrc.o
|
|
||||||
|
|
||||||
# OPP table initialization
|
# OPP table initialization
|
||||||
ifeq ($(CONFIG_PM_OPP),y)
|
ifeq ($(CONFIG_PM_OPP),y)
|
||||||
@@ -64,15 +69,15 @@ endif
|
|||||||
|
|
||||||
# Power Management
|
# Power Management
|
||||||
ifeq ($(CONFIG_PM),y)
|
ifeq ($(CONFIG_PM),y)
|
||||||
obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o sleep24xx.o
|
obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
|
||||||
|
obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o
|
||||||
obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o
|
obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o
|
||||||
obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o omap-mpuss-lowpower.o
|
obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o omap-mpuss-lowpower.o
|
||||||
obj-$(CONFIG_ARCH_OMAP4) += sleep44xx.o
|
obj-$(CONFIG_SOC_OMAP5) += omap-mpuss-lowpower.o
|
||||||
obj-$(CONFIG_SOC_OMAP5) += omap-mpuss-lowpower.o sleep44xx.o
|
|
||||||
obj-$(CONFIG_PM_DEBUG) += pm-debug.o
|
obj-$(CONFIG_PM_DEBUG) += pm-debug.o
|
||||||
|
|
||||||
obj-$(CONFIG_POWER_AVS_OMAP) += sr_device.o
|
obj-$(CONFIG_POWER_AVS_OMAP) += sr_device.o
|
||||||
obj-$(CONFIG_POWER_AVS_OMAP_CLASS3) += smartreflex-class3.o
|
obj-$(CONFIG_POWER_AVS_OMAP_CLASS3) += smartreflex-class3.o
|
||||||
|
|
||||||
AFLAGS_sleep24xx.o :=-Wa,-march=armv6
|
AFLAGS_sleep24xx.o :=-Wa,-march=armv6
|
||||||
AFLAGS_sleep34xx.o :=-Wa,-march=armv7-a$(plus_sec)
|
AFLAGS_sleep34xx.o :=-Wa,-march=armv7-a$(plus_sec)
|
||||||
@@ -84,76 +89,82 @@ endif
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_CPU_IDLE),y)
|
ifeq ($(CONFIG_CPU_IDLE),y)
|
||||||
obj-$(CONFIG_ARCH_OMAP3) += cpuidle34xx.o
|
obj-$(CONFIG_ARCH_OMAP3) += cpuidle34xx.o
|
||||||
obj-$(CONFIG_ARCH_OMAP4) += cpuidle44xx.o
|
obj-$(CONFIG_ARCH_OMAP4) += cpuidle44xx.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# PRCM
|
# PRCM
|
||||||
obj-y += prcm.o prm_common.o
|
obj-y += prcm.o prm_common.o cm_common.o
|
||||||
obj-$(CONFIG_ARCH_OMAP2) += cm2xxx_3xxx.o prm2xxx_3xxx.o
|
obj-$(CONFIG_ARCH_OMAP2) += prm2xxx_3xxx.o prm2xxx.o cm2xxx.o
|
||||||
obj-$(CONFIG_ARCH_OMAP3) += cm2xxx_3xxx.o prm2xxx_3xxx.o
|
obj-$(CONFIG_ARCH_OMAP3) += prm2xxx_3xxx.o prm3xxx.o cm3xxx.o
|
||||||
obj-$(CONFIG_ARCH_OMAP3) += vc3xxx_data.o vp3xxx_data.o
|
obj-$(CONFIG_ARCH_OMAP3) += vc3xxx_data.o vp3xxx_data.o
|
||||||
obj-$(CONFIG_SOC_AM33XX) += prm33xx.o cm33xx.o
|
obj-$(CONFIG_SOC_AM33XX) += prm33xx.o cm33xx.o
|
||||||
omap-prcm-4-5-common = cminst44xx.o cm44xx.o prm44xx.o \
|
omap-prcm-4-5-common = cminst44xx.o cm44xx.o prm44xx.o \
|
||||||
prcm_mpu44xx.o prminst44xx.o \
|
prcm_mpu44xx.o prminst44xx.o \
|
||||||
vc44xx_data.o vp44xx_data.o \
|
vc44xx_data.o vp44xx_data.o
|
||||||
prm44xx.o
|
|
||||||
obj-$(CONFIG_ARCH_OMAP4) += $(omap-prcm-4-5-common)
|
obj-$(CONFIG_ARCH_OMAP4) += $(omap-prcm-4-5-common)
|
||||||
obj-$(CONFIG_SOC_OMAP5) += $(omap-prcm-4-5-common)
|
obj-$(CONFIG_SOC_OMAP5) += $(omap-prcm-4-5-common)
|
||||||
|
|
||||||
# OMAP voltage domains
|
# OMAP voltage domains
|
||||||
obj-y += voltage.o vc.o vp.o
|
voltagedomain-common := voltage.o vc.o vp.o
|
||||||
|
obj-$(CONFIG_ARCH_OMAP2) += $(voltagedomain-common)
|
||||||
obj-$(CONFIG_ARCH_OMAP2) += voltagedomains2xxx_data.o
|
obj-$(CONFIG_ARCH_OMAP2) += voltagedomains2xxx_data.o
|
||||||
|
obj-$(CONFIG_ARCH_OMAP3) += $(voltagedomain-common)
|
||||||
obj-$(CONFIG_ARCH_OMAP3) += voltagedomains3xxx_data.o
|
obj-$(CONFIG_ARCH_OMAP3) += voltagedomains3xxx_data.o
|
||||||
|
obj-$(CONFIG_ARCH_OMAP4) += $(voltagedomain-common)
|
||||||
obj-$(CONFIG_ARCH_OMAP4) += voltagedomains44xx_data.o
|
obj-$(CONFIG_ARCH_OMAP4) += voltagedomains44xx_data.o
|
||||||
obj-$(CONFIG_SOC_AM33XX) += voltagedomains33xx_data.o
|
obj-$(CONFIG_SOC_AM33XX) += $(voltagedomain-common)
|
||||||
|
obj-$(CONFIG_SOC_AM33XX) += voltagedomains33xx_data.o
|
||||||
|
obj-$(CONFIG_SOC_OMAP5) += $(voltagedomain-common)
|
||||||
|
|
||||||
# OMAP powerdomain framework
|
# OMAP powerdomain framework
|
||||||
obj-y += powerdomain.o powerdomain-common.o
|
powerdomain-common += powerdomain.o powerdomain-common.o
|
||||||
|
obj-$(CONFIG_ARCH_OMAP2) += $(powerdomain-common)
|
||||||
obj-$(CONFIG_ARCH_OMAP2) += powerdomains2xxx_data.o
|
obj-$(CONFIG_ARCH_OMAP2) += powerdomains2xxx_data.o
|
||||||
obj-$(CONFIG_ARCH_OMAP2) += powerdomain2xxx_3xxx.o
|
|
||||||
obj-$(CONFIG_ARCH_OMAP2) += powerdomains2xxx_3xxx_data.o
|
obj-$(CONFIG_ARCH_OMAP2) += powerdomains2xxx_3xxx_data.o
|
||||||
obj-$(CONFIG_ARCH_OMAP3) += powerdomain2xxx_3xxx.o
|
obj-$(CONFIG_ARCH_OMAP3) += $(powerdomain-common)
|
||||||
obj-$(CONFIG_ARCH_OMAP3) += powerdomains3xxx_data.o
|
obj-$(CONFIG_ARCH_OMAP3) += powerdomains3xxx_data.o
|
||||||
obj-$(CONFIG_ARCH_OMAP3) += powerdomains2xxx_3xxx_data.o
|
obj-$(CONFIG_ARCH_OMAP3) += powerdomains2xxx_3xxx_data.o
|
||||||
obj-$(CONFIG_ARCH_OMAP4) += powerdomain44xx.o
|
obj-$(CONFIG_ARCH_OMAP4) += $(powerdomain-common)
|
||||||
obj-$(CONFIG_ARCH_OMAP4) += powerdomains44xx_data.o
|
obj-$(CONFIG_ARCH_OMAP4) += powerdomains44xx_data.o
|
||||||
obj-$(CONFIG_SOC_AM33XX) += powerdomain33xx.o
|
obj-$(CONFIG_SOC_AM33XX) += $(powerdomain-common)
|
||||||
obj-$(CONFIG_SOC_AM33XX) += powerdomains33xx_data.o
|
obj-$(CONFIG_SOC_AM33XX) += powerdomains33xx_data.o
|
||||||
obj-$(CONFIG_SOC_OMAP5) += powerdomain44xx.o
|
obj-$(CONFIG_SOC_OMAP5) += $(powerdomain-common)
|
||||||
|
|
||||||
# PRCM clockdomain control
|
# PRCM clockdomain control
|
||||||
obj-y += clockdomain.o
|
clockdomain-common += clockdomain.o
|
||||||
obj-$(CONFIG_ARCH_OMAP2) += clockdomain2xxx_3xxx.o
|
obj-$(CONFIG_ARCH_OMAP2) += $(clockdomain-common)
|
||||||
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) += clockdomain2xxx_3xxx.o
|
obj-$(CONFIG_ARCH_OMAP3) += $(clockdomain-common)
|
||||||
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) += clockdomain44xx.o
|
obj-$(CONFIG_ARCH_OMAP4) += $(clockdomain-common)
|
||||||
obj-$(CONFIG_ARCH_OMAP4) += clockdomains44xx_data.o
|
obj-$(CONFIG_ARCH_OMAP4) += clockdomains44xx_data.o
|
||||||
obj-$(CONFIG_SOC_AM33XX) += clockdomain33xx.o
|
obj-$(CONFIG_SOC_AM33XX) += $(clockdomain-common)
|
||||||
obj-$(CONFIG_SOC_AM33XX) += clockdomains33xx_data.o
|
obj-$(CONFIG_SOC_AM33XX) += clockdomains33xx_data.o
|
||||||
obj-$(CONFIG_SOC_OMAP5) += clockdomain44xx.o
|
obj-$(CONFIG_SOC_OMAP5) += $(clockdomain-common)
|
||||||
|
|
||||||
# Clock framework
|
# Clock framework
|
||||||
obj-y += clock.o clock_common_data.o \
|
obj-$(CONFIG_ARCH_OMAP2) += $(clock-common) clock2xxx.o
|
||||||
clkt_dpll.o clkt_clksel.o
|
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_sys.o
|
||||||
obj-$(CONFIG_ARCH_OMAP2) += clock2xxx.o
|
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpllcore.o
|
||||||
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpllcore.o clkt2xxx_sys.o
|
|
||||||
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_virt_prcm_set.o
|
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_virt_prcm_set.o
|
||||||
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_apll.o clkt2xxx_osc.o
|
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_apll.o clkt2xxx_osc.o
|
||||||
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpll.o clkt_iclk.o
|
obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpll.o clkt_iclk.o
|
||||||
obj-$(CONFIG_SOC_OMAP2420) += clock2420_data.o
|
obj-$(CONFIG_SOC_OMAP2420) += clock2420_data.o
|
||||||
obj-$(CONFIG_SOC_OMAP2430) += clock2430.o clock2430_data.o
|
obj-$(CONFIG_SOC_OMAP2430) += clock2430.o clock2430_data.o
|
||||||
obj-$(CONFIG_ARCH_OMAP3) += clock3xxx.o
|
obj-$(CONFIG_ARCH_OMAP3) += $(clock-common) clock3xxx.o
|
||||||
obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o clkt34xx_dpll3m2.o
|
obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o clkt34xx_dpll3m2.o
|
||||||
obj-$(CONFIG_ARCH_OMAP3) += clock3517.o clock36xx.o clkt_iclk.o
|
obj-$(CONFIG_ARCH_OMAP3) += clock3517.o clock36xx.o
|
||||||
obj-$(CONFIG_ARCH_OMAP3) += dpll3xxx.o clock3xxx_data.o
|
obj-$(CONFIG_ARCH_OMAP3) += dpll3xxx.o clock3xxx_data.o
|
||||||
obj-$(CONFIG_ARCH_OMAP4) += clock44xx_data.o
|
obj-$(CONFIG_ARCH_OMAP3) += clkt_iclk.o
|
||||||
|
obj-$(CONFIG_ARCH_OMAP4) += $(clock-common) clock44xx_data.o
|
||||||
obj-$(CONFIG_ARCH_OMAP4) += dpll3xxx.o dpll44xx.o
|
obj-$(CONFIG_ARCH_OMAP4) += dpll3xxx.o dpll44xx.o
|
||||||
obj-$(CONFIG_SOC_AM33XX) += dpll3xxx.o clock33xx_data.o
|
obj-$(CONFIG_SOC_AM33XX) += $(clock-common) dpll3xxx.o
|
||||||
|
obj-$(CONFIG_SOC_AM33XX) += clock33xx_data.o
|
||||||
|
obj-$(CONFIG_SOC_OMAP5) += $(clock-common)
|
||||||
obj-$(CONFIG_SOC_OMAP5) += dpll3xxx.o dpll44xx.o
|
obj-$(CONFIG_SOC_OMAP5) += dpll3xxx.o dpll44xx.o
|
||||||
|
|
||||||
# OMAP2 clock rate set data (old "OPP" data)
|
# OMAP2 clock rate set data (old "OPP" data)
|
||||||
@@ -161,7 +172,6 @@ obj-$(CONFIG_SOC_OMAP2420) += opp2420_data.o
|
|||||||
obj-$(CONFIG_SOC_OMAP2430) += opp2430_data.o
|
obj-$(CONFIG_SOC_OMAP2430) += opp2430_data.o
|
||||||
|
|
||||||
# hwmod data
|
# hwmod data
|
||||||
obj-y += omap_hwmod_common_data.o
|
|
||||||
obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2xxx_ipblock_data.o
|
obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2xxx_ipblock_data.o
|
||||||
obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2xxx_3xxx_ipblock_data.o
|
obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2xxx_3xxx_ipblock_data.o
|
||||||
obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2xxx_interconnect_data.o
|
obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2xxx_interconnect_data.o
|
||||||
@@ -207,10 +217,10 @@ obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o
|
|||||||
obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o
|
obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o
|
||||||
obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o
|
obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o
|
||||||
obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o
|
obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o
|
||||||
obj-$(CONFIG_MACH_DEVKIT8000) += board-devkit8000.o
|
obj-$(CONFIG_MACH_DEVKIT8000) += board-devkit8000.o
|
||||||
obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o
|
obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o
|
||||||
obj-$(CONFIG_MACH_OMAP3530_LV_SOM) += board-omap3logic.o
|
obj-$(CONFIG_MACH_OMAP3530_LV_SOM) += board-omap3logic.o
|
||||||
obj-$(CONFIG_MACH_OMAP3_TORPEDO) += board-omap3logic.o
|
obj-$(CONFIG_MACH_OMAP3_TORPEDO) += board-omap3logic.o
|
||||||
obj-$(CONFIG_MACH_ENCORE) += board-omap3encore.o
|
obj-$(CONFIG_MACH_ENCORE) += board-omap3encore.o
|
||||||
obj-$(CONFIG_MACH_OVERO) += board-overo.o
|
obj-$(CONFIG_MACH_OVERO) += board-overo.o
|
||||||
obj-$(CONFIG_MACH_OMAP3EVM) += board-omap3evm.o
|
obj-$(CONFIG_MACH_OMAP3EVM) += board-omap3evm.o
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "clock2xxx.h"
|
#include "clock2xxx.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
#include "cm2xxx.h"
|
||||||
#include "cm-regbits-24xx.h"
|
#include "cm-regbits-24xx.h"
|
||||||
|
|
||||||
/* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
|
/* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
#include "cm2xxx.h"
|
||||||
#include "cm-regbits-24xx.h"
|
#include "cm-regbits-24xx.h"
|
||||||
|
|
||||||
/* Private functions */
|
/* Private functions */
|
||||||
|
|||||||
@@ -33,7 +33,8 @@
|
|||||||
#include "soc.h"
|
#include "soc.h"
|
||||||
#include "clockdomain.h"
|
#include "clockdomain.h"
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
#include "cm2xxx.h"
|
||||||
|
#include "cm3xxx.h"
|
||||||
#include "cm-regbits-24xx.h"
|
#include "cm-regbits-24xx.h"
|
||||||
#include "cm-regbits-34xx.h"
|
#include "cm-regbits-34xx.h"
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "clock2xxx.h"
|
#include "clock2xxx.h"
|
||||||
#include "opp2xxx.h"
|
#include "opp2xxx.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
#include "cm2xxx.h"
|
||||||
#include "prm2xxx_3xxx.h"
|
#include "prm2xxx_3xxx.h"
|
||||||
#include "prm-regbits-24xx.h"
|
#include "prm-regbits-24xx.h"
|
||||||
#include "cm-regbits-24xx.h"
|
#include "cm-regbits-24xx.h"
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#include "iomap.h"
|
#include "iomap.h"
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "clock2xxx.h"
|
#include "clock2xxx.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
#include "cm2xxx.h"
|
||||||
#include "cm-regbits-24xx.h"
|
#include "cm-regbits-24xx.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "clock2xxx.h"
|
#include "clock2xxx.h"
|
||||||
#include "opp2xxx.h"
|
#include "opp2xxx.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
#include "cm2xxx.h"
|
||||||
#include "prm2xxx_3xxx.h"
|
#include "prm2xxx_3xxx.h"
|
||||||
#include "prm-regbits-24xx.h"
|
#include "prm-regbits-24xx.h"
|
||||||
#include "cm-regbits-24xx.h"
|
#include "cm-regbits-24xx.h"
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "clock34xx.h"
|
#include "clock34xx.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
#include "cm3xxx.h"
|
||||||
#include "cm-regbits-34xx.h"
|
#include "cm-regbits-34xx.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "clock3517.h"
|
#include "clock3517.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
#include "cm3xxx.h"
|
||||||
#include "cm-regbits-34xx.h"
|
#include "cm-regbits-34xx.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
#include "clock34xx.h"
|
#include "clock34xx.h"
|
||||||
#include "clock36xx.h"
|
#include "clock36xx.h"
|
||||||
#include "clock3517.h"
|
#include "clock3517.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
#include "cm3xxx.h"
|
||||||
#include "cm-regbits-34xx.h"
|
#include "cm-regbits-34xx.h"
|
||||||
#include "prm2xxx_3xxx.h"
|
#include "prm2xxx_3xxx.h"
|
||||||
#include "prm-regbits-34xx.h"
|
#include "prm-regbits-34xx.h"
|
||||||
|
|||||||
@@ -1,341 +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 "soc.h"
|
|
||||||
#include "prm.h"
|
|
||||||
#include "prm2xxx_3xxx.h"
|
|
||||||
#include "cm.h"
|
|
||||||
#include "cm2xxx_3xxx.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 omap2_clkdm_clk_enable(struct clockdomain *clkdm)
|
|
||||||
{
|
|
||||||
bool hwsup = false;
|
|
||||||
|
|
||||||
if (!clkdm->clktrctrl_mask)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
hwsup = omap2_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 omap2_clkdm_clk_disable(struct clockdomain *clkdm)
|
|
||||||
{
|
|
||||||
bool hwsup = false;
|
|
||||||
|
|
||||||
if (!clkdm->clktrctrl_mask)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
hwsup = omap2_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 = omap2_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 = omap2_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 = omap2_clkdm_clk_enable,
|
|
||||||
.clkdm_clk_disable = omap2_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,
|
|
||||||
};
|
|
||||||
@@ -33,4 +33,16 @@
|
|||||||
*/
|
*/
|
||||||
#define MAX_MODULE_DISABLE_TIME 5000
|
#define MAX_MODULE_DISABLE_TIME 5000
|
||||||
|
|
||||||
|
# ifndef __ASSEMBLER__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cm_ll_data - fn ptrs to per-SoC CM function implementations
|
||||||
|
*/
|
||||||
|
struct cm_ll_data {};
|
||||||
|
|
||||||
|
extern int cm_register(struct cm_ll_data *cld);
|
||||||
|
extern int cm_unregister(struct cm_ll_data *cld);
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,255 @@
|
|||||||
|
/*
|
||||||
|
* OMAP2xxx CM module functions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Nokia Corporation
|
||||||
|
* 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
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
|
||||||
|
#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
|
||||||
|
#define OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP 0x3
|
||||||
|
|
||||||
|
/* CM_AUTOIDLE_PLL.AUTO_* bit values for APLLs (OMAP2xxx only) */
|
||||||
|
#define OMAP2XXX_APLL_AUTOIDLE_DISABLE 0x0
|
||||||
|
#define OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP 0x3
|
||||||
|
|
||||||
|
static const u8 omap2xxx_cm_idlest_offs[] = {
|
||||||
|
CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3, OMAP24XX_CM_IDLEST4
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void _write_clktrctrl(u8 c, s16 module, u32 mask)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
|
||||||
|
v &= ~mask;
|
||||||
|
v |= c << __ffs(mask);
|
||||||
|
omap2_cm_write_mod_reg(v, module, OMAP2_CM_CLKSTCTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool omap2xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
|
||||||
|
v &= mask;
|
||||||
|
v >>= __ffs(mask);
|
||||||
|
|
||||||
|
return (v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void omap2xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
|
||||||
|
{
|
||||||
|
_write_clktrctrl(OMAP24XX_CLKSTCTRL_ENABLE_AUTO, module, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void omap2xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask)
|
||||||
|
{
|
||||||
|
_write_clktrctrl(OMAP24XX_CLKSTCTRL_DISABLE_AUTO, module, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DPLL autoidle control
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void _omap2xxx_set_dpll_autoidle(u8 m)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
|
||||||
|
v &= ~OMAP24XX_AUTO_DPLL_MASK;
|
||||||
|
v |= m << OMAP24XX_AUTO_DPLL_SHIFT;
|
||||||
|
omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void omap2xxx_cm_set_dpll_disable_autoidle(void)
|
||||||
|
{
|
||||||
|
_omap2xxx_set_dpll_autoidle(OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void omap2xxx_cm_set_dpll_auto_low_power_stop(void)
|
||||||
|
{
|
||||||
|
_omap2xxx_set_dpll_autoidle(DPLL_AUTOIDLE_DISABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* APLL autoidle control
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void _omap2xxx_set_apll_autoidle(u8 m, u32 mask)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
|
||||||
|
v &= ~mask;
|
||||||
|
v |= m << __ffs(mask);
|
||||||
|
omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void omap2xxx_cm_set_apll54_disable_autoidle(void)
|
||||||
|
{
|
||||||
|
_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP,
|
||||||
|
OMAP24XX_AUTO_54M_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void omap2xxx_cm_set_apll54_auto_low_power_stop(void)
|
||||||
|
{
|
||||||
|
_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE,
|
||||||
|
OMAP24XX_AUTO_54M_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void omap2xxx_cm_set_apll96_disable_autoidle(void)
|
||||||
|
{
|
||||||
|
_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP,
|
||||||
|
OMAP24XX_AUTO_96M_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void omap2xxx_cm_set_apll96_auto_low_power_stop(void)
|
||||||
|
{
|
||||||
|
_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE,
|
||||||
|
OMAP24XX_AUTO_96M_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* omap2xxx_cm_wait_module_ready - wait for a module to leave idle or standby
|
||||||
|
* @prcm_mod: PRCM module offset
|
||||||
|
* @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
|
||||||
|
* @idlest_shift: shift of the bit in the CM_IDLEST* register to check
|
||||||
|
*
|
||||||
|
* Wait for the PRCM to indicate that the module identified by
|
||||||
|
* (@prcm_mod, @idlest_id, @idlest_shift) is clocked. Return 0 upon
|
||||||
|
* success or -EBUSY if the module doesn't enable in time.
|
||||||
|
*/
|
||||||
|
int omap2xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
|
||||||
|
{
|
||||||
|
int ena = 0, i = 0;
|
||||||
|
u8 cm_idlest_reg;
|
||||||
|
u32 mask;
|
||||||
|
|
||||||
|
if (!idlest_id || (idlest_id > ARRAY_SIZE(omap2xxx_cm_idlest_offs)))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
cm_idlest_reg = omap2xxx_cm_idlest_offs[idlest_id - 1];
|
||||||
|
|
||||||
|
mask = 1 << idlest_shift;
|
||||||
|
ena = mask;
|
||||||
|
|
||||||
|
omap_test_timeout(((omap2_cm_read_mod_reg(prcm_mod, cm_idlest_reg) &
|
||||||
|
mask) == ena), MAX_MODULE_READY_TIME, i);
|
||||||
|
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* OMAP2xxx Clock Management (CM) register definitions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2009, 2012 Texas Instruments, Inc.
|
||||||
|
* Copyright (C) 2007-2010 Nokia Corporation
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* The CM hardware modules on the OMAP2/3 are quite similar to each
|
||||||
|
* other. The CM modules/instances on OMAP4 are quite different, so
|
||||||
|
* they are handled in a separate file.
|
||||||
|
*/
|
||||||
|
#ifndef __ARCH_ASM_MACH_OMAP2_CM2XXX_H
|
||||||
|
#define __ARCH_ASM_MACH_OMAP2_CM2XXX_H
|
||||||
|
|
||||||
|
#include "prcm-common.h"
|
||||||
|
#include "cm2xxx_3xxx.h"
|
||||||
|
|
||||||
|
#define OMAP2420_CM_REGADDR(module, reg) \
|
||||||
|
OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE + (module) + (reg))
|
||||||
|
#define OMAP2430_CM_REGADDR(module, reg) \
|
||||||
|
OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE + (module) + (reg))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module specific CM register offsets from CM_BASE + domain offset
|
||||||
|
* Use cm_{read,write}_mod_reg() with these registers.
|
||||||
|
* These register offsets generally appear in more than one PRCM submodule.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* OMAP2-specific register offsets */
|
||||||
|
|
||||||
|
#define OMAP24XX_CM_FCLKEN2 0x0004
|
||||||
|
#define OMAP24XX_CM_ICLKEN4 0x001c
|
||||||
|
#define OMAP24XX_CM_AUTOIDLE4 0x003c
|
||||||
|
#define OMAP24XX_CM_IDLEST4 0x002c
|
||||||
|
|
||||||
|
/* CM_IDLEST bit field values to indicate deasserted IdleReq */
|
||||||
|
|
||||||
|
#define OMAP24XX_CM_IDLEST_VAL 0
|
||||||
|
|
||||||
|
|
||||||
|
/* Clock management domain register get/set */
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLER__
|
||||||
|
|
||||||
|
extern void omap2xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask);
|
||||||
|
extern void omap2xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask);
|
||||||
|
|
||||||
|
extern void omap2xxx_cm_set_dpll_disable_autoidle(void);
|
||||||
|
extern void omap2xxx_cm_set_dpll_auto_low_power_stop(void);
|
||||||
|
|
||||||
|
extern void omap2xxx_cm_set_apll54_disable_autoidle(void);
|
||||||
|
extern void omap2xxx_cm_set_apll54_auto_low_power_stop(void);
|
||||||
|
extern void omap2xxx_cm_set_apll96_disable_autoidle(void);
|
||||||
|
extern void omap2xxx_cm_set_apll96_auto_low_power_stop(void);
|
||||||
|
|
||||||
|
extern bool omap2xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask);
|
||||||
|
extern int omap2xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id,
|
||||||
|
u8 idlest_shift);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -18,27 +18,6 @@
|
|||||||
|
|
||||||
#include "prcm-common.h"
|
#include "prcm-common.h"
|
||||||
|
|
||||||
#define OMAP2420_CM_REGADDR(module, reg) \
|
|
||||||
OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE + (module) + (reg))
|
|
||||||
#define OMAP2430_CM_REGADDR(module, reg) \
|
|
||||||
OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE + (module) + (reg))
|
|
||||||
#define OMAP34XX_CM_REGADDR(module, reg) \
|
|
||||||
OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE + (module) + (reg))
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OMAP3-specific global CM registers
|
|
||||||
* Use cm_{read,write}_reg() with these registers.
|
|
||||||
* These registers appear once per CM module.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define OMAP3430_CM_REVISION OMAP34XX_CM_REGADDR(OCP_MOD, 0x0000)
|
|
||||||
#define OMAP3430_CM_SYSCONFIG OMAP34XX_CM_REGADDR(OCP_MOD, 0x0010)
|
|
||||||
#define OMAP3430_CM_POLCTRL OMAP34XX_CM_REGADDR(OCP_MOD, 0x009c)
|
|
||||||
|
|
||||||
#define OMAP3_CM_CLKOUT_CTRL_OFFSET 0x0070
|
|
||||||
#define OMAP3430_CM_CLKOUT_CTRL OMAP_CM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Module specific CM register offsets from CM_BASE + domain offset
|
* Module specific CM register offsets from CM_BASE + domain offset
|
||||||
* Use cm_{read,write}_mod_reg() with these registers.
|
* Use cm_{read,write}_mod_reg() with these registers.
|
||||||
@@ -57,6 +36,7 @@
|
|||||||
#define CM_IDLEST 0x0020
|
#define CM_IDLEST 0x0020
|
||||||
#define CM_IDLEST1 CM_IDLEST
|
#define CM_IDLEST1 CM_IDLEST
|
||||||
#define CM_IDLEST2 0x0024
|
#define CM_IDLEST2 0x0024
|
||||||
|
#define OMAP2430_CM_IDLEST3 0x0028
|
||||||
#define CM_AUTOIDLE 0x0030
|
#define CM_AUTOIDLE 0x0030
|
||||||
#define CM_AUTOIDLE1 CM_AUTOIDLE
|
#define CM_AUTOIDLE1 CM_AUTOIDLE
|
||||||
#define CM_AUTOIDLE2 0x0034
|
#define CM_AUTOIDLE2 0x0034
|
||||||
@@ -66,70 +46,55 @@
|
|||||||
#define CM_CLKSEL2 0x0044
|
#define CM_CLKSEL2 0x0044
|
||||||
#define OMAP2_CM_CLKSTCTRL 0x0048
|
#define OMAP2_CM_CLKSTCTRL 0x0048
|
||||||
|
|
||||||
/* OMAP2-specific register offsets */
|
|
||||||
|
|
||||||
#define OMAP24XX_CM_FCLKEN2 0x0004
|
|
||||||
#define OMAP24XX_CM_ICLKEN4 0x001c
|
|
||||||
#define OMAP24XX_CM_AUTOIDLE4 0x003c
|
|
||||||
#define OMAP24XX_CM_IDLEST4 0x002c
|
|
||||||
|
|
||||||
#define OMAP2430_CM_IDLEST3 0x0028
|
|
||||||
|
|
||||||
/* OMAP3-specific register offsets */
|
|
||||||
|
|
||||||
#define OMAP3430_CM_CLKEN_PLL 0x0004
|
|
||||||
#define OMAP3430ES2_CM_CLKEN2 0x0004
|
|
||||||
#define OMAP3430ES2_CM_FCLKEN3 0x0008
|
|
||||||
#define OMAP3430_CM_IDLEST_PLL CM_IDLEST2
|
|
||||||
#define OMAP3430_CM_AUTOIDLE_PLL CM_AUTOIDLE2
|
|
||||||
#define OMAP3430ES2_CM_AUTOIDLE2_PLL CM_AUTOIDLE2
|
|
||||||
#define OMAP3430_CM_CLKSEL1 CM_CLKSEL
|
|
||||||
#define OMAP3430_CM_CLKSEL1_PLL CM_CLKSEL
|
|
||||||
#define OMAP3430_CM_CLKSEL2_PLL CM_CLKSEL2
|
|
||||||
#define OMAP3430_CM_SLEEPDEP CM_CLKSEL2
|
|
||||||
#define OMAP3430_CM_CLKSEL3 OMAP2_CM_CLKSTCTRL
|
|
||||||
#define OMAP3430_CM_CLKSTST 0x004c
|
|
||||||
#define OMAP3430ES2_CM_CLKSEL4 0x004c
|
|
||||||
#define OMAP3430ES2_CM_CLKSEL5 0x0050
|
|
||||||
#define OMAP3430_CM_CLKSEL2_EMU 0x0050
|
|
||||||
#define OMAP3430_CM_CLKSEL3_EMU 0x0054
|
|
||||||
|
|
||||||
|
|
||||||
/* CM_IDLEST bit field values to indicate deasserted IdleReq */
|
|
||||||
|
|
||||||
#define OMAP24XX_CM_IDLEST_VAL 0
|
|
||||||
#define OMAP34XX_CM_IDLEST_VAL 1
|
|
||||||
|
|
||||||
|
|
||||||
/* Clock management domain register get/set */
|
|
||||||
|
|
||||||
#ifndef __ASSEMBLER__
|
#ifndef __ASSEMBLER__
|
||||||
|
|
||||||
extern u32 omap2_cm_read_mod_reg(s16 module, u16 idx);
|
#include <linux/io.h>
|
||||||
extern void omap2_cm_write_mod_reg(u32 val, s16 module, u16 idx);
|
|
||||||
extern u32 omap2_cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
|
|
||||||
|
|
||||||
extern int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id,
|
static inline u32 omap2_cm_read_mod_reg(s16 module, u16 idx)
|
||||||
u8 idlest_shift);
|
{
|
||||||
extern u32 omap2_cm_set_mod_reg_bits(u32 bits, s16 module, s16 idx);
|
return __raw_readl(cm_base + module + idx);
|
||||||
extern u32 omap2_cm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx);
|
}
|
||||||
|
|
||||||
extern bool omap2_cm_is_clkdm_in_hwsup(s16 module, u32 mask);
|
static inline void omap2_cm_write_mod_reg(u32 val, s16 module, u16 idx)
|
||||||
extern void omap2xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask);
|
{
|
||||||
extern void omap2xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask);
|
__raw_writel(val, cm_base + module + idx);
|
||||||
|
}
|
||||||
|
|
||||||
extern void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask);
|
/* Read-modify-write a register in a CM module. Caller must lock */
|
||||||
extern void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask);
|
static inline u32 omap2_cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module,
|
||||||
extern void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask);
|
s16 idx)
|
||||||
extern void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask);
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
extern void omap2xxx_cm_set_dpll_disable_autoidle(void);
|
v = omap2_cm_read_mod_reg(module, idx);
|
||||||
extern void omap2xxx_cm_set_dpll_auto_low_power_stop(void);
|
v &= ~mask;
|
||||||
|
v |= bits;
|
||||||
|
omap2_cm_write_mod_reg(v, module, idx);
|
||||||
|
|
||||||
extern void omap2xxx_cm_set_apll54_disable_autoidle(void);
|
return v;
|
||||||
extern void omap2xxx_cm_set_apll54_auto_low_power_stop(void);
|
}
|
||||||
extern void omap2xxx_cm_set_apll96_disable_autoidle(void);
|
|
||||||
extern void omap2xxx_cm_set_apll96_auto_low_power_stop(void);
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 omap2_cm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
|
||||||
|
{
|
||||||
|
return omap2_cm_rmw_mod_reg_bits(bits, 0x0, module, idx);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -147,10 +112,4 @@ extern void omap2xxx_cm_set_apll96_auto_low_power_stop(void);
|
|||||||
#define OMAP_ST_GFX_MASK (1 << 0)
|
#define OMAP_ST_GFX_MASK (1 << 0)
|
||||||
|
|
||||||
|
|
||||||
/* Function prototypes */
|
|
||||||
# ifndef __ASSEMBLER__
|
|
||||||
extern void omap3_cm_save_context(void);
|
|
||||||
extern void omap3_cm_restore_context(void);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "../plat-omap/common.h"
|
#include "../plat-omap/common.h"
|
||||||
|
|
||||||
|
#include "clockdomain.h"
|
||||||
#include "cm.h"
|
#include "cm.h"
|
||||||
#include "cm33xx.h"
|
#include "cm33xx.h"
|
||||||
#include "cm-regbits-34xx.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;
|
v &= ~AM33XX_MODULEMODE_MASK;
|
||||||
am33xx_cm_write_reg(v, inst, clkctrl_offs);
|
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,8 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* OMAP2/3 CM module functions
|
* OMAP3xxx CM module functions
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009 Nokia Corporation
|
* Copyright (C) 2009 Nokia Corporation
|
||||||
|
* 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
|
||||||
@@ -12,8 +14,6 @@
|
|||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/spinlock.h>
|
|
||||||
#include <linux/list.h>
|
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
@@ -21,56 +21,16 @@
|
|||||||
#include "soc.h"
|
#include "soc.h"
|
||||||
#include "iomap.h"
|
#include "iomap.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "prm2xxx_3xxx.h"
|
||||||
#include "cm.h"
|
#include "cm.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
#include "cm3xxx.h"
|
||||||
#include "cm-regbits-24xx.h"
|
|
||||||
#include "cm-regbits-34xx.h"
|
#include "cm-regbits-34xx.h"
|
||||||
|
#include "clockdomain.h"
|
||||||
|
|
||||||
/* CM_AUTOIDLE_PLL.AUTO_* bit values for DPLLs */
|
static const u8 omap3xxx_cm_idlest_offs[] = {
|
||||||
#define DPLL_AUTOIDLE_DISABLE 0x0
|
CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3
|
||||||
#define OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP 0x3
|
|
||||||
|
|
||||||
/* CM_AUTOIDLE_PLL.AUTO_* bit values for APLLs (OMAP2xxx only) */
|
|
||||||
#define OMAP2XXX_APLL_AUTOIDLE_DISABLE 0x0
|
|
||||||
#define OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP 0x3
|
|
||||||
|
|
||||||
static const u8 cm_idlest_offs[] = {
|
|
||||||
CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3, OMAP24XX_CM_IDLEST4
|
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 omap2_cm_read_mod_reg(s16 module, u16 idx)
|
|
||||||
{
|
|
||||||
return __raw_readl(cm_base + module + idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void omap2_cm_write_mod_reg(u32 val, s16 module, u16 idx)
|
|
||||||
{
|
|
||||||
__raw_writel(val, cm_base + module + idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read-modify-write a register in a CM module. Caller must lock */
|
|
||||||
u32 omap2_cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
|
|
||||||
{
|
|
||||||
u32 v;
|
|
||||||
|
|
||||||
v = omap2_cm_read_mod_reg(module, idx);
|
|
||||||
v &= ~mask;
|
|
||||||
v |= bits;
|
|
||||||
omap2_cm_write_mod_reg(v, module, idx);
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 omap2_cm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
|
|
||||||
{
|
|
||||||
return omap2_cm_rmw_mod_reg_bits(bits, bits, module, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 omap2_cm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
|
|
||||||
{
|
|
||||||
return omap2_cm_rmw_mod_reg_bits(bits, 0x0, module, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -85,33 +45,15 @@ static void _write_clktrctrl(u8 c, s16 module, u32 mask)
|
|||||||
omap2_cm_write_mod_reg(v, module, OMAP2_CM_CLKSTCTRL);
|
omap2_cm_write_mod_reg(v, module, OMAP2_CM_CLKSTCTRL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool omap2_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
|
bool omap3xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask)
|
||||||
{
|
{
|
||||||
u32 v;
|
u32 v;
|
||||||
bool ret = 0;
|
|
||||||
|
|
||||||
BUG_ON(!cpu_is_omap24xx() && !cpu_is_omap34xx());
|
|
||||||
|
|
||||||
v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
|
v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);
|
||||||
v &= mask;
|
v &= mask;
|
||||||
v >>= __ffs(mask);
|
v >>= __ffs(mask);
|
||||||
|
|
||||||
if (cpu_is_omap24xx())
|
return (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;
|
||||||
ret = (v == OMAP24XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;
|
|
||||||
else
|
|
||||||
ret = (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void omap2xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
|
|
||||||
{
|
|
||||||
_write_clktrctrl(OMAP24XX_CLKSTCTRL_ENABLE_AUTO, module, mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
void omap2xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask)
|
|
||||||
{
|
|
||||||
_write_clktrctrl(OMAP24XX_CLKSTCTRL_DISABLE_AUTO, module, mask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
|
void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask)
|
||||||
@@ -134,110 +76,210 @@ void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask)
|
|||||||
_write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, module, mask);
|
_write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, module, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* DPLL autoidle control
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void _omap2xxx_set_dpll_autoidle(u8 m)
|
|
||||||
{
|
|
||||||
u32 v;
|
|
||||||
|
|
||||||
v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
|
|
||||||
v &= ~OMAP24XX_AUTO_DPLL_MASK;
|
|
||||||
v |= m << OMAP24XX_AUTO_DPLL_SHIFT;
|
|
||||||
omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void omap2xxx_cm_set_dpll_disable_autoidle(void)
|
|
||||||
{
|
|
||||||
_omap2xxx_set_dpll_autoidle(OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP);
|
|
||||||
}
|
|
||||||
|
|
||||||
void omap2xxx_cm_set_dpll_auto_low_power_stop(void)
|
|
||||||
{
|
|
||||||
_omap2xxx_set_dpll_autoidle(DPLL_AUTOIDLE_DISABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* APLL autoidle control
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void _omap2xxx_set_apll_autoidle(u8 m, u32 mask)
|
|
||||||
{
|
|
||||||
u32 v;
|
|
||||||
|
|
||||||
v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
|
|
||||||
v &= ~mask;
|
|
||||||
v |= m << __ffs(mask);
|
|
||||||
omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void omap2xxx_cm_set_apll54_disable_autoidle(void)
|
|
||||||
{
|
|
||||||
_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP,
|
|
||||||
OMAP24XX_AUTO_54M_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
void omap2xxx_cm_set_apll54_auto_low_power_stop(void)
|
|
||||||
{
|
|
||||||
_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE,
|
|
||||||
OMAP24XX_AUTO_54M_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
void omap2xxx_cm_set_apll96_disable_autoidle(void)
|
|
||||||
{
|
|
||||||
_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP,
|
|
||||||
OMAP24XX_AUTO_96M_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
void omap2xxx_cm_set_apll96_auto_low_power_stop(void)
|
|
||||||
{
|
|
||||||
_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE,
|
|
||||||
OMAP24XX_AUTO_96M_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* omap2_cm_wait_idlest_ready - wait for a module to leave idle or standby
|
* omap3xxx_cm_wait_module_ready - wait for a module to leave idle or standby
|
||||||
* @prcm_mod: PRCM module offset
|
* @prcm_mod: PRCM module offset
|
||||||
* @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
|
* @idlest_id: CM_IDLESTx register ID (i.e., x = 1, 2, 3)
|
||||||
* @idlest_shift: shift of the bit in the CM_IDLEST* register to check
|
* @idlest_shift: shift of the bit in the CM_IDLEST* register to check
|
||||||
*
|
*
|
||||||
* XXX document
|
* Wait for the PRCM to indicate that the module identified by
|
||||||
|
* (@prcm_mod, @idlest_id, @idlest_shift) is clocked. Return 0 upon
|
||||||
|
* success or -EBUSY if the module doesn't enable in time.
|
||||||
*/
|
*/
|
||||||
int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
|
int omap3xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)
|
||||||
{
|
{
|
||||||
int ena = 0, i = 0;
|
int ena = 0, i = 0;
|
||||||
u8 cm_idlest_reg;
|
u8 cm_idlest_reg;
|
||||||
u32 mask;
|
u32 mask;
|
||||||
|
|
||||||
if (!idlest_id || (idlest_id > ARRAY_SIZE(cm_idlest_offs)))
|
if (!idlest_id || (idlest_id > ARRAY_SIZE(omap3xxx_cm_idlest_offs)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
cm_idlest_reg = cm_idlest_offs[idlest_id - 1];
|
cm_idlest_reg = omap3xxx_cm_idlest_offs[idlest_id - 1];
|
||||||
|
|
||||||
mask = 1 << idlest_shift;
|
mask = 1 << idlest_shift;
|
||||||
|
ena = 0;
|
||||||
|
|
||||||
if (cpu_is_omap24xx())
|
omap_test_timeout(((omap2_cm_read_mod_reg(prcm_mod, cm_idlest_reg) &
|
||||||
ena = mask;
|
mask) == ena), MAX_MODULE_READY_TIME, i);
|
||||||
else if (cpu_is_omap34xx())
|
|
||||||
ena = 0;
|
|
||||||
else
|
|
||||||
BUG();
|
|
||||||
|
|
||||||
omap_test_timeout(((omap2_cm_read_mod_reg(prcm_mod, cm_idlest_reg) & mask) == ena),
|
|
||||||
MAX_MODULE_READY_TIME, i);
|
|
||||||
|
|
||||||
return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
|
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
|
* Context save/restore code - OMAP3 only
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_ARCH_OMAP3
|
|
||||||
struct omap3_cm_regs {
|
struct omap3_cm_regs {
|
||||||
u32 iva2_cm_clksel1;
|
u32 iva2_cm_clksel1;
|
||||||
u32 iva2_cm_clksel2;
|
u32 iva2_cm_clksel2;
|
||||||
@@ -555,4 +597,3 @@ void omap3_cm_restore_context(void)
|
|||||||
omap2_cm_write_mod_reg(cm_context.cm_clkout_ctrl, OMAP3430_CCR_MOD,
|
omap2_cm_write_mod_reg(cm_context.cm_clkout_ctrl, OMAP3430_CCR_MOD,
|
||||||
OMAP3_CM_CLKOUT_CTRL_OFFSET);
|
OMAP3_CM_CLKOUT_CTRL_OFFSET);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* OMAP2/3 Clock Management (CM) register definitions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2009 Texas Instruments, Inc.
|
||||||
|
* Copyright (C) 2007-2010 Nokia Corporation
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* The CM hardware modules on the OMAP2/3 are quite similar to each
|
||||||
|
* other. The CM modules/instances on OMAP4 are quite different, so
|
||||||
|
* they are handled in a separate file.
|
||||||
|
*/
|
||||||
|
#ifndef __ARCH_ASM_MACH_OMAP2_CM3XXX_H
|
||||||
|
#define __ARCH_ASM_MACH_OMAP2_CM3XXX_H
|
||||||
|
|
||||||
|
#include "prcm-common.h"
|
||||||
|
#include "cm2xxx_3xxx.h"
|
||||||
|
|
||||||
|
#define OMAP34XX_CM_REGADDR(module, reg) \
|
||||||
|
OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE + (module) + (reg))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OMAP3-specific global CM registers
|
||||||
|
* Use cm_{read,write}_reg() with these registers.
|
||||||
|
* These registers appear once per CM module.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define OMAP3430_CM_REVISION OMAP34XX_CM_REGADDR(OCP_MOD, 0x0000)
|
||||||
|
#define OMAP3430_CM_SYSCONFIG OMAP34XX_CM_REGADDR(OCP_MOD, 0x0010)
|
||||||
|
#define OMAP3430_CM_POLCTRL OMAP34XX_CM_REGADDR(OCP_MOD, 0x009c)
|
||||||
|
|
||||||
|
#define OMAP3_CM_CLKOUT_CTRL_OFFSET 0x0070
|
||||||
|
#define OMAP3430_CM_CLKOUT_CTRL OMAP_CM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module specific CM register offsets from CM_BASE + domain offset
|
||||||
|
* Use cm_{read,write}_mod_reg() with these registers.
|
||||||
|
* These register offsets generally appear in more than one PRCM submodule.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* OMAP3-specific register offsets */
|
||||||
|
|
||||||
|
#define OMAP3430_CM_CLKEN_PLL 0x0004
|
||||||
|
#define OMAP3430ES2_CM_CLKEN2 0x0004
|
||||||
|
#define OMAP3430ES2_CM_FCLKEN3 0x0008
|
||||||
|
#define OMAP3430_CM_IDLEST_PLL CM_IDLEST2
|
||||||
|
#define OMAP3430_CM_AUTOIDLE_PLL CM_AUTOIDLE2
|
||||||
|
#define OMAP3430ES2_CM_AUTOIDLE2_PLL CM_AUTOIDLE2
|
||||||
|
#define OMAP3430_CM_CLKSEL1 CM_CLKSEL
|
||||||
|
#define OMAP3430_CM_CLKSEL1_PLL CM_CLKSEL
|
||||||
|
#define OMAP3430_CM_CLKSEL2_PLL CM_CLKSEL2
|
||||||
|
#define OMAP3430_CM_SLEEPDEP CM_CLKSEL2
|
||||||
|
#define OMAP3430_CM_CLKSEL3 OMAP2_CM_CLKSTCTRL
|
||||||
|
#define OMAP3430_CM_CLKSTST 0x004c
|
||||||
|
#define OMAP3430ES2_CM_CLKSEL4 0x004c
|
||||||
|
#define OMAP3430ES2_CM_CLKSEL5 0x0050
|
||||||
|
#define OMAP3430_CM_CLKSEL2_EMU 0x0050
|
||||||
|
#define OMAP3430_CM_CLKSEL3_EMU 0x0054
|
||||||
|
|
||||||
|
|
||||||
|
/* CM_IDLEST bit field values to indicate deasserted IdleReq */
|
||||||
|
|
||||||
|
#define OMAP34XX_CM_IDLEST_VAL 1
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLER__
|
||||||
|
|
||||||
|
extern void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask);
|
||||||
|
extern void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask);
|
||||||
|
extern void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask);
|
||||||
|
extern void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask);
|
||||||
|
|
||||||
|
extern bool omap3xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask);
|
||||||
|
extern int omap3xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id,
|
||||||
|
u8 idlest_shift);
|
||||||
|
|
||||||
|
extern void omap3_cm_save_context(void);
|
||||||
|
extern void omap3_cm_restore_context(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* OMAP2+ common Clock Management (CM) IP block functions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Texas Instruments, Inc.
|
||||||
|
* Paul Walmsley <paul@pwsan.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.
|
||||||
|
*
|
||||||
|
* XXX This code should eventually be moved to a CM driver.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
|
||||||
|
#include "cm2xxx.h"
|
||||||
|
#include "cm3xxx.h"
|
||||||
|
#include "cm44xx.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cm_ll_data: function pointers to SoC-specific implementations of
|
||||||
|
* common CM functions
|
||||||
|
*/
|
||||||
|
static struct cm_ll_data null_cm_ll_data;
|
||||||
|
static struct cm_ll_data *cm_ll_data = &null_cm_ll_data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cm_register - register per-SoC low-level data with the CM
|
||||||
|
* @cld: low-level per-SoC OMAP CM data & function pointers to register
|
||||||
|
*
|
||||||
|
* Register per-SoC low-level OMAP CM data and function pointers with
|
||||||
|
* the OMAP CM common interface. The caller must keep the data
|
||||||
|
* pointed to by @cld valid until it calls cm_unregister() and
|
||||||
|
* it returns successfully. Returns 0 upon success, -EINVAL if @cld
|
||||||
|
* is NULL, or -EEXIST if cm_register() has already been called
|
||||||
|
* without an intervening cm_unregister().
|
||||||
|
*/
|
||||||
|
int cm_register(struct cm_ll_data *cld)
|
||||||
|
{
|
||||||
|
if (!cld)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (cm_ll_data != &null_cm_ll_data)
|
||||||
|
return -EEXIST;
|
||||||
|
|
||||||
|
cm_ll_data = cld;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cm_unregister - unregister per-SoC low-level data & function pointers
|
||||||
|
* @cld: low-level per-SoC OMAP CM data & function pointers to unregister
|
||||||
|
*
|
||||||
|
* Unregister per-SoC low-level OMAP CM data and function pointers
|
||||||
|
* that were previously registered with cm_register(). The
|
||||||
|
* caller may not destroy any of the data pointed to by @cld until
|
||||||
|
* this function returns successfully. Returns 0 upon success, or
|
||||||
|
* -EINVAL if @cld is NULL or if @cld does not match the struct
|
||||||
|
* cm_ll_data * previously registered by cm_register().
|
||||||
|
*/
|
||||||
|
int cm_unregister(struct cm_ll_data *cld)
|
||||||
|
{
|
||||||
|
if (!cld || cm_ll_data != cld)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
cm_ll_data = &null_cm_ll_data;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -2,8 +2,9 @@
|
|||||||
* OMAP4 CM instance functions
|
* OMAP4 CM instance functions
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009 Nokia Corporation
|
* Copyright (C) 2009 Nokia Corporation
|
||||||
* Copyright (C) 2011 Texas Instruments, Inc.
|
* Copyright (C) 2008-2011 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
|
||||||
@@ -22,6 +23,7 @@
|
|||||||
|
|
||||||
#include "iomap.h"
|
#include "iomap.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "clockdomain.h"
|
||||||
#include "cm.h"
|
#include "cm.h"
|
||||||
#include "cm1_44xx.h"
|
#include "cm1_44xx.h"
|
||||||
#include "cm2_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;
|
v &= ~OMAP4430_MODULEMODE_MASK;
|
||||||
omap4_cminst_write_inst_reg(v, part, inst, clkctrl_offs);
|
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,
|
||||||
|
};
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "cm-regbits-34xx.h"
|
#include "cm-regbits-34xx.h"
|
||||||
#include "prm-regbits-34xx.h"
|
#include "prm-regbits-34xx.h"
|
||||||
#include "prm2xxx_3xxx.h"
|
#include "prm3xxx.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
#include "cm3xxx.h"
|
||||||
#include "sdrc.h"
|
#include "sdrc.h"
|
||||||
#include "pm.h"
|
#include "pm.h"
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
|
|||||||
@@ -147,10 +147,11 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "clockdomain.h"
|
#include "clockdomain.h"
|
||||||
#include "powerdomain.h"
|
#include "powerdomain.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
#include "cm2xxx.h"
|
||||||
|
#include "cm3xxx.h"
|
||||||
#include "cminst44xx.h"
|
#include "cminst44xx.h"
|
||||||
#include "cm33xx.h"
|
#include "cm33xx.h"
|
||||||
#include "prm2xxx_3xxx.h"
|
#include "prm3xxx.h"
|
||||||
#include "prm44xx.h"
|
#include "prm44xx.h"
|
||||||
#include "prm33xx.h"
|
#include "prm33xx.h"
|
||||||
#include "prminst44xx.h"
|
#include "prminst44xx.h"
|
||||||
@@ -2668,7 +2669,7 @@ static int __init _alloc_linkspace(struct omap_hwmod_ocp_if **ois)
|
|||||||
/* Static functions intended only for use in soc_ops field function pointers */
|
/* Static functions intended only for use in soc_ops field function pointers */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _omap2_wait_target_ready - wait for a module to leave slave idle
|
* _omap2xxx_wait_target_ready - wait for a module to leave slave idle
|
||||||
* @oh: struct omap_hwmod *
|
* @oh: struct omap_hwmod *
|
||||||
*
|
*
|
||||||
* Wait for a module @oh to leave slave idle. Returns 0 if the module
|
* Wait for a module @oh to leave slave idle. Returns 0 if the module
|
||||||
@@ -2676,7 +2677,7 @@ static int __init _alloc_linkspace(struct omap_hwmod_ocp_if **ois)
|
|||||||
* slave idle; otherwise, pass along the return value of the
|
* slave idle; otherwise, pass along the return value of the
|
||||||
* appropriate *_cm*_wait_module_ready() function.
|
* appropriate *_cm*_wait_module_ready() function.
|
||||||
*/
|
*/
|
||||||
static int _omap2_wait_target_ready(struct omap_hwmod *oh)
|
static int _omap2xxx_wait_target_ready(struct omap_hwmod *oh)
|
||||||
{
|
{
|
||||||
if (!oh)
|
if (!oh)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -2689,9 +2690,36 @@ static int _omap2_wait_target_ready(struct omap_hwmod *oh)
|
|||||||
|
|
||||||
/* XXX check module SIDLEMODE, hardreset status, enabled clocks */
|
/* XXX check module SIDLEMODE, hardreset status, enabled clocks */
|
||||||
|
|
||||||
return omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs,
|
return omap2xxx_cm_wait_module_ready(oh->prcm.omap2.module_offs,
|
||||||
oh->prcm.omap2.idlest_reg_id,
|
oh->prcm.omap2.idlest_reg_id,
|
||||||
oh->prcm.omap2.idlest_idle_bit);
|
oh->prcm.omap2.idlest_idle_bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _omap3xxx_wait_target_ready - wait for a module to leave slave idle
|
||||||
|
* @oh: struct omap_hwmod *
|
||||||
|
*
|
||||||
|
* Wait for a module @oh to leave slave idle. Returns 0 if the module
|
||||||
|
* does not have an IDLEST bit or if the module successfully leaves
|
||||||
|
* slave idle; otherwise, pass along the return value of the
|
||||||
|
* appropriate *_cm*_wait_module_ready() function.
|
||||||
|
*/
|
||||||
|
static int _omap3xxx_wait_target_ready(struct omap_hwmod *oh)
|
||||||
|
{
|
||||||
|
if (!oh)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (oh->flags & HWMOD_NO_IDLEST)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!_find_mpu_rt_port(oh))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* XXX check module SIDLEMODE, hardreset status, enabled clocks */
|
||||||
|
|
||||||
|
return omap3xxx_cm_wait_module_ready(oh->prcm.omap2.module_offs,
|
||||||
|
oh->prcm.omap2.idlest_reg_id,
|
||||||
|
oh->prcm.omap2.idlest_idle_bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -3959,8 +3987,13 @@ int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx)
|
|||||||
*/
|
*/
|
||||||
void __init omap_hwmod_init(void)
|
void __init omap_hwmod_init(void)
|
||||||
{
|
{
|
||||||
if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
|
if (cpu_is_omap24xx()) {
|
||||||
soc_ops.wait_target_ready = _omap2_wait_target_ready;
|
soc_ops.wait_target_ready = _omap2xxx_wait_target_ready;
|
||||||
|
soc_ops.assert_hardreset = _omap2_assert_hardreset;
|
||||||
|
soc_ops.deassert_hardreset = _omap2_deassert_hardreset;
|
||||||
|
soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted;
|
||||||
|
} else if (cpu_is_omap34xx()) {
|
||||||
|
soc_ops.wait_target_ready = _omap3xxx_wait_target_ready;
|
||||||
soc_ops.assert_hardreset = _omap2_assert_hardreset;
|
soc_ops.assert_hardreset = _omap2_assert_hardreset;
|
||||||
soc_ops.deassert_hardreset = _omap2_deassert_hardreset;
|
soc_ops.deassert_hardreset = _omap2_deassert_hardreset;
|
||||||
soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted;
|
soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted;
|
||||||
|
|||||||
@@ -43,9 +43,9 @@
|
|||||||
#include "soc.h"
|
#include "soc.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "prm2xxx_3xxx.h"
|
#include "prm2xxx.h"
|
||||||
#include "prm-regbits-24xx.h"
|
#include "prm-regbits-24xx.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
#include "cm2xxx.h"
|
||||||
#include "cm-regbits-24xx.h"
|
#include "cm-regbits-24xx.h"
|
||||||
#include "sdrc.h"
|
#include "sdrc.h"
|
||||||
#include "pm.h"
|
#include "pm.h"
|
||||||
|
|||||||
@@ -44,12 +44,11 @@
|
|||||||
|
|
||||||
#include "soc.h"
|
#include "soc.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
#include "cm3xxx.h"
|
||||||
#include "cm-regbits-34xx.h"
|
#include "cm-regbits-34xx.h"
|
||||||
#include "gpmc.h"
|
#include "gpmc.h"
|
||||||
#include "prm-regbits-34xx.h"
|
#include "prm-regbits-34xx.h"
|
||||||
|
#include "prm3xxx.h"
|
||||||
#include "prm2xxx_3xxx.h"
|
|
||||||
#include "pm.h"
|
#include "pm.h"
|
||||||
#include "sdrc.h"
|
#include "sdrc.h"
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
|
|||||||
@@ -1,242 +0,0 @@
|
|||||||
/*
|
|
||||||
* OMAP2 and OMAP3 powerdomain control
|
|
||||||
*
|
|
||||||
* Copyright (C) 2009-2011 Texas Instruments, Inc.
|
|
||||||
* Copyright (C) 2007-2009 Nokia Corporation
|
|
||||||
*
|
|
||||||
* Derived from mach-omap2/powerdomain.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/io.h>
|
|
||||||
#include <linux/errno.h>
|
|
||||||
#include <linux/delay.h>
|
|
||||||
#include <linux/bug.h>
|
|
||||||
|
|
||||||
#include <plat/prcm.h>
|
|
||||||
|
|
||||||
#include "powerdomain.h"
|
|
||||||
#include "prm.h"
|
|
||||||
#include "prm-regbits-24xx.h"
|
|
||||||
#include "prm-regbits-34xx.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* Common functions across OMAP2 and OMAP3 */
|
|
||||||
static int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
|
|
||||||
{
|
|
||||||
omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
|
|
||||||
(pwrst << OMAP_POWERSTATE_SHIFT),
|
|
||||||
pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
|
||||||
OMAP2_PM_PWSTCTRL,
|
|
||||||
OMAP_POWERSTATE_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
|
||||||
OMAP2_PM_PWSTST,
|
|
||||||
OMAP_POWERSTATEST_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
|
|
||||||
u8 pwrst)
|
|
||||||
{
|
|
||||||
u32 m;
|
|
||||||
|
|
||||||
m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
|
|
||||||
|
|
||||||
omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
|
|
||||||
OMAP2_PM_PWSTCTRL);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap2_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
|
|
||||||
u8 pwrst)
|
|
||||||
{
|
|
||||||
u32 m;
|
|
||||||
|
|
||||||
m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
|
|
||||||
|
|
||||||
omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
|
|
||||||
OMAP2_PM_PWSTCTRL);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap2_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
|
|
||||||
{
|
|
||||||
u32 m;
|
|
||||||
|
|
||||||
m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
|
|
||||||
|
|
||||||
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP2_PM_PWSTST,
|
|
||||||
m);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap2_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
|
|
||||||
{
|
|
||||||
u32 m;
|
|
||||||
|
|
||||||
m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
|
|
||||||
|
|
||||||
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
|
||||||
OMAP2_PM_PWSTCTRL, m);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
|
|
||||||
{
|
|
||||||
u32 v;
|
|
||||||
|
|
||||||
v = pwrst << __ffs(OMAP3430_LOGICL1CACHERETSTATE_MASK);
|
|
||||||
omap2_prm_rmw_mod_reg_bits(OMAP3430_LOGICL1CACHERETSTATE_MASK, v,
|
|
||||||
pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap2_pwrdm_wait_transition(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
u32 c = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* REVISIT: pwrdm_wait_transition() may be better implemented
|
|
||||||
* via a callback and a periodic timer check -- how long do we expect
|
|
||||||
* powerdomain transitions to take?
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* XXX Is this udelay() value meaningful? */
|
|
||||||
while ((omap2_prm_read_mod_reg(pwrdm->prcm_offs, OMAP2_PM_PWSTST) &
|
|
||||||
OMAP_INTRANSITION_MASK) &&
|
|
||||||
(c++ < PWRDM_TRANSITION_BAILOUT))
|
|
||||||
udelay(1);
|
|
||||||
|
|
||||||
if (c > PWRDM_TRANSITION_BAILOUT) {
|
|
||||||
pr_err("powerdomain: %s: waited too long to complete transition\n",
|
|
||||||
pwrdm->name);
|
|
||||||
return -EAGAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("powerdomain: completed transition in %d loops\n", c);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Applicable only for OMAP3. Not supported on OMAP2 */
|
|
||||||
static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
|
||||||
OMAP3430_PM_PREPWSTST,
|
|
||||||
OMAP3430_LASTPOWERSTATEENTERED_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap3_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
|
||||||
OMAP2_PM_PWSTST,
|
|
||||||
OMAP3430_LOGICSTATEST_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap3_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
|
||||||
OMAP2_PM_PWSTCTRL,
|
|
||||||
OMAP3430_LOGICSTATEST_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap3_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
|
||||||
OMAP3430_PM_PREPWSTST,
|
|
||||||
OMAP3430_LASTLOGICSTATEENTERED_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap3_get_mem_bank_lastmemst_mask(u8 bank)
|
|
||||||
{
|
|
||||||
switch (bank) {
|
|
||||||
case 0:
|
|
||||||
return OMAP3430_LASTMEM1STATEENTERED_MASK;
|
|
||||||
case 1:
|
|
||||||
return OMAP3430_LASTMEM2STATEENTERED_MASK;
|
|
||||||
case 2:
|
|
||||||
return OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
|
|
||||||
case 3:
|
|
||||||
return OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
|
|
||||||
default:
|
|
||||||
WARN_ON(1); /* should never happen */
|
|
||||||
return -EEXIST;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap3_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
|
|
||||||
{
|
|
||||||
u32 m;
|
|
||||||
|
|
||||||
m = omap3_get_mem_bank_lastmemst_mask(bank);
|
|
||||||
|
|
||||||
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
|
||||||
OMAP3430_PM_PREPWSTST, m);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap3_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
omap2_prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap3_pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
return omap2_prm_rmw_mod_reg_bits(0,
|
|
||||||
1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
|
|
||||||
pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
return omap2_prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
|
|
||||||
0, pwrdm->prcm_offs,
|
|
||||||
OMAP2_PM_PWSTCTRL);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct pwrdm_ops omap2_pwrdm_operations = {
|
|
||||||
.pwrdm_set_next_pwrst = omap2_pwrdm_set_next_pwrst,
|
|
||||||
.pwrdm_read_next_pwrst = omap2_pwrdm_read_next_pwrst,
|
|
||||||
.pwrdm_read_pwrst = omap2_pwrdm_read_pwrst,
|
|
||||||
.pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst,
|
|
||||||
.pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst,
|
|
||||||
.pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst,
|
|
||||||
.pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst,
|
|
||||||
.pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst,
|
|
||||||
.pwrdm_wait_transition = omap2_pwrdm_wait_transition,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pwrdm_ops omap3_pwrdm_operations = {
|
|
||||||
.pwrdm_set_next_pwrst = omap2_pwrdm_set_next_pwrst,
|
|
||||||
.pwrdm_read_next_pwrst = omap2_pwrdm_read_next_pwrst,
|
|
||||||
.pwrdm_read_pwrst = omap2_pwrdm_read_pwrst,
|
|
||||||
.pwrdm_read_prev_pwrst = omap3_pwrdm_read_prev_pwrst,
|
|
||||||
.pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst,
|
|
||||||
.pwrdm_read_logic_pwrst = omap3_pwrdm_read_logic_pwrst,
|
|
||||||
.pwrdm_read_logic_retst = omap3_pwrdm_read_logic_retst,
|
|
||||||
.pwrdm_read_prev_logic_pwrst = omap3_pwrdm_read_prev_logic_pwrst,
|
|
||||||
.pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst,
|
|
||||||
.pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst,
|
|
||||||
.pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst,
|
|
||||||
.pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst,
|
|
||||||
.pwrdm_read_prev_mem_pwrst = omap3_pwrdm_read_prev_mem_pwrst,
|
|
||||||
.pwrdm_clear_all_prev_pwrst = omap3_pwrdm_clear_all_prev_pwrst,
|
|
||||||
.pwrdm_enable_hdwr_sar = omap3_pwrdm_enable_hdwr_sar,
|
|
||||||
.pwrdm_disable_hdwr_sar = omap3_pwrdm_disable_hdwr_sar,
|
|
||||||
.pwrdm_wait_transition = omap2_pwrdm_wait_transition,
|
|
||||||
};
|
|
||||||
@@ -1,229 +0,0 @@
|
|||||||
/*
|
|
||||||
* AM33XX Powerdomain control
|
|
||||||
*
|
|
||||||
* Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
|
|
||||||
*
|
|
||||||
* Derived from mach-omap2/powerdomain44xx.c written by 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 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/io.h>
|
|
||||||
#include <linux/errno.h>
|
|
||||||
#include <linux/delay.h>
|
|
||||||
|
|
||||||
#include <plat/prcm.h>
|
|
||||||
|
|
||||||
#include "powerdomain.h"
|
|
||||||
#include "prm33xx.h"
|
|
||||||
#include "prm-regbits-33xx.h"
|
|
||||||
|
|
||||||
|
|
||||||
static int am33xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
|
|
||||||
{
|
|
||||||
am33xx_prm_rmw_reg_bits(OMAP_POWERSTATE_MASK,
|
|
||||||
(pwrst << OMAP_POWERSTATE_SHIFT),
|
|
||||||
pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int am33xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
u32 v;
|
|
||||||
|
|
||||||
v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
|
|
||||||
v &= OMAP_POWERSTATE_MASK;
|
|
||||||
v >>= OMAP_POWERSTATE_SHIFT;
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
u32 v;
|
|
||||||
|
|
||||||
v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
|
|
||||||
v &= OMAP_POWERSTATEST_MASK;
|
|
||||||
v >>= OMAP_POWERSTATEST_SHIFT;
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int am33xx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
u32 v;
|
|
||||||
|
|
||||||
v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
|
|
||||||
v &= AM33XX_LASTPOWERSTATEENTERED_MASK;
|
|
||||||
v >>= AM33XX_LASTPOWERSTATEENTERED_SHIFT;
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK,
|
|
||||||
(1 << AM33XX_LOWPOWERSTATECHANGE_SHIFT),
|
|
||||||
pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int am33xx_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
am33xx_prm_rmw_reg_bits(AM33XX_LASTPOWERSTATEENTERED_MASK,
|
|
||||||
AM33XX_LASTPOWERSTATEENTERED_MASK,
|
|
||||||
pwrdm->prcm_offs, pwrdm->pwrstst_offs);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int am33xx_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
|
|
||||||
{
|
|
||||||
u32 m;
|
|
||||||
|
|
||||||
m = pwrdm->logicretstate_mask;
|
|
||||||
if (!m)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
|
|
||||||
pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
u32 v;
|
|
||||||
|
|
||||||
v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
|
|
||||||
v &= AM33XX_LOGICSTATEST_MASK;
|
|
||||||
v >>= AM33XX_LOGICSTATEST_SHIFT;
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
u32 v, m;
|
|
||||||
|
|
||||||
m = pwrdm->logicretstate_mask;
|
|
||||||
if (!m)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
|
|
||||||
v &= m;
|
|
||||||
v >>= __ffs(m);
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int am33xx_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
|
|
||||||
u8 pwrst)
|
|
||||||
{
|
|
||||||
u32 m;
|
|
||||||
|
|
||||||
m = pwrdm->mem_on_mask[bank];
|
|
||||||
if (!m)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
|
|
||||||
pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int am33xx_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
|
|
||||||
u8 pwrst)
|
|
||||||
{
|
|
||||||
u32 m;
|
|
||||||
|
|
||||||
m = pwrdm->mem_ret_mask[bank];
|
|
||||||
if (!m)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
|
|
||||||
pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int am33xx_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
|
|
||||||
{
|
|
||||||
u32 m, v;
|
|
||||||
|
|
||||||
m = pwrdm->mem_pwrst_mask[bank];
|
|
||||||
if (!m)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
|
|
||||||
v &= m;
|
|
||||||
v >>= __ffs(m);
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int am33xx_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
|
|
||||||
{
|
|
||||||
u32 m, v;
|
|
||||||
|
|
||||||
m = pwrdm->mem_retst_mask[bank];
|
|
||||||
if (!m)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
|
|
||||||
v &= m;
|
|
||||||
v >>= __ffs(m);
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int am33xx_pwrdm_wait_transition(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
u32 c = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* REVISIT: pwrdm_wait_transition() may be better implemented
|
|
||||||
* via a callback and a periodic timer check -- how long do we expect
|
|
||||||
* powerdomain transitions to take?
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* XXX Is this udelay() value meaningful? */
|
|
||||||
while ((am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs)
|
|
||||||
& OMAP_INTRANSITION_MASK) &&
|
|
||||||
(c++ < PWRDM_TRANSITION_BAILOUT))
|
|
||||||
udelay(1);
|
|
||||||
|
|
||||||
if (c > PWRDM_TRANSITION_BAILOUT) {
|
|
||||||
pr_err("powerdomain: %s: waited too long to complete transition\n",
|
|
||||||
pwrdm->name);
|
|
||||||
return -EAGAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("powerdomain: completed transition in %d loops\n", c);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct pwrdm_ops am33xx_pwrdm_operations = {
|
|
||||||
.pwrdm_set_next_pwrst = am33xx_pwrdm_set_next_pwrst,
|
|
||||||
.pwrdm_read_next_pwrst = am33xx_pwrdm_read_next_pwrst,
|
|
||||||
.pwrdm_read_pwrst = am33xx_pwrdm_read_pwrst,
|
|
||||||
.pwrdm_read_prev_pwrst = am33xx_pwrdm_read_prev_pwrst,
|
|
||||||
.pwrdm_set_logic_retst = am33xx_pwrdm_set_logic_retst,
|
|
||||||
.pwrdm_read_logic_pwrst = am33xx_pwrdm_read_logic_pwrst,
|
|
||||||
.pwrdm_read_logic_retst = am33xx_pwrdm_read_logic_retst,
|
|
||||||
.pwrdm_clear_all_prev_pwrst = am33xx_pwrdm_clear_all_prev_pwrst,
|
|
||||||
.pwrdm_set_lowpwrstchange = am33xx_pwrdm_set_lowpwrstchange,
|
|
||||||
.pwrdm_read_mem_pwrst = am33xx_pwrdm_read_mem_pwrst,
|
|
||||||
.pwrdm_read_mem_retst = am33xx_pwrdm_read_mem_retst,
|
|
||||||
.pwrdm_set_mem_onst = am33xx_pwrdm_set_mem_onst,
|
|
||||||
.pwrdm_set_mem_retst = am33xx_pwrdm_set_mem_retst,
|
|
||||||
.pwrdm_wait_transition = am33xx_pwrdm_wait_transition,
|
|
||||||
};
|
|
||||||
@@ -1,285 +0,0 @@
|
|||||||
/*
|
|
||||||
* OMAP4 powerdomain control
|
|
||||||
*
|
|
||||||
* Copyright (C) 2009-2010, 2012 Texas Instruments, Inc.
|
|
||||||
* Copyright (C) 2007-2009 Nokia Corporation
|
|
||||||
*
|
|
||||||
* Derived from mach-omap2/powerdomain.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/io.h>
|
|
||||||
#include <linux/errno.h>
|
|
||||||
#include <linux/delay.h>
|
|
||||||
#include <linux/bug.h>
|
|
||||||
|
|
||||||
#include "powerdomain.h"
|
|
||||||
#include <plat/prcm.h>
|
|
||||||
#include "prm2xxx_3xxx.h"
|
|
||||||
#include "prm44xx.h"
|
|
||||||
#include "prminst44xx.h"
|
|
||||||
#include "prm-regbits-44xx.h"
|
|
||||||
|
|
||||||
static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
|
|
||||||
{
|
|
||||||
omap4_prminst_rmw_inst_reg_bits(OMAP_POWERSTATE_MASK,
|
|
||||||
(pwrst << OMAP_POWERSTATE_SHIFT),
|
|
||||||
pwrdm->prcm_partition,
|
|
||||||
pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap4_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
u32 v;
|
|
||||||
|
|
||||||
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
|
|
||||||
OMAP4_PM_PWSTCTRL);
|
|
||||||
v &= OMAP_POWERSTATE_MASK;
|
|
||||||
v >>= OMAP_POWERSTATE_SHIFT;
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap4_pwrdm_read_pwrst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
u32 v;
|
|
||||||
|
|
||||||
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
|
|
||||||
OMAP4_PM_PWSTST);
|
|
||||||
v &= OMAP_POWERSTATEST_MASK;
|
|
||||||
v >>= OMAP_POWERSTATEST_SHIFT;
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap4_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
u32 v;
|
|
||||||
|
|
||||||
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
|
|
||||||
OMAP4_PM_PWSTST);
|
|
||||||
v &= OMAP4430_LASTPOWERSTATEENTERED_MASK;
|
|
||||||
v >>= OMAP4430_LASTPOWERSTATEENTERED_SHIFT;
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap4_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK,
|
|
||||||
(1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT),
|
|
||||||
pwrdm->prcm_partition,
|
|
||||||
pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap4_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
omap4_prminst_rmw_inst_reg_bits(OMAP4430_LASTPOWERSTATEENTERED_MASK,
|
|
||||||
OMAP4430_LASTPOWERSTATEENTERED_MASK,
|
|
||||||
pwrdm->prcm_partition,
|
|
||||||
pwrdm->prcm_offs, OMAP4_PM_PWSTST);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap4_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
|
|
||||||
{
|
|
||||||
u32 v;
|
|
||||||
|
|
||||||
v = pwrst << __ffs(OMAP4430_LOGICRETSTATE_MASK);
|
|
||||||
omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOGICRETSTATE_MASK, v,
|
|
||||||
pwrdm->prcm_partition, pwrdm->prcm_offs,
|
|
||||||
OMAP4_PM_PWSTCTRL);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap4_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
|
|
||||||
u8 pwrst)
|
|
||||||
{
|
|
||||||
u32 m;
|
|
||||||
|
|
||||||
m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
|
|
||||||
|
|
||||||
omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
|
|
||||||
pwrdm->prcm_partition, pwrdm->prcm_offs,
|
|
||||||
OMAP4_PM_PWSTCTRL);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap4_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
|
|
||||||
u8 pwrst)
|
|
||||||
{
|
|
||||||
u32 m;
|
|
||||||
|
|
||||||
m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
|
|
||||||
|
|
||||||
omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
|
|
||||||
pwrdm->prcm_partition, pwrdm->prcm_offs,
|
|
||||||
OMAP4_PM_PWSTCTRL);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap4_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
u32 v;
|
|
||||||
|
|
||||||
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
|
|
||||||
OMAP4_PM_PWSTST);
|
|
||||||
v &= OMAP4430_LOGICSTATEST_MASK;
|
|
||||||
v >>= OMAP4430_LOGICSTATEST_SHIFT;
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
u32 v;
|
|
||||||
|
|
||||||
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
|
|
||||||
OMAP4_PM_PWSTCTRL);
|
|
||||||
v &= OMAP4430_LOGICRETSTATE_MASK;
|
|
||||||
v >>= OMAP4430_LOGICRETSTATE_SHIFT;
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* omap4_pwrdm_read_prev_logic_pwrst - read the previous logic powerstate
|
|
||||||
* @pwrdm: struct powerdomain * to read the state for
|
|
||||||
*
|
|
||||||
* Reads the previous logic powerstate for a powerdomain. This
|
|
||||||
* function must determine the previous logic powerstate by first
|
|
||||||
* checking the previous powerstate for the domain. If that was OFF,
|
|
||||||
* then logic has been lost. If previous state was RETENTION, the
|
|
||||||
* function reads the setting for the next retention logic state to
|
|
||||||
* see the actual value. In every other case, the logic is
|
|
||||||
* retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
|
|
||||||
* depending whether the logic was retained or not.
|
|
||||||
*/
|
|
||||||
static int omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
int state;
|
|
||||||
|
|
||||||
state = omap4_pwrdm_read_prev_pwrst(pwrdm);
|
|
||||||
|
|
||||||
if (state == PWRDM_POWER_OFF)
|
|
||||||
return PWRDM_POWER_OFF;
|
|
||||||
|
|
||||||
if (state != PWRDM_POWER_RET)
|
|
||||||
return PWRDM_POWER_RET;
|
|
||||||
|
|
||||||
return omap4_pwrdm_read_logic_retst(pwrdm);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
|
|
||||||
{
|
|
||||||
u32 m, v;
|
|
||||||
|
|
||||||
m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
|
|
||||||
|
|
||||||
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
|
|
||||||
OMAP4_PM_PWSTST);
|
|
||||||
v &= m;
|
|
||||||
v >>= __ffs(m);
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
|
|
||||||
{
|
|
||||||
u32 m, v;
|
|
||||||
|
|
||||||
m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
|
|
||||||
|
|
||||||
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
|
|
||||||
OMAP4_PM_PWSTCTRL);
|
|
||||||
v &= m;
|
|
||||||
v >>= __ffs(m);
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* omap4_pwrdm_read_prev_mem_pwrst - reads the previous memory powerstate
|
|
||||||
* @pwrdm: struct powerdomain * to read mem powerstate for
|
|
||||||
* @bank: memory bank index
|
|
||||||
*
|
|
||||||
* Reads the previous memory powerstate for a powerdomain. This
|
|
||||||
* function must determine the previous memory powerstate by first
|
|
||||||
* checking the previous powerstate for the domain. If that was OFF,
|
|
||||||
* then logic has been lost. If previous state was RETENTION, the
|
|
||||||
* function reads the setting for the next memory retention state to
|
|
||||||
* see the actual value. In every other case, the logic is
|
|
||||||
* retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
|
|
||||||
* depending whether logic was retained or not.
|
|
||||||
*/
|
|
||||||
static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
|
|
||||||
{
|
|
||||||
int state;
|
|
||||||
|
|
||||||
state = omap4_pwrdm_read_prev_pwrst(pwrdm);
|
|
||||||
|
|
||||||
if (state == PWRDM_POWER_OFF)
|
|
||||||
return PWRDM_POWER_OFF;
|
|
||||||
|
|
||||||
if (state != PWRDM_POWER_RET)
|
|
||||||
return PWRDM_POWER_RET;
|
|
||||||
|
|
||||||
return omap4_pwrdm_read_mem_retst(pwrdm, bank);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
|
|
||||||
{
|
|
||||||
u32 c = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* REVISIT: pwrdm_wait_transition() may be better implemented
|
|
||||||
* via a callback and a periodic timer check -- how long do we expect
|
|
||||||
* powerdomain transitions to take?
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* XXX Is this udelay() value meaningful? */
|
|
||||||
while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
|
|
||||||
pwrdm->prcm_offs,
|
|
||||||
OMAP4_PM_PWSTST) &
|
|
||||||
OMAP_INTRANSITION_MASK) &&
|
|
||||||
(c++ < PWRDM_TRANSITION_BAILOUT))
|
|
||||||
udelay(1);
|
|
||||||
|
|
||||||
if (c > PWRDM_TRANSITION_BAILOUT) {
|
|
||||||
pr_err("powerdomain: %s: waited too long to complete transition\n",
|
|
||||||
pwrdm->name);
|
|
||||||
return -EAGAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("powerdomain: completed transition in %d loops\n", c);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct pwrdm_ops omap4_pwrdm_operations = {
|
|
||||||
.pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst,
|
|
||||||
.pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst,
|
|
||||||
.pwrdm_read_pwrst = omap4_pwrdm_read_pwrst,
|
|
||||||
.pwrdm_read_prev_pwrst = omap4_pwrdm_read_prev_pwrst,
|
|
||||||
.pwrdm_set_lowpwrstchange = omap4_pwrdm_set_lowpwrstchange,
|
|
||||||
.pwrdm_clear_all_prev_pwrst = omap4_pwrdm_clear_all_prev_pwrst,
|
|
||||||
.pwrdm_set_logic_retst = omap4_pwrdm_set_logic_retst,
|
|
||||||
.pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst,
|
|
||||||
.pwrdm_read_prev_logic_pwrst = omap4_pwrdm_read_prev_logic_pwrst,
|
|
||||||
.pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst,
|
|
||||||
.pwrdm_read_mem_pwrst = omap4_pwrdm_read_mem_pwrst,
|
|
||||||
.pwrdm_read_mem_retst = omap4_pwrdm_read_mem_retst,
|
|
||||||
.pwrdm_read_prev_mem_pwrst = omap4_pwrdm_read_prev_mem_pwrst,
|
|
||||||
.pwrdm_set_mem_onst = omap4_pwrdm_set_mem_onst,
|
|
||||||
.pwrdm_set_mem_retst = omap4_pwrdm_set_mem_retst,
|
|
||||||
.pwrdm_wait_transition = omap4_pwrdm_wait_transition,
|
|
||||||
};
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "prm2xxx_3xxx.h"
|
#include "prm2xxx.h"
|
||||||
|
|
||||||
/* Bits shared between registers */
|
/* Bits shared between registers */
|
||||||
|
|
||||||
@@ -209,9 +209,13 @@
|
|||||||
|
|
||||||
/* RM_RSTST_WKUP specific bits */
|
/* RM_RSTST_WKUP specific bits */
|
||||||
/* 2430 calls EXTWMPU_RST "EXTWARM_RST" and GLOBALWMPU_RST "GLOBALWARM_RST" */
|
/* 2430 calls EXTWMPU_RST "EXTWARM_RST" and GLOBALWMPU_RST "GLOBALWARM_RST" */
|
||||||
|
#define OMAP24XX_EXTWMPU_RST_SHIFT 6
|
||||||
#define OMAP24XX_EXTWMPU_RST_MASK (1 << 6)
|
#define OMAP24XX_EXTWMPU_RST_MASK (1 << 6)
|
||||||
|
#define OMAP24XX_SECU_WD_RST_SHIFT 5
|
||||||
#define OMAP24XX_SECU_WD_RST_MASK (1 << 5)
|
#define OMAP24XX_SECU_WD_RST_MASK (1 << 5)
|
||||||
|
#define OMAP24XX_MPU_WD_RST_SHIFT 4
|
||||||
#define OMAP24XX_MPU_WD_RST_MASK (1 << 4)
|
#define OMAP24XX_MPU_WD_RST_MASK (1 << 4)
|
||||||
|
#define OMAP24XX_SECU_VIOL_RST_SHIFT 3
|
||||||
#define OMAP24XX_SECU_VIOL_RST_MASK (1 << 3)
|
#define OMAP24XX_SECU_VIOL_RST_MASK (1 << 3)
|
||||||
|
|
||||||
/* PM_WKEN_WKUP specific bits */
|
/* PM_WKEN_WKUP specific bits */
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#define __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_34XX_H
|
#define __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_34XX_H
|
||||||
|
|
||||||
|
|
||||||
#include "prm2xxx_3xxx.h"
|
#include "prm3xxx.h"
|
||||||
|
|
||||||
/* Shared register bits */
|
/* Shared register bits */
|
||||||
|
|
||||||
@@ -509,15 +509,25 @@
|
|||||||
#define OMAP3430_RSTTIME1_MASK (0xff << 0)
|
#define OMAP3430_RSTTIME1_MASK (0xff << 0)
|
||||||
|
|
||||||
/* PRM_RSTST */
|
/* PRM_RSTST */
|
||||||
|
#define OMAP3430_ICECRUSHER_RST_SHIFT 10
|
||||||
#define OMAP3430_ICECRUSHER_RST_MASK (1 << 10)
|
#define OMAP3430_ICECRUSHER_RST_MASK (1 << 10)
|
||||||
|
#define OMAP3430_ICEPICK_RST_SHIFT 9
|
||||||
#define OMAP3430_ICEPICK_RST_MASK (1 << 9)
|
#define OMAP3430_ICEPICK_RST_MASK (1 << 9)
|
||||||
|
#define OMAP3430_VDD2_VOLTAGE_MANAGER_RST_SHIFT 8
|
||||||
#define OMAP3430_VDD2_VOLTAGE_MANAGER_RST_MASK (1 << 8)
|
#define OMAP3430_VDD2_VOLTAGE_MANAGER_RST_MASK (1 << 8)
|
||||||
|
#define OMAP3430_VDD1_VOLTAGE_MANAGER_RST_SHIFT 7
|
||||||
#define OMAP3430_VDD1_VOLTAGE_MANAGER_RST_MASK (1 << 7)
|
#define OMAP3430_VDD1_VOLTAGE_MANAGER_RST_MASK (1 << 7)
|
||||||
|
#define OMAP3430_EXTERNAL_WARM_RST_SHIFT 6
|
||||||
#define OMAP3430_EXTERNAL_WARM_RST_MASK (1 << 6)
|
#define OMAP3430_EXTERNAL_WARM_RST_MASK (1 << 6)
|
||||||
|
#define OMAP3430_SECURE_WD_RST_SHIFT 5
|
||||||
#define OMAP3430_SECURE_WD_RST_MASK (1 << 5)
|
#define OMAP3430_SECURE_WD_RST_MASK (1 << 5)
|
||||||
|
#define OMAP3430_MPU_WD_RST_SHIFT 4
|
||||||
#define OMAP3430_MPU_WD_RST_MASK (1 << 4)
|
#define OMAP3430_MPU_WD_RST_MASK (1 << 4)
|
||||||
|
#define OMAP3430_SECURITY_VIOL_RST_SHIFT 3
|
||||||
#define OMAP3430_SECURITY_VIOL_RST_MASK (1 << 3)
|
#define OMAP3430_SECURITY_VIOL_RST_MASK (1 << 3)
|
||||||
|
#define OMAP3430_GLOBAL_SW_RST_SHIFT 1
|
||||||
#define OMAP3430_GLOBAL_SW_RST_MASK (1 << 1)
|
#define OMAP3430_GLOBAL_SW_RST_MASK (1 << 1)
|
||||||
|
#define OMAP3430_GLOBAL_COLD_RST_SHIFT 0
|
||||||
#define OMAP3430_GLOBAL_COLD_RST_MASK (1 << 0)
|
#define OMAP3430_GLOBAL_COLD_RST_MASK (1 << 0)
|
||||||
|
|
||||||
/* PRM_VOLTCTRL */
|
/* PRM_VOLTCTRL */
|
||||||
|
|||||||
@@ -52,5 +52,58 @@
|
|||||||
#define OMAP_POWERSTATE_SHIFT 0
|
#define OMAP_POWERSTATE_SHIFT 0
|
||||||
#define OMAP_POWERSTATE_MASK (0x3 << 0)
|
#define OMAP_POWERSTATE_MASK (0x3 << 0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Standardized OMAP reset source bits
|
||||||
|
*
|
||||||
|
* To the extent these happen to match the hardware register bit
|
||||||
|
* shifts, it's purely coincidental. Used by omap-wdt.c.
|
||||||
|
* OMAP_UNKNOWN_RST_SRC_ID_SHIFT is a special value, used whenever
|
||||||
|
* there are any bits remaining in the global PRM_RSTST register that
|
||||||
|
* haven't been identified, or when the PRM code for the current SoC
|
||||||
|
* doesn't know how to interpret the register.
|
||||||
|
*/
|
||||||
|
#define OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT 0
|
||||||
|
#define OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT 1
|
||||||
|
#define OMAP_SECU_VIOL_RST_SRC_ID_SHIFT 2
|
||||||
|
#define OMAP_MPU_WD_RST_SRC_ID_SHIFT 3
|
||||||
|
#define OMAP_SECU_WD_RST_SRC_ID_SHIFT 4
|
||||||
|
#define OMAP_EXTWARM_RST_SRC_ID_SHIFT 5
|
||||||
|
#define OMAP_VDD_MPU_VM_RST_SRC_ID_SHIFT 6
|
||||||
|
#define OMAP_VDD_IVA_VM_RST_SRC_ID_SHIFT 7
|
||||||
|
#define OMAP_VDD_CORE_VM_RST_SRC_ID_SHIFT 8
|
||||||
|
#define OMAP_ICEPICK_RST_SRC_ID_SHIFT 9
|
||||||
|
#define OMAP_ICECRUSHER_RST_SRC_ID_SHIFT 10
|
||||||
|
#define OMAP_C2C_RST_SRC_ID_SHIFT 11
|
||||||
|
#define OMAP_UNKNOWN_RST_SRC_ID_SHIFT 12
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLER__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct prm_reset_src_map - map register bitshifts to standard bitshifts
|
||||||
|
* @reg_shift: bitshift in the PRM reset source register
|
||||||
|
* @std_shift: bitshift equivalent in the standard reset source list
|
||||||
|
*
|
||||||
|
* The fields are signed because -1 is used as a terminator.
|
||||||
|
*/
|
||||||
|
struct prm_reset_src_map {
|
||||||
|
s8 reg_shift;
|
||||||
|
s8 std_shift;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct prm_ll_data - fn ptrs to per-SoC PRM function implementations
|
||||||
|
* @read_reset_sources: ptr to the Soc PRM-specific get_reset_source impl
|
||||||
|
*/
|
||||||
|
struct prm_ll_data {
|
||||||
|
u32 (*read_reset_sources)(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int prm_register(struct prm_ll_data *pld);
|
||||||
|
extern int prm_unregister(struct prm_ll_data *pld);
|
||||||
|
|
||||||
|
extern u32 prm_read_reset_sources(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* OMAP2xxx PRM module functions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2012 Texas Instruments, Inc.
|
||||||
|
* Copyright (C) 2010 Nokia Corporation
|
||||||
|
* Benoît Cousson
|
||||||
|
* 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 <linux/errno.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/irq.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include <plat/cpu.h>
|
||||||
|
#include <plat/prcm.h>
|
||||||
|
|
||||||
|
#include "vp.h"
|
||||||
|
#include "powerdomain.h"
|
||||||
|
#include "clockdomain.h"
|
||||||
|
#include "prm2xxx.h"
|
||||||
|
#include "cm2xxx_3xxx.h"
|
||||||
|
#include "prm-regbits-24xx.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* omap2xxx_prm_reset_src_map - map from bits in the PRM_RSTST_WKUP
|
||||||
|
* hardware register (which are specific to the OMAP2xxx SoCs) to
|
||||||
|
* reset source ID bit shifts (which is an OMAP SoC-independent
|
||||||
|
* enumeration)
|
||||||
|
*/
|
||||||
|
static struct prm_reset_src_map omap2xxx_prm_reset_src_map[] = {
|
||||||
|
{ OMAP_GLOBALCOLD_RST_SHIFT, OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP_GLOBALWARM_RST_SHIFT, OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP24XX_SECU_VIOL_RST_SHIFT, OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP24XX_MPU_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP24XX_SECU_WD_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP24XX_EXTWMPU_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
|
||||||
|
{ -1, -1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* omap2xxx_prm_read_reset_sources - return the last SoC reset source
|
||||||
|
*
|
||||||
|
* Return a u32 representing the last reset sources of the SoC. The
|
||||||
|
* returned reset source bits are standardized across OMAP SoCs.
|
||||||
|
*/
|
||||||
|
static u32 omap2xxx_prm_read_reset_sources(void)
|
||||||
|
{
|
||||||
|
struct prm_reset_src_map *p;
|
||||||
|
u32 r = 0;
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST);
|
||||||
|
|
||||||
|
p = omap2xxx_prm_reset_src_map;
|
||||||
|
while (p->reg_shift >= 0 && p->std_shift >= 0) {
|
||||||
|
if (v & (1 << p->reg_shift))
|
||||||
|
r |= 1 << p->std_shift;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
.pwrdm_read_pwrst = omap2_pwrdm_read_pwrst,
|
||||||
|
.pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst,
|
||||||
|
.pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst,
|
||||||
|
.pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst,
|
||||||
|
.pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst,
|
||||||
|
.pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst,
|
||||||
|
.pwrdm_wait_transition = omap2_pwrdm_wait_transition,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct prm_ll_data omap2xxx_prm_ll_data = {
|
||||||
|
.read_reset_sources = &omap2xxx_prm_read_reset_sources,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init omap2xxx_prm_init(void)
|
||||||
|
{
|
||||||
|
if (!cpu_is_omap24xx())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return prm_register(&omap2xxx_prm_ll_data);
|
||||||
|
}
|
||||||
|
subsys_initcall(omap2xxx_prm_init);
|
||||||
|
|
||||||
|
static void __exit omap2xxx_prm_exit(void)
|
||||||
|
{
|
||||||
|
if (!cpu_is_omap24xx())
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Should never happen */
|
||||||
|
WARN(prm_unregister(&omap2xxx_prm_ll_data),
|
||||||
|
"%s: prm_ll_data function pointer mismatch\n", __func__);
|
||||||
|
}
|
||||||
|
__exitcall(omap2xxx_prm_exit);
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* OMAP2xxx Power/Reset Management (PRM) register definitions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2009, 2011-2012 Texas Instruments, Inc.
|
||||||
|
* Copyright (C) 2008-2010 Nokia Corporation
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* The PRM hardware modules on the OMAP2/3 are quite similar to each
|
||||||
|
* other. The PRM on OMAP4 has a new register layout, and is handled
|
||||||
|
* in a separate file.
|
||||||
|
*/
|
||||||
|
#ifndef __ARCH_ARM_MACH_OMAP2_PRM2XXX_H
|
||||||
|
#define __ARCH_ARM_MACH_OMAP2_PRM2XXX_H
|
||||||
|
|
||||||
|
#include "prcm-common.h"
|
||||||
|
#include "prm.h"
|
||||||
|
#include "prm2xxx_3xxx.h"
|
||||||
|
|
||||||
|
#define OMAP2420_PRM_REGADDR(module, reg) \
|
||||||
|
OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE + (module) + (reg))
|
||||||
|
#define OMAP2430_PRM_REGADDR(module, reg) \
|
||||||
|
OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE + (module) + (reg))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OMAP2-specific global PRM registers
|
||||||
|
* Use __raw_{read,write}l() with these registers.
|
||||||
|
*
|
||||||
|
* With a few exceptions, these are the register names beginning with
|
||||||
|
* PRCM_* on 24xx. (The exceptions are the IRQSTATUS and IRQENABLE
|
||||||
|
* bits.)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define OMAP2_PRCM_REVISION_OFFSET 0x0000
|
||||||
|
#define OMAP2420_PRCM_REVISION OMAP2420_PRM_REGADDR(OCP_MOD, 0x0000)
|
||||||
|
#define OMAP2_PRCM_SYSCONFIG_OFFSET 0x0010
|
||||||
|
#define OMAP2420_PRCM_SYSCONFIG OMAP2420_PRM_REGADDR(OCP_MOD, 0x0010)
|
||||||
|
|
||||||
|
#define OMAP2_PRCM_IRQSTATUS_MPU_OFFSET 0x0018
|
||||||
|
#define OMAP2420_PRCM_IRQSTATUS_MPU OMAP2420_PRM_REGADDR(OCP_MOD, 0x0018)
|
||||||
|
#define OMAP2_PRCM_IRQENABLE_MPU_OFFSET 0x001c
|
||||||
|
#define OMAP2420_PRCM_IRQENABLE_MPU OMAP2420_PRM_REGADDR(OCP_MOD, 0x001c)
|
||||||
|
|
||||||
|
#define OMAP2_PRCM_VOLTCTRL_OFFSET 0x0050
|
||||||
|
#define OMAP2420_PRCM_VOLTCTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0050)
|
||||||
|
#define OMAP2_PRCM_VOLTST_OFFSET 0x0054
|
||||||
|
#define OMAP2420_PRCM_VOLTST OMAP2420_PRM_REGADDR(OCP_MOD, 0x0054)
|
||||||
|
#define OMAP2_PRCM_CLKSRC_CTRL_OFFSET 0x0060
|
||||||
|
#define OMAP2420_PRCM_CLKSRC_CTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0060)
|
||||||
|
#define OMAP2_PRCM_CLKOUT_CTRL_OFFSET 0x0070
|
||||||
|
#define OMAP2420_PRCM_CLKOUT_CTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0070)
|
||||||
|
#define OMAP2_PRCM_CLKEMUL_CTRL_OFFSET 0x0078
|
||||||
|
#define OMAP2420_PRCM_CLKEMUL_CTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0078)
|
||||||
|
#define OMAP2_PRCM_CLKCFG_CTRL_OFFSET 0x0080
|
||||||
|
#define OMAP2420_PRCM_CLKCFG_CTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0080)
|
||||||
|
#define OMAP2_PRCM_CLKCFG_STATUS_OFFSET 0x0084
|
||||||
|
#define OMAP2420_PRCM_CLKCFG_STATUS OMAP2420_PRM_REGADDR(OCP_MOD, 0x0084)
|
||||||
|
#define OMAP2_PRCM_VOLTSETUP_OFFSET 0x0090
|
||||||
|
#define OMAP2420_PRCM_VOLTSETUP OMAP2420_PRM_REGADDR(OCP_MOD, 0x0090)
|
||||||
|
#define OMAP2_PRCM_CLKSSETUP_OFFSET 0x0094
|
||||||
|
#define OMAP2420_PRCM_CLKSSETUP OMAP2420_PRM_REGADDR(OCP_MOD, 0x0094)
|
||||||
|
#define OMAP2_PRCM_POLCTRL_OFFSET 0x0098
|
||||||
|
#define OMAP2420_PRCM_POLCTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0098)
|
||||||
|
|
||||||
|
#define OMAP2430_PRCM_REVISION OMAP2430_PRM_REGADDR(OCP_MOD, 0x0000)
|
||||||
|
#define OMAP2430_PRCM_SYSCONFIG OMAP2430_PRM_REGADDR(OCP_MOD, 0x0010)
|
||||||
|
|
||||||
|
#define OMAP2430_PRCM_IRQSTATUS_MPU OMAP2430_PRM_REGADDR(OCP_MOD, 0x0018)
|
||||||
|
#define OMAP2430_PRCM_IRQENABLE_MPU OMAP2430_PRM_REGADDR(OCP_MOD, 0x001c)
|
||||||
|
|
||||||
|
#define OMAP2430_PRCM_VOLTCTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0050)
|
||||||
|
#define OMAP2430_PRCM_VOLTST OMAP2430_PRM_REGADDR(OCP_MOD, 0x0054)
|
||||||
|
#define OMAP2430_PRCM_CLKSRC_CTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0060)
|
||||||
|
#define OMAP2430_PRCM_CLKOUT_CTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0070)
|
||||||
|
#define OMAP2430_PRCM_CLKEMUL_CTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0078)
|
||||||
|
#define OMAP2430_PRCM_CLKCFG_CTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0080)
|
||||||
|
#define OMAP2430_PRCM_CLKCFG_STATUS OMAP2430_PRM_REGADDR(OCP_MOD, 0x0084)
|
||||||
|
#define OMAP2430_PRCM_VOLTSETUP OMAP2430_PRM_REGADDR(OCP_MOD, 0x0090)
|
||||||
|
#define OMAP2430_PRCM_CLKSSETUP OMAP2430_PRM_REGADDR(OCP_MOD, 0x0094)
|
||||||
|
#define OMAP2430_PRCM_POLCTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0098)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module specific PRM register offsets from PRM_BASE + domain offset
|
||||||
|
*
|
||||||
|
* Use prm_{read,write}_mod_reg() with these registers.
|
||||||
|
*
|
||||||
|
* With a few exceptions, these are the register names beginning with
|
||||||
|
* {PM,RM}_* on both OMAP2/3 SoC families.. (The exceptions are the
|
||||||
|
* IRQSTATUS and IRQENABLE bits.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Register offsets appearing on both OMAP2 and OMAP3 */
|
||||||
|
|
||||||
|
#define OMAP2_RM_RSTCTRL 0x0050
|
||||||
|
#define OMAP2_RM_RSTTIME 0x0054
|
||||||
|
#define OMAP2_RM_RSTST 0x0058
|
||||||
|
#define OMAP2_PM_PWSTCTRL 0x00e0
|
||||||
|
#define OMAP2_PM_PWSTST 0x00e4
|
||||||
|
|
||||||
|
#define PM_WKEN 0x00a0
|
||||||
|
#define PM_WKEN1 PM_WKEN
|
||||||
|
#define PM_WKST 0x00b0
|
||||||
|
#define PM_WKST1 PM_WKST
|
||||||
|
#define PM_WKDEP 0x00c8
|
||||||
|
#define PM_EVGENCTRL 0x00d4
|
||||||
|
#define PM_EVGENONTIM 0x00d8
|
||||||
|
#define PM_EVGENOFFTIM 0x00dc
|
||||||
|
|
||||||
|
/* OMAP2xxx specific register offsets */
|
||||||
|
#define OMAP24XX_PM_WKEN2 0x00a4
|
||||||
|
#define OMAP24XX_PM_WKST2 0x00b4
|
||||||
|
|
||||||
|
#define OMAP24XX_PRCM_IRQSTATUS_DSP 0x00f0 /* IVA mod */
|
||||||
|
#define OMAP24XX_PRCM_IRQENABLE_DSP 0x00f4 /* IVA mod */
|
||||||
|
#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);
|
||||||
|
|
||||||
|
extern int __init prm2xxx_init(void);
|
||||||
|
extern int __exit prm2xxx_exit(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
+118
-230
@@ -15,82 +15,12 @@
|
|||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/irq.h>
|
|
||||||
|
|
||||||
#include <plat/prcm.h>
|
|
||||||
|
|
||||||
#include "soc.h"
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "vp.h"
|
#include "powerdomain.h"
|
||||||
|
|
||||||
#include "prm2xxx_3xxx.h"
|
#include "prm2xxx_3xxx.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
|
||||||
#include "prm-regbits-24xx.h"
|
#include "prm-regbits-24xx.h"
|
||||||
#include "prm-regbits-34xx.h"
|
#include "clockdomain.h"
|
||||||
|
|
||||||
static const struct omap_prcm_irq omap3_prcm_irqs[] = {
|
|
||||||
OMAP_PRCM_IRQ("wkup", 0, 0),
|
|
||||||
OMAP_PRCM_IRQ("io", 9, 1),
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct omap_prcm_irq_setup omap3_prcm_irq_setup = {
|
|
||||||
.ack = OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
|
|
||||||
.mask = OMAP3_PRM_IRQENABLE_MPU_OFFSET,
|
|
||||||
.nr_regs = 1,
|
|
||||||
.irqs = omap3_prcm_irqs,
|
|
||||||
.nr_irqs = ARRAY_SIZE(omap3_prcm_irqs),
|
|
||||||
.irq = 11 + OMAP_INTC_START,
|
|
||||||
.read_pending_irqs = &omap3xxx_prm_read_pending_irqs,
|
|
||||||
.ocp_barrier = &omap3xxx_prm_ocp_barrier,
|
|
||||||
.save_and_clear_irqen = &omap3xxx_prm_save_and_clear_irqen,
|
|
||||||
.restore_irqen = &omap3xxx_prm_restore_irqen,
|
|
||||||
};
|
|
||||||
|
|
||||||
u32 omap2_prm_read_mod_reg(s16 module, u16 idx)
|
|
||||||
{
|
|
||||||
return __raw_readl(prm_base + module + idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx)
|
|
||||||
{
|
|
||||||
__raw_writel(val, prm_base + module + idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read-modify-write a register in a PRM module. Caller must lock */
|
|
||||||
u32 omap2_prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
|
|
||||||
{
|
|
||||||
u32 v;
|
|
||||||
|
|
||||||
v = omap2_prm_read_mod_reg(module, idx);
|
|
||||||
v &= ~mask;
|
|
||||||
v |= bits;
|
|
||||||
omap2_prm_write_mod_reg(v, module, idx);
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read a PRM register, AND it, and shift the result down to bit 0 */
|
|
||||||
u32 omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
|
|
||||||
{
|
|
||||||
u32 v;
|
|
||||||
|
|
||||||
v = omap2_prm_read_mod_reg(domain, idx);
|
|
||||||
v &= mask;
|
|
||||||
v >>= __ffs(mask);
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 omap2_prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
|
|
||||||
{
|
|
||||||
return omap2_prm_rmw_mod_reg_bits(bits, bits, module, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
|
|
||||||
{
|
|
||||||
return omap2_prm_rmw_mod_reg_bits(bits, 0x0, module, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* omap2_prm_is_hardreset_asserted - read the HW reset line state of
|
* omap2_prm_is_hardreset_asserted - read the HW reset line state of
|
||||||
@@ -104,9 +34,6 @@ u32 omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
|
|||||||
*/
|
*/
|
||||||
int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift)
|
int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift)
|
||||||
{
|
{
|
||||||
if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL,
|
return omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL,
|
||||||
(1 << shift));
|
(1 << shift));
|
||||||
}
|
}
|
||||||
@@ -127,9 +54,6 @@ int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
|
|||||||
{
|
{
|
||||||
u32 mask;
|
u32 mask;
|
||||||
|
|
||||||
if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
mask = 1 << shift;
|
mask = 1 << shift;
|
||||||
omap2_prm_rmw_mod_reg_bits(mask, mask, prm_mod, OMAP2_RM_RSTCTRL);
|
omap2_prm_rmw_mod_reg_bits(mask, mask, prm_mod, OMAP2_RM_RSTCTRL);
|
||||||
|
|
||||||
@@ -156,9 +80,6 @@ int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift)
|
|||||||
u32 rst, st;
|
u32 rst, st;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
rst = 1 << rst_shift;
|
rst = 1 << rst_shift;
|
||||||
st = 1 << st_shift;
|
st = 1 << st_shift;
|
||||||
|
|
||||||
@@ -178,188 +99,155 @@ int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift)
|
|||||||
return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
|
return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PRM VP */
|
|
||||||
|
|
||||||
/*
|
/* Powerdomain low-level functions */
|
||||||
* struct omap3_vp - OMAP3 VP register access description.
|
|
||||||
* @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
|
|
||||||
*/
|
|
||||||
struct omap3_vp {
|
|
||||||
u32 tranxdone_status;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct omap3_vp omap3_vp[] = {
|
/* Common functions across OMAP2 and OMAP3 */
|
||||||
[OMAP3_VP_VDD_MPU_ID] = {
|
int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
|
||||||
.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
|
|
||||||
},
|
|
||||||
[OMAP3_VP_VDD_CORE_ID] = {
|
|
||||||
.tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MAX_VP_ID ARRAY_SIZE(omap3_vp);
|
|
||||||
|
|
||||||
u32 omap3_prm_vp_check_txdone(u8 vp_id)
|
|
||||||
{
|
{
|
||||||
struct omap3_vp *vp = &omap3_vp[vp_id];
|
omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK,
|
||||||
u32 irqstatus;
|
(pwrst << OMAP_POWERSTATE_SHIFT),
|
||||||
|
pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
|
||||||
irqstatus = omap2_prm_read_mod_reg(OCP_MOD,
|
return 0;
|
||||||
OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
|
|
||||||
return irqstatus & vp->tranxdone_status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void omap3_prm_vp_clear_txdone(u8 vp_id)
|
int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
|
||||||
{
|
{
|
||||||
struct omap3_vp *vp = &omap3_vp[vp_id];
|
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
||||||
|
OMAP2_PM_PWSTCTRL,
|
||||||
omap2_prm_write_mod_reg(vp->tranxdone_status,
|
OMAP_POWERSTATE_MASK);
|
||||||
OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 omap3_prm_vcvp_read(u8 offset)
|
int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm)
|
||||||
{
|
{
|
||||||
return omap2_prm_read_mod_reg(OMAP3430_GR_MOD, offset);
|
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
||||||
|
OMAP2_PM_PWSTST,
|
||||||
|
OMAP_POWERSTATEST_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void omap3_prm_vcvp_write(u32 val, u8 offset)
|
int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
|
||||||
|
u8 pwrst)
|
||||||
{
|
{
|
||||||
omap2_prm_write_mod_reg(val, OMAP3430_GR_MOD, offset);
|
u32 m;
|
||||||
|
|
||||||
|
m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
|
||||||
|
|
||||||
|
omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
|
||||||
|
OMAP2_PM_PWSTCTRL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
|
int omap2_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
|
||||||
|
u8 pwrst)
|
||||||
{
|
{
|
||||||
return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, offset);
|
u32 m;
|
||||||
|
|
||||||
|
m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
|
||||||
|
|
||||||
|
omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs,
|
||||||
|
OMAP2_PM_PWSTCTRL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int omap2_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
|
||||||
* omap3xxx_prm_read_pending_irqs - read pending PRM MPU IRQs into @events
|
|
||||||
* @events: ptr to a u32, preallocated by caller
|
|
||||||
*
|
|
||||||
* Read PRM_IRQSTATUS_MPU bits, AND'ed with the currently-enabled PRM
|
|
||||||
* MPU IRQs, and store the result into the u32 pointed to by @events.
|
|
||||||
* No return value.
|
|
||||||
*/
|
|
||||||
void omap3xxx_prm_read_pending_irqs(unsigned long *events)
|
|
||||||
{
|
{
|
||||||
u32 mask, st;
|
u32 m;
|
||||||
|
|
||||||
/* XXX Can the mask read be avoided (e.g., can it come from RAM?) */
|
m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
|
||||||
mask = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
|
|
||||||
st = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
|
|
||||||
|
|
||||||
events[0] = mask & st;
|
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, OMAP2_PM_PWSTST,
|
||||||
|
m);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int omap2_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
|
||||||
* omap3xxx_prm_ocp_barrier - force buffered MPU writes to the PRM to complete
|
|
||||||
*
|
|
||||||
* Force any buffered writes to the PRM IP block to complete. Needed
|
|
||||||
* by the PRM IRQ handler, which reads and writes directly to the IP
|
|
||||||
* block, to avoid race conditions after acknowledging or clearing IRQ
|
|
||||||
* bits. No return value.
|
|
||||||
*/
|
|
||||||
void omap3xxx_prm_ocp_barrier(void)
|
|
||||||
{
|
{
|
||||||
omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET);
|
u32 m;
|
||||||
|
|
||||||
|
m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
|
||||||
|
|
||||||
|
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
||||||
|
OMAP2_PM_PWSTCTRL, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
|
||||||
* omap3xxx_prm_save_and_clear_irqen - save/clear PRM_IRQENABLE_MPU reg
|
|
||||||
* @saved_mask: ptr to a u32 array to save IRQENABLE bits
|
|
||||||
*
|
|
||||||
* Save the PRM_IRQENABLE_MPU register to @saved_mask. @saved_mask
|
|
||||||
* must be allocated by the caller. Intended to be used in the PRM
|
|
||||||
* interrupt handler suspend callback. The OCP barrier is needed to
|
|
||||||
* ensure the write to disable PRM interrupts reaches the PRM before
|
|
||||||
* returning; otherwise, spurious interrupts might occur. No return
|
|
||||||
* value.
|
|
||||||
*/
|
|
||||||
void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask)
|
|
||||||
{
|
{
|
||||||
saved_mask[0] = omap2_prm_read_mod_reg(OCP_MOD,
|
u32 v;
|
||||||
OMAP3_PRM_IRQENABLE_MPU_OFFSET);
|
|
||||||
omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
|
|
||||||
|
|
||||||
/* OCP barrier */
|
v = pwrst << __ffs(OMAP_LOGICRETSTATE_MASK);
|
||||||
omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET);
|
omap2_prm_rmw_mod_reg_bits(OMAP_LOGICRETSTATE_MASK, v, pwrdm->prcm_offs,
|
||||||
|
OMAP2_PM_PWSTCTRL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int omap2_pwrdm_wait_transition(struct powerdomain *pwrdm)
|
||||||
* omap3xxx_prm_restore_irqen - set PRM_IRQENABLE_MPU register from args
|
|
||||||
* @saved_mask: ptr to a u32 array of IRQENABLE bits saved previously
|
|
||||||
*
|
|
||||||
* Restore the PRM_IRQENABLE_MPU register from @saved_mask. Intended
|
|
||||||
* to be used in the PRM interrupt handler resume callback to restore
|
|
||||||
* values saved by omap3xxx_prm_save_and_clear_irqen(). No OCP
|
|
||||||
* barrier should be needed here; any pending PRM interrupts will fire
|
|
||||||
* once the writes reach the PRM. No return value.
|
|
||||||
*/
|
|
||||||
void omap3xxx_prm_restore_irqen(u32 *saved_mask)
|
|
||||||
{
|
{
|
||||||
omap2_prm_write_mod_reg(saved_mask[0], OCP_MOD,
|
u32 c = 0;
|
||||||
OMAP3_PRM_IRQENABLE_MPU_OFFSET);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* omap3xxx_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain
|
* REVISIT: pwrdm_wait_transition() may be better implemented
|
||||||
*
|
* via a callback and a periodic timer check -- how long do we expect
|
||||||
* Clear any previously-latched I/O wakeup events and ensure that the
|
* powerdomain transitions to take?
|
||||||
* I/O wakeup gates are aligned with the current mux settings. Works
|
*/
|
||||||
* by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then
|
|
||||||
* deasserting WUCLKIN and clearing the ST_IO_CHAIN WKST bit. No
|
|
||||||
* return value.
|
|
||||||
*/
|
|
||||||
void omap3xxx_prm_reconfigure_io_chain(void)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
|
/* XXX Is this udelay() value meaningful? */
|
||||||
PM_WKEN);
|
while ((omap2_prm_read_mod_reg(pwrdm->prcm_offs, OMAP2_PM_PWSTST) &
|
||||||
|
OMAP_INTRANSITION_MASK) &&
|
||||||
|
(c++ < PWRDM_TRANSITION_BAILOUT))
|
||||||
|
udelay(1);
|
||||||
|
|
||||||
omap_test_timeout(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST) &
|
if (c > PWRDM_TRANSITION_BAILOUT) {
|
||||||
OMAP3430_ST_IO_CHAIN_MASK,
|
pr_err("powerdomain: %s: waited too long to complete transition\n",
|
||||||
MAX_IOPAD_LATCH_TIME, i);
|
pwrdm->name);
|
||||||
if (i == MAX_IOPAD_LATCH_TIME)
|
return -EAGAIN;
|
||||||
pr_warn("PRM: I/O chain clock line assertion timed out\n");
|
|
||||||
|
|
||||||
omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
|
|
||||||
PM_WKEN);
|
|
||||||
|
|
||||||
omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK, WKUP_MOD,
|
|
||||||
PM_WKST);
|
|
||||||
|
|
||||||
omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* omap3xxx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches
|
|
||||||
*
|
|
||||||
* Activates the I/O wakeup event latches and allows events logged by
|
|
||||||
* those latches to signal a wakeup event to the PRCM. For I/O
|
|
||||||
* wakeups to occur, WAKEUPENABLE bits must be set in the pad mux
|
|
||||||
* registers, and omap3xxx_prm_reconfigure_io_chain() must be called.
|
|
||||||
* No return value.
|
|
||||||
*/
|
|
||||||
static void __init omap3xxx_prm_enable_io_wakeup(void)
|
|
||||||
{
|
|
||||||
if (omap3_has_io_wakeup())
|
|
||||||
omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
|
|
||||||
PM_WKEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __init omap3xxx_prcm_init(void)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (cpu_is_omap34xx()) {
|
|
||||||
omap3xxx_prm_enable_io_wakeup();
|
|
||||||
ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
|
|
||||||
if (!ret)
|
|
||||||
irq_set_status_flags(omap_prcm_event_to_irq("io"),
|
|
||||||
IRQ_NOAUTOEN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
pr_debug("powerdomain: completed transition in %d loops\n", c);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
subsys_initcall(omap3xxx_prcm_init);
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* OMAP2/3 Power/Reset Management (PRM) register definitions
|
* OMAP2xxx/3xxx-common Power/Reset Management (PRM) register definitions
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2009, 2011 Texas Instruments, Inc.
|
* Copyright (C) 2007-2009, 2011-2012 Texas Instruments, Inc.
|
||||||
* Copyright (C) 2008-2010 Nokia Corporation
|
* Copyright (C) 2008-2010 Nokia Corporation
|
||||||
* Paul Walmsley
|
* Paul Walmsley
|
||||||
*
|
*
|
||||||
@@ -19,160 +19,6 @@
|
|||||||
#include "prcm-common.h"
|
#include "prcm-common.h"
|
||||||
#include "prm.h"
|
#include "prm.h"
|
||||||
|
|
||||||
#define OMAP2420_PRM_REGADDR(module, reg) \
|
|
||||||
OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE + (module) + (reg))
|
|
||||||
#define OMAP2430_PRM_REGADDR(module, reg) \
|
|
||||||
OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE + (module) + (reg))
|
|
||||||
#define OMAP34XX_PRM_REGADDR(module, reg) \
|
|
||||||
OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE + (module) + (reg))
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OMAP2-specific global PRM registers
|
|
||||||
* Use __raw_{read,write}l() with these registers.
|
|
||||||
*
|
|
||||||
* With a few exceptions, these are the register names beginning with
|
|
||||||
* PRCM_* on 24xx. (The exceptions are the IRQSTATUS and IRQENABLE
|
|
||||||
* bits.)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define OMAP2_PRCM_REVISION_OFFSET 0x0000
|
|
||||||
#define OMAP2420_PRCM_REVISION OMAP2420_PRM_REGADDR(OCP_MOD, 0x0000)
|
|
||||||
#define OMAP2_PRCM_SYSCONFIG_OFFSET 0x0010
|
|
||||||
#define OMAP2420_PRCM_SYSCONFIG OMAP2420_PRM_REGADDR(OCP_MOD, 0x0010)
|
|
||||||
|
|
||||||
#define OMAP2_PRCM_IRQSTATUS_MPU_OFFSET 0x0018
|
|
||||||
#define OMAP2420_PRCM_IRQSTATUS_MPU OMAP2420_PRM_REGADDR(OCP_MOD, 0x0018)
|
|
||||||
#define OMAP2_PRCM_IRQENABLE_MPU_OFFSET 0x001c
|
|
||||||
#define OMAP2420_PRCM_IRQENABLE_MPU OMAP2420_PRM_REGADDR(OCP_MOD, 0x001c)
|
|
||||||
|
|
||||||
#define OMAP2_PRCM_VOLTCTRL_OFFSET 0x0050
|
|
||||||
#define OMAP2420_PRCM_VOLTCTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0050)
|
|
||||||
#define OMAP2_PRCM_VOLTST_OFFSET 0x0054
|
|
||||||
#define OMAP2420_PRCM_VOLTST OMAP2420_PRM_REGADDR(OCP_MOD, 0x0054)
|
|
||||||
#define OMAP2_PRCM_CLKSRC_CTRL_OFFSET 0x0060
|
|
||||||
#define OMAP2420_PRCM_CLKSRC_CTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0060)
|
|
||||||
#define OMAP2_PRCM_CLKOUT_CTRL_OFFSET 0x0070
|
|
||||||
#define OMAP2420_PRCM_CLKOUT_CTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0070)
|
|
||||||
#define OMAP2_PRCM_CLKEMUL_CTRL_OFFSET 0x0078
|
|
||||||
#define OMAP2420_PRCM_CLKEMUL_CTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0078)
|
|
||||||
#define OMAP2_PRCM_CLKCFG_CTRL_OFFSET 0x0080
|
|
||||||
#define OMAP2420_PRCM_CLKCFG_CTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0080)
|
|
||||||
#define OMAP2_PRCM_CLKCFG_STATUS_OFFSET 0x0084
|
|
||||||
#define OMAP2420_PRCM_CLKCFG_STATUS OMAP2420_PRM_REGADDR(OCP_MOD, 0x0084)
|
|
||||||
#define OMAP2_PRCM_VOLTSETUP_OFFSET 0x0090
|
|
||||||
#define OMAP2420_PRCM_VOLTSETUP OMAP2420_PRM_REGADDR(OCP_MOD, 0x0090)
|
|
||||||
#define OMAP2_PRCM_CLKSSETUP_OFFSET 0x0094
|
|
||||||
#define OMAP2420_PRCM_CLKSSETUP OMAP2420_PRM_REGADDR(OCP_MOD, 0x0094)
|
|
||||||
#define OMAP2_PRCM_POLCTRL_OFFSET 0x0098
|
|
||||||
#define OMAP2420_PRCM_POLCTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0098)
|
|
||||||
|
|
||||||
#define OMAP2430_PRCM_REVISION OMAP2430_PRM_REGADDR(OCP_MOD, 0x0000)
|
|
||||||
#define OMAP2430_PRCM_SYSCONFIG OMAP2430_PRM_REGADDR(OCP_MOD, 0x0010)
|
|
||||||
|
|
||||||
#define OMAP2430_PRCM_IRQSTATUS_MPU OMAP2430_PRM_REGADDR(OCP_MOD, 0x0018)
|
|
||||||
#define OMAP2430_PRCM_IRQENABLE_MPU OMAP2430_PRM_REGADDR(OCP_MOD, 0x001c)
|
|
||||||
|
|
||||||
#define OMAP2430_PRCM_VOLTCTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0050)
|
|
||||||
#define OMAP2430_PRCM_VOLTST OMAP2430_PRM_REGADDR(OCP_MOD, 0x0054)
|
|
||||||
#define OMAP2430_PRCM_CLKSRC_CTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0060)
|
|
||||||
#define OMAP2430_PRCM_CLKOUT_CTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0070)
|
|
||||||
#define OMAP2430_PRCM_CLKEMUL_CTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0078)
|
|
||||||
#define OMAP2430_PRCM_CLKCFG_CTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0080)
|
|
||||||
#define OMAP2430_PRCM_CLKCFG_STATUS OMAP2430_PRM_REGADDR(OCP_MOD, 0x0084)
|
|
||||||
#define OMAP2430_PRCM_VOLTSETUP OMAP2430_PRM_REGADDR(OCP_MOD, 0x0090)
|
|
||||||
#define OMAP2430_PRCM_CLKSSETUP OMAP2430_PRM_REGADDR(OCP_MOD, 0x0094)
|
|
||||||
#define OMAP2430_PRCM_POLCTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0098)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OMAP3-specific global PRM registers
|
|
||||||
* Use __raw_{read,write}l() with these registers.
|
|
||||||
*
|
|
||||||
* With a few exceptions, these are the register names beginning with
|
|
||||||
* PRM_* on 34xx. (The exceptions are the IRQSTATUS and IRQENABLE
|
|
||||||
* bits.)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define OMAP3_PRM_REVISION_OFFSET 0x0004
|
|
||||||
#define OMAP3430_PRM_REVISION OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0004)
|
|
||||||
#define OMAP3_PRM_SYSCONFIG_OFFSET 0x0014
|
|
||||||
#define OMAP3430_PRM_SYSCONFIG OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0014)
|
|
||||||
|
|
||||||
#define OMAP3_PRM_IRQSTATUS_MPU_OFFSET 0x0018
|
|
||||||
#define OMAP3430_PRM_IRQSTATUS_MPU OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0018)
|
|
||||||
#define OMAP3_PRM_IRQENABLE_MPU_OFFSET 0x001c
|
|
||||||
#define OMAP3430_PRM_IRQENABLE_MPU OMAP34XX_PRM_REGADDR(OCP_MOD, 0x001c)
|
|
||||||
|
|
||||||
|
|
||||||
#define OMAP3_PRM_VC_SMPS_SA_OFFSET 0x0020
|
|
||||||
#define OMAP3430_PRM_VC_SMPS_SA OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0020)
|
|
||||||
#define OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET 0x0024
|
|
||||||
#define OMAP3430_PRM_VC_SMPS_VOL_RA OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0024)
|
|
||||||
#define OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET 0x0028
|
|
||||||
#define OMAP3430_PRM_VC_SMPS_CMD_RA OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0028)
|
|
||||||
#define OMAP3_PRM_VC_CMD_VAL_0_OFFSET 0x002c
|
|
||||||
#define OMAP3430_PRM_VC_CMD_VAL_0 OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x002c)
|
|
||||||
#define OMAP3_PRM_VC_CMD_VAL_1_OFFSET 0x0030
|
|
||||||
#define OMAP3430_PRM_VC_CMD_VAL_1 OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0030)
|
|
||||||
#define OMAP3_PRM_VC_CH_CONF_OFFSET 0x0034
|
|
||||||
#define OMAP3430_PRM_VC_CH_CONF OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0034)
|
|
||||||
#define OMAP3_PRM_VC_I2C_CFG_OFFSET 0x0038
|
|
||||||
#define OMAP3430_PRM_VC_I2C_CFG OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0038)
|
|
||||||
#define OMAP3_PRM_VC_BYPASS_VAL_OFFSET 0x003c
|
|
||||||
#define OMAP3430_PRM_VC_BYPASS_VAL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x003c)
|
|
||||||
#define OMAP3_PRM_RSTCTRL_OFFSET 0x0050
|
|
||||||
#define OMAP3430_PRM_RSTCTRL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0050)
|
|
||||||
#define OMAP3_PRM_RSTTIME_OFFSET 0x0054
|
|
||||||
#define OMAP3430_PRM_RSTTIME OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0054)
|
|
||||||
#define OMAP3_PRM_RSTST_OFFSET 0x0058
|
|
||||||
#define OMAP3430_PRM_RSTST OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0058)
|
|
||||||
#define OMAP3_PRM_VOLTCTRL_OFFSET 0x0060
|
|
||||||
#define OMAP3430_PRM_VOLTCTRL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0060)
|
|
||||||
#define OMAP3_PRM_SRAM_PCHARGE_OFFSET 0x0064
|
|
||||||
#define OMAP3430_PRM_SRAM_PCHARGE OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0064)
|
|
||||||
#define OMAP3_PRM_CLKSRC_CTRL_OFFSET 0x0070
|
|
||||||
#define OMAP3430_PRM_CLKSRC_CTRL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0070)
|
|
||||||
#define OMAP3_PRM_VOLTSETUP1_OFFSET 0x0090
|
|
||||||
#define OMAP3430_PRM_VOLTSETUP1 OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0090)
|
|
||||||
#define OMAP3_PRM_VOLTOFFSET_OFFSET 0x0094
|
|
||||||
#define OMAP3430_PRM_VOLTOFFSET OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0094)
|
|
||||||
#define OMAP3_PRM_CLKSETUP_OFFSET 0x0098
|
|
||||||
#define OMAP3430_PRM_CLKSETUP OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0098)
|
|
||||||
#define OMAP3_PRM_POLCTRL_OFFSET 0x009c
|
|
||||||
#define OMAP3430_PRM_POLCTRL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x009c)
|
|
||||||
#define OMAP3_PRM_VOLTSETUP2_OFFSET 0x00a0
|
|
||||||
#define OMAP3430_PRM_VOLTSETUP2 OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00a0)
|
|
||||||
#define OMAP3_PRM_VP1_CONFIG_OFFSET 0x00b0
|
|
||||||
#define OMAP3430_PRM_VP1_CONFIG OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b0)
|
|
||||||
#define OMAP3_PRM_VP1_VSTEPMIN_OFFSET 0x00b4
|
|
||||||
#define OMAP3430_PRM_VP1_VSTEPMIN OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b4)
|
|
||||||
#define OMAP3_PRM_VP1_VSTEPMAX_OFFSET 0x00b8
|
|
||||||
#define OMAP3430_PRM_VP1_VSTEPMAX OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b8)
|
|
||||||
#define OMAP3_PRM_VP1_VLIMITTO_OFFSET 0x00bc
|
|
||||||
#define OMAP3430_PRM_VP1_VLIMITTO OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00bc)
|
|
||||||
#define OMAP3_PRM_VP1_VOLTAGE_OFFSET 0x00c0
|
|
||||||
#define OMAP3430_PRM_VP1_VOLTAGE OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c0)
|
|
||||||
#define OMAP3_PRM_VP1_STATUS_OFFSET 0x00c4
|
|
||||||
#define OMAP3430_PRM_VP1_STATUS OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c4)
|
|
||||||
#define OMAP3_PRM_VP2_CONFIG_OFFSET 0x00d0
|
|
||||||
#define OMAP3430_PRM_VP2_CONFIG OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d0)
|
|
||||||
#define OMAP3_PRM_VP2_VSTEPMIN_OFFSET 0x00d4
|
|
||||||
#define OMAP3430_PRM_VP2_VSTEPMIN OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d4)
|
|
||||||
#define OMAP3_PRM_VP2_VSTEPMAX_OFFSET 0x00d8
|
|
||||||
#define OMAP3430_PRM_VP2_VSTEPMAX OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d8)
|
|
||||||
#define OMAP3_PRM_VP2_VLIMITTO_OFFSET 0x00dc
|
|
||||||
#define OMAP3430_PRM_VP2_VLIMITTO OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00dc)
|
|
||||||
#define OMAP3_PRM_VP2_VOLTAGE_OFFSET 0x00e0
|
|
||||||
#define OMAP3430_PRM_VP2_VOLTAGE OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e0)
|
|
||||||
#define OMAP3_PRM_VP2_STATUS_OFFSET 0x00e4
|
|
||||||
#define OMAP3430_PRM_VP2_STATUS OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e4)
|
|
||||||
|
|
||||||
#define OMAP3_PRM_CLKSEL_OFFSET 0x0040
|
|
||||||
#define OMAP3430_PRM_CLKSEL OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0040)
|
|
||||||
#define OMAP3_PRM_CLKOUT_CTRL_OFFSET 0x0070
|
|
||||||
#define OMAP3430_PRM_CLKOUT_CTRL OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Module specific PRM register offsets from PRM_BASE + domain offset
|
* Module specific PRM register offsets from PRM_BASE + domain offset
|
||||||
*
|
*
|
||||||
@@ -200,66 +46,83 @@
|
|||||||
#define PM_EVGENONTIM 0x00d8
|
#define PM_EVGENONTIM 0x00d8
|
||||||
#define PM_EVGENOFFTIM 0x00dc
|
#define PM_EVGENOFFTIM 0x00dc
|
||||||
|
|
||||||
/* OMAP2xxx specific register offsets */
|
|
||||||
#define OMAP24XX_PM_WKEN2 0x00a4
|
|
||||||
#define OMAP24XX_PM_WKST2 0x00b4
|
|
||||||
|
|
||||||
#define OMAP24XX_PRCM_IRQSTATUS_DSP 0x00f0 /* IVA mod */
|
|
||||||
#define OMAP24XX_PRCM_IRQENABLE_DSP 0x00f4 /* IVA mod */
|
|
||||||
#define OMAP24XX_PRCM_IRQSTATUS_IVA 0x00f8
|
|
||||||
#define OMAP24XX_PRCM_IRQENABLE_IVA 0x00fc
|
|
||||||
|
|
||||||
/* OMAP3 specific register offsets */
|
|
||||||
#define OMAP3430ES2_PM_WKEN3 0x00f0
|
|
||||||
#define OMAP3430ES2_PM_WKST3 0x00b8
|
|
||||||
|
|
||||||
#define OMAP3430_PM_MPUGRPSEL 0x00a4
|
|
||||||
#define OMAP3430_PM_MPUGRPSEL1 OMAP3430_PM_MPUGRPSEL
|
|
||||||
#define OMAP3430ES2_PM_MPUGRPSEL3 0x00f8
|
|
||||||
|
|
||||||
#define OMAP3430_PM_IVAGRPSEL 0x00a8
|
|
||||||
#define OMAP3430_PM_IVAGRPSEL1 OMAP3430_PM_IVAGRPSEL
|
|
||||||
#define OMAP3430ES2_PM_IVAGRPSEL3 0x00f4
|
|
||||||
|
|
||||||
#define OMAP3430_PM_PREPWSTST 0x00e8
|
|
||||||
|
|
||||||
#define OMAP3430_PRM_IRQSTATUS_IVA2 0x00f8
|
|
||||||
#define OMAP3430_PRM_IRQENABLE_IVA2 0x00fc
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __ASSEMBLER__
|
#ifndef __ASSEMBLER__
|
||||||
|
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include "powerdomain.h"
|
||||||
|
|
||||||
/* Power/reset management domain register get/set */
|
/* Power/reset management domain register get/set */
|
||||||
extern u32 omap2_prm_read_mod_reg(s16 module, u16 idx);
|
static inline u32 omap2_prm_read_mod_reg(s16 module, u16 idx)
|
||||||
extern void omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx);
|
{
|
||||||
extern u32 omap2_prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
|
return __raw_readl(prm_base + module + idx);
|
||||||
extern u32 omap2_prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx);
|
}
|
||||||
extern u32 omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx);
|
|
||||||
extern u32 omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask);
|
static inline void omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx)
|
||||||
|
{
|
||||||
|
__raw_writel(val, prm_base + module + idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read-modify-write a register in a PRM module. Caller must lock */
|
||||||
|
static inline u32 omap2_prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module,
|
||||||
|
s16 idx)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = omap2_prm_read_mod_reg(module, idx);
|
||||||
|
v &= ~mask;
|
||||||
|
v |= bits;
|
||||||
|
omap2_prm_write_mod_reg(v, module, idx);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read a PRM register, AND it, and shift the result down to bit 0 */
|
||||||
|
static inline u32 omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = omap2_prm_read_mod_reg(domain, idx);
|
||||||
|
v &= mask;
|
||||||
|
v >>= __ffs(mask);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 omap2_prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
|
||||||
|
{
|
||||||
|
return omap2_prm_rmw_mod_reg_bits(bits, bits, module, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
|
||||||
|
{
|
||||||
|
return omap2_prm_rmw_mod_reg_bits(bits, 0x0, module, idx);
|
||||||
|
}
|
||||||
|
|
||||||
/* These omap2_ PRM functions apply to both OMAP2 and 3 */
|
/* These omap2_ PRM functions apply to both OMAP2 and 3 */
|
||||||
extern int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift);
|
extern int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift);
|
||||||
extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
|
extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
|
||||||
extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift);
|
extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift);
|
||||||
|
|
||||||
/* OMAP3-specific VP functions */
|
extern int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);
|
||||||
u32 omap3_prm_vp_check_txdone(u8 vp_id);
|
extern int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm);
|
||||||
void omap3_prm_vp_clear_txdone(u8 vp_id);
|
extern int omap2_pwrdm_read_pwrst(struct powerdomain *pwrdm);
|
||||||
|
extern int omap2_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
|
||||||
|
u8 pwrst);
|
||||||
|
extern int omap2_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
|
||||||
|
u8 pwrst);
|
||||||
|
extern int omap2_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank);
|
||||||
|
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,
|
||||||
* OMAP3 access functions for voltage controller (VC) and
|
struct clockdomain *clkdm2);
|
||||||
* voltage proccessor (VP) in the PRM.
|
extern int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1,
|
||||||
*/
|
struct clockdomain *clkdm2);
|
||||||
extern u32 omap3_prm_vcvp_read(u8 offset);
|
extern int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1,
|
||||||
extern void omap3_prm_vcvp_write(u32 val, u8 offset);
|
struct clockdomain *clkdm2);
|
||||||
extern u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
|
extern int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm);
|
||||||
|
|
||||||
extern void omap3xxx_prm_reconfigure_io_chain(void);
|
|
||||||
|
|
||||||
/* PRM interrupt-related functions */
|
|
||||||
extern void omap3xxx_prm_read_pending_irqs(unsigned long *events);
|
|
||||||
extern void omap3xxx_prm_ocp_barrier(void);
|
|
||||||
extern void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask);
|
|
||||||
extern void omap3xxx_prm_restore_irqen(u32 *saved_mask);
|
|
||||||
|
|
||||||
#endif /* __ASSEMBLER */
|
#endif /* __ASSEMBLER */
|
||||||
|
|
||||||
@@ -348,7 +211,9 @@ extern void omap3xxx_prm_restore_irqen(u32 *saved_mask);
|
|||||||
*
|
*
|
||||||
* 3430: RM_RSTST_CORE, RM_RSTST_EMU
|
* 3430: RM_RSTST_CORE, RM_RSTST_EMU
|
||||||
*/
|
*/
|
||||||
|
#define OMAP_GLOBALWARM_RST_SHIFT 1
|
||||||
#define OMAP_GLOBALWARM_RST_MASK (1 << 1)
|
#define OMAP_GLOBALWARM_RST_MASK (1 << 1)
|
||||||
|
#define OMAP_GLOBALCOLD_RST_SHIFT 0
|
||||||
#define OMAP_GLOBALCOLD_RST_MASK (1 << 0)
|
#define OMAP_GLOBALCOLD_RST_MASK (1 << 0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "../plat-omap/common.h"
|
#include "../plat-omap/common.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "powerdomain.h"
|
||||||
#include "prm33xx.h"
|
#include "prm33xx.h"
|
||||||
#include "prm-regbits-33xx.h"
|
#include "prm-regbits-33xx.h"
|
||||||
|
|
||||||
@@ -133,3 +134,204 @@ int am33xx_prm_deassert_hardreset(u8 shift, s16 inst,
|
|||||||
|
|
||||||
return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
|
return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int am33xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
|
||||||
|
{
|
||||||
|
am33xx_prm_rmw_reg_bits(OMAP_POWERSTATE_MASK,
|
||||||
|
(pwrst << OMAP_POWERSTATE_SHIFT),
|
||||||
|
pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int am33xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
|
||||||
|
v &= OMAP_POWERSTATE_MASK;
|
||||||
|
v >>= OMAP_POWERSTATE_SHIFT;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
|
||||||
|
v &= OMAP_POWERSTATEST_MASK;
|
||||||
|
v >>= OMAP_POWERSTATEST_SHIFT;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int am33xx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
|
||||||
|
v &= AM33XX_LASTPOWERSTATEENTERED_MASK;
|
||||||
|
v >>= AM33XX_LASTPOWERSTATEENTERED_SHIFT;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK,
|
||||||
|
(1 << AM33XX_LOWPOWERSTATECHANGE_SHIFT),
|
||||||
|
pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int am33xx_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
am33xx_prm_rmw_reg_bits(AM33XX_LASTPOWERSTATEENTERED_MASK,
|
||||||
|
AM33XX_LASTPOWERSTATEENTERED_MASK,
|
||||||
|
pwrdm->prcm_offs, pwrdm->pwrstst_offs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int am33xx_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
|
||||||
|
{
|
||||||
|
u32 m;
|
||||||
|
|
||||||
|
m = pwrdm->logicretstate_mask;
|
||||||
|
if (!m)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
|
||||||
|
pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
|
||||||
|
v &= AM33XX_LOGICSTATEST_MASK;
|
||||||
|
v >>= AM33XX_LOGICSTATEST_SHIFT;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
u32 v, m;
|
||||||
|
|
||||||
|
m = pwrdm->logicretstate_mask;
|
||||||
|
if (!m)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
|
||||||
|
v &= m;
|
||||||
|
v >>= __ffs(m);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int am33xx_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
|
||||||
|
u8 pwrst)
|
||||||
|
{
|
||||||
|
u32 m;
|
||||||
|
|
||||||
|
m = pwrdm->mem_on_mask[bank];
|
||||||
|
if (!m)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
|
||||||
|
pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int am33xx_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
|
||||||
|
u8 pwrst)
|
||||||
|
{
|
||||||
|
u32 m;
|
||||||
|
|
||||||
|
m = pwrdm->mem_ret_mask[bank];
|
||||||
|
if (!m)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
|
||||||
|
pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int am33xx_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
|
||||||
|
{
|
||||||
|
u32 m, v;
|
||||||
|
|
||||||
|
m = pwrdm->mem_pwrst_mask[bank];
|
||||||
|
if (!m)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
|
||||||
|
v &= m;
|
||||||
|
v >>= __ffs(m);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int am33xx_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
|
||||||
|
{
|
||||||
|
u32 m, v;
|
||||||
|
|
||||||
|
m = pwrdm->mem_retst_mask[bank];
|
||||||
|
if (!m)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
|
||||||
|
v &= m;
|
||||||
|
v >>= __ffs(m);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int am33xx_pwrdm_wait_transition(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
u32 c = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* REVISIT: pwrdm_wait_transition() may be better implemented
|
||||||
|
* via a callback and a periodic timer check -- how long do we expect
|
||||||
|
* powerdomain transitions to take?
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* XXX Is this udelay() value meaningful? */
|
||||||
|
while ((am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs)
|
||||||
|
& OMAP_INTRANSITION_MASK) &&
|
||||||
|
(c++ < PWRDM_TRANSITION_BAILOUT))
|
||||||
|
udelay(1);
|
||||||
|
|
||||||
|
if (c > PWRDM_TRANSITION_BAILOUT) {
|
||||||
|
pr_err("powerdomain: %s: waited too long to complete transition\n",
|
||||||
|
pwrdm->name);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_debug("powerdomain: completed transition in %d loops\n", c);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pwrdm_ops am33xx_pwrdm_operations = {
|
||||||
|
.pwrdm_set_next_pwrst = am33xx_pwrdm_set_next_pwrst,
|
||||||
|
.pwrdm_read_next_pwrst = am33xx_pwrdm_read_next_pwrst,
|
||||||
|
.pwrdm_read_pwrst = am33xx_pwrdm_read_pwrst,
|
||||||
|
.pwrdm_read_prev_pwrst = am33xx_pwrdm_read_prev_pwrst,
|
||||||
|
.pwrdm_set_logic_retst = am33xx_pwrdm_set_logic_retst,
|
||||||
|
.pwrdm_read_logic_pwrst = am33xx_pwrdm_read_logic_pwrst,
|
||||||
|
.pwrdm_read_logic_retst = am33xx_pwrdm_read_logic_retst,
|
||||||
|
.pwrdm_clear_all_prev_pwrst = am33xx_pwrdm_clear_all_prev_pwrst,
|
||||||
|
.pwrdm_set_lowpwrstchange = am33xx_pwrdm_set_lowpwrstchange,
|
||||||
|
.pwrdm_read_mem_pwrst = am33xx_pwrdm_read_mem_pwrst,
|
||||||
|
.pwrdm_read_mem_retst = am33xx_pwrdm_read_mem_retst,
|
||||||
|
.pwrdm_set_mem_onst = am33xx_pwrdm_set_mem_onst,
|
||||||
|
.pwrdm_set_mem_retst = am33xx_pwrdm_set_mem_retst,
|
||||||
|
.pwrdm_wait_transition = am33xx_pwrdm_wait_transition,
|
||||||
|
};
|
||||||
|
|||||||
@@ -0,0 +1,403 @@
|
|||||||
|
/*
|
||||||
|
* OMAP3xxx PRM module functions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2012 Texas Instruments, Inc.
|
||||||
|
* Copyright (C) 2010 Nokia Corporation
|
||||||
|
* Benoît Cousson
|
||||||
|
* 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 <linux/errno.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/irq.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include <plat/cpu.h>
|
||||||
|
#include <plat/prcm.h>
|
||||||
|
|
||||||
|
#include "vp.h"
|
||||||
|
#include "powerdomain.h"
|
||||||
|
#include "prm3xxx.h"
|
||||||
|
#include "prm2xxx_3xxx.h"
|
||||||
|
#include "cm2xxx_3xxx.h"
|
||||||
|
#include "prm-regbits-34xx.h"
|
||||||
|
|
||||||
|
static const struct omap_prcm_irq omap3_prcm_irqs[] = {
|
||||||
|
OMAP_PRCM_IRQ("wkup", 0, 0),
|
||||||
|
OMAP_PRCM_IRQ("io", 9, 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct omap_prcm_irq_setup omap3_prcm_irq_setup = {
|
||||||
|
.ack = OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
|
||||||
|
.mask = OMAP3_PRM_IRQENABLE_MPU_OFFSET,
|
||||||
|
.nr_regs = 1,
|
||||||
|
.irqs = omap3_prcm_irqs,
|
||||||
|
.nr_irqs = ARRAY_SIZE(omap3_prcm_irqs),
|
||||||
|
.irq = 11 + OMAP_INTC_START,
|
||||||
|
.read_pending_irqs = &omap3xxx_prm_read_pending_irqs,
|
||||||
|
.ocp_barrier = &omap3xxx_prm_ocp_barrier,
|
||||||
|
.save_and_clear_irqen = &omap3xxx_prm_save_and_clear_irqen,
|
||||||
|
.restore_irqen = &omap3xxx_prm_restore_irqen,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* omap3_prm_reset_src_map - map from bits in the PRM_RSTST hardware
|
||||||
|
* register (which are specific to OMAP3xxx SoCs) to reset source ID
|
||||||
|
* bit shifts (which is an OMAP SoC-independent enumeration)
|
||||||
|
*/
|
||||||
|
static struct prm_reset_src_map omap3xxx_prm_reset_src_map[] = {
|
||||||
|
{ OMAP3430_GLOBAL_COLD_RST_SHIFT, OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP3430_GLOBAL_SW_RST_SHIFT, OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP3430_SECURITY_VIOL_RST_SHIFT, OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP3430_MPU_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP3430_SECURE_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP3430_EXTERNAL_WARM_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP3430_VDD1_VOLTAGE_MANAGER_RST_SHIFT,
|
||||||
|
OMAP_VDD_MPU_VM_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP3430_VDD2_VOLTAGE_MANAGER_RST_SHIFT,
|
||||||
|
OMAP_VDD_CORE_VM_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP3430_ICEPICK_RST_SHIFT, OMAP_ICEPICK_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP3430_ICECRUSHER_RST_SHIFT, OMAP_ICECRUSHER_RST_SRC_ID_SHIFT },
|
||||||
|
{ -1, -1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* PRM VP */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* struct omap3_vp - OMAP3 VP register access description.
|
||||||
|
* @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
|
||||||
|
*/
|
||||||
|
struct omap3_vp {
|
||||||
|
u32 tranxdone_status;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct omap3_vp omap3_vp[] = {
|
||||||
|
[OMAP3_VP_VDD_MPU_ID] = {
|
||||||
|
.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
|
||||||
|
},
|
||||||
|
[OMAP3_VP_VDD_CORE_ID] = {
|
||||||
|
.tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAX_VP_ID ARRAY_SIZE(omap3_vp);
|
||||||
|
|
||||||
|
u32 omap3_prm_vp_check_txdone(u8 vp_id)
|
||||||
|
{
|
||||||
|
struct omap3_vp *vp = &omap3_vp[vp_id];
|
||||||
|
u32 irqstatus;
|
||||||
|
|
||||||
|
irqstatus = omap2_prm_read_mod_reg(OCP_MOD,
|
||||||
|
OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
|
||||||
|
return irqstatus & vp->tranxdone_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void omap3_prm_vp_clear_txdone(u8 vp_id)
|
||||||
|
{
|
||||||
|
struct omap3_vp *vp = &omap3_vp[vp_id];
|
||||||
|
|
||||||
|
omap2_prm_write_mod_reg(vp->tranxdone_status,
|
||||||
|
OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 omap3_prm_vcvp_read(u8 offset)
|
||||||
|
{
|
||||||
|
return omap2_prm_read_mod_reg(OMAP3430_GR_MOD, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void omap3_prm_vcvp_write(u32 val, u8 offset)
|
||||||
|
{
|
||||||
|
omap2_prm_write_mod_reg(val, OMAP3430_GR_MOD, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
|
||||||
|
{
|
||||||
|
return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* omap3xxx_prm_read_pending_irqs - read pending PRM MPU IRQs into @events
|
||||||
|
* @events: ptr to a u32, preallocated by caller
|
||||||
|
*
|
||||||
|
* Read PRM_IRQSTATUS_MPU bits, AND'ed with the currently-enabled PRM
|
||||||
|
* MPU IRQs, and store the result into the u32 pointed to by @events.
|
||||||
|
* No return value.
|
||||||
|
*/
|
||||||
|
void omap3xxx_prm_read_pending_irqs(unsigned long *events)
|
||||||
|
{
|
||||||
|
u32 mask, st;
|
||||||
|
|
||||||
|
/* XXX Can the mask read be avoided (e.g., can it come from RAM?) */
|
||||||
|
mask = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
|
||||||
|
st = omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
|
||||||
|
|
||||||
|
events[0] = mask & st;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* omap3xxx_prm_ocp_barrier - force buffered MPU writes to the PRM to complete
|
||||||
|
*
|
||||||
|
* Force any buffered writes to the PRM IP block to complete. Needed
|
||||||
|
* by the PRM IRQ handler, which reads and writes directly to the IP
|
||||||
|
* block, to avoid race conditions after acknowledging or clearing IRQ
|
||||||
|
* bits. No return value.
|
||||||
|
*/
|
||||||
|
void omap3xxx_prm_ocp_barrier(void)
|
||||||
|
{
|
||||||
|
omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* omap3xxx_prm_save_and_clear_irqen - save/clear PRM_IRQENABLE_MPU reg
|
||||||
|
* @saved_mask: ptr to a u32 array to save IRQENABLE bits
|
||||||
|
*
|
||||||
|
* Save the PRM_IRQENABLE_MPU register to @saved_mask. @saved_mask
|
||||||
|
* must be allocated by the caller. Intended to be used in the PRM
|
||||||
|
* interrupt handler suspend callback. The OCP barrier is needed to
|
||||||
|
* ensure the write to disable PRM interrupts reaches the PRM before
|
||||||
|
* returning; otherwise, spurious interrupts might occur. No return
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
|
void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask)
|
||||||
|
{
|
||||||
|
saved_mask[0] = omap2_prm_read_mod_reg(OCP_MOD,
|
||||||
|
OMAP3_PRM_IRQENABLE_MPU_OFFSET);
|
||||||
|
omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
|
||||||
|
|
||||||
|
/* OCP barrier */
|
||||||
|
omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* omap3xxx_prm_restore_irqen - set PRM_IRQENABLE_MPU register from args
|
||||||
|
* @saved_mask: ptr to a u32 array of IRQENABLE bits saved previously
|
||||||
|
*
|
||||||
|
* Restore the PRM_IRQENABLE_MPU register from @saved_mask. Intended
|
||||||
|
* to be used in the PRM interrupt handler resume callback to restore
|
||||||
|
* values saved by omap3xxx_prm_save_and_clear_irqen(). No OCP
|
||||||
|
* barrier should be needed here; any pending PRM interrupts will fire
|
||||||
|
* once the writes reach the PRM. No return value.
|
||||||
|
*/
|
||||||
|
void omap3xxx_prm_restore_irqen(u32 *saved_mask)
|
||||||
|
{
|
||||||
|
omap2_prm_write_mod_reg(saved_mask[0], OCP_MOD,
|
||||||
|
OMAP3_PRM_IRQENABLE_MPU_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* omap3xxx_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain
|
||||||
|
*
|
||||||
|
* Clear any previously-latched I/O wakeup events and ensure that the
|
||||||
|
* I/O wakeup gates are aligned with the current mux settings. Works
|
||||||
|
* by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then
|
||||||
|
* deasserting WUCLKIN and clearing the ST_IO_CHAIN WKST bit. No
|
||||||
|
* return value.
|
||||||
|
*/
|
||||||
|
void omap3xxx_prm_reconfigure_io_chain(void)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
|
||||||
|
PM_WKEN);
|
||||||
|
|
||||||
|
omap_test_timeout(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST) &
|
||||||
|
OMAP3430_ST_IO_CHAIN_MASK,
|
||||||
|
MAX_IOPAD_LATCH_TIME, i);
|
||||||
|
if (i == MAX_IOPAD_LATCH_TIME)
|
||||||
|
pr_warn("PRM: I/O chain clock line assertion timed out\n");
|
||||||
|
|
||||||
|
omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
|
||||||
|
PM_WKEN);
|
||||||
|
|
||||||
|
omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK, WKUP_MOD,
|
||||||
|
PM_WKST);
|
||||||
|
|
||||||
|
omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* omap3xxx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches
|
||||||
|
*
|
||||||
|
* Activates the I/O wakeup event latches and allows events logged by
|
||||||
|
* those latches to signal a wakeup event to the PRCM. For I/O
|
||||||
|
* wakeups to occur, WAKEUPENABLE bits must be set in the pad mux
|
||||||
|
* registers, and omap3xxx_prm_reconfigure_io_chain() must be called.
|
||||||
|
* No return value.
|
||||||
|
*/
|
||||||
|
static void __init omap3xxx_prm_enable_io_wakeup(void)
|
||||||
|
{
|
||||||
|
if (omap3_has_io_wakeup())
|
||||||
|
omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
|
||||||
|
PM_WKEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* omap3xxx_prm_read_reset_sources - return the last SoC reset source
|
||||||
|
*
|
||||||
|
* Return a u32 representing the last reset sources of the SoC. The
|
||||||
|
* returned reset source bits are standardized across OMAP SoCs.
|
||||||
|
*/
|
||||||
|
static u32 omap3xxx_prm_read_reset_sources(void)
|
||||||
|
{
|
||||||
|
struct prm_reset_src_map *p;
|
||||||
|
u32 r = 0;
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST);
|
||||||
|
|
||||||
|
p = omap3xxx_prm_reset_src_map;
|
||||||
|
while (p->reg_shift >= 0 && p->std_shift >= 0) {
|
||||||
|
if (v & (1 << p->reg_shift))
|
||||||
|
r |= 1 << p->std_shift;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Powerdomain low-level functions */
|
||||||
|
|
||||||
|
/* Applicable only for OMAP3. Not supported on OMAP2 */
|
||||||
|
static int omap3_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
||||||
|
OMAP3430_PM_PREPWSTST,
|
||||||
|
OMAP3430_LASTPOWERSTATEENTERED_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap3_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
||||||
|
OMAP2_PM_PWSTST,
|
||||||
|
OMAP3430_LOGICSTATEST_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap3_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
||||||
|
OMAP2_PM_PWSTCTRL,
|
||||||
|
OMAP3430_LOGICSTATEST_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap3_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
||||||
|
OMAP3430_PM_PREPWSTST,
|
||||||
|
OMAP3430_LASTLOGICSTATEENTERED_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap3_get_mem_bank_lastmemst_mask(u8 bank)
|
||||||
|
{
|
||||||
|
switch (bank) {
|
||||||
|
case 0:
|
||||||
|
return OMAP3430_LASTMEM1STATEENTERED_MASK;
|
||||||
|
case 1:
|
||||||
|
return OMAP3430_LASTMEM2STATEENTERED_MASK;
|
||||||
|
case 2:
|
||||||
|
return OMAP3430_LASTSHAREDL2CACHEFLATSTATEENTERED_MASK;
|
||||||
|
case 3:
|
||||||
|
return OMAP3430_LASTL2FLATMEMSTATEENTERED_MASK;
|
||||||
|
default:
|
||||||
|
WARN_ON(1); /* should never happen */
|
||||||
|
return -EEXIST;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap3_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
|
||||||
|
{
|
||||||
|
u32 m;
|
||||||
|
|
||||||
|
m = omap3_get_mem_bank_lastmemst_mask(bank);
|
||||||
|
|
||||||
|
return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs,
|
||||||
|
OMAP3430_PM_PREPWSTST, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap3_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
omap2_prm_write_mod_reg(0, pwrdm->prcm_offs, OMAP3430_PM_PREPWSTST);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap3_pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
return omap2_prm_rmw_mod_reg_bits(0,
|
||||||
|
1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
|
||||||
|
pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap3_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
return omap2_prm_rmw_mod_reg_bits(1 << OMAP3430ES2_SAVEANDRESTORE_SHIFT,
|
||||||
|
0, pwrdm->prcm_offs,
|
||||||
|
OMAP2_PM_PWSTCTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pwrdm_ops omap3_pwrdm_operations = {
|
||||||
|
.pwrdm_set_next_pwrst = omap2_pwrdm_set_next_pwrst,
|
||||||
|
.pwrdm_read_next_pwrst = omap2_pwrdm_read_next_pwrst,
|
||||||
|
.pwrdm_read_pwrst = omap2_pwrdm_read_pwrst,
|
||||||
|
.pwrdm_read_prev_pwrst = omap3_pwrdm_read_prev_pwrst,
|
||||||
|
.pwrdm_set_logic_retst = omap2_pwrdm_set_logic_retst,
|
||||||
|
.pwrdm_read_logic_pwrst = omap3_pwrdm_read_logic_pwrst,
|
||||||
|
.pwrdm_read_logic_retst = omap3_pwrdm_read_logic_retst,
|
||||||
|
.pwrdm_read_prev_logic_pwrst = omap3_pwrdm_read_prev_logic_pwrst,
|
||||||
|
.pwrdm_set_mem_onst = omap2_pwrdm_set_mem_onst,
|
||||||
|
.pwrdm_set_mem_retst = omap2_pwrdm_set_mem_retst,
|
||||||
|
.pwrdm_read_mem_pwrst = omap2_pwrdm_read_mem_pwrst,
|
||||||
|
.pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst,
|
||||||
|
.pwrdm_read_prev_mem_pwrst = omap3_pwrdm_read_prev_mem_pwrst,
|
||||||
|
.pwrdm_clear_all_prev_pwrst = omap3_pwrdm_clear_all_prev_pwrst,
|
||||||
|
.pwrdm_enable_hdwr_sar = omap3_pwrdm_enable_hdwr_sar,
|
||||||
|
.pwrdm_disable_hdwr_sar = omap3_pwrdm_disable_hdwr_sar,
|
||||||
|
.pwrdm_wait_transition = omap2_pwrdm_wait_transition,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct prm_ll_data omap3xxx_prm_ll_data = {
|
||||||
|
.read_reset_sources = &omap3xxx_prm_read_reset_sources,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init omap3xxx_prm_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!cpu_is_omap34xx())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = prm_register(&omap3xxx_prm_ll_data);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
omap3xxx_prm_enable_io_wakeup();
|
||||||
|
ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
|
||||||
|
if (!ret)
|
||||||
|
irq_set_status_flags(omap_prcm_event_to_irq("io"),
|
||||||
|
IRQ_NOAUTOEN);
|
||||||
|
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
subsys_initcall(omap3xxx_prm_init);
|
||||||
|
|
||||||
|
static void __exit omap3xxx_prm_exit(void)
|
||||||
|
{
|
||||||
|
if (!cpu_is_omap34xx())
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Should never happen */
|
||||||
|
WARN(prm_unregister(&omap3xxx_prm_ll_data),
|
||||||
|
"%s: prm_ll_data function pointer mismatch\n", __func__);
|
||||||
|
}
|
||||||
|
__exitcall(omap3xxx_prm_exit);
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* OMAP3xxx Power/Reset Management (PRM) register definitions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2009, 2011-2012 Texas Instruments, Inc.
|
||||||
|
* Copyright (C) 2008-2010 Nokia Corporation
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* The PRM hardware modules on the OMAP2/3 are quite similar to each
|
||||||
|
* other. The PRM on OMAP4 has a new register layout, and is handled
|
||||||
|
* in a separate file.
|
||||||
|
*/
|
||||||
|
#ifndef __ARCH_ARM_MACH_OMAP2_PRM3XXX_H
|
||||||
|
#define __ARCH_ARM_MACH_OMAP2_PRM3XXX_H
|
||||||
|
|
||||||
|
#include "prcm-common.h"
|
||||||
|
#include "prm.h"
|
||||||
|
#include "prm2xxx_3xxx.h"
|
||||||
|
|
||||||
|
#define OMAP34XX_PRM_REGADDR(module, reg) \
|
||||||
|
OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE + (module) + (reg))
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OMAP3-specific global PRM registers
|
||||||
|
* Use __raw_{read,write}l() with these registers.
|
||||||
|
*
|
||||||
|
* With a few exceptions, these are the register names beginning with
|
||||||
|
* PRM_* on 34xx. (The exceptions are the IRQSTATUS and IRQENABLE
|
||||||
|
* bits.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define OMAP3_PRM_REVISION_OFFSET 0x0004
|
||||||
|
#define OMAP3430_PRM_REVISION OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0004)
|
||||||
|
#define OMAP3_PRM_SYSCONFIG_OFFSET 0x0014
|
||||||
|
#define OMAP3430_PRM_SYSCONFIG OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0014)
|
||||||
|
|
||||||
|
#define OMAP3_PRM_IRQSTATUS_MPU_OFFSET 0x0018
|
||||||
|
#define OMAP3430_PRM_IRQSTATUS_MPU OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0018)
|
||||||
|
#define OMAP3_PRM_IRQENABLE_MPU_OFFSET 0x001c
|
||||||
|
#define OMAP3430_PRM_IRQENABLE_MPU OMAP34XX_PRM_REGADDR(OCP_MOD, 0x001c)
|
||||||
|
|
||||||
|
|
||||||
|
#define OMAP3_PRM_VC_SMPS_SA_OFFSET 0x0020
|
||||||
|
#define OMAP3430_PRM_VC_SMPS_SA OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0020)
|
||||||
|
#define OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET 0x0024
|
||||||
|
#define OMAP3430_PRM_VC_SMPS_VOL_RA OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0024)
|
||||||
|
#define OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET 0x0028
|
||||||
|
#define OMAP3430_PRM_VC_SMPS_CMD_RA OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0028)
|
||||||
|
#define OMAP3_PRM_VC_CMD_VAL_0_OFFSET 0x002c
|
||||||
|
#define OMAP3430_PRM_VC_CMD_VAL_0 OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x002c)
|
||||||
|
#define OMAP3_PRM_VC_CMD_VAL_1_OFFSET 0x0030
|
||||||
|
#define OMAP3430_PRM_VC_CMD_VAL_1 OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0030)
|
||||||
|
#define OMAP3_PRM_VC_CH_CONF_OFFSET 0x0034
|
||||||
|
#define OMAP3430_PRM_VC_CH_CONF OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0034)
|
||||||
|
#define OMAP3_PRM_VC_I2C_CFG_OFFSET 0x0038
|
||||||
|
#define OMAP3430_PRM_VC_I2C_CFG OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0038)
|
||||||
|
#define OMAP3_PRM_VC_BYPASS_VAL_OFFSET 0x003c
|
||||||
|
#define OMAP3430_PRM_VC_BYPASS_VAL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x003c)
|
||||||
|
#define OMAP3_PRM_RSTCTRL_OFFSET 0x0050
|
||||||
|
#define OMAP3430_PRM_RSTCTRL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0050)
|
||||||
|
#define OMAP3_PRM_RSTTIME_OFFSET 0x0054
|
||||||
|
#define OMAP3430_PRM_RSTTIME OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0054)
|
||||||
|
#define OMAP3_PRM_RSTST_OFFSET 0x0058
|
||||||
|
#define OMAP3430_PRM_RSTST OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0058)
|
||||||
|
#define OMAP3_PRM_VOLTCTRL_OFFSET 0x0060
|
||||||
|
#define OMAP3430_PRM_VOLTCTRL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0060)
|
||||||
|
#define OMAP3_PRM_SRAM_PCHARGE_OFFSET 0x0064
|
||||||
|
#define OMAP3430_PRM_SRAM_PCHARGE OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0064)
|
||||||
|
#define OMAP3_PRM_CLKSRC_CTRL_OFFSET 0x0070
|
||||||
|
#define OMAP3430_PRM_CLKSRC_CTRL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0070)
|
||||||
|
#define OMAP3_PRM_VOLTSETUP1_OFFSET 0x0090
|
||||||
|
#define OMAP3430_PRM_VOLTSETUP1 OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0090)
|
||||||
|
#define OMAP3_PRM_VOLTOFFSET_OFFSET 0x0094
|
||||||
|
#define OMAP3430_PRM_VOLTOFFSET OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0094)
|
||||||
|
#define OMAP3_PRM_CLKSETUP_OFFSET 0x0098
|
||||||
|
#define OMAP3430_PRM_CLKSETUP OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0098)
|
||||||
|
#define OMAP3_PRM_POLCTRL_OFFSET 0x009c
|
||||||
|
#define OMAP3430_PRM_POLCTRL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x009c)
|
||||||
|
#define OMAP3_PRM_VOLTSETUP2_OFFSET 0x00a0
|
||||||
|
#define OMAP3430_PRM_VOLTSETUP2 OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00a0)
|
||||||
|
#define OMAP3_PRM_VP1_CONFIG_OFFSET 0x00b0
|
||||||
|
#define OMAP3430_PRM_VP1_CONFIG OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b0)
|
||||||
|
#define OMAP3_PRM_VP1_VSTEPMIN_OFFSET 0x00b4
|
||||||
|
#define OMAP3430_PRM_VP1_VSTEPMIN OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b4)
|
||||||
|
#define OMAP3_PRM_VP1_VSTEPMAX_OFFSET 0x00b8
|
||||||
|
#define OMAP3430_PRM_VP1_VSTEPMAX OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b8)
|
||||||
|
#define OMAP3_PRM_VP1_VLIMITTO_OFFSET 0x00bc
|
||||||
|
#define OMAP3430_PRM_VP1_VLIMITTO OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00bc)
|
||||||
|
#define OMAP3_PRM_VP1_VOLTAGE_OFFSET 0x00c0
|
||||||
|
#define OMAP3430_PRM_VP1_VOLTAGE OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c0)
|
||||||
|
#define OMAP3_PRM_VP1_STATUS_OFFSET 0x00c4
|
||||||
|
#define OMAP3430_PRM_VP1_STATUS OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c4)
|
||||||
|
#define OMAP3_PRM_VP2_CONFIG_OFFSET 0x00d0
|
||||||
|
#define OMAP3430_PRM_VP2_CONFIG OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d0)
|
||||||
|
#define OMAP3_PRM_VP2_VSTEPMIN_OFFSET 0x00d4
|
||||||
|
#define OMAP3430_PRM_VP2_VSTEPMIN OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d4)
|
||||||
|
#define OMAP3_PRM_VP2_VSTEPMAX_OFFSET 0x00d8
|
||||||
|
#define OMAP3430_PRM_VP2_VSTEPMAX OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d8)
|
||||||
|
#define OMAP3_PRM_VP2_VLIMITTO_OFFSET 0x00dc
|
||||||
|
#define OMAP3430_PRM_VP2_VLIMITTO OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00dc)
|
||||||
|
#define OMAP3_PRM_VP2_VOLTAGE_OFFSET 0x00e0
|
||||||
|
#define OMAP3430_PRM_VP2_VOLTAGE OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e0)
|
||||||
|
#define OMAP3_PRM_VP2_STATUS_OFFSET 0x00e4
|
||||||
|
#define OMAP3430_PRM_VP2_STATUS OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e4)
|
||||||
|
|
||||||
|
#define OMAP3_PRM_CLKSEL_OFFSET 0x0040
|
||||||
|
#define OMAP3430_PRM_CLKSEL OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0040)
|
||||||
|
#define OMAP3_PRM_CLKOUT_CTRL_OFFSET 0x0070
|
||||||
|
#define OMAP3430_PRM_CLKOUT_CTRL OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
|
||||||
|
|
||||||
|
/* OMAP3 specific register offsets */
|
||||||
|
#define OMAP3430ES2_PM_WKEN3 0x00f0
|
||||||
|
#define OMAP3430ES2_PM_WKST3 0x00b8
|
||||||
|
|
||||||
|
#define OMAP3430_PM_MPUGRPSEL 0x00a4
|
||||||
|
#define OMAP3430_PM_MPUGRPSEL1 OMAP3430_PM_MPUGRPSEL
|
||||||
|
#define OMAP3430ES2_PM_MPUGRPSEL3 0x00f8
|
||||||
|
|
||||||
|
#define OMAP3430_PM_IVAGRPSEL 0x00a8
|
||||||
|
#define OMAP3430_PM_IVAGRPSEL1 OMAP3430_PM_IVAGRPSEL
|
||||||
|
#define OMAP3430ES2_PM_IVAGRPSEL3 0x00f4
|
||||||
|
|
||||||
|
#define OMAP3430_PM_PREPWSTST 0x00e8
|
||||||
|
|
||||||
|
#define OMAP3430_PRM_IRQSTATUS_IVA2 0x00f8
|
||||||
|
#define OMAP3430_PRM_IRQENABLE_IVA2 0x00fc
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLER__
|
||||||
|
|
||||||
|
/* OMAP3-specific VP functions */
|
||||||
|
u32 omap3_prm_vp_check_txdone(u8 vp_id);
|
||||||
|
void omap3_prm_vp_clear_txdone(u8 vp_id);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OMAP3 access functions for voltage controller (VC) and
|
||||||
|
* voltage proccessor (VP) in the PRM.
|
||||||
|
*/
|
||||||
|
extern u32 omap3_prm_vcvp_read(u8 offset);
|
||||||
|
extern void omap3_prm_vcvp_write(u32 val, u8 offset);
|
||||||
|
extern u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
|
||||||
|
|
||||||
|
extern void omap3xxx_prm_reconfigure_io_chain(void);
|
||||||
|
|
||||||
|
/* PRM interrupt-related functions */
|
||||||
|
extern void omap3xxx_prm_read_pending_irqs(unsigned long *events);
|
||||||
|
extern void omap3xxx_prm_ocp_barrier(void);
|
||||||
|
extern void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask);
|
||||||
|
extern void omap3xxx_prm_restore_irqen(u32 *saved_mask);
|
||||||
|
|
||||||
|
extern u32 omap3xxx_prm_get_reset_sources(void);
|
||||||
|
|
||||||
|
#endif /* __ASSEMBLER */
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* OMAP4 PRM module functions
|
* OMAP4 PRM module functions
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Texas Instruments, Inc.
|
* Copyright (C) 2011-2012 Texas Instruments, Inc.
|
||||||
* Copyright (C) 2010 Nokia Corporation
|
* Copyright (C) 2010 Nokia Corporation
|
||||||
* Benoît Cousson
|
* Benoît Cousson
|
||||||
* 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
|
||||||
@@ -27,6 +28,9 @@
|
|||||||
#include "prm-regbits-44xx.h"
|
#include "prm-regbits-44xx.h"
|
||||||
#include "prcm44xx.h"
|
#include "prcm44xx.h"
|
||||||
#include "prminst44xx.h"
|
#include "prminst44xx.h"
|
||||||
|
#include "powerdomain.h"
|
||||||
|
|
||||||
|
/* Static data */
|
||||||
|
|
||||||
static const struct omap_prcm_irq omap4_prcm_irqs[] = {
|
static const struct omap_prcm_irq omap4_prcm_irqs[] = {
|
||||||
OMAP_PRCM_IRQ("wkup", 0, 0),
|
OMAP_PRCM_IRQ("wkup", 0, 0),
|
||||||
@@ -46,6 +50,33 @@ static struct omap_prcm_irq_setup omap4_prcm_irq_setup = {
|
|||||||
.restore_irqen = &omap44xx_prm_restore_irqen,
|
.restore_irqen = &omap44xx_prm_restore_irqen,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* omap44xx_prm_reset_src_map - map from bits in the PRM_RSTST
|
||||||
|
* hardware register (which are specific to OMAP44xx SoCs) to reset
|
||||||
|
* source ID bit shifts (which is an OMAP SoC-independent
|
||||||
|
* enumeration)
|
||||||
|
*/
|
||||||
|
static struct prm_reset_src_map omap44xx_prm_reset_src_map[] = {
|
||||||
|
{ OMAP4430_RST_GLOBAL_WARM_SW_SHIFT,
|
||||||
|
OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP4430_RST_GLOBAL_COLD_SW_SHIFT,
|
||||||
|
OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP4430_MPU_SECURITY_VIOL_RST_SHIFT,
|
||||||
|
OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP4430_MPU_WDT_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP4430_SECURE_WDT_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP4430_EXTERNAL_WARM_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP4430_VDD_MPU_VOLT_MGR_RST_SHIFT,
|
||||||
|
OMAP_VDD_MPU_VM_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP4430_VDD_IVA_VOLT_MGR_RST_SHIFT,
|
||||||
|
OMAP_VDD_IVA_VM_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP4430_VDD_CORE_VOLT_MGR_RST_SHIFT,
|
||||||
|
OMAP_VDD_CORE_VM_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP4430_ICEPICK_RST_SHIFT, OMAP_ICEPICK_RST_SRC_ID_SHIFT },
|
||||||
|
{ OMAP4430_C2C_RST_SHIFT, OMAP_C2C_RST_SRC_ID_SHIFT },
|
||||||
|
{ -1, -1 },
|
||||||
|
};
|
||||||
|
|
||||||
/* PRM low-level functions */
|
/* PRM low-level functions */
|
||||||
|
|
||||||
/* Read a register in a CM/PRM instance in the PRM module */
|
/* Read a register in a CM/PRM instance in the PRM module */
|
||||||
@@ -291,12 +322,324 @@ static void __init omap44xx_prm_enable_io_wakeup(void)
|
|||||||
OMAP4_PRM_IO_PMCTRL_OFFSET);
|
OMAP4_PRM_IO_PMCTRL_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init omap4xxx_prcm_init(void)
|
/**
|
||||||
|
* omap44xx_prm_read_reset_sources - return the last SoC reset source
|
||||||
|
*
|
||||||
|
* Return a u32 representing the last reset sources of the SoC. The
|
||||||
|
* returned reset source bits are standardized across OMAP SoCs.
|
||||||
|
*/
|
||||||
|
static u32 omap44xx_prm_read_reset_sources(void)
|
||||||
{
|
{
|
||||||
if (cpu_is_omap44xx()) {
|
struct prm_reset_src_map *p;
|
||||||
omap44xx_prm_enable_io_wakeup();
|
u32 r = 0;
|
||||||
return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
|
u32 v;
|
||||||
|
|
||||||
|
v = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
|
||||||
|
OMAP4_RM_RSTST);
|
||||||
|
|
||||||
|
p = omap44xx_prm_reset_src_map;
|
||||||
|
while (p->reg_shift >= 0 && p->std_shift >= 0) {
|
||||||
|
if (v & (1 << p->reg_shift))
|
||||||
|
r |= 1 << p->std_shift;
|
||||||
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Powerdomain low-level functions */
|
||||||
|
|
||||||
|
static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
|
||||||
|
{
|
||||||
|
omap4_prminst_rmw_inst_reg_bits(OMAP_POWERSTATE_MASK,
|
||||||
|
(pwrst << OMAP_POWERSTATE_SHIFT),
|
||||||
|
pwrdm->prcm_partition,
|
||||||
|
pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
subsys_initcall(omap4xxx_prcm_init);
|
|
||||||
|
static int omap4_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
|
||||||
|
OMAP4_PM_PWSTCTRL);
|
||||||
|
v &= OMAP_POWERSTATE_MASK;
|
||||||
|
v >>= OMAP_POWERSTATE_SHIFT;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap4_pwrdm_read_pwrst(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
|
||||||
|
OMAP4_PM_PWSTST);
|
||||||
|
v &= OMAP_POWERSTATEST_MASK;
|
||||||
|
v >>= OMAP_POWERSTATEST_SHIFT;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap4_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
|
||||||
|
OMAP4_PM_PWSTST);
|
||||||
|
v &= OMAP4430_LASTPOWERSTATEENTERED_MASK;
|
||||||
|
v >>= OMAP4430_LASTPOWERSTATEENTERED_SHIFT;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap4_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOWPOWERSTATECHANGE_MASK,
|
||||||
|
(1 << OMAP4430_LOWPOWERSTATECHANGE_SHIFT),
|
||||||
|
pwrdm->prcm_partition,
|
||||||
|
pwrdm->prcm_offs, OMAP4_PM_PWSTCTRL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap4_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
omap4_prminst_rmw_inst_reg_bits(OMAP4430_LASTPOWERSTATEENTERED_MASK,
|
||||||
|
OMAP4430_LASTPOWERSTATEENTERED_MASK,
|
||||||
|
pwrdm->prcm_partition,
|
||||||
|
pwrdm->prcm_offs, OMAP4_PM_PWSTST);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap4_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = pwrst << __ffs(OMAP4430_LOGICRETSTATE_MASK);
|
||||||
|
omap4_prminst_rmw_inst_reg_bits(OMAP4430_LOGICRETSTATE_MASK, v,
|
||||||
|
pwrdm->prcm_partition, pwrdm->prcm_offs,
|
||||||
|
OMAP4_PM_PWSTCTRL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap4_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
|
||||||
|
u8 pwrst)
|
||||||
|
{
|
||||||
|
u32 m;
|
||||||
|
|
||||||
|
m = omap2_pwrdm_get_mem_bank_onstate_mask(bank);
|
||||||
|
|
||||||
|
omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
|
||||||
|
pwrdm->prcm_partition, pwrdm->prcm_offs,
|
||||||
|
OMAP4_PM_PWSTCTRL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap4_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
|
||||||
|
u8 pwrst)
|
||||||
|
{
|
||||||
|
u32 m;
|
||||||
|
|
||||||
|
m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
|
||||||
|
|
||||||
|
omap4_prminst_rmw_inst_reg_bits(m, (pwrst << __ffs(m)),
|
||||||
|
pwrdm->prcm_partition, pwrdm->prcm_offs,
|
||||||
|
OMAP4_PM_PWSTCTRL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap4_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
|
||||||
|
OMAP4_PM_PWSTST);
|
||||||
|
v &= OMAP4430_LOGICSTATEST_MASK;
|
||||||
|
v >>= OMAP4430_LOGICSTATEST_SHIFT;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
|
||||||
|
OMAP4_PM_PWSTCTRL);
|
||||||
|
v &= OMAP4430_LOGICRETSTATE_MASK;
|
||||||
|
v >>= OMAP4430_LOGICRETSTATE_SHIFT;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* omap4_pwrdm_read_prev_logic_pwrst - read the previous logic powerstate
|
||||||
|
* @pwrdm: struct powerdomain * to read the state for
|
||||||
|
*
|
||||||
|
* Reads the previous logic powerstate for a powerdomain. This
|
||||||
|
* function must determine the previous logic powerstate by first
|
||||||
|
* checking the previous powerstate for the domain. If that was OFF,
|
||||||
|
* then logic has been lost. If previous state was RETENTION, the
|
||||||
|
* function reads the setting for the next retention logic state to
|
||||||
|
* see the actual value. In every other case, the logic is
|
||||||
|
* retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
|
||||||
|
* depending whether the logic was retained or not.
|
||||||
|
*/
|
||||||
|
static int omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
int state;
|
||||||
|
|
||||||
|
state = omap4_pwrdm_read_prev_pwrst(pwrdm);
|
||||||
|
|
||||||
|
if (state == PWRDM_POWER_OFF)
|
||||||
|
return PWRDM_POWER_OFF;
|
||||||
|
|
||||||
|
if (state != PWRDM_POWER_RET)
|
||||||
|
return PWRDM_POWER_RET;
|
||||||
|
|
||||||
|
return omap4_pwrdm_read_logic_retst(pwrdm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
|
||||||
|
{
|
||||||
|
u32 m, v;
|
||||||
|
|
||||||
|
m = omap2_pwrdm_get_mem_bank_stst_mask(bank);
|
||||||
|
|
||||||
|
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
|
||||||
|
OMAP4_PM_PWSTST);
|
||||||
|
v &= m;
|
||||||
|
v >>= __ffs(m);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
|
||||||
|
{
|
||||||
|
u32 m, v;
|
||||||
|
|
||||||
|
m = omap2_pwrdm_get_mem_bank_retst_mask(bank);
|
||||||
|
|
||||||
|
v = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, pwrdm->prcm_offs,
|
||||||
|
OMAP4_PM_PWSTCTRL);
|
||||||
|
v &= m;
|
||||||
|
v >>= __ffs(m);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* omap4_pwrdm_read_prev_mem_pwrst - reads the previous memory powerstate
|
||||||
|
* @pwrdm: struct powerdomain * to read mem powerstate for
|
||||||
|
* @bank: memory bank index
|
||||||
|
*
|
||||||
|
* Reads the previous memory powerstate for a powerdomain. This
|
||||||
|
* function must determine the previous memory powerstate by first
|
||||||
|
* checking the previous powerstate for the domain. If that was OFF,
|
||||||
|
* then logic has been lost. If previous state was RETENTION, the
|
||||||
|
* function reads the setting for the next memory retention state to
|
||||||
|
* see the actual value. In every other case, the logic is
|
||||||
|
* retained. Returns either PWRDM_POWER_OFF or PWRDM_POWER_RET
|
||||||
|
* depending whether logic was retained or not.
|
||||||
|
*/
|
||||||
|
static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
|
||||||
|
{
|
||||||
|
int state;
|
||||||
|
|
||||||
|
state = omap4_pwrdm_read_prev_pwrst(pwrdm);
|
||||||
|
|
||||||
|
if (state == PWRDM_POWER_OFF)
|
||||||
|
return PWRDM_POWER_OFF;
|
||||||
|
|
||||||
|
if (state != PWRDM_POWER_RET)
|
||||||
|
return PWRDM_POWER_RET;
|
||||||
|
|
||||||
|
return omap4_pwrdm_read_mem_retst(pwrdm, bank);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
|
||||||
|
{
|
||||||
|
u32 c = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* REVISIT: pwrdm_wait_transition() may be better implemented
|
||||||
|
* via a callback and a periodic timer check -- how long do we expect
|
||||||
|
* powerdomain transitions to take?
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* XXX Is this udelay() value meaningful? */
|
||||||
|
while ((omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
|
||||||
|
pwrdm->prcm_offs,
|
||||||
|
OMAP4_PM_PWSTST) &
|
||||||
|
OMAP_INTRANSITION_MASK) &&
|
||||||
|
(c++ < PWRDM_TRANSITION_BAILOUT))
|
||||||
|
udelay(1);
|
||||||
|
|
||||||
|
if (c > PWRDM_TRANSITION_BAILOUT) {
|
||||||
|
pr_err("powerdomain: %s: waited too long to complete transition\n",
|
||||||
|
pwrdm->name);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_debug("powerdomain: completed transition in %d loops\n", c);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pwrdm_ops omap4_pwrdm_operations = {
|
||||||
|
.pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst,
|
||||||
|
.pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst,
|
||||||
|
.pwrdm_read_pwrst = omap4_pwrdm_read_pwrst,
|
||||||
|
.pwrdm_read_prev_pwrst = omap4_pwrdm_read_prev_pwrst,
|
||||||
|
.pwrdm_set_lowpwrstchange = omap4_pwrdm_set_lowpwrstchange,
|
||||||
|
.pwrdm_clear_all_prev_pwrst = omap4_pwrdm_clear_all_prev_pwrst,
|
||||||
|
.pwrdm_set_logic_retst = omap4_pwrdm_set_logic_retst,
|
||||||
|
.pwrdm_read_logic_pwrst = omap4_pwrdm_read_logic_pwrst,
|
||||||
|
.pwrdm_read_prev_logic_pwrst = omap4_pwrdm_read_prev_logic_pwrst,
|
||||||
|
.pwrdm_read_logic_retst = omap4_pwrdm_read_logic_retst,
|
||||||
|
.pwrdm_read_mem_pwrst = omap4_pwrdm_read_mem_pwrst,
|
||||||
|
.pwrdm_read_mem_retst = omap4_pwrdm_read_mem_retst,
|
||||||
|
.pwrdm_read_prev_mem_pwrst = omap4_pwrdm_read_prev_mem_pwrst,
|
||||||
|
.pwrdm_set_mem_onst = omap4_pwrdm_set_mem_onst,
|
||||||
|
.pwrdm_set_mem_retst = omap4_pwrdm_set_mem_retst,
|
||||||
|
.pwrdm_wait_transition = omap4_pwrdm_wait_transition,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX document
|
||||||
|
*/
|
||||||
|
static struct prm_ll_data omap44xx_prm_ll_data = {
|
||||||
|
.read_reset_sources = &omap44xx_prm_read_reset_sources,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init omap44xx_prm_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!cpu_is_omap44xx())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = prm_register(&omap44xx_prm_ll_data);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
omap44xx_prm_enable_io_wakeup();
|
||||||
|
|
||||||
|
return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
|
||||||
|
}
|
||||||
|
subsys_initcall(omap44xx_prm_init);
|
||||||
|
|
||||||
|
static void __exit omap44xx_prm_exit(void)
|
||||||
|
{
|
||||||
|
if (!cpu_is_omap44xx())
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Should never happen */
|
||||||
|
WARN(prm_unregister(&omap44xx_prm_ll_data),
|
||||||
|
"%s: prm_ll_data function pointer mismatch\n", __func__);
|
||||||
|
}
|
||||||
|
__exitcall(omap44xx_prm_exit);
|
||||||
|
|||||||
@@ -771,6 +771,8 @@ extern void omap44xx_prm_ocp_barrier(void);
|
|||||||
extern void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask);
|
extern void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask);
|
||||||
extern void omap44xx_prm_restore_irqen(u32 *saved_mask);
|
extern void omap44xx_prm_restore_irqen(u32 *saved_mask);
|
||||||
|
|
||||||
|
extern u32 omap44xx_prm_get_reset_sources(void);
|
||||||
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
#include <plat/prcm.h>
|
#include <plat/prcm.h>
|
||||||
|
|
||||||
#include "prm2xxx_3xxx.h"
|
#include "prm2xxx_3xxx.h"
|
||||||
|
#include "prm2xxx.h"
|
||||||
|
#include "prm3xxx.h"
|
||||||
#include "prm44xx.h"
|
#include "prm44xx.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -53,6 +55,13 @@ static struct irq_chip_generic **prcm_irq_chips;
|
|||||||
*/
|
*/
|
||||||
static struct omap_prcm_irq_setup *prcm_irq_setup;
|
static struct omap_prcm_irq_setup *prcm_irq_setup;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* prm_ll_data: function pointers to SoC-specific implementations of
|
||||||
|
* common PRM functions
|
||||||
|
*/
|
||||||
|
static struct prm_ll_data null_prm_ll_data;
|
||||||
|
static struct prm_ll_data *prm_ll_data = &null_prm_ll_data;
|
||||||
|
|
||||||
/* Private functions */
|
/* Private functions */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -319,64 +328,71 @@ err:
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Stubbed functions so that common files continue to build when
|
* prm_read_reset_sources - return the sources of the SoC's last reset
|
||||||
* custom builds are used
|
*
|
||||||
* XXX These are temporary and should be removed at the earliest possible
|
* Return a u32 bitmask representing the reset sources that caused the
|
||||||
* opportunity
|
* SoC to reset. The low-level per-SoC functions called by this
|
||||||
|
* function remap the SoC-specific reset source bits into an
|
||||||
|
* OMAP-common set of reset source bits, defined in
|
||||||
|
* arch/arm/mach-omap2/prm.h. Returns the standardized reset source
|
||||||
|
* u32 bitmask from the hardware upon success, or returns (1 <<
|
||||||
|
* OMAP_UNKNOWN_RST_SRC_ID_SHIFT) if no low-level read_reset_sources()
|
||||||
|
* function was registered.
|
||||||
*/
|
*/
|
||||||
u32 __weak omap2_prm_read_mod_reg(s16 module, u16 idx)
|
u32 prm_read_reset_sources(void)
|
||||||
{
|
{
|
||||||
WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
|
u32 ret = 1 << OMAP_UNKNOWN_RST_SRC_ID_SHIFT;
|
||||||
|
|
||||||
|
if (prm_ll_data->read_reset_sources)
|
||||||
|
ret = prm_ll_data->read_reset_sources();
|
||||||
|
else
|
||||||
|
WARN_ONCE(1, "prm: %s: no mapping function defined for reset sources\n", __func__);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prm_register - register per-SoC low-level data with the PRM
|
||||||
|
* @pld: low-level per-SoC OMAP PRM data & function pointers to register
|
||||||
|
*
|
||||||
|
* Register per-SoC low-level OMAP PRM data and function pointers with
|
||||||
|
* the OMAP PRM common interface. The caller must keep the data
|
||||||
|
* pointed to by @pld valid until it calls prm_unregister() and
|
||||||
|
* it returns successfully. Returns 0 upon success, -EINVAL if @pld
|
||||||
|
* is NULL, or -EEXIST if prm_register() has already been called
|
||||||
|
* without an intervening prm_unregister().
|
||||||
|
*/
|
||||||
|
int prm_register(struct prm_ll_data *pld)
|
||||||
|
{
|
||||||
|
if (!pld)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (prm_ll_data != &null_prm_ll_data)
|
||||||
|
return -EEXIST;
|
||||||
|
|
||||||
|
prm_ll_data = pld;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __weak omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx)
|
/**
|
||||||
|
* prm_unregister - unregister per-SoC low-level data & function pointers
|
||||||
|
* @pld: low-level per-SoC OMAP PRM data & function pointers to unregister
|
||||||
|
*
|
||||||
|
* Unregister per-SoC low-level OMAP PRM data and function pointers
|
||||||
|
* that were previously registered with prm_register(). The
|
||||||
|
* caller may not destroy any of the data pointed to by @pld until
|
||||||
|
* this function returns successfully. Returns 0 upon success, or
|
||||||
|
* -EINVAL if @pld is NULL or if @pld does not match the struct
|
||||||
|
* prm_ll_data * previously registered by prm_register().
|
||||||
|
*/
|
||||||
|
int prm_unregister(struct prm_ll_data *pld)
|
||||||
{
|
{
|
||||||
WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
|
if (!pld || prm_ll_data != pld)
|
||||||
}
|
return -EINVAL;
|
||||||
|
|
||||||
|
prm_ll_data = &null_prm_ll_data;
|
||||||
|
|
||||||
u32 __weak omap2_prm_rmw_mod_reg_bits(u32 mask, u32 bits,
|
|
||||||
s16 module, s16 idx)
|
|
||||||
{
|
|
||||||
WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 __weak omap2_prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
|
|
||||||
{
|
|
||||||
WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 __weak omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
|
|
||||||
{
|
|
||||||
WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 __weak omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
|
|
||||||
{
|
|
||||||
WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int __weak omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift)
|
|
||||||
{
|
|
||||||
WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int __weak omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
|
|
||||||
{
|
|
||||||
WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int __weak omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift,
|
|
||||||
u8 st_shift)
|
|
||||||
{
|
|
||||||
WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
#include "soc.h"
|
#include "soc.h"
|
||||||
#include "iomap.h"
|
#include "iomap.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "prm2xxx_3xxx.h"
|
#include "prm2xxx.h"
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
#include "sdrc.h"
|
#include "sdrc.h"
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,8 @@
|
|||||||
|
|
||||||
#include "omap34xx.h"
|
#include "omap34xx.h"
|
||||||
#include "iomap.h"
|
#include "iomap.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
#include "cm3xxx.h"
|
||||||
#include "prm2xxx_3xxx.h"
|
#include "prm3xxx.h"
|
||||||
#include "sdrc.h"
|
#include "sdrc.h"
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,8 @@
|
|||||||
|
|
||||||
#include "soc.h"
|
#include "soc.h"
|
||||||
#include "iomap.h"
|
#include "iomap.h"
|
||||||
#include "prm2xxx_3xxx.h"
|
#include "prm2xxx.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
#include "cm2xxx.h"
|
||||||
#include "sdrc.h"
|
#include "sdrc.h"
|
||||||
|
|
||||||
.text
|
.text
|
||||||
|
|||||||
@@ -34,8 +34,8 @@
|
|||||||
|
|
||||||
#include "soc.h"
|
#include "soc.h"
|
||||||
#include "iomap.h"
|
#include "iomap.h"
|
||||||
#include "prm2xxx_3xxx.h"
|
#include "prm2xxx.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
#include "cm2xxx.h"
|
||||||
#include "sdrc.h"
|
#include "sdrc.h"
|
||||||
|
|
||||||
.text
|
.text
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
#include "soc.h"
|
#include "soc.h"
|
||||||
#include "iomap.h"
|
#include "iomap.h"
|
||||||
#include "sdrc.h"
|
#include "sdrc.h"
|
||||||
#include "cm2xxx_3xxx.h"
|
#include "cm3xxx.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file needs be built unconditionally as ARM to interoperate correctly
|
* This file needs be built unconditionally as ARM to interoperate correctly
|
||||||
|
|||||||
Reference in New Issue
Block a user