diff options
| author | Tony Lindgren <tony@atomide.com> | 2012-10-24 17:05:59 -0700 | 
|---|---|---|
| committer | Tony Lindgren <tony@atomide.com> | 2012-10-24 17:05:59 -0700 | 
| commit | 8634155ef41d3a035f2ea0b6c5bed2806f2788bc (patch) | |
| tree | 6334a630abf196685803f17002fbf25d11babe17 | |
| parent | 6d02643d64b4440394ee462ea4b870c8506cd9e7 (diff) | |
| parent | 2bb2a5d30abb0dc99d074877bfad2056142c730b (diff) | |
| download | olio-linux-3.10-8634155ef41d3a035f2ea0b6c5bed2806f2788bc.tar.xz olio-linux-3.10-8634155ef41d3a035f2ea0b6c5bed2806f2788bc.zip  | |
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
49 files changed, 2740 insertions, 2089 deletions
diff --git a/arch/arm/mach-omap1/common.h b/arch/arm/mach-omap1/common.h index 26e19d3b792..d6ac18d04da 100644 --- a/arch/arm/mach-omap1/common.h +++ b/arch/arm/mach-omap1/common.h @@ -94,4 +94,6 @@ extern int ocpi_enable(void);  static inline int ocpi_enable(void) { return 0; }  #endif +extern int omap1_get_reset_sources(void); +  #endif /* __ARCH_ARM_MACH_OMAP1_COMMON_H */ diff --git a/arch/arm/mach-omap1/reset.c b/arch/arm/mach-omap1/reset.c index b1770910386..a0a9f97772e 100644 --- a/arch/arm/mach-omap1/reset.c +++ b/arch/arm/mach-omap1/reset.c @@ -10,6 +10,19 @@  #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)  {  	/* @@ -23,3 +36,28 @@ void omap1_restart(char mode, const char *cmd)  	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; +} diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 46d9071f093..ae87a3ea53a 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -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 \  	 omap_device.o -# INTCPS IP block support - XXX should be moved to drivers/ -obj-$(CONFIG_ARCH_OMAP2)		+= irq.o -obj-$(CONFIG_ARCH_OMAP3)		+= irq.o -obj-$(CONFIG_SOC_AM33XX)		+= irq.o +omap-2-3-common				= irq.o +hwmod-common				= omap_hwmod.o \ +					  omap_hwmod_common_data.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_OMAP3)		+= omap-smc.o omap-secure.o -obj-$(CONFIG_ARCH_OMAP4)		+= omap-smc.o omap-secure.o -obj-$(CONFIG_SOC_OMAP5)			+= omap-smc.o omap-secure.o +obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common) +obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common) +obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common) $(secure-common) +obj-$(CONFIG_SOC_AM33XX) += irq.o $(hwmod-common) +obj-$(CONFIG_SOC_OMAP5)	 += prm44xx.o $(hwmod-common) $(secure-common)  ifneq ($(CONFIG_SND_OMAP_SOC_MCBSP),)  obj-y += mcbsp.o  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  obj-$(CONFIG_SMP)			+= omap-smp.o omap-headsmp.o  obj-$(CONFIG_HOTPLUG_CPU)		+= omap-hotplug.o -obj-$(CONFIG_ARCH_OMAP4)		+= omap4-common.o omap-wakeupgen.o -obj-$(CONFIG_SOC_OMAP5)			+= omap4-common.o omap-wakeupgen.o +omap-4-5-common				=  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)  AFLAGS_omap-headsmp.o			:=-Wa,-march=armv7-a$(plus_sec) @@ -53,7 +59,6 @@ obj-$(CONFIG_ARCH_OMAP4)		+= mux44xx.o  # SMS/SDRC  obj-$(CONFIG_ARCH_OMAP2)		+= sdrc2xxx.o  # obj-$(CONFIG_ARCH_OMAP3)		+= sdrc3xxx.o -obj-$(CONFIG_SOC_HAS_OMAP2_SDRC)	+= sdrc.o  # OPP table initialization  ifeq ($(CONFIG_PM_OPP),y) @@ -64,15 +69,15 @@ endif  # Power Management  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_OMAP4)		+= pm44xx.o omap-mpuss-lowpower.o -obj-$(CONFIG_ARCH_OMAP4)		+= sleep44xx.o -obj-$(CONFIG_SOC_OMAP5)			+= omap-mpuss-lowpower.o sleep44xx.o +obj-$(CONFIG_SOC_OMAP5)			+= omap-mpuss-lowpower.o  obj-$(CONFIG_PM_DEBUG)			+= pm-debug.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_sleep34xx.o			:=-Wa,-march=armv7-a$(plus_sec) @@ -84,76 +89,82 @@ endif  endif  ifeq ($(CONFIG_CPU_IDLE),y) -obj-$(CONFIG_ARCH_OMAP3)		+= cpuidle34xx.o -obj-$(CONFIG_ARCH_OMAP4)		+= cpuidle44xx.o +obj-$(CONFIG_ARCH_OMAP3)                += cpuidle34xx.o +obj-$(CONFIG_ARCH_OMAP4)                += cpuidle44xx.o  endif  # PRCM -obj-y					+= prcm.o prm_common.o -obj-$(CONFIG_ARCH_OMAP2)		+= cm2xxx_3xxx.o prm2xxx_3xxx.o -obj-$(CONFIG_ARCH_OMAP3)		+= cm2xxx_3xxx.o prm2xxx_3xxx.o +obj-y					+= prcm.o prm_common.o cm_common.o +obj-$(CONFIG_ARCH_OMAP2)		+= prm2xxx_3xxx.o prm2xxx.o cm2xxx.o +obj-$(CONFIG_ARCH_OMAP3)		+= prm2xxx_3xxx.o prm3xxx.o cm3xxx.o  obj-$(CONFIG_ARCH_OMAP3)		+= vc3xxx_data.o vp3xxx_data.o  obj-$(CONFIG_SOC_AM33XX)		+= prm33xx.o cm33xx.o  omap-prcm-4-5-common			=  cminst44xx.o cm44xx.o prm44xx.o \  					   prcm_mpu44xx.o prminst44xx.o \ -					   vc44xx_data.o vp44xx_data.o \ -					   prm44xx.o +					   vc44xx_data.o vp44xx_data.o  obj-$(CONFIG_ARCH_OMAP4)		+= $(omap-prcm-4-5-common)  obj-$(CONFIG_SOC_OMAP5)			+= $(omap-prcm-4-5-common)  # 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_OMAP3)		+= $(voltagedomain-common)  obj-$(CONFIG_ARCH_OMAP3)		+= voltagedomains3xxx_data.o +obj-$(CONFIG_ARCH_OMAP4)		+= $(voltagedomain-common)  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 -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)		+= powerdomain2xxx_3xxx.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)		+= 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_SOC_AM33XX)		+= powerdomain33xx.o +obj-$(CONFIG_SOC_AM33XX)		+= $(powerdomain-common)  obj-$(CONFIG_SOC_AM33XX)		+= powerdomains33xx_data.o -obj-$(CONFIG_SOC_OMAP5)			+= powerdomain44xx.o +obj-$(CONFIG_SOC_OMAP5)			+= $(powerdomain-common)  # PRCM clockdomain control -obj-y					+= clockdomain.o -obj-$(CONFIG_ARCH_OMAP2)		+= clockdomain2xxx_3xxx.o +clockdomain-common			+= clockdomain.o +obj-$(CONFIG_ARCH_OMAP2)		+= $(clockdomain-common)  obj-$(CONFIG_ARCH_OMAP2)		+= clockdomains2xxx_3xxx_data.o  obj-$(CONFIG_SOC_OMAP2420)		+= clockdomains2420_data.o  obj-$(CONFIG_SOC_OMAP2430)		+= clockdomains2430_data.o -obj-$(CONFIG_ARCH_OMAP3)		+= clockdomain2xxx_3xxx.o +obj-$(CONFIG_ARCH_OMAP3)		+= $(clockdomain-common)  obj-$(CONFIG_ARCH_OMAP3)		+= clockdomains2xxx_3xxx_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_SOC_AM33XX)		+= clockdomain33xx.o +obj-$(CONFIG_SOC_AM33XX)		+= $(clockdomain-common)  obj-$(CONFIG_SOC_AM33XX)		+= clockdomains33xx_data.o -obj-$(CONFIG_SOC_OMAP5)			+= clockdomain44xx.o +obj-$(CONFIG_SOC_OMAP5)			+= $(clockdomain-common)  # Clock framework -obj-y					+= clock.o clock_common_data.o \ -					   clkt_dpll.o clkt_clksel.o -obj-$(CONFIG_ARCH_OMAP2)		+= clock2xxx.o -obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_dpllcore.o clkt2xxx_sys.o +obj-$(CONFIG_ARCH_OMAP2)		+= $(clock-common) clock2xxx.o +obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_sys.o +obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_dpllcore.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_dpll.o clkt_iclk.o  obj-$(CONFIG_SOC_OMAP2420)		+= clock2420_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)		+= 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_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_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  # 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  # 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_3xxx_ipblock_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_APOLLON)		+= board-apollon.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_OMAP3530_LV_SOM)	+= board-omap3logic.o -obj-$(CONFIG_MACH_OMAP3_TORPEDO)	+= board-omap3logic.o +obj-$(CONFIG_MACH_OMAP3530_LV_SOM)      += board-omap3logic.o +obj-$(CONFIG_MACH_OMAP3_TORPEDO)        += board-omap3logic.o  obj-$(CONFIG_MACH_ENCORE)		+= board-omap3encore.o  obj-$(CONFIG_MACH_OVERO)		+= board-overo.o  obj-$(CONFIG_MACH_OMAP3EVM)		+= board-omap3evm.o diff --git a/arch/arm/mach-omap2/clkt2xxx_apll.c b/arch/arm/mach-omap2/clkt2xxx_apll.c index 73a1414b89b..e3f0c1e262a 100644 --- a/arch/arm/mach-omap2/clkt2xxx_apll.c +++ b/arch/arm/mach-omap2/clkt2xxx_apll.c @@ -25,7 +25,7 @@  #include "clock.h"  #include "clock2xxx.h" -#include "cm2xxx_3xxx.h" +#include "cm2xxx.h"  #include "cm-regbits-24xx.h"  /* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */ diff --git a/arch/arm/mach-omap2/clkt2xxx_dpll.c b/arch/arm/mach-omap2/clkt2xxx_dpll.c index 0890ba94a28..399534c7843 100644 --- a/arch/arm/mach-omap2/clkt2xxx_dpll.c +++ b/arch/arm/mach-omap2/clkt2xxx_dpll.c @@ -15,7 +15,7 @@  #include <linux/io.h>  #include "clock.h" -#include "cm2xxx_3xxx.h" +#include "cm2xxx.h"  #include "cm-regbits-24xx.h"  /* Private functions */ diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 8b30759f8f9..9205ea7d8dd 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -33,7 +33,8 @@  #include "soc.h"  #include "clockdomain.h"  #include "clock.h" -#include "cm2xxx_3xxx.h" +#include "cm2xxx.h" +#include "cm3xxx.h"  #include "cm-regbits-24xx.h"  #include "cm-regbits-34xx.h" diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c index ff47a6c2611..da1e388f22f 100644 --- a/arch/arm/mach-omap2/clock2420_data.c +++ b/arch/arm/mach-omap2/clock2420_data.c @@ -23,7 +23,7 @@  #include "clock.h"  #include "clock2xxx.h"  #include "opp2xxx.h" -#include "cm2xxx_3xxx.h" +#include "cm2xxx.h"  #include "prm2xxx_3xxx.h"  #include "prm-regbits-24xx.h"  #include "cm-regbits-24xx.h" diff --git a/arch/arm/mach-omap2/clock2430.c b/arch/arm/mach-omap2/clock2430.c index 850f83e8954..e37df538bcd 100644 --- a/arch/arm/mach-omap2/clock2430.c +++ b/arch/arm/mach-omap2/clock2430.c @@ -25,7 +25,7 @@  #include "iomap.h"  #include "clock.h"  #include "clock2xxx.h" -#include "cm2xxx_3xxx.h" +#include "cm2xxx.h"  #include "cm-regbits-24xx.h"  /** diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c index cab8e9c52d6..c97dafef894 100644 --- a/arch/arm/mach-omap2/clock2430_data.c +++ b/arch/arm/mach-omap2/clock2430_data.c @@ -22,7 +22,7 @@  #include "clock.h"  #include "clock2xxx.h"  #include "opp2xxx.h" -#include "cm2xxx_3xxx.h" +#include "cm2xxx.h"  #include "prm2xxx_3xxx.h"  #include "prm-regbits-24xx.h"  #include "cm-regbits-24xx.h" diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index baaaa425870..e41819ba748 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -23,7 +23,7 @@  #include "clock.h"  #include "clock34xx.h" -#include "cm2xxx_3xxx.h" +#include "cm3xxx.h"  #include "cm-regbits-34xx.h"  /** diff --git a/arch/arm/mach-omap2/clock3517.c b/arch/arm/mach-omap2/clock3517.c index 80209050cd7..622ea050261 100644 --- a/arch/arm/mach-omap2/clock3517.c +++ b/arch/arm/mach-omap2/clock3517.c @@ -23,7 +23,7 @@  #include "clock.h"  #include "clock3517.h" -#include "cm2xxx_3xxx.h" +#include "cm3xxx.h"  #include "cm-regbits-34xx.h"  /* diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index a02d158568e..6cca1995395 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -28,7 +28,7 @@  #include "clock34xx.h"  #include "clock36xx.h"  #include "clock3517.h" -#include "cm2xxx_3xxx.h" +#include "cm3xxx.h"  #include "cm-regbits-34xx.h"  #include "prm2xxx_3xxx.h"  #include "prm-regbits-34xx.h" diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c deleted file mode 100644 index 3e4e9209b2d..00000000000 --- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c +++ /dev/null @@ -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, -}; diff --git a/arch/arm/mach-omap2/clockdomain33xx.c b/arch/arm/mach-omap2/clockdomain33xx.c deleted file mode 100644 index aca6388fad7..00000000000 --- a/arch/arm/mach-omap2/clockdomain33xx.c +++ /dev/null @@ -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, -}; diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c deleted file mode 100644 index 6fc6155625b..00000000000 --- a/arch/arm/mach-omap2/clockdomain44xx.c +++ /dev/null @@ -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, -}; diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h index f24e3f7a2bb..b3cee913dd6 100644 --- a/arch/arm/mach-omap2/cm.h +++ b/arch/arm/mach-omap2/cm.h @@ -33,4 +33,16 @@   */  #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 diff --git a/arch/arm/mach-omap2/cm2xxx.c b/arch/arm/mach-omap2/cm2xxx.c new file mode 100644 index 00000000000..64165013daf --- /dev/null +++ b/arch/arm/mach-omap2/cm2xxx.c @@ -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, +}; + diff --git a/arch/arm/mach-omap2/cm2xxx.h b/arch/arm/mach-omap2/cm2xxx.h new file mode 100644 index 00000000000..bce3c4be6d1 --- /dev/null +++ b/arch/arm/mach-omap2/cm2xxx.h @@ -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 diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.h b/arch/arm/mach-omap2/cm2xxx_3xxx.h index 57b2f3c2fbf..0e26bb1bf7e 100644 --- a/arch/arm/mach-omap2/cm2xxx_3xxx.h +++ b/arch/arm/mach-omap2/cm2xxx_3xxx.h @@ -18,27 +18,6 @@  #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   * Use cm_{read,write}_mod_reg() with these registers. @@ -57,6 +36,7 @@  #define CM_IDLEST					0x0020  #define CM_IDLEST1					CM_IDLEST  #define CM_IDLEST2					0x0024 +#define OMAP2430_CM_IDLEST3				0x0028  #define CM_AUTOIDLE					0x0030  #define CM_AUTOIDLE1					CM_AUTOIDLE  #define CM_AUTOIDLE2					0x0034 @@ -66,70 +46,55 @@  #define CM_CLKSEL2					0x0044  #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 - +#ifndef __ASSEMBLER__ -/* CM_IDLEST bit field values to indicate deasserted IdleReq */ +#include <linux/io.h> -#define OMAP24XX_CM_IDLEST_VAL				0 -#define OMAP34XX_CM_IDLEST_VAL				1 +static inline u32 omap2_cm_read_mod_reg(s16 module, u16 idx) +{ +	return __raw_readl(cm_base + module + idx); +} +static inline void omap2_cm_write_mod_reg(u32 val, s16 module, u16 idx) +{ +	__raw_writel(val, cm_base + module + idx); +} -/* Clock management domain register get/set */ +/* Read-modify-write a register in a CM module. Caller must lock */ +static inline u32 omap2_cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, +					    s16 idx) +{ +	u32 v; -#ifndef __ASSEMBLER__ +	v = omap2_cm_read_mod_reg(module, idx); +	v &= ~mask; +	v |= bits; +	omap2_cm_write_mod_reg(v, module, idx); -extern u32 omap2_cm_read_mod_reg(s16 module, u16 idx); -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); +	return v; +} -extern int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, -				      u8 idlest_shift); -extern u32 omap2_cm_set_mod_reg_bits(u32 bits, s16 module, s16 idx); -extern u32 omap2_cm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx); +/* 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; -extern bool omap2_cm_is_clkdm_in_hwsup(s16 module, u32 mask); -extern void omap2xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask); -extern void omap2xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask); +	v = omap2_cm_read_mod_reg(domain, idx); +	v &= mask; +	v >>= __ffs(mask); -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); +	return v; +} -extern void omap2xxx_cm_set_dpll_disable_autoidle(void); -extern void omap2xxx_cm_set_dpll_auto_low_power_stop(void); +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); +} -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); +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 @@ -147,10 +112,4 @@ extern void omap2xxx_cm_set_apll96_auto_low_power_stop(void);  #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 diff --git a/arch/arm/mach-omap2/cm33xx.c b/arch/arm/mach-omap2/cm33xx.c index b4938abf28c..b2dfcd77719 100644 --- a/arch/arm/mach-omap2/cm33xx.c +++ b/arch/arm/mach-omap2/cm33xx.c @@ -24,6 +24,7 @@  #include "../plat-omap/common.h" +#include "clockdomain.h"  #include "cm.h"  #include "cm33xx.h"  #include "cm-regbits-34xx.h" @@ -311,3 +312,58 @@ void am33xx_cm_module_disable(u16 inst, s16 cdoffs, u16 clkctrl_offs)  	v &= ~AM33XX_MODULEMODE_MASK;  	am33xx_cm_write_reg(v, inst, clkctrl_offs);  } + +/* + * Clockdomain low-level functions + */ + +static int am33xx_clkdm_sleep(struct clockdomain *clkdm) +{ +	am33xx_cm_clkdm_force_sleep(clkdm->cm_inst, clkdm->clkdm_offs); +	return 0; +} + +static int am33xx_clkdm_wakeup(struct clockdomain *clkdm) +{ +	am33xx_cm_clkdm_force_wakeup(clkdm->cm_inst, clkdm->clkdm_offs); +	return 0; +} + +static void am33xx_clkdm_allow_idle(struct clockdomain *clkdm) +{ +	am33xx_cm_clkdm_enable_hwsup(clkdm->cm_inst, clkdm->clkdm_offs); +} + +static void am33xx_clkdm_deny_idle(struct clockdomain *clkdm) +{ +	am33xx_cm_clkdm_disable_hwsup(clkdm->cm_inst, clkdm->clkdm_offs); +} + +static int am33xx_clkdm_clk_enable(struct clockdomain *clkdm) +{ +	if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) +		return am33xx_clkdm_wakeup(clkdm); + +	return 0; +} + +static int am33xx_clkdm_clk_disable(struct clockdomain *clkdm) +{ +	bool hwsup = false; + +	hwsup = am33xx_cm_is_clkdm_in_hwsup(clkdm->cm_inst, clkdm->clkdm_offs); + +	if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) +		am33xx_clkdm_sleep(clkdm); + +	return 0; +} + +struct clkdm_ops am33xx_clkdm_operations = { +	.clkdm_sleep		= am33xx_clkdm_sleep, +	.clkdm_wakeup		= am33xx_clkdm_wakeup, +	.clkdm_allow_idle	= am33xx_clkdm_allow_idle, +	.clkdm_deny_idle	= am33xx_clkdm_deny_idle, +	.clkdm_clk_enable	= am33xx_clkdm_clk_enable, +	.clkdm_clk_disable	= am33xx_clkdm_clk_disable, +}; diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.c b/arch/arm/mach-omap2/cm3xxx.c index 7f07ab02a5b..8b03ec2f439 100644 --- a/arch/arm/mach-omap2/cm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/cm3xxx.c @@ -1,8 +1,10 @@  /* - * OMAP2/3 CM module functions + * OMAP3xxx 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 @@ -12,8 +14,6 @@  #include <linux/kernel.h>  #include <linux/types.h>  #include <linux/delay.h> -#include <linux/spinlock.h> -#include <linux/list.h>  #include <linux/errno.h>  #include <linux/err.h>  #include <linux/io.h> @@ -21,56 +21,16 @@  #include "soc.h"  #include "iomap.h"  #include "common.h" +#include "prm2xxx_3xxx.h"  #include "cm.h" -#include "cm2xxx_3xxx.h" -#include "cm-regbits-24xx.h" +#include "cm3xxx.h"  #include "cm-regbits-34xx.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 cm_idlest_offs[] = { -	CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3, OMAP24XX_CM_IDLEST4 +static const u8 omap3xxx_cm_idlest_offs[] = { +	CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3  }; -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);  } -bool omap2_cm_is_clkdm_in_hwsup(s16 module, u32 mask) +bool omap3xxx_cm_is_clkdm_in_hwsup(s16 module, u32 mask)  {  	u32 v; -	bool ret = 0; - -	BUG_ON(!cpu_is_omap24xx() && !cpu_is_omap34xx());  	v = omap2_cm_read_mod_reg(module, OMAP2_CM_CLKSTCTRL);  	v &= mask;  	v >>= __ffs(mask); -	if (cpu_is_omap24xx()) -		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); +	return (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? 1 : 0;  }  void omap3xxx_cm_clkdm_enable_hwsup(s16 module, u32 mask) @@ -135,109 +77,209 @@ void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask)  }  /* - * DPLL autoidle control + *   */ -static void _omap2xxx_set_dpll_autoidle(u8 m) +/** + * omap3xxx_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 omap3xxx_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift)  { -	u32 v; +	int ena = 0, i = 0; +	u8 cm_idlest_reg; +	u32 mask; + +	if (!idlest_id || (idlest_id > ARRAY_SIZE(omap3xxx_cm_idlest_offs))) +		return -EINVAL; + +	cm_idlest_reg = omap3xxx_cm_idlest_offs[idlest_id - 1]; -	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); +	mask = 1 << idlest_shift; +	ena = 0; + +	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;  } -void omap2xxx_cm_set_dpll_disable_autoidle(void) +/* Clockdomain low-level operations */ + +static int omap3xxx_clkdm_add_sleepdep(struct clockdomain *clkdm1, +				       struct clockdomain *clkdm2)  { -	_omap2xxx_set_dpll_autoidle(OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP); +	omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit), +				  clkdm1->pwrdm.ptr->prcm_offs, +				  OMAP3430_CM_SLEEPDEP); +	return 0;  } -void omap2xxx_cm_set_dpll_auto_low_power_stop(void) +static int omap3xxx_clkdm_del_sleepdep(struct clockdomain *clkdm1, +				       struct clockdomain *clkdm2)  { -	_omap2xxx_set_dpll_autoidle(DPLL_AUTOIDLE_DISABLE); +	omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit), +				    clkdm1->pwrdm.ptr->prcm_offs, +				    OMAP3430_CM_SLEEPDEP); +	return 0;  } -/* - * APLL autoidle control - */ +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 void _omap2xxx_set_apll_autoidle(u8 m, u32 mask) +static int omap3xxx_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)  { -	u32 v; +	struct clkdm_dep *cd; +	u32 mask = 0; -	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); +	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;  } -void omap2xxx_cm_set_apll54_disable_autoidle(void) +static int omap3xxx_clkdm_sleep(struct clockdomain *clkdm)  { -	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP, -				    OMAP24XX_AUTO_54M_MASK); +	omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs, +				      clkdm->clktrctrl_mask); +	return 0;  } -void omap2xxx_cm_set_apll54_auto_low_power_stop(void) +static int omap3xxx_clkdm_wakeup(struct clockdomain *clkdm)  { -	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE, -				    OMAP24XX_AUTO_54M_MASK); +	omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs, +				       clkdm->clktrctrl_mask); +	return 0;  } -void omap2xxx_cm_set_apll96_disable_autoidle(void) +static void omap3xxx_clkdm_allow_idle(struct clockdomain *clkdm)  { -	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP, -				    OMAP24XX_AUTO_96M_MASK); +	if (atomic_read(&clkdm->usecount) > 0) +		_clkdm_add_autodeps(clkdm); + +	omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs, +				       clkdm->clktrctrl_mask);  } -void omap2xxx_cm_set_apll96_auto_low_power_stop(void) +static void omap3xxx_clkdm_deny_idle(struct clockdomain *clkdm)  { -	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE, -				    OMAP24XX_AUTO_96M_MASK); -} +	omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs, +					clkdm->clktrctrl_mask); -/* - * - */ +	if (atomic_read(&clkdm->usecount) > 0) +		_clkdm_del_autodeps(clkdm); +} -/** - * omap2_cm_wait_idlest_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 - * - * XXX document - */ -int omap2_cm_wait_module_ready(s16 prcm_mod, u8 idlest_id, u8 idlest_shift) +static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm)  { -	int ena = 0, i = 0; -	u8 cm_idlest_reg; -	u32 mask; +	bool hwsup = false; -	if (!idlest_id || (idlest_id > ARRAY_SIZE(cm_idlest_offs))) -		return -EINVAL; +	if (!clkdm->clktrctrl_mask) +		return 0; -	cm_idlest_reg = cm_idlest_offs[idlest_id - 1]; +	/* +	 * 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; +	} -	mask = 1 << idlest_shift; +	hwsup = omap3xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, +					      clkdm->clktrctrl_mask); -	if (cpu_is_omap24xx()) -		ena = mask; -	else if (cpu_is_omap34xx()) -		ena = 0; -	else -		BUG(); +	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); +	} -	omap_test_timeout(((omap2_cm_read_mod_reg(prcm_mod, cm_idlest_reg) & mask) == ena), -			  MAX_MODULE_READY_TIME, i); +	return 0; +} -	return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY; +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   */ -#ifdef CONFIG_ARCH_OMAP3  struct omap3_cm_regs {  	u32 iva2_cm_clksel1;  	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,  			       OMAP3_CM_CLKOUT_CTRL_OFFSET);  } -#endif diff --git a/arch/arm/mach-omap2/cm3xxx.h b/arch/arm/mach-omap2/cm3xxx.h new file mode 100644 index 00000000000..4a6ac812edf --- /dev/null +++ b/arch/arm/mach-omap2/cm3xxx.h @@ -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 diff --git a/arch/arm/mach-omap2/cm_common.c b/arch/arm/mach-omap2/cm_common.c new file mode 100644 index 00000000000..3246cef151d --- /dev/null +++ b/arch/arm/mach-omap2/cm_common.c @@ -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; +} diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c index 1894015ff04..7f9a464f01e 100644 --- a/arch/arm/mach-omap2/cminst44xx.c +++ b/arch/arm/mach-omap2/cminst44xx.c @@ -2,8 +2,9 @@   * OMAP4 CM instance functions   *   * Copyright (C) 2009 Nokia Corporation - * Copyright (C) 2011 Texas Instruments, Inc. + * Copyright (C) 2008-2011 Texas Instruments, Inc.   * Paul Walmsley + * Rajendra Nayak <rnayak@ti.com>   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License version 2 as @@ -22,6 +23,7 @@  #include "iomap.h"  #include "common.h" +#include "clockdomain.h"  #include "cm.h"  #include "cm1_44xx.h"  #include "cm2_44xx.h" @@ -343,3 +345,141 @@ void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs,  	v &= ~OMAP4430_MODULEMODE_MASK;  	omap4_cminst_write_inst_reg(v, part, inst, clkctrl_offs);  } + +/* + * Clockdomain low-level functions + */ + +static int omap4_clkdm_add_wkup_sleep_dep(struct clockdomain *clkdm1, +					struct clockdomain *clkdm2) +{ +	omap4_cminst_set_inst_reg_bits((1 << clkdm2->dep_bit), +				       clkdm1->prcm_partition, +				       clkdm1->cm_inst, clkdm1->clkdm_offs + +				       OMAP4_CM_STATICDEP); +	return 0; +} + +static int omap4_clkdm_del_wkup_sleep_dep(struct clockdomain *clkdm1, +					struct clockdomain *clkdm2) +{ +	omap4_cminst_clear_inst_reg_bits((1 << clkdm2->dep_bit), +					 clkdm1->prcm_partition, +					 clkdm1->cm_inst, clkdm1->clkdm_offs + +					 OMAP4_CM_STATICDEP); +	return 0; +} + +static int omap4_clkdm_read_wkup_sleep_dep(struct clockdomain *clkdm1, +					struct clockdomain *clkdm2) +{ +	return omap4_cminst_read_inst_reg_bits(clkdm1->prcm_partition, +					       clkdm1->cm_inst, +					       clkdm1->clkdm_offs + +					       OMAP4_CM_STATICDEP, +					       (1 << clkdm2->dep_bit)); +} + +static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm) +{ +	struct clkdm_dep *cd; +	u32 mask = 0; + +	if (!clkdm->prcm_partition) +		return 0; + +	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) { +		if (!cd->clkdm) +			continue; /* only happens if data is erroneous */ + +		mask |= 1 << cd->clkdm->dep_bit; +		atomic_set(&cd->wkdep_usecount, 0); +	} + +	omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition, +					 clkdm->cm_inst, clkdm->clkdm_offs + +					 OMAP4_CM_STATICDEP); +	return 0; +} + +static int omap4_clkdm_sleep(struct clockdomain *clkdm) +{ +	omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition, +					clkdm->cm_inst, clkdm->clkdm_offs); +	return 0; +} + +static int omap4_clkdm_wakeup(struct clockdomain *clkdm) +{ +	omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition, +					clkdm->cm_inst, clkdm->clkdm_offs); +	return 0; +} + +static void omap4_clkdm_allow_idle(struct clockdomain *clkdm) +{ +	omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition, +					clkdm->cm_inst, clkdm->clkdm_offs); +} + +static void omap4_clkdm_deny_idle(struct clockdomain *clkdm) +{ +	if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) +		omap4_clkdm_wakeup(clkdm); +	else +		omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition, +						 clkdm->cm_inst, +						 clkdm->clkdm_offs); +} + +static int omap4_clkdm_clk_enable(struct clockdomain *clkdm) +{ +	if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) +		return omap4_clkdm_wakeup(clkdm); + +	return 0; +} + +static int omap4_clkdm_clk_disable(struct clockdomain *clkdm) +{ +	bool hwsup = false; + +	if (!clkdm->prcm_partition) +		return 0; + +	/* +	 * The CLKDM_MISSING_IDLE_REPORTING flag documentation has +	 * more details on the unpleasant problem this is working +	 * around +	 */ +	if (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING && +	    !(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) { +		omap4_clkdm_allow_idle(clkdm); +		return 0; +	} + +	hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition, +					clkdm->cm_inst, clkdm->clkdm_offs); + +	if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) +		omap4_clkdm_sleep(clkdm); + +	return 0; +} + +struct clkdm_ops omap4_clkdm_operations = { +	.clkdm_add_wkdep	= omap4_clkdm_add_wkup_sleep_dep, +	.clkdm_del_wkdep	= omap4_clkdm_del_wkup_sleep_dep, +	.clkdm_read_wkdep	= omap4_clkdm_read_wkup_sleep_dep, +	.clkdm_clear_all_wkdeps	= omap4_clkdm_clear_all_wkup_sleep_deps, +	.clkdm_add_sleepdep	= omap4_clkdm_add_wkup_sleep_dep, +	.clkdm_del_sleepdep	= omap4_clkdm_del_wkup_sleep_dep, +	.clkdm_read_sleepdep	= omap4_clkdm_read_wkup_sleep_dep, +	.clkdm_clear_all_sleepdeps	= omap4_clkdm_clear_all_wkup_sleep_deps, +	.clkdm_sleep		= omap4_clkdm_sleep, +	.clkdm_wakeup		= omap4_clkdm_wakeup, +	.clkdm_allow_idle	= omap4_clkdm_allow_idle, +	.clkdm_deny_idle	= omap4_clkdm_deny_idle, +	.clkdm_clk_enable	= omap4_clkdm_clk_enable, +	.clkdm_clk_disable	= omap4_clkdm_clk_disable, +}; diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index bf2be5c5468..06375ad2091 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -20,8 +20,8 @@  #include "common.h"  #include "cm-regbits-34xx.h"  #include "prm-regbits-34xx.h" -#include "prm2xxx_3xxx.h" -#include "cm2xxx_3xxx.h" +#include "prm3xxx.h" +#include "cm3xxx.h"  #include "sdrc.h"  #include "pm.h"  #include "control.h" diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 87eee3b62a3..37eeb45612f 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -147,10 +147,11 @@  #include "common.h"  #include "clockdomain.h"  #include "powerdomain.h" -#include "cm2xxx_3xxx.h" +#include "cm2xxx.h" +#include "cm3xxx.h"  #include "cminst44xx.h"  #include "cm33xx.h" -#include "prm2xxx_3xxx.h" +#include "prm3xxx.h"  #include "prm44xx.h"  #include "prm33xx.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 */  /** - * _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 *   *   * 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   * 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)  		return -EINVAL; @@ -2689,9 +2690,36 @@ static int _omap2_wait_target_ready(struct omap_hwmod *oh)  	/* XXX check module SIDLEMODE, hardreset status, enabled clocks */ -	return omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs, -					  oh->prcm.omap2.idlest_reg_id, -					  oh->prcm.omap2.idlest_idle_bit); +	return omap2xxx_cm_wait_module_ready(oh->prcm.omap2.module_offs, +					     oh->prcm.omap2.idlest_reg_id, +					     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)  { -	if (cpu_is_omap24xx() || cpu_is_omap34xx()) { -		soc_ops.wait_target_ready = _omap2_wait_target_ready; +	if (cpu_is_omap24xx()) { +		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.deassert_hardreset = _omap2_deassert_hardreset;  		soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted; diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index 6d17e044ffb..83815ddc478 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c @@ -43,9 +43,9 @@  #include "soc.h"  #include "common.h"  #include "clock.h" -#include "prm2xxx_3xxx.h" +#include "prm2xxx.h"  #include "prm-regbits-24xx.h" -#include "cm2xxx_3xxx.h" +#include "cm2xxx.h"  #include "cm-regbits-24xx.h"  #include "sdrc.h"  #include "pm.h" diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 160fa250c41..2f1ad87c1bb 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -44,12 +44,11 @@  #include "soc.h"  #include "common.h" -#include "cm2xxx_3xxx.h" +#include "cm3xxx.h"  #include "cm-regbits-34xx.h"  #include "gpmc.h"  #include "prm-regbits-34xx.h" - -#include "prm2xxx_3xxx.h" +#include "prm3xxx.h"  #include "pm.h"  #include "sdrc.h"  #include "control.h" diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c deleted file mode 100644 index 3950ccfe5f4..00000000000 --- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c +++ /dev/null @@ -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, -}; diff --git a/arch/arm/mach-omap2/powerdomain33xx.c b/arch/arm/mach-omap2/powerdomain33xx.c deleted file mode 100644 index 67c5663899b..00000000000 --- a/arch/arm/mach-omap2/powerdomain33xx.c +++ /dev/null @@ -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, -}; diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c deleted file mode 100644 index aceb4f464c9..00000000000 --- a/arch/arm/mach-omap2/powerdomain44xx.c +++ /dev/null @@ -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, -}; diff --git a/arch/arm/mach-omap2/prm-regbits-24xx.h b/arch/arm/mach-omap2/prm-regbits-24xx.h index 6ac966103f3..638da6dd41c 100644 --- a/arch/arm/mach-omap2/prm-regbits-24xx.h +++ b/arch/arm/mach-omap2/prm-regbits-24xx.h @@ -14,7 +14,7 @@   * published by the Free Software Foundation.   */ -#include "prm2xxx_3xxx.h" +#include "prm2xxx.h"  /* Bits shared between registers */ @@ -209,9 +209,13 @@  /* RM_RSTST_WKUP specific bits */  /* 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_SECU_WD_RST_SHIFT			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_SECU_VIOL_RST_SHIFT			3  #define OMAP24XX_SECU_VIOL_RST_MASK			(1 << 3)  /* PM_WKEN_WKUP specific bits */ diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h index 64c087af6a8..838b594d4e1 100644 --- a/arch/arm/mach-omap2/prm-regbits-34xx.h +++ b/arch/arm/mach-omap2/prm-regbits-34xx.h @@ -14,7 +14,7 @@  #define __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_34XX_H -#include "prm2xxx_3xxx.h" +#include "prm3xxx.h"  /* Shared register bits */ @@ -509,15 +509,25 @@  #define OMAP3430_RSTTIME1_MASK				(0xff << 0)  /* PRM_RSTST */ +#define OMAP3430_ICECRUSHER_RST_SHIFT			10  #define OMAP3430_ICECRUSHER_RST_MASK			(1 << 10) +#define OMAP3430_ICEPICK_RST_SHIFT			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_VDD1_VOLTAGE_MANAGER_RST_SHIFT		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_SECURE_WD_RST_SHIFT			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_SECURITY_VIOL_RST_SHIFT		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_COLD_RST_SHIFT			0  #define OMAP3430_GLOBAL_COLD_RST_MASK			(1 << 0)  /* PRM_VOLTCTRL */ diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h index 39d562169d1..c30ab5de8d1 100644 --- a/arch/arm/mach-omap2/prm.h +++ b/arch/arm/mach-omap2/prm.h @@ -52,5 +52,58 @@  #define OMAP_POWERSTATE_SHIFT				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 diff --git a/arch/arm/mach-omap2/prm2xxx.c b/arch/arm/mach-omap2/prm2xxx.c new file mode 100644 index 00000000000..e2860f9c111 --- /dev/null +++ b/arch/arm/mach-omap2/prm2xxx.c @@ -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); diff --git a/arch/arm/mach-omap2/prm2xxx.h b/arch/arm/mach-omap2/prm2xxx.h new file mode 100644 index 00000000000..1d97112524f --- /dev/null +++ b/arch/arm/mach-omap2/prm2xxx.h @@ -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 diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c index 9529984d8d2..30517f5af70 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c @@ -15,82 +15,12 @@  #include <linux/errno.h>  #include <linux/err.h>  #include <linux/io.h> -#include <linux/irq.h> -#include <plat/prcm.h> - -#include "soc.h"  #include "common.h" -#include "vp.h" - +#include "powerdomain.h"  #include "prm2xxx_3xxx.h" -#include "cm2xxx_3xxx.h"  #include "prm-regbits-24xx.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, -}; - -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); -} - +#include "clockdomain.h"  /**   * 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)  { -	if (!(cpu_is_omap24xx() || cpu_is_omap34xx())) -		return -EINVAL; -  	return omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL,  				       (1 << shift));  } @@ -127,9 +54,6 @@ int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)  {  	u32 mask; -	if (!(cpu_is_omap24xx() || cpu_is_omap34xx())) -		return -EINVAL; -  	mask = 1 << shift;  	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;  	int c; -	if (!(cpu_is_omap24xx() || cpu_is_omap34xx())) -		return -EINVAL; -  	rst = 1 << rst_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;  } -/* 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, -	}, -}; +/* Powerdomain low-level functions */ -#define MAX_VP_ID ARRAY_SIZE(omap3_vp); - -u32 omap3_prm_vp_check_txdone(u8 vp_id) +/* Common functions across OMAP2 and OMAP3 */ +int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)  { -	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; +	omap2_prm_rmw_mod_reg_bits(OMAP_POWERSTATE_MASK, +				   (pwrst << OMAP_POWERSTATE_SHIFT), +				   pwrdm->prcm_offs, OMAP2_PM_PWSTCTRL); +	return 0;  } -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]; - -	omap2_prm_write_mod_reg(vp->tranxdone_status, -				OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET); +	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, +					     OMAP2_PM_PWSTCTRL, +					     OMAP_POWERSTATE_MASK);  } -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; -u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset) -{ -	return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, offset); +	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;  } -/** - * 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) +int omap2_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, +								u8 pwrst)  { -	u32 mask, st; +	u32 m; + +	m = omap2_pwrdm_get_mem_bank_retst_mask(bank); -	/* 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); +	omap2_prm_rmw_mod_reg_bits(m, (pwrst << __ffs(m)), pwrdm->prcm_offs, +				   OMAP2_PM_PWSTCTRL); -	events[0] = mask & st; +	return 0;  } -/** - * 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) +int omap2_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)  { -	omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET); +	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);  } -/** - * 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) +int omap2_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)  { -	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); +	u32 m; + +	m = omap2_pwrdm_get_mem_bank_retst_mask(bank); -	/* OCP barrier */ -	omap2_prm_read_mod_reg(OCP_MOD, OMAP3_PRM_REVISION_OFFSET); +	return omap2_prm_read_mod_bits_shift(pwrdm->prcm_offs, +					     OMAP2_PM_PWSTCTRL, m);  } -/** - * 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) +int omap2_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)  { -	omap2_prm_write_mod_reg(saved_mask[0], OCP_MOD, -				OMAP3_PRM_IRQENABLE_MPU_OFFSET); +	u32 v; + +	v = pwrst << __ffs(OMAP_LOGICRETSTATE_MASK); +	omap2_prm_rmw_mod_reg_bits(OMAP_LOGICRETSTATE_MASK, v, pwrdm->prcm_offs, +				   OMAP2_PM_PWSTCTRL); + +	return 0;  } -/** - * 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 omap2_pwrdm_wait_transition(struct powerdomain *pwrdm)  { -	int i = 0; +	u32 c = 0; -	omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD, -				   PM_WKEN); +	/* +	 * 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? +	 */ -	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"); +	/* 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); -	omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD, -				     PM_WKEN); +	if (c > PWRDM_TRANSITION_BAILOUT) { +		pr_err("powerdomain: %s: waited too long to complete transition\n", +		       pwrdm->name); +		return -EAGAIN; +	} -	omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK, WKUP_MOD, -				   PM_WKST); +	pr_debug("powerdomain: completed transition in %d loops\n", c); -	omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST); +	return 0;  } -/** - * 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) +int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1, +			  struct clockdomain *clkdm2)  { -	if (omap3_has_io_wakeup()) -		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, -					   PM_WKEN); +	omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit), +				   clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP); +	return 0;  } -static int __init omap3xxx_prcm_init(void) +int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1, +			  struct clockdomain *clkdm2)  { -	int ret = 0; +	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)); +} -	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); +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);  	} -	return ret; +	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, +				     PM_WKDEP); +	return 0;  } -subsys_initcall(omap3xxx_prcm_init); + diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h index c19d249b481..3330b1bf789 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.h +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h @@ -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   * Paul Walmsley   * @@ -19,160 +19,6 @@  #include "prcm-common.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   * @@ -200,66 +46,83 @@  #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__ -/* OMAP3 specific register offsets */ -#define OMAP3430ES2_PM_WKEN3				0x00f0 -#define OMAP3430ES2_PM_WKST3				0x00b8 +#include <linux/io.h> +#include "powerdomain.h" -#define OMAP3430_PM_MPUGRPSEL				0x00a4 -#define OMAP3430_PM_MPUGRPSEL1				OMAP3430_PM_MPUGRPSEL -#define OMAP3430ES2_PM_MPUGRPSEL3			0x00f8 +/* Power/reset management domain register get/set */ +static inline u32 omap2_prm_read_mod_reg(s16 module, u16 idx) +{ +	return __raw_readl(prm_base + module + idx); +} -#define OMAP3430_PM_IVAGRPSEL				0x00a8 -#define OMAP3430_PM_IVAGRPSEL1				OMAP3430_PM_IVAGRPSEL -#define OMAP3430ES2_PM_IVAGRPSEL3			0x00f4 +static inline void omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx) +{ +	__raw_writel(val, prm_base + module + idx); +} -#define OMAP3430_PM_PREPWSTST				0x00e8 +/* 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; -#define OMAP3430_PRM_IRQSTATUS_IVA2			0x00f8 -#define OMAP3430_PRM_IRQENABLE_IVA2			0x00fc +	v = omap2_prm_read_mod_reg(module, idx); +	v &= ~mask; +	v |= bits; +	omap2_prm_write_mod_reg(v, module, idx); +	return v; +} -#ifndef __ASSEMBLER__ -/* Power/reset management domain register get/set */ -extern 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); -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); +/* 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 */  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_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift); -/* 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); +extern int omap2_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst); +extern int omap2_pwrdm_read_next_pwrst(struct powerdomain *pwrdm); +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); -/* 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 int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1, +				 struct clockdomain *clkdm2); +extern int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1, +				 struct clockdomain *clkdm2); +extern int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1, +				  struct clockdomain *clkdm2); +extern int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm);  #endif /* __ASSEMBLER */ @@ -348,7 +211,9 @@ extern void omap3xxx_prm_restore_irqen(u32 *saved_mask);   *   * 3430: RM_RSTST_CORE, RM_RSTST_EMU   */ +#define OMAP_GLOBALWARM_RST_SHIFT			1  #define OMAP_GLOBALWARM_RST_MASK			(1 << 1) +#define OMAP_GLOBALCOLD_RST_SHIFT			0  #define OMAP_GLOBALCOLD_RST_MASK			(1 << 0)  /* diff --git a/arch/arm/mach-omap2/prm33xx.c b/arch/arm/mach-omap2/prm33xx.c index 624ade5c3c3..53ec9cbaa3d 100644 --- a/arch/arm/mach-omap2/prm33xx.c +++ b/arch/arm/mach-omap2/prm33xx.c @@ -22,6 +22,7 @@  #include "../plat-omap/common.h"  #include "common.h" +#include "powerdomain.h"  #include "prm33xx.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;  } + +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, +}; diff --git a/arch/arm/mach-omap2/prm3xxx.c b/arch/arm/mach-omap2/prm3xxx.c new file mode 100644 index 00000000000..1fea656b2ca --- /dev/null +++ b/arch/arm/mach-omap2/prm3xxx.c @@ -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); diff --git a/arch/arm/mach-omap2/prm3xxx.h b/arch/arm/mach-omap2/prm3xxx.h new file mode 100644 index 00000000000..a3c28a87541 --- /dev/null +++ b/arch/arm/mach-omap2/prm3xxx.h @@ -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 diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c index f0c4d5f4a17..a799e9552fb 100644 --- a/arch/arm/mach-omap2/prm44xx.c +++ b/arch/arm/mach-omap2/prm44xx.c @@ -1,10 +1,11 @@  /*   * OMAP4 PRM module functions   * - * Copyright (C) 2011 Texas Instruments, Inc. + * Copyright (C) 2011-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 @@ -27,6 +28,9 @@  #include "prm-regbits-44xx.h"  #include "prcm44xx.h"  #include "prminst44xx.h" +#include "powerdomain.h" + +/* Static data */  static const struct omap_prcm_irq omap4_prcm_irqs[] = {  	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,  }; +/* + * 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 */  /* 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);  } -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()) { -		omap44xx_prm_enable_io_wakeup(); -		return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup); +	struct prm_reset_src_map *p; +	u32 r = 0; +	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;  } -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); diff --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h index ee72ae6bd8c..c8e1accdc90 100644 --- a/arch/arm/mach-omap2/prm44xx.h +++ b/arch/arm/mach-omap2/prm44xx.h @@ -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_restore_irqen(u32 *saved_mask); +extern u32 omap44xx_prm_get_reset_sources(void); +  # endif  #endif diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c index 6fabbd816d6..6c595798c5c 100644 --- a/arch/arm/mach-omap2/prm_common.c +++ b/arch/arm/mach-omap2/prm_common.c @@ -28,6 +28,8 @@  #include <plat/prcm.h>  #include "prm2xxx_3xxx.h" +#include "prm2xxx.h" +#include "prm3xxx.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; +/* + * 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 */  /* @@ -319,64 +328,71 @@ err:  	return -ENOMEM;  } -/* - * Stubbed functions so that common files continue to build when - * custom builds are used - * XXX These are temporary and should be removed at the earliest possible - * opportunity +/** + * prm_read_reset_sources - return the sources of the SoC's last reset + * + * Return a u32 bitmask representing the reset sources that caused the + * 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"); -	return 0; -} +	u32 ret = 1 << OMAP_UNKNOWN_RST_SRC_ID_SHIFT; -void __weak omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx) -{ -	WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n"); -} +	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__); -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 ret;  } -u32 __weak omap2_prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx) +/** + * 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)  { -	WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n"); -	return 0; -} +	if (!pld) +		return -EINVAL; -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; -} +	if (prm_ll_data != &null_prm_ll_data) +		return -EEXIST; -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; -} +	prm_ll_data = pld; -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) +/** + * 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"); -	return 0; -} +	if (!pld || prm_ll_data != pld) +		return -EINVAL; + +	prm_ll_data = &null_prm_ll_data; -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;  } - diff --git a/arch/arm/mach-omap2/sdrc2xxx.c b/arch/arm/mach-omap2/sdrc2xxx.c index 3b8bfdf848d..26c1728e09c 100644 --- a/arch/arm/mach-omap2/sdrc2xxx.c +++ b/arch/arm/mach-omap2/sdrc2xxx.c @@ -29,7 +29,7 @@  #include "soc.h"  #include "iomap.h"  #include "common.h" -#include "prm2xxx_3xxx.h" +#include "prm2xxx.h"  #include "clock.h"  #include "sdrc.h" diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S index 75afe11207f..474dba7263e 100644 --- a/arch/arm/mach-omap2/sleep34xx.S +++ b/arch/arm/mach-omap2/sleep34xx.S @@ -30,8 +30,8 @@  #include "omap34xx.h"  #include "iomap.h" -#include "cm2xxx_3xxx.h" -#include "prm2xxx_3xxx.h" +#include "cm3xxx.h" +#include "prm3xxx.h"  #include "sdrc.h"  #include "control.h" diff --git a/arch/arm/mach-omap2/sram242x.S b/arch/arm/mach-omap2/sram242x.S index 8f7326cd435..680a7c56cc3 100644 --- a/arch/arm/mach-omap2/sram242x.S +++ b/arch/arm/mach-omap2/sram242x.S @@ -34,8 +34,8 @@  #include "soc.h"  #include "iomap.h" -#include "prm2xxx_3xxx.h" -#include "cm2xxx_3xxx.h" +#include "prm2xxx.h" +#include "cm2xxx.h"  #include "sdrc.h"  	.text diff --git a/arch/arm/mach-omap2/sram243x.S b/arch/arm/mach-omap2/sram243x.S index b140d657852..a1e9edd673f 100644 --- a/arch/arm/mach-omap2/sram243x.S +++ b/arch/arm/mach-omap2/sram243x.S @@ -34,8 +34,8 @@  #include "soc.h"  #include "iomap.h" -#include "prm2xxx_3xxx.h" -#include "cm2xxx_3xxx.h" +#include "prm2xxx.h" +#include "cm2xxx.h"  #include "sdrc.h"  	.text diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S index 2d0ceaa23fb..1446331b576 100644 --- a/arch/arm/mach-omap2/sram34xx.S +++ b/arch/arm/mach-omap2/sram34xx.S @@ -32,7 +32,7 @@  #include "soc.h"  #include "iomap.h"  #include "sdrc.h" -#include "cm2xxx_3xxx.h" +#include "cm3xxx.h"  /*   * This file needs be built unconditionally as ARM to interoperate correctly  |