All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-08-06 17:49 ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap; +Cc: Paul Walmsley, Kevin Hilman, Dave Gerlach

Hi,

This is the third version of the patch series for adding basic suspend-resume
support for AM33XX, previously submitted by Vaibhav Bedia. This patchset 
is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are 
required for the pm code to properly suspend and resume.

The PM code uses the firmware interface and expects the userspace to load 
the WKUP_M3 binary before the suspend-resume functionality is made available.
The binary file (and the source-code for WKUP_M3) can be obtained from the 
'next2' branch at [4]. The WKUP_M3 binary can either be loaded post bootup 
via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be 
included in the kernel image as part of the build process.

Suspend to mem is tested on am335x-bone and am335x-evm.

More details on AM335x suspend-resume are provided within the commit logs
for each patch.

Changes in v3:
- Moved wkup_m3 code into separate driver
- Split up ti_emif header move
- Addressed clean-up comments
- Removed mailbox patches
- v2-v3 Discussion:
http://marc.info/?l=linux-arm-kernel&m=135698501821090&w=4

Changes in v2:
- Broke patches up to isolate assembly code and build hookup.
- Moved control module code to separate module
- v1->v2 Discussion:
http://lists.infradead.org/pipermail/linux-arm-kernel/2012-November/129508.html

Regards,
Dave

[1] http://marc.info/?l=linux-arm-kernel&m=137303736714638&w=4
[2] http://marc.info/?l=linux-omap&m=137303723114610&w=4
[3] http://marc.info/?l=linux-omap&m=137401384611934&w=4
[4] http://arago-project.org/git/projects/?p=am33x-cm3.git;a=shortlog;h=refs/heads/next2


Dave Gerlach (1):
  memory: emif: Move EMIF register defines to include/linux/

Vaibhav Bedia (8):
  ARM: OMAP2+: AM33XX: control: Add some control module registers and
    APIs
  ARM: OMAP: DTB: Update IRQ data for WKUP_M3
  ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
  ARM: OMAP2+: AM33XX: Add assembly code for PM operations
  ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device
  ARM: OMAP: omap_device: Add APIs to enable and idle hwmods
  ARM: OMAP2+: AM33XX: Basic suspend resume support
  ARM: OMAP2+: AM33XX: Hookup AM33XX PM code into OMAP builds

 arch/arm/boot/dts/am33xx.dtsi       |    1 +
 arch/arm/mach-omap2/Kconfig         |    7 +-
 arch/arm/mach-omap2/Makefile        |    2 +
 arch/arm/mach-omap2/board-generic.c |    3 +-
 arch/arm/mach-omap2/common.c        |   28 ++
 arch/arm/mach-omap2/common.h        |   14 +
 arch/arm/mach-omap2/control.c       |   57 ++++
 arch/arm/mach-omap2/control.h       |   54 ++++
 arch/arm/mach-omap2/io.c            |    6 +
 arch/arm/mach-omap2/omap_device.c   |    8 +
 arch/arm/mach-omap2/omap_device.h   |    2 +
 arch/arm/mach-omap2/pm.c            |    3 +-
 arch/arm/mach-omap2/pm.h            |    5 +
 arch/arm/mach-omap2/pm33xx.c        |  474 +++++++++++++++++++++++++++++
 arch/arm/mach-omap2/pm33xx.h        |   77 +++++
 arch/arm/mach-omap2/sleep33xx.S     |  350 ++++++++++++++++++++++
 arch/arm/mach-omap2/sram.c          |   10 +-
 arch/arm/mach-omap2/sram.h          |    2 +
 arch/arm/mach-omap2/timer.c         |   32 ++
 arch/arm/mach-omap2/wkup_m3.c       |  183 ++++++++++++
 drivers/memory/emif.h               |  543 +---------------------------------
 include/linux/ti_emif.h             |  558 +++++++++++++++++++++++++++++++++++
 22 files changed, 1872 insertions(+), 547 deletions(-)
 create mode 100644 arch/arm/mach-omap2/pm33xx.c
 create mode 100644 arch/arm/mach-omap2/pm33xx.h
 create mode 100644 arch/arm/mach-omap2/sleep33xx.S
 create mode 100644 arch/arm/mach-omap2/wkup_m3.c
 create mode 100644 include/linux/ti_emif.h

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-08-06 17:49 ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

This is the third version of the patch series for adding basic suspend-resume
support for AM33XX, previously submitted by Vaibhav Bedia. This patchset 
is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are 
required for the pm code to properly suspend and resume.

The PM code uses the firmware interface and expects the userspace to load 
the WKUP_M3 binary before the suspend-resume functionality is made available.
The binary file (and the source-code for WKUP_M3) can be obtained from the 
'next2' branch at [4]. The WKUP_M3 binary can either be loaded post bootup 
via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be 
included in the kernel image as part of the build process.

Suspend to mem is tested on am335x-bone and am335x-evm.

More details on AM335x suspend-resume are provided within the commit logs
for each patch.

Changes in v3:
- Moved wkup_m3 code into separate driver
- Split up ti_emif header move
- Addressed clean-up comments
- Removed mailbox patches
- v2-v3 Discussion:
http://marc.info/?l=linux-arm-kernel&m=135698501821090&w=4

Changes in v2:
- Broke patches up to isolate assembly code and build hookup.
- Moved control module code to separate module
- v1->v2 Discussion:
http://lists.infradead.org/pipermail/linux-arm-kernel/2012-November/129508.html

Regards,
Dave

[1] http://marc.info/?l=linux-arm-kernel&m=137303736714638&w=4
[2] http://marc.info/?l=linux-omap&m=137303723114610&w=4
[3] http://marc.info/?l=linux-omap&m=137401384611934&w=4
[4] http://arago-project.org/git/projects/?p=am33x-cm3.git;a=shortlog;h=refs/heads/next2


Dave Gerlach (1):
  memory: emif: Move EMIF register defines to include/linux/

Vaibhav Bedia (8):
  ARM: OMAP2+: AM33XX: control: Add some control module registers and
    APIs
  ARM: OMAP: DTB: Update IRQ data for WKUP_M3
  ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
  ARM: OMAP2+: AM33XX: Add assembly code for PM operations
  ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device
  ARM: OMAP: omap_device: Add APIs to enable and idle hwmods
  ARM: OMAP2+: AM33XX: Basic suspend resume support
  ARM: OMAP2+: AM33XX: Hookup AM33XX PM code into OMAP builds

 arch/arm/boot/dts/am33xx.dtsi       |    1 +
 arch/arm/mach-omap2/Kconfig         |    7 +-
 arch/arm/mach-omap2/Makefile        |    2 +
 arch/arm/mach-omap2/board-generic.c |    3 +-
 arch/arm/mach-omap2/common.c        |   28 ++
 arch/arm/mach-omap2/common.h        |   14 +
 arch/arm/mach-omap2/control.c       |   57 ++++
 arch/arm/mach-omap2/control.h       |   54 ++++
 arch/arm/mach-omap2/io.c            |    6 +
 arch/arm/mach-omap2/omap_device.c   |    8 +
 arch/arm/mach-omap2/omap_device.h   |    2 +
 arch/arm/mach-omap2/pm.c            |    3 +-
 arch/arm/mach-omap2/pm.h            |    5 +
 arch/arm/mach-omap2/pm33xx.c        |  474 +++++++++++++++++++++++++++++
 arch/arm/mach-omap2/pm33xx.h        |   77 +++++
 arch/arm/mach-omap2/sleep33xx.S     |  350 ++++++++++++++++++++++
 arch/arm/mach-omap2/sram.c          |   10 +-
 arch/arm/mach-omap2/sram.h          |    2 +
 arch/arm/mach-omap2/timer.c         |   32 ++
 arch/arm/mach-omap2/wkup_m3.c       |  183 ++++++++++++
 drivers/memory/emif.h               |  543 +---------------------------------
 include/linux/ti_emif.h             |  558 +++++++++++++++++++++++++++++++++++
 22 files changed, 1872 insertions(+), 547 deletions(-)
 create mode 100644 arch/arm/mach-omap2/pm33xx.c
 create mode 100644 arch/arm/mach-omap2/pm33xx.h
 create mode 100644 arch/arm/mach-omap2/sleep33xx.S
 create mode 100644 arch/arm/mach-omap2/wkup_m3.c
 create mode 100644 include/linux/ti_emif.h

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 1/9] memory: emif: Move EMIF register defines to include/linux/
  2013-08-06 17:49 ` Dave Gerlach
@ 2013-08-06 17:49   ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap
  Cc: Paul Walmsley, Kevin Hilman, Dave Gerlach, Santosh Shilimkar,
	Benoit Cousson, Aneesh V

OMAP4 and AM33XX share the same EMIF controller IP. Although there
are significant differences in the IP integration due to which
AM33XX can't reuse the EMIF driver DVFS similar to OMAP4,
it can definitely benefit by reusing the EMIF related macros
defined in drivers/memory/emif.h.

In the current OMAP PM framework the PM code resides under
arch/arm/mach-omap2/. To enable reuse of the register defines move
the register defines in the emif header file to include/linux so that
both the EMIF driver and the AM33XX PM code can benefit.

Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <benoit.cousson@linaro.org>
Cc: Aneesh V <aneesh@ti.com>
---
 drivers/memory/emif.h   |  543 +--------------------------------------------
 include/linux/ti_emif.h |  558 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 559 insertions(+), 542 deletions(-)
 create mode 100644 include/linux/ti_emif.h

diff --git a/drivers/memory/emif.h b/drivers/memory/emif.h
index bfe08ba..8214f07 100644
--- a/drivers/memory/emif.h
+++ b/drivers/memory/emif.h
@@ -12,548 +12,7 @@
 #ifndef __EMIF_H
 #define __EMIF_H
 
-/*
- * Maximum number of different frequencies supported by EMIF driver
- * Determines the number of entries in the pointer array for register
- * cache
- */
-#define EMIF_MAX_NUM_FREQUENCIES			6
-
-/* State of the core voltage */
-#define DDR_VOLTAGE_STABLE				0
-#define DDR_VOLTAGE_RAMPING				1
-
-/* Defines for timing De-rating */
-#define EMIF_NORMAL_TIMINGS				0
-#define EMIF_DERATED_TIMINGS				1
-
-/* Length of the forced read idle period in terms of cycles */
-#define EMIF_READ_IDLE_LEN_VAL				5
-
-/*
- * forced read idle interval to be used when voltage
- * is changed as part of DVFS/DPS - 1ms
- */
-#define READ_IDLE_INTERVAL_DVFS				(1*1000000)
-
-/*
- * Forced read idle interval to be used when voltage is stable
- * 50us - or maximum value will do
- */
-#define READ_IDLE_INTERVAL_NORMAL			(50*1000000)
-
-/* DLL calibration interval when voltage is NOT stable - 1us */
-#define DLL_CALIB_INTERVAL_DVFS				(1*1000000)
-
-#define DLL_CALIB_ACK_WAIT_VAL				5
-
-/* Interval between ZQCS commands - hw team recommended value */
-#define EMIF_ZQCS_INTERVAL_US				(50*1000)
-/* Enable ZQ Calibration on exiting Self-refresh */
-#define ZQ_SFEXITEN_ENABLE				1
-/*
- * ZQ Calibration simultaneously on both chip-selects:
- * Needs one calibration resistor per CS
- */
-#define	ZQ_DUALCALEN_DISABLE				0
-#define	ZQ_DUALCALEN_ENABLE				1
-
-#define T_ZQCS_DEFAULT_NS				90
-#define T_ZQCL_DEFAULT_NS				360
-#define T_ZQINIT_DEFAULT_NS				1000
-
-/* DPD_EN */
-#define DPD_DISABLE					0
-#define DPD_ENABLE					1
-
-/*
- * Default values for the low-power entry to be used if not provided by user.
- * OMAP4/5 has a hw bug(i735) due to which this value can not be less than 512
- * Timeout values are in DDR clock 'cycles' and frequency threshold in Hz
- */
-#define EMIF_LP_MODE_TIMEOUT_PERFORMANCE		2048
-#define EMIF_LP_MODE_TIMEOUT_POWER			512
-#define EMIF_LP_MODE_FREQ_THRESHOLD			400000000
-
-/* DDR_PHY_CTRL_1 values for EMIF4D - ATTILA PHY combination */
-#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY		0x049FF000
-#define EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY	0x41
-#define EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY	0x80
-#define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY 0xFF
-
-/* DDR_PHY_CTRL_1 values for EMIF4D5 INTELLIPHY combination */
-#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY		0x0E084200
-#define EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS	10000
-
-/* TEMP_ALERT_CONFIG - corresponding to temp gradient 5 C/s */
-#define TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS		360
-
-#define EMIF_T_CSTA					3
-#define EMIF_T_PDLL_UL					128
-
-/* External PHY control registers magic values */
-#define EMIF_EXT_PHY_CTRL_1_VAL				0x04020080
-#define EMIF_EXT_PHY_CTRL_5_VAL				0x04010040
-#define EMIF_EXT_PHY_CTRL_6_VAL				0x01004010
-#define EMIF_EXT_PHY_CTRL_7_VAL				0x00001004
-#define EMIF_EXT_PHY_CTRL_8_VAL				0x04010040
-#define EMIF_EXT_PHY_CTRL_9_VAL				0x01004010
-#define EMIF_EXT_PHY_CTRL_10_VAL			0x00001004
-#define EMIF_EXT_PHY_CTRL_11_VAL			0x00000000
-#define EMIF_EXT_PHY_CTRL_12_VAL			0x00000000
-#define EMIF_EXT_PHY_CTRL_13_VAL			0x00000000
-#define EMIF_EXT_PHY_CTRL_14_VAL			0x80080080
-#define EMIF_EXT_PHY_CTRL_15_VAL			0x00800800
-#define EMIF_EXT_PHY_CTRL_16_VAL			0x08102040
-#define EMIF_EXT_PHY_CTRL_17_VAL			0x00000001
-#define EMIF_EXT_PHY_CTRL_18_VAL			0x540A8150
-#define EMIF_EXT_PHY_CTRL_19_VAL			0xA81502A0
-#define EMIF_EXT_PHY_CTRL_20_VAL			0x002A0540
-#define EMIF_EXT_PHY_CTRL_21_VAL			0x00000000
-#define EMIF_EXT_PHY_CTRL_22_VAL			0x00000000
-#define EMIF_EXT_PHY_CTRL_23_VAL			0x00000000
-#define EMIF_EXT_PHY_CTRL_24_VAL			0x00000077
-
-#define EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS	1200
-
-/* Registers offset */
-#define EMIF_MODULE_ID_AND_REVISION			0x0000
-#define EMIF_STATUS					0x0004
-#define EMIF_SDRAM_CONFIG				0x0008
-#define EMIF_SDRAM_CONFIG_2				0x000c
-#define EMIF_SDRAM_REFRESH_CONTROL			0x0010
-#define EMIF_SDRAM_REFRESH_CTRL_SHDW			0x0014
-#define EMIF_SDRAM_TIMING_1				0x0018
-#define EMIF_SDRAM_TIMING_1_SHDW			0x001c
-#define EMIF_SDRAM_TIMING_2				0x0020
-#define EMIF_SDRAM_TIMING_2_SHDW			0x0024
-#define EMIF_SDRAM_TIMING_3				0x0028
-#define EMIF_SDRAM_TIMING_3_SHDW			0x002c
-#define EMIF_LPDDR2_NVM_TIMING				0x0030
-#define EMIF_LPDDR2_NVM_TIMING_SHDW			0x0034
-#define EMIF_POWER_MANAGEMENT_CONTROL			0x0038
-#define EMIF_POWER_MANAGEMENT_CTRL_SHDW			0x003c
-#define EMIF_LPDDR2_MODE_REG_DATA			0x0040
-#define EMIF_LPDDR2_MODE_REG_CONFIG			0x0050
-#define EMIF_OCP_CONFIG					0x0054
-#define EMIF_OCP_CONFIG_VALUE_1				0x0058
-#define EMIF_OCP_CONFIG_VALUE_2				0x005c
-#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL		0x0060
-#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT		0x0064
-#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT	0x0068
-#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1	0x006c
-#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2	0x0070
-#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3	0x0074
-#define EMIF_PERFORMANCE_COUNTER_1			0x0080
-#define EMIF_PERFORMANCE_COUNTER_2			0x0084
-#define EMIF_PERFORMANCE_COUNTER_CONFIG			0x0088
-#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT	0x008c
-#define EMIF_PERFORMANCE_COUNTER_TIME			0x0090
-#define EMIF_MISC_REG					0x0094
-#define EMIF_DLL_CALIB_CTRL				0x0098
-#define EMIF_DLL_CALIB_CTRL_SHDW			0x009c
-#define EMIF_END_OF_INTERRUPT				0x00a0
-#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS		0x00a4
-#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS		0x00a8
-#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS		0x00ac
-#define EMIF_LL_OCP_INTERRUPT_STATUS			0x00b0
-#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET		0x00b4
-#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET		0x00b8
-#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR		0x00bc
-#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR		0x00c0
-#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG	0x00c8
-#define EMIF_TEMPERATURE_ALERT_CONFIG			0x00cc
-#define EMIF_OCP_ERROR_LOG				0x00d0
-#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW		0x00d4
-#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL		0x00d8
-#define EMIF_READ_WRITE_LEVELING_CONTROL		0x00dc
-#define EMIF_DDR_PHY_CTRL_1				0x00e4
-#define EMIF_DDR_PHY_CTRL_1_SHDW			0x00e8
-#define EMIF_DDR_PHY_CTRL_2				0x00ec
-#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING	0x0100
-#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104
-#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108
-#define EMIF_READ_WRITE_EXECUTION_THRESHOLD		0x0120
-#define EMIF_COS_CONFIG					0x0124
-#define EMIF_PHY_STATUS_1				0x0140
-#define EMIF_PHY_STATUS_2				0x0144
-#define EMIF_PHY_STATUS_3				0x0148
-#define EMIF_PHY_STATUS_4				0x014c
-#define EMIF_PHY_STATUS_5				0x0150
-#define EMIF_PHY_STATUS_6				0x0154
-#define EMIF_PHY_STATUS_7				0x0158
-#define EMIF_PHY_STATUS_8				0x015c
-#define EMIF_PHY_STATUS_9				0x0160
-#define EMIF_PHY_STATUS_10				0x0164
-#define EMIF_PHY_STATUS_11				0x0168
-#define EMIF_PHY_STATUS_12				0x016c
-#define EMIF_PHY_STATUS_13				0x0170
-#define EMIF_PHY_STATUS_14				0x0174
-#define EMIF_PHY_STATUS_15				0x0178
-#define EMIF_PHY_STATUS_16				0x017c
-#define EMIF_PHY_STATUS_17				0x0180
-#define EMIF_PHY_STATUS_18				0x0184
-#define EMIF_PHY_STATUS_19				0x0188
-#define EMIF_PHY_STATUS_20				0x018c
-#define EMIF_PHY_STATUS_21				0x0190
-#define EMIF_EXT_PHY_CTRL_1				0x0200
-#define EMIF_EXT_PHY_CTRL_1_SHDW			0x0204
-#define EMIF_EXT_PHY_CTRL_2				0x0208
-#define EMIF_EXT_PHY_CTRL_2_SHDW			0x020c
-#define EMIF_EXT_PHY_CTRL_3				0x0210
-#define EMIF_EXT_PHY_CTRL_3_SHDW			0x0214
-#define EMIF_EXT_PHY_CTRL_4				0x0218
-#define EMIF_EXT_PHY_CTRL_4_SHDW			0x021c
-#define EMIF_EXT_PHY_CTRL_5				0x0220
-#define EMIF_EXT_PHY_CTRL_5_SHDW			0x0224
-#define EMIF_EXT_PHY_CTRL_6				0x0228
-#define EMIF_EXT_PHY_CTRL_6_SHDW			0x022c
-#define EMIF_EXT_PHY_CTRL_7				0x0230
-#define EMIF_EXT_PHY_CTRL_7_SHDW			0x0234
-#define EMIF_EXT_PHY_CTRL_8				0x0238
-#define EMIF_EXT_PHY_CTRL_8_SHDW			0x023c
-#define EMIF_EXT_PHY_CTRL_9				0x0240
-#define EMIF_EXT_PHY_CTRL_9_SHDW			0x0244
-#define EMIF_EXT_PHY_CTRL_10				0x0248
-#define EMIF_EXT_PHY_CTRL_10_SHDW			0x024c
-#define EMIF_EXT_PHY_CTRL_11				0x0250
-#define EMIF_EXT_PHY_CTRL_11_SHDW			0x0254
-#define EMIF_EXT_PHY_CTRL_12				0x0258
-#define EMIF_EXT_PHY_CTRL_12_SHDW			0x025c
-#define EMIF_EXT_PHY_CTRL_13				0x0260
-#define EMIF_EXT_PHY_CTRL_13_SHDW			0x0264
-#define EMIF_EXT_PHY_CTRL_14				0x0268
-#define EMIF_EXT_PHY_CTRL_14_SHDW			0x026c
-#define EMIF_EXT_PHY_CTRL_15				0x0270
-#define EMIF_EXT_PHY_CTRL_15_SHDW			0x0274
-#define EMIF_EXT_PHY_CTRL_16				0x0278
-#define EMIF_EXT_PHY_CTRL_16_SHDW			0x027c
-#define EMIF_EXT_PHY_CTRL_17				0x0280
-#define EMIF_EXT_PHY_CTRL_17_SHDW			0x0284
-#define EMIF_EXT_PHY_CTRL_18				0x0288
-#define EMIF_EXT_PHY_CTRL_18_SHDW			0x028c
-#define EMIF_EXT_PHY_CTRL_19				0x0290
-#define EMIF_EXT_PHY_CTRL_19_SHDW			0x0294
-#define EMIF_EXT_PHY_CTRL_20				0x0298
-#define EMIF_EXT_PHY_CTRL_20_SHDW			0x029c
-#define EMIF_EXT_PHY_CTRL_21				0x02a0
-#define EMIF_EXT_PHY_CTRL_21_SHDW			0x02a4
-#define EMIF_EXT_PHY_CTRL_22				0x02a8
-#define EMIF_EXT_PHY_CTRL_22_SHDW			0x02ac
-#define EMIF_EXT_PHY_CTRL_23				0x02b0
-#define EMIF_EXT_PHY_CTRL_23_SHDW			0x02b4
-#define EMIF_EXT_PHY_CTRL_24				0x02b8
-#define EMIF_EXT_PHY_CTRL_24_SHDW			0x02bc
-#define EMIF_EXT_PHY_CTRL_25				0x02c0
-#define EMIF_EXT_PHY_CTRL_25_SHDW			0x02c4
-#define EMIF_EXT_PHY_CTRL_26				0x02c8
-#define EMIF_EXT_PHY_CTRL_26_SHDW			0x02cc
-#define EMIF_EXT_PHY_CTRL_27				0x02d0
-#define EMIF_EXT_PHY_CTRL_27_SHDW			0x02d4
-#define EMIF_EXT_PHY_CTRL_28				0x02d8
-#define EMIF_EXT_PHY_CTRL_28_SHDW			0x02dc
-#define EMIF_EXT_PHY_CTRL_29				0x02e0
-#define EMIF_EXT_PHY_CTRL_29_SHDW			0x02e4
-#define EMIF_EXT_PHY_CTRL_30				0x02e8
-#define EMIF_EXT_PHY_CTRL_30_SHDW			0x02ec
-
-/* Registers shifts and masks */
-
-/* EMIF_MODULE_ID_AND_REVISION */
-#define SCHEME_SHIFT					30
-#define SCHEME_MASK					(0x3 << 30)
-#define MODULE_ID_SHIFT					16
-#define MODULE_ID_MASK					(0xfff << 16)
-#define RTL_VERSION_SHIFT				11
-#define RTL_VERSION_MASK				(0x1f << 11)
-#define MAJOR_REVISION_SHIFT				8
-#define MAJOR_REVISION_MASK				(0x7 << 8)
-#define MINOR_REVISION_SHIFT				0
-#define MINOR_REVISION_MASK				(0x3f << 0)
-
-/* STATUS */
-#define BE_SHIFT					31
-#define BE_MASK						(1 << 31)
-#define DUAL_CLK_MODE_SHIFT				30
-#define DUAL_CLK_MODE_MASK				(1 << 30)
-#define FAST_INIT_SHIFT					29
-#define FAST_INIT_MASK					(1 << 29)
-#define RDLVLGATETO_SHIFT				6
-#define RDLVLGATETO_MASK				(1 << 6)
-#define RDLVLTO_SHIFT					5
-#define RDLVLTO_MASK					(1 << 5)
-#define WRLVLTO_SHIFT					4
-#define WRLVLTO_MASK					(1 << 4)
-#define PHY_DLL_READY_SHIFT				2
-#define PHY_DLL_READY_MASK				(1 << 2)
-
-/* SDRAM_CONFIG */
-#define SDRAM_TYPE_SHIFT				29
-#define SDRAM_TYPE_MASK					(0x7 << 29)
-#define IBANK_POS_SHIFT					27
-#define IBANK_POS_MASK					(0x3 << 27)
-#define DDR_TERM_SHIFT					24
-#define DDR_TERM_MASK					(0x7 << 24)
-#define DDR2_DDQS_SHIFT					23
-#define DDR2_DDQS_MASK					(1 << 23)
-#define DYN_ODT_SHIFT					21
-#define DYN_ODT_MASK					(0x3 << 21)
-#define DDR_DISABLE_DLL_SHIFT				20
-#define DDR_DISABLE_DLL_MASK				(1 << 20)
-#define SDRAM_DRIVE_SHIFT				18
-#define SDRAM_DRIVE_MASK				(0x3 << 18)
-#define CWL_SHIFT					16
-#define CWL_MASK					(0x3 << 16)
-#define NARROW_MODE_SHIFT				14
-#define NARROW_MODE_MASK				(0x3 << 14)
-#define CL_SHIFT					10
-#define CL_MASK						(0xf << 10)
-#define ROWSIZE_SHIFT					7
-#define ROWSIZE_MASK					(0x7 << 7)
-#define IBANK_SHIFT					4
-#define IBANK_MASK					(0x7 << 4)
-#define EBANK_SHIFT					3
-#define EBANK_MASK					(1 << 3)
-#define PAGESIZE_SHIFT					0
-#define PAGESIZE_MASK					(0x7 << 0)
-
-/* SDRAM_CONFIG_2 */
-#define CS1NVMEN_SHIFT					30
-#define CS1NVMEN_MASK					(1 << 30)
-#define EBANK_POS_SHIFT					27
-#define EBANK_POS_MASK					(1 << 27)
-#define RDBNUM_SHIFT					4
-#define RDBNUM_MASK					(0x3 << 4)
-#define RDBSIZE_SHIFT					0
-#define RDBSIZE_MASK					(0x7 << 0)
-
-/* SDRAM_REFRESH_CONTROL */
-#define INITREF_DIS_SHIFT				31
-#define INITREF_DIS_MASK				(1 << 31)
-#define SRT_SHIFT					29
-#define SRT_MASK					(1 << 29)
-#define ASR_SHIFT					28
-#define ASR_MASK					(1 << 28)
-#define PASR_SHIFT					24
-#define PASR_MASK					(0x7 << 24)
-#define REFRESH_RATE_SHIFT				0
-#define REFRESH_RATE_MASK				(0xffff << 0)
-
-/* SDRAM_TIMING_1 */
-#define T_RTW_SHIFT					29
-#define T_RTW_MASK					(0x7 << 29)
-#define T_RP_SHIFT					25
-#define T_RP_MASK					(0xf << 25)
-#define T_RCD_SHIFT					21
-#define T_RCD_MASK					(0xf << 21)
-#define T_WR_SHIFT					17
-#define T_WR_MASK					(0xf << 17)
-#define T_RAS_SHIFT					12
-#define T_RAS_MASK					(0x1f << 12)
-#define T_RC_SHIFT					6
-#define T_RC_MASK					(0x3f << 6)
-#define T_RRD_SHIFT					3
-#define T_RRD_MASK					(0x7 << 3)
-#define T_WTR_SHIFT					0
-#define T_WTR_MASK					(0x7 << 0)
-
-/* SDRAM_TIMING_2 */
-#define T_XP_SHIFT					28
-#define T_XP_MASK					(0x7 << 28)
-#define T_ODT_SHIFT					25
-#define T_ODT_MASK					(0x7 << 25)
-#define T_XSNR_SHIFT					16
-#define T_XSNR_MASK					(0x1ff << 16)
-#define T_XSRD_SHIFT					6
-#define T_XSRD_MASK					(0x3ff << 6)
-#define T_RTP_SHIFT					3
-#define T_RTP_MASK					(0x7 << 3)
-#define T_CKE_SHIFT					0
-#define T_CKE_MASK					(0x7 << 0)
-
-/* SDRAM_TIMING_3 */
-#define T_PDLL_UL_SHIFT					28
-#define T_PDLL_UL_MASK					(0xf << 28)
-#define T_CSTA_SHIFT					24
-#define T_CSTA_MASK					(0xf << 24)
-#define T_CKESR_SHIFT					21
-#define T_CKESR_MASK					(0x7 << 21)
-#define ZQ_ZQCS_SHIFT					15
-#define ZQ_ZQCS_MASK					(0x3f << 15)
-#define T_TDQSCKMAX_SHIFT				13
-#define T_TDQSCKMAX_MASK				(0x3 << 13)
-#define T_RFC_SHIFT					4
-#define T_RFC_MASK					(0x1ff << 4)
-#define T_RAS_MAX_SHIFT					0
-#define T_RAS_MAX_MASK					(0xf << 0)
-
-/* POWER_MANAGEMENT_CONTROL */
-#define PD_TIM_SHIFT					12
-#define PD_TIM_MASK					(0xf << 12)
-#define DPD_EN_SHIFT					11
-#define DPD_EN_MASK					(1 << 11)
-#define LP_MODE_SHIFT					8
-#define LP_MODE_MASK					(0x7 << 8)
-#define SR_TIM_SHIFT					4
-#define SR_TIM_MASK					(0xf << 4)
-#define CS_TIM_SHIFT					0
-#define CS_TIM_MASK					(0xf << 0)
-
-/* LPDDR2_MODE_REG_DATA */
-#define VALUE_0_SHIFT					0
-#define VALUE_0_MASK					(0x7f << 0)
-
-/* LPDDR2_MODE_REG_CONFIG */
-#define CS_SHIFT					31
-#define CS_MASK						(1 << 31)
-#define REFRESH_EN_SHIFT				30
-#define REFRESH_EN_MASK					(1 << 30)
-#define ADDRESS_SHIFT					0
-#define ADDRESS_MASK					(0xff << 0)
-
-/* OCP_CONFIG */
-#define SYS_THRESH_MAX_SHIFT				24
-#define SYS_THRESH_MAX_MASK				(0xf << 24)
-#define MPU_THRESH_MAX_SHIFT				20
-#define MPU_THRESH_MAX_MASK				(0xf << 20)
-#define LL_THRESH_MAX_SHIFT				16
-#define LL_THRESH_MAX_MASK				(0xf << 16)
-
-/* PERFORMANCE_COUNTER_1 */
-#define COUNTER1_SHIFT					0
-#define COUNTER1_MASK					(0xffffffff << 0)
-
-/* PERFORMANCE_COUNTER_2 */
-#define COUNTER2_SHIFT					0
-#define COUNTER2_MASK					(0xffffffff << 0)
-
-/* PERFORMANCE_COUNTER_CONFIG */
-#define CNTR2_MCONNID_EN_SHIFT				31
-#define CNTR2_MCONNID_EN_MASK				(1 << 31)
-#define CNTR2_REGION_EN_SHIFT				30
-#define CNTR2_REGION_EN_MASK				(1 << 30)
-#define CNTR2_CFG_SHIFT					16
-#define CNTR2_CFG_MASK					(0xf << 16)
-#define CNTR1_MCONNID_EN_SHIFT				15
-#define CNTR1_MCONNID_EN_MASK				(1 << 15)
-#define CNTR1_REGION_EN_SHIFT				14
-#define CNTR1_REGION_EN_MASK				(1 << 14)
-#define CNTR1_CFG_SHIFT					0
-#define CNTR1_CFG_MASK					(0xf << 0)
-
-/* PERFORMANCE_COUNTER_MASTER_REGION_SELECT */
-#define MCONNID2_SHIFT					24
-#define MCONNID2_MASK					(0xff << 24)
-#define REGION_SEL2_SHIFT				16
-#define REGION_SEL2_MASK				(0x3 << 16)
-#define MCONNID1_SHIFT					8
-#define MCONNID1_MASK					(0xff << 8)
-#define REGION_SEL1_SHIFT				0
-#define REGION_SEL1_MASK				(0x3 << 0)
-
-/* PERFORMANCE_COUNTER_TIME */
-#define TOTAL_TIME_SHIFT				0
-#define TOTAL_TIME_MASK					(0xffffffff << 0)
-
-/* DLL_CALIB_CTRL */
-#define ACK_WAIT_SHIFT					16
-#define ACK_WAIT_MASK					(0xf << 16)
-#define DLL_CALIB_INTERVAL_SHIFT			0
-#define DLL_CALIB_INTERVAL_MASK				(0x1ff << 0)
-
-/* END_OF_INTERRUPT */
-#define EOI_SHIFT					0
-#define EOI_MASK					(1 << 0)
-
-/* SYSTEM_OCP_INTERRUPT_RAW_STATUS */
-#define DNV_SYS_SHIFT					2
-#define DNV_SYS_MASK					(1 << 2)
-#define TA_SYS_SHIFT					1
-#define TA_SYS_MASK					(1 << 1)
-#define ERR_SYS_SHIFT					0
-#define ERR_SYS_MASK					(1 << 0)
-
-/* LOW_LATENCY_OCP_INTERRUPT_RAW_STATUS */
-#define DNV_LL_SHIFT					2
-#define DNV_LL_MASK					(1 << 2)
-#define TA_LL_SHIFT					1
-#define TA_LL_MASK					(1 << 1)
-#define ERR_LL_SHIFT					0
-#define ERR_LL_MASK					(1 << 0)
-
-/* SYSTEM_OCP_INTERRUPT_ENABLE_SET */
-#define EN_DNV_SYS_SHIFT				2
-#define EN_DNV_SYS_MASK					(1 << 2)
-#define EN_TA_SYS_SHIFT					1
-#define EN_TA_SYS_MASK					(1 << 1)
-#define EN_ERR_SYS_SHIFT					0
-#define EN_ERR_SYS_MASK					(1 << 0)
-
-/* LOW_LATENCY_OCP_INTERRUPT_ENABLE_SET */
-#define EN_DNV_LL_SHIFT					2
-#define EN_DNV_LL_MASK					(1 << 2)
-#define EN_TA_LL_SHIFT					1
-#define EN_TA_LL_MASK					(1 << 1)
-#define EN_ERR_LL_SHIFT					0
-#define EN_ERR_LL_MASK					(1 << 0)
-
-/* SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG */
-#define ZQ_CS1EN_SHIFT					31
-#define ZQ_CS1EN_MASK					(1 << 31)
-#define ZQ_CS0EN_SHIFT					30
-#define ZQ_CS0EN_MASK					(1 << 30)
-#define ZQ_DUALCALEN_SHIFT				29
-#define ZQ_DUALCALEN_MASK				(1 << 29)
-#define ZQ_SFEXITEN_SHIFT				28
-#define ZQ_SFEXITEN_MASK				(1 << 28)
-#define ZQ_ZQINIT_MULT_SHIFT				18
-#define ZQ_ZQINIT_MULT_MASK				(0x3 << 18)
-#define ZQ_ZQCL_MULT_SHIFT				16
-#define ZQ_ZQCL_MULT_MASK				(0x3 << 16)
-#define ZQ_REFINTERVAL_SHIFT				0
-#define ZQ_REFINTERVAL_MASK				(0xffff << 0)
-
-/* TEMPERATURE_ALERT_CONFIG */
-#define TA_CS1EN_SHIFT					31
-#define TA_CS1EN_MASK					(1 << 31)
-#define TA_CS0EN_SHIFT					30
-#define TA_CS0EN_MASK					(1 << 30)
-#define TA_SFEXITEN_SHIFT				28
-#define TA_SFEXITEN_MASK				(1 << 28)
-#define TA_DEVWDT_SHIFT					26
-#define TA_DEVWDT_MASK					(0x3 << 26)
-#define TA_DEVCNT_SHIFT					24
-#define TA_DEVCNT_MASK					(0x3 << 24)
-#define TA_REFINTERVAL_SHIFT				0
-#define TA_REFINTERVAL_MASK				(0x3fffff << 0)
-
-/* OCP_ERROR_LOG */
-#define MADDRSPACE_SHIFT				14
-#define MADDRSPACE_MASK					(0x3 << 14)
-#define MBURSTSEQ_SHIFT					11
-#define MBURSTSEQ_MASK					(0x7 << 11)
-#define MCMD_SHIFT					8
-#define MCMD_MASK					(0x7 << 8)
-#define MCONNID_SHIFT					0
-#define MCONNID_MASK					(0xff << 0)
-
-/* DDR_PHY_CTRL_1 - EMIF4D */
-#define DLL_SLAVE_DLY_CTRL_SHIFT_4D			4
-#define DLL_SLAVE_DLY_CTRL_MASK_4D			(0xFF << 4)
-#define READ_LATENCY_SHIFT_4D				0
-#define READ_LATENCY_MASK_4D				(0xf << 0)
-
-/* DDR_PHY_CTRL_1 - EMIF4D5 */
-#define DLL_HALF_DELAY_SHIFT_4D5			21
-#define DLL_HALF_DELAY_MASK_4D5				(1 << 21)
-#define READ_LATENCY_SHIFT_4D5				0
-#define READ_LATENCY_MASK_4D5				(0x1f << 0)
-
-/* DDR_PHY_CTRL_1_SHDW */
-#define DDR_PHY_CTRL_1_SHDW_SHIFT			5
-#define DDR_PHY_CTRL_1_SHDW_MASK			(0x7ffffff << 5)
-#define READ_LATENCY_SHDW_SHIFT				0
-#define READ_LATENCY_SHDW_MASK				(0x1f << 0)
+#include <linux/ti_emif.h>
 
 #ifndef __ASSEMBLY__
 /*
diff --git a/include/linux/ti_emif.h b/include/linux/ti_emif.h
new file mode 100644
index 0000000..be26e7f
--- /dev/null
+++ b/include/linux/ti_emif.h
@@ -0,0 +1,558 @@
+/*
+ * Register defines for the EMIF driver
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@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.
+ */
+#ifndef __TI_EMIF_H
+#define __TI_EMIF_H
+
+/*
+ * Maximum number of different frequencies supported by EMIF driver
+ * Determines the number of entries in the pointer array for register
+ * cache
+ */
+#define EMIF_MAX_NUM_FREQUENCIES			6
+
+/* State of the core voltage */
+#define DDR_VOLTAGE_STABLE				0
+#define DDR_VOLTAGE_RAMPING				1
+
+/* Defines for timing De-rating */
+#define EMIF_NORMAL_TIMINGS				0
+#define EMIF_DERATED_TIMINGS				1
+
+/* Length of the forced read idle period in terms of cycles */
+#define EMIF_READ_IDLE_LEN_VAL				5
+
+/*
+ * forced read idle interval to be used when voltage
+ * is changed as part of DVFS/DPS - 1ms
+ */
+#define READ_IDLE_INTERVAL_DVFS				(1*1000000)
+
+/*
+ * Forced read idle interval to be used when voltage is stable
+ * 50us - or maximum value will do
+ */
+#define READ_IDLE_INTERVAL_NORMAL			(50*1000000)
+
+/* DLL calibration interval when voltage is NOT stable - 1us */
+#define DLL_CALIB_INTERVAL_DVFS				(1*1000000)
+
+#define DLL_CALIB_ACK_WAIT_VAL				5
+
+/* Interval between ZQCS commands - hw team recommended value */
+#define EMIF_ZQCS_INTERVAL_US				(50*1000)
+/* Enable ZQ Calibration on exiting Self-refresh */
+#define ZQ_SFEXITEN_ENABLE				1
+/*
+ * ZQ Calibration simultaneously on both chip-selects:
+ * Needs one calibration resistor per CS
+ */
+#define	ZQ_DUALCALEN_DISABLE				0
+#define	ZQ_DUALCALEN_ENABLE				1
+
+#define T_ZQCS_DEFAULT_NS				90
+#define T_ZQCL_DEFAULT_NS				360
+#define T_ZQINIT_DEFAULT_NS				1000
+
+/* DPD_EN */
+#define DPD_DISABLE					0
+#define DPD_ENABLE					1
+
+/*
+ * Default values for the low-power entry to be used if not provided by user.
+ * OMAP4/5 has a hw bug(i735) due to which this value can not be less than 512
+ * Timeout values are in DDR clock 'cycles' and frequency threshold in Hz
+ */
+#define EMIF_LP_MODE_TIMEOUT_PERFORMANCE		2048
+#define EMIF_LP_MODE_TIMEOUT_POWER			512
+#define EMIF_LP_MODE_FREQ_THRESHOLD			400000000
+
+/* DDR_PHY_CTRL_1 values for EMIF4D - ATTILA PHY combination */
+#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY		0x049FF000
+#define EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY	0x41
+#define EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY	0x80
+#define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY 0xFF
+
+/* DDR_PHY_CTRL_1 values for EMIF4D5 INTELLIPHY combination */
+#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY		0x0E084200
+#define EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS	10000
+
+/* TEMP_ALERT_CONFIG - corresponding to temp gradient 5 C/s */
+#define TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS		360
+
+#define EMIF_T_CSTA					3
+#define EMIF_T_PDLL_UL					128
+
+/* External PHY control registers magic values */
+#define EMIF_EXT_PHY_CTRL_1_VAL				0x04020080
+#define EMIF_EXT_PHY_CTRL_5_VAL				0x04010040
+#define EMIF_EXT_PHY_CTRL_6_VAL				0x01004010
+#define EMIF_EXT_PHY_CTRL_7_VAL				0x00001004
+#define EMIF_EXT_PHY_CTRL_8_VAL				0x04010040
+#define EMIF_EXT_PHY_CTRL_9_VAL				0x01004010
+#define EMIF_EXT_PHY_CTRL_10_VAL			0x00001004
+#define EMIF_EXT_PHY_CTRL_11_VAL			0x00000000
+#define EMIF_EXT_PHY_CTRL_12_VAL			0x00000000
+#define EMIF_EXT_PHY_CTRL_13_VAL			0x00000000
+#define EMIF_EXT_PHY_CTRL_14_VAL			0x80080080
+#define EMIF_EXT_PHY_CTRL_15_VAL			0x00800800
+#define EMIF_EXT_PHY_CTRL_16_VAL			0x08102040
+#define EMIF_EXT_PHY_CTRL_17_VAL			0x00000001
+#define EMIF_EXT_PHY_CTRL_18_VAL			0x540A8150
+#define EMIF_EXT_PHY_CTRL_19_VAL			0xA81502A0
+#define EMIF_EXT_PHY_CTRL_20_VAL			0x002A0540
+#define EMIF_EXT_PHY_CTRL_21_VAL			0x00000000
+#define EMIF_EXT_PHY_CTRL_22_VAL			0x00000000
+#define EMIF_EXT_PHY_CTRL_23_VAL			0x00000000
+#define EMIF_EXT_PHY_CTRL_24_VAL			0x00000077
+
+#define EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS	1200
+
+/* Registers offset */
+#define EMIF_MODULE_ID_AND_REVISION			0x0000
+#define EMIF_STATUS					0x0004
+#define EMIF_SDRAM_CONFIG				0x0008
+#define EMIF_SDRAM_CONFIG_2				0x000c
+#define EMIF_SDRAM_REFRESH_CONTROL			0x0010
+#define EMIF_SDRAM_REFRESH_CTRL_SHDW			0x0014
+#define EMIF_SDRAM_TIMING_1				0x0018
+#define EMIF_SDRAM_TIMING_1_SHDW			0x001c
+#define EMIF_SDRAM_TIMING_2				0x0020
+#define EMIF_SDRAM_TIMING_2_SHDW			0x0024
+#define EMIF_SDRAM_TIMING_3				0x0028
+#define EMIF_SDRAM_TIMING_3_SHDW			0x002c
+#define EMIF_LPDDR2_NVM_TIMING				0x0030
+#define EMIF_LPDDR2_NVM_TIMING_SHDW			0x0034
+#define EMIF_POWER_MANAGEMENT_CONTROL			0x0038
+#define EMIF_POWER_MANAGEMENT_CTRL_SHDW			0x003c
+#define EMIF_LPDDR2_MODE_REG_DATA			0x0040
+#define EMIF_LPDDR2_MODE_REG_CONFIG			0x0050
+#define EMIF_OCP_CONFIG					0x0054
+#define EMIF_OCP_CONFIG_VALUE_1				0x0058
+#define EMIF_OCP_CONFIG_VALUE_2				0x005c
+#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL		0x0060
+#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT		0x0064
+#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT	0x0068
+#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1	0x006c
+#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2	0x0070
+#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3	0x0074
+#define EMIF_PERFORMANCE_COUNTER_1			0x0080
+#define EMIF_PERFORMANCE_COUNTER_2			0x0084
+#define EMIF_PERFORMANCE_COUNTER_CONFIG			0x0088
+#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT	0x008c
+#define EMIF_PERFORMANCE_COUNTER_TIME			0x0090
+#define EMIF_MISC_REG					0x0094
+#define EMIF_DLL_CALIB_CTRL				0x0098
+#define EMIF_DLL_CALIB_CTRL_SHDW			0x009c
+#define EMIF_END_OF_INTERRUPT				0x00a0
+#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS		0x00a4
+#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS		0x00a8
+#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS		0x00ac
+#define EMIF_LL_OCP_INTERRUPT_STATUS			0x00b0
+#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET		0x00b4
+#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET		0x00b8
+#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR		0x00bc
+#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR		0x00c0
+#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG	0x00c8
+#define EMIF_TEMPERATURE_ALERT_CONFIG			0x00cc
+#define EMIF_OCP_ERROR_LOG				0x00d0
+#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW		0x00d4
+#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL		0x00d8
+#define EMIF_READ_WRITE_LEVELING_CONTROL		0x00dc
+#define EMIF_DDR_PHY_CTRL_1				0x00e4
+#define EMIF_DDR_PHY_CTRL_1_SHDW			0x00e8
+#define EMIF_DDR_PHY_CTRL_2				0x00ec
+#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING	0x0100
+#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104
+#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108
+#define EMIF_READ_WRITE_EXECUTION_THRESHOLD		0x0120
+#define EMIF_COS_CONFIG					0x0124
+#define EMIF_PHY_STATUS_1				0x0140
+#define EMIF_PHY_STATUS_2				0x0144
+#define EMIF_PHY_STATUS_3				0x0148
+#define EMIF_PHY_STATUS_4				0x014c
+#define EMIF_PHY_STATUS_5				0x0150
+#define EMIF_PHY_STATUS_6				0x0154
+#define EMIF_PHY_STATUS_7				0x0158
+#define EMIF_PHY_STATUS_8				0x015c
+#define EMIF_PHY_STATUS_9				0x0160
+#define EMIF_PHY_STATUS_10				0x0164
+#define EMIF_PHY_STATUS_11				0x0168
+#define EMIF_PHY_STATUS_12				0x016c
+#define EMIF_PHY_STATUS_13				0x0170
+#define EMIF_PHY_STATUS_14				0x0174
+#define EMIF_PHY_STATUS_15				0x0178
+#define EMIF_PHY_STATUS_16				0x017c
+#define EMIF_PHY_STATUS_17				0x0180
+#define EMIF_PHY_STATUS_18				0x0184
+#define EMIF_PHY_STATUS_19				0x0188
+#define EMIF_PHY_STATUS_20				0x018c
+#define EMIF_PHY_STATUS_21				0x0190
+#define EMIF_EXT_PHY_CTRL_1				0x0200
+#define EMIF_EXT_PHY_CTRL_1_SHDW			0x0204
+#define EMIF_EXT_PHY_CTRL_2				0x0208
+#define EMIF_EXT_PHY_CTRL_2_SHDW			0x020c
+#define EMIF_EXT_PHY_CTRL_3				0x0210
+#define EMIF_EXT_PHY_CTRL_3_SHDW			0x0214
+#define EMIF_EXT_PHY_CTRL_4				0x0218
+#define EMIF_EXT_PHY_CTRL_4_SHDW			0x021c
+#define EMIF_EXT_PHY_CTRL_5				0x0220
+#define EMIF_EXT_PHY_CTRL_5_SHDW			0x0224
+#define EMIF_EXT_PHY_CTRL_6				0x0228
+#define EMIF_EXT_PHY_CTRL_6_SHDW			0x022c
+#define EMIF_EXT_PHY_CTRL_7				0x0230
+#define EMIF_EXT_PHY_CTRL_7_SHDW			0x0234
+#define EMIF_EXT_PHY_CTRL_8				0x0238
+#define EMIF_EXT_PHY_CTRL_8_SHDW			0x023c
+#define EMIF_EXT_PHY_CTRL_9				0x0240
+#define EMIF_EXT_PHY_CTRL_9_SHDW			0x0244
+#define EMIF_EXT_PHY_CTRL_10				0x0248
+#define EMIF_EXT_PHY_CTRL_10_SHDW			0x024c
+#define EMIF_EXT_PHY_CTRL_11				0x0250
+#define EMIF_EXT_PHY_CTRL_11_SHDW			0x0254
+#define EMIF_EXT_PHY_CTRL_12				0x0258
+#define EMIF_EXT_PHY_CTRL_12_SHDW			0x025c
+#define EMIF_EXT_PHY_CTRL_13				0x0260
+#define EMIF_EXT_PHY_CTRL_13_SHDW			0x0264
+#define EMIF_EXT_PHY_CTRL_14				0x0268
+#define EMIF_EXT_PHY_CTRL_14_SHDW			0x026c
+#define EMIF_EXT_PHY_CTRL_15				0x0270
+#define EMIF_EXT_PHY_CTRL_15_SHDW			0x0274
+#define EMIF_EXT_PHY_CTRL_16				0x0278
+#define EMIF_EXT_PHY_CTRL_16_SHDW			0x027c
+#define EMIF_EXT_PHY_CTRL_17				0x0280
+#define EMIF_EXT_PHY_CTRL_17_SHDW			0x0284
+#define EMIF_EXT_PHY_CTRL_18				0x0288
+#define EMIF_EXT_PHY_CTRL_18_SHDW			0x028c
+#define EMIF_EXT_PHY_CTRL_19				0x0290
+#define EMIF_EXT_PHY_CTRL_19_SHDW			0x0294
+#define EMIF_EXT_PHY_CTRL_20				0x0298
+#define EMIF_EXT_PHY_CTRL_20_SHDW			0x029c
+#define EMIF_EXT_PHY_CTRL_21				0x02a0
+#define EMIF_EXT_PHY_CTRL_21_SHDW			0x02a4
+#define EMIF_EXT_PHY_CTRL_22				0x02a8
+#define EMIF_EXT_PHY_CTRL_22_SHDW			0x02ac
+#define EMIF_EXT_PHY_CTRL_23				0x02b0
+#define EMIF_EXT_PHY_CTRL_23_SHDW			0x02b4
+#define EMIF_EXT_PHY_CTRL_24				0x02b8
+#define EMIF_EXT_PHY_CTRL_24_SHDW			0x02bc
+#define EMIF_EXT_PHY_CTRL_25				0x02c0
+#define EMIF_EXT_PHY_CTRL_25_SHDW			0x02c4
+#define EMIF_EXT_PHY_CTRL_26				0x02c8
+#define EMIF_EXT_PHY_CTRL_26_SHDW			0x02cc
+#define EMIF_EXT_PHY_CTRL_27				0x02d0
+#define EMIF_EXT_PHY_CTRL_27_SHDW			0x02d4
+#define EMIF_EXT_PHY_CTRL_28				0x02d8
+#define EMIF_EXT_PHY_CTRL_28_SHDW			0x02dc
+#define EMIF_EXT_PHY_CTRL_29				0x02e0
+#define EMIF_EXT_PHY_CTRL_29_SHDW			0x02e4
+#define EMIF_EXT_PHY_CTRL_30				0x02e8
+#define EMIF_EXT_PHY_CTRL_30_SHDW			0x02ec
+
+/* Registers shifts and masks */
+
+/* EMIF_MODULE_ID_AND_REVISION */
+#define SCHEME_SHIFT					30
+#define SCHEME_MASK					(0x3 << 30)
+#define MODULE_ID_SHIFT					16
+#define MODULE_ID_MASK					(0xfff << 16)
+#define RTL_VERSION_SHIFT				11
+#define RTL_VERSION_MASK				(0x1f << 11)
+#define MAJOR_REVISION_SHIFT				8
+#define MAJOR_REVISION_MASK				(0x7 << 8)
+#define MINOR_REVISION_SHIFT				0
+#define MINOR_REVISION_MASK				(0x3f << 0)
+
+/* STATUS */
+#define BE_SHIFT					31
+#define BE_MASK						(1 << 31)
+#define DUAL_CLK_MODE_SHIFT				30
+#define DUAL_CLK_MODE_MASK				(1 << 30)
+#define FAST_INIT_SHIFT					29
+#define FAST_INIT_MASK					(1 << 29)
+#define RDLVLGATETO_SHIFT				6
+#define RDLVLGATETO_MASK				(1 << 6)
+#define RDLVLTO_SHIFT					5
+#define RDLVLTO_MASK					(1 << 5)
+#define WRLVLTO_SHIFT					4
+#define WRLVLTO_MASK					(1 << 4)
+#define PHY_DLL_READY_SHIFT				2
+#define PHY_DLL_READY_MASK				(1 << 2)
+
+/* SDRAM_CONFIG */
+#define SDRAM_TYPE_SHIFT				29
+#define SDRAM_TYPE_MASK					(0x7 << 29)
+#define IBANK_POS_SHIFT					27
+#define IBANK_POS_MASK					(0x3 << 27)
+#define DDR_TERM_SHIFT					24
+#define DDR_TERM_MASK					(0x7 << 24)
+#define DDR2_DDQS_SHIFT					23
+#define DDR2_DDQS_MASK					(1 << 23)
+#define DYN_ODT_SHIFT					21
+#define DYN_ODT_MASK					(0x3 << 21)
+#define DDR_DISABLE_DLL_SHIFT				20
+#define DDR_DISABLE_DLL_MASK				(1 << 20)
+#define SDRAM_DRIVE_SHIFT				18
+#define SDRAM_DRIVE_MASK				(0x3 << 18)
+#define CWL_SHIFT					16
+#define CWL_MASK					(0x3 << 16)
+#define NARROW_MODE_SHIFT				14
+#define NARROW_MODE_MASK				(0x3 << 14)
+#define CL_SHIFT					10
+#define CL_MASK						(0xf << 10)
+#define ROWSIZE_SHIFT					7
+#define ROWSIZE_MASK					(0x7 << 7)
+#define IBANK_SHIFT					4
+#define IBANK_MASK					(0x7 << 4)
+#define EBANK_SHIFT					3
+#define EBANK_MASK					(1 << 3)
+#define PAGESIZE_SHIFT					0
+#define PAGESIZE_MASK					(0x7 << 0)
+
+/* SDRAM_CONFIG_2 */
+#define CS1NVMEN_SHIFT					30
+#define CS1NVMEN_MASK					(1 << 30)
+#define EBANK_POS_SHIFT					27
+#define EBANK_POS_MASK					(1 << 27)
+#define RDBNUM_SHIFT					4
+#define RDBNUM_MASK					(0x3 << 4)
+#define RDBSIZE_SHIFT					0
+#define RDBSIZE_MASK					(0x7 << 0)
+
+/* SDRAM_REFRESH_CONTROL */
+#define INITREF_DIS_SHIFT				31
+#define INITREF_DIS_MASK				(1 << 31)
+#define SRT_SHIFT					29
+#define SRT_MASK					(1 << 29)
+#define ASR_SHIFT					28
+#define ASR_MASK					(1 << 28)
+#define PASR_SHIFT					24
+#define PASR_MASK					(0x7 << 24)
+#define REFRESH_RATE_SHIFT				0
+#define REFRESH_RATE_MASK				(0xffff << 0)
+
+/* SDRAM_TIMING_1 */
+#define T_RTW_SHIFT					29
+#define T_RTW_MASK					(0x7 << 29)
+#define T_RP_SHIFT					25
+#define T_RP_MASK					(0xf << 25)
+#define T_RCD_SHIFT					21
+#define T_RCD_MASK					(0xf << 21)
+#define T_WR_SHIFT					17
+#define T_WR_MASK					(0xf << 17)
+#define T_RAS_SHIFT					12
+#define T_RAS_MASK					(0x1f << 12)
+#define T_RC_SHIFT					6
+#define T_RC_MASK					(0x3f << 6)
+#define T_RRD_SHIFT					3
+#define T_RRD_MASK					(0x7 << 3)
+#define T_WTR_SHIFT					0
+#define T_WTR_MASK					(0x7 << 0)
+
+/* SDRAM_TIMING_2 */
+#define T_XP_SHIFT					28
+#define T_XP_MASK					(0x7 << 28)
+#define T_ODT_SHIFT					25
+#define T_ODT_MASK					(0x7 << 25)
+#define T_XSNR_SHIFT					16
+#define T_XSNR_MASK					(0x1ff << 16)
+#define T_XSRD_SHIFT					6
+#define T_XSRD_MASK					(0x3ff << 6)
+#define T_RTP_SHIFT					3
+#define T_RTP_MASK					(0x7 << 3)
+#define T_CKE_SHIFT					0
+#define T_CKE_MASK					(0x7 << 0)
+
+/* SDRAM_TIMING_3 */
+#define T_PDLL_UL_SHIFT					28
+#define T_PDLL_UL_MASK					(0xf << 28)
+#define T_CSTA_SHIFT					24
+#define T_CSTA_MASK					(0xf << 24)
+#define T_CKESR_SHIFT					21
+#define T_CKESR_MASK					(0x7 << 21)
+#define ZQ_ZQCS_SHIFT					15
+#define ZQ_ZQCS_MASK					(0x3f << 15)
+#define T_TDQSCKMAX_SHIFT				13
+#define T_TDQSCKMAX_MASK				(0x3 << 13)
+#define T_RFC_SHIFT					4
+#define T_RFC_MASK					(0x1ff << 4)
+#define T_RAS_MAX_SHIFT					0
+#define T_RAS_MAX_MASK					(0xf << 0)
+
+/* POWER_MANAGEMENT_CONTROL */
+#define PD_TIM_SHIFT					12
+#define PD_TIM_MASK					(0xf << 12)
+#define DPD_EN_SHIFT					11
+#define DPD_EN_MASK					(1 << 11)
+#define LP_MODE_SHIFT					8
+#define LP_MODE_MASK					(0x7 << 8)
+#define SR_TIM_SHIFT					4
+#define SR_TIM_MASK					(0xf << 4)
+#define CS_TIM_SHIFT					0
+#define CS_TIM_MASK					(0xf << 0)
+
+/* LPDDR2_MODE_REG_DATA */
+#define VALUE_0_SHIFT					0
+#define VALUE_0_MASK					(0x7f << 0)
+
+/* LPDDR2_MODE_REG_CONFIG */
+#define CS_SHIFT					31
+#define CS_MASK						(1 << 31)
+#define REFRESH_EN_SHIFT				30
+#define REFRESH_EN_MASK					(1 << 30)
+#define ADDRESS_SHIFT					0
+#define ADDRESS_MASK					(0xff << 0)
+
+/* OCP_CONFIG */
+#define SYS_THRESH_MAX_SHIFT				24
+#define SYS_THRESH_MAX_MASK				(0xf << 24)
+#define MPU_THRESH_MAX_SHIFT				20
+#define MPU_THRESH_MAX_MASK				(0xf << 20)
+#define LL_THRESH_MAX_SHIFT				16
+#define LL_THRESH_MAX_MASK				(0xf << 16)
+
+/* PERFORMANCE_COUNTER_1 */
+#define COUNTER1_SHIFT					0
+#define COUNTER1_MASK					(0xffffffff << 0)
+
+/* PERFORMANCE_COUNTER_2 */
+#define COUNTER2_SHIFT					0
+#define COUNTER2_MASK					(0xffffffff << 0)
+
+/* PERFORMANCE_COUNTER_CONFIG */
+#define CNTR2_MCONNID_EN_SHIFT				31
+#define CNTR2_MCONNID_EN_MASK				(1 << 31)
+#define CNTR2_REGION_EN_SHIFT				30
+#define CNTR2_REGION_EN_MASK				(1 << 30)
+#define CNTR2_CFG_SHIFT					16
+#define CNTR2_CFG_MASK					(0xf << 16)
+#define CNTR1_MCONNID_EN_SHIFT				15
+#define CNTR1_MCONNID_EN_MASK				(1 << 15)
+#define CNTR1_REGION_EN_SHIFT				14
+#define CNTR1_REGION_EN_MASK				(1 << 14)
+#define CNTR1_CFG_SHIFT					0
+#define CNTR1_CFG_MASK					(0xf << 0)
+
+/* PERFORMANCE_COUNTER_MASTER_REGION_SELECT */
+#define MCONNID2_SHIFT					24
+#define MCONNID2_MASK					(0xff << 24)
+#define REGION_SEL2_SHIFT				16
+#define REGION_SEL2_MASK				(0x3 << 16)
+#define MCONNID1_SHIFT					8
+#define MCONNID1_MASK					(0xff << 8)
+#define REGION_SEL1_SHIFT				0
+#define REGION_SEL1_MASK				(0x3 << 0)
+
+/* PERFORMANCE_COUNTER_TIME */
+#define TOTAL_TIME_SHIFT				0
+#define TOTAL_TIME_MASK					(0xffffffff << 0)
+
+/* DLL_CALIB_CTRL */
+#define ACK_WAIT_SHIFT					16
+#define ACK_WAIT_MASK					(0xf << 16)
+#define DLL_CALIB_INTERVAL_SHIFT			0
+#define DLL_CALIB_INTERVAL_MASK				(0x1ff << 0)
+
+/* END_OF_INTERRUPT */
+#define EOI_SHIFT					0
+#define EOI_MASK					(1 << 0)
+
+/* SYSTEM_OCP_INTERRUPT_RAW_STATUS */
+#define DNV_SYS_SHIFT					2
+#define DNV_SYS_MASK					(1 << 2)
+#define TA_SYS_SHIFT					1
+#define TA_SYS_MASK					(1 << 1)
+#define ERR_SYS_SHIFT					0
+#define ERR_SYS_MASK					(1 << 0)
+
+/* LOW_LATENCY_OCP_INTERRUPT_RAW_STATUS */
+#define DNV_LL_SHIFT					2
+#define DNV_LL_MASK					(1 << 2)
+#define TA_LL_SHIFT					1
+#define TA_LL_MASK					(1 << 1)
+#define ERR_LL_SHIFT					0
+#define ERR_LL_MASK					(1 << 0)
+
+/* SYSTEM_OCP_INTERRUPT_ENABLE_SET */
+#define EN_DNV_SYS_SHIFT				2
+#define EN_DNV_SYS_MASK					(1 << 2)
+#define EN_TA_SYS_SHIFT					1
+#define EN_TA_SYS_MASK					(1 << 1)
+#define EN_ERR_SYS_SHIFT					0
+#define EN_ERR_SYS_MASK					(1 << 0)
+
+/* LOW_LATENCY_OCP_INTERRUPT_ENABLE_SET */
+#define EN_DNV_LL_SHIFT					2
+#define EN_DNV_LL_MASK					(1 << 2)
+#define EN_TA_LL_SHIFT					1
+#define EN_TA_LL_MASK					(1 << 1)
+#define EN_ERR_LL_SHIFT					0
+#define EN_ERR_LL_MASK					(1 << 0)
+
+/* SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG */
+#define ZQ_CS1EN_SHIFT					31
+#define ZQ_CS1EN_MASK					(1 << 31)
+#define ZQ_CS0EN_SHIFT					30
+#define ZQ_CS0EN_MASK					(1 << 30)
+#define ZQ_DUALCALEN_SHIFT				29
+#define ZQ_DUALCALEN_MASK				(1 << 29)
+#define ZQ_SFEXITEN_SHIFT				28
+#define ZQ_SFEXITEN_MASK				(1 << 28)
+#define ZQ_ZQINIT_MULT_SHIFT				18
+#define ZQ_ZQINIT_MULT_MASK				(0x3 << 18)
+#define ZQ_ZQCL_MULT_SHIFT				16
+#define ZQ_ZQCL_MULT_MASK				(0x3 << 16)
+#define ZQ_REFINTERVAL_SHIFT				0
+#define ZQ_REFINTERVAL_MASK				(0xffff << 0)
+
+/* TEMPERATURE_ALERT_CONFIG */
+#define TA_CS1EN_SHIFT					31
+#define TA_CS1EN_MASK					(1 << 31)
+#define TA_CS0EN_SHIFT					30
+#define TA_CS0EN_MASK					(1 << 30)
+#define TA_SFEXITEN_SHIFT				28
+#define TA_SFEXITEN_MASK				(1 << 28)
+#define TA_DEVWDT_SHIFT					26
+#define TA_DEVWDT_MASK					(0x3 << 26)
+#define TA_DEVCNT_SHIFT					24
+#define TA_DEVCNT_MASK					(0x3 << 24)
+#define TA_REFINTERVAL_SHIFT				0
+#define TA_REFINTERVAL_MASK				(0x3fffff << 0)
+
+/* OCP_ERROR_LOG */
+#define MADDRSPACE_SHIFT				14
+#define MADDRSPACE_MASK					(0x3 << 14)
+#define MBURSTSEQ_SHIFT					11
+#define MBURSTSEQ_MASK					(0x7 << 11)
+#define MCMD_SHIFT					8
+#define MCMD_MASK					(0x7 << 8)
+#define MCONNID_SHIFT					0
+#define MCONNID_MASK					(0xff << 0)
+
+/* DDR_PHY_CTRL_1 - EMIF4D */
+#define DLL_SLAVE_DLY_CTRL_SHIFT_4D			4
+#define DLL_SLAVE_DLY_CTRL_MASK_4D			(0xFF << 4)
+#define READ_LATENCY_SHIFT_4D				0
+#define READ_LATENCY_MASK_4D				(0xf << 0)
+
+/* DDR_PHY_CTRL_1 - EMIF4D5 */
+#define DLL_HALF_DELAY_SHIFT_4D5			21
+#define DLL_HALF_DELAY_MASK_4D5				(1 << 21)
+#define READ_LATENCY_SHIFT_4D5				0
+#define READ_LATENCY_MASK_4D5				(0x1f << 0)
+
+/* DDR_PHY_CTRL_1_SHDW */
+#define DDR_PHY_CTRL_1_SHDW_SHIFT			5
+#define DDR_PHY_CTRL_1_SHDW_MASK			(0x7ffffff << 5)
+#define READ_LATENCY_SHDW_SHIFT				0
+#define READ_LATENCY_SHDW_MASK				(0x1f << 0)
+
+#endif /* __TI_EMIF_H */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 212+ messages in thread

* [PATCHv3 1/9] memory: emif: Move EMIF register defines to include/linux/
@ 2013-08-06 17:49   ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel

OMAP4 and AM33XX share the same EMIF controller IP. Although there
are significant differences in the IP integration due to which
AM33XX can't reuse the EMIF driver DVFS similar to OMAP4,
it can definitely benefit by reusing the EMIF related macros
defined in drivers/memory/emif.h.

In the current OMAP PM framework the PM code resides under
arch/arm/mach-omap2/. To enable reuse of the register defines move
the register defines in the emif header file to include/linux so that
both the EMIF driver and the AM33XX PM code can benefit.

Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <benoit.cousson@linaro.org>
Cc: Aneesh V <aneesh@ti.com>
---
 drivers/memory/emif.h   |  543 +--------------------------------------------
 include/linux/ti_emif.h |  558 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 559 insertions(+), 542 deletions(-)
 create mode 100644 include/linux/ti_emif.h

diff --git a/drivers/memory/emif.h b/drivers/memory/emif.h
index bfe08ba..8214f07 100644
--- a/drivers/memory/emif.h
+++ b/drivers/memory/emif.h
@@ -12,548 +12,7 @@
 #ifndef __EMIF_H
 #define __EMIF_H
 
-/*
- * Maximum number of different frequencies supported by EMIF driver
- * Determines the number of entries in the pointer array for register
- * cache
- */
-#define EMIF_MAX_NUM_FREQUENCIES			6
-
-/* State of the core voltage */
-#define DDR_VOLTAGE_STABLE				0
-#define DDR_VOLTAGE_RAMPING				1
-
-/* Defines for timing De-rating */
-#define EMIF_NORMAL_TIMINGS				0
-#define EMIF_DERATED_TIMINGS				1
-
-/* Length of the forced read idle period in terms of cycles */
-#define EMIF_READ_IDLE_LEN_VAL				5
-
-/*
- * forced read idle interval to be used when voltage
- * is changed as part of DVFS/DPS - 1ms
- */
-#define READ_IDLE_INTERVAL_DVFS				(1*1000000)
-
-/*
- * Forced read idle interval to be used when voltage is stable
- * 50us - or maximum value will do
- */
-#define READ_IDLE_INTERVAL_NORMAL			(50*1000000)
-
-/* DLL calibration interval when voltage is NOT stable - 1us */
-#define DLL_CALIB_INTERVAL_DVFS				(1*1000000)
-
-#define DLL_CALIB_ACK_WAIT_VAL				5
-
-/* Interval between ZQCS commands - hw team recommended value */
-#define EMIF_ZQCS_INTERVAL_US				(50*1000)
-/* Enable ZQ Calibration on exiting Self-refresh */
-#define ZQ_SFEXITEN_ENABLE				1
-/*
- * ZQ Calibration simultaneously on both chip-selects:
- * Needs one calibration resistor per CS
- */
-#define	ZQ_DUALCALEN_DISABLE				0
-#define	ZQ_DUALCALEN_ENABLE				1
-
-#define T_ZQCS_DEFAULT_NS				90
-#define T_ZQCL_DEFAULT_NS				360
-#define T_ZQINIT_DEFAULT_NS				1000
-
-/* DPD_EN */
-#define DPD_DISABLE					0
-#define DPD_ENABLE					1
-
-/*
- * Default values for the low-power entry to be used if not provided by user.
- * OMAP4/5 has a hw bug(i735) due to which this value can not be less than 512
- * Timeout values are in DDR clock 'cycles' and frequency threshold in Hz
- */
-#define EMIF_LP_MODE_TIMEOUT_PERFORMANCE		2048
-#define EMIF_LP_MODE_TIMEOUT_POWER			512
-#define EMIF_LP_MODE_FREQ_THRESHOLD			400000000
-
-/* DDR_PHY_CTRL_1 values for EMIF4D - ATTILA PHY combination */
-#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY		0x049FF000
-#define EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY	0x41
-#define EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY	0x80
-#define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY 0xFF
-
-/* DDR_PHY_CTRL_1 values for EMIF4D5 INTELLIPHY combination */
-#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY		0x0E084200
-#define EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS	10000
-
-/* TEMP_ALERT_CONFIG - corresponding to temp gradient 5 C/s */
-#define TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS		360
-
-#define EMIF_T_CSTA					3
-#define EMIF_T_PDLL_UL					128
-
-/* External PHY control registers magic values */
-#define EMIF_EXT_PHY_CTRL_1_VAL				0x04020080
-#define EMIF_EXT_PHY_CTRL_5_VAL				0x04010040
-#define EMIF_EXT_PHY_CTRL_6_VAL				0x01004010
-#define EMIF_EXT_PHY_CTRL_7_VAL				0x00001004
-#define EMIF_EXT_PHY_CTRL_8_VAL				0x04010040
-#define EMIF_EXT_PHY_CTRL_9_VAL				0x01004010
-#define EMIF_EXT_PHY_CTRL_10_VAL			0x00001004
-#define EMIF_EXT_PHY_CTRL_11_VAL			0x00000000
-#define EMIF_EXT_PHY_CTRL_12_VAL			0x00000000
-#define EMIF_EXT_PHY_CTRL_13_VAL			0x00000000
-#define EMIF_EXT_PHY_CTRL_14_VAL			0x80080080
-#define EMIF_EXT_PHY_CTRL_15_VAL			0x00800800
-#define EMIF_EXT_PHY_CTRL_16_VAL			0x08102040
-#define EMIF_EXT_PHY_CTRL_17_VAL			0x00000001
-#define EMIF_EXT_PHY_CTRL_18_VAL			0x540A8150
-#define EMIF_EXT_PHY_CTRL_19_VAL			0xA81502A0
-#define EMIF_EXT_PHY_CTRL_20_VAL			0x002A0540
-#define EMIF_EXT_PHY_CTRL_21_VAL			0x00000000
-#define EMIF_EXT_PHY_CTRL_22_VAL			0x00000000
-#define EMIF_EXT_PHY_CTRL_23_VAL			0x00000000
-#define EMIF_EXT_PHY_CTRL_24_VAL			0x00000077
-
-#define EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS	1200
-
-/* Registers offset */
-#define EMIF_MODULE_ID_AND_REVISION			0x0000
-#define EMIF_STATUS					0x0004
-#define EMIF_SDRAM_CONFIG				0x0008
-#define EMIF_SDRAM_CONFIG_2				0x000c
-#define EMIF_SDRAM_REFRESH_CONTROL			0x0010
-#define EMIF_SDRAM_REFRESH_CTRL_SHDW			0x0014
-#define EMIF_SDRAM_TIMING_1				0x0018
-#define EMIF_SDRAM_TIMING_1_SHDW			0x001c
-#define EMIF_SDRAM_TIMING_2				0x0020
-#define EMIF_SDRAM_TIMING_2_SHDW			0x0024
-#define EMIF_SDRAM_TIMING_3				0x0028
-#define EMIF_SDRAM_TIMING_3_SHDW			0x002c
-#define EMIF_LPDDR2_NVM_TIMING				0x0030
-#define EMIF_LPDDR2_NVM_TIMING_SHDW			0x0034
-#define EMIF_POWER_MANAGEMENT_CONTROL			0x0038
-#define EMIF_POWER_MANAGEMENT_CTRL_SHDW			0x003c
-#define EMIF_LPDDR2_MODE_REG_DATA			0x0040
-#define EMIF_LPDDR2_MODE_REG_CONFIG			0x0050
-#define EMIF_OCP_CONFIG					0x0054
-#define EMIF_OCP_CONFIG_VALUE_1				0x0058
-#define EMIF_OCP_CONFIG_VALUE_2				0x005c
-#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL		0x0060
-#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT		0x0064
-#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT	0x0068
-#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1	0x006c
-#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2	0x0070
-#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3	0x0074
-#define EMIF_PERFORMANCE_COUNTER_1			0x0080
-#define EMIF_PERFORMANCE_COUNTER_2			0x0084
-#define EMIF_PERFORMANCE_COUNTER_CONFIG			0x0088
-#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT	0x008c
-#define EMIF_PERFORMANCE_COUNTER_TIME			0x0090
-#define EMIF_MISC_REG					0x0094
-#define EMIF_DLL_CALIB_CTRL				0x0098
-#define EMIF_DLL_CALIB_CTRL_SHDW			0x009c
-#define EMIF_END_OF_INTERRUPT				0x00a0
-#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS		0x00a4
-#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS		0x00a8
-#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS		0x00ac
-#define EMIF_LL_OCP_INTERRUPT_STATUS			0x00b0
-#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET		0x00b4
-#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET		0x00b8
-#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR		0x00bc
-#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR		0x00c0
-#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG	0x00c8
-#define EMIF_TEMPERATURE_ALERT_CONFIG			0x00cc
-#define EMIF_OCP_ERROR_LOG				0x00d0
-#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW		0x00d4
-#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL		0x00d8
-#define EMIF_READ_WRITE_LEVELING_CONTROL		0x00dc
-#define EMIF_DDR_PHY_CTRL_1				0x00e4
-#define EMIF_DDR_PHY_CTRL_1_SHDW			0x00e8
-#define EMIF_DDR_PHY_CTRL_2				0x00ec
-#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING	0x0100
-#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104
-#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108
-#define EMIF_READ_WRITE_EXECUTION_THRESHOLD		0x0120
-#define EMIF_COS_CONFIG					0x0124
-#define EMIF_PHY_STATUS_1				0x0140
-#define EMIF_PHY_STATUS_2				0x0144
-#define EMIF_PHY_STATUS_3				0x0148
-#define EMIF_PHY_STATUS_4				0x014c
-#define EMIF_PHY_STATUS_5				0x0150
-#define EMIF_PHY_STATUS_6				0x0154
-#define EMIF_PHY_STATUS_7				0x0158
-#define EMIF_PHY_STATUS_8				0x015c
-#define EMIF_PHY_STATUS_9				0x0160
-#define EMIF_PHY_STATUS_10				0x0164
-#define EMIF_PHY_STATUS_11				0x0168
-#define EMIF_PHY_STATUS_12				0x016c
-#define EMIF_PHY_STATUS_13				0x0170
-#define EMIF_PHY_STATUS_14				0x0174
-#define EMIF_PHY_STATUS_15				0x0178
-#define EMIF_PHY_STATUS_16				0x017c
-#define EMIF_PHY_STATUS_17				0x0180
-#define EMIF_PHY_STATUS_18				0x0184
-#define EMIF_PHY_STATUS_19				0x0188
-#define EMIF_PHY_STATUS_20				0x018c
-#define EMIF_PHY_STATUS_21				0x0190
-#define EMIF_EXT_PHY_CTRL_1				0x0200
-#define EMIF_EXT_PHY_CTRL_1_SHDW			0x0204
-#define EMIF_EXT_PHY_CTRL_2				0x0208
-#define EMIF_EXT_PHY_CTRL_2_SHDW			0x020c
-#define EMIF_EXT_PHY_CTRL_3				0x0210
-#define EMIF_EXT_PHY_CTRL_3_SHDW			0x0214
-#define EMIF_EXT_PHY_CTRL_4				0x0218
-#define EMIF_EXT_PHY_CTRL_4_SHDW			0x021c
-#define EMIF_EXT_PHY_CTRL_5				0x0220
-#define EMIF_EXT_PHY_CTRL_5_SHDW			0x0224
-#define EMIF_EXT_PHY_CTRL_6				0x0228
-#define EMIF_EXT_PHY_CTRL_6_SHDW			0x022c
-#define EMIF_EXT_PHY_CTRL_7				0x0230
-#define EMIF_EXT_PHY_CTRL_7_SHDW			0x0234
-#define EMIF_EXT_PHY_CTRL_8				0x0238
-#define EMIF_EXT_PHY_CTRL_8_SHDW			0x023c
-#define EMIF_EXT_PHY_CTRL_9				0x0240
-#define EMIF_EXT_PHY_CTRL_9_SHDW			0x0244
-#define EMIF_EXT_PHY_CTRL_10				0x0248
-#define EMIF_EXT_PHY_CTRL_10_SHDW			0x024c
-#define EMIF_EXT_PHY_CTRL_11				0x0250
-#define EMIF_EXT_PHY_CTRL_11_SHDW			0x0254
-#define EMIF_EXT_PHY_CTRL_12				0x0258
-#define EMIF_EXT_PHY_CTRL_12_SHDW			0x025c
-#define EMIF_EXT_PHY_CTRL_13				0x0260
-#define EMIF_EXT_PHY_CTRL_13_SHDW			0x0264
-#define EMIF_EXT_PHY_CTRL_14				0x0268
-#define EMIF_EXT_PHY_CTRL_14_SHDW			0x026c
-#define EMIF_EXT_PHY_CTRL_15				0x0270
-#define EMIF_EXT_PHY_CTRL_15_SHDW			0x0274
-#define EMIF_EXT_PHY_CTRL_16				0x0278
-#define EMIF_EXT_PHY_CTRL_16_SHDW			0x027c
-#define EMIF_EXT_PHY_CTRL_17				0x0280
-#define EMIF_EXT_PHY_CTRL_17_SHDW			0x0284
-#define EMIF_EXT_PHY_CTRL_18				0x0288
-#define EMIF_EXT_PHY_CTRL_18_SHDW			0x028c
-#define EMIF_EXT_PHY_CTRL_19				0x0290
-#define EMIF_EXT_PHY_CTRL_19_SHDW			0x0294
-#define EMIF_EXT_PHY_CTRL_20				0x0298
-#define EMIF_EXT_PHY_CTRL_20_SHDW			0x029c
-#define EMIF_EXT_PHY_CTRL_21				0x02a0
-#define EMIF_EXT_PHY_CTRL_21_SHDW			0x02a4
-#define EMIF_EXT_PHY_CTRL_22				0x02a8
-#define EMIF_EXT_PHY_CTRL_22_SHDW			0x02ac
-#define EMIF_EXT_PHY_CTRL_23				0x02b0
-#define EMIF_EXT_PHY_CTRL_23_SHDW			0x02b4
-#define EMIF_EXT_PHY_CTRL_24				0x02b8
-#define EMIF_EXT_PHY_CTRL_24_SHDW			0x02bc
-#define EMIF_EXT_PHY_CTRL_25				0x02c0
-#define EMIF_EXT_PHY_CTRL_25_SHDW			0x02c4
-#define EMIF_EXT_PHY_CTRL_26				0x02c8
-#define EMIF_EXT_PHY_CTRL_26_SHDW			0x02cc
-#define EMIF_EXT_PHY_CTRL_27				0x02d0
-#define EMIF_EXT_PHY_CTRL_27_SHDW			0x02d4
-#define EMIF_EXT_PHY_CTRL_28				0x02d8
-#define EMIF_EXT_PHY_CTRL_28_SHDW			0x02dc
-#define EMIF_EXT_PHY_CTRL_29				0x02e0
-#define EMIF_EXT_PHY_CTRL_29_SHDW			0x02e4
-#define EMIF_EXT_PHY_CTRL_30				0x02e8
-#define EMIF_EXT_PHY_CTRL_30_SHDW			0x02ec
-
-/* Registers shifts and masks */
-
-/* EMIF_MODULE_ID_AND_REVISION */
-#define SCHEME_SHIFT					30
-#define SCHEME_MASK					(0x3 << 30)
-#define MODULE_ID_SHIFT					16
-#define MODULE_ID_MASK					(0xfff << 16)
-#define RTL_VERSION_SHIFT				11
-#define RTL_VERSION_MASK				(0x1f << 11)
-#define MAJOR_REVISION_SHIFT				8
-#define MAJOR_REVISION_MASK				(0x7 << 8)
-#define MINOR_REVISION_SHIFT				0
-#define MINOR_REVISION_MASK				(0x3f << 0)
-
-/* STATUS */
-#define BE_SHIFT					31
-#define BE_MASK						(1 << 31)
-#define DUAL_CLK_MODE_SHIFT				30
-#define DUAL_CLK_MODE_MASK				(1 << 30)
-#define FAST_INIT_SHIFT					29
-#define FAST_INIT_MASK					(1 << 29)
-#define RDLVLGATETO_SHIFT				6
-#define RDLVLGATETO_MASK				(1 << 6)
-#define RDLVLTO_SHIFT					5
-#define RDLVLTO_MASK					(1 << 5)
-#define WRLVLTO_SHIFT					4
-#define WRLVLTO_MASK					(1 << 4)
-#define PHY_DLL_READY_SHIFT				2
-#define PHY_DLL_READY_MASK				(1 << 2)
-
-/* SDRAM_CONFIG */
-#define SDRAM_TYPE_SHIFT				29
-#define SDRAM_TYPE_MASK					(0x7 << 29)
-#define IBANK_POS_SHIFT					27
-#define IBANK_POS_MASK					(0x3 << 27)
-#define DDR_TERM_SHIFT					24
-#define DDR_TERM_MASK					(0x7 << 24)
-#define DDR2_DDQS_SHIFT					23
-#define DDR2_DDQS_MASK					(1 << 23)
-#define DYN_ODT_SHIFT					21
-#define DYN_ODT_MASK					(0x3 << 21)
-#define DDR_DISABLE_DLL_SHIFT				20
-#define DDR_DISABLE_DLL_MASK				(1 << 20)
-#define SDRAM_DRIVE_SHIFT				18
-#define SDRAM_DRIVE_MASK				(0x3 << 18)
-#define CWL_SHIFT					16
-#define CWL_MASK					(0x3 << 16)
-#define NARROW_MODE_SHIFT				14
-#define NARROW_MODE_MASK				(0x3 << 14)
-#define CL_SHIFT					10
-#define CL_MASK						(0xf << 10)
-#define ROWSIZE_SHIFT					7
-#define ROWSIZE_MASK					(0x7 << 7)
-#define IBANK_SHIFT					4
-#define IBANK_MASK					(0x7 << 4)
-#define EBANK_SHIFT					3
-#define EBANK_MASK					(1 << 3)
-#define PAGESIZE_SHIFT					0
-#define PAGESIZE_MASK					(0x7 << 0)
-
-/* SDRAM_CONFIG_2 */
-#define CS1NVMEN_SHIFT					30
-#define CS1NVMEN_MASK					(1 << 30)
-#define EBANK_POS_SHIFT					27
-#define EBANK_POS_MASK					(1 << 27)
-#define RDBNUM_SHIFT					4
-#define RDBNUM_MASK					(0x3 << 4)
-#define RDBSIZE_SHIFT					0
-#define RDBSIZE_MASK					(0x7 << 0)
-
-/* SDRAM_REFRESH_CONTROL */
-#define INITREF_DIS_SHIFT				31
-#define INITREF_DIS_MASK				(1 << 31)
-#define SRT_SHIFT					29
-#define SRT_MASK					(1 << 29)
-#define ASR_SHIFT					28
-#define ASR_MASK					(1 << 28)
-#define PASR_SHIFT					24
-#define PASR_MASK					(0x7 << 24)
-#define REFRESH_RATE_SHIFT				0
-#define REFRESH_RATE_MASK				(0xffff << 0)
-
-/* SDRAM_TIMING_1 */
-#define T_RTW_SHIFT					29
-#define T_RTW_MASK					(0x7 << 29)
-#define T_RP_SHIFT					25
-#define T_RP_MASK					(0xf << 25)
-#define T_RCD_SHIFT					21
-#define T_RCD_MASK					(0xf << 21)
-#define T_WR_SHIFT					17
-#define T_WR_MASK					(0xf << 17)
-#define T_RAS_SHIFT					12
-#define T_RAS_MASK					(0x1f << 12)
-#define T_RC_SHIFT					6
-#define T_RC_MASK					(0x3f << 6)
-#define T_RRD_SHIFT					3
-#define T_RRD_MASK					(0x7 << 3)
-#define T_WTR_SHIFT					0
-#define T_WTR_MASK					(0x7 << 0)
-
-/* SDRAM_TIMING_2 */
-#define T_XP_SHIFT					28
-#define T_XP_MASK					(0x7 << 28)
-#define T_ODT_SHIFT					25
-#define T_ODT_MASK					(0x7 << 25)
-#define T_XSNR_SHIFT					16
-#define T_XSNR_MASK					(0x1ff << 16)
-#define T_XSRD_SHIFT					6
-#define T_XSRD_MASK					(0x3ff << 6)
-#define T_RTP_SHIFT					3
-#define T_RTP_MASK					(0x7 << 3)
-#define T_CKE_SHIFT					0
-#define T_CKE_MASK					(0x7 << 0)
-
-/* SDRAM_TIMING_3 */
-#define T_PDLL_UL_SHIFT					28
-#define T_PDLL_UL_MASK					(0xf << 28)
-#define T_CSTA_SHIFT					24
-#define T_CSTA_MASK					(0xf << 24)
-#define T_CKESR_SHIFT					21
-#define T_CKESR_MASK					(0x7 << 21)
-#define ZQ_ZQCS_SHIFT					15
-#define ZQ_ZQCS_MASK					(0x3f << 15)
-#define T_TDQSCKMAX_SHIFT				13
-#define T_TDQSCKMAX_MASK				(0x3 << 13)
-#define T_RFC_SHIFT					4
-#define T_RFC_MASK					(0x1ff << 4)
-#define T_RAS_MAX_SHIFT					0
-#define T_RAS_MAX_MASK					(0xf << 0)
-
-/* POWER_MANAGEMENT_CONTROL */
-#define PD_TIM_SHIFT					12
-#define PD_TIM_MASK					(0xf << 12)
-#define DPD_EN_SHIFT					11
-#define DPD_EN_MASK					(1 << 11)
-#define LP_MODE_SHIFT					8
-#define LP_MODE_MASK					(0x7 << 8)
-#define SR_TIM_SHIFT					4
-#define SR_TIM_MASK					(0xf << 4)
-#define CS_TIM_SHIFT					0
-#define CS_TIM_MASK					(0xf << 0)
-
-/* LPDDR2_MODE_REG_DATA */
-#define VALUE_0_SHIFT					0
-#define VALUE_0_MASK					(0x7f << 0)
-
-/* LPDDR2_MODE_REG_CONFIG */
-#define CS_SHIFT					31
-#define CS_MASK						(1 << 31)
-#define REFRESH_EN_SHIFT				30
-#define REFRESH_EN_MASK					(1 << 30)
-#define ADDRESS_SHIFT					0
-#define ADDRESS_MASK					(0xff << 0)
-
-/* OCP_CONFIG */
-#define SYS_THRESH_MAX_SHIFT				24
-#define SYS_THRESH_MAX_MASK				(0xf << 24)
-#define MPU_THRESH_MAX_SHIFT				20
-#define MPU_THRESH_MAX_MASK				(0xf << 20)
-#define LL_THRESH_MAX_SHIFT				16
-#define LL_THRESH_MAX_MASK				(0xf << 16)
-
-/* PERFORMANCE_COUNTER_1 */
-#define COUNTER1_SHIFT					0
-#define COUNTER1_MASK					(0xffffffff << 0)
-
-/* PERFORMANCE_COUNTER_2 */
-#define COUNTER2_SHIFT					0
-#define COUNTER2_MASK					(0xffffffff << 0)
-
-/* PERFORMANCE_COUNTER_CONFIG */
-#define CNTR2_MCONNID_EN_SHIFT				31
-#define CNTR2_MCONNID_EN_MASK				(1 << 31)
-#define CNTR2_REGION_EN_SHIFT				30
-#define CNTR2_REGION_EN_MASK				(1 << 30)
-#define CNTR2_CFG_SHIFT					16
-#define CNTR2_CFG_MASK					(0xf << 16)
-#define CNTR1_MCONNID_EN_SHIFT				15
-#define CNTR1_MCONNID_EN_MASK				(1 << 15)
-#define CNTR1_REGION_EN_SHIFT				14
-#define CNTR1_REGION_EN_MASK				(1 << 14)
-#define CNTR1_CFG_SHIFT					0
-#define CNTR1_CFG_MASK					(0xf << 0)
-
-/* PERFORMANCE_COUNTER_MASTER_REGION_SELECT */
-#define MCONNID2_SHIFT					24
-#define MCONNID2_MASK					(0xff << 24)
-#define REGION_SEL2_SHIFT				16
-#define REGION_SEL2_MASK				(0x3 << 16)
-#define MCONNID1_SHIFT					8
-#define MCONNID1_MASK					(0xff << 8)
-#define REGION_SEL1_SHIFT				0
-#define REGION_SEL1_MASK				(0x3 << 0)
-
-/* PERFORMANCE_COUNTER_TIME */
-#define TOTAL_TIME_SHIFT				0
-#define TOTAL_TIME_MASK					(0xffffffff << 0)
-
-/* DLL_CALIB_CTRL */
-#define ACK_WAIT_SHIFT					16
-#define ACK_WAIT_MASK					(0xf << 16)
-#define DLL_CALIB_INTERVAL_SHIFT			0
-#define DLL_CALIB_INTERVAL_MASK				(0x1ff << 0)
-
-/* END_OF_INTERRUPT */
-#define EOI_SHIFT					0
-#define EOI_MASK					(1 << 0)
-
-/* SYSTEM_OCP_INTERRUPT_RAW_STATUS */
-#define DNV_SYS_SHIFT					2
-#define DNV_SYS_MASK					(1 << 2)
-#define TA_SYS_SHIFT					1
-#define TA_SYS_MASK					(1 << 1)
-#define ERR_SYS_SHIFT					0
-#define ERR_SYS_MASK					(1 << 0)
-
-/* LOW_LATENCY_OCP_INTERRUPT_RAW_STATUS */
-#define DNV_LL_SHIFT					2
-#define DNV_LL_MASK					(1 << 2)
-#define TA_LL_SHIFT					1
-#define TA_LL_MASK					(1 << 1)
-#define ERR_LL_SHIFT					0
-#define ERR_LL_MASK					(1 << 0)
-
-/* SYSTEM_OCP_INTERRUPT_ENABLE_SET */
-#define EN_DNV_SYS_SHIFT				2
-#define EN_DNV_SYS_MASK					(1 << 2)
-#define EN_TA_SYS_SHIFT					1
-#define EN_TA_SYS_MASK					(1 << 1)
-#define EN_ERR_SYS_SHIFT					0
-#define EN_ERR_SYS_MASK					(1 << 0)
-
-/* LOW_LATENCY_OCP_INTERRUPT_ENABLE_SET */
-#define EN_DNV_LL_SHIFT					2
-#define EN_DNV_LL_MASK					(1 << 2)
-#define EN_TA_LL_SHIFT					1
-#define EN_TA_LL_MASK					(1 << 1)
-#define EN_ERR_LL_SHIFT					0
-#define EN_ERR_LL_MASK					(1 << 0)
-
-/* SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG */
-#define ZQ_CS1EN_SHIFT					31
-#define ZQ_CS1EN_MASK					(1 << 31)
-#define ZQ_CS0EN_SHIFT					30
-#define ZQ_CS0EN_MASK					(1 << 30)
-#define ZQ_DUALCALEN_SHIFT				29
-#define ZQ_DUALCALEN_MASK				(1 << 29)
-#define ZQ_SFEXITEN_SHIFT				28
-#define ZQ_SFEXITEN_MASK				(1 << 28)
-#define ZQ_ZQINIT_MULT_SHIFT				18
-#define ZQ_ZQINIT_MULT_MASK				(0x3 << 18)
-#define ZQ_ZQCL_MULT_SHIFT				16
-#define ZQ_ZQCL_MULT_MASK				(0x3 << 16)
-#define ZQ_REFINTERVAL_SHIFT				0
-#define ZQ_REFINTERVAL_MASK				(0xffff << 0)
-
-/* TEMPERATURE_ALERT_CONFIG */
-#define TA_CS1EN_SHIFT					31
-#define TA_CS1EN_MASK					(1 << 31)
-#define TA_CS0EN_SHIFT					30
-#define TA_CS0EN_MASK					(1 << 30)
-#define TA_SFEXITEN_SHIFT				28
-#define TA_SFEXITEN_MASK				(1 << 28)
-#define TA_DEVWDT_SHIFT					26
-#define TA_DEVWDT_MASK					(0x3 << 26)
-#define TA_DEVCNT_SHIFT					24
-#define TA_DEVCNT_MASK					(0x3 << 24)
-#define TA_REFINTERVAL_SHIFT				0
-#define TA_REFINTERVAL_MASK				(0x3fffff << 0)
-
-/* OCP_ERROR_LOG */
-#define MADDRSPACE_SHIFT				14
-#define MADDRSPACE_MASK					(0x3 << 14)
-#define MBURSTSEQ_SHIFT					11
-#define MBURSTSEQ_MASK					(0x7 << 11)
-#define MCMD_SHIFT					8
-#define MCMD_MASK					(0x7 << 8)
-#define MCONNID_SHIFT					0
-#define MCONNID_MASK					(0xff << 0)
-
-/* DDR_PHY_CTRL_1 - EMIF4D */
-#define DLL_SLAVE_DLY_CTRL_SHIFT_4D			4
-#define DLL_SLAVE_DLY_CTRL_MASK_4D			(0xFF << 4)
-#define READ_LATENCY_SHIFT_4D				0
-#define READ_LATENCY_MASK_4D				(0xf << 0)
-
-/* DDR_PHY_CTRL_1 - EMIF4D5 */
-#define DLL_HALF_DELAY_SHIFT_4D5			21
-#define DLL_HALF_DELAY_MASK_4D5				(1 << 21)
-#define READ_LATENCY_SHIFT_4D5				0
-#define READ_LATENCY_MASK_4D5				(0x1f << 0)
-
-/* DDR_PHY_CTRL_1_SHDW */
-#define DDR_PHY_CTRL_1_SHDW_SHIFT			5
-#define DDR_PHY_CTRL_1_SHDW_MASK			(0x7ffffff << 5)
-#define READ_LATENCY_SHDW_SHIFT				0
-#define READ_LATENCY_SHDW_MASK				(0x1f << 0)
+#include <linux/ti_emif.h>
 
 #ifndef __ASSEMBLY__
 /*
diff --git a/include/linux/ti_emif.h b/include/linux/ti_emif.h
new file mode 100644
index 0000000..be26e7f
--- /dev/null
+++ b/include/linux/ti_emif.h
@@ -0,0 +1,558 @@
+/*
+ * Register defines for the EMIF driver
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson at 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.
+ */
+#ifndef __TI_EMIF_H
+#define __TI_EMIF_H
+
+/*
+ * Maximum number of different frequencies supported by EMIF driver
+ * Determines the number of entries in the pointer array for register
+ * cache
+ */
+#define EMIF_MAX_NUM_FREQUENCIES			6
+
+/* State of the core voltage */
+#define DDR_VOLTAGE_STABLE				0
+#define DDR_VOLTAGE_RAMPING				1
+
+/* Defines for timing De-rating */
+#define EMIF_NORMAL_TIMINGS				0
+#define EMIF_DERATED_TIMINGS				1
+
+/* Length of the forced read idle period in terms of cycles */
+#define EMIF_READ_IDLE_LEN_VAL				5
+
+/*
+ * forced read idle interval to be used when voltage
+ * is changed as part of DVFS/DPS - 1ms
+ */
+#define READ_IDLE_INTERVAL_DVFS				(1*1000000)
+
+/*
+ * Forced read idle interval to be used when voltage is stable
+ * 50us - or maximum value will do
+ */
+#define READ_IDLE_INTERVAL_NORMAL			(50*1000000)
+
+/* DLL calibration interval when voltage is NOT stable - 1us */
+#define DLL_CALIB_INTERVAL_DVFS				(1*1000000)
+
+#define DLL_CALIB_ACK_WAIT_VAL				5
+
+/* Interval between ZQCS commands - hw team recommended value */
+#define EMIF_ZQCS_INTERVAL_US				(50*1000)
+/* Enable ZQ Calibration on exiting Self-refresh */
+#define ZQ_SFEXITEN_ENABLE				1
+/*
+ * ZQ Calibration simultaneously on both chip-selects:
+ * Needs one calibration resistor per CS
+ */
+#define	ZQ_DUALCALEN_DISABLE				0
+#define	ZQ_DUALCALEN_ENABLE				1
+
+#define T_ZQCS_DEFAULT_NS				90
+#define T_ZQCL_DEFAULT_NS				360
+#define T_ZQINIT_DEFAULT_NS				1000
+
+/* DPD_EN */
+#define DPD_DISABLE					0
+#define DPD_ENABLE					1
+
+/*
+ * Default values for the low-power entry to be used if not provided by user.
+ * OMAP4/5 has a hw bug(i735) due to which this value can not be less than 512
+ * Timeout values are in DDR clock 'cycles' and frequency threshold in Hz
+ */
+#define EMIF_LP_MODE_TIMEOUT_PERFORMANCE		2048
+#define EMIF_LP_MODE_TIMEOUT_POWER			512
+#define EMIF_LP_MODE_FREQ_THRESHOLD			400000000
+
+/* DDR_PHY_CTRL_1 values for EMIF4D - ATTILA PHY combination */
+#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY		0x049FF000
+#define EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY	0x41
+#define EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY	0x80
+#define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY 0xFF
+
+/* DDR_PHY_CTRL_1 values for EMIF4D5 INTELLIPHY combination */
+#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY		0x0E084200
+#define EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS	10000
+
+/* TEMP_ALERT_CONFIG - corresponding to temp gradient 5 C/s */
+#define TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS		360
+
+#define EMIF_T_CSTA					3
+#define EMIF_T_PDLL_UL					128
+
+/* External PHY control registers magic values */
+#define EMIF_EXT_PHY_CTRL_1_VAL				0x04020080
+#define EMIF_EXT_PHY_CTRL_5_VAL				0x04010040
+#define EMIF_EXT_PHY_CTRL_6_VAL				0x01004010
+#define EMIF_EXT_PHY_CTRL_7_VAL				0x00001004
+#define EMIF_EXT_PHY_CTRL_8_VAL				0x04010040
+#define EMIF_EXT_PHY_CTRL_9_VAL				0x01004010
+#define EMIF_EXT_PHY_CTRL_10_VAL			0x00001004
+#define EMIF_EXT_PHY_CTRL_11_VAL			0x00000000
+#define EMIF_EXT_PHY_CTRL_12_VAL			0x00000000
+#define EMIF_EXT_PHY_CTRL_13_VAL			0x00000000
+#define EMIF_EXT_PHY_CTRL_14_VAL			0x80080080
+#define EMIF_EXT_PHY_CTRL_15_VAL			0x00800800
+#define EMIF_EXT_PHY_CTRL_16_VAL			0x08102040
+#define EMIF_EXT_PHY_CTRL_17_VAL			0x00000001
+#define EMIF_EXT_PHY_CTRL_18_VAL			0x540A8150
+#define EMIF_EXT_PHY_CTRL_19_VAL			0xA81502A0
+#define EMIF_EXT_PHY_CTRL_20_VAL			0x002A0540
+#define EMIF_EXT_PHY_CTRL_21_VAL			0x00000000
+#define EMIF_EXT_PHY_CTRL_22_VAL			0x00000000
+#define EMIF_EXT_PHY_CTRL_23_VAL			0x00000000
+#define EMIF_EXT_PHY_CTRL_24_VAL			0x00000077
+
+#define EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS	1200
+
+/* Registers offset */
+#define EMIF_MODULE_ID_AND_REVISION			0x0000
+#define EMIF_STATUS					0x0004
+#define EMIF_SDRAM_CONFIG				0x0008
+#define EMIF_SDRAM_CONFIG_2				0x000c
+#define EMIF_SDRAM_REFRESH_CONTROL			0x0010
+#define EMIF_SDRAM_REFRESH_CTRL_SHDW			0x0014
+#define EMIF_SDRAM_TIMING_1				0x0018
+#define EMIF_SDRAM_TIMING_1_SHDW			0x001c
+#define EMIF_SDRAM_TIMING_2				0x0020
+#define EMIF_SDRAM_TIMING_2_SHDW			0x0024
+#define EMIF_SDRAM_TIMING_3				0x0028
+#define EMIF_SDRAM_TIMING_3_SHDW			0x002c
+#define EMIF_LPDDR2_NVM_TIMING				0x0030
+#define EMIF_LPDDR2_NVM_TIMING_SHDW			0x0034
+#define EMIF_POWER_MANAGEMENT_CONTROL			0x0038
+#define EMIF_POWER_MANAGEMENT_CTRL_SHDW			0x003c
+#define EMIF_LPDDR2_MODE_REG_DATA			0x0040
+#define EMIF_LPDDR2_MODE_REG_CONFIG			0x0050
+#define EMIF_OCP_CONFIG					0x0054
+#define EMIF_OCP_CONFIG_VALUE_1				0x0058
+#define EMIF_OCP_CONFIG_VALUE_2				0x005c
+#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL		0x0060
+#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT		0x0064
+#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT	0x0068
+#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1	0x006c
+#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2	0x0070
+#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3	0x0074
+#define EMIF_PERFORMANCE_COUNTER_1			0x0080
+#define EMIF_PERFORMANCE_COUNTER_2			0x0084
+#define EMIF_PERFORMANCE_COUNTER_CONFIG			0x0088
+#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT	0x008c
+#define EMIF_PERFORMANCE_COUNTER_TIME			0x0090
+#define EMIF_MISC_REG					0x0094
+#define EMIF_DLL_CALIB_CTRL				0x0098
+#define EMIF_DLL_CALIB_CTRL_SHDW			0x009c
+#define EMIF_END_OF_INTERRUPT				0x00a0
+#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS		0x00a4
+#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS		0x00a8
+#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS		0x00ac
+#define EMIF_LL_OCP_INTERRUPT_STATUS			0x00b0
+#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET		0x00b4
+#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET		0x00b8
+#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR		0x00bc
+#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR		0x00c0
+#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG	0x00c8
+#define EMIF_TEMPERATURE_ALERT_CONFIG			0x00cc
+#define EMIF_OCP_ERROR_LOG				0x00d0
+#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW		0x00d4
+#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL		0x00d8
+#define EMIF_READ_WRITE_LEVELING_CONTROL		0x00dc
+#define EMIF_DDR_PHY_CTRL_1				0x00e4
+#define EMIF_DDR_PHY_CTRL_1_SHDW			0x00e8
+#define EMIF_DDR_PHY_CTRL_2				0x00ec
+#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING	0x0100
+#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104
+#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108
+#define EMIF_READ_WRITE_EXECUTION_THRESHOLD		0x0120
+#define EMIF_COS_CONFIG					0x0124
+#define EMIF_PHY_STATUS_1				0x0140
+#define EMIF_PHY_STATUS_2				0x0144
+#define EMIF_PHY_STATUS_3				0x0148
+#define EMIF_PHY_STATUS_4				0x014c
+#define EMIF_PHY_STATUS_5				0x0150
+#define EMIF_PHY_STATUS_6				0x0154
+#define EMIF_PHY_STATUS_7				0x0158
+#define EMIF_PHY_STATUS_8				0x015c
+#define EMIF_PHY_STATUS_9				0x0160
+#define EMIF_PHY_STATUS_10				0x0164
+#define EMIF_PHY_STATUS_11				0x0168
+#define EMIF_PHY_STATUS_12				0x016c
+#define EMIF_PHY_STATUS_13				0x0170
+#define EMIF_PHY_STATUS_14				0x0174
+#define EMIF_PHY_STATUS_15				0x0178
+#define EMIF_PHY_STATUS_16				0x017c
+#define EMIF_PHY_STATUS_17				0x0180
+#define EMIF_PHY_STATUS_18				0x0184
+#define EMIF_PHY_STATUS_19				0x0188
+#define EMIF_PHY_STATUS_20				0x018c
+#define EMIF_PHY_STATUS_21				0x0190
+#define EMIF_EXT_PHY_CTRL_1				0x0200
+#define EMIF_EXT_PHY_CTRL_1_SHDW			0x0204
+#define EMIF_EXT_PHY_CTRL_2				0x0208
+#define EMIF_EXT_PHY_CTRL_2_SHDW			0x020c
+#define EMIF_EXT_PHY_CTRL_3				0x0210
+#define EMIF_EXT_PHY_CTRL_3_SHDW			0x0214
+#define EMIF_EXT_PHY_CTRL_4				0x0218
+#define EMIF_EXT_PHY_CTRL_4_SHDW			0x021c
+#define EMIF_EXT_PHY_CTRL_5				0x0220
+#define EMIF_EXT_PHY_CTRL_5_SHDW			0x0224
+#define EMIF_EXT_PHY_CTRL_6				0x0228
+#define EMIF_EXT_PHY_CTRL_6_SHDW			0x022c
+#define EMIF_EXT_PHY_CTRL_7				0x0230
+#define EMIF_EXT_PHY_CTRL_7_SHDW			0x0234
+#define EMIF_EXT_PHY_CTRL_8				0x0238
+#define EMIF_EXT_PHY_CTRL_8_SHDW			0x023c
+#define EMIF_EXT_PHY_CTRL_9				0x0240
+#define EMIF_EXT_PHY_CTRL_9_SHDW			0x0244
+#define EMIF_EXT_PHY_CTRL_10				0x0248
+#define EMIF_EXT_PHY_CTRL_10_SHDW			0x024c
+#define EMIF_EXT_PHY_CTRL_11				0x0250
+#define EMIF_EXT_PHY_CTRL_11_SHDW			0x0254
+#define EMIF_EXT_PHY_CTRL_12				0x0258
+#define EMIF_EXT_PHY_CTRL_12_SHDW			0x025c
+#define EMIF_EXT_PHY_CTRL_13				0x0260
+#define EMIF_EXT_PHY_CTRL_13_SHDW			0x0264
+#define EMIF_EXT_PHY_CTRL_14				0x0268
+#define EMIF_EXT_PHY_CTRL_14_SHDW			0x026c
+#define EMIF_EXT_PHY_CTRL_15				0x0270
+#define EMIF_EXT_PHY_CTRL_15_SHDW			0x0274
+#define EMIF_EXT_PHY_CTRL_16				0x0278
+#define EMIF_EXT_PHY_CTRL_16_SHDW			0x027c
+#define EMIF_EXT_PHY_CTRL_17				0x0280
+#define EMIF_EXT_PHY_CTRL_17_SHDW			0x0284
+#define EMIF_EXT_PHY_CTRL_18				0x0288
+#define EMIF_EXT_PHY_CTRL_18_SHDW			0x028c
+#define EMIF_EXT_PHY_CTRL_19				0x0290
+#define EMIF_EXT_PHY_CTRL_19_SHDW			0x0294
+#define EMIF_EXT_PHY_CTRL_20				0x0298
+#define EMIF_EXT_PHY_CTRL_20_SHDW			0x029c
+#define EMIF_EXT_PHY_CTRL_21				0x02a0
+#define EMIF_EXT_PHY_CTRL_21_SHDW			0x02a4
+#define EMIF_EXT_PHY_CTRL_22				0x02a8
+#define EMIF_EXT_PHY_CTRL_22_SHDW			0x02ac
+#define EMIF_EXT_PHY_CTRL_23				0x02b0
+#define EMIF_EXT_PHY_CTRL_23_SHDW			0x02b4
+#define EMIF_EXT_PHY_CTRL_24				0x02b8
+#define EMIF_EXT_PHY_CTRL_24_SHDW			0x02bc
+#define EMIF_EXT_PHY_CTRL_25				0x02c0
+#define EMIF_EXT_PHY_CTRL_25_SHDW			0x02c4
+#define EMIF_EXT_PHY_CTRL_26				0x02c8
+#define EMIF_EXT_PHY_CTRL_26_SHDW			0x02cc
+#define EMIF_EXT_PHY_CTRL_27				0x02d0
+#define EMIF_EXT_PHY_CTRL_27_SHDW			0x02d4
+#define EMIF_EXT_PHY_CTRL_28				0x02d8
+#define EMIF_EXT_PHY_CTRL_28_SHDW			0x02dc
+#define EMIF_EXT_PHY_CTRL_29				0x02e0
+#define EMIF_EXT_PHY_CTRL_29_SHDW			0x02e4
+#define EMIF_EXT_PHY_CTRL_30				0x02e8
+#define EMIF_EXT_PHY_CTRL_30_SHDW			0x02ec
+
+/* Registers shifts and masks */
+
+/* EMIF_MODULE_ID_AND_REVISION */
+#define SCHEME_SHIFT					30
+#define SCHEME_MASK					(0x3 << 30)
+#define MODULE_ID_SHIFT					16
+#define MODULE_ID_MASK					(0xfff << 16)
+#define RTL_VERSION_SHIFT				11
+#define RTL_VERSION_MASK				(0x1f << 11)
+#define MAJOR_REVISION_SHIFT				8
+#define MAJOR_REVISION_MASK				(0x7 << 8)
+#define MINOR_REVISION_SHIFT				0
+#define MINOR_REVISION_MASK				(0x3f << 0)
+
+/* STATUS */
+#define BE_SHIFT					31
+#define BE_MASK						(1 << 31)
+#define DUAL_CLK_MODE_SHIFT				30
+#define DUAL_CLK_MODE_MASK				(1 << 30)
+#define FAST_INIT_SHIFT					29
+#define FAST_INIT_MASK					(1 << 29)
+#define RDLVLGATETO_SHIFT				6
+#define RDLVLGATETO_MASK				(1 << 6)
+#define RDLVLTO_SHIFT					5
+#define RDLVLTO_MASK					(1 << 5)
+#define WRLVLTO_SHIFT					4
+#define WRLVLTO_MASK					(1 << 4)
+#define PHY_DLL_READY_SHIFT				2
+#define PHY_DLL_READY_MASK				(1 << 2)
+
+/* SDRAM_CONFIG */
+#define SDRAM_TYPE_SHIFT				29
+#define SDRAM_TYPE_MASK					(0x7 << 29)
+#define IBANK_POS_SHIFT					27
+#define IBANK_POS_MASK					(0x3 << 27)
+#define DDR_TERM_SHIFT					24
+#define DDR_TERM_MASK					(0x7 << 24)
+#define DDR2_DDQS_SHIFT					23
+#define DDR2_DDQS_MASK					(1 << 23)
+#define DYN_ODT_SHIFT					21
+#define DYN_ODT_MASK					(0x3 << 21)
+#define DDR_DISABLE_DLL_SHIFT				20
+#define DDR_DISABLE_DLL_MASK				(1 << 20)
+#define SDRAM_DRIVE_SHIFT				18
+#define SDRAM_DRIVE_MASK				(0x3 << 18)
+#define CWL_SHIFT					16
+#define CWL_MASK					(0x3 << 16)
+#define NARROW_MODE_SHIFT				14
+#define NARROW_MODE_MASK				(0x3 << 14)
+#define CL_SHIFT					10
+#define CL_MASK						(0xf << 10)
+#define ROWSIZE_SHIFT					7
+#define ROWSIZE_MASK					(0x7 << 7)
+#define IBANK_SHIFT					4
+#define IBANK_MASK					(0x7 << 4)
+#define EBANK_SHIFT					3
+#define EBANK_MASK					(1 << 3)
+#define PAGESIZE_SHIFT					0
+#define PAGESIZE_MASK					(0x7 << 0)
+
+/* SDRAM_CONFIG_2 */
+#define CS1NVMEN_SHIFT					30
+#define CS1NVMEN_MASK					(1 << 30)
+#define EBANK_POS_SHIFT					27
+#define EBANK_POS_MASK					(1 << 27)
+#define RDBNUM_SHIFT					4
+#define RDBNUM_MASK					(0x3 << 4)
+#define RDBSIZE_SHIFT					0
+#define RDBSIZE_MASK					(0x7 << 0)
+
+/* SDRAM_REFRESH_CONTROL */
+#define INITREF_DIS_SHIFT				31
+#define INITREF_DIS_MASK				(1 << 31)
+#define SRT_SHIFT					29
+#define SRT_MASK					(1 << 29)
+#define ASR_SHIFT					28
+#define ASR_MASK					(1 << 28)
+#define PASR_SHIFT					24
+#define PASR_MASK					(0x7 << 24)
+#define REFRESH_RATE_SHIFT				0
+#define REFRESH_RATE_MASK				(0xffff << 0)
+
+/* SDRAM_TIMING_1 */
+#define T_RTW_SHIFT					29
+#define T_RTW_MASK					(0x7 << 29)
+#define T_RP_SHIFT					25
+#define T_RP_MASK					(0xf << 25)
+#define T_RCD_SHIFT					21
+#define T_RCD_MASK					(0xf << 21)
+#define T_WR_SHIFT					17
+#define T_WR_MASK					(0xf << 17)
+#define T_RAS_SHIFT					12
+#define T_RAS_MASK					(0x1f << 12)
+#define T_RC_SHIFT					6
+#define T_RC_MASK					(0x3f << 6)
+#define T_RRD_SHIFT					3
+#define T_RRD_MASK					(0x7 << 3)
+#define T_WTR_SHIFT					0
+#define T_WTR_MASK					(0x7 << 0)
+
+/* SDRAM_TIMING_2 */
+#define T_XP_SHIFT					28
+#define T_XP_MASK					(0x7 << 28)
+#define T_ODT_SHIFT					25
+#define T_ODT_MASK					(0x7 << 25)
+#define T_XSNR_SHIFT					16
+#define T_XSNR_MASK					(0x1ff << 16)
+#define T_XSRD_SHIFT					6
+#define T_XSRD_MASK					(0x3ff << 6)
+#define T_RTP_SHIFT					3
+#define T_RTP_MASK					(0x7 << 3)
+#define T_CKE_SHIFT					0
+#define T_CKE_MASK					(0x7 << 0)
+
+/* SDRAM_TIMING_3 */
+#define T_PDLL_UL_SHIFT					28
+#define T_PDLL_UL_MASK					(0xf << 28)
+#define T_CSTA_SHIFT					24
+#define T_CSTA_MASK					(0xf << 24)
+#define T_CKESR_SHIFT					21
+#define T_CKESR_MASK					(0x7 << 21)
+#define ZQ_ZQCS_SHIFT					15
+#define ZQ_ZQCS_MASK					(0x3f << 15)
+#define T_TDQSCKMAX_SHIFT				13
+#define T_TDQSCKMAX_MASK				(0x3 << 13)
+#define T_RFC_SHIFT					4
+#define T_RFC_MASK					(0x1ff << 4)
+#define T_RAS_MAX_SHIFT					0
+#define T_RAS_MAX_MASK					(0xf << 0)
+
+/* POWER_MANAGEMENT_CONTROL */
+#define PD_TIM_SHIFT					12
+#define PD_TIM_MASK					(0xf << 12)
+#define DPD_EN_SHIFT					11
+#define DPD_EN_MASK					(1 << 11)
+#define LP_MODE_SHIFT					8
+#define LP_MODE_MASK					(0x7 << 8)
+#define SR_TIM_SHIFT					4
+#define SR_TIM_MASK					(0xf << 4)
+#define CS_TIM_SHIFT					0
+#define CS_TIM_MASK					(0xf << 0)
+
+/* LPDDR2_MODE_REG_DATA */
+#define VALUE_0_SHIFT					0
+#define VALUE_0_MASK					(0x7f << 0)
+
+/* LPDDR2_MODE_REG_CONFIG */
+#define CS_SHIFT					31
+#define CS_MASK						(1 << 31)
+#define REFRESH_EN_SHIFT				30
+#define REFRESH_EN_MASK					(1 << 30)
+#define ADDRESS_SHIFT					0
+#define ADDRESS_MASK					(0xff << 0)
+
+/* OCP_CONFIG */
+#define SYS_THRESH_MAX_SHIFT				24
+#define SYS_THRESH_MAX_MASK				(0xf << 24)
+#define MPU_THRESH_MAX_SHIFT				20
+#define MPU_THRESH_MAX_MASK				(0xf << 20)
+#define LL_THRESH_MAX_SHIFT				16
+#define LL_THRESH_MAX_MASK				(0xf << 16)
+
+/* PERFORMANCE_COUNTER_1 */
+#define COUNTER1_SHIFT					0
+#define COUNTER1_MASK					(0xffffffff << 0)
+
+/* PERFORMANCE_COUNTER_2 */
+#define COUNTER2_SHIFT					0
+#define COUNTER2_MASK					(0xffffffff << 0)
+
+/* PERFORMANCE_COUNTER_CONFIG */
+#define CNTR2_MCONNID_EN_SHIFT				31
+#define CNTR2_MCONNID_EN_MASK				(1 << 31)
+#define CNTR2_REGION_EN_SHIFT				30
+#define CNTR2_REGION_EN_MASK				(1 << 30)
+#define CNTR2_CFG_SHIFT					16
+#define CNTR2_CFG_MASK					(0xf << 16)
+#define CNTR1_MCONNID_EN_SHIFT				15
+#define CNTR1_MCONNID_EN_MASK				(1 << 15)
+#define CNTR1_REGION_EN_SHIFT				14
+#define CNTR1_REGION_EN_MASK				(1 << 14)
+#define CNTR1_CFG_SHIFT					0
+#define CNTR1_CFG_MASK					(0xf << 0)
+
+/* PERFORMANCE_COUNTER_MASTER_REGION_SELECT */
+#define MCONNID2_SHIFT					24
+#define MCONNID2_MASK					(0xff << 24)
+#define REGION_SEL2_SHIFT				16
+#define REGION_SEL2_MASK				(0x3 << 16)
+#define MCONNID1_SHIFT					8
+#define MCONNID1_MASK					(0xff << 8)
+#define REGION_SEL1_SHIFT				0
+#define REGION_SEL1_MASK				(0x3 << 0)
+
+/* PERFORMANCE_COUNTER_TIME */
+#define TOTAL_TIME_SHIFT				0
+#define TOTAL_TIME_MASK					(0xffffffff << 0)
+
+/* DLL_CALIB_CTRL */
+#define ACK_WAIT_SHIFT					16
+#define ACK_WAIT_MASK					(0xf << 16)
+#define DLL_CALIB_INTERVAL_SHIFT			0
+#define DLL_CALIB_INTERVAL_MASK				(0x1ff << 0)
+
+/* END_OF_INTERRUPT */
+#define EOI_SHIFT					0
+#define EOI_MASK					(1 << 0)
+
+/* SYSTEM_OCP_INTERRUPT_RAW_STATUS */
+#define DNV_SYS_SHIFT					2
+#define DNV_SYS_MASK					(1 << 2)
+#define TA_SYS_SHIFT					1
+#define TA_SYS_MASK					(1 << 1)
+#define ERR_SYS_SHIFT					0
+#define ERR_SYS_MASK					(1 << 0)
+
+/* LOW_LATENCY_OCP_INTERRUPT_RAW_STATUS */
+#define DNV_LL_SHIFT					2
+#define DNV_LL_MASK					(1 << 2)
+#define TA_LL_SHIFT					1
+#define TA_LL_MASK					(1 << 1)
+#define ERR_LL_SHIFT					0
+#define ERR_LL_MASK					(1 << 0)
+
+/* SYSTEM_OCP_INTERRUPT_ENABLE_SET */
+#define EN_DNV_SYS_SHIFT				2
+#define EN_DNV_SYS_MASK					(1 << 2)
+#define EN_TA_SYS_SHIFT					1
+#define EN_TA_SYS_MASK					(1 << 1)
+#define EN_ERR_SYS_SHIFT					0
+#define EN_ERR_SYS_MASK					(1 << 0)
+
+/* LOW_LATENCY_OCP_INTERRUPT_ENABLE_SET */
+#define EN_DNV_LL_SHIFT					2
+#define EN_DNV_LL_MASK					(1 << 2)
+#define EN_TA_LL_SHIFT					1
+#define EN_TA_LL_MASK					(1 << 1)
+#define EN_ERR_LL_SHIFT					0
+#define EN_ERR_LL_MASK					(1 << 0)
+
+/* SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG */
+#define ZQ_CS1EN_SHIFT					31
+#define ZQ_CS1EN_MASK					(1 << 31)
+#define ZQ_CS0EN_SHIFT					30
+#define ZQ_CS0EN_MASK					(1 << 30)
+#define ZQ_DUALCALEN_SHIFT				29
+#define ZQ_DUALCALEN_MASK				(1 << 29)
+#define ZQ_SFEXITEN_SHIFT				28
+#define ZQ_SFEXITEN_MASK				(1 << 28)
+#define ZQ_ZQINIT_MULT_SHIFT				18
+#define ZQ_ZQINIT_MULT_MASK				(0x3 << 18)
+#define ZQ_ZQCL_MULT_SHIFT				16
+#define ZQ_ZQCL_MULT_MASK				(0x3 << 16)
+#define ZQ_REFINTERVAL_SHIFT				0
+#define ZQ_REFINTERVAL_MASK				(0xffff << 0)
+
+/* TEMPERATURE_ALERT_CONFIG */
+#define TA_CS1EN_SHIFT					31
+#define TA_CS1EN_MASK					(1 << 31)
+#define TA_CS0EN_SHIFT					30
+#define TA_CS0EN_MASK					(1 << 30)
+#define TA_SFEXITEN_SHIFT				28
+#define TA_SFEXITEN_MASK				(1 << 28)
+#define TA_DEVWDT_SHIFT					26
+#define TA_DEVWDT_MASK					(0x3 << 26)
+#define TA_DEVCNT_SHIFT					24
+#define TA_DEVCNT_MASK					(0x3 << 24)
+#define TA_REFINTERVAL_SHIFT				0
+#define TA_REFINTERVAL_MASK				(0x3fffff << 0)
+
+/* OCP_ERROR_LOG */
+#define MADDRSPACE_SHIFT				14
+#define MADDRSPACE_MASK					(0x3 << 14)
+#define MBURSTSEQ_SHIFT					11
+#define MBURSTSEQ_MASK					(0x7 << 11)
+#define MCMD_SHIFT					8
+#define MCMD_MASK					(0x7 << 8)
+#define MCONNID_SHIFT					0
+#define MCONNID_MASK					(0xff << 0)
+
+/* DDR_PHY_CTRL_1 - EMIF4D */
+#define DLL_SLAVE_DLY_CTRL_SHIFT_4D			4
+#define DLL_SLAVE_DLY_CTRL_MASK_4D			(0xFF << 4)
+#define READ_LATENCY_SHIFT_4D				0
+#define READ_LATENCY_MASK_4D				(0xf << 0)
+
+/* DDR_PHY_CTRL_1 - EMIF4D5 */
+#define DLL_HALF_DELAY_SHIFT_4D5			21
+#define DLL_HALF_DELAY_MASK_4D5				(1 << 21)
+#define READ_LATENCY_SHIFT_4D5				0
+#define READ_LATENCY_MASK_4D5				(0x1f << 0)
+
+/* DDR_PHY_CTRL_1_SHDW */
+#define DDR_PHY_CTRL_1_SHDW_SHIFT			5
+#define DDR_PHY_CTRL_1_SHDW_MASK			(0x7ffffff << 5)
+#define READ_LATENCY_SHDW_SHIFT				0
+#define READ_LATENCY_SHDW_MASK				(0x1f << 0)
+
+#endif /* __TI_EMIF_H */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-06 17:49 ` Dave Gerlach
@ 2013-08-06 17:49   ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap
  Cc: Paul Walmsley, Kevin Hilman, Vaibhav Bedia, Dave Gerlach

From: Vaibhav Bedia <vaibhav.bedia@ti.com>

Interacting with WKUP-M3 requires some more control
module register writes. Add the register offsets and
APIs to write to these.

Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
 arch/arm/mach-omap2/control.c |   57 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/control.h |   54 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 111 insertions(+)

diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index 31e0dfe..934041a 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -605,3 +605,60 @@ int omap3_ctrl_save_padconf(void)
 }
 
 #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
+
+#if defined(CONFIG_SOC_AM33XX) && defined(CONFIG_PM)
+void am33xx_txev_eoi(void)
+{
+	omap_ctrl_writel(AM33XX_M3_TXEV_ACK, AM33XX_CONTROL_M3_TXEV_EOI);
+}
+
+void am33xx_txev_enable(void)
+{
+	omap_ctrl_writel(AM33XX_M3_TXEV_ENABLE, AM33XX_CONTROL_M3_TXEV_EOI);
+}
+
+/*
+ * Invalidate M3 firmware version before hardreset.
+ * Write invalid version in lower 4 nibbles of parameter
+ * register (ipc_regs + 0x8).
+ */
+void am33xx_pm_version_clear(void)
+{
+	omap_ctrl_writel(0xffff0000, AM33XX_CONTROL_IPC_MSG_REG2);
+}
+
+int am33xx_pm_version_get(void)
+{
+	return omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG2) & M3_VERSION_MASK;
+}
+
+void am33xx_pm_ipc_cmd(struct am33xx_ipc_data *data)
+{
+	omap_ctrl_writel(data->resume_addr, AM33XX_CONTROL_IPC_MSG_REG0);
+	omap_ctrl_writel(data->sleep_mode, AM33XX_CONTROL_IPC_MSG_REG1);
+	omap_ctrl_writel(data->param1, AM33XX_CONTROL_IPC_MSG_REG2);
+	omap_ctrl_writel(data->param2, AM33XX_CONTROL_IPC_MSG_REG3);
+	omap_ctrl_writel(data->param3, AM33XX_CONTROL_IPC_MSG_REG4);
+}
+
+int am33xx_pm_status(void)
+{
+	int i;
+
+	i = omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG1);
+	i &= IPC_RESP_MASK;
+	i >>= __ffs(IPC_RESP_MASK);
+
+	return i;
+}
+
+int am33xx_pm_wake_src(void)
+{
+	int i;
+
+	i = omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG6);
+	i &= 0xff;
+
+	return i;
+}
+#endif /* CONFIG_SOC_AM33XX && CONFIG_PM */
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index f7d7c2e..9be587c 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -370,6 +370,22 @@
 #define AM33XX_DEV_FEATURE		0x604
 #define AM33XX_SGX_MASK			BIT(29)
 
+/* AM33XX M3_TXEV_EOI register */
+#define AM33XX_CONTROL_M3_TXEV_EOI	0x1324
+
+#define AM33XX_M3_TXEV_ACK		(0x1 << 0)
+#define AM33XX_M3_TXEV_ENABLE		(0x0 << 0)
+
+/* AM33XX IPC message registers */
+#define AM33XX_CONTROL_IPC_MSG_REG0	0x1328
+#define AM33XX_CONTROL_IPC_MSG_REG1	0x132C
+#define AM33XX_CONTROL_IPC_MSG_REG2	0x1330
+#define AM33XX_CONTROL_IPC_MSG_REG3	0x1334
+#define AM33XX_CONTROL_IPC_MSG_REG4	0x1338
+#define AM33XX_CONTROL_IPC_MSG_REG5	0x133C
+#define AM33XX_CONTROL_IPC_MSG_REG6	0x1340
+#define AM33XX_CONTROL_IPC_MSG_REG7	0x1344
+
 /* CONTROL OMAP STATUS register to identify OMAP3 features */
 #define OMAP3_CONTROL_OMAP_STATUS	0x044c
 
@@ -429,6 +445,44 @@ extern void omap3630_ctrl_disable_rta(void);
 extern int omap3_ctrl_save_padconf(void);
 extern void omap2_set_globals_control(void __iomem *ctrl,
 				      void __iomem *ctrl_pad);
+struct am33xx_ipc_data {
+	u32 resume_addr;
+	u32 sleep_mode;
+	u32 param1;
+	u32 param2;
+	u32 param3;
+	u32 param4;
+	u32 param5;
+	u32 param6;
+};
+
+#define IPC_RESP_SHIFT			16
+#define IPC_RESP_MASK			(0xffff << 16)
+
+#define M3_VERSION_SHIFT		0
+#define M3_VERSION_MASK			(0xffff << 0)
+
+/*
+ * 9-4 = VTT GPIO PIN (6 Bits)
+ *   3 = VTT Status (1 Bit)
+ * 2-0 = Memory Type (2 Bits)
+*/
+#define MEM_TYPE_SHIFT		(0x0)
+#define MEM_TYPE_MASK		(0x7 << 0)
+#define VTT_STAT_SHIFT		(0x3)
+#define VTT_STAT_MASK		(0x1 << 3)
+#define VTT_GPIO_PIN_SHIFT	(0x4)
+#define VTT_GPIO_PIN_MASK	(0x2f << 4)
+
+extern void am33xx_wkup_m3_ipc_cmd(struct am33xx_ipc_data *data);
+extern void am33xx_txev_eoi(void);
+extern void am33xx_txev_enable(void);
+extern void am33xx_pm_version_clear(void);
+extern int am33xx_pm_version_get(void);
+extern void am33xx_pm_ipc_cmd(struct am33xx_ipc_data *data);
+extern int am33xx_pm_status(void);
+extern int am33xx_pm_wake_src(void);
+
 #else
 #define omap_ctrl_base_get()		0
 #define omap_ctrl_readb(x)		0
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-06 17:49   ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel

From: Vaibhav Bedia <vaibhav.bedia@ti.com>

Interacting with WKUP-M3 requires some more control
module register writes. Add the register offsets and
APIs to write to these.

Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
 arch/arm/mach-omap2/control.c |   57 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/control.h |   54 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 111 insertions(+)

diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index 31e0dfe..934041a 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -605,3 +605,60 @@ int omap3_ctrl_save_padconf(void)
 }
 
 #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
+
+#if defined(CONFIG_SOC_AM33XX) && defined(CONFIG_PM)
+void am33xx_txev_eoi(void)
+{
+	omap_ctrl_writel(AM33XX_M3_TXEV_ACK, AM33XX_CONTROL_M3_TXEV_EOI);
+}
+
+void am33xx_txev_enable(void)
+{
+	omap_ctrl_writel(AM33XX_M3_TXEV_ENABLE, AM33XX_CONTROL_M3_TXEV_EOI);
+}
+
+/*
+ * Invalidate M3 firmware version before hardreset.
+ * Write invalid version in lower 4 nibbles of parameter
+ * register (ipc_regs + 0x8).
+ */
+void am33xx_pm_version_clear(void)
+{
+	omap_ctrl_writel(0xffff0000, AM33XX_CONTROL_IPC_MSG_REG2);
+}
+
+int am33xx_pm_version_get(void)
+{
+	return omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG2) & M3_VERSION_MASK;
+}
+
+void am33xx_pm_ipc_cmd(struct am33xx_ipc_data *data)
+{
+	omap_ctrl_writel(data->resume_addr, AM33XX_CONTROL_IPC_MSG_REG0);
+	omap_ctrl_writel(data->sleep_mode, AM33XX_CONTROL_IPC_MSG_REG1);
+	omap_ctrl_writel(data->param1, AM33XX_CONTROL_IPC_MSG_REG2);
+	omap_ctrl_writel(data->param2, AM33XX_CONTROL_IPC_MSG_REG3);
+	omap_ctrl_writel(data->param3, AM33XX_CONTROL_IPC_MSG_REG4);
+}
+
+int am33xx_pm_status(void)
+{
+	int i;
+
+	i = omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG1);
+	i &= IPC_RESP_MASK;
+	i >>= __ffs(IPC_RESP_MASK);
+
+	return i;
+}
+
+int am33xx_pm_wake_src(void)
+{
+	int i;
+
+	i = omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG6);
+	i &= 0xff;
+
+	return i;
+}
+#endif /* CONFIG_SOC_AM33XX && CONFIG_PM */
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index f7d7c2e..9be587c 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -370,6 +370,22 @@
 #define AM33XX_DEV_FEATURE		0x604
 #define AM33XX_SGX_MASK			BIT(29)
 
+/* AM33XX M3_TXEV_EOI register */
+#define AM33XX_CONTROL_M3_TXEV_EOI	0x1324
+
+#define AM33XX_M3_TXEV_ACK		(0x1 << 0)
+#define AM33XX_M3_TXEV_ENABLE		(0x0 << 0)
+
+/* AM33XX IPC message registers */
+#define AM33XX_CONTROL_IPC_MSG_REG0	0x1328
+#define AM33XX_CONTROL_IPC_MSG_REG1	0x132C
+#define AM33XX_CONTROL_IPC_MSG_REG2	0x1330
+#define AM33XX_CONTROL_IPC_MSG_REG3	0x1334
+#define AM33XX_CONTROL_IPC_MSG_REG4	0x1338
+#define AM33XX_CONTROL_IPC_MSG_REG5	0x133C
+#define AM33XX_CONTROL_IPC_MSG_REG6	0x1340
+#define AM33XX_CONTROL_IPC_MSG_REG7	0x1344
+
 /* CONTROL OMAP STATUS register to identify OMAP3 features */
 #define OMAP3_CONTROL_OMAP_STATUS	0x044c
 
@@ -429,6 +445,44 @@ extern void omap3630_ctrl_disable_rta(void);
 extern int omap3_ctrl_save_padconf(void);
 extern void omap2_set_globals_control(void __iomem *ctrl,
 				      void __iomem *ctrl_pad);
+struct am33xx_ipc_data {
+	u32 resume_addr;
+	u32 sleep_mode;
+	u32 param1;
+	u32 param2;
+	u32 param3;
+	u32 param4;
+	u32 param5;
+	u32 param6;
+};
+
+#define IPC_RESP_SHIFT			16
+#define IPC_RESP_MASK			(0xffff << 16)
+
+#define M3_VERSION_SHIFT		0
+#define M3_VERSION_MASK			(0xffff << 0)
+
+/*
+ * 9-4 = VTT GPIO PIN (6 Bits)
+ *   3 = VTT Status (1 Bit)
+ * 2-0 = Memory Type (2 Bits)
+*/
+#define MEM_TYPE_SHIFT		(0x0)
+#define MEM_TYPE_MASK		(0x7 << 0)
+#define VTT_STAT_SHIFT		(0x3)
+#define VTT_STAT_MASK		(0x1 << 3)
+#define VTT_GPIO_PIN_SHIFT	(0x4)
+#define VTT_GPIO_PIN_MASK	(0x2f << 4)
+
+extern void am33xx_wkup_m3_ipc_cmd(struct am33xx_ipc_data *data);
+extern void am33xx_txev_eoi(void);
+extern void am33xx_txev_enable(void);
+extern void am33xx_pm_version_clear(void);
+extern int am33xx_pm_version_get(void);
+extern void am33xx_pm_ipc_cmd(struct am33xx_ipc_data *data);
+extern int am33xx_pm_status(void);
+extern int am33xx_pm_wake_src(void);
+
 #else
 #define omap_ctrl_base_get()		0
 #define omap_ctrl_readb(x)		0
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 212+ messages in thread

* [PATCHv3 3/9] ARM: OMAP: DTB: Update IRQ data for WKUP_M3
  2013-08-06 17:49 ` Dave Gerlach
@ 2013-08-06 17:49   ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap
  Cc: Paul Walmsley, Kevin Hilman, Vaibhav Bedia, Dave Gerlach, Benoit Cousson

From: Vaibhav Bedia <vaibhav.bedia@ti.com>

Allow interrupt for wkup_m3 to be set from DT.

Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
Cc: Benoit Cousson <benoit.cousson@linaro.org>
---
 arch/arm/boot/dts/am33xx.dtsi |    1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 38b446b..05353bf 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -491,6 +491,7 @@
 			compatible = "ti,am3353-wkup-m3";
 			reg = <0x44d00000 0x4000	/* M3 UMEM */
 			       0x44d80000 0x2000>;	/* M3 DMEM */
+			interrupts = <78>;
 			ti,hwmods = "wkup_m3";
 		};
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 212+ messages in thread

* [PATCHv3 3/9] ARM: OMAP: DTB: Update IRQ data for WKUP_M3
@ 2013-08-06 17:49   ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel

From: Vaibhav Bedia <vaibhav.bedia@ti.com>

Allow interrupt for wkup_m3 to be set from DT.

Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
Cc: Benoit Cousson <benoit.cousson@linaro.org>
---
 arch/arm/boot/dts/am33xx.dtsi |    1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 38b446b..05353bf 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -491,6 +491,7 @@
 			compatible = "ti,am3353-wkup-m3";
 			reg = <0x44d00000 0x4000	/* M3 UMEM */
 			       0x44d80000 0x2000>;	/* M3 DMEM */
+			interrupts = <78>;
 			ti,hwmods = "wkup_m3";
 		};
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 212+ messages in thread

* [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
  2013-08-06 17:49 ` Dave Gerlach
@ 2013-08-06 17:49   ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap
  Cc: Paul Walmsley, Kevin Hilman, Vaibhav Bedia, Dave Gerlach

From: Vaibhav Bedia <vaibhav.bedia@ti.com>

SDRAM controller on AM33XX requires that a modification of certain
bit-fields in PWR_MGMT_CTRL register (ref. section 7.3.5.13 in
AM335x-Rev H) is followed by a dummy read access to SDRAM. This
scenario arises when entering a low power state like DeepSleep.
To ensure that the read is not from a cached region we reserve
some memory during bootup using the arm_memblock_steal() API.

A subsequent patch will pass along the location of the reserved
memory location to the AM335x suspend handler which modifies the
PWR_MGMT_CTRL register in the EMIF.

Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
 arch/arm/mach-omap2/board-generic.c |    2 +-
 arch/arm/mach-omap2/common.c        |   28 ++++++++++++++++++++++++++++
 arch/arm/mach-omap2/common.h        |    4 ++++
 arch/arm/mach-omap2/io.c            |    1 +
 4 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index be5d005..aed750c 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -156,7 +156,7 @@ static const char *am33xx_boards_compat[] __initdata = {
 };
 
 DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)")
-	.reserve	= omap_reserve,
+	.reserve	= am33xx_reserve,
 	.map_io		= am33xx_map_io,
 	.init_early	= am33xx_init_early,
 	.init_irq	= omap_intc_of_init,
diff --git a/arch/arm/mach-omap2/common.c b/arch/arm/mach-omap2/common.c
index 2dabb9e..756586f 100644
--- a/arch/arm/mach-omap2/common.c
+++ b/arch/arm/mach-omap2/common.c
@@ -15,6 +15,8 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_data/dsp-omap.h>
+#include <asm/memblock.h>
+#include <asm/mach/map.h>
 
 #include "common.h"
 #include "omap-secure.h"
@@ -34,3 +36,29 @@ void __init omap_reserve(void)
 	omap_secure_ram_reserve_memblock();
 	omap_barrier_reserve_memblock();
 }
+
+static phys_addr_t am33xx_paddr;
+static u32 am33xx_size;
+
+/* Steal one page physical memory for uncached read DeepSleep */
+void __init am33xx_reserve(void)
+{
+	am33xx_size = ALIGN(PAGE_SIZE, SZ_1M);
+	am33xx_paddr = arm_memblock_steal(am33xx_size, SZ_1M);
+}
+
+void __iomem *am33xx_dram_sync;
+
+void __init am33xx_dram_sync_init(void)
+{
+	struct map_desc dram_io_desc[1];
+
+	dram_io_desc[0].virtual = __phys_to_virt(am33xx_paddr);
+	dram_io_desc[0].pfn = __phys_to_pfn(am33xx_paddr);
+	dram_io_desc[0].length = am33xx_size;
+	dram_io_desc[0].type = MT_MEMORY_SO;
+
+	iotable_init(dram_io_desc, ARRAY_SIZE(dram_io_desc));
+
+	am33xx_dram_sync = (void __iomem *) dram_io_desc[0].virtual;
+}
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index dfcc182..6b8ef74 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -294,6 +294,10 @@ struct omap2_hsmmc_info;
 extern int omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers);
 extern void omap_reserve(void);
 
+extern void am33xx_reserve(void);
+extern void am33xx_dram_sync_init(void);
+extern void __iomem *am33xx_dram_sync;
+
 struct omap_hwmod;
 extern int omap_dss_reset(struct omap_hwmod *);
 
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 4a3f06f..3ad7543 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -322,6 +322,7 @@ void __init ti81xx_map_io(void)
 void __init am33xx_map_io(void)
 {
 	iotable_init(omapam33xx_io_desc, ARRAY_SIZE(omapam33xx_io_desc));
+	am33xx_dram_sync_init();
 }
 #endif
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 212+ messages in thread

* [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
@ 2013-08-06 17:49   ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel

From: Vaibhav Bedia <vaibhav.bedia@ti.com>

SDRAM controller on AM33XX requires that a modification of certain
bit-fields in PWR_MGMT_CTRL register (ref. section 7.3.5.13 in
AM335x-Rev H) is followed by a dummy read access to SDRAM. This
scenario arises when entering a low power state like DeepSleep.
To ensure that the read is not from a cached region we reserve
some memory during bootup using the arm_memblock_steal() API.

A subsequent patch will pass along the location of the reserved
memory location to the AM335x suspend handler which modifies the
PWR_MGMT_CTRL register in the EMIF.

Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
 arch/arm/mach-omap2/board-generic.c |    2 +-
 arch/arm/mach-omap2/common.c        |   28 ++++++++++++++++++++++++++++
 arch/arm/mach-omap2/common.h        |    4 ++++
 arch/arm/mach-omap2/io.c            |    1 +
 4 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index be5d005..aed750c 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -156,7 +156,7 @@ static const char *am33xx_boards_compat[] __initdata = {
 };
 
 DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)")
-	.reserve	= omap_reserve,
+	.reserve	= am33xx_reserve,
 	.map_io		= am33xx_map_io,
 	.init_early	= am33xx_init_early,
 	.init_irq	= omap_intc_of_init,
diff --git a/arch/arm/mach-omap2/common.c b/arch/arm/mach-omap2/common.c
index 2dabb9e..756586f 100644
--- a/arch/arm/mach-omap2/common.c
+++ b/arch/arm/mach-omap2/common.c
@@ -15,6 +15,8 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_data/dsp-omap.h>
+#include <asm/memblock.h>
+#include <asm/mach/map.h>
 
 #include "common.h"
 #include "omap-secure.h"
@@ -34,3 +36,29 @@ void __init omap_reserve(void)
 	omap_secure_ram_reserve_memblock();
 	omap_barrier_reserve_memblock();
 }
+
+static phys_addr_t am33xx_paddr;
+static u32 am33xx_size;
+
+/* Steal one page physical memory for uncached read DeepSleep */
+void __init am33xx_reserve(void)
+{
+	am33xx_size = ALIGN(PAGE_SIZE, SZ_1M);
+	am33xx_paddr = arm_memblock_steal(am33xx_size, SZ_1M);
+}
+
+void __iomem *am33xx_dram_sync;
+
+void __init am33xx_dram_sync_init(void)
+{
+	struct map_desc dram_io_desc[1];
+
+	dram_io_desc[0].virtual = __phys_to_virt(am33xx_paddr);
+	dram_io_desc[0].pfn = __phys_to_pfn(am33xx_paddr);
+	dram_io_desc[0].length = am33xx_size;
+	dram_io_desc[0].type = MT_MEMORY_SO;
+
+	iotable_init(dram_io_desc, ARRAY_SIZE(dram_io_desc));
+
+	am33xx_dram_sync = (void __iomem *) dram_io_desc[0].virtual;
+}
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index dfcc182..6b8ef74 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -294,6 +294,10 @@ struct omap2_hsmmc_info;
 extern int omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers);
 extern void omap_reserve(void);
 
+extern void am33xx_reserve(void);
+extern void am33xx_dram_sync_init(void);
+extern void __iomem *am33xx_dram_sync;
+
 struct omap_hwmod;
 extern int omap_dss_reset(struct omap_hwmod *);
 
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 4a3f06f..3ad7543 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -322,6 +322,7 @@ void __init ti81xx_map_io(void)
 void __init am33xx_map_io(void)
 {
 	iotable_init(omapam33xx_io_desc, ARRAY_SIZE(omapam33xx_io_desc));
+	am33xx_dram_sync_init();
 }
 #endif
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 212+ messages in thread

* [PATCHv3 5/9] ARM: OMAP2+: AM33XX: Add assembly code for PM operations
  2013-08-06 17:49 ` Dave Gerlach
@ 2013-08-06 17:49   ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap
  Cc: Paul Walmsley, Kevin Hilman, Vaibhav Bedia, Dave Gerlach,
	Santosh Shilimkar

From: Vaibhav Bedia <vaibhav.bedia@ti.com>

In preparation for suspend-resume support for AM33XX, add
the assembly file with the code which is copied to internal
memory (OCMC RAM) during bootup and runs from there.

As part of the low power entry (DeepSleep0 mode in AM33XX TRM),
the code running from OCMC RAM does the following
1. Stores the EMIF configuration
2. Puts external memory in self-refresh
3. Disables EMIF clock
4. Executes WFI after writing to MPU_CLKCTRL register.

If no interrupts have come, WFI execution on MPU gets registered
as an interrupt with the WKUP-M3. WKUP-M3 takes care of disabling
some clocks which MPU should not (L3, L4, OCMC RAM etc) and takes
care of clockdomain and powerdomain transitions as part of the
DeepSleep0 mode entry.

In case a late interrupt comes in, WFI ends up as a NOP and MPU
continues execution from internal memory. The 'abort path' code
undoes whatever was done as part of the low power entry and indicates
a suspend failure by passing a non-zero value to the cpu_resume routine.

The 'resume path' code is similar to the 'abort path' with the key
difference of MMU being enabled in the 'abort path' but being
disabled in the 'resume path' due to MPU getting powered off.

Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Kevin Hilman <khilman@linaro.org>
---
 arch/arm/mach-omap2/sleep33xx.S |  350 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 350 insertions(+)
 create mode 100644 arch/arm/mach-omap2/sleep33xx.S

diff --git a/arch/arm/mach-omap2/sleep33xx.S b/arch/arm/mach-omap2/sleep33xx.S
new file mode 100644
index 0000000..834c7d4
--- /dev/null
+++ b/arch/arm/mach-omap2/sleep33xx.S
@@ -0,0 +1,350 @@
+/*
+ * Low level suspend code for AM33XX SoCs
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Vaibhav Bedia <vaibhav.bedia@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/linkage.h>
+#include <linux/ti_emif.h>
+#include <asm/memory.h>
+#include <asm/assembler.h>
+
+#include "cm33xx.h"
+#include "pm33xx.h"
+#include "prm33xx.h"
+
+	.text
+	.align 3
+
+/*
+ * This routine is executed from internal RAM and expects some
+ * parameters to be passed in r0 _strictly_ in following order:
+ * 1) emif_addr_virt - ioremapped EMIF address
+ * 2) mem_type - 2 -> DDR2, 3-> DDR3
+ * 3) dram_sync_word - uncached word in SDRAM
+ *
+ * The code loads these values taking r0 value as reference to
+ * the array in registers starting from r0, i.e emif_addr_virt
+ * goes to r1, mem_type goes to r2 and and so on. These are
+ * then saved into memory locations before proceeding with the
+ * sleep sequence and hence registers r0, r1 etc can still be
+ * used in the rest of the sleep code.
+ */
+
+ENTRY(am33xx_do_wfi)
+	stmfd	sp!, {r4 - r11, lr}	@ save registers on stack
+
+	ldm	r0, {r1-r3}		@ gather values passed
+
+	/* Save the values passed */
+	str	r1, emif_addr_virt
+	str	r2, mem_type
+	str	r3, dram_sync_word
+
+	/*
+	 * Flush all data from the L1 data cache before disabling
+	 * SCTLR.C bit.
+	 */
+	ldr	r1, kernel_flush
+	blx	r1
+
+	/*
+	 * Clear the SCTLR.C bit to prevent further data cache
+	 * allocation. Clearing SCTLR.C would make all the data accesses
+	 * strongly ordered and would not hit the cache.
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #(1 << 2)	@ Disable the C bit
+	mcr	p15, 0, r0, c1, c0, 0
+	isb
+
+	/*
+	 * Invalidate L1 data cache. Even though only invalidate is
+	 * necessary exported flush API is used here. Doing clean
+	 * on already clean cache would be almost NOP.
+	 */
+	ldr	r1, kernel_flush
+	blx	r1
+
+	ldr	r0, emif_addr_virt
+	/* Save EMIF configuration */
+	ldr	r1, [r0, #EMIF_SDRAM_CONFIG]
+	str	r1, emif_sdcfg_val
+	ldr	r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
+	str	r1, emif_ref_ctrl_val
+	ldr	r1, [r0, #EMIF_SDRAM_TIMING_1]
+	str	r1, emif_timing1_val
+	ldr	r1, [r0, #EMIF_SDRAM_TIMING_2]
+	str	r1, emif_timing2_val
+	ldr	r1, [r0, #EMIF_SDRAM_TIMING_3]
+	str	r1, emif_timing3_val
+	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+	str	r1, emif_pmcr_val
+	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
+	str	r1, emif_pmcr_shdw_val
+	ldr	r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
+	str	r1, emif_zqcfg_val
+	ldr	r1, [r0, #EMIF_DDR_PHY_CTRL_1]
+	str	r1, emif_rd_lat_val
+
+	/* Put SDRAM in self-refresh */
+	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+	orr	r1, r1, #0xa0
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
+	str	r1, [r0, #4]
+
+	ldr	r1, dram_sync_word	@ a dummy access to DDR as per spec
+	ldr	r2, [r1, #0]
+	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+	orr	r1, r1, #0x200
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+
+	mov	r1, #0x1000		@ Wait for system to enter SR
+wait_sr:
+	subs	r1, r1, #1
+	bne	wait_sr
+
+	/* Disable EMIF */
+	ldr	r1, virt_emif_clkctrl
+	ldr	r2, [r1]
+	bic	r2, r2, #0x03
+	str	r2, [r1]
+
+	ldr	r1, virt_emif_clkctrl
+wait_emif_disable:
+	ldr	r2, [r1]
+	ldr	r3, module_disabled_val
+	cmp	r2, r3
+	bne	wait_emif_disable
+
+	/*
+	 * For the MPU WFI to be registered as an interrupt
+	 * to WKUP_M3, MPU_CLKCTRL.MODULEMODE needs to be set
+	 * to DISABLED
+	 */
+	ldr	r1, virt_mpu_clkctrl
+	ldr	r2, [r1]
+	bic	r2, r2, #0x03
+	str	r2, [r1]
+
+	/*
+	 * Execute an ISB instruction to ensure that all of the
+	 * CP15 register changes have been committed.
+	 */
+	isb
+
+	/*
+	 * Execute a barrier instruction to ensure that all cache,
+	 * TLB and branch predictor maintenance operations issued
+	 * have completed.
+	 */
+	dsb
+	dmb
+
+	/*
+	 * Execute a WFI instruction and wait until the
+	 * STANDBYWFI output is asserted to indicate that the
+	 * CPU is in idle and low power state. CPU can specualatively
+	 * prefetch the instructions so add NOPs after WFI. Thirteen
+	 * NOPs as per Cortex-A8 pipeline.
+	 */
+	wfi
+
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	/* We come here in case of an abort due to a late interrupt */
+
+	/* Set MPU_CLKCTRL.MODULEMODE back to ENABLE */
+	ldr	r1, virt_mpu_clkctrl
+	mov	r2, #0x02
+	str	r2, [r1]
+
+	/* Re-enable EMIF */
+	ldr	r1, virt_emif_clkctrl
+	mov	r2, #0x02
+	str	r2, [r1]
+wait_emif_enable:
+	ldr	r3, [r1]
+	cmp	r2, r3
+	bne	wait_emif_enable
+
+	/* Disable EMIF self-refresh */
+	ldr	r0, emif_addr_virt
+	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+	bic	r1, r1, #LP_MODE_MASK
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
+
+	/*
+	 * A write to SDRAM CONFIG register triggers
+	 * an init sequence and hence it must be done
+	 * at the end for DDR2
+	 */
+	ldr r0, emif_addr_virt
+	add r0, r0, #EMIF_SDRAM_CONFIG
+	ldr r4, emif_sdcfg_val
+	str r4, [r0]
+
+	/*
+	 * Set SCTLR.C bit to allow data cache allocation
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	orr	r0, r0, #(1 << 2)	@ Enable the C bit
+	mcr	p15, 0, r0, c1, c0, 0
+	isb
+
+	/* Kill some time for sanity to settle in */
+	mov r0, #0x1000
+wait_abt:
+	subs   r0, r0, #1
+	bne wait_abt
+
+	/* Let the suspend code know about the abort */
+	mov	r0, #1
+	ldmfd	sp!, {r4 - r11, pc}	@ restore regs and return
+ENDPROC(am33xx_do_wfi)
+
+	.align
+ENTRY(am33xx_resume_offset)
+	.word . - am33xx_do_wfi
+
+ENTRY(am33xx_resume_from_deep_sleep)
+	/* Re-enable EMIF */
+	ldr	r0, phys_emif_clkctrl
+	mov	r1, #0x02
+	str	r1, [r0]
+wait_emif_enable1:
+	ldr	r2, [r0]
+	cmp	r1, r2
+	bne	wait_emif_enable1
+
+	/* Config EMIF Timings */
+	ldr	r0, emif_phys_addr
+	ldr	r1, emif_rd_lat_val
+	str	r1, [r0, #EMIF_DDR_PHY_CTRL_1]
+	str	r1, [r0, #EMIF_DDR_PHY_CTRL_1_SHDW]
+	ldr	r1, emif_timing1_val
+	str	r1, [r0, #EMIF_SDRAM_TIMING_1]
+	str	r1, [r0, #EMIF_SDRAM_TIMING_1_SHDW]
+	ldr	r1, emif_timing2_val
+	str	r1, [r0, #EMIF_SDRAM_TIMING_2]
+	str	r1, [r0, #EMIF_SDRAM_TIMING_2_SHDW]
+	ldr	r1, emif_timing3_val
+	str	r1, [r0, #EMIF_SDRAM_TIMING_3]
+	str	r1, [r0, #EMIF_SDRAM_TIMING_3_SHDW]
+	ldr	r1, emif_ref_ctrl_val
+	str	r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
+	str	r1, [r0, #EMIF_SDRAM_REFRESH_CTRL_SHDW]
+	ldr	r1, emif_pmcr_val
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+	ldr	r1, emif_pmcr_shdw_val
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
+
+	/*
+	 * Output impedence calib needed only for DDR3
+	 * but since the initial state of this will be
+	 * disabled for DDR2 no harm in restoring the
+	 * old configuration
+	 */
+	ldr	r1, emif_zqcfg_val
+	str	r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
+
+	/* Write to SDRAM_CONFIG only for DDR2 */
+	ldr	r2, mem_type
+	cmp	r2, #MEM_TYPE_DDR2
+	bne	resume_to_ddr
+
+	/*
+	 * A write to SDRAM CONFIG register triggers
+	 * an init sequence and hence it must be done
+	 * at the end for DDR2
+	 */
+	ldr	r1, emif_sdcfg_val
+	str	r1, [r0, #EMIF_SDRAM_CONFIG]
+
+resume_to_ddr:
+	/* Back from la-la-land. Kill some time for sanity to settle in */
+	mov	r0, #0x1000
+wait_resume:
+	subs	r0, r0, #1
+	bne	wait_resume
+
+	/* We are back. Branch to the common CPU resume routine */
+	mov	r0, #0
+	ldr	pc, resume_addr
+ENDPROC(am33xx_resume_from_deep_sleep)
+
+
+/*
+ * Local variables
+ */
+	.align
+resume_addr:
+	.word	cpu_resume - PAGE_OFFSET + 0x80000000
+kernel_flush:
+	.word   v7_flush_dcache_all
+ddr_start:
+	.word	PAGE_OFFSET
+emif_phys_addr:
+	.word	AM33XX_EMIF_BASE
+virt_mpu_clkctrl:
+	.word	AM33XX_CM_MPU_MPU_CLKCTRL
+virt_emif_clkctrl:
+	.word	AM33XX_CM_PER_EMIF_CLKCTRL
+phys_emif_clkctrl:
+	.word	(AM33XX_CM_BASE + AM33XX_CM_PER_MOD + \
+		AM33XX_CM_PER_EMIF_CLKCTRL_OFFSET)
+module_disabled_val:
+	.word	0x30000
+
+/* DDR related defines */
+dram_sync_word:
+	.word	0xDEADBEEF
+mem_type:
+	.word	0xDEADBEEF
+emif_addr_virt:
+	.word	0xDEADBEEF
+emif_rd_lat_val:
+	.word	0xDEADBEEF
+emif_timing1_val:
+	.word	0xDEADBEEF
+emif_timing2_val:
+	.word	0xDEADBEEF
+emif_timing3_val:
+	.word	0xDEADBEEF
+emif_sdcfg_val:
+	.word	0xDEADBEEF
+emif_ref_ctrl_val:
+	.word	0xDEADBEEF
+emif_zqcfg_val:
+	.word	0xDEADBEEF
+emif_pmcr_val:
+	.word	0xDEADBEEF
+emif_pmcr_shdw_val:
+	.word	0xDEADBEEF
+
+	.align 3
+ENTRY(am33xx_do_wfi_sz)
+	.word	. - am33xx_do_wfi
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 212+ messages in thread

* [PATCHv3 5/9] ARM: OMAP2+: AM33XX: Add assembly code for PM operations
@ 2013-08-06 17:49   ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel

From: Vaibhav Bedia <vaibhav.bedia@ti.com>

In preparation for suspend-resume support for AM33XX, add
the assembly file with the code which is copied to internal
memory (OCMC RAM) during bootup and runs from there.

As part of the low power entry (DeepSleep0 mode in AM33XX TRM),
the code running from OCMC RAM does the following
1. Stores the EMIF configuration
2. Puts external memory in self-refresh
3. Disables EMIF clock
4. Executes WFI after writing to MPU_CLKCTRL register.

If no interrupts have come, WFI execution on MPU gets registered
as an interrupt with the WKUP-M3. WKUP-M3 takes care of disabling
some clocks which MPU should not (L3, L4, OCMC RAM etc) and takes
care of clockdomain and powerdomain transitions as part of the
DeepSleep0 mode entry.

In case a late interrupt comes in, WFI ends up as a NOP and MPU
continues execution from internal memory. The 'abort path' code
undoes whatever was done as part of the low power entry and indicates
a suspend failure by passing a non-zero value to the cpu_resume routine.

The 'resume path' code is similar to the 'abort path' with the key
difference of MMU being enabled in the 'abort path' but being
disabled in the 'resume path' due to MPU getting powered off.

Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Kevin Hilman <khilman@linaro.org>
---
 arch/arm/mach-omap2/sleep33xx.S |  350 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 350 insertions(+)
 create mode 100644 arch/arm/mach-omap2/sleep33xx.S

diff --git a/arch/arm/mach-omap2/sleep33xx.S b/arch/arm/mach-omap2/sleep33xx.S
new file mode 100644
index 0000000..834c7d4
--- /dev/null
+++ b/arch/arm/mach-omap2/sleep33xx.S
@@ -0,0 +1,350 @@
+/*
+ * Low level suspend code for AM33XX SoCs
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Vaibhav Bedia <vaibhav.bedia@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/linkage.h>
+#include <linux/ti_emif.h>
+#include <asm/memory.h>
+#include <asm/assembler.h>
+
+#include "cm33xx.h"
+#include "pm33xx.h"
+#include "prm33xx.h"
+
+	.text
+	.align 3
+
+/*
+ * This routine is executed from internal RAM and expects some
+ * parameters to be passed in r0 _strictly_ in following order:
+ * 1) emif_addr_virt - ioremapped EMIF address
+ * 2) mem_type - 2 -> DDR2, 3-> DDR3
+ * 3) dram_sync_word - uncached word in SDRAM
+ *
+ * The code loads these values taking r0 value as reference to
+ * the array in registers starting from r0, i.e emif_addr_virt
+ * goes to r1, mem_type goes to r2 and and so on. These are
+ * then saved into memory locations before proceeding with the
+ * sleep sequence and hence registers r0, r1 etc can still be
+ * used in the rest of the sleep code.
+ */
+
+ENTRY(am33xx_do_wfi)
+	stmfd	sp!, {r4 - r11, lr}	@ save registers on stack
+
+	ldm	r0, {r1-r3}		@ gather values passed
+
+	/* Save the values passed */
+	str	r1, emif_addr_virt
+	str	r2, mem_type
+	str	r3, dram_sync_word
+
+	/*
+	 * Flush all data from the L1 data cache before disabling
+	 * SCTLR.C bit.
+	 */
+	ldr	r1, kernel_flush
+	blx	r1
+
+	/*
+	 * Clear the SCTLR.C bit to prevent further data cache
+	 * allocation. Clearing SCTLR.C would make all the data accesses
+	 * strongly ordered and would not hit the cache.
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #(1 << 2)	@ Disable the C bit
+	mcr	p15, 0, r0, c1, c0, 0
+	isb
+
+	/*
+	 * Invalidate L1 data cache. Even though only invalidate is
+	 * necessary exported flush API is used here. Doing clean
+	 * on already clean cache would be almost NOP.
+	 */
+	ldr	r1, kernel_flush
+	blx	r1
+
+	ldr	r0, emif_addr_virt
+	/* Save EMIF configuration */
+	ldr	r1, [r0, #EMIF_SDRAM_CONFIG]
+	str	r1, emif_sdcfg_val
+	ldr	r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
+	str	r1, emif_ref_ctrl_val
+	ldr	r1, [r0, #EMIF_SDRAM_TIMING_1]
+	str	r1, emif_timing1_val
+	ldr	r1, [r0, #EMIF_SDRAM_TIMING_2]
+	str	r1, emif_timing2_val
+	ldr	r1, [r0, #EMIF_SDRAM_TIMING_3]
+	str	r1, emif_timing3_val
+	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+	str	r1, emif_pmcr_val
+	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
+	str	r1, emif_pmcr_shdw_val
+	ldr	r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
+	str	r1, emif_zqcfg_val
+	ldr	r1, [r0, #EMIF_DDR_PHY_CTRL_1]
+	str	r1, emif_rd_lat_val
+
+	/* Put SDRAM in self-refresh */
+	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+	orr	r1, r1, #0xa0
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
+	str	r1, [r0, #4]
+
+	ldr	r1, dram_sync_word	@ a dummy access to DDR as per spec
+	ldr	r2, [r1, #0]
+	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+	orr	r1, r1, #0x200
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+
+	mov	r1, #0x1000		@ Wait for system to enter SR
+wait_sr:
+	subs	r1, r1, #1
+	bne	wait_sr
+
+	/* Disable EMIF */
+	ldr	r1, virt_emif_clkctrl
+	ldr	r2, [r1]
+	bic	r2, r2, #0x03
+	str	r2, [r1]
+
+	ldr	r1, virt_emif_clkctrl
+wait_emif_disable:
+	ldr	r2, [r1]
+	ldr	r3, module_disabled_val
+	cmp	r2, r3
+	bne	wait_emif_disable
+
+	/*
+	 * For the MPU WFI to be registered as an interrupt
+	 * to WKUP_M3, MPU_CLKCTRL.MODULEMODE needs to be set
+	 * to DISABLED
+	 */
+	ldr	r1, virt_mpu_clkctrl
+	ldr	r2, [r1]
+	bic	r2, r2, #0x03
+	str	r2, [r1]
+
+	/*
+	 * Execute an ISB instruction to ensure that all of the
+	 * CP15 register changes have been committed.
+	 */
+	isb
+
+	/*
+	 * Execute a barrier instruction to ensure that all cache,
+	 * TLB and branch predictor maintenance operations issued
+	 * have completed.
+	 */
+	dsb
+	dmb
+
+	/*
+	 * Execute a WFI instruction and wait until the
+	 * STANDBYWFI output is asserted to indicate that the
+	 * CPU is in idle and low power state. CPU can specualatively
+	 * prefetch the instructions so add NOPs after WFI. Thirteen
+	 * NOPs as per Cortex-A8 pipeline.
+	 */
+	wfi
+
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	/* We come here in case of an abort due to a late interrupt */
+
+	/* Set MPU_CLKCTRL.MODULEMODE back to ENABLE */
+	ldr	r1, virt_mpu_clkctrl
+	mov	r2, #0x02
+	str	r2, [r1]
+
+	/* Re-enable EMIF */
+	ldr	r1, virt_emif_clkctrl
+	mov	r2, #0x02
+	str	r2, [r1]
+wait_emif_enable:
+	ldr	r3, [r1]
+	cmp	r2, r3
+	bne	wait_emif_enable
+
+	/* Disable EMIF self-refresh */
+	ldr	r0, emif_addr_virt
+	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+	bic	r1, r1, #LP_MODE_MASK
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
+
+	/*
+	 * A write to SDRAM CONFIG register triggers
+	 * an init sequence and hence it must be done
+	 * at the end for DDR2
+	 */
+	ldr r0, emif_addr_virt
+	add r0, r0, #EMIF_SDRAM_CONFIG
+	ldr r4, emif_sdcfg_val
+	str r4, [r0]
+
+	/*
+	 * Set SCTLR.C bit to allow data cache allocation
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	orr	r0, r0, #(1 << 2)	@ Enable the C bit
+	mcr	p15, 0, r0, c1, c0, 0
+	isb
+
+	/* Kill some time for sanity to settle in */
+	mov r0, #0x1000
+wait_abt:
+	subs   r0, r0, #1
+	bne wait_abt
+
+	/* Let the suspend code know about the abort */
+	mov	r0, #1
+	ldmfd	sp!, {r4 - r11, pc}	@ restore regs and return
+ENDPROC(am33xx_do_wfi)
+
+	.align
+ENTRY(am33xx_resume_offset)
+	.word . - am33xx_do_wfi
+
+ENTRY(am33xx_resume_from_deep_sleep)
+	/* Re-enable EMIF */
+	ldr	r0, phys_emif_clkctrl
+	mov	r1, #0x02
+	str	r1, [r0]
+wait_emif_enable1:
+	ldr	r2, [r0]
+	cmp	r1, r2
+	bne	wait_emif_enable1
+
+	/* Config EMIF Timings */
+	ldr	r0, emif_phys_addr
+	ldr	r1, emif_rd_lat_val
+	str	r1, [r0, #EMIF_DDR_PHY_CTRL_1]
+	str	r1, [r0, #EMIF_DDR_PHY_CTRL_1_SHDW]
+	ldr	r1, emif_timing1_val
+	str	r1, [r0, #EMIF_SDRAM_TIMING_1]
+	str	r1, [r0, #EMIF_SDRAM_TIMING_1_SHDW]
+	ldr	r1, emif_timing2_val
+	str	r1, [r0, #EMIF_SDRAM_TIMING_2]
+	str	r1, [r0, #EMIF_SDRAM_TIMING_2_SHDW]
+	ldr	r1, emif_timing3_val
+	str	r1, [r0, #EMIF_SDRAM_TIMING_3]
+	str	r1, [r0, #EMIF_SDRAM_TIMING_3_SHDW]
+	ldr	r1, emif_ref_ctrl_val
+	str	r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
+	str	r1, [r0, #EMIF_SDRAM_REFRESH_CTRL_SHDW]
+	ldr	r1, emif_pmcr_val
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+	ldr	r1, emif_pmcr_shdw_val
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
+
+	/*
+	 * Output impedence calib needed only for DDR3
+	 * but since the initial state of this will be
+	 * disabled for DDR2 no harm in restoring the
+	 * old configuration
+	 */
+	ldr	r1, emif_zqcfg_val
+	str	r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
+
+	/* Write to SDRAM_CONFIG only for DDR2 */
+	ldr	r2, mem_type
+	cmp	r2, #MEM_TYPE_DDR2
+	bne	resume_to_ddr
+
+	/*
+	 * A write to SDRAM CONFIG register triggers
+	 * an init sequence and hence it must be done
+	 *@the end for DDR2
+	 */
+	ldr	r1, emif_sdcfg_val
+	str	r1, [r0, #EMIF_SDRAM_CONFIG]
+
+resume_to_ddr:
+	/* Back from la-la-land. Kill some time for sanity to settle in */
+	mov	r0, #0x1000
+wait_resume:
+	subs	r0, r0, #1
+	bne	wait_resume
+
+	/* We are back. Branch to the common CPU resume routine */
+	mov	r0, #0
+	ldr	pc, resume_addr
+ENDPROC(am33xx_resume_from_deep_sleep)
+
+
+/*
+ * Local variables
+ */
+	.align
+resume_addr:
+	.word	cpu_resume - PAGE_OFFSET + 0x80000000
+kernel_flush:
+	.word   v7_flush_dcache_all
+ddr_start:
+	.word	PAGE_OFFSET
+emif_phys_addr:
+	.word	AM33XX_EMIF_BASE
+virt_mpu_clkctrl:
+	.word	AM33XX_CM_MPU_MPU_CLKCTRL
+virt_emif_clkctrl:
+	.word	AM33XX_CM_PER_EMIF_CLKCTRL
+phys_emif_clkctrl:
+	.word	(AM33XX_CM_BASE + AM33XX_CM_PER_MOD + \
+		AM33XX_CM_PER_EMIF_CLKCTRL_OFFSET)
+module_disabled_val:
+	.word	0x30000
+
+/* DDR related defines */
+dram_sync_word:
+	.word	0xDEADBEEF
+mem_type:
+	.word	0xDEADBEEF
+emif_addr_virt:
+	.word	0xDEADBEEF
+emif_rd_lat_val:
+	.word	0xDEADBEEF
+emif_timing1_val:
+	.word	0xDEADBEEF
+emif_timing2_val:
+	.word	0xDEADBEEF
+emif_timing3_val:
+	.word	0xDEADBEEF
+emif_sdcfg_val:
+	.word	0xDEADBEEF
+emif_ref_ctrl_val:
+	.word	0xDEADBEEF
+emif_zqcfg_val:
+	.word	0xDEADBEEF
+emif_pmcr_val:
+	.word	0xDEADBEEF
+emif_pmcr_shdw_val:
+	.word	0xDEADBEEF
+
+	.align 3
+ENTRY(am33xx_do_wfi_sz)
+	.word	. - am33xx_do_wfi
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 212+ messages in thread

* [PATCHv3 6/9] ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device
  2013-08-06 17:49 ` Dave Gerlach
@ 2013-08-06 17:49   ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap
  Cc: Paul Walmsley, Kevin Hilman, Vaibhav Bedia, Dave Gerlach

From: Vaibhav Bedia <vaibhav.bedia@ti.com>

OMAP timer code registers two timers - one as clocksource
and one as clockevent. Since AM33XX has only one usable timer
in the WKUP domain one of the timers needs suspend-resume
support to restore the configuration to pre-suspend state.

commit adc78e6 (timekeeping: Add suspend and resume
of clock event devices) introduced .suspend and .resume
callbacks for clock event devices. Leverages these
callbacks to have AM33XX clockevent timer which is
in not in WKUP domain to behave properly across system
suspend.

Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
 arch/arm/mach-omap2/timer.c |   32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index b37e1fc..cce5d39 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -118,11 +118,43 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
 	}
 }
 
+static void omap_clkevt_suspend(struct clock_event_device *unused)
+{
+	char name[10];
+	struct omap_hwmod *oh;
+
+	sprintf(name, "timer%d", clkev.id);
+	oh = omap_hwmod_lookup(name);
+	if (!oh)
+		return;
+
+	__omap_dm_timer_stop(&clkev, 1, clkev.rate);
+	omap_hwmod_idle(oh);
+}
+
+static void omap_clkevt_resume(struct clock_event_device *unused)
+{
+	char name[10];
+	struct omap_hwmod *oh;
+
+	sprintf(name, "timer%d", clkev.id);
+	oh = omap_hwmod_lookup(name);
+	if (!oh)
+		return;
+
+	omap_hwmod_enable(oh);
+	__omap_dm_timer_load_start(&clkev,
+			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
+	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
+}
+
 static struct clock_event_device clockevent_gpt = {
 	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
 	.rating		= 300,
 	.set_next_event	= omap2_gp_timer_set_next_event,
 	.set_mode	= omap2_gp_timer_set_mode,
+	.suspend	= omap_clkevt_suspend,
+	.resume		= omap_clkevt_resume,
 };
 
 static struct property device_disabled = {
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 212+ messages in thread

* [PATCHv3 6/9] ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device
@ 2013-08-06 17:49   ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel

From: Vaibhav Bedia <vaibhav.bedia@ti.com>

OMAP timer code registers two timers - one as clocksource
and one as clockevent. Since AM33XX has only one usable timer
in the WKUP domain one of the timers needs suspend-resume
support to restore the configuration to pre-suspend state.

commit adc78e6 (timekeeping: Add suspend and resume
of clock event devices) introduced .suspend and .resume
callbacks for clock event devices. Leverages these
callbacks to have AM33XX clockevent timer which is
in not in WKUP domain to behave properly across system
suspend.

Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
 arch/arm/mach-omap2/timer.c |   32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index b37e1fc..cce5d39 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -118,11 +118,43 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
 	}
 }
 
+static void omap_clkevt_suspend(struct clock_event_device *unused)
+{
+	char name[10];
+	struct omap_hwmod *oh;
+
+	sprintf(name, "timer%d", clkev.id);
+	oh = omap_hwmod_lookup(name);
+	if (!oh)
+		return;
+
+	__omap_dm_timer_stop(&clkev, 1, clkev.rate);
+	omap_hwmod_idle(oh);
+}
+
+static void omap_clkevt_resume(struct clock_event_device *unused)
+{
+	char name[10];
+	struct omap_hwmod *oh;
+
+	sprintf(name, "timer%d", clkev.id);
+	oh = omap_hwmod_lookup(name);
+	if (!oh)
+		return;
+
+	omap_hwmod_enable(oh);
+	__omap_dm_timer_load_start(&clkev,
+			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
+	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
+}
+
 static struct clock_event_device clockevent_gpt = {
 	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
 	.rating		= 300,
 	.set_next_event	= omap2_gp_timer_set_next_event,
 	.set_mode	= omap2_gp_timer_set_mode,
+	.suspend	= omap_clkevt_suspend,
+	.resume		= omap_clkevt_resume,
 };
 
 static struct property device_disabled = {
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 212+ messages in thread

* [PATCHv3 7/9] ARM: OMAP: omap_device: Add APIs to enable and idle hwmods
  2013-08-06 17:49 ` Dave Gerlach
@ 2013-08-06 17:49   ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap
  Cc: Paul Walmsley, Kevin Hilman, Vaibhav Bedia, Dave Gerlach

From: Vaibhav Bedia <vaibhav.bedia@ti.com>

Needed to let the AM335x PM handle the IPs which need forced
standby transition during every suspend-resume cycle when
the corresponding driver is not compiled into the kernel.

Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
 arch/arm/mach-omap2/omap_device.c |    8 ++++++++
 arch/arm/mach-omap2/omap_device.h |    2 ++
 2 files changed, 10 insertions(+)

diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index 5cc9287..8cf63f6 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -219,6 +219,10 @@ static int _omap_device_enable_hwmods(struct omap_device *od)
 	return 0;
 }
 
+int omap_device_enable_hwmods(struct omap_device *od)
+{
+	return _omap_device_enable_hwmods(od);
+}
 /**
  * _omap_device_idle_hwmods - call omap_hwmod_idle() on all hwmods
  * @od: struct omap_device *od
@@ -236,6 +240,10 @@ static int _omap_device_idle_hwmods(struct omap_device *od)
 	return 0;
 }
 
+int omap_device_idle_hwmods(struct omap_device *od)
+{
+	return _omap_device_idle_hwmods(od);
+}
 /* Public functions for use by core code */
 
 /**
diff --git a/arch/arm/mach-omap2/omap_device.h b/arch/arm/mach-omap2/omap_device.h
index 17ca1ae..655ec35 100644
--- a/arch/arm/mach-omap2/omap_device.h
+++ b/arch/arm/mach-omap2/omap_device.h
@@ -87,6 +87,8 @@ struct device *omap_device_get_by_hwmod_name(const char *oh_name);
 
 /* OMAP PM interface */
 int omap_device_get_context_loss_count(struct platform_device *pdev);
+int omap_device_enable_hwmods(struct omap_device *od);
+int omap_device_idle_hwmods(struct omap_device *od);
 
 /* Other */
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 212+ messages in thread

* [PATCHv3 7/9] ARM: OMAP: omap_device: Add APIs to enable and idle hwmods
@ 2013-08-06 17:49   ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel

From: Vaibhav Bedia <vaibhav.bedia@ti.com>

Needed to let the AM335x PM handle the IPs which need forced
standby transition during every suspend-resume cycle when
the corresponding driver is not compiled into the kernel.

Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
 arch/arm/mach-omap2/omap_device.c |    8 ++++++++
 arch/arm/mach-omap2/omap_device.h |    2 ++
 2 files changed, 10 insertions(+)

diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index 5cc9287..8cf63f6 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -219,6 +219,10 @@ static int _omap_device_enable_hwmods(struct omap_device *od)
 	return 0;
 }
 
+int omap_device_enable_hwmods(struct omap_device *od)
+{
+	return _omap_device_enable_hwmods(od);
+}
 /**
  * _omap_device_idle_hwmods - call omap_hwmod_idle() on all hwmods
  * @od: struct omap_device *od
@@ -236,6 +240,10 @@ static int _omap_device_idle_hwmods(struct omap_device *od)
 	return 0;
 }
 
+int omap_device_idle_hwmods(struct omap_device *od)
+{
+	return _omap_device_idle_hwmods(od);
+}
 /* Public functions for use by core code */
 
 /**
diff --git a/arch/arm/mach-omap2/omap_device.h b/arch/arm/mach-omap2/omap_device.h
index 17ca1ae..655ec35 100644
--- a/arch/arm/mach-omap2/omap_device.h
+++ b/arch/arm/mach-omap2/omap_device.h
@@ -87,6 +87,8 @@ struct device *omap_device_get_by_hwmod_name(const char *oh_name);
 
 /* OMAP PM interface */
 int omap_device_get_context_loss_count(struct platform_device *pdev);
+int omap_device_enable_hwmods(struct omap_device *od);
+int omap_device_idle_hwmods(struct omap_device *od);
 
 /* Other */
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-06 17:49 ` Dave Gerlach
@ 2013-08-06 17:49   ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap
  Cc: Paul Walmsley, Kevin Hilman, Vaibhav Bedia, Dave Gerlach,
	Tony Lingren, Santosh Shilimkar, Benoit Cousson

From: Vaibhav Bedia <vaibhav.bedia@ti.com>

AM335x supports various low power modes as documented
in section 8.1.4.3 of the AM335x TRM which is available
@ http://www.ti.com/litv/pdf/spruh73f

DeepSleep0 mode offers the lowest power mode with limited
wakeup sources without a system reboot and is mapped as
the suspend state in the kernel. In this state, MPU and
PER domains are turned off with the internal RAM held in
retention to facilitate resume process. As part of the boot
process, the assembly code is copied over to OCMCRAM using
the OMAP SRAM code.

AM335x has a Cortex-M3 (WKUP_M3) which assists the MPU
in DeepSleep0 entry and exit. WKUP_M3 takes care of the
clockdomain and powerdomain transitions based on the
intended low power state. MPU needs to load the appropriate
WKUP_M3 binary onto the WKUP_M3 memory space before it can
leverage any of the PM features like DeepSleep.

The IPC mechanism between MPU and WKUP_M3 uses a mailbox
sub-module and 8 IPC registers in the Control module. MPU
uses the assigned Mailbox for issuing an interrupt to
WKUP_M3 which then goes and checks the IPC registers for
the payload. WKUP_M3 has the ability to trigger on interrupt
to MPU by executing the "sev" instruction.

In the current implementation when the suspend process
is initiated MPU interrupts the WKUP_M3 to let it know about
the intent of entering DeepSleep0 and waits for an ACK. When
the ACK is received MPU continues with its suspend process
to suspend all the drivers and then jumps to assembly in
OCMC RAM. The assembly code puts the PLLs in bypass, puts the
external RAM in self-refresh mode and then finally execute the
WFI instruction. Execution of the WFI instruction triggers another
interrupt to the WKUP_M3 which then continues wiht the power down
sequence wherein the clockdomain and powerdomain transition takes
place. As part of the sleep sequence, WKUP_M3 unmasks the interrupt
lines for the wakeup sources. WFI execution on WKUP_M3 causes the
hardware to disable the main oscillator of the SoC.

When a wakeup event occurs, WKUP_M3 starts the power-up
sequence by switching on the power domains and finally
enabling the clock to MPU. Since the MPU gets powered down
as part of the sleep sequence in the resume path ROM code
starts executing. The ROM code detects a wakeup from sleep
and then jumps to the resume location in OCMC which was
populated in one of the IPC registers as part of the suspend
sequence.

The low level code in OCMC relocks the PLLs, enables access
to external RAM and then jumps to the cpu_resume code of
the kernel to finish the resume process.

Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
Cc: Tony Lingren <tony@atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <benoit.cousson@linaro.org>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@linaro.org>
---
 arch/arm/mach-omap2/pm33xx.c  |  474 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/pm33xx.h  |   77 +++++++
 arch/arm/mach-omap2/wkup_m3.c |  183 ++++++++++++++++
 3 files changed, 734 insertions(+)
 create mode 100644 arch/arm/mach-omap2/pm33xx.c
 create mode 100644 arch/arm/mach-omap2/pm33xx.h
 create mode 100644 arch/arm/mach-omap2/wkup_m3.c

diff --git a/arch/arm/mach-omap2/pm33xx.c b/arch/arm/mach-omap2/pm33xx.c
new file mode 100644
index 0000000..d291c76
--- /dev/null
+++ b/arch/arm/mach-omap2/pm33xx.c
@@ -0,0 +1,474 @@
+/*
+ * AM33XX Power Management Routines
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Vaibhav Bedia <vaibhav.bedia@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/kernel.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/err.h>
+#include <linux/firmware.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/suspend.h>
+#include <linux/completion.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ti_emif.h>
+#include <linux/omap-mailbox.h>
+
+#include <asm/suspend.h>
+#include <asm/proc-fns.h>
+#include <asm/sizes.h>
+#include <asm/fncpy.h>
+#include <asm/system_misc.h>
+
+#include "pm.h"
+#include "cm33xx.h"
+#include "pm33xx.h"
+#include "control.h"
+#include "common.h"
+#include "clockdomain.h"
+#include "powerdomain.h"
+#include "omap_hwmod.h"
+#include "omap_device.h"
+#include "soc.h"
+#include "sram.h"
+
+static void __iomem *am33xx_emif_base;
+static struct powerdomain *cefuse_pwrdm, *gfx_pwrdm, *per_pwrdm, *mpu_pwrdm;
+static struct clockdomain *gfx_l4ls_clkdm;
+
+struct wakeup_src wakeups[] = {
+	{.irq_nr = 35,	.src = "USB0_PHY"},
+	{.irq_nr = 36,	.src = "USB1_PHY"},
+	{.irq_nr = 40,	.src = "I2C0"},
+	{.irq_nr = 41,	.src = "RTC Timer"},
+	{.irq_nr = 42,	.src = "RTC Alarm"},
+	{.irq_nr = 43,	.src = "Timer0"},
+	{.irq_nr = 44,	.src = "Timer1"},
+	{.irq_nr = 45,	.src = "UART"},
+	{.irq_nr = 46,	.src = "GPIO0"},
+	{.irq_nr = 48,	.src = "MPU_WAKE"},
+	{.irq_nr = 49,	.src = "WDT0"},
+	{.irq_nr = 50,	.src = "WDT1"},
+	{.irq_nr = 51,	.src = "ADC_TSC"},
+};
+
+struct forced_standby_module am33xx_mod[] = {
+	{.oh_name = "usb_otg_hs"},
+	{.oh_name = "tptc0"},
+	{.oh_name = "tptc1"},
+	{.oh_name = "tptc2"},
+	{.oh_name = "cpgmac0"},
+};
+
+static struct am33xx_pm_context *am33xx_pm;
+
+static DECLARE_COMPLETION(am33xx_pm_sync);
+
+static void (*am33xx_do_wfi_sram)(struct am33xx_suspend_params *);
+
+static struct am33xx_suspend_params susp_params;
+
+#ifdef CONFIG_SUSPEND
+
+static int am33xx_do_sram_idle(long unsigned int unused)
+{
+	am33xx_do_wfi_sram(&susp_params);
+	return 0;
+}
+
+static int am33xx_pm_suspend(void)
+{
+	int i, j, ret = 0;
+
+	int status = 0;
+	struct platform_device *pdev;
+	struct omap_device *od;
+
+	/*
+	 * By default the following IPs do not have MSTANDBY asserted
+	 * which is necessary for PER domain transition. If the drivers
+	 * are not compiled into the kernel HWMOD code will not change the
+	 * state of the IPs if the IP was not never enabled. To ensure
+	 * that there no issues with or without the drivers being compiled
+	 * in the kernel, we forcefully put these IPs to idle.
+	 */
+	for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++) {
+		pdev = to_platform_device(am33xx_mod[i].dev);
+		od = to_omap_device(pdev);
+		if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
+			omap_device_enable_hwmods(od);
+			omap_device_idle_hwmods(od);
+		}
+	}
+
+	/* Try to put GFX to sleep */
+	omap_set_pwrdm_state(gfx_pwrdm, PWRDM_POWER_OFF);
+	ret = cpu_suspend(0, am33xx_do_sram_idle);
+
+	status = pwrdm_read_prev_pwrst(gfx_pwrdm);
+	if (status != PWRDM_POWER_OFF)
+		pr_err("PM: GFX domain did not transition\n");
+	else
+		pr_info("PM: GFX domain entered low power state\n");
+
+	/*
+	 * BUG: GFX_L4LS clock domain needs to be woken up to
+	 * ensure thet L4LS clock domain does not get stuck in transition
+	 * If that happens L3 module does not get disabled, thereby leading
+	 * to PER power domain transition failing
+	 */
+	clkdm_wakeup(gfx_l4ls_clkdm);
+	clkdm_sleep(gfx_l4ls_clkdm);
+
+	if (ret) {
+		pr_err("PM: Kernel suspend failure\n");
+	} else {
+		i = am33xx_pm_status();
+		switch (i) {
+		case 0:
+			pr_info("PM: Successfully put all powerdomains to target state\n");
+
+			/*
+			 * The PRCM registers on AM335x do not contain previous state
+			 * information like those present on OMAP4 so we must manually
+			 * indicate transition so state counters are properly incremented
+			 */
+			pwrdm_post_transition(mpu_pwrdm);
+			pwrdm_post_transition(per_pwrdm);
+			break;
+		case 1:
+			pr_err("PM: Could not transition all powerdomains to target state\n");
+			ret = -1;
+			break;
+		default:
+			pr_err("PM: CM3 returned unknown result :(\nStatus = %d\n", i);
+			ret = -1;
+		}
+
+		/* print the wakeup reason */
+		i = am33xx_pm_wake_src();
+		for (j = 0; j < ARRAY_SIZE(wakeups); j++) {
+			if (wakeups[j].irq_nr == i) {
+				pr_info("PM: Wakeup source %s\n", wakeups[j].src);
+				break;
+			}
+		}
+
+		if (j == ARRAY_SIZE(wakeups))
+			pr_info("PM: Unknown wakeup source %d!\n", i);
+	}
+
+	return ret;
+}
+
+static int am33xx_pm_enter(suspend_state_t suspend_state)
+{
+	int ret = 0;
+
+	switch (suspend_state) {
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		ret = am33xx_pm_suspend();
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/* returns the error code from msg_send - 0 for success, failure otherwise */
+static int am33xx_ping_wkup_m3(void)
+{
+	int ret = 0;
+
+	/*
+	 * Write a dummy message to the mailbox in order to trigger the RX
+	 * interrupt to alert the M3 that data is available in the IPC
+	 * registers.
+	 */
+	ret = omap_mbox_msg_send(am33xx_pm->mbox, 0xABCDABCD);
+
+	return ret;
+}
+
+static void am33xx_m3_state_machine_reset(void)
+{
+	int i;
+
+	am33xx_pm->ipc.sleep_mode = IPC_CMD_RESET;
+
+	am33xx_pm_ipc_cmd(&am33xx_pm->ipc);
+
+	am33xx_pm->state = M3_STATE_MSG_FOR_RESET;
+
+	pr_info("PM: Sending message for resetting M3 state machine\n");
+
+	if (!am33xx_ping_wkup_m3()) {
+		i = wait_for_completion_timeout(&am33xx_pm_sync,
+					msecs_to_jiffies(500));
+		if (WARN(i == 0, "PM: MPU<->CM3 sync failure\n"))
+			am33xx_pm->state = M3_STATE_UNKNOWN;
+	} else {
+		pr_warn("PM: Unable to ping CM3\n");
+	}
+}
+
+static int am33xx_pm_begin(suspend_state_t state)
+{
+	int i;
+
+	cpu_idle_poll_ctrl(true);
+
+	am33xx_pm->ipc.sleep_mode	= IPC_CMD_DS0;
+	am33xx_pm->ipc.param1		= DS_IPC_DEFAULT;
+	am33xx_pm->ipc.param2		= DS_IPC_DEFAULT;
+
+	am33xx_pm_ipc_cmd(&am33xx_pm->ipc);
+
+	am33xx_pm->state = M3_STATE_MSG_FOR_LP;
+
+	pr_info("PM: Sending message for entering DeepSleep mode\n");
+
+	if (!am33xx_ping_wkup_m3()) {
+		i = wait_for_completion_timeout(&am33xx_pm_sync,
+					msecs_to_jiffies(500));
+		if (WARN(i == 0, "PM: MPU<->CM3 sync failure\n"))
+			return -1;
+	} else {
+		pr_warn("PM: Unable to ping CM3\n");
+	}
+
+	return 0;
+}
+
+static void am33xx_pm_end(void)
+{
+	am33xx_m3_state_machine_reset();
+
+	cpu_idle_poll_ctrl(false);
+
+	return;
+}
+
+static struct platform_suspend_ops am33xx_pm_ops = {
+	.begin		= am33xx_pm_begin,
+	.end		= am33xx_pm_end,
+	.enter		= am33xx_pm_enter,
+};
+
+/*
+ * Dummy notifier for the mailbox
+ */
+
+static int wkup_mbox_msg(struct notifier_block *self, unsigned long len,
+		void *msg)
+{
+	return 0;
+}
+
+static struct notifier_block wkup_mbox_notifier = {
+	.notifier_call = wkup_mbox_msg,
+};
+
+void am33xx_txev_handler(void)
+{
+	switch (am33xx_pm->state) {
+	case M3_STATE_RESET:
+		am33xx_pm->state = M3_STATE_INITED;
+		am33xx_pm->ver = am33xx_pm_version_get();
+		if (am33xx_pm->ver == M3_VERSION_UNKNOWN ||
+			am33xx_pm->ver < M3_BASELINE_VERSION) {
+			pr_warn("PM: CM3 Firmware Version %x not supported\n",
+						am33xx_pm->ver);
+		} else {
+			pr_info("PM: CM3 Firmware Version = 0x%x\n",
+						am33xx_pm->ver);
+			am33xx_pm_ops.valid = suspend_valid_only_mem;
+		}
+		break;
+	case M3_STATE_MSG_FOR_RESET:
+		am33xx_pm->state = M3_STATE_INITED;
+		complete(&am33xx_pm_sync);
+		break;
+	case M3_STATE_MSG_FOR_LP:
+		complete(&am33xx_pm_sync);
+		break;
+	case M3_STATE_UNKNOWN:
+		pr_warn("PM: Unknown CM3 State\n");
+	}
+
+	return;
+}
+
+static void am33xx_pm_firmware_cb(const struct firmware *fw, void *context)
+{
+	struct am33xx_pm_context *am33xx_pm = context;
+	int ret = 0;
+
+	/* no firmware found */
+	if (!fw) {
+		pr_err("PM: request_firmware failed\n");
+		return;
+	}
+
+	wkup_m3_copy_code(fw->data, fw->size);
+
+	wkup_m3_register_txev_handler(am33xx_txev_handler);
+
+	pr_info("PM: Copied the M3 firmware to UMEM\n");
+
+	/*
+	 * Invalidate M3 firmware version before hardreset.
+	 * Write invalid version in lower 4 nibbles of parameter
+	 * register (ipc_regs + 0x8).
+	 */
+	am33xx_pm_version_clear();
+
+	am33xx_pm->state = M3_STATE_RESET;
+
+	ret = wkup_m3_prepare();
+	if (ret) {
+		pr_err("PM: Could not prepare WKUP_M3\n");
+		return;
+	}
+
+	/* Physical resume address to be used by ROM code */
+	am33xx_pm->ipc.resume_addr = (AM33XX_OCMC_END -
+		am33xx_do_wfi_sz + am33xx_resume_offset + 0x4);
+
+	am33xx_pm->mbox = omap_mbox_get("wkup_m3", &wkup_mbox_notifier);
+
+	if (IS_ERR(am33xx_pm->mbox)) {
+		ret = -EBUSY;
+		pr_err("PM: IPC Request for A8->M3 Channel failed!\n");
+		return;
+	} else {
+		suspend_set_ops(&am33xx_pm_ops);
+	}
+
+	return;
+}
+
+#endif /* CONFIG_SUSPEND */
+
+/*
+ * Push the minimal suspend-resume code to SRAM
+ */
+void am33xx_push_sram_idle(void)
+{
+	am33xx_do_wfi_sram = (void *)omap_sram_push
+					(am33xx_do_wfi, am33xx_do_wfi_sz);
+}
+
+static int __init am33xx_map_emif(void)
+{
+	am33xx_emif_base = ioremap(AM33XX_EMIF_BASE, SZ_32K);
+
+	if (!am33xx_emif_base)
+		return -ENOMEM;
+
+	return 0;
+}
+
+int __init am33xx_pm_init(void)
+{
+	int ret;
+	u32 temp;
+	struct device_node *np;
+	int i;
+
+	if (!soc_is_am33xx())
+		return -ENODEV;
+
+	pr_info("Power Management for AM33XX family\n");
+
+	/*
+	 * By default the following IPs do not have MSTANDBY asserted
+	 * which is necessary for PER domain transition. If the drivers
+	 * are not compiled into the kernel HWMOD code will not change the
+	 * state of the IPs if the IP was not never enabled
+	 */
+	for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++)
+		am33xx_mod[i].dev = omap_device_get_by_hwmod_name(am33xx_mod[i].oh_name);
+
+	gfx_pwrdm = pwrdm_lookup("gfx_pwrdm");
+	per_pwrdm = pwrdm_lookup("per_pwrdm");
+	mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
+
+	gfx_l4ls_clkdm = clkdm_lookup("gfx_l4ls_gfx_clkdm");
+
+	if ((!gfx_pwrdm) || (!per_pwrdm) || (!mpu_pwrdm) || (!gfx_l4ls_clkdm)) {
+		ret = -ENODEV;
+		goto err;
+	}
+
+	am33xx_pm = kzalloc(sizeof(*am33xx_pm), GFP_KERNEL);
+	if (!am33xx_pm) {
+		pr_err("Memory allocation failed\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	ret = am33xx_map_emif();
+	if (ret) {
+		pr_err("PM: Could not ioremap EMIF\n");
+		goto err;
+	}
+	/* Determine Memory Type */
+	temp = readl(am33xx_emif_base + EMIF_SDRAM_CONFIG);
+	temp = (temp & SDRAM_TYPE_MASK) >> SDRAM_TYPE_SHIFT;
+	/* Parameters to pass to aseembly code */
+	susp_params.emif_addr_virt = am33xx_emif_base;
+	susp_params.dram_sync = am33xx_dram_sync;
+	susp_params.mem_type = temp;
+	am33xx_pm->ipc.param3 = temp;
+
+	np = of_find_compatible_node(NULL, NULL, "ti,am3353-wkup-m3");
+	if (np) {
+		if (of_find_property(np, "ti,needs_vtt_toggle", NULL) &&
+		    (!(of_property_read_u32(np, "vtt-gpio-pin",
+							&temp)))) {
+			if (temp >= 0 && temp <= 31)
+				am33xx_pm->ipc.param3 |=
+					((1 << VTT_STAT_SHIFT) |
+					(temp << VTT_GPIO_PIN_SHIFT));
+		}
+	}
+
+	(void) clkdm_for_each(omap_pm_clkdms_setup, NULL);
+
+	/* CEFUSE domain can be turned off post bootup */
+	cefuse_pwrdm = pwrdm_lookup("cefuse_pwrdm");
+	if (cefuse_pwrdm)
+		omap_set_pwrdm_state(cefuse_pwrdm, PWRDM_POWER_OFF);
+	else
+		pr_err("PM: Failed to get cefuse_pwrdm\n");
+
+#ifdef CONFIG_SUSPEND
+	pr_info("PM: Trying to load am335x-pm-firmware.bin");
+
+	/* We don't want to delay boot */
+	request_firmware_nowait(THIS_MODULE, 0, "am335x-pm-firmware.bin",
+				NULL, GFP_KERNEL, am33xx_pm,
+				am33xx_pm_firmware_cb);
+#endif /* CONFIG_SUSPEND */
+
+err:
+	return ret;
+}
diff --git a/arch/arm/mach-omap2/pm33xx.h b/arch/arm/mach-omap2/pm33xx.h
new file mode 100644
index 0000000..befdd11
--- /dev/null
+++ b/arch/arm/mach-omap2/pm33xx.h
@@ -0,0 +1,77 @@
+/*
+ * AM33XX Power Management Routines
+ *
+ * Copyright (C) 2012 Texas Instruments Inc.
+ * Vaibhav Bedia <vaibhav.bedia@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.
+ */
+#ifndef __ARCH_ARM_MACH_OMAP2_PM33XX_H
+#define __ARCH_ARM_MACH_OMAP2_PM33XX_H
+
+#include "control.h"
+
+#ifndef __ASSEMBLER__
+
+struct am33xx_pm_context {
+	struct am33xx_ipc_data	ipc;
+	struct firmware		*firmware;
+	struct omap_mbox	*mbox;
+	u8			state;
+	u32			ver;
+};
+
+/*
+ * Params passed to suspend routine
+ *
+ * Since these are used to load into registers by suspend code,
+ * entries here must always be in sync with the suspend code
+ * in arm/mach-omap2/sleep33xx.S
+ */
+struct am33xx_suspend_params {
+	void __iomem *emif_addr_virt;
+	u32 mem_type;
+	void __iomem *dram_sync;
+};
+
+struct wakeup_src {
+	int irq_nr;
+	char src[10];
+};
+
+struct forced_standby_module {
+	char oh_name[15];
+	struct device *dev;
+};
+
+int wkup_m3_copy_code(const u8 *data, size_t size);
+int wkup_m3_prepare(void);
+void wkup_m3_register_txev_handler(void (*txev_handler)(void));
+
+#endif
+
+#define	IPC_CMD_DS0			0x3
+#define IPC_CMD_RESET                   0xe
+#define DS_IPC_DEFAULT			0xffffffff
+#define M3_VERSION_UNKNOWN		0x0000ffff
+#define M3_BASELINE_VERSION		0x21
+
+#define M3_STATE_UNKNOWN		0
+#define M3_STATE_RESET			1
+#define M3_STATE_INITED			2
+#define M3_STATE_MSG_FOR_LP		3
+#define M3_STATE_MSG_FOR_RESET		4
+
+#define AM33XX_OCMC_END			0x40310000
+#define AM33XX_EMIF_BASE		0x4C000000
+
+#define MEM_TYPE_DDR2		2
+
+#endif
diff --git a/arch/arm/mach-omap2/wkup_m3.c b/arch/arm/mach-omap2/wkup_m3.c
new file mode 100644
index 0000000..8eaa7f3
--- /dev/null
+++ b/arch/arm/mach-omap2/wkup_m3.c
@@ -0,0 +1,183 @@
+/*
+ * AM33XX Power Management Routines
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Vaibhav Bedia <vaibhav.bedia@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/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/cpu.h>
+#include <linux/err.h>
+#include <linux/firmware.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+
+#include "pm33xx.h"
+#include "control.h"
+#include "omap_device.h"
+#include "soc.h"
+
+struct wkup_m3_context {
+	struct device	*dev;
+	void __iomem	*code;
+	void (*txev_handler)(void);
+};
+
+struct wkup_m3_context *wkup_m3;
+
+int wkup_m3_copy_code(const u8 *data, size_t size)
+{
+	if (size > SZ_16K)
+		return -ENOMEM;
+
+	memcpy_toio(wkup_m3->code, data, size);
+
+	return 0;
+}
+
+
+void wkup_m3_register_txev_handler(void (*txev_handler)(void))
+{
+	wkup_m3->txev_handler = txev_handler;
+}
+
+/* have platforms do what they want in atomic context over here? */
+static irqreturn_t wkup_m3_txev_handler(int irq, void *unused)
+{
+	am33xx_txev_eoi();
+
+	/* callback to be executed in atomic context */
+	/* return 0 implies IRQ_HANDLED else IRQ_NONE */
+	wkup_m3->txev_handler();
+
+	am33xx_txev_enable();
+
+	return IRQ_HANDLED;
+}
+
+int wkup_m3_prepare(void)
+{
+	struct platform_device *pdev = to_platform_device(wkup_m3->dev);
+
+	/* check that the code is loaded */
+	omap_device_deassert_hardreset(pdev, "wkup_m3");
+
+	return 0;
+}
+
+static int wkup_m3_probe(struct platform_device *pdev)
+{
+	int irq, ret = 0;
+	struct resource *mem;
+
+	pm_runtime_enable(&pdev->dev);
+
+	ret = pm_runtime_get_sync(&pdev->dev);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
+		return ret;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (!irq) {
+		dev_err(wkup_m3->dev, "no irq resource\n");
+		ret = -ENXIO;
+		goto err;
+	}
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(wkup_m3->dev, "no memory resource\n");
+		ret = -ENXIO;
+		goto err;
+	}
+
+	wkup_m3 = kzalloc(sizeof(*wkup_m3), GFP_KERNEL);
+	if (!wkup_m3) {
+		pr_err("Memory allocation failed\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	wkup_m3->dev = &pdev->dev;
+
+	wkup_m3->code = devm_request_and_ioremap(wkup_m3->dev, mem);
+	if (!wkup_m3->code) {
+		dev_err(wkup_m3->dev, "could not ioremap\n");
+		ret = -EADDRNOTAVAIL;
+		goto err;
+	}
+
+	ret = devm_request_irq(wkup_m3->dev, irq, wkup_m3_txev_handler,
+		  IRQF_DISABLED, "wkup_m3_txev", NULL);
+	if (ret) {
+		dev_err(wkup_m3->dev, "request_irq failed\n");
+		goto err;
+	}
+
+err:
+	return ret;
+}
+
+static int wkup_m3_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct of_device_id wkup_m3_dt_ids[] = {
+	{ .compatible = "ti,am3353-wkup-m3" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, wkup_m3_dt_ids);
+
+static int wkup_m3_rpm_suspend(struct device *dev)
+{
+	return -EBUSY;
+}
+
+static int wkup_m3_rpm_resume(struct device *dev)
+{
+	return 0;
+}
+
+static const struct dev_pm_ops wkup_m3_ops = {
+	SET_RUNTIME_PM_OPS(wkup_m3_rpm_suspend, wkup_m3_rpm_resume, NULL)
+};
+
+static struct platform_driver wkup_m3_driver = {
+	.probe		= wkup_m3_probe,
+	.remove		= wkup_m3_remove,
+	.driver		= {
+		.name	= "wkup_m3",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(wkup_m3_dt_ids),
+		.pm	= &wkup_m3_ops,
+	},
+};
+
+static __init int wkup_m3_init(void)
+{
+	return platform_driver_register(&wkup_m3_driver);
+}
+
+static __exit void wkup_m3_exit(void)
+{
+	platform_driver_unregister(&wkup_m3_driver);
+}
+omap_postcore_initcall(wkup_m3_init);
+module_exit(wkup_m3_exit);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-06 17:49   ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel

From: Vaibhav Bedia <vaibhav.bedia@ti.com>

AM335x supports various low power modes as documented
in section 8.1.4.3 of the AM335x TRM which is available
@ http://www.ti.com/litv/pdf/spruh73f

DeepSleep0 mode offers the lowest power mode with limited
wakeup sources without a system reboot and is mapped as
the suspend state in the kernel. In this state, MPU and
PER domains are turned off with the internal RAM held in
retention to facilitate resume process. As part of the boot
process, the assembly code is copied over to OCMCRAM using
the OMAP SRAM code.

AM335x has a Cortex-M3 (WKUP_M3) which assists the MPU
in DeepSleep0 entry and exit. WKUP_M3 takes care of the
clockdomain and powerdomain transitions based on the
intended low power state. MPU needs to load the appropriate
WKUP_M3 binary onto the WKUP_M3 memory space before it can
leverage any of the PM features like DeepSleep.

The IPC mechanism between MPU and WKUP_M3 uses a mailbox
sub-module and 8 IPC registers in the Control module. MPU
uses the assigned Mailbox for issuing an interrupt to
WKUP_M3 which then goes and checks the IPC registers for
the payload. WKUP_M3 has the ability to trigger on interrupt
to MPU by executing the "sev" instruction.

In the current implementation when the suspend process
is initiated MPU interrupts the WKUP_M3 to let it know about
the intent of entering DeepSleep0 and waits for an ACK. When
the ACK is received MPU continues with its suspend process
to suspend all the drivers and then jumps to assembly in
OCMC RAM. The assembly code puts the PLLs in bypass, puts the
external RAM in self-refresh mode and then finally execute the
WFI instruction. Execution of the WFI instruction triggers another
interrupt to the WKUP_M3 which then continues wiht the power down
sequence wherein the clockdomain and powerdomain transition takes
place. As part of the sleep sequence, WKUP_M3 unmasks the interrupt
lines for the wakeup sources. WFI execution on WKUP_M3 causes the
hardware to disable the main oscillator of the SoC.

When a wakeup event occurs, WKUP_M3 starts the power-up
sequence by switching on the power domains and finally
enabling the clock to MPU. Since the MPU gets powered down
as part of the sleep sequence in the resume path ROM code
starts executing. The ROM code detects a wakeup from sleep
and then jumps to the resume location in OCMC which was
populated in one of the IPC registers as part of the suspend
sequence.

The low level code in OCMC relocks the PLLs, enables access
to external RAM and then jumps to the cpu_resume code of
the kernel to finish the resume process.

Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
Cc: Tony Lingren <tony@atomide.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <benoit.cousson@linaro.org>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@linaro.org>
---
 arch/arm/mach-omap2/pm33xx.c  |  474 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/pm33xx.h  |   77 +++++++
 arch/arm/mach-omap2/wkup_m3.c |  183 ++++++++++++++++
 3 files changed, 734 insertions(+)
 create mode 100644 arch/arm/mach-omap2/pm33xx.c
 create mode 100644 arch/arm/mach-omap2/pm33xx.h
 create mode 100644 arch/arm/mach-omap2/wkup_m3.c

diff --git a/arch/arm/mach-omap2/pm33xx.c b/arch/arm/mach-omap2/pm33xx.c
new file mode 100644
index 0000000..d291c76
--- /dev/null
+++ b/arch/arm/mach-omap2/pm33xx.c
@@ -0,0 +1,474 @@
+/*
+ * AM33XX Power Management Routines
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Vaibhav Bedia <vaibhav.bedia@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/kernel.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/err.h>
+#include <linux/firmware.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/suspend.h>
+#include <linux/completion.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ti_emif.h>
+#include <linux/omap-mailbox.h>
+
+#include <asm/suspend.h>
+#include <asm/proc-fns.h>
+#include <asm/sizes.h>
+#include <asm/fncpy.h>
+#include <asm/system_misc.h>
+
+#include "pm.h"
+#include "cm33xx.h"
+#include "pm33xx.h"
+#include "control.h"
+#include "common.h"
+#include "clockdomain.h"
+#include "powerdomain.h"
+#include "omap_hwmod.h"
+#include "omap_device.h"
+#include "soc.h"
+#include "sram.h"
+
+static void __iomem *am33xx_emif_base;
+static struct powerdomain *cefuse_pwrdm, *gfx_pwrdm, *per_pwrdm, *mpu_pwrdm;
+static struct clockdomain *gfx_l4ls_clkdm;
+
+struct wakeup_src wakeups[] = {
+	{.irq_nr = 35,	.src = "USB0_PHY"},
+	{.irq_nr = 36,	.src = "USB1_PHY"},
+	{.irq_nr = 40,	.src = "I2C0"},
+	{.irq_nr = 41,	.src = "RTC Timer"},
+	{.irq_nr = 42,	.src = "RTC Alarm"},
+	{.irq_nr = 43,	.src = "Timer0"},
+	{.irq_nr = 44,	.src = "Timer1"},
+	{.irq_nr = 45,	.src = "UART"},
+	{.irq_nr = 46,	.src = "GPIO0"},
+	{.irq_nr = 48,	.src = "MPU_WAKE"},
+	{.irq_nr = 49,	.src = "WDT0"},
+	{.irq_nr = 50,	.src = "WDT1"},
+	{.irq_nr = 51,	.src = "ADC_TSC"},
+};
+
+struct forced_standby_module am33xx_mod[] = {
+	{.oh_name = "usb_otg_hs"},
+	{.oh_name = "tptc0"},
+	{.oh_name = "tptc1"},
+	{.oh_name = "tptc2"},
+	{.oh_name = "cpgmac0"},
+};
+
+static struct am33xx_pm_context *am33xx_pm;
+
+static DECLARE_COMPLETION(am33xx_pm_sync);
+
+static void (*am33xx_do_wfi_sram)(struct am33xx_suspend_params *);
+
+static struct am33xx_suspend_params susp_params;
+
+#ifdef CONFIG_SUSPEND
+
+static int am33xx_do_sram_idle(long unsigned int unused)
+{
+	am33xx_do_wfi_sram(&susp_params);
+	return 0;
+}
+
+static int am33xx_pm_suspend(void)
+{
+	int i, j, ret = 0;
+
+	int status = 0;
+	struct platform_device *pdev;
+	struct omap_device *od;
+
+	/*
+	 * By default the following IPs do not have MSTANDBY asserted
+	 * which is necessary for PER domain transition. If the drivers
+	 * are not compiled into the kernel HWMOD code will not change the
+	 * state of the IPs if the IP was not never enabled. To ensure
+	 * that there no issues with or without the drivers being compiled
+	 * in the kernel, we forcefully put these IPs to idle.
+	 */
+	for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++) {
+		pdev = to_platform_device(am33xx_mod[i].dev);
+		od = to_omap_device(pdev);
+		if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
+			omap_device_enable_hwmods(od);
+			omap_device_idle_hwmods(od);
+		}
+	}
+
+	/* Try to put GFX to sleep */
+	omap_set_pwrdm_state(gfx_pwrdm, PWRDM_POWER_OFF);
+	ret = cpu_suspend(0, am33xx_do_sram_idle);
+
+	status = pwrdm_read_prev_pwrst(gfx_pwrdm);
+	if (status != PWRDM_POWER_OFF)
+		pr_err("PM: GFX domain did not transition\n");
+	else
+		pr_info("PM: GFX domain entered low power state\n");
+
+	/*
+	 * BUG: GFX_L4LS clock domain needs to be woken up to
+	 * ensure thet L4LS clock domain does not get stuck in transition
+	 * If that happens L3 module does not get disabled, thereby leading
+	 * to PER power domain transition failing
+	 */
+	clkdm_wakeup(gfx_l4ls_clkdm);
+	clkdm_sleep(gfx_l4ls_clkdm);
+
+	if (ret) {
+		pr_err("PM: Kernel suspend failure\n");
+	} else {
+		i = am33xx_pm_status();
+		switch (i) {
+		case 0:
+			pr_info("PM: Successfully put all powerdomains to target state\n");
+
+			/*
+			 * The PRCM registers on AM335x do not contain previous state
+			 * information like those present on OMAP4 so we must manually
+			 * indicate transition so state counters are properly incremented
+			 */
+			pwrdm_post_transition(mpu_pwrdm);
+			pwrdm_post_transition(per_pwrdm);
+			break;
+		case 1:
+			pr_err("PM: Could not transition all powerdomains to target state\n");
+			ret = -1;
+			break;
+		default:
+			pr_err("PM: CM3 returned unknown result :(\nStatus = %d\n", i);
+			ret = -1;
+		}
+
+		/* print the wakeup reason */
+		i = am33xx_pm_wake_src();
+		for (j = 0; j < ARRAY_SIZE(wakeups); j++) {
+			if (wakeups[j].irq_nr == i) {
+				pr_info("PM: Wakeup source %s\n", wakeups[j].src);
+				break;
+			}
+		}
+
+		if (j == ARRAY_SIZE(wakeups))
+			pr_info("PM: Unknown wakeup source %d!\n", i);
+	}
+
+	return ret;
+}
+
+static int am33xx_pm_enter(suspend_state_t suspend_state)
+{
+	int ret = 0;
+
+	switch (suspend_state) {
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		ret = am33xx_pm_suspend();
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/* returns the error code from msg_send - 0 for success, failure otherwise */
+static int am33xx_ping_wkup_m3(void)
+{
+	int ret = 0;
+
+	/*
+	 * Write a dummy message to the mailbox in order to trigger the RX
+	 * interrupt to alert the M3 that data is available in the IPC
+	 * registers.
+	 */
+	ret = omap_mbox_msg_send(am33xx_pm->mbox, 0xABCDABCD);
+
+	return ret;
+}
+
+static void am33xx_m3_state_machine_reset(void)
+{
+	int i;
+
+	am33xx_pm->ipc.sleep_mode = IPC_CMD_RESET;
+
+	am33xx_pm_ipc_cmd(&am33xx_pm->ipc);
+
+	am33xx_pm->state = M3_STATE_MSG_FOR_RESET;
+
+	pr_info("PM: Sending message for resetting M3 state machine\n");
+
+	if (!am33xx_ping_wkup_m3()) {
+		i = wait_for_completion_timeout(&am33xx_pm_sync,
+					msecs_to_jiffies(500));
+		if (WARN(i == 0, "PM: MPU<->CM3 sync failure\n"))
+			am33xx_pm->state = M3_STATE_UNKNOWN;
+	} else {
+		pr_warn("PM: Unable to ping CM3\n");
+	}
+}
+
+static int am33xx_pm_begin(suspend_state_t state)
+{
+	int i;
+
+	cpu_idle_poll_ctrl(true);
+
+	am33xx_pm->ipc.sleep_mode	= IPC_CMD_DS0;
+	am33xx_pm->ipc.param1		= DS_IPC_DEFAULT;
+	am33xx_pm->ipc.param2		= DS_IPC_DEFAULT;
+
+	am33xx_pm_ipc_cmd(&am33xx_pm->ipc);
+
+	am33xx_pm->state = M3_STATE_MSG_FOR_LP;
+
+	pr_info("PM: Sending message for entering DeepSleep mode\n");
+
+	if (!am33xx_ping_wkup_m3()) {
+		i = wait_for_completion_timeout(&am33xx_pm_sync,
+					msecs_to_jiffies(500));
+		if (WARN(i == 0, "PM: MPU<->CM3 sync failure\n"))
+			return -1;
+	} else {
+		pr_warn("PM: Unable to ping CM3\n");
+	}
+
+	return 0;
+}
+
+static void am33xx_pm_end(void)
+{
+	am33xx_m3_state_machine_reset();
+
+	cpu_idle_poll_ctrl(false);
+
+	return;
+}
+
+static struct platform_suspend_ops am33xx_pm_ops = {
+	.begin		= am33xx_pm_begin,
+	.end		= am33xx_pm_end,
+	.enter		= am33xx_pm_enter,
+};
+
+/*
+ * Dummy notifier for the mailbox
+ */
+
+static int wkup_mbox_msg(struct notifier_block *self, unsigned long len,
+		void *msg)
+{
+	return 0;
+}
+
+static struct notifier_block wkup_mbox_notifier = {
+	.notifier_call = wkup_mbox_msg,
+};
+
+void am33xx_txev_handler(void)
+{
+	switch (am33xx_pm->state) {
+	case M3_STATE_RESET:
+		am33xx_pm->state = M3_STATE_INITED;
+		am33xx_pm->ver = am33xx_pm_version_get();
+		if (am33xx_pm->ver == M3_VERSION_UNKNOWN ||
+			am33xx_pm->ver < M3_BASELINE_VERSION) {
+			pr_warn("PM: CM3 Firmware Version %x not supported\n",
+						am33xx_pm->ver);
+		} else {
+			pr_info("PM: CM3 Firmware Version = 0x%x\n",
+						am33xx_pm->ver);
+			am33xx_pm_ops.valid = suspend_valid_only_mem;
+		}
+		break;
+	case M3_STATE_MSG_FOR_RESET:
+		am33xx_pm->state = M3_STATE_INITED;
+		complete(&am33xx_pm_sync);
+		break;
+	case M3_STATE_MSG_FOR_LP:
+		complete(&am33xx_pm_sync);
+		break;
+	case M3_STATE_UNKNOWN:
+		pr_warn("PM: Unknown CM3 State\n");
+	}
+
+	return;
+}
+
+static void am33xx_pm_firmware_cb(const struct firmware *fw, void *context)
+{
+	struct am33xx_pm_context *am33xx_pm = context;
+	int ret = 0;
+
+	/* no firmware found */
+	if (!fw) {
+		pr_err("PM: request_firmware failed\n");
+		return;
+	}
+
+	wkup_m3_copy_code(fw->data, fw->size);
+
+	wkup_m3_register_txev_handler(am33xx_txev_handler);
+
+	pr_info("PM: Copied the M3 firmware to UMEM\n");
+
+	/*
+	 * Invalidate M3 firmware version before hardreset.
+	 * Write invalid version in lower 4 nibbles of parameter
+	 * register (ipc_regs + 0x8).
+	 */
+	am33xx_pm_version_clear();
+
+	am33xx_pm->state = M3_STATE_RESET;
+
+	ret = wkup_m3_prepare();
+	if (ret) {
+		pr_err("PM: Could not prepare WKUP_M3\n");
+		return;
+	}
+
+	/* Physical resume address to be used by ROM code */
+	am33xx_pm->ipc.resume_addr = (AM33XX_OCMC_END -
+		am33xx_do_wfi_sz + am33xx_resume_offset + 0x4);
+
+	am33xx_pm->mbox = omap_mbox_get("wkup_m3", &wkup_mbox_notifier);
+
+	if (IS_ERR(am33xx_pm->mbox)) {
+		ret = -EBUSY;
+		pr_err("PM: IPC Request for A8->M3 Channel failed!\n");
+		return;
+	} else {
+		suspend_set_ops(&am33xx_pm_ops);
+	}
+
+	return;
+}
+
+#endif /* CONFIG_SUSPEND */
+
+/*
+ * Push the minimal suspend-resume code to SRAM
+ */
+void am33xx_push_sram_idle(void)
+{
+	am33xx_do_wfi_sram = (void *)omap_sram_push
+					(am33xx_do_wfi, am33xx_do_wfi_sz);
+}
+
+static int __init am33xx_map_emif(void)
+{
+	am33xx_emif_base = ioremap(AM33XX_EMIF_BASE, SZ_32K);
+
+	if (!am33xx_emif_base)
+		return -ENOMEM;
+
+	return 0;
+}
+
+int __init am33xx_pm_init(void)
+{
+	int ret;
+	u32 temp;
+	struct device_node *np;
+	int i;
+
+	if (!soc_is_am33xx())
+		return -ENODEV;
+
+	pr_info("Power Management for AM33XX family\n");
+
+	/*
+	 * By default the following IPs do not have MSTANDBY asserted
+	 * which is necessary for PER domain transition. If the drivers
+	 * are not compiled into the kernel HWMOD code will not change the
+	 * state of the IPs if the IP was not never enabled
+	 */
+	for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++)
+		am33xx_mod[i].dev = omap_device_get_by_hwmod_name(am33xx_mod[i].oh_name);
+
+	gfx_pwrdm = pwrdm_lookup("gfx_pwrdm");
+	per_pwrdm = pwrdm_lookup("per_pwrdm");
+	mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
+
+	gfx_l4ls_clkdm = clkdm_lookup("gfx_l4ls_gfx_clkdm");
+
+	if ((!gfx_pwrdm) || (!per_pwrdm) || (!mpu_pwrdm) || (!gfx_l4ls_clkdm)) {
+		ret = -ENODEV;
+		goto err;
+	}
+
+	am33xx_pm = kzalloc(sizeof(*am33xx_pm), GFP_KERNEL);
+	if (!am33xx_pm) {
+		pr_err("Memory allocation failed\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	ret = am33xx_map_emif();
+	if (ret) {
+		pr_err("PM: Could not ioremap EMIF\n");
+		goto err;
+	}
+	/* Determine Memory Type */
+	temp = readl(am33xx_emif_base + EMIF_SDRAM_CONFIG);
+	temp = (temp & SDRAM_TYPE_MASK) >> SDRAM_TYPE_SHIFT;
+	/* Parameters to pass to aseembly code */
+	susp_params.emif_addr_virt = am33xx_emif_base;
+	susp_params.dram_sync = am33xx_dram_sync;
+	susp_params.mem_type = temp;
+	am33xx_pm->ipc.param3 = temp;
+
+	np = of_find_compatible_node(NULL, NULL, "ti,am3353-wkup-m3");
+	if (np) {
+		if (of_find_property(np, "ti,needs_vtt_toggle", NULL) &&
+		    (!(of_property_read_u32(np, "vtt-gpio-pin",
+							&temp)))) {
+			if (temp >= 0 && temp <= 31)
+				am33xx_pm->ipc.param3 |=
+					((1 << VTT_STAT_SHIFT) |
+					(temp << VTT_GPIO_PIN_SHIFT));
+		}
+	}
+
+	(void) clkdm_for_each(omap_pm_clkdms_setup, NULL);
+
+	/* CEFUSE domain can be turned off post bootup */
+	cefuse_pwrdm = pwrdm_lookup("cefuse_pwrdm");
+	if (cefuse_pwrdm)
+		omap_set_pwrdm_state(cefuse_pwrdm, PWRDM_POWER_OFF);
+	else
+		pr_err("PM: Failed to get cefuse_pwrdm\n");
+
+#ifdef CONFIG_SUSPEND
+	pr_info("PM: Trying to load am335x-pm-firmware.bin");
+
+	/* We don't want to delay boot */
+	request_firmware_nowait(THIS_MODULE, 0, "am335x-pm-firmware.bin",
+				NULL, GFP_KERNEL, am33xx_pm,
+				am33xx_pm_firmware_cb);
+#endif /* CONFIG_SUSPEND */
+
+err:
+	return ret;
+}
diff --git a/arch/arm/mach-omap2/pm33xx.h b/arch/arm/mach-omap2/pm33xx.h
new file mode 100644
index 0000000..befdd11
--- /dev/null
+++ b/arch/arm/mach-omap2/pm33xx.h
@@ -0,0 +1,77 @@
+/*
+ * AM33XX Power Management Routines
+ *
+ * Copyright (C) 2012 Texas Instruments Inc.
+ * Vaibhav Bedia <vaibhav.bedia@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.
+ */
+#ifndef __ARCH_ARM_MACH_OMAP2_PM33XX_H
+#define __ARCH_ARM_MACH_OMAP2_PM33XX_H
+
+#include "control.h"
+
+#ifndef __ASSEMBLER__
+
+struct am33xx_pm_context {
+	struct am33xx_ipc_data	ipc;
+	struct firmware		*firmware;
+	struct omap_mbox	*mbox;
+	u8			state;
+	u32			ver;
+};
+
+/*
+ * Params passed to suspend routine
+ *
+ * Since these are used to load into registers by suspend code,
+ * entries here must always be in sync with the suspend code
+ * in arm/mach-omap2/sleep33xx.S
+ */
+struct am33xx_suspend_params {
+	void __iomem *emif_addr_virt;
+	u32 mem_type;
+	void __iomem *dram_sync;
+};
+
+struct wakeup_src {
+	int irq_nr;
+	char src[10];
+};
+
+struct forced_standby_module {
+	char oh_name[15];
+	struct device *dev;
+};
+
+int wkup_m3_copy_code(const u8 *data, size_t size);
+int wkup_m3_prepare(void);
+void wkup_m3_register_txev_handler(void (*txev_handler)(void));
+
+#endif
+
+#define	IPC_CMD_DS0			0x3
+#define IPC_CMD_RESET                   0xe
+#define DS_IPC_DEFAULT			0xffffffff
+#define M3_VERSION_UNKNOWN		0x0000ffff
+#define M3_BASELINE_VERSION		0x21
+
+#define M3_STATE_UNKNOWN		0
+#define M3_STATE_RESET			1
+#define M3_STATE_INITED			2
+#define M3_STATE_MSG_FOR_LP		3
+#define M3_STATE_MSG_FOR_RESET		4
+
+#define AM33XX_OCMC_END			0x40310000
+#define AM33XX_EMIF_BASE		0x4C000000
+
+#define MEM_TYPE_DDR2		2
+
+#endif
diff --git a/arch/arm/mach-omap2/wkup_m3.c b/arch/arm/mach-omap2/wkup_m3.c
new file mode 100644
index 0000000..8eaa7f3
--- /dev/null
+++ b/arch/arm/mach-omap2/wkup_m3.c
@@ -0,0 +1,183 @@
+/*
+ * AM33XX Power Management Routines
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Vaibhav Bedia <vaibhav.bedia@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/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/cpu.h>
+#include <linux/err.h>
+#include <linux/firmware.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+
+#include "pm33xx.h"
+#include "control.h"
+#include "omap_device.h"
+#include "soc.h"
+
+struct wkup_m3_context {
+	struct device	*dev;
+	void __iomem	*code;
+	void (*txev_handler)(void);
+};
+
+struct wkup_m3_context *wkup_m3;
+
+int wkup_m3_copy_code(const u8 *data, size_t size)
+{
+	if (size > SZ_16K)
+		return -ENOMEM;
+
+	memcpy_toio(wkup_m3->code, data, size);
+
+	return 0;
+}
+
+
+void wkup_m3_register_txev_handler(void (*txev_handler)(void))
+{
+	wkup_m3->txev_handler = txev_handler;
+}
+
+/* have platforms do what they want in atomic context over here? */
+static irqreturn_t wkup_m3_txev_handler(int irq, void *unused)
+{
+	am33xx_txev_eoi();
+
+	/* callback to be executed in atomic context */
+	/* return 0 implies IRQ_HANDLED else IRQ_NONE */
+	wkup_m3->txev_handler();
+
+	am33xx_txev_enable();
+
+	return IRQ_HANDLED;
+}
+
+int wkup_m3_prepare(void)
+{
+	struct platform_device *pdev = to_platform_device(wkup_m3->dev);
+
+	/* check that the code is loaded */
+	omap_device_deassert_hardreset(pdev, "wkup_m3");
+
+	return 0;
+}
+
+static int wkup_m3_probe(struct platform_device *pdev)
+{
+	int irq, ret = 0;
+	struct resource *mem;
+
+	pm_runtime_enable(&pdev->dev);
+
+	ret = pm_runtime_get_sync(&pdev->dev);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
+		return ret;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (!irq) {
+		dev_err(wkup_m3->dev, "no irq resource\n");
+		ret = -ENXIO;
+		goto err;
+	}
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(wkup_m3->dev, "no memory resource\n");
+		ret = -ENXIO;
+		goto err;
+	}
+
+	wkup_m3 = kzalloc(sizeof(*wkup_m3), GFP_KERNEL);
+	if (!wkup_m3) {
+		pr_err("Memory allocation failed\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	wkup_m3->dev = &pdev->dev;
+
+	wkup_m3->code = devm_request_and_ioremap(wkup_m3->dev, mem);
+	if (!wkup_m3->code) {
+		dev_err(wkup_m3->dev, "could not ioremap\n");
+		ret = -EADDRNOTAVAIL;
+		goto err;
+	}
+
+	ret = devm_request_irq(wkup_m3->dev, irq, wkup_m3_txev_handler,
+		  IRQF_DISABLED, "wkup_m3_txev", NULL);
+	if (ret) {
+		dev_err(wkup_m3->dev, "request_irq failed\n");
+		goto err;
+	}
+
+err:
+	return ret;
+}
+
+static int wkup_m3_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct of_device_id wkup_m3_dt_ids[] = {
+	{ .compatible = "ti,am3353-wkup-m3" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, wkup_m3_dt_ids);
+
+static int wkup_m3_rpm_suspend(struct device *dev)
+{
+	return -EBUSY;
+}
+
+static int wkup_m3_rpm_resume(struct device *dev)
+{
+	return 0;
+}
+
+static const struct dev_pm_ops wkup_m3_ops = {
+	SET_RUNTIME_PM_OPS(wkup_m3_rpm_suspend, wkup_m3_rpm_resume, NULL)
+};
+
+static struct platform_driver wkup_m3_driver = {
+	.probe		= wkup_m3_probe,
+	.remove		= wkup_m3_remove,
+	.driver		= {
+		.name	= "wkup_m3",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(wkup_m3_dt_ids),
+		.pm	= &wkup_m3_ops,
+	},
+};
+
+static __init int wkup_m3_init(void)
+{
+	return platform_driver_register(&wkup_m3_driver);
+}
+
+static __exit void wkup_m3_exit(void)
+{
+	platform_driver_unregister(&wkup_m3_driver);
+}
+omap_postcore_initcall(wkup_m3_init);
+module_exit(wkup_m3_exit);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 212+ messages in thread

* [PATCHv3 9/9] ARM: OMAP2+: AM33XX: Hookup AM33XX PM code into OMAP builds
  2013-08-06 17:49 ` Dave Gerlach
@ 2013-08-06 17:49   ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel, linux-omap
  Cc: Paul Walmsley, Kevin Hilman, Vaibhav Bedia, Dave Gerlach

From: Vaibhav Bedia <vaibhav.bedia@ti.com>

With all the requisite changes in place we can now
enable the basic PM support for AM335x. This patch
updates the various OMAP files to enable suspend-resume
on AM335x.

Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
 arch/arm/mach-omap2/Kconfig         |    7 +++++--
 arch/arm/mach-omap2/Makefile        |    2 ++
 arch/arm/mach-omap2/board-generic.c |    1 +
 arch/arm/mach-omap2/common.h        |   10 ++++++++++
 arch/arm/mach-omap2/io.c            |    5 +++++
 arch/arm/mach-omap2/pm.c            |    3 ++-
 arch/arm/mach-omap2/pm.h            |    5 +++++
 arch/arm/mach-omap2/sram.c          |   10 +++++++++-
 arch/arm/mach-omap2/sram.h          |    2 ++
 9 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 3eed000..ef3fe40 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -67,11 +67,14 @@ config SOC_OMAP5
 config SOC_AM33XX
 	bool "AM33XX support"
 	depends on ARCH_MULTI_V7
-	select ARCH_OMAP2PLUS
+	default y
 	select ARM_CPU_SUSPEND if PM
+	select COMMON_CLK
 	select CPU_V7
+	select MAILBOX if PM
 	select MULTI_IRQ_HANDLER
-	select COMMON_CLK
+	select OMAP_MBOX_FWK if PM
+	select OMAP2PLUS_MBOX if PM
 
 config SOC_AM43XX
 	bool "TI AM43x"
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index d4f6715..eb3a47a 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -87,6 +87,7 @@ 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_SOC_OMAP5)			+= omap-mpuss-lowpower.o
+obj-$(CONFIG_SOC_AM33XX)		+= pm33xx.o sleep33xx.o wkup_m3.o
 obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
 
 obj-$(CONFIG_POWER_AVS_OMAP)		+= sr_device.o
@@ -94,6 +95,7 @@ obj-$(CONFIG_POWER_AVS_OMAP_CLASS3)    += smartreflex-class3.o
 
 AFLAGS_sleep24xx.o			:=-Wa,-march=armv6
 AFLAGS_sleep34xx.o			:=-Wa,-march=armv7-a$(plus_sec)
+AFLAGS_sleep33xx.o			:=-Wa,-march=armv7-a$(plus_sec)
 
 endif
 
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index aed750c..3f2d6a7 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -159,6 +159,7 @@ DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)")
 	.reserve	= am33xx_reserve,
 	.map_io		= am33xx_map_io,
 	.init_early	= am33xx_init_early,
+	.init_late	= am33xx_init_late,
 	.init_irq	= omap_intc_of_init,
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= omap_generic_init,
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 6b8ef74..80bf0da 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -69,6 +69,15 @@ static inline int omap4_pm_init(void)
 }
 #endif
 
+#if defined(CONFIG_PM) && defined(CONFIG_SOC_AM33XX)
+int am33xx_pm_init(void);
+#else
+static inline int am33xx_pm_init(void)
+{
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_OMAP_MUX
 int omap_mux_late_init(void);
 #else
@@ -107,6 +116,7 @@ void omap2430_init_late(void);
 void omap3430_init_late(void);
 void omap35xx_init_late(void);
 void omap3630_init_late(void);
+void am33xx_init_late(void);
 void am35xx_init_late(void);
 void ti81xx_init_late(void);
 int omap2_common_pm_late_init(void);
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 3ad7543..63516e5 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -584,6 +584,11 @@ void __init am33xx_init_early(void)
 	omap_hwmod_init_postsetup();
 	omap_clk_init = am33xx_clk_init;
 }
+
+void __init am33xx_init_late(void)
+{
+	am33xx_pm_init();
+}
 #endif
 
 #ifdef CONFIG_SOC_AM43XX
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index e742118..f8bd883 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -305,7 +305,8 @@ int __init omap2_common_pm_late_init(void)
 	}
 
 #ifdef CONFIG_SUSPEND
-	suspend_set_ops(&omap_pm_ops);
+	if (!soc_is_am33xx())
+		suspend_set_ops(&omap_pm_ops);
 #endif
 
 	return 0;
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 7bdd22a..5122bb6 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -82,6 +82,11 @@ extern unsigned int omap3_do_wfi_sz;
 /* ... and its pointer from SRAM after copy */
 extern void (*omap3_do_wfi_sram)(void);
 
+/* am33xx_do_wfi function pointer and size, for copy to SRAM */
+extern void am33xx_do_wfi(void);
+extern unsigned int am33xx_do_wfi_sz;
+extern unsigned int am33xx_resume_offset;
+
 /* save_secure_ram_context function pointer and size, for copy to SRAM */
 extern int save_secure_ram_context(u32 *addr);
 extern unsigned int save_secure_ram_context_sz;
diff --git a/arch/arm/mach-omap2/sram.c b/arch/arm/mach-omap2/sram.c
index 4bd0968..303c562 100644
--- a/arch/arm/mach-omap2/sram.c
+++ b/arch/arm/mach-omap2/sram.c
@@ -154,7 +154,7 @@ static void __init omap2_map_sram(void)
 		omap_sram_size -= SZ_16K;
 	}
 #endif
-	if (cpu_is_omap34xx()) {
+	if (cpu_is_omap34xx() || soc_is_am33xx()) {
 		/*
 		 * SRAM must be marked as non-cached on OMAP3 since the
 		 * CORE DPLL M2 divider change code (in SRAM) runs with the
@@ -285,10 +285,18 @@ static inline int omap34xx_sram_init(void)
 }
 #endif /* CONFIG_ARCH_OMAP3 */
 
+#ifdef CONFIG_SOC_AM33XX
 static inline int am33xx_sram_init(void)
 {
+	am33xx_push_sram_idle();
 	return 0;
 }
+#else
+static inline int am33xx_sram_init(void)
+{
+	return 0;
+}
+#endif
 
 int __init omap_sram_init(void)
 {
diff --git a/arch/arm/mach-omap2/sram.h b/arch/arm/mach-omap2/sram.h
index ca7277c..24788b5 100644
--- a/arch/arm/mach-omap2/sram.h
+++ b/arch/arm/mach-omap2/sram.h
@@ -62,8 +62,10 @@ extern unsigned long omap3_sram_configure_core_dpll_sz;
 
 #ifdef CONFIG_PM
 extern void omap_push_sram_idle(void);
+extern void am33xx_push_sram_idle(void);
 #else
 static inline void omap_push_sram_idle(void) {}
+static inline void am33xx_push_sram_idle(void) {}
 #endif /* CONFIG_PM */
 
 #endif /* __ASSEMBLY__ */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 212+ messages in thread

* [PATCHv3 9/9] ARM: OMAP2+: AM33XX: Hookup AM33XX PM code into OMAP builds
@ 2013-08-06 17:49   ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-06 17:49 UTC (permalink / raw)
  To: linux-arm-kernel

From: Vaibhav Bedia <vaibhav.bedia@ti.com>

With all the requisite changes in place we can now
enable the basic PM support for AM335x. This patch
updates the various OMAP files to enable suspend-resume
on AM335x.

Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
 arch/arm/mach-omap2/Kconfig         |    7 +++++--
 arch/arm/mach-omap2/Makefile        |    2 ++
 arch/arm/mach-omap2/board-generic.c |    1 +
 arch/arm/mach-omap2/common.h        |   10 ++++++++++
 arch/arm/mach-omap2/io.c            |    5 +++++
 arch/arm/mach-omap2/pm.c            |    3 ++-
 arch/arm/mach-omap2/pm.h            |    5 +++++
 arch/arm/mach-omap2/sram.c          |   10 +++++++++-
 arch/arm/mach-omap2/sram.h          |    2 ++
 9 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 3eed000..ef3fe40 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -67,11 +67,14 @@ config SOC_OMAP5
 config SOC_AM33XX
 	bool "AM33XX support"
 	depends on ARCH_MULTI_V7
-	select ARCH_OMAP2PLUS
+	default y
 	select ARM_CPU_SUSPEND if PM
+	select COMMON_CLK
 	select CPU_V7
+	select MAILBOX if PM
 	select MULTI_IRQ_HANDLER
-	select COMMON_CLK
+	select OMAP_MBOX_FWK if PM
+	select OMAP2PLUS_MBOX if PM
 
 config SOC_AM43XX
 	bool "TI AM43x"
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index d4f6715..eb3a47a 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -87,6 +87,7 @@ 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_SOC_OMAP5)			+= omap-mpuss-lowpower.o
+obj-$(CONFIG_SOC_AM33XX)		+= pm33xx.o sleep33xx.o wkup_m3.o
 obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
 
 obj-$(CONFIG_POWER_AVS_OMAP)		+= sr_device.o
@@ -94,6 +95,7 @@ obj-$(CONFIG_POWER_AVS_OMAP_CLASS3)    += smartreflex-class3.o
 
 AFLAGS_sleep24xx.o			:=-Wa,-march=armv6
 AFLAGS_sleep34xx.o			:=-Wa,-march=armv7-a$(plus_sec)
+AFLAGS_sleep33xx.o			:=-Wa,-march=armv7-a$(plus_sec)
 
 endif
 
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index aed750c..3f2d6a7 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -159,6 +159,7 @@ DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)")
 	.reserve	= am33xx_reserve,
 	.map_io		= am33xx_map_io,
 	.init_early	= am33xx_init_early,
+	.init_late	= am33xx_init_late,
 	.init_irq	= omap_intc_of_init,
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= omap_generic_init,
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 6b8ef74..80bf0da 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -69,6 +69,15 @@ static inline int omap4_pm_init(void)
 }
 #endif
 
+#if defined(CONFIG_PM) && defined(CONFIG_SOC_AM33XX)
+int am33xx_pm_init(void);
+#else
+static inline int am33xx_pm_init(void)
+{
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_OMAP_MUX
 int omap_mux_late_init(void);
 #else
@@ -107,6 +116,7 @@ void omap2430_init_late(void);
 void omap3430_init_late(void);
 void omap35xx_init_late(void);
 void omap3630_init_late(void);
+void am33xx_init_late(void);
 void am35xx_init_late(void);
 void ti81xx_init_late(void);
 int omap2_common_pm_late_init(void);
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 3ad7543..63516e5 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -584,6 +584,11 @@ void __init am33xx_init_early(void)
 	omap_hwmod_init_postsetup();
 	omap_clk_init = am33xx_clk_init;
 }
+
+void __init am33xx_init_late(void)
+{
+	am33xx_pm_init();
+}
 #endif
 
 #ifdef CONFIG_SOC_AM43XX
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index e742118..f8bd883 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -305,7 +305,8 @@ int __init omap2_common_pm_late_init(void)
 	}
 
 #ifdef CONFIG_SUSPEND
-	suspend_set_ops(&omap_pm_ops);
+	if (!soc_is_am33xx())
+		suspend_set_ops(&omap_pm_ops);
 #endif
 
 	return 0;
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 7bdd22a..5122bb6 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -82,6 +82,11 @@ extern unsigned int omap3_do_wfi_sz;
 /* ... and its pointer from SRAM after copy */
 extern void (*omap3_do_wfi_sram)(void);
 
+/* am33xx_do_wfi function pointer and size, for copy to SRAM */
+extern void am33xx_do_wfi(void);
+extern unsigned int am33xx_do_wfi_sz;
+extern unsigned int am33xx_resume_offset;
+
 /* save_secure_ram_context function pointer and size, for copy to SRAM */
 extern int save_secure_ram_context(u32 *addr);
 extern unsigned int save_secure_ram_context_sz;
diff --git a/arch/arm/mach-omap2/sram.c b/arch/arm/mach-omap2/sram.c
index 4bd0968..303c562 100644
--- a/arch/arm/mach-omap2/sram.c
+++ b/arch/arm/mach-omap2/sram.c
@@ -154,7 +154,7 @@ static void __init omap2_map_sram(void)
 		omap_sram_size -= SZ_16K;
 	}
 #endif
-	if (cpu_is_omap34xx()) {
+	if (cpu_is_omap34xx() || soc_is_am33xx()) {
 		/*
 		 * SRAM must be marked as non-cached on OMAP3 since the
 		 * CORE DPLL M2 divider change code (in SRAM) runs with the
@@ -285,10 +285,18 @@ static inline int omap34xx_sram_init(void)
 }
 #endif /* CONFIG_ARCH_OMAP3 */
 
+#ifdef CONFIG_SOC_AM33XX
 static inline int am33xx_sram_init(void)
 {
+	am33xx_push_sram_idle();
 	return 0;
 }
+#else
+static inline int am33xx_sram_init(void)
+{
+	return 0;
+}
+#endif
 
 int __init omap_sram_init(void)
 {
diff --git a/arch/arm/mach-omap2/sram.h b/arch/arm/mach-omap2/sram.h
index ca7277c..24788b5 100644
--- a/arch/arm/mach-omap2/sram.h
+++ b/arch/arm/mach-omap2/sram.h
@@ -62,8 +62,10 @@ extern unsigned long omap3_sram_configure_core_dpll_sz;
 
 #ifdef CONFIG_PM
 extern void omap_push_sram_idle(void);
+extern void am33xx_push_sram_idle(void);
 #else
 static inline void omap_push_sram_idle(void) {}
+static inline void am33xx_push_sram_idle(void) {}
 #endif /* CONFIG_PM */
 
 #endif /* __ASSEMBLY__ */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-07 16:22     ` Nishanth Menon
  -1 siblings, 0 replies; 212+ messages in thread
From: Nishanth Menon @ 2013-08-07 16:22 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: Paul Walmsley, Kevin Hilman, Tony Lingren, Vaibhav Bedia,
	Santosh Shilimkar, Benoit Cousson, linux-omap, linux-arm-kernel

On 08/06/2013 12:49 PM, Dave Gerlach wrote:
[...]

> +
> +struct forced_standby_module am33xx_mod[] = {
> +	{.oh_name = "usb_otg_hs"},
> +	{.oh_name = "tptc0"},
> +	{.oh_name = "tptc1"},
> +	{.oh_name = "tptc2"},
> +	{.oh_name = "cpgmac0"},
> +};
> +
[...]
> +
> +static int am33xx_pm_suspend(void)
> +{
> +	int i, j, ret = 0;
> +
> +	int status = 0;
> +	struct platform_device *pdev;
> +	struct omap_device *od;
> +
> +	/*
> +	 * By default the following IPs do not have MSTANDBY asserted
> +	 * which is necessary for PER domain transition. If the drivers
> +	 * are not compiled into the kernel HWMOD code will not change the
> +	 * state of the IPs if the IP was not never enabled. To ensure
> +	 * that there no issues with or without the drivers being compiled
> +	 * in the kernel, we forcefully put these IPs to idle.
> +	 */
> +	for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++) {
> +		pdev = to_platform_device(am33xx_mod[i].dev);
> +		od = to_omap_device(pdev);
> +		if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
> +			omap_device_enable_hwmods(od);
> +			omap_device_idle_hwmods(od);
> +		}
> +	}

Sorry, I dont like this one bit. this is the job of the suspend / resume 
handler dealing with the specific device. I recollect having a similar 
issue on OMAP5 where without USB driver, USB wont idle, hence we cant 
suspend either. is the solution to do a custom handling for specific 
nodes as above? is it even necessary - considering that in multiple 
suspend-resume iterations, do we need to "enable and idle" multiple 
times? Cant we do it just in hwmod/omap_device level where unbound 
devices are disabled? Is there absolutely no possible way to do this in 
a generic manner?

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-07 16:22     ` Nishanth Menon
  0 siblings, 0 replies; 212+ messages in thread
From: Nishanth Menon @ 2013-08-07 16:22 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/06/2013 12:49 PM, Dave Gerlach wrote:
[...]

> +
> +struct forced_standby_module am33xx_mod[] = {
> +	{.oh_name = "usb_otg_hs"},
> +	{.oh_name = "tptc0"},
> +	{.oh_name = "tptc1"},
> +	{.oh_name = "tptc2"},
> +	{.oh_name = "cpgmac0"},
> +};
> +
[...]
> +
> +static int am33xx_pm_suspend(void)
> +{
> +	int i, j, ret = 0;
> +
> +	int status = 0;
> +	struct platform_device *pdev;
> +	struct omap_device *od;
> +
> +	/*
> +	 * By default the following IPs do not have MSTANDBY asserted
> +	 * which is necessary for PER domain transition. If the drivers
> +	 * are not compiled into the kernel HWMOD code will not change the
> +	 * state of the IPs if the IP was not never enabled. To ensure
> +	 * that there no issues with or without the drivers being compiled
> +	 * in the kernel, we forcefully put these IPs to idle.
> +	 */
> +	for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++) {
> +		pdev = to_platform_device(am33xx_mod[i].dev);
> +		od = to_omap_device(pdev);
> +		if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
> +			omap_device_enable_hwmods(od);
> +			omap_device_idle_hwmods(od);
> +		}
> +	}

Sorry, I dont like this one bit. this is the job of the suspend / resume 
handler dealing with the specific device. I recollect having a similar 
issue on OMAP5 where without USB driver, USB wont idle, hence we cant 
suspend either. is the solution to do a custom handling for specific 
nodes as above? is it even necessary - considering that in multiple 
suspend-resume iterations, do we need to "enable and idle" multiple 
times? Cant we do it just in hwmod/omap_device level where unbound 
devices are disabled? Is there absolutely no possible way to do this in 
a generic manner?

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-07 16:22     ` Nishanth Menon
@ 2013-08-07 18:12       ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-07 18:12 UTC (permalink / raw)
  To: Nishanth Menon
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman,
	Vaibhav Bedia, Tony Lingren, Santosh Shilimkar, Benoit Cousson

Nishanth,
The issue here is that during a low-power transition the peripheral 
power domain loses context so the MSTANDBY config gets lost which is why 
the custom handling is needed on every cycle if there is no driver to 
handle it. I was unable to come up with a more generic way to handle 
this but I am certainly open for suggestions.

Regards,
Dave

On 08/07/2013 11:22 AM, Nishanth Menon wrote:
> On 08/06/2013 12:49 PM, Dave Gerlach wrote:
> [...]
>
>> +
>> +struct forced_standby_module am33xx_mod[] = {
>> +    {.oh_name = "usb_otg_hs"},
>> +    {.oh_name = "tptc0"},
>> +    {.oh_name = "tptc1"},
>> +    {.oh_name = "tptc2"},
>> +    {.oh_name = "cpgmac0"},
>> +};
>> +
> [...]
>> +
>> +static int am33xx_pm_suspend(void)
>> +{
>> +    int i, j, ret = 0;
>> +
>> +    int status = 0;
>> +    struct platform_device *pdev;
>> +    struct omap_device *od;
>> +
>> +    /*
>> +     * By default the following IPs do not have MSTANDBY asserted
>> +     * which is necessary for PER domain transition. If the drivers
>> +     * are not compiled into the kernel HWMOD code will not change the
>> +     * state of the IPs if the IP was not never enabled. To ensure
>> +     * that there no issues with or without the drivers being compiled
>> +     * in the kernel, we forcefully put these IPs to idle.
>> +     */
>> +    for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++) {
>> +        pdev = to_platform_device(am33xx_mod[i].dev);
>> +        od = to_omap_device(pdev);
>> +        if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
>> +            omap_device_enable_hwmods(od);
>> +            omap_device_idle_hwmods(od);
>> +        }
>> +    }
>
> Sorry, I dont like this one bit. this is the job of the suspend / resume
> handler dealing with the specific device. I recollect having a similar
> issue on OMAP5 where without USB driver, USB wont idle, hence we cant
> suspend either. is the solution to do a custom handling for specific
> nodes as above? is it even necessary - considering that in multiple
> suspend-resume iterations, do we need to "enable and idle" multiple
> times? Cant we do it just in hwmod/omap_device level where unbound
> devices are disabled? Is there absolutely no possible way to do this in
> a generic manner?
>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-07 18:12       ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-07 18:12 UTC (permalink / raw)
  To: linux-arm-kernel

Nishanth,
The issue here is that during a low-power transition the peripheral 
power domain loses context so the MSTANDBY config gets lost which is why 
the custom handling is needed on every cycle if there is no driver to 
handle it. I was unable to come up with a more generic way to handle 
this but I am certainly open for suggestions.

Regards,
Dave

On 08/07/2013 11:22 AM, Nishanth Menon wrote:
> On 08/06/2013 12:49 PM, Dave Gerlach wrote:
> [...]
>
>> +
>> +struct forced_standby_module am33xx_mod[] = {
>> +    {.oh_name = "usb_otg_hs"},
>> +    {.oh_name = "tptc0"},
>> +    {.oh_name = "tptc1"},
>> +    {.oh_name = "tptc2"},
>> +    {.oh_name = "cpgmac0"},
>> +};
>> +
> [...]
>> +
>> +static int am33xx_pm_suspend(void)
>> +{
>> +    int i, j, ret = 0;
>> +
>> +    int status = 0;
>> +    struct platform_device *pdev;
>> +    struct omap_device *od;
>> +
>> +    /*
>> +     * By default the following IPs do not have MSTANDBY asserted
>> +     * which is necessary for PER domain transition. If the drivers
>> +     * are not compiled into the kernel HWMOD code will not change the
>> +     * state of the IPs if the IP was not never enabled. To ensure
>> +     * that there no issues with or without the drivers being compiled
>> +     * in the kernel, we forcefully put these IPs to idle.
>> +     */
>> +    for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++) {
>> +        pdev = to_platform_device(am33xx_mod[i].dev);
>> +        od = to_omap_device(pdev);
>> +        if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
>> +            omap_device_enable_hwmods(od);
>> +            omap_device_idle_hwmods(od);
>> +        }
>> +    }
>
> Sorry, I dont like this one bit. this is the job of the suspend / resume
> handler dealing with the specific device. I recollect having a similar
> issue on OMAP5 where without USB driver, USB wont idle, hence we cant
> suspend either. is the solution to do a custom handling for specific
> nodes as above? is it even necessary - considering that in multiple
> suspend-resume iterations, do we need to "enable and idle" multiple
> times? Cant we do it just in hwmod/omap_device level where unbound
> devices are disabled? Is there absolutely no possible way to do this in
> a generic manner?
>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-07 18:12       ` Dave Gerlach
@ 2013-08-07 19:16         ` Nishanth Menon
  -1 siblings, 0 replies; 212+ messages in thread
From: Nishanth Menon @ 2013-08-07 19:16 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman,
	Vaibhav Bedia, Tony Lingren, Santosh Shilimkar, Benoit Cousson

On 08/07/2013 01:12 PM, Dave Gerlach wrote:
> On 08/07/2013 11:22 AM, Nishanth Menon wrote:
>> On 08/06/2013 12:49 PM, Dave Gerlach wrote:
>> [...]
>>
>>> +
>>> +struct forced_standby_module am33xx_mod[] = {
>>> +    {.oh_name = "usb_otg_hs"},
>>> +    {.oh_name = "tptc0"},
>>> +    {.oh_name = "tptc1"},
>>> +    {.oh_name = "tptc2"},
>>> +    {.oh_name = "cpgmac0"},
>>> +};
>>> +
>> [...]
>>> +
>>> +static int am33xx_pm_suspend(void)
>>> +{
>>> +    int i, j, ret = 0;
>>> +
>>> +    int status = 0;
>>> +    struct platform_device *pdev;
>>> +    struct omap_device *od;
>>> +
>>> +    /*
>>> +     * By default the following IPs do not have MSTANDBY asserted
>>> +     * which is necessary for PER domain transition. If the drivers
>>> +     * are not compiled into the kernel HWMOD code will not change the
>>> +     * state of the IPs if the IP was not never enabled. To ensure
>>> +     * that there no issues with or without the drivers being compiled
>>> +     * in the kernel, we forcefully put these IPs to idle.
>>> +     */
>>> +    for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++) {
>>> +        pdev = to_platform_device(am33xx_mod[i].dev);
>>> +        od = to_omap_device(pdev);
>>> +        if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
>>> +            omap_device_enable_hwmods(od);
>>> +            omap_device_idle_hwmods(od);
>>> +        }
>>> +    }
>>
>> Sorry, I dont like this one bit. this is the job of the suspend / resume
>> handler dealing with the specific device. I recollect having a similar
>> issue on OMAP5 where without USB driver, USB wont idle, hence we cant
>> suspend either. is the solution to do a custom handling for specific
>> nodes as above? is it even necessary - considering that in multiple
>> suspend-resume iterations, do we need to "enable and idle" multiple
>> times? Cant we do it just in hwmod/omap_device level where unbound
>> devices are disabled? Is there absolutely no possible way to do this in
>> a generic manner?
>>
>
> The issue here is that during a low-power transition the peripheral
> power domain loses context so the MSTANDBY config gets lost which is why
> the custom handling is needed on every cycle if there is no driver to
> handle it. I was unable to come up with a more generic way to handle
> this but I am certainly open for suggestions.
>

If the dts entry for device status = "disabled" you should not have 
these even registered right? kinda makes me wonder if M3 could do 
something about it -> since they are minimal?

When they are not,

I think the generic omap_device_pm_domain ops does not apply for these 
devices due to the quirks?

Making a flag for these improper devices should let omap_device 
abstraction setup different pm_domain configuration also shut them up at 
boot as well (if un-bound). that will let a generic device solution 
scale out to more SoCs without custom handling, perhaps?

just an quick idea - not sure about validity about the approach without 
digging in more.


usually, we try to ensure system is exactly the same state as it entered 
-> so at boot, we shut down everything, on wakeup, if unexpected things 
like these are present, we shut them down again (in .finish handler).

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-07 19:16         ` Nishanth Menon
  0 siblings, 0 replies; 212+ messages in thread
From: Nishanth Menon @ 2013-08-07 19:16 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/07/2013 01:12 PM, Dave Gerlach wrote:
> On 08/07/2013 11:22 AM, Nishanth Menon wrote:
>> On 08/06/2013 12:49 PM, Dave Gerlach wrote:
>> [...]
>>
>>> +
>>> +struct forced_standby_module am33xx_mod[] = {
>>> +    {.oh_name = "usb_otg_hs"},
>>> +    {.oh_name = "tptc0"},
>>> +    {.oh_name = "tptc1"},
>>> +    {.oh_name = "tptc2"},
>>> +    {.oh_name = "cpgmac0"},
>>> +};
>>> +
>> [...]
>>> +
>>> +static int am33xx_pm_suspend(void)
>>> +{
>>> +    int i, j, ret = 0;
>>> +
>>> +    int status = 0;
>>> +    struct platform_device *pdev;
>>> +    struct omap_device *od;
>>> +
>>> +    /*
>>> +     * By default the following IPs do not have MSTANDBY asserted
>>> +     * which is necessary for PER domain transition. If the drivers
>>> +     * are not compiled into the kernel HWMOD code will not change the
>>> +     * state of the IPs if the IP was not never enabled. To ensure
>>> +     * that there no issues with or without the drivers being compiled
>>> +     * in the kernel, we forcefully put these IPs to idle.
>>> +     */
>>> +    for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++) {
>>> +        pdev = to_platform_device(am33xx_mod[i].dev);
>>> +        od = to_omap_device(pdev);
>>> +        if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
>>> +            omap_device_enable_hwmods(od);
>>> +            omap_device_idle_hwmods(od);
>>> +        }
>>> +    }
>>
>> Sorry, I dont like this one bit. this is the job of the suspend / resume
>> handler dealing with the specific device. I recollect having a similar
>> issue on OMAP5 where without USB driver, USB wont idle, hence we cant
>> suspend either. is the solution to do a custom handling for specific
>> nodes as above? is it even necessary - considering that in multiple
>> suspend-resume iterations, do we need to "enable and idle" multiple
>> times? Cant we do it just in hwmod/omap_device level where unbound
>> devices are disabled? Is there absolutely no possible way to do this in
>> a generic manner?
>>
>
> The issue here is that during a low-power transition the peripheral
> power domain loses context so the MSTANDBY config gets lost which is why
> the custom handling is needed on every cycle if there is no driver to
> handle it. I was unable to come up with a more generic way to handle
> this but I am certainly open for suggestions.
>

If the dts entry for device status = "disabled" you should not have 
these even registered right? kinda makes me wonder if M3 could do 
something about it -> since they are minimal?

When they are not,

I think the generic omap_device_pm_domain ops does not apply for these 
devices due to the quirks?

Making a flag for these improper devices should let omap_device 
abstraction setup different pm_domain configuration also shut them up at 
boot as well (if un-bound). that will let a generic device solution 
scale out to more SoCs without custom handling, perhaps?

just an quick idea - not sure about validity about the approach without 
digging in more.


usually, we try to ensure system is exactly the same state as it entered 
-> so at boot, we shut down everything, on wakeup, if unexpected things 
like these are present, we shut them down again (in .finish handler).

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 1/9] memory: emif: Move EMIF register defines to include/linux/
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08  0:48     ` Russ Dill
  -1 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08  0:48 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman,
	Santosh Shilimkar, Benoit Cousson, Aneesh V

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> OMAP4 and AM33XX share the same EMIF controller IP. Although there
> are significant differences in the IP integration due to which
> AM33XX can't reuse the EMIF driver DVFS similar to OMAP4,
> it can definitely benefit by reusing the EMIF related macros
> defined in drivers/memory/emif.h.
>
> In the current OMAP PM framework the PM code resides under
> arch/arm/mach-omap2/. To enable reuse of the register defines move
> the register defines in the emif header file to include/linux so that
> both the EMIF driver and the AM33XX PM code can benefit.
>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Benoit Cousson <benoit.cousson@linaro.org>
> Cc: Aneesh V <aneesh@ti.com>

Reviewed-by: Russ Dill <russ.dill@ti.com>

> ---
>  drivers/memory/emif.h   |  543 +--------------------------------------------
>  include/linux/ti_emif.h |  558 +++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 559 insertions(+), 542 deletions(-)
>  create mode 100644 include/linux/ti_emif.h
>
> diff --git a/drivers/memory/emif.h b/drivers/memory/emif.h
> index bfe08ba..8214f07 100644
> --- a/drivers/memory/emif.h
> +++ b/drivers/memory/emif.h
> @@ -12,548 +12,7 @@
>  #ifndef __EMIF_H
>  #define __EMIF_H
>
> -/*
> - * Maximum number of different frequencies supported by EMIF driver
> - * Determines the number of entries in the pointer array for register
> - * cache
> - */
> -#define EMIF_MAX_NUM_FREQUENCIES                       6
> -
> -/* State of the core voltage */
> -#define DDR_VOLTAGE_STABLE                             0
> -#define DDR_VOLTAGE_RAMPING                            1
> -
> -/* Defines for timing De-rating */
> -#define EMIF_NORMAL_TIMINGS                            0
> -#define EMIF_DERATED_TIMINGS                           1
> -
> -/* Length of the forced read idle period in terms of cycles */
> -#define EMIF_READ_IDLE_LEN_VAL                         5
> -
> -/*
> - * forced read idle interval to be used when voltage
> - * is changed as part of DVFS/DPS - 1ms
> - */
> -#define READ_IDLE_INTERVAL_DVFS                                (1*1000000)
> -
> -/*
> - * Forced read idle interval to be used when voltage is stable
> - * 50us - or maximum value will do
> - */
> -#define READ_IDLE_INTERVAL_NORMAL                      (50*1000000)
> -
> -/* DLL calibration interval when voltage is NOT stable - 1us */
> -#define DLL_CALIB_INTERVAL_DVFS                                (1*1000000)
> -
> -#define DLL_CALIB_ACK_WAIT_VAL                         5
> -
> -/* Interval between ZQCS commands - hw team recommended value */
> -#define EMIF_ZQCS_INTERVAL_US                          (50*1000)
> -/* Enable ZQ Calibration on exiting Self-refresh */
> -#define ZQ_SFEXITEN_ENABLE                             1
> -/*
> - * ZQ Calibration simultaneously on both chip-selects:
> - * Needs one calibration resistor per CS
> - */
> -#define        ZQ_DUALCALEN_DISABLE                            0
> -#define        ZQ_DUALCALEN_ENABLE                             1
> -
> -#define T_ZQCS_DEFAULT_NS                              90
> -#define T_ZQCL_DEFAULT_NS                              360
> -#define T_ZQINIT_DEFAULT_NS                            1000
> -
> -/* DPD_EN */
> -#define DPD_DISABLE                                    0
> -#define DPD_ENABLE                                     1
> -
> -/*
> - * Default values for the low-power entry to be used if not provided by user.
> - * OMAP4/5 has a hw bug(i735) due to which this value can not be less than 512
> - * Timeout values are in DDR clock 'cycles' and frequency threshold in Hz
> - */
> -#define EMIF_LP_MODE_TIMEOUT_PERFORMANCE               2048
> -#define EMIF_LP_MODE_TIMEOUT_POWER                     512
> -#define EMIF_LP_MODE_FREQ_THRESHOLD                    400000000
> -
> -/* DDR_PHY_CTRL_1 values for EMIF4D - ATTILA PHY combination */
> -#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY         0x049FF000
> -#define EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY      0x41
> -#define EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY      0x80
> -#define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY 0xFF
> -
> -/* DDR_PHY_CTRL_1 values for EMIF4D5 INTELLIPHY combination */
> -#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY                0x0E084200
> -#define EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS      10000
> -
> -/* TEMP_ALERT_CONFIG - corresponding to temp gradient 5 C/s */
> -#define TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS            360
> -
> -#define EMIF_T_CSTA                                    3
> -#define EMIF_T_PDLL_UL                                 128
> -
> -/* External PHY control registers magic values */
> -#define EMIF_EXT_PHY_CTRL_1_VAL                                0x04020080
> -#define EMIF_EXT_PHY_CTRL_5_VAL                                0x04010040
> -#define EMIF_EXT_PHY_CTRL_6_VAL                                0x01004010
> -#define EMIF_EXT_PHY_CTRL_7_VAL                                0x00001004
> -#define EMIF_EXT_PHY_CTRL_8_VAL                                0x04010040
> -#define EMIF_EXT_PHY_CTRL_9_VAL                                0x01004010
> -#define EMIF_EXT_PHY_CTRL_10_VAL                       0x00001004
> -#define EMIF_EXT_PHY_CTRL_11_VAL                       0x00000000
> -#define EMIF_EXT_PHY_CTRL_12_VAL                       0x00000000
> -#define EMIF_EXT_PHY_CTRL_13_VAL                       0x00000000
> -#define EMIF_EXT_PHY_CTRL_14_VAL                       0x80080080
> -#define EMIF_EXT_PHY_CTRL_15_VAL                       0x00800800
> -#define EMIF_EXT_PHY_CTRL_16_VAL                       0x08102040
> -#define EMIF_EXT_PHY_CTRL_17_VAL                       0x00000001
> -#define EMIF_EXT_PHY_CTRL_18_VAL                       0x540A8150
> -#define EMIF_EXT_PHY_CTRL_19_VAL                       0xA81502A0
> -#define EMIF_EXT_PHY_CTRL_20_VAL                       0x002A0540
> -#define EMIF_EXT_PHY_CTRL_21_VAL                       0x00000000
> -#define EMIF_EXT_PHY_CTRL_22_VAL                       0x00000000
> -#define EMIF_EXT_PHY_CTRL_23_VAL                       0x00000000
> -#define EMIF_EXT_PHY_CTRL_24_VAL                       0x00000077
> -
> -#define EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS     1200
> -
> -/* Registers offset */
> -#define EMIF_MODULE_ID_AND_REVISION                    0x0000
> -#define EMIF_STATUS                                    0x0004
> -#define EMIF_SDRAM_CONFIG                              0x0008
> -#define EMIF_SDRAM_CONFIG_2                            0x000c
> -#define EMIF_SDRAM_REFRESH_CONTROL                     0x0010
> -#define EMIF_SDRAM_REFRESH_CTRL_SHDW                   0x0014
> -#define EMIF_SDRAM_TIMING_1                            0x0018
> -#define EMIF_SDRAM_TIMING_1_SHDW                       0x001c
> -#define EMIF_SDRAM_TIMING_2                            0x0020
> -#define EMIF_SDRAM_TIMING_2_SHDW                       0x0024
> -#define EMIF_SDRAM_TIMING_3                            0x0028
> -#define EMIF_SDRAM_TIMING_3_SHDW                       0x002c
> -#define EMIF_LPDDR2_NVM_TIMING                         0x0030
> -#define EMIF_LPDDR2_NVM_TIMING_SHDW                    0x0034
> -#define EMIF_POWER_MANAGEMENT_CONTROL                  0x0038
> -#define EMIF_POWER_MANAGEMENT_CTRL_SHDW                        0x003c
> -#define EMIF_LPDDR2_MODE_REG_DATA                      0x0040
> -#define EMIF_LPDDR2_MODE_REG_CONFIG                    0x0050
> -#define EMIF_OCP_CONFIG                                        0x0054
> -#define EMIF_OCP_CONFIG_VALUE_1                                0x0058
> -#define EMIF_OCP_CONFIG_VALUE_2                                0x005c
> -#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL           0x0060
> -#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT         0x0064
> -#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT      0x0068
> -#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1       0x006c
> -#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2       0x0070
> -#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3       0x0074
> -#define EMIF_PERFORMANCE_COUNTER_1                     0x0080
> -#define EMIF_PERFORMANCE_COUNTER_2                     0x0084
> -#define EMIF_PERFORMANCE_COUNTER_CONFIG                        0x0088
> -#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT  0x008c
> -#define EMIF_PERFORMANCE_COUNTER_TIME                  0x0090
> -#define EMIF_MISC_REG                                  0x0094
> -#define EMIF_DLL_CALIB_CTRL                            0x0098
> -#define EMIF_DLL_CALIB_CTRL_SHDW                       0x009c
> -#define EMIF_END_OF_INTERRUPT                          0x00a0
> -#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS           0x00a4
> -#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS               0x00a8
> -#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS               0x00ac
> -#define EMIF_LL_OCP_INTERRUPT_STATUS                   0x00b0
> -#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET           0x00b4
> -#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET               0x00b8
> -#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR         0x00bc
> -#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR             0x00c0
> -#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG 0x00c8
> -#define EMIF_TEMPERATURE_ALERT_CONFIG                  0x00cc
> -#define EMIF_OCP_ERROR_LOG                             0x00d0
> -#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW           0x00d4
> -#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL          0x00d8
> -#define EMIF_READ_WRITE_LEVELING_CONTROL               0x00dc
> -#define EMIF_DDR_PHY_CTRL_1                            0x00e4
> -#define EMIF_DDR_PHY_CTRL_1_SHDW                       0x00e8
> -#define EMIF_DDR_PHY_CTRL_2                            0x00ec
> -#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING      0x0100
> -#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104
> -#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108
> -#define EMIF_READ_WRITE_EXECUTION_THRESHOLD            0x0120
> -#define EMIF_COS_CONFIG                                        0x0124
> -#define EMIF_PHY_STATUS_1                              0x0140
> -#define EMIF_PHY_STATUS_2                              0x0144
> -#define EMIF_PHY_STATUS_3                              0x0148
> -#define EMIF_PHY_STATUS_4                              0x014c
> -#define EMIF_PHY_STATUS_5                              0x0150
> -#define EMIF_PHY_STATUS_6                              0x0154
> -#define EMIF_PHY_STATUS_7                              0x0158
> -#define EMIF_PHY_STATUS_8                              0x015c
> -#define EMIF_PHY_STATUS_9                              0x0160
> -#define EMIF_PHY_STATUS_10                             0x0164
> -#define EMIF_PHY_STATUS_11                             0x0168
> -#define EMIF_PHY_STATUS_12                             0x016c
> -#define EMIF_PHY_STATUS_13                             0x0170
> -#define EMIF_PHY_STATUS_14                             0x0174
> -#define EMIF_PHY_STATUS_15                             0x0178
> -#define EMIF_PHY_STATUS_16                             0x017c
> -#define EMIF_PHY_STATUS_17                             0x0180
> -#define EMIF_PHY_STATUS_18                             0x0184
> -#define EMIF_PHY_STATUS_19                             0x0188
> -#define EMIF_PHY_STATUS_20                             0x018c
> -#define EMIF_PHY_STATUS_21                             0x0190
> -#define EMIF_EXT_PHY_CTRL_1                            0x0200
> -#define EMIF_EXT_PHY_CTRL_1_SHDW                       0x0204
> -#define EMIF_EXT_PHY_CTRL_2                            0x0208
> -#define EMIF_EXT_PHY_CTRL_2_SHDW                       0x020c
> -#define EMIF_EXT_PHY_CTRL_3                            0x0210
> -#define EMIF_EXT_PHY_CTRL_3_SHDW                       0x0214
> -#define EMIF_EXT_PHY_CTRL_4                            0x0218
> -#define EMIF_EXT_PHY_CTRL_4_SHDW                       0x021c
> -#define EMIF_EXT_PHY_CTRL_5                            0x0220
> -#define EMIF_EXT_PHY_CTRL_5_SHDW                       0x0224
> -#define EMIF_EXT_PHY_CTRL_6                            0x0228
> -#define EMIF_EXT_PHY_CTRL_6_SHDW                       0x022c
> -#define EMIF_EXT_PHY_CTRL_7                            0x0230
> -#define EMIF_EXT_PHY_CTRL_7_SHDW                       0x0234
> -#define EMIF_EXT_PHY_CTRL_8                            0x0238
> -#define EMIF_EXT_PHY_CTRL_8_SHDW                       0x023c
> -#define EMIF_EXT_PHY_CTRL_9                            0x0240
> -#define EMIF_EXT_PHY_CTRL_9_SHDW                       0x0244
> -#define EMIF_EXT_PHY_CTRL_10                           0x0248
> -#define EMIF_EXT_PHY_CTRL_10_SHDW                      0x024c
> -#define EMIF_EXT_PHY_CTRL_11                           0x0250
> -#define EMIF_EXT_PHY_CTRL_11_SHDW                      0x0254
> -#define EMIF_EXT_PHY_CTRL_12                           0x0258
> -#define EMIF_EXT_PHY_CTRL_12_SHDW                      0x025c
> -#define EMIF_EXT_PHY_CTRL_13                           0x0260
> -#define EMIF_EXT_PHY_CTRL_13_SHDW                      0x0264
> -#define EMIF_EXT_PHY_CTRL_14                           0x0268
> -#define EMIF_EXT_PHY_CTRL_14_SHDW                      0x026c
> -#define EMIF_EXT_PHY_CTRL_15                           0x0270
> -#define EMIF_EXT_PHY_CTRL_15_SHDW                      0x0274
> -#define EMIF_EXT_PHY_CTRL_16                           0x0278
> -#define EMIF_EXT_PHY_CTRL_16_SHDW                      0x027c
> -#define EMIF_EXT_PHY_CTRL_17                           0x0280
> -#define EMIF_EXT_PHY_CTRL_17_SHDW                      0x0284
> -#define EMIF_EXT_PHY_CTRL_18                           0x0288
> -#define EMIF_EXT_PHY_CTRL_18_SHDW                      0x028c
> -#define EMIF_EXT_PHY_CTRL_19                           0x0290
> -#define EMIF_EXT_PHY_CTRL_19_SHDW                      0x0294
> -#define EMIF_EXT_PHY_CTRL_20                           0x0298
> -#define EMIF_EXT_PHY_CTRL_20_SHDW                      0x029c
> -#define EMIF_EXT_PHY_CTRL_21                           0x02a0
> -#define EMIF_EXT_PHY_CTRL_21_SHDW                      0x02a4
> -#define EMIF_EXT_PHY_CTRL_22                           0x02a8
> -#define EMIF_EXT_PHY_CTRL_22_SHDW                      0x02ac
> -#define EMIF_EXT_PHY_CTRL_23                           0x02b0
> -#define EMIF_EXT_PHY_CTRL_23_SHDW                      0x02b4
> -#define EMIF_EXT_PHY_CTRL_24                           0x02b8
> -#define EMIF_EXT_PHY_CTRL_24_SHDW                      0x02bc
> -#define EMIF_EXT_PHY_CTRL_25                           0x02c0
> -#define EMIF_EXT_PHY_CTRL_25_SHDW                      0x02c4
> -#define EMIF_EXT_PHY_CTRL_26                           0x02c8
> -#define EMIF_EXT_PHY_CTRL_26_SHDW                      0x02cc
> -#define EMIF_EXT_PHY_CTRL_27                           0x02d0
> -#define EMIF_EXT_PHY_CTRL_27_SHDW                      0x02d4
> -#define EMIF_EXT_PHY_CTRL_28                           0x02d8
> -#define EMIF_EXT_PHY_CTRL_28_SHDW                      0x02dc
> -#define EMIF_EXT_PHY_CTRL_29                           0x02e0
> -#define EMIF_EXT_PHY_CTRL_29_SHDW                      0x02e4
> -#define EMIF_EXT_PHY_CTRL_30                           0x02e8
> -#define EMIF_EXT_PHY_CTRL_30_SHDW                      0x02ec
> -
> -/* Registers shifts and masks */
> -
> -/* EMIF_MODULE_ID_AND_REVISION */
> -#define SCHEME_SHIFT                                   30
> -#define SCHEME_MASK                                    (0x3 << 30)
> -#define MODULE_ID_SHIFT                                        16
> -#define MODULE_ID_MASK                                 (0xfff << 16)
> -#define RTL_VERSION_SHIFT                              11
> -#define RTL_VERSION_MASK                               (0x1f << 11)
> -#define MAJOR_REVISION_SHIFT                           8
> -#define MAJOR_REVISION_MASK                            (0x7 << 8)
> -#define MINOR_REVISION_SHIFT                           0
> -#define MINOR_REVISION_MASK                            (0x3f << 0)
> -
> -/* STATUS */
> -#define BE_SHIFT                                       31
> -#define BE_MASK                                                (1 << 31)
> -#define DUAL_CLK_MODE_SHIFT                            30
> -#define DUAL_CLK_MODE_MASK                             (1 << 30)
> -#define FAST_INIT_SHIFT                                        29
> -#define FAST_INIT_MASK                                 (1 << 29)
> -#define RDLVLGATETO_SHIFT                              6
> -#define RDLVLGATETO_MASK                               (1 << 6)
> -#define RDLVLTO_SHIFT                                  5
> -#define RDLVLTO_MASK                                   (1 << 5)
> -#define WRLVLTO_SHIFT                                  4
> -#define WRLVLTO_MASK                                   (1 << 4)
> -#define PHY_DLL_READY_SHIFT                            2
> -#define PHY_DLL_READY_MASK                             (1 << 2)
> -
> -/* SDRAM_CONFIG */
> -#define SDRAM_TYPE_SHIFT                               29
> -#define SDRAM_TYPE_MASK                                        (0x7 << 29)
> -#define IBANK_POS_SHIFT                                        27
> -#define IBANK_POS_MASK                                 (0x3 << 27)
> -#define DDR_TERM_SHIFT                                 24
> -#define DDR_TERM_MASK                                  (0x7 << 24)
> -#define DDR2_DDQS_SHIFT                                        23
> -#define DDR2_DDQS_MASK                                 (1 << 23)
> -#define DYN_ODT_SHIFT                                  21
> -#define DYN_ODT_MASK                                   (0x3 << 21)
> -#define DDR_DISABLE_DLL_SHIFT                          20
> -#define DDR_DISABLE_DLL_MASK                           (1 << 20)
> -#define SDRAM_DRIVE_SHIFT                              18
> -#define SDRAM_DRIVE_MASK                               (0x3 << 18)
> -#define CWL_SHIFT                                      16
> -#define CWL_MASK                                       (0x3 << 16)
> -#define NARROW_MODE_SHIFT                              14
> -#define NARROW_MODE_MASK                               (0x3 << 14)
> -#define CL_SHIFT                                       10
> -#define CL_MASK                                                (0xf << 10)
> -#define ROWSIZE_SHIFT                                  7
> -#define ROWSIZE_MASK                                   (0x7 << 7)
> -#define IBANK_SHIFT                                    4
> -#define IBANK_MASK                                     (0x7 << 4)
> -#define EBANK_SHIFT                                    3
> -#define EBANK_MASK                                     (1 << 3)
> -#define PAGESIZE_SHIFT                                 0
> -#define PAGESIZE_MASK                                  (0x7 << 0)
> -
> -/* SDRAM_CONFIG_2 */
> -#define CS1NVMEN_SHIFT                                 30
> -#define CS1NVMEN_MASK                                  (1 << 30)
> -#define EBANK_POS_SHIFT                                        27
> -#define EBANK_POS_MASK                                 (1 << 27)
> -#define RDBNUM_SHIFT                                   4
> -#define RDBNUM_MASK                                    (0x3 << 4)
> -#define RDBSIZE_SHIFT                                  0
> -#define RDBSIZE_MASK                                   (0x7 << 0)
> -
> -/* SDRAM_REFRESH_CONTROL */
> -#define INITREF_DIS_SHIFT                              31
> -#define INITREF_DIS_MASK                               (1 << 31)
> -#define SRT_SHIFT                                      29
> -#define SRT_MASK                                       (1 << 29)
> -#define ASR_SHIFT                                      28
> -#define ASR_MASK                                       (1 << 28)
> -#define PASR_SHIFT                                     24
> -#define PASR_MASK                                      (0x7 << 24)
> -#define REFRESH_RATE_SHIFT                             0
> -#define REFRESH_RATE_MASK                              (0xffff << 0)
> -
> -/* SDRAM_TIMING_1 */
> -#define T_RTW_SHIFT                                    29
> -#define T_RTW_MASK                                     (0x7 << 29)
> -#define T_RP_SHIFT                                     25
> -#define T_RP_MASK                                      (0xf << 25)
> -#define T_RCD_SHIFT                                    21
> -#define T_RCD_MASK                                     (0xf << 21)
> -#define T_WR_SHIFT                                     17
> -#define T_WR_MASK                                      (0xf << 17)
> -#define T_RAS_SHIFT                                    12
> -#define T_RAS_MASK                                     (0x1f << 12)
> -#define T_RC_SHIFT                                     6
> -#define T_RC_MASK                                      (0x3f << 6)
> -#define T_RRD_SHIFT                                    3
> -#define T_RRD_MASK                                     (0x7 << 3)
> -#define T_WTR_SHIFT                                    0
> -#define T_WTR_MASK                                     (0x7 << 0)
> -
> -/* SDRAM_TIMING_2 */
> -#define T_XP_SHIFT                                     28
> -#define T_XP_MASK                                      (0x7 << 28)
> -#define T_ODT_SHIFT                                    25
> -#define T_ODT_MASK                                     (0x7 << 25)
> -#define T_XSNR_SHIFT                                   16
> -#define T_XSNR_MASK                                    (0x1ff << 16)
> -#define T_XSRD_SHIFT                                   6
> -#define T_XSRD_MASK                                    (0x3ff << 6)
> -#define T_RTP_SHIFT                                    3
> -#define T_RTP_MASK                                     (0x7 << 3)
> -#define T_CKE_SHIFT                                    0
> -#define T_CKE_MASK                                     (0x7 << 0)
> -
> -/* SDRAM_TIMING_3 */
> -#define T_PDLL_UL_SHIFT                                        28
> -#define T_PDLL_UL_MASK                                 (0xf << 28)
> -#define T_CSTA_SHIFT                                   24
> -#define T_CSTA_MASK                                    (0xf << 24)
> -#define T_CKESR_SHIFT                                  21
> -#define T_CKESR_MASK                                   (0x7 << 21)
> -#define ZQ_ZQCS_SHIFT                                  15
> -#define ZQ_ZQCS_MASK                                   (0x3f << 15)
> -#define T_TDQSCKMAX_SHIFT                              13
> -#define T_TDQSCKMAX_MASK                               (0x3 << 13)
> -#define T_RFC_SHIFT                                    4
> -#define T_RFC_MASK                                     (0x1ff << 4)
> -#define T_RAS_MAX_SHIFT                                        0
> -#define T_RAS_MAX_MASK                                 (0xf << 0)
> -
> -/* POWER_MANAGEMENT_CONTROL */
> -#define PD_TIM_SHIFT                                   12
> -#define PD_TIM_MASK                                    (0xf << 12)
> -#define DPD_EN_SHIFT                                   11
> -#define DPD_EN_MASK                                    (1 << 11)
> -#define LP_MODE_SHIFT                                  8
> -#define LP_MODE_MASK                                   (0x7 << 8)
> -#define SR_TIM_SHIFT                                   4
> -#define SR_TIM_MASK                                    (0xf << 4)
> -#define CS_TIM_SHIFT                                   0
> -#define CS_TIM_MASK                                    (0xf << 0)
> -
> -/* LPDDR2_MODE_REG_DATA */
> -#define VALUE_0_SHIFT                                  0
> -#define VALUE_0_MASK                                   (0x7f << 0)
> -
> -/* LPDDR2_MODE_REG_CONFIG */
> -#define CS_SHIFT                                       31
> -#define CS_MASK                                                (1 << 31)
> -#define REFRESH_EN_SHIFT                               30
> -#define REFRESH_EN_MASK                                        (1 << 30)
> -#define ADDRESS_SHIFT                                  0
> -#define ADDRESS_MASK                                   (0xff << 0)
> -
> -/* OCP_CONFIG */
> -#define SYS_THRESH_MAX_SHIFT                           24
> -#define SYS_THRESH_MAX_MASK                            (0xf << 24)
> -#define MPU_THRESH_MAX_SHIFT                           20
> -#define MPU_THRESH_MAX_MASK                            (0xf << 20)
> -#define LL_THRESH_MAX_SHIFT                            16
> -#define LL_THRESH_MAX_MASK                             (0xf << 16)
> -
> -/* PERFORMANCE_COUNTER_1 */
> -#define COUNTER1_SHIFT                                 0
> -#define COUNTER1_MASK                                  (0xffffffff << 0)
> -
> -/* PERFORMANCE_COUNTER_2 */
> -#define COUNTER2_SHIFT                                 0
> -#define COUNTER2_MASK                                  (0xffffffff << 0)
> -
> -/* PERFORMANCE_COUNTER_CONFIG */
> -#define CNTR2_MCONNID_EN_SHIFT                         31
> -#define CNTR2_MCONNID_EN_MASK                          (1 << 31)
> -#define CNTR2_REGION_EN_SHIFT                          30
> -#define CNTR2_REGION_EN_MASK                           (1 << 30)
> -#define CNTR2_CFG_SHIFT                                        16
> -#define CNTR2_CFG_MASK                                 (0xf << 16)
> -#define CNTR1_MCONNID_EN_SHIFT                         15
> -#define CNTR1_MCONNID_EN_MASK                          (1 << 15)
> -#define CNTR1_REGION_EN_SHIFT                          14
> -#define CNTR1_REGION_EN_MASK                           (1 << 14)
> -#define CNTR1_CFG_SHIFT                                        0
> -#define CNTR1_CFG_MASK                                 (0xf << 0)
> -
> -/* PERFORMANCE_COUNTER_MASTER_REGION_SELECT */
> -#define MCONNID2_SHIFT                                 24
> -#define MCONNID2_MASK                                  (0xff << 24)
> -#define REGION_SEL2_SHIFT                              16
> -#define REGION_SEL2_MASK                               (0x3 << 16)
> -#define MCONNID1_SHIFT                                 8
> -#define MCONNID1_MASK                                  (0xff << 8)
> -#define REGION_SEL1_SHIFT                              0
> -#define REGION_SEL1_MASK                               (0x3 << 0)
> -
> -/* PERFORMANCE_COUNTER_TIME */
> -#define TOTAL_TIME_SHIFT                               0
> -#define TOTAL_TIME_MASK                                        (0xffffffff << 0)
> -
> -/* DLL_CALIB_CTRL */
> -#define ACK_WAIT_SHIFT                                 16
> -#define ACK_WAIT_MASK                                  (0xf << 16)
> -#define DLL_CALIB_INTERVAL_SHIFT                       0
> -#define DLL_CALIB_INTERVAL_MASK                                (0x1ff << 0)
> -
> -/* END_OF_INTERRUPT */
> -#define EOI_SHIFT                                      0
> -#define EOI_MASK                                       (1 << 0)
> -
> -/* SYSTEM_OCP_INTERRUPT_RAW_STATUS */
> -#define DNV_SYS_SHIFT                                  2
> -#define DNV_SYS_MASK                                   (1 << 2)
> -#define TA_SYS_SHIFT                                   1
> -#define TA_SYS_MASK                                    (1 << 1)
> -#define ERR_SYS_SHIFT                                  0
> -#define ERR_SYS_MASK                                   (1 << 0)
> -
> -/* LOW_LATENCY_OCP_INTERRUPT_RAW_STATUS */
> -#define DNV_LL_SHIFT                                   2
> -#define DNV_LL_MASK                                    (1 << 2)
> -#define TA_LL_SHIFT                                    1
> -#define TA_LL_MASK                                     (1 << 1)
> -#define ERR_LL_SHIFT                                   0
> -#define ERR_LL_MASK                                    (1 << 0)
> -
> -/* SYSTEM_OCP_INTERRUPT_ENABLE_SET */
> -#define EN_DNV_SYS_SHIFT                               2
> -#define EN_DNV_SYS_MASK                                        (1 << 2)
> -#define EN_TA_SYS_SHIFT                                        1
> -#define EN_TA_SYS_MASK                                 (1 << 1)
> -#define EN_ERR_SYS_SHIFT                                       0
> -#define EN_ERR_SYS_MASK                                        (1 << 0)
> -
> -/* LOW_LATENCY_OCP_INTERRUPT_ENABLE_SET */
> -#define EN_DNV_LL_SHIFT                                        2
> -#define EN_DNV_LL_MASK                                 (1 << 2)
> -#define EN_TA_LL_SHIFT                                 1
> -#define EN_TA_LL_MASK                                  (1 << 1)
> -#define EN_ERR_LL_SHIFT                                        0
> -#define EN_ERR_LL_MASK                                 (1 << 0)
> -
> -/* SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG */
> -#define ZQ_CS1EN_SHIFT                                 31
> -#define ZQ_CS1EN_MASK                                  (1 << 31)
> -#define ZQ_CS0EN_SHIFT                                 30
> -#define ZQ_CS0EN_MASK                                  (1 << 30)
> -#define ZQ_DUALCALEN_SHIFT                             29
> -#define ZQ_DUALCALEN_MASK                              (1 << 29)
> -#define ZQ_SFEXITEN_SHIFT                              28
> -#define ZQ_SFEXITEN_MASK                               (1 << 28)
> -#define ZQ_ZQINIT_MULT_SHIFT                           18
> -#define ZQ_ZQINIT_MULT_MASK                            (0x3 << 18)
> -#define ZQ_ZQCL_MULT_SHIFT                             16
> -#define ZQ_ZQCL_MULT_MASK                              (0x3 << 16)
> -#define ZQ_REFINTERVAL_SHIFT                           0
> -#define ZQ_REFINTERVAL_MASK                            (0xffff << 0)
> -
> -/* TEMPERATURE_ALERT_CONFIG */
> -#define TA_CS1EN_SHIFT                                 31
> -#define TA_CS1EN_MASK                                  (1 << 31)
> -#define TA_CS0EN_SHIFT                                 30
> -#define TA_CS0EN_MASK                                  (1 << 30)
> -#define TA_SFEXITEN_SHIFT                              28
> -#define TA_SFEXITEN_MASK                               (1 << 28)
> -#define TA_DEVWDT_SHIFT                                        26
> -#define TA_DEVWDT_MASK                                 (0x3 << 26)
> -#define TA_DEVCNT_SHIFT                                        24
> -#define TA_DEVCNT_MASK                                 (0x3 << 24)
> -#define TA_REFINTERVAL_SHIFT                           0
> -#define TA_REFINTERVAL_MASK                            (0x3fffff << 0)
> -
> -/* OCP_ERROR_LOG */
> -#define MADDRSPACE_SHIFT                               14
> -#define MADDRSPACE_MASK                                        (0x3 << 14)
> -#define MBURSTSEQ_SHIFT                                        11
> -#define MBURSTSEQ_MASK                                 (0x7 << 11)
> -#define MCMD_SHIFT                                     8
> -#define MCMD_MASK                                      (0x7 << 8)
> -#define MCONNID_SHIFT                                  0
> -#define MCONNID_MASK                                   (0xff << 0)
> -
> -/* DDR_PHY_CTRL_1 - EMIF4D */
> -#define DLL_SLAVE_DLY_CTRL_SHIFT_4D                    4
> -#define DLL_SLAVE_DLY_CTRL_MASK_4D                     (0xFF << 4)
> -#define READ_LATENCY_SHIFT_4D                          0
> -#define READ_LATENCY_MASK_4D                           (0xf << 0)
> -
> -/* DDR_PHY_CTRL_1 - EMIF4D5 */
> -#define DLL_HALF_DELAY_SHIFT_4D5                       21
> -#define DLL_HALF_DELAY_MASK_4D5                                (1 << 21)
> -#define READ_LATENCY_SHIFT_4D5                         0
> -#define READ_LATENCY_MASK_4D5                          (0x1f << 0)
> -
> -/* DDR_PHY_CTRL_1_SHDW */
> -#define DDR_PHY_CTRL_1_SHDW_SHIFT                      5
> -#define DDR_PHY_CTRL_1_SHDW_MASK                       (0x7ffffff << 5)
> -#define READ_LATENCY_SHDW_SHIFT                                0
> -#define READ_LATENCY_SHDW_MASK                         (0x1f << 0)
> +#include <linux/ti_emif.h>
>
>  #ifndef __ASSEMBLY__
>  /*
> diff --git a/include/linux/ti_emif.h b/include/linux/ti_emif.h
> new file mode 100644
> index 0000000..be26e7f
> --- /dev/null
> +++ b/include/linux/ti_emif.h
> @@ -0,0 +1,558 @@
> +/*
> + * Register defines for the EMIF driver
> + *
> + * Copyright (C) 2012 Texas Instruments, Inc.
> + *
> + * Benoit Cousson (b-cousson@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.
> + */
> +#ifndef __TI_EMIF_H
> +#define __TI_EMIF_H
> +
> +/*
> + * Maximum number of different frequencies supported by EMIF driver
> + * Determines the number of entries in the pointer array for register
> + * cache
> + */
> +#define EMIF_MAX_NUM_FREQUENCIES                       6
> +
> +/* State of the core voltage */
> +#define DDR_VOLTAGE_STABLE                             0
> +#define DDR_VOLTAGE_RAMPING                            1
> +
> +/* Defines for timing De-rating */
> +#define EMIF_NORMAL_TIMINGS                            0
> +#define EMIF_DERATED_TIMINGS                           1
> +
> +/* Length of the forced read idle period in terms of cycles */
> +#define EMIF_READ_IDLE_LEN_VAL                         5
> +
> +/*
> + * forced read idle interval to be used when voltage
> + * is changed as part of DVFS/DPS - 1ms
> + */
> +#define READ_IDLE_INTERVAL_DVFS                                (1*1000000)
> +
> +/*
> + * Forced read idle interval to be used when voltage is stable
> + * 50us - or maximum value will do
> + */
> +#define READ_IDLE_INTERVAL_NORMAL                      (50*1000000)
> +
> +/* DLL calibration interval when voltage is NOT stable - 1us */
> +#define DLL_CALIB_INTERVAL_DVFS                                (1*1000000)
> +
> +#define DLL_CALIB_ACK_WAIT_VAL                         5
> +
> +/* Interval between ZQCS commands - hw team recommended value */
> +#define EMIF_ZQCS_INTERVAL_US                          (50*1000)
> +/* Enable ZQ Calibration on exiting Self-refresh */
> +#define ZQ_SFEXITEN_ENABLE                             1
> +/*
> + * ZQ Calibration simultaneously on both chip-selects:
> + * Needs one calibration resistor per CS
> + */
> +#define        ZQ_DUALCALEN_DISABLE                            0
> +#define        ZQ_DUALCALEN_ENABLE                             1
> +
> +#define T_ZQCS_DEFAULT_NS                              90
> +#define T_ZQCL_DEFAULT_NS                              360
> +#define T_ZQINIT_DEFAULT_NS                            1000
> +
> +/* DPD_EN */
> +#define DPD_DISABLE                                    0
> +#define DPD_ENABLE                                     1
> +
> +/*
> + * Default values for the low-power entry to be used if not provided by user.
> + * OMAP4/5 has a hw bug(i735) due to which this value can not be less than 512
> + * Timeout values are in DDR clock 'cycles' and frequency threshold in Hz
> + */
> +#define EMIF_LP_MODE_TIMEOUT_PERFORMANCE               2048
> +#define EMIF_LP_MODE_TIMEOUT_POWER                     512
> +#define EMIF_LP_MODE_FREQ_THRESHOLD                    400000000
> +
> +/* DDR_PHY_CTRL_1 values for EMIF4D - ATTILA PHY combination */
> +#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY         0x049FF000
> +#define EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY      0x41
> +#define EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY      0x80
> +#define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY 0xFF
> +
> +/* DDR_PHY_CTRL_1 values for EMIF4D5 INTELLIPHY combination */
> +#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY                0x0E084200
> +#define EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS      10000
> +
> +/* TEMP_ALERT_CONFIG - corresponding to temp gradient 5 C/s */
> +#define TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS            360
> +
> +#define EMIF_T_CSTA                                    3
> +#define EMIF_T_PDLL_UL                                 128
> +
> +/* External PHY control registers magic values */
> +#define EMIF_EXT_PHY_CTRL_1_VAL                                0x04020080
> +#define EMIF_EXT_PHY_CTRL_5_VAL                                0x04010040
> +#define EMIF_EXT_PHY_CTRL_6_VAL                                0x01004010
> +#define EMIF_EXT_PHY_CTRL_7_VAL                                0x00001004
> +#define EMIF_EXT_PHY_CTRL_8_VAL                                0x04010040
> +#define EMIF_EXT_PHY_CTRL_9_VAL                                0x01004010
> +#define EMIF_EXT_PHY_CTRL_10_VAL                       0x00001004
> +#define EMIF_EXT_PHY_CTRL_11_VAL                       0x00000000
> +#define EMIF_EXT_PHY_CTRL_12_VAL                       0x00000000
> +#define EMIF_EXT_PHY_CTRL_13_VAL                       0x00000000
> +#define EMIF_EXT_PHY_CTRL_14_VAL                       0x80080080
> +#define EMIF_EXT_PHY_CTRL_15_VAL                       0x00800800
> +#define EMIF_EXT_PHY_CTRL_16_VAL                       0x08102040
> +#define EMIF_EXT_PHY_CTRL_17_VAL                       0x00000001
> +#define EMIF_EXT_PHY_CTRL_18_VAL                       0x540A8150
> +#define EMIF_EXT_PHY_CTRL_19_VAL                       0xA81502A0
> +#define EMIF_EXT_PHY_CTRL_20_VAL                       0x002A0540
> +#define EMIF_EXT_PHY_CTRL_21_VAL                       0x00000000
> +#define EMIF_EXT_PHY_CTRL_22_VAL                       0x00000000
> +#define EMIF_EXT_PHY_CTRL_23_VAL                       0x00000000
> +#define EMIF_EXT_PHY_CTRL_24_VAL                       0x00000077
> +
> +#define EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS     1200
> +
> +/* Registers offset */
> +#define EMIF_MODULE_ID_AND_REVISION                    0x0000
> +#define EMIF_STATUS                                    0x0004
> +#define EMIF_SDRAM_CONFIG                              0x0008
> +#define EMIF_SDRAM_CONFIG_2                            0x000c
> +#define EMIF_SDRAM_REFRESH_CONTROL                     0x0010
> +#define EMIF_SDRAM_REFRESH_CTRL_SHDW                   0x0014
> +#define EMIF_SDRAM_TIMING_1                            0x0018
> +#define EMIF_SDRAM_TIMING_1_SHDW                       0x001c
> +#define EMIF_SDRAM_TIMING_2                            0x0020
> +#define EMIF_SDRAM_TIMING_2_SHDW                       0x0024
> +#define EMIF_SDRAM_TIMING_3                            0x0028
> +#define EMIF_SDRAM_TIMING_3_SHDW                       0x002c
> +#define EMIF_LPDDR2_NVM_TIMING                         0x0030
> +#define EMIF_LPDDR2_NVM_TIMING_SHDW                    0x0034
> +#define EMIF_POWER_MANAGEMENT_CONTROL                  0x0038
> +#define EMIF_POWER_MANAGEMENT_CTRL_SHDW                        0x003c
> +#define EMIF_LPDDR2_MODE_REG_DATA                      0x0040
> +#define EMIF_LPDDR2_MODE_REG_CONFIG                    0x0050
> +#define EMIF_OCP_CONFIG                                        0x0054
> +#define EMIF_OCP_CONFIG_VALUE_1                                0x0058
> +#define EMIF_OCP_CONFIG_VALUE_2                                0x005c
> +#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL           0x0060
> +#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT         0x0064
> +#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT      0x0068
> +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1       0x006c
> +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2       0x0070
> +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3       0x0074
> +#define EMIF_PERFORMANCE_COUNTER_1                     0x0080
> +#define EMIF_PERFORMANCE_COUNTER_2                     0x0084
> +#define EMIF_PERFORMANCE_COUNTER_CONFIG                        0x0088
> +#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT  0x008c
> +#define EMIF_PERFORMANCE_COUNTER_TIME                  0x0090
> +#define EMIF_MISC_REG                                  0x0094
> +#define EMIF_DLL_CALIB_CTRL                            0x0098
> +#define EMIF_DLL_CALIB_CTRL_SHDW                       0x009c
> +#define EMIF_END_OF_INTERRUPT                          0x00a0
> +#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS           0x00a4
> +#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS               0x00a8
> +#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS               0x00ac
> +#define EMIF_LL_OCP_INTERRUPT_STATUS                   0x00b0
> +#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET           0x00b4
> +#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET               0x00b8
> +#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR         0x00bc
> +#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR             0x00c0
> +#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG 0x00c8
> +#define EMIF_TEMPERATURE_ALERT_CONFIG                  0x00cc
> +#define EMIF_OCP_ERROR_LOG                             0x00d0
> +#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW           0x00d4
> +#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL          0x00d8
> +#define EMIF_READ_WRITE_LEVELING_CONTROL               0x00dc
> +#define EMIF_DDR_PHY_CTRL_1                            0x00e4
> +#define EMIF_DDR_PHY_CTRL_1_SHDW                       0x00e8
> +#define EMIF_DDR_PHY_CTRL_2                            0x00ec
> +#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING      0x0100
> +#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104
> +#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108
> +#define EMIF_READ_WRITE_EXECUTION_THRESHOLD            0x0120
> +#define EMIF_COS_CONFIG                                        0x0124
> +#define EMIF_PHY_STATUS_1                              0x0140
> +#define EMIF_PHY_STATUS_2                              0x0144
> +#define EMIF_PHY_STATUS_3                              0x0148
> +#define EMIF_PHY_STATUS_4                              0x014c
> +#define EMIF_PHY_STATUS_5                              0x0150
> +#define EMIF_PHY_STATUS_6                              0x0154
> +#define EMIF_PHY_STATUS_7                              0x0158
> +#define EMIF_PHY_STATUS_8                              0x015c
> +#define EMIF_PHY_STATUS_9                              0x0160
> +#define EMIF_PHY_STATUS_10                             0x0164
> +#define EMIF_PHY_STATUS_11                             0x0168
> +#define EMIF_PHY_STATUS_12                             0x016c
> +#define EMIF_PHY_STATUS_13                             0x0170
> +#define EMIF_PHY_STATUS_14                             0x0174
> +#define EMIF_PHY_STATUS_15                             0x0178
> +#define EMIF_PHY_STATUS_16                             0x017c
> +#define EMIF_PHY_STATUS_17                             0x0180
> +#define EMIF_PHY_STATUS_18                             0x0184
> +#define EMIF_PHY_STATUS_19                             0x0188
> +#define EMIF_PHY_STATUS_20                             0x018c
> +#define EMIF_PHY_STATUS_21                             0x0190
> +#define EMIF_EXT_PHY_CTRL_1                            0x0200
> +#define EMIF_EXT_PHY_CTRL_1_SHDW                       0x0204
> +#define EMIF_EXT_PHY_CTRL_2                            0x0208
> +#define EMIF_EXT_PHY_CTRL_2_SHDW                       0x020c
> +#define EMIF_EXT_PHY_CTRL_3                            0x0210
> +#define EMIF_EXT_PHY_CTRL_3_SHDW                       0x0214
> +#define EMIF_EXT_PHY_CTRL_4                            0x0218
> +#define EMIF_EXT_PHY_CTRL_4_SHDW                       0x021c
> +#define EMIF_EXT_PHY_CTRL_5                            0x0220
> +#define EMIF_EXT_PHY_CTRL_5_SHDW                       0x0224
> +#define EMIF_EXT_PHY_CTRL_6                            0x0228
> +#define EMIF_EXT_PHY_CTRL_6_SHDW                       0x022c
> +#define EMIF_EXT_PHY_CTRL_7                            0x0230
> +#define EMIF_EXT_PHY_CTRL_7_SHDW                       0x0234
> +#define EMIF_EXT_PHY_CTRL_8                            0x0238
> +#define EMIF_EXT_PHY_CTRL_8_SHDW                       0x023c
> +#define EMIF_EXT_PHY_CTRL_9                            0x0240
> +#define EMIF_EXT_PHY_CTRL_9_SHDW                       0x0244
> +#define EMIF_EXT_PHY_CTRL_10                           0x0248
> +#define EMIF_EXT_PHY_CTRL_10_SHDW                      0x024c
> +#define EMIF_EXT_PHY_CTRL_11                           0x0250
> +#define EMIF_EXT_PHY_CTRL_11_SHDW                      0x0254
> +#define EMIF_EXT_PHY_CTRL_12                           0x0258
> +#define EMIF_EXT_PHY_CTRL_12_SHDW                      0x025c
> +#define EMIF_EXT_PHY_CTRL_13                           0x0260
> +#define EMIF_EXT_PHY_CTRL_13_SHDW                      0x0264
> +#define EMIF_EXT_PHY_CTRL_14                           0x0268
> +#define EMIF_EXT_PHY_CTRL_14_SHDW                      0x026c
> +#define EMIF_EXT_PHY_CTRL_15                           0x0270
> +#define EMIF_EXT_PHY_CTRL_15_SHDW                      0x0274
> +#define EMIF_EXT_PHY_CTRL_16                           0x0278
> +#define EMIF_EXT_PHY_CTRL_16_SHDW                      0x027c
> +#define EMIF_EXT_PHY_CTRL_17                           0x0280
> +#define EMIF_EXT_PHY_CTRL_17_SHDW                      0x0284
> +#define EMIF_EXT_PHY_CTRL_18                           0x0288
> +#define EMIF_EXT_PHY_CTRL_18_SHDW                      0x028c
> +#define EMIF_EXT_PHY_CTRL_19                           0x0290
> +#define EMIF_EXT_PHY_CTRL_19_SHDW                      0x0294
> +#define EMIF_EXT_PHY_CTRL_20                           0x0298
> +#define EMIF_EXT_PHY_CTRL_20_SHDW                      0x029c
> +#define EMIF_EXT_PHY_CTRL_21                           0x02a0
> +#define EMIF_EXT_PHY_CTRL_21_SHDW                      0x02a4
> +#define EMIF_EXT_PHY_CTRL_22                           0x02a8
> +#define EMIF_EXT_PHY_CTRL_22_SHDW                      0x02ac
> +#define EMIF_EXT_PHY_CTRL_23                           0x02b0
> +#define EMIF_EXT_PHY_CTRL_23_SHDW                      0x02b4
> +#define EMIF_EXT_PHY_CTRL_24                           0x02b8
> +#define EMIF_EXT_PHY_CTRL_24_SHDW                      0x02bc
> +#define EMIF_EXT_PHY_CTRL_25                           0x02c0
> +#define EMIF_EXT_PHY_CTRL_25_SHDW                      0x02c4
> +#define EMIF_EXT_PHY_CTRL_26                           0x02c8
> +#define EMIF_EXT_PHY_CTRL_26_SHDW                      0x02cc
> +#define EMIF_EXT_PHY_CTRL_27                           0x02d0
> +#define EMIF_EXT_PHY_CTRL_27_SHDW                      0x02d4
> +#define EMIF_EXT_PHY_CTRL_28                           0x02d8
> +#define EMIF_EXT_PHY_CTRL_28_SHDW                      0x02dc
> +#define EMIF_EXT_PHY_CTRL_29                           0x02e0
> +#define EMIF_EXT_PHY_CTRL_29_SHDW                      0x02e4
> +#define EMIF_EXT_PHY_CTRL_30                           0x02e8
> +#define EMIF_EXT_PHY_CTRL_30_SHDW                      0x02ec
> +
> +/* Registers shifts and masks */
> +
> +/* EMIF_MODULE_ID_AND_REVISION */
> +#define SCHEME_SHIFT                                   30
> +#define SCHEME_MASK                                    (0x3 << 30)
> +#define MODULE_ID_SHIFT                                        16
> +#define MODULE_ID_MASK                                 (0xfff << 16)
> +#define RTL_VERSION_SHIFT                              11
> +#define RTL_VERSION_MASK                               (0x1f << 11)
> +#define MAJOR_REVISION_SHIFT                           8
> +#define MAJOR_REVISION_MASK                            (0x7 << 8)
> +#define MINOR_REVISION_SHIFT                           0
> +#define MINOR_REVISION_MASK                            (0x3f << 0)
> +
> +/* STATUS */
> +#define BE_SHIFT                                       31
> +#define BE_MASK                                                (1 << 31)
> +#define DUAL_CLK_MODE_SHIFT                            30
> +#define DUAL_CLK_MODE_MASK                             (1 << 30)
> +#define FAST_INIT_SHIFT                                        29
> +#define FAST_INIT_MASK                                 (1 << 29)
> +#define RDLVLGATETO_SHIFT                              6
> +#define RDLVLGATETO_MASK                               (1 << 6)
> +#define RDLVLTO_SHIFT                                  5
> +#define RDLVLTO_MASK                                   (1 << 5)
> +#define WRLVLTO_SHIFT                                  4
> +#define WRLVLTO_MASK                                   (1 << 4)
> +#define PHY_DLL_READY_SHIFT                            2
> +#define PHY_DLL_READY_MASK                             (1 << 2)
> +
> +/* SDRAM_CONFIG */
> +#define SDRAM_TYPE_SHIFT                               29
> +#define SDRAM_TYPE_MASK                                        (0x7 << 29)
> +#define IBANK_POS_SHIFT                                        27
> +#define IBANK_POS_MASK                                 (0x3 << 27)
> +#define DDR_TERM_SHIFT                                 24
> +#define DDR_TERM_MASK                                  (0x7 << 24)
> +#define DDR2_DDQS_SHIFT                                        23
> +#define DDR2_DDQS_MASK                                 (1 << 23)
> +#define DYN_ODT_SHIFT                                  21
> +#define DYN_ODT_MASK                                   (0x3 << 21)
> +#define DDR_DISABLE_DLL_SHIFT                          20
> +#define DDR_DISABLE_DLL_MASK                           (1 << 20)
> +#define SDRAM_DRIVE_SHIFT                              18
> +#define SDRAM_DRIVE_MASK                               (0x3 << 18)
> +#define CWL_SHIFT                                      16
> +#define CWL_MASK                                       (0x3 << 16)
> +#define NARROW_MODE_SHIFT                              14
> +#define NARROW_MODE_MASK                               (0x3 << 14)
> +#define CL_SHIFT                                       10
> +#define CL_MASK                                                (0xf << 10)
> +#define ROWSIZE_SHIFT                                  7
> +#define ROWSIZE_MASK                                   (0x7 << 7)
> +#define IBANK_SHIFT                                    4
> +#define IBANK_MASK                                     (0x7 << 4)
> +#define EBANK_SHIFT                                    3
> +#define EBANK_MASK                                     (1 << 3)
> +#define PAGESIZE_SHIFT                                 0
> +#define PAGESIZE_MASK                                  (0x7 << 0)
> +
> +/* SDRAM_CONFIG_2 */
> +#define CS1NVMEN_SHIFT                                 30
> +#define CS1NVMEN_MASK                                  (1 << 30)
> +#define EBANK_POS_SHIFT                                        27
> +#define EBANK_POS_MASK                                 (1 << 27)
> +#define RDBNUM_SHIFT                                   4
> +#define RDBNUM_MASK                                    (0x3 << 4)
> +#define RDBSIZE_SHIFT                                  0
> +#define RDBSIZE_MASK                                   (0x7 << 0)
> +
> +/* SDRAM_REFRESH_CONTROL */
> +#define INITREF_DIS_SHIFT                              31
> +#define INITREF_DIS_MASK                               (1 << 31)
> +#define SRT_SHIFT                                      29
> +#define SRT_MASK                                       (1 << 29)
> +#define ASR_SHIFT                                      28
> +#define ASR_MASK                                       (1 << 28)
> +#define PASR_SHIFT                                     24
> +#define PASR_MASK                                      (0x7 << 24)
> +#define REFRESH_RATE_SHIFT                             0
> +#define REFRESH_RATE_MASK                              (0xffff << 0)
> +
> +/* SDRAM_TIMING_1 */
> +#define T_RTW_SHIFT                                    29
> +#define T_RTW_MASK                                     (0x7 << 29)
> +#define T_RP_SHIFT                                     25
> +#define T_RP_MASK                                      (0xf << 25)
> +#define T_RCD_SHIFT                                    21
> +#define T_RCD_MASK                                     (0xf << 21)
> +#define T_WR_SHIFT                                     17
> +#define T_WR_MASK                                      (0xf << 17)
> +#define T_RAS_SHIFT                                    12
> +#define T_RAS_MASK                                     (0x1f << 12)
> +#define T_RC_SHIFT                                     6
> +#define T_RC_MASK                                      (0x3f << 6)
> +#define T_RRD_SHIFT                                    3
> +#define T_RRD_MASK                                     (0x7 << 3)
> +#define T_WTR_SHIFT                                    0
> +#define T_WTR_MASK                                     (0x7 << 0)
> +
> +/* SDRAM_TIMING_2 */
> +#define T_XP_SHIFT                                     28
> +#define T_XP_MASK                                      (0x7 << 28)
> +#define T_ODT_SHIFT                                    25
> +#define T_ODT_MASK                                     (0x7 << 25)
> +#define T_XSNR_SHIFT                                   16
> +#define T_XSNR_MASK                                    (0x1ff << 16)
> +#define T_XSRD_SHIFT                                   6
> +#define T_XSRD_MASK                                    (0x3ff << 6)
> +#define T_RTP_SHIFT                                    3
> +#define T_RTP_MASK                                     (0x7 << 3)
> +#define T_CKE_SHIFT                                    0
> +#define T_CKE_MASK                                     (0x7 << 0)
> +
> +/* SDRAM_TIMING_3 */
> +#define T_PDLL_UL_SHIFT                                        28
> +#define T_PDLL_UL_MASK                                 (0xf << 28)
> +#define T_CSTA_SHIFT                                   24
> +#define T_CSTA_MASK                                    (0xf << 24)
> +#define T_CKESR_SHIFT                                  21
> +#define T_CKESR_MASK                                   (0x7 << 21)
> +#define ZQ_ZQCS_SHIFT                                  15
> +#define ZQ_ZQCS_MASK                                   (0x3f << 15)
> +#define T_TDQSCKMAX_SHIFT                              13
> +#define T_TDQSCKMAX_MASK                               (0x3 << 13)
> +#define T_RFC_SHIFT                                    4
> +#define T_RFC_MASK                                     (0x1ff << 4)
> +#define T_RAS_MAX_SHIFT                                        0
> +#define T_RAS_MAX_MASK                                 (0xf << 0)
> +
> +/* POWER_MANAGEMENT_CONTROL */
> +#define PD_TIM_SHIFT                                   12
> +#define PD_TIM_MASK                                    (0xf << 12)
> +#define DPD_EN_SHIFT                                   11
> +#define DPD_EN_MASK                                    (1 << 11)
> +#define LP_MODE_SHIFT                                  8
> +#define LP_MODE_MASK                                   (0x7 << 8)
> +#define SR_TIM_SHIFT                                   4
> +#define SR_TIM_MASK                                    (0xf << 4)
> +#define CS_TIM_SHIFT                                   0
> +#define CS_TIM_MASK                                    (0xf << 0)
> +
> +/* LPDDR2_MODE_REG_DATA */
> +#define VALUE_0_SHIFT                                  0
> +#define VALUE_0_MASK                                   (0x7f << 0)
> +
> +/* LPDDR2_MODE_REG_CONFIG */
> +#define CS_SHIFT                                       31
> +#define CS_MASK                                                (1 << 31)
> +#define REFRESH_EN_SHIFT                               30
> +#define REFRESH_EN_MASK                                        (1 << 30)
> +#define ADDRESS_SHIFT                                  0
> +#define ADDRESS_MASK                                   (0xff << 0)
> +
> +/* OCP_CONFIG */
> +#define SYS_THRESH_MAX_SHIFT                           24
> +#define SYS_THRESH_MAX_MASK                            (0xf << 24)
> +#define MPU_THRESH_MAX_SHIFT                           20
> +#define MPU_THRESH_MAX_MASK                            (0xf << 20)
> +#define LL_THRESH_MAX_SHIFT                            16
> +#define LL_THRESH_MAX_MASK                             (0xf << 16)
> +
> +/* PERFORMANCE_COUNTER_1 */
> +#define COUNTER1_SHIFT                                 0
> +#define COUNTER1_MASK                                  (0xffffffff << 0)
> +
> +/* PERFORMANCE_COUNTER_2 */
> +#define COUNTER2_SHIFT                                 0
> +#define COUNTER2_MASK                                  (0xffffffff << 0)
> +
> +/* PERFORMANCE_COUNTER_CONFIG */
> +#define CNTR2_MCONNID_EN_SHIFT                         31
> +#define CNTR2_MCONNID_EN_MASK                          (1 << 31)
> +#define CNTR2_REGION_EN_SHIFT                          30
> +#define CNTR2_REGION_EN_MASK                           (1 << 30)
> +#define CNTR2_CFG_SHIFT                                        16
> +#define CNTR2_CFG_MASK                                 (0xf << 16)
> +#define CNTR1_MCONNID_EN_SHIFT                         15
> +#define CNTR1_MCONNID_EN_MASK                          (1 << 15)
> +#define CNTR1_REGION_EN_SHIFT                          14
> +#define CNTR1_REGION_EN_MASK                           (1 << 14)
> +#define CNTR1_CFG_SHIFT                                        0
> +#define CNTR1_CFG_MASK                                 (0xf << 0)
> +
> +/* PERFORMANCE_COUNTER_MASTER_REGION_SELECT */
> +#define MCONNID2_SHIFT                                 24
> +#define MCONNID2_MASK                                  (0xff << 24)
> +#define REGION_SEL2_SHIFT                              16
> +#define REGION_SEL2_MASK                               (0x3 << 16)
> +#define MCONNID1_SHIFT                                 8
> +#define MCONNID1_MASK                                  (0xff << 8)
> +#define REGION_SEL1_SHIFT                              0
> +#define REGION_SEL1_MASK                               (0x3 << 0)
> +
> +/* PERFORMANCE_COUNTER_TIME */
> +#define TOTAL_TIME_SHIFT                               0
> +#define TOTAL_TIME_MASK                                        (0xffffffff << 0)
> +
> +/* DLL_CALIB_CTRL */
> +#define ACK_WAIT_SHIFT                                 16
> +#define ACK_WAIT_MASK                                  (0xf << 16)
> +#define DLL_CALIB_INTERVAL_SHIFT                       0
> +#define DLL_CALIB_INTERVAL_MASK                                (0x1ff << 0)
> +
> +/* END_OF_INTERRUPT */
> +#define EOI_SHIFT                                      0
> +#define EOI_MASK                                       (1 << 0)
> +
> +/* SYSTEM_OCP_INTERRUPT_RAW_STATUS */
> +#define DNV_SYS_SHIFT                                  2
> +#define DNV_SYS_MASK                                   (1 << 2)
> +#define TA_SYS_SHIFT                                   1
> +#define TA_SYS_MASK                                    (1 << 1)
> +#define ERR_SYS_SHIFT                                  0
> +#define ERR_SYS_MASK                                   (1 << 0)
> +
> +/* LOW_LATENCY_OCP_INTERRUPT_RAW_STATUS */
> +#define DNV_LL_SHIFT                                   2
> +#define DNV_LL_MASK                                    (1 << 2)
> +#define TA_LL_SHIFT                                    1
> +#define TA_LL_MASK                                     (1 << 1)
> +#define ERR_LL_SHIFT                                   0
> +#define ERR_LL_MASK                                    (1 << 0)
> +
> +/* SYSTEM_OCP_INTERRUPT_ENABLE_SET */
> +#define EN_DNV_SYS_SHIFT                               2
> +#define EN_DNV_SYS_MASK                                        (1 << 2)
> +#define EN_TA_SYS_SHIFT                                        1
> +#define EN_TA_SYS_MASK                                 (1 << 1)
> +#define EN_ERR_SYS_SHIFT                                       0
> +#define EN_ERR_SYS_MASK                                        (1 << 0)
> +
> +/* LOW_LATENCY_OCP_INTERRUPT_ENABLE_SET */
> +#define EN_DNV_LL_SHIFT                                        2
> +#define EN_DNV_LL_MASK                                 (1 << 2)
> +#define EN_TA_LL_SHIFT                                 1
> +#define EN_TA_LL_MASK                                  (1 << 1)
> +#define EN_ERR_LL_SHIFT                                        0
> +#define EN_ERR_LL_MASK                                 (1 << 0)
> +
> +/* SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG */
> +#define ZQ_CS1EN_SHIFT                                 31
> +#define ZQ_CS1EN_MASK                                  (1 << 31)
> +#define ZQ_CS0EN_SHIFT                                 30
> +#define ZQ_CS0EN_MASK                                  (1 << 30)
> +#define ZQ_DUALCALEN_SHIFT                             29
> +#define ZQ_DUALCALEN_MASK                              (1 << 29)
> +#define ZQ_SFEXITEN_SHIFT                              28
> +#define ZQ_SFEXITEN_MASK                               (1 << 28)
> +#define ZQ_ZQINIT_MULT_SHIFT                           18
> +#define ZQ_ZQINIT_MULT_MASK                            (0x3 << 18)
> +#define ZQ_ZQCL_MULT_SHIFT                             16
> +#define ZQ_ZQCL_MULT_MASK                              (0x3 << 16)
> +#define ZQ_REFINTERVAL_SHIFT                           0
> +#define ZQ_REFINTERVAL_MASK                            (0xffff << 0)
> +
> +/* TEMPERATURE_ALERT_CONFIG */
> +#define TA_CS1EN_SHIFT                                 31
> +#define TA_CS1EN_MASK                                  (1 << 31)
> +#define TA_CS0EN_SHIFT                                 30
> +#define TA_CS0EN_MASK                                  (1 << 30)
> +#define TA_SFEXITEN_SHIFT                              28
> +#define TA_SFEXITEN_MASK                               (1 << 28)
> +#define TA_DEVWDT_SHIFT                                        26
> +#define TA_DEVWDT_MASK                                 (0x3 << 26)
> +#define TA_DEVCNT_SHIFT                                        24
> +#define TA_DEVCNT_MASK                                 (0x3 << 24)
> +#define TA_REFINTERVAL_SHIFT                           0
> +#define TA_REFINTERVAL_MASK                            (0x3fffff << 0)
> +
> +/* OCP_ERROR_LOG */
> +#define MADDRSPACE_SHIFT                               14
> +#define MADDRSPACE_MASK                                        (0x3 << 14)
> +#define MBURSTSEQ_SHIFT                                        11
> +#define MBURSTSEQ_MASK                                 (0x7 << 11)
> +#define MCMD_SHIFT                                     8
> +#define MCMD_MASK                                      (0x7 << 8)
> +#define MCONNID_SHIFT                                  0
> +#define MCONNID_MASK                                   (0xff << 0)
> +
> +/* DDR_PHY_CTRL_1 - EMIF4D */
> +#define DLL_SLAVE_DLY_CTRL_SHIFT_4D                    4
> +#define DLL_SLAVE_DLY_CTRL_MASK_4D                     (0xFF << 4)
> +#define READ_LATENCY_SHIFT_4D                          0
> +#define READ_LATENCY_MASK_4D                           (0xf << 0)
> +
> +/* DDR_PHY_CTRL_1 - EMIF4D5 */
> +#define DLL_HALF_DELAY_SHIFT_4D5                       21
> +#define DLL_HALF_DELAY_MASK_4D5                                (1 << 21)
> +#define READ_LATENCY_SHIFT_4D5                         0
> +#define READ_LATENCY_MASK_4D5                          (0x1f << 0)
> +
> +/* DDR_PHY_CTRL_1_SHDW */
> +#define DDR_PHY_CTRL_1_SHDW_SHIFT                      5
> +#define DDR_PHY_CTRL_1_SHDW_MASK                       (0x7ffffff << 5)
> +#define READ_LATENCY_SHDW_SHIFT                                0
> +#define READ_LATENCY_SHDW_MASK                         (0x1f << 0)
> +
> +#endif /* __TI_EMIF_H */
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 1/9] memory: emif: Move EMIF register defines to include/linux/
@ 2013-08-08  0:48     ` Russ Dill
  0 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08  0:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> OMAP4 and AM33XX share the same EMIF controller IP. Although there
> are significant differences in the IP integration due to which
> AM33XX can't reuse the EMIF driver DVFS similar to OMAP4,
> it can definitely benefit by reusing the EMIF related macros
> defined in drivers/memory/emif.h.
>
> In the current OMAP PM framework the PM code resides under
> arch/arm/mach-omap2/. To enable reuse of the register defines move
> the register defines in the emif header file to include/linux so that
> both the EMIF driver and the AM33XX PM code can benefit.
>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Benoit Cousson <benoit.cousson@linaro.org>
> Cc: Aneesh V <aneesh@ti.com>

Reviewed-by: Russ Dill <russ.dill@ti.com>

> ---
>  drivers/memory/emif.h   |  543 +--------------------------------------------
>  include/linux/ti_emif.h |  558 +++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 559 insertions(+), 542 deletions(-)
>  create mode 100644 include/linux/ti_emif.h
>
> diff --git a/drivers/memory/emif.h b/drivers/memory/emif.h
> index bfe08ba..8214f07 100644
> --- a/drivers/memory/emif.h
> +++ b/drivers/memory/emif.h
> @@ -12,548 +12,7 @@
>  #ifndef __EMIF_H
>  #define __EMIF_H
>
> -/*
> - * Maximum number of different frequencies supported by EMIF driver
> - * Determines the number of entries in the pointer array for register
> - * cache
> - */
> -#define EMIF_MAX_NUM_FREQUENCIES                       6
> -
> -/* State of the core voltage */
> -#define DDR_VOLTAGE_STABLE                             0
> -#define DDR_VOLTAGE_RAMPING                            1
> -
> -/* Defines for timing De-rating */
> -#define EMIF_NORMAL_TIMINGS                            0
> -#define EMIF_DERATED_TIMINGS                           1
> -
> -/* Length of the forced read idle period in terms of cycles */
> -#define EMIF_READ_IDLE_LEN_VAL                         5
> -
> -/*
> - * forced read idle interval to be used when voltage
> - * is changed as part of DVFS/DPS - 1ms
> - */
> -#define READ_IDLE_INTERVAL_DVFS                                (1*1000000)
> -
> -/*
> - * Forced read idle interval to be used when voltage is stable
> - * 50us - or maximum value will do
> - */
> -#define READ_IDLE_INTERVAL_NORMAL                      (50*1000000)
> -
> -/* DLL calibration interval when voltage is NOT stable - 1us */
> -#define DLL_CALIB_INTERVAL_DVFS                                (1*1000000)
> -
> -#define DLL_CALIB_ACK_WAIT_VAL                         5
> -
> -/* Interval between ZQCS commands - hw team recommended value */
> -#define EMIF_ZQCS_INTERVAL_US                          (50*1000)
> -/* Enable ZQ Calibration on exiting Self-refresh */
> -#define ZQ_SFEXITEN_ENABLE                             1
> -/*
> - * ZQ Calibration simultaneously on both chip-selects:
> - * Needs one calibration resistor per CS
> - */
> -#define        ZQ_DUALCALEN_DISABLE                            0
> -#define        ZQ_DUALCALEN_ENABLE                             1
> -
> -#define T_ZQCS_DEFAULT_NS                              90
> -#define T_ZQCL_DEFAULT_NS                              360
> -#define T_ZQINIT_DEFAULT_NS                            1000
> -
> -/* DPD_EN */
> -#define DPD_DISABLE                                    0
> -#define DPD_ENABLE                                     1
> -
> -/*
> - * Default values for the low-power entry to be used if not provided by user.
> - * OMAP4/5 has a hw bug(i735) due to which this value can not be less than 512
> - * Timeout values are in DDR clock 'cycles' and frequency threshold in Hz
> - */
> -#define EMIF_LP_MODE_TIMEOUT_PERFORMANCE               2048
> -#define EMIF_LP_MODE_TIMEOUT_POWER                     512
> -#define EMIF_LP_MODE_FREQ_THRESHOLD                    400000000
> -
> -/* DDR_PHY_CTRL_1 values for EMIF4D - ATTILA PHY combination */
> -#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY         0x049FF000
> -#define EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY      0x41
> -#define EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY      0x80
> -#define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY 0xFF
> -
> -/* DDR_PHY_CTRL_1 values for EMIF4D5 INTELLIPHY combination */
> -#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY                0x0E084200
> -#define EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS      10000
> -
> -/* TEMP_ALERT_CONFIG - corresponding to temp gradient 5 C/s */
> -#define TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS            360
> -
> -#define EMIF_T_CSTA                                    3
> -#define EMIF_T_PDLL_UL                                 128
> -
> -/* External PHY control registers magic values */
> -#define EMIF_EXT_PHY_CTRL_1_VAL                                0x04020080
> -#define EMIF_EXT_PHY_CTRL_5_VAL                                0x04010040
> -#define EMIF_EXT_PHY_CTRL_6_VAL                                0x01004010
> -#define EMIF_EXT_PHY_CTRL_7_VAL                                0x00001004
> -#define EMIF_EXT_PHY_CTRL_8_VAL                                0x04010040
> -#define EMIF_EXT_PHY_CTRL_9_VAL                                0x01004010
> -#define EMIF_EXT_PHY_CTRL_10_VAL                       0x00001004
> -#define EMIF_EXT_PHY_CTRL_11_VAL                       0x00000000
> -#define EMIF_EXT_PHY_CTRL_12_VAL                       0x00000000
> -#define EMIF_EXT_PHY_CTRL_13_VAL                       0x00000000
> -#define EMIF_EXT_PHY_CTRL_14_VAL                       0x80080080
> -#define EMIF_EXT_PHY_CTRL_15_VAL                       0x00800800
> -#define EMIF_EXT_PHY_CTRL_16_VAL                       0x08102040
> -#define EMIF_EXT_PHY_CTRL_17_VAL                       0x00000001
> -#define EMIF_EXT_PHY_CTRL_18_VAL                       0x540A8150
> -#define EMIF_EXT_PHY_CTRL_19_VAL                       0xA81502A0
> -#define EMIF_EXT_PHY_CTRL_20_VAL                       0x002A0540
> -#define EMIF_EXT_PHY_CTRL_21_VAL                       0x00000000
> -#define EMIF_EXT_PHY_CTRL_22_VAL                       0x00000000
> -#define EMIF_EXT_PHY_CTRL_23_VAL                       0x00000000
> -#define EMIF_EXT_PHY_CTRL_24_VAL                       0x00000077
> -
> -#define EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS     1200
> -
> -/* Registers offset */
> -#define EMIF_MODULE_ID_AND_REVISION                    0x0000
> -#define EMIF_STATUS                                    0x0004
> -#define EMIF_SDRAM_CONFIG                              0x0008
> -#define EMIF_SDRAM_CONFIG_2                            0x000c
> -#define EMIF_SDRAM_REFRESH_CONTROL                     0x0010
> -#define EMIF_SDRAM_REFRESH_CTRL_SHDW                   0x0014
> -#define EMIF_SDRAM_TIMING_1                            0x0018
> -#define EMIF_SDRAM_TIMING_1_SHDW                       0x001c
> -#define EMIF_SDRAM_TIMING_2                            0x0020
> -#define EMIF_SDRAM_TIMING_2_SHDW                       0x0024
> -#define EMIF_SDRAM_TIMING_3                            0x0028
> -#define EMIF_SDRAM_TIMING_3_SHDW                       0x002c
> -#define EMIF_LPDDR2_NVM_TIMING                         0x0030
> -#define EMIF_LPDDR2_NVM_TIMING_SHDW                    0x0034
> -#define EMIF_POWER_MANAGEMENT_CONTROL                  0x0038
> -#define EMIF_POWER_MANAGEMENT_CTRL_SHDW                        0x003c
> -#define EMIF_LPDDR2_MODE_REG_DATA                      0x0040
> -#define EMIF_LPDDR2_MODE_REG_CONFIG                    0x0050
> -#define EMIF_OCP_CONFIG                                        0x0054
> -#define EMIF_OCP_CONFIG_VALUE_1                                0x0058
> -#define EMIF_OCP_CONFIG_VALUE_2                                0x005c
> -#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL           0x0060
> -#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT         0x0064
> -#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT      0x0068
> -#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1       0x006c
> -#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2       0x0070
> -#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3       0x0074
> -#define EMIF_PERFORMANCE_COUNTER_1                     0x0080
> -#define EMIF_PERFORMANCE_COUNTER_2                     0x0084
> -#define EMIF_PERFORMANCE_COUNTER_CONFIG                        0x0088
> -#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT  0x008c
> -#define EMIF_PERFORMANCE_COUNTER_TIME                  0x0090
> -#define EMIF_MISC_REG                                  0x0094
> -#define EMIF_DLL_CALIB_CTRL                            0x0098
> -#define EMIF_DLL_CALIB_CTRL_SHDW                       0x009c
> -#define EMIF_END_OF_INTERRUPT                          0x00a0
> -#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS           0x00a4
> -#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS               0x00a8
> -#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS               0x00ac
> -#define EMIF_LL_OCP_INTERRUPT_STATUS                   0x00b0
> -#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET           0x00b4
> -#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET               0x00b8
> -#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR         0x00bc
> -#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR             0x00c0
> -#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG 0x00c8
> -#define EMIF_TEMPERATURE_ALERT_CONFIG                  0x00cc
> -#define EMIF_OCP_ERROR_LOG                             0x00d0
> -#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW           0x00d4
> -#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL          0x00d8
> -#define EMIF_READ_WRITE_LEVELING_CONTROL               0x00dc
> -#define EMIF_DDR_PHY_CTRL_1                            0x00e4
> -#define EMIF_DDR_PHY_CTRL_1_SHDW                       0x00e8
> -#define EMIF_DDR_PHY_CTRL_2                            0x00ec
> -#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING      0x0100
> -#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104
> -#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108
> -#define EMIF_READ_WRITE_EXECUTION_THRESHOLD            0x0120
> -#define EMIF_COS_CONFIG                                        0x0124
> -#define EMIF_PHY_STATUS_1                              0x0140
> -#define EMIF_PHY_STATUS_2                              0x0144
> -#define EMIF_PHY_STATUS_3                              0x0148
> -#define EMIF_PHY_STATUS_4                              0x014c
> -#define EMIF_PHY_STATUS_5                              0x0150
> -#define EMIF_PHY_STATUS_6                              0x0154
> -#define EMIF_PHY_STATUS_7                              0x0158
> -#define EMIF_PHY_STATUS_8                              0x015c
> -#define EMIF_PHY_STATUS_9                              0x0160
> -#define EMIF_PHY_STATUS_10                             0x0164
> -#define EMIF_PHY_STATUS_11                             0x0168
> -#define EMIF_PHY_STATUS_12                             0x016c
> -#define EMIF_PHY_STATUS_13                             0x0170
> -#define EMIF_PHY_STATUS_14                             0x0174
> -#define EMIF_PHY_STATUS_15                             0x0178
> -#define EMIF_PHY_STATUS_16                             0x017c
> -#define EMIF_PHY_STATUS_17                             0x0180
> -#define EMIF_PHY_STATUS_18                             0x0184
> -#define EMIF_PHY_STATUS_19                             0x0188
> -#define EMIF_PHY_STATUS_20                             0x018c
> -#define EMIF_PHY_STATUS_21                             0x0190
> -#define EMIF_EXT_PHY_CTRL_1                            0x0200
> -#define EMIF_EXT_PHY_CTRL_1_SHDW                       0x0204
> -#define EMIF_EXT_PHY_CTRL_2                            0x0208
> -#define EMIF_EXT_PHY_CTRL_2_SHDW                       0x020c
> -#define EMIF_EXT_PHY_CTRL_3                            0x0210
> -#define EMIF_EXT_PHY_CTRL_3_SHDW                       0x0214
> -#define EMIF_EXT_PHY_CTRL_4                            0x0218
> -#define EMIF_EXT_PHY_CTRL_4_SHDW                       0x021c
> -#define EMIF_EXT_PHY_CTRL_5                            0x0220
> -#define EMIF_EXT_PHY_CTRL_5_SHDW                       0x0224
> -#define EMIF_EXT_PHY_CTRL_6                            0x0228
> -#define EMIF_EXT_PHY_CTRL_6_SHDW                       0x022c
> -#define EMIF_EXT_PHY_CTRL_7                            0x0230
> -#define EMIF_EXT_PHY_CTRL_7_SHDW                       0x0234
> -#define EMIF_EXT_PHY_CTRL_8                            0x0238
> -#define EMIF_EXT_PHY_CTRL_8_SHDW                       0x023c
> -#define EMIF_EXT_PHY_CTRL_9                            0x0240
> -#define EMIF_EXT_PHY_CTRL_9_SHDW                       0x0244
> -#define EMIF_EXT_PHY_CTRL_10                           0x0248
> -#define EMIF_EXT_PHY_CTRL_10_SHDW                      0x024c
> -#define EMIF_EXT_PHY_CTRL_11                           0x0250
> -#define EMIF_EXT_PHY_CTRL_11_SHDW                      0x0254
> -#define EMIF_EXT_PHY_CTRL_12                           0x0258
> -#define EMIF_EXT_PHY_CTRL_12_SHDW                      0x025c
> -#define EMIF_EXT_PHY_CTRL_13                           0x0260
> -#define EMIF_EXT_PHY_CTRL_13_SHDW                      0x0264
> -#define EMIF_EXT_PHY_CTRL_14                           0x0268
> -#define EMIF_EXT_PHY_CTRL_14_SHDW                      0x026c
> -#define EMIF_EXT_PHY_CTRL_15                           0x0270
> -#define EMIF_EXT_PHY_CTRL_15_SHDW                      0x0274
> -#define EMIF_EXT_PHY_CTRL_16                           0x0278
> -#define EMIF_EXT_PHY_CTRL_16_SHDW                      0x027c
> -#define EMIF_EXT_PHY_CTRL_17                           0x0280
> -#define EMIF_EXT_PHY_CTRL_17_SHDW                      0x0284
> -#define EMIF_EXT_PHY_CTRL_18                           0x0288
> -#define EMIF_EXT_PHY_CTRL_18_SHDW                      0x028c
> -#define EMIF_EXT_PHY_CTRL_19                           0x0290
> -#define EMIF_EXT_PHY_CTRL_19_SHDW                      0x0294
> -#define EMIF_EXT_PHY_CTRL_20                           0x0298
> -#define EMIF_EXT_PHY_CTRL_20_SHDW                      0x029c
> -#define EMIF_EXT_PHY_CTRL_21                           0x02a0
> -#define EMIF_EXT_PHY_CTRL_21_SHDW                      0x02a4
> -#define EMIF_EXT_PHY_CTRL_22                           0x02a8
> -#define EMIF_EXT_PHY_CTRL_22_SHDW                      0x02ac
> -#define EMIF_EXT_PHY_CTRL_23                           0x02b0
> -#define EMIF_EXT_PHY_CTRL_23_SHDW                      0x02b4
> -#define EMIF_EXT_PHY_CTRL_24                           0x02b8
> -#define EMIF_EXT_PHY_CTRL_24_SHDW                      0x02bc
> -#define EMIF_EXT_PHY_CTRL_25                           0x02c0
> -#define EMIF_EXT_PHY_CTRL_25_SHDW                      0x02c4
> -#define EMIF_EXT_PHY_CTRL_26                           0x02c8
> -#define EMIF_EXT_PHY_CTRL_26_SHDW                      0x02cc
> -#define EMIF_EXT_PHY_CTRL_27                           0x02d0
> -#define EMIF_EXT_PHY_CTRL_27_SHDW                      0x02d4
> -#define EMIF_EXT_PHY_CTRL_28                           0x02d8
> -#define EMIF_EXT_PHY_CTRL_28_SHDW                      0x02dc
> -#define EMIF_EXT_PHY_CTRL_29                           0x02e0
> -#define EMIF_EXT_PHY_CTRL_29_SHDW                      0x02e4
> -#define EMIF_EXT_PHY_CTRL_30                           0x02e8
> -#define EMIF_EXT_PHY_CTRL_30_SHDW                      0x02ec
> -
> -/* Registers shifts and masks */
> -
> -/* EMIF_MODULE_ID_AND_REVISION */
> -#define SCHEME_SHIFT                                   30
> -#define SCHEME_MASK                                    (0x3 << 30)
> -#define MODULE_ID_SHIFT                                        16
> -#define MODULE_ID_MASK                                 (0xfff << 16)
> -#define RTL_VERSION_SHIFT                              11
> -#define RTL_VERSION_MASK                               (0x1f << 11)
> -#define MAJOR_REVISION_SHIFT                           8
> -#define MAJOR_REVISION_MASK                            (0x7 << 8)
> -#define MINOR_REVISION_SHIFT                           0
> -#define MINOR_REVISION_MASK                            (0x3f << 0)
> -
> -/* STATUS */
> -#define BE_SHIFT                                       31
> -#define BE_MASK                                                (1 << 31)
> -#define DUAL_CLK_MODE_SHIFT                            30
> -#define DUAL_CLK_MODE_MASK                             (1 << 30)
> -#define FAST_INIT_SHIFT                                        29
> -#define FAST_INIT_MASK                                 (1 << 29)
> -#define RDLVLGATETO_SHIFT                              6
> -#define RDLVLGATETO_MASK                               (1 << 6)
> -#define RDLVLTO_SHIFT                                  5
> -#define RDLVLTO_MASK                                   (1 << 5)
> -#define WRLVLTO_SHIFT                                  4
> -#define WRLVLTO_MASK                                   (1 << 4)
> -#define PHY_DLL_READY_SHIFT                            2
> -#define PHY_DLL_READY_MASK                             (1 << 2)
> -
> -/* SDRAM_CONFIG */
> -#define SDRAM_TYPE_SHIFT                               29
> -#define SDRAM_TYPE_MASK                                        (0x7 << 29)
> -#define IBANK_POS_SHIFT                                        27
> -#define IBANK_POS_MASK                                 (0x3 << 27)
> -#define DDR_TERM_SHIFT                                 24
> -#define DDR_TERM_MASK                                  (0x7 << 24)
> -#define DDR2_DDQS_SHIFT                                        23
> -#define DDR2_DDQS_MASK                                 (1 << 23)
> -#define DYN_ODT_SHIFT                                  21
> -#define DYN_ODT_MASK                                   (0x3 << 21)
> -#define DDR_DISABLE_DLL_SHIFT                          20
> -#define DDR_DISABLE_DLL_MASK                           (1 << 20)
> -#define SDRAM_DRIVE_SHIFT                              18
> -#define SDRAM_DRIVE_MASK                               (0x3 << 18)
> -#define CWL_SHIFT                                      16
> -#define CWL_MASK                                       (0x3 << 16)
> -#define NARROW_MODE_SHIFT                              14
> -#define NARROW_MODE_MASK                               (0x3 << 14)
> -#define CL_SHIFT                                       10
> -#define CL_MASK                                                (0xf << 10)
> -#define ROWSIZE_SHIFT                                  7
> -#define ROWSIZE_MASK                                   (0x7 << 7)
> -#define IBANK_SHIFT                                    4
> -#define IBANK_MASK                                     (0x7 << 4)
> -#define EBANK_SHIFT                                    3
> -#define EBANK_MASK                                     (1 << 3)
> -#define PAGESIZE_SHIFT                                 0
> -#define PAGESIZE_MASK                                  (0x7 << 0)
> -
> -/* SDRAM_CONFIG_2 */
> -#define CS1NVMEN_SHIFT                                 30
> -#define CS1NVMEN_MASK                                  (1 << 30)
> -#define EBANK_POS_SHIFT                                        27
> -#define EBANK_POS_MASK                                 (1 << 27)
> -#define RDBNUM_SHIFT                                   4
> -#define RDBNUM_MASK                                    (0x3 << 4)
> -#define RDBSIZE_SHIFT                                  0
> -#define RDBSIZE_MASK                                   (0x7 << 0)
> -
> -/* SDRAM_REFRESH_CONTROL */
> -#define INITREF_DIS_SHIFT                              31
> -#define INITREF_DIS_MASK                               (1 << 31)
> -#define SRT_SHIFT                                      29
> -#define SRT_MASK                                       (1 << 29)
> -#define ASR_SHIFT                                      28
> -#define ASR_MASK                                       (1 << 28)
> -#define PASR_SHIFT                                     24
> -#define PASR_MASK                                      (0x7 << 24)
> -#define REFRESH_RATE_SHIFT                             0
> -#define REFRESH_RATE_MASK                              (0xffff << 0)
> -
> -/* SDRAM_TIMING_1 */
> -#define T_RTW_SHIFT                                    29
> -#define T_RTW_MASK                                     (0x7 << 29)
> -#define T_RP_SHIFT                                     25
> -#define T_RP_MASK                                      (0xf << 25)
> -#define T_RCD_SHIFT                                    21
> -#define T_RCD_MASK                                     (0xf << 21)
> -#define T_WR_SHIFT                                     17
> -#define T_WR_MASK                                      (0xf << 17)
> -#define T_RAS_SHIFT                                    12
> -#define T_RAS_MASK                                     (0x1f << 12)
> -#define T_RC_SHIFT                                     6
> -#define T_RC_MASK                                      (0x3f << 6)
> -#define T_RRD_SHIFT                                    3
> -#define T_RRD_MASK                                     (0x7 << 3)
> -#define T_WTR_SHIFT                                    0
> -#define T_WTR_MASK                                     (0x7 << 0)
> -
> -/* SDRAM_TIMING_2 */
> -#define T_XP_SHIFT                                     28
> -#define T_XP_MASK                                      (0x7 << 28)
> -#define T_ODT_SHIFT                                    25
> -#define T_ODT_MASK                                     (0x7 << 25)
> -#define T_XSNR_SHIFT                                   16
> -#define T_XSNR_MASK                                    (0x1ff << 16)
> -#define T_XSRD_SHIFT                                   6
> -#define T_XSRD_MASK                                    (0x3ff << 6)
> -#define T_RTP_SHIFT                                    3
> -#define T_RTP_MASK                                     (0x7 << 3)
> -#define T_CKE_SHIFT                                    0
> -#define T_CKE_MASK                                     (0x7 << 0)
> -
> -/* SDRAM_TIMING_3 */
> -#define T_PDLL_UL_SHIFT                                        28
> -#define T_PDLL_UL_MASK                                 (0xf << 28)
> -#define T_CSTA_SHIFT                                   24
> -#define T_CSTA_MASK                                    (0xf << 24)
> -#define T_CKESR_SHIFT                                  21
> -#define T_CKESR_MASK                                   (0x7 << 21)
> -#define ZQ_ZQCS_SHIFT                                  15
> -#define ZQ_ZQCS_MASK                                   (0x3f << 15)
> -#define T_TDQSCKMAX_SHIFT                              13
> -#define T_TDQSCKMAX_MASK                               (0x3 << 13)
> -#define T_RFC_SHIFT                                    4
> -#define T_RFC_MASK                                     (0x1ff << 4)
> -#define T_RAS_MAX_SHIFT                                        0
> -#define T_RAS_MAX_MASK                                 (0xf << 0)
> -
> -/* POWER_MANAGEMENT_CONTROL */
> -#define PD_TIM_SHIFT                                   12
> -#define PD_TIM_MASK                                    (0xf << 12)
> -#define DPD_EN_SHIFT                                   11
> -#define DPD_EN_MASK                                    (1 << 11)
> -#define LP_MODE_SHIFT                                  8
> -#define LP_MODE_MASK                                   (0x7 << 8)
> -#define SR_TIM_SHIFT                                   4
> -#define SR_TIM_MASK                                    (0xf << 4)
> -#define CS_TIM_SHIFT                                   0
> -#define CS_TIM_MASK                                    (0xf << 0)
> -
> -/* LPDDR2_MODE_REG_DATA */
> -#define VALUE_0_SHIFT                                  0
> -#define VALUE_0_MASK                                   (0x7f << 0)
> -
> -/* LPDDR2_MODE_REG_CONFIG */
> -#define CS_SHIFT                                       31
> -#define CS_MASK                                                (1 << 31)
> -#define REFRESH_EN_SHIFT                               30
> -#define REFRESH_EN_MASK                                        (1 << 30)
> -#define ADDRESS_SHIFT                                  0
> -#define ADDRESS_MASK                                   (0xff << 0)
> -
> -/* OCP_CONFIG */
> -#define SYS_THRESH_MAX_SHIFT                           24
> -#define SYS_THRESH_MAX_MASK                            (0xf << 24)
> -#define MPU_THRESH_MAX_SHIFT                           20
> -#define MPU_THRESH_MAX_MASK                            (0xf << 20)
> -#define LL_THRESH_MAX_SHIFT                            16
> -#define LL_THRESH_MAX_MASK                             (0xf << 16)
> -
> -/* PERFORMANCE_COUNTER_1 */
> -#define COUNTER1_SHIFT                                 0
> -#define COUNTER1_MASK                                  (0xffffffff << 0)
> -
> -/* PERFORMANCE_COUNTER_2 */
> -#define COUNTER2_SHIFT                                 0
> -#define COUNTER2_MASK                                  (0xffffffff << 0)
> -
> -/* PERFORMANCE_COUNTER_CONFIG */
> -#define CNTR2_MCONNID_EN_SHIFT                         31
> -#define CNTR2_MCONNID_EN_MASK                          (1 << 31)
> -#define CNTR2_REGION_EN_SHIFT                          30
> -#define CNTR2_REGION_EN_MASK                           (1 << 30)
> -#define CNTR2_CFG_SHIFT                                        16
> -#define CNTR2_CFG_MASK                                 (0xf << 16)
> -#define CNTR1_MCONNID_EN_SHIFT                         15
> -#define CNTR1_MCONNID_EN_MASK                          (1 << 15)
> -#define CNTR1_REGION_EN_SHIFT                          14
> -#define CNTR1_REGION_EN_MASK                           (1 << 14)
> -#define CNTR1_CFG_SHIFT                                        0
> -#define CNTR1_CFG_MASK                                 (0xf << 0)
> -
> -/* PERFORMANCE_COUNTER_MASTER_REGION_SELECT */
> -#define MCONNID2_SHIFT                                 24
> -#define MCONNID2_MASK                                  (0xff << 24)
> -#define REGION_SEL2_SHIFT                              16
> -#define REGION_SEL2_MASK                               (0x3 << 16)
> -#define MCONNID1_SHIFT                                 8
> -#define MCONNID1_MASK                                  (0xff << 8)
> -#define REGION_SEL1_SHIFT                              0
> -#define REGION_SEL1_MASK                               (0x3 << 0)
> -
> -/* PERFORMANCE_COUNTER_TIME */
> -#define TOTAL_TIME_SHIFT                               0
> -#define TOTAL_TIME_MASK                                        (0xffffffff << 0)
> -
> -/* DLL_CALIB_CTRL */
> -#define ACK_WAIT_SHIFT                                 16
> -#define ACK_WAIT_MASK                                  (0xf << 16)
> -#define DLL_CALIB_INTERVAL_SHIFT                       0
> -#define DLL_CALIB_INTERVAL_MASK                                (0x1ff << 0)
> -
> -/* END_OF_INTERRUPT */
> -#define EOI_SHIFT                                      0
> -#define EOI_MASK                                       (1 << 0)
> -
> -/* SYSTEM_OCP_INTERRUPT_RAW_STATUS */
> -#define DNV_SYS_SHIFT                                  2
> -#define DNV_SYS_MASK                                   (1 << 2)
> -#define TA_SYS_SHIFT                                   1
> -#define TA_SYS_MASK                                    (1 << 1)
> -#define ERR_SYS_SHIFT                                  0
> -#define ERR_SYS_MASK                                   (1 << 0)
> -
> -/* LOW_LATENCY_OCP_INTERRUPT_RAW_STATUS */
> -#define DNV_LL_SHIFT                                   2
> -#define DNV_LL_MASK                                    (1 << 2)
> -#define TA_LL_SHIFT                                    1
> -#define TA_LL_MASK                                     (1 << 1)
> -#define ERR_LL_SHIFT                                   0
> -#define ERR_LL_MASK                                    (1 << 0)
> -
> -/* SYSTEM_OCP_INTERRUPT_ENABLE_SET */
> -#define EN_DNV_SYS_SHIFT                               2
> -#define EN_DNV_SYS_MASK                                        (1 << 2)
> -#define EN_TA_SYS_SHIFT                                        1
> -#define EN_TA_SYS_MASK                                 (1 << 1)
> -#define EN_ERR_SYS_SHIFT                                       0
> -#define EN_ERR_SYS_MASK                                        (1 << 0)
> -
> -/* LOW_LATENCY_OCP_INTERRUPT_ENABLE_SET */
> -#define EN_DNV_LL_SHIFT                                        2
> -#define EN_DNV_LL_MASK                                 (1 << 2)
> -#define EN_TA_LL_SHIFT                                 1
> -#define EN_TA_LL_MASK                                  (1 << 1)
> -#define EN_ERR_LL_SHIFT                                        0
> -#define EN_ERR_LL_MASK                                 (1 << 0)
> -
> -/* SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG */
> -#define ZQ_CS1EN_SHIFT                                 31
> -#define ZQ_CS1EN_MASK                                  (1 << 31)
> -#define ZQ_CS0EN_SHIFT                                 30
> -#define ZQ_CS0EN_MASK                                  (1 << 30)
> -#define ZQ_DUALCALEN_SHIFT                             29
> -#define ZQ_DUALCALEN_MASK                              (1 << 29)
> -#define ZQ_SFEXITEN_SHIFT                              28
> -#define ZQ_SFEXITEN_MASK                               (1 << 28)
> -#define ZQ_ZQINIT_MULT_SHIFT                           18
> -#define ZQ_ZQINIT_MULT_MASK                            (0x3 << 18)
> -#define ZQ_ZQCL_MULT_SHIFT                             16
> -#define ZQ_ZQCL_MULT_MASK                              (0x3 << 16)
> -#define ZQ_REFINTERVAL_SHIFT                           0
> -#define ZQ_REFINTERVAL_MASK                            (0xffff << 0)
> -
> -/* TEMPERATURE_ALERT_CONFIG */
> -#define TA_CS1EN_SHIFT                                 31
> -#define TA_CS1EN_MASK                                  (1 << 31)
> -#define TA_CS0EN_SHIFT                                 30
> -#define TA_CS0EN_MASK                                  (1 << 30)
> -#define TA_SFEXITEN_SHIFT                              28
> -#define TA_SFEXITEN_MASK                               (1 << 28)
> -#define TA_DEVWDT_SHIFT                                        26
> -#define TA_DEVWDT_MASK                                 (0x3 << 26)
> -#define TA_DEVCNT_SHIFT                                        24
> -#define TA_DEVCNT_MASK                                 (0x3 << 24)
> -#define TA_REFINTERVAL_SHIFT                           0
> -#define TA_REFINTERVAL_MASK                            (0x3fffff << 0)
> -
> -/* OCP_ERROR_LOG */
> -#define MADDRSPACE_SHIFT                               14
> -#define MADDRSPACE_MASK                                        (0x3 << 14)
> -#define MBURSTSEQ_SHIFT                                        11
> -#define MBURSTSEQ_MASK                                 (0x7 << 11)
> -#define MCMD_SHIFT                                     8
> -#define MCMD_MASK                                      (0x7 << 8)
> -#define MCONNID_SHIFT                                  0
> -#define MCONNID_MASK                                   (0xff << 0)
> -
> -/* DDR_PHY_CTRL_1 - EMIF4D */
> -#define DLL_SLAVE_DLY_CTRL_SHIFT_4D                    4
> -#define DLL_SLAVE_DLY_CTRL_MASK_4D                     (0xFF << 4)
> -#define READ_LATENCY_SHIFT_4D                          0
> -#define READ_LATENCY_MASK_4D                           (0xf << 0)
> -
> -/* DDR_PHY_CTRL_1 - EMIF4D5 */
> -#define DLL_HALF_DELAY_SHIFT_4D5                       21
> -#define DLL_HALF_DELAY_MASK_4D5                                (1 << 21)
> -#define READ_LATENCY_SHIFT_4D5                         0
> -#define READ_LATENCY_MASK_4D5                          (0x1f << 0)
> -
> -/* DDR_PHY_CTRL_1_SHDW */
> -#define DDR_PHY_CTRL_1_SHDW_SHIFT                      5
> -#define DDR_PHY_CTRL_1_SHDW_MASK                       (0x7ffffff << 5)
> -#define READ_LATENCY_SHDW_SHIFT                                0
> -#define READ_LATENCY_SHDW_MASK                         (0x1f << 0)
> +#include <linux/ti_emif.h>
>
>  #ifndef __ASSEMBLY__
>  /*
> diff --git a/include/linux/ti_emif.h b/include/linux/ti_emif.h
> new file mode 100644
> index 0000000..be26e7f
> --- /dev/null
> +++ b/include/linux/ti_emif.h
> @@ -0,0 +1,558 @@
> +/*
> + * Register defines for the EMIF driver
> + *
> + * Copyright (C) 2012 Texas Instruments, Inc.
> + *
> + * Benoit Cousson (b-cousson at 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.
> + */
> +#ifndef __TI_EMIF_H
> +#define __TI_EMIF_H
> +
> +/*
> + * Maximum number of different frequencies supported by EMIF driver
> + * Determines the number of entries in the pointer array for register
> + * cache
> + */
> +#define EMIF_MAX_NUM_FREQUENCIES                       6
> +
> +/* State of the core voltage */
> +#define DDR_VOLTAGE_STABLE                             0
> +#define DDR_VOLTAGE_RAMPING                            1
> +
> +/* Defines for timing De-rating */
> +#define EMIF_NORMAL_TIMINGS                            0
> +#define EMIF_DERATED_TIMINGS                           1
> +
> +/* Length of the forced read idle period in terms of cycles */
> +#define EMIF_READ_IDLE_LEN_VAL                         5
> +
> +/*
> + * forced read idle interval to be used when voltage
> + * is changed as part of DVFS/DPS - 1ms
> + */
> +#define READ_IDLE_INTERVAL_DVFS                                (1*1000000)
> +
> +/*
> + * Forced read idle interval to be used when voltage is stable
> + * 50us - or maximum value will do
> + */
> +#define READ_IDLE_INTERVAL_NORMAL                      (50*1000000)
> +
> +/* DLL calibration interval when voltage is NOT stable - 1us */
> +#define DLL_CALIB_INTERVAL_DVFS                                (1*1000000)
> +
> +#define DLL_CALIB_ACK_WAIT_VAL                         5
> +
> +/* Interval between ZQCS commands - hw team recommended value */
> +#define EMIF_ZQCS_INTERVAL_US                          (50*1000)
> +/* Enable ZQ Calibration on exiting Self-refresh */
> +#define ZQ_SFEXITEN_ENABLE                             1
> +/*
> + * ZQ Calibration simultaneously on both chip-selects:
> + * Needs one calibration resistor per CS
> + */
> +#define        ZQ_DUALCALEN_DISABLE                            0
> +#define        ZQ_DUALCALEN_ENABLE                             1
> +
> +#define T_ZQCS_DEFAULT_NS                              90
> +#define T_ZQCL_DEFAULT_NS                              360
> +#define T_ZQINIT_DEFAULT_NS                            1000
> +
> +/* DPD_EN */
> +#define DPD_DISABLE                                    0
> +#define DPD_ENABLE                                     1
> +
> +/*
> + * Default values for the low-power entry to be used if not provided by user.
> + * OMAP4/5 has a hw bug(i735) due to which this value can not be less than 512
> + * Timeout values are in DDR clock 'cycles' and frequency threshold in Hz
> + */
> +#define EMIF_LP_MODE_TIMEOUT_PERFORMANCE               2048
> +#define EMIF_LP_MODE_TIMEOUT_POWER                     512
> +#define EMIF_LP_MODE_FREQ_THRESHOLD                    400000000
> +
> +/* DDR_PHY_CTRL_1 values for EMIF4D - ATTILA PHY combination */
> +#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY         0x049FF000
> +#define EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY      0x41
> +#define EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY      0x80
> +#define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY 0xFF
> +
> +/* DDR_PHY_CTRL_1 values for EMIF4D5 INTELLIPHY combination */
> +#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY                0x0E084200
> +#define EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS      10000
> +
> +/* TEMP_ALERT_CONFIG - corresponding to temp gradient 5 C/s */
> +#define TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS            360
> +
> +#define EMIF_T_CSTA                                    3
> +#define EMIF_T_PDLL_UL                                 128
> +
> +/* External PHY control registers magic values */
> +#define EMIF_EXT_PHY_CTRL_1_VAL                                0x04020080
> +#define EMIF_EXT_PHY_CTRL_5_VAL                                0x04010040
> +#define EMIF_EXT_PHY_CTRL_6_VAL                                0x01004010
> +#define EMIF_EXT_PHY_CTRL_7_VAL                                0x00001004
> +#define EMIF_EXT_PHY_CTRL_8_VAL                                0x04010040
> +#define EMIF_EXT_PHY_CTRL_9_VAL                                0x01004010
> +#define EMIF_EXT_PHY_CTRL_10_VAL                       0x00001004
> +#define EMIF_EXT_PHY_CTRL_11_VAL                       0x00000000
> +#define EMIF_EXT_PHY_CTRL_12_VAL                       0x00000000
> +#define EMIF_EXT_PHY_CTRL_13_VAL                       0x00000000
> +#define EMIF_EXT_PHY_CTRL_14_VAL                       0x80080080
> +#define EMIF_EXT_PHY_CTRL_15_VAL                       0x00800800
> +#define EMIF_EXT_PHY_CTRL_16_VAL                       0x08102040
> +#define EMIF_EXT_PHY_CTRL_17_VAL                       0x00000001
> +#define EMIF_EXT_PHY_CTRL_18_VAL                       0x540A8150
> +#define EMIF_EXT_PHY_CTRL_19_VAL                       0xA81502A0
> +#define EMIF_EXT_PHY_CTRL_20_VAL                       0x002A0540
> +#define EMIF_EXT_PHY_CTRL_21_VAL                       0x00000000
> +#define EMIF_EXT_PHY_CTRL_22_VAL                       0x00000000
> +#define EMIF_EXT_PHY_CTRL_23_VAL                       0x00000000
> +#define EMIF_EXT_PHY_CTRL_24_VAL                       0x00000077
> +
> +#define EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS     1200
> +
> +/* Registers offset */
> +#define EMIF_MODULE_ID_AND_REVISION                    0x0000
> +#define EMIF_STATUS                                    0x0004
> +#define EMIF_SDRAM_CONFIG                              0x0008
> +#define EMIF_SDRAM_CONFIG_2                            0x000c
> +#define EMIF_SDRAM_REFRESH_CONTROL                     0x0010
> +#define EMIF_SDRAM_REFRESH_CTRL_SHDW                   0x0014
> +#define EMIF_SDRAM_TIMING_1                            0x0018
> +#define EMIF_SDRAM_TIMING_1_SHDW                       0x001c
> +#define EMIF_SDRAM_TIMING_2                            0x0020
> +#define EMIF_SDRAM_TIMING_2_SHDW                       0x0024
> +#define EMIF_SDRAM_TIMING_3                            0x0028
> +#define EMIF_SDRAM_TIMING_3_SHDW                       0x002c
> +#define EMIF_LPDDR2_NVM_TIMING                         0x0030
> +#define EMIF_LPDDR2_NVM_TIMING_SHDW                    0x0034
> +#define EMIF_POWER_MANAGEMENT_CONTROL                  0x0038
> +#define EMIF_POWER_MANAGEMENT_CTRL_SHDW                        0x003c
> +#define EMIF_LPDDR2_MODE_REG_DATA                      0x0040
> +#define EMIF_LPDDR2_MODE_REG_CONFIG                    0x0050
> +#define EMIF_OCP_CONFIG                                        0x0054
> +#define EMIF_OCP_CONFIG_VALUE_1                                0x0058
> +#define EMIF_OCP_CONFIG_VALUE_2                                0x005c
> +#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL           0x0060
> +#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT         0x0064
> +#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT      0x0068
> +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1       0x006c
> +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2       0x0070
> +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3       0x0074
> +#define EMIF_PERFORMANCE_COUNTER_1                     0x0080
> +#define EMIF_PERFORMANCE_COUNTER_2                     0x0084
> +#define EMIF_PERFORMANCE_COUNTER_CONFIG                        0x0088
> +#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT  0x008c
> +#define EMIF_PERFORMANCE_COUNTER_TIME                  0x0090
> +#define EMIF_MISC_REG                                  0x0094
> +#define EMIF_DLL_CALIB_CTRL                            0x0098
> +#define EMIF_DLL_CALIB_CTRL_SHDW                       0x009c
> +#define EMIF_END_OF_INTERRUPT                          0x00a0
> +#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS           0x00a4
> +#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS               0x00a8
> +#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS               0x00ac
> +#define EMIF_LL_OCP_INTERRUPT_STATUS                   0x00b0
> +#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET           0x00b4
> +#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET               0x00b8
> +#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR         0x00bc
> +#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR             0x00c0
> +#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG 0x00c8
> +#define EMIF_TEMPERATURE_ALERT_CONFIG                  0x00cc
> +#define EMIF_OCP_ERROR_LOG                             0x00d0
> +#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW           0x00d4
> +#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL          0x00d8
> +#define EMIF_READ_WRITE_LEVELING_CONTROL               0x00dc
> +#define EMIF_DDR_PHY_CTRL_1                            0x00e4
> +#define EMIF_DDR_PHY_CTRL_1_SHDW                       0x00e8
> +#define EMIF_DDR_PHY_CTRL_2                            0x00ec
> +#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING      0x0100
> +#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104
> +#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108
> +#define EMIF_READ_WRITE_EXECUTION_THRESHOLD            0x0120
> +#define EMIF_COS_CONFIG                                        0x0124
> +#define EMIF_PHY_STATUS_1                              0x0140
> +#define EMIF_PHY_STATUS_2                              0x0144
> +#define EMIF_PHY_STATUS_3                              0x0148
> +#define EMIF_PHY_STATUS_4                              0x014c
> +#define EMIF_PHY_STATUS_5                              0x0150
> +#define EMIF_PHY_STATUS_6                              0x0154
> +#define EMIF_PHY_STATUS_7                              0x0158
> +#define EMIF_PHY_STATUS_8                              0x015c
> +#define EMIF_PHY_STATUS_9                              0x0160
> +#define EMIF_PHY_STATUS_10                             0x0164
> +#define EMIF_PHY_STATUS_11                             0x0168
> +#define EMIF_PHY_STATUS_12                             0x016c
> +#define EMIF_PHY_STATUS_13                             0x0170
> +#define EMIF_PHY_STATUS_14                             0x0174
> +#define EMIF_PHY_STATUS_15                             0x0178
> +#define EMIF_PHY_STATUS_16                             0x017c
> +#define EMIF_PHY_STATUS_17                             0x0180
> +#define EMIF_PHY_STATUS_18                             0x0184
> +#define EMIF_PHY_STATUS_19                             0x0188
> +#define EMIF_PHY_STATUS_20                             0x018c
> +#define EMIF_PHY_STATUS_21                             0x0190
> +#define EMIF_EXT_PHY_CTRL_1                            0x0200
> +#define EMIF_EXT_PHY_CTRL_1_SHDW                       0x0204
> +#define EMIF_EXT_PHY_CTRL_2                            0x0208
> +#define EMIF_EXT_PHY_CTRL_2_SHDW                       0x020c
> +#define EMIF_EXT_PHY_CTRL_3                            0x0210
> +#define EMIF_EXT_PHY_CTRL_3_SHDW                       0x0214
> +#define EMIF_EXT_PHY_CTRL_4                            0x0218
> +#define EMIF_EXT_PHY_CTRL_4_SHDW                       0x021c
> +#define EMIF_EXT_PHY_CTRL_5                            0x0220
> +#define EMIF_EXT_PHY_CTRL_5_SHDW                       0x0224
> +#define EMIF_EXT_PHY_CTRL_6                            0x0228
> +#define EMIF_EXT_PHY_CTRL_6_SHDW                       0x022c
> +#define EMIF_EXT_PHY_CTRL_7                            0x0230
> +#define EMIF_EXT_PHY_CTRL_7_SHDW                       0x0234
> +#define EMIF_EXT_PHY_CTRL_8                            0x0238
> +#define EMIF_EXT_PHY_CTRL_8_SHDW                       0x023c
> +#define EMIF_EXT_PHY_CTRL_9                            0x0240
> +#define EMIF_EXT_PHY_CTRL_9_SHDW                       0x0244
> +#define EMIF_EXT_PHY_CTRL_10                           0x0248
> +#define EMIF_EXT_PHY_CTRL_10_SHDW                      0x024c
> +#define EMIF_EXT_PHY_CTRL_11                           0x0250
> +#define EMIF_EXT_PHY_CTRL_11_SHDW                      0x0254
> +#define EMIF_EXT_PHY_CTRL_12                           0x0258
> +#define EMIF_EXT_PHY_CTRL_12_SHDW                      0x025c
> +#define EMIF_EXT_PHY_CTRL_13                           0x0260
> +#define EMIF_EXT_PHY_CTRL_13_SHDW                      0x0264
> +#define EMIF_EXT_PHY_CTRL_14                           0x0268
> +#define EMIF_EXT_PHY_CTRL_14_SHDW                      0x026c
> +#define EMIF_EXT_PHY_CTRL_15                           0x0270
> +#define EMIF_EXT_PHY_CTRL_15_SHDW                      0x0274
> +#define EMIF_EXT_PHY_CTRL_16                           0x0278
> +#define EMIF_EXT_PHY_CTRL_16_SHDW                      0x027c
> +#define EMIF_EXT_PHY_CTRL_17                           0x0280
> +#define EMIF_EXT_PHY_CTRL_17_SHDW                      0x0284
> +#define EMIF_EXT_PHY_CTRL_18                           0x0288
> +#define EMIF_EXT_PHY_CTRL_18_SHDW                      0x028c
> +#define EMIF_EXT_PHY_CTRL_19                           0x0290
> +#define EMIF_EXT_PHY_CTRL_19_SHDW                      0x0294
> +#define EMIF_EXT_PHY_CTRL_20                           0x0298
> +#define EMIF_EXT_PHY_CTRL_20_SHDW                      0x029c
> +#define EMIF_EXT_PHY_CTRL_21                           0x02a0
> +#define EMIF_EXT_PHY_CTRL_21_SHDW                      0x02a4
> +#define EMIF_EXT_PHY_CTRL_22                           0x02a8
> +#define EMIF_EXT_PHY_CTRL_22_SHDW                      0x02ac
> +#define EMIF_EXT_PHY_CTRL_23                           0x02b0
> +#define EMIF_EXT_PHY_CTRL_23_SHDW                      0x02b4
> +#define EMIF_EXT_PHY_CTRL_24                           0x02b8
> +#define EMIF_EXT_PHY_CTRL_24_SHDW                      0x02bc
> +#define EMIF_EXT_PHY_CTRL_25                           0x02c0
> +#define EMIF_EXT_PHY_CTRL_25_SHDW                      0x02c4
> +#define EMIF_EXT_PHY_CTRL_26                           0x02c8
> +#define EMIF_EXT_PHY_CTRL_26_SHDW                      0x02cc
> +#define EMIF_EXT_PHY_CTRL_27                           0x02d0
> +#define EMIF_EXT_PHY_CTRL_27_SHDW                      0x02d4
> +#define EMIF_EXT_PHY_CTRL_28                           0x02d8
> +#define EMIF_EXT_PHY_CTRL_28_SHDW                      0x02dc
> +#define EMIF_EXT_PHY_CTRL_29                           0x02e0
> +#define EMIF_EXT_PHY_CTRL_29_SHDW                      0x02e4
> +#define EMIF_EXT_PHY_CTRL_30                           0x02e8
> +#define EMIF_EXT_PHY_CTRL_30_SHDW                      0x02ec
> +
> +/* Registers shifts and masks */
> +
> +/* EMIF_MODULE_ID_AND_REVISION */
> +#define SCHEME_SHIFT                                   30
> +#define SCHEME_MASK                                    (0x3 << 30)
> +#define MODULE_ID_SHIFT                                        16
> +#define MODULE_ID_MASK                                 (0xfff << 16)
> +#define RTL_VERSION_SHIFT                              11
> +#define RTL_VERSION_MASK                               (0x1f << 11)
> +#define MAJOR_REVISION_SHIFT                           8
> +#define MAJOR_REVISION_MASK                            (0x7 << 8)
> +#define MINOR_REVISION_SHIFT                           0
> +#define MINOR_REVISION_MASK                            (0x3f << 0)
> +
> +/* STATUS */
> +#define BE_SHIFT                                       31
> +#define BE_MASK                                                (1 << 31)
> +#define DUAL_CLK_MODE_SHIFT                            30
> +#define DUAL_CLK_MODE_MASK                             (1 << 30)
> +#define FAST_INIT_SHIFT                                        29
> +#define FAST_INIT_MASK                                 (1 << 29)
> +#define RDLVLGATETO_SHIFT                              6
> +#define RDLVLGATETO_MASK                               (1 << 6)
> +#define RDLVLTO_SHIFT                                  5
> +#define RDLVLTO_MASK                                   (1 << 5)
> +#define WRLVLTO_SHIFT                                  4
> +#define WRLVLTO_MASK                                   (1 << 4)
> +#define PHY_DLL_READY_SHIFT                            2
> +#define PHY_DLL_READY_MASK                             (1 << 2)
> +
> +/* SDRAM_CONFIG */
> +#define SDRAM_TYPE_SHIFT                               29
> +#define SDRAM_TYPE_MASK                                        (0x7 << 29)
> +#define IBANK_POS_SHIFT                                        27
> +#define IBANK_POS_MASK                                 (0x3 << 27)
> +#define DDR_TERM_SHIFT                                 24
> +#define DDR_TERM_MASK                                  (0x7 << 24)
> +#define DDR2_DDQS_SHIFT                                        23
> +#define DDR2_DDQS_MASK                                 (1 << 23)
> +#define DYN_ODT_SHIFT                                  21
> +#define DYN_ODT_MASK                                   (0x3 << 21)
> +#define DDR_DISABLE_DLL_SHIFT                          20
> +#define DDR_DISABLE_DLL_MASK                           (1 << 20)
> +#define SDRAM_DRIVE_SHIFT                              18
> +#define SDRAM_DRIVE_MASK                               (0x3 << 18)
> +#define CWL_SHIFT                                      16
> +#define CWL_MASK                                       (0x3 << 16)
> +#define NARROW_MODE_SHIFT                              14
> +#define NARROW_MODE_MASK                               (0x3 << 14)
> +#define CL_SHIFT                                       10
> +#define CL_MASK                                                (0xf << 10)
> +#define ROWSIZE_SHIFT                                  7
> +#define ROWSIZE_MASK                                   (0x7 << 7)
> +#define IBANK_SHIFT                                    4
> +#define IBANK_MASK                                     (0x7 << 4)
> +#define EBANK_SHIFT                                    3
> +#define EBANK_MASK                                     (1 << 3)
> +#define PAGESIZE_SHIFT                                 0
> +#define PAGESIZE_MASK                                  (0x7 << 0)
> +
> +/* SDRAM_CONFIG_2 */
> +#define CS1NVMEN_SHIFT                                 30
> +#define CS1NVMEN_MASK                                  (1 << 30)
> +#define EBANK_POS_SHIFT                                        27
> +#define EBANK_POS_MASK                                 (1 << 27)
> +#define RDBNUM_SHIFT                                   4
> +#define RDBNUM_MASK                                    (0x3 << 4)
> +#define RDBSIZE_SHIFT                                  0
> +#define RDBSIZE_MASK                                   (0x7 << 0)
> +
> +/* SDRAM_REFRESH_CONTROL */
> +#define INITREF_DIS_SHIFT                              31
> +#define INITREF_DIS_MASK                               (1 << 31)
> +#define SRT_SHIFT                                      29
> +#define SRT_MASK                                       (1 << 29)
> +#define ASR_SHIFT                                      28
> +#define ASR_MASK                                       (1 << 28)
> +#define PASR_SHIFT                                     24
> +#define PASR_MASK                                      (0x7 << 24)
> +#define REFRESH_RATE_SHIFT                             0
> +#define REFRESH_RATE_MASK                              (0xffff << 0)
> +
> +/* SDRAM_TIMING_1 */
> +#define T_RTW_SHIFT                                    29
> +#define T_RTW_MASK                                     (0x7 << 29)
> +#define T_RP_SHIFT                                     25
> +#define T_RP_MASK                                      (0xf << 25)
> +#define T_RCD_SHIFT                                    21
> +#define T_RCD_MASK                                     (0xf << 21)
> +#define T_WR_SHIFT                                     17
> +#define T_WR_MASK                                      (0xf << 17)
> +#define T_RAS_SHIFT                                    12
> +#define T_RAS_MASK                                     (0x1f << 12)
> +#define T_RC_SHIFT                                     6
> +#define T_RC_MASK                                      (0x3f << 6)
> +#define T_RRD_SHIFT                                    3
> +#define T_RRD_MASK                                     (0x7 << 3)
> +#define T_WTR_SHIFT                                    0
> +#define T_WTR_MASK                                     (0x7 << 0)
> +
> +/* SDRAM_TIMING_2 */
> +#define T_XP_SHIFT                                     28
> +#define T_XP_MASK                                      (0x7 << 28)
> +#define T_ODT_SHIFT                                    25
> +#define T_ODT_MASK                                     (0x7 << 25)
> +#define T_XSNR_SHIFT                                   16
> +#define T_XSNR_MASK                                    (0x1ff << 16)
> +#define T_XSRD_SHIFT                                   6
> +#define T_XSRD_MASK                                    (0x3ff << 6)
> +#define T_RTP_SHIFT                                    3
> +#define T_RTP_MASK                                     (0x7 << 3)
> +#define T_CKE_SHIFT                                    0
> +#define T_CKE_MASK                                     (0x7 << 0)
> +
> +/* SDRAM_TIMING_3 */
> +#define T_PDLL_UL_SHIFT                                        28
> +#define T_PDLL_UL_MASK                                 (0xf << 28)
> +#define T_CSTA_SHIFT                                   24
> +#define T_CSTA_MASK                                    (0xf << 24)
> +#define T_CKESR_SHIFT                                  21
> +#define T_CKESR_MASK                                   (0x7 << 21)
> +#define ZQ_ZQCS_SHIFT                                  15
> +#define ZQ_ZQCS_MASK                                   (0x3f << 15)
> +#define T_TDQSCKMAX_SHIFT                              13
> +#define T_TDQSCKMAX_MASK                               (0x3 << 13)
> +#define T_RFC_SHIFT                                    4
> +#define T_RFC_MASK                                     (0x1ff << 4)
> +#define T_RAS_MAX_SHIFT                                        0
> +#define T_RAS_MAX_MASK                                 (0xf << 0)
> +
> +/* POWER_MANAGEMENT_CONTROL */
> +#define PD_TIM_SHIFT                                   12
> +#define PD_TIM_MASK                                    (0xf << 12)
> +#define DPD_EN_SHIFT                                   11
> +#define DPD_EN_MASK                                    (1 << 11)
> +#define LP_MODE_SHIFT                                  8
> +#define LP_MODE_MASK                                   (0x7 << 8)
> +#define SR_TIM_SHIFT                                   4
> +#define SR_TIM_MASK                                    (0xf << 4)
> +#define CS_TIM_SHIFT                                   0
> +#define CS_TIM_MASK                                    (0xf << 0)
> +
> +/* LPDDR2_MODE_REG_DATA */
> +#define VALUE_0_SHIFT                                  0
> +#define VALUE_0_MASK                                   (0x7f << 0)
> +
> +/* LPDDR2_MODE_REG_CONFIG */
> +#define CS_SHIFT                                       31
> +#define CS_MASK                                                (1 << 31)
> +#define REFRESH_EN_SHIFT                               30
> +#define REFRESH_EN_MASK                                        (1 << 30)
> +#define ADDRESS_SHIFT                                  0
> +#define ADDRESS_MASK                                   (0xff << 0)
> +
> +/* OCP_CONFIG */
> +#define SYS_THRESH_MAX_SHIFT                           24
> +#define SYS_THRESH_MAX_MASK                            (0xf << 24)
> +#define MPU_THRESH_MAX_SHIFT                           20
> +#define MPU_THRESH_MAX_MASK                            (0xf << 20)
> +#define LL_THRESH_MAX_SHIFT                            16
> +#define LL_THRESH_MAX_MASK                             (0xf << 16)
> +
> +/* PERFORMANCE_COUNTER_1 */
> +#define COUNTER1_SHIFT                                 0
> +#define COUNTER1_MASK                                  (0xffffffff << 0)
> +
> +/* PERFORMANCE_COUNTER_2 */
> +#define COUNTER2_SHIFT                                 0
> +#define COUNTER2_MASK                                  (0xffffffff << 0)
> +
> +/* PERFORMANCE_COUNTER_CONFIG */
> +#define CNTR2_MCONNID_EN_SHIFT                         31
> +#define CNTR2_MCONNID_EN_MASK                          (1 << 31)
> +#define CNTR2_REGION_EN_SHIFT                          30
> +#define CNTR2_REGION_EN_MASK                           (1 << 30)
> +#define CNTR2_CFG_SHIFT                                        16
> +#define CNTR2_CFG_MASK                                 (0xf << 16)
> +#define CNTR1_MCONNID_EN_SHIFT                         15
> +#define CNTR1_MCONNID_EN_MASK                          (1 << 15)
> +#define CNTR1_REGION_EN_SHIFT                          14
> +#define CNTR1_REGION_EN_MASK                           (1 << 14)
> +#define CNTR1_CFG_SHIFT                                        0
> +#define CNTR1_CFG_MASK                                 (0xf << 0)
> +
> +/* PERFORMANCE_COUNTER_MASTER_REGION_SELECT */
> +#define MCONNID2_SHIFT                                 24
> +#define MCONNID2_MASK                                  (0xff << 24)
> +#define REGION_SEL2_SHIFT                              16
> +#define REGION_SEL2_MASK                               (0x3 << 16)
> +#define MCONNID1_SHIFT                                 8
> +#define MCONNID1_MASK                                  (0xff << 8)
> +#define REGION_SEL1_SHIFT                              0
> +#define REGION_SEL1_MASK                               (0x3 << 0)
> +
> +/* PERFORMANCE_COUNTER_TIME */
> +#define TOTAL_TIME_SHIFT                               0
> +#define TOTAL_TIME_MASK                                        (0xffffffff << 0)
> +
> +/* DLL_CALIB_CTRL */
> +#define ACK_WAIT_SHIFT                                 16
> +#define ACK_WAIT_MASK                                  (0xf << 16)
> +#define DLL_CALIB_INTERVAL_SHIFT                       0
> +#define DLL_CALIB_INTERVAL_MASK                                (0x1ff << 0)
> +
> +/* END_OF_INTERRUPT */
> +#define EOI_SHIFT                                      0
> +#define EOI_MASK                                       (1 << 0)
> +
> +/* SYSTEM_OCP_INTERRUPT_RAW_STATUS */
> +#define DNV_SYS_SHIFT                                  2
> +#define DNV_SYS_MASK                                   (1 << 2)
> +#define TA_SYS_SHIFT                                   1
> +#define TA_SYS_MASK                                    (1 << 1)
> +#define ERR_SYS_SHIFT                                  0
> +#define ERR_SYS_MASK                                   (1 << 0)
> +
> +/* LOW_LATENCY_OCP_INTERRUPT_RAW_STATUS */
> +#define DNV_LL_SHIFT                                   2
> +#define DNV_LL_MASK                                    (1 << 2)
> +#define TA_LL_SHIFT                                    1
> +#define TA_LL_MASK                                     (1 << 1)
> +#define ERR_LL_SHIFT                                   0
> +#define ERR_LL_MASK                                    (1 << 0)
> +
> +/* SYSTEM_OCP_INTERRUPT_ENABLE_SET */
> +#define EN_DNV_SYS_SHIFT                               2
> +#define EN_DNV_SYS_MASK                                        (1 << 2)
> +#define EN_TA_SYS_SHIFT                                        1
> +#define EN_TA_SYS_MASK                                 (1 << 1)
> +#define EN_ERR_SYS_SHIFT                                       0
> +#define EN_ERR_SYS_MASK                                        (1 << 0)
> +
> +/* LOW_LATENCY_OCP_INTERRUPT_ENABLE_SET */
> +#define EN_DNV_LL_SHIFT                                        2
> +#define EN_DNV_LL_MASK                                 (1 << 2)
> +#define EN_TA_LL_SHIFT                                 1
> +#define EN_TA_LL_MASK                                  (1 << 1)
> +#define EN_ERR_LL_SHIFT                                        0
> +#define EN_ERR_LL_MASK                                 (1 << 0)
> +
> +/* SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG */
> +#define ZQ_CS1EN_SHIFT                                 31
> +#define ZQ_CS1EN_MASK                                  (1 << 31)
> +#define ZQ_CS0EN_SHIFT                                 30
> +#define ZQ_CS0EN_MASK                                  (1 << 30)
> +#define ZQ_DUALCALEN_SHIFT                             29
> +#define ZQ_DUALCALEN_MASK                              (1 << 29)
> +#define ZQ_SFEXITEN_SHIFT                              28
> +#define ZQ_SFEXITEN_MASK                               (1 << 28)
> +#define ZQ_ZQINIT_MULT_SHIFT                           18
> +#define ZQ_ZQINIT_MULT_MASK                            (0x3 << 18)
> +#define ZQ_ZQCL_MULT_SHIFT                             16
> +#define ZQ_ZQCL_MULT_MASK                              (0x3 << 16)
> +#define ZQ_REFINTERVAL_SHIFT                           0
> +#define ZQ_REFINTERVAL_MASK                            (0xffff << 0)
> +
> +/* TEMPERATURE_ALERT_CONFIG */
> +#define TA_CS1EN_SHIFT                                 31
> +#define TA_CS1EN_MASK                                  (1 << 31)
> +#define TA_CS0EN_SHIFT                                 30
> +#define TA_CS0EN_MASK                                  (1 << 30)
> +#define TA_SFEXITEN_SHIFT                              28
> +#define TA_SFEXITEN_MASK                               (1 << 28)
> +#define TA_DEVWDT_SHIFT                                        26
> +#define TA_DEVWDT_MASK                                 (0x3 << 26)
> +#define TA_DEVCNT_SHIFT                                        24
> +#define TA_DEVCNT_MASK                                 (0x3 << 24)
> +#define TA_REFINTERVAL_SHIFT                           0
> +#define TA_REFINTERVAL_MASK                            (0x3fffff << 0)
> +
> +/* OCP_ERROR_LOG */
> +#define MADDRSPACE_SHIFT                               14
> +#define MADDRSPACE_MASK                                        (0x3 << 14)
> +#define MBURSTSEQ_SHIFT                                        11
> +#define MBURSTSEQ_MASK                                 (0x7 << 11)
> +#define MCMD_SHIFT                                     8
> +#define MCMD_MASK                                      (0x7 << 8)
> +#define MCONNID_SHIFT                                  0
> +#define MCONNID_MASK                                   (0xff << 0)
> +
> +/* DDR_PHY_CTRL_1 - EMIF4D */
> +#define DLL_SLAVE_DLY_CTRL_SHIFT_4D                    4
> +#define DLL_SLAVE_DLY_CTRL_MASK_4D                     (0xFF << 4)
> +#define READ_LATENCY_SHIFT_4D                          0
> +#define READ_LATENCY_MASK_4D                           (0xf << 0)
> +
> +/* DDR_PHY_CTRL_1 - EMIF4D5 */
> +#define DLL_HALF_DELAY_SHIFT_4D5                       21
> +#define DLL_HALF_DELAY_MASK_4D5                                (1 << 21)
> +#define READ_LATENCY_SHIFT_4D5                         0
> +#define READ_LATENCY_MASK_4D5                          (0x1f << 0)
> +
> +/* DDR_PHY_CTRL_1_SHDW */
> +#define DDR_PHY_CTRL_1_SHDW_SHIFT                      5
> +#define DDR_PHY_CTRL_1_SHDW_MASK                       (0x7ffffff << 5)
> +#define READ_LATENCY_SHDW_SHIFT                                0
> +#define READ_LATENCY_SHDW_MASK                         (0x1f << 0)
> +
> +#endif /* __TI_EMIF_H */
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08  0:52     ` Russ Dill
  -1 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08  0:52 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman, Vaibhav Bedia

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> Interacting with WKUP-M3 requires some more control
> module register writes. Add the register offsets and
> APIs to write to these.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>

Reviewed-by: Russ Dill <russ.dill@ti.com>

> ---
>  arch/arm/mach-omap2/control.c |   57 +++++++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/control.h |   54 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 111 insertions(+)
>
> diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
> index 31e0dfe..934041a 100644
> --- a/arch/arm/mach-omap2/control.c
> +++ b/arch/arm/mach-omap2/control.c
> @@ -605,3 +605,60 @@ int omap3_ctrl_save_padconf(void)
>  }
>
>  #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
> +
> +#if defined(CONFIG_SOC_AM33XX) && defined(CONFIG_PM)
> +void am33xx_txev_eoi(void)
> +{
> +       omap_ctrl_writel(AM33XX_M3_TXEV_ACK, AM33XX_CONTROL_M3_TXEV_EOI);
> +}
> +
> +void am33xx_txev_enable(void)
> +{
> +       omap_ctrl_writel(AM33XX_M3_TXEV_ENABLE, AM33XX_CONTROL_M3_TXEV_EOI);
> +}
> +
> +/*
> + * Invalidate M3 firmware version before hardreset.
> + * Write invalid version in lower 4 nibbles of parameter
> + * register (ipc_regs + 0x8).
> + */
> +void am33xx_pm_version_clear(void)
> +{
> +       omap_ctrl_writel(0xffff0000, AM33XX_CONTROL_IPC_MSG_REG2);
> +}
> +
> +int am33xx_pm_version_get(void)
> +{
> +       return omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG2) & M3_VERSION_MASK;
> +}
> +
> +void am33xx_pm_ipc_cmd(struct am33xx_ipc_data *data)
> +{
> +       omap_ctrl_writel(data->resume_addr, AM33XX_CONTROL_IPC_MSG_REG0);
> +       omap_ctrl_writel(data->sleep_mode, AM33XX_CONTROL_IPC_MSG_REG1);
> +       omap_ctrl_writel(data->param1, AM33XX_CONTROL_IPC_MSG_REG2);
> +       omap_ctrl_writel(data->param2, AM33XX_CONTROL_IPC_MSG_REG3);
> +       omap_ctrl_writel(data->param3, AM33XX_CONTROL_IPC_MSG_REG4);
> +}
> +
> +int am33xx_pm_status(void)
> +{
> +       int i;
> +
> +       i = omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG1);
> +       i &= IPC_RESP_MASK;
> +       i >>= __ffs(IPC_RESP_MASK);
> +
> +       return i;
> +}
> +
> +int am33xx_pm_wake_src(void)
> +{
> +       int i;
> +
> +       i = omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG6);
> +       i &= 0xff;
> +
> +       return i;
> +}
> +#endif /* CONFIG_SOC_AM33XX && CONFIG_PM */
> diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
> index f7d7c2e..9be587c 100644
> --- a/arch/arm/mach-omap2/control.h
> +++ b/arch/arm/mach-omap2/control.h
> @@ -370,6 +370,22 @@
>  #define AM33XX_DEV_FEATURE             0x604
>  #define AM33XX_SGX_MASK                        BIT(29)
>
> +/* AM33XX M3_TXEV_EOI register */
> +#define AM33XX_CONTROL_M3_TXEV_EOI     0x1324
> +
> +#define AM33XX_M3_TXEV_ACK             (0x1 << 0)
> +#define AM33XX_M3_TXEV_ENABLE          (0x0 << 0)
> +
> +/* AM33XX IPC message registers */
> +#define AM33XX_CONTROL_IPC_MSG_REG0    0x1328
> +#define AM33XX_CONTROL_IPC_MSG_REG1    0x132C
> +#define AM33XX_CONTROL_IPC_MSG_REG2    0x1330
> +#define AM33XX_CONTROL_IPC_MSG_REG3    0x1334
> +#define AM33XX_CONTROL_IPC_MSG_REG4    0x1338
> +#define AM33XX_CONTROL_IPC_MSG_REG5    0x133C
> +#define AM33XX_CONTROL_IPC_MSG_REG6    0x1340
> +#define AM33XX_CONTROL_IPC_MSG_REG7    0x1344
> +
>  /* CONTROL OMAP STATUS register to identify OMAP3 features */
>  #define OMAP3_CONTROL_OMAP_STATUS      0x044c
>
> @@ -429,6 +445,44 @@ extern void omap3630_ctrl_disable_rta(void);
>  extern int omap3_ctrl_save_padconf(void);
>  extern void omap2_set_globals_control(void __iomem *ctrl,
>                                       void __iomem *ctrl_pad);
> +struct am33xx_ipc_data {
> +       u32 resume_addr;
> +       u32 sleep_mode;
> +       u32 param1;
> +       u32 param2;
> +       u32 param3;
> +       u32 param4;
> +       u32 param5;
> +       u32 param6;
> +};
> +
> +#define IPC_RESP_SHIFT                 16
> +#define IPC_RESP_MASK                  (0xffff << 16)
> +
> +#define M3_VERSION_SHIFT               0
> +#define M3_VERSION_MASK                        (0xffff << 0)
> +
> +/*
> + * 9-4 = VTT GPIO PIN (6 Bits)
> + *   3 = VTT Status (1 Bit)
> + * 2-0 = Memory Type (2 Bits)
> +*/
> +#define MEM_TYPE_SHIFT         (0x0)
> +#define MEM_TYPE_MASK          (0x7 << 0)
> +#define VTT_STAT_SHIFT         (0x3)
> +#define VTT_STAT_MASK          (0x1 << 3)
> +#define VTT_GPIO_PIN_SHIFT     (0x4)
> +#define VTT_GPIO_PIN_MASK      (0x2f << 4)
> +
> +extern void am33xx_wkup_m3_ipc_cmd(struct am33xx_ipc_data *data);
> +extern void am33xx_txev_eoi(void);
> +extern void am33xx_txev_enable(void);
> +extern void am33xx_pm_version_clear(void);
> +extern int am33xx_pm_version_get(void);
> +extern void am33xx_pm_ipc_cmd(struct am33xx_ipc_data *data);
> +extern int am33xx_pm_status(void);
> +extern int am33xx_pm_wake_src(void);
> +
>  #else
>  #define omap_ctrl_base_get()           0
>  #define omap_ctrl_readb(x)             0
> --
> 1.7.9.5
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-08  0:52     ` Russ Dill
  0 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08  0:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> Interacting with WKUP-M3 requires some more control
> module register writes. Add the register offsets and
> APIs to write to these.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>

Reviewed-by: Russ Dill <russ.dill@ti.com>

> ---
>  arch/arm/mach-omap2/control.c |   57 +++++++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/control.h |   54 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 111 insertions(+)
>
> diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
> index 31e0dfe..934041a 100644
> --- a/arch/arm/mach-omap2/control.c
> +++ b/arch/arm/mach-omap2/control.c
> @@ -605,3 +605,60 @@ int omap3_ctrl_save_padconf(void)
>  }
>
>  #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
> +
> +#if defined(CONFIG_SOC_AM33XX) && defined(CONFIG_PM)
> +void am33xx_txev_eoi(void)
> +{
> +       omap_ctrl_writel(AM33XX_M3_TXEV_ACK, AM33XX_CONTROL_M3_TXEV_EOI);
> +}
> +
> +void am33xx_txev_enable(void)
> +{
> +       omap_ctrl_writel(AM33XX_M3_TXEV_ENABLE, AM33XX_CONTROL_M3_TXEV_EOI);
> +}
> +
> +/*
> + * Invalidate M3 firmware version before hardreset.
> + * Write invalid version in lower 4 nibbles of parameter
> + * register (ipc_regs + 0x8).
> + */
> +void am33xx_pm_version_clear(void)
> +{
> +       omap_ctrl_writel(0xffff0000, AM33XX_CONTROL_IPC_MSG_REG2);
> +}
> +
> +int am33xx_pm_version_get(void)
> +{
> +       return omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG2) & M3_VERSION_MASK;
> +}
> +
> +void am33xx_pm_ipc_cmd(struct am33xx_ipc_data *data)
> +{
> +       omap_ctrl_writel(data->resume_addr, AM33XX_CONTROL_IPC_MSG_REG0);
> +       omap_ctrl_writel(data->sleep_mode, AM33XX_CONTROL_IPC_MSG_REG1);
> +       omap_ctrl_writel(data->param1, AM33XX_CONTROL_IPC_MSG_REG2);
> +       omap_ctrl_writel(data->param2, AM33XX_CONTROL_IPC_MSG_REG3);
> +       omap_ctrl_writel(data->param3, AM33XX_CONTROL_IPC_MSG_REG4);
> +}
> +
> +int am33xx_pm_status(void)
> +{
> +       int i;
> +
> +       i = omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG1);
> +       i &= IPC_RESP_MASK;
> +       i >>= __ffs(IPC_RESP_MASK);
> +
> +       return i;
> +}
> +
> +int am33xx_pm_wake_src(void)
> +{
> +       int i;
> +
> +       i = omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG6);
> +       i &= 0xff;
> +
> +       return i;
> +}
> +#endif /* CONFIG_SOC_AM33XX && CONFIG_PM */
> diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
> index f7d7c2e..9be587c 100644
> --- a/arch/arm/mach-omap2/control.h
> +++ b/arch/arm/mach-omap2/control.h
> @@ -370,6 +370,22 @@
>  #define AM33XX_DEV_FEATURE             0x604
>  #define AM33XX_SGX_MASK                        BIT(29)
>
> +/* AM33XX M3_TXEV_EOI register */
> +#define AM33XX_CONTROL_M3_TXEV_EOI     0x1324
> +
> +#define AM33XX_M3_TXEV_ACK             (0x1 << 0)
> +#define AM33XX_M3_TXEV_ENABLE          (0x0 << 0)
> +
> +/* AM33XX IPC message registers */
> +#define AM33XX_CONTROL_IPC_MSG_REG0    0x1328
> +#define AM33XX_CONTROL_IPC_MSG_REG1    0x132C
> +#define AM33XX_CONTROL_IPC_MSG_REG2    0x1330
> +#define AM33XX_CONTROL_IPC_MSG_REG3    0x1334
> +#define AM33XX_CONTROL_IPC_MSG_REG4    0x1338
> +#define AM33XX_CONTROL_IPC_MSG_REG5    0x133C
> +#define AM33XX_CONTROL_IPC_MSG_REG6    0x1340
> +#define AM33XX_CONTROL_IPC_MSG_REG7    0x1344
> +
>  /* CONTROL OMAP STATUS register to identify OMAP3 features */
>  #define OMAP3_CONTROL_OMAP_STATUS      0x044c
>
> @@ -429,6 +445,44 @@ extern void omap3630_ctrl_disable_rta(void);
>  extern int omap3_ctrl_save_padconf(void);
>  extern void omap2_set_globals_control(void __iomem *ctrl,
>                                       void __iomem *ctrl_pad);
> +struct am33xx_ipc_data {
> +       u32 resume_addr;
> +       u32 sleep_mode;
> +       u32 param1;
> +       u32 param2;
> +       u32 param3;
> +       u32 param4;
> +       u32 param5;
> +       u32 param6;
> +};
> +
> +#define IPC_RESP_SHIFT                 16
> +#define IPC_RESP_MASK                  (0xffff << 16)
> +
> +#define M3_VERSION_SHIFT               0
> +#define M3_VERSION_MASK                        (0xffff << 0)
> +
> +/*
> + * 9-4 = VTT GPIO PIN (6 Bits)
> + *   3 = VTT Status (1 Bit)
> + * 2-0 = Memory Type (2 Bits)
> +*/
> +#define MEM_TYPE_SHIFT         (0x0)
> +#define MEM_TYPE_MASK          (0x7 << 0)
> +#define VTT_STAT_SHIFT         (0x3)
> +#define VTT_STAT_MASK          (0x1 << 3)
> +#define VTT_GPIO_PIN_SHIFT     (0x4)
> +#define VTT_GPIO_PIN_MASK      (0x2f << 4)
> +
> +extern void am33xx_wkup_m3_ipc_cmd(struct am33xx_ipc_data *data);
> +extern void am33xx_txev_eoi(void);
> +extern void am33xx_txev_enable(void);
> +extern void am33xx_pm_version_clear(void);
> +extern int am33xx_pm_version_get(void);
> +extern void am33xx_pm_ipc_cmd(struct am33xx_ipc_data *data);
> +extern int am33xx_pm_status(void);
> +extern int am33xx_pm_wake_src(void);
> +
>  #else
>  #define omap_ctrl_base_get()           0
>  #define omap_ctrl_readb(x)             0
> --
> 1.7.9.5
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 3/9] ARM: OMAP: DTB: Update IRQ data for WKUP_M3
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08  0:53     ` Russ Dill
  -1 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08  0:53 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman,
	Vaibhav Bedia, Benoit Cousson

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> Allow interrupt for wkup_m3 to be set from DT.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> Cc: Benoit Cousson <benoit.cousson@linaro.org>

Reviewed-by: Russ Dill <russ.dill@ti.com>

> ---
>  arch/arm/boot/dts/am33xx.dtsi |    1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
> index 38b446b..05353bf 100644
> --- a/arch/arm/boot/dts/am33xx.dtsi
> +++ b/arch/arm/boot/dts/am33xx.dtsi
> @@ -491,6 +491,7 @@
>                         compatible = "ti,am3353-wkup-m3";
>                         reg = <0x44d00000 0x4000        /* M3 UMEM */
>                                0x44d80000 0x2000>;      /* M3 DMEM */
> +                       interrupts = <78>;
>                         ti,hwmods = "wkup_m3";
>                 };
>
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 3/9] ARM: OMAP: DTB: Update IRQ data for WKUP_M3
@ 2013-08-08  0:53     ` Russ Dill
  0 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08  0:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> Allow interrupt for wkup_m3 to be set from DT.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> Cc: Benoit Cousson <benoit.cousson@linaro.org>

Reviewed-by: Russ Dill <russ.dill@ti.com>

> ---
>  arch/arm/boot/dts/am33xx.dtsi |    1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
> index 38b446b..05353bf 100644
> --- a/arch/arm/boot/dts/am33xx.dtsi
> +++ b/arch/arm/boot/dts/am33xx.dtsi
> @@ -491,6 +491,7 @@
>                         compatible = "ti,am3353-wkup-m3";
>                         reg = <0x44d00000 0x4000        /* M3 UMEM */
>                                0x44d80000 0x2000>;      /* M3 DMEM */
> +                       interrupts = <78>;
>                         ti,hwmods = "wkup_m3";
>                 };
>
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08  2:30     ` Russ Dill
  -1 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08  2:30 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman, Vaibhav Bedia

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> SDRAM controller on AM33XX requires that a modification of certain
> bit-fields in PWR_MGMT_CTRL register (ref. section 7.3.5.13 in
> AM335x-Rev H) is followed by a dummy read access to SDRAM. This
> scenario arises when entering a low power state like DeepSleep.
> To ensure that the read is not from a cached region we reserve
> some memory during bootup using the arm_memblock_steal() API.
>
> A subsequent patch will pass along the location of the reserved
> memory location to the AM335x suspend handler which modifies the
> PWR_MGMT_CTRL register in the EMIF.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>

Reviewed-by: Russ Dill <russ.dill@ti.com>

> ---
>  arch/arm/mach-omap2/board-generic.c |    2 +-
>  arch/arm/mach-omap2/common.c        |   28 ++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/common.h        |    4 ++++
>  arch/arm/mach-omap2/io.c            |    1 +
>  4 files changed, 34 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
> index be5d005..aed750c 100644
> --- a/arch/arm/mach-omap2/board-generic.c
> +++ b/arch/arm/mach-omap2/board-generic.c
> @@ -156,7 +156,7 @@ static const char *am33xx_boards_compat[] __initdata = {
>  };
>
>  DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)")
> -       .reserve        = omap_reserve,
> +       .reserve        = am33xx_reserve,
>         .map_io         = am33xx_map_io,
>         .init_early     = am33xx_init_early,
>         .init_irq       = omap_intc_of_init,
> diff --git a/arch/arm/mach-omap2/common.c b/arch/arm/mach-omap2/common.c
> index 2dabb9e..756586f 100644
> --- a/arch/arm/mach-omap2/common.c
> +++ b/arch/arm/mach-omap2/common.c
> @@ -15,6 +15,8 @@
>  #include <linux/kernel.h>
>  #include <linux/init.h>
>  #include <linux/platform_data/dsp-omap.h>
> +#include <asm/memblock.h>
> +#include <asm/mach/map.h>
>
>  #include "common.h"
>  #include "omap-secure.h"
> @@ -34,3 +36,29 @@ void __init omap_reserve(void)
>         omap_secure_ram_reserve_memblock();
>         omap_barrier_reserve_memblock();
>  }
> +
> +static phys_addr_t am33xx_paddr;
> +static u32 am33xx_size;
> +
> +/* Steal one page physical memory for uncached read DeepSleep */
> +void __init am33xx_reserve(void)
> +{
> +       am33xx_size = ALIGN(PAGE_SIZE, SZ_1M);
> +       am33xx_paddr = arm_memblock_steal(am33xx_size, SZ_1M);
> +}
> +
> +void __iomem *am33xx_dram_sync;
> +
> +void __init am33xx_dram_sync_init(void)
> +{
> +       struct map_desc dram_io_desc[1];
> +
> +       dram_io_desc[0].virtual = __phys_to_virt(am33xx_paddr);
> +       dram_io_desc[0].pfn = __phys_to_pfn(am33xx_paddr);
> +       dram_io_desc[0].length = am33xx_size;
> +       dram_io_desc[0].type = MT_MEMORY_SO;
> +
> +       iotable_init(dram_io_desc, ARRAY_SIZE(dram_io_desc));
> +
> +       am33xx_dram_sync = (void __iomem *) dram_io_desc[0].virtual;
> +}
> diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
> index dfcc182..6b8ef74 100644
> --- a/arch/arm/mach-omap2/common.h
> +++ b/arch/arm/mach-omap2/common.h
> @@ -294,6 +294,10 @@ struct omap2_hsmmc_info;
>  extern int omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers);
>  extern void omap_reserve(void);
>
> +extern void am33xx_reserve(void);
> +extern void am33xx_dram_sync_init(void);
> +extern void __iomem *am33xx_dram_sync;
> +
>  struct omap_hwmod;
>  extern int omap_dss_reset(struct omap_hwmod *);
>
> diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
> index 4a3f06f..3ad7543 100644
> --- a/arch/arm/mach-omap2/io.c
> +++ b/arch/arm/mach-omap2/io.c
> @@ -322,6 +322,7 @@ void __init ti81xx_map_io(void)
>  void __init am33xx_map_io(void)
>  {
>         iotable_init(omapam33xx_io_desc, ARRAY_SIZE(omapam33xx_io_desc));
> +       am33xx_dram_sync_init();
>  }
>  #endif
>
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
@ 2013-08-08  2:30     ` Russ Dill
  0 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08  2:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> SDRAM controller on AM33XX requires that a modification of certain
> bit-fields in PWR_MGMT_CTRL register (ref. section 7.3.5.13 in
> AM335x-Rev H) is followed by a dummy read access to SDRAM. This
> scenario arises when entering a low power state like DeepSleep.
> To ensure that the read is not from a cached region we reserve
> some memory during bootup using the arm_memblock_steal() API.
>
> A subsequent patch will pass along the location of the reserved
> memory location to the AM335x suspend handler which modifies the
> PWR_MGMT_CTRL register in the EMIF.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>

Reviewed-by: Russ Dill <russ.dill@ti.com>

> ---
>  arch/arm/mach-omap2/board-generic.c |    2 +-
>  arch/arm/mach-omap2/common.c        |   28 ++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/common.h        |    4 ++++
>  arch/arm/mach-omap2/io.c            |    1 +
>  4 files changed, 34 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
> index be5d005..aed750c 100644
> --- a/arch/arm/mach-omap2/board-generic.c
> +++ b/arch/arm/mach-omap2/board-generic.c
> @@ -156,7 +156,7 @@ static const char *am33xx_boards_compat[] __initdata = {
>  };
>
>  DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)")
> -       .reserve        = omap_reserve,
> +       .reserve        = am33xx_reserve,
>         .map_io         = am33xx_map_io,
>         .init_early     = am33xx_init_early,
>         .init_irq       = omap_intc_of_init,
> diff --git a/arch/arm/mach-omap2/common.c b/arch/arm/mach-omap2/common.c
> index 2dabb9e..756586f 100644
> --- a/arch/arm/mach-omap2/common.c
> +++ b/arch/arm/mach-omap2/common.c
> @@ -15,6 +15,8 @@
>  #include <linux/kernel.h>
>  #include <linux/init.h>
>  #include <linux/platform_data/dsp-omap.h>
> +#include <asm/memblock.h>
> +#include <asm/mach/map.h>
>
>  #include "common.h"
>  #include "omap-secure.h"
> @@ -34,3 +36,29 @@ void __init omap_reserve(void)
>         omap_secure_ram_reserve_memblock();
>         omap_barrier_reserve_memblock();
>  }
> +
> +static phys_addr_t am33xx_paddr;
> +static u32 am33xx_size;
> +
> +/* Steal one page physical memory for uncached read DeepSleep */
> +void __init am33xx_reserve(void)
> +{
> +       am33xx_size = ALIGN(PAGE_SIZE, SZ_1M);
> +       am33xx_paddr = arm_memblock_steal(am33xx_size, SZ_1M);
> +}
> +
> +void __iomem *am33xx_dram_sync;
> +
> +void __init am33xx_dram_sync_init(void)
> +{
> +       struct map_desc dram_io_desc[1];
> +
> +       dram_io_desc[0].virtual = __phys_to_virt(am33xx_paddr);
> +       dram_io_desc[0].pfn = __phys_to_pfn(am33xx_paddr);
> +       dram_io_desc[0].length = am33xx_size;
> +       dram_io_desc[0].type = MT_MEMORY_SO;
> +
> +       iotable_init(dram_io_desc, ARRAY_SIZE(dram_io_desc));
> +
> +       am33xx_dram_sync = (void __iomem *) dram_io_desc[0].virtual;
> +}
> diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
> index dfcc182..6b8ef74 100644
> --- a/arch/arm/mach-omap2/common.h
> +++ b/arch/arm/mach-omap2/common.h
> @@ -294,6 +294,10 @@ struct omap2_hsmmc_info;
>  extern int omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers);
>  extern void omap_reserve(void);
>
> +extern void am33xx_reserve(void);
> +extern void am33xx_dram_sync_init(void);
> +extern void __iomem *am33xx_dram_sync;
> +
>  struct omap_hwmod;
>  extern int omap_dss_reset(struct omap_hwmod *);
>
> diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
> index 4a3f06f..3ad7543 100644
> --- a/arch/arm/mach-omap2/io.c
> +++ b/arch/arm/mach-omap2/io.c
> @@ -322,6 +322,7 @@ void __init ti81xx_map_io(void)
>  void __init am33xx_map_io(void)
>  {
>         iotable_init(omapam33xx_io_desc, ARRAY_SIZE(omapam33xx_io_desc));
> +       am33xx_dram_sync_init();
>  }
>  #endif
>
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 5/9] ARM: OMAP2+: AM33XX: Add assembly code for PM operations
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08  7:02     ` Russ Dill
  -1 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08  7:02 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman,
	Vaibhav Bedia, Santosh Shilimkar

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> In preparation for suspend-resume support for AM33XX, add
> the assembly file with the code which is copied to internal
> memory (OCMC RAM) during bootup and runs from there.
>
> As part of the low power entry (DeepSleep0 mode in AM33XX TRM),
> the code running from OCMC RAM does the following
> 1. Stores the EMIF configuration
> 2. Puts external memory in self-refresh
> 3. Disables EMIF clock
> 4. Executes WFI after writing to MPU_CLKCTRL register.
>
> If no interrupts have come, WFI execution on MPU gets registered
> as an interrupt with the WKUP-M3. WKUP-M3 takes care of disabling
> some clocks which MPU should not (L3, L4, OCMC RAM etc) and takes
> care of clockdomain and powerdomain transitions as part of the
> DeepSleep0 mode entry.
>
> In case a late interrupt comes in, WFI ends up as a NOP and MPU
> continues execution from internal memory. The 'abort path' code
> undoes whatever was done as part of the low power entry and indicates
> a suspend failure by passing a non-zero value to the cpu_resume routine.
>
> The 'resume path' code is similar to the 'abort path' with the key
> difference of MMU being enabled in the 'abort path' but being
> disabled in the 'resume path' due to MPU getting powered off.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Kevin Hilman <khilman@linaro.org>

Reviewed-by: Russ Dill <russ.dill@ti.com>

> ---
>  arch/arm/mach-omap2/sleep33xx.S |  350 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 350 insertions(+)
>  create mode 100644 arch/arm/mach-omap2/sleep33xx.S
>
> diff --git a/arch/arm/mach-omap2/sleep33xx.S b/arch/arm/mach-omap2/sleep33xx.S
> new file mode 100644
> index 0000000..834c7d4
> --- /dev/null
> +++ b/arch/arm/mach-omap2/sleep33xx.S
> @@ -0,0 +1,350 @@
> +/*
> + * Low level suspend code for AM33XX SoCs
> + *
> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
> + * Vaibhav Bedia <vaibhav.bedia@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/linkage.h>
> +#include <linux/ti_emif.h>
> +#include <asm/memory.h>
> +#include <asm/assembler.h>
> +
> +#include "cm33xx.h"
> +#include "pm33xx.h"
> +#include "prm33xx.h"
> +
> +       .text
> +       .align 3
> +
> +/*
> + * This routine is executed from internal RAM and expects some
> + * parameters to be passed in r0 _strictly_ in following order:
> + * 1) emif_addr_virt - ioremapped EMIF address
> + * 2) mem_type - 2 -> DDR2, 3-> DDR3
> + * 3) dram_sync_word - uncached word in SDRAM
> + *
> + * The code loads these values taking r0 value as reference to
> + * the array in registers starting from r0, i.e emif_addr_virt
> + * goes to r1, mem_type goes to r2 and and so on. These are
> + * then saved into memory locations before proceeding with the
> + * sleep sequence and hence registers r0, r1 etc can still be
> + * used in the rest of the sleep code.
> + */
> +
> +ENTRY(am33xx_do_wfi)
> +       stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
> +
> +       ldm     r0, {r1-r3}             @ gather values passed
> +
> +       /* Save the values passed */
> +       str     r1, emif_addr_virt
> +       str     r2, mem_type
> +       str     r3, dram_sync_word
> +
> +       /*
> +        * Flush all data from the L1 data cache before disabling
> +        * SCTLR.C bit.
> +        */
> +       ldr     r1, kernel_flush
> +       blx     r1
> +
> +       /*
> +        * Clear the SCTLR.C bit to prevent further data cache
> +        * allocation. Clearing SCTLR.C would make all the data accesses
> +        * strongly ordered and would not hit the cache.
> +        */
> +       mrc     p15, 0, r0, c1, c0, 0
> +       bic     r0, r0, #(1 << 2)       @ Disable the C bit
> +       mcr     p15, 0, r0, c1, c0, 0
> +       isb
> +
> +       /*
> +        * Invalidate L1 data cache. Even though only invalidate is
> +        * necessary exported flush API is used here. Doing clean
> +        * on already clean cache would be almost NOP.
> +        */
> +       ldr     r1, kernel_flush
> +       blx     r1
> +
> +       ldr     r0, emif_addr_virt
> +       /* Save EMIF configuration */
> +       ldr     r1, [r0, #EMIF_SDRAM_CONFIG]
> +       str     r1, emif_sdcfg_val
> +       ldr     r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
> +       str     r1, emif_ref_ctrl_val
> +       ldr     r1, [r0, #EMIF_SDRAM_TIMING_1]
> +       str     r1, emif_timing1_val
> +       ldr     r1, [r0, #EMIF_SDRAM_TIMING_2]
> +       str     r1, emif_timing2_val
> +       ldr     r1, [r0, #EMIF_SDRAM_TIMING_3]
> +       str     r1, emif_timing3_val
> +       ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +       str     r1, emif_pmcr_val
> +       ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
> +       str     r1, emif_pmcr_shdw_val
> +       ldr     r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
> +       str     r1, emif_zqcfg_val
> +       ldr     r1, [r0, #EMIF_DDR_PHY_CTRL_1]
> +       str     r1, emif_rd_lat_val
> +
> +       /* Put SDRAM in self-refresh */
> +       ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +       orr     r1, r1, #0xa0
> +       str     r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
> +       str     r1, [r0, #4]
> +
> +       ldr     r1, dram_sync_word      @ a dummy access to DDR as per spec
> +       ldr     r2, [r1, #0]
> +       ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +       orr     r1, r1, #0x200
> +       str     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +
> +       mov     r1, #0x1000             @ Wait for system to enter SR
> +wait_sr:
> +       subs    r1, r1, #1
> +       bne     wait_sr
> +
> +       /* Disable EMIF */
> +       ldr     r1, virt_emif_clkctrl
> +       ldr     r2, [r1]
> +       bic     r2, r2, #0x03
> +       str     r2, [r1]
> +
> +       ldr     r1, virt_emif_clkctrl
> +wait_emif_disable:
> +       ldr     r2, [r1]
> +       ldr     r3, module_disabled_val
> +       cmp     r2, r3
> +       bne     wait_emif_disable
> +
> +       /*
> +        * For the MPU WFI to be registered as an interrupt
> +        * to WKUP_M3, MPU_CLKCTRL.MODULEMODE needs to be set
> +        * to DISABLED
> +        */
> +       ldr     r1, virt_mpu_clkctrl
> +       ldr     r2, [r1]
> +       bic     r2, r2, #0x03
> +       str     r2, [r1]
> +
> +       /*
> +        * Execute an ISB instruction to ensure that all of the
> +        * CP15 register changes have been committed.
> +        */
> +       isb
> +
> +       /*
> +        * Execute a barrier instruction to ensure that all cache,
> +        * TLB and branch predictor maintenance operations issued
> +        * have completed.
> +        */
> +       dsb
> +       dmb
> +
> +       /*
> +        * Execute a WFI instruction and wait until the
> +        * STANDBYWFI output is asserted to indicate that the
> +        * CPU is in idle and low power state. CPU can specualatively
> +        * prefetch the instructions so add NOPs after WFI. Thirteen
> +        * NOPs as per Cortex-A8 pipeline.
> +        */
> +       wfi
> +
> +       nop
> +       nop
> +       nop
> +       nop
> +       nop
> +       nop
> +       nop
> +       nop
> +       nop
> +       nop
> +       nop
> +       nop
> +       nop
> +
> +       /* We come here in case of an abort due to a late interrupt */
> +
> +       /* Set MPU_CLKCTRL.MODULEMODE back to ENABLE */
> +       ldr     r1, virt_mpu_clkctrl
> +       mov     r2, #0x02
> +       str     r2, [r1]
> +
> +       /* Re-enable EMIF */
> +       ldr     r1, virt_emif_clkctrl
> +       mov     r2, #0x02
> +       str     r2, [r1]
> +wait_emif_enable:
> +       ldr     r3, [r1]
> +       cmp     r2, r3
> +       bne     wait_emif_enable
> +
> +       /* Disable EMIF self-refresh */
> +       ldr     r0, emif_addr_virt
> +       ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +       bic     r1, r1, #LP_MODE_MASK
> +       str     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +       str     r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
> +
> +       /*
> +        * A write to SDRAM CONFIG register triggers
> +        * an init sequence and hence it must be done
> +        * at the end for DDR2
> +        */
> +       ldr r0, emif_addr_virt
> +       add r0, r0, #EMIF_SDRAM_CONFIG
> +       ldr r4, emif_sdcfg_val
> +       str r4, [r0]
> +
> +       /*
> +        * Set SCTLR.C bit to allow data cache allocation
> +        */
> +       mrc     p15, 0, r0, c1, c0, 0
> +       orr     r0, r0, #(1 << 2)       @ Enable the C bit
> +       mcr     p15, 0, r0, c1, c0, 0
> +       isb
> +
> +       /* Kill some time for sanity to settle in */
> +       mov r0, #0x1000
> +wait_abt:
> +       subs   r0, r0, #1
> +       bne wait_abt
> +
> +       /* Let the suspend code know about the abort */
> +       mov     r0, #1
> +       ldmfd   sp!, {r4 - r11, pc}     @ restore regs and return
> +ENDPROC(am33xx_do_wfi)
> +
> +       .align
> +ENTRY(am33xx_resume_offset)
> +       .word . - am33xx_do_wfi
> +
> +ENTRY(am33xx_resume_from_deep_sleep)
> +       /* Re-enable EMIF */
> +       ldr     r0, phys_emif_clkctrl
> +       mov     r1, #0x02
> +       str     r1, [r0]
> +wait_emif_enable1:
> +       ldr     r2, [r0]
> +       cmp     r1, r2
> +       bne     wait_emif_enable1
> +
> +       /* Config EMIF Timings */
> +       ldr     r0, emif_phys_addr
> +       ldr     r1, emif_rd_lat_val
> +       str     r1, [r0, #EMIF_DDR_PHY_CTRL_1]
> +       str     r1, [r0, #EMIF_DDR_PHY_CTRL_1_SHDW]
> +       ldr     r1, emif_timing1_val
> +       str     r1, [r0, #EMIF_SDRAM_TIMING_1]
> +       str     r1, [r0, #EMIF_SDRAM_TIMING_1_SHDW]
> +       ldr     r1, emif_timing2_val
> +       str     r1, [r0, #EMIF_SDRAM_TIMING_2]
> +       str     r1, [r0, #EMIF_SDRAM_TIMING_2_SHDW]
> +       ldr     r1, emif_timing3_val
> +       str     r1, [r0, #EMIF_SDRAM_TIMING_3]
> +       str     r1, [r0, #EMIF_SDRAM_TIMING_3_SHDW]
> +       ldr     r1, emif_ref_ctrl_val
> +       str     r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
> +       str     r1, [r0, #EMIF_SDRAM_REFRESH_CTRL_SHDW]
> +       ldr     r1, emif_pmcr_val
> +       str     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +       ldr     r1, emif_pmcr_shdw_val
> +       str     r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
> +
> +       /*
> +        * Output impedence calib needed only for DDR3
> +        * but since the initial state of this will be
> +        * disabled for DDR2 no harm in restoring the
> +        * old configuration
> +        */
> +       ldr     r1, emif_zqcfg_val
> +       str     r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
> +
> +       /* Write to SDRAM_CONFIG only for DDR2 */
> +       ldr     r2, mem_type
> +       cmp     r2, #MEM_TYPE_DDR2
> +       bne     resume_to_ddr
> +
> +       /*
> +        * A write to SDRAM CONFIG register triggers
> +        * an init sequence and hence it must be done
> +        * at the end for DDR2
> +        */
> +       ldr     r1, emif_sdcfg_val
> +       str     r1, [r0, #EMIF_SDRAM_CONFIG]
> +
> +resume_to_ddr:
> +       /* Back from la-la-land. Kill some time for sanity to settle in */
> +       mov     r0, #0x1000
> +wait_resume:
> +       subs    r0, r0, #1
> +       bne     wait_resume
> +
> +       /* We are back. Branch to the common CPU resume routine */
> +       mov     r0, #0
> +       ldr     pc, resume_addr
> +ENDPROC(am33xx_resume_from_deep_sleep)
> +
> +
> +/*
> + * Local variables
> + */
> +       .align
> +resume_addr:
> +       .word   cpu_resume - PAGE_OFFSET + 0x80000000
> +kernel_flush:
> +       .word   v7_flush_dcache_all
> +ddr_start:
> +       .word   PAGE_OFFSET
> +emif_phys_addr:
> +       .word   AM33XX_EMIF_BASE
> +virt_mpu_clkctrl:
> +       .word   AM33XX_CM_MPU_MPU_CLKCTRL
> +virt_emif_clkctrl:
> +       .word   AM33XX_CM_PER_EMIF_CLKCTRL
> +phys_emif_clkctrl:
> +       .word   (AM33XX_CM_BASE + AM33XX_CM_PER_MOD + \
> +               AM33XX_CM_PER_EMIF_CLKCTRL_OFFSET)
> +module_disabled_val:
> +       .word   0x30000
> +
> +/* DDR related defines */
> +dram_sync_word:
> +       .word   0xDEADBEEF
> +mem_type:
> +       .word   0xDEADBEEF
> +emif_addr_virt:
> +       .word   0xDEADBEEF
> +emif_rd_lat_val:
> +       .word   0xDEADBEEF
> +emif_timing1_val:
> +       .word   0xDEADBEEF
> +emif_timing2_val:
> +       .word   0xDEADBEEF
> +emif_timing3_val:
> +       .word   0xDEADBEEF
> +emif_sdcfg_val:
> +       .word   0xDEADBEEF
> +emif_ref_ctrl_val:
> +       .word   0xDEADBEEF
> +emif_zqcfg_val:
> +       .word   0xDEADBEEF
> +emif_pmcr_val:
> +       .word   0xDEADBEEF
> +emif_pmcr_shdw_val:
> +       .word   0xDEADBEEF
> +
> +       .align 3
> +ENTRY(am33xx_do_wfi_sz)
> +       .word   . - am33xx_do_wfi
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 5/9] ARM: OMAP2+: AM33XX: Add assembly code for PM operations
@ 2013-08-08  7:02     ` Russ Dill
  0 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08  7:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> In preparation for suspend-resume support for AM33XX, add
> the assembly file with the code which is copied to internal
> memory (OCMC RAM) during bootup and runs from there.
>
> As part of the low power entry (DeepSleep0 mode in AM33XX TRM),
> the code running from OCMC RAM does the following
> 1. Stores the EMIF configuration
> 2. Puts external memory in self-refresh
> 3. Disables EMIF clock
> 4. Executes WFI after writing to MPU_CLKCTRL register.
>
> If no interrupts have come, WFI execution on MPU gets registered
> as an interrupt with the WKUP-M3. WKUP-M3 takes care of disabling
> some clocks which MPU should not (L3, L4, OCMC RAM etc) and takes
> care of clockdomain and powerdomain transitions as part of the
> DeepSleep0 mode entry.
>
> In case a late interrupt comes in, WFI ends up as a NOP and MPU
> continues execution from internal memory. The 'abort path' code
> undoes whatever was done as part of the low power entry and indicates
> a suspend failure by passing a non-zero value to the cpu_resume routine.
>
> The 'resume path' code is similar to the 'abort path' with the key
> difference of MMU being enabled in the 'abort path' but being
> disabled in the 'resume path' due to MPU getting powered off.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Kevin Hilman <khilman@linaro.org>

Reviewed-by: Russ Dill <russ.dill@ti.com>

> ---
>  arch/arm/mach-omap2/sleep33xx.S |  350 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 350 insertions(+)
>  create mode 100644 arch/arm/mach-omap2/sleep33xx.S
>
> diff --git a/arch/arm/mach-omap2/sleep33xx.S b/arch/arm/mach-omap2/sleep33xx.S
> new file mode 100644
> index 0000000..834c7d4
> --- /dev/null
> +++ b/arch/arm/mach-omap2/sleep33xx.S
> @@ -0,0 +1,350 @@
> +/*
> + * Low level suspend code for AM33XX SoCs
> + *
> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
> + * Vaibhav Bedia <vaibhav.bedia@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/linkage.h>
> +#include <linux/ti_emif.h>
> +#include <asm/memory.h>
> +#include <asm/assembler.h>
> +
> +#include "cm33xx.h"
> +#include "pm33xx.h"
> +#include "prm33xx.h"
> +
> +       .text
> +       .align 3
> +
> +/*
> + * This routine is executed from internal RAM and expects some
> + * parameters to be passed in r0 _strictly_ in following order:
> + * 1) emif_addr_virt - ioremapped EMIF address
> + * 2) mem_type - 2 -> DDR2, 3-> DDR3
> + * 3) dram_sync_word - uncached word in SDRAM
> + *
> + * The code loads these values taking r0 value as reference to
> + * the array in registers starting from r0, i.e emif_addr_virt
> + * goes to r1, mem_type goes to r2 and and so on. These are
> + * then saved into memory locations before proceeding with the
> + * sleep sequence and hence registers r0, r1 etc can still be
> + * used in the rest of the sleep code.
> + */
> +
> +ENTRY(am33xx_do_wfi)
> +       stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
> +
> +       ldm     r0, {r1-r3}             @ gather values passed
> +
> +       /* Save the values passed */
> +       str     r1, emif_addr_virt
> +       str     r2, mem_type
> +       str     r3, dram_sync_word
> +
> +       /*
> +        * Flush all data from the L1 data cache before disabling
> +        * SCTLR.C bit.
> +        */
> +       ldr     r1, kernel_flush
> +       blx     r1
> +
> +       /*
> +        * Clear the SCTLR.C bit to prevent further data cache
> +        * allocation. Clearing SCTLR.C would make all the data accesses
> +        * strongly ordered and would not hit the cache.
> +        */
> +       mrc     p15, 0, r0, c1, c0, 0
> +       bic     r0, r0, #(1 << 2)       @ Disable the C bit
> +       mcr     p15, 0, r0, c1, c0, 0
> +       isb
> +
> +       /*
> +        * Invalidate L1 data cache. Even though only invalidate is
> +        * necessary exported flush API is used here. Doing clean
> +        * on already clean cache would be almost NOP.
> +        */
> +       ldr     r1, kernel_flush
> +       blx     r1
> +
> +       ldr     r0, emif_addr_virt
> +       /* Save EMIF configuration */
> +       ldr     r1, [r0, #EMIF_SDRAM_CONFIG]
> +       str     r1, emif_sdcfg_val
> +       ldr     r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
> +       str     r1, emif_ref_ctrl_val
> +       ldr     r1, [r0, #EMIF_SDRAM_TIMING_1]
> +       str     r1, emif_timing1_val
> +       ldr     r1, [r0, #EMIF_SDRAM_TIMING_2]
> +       str     r1, emif_timing2_val
> +       ldr     r1, [r0, #EMIF_SDRAM_TIMING_3]
> +       str     r1, emif_timing3_val
> +       ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +       str     r1, emif_pmcr_val
> +       ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
> +       str     r1, emif_pmcr_shdw_val
> +       ldr     r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
> +       str     r1, emif_zqcfg_val
> +       ldr     r1, [r0, #EMIF_DDR_PHY_CTRL_1]
> +       str     r1, emif_rd_lat_val
> +
> +       /* Put SDRAM in self-refresh */
> +       ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +       orr     r1, r1, #0xa0
> +       str     r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
> +       str     r1, [r0, #4]
> +
> +       ldr     r1, dram_sync_word      @ a dummy access to DDR as per spec
> +       ldr     r2, [r1, #0]
> +       ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +       orr     r1, r1, #0x200
> +       str     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +
> +       mov     r1, #0x1000             @ Wait for system to enter SR
> +wait_sr:
> +       subs    r1, r1, #1
> +       bne     wait_sr
> +
> +       /* Disable EMIF */
> +       ldr     r1, virt_emif_clkctrl
> +       ldr     r2, [r1]
> +       bic     r2, r2, #0x03
> +       str     r2, [r1]
> +
> +       ldr     r1, virt_emif_clkctrl
> +wait_emif_disable:
> +       ldr     r2, [r1]
> +       ldr     r3, module_disabled_val
> +       cmp     r2, r3
> +       bne     wait_emif_disable
> +
> +       /*
> +        * For the MPU WFI to be registered as an interrupt
> +        * to WKUP_M3, MPU_CLKCTRL.MODULEMODE needs to be set
> +        * to DISABLED
> +        */
> +       ldr     r1, virt_mpu_clkctrl
> +       ldr     r2, [r1]
> +       bic     r2, r2, #0x03
> +       str     r2, [r1]
> +
> +       /*
> +        * Execute an ISB instruction to ensure that all of the
> +        * CP15 register changes have been committed.
> +        */
> +       isb
> +
> +       /*
> +        * Execute a barrier instruction to ensure that all cache,
> +        * TLB and branch predictor maintenance operations issued
> +        * have completed.
> +        */
> +       dsb
> +       dmb
> +
> +       /*
> +        * Execute a WFI instruction and wait until the
> +        * STANDBYWFI output is asserted to indicate that the
> +        * CPU is in idle and low power state. CPU can specualatively
> +        * prefetch the instructions so add NOPs after WFI. Thirteen
> +        * NOPs as per Cortex-A8 pipeline.
> +        */
> +       wfi
> +
> +       nop
> +       nop
> +       nop
> +       nop
> +       nop
> +       nop
> +       nop
> +       nop
> +       nop
> +       nop
> +       nop
> +       nop
> +       nop
> +
> +       /* We come here in case of an abort due to a late interrupt */
> +
> +       /* Set MPU_CLKCTRL.MODULEMODE back to ENABLE */
> +       ldr     r1, virt_mpu_clkctrl
> +       mov     r2, #0x02
> +       str     r2, [r1]
> +
> +       /* Re-enable EMIF */
> +       ldr     r1, virt_emif_clkctrl
> +       mov     r2, #0x02
> +       str     r2, [r1]
> +wait_emif_enable:
> +       ldr     r3, [r1]
> +       cmp     r2, r3
> +       bne     wait_emif_enable
> +
> +       /* Disable EMIF self-refresh */
> +       ldr     r0, emif_addr_virt
> +       ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +       bic     r1, r1, #LP_MODE_MASK
> +       str     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +       str     r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
> +
> +       /*
> +        * A write to SDRAM CONFIG register triggers
> +        * an init sequence and hence it must be done
> +        * at the end for DDR2
> +        */
> +       ldr r0, emif_addr_virt
> +       add r0, r0, #EMIF_SDRAM_CONFIG
> +       ldr r4, emif_sdcfg_val
> +       str r4, [r0]
> +
> +       /*
> +        * Set SCTLR.C bit to allow data cache allocation
> +        */
> +       mrc     p15, 0, r0, c1, c0, 0
> +       orr     r0, r0, #(1 << 2)       @ Enable the C bit
> +       mcr     p15, 0, r0, c1, c0, 0
> +       isb
> +
> +       /* Kill some time for sanity to settle in */
> +       mov r0, #0x1000
> +wait_abt:
> +       subs   r0, r0, #1
> +       bne wait_abt
> +
> +       /* Let the suspend code know about the abort */
> +       mov     r0, #1
> +       ldmfd   sp!, {r4 - r11, pc}     @ restore regs and return
> +ENDPROC(am33xx_do_wfi)
> +
> +       .align
> +ENTRY(am33xx_resume_offset)
> +       .word . - am33xx_do_wfi
> +
> +ENTRY(am33xx_resume_from_deep_sleep)
> +       /* Re-enable EMIF */
> +       ldr     r0, phys_emif_clkctrl
> +       mov     r1, #0x02
> +       str     r1, [r0]
> +wait_emif_enable1:
> +       ldr     r2, [r0]
> +       cmp     r1, r2
> +       bne     wait_emif_enable1
> +
> +       /* Config EMIF Timings */
> +       ldr     r0, emif_phys_addr
> +       ldr     r1, emif_rd_lat_val
> +       str     r1, [r0, #EMIF_DDR_PHY_CTRL_1]
> +       str     r1, [r0, #EMIF_DDR_PHY_CTRL_1_SHDW]
> +       ldr     r1, emif_timing1_val
> +       str     r1, [r0, #EMIF_SDRAM_TIMING_1]
> +       str     r1, [r0, #EMIF_SDRAM_TIMING_1_SHDW]
> +       ldr     r1, emif_timing2_val
> +       str     r1, [r0, #EMIF_SDRAM_TIMING_2]
> +       str     r1, [r0, #EMIF_SDRAM_TIMING_2_SHDW]
> +       ldr     r1, emif_timing3_val
> +       str     r1, [r0, #EMIF_SDRAM_TIMING_3]
> +       str     r1, [r0, #EMIF_SDRAM_TIMING_3_SHDW]
> +       ldr     r1, emif_ref_ctrl_val
> +       str     r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
> +       str     r1, [r0, #EMIF_SDRAM_REFRESH_CTRL_SHDW]
> +       ldr     r1, emif_pmcr_val
> +       str     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +       ldr     r1, emif_pmcr_shdw_val
> +       str     r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
> +
> +       /*
> +        * Output impedence calib needed only for DDR3
> +        * but since the initial state of this will be
> +        * disabled for DDR2 no harm in restoring the
> +        * old configuration
> +        */
> +       ldr     r1, emif_zqcfg_val
> +       str     r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
> +
> +       /* Write to SDRAM_CONFIG only for DDR2 */
> +       ldr     r2, mem_type
> +       cmp     r2, #MEM_TYPE_DDR2
> +       bne     resume_to_ddr
> +
> +       /*
> +        * A write to SDRAM CONFIG register triggers
> +        * an init sequence and hence it must be done
> +        * at the end for DDR2
> +        */
> +       ldr     r1, emif_sdcfg_val
> +       str     r1, [r0, #EMIF_SDRAM_CONFIG]
> +
> +resume_to_ddr:
> +       /* Back from la-la-land. Kill some time for sanity to settle in */
> +       mov     r0, #0x1000
> +wait_resume:
> +       subs    r0, r0, #1
> +       bne     wait_resume
> +
> +       /* We are back. Branch to the common CPU resume routine */
> +       mov     r0, #0
> +       ldr     pc, resume_addr
> +ENDPROC(am33xx_resume_from_deep_sleep)
> +
> +
> +/*
> + * Local variables
> + */
> +       .align
> +resume_addr:
> +       .word   cpu_resume - PAGE_OFFSET + 0x80000000
> +kernel_flush:
> +       .word   v7_flush_dcache_all
> +ddr_start:
> +       .word   PAGE_OFFSET
> +emif_phys_addr:
> +       .word   AM33XX_EMIF_BASE
> +virt_mpu_clkctrl:
> +       .word   AM33XX_CM_MPU_MPU_CLKCTRL
> +virt_emif_clkctrl:
> +       .word   AM33XX_CM_PER_EMIF_CLKCTRL
> +phys_emif_clkctrl:
> +       .word   (AM33XX_CM_BASE + AM33XX_CM_PER_MOD + \
> +               AM33XX_CM_PER_EMIF_CLKCTRL_OFFSET)
> +module_disabled_val:
> +       .word   0x30000
> +
> +/* DDR related defines */
> +dram_sync_word:
> +       .word   0xDEADBEEF
> +mem_type:
> +       .word   0xDEADBEEF
> +emif_addr_virt:
> +       .word   0xDEADBEEF
> +emif_rd_lat_val:
> +       .word   0xDEADBEEF
> +emif_timing1_val:
> +       .word   0xDEADBEEF
> +emif_timing2_val:
> +       .word   0xDEADBEEF
> +emif_timing3_val:
> +       .word   0xDEADBEEF
> +emif_sdcfg_val:
> +       .word   0xDEADBEEF
> +emif_ref_ctrl_val:
> +       .word   0xDEADBEEF
> +emif_zqcfg_val:
> +       .word   0xDEADBEEF
> +emif_pmcr_val:
> +       .word   0xDEADBEEF
> +emif_pmcr_shdw_val:
> +       .word   0xDEADBEEF
> +
> +       .align 3
> +ENTRY(am33xx_do_wfi_sz)
> +       .word   . - am33xx_do_wfi
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 6/9] ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08  7:03     ` Russ Dill
  -1 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08  7:03 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman, Vaibhav Bedia

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> OMAP timer code registers two timers - one as clocksource
> and one as clockevent. Since AM33XX has only one usable timer
> in the WKUP domain one of the timers needs suspend-resume
> support to restore the configuration to pre-suspend state.
>
> commit adc78e6 (timekeeping: Add suspend and resume
> of clock event devices) introduced .suspend and .resume
> callbacks for clock event devices. Leverages these
> callbacks to have AM33XX clockevent timer which is
> in not in WKUP domain to behave properly across system
> suspend.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>

Reviewed-by: Russ Dill <russ.dill@ti.com>

> ---
>  arch/arm/mach-omap2/timer.c |   32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
>
> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
> index b37e1fc..cce5d39 100644
> --- a/arch/arm/mach-omap2/timer.c
> +++ b/arch/arm/mach-omap2/timer.c
> @@ -118,11 +118,43 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
>         }
>  }
>
> +static void omap_clkevt_suspend(struct clock_event_device *unused)
> +{
> +       char name[10];
> +       struct omap_hwmod *oh;
> +
> +       sprintf(name, "timer%d", clkev.id);
> +       oh = omap_hwmod_lookup(name);
> +       if (!oh)
> +               return;
> +
> +       __omap_dm_timer_stop(&clkev, 1, clkev.rate);
> +       omap_hwmod_idle(oh);
> +}
> +
> +static void omap_clkevt_resume(struct clock_event_device *unused)
> +{
> +       char name[10];
> +       struct omap_hwmod *oh;
> +
> +       sprintf(name, "timer%d", clkev.id);
> +       oh = omap_hwmod_lookup(name);
> +       if (!oh)
> +               return;
> +
> +       omap_hwmod_enable(oh);
> +       __omap_dm_timer_load_start(&clkev,
> +                       OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
> +       __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
> +}
> +
>  static struct clock_event_device clockevent_gpt = {
>         .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
>         .rating         = 300,
>         .set_next_event = omap2_gp_timer_set_next_event,
>         .set_mode       = omap2_gp_timer_set_mode,
> +       .suspend        = omap_clkevt_suspend,
> +       .resume         = omap_clkevt_resume,
>  };
>
>  static struct property device_disabled = {
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 6/9] ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device
@ 2013-08-08  7:03     ` Russ Dill
  0 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08  7:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> OMAP timer code registers two timers - one as clocksource
> and one as clockevent. Since AM33XX has only one usable timer
> in the WKUP domain one of the timers needs suspend-resume
> support to restore the configuration to pre-suspend state.
>
> commit adc78e6 (timekeeping: Add suspend and resume
> of clock event devices) introduced .suspend and .resume
> callbacks for clock event devices. Leverages these
> callbacks to have AM33XX clockevent timer which is
> in not in WKUP domain to behave properly across system
> suspend.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>

Reviewed-by: Russ Dill <russ.dill@ti.com>

> ---
>  arch/arm/mach-omap2/timer.c |   32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
>
> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
> index b37e1fc..cce5d39 100644
> --- a/arch/arm/mach-omap2/timer.c
> +++ b/arch/arm/mach-omap2/timer.c
> @@ -118,11 +118,43 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
>         }
>  }
>
> +static void omap_clkevt_suspend(struct clock_event_device *unused)
> +{
> +       char name[10];
> +       struct omap_hwmod *oh;
> +
> +       sprintf(name, "timer%d", clkev.id);
> +       oh = omap_hwmod_lookup(name);
> +       if (!oh)
> +               return;
> +
> +       __omap_dm_timer_stop(&clkev, 1, clkev.rate);
> +       omap_hwmod_idle(oh);
> +}
> +
> +static void omap_clkevt_resume(struct clock_event_device *unused)
> +{
> +       char name[10];
> +       struct omap_hwmod *oh;
> +
> +       sprintf(name, "timer%d", clkev.id);
> +       oh = omap_hwmod_lookup(name);
> +       if (!oh)
> +               return;
> +
> +       omap_hwmod_enable(oh);
> +       __omap_dm_timer_load_start(&clkev,
> +                       OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
> +       __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
> +}
> +
>  static struct clock_event_device clockevent_gpt = {
>         .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
>         .rating         = 300,
>         .set_next_event = omap2_gp_timer_set_next_event,
>         .set_mode       = omap2_gp_timer_set_mode,
> +       .suspend        = omap_clkevt_suspend,
> +       .resume         = omap_clkevt_resume,
>  };
>
>  static struct property device_disabled = {
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 7/9] ARM: OMAP: omap_device: Add APIs to enable and idle hwmods
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08  7:05     ` Russ Dill
  -1 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08  7:05 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman, Vaibhav Bedia

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> Needed to let the AM335x PM handle the IPs which need forced
> standby transition during every suspend-resume cycle when
> the corresponding driver is not compiled into the kernel.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>

Reviewed-by: Russ Dill <russ.dill@ti.com>

> ---
>  arch/arm/mach-omap2/omap_device.c |    8 ++++++++
>  arch/arm/mach-omap2/omap_device.h |    2 ++
>  2 files changed, 10 insertions(+)
>
> diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
> index 5cc9287..8cf63f6 100644
> --- a/arch/arm/mach-omap2/omap_device.c
> +++ b/arch/arm/mach-omap2/omap_device.c
> @@ -219,6 +219,10 @@ static int _omap_device_enable_hwmods(struct omap_device *od)
>         return 0;
>  }
>
> +int omap_device_enable_hwmods(struct omap_device *od)
> +{
> +       return _omap_device_enable_hwmods(od);
> +}
>  /**
>   * _omap_device_idle_hwmods - call omap_hwmod_idle() on all hwmods
>   * @od: struct omap_device *od
> @@ -236,6 +240,10 @@ static int _omap_device_idle_hwmods(struct omap_device *od)
>         return 0;
>  }
>
> +int omap_device_idle_hwmods(struct omap_device *od)
> +{
> +       return _omap_device_idle_hwmods(od);
> +}
>  /* Public functions for use by core code */
>
>  /**
> diff --git a/arch/arm/mach-omap2/omap_device.h b/arch/arm/mach-omap2/omap_device.h
> index 17ca1ae..655ec35 100644
> --- a/arch/arm/mach-omap2/omap_device.h
> +++ b/arch/arm/mach-omap2/omap_device.h
> @@ -87,6 +87,8 @@ struct device *omap_device_get_by_hwmod_name(const char *oh_name);
>
>  /* OMAP PM interface */
>  int omap_device_get_context_loss_count(struct platform_device *pdev);
> +int omap_device_enable_hwmods(struct omap_device *od);
> +int omap_device_idle_hwmods(struct omap_device *od);
>
>  /* Other */
>
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 7/9] ARM: OMAP: omap_device: Add APIs to enable and idle hwmods
@ 2013-08-08  7:05     ` Russ Dill
  0 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08  7:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> Needed to let the AM335x PM handle the IPs which need forced
> standby transition during every suspend-resume cycle when
> the corresponding driver is not compiled into the kernel.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>

Reviewed-by: Russ Dill <russ.dill@ti.com>

> ---
>  arch/arm/mach-omap2/omap_device.c |    8 ++++++++
>  arch/arm/mach-omap2/omap_device.h |    2 ++
>  2 files changed, 10 insertions(+)
>
> diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
> index 5cc9287..8cf63f6 100644
> --- a/arch/arm/mach-omap2/omap_device.c
> +++ b/arch/arm/mach-omap2/omap_device.c
> @@ -219,6 +219,10 @@ static int _omap_device_enable_hwmods(struct omap_device *od)
>         return 0;
>  }
>
> +int omap_device_enable_hwmods(struct omap_device *od)
> +{
> +       return _omap_device_enable_hwmods(od);
> +}
>  /**
>   * _omap_device_idle_hwmods - call omap_hwmod_idle() on all hwmods
>   * @od: struct omap_device *od
> @@ -236,6 +240,10 @@ static int _omap_device_idle_hwmods(struct omap_device *od)
>         return 0;
>  }
>
> +int omap_device_idle_hwmods(struct omap_device *od)
> +{
> +       return _omap_device_idle_hwmods(od);
> +}
>  /* Public functions for use by core code */
>
>  /**
> diff --git a/arch/arm/mach-omap2/omap_device.h b/arch/arm/mach-omap2/omap_device.h
> index 17ca1ae..655ec35 100644
> --- a/arch/arm/mach-omap2/omap_device.h
> +++ b/arch/arm/mach-omap2/omap_device.h
> @@ -87,6 +87,8 @@ struct device *omap_device_get_by_hwmod_name(const char *oh_name);
>
>  /* OMAP PM interface */
>  int omap_device_get_context_loss_count(struct platform_device *pdev);
> +int omap_device_enable_hwmods(struct omap_device *od);
> +int omap_device_idle_hwmods(struct omap_device *od);
>
>  /* Other */
>
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08  8:45     ` Russ Dill
  -1 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08  8:45 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman,
	Vaibhav Bedia, Tony Lingren, Santosh Shilimkar, Benoit Cousson

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> AM335x supports various low power modes as documented
> in section 8.1.4.3 of the AM335x TRM which is available
> @ http://www.ti.com/litv/pdf/spruh73f
>
> DeepSleep0 mode offers the lowest power mode with limited
> wakeup sources without a system reboot and is mapped as
> the suspend state in the kernel. In this state, MPU and
> PER domains are turned off with the internal RAM held in
> retention to facilitate resume process. As part of the boot
> process, the assembly code is copied over to OCMCRAM using
> the OMAP SRAM code.
>
> AM335x has a Cortex-M3 (WKUP_M3) which assists the MPU
> in DeepSleep0 entry and exit. WKUP_M3 takes care of the
> clockdomain and powerdomain transitions based on the
> intended low power state. MPU needs to load the appropriate
> WKUP_M3 binary onto the WKUP_M3 memory space before it can
> leverage any of the PM features like DeepSleep.
>
> The IPC mechanism between MPU and WKUP_M3 uses a mailbox
> sub-module and 8 IPC registers in the Control module. MPU
> uses the assigned Mailbox for issuing an interrupt to
> WKUP_M3 which then goes and checks the IPC registers for
> the payload. WKUP_M3 has the ability to trigger on interrupt
> to MPU by executing the "sev" instruction.
>
> In the current implementation when the suspend process
> is initiated MPU interrupts the WKUP_M3 to let it know about
> the intent of entering DeepSleep0 and waits for an ACK. When
> the ACK is received MPU continues with its suspend process
> to suspend all the drivers and then jumps to assembly in
> OCMC RAM. The assembly code puts the PLLs in bypass, puts the
> external RAM in self-refresh mode and then finally execute the
> WFI instruction. Execution of the WFI instruction triggers another
> interrupt to the WKUP_M3 which then continues wiht the power down
> sequence wherein the clockdomain and powerdomain transition takes
> place. As part of the sleep sequence, WKUP_M3 unmasks the interrupt
> lines for the wakeup sources. WFI execution on WKUP_M3 causes the
> hardware to disable the main oscillator of the SoC.
>
> When a wakeup event occurs, WKUP_M3 starts the power-up
> sequence by switching on the power domains and finally
> enabling the clock to MPU. Since the MPU gets powered down
> as part of the sleep sequence in the resume path ROM code
> starts executing. The ROM code detects a wakeup from sleep
> and then jumps to the resume location in OCMC which was
> populated in one of the IPC registers as part of the suspend
> sequence.
>
> The low level code in OCMC relocks the PLLs, enables access
> to external RAM and then jumps to the cpu_resume code of
> the kernel to finish the resume process.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> Cc: Tony Lingren <tony@atomide.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Benoit Cousson <benoit.cousson@linaro.org>
> Cc: Paul Walmsley <paul@pwsan.com>
> Cc: Kevin Hilman <khilman@linaro.org>

Reviewed-by: Russ Dill <russ.dill@ti.com>

In response to Nishanth's comments about the list of omap modules to
idle, I saw that, but it looks like its only for devices that no
device driver ever binds do, eg, the support is not built into the
kernel or the module is currently not loaded. Hence I don't think
there is any suspend/resume function that gets called. In reference to
the M3 handling it, the M3 wouldn't know which devices have a driver
bound and which don't.

> ---
>  arch/arm/mach-omap2/pm33xx.c  |  474 +++++++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/pm33xx.h  |   77 +++++++
>  arch/arm/mach-omap2/wkup_m3.c |  183 ++++++++++++++++
>  3 files changed, 734 insertions(+)
>  create mode 100644 arch/arm/mach-omap2/pm33xx.c
>  create mode 100644 arch/arm/mach-omap2/pm33xx.h
>  create mode 100644 arch/arm/mach-omap2/wkup_m3.c
>
> diff --git a/arch/arm/mach-omap2/pm33xx.c b/arch/arm/mach-omap2/pm33xx.c
> new file mode 100644
> index 0000000..d291c76
> --- /dev/null
> +++ b/arch/arm/mach-omap2/pm33xx.c
> @@ -0,0 +1,474 @@
> +/*
> + * AM33XX Power Management Routines
> + *
> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
> + * Vaibhav Bedia <vaibhav.bedia@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/kernel.h>
> +#include <linux/init.h>
> +#include <linux/cpu.h>
> +#include <linux/err.h>
> +#include <linux/firmware.h>
> +#include <linux/io.h>
> +#include <linux/platform_device.h>
> +#include <linux/sched.h>
> +#include <linux/suspend.h>
> +#include <linux/completion.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/ti_emif.h>
> +#include <linux/omap-mailbox.h>
> +
> +#include <asm/suspend.h>
> +#include <asm/proc-fns.h>
> +#include <asm/sizes.h>
> +#include <asm/fncpy.h>
> +#include <asm/system_misc.h>
> +
> +#include "pm.h"
> +#include "cm33xx.h"
> +#include "pm33xx.h"
> +#include "control.h"
> +#include "common.h"
> +#include "clockdomain.h"
> +#include "powerdomain.h"
> +#include "omap_hwmod.h"
> +#include "omap_device.h"
> +#include "soc.h"
> +#include "sram.h"
> +
> +static void __iomem *am33xx_emif_base;
> +static struct powerdomain *cefuse_pwrdm, *gfx_pwrdm, *per_pwrdm, *mpu_pwrdm;
> +static struct clockdomain *gfx_l4ls_clkdm;
> +
> +struct wakeup_src wakeups[] = {
> +       {.irq_nr = 35,  .src = "USB0_PHY"},
> +       {.irq_nr = 36,  .src = "USB1_PHY"},
> +       {.irq_nr = 40,  .src = "I2C0"},
> +       {.irq_nr = 41,  .src = "RTC Timer"},
> +       {.irq_nr = 42,  .src = "RTC Alarm"},
> +       {.irq_nr = 43,  .src = "Timer0"},
> +       {.irq_nr = 44,  .src = "Timer1"},
> +       {.irq_nr = 45,  .src = "UART"},
> +       {.irq_nr = 46,  .src = "GPIO0"},
> +       {.irq_nr = 48,  .src = "MPU_WAKE"},
> +       {.irq_nr = 49,  .src = "WDT0"},
> +       {.irq_nr = 50,  .src = "WDT1"},
> +       {.irq_nr = 51,  .src = "ADC_TSC"},
> +};
> +
> +struct forced_standby_module am33xx_mod[] = {
> +       {.oh_name = "usb_otg_hs"},
> +       {.oh_name = "tptc0"},
> +       {.oh_name = "tptc1"},
> +       {.oh_name = "tptc2"},
> +       {.oh_name = "cpgmac0"},
> +};
> +
> +static struct am33xx_pm_context *am33xx_pm;
> +
> +static DECLARE_COMPLETION(am33xx_pm_sync);
> +
> +static void (*am33xx_do_wfi_sram)(struct am33xx_suspend_params *);
> +
> +static struct am33xx_suspend_params susp_params;
> +
> +#ifdef CONFIG_SUSPEND
> +
> +static int am33xx_do_sram_idle(long unsigned int unused)
> +{
> +       am33xx_do_wfi_sram(&susp_params);
> +       return 0;
> +}
> +
> +static int am33xx_pm_suspend(void)
> +{
> +       int i, j, ret = 0;
> +
> +       int status = 0;
> +       struct platform_device *pdev;
> +       struct omap_device *od;
> +
> +       /*
> +        * By default the following IPs do not have MSTANDBY asserted
> +        * which is necessary for PER domain transition. If the drivers
> +        * are not compiled into the kernel HWMOD code will not change the
> +        * state of the IPs if the IP was not never enabled. To ensure
> +        * that there no issues with or without the drivers being compiled
> +        * in the kernel, we forcefully put these IPs to idle.
> +        */
> +       for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++) {
> +               pdev = to_platform_device(am33xx_mod[i].dev);
> +               od = to_omap_device(pdev);
> +               if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
> +                       omap_device_enable_hwmods(od);
> +                       omap_device_idle_hwmods(od);
> +               }
> +       }
> +
> +       /* Try to put GFX to sleep */
> +       omap_set_pwrdm_state(gfx_pwrdm, PWRDM_POWER_OFF);
> +       ret = cpu_suspend(0, am33xx_do_sram_idle);
> +
> +       status = pwrdm_read_prev_pwrst(gfx_pwrdm);
> +       if (status != PWRDM_POWER_OFF)
> +               pr_err("PM: GFX domain did not transition\n");
> +       else
> +               pr_info("PM: GFX domain entered low power state\n");
> +
> +       /*
> +        * BUG: GFX_L4LS clock domain needs to be woken up to
> +        * ensure thet L4LS clock domain does not get stuck in transition
> +        * If that happens L3 module does not get disabled, thereby leading
> +        * to PER power domain transition failing
> +        */
> +       clkdm_wakeup(gfx_l4ls_clkdm);
> +       clkdm_sleep(gfx_l4ls_clkdm);
> +
> +       if (ret) {
> +               pr_err("PM: Kernel suspend failure\n");
> +       } else {
> +               i = am33xx_pm_status();
> +               switch (i) {
> +               case 0:
> +                       pr_info("PM: Successfully put all powerdomains to target state\n");
> +
> +                       /*
> +                        * The PRCM registers on AM335x do not contain previous state
> +                        * information like those present on OMAP4 so we must manually
> +                        * indicate transition so state counters are properly incremented
> +                        */
> +                       pwrdm_post_transition(mpu_pwrdm);
> +                       pwrdm_post_transition(per_pwrdm);
> +                       break;
> +               case 1:
> +                       pr_err("PM: Could not transition all powerdomains to target state\n");
> +                       ret = -1;
> +                       break;
> +               default:
> +                       pr_err("PM: CM3 returned unknown result :(\nStatus = %d\n", i);
> +                       ret = -1;
> +               }
> +
> +               /* print the wakeup reason */
> +               i = am33xx_pm_wake_src();
> +               for (j = 0; j < ARRAY_SIZE(wakeups); j++) {
> +                       if (wakeups[j].irq_nr == i) {
> +                               pr_info("PM: Wakeup source %s\n", wakeups[j].src);
> +                               break;
> +                       }
> +               }
> +
> +               if (j == ARRAY_SIZE(wakeups))
> +                       pr_info("PM: Unknown wakeup source %d!\n", i);
> +       }
> +
> +       return ret;
> +}
> +
> +static int am33xx_pm_enter(suspend_state_t suspend_state)
> +{
> +       int ret = 0;
> +
> +       switch (suspend_state) {
> +       case PM_SUSPEND_STANDBY:
> +       case PM_SUSPEND_MEM:
> +               ret = am33xx_pm_suspend();
> +               break;
> +       default:
> +               ret = -EINVAL;
> +       }
> +
> +       return ret;
> +}
> +
> +/* returns the error code from msg_send - 0 for success, failure otherwise */
> +static int am33xx_ping_wkup_m3(void)
> +{
> +       int ret = 0;
> +
> +       /*
> +        * Write a dummy message to the mailbox in order to trigger the RX
> +        * interrupt to alert the M3 that data is available in the IPC
> +        * registers.
> +        */
> +       ret = omap_mbox_msg_send(am33xx_pm->mbox, 0xABCDABCD);
> +
> +       return ret;
> +}
> +
> +static void am33xx_m3_state_machine_reset(void)
> +{
> +       int i;
> +
> +       am33xx_pm->ipc.sleep_mode = IPC_CMD_RESET;
> +
> +       am33xx_pm_ipc_cmd(&am33xx_pm->ipc);
> +
> +       am33xx_pm->state = M3_STATE_MSG_FOR_RESET;
> +
> +       pr_info("PM: Sending message for resetting M3 state machine\n");
> +
> +       if (!am33xx_ping_wkup_m3()) {
> +               i = wait_for_completion_timeout(&am33xx_pm_sync,
> +                                       msecs_to_jiffies(500));
> +               if (WARN(i == 0, "PM: MPU<->CM3 sync failure\n"))
> +                       am33xx_pm->state = M3_STATE_UNKNOWN;
> +       } else {
> +               pr_warn("PM: Unable to ping CM3\n");
> +       }
> +}
> +
> +static int am33xx_pm_begin(suspend_state_t state)
> +{
> +       int i;
> +
> +       cpu_idle_poll_ctrl(true);
> +
> +       am33xx_pm->ipc.sleep_mode       = IPC_CMD_DS0;
> +       am33xx_pm->ipc.param1           = DS_IPC_DEFAULT;
> +       am33xx_pm->ipc.param2           = DS_IPC_DEFAULT;
> +
> +       am33xx_pm_ipc_cmd(&am33xx_pm->ipc);
> +
> +       am33xx_pm->state = M3_STATE_MSG_FOR_LP;
> +
> +       pr_info("PM: Sending message for entering DeepSleep mode\n");
> +
> +       if (!am33xx_ping_wkup_m3()) {
> +               i = wait_for_completion_timeout(&am33xx_pm_sync,
> +                                       msecs_to_jiffies(500));
> +               if (WARN(i == 0, "PM: MPU<->CM3 sync failure\n"))
> +                       return -1;
> +       } else {
> +               pr_warn("PM: Unable to ping CM3\n");
> +       }
> +
> +       return 0;
> +}
> +
> +static void am33xx_pm_end(void)
> +{
> +       am33xx_m3_state_machine_reset();
> +
> +       cpu_idle_poll_ctrl(false);
> +
> +       return;
> +}
> +
> +static struct platform_suspend_ops am33xx_pm_ops = {
> +       .begin          = am33xx_pm_begin,
> +       .end            = am33xx_pm_end,
> +       .enter          = am33xx_pm_enter,
> +};
> +
> +/*
> + * Dummy notifier for the mailbox
> + */
> +
> +static int wkup_mbox_msg(struct notifier_block *self, unsigned long len,
> +               void *msg)
> +{
> +       return 0;
> +}
> +
> +static struct notifier_block wkup_mbox_notifier = {
> +       .notifier_call = wkup_mbox_msg,
> +};
> +
> +void am33xx_txev_handler(void)
> +{
> +       switch (am33xx_pm->state) {
> +       case M3_STATE_RESET:
> +               am33xx_pm->state = M3_STATE_INITED;
> +               am33xx_pm->ver = am33xx_pm_version_get();
> +               if (am33xx_pm->ver == M3_VERSION_UNKNOWN ||
> +                       am33xx_pm->ver < M3_BASELINE_VERSION) {
> +                       pr_warn("PM: CM3 Firmware Version %x not supported\n",
> +                                               am33xx_pm->ver);
> +               } else {
> +                       pr_info("PM: CM3 Firmware Version = 0x%x\n",
> +                                               am33xx_pm->ver);
> +                       am33xx_pm_ops.valid = suspend_valid_only_mem;
> +               }
> +               break;
> +       case M3_STATE_MSG_FOR_RESET:
> +               am33xx_pm->state = M3_STATE_INITED;
> +               complete(&am33xx_pm_sync);
> +               break;
> +       case M3_STATE_MSG_FOR_LP:
> +               complete(&am33xx_pm_sync);
> +               break;
> +       case M3_STATE_UNKNOWN:
> +               pr_warn("PM: Unknown CM3 State\n");
> +       }
> +
> +       return;
> +}
> +
> +static void am33xx_pm_firmware_cb(const struct firmware *fw, void *context)
> +{
> +       struct am33xx_pm_context *am33xx_pm = context;
> +       int ret = 0;
> +
> +       /* no firmware found */
> +       if (!fw) {
> +               pr_err("PM: request_firmware failed\n");
> +               return;
> +       }
> +
> +       wkup_m3_copy_code(fw->data, fw->size);
> +
> +       wkup_m3_register_txev_handler(am33xx_txev_handler);
> +
> +       pr_info("PM: Copied the M3 firmware to UMEM\n");
> +
> +       /*
> +        * Invalidate M3 firmware version before hardreset.
> +        * Write invalid version in lower 4 nibbles of parameter
> +        * register (ipc_regs + 0x8).
> +        */
> +       am33xx_pm_version_clear();
> +
> +       am33xx_pm->state = M3_STATE_RESET;
> +
> +       ret = wkup_m3_prepare();
> +       if (ret) {
> +               pr_err("PM: Could not prepare WKUP_M3\n");
> +               return;
> +       }
> +
> +       /* Physical resume address to be used by ROM code */
> +       am33xx_pm->ipc.resume_addr = (AM33XX_OCMC_END -
> +               am33xx_do_wfi_sz + am33xx_resume_offset + 0x4);
> +
> +       am33xx_pm->mbox = omap_mbox_get("wkup_m3", &wkup_mbox_notifier);
> +
> +       if (IS_ERR(am33xx_pm->mbox)) {
> +               ret = -EBUSY;
> +               pr_err("PM: IPC Request for A8->M3 Channel failed!\n");
> +               return;
> +       } else {
> +               suspend_set_ops(&am33xx_pm_ops);
> +       }
> +
> +       return;
> +}
> +
> +#endif /* CONFIG_SUSPEND */
> +
> +/*
> + * Push the minimal suspend-resume code to SRAM
> + */
> +void am33xx_push_sram_idle(void)
> +{
> +       am33xx_do_wfi_sram = (void *)omap_sram_push
> +                                       (am33xx_do_wfi, am33xx_do_wfi_sz);
> +}
> +
> +static int __init am33xx_map_emif(void)
> +{
> +       am33xx_emif_base = ioremap(AM33XX_EMIF_BASE, SZ_32K);
> +
> +       if (!am33xx_emif_base)
> +               return -ENOMEM;
> +
> +       return 0;
> +}
> +
> +int __init am33xx_pm_init(void)
> +{
> +       int ret;
> +       u32 temp;
> +       struct device_node *np;
> +       int i;
> +
> +       if (!soc_is_am33xx())
> +               return -ENODEV;
> +
> +       pr_info("Power Management for AM33XX family\n");
> +
> +       /*
> +        * By default the following IPs do not have MSTANDBY asserted
> +        * which is necessary for PER domain transition. If the drivers
> +        * are not compiled into the kernel HWMOD code will not change the
> +        * state of the IPs if the IP was not never enabled
> +        */
> +       for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++)
> +               am33xx_mod[i].dev = omap_device_get_by_hwmod_name(am33xx_mod[i].oh_name);
> +
> +       gfx_pwrdm = pwrdm_lookup("gfx_pwrdm");
> +       per_pwrdm = pwrdm_lookup("per_pwrdm");
> +       mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
> +
> +       gfx_l4ls_clkdm = clkdm_lookup("gfx_l4ls_gfx_clkdm");
> +
> +       if ((!gfx_pwrdm) || (!per_pwrdm) || (!mpu_pwrdm) || (!gfx_l4ls_clkdm)) {
> +               ret = -ENODEV;
> +               goto err;
> +       }
> +
> +       am33xx_pm = kzalloc(sizeof(*am33xx_pm), GFP_KERNEL);
> +       if (!am33xx_pm) {
> +               pr_err("Memory allocation failed\n");
> +               ret = -ENOMEM;
> +               goto err;
> +       }
> +
> +       ret = am33xx_map_emif();
> +       if (ret) {
> +               pr_err("PM: Could not ioremap EMIF\n");
> +               goto err;
> +       }
> +       /* Determine Memory Type */
> +       temp = readl(am33xx_emif_base + EMIF_SDRAM_CONFIG);
> +       temp = (temp & SDRAM_TYPE_MASK) >> SDRAM_TYPE_SHIFT;
> +       /* Parameters to pass to aseembly code */
> +       susp_params.emif_addr_virt = am33xx_emif_base;
> +       susp_params.dram_sync = am33xx_dram_sync;
> +       susp_params.mem_type = temp;
> +       am33xx_pm->ipc.param3 = temp;
> +
> +       np = of_find_compatible_node(NULL, NULL, "ti,am3353-wkup-m3");
> +       if (np) {
> +               if (of_find_property(np, "ti,needs_vtt_toggle", NULL) &&
> +                   (!(of_property_read_u32(np, "vtt-gpio-pin",
> +                                                       &temp)))) {
> +                       if (temp >= 0 && temp <= 31)
> +                               am33xx_pm->ipc.param3 |=
> +                                       ((1 << VTT_STAT_SHIFT) |
> +                                       (temp << VTT_GPIO_PIN_SHIFT));
> +               }
> +       }
> +
> +       (void) clkdm_for_each(omap_pm_clkdms_setup, NULL);
> +
> +       /* CEFUSE domain can be turned off post bootup */
> +       cefuse_pwrdm = pwrdm_lookup("cefuse_pwrdm");
> +       if (cefuse_pwrdm)
> +               omap_set_pwrdm_state(cefuse_pwrdm, PWRDM_POWER_OFF);
> +       else
> +               pr_err("PM: Failed to get cefuse_pwrdm\n");
> +
> +#ifdef CONFIG_SUSPEND
> +       pr_info("PM: Trying to load am335x-pm-firmware.bin");
> +
> +       /* We don't want to delay boot */
> +       request_firmware_nowait(THIS_MODULE, 0, "am335x-pm-firmware.bin",
> +                               NULL, GFP_KERNEL, am33xx_pm,
> +                               am33xx_pm_firmware_cb);
> +#endif /* CONFIG_SUSPEND */
> +
> +err:
> +       return ret;
> +}
> diff --git a/arch/arm/mach-omap2/pm33xx.h b/arch/arm/mach-omap2/pm33xx.h
> new file mode 100644
> index 0000000..befdd11
> --- /dev/null
> +++ b/arch/arm/mach-omap2/pm33xx.h
> @@ -0,0 +1,77 @@
> +/*
> + * AM33XX Power Management Routines
> + *
> + * Copyright (C) 2012 Texas Instruments Inc.
> + * Vaibhav Bedia <vaibhav.bedia@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.
> + */
> +#ifndef __ARCH_ARM_MACH_OMAP2_PM33XX_H
> +#define __ARCH_ARM_MACH_OMAP2_PM33XX_H
> +
> +#include "control.h"
> +
> +#ifndef __ASSEMBLER__
> +
> +struct am33xx_pm_context {
> +       struct am33xx_ipc_data  ipc;
> +       struct firmware         *firmware;
> +       struct omap_mbox        *mbox;
> +       u8                      state;
> +       u32                     ver;
> +};
> +
> +/*
> + * Params passed to suspend routine
> + *
> + * Since these are used to load into registers by suspend code,
> + * entries here must always be in sync with the suspend code
> + * in arm/mach-omap2/sleep33xx.S
> + */
> +struct am33xx_suspend_params {
> +       void __iomem *emif_addr_virt;
> +       u32 mem_type;
> +       void __iomem *dram_sync;
> +};
> +
> +struct wakeup_src {
> +       int irq_nr;
> +       char src[10];
> +};
> +
> +struct forced_standby_module {
> +       char oh_name[15];
> +       struct device *dev;
> +};
> +
> +int wkup_m3_copy_code(const u8 *data, size_t size);
> +int wkup_m3_prepare(void);
> +void wkup_m3_register_txev_handler(void (*txev_handler)(void));
> +
> +#endif
> +
> +#define        IPC_CMD_DS0                     0x3
> +#define IPC_CMD_RESET                   0xe
> +#define DS_IPC_DEFAULT                 0xffffffff
> +#define M3_VERSION_UNKNOWN             0x0000ffff
> +#define M3_BASELINE_VERSION            0x21
> +
> +#define M3_STATE_UNKNOWN               0
> +#define M3_STATE_RESET                 1
> +#define M3_STATE_INITED                        2
> +#define M3_STATE_MSG_FOR_LP            3
> +#define M3_STATE_MSG_FOR_RESET         4
> +
> +#define AM33XX_OCMC_END                        0x40310000
> +#define AM33XX_EMIF_BASE               0x4C000000
> +
> +#define MEM_TYPE_DDR2          2
> +
> +#endif
> diff --git a/arch/arm/mach-omap2/wkup_m3.c b/arch/arm/mach-omap2/wkup_m3.c
> new file mode 100644
> index 0000000..8eaa7f3
> --- /dev/null
> +++ b/arch/arm/mach-omap2/wkup_m3.c
> @@ -0,0 +1,183 @@
> +/*
> + * AM33XX Power Management Routines
> + *
> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
> + * Vaibhav Bedia <vaibhav.bedia@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/kernel.h>
> +#include <linux/init.h>
> +#include <linux/slab.h>
> +#include <linux/cpu.h>
> +#include <linux/err.h>
> +#include <linux/firmware.h>
> +#include <linux/io.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/of.h>
> +
> +#include "pm33xx.h"
> +#include "control.h"
> +#include "omap_device.h"
> +#include "soc.h"
> +
> +struct wkup_m3_context {
> +       struct device   *dev;
> +       void __iomem    *code;
> +       void (*txev_handler)(void);
> +};
> +
> +struct wkup_m3_context *wkup_m3;
> +
> +int wkup_m3_copy_code(const u8 *data, size_t size)
> +{
> +       if (size > SZ_16K)
> +               return -ENOMEM;
> +
> +       memcpy_toio(wkup_m3->code, data, size);
> +
> +       return 0;
> +}
> +
> +
> +void wkup_m3_register_txev_handler(void (*txev_handler)(void))
> +{
> +       wkup_m3->txev_handler = txev_handler;
> +}
> +
> +/* have platforms do what they want in atomic context over here? */
> +static irqreturn_t wkup_m3_txev_handler(int irq, void *unused)
> +{
> +       am33xx_txev_eoi();
> +
> +       /* callback to be executed in atomic context */
> +       /* return 0 implies IRQ_HANDLED else IRQ_NONE */
> +       wkup_m3->txev_handler();
> +
> +       am33xx_txev_enable();
> +
> +       return IRQ_HANDLED;
> +}
> +
> +int wkup_m3_prepare(void)
> +{
> +       struct platform_device *pdev = to_platform_device(wkup_m3->dev);
> +
> +       /* check that the code is loaded */
> +       omap_device_deassert_hardreset(pdev, "wkup_m3");
> +
> +       return 0;
> +}
> +
> +static int wkup_m3_probe(struct platform_device *pdev)
> +{
> +       int irq, ret = 0;
> +       struct resource *mem;
> +
> +       pm_runtime_enable(&pdev->dev);
> +
> +       ret = pm_runtime_get_sync(&pdev->dev);
> +       if (IS_ERR_VALUE(ret)) {
> +               dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
> +               return ret;
> +       }
> +
> +       irq = platform_get_irq(pdev, 0);
> +       if (!irq) {
> +               dev_err(wkup_m3->dev, "no irq resource\n");
> +               ret = -ENXIO;
> +               goto err;
> +       }
> +
> +       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       if (!mem) {
> +               dev_err(wkup_m3->dev, "no memory resource\n");
> +               ret = -ENXIO;
> +               goto err;
> +       }
> +
> +       wkup_m3 = kzalloc(sizeof(*wkup_m3), GFP_KERNEL);
> +       if (!wkup_m3) {
> +               pr_err("Memory allocation failed\n");
> +               ret = -ENOMEM;
> +               goto err;
> +       }
> +
> +       wkup_m3->dev = &pdev->dev;
> +
> +       wkup_m3->code = devm_request_and_ioremap(wkup_m3->dev, mem);
> +       if (!wkup_m3->code) {
> +               dev_err(wkup_m3->dev, "could not ioremap\n");
> +               ret = -EADDRNOTAVAIL;
> +               goto err;
> +       }
> +
> +       ret = devm_request_irq(wkup_m3->dev, irq, wkup_m3_txev_handler,
> +                 IRQF_DISABLED, "wkup_m3_txev", NULL);
> +       if (ret) {
> +               dev_err(wkup_m3->dev, "request_irq failed\n");
> +               goto err;
> +       }
> +
> +err:
> +       return ret;
> +}
> +
> +static int wkup_m3_remove(struct platform_device *pdev)
> +{
> +       return 0;
> +}
> +
> +static struct of_device_id wkup_m3_dt_ids[] = {
> +       { .compatible = "ti,am3353-wkup-m3" },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(of, wkup_m3_dt_ids);
> +
> +static int wkup_m3_rpm_suspend(struct device *dev)
> +{
> +       return -EBUSY;
> +}
> +
> +static int wkup_m3_rpm_resume(struct device *dev)
> +{
> +       return 0;
> +}
> +
> +static const struct dev_pm_ops wkup_m3_ops = {
> +       SET_RUNTIME_PM_OPS(wkup_m3_rpm_suspend, wkup_m3_rpm_resume, NULL)
> +};
> +
> +static struct platform_driver wkup_m3_driver = {
> +       .probe          = wkup_m3_probe,
> +       .remove         = wkup_m3_remove,
> +       .driver         = {
> +               .name   = "wkup_m3",
> +               .owner  = THIS_MODULE,
> +               .of_match_table = of_match_ptr(wkup_m3_dt_ids),
> +               .pm     = &wkup_m3_ops,
> +       },
> +};
> +
> +static __init int wkup_m3_init(void)
> +{
> +       return platform_driver_register(&wkup_m3_driver);
> +}
> +
> +static __exit void wkup_m3_exit(void)
> +{
> +       platform_driver_unregister(&wkup_m3_driver);
> +}
> +omap_postcore_initcall(wkup_m3_init);
> +module_exit(wkup_m3_exit);
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-08  8:45     ` Russ Dill
  0 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08  8:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> AM335x supports various low power modes as documented
> in section 8.1.4.3 of the AM335x TRM which is available
> @ http://www.ti.com/litv/pdf/spruh73f
>
> DeepSleep0 mode offers the lowest power mode with limited
> wakeup sources without a system reboot and is mapped as
> the suspend state in the kernel. In this state, MPU and
> PER domains are turned off with the internal RAM held in
> retention to facilitate resume process. As part of the boot
> process, the assembly code is copied over to OCMCRAM using
> the OMAP SRAM code.
>
> AM335x has a Cortex-M3 (WKUP_M3) which assists the MPU
> in DeepSleep0 entry and exit. WKUP_M3 takes care of the
> clockdomain and powerdomain transitions based on the
> intended low power state. MPU needs to load the appropriate
> WKUP_M3 binary onto the WKUP_M3 memory space before it can
> leverage any of the PM features like DeepSleep.
>
> The IPC mechanism between MPU and WKUP_M3 uses a mailbox
> sub-module and 8 IPC registers in the Control module. MPU
> uses the assigned Mailbox for issuing an interrupt to
> WKUP_M3 which then goes and checks the IPC registers for
> the payload. WKUP_M3 has the ability to trigger on interrupt
> to MPU by executing the "sev" instruction.
>
> In the current implementation when the suspend process
> is initiated MPU interrupts the WKUP_M3 to let it know about
> the intent of entering DeepSleep0 and waits for an ACK. When
> the ACK is received MPU continues with its suspend process
> to suspend all the drivers and then jumps to assembly in
> OCMC RAM. The assembly code puts the PLLs in bypass, puts the
> external RAM in self-refresh mode and then finally execute the
> WFI instruction. Execution of the WFI instruction triggers another
> interrupt to the WKUP_M3 which then continues wiht the power down
> sequence wherein the clockdomain and powerdomain transition takes
> place. As part of the sleep sequence, WKUP_M3 unmasks the interrupt
> lines for the wakeup sources. WFI execution on WKUP_M3 causes the
> hardware to disable the main oscillator of the SoC.
>
> When a wakeup event occurs, WKUP_M3 starts the power-up
> sequence by switching on the power domains and finally
> enabling the clock to MPU. Since the MPU gets powered down
> as part of the sleep sequence in the resume path ROM code
> starts executing. The ROM code detects a wakeup from sleep
> and then jumps to the resume location in OCMC which was
> populated in one of the IPC registers as part of the suspend
> sequence.
>
> The low level code in OCMC relocks the PLLs, enables access
> to external RAM and then jumps to the cpu_resume code of
> the kernel to finish the resume process.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> Cc: Tony Lingren <tony@atomide.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Benoit Cousson <benoit.cousson@linaro.org>
> Cc: Paul Walmsley <paul@pwsan.com>
> Cc: Kevin Hilman <khilman@linaro.org>

Reviewed-by: Russ Dill <russ.dill@ti.com>

In response to Nishanth's comments about the list of omap modules to
idle, I saw that, but it looks like its only for devices that no
device driver ever binds do, eg, the support is not built into the
kernel or the module is currently not loaded. Hence I don't think
there is any suspend/resume function that gets called. In reference to
the M3 handling it, the M3 wouldn't know which devices have a driver
bound and which don't.

> ---
>  arch/arm/mach-omap2/pm33xx.c  |  474 +++++++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/pm33xx.h  |   77 +++++++
>  arch/arm/mach-omap2/wkup_m3.c |  183 ++++++++++++++++
>  3 files changed, 734 insertions(+)
>  create mode 100644 arch/arm/mach-omap2/pm33xx.c
>  create mode 100644 arch/arm/mach-omap2/pm33xx.h
>  create mode 100644 arch/arm/mach-omap2/wkup_m3.c
>
> diff --git a/arch/arm/mach-omap2/pm33xx.c b/arch/arm/mach-omap2/pm33xx.c
> new file mode 100644
> index 0000000..d291c76
> --- /dev/null
> +++ b/arch/arm/mach-omap2/pm33xx.c
> @@ -0,0 +1,474 @@
> +/*
> + * AM33XX Power Management Routines
> + *
> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
> + * Vaibhav Bedia <vaibhav.bedia@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/kernel.h>
> +#include <linux/init.h>
> +#include <linux/cpu.h>
> +#include <linux/err.h>
> +#include <linux/firmware.h>
> +#include <linux/io.h>
> +#include <linux/platform_device.h>
> +#include <linux/sched.h>
> +#include <linux/suspend.h>
> +#include <linux/completion.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/ti_emif.h>
> +#include <linux/omap-mailbox.h>
> +
> +#include <asm/suspend.h>
> +#include <asm/proc-fns.h>
> +#include <asm/sizes.h>
> +#include <asm/fncpy.h>
> +#include <asm/system_misc.h>
> +
> +#include "pm.h"
> +#include "cm33xx.h"
> +#include "pm33xx.h"
> +#include "control.h"
> +#include "common.h"
> +#include "clockdomain.h"
> +#include "powerdomain.h"
> +#include "omap_hwmod.h"
> +#include "omap_device.h"
> +#include "soc.h"
> +#include "sram.h"
> +
> +static void __iomem *am33xx_emif_base;
> +static struct powerdomain *cefuse_pwrdm, *gfx_pwrdm, *per_pwrdm, *mpu_pwrdm;
> +static struct clockdomain *gfx_l4ls_clkdm;
> +
> +struct wakeup_src wakeups[] = {
> +       {.irq_nr = 35,  .src = "USB0_PHY"},
> +       {.irq_nr = 36,  .src = "USB1_PHY"},
> +       {.irq_nr = 40,  .src = "I2C0"},
> +       {.irq_nr = 41,  .src = "RTC Timer"},
> +       {.irq_nr = 42,  .src = "RTC Alarm"},
> +       {.irq_nr = 43,  .src = "Timer0"},
> +       {.irq_nr = 44,  .src = "Timer1"},
> +       {.irq_nr = 45,  .src = "UART"},
> +       {.irq_nr = 46,  .src = "GPIO0"},
> +       {.irq_nr = 48,  .src = "MPU_WAKE"},
> +       {.irq_nr = 49,  .src = "WDT0"},
> +       {.irq_nr = 50,  .src = "WDT1"},
> +       {.irq_nr = 51,  .src = "ADC_TSC"},
> +};
> +
> +struct forced_standby_module am33xx_mod[] = {
> +       {.oh_name = "usb_otg_hs"},
> +       {.oh_name = "tptc0"},
> +       {.oh_name = "tptc1"},
> +       {.oh_name = "tptc2"},
> +       {.oh_name = "cpgmac0"},
> +};
> +
> +static struct am33xx_pm_context *am33xx_pm;
> +
> +static DECLARE_COMPLETION(am33xx_pm_sync);
> +
> +static void (*am33xx_do_wfi_sram)(struct am33xx_suspend_params *);
> +
> +static struct am33xx_suspend_params susp_params;
> +
> +#ifdef CONFIG_SUSPEND
> +
> +static int am33xx_do_sram_idle(long unsigned int unused)
> +{
> +       am33xx_do_wfi_sram(&susp_params);
> +       return 0;
> +}
> +
> +static int am33xx_pm_suspend(void)
> +{
> +       int i, j, ret = 0;
> +
> +       int status = 0;
> +       struct platform_device *pdev;
> +       struct omap_device *od;
> +
> +       /*
> +        * By default the following IPs do not have MSTANDBY asserted
> +        * which is necessary for PER domain transition. If the drivers
> +        * are not compiled into the kernel HWMOD code will not change the
> +        * state of the IPs if the IP was not never enabled. To ensure
> +        * that there no issues with or without the drivers being compiled
> +        * in the kernel, we forcefully put these IPs to idle.
> +        */
> +       for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++) {
> +               pdev = to_platform_device(am33xx_mod[i].dev);
> +               od = to_omap_device(pdev);
> +               if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
> +                       omap_device_enable_hwmods(od);
> +                       omap_device_idle_hwmods(od);
> +               }
> +       }
> +
> +       /* Try to put GFX to sleep */
> +       omap_set_pwrdm_state(gfx_pwrdm, PWRDM_POWER_OFF);
> +       ret = cpu_suspend(0, am33xx_do_sram_idle);
> +
> +       status = pwrdm_read_prev_pwrst(gfx_pwrdm);
> +       if (status != PWRDM_POWER_OFF)
> +               pr_err("PM: GFX domain did not transition\n");
> +       else
> +               pr_info("PM: GFX domain entered low power state\n");
> +
> +       /*
> +        * BUG: GFX_L4LS clock domain needs to be woken up to
> +        * ensure thet L4LS clock domain does not get stuck in transition
> +        * If that happens L3 module does not get disabled, thereby leading
> +        * to PER power domain transition failing
> +        */
> +       clkdm_wakeup(gfx_l4ls_clkdm);
> +       clkdm_sleep(gfx_l4ls_clkdm);
> +
> +       if (ret) {
> +               pr_err("PM: Kernel suspend failure\n");
> +       } else {
> +               i = am33xx_pm_status();
> +               switch (i) {
> +               case 0:
> +                       pr_info("PM: Successfully put all powerdomains to target state\n");
> +
> +                       /*
> +                        * The PRCM registers on AM335x do not contain previous state
> +                        * information like those present on OMAP4 so we must manually
> +                        * indicate transition so state counters are properly incremented
> +                        */
> +                       pwrdm_post_transition(mpu_pwrdm);
> +                       pwrdm_post_transition(per_pwrdm);
> +                       break;
> +               case 1:
> +                       pr_err("PM: Could not transition all powerdomains to target state\n");
> +                       ret = -1;
> +                       break;
> +               default:
> +                       pr_err("PM: CM3 returned unknown result :(\nStatus = %d\n", i);
> +                       ret = -1;
> +               }
> +
> +               /* print the wakeup reason */
> +               i = am33xx_pm_wake_src();
> +               for (j = 0; j < ARRAY_SIZE(wakeups); j++) {
> +                       if (wakeups[j].irq_nr == i) {
> +                               pr_info("PM: Wakeup source %s\n", wakeups[j].src);
> +                               break;
> +                       }
> +               }
> +
> +               if (j == ARRAY_SIZE(wakeups))
> +                       pr_info("PM: Unknown wakeup source %d!\n", i);
> +       }
> +
> +       return ret;
> +}
> +
> +static int am33xx_pm_enter(suspend_state_t suspend_state)
> +{
> +       int ret = 0;
> +
> +       switch (suspend_state) {
> +       case PM_SUSPEND_STANDBY:
> +       case PM_SUSPEND_MEM:
> +               ret = am33xx_pm_suspend();
> +               break;
> +       default:
> +               ret = -EINVAL;
> +       }
> +
> +       return ret;
> +}
> +
> +/* returns the error code from msg_send - 0 for success, failure otherwise */
> +static int am33xx_ping_wkup_m3(void)
> +{
> +       int ret = 0;
> +
> +       /*
> +        * Write a dummy message to the mailbox in order to trigger the RX
> +        * interrupt to alert the M3 that data is available in the IPC
> +        * registers.
> +        */
> +       ret = omap_mbox_msg_send(am33xx_pm->mbox, 0xABCDABCD);
> +
> +       return ret;
> +}
> +
> +static void am33xx_m3_state_machine_reset(void)
> +{
> +       int i;
> +
> +       am33xx_pm->ipc.sleep_mode = IPC_CMD_RESET;
> +
> +       am33xx_pm_ipc_cmd(&am33xx_pm->ipc);
> +
> +       am33xx_pm->state = M3_STATE_MSG_FOR_RESET;
> +
> +       pr_info("PM: Sending message for resetting M3 state machine\n");
> +
> +       if (!am33xx_ping_wkup_m3()) {
> +               i = wait_for_completion_timeout(&am33xx_pm_sync,
> +                                       msecs_to_jiffies(500));
> +               if (WARN(i == 0, "PM: MPU<->CM3 sync failure\n"))
> +                       am33xx_pm->state = M3_STATE_UNKNOWN;
> +       } else {
> +               pr_warn("PM: Unable to ping CM3\n");
> +       }
> +}
> +
> +static int am33xx_pm_begin(suspend_state_t state)
> +{
> +       int i;
> +
> +       cpu_idle_poll_ctrl(true);
> +
> +       am33xx_pm->ipc.sleep_mode       = IPC_CMD_DS0;
> +       am33xx_pm->ipc.param1           = DS_IPC_DEFAULT;
> +       am33xx_pm->ipc.param2           = DS_IPC_DEFAULT;
> +
> +       am33xx_pm_ipc_cmd(&am33xx_pm->ipc);
> +
> +       am33xx_pm->state = M3_STATE_MSG_FOR_LP;
> +
> +       pr_info("PM: Sending message for entering DeepSleep mode\n");
> +
> +       if (!am33xx_ping_wkup_m3()) {
> +               i = wait_for_completion_timeout(&am33xx_pm_sync,
> +                                       msecs_to_jiffies(500));
> +               if (WARN(i == 0, "PM: MPU<->CM3 sync failure\n"))
> +                       return -1;
> +       } else {
> +               pr_warn("PM: Unable to ping CM3\n");
> +       }
> +
> +       return 0;
> +}
> +
> +static void am33xx_pm_end(void)
> +{
> +       am33xx_m3_state_machine_reset();
> +
> +       cpu_idle_poll_ctrl(false);
> +
> +       return;
> +}
> +
> +static struct platform_suspend_ops am33xx_pm_ops = {
> +       .begin          = am33xx_pm_begin,
> +       .end            = am33xx_pm_end,
> +       .enter          = am33xx_pm_enter,
> +};
> +
> +/*
> + * Dummy notifier for the mailbox
> + */
> +
> +static int wkup_mbox_msg(struct notifier_block *self, unsigned long len,
> +               void *msg)
> +{
> +       return 0;
> +}
> +
> +static struct notifier_block wkup_mbox_notifier = {
> +       .notifier_call = wkup_mbox_msg,
> +};
> +
> +void am33xx_txev_handler(void)
> +{
> +       switch (am33xx_pm->state) {
> +       case M3_STATE_RESET:
> +               am33xx_pm->state = M3_STATE_INITED;
> +               am33xx_pm->ver = am33xx_pm_version_get();
> +               if (am33xx_pm->ver == M3_VERSION_UNKNOWN ||
> +                       am33xx_pm->ver < M3_BASELINE_VERSION) {
> +                       pr_warn("PM: CM3 Firmware Version %x not supported\n",
> +                                               am33xx_pm->ver);
> +               } else {
> +                       pr_info("PM: CM3 Firmware Version = 0x%x\n",
> +                                               am33xx_pm->ver);
> +                       am33xx_pm_ops.valid = suspend_valid_only_mem;
> +               }
> +               break;
> +       case M3_STATE_MSG_FOR_RESET:
> +               am33xx_pm->state = M3_STATE_INITED;
> +               complete(&am33xx_pm_sync);
> +               break;
> +       case M3_STATE_MSG_FOR_LP:
> +               complete(&am33xx_pm_sync);
> +               break;
> +       case M3_STATE_UNKNOWN:
> +               pr_warn("PM: Unknown CM3 State\n");
> +       }
> +
> +       return;
> +}
> +
> +static void am33xx_pm_firmware_cb(const struct firmware *fw, void *context)
> +{
> +       struct am33xx_pm_context *am33xx_pm = context;
> +       int ret = 0;
> +
> +       /* no firmware found */
> +       if (!fw) {
> +               pr_err("PM: request_firmware failed\n");
> +               return;
> +       }
> +
> +       wkup_m3_copy_code(fw->data, fw->size);
> +
> +       wkup_m3_register_txev_handler(am33xx_txev_handler);
> +
> +       pr_info("PM: Copied the M3 firmware to UMEM\n");
> +
> +       /*
> +        * Invalidate M3 firmware version before hardreset.
> +        * Write invalid version in lower 4 nibbles of parameter
> +        * register (ipc_regs + 0x8).
> +        */
> +       am33xx_pm_version_clear();
> +
> +       am33xx_pm->state = M3_STATE_RESET;
> +
> +       ret = wkup_m3_prepare();
> +       if (ret) {
> +               pr_err("PM: Could not prepare WKUP_M3\n");
> +               return;
> +       }
> +
> +       /* Physical resume address to be used by ROM code */
> +       am33xx_pm->ipc.resume_addr = (AM33XX_OCMC_END -
> +               am33xx_do_wfi_sz + am33xx_resume_offset + 0x4);
> +
> +       am33xx_pm->mbox = omap_mbox_get("wkup_m3", &wkup_mbox_notifier);
> +
> +       if (IS_ERR(am33xx_pm->mbox)) {
> +               ret = -EBUSY;
> +               pr_err("PM: IPC Request for A8->M3 Channel failed!\n");
> +               return;
> +       } else {
> +               suspend_set_ops(&am33xx_pm_ops);
> +       }
> +
> +       return;
> +}
> +
> +#endif /* CONFIG_SUSPEND */
> +
> +/*
> + * Push the minimal suspend-resume code to SRAM
> + */
> +void am33xx_push_sram_idle(void)
> +{
> +       am33xx_do_wfi_sram = (void *)omap_sram_push
> +                                       (am33xx_do_wfi, am33xx_do_wfi_sz);
> +}
> +
> +static int __init am33xx_map_emif(void)
> +{
> +       am33xx_emif_base = ioremap(AM33XX_EMIF_BASE, SZ_32K);
> +
> +       if (!am33xx_emif_base)
> +               return -ENOMEM;
> +
> +       return 0;
> +}
> +
> +int __init am33xx_pm_init(void)
> +{
> +       int ret;
> +       u32 temp;
> +       struct device_node *np;
> +       int i;
> +
> +       if (!soc_is_am33xx())
> +               return -ENODEV;
> +
> +       pr_info("Power Management for AM33XX family\n");
> +
> +       /*
> +        * By default the following IPs do not have MSTANDBY asserted
> +        * which is necessary for PER domain transition. If the drivers
> +        * are not compiled into the kernel HWMOD code will not change the
> +        * state of the IPs if the IP was not never enabled
> +        */
> +       for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++)
> +               am33xx_mod[i].dev = omap_device_get_by_hwmod_name(am33xx_mod[i].oh_name);
> +
> +       gfx_pwrdm = pwrdm_lookup("gfx_pwrdm");
> +       per_pwrdm = pwrdm_lookup("per_pwrdm");
> +       mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
> +
> +       gfx_l4ls_clkdm = clkdm_lookup("gfx_l4ls_gfx_clkdm");
> +
> +       if ((!gfx_pwrdm) || (!per_pwrdm) || (!mpu_pwrdm) || (!gfx_l4ls_clkdm)) {
> +               ret = -ENODEV;
> +               goto err;
> +       }
> +
> +       am33xx_pm = kzalloc(sizeof(*am33xx_pm), GFP_KERNEL);
> +       if (!am33xx_pm) {
> +               pr_err("Memory allocation failed\n");
> +               ret = -ENOMEM;
> +               goto err;
> +       }
> +
> +       ret = am33xx_map_emif();
> +       if (ret) {
> +               pr_err("PM: Could not ioremap EMIF\n");
> +               goto err;
> +       }
> +       /* Determine Memory Type */
> +       temp = readl(am33xx_emif_base + EMIF_SDRAM_CONFIG);
> +       temp = (temp & SDRAM_TYPE_MASK) >> SDRAM_TYPE_SHIFT;
> +       /* Parameters to pass to aseembly code */
> +       susp_params.emif_addr_virt = am33xx_emif_base;
> +       susp_params.dram_sync = am33xx_dram_sync;
> +       susp_params.mem_type = temp;
> +       am33xx_pm->ipc.param3 = temp;
> +
> +       np = of_find_compatible_node(NULL, NULL, "ti,am3353-wkup-m3");
> +       if (np) {
> +               if (of_find_property(np, "ti,needs_vtt_toggle", NULL) &&
> +                   (!(of_property_read_u32(np, "vtt-gpio-pin",
> +                                                       &temp)))) {
> +                       if (temp >= 0 && temp <= 31)
> +                               am33xx_pm->ipc.param3 |=
> +                                       ((1 << VTT_STAT_SHIFT) |
> +                                       (temp << VTT_GPIO_PIN_SHIFT));
> +               }
> +       }
> +
> +       (void) clkdm_for_each(omap_pm_clkdms_setup, NULL);
> +
> +       /* CEFUSE domain can be turned off post bootup */
> +       cefuse_pwrdm = pwrdm_lookup("cefuse_pwrdm");
> +       if (cefuse_pwrdm)
> +               omap_set_pwrdm_state(cefuse_pwrdm, PWRDM_POWER_OFF);
> +       else
> +               pr_err("PM: Failed to get cefuse_pwrdm\n");
> +
> +#ifdef CONFIG_SUSPEND
> +       pr_info("PM: Trying to load am335x-pm-firmware.bin");
> +
> +       /* We don't want to delay boot */
> +       request_firmware_nowait(THIS_MODULE, 0, "am335x-pm-firmware.bin",
> +                               NULL, GFP_KERNEL, am33xx_pm,
> +                               am33xx_pm_firmware_cb);
> +#endif /* CONFIG_SUSPEND */
> +
> +err:
> +       return ret;
> +}
> diff --git a/arch/arm/mach-omap2/pm33xx.h b/arch/arm/mach-omap2/pm33xx.h
> new file mode 100644
> index 0000000..befdd11
> --- /dev/null
> +++ b/arch/arm/mach-omap2/pm33xx.h
> @@ -0,0 +1,77 @@
> +/*
> + * AM33XX Power Management Routines
> + *
> + * Copyright (C) 2012 Texas Instruments Inc.
> + * Vaibhav Bedia <vaibhav.bedia@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.
> + */
> +#ifndef __ARCH_ARM_MACH_OMAP2_PM33XX_H
> +#define __ARCH_ARM_MACH_OMAP2_PM33XX_H
> +
> +#include "control.h"
> +
> +#ifndef __ASSEMBLER__
> +
> +struct am33xx_pm_context {
> +       struct am33xx_ipc_data  ipc;
> +       struct firmware         *firmware;
> +       struct omap_mbox        *mbox;
> +       u8                      state;
> +       u32                     ver;
> +};
> +
> +/*
> + * Params passed to suspend routine
> + *
> + * Since these are used to load into registers by suspend code,
> + * entries here must always be in sync with the suspend code
> + * in arm/mach-omap2/sleep33xx.S
> + */
> +struct am33xx_suspend_params {
> +       void __iomem *emif_addr_virt;
> +       u32 mem_type;
> +       void __iomem *dram_sync;
> +};
> +
> +struct wakeup_src {
> +       int irq_nr;
> +       char src[10];
> +};
> +
> +struct forced_standby_module {
> +       char oh_name[15];
> +       struct device *dev;
> +};
> +
> +int wkup_m3_copy_code(const u8 *data, size_t size);
> +int wkup_m3_prepare(void);
> +void wkup_m3_register_txev_handler(void (*txev_handler)(void));
> +
> +#endif
> +
> +#define        IPC_CMD_DS0                     0x3
> +#define IPC_CMD_RESET                   0xe
> +#define DS_IPC_DEFAULT                 0xffffffff
> +#define M3_VERSION_UNKNOWN             0x0000ffff
> +#define M3_BASELINE_VERSION            0x21
> +
> +#define M3_STATE_UNKNOWN               0
> +#define M3_STATE_RESET                 1
> +#define M3_STATE_INITED                        2
> +#define M3_STATE_MSG_FOR_LP            3
> +#define M3_STATE_MSG_FOR_RESET         4
> +
> +#define AM33XX_OCMC_END                        0x40310000
> +#define AM33XX_EMIF_BASE               0x4C000000
> +
> +#define MEM_TYPE_DDR2          2
> +
> +#endif
> diff --git a/arch/arm/mach-omap2/wkup_m3.c b/arch/arm/mach-omap2/wkup_m3.c
> new file mode 100644
> index 0000000..8eaa7f3
> --- /dev/null
> +++ b/arch/arm/mach-omap2/wkup_m3.c
> @@ -0,0 +1,183 @@
> +/*
> + * AM33XX Power Management Routines
> + *
> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
> + * Vaibhav Bedia <vaibhav.bedia@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/kernel.h>
> +#include <linux/init.h>
> +#include <linux/slab.h>
> +#include <linux/cpu.h>
> +#include <linux/err.h>
> +#include <linux/firmware.h>
> +#include <linux/io.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/of.h>
> +
> +#include "pm33xx.h"
> +#include "control.h"
> +#include "omap_device.h"
> +#include "soc.h"
> +
> +struct wkup_m3_context {
> +       struct device   *dev;
> +       void __iomem    *code;
> +       void (*txev_handler)(void);
> +};
> +
> +struct wkup_m3_context *wkup_m3;
> +
> +int wkup_m3_copy_code(const u8 *data, size_t size)
> +{
> +       if (size > SZ_16K)
> +               return -ENOMEM;
> +
> +       memcpy_toio(wkup_m3->code, data, size);
> +
> +       return 0;
> +}
> +
> +
> +void wkup_m3_register_txev_handler(void (*txev_handler)(void))
> +{
> +       wkup_m3->txev_handler = txev_handler;
> +}
> +
> +/* have platforms do what they want in atomic context over here? */
> +static irqreturn_t wkup_m3_txev_handler(int irq, void *unused)
> +{
> +       am33xx_txev_eoi();
> +
> +       /* callback to be executed in atomic context */
> +       /* return 0 implies IRQ_HANDLED else IRQ_NONE */
> +       wkup_m3->txev_handler();
> +
> +       am33xx_txev_enable();
> +
> +       return IRQ_HANDLED;
> +}
> +
> +int wkup_m3_prepare(void)
> +{
> +       struct platform_device *pdev = to_platform_device(wkup_m3->dev);
> +
> +       /* check that the code is loaded */
> +       omap_device_deassert_hardreset(pdev, "wkup_m3");
> +
> +       return 0;
> +}
> +
> +static int wkup_m3_probe(struct platform_device *pdev)
> +{
> +       int irq, ret = 0;
> +       struct resource *mem;
> +
> +       pm_runtime_enable(&pdev->dev);
> +
> +       ret = pm_runtime_get_sync(&pdev->dev);
> +       if (IS_ERR_VALUE(ret)) {
> +               dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
> +               return ret;
> +       }
> +
> +       irq = platform_get_irq(pdev, 0);
> +       if (!irq) {
> +               dev_err(wkup_m3->dev, "no irq resource\n");
> +               ret = -ENXIO;
> +               goto err;
> +       }
> +
> +       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       if (!mem) {
> +               dev_err(wkup_m3->dev, "no memory resource\n");
> +               ret = -ENXIO;
> +               goto err;
> +       }
> +
> +       wkup_m3 = kzalloc(sizeof(*wkup_m3), GFP_KERNEL);
> +       if (!wkup_m3) {
> +               pr_err("Memory allocation failed\n");
> +               ret = -ENOMEM;
> +               goto err;
> +       }
> +
> +       wkup_m3->dev = &pdev->dev;
> +
> +       wkup_m3->code = devm_request_and_ioremap(wkup_m3->dev, mem);
> +       if (!wkup_m3->code) {
> +               dev_err(wkup_m3->dev, "could not ioremap\n");
> +               ret = -EADDRNOTAVAIL;
> +               goto err;
> +       }
> +
> +       ret = devm_request_irq(wkup_m3->dev, irq, wkup_m3_txev_handler,
> +                 IRQF_DISABLED, "wkup_m3_txev", NULL);
> +       if (ret) {
> +               dev_err(wkup_m3->dev, "request_irq failed\n");
> +               goto err;
> +       }
> +
> +err:
> +       return ret;
> +}
> +
> +static int wkup_m3_remove(struct platform_device *pdev)
> +{
> +       return 0;
> +}
> +
> +static struct of_device_id wkup_m3_dt_ids[] = {
> +       { .compatible = "ti,am3353-wkup-m3" },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(of, wkup_m3_dt_ids);
> +
> +static int wkup_m3_rpm_suspend(struct device *dev)
> +{
> +       return -EBUSY;
> +}
> +
> +static int wkup_m3_rpm_resume(struct device *dev)
> +{
> +       return 0;
> +}
> +
> +static const struct dev_pm_ops wkup_m3_ops = {
> +       SET_RUNTIME_PM_OPS(wkup_m3_rpm_suspend, wkup_m3_rpm_resume, NULL)
> +};
> +
> +static struct platform_driver wkup_m3_driver = {
> +       .probe          = wkup_m3_probe,
> +       .remove         = wkup_m3_remove,
> +       .driver         = {
> +               .name   = "wkup_m3",
> +               .owner  = THIS_MODULE,
> +               .of_match_table = of_match_ptr(wkup_m3_dt_ids),
> +               .pm     = &wkup_m3_ops,
> +       },
> +};
> +
> +static __init int wkup_m3_init(void)
> +{
> +       return platform_driver_register(&wkup_m3_driver);
> +}
> +
> +static __exit void wkup_m3_exit(void)
> +{
> +       platform_driver_unregister(&wkup_m3_driver);
> +}
> +omap_postcore_initcall(wkup_m3_init);
> +module_exit(wkup_m3_exit);
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 9/9] ARM: OMAP2+: AM33XX: Hookup AM33XX PM code into OMAP builds
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08  8:47     ` Russ Dill
  -1 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08  8:47 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman, Vaibhav Bedia

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> With all the requisite changes in place we can now
> enable the basic PM support for AM335x. This patch
> updates the various OMAP files to enable suspend-resume
> on AM335x.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>

Reviewed-by: Russ Dill <russ.dill@ti.com>

> ---
>  arch/arm/mach-omap2/Kconfig         |    7 +++++--
>  arch/arm/mach-omap2/Makefile        |    2 ++
>  arch/arm/mach-omap2/board-generic.c |    1 +
>  arch/arm/mach-omap2/common.h        |   10 ++++++++++
>  arch/arm/mach-omap2/io.c            |    5 +++++
>  arch/arm/mach-omap2/pm.c            |    3 ++-
>  arch/arm/mach-omap2/pm.h            |    5 +++++
>  arch/arm/mach-omap2/sram.c          |   10 +++++++++-
>  arch/arm/mach-omap2/sram.h          |    2 ++
>  9 files changed, 41 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
> index 3eed000..ef3fe40 100644
> --- a/arch/arm/mach-omap2/Kconfig
> +++ b/arch/arm/mach-omap2/Kconfig
> @@ -67,11 +67,14 @@ config SOC_OMAP5
>  config SOC_AM33XX
>         bool "AM33XX support"
>         depends on ARCH_MULTI_V7
> -       select ARCH_OMAP2PLUS
> +       default y
>         select ARM_CPU_SUSPEND if PM
> +       select COMMON_CLK
>         select CPU_V7
> +       select MAILBOX if PM
>         select MULTI_IRQ_HANDLER
> -       select COMMON_CLK
> +       select OMAP_MBOX_FWK if PM
> +       select OMAP2PLUS_MBOX if PM
>
>  config SOC_AM43XX
>         bool "TI AM43x"
> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
> index d4f6715..eb3a47a 100644
> --- a/arch/arm/mach-omap2/Makefile
> +++ b/arch/arm/mach-omap2/Makefile
> @@ -87,6 +87,7 @@ 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_SOC_OMAP5)                        += omap-mpuss-lowpower.o
> +obj-$(CONFIG_SOC_AM33XX)               += pm33xx.o sleep33xx.o wkup_m3.o
>  obj-$(CONFIG_PM_DEBUG)                 += pm-debug.o
>
>  obj-$(CONFIG_POWER_AVS_OMAP)           += sr_device.o
> @@ -94,6 +95,7 @@ obj-$(CONFIG_POWER_AVS_OMAP_CLASS3)    += smartreflex-class3.o
>
>  AFLAGS_sleep24xx.o                     :=-Wa,-march=armv6
>  AFLAGS_sleep34xx.o                     :=-Wa,-march=armv7-a$(plus_sec)
> +AFLAGS_sleep33xx.o                     :=-Wa,-march=armv7-a$(plus_sec)
>
>  endif
>
> diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
> index aed750c..3f2d6a7 100644
> --- a/arch/arm/mach-omap2/board-generic.c
> +++ b/arch/arm/mach-omap2/board-generic.c
> @@ -159,6 +159,7 @@ DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)")
>         .reserve        = am33xx_reserve,
>         .map_io         = am33xx_map_io,
>         .init_early     = am33xx_init_early,
> +       .init_late      = am33xx_init_late,
>         .init_irq       = omap_intc_of_init,
>         .handle_irq     = omap3_intc_handle_irq,
>         .init_machine   = omap_generic_init,
> diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
> index 6b8ef74..80bf0da 100644
> --- a/arch/arm/mach-omap2/common.h
> +++ b/arch/arm/mach-omap2/common.h
> @@ -69,6 +69,15 @@ static inline int omap4_pm_init(void)
>  }
>  #endif
>
> +#if defined(CONFIG_PM) && defined(CONFIG_SOC_AM33XX)
> +int am33xx_pm_init(void);
> +#else
> +static inline int am33xx_pm_init(void)
> +{
> +       return 0;
> +}
> +#endif
> +
>  #ifdef CONFIG_OMAP_MUX
>  int omap_mux_late_init(void);
>  #else
> @@ -107,6 +116,7 @@ void omap2430_init_late(void);
>  void omap3430_init_late(void);
>  void omap35xx_init_late(void);
>  void omap3630_init_late(void);
> +void am33xx_init_late(void);
>  void am35xx_init_late(void);
>  void ti81xx_init_late(void);
>  int omap2_common_pm_late_init(void);
> diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
> index 3ad7543..63516e5 100644
> --- a/arch/arm/mach-omap2/io.c
> +++ b/arch/arm/mach-omap2/io.c
> @@ -584,6 +584,11 @@ void __init am33xx_init_early(void)
>         omap_hwmod_init_postsetup();
>         omap_clk_init = am33xx_clk_init;
>  }
> +
> +void __init am33xx_init_late(void)
> +{
> +       am33xx_pm_init();
> +}
>  #endif
>
>  #ifdef CONFIG_SOC_AM43XX
> diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
> index e742118..f8bd883 100644
> --- a/arch/arm/mach-omap2/pm.c
> +++ b/arch/arm/mach-omap2/pm.c
> @@ -305,7 +305,8 @@ int __init omap2_common_pm_late_init(void)
>         }
>
>  #ifdef CONFIG_SUSPEND
> -       suspend_set_ops(&omap_pm_ops);
> +       if (!soc_is_am33xx())
> +               suspend_set_ops(&omap_pm_ops);
>  #endif
>
>         return 0;
> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> index 7bdd22a..5122bb6 100644
> --- a/arch/arm/mach-omap2/pm.h
> +++ b/arch/arm/mach-omap2/pm.h
> @@ -82,6 +82,11 @@ extern unsigned int omap3_do_wfi_sz;
>  /* ... and its pointer from SRAM after copy */
>  extern void (*omap3_do_wfi_sram)(void);
>
> +/* am33xx_do_wfi function pointer and size, for copy to SRAM */
> +extern void am33xx_do_wfi(void);
> +extern unsigned int am33xx_do_wfi_sz;
> +extern unsigned int am33xx_resume_offset;
> +
>  /* save_secure_ram_context function pointer and size, for copy to SRAM */
>  extern int save_secure_ram_context(u32 *addr);
>  extern unsigned int save_secure_ram_context_sz;
> diff --git a/arch/arm/mach-omap2/sram.c b/arch/arm/mach-omap2/sram.c
> index 4bd0968..303c562 100644
> --- a/arch/arm/mach-omap2/sram.c
> +++ b/arch/arm/mach-omap2/sram.c
> @@ -154,7 +154,7 @@ static void __init omap2_map_sram(void)
>                 omap_sram_size -= SZ_16K;
>         }
>  #endif
> -       if (cpu_is_omap34xx()) {
> +       if (cpu_is_omap34xx() || soc_is_am33xx()) {
>                 /*
>                  * SRAM must be marked as non-cached on OMAP3 since the
>                  * CORE DPLL M2 divider change code (in SRAM) runs with the
> @@ -285,10 +285,18 @@ static inline int omap34xx_sram_init(void)
>  }
>  #endif /* CONFIG_ARCH_OMAP3 */
>
> +#ifdef CONFIG_SOC_AM33XX
>  static inline int am33xx_sram_init(void)
>  {
> +       am33xx_push_sram_idle();
>         return 0;
>  }
> +#else
> +static inline int am33xx_sram_init(void)
> +{
> +       return 0;
> +}
> +#endif
>
>  int __init omap_sram_init(void)
>  {
> diff --git a/arch/arm/mach-omap2/sram.h b/arch/arm/mach-omap2/sram.h
> index ca7277c..24788b5 100644
> --- a/arch/arm/mach-omap2/sram.h
> +++ b/arch/arm/mach-omap2/sram.h
> @@ -62,8 +62,10 @@ extern unsigned long omap3_sram_configure_core_dpll_sz;
>
>  #ifdef CONFIG_PM
>  extern void omap_push_sram_idle(void);
> +extern void am33xx_push_sram_idle(void);
>  #else
>  static inline void omap_push_sram_idle(void) {}
> +static inline void am33xx_push_sram_idle(void) {}
>  #endif /* CONFIG_PM */
>
>  #endif /* __ASSEMBLY__ */
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 9/9] ARM: OMAP2+: AM33XX: Hookup AM33XX PM code into OMAP builds
@ 2013-08-08  8:47     ` Russ Dill
  0 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08  8:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> With all the requisite changes in place we can now
> enable the basic PM support for AM335x. This patch
> updates the various OMAP files to enable suspend-resume
> on AM335x.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>

Reviewed-by: Russ Dill <russ.dill@ti.com>

> ---
>  arch/arm/mach-omap2/Kconfig         |    7 +++++--
>  arch/arm/mach-omap2/Makefile        |    2 ++
>  arch/arm/mach-omap2/board-generic.c |    1 +
>  arch/arm/mach-omap2/common.h        |   10 ++++++++++
>  arch/arm/mach-omap2/io.c            |    5 +++++
>  arch/arm/mach-omap2/pm.c            |    3 ++-
>  arch/arm/mach-omap2/pm.h            |    5 +++++
>  arch/arm/mach-omap2/sram.c          |   10 +++++++++-
>  arch/arm/mach-omap2/sram.h          |    2 ++
>  9 files changed, 41 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
> index 3eed000..ef3fe40 100644
> --- a/arch/arm/mach-omap2/Kconfig
> +++ b/arch/arm/mach-omap2/Kconfig
> @@ -67,11 +67,14 @@ config SOC_OMAP5
>  config SOC_AM33XX
>         bool "AM33XX support"
>         depends on ARCH_MULTI_V7
> -       select ARCH_OMAP2PLUS
> +       default y
>         select ARM_CPU_SUSPEND if PM
> +       select COMMON_CLK
>         select CPU_V7
> +       select MAILBOX if PM
>         select MULTI_IRQ_HANDLER
> -       select COMMON_CLK
> +       select OMAP_MBOX_FWK if PM
> +       select OMAP2PLUS_MBOX if PM
>
>  config SOC_AM43XX
>         bool "TI AM43x"
> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
> index d4f6715..eb3a47a 100644
> --- a/arch/arm/mach-omap2/Makefile
> +++ b/arch/arm/mach-omap2/Makefile
> @@ -87,6 +87,7 @@ 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_SOC_OMAP5)                        += omap-mpuss-lowpower.o
> +obj-$(CONFIG_SOC_AM33XX)               += pm33xx.o sleep33xx.o wkup_m3.o
>  obj-$(CONFIG_PM_DEBUG)                 += pm-debug.o
>
>  obj-$(CONFIG_POWER_AVS_OMAP)           += sr_device.o
> @@ -94,6 +95,7 @@ obj-$(CONFIG_POWER_AVS_OMAP_CLASS3)    += smartreflex-class3.o
>
>  AFLAGS_sleep24xx.o                     :=-Wa,-march=armv6
>  AFLAGS_sleep34xx.o                     :=-Wa,-march=armv7-a$(plus_sec)
> +AFLAGS_sleep33xx.o                     :=-Wa,-march=armv7-a$(plus_sec)
>
>  endif
>
> diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
> index aed750c..3f2d6a7 100644
> --- a/arch/arm/mach-omap2/board-generic.c
> +++ b/arch/arm/mach-omap2/board-generic.c
> @@ -159,6 +159,7 @@ DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)")
>         .reserve        = am33xx_reserve,
>         .map_io         = am33xx_map_io,
>         .init_early     = am33xx_init_early,
> +       .init_late      = am33xx_init_late,
>         .init_irq       = omap_intc_of_init,
>         .handle_irq     = omap3_intc_handle_irq,
>         .init_machine   = omap_generic_init,
> diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
> index 6b8ef74..80bf0da 100644
> --- a/arch/arm/mach-omap2/common.h
> +++ b/arch/arm/mach-omap2/common.h
> @@ -69,6 +69,15 @@ static inline int omap4_pm_init(void)
>  }
>  #endif
>
> +#if defined(CONFIG_PM) && defined(CONFIG_SOC_AM33XX)
> +int am33xx_pm_init(void);
> +#else
> +static inline int am33xx_pm_init(void)
> +{
> +       return 0;
> +}
> +#endif
> +
>  #ifdef CONFIG_OMAP_MUX
>  int omap_mux_late_init(void);
>  #else
> @@ -107,6 +116,7 @@ void omap2430_init_late(void);
>  void omap3430_init_late(void);
>  void omap35xx_init_late(void);
>  void omap3630_init_late(void);
> +void am33xx_init_late(void);
>  void am35xx_init_late(void);
>  void ti81xx_init_late(void);
>  int omap2_common_pm_late_init(void);
> diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
> index 3ad7543..63516e5 100644
> --- a/arch/arm/mach-omap2/io.c
> +++ b/arch/arm/mach-omap2/io.c
> @@ -584,6 +584,11 @@ void __init am33xx_init_early(void)
>         omap_hwmod_init_postsetup();
>         omap_clk_init = am33xx_clk_init;
>  }
> +
> +void __init am33xx_init_late(void)
> +{
> +       am33xx_pm_init();
> +}
>  #endif
>
>  #ifdef CONFIG_SOC_AM43XX
> diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
> index e742118..f8bd883 100644
> --- a/arch/arm/mach-omap2/pm.c
> +++ b/arch/arm/mach-omap2/pm.c
> @@ -305,7 +305,8 @@ int __init omap2_common_pm_late_init(void)
>         }
>
>  #ifdef CONFIG_SUSPEND
> -       suspend_set_ops(&omap_pm_ops);
> +       if (!soc_is_am33xx())
> +               suspend_set_ops(&omap_pm_ops);
>  #endif
>
>         return 0;
> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> index 7bdd22a..5122bb6 100644
> --- a/arch/arm/mach-omap2/pm.h
> +++ b/arch/arm/mach-omap2/pm.h
> @@ -82,6 +82,11 @@ extern unsigned int omap3_do_wfi_sz;
>  /* ... and its pointer from SRAM after copy */
>  extern void (*omap3_do_wfi_sram)(void);
>
> +/* am33xx_do_wfi function pointer and size, for copy to SRAM */
> +extern void am33xx_do_wfi(void);
> +extern unsigned int am33xx_do_wfi_sz;
> +extern unsigned int am33xx_resume_offset;
> +
>  /* save_secure_ram_context function pointer and size, for copy to SRAM */
>  extern int save_secure_ram_context(u32 *addr);
>  extern unsigned int save_secure_ram_context_sz;
> diff --git a/arch/arm/mach-omap2/sram.c b/arch/arm/mach-omap2/sram.c
> index 4bd0968..303c562 100644
> --- a/arch/arm/mach-omap2/sram.c
> +++ b/arch/arm/mach-omap2/sram.c
> @@ -154,7 +154,7 @@ static void __init omap2_map_sram(void)
>                 omap_sram_size -= SZ_16K;
>         }
>  #endif
> -       if (cpu_is_omap34xx()) {
> +       if (cpu_is_omap34xx() || soc_is_am33xx()) {
>                 /*
>                  * SRAM must be marked as non-cached on OMAP3 since the
>                  * CORE DPLL M2 divider change code (in SRAM) runs with the
> @@ -285,10 +285,18 @@ static inline int omap34xx_sram_init(void)
>  }
>  #endif /* CONFIG_ARCH_OMAP3 */
>
> +#ifdef CONFIG_SOC_AM33XX
>  static inline int am33xx_sram_init(void)
>  {
> +       am33xx_push_sram_idle();
>         return 0;
>  }
> +#else
> +static inline int am33xx_sram_init(void)
> +{
> +       return 0;
> +}
> +#endif
>
>  int __init omap_sram_init(void)
>  {
> diff --git a/arch/arm/mach-omap2/sram.h b/arch/arm/mach-omap2/sram.h
> index ca7277c..24788b5 100644
> --- a/arch/arm/mach-omap2/sram.h
> +++ b/arch/arm/mach-omap2/sram.h
> @@ -62,8 +62,10 @@ extern unsigned long omap3_sram_configure_core_dpll_sz;
>
>  #ifdef CONFIG_PM
>  extern void omap_push_sram_idle(void);
> +extern void am33xx_push_sram_idle(void);
>  #else
>  static inline void omap_push_sram_idle(void) {}
> +static inline void am33xx_push_sram_idle(void) {}
>  #endif /* CONFIG_PM */
>
>  #endif /* __ASSEMBLY__ */
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-08  8:45     ` Russ Dill
@ 2013-08-08 12:26       ` Nishanth Menon
  -1 siblings, 0 replies; 212+ messages in thread
From: Nishanth Menon @ 2013-08-08 12:26 UTC (permalink / raw)
  To: Russ Dill
  Cc: Dave Gerlach, linux-arm-kernel, linux-omap, Paul Walmsley,
	Kevin Hilman, Vaibhav Bedia, Tony Lingren, Santosh Shilimkar,
	Benoit Cousson

On 08/08/2013 03:45 AM, Russ Dill wrote:
>   In reference to
> the M3 handling it, the M3 wouldn't know which devices have a driver
> bound and which don't.
Does it need to? M3 firmware can pretty much define "I will force the 
device into low power state, and if the drivers dont handle things 
properly, fix the darned driver". M3 behavior should be considered as a 
"hardware" as far as Linux running on MPU is concerned, and firmware 
helps change the behavior by accounting for SoC quirks. *if* we have 
ability to handle this in the firmware, there is no need to carry this 
in Linux.

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-08 12:26       ` Nishanth Menon
  0 siblings, 0 replies; 212+ messages in thread
From: Nishanth Menon @ 2013-08-08 12:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/08/2013 03:45 AM, Russ Dill wrote:
>   In reference to
> the M3 handling it, the M3 wouldn't know which devices have a driver
> bound and which don't.
Does it need to? M3 firmware can pretty much define "I will force the 
device into low power state, and if the drivers dont handle things 
properly, fix the darned driver". M3 behavior should be considered as a 
"hardware" as far as Linux running on MPU is concerned, and firmware 
helps change the behavior by accounting for SoC quirks. *if* we have 
ability to handle this in the firmware, there is no need to carry this 
in Linux.

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-08-06 17:49 ` Dave Gerlach
@ 2013-08-08 13:31   ` Santosh Shilimkar
  -1 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 13:31 UTC (permalink / raw)
  To: Dave Gerlach; +Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman

On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> Hi,
> 
> This is the third version of the patch series for adding basic suspend-resume
> support for AM33XX, previously submitted by Vaibhav Bedia. This patchset 
> is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
> that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are 
> required for the pm code to properly suspend and resume.
> 
> The PM code uses the firmware interface and expects the userspace to load 
> the WKUP_M3 binary before the suspend-resume functionality is made available.
> The binary file (and the source-code for WKUP_M3) can be obtained from the 
> 'next2' branch at [4]. The WKUP_M3 binary can either be loaded post bootup 
> via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be 
> included in the kernel image as part of the build process.
> 
> Suspend to mem is tested on am335x-bone and am335x-evm.
> 
> More details on AM335x suspend-resume are provided within the commit logs
> for each patch.
> 
> Changes in v3:
> - Moved wkup_m3 code into separate driver
> - Split up ti_emif header move
> - Addressed clean-up comments
> - Removed mailbox patches
> - v2-v3 Discussion:
> http://marc.info/?l=linux-arm-kernel&m=135698501821090&w=4
> 
Please CC people who have at least reviewed the last version of
the series. Couple of patches I was CC'ed o.w I would missed this series.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-08-08 13:31   ` Santosh Shilimkar
  0 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 13:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> Hi,
> 
> This is the third version of the patch series for adding basic suspend-resume
> support for AM33XX, previously submitted by Vaibhav Bedia. This patchset 
> is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
> that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are 
> required for the pm code to properly suspend and resume.
> 
> The PM code uses the firmware interface and expects the userspace to load 
> the WKUP_M3 binary before the suspend-resume functionality is made available.
> The binary file (and the source-code for WKUP_M3) can be obtained from the 
> 'next2' branch at [4]. The WKUP_M3 binary can either be loaded post bootup 
> via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be 
> included in the kernel image as part of the build process.
> 
> Suspend to mem is tested on am335x-bone and am335x-evm.
> 
> More details on AM335x suspend-resume are provided within the commit logs
> for each patch.
> 
> Changes in v3:
> - Moved wkup_m3 code into separate driver
> - Split up ti_emif header move
> - Addressed clean-up comments
> - Removed mailbox patches
> - v2-v3 Discussion:
> http://marc.info/?l=linux-arm-kernel&m=135698501821090&w=4
> 
Please CC people who have at least reviewed the last version of
the series. Couple of patches I was CC'ed o.w I would missed this series.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 1/9] memory: emif: Move EMIF register defines to include/linux/
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08 13:35     ` Santosh Shilimkar
  -1 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 13:35 UTC (permalink / raw)
  To: Dave Gerlach, Greg Kroah-Hartman
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman,
	Benoit Cousson, Aneesh V

(You have not CC'ed Greg, Looping him)

On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> OMAP4 and AM33XX share the same EMIF controller IP. Although there
> are significant differences in the IP integration due to which
> AM33XX can't reuse the EMIF driver DVFS similar to OMAP4,
> it can definitely benefit by reusing the EMIF related macros
> defined in drivers/memory/emif.h.
> 
> In the current OMAP PM framework the PM code resides under
> arch/arm/mach-omap2/. To enable reuse of the register defines move
> the register defines in the emif header file to include/linux so that
> both the EMIF driver and the AM33XX PM code can benefit.
> 
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Benoit Cousson <benoit.cousson@linaro.org>
> Cc: Aneesh V <aneesh@ti.com>
> ---
>  drivers/memory/emif.h   |  543 +--------------------------------------------
>  include/linux/ti_emif.h |  558 +++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 559 insertions(+), 542 deletions(-)
>  create mode 100644 include/linux/ti_emif.h
> 
For file movement or some part of file movement, while formating
patch, use "git format-patch -C" so that only delta change will
appear in the patch.

The patch as such is fine by me.
Acked-by: Santosh Shililmar <santosh.shilimkar@ti.com>

Greg,
Your ack is needed on this patch so that it can go
along with the series. Subsequent patch from this series
use the register defines from this patch.

> diff --git a/drivers/memory/emif.h b/drivers/memory/emif.h
> index bfe08ba..8214f07 100644
> --- a/drivers/memory/emif.h
> +++ b/drivers/memory/emif.h
> @@ -12,548 +12,7 @@
>  #ifndef __EMIF_H
>  #define __EMIF_H
>  
> -/*
> - * Maximum number of different frequencies supported by EMIF driver
> - * Determines the number of entries in the pointer array for register
> - * cache
> - */
> -#define EMIF_MAX_NUM_FREQUENCIES			6
> -
> -/* State of the core voltage */
> -#define DDR_VOLTAGE_STABLE				0
> -#define DDR_VOLTAGE_RAMPING				1
> -
> -/* Defines for timing De-rating */
> -#define EMIF_NORMAL_TIMINGS				0
> -#define EMIF_DERATED_TIMINGS				1
> -
> -/* Length of the forced read idle period in terms of cycles */
> -#define EMIF_READ_IDLE_LEN_VAL				5
> -
> -/*
> - * forced read idle interval to be used when voltage
> - * is changed as part of DVFS/DPS - 1ms
> - */
> -#define READ_IDLE_INTERVAL_DVFS				(1*1000000)
> -
> -/*
> - * Forced read idle interval to be used when voltage is stable
> - * 50us - or maximum value will do
> - */
> -#define READ_IDLE_INTERVAL_NORMAL			(50*1000000)
> -
> -/* DLL calibration interval when voltage is NOT stable - 1us */
> -#define DLL_CALIB_INTERVAL_DVFS				(1*1000000)
> -
> -#define DLL_CALIB_ACK_WAIT_VAL				5
> -
> -/* Interval between ZQCS commands - hw team recommended value */
> -#define EMIF_ZQCS_INTERVAL_US				(50*1000)
> -/* Enable ZQ Calibration on exiting Self-refresh */
> -#define ZQ_SFEXITEN_ENABLE				1
> -/*
> - * ZQ Calibration simultaneously on both chip-selects:
> - * Needs one calibration resistor per CS
> - */
> -#define	ZQ_DUALCALEN_DISABLE				0
> -#define	ZQ_DUALCALEN_ENABLE				1
> -
> -#define T_ZQCS_DEFAULT_NS				90
> -#define T_ZQCL_DEFAULT_NS				360
> -#define T_ZQINIT_DEFAULT_NS				1000
> -
> -/* DPD_EN */
> -#define DPD_DISABLE					0
> -#define DPD_ENABLE					1
> -
> -/*
> - * Default values for the low-power entry to be used if not provided by user.
> - * OMAP4/5 has a hw bug(i735) due to which this value can not be less than 512
> - * Timeout values are in DDR clock 'cycles' and frequency threshold in Hz
> - */
> -#define EMIF_LP_MODE_TIMEOUT_PERFORMANCE		2048
> -#define EMIF_LP_MODE_TIMEOUT_POWER			512
> -#define EMIF_LP_MODE_FREQ_THRESHOLD			400000000
> -
> -/* DDR_PHY_CTRL_1 values for EMIF4D - ATTILA PHY combination */
> -#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY		0x049FF000
> -#define EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY	0x41
> -#define EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY	0x80
> -#define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY 0xFF
> -
> -/* DDR_PHY_CTRL_1 values for EMIF4D5 INTELLIPHY combination */
> -#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY		0x0E084200
> -#define EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS	10000
> -
> -/* TEMP_ALERT_CONFIG - corresponding to temp gradient 5 C/s */
> -#define TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS		360
> -
> -#define EMIF_T_CSTA					3
> -#define EMIF_T_PDLL_UL					128
> -
> -/* External PHY control registers magic values */
> -#define EMIF_EXT_PHY_CTRL_1_VAL				0x04020080
> -#define EMIF_EXT_PHY_CTRL_5_VAL				0x04010040
> -#define EMIF_EXT_PHY_CTRL_6_VAL				0x01004010
> -#define EMIF_EXT_PHY_CTRL_7_VAL				0x00001004
> -#define EMIF_EXT_PHY_CTRL_8_VAL				0x04010040
> -#define EMIF_EXT_PHY_CTRL_9_VAL				0x01004010
> -#define EMIF_EXT_PHY_CTRL_10_VAL			0x00001004
> -#define EMIF_EXT_PHY_CTRL_11_VAL			0x00000000
> -#define EMIF_EXT_PHY_CTRL_12_VAL			0x00000000
> -#define EMIF_EXT_PHY_CTRL_13_VAL			0x00000000
> -#define EMIF_EXT_PHY_CTRL_14_VAL			0x80080080
> -#define EMIF_EXT_PHY_CTRL_15_VAL			0x00800800
> -#define EMIF_EXT_PHY_CTRL_16_VAL			0x08102040
> -#define EMIF_EXT_PHY_CTRL_17_VAL			0x00000001
> -#define EMIF_EXT_PHY_CTRL_18_VAL			0x540A8150
> -#define EMIF_EXT_PHY_CTRL_19_VAL			0xA81502A0
> -#define EMIF_EXT_PHY_CTRL_20_VAL			0x002A0540
> -#define EMIF_EXT_PHY_CTRL_21_VAL			0x00000000
> -#define EMIF_EXT_PHY_CTRL_22_VAL			0x00000000
> -#define EMIF_EXT_PHY_CTRL_23_VAL			0x00000000
> -#define EMIF_EXT_PHY_CTRL_24_VAL			0x00000077
> -
> -#define EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS	1200
> -
> -/* Registers offset */
> -#define EMIF_MODULE_ID_AND_REVISION			0x0000
> -#define EMIF_STATUS					0x0004
> -#define EMIF_SDRAM_CONFIG				0x0008
> -#define EMIF_SDRAM_CONFIG_2				0x000c
> -#define EMIF_SDRAM_REFRESH_CONTROL			0x0010
> -#define EMIF_SDRAM_REFRESH_CTRL_SHDW			0x0014
> -#define EMIF_SDRAM_TIMING_1				0x0018
> -#define EMIF_SDRAM_TIMING_1_SHDW			0x001c
> -#define EMIF_SDRAM_TIMING_2				0x0020
> -#define EMIF_SDRAM_TIMING_2_SHDW			0x0024
> -#define EMIF_SDRAM_TIMING_3				0x0028
> -#define EMIF_SDRAM_TIMING_3_SHDW			0x002c
> -#define EMIF_LPDDR2_NVM_TIMING				0x0030
> -#define EMIF_LPDDR2_NVM_TIMING_SHDW			0x0034
> -#define EMIF_POWER_MANAGEMENT_CONTROL			0x0038
> -#define EMIF_POWER_MANAGEMENT_CTRL_SHDW			0x003c
> -#define EMIF_LPDDR2_MODE_REG_DATA			0x0040
> -#define EMIF_LPDDR2_MODE_REG_CONFIG			0x0050
> -#define EMIF_OCP_CONFIG					0x0054
> -#define EMIF_OCP_CONFIG_VALUE_1				0x0058
> -#define EMIF_OCP_CONFIG_VALUE_2				0x005c
> -#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL		0x0060
> -#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT		0x0064
> -#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT	0x0068
> -#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1	0x006c
> -#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2	0x0070
> -#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3	0x0074
> -#define EMIF_PERFORMANCE_COUNTER_1			0x0080
> -#define EMIF_PERFORMANCE_COUNTER_2			0x0084
> -#define EMIF_PERFORMANCE_COUNTER_CONFIG			0x0088
> -#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT	0x008c
> -#define EMIF_PERFORMANCE_COUNTER_TIME			0x0090
> -#define EMIF_MISC_REG					0x0094
> -#define EMIF_DLL_CALIB_CTRL				0x0098
> -#define EMIF_DLL_CALIB_CTRL_SHDW			0x009c
> -#define EMIF_END_OF_INTERRUPT				0x00a0
> -#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS		0x00a4
> -#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS		0x00a8
> -#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS		0x00ac
> -#define EMIF_LL_OCP_INTERRUPT_STATUS			0x00b0
> -#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET		0x00b4
> -#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET		0x00b8
> -#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR		0x00bc
> -#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR		0x00c0
> -#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG	0x00c8
> -#define EMIF_TEMPERATURE_ALERT_CONFIG			0x00cc
> -#define EMIF_OCP_ERROR_LOG				0x00d0
> -#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW		0x00d4
> -#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL		0x00d8
> -#define EMIF_READ_WRITE_LEVELING_CONTROL		0x00dc
> -#define EMIF_DDR_PHY_CTRL_1				0x00e4
> -#define EMIF_DDR_PHY_CTRL_1_SHDW			0x00e8
> -#define EMIF_DDR_PHY_CTRL_2				0x00ec
> -#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING	0x0100
> -#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104
> -#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108
> -#define EMIF_READ_WRITE_EXECUTION_THRESHOLD		0x0120
> -#define EMIF_COS_CONFIG					0x0124
> -#define EMIF_PHY_STATUS_1				0x0140
> -#define EMIF_PHY_STATUS_2				0x0144
> -#define EMIF_PHY_STATUS_3				0x0148
> -#define EMIF_PHY_STATUS_4				0x014c
> -#define EMIF_PHY_STATUS_5				0x0150
> -#define EMIF_PHY_STATUS_6				0x0154
> -#define EMIF_PHY_STATUS_7				0x0158
> -#define EMIF_PHY_STATUS_8				0x015c
> -#define EMIF_PHY_STATUS_9				0x0160
> -#define EMIF_PHY_STATUS_10				0x0164
> -#define EMIF_PHY_STATUS_11				0x0168
> -#define EMIF_PHY_STATUS_12				0x016c
> -#define EMIF_PHY_STATUS_13				0x0170
> -#define EMIF_PHY_STATUS_14				0x0174
> -#define EMIF_PHY_STATUS_15				0x0178
> -#define EMIF_PHY_STATUS_16				0x017c
> -#define EMIF_PHY_STATUS_17				0x0180
> -#define EMIF_PHY_STATUS_18				0x0184
> -#define EMIF_PHY_STATUS_19				0x0188
> -#define EMIF_PHY_STATUS_20				0x018c
> -#define EMIF_PHY_STATUS_21				0x0190
> -#define EMIF_EXT_PHY_CTRL_1				0x0200
> -#define EMIF_EXT_PHY_CTRL_1_SHDW			0x0204
> -#define EMIF_EXT_PHY_CTRL_2				0x0208
> -#define EMIF_EXT_PHY_CTRL_2_SHDW			0x020c
> -#define EMIF_EXT_PHY_CTRL_3				0x0210
> -#define EMIF_EXT_PHY_CTRL_3_SHDW			0x0214
> -#define EMIF_EXT_PHY_CTRL_4				0x0218
> -#define EMIF_EXT_PHY_CTRL_4_SHDW			0x021c
> -#define EMIF_EXT_PHY_CTRL_5				0x0220
> -#define EMIF_EXT_PHY_CTRL_5_SHDW			0x0224
> -#define EMIF_EXT_PHY_CTRL_6				0x0228
> -#define EMIF_EXT_PHY_CTRL_6_SHDW			0x022c
> -#define EMIF_EXT_PHY_CTRL_7				0x0230
> -#define EMIF_EXT_PHY_CTRL_7_SHDW			0x0234
> -#define EMIF_EXT_PHY_CTRL_8				0x0238
> -#define EMIF_EXT_PHY_CTRL_8_SHDW			0x023c
> -#define EMIF_EXT_PHY_CTRL_9				0x0240
> -#define EMIF_EXT_PHY_CTRL_9_SHDW			0x0244
> -#define EMIF_EXT_PHY_CTRL_10				0x0248
> -#define EMIF_EXT_PHY_CTRL_10_SHDW			0x024c
> -#define EMIF_EXT_PHY_CTRL_11				0x0250
> -#define EMIF_EXT_PHY_CTRL_11_SHDW			0x0254
> -#define EMIF_EXT_PHY_CTRL_12				0x0258
> -#define EMIF_EXT_PHY_CTRL_12_SHDW			0x025c
> -#define EMIF_EXT_PHY_CTRL_13				0x0260
> -#define EMIF_EXT_PHY_CTRL_13_SHDW			0x0264
> -#define EMIF_EXT_PHY_CTRL_14				0x0268
> -#define EMIF_EXT_PHY_CTRL_14_SHDW			0x026c
> -#define EMIF_EXT_PHY_CTRL_15				0x0270
> -#define EMIF_EXT_PHY_CTRL_15_SHDW			0x0274
> -#define EMIF_EXT_PHY_CTRL_16				0x0278
> -#define EMIF_EXT_PHY_CTRL_16_SHDW			0x027c
> -#define EMIF_EXT_PHY_CTRL_17				0x0280
> -#define EMIF_EXT_PHY_CTRL_17_SHDW			0x0284
> -#define EMIF_EXT_PHY_CTRL_18				0x0288
> -#define EMIF_EXT_PHY_CTRL_18_SHDW			0x028c
> -#define EMIF_EXT_PHY_CTRL_19				0x0290
> -#define EMIF_EXT_PHY_CTRL_19_SHDW			0x0294
> -#define EMIF_EXT_PHY_CTRL_20				0x0298
> -#define EMIF_EXT_PHY_CTRL_20_SHDW			0x029c
> -#define EMIF_EXT_PHY_CTRL_21				0x02a0
> -#define EMIF_EXT_PHY_CTRL_21_SHDW			0x02a4
> -#define EMIF_EXT_PHY_CTRL_22				0x02a8
> -#define EMIF_EXT_PHY_CTRL_22_SHDW			0x02ac
> -#define EMIF_EXT_PHY_CTRL_23				0x02b0
> -#define EMIF_EXT_PHY_CTRL_23_SHDW			0x02b4
> -#define EMIF_EXT_PHY_CTRL_24				0x02b8
> -#define EMIF_EXT_PHY_CTRL_24_SHDW			0x02bc
> -#define EMIF_EXT_PHY_CTRL_25				0x02c0
> -#define EMIF_EXT_PHY_CTRL_25_SHDW			0x02c4
> -#define EMIF_EXT_PHY_CTRL_26				0x02c8
> -#define EMIF_EXT_PHY_CTRL_26_SHDW			0x02cc
> -#define EMIF_EXT_PHY_CTRL_27				0x02d0
> -#define EMIF_EXT_PHY_CTRL_27_SHDW			0x02d4
> -#define EMIF_EXT_PHY_CTRL_28				0x02d8
> -#define EMIF_EXT_PHY_CTRL_28_SHDW			0x02dc
> -#define EMIF_EXT_PHY_CTRL_29				0x02e0
> -#define EMIF_EXT_PHY_CTRL_29_SHDW			0x02e4
> -#define EMIF_EXT_PHY_CTRL_30				0x02e8
> -#define EMIF_EXT_PHY_CTRL_30_SHDW			0x02ec
> -
> -/* Registers shifts and masks */
> -
> -/* EMIF_MODULE_ID_AND_REVISION */
> -#define SCHEME_SHIFT					30
> -#define SCHEME_MASK					(0x3 << 30)
> -#define MODULE_ID_SHIFT					16
> -#define MODULE_ID_MASK					(0xfff << 16)
> -#define RTL_VERSION_SHIFT				11
> -#define RTL_VERSION_MASK				(0x1f << 11)
> -#define MAJOR_REVISION_SHIFT				8
> -#define MAJOR_REVISION_MASK				(0x7 << 8)
> -#define MINOR_REVISION_SHIFT				0
> -#define MINOR_REVISION_MASK				(0x3f << 0)
> -
> -/* STATUS */
> -#define BE_SHIFT					31
> -#define BE_MASK						(1 << 31)
> -#define DUAL_CLK_MODE_SHIFT				30
> -#define DUAL_CLK_MODE_MASK				(1 << 30)
> -#define FAST_INIT_SHIFT					29
> -#define FAST_INIT_MASK					(1 << 29)
> -#define RDLVLGATETO_SHIFT				6
> -#define RDLVLGATETO_MASK				(1 << 6)
> -#define RDLVLTO_SHIFT					5
> -#define RDLVLTO_MASK					(1 << 5)
> -#define WRLVLTO_SHIFT					4
> -#define WRLVLTO_MASK					(1 << 4)
> -#define PHY_DLL_READY_SHIFT				2
> -#define PHY_DLL_READY_MASK				(1 << 2)
> -
> -/* SDRAM_CONFIG */
> -#define SDRAM_TYPE_SHIFT				29
> -#define SDRAM_TYPE_MASK					(0x7 << 29)
> -#define IBANK_POS_SHIFT					27
> -#define IBANK_POS_MASK					(0x3 << 27)
> -#define DDR_TERM_SHIFT					24
> -#define DDR_TERM_MASK					(0x7 << 24)
> -#define DDR2_DDQS_SHIFT					23
> -#define DDR2_DDQS_MASK					(1 << 23)
> -#define DYN_ODT_SHIFT					21
> -#define DYN_ODT_MASK					(0x3 << 21)
> -#define DDR_DISABLE_DLL_SHIFT				20
> -#define DDR_DISABLE_DLL_MASK				(1 << 20)
> -#define SDRAM_DRIVE_SHIFT				18
> -#define SDRAM_DRIVE_MASK				(0x3 << 18)
> -#define CWL_SHIFT					16
> -#define CWL_MASK					(0x3 << 16)
> -#define NARROW_MODE_SHIFT				14
> -#define NARROW_MODE_MASK				(0x3 << 14)
> -#define CL_SHIFT					10
> -#define CL_MASK						(0xf << 10)
> -#define ROWSIZE_SHIFT					7
> -#define ROWSIZE_MASK					(0x7 << 7)
> -#define IBANK_SHIFT					4
> -#define IBANK_MASK					(0x7 << 4)
> -#define EBANK_SHIFT					3
> -#define EBANK_MASK					(1 << 3)
> -#define PAGESIZE_SHIFT					0
> -#define PAGESIZE_MASK					(0x7 << 0)
> -
> -/* SDRAM_CONFIG_2 */
> -#define CS1NVMEN_SHIFT					30
> -#define CS1NVMEN_MASK					(1 << 30)
> -#define EBANK_POS_SHIFT					27
> -#define EBANK_POS_MASK					(1 << 27)
> -#define RDBNUM_SHIFT					4
> -#define RDBNUM_MASK					(0x3 << 4)
> -#define RDBSIZE_SHIFT					0
> -#define RDBSIZE_MASK					(0x7 << 0)
> -
> -/* SDRAM_REFRESH_CONTROL */
> -#define INITREF_DIS_SHIFT				31
> -#define INITREF_DIS_MASK				(1 << 31)
> -#define SRT_SHIFT					29
> -#define SRT_MASK					(1 << 29)
> -#define ASR_SHIFT					28
> -#define ASR_MASK					(1 << 28)
> -#define PASR_SHIFT					24
> -#define PASR_MASK					(0x7 << 24)
> -#define REFRESH_RATE_SHIFT				0
> -#define REFRESH_RATE_MASK				(0xffff << 0)
> -
> -/* SDRAM_TIMING_1 */
> -#define T_RTW_SHIFT					29
> -#define T_RTW_MASK					(0x7 << 29)
> -#define T_RP_SHIFT					25
> -#define T_RP_MASK					(0xf << 25)
> -#define T_RCD_SHIFT					21
> -#define T_RCD_MASK					(0xf << 21)
> -#define T_WR_SHIFT					17
> -#define T_WR_MASK					(0xf << 17)
> -#define T_RAS_SHIFT					12
> -#define T_RAS_MASK					(0x1f << 12)
> -#define T_RC_SHIFT					6
> -#define T_RC_MASK					(0x3f << 6)
> -#define T_RRD_SHIFT					3
> -#define T_RRD_MASK					(0x7 << 3)
> -#define T_WTR_SHIFT					0
> -#define T_WTR_MASK					(0x7 << 0)
> -
> -/* SDRAM_TIMING_2 */
> -#define T_XP_SHIFT					28
> -#define T_XP_MASK					(0x7 << 28)
> -#define T_ODT_SHIFT					25
> -#define T_ODT_MASK					(0x7 << 25)
> -#define T_XSNR_SHIFT					16
> -#define T_XSNR_MASK					(0x1ff << 16)
> -#define T_XSRD_SHIFT					6
> -#define T_XSRD_MASK					(0x3ff << 6)
> -#define T_RTP_SHIFT					3
> -#define T_RTP_MASK					(0x7 << 3)
> -#define T_CKE_SHIFT					0
> -#define T_CKE_MASK					(0x7 << 0)
> -
> -/* SDRAM_TIMING_3 */
> -#define T_PDLL_UL_SHIFT					28
> -#define T_PDLL_UL_MASK					(0xf << 28)
> -#define T_CSTA_SHIFT					24
> -#define T_CSTA_MASK					(0xf << 24)
> -#define T_CKESR_SHIFT					21
> -#define T_CKESR_MASK					(0x7 << 21)
> -#define ZQ_ZQCS_SHIFT					15
> -#define ZQ_ZQCS_MASK					(0x3f << 15)
> -#define T_TDQSCKMAX_SHIFT				13
> -#define T_TDQSCKMAX_MASK				(0x3 << 13)
> -#define T_RFC_SHIFT					4
> -#define T_RFC_MASK					(0x1ff << 4)
> -#define T_RAS_MAX_SHIFT					0
> -#define T_RAS_MAX_MASK					(0xf << 0)
> -
> -/* POWER_MANAGEMENT_CONTROL */
> -#define PD_TIM_SHIFT					12
> -#define PD_TIM_MASK					(0xf << 12)
> -#define DPD_EN_SHIFT					11
> -#define DPD_EN_MASK					(1 << 11)
> -#define LP_MODE_SHIFT					8
> -#define LP_MODE_MASK					(0x7 << 8)
> -#define SR_TIM_SHIFT					4
> -#define SR_TIM_MASK					(0xf << 4)
> -#define CS_TIM_SHIFT					0
> -#define CS_TIM_MASK					(0xf << 0)
> -
> -/* LPDDR2_MODE_REG_DATA */
> -#define VALUE_0_SHIFT					0
> -#define VALUE_0_MASK					(0x7f << 0)
> -
> -/* LPDDR2_MODE_REG_CONFIG */
> -#define CS_SHIFT					31
> -#define CS_MASK						(1 << 31)
> -#define REFRESH_EN_SHIFT				30
> -#define REFRESH_EN_MASK					(1 << 30)
> -#define ADDRESS_SHIFT					0
> -#define ADDRESS_MASK					(0xff << 0)
> -
> -/* OCP_CONFIG */
> -#define SYS_THRESH_MAX_SHIFT				24
> -#define SYS_THRESH_MAX_MASK				(0xf << 24)
> -#define MPU_THRESH_MAX_SHIFT				20
> -#define MPU_THRESH_MAX_MASK				(0xf << 20)
> -#define LL_THRESH_MAX_SHIFT				16
> -#define LL_THRESH_MAX_MASK				(0xf << 16)
> -
> -/* PERFORMANCE_COUNTER_1 */
> -#define COUNTER1_SHIFT					0
> -#define COUNTER1_MASK					(0xffffffff << 0)
> -
> -/* PERFORMANCE_COUNTER_2 */
> -#define COUNTER2_SHIFT					0
> -#define COUNTER2_MASK					(0xffffffff << 0)
> -
> -/* PERFORMANCE_COUNTER_CONFIG */
> -#define CNTR2_MCONNID_EN_SHIFT				31
> -#define CNTR2_MCONNID_EN_MASK				(1 << 31)
> -#define CNTR2_REGION_EN_SHIFT				30
> -#define CNTR2_REGION_EN_MASK				(1 << 30)
> -#define CNTR2_CFG_SHIFT					16
> -#define CNTR2_CFG_MASK					(0xf << 16)
> -#define CNTR1_MCONNID_EN_SHIFT				15
> -#define CNTR1_MCONNID_EN_MASK				(1 << 15)
> -#define CNTR1_REGION_EN_SHIFT				14
> -#define CNTR1_REGION_EN_MASK				(1 << 14)
> -#define CNTR1_CFG_SHIFT					0
> -#define CNTR1_CFG_MASK					(0xf << 0)
> -
> -/* PERFORMANCE_COUNTER_MASTER_REGION_SELECT */
> -#define MCONNID2_SHIFT					24
> -#define MCONNID2_MASK					(0xff << 24)
> -#define REGION_SEL2_SHIFT				16
> -#define REGION_SEL2_MASK				(0x3 << 16)
> -#define MCONNID1_SHIFT					8
> -#define MCONNID1_MASK					(0xff << 8)
> -#define REGION_SEL1_SHIFT				0
> -#define REGION_SEL1_MASK				(0x3 << 0)
> -
> -/* PERFORMANCE_COUNTER_TIME */
> -#define TOTAL_TIME_SHIFT				0
> -#define TOTAL_TIME_MASK					(0xffffffff << 0)
> -
> -/* DLL_CALIB_CTRL */
> -#define ACK_WAIT_SHIFT					16
> -#define ACK_WAIT_MASK					(0xf << 16)
> -#define DLL_CALIB_INTERVAL_SHIFT			0
> -#define DLL_CALIB_INTERVAL_MASK				(0x1ff << 0)
> -
> -/* END_OF_INTERRUPT */
> -#define EOI_SHIFT					0
> -#define EOI_MASK					(1 << 0)
> -
> -/* SYSTEM_OCP_INTERRUPT_RAW_STATUS */
> -#define DNV_SYS_SHIFT					2
> -#define DNV_SYS_MASK					(1 << 2)
> -#define TA_SYS_SHIFT					1
> -#define TA_SYS_MASK					(1 << 1)
> -#define ERR_SYS_SHIFT					0
> -#define ERR_SYS_MASK					(1 << 0)
> -
> -/* LOW_LATENCY_OCP_INTERRUPT_RAW_STATUS */
> -#define DNV_LL_SHIFT					2
> -#define DNV_LL_MASK					(1 << 2)
> -#define TA_LL_SHIFT					1
> -#define TA_LL_MASK					(1 << 1)
> -#define ERR_LL_SHIFT					0
> -#define ERR_LL_MASK					(1 << 0)
> -
> -/* SYSTEM_OCP_INTERRUPT_ENABLE_SET */
> -#define EN_DNV_SYS_SHIFT				2
> -#define EN_DNV_SYS_MASK					(1 << 2)
> -#define EN_TA_SYS_SHIFT					1
> -#define EN_TA_SYS_MASK					(1 << 1)
> -#define EN_ERR_SYS_SHIFT					0
> -#define EN_ERR_SYS_MASK					(1 << 0)
> -
> -/* LOW_LATENCY_OCP_INTERRUPT_ENABLE_SET */
> -#define EN_DNV_LL_SHIFT					2
> -#define EN_DNV_LL_MASK					(1 << 2)
> -#define EN_TA_LL_SHIFT					1
> -#define EN_TA_LL_MASK					(1 << 1)
> -#define EN_ERR_LL_SHIFT					0
> -#define EN_ERR_LL_MASK					(1 << 0)
> -
> -/* SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG */
> -#define ZQ_CS1EN_SHIFT					31
> -#define ZQ_CS1EN_MASK					(1 << 31)
> -#define ZQ_CS0EN_SHIFT					30
> -#define ZQ_CS0EN_MASK					(1 << 30)
> -#define ZQ_DUALCALEN_SHIFT				29
> -#define ZQ_DUALCALEN_MASK				(1 << 29)
> -#define ZQ_SFEXITEN_SHIFT				28
> -#define ZQ_SFEXITEN_MASK				(1 << 28)
> -#define ZQ_ZQINIT_MULT_SHIFT				18
> -#define ZQ_ZQINIT_MULT_MASK				(0x3 << 18)
> -#define ZQ_ZQCL_MULT_SHIFT				16
> -#define ZQ_ZQCL_MULT_MASK				(0x3 << 16)
> -#define ZQ_REFINTERVAL_SHIFT				0
> -#define ZQ_REFINTERVAL_MASK				(0xffff << 0)
> -
> -/* TEMPERATURE_ALERT_CONFIG */
> -#define TA_CS1EN_SHIFT					31
> -#define TA_CS1EN_MASK					(1 << 31)
> -#define TA_CS0EN_SHIFT					30
> -#define TA_CS0EN_MASK					(1 << 30)
> -#define TA_SFEXITEN_SHIFT				28
> -#define TA_SFEXITEN_MASK				(1 << 28)
> -#define TA_DEVWDT_SHIFT					26
> -#define TA_DEVWDT_MASK					(0x3 << 26)
> -#define TA_DEVCNT_SHIFT					24
> -#define TA_DEVCNT_MASK					(0x3 << 24)
> -#define TA_REFINTERVAL_SHIFT				0
> -#define TA_REFINTERVAL_MASK				(0x3fffff << 0)
> -
> -/* OCP_ERROR_LOG */
> -#define MADDRSPACE_SHIFT				14
> -#define MADDRSPACE_MASK					(0x3 << 14)
> -#define MBURSTSEQ_SHIFT					11
> -#define MBURSTSEQ_MASK					(0x7 << 11)
> -#define MCMD_SHIFT					8
> -#define MCMD_MASK					(0x7 << 8)
> -#define MCONNID_SHIFT					0
> -#define MCONNID_MASK					(0xff << 0)
> -
> -/* DDR_PHY_CTRL_1 - EMIF4D */
> -#define DLL_SLAVE_DLY_CTRL_SHIFT_4D			4
> -#define DLL_SLAVE_DLY_CTRL_MASK_4D			(0xFF << 4)
> -#define READ_LATENCY_SHIFT_4D				0
> -#define READ_LATENCY_MASK_4D				(0xf << 0)
> -
> -/* DDR_PHY_CTRL_1 - EMIF4D5 */
> -#define DLL_HALF_DELAY_SHIFT_4D5			21
> -#define DLL_HALF_DELAY_MASK_4D5				(1 << 21)
> -#define READ_LATENCY_SHIFT_4D5				0
> -#define READ_LATENCY_MASK_4D5				(0x1f << 0)
> -
> -/* DDR_PHY_CTRL_1_SHDW */
> -#define DDR_PHY_CTRL_1_SHDW_SHIFT			5
> -#define DDR_PHY_CTRL_1_SHDW_MASK			(0x7ffffff << 5)
> -#define READ_LATENCY_SHDW_SHIFT				0
> -#define READ_LATENCY_SHDW_MASK				(0x1f << 0)
> +#include <linux/ti_emif.h>
>  
>  #ifndef __ASSEMBLY__
>  /*
> diff --git a/include/linux/ti_emif.h b/include/linux/ti_emif.h
> new file mode 100644
> index 0000000..be26e7f
> --- /dev/null
> +++ b/include/linux/ti_emif.h
> @@ -0,0 +1,558 @@
> +/*
> + * Register defines for the EMIF driver
> + *
> + * Copyright (C) 2012 Texas Instruments, Inc.
> + *
> + * Benoit Cousson (b-cousson@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.
> + */
> +#ifndef __TI_EMIF_H
> +#define __TI_EMIF_H
> +
> +/*
> + * Maximum number of different frequencies supported by EMIF driver
> + * Determines the number of entries in the pointer array for register
> + * cache
> + */
> +#define EMIF_MAX_NUM_FREQUENCIES			6
> +
> +/* State of the core voltage */
> +#define DDR_VOLTAGE_STABLE				0
> +#define DDR_VOLTAGE_RAMPING				1
> +
> +/* Defines for timing De-rating */
> +#define EMIF_NORMAL_TIMINGS				0
> +#define EMIF_DERATED_TIMINGS				1
> +
> +/* Length of the forced read idle period in terms of cycles */
> +#define EMIF_READ_IDLE_LEN_VAL				5
> +
> +/*
> + * forced read idle interval to be used when voltage
> + * is changed as part of DVFS/DPS - 1ms
> + */
> +#define READ_IDLE_INTERVAL_DVFS				(1*1000000)
> +
> +/*
> + * Forced read idle interval to be used when voltage is stable
> + * 50us - or maximum value will do
> + */
> +#define READ_IDLE_INTERVAL_NORMAL			(50*1000000)
> +
> +/* DLL calibration interval when voltage is NOT stable - 1us */
> +#define DLL_CALIB_INTERVAL_DVFS				(1*1000000)
> +
> +#define DLL_CALIB_ACK_WAIT_VAL				5
> +
> +/* Interval between ZQCS commands - hw team recommended value */
> +#define EMIF_ZQCS_INTERVAL_US				(50*1000)
> +/* Enable ZQ Calibration on exiting Self-refresh */
> +#define ZQ_SFEXITEN_ENABLE				1
> +/*
> + * ZQ Calibration simultaneously on both chip-selects:
> + * Needs one calibration resistor per CS
> + */
> +#define	ZQ_DUALCALEN_DISABLE				0
> +#define	ZQ_DUALCALEN_ENABLE				1
> +
> +#define T_ZQCS_DEFAULT_NS				90
> +#define T_ZQCL_DEFAULT_NS				360
> +#define T_ZQINIT_DEFAULT_NS				1000
> +
> +/* DPD_EN */
> +#define DPD_DISABLE					0
> +#define DPD_ENABLE					1
> +
> +/*
> + * Default values for the low-power entry to be used if not provided by user.
> + * OMAP4/5 has a hw bug(i735) due to which this value can not be less than 512
> + * Timeout values are in DDR clock 'cycles' and frequency threshold in Hz
> + */
> +#define EMIF_LP_MODE_TIMEOUT_PERFORMANCE		2048
> +#define EMIF_LP_MODE_TIMEOUT_POWER			512
> +#define EMIF_LP_MODE_FREQ_THRESHOLD			400000000
> +
> +/* DDR_PHY_CTRL_1 values for EMIF4D - ATTILA PHY combination */
> +#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY		0x049FF000
> +#define EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY	0x41
> +#define EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY	0x80
> +#define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY 0xFF
> +
> +/* DDR_PHY_CTRL_1 values for EMIF4D5 INTELLIPHY combination */
> +#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY		0x0E084200
> +#define EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS	10000
> +
> +/* TEMP_ALERT_CONFIG - corresponding to temp gradient 5 C/s */
> +#define TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS		360
> +
> +#define EMIF_T_CSTA					3
> +#define EMIF_T_PDLL_UL					128
> +
> +/* External PHY control registers magic values */
> +#define EMIF_EXT_PHY_CTRL_1_VAL				0x04020080
> +#define EMIF_EXT_PHY_CTRL_5_VAL				0x04010040
> +#define EMIF_EXT_PHY_CTRL_6_VAL				0x01004010
> +#define EMIF_EXT_PHY_CTRL_7_VAL				0x00001004
> +#define EMIF_EXT_PHY_CTRL_8_VAL				0x04010040
> +#define EMIF_EXT_PHY_CTRL_9_VAL				0x01004010
> +#define EMIF_EXT_PHY_CTRL_10_VAL			0x00001004
> +#define EMIF_EXT_PHY_CTRL_11_VAL			0x00000000
> +#define EMIF_EXT_PHY_CTRL_12_VAL			0x00000000
> +#define EMIF_EXT_PHY_CTRL_13_VAL			0x00000000
> +#define EMIF_EXT_PHY_CTRL_14_VAL			0x80080080
> +#define EMIF_EXT_PHY_CTRL_15_VAL			0x00800800
> +#define EMIF_EXT_PHY_CTRL_16_VAL			0x08102040
> +#define EMIF_EXT_PHY_CTRL_17_VAL			0x00000001
> +#define EMIF_EXT_PHY_CTRL_18_VAL			0x540A8150
> +#define EMIF_EXT_PHY_CTRL_19_VAL			0xA81502A0
> +#define EMIF_EXT_PHY_CTRL_20_VAL			0x002A0540
> +#define EMIF_EXT_PHY_CTRL_21_VAL			0x00000000
> +#define EMIF_EXT_PHY_CTRL_22_VAL			0x00000000
> +#define EMIF_EXT_PHY_CTRL_23_VAL			0x00000000
> +#define EMIF_EXT_PHY_CTRL_24_VAL			0x00000077
> +
> +#define EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS	1200
> +
> +/* Registers offset */
> +#define EMIF_MODULE_ID_AND_REVISION			0x0000
> +#define EMIF_STATUS					0x0004
> +#define EMIF_SDRAM_CONFIG				0x0008
> +#define EMIF_SDRAM_CONFIG_2				0x000c
> +#define EMIF_SDRAM_REFRESH_CONTROL			0x0010
> +#define EMIF_SDRAM_REFRESH_CTRL_SHDW			0x0014
> +#define EMIF_SDRAM_TIMING_1				0x0018
> +#define EMIF_SDRAM_TIMING_1_SHDW			0x001c
> +#define EMIF_SDRAM_TIMING_2				0x0020
> +#define EMIF_SDRAM_TIMING_2_SHDW			0x0024
> +#define EMIF_SDRAM_TIMING_3				0x0028
> +#define EMIF_SDRAM_TIMING_3_SHDW			0x002c
> +#define EMIF_LPDDR2_NVM_TIMING				0x0030
> +#define EMIF_LPDDR2_NVM_TIMING_SHDW			0x0034
> +#define EMIF_POWER_MANAGEMENT_CONTROL			0x0038
> +#define EMIF_POWER_MANAGEMENT_CTRL_SHDW			0x003c
> +#define EMIF_LPDDR2_MODE_REG_DATA			0x0040
> +#define EMIF_LPDDR2_MODE_REG_CONFIG			0x0050
> +#define EMIF_OCP_CONFIG					0x0054
> +#define EMIF_OCP_CONFIG_VALUE_1				0x0058
> +#define EMIF_OCP_CONFIG_VALUE_2				0x005c
> +#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL		0x0060
> +#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT		0x0064
> +#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT	0x0068
> +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1	0x006c
> +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2	0x0070
> +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3	0x0074
> +#define EMIF_PERFORMANCE_COUNTER_1			0x0080
> +#define EMIF_PERFORMANCE_COUNTER_2			0x0084
> +#define EMIF_PERFORMANCE_COUNTER_CONFIG			0x0088
> +#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT	0x008c
> +#define EMIF_PERFORMANCE_COUNTER_TIME			0x0090
> +#define EMIF_MISC_REG					0x0094
> +#define EMIF_DLL_CALIB_CTRL				0x0098
> +#define EMIF_DLL_CALIB_CTRL_SHDW			0x009c
> +#define EMIF_END_OF_INTERRUPT				0x00a0
> +#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS		0x00a4
> +#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS		0x00a8
> +#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS		0x00ac
> +#define EMIF_LL_OCP_INTERRUPT_STATUS			0x00b0
> +#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET		0x00b4
> +#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET		0x00b8
> +#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR		0x00bc
> +#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR		0x00c0
> +#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG	0x00c8
> +#define EMIF_TEMPERATURE_ALERT_CONFIG			0x00cc
> +#define EMIF_OCP_ERROR_LOG				0x00d0
> +#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW		0x00d4
> +#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL		0x00d8
> +#define EMIF_READ_WRITE_LEVELING_CONTROL		0x00dc
> +#define EMIF_DDR_PHY_CTRL_1				0x00e4
> +#define EMIF_DDR_PHY_CTRL_1_SHDW			0x00e8
> +#define EMIF_DDR_PHY_CTRL_2				0x00ec
> +#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING	0x0100
> +#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104
> +#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108
> +#define EMIF_READ_WRITE_EXECUTION_THRESHOLD		0x0120
> +#define EMIF_COS_CONFIG					0x0124
> +#define EMIF_PHY_STATUS_1				0x0140
> +#define EMIF_PHY_STATUS_2				0x0144
> +#define EMIF_PHY_STATUS_3				0x0148
> +#define EMIF_PHY_STATUS_4				0x014c
> +#define EMIF_PHY_STATUS_5				0x0150
> +#define EMIF_PHY_STATUS_6				0x0154
> +#define EMIF_PHY_STATUS_7				0x0158
> +#define EMIF_PHY_STATUS_8				0x015c
> +#define EMIF_PHY_STATUS_9				0x0160
> +#define EMIF_PHY_STATUS_10				0x0164
> +#define EMIF_PHY_STATUS_11				0x0168
> +#define EMIF_PHY_STATUS_12				0x016c
> +#define EMIF_PHY_STATUS_13				0x0170
> +#define EMIF_PHY_STATUS_14				0x0174
> +#define EMIF_PHY_STATUS_15				0x0178
> +#define EMIF_PHY_STATUS_16				0x017c
> +#define EMIF_PHY_STATUS_17				0x0180
> +#define EMIF_PHY_STATUS_18				0x0184
> +#define EMIF_PHY_STATUS_19				0x0188
> +#define EMIF_PHY_STATUS_20				0x018c
> +#define EMIF_PHY_STATUS_21				0x0190
> +#define EMIF_EXT_PHY_CTRL_1				0x0200
> +#define EMIF_EXT_PHY_CTRL_1_SHDW			0x0204
> +#define EMIF_EXT_PHY_CTRL_2				0x0208
> +#define EMIF_EXT_PHY_CTRL_2_SHDW			0x020c
> +#define EMIF_EXT_PHY_CTRL_3				0x0210
> +#define EMIF_EXT_PHY_CTRL_3_SHDW			0x0214
> +#define EMIF_EXT_PHY_CTRL_4				0x0218
> +#define EMIF_EXT_PHY_CTRL_4_SHDW			0x021c
> +#define EMIF_EXT_PHY_CTRL_5				0x0220
> +#define EMIF_EXT_PHY_CTRL_5_SHDW			0x0224
> +#define EMIF_EXT_PHY_CTRL_6				0x0228
> +#define EMIF_EXT_PHY_CTRL_6_SHDW			0x022c
> +#define EMIF_EXT_PHY_CTRL_7				0x0230
> +#define EMIF_EXT_PHY_CTRL_7_SHDW			0x0234
> +#define EMIF_EXT_PHY_CTRL_8				0x0238
> +#define EMIF_EXT_PHY_CTRL_8_SHDW			0x023c
> +#define EMIF_EXT_PHY_CTRL_9				0x0240
> +#define EMIF_EXT_PHY_CTRL_9_SHDW			0x0244
> +#define EMIF_EXT_PHY_CTRL_10				0x0248
> +#define EMIF_EXT_PHY_CTRL_10_SHDW			0x024c
> +#define EMIF_EXT_PHY_CTRL_11				0x0250
> +#define EMIF_EXT_PHY_CTRL_11_SHDW			0x0254
> +#define EMIF_EXT_PHY_CTRL_12				0x0258
> +#define EMIF_EXT_PHY_CTRL_12_SHDW			0x025c
> +#define EMIF_EXT_PHY_CTRL_13				0x0260
> +#define EMIF_EXT_PHY_CTRL_13_SHDW			0x0264
> +#define EMIF_EXT_PHY_CTRL_14				0x0268
> +#define EMIF_EXT_PHY_CTRL_14_SHDW			0x026c
> +#define EMIF_EXT_PHY_CTRL_15				0x0270
> +#define EMIF_EXT_PHY_CTRL_15_SHDW			0x0274
> +#define EMIF_EXT_PHY_CTRL_16				0x0278
> +#define EMIF_EXT_PHY_CTRL_16_SHDW			0x027c
> +#define EMIF_EXT_PHY_CTRL_17				0x0280
> +#define EMIF_EXT_PHY_CTRL_17_SHDW			0x0284
> +#define EMIF_EXT_PHY_CTRL_18				0x0288
> +#define EMIF_EXT_PHY_CTRL_18_SHDW			0x028c
> +#define EMIF_EXT_PHY_CTRL_19				0x0290
> +#define EMIF_EXT_PHY_CTRL_19_SHDW			0x0294
> +#define EMIF_EXT_PHY_CTRL_20				0x0298
> +#define EMIF_EXT_PHY_CTRL_20_SHDW			0x029c
> +#define EMIF_EXT_PHY_CTRL_21				0x02a0
> +#define EMIF_EXT_PHY_CTRL_21_SHDW			0x02a4
> +#define EMIF_EXT_PHY_CTRL_22				0x02a8
> +#define EMIF_EXT_PHY_CTRL_22_SHDW			0x02ac
> +#define EMIF_EXT_PHY_CTRL_23				0x02b0
> +#define EMIF_EXT_PHY_CTRL_23_SHDW			0x02b4
> +#define EMIF_EXT_PHY_CTRL_24				0x02b8
> +#define EMIF_EXT_PHY_CTRL_24_SHDW			0x02bc
> +#define EMIF_EXT_PHY_CTRL_25				0x02c0
> +#define EMIF_EXT_PHY_CTRL_25_SHDW			0x02c4
> +#define EMIF_EXT_PHY_CTRL_26				0x02c8
> +#define EMIF_EXT_PHY_CTRL_26_SHDW			0x02cc
> +#define EMIF_EXT_PHY_CTRL_27				0x02d0
> +#define EMIF_EXT_PHY_CTRL_27_SHDW			0x02d4
> +#define EMIF_EXT_PHY_CTRL_28				0x02d8
> +#define EMIF_EXT_PHY_CTRL_28_SHDW			0x02dc
> +#define EMIF_EXT_PHY_CTRL_29				0x02e0
> +#define EMIF_EXT_PHY_CTRL_29_SHDW			0x02e4
> +#define EMIF_EXT_PHY_CTRL_30				0x02e8
> +#define EMIF_EXT_PHY_CTRL_30_SHDW			0x02ec
> +
> +/* Registers shifts and masks */
> +
> +/* EMIF_MODULE_ID_AND_REVISION */
> +#define SCHEME_SHIFT					30
> +#define SCHEME_MASK					(0x3 << 30)
> +#define MODULE_ID_SHIFT					16
> +#define MODULE_ID_MASK					(0xfff << 16)
> +#define RTL_VERSION_SHIFT				11
> +#define RTL_VERSION_MASK				(0x1f << 11)
> +#define MAJOR_REVISION_SHIFT				8
> +#define MAJOR_REVISION_MASK				(0x7 << 8)
> +#define MINOR_REVISION_SHIFT				0
> +#define MINOR_REVISION_MASK				(0x3f << 0)
> +
> +/* STATUS */
> +#define BE_SHIFT					31
> +#define BE_MASK						(1 << 31)
> +#define DUAL_CLK_MODE_SHIFT				30
> +#define DUAL_CLK_MODE_MASK				(1 << 30)
> +#define FAST_INIT_SHIFT					29
> +#define FAST_INIT_MASK					(1 << 29)
> +#define RDLVLGATETO_SHIFT				6
> +#define RDLVLGATETO_MASK				(1 << 6)
> +#define RDLVLTO_SHIFT					5
> +#define RDLVLTO_MASK					(1 << 5)
> +#define WRLVLTO_SHIFT					4
> +#define WRLVLTO_MASK					(1 << 4)
> +#define PHY_DLL_READY_SHIFT				2
> +#define PHY_DLL_READY_MASK				(1 << 2)
> +
> +/* SDRAM_CONFIG */
> +#define SDRAM_TYPE_SHIFT				29
> +#define SDRAM_TYPE_MASK					(0x7 << 29)
> +#define IBANK_POS_SHIFT					27
> +#define IBANK_POS_MASK					(0x3 << 27)
> +#define DDR_TERM_SHIFT					24
> +#define DDR_TERM_MASK					(0x7 << 24)
> +#define DDR2_DDQS_SHIFT					23
> +#define DDR2_DDQS_MASK					(1 << 23)
> +#define DYN_ODT_SHIFT					21
> +#define DYN_ODT_MASK					(0x3 << 21)
> +#define DDR_DISABLE_DLL_SHIFT				20
> +#define DDR_DISABLE_DLL_MASK				(1 << 20)
> +#define SDRAM_DRIVE_SHIFT				18
> +#define SDRAM_DRIVE_MASK				(0x3 << 18)
> +#define CWL_SHIFT					16
> +#define CWL_MASK					(0x3 << 16)
> +#define NARROW_MODE_SHIFT				14
> +#define NARROW_MODE_MASK				(0x3 << 14)
> +#define CL_SHIFT					10
> +#define CL_MASK						(0xf << 10)
> +#define ROWSIZE_SHIFT					7
> +#define ROWSIZE_MASK					(0x7 << 7)
> +#define IBANK_SHIFT					4
> +#define IBANK_MASK					(0x7 << 4)
> +#define EBANK_SHIFT					3
> +#define EBANK_MASK					(1 << 3)
> +#define PAGESIZE_SHIFT					0
> +#define PAGESIZE_MASK					(0x7 << 0)
> +
> +/* SDRAM_CONFIG_2 */
> +#define CS1NVMEN_SHIFT					30
> +#define CS1NVMEN_MASK					(1 << 30)
> +#define EBANK_POS_SHIFT					27
> +#define EBANK_POS_MASK					(1 << 27)
> +#define RDBNUM_SHIFT					4
> +#define RDBNUM_MASK					(0x3 << 4)
> +#define RDBSIZE_SHIFT					0
> +#define RDBSIZE_MASK					(0x7 << 0)
> +
> +/* SDRAM_REFRESH_CONTROL */
> +#define INITREF_DIS_SHIFT				31
> +#define INITREF_DIS_MASK				(1 << 31)
> +#define SRT_SHIFT					29
> +#define SRT_MASK					(1 << 29)
> +#define ASR_SHIFT					28
> +#define ASR_MASK					(1 << 28)
> +#define PASR_SHIFT					24
> +#define PASR_MASK					(0x7 << 24)
> +#define REFRESH_RATE_SHIFT				0
> +#define REFRESH_RATE_MASK				(0xffff << 0)
> +
> +/* SDRAM_TIMING_1 */
> +#define T_RTW_SHIFT					29
> +#define T_RTW_MASK					(0x7 << 29)
> +#define T_RP_SHIFT					25
> +#define T_RP_MASK					(0xf << 25)
> +#define T_RCD_SHIFT					21
> +#define T_RCD_MASK					(0xf << 21)
> +#define T_WR_SHIFT					17
> +#define T_WR_MASK					(0xf << 17)
> +#define T_RAS_SHIFT					12
> +#define T_RAS_MASK					(0x1f << 12)
> +#define T_RC_SHIFT					6
> +#define T_RC_MASK					(0x3f << 6)
> +#define T_RRD_SHIFT					3
> +#define T_RRD_MASK					(0x7 << 3)
> +#define T_WTR_SHIFT					0
> +#define T_WTR_MASK					(0x7 << 0)
> +
> +/* SDRAM_TIMING_2 */
> +#define T_XP_SHIFT					28
> +#define T_XP_MASK					(0x7 << 28)
> +#define T_ODT_SHIFT					25
> +#define T_ODT_MASK					(0x7 << 25)
> +#define T_XSNR_SHIFT					16
> +#define T_XSNR_MASK					(0x1ff << 16)
> +#define T_XSRD_SHIFT					6
> +#define T_XSRD_MASK					(0x3ff << 6)
> +#define T_RTP_SHIFT					3
> +#define T_RTP_MASK					(0x7 << 3)
> +#define T_CKE_SHIFT					0
> +#define T_CKE_MASK					(0x7 << 0)
> +
> +/* SDRAM_TIMING_3 */
> +#define T_PDLL_UL_SHIFT					28
> +#define T_PDLL_UL_MASK					(0xf << 28)
> +#define T_CSTA_SHIFT					24
> +#define T_CSTA_MASK					(0xf << 24)
> +#define T_CKESR_SHIFT					21
> +#define T_CKESR_MASK					(0x7 << 21)
> +#define ZQ_ZQCS_SHIFT					15
> +#define ZQ_ZQCS_MASK					(0x3f << 15)
> +#define T_TDQSCKMAX_SHIFT				13
> +#define T_TDQSCKMAX_MASK				(0x3 << 13)
> +#define T_RFC_SHIFT					4
> +#define T_RFC_MASK					(0x1ff << 4)
> +#define T_RAS_MAX_SHIFT					0
> +#define T_RAS_MAX_MASK					(0xf << 0)
> +
> +/* POWER_MANAGEMENT_CONTROL */
> +#define PD_TIM_SHIFT					12
> +#define PD_TIM_MASK					(0xf << 12)
> +#define DPD_EN_SHIFT					11
> +#define DPD_EN_MASK					(1 << 11)
> +#define LP_MODE_SHIFT					8
> +#define LP_MODE_MASK					(0x7 << 8)
> +#define SR_TIM_SHIFT					4
> +#define SR_TIM_MASK					(0xf << 4)
> +#define CS_TIM_SHIFT					0
> +#define CS_TIM_MASK					(0xf << 0)
> +
> +/* LPDDR2_MODE_REG_DATA */
> +#define VALUE_0_SHIFT					0
> +#define VALUE_0_MASK					(0x7f << 0)
> +
> +/* LPDDR2_MODE_REG_CONFIG */
> +#define CS_SHIFT					31
> +#define CS_MASK						(1 << 31)
> +#define REFRESH_EN_SHIFT				30
> +#define REFRESH_EN_MASK					(1 << 30)
> +#define ADDRESS_SHIFT					0
> +#define ADDRESS_MASK					(0xff << 0)
> +
> +/* OCP_CONFIG */
> +#define SYS_THRESH_MAX_SHIFT				24
> +#define SYS_THRESH_MAX_MASK				(0xf << 24)
> +#define MPU_THRESH_MAX_SHIFT				20
> +#define MPU_THRESH_MAX_MASK				(0xf << 20)
> +#define LL_THRESH_MAX_SHIFT				16
> +#define LL_THRESH_MAX_MASK				(0xf << 16)
> +
> +/* PERFORMANCE_COUNTER_1 */
> +#define COUNTER1_SHIFT					0
> +#define COUNTER1_MASK					(0xffffffff << 0)
> +
> +/* PERFORMANCE_COUNTER_2 */
> +#define COUNTER2_SHIFT					0
> +#define COUNTER2_MASK					(0xffffffff << 0)
> +
> +/* PERFORMANCE_COUNTER_CONFIG */
> +#define CNTR2_MCONNID_EN_SHIFT				31
> +#define CNTR2_MCONNID_EN_MASK				(1 << 31)
> +#define CNTR2_REGION_EN_SHIFT				30
> +#define CNTR2_REGION_EN_MASK				(1 << 30)
> +#define CNTR2_CFG_SHIFT					16
> +#define CNTR2_CFG_MASK					(0xf << 16)
> +#define CNTR1_MCONNID_EN_SHIFT				15
> +#define CNTR1_MCONNID_EN_MASK				(1 << 15)
> +#define CNTR1_REGION_EN_SHIFT				14
> +#define CNTR1_REGION_EN_MASK				(1 << 14)
> +#define CNTR1_CFG_SHIFT					0
> +#define CNTR1_CFG_MASK					(0xf << 0)
> +
> +/* PERFORMANCE_COUNTER_MASTER_REGION_SELECT */
> +#define MCONNID2_SHIFT					24
> +#define MCONNID2_MASK					(0xff << 24)
> +#define REGION_SEL2_SHIFT				16
> +#define REGION_SEL2_MASK				(0x3 << 16)
> +#define MCONNID1_SHIFT					8
> +#define MCONNID1_MASK					(0xff << 8)
> +#define REGION_SEL1_SHIFT				0
> +#define REGION_SEL1_MASK				(0x3 << 0)
> +
> +/* PERFORMANCE_COUNTER_TIME */
> +#define TOTAL_TIME_SHIFT				0
> +#define TOTAL_TIME_MASK					(0xffffffff << 0)
> +
> +/* DLL_CALIB_CTRL */
> +#define ACK_WAIT_SHIFT					16
> +#define ACK_WAIT_MASK					(0xf << 16)
> +#define DLL_CALIB_INTERVAL_SHIFT			0
> +#define DLL_CALIB_INTERVAL_MASK				(0x1ff << 0)
> +
> +/* END_OF_INTERRUPT */
> +#define EOI_SHIFT					0
> +#define EOI_MASK					(1 << 0)
> +
> +/* SYSTEM_OCP_INTERRUPT_RAW_STATUS */
> +#define DNV_SYS_SHIFT					2
> +#define DNV_SYS_MASK					(1 << 2)
> +#define TA_SYS_SHIFT					1
> +#define TA_SYS_MASK					(1 << 1)
> +#define ERR_SYS_SHIFT					0
> +#define ERR_SYS_MASK					(1 << 0)
> +
> +/* LOW_LATENCY_OCP_INTERRUPT_RAW_STATUS */
> +#define DNV_LL_SHIFT					2
> +#define DNV_LL_MASK					(1 << 2)
> +#define TA_LL_SHIFT					1
> +#define TA_LL_MASK					(1 << 1)
> +#define ERR_LL_SHIFT					0
> +#define ERR_LL_MASK					(1 << 0)
> +
> +/* SYSTEM_OCP_INTERRUPT_ENABLE_SET */
> +#define EN_DNV_SYS_SHIFT				2
> +#define EN_DNV_SYS_MASK					(1 << 2)
> +#define EN_TA_SYS_SHIFT					1
> +#define EN_TA_SYS_MASK					(1 << 1)
> +#define EN_ERR_SYS_SHIFT					0
> +#define EN_ERR_SYS_MASK					(1 << 0)
> +
> +/* LOW_LATENCY_OCP_INTERRUPT_ENABLE_SET */
> +#define EN_DNV_LL_SHIFT					2
> +#define EN_DNV_LL_MASK					(1 << 2)
> +#define EN_TA_LL_SHIFT					1
> +#define EN_TA_LL_MASK					(1 << 1)
> +#define EN_ERR_LL_SHIFT					0
> +#define EN_ERR_LL_MASK					(1 << 0)
> +
> +/* SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG */
> +#define ZQ_CS1EN_SHIFT					31
> +#define ZQ_CS1EN_MASK					(1 << 31)
> +#define ZQ_CS0EN_SHIFT					30
> +#define ZQ_CS0EN_MASK					(1 << 30)
> +#define ZQ_DUALCALEN_SHIFT				29
> +#define ZQ_DUALCALEN_MASK				(1 << 29)
> +#define ZQ_SFEXITEN_SHIFT				28
> +#define ZQ_SFEXITEN_MASK				(1 << 28)
> +#define ZQ_ZQINIT_MULT_SHIFT				18
> +#define ZQ_ZQINIT_MULT_MASK				(0x3 << 18)
> +#define ZQ_ZQCL_MULT_SHIFT				16
> +#define ZQ_ZQCL_MULT_MASK				(0x3 << 16)
> +#define ZQ_REFINTERVAL_SHIFT				0
> +#define ZQ_REFINTERVAL_MASK				(0xffff << 0)
> +
> +/* TEMPERATURE_ALERT_CONFIG */
> +#define TA_CS1EN_SHIFT					31
> +#define TA_CS1EN_MASK					(1 << 31)
> +#define TA_CS0EN_SHIFT					30
> +#define TA_CS0EN_MASK					(1 << 30)
> +#define TA_SFEXITEN_SHIFT				28
> +#define TA_SFEXITEN_MASK				(1 << 28)
> +#define TA_DEVWDT_SHIFT					26
> +#define TA_DEVWDT_MASK					(0x3 << 26)
> +#define TA_DEVCNT_SHIFT					24
> +#define TA_DEVCNT_MASK					(0x3 << 24)
> +#define TA_REFINTERVAL_SHIFT				0
> +#define TA_REFINTERVAL_MASK				(0x3fffff << 0)
> +
> +/* OCP_ERROR_LOG */
> +#define MADDRSPACE_SHIFT				14
> +#define MADDRSPACE_MASK					(0x3 << 14)
> +#define MBURSTSEQ_SHIFT					11
> +#define MBURSTSEQ_MASK					(0x7 << 11)
> +#define MCMD_SHIFT					8
> +#define MCMD_MASK					(0x7 << 8)
> +#define MCONNID_SHIFT					0
> +#define MCONNID_MASK					(0xff << 0)
> +
> +/* DDR_PHY_CTRL_1 - EMIF4D */
> +#define DLL_SLAVE_DLY_CTRL_SHIFT_4D			4
> +#define DLL_SLAVE_DLY_CTRL_MASK_4D			(0xFF << 4)
> +#define READ_LATENCY_SHIFT_4D				0
> +#define READ_LATENCY_MASK_4D				(0xf << 0)
> +
> +/* DDR_PHY_CTRL_1 - EMIF4D5 */
> +#define DLL_HALF_DELAY_SHIFT_4D5			21
> +#define DLL_HALF_DELAY_MASK_4D5				(1 << 21)
> +#define READ_LATENCY_SHIFT_4D5				0
> +#define READ_LATENCY_MASK_4D5				(0x1f << 0)
> +
> +/* DDR_PHY_CTRL_1_SHDW */
> +#define DDR_PHY_CTRL_1_SHDW_SHIFT			5
> +#define DDR_PHY_CTRL_1_SHDW_MASK			(0x7ffffff << 5)
> +#define READ_LATENCY_SHDW_SHIFT				0
> +#define READ_LATENCY_SHDW_MASK				(0x1f << 0)
> +
> +#endif /* __TI_EMIF_H */
> 


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 1/9] memory: emif: Move EMIF register defines to include/linux/
@ 2013-08-08 13:35     ` Santosh Shilimkar
  0 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 13:35 UTC (permalink / raw)
  To: linux-arm-kernel

(You have not CC'ed Greg, Looping him)

On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> OMAP4 and AM33XX share the same EMIF controller IP. Although there
> are significant differences in the IP integration due to which
> AM33XX can't reuse the EMIF driver DVFS similar to OMAP4,
> it can definitely benefit by reusing the EMIF related macros
> defined in drivers/memory/emif.h.
> 
> In the current OMAP PM framework the PM code resides under
> arch/arm/mach-omap2/. To enable reuse of the register defines move
> the register defines in the emif header file to include/linux so that
> both the EMIF driver and the AM33XX PM code can benefit.
> 
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Benoit Cousson <benoit.cousson@linaro.org>
> Cc: Aneesh V <aneesh@ti.com>
> ---
>  drivers/memory/emif.h   |  543 +--------------------------------------------
>  include/linux/ti_emif.h |  558 +++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 559 insertions(+), 542 deletions(-)
>  create mode 100644 include/linux/ti_emif.h
> 
For file movement or some part of file movement, while formating
patch, use "git format-patch -C" so that only delta change will
appear in the patch.

The patch as such is fine by me.
Acked-by: Santosh Shililmar <santosh.shilimkar@ti.com>

Greg,
Your ack is needed on this patch so that it can go
along with the series. Subsequent patch from this series
use the register defines from this patch.

> diff --git a/drivers/memory/emif.h b/drivers/memory/emif.h
> index bfe08ba..8214f07 100644
> --- a/drivers/memory/emif.h
> +++ b/drivers/memory/emif.h
> @@ -12,548 +12,7 @@
>  #ifndef __EMIF_H
>  #define __EMIF_H
>  
> -/*
> - * Maximum number of different frequencies supported by EMIF driver
> - * Determines the number of entries in the pointer array for register
> - * cache
> - */
> -#define EMIF_MAX_NUM_FREQUENCIES			6
> -
> -/* State of the core voltage */
> -#define DDR_VOLTAGE_STABLE				0
> -#define DDR_VOLTAGE_RAMPING				1
> -
> -/* Defines for timing De-rating */
> -#define EMIF_NORMAL_TIMINGS				0
> -#define EMIF_DERATED_TIMINGS				1
> -
> -/* Length of the forced read idle period in terms of cycles */
> -#define EMIF_READ_IDLE_LEN_VAL				5
> -
> -/*
> - * forced read idle interval to be used when voltage
> - * is changed as part of DVFS/DPS - 1ms
> - */
> -#define READ_IDLE_INTERVAL_DVFS				(1*1000000)
> -
> -/*
> - * Forced read idle interval to be used when voltage is stable
> - * 50us - or maximum value will do
> - */
> -#define READ_IDLE_INTERVAL_NORMAL			(50*1000000)
> -
> -/* DLL calibration interval when voltage is NOT stable - 1us */
> -#define DLL_CALIB_INTERVAL_DVFS				(1*1000000)
> -
> -#define DLL_CALIB_ACK_WAIT_VAL				5
> -
> -/* Interval between ZQCS commands - hw team recommended value */
> -#define EMIF_ZQCS_INTERVAL_US				(50*1000)
> -/* Enable ZQ Calibration on exiting Self-refresh */
> -#define ZQ_SFEXITEN_ENABLE				1
> -/*
> - * ZQ Calibration simultaneously on both chip-selects:
> - * Needs one calibration resistor per CS
> - */
> -#define	ZQ_DUALCALEN_DISABLE				0
> -#define	ZQ_DUALCALEN_ENABLE				1
> -
> -#define T_ZQCS_DEFAULT_NS				90
> -#define T_ZQCL_DEFAULT_NS				360
> -#define T_ZQINIT_DEFAULT_NS				1000
> -
> -/* DPD_EN */
> -#define DPD_DISABLE					0
> -#define DPD_ENABLE					1
> -
> -/*
> - * Default values for the low-power entry to be used if not provided by user.
> - * OMAP4/5 has a hw bug(i735) due to which this value can not be less than 512
> - * Timeout values are in DDR clock 'cycles' and frequency threshold in Hz
> - */
> -#define EMIF_LP_MODE_TIMEOUT_PERFORMANCE		2048
> -#define EMIF_LP_MODE_TIMEOUT_POWER			512
> -#define EMIF_LP_MODE_FREQ_THRESHOLD			400000000
> -
> -/* DDR_PHY_CTRL_1 values for EMIF4D - ATTILA PHY combination */
> -#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY		0x049FF000
> -#define EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY	0x41
> -#define EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY	0x80
> -#define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY 0xFF
> -
> -/* DDR_PHY_CTRL_1 values for EMIF4D5 INTELLIPHY combination */
> -#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY		0x0E084200
> -#define EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS	10000
> -
> -/* TEMP_ALERT_CONFIG - corresponding to temp gradient 5 C/s */
> -#define TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS		360
> -
> -#define EMIF_T_CSTA					3
> -#define EMIF_T_PDLL_UL					128
> -
> -/* External PHY control registers magic values */
> -#define EMIF_EXT_PHY_CTRL_1_VAL				0x04020080
> -#define EMIF_EXT_PHY_CTRL_5_VAL				0x04010040
> -#define EMIF_EXT_PHY_CTRL_6_VAL				0x01004010
> -#define EMIF_EXT_PHY_CTRL_7_VAL				0x00001004
> -#define EMIF_EXT_PHY_CTRL_8_VAL				0x04010040
> -#define EMIF_EXT_PHY_CTRL_9_VAL				0x01004010
> -#define EMIF_EXT_PHY_CTRL_10_VAL			0x00001004
> -#define EMIF_EXT_PHY_CTRL_11_VAL			0x00000000
> -#define EMIF_EXT_PHY_CTRL_12_VAL			0x00000000
> -#define EMIF_EXT_PHY_CTRL_13_VAL			0x00000000
> -#define EMIF_EXT_PHY_CTRL_14_VAL			0x80080080
> -#define EMIF_EXT_PHY_CTRL_15_VAL			0x00800800
> -#define EMIF_EXT_PHY_CTRL_16_VAL			0x08102040
> -#define EMIF_EXT_PHY_CTRL_17_VAL			0x00000001
> -#define EMIF_EXT_PHY_CTRL_18_VAL			0x540A8150
> -#define EMIF_EXT_PHY_CTRL_19_VAL			0xA81502A0
> -#define EMIF_EXT_PHY_CTRL_20_VAL			0x002A0540
> -#define EMIF_EXT_PHY_CTRL_21_VAL			0x00000000
> -#define EMIF_EXT_PHY_CTRL_22_VAL			0x00000000
> -#define EMIF_EXT_PHY_CTRL_23_VAL			0x00000000
> -#define EMIF_EXT_PHY_CTRL_24_VAL			0x00000077
> -
> -#define EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS	1200
> -
> -/* Registers offset */
> -#define EMIF_MODULE_ID_AND_REVISION			0x0000
> -#define EMIF_STATUS					0x0004
> -#define EMIF_SDRAM_CONFIG				0x0008
> -#define EMIF_SDRAM_CONFIG_2				0x000c
> -#define EMIF_SDRAM_REFRESH_CONTROL			0x0010
> -#define EMIF_SDRAM_REFRESH_CTRL_SHDW			0x0014
> -#define EMIF_SDRAM_TIMING_1				0x0018
> -#define EMIF_SDRAM_TIMING_1_SHDW			0x001c
> -#define EMIF_SDRAM_TIMING_2				0x0020
> -#define EMIF_SDRAM_TIMING_2_SHDW			0x0024
> -#define EMIF_SDRAM_TIMING_3				0x0028
> -#define EMIF_SDRAM_TIMING_3_SHDW			0x002c
> -#define EMIF_LPDDR2_NVM_TIMING				0x0030
> -#define EMIF_LPDDR2_NVM_TIMING_SHDW			0x0034
> -#define EMIF_POWER_MANAGEMENT_CONTROL			0x0038
> -#define EMIF_POWER_MANAGEMENT_CTRL_SHDW			0x003c
> -#define EMIF_LPDDR2_MODE_REG_DATA			0x0040
> -#define EMIF_LPDDR2_MODE_REG_CONFIG			0x0050
> -#define EMIF_OCP_CONFIG					0x0054
> -#define EMIF_OCP_CONFIG_VALUE_1				0x0058
> -#define EMIF_OCP_CONFIG_VALUE_2				0x005c
> -#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL		0x0060
> -#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT		0x0064
> -#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT	0x0068
> -#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1	0x006c
> -#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2	0x0070
> -#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3	0x0074
> -#define EMIF_PERFORMANCE_COUNTER_1			0x0080
> -#define EMIF_PERFORMANCE_COUNTER_2			0x0084
> -#define EMIF_PERFORMANCE_COUNTER_CONFIG			0x0088
> -#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT	0x008c
> -#define EMIF_PERFORMANCE_COUNTER_TIME			0x0090
> -#define EMIF_MISC_REG					0x0094
> -#define EMIF_DLL_CALIB_CTRL				0x0098
> -#define EMIF_DLL_CALIB_CTRL_SHDW			0x009c
> -#define EMIF_END_OF_INTERRUPT				0x00a0
> -#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS		0x00a4
> -#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS		0x00a8
> -#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS		0x00ac
> -#define EMIF_LL_OCP_INTERRUPT_STATUS			0x00b0
> -#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET		0x00b4
> -#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET		0x00b8
> -#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR		0x00bc
> -#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR		0x00c0
> -#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG	0x00c8
> -#define EMIF_TEMPERATURE_ALERT_CONFIG			0x00cc
> -#define EMIF_OCP_ERROR_LOG				0x00d0
> -#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW		0x00d4
> -#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL		0x00d8
> -#define EMIF_READ_WRITE_LEVELING_CONTROL		0x00dc
> -#define EMIF_DDR_PHY_CTRL_1				0x00e4
> -#define EMIF_DDR_PHY_CTRL_1_SHDW			0x00e8
> -#define EMIF_DDR_PHY_CTRL_2				0x00ec
> -#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING	0x0100
> -#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104
> -#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108
> -#define EMIF_READ_WRITE_EXECUTION_THRESHOLD		0x0120
> -#define EMIF_COS_CONFIG					0x0124
> -#define EMIF_PHY_STATUS_1				0x0140
> -#define EMIF_PHY_STATUS_2				0x0144
> -#define EMIF_PHY_STATUS_3				0x0148
> -#define EMIF_PHY_STATUS_4				0x014c
> -#define EMIF_PHY_STATUS_5				0x0150
> -#define EMIF_PHY_STATUS_6				0x0154
> -#define EMIF_PHY_STATUS_7				0x0158
> -#define EMIF_PHY_STATUS_8				0x015c
> -#define EMIF_PHY_STATUS_9				0x0160
> -#define EMIF_PHY_STATUS_10				0x0164
> -#define EMIF_PHY_STATUS_11				0x0168
> -#define EMIF_PHY_STATUS_12				0x016c
> -#define EMIF_PHY_STATUS_13				0x0170
> -#define EMIF_PHY_STATUS_14				0x0174
> -#define EMIF_PHY_STATUS_15				0x0178
> -#define EMIF_PHY_STATUS_16				0x017c
> -#define EMIF_PHY_STATUS_17				0x0180
> -#define EMIF_PHY_STATUS_18				0x0184
> -#define EMIF_PHY_STATUS_19				0x0188
> -#define EMIF_PHY_STATUS_20				0x018c
> -#define EMIF_PHY_STATUS_21				0x0190
> -#define EMIF_EXT_PHY_CTRL_1				0x0200
> -#define EMIF_EXT_PHY_CTRL_1_SHDW			0x0204
> -#define EMIF_EXT_PHY_CTRL_2				0x0208
> -#define EMIF_EXT_PHY_CTRL_2_SHDW			0x020c
> -#define EMIF_EXT_PHY_CTRL_3				0x0210
> -#define EMIF_EXT_PHY_CTRL_3_SHDW			0x0214
> -#define EMIF_EXT_PHY_CTRL_4				0x0218
> -#define EMIF_EXT_PHY_CTRL_4_SHDW			0x021c
> -#define EMIF_EXT_PHY_CTRL_5				0x0220
> -#define EMIF_EXT_PHY_CTRL_5_SHDW			0x0224
> -#define EMIF_EXT_PHY_CTRL_6				0x0228
> -#define EMIF_EXT_PHY_CTRL_6_SHDW			0x022c
> -#define EMIF_EXT_PHY_CTRL_7				0x0230
> -#define EMIF_EXT_PHY_CTRL_7_SHDW			0x0234
> -#define EMIF_EXT_PHY_CTRL_8				0x0238
> -#define EMIF_EXT_PHY_CTRL_8_SHDW			0x023c
> -#define EMIF_EXT_PHY_CTRL_9				0x0240
> -#define EMIF_EXT_PHY_CTRL_9_SHDW			0x0244
> -#define EMIF_EXT_PHY_CTRL_10				0x0248
> -#define EMIF_EXT_PHY_CTRL_10_SHDW			0x024c
> -#define EMIF_EXT_PHY_CTRL_11				0x0250
> -#define EMIF_EXT_PHY_CTRL_11_SHDW			0x0254
> -#define EMIF_EXT_PHY_CTRL_12				0x0258
> -#define EMIF_EXT_PHY_CTRL_12_SHDW			0x025c
> -#define EMIF_EXT_PHY_CTRL_13				0x0260
> -#define EMIF_EXT_PHY_CTRL_13_SHDW			0x0264
> -#define EMIF_EXT_PHY_CTRL_14				0x0268
> -#define EMIF_EXT_PHY_CTRL_14_SHDW			0x026c
> -#define EMIF_EXT_PHY_CTRL_15				0x0270
> -#define EMIF_EXT_PHY_CTRL_15_SHDW			0x0274
> -#define EMIF_EXT_PHY_CTRL_16				0x0278
> -#define EMIF_EXT_PHY_CTRL_16_SHDW			0x027c
> -#define EMIF_EXT_PHY_CTRL_17				0x0280
> -#define EMIF_EXT_PHY_CTRL_17_SHDW			0x0284
> -#define EMIF_EXT_PHY_CTRL_18				0x0288
> -#define EMIF_EXT_PHY_CTRL_18_SHDW			0x028c
> -#define EMIF_EXT_PHY_CTRL_19				0x0290
> -#define EMIF_EXT_PHY_CTRL_19_SHDW			0x0294
> -#define EMIF_EXT_PHY_CTRL_20				0x0298
> -#define EMIF_EXT_PHY_CTRL_20_SHDW			0x029c
> -#define EMIF_EXT_PHY_CTRL_21				0x02a0
> -#define EMIF_EXT_PHY_CTRL_21_SHDW			0x02a4
> -#define EMIF_EXT_PHY_CTRL_22				0x02a8
> -#define EMIF_EXT_PHY_CTRL_22_SHDW			0x02ac
> -#define EMIF_EXT_PHY_CTRL_23				0x02b0
> -#define EMIF_EXT_PHY_CTRL_23_SHDW			0x02b4
> -#define EMIF_EXT_PHY_CTRL_24				0x02b8
> -#define EMIF_EXT_PHY_CTRL_24_SHDW			0x02bc
> -#define EMIF_EXT_PHY_CTRL_25				0x02c0
> -#define EMIF_EXT_PHY_CTRL_25_SHDW			0x02c4
> -#define EMIF_EXT_PHY_CTRL_26				0x02c8
> -#define EMIF_EXT_PHY_CTRL_26_SHDW			0x02cc
> -#define EMIF_EXT_PHY_CTRL_27				0x02d0
> -#define EMIF_EXT_PHY_CTRL_27_SHDW			0x02d4
> -#define EMIF_EXT_PHY_CTRL_28				0x02d8
> -#define EMIF_EXT_PHY_CTRL_28_SHDW			0x02dc
> -#define EMIF_EXT_PHY_CTRL_29				0x02e0
> -#define EMIF_EXT_PHY_CTRL_29_SHDW			0x02e4
> -#define EMIF_EXT_PHY_CTRL_30				0x02e8
> -#define EMIF_EXT_PHY_CTRL_30_SHDW			0x02ec
> -
> -/* Registers shifts and masks */
> -
> -/* EMIF_MODULE_ID_AND_REVISION */
> -#define SCHEME_SHIFT					30
> -#define SCHEME_MASK					(0x3 << 30)
> -#define MODULE_ID_SHIFT					16
> -#define MODULE_ID_MASK					(0xfff << 16)
> -#define RTL_VERSION_SHIFT				11
> -#define RTL_VERSION_MASK				(0x1f << 11)
> -#define MAJOR_REVISION_SHIFT				8
> -#define MAJOR_REVISION_MASK				(0x7 << 8)
> -#define MINOR_REVISION_SHIFT				0
> -#define MINOR_REVISION_MASK				(0x3f << 0)
> -
> -/* STATUS */
> -#define BE_SHIFT					31
> -#define BE_MASK						(1 << 31)
> -#define DUAL_CLK_MODE_SHIFT				30
> -#define DUAL_CLK_MODE_MASK				(1 << 30)
> -#define FAST_INIT_SHIFT					29
> -#define FAST_INIT_MASK					(1 << 29)
> -#define RDLVLGATETO_SHIFT				6
> -#define RDLVLGATETO_MASK				(1 << 6)
> -#define RDLVLTO_SHIFT					5
> -#define RDLVLTO_MASK					(1 << 5)
> -#define WRLVLTO_SHIFT					4
> -#define WRLVLTO_MASK					(1 << 4)
> -#define PHY_DLL_READY_SHIFT				2
> -#define PHY_DLL_READY_MASK				(1 << 2)
> -
> -/* SDRAM_CONFIG */
> -#define SDRAM_TYPE_SHIFT				29
> -#define SDRAM_TYPE_MASK					(0x7 << 29)
> -#define IBANK_POS_SHIFT					27
> -#define IBANK_POS_MASK					(0x3 << 27)
> -#define DDR_TERM_SHIFT					24
> -#define DDR_TERM_MASK					(0x7 << 24)
> -#define DDR2_DDQS_SHIFT					23
> -#define DDR2_DDQS_MASK					(1 << 23)
> -#define DYN_ODT_SHIFT					21
> -#define DYN_ODT_MASK					(0x3 << 21)
> -#define DDR_DISABLE_DLL_SHIFT				20
> -#define DDR_DISABLE_DLL_MASK				(1 << 20)
> -#define SDRAM_DRIVE_SHIFT				18
> -#define SDRAM_DRIVE_MASK				(0x3 << 18)
> -#define CWL_SHIFT					16
> -#define CWL_MASK					(0x3 << 16)
> -#define NARROW_MODE_SHIFT				14
> -#define NARROW_MODE_MASK				(0x3 << 14)
> -#define CL_SHIFT					10
> -#define CL_MASK						(0xf << 10)
> -#define ROWSIZE_SHIFT					7
> -#define ROWSIZE_MASK					(0x7 << 7)
> -#define IBANK_SHIFT					4
> -#define IBANK_MASK					(0x7 << 4)
> -#define EBANK_SHIFT					3
> -#define EBANK_MASK					(1 << 3)
> -#define PAGESIZE_SHIFT					0
> -#define PAGESIZE_MASK					(0x7 << 0)
> -
> -/* SDRAM_CONFIG_2 */
> -#define CS1NVMEN_SHIFT					30
> -#define CS1NVMEN_MASK					(1 << 30)
> -#define EBANK_POS_SHIFT					27
> -#define EBANK_POS_MASK					(1 << 27)
> -#define RDBNUM_SHIFT					4
> -#define RDBNUM_MASK					(0x3 << 4)
> -#define RDBSIZE_SHIFT					0
> -#define RDBSIZE_MASK					(0x7 << 0)
> -
> -/* SDRAM_REFRESH_CONTROL */
> -#define INITREF_DIS_SHIFT				31
> -#define INITREF_DIS_MASK				(1 << 31)
> -#define SRT_SHIFT					29
> -#define SRT_MASK					(1 << 29)
> -#define ASR_SHIFT					28
> -#define ASR_MASK					(1 << 28)
> -#define PASR_SHIFT					24
> -#define PASR_MASK					(0x7 << 24)
> -#define REFRESH_RATE_SHIFT				0
> -#define REFRESH_RATE_MASK				(0xffff << 0)
> -
> -/* SDRAM_TIMING_1 */
> -#define T_RTW_SHIFT					29
> -#define T_RTW_MASK					(0x7 << 29)
> -#define T_RP_SHIFT					25
> -#define T_RP_MASK					(0xf << 25)
> -#define T_RCD_SHIFT					21
> -#define T_RCD_MASK					(0xf << 21)
> -#define T_WR_SHIFT					17
> -#define T_WR_MASK					(0xf << 17)
> -#define T_RAS_SHIFT					12
> -#define T_RAS_MASK					(0x1f << 12)
> -#define T_RC_SHIFT					6
> -#define T_RC_MASK					(0x3f << 6)
> -#define T_RRD_SHIFT					3
> -#define T_RRD_MASK					(0x7 << 3)
> -#define T_WTR_SHIFT					0
> -#define T_WTR_MASK					(0x7 << 0)
> -
> -/* SDRAM_TIMING_2 */
> -#define T_XP_SHIFT					28
> -#define T_XP_MASK					(0x7 << 28)
> -#define T_ODT_SHIFT					25
> -#define T_ODT_MASK					(0x7 << 25)
> -#define T_XSNR_SHIFT					16
> -#define T_XSNR_MASK					(0x1ff << 16)
> -#define T_XSRD_SHIFT					6
> -#define T_XSRD_MASK					(0x3ff << 6)
> -#define T_RTP_SHIFT					3
> -#define T_RTP_MASK					(0x7 << 3)
> -#define T_CKE_SHIFT					0
> -#define T_CKE_MASK					(0x7 << 0)
> -
> -/* SDRAM_TIMING_3 */
> -#define T_PDLL_UL_SHIFT					28
> -#define T_PDLL_UL_MASK					(0xf << 28)
> -#define T_CSTA_SHIFT					24
> -#define T_CSTA_MASK					(0xf << 24)
> -#define T_CKESR_SHIFT					21
> -#define T_CKESR_MASK					(0x7 << 21)
> -#define ZQ_ZQCS_SHIFT					15
> -#define ZQ_ZQCS_MASK					(0x3f << 15)
> -#define T_TDQSCKMAX_SHIFT				13
> -#define T_TDQSCKMAX_MASK				(0x3 << 13)
> -#define T_RFC_SHIFT					4
> -#define T_RFC_MASK					(0x1ff << 4)
> -#define T_RAS_MAX_SHIFT					0
> -#define T_RAS_MAX_MASK					(0xf << 0)
> -
> -/* POWER_MANAGEMENT_CONTROL */
> -#define PD_TIM_SHIFT					12
> -#define PD_TIM_MASK					(0xf << 12)
> -#define DPD_EN_SHIFT					11
> -#define DPD_EN_MASK					(1 << 11)
> -#define LP_MODE_SHIFT					8
> -#define LP_MODE_MASK					(0x7 << 8)
> -#define SR_TIM_SHIFT					4
> -#define SR_TIM_MASK					(0xf << 4)
> -#define CS_TIM_SHIFT					0
> -#define CS_TIM_MASK					(0xf << 0)
> -
> -/* LPDDR2_MODE_REG_DATA */
> -#define VALUE_0_SHIFT					0
> -#define VALUE_0_MASK					(0x7f << 0)
> -
> -/* LPDDR2_MODE_REG_CONFIG */
> -#define CS_SHIFT					31
> -#define CS_MASK						(1 << 31)
> -#define REFRESH_EN_SHIFT				30
> -#define REFRESH_EN_MASK					(1 << 30)
> -#define ADDRESS_SHIFT					0
> -#define ADDRESS_MASK					(0xff << 0)
> -
> -/* OCP_CONFIG */
> -#define SYS_THRESH_MAX_SHIFT				24
> -#define SYS_THRESH_MAX_MASK				(0xf << 24)
> -#define MPU_THRESH_MAX_SHIFT				20
> -#define MPU_THRESH_MAX_MASK				(0xf << 20)
> -#define LL_THRESH_MAX_SHIFT				16
> -#define LL_THRESH_MAX_MASK				(0xf << 16)
> -
> -/* PERFORMANCE_COUNTER_1 */
> -#define COUNTER1_SHIFT					0
> -#define COUNTER1_MASK					(0xffffffff << 0)
> -
> -/* PERFORMANCE_COUNTER_2 */
> -#define COUNTER2_SHIFT					0
> -#define COUNTER2_MASK					(0xffffffff << 0)
> -
> -/* PERFORMANCE_COUNTER_CONFIG */
> -#define CNTR2_MCONNID_EN_SHIFT				31
> -#define CNTR2_MCONNID_EN_MASK				(1 << 31)
> -#define CNTR2_REGION_EN_SHIFT				30
> -#define CNTR2_REGION_EN_MASK				(1 << 30)
> -#define CNTR2_CFG_SHIFT					16
> -#define CNTR2_CFG_MASK					(0xf << 16)
> -#define CNTR1_MCONNID_EN_SHIFT				15
> -#define CNTR1_MCONNID_EN_MASK				(1 << 15)
> -#define CNTR1_REGION_EN_SHIFT				14
> -#define CNTR1_REGION_EN_MASK				(1 << 14)
> -#define CNTR1_CFG_SHIFT					0
> -#define CNTR1_CFG_MASK					(0xf << 0)
> -
> -/* PERFORMANCE_COUNTER_MASTER_REGION_SELECT */
> -#define MCONNID2_SHIFT					24
> -#define MCONNID2_MASK					(0xff << 24)
> -#define REGION_SEL2_SHIFT				16
> -#define REGION_SEL2_MASK				(0x3 << 16)
> -#define MCONNID1_SHIFT					8
> -#define MCONNID1_MASK					(0xff << 8)
> -#define REGION_SEL1_SHIFT				0
> -#define REGION_SEL1_MASK				(0x3 << 0)
> -
> -/* PERFORMANCE_COUNTER_TIME */
> -#define TOTAL_TIME_SHIFT				0
> -#define TOTAL_TIME_MASK					(0xffffffff << 0)
> -
> -/* DLL_CALIB_CTRL */
> -#define ACK_WAIT_SHIFT					16
> -#define ACK_WAIT_MASK					(0xf << 16)
> -#define DLL_CALIB_INTERVAL_SHIFT			0
> -#define DLL_CALIB_INTERVAL_MASK				(0x1ff << 0)
> -
> -/* END_OF_INTERRUPT */
> -#define EOI_SHIFT					0
> -#define EOI_MASK					(1 << 0)
> -
> -/* SYSTEM_OCP_INTERRUPT_RAW_STATUS */
> -#define DNV_SYS_SHIFT					2
> -#define DNV_SYS_MASK					(1 << 2)
> -#define TA_SYS_SHIFT					1
> -#define TA_SYS_MASK					(1 << 1)
> -#define ERR_SYS_SHIFT					0
> -#define ERR_SYS_MASK					(1 << 0)
> -
> -/* LOW_LATENCY_OCP_INTERRUPT_RAW_STATUS */
> -#define DNV_LL_SHIFT					2
> -#define DNV_LL_MASK					(1 << 2)
> -#define TA_LL_SHIFT					1
> -#define TA_LL_MASK					(1 << 1)
> -#define ERR_LL_SHIFT					0
> -#define ERR_LL_MASK					(1 << 0)
> -
> -/* SYSTEM_OCP_INTERRUPT_ENABLE_SET */
> -#define EN_DNV_SYS_SHIFT				2
> -#define EN_DNV_SYS_MASK					(1 << 2)
> -#define EN_TA_SYS_SHIFT					1
> -#define EN_TA_SYS_MASK					(1 << 1)
> -#define EN_ERR_SYS_SHIFT					0
> -#define EN_ERR_SYS_MASK					(1 << 0)
> -
> -/* LOW_LATENCY_OCP_INTERRUPT_ENABLE_SET */
> -#define EN_DNV_LL_SHIFT					2
> -#define EN_DNV_LL_MASK					(1 << 2)
> -#define EN_TA_LL_SHIFT					1
> -#define EN_TA_LL_MASK					(1 << 1)
> -#define EN_ERR_LL_SHIFT					0
> -#define EN_ERR_LL_MASK					(1 << 0)
> -
> -/* SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG */
> -#define ZQ_CS1EN_SHIFT					31
> -#define ZQ_CS1EN_MASK					(1 << 31)
> -#define ZQ_CS0EN_SHIFT					30
> -#define ZQ_CS0EN_MASK					(1 << 30)
> -#define ZQ_DUALCALEN_SHIFT				29
> -#define ZQ_DUALCALEN_MASK				(1 << 29)
> -#define ZQ_SFEXITEN_SHIFT				28
> -#define ZQ_SFEXITEN_MASK				(1 << 28)
> -#define ZQ_ZQINIT_MULT_SHIFT				18
> -#define ZQ_ZQINIT_MULT_MASK				(0x3 << 18)
> -#define ZQ_ZQCL_MULT_SHIFT				16
> -#define ZQ_ZQCL_MULT_MASK				(0x3 << 16)
> -#define ZQ_REFINTERVAL_SHIFT				0
> -#define ZQ_REFINTERVAL_MASK				(0xffff << 0)
> -
> -/* TEMPERATURE_ALERT_CONFIG */
> -#define TA_CS1EN_SHIFT					31
> -#define TA_CS1EN_MASK					(1 << 31)
> -#define TA_CS0EN_SHIFT					30
> -#define TA_CS0EN_MASK					(1 << 30)
> -#define TA_SFEXITEN_SHIFT				28
> -#define TA_SFEXITEN_MASK				(1 << 28)
> -#define TA_DEVWDT_SHIFT					26
> -#define TA_DEVWDT_MASK					(0x3 << 26)
> -#define TA_DEVCNT_SHIFT					24
> -#define TA_DEVCNT_MASK					(0x3 << 24)
> -#define TA_REFINTERVAL_SHIFT				0
> -#define TA_REFINTERVAL_MASK				(0x3fffff << 0)
> -
> -/* OCP_ERROR_LOG */
> -#define MADDRSPACE_SHIFT				14
> -#define MADDRSPACE_MASK					(0x3 << 14)
> -#define MBURSTSEQ_SHIFT					11
> -#define MBURSTSEQ_MASK					(0x7 << 11)
> -#define MCMD_SHIFT					8
> -#define MCMD_MASK					(0x7 << 8)
> -#define MCONNID_SHIFT					0
> -#define MCONNID_MASK					(0xff << 0)
> -
> -/* DDR_PHY_CTRL_1 - EMIF4D */
> -#define DLL_SLAVE_DLY_CTRL_SHIFT_4D			4
> -#define DLL_SLAVE_DLY_CTRL_MASK_4D			(0xFF << 4)
> -#define READ_LATENCY_SHIFT_4D				0
> -#define READ_LATENCY_MASK_4D				(0xf << 0)
> -
> -/* DDR_PHY_CTRL_1 - EMIF4D5 */
> -#define DLL_HALF_DELAY_SHIFT_4D5			21
> -#define DLL_HALF_DELAY_MASK_4D5				(1 << 21)
> -#define READ_LATENCY_SHIFT_4D5				0
> -#define READ_LATENCY_MASK_4D5				(0x1f << 0)
> -
> -/* DDR_PHY_CTRL_1_SHDW */
> -#define DDR_PHY_CTRL_1_SHDW_SHIFT			5
> -#define DDR_PHY_CTRL_1_SHDW_MASK			(0x7ffffff << 5)
> -#define READ_LATENCY_SHDW_SHIFT				0
> -#define READ_LATENCY_SHDW_MASK				(0x1f << 0)
> +#include <linux/ti_emif.h>
>  
>  #ifndef __ASSEMBLY__
>  /*
> diff --git a/include/linux/ti_emif.h b/include/linux/ti_emif.h
> new file mode 100644
> index 0000000..be26e7f
> --- /dev/null
> +++ b/include/linux/ti_emif.h
> @@ -0,0 +1,558 @@
> +/*
> + * Register defines for the EMIF driver
> + *
> + * Copyright (C) 2012 Texas Instruments, Inc.
> + *
> + * Benoit Cousson (b-cousson at 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.
> + */
> +#ifndef __TI_EMIF_H
> +#define __TI_EMIF_H
> +
> +/*
> + * Maximum number of different frequencies supported by EMIF driver
> + * Determines the number of entries in the pointer array for register
> + * cache
> + */
> +#define EMIF_MAX_NUM_FREQUENCIES			6
> +
> +/* State of the core voltage */
> +#define DDR_VOLTAGE_STABLE				0
> +#define DDR_VOLTAGE_RAMPING				1
> +
> +/* Defines for timing De-rating */
> +#define EMIF_NORMAL_TIMINGS				0
> +#define EMIF_DERATED_TIMINGS				1
> +
> +/* Length of the forced read idle period in terms of cycles */
> +#define EMIF_READ_IDLE_LEN_VAL				5
> +
> +/*
> + * forced read idle interval to be used when voltage
> + * is changed as part of DVFS/DPS - 1ms
> + */
> +#define READ_IDLE_INTERVAL_DVFS				(1*1000000)
> +
> +/*
> + * Forced read idle interval to be used when voltage is stable
> + * 50us - or maximum value will do
> + */
> +#define READ_IDLE_INTERVAL_NORMAL			(50*1000000)
> +
> +/* DLL calibration interval when voltage is NOT stable - 1us */
> +#define DLL_CALIB_INTERVAL_DVFS				(1*1000000)
> +
> +#define DLL_CALIB_ACK_WAIT_VAL				5
> +
> +/* Interval between ZQCS commands - hw team recommended value */
> +#define EMIF_ZQCS_INTERVAL_US				(50*1000)
> +/* Enable ZQ Calibration on exiting Self-refresh */
> +#define ZQ_SFEXITEN_ENABLE				1
> +/*
> + * ZQ Calibration simultaneously on both chip-selects:
> + * Needs one calibration resistor per CS
> + */
> +#define	ZQ_DUALCALEN_DISABLE				0
> +#define	ZQ_DUALCALEN_ENABLE				1
> +
> +#define T_ZQCS_DEFAULT_NS				90
> +#define T_ZQCL_DEFAULT_NS				360
> +#define T_ZQINIT_DEFAULT_NS				1000
> +
> +/* DPD_EN */
> +#define DPD_DISABLE					0
> +#define DPD_ENABLE					1
> +
> +/*
> + * Default values for the low-power entry to be used if not provided by user.
> + * OMAP4/5 has a hw bug(i735) due to which this value can not be less than 512
> + * Timeout values are in DDR clock 'cycles' and frequency threshold in Hz
> + */
> +#define EMIF_LP_MODE_TIMEOUT_PERFORMANCE		2048
> +#define EMIF_LP_MODE_TIMEOUT_POWER			512
> +#define EMIF_LP_MODE_FREQ_THRESHOLD			400000000
> +
> +/* DDR_PHY_CTRL_1 values for EMIF4D - ATTILA PHY combination */
> +#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY		0x049FF000
> +#define EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY	0x41
> +#define EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY	0x80
> +#define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY 0xFF
> +
> +/* DDR_PHY_CTRL_1 values for EMIF4D5 INTELLIPHY combination */
> +#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY		0x0E084200
> +#define EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS	10000
> +
> +/* TEMP_ALERT_CONFIG - corresponding to temp gradient 5 C/s */
> +#define TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS		360
> +
> +#define EMIF_T_CSTA					3
> +#define EMIF_T_PDLL_UL					128
> +
> +/* External PHY control registers magic values */
> +#define EMIF_EXT_PHY_CTRL_1_VAL				0x04020080
> +#define EMIF_EXT_PHY_CTRL_5_VAL				0x04010040
> +#define EMIF_EXT_PHY_CTRL_6_VAL				0x01004010
> +#define EMIF_EXT_PHY_CTRL_7_VAL				0x00001004
> +#define EMIF_EXT_PHY_CTRL_8_VAL				0x04010040
> +#define EMIF_EXT_PHY_CTRL_9_VAL				0x01004010
> +#define EMIF_EXT_PHY_CTRL_10_VAL			0x00001004
> +#define EMIF_EXT_PHY_CTRL_11_VAL			0x00000000
> +#define EMIF_EXT_PHY_CTRL_12_VAL			0x00000000
> +#define EMIF_EXT_PHY_CTRL_13_VAL			0x00000000
> +#define EMIF_EXT_PHY_CTRL_14_VAL			0x80080080
> +#define EMIF_EXT_PHY_CTRL_15_VAL			0x00800800
> +#define EMIF_EXT_PHY_CTRL_16_VAL			0x08102040
> +#define EMIF_EXT_PHY_CTRL_17_VAL			0x00000001
> +#define EMIF_EXT_PHY_CTRL_18_VAL			0x540A8150
> +#define EMIF_EXT_PHY_CTRL_19_VAL			0xA81502A0
> +#define EMIF_EXT_PHY_CTRL_20_VAL			0x002A0540
> +#define EMIF_EXT_PHY_CTRL_21_VAL			0x00000000
> +#define EMIF_EXT_PHY_CTRL_22_VAL			0x00000000
> +#define EMIF_EXT_PHY_CTRL_23_VAL			0x00000000
> +#define EMIF_EXT_PHY_CTRL_24_VAL			0x00000077
> +
> +#define EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS	1200
> +
> +/* Registers offset */
> +#define EMIF_MODULE_ID_AND_REVISION			0x0000
> +#define EMIF_STATUS					0x0004
> +#define EMIF_SDRAM_CONFIG				0x0008
> +#define EMIF_SDRAM_CONFIG_2				0x000c
> +#define EMIF_SDRAM_REFRESH_CONTROL			0x0010
> +#define EMIF_SDRAM_REFRESH_CTRL_SHDW			0x0014
> +#define EMIF_SDRAM_TIMING_1				0x0018
> +#define EMIF_SDRAM_TIMING_1_SHDW			0x001c
> +#define EMIF_SDRAM_TIMING_2				0x0020
> +#define EMIF_SDRAM_TIMING_2_SHDW			0x0024
> +#define EMIF_SDRAM_TIMING_3				0x0028
> +#define EMIF_SDRAM_TIMING_3_SHDW			0x002c
> +#define EMIF_LPDDR2_NVM_TIMING				0x0030
> +#define EMIF_LPDDR2_NVM_TIMING_SHDW			0x0034
> +#define EMIF_POWER_MANAGEMENT_CONTROL			0x0038
> +#define EMIF_POWER_MANAGEMENT_CTRL_SHDW			0x003c
> +#define EMIF_LPDDR2_MODE_REG_DATA			0x0040
> +#define EMIF_LPDDR2_MODE_REG_CONFIG			0x0050
> +#define EMIF_OCP_CONFIG					0x0054
> +#define EMIF_OCP_CONFIG_VALUE_1				0x0058
> +#define EMIF_OCP_CONFIG_VALUE_2				0x005c
> +#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL		0x0060
> +#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT		0x0064
> +#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT	0x0068
> +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1	0x006c
> +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2	0x0070
> +#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3	0x0074
> +#define EMIF_PERFORMANCE_COUNTER_1			0x0080
> +#define EMIF_PERFORMANCE_COUNTER_2			0x0084
> +#define EMIF_PERFORMANCE_COUNTER_CONFIG			0x0088
> +#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT	0x008c
> +#define EMIF_PERFORMANCE_COUNTER_TIME			0x0090
> +#define EMIF_MISC_REG					0x0094
> +#define EMIF_DLL_CALIB_CTRL				0x0098
> +#define EMIF_DLL_CALIB_CTRL_SHDW			0x009c
> +#define EMIF_END_OF_INTERRUPT				0x00a0
> +#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS		0x00a4
> +#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS		0x00a8
> +#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS		0x00ac
> +#define EMIF_LL_OCP_INTERRUPT_STATUS			0x00b0
> +#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET		0x00b4
> +#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET		0x00b8
> +#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR		0x00bc
> +#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR		0x00c0
> +#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG	0x00c8
> +#define EMIF_TEMPERATURE_ALERT_CONFIG			0x00cc
> +#define EMIF_OCP_ERROR_LOG				0x00d0
> +#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW		0x00d4
> +#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL		0x00d8
> +#define EMIF_READ_WRITE_LEVELING_CONTROL		0x00dc
> +#define EMIF_DDR_PHY_CTRL_1				0x00e4
> +#define EMIF_DDR_PHY_CTRL_1_SHDW			0x00e8
> +#define EMIF_DDR_PHY_CTRL_2				0x00ec
> +#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING	0x0100
> +#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104
> +#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108
> +#define EMIF_READ_WRITE_EXECUTION_THRESHOLD		0x0120
> +#define EMIF_COS_CONFIG					0x0124
> +#define EMIF_PHY_STATUS_1				0x0140
> +#define EMIF_PHY_STATUS_2				0x0144
> +#define EMIF_PHY_STATUS_3				0x0148
> +#define EMIF_PHY_STATUS_4				0x014c
> +#define EMIF_PHY_STATUS_5				0x0150
> +#define EMIF_PHY_STATUS_6				0x0154
> +#define EMIF_PHY_STATUS_7				0x0158
> +#define EMIF_PHY_STATUS_8				0x015c
> +#define EMIF_PHY_STATUS_9				0x0160
> +#define EMIF_PHY_STATUS_10				0x0164
> +#define EMIF_PHY_STATUS_11				0x0168
> +#define EMIF_PHY_STATUS_12				0x016c
> +#define EMIF_PHY_STATUS_13				0x0170
> +#define EMIF_PHY_STATUS_14				0x0174
> +#define EMIF_PHY_STATUS_15				0x0178
> +#define EMIF_PHY_STATUS_16				0x017c
> +#define EMIF_PHY_STATUS_17				0x0180
> +#define EMIF_PHY_STATUS_18				0x0184
> +#define EMIF_PHY_STATUS_19				0x0188
> +#define EMIF_PHY_STATUS_20				0x018c
> +#define EMIF_PHY_STATUS_21				0x0190
> +#define EMIF_EXT_PHY_CTRL_1				0x0200
> +#define EMIF_EXT_PHY_CTRL_1_SHDW			0x0204
> +#define EMIF_EXT_PHY_CTRL_2				0x0208
> +#define EMIF_EXT_PHY_CTRL_2_SHDW			0x020c
> +#define EMIF_EXT_PHY_CTRL_3				0x0210
> +#define EMIF_EXT_PHY_CTRL_3_SHDW			0x0214
> +#define EMIF_EXT_PHY_CTRL_4				0x0218
> +#define EMIF_EXT_PHY_CTRL_4_SHDW			0x021c
> +#define EMIF_EXT_PHY_CTRL_5				0x0220
> +#define EMIF_EXT_PHY_CTRL_5_SHDW			0x0224
> +#define EMIF_EXT_PHY_CTRL_6				0x0228
> +#define EMIF_EXT_PHY_CTRL_6_SHDW			0x022c
> +#define EMIF_EXT_PHY_CTRL_7				0x0230
> +#define EMIF_EXT_PHY_CTRL_7_SHDW			0x0234
> +#define EMIF_EXT_PHY_CTRL_8				0x0238
> +#define EMIF_EXT_PHY_CTRL_8_SHDW			0x023c
> +#define EMIF_EXT_PHY_CTRL_9				0x0240
> +#define EMIF_EXT_PHY_CTRL_9_SHDW			0x0244
> +#define EMIF_EXT_PHY_CTRL_10				0x0248
> +#define EMIF_EXT_PHY_CTRL_10_SHDW			0x024c
> +#define EMIF_EXT_PHY_CTRL_11				0x0250
> +#define EMIF_EXT_PHY_CTRL_11_SHDW			0x0254
> +#define EMIF_EXT_PHY_CTRL_12				0x0258
> +#define EMIF_EXT_PHY_CTRL_12_SHDW			0x025c
> +#define EMIF_EXT_PHY_CTRL_13				0x0260
> +#define EMIF_EXT_PHY_CTRL_13_SHDW			0x0264
> +#define EMIF_EXT_PHY_CTRL_14				0x0268
> +#define EMIF_EXT_PHY_CTRL_14_SHDW			0x026c
> +#define EMIF_EXT_PHY_CTRL_15				0x0270
> +#define EMIF_EXT_PHY_CTRL_15_SHDW			0x0274
> +#define EMIF_EXT_PHY_CTRL_16				0x0278
> +#define EMIF_EXT_PHY_CTRL_16_SHDW			0x027c
> +#define EMIF_EXT_PHY_CTRL_17				0x0280
> +#define EMIF_EXT_PHY_CTRL_17_SHDW			0x0284
> +#define EMIF_EXT_PHY_CTRL_18				0x0288
> +#define EMIF_EXT_PHY_CTRL_18_SHDW			0x028c
> +#define EMIF_EXT_PHY_CTRL_19				0x0290
> +#define EMIF_EXT_PHY_CTRL_19_SHDW			0x0294
> +#define EMIF_EXT_PHY_CTRL_20				0x0298
> +#define EMIF_EXT_PHY_CTRL_20_SHDW			0x029c
> +#define EMIF_EXT_PHY_CTRL_21				0x02a0
> +#define EMIF_EXT_PHY_CTRL_21_SHDW			0x02a4
> +#define EMIF_EXT_PHY_CTRL_22				0x02a8
> +#define EMIF_EXT_PHY_CTRL_22_SHDW			0x02ac
> +#define EMIF_EXT_PHY_CTRL_23				0x02b0
> +#define EMIF_EXT_PHY_CTRL_23_SHDW			0x02b4
> +#define EMIF_EXT_PHY_CTRL_24				0x02b8
> +#define EMIF_EXT_PHY_CTRL_24_SHDW			0x02bc
> +#define EMIF_EXT_PHY_CTRL_25				0x02c0
> +#define EMIF_EXT_PHY_CTRL_25_SHDW			0x02c4
> +#define EMIF_EXT_PHY_CTRL_26				0x02c8
> +#define EMIF_EXT_PHY_CTRL_26_SHDW			0x02cc
> +#define EMIF_EXT_PHY_CTRL_27				0x02d0
> +#define EMIF_EXT_PHY_CTRL_27_SHDW			0x02d4
> +#define EMIF_EXT_PHY_CTRL_28				0x02d8
> +#define EMIF_EXT_PHY_CTRL_28_SHDW			0x02dc
> +#define EMIF_EXT_PHY_CTRL_29				0x02e0
> +#define EMIF_EXT_PHY_CTRL_29_SHDW			0x02e4
> +#define EMIF_EXT_PHY_CTRL_30				0x02e8
> +#define EMIF_EXT_PHY_CTRL_30_SHDW			0x02ec
> +
> +/* Registers shifts and masks */
> +
> +/* EMIF_MODULE_ID_AND_REVISION */
> +#define SCHEME_SHIFT					30
> +#define SCHEME_MASK					(0x3 << 30)
> +#define MODULE_ID_SHIFT					16
> +#define MODULE_ID_MASK					(0xfff << 16)
> +#define RTL_VERSION_SHIFT				11
> +#define RTL_VERSION_MASK				(0x1f << 11)
> +#define MAJOR_REVISION_SHIFT				8
> +#define MAJOR_REVISION_MASK				(0x7 << 8)
> +#define MINOR_REVISION_SHIFT				0
> +#define MINOR_REVISION_MASK				(0x3f << 0)
> +
> +/* STATUS */
> +#define BE_SHIFT					31
> +#define BE_MASK						(1 << 31)
> +#define DUAL_CLK_MODE_SHIFT				30
> +#define DUAL_CLK_MODE_MASK				(1 << 30)
> +#define FAST_INIT_SHIFT					29
> +#define FAST_INIT_MASK					(1 << 29)
> +#define RDLVLGATETO_SHIFT				6
> +#define RDLVLGATETO_MASK				(1 << 6)
> +#define RDLVLTO_SHIFT					5
> +#define RDLVLTO_MASK					(1 << 5)
> +#define WRLVLTO_SHIFT					4
> +#define WRLVLTO_MASK					(1 << 4)
> +#define PHY_DLL_READY_SHIFT				2
> +#define PHY_DLL_READY_MASK				(1 << 2)
> +
> +/* SDRAM_CONFIG */
> +#define SDRAM_TYPE_SHIFT				29
> +#define SDRAM_TYPE_MASK					(0x7 << 29)
> +#define IBANK_POS_SHIFT					27
> +#define IBANK_POS_MASK					(0x3 << 27)
> +#define DDR_TERM_SHIFT					24
> +#define DDR_TERM_MASK					(0x7 << 24)
> +#define DDR2_DDQS_SHIFT					23
> +#define DDR2_DDQS_MASK					(1 << 23)
> +#define DYN_ODT_SHIFT					21
> +#define DYN_ODT_MASK					(0x3 << 21)
> +#define DDR_DISABLE_DLL_SHIFT				20
> +#define DDR_DISABLE_DLL_MASK				(1 << 20)
> +#define SDRAM_DRIVE_SHIFT				18
> +#define SDRAM_DRIVE_MASK				(0x3 << 18)
> +#define CWL_SHIFT					16
> +#define CWL_MASK					(0x3 << 16)
> +#define NARROW_MODE_SHIFT				14
> +#define NARROW_MODE_MASK				(0x3 << 14)
> +#define CL_SHIFT					10
> +#define CL_MASK						(0xf << 10)
> +#define ROWSIZE_SHIFT					7
> +#define ROWSIZE_MASK					(0x7 << 7)
> +#define IBANK_SHIFT					4
> +#define IBANK_MASK					(0x7 << 4)
> +#define EBANK_SHIFT					3
> +#define EBANK_MASK					(1 << 3)
> +#define PAGESIZE_SHIFT					0
> +#define PAGESIZE_MASK					(0x7 << 0)
> +
> +/* SDRAM_CONFIG_2 */
> +#define CS1NVMEN_SHIFT					30
> +#define CS1NVMEN_MASK					(1 << 30)
> +#define EBANK_POS_SHIFT					27
> +#define EBANK_POS_MASK					(1 << 27)
> +#define RDBNUM_SHIFT					4
> +#define RDBNUM_MASK					(0x3 << 4)
> +#define RDBSIZE_SHIFT					0
> +#define RDBSIZE_MASK					(0x7 << 0)
> +
> +/* SDRAM_REFRESH_CONTROL */
> +#define INITREF_DIS_SHIFT				31
> +#define INITREF_DIS_MASK				(1 << 31)
> +#define SRT_SHIFT					29
> +#define SRT_MASK					(1 << 29)
> +#define ASR_SHIFT					28
> +#define ASR_MASK					(1 << 28)
> +#define PASR_SHIFT					24
> +#define PASR_MASK					(0x7 << 24)
> +#define REFRESH_RATE_SHIFT				0
> +#define REFRESH_RATE_MASK				(0xffff << 0)
> +
> +/* SDRAM_TIMING_1 */
> +#define T_RTW_SHIFT					29
> +#define T_RTW_MASK					(0x7 << 29)
> +#define T_RP_SHIFT					25
> +#define T_RP_MASK					(0xf << 25)
> +#define T_RCD_SHIFT					21
> +#define T_RCD_MASK					(0xf << 21)
> +#define T_WR_SHIFT					17
> +#define T_WR_MASK					(0xf << 17)
> +#define T_RAS_SHIFT					12
> +#define T_RAS_MASK					(0x1f << 12)
> +#define T_RC_SHIFT					6
> +#define T_RC_MASK					(0x3f << 6)
> +#define T_RRD_SHIFT					3
> +#define T_RRD_MASK					(0x7 << 3)
> +#define T_WTR_SHIFT					0
> +#define T_WTR_MASK					(0x7 << 0)
> +
> +/* SDRAM_TIMING_2 */
> +#define T_XP_SHIFT					28
> +#define T_XP_MASK					(0x7 << 28)
> +#define T_ODT_SHIFT					25
> +#define T_ODT_MASK					(0x7 << 25)
> +#define T_XSNR_SHIFT					16
> +#define T_XSNR_MASK					(0x1ff << 16)
> +#define T_XSRD_SHIFT					6
> +#define T_XSRD_MASK					(0x3ff << 6)
> +#define T_RTP_SHIFT					3
> +#define T_RTP_MASK					(0x7 << 3)
> +#define T_CKE_SHIFT					0
> +#define T_CKE_MASK					(0x7 << 0)
> +
> +/* SDRAM_TIMING_3 */
> +#define T_PDLL_UL_SHIFT					28
> +#define T_PDLL_UL_MASK					(0xf << 28)
> +#define T_CSTA_SHIFT					24
> +#define T_CSTA_MASK					(0xf << 24)
> +#define T_CKESR_SHIFT					21
> +#define T_CKESR_MASK					(0x7 << 21)
> +#define ZQ_ZQCS_SHIFT					15
> +#define ZQ_ZQCS_MASK					(0x3f << 15)
> +#define T_TDQSCKMAX_SHIFT				13
> +#define T_TDQSCKMAX_MASK				(0x3 << 13)
> +#define T_RFC_SHIFT					4
> +#define T_RFC_MASK					(0x1ff << 4)
> +#define T_RAS_MAX_SHIFT					0
> +#define T_RAS_MAX_MASK					(0xf << 0)
> +
> +/* POWER_MANAGEMENT_CONTROL */
> +#define PD_TIM_SHIFT					12
> +#define PD_TIM_MASK					(0xf << 12)
> +#define DPD_EN_SHIFT					11
> +#define DPD_EN_MASK					(1 << 11)
> +#define LP_MODE_SHIFT					8
> +#define LP_MODE_MASK					(0x7 << 8)
> +#define SR_TIM_SHIFT					4
> +#define SR_TIM_MASK					(0xf << 4)
> +#define CS_TIM_SHIFT					0
> +#define CS_TIM_MASK					(0xf << 0)
> +
> +/* LPDDR2_MODE_REG_DATA */
> +#define VALUE_0_SHIFT					0
> +#define VALUE_0_MASK					(0x7f << 0)
> +
> +/* LPDDR2_MODE_REG_CONFIG */
> +#define CS_SHIFT					31
> +#define CS_MASK						(1 << 31)
> +#define REFRESH_EN_SHIFT				30
> +#define REFRESH_EN_MASK					(1 << 30)
> +#define ADDRESS_SHIFT					0
> +#define ADDRESS_MASK					(0xff << 0)
> +
> +/* OCP_CONFIG */
> +#define SYS_THRESH_MAX_SHIFT				24
> +#define SYS_THRESH_MAX_MASK				(0xf << 24)
> +#define MPU_THRESH_MAX_SHIFT				20
> +#define MPU_THRESH_MAX_MASK				(0xf << 20)
> +#define LL_THRESH_MAX_SHIFT				16
> +#define LL_THRESH_MAX_MASK				(0xf << 16)
> +
> +/* PERFORMANCE_COUNTER_1 */
> +#define COUNTER1_SHIFT					0
> +#define COUNTER1_MASK					(0xffffffff << 0)
> +
> +/* PERFORMANCE_COUNTER_2 */
> +#define COUNTER2_SHIFT					0
> +#define COUNTER2_MASK					(0xffffffff << 0)
> +
> +/* PERFORMANCE_COUNTER_CONFIG */
> +#define CNTR2_MCONNID_EN_SHIFT				31
> +#define CNTR2_MCONNID_EN_MASK				(1 << 31)
> +#define CNTR2_REGION_EN_SHIFT				30
> +#define CNTR2_REGION_EN_MASK				(1 << 30)
> +#define CNTR2_CFG_SHIFT					16
> +#define CNTR2_CFG_MASK					(0xf << 16)
> +#define CNTR1_MCONNID_EN_SHIFT				15
> +#define CNTR1_MCONNID_EN_MASK				(1 << 15)
> +#define CNTR1_REGION_EN_SHIFT				14
> +#define CNTR1_REGION_EN_MASK				(1 << 14)
> +#define CNTR1_CFG_SHIFT					0
> +#define CNTR1_CFG_MASK					(0xf << 0)
> +
> +/* PERFORMANCE_COUNTER_MASTER_REGION_SELECT */
> +#define MCONNID2_SHIFT					24
> +#define MCONNID2_MASK					(0xff << 24)
> +#define REGION_SEL2_SHIFT				16
> +#define REGION_SEL2_MASK				(0x3 << 16)
> +#define MCONNID1_SHIFT					8
> +#define MCONNID1_MASK					(0xff << 8)
> +#define REGION_SEL1_SHIFT				0
> +#define REGION_SEL1_MASK				(0x3 << 0)
> +
> +/* PERFORMANCE_COUNTER_TIME */
> +#define TOTAL_TIME_SHIFT				0
> +#define TOTAL_TIME_MASK					(0xffffffff << 0)
> +
> +/* DLL_CALIB_CTRL */
> +#define ACK_WAIT_SHIFT					16
> +#define ACK_WAIT_MASK					(0xf << 16)
> +#define DLL_CALIB_INTERVAL_SHIFT			0
> +#define DLL_CALIB_INTERVAL_MASK				(0x1ff << 0)
> +
> +/* END_OF_INTERRUPT */
> +#define EOI_SHIFT					0
> +#define EOI_MASK					(1 << 0)
> +
> +/* SYSTEM_OCP_INTERRUPT_RAW_STATUS */
> +#define DNV_SYS_SHIFT					2
> +#define DNV_SYS_MASK					(1 << 2)
> +#define TA_SYS_SHIFT					1
> +#define TA_SYS_MASK					(1 << 1)
> +#define ERR_SYS_SHIFT					0
> +#define ERR_SYS_MASK					(1 << 0)
> +
> +/* LOW_LATENCY_OCP_INTERRUPT_RAW_STATUS */
> +#define DNV_LL_SHIFT					2
> +#define DNV_LL_MASK					(1 << 2)
> +#define TA_LL_SHIFT					1
> +#define TA_LL_MASK					(1 << 1)
> +#define ERR_LL_SHIFT					0
> +#define ERR_LL_MASK					(1 << 0)
> +
> +/* SYSTEM_OCP_INTERRUPT_ENABLE_SET */
> +#define EN_DNV_SYS_SHIFT				2
> +#define EN_DNV_SYS_MASK					(1 << 2)
> +#define EN_TA_SYS_SHIFT					1
> +#define EN_TA_SYS_MASK					(1 << 1)
> +#define EN_ERR_SYS_SHIFT					0
> +#define EN_ERR_SYS_MASK					(1 << 0)
> +
> +/* LOW_LATENCY_OCP_INTERRUPT_ENABLE_SET */
> +#define EN_DNV_LL_SHIFT					2
> +#define EN_DNV_LL_MASK					(1 << 2)
> +#define EN_TA_LL_SHIFT					1
> +#define EN_TA_LL_MASK					(1 << 1)
> +#define EN_ERR_LL_SHIFT					0
> +#define EN_ERR_LL_MASK					(1 << 0)
> +
> +/* SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG */
> +#define ZQ_CS1EN_SHIFT					31
> +#define ZQ_CS1EN_MASK					(1 << 31)
> +#define ZQ_CS0EN_SHIFT					30
> +#define ZQ_CS0EN_MASK					(1 << 30)
> +#define ZQ_DUALCALEN_SHIFT				29
> +#define ZQ_DUALCALEN_MASK				(1 << 29)
> +#define ZQ_SFEXITEN_SHIFT				28
> +#define ZQ_SFEXITEN_MASK				(1 << 28)
> +#define ZQ_ZQINIT_MULT_SHIFT				18
> +#define ZQ_ZQINIT_MULT_MASK				(0x3 << 18)
> +#define ZQ_ZQCL_MULT_SHIFT				16
> +#define ZQ_ZQCL_MULT_MASK				(0x3 << 16)
> +#define ZQ_REFINTERVAL_SHIFT				0
> +#define ZQ_REFINTERVAL_MASK				(0xffff << 0)
> +
> +/* TEMPERATURE_ALERT_CONFIG */
> +#define TA_CS1EN_SHIFT					31
> +#define TA_CS1EN_MASK					(1 << 31)
> +#define TA_CS0EN_SHIFT					30
> +#define TA_CS0EN_MASK					(1 << 30)
> +#define TA_SFEXITEN_SHIFT				28
> +#define TA_SFEXITEN_MASK				(1 << 28)
> +#define TA_DEVWDT_SHIFT					26
> +#define TA_DEVWDT_MASK					(0x3 << 26)
> +#define TA_DEVCNT_SHIFT					24
> +#define TA_DEVCNT_MASK					(0x3 << 24)
> +#define TA_REFINTERVAL_SHIFT				0
> +#define TA_REFINTERVAL_MASK				(0x3fffff << 0)
> +
> +/* OCP_ERROR_LOG */
> +#define MADDRSPACE_SHIFT				14
> +#define MADDRSPACE_MASK					(0x3 << 14)
> +#define MBURSTSEQ_SHIFT					11
> +#define MBURSTSEQ_MASK					(0x7 << 11)
> +#define MCMD_SHIFT					8
> +#define MCMD_MASK					(0x7 << 8)
> +#define MCONNID_SHIFT					0
> +#define MCONNID_MASK					(0xff << 0)
> +
> +/* DDR_PHY_CTRL_1 - EMIF4D */
> +#define DLL_SLAVE_DLY_CTRL_SHIFT_4D			4
> +#define DLL_SLAVE_DLY_CTRL_MASK_4D			(0xFF << 4)
> +#define READ_LATENCY_SHIFT_4D				0
> +#define READ_LATENCY_MASK_4D				(0xf << 0)
> +
> +/* DDR_PHY_CTRL_1 - EMIF4D5 */
> +#define DLL_HALF_DELAY_SHIFT_4D5			21
> +#define DLL_HALF_DELAY_MASK_4D5				(1 << 21)
> +#define READ_LATENCY_SHIFT_4D5				0
> +#define READ_LATENCY_MASK_4D5				(0x1f << 0)
> +
> +/* DDR_PHY_CTRL_1_SHDW */
> +#define DDR_PHY_CTRL_1_SHDW_SHIFT			5
> +#define DDR_PHY_CTRL_1_SHDW_MASK			(0x7ffffff << 5)
> +#define READ_LATENCY_SHDW_SHIFT				0
> +#define READ_LATENCY_SHDW_MASK				(0x1f << 0)
> +
> +#endif /* __TI_EMIF_H */
> 

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08 13:44     ` Santosh Shilimkar
  -1 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 13:44 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman, Vaibhav Bedia

On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
> 
> Interacting with WKUP-M3 requires some more control
> module register writes. Add the register offsets and
> APIs to write to these.
> 
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> ---
>  arch/arm/mach-omap2/control.c |   57 +++++++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/control.h |   54 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 111 insertions(+)
> 
> diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
> index 31e0dfe..934041a 100644
> --- a/arch/arm/mach-omap2/control.c
> +++ b/arch/arm/mach-omap2/control.c
> @@ -605,3 +605,60 @@ int omap3_ctrl_save_padconf(void)
>  }
>  
>  #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
> +
> +#if defined(CONFIG_SOC_AM33XX) && defined(CONFIG_PM)
> +void am33xx_txev_eoi(void)
> +{
> +	omap_ctrl_writel(AM33XX_M3_TXEV_ACK, AM33XX_CONTROL_M3_TXEV_EOI);
> +}
> +
> +void am33xx_txev_enable(void)
> +{
> +	omap_ctrl_writel(AM33XX_M3_TXEV_ENABLE, AM33XX_CONTROL_M3_TXEV_EOI);
> +}
> +
> +/*
> + * Invalidate M3 firmware version before hardreset.
> + * Write invalid version in lower 4 nibbles of parameter
> + * register (ipc_regs + 0x8).
> + */
> +void am33xx_pm_version_clear(void)
> +{
> +	omap_ctrl_writel(0xffff0000, AM33XX_CONTROL_IPC_MSG_REG2);
> +}
> +
> +int am33xx_pm_version_get(void)
> +{
> +	return omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG2) & M3_VERSION_MASK;
> +}
> +
> +void am33xx_pm_ipc_cmd(struct am33xx_ipc_data *data)
> +{
> +	omap_ctrl_writel(data->resume_addr, AM33XX_CONTROL_IPC_MSG_REG0);
> +	omap_ctrl_writel(data->sleep_mode, AM33XX_CONTROL_IPC_MSG_REG1);
> +	omap_ctrl_writel(data->param1, AM33XX_CONTROL_IPC_MSG_REG2);
> +	omap_ctrl_writel(data->param2, AM33XX_CONTROL_IPC_MSG_REG3);
> +	omap_ctrl_writel(data->param3, AM33XX_CONTROL_IPC_MSG_REG4);
> +}
> +
> +int am33xx_pm_status(void)
> +{
> +	int i;
> +
> +	i = omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG1);
> +	i &= IPC_RESP_MASK;
> +	i >>= __ffs(IPC_RESP_MASK);
> +
> +	return i;
> +}
> +
> +int am33xx_pm_wake_src(void)
> +{
> +	int i;
> +
> +	i = omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG6);
> +	i &= 0xff;
> +
> +	return i;
> +}
> +#endif /* CONFIG_SOC_AM33XX && CONFIG_PM */
> diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
> index f7d7c2e..9be587c 100644
> --- a/arch/arm/mach-omap2/control.h
> +++ b/arch/arm/mach-omap2/control.h
> @@ -370,6 +370,22 @@
>  #define AM33XX_DEV_FEATURE		0x604
>  #define AM33XX_SGX_MASK			BIT(29)
>  
> +/* AM33XX M3_TXEV_EOI register */
> +#define AM33XX_CONTROL_M3_TXEV_EOI	0x1324
> +
> +#define AM33XX_M3_TXEV_ACK		(0x1 << 0)
> +#define AM33XX_M3_TXEV_ENABLE		(0x0 << 0)
> +
> +/* AM33XX IPC message registers */
> +#define AM33XX_CONTROL_IPC_MSG_REG0	0x1328
> +#define AM33XX_CONTROL_IPC_MSG_REG1	0x132C
> +#define AM33XX_CONTROL_IPC_MSG_REG2	0x1330
> +#define AM33XX_CONTROL_IPC_MSG_REG3	0x1334
> +#define AM33XX_CONTROL_IPC_MSG_REG4	0x1338
> +#define AM33XX_CONTROL_IPC_MSG_REG5	0x133C
> +#define AM33XX_CONTROL_IPC_MSG_REG6	0x1340
> +#define AM33XX_CONTROL_IPC_MSG_REG7	0x1344
> +
>  /* CONTROL OMAP STATUS register to identify OMAP3 features */
>  #define OMAP3_CONTROL_OMAP_STATUS	0x044c
>  
> @@ -429,6 +445,44 @@ extern void omap3630_ctrl_disable_rta(void);
>  extern int omap3_ctrl_save_padconf(void);
>  extern void omap2_set_globals_control(void __iomem *ctrl,
>  				      void __iomem *ctrl_pad);
> +struct am33xx_ipc_data {
> +	u32 resume_addr;
> +	u32 sleep_mode;
> +	u32 param1;
> +	u32 param2;
> +	u32 param3;
> +	u32 param4;
> +	u32 param5;
> +	u32 param6;
> +};
> +
> +#define IPC_RESP_SHIFT			16
> +#define IPC_RESP_MASK			(0xffff << 16)
> +
> +#define M3_VERSION_SHIFT		0
> +#define M3_VERSION_MASK			(0xffff << 0)
> +
> +/*
> + * 9-4 = VTT GPIO PIN (6 Bits)
> + *   3 = VTT Status (1 Bit)
> + * 2-0 = Memory Type (2 Bits)
> +*/
> +#define MEM_TYPE_SHIFT		(0x0)
> +#define MEM_TYPE_MASK		(0x7 << 0)
> +#define VTT_STAT_SHIFT		(0x3)
> +#define VTT_STAT_MASK		(0x1 << 3)
> +#define VTT_GPIO_PIN_SHIFT	(0x4)
> +#define VTT_GPIO_PIN_MASK	(0x2f << 4)
> +
> +extern void am33xx_wkup_m3_ipc_cmd(struct am33xx_ipc_data *data);
> +extern void am33xx_txev_eoi(void);
> +extern void am33xx_txev_enable(void);
> +extern void am33xx_pm_version_clear(void);
> +extern int am33xx_pm_version_get(void);
> +extern void am33xx_pm_ipc_cmd(struct am33xx_ipc_data *data);
> +extern int am33xx_pm_status(void);
> +extern int am33xx_pm_wake_src(void);
> +
Lets address the above better. I don't see a need of 8 functions
exported doing one or 2 register writes.

Look M3 based handling is going to be there on future SOCs
as well and this kind of handling of IPC is very short cited.

Probably we should have a separate driver for M3 in linux which
can have all this local code instead of all these exports.

Regards,
Santosh


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-08 13:44     ` Santosh Shilimkar
  0 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 13:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
> 
> Interacting with WKUP-M3 requires some more control
> module register writes. Add the register offsets and
> APIs to write to these.
> 
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> ---
>  arch/arm/mach-omap2/control.c |   57 +++++++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/control.h |   54 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 111 insertions(+)
> 
> diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
> index 31e0dfe..934041a 100644
> --- a/arch/arm/mach-omap2/control.c
> +++ b/arch/arm/mach-omap2/control.c
> @@ -605,3 +605,60 @@ int omap3_ctrl_save_padconf(void)
>  }
>  
>  #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
> +
> +#if defined(CONFIG_SOC_AM33XX) && defined(CONFIG_PM)
> +void am33xx_txev_eoi(void)
> +{
> +	omap_ctrl_writel(AM33XX_M3_TXEV_ACK, AM33XX_CONTROL_M3_TXEV_EOI);
> +}
> +
> +void am33xx_txev_enable(void)
> +{
> +	omap_ctrl_writel(AM33XX_M3_TXEV_ENABLE, AM33XX_CONTROL_M3_TXEV_EOI);
> +}
> +
> +/*
> + * Invalidate M3 firmware version before hardreset.
> + * Write invalid version in lower 4 nibbles of parameter
> + * register (ipc_regs + 0x8).
> + */
> +void am33xx_pm_version_clear(void)
> +{
> +	omap_ctrl_writel(0xffff0000, AM33XX_CONTROL_IPC_MSG_REG2);
> +}
> +
> +int am33xx_pm_version_get(void)
> +{
> +	return omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG2) & M3_VERSION_MASK;
> +}
> +
> +void am33xx_pm_ipc_cmd(struct am33xx_ipc_data *data)
> +{
> +	omap_ctrl_writel(data->resume_addr, AM33XX_CONTROL_IPC_MSG_REG0);
> +	omap_ctrl_writel(data->sleep_mode, AM33XX_CONTROL_IPC_MSG_REG1);
> +	omap_ctrl_writel(data->param1, AM33XX_CONTROL_IPC_MSG_REG2);
> +	omap_ctrl_writel(data->param2, AM33XX_CONTROL_IPC_MSG_REG3);
> +	omap_ctrl_writel(data->param3, AM33XX_CONTROL_IPC_MSG_REG4);
> +}
> +
> +int am33xx_pm_status(void)
> +{
> +	int i;
> +
> +	i = omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG1);
> +	i &= IPC_RESP_MASK;
> +	i >>= __ffs(IPC_RESP_MASK);
> +
> +	return i;
> +}
> +
> +int am33xx_pm_wake_src(void)
> +{
> +	int i;
> +
> +	i = omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG6);
> +	i &= 0xff;
> +
> +	return i;
> +}
> +#endif /* CONFIG_SOC_AM33XX && CONFIG_PM */
> diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
> index f7d7c2e..9be587c 100644
> --- a/arch/arm/mach-omap2/control.h
> +++ b/arch/arm/mach-omap2/control.h
> @@ -370,6 +370,22 @@
>  #define AM33XX_DEV_FEATURE		0x604
>  #define AM33XX_SGX_MASK			BIT(29)
>  
> +/* AM33XX M3_TXEV_EOI register */
> +#define AM33XX_CONTROL_M3_TXEV_EOI	0x1324
> +
> +#define AM33XX_M3_TXEV_ACK		(0x1 << 0)
> +#define AM33XX_M3_TXEV_ENABLE		(0x0 << 0)
> +
> +/* AM33XX IPC message registers */
> +#define AM33XX_CONTROL_IPC_MSG_REG0	0x1328
> +#define AM33XX_CONTROL_IPC_MSG_REG1	0x132C
> +#define AM33XX_CONTROL_IPC_MSG_REG2	0x1330
> +#define AM33XX_CONTROL_IPC_MSG_REG3	0x1334
> +#define AM33XX_CONTROL_IPC_MSG_REG4	0x1338
> +#define AM33XX_CONTROL_IPC_MSG_REG5	0x133C
> +#define AM33XX_CONTROL_IPC_MSG_REG6	0x1340
> +#define AM33XX_CONTROL_IPC_MSG_REG7	0x1344
> +
>  /* CONTROL OMAP STATUS register to identify OMAP3 features */
>  #define OMAP3_CONTROL_OMAP_STATUS	0x044c
>  
> @@ -429,6 +445,44 @@ extern void omap3630_ctrl_disable_rta(void);
>  extern int omap3_ctrl_save_padconf(void);
>  extern void omap2_set_globals_control(void __iomem *ctrl,
>  				      void __iomem *ctrl_pad);
> +struct am33xx_ipc_data {
> +	u32 resume_addr;
> +	u32 sleep_mode;
> +	u32 param1;
> +	u32 param2;
> +	u32 param3;
> +	u32 param4;
> +	u32 param5;
> +	u32 param6;
> +};
> +
> +#define IPC_RESP_SHIFT			16
> +#define IPC_RESP_MASK			(0xffff << 16)
> +
> +#define M3_VERSION_SHIFT		0
> +#define M3_VERSION_MASK			(0xffff << 0)
> +
> +/*
> + * 9-4 = VTT GPIO PIN (6 Bits)
> + *   3 = VTT Status (1 Bit)
> + * 2-0 = Memory Type (2 Bits)
> +*/
> +#define MEM_TYPE_SHIFT		(0x0)
> +#define MEM_TYPE_MASK		(0x7 << 0)
> +#define VTT_STAT_SHIFT		(0x3)
> +#define VTT_STAT_MASK		(0x1 << 3)
> +#define VTT_GPIO_PIN_SHIFT	(0x4)
> +#define VTT_GPIO_PIN_MASK	(0x2f << 4)
> +
> +extern void am33xx_wkup_m3_ipc_cmd(struct am33xx_ipc_data *data);
> +extern void am33xx_txev_eoi(void);
> +extern void am33xx_txev_enable(void);
> +extern void am33xx_pm_version_clear(void);
> +extern int am33xx_pm_version_get(void);
> +extern void am33xx_pm_ipc_cmd(struct am33xx_ipc_data *data);
> +extern int am33xx_pm_status(void);
> +extern int am33xx_pm_wake_src(void);
> +
Lets address the above better. I don't see a need of 8 functions
exported doing one or 2 register writes.

Look M3 based handling is going to be there on future SOCs
as well and this kind of handling of IPC is very short cited.

Probably we should have a separate driver for M3 in linux which
can have all this local code instead of all these exports.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 3/9] ARM: OMAP: DTB: Update IRQ data for WKUP_M3
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08 13:46     ` Santosh Shilimkar
  -1 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 13:46 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman,
	Vaibhav Bedia, Benoit Cousson

On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
> 
> Allow interrupt for wkup_m3 to be set from DT.
> 
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> Cc: Benoit Cousson <benoit.cousson@linaro.org>
> ---
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 3/9] ARM: OMAP: DTB: Update IRQ data for WKUP_M3
@ 2013-08-08 13:46     ` Santosh Shilimkar
  0 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 13:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
> 
> Allow interrupt for wkup_m3 to be set from DT.
> 
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> Cc: Benoit Cousson <benoit.cousson@linaro.org>
> ---
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08 14:19     ` Santosh Shilimkar
  -1 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 14:19 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman, Vaibhav Bedia

On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
> 
> SDRAM controller on AM33XX requires that a modification of certain
> bit-fields in PWR_MGMT_CTRL register (ref. section 7.3.5.13 in
> AM335x-Rev H) is followed by a dummy read access to SDRAM. This
> scenario arises when entering a low power state like DeepSleep.
> To ensure that the read is not from a cached region we reserve
> some memory during bootup using the arm_memblock_steal() API.
> 
> A subsequent patch will pass along the location of the reserved
> memory location to the AM335x suspend handler which modifies the
> PWR_MGMT_CTRL register in the EMIF.
> 
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> ---
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
@ 2013-08-08 14:19     ` Santosh Shilimkar
  0 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 14:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
> 
> SDRAM controller on AM33XX requires that a modification of certain
> bit-fields in PWR_MGMT_CTRL register (ref. section 7.3.5.13 in
> AM335x-Rev H) is followed by a dummy read access to SDRAM. This
> scenario arises when entering a low power state like DeepSleep.
> To ensure that the read is not from a cached region we reserve
> some memory during bootup using the arm_memblock_steal() API.
> 
> A subsequent patch will pass along the location of the reserved
> memory location to the AM335x suspend handler which modifies the
> PWR_MGMT_CTRL register in the EMIF.
> 
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> ---
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 6/9] ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08 14:23     ` Santosh Shilimkar
  -1 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 14:23 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman, Vaibhav Bedia

On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
> 
> OMAP timer code registers two timers - one as clocksource
> and one as clockevent. Since AM33XX has only one usable timer
> in the WKUP domain one of the timers needs suspend-resume
> support to restore the configuration to pre-suspend state.
> 
> commit adc78e6 (timekeeping: Add suspend and resume
> of clock event devices) introduced .suspend and .resume
> callbacks for clock event devices. Leverages these
> callbacks to have AM33XX clockevent timer which is
> in not in WKUP domain to behave properly across system
> suspend.
> 
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> ---
NAK

This patch doesn't addressed previous comments.
- The issue is specific to AM33XX and hence you
need to take care of that. These callbacks will happen on
all OMAP machines where the problem doesn't exist.

- Don't use hwmod APIs directly. At least abstract it
at omap_device layer and use that one instead.

>  arch/arm/mach-omap2/timer.c |   32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
> 
> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
> index b37e1fc..cce5d39 100644
> --- a/arch/arm/mach-omap2/timer.c
> +++ b/arch/arm/mach-omap2/timer.c
> @@ -118,11 +118,43 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
>  	}
>  }
>  
> +static void omap_clkevt_suspend(struct clock_event_device *unused)
> +{
> +	char name[10];
> +	struct omap_hwmod *oh;
> +
> +	sprintf(name, "timer%d", clkev.id);
> +	oh = omap_hwmod_lookup(name);
> +	if (!oh)
> +		return;
> +
> +	__omap_dm_timer_stop(&clkev, 1, clkev.rate);
> +	omap_hwmod_idle(oh);
> +}
> +
> +static void omap_clkevt_resume(struct clock_event_device *unused)
> +{
> +	char name[10];
> +	struct omap_hwmod *oh;
> +
> +	sprintf(name, "timer%d", clkev.id);
> +	oh = omap_hwmod_lookup(name);
> +	if (!oh)
> +		return;
> +
> +	omap_hwmod_enable(oh);
> +	__omap_dm_timer_load_start(&clkev,
> +			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
> +	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
> +}
> +
>  static struct clock_event_device clockevent_gpt = {
>  	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
>  	.rating		= 300,
>  	.set_next_event	= omap2_gp_timer_set_next_event,
>  	.set_mode	= omap2_gp_timer_set_mode,
> +	.suspend	= omap_clkevt_suspend,
> +	.resume		= omap_clkevt_resume,
>  };
>  
>  static struct property device_disabled = {
> 


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 6/9] ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device
@ 2013-08-08 14:23     ` Santosh Shilimkar
  0 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 14:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
> 
> OMAP timer code registers two timers - one as clocksource
> and one as clockevent. Since AM33XX has only one usable timer
> in the WKUP domain one of the timers needs suspend-resume
> support to restore the configuration to pre-suspend state.
> 
> commit adc78e6 (timekeeping: Add suspend and resume
> of clock event devices) introduced .suspend and .resume
> callbacks for clock event devices. Leverages these
> callbacks to have AM33XX clockevent timer which is
> in not in WKUP domain to behave properly across system
> suspend.
> 
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> ---
NAK

This patch doesn't addressed previous comments.
- The issue is specific to AM33XX and hence you
need to take care of that. These callbacks will happen on
all OMAP machines where the problem doesn't exist.

- Don't use hwmod APIs directly. At least abstract it
at omap_device layer and use that one instead.

>  arch/arm/mach-omap2/timer.c |   32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
> 
> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
> index b37e1fc..cce5d39 100644
> --- a/arch/arm/mach-omap2/timer.c
> +++ b/arch/arm/mach-omap2/timer.c
> @@ -118,11 +118,43 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
>  	}
>  }
>  
> +static void omap_clkevt_suspend(struct clock_event_device *unused)
> +{
> +	char name[10];
> +	struct omap_hwmod *oh;
> +
> +	sprintf(name, "timer%d", clkev.id);
> +	oh = omap_hwmod_lookup(name);
> +	if (!oh)
> +		return;
> +
> +	__omap_dm_timer_stop(&clkev, 1, clkev.rate);
> +	omap_hwmod_idle(oh);
> +}
> +
> +static void omap_clkevt_resume(struct clock_event_device *unused)
> +{
> +	char name[10];
> +	struct omap_hwmod *oh;
> +
> +	sprintf(name, "timer%d", clkev.id);
> +	oh = omap_hwmod_lookup(name);
> +	if (!oh)
> +		return;
> +
> +	omap_hwmod_enable(oh);
> +	__omap_dm_timer_load_start(&clkev,
> +			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
> +	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
> +}
> +
>  static struct clock_event_device clockevent_gpt = {
>  	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
>  	.rating		= 300,
>  	.set_next_event	= omap2_gp_timer_set_next_event,
>  	.set_mode	= omap2_gp_timer_set_mode,
> +	.suspend	= omap_clkevt_suspend,
> +	.resume		= omap_clkevt_resume,
>  };
>  
>  static struct property device_disabled = {
> 

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 7/9] ARM: OMAP: omap_device: Add APIs to enable and idle hwmods
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08 14:26     ` Santosh Shilimkar
  -1 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 14:26 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman, Vaibhav Bedia

On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
> 
> Needed to let the AM335x PM handle the IPs which need forced
> standby transition during every suspend-resume cycle when
> the corresponding driver is not compiled into the kernel.
> 
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> ---
>  arch/arm/mach-omap2/omap_device.c |    8 ++++++++
>  arch/arm/mach-omap2/omap_device.h |    2 ++
>  2 files changed, 10 insertions(+)
> 
The interface might be sane but the need of force standby
is just non-sense. Why can't we take care of this in
firmware itself. Linux doesn't need to know about it.
More comments on this in other patch where it is being used.

Regards,
Santosh


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 7/9] ARM: OMAP: omap_device: Add APIs to enable and idle hwmods
@ 2013-08-08 14:26     ` Santosh Shilimkar
  0 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 14:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
> 
> Needed to let the AM335x PM handle the IPs which need forced
> standby transition during every suspend-resume cycle when
> the corresponding driver is not compiled into the kernel.
> 
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> ---
>  arch/arm/mach-omap2/omap_device.c |    8 ++++++++
>  arch/arm/mach-omap2/omap_device.h |    2 ++
>  2 files changed, 10 insertions(+)
> 
The interface might be sane but the need of force standby
is just non-sense. Why can't we take care of this in
firmware itself. Linux doesn't need to know about it.
More comments on this in other patch where it is being used.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 5/9] ARM: OMAP2+: AM33XX: Add assembly code for PM operations
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08 14:50     ` Santosh Shilimkar
  -1 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 14:50 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: Kevin Hilman, Paul Walmsley, linux-omap, Vaibhav Bedia, linux-arm-kernel

On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
> 
> In preparation for suspend-resume support for AM33XX, add
> the assembly file with the code which is copied to internal
> memory (OCMC RAM) during bootup and runs from there.
> 
> As part of the low power entry (DeepSleep0 mode in AM33XX TRM),
> the code running from OCMC RAM does the following
> 1. Stores the EMIF configuration
> 2. Puts external memory in self-refresh
> 3. Disables EMIF clock
> 4. Executes WFI after writing to MPU_CLKCTRL register.
> 
> If no interrupts have come, WFI execution on MPU gets registered
> as an interrupt with the WKUP-M3. WKUP-M3 takes care of disabling
> some clocks which MPU should not (L3, L4, OCMC RAM etc) and takes
> care of clockdomain and powerdomain transitions as part of the
> DeepSleep0 mode entry.
> 
> In case a late interrupt comes in, WFI ends up as a NOP and MPU
> continues execution from internal memory. The 'abort path' code
> undoes whatever was done as part of the low power entry and indicates
> a suspend failure by passing a non-zero value to the cpu_resume routine.
> 
> The 'resume path' code is similar to the 'abort path' with the key
> difference of MMU being enabled in the 'abort path' but being
> disabled in the 'resume path' due to MPU getting powered off.
> 
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Kevin Hilman <khilman@linaro.org>
> ---
>  arch/arm/mach-omap2/sleep33xx.S |  350 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 350 insertions(+)
>  create mode 100644 arch/arm/mach-omap2/sleep33xx.S
> 
> diff --git a/arch/arm/mach-omap2/sleep33xx.S b/arch/arm/mach-omap2/sleep33xx.S
> new file mode 100644
> index 0000000..834c7d4
> --- /dev/null
> +++ b/arch/arm/mach-omap2/sleep33xx.S
> @@ -0,0 +1,350 @@
> +/*
> + * Low level suspend code for AM33XX SoCs
> + *
> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
> + * Vaibhav Bedia <vaibhav.bedia@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/linkage.h>
> +#include <linux/ti_emif.h>
> +#include <asm/memory.h>
> +#include <asm/assembler.h>
> +
> +#include "cm33xx.h"
> +#include "pm33xx.h"
> +#include "prm33xx.h"
> +
> +	.text
> +	.align 3
> +
> +/*
> + * This routine is executed from internal RAM and expects some
> + * parameters to be passed in r0 _strictly_ in following order:
> + * 1) emif_addr_virt - ioremapped EMIF address
> + * 2) mem_type - 2 -> DDR2, 3-> DDR3
> + * 3) dram_sync_word - uncached word in SDRAM
> + *
> + * The code loads these values taking r0 value as reference to
> + * the array in registers starting from r0, i.e emif_addr_virt
> + * goes to r1, mem_type goes to r2 and and so on. These are
> + * then saved into memory locations before proceeding with the
> + * sleep sequence and hence registers r0, r1 etc can still be
> + * used in the rest of the sleep code.
> + */
> +
> +ENTRY(am33xx_do_wfi)
> +	stmfd	sp!, {r4 - r11, lr}	@ save registers on stack
> +
> +	ldm	r0, {r1-r3}		@ gather values passed
> +
> +	/* Save the values passed */
> +	str	r1, emif_addr_virt
> +	str	r2, mem_type
> +	str	r3, dram_sync_word

None of this parameter are going to change for every suspend entry and
exit so saving them once and accessing them should be fine. Just
create a structure with above, save them in init from C code and
then access that structure where you need to.

> +
> +	/*
> +	 * Flush all data from the L1 data cache before disabling
> +	 * SCTLR.C bit.
> +	 */
> +	ldr	r1, kernel_flush
> +	blx	r1
> +
> +	/*
> +	 * Clear the SCTLR.C bit to prevent further data cache
> +	 * allocation. Clearing SCTLR.C would make all the data accesses
> +	 * strongly ordered and would not hit the cache.
> +	 */
> +	mrc	p15, 0, r0, c1, c0, 0
> +	bic	r0, r0, #(1 << 2)	@ Disable the C bit
> +	mcr	p15, 0, r0, c1, c0, 0
> +	isb
> +
> +	/*
> +	 * Invalidate L1 data cache. Even though only invalidate is
> +	 * necessary exported flush API is used here. Doing clean
> +	 * on already clean cache would be almost NOP.
> +	 */
Comment is stale for AM33XX since below flush will clean l1 and l2
together. We need to first flush and then invalidate. Please update it.
> +	ldr	r1, kernel_flush
> +	blx	r1
> +
> +	ldr	r0, emif_addr_virt
> +	/* Save EMIF configuration */
> +	ldr	r1, [r0, #EMIF_SDRAM_CONFIG]
> +	str	r1, emif_sdcfg_val
> +	ldr	r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
> +	str	r1, emif_ref_ctrl_val
> +	ldr	r1, [r0, #EMIF_SDRAM_TIMING_1]
> +	str	r1, emif_timing1_val
> +	ldr	r1, [r0, #EMIF_SDRAM_TIMING_2]
> +	str	r1, emif_timing2_val
> +	ldr	r1, [r0, #EMIF_SDRAM_TIMING_3]
> +	str	r1, emif_timing3_val
> +	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +	str	r1, emif_pmcr_val
> +	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
> +	str	r1, emif_pmcr_shdw_val
> +	ldr	r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
> +	str	r1, emif_zqcfg_val
> +	ldr	r1, [r0, #EMIF_DDR_PHY_CTRL_1]
> +	str	r1, emif_rd_lat_val
> +
> +	/* Put SDRAM in self-refresh */
> +	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +	orr	r1, r1, #0xa0
No magic numbers please. here and rest of the patch. Have proper
defines.

> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
> +	str	r1, [r0, #4]
> +
> +	ldr	r1, dram_sync_word	@ a dummy access to DDR as per spec
> +	ldr	r2, [r1, #0]
> +	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +	orr	r1, r1, #0x200
> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +
> +	mov	r1, #0x1000		@ Wait for system to enter SR
> +wait_sr:
What is sr ? I know you mean self-refresh, but sr can be smart reflex
as well. Fix that please.
> +	subs	r1, r1, #1
> +	bne	wait_sr
> +
So how did you derive this 0x1000 number. Whats the real
delay need ? For e.g a CPU running at 600 MHz vs running
at 1.2 GHz, the above loop becomes 2 times faster.

> +	/* Disable EMIF */
> +	ldr	r1, virt_emif_clkctrl
> +	ldr	r2, [r1]
> +	bic	r2, r2, #0x03
> +	str	r2, [r1]
> +
> +	ldr	r1, virt_emif_clkctrl
> +wait_emif_disable:
> +	ldr	r2, [r1]
> +	ldr	r3, module_disabled_val
> +	cmp	r2, r3
> +	bne	wait_emif_disable
> +
> +	/*
> +	 * For the MPU WFI to be registered as an interrupt
> +	 * to WKUP_M3, MPU_CLKCTRL.MODULEMODE needs to be set
> +	 * to DISABLED
> +	 */
> +	ldr	r1, virt_mpu_clkctrl
> +	ldr	r2, [r1]
> +	bic	r2, r2, #0x03
Magic value
> +	str	r2, [r1]
> +
> +	/*
> +	 * Execute an ISB instruction to ensure that all of the
> +	 * CP15 register changes have been committed.
> +	 */
> +	isb
> +
> +	/*
> +	 * Execute a barrier instruction to ensure that all cache,
> +	 * TLB and branch predictor maintenance operations issued
> +	 * have completed.
> +	 */
> +	dsb
> +	dmb
> +
> +	/*
> +	 * Execute a WFI instruction and wait until the
> +	 * STANDBYWFI output is asserted to indicate that the
> +	 * CPU is in idle and low power state. CPU can specualatively
> +	 * prefetch the instructions so add NOPs after WFI. Thirteen
> +	 * NOPs as per Cortex-A8 pipeline.
> +	 */
> +	wfi
> +
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +
> +	/* We come here in case of an abort due to a late interrupt */
> +
> +	/* Set MPU_CLKCTRL.MODULEMODE back to ENABLE */
> +	ldr	r1, virt_mpu_clkctrl
> +	mov	r2, #0x02
> +	str	r2, [r1]
> +
> +	/* Re-enable EMIF */
> +	ldr	r1, virt_emif_clkctrl
> +	mov	r2, #0x02
> +	str	r2, [r1]
> +wait_emif_enable:
> +	ldr	r3, [r1]
> +	cmp	r2, r3
> +	bne	wait_emif_enable
> +
> +	/* Disable EMIF self-refresh */
> +	ldr	r0, emif_addr_virt
> +	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +	bic	r1, r1, #LP_MODE_MASK
> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
> +
> +	/*
> +	 * A write to SDRAM CONFIG register triggers
> +	 * an init sequence and hence it must be done
> +	 * at the end for DDR2
> +	 */
> +	ldr r0, emif_addr_virt
> +	add r0, r0, #EMIF_SDRAM_CONFIG
> +	ldr r4, emif_sdcfg_val
> +	str r4, [r0]
> +
> +	/*
> +	 * Set SCTLR.C bit to allow data cache allocation
> +	 */
> +	mrc	p15, 0, r0, c1, c0, 0
> +	orr	r0, r0, #(1 << 2)	@ Enable the C bit
> +	mcr	p15, 0, r0, c1, c0, 0
> +	isb
> +
> +	/* Kill some time for sanity to settle in */
Really ?
> +	mov r0, #0x1000
> +wait_abt:
> +	subs   r0, r0, #1
> +	bne wait_abt
Why do you want to kill time ? How
does this 0x1000 delay sanities it.

> +
> +	/* Let the suspend code know about the abort */
> +	mov	r0, #1
> +	ldmfd	sp!, {r4 - r11, pc}	@ restore regs and return
> +ENDPROC(am33xx_do_wfi)
> +
> +	.align
> +ENTRY(am33xx_resume_offset)
> +	.word . - am33xx_do_wfi
> +
> +ENTRY(am33xx_resume_from_deep_sleep)
> +	/* Re-enable EMIF */
> +	ldr	r0, phys_emif_clkctrl
> +	mov	r1, #0x02
> +	str	r1, [r0]
> +wait_emif_enable1:
> +	ldr	r2, [r0]
> +	cmp	r1, r2
> +	bne	wait_emif_enable1
> +
> +	/* Config EMIF Timings */
> +	ldr	r0, emif_phys_addr
> +	ldr	r1, emif_rd_lat_val
> +	str	r1, [r0, #EMIF_DDR_PHY_CTRL_1]
> +	str	r1, [r0, #EMIF_DDR_PHY_CTRL_1_SHDW]
> +	ldr	r1, emif_timing1_val
> +	str	r1, [r0, #EMIF_SDRAM_TIMING_1]
> +	str	r1, [r0, #EMIF_SDRAM_TIMING_1_SHDW]
> +	ldr	r1, emif_timing2_val
> +	str	r1, [r0, #EMIF_SDRAM_TIMING_2]
> +	str	r1, [r0, #EMIF_SDRAM_TIMING_2_SHDW]
> +	ldr	r1, emif_timing3_val
> +	str	r1, [r0, #EMIF_SDRAM_TIMING_3]
> +	str	r1, [r0, #EMIF_SDRAM_TIMING_3_SHDW]
> +	ldr	r1, emif_ref_ctrl_val
> +	str	r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
> +	str	r1, [r0, #EMIF_SDRAM_REFRESH_CTRL_SHDW]
> +	ldr	r1, emif_pmcr_val
> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +	ldr	r1, emif_pmcr_shdw_val
> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
> +
> +	/*
> +	 * Output impedence calib needed only for DDR3
> +	 * but since the initial state of this will be
> +	 * disabled for DDR2 no harm in restoring the
> +	 * old configuration
> +	 */
> +	ldr	r1, emif_zqcfg_val
> +	str	r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
> +
> +	/* Write to SDRAM_CONFIG only for DDR2 */
> +	ldr	r2, mem_type
> +	cmp	r2, #MEM_TYPE_DDR2
> +	bne	resume_to_ddr
> +
> +	/*
> +	 * A write to SDRAM CONFIG register triggers
> +	 * an init sequence and hence it must be done
> +	 * at the end for DDR2
> +	 */
> +	ldr	r1, emif_sdcfg_val
> +	str	r1, [r0, #EMIF_SDRAM_CONFIG]
> +
> +resume_to_ddr:
> +	/* Back from la-la-land. Kill some time for sanity to settle in */
> +	mov	r0, #0x1000
> +wait_resume:
> +	subs	r0, r0, #1
> +	bne	wait_resume
> +
You are killing too much time ;-)
without mentioning why ?

> +	/* We are back. Branch to the common CPU resume routine */
> +	mov	r0, #0
> +	ldr	pc, resume_addr
Why can't you resume to "cpu_resume" directly.

> +ENDPROC(am33xx_resume_from_deep_sleep)
> +
> +
> +/*
> + * Local variables
> + */
> +	.align
> +resume_addr:
> +	.word	cpu_resume - PAGE_OFFSET + 0x80000000
Do you really need above math ?

> +kernel_flush:
> +	.word   v7_flush_dcache_all
> +ddr_start:
> +	.word	PAGE_OFFSET
> +emif_phys_addr:
> +	.word	AM33XX_EMIF_BASE
> +virt_mpu_clkctrl:
> +	.word	AM33XX_CM_MPU_MPU_CLKCTRL
> +virt_emif_clkctrl:
> +	.word	AM33XX_CM_PER_EMIF_CLKCTRL
> +phys_emif_clkctrl:
> +	.word	(AM33XX_CM_BASE + AM33XX_CM_PER_MOD + \
> +		AM33XX_CM_PER_EMIF_CLKCTRL_OFFSET)
> +module_disabled_val:
> +	.word	0x30000
> +
> +/* DDR related defines */
> +dram_sync_word:
> +	.word	0xDEADBEEF
> +mem_type:
> +	.word	0xDEADBEEF
> +emif_addr_virt:
> +	.word	0xDEADBEEF
> +emif_rd_lat_val:
> +	.word	0xDEADBEEF
> +emif_timing1_val:
> +	.word	0xDEADBEEF
> +emif_timing2_val:
> +	.word	0xDEADBEEF
> +emif_timing3_val:
> +	.word	0xDEADBEEF
> +emif_sdcfg_val:
> +	.word	0xDEADBEEF
> +emif_ref_ctrl_val:
> +	.word	0xDEADBEEF
> +emif_zqcfg_val:
> +	.word	0xDEADBEEF
> +emif_pmcr_val:
> +	.word	0xDEADBEEF
> +emif_pmcr_shdw_val:
> +	.word	0xDEADBEEF
> +
You can create a structure above above regs.
refer 'cache-l2x0.h'  struct l2x0_regs in case
you need an example.


Looks like you don't care about secure devices ?
Just confirm it.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 5/9] ARM: OMAP2+: AM33XX: Add assembly code for PM operations
@ 2013-08-08 14:50     ` Santosh Shilimkar
  0 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 14:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
> 
> In preparation for suspend-resume support for AM33XX, add
> the assembly file with the code which is copied to internal
> memory (OCMC RAM) during bootup and runs from there.
> 
> As part of the low power entry (DeepSleep0 mode in AM33XX TRM),
> the code running from OCMC RAM does the following
> 1. Stores the EMIF configuration
> 2. Puts external memory in self-refresh
> 3. Disables EMIF clock
> 4. Executes WFI after writing to MPU_CLKCTRL register.
> 
> If no interrupts have come, WFI execution on MPU gets registered
> as an interrupt with the WKUP-M3. WKUP-M3 takes care of disabling
> some clocks which MPU should not (L3, L4, OCMC RAM etc) and takes
> care of clockdomain and powerdomain transitions as part of the
> DeepSleep0 mode entry.
> 
> In case a late interrupt comes in, WFI ends up as a NOP and MPU
> continues execution from internal memory. The 'abort path' code
> undoes whatever was done as part of the low power entry and indicates
> a suspend failure by passing a non-zero value to the cpu_resume routine.
> 
> The 'resume path' code is similar to the 'abort path' with the key
> difference of MMU being enabled in the 'abort path' but being
> disabled in the 'resume path' due to MPU getting powered off.
> 
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Kevin Hilman <khilman@linaro.org>
> ---
>  arch/arm/mach-omap2/sleep33xx.S |  350 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 350 insertions(+)
>  create mode 100644 arch/arm/mach-omap2/sleep33xx.S
> 
> diff --git a/arch/arm/mach-omap2/sleep33xx.S b/arch/arm/mach-omap2/sleep33xx.S
> new file mode 100644
> index 0000000..834c7d4
> --- /dev/null
> +++ b/arch/arm/mach-omap2/sleep33xx.S
> @@ -0,0 +1,350 @@
> +/*
> + * Low level suspend code for AM33XX SoCs
> + *
> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
> + * Vaibhav Bedia <vaibhav.bedia@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/linkage.h>
> +#include <linux/ti_emif.h>
> +#include <asm/memory.h>
> +#include <asm/assembler.h>
> +
> +#include "cm33xx.h"
> +#include "pm33xx.h"
> +#include "prm33xx.h"
> +
> +	.text
> +	.align 3
> +
> +/*
> + * This routine is executed from internal RAM and expects some
> + * parameters to be passed in r0 _strictly_ in following order:
> + * 1) emif_addr_virt - ioremapped EMIF address
> + * 2) mem_type - 2 -> DDR2, 3-> DDR3
> + * 3) dram_sync_word - uncached word in SDRAM
> + *
> + * The code loads these values taking r0 value as reference to
> + * the array in registers starting from r0, i.e emif_addr_virt
> + * goes to r1, mem_type goes to r2 and and so on. These are
> + * then saved into memory locations before proceeding with the
> + * sleep sequence and hence registers r0, r1 etc can still be
> + * used in the rest of the sleep code.
> + */
> +
> +ENTRY(am33xx_do_wfi)
> +	stmfd	sp!, {r4 - r11, lr}	@ save registers on stack
> +
> +	ldm	r0, {r1-r3}		@ gather values passed
> +
> +	/* Save the values passed */
> +	str	r1, emif_addr_virt
> +	str	r2, mem_type
> +	str	r3, dram_sync_word

None of this parameter are going to change for every suspend entry and
exit so saving them once and accessing them should be fine. Just
create a structure with above, save them in init from C code and
then access that structure where you need to.

> +
> +	/*
> +	 * Flush all data from the L1 data cache before disabling
> +	 * SCTLR.C bit.
> +	 */
> +	ldr	r1, kernel_flush
> +	blx	r1
> +
> +	/*
> +	 * Clear the SCTLR.C bit to prevent further data cache
> +	 * allocation. Clearing SCTLR.C would make all the data accesses
> +	 * strongly ordered and would not hit the cache.
> +	 */
> +	mrc	p15, 0, r0, c1, c0, 0
> +	bic	r0, r0, #(1 << 2)	@ Disable the C bit
> +	mcr	p15, 0, r0, c1, c0, 0
> +	isb
> +
> +	/*
> +	 * Invalidate L1 data cache. Even though only invalidate is
> +	 * necessary exported flush API is used here. Doing clean
> +	 * on already clean cache would be almost NOP.
> +	 */
Comment is stale for AM33XX since below flush will clean l1 and l2
together. We need to first flush and then invalidate. Please update it.
> +	ldr	r1, kernel_flush
> +	blx	r1
> +
> +	ldr	r0, emif_addr_virt
> +	/* Save EMIF configuration */
> +	ldr	r1, [r0, #EMIF_SDRAM_CONFIG]
> +	str	r1, emif_sdcfg_val
> +	ldr	r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
> +	str	r1, emif_ref_ctrl_val
> +	ldr	r1, [r0, #EMIF_SDRAM_TIMING_1]
> +	str	r1, emif_timing1_val
> +	ldr	r1, [r0, #EMIF_SDRAM_TIMING_2]
> +	str	r1, emif_timing2_val
> +	ldr	r1, [r0, #EMIF_SDRAM_TIMING_3]
> +	str	r1, emif_timing3_val
> +	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +	str	r1, emif_pmcr_val
> +	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
> +	str	r1, emif_pmcr_shdw_val
> +	ldr	r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
> +	str	r1, emif_zqcfg_val
> +	ldr	r1, [r0, #EMIF_DDR_PHY_CTRL_1]
> +	str	r1, emif_rd_lat_val
> +
> +	/* Put SDRAM in self-refresh */
> +	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +	orr	r1, r1, #0xa0
No magic numbers please. here and rest of the patch. Have proper
defines.

> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
> +	str	r1, [r0, #4]
> +
> +	ldr	r1, dram_sync_word	@ a dummy access to DDR as per spec
> +	ldr	r2, [r1, #0]
> +	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +	orr	r1, r1, #0x200
> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +
> +	mov	r1, #0x1000		@ Wait for system to enter SR
> +wait_sr:
What is sr ? I know you mean self-refresh, but sr can be smart reflex
as well. Fix that please.
> +	subs	r1, r1, #1
> +	bne	wait_sr
> +
So how did you derive this 0x1000 number. Whats the real
delay need ? For e.g a CPU running at 600 MHz vs running
at 1.2 GHz, the above loop becomes 2 times faster.

> +	/* Disable EMIF */
> +	ldr	r1, virt_emif_clkctrl
> +	ldr	r2, [r1]
> +	bic	r2, r2, #0x03
> +	str	r2, [r1]
> +
> +	ldr	r1, virt_emif_clkctrl
> +wait_emif_disable:
> +	ldr	r2, [r1]
> +	ldr	r3, module_disabled_val
> +	cmp	r2, r3
> +	bne	wait_emif_disable
> +
> +	/*
> +	 * For the MPU WFI to be registered as an interrupt
> +	 * to WKUP_M3, MPU_CLKCTRL.MODULEMODE needs to be set
> +	 * to DISABLED
> +	 */
> +	ldr	r1, virt_mpu_clkctrl
> +	ldr	r2, [r1]
> +	bic	r2, r2, #0x03
Magic value
> +	str	r2, [r1]
> +
> +	/*
> +	 * Execute an ISB instruction to ensure that all of the
> +	 * CP15 register changes have been committed.
> +	 */
> +	isb
> +
> +	/*
> +	 * Execute a barrier instruction to ensure that all cache,
> +	 * TLB and branch predictor maintenance operations issued
> +	 * have completed.
> +	 */
> +	dsb
> +	dmb
> +
> +	/*
> +	 * Execute a WFI instruction and wait until the
> +	 * STANDBYWFI output is asserted to indicate that the
> +	 * CPU is in idle and low power state. CPU can specualatively
> +	 * prefetch the instructions so add NOPs after WFI. Thirteen
> +	 * NOPs as per Cortex-A8 pipeline.
> +	 */
> +	wfi
> +
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +
> +	/* We come here in case of an abort due to a late interrupt */
> +
> +	/* Set MPU_CLKCTRL.MODULEMODE back to ENABLE */
> +	ldr	r1, virt_mpu_clkctrl
> +	mov	r2, #0x02
> +	str	r2, [r1]
> +
> +	/* Re-enable EMIF */
> +	ldr	r1, virt_emif_clkctrl
> +	mov	r2, #0x02
> +	str	r2, [r1]
> +wait_emif_enable:
> +	ldr	r3, [r1]
> +	cmp	r2, r3
> +	bne	wait_emif_enable
> +
> +	/* Disable EMIF self-refresh */
> +	ldr	r0, emif_addr_virt
> +	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +	bic	r1, r1, #LP_MODE_MASK
> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
> +
> +	/*
> +	 * A write to SDRAM CONFIG register triggers
> +	 * an init sequence and hence it must be done
> +	 * at the end for DDR2
> +	 */
> +	ldr r0, emif_addr_virt
> +	add r0, r0, #EMIF_SDRAM_CONFIG
> +	ldr r4, emif_sdcfg_val
> +	str r4, [r0]
> +
> +	/*
> +	 * Set SCTLR.C bit to allow data cache allocation
> +	 */
> +	mrc	p15, 0, r0, c1, c0, 0
> +	orr	r0, r0, #(1 << 2)	@ Enable the C bit
> +	mcr	p15, 0, r0, c1, c0, 0
> +	isb
> +
> +	/* Kill some time for sanity to settle in */
Really ?
> +	mov r0, #0x1000
> +wait_abt:
> +	subs   r0, r0, #1
> +	bne wait_abt
Why do you want to kill time ? How
does this 0x1000 delay sanities it.

> +
> +	/* Let the suspend code know about the abort */
> +	mov	r0, #1
> +	ldmfd	sp!, {r4 - r11, pc}	@ restore regs and return
> +ENDPROC(am33xx_do_wfi)
> +
> +	.align
> +ENTRY(am33xx_resume_offset)
> +	.word . - am33xx_do_wfi
> +
> +ENTRY(am33xx_resume_from_deep_sleep)
> +	/* Re-enable EMIF */
> +	ldr	r0, phys_emif_clkctrl
> +	mov	r1, #0x02
> +	str	r1, [r0]
> +wait_emif_enable1:
> +	ldr	r2, [r0]
> +	cmp	r1, r2
> +	bne	wait_emif_enable1
> +
> +	/* Config EMIF Timings */
> +	ldr	r0, emif_phys_addr
> +	ldr	r1, emif_rd_lat_val
> +	str	r1, [r0, #EMIF_DDR_PHY_CTRL_1]
> +	str	r1, [r0, #EMIF_DDR_PHY_CTRL_1_SHDW]
> +	ldr	r1, emif_timing1_val
> +	str	r1, [r0, #EMIF_SDRAM_TIMING_1]
> +	str	r1, [r0, #EMIF_SDRAM_TIMING_1_SHDW]
> +	ldr	r1, emif_timing2_val
> +	str	r1, [r0, #EMIF_SDRAM_TIMING_2]
> +	str	r1, [r0, #EMIF_SDRAM_TIMING_2_SHDW]
> +	ldr	r1, emif_timing3_val
> +	str	r1, [r0, #EMIF_SDRAM_TIMING_3]
> +	str	r1, [r0, #EMIF_SDRAM_TIMING_3_SHDW]
> +	ldr	r1, emif_ref_ctrl_val
> +	str	r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
> +	str	r1, [r0, #EMIF_SDRAM_REFRESH_CTRL_SHDW]
> +	ldr	r1, emif_pmcr_val
> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +	ldr	r1, emif_pmcr_shdw_val
> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
> +
> +	/*
> +	 * Output impedence calib needed only for DDR3
> +	 * but since the initial state of this will be
> +	 * disabled for DDR2 no harm in restoring the
> +	 * old configuration
> +	 */
> +	ldr	r1, emif_zqcfg_val
> +	str	r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
> +
> +	/* Write to SDRAM_CONFIG only for DDR2 */
> +	ldr	r2, mem_type
> +	cmp	r2, #MEM_TYPE_DDR2
> +	bne	resume_to_ddr
> +
> +	/*
> +	 * A write to SDRAM CONFIG register triggers
> +	 * an init sequence and hence it must be done
> +	 * at the end for DDR2
> +	 */
> +	ldr	r1, emif_sdcfg_val
> +	str	r1, [r0, #EMIF_SDRAM_CONFIG]
> +
> +resume_to_ddr:
> +	/* Back from la-la-land. Kill some time for sanity to settle in */
> +	mov	r0, #0x1000
> +wait_resume:
> +	subs	r0, r0, #1
> +	bne	wait_resume
> +
You are killing too much time ;-)
without mentioning why ?

> +	/* We are back. Branch to the common CPU resume routine */
> +	mov	r0, #0
> +	ldr	pc, resume_addr
Why can't you resume to "cpu_resume" directly.

> +ENDPROC(am33xx_resume_from_deep_sleep)
> +
> +
> +/*
> + * Local variables
> + */
> +	.align
> +resume_addr:
> +	.word	cpu_resume - PAGE_OFFSET + 0x80000000
Do you really need above math ?

> +kernel_flush:
> +	.word   v7_flush_dcache_all
> +ddr_start:
> +	.word	PAGE_OFFSET
> +emif_phys_addr:
> +	.word	AM33XX_EMIF_BASE
> +virt_mpu_clkctrl:
> +	.word	AM33XX_CM_MPU_MPU_CLKCTRL
> +virt_emif_clkctrl:
> +	.word	AM33XX_CM_PER_EMIF_CLKCTRL
> +phys_emif_clkctrl:
> +	.word	(AM33XX_CM_BASE + AM33XX_CM_PER_MOD + \
> +		AM33XX_CM_PER_EMIF_CLKCTRL_OFFSET)
> +module_disabled_val:
> +	.word	0x30000
> +
> +/* DDR related defines */
> +dram_sync_word:
> +	.word	0xDEADBEEF
> +mem_type:
> +	.word	0xDEADBEEF
> +emif_addr_virt:
> +	.word	0xDEADBEEF
> +emif_rd_lat_val:
> +	.word	0xDEADBEEF
> +emif_timing1_val:
> +	.word	0xDEADBEEF
> +emif_timing2_val:
> +	.word	0xDEADBEEF
> +emif_timing3_val:
> +	.word	0xDEADBEEF
> +emif_sdcfg_val:
> +	.word	0xDEADBEEF
> +emif_ref_ctrl_val:
> +	.word	0xDEADBEEF
> +emif_zqcfg_val:
> +	.word	0xDEADBEEF
> +emif_pmcr_val:
> +	.word	0xDEADBEEF
> +emif_pmcr_shdw_val:
> +	.word	0xDEADBEEF
> +
You can create a structure above above regs.
refer 'cache-l2x0.h'  struct l2x0_regs in case
you need an example.


Looks like you don't care about secure devices ?
Just confirm it.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 9/9] ARM: OMAP2+: AM33XX: Hookup AM33XX PM code into OMAP builds
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08 14:53     ` Santosh Shilimkar
  -1 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 14:53 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman, Vaibhav Bedia

On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
> 
> With all the requisite changes in place we can now
> enable the basic PM support for AM335x. This patch
> updates the various OMAP files to enable suspend-resume
> on AM335x.
> 
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> ---
>  arch/arm/mach-omap2/Kconfig         |    7 +++++--
>  arch/arm/mach-omap2/Makefile        |    2 ++
>  arch/arm/mach-omap2/board-generic.c |    1 +
>  arch/arm/mach-omap2/common.h        |   10 ++++++++++
>  arch/arm/mach-omap2/io.c            |    5 +++++
>  arch/arm/mach-omap2/pm.c            |    3 ++-
>  arch/arm/mach-omap2/pm.h            |    5 +++++
>  arch/arm/mach-omap2/sram.c          |   10 +++++++++-
>  arch/arm/mach-omap2/sram.h          |    2 ++
>  9 files changed, 41 insertions(+), 4 deletions(-)
> 
The patch looks fine but too many changes in one patch
than my liking. No strong preference though.

Acked-by: Santosh Shilikar<santosh.shilimkar@ti.com>


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 9/9] ARM: OMAP2+: AM33XX: Hookup AM33XX PM code into OMAP builds
@ 2013-08-08 14:53     ` Santosh Shilimkar
  0 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 14:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
> 
> With all the requisite changes in place we can now
> enable the basic PM support for AM335x. This patch
> updates the various OMAP files to enable suspend-resume
> on AM335x.
> 
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> ---
>  arch/arm/mach-omap2/Kconfig         |    7 +++++--
>  arch/arm/mach-omap2/Makefile        |    2 ++
>  arch/arm/mach-omap2/board-generic.c |    1 +
>  arch/arm/mach-omap2/common.h        |   10 ++++++++++
>  arch/arm/mach-omap2/io.c            |    5 +++++
>  arch/arm/mach-omap2/pm.c            |    3 ++-
>  arch/arm/mach-omap2/pm.h            |    5 +++++
>  arch/arm/mach-omap2/sram.c          |   10 +++++++++-
>  arch/arm/mach-omap2/sram.h          |    2 ++
>  9 files changed, 41 insertions(+), 4 deletions(-)
> 
The patch looks fine but too many changes in one patch
than my liking. No strong preference though.

Acked-by: Santosh Shilikar<santosh.shilimkar@ti.com>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-08 12:26       ` Nishanth Menon
@ 2013-08-08 15:03         ` Santosh Shilimkar
  -1 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 15:03 UTC (permalink / raw)
  To: Nishanth Menon
  Cc: Paul Walmsley, Kevin Hilman, Dave Gerlach, Russ Dill,
	Vaibhav Bedia, Tony Lingren, Benoit Cousson, linux-omap,
	linux-arm-kernel

$subject and patch don't match.

On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>   In reference to
>> the M3 handling it, the M3 wouldn't know which devices have a driver
>> bound and which don't.
> Does it need to? M3 firmware can pretty much define "I will force the device into low power state, and if the drivers dont handle things properly, fix the darned driver". M3 behavior should be considered as a "hardware" as far as Linux running on MPU is concerned, and firmware helps change the behavior by accounting for SoC quirks. *if* we have ability to handle this in the firmware, there is no need to carry this in Linux.
> 
I agree with Nishant. I don't like this patch and IIRC, I gave same
comment in the last version. Linux need not know about all such firmware
quirks. Also all these M3 specific stuff, should be done somewhere
else. Probably having a small M3 driver won't be a bad idea.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-08 15:03         ` Santosh Shilimkar
  0 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 15:03 UTC (permalink / raw)
  To: linux-arm-kernel

$subject and patch don't match.

On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>   In reference to
>> the M3 handling it, the M3 wouldn't know which devices have a driver
>> bound and which don't.
> Does it need to? M3 firmware can pretty much define "I will force the device into low power state, and if the drivers dont handle things properly, fix the darned driver". M3 behavior should be considered as a "hardware" as far as Linux running on MPU is concerned, and firmware helps change the behavior by accounting for SoC quirks. *if* we have ability to handle this in the firmware, there is no need to carry this in Linux.
> 
I agree with Nishant. I don't like this patch and IIRC, I gave same
comment in the last version. Linux need not know about all such firmware
quirks. Also all these M3 specific stuff, should be done somewhere
else. Probably having a small M3 driver won't be a bad idea.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 5/9] ARM: OMAP2+: AM33XX: Add assembly code for PM operations
  2013-08-08 14:50     ` Santosh Shilimkar
@ 2013-08-08 15:16       ` Russ Dill
  -1 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08 15:16 UTC (permalink / raw)
  To: Santosh Shilimkar
  Cc: Dave Gerlach, Kevin Hilman, Paul Walmsley, linux-omap,
	Vaibhav Bedia, linux-arm-kernel

On Thu, Aug 8, 2013 at 7:50 AM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
> On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>
>> In preparation for suspend-resume support for AM33XX, add
>> the assembly file with the code which is copied to internal
>> memory (OCMC RAM) during bootup and runs from there.
>>
>> As part of the low power entry (DeepSleep0 mode in AM33XX TRM),
>> the code running from OCMC RAM does the following
>> 1. Stores the EMIF configuration
>> 2. Puts external memory in self-refresh
>> 3. Disables EMIF clock
>> 4. Executes WFI after writing to MPU_CLKCTRL register.
>>
>> If no interrupts have come, WFI execution on MPU gets registered
>> as an interrupt with the WKUP-M3. WKUP-M3 takes care of disabling
>> some clocks which MPU should not (L3, L4, OCMC RAM etc) and takes
>> care of clockdomain and powerdomain transitions as part of the
>> DeepSleep0 mode entry.
>>
>> In case a late interrupt comes in, WFI ends up as a NOP and MPU
>> continues execution from internal memory. The 'abort path' code
>> undoes whatever was done as part of the low power entry and indicates
>> a suspend failure by passing a non-zero value to the cpu_resume routine.
>>
>> The 'resume path' code is similar to the 'abort path' with the key
>> difference of MMU being enabled in the 'abort path' but being
>> disabled in the 'resume path' due to MPU getting powered off.
>>
>> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>> Cc: Kevin Hilman <khilman@linaro.org>
>> ---
>>  arch/arm/mach-omap2/sleep33xx.S |  350 +++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 350 insertions(+)
>>  create mode 100644 arch/arm/mach-omap2/sleep33xx.S
>>
>> diff --git a/arch/arm/mach-omap2/sleep33xx.S b/arch/arm/mach-omap2/sleep33xx.S
>> new file mode 100644
>> index 0000000..834c7d4
>> --- /dev/null
>> +++ b/arch/arm/mach-omap2/sleep33xx.S
>> @@ -0,0 +1,350 @@
>> +/*
>> + * Low level suspend code for AM33XX SoCs
>> + *
>> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
>> + * Vaibhav Bedia <vaibhav.bedia@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/linkage.h>
>> +#include <linux/ti_emif.h>
>> +#include <asm/memory.h>
>> +#include <asm/assembler.h>
>> +
>> +#include "cm33xx.h"
>> +#include "pm33xx.h"
>> +#include "prm33xx.h"
>> +
>> +     .text
>> +     .align 3
>> +
>> +/*
>> + * This routine is executed from internal RAM and expects some
>> + * parameters to be passed in r0 _strictly_ in following order:
>> + * 1) emif_addr_virt - ioremapped EMIF address
>> + * 2) mem_type - 2 -> DDR2, 3-> DDR3
>> + * 3) dram_sync_word - uncached word in SDRAM
>> + *
>> + * The code loads these values taking r0 value as reference to
>> + * the array in registers starting from r0, i.e emif_addr_virt
>> + * goes to r1, mem_type goes to r2 and and so on. These are
>> + * then saved into memory locations before proceeding with the
>> + * sleep sequence and hence registers r0, r1 etc can still be
>> + * used in the rest of the sleep code.
>> + */
>> +
>> +ENTRY(am33xx_do_wfi)
>> +     stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
>> +
>> +     ldm     r0, {r1-r3}             @ gather values passed
>> +
>> +     /* Save the values passed */
>> +     str     r1, emif_addr_virt
>> +     str     r2, mem_type
>> +     str     r3, dram_sync_word
>
> None of this parameter are going to change for every suspend entry and
> exit so saving them once and accessing them should be fine. Just
> create a structure with above, save them in init from C code and
> then access that structure where you need to.

It isn't possible to do so since the structure would be in SDRAM and
at resume time, we don't have access to SDRAM. Additionally, I'd like
to expand the mem_type parameter to a bit field in the future to allow
this code path to be shared with CPU idle.

>> +
>> +     /*
>> +      * Flush all data from the L1 data cache before disabling
>> +      * SCTLR.C bit.
>> +      */
>> +     ldr     r1, kernel_flush
>> +     blx     r1
>> +
>> +     /*
>> +      * Clear the SCTLR.C bit to prevent further data cache
>> +      * allocation. Clearing SCTLR.C would make all the data accesses
>> +      * strongly ordered and would not hit the cache.
>> +      */
>> +     mrc     p15, 0, r0, c1, c0, 0
>> +     bic     r0, r0, #(1 << 2)       @ Disable the C bit
>> +     mcr     p15, 0, r0, c1, c0, 0
>> +     isb
>> +
>> +     /*
>> +      * Invalidate L1 data cache. Even though only invalidate is
>> +      * necessary exported flush API is used here. Doing clean
>> +      * on already clean cache would be almost NOP.
>> +      */
> Comment is stale for AM33XX since below flush will clean l1 and l2
> together. We need to first flush and then invalidate. Please update it.
>> +     ldr     r1, kernel_flush
>> +     blx     r1
>> +
>> +     ldr     r0, emif_addr_virt
>> +     /* Save EMIF configuration */
>> +     ldr     r1, [r0, #EMIF_SDRAM_CONFIG]
>> +     str     r1, emif_sdcfg_val
>> +     ldr     r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
>> +     str     r1, emif_ref_ctrl_val
>> +     ldr     r1, [r0, #EMIF_SDRAM_TIMING_1]
>> +     str     r1, emif_timing1_val
>> +     ldr     r1, [r0, #EMIF_SDRAM_TIMING_2]
>> +     str     r1, emif_timing2_val
>> +     ldr     r1, [r0, #EMIF_SDRAM_TIMING_3]
>> +     str     r1, emif_timing3_val
>> +     ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
>> +     str     r1, emif_pmcr_val
>> +     ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
>> +     str     r1, emif_pmcr_shdw_val
>> +     ldr     r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
>> +     str     r1, emif_zqcfg_val
>> +     ldr     r1, [r0, #EMIF_DDR_PHY_CTRL_1]
>> +     str     r1, emif_rd_lat_val
>> +
>> +     /* Put SDRAM in self-refresh */
>> +     ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
>> +     orr     r1, r1, #0xa0
> No magic numbers please. here and rest of the patch. Have proper
> defines.
>
>> +     str     r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
>> +     str     r1, [r0, #4]
>> +
>> +     ldr     r1, dram_sync_word      @ a dummy access to DDR as per spec
>> +     ldr     r2, [r1, #0]
>> +     ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
>> +     orr     r1, r1, #0x200
>> +     str     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
>> +
>> +     mov     r1, #0x1000             @ Wait for system to enter SR
>> +wait_sr:
> What is sr ? I know you mean self-refresh, but sr can be smart reflex
> as well. Fix that please.
>> +     subs    r1, r1, #1
>> +     bne     wait_sr
>> +
> So how did you derive this 0x1000 number. Whats the real
> delay need ? For e.g a CPU running at 600 MHz vs running
> at 1.2 GHz, the above loop becomes 2 times faster.
>
>> +     /* Disable EMIF */
>> +     ldr     r1, virt_emif_clkctrl
>> +     ldr     r2, [r1]
>> +     bic     r2, r2, #0x03
>> +     str     r2, [r1]
>> +
>> +     ldr     r1, virt_emif_clkctrl
>> +wait_emif_disable:
>> +     ldr     r2, [r1]
>> +     ldr     r3, module_disabled_val
>> +     cmp     r2, r3
>> +     bne     wait_emif_disable
>> +
>> +     /*
>> +      * For the MPU WFI to be registered as an interrupt
>> +      * to WKUP_M3, MPU_CLKCTRL.MODULEMODE needs to be set
>> +      * to DISABLED
>> +      */
>> +     ldr     r1, virt_mpu_clkctrl
>> +     ldr     r2, [r1]
>> +     bic     r2, r2, #0x03
> Magic value
>> +     str     r2, [r1]
>> +
>> +     /*
>> +      * Execute an ISB instruction to ensure that all of the
>> +      * CP15 register changes have been committed.
>> +      */
>> +     isb
>> +
>> +     /*
>> +      * Execute a barrier instruction to ensure that all cache,
>> +      * TLB and branch predictor maintenance operations issued
>> +      * have completed.
>> +      */
>> +     dsb
>> +     dmb
>> +
>> +     /*
>> +      * Execute a WFI instruction and wait until the
>> +      * STANDBYWFI output is asserted to indicate that the
>> +      * CPU is in idle and low power state. CPU can specualatively
>> +      * prefetch the instructions so add NOPs after WFI. Thirteen
>> +      * NOPs as per Cortex-A8 pipeline.
>> +      */
>> +     wfi
>> +
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +
>> +     /* We come here in case of an abort due to a late interrupt */
>> +
>> +     /* Set MPU_CLKCTRL.MODULEMODE back to ENABLE */
>> +     ldr     r1, virt_mpu_clkctrl
>> +     mov     r2, #0x02
>> +     str     r2, [r1]
>> +
>> +     /* Re-enable EMIF */
>> +     ldr     r1, virt_emif_clkctrl
>> +     mov     r2, #0x02
>> +     str     r2, [r1]
>> +wait_emif_enable:
>> +     ldr     r3, [r1]
>> +     cmp     r2, r3
>> +     bne     wait_emif_enable
>> +
>> +     /* Disable EMIF self-refresh */
>> +     ldr     r0, emif_addr_virt
>> +     ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
>> +     bic     r1, r1, #LP_MODE_MASK
>> +     str     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
>> +     str     r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
>> +
>> +     /*
>> +      * A write to SDRAM CONFIG register triggers
>> +      * an init sequence and hence it must be done
>> +      * at the end for DDR2
>> +      */
>> +     ldr r0, emif_addr_virt
>> +     add r0, r0, #EMIF_SDRAM_CONFIG
>> +     ldr r4, emif_sdcfg_val
>> +     str r4, [r0]
>> +
>> +     /*
>> +      * Set SCTLR.C bit to allow data cache allocation
>> +      */
>> +     mrc     p15, 0, r0, c1, c0, 0
>> +     orr     r0, r0, #(1 << 2)       @ Enable the C bit
>> +     mcr     p15, 0, r0, c1, c0, 0
>> +     isb
>> +
>> +     /* Kill some time for sanity to settle in */
> Really ?
>> +     mov r0, #0x1000
>> +wait_abt:
>> +     subs   r0, r0, #1
>> +     bne wait_abt
> Why do you want to kill time ? How
> does this 0x1000 delay sanities it.
>
>> +
>> +     /* Let the suspend code know about the abort */
>> +     mov     r0, #1
>> +     ldmfd   sp!, {r4 - r11, pc}     @ restore regs and return
>> +ENDPROC(am33xx_do_wfi)
>> +
>> +     .align
>> +ENTRY(am33xx_resume_offset)
>> +     .word . - am33xx_do_wfi
>> +
>> +ENTRY(am33xx_resume_from_deep_sleep)
>> +     /* Re-enable EMIF */
>> +     ldr     r0, phys_emif_clkctrl
>> +     mov     r1, #0x02
>> +     str     r1, [r0]
>> +wait_emif_enable1:
>> +     ldr     r2, [r0]
>> +     cmp     r1, r2
>> +     bne     wait_emif_enable1
>> +
>> +     /* Config EMIF Timings */
>> +     ldr     r0, emif_phys_addr
>> +     ldr     r1, emif_rd_lat_val
>> +     str     r1, [r0, #EMIF_DDR_PHY_CTRL_1]
>> +     str     r1, [r0, #EMIF_DDR_PHY_CTRL_1_SHDW]
>> +     ldr     r1, emif_timing1_val
>> +     str     r1, [r0, #EMIF_SDRAM_TIMING_1]
>> +     str     r1, [r0, #EMIF_SDRAM_TIMING_1_SHDW]
>> +     ldr     r1, emif_timing2_val
>> +     str     r1, [r0, #EMIF_SDRAM_TIMING_2]
>> +     str     r1, [r0, #EMIF_SDRAM_TIMING_2_SHDW]
>> +     ldr     r1, emif_timing3_val
>> +     str     r1, [r0, #EMIF_SDRAM_TIMING_3]
>> +     str     r1, [r0, #EMIF_SDRAM_TIMING_3_SHDW]
>> +     ldr     r1, emif_ref_ctrl_val
>> +     str     r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
>> +     str     r1, [r0, #EMIF_SDRAM_REFRESH_CTRL_SHDW]
>> +     ldr     r1, emif_pmcr_val
>> +     str     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
>> +     ldr     r1, emif_pmcr_shdw_val
>> +     str     r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
>> +
>> +     /*
>> +      * Output impedence calib needed only for DDR3
>> +      * but since the initial state of this will be
>> +      * disabled for DDR2 no harm in restoring the
>> +      * old configuration
>> +      */
>> +     ldr     r1, emif_zqcfg_val
>> +     str     r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
>> +
>> +     /* Write to SDRAM_CONFIG only for DDR2 */
>> +     ldr     r2, mem_type
>> +     cmp     r2, #MEM_TYPE_DDR2
>> +     bne     resume_to_ddr
>> +
>> +     /*
>> +      * A write to SDRAM CONFIG register triggers
>> +      * an init sequence and hence it must be done
>> +      * at the end for DDR2
>> +      */
>> +     ldr     r1, emif_sdcfg_val
>> +     str     r1, [r0, #EMIF_SDRAM_CONFIG]
>> +
>> +resume_to_ddr:
>> +     /* Back from la-la-land. Kill some time for sanity to settle in */
>> +     mov     r0, #0x1000
>> +wait_resume:
>> +     subs    r0, r0, #1
>> +     bne     wait_resume
>> +
> You are killing too much time ;-)
> without mentioning why ?
>
>> +     /* We are back. Branch to the common CPU resume routine */
>> +     mov     r0, #0
>> +     ldr     pc, resume_addr
> Why can't you resume to "cpu_resume" directly.
>
>> +ENDPROC(am33xx_resume_from_deep_sleep)
>> +
>> +
>> +/*
>> + * Local variables
>> + */
>> +     .align
>> +resume_addr:
>> +     .word   cpu_resume - PAGE_OFFSET + 0x80000000
> Do you really need above math ?
>
>> +kernel_flush:
>> +     .word   v7_flush_dcache_all
>> +ddr_start:
>> +     .word   PAGE_OFFSET
>> +emif_phys_addr:
>> +     .word   AM33XX_EMIF_BASE
>> +virt_mpu_clkctrl:
>> +     .word   AM33XX_CM_MPU_MPU_CLKCTRL
>> +virt_emif_clkctrl:
>> +     .word   AM33XX_CM_PER_EMIF_CLKCTRL
>> +phys_emif_clkctrl:
>> +     .word   (AM33XX_CM_BASE + AM33XX_CM_PER_MOD + \
>> +             AM33XX_CM_PER_EMIF_CLKCTRL_OFFSET)
>> +module_disabled_val:
>> +     .word   0x30000
>> +
>> +/* DDR related defines */
>> +dram_sync_word:
>> +     .word   0xDEADBEEF
>> +mem_type:
>> +     .word   0xDEADBEEF
>> +emif_addr_virt:
>> +     .word   0xDEADBEEF
>> +emif_rd_lat_val:
>> +     .word   0xDEADBEEF
>> +emif_timing1_val:
>> +     .word   0xDEADBEEF
>> +emif_timing2_val:
>> +     .word   0xDEADBEEF
>> +emif_timing3_val:
>> +     .word   0xDEADBEEF
>> +emif_sdcfg_val:
>> +     .word   0xDEADBEEF
>> +emif_ref_ctrl_val:
>> +     .word   0xDEADBEEF
>> +emif_zqcfg_val:
>> +     .word   0xDEADBEEF
>> +emif_pmcr_val:
>> +     .word   0xDEADBEEF
>> +emif_pmcr_shdw_val:
>> +     .word   0xDEADBEEF
>> +
> You can create a structure above above regs.
> refer 'cache-l2x0.h'  struct l2x0_regs in case
> you need an example.
>
>
> Looks like you don't care about secure devices ?
> Just confirm it.
>
> Regards,
> Santosh
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 5/9] ARM: OMAP2+: AM33XX: Add assembly code for PM operations
@ 2013-08-08 15:16       ` Russ Dill
  0 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08 15:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 8, 2013 at 7:50 AM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
> On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>
>> In preparation for suspend-resume support for AM33XX, add
>> the assembly file with the code which is copied to internal
>> memory (OCMC RAM) during bootup and runs from there.
>>
>> As part of the low power entry (DeepSleep0 mode in AM33XX TRM),
>> the code running from OCMC RAM does the following
>> 1. Stores the EMIF configuration
>> 2. Puts external memory in self-refresh
>> 3. Disables EMIF clock
>> 4. Executes WFI after writing to MPU_CLKCTRL register.
>>
>> If no interrupts have come, WFI execution on MPU gets registered
>> as an interrupt with the WKUP-M3. WKUP-M3 takes care of disabling
>> some clocks which MPU should not (L3, L4, OCMC RAM etc) and takes
>> care of clockdomain and powerdomain transitions as part of the
>> DeepSleep0 mode entry.
>>
>> In case a late interrupt comes in, WFI ends up as a NOP and MPU
>> continues execution from internal memory. The 'abort path' code
>> undoes whatever was done as part of the low power entry and indicates
>> a suspend failure by passing a non-zero value to the cpu_resume routine.
>>
>> The 'resume path' code is similar to the 'abort path' with the key
>> difference of MMU being enabled in the 'abort path' but being
>> disabled in the 'resume path' due to MPU getting powered off.
>>
>> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>> Cc: Kevin Hilman <khilman@linaro.org>
>> ---
>>  arch/arm/mach-omap2/sleep33xx.S |  350 +++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 350 insertions(+)
>>  create mode 100644 arch/arm/mach-omap2/sleep33xx.S
>>
>> diff --git a/arch/arm/mach-omap2/sleep33xx.S b/arch/arm/mach-omap2/sleep33xx.S
>> new file mode 100644
>> index 0000000..834c7d4
>> --- /dev/null
>> +++ b/arch/arm/mach-omap2/sleep33xx.S
>> @@ -0,0 +1,350 @@
>> +/*
>> + * Low level suspend code for AM33XX SoCs
>> + *
>> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
>> + * Vaibhav Bedia <vaibhav.bedia@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/linkage.h>
>> +#include <linux/ti_emif.h>
>> +#include <asm/memory.h>
>> +#include <asm/assembler.h>
>> +
>> +#include "cm33xx.h"
>> +#include "pm33xx.h"
>> +#include "prm33xx.h"
>> +
>> +     .text
>> +     .align 3
>> +
>> +/*
>> + * This routine is executed from internal RAM and expects some
>> + * parameters to be passed in r0 _strictly_ in following order:
>> + * 1) emif_addr_virt - ioremapped EMIF address
>> + * 2) mem_type - 2 -> DDR2, 3-> DDR3
>> + * 3) dram_sync_word - uncached word in SDRAM
>> + *
>> + * The code loads these values taking r0 value as reference to
>> + * the array in registers starting from r0, i.e emif_addr_virt
>> + * goes to r1, mem_type goes to r2 and and so on. These are
>> + * then saved into memory locations before proceeding with the
>> + * sleep sequence and hence registers r0, r1 etc can still be
>> + * used in the rest of the sleep code.
>> + */
>> +
>> +ENTRY(am33xx_do_wfi)
>> +     stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
>> +
>> +     ldm     r0, {r1-r3}             @ gather values passed
>> +
>> +     /* Save the values passed */
>> +     str     r1, emif_addr_virt
>> +     str     r2, mem_type
>> +     str     r3, dram_sync_word
>
> None of this parameter are going to change for every suspend entry and
> exit so saving them once and accessing them should be fine. Just
> create a structure with above, save them in init from C code and
> then access that structure where you need to.

It isn't possible to do so since the structure would be in SDRAM and
at resume time, we don't have access to SDRAM. Additionally, I'd like
to expand the mem_type parameter to a bit field in the future to allow
this code path to be shared with CPU idle.

>> +
>> +     /*
>> +      * Flush all data from the L1 data cache before disabling
>> +      * SCTLR.C bit.
>> +      */
>> +     ldr     r1, kernel_flush
>> +     blx     r1
>> +
>> +     /*
>> +      * Clear the SCTLR.C bit to prevent further data cache
>> +      * allocation. Clearing SCTLR.C would make all the data accesses
>> +      * strongly ordered and would not hit the cache.
>> +      */
>> +     mrc     p15, 0, r0, c1, c0, 0
>> +     bic     r0, r0, #(1 << 2)       @ Disable the C bit
>> +     mcr     p15, 0, r0, c1, c0, 0
>> +     isb
>> +
>> +     /*
>> +      * Invalidate L1 data cache. Even though only invalidate is
>> +      * necessary exported flush API is used here. Doing clean
>> +      * on already clean cache would be almost NOP.
>> +      */
> Comment is stale for AM33XX since below flush will clean l1 and l2
> together. We need to first flush and then invalidate. Please update it.
>> +     ldr     r1, kernel_flush
>> +     blx     r1
>> +
>> +     ldr     r0, emif_addr_virt
>> +     /* Save EMIF configuration */
>> +     ldr     r1, [r0, #EMIF_SDRAM_CONFIG]
>> +     str     r1, emif_sdcfg_val
>> +     ldr     r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
>> +     str     r1, emif_ref_ctrl_val
>> +     ldr     r1, [r0, #EMIF_SDRAM_TIMING_1]
>> +     str     r1, emif_timing1_val
>> +     ldr     r1, [r0, #EMIF_SDRAM_TIMING_2]
>> +     str     r1, emif_timing2_val
>> +     ldr     r1, [r0, #EMIF_SDRAM_TIMING_3]
>> +     str     r1, emif_timing3_val
>> +     ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
>> +     str     r1, emif_pmcr_val
>> +     ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
>> +     str     r1, emif_pmcr_shdw_val
>> +     ldr     r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
>> +     str     r1, emif_zqcfg_val
>> +     ldr     r1, [r0, #EMIF_DDR_PHY_CTRL_1]
>> +     str     r1, emif_rd_lat_val
>> +
>> +     /* Put SDRAM in self-refresh */
>> +     ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
>> +     orr     r1, r1, #0xa0
> No magic numbers please. here and rest of the patch. Have proper
> defines.
>
>> +     str     r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
>> +     str     r1, [r0, #4]
>> +
>> +     ldr     r1, dram_sync_word      @ a dummy access to DDR as per spec
>> +     ldr     r2, [r1, #0]
>> +     ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
>> +     orr     r1, r1, #0x200
>> +     str     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
>> +
>> +     mov     r1, #0x1000             @ Wait for system to enter SR
>> +wait_sr:
> What is sr ? I know you mean self-refresh, but sr can be smart reflex
> as well. Fix that please.
>> +     subs    r1, r1, #1
>> +     bne     wait_sr
>> +
> So how did you derive this 0x1000 number. Whats the real
> delay need ? For e.g a CPU running at 600 MHz vs running
> at 1.2 GHz, the above loop becomes 2 times faster.
>
>> +     /* Disable EMIF */
>> +     ldr     r1, virt_emif_clkctrl
>> +     ldr     r2, [r1]
>> +     bic     r2, r2, #0x03
>> +     str     r2, [r1]
>> +
>> +     ldr     r1, virt_emif_clkctrl
>> +wait_emif_disable:
>> +     ldr     r2, [r1]
>> +     ldr     r3, module_disabled_val
>> +     cmp     r2, r3
>> +     bne     wait_emif_disable
>> +
>> +     /*
>> +      * For the MPU WFI to be registered as an interrupt
>> +      * to WKUP_M3, MPU_CLKCTRL.MODULEMODE needs to be set
>> +      * to DISABLED
>> +      */
>> +     ldr     r1, virt_mpu_clkctrl
>> +     ldr     r2, [r1]
>> +     bic     r2, r2, #0x03
> Magic value
>> +     str     r2, [r1]
>> +
>> +     /*
>> +      * Execute an ISB instruction to ensure that all of the
>> +      * CP15 register changes have been committed.
>> +      */
>> +     isb
>> +
>> +     /*
>> +      * Execute a barrier instruction to ensure that all cache,
>> +      * TLB and branch predictor maintenance operations issued
>> +      * have completed.
>> +      */
>> +     dsb
>> +     dmb
>> +
>> +     /*
>> +      * Execute a WFI instruction and wait until the
>> +      * STANDBYWFI output is asserted to indicate that the
>> +      * CPU is in idle and low power state. CPU can specualatively
>> +      * prefetch the instructions so add NOPs after WFI. Thirteen
>> +      * NOPs as per Cortex-A8 pipeline.
>> +      */
>> +     wfi
>> +
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +     nop
>> +
>> +     /* We come here in case of an abort due to a late interrupt */
>> +
>> +     /* Set MPU_CLKCTRL.MODULEMODE back to ENABLE */
>> +     ldr     r1, virt_mpu_clkctrl
>> +     mov     r2, #0x02
>> +     str     r2, [r1]
>> +
>> +     /* Re-enable EMIF */
>> +     ldr     r1, virt_emif_clkctrl
>> +     mov     r2, #0x02
>> +     str     r2, [r1]
>> +wait_emif_enable:
>> +     ldr     r3, [r1]
>> +     cmp     r2, r3
>> +     bne     wait_emif_enable
>> +
>> +     /* Disable EMIF self-refresh */
>> +     ldr     r0, emif_addr_virt
>> +     ldr     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
>> +     bic     r1, r1, #LP_MODE_MASK
>> +     str     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
>> +     str     r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
>> +
>> +     /*
>> +      * A write to SDRAM CONFIG register triggers
>> +      * an init sequence and hence it must be done
>> +      * at the end for DDR2
>> +      */
>> +     ldr r0, emif_addr_virt
>> +     add r0, r0, #EMIF_SDRAM_CONFIG
>> +     ldr r4, emif_sdcfg_val
>> +     str r4, [r0]
>> +
>> +     /*
>> +      * Set SCTLR.C bit to allow data cache allocation
>> +      */
>> +     mrc     p15, 0, r0, c1, c0, 0
>> +     orr     r0, r0, #(1 << 2)       @ Enable the C bit
>> +     mcr     p15, 0, r0, c1, c0, 0
>> +     isb
>> +
>> +     /* Kill some time for sanity to settle in */
> Really ?
>> +     mov r0, #0x1000
>> +wait_abt:
>> +     subs   r0, r0, #1
>> +     bne wait_abt
> Why do you want to kill time ? How
> does this 0x1000 delay sanities it.
>
>> +
>> +     /* Let the suspend code know about the abort */
>> +     mov     r0, #1
>> +     ldmfd   sp!, {r4 - r11, pc}     @ restore regs and return
>> +ENDPROC(am33xx_do_wfi)
>> +
>> +     .align
>> +ENTRY(am33xx_resume_offset)
>> +     .word . - am33xx_do_wfi
>> +
>> +ENTRY(am33xx_resume_from_deep_sleep)
>> +     /* Re-enable EMIF */
>> +     ldr     r0, phys_emif_clkctrl
>> +     mov     r1, #0x02
>> +     str     r1, [r0]
>> +wait_emif_enable1:
>> +     ldr     r2, [r0]
>> +     cmp     r1, r2
>> +     bne     wait_emif_enable1
>> +
>> +     /* Config EMIF Timings */
>> +     ldr     r0, emif_phys_addr
>> +     ldr     r1, emif_rd_lat_val
>> +     str     r1, [r0, #EMIF_DDR_PHY_CTRL_1]
>> +     str     r1, [r0, #EMIF_DDR_PHY_CTRL_1_SHDW]
>> +     ldr     r1, emif_timing1_val
>> +     str     r1, [r0, #EMIF_SDRAM_TIMING_1]
>> +     str     r1, [r0, #EMIF_SDRAM_TIMING_1_SHDW]
>> +     ldr     r1, emif_timing2_val
>> +     str     r1, [r0, #EMIF_SDRAM_TIMING_2]
>> +     str     r1, [r0, #EMIF_SDRAM_TIMING_2_SHDW]
>> +     ldr     r1, emif_timing3_val
>> +     str     r1, [r0, #EMIF_SDRAM_TIMING_3]
>> +     str     r1, [r0, #EMIF_SDRAM_TIMING_3_SHDW]
>> +     ldr     r1, emif_ref_ctrl_val
>> +     str     r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
>> +     str     r1, [r0, #EMIF_SDRAM_REFRESH_CTRL_SHDW]
>> +     ldr     r1, emif_pmcr_val
>> +     str     r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
>> +     ldr     r1, emif_pmcr_shdw_val
>> +     str     r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
>> +
>> +     /*
>> +      * Output impedence calib needed only for DDR3
>> +      * but since the initial state of this will be
>> +      * disabled for DDR2 no harm in restoring the
>> +      * old configuration
>> +      */
>> +     ldr     r1, emif_zqcfg_val
>> +     str     r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
>> +
>> +     /* Write to SDRAM_CONFIG only for DDR2 */
>> +     ldr     r2, mem_type
>> +     cmp     r2, #MEM_TYPE_DDR2
>> +     bne     resume_to_ddr
>> +
>> +     /*
>> +      * A write to SDRAM CONFIG register triggers
>> +      * an init sequence and hence it must be done
>> +      * at the end for DDR2
>> +      */
>> +     ldr     r1, emif_sdcfg_val
>> +     str     r1, [r0, #EMIF_SDRAM_CONFIG]
>> +
>> +resume_to_ddr:
>> +     /* Back from la-la-land. Kill some time for sanity to settle in */
>> +     mov     r0, #0x1000
>> +wait_resume:
>> +     subs    r0, r0, #1
>> +     bne     wait_resume
>> +
> You are killing too much time ;-)
> without mentioning why ?
>
>> +     /* We are back. Branch to the common CPU resume routine */
>> +     mov     r0, #0
>> +     ldr     pc, resume_addr
> Why can't you resume to "cpu_resume" directly.
>
>> +ENDPROC(am33xx_resume_from_deep_sleep)
>> +
>> +
>> +/*
>> + * Local variables
>> + */
>> +     .align
>> +resume_addr:
>> +     .word   cpu_resume - PAGE_OFFSET + 0x80000000
> Do you really need above math ?
>
>> +kernel_flush:
>> +     .word   v7_flush_dcache_all
>> +ddr_start:
>> +     .word   PAGE_OFFSET
>> +emif_phys_addr:
>> +     .word   AM33XX_EMIF_BASE
>> +virt_mpu_clkctrl:
>> +     .word   AM33XX_CM_MPU_MPU_CLKCTRL
>> +virt_emif_clkctrl:
>> +     .word   AM33XX_CM_PER_EMIF_CLKCTRL
>> +phys_emif_clkctrl:
>> +     .word   (AM33XX_CM_BASE + AM33XX_CM_PER_MOD + \
>> +             AM33XX_CM_PER_EMIF_CLKCTRL_OFFSET)
>> +module_disabled_val:
>> +     .word   0x30000
>> +
>> +/* DDR related defines */
>> +dram_sync_word:
>> +     .word   0xDEADBEEF
>> +mem_type:
>> +     .word   0xDEADBEEF
>> +emif_addr_virt:
>> +     .word   0xDEADBEEF
>> +emif_rd_lat_val:
>> +     .word   0xDEADBEEF
>> +emif_timing1_val:
>> +     .word   0xDEADBEEF
>> +emif_timing2_val:
>> +     .word   0xDEADBEEF
>> +emif_timing3_val:
>> +     .word   0xDEADBEEF
>> +emif_sdcfg_val:
>> +     .word   0xDEADBEEF
>> +emif_ref_ctrl_val:
>> +     .word   0xDEADBEEF
>> +emif_zqcfg_val:
>> +     .word   0xDEADBEEF
>> +emif_pmcr_val:
>> +     .word   0xDEADBEEF
>> +emif_pmcr_shdw_val:
>> +     .word   0xDEADBEEF
>> +
> You can create a structure above above regs.
> refer 'cache-l2x0.h'  struct l2x0_regs in case
> you need an example.
>
>
> Looks like you don't care about secure devices ?
> Just confirm it.
>
> Regards,
> Santosh
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 5/9] ARM: OMAP2+: AM33XX: Add assembly code for PM operations
  2013-08-08 15:16       ` Russ Dill
@ 2013-08-08 15:22         ` Santosh Shilimkar
  -1 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 15:22 UTC (permalink / raw)
  To: Russ Dill
  Cc: Paul Walmsley, Kevin Hilman, Dave Gerlach, Vaibhav Bedia,
	linux-omap, linux-arm-kernel

On Thursday 08 August 2013 11:16 AM, Russ Dill wrote:
> On Thu, Aug 8, 2013 at 7:50 AM, Santosh Shilimkar
> <santosh.shilimkar@ti.com> wrote:
>> On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
>>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>>
>>> In preparation for suspend-resume support for AM33XX, add
>>> the assembly file with the code which is copied to internal
>>> memory (OCMC RAM) during bootup and runs from there.
>>>
>>> As part of the low power entry (DeepSleep0 mode in AM33XX TRM),
>>> the code running from OCMC RAM does the following
>>> 1. Stores the EMIF configuration
>>> 2. Puts external memory in self-refresh
>>> 3. Disables EMIF clock
>>> 4. Executes WFI after writing to MPU_CLKCTRL register.
>>>
>>> If no interrupts have come, WFI execution on MPU gets registered
>>> as an interrupt with the WKUP-M3. WKUP-M3 takes care of disabling
>>> some clocks which MPU should not (L3, L4, OCMC RAM etc) and takes
>>> care of clockdomain and powerdomain transitions as part of the
>>> DeepSleep0 mode entry.
>>>
>>> In case a late interrupt comes in, WFI ends up as a NOP and MPU
>>> continues execution from internal memory. The 'abort path' code
>>> undoes whatever was done as part of the low power entry and indicates
>>> a suspend failure by passing a non-zero value to the cpu_resume routine.
>>>
>>> The 'resume path' code is similar to the 'abort path' with the key
>>> difference of MMU being enabled in the 'abort path' but being
>>> disabled in the 'resume path' due to MPU getting powered off.
>>>
>>> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>> Cc: Kevin Hilman <khilman@linaro.org>
>>> ---
>>>  arch/arm/mach-omap2/sleep33xx.S |  350 +++++++++++++++++++++++++++++++++++++++
>>>  1 file changed, 350 insertions(+)
>>>  create mode 100644 arch/arm/mach-omap2/sleep33xx.S
>>>
>>> diff --git a/arch/arm/mach-omap2/sleep33xx.S b/arch/arm/mach-omap2/sleep33xx.S
>>> new file mode 100644
>>> index 0000000..834c7d4
>>> --- /dev/null
>>> +++ b/arch/arm/mach-omap2/sleep33xx.S
>>> @@ -0,0 +1,350 @@
>>> +/*
>>> + * Low level suspend code for AM33XX SoCs
>>> + *
>>> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
>>> + * Vaibhav Bedia <vaibhav.bedia@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/linkage.h>
>>> +#include <linux/ti_emif.h>
>>> +#include <asm/memory.h>
>>> +#include <asm/assembler.h>
>>> +
>>> +#include "cm33xx.h"
>>> +#include "pm33xx.h"
>>> +#include "prm33xx.h"
>>> +
>>> +     .text
>>> +     .align 3
>>> +
>>> +/*
>>> + * This routine is executed from internal RAM and expects some
>>> + * parameters to be passed in r0 _strictly_ in following order:
>>> + * 1) emif_addr_virt - ioremapped EMIF address
>>> + * 2) mem_type - 2 -> DDR2, 3-> DDR3
>>> + * 3) dram_sync_word - uncached word in SDRAM
>>> + *
>>> + * The code loads these values taking r0 value as reference to
>>> + * the array in registers starting from r0, i.e emif_addr_virt
>>> + * goes to r1, mem_type goes to r2 and and so on. These are
>>> + * then saved into memory locations before proceeding with the
>>> + * sleep sequence and hence registers r0, r1 etc can still be
>>> + * used in the rest of the sleep code.
>>> + */
>>> +
>>> +ENTRY(am33xx_do_wfi)
>>> +     stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
>>> +
>>> +     ldm     r0, {r1-r3}             @ gather values passed
>>> +
>>> +     /* Save the values passed */
>>> +     str     r1, emif_addr_virt
>>> +     str     r2, mem_type
>>> +     str     r3, dram_sync_word
>>
>> None of this parameter are going to change for every suspend entry and
>> exit so saving them once and accessing them should be fine. Just
>> create a structure with above, save them in init from C code and
>> then access that structure where you need to.
> 
> It isn't possible to do so since the structure would be in SDRAM and
> at resume time, we don't have access to SDRAM. Additionally, I'd like
> to expand the mem_type parameter to a bit field in the future to allow
> this code path to be shared with CPU idle.
>
You can copy the structure in SRAM. So how does memtype need
changes for CPUIDLE ?

I have several comments on this patch so I assume you are
going to address them then.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 5/9] ARM: OMAP2+: AM33XX: Add assembly code for PM operations
@ 2013-08-08 15:22         ` Santosh Shilimkar
  0 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 15:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 08 August 2013 11:16 AM, Russ Dill wrote:
> On Thu, Aug 8, 2013 at 7:50 AM, Santosh Shilimkar
> <santosh.shilimkar@ti.com> wrote:
>> On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
>>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>>
>>> In preparation for suspend-resume support for AM33XX, add
>>> the assembly file with the code which is copied to internal
>>> memory (OCMC RAM) during bootup and runs from there.
>>>
>>> As part of the low power entry (DeepSleep0 mode in AM33XX TRM),
>>> the code running from OCMC RAM does the following
>>> 1. Stores the EMIF configuration
>>> 2. Puts external memory in self-refresh
>>> 3. Disables EMIF clock
>>> 4. Executes WFI after writing to MPU_CLKCTRL register.
>>>
>>> If no interrupts have come, WFI execution on MPU gets registered
>>> as an interrupt with the WKUP-M3. WKUP-M3 takes care of disabling
>>> some clocks which MPU should not (L3, L4, OCMC RAM etc) and takes
>>> care of clockdomain and powerdomain transitions as part of the
>>> DeepSleep0 mode entry.
>>>
>>> In case a late interrupt comes in, WFI ends up as a NOP and MPU
>>> continues execution from internal memory. The 'abort path' code
>>> undoes whatever was done as part of the low power entry and indicates
>>> a suspend failure by passing a non-zero value to the cpu_resume routine.
>>>
>>> The 'resume path' code is similar to the 'abort path' with the key
>>> difference of MMU being enabled in the 'abort path' but being
>>> disabled in the 'resume path' due to MPU getting powered off.
>>>
>>> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>> Cc: Kevin Hilman <khilman@linaro.org>
>>> ---
>>>  arch/arm/mach-omap2/sleep33xx.S |  350 +++++++++++++++++++++++++++++++++++++++
>>>  1 file changed, 350 insertions(+)
>>>  create mode 100644 arch/arm/mach-omap2/sleep33xx.S
>>>
>>> diff --git a/arch/arm/mach-omap2/sleep33xx.S b/arch/arm/mach-omap2/sleep33xx.S
>>> new file mode 100644
>>> index 0000000..834c7d4
>>> --- /dev/null
>>> +++ b/arch/arm/mach-omap2/sleep33xx.S
>>> @@ -0,0 +1,350 @@
>>> +/*
>>> + * Low level suspend code for AM33XX SoCs
>>> + *
>>> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
>>> + * Vaibhav Bedia <vaibhav.bedia@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/linkage.h>
>>> +#include <linux/ti_emif.h>
>>> +#include <asm/memory.h>
>>> +#include <asm/assembler.h>
>>> +
>>> +#include "cm33xx.h"
>>> +#include "pm33xx.h"
>>> +#include "prm33xx.h"
>>> +
>>> +     .text
>>> +     .align 3
>>> +
>>> +/*
>>> + * This routine is executed from internal RAM and expects some
>>> + * parameters to be passed in r0 _strictly_ in following order:
>>> + * 1) emif_addr_virt - ioremapped EMIF address
>>> + * 2) mem_type - 2 -> DDR2, 3-> DDR3
>>> + * 3) dram_sync_word - uncached word in SDRAM
>>> + *
>>> + * The code loads these values taking r0 value as reference to
>>> + * the array in registers starting from r0, i.e emif_addr_virt
>>> + * goes to r1, mem_type goes to r2 and and so on. These are
>>> + * then saved into memory locations before proceeding with the
>>> + * sleep sequence and hence registers r0, r1 etc can still be
>>> + * used in the rest of the sleep code.
>>> + */
>>> +
>>> +ENTRY(am33xx_do_wfi)
>>> +     stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
>>> +
>>> +     ldm     r0, {r1-r3}             @ gather values passed
>>> +
>>> +     /* Save the values passed */
>>> +     str     r1, emif_addr_virt
>>> +     str     r2, mem_type
>>> +     str     r3, dram_sync_word
>>
>> None of this parameter are going to change for every suspend entry and
>> exit so saving them once and accessing them should be fine. Just
>> create a structure with above, save them in init from C code and
>> then access that structure where you need to.
> 
> It isn't possible to do so since the structure would be in SDRAM and
> at resume time, we don't have access to SDRAM. Additionally, I'd like
> to expand the mem_type parameter to a bit field in the future to allow
> this code path to be shared with CPU idle.
>
You can copy the structure in SRAM. So how does memtype need
changes for CPUIDLE ?

I have several comments on this patch so I assume you are
going to address them then.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 5/9] ARM: OMAP2+: AM33XX: Add assembly code for PM operations
  2013-08-08 15:22         ` Santosh Shilimkar
@ 2013-08-08 16:03           ` Russ Dill
  -1 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08 16:03 UTC (permalink / raw)
  To: Santosh Shilimkar
  Cc: Dave Gerlach, Kevin Hilman, Paul Walmsley, linux-omap,
	Vaibhav Bedia, linux-arm-kernel

On Thu, Aug 8, 2013 at 8:22 AM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
> On Thursday 08 August 2013 11:16 AM, Russ Dill wrote:
>> On Thu, Aug 8, 2013 at 7:50 AM, Santosh Shilimkar
>> <santosh.shilimkar@ti.com> wrote:
>>> On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
>>>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>>>
>>>> In preparation for suspend-resume support for AM33XX, add
>>>> the assembly file with the code which is copied to internal
>>>> memory (OCMC RAM) during bootup and runs from there.
>>>>
>>>> As part of the low power entry (DeepSleep0 mode in AM33XX TRM),
>>>> the code running from OCMC RAM does the following
>>>> 1. Stores the EMIF configuration
>>>> 2. Puts external memory in self-refresh
>>>> 3. Disables EMIF clock
>>>> 4. Executes WFI after writing to MPU_CLKCTRL register.
>>>>
>>>> If no interrupts have come, WFI execution on MPU gets registered
>>>> as an interrupt with the WKUP-M3. WKUP-M3 takes care of disabling
>>>> some clocks which MPU should not (L3, L4, OCMC RAM etc) and takes
>>>> care of clockdomain and powerdomain transitions as part of the
>>>> DeepSleep0 mode entry.
>>>>
>>>> In case a late interrupt comes in, WFI ends up as a NOP and MPU
>>>> continues execution from internal memory. The 'abort path' code
>>>> undoes whatever was done as part of the low power entry and indicates
>>>> a suspend failure by passing a non-zero value to the cpu_resume routine.
>>>>
>>>> The 'resume path' code is similar to the 'abort path' with the key
>>>> difference of MMU being enabled in the 'abort path' but being
>>>> disabled in the 'resume path' due to MPU getting powered off.
>>>>
>>>> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>>>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>> Cc: Kevin Hilman <khilman@linaro.org>
>>>> ---
>>>>  arch/arm/mach-omap2/sleep33xx.S |  350 +++++++++++++++++++++++++++++++++++++++
>>>>  1 file changed, 350 insertions(+)
>>>>  create mode 100644 arch/arm/mach-omap2/sleep33xx.S
>>>>
>>>> diff --git a/arch/arm/mach-omap2/sleep33xx.S b/arch/arm/mach-omap2/sleep33xx.S
>>>> new file mode 100644
>>>> index 0000000..834c7d4
>>>> --- /dev/null
>>>> +++ b/arch/arm/mach-omap2/sleep33xx.S
>>>> @@ -0,0 +1,350 @@
>>>> +/*
>>>> + * Low level suspend code for AM33XX SoCs
>>>> + *
>>>> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
>>>> + * Vaibhav Bedia <vaibhav.bedia@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/linkage.h>
>>>> +#include <linux/ti_emif.h>
>>>> +#include <asm/memory.h>
>>>> +#include <asm/assembler.h>
>>>> +
>>>> +#include "cm33xx.h"
>>>> +#include "pm33xx.h"
>>>> +#include "prm33xx.h"
>>>> +
>>>> +     .text
>>>> +     .align 3
>>>> +
>>>> +/*
>>>> + * This routine is executed from internal RAM and expects some
>>>> + * parameters to be passed in r0 _strictly_ in following order:
>>>> + * 1) emif_addr_virt - ioremapped EMIF address
>>>> + * 2) mem_type - 2 -> DDR2, 3-> DDR3
>>>> + * 3) dram_sync_word - uncached word in SDRAM
>>>> + *
>>>> + * The code loads these values taking r0 value as reference to
>>>> + * the array in registers starting from r0, i.e emif_addr_virt
>>>> + * goes to r1, mem_type goes to r2 and and so on. These are
>>>> + * then saved into memory locations before proceeding with the
>>>> + * sleep sequence and hence registers r0, r1 etc can still be
>>>> + * used in the rest of the sleep code.
>>>> + */
>>>> +
>>>> +ENTRY(am33xx_do_wfi)
>>>> +     stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
>>>> +
>>>> +     ldm     r0, {r1-r3}             @ gather values passed
>>>> +
>>>> +     /* Save the values passed */
>>>> +     str     r1, emif_addr_virt
>>>> +     str     r2, mem_type
>>>> +     str     r3, dram_sync_word
>>>
>>> None of this parameter are going to change for every suspend entry and
>>> exit so saving them once and accessing them should be fine. Just
>>> create a structure with above, save them in init from C code and
>>> then access that structure where you need to.
>>
>> It isn't possible to do so since the structure would be in SDRAM and
>> at resume time, we don't have access to SDRAM. Additionally, I'd like
>> to expand the mem_type parameter to a bit field in the future to allow
>> this code path to be shared with CPU idle.
>>
> You can copy the structure in SRAM. So how does memtype need
> changes for CPUIDLE ?

You'd have to reserve the address and have a symbol exported for it,
then after pushing everything to SRAM, you'd have to calculate the
pushed address of the reserved space, then do a memcpy. It'd be a bit
convoluted. Passing the address to the struct into tho wfi function is
really easy and a pretty common thing to do.

For cpuidle, i'd probably change it to a flags field instead of just
memtype. For instance ddr2 would be (1 << 0), and ddr3 would (1 << 1).
Other flags could then be added, such as whether or not to notify the
M3 at WFI time.

> I have several comments on this patch so I assume you are
> going to address them then.
>
> Regards,
> Santosh
>
>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 5/9] ARM: OMAP2+: AM33XX: Add assembly code for PM operations
@ 2013-08-08 16:03           ` Russ Dill
  0 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-08 16:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 8, 2013 at 8:22 AM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
> On Thursday 08 August 2013 11:16 AM, Russ Dill wrote:
>> On Thu, Aug 8, 2013 at 7:50 AM, Santosh Shilimkar
>> <santosh.shilimkar@ti.com> wrote:
>>> On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
>>>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>>>
>>>> In preparation for suspend-resume support for AM33XX, add
>>>> the assembly file with the code which is copied to internal
>>>> memory (OCMC RAM) during bootup and runs from there.
>>>>
>>>> As part of the low power entry (DeepSleep0 mode in AM33XX TRM),
>>>> the code running from OCMC RAM does the following
>>>> 1. Stores the EMIF configuration
>>>> 2. Puts external memory in self-refresh
>>>> 3. Disables EMIF clock
>>>> 4. Executes WFI after writing to MPU_CLKCTRL register.
>>>>
>>>> If no interrupts have come, WFI execution on MPU gets registered
>>>> as an interrupt with the WKUP-M3. WKUP-M3 takes care of disabling
>>>> some clocks which MPU should not (L3, L4, OCMC RAM etc) and takes
>>>> care of clockdomain and powerdomain transitions as part of the
>>>> DeepSleep0 mode entry.
>>>>
>>>> In case a late interrupt comes in, WFI ends up as a NOP and MPU
>>>> continues execution from internal memory. The 'abort path' code
>>>> undoes whatever was done as part of the low power entry and indicates
>>>> a suspend failure by passing a non-zero value to the cpu_resume routine.
>>>>
>>>> The 'resume path' code is similar to the 'abort path' with the key
>>>> difference of MMU being enabled in the 'abort path' but being
>>>> disabled in the 'resume path' due to MPU getting powered off.
>>>>
>>>> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>>>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>> Cc: Kevin Hilman <khilman@linaro.org>
>>>> ---
>>>>  arch/arm/mach-omap2/sleep33xx.S |  350 +++++++++++++++++++++++++++++++++++++++
>>>>  1 file changed, 350 insertions(+)
>>>>  create mode 100644 arch/arm/mach-omap2/sleep33xx.S
>>>>
>>>> diff --git a/arch/arm/mach-omap2/sleep33xx.S b/arch/arm/mach-omap2/sleep33xx.S
>>>> new file mode 100644
>>>> index 0000000..834c7d4
>>>> --- /dev/null
>>>> +++ b/arch/arm/mach-omap2/sleep33xx.S
>>>> @@ -0,0 +1,350 @@
>>>> +/*
>>>> + * Low level suspend code for AM33XX SoCs
>>>> + *
>>>> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
>>>> + * Vaibhav Bedia <vaibhav.bedia@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/linkage.h>
>>>> +#include <linux/ti_emif.h>
>>>> +#include <asm/memory.h>
>>>> +#include <asm/assembler.h>
>>>> +
>>>> +#include "cm33xx.h"
>>>> +#include "pm33xx.h"
>>>> +#include "prm33xx.h"
>>>> +
>>>> +     .text
>>>> +     .align 3
>>>> +
>>>> +/*
>>>> + * This routine is executed from internal RAM and expects some
>>>> + * parameters to be passed in r0 _strictly_ in following order:
>>>> + * 1) emif_addr_virt - ioremapped EMIF address
>>>> + * 2) mem_type - 2 -> DDR2, 3-> DDR3
>>>> + * 3) dram_sync_word - uncached word in SDRAM
>>>> + *
>>>> + * The code loads these values taking r0 value as reference to
>>>> + * the array in registers starting from r0, i.e emif_addr_virt
>>>> + * goes to r1, mem_type goes to r2 and and so on. These are
>>>> + * then saved into memory locations before proceeding with the
>>>> + * sleep sequence and hence registers r0, r1 etc can still be
>>>> + * used in the rest of the sleep code.
>>>> + */
>>>> +
>>>> +ENTRY(am33xx_do_wfi)
>>>> +     stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
>>>> +
>>>> +     ldm     r0, {r1-r3}             @ gather values passed
>>>> +
>>>> +     /* Save the values passed */
>>>> +     str     r1, emif_addr_virt
>>>> +     str     r2, mem_type
>>>> +     str     r3, dram_sync_word
>>>
>>> None of this parameter are going to change for every suspend entry and
>>> exit so saving them once and accessing them should be fine. Just
>>> create a structure with above, save them in init from C code and
>>> then access that structure where you need to.
>>
>> It isn't possible to do so since the structure would be in SDRAM and
>> at resume time, we don't have access to SDRAM. Additionally, I'd like
>> to expand the mem_type parameter to a bit field in the future to allow
>> this code path to be shared with CPU idle.
>>
> You can copy the structure in SRAM. So how does memtype need
> changes for CPUIDLE ?

You'd have to reserve the address and have a symbol exported for it,
then after pushing everything to SRAM, you'd have to calculate the
pushed address of the reserved space, then do a memcpy. It'd be a bit
convoluted. Passing the address to the struct into tho wfi function is
really easy and a pretty common thing to do.

For cpuidle, i'd probably change it to a flags field instead of just
memtype. For instance ddr2 would be (1 << 0), and ddr3 would (1 << 1).
Other flags could then be added, such as whether or not to notify the
M3@WFI time.

> I have several comments on this patch so I assume you are
> going to address them then.
>
> Regards,
> Santosh
>
>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-08 15:03         ` Santosh Shilimkar
@ 2013-08-08 16:06           ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-08 16:06 UTC (permalink / raw)
  To: Santosh Shilimkar
  Cc: Nishanth Menon, Russ Dill, linux-arm-kernel, linux-omap,
	Paul Walmsley, Kevin Hilman, Vaibhav Bedia, Tony Lingren,
	Benoit Cousson

On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
> $subject and patch don't match.
>
> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>    In reference to
>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>> bound and which don't.
>> Does it need to? M3 firmware can pretty much define "I will force the device into low power state, and if the drivers dont handle things properly, fix the darned driver". M3 behavior should be considered as a "hardware" as far as Linux running on MPU is concerned, and firmware helps change the behavior by accounting for SoC quirks. *if* we have ability to handle this in the firmware, there is no need to carry this in Linux.
>>
> I agree with Nishant. I don't like this patch and IIRC, I gave same
> comment in the last version. Linux need not know about all such firmware
> quirks. Also all these M3 specific stuff, should be done somewhere
> else. Probably having a small M3 driver won't be a bad idea.
>
> Regards,
> Santosh
>

I am not opposed to doing it this way and letting the M3 firmware handle 
idling these modules, however the one concern raised in the last series 
is that an approach that does not acknowledge drivers will hide driver 
PM bugs. I suppose as long as I make sure to document that the devices 
are being idled by the M3 firmware this may not be an issue. I will look 
into implementing this.

Regards,
Dave

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-08 16:06           ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-08 16:06 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
> $subject and patch don't match.
>
> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>    In reference to
>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>> bound and which don't.
>> Does it need to? M3 firmware can pretty much define "I will force the device into low power state, and if the drivers dont handle things properly, fix the darned driver". M3 behavior should be considered as a "hardware" as far as Linux running on MPU is concerned, and firmware helps change the behavior by accounting for SoC quirks. *if* we have ability to handle this in the firmware, there is no need to carry this in Linux.
>>
> I agree with Nishant. I don't like this patch and IIRC, I gave same
> comment in the last version. Linux need not know about all such firmware
> quirks. Also all these M3 specific stuff, should be done somewhere
> else. Probably having a small M3 driver won't be a bad idea.
>
> Regards,
> Santosh
>

I am not opposed to doing it this way and letting the M3 firmware handle 
idling these modules, however the one concern raised in the last series 
is that an approach that does not acknowledge drivers will hide driver 
PM bugs. I suppose as long as I make sure to document that the devices 
are being idled by the M3 firmware this may not be an issue. I will look 
into implementing this.

Regards,
Dave

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 6/9] ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device
  2013-08-08 14:23     ` Santosh Shilimkar
@ 2013-08-08 16:09       ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-08 16:09 UTC (permalink / raw)
  To: Santosh Shilimkar
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman, Vaibhav Bedia

On 08/08/2013 09:23 AM, Santosh Shilimkar wrote:
> On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>
>> OMAP timer code registers two timers - one as clocksource
>> and one as clockevent. Since AM33XX has only one usable timer
>> in the WKUP domain one of the timers needs suspend-resume
>> support to restore the configuration to pre-suspend state.
>>
>> commit adc78e6 (timekeeping: Add suspend and resume
>> of clock event devices) introduced .suspend and .resume
>> callbacks for clock event devices. Leverages these
>> callbacks to have AM33XX clockevent timer which is
>> in not in WKUP domain to behave properly across system
>> suspend.
>>
>> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>> ---
> NAK
>
> This patch doesn't addressed previous comments.
> - The issue is specific to AM33XX and hence you
> need to take care of that. These callbacks will happen on
> all OMAP machines where the problem doesn't exist.
>
> - Don't use hwmod APIs directly. At least abstract it
> at omap_device layer and use that one instead.
>

Ok I will fix this, seems I missed those.

>>   arch/arm/mach-omap2/timer.c |   32 ++++++++++++++++++++++++++++++++
>>   1 file changed, 32 insertions(+)
>>
>> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
>> index b37e1fc..cce5d39 100644
>> --- a/arch/arm/mach-omap2/timer.c
>> +++ b/arch/arm/mach-omap2/timer.c
>> @@ -118,11 +118,43 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
>>   	}
>>   }
>>
>> +static void omap_clkevt_suspend(struct clock_event_device *unused)
>> +{
>> +	char name[10];
>> +	struct omap_hwmod *oh;
>> +
>> +	sprintf(name, "timer%d", clkev.id);
>> +	oh = omap_hwmod_lookup(name);
>> +	if (!oh)
>> +		return;
>> +
>> +	__omap_dm_timer_stop(&clkev, 1, clkev.rate);
>> +	omap_hwmod_idle(oh);
>> +}
>> +
>> +static void omap_clkevt_resume(struct clock_event_device *unused)
>> +{
>> +	char name[10];
>> +	struct omap_hwmod *oh;
>> +
>> +	sprintf(name, "timer%d", clkev.id);
>> +	oh = omap_hwmod_lookup(name);
>> +	if (!oh)
>> +		return;
>> +
>> +	omap_hwmod_enable(oh);
>> +	__omap_dm_timer_load_start(&clkev,
>> +			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
>> +	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
>> +}
>> +
>>   static struct clock_event_device clockevent_gpt = {
>>   	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
>>   	.rating		= 300,
>>   	.set_next_event	= omap2_gp_timer_set_next_event,
>>   	.set_mode	= omap2_gp_timer_set_mode,
>> +	.suspend	= omap_clkevt_suspend,
>> +	.resume		= omap_clkevt_resume,
>>   };
>>
>>   static struct property device_disabled = {
>>
>


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 6/9] ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device
@ 2013-08-08 16:09       ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-08 16:09 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/08/2013 09:23 AM, Santosh Shilimkar wrote:
> On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>
>> OMAP timer code registers two timers - one as clocksource
>> and one as clockevent. Since AM33XX has only one usable timer
>> in the WKUP domain one of the timers needs suspend-resume
>> support to restore the configuration to pre-suspend state.
>>
>> commit adc78e6 (timekeeping: Add suspend and resume
>> of clock event devices) introduced .suspend and .resume
>> callbacks for clock event devices. Leverages these
>> callbacks to have AM33XX clockevent timer which is
>> in not in WKUP domain to behave properly across system
>> suspend.
>>
>> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>> ---
> NAK
>
> This patch doesn't addressed previous comments.
> - The issue is specific to AM33XX and hence you
> need to take care of that. These callbacks will happen on
> all OMAP machines where the problem doesn't exist.
>
> - Don't use hwmod APIs directly. At least abstract it
> at omap_device layer and use that one instead.
>

Ok I will fix this, seems I missed those.

>>   arch/arm/mach-omap2/timer.c |   32 ++++++++++++++++++++++++++++++++
>>   1 file changed, 32 insertions(+)
>>
>> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
>> index b37e1fc..cce5d39 100644
>> --- a/arch/arm/mach-omap2/timer.c
>> +++ b/arch/arm/mach-omap2/timer.c
>> @@ -118,11 +118,43 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
>>   	}
>>   }
>>
>> +static void omap_clkevt_suspend(struct clock_event_device *unused)
>> +{
>> +	char name[10];
>> +	struct omap_hwmod *oh;
>> +
>> +	sprintf(name, "timer%d", clkev.id);
>> +	oh = omap_hwmod_lookup(name);
>> +	if (!oh)
>> +		return;
>> +
>> +	__omap_dm_timer_stop(&clkev, 1, clkev.rate);
>> +	omap_hwmod_idle(oh);
>> +}
>> +
>> +static void omap_clkevt_resume(struct clock_event_device *unused)
>> +{
>> +	char name[10];
>> +	struct omap_hwmod *oh;
>> +
>> +	sprintf(name, "timer%d", clkev.id);
>> +	oh = omap_hwmod_lookup(name);
>> +	if (!oh)
>> +		return;
>> +
>> +	omap_hwmod_enable(oh);
>> +	__omap_dm_timer_load_start(&clkev,
>> +			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
>> +	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
>> +}
>> +
>>   static struct clock_event_device clockevent_gpt = {
>>   	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
>>   	.rating		= 300,
>>   	.set_next_event	= omap2_gp_timer_set_next_event,
>>   	.set_mode	= omap2_gp_timer_set_mode,
>> +	.suspend	= omap_clkevt_suspend,
>> +	.resume		= omap_clkevt_resume,
>>   };
>>
>>   static struct property device_disabled = {
>>
>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-08 13:44     ` Santosh Shilimkar
@ 2013-08-08 16:16       ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-08 16:16 UTC (permalink / raw)
  To: Santosh Shilimkar
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman, Vaibhav Bedia

On 08/08/2013 08:44 AM, Santosh Shilimkar wrote:
> On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>
>> Interacting with WKUP-M3 requires some more control
>> module register writes. Add the register offsets and
>> APIs to write to these.
>>
>> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>> ---
>>   arch/arm/mach-omap2/control.c |   57 +++++++++++++++++++++++++++++++++++++++++
>>   arch/arm/mach-omap2/control.h |   54 ++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 111 insertions(+)
>>
>> diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
>> index 31e0dfe..934041a 100644
>> --- a/arch/arm/mach-omap2/control.c
>> +++ b/arch/arm/mach-omap2/control.c
>> @@ -605,3 +605,60 @@ int omap3_ctrl_save_padconf(void)
>>   }
>>
>>   #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
>> +
>> +#if defined(CONFIG_SOC_AM33XX) && defined(CONFIG_PM)
>> +void am33xx_txev_eoi(void)
>> +{
>> +	omap_ctrl_writel(AM33XX_M3_TXEV_ACK, AM33XX_CONTROL_M3_TXEV_EOI);
>> +}
>> +
>> +void am33xx_txev_enable(void)
>> +{
>> +	omap_ctrl_writel(AM33XX_M3_TXEV_ENABLE, AM33XX_CONTROL_M3_TXEV_EOI);
>> +}
>> +
>> +/*
>> + * Invalidate M3 firmware version before hardreset.
>> + * Write invalid version in lower 4 nibbles of parameter
>> + * register (ipc_regs + 0x8).
>> + */
>> +void am33xx_pm_version_clear(void)
>> +{
>> +	omap_ctrl_writel(0xffff0000, AM33XX_CONTROL_IPC_MSG_REG2);
>> +}
>> +
>> +int am33xx_pm_version_get(void)
>> +{
>> +	return omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG2) & M3_VERSION_MASK;
>> +}
>> +
>> +void am33xx_pm_ipc_cmd(struct am33xx_ipc_data *data)
>> +{
>> +	omap_ctrl_writel(data->resume_addr, AM33XX_CONTROL_IPC_MSG_REG0);
>> +	omap_ctrl_writel(data->sleep_mode, AM33XX_CONTROL_IPC_MSG_REG1);
>> +	omap_ctrl_writel(data->param1, AM33XX_CONTROL_IPC_MSG_REG2);
>> +	omap_ctrl_writel(data->param2, AM33XX_CONTROL_IPC_MSG_REG3);
>> +	omap_ctrl_writel(data->param3, AM33XX_CONTROL_IPC_MSG_REG4);
>> +}
>> +
>> +int am33xx_pm_status(void)
>> +{
>> +	int i;
>> +
>> +	i = omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG1);
>> +	i &= IPC_RESP_MASK;
>> +	i >>= __ffs(IPC_RESP_MASK);
>> +
>> +	return i;
>> +}
>> +
>> +int am33xx_pm_wake_src(void)
>> +{
>> +	int i;
>> +
>> +	i = omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG6);
>> +	i &= 0xff;
>> +
>> +	return i;
>> +}
>> +#endif /* CONFIG_SOC_AM33XX && CONFIG_PM */
>> diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
>> index f7d7c2e..9be587c 100644
>> --- a/arch/arm/mach-omap2/control.h
>> +++ b/arch/arm/mach-omap2/control.h
>> @@ -370,6 +370,22 @@
>>   #define AM33XX_DEV_FEATURE		0x604
>>   #define AM33XX_SGX_MASK			BIT(29)
>>
>> +/* AM33XX M3_TXEV_EOI register */
>> +#define AM33XX_CONTROL_M3_TXEV_EOI	0x1324
>> +
>> +#define AM33XX_M3_TXEV_ACK		(0x1 << 0)
>> +#define AM33XX_M3_TXEV_ENABLE		(0x0 << 0)
>> +
>> +/* AM33XX IPC message registers */
>> +#define AM33XX_CONTROL_IPC_MSG_REG0	0x1328
>> +#define AM33XX_CONTROL_IPC_MSG_REG1	0x132C
>> +#define AM33XX_CONTROL_IPC_MSG_REG2	0x1330
>> +#define AM33XX_CONTROL_IPC_MSG_REG3	0x1334
>> +#define AM33XX_CONTROL_IPC_MSG_REG4	0x1338
>> +#define AM33XX_CONTROL_IPC_MSG_REG5	0x133C
>> +#define AM33XX_CONTROL_IPC_MSG_REG6	0x1340
>> +#define AM33XX_CONTROL_IPC_MSG_REG7	0x1344
>> +
>>   /* CONTROL OMAP STATUS register to identify OMAP3 features */
>>   #define OMAP3_CONTROL_OMAP_STATUS	0x044c
>>
>> @@ -429,6 +445,44 @@ extern void omap3630_ctrl_disable_rta(void);
>>   extern int omap3_ctrl_save_padconf(void);
>>   extern void omap2_set_globals_control(void __iomem *ctrl,
>>   				      void __iomem *ctrl_pad);
>> +struct am33xx_ipc_data {
>> +	u32 resume_addr;
>> +	u32 sleep_mode;
>> +	u32 param1;
>> +	u32 param2;
>> +	u32 param3;
>> +	u32 param4;
>> +	u32 param5;
>> +	u32 param6;
>> +};
>> +
>> +#define IPC_RESP_SHIFT			16
>> +#define IPC_RESP_MASK			(0xffff << 16)
>> +
>> +#define M3_VERSION_SHIFT		0
>> +#define M3_VERSION_MASK			(0xffff << 0)
>> +
>> +/*
>> + * 9-4 = VTT GPIO PIN (6 Bits)
>> + *   3 = VTT Status (1 Bit)
>> + * 2-0 = Memory Type (2 Bits)
>> +*/
>> +#define MEM_TYPE_SHIFT		(0x0)
>> +#define MEM_TYPE_MASK		(0x7 << 0)
>> +#define VTT_STAT_SHIFT		(0x3)
>> +#define VTT_STAT_MASK		(0x1 << 3)
>> +#define VTT_GPIO_PIN_SHIFT	(0x4)
>> +#define VTT_GPIO_PIN_MASK	(0x2f << 4)
>> +
>> +extern void am33xx_wkup_m3_ipc_cmd(struct am33xx_ipc_data *data);
>> +extern void am33xx_txev_eoi(void);
>> +extern void am33xx_txev_enable(void);
>> +extern void am33xx_pm_version_clear(void);
>> +extern int am33xx_pm_version_get(void);
>> +extern void am33xx_pm_ipc_cmd(struct am33xx_ipc_data *data);
>> +extern int am33xx_pm_status(void);
>> +extern int am33xx_pm_wake_src(void);
>> +
> Lets address the above better. I don't see a need of 8 functions
> exported doing one or 2 register writes.
>
> Look M3 based handling is going to be there on future SOCs
> as well and this kind of handling of IPC is very short cited.
>

The idea here was to move all control module register accesses into one 
file in planning of implementing a driver for the control module itself 
in the future.

> Probably we should have a separate driver for M3 in linux which
> can have all this local code instead of all these exports.

The wkup_m3 code has been moved to a small driver found in patch 8 of 
this series, would it better to move this code there rather than with 
the rest of the control module code?

>
> Regards,
> Santosh
>


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-08 16:16       ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-08 16:16 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/08/2013 08:44 AM, Santosh Shilimkar wrote:
> On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>
>> Interacting with WKUP-M3 requires some more control
>> module register writes. Add the register offsets and
>> APIs to write to these.
>>
>> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>> ---
>>   arch/arm/mach-omap2/control.c |   57 +++++++++++++++++++++++++++++++++++++++++
>>   arch/arm/mach-omap2/control.h |   54 ++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 111 insertions(+)
>>
>> diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
>> index 31e0dfe..934041a 100644
>> --- a/arch/arm/mach-omap2/control.c
>> +++ b/arch/arm/mach-omap2/control.c
>> @@ -605,3 +605,60 @@ int omap3_ctrl_save_padconf(void)
>>   }
>>
>>   #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
>> +
>> +#if defined(CONFIG_SOC_AM33XX) && defined(CONFIG_PM)
>> +void am33xx_txev_eoi(void)
>> +{
>> +	omap_ctrl_writel(AM33XX_M3_TXEV_ACK, AM33XX_CONTROL_M3_TXEV_EOI);
>> +}
>> +
>> +void am33xx_txev_enable(void)
>> +{
>> +	omap_ctrl_writel(AM33XX_M3_TXEV_ENABLE, AM33XX_CONTROL_M3_TXEV_EOI);
>> +}
>> +
>> +/*
>> + * Invalidate M3 firmware version before hardreset.
>> + * Write invalid version in lower 4 nibbles of parameter
>> + * register (ipc_regs + 0x8).
>> + */
>> +void am33xx_pm_version_clear(void)
>> +{
>> +	omap_ctrl_writel(0xffff0000, AM33XX_CONTROL_IPC_MSG_REG2);
>> +}
>> +
>> +int am33xx_pm_version_get(void)
>> +{
>> +	return omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG2) & M3_VERSION_MASK;
>> +}
>> +
>> +void am33xx_pm_ipc_cmd(struct am33xx_ipc_data *data)
>> +{
>> +	omap_ctrl_writel(data->resume_addr, AM33XX_CONTROL_IPC_MSG_REG0);
>> +	omap_ctrl_writel(data->sleep_mode, AM33XX_CONTROL_IPC_MSG_REG1);
>> +	omap_ctrl_writel(data->param1, AM33XX_CONTROL_IPC_MSG_REG2);
>> +	omap_ctrl_writel(data->param2, AM33XX_CONTROL_IPC_MSG_REG3);
>> +	omap_ctrl_writel(data->param3, AM33XX_CONTROL_IPC_MSG_REG4);
>> +}
>> +
>> +int am33xx_pm_status(void)
>> +{
>> +	int i;
>> +
>> +	i = omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG1);
>> +	i &= IPC_RESP_MASK;
>> +	i >>= __ffs(IPC_RESP_MASK);
>> +
>> +	return i;
>> +}
>> +
>> +int am33xx_pm_wake_src(void)
>> +{
>> +	int i;
>> +
>> +	i = omap_ctrl_readl(AM33XX_CONTROL_IPC_MSG_REG6);
>> +	i &= 0xff;
>> +
>> +	return i;
>> +}
>> +#endif /* CONFIG_SOC_AM33XX && CONFIG_PM */
>> diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
>> index f7d7c2e..9be587c 100644
>> --- a/arch/arm/mach-omap2/control.h
>> +++ b/arch/arm/mach-omap2/control.h
>> @@ -370,6 +370,22 @@
>>   #define AM33XX_DEV_FEATURE		0x604
>>   #define AM33XX_SGX_MASK			BIT(29)
>>
>> +/* AM33XX M3_TXEV_EOI register */
>> +#define AM33XX_CONTROL_M3_TXEV_EOI	0x1324
>> +
>> +#define AM33XX_M3_TXEV_ACK		(0x1 << 0)
>> +#define AM33XX_M3_TXEV_ENABLE		(0x0 << 0)
>> +
>> +/* AM33XX IPC message registers */
>> +#define AM33XX_CONTROL_IPC_MSG_REG0	0x1328
>> +#define AM33XX_CONTROL_IPC_MSG_REG1	0x132C
>> +#define AM33XX_CONTROL_IPC_MSG_REG2	0x1330
>> +#define AM33XX_CONTROL_IPC_MSG_REG3	0x1334
>> +#define AM33XX_CONTROL_IPC_MSG_REG4	0x1338
>> +#define AM33XX_CONTROL_IPC_MSG_REG5	0x133C
>> +#define AM33XX_CONTROL_IPC_MSG_REG6	0x1340
>> +#define AM33XX_CONTROL_IPC_MSG_REG7	0x1344
>> +
>>   /* CONTROL OMAP STATUS register to identify OMAP3 features */
>>   #define OMAP3_CONTROL_OMAP_STATUS	0x044c
>>
>> @@ -429,6 +445,44 @@ extern void omap3630_ctrl_disable_rta(void);
>>   extern int omap3_ctrl_save_padconf(void);
>>   extern void omap2_set_globals_control(void __iomem *ctrl,
>>   				      void __iomem *ctrl_pad);
>> +struct am33xx_ipc_data {
>> +	u32 resume_addr;
>> +	u32 sleep_mode;
>> +	u32 param1;
>> +	u32 param2;
>> +	u32 param3;
>> +	u32 param4;
>> +	u32 param5;
>> +	u32 param6;
>> +};
>> +
>> +#define IPC_RESP_SHIFT			16
>> +#define IPC_RESP_MASK			(0xffff << 16)
>> +
>> +#define M3_VERSION_SHIFT		0
>> +#define M3_VERSION_MASK			(0xffff << 0)
>> +
>> +/*
>> + * 9-4 = VTT GPIO PIN (6 Bits)
>> + *   3 = VTT Status (1 Bit)
>> + * 2-0 = Memory Type (2 Bits)
>> +*/
>> +#define MEM_TYPE_SHIFT		(0x0)
>> +#define MEM_TYPE_MASK		(0x7 << 0)
>> +#define VTT_STAT_SHIFT		(0x3)
>> +#define VTT_STAT_MASK		(0x1 << 3)
>> +#define VTT_GPIO_PIN_SHIFT	(0x4)
>> +#define VTT_GPIO_PIN_MASK	(0x2f << 4)
>> +
>> +extern void am33xx_wkup_m3_ipc_cmd(struct am33xx_ipc_data *data);
>> +extern void am33xx_txev_eoi(void);
>> +extern void am33xx_txev_enable(void);
>> +extern void am33xx_pm_version_clear(void);
>> +extern int am33xx_pm_version_get(void);
>> +extern void am33xx_pm_ipc_cmd(struct am33xx_ipc_data *data);
>> +extern int am33xx_pm_status(void);
>> +extern int am33xx_pm_wake_src(void);
>> +
> Lets address the above better. I don't see a need of 8 functions
> exported doing one or 2 register writes.
>
> Look M3 based handling is going to be there on future SOCs
> as well and this kind of handling of IPC is very short cited.
>

The idea here was to move all control module register accesses into one 
file in planning of implementing a driver for the control module itself 
in the future.

> Probably we should have a separate driver for M3 in linux which
> can have all this local code instead of all these exports.

The wkup_m3 code has been moved to a small driver found in patch 8 of 
this series, would it better to move this code there rather than with 
the rest of the control module code?

>
> Regards,
> Santosh
>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-08 16:06           ` Dave Gerlach
@ 2013-08-08 16:22             ` Nishanth Menon
  -1 siblings, 0 replies; 212+ messages in thread
From: Nishanth Menon @ 2013-08-08 16:22 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: Santosh Shilimkar, Russ Dill, linux-arm-kernel, linux-omap,
	Paul Walmsley, Kevin Hilman, Vaibhav Bedia, Tony Lingren,
	Benoit Cousson

On 08/08/2013 11:06 AM, Dave Gerlach wrote:
> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>> $subject and patch don't match.
>>
>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>    In reference to
>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>> bound and which don't.
>>> Does it need to? M3 firmware can pretty much define "I will force the
>>> device into low power state, and if the drivers dont handle things
>>> properly, fix the darned driver". M3 behavior should be considered as
>>> a "hardware" as far as Linux running on MPU is concerned, and
>>> firmware helps change the behavior by accounting for SoC quirks. *if*
>>> we have ability to handle this in the firmware, there is no need to
>>> carry this in Linux.
>>>
>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>> comment in the last version. Linux need not know about all such firmware
>> quirks. Also all these M3 specific stuff, should be done somewhere
>> else. Probably having a small M3 driver won't be a bad idea.
>>
>> Regards,
>> Santosh
>>
>
> I am not opposed to doing it this way and letting the M3 firmware handle
> idling these modules, however the one concern raised in the last series
> is that an approach that does not acknowledge drivers will hide driver
> PM bugs. I suppose as long as I make sure to document that the devices
> are being idled by the M3 firmware this may not be an issue. I will look
> into implementing this.

yes, but doing it in M3 will ensure it is a "hardware behavior" - from 
debug perspective, you could make M3 firmware "release mode" - which it 
is stringent in terms of forcing all down to target state, OR "debug" 
where it does nothing - thus helping pick up driver bugs. With M3 in the 
picture, we now have an awesome flexibility of "defining what the 
hardware behavior should be" - that allows us to have lesser code to 
carry in kernel- especially ones(like quirks) that does not really add 
value from power saving strategies.

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-08 16:22             ` Nishanth Menon
  0 siblings, 0 replies; 212+ messages in thread
From: Nishanth Menon @ 2013-08-08 16:22 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/08/2013 11:06 AM, Dave Gerlach wrote:
> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>> $subject and patch don't match.
>>
>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>    In reference to
>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>> bound and which don't.
>>> Does it need to? M3 firmware can pretty much define "I will force the
>>> device into low power state, and if the drivers dont handle things
>>> properly, fix the darned driver". M3 behavior should be considered as
>>> a "hardware" as far as Linux running on MPU is concerned, and
>>> firmware helps change the behavior by accounting for SoC quirks. *if*
>>> we have ability to handle this in the firmware, there is no need to
>>> carry this in Linux.
>>>
>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>> comment in the last version. Linux need not know about all such firmware
>> quirks. Also all these M3 specific stuff, should be done somewhere
>> else. Probably having a small M3 driver won't be a bad idea.
>>
>> Regards,
>> Santosh
>>
>
> I am not opposed to doing it this way and letting the M3 firmware handle
> idling these modules, however the one concern raised in the last series
> is that an approach that does not acknowledge drivers will hide driver
> PM bugs. I suppose as long as I make sure to document that the devices
> are being idled by the M3 firmware this may not be an issue. I will look
> into implementing this.

yes, but doing it in M3 will ensure it is a "hardware behavior" - from 
debug perspective, you could make M3 firmware "release mode" - which it 
is stringent in terms of forcing all down to target state, OR "debug" 
where it does nothing - thus helping pick up driver bugs. With M3 in the 
picture, we now have an awesome flexibility of "defining what the 
hardware behavior should be" - that allows us to have lesser code to 
carry in kernel- especially ones(like quirks) that does not really add 
value from power saving strategies.

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08 18:16     ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-08 18:16 UTC (permalink / raw)
  To: Dave Gerlach; +Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Vaibhav Bedia

Dave Gerlach <d-gerlach@ti.com> writes:

> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> SDRAM controller on AM33XX requires that a modification of certain
> bit-fields in PWR_MGMT_CTRL register (ref. section 7.3.5.13 in
> AM335x-Rev H) is followed by a dummy read access to SDRAM. This
> scenario arises when entering a low power state like DeepSleep.
> To ensure that the read is not from a cached region we reserve
> some memory during bootup using the arm_memblock_steal() API.

Hmm, sounds to me an awful lot like the existing omap_bus_sync() ?

However, you remove that feature when you remove omap_reserve() here
becasue omap_reserve() ss not called from your new reserve function.
Are you *really* sure you don't need the functions called there?  This
is a pretty big change that's not mentioned anywhere in the changelog.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
@ 2013-08-08 18:16     ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-08 18:16 UTC (permalink / raw)
  To: linux-arm-kernel

Dave Gerlach <d-gerlach@ti.com> writes:

> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> SDRAM controller on AM33XX requires that a modification of certain
> bit-fields in PWR_MGMT_CTRL register (ref. section 7.3.5.13 in
> AM335x-Rev H) is followed by a dummy read access to SDRAM. This
> scenario arises when entering a low power state like DeepSleep.
> To ensure that the read is not from a cached region we reserve
> some memory during bootup using the arm_memblock_steal() API.

Hmm, sounds to me an awful lot like the existing omap_bus_sync() ?

However, you remove that feature when you remove omap_reserve() here
becasue omap_reserve() ss not called from your new reserve function.
Are you *really* sure you don't need the functions called there?  This
is a pretty big change that's not mentioned anywhere in the changelog.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 6/9] ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-08 18:25     ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-08 18:25 UTC (permalink / raw)
  To: Dave Gerlach; +Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Vaibhav Bedia

Dave Gerlach <d-gerlach@ti.com> writes:

> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> OMAP timer code registers two timers - one as clocksource
> and one as clockevent. Since AM33XX has only one usable timer
> in the WKUP domain one of the timers needs suspend-resume
> support to restore the configuration to pre-suspend state.
>
> commit adc78e6 (timekeeping: Add suspend and resume
> of clock event devices) introduced .suspend and .resume
> callbacks for clock event devices. Leverages these
> callbacks to have AM33XX clockevent timer which is
> in not in WKUP domain to behave properly across system
> suspend.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> ---
>  arch/arm/mach-omap2/timer.c |   32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
>
> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
> index b37e1fc..cce5d39 100644
> --- a/arch/arm/mach-omap2/timer.c
> +++ b/arch/arm/mach-omap2/timer.c
> @@ -118,11 +118,43 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
>  	}
>  }
>  
> +static void omap_clkevt_suspend(struct clock_event_device *unused)
> +{
> +	char name[10];
> +	struct omap_hwmod *oh;
> +
> +	sprintf(name, "timer%d", clkev.id);
> +	oh = omap_hwmod_lookup(name);

/me stops reviewing here.  This should be a one-time thing.

Seeing things *again* in patches that I've already reviewed (multiple
times) is very frustrating.  It also increases the likelihood of future
patches to be "filtered."  (in this case, you get a pass since you seem
to have inherited Vaibhav's code, but please take care to address all
reviewer comments, or at least explain why you didn'.)

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 6/9] ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device
@ 2013-08-08 18:25     ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-08 18:25 UTC (permalink / raw)
  To: linux-arm-kernel

Dave Gerlach <d-gerlach@ti.com> writes:

> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> OMAP timer code registers two timers - one as clocksource
> and one as clockevent. Since AM33XX has only one usable timer
> in the WKUP domain one of the timers needs suspend-resume
> support to restore the configuration to pre-suspend state.
>
> commit adc78e6 (timekeeping: Add suspend and resume
> of clock event devices) introduced .suspend and .resume
> callbacks for clock event devices. Leverages these
> callbacks to have AM33XX clockevent timer which is
> in not in WKUP domain to behave properly across system
> suspend.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> ---
>  arch/arm/mach-omap2/timer.c |   32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
>
> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
> index b37e1fc..cce5d39 100644
> --- a/arch/arm/mach-omap2/timer.c
> +++ b/arch/arm/mach-omap2/timer.c
> @@ -118,11 +118,43 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
>  	}
>  }
>  
> +static void omap_clkevt_suspend(struct clock_event_device *unused)
> +{
> +	char name[10];
> +	struct omap_hwmod *oh;
> +
> +	sprintf(name, "timer%d", clkev.id);
> +	oh = omap_hwmod_lookup(name);

/me stops reviewing here.  This should be a one-time thing.

Seeing things *again* in patches that I've already reviewed (multiple
times) is very frustrating.  It also increases the likelihood of future
patches to be "filtered."  (in this case, you get a pass since you seem
to have inherited Vaibhav's code, but please take care to address all
reviewer comments, or at least explain why you didn'.)

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
  2013-08-08 18:16     ` Kevin Hilman
@ 2013-08-08 19:31       ` Santosh Shilimkar
  -1 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 19:31 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Dave Gerlach, linux-arm-kernel, linux-omap, Paul Walmsley, Vaibhav Bedia

On Thursday 08 August 2013 02:16 PM, Kevin Hilman wrote:
> Dave Gerlach <d-gerlach@ti.com> writes:
> 
>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>
>> SDRAM controller on AM33XX requires that a modification of certain
>> bit-fields in PWR_MGMT_CTRL register (ref. section 7.3.5.13 in
>> AM335x-Rev H) is followed by a dummy read access to SDRAM. This
>> scenario arises when entering a low power state like DeepSleep.
>> To ensure that the read is not from a cached region we reserve
>> some memory during bootup using the arm_memblock_steal() API.
> 
> Hmm, sounds to me an awful lot like the existing omap_bus_sync() ?
>
All the credit of that awful omap_bus_sync() goes to me since 
I introduced it. And I keep beating the hardware guys
who have not left a choice but to introduce the ugly work
around in software. ;-)

Regards,
Santosh
 


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
@ 2013-08-08 19:31       ` Santosh Shilimkar
  0 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 19:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 08 August 2013 02:16 PM, Kevin Hilman wrote:
> Dave Gerlach <d-gerlach@ti.com> writes:
> 
>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>
>> SDRAM controller on AM33XX requires that a modification of certain
>> bit-fields in PWR_MGMT_CTRL register (ref. section 7.3.5.13 in
>> AM335x-Rev H) is followed by a dummy read access to SDRAM. This
>> scenario arises when entering a low power state like DeepSleep.
>> To ensure that the read is not from a cached region we reserve
>> some memory during bootup using the arm_memblock_steal() API.
> 
> Hmm, sounds to me an awful lot like the existing omap_bus_sync() ?
>
All the credit of that awful omap_bus_sync() goes to me since 
I introduced it. And I keep beating the hardware guys
who have not left a choice but to introduce the ugly work
around in software. ;-)

Regards,
Santosh
 

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 6/9] ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device
  2013-08-08 18:25     ` Kevin Hilman
@ 2013-08-08 19:49       ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-08 19:49 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Paul Walmsley, linux-omap, Vaibhav Bedia, linux-arm-kernel

On 08/08/2013 01:25 PM, Kevin Hilman wrote:
> Dave Gerlach <d-gerlach@ti.com> writes:
>
>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>
>> OMAP timer code registers two timers - one as clocksource
>> and one as clockevent. Since AM33XX has only one usable timer
>> in the WKUP domain one of the timers needs suspend-resume
>> support to restore the configuration to pre-suspend state.
>>
>> commit adc78e6 (timekeeping: Add suspend and resume
>> of clock event devices) introduced .suspend and .resume
>> callbacks for clock event devices. Leverages these
>> callbacks to have AM33XX clockevent timer which is
>> in not in WKUP domain to behave properly across system
>> suspend.
>>
>> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>> ---
>>   arch/arm/mach-omap2/timer.c |   32 ++++++++++++++++++++++++++++++++
>>   1 file changed, 32 insertions(+)
>>
>> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
>> index b37e1fc..cce5d39 100644
>> --- a/arch/arm/mach-omap2/timer.c
>> +++ b/arch/arm/mach-omap2/timer.c
>> @@ -118,11 +118,43 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
>>   	}
>>   }
>>
>> +static void omap_clkevt_suspend(struct clock_event_device *unused)
>> +{
>> +	char name[10];
>> +	struct omap_hwmod *oh;
>> +
>> +	sprintf(name, "timer%d", clkev.id);
>> +	oh = omap_hwmod_lookup(name);
>
> /me stops reviewing here.  This should be a one-time thing.
>
> Seeing things *again* in patches that I've already reviewed (multiple
> times) is very frustrating.  It also increases the likelihood of future
> patches to be "filtered."  (in this case, you get a pass since you seem
> to have inherited Vaibhav's code, but please take care to address all
> reviewer comments, or at least explain why you didn'.)
>
> Kevin
>

Sorry for missing this. Seems I missed this patch completely when taking 
over. I'll make sure it's addressed in the next version.

Regards,
Dave

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 6/9] ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device
@ 2013-08-08 19:49       ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-08 19:49 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/08/2013 01:25 PM, Kevin Hilman wrote:
> Dave Gerlach <d-gerlach@ti.com> writes:
>
>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>
>> OMAP timer code registers two timers - one as clocksource
>> and one as clockevent. Since AM33XX has only one usable timer
>> in the WKUP domain one of the timers needs suspend-resume
>> support to restore the configuration to pre-suspend state.
>>
>> commit adc78e6 (timekeeping: Add suspend and resume
>> of clock event devices) introduced .suspend and .resume
>> callbacks for clock event devices. Leverages these
>> callbacks to have AM33XX clockevent timer which is
>> in not in WKUP domain to behave properly across system
>> suspend.
>>
>> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>> ---
>>   arch/arm/mach-omap2/timer.c |   32 ++++++++++++++++++++++++++++++++
>>   1 file changed, 32 insertions(+)
>>
>> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
>> index b37e1fc..cce5d39 100644
>> --- a/arch/arm/mach-omap2/timer.c
>> +++ b/arch/arm/mach-omap2/timer.c
>> @@ -118,11 +118,43 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
>>   	}
>>   }
>>
>> +static void omap_clkevt_suspend(struct clock_event_device *unused)
>> +{
>> +	char name[10];
>> +	struct omap_hwmod *oh;
>> +
>> +	sprintf(name, "timer%d", clkev.id);
>> +	oh = omap_hwmod_lookup(name);
>
> /me stops reviewing here.  This should be a one-time thing.
>
> Seeing things *again* in patches that I've already reviewed (multiple
> times) is very frustrating.  It also increases the likelihood of future
> patches to be "filtered."  (in this case, you get a pass since you seem
> to have inherited Vaibhav's code, but please take care to address all
> reviewer comments, or at least explain why you didn'.)
>
> Kevin
>

Sorry for missing this. Seems I missed this patch completely when taking 
over. I'll make sure it's addressed in the next version.

Regards,
Dave

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
  2013-08-08 19:31       ` Santosh Shilimkar
@ 2013-08-08 20:05         ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-08 20:05 UTC (permalink / raw)
  To: Santosh Shilimkar
  Cc: Dave Gerlach, linux-arm-kernel, linux-omap, Paul Walmsley, Vaibhav Bedia

Santosh Shilimkar <santosh.shilimkar@ti.com> writes:

> On Thursday 08 August 2013 02:16 PM, Kevin Hilman wrote:
>> Dave Gerlach <d-gerlach@ti.com> writes:
>> 
>>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>>
>>> SDRAM controller on AM33XX requires that a modification of certain
>>> bit-fields in PWR_MGMT_CTRL register (ref. section 7.3.5.13 in
>>> AM335x-Rev H) is followed by a dummy read access to SDRAM. This
>>> scenario arises when entering a low power state like DeepSleep.
>>> To ensure that the read is not from a cached region we reserve
>>> some memory during bootup using the arm_memblock_steal() API.
>> 
>> Hmm, sounds to me an awful lot like the existing omap_bus_sync() ?
>>
> All the credit of that awful omap_bus_sync() goes to me since 
> I introduced it. And I keep beating the hardware guys
> who have not left a choice but to introduce the ugly work
> around in software. ;-)

Agreed, but what's even more awful than the current version is
duplicating it in a slightly different way using yet another whole page
mapping for a single read/write location.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
@ 2013-08-08 20:05         ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-08 20:05 UTC (permalink / raw)
  To: linux-arm-kernel

Santosh Shilimkar <santosh.shilimkar@ti.com> writes:

> On Thursday 08 August 2013 02:16 PM, Kevin Hilman wrote:
>> Dave Gerlach <d-gerlach@ti.com> writes:
>> 
>>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>>
>>> SDRAM controller on AM33XX requires that a modification of certain
>>> bit-fields in PWR_MGMT_CTRL register (ref. section 7.3.5.13 in
>>> AM335x-Rev H) is followed by a dummy read access to SDRAM. This
>>> scenario arises when entering a low power state like DeepSleep.
>>> To ensure that the read is not from a cached region we reserve
>>> some memory during bootup using the arm_memblock_steal() API.
>> 
>> Hmm, sounds to me an awful lot like the existing omap_bus_sync() ?
>>
> All the credit of that awful omap_bus_sync() goes to me since 
> I introduced it. And I keep beating the hardware guys
> who have not left a choice but to introduce the ugly work
> around in software. ;-)

Agreed, but what's even more awful than the current version is
duplicating it in a slightly different way using yet another whole page
mapping for a single read/write location.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
  2013-08-08 20:05         ` Kevin Hilman
@ 2013-08-08 20:11           ` Santosh Shilimkar
  -1 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 20:11 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Dave Gerlach, linux-arm-kernel, linux-omap, Paul Walmsley, Vaibhav Bedia

On Thursday 08 August 2013 04:05 PM, Kevin Hilman wrote:
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> 
>> On Thursday 08 August 2013 02:16 PM, Kevin Hilman wrote:
>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>
>>>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>>>
>>>> SDRAM controller on AM33XX requires that a modification of certain
>>>> bit-fields in PWR_MGMT_CTRL register (ref. section 7.3.5.13 in
>>>> AM335x-Rev H) is followed by a dummy read access to SDRAM. This
>>>> scenario arises when entering a low power state like DeepSleep.
>>>> To ensure that the read is not from a cached region we reserve
>>>> some memory during bootup using the arm_memblock_steal() API.
>>>
>>> Hmm, sounds to me an awful lot like the existing omap_bus_sync() ?
>>>
>> All the credit of that awful omap_bus_sync() goes to me since 
>> I introduced it. And I keep beating the hardware guys
>> who have not left a choice but to introduce the ugly work
>> around in software. ;-)
> 
> Agreed, but what's even more awful than the current version is
> duplicating it in a slightly different way using yet another whole page
> mapping for a single read/write location.
> 
The real issue is limitation of the kernel memory steal(memblock) API which
won't let you still less than 1 MB. It would have been ok for page allocation
because that is any way what you will get minimum on standard non-cached
allocations.

Regards,
Santosh


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
@ 2013-08-08 20:11           ` Santosh Shilimkar
  0 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-08 20:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 08 August 2013 04:05 PM, Kevin Hilman wrote:
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> 
>> On Thursday 08 August 2013 02:16 PM, Kevin Hilman wrote:
>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>
>>>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>>>
>>>> SDRAM controller on AM33XX requires that a modification of certain
>>>> bit-fields in PWR_MGMT_CTRL register (ref. section 7.3.5.13 in
>>>> AM335x-Rev H) is followed by a dummy read access to SDRAM. This
>>>> scenario arises when entering a low power state like DeepSleep.
>>>> To ensure that the read is not from a cached region we reserve
>>>> some memory during bootup using the arm_memblock_steal() API.
>>>
>>> Hmm, sounds to me an awful lot like the existing omap_bus_sync() ?
>>>
>> All the credit of that awful omap_bus_sync() goes to me since 
>> I introduced it. And I keep beating the hardware guys
>> who have not left a choice but to introduce the ugly work
>> around in software. ;-)
> 
> Agreed, but what's even more awful than the current version is
> duplicating it in a slightly different way using yet another whole page
> mapping for a single read/write location.
> 
The real issue is limitation of the kernel memory steal(memblock) API which
won't let you still less than 1 MB. It would have been ok for page allocation
because that is any way what you will get minimum on standard non-cached
allocations.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-08 16:06           ` Dave Gerlach
@ 2013-08-08 21:14             ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-08 21:14 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: Santosh Shilimkar, Nishanth Menon, Russ Dill, linux-arm-kernel,
	linux-omap, Paul Walmsley, Vaibhav Bedia, Tony Lingren,
	Benoit Cousson

Dave Gerlach <d-gerlach@ti.com> writes:

> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>> $subject and patch don't match.
>>
>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>    In reference to
>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>> bound and which don't.
>>> Does it need to? M3 firmware can pretty much define "I will force
>>> the device into low power state, and if the drivers dont handle
>>> things properly, fix the darned driver". M3 behavior should be
>>> considered as a "hardware" as far as Linux running on MPU is
>>> concerned, and firmware helps change the behavior by accounting for
>>> SoC quirks. *if* we have ability to handle this in the firmware,
>>> there is no need to carry this in Linux.
>>>
>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>> comment in the last version. Linux need not know about all such firmware
>> quirks. Also all these M3 specific stuff, should be done somewhere
>> else. Probably having a small M3 driver won't be a bad idea.
>>
>> Regards,
>> Santosh
>>
>
> I am not opposed to doing it this way and letting the M3 firmware
> handle idling these modules, however the one concern raised in the
> last series is that an approach that does not acknowledge drivers will
> hide driver PM bugs. I suppose as long as I make sure to document that
> the devices are being idled by the M3 firmware this may not be an
> issue. I will look into implementing this.

No, please don't start idling devices in firmware that are otherwise
managed by Linux.  Keep the firmware simple and dumb.  Linux is managing
these devices, it should manage their bugs too.

This is not just about idling devices.  This is about handling broken IP
blocks whose power-on reset state does not allow the the powerdomain to
reach its target state.  That's just bad hardware design.  

That being said, IMO, the kernel (specifically omap_device) should
handle this, and it should be rather easy to do in the omap_device layer
and keep the SoC suspend/resume core code simple and ignorant of these
"quirks."

AFAICT, there's no reason these quirks need to be dealt with immediatly
on suspend.  A slight delay should be fine, as long as it's before the
next suspend/idle attempt, right?  

Given that, what we need to do (and by we, I mean you) is to flag all
broken IP blocks, and let omap_device handle them in a suspend/resume
notifier (c.f. register_pm_notifier() and PM_POST_SUSPEND.)

That will keep things contained to the omap_device/hwmod level and allow
flexiblity for future broken SoCs where the list of broken IP blocks is
different.  Though surely this broken hardware doesn't exist in AM4xxx
because someone noticed this early on and pointed out that it should be
fixed in hardware, right?  ;)

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-08 21:14             ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-08 21:14 UTC (permalink / raw)
  To: linux-arm-kernel

Dave Gerlach <d-gerlach@ti.com> writes:

> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>> $subject and patch don't match.
>>
>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>    In reference to
>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>> bound and which don't.
>>> Does it need to? M3 firmware can pretty much define "I will force
>>> the device into low power state, and if the drivers dont handle
>>> things properly, fix the darned driver". M3 behavior should be
>>> considered as a "hardware" as far as Linux running on MPU is
>>> concerned, and firmware helps change the behavior by accounting for
>>> SoC quirks. *if* we have ability to handle this in the firmware,
>>> there is no need to carry this in Linux.
>>>
>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>> comment in the last version. Linux need not know about all such firmware
>> quirks. Also all these M3 specific stuff, should be done somewhere
>> else. Probably having a small M3 driver won't be a bad idea.
>>
>> Regards,
>> Santosh
>>
>
> I am not opposed to doing it this way and letting the M3 firmware
> handle idling these modules, however the one concern raised in the
> last series is that an approach that does not acknowledge drivers will
> hide driver PM bugs. I suppose as long as I make sure to document that
> the devices are being idled by the M3 firmware this may not be an
> issue. I will look into implementing this.

No, please don't start idling devices in firmware that are otherwise
managed by Linux.  Keep the firmware simple and dumb.  Linux is managing
these devices, it should manage their bugs too.

This is not just about idling devices.  This is about handling broken IP
blocks whose power-on reset state does not allow the the powerdomain to
reach its target state.  That's just bad hardware design.  

That being said, IMO, the kernel (specifically omap_device) should
handle this, and it should be rather easy to do in the omap_device layer
and keep the SoC suspend/resume core code simple and ignorant of these
"quirks."

AFAICT, there's no reason these quirks need to be dealt with immediatly
on suspend.  A slight delay should be fine, as long as it's before the
next suspend/idle attempt, right?  

Given that, what we need to do (and by we, I mean you) is to flag all
broken IP blocks, and let omap_device handle them in a suspend/resume
notifier (c.f. register_pm_notifier() and PM_POST_SUSPEND.)

That will keep things contained to the omap_device/hwmod level and allow
flexiblity for future broken SoCs where the list of broken IP blocks is
different.  Though surely this broken hardware doesn't exist in AM4xxx
because someone noticed this early on and pointed out that it should be
fixed in hardware, right?  ;)

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-08 21:14             ` Kevin Hilman
@ 2013-08-08 21:32               ` Nishanth Menon
  -1 siblings, 0 replies; 212+ messages in thread
From: Nishanth Menon @ 2013-08-08 21:32 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Dave Gerlach, Santosh Shilimkar, Russ Dill, linux-arm-kernel,
	linux-omap, Paul Walmsley, Vaibhav Bedia, Tony Lingren,
	Benoit Cousson

On 08/08/2013 04:14 PM, Kevin Hilman wrote:
> Dave Gerlach <d-gerlach@ti.com> writes:
>
>> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>>> $subject and patch don't match.
>>>
>>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>>     In reference to
>>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>>> bound and which don't.
>>>> Does it need to? M3 firmware can pretty much define "I will force
>>>> the device into low power state, and if the drivers dont handle
>>>> things properly, fix the darned driver". M3 behavior should be
>>>> considered as a "hardware" as far as Linux running on MPU is
>>>> concerned, and firmware helps change the behavior by accounting for
>>>> SoC quirks. *if* we have ability to handle this in the firmware,
>>>> there is no need to carry this in Linux.
>>>>
>>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>>> comment in the last version. Linux need not know about all such firmware
>>> quirks. Also all these M3 specific stuff, should be done somewhere
>>> else. Probably having a small M3 driver won't be a bad idea.
 >>
>> I am not opposed to doing it this way and letting the M3 firmware
>> handle idling these modules, however the one concern raised in the
>> last series is that an approach that does not acknowledge drivers will
>> hide driver PM bugs. I suppose as long as I make sure to document that
>> the devices are being idled by the M3 firmware this may not be an
>> issue. I will look into implementing this.
>
> No, please don't start idling devices in firmware that are otherwise
> managed by Linux.  Keep the firmware simple and dumb.  Linux is managing
> these devices, it should manage their bugs too.

>
> This is not just about idling devices.  This is about handling broken IP
> blocks whose power-on reset state does not allow the the powerdomain to
> reach its target state.  That's just bad hardware design.

Right, this is where M3 can help -> provide a consistent state for linux 
kernel to work with. by the fact that we want to keep majority of the 
power code inside master CPU, we are just letting M3 help us with 
nothing major at all.. tiny stuff like these can help "fix" the hardware 
design quirks by hiding it behind the firmware and modifying the 
hardware behavior. I know it breaks the purity of role, but as the next 
evolution, we might want to consider M3 something like an "accelerator" 
for power management activity.. (not saying it is that fast.. but 
conceptually).

>
> That being said, IMO, the kernel (specifically omap_device) should
> handle this, and it should be rather easy to do in the omap_device layer
> and keep the SoC suspend/resume core code simple and ignorant of these
> "quirks."
>
> AFAICT, there's no reason these quirks need to be dealt with immediatly
> on suspend.  A slight delay should be fine, as long as it's before the
> next suspend/idle attempt, right?
>
> Given that, what we need to do (and by we, I mean you) is to flag all
> broken IP blocks, and let omap_device handle them in a suspend/resume
> notifier (c.f. register_pm_notifier() and PM_POST_SUSPEND.)

yes - that is the alternate that comes to mind.

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-08 21:32               ` Nishanth Menon
  0 siblings, 0 replies; 212+ messages in thread
From: Nishanth Menon @ 2013-08-08 21:32 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/08/2013 04:14 PM, Kevin Hilman wrote:
> Dave Gerlach <d-gerlach@ti.com> writes:
>
>> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>>> $subject and patch don't match.
>>>
>>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>>     In reference to
>>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>>> bound and which don't.
>>>> Does it need to? M3 firmware can pretty much define "I will force
>>>> the device into low power state, and if the drivers dont handle
>>>> things properly, fix the darned driver". M3 behavior should be
>>>> considered as a "hardware" as far as Linux running on MPU is
>>>> concerned, and firmware helps change the behavior by accounting for
>>>> SoC quirks. *if* we have ability to handle this in the firmware,
>>>> there is no need to carry this in Linux.
>>>>
>>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>>> comment in the last version. Linux need not know about all such firmware
>>> quirks. Also all these M3 specific stuff, should be done somewhere
>>> else. Probably having a small M3 driver won't be a bad idea.
 >>
>> I am not opposed to doing it this way and letting the M3 firmware
>> handle idling these modules, however the one concern raised in the
>> last series is that an approach that does not acknowledge drivers will
>> hide driver PM bugs. I suppose as long as I make sure to document that
>> the devices are being idled by the M3 firmware this may not be an
>> issue. I will look into implementing this.
>
> No, please don't start idling devices in firmware that are otherwise
> managed by Linux.  Keep the firmware simple and dumb.  Linux is managing
> these devices, it should manage their bugs too.

>
> This is not just about idling devices.  This is about handling broken IP
> blocks whose power-on reset state does not allow the the powerdomain to
> reach its target state.  That's just bad hardware design.

Right, this is where M3 can help -> provide a consistent state for linux 
kernel to work with. by the fact that we want to keep majority of the 
power code inside master CPU, we are just letting M3 help us with 
nothing major at all.. tiny stuff like these can help "fix" the hardware 
design quirks by hiding it behind the firmware and modifying the 
hardware behavior. I know it breaks the purity of role, but as the next 
evolution, we might want to consider M3 something like an "accelerator" 
for power management activity.. (not saying it is that fast.. but 
conceptually).

>
> That being said, IMO, the kernel (specifically omap_device) should
> handle this, and it should be rather easy to do in the omap_device layer
> and keep the SoC suspend/resume core code simple and ignorant of these
> "quirks."
>
> AFAICT, there's no reason these quirks need to be dealt with immediatly
> on suspend.  A slight delay should be fine, as long as it's before the
> next suspend/idle attempt, right?
>
> Given that, what we need to do (and by we, I mean you) is to flag all
> broken IP blocks, and let omap_device handle them in a suspend/resume
> notifier (c.f. register_pm_notifier() and PM_POST_SUSPEND.)

yes - that is the alternate that comes to mind.

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-08 21:32               ` Nishanth Menon
@ 2013-08-08 23:04                 ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-08 23:04 UTC (permalink / raw)
  To: Nishanth Menon
  Cc: Dave Gerlach, Santosh Shilimkar, Russ Dill, linux-arm-kernel,
	linux-omap, Paul Walmsley, Vaibhav Bedia, Tony Lingren,
	Benoit Cousson

Nishanth Menon <nm@ti.com> writes:

> On 08/08/2013 04:14 PM, Kevin Hilman wrote:
>> Dave Gerlach <d-gerlach@ti.com> writes:
>>
>>> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>>>> $subject and patch don't match.
>>>>
>>>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>>>     In reference to
>>>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>>>> bound and which don't.
>>>>> Does it need to? M3 firmware can pretty much define "I will force
>>>>> the device into low power state, and if the drivers dont handle
>>>>> things properly, fix the darned driver". M3 behavior should be
>>>>> considered as a "hardware" as far as Linux running on MPU is
>>>>> concerned, and firmware helps change the behavior by accounting for
>>>>> SoC quirks. *if* we have ability to handle this in the firmware,
>>>>> there is no need to carry this in Linux.
>>>>>
>>>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>>>> comment in the last version. Linux need not know about all such firmware
>>>> quirks. Also all these M3 specific stuff, should be done somewhere
>>>> else. Probably having a small M3 driver won't be a bad idea.
>>>
>>> I am not opposed to doing it this way and letting the M3 firmware
>>> handle idling these modules, however the one concern raised in the
>>> last series is that an approach that does not acknowledge drivers will
>>> hide driver PM bugs. I suppose as long as I make sure to document that
>>> the devices are being idled by the M3 firmware this may not be an
>>> issue. I will look into implementing this.
>>
>> No, please don't start idling devices in firmware that are otherwise
>> managed by Linux.  Keep the firmware simple and dumb.  Linux is managing
>> these devices, it should manage their bugs too.
>
>>
>> This is not just about idling devices.  This is about handling broken IP
>> blocks whose power-on reset state does not allow the the powerdomain to
>> reach its target state.  That's just bad hardware design.
>
> Right, this is where M3 can help -> provide a consistent state for
> linux kernel to work with. by the fact that we want to keep majority
> of the power code inside master CPU, we are just letting M3 help us
> with nothing major at all.. 

heh, I would say HW design bugs like this are more than "nothing major
at all." :)  

> tiny stuff like these can help "fix" the hardware design quirks by
> hiding it behind the firmware and modifying the hardware behavior.

I disagree here.  I'm a firmware minimalist, and hiding bugs like this
in the firmware is wrong when Linux is otherwise managing these devices.
It also imposes criteria on the firmware of future SoCs that doesn't
belong there either.  IMO, the only stuff the firmware should do is what
Linux *cannot* do.

Remember, this only needs to happen when there isn't a driver for these
devices.  Should we communicate to the firmware that the OS has no
driver, so please enable the hack?  I think not.

> I know it breaks the purity of role, but as the
> next evolution, we might want to consider M3 something like an
> "accelerator" for power management activity.. (not saying it is that
> fast.. but conceptually).

Yes, it breaks the purity of role, and makes it hard to maintain and
extend to future SoCs.  As a maintainer, that's a red flag.  IMO, the
roles need to be kept clear.  The M3 manages some devices and the
interconnect that MPU/Linux cannot, the rest are managed by Linux.

>> That being said, IMO, the kernel (specifically omap_device) should
>> handle this, and it should be rather easy to do in the omap_device layer
>> and keep the SoC suspend/resume core code simple and ignorant of these
>> "quirks."
>>
>> AFAICT, there's no reason these quirks need to be dealt with immediatly
>> on suspend.  A slight delay should be fine, as long as it's before the
>> next suspend/idle attempt, right?
>>
>> Given that, what we need to do (and by we, I mean you) is to flag all
>> broken IP blocks, and let omap_device handle them in a suspend/resume
>> notifier (c.f. register_pm_notifier() and PM_POST_SUSPEND.)
>
> yes - that is the alternate that comes to mind.

In the earlier reviews of this series (many months ago now), I
complained about the presence of this device specific handling in the
core MPU PM code.  I'm somewhat troubled by the fact that nobody explored
alternatives that so easily come to mind.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-08 23:04                 ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-08 23:04 UTC (permalink / raw)
  To: linux-arm-kernel

Nishanth Menon <nm@ti.com> writes:

> On 08/08/2013 04:14 PM, Kevin Hilman wrote:
>> Dave Gerlach <d-gerlach@ti.com> writes:
>>
>>> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>>>> $subject and patch don't match.
>>>>
>>>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>>>     In reference to
>>>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>>>> bound and which don't.
>>>>> Does it need to? M3 firmware can pretty much define "I will force
>>>>> the device into low power state, and if the drivers dont handle
>>>>> things properly, fix the darned driver". M3 behavior should be
>>>>> considered as a "hardware" as far as Linux running on MPU is
>>>>> concerned, and firmware helps change the behavior by accounting for
>>>>> SoC quirks. *if* we have ability to handle this in the firmware,
>>>>> there is no need to carry this in Linux.
>>>>>
>>>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>>>> comment in the last version. Linux need not know about all such firmware
>>>> quirks. Also all these M3 specific stuff, should be done somewhere
>>>> else. Probably having a small M3 driver won't be a bad idea.
>>>
>>> I am not opposed to doing it this way and letting the M3 firmware
>>> handle idling these modules, however the one concern raised in the
>>> last series is that an approach that does not acknowledge drivers will
>>> hide driver PM bugs. I suppose as long as I make sure to document that
>>> the devices are being idled by the M3 firmware this may not be an
>>> issue. I will look into implementing this.
>>
>> No, please don't start idling devices in firmware that are otherwise
>> managed by Linux.  Keep the firmware simple and dumb.  Linux is managing
>> these devices, it should manage their bugs too.
>
>>
>> This is not just about idling devices.  This is about handling broken IP
>> blocks whose power-on reset state does not allow the the powerdomain to
>> reach its target state.  That's just bad hardware design.
>
> Right, this is where M3 can help -> provide a consistent state for
> linux kernel to work with. by the fact that we want to keep majority
> of the power code inside master CPU, we are just letting M3 help us
> with nothing major at all.. 

heh, I would say HW design bugs like this are more than "nothing major
at all." :)  

> tiny stuff like these can help "fix" the hardware design quirks by
> hiding it behind the firmware and modifying the hardware behavior.

I disagree here.  I'm a firmware minimalist, and hiding bugs like this
in the firmware is wrong when Linux is otherwise managing these devices.
It also imposes criteria on the firmware of future SoCs that doesn't
belong there either.  IMO, the only stuff the firmware should do is what
Linux *cannot* do.

Remember, this only needs to happen when there isn't a driver for these
devices.  Should we communicate to the firmware that the OS has no
driver, so please enable the hack?  I think not.

> I know it breaks the purity of role, but as the
> next evolution, we might want to consider M3 something like an
> "accelerator" for power management activity.. (not saying it is that
> fast.. but conceptually).

Yes, it breaks the purity of role, and makes it hard to maintain and
extend to future SoCs.  As a maintainer, that's a red flag.  IMO, the
roles need to be kept clear.  The M3 manages some devices and the
interconnect that MPU/Linux cannot, the rest are managed by Linux.

>> That being said, IMO, the kernel (specifically omap_device) should
>> handle this, and it should be rather easy to do in the omap_device layer
>> and keep the SoC suspend/resume core code simple and ignorant of these
>> "quirks."
>>
>> AFAICT, there's no reason these quirks need to be dealt with immediatly
>> on suspend.  A slight delay should be fine, as long as it's before the
>> next suspend/idle attempt, right?
>>
>> Given that, what we need to do (and by we, I mean you) is to flag all
>> broken IP blocks, and let omap_device handle them in a suspend/resume
>> notifier (c.f. register_pm_notifier() and PM_POST_SUSPEND.)
>
> yes - that is the alternate that comes to mind.

In the earlier reviews of this series (many months ago now), I
complained about the presence of this device specific handling in the
core MPU PM code.  I'm somewhat troubled by the fact that nobody explored
alternatives that so easily come to mind.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-08 16:16       ` Dave Gerlach
@ 2013-08-09  5:11         ` Tony Lindgren
  -1 siblings, 0 replies; 212+ messages in thread
From: Tony Lindgren @ 2013-08-09  5:11 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: Santosh Shilimkar, linux-arm-kernel, linux-omap, Paul Walmsley,
	Kevin Hilman, Vaibhav Bedia

* Dave Gerlach <d-gerlach@ti.com> [130808 09:23]:
> On 08/08/2013 08:44 AM, Santosh Shilimkar wrote:
> >Lets address the above better. I don't see a need of 8 functions
> >exported doing one or 2 register writes.
> >
> >Look M3 based handling is going to be there on future SOCs
> >as well and this kind of handling of IPC is very short cited.
> >
> 
> The idea here was to move all control module register accesses into
> one file in planning of implementing a driver for the control module
> itself in the future.
> 
> >Probably we should have a separate driver for M3 in linux which
> >can have all this local code instead of all these exports.
> 
> The wkup_m3 code has been moved to a small driver found in patch 8
> of this series, would it better to move this code there rather than
> with the rest of the control module code?

Please make everything you can into regular device drivers.

We still have some dependencies to mach-omap2 code for PRCM
for example, but we're trying to get all that to live in
drivers.

So for new pieces, let's not add further dependencies to
complicate moving things to drivers.

Regards,

Tony

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-09  5:11         ` Tony Lindgren
  0 siblings, 0 replies; 212+ messages in thread
From: Tony Lindgren @ 2013-08-09  5:11 UTC (permalink / raw)
  To: linux-arm-kernel

* Dave Gerlach <d-gerlach@ti.com> [130808 09:23]:
> On 08/08/2013 08:44 AM, Santosh Shilimkar wrote:
> >Lets address the above better. I don't see a need of 8 functions
> >exported doing one or 2 register writes.
> >
> >Look M3 based handling is going to be there on future SOCs
> >as well and this kind of handling of IPC is very short cited.
> >
> 
> The idea here was to move all control module register accesses into
> one file in planning of implementing a driver for the control module
> itself in the future.
> 
> >Probably we should have a separate driver for M3 in linux which
> >can have all this local code instead of all these exports.
> 
> The wkup_m3 code has been moved to a small driver found in patch 8
> of this series, would it better to move this code there rather than
> with the rest of the control module code?

Please make everything you can into regular device drivers.

We still have some dependencies to mach-omap2 code for PRCM
for example, but we're trying to get all that to live in
drivers.

So for new pieces, let's not add further dependencies to
complicate moving things to drivers.

Regards,

Tony

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
  2013-08-08 20:11           ` Santosh Shilimkar
@ 2013-08-09 15:11             ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-09 15:11 UTC (permalink / raw)
  To: Santosh Shilimkar
  Cc: Dave Gerlach, linux-arm-kernel, linux-omap, Paul Walmsley, Vaibhav Bedia

Santosh Shilimkar <santosh.shilimkar@ti.com> writes:

> On Thursday 08 August 2013 04:05 PM, Kevin Hilman wrote:
>> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>> 
>>> On Thursday 08 August 2013 02:16 PM, Kevin Hilman wrote:
>>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>>
>>>>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>>>>
>>>>> SDRAM controller on AM33XX requires that a modification of certain
>>>>> bit-fields in PWR_MGMT_CTRL register (ref. section 7.3.5.13 in
>>>>> AM335x-Rev H) is followed by a dummy read access to SDRAM. This
>>>>> scenario arises when entering a low power state like DeepSleep.
>>>>> To ensure that the read is not from a cached region we reserve
>>>>> some memory during bootup using the arm_memblock_steal() API.
>>>>
>>>> Hmm, sounds to me an awful lot like the existing omap_bus_sync() ?
>>>>
>>> All the credit of that awful omap_bus_sync() goes to me since 
>>> I introduced it. And I keep beating the hardware guys
>>> who have not left a choice but to introduce the ugly work
>>> around in software. ;-)
>> 
>> Agreed, but what's even more awful than the current version is
>> duplicating it in a slightly different way using yet another whole page
>> mapping for a single read/write location.
>> 
> The real issue is limitation of the kernel memory steal(memblock) API which
> won't let you still less than 1 MB. It would have been ok for page allocation
> because that is any way what you will get minimum on standard non-cached
> allocations.

All the more reason that the omap_bus_sync() should be refactored
slightly in a way that would be reusable for AM33xx.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
@ 2013-08-09 15:11             ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-09 15:11 UTC (permalink / raw)
  To: linux-arm-kernel

Santosh Shilimkar <santosh.shilimkar@ti.com> writes:

> On Thursday 08 August 2013 04:05 PM, Kevin Hilman wrote:
>> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>> 
>>> On Thursday 08 August 2013 02:16 PM, Kevin Hilman wrote:
>>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>>
>>>>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>>>>
>>>>> SDRAM controller on AM33XX requires that a modification of certain
>>>>> bit-fields in PWR_MGMT_CTRL register (ref. section 7.3.5.13 in
>>>>> AM335x-Rev H) is followed by a dummy read access to SDRAM. This
>>>>> scenario arises when entering a low power state like DeepSleep.
>>>>> To ensure that the read is not from a cached region we reserve
>>>>> some memory during bootup using the arm_memblock_steal() API.
>>>>
>>>> Hmm, sounds to me an awful lot like the existing omap_bus_sync() ?
>>>>
>>> All the credit of that awful omap_bus_sync() goes to me since 
>>> I introduced it. And I keep beating the hardware guys
>>> who have not left a choice but to introduce the ugly work
>>> around in software. ;-)
>> 
>> Agreed, but what's even more awful than the current version is
>> duplicating it in a slightly different way using yet another whole page
>> mapping for a single read/write location.
>> 
> The real issue is limitation of the kernel memory steal(memblock) API which
> won't let you still less than 1 MB. It would have been ok for page allocation
> because that is any way what you will get minimum on standard non-cached
> allocations.

All the more reason that the omap_bus_sync() should be refactored
slightly in a way that would be reusable for AM33xx.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-08 23:04                 ` Kevin Hilman
@ 2013-08-09 15:11                   ` Nishanth Menon
  -1 siblings, 0 replies; 212+ messages in thread
From: Nishanth Menon @ 2013-08-09 15:11 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Dave Gerlach, Santosh Shilimkar, Russ Dill, linux-arm-kernel,
	linux-omap, Paul Walmsley, Vaibhav Bedia, Tony Lingren,
	Benoit Cousson

On 08/08/2013 06:04 PM, Kevin Hilman wrote:
> Nishanth Menon <nm@ti.com> writes:
>
>> On 08/08/2013 04:14 PM, Kevin Hilman wrote:
>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>
>>>> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>>>>> $subject and patch don't match.
>>>>>
>>>>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>>>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>>>>      In reference to
>>>>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>>>>> bound and which don't.
>>>>>> Does it need to? M3 firmware can pretty much define "I will force
>>>>>> the device into low power state, and if the drivers dont handle
>>>>>> things properly, fix the darned driver". M3 behavior should be
>>>>>> considered as a "hardware" as far as Linux running on MPU is
>>>>>> concerned, and firmware helps change the behavior by accounting for
>>>>>> SoC quirks. *if* we have ability to handle this in the firmware,
>>>>>> there is no need to carry this in Linux.
>>>>>>
>>>>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>>>>> comment in the last version. Linux need not know about all such firmware
>>>>> quirks. Also all these M3 specific stuff, should be done somewhere
>>>>> else. Probably having a small M3 driver won't be a bad idea.
>>>>
>>>> I am not opposed to doing it this way and letting the M3 firmware
>>>> handle idling these modules, however the one concern raised in the
>>>> last series is that an approach that does not acknowledge drivers will
>>>> hide driver PM bugs. I suppose as long as I make sure to document that
>>>> the devices are being idled by the M3 firmware this may not be an
>>>> issue. I will look into implementing this.
>>>
>>> No, please don't start idling devices in firmware that are otherwise
>>> managed by Linux.  Keep the firmware simple and dumb.  Linux is managing
>>> these devices, it should manage their bugs too.
>>
>>>
>>> This is not just about idling devices.  This is about handling broken IP
>>> blocks whose power-on reset state does not allow the the powerdomain to
>>> reach its target state.  That's just bad hardware design.
>>
>> Right, this is where M3 can help -> provide a consistent state for
>> linux kernel to work with. by the fact that we want to keep majority
>> of the power code inside master CPU, we are just letting M3 help us
>> with nothing major at all..
>
> heh, I would say HW design bugs like this are more than "nothing major
> at all." :)
>
>> tiny stuff like these can help "fix" the hardware design quirks by
>> hiding it behind the firmware and modifying the hardware behavior.
>
> I disagree here.  I'm a firmware minimalist, and hiding bugs like this
> in the firmware is wrong when Linux is otherwise managing these devices.
> It also imposes criteria on the firmware of future SoCs that doesn't
> belong there either.  IMO, the only stuff the firmware should do is what
> Linux *cannot* do.
>
> Remember, this only needs to happen when there isn't a driver for these
> devices.  Should we communicate to the firmware that the OS has no
> driver, so please enable the hack?  I think not.

My view is that the M3 should *ignore* the presence/existence of MPU's 
drivers. M3 will do whatever to force the system to go to suspend once 
notified - this saves us the prehistoric perpetual trouble when drivers 
have bugs (which get exposed in weird usage scenarios) in production 
systems, we dont get any hardware help to fix them up while attempting 
low power states and system never really hits low power state. This was 
always because OMAP and it's derivatives have been "democratic" in power 
management - if every hardware block achieves proper state, then we 
achieve a system-wide low power state.

>
>> I know it breaks the purity of role, but as the
>> next evolution, we might want to consider M3 something like an
>> "accelerator" for power management activity.. (not saying it is that
>> fast.. but conceptually).
>
> Yes, it breaks the purity of role, and makes it hard to maintain and
> extend to future SoCs.  As a maintainer, that's a red flag.  IMO, the
> roles need to be kept clear.  The M3 manages some devices and the
> interconnect that MPU/Linux cannot, the rest are managed by Linux.

suspend is a very controlled state as against cpuidle where driver 
knowledge is necessary and in fact mandatory. drivers are supposed to 
release their resources - and even though we test the hell out of them, 
we do have paths untrodden when it comes to production systems.

I think the insight we have about the hardware make us(linux folks) want 
to own the decision making process on the master MPU - I mean, 
*nobody*(including me) wants to trust a "firmware" - that word is almost 
synonymous with "unspeakable horror".

If on the other hand, we had a non-programmable hardware which would 
force all systems to achieve off mode (imagine having a PRCM which was 
really capable of doing it), we would have probably not had to deal with 
those pesky "stuck-in-transition" and other variants of issues (where 
MPU went to low power state, but core refused to go down - resulting in 
200mA+ power instead of the <1mA we expected to see).

I consider M3 to power management similar to what Neon is to ARM. I 
mean, I would even love a PMIC which is completely reprogrammable (where 
I could define the registers in s/w)!

My personal thought is that (if possible):
a) we should try to make the source firmware visible to everyone who has 
a stake on it.
b) If (a) is possible, then we should see how we can consider M3 as an 
extension to Linux power strategy, rather than a "necessary burden" to 
carry around.

In this particular case. (a) is done see [1]. So, why not (b)? A synergy 
does not necessarily mean "purity of role" is broken. it is just another 
way of doing the job.

While, I personally dont think [1] is public enough, we can try to work 
through those current constraints to ensure everything is synergistic.

in other words, this is not a "Graphics" or "Multimedia" or even few 
"BIOS" kind of "hidden firmware you cannot do anything about" scenario - 
here, *we* have the choice.

[1] http://arago-project.org/git/projects/?p=am33x-cm3.git;a=summary
>
>>> That being said, IMO, the kernel (specifically omap_device) should
>>> handle this, and it should be rather easy to do in the omap_device layer
>>> and keep the SoC suspend/resume core code simple and ignorant of these
>>> "quirks."
>>>
>>> AFAICT, there's no reason these quirks need to be dealt with immediatly
>>> on suspend.  A slight delay should be fine, as long as it's before the
>>> next suspend/idle attempt, right?
>>>
>>> Given that, what we need to do (and by we, I mean you) is to flag all
>>> broken IP blocks, and let omap_device handle them in a suspend/resume
>>> notifier (c.f. register_pm_notifier() and PM_POST_SUSPEND.)
>>
>> yes - that is the alternate that comes to mind.
>
> In the earlier reviews of this series (many months ago now), I
> complained about the presence of this device specific handling in the
> core MPU PM code.  I'm somewhat troubled by the fact that nobody explored
> alternatives that so easily come to mind.

Just spoke to Dave in person a few mins back, and he is going to go 
through all the previous mail chains and attempt to be thorough again - 
seems like going through a written list of pending actions completely 
missed many key aspects of prior reviews :). Apologies on this.


-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-09 15:11                   ` Nishanth Menon
  0 siblings, 0 replies; 212+ messages in thread
From: Nishanth Menon @ 2013-08-09 15:11 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/08/2013 06:04 PM, Kevin Hilman wrote:
> Nishanth Menon <nm@ti.com> writes:
>
>> On 08/08/2013 04:14 PM, Kevin Hilman wrote:
>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>
>>>> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>>>>> $subject and patch don't match.
>>>>>
>>>>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>>>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>>>>      In reference to
>>>>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>>>>> bound and which don't.
>>>>>> Does it need to? M3 firmware can pretty much define "I will force
>>>>>> the device into low power state, and if the drivers dont handle
>>>>>> things properly, fix the darned driver". M3 behavior should be
>>>>>> considered as a "hardware" as far as Linux running on MPU is
>>>>>> concerned, and firmware helps change the behavior by accounting for
>>>>>> SoC quirks. *if* we have ability to handle this in the firmware,
>>>>>> there is no need to carry this in Linux.
>>>>>>
>>>>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>>>>> comment in the last version. Linux need not know about all such firmware
>>>>> quirks. Also all these M3 specific stuff, should be done somewhere
>>>>> else. Probably having a small M3 driver won't be a bad idea.
>>>>
>>>> I am not opposed to doing it this way and letting the M3 firmware
>>>> handle idling these modules, however the one concern raised in the
>>>> last series is that an approach that does not acknowledge drivers will
>>>> hide driver PM bugs. I suppose as long as I make sure to document that
>>>> the devices are being idled by the M3 firmware this may not be an
>>>> issue. I will look into implementing this.
>>>
>>> No, please don't start idling devices in firmware that are otherwise
>>> managed by Linux.  Keep the firmware simple and dumb.  Linux is managing
>>> these devices, it should manage their bugs too.
>>
>>>
>>> This is not just about idling devices.  This is about handling broken IP
>>> blocks whose power-on reset state does not allow the the powerdomain to
>>> reach its target state.  That's just bad hardware design.
>>
>> Right, this is where M3 can help -> provide a consistent state for
>> linux kernel to work with. by the fact that we want to keep majority
>> of the power code inside master CPU, we are just letting M3 help us
>> with nothing major at all..
>
> heh, I would say HW design bugs like this are more than "nothing major
> at all." :)
>
>> tiny stuff like these can help "fix" the hardware design quirks by
>> hiding it behind the firmware and modifying the hardware behavior.
>
> I disagree here.  I'm a firmware minimalist, and hiding bugs like this
> in the firmware is wrong when Linux is otherwise managing these devices.
> It also imposes criteria on the firmware of future SoCs that doesn't
> belong there either.  IMO, the only stuff the firmware should do is what
> Linux *cannot* do.
>
> Remember, this only needs to happen when there isn't a driver for these
> devices.  Should we communicate to the firmware that the OS has no
> driver, so please enable the hack?  I think not.

My view is that the M3 should *ignore* the presence/existence of MPU's 
drivers. M3 will do whatever to force the system to go to suspend once 
notified - this saves us the prehistoric perpetual trouble when drivers 
have bugs (which get exposed in weird usage scenarios) in production 
systems, we dont get any hardware help to fix them up while attempting 
low power states and system never really hits low power state. This was 
always because OMAP and it's derivatives have been "democratic" in power 
management - if every hardware block achieves proper state, then we 
achieve a system-wide low power state.

>
>> I know it breaks the purity of role, but as the
>> next evolution, we might want to consider M3 something like an
>> "accelerator" for power management activity.. (not saying it is that
>> fast.. but conceptually).
>
> Yes, it breaks the purity of role, and makes it hard to maintain and
> extend to future SoCs.  As a maintainer, that's a red flag.  IMO, the
> roles need to be kept clear.  The M3 manages some devices and the
> interconnect that MPU/Linux cannot, the rest are managed by Linux.

suspend is a very controlled state as against cpuidle where driver 
knowledge is necessary and in fact mandatory. drivers are supposed to 
release their resources - and even though we test the hell out of them, 
we do have paths untrodden when it comes to production systems.

I think the insight we have about the hardware make us(linux folks) want 
to own the decision making process on the master MPU - I mean, 
*nobody*(including me) wants to trust a "firmware" - that word is almost 
synonymous with "unspeakable horror".

If on the other hand, we had a non-programmable hardware which would 
force all systems to achieve off mode (imagine having a PRCM which was 
really capable of doing it), we would have probably not had to deal with 
those pesky "stuck-in-transition" and other variants of issues (where 
MPU went to low power state, but core refused to go down - resulting in 
200mA+ power instead of the <1mA we expected to see).

I consider M3 to power management similar to what Neon is to ARM. I 
mean, I would even love a PMIC which is completely reprogrammable (where 
I could define the registers in s/w)!

My personal thought is that (if possible):
a) we should try to make the source firmware visible to everyone who has 
a stake on it.
b) If (a) is possible, then we should see how we can consider M3 as an 
extension to Linux power strategy, rather than a "necessary burden" to 
carry around.

In this particular case. (a) is done see [1]. So, why not (b)? A synergy 
does not necessarily mean "purity of role" is broken. it is just another 
way of doing the job.

While, I personally dont think [1] is public enough, we can try to work 
through those current constraints to ensure everything is synergistic.

in other words, this is not a "Graphics" or "Multimedia" or even few 
"BIOS" kind of "hidden firmware you cannot do anything about" scenario - 
here, *we* have the choice.

[1] http://arago-project.org/git/projects/?p=am33x-cm3.git;a=summary
>
>>> That being said, IMO, the kernel (specifically omap_device) should
>>> handle this, and it should be rather easy to do in the omap_device layer
>>> and keep the SoC suspend/resume core code simple and ignorant of these
>>> "quirks."
>>>
>>> AFAICT, there's no reason these quirks need to be dealt with immediatly
>>> on suspend.  A slight delay should be fine, as long as it's before the
>>> next suspend/idle attempt, right?
>>>
>>> Given that, what we need to do (and by we, I mean you) is to flag all
>>> broken IP blocks, and let omap_device handle them in a suspend/resume
>>> notifier (c.f. register_pm_notifier() and PM_POST_SUSPEND.)
>>
>> yes - that is the alternate that comes to mind.
>
> In the earlier reviews of this series (many months ago now), I
> complained about the presence of this device specific handling in the
> core MPU PM code.  I'm somewhat troubled by the fact that nobody explored
> alternatives that so easily come to mind.

Just spoke to Dave in person a few mins back, and he is going to go 
through all the previous mail chains and attempt to be thorough again - 
seems like going through a written list of pending actions completely 
missed many key aspects of prior reviews :). Apologies on this.


-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-09 15:11                   ` Nishanth Menon
@ 2013-08-09 16:12                     ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-09 16:12 UTC (permalink / raw)
  To: Nishanth Menon
  Cc: Dave Gerlach, Santosh Shilimkar, Russ Dill, linux-arm-kernel,
	linux-omap, Paul Walmsley, Vaibhav Bedia, Tony Lingren,
	Benoit Cousson

Nishanth Menon <nm@ti.com> writes:

> On 08/08/2013 06:04 PM, Kevin Hilman wrote:
>> Nishanth Menon <nm@ti.com> writes:
>>
>>> On 08/08/2013 04:14 PM, Kevin Hilman wrote:
>>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>>
>>>>> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>>>>>> $subject and patch don't match.
>>>>>>
>>>>>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>>>>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>>>>>      In reference to
>>>>>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>>>>>> bound and which don't.
>>>>>>> Does it need to? M3 firmware can pretty much define "I will force
>>>>>>> the device into low power state, and if the drivers dont handle
>>>>>>> things properly, fix the darned driver". M3 behavior should be
>>>>>>> considered as a "hardware" as far as Linux running on MPU is
>>>>>>> concerned, and firmware helps change the behavior by accounting for
>>>>>>> SoC quirks. *if* we have ability to handle this in the firmware,
>>>>>>> there is no need to carry this in Linux.
>>>>>>>
>>>>>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>>>>>> comment in the last version. Linux need not know about all such firmware
>>>>>> quirks. Also all these M3 specific stuff, should be done somewhere
>>>>>> else. Probably having a small M3 driver won't be a bad idea.
>>>>>
>>>>> I am not opposed to doing it this way and letting the M3 firmware
>>>>> handle idling these modules, however the one concern raised in the
>>>>> last series is that an approach that does not acknowledge drivers will
>>>>> hide driver PM bugs. I suppose as long as I make sure to document that
>>>>> the devices are being idled by the M3 firmware this may not be an
>>>>> issue. I will look into implementing this.
>>>>
>>>> No, please don't start idling devices in firmware that are otherwise
>>>> managed by Linux.  Keep the firmware simple and dumb.  Linux is managing
>>>> these devices, it should manage their bugs too.
>>>
>>>>
>>>> This is not just about idling devices.  This is about handling broken IP
>>>> blocks whose power-on reset state does not allow the the powerdomain to
>>>> reach its target state.  That's just bad hardware design.
>>>
>>> Right, this is where M3 can help -> provide a consistent state for
>>> linux kernel to work with. by the fact that we want to keep majority
>>> of the power code inside master CPU, we are just letting M3 help us
>>> with nothing major at all..
>>
>> heh, I would say HW design bugs like this are more than "nothing major
>> at all." :)
>>
>>> tiny stuff like these can help "fix" the hardware design quirks by
>>> hiding it behind the firmware and modifying the hardware behavior.
>>
>> I disagree here.  I'm a firmware minimalist, and hiding bugs like this
>> in the firmware is wrong when Linux is otherwise managing these devices.
>> It also imposes criteria on the firmware of future SoCs that doesn't
>> belong there either.  IMO, the only stuff the firmware should do is what
>> Linux *cannot* do.
>>
>> Remember, this only needs to happen when there isn't a driver for these
>> devices.  Should we communicate to the firmware that the OS has no
>> driver, so please enable the hack?  I think not.
>
> My view is that the M3 should *ignore* the presence/existence of MPU's
> drivers. M3 will do whatever to force the system to go to suspend once
> notified - this saves us the prehistoric perpetual trouble when
> drivers have bugs (which get exposed in weird usage scenarios) in
> production systems, we dont get any hardware help to fix them up while
> attempting low power states and system never really hits low power
> state. This was always because OMAP and it's derivatives have been
> "democratic" in power management - if every hardware block achieves
> proper state, then we achieve a system-wide low power state.
>
>>
>>> I know it breaks the purity of role, but as the
>>> next evolution, we might want to consider M3 something like an
>>> "accelerator" for power management activity.. (not saying it is that
>>> fast.. but conceptually).
>>
>> Yes, it breaks the purity of role, and makes it hard to maintain and
>> extend to future SoCs.  As a maintainer, that's a red flag.  IMO, the
>> roles need to be kept clear.  The M3 manages some devices and the
>> interconnect that MPU/Linux cannot, the rest are managed by Linux.
>
> suspend is a very controlled state as against cpuidle where driver
> knowledge is necessary and in fact mandatory. drivers are supposed to
> release their resources - and even though we test the hell out of
> them, we do have paths untrodden when it comes to production systems.

Since folks don't seem to care about idle for AM33xx (starting with the
hw designers, from what I can tell), you have the luxury of thinking
only about suspend, where firmware can be heavy handed and force things
into submission.  Unfortunately, with cpuidle, life is not that easy and
you have to have cooperation of the device drivers.  Coordinating that
with firmware is not so simple, to put it mildly.

Any SW/firmware design that does not account for *both* static PM
(suspend/resume) and dynamic PM (runtime PM + CPUidle) is not long-term
maintainable, and thus ready for mainline IMO.  (BTW, this is another
theme from previous reviews of this series.)

> I think the insight we have about the hardware make us(linux folks)
> want to own the decision making process on the master MPU - I mean,
> *nobody*(including me) wants to trust a "firmware" - that word is
> almost synonymous with "unspeakable horror".
>
> If on the other hand, we had a non-programmable hardware which would
> force all systems to achieve off mode (imagine having a PRCM which was
> really capable of doing it), we would have probably not had to deal
> with those pesky "stuck-in-transition" and other variants of issues
> (where MPU went to low power state, but core refused to go down -
> resulting in 200mA+ power instead of the <1mA we expected to see).
>
> I consider M3 to power management similar to what Neon is to ARM. I
> mean, I would even love a PMIC which is completely reprogrammable
> (where I could define the registers in s/w)!
>
> My personal thought is that (if possible):
> a) we should try to make the source firmware visible to everyone who
> has a stake on it.
> b) If (a) is possible, then we should see how we can consider M3 as an
> extension to Linux power strategy, rather than a "necessary burden" to
> carry around.
>
> In this particular case. (a) is done see [1]. So, why not (b)? A
> synergy does not necessarily mean "purity of role" is broken. it is
> just another way of doing the job.
>
> While, I personally dont think [1] is public enough, we can try to
> work through those current constraints to ensure everything is
> synergistic.
>
> in other words, this is not a "Graphics" or "Multimedia" or even few
> "BIOS" kind of "hidden firmware you cannot do anything about" scenario
> - 
> here, *we* have the choice.
>
> [1] http://arago-project.org/git/projects/?p=am33x-cm3.git;a=summary
>>
>>>> That being said, IMO, the kernel (specifically omap_device) should
>>>> handle this, and it should be rather easy to do in the omap_device layer
>>>> and keep the SoC suspend/resume core code simple and ignorant of these
>>>> "quirks."
>>>>
>>>> AFAICT, there's no reason these quirks need to be dealt with immediatly
>>>> on suspend.  A slight delay should be fine, as long as it's before the
>>>> next suspend/idle attempt, right?
>>>>
>>>> Given that, what we need to do (and by we, I mean you) is to flag all
>>>> broken IP blocks, and let omap_device handle them in a suspend/resume
>>>> notifier (c.f. register_pm_notifier() and PM_POST_SUSPEND.)
>>>
>>> yes - that is the alternate that comes to mind.
>>
>> In the earlier reviews of this series (many months ago now), I
>> complained about the presence of this device specific handling in the
>> core MPU PM code.  I'm somewhat troubled by the fact that nobody explored
>> alternatives that so easily come to mind.
>
> Just spoke to Dave in person a few mins back, and he is going to go
> through all the previous mail chains and attempt to be thorough again
> - 
> seems like going through a written list of pending actions completely
> missed many key aspects of prior reviews :). Apologies on this.

Thanks.

Since he's inherited this series Dave gets a get out of jail free
card... this time.  Next time, I expect I might be grumpier.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-09 16:12                     ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-09 16:12 UTC (permalink / raw)
  To: linux-arm-kernel

Nishanth Menon <nm@ti.com> writes:

> On 08/08/2013 06:04 PM, Kevin Hilman wrote:
>> Nishanth Menon <nm@ti.com> writes:
>>
>>> On 08/08/2013 04:14 PM, Kevin Hilman wrote:
>>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>>
>>>>> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>>>>>> $subject and patch don't match.
>>>>>>
>>>>>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>>>>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>>>>>      In reference to
>>>>>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>>>>>> bound and which don't.
>>>>>>> Does it need to? M3 firmware can pretty much define "I will force
>>>>>>> the device into low power state, and if the drivers dont handle
>>>>>>> things properly, fix the darned driver". M3 behavior should be
>>>>>>> considered as a "hardware" as far as Linux running on MPU is
>>>>>>> concerned, and firmware helps change the behavior by accounting for
>>>>>>> SoC quirks. *if* we have ability to handle this in the firmware,
>>>>>>> there is no need to carry this in Linux.
>>>>>>>
>>>>>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>>>>>> comment in the last version. Linux need not know about all such firmware
>>>>>> quirks. Also all these M3 specific stuff, should be done somewhere
>>>>>> else. Probably having a small M3 driver won't be a bad idea.
>>>>>
>>>>> I am not opposed to doing it this way and letting the M3 firmware
>>>>> handle idling these modules, however the one concern raised in the
>>>>> last series is that an approach that does not acknowledge drivers will
>>>>> hide driver PM bugs. I suppose as long as I make sure to document that
>>>>> the devices are being idled by the M3 firmware this may not be an
>>>>> issue. I will look into implementing this.
>>>>
>>>> No, please don't start idling devices in firmware that are otherwise
>>>> managed by Linux.  Keep the firmware simple and dumb.  Linux is managing
>>>> these devices, it should manage their bugs too.
>>>
>>>>
>>>> This is not just about idling devices.  This is about handling broken IP
>>>> blocks whose power-on reset state does not allow the the powerdomain to
>>>> reach its target state.  That's just bad hardware design.
>>>
>>> Right, this is where M3 can help -> provide a consistent state for
>>> linux kernel to work with. by the fact that we want to keep majority
>>> of the power code inside master CPU, we are just letting M3 help us
>>> with nothing major at all..
>>
>> heh, I would say HW design bugs like this are more than "nothing major
>> at all." :)
>>
>>> tiny stuff like these can help "fix" the hardware design quirks by
>>> hiding it behind the firmware and modifying the hardware behavior.
>>
>> I disagree here.  I'm a firmware minimalist, and hiding bugs like this
>> in the firmware is wrong when Linux is otherwise managing these devices.
>> It also imposes criteria on the firmware of future SoCs that doesn't
>> belong there either.  IMO, the only stuff the firmware should do is what
>> Linux *cannot* do.
>>
>> Remember, this only needs to happen when there isn't a driver for these
>> devices.  Should we communicate to the firmware that the OS has no
>> driver, so please enable the hack?  I think not.
>
> My view is that the M3 should *ignore* the presence/existence of MPU's
> drivers. M3 will do whatever to force the system to go to suspend once
> notified - this saves us the prehistoric perpetual trouble when
> drivers have bugs (which get exposed in weird usage scenarios) in
> production systems, we dont get any hardware help to fix them up while
> attempting low power states and system never really hits low power
> state. This was always because OMAP and it's derivatives have been
> "democratic" in power management - if every hardware block achieves
> proper state, then we achieve a system-wide low power state.
>
>>
>>> I know it breaks the purity of role, but as the
>>> next evolution, we might want to consider M3 something like an
>>> "accelerator" for power management activity.. (not saying it is that
>>> fast.. but conceptually).
>>
>> Yes, it breaks the purity of role, and makes it hard to maintain and
>> extend to future SoCs.  As a maintainer, that's a red flag.  IMO, the
>> roles need to be kept clear.  The M3 manages some devices and the
>> interconnect that MPU/Linux cannot, the rest are managed by Linux.
>
> suspend is a very controlled state as against cpuidle where driver
> knowledge is necessary and in fact mandatory. drivers are supposed to
> release their resources - and even though we test the hell out of
> them, we do have paths untrodden when it comes to production systems.

Since folks don't seem to care about idle for AM33xx (starting with the
hw designers, from what I can tell), you have the luxury of thinking
only about suspend, where firmware can be heavy handed and force things
into submission.  Unfortunately, with cpuidle, life is not that easy and
you have to have cooperation of the device drivers.  Coordinating that
with firmware is not so simple, to put it mildly.

Any SW/firmware design that does not account for *both* static PM
(suspend/resume) and dynamic PM (runtime PM + CPUidle) is not long-term
maintainable, and thus ready for mainline IMO.  (BTW, this is another
theme from previous reviews of this series.)

> I think the insight we have about the hardware make us(linux folks)
> want to own the decision making process on the master MPU - I mean,
> *nobody*(including me) wants to trust a "firmware" - that word is
> almost synonymous with "unspeakable horror".
>
> If on the other hand, we had a non-programmable hardware which would
> force all systems to achieve off mode (imagine having a PRCM which was
> really capable of doing it), we would have probably not had to deal
> with those pesky "stuck-in-transition" and other variants of issues
> (where MPU went to low power state, but core refused to go down -
> resulting in 200mA+ power instead of the <1mA we expected to see).
>
> I consider M3 to power management similar to what Neon is to ARM. I
> mean, I would even love a PMIC which is completely reprogrammable
> (where I could define the registers in s/w)!
>
> My personal thought is that (if possible):
> a) we should try to make the source firmware visible to everyone who
> has a stake on it.
> b) If (a) is possible, then we should see how we can consider M3 as an
> extension to Linux power strategy, rather than a "necessary burden" to
> carry around.
>
> In this particular case. (a) is done see [1]. So, why not (b)? A
> synergy does not necessarily mean "purity of role" is broken. it is
> just another way of doing the job.
>
> While, I personally dont think [1] is public enough, we can try to
> work through those current constraints to ensure everything is
> synergistic.
>
> in other words, this is not a "Graphics" or "Multimedia" or even few
> "BIOS" kind of "hidden firmware you cannot do anything about" scenario
> - 
> here, *we* have the choice.
>
> [1] http://arago-project.org/git/projects/?p=am33x-cm3.git;a=summary
>>
>>>> That being said, IMO, the kernel (specifically omap_device) should
>>>> handle this, and it should be rather easy to do in the omap_device layer
>>>> and keep the SoC suspend/resume core code simple and ignorant of these
>>>> "quirks."
>>>>
>>>> AFAICT, there's no reason these quirks need to be dealt with immediatly
>>>> on suspend.  A slight delay should be fine, as long as it's before the
>>>> next suspend/idle attempt, right?
>>>>
>>>> Given that, what we need to do (and by we, I mean you) is to flag all
>>>> broken IP blocks, and let omap_device handle them in a suspend/resume
>>>> notifier (c.f. register_pm_notifier() and PM_POST_SUSPEND.)
>>>
>>> yes - that is the alternate that comes to mind.
>>
>> In the earlier reviews of this series (many months ago now), I
>> complained about the presence of this device specific handling in the
>> core MPU PM code.  I'm somewhat troubled by the fact that nobody explored
>> alternatives that so easily come to mind.
>
> Just spoke to Dave in person a few mins back, and he is going to go
> through all the previous mail chains and attempt to be thorough again
> - 
> seems like going through a written list of pending actions completely
> missed many key aspects of prior reviews :). Apologies on this.

Thanks.

Since he's inherited this series Dave gets a get out of jail free
card... this time.  Next time, I expect I might be grumpier.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
  2013-08-09 15:11             ` Kevin Hilman
@ 2013-08-09 16:25               ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-09 16:25 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Santosh Shilimkar, linux-arm-kernel, linux-omap, Paul Walmsley,
	Vaibhav Bedia

On 08/09/2013 10:11 AM, Kevin Hilman wrote:
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>
>> On Thursday 08 August 2013 04:05 PM, Kevin Hilman wrote:
>>> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>>>
>>>> On Thursday 08 August 2013 02:16 PM, Kevin Hilman wrote:
>>>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>>>
>>>>>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>>>>>
>>>>>> SDRAM controller on AM33XX requires that a modification of certain
>>>>>> bit-fields in PWR_MGMT_CTRL register (ref. section 7.3.5.13 in
>>>>>> AM335x-Rev H) is followed by a dummy read access to SDRAM. This
>>>>>> scenario arises when entering a low power state like DeepSleep.
>>>>>> To ensure that the read is not from a cached region we reserve
>>>>>> some memory during bootup using the arm_memblock_steal() API.
>>>>>
>>>>> Hmm, sounds to me an awful lot like the existing omap_bus_sync() ?
>>>>>
>>>> All the credit of that awful omap_bus_sync() goes to me since
>>>> I introduced it. And I keep beating the hardware guys
>>>> who have not left a choice but to introduce the ugly work
>>>> around in software. ;-)
>>>
>>> Agreed, but what's even more awful than the current version is
>>> duplicating it in a slightly different way using yet another whole page
>>> mapping for a single read/write location.
>>>
>> The real issue is limitation of the kernel memory steal(memblock) API which
>> won't let you still less than 1 MB. It would have been ok for page allocation
>> because that is any way what you will get minimum on standard non-cached
>> allocations.
>
> All the more reason that the omap_bus_sync() should be refactored
> slightly in a way that would be reusable for AM33xx.
>
> Kevin
>

I will look in to doing it this way. I do not know if there was any 
specific reason for doing it the way it was done.

Dave


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
@ 2013-08-09 16:25               ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-09 16:25 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/09/2013 10:11 AM, Kevin Hilman wrote:
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>
>> On Thursday 08 August 2013 04:05 PM, Kevin Hilman wrote:
>>> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>>>
>>>> On Thursday 08 August 2013 02:16 PM, Kevin Hilman wrote:
>>>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>>>
>>>>>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>>>>>
>>>>>> SDRAM controller on AM33XX requires that a modification of certain
>>>>>> bit-fields in PWR_MGMT_CTRL register (ref. section 7.3.5.13 in
>>>>>> AM335x-Rev H) is followed by a dummy read access to SDRAM. This
>>>>>> scenario arises when entering a low power state like DeepSleep.
>>>>>> To ensure that the read is not from a cached region we reserve
>>>>>> some memory during bootup using the arm_memblock_steal() API.
>>>>>
>>>>> Hmm, sounds to me an awful lot like the existing omap_bus_sync() ?
>>>>>
>>>> All the credit of that awful omap_bus_sync() goes to me since
>>>> I introduced it. And I keep beating the hardware guys
>>>> who have not left a choice but to introduce the ugly work
>>>> around in software. ;-)
>>>
>>> Agreed, but what's even more awful than the current version is
>>> duplicating it in a slightly different way using yet another whole page
>>> mapping for a single read/write location.
>>>
>> The real issue is limitation of the kernel memory steal(memblock) API which
>> won't let you still less than 1 MB. It would have been ok for page allocation
>> because that is any way what you will get minimum on standard non-cached
>> allocations.
>
> All the more reason that the omap_bus_sync() should be refactored
> slightly in a way that would be reusable for AM33xx.
>
> Kevin
>

I will look in to doing it this way. I do not know if there was any 
specific reason for doing it the way it was done.

Dave

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-09 16:12                     ` Kevin Hilman
@ 2013-08-09 16:36                       ` Nishanth Menon
  -1 siblings, 0 replies; 212+ messages in thread
From: Nishanth Menon @ 2013-08-09 16:36 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Dave Gerlach, Santosh Shilimkar, Russ Dill, linux-arm-kernel,
	linux-omap, Paul Walmsley, Vaibhav Bedia, Tony Lingren,
	Benoit Cousson

On 08/09/2013 11:12 AM, Kevin Hilman wrote:
> Nishanth Menon <nm@ti.com> writes:
>
>> On 08/08/2013 06:04 PM, Kevin Hilman wrote:
>>> Nishanth Menon <nm@ti.com> writes:
>>>
>>>> On 08/08/2013 04:14 PM, Kevin Hilman wrote:
>>>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>>>
>>>>>> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>>>>>>> $subject and patch don't match.
>>>>>>>
>>>>>>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>>>>>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>>>>>>       In reference to
>>>>>>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>>>>>>> bound and which don't.
>>>>>>>> Does it need to? M3 firmware can pretty much define "I will force
>>>>>>>> the device into low power state, and if the drivers dont handle
>>>>>>>> things properly, fix the darned driver". M3 behavior should be
>>>>>>>> considered as a "hardware" as far as Linux running on MPU is
>>>>>>>> concerned, and firmware helps change the behavior by accounting for
>>>>>>>> SoC quirks. *if* we have ability to handle this in the firmware,
>>>>>>>> there is no need to carry this in Linux.
>>>>>>>>
>>>>>>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>>>>>>> comment in the last version. Linux need not know about all such firmware
>>>>>>> quirks. Also all these M3 specific stuff, should be done somewhere
>>>>>>> else. Probably having a small M3 driver won't be a bad idea.
>>>>>>
>>>>>> I am not opposed to doing it this way and letting the M3 firmware
>>>>>> handle idling these modules, however the one concern raised in the
>>>>>> last series is that an approach that does not acknowledge drivers will
>>>>>> hide driver PM bugs. I suppose as long as I make sure to document that
>>>>>> the devices are being idled by the M3 firmware this may not be an
>>>>>> issue. I will look into implementing this.
>>>>>
>>>>> No, please don't start idling devices in firmware that are otherwise
>>>>> managed by Linux.  Keep the firmware simple and dumb.  Linux is managing
>>>>> these devices, it should manage their bugs too.
>>>>
>>>>>
>>>>> This is not just about idling devices.  This is about handling broken IP
>>>>> blocks whose power-on reset state does not allow the the powerdomain to
>>>>> reach its target state.  That's just bad hardware design.
>>>>
>>>> Right, this is where M3 can help -> provide a consistent state for
>>>> linux kernel to work with. by the fact that we want to keep majority
>>>> of the power code inside master CPU, we are just letting M3 help us
>>>> with nothing major at all..
>>>
>>> heh, I would say HW design bugs like this are more than "nothing major
>>> at all." :)
>>>
>>>> tiny stuff like these can help "fix" the hardware design quirks by
>>>> hiding it behind the firmware and modifying the hardware behavior.
>>>
>>> I disagree here.  I'm a firmware minimalist, and hiding bugs like this
>>> in the firmware is wrong when Linux is otherwise managing these devices.
>>> It also imposes criteria on the firmware of future SoCs that doesn't
>>> belong there either.  IMO, the only stuff the firmware should do is what
>>> Linux *cannot* do.
>>>
>>> Remember, this only needs to happen when there isn't a driver for these
>>> devices.  Should we communicate to the firmware that the OS has no
>>> driver, so please enable the hack?  I think not.
>>
>> My view is that the M3 should *ignore* the presence/existence of MPU's
>> drivers. M3 will do whatever to force the system to go to suspend once
>> notified - this saves us the prehistoric perpetual trouble when
>> drivers have bugs (which get exposed in weird usage scenarios) in
>> production systems, we dont get any hardware help to fix them up while
>> attempting low power states and system never really hits low power
>> state. This was always because OMAP and it's derivatives have been
>> "democratic" in power management - if every hardware block achieves
>> proper state, then we achieve a system-wide low power state.
>>
>>>
>>>> I know it breaks the purity of role, but as the
>>>> next evolution, we might want to consider M3 something like an
>>>> "accelerator" for power management activity.. (not saying it is that
>>>> fast.. but conceptually).
>>>
>>> Yes, it breaks the purity of role, and makes it hard to maintain and
>>> extend to future SoCs.  As a maintainer, that's a red flag.  IMO, the
>>> roles need to be kept clear.  The M3 manages some devices and the
>>> interconnect that MPU/Linux cannot, the rest are managed by Linux.
>>
>> suspend is a very controlled state as against cpuidle where driver
>> knowledge is necessary and in fact mandatory. drivers are supposed to
>> release their resources - and even though we test the hell out of
>> them, we do have paths untrodden when it comes to production systems.
>
> Since folks don't seem to care about idle for AM33xx (starting with the
> hw designers, from what I can tell), you have the luxury of thinking
> only about suspend, where firmware can be heavy handed and force things
> into submission.  Unfortunately, with cpuidle, life is not that easy and
> you have to have cooperation of the device drivers.  Coordinating that
> with firmware is not so simple, to put it mildly.
>
> Any SW/firmware design that does not account for *both* static PM
> (suspend/resume) and dynamic PM (runtime PM + CPUidle) is not long-term
> maintainable, and thus ready for mainline IMO.  (BTW, this is another
> theme from previous reviews of this series.)

I completely agree with you. But is'nt the specific suspend state we are 
attempting to achieve on AM335x just tooo expensive latency wise for 
being even considered for cpuidle? I am sure you recollect the latencies 
involved in OMAP3 OFF mode Vs OMAP4+ OFF mode - which basically kicked 
out OFF mode from OMAP4 cpuidle C states? - it was practically useless

in this *specific* power state we are attempting, we do a bunch of i2c 
operations, etc, in short something that cannot even be considered for 
cpuidle.

Considering this, we can consider the same only for suspend path - hence 
allowing firmware to do more here.


This does not conflict with cpuidle (which controls MPU) or runtime PM 
(which kicks in once you have drivers active, but if drivers get active, 
we dont need to deal with this crap).

Dont you think this helps the specific case to move this into firmware 
rather than into omap_device?
[...]

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-09 16:36                       ` Nishanth Menon
  0 siblings, 0 replies; 212+ messages in thread
From: Nishanth Menon @ 2013-08-09 16:36 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/09/2013 11:12 AM, Kevin Hilman wrote:
> Nishanth Menon <nm@ti.com> writes:
>
>> On 08/08/2013 06:04 PM, Kevin Hilman wrote:
>>> Nishanth Menon <nm@ti.com> writes:
>>>
>>>> On 08/08/2013 04:14 PM, Kevin Hilman wrote:
>>>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>>>
>>>>>> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>>>>>>> $subject and patch don't match.
>>>>>>>
>>>>>>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>>>>>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>>>>>>       In reference to
>>>>>>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>>>>>>> bound and which don't.
>>>>>>>> Does it need to? M3 firmware can pretty much define "I will force
>>>>>>>> the device into low power state, and if the drivers dont handle
>>>>>>>> things properly, fix the darned driver". M3 behavior should be
>>>>>>>> considered as a "hardware" as far as Linux running on MPU is
>>>>>>>> concerned, and firmware helps change the behavior by accounting for
>>>>>>>> SoC quirks. *if* we have ability to handle this in the firmware,
>>>>>>>> there is no need to carry this in Linux.
>>>>>>>>
>>>>>>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>>>>>>> comment in the last version. Linux need not know about all such firmware
>>>>>>> quirks. Also all these M3 specific stuff, should be done somewhere
>>>>>>> else. Probably having a small M3 driver won't be a bad idea.
>>>>>>
>>>>>> I am not opposed to doing it this way and letting the M3 firmware
>>>>>> handle idling these modules, however the one concern raised in the
>>>>>> last series is that an approach that does not acknowledge drivers will
>>>>>> hide driver PM bugs. I suppose as long as I make sure to document that
>>>>>> the devices are being idled by the M3 firmware this may not be an
>>>>>> issue. I will look into implementing this.
>>>>>
>>>>> No, please don't start idling devices in firmware that are otherwise
>>>>> managed by Linux.  Keep the firmware simple and dumb.  Linux is managing
>>>>> these devices, it should manage their bugs too.
>>>>
>>>>>
>>>>> This is not just about idling devices.  This is about handling broken IP
>>>>> blocks whose power-on reset state does not allow the the powerdomain to
>>>>> reach its target state.  That's just bad hardware design.
>>>>
>>>> Right, this is where M3 can help -> provide a consistent state for
>>>> linux kernel to work with. by the fact that we want to keep majority
>>>> of the power code inside master CPU, we are just letting M3 help us
>>>> with nothing major at all..
>>>
>>> heh, I would say HW design bugs like this are more than "nothing major
>>> at all." :)
>>>
>>>> tiny stuff like these can help "fix" the hardware design quirks by
>>>> hiding it behind the firmware and modifying the hardware behavior.
>>>
>>> I disagree here.  I'm a firmware minimalist, and hiding bugs like this
>>> in the firmware is wrong when Linux is otherwise managing these devices.
>>> It also imposes criteria on the firmware of future SoCs that doesn't
>>> belong there either.  IMO, the only stuff the firmware should do is what
>>> Linux *cannot* do.
>>>
>>> Remember, this only needs to happen when there isn't a driver for these
>>> devices.  Should we communicate to the firmware that the OS has no
>>> driver, so please enable the hack?  I think not.
>>
>> My view is that the M3 should *ignore* the presence/existence of MPU's
>> drivers. M3 will do whatever to force the system to go to suspend once
>> notified - this saves us the prehistoric perpetual trouble when
>> drivers have bugs (which get exposed in weird usage scenarios) in
>> production systems, we dont get any hardware help to fix them up while
>> attempting low power states and system never really hits low power
>> state. This was always because OMAP and it's derivatives have been
>> "democratic" in power management - if every hardware block achieves
>> proper state, then we achieve a system-wide low power state.
>>
>>>
>>>> I know it breaks the purity of role, but as the
>>>> next evolution, we might want to consider M3 something like an
>>>> "accelerator" for power management activity.. (not saying it is that
>>>> fast.. but conceptually).
>>>
>>> Yes, it breaks the purity of role, and makes it hard to maintain and
>>> extend to future SoCs.  As a maintainer, that's a red flag.  IMO, the
>>> roles need to be kept clear.  The M3 manages some devices and the
>>> interconnect that MPU/Linux cannot, the rest are managed by Linux.
>>
>> suspend is a very controlled state as against cpuidle where driver
>> knowledge is necessary and in fact mandatory. drivers are supposed to
>> release their resources - and even though we test the hell out of
>> them, we do have paths untrodden when it comes to production systems.
>
> Since folks don't seem to care about idle for AM33xx (starting with the
> hw designers, from what I can tell), you have the luxury of thinking
> only about suspend, where firmware can be heavy handed and force things
> into submission.  Unfortunately, with cpuidle, life is not that easy and
> you have to have cooperation of the device drivers.  Coordinating that
> with firmware is not so simple, to put it mildly.
>
> Any SW/firmware design that does not account for *both* static PM
> (suspend/resume) and dynamic PM (runtime PM + CPUidle) is not long-term
> maintainable, and thus ready for mainline IMO.  (BTW, this is another
> theme from previous reviews of this series.)

I completely agree with you. But is'nt the specific suspend state we are 
attempting to achieve on AM335x just tooo expensive latency wise for 
being even considered for cpuidle? I am sure you recollect the latencies 
involved in OMAP3 OFF mode Vs OMAP4+ OFF mode - which basically kicked 
out OFF mode from OMAP4 cpuidle C states? - it was practically useless

in this *specific* power state we are attempting, we do a bunch of i2c 
operations, etc, in short something that cannot even be considered for 
cpuidle.

Considering this, we can consider the same only for suspend path - hence 
allowing firmware to do more here.


This does not conflict with cpuidle (which controls MPU) or runtime PM 
(which kicks in once you have drivers active, but if drivers get active, 
we dont need to deal with this crap).

Dont you think this helps the specific case to move this into firmware 
rather than into omap_device?
[...]

-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-09 16:36                       ` Nishanth Menon
@ 2013-08-09 20:34                         ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-09 20:34 UTC (permalink / raw)
  To: Nishanth Menon
  Cc: Dave Gerlach, Santosh Shilimkar, Russ Dill, linux-arm-kernel,
	linux-omap, Paul Walmsley, Vaibhav Bedia, Tony Lingren,
	Benoit Cousson

Nishanth Menon <nm@ti.com> writes:

> On 08/09/2013 11:12 AM, Kevin Hilman wrote:
>> Nishanth Menon <nm@ti.com> writes:
>>
>>> On 08/08/2013 06:04 PM, Kevin Hilman wrote:
>>>> Nishanth Menon <nm@ti.com> writes:
>>>>
>>>>> On 08/08/2013 04:14 PM, Kevin Hilman wrote:
>>>>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>>>>
>>>>>>> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>>>>>>>> $subject and patch don't match.
>>>>>>>>
>>>>>>>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>>>>>>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>>>>>>>       In reference to
>>>>>>>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>>>>>>>> bound and which don't.
>>>>>>>>> Does it need to? M3 firmware can pretty much define "I will force
>>>>>>>>> the device into low power state, and if the drivers dont handle
>>>>>>>>> things properly, fix the darned driver". M3 behavior should be
>>>>>>>>> considered as a "hardware" as far as Linux running on MPU is
>>>>>>>>> concerned, and firmware helps change the behavior by accounting for
>>>>>>>>> SoC quirks. *if* we have ability to handle this in the firmware,
>>>>>>>>> there is no need to carry this in Linux.
>>>>>>>>>
>>>>>>>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>>>>>>>> comment in the last version. Linux need not know about all such firmware
>>>>>>>> quirks. Also all these M3 specific stuff, should be done somewhere
>>>>>>>> else. Probably having a small M3 driver won't be a bad idea.
>>>>>>>
>>>>>>> I am not opposed to doing it this way and letting the M3 firmware
>>>>>>> handle idling these modules, however the one concern raised in the
>>>>>>> last series is that an approach that does not acknowledge drivers will
>>>>>>> hide driver PM bugs. I suppose as long as I make sure to document that
>>>>>>> the devices are being idled by the M3 firmware this may not be an
>>>>>>> issue. I will look into implementing this.
>>>>>>
>>>>>> No, please don't start idling devices in firmware that are otherwise
>>>>>> managed by Linux.  Keep the firmware simple and dumb.  Linux is managing
>>>>>> these devices, it should manage their bugs too.
>>>>>
>>>>>>
>>>>>> This is not just about idling devices.  This is about handling broken IP
>>>>>> blocks whose power-on reset state does not allow the the powerdomain to
>>>>>> reach its target state.  That's just bad hardware design.
>>>>>
>>>>> Right, this is where M3 can help -> provide a consistent state for
>>>>> linux kernel to work with. by the fact that we want to keep majority
>>>>> of the power code inside master CPU, we are just letting M3 help us
>>>>> with nothing major at all..
>>>>
>>>> heh, I would say HW design bugs like this are more than "nothing major
>>>> at all." :)
>>>>
>>>>> tiny stuff like these can help "fix" the hardware design quirks by
>>>>> hiding it behind the firmware and modifying the hardware behavior.
>>>>
>>>> I disagree here.  I'm a firmware minimalist, and hiding bugs like this
>>>> in the firmware is wrong when Linux is otherwise managing these devices.
>>>> It also imposes criteria on the firmware of future SoCs that doesn't
>>>> belong there either.  IMO, the only stuff the firmware should do is what
>>>> Linux *cannot* do.
>>>>
>>>> Remember, this only needs to happen when there isn't a driver for these
>>>> devices.  Should we communicate to the firmware that the OS has no
>>>> driver, so please enable the hack?  I think not.
>>>
>>> My view is that the M3 should *ignore* the presence/existence of MPU's
>>> drivers. M3 will do whatever to force the system to go to suspend once
>>> notified - this saves us the prehistoric perpetual trouble when
>>> drivers have bugs (which get exposed in weird usage scenarios) in
>>> production systems, we dont get any hardware help to fix them up while
>>> attempting low power states and system never really hits low power
>>> state. This was always because OMAP and it's derivatives have been
>>> "democratic" in power management - if every hardware block achieves
>>> proper state, then we achieve a system-wide low power state.
>>>
>>>>
>>>>> I know it breaks the purity of role, but as the
>>>>> next evolution, we might want to consider M3 something like an
>>>>> "accelerator" for power management activity.. (not saying it is that
>>>>> fast.. but conceptually).
>>>>
>>>> Yes, it breaks the purity of role, and makes it hard to maintain and
>>>> extend to future SoCs.  As a maintainer, that's a red flag.  IMO, the
>>>> roles need to be kept clear.  The M3 manages some devices and the
>>>> interconnect that MPU/Linux cannot, the rest are managed by Linux.
>>>
>>> suspend is a very controlled state as against cpuidle where driver
>>> knowledge is necessary and in fact mandatory. drivers are supposed to
>>> release their resources - and even though we test the hell out of
>>> them, we do have paths untrodden when it comes to production systems.
>>
>> Since folks don't seem to care about idle for AM33xx (starting with the
>> hw designers, from what I can tell), you have the luxury of thinking
>> only about suspend, where firmware can be heavy handed and force things
>> into submission.  Unfortunately, with cpuidle, life is not that easy and
>> you have to have cooperation of the device drivers.  Coordinating that
>> with firmware is not so simple, to put it mildly.
>>
>> Any SW/firmware design that does not account for *both* static PM
>> (suspend/resume) and dynamic PM (runtime PM + CPUidle) is not long-term
>> maintainable, and thus ready for mainline IMO.  (BTW, this is another
>> theme from previous reviews of this series.)
>
> I completely agree with you.  But is'nt the specific suspend state we
> are attempting to achieve on AM335x just tooo expensive latency wise
> for being even considered for cpuidle? 
>
> I am sure you recollect the latencies involved in OMAP3 OFF mode Vs
> OMAP4+ OFF mode - which basically kicked out OFF mode from OMAP4
> cpuidle C states? - it was practically useless
>
> in this *specific* power state we are attempting, we do a bunch of i2c
> operations, etc, in short something that cannot even be considered for
> cpuidle.
>
> Considering this, we can consider the same only for suspend path -
> hence allowing firmware to do more here.
>
>
> This does not conflict with cpuidle (which controls MPU) or runtime PM
> (which kicks in once you have drivers active, but if drivers get
> active, we dont need to deal with this crap).
>
> Dont you think this helps the specific case to move this into firmware
> rather than into omap_device?

No, I don't.

That means the firmware design is based on several assumptions about
what Linux can and can't do in idle, and then imposing that on future
Linux designs as well.  I dont' buy it.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-09 20:34                         ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-09 20:34 UTC (permalink / raw)
  To: linux-arm-kernel

Nishanth Menon <nm@ti.com> writes:

> On 08/09/2013 11:12 AM, Kevin Hilman wrote:
>> Nishanth Menon <nm@ti.com> writes:
>>
>>> On 08/08/2013 06:04 PM, Kevin Hilman wrote:
>>>> Nishanth Menon <nm@ti.com> writes:
>>>>
>>>>> On 08/08/2013 04:14 PM, Kevin Hilman wrote:
>>>>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>>>>
>>>>>>> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>>>>>>>> $subject and patch don't match.
>>>>>>>>
>>>>>>>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>>>>>>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>>>>>>>       In reference to
>>>>>>>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>>>>>>>> bound and which don't.
>>>>>>>>> Does it need to? M3 firmware can pretty much define "I will force
>>>>>>>>> the device into low power state, and if the drivers dont handle
>>>>>>>>> things properly, fix the darned driver". M3 behavior should be
>>>>>>>>> considered as a "hardware" as far as Linux running on MPU is
>>>>>>>>> concerned, and firmware helps change the behavior by accounting for
>>>>>>>>> SoC quirks. *if* we have ability to handle this in the firmware,
>>>>>>>>> there is no need to carry this in Linux.
>>>>>>>>>
>>>>>>>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>>>>>>>> comment in the last version. Linux need not know about all such firmware
>>>>>>>> quirks. Also all these M3 specific stuff, should be done somewhere
>>>>>>>> else. Probably having a small M3 driver won't be a bad idea.
>>>>>>>
>>>>>>> I am not opposed to doing it this way and letting the M3 firmware
>>>>>>> handle idling these modules, however the one concern raised in the
>>>>>>> last series is that an approach that does not acknowledge drivers will
>>>>>>> hide driver PM bugs. I suppose as long as I make sure to document that
>>>>>>> the devices are being idled by the M3 firmware this may not be an
>>>>>>> issue. I will look into implementing this.
>>>>>>
>>>>>> No, please don't start idling devices in firmware that are otherwise
>>>>>> managed by Linux.  Keep the firmware simple and dumb.  Linux is managing
>>>>>> these devices, it should manage their bugs too.
>>>>>
>>>>>>
>>>>>> This is not just about idling devices.  This is about handling broken IP
>>>>>> blocks whose power-on reset state does not allow the the powerdomain to
>>>>>> reach its target state.  That's just bad hardware design.
>>>>>
>>>>> Right, this is where M3 can help -> provide a consistent state for
>>>>> linux kernel to work with. by the fact that we want to keep majority
>>>>> of the power code inside master CPU, we are just letting M3 help us
>>>>> with nothing major at all..
>>>>
>>>> heh, I would say HW design bugs like this are more than "nothing major
>>>> at all." :)
>>>>
>>>>> tiny stuff like these can help "fix" the hardware design quirks by
>>>>> hiding it behind the firmware and modifying the hardware behavior.
>>>>
>>>> I disagree here.  I'm a firmware minimalist, and hiding bugs like this
>>>> in the firmware is wrong when Linux is otherwise managing these devices.
>>>> It also imposes criteria on the firmware of future SoCs that doesn't
>>>> belong there either.  IMO, the only stuff the firmware should do is what
>>>> Linux *cannot* do.
>>>>
>>>> Remember, this only needs to happen when there isn't a driver for these
>>>> devices.  Should we communicate to the firmware that the OS has no
>>>> driver, so please enable the hack?  I think not.
>>>
>>> My view is that the M3 should *ignore* the presence/existence of MPU's
>>> drivers. M3 will do whatever to force the system to go to suspend once
>>> notified - this saves us the prehistoric perpetual trouble when
>>> drivers have bugs (which get exposed in weird usage scenarios) in
>>> production systems, we dont get any hardware help to fix them up while
>>> attempting low power states and system never really hits low power
>>> state. This was always because OMAP and it's derivatives have been
>>> "democratic" in power management - if every hardware block achieves
>>> proper state, then we achieve a system-wide low power state.
>>>
>>>>
>>>>> I know it breaks the purity of role, but as the
>>>>> next evolution, we might want to consider M3 something like an
>>>>> "accelerator" for power management activity.. (not saying it is that
>>>>> fast.. but conceptually).
>>>>
>>>> Yes, it breaks the purity of role, and makes it hard to maintain and
>>>> extend to future SoCs.  As a maintainer, that's a red flag.  IMO, the
>>>> roles need to be kept clear.  The M3 manages some devices and the
>>>> interconnect that MPU/Linux cannot, the rest are managed by Linux.
>>>
>>> suspend is a very controlled state as against cpuidle where driver
>>> knowledge is necessary and in fact mandatory. drivers are supposed to
>>> release their resources - and even though we test the hell out of
>>> them, we do have paths untrodden when it comes to production systems.
>>
>> Since folks don't seem to care about idle for AM33xx (starting with the
>> hw designers, from what I can tell), you have the luxury of thinking
>> only about suspend, where firmware can be heavy handed and force things
>> into submission.  Unfortunately, with cpuidle, life is not that easy and
>> you have to have cooperation of the device drivers.  Coordinating that
>> with firmware is not so simple, to put it mildly.
>>
>> Any SW/firmware design that does not account for *both* static PM
>> (suspend/resume) and dynamic PM (runtime PM + CPUidle) is not long-term
>> maintainable, and thus ready for mainline IMO.  (BTW, this is another
>> theme from previous reviews of this series.)
>
> I completely agree with you.  But is'nt the specific suspend state we
> are attempting to achieve on AM335x just tooo expensive latency wise
> for being even considered for cpuidle? 
>
> I am sure you recollect the latencies involved in OMAP3 OFF mode Vs
> OMAP4+ OFF mode - which basically kicked out OFF mode from OMAP4
> cpuidle C states? - it was practically useless
>
> in this *specific* power state we are attempting, we do a bunch of i2c
> operations, etc, in short something that cannot even be considered for
> cpuidle.
>
> Considering this, we can consider the same only for suspend path -
> hence allowing firmware to do more here.
>
>
> This does not conflict with cpuidle (which controls MPU) or runtime PM
> (which kicks in once you have drivers active, but if drivers get
> active, we dont need to deal with this crap).
>
> Dont you think this helps the specific case to move this into firmware
> rather than into omap_device?

No, I don't.

That means the firmware design is based on several assumptions about
what Linux can and can't do in idle, and then imposing that on future
Linux designs as well.  I dont' buy it.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-09  5:11         ` Tony Lindgren
@ 2013-08-09 20:55           ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-09 20:55 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Santosh Shilimkar, linux-arm-kernel, linux-omap, Paul Walmsley,
	Kevin Hilman, Vaibhav Bedia

On 08/09/2013 12:11 AM, Tony Lindgren wrote:
> * Dave Gerlach <d-gerlach@ti.com> [130808 09:23]:
>> On 08/08/2013 08:44 AM, Santosh Shilimkar wrote:
>>> Lets address the above better. I don't see a need of 8 functions
>>> exported doing one or 2 register writes.
>>>
>>> Look M3 based handling is going to be there on future SOCs
>>> as well and this kind of handling of IPC is very short cited.
>>>
>>
>> The idea here was to move all control module register accesses into
>> one file in planning of implementing a driver for the control module
>> itself in the future.
>>
>>> Probably we should have a separate driver for M3 in linux which
>>> can have all this local code instead of all these exports.
>>
>> The wkup_m3 code has been moved to a small driver found in patch 8
>> of this series, would it better to move this code there rather than
>> with the rest of the control module code?
>
> Please make everything you can into regular device drivers.
>
> We still have some dependencies to mach-omap2 code for PRCM
> for example, but we're trying to get all that to live in
> drivers.
>
> So for new pieces, let's not add further dependencies to
> complicate moving things to drivers.
>
> Regards,
>
> Tony
>

Ok I will go ahead and pull the control module code that handles IPC 
into the wkup_m3 driver. The wkup_m3.c file is still present in 
mach-omap2 as the right location for it wasn't decided in the last RFC. 
Any thoughts on a good location for it?

Regards,
Dave

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-09 20:55           ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-09 20:55 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/09/2013 12:11 AM, Tony Lindgren wrote:
> * Dave Gerlach <d-gerlach@ti.com> [130808 09:23]:
>> On 08/08/2013 08:44 AM, Santosh Shilimkar wrote:
>>> Lets address the above better. I don't see a need of 8 functions
>>> exported doing one or 2 register writes.
>>>
>>> Look M3 based handling is going to be there on future SOCs
>>> as well and this kind of handling of IPC is very short cited.
>>>
>>
>> The idea here was to move all control module register accesses into
>> one file in planning of implementing a driver for the control module
>> itself in the future.
>>
>>> Probably we should have a separate driver for M3 in linux which
>>> can have all this local code instead of all these exports.
>>
>> The wkup_m3 code has been moved to a small driver found in patch 8
>> of this series, would it better to move this code there rather than
>> with the rest of the control module code?
>
> Please make everything you can into regular device drivers.
>
> We still have some dependencies to mach-omap2 code for PRCM
> for example, but we're trying to get all that to live in
> drivers.
>
> So for new pieces, let's not add further dependencies to
> complicate moving things to drivers.
>
> Regards,
>
> Tony
>

Ok I will go ahead and pull the control module code that handles IPC 
into the wkup_m3 driver. The wkup_m3.c file is still present in 
mach-omap2 as the right location for it wasn't decided in the last RFC. 
Any thoughts on a good location for it?

Regards,
Dave

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-09 20:34                         ` Kevin Hilman
@ 2013-08-09 21:35                           ` Nishanth Menon
  -1 siblings, 0 replies; 212+ messages in thread
From: Nishanth Menon @ 2013-08-09 21:35 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Dave Gerlach, Santosh Shilimkar, Russ Dill, linux-arm-kernel,
	linux-omap, Paul Walmsley, Vaibhav Bedia, Tony Lingren,
	Benoit Cousson

On 08/09/2013 03:34 PM, Kevin Hilman wrote:
> Nishanth Menon <nm@ti.com> writes:
>
>> On 08/09/2013 11:12 AM, Kevin Hilman wrote:
>>> Nishanth Menon <nm@ti.com> writes:
>>>
>>>> On 08/08/2013 06:04 PM, Kevin Hilman wrote:
>>>>> Nishanth Menon <nm@ti.com> writes:
>>>>>
>>>>>> On 08/08/2013 04:14 PM, Kevin Hilman wrote:
>>>>>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>>>>>
>>>>>>>> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>>>>>>>>> $subject and patch don't match.
>>>>>>>>>
>>>>>>>>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>>>>>>>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>>>>>>>>        In reference to
>>>>>>>>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>>>>>>>>> bound and which don't.
>>>>>>>>>> Does it need to? M3 firmware can pretty much define "I will force
>>>>>>>>>> the device into low power state, and if the drivers dont handle
>>>>>>>>>> things properly, fix the darned driver". M3 behavior should be
>>>>>>>>>> considered as a "hardware" as far as Linux running on MPU is
>>>>>>>>>> concerned, and firmware helps change the behavior by accounting for
>>>>>>>>>> SoC quirks. *if* we have ability to handle this in the firmware,
>>>>>>>>>> there is no need to carry this in Linux.
>>>>>>>>>>
>>>>>>>>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>>>>>>>>> comment in the last version. Linux need not know about all such firmware
>>>>>>>>> quirks. Also all these M3 specific stuff, should be done somewhere
>>>>>>>>> else. Probably having a small M3 driver won't be a bad idea.
>>>>>>>>
>>>>>>>> I am not opposed to doing it this way and letting the M3 firmware
>>>>>>>> handle idling these modules, however the one concern raised in the
>>>>>>>> last series is that an approach that does not acknowledge drivers will
>>>>>>>> hide driver PM bugs. I suppose as long as I make sure to document that
>>>>>>>> the devices are being idled by the M3 firmware this may not be an
>>>>>>>> issue. I will look into implementing this.
>>>>>>>
>>>>>>> No, please don't start idling devices in firmware that are otherwise
>>>>>>> managed by Linux.  Keep the firmware simple and dumb.  Linux is managing
>>>>>>> these devices, it should manage their bugs too.
>>>>>>
>>>>>>>
>>>>>>> This is not just about idling devices.  This is about handling broken IP
>>>>>>> blocks whose power-on reset state does not allow the the powerdomain to
>>>>>>> reach its target state.  That's just bad hardware design.
>>>>>>
>>>>>> Right, this is where M3 can help -> provide a consistent state for
>>>>>> linux kernel to work with. by the fact that we want to keep majority
>>>>>> of the power code inside master CPU, we are just letting M3 help us
>>>>>> with nothing major at all..
>>>>>
>>>>> heh, I would say HW design bugs like this are more than "nothing major
>>>>> at all." :)
>>>>>
>>>>>> tiny stuff like these can help "fix" the hardware design quirks by
>>>>>> hiding it behind the firmware and modifying the hardware behavior.
>>>>>
>>>>> I disagree here.  I'm a firmware minimalist, and hiding bugs like this
>>>>> in the firmware is wrong when Linux is otherwise managing these devices.
>>>>> It also imposes criteria on the firmware of future SoCs that doesn't
>>>>> belong there either.  IMO, the only stuff the firmware should do is what
>>>>> Linux *cannot* do.
>>>>>
>>>>> Remember, this only needs to happen when there isn't a driver for these
>>>>> devices.  Should we communicate to the firmware that the OS has no
>>>>> driver, so please enable the hack?  I think not.
>>>>
>>>> My view is that the M3 should *ignore* the presence/existence of MPU's
>>>> drivers. M3 will do whatever to force the system to go to suspend once
>>>> notified - this saves us the prehistoric perpetual trouble when
>>>> drivers have bugs (which get exposed in weird usage scenarios) in
>>>> production systems, we dont get any hardware help to fix them up while
>>>> attempting low power states and system never really hits low power
>>>> state. This was always because OMAP and it's derivatives have been
>>>> "democratic" in power management - if every hardware block achieves
>>>> proper state, then we achieve a system-wide low power state.
>>>>
>>>>>
>>>>>> I know it breaks the purity of role, but as the
>>>>>> next evolution, we might want to consider M3 something like an
>>>>>> "accelerator" for power management activity.. (not saying it is that
>>>>>> fast.. but conceptually).
>>>>>
>>>>> Yes, it breaks the purity of role, and makes it hard to maintain and
>>>>> extend to future SoCs.  As a maintainer, that's a red flag.  IMO, the
>>>>> roles need to be kept clear.  The M3 manages some devices and the
>>>>> interconnect that MPU/Linux cannot, the rest are managed by Linux.
>>>>
>>>> suspend is a very controlled state as against cpuidle where driver
>>>> knowledge is necessary and in fact mandatory. drivers are supposed to
>>>> release their resources - and even though we test the hell out of
>>>> them, we do have paths untrodden when it comes to production systems.
>>>
>>> Since folks don't seem to care about idle for AM33xx (starting with the
>>> hw designers, from what I can tell), you have the luxury of thinking
>>> only about suspend, where firmware can be heavy handed and force things
>>> into submission.  Unfortunately, with cpuidle, life is not that easy and
>>> you have to have cooperation of the device drivers.  Coordinating that
>>> with firmware is not so simple, to put it mildly.
>>>
>>> Any SW/firmware design that does not account for *both* static PM
>>> (suspend/resume) and dynamic PM (runtime PM + CPUidle) is not long-term
>>> maintainable, and thus ready for mainline IMO.  (BTW, this is another
>>> theme from previous reviews of this series.)
>>
>> I completely agree with you.  But is'nt the specific suspend state we
>> are attempting to achieve on AM335x just tooo expensive latency wise
>> for being even considered for cpuidle?
>>
>> I am sure you recollect the latencies involved in OMAP3 OFF mode Vs
>> OMAP4+ OFF mode - which basically kicked out OFF mode from OMAP4
>> cpuidle C states? - it was practically useless
>>
>> in this *specific* power state we are attempting, we do a bunch of i2c
>> operations, etc, in short something that cannot even be considered for
>> cpuidle.
>>
>> Considering this, we can consider the same only for suspend path -
>> hence allowing firmware to do more here.
>>
>>
>> This does not conflict with cpuidle (which controls MPU) or runtime PM
>> (which kicks in once you have drivers active, but if drivers get
>> active, we dont need to deal with this crap).
>>
>> Dont you think this helps the specific case to move this into firmware
>> rather than into omap_device?
>
> No, I don't.
>
> That means the firmware design is based on several assumptions about
> what Linux can and can't do in idle, and then imposing that on future
> Linux designs as well.  I dont' buy it.

OK, I back out my proposal. Will let Dave try out a generic solution in 
kernel and comment back.


-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-09 21:35                           ` Nishanth Menon
  0 siblings, 0 replies; 212+ messages in thread
From: Nishanth Menon @ 2013-08-09 21:35 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/09/2013 03:34 PM, Kevin Hilman wrote:
> Nishanth Menon <nm@ti.com> writes:
>
>> On 08/09/2013 11:12 AM, Kevin Hilman wrote:
>>> Nishanth Menon <nm@ti.com> writes:
>>>
>>>> On 08/08/2013 06:04 PM, Kevin Hilman wrote:
>>>>> Nishanth Menon <nm@ti.com> writes:
>>>>>
>>>>>> On 08/08/2013 04:14 PM, Kevin Hilman wrote:
>>>>>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>>>>>
>>>>>>>> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>>>>>>>>> $subject and patch don't match.
>>>>>>>>>
>>>>>>>>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>>>>>>>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>>>>>>>>        In reference to
>>>>>>>>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>>>>>>>>> bound and which don't.
>>>>>>>>>> Does it need to? M3 firmware can pretty much define "I will force
>>>>>>>>>> the device into low power state, and if the drivers dont handle
>>>>>>>>>> things properly, fix the darned driver". M3 behavior should be
>>>>>>>>>> considered as a "hardware" as far as Linux running on MPU is
>>>>>>>>>> concerned, and firmware helps change the behavior by accounting for
>>>>>>>>>> SoC quirks. *if* we have ability to handle this in the firmware,
>>>>>>>>>> there is no need to carry this in Linux.
>>>>>>>>>>
>>>>>>>>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>>>>>>>>> comment in the last version. Linux need not know about all such firmware
>>>>>>>>> quirks. Also all these M3 specific stuff, should be done somewhere
>>>>>>>>> else. Probably having a small M3 driver won't be a bad idea.
>>>>>>>>
>>>>>>>> I am not opposed to doing it this way and letting the M3 firmware
>>>>>>>> handle idling these modules, however the one concern raised in the
>>>>>>>> last series is that an approach that does not acknowledge drivers will
>>>>>>>> hide driver PM bugs. I suppose as long as I make sure to document that
>>>>>>>> the devices are being idled by the M3 firmware this may not be an
>>>>>>>> issue. I will look into implementing this.
>>>>>>>
>>>>>>> No, please don't start idling devices in firmware that are otherwise
>>>>>>> managed by Linux.  Keep the firmware simple and dumb.  Linux is managing
>>>>>>> these devices, it should manage their bugs too.
>>>>>>
>>>>>>>
>>>>>>> This is not just about idling devices.  This is about handling broken IP
>>>>>>> blocks whose power-on reset state does not allow the the powerdomain to
>>>>>>> reach its target state.  That's just bad hardware design.
>>>>>>
>>>>>> Right, this is where M3 can help -> provide a consistent state for
>>>>>> linux kernel to work with. by the fact that we want to keep majority
>>>>>> of the power code inside master CPU, we are just letting M3 help us
>>>>>> with nothing major at all..
>>>>>
>>>>> heh, I would say HW design bugs like this are more than "nothing major
>>>>> at all." :)
>>>>>
>>>>>> tiny stuff like these can help "fix" the hardware design quirks by
>>>>>> hiding it behind the firmware and modifying the hardware behavior.
>>>>>
>>>>> I disagree here.  I'm a firmware minimalist, and hiding bugs like this
>>>>> in the firmware is wrong when Linux is otherwise managing these devices.
>>>>> It also imposes criteria on the firmware of future SoCs that doesn't
>>>>> belong there either.  IMO, the only stuff the firmware should do is what
>>>>> Linux *cannot* do.
>>>>>
>>>>> Remember, this only needs to happen when there isn't a driver for these
>>>>> devices.  Should we communicate to the firmware that the OS has no
>>>>> driver, so please enable the hack?  I think not.
>>>>
>>>> My view is that the M3 should *ignore* the presence/existence of MPU's
>>>> drivers. M3 will do whatever to force the system to go to suspend once
>>>> notified - this saves us the prehistoric perpetual trouble when
>>>> drivers have bugs (which get exposed in weird usage scenarios) in
>>>> production systems, we dont get any hardware help to fix them up while
>>>> attempting low power states and system never really hits low power
>>>> state. This was always because OMAP and it's derivatives have been
>>>> "democratic" in power management - if every hardware block achieves
>>>> proper state, then we achieve a system-wide low power state.
>>>>
>>>>>
>>>>>> I know it breaks the purity of role, but as the
>>>>>> next evolution, we might want to consider M3 something like an
>>>>>> "accelerator" for power management activity.. (not saying it is that
>>>>>> fast.. but conceptually).
>>>>>
>>>>> Yes, it breaks the purity of role, and makes it hard to maintain and
>>>>> extend to future SoCs.  As a maintainer, that's a red flag.  IMO, the
>>>>> roles need to be kept clear.  The M3 manages some devices and the
>>>>> interconnect that MPU/Linux cannot, the rest are managed by Linux.
>>>>
>>>> suspend is a very controlled state as against cpuidle where driver
>>>> knowledge is necessary and in fact mandatory. drivers are supposed to
>>>> release their resources - and even though we test the hell out of
>>>> them, we do have paths untrodden when it comes to production systems.
>>>
>>> Since folks don't seem to care about idle for AM33xx (starting with the
>>> hw designers, from what I can tell), you have the luxury of thinking
>>> only about suspend, where firmware can be heavy handed and force things
>>> into submission.  Unfortunately, with cpuidle, life is not that easy and
>>> you have to have cooperation of the device drivers.  Coordinating that
>>> with firmware is not so simple, to put it mildly.
>>>
>>> Any SW/firmware design that does not account for *both* static PM
>>> (suspend/resume) and dynamic PM (runtime PM + CPUidle) is not long-term
>>> maintainable, and thus ready for mainline IMO.  (BTW, this is another
>>> theme from previous reviews of this series.)
>>
>> I completely agree with you.  But is'nt the specific suspend state we
>> are attempting to achieve on AM335x just tooo expensive latency wise
>> for being even considered for cpuidle?
>>
>> I am sure you recollect the latencies involved in OMAP3 OFF mode Vs
>> OMAP4+ OFF mode - which basically kicked out OFF mode from OMAP4
>> cpuidle C states? - it was practically useless
>>
>> in this *specific* power state we are attempting, we do a bunch of i2c
>> operations, etc, in short something that cannot even be considered for
>> cpuidle.
>>
>> Considering this, we can consider the same only for suspend path -
>> hence allowing firmware to do more here.
>>
>>
>> This does not conflict with cpuidle (which controls MPU) or runtime PM
>> (which kicks in once you have drivers active, but if drivers get
>> active, we dont need to deal with this crap).
>>
>> Dont you think this helps the specific case to move this into firmware
>> rather than into omap_device?
>
> No, I don't.
>
> That means the firmware design is based on several assumptions about
> what Linux can and can't do in idle, and then imposing that on future
> Linux designs as well.  I dont' buy it.

OK, I back out my proposal. Will let Dave try out a generic solution in 
kernel and comment back.


-- 
Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-09 20:34                         ` Kevin Hilman
@ 2013-08-09 22:28                           ` Russ Dill
  -1 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-09 22:28 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Nishanth Menon, Dave Gerlach, Santosh Shilimkar,
	linux-arm-kernel, linux-omap, Paul Walmsley, Vaibhav Bedia,
	Tony Lingren, Benoit Cousson

On Fri, Aug 9, 2013 at 1:34 PM, Kevin Hilman <khilman@linaro.org> wrote:
> Nishanth Menon <nm@ti.com> writes:
>
>> On 08/09/2013 11:12 AM, Kevin Hilman wrote:
>>> Nishanth Menon <nm@ti.com> writes:
>>>
>>>> On 08/08/2013 06:04 PM, Kevin Hilman wrote:
>>>>> Nishanth Menon <nm@ti.com> writes:
>>>>>
>>>>>> On 08/08/2013 04:14 PM, Kevin Hilman wrote:
>>>>>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>>>>>
>>>>>>>> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>>>>>>>>> $subject and patch don't match.
>>>>>>>>>
>>>>>>>>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>>>>>>>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>>>>>>>>       In reference to
>>>>>>>>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>>>>>>>>> bound and which don't.
>>>>>>>>>> Does it need to? M3 firmware can pretty much define "I will force
>>>>>>>>>> the device into low power state, and if the drivers dont handle
>>>>>>>>>> things properly, fix the darned driver". M3 behavior should be
>>>>>>>>>> considered as a "hardware" as far as Linux running on MPU is
>>>>>>>>>> concerned, and firmware helps change the behavior by accounting for
>>>>>>>>>> SoC quirks. *if* we have ability to handle this in the firmware,
>>>>>>>>>> there is no need to carry this in Linux.
>>>>>>>>>>
>>>>>>>>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>>>>>>>>> comment in the last version. Linux need not know about all such firmware
>>>>>>>>> quirks. Also all these M3 specific stuff, should be done somewhere
>>>>>>>>> else. Probably having a small M3 driver won't be a bad idea.
>>>>>>>>
>>>>>>>> I am not opposed to doing it this way and letting the M3 firmware
>>>>>>>> handle idling these modules, however the one concern raised in the
>>>>>>>> last series is that an approach that does not acknowledge drivers will
>>>>>>>> hide driver PM bugs. I suppose as long as I make sure to document that
>>>>>>>> the devices are being idled by the M3 firmware this may not be an
>>>>>>>> issue. I will look into implementing this.
>>>>>>>
>>>>>>> No, please don't start idling devices in firmware that are otherwise
>>>>>>> managed by Linux.  Keep the firmware simple and dumb.  Linux is managing
>>>>>>> these devices, it should manage their bugs too.
>>>>>>
>>>>>>>
>>>>>>> This is not just about idling devices.  This is about handling broken IP
>>>>>>> blocks whose power-on reset state does not allow the the powerdomain to
>>>>>>> reach its target state.  That's just bad hardware design.
>>>>>>
>>>>>> Right, this is where M3 can help -> provide a consistent state for
>>>>>> linux kernel to work with. by the fact that we want to keep majority
>>>>>> of the power code inside master CPU, we are just letting M3 help us
>>>>>> with nothing major at all..
>>>>>
>>>>> heh, I would say HW design bugs like this are more than "nothing major
>>>>> at all." :)
>>>>>
>>>>>> tiny stuff like these can help "fix" the hardware design quirks by
>>>>>> hiding it behind the firmware and modifying the hardware behavior.
>>>>>
>>>>> I disagree here.  I'm a firmware minimalist, and hiding bugs like this
>>>>> in the firmware is wrong when Linux is otherwise managing these devices.
>>>>> It also imposes criteria on the firmware of future SoCs that doesn't
>>>>> belong there either.  IMO, the only stuff the firmware should do is what
>>>>> Linux *cannot* do.
>>>>>
>>>>> Remember, this only needs to happen when there isn't a driver for these
>>>>> devices.  Should we communicate to the firmware that the OS has no
>>>>> driver, so please enable the hack?  I think not.
>>>>
>>>> My view is that the M3 should *ignore* the presence/existence of MPU's
>>>> drivers. M3 will do whatever to force the system to go to suspend once
>>>> notified - this saves us the prehistoric perpetual trouble when
>>>> drivers have bugs (which get exposed in weird usage scenarios) in
>>>> production systems, we dont get any hardware help to fix them up while
>>>> attempting low power states and system never really hits low power
>>>> state. This was always because OMAP and it's derivatives have been
>>>> "democratic" in power management - if every hardware block achieves
>>>> proper state, then we achieve a system-wide low power state.
>>>>
>>>>>
>>>>>> I know it breaks the purity of role, but as the
>>>>>> next evolution, we might want to consider M3 something like an
>>>>>> "accelerator" for power management activity.. (not saying it is that
>>>>>> fast.. but conceptually).
>>>>>
>>>>> Yes, it breaks the purity of role, and makes it hard to maintain and
>>>>> extend to future SoCs.  As a maintainer, that's a red flag.  IMO, the
>>>>> roles need to be kept clear.  The M3 manages some devices and the
>>>>> interconnect that MPU/Linux cannot, the rest are managed by Linux.
>>>>
>>>> suspend is a very controlled state as against cpuidle where driver
>>>> knowledge is necessary and in fact mandatory. drivers are supposed to
>>>> release their resources - and even though we test the hell out of
>>>> them, we do have paths untrodden when it comes to production systems.
>>>
>>> Since folks don't seem to care about idle for AM33xx (starting with the
>>> hw designers, from what I can tell), you have the luxury of thinking
>>> only about suspend, where firmware can be heavy handed and force things
>>> into submission.  Unfortunately, with cpuidle, life is not that easy and
>>> you have to have cooperation of the device drivers.  Coordinating that
>>> with firmware is not so simple, to put it mildly.
>>>
>>> Any SW/firmware design that does not account for *both* static PM
>>> (suspend/resume) and dynamic PM (runtime PM + CPUidle) is not long-term
>>> maintainable, and thus ready for mainline IMO.  (BTW, this is another
>>> theme from previous reviews of this series.)
>>
>> I completely agree with you.  But is'nt the specific suspend state we
>> are attempting to achieve on AM335x just tooo expensive latency wise
>> for being even considered for cpuidle?
>>
>> I am sure you recollect the latencies involved in OMAP3 OFF mode Vs
>> OMAP4+ OFF mode - which basically kicked out OFF mode from OMAP4
>> cpuidle C states? - it was practically useless
>>
>> in this *specific* power state we are attempting, we do a bunch of i2c
>> operations, etc, in short something that cannot even be considered for
>> cpuidle.
>>
>> Considering this, we can consider the same only for suspend path -
>> hence allowing firmware to do more here.
>>
>>
>> This does not conflict with cpuidle (which controls MPU) or runtime PM
>> (which kicks in once you have drivers active, but if drivers get
>> active, we dont need to deal with this crap).
>>
>> Dont you think this helps the specific case to move this into firmware
>> rather than into omap_device?
>
> No, I don't.
>
> That means the firmware design is based on several assumptions about
> what Linux can and can't do in idle, and then imposing that on future
> Linux designs as well.  I dont' buy it.
>
> Kevin

I was taking a look at this situation, figuring that the
suspend/resume callbacks in omap_device might be the right place to do
it, and came across this:

https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=72bb6f9b51c82c820ddef892455a85b115460904

Under what situations would the driver callbacks be present if probe
fails? I'm looking at really_probe in drivers/base/dd.c, and if probe
fails, dev->driver is set to NULL. What was the condition this was
protecting against?

Also, by modifying _od_suspend_noirq, can we force idle unbound omap
device? Would we need a new omap_hwmod flag to check which devices
should be force idled if no driver is bound?

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-09 22:28                           ` Russ Dill
  0 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-09 22:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Aug 9, 2013 at 1:34 PM, Kevin Hilman <khilman@linaro.org> wrote:
> Nishanth Menon <nm@ti.com> writes:
>
>> On 08/09/2013 11:12 AM, Kevin Hilman wrote:
>>> Nishanth Menon <nm@ti.com> writes:
>>>
>>>> On 08/08/2013 06:04 PM, Kevin Hilman wrote:
>>>>> Nishanth Menon <nm@ti.com> writes:
>>>>>
>>>>>> On 08/08/2013 04:14 PM, Kevin Hilman wrote:
>>>>>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>>>>>
>>>>>>>> On 08/08/2013 10:03 AM, Santosh Shilimkar wrote:
>>>>>>>>> $subject and patch don't match.
>>>>>>>>>
>>>>>>>>> On Thursday 08 August 2013 08:26 AM, Nishanth Menon wrote:
>>>>>>>>>> On 08/08/2013 03:45 AM, Russ Dill wrote:
>>>>>>>>>>>       In reference to
>>>>>>>>>>> the M3 handling it, the M3 wouldn't know which devices have a driver
>>>>>>>>>>> bound and which don't.
>>>>>>>>>> Does it need to? M3 firmware can pretty much define "I will force
>>>>>>>>>> the device into low power state, and if the drivers dont handle
>>>>>>>>>> things properly, fix the darned driver". M3 behavior should be
>>>>>>>>>> considered as a "hardware" as far as Linux running on MPU is
>>>>>>>>>> concerned, and firmware helps change the behavior by accounting for
>>>>>>>>>> SoC quirks. *if* we have ability to handle this in the firmware,
>>>>>>>>>> there is no need to carry this in Linux.
>>>>>>>>>>
>>>>>>>>> I agree with Nishant. I don't like this patch and IIRC, I gave same
>>>>>>>>> comment in the last version. Linux need not know about all such firmware
>>>>>>>>> quirks. Also all these M3 specific stuff, should be done somewhere
>>>>>>>>> else. Probably having a small M3 driver won't be a bad idea.
>>>>>>>>
>>>>>>>> I am not opposed to doing it this way and letting the M3 firmware
>>>>>>>> handle idling these modules, however the one concern raised in the
>>>>>>>> last series is that an approach that does not acknowledge drivers will
>>>>>>>> hide driver PM bugs. I suppose as long as I make sure to document that
>>>>>>>> the devices are being idled by the M3 firmware this may not be an
>>>>>>>> issue. I will look into implementing this.
>>>>>>>
>>>>>>> No, please don't start idling devices in firmware that are otherwise
>>>>>>> managed by Linux.  Keep the firmware simple and dumb.  Linux is managing
>>>>>>> these devices, it should manage their bugs too.
>>>>>>
>>>>>>>
>>>>>>> This is not just about idling devices.  This is about handling broken IP
>>>>>>> blocks whose power-on reset state does not allow the the powerdomain to
>>>>>>> reach its target state.  That's just bad hardware design.
>>>>>>
>>>>>> Right, this is where M3 can help -> provide a consistent state for
>>>>>> linux kernel to work with. by the fact that we want to keep majority
>>>>>> of the power code inside master CPU, we are just letting M3 help us
>>>>>> with nothing major at all..
>>>>>
>>>>> heh, I would say HW design bugs like this are more than "nothing major
>>>>> at all." :)
>>>>>
>>>>>> tiny stuff like these can help "fix" the hardware design quirks by
>>>>>> hiding it behind the firmware and modifying the hardware behavior.
>>>>>
>>>>> I disagree here.  I'm a firmware minimalist, and hiding bugs like this
>>>>> in the firmware is wrong when Linux is otherwise managing these devices.
>>>>> It also imposes criteria on the firmware of future SoCs that doesn't
>>>>> belong there either.  IMO, the only stuff the firmware should do is what
>>>>> Linux *cannot* do.
>>>>>
>>>>> Remember, this only needs to happen when there isn't a driver for these
>>>>> devices.  Should we communicate to the firmware that the OS has no
>>>>> driver, so please enable the hack?  I think not.
>>>>
>>>> My view is that the M3 should *ignore* the presence/existence of MPU's
>>>> drivers. M3 will do whatever to force the system to go to suspend once
>>>> notified - this saves us the prehistoric perpetual trouble when
>>>> drivers have bugs (which get exposed in weird usage scenarios) in
>>>> production systems, we dont get any hardware help to fix them up while
>>>> attempting low power states and system never really hits low power
>>>> state. This was always because OMAP and it's derivatives have been
>>>> "democratic" in power management - if every hardware block achieves
>>>> proper state, then we achieve a system-wide low power state.
>>>>
>>>>>
>>>>>> I know it breaks the purity of role, but as the
>>>>>> next evolution, we might want to consider M3 something like an
>>>>>> "accelerator" for power management activity.. (not saying it is that
>>>>>> fast.. but conceptually).
>>>>>
>>>>> Yes, it breaks the purity of role, and makes it hard to maintain and
>>>>> extend to future SoCs.  As a maintainer, that's a red flag.  IMO, the
>>>>> roles need to be kept clear.  The M3 manages some devices and the
>>>>> interconnect that MPU/Linux cannot, the rest are managed by Linux.
>>>>
>>>> suspend is a very controlled state as against cpuidle where driver
>>>> knowledge is necessary and in fact mandatory. drivers are supposed to
>>>> release their resources - and even though we test the hell out of
>>>> them, we do have paths untrodden when it comes to production systems.
>>>
>>> Since folks don't seem to care about idle for AM33xx (starting with the
>>> hw designers, from what I can tell), you have the luxury of thinking
>>> only about suspend, where firmware can be heavy handed and force things
>>> into submission.  Unfortunately, with cpuidle, life is not that easy and
>>> you have to have cooperation of the device drivers.  Coordinating that
>>> with firmware is not so simple, to put it mildly.
>>>
>>> Any SW/firmware design that does not account for *both* static PM
>>> (suspend/resume) and dynamic PM (runtime PM + CPUidle) is not long-term
>>> maintainable, and thus ready for mainline IMO.  (BTW, this is another
>>> theme from previous reviews of this series.)
>>
>> I completely agree with you.  But is'nt the specific suspend state we
>> are attempting to achieve on AM335x just tooo expensive latency wise
>> for being even considered for cpuidle?
>>
>> I am sure you recollect the latencies involved in OMAP3 OFF mode Vs
>> OMAP4+ OFF mode - which basically kicked out OFF mode from OMAP4
>> cpuidle C states? - it was practically useless
>>
>> in this *specific* power state we are attempting, we do a bunch of i2c
>> operations, etc, in short something that cannot even be considered for
>> cpuidle.
>>
>> Considering this, we can consider the same only for suspend path -
>> hence allowing firmware to do more here.
>>
>>
>> This does not conflict with cpuidle (which controls MPU) or runtime PM
>> (which kicks in once you have drivers active, but if drivers get
>> active, we dont need to deal with this crap).
>>
>> Dont you think this helps the specific case to move this into firmware
>> rather than into omap_device?
>
> No, I don't.
>
> That means the firmware design is based on several assumptions about
> what Linux can and can't do in idle, and then imposing that on future
> Linux designs as well.  I dont' buy it.
>
> Kevin

I was taking a look at this situation, figuring that the
suspend/resume callbacks in omap_device might be the right place to do
it, and came across this:

https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=72bb6f9b51c82c820ddef892455a85b115460904

Under what situations would the driver callbacks be present if probe
fails? I'm looking at really_probe in drivers/base/dd.c, and if probe
fails, dev->driver is set to NULL. What was the condition this was
protecting against?

Also, by modifying _od_suspend_noirq, can we force idle unbound omap
device? Would we need a new omap_hwmod flag to check which devices
should be force idled if no driver is bound?

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-08-06 17:49 ` Dave Gerlach
@ 2013-08-11 11:53   ` Daniel Mack
  -1 siblings, 0 replies; 212+ messages in thread
From: Daniel Mack @ 2013-08-11 11:53 UTC (permalink / raw)
  To: Dave Gerlach; +Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman

Hi Dave,

Thanks a lot for your work on this.

On 06.08.2013 19:49, Dave Gerlach wrote:
> This is the third version of the patch series for adding basic suspend-resume
> support for AM33XX, previously submitted by Vaibhav Bedia. This patchset 
> is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
> that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are 
> required for the pm code to properly suspend and resume.

I applied your set and the one from Suman Anna, and with musb disabled
and the firmware built from the sources you referenced, I'm able to put
a custom AM33xx based board to suspend.

The problem I currently face is that I can't make the board resume, as
neither UART0 nor GPIO0 seem to work as wakeup source.

Which wakeup source did you use in your tests?


Thanks,
Daniel


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-08-11 11:53   ` Daniel Mack
  0 siblings, 0 replies; 212+ messages in thread
From: Daniel Mack @ 2013-08-11 11:53 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Dave,

Thanks a lot for your work on this.

On 06.08.2013 19:49, Dave Gerlach wrote:
> This is the third version of the patch series for adding basic suspend-resume
> support for AM33XX, previously submitted by Vaibhav Bedia. This patchset 
> is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
> that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are 
> required for the pm code to properly suspend and resume.

I applied your set and the one from Suman Anna, and with musb disabled
and the firmware built from the sources you referenced, I'm able to put
a custom AM33xx based board to suspend.

The problem I currently face is that I can't make the board resume, as
neither UART0 nor GPIO0 seem to work as wakeup source.

Which wakeup source did you use in your tests?


Thanks,
Daniel

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-09 20:55           ` Dave Gerlach
@ 2013-08-12  7:54             ` Tony Lindgren
  -1 siblings, 0 replies; 212+ messages in thread
From: Tony Lindgren @ 2013-08-12  7:54 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: Santosh Shilimkar, linux-arm-kernel, linux-omap, Paul Walmsley,
	Kevin Hilman, Vaibhav Bedia

* Dave Gerlach <d-gerlach@ti.com> [130809 14:02]:
>
> Ok I will go ahead and pull the control module code that handles IPC
> into the wkup_m3 driver. The wkup_m3.c file is still present in
> mach-omap2 as the right location for it wasn't decided in the last
> RFC. Any thoughts on a good location for it?

Well maybe try to think how to use these features in a Linux
generic way without having to export tons of custom functions?

Regards,

Tony

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-12  7:54             ` Tony Lindgren
  0 siblings, 0 replies; 212+ messages in thread
From: Tony Lindgren @ 2013-08-12  7:54 UTC (permalink / raw)
  To: linux-arm-kernel

* Dave Gerlach <d-gerlach@ti.com> [130809 14:02]:
>
> Ok I will go ahead and pull the control module code that handles IPC
> into the wkup_m3 driver. The wkup_m3.c file is still present in
> mach-omap2 as the right location for it wasn't decided in the last
> RFC. Any thoughts on a good location for it?

Well maybe try to think how to use these features in a Linux
generic way without having to export tons of custom functions?

Regards,

Tony

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-09 22:28                           ` Russ Dill
@ 2013-08-12 16:09                             ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-12 16:09 UTC (permalink / raw)
  To: Russ Dill
  Cc: Nishanth Menon, Dave Gerlach, Santosh Shilimkar,
	linux-arm-kernel, linux-omap, Paul Walmsley, Vaibhav Bedia,
	Tony Lingren, Benoit Cousson

Hi Russ,

Russ Dill <russ.dill@gmail.com> writes:

[...]

> I was taking a look at this situation, figuring that the
> suspend/resume callbacks in omap_device might be the right place to do
> it, and came across this:
>
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=72bb6f9b51c82c820ddef892455a85b115460904
>
> Under what situations would the driver callbacks be present if probe
> fails? I'm looking at really_probe in drivers/base/dd.c, and if probe
> fails, dev->driver is set to NULL. What was the condition this was
> protecting against?

The static suspend/resume methods for PM domains don't check for
dev->driver.  (c.f. device_resume_noirq()), so during system suspend,
the PM domain callbacks are called whether or not there is a driver.

A simlar fix could've been done by checking for the existence of
dev->driver (and maybe that's a better solution), but I chose the latter
so omap_device has a finer grained track of the driver status.

> Also, by modifying _od_suspend_noirq, can we force idle unbound omap
> device? Would we need a new omap_hwmod flag to check which devices
> should be force idled if no driver is bound?

I suppose you could, but that would probably mask driver bugs where the
driver is not properly runtime suspending itself before being removed.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-12 16:09                             ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-12 16:09 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Russ,

Russ Dill <russ.dill@gmail.com> writes:

[...]

> I was taking a look at this situation, figuring that the
> suspend/resume callbacks in omap_device might be the right place to do
> it, and came across this:
>
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=72bb6f9b51c82c820ddef892455a85b115460904
>
> Under what situations would the driver callbacks be present if probe
> fails? I'm looking at really_probe in drivers/base/dd.c, and if probe
> fails, dev->driver is set to NULL. What was the condition this was
> protecting against?

The static suspend/resume methods for PM domains don't check for
dev->driver.  (c.f. device_resume_noirq()), so during system suspend,
the PM domain callbacks are called whether or not there is a driver.

A simlar fix could've been done by checking for the existence of
dev->driver (and maybe that's a better solution), but I chose the latter
so omap_device has a finer grained track of the driver status.

> Also, by modifying _od_suspend_noirq, can we force idle unbound omap
> device? Would we need a new omap_hwmod flag to check which devices
> should be force idled if no driver is bound?

I suppose you could, but that would probably mask driver bugs where the
driver is not properly runtime suspending itself before being removed.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-08-11 11:53   ` Daniel Mack
@ 2013-08-12 18:59     ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-12 18:59 UTC (permalink / raw)
  To: Daniel Mack; +Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman

On 08/11/2013 06:53 AM, Daniel Mack wrote:
> Hi Dave,
>
> Thanks a lot for your work on this.
>
> On 06.08.2013 19:49, Dave Gerlach wrote:
>> This is the third version of the patch series for adding basic suspend-resume
>> support for AM33XX, previously submitted by Vaibhav Bedia. This patchset
>> is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
>> that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are
>> required for the pm code to properly suspend and resume.
>
> I applied your set and the one from Suman Anna, and with musb disabled
> and the firmware built from the sources you referenced, I'm able to put
> a custom AM33xx based board to suspend.
>
> The problem I currently face is that I can't make the board resume, as
> neither UART0 nor GPIO0 seem to work as wakeup source.

Did you apply the other patches that are mentioned besides Suman's 
series? The board will hang while suspending without these.

>
> Which wakeup source did you use in your tests?
>

Most of my verification was done with UART wakeup.

>
> Thanks,
> Daniel
>



^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-08-12 18:59     ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-12 18:59 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/11/2013 06:53 AM, Daniel Mack wrote:
> Hi Dave,
>
> Thanks a lot for your work on this.
>
> On 06.08.2013 19:49, Dave Gerlach wrote:
>> This is the third version of the patch series for adding basic suspend-resume
>> support for AM33XX, previously submitted by Vaibhav Bedia. This patchset
>> is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
>> that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are
>> required for the pm code to properly suspend and resume.
>
> I applied your set and the one from Suman Anna, and with musb disabled
> and the firmware built from the sources you referenced, I'm able to put
> a custom AM33xx based board to suspend.
>
> The problem I currently face is that I can't make the board resume, as
> neither UART0 nor GPIO0 seem to work as wakeup source.

Did you apply the other patches that are mentioned besides Suman's 
series? The board will hang while suspending without these.

>
> Which wakeup source did you use in your tests?
>

Most of my verification was done with UART wakeup.

>
> Thanks,
> Daniel
>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-09 20:55           ` Dave Gerlach
@ 2013-08-12 19:17             ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-12 19:17 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: Tony Lindgren, Santosh Shilimkar, linux-arm-kernel, linux-omap,
	Paul Walmsley, Vaibhav Bedia

Dave Gerlach <d-gerlach@ti.com> writes:

> On 08/09/2013 12:11 AM, Tony Lindgren wrote:
>> * Dave Gerlach <d-gerlach@ti.com> [130808 09:23]:
>>> On 08/08/2013 08:44 AM, Santosh Shilimkar wrote:
>>>> Lets address the above better. I don't see a need of 8 functions
>>>> exported doing one or 2 register writes.
>>>>
>>>> Look M3 based handling is going to be there on future SOCs
>>>> as well and this kind of handling of IPC is very short cited.
>>>>
>>>
>>> The idea here was to move all control module register accesses into
>>> one file in planning of implementing a driver for the control module
>>> itself in the future.
>>>
>>>> Probably we should have a separate driver for M3 in linux which
>>>> can have all this local code instead of all these exports.
>>>
>>> The wkup_m3 code has been moved to a small driver found in patch 8
>>> of this series, would it better to move this code there rather than
>>> with the rest of the control module code?
>>
>> Please make everything you can into regular device drivers.
>>
>> We still have some dependencies to mach-omap2 code for PRCM
>> for example, but we're trying to get all that to live in
>> drivers.
>>
>> So for new pieces, let's not add further dependencies to
>> complicate moving things to drivers.
>>
>> Regards,
>>
>> Tony
>>
>
> Ok I will go ahead and pull the control module code that handles IPC
> into the wkup_m3 driver. 

Any control module register access still needs to stay in control.c.

> The wkup_m3.c file is still present in mach-omap2 as the right
> location for it wasn't decided in the last RFC. Any thoughts on a good
> location for it?

I raised this also in earlier reviews, but don't remember the if it was
answered... 

Why can't we handle the wkup_m3 using remoteproc/rpmsg instead of
creating another little driver that duplicates communication with the
M3.  Note also that the firmware load part would also be provided by
remoteproc/rpmsg.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-12 19:17             ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-12 19:17 UTC (permalink / raw)
  To: linux-arm-kernel

Dave Gerlach <d-gerlach@ti.com> writes:

> On 08/09/2013 12:11 AM, Tony Lindgren wrote:
>> * Dave Gerlach <d-gerlach@ti.com> [130808 09:23]:
>>> On 08/08/2013 08:44 AM, Santosh Shilimkar wrote:
>>>> Lets address the above better. I don't see a need of 8 functions
>>>> exported doing one or 2 register writes.
>>>>
>>>> Look M3 based handling is going to be there on future SOCs
>>>> as well and this kind of handling of IPC is very short cited.
>>>>
>>>
>>> The idea here was to move all control module register accesses into
>>> one file in planning of implementing a driver for the control module
>>> itself in the future.
>>>
>>>> Probably we should have a separate driver for M3 in linux which
>>>> can have all this local code instead of all these exports.
>>>
>>> The wkup_m3 code has been moved to a small driver found in patch 8
>>> of this series, would it better to move this code there rather than
>>> with the rest of the control module code?
>>
>> Please make everything you can into regular device drivers.
>>
>> We still have some dependencies to mach-omap2 code for PRCM
>> for example, but we're trying to get all that to live in
>> drivers.
>>
>> So for new pieces, let's not add further dependencies to
>> complicate moving things to drivers.
>>
>> Regards,
>>
>> Tony
>>
>
> Ok I will go ahead and pull the control module code that handles IPC
> into the wkup_m3 driver. 

Any control module register access still needs to stay in control.c.

> The wkup_m3.c file is still present in mach-omap2 as the right
> location for it wasn't decided in the last RFC. Any thoughts on a good
> location for it?

I raised this also in earlier reviews, but don't remember the if it was
answered... 

Why can't we handle the wkup_m3 using remoteproc/rpmsg instead of
creating another little driver that duplicates communication with the
M3.  Note also that the firmware load part would also be provided by
remoteproc/rpmsg.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 1/9] memory: emif: Move EMIF register defines to include/linux/
  2013-08-08 13:35     ` Santosh Shilimkar
@ 2013-08-12 19:32       ` Greg Kroah-Hartman
  -1 siblings, 0 replies; 212+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-12 19:32 UTC (permalink / raw)
  To: Santosh Shilimkar
  Cc: Dave Gerlach, linux-arm-kernel, linux-omap, Paul Walmsley,
	Kevin Hilman, Benoit Cousson, Aneesh V

On Thu, Aug 08, 2013 at 09:35:46AM -0400, Santosh Shilimkar wrote:
> (You have not CC'ed Greg, Looping him)
> 
> On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> > OMAP4 and AM33XX share the same EMIF controller IP. Although there
> > are significant differences in the IP integration due to which
> > AM33XX can't reuse the EMIF driver DVFS similar to OMAP4,
> > it can definitely benefit by reusing the EMIF related macros
> > defined in drivers/memory/emif.h.
> > 
> > In the current OMAP PM framework the PM code resides under
> > arch/arm/mach-omap2/. To enable reuse of the register defines move
> > the register defines in the emif header file to include/linux so that
> > both the EMIF driver and the AM33XX PM code can benefit.
> > 
> > Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> > Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> > Cc: Benoit Cousson <benoit.cousson@linaro.org>
> > Cc: Aneesh V <aneesh@ti.com>
> > ---
> >  drivers/memory/emif.h   |  543 +--------------------------------------------
> >  include/linux/ti_emif.h |  558 +++++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 559 insertions(+), 542 deletions(-)
> >  create mode 100644 include/linux/ti_emif.h
> > 
> For file movement or some part of file movement, while formating
> patch, use "git format-patch -C" so that only delta change will
> appear in the patch.
> 
> The patch as such is fine by me.
> Acked-by: Santosh Shililmar <santosh.shilimkar@ti.com>
> 
> Greg,
> Your ack is needed on this patch so that it can go
> along with the series. Subsequent patch from this series
> use the register defines from this patch.

Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 1/9] memory: emif: Move EMIF register defines to include/linux/
@ 2013-08-12 19:32       ` Greg Kroah-Hartman
  0 siblings, 0 replies; 212+ messages in thread
From: Greg Kroah-Hartman @ 2013-08-12 19:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 08, 2013 at 09:35:46AM -0400, Santosh Shilimkar wrote:
> (You have not CC'ed Greg, Looping him)
> 
> On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
> > OMAP4 and AM33XX share the same EMIF controller IP. Although there
> > are significant differences in the IP integration due to which
> > AM33XX can't reuse the EMIF driver DVFS similar to OMAP4,
> > it can definitely benefit by reusing the EMIF related macros
> > defined in drivers/memory/emif.h.
> > 
> > In the current OMAP PM framework the PM code resides under
> > arch/arm/mach-omap2/. To enable reuse of the register defines move
> > the register defines in the emif header file to include/linux so that
> > both the EMIF driver and the AM33XX PM code can benefit.
> > 
> > Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> > Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> > Cc: Benoit Cousson <benoit.cousson@linaro.org>
> > Cc: Aneesh V <aneesh@ti.com>
> > ---
> >  drivers/memory/emif.h   |  543 +--------------------------------------------
> >  include/linux/ti_emif.h |  558 +++++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 559 insertions(+), 542 deletions(-)
> >  create mode 100644 include/linux/ti_emif.h
> > 
> For file movement or some part of file movement, while formating
> patch, use "git format-patch -C" so that only delta change will
> appear in the patch.
> 
> The patch as such is fine by me.
> Acked-by: Santosh Shililmar <santosh.shilimkar@ti.com>
> 
> Greg,
> Your ack is needed on this patch so that it can go
> along with the series. Subsequent patch from this series
> use the register defines from this patch.

Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 1/9] memory: emif: Move EMIF register defines to include/linux/
  2013-08-12 19:32       ` Greg Kroah-Hartman
@ 2013-08-12 19:33         ` Santosh Shilimkar
  -1 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-12 19:33 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Dave Gerlach, linux-arm-kernel, linux-omap, Paul Walmsley,
	Kevin Hilman, Benoit Cousson, Aneesh V

On Monday 12 August 2013 03:32 PM, Greg Kroah-Hartman wrote:
> On Thu, Aug 08, 2013 at 09:35:46AM -0400, Santosh Shilimkar wrote:
>> (You have not CC'ed Greg, Looping him)
>>
>> On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
>>> OMAP4 and AM33XX share the same EMIF controller IP. Although there
>>> are significant differences in the IP integration due to which
>>> AM33XX can't reuse the EMIF driver DVFS similar to OMAP4,
>>> it can definitely benefit by reusing the EMIF related macros
>>> defined in drivers/memory/emif.h.
>>>
>>> In the current OMAP PM framework the PM code resides under
>>> arch/arm/mach-omap2/. To enable reuse of the register defines move
>>> the register defines in the emif header file to include/linux so that
>>> both the EMIF driver and the AM33XX PM code can benefit.
>>>
>>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>> Cc: Benoit Cousson <benoit.cousson@linaro.org>
>>> Cc: Aneesh V <aneesh@ti.com>
>>> ---
>>>  drivers/memory/emif.h   |  543 +--------------------------------------------
>>>  include/linux/ti_emif.h |  558 +++++++++++++++++++++++++++++++++++++++++++++++
>>>  2 files changed, 559 insertions(+), 542 deletions(-)
>>>  create mode 100644 include/linux/ti_emif.h
>>>
>> For file movement or some part of file movement, while formating
>> patch, use "git format-patch -C" so that only delta change will
>> appear in the patch.
>>
>> The patch as such is fine by me.
>> Acked-by: Santosh Shililmar <santosh.shilimkar@ti.com>
>>
>> Greg,
>> Your ack is needed on this patch so that it can go
>> along with the series. Subsequent patch from this series
>> use the register defines from this patch.
> 
> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> 
Thanks !!

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 1/9] memory: emif: Move EMIF register defines to include/linux/
@ 2013-08-12 19:33         ` Santosh Shilimkar
  0 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-12 19:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Monday 12 August 2013 03:32 PM, Greg Kroah-Hartman wrote:
> On Thu, Aug 08, 2013 at 09:35:46AM -0400, Santosh Shilimkar wrote:
>> (You have not CC'ed Greg, Looping him)
>>
>> On Tuesday 06 August 2013 01:49 PM, Dave Gerlach wrote:
>>> OMAP4 and AM33XX share the same EMIF controller IP. Although there
>>> are significant differences in the IP integration due to which
>>> AM33XX can't reuse the EMIF driver DVFS similar to OMAP4,
>>> it can definitely benefit by reusing the EMIF related macros
>>> defined in drivers/memory/emif.h.
>>>
>>> In the current OMAP PM framework the PM code resides under
>>> arch/arm/mach-omap2/. To enable reuse of the register defines move
>>> the register defines in the emif header file to include/linux so that
>>> both the EMIF driver and the AM33XX PM code can benefit.
>>>
>>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>> Cc: Benoit Cousson <benoit.cousson@linaro.org>
>>> Cc: Aneesh V <aneesh@ti.com>
>>> ---
>>>  drivers/memory/emif.h   |  543 +--------------------------------------------
>>>  include/linux/ti_emif.h |  558 +++++++++++++++++++++++++++++++++++++++++++++++
>>>  2 files changed, 559 insertions(+), 542 deletions(-)
>>>  create mode 100644 include/linux/ti_emif.h
>>>
>> For file movement or some part of file movement, while formating
>> patch, use "git format-patch -C" so that only delta change will
>> appear in the patch.
>>
>> The patch as such is fine by me.
>> Acked-by: Santosh Shililmar <santosh.shilimkar@ti.com>
>>
>> Greg,
>> Your ack is needed on this patch so that it can go
>> along with the series. Subsequent patch from this series
>> use the register defines from this patch.
> 
> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> 
Thanks !!

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-12 19:17             ` Kevin Hilman
@ 2013-08-12 21:40               ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-12 21:40 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Tony Lindgren, Santosh Shilimkar, linux-arm-kernel, linux-omap,
	Paul Walmsley, Vaibhav Bedia, Suman Anna

On 08/12/2013 02:17 PM, Kevin Hilman wrote:
> Dave Gerlach <d-gerlach@ti.com> writes:
>
>> On 08/09/2013 12:11 AM, Tony Lindgren wrote:
>>> * Dave Gerlach <d-gerlach@ti.com> [130808 09:23]:
>>>> On 08/08/2013 08:44 AM, Santosh Shilimkar wrote:
>>>>> Lets address the above better. I don't see a need of 8 functions
>>>>> exported doing one or 2 register writes.
>>>>>
>>>>> Look M3 based handling is going to be there on future SOCs
>>>>> as well and this kind of handling of IPC is very short cited.
>>>>>
>>>>
>>>> The idea here was to move all control module register accesses into
>>>> one file in planning of implementing a driver for the control module
>>>> itself in the future.
>>>>
>>>>> Probably we should have a separate driver for M3 in linux which
>>>>> can have all this local code instead of all these exports.
>>>>
>>>> The wkup_m3 code has been moved to a small driver found in patch 8
>>>> of this series, would it better to move this code there rather than
>>>> with the rest of the control module code?
>>>
>>> Please make everything you can into regular device drivers.
>>>
>>> We still have some dependencies to mach-omap2 code for PRCM
>>> for example, but we're trying to get all that to live in
>>> drivers.
>>>
>>> So for new pieces, let's not add further dependencies to
>>> complicate moving things to drivers.
>>>
>>> Regards,
>>>
>>> Tony
>>>
>>
>> Ok I will go ahead and pull the control module code that handles IPC
>> into the wkup_m3 driver.
>
> Any control module register access still needs to stay in control.c.
>
>> The wkup_m3.c file is still present in mach-omap2 as the right
>> location for it wasn't decided in the last RFC. Any thoughts on a good
>> location for it?
>
> I raised this also in earlier reviews, but don't remember the if it was
> answered...
>
> Why can't we handle the wkup_m3 using remoteproc/rpmsg instead of
> creating another little driver that duplicates communication with the
> M3.  Note also that the firmware load part would also be provided by
> remoteproc/rpmsg.

Looping Suman Anna who handled the IPC patches this patch set is based 
on top of...

For the wkup_m3, the mailbox isn't used in a traditional manner. It's 
only used with a dummy write to trigger an interrupt from the A8 to the 
M3 and then communication happens in IPC registers within the control 
module. No messages are actually sent through the mailbox in either 
direction so that's why it was done this way rather than bring in full 
support for the mailbox.

>
> Kevin
>


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-12 21:40               ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-12 21:40 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/12/2013 02:17 PM, Kevin Hilman wrote:
> Dave Gerlach <d-gerlach@ti.com> writes:
>
>> On 08/09/2013 12:11 AM, Tony Lindgren wrote:
>>> * Dave Gerlach <d-gerlach@ti.com> [130808 09:23]:
>>>> On 08/08/2013 08:44 AM, Santosh Shilimkar wrote:
>>>>> Lets address the above better. I don't see a need of 8 functions
>>>>> exported doing one or 2 register writes.
>>>>>
>>>>> Look M3 based handling is going to be there on future SOCs
>>>>> as well and this kind of handling of IPC is very short cited.
>>>>>
>>>>
>>>> The idea here was to move all control module register accesses into
>>>> one file in planning of implementing a driver for the control module
>>>> itself in the future.
>>>>
>>>>> Probably we should have a separate driver for M3 in linux which
>>>>> can have all this local code instead of all these exports.
>>>>
>>>> The wkup_m3 code has been moved to a small driver found in patch 8
>>>> of this series, would it better to move this code there rather than
>>>> with the rest of the control module code?
>>>
>>> Please make everything you can into regular device drivers.
>>>
>>> We still have some dependencies to mach-omap2 code for PRCM
>>> for example, but we're trying to get all that to live in
>>> drivers.
>>>
>>> So for new pieces, let's not add further dependencies to
>>> complicate moving things to drivers.
>>>
>>> Regards,
>>>
>>> Tony
>>>
>>
>> Ok I will go ahead and pull the control module code that handles IPC
>> into the wkup_m3 driver.
>
> Any control module register access still needs to stay in control.c.
>
>> The wkup_m3.c file is still present in mach-omap2 as the right
>> location for it wasn't decided in the last RFC. Any thoughts on a good
>> location for it?
>
> I raised this also in earlier reviews, but don't remember the if it was
> answered...
>
> Why can't we handle the wkup_m3 using remoteproc/rpmsg instead of
> creating another little driver that duplicates communication with the
> M3.  Note also that the firmware load part would also be provided by
> remoteproc/rpmsg.

Looping Suman Anna who handled the IPC patches this patch set is based 
on top of...

For the wkup_m3, the mailbox isn't used in a traditional manner. It's 
only used with a dummy write to trigger an interrupt from the A8 to the 
M3 and then communication happens in IPC registers within the control 
module. No messages are actually sent through the mailbox in either 
direction so that's why it was done this way rather than bring in full 
support for the mailbox.

>
> Kevin
>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-13  7:43     ` Russ Dill
  -1 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-13  7:43 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman,
	Vaibhav Bedia, Tony Lingren, Santosh Shilimkar, Benoit Cousson

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> AM335x supports various low power modes as documented
> in section 8.1.4.3 of the AM335x TRM which is available
> @ http://www.ti.com/litv/pdf/spruh73f
>
> DeepSleep0 mode offers the lowest power mode with limited
> wakeup sources without a system reboot and is mapped as
> the suspend state in the kernel. In this state, MPU and
> PER domains are turned off with the internal RAM held in
> retention to facilitate resume process. As part of the boot
> process, the assembly code is copied over to OCMCRAM using
> the OMAP SRAM code.
>
> AM335x has a Cortex-M3 (WKUP_M3) which assists the MPU
> in DeepSleep0 entry and exit. WKUP_M3 takes care of the
> clockdomain and powerdomain transitions based on the
> intended low power state. MPU needs to load the appropriate
> WKUP_M3 binary onto the WKUP_M3 memory space before it can
> leverage any of the PM features like DeepSleep.
>
> The IPC mechanism between MPU and WKUP_M3 uses a mailbox
> sub-module and 8 IPC registers in the Control module. MPU
> uses the assigned Mailbox for issuing an interrupt to
> WKUP_M3 which then goes and checks the IPC registers for
> the payload. WKUP_M3 has the ability to trigger on interrupt
> to MPU by executing the "sev" instruction.
>
> In the current implementation when the suspend process
> is initiated MPU interrupts the WKUP_M3 to let it know about
> the intent of entering DeepSleep0 and waits for an ACK. When
> the ACK is received MPU continues with its suspend process
> to suspend all the drivers and then jumps to assembly in
> OCMC RAM. The assembly code puts the PLLs in bypass, puts the
> external RAM in self-refresh mode and then finally execute the
> WFI instruction. Execution of the WFI instruction triggers another
> interrupt to the WKUP_M3 which then continues wiht the power down
> sequence wherein the clockdomain and powerdomain transition takes
> place. As part of the sleep sequence, WKUP_M3 unmasks the interrupt
> lines for the wakeup sources. WFI execution on WKUP_M3 causes the
> hardware to disable the main oscillator of the SoC.
>
> When a wakeup event occurs, WKUP_M3 starts the power-up
> sequence by switching on the power domains and finally
> enabling the clock to MPU. Since the MPU gets powered down
> as part of the sleep sequence in the resume path ROM code
> starts executing. The ROM code detects a wakeup from sleep
> and then jumps to the resume location in OCMC which was
> populated in one of the IPC registers as part of the suspend
> sequence.
>
> The low level code in OCMC relocks the PLLs, enables access
> to external RAM and then jumps to the cpu_resume code of
> the kernel to finish the resume process.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> Cc: Tony Lingren <tony@atomide.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Benoit Cousson <benoit.cousson@linaro.org>
> Cc: Paul Walmsley <paul@pwsan.com>
> Cc: Kevin Hilman <khilman@linaro.org>
> ---
>  arch/arm/mach-omap2/pm33xx.c  |  474 +++++++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/pm33xx.h  |   77 +++++++
>  arch/arm/mach-omap2/wkup_m3.c |  183 ++++++++++++++++
>  3 files changed, 734 insertions(+)
>  create mode 100644 arch/arm/mach-omap2/pm33xx.c
>  create mode 100644 arch/arm/mach-omap2/pm33xx.h
>  create mode 100644 arch/arm/mach-omap2/wkup_m3.c
>
> diff --git a/arch/arm/mach-omap2/pm33xx.c b/arch/arm/mach-omap2/pm33xx.c
> new file mode 100644
> index 0000000..d291c76
> --- /dev/null
> +++ b/arch/arm/mach-omap2/pm33xx.c
> @@ -0,0 +1,474 @@
> +/*
> + * AM33XX Power Management Routines
> + *
> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
> + * Vaibhav Bedia <vaibhav.bedia@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/kernel.h>
> +#include <linux/init.h>
> +#include <linux/cpu.h>
> +#include <linux/err.h>
> +#include <linux/firmware.h>
> +#include <linux/io.h>
> +#include <linux/platform_device.h>
> +#include <linux/sched.h>
> +#include <linux/suspend.h>
> +#include <linux/completion.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/ti_emif.h>
> +#include <linux/omap-mailbox.h>
> +
> +#include <asm/suspend.h>
> +#include <asm/proc-fns.h>
> +#include <asm/sizes.h>
> +#include <asm/fncpy.h>
> +#include <asm/system_misc.h>
> +
> +#include "pm.h"
> +#include "cm33xx.h"
> +#include "pm33xx.h"
> +#include "control.h"
> +#include "common.h"
> +#include "clockdomain.h"
> +#include "powerdomain.h"
> +#include "omap_hwmod.h"
> +#include "omap_device.h"
> +#include "soc.h"
> +#include "sram.h"
> +
> +static void __iomem *am33xx_emif_base;
> +static struct powerdomain *cefuse_pwrdm, *gfx_pwrdm, *per_pwrdm, *mpu_pwrdm;
> +static struct clockdomain *gfx_l4ls_clkdm;
> +
> +struct wakeup_src wakeups[] = {
> +       {.irq_nr = 35,  .src = "USB0_PHY"},
> +       {.irq_nr = 36,  .src = "USB1_PHY"},
> +       {.irq_nr = 40,  .src = "I2C0"},
> +       {.irq_nr = 41,  .src = "RTC Timer"},
> +       {.irq_nr = 42,  .src = "RTC Alarm"},
> +       {.irq_nr = 43,  .src = "Timer0"},
> +       {.irq_nr = 44,  .src = "Timer1"},
> +       {.irq_nr = 45,  .src = "UART"},
> +       {.irq_nr = 46,  .src = "GPIO0"},
> +       {.irq_nr = 48,  .src = "MPU_WAKE"},
> +       {.irq_nr = 49,  .src = "WDT0"},
> +       {.irq_nr = 50,  .src = "WDT1"},
> +       {.irq_nr = 51,  .src = "ADC_TSC"},
> +};
> +
> +struct forced_standby_module am33xx_mod[] = {
> +       {.oh_name = "usb_otg_hs"},
> +       {.oh_name = "tptc0"},
> +       {.oh_name = "tptc1"},
> +       {.oh_name = "tptc2"},
> +       {.oh_name = "cpgmac0"},
> +};
> +
> +static struct am33xx_pm_context *am33xx_pm;
> +
> +static DECLARE_COMPLETION(am33xx_pm_sync);
> +
> +static void (*am33xx_do_wfi_sram)(struct am33xx_suspend_params *);
> +
> +static struct am33xx_suspend_params susp_params;
> +
> +#ifdef CONFIG_SUSPEND
> +
> +static int am33xx_do_sram_idle(long unsigned int unused)
> +{
> +       am33xx_do_wfi_sram(&susp_params);
> +       return 0;
> +}
> +
> +static int am33xx_pm_suspend(void)
> +{
> +       int i, j, ret = 0;
> +
> +       int status = 0;
> +       struct platform_device *pdev;
> +       struct omap_device *od;
> +
> +       /*
> +        * By default the following IPs do not have MSTANDBY asserted
> +        * which is necessary for PER domain transition. If the drivers
> +        * are not compiled into the kernel HWMOD code will not change the
> +        * state of the IPs if the IP was not never enabled. To ensure
> +        * that there no issues with or without the drivers being compiled
> +        * in the kernel, we forcefully put these IPs to idle.
> +        */
> +       for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++) {
> +               pdev = to_platform_device(am33xx_mod[i].dev);
> +               od = to_omap_device(pdev);
> +               if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
> +                       omap_device_enable_hwmods(od);
> +                       omap_device_idle_hwmods(od);
> +               }
> +       }
> +
> +       /* Try to put GFX to sleep */
> +       omap_set_pwrdm_state(gfx_pwrdm, PWRDM_POWER_OFF);
> +       ret = cpu_suspend(0, am33xx_do_sram_idle);
> +
> +       status = pwrdm_read_prev_pwrst(gfx_pwrdm);
> +       if (status != PWRDM_POWER_OFF)
> +               pr_err("PM: GFX domain did not transition\n");
> +       else
> +               pr_info("PM: GFX domain entered low power state\n");
> +
> +       /*
> +        * BUG: GFX_L4LS clock domain needs to be woken up to
> +        * ensure thet L4LS clock domain does not get stuck in transition
> +        * If that happens L3 module does not get disabled, thereby leading
> +        * to PER power domain transition failing
> +        */
> +       clkdm_wakeup(gfx_l4ls_clkdm);
> +       clkdm_sleep(gfx_l4ls_clkdm);
> +
> +       if (ret) {
> +               pr_err("PM: Kernel suspend failure\n");
> +       } else {
> +               i = am33xx_pm_status();
> +               switch (i) {
> +               case 0:
> +                       pr_info("PM: Successfully put all powerdomains to target state\n");
> +
> +                       /*
> +                        * The PRCM registers on AM335x do not contain previous state
> +                        * information like those present on OMAP4 so we must manually
> +                        * indicate transition so state counters are properly incremented
> +                        */
> +                       pwrdm_post_transition(mpu_pwrdm);
> +                       pwrdm_post_transition(per_pwrdm);
> +                       break;
> +               case 1:
> +                       pr_err("PM: Could not transition all powerdomains to target state\n");
> +                       ret = -1;
> +                       break;
> +               default:
> +                       pr_err("PM: CM3 returned unknown result :(\nStatus = %d\n", i);
> +                       ret = -1;
> +               }
> +
> +               /* print the wakeup reason */
> +               i = am33xx_pm_wake_src();
> +               for (j = 0; j < ARRAY_SIZE(wakeups); j++) {
> +                       if (wakeups[j].irq_nr == i) {
> +                               pr_info("PM: Wakeup source %s\n", wakeups[j].src);
> +                               break;
> +                       }
> +               }
> +
> +               if (j == ARRAY_SIZE(wakeups))
> +                       pr_info("PM: Unknown wakeup source %d!\n", i);
> +       }
> +
> +       return ret;
> +}
> +
> +static int am33xx_pm_enter(suspend_state_t suspend_state)
> +{
> +       int ret = 0;
> +
> +       switch (suspend_state) {
> +       case PM_SUSPEND_STANDBY:
> +       case PM_SUSPEND_MEM:
> +               ret = am33xx_pm_suspend();
> +               break;
> +       default:
> +               ret = -EINVAL;
> +       }
> +
> +       return ret;
> +}
> +
> +/* returns the error code from msg_send - 0 for success, failure otherwise */
> +static int am33xx_ping_wkup_m3(void)
> +{
> +       int ret = 0;
> +
> +       /*
> +        * Write a dummy message to the mailbox in order to trigger the RX
> +        * interrupt to alert the M3 that data is available in the IPC
> +        * registers.
> +        */
> +       ret = omap_mbox_msg_send(am33xx_pm->mbox, 0xABCDABCD);
> +
> +       return ret;
> +}
> +
> +static void am33xx_m3_state_machine_reset(void)
> +{
> +       int i;
> +
> +       am33xx_pm->ipc.sleep_mode = IPC_CMD_RESET;
> +
> +       am33xx_pm_ipc_cmd(&am33xx_pm->ipc);
> +
> +       am33xx_pm->state = M3_STATE_MSG_FOR_RESET;
> +
> +       pr_info("PM: Sending message for resetting M3 state machine\n");
> +
> +       if (!am33xx_ping_wkup_m3()) {
> +               i = wait_for_completion_timeout(&am33xx_pm_sync,
> +                                       msecs_to_jiffies(500));
> +               if (WARN(i == 0, "PM: MPU<->CM3 sync failure\n"))
> +                       am33xx_pm->state = M3_STATE_UNKNOWN;
> +       } else {
> +               pr_warn("PM: Unable to ping CM3\n");
> +       }
> +}
> +
> +static int am33xx_pm_begin(suspend_state_t state)
> +{
> +       int i;
> +
> +       cpu_idle_poll_ctrl(true);
> +
> +       am33xx_pm->ipc.sleep_mode       = IPC_CMD_DS0;
> +       am33xx_pm->ipc.param1           = DS_IPC_DEFAULT;
> +       am33xx_pm->ipc.param2           = DS_IPC_DEFAULT;
> +
> +       am33xx_pm_ipc_cmd(&am33xx_pm->ipc);
> +
> +       am33xx_pm->state = M3_STATE_MSG_FOR_LP;
> +
> +       pr_info("PM: Sending message for entering DeepSleep mode\n");
> +
> +       if (!am33xx_ping_wkup_m3()) {
> +               i = wait_for_completion_timeout(&am33xx_pm_sync,
> +                                       msecs_to_jiffies(500));
> +               if (WARN(i == 0, "PM: MPU<->CM3 sync failure\n"))
> +                       return -1;
> +       } else {
> +               pr_warn("PM: Unable to ping CM3\n");
> +       }
> +
> +       return 0;
> +}
> +
> +static void am33xx_pm_end(void)
> +{
> +       am33xx_m3_state_machine_reset();
> +
> +       cpu_idle_poll_ctrl(false);
> +
> +       return;
> +}
> +
> +static struct platform_suspend_ops am33xx_pm_ops = {
> +       .begin          = am33xx_pm_begin,
> +       .end            = am33xx_pm_end,
> +       .enter          = am33xx_pm_enter,
> +};
> +
> +/*
> + * Dummy notifier for the mailbox
> + */
> +
> +static int wkup_mbox_msg(struct notifier_block *self, unsigned long len,
> +               void *msg)
> +{
> +       return 0;
> +}
> +
> +static struct notifier_block wkup_mbox_notifier = {
> +       .notifier_call = wkup_mbox_msg,
> +};
> +
> +void am33xx_txev_handler(void)
> +{
> +       switch (am33xx_pm->state) {
> +       case M3_STATE_RESET:
> +               am33xx_pm->state = M3_STATE_INITED;
> +               am33xx_pm->ver = am33xx_pm_version_get();
> +               if (am33xx_pm->ver == M3_VERSION_UNKNOWN ||
> +                       am33xx_pm->ver < M3_BASELINE_VERSION) {
> +                       pr_warn("PM: CM3 Firmware Version %x not supported\n",
> +                                               am33xx_pm->ver);
> +               } else {
> +                       pr_info("PM: CM3 Firmware Version = 0x%x\n",
> +                                               am33xx_pm->ver);
> +                       am33xx_pm_ops.valid = suspend_valid_only_mem;
> +               }
> +               break;
> +       case M3_STATE_MSG_FOR_RESET:
> +               am33xx_pm->state = M3_STATE_INITED;
> +               complete(&am33xx_pm_sync);
> +               break;
> +       case M3_STATE_MSG_FOR_LP:
> +               complete(&am33xx_pm_sync);
> +               break;
> +       case M3_STATE_UNKNOWN:
> +               pr_warn("PM: Unknown CM3 State\n");
> +       }
> +
> +       return;
> +}
> +
> +static void am33xx_pm_firmware_cb(const struct firmware *fw, void *context)
> +{
> +       struct am33xx_pm_context *am33xx_pm = context;
> +       int ret = 0;
> +
> +       /* no firmware found */
> +       if (!fw) {
> +               pr_err("PM: request_firmware failed\n");
> +               return;
> +       }
> +
> +       wkup_m3_copy_code(fw->data, fw->size);
> +
> +       wkup_m3_register_txev_handler(am33xx_txev_handler);
> +
> +       pr_info("PM: Copied the M3 firmware to UMEM\n");
> +
> +       /*
> +        * Invalidate M3 firmware version before hardreset.
> +        * Write invalid version in lower 4 nibbles of parameter
> +        * register (ipc_regs + 0x8).
> +        */
> +       am33xx_pm_version_clear();
> +
> +       am33xx_pm->state = M3_STATE_RESET;
> +
> +       ret = wkup_m3_prepare();
> +       if (ret) {
> +               pr_err("PM: Could not prepare WKUP_M3\n");
> +               return;
> +       }
> +
> +       /* Physical resume address to be used by ROM code */
> +       am33xx_pm->ipc.resume_addr = (AM33XX_OCMC_END -
> +               am33xx_do_wfi_sz + am33xx_resume_offset + 0x4);
> +
> +       am33xx_pm->mbox = omap_mbox_get("wkup_m3", &wkup_mbox_notifier);
> +
> +       if (IS_ERR(am33xx_pm->mbox)) {
> +               ret = -EBUSY;
> +               pr_err("PM: IPC Request for A8->M3 Channel failed!\n");
> +               return;
> +       } else {
> +               suspend_set_ops(&am33xx_pm_ops);
> +       }
> +
> +       return;
> +}
> +
> +#endif /* CONFIG_SUSPEND */
> +
> +/*
> + * Push the minimal suspend-resume code to SRAM
> + */
> +void am33xx_push_sram_idle(void)
> +{
> +       am33xx_do_wfi_sram = (void *)omap_sram_push
> +                                       (am33xx_do_wfi, am33xx_do_wfi_sz);
> +}
> +
> +static int __init am33xx_map_emif(void)
> +{
> +       am33xx_emif_base = ioremap(AM33XX_EMIF_BASE, SZ_32K);
> +
> +       if (!am33xx_emif_base)
> +               return -ENOMEM;
> +
> +       return 0;
> +}
> +
> +int __init am33xx_pm_init(void)
> +{
> +       int ret;
> +       u32 temp;
> +       struct device_node *np;
> +       int i;
> +
> +       if (!soc_is_am33xx())
> +               return -ENODEV;
> +
> +       pr_info("Power Management for AM33XX family\n");
> +
> +       /*
> +        * By default the following IPs do not have MSTANDBY asserted
> +        * which is necessary for PER domain transition. If the drivers
> +        * are not compiled into the kernel HWMOD code will not change the
> +        * state of the IPs if the IP was not never enabled
> +        */
> +       for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++)
> +               am33xx_mod[i].dev = omap_device_get_by_hwmod_name(am33xx_mod[i].oh_name);
> +
> +       gfx_pwrdm = pwrdm_lookup("gfx_pwrdm");
> +       per_pwrdm = pwrdm_lookup("per_pwrdm");
> +       mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
> +
> +       gfx_l4ls_clkdm = clkdm_lookup("gfx_l4ls_gfx_clkdm");
> +
> +       if ((!gfx_pwrdm) || (!per_pwrdm) || (!mpu_pwrdm) || (!gfx_l4ls_clkdm)) {
> +               ret = -ENODEV;
> +               goto err;
> +       }
> +
> +       am33xx_pm = kzalloc(sizeof(*am33xx_pm), GFP_KERNEL);
> +       if (!am33xx_pm) {
> +               pr_err("Memory allocation failed\n");
> +               ret = -ENOMEM;
> +               goto err;
> +       }
> +
> +       ret = am33xx_map_emif();
> +       if (ret) {
> +               pr_err("PM: Could not ioremap EMIF\n");
> +               goto err;
> +       }
> +       /* Determine Memory Type */
> +       temp = readl(am33xx_emif_base + EMIF_SDRAM_CONFIG);
> +       temp = (temp & SDRAM_TYPE_MASK) >> SDRAM_TYPE_SHIFT;
> +       /* Parameters to pass to aseembly code */
> +       susp_params.emif_addr_virt = am33xx_emif_base;
> +       susp_params.dram_sync = am33xx_dram_sync;
> +       susp_params.mem_type = temp;
> +       am33xx_pm->ipc.param3 = temp;
> +
> +       np = of_find_compatible_node(NULL, NULL, "ti,am3353-wkup-m3");
> +       if (np) {
> +               if (of_find_property(np, "ti,needs_vtt_toggle", NULL) &&
> +                   (!(of_property_read_u32(np, "vtt-gpio-pin",
> +                                                       &temp)))) {
> +                       if (temp >= 0 && temp <= 31)
> +                               am33xx_pm->ipc.param3 |=
> +                                       ((1 << VTT_STAT_SHIFT) |
> +                                       (temp << VTT_GPIO_PIN_SHIFT));
> +               }
> +       }
> +
> +       (void) clkdm_for_each(omap_pm_clkdms_setup, NULL);
> +
> +       /* CEFUSE domain can be turned off post bootup */
> +       cefuse_pwrdm = pwrdm_lookup("cefuse_pwrdm");
> +       if (cefuse_pwrdm)
> +               omap_set_pwrdm_state(cefuse_pwrdm, PWRDM_POWER_OFF);
> +       else
> +               pr_err("PM: Failed to get cefuse_pwrdm\n");
> +
> +#ifdef CONFIG_SUSPEND
> +       pr_info("PM: Trying to load am335x-pm-firmware.bin");
> +
> +       /* We don't want to delay boot */
> +       request_firmware_nowait(THIS_MODULE, 0, "am335x-pm-firmware.bin",
> +                               NULL, GFP_KERNEL, am33xx_pm,
> +                               am33xx_pm_firmware_cb);
> +#endif /* CONFIG_SUSPEND */
> +
> +err:
> +       return ret;
> +}
> diff --git a/arch/arm/mach-omap2/pm33xx.h b/arch/arm/mach-omap2/pm33xx.h
> new file mode 100644
> index 0000000..befdd11
> --- /dev/null
> +++ b/arch/arm/mach-omap2/pm33xx.h
> @@ -0,0 +1,77 @@
> +/*
> + * AM33XX Power Management Routines
> + *
> + * Copyright (C) 2012 Texas Instruments Inc.
> + * Vaibhav Bedia <vaibhav.bedia@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.
> + */
> +#ifndef __ARCH_ARM_MACH_OMAP2_PM33XX_H
> +#define __ARCH_ARM_MACH_OMAP2_PM33XX_H
> +
> +#include "control.h"
> +
> +#ifndef __ASSEMBLER__
> +
> +struct am33xx_pm_context {
> +       struct am33xx_ipc_data  ipc;
> +       struct firmware         *firmware;
> +       struct omap_mbox        *mbox;
> +       u8                      state;
> +       u32                     ver;
> +};
> +
> +/*
> + * Params passed to suspend routine
> + *
> + * Since these are used to load into registers by suspend code,
> + * entries here must always be in sync with the suspend code
> + * in arm/mach-omap2/sleep33xx.S
> + */
> +struct am33xx_suspend_params {
> +       void __iomem *emif_addr_virt;
> +       u32 mem_type;
> +       void __iomem *dram_sync;
> +};
> +
> +struct wakeup_src {
> +       int irq_nr;
> +       char src[10];
> +};
> +
> +struct forced_standby_module {
> +       char oh_name[15];
> +       struct device *dev;
> +};
> +
> +int wkup_m3_copy_code(const u8 *data, size_t size);
> +int wkup_m3_prepare(void);
> +void wkup_m3_register_txev_handler(void (*txev_handler)(void));
> +
> +#endif
> +
> +#define        IPC_CMD_DS0                     0x3
> +#define IPC_CMD_RESET                   0xe
> +#define DS_IPC_DEFAULT                 0xffffffff
> +#define M3_VERSION_UNKNOWN             0x0000ffff
> +#define M3_BASELINE_VERSION            0x21
> +
> +#define M3_STATE_UNKNOWN               0
> +#define M3_STATE_RESET                 1
> +#define M3_STATE_INITED                        2
> +#define M3_STATE_MSG_FOR_LP            3
> +#define M3_STATE_MSG_FOR_RESET         4
> +
> +#define AM33XX_OCMC_END                        0x40310000
> +#define AM33XX_EMIF_BASE               0x4C000000
> +
> +#define MEM_TYPE_DDR2          2
> +
> +#endif
> diff --git a/arch/arm/mach-omap2/wkup_m3.c b/arch/arm/mach-omap2/wkup_m3.c
> new file mode 100644
> index 0000000..8eaa7f3
> --- /dev/null
> +++ b/arch/arm/mach-omap2/wkup_m3.c
> @@ -0,0 +1,183 @@
> +/*
> + * AM33XX Power Management Routines
> + *
> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
> + * Vaibhav Bedia <vaibhav.bedia@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/kernel.h>
> +#include <linux/init.h>
> +#include <linux/slab.h>
> +#include <linux/cpu.h>
> +#include <linux/err.h>
> +#include <linux/firmware.h>
> +#include <linux/io.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/of.h>
> +
> +#include "pm33xx.h"
> +#include "control.h"
> +#include "omap_device.h"
> +#include "soc.h"
> +
> +struct wkup_m3_context {
> +       struct device   *dev;
> +       void __iomem    *code;
> +       void (*txev_handler)(void);
> +};
> +
> +struct wkup_m3_context *wkup_m3;
> +
> +int wkup_m3_copy_code(const u8 *data, size_t size)
> +{
> +       if (size > SZ_16K)
> +               return -ENOMEM;
> +
> +       memcpy_toio(wkup_m3->code, data, size);
> +
> +       return 0;
> +}
> +
> +
> +void wkup_m3_register_txev_handler(void (*txev_handler)(void))
> +{
> +       wkup_m3->txev_handler = txev_handler;
> +}
> +
> +/* have platforms do what they want in atomic context over here? */
> +static irqreturn_t wkup_m3_txev_handler(int irq, void *unused)
> +{
> +       am33xx_txev_eoi();
> +
> +       /* callback to be executed in atomic context */
> +       /* return 0 implies IRQ_HANDLED else IRQ_NONE */
> +       wkup_m3->txev_handler();
> +
> +       am33xx_txev_enable();
> +
> +       return IRQ_HANDLED;
> +}
> +
> +int wkup_m3_prepare(void)
> +{
> +       struct platform_device *pdev = to_platform_device(wkup_m3->dev);
> +
> +       /* check that the code is loaded */
> +       omap_device_deassert_hardreset(pdev, "wkup_m3");
> +
> +       return 0;
> +}
> +
> +static int wkup_m3_probe(struct platform_device *pdev)
> +{
> +       int irq, ret = 0;
> +       struct resource *mem;
> +
> +       pm_runtime_enable(&pdev->dev);
> +
> +       ret = pm_runtime_get_sync(&pdev->dev);
> +       if (IS_ERR_VALUE(ret)) {
> +               dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
> +               return ret;
> +       }
> +
> +       irq = platform_get_irq(pdev, 0);
> +       if (!irq) {
> +               dev_err(wkup_m3->dev, "no irq resource\n");

&pdev->dev

> +               ret = -ENXIO;
> +               goto err;
> +       }
> +
> +       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       if (!mem) {
> +               dev_err(wkup_m3->dev, "no memory resource\n");

&pdev->dev

> +               ret = -ENXIO;
> +               goto err;
> +       }
> +
> +       wkup_m3 = kzalloc(sizeof(*wkup_m3), GFP_KERNEL);
> +       if (!wkup_m3) {
> +               pr_err("Memory allocation failed\n");
> +               ret = -ENOMEM;
> +               goto err;
> +       }
> +
> +       wkup_m3->dev = &pdev->dev;
> +
> +       wkup_m3->code = devm_request_and_ioremap(wkup_m3->dev, mem);
> +       if (!wkup_m3->code) {
> +               dev_err(wkup_m3->dev, "could not ioremap\n");
> +               ret = -EADDRNOTAVAIL;
> +               goto err;
> +       }
> +
> +       ret = devm_request_irq(wkup_m3->dev, irq, wkup_m3_txev_handler,
> +                 IRQF_DISABLED, "wkup_m3_txev", NULL);
> +       if (ret) {
> +               dev_err(wkup_m3->dev, "request_irq failed\n");
> +               goto err;
> +       }
> +
> +err:
> +       return ret;
> +}
> +
> +static int wkup_m3_remove(struct platform_device *pdev)
> +{
> +       return 0;
> +}
> +
> +static struct of_device_id wkup_m3_dt_ids[] = {
> +       { .compatible = "ti,am3353-wkup-m3" },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(of, wkup_m3_dt_ids);
> +
> +static int wkup_m3_rpm_suspend(struct device *dev)
> +{
> +       return -EBUSY;
> +}
> +
> +static int wkup_m3_rpm_resume(struct device *dev)
> +{
> +       return 0;
> +}
> +
> +static const struct dev_pm_ops wkup_m3_ops = {
> +       SET_RUNTIME_PM_OPS(wkup_m3_rpm_suspend, wkup_m3_rpm_resume, NULL)
> +};
> +
> +static struct platform_driver wkup_m3_driver = {
> +       .probe          = wkup_m3_probe,
> +       .remove         = wkup_m3_remove,
> +       .driver         = {
> +               .name   = "wkup_m3",
> +               .owner  = THIS_MODULE,
> +               .of_match_table = of_match_ptr(wkup_m3_dt_ids),
> +               .pm     = &wkup_m3_ops,
> +       },
> +};
> +
> +static __init int wkup_m3_init(void)
> +{
> +       return platform_driver_register(&wkup_m3_driver);
> +}
> +
> +static __exit void wkup_m3_exit(void)
> +{
> +       platform_driver_unregister(&wkup_m3_driver);
> +}
> +omap_postcore_initcall(wkup_m3_init);
> +module_exit(wkup_m3_exit);
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-13  7:43     ` Russ Dill
  0 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-13  7:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> AM335x supports various low power modes as documented
> in section 8.1.4.3 of the AM335x TRM which is available
> @ http://www.ti.com/litv/pdf/spruh73f
>
> DeepSleep0 mode offers the lowest power mode with limited
> wakeup sources without a system reboot and is mapped as
> the suspend state in the kernel. In this state, MPU and
> PER domains are turned off with the internal RAM held in
> retention to facilitate resume process. As part of the boot
> process, the assembly code is copied over to OCMCRAM using
> the OMAP SRAM code.
>
> AM335x has a Cortex-M3 (WKUP_M3) which assists the MPU
> in DeepSleep0 entry and exit. WKUP_M3 takes care of the
> clockdomain and powerdomain transitions based on the
> intended low power state. MPU needs to load the appropriate
> WKUP_M3 binary onto the WKUP_M3 memory space before it can
> leverage any of the PM features like DeepSleep.
>
> The IPC mechanism between MPU and WKUP_M3 uses a mailbox
> sub-module and 8 IPC registers in the Control module. MPU
> uses the assigned Mailbox for issuing an interrupt to
> WKUP_M3 which then goes and checks the IPC registers for
> the payload. WKUP_M3 has the ability to trigger on interrupt
> to MPU by executing the "sev" instruction.
>
> In the current implementation when the suspend process
> is initiated MPU interrupts the WKUP_M3 to let it know about
> the intent of entering DeepSleep0 and waits for an ACK. When
> the ACK is received MPU continues with its suspend process
> to suspend all the drivers and then jumps to assembly in
> OCMC RAM. The assembly code puts the PLLs in bypass, puts the
> external RAM in self-refresh mode and then finally execute the
> WFI instruction. Execution of the WFI instruction triggers another
> interrupt to the WKUP_M3 which then continues wiht the power down
> sequence wherein the clockdomain and powerdomain transition takes
> place. As part of the sleep sequence, WKUP_M3 unmasks the interrupt
> lines for the wakeup sources. WFI execution on WKUP_M3 causes the
> hardware to disable the main oscillator of the SoC.
>
> When a wakeup event occurs, WKUP_M3 starts the power-up
> sequence by switching on the power domains and finally
> enabling the clock to MPU. Since the MPU gets powered down
> as part of the sleep sequence in the resume path ROM code
> starts executing. The ROM code detects a wakeup from sleep
> and then jumps to the resume location in OCMC which was
> populated in one of the IPC registers as part of the suspend
> sequence.
>
> The low level code in OCMC relocks the PLLs, enables access
> to external RAM and then jumps to the cpu_resume code of
> the kernel to finish the resume process.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> Cc: Tony Lingren <tony@atomide.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Benoit Cousson <benoit.cousson@linaro.org>
> Cc: Paul Walmsley <paul@pwsan.com>
> Cc: Kevin Hilman <khilman@linaro.org>
> ---
>  arch/arm/mach-omap2/pm33xx.c  |  474 +++++++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/pm33xx.h  |   77 +++++++
>  arch/arm/mach-omap2/wkup_m3.c |  183 ++++++++++++++++
>  3 files changed, 734 insertions(+)
>  create mode 100644 arch/arm/mach-omap2/pm33xx.c
>  create mode 100644 arch/arm/mach-omap2/pm33xx.h
>  create mode 100644 arch/arm/mach-omap2/wkup_m3.c
>
> diff --git a/arch/arm/mach-omap2/pm33xx.c b/arch/arm/mach-omap2/pm33xx.c
> new file mode 100644
> index 0000000..d291c76
> --- /dev/null
> +++ b/arch/arm/mach-omap2/pm33xx.c
> @@ -0,0 +1,474 @@
> +/*
> + * AM33XX Power Management Routines
> + *
> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
> + * Vaibhav Bedia <vaibhav.bedia@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/kernel.h>
> +#include <linux/init.h>
> +#include <linux/cpu.h>
> +#include <linux/err.h>
> +#include <linux/firmware.h>
> +#include <linux/io.h>
> +#include <linux/platform_device.h>
> +#include <linux/sched.h>
> +#include <linux/suspend.h>
> +#include <linux/completion.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/ti_emif.h>
> +#include <linux/omap-mailbox.h>
> +
> +#include <asm/suspend.h>
> +#include <asm/proc-fns.h>
> +#include <asm/sizes.h>
> +#include <asm/fncpy.h>
> +#include <asm/system_misc.h>
> +
> +#include "pm.h"
> +#include "cm33xx.h"
> +#include "pm33xx.h"
> +#include "control.h"
> +#include "common.h"
> +#include "clockdomain.h"
> +#include "powerdomain.h"
> +#include "omap_hwmod.h"
> +#include "omap_device.h"
> +#include "soc.h"
> +#include "sram.h"
> +
> +static void __iomem *am33xx_emif_base;
> +static struct powerdomain *cefuse_pwrdm, *gfx_pwrdm, *per_pwrdm, *mpu_pwrdm;
> +static struct clockdomain *gfx_l4ls_clkdm;
> +
> +struct wakeup_src wakeups[] = {
> +       {.irq_nr = 35,  .src = "USB0_PHY"},
> +       {.irq_nr = 36,  .src = "USB1_PHY"},
> +       {.irq_nr = 40,  .src = "I2C0"},
> +       {.irq_nr = 41,  .src = "RTC Timer"},
> +       {.irq_nr = 42,  .src = "RTC Alarm"},
> +       {.irq_nr = 43,  .src = "Timer0"},
> +       {.irq_nr = 44,  .src = "Timer1"},
> +       {.irq_nr = 45,  .src = "UART"},
> +       {.irq_nr = 46,  .src = "GPIO0"},
> +       {.irq_nr = 48,  .src = "MPU_WAKE"},
> +       {.irq_nr = 49,  .src = "WDT0"},
> +       {.irq_nr = 50,  .src = "WDT1"},
> +       {.irq_nr = 51,  .src = "ADC_TSC"},
> +};
> +
> +struct forced_standby_module am33xx_mod[] = {
> +       {.oh_name = "usb_otg_hs"},
> +       {.oh_name = "tptc0"},
> +       {.oh_name = "tptc1"},
> +       {.oh_name = "tptc2"},
> +       {.oh_name = "cpgmac0"},
> +};
> +
> +static struct am33xx_pm_context *am33xx_pm;
> +
> +static DECLARE_COMPLETION(am33xx_pm_sync);
> +
> +static void (*am33xx_do_wfi_sram)(struct am33xx_suspend_params *);
> +
> +static struct am33xx_suspend_params susp_params;
> +
> +#ifdef CONFIG_SUSPEND
> +
> +static int am33xx_do_sram_idle(long unsigned int unused)
> +{
> +       am33xx_do_wfi_sram(&susp_params);
> +       return 0;
> +}
> +
> +static int am33xx_pm_suspend(void)
> +{
> +       int i, j, ret = 0;
> +
> +       int status = 0;
> +       struct platform_device *pdev;
> +       struct omap_device *od;
> +
> +       /*
> +        * By default the following IPs do not have MSTANDBY asserted
> +        * which is necessary for PER domain transition. If the drivers
> +        * are not compiled into the kernel HWMOD code will not change the
> +        * state of the IPs if the IP was not never enabled. To ensure
> +        * that there no issues with or without the drivers being compiled
> +        * in the kernel, we forcefully put these IPs to idle.
> +        */
> +       for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++) {
> +               pdev = to_platform_device(am33xx_mod[i].dev);
> +               od = to_omap_device(pdev);
> +               if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
> +                       omap_device_enable_hwmods(od);
> +                       omap_device_idle_hwmods(od);
> +               }
> +       }
> +
> +       /* Try to put GFX to sleep */
> +       omap_set_pwrdm_state(gfx_pwrdm, PWRDM_POWER_OFF);
> +       ret = cpu_suspend(0, am33xx_do_sram_idle);
> +
> +       status = pwrdm_read_prev_pwrst(gfx_pwrdm);
> +       if (status != PWRDM_POWER_OFF)
> +               pr_err("PM: GFX domain did not transition\n");
> +       else
> +               pr_info("PM: GFX domain entered low power state\n");
> +
> +       /*
> +        * BUG: GFX_L4LS clock domain needs to be woken up to
> +        * ensure thet L4LS clock domain does not get stuck in transition
> +        * If that happens L3 module does not get disabled, thereby leading
> +        * to PER power domain transition failing
> +        */
> +       clkdm_wakeup(gfx_l4ls_clkdm);
> +       clkdm_sleep(gfx_l4ls_clkdm);
> +
> +       if (ret) {
> +               pr_err("PM: Kernel suspend failure\n");
> +       } else {
> +               i = am33xx_pm_status();
> +               switch (i) {
> +               case 0:
> +                       pr_info("PM: Successfully put all powerdomains to target state\n");
> +
> +                       /*
> +                        * The PRCM registers on AM335x do not contain previous state
> +                        * information like those present on OMAP4 so we must manually
> +                        * indicate transition so state counters are properly incremented
> +                        */
> +                       pwrdm_post_transition(mpu_pwrdm);
> +                       pwrdm_post_transition(per_pwrdm);
> +                       break;
> +               case 1:
> +                       pr_err("PM: Could not transition all powerdomains to target state\n");
> +                       ret = -1;
> +                       break;
> +               default:
> +                       pr_err("PM: CM3 returned unknown result :(\nStatus = %d\n", i);
> +                       ret = -1;
> +               }
> +
> +               /* print the wakeup reason */
> +               i = am33xx_pm_wake_src();
> +               for (j = 0; j < ARRAY_SIZE(wakeups); j++) {
> +                       if (wakeups[j].irq_nr == i) {
> +                               pr_info("PM: Wakeup source %s\n", wakeups[j].src);
> +                               break;
> +                       }
> +               }
> +
> +               if (j == ARRAY_SIZE(wakeups))
> +                       pr_info("PM: Unknown wakeup source %d!\n", i);
> +       }
> +
> +       return ret;
> +}
> +
> +static int am33xx_pm_enter(suspend_state_t suspend_state)
> +{
> +       int ret = 0;
> +
> +       switch (suspend_state) {
> +       case PM_SUSPEND_STANDBY:
> +       case PM_SUSPEND_MEM:
> +               ret = am33xx_pm_suspend();
> +               break;
> +       default:
> +               ret = -EINVAL;
> +       }
> +
> +       return ret;
> +}
> +
> +/* returns the error code from msg_send - 0 for success, failure otherwise */
> +static int am33xx_ping_wkup_m3(void)
> +{
> +       int ret = 0;
> +
> +       /*
> +        * Write a dummy message to the mailbox in order to trigger the RX
> +        * interrupt to alert the M3 that data is available in the IPC
> +        * registers.
> +        */
> +       ret = omap_mbox_msg_send(am33xx_pm->mbox, 0xABCDABCD);
> +
> +       return ret;
> +}
> +
> +static void am33xx_m3_state_machine_reset(void)
> +{
> +       int i;
> +
> +       am33xx_pm->ipc.sleep_mode = IPC_CMD_RESET;
> +
> +       am33xx_pm_ipc_cmd(&am33xx_pm->ipc);
> +
> +       am33xx_pm->state = M3_STATE_MSG_FOR_RESET;
> +
> +       pr_info("PM: Sending message for resetting M3 state machine\n");
> +
> +       if (!am33xx_ping_wkup_m3()) {
> +               i = wait_for_completion_timeout(&am33xx_pm_sync,
> +                                       msecs_to_jiffies(500));
> +               if (WARN(i == 0, "PM: MPU<->CM3 sync failure\n"))
> +                       am33xx_pm->state = M3_STATE_UNKNOWN;
> +       } else {
> +               pr_warn("PM: Unable to ping CM3\n");
> +       }
> +}
> +
> +static int am33xx_pm_begin(suspend_state_t state)
> +{
> +       int i;
> +
> +       cpu_idle_poll_ctrl(true);
> +
> +       am33xx_pm->ipc.sleep_mode       = IPC_CMD_DS0;
> +       am33xx_pm->ipc.param1           = DS_IPC_DEFAULT;
> +       am33xx_pm->ipc.param2           = DS_IPC_DEFAULT;
> +
> +       am33xx_pm_ipc_cmd(&am33xx_pm->ipc);
> +
> +       am33xx_pm->state = M3_STATE_MSG_FOR_LP;
> +
> +       pr_info("PM: Sending message for entering DeepSleep mode\n");
> +
> +       if (!am33xx_ping_wkup_m3()) {
> +               i = wait_for_completion_timeout(&am33xx_pm_sync,
> +                                       msecs_to_jiffies(500));
> +               if (WARN(i == 0, "PM: MPU<->CM3 sync failure\n"))
> +                       return -1;
> +       } else {
> +               pr_warn("PM: Unable to ping CM3\n");
> +       }
> +
> +       return 0;
> +}
> +
> +static void am33xx_pm_end(void)
> +{
> +       am33xx_m3_state_machine_reset();
> +
> +       cpu_idle_poll_ctrl(false);
> +
> +       return;
> +}
> +
> +static struct platform_suspend_ops am33xx_pm_ops = {
> +       .begin          = am33xx_pm_begin,
> +       .end            = am33xx_pm_end,
> +       .enter          = am33xx_pm_enter,
> +};
> +
> +/*
> + * Dummy notifier for the mailbox
> + */
> +
> +static int wkup_mbox_msg(struct notifier_block *self, unsigned long len,
> +               void *msg)
> +{
> +       return 0;
> +}
> +
> +static struct notifier_block wkup_mbox_notifier = {
> +       .notifier_call = wkup_mbox_msg,
> +};
> +
> +void am33xx_txev_handler(void)
> +{
> +       switch (am33xx_pm->state) {
> +       case M3_STATE_RESET:
> +               am33xx_pm->state = M3_STATE_INITED;
> +               am33xx_pm->ver = am33xx_pm_version_get();
> +               if (am33xx_pm->ver == M3_VERSION_UNKNOWN ||
> +                       am33xx_pm->ver < M3_BASELINE_VERSION) {
> +                       pr_warn("PM: CM3 Firmware Version %x not supported\n",
> +                                               am33xx_pm->ver);
> +               } else {
> +                       pr_info("PM: CM3 Firmware Version = 0x%x\n",
> +                                               am33xx_pm->ver);
> +                       am33xx_pm_ops.valid = suspend_valid_only_mem;
> +               }
> +               break;
> +       case M3_STATE_MSG_FOR_RESET:
> +               am33xx_pm->state = M3_STATE_INITED;
> +               complete(&am33xx_pm_sync);
> +               break;
> +       case M3_STATE_MSG_FOR_LP:
> +               complete(&am33xx_pm_sync);
> +               break;
> +       case M3_STATE_UNKNOWN:
> +               pr_warn("PM: Unknown CM3 State\n");
> +       }
> +
> +       return;
> +}
> +
> +static void am33xx_pm_firmware_cb(const struct firmware *fw, void *context)
> +{
> +       struct am33xx_pm_context *am33xx_pm = context;
> +       int ret = 0;
> +
> +       /* no firmware found */
> +       if (!fw) {
> +               pr_err("PM: request_firmware failed\n");
> +               return;
> +       }
> +
> +       wkup_m3_copy_code(fw->data, fw->size);
> +
> +       wkup_m3_register_txev_handler(am33xx_txev_handler);
> +
> +       pr_info("PM: Copied the M3 firmware to UMEM\n");
> +
> +       /*
> +        * Invalidate M3 firmware version before hardreset.
> +        * Write invalid version in lower 4 nibbles of parameter
> +        * register (ipc_regs + 0x8).
> +        */
> +       am33xx_pm_version_clear();
> +
> +       am33xx_pm->state = M3_STATE_RESET;
> +
> +       ret = wkup_m3_prepare();
> +       if (ret) {
> +               pr_err("PM: Could not prepare WKUP_M3\n");
> +               return;
> +       }
> +
> +       /* Physical resume address to be used by ROM code */
> +       am33xx_pm->ipc.resume_addr = (AM33XX_OCMC_END -
> +               am33xx_do_wfi_sz + am33xx_resume_offset + 0x4);
> +
> +       am33xx_pm->mbox = omap_mbox_get("wkup_m3", &wkup_mbox_notifier);
> +
> +       if (IS_ERR(am33xx_pm->mbox)) {
> +               ret = -EBUSY;
> +               pr_err("PM: IPC Request for A8->M3 Channel failed!\n");
> +               return;
> +       } else {
> +               suspend_set_ops(&am33xx_pm_ops);
> +       }
> +
> +       return;
> +}
> +
> +#endif /* CONFIG_SUSPEND */
> +
> +/*
> + * Push the minimal suspend-resume code to SRAM
> + */
> +void am33xx_push_sram_idle(void)
> +{
> +       am33xx_do_wfi_sram = (void *)omap_sram_push
> +                                       (am33xx_do_wfi, am33xx_do_wfi_sz);
> +}
> +
> +static int __init am33xx_map_emif(void)
> +{
> +       am33xx_emif_base = ioremap(AM33XX_EMIF_BASE, SZ_32K);
> +
> +       if (!am33xx_emif_base)
> +               return -ENOMEM;
> +
> +       return 0;
> +}
> +
> +int __init am33xx_pm_init(void)
> +{
> +       int ret;
> +       u32 temp;
> +       struct device_node *np;
> +       int i;
> +
> +       if (!soc_is_am33xx())
> +               return -ENODEV;
> +
> +       pr_info("Power Management for AM33XX family\n");
> +
> +       /*
> +        * By default the following IPs do not have MSTANDBY asserted
> +        * which is necessary for PER domain transition. If the drivers
> +        * are not compiled into the kernel HWMOD code will not change the
> +        * state of the IPs if the IP was not never enabled
> +        */
> +       for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++)
> +               am33xx_mod[i].dev = omap_device_get_by_hwmod_name(am33xx_mod[i].oh_name);
> +
> +       gfx_pwrdm = pwrdm_lookup("gfx_pwrdm");
> +       per_pwrdm = pwrdm_lookup("per_pwrdm");
> +       mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
> +
> +       gfx_l4ls_clkdm = clkdm_lookup("gfx_l4ls_gfx_clkdm");
> +
> +       if ((!gfx_pwrdm) || (!per_pwrdm) || (!mpu_pwrdm) || (!gfx_l4ls_clkdm)) {
> +               ret = -ENODEV;
> +               goto err;
> +       }
> +
> +       am33xx_pm = kzalloc(sizeof(*am33xx_pm), GFP_KERNEL);
> +       if (!am33xx_pm) {
> +               pr_err("Memory allocation failed\n");
> +               ret = -ENOMEM;
> +               goto err;
> +       }
> +
> +       ret = am33xx_map_emif();
> +       if (ret) {
> +               pr_err("PM: Could not ioremap EMIF\n");
> +               goto err;
> +       }
> +       /* Determine Memory Type */
> +       temp = readl(am33xx_emif_base + EMIF_SDRAM_CONFIG);
> +       temp = (temp & SDRAM_TYPE_MASK) >> SDRAM_TYPE_SHIFT;
> +       /* Parameters to pass to aseembly code */
> +       susp_params.emif_addr_virt = am33xx_emif_base;
> +       susp_params.dram_sync = am33xx_dram_sync;
> +       susp_params.mem_type = temp;
> +       am33xx_pm->ipc.param3 = temp;
> +
> +       np = of_find_compatible_node(NULL, NULL, "ti,am3353-wkup-m3");
> +       if (np) {
> +               if (of_find_property(np, "ti,needs_vtt_toggle", NULL) &&
> +                   (!(of_property_read_u32(np, "vtt-gpio-pin",
> +                                                       &temp)))) {
> +                       if (temp >= 0 && temp <= 31)
> +                               am33xx_pm->ipc.param3 |=
> +                                       ((1 << VTT_STAT_SHIFT) |
> +                                       (temp << VTT_GPIO_PIN_SHIFT));
> +               }
> +       }
> +
> +       (void) clkdm_for_each(omap_pm_clkdms_setup, NULL);
> +
> +       /* CEFUSE domain can be turned off post bootup */
> +       cefuse_pwrdm = pwrdm_lookup("cefuse_pwrdm");
> +       if (cefuse_pwrdm)
> +               omap_set_pwrdm_state(cefuse_pwrdm, PWRDM_POWER_OFF);
> +       else
> +               pr_err("PM: Failed to get cefuse_pwrdm\n");
> +
> +#ifdef CONFIG_SUSPEND
> +       pr_info("PM: Trying to load am335x-pm-firmware.bin");
> +
> +       /* We don't want to delay boot */
> +       request_firmware_nowait(THIS_MODULE, 0, "am335x-pm-firmware.bin",
> +                               NULL, GFP_KERNEL, am33xx_pm,
> +                               am33xx_pm_firmware_cb);
> +#endif /* CONFIG_SUSPEND */
> +
> +err:
> +       return ret;
> +}
> diff --git a/arch/arm/mach-omap2/pm33xx.h b/arch/arm/mach-omap2/pm33xx.h
> new file mode 100644
> index 0000000..befdd11
> --- /dev/null
> +++ b/arch/arm/mach-omap2/pm33xx.h
> @@ -0,0 +1,77 @@
> +/*
> + * AM33XX Power Management Routines
> + *
> + * Copyright (C) 2012 Texas Instruments Inc.
> + * Vaibhav Bedia <vaibhav.bedia@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.
> + */
> +#ifndef __ARCH_ARM_MACH_OMAP2_PM33XX_H
> +#define __ARCH_ARM_MACH_OMAP2_PM33XX_H
> +
> +#include "control.h"
> +
> +#ifndef __ASSEMBLER__
> +
> +struct am33xx_pm_context {
> +       struct am33xx_ipc_data  ipc;
> +       struct firmware         *firmware;
> +       struct omap_mbox        *mbox;
> +       u8                      state;
> +       u32                     ver;
> +};
> +
> +/*
> + * Params passed to suspend routine
> + *
> + * Since these are used to load into registers by suspend code,
> + * entries here must always be in sync with the suspend code
> + * in arm/mach-omap2/sleep33xx.S
> + */
> +struct am33xx_suspend_params {
> +       void __iomem *emif_addr_virt;
> +       u32 mem_type;
> +       void __iomem *dram_sync;
> +};
> +
> +struct wakeup_src {
> +       int irq_nr;
> +       char src[10];
> +};
> +
> +struct forced_standby_module {
> +       char oh_name[15];
> +       struct device *dev;
> +};
> +
> +int wkup_m3_copy_code(const u8 *data, size_t size);
> +int wkup_m3_prepare(void);
> +void wkup_m3_register_txev_handler(void (*txev_handler)(void));
> +
> +#endif
> +
> +#define        IPC_CMD_DS0                     0x3
> +#define IPC_CMD_RESET                   0xe
> +#define DS_IPC_DEFAULT                 0xffffffff
> +#define M3_VERSION_UNKNOWN             0x0000ffff
> +#define M3_BASELINE_VERSION            0x21
> +
> +#define M3_STATE_UNKNOWN               0
> +#define M3_STATE_RESET                 1
> +#define M3_STATE_INITED                        2
> +#define M3_STATE_MSG_FOR_LP            3
> +#define M3_STATE_MSG_FOR_RESET         4
> +
> +#define AM33XX_OCMC_END                        0x40310000
> +#define AM33XX_EMIF_BASE               0x4C000000
> +
> +#define MEM_TYPE_DDR2          2
> +
> +#endif
> diff --git a/arch/arm/mach-omap2/wkup_m3.c b/arch/arm/mach-omap2/wkup_m3.c
> new file mode 100644
> index 0000000..8eaa7f3
> --- /dev/null
> +++ b/arch/arm/mach-omap2/wkup_m3.c
> @@ -0,0 +1,183 @@
> +/*
> + * AM33XX Power Management Routines
> + *
> + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
> + * Vaibhav Bedia <vaibhav.bedia@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/kernel.h>
> +#include <linux/init.h>
> +#include <linux/slab.h>
> +#include <linux/cpu.h>
> +#include <linux/err.h>
> +#include <linux/firmware.h>
> +#include <linux/io.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/of.h>
> +
> +#include "pm33xx.h"
> +#include "control.h"
> +#include "omap_device.h"
> +#include "soc.h"
> +
> +struct wkup_m3_context {
> +       struct device   *dev;
> +       void __iomem    *code;
> +       void (*txev_handler)(void);
> +};
> +
> +struct wkup_m3_context *wkup_m3;
> +
> +int wkup_m3_copy_code(const u8 *data, size_t size)
> +{
> +       if (size > SZ_16K)
> +               return -ENOMEM;
> +
> +       memcpy_toio(wkup_m3->code, data, size);
> +
> +       return 0;
> +}
> +
> +
> +void wkup_m3_register_txev_handler(void (*txev_handler)(void))
> +{
> +       wkup_m3->txev_handler = txev_handler;
> +}
> +
> +/* have platforms do what they want in atomic context over here? */
> +static irqreturn_t wkup_m3_txev_handler(int irq, void *unused)
> +{
> +       am33xx_txev_eoi();
> +
> +       /* callback to be executed in atomic context */
> +       /* return 0 implies IRQ_HANDLED else IRQ_NONE */
> +       wkup_m3->txev_handler();
> +
> +       am33xx_txev_enable();
> +
> +       return IRQ_HANDLED;
> +}
> +
> +int wkup_m3_prepare(void)
> +{
> +       struct platform_device *pdev = to_platform_device(wkup_m3->dev);
> +
> +       /* check that the code is loaded */
> +       omap_device_deassert_hardreset(pdev, "wkup_m3");
> +
> +       return 0;
> +}
> +
> +static int wkup_m3_probe(struct platform_device *pdev)
> +{
> +       int irq, ret = 0;
> +       struct resource *mem;
> +
> +       pm_runtime_enable(&pdev->dev);
> +
> +       ret = pm_runtime_get_sync(&pdev->dev);
> +       if (IS_ERR_VALUE(ret)) {
> +               dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
> +               return ret;
> +       }
> +
> +       irq = platform_get_irq(pdev, 0);
> +       if (!irq) {
> +               dev_err(wkup_m3->dev, "no irq resource\n");

&pdev->dev

> +               ret = -ENXIO;
> +               goto err;
> +       }
> +
> +       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       if (!mem) {
> +               dev_err(wkup_m3->dev, "no memory resource\n");

&pdev->dev

> +               ret = -ENXIO;
> +               goto err;
> +       }
> +
> +       wkup_m3 = kzalloc(sizeof(*wkup_m3), GFP_KERNEL);
> +       if (!wkup_m3) {
> +               pr_err("Memory allocation failed\n");
> +               ret = -ENOMEM;
> +               goto err;
> +       }
> +
> +       wkup_m3->dev = &pdev->dev;
> +
> +       wkup_m3->code = devm_request_and_ioremap(wkup_m3->dev, mem);
> +       if (!wkup_m3->code) {
> +               dev_err(wkup_m3->dev, "could not ioremap\n");
> +               ret = -EADDRNOTAVAIL;
> +               goto err;
> +       }
> +
> +       ret = devm_request_irq(wkup_m3->dev, irq, wkup_m3_txev_handler,
> +                 IRQF_DISABLED, "wkup_m3_txev", NULL);
> +       if (ret) {
> +               dev_err(wkup_m3->dev, "request_irq failed\n");
> +               goto err;
> +       }
> +
> +err:
> +       return ret;
> +}
> +
> +static int wkup_m3_remove(struct platform_device *pdev)
> +{
> +       return 0;
> +}
> +
> +static struct of_device_id wkup_m3_dt_ids[] = {
> +       { .compatible = "ti,am3353-wkup-m3" },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(of, wkup_m3_dt_ids);
> +
> +static int wkup_m3_rpm_suspend(struct device *dev)
> +{
> +       return -EBUSY;
> +}
> +
> +static int wkup_m3_rpm_resume(struct device *dev)
> +{
> +       return 0;
> +}
> +
> +static const struct dev_pm_ops wkup_m3_ops = {
> +       SET_RUNTIME_PM_OPS(wkup_m3_rpm_suspend, wkup_m3_rpm_resume, NULL)
> +};
> +
> +static struct platform_driver wkup_m3_driver = {
> +       .probe          = wkup_m3_probe,
> +       .remove         = wkup_m3_remove,
> +       .driver         = {
> +               .name   = "wkup_m3",
> +               .owner  = THIS_MODULE,
> +               .of_match_table = of_match_ptr(wkup_m3_dt_ids),
> +               .pm     = &wkup_m3_ops,
> +       },
> +};
> +
> +static __init int wkup_m3_init(void)
> +{
> +       return platform_driver_register(&wkup_m3_driver);
> +}
> +
> +static __exit void wkup_m3_exit(void)
> +{
> +       platform_driver_unregister(&wkup_m3_driver);
> +}
> +omap_postcore_initcall(wkup_m3_init);
> +module_exit(wkup_m3_exit);
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-08-12 18:59     ` Dave Gerlach
@ 2013-08-13 12:39       ` Daniel Mack
  -1 siblings, 0 replies; 212+ messages in thread
From: Daniel Mack @ 2013-08-13 12:39 UTC (permalink / raw)
  To: Dave Gerlach; +Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman

Hi Dave,

On 12.08.2013 20:59, Dave Gerlach wrote:
> On 08/11/2013 06:53 AM, Daniel Mack wrote:

>> The problem I currently face is that I can't make the board resume, as
>> neither UART0 nor GPIO0 seem to work as wakeup source.
> 
> Did you apply the other patches that are mentioned besides Suman's 
> series? The board will hang while suspending without these.

Yes. However, just to make sure you referenced the correct patches - on
top of yours an Suman's set, I have:

  [PATCH 1/2] ARM: OMAP2+: hwmod: rt address space index for DT
  [PATCH 2/2] ARM: OMAP2+: hwmod: AM335x: fix cpgmac address space
  [PATCH 1/2] ARM: dts: add AM33XX EDMA support

The last one seems somewhat unrelated though.

However, I see an issue with the musb dsps glue. With the usb controller
disabled in DT, I also had to remove the usb_otg_hs entry from
am33xx_mod[] (pm33xx.c). When the usb controller is _enabled_, I get an
instant NULL pointer exception due to a rather obvious bug. I'll send
out a patch right now.

When I send the board to suspend (with USB disabled), the power
consumption drops significantly, and the output is:

# echo mem > /sys/power/state
[   93.001937] PM: Syncing filesystems ... done.
[   93.033591] Freezing user space processes ... (elapsed 0.002 seconds)
done.
[   93.048532] Freezing remaining freezable tasks ... (elapsed 0.002
seconds) done.
[   93.059277] PM: Sending message for entering DeepSleep mode
[   93.085368] PM: suspend of devices complete after 15.070 msecs
[   93.096671] PM: late suspend of devices complete after 5.122 msecs
[   93.108853] PM: noirq suspend of devices complete after 5.647 msecs


... but traffic on UART0 won't cause a resume.


I'll dig a little deeper now, but if you have any idea, please let me know.


Thanks,
Daniel


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-08-13 12:39       ` Daniel Mack
  0 siblings, 0 replies; 212+ messages in thread
From: Daniel Mack @ 2013-08-13 12:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Dave,

On 12.08.2013 20:59, Dave Gerlach wrote:
> On 08/11/2013 06:53 AM, Daniel Mack wrote:

>> The problem I currently face is that I can't make the board resume, as
>> neither UART0 nor GPIO0 seem to work as wakeup source.
> 
> Did you apply the other patches that are mentioned besides Suman's 
> series? The board will hang while suspending without these.

Yes. However, just to make sure you referenced the correct patches - on
top of yours an Suman's set, I have:

  [PATCH 1/2] ARM: OMAP2+: hwmod: rt address space index for DT
  [PATCH 2/2] ARM: OMAP2+: hwmod: AM335x: fix cpgmac address space
  [PATCH 1/2] ARM: dts: add AM33XX EDMA support

The last one seems somewhat unrelated though.

However, I see an issue with the musb dsps glue. With the usb controller
disabled in DT, I also had to remove the usb_otg_hs entry from
am33xx_mod[] (pm33xx.c). When the usb controller is _enabled_, I get an
instant NULL pointer exception due to a rather obvious bug. I'll send
out a patch right now.

When I send the board to suspend (with USB disabled), the power
consumption drops significantly, and the output is:

# echo mem > /sys/power/state
[   93.001937] PM: Syncing filesystems ... done.
[   93.033591] Freezing user space processes ... (elapsed 0.002 seconds)
done.
[   93.048532] Freezing remaining freezable tasks ... (elapsed 0.002
seconds) done.
[   93.059277] PM: Sending message for entering DeepSleep mode
[   93.085368] PM: suspend of devices complete after 15.070 msecs
[   93.096671] PM: late suspend of devices complete after 5.122 msecs
[   93.108853] PM: noirq suspend of devices complete after 5.647 msecs


... but traffic on UART0 won't cause a resume.


I'll dig a little deeper now, but if you have any idea, please let me know.


Thanks,
Daniel

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-12 21:40               ` Dave Gerlach
@ 2013-08-13 14:29                 ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-13 14:29 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: Tony Lindgren, Santosh Shilimkar, linux-arm-kernel, linux-omap,
	Paul Walmsley, Vaibhav Bedia, Suman Anna

Dave Gerlach <d-gerlach@ti.com> writes:

> On 08/12/2013 02:17 PM, Kevin Hilman wrote:
>> Dave Gerlach <d-gerlach@ti.com> writes:
>>
>>> On 08/09/2013 12:11 AM, Tony Lindgren wrote:
>>>> * Dave Gerlach <d-gerlach@ti.com> [130808 09:23]:
>>>>> On 08/08/2013 08:44 AM, Santosh Shilimkar wrote:
>>>>>> Lets address the above better. I don't see a need of 8 functions
>>>>>> exported doing one or 2 register writes.
>>>>>>
>>>>>> Look M3 based handling is going to be there on future SOCs
>>>>>> as well and this kind of handling of IPC is very short cited.
>>>>>>
>>>>>
>>>>> The idea here was to move all control module register accesses into
>>>>> one file in planning of implementing a driver for the control module
>>>>> itself in the future.
>>>>>
>>>>>> Probably we should have a separate driver for M3 in linux which
>>>>>> can have all this local code instead of all these exports.
>>>>>
>>>>> The wkup_m3 code has been moved to a small driver found in patch 8
>>>>> of this series, would it better to move this code there rather than
>>>>> with the rest of the control module code?
>>>>
>>>> Please make everything you can into regular device drivers.
>>>>
>>>> We still have some dependencies to mach-omap2 code for PRCM
>>>> for example, but we're trying to get all that to live in
>>>> drivers.
>>>>
>>>> So for new pieces, let's not add further dependencies to
>>>> complicate moving things to drivers.
>>>>
>>>> Regards,
>>>>
>>>> Tony
>>>>
>>>
>>> Ok I will go ahead and pull the control module code that handles IPC
>>> into the wkup_m3 driver.
>>
>> Any control module register access still needs to stay in control.c.
>>
>>> The wkup_m3.c file is still present in mach-omap2 as the right
>>> location for it wasn't decided in the last RFC. Any thoughts on a good
>>> location for it?
>>
>> I raised this also in earlier reviews, but don't remember the if it was
>> answered...
>>
>> Why can't we handle the wkup_m3 using remoteproc/rpmsg instead of
>> creating another little driver that duplicates communication with the
>> M3.  Note also that the firmware load part would also be provided by
>> remoteproc/rpmsg.
>
> Looping Suman Anna who handled the IPC patches this patch set is based
> on top of...
>
> For the wkup_m3, the mailbox isn't used in a traditional manner. It's
> only used with a dummy write to trigger an interrupt from the A8 to
> the M3 and then communication happens in IPC registers within the
> control module. No messages are actually sent through the mailbox in
> either direction so that's why it was done this way rather than bring
> in full support for the mailbox.

I don't believe remoteproc/rpmsg forces you to use the mailbox for
communication, and can use other IPC mechanisms.  This still sounds
cleaner than reinventing remoteproc/rpmsg because of slight variations.

The linux way is to use and extend what is already there, and if it's
extended to the breaking point, then make a case for why something new
is needed.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-13 14:29                 ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-13 14:29 UTC (permalink / raw)
  To: linux-arm-kernel

Dave Gerlach <d-gerlach@ti.com> writes:

> On 08/12/2013 02:17 PM, Kevin Hilman wrote:
>> Dave Gerlach <d-gerlach@ti.com> writes:
>>
>>> On 08/09/2013 12:11 AM, Tony Lindgren wrote:
>>>> * Dave Gerlach <d-gerlach@ti.com> [130808 09:23]:
>>>>> On 08/08/2013 08:44 AM, Santosh Shilimkar wrote:
>>>>>> Lets address the above better. I don't see a need of 8 functions
>>>>>> exported doing one or 2 register writes.
>>>>>>
>>>>>> Look M3 based handling is going to be there on future SOCs
>>>>>> as well and this kind of handling of IPC is very short cited.
>>>>>>
>>>>>
>>>>> The idea here was to move all control module register accesses into
>>>>> one file in planning of implementing a driver for the control module
>>>>> itself in the future.
>>>>>
>>>>>> Probably we should have a separate driver for M3 in linux which
>>>>>> can have all this local code instead of all these exports.
>>>>>
>>>>> The wkup_m3 code has been moved to a small driver found in patch 8
>>>>> of this series, would it better to move this code there rather than
>>>>> with the rest of the control module code?
>>>>
>>>> Please make everything you can into regular device drivers.
>>>>
>>>> We still have some dependencies to mach-omap2 code for PRCM
>>>> for example, but we're trying to get all that to live in
>>>> drivers.
>>>>
>>>> So for new pieces, let's not add further dependencies to
>>>> complicate moving things to drivers.
>>>>
>>>> Regards,
>>>>
>>>> Tony
>>>>
>>>
>>> Ok I will go ahead and pull the control module code that handles IPC
>>> into the wkup_m3 driver.
>>
>> Any control module register access still needs to stay in control.c.
>>
>>> The wkup_m3.c file is still present in mach-omap2 as the right
>>> location for it wasn't decided in the last RFC. Any thoughts on a good
>>> location for it?
>>
>> I raised this also in earlier reviews, but don't remember the if it was
>> answered...
>>
>> Why can't we handle the wkup_m3 using remoteproc/rpmsg instead of
>> creating another little driver that duplicates communication with the
>> M3.  Note also that the firmware load part would also be provided by
>> remoteproc/rpmsg.
>
> Looping Suman Anna who handled the IPC patches this patch set is based
> on top of...
>
> For the wkup_m3, the mailbox isn't used in a traditional manner. It's
> only used with a dummy write to trigger an interrupt from the A8 to
> the M3 and then communication happens in IPC registers within the
> control module. No messages are actually sent through the mailbox in
> either direction so that's why it was done this way rather than bring
> in full support for the mailbox.

I don't believe remoteproc/rpmsg forces you to use the mailbox for
communication, and can use other IPC mechanisms.  This still sounds
cleaner than reinventing remoteproc/rpmsg because of slight variations.

The linux way is to use and extend what is already there, and if it's
extended to the breaking point, then make a case for why something new
is needed.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-13  7:43     ` Russ Dill
@ 2013-08-13 14:59       ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-13 14:59 UTC (permalink / raw)
  To: Russ Dill
  Cc: Dave Gerlach, linux-arm-kernel, linux-omap, Paul Walmsley,
	Vaibhav Bedia, Tony Lingren, Santosh Shilimkar, Benoit Cousson

Russ Dill <russ.dill@gmail.com> writes:

> On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:

[...]

>> +static int wkup_m3_probe(struct platform_device *pdev)
>> +{
>> +       int irq, ret = 0;
>> +       struct resource *mem;
>> +
>> +       pm_runtime_enable(&pdev->dev);
>> +
>> +       ret = pm_runtime_get_sync(&pdev->dev);
>> +       if (IS_ERR_VALUE(ret)) {
>> +               dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
>> +               return ret;
>> +       }
>> +
>> +       irq = platform_get_irq(pdev, 0);
>> +       if (!irq) {
>> +               dev_err(wkup_m3->dev, "no irq resource\n");
>
> &pdev->dev
>
>> +               ret = -ENXIO;
>> +               goto err;
>> +       }
>> +
>> +       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +       if (!mem) {
>> +               dev_err(wkup_m3->dev, "no memory resource\n");
>
> &pdev->dev

For future reference, when reviewing, please trim to only relevant
content/context, especially on large patches so maintainers/reviewers do
not have to find 2 one-line comments in a huge amount of irrelevant
context.

Thanks,

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-13 14:59       ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-13 14:59 UTC (permalink / raw)
  To: linux-arm-kernel

Russ Dill <russ.dill@gmail.com> writes:

> On Tue, Aug 6, 2013 at 10:49 AM, Dave Gerlach <d-gerlach@ti.com> wrote:

[...]

>> +static int wkup_m3_probe(struct platform_device *pdev)
>> +{
>> +       int irq, ret = 0;
>> +       struct resource *mem;
>> +
>> +       pm_runtime_enable(&pdev->dev);
>> +
>> +       ret = pm_runtime_get_sync(&pdev->dev);
>> +       if (IS_ERR_VALUE(ret)) {
>> +               dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
>> +               return ret;
>> +       }
>> +
>> +       irq = platform_get_irq(pdev, 0);
>> +       if (!irq) {
>> +               dev_err(wkup_m3->dev, "no irq resource\n");
>
> &pdev->dev
>
>> +               ret = -ENXIO;
>> +               goto err;
>> +       }
>> +
>> +       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +       if (!mem) {
>> +               dev_err(wkup_m3->dev, "no memory resource\n");
>
> &pdev->dev

For future reference, when reviewing, please trim to only relevant
content/context, especially on large patches so maintainers/reviewers do
not have to find 2 one-line comments in a huge amount of irrelevant
context.

Thanks,

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-13 14:29                 ` Kevin Hilman
@ 2013-08-13 15:08                   ` Santosh Shilimkar
  -1 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-13 15:08 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Dave Gerlach, Tony Lindgren, linux-arm-kernel, linux-omap,
	Paul Walmsley, Vaibhav Bedia, Suman Anna

On Tuesday 13 August 2013 10:29 AM, Kevin Hilman wrote:
> Dave Gerlach <d-gerlach@ti.com> writes:
> 
>> On 08/12/2013 02:17 PM, Kevin Hilman wrote:
>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>
>>>> On 08/09/2013 12:11 AM, Tony Lindgren wrote:
>>>>> * Dave Gerlach <d-gerlach@ti.com> [130808 09:23]:
>>>>>> On 08/08/2013 08:44 AM, Santosh Shilimkar wrote:
>>>>>>> Lets address the above better. I don't see a need of 8 functions
>>>>>>> exported doing one or 2 register writes.
>>>>>>>
>>>>>>> Look M3 based handling is going to be there on future SOCs
>>>>>>> as well and this kind of handling of IPC is very short cited.
>>>>>>>
>>>>>>
>>>>>> The idea here was to move all control module register accesses into
>>>>>> one file in planning of implementing a driver for the control module
>>>>>> itself in the future.
>>>>>>
>>>>>>> Probably we should have a separate driver for M3 in linux which
>>>>>>> can have all this local code instead of all these exports.
>>>>>>
>>>>>> The wkup_m3 code has been moved to a small driver found in patch 8
>>>>>> of this series, would it better to move this code there rather than
>>>>>> with the rest of the control module code?
>>>>>
>>>>> Please make everything you can into regular device drivers.
>>>>>
>>>>> We still have some dependencies to mach-omap2 code for PRCM
>>>>> for example, but we're trying to get all that to live in
>>>>> drivers.
>>>>>
>>>>> So for new pieces, let's not add further dependencies to
>>>>> complicate moving things to drivers.
>>>>>
>>>>> Regards,
>>>>>
>>>>> Tony
>>>>>
>>>>
>>>> Ok I will go ahead and pull the control module code that handles IPC
>>>> into the wkup_m3 driver.
>>>
>>> Any control module register access still needs to stay in control.c.
>>>
>>>> The wkup_m3.c file is still present in mach-omap2 as the right
>>>> location for it wasn't decided in the last RFC. Any thoughts on a good
>>>> location for it?
>>>
>>> I raised this also in earlier reviews, but don't remember the if it was
>>> answered...
>>>
>>> Why can't we handle the wkup_m3 using remoteproc/rpmsg instead of
>>> creating another little driver that duplicates communication with the
>>> M3.  Note also that the firmware load part would also be provided by
>>> remoteproc/rpmsg.
>>
>> Looping Suman Anna who handled the IPC patches this patch set is based
>> on top of...
>>
>> For the wkup_m3, the mailbox isn't used in a traditional manner. It's
>> only used with a dummy write to trigger an interrupt from the A8 to
>> the M3 and then communication happens in IPC registers within the
>> control module. No messages are actually sent through the mailbox in
>> either direction so that's why it was done this way rather than bring
>> in full support for the mailbox.
> 
> I don't believe remoteproc/rpmsg forces you to use the mailbox for
> communication, and can use other IPC mechanisms.  This still sounds
> cleaner than reinventing remoteproc/rpmsg because of slight variations.
> 
> The linux way is to use and extend what is already there, and if it's
> extended to the breaking point, then make a case for why something new
> is needed.
> 
While I agree to re-use frameworks, am strongly against use of IPC for
the power management which is time sensitive. Imagine a scenario where
ACPI is asked to go through remoteproc/ipc for talking to firmware.
If it takes 10 to 15 uS just to send a command to firmware to change
some control, that just tells something is not right and thats what
IPC will do.

ARM world is also moving towards that by standardizing some of these
through (read PSCI) and thats the way to go in general. Specifically
for this series, I am also against having tons of exports and all
of that should be extracted properly but remoteproc is not going
to be the way. Firmware download has to happen much earlier(ROM
path) so thats not the requirement where we could have used the
remoteproc firmware download feature.

Regards,
Santosh


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-13 15:08                   ` Santosh Shilimkar
  0 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-13 15:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 13 August 2013 10:29 AM, Kevin Hilman wrote:
> Dave Gerlach <d-gerlach@ti.com> writes:
> 
>> On 08/12/2013 02:17 PM, Kevin Hilman wrote:
>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>
>>>> On 08/09/2013 12:11 AM, Tony Lindgren wrote:
>>>>> * Dave Gerlach <d-gerlach@ti.com> [130808 09:23]:
>>>>>> On 08/08/2013 08:44 AM, Santosh Shilimkar wrote:
>>>>>>> Lets address the above better. I don't see a need of 8 functions
>>>>>>> exported doing one or 2 register writes.
>>>>>>>
>>>>>>> Look M3 based handling is going to be there on future SOCs
>>>>>>> as well and this kind of handling of IPC is very short cited.
>>>>>>>
>>>>>>
>>>>>> The idea here was to move all control module register accesses into
>>>>>> one file in planning of implementing a driver for the control module
>>>>>> itself in the future.
>>>>>>
>>>>>>> Probably we should have a separate driver for M3 in linux which
>>>>>>> can have all this local code instead of all these exports.
>>>>>>
>>>>>> The wkup_m3 code has been moved to a small driver found in patch 8
>>>>>> of this series, would it better to move this code there rather than
>>>>>> with the rest of the control module code?
>>>>>
>>>>> Please make everything you can into regular device drivers.
>>>>>
>>>>> We still have some dependencies to mach-omap2 code for PRCM
>>>>> for example, but we're trying to get all that to live in
>>>>> drivers.
>>>>>
>>>>> So for new pieces, let's not add further dependencies to
>>>>> complicate moving things to drivers.
>>>>>
>>>>> Regards,
>>>>>
>>>>> Tony
>>>>>
>>>>
>>>> Ok I will go ahead and pull the control module code that handles IPC
>>>> into the wkup_m3 driver.
>>>
>>> Any control module register access still needs to stay in control.c.
>>>
>>>> The wkup_m3.c file is still present in mach-omap2 as the right
>>>> location for it wasn't decided in the last RFC. Any thoughts on a good
>>>> location for it?
>>>
>>> I raised this also in earlier reviews, but don't remember the if it was
>>> answered...
>>>
>>> Why can't we handle the wkup_m3 using remoteproc/rpmsg instead of
>>> creating another little driver that duplicates communication with the
>>> M3.  Note also that the firmware load part would also be provided by
>>> remoteproc/rpmsg.
>>
>> Looping Suman Anna who handled the IPC patches this patch set is based
>> on top of...
>>
>> For the wkup_m3, the mailbox isn't used in a traditional manner. It's
>> only used with a dummy write to trigger an interrupt from the A8 to
>> the M3 and then communication happens in IPC registers within the
>> control module. No messages are actually sent through the mailbox in
>> either direction so that's why it was done this way rather than bring
>> in full support for the mailbox.
> 
> I don't believe remoteproc/rpmsg forces you to use the mailbox for
> communication, and can use other IPC mechanisms.  This still sounds
> cleaner than reinventing remoteproc/rpmsg because of slight variations.
> 
> The linux way is to use and extend what is already there, and if it's
> extended to the breaking point, then make a case for why something new
> is needed.
> 
While I agree to re-use frameworks, am strongly against use of IPC for
the power management which is time sensitive. Imagine a scenario where
ACPI is asked to go through remoteproc/ipc for talking to firmware.
If it takes 10 to 15 uS just to send a command to firmware to change
some control, that just tells something is not right and thats what
IPC will do.

ARM world is also moving towards that by standardizing some of these
through (read PSCI) and thats the way to go in general. Specifically
for this series, I am also against having tons of exports and all
of that should be extracted properly but remoteproc is not going
to be the way. Firmware download has to happen much earlier(ROM
path) so thats not the requirement where we could have used the
remoteproc firmware download feature.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-08-13 12:39       ` Daniel Mack
@ 2013-08-13 15:33         ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-13 15:33 UTC (permalink / raw)
  To: Daniel Mack; +Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman

On 08/13/2013 07:39 AM, Daniel Mack wrote:
> Hi Dave,
>
> On 12.08.2013 20:59, Dave Gerlach wrote:
>> On 08/11/2013 06:53 AM, Daniel Mack wrote:
>
>>> The problem I currently face is that I can't make the board resume, as
>>> neither UART0 nor GPIO0 seem to work as wakeup source.
>>
>> Did you apply the other patches that are mentioned besides Suman's
>> series? The board will hang while suspending without these.
>
> Yes. However, just to make sure you referenced the correct patches - on
> top of yours an Suman's set, I have:
>
>    [PATCH 1/2] ARM: OMAP2+: hwmod: rt address space index for DT
>    [PATCH 2/2] ARM: OMAP2+: hwmod: AM335x: fix cpgmac address space
>    [PATCH 1/2] ARM: dts: add AM33XX EDMA support
>
> The last one seems somewhat unrelated though.
>
> However, I see an issue with the musb dsps glue. With the usb controller
> disabled in DT, I also had to remove the usb_otg_hs entry from
> am33xx_mod[] (pm33xx.c). When the usb controller is _enabled_, I get an
> instant NULL pointer exception due to a rather obvious bug. I'll send
> out a patch right now.
>
> When I send the board to suspend (with USB disabled), the power
> consumption drops significantly, and the output is:
>
> # echo mem > /sys/power/state
> [   93.001937] PM: Syncing filesystems ... done.
> [   93.033591] Freezing user space processes ... (elapsed 0.002 seconds)
> done.
> [   93.048532] Freezing remaining freezable tasks ... (elapsed 0.002
> seconds) done.
> [   93.059277] PM: Sending message for entering DeepSleep mode
> [   93.085368] PM: suspend of devices complete after 15.070 msecs
> [   93.096671] PM: late suspend of devices complete after 5.122 msecs
> [   93.108853] PM: noirq suspend of devices complete after 5.647 msecs
>
>
> ... but traffic on UART0 won't cause a resume.
>

It looks like you are using no_console_suspend? UART0 does not work as a 
wakeup source with this option set.

>
> I'll dig a little deeper now, but if you have any idea, please let me know.
>
>
> Thanks,
> Daniel
>


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-08-13 15:33         ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-13 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/13/2013 07:39 AM, Daniel Mack wrote:
> Hi Dave,
>
> On 12.08.2013 20:59, Dave Gerlach wrote:
>> On 08/11/2013 06:53 AM, Daniel Mack wrote:
>
>>> The problem I currently face is that I can't make the board resume, as
>>> neither UART0 nor GPIO0 seem to work as wakeup source.
>>
>> Did you apply the other patches that are mentioned besides Suman's
>> series? The board will hang while suspending without these.
>
> Yes. However, just to make sure you referenced the correct patches - on
> top of yours an Suman's set, I have:
>
>    [PATCH 1/2] ARM: OMAP2+: hwmod: rt address space index for DT
>    [PATCH 2/2] ARM: OMAP2+: hwmod: AM335x: fix cpgmac address space
>    [PATCH 1/2] ARM: dts: add AM33XX EDMA support
>
> The last one seems somewhat unrelated though.
>
> However, I see an issue with the musb dsps glue. With the usb controller
> disabled in DT, I also had to remove the usb_otg_hs entry from
> am33xx_mod[] (pm33xx.c). When the usb controller is _enabled_, I get an
> instant NULL pointer exception due to a rather obvious bug. I'll send
> out a patch right now.
>
> When I send the board to suspend (with USB disabled), the power
> consumption drops significantly, and the output is:
>
> # echo mem > /sys/power/state
> [   93.001937] PM: Syncing filesystems ... done.
> [   93.033591] Freezing user space processes ... (elapsed 0.002 seconds)
> done.
> [   93.048532] Freezing remaining freezable tasks ... (elapsed 0.002
> seconds) done.
> [   93.059277] PM: Sending message for entering DeepSleep mode
> [   93.085368] PM: suspend of devices complete after 15.070 msecs
> [   93.096671] PM: late suspend of devices complete after 5.122 msecs
> [   93.108853] PM: noirq suspend of devices complete after 5.647 msecs
>
>
> ... but traffic on UART0 won't cause a resume.
>

It looks like you are using no_console_suspend? UART0 does not work as a 
wakeup source with this option set.

>
> I'll dig a little deeper now, but if you have any idea, please let me know.
>
>
> Thanks,
> Daniel
>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-08-13 15:33         ` Dave Gerlach
@ 2013-08-13 15:51           ` Daniel Mack
  -1 siblings, 0 replies; 212+ messages in thread
From: Daniel Mack @ 2013-08-13 15:51 UTC (permalink / raw)
  To: Dave Gerlach; +Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman

On 13.08.2013 17:33, Dave Gerlach wrote:
> On 08/13/2013 07:39 AM, Daniel Mack wrote:

>> ... but traffic on UART0 won't cause a resume.
>>
> 
> It looks like you are using no_console_suspend? UART0 does not work as a 
> wakeup source with this option set.

Meh. Sorry, I didn't think about that possibility. Indeed, without that
option, it does resume. Now I can search for the reason why other wakeup
sources won't work yet, but that shouldn't bother you.


Thanks again,
Daniel


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-08-13 15:51           ` Daniel Mack
  0 siblings, 0 replies; 212+ messages in thread
From: Daniel Mack @ 2013-08-13 15:51 UTC (permalink / raw)
  To: linux-arm-kernel

On 13.08.2013 17:33, Dave Gerlach wrote:
> On 08/13/2013 07:39 AM, Daniel Mack wrote:

>> ... but traffic on UART0 won't cause a resume.
>>
> 
> It looks like you are using no_console_suspend? UART0 does not work as a 
> wakeup source with this option set.

Meh. Sorry, I didn't think about that possibility. Indeed, without that
option, it does resume. Now I can search for the reason why other wakeup
sources won't work yet, but that shouldn't bother you.


Thanks again,
Daniel

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-13 15:08                   ` Santosh Shilimkar
@ 2013-08-13 16:19                     ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-13 16:19 UTC (permalink / raw)
  To: Santosh Shilimkar
  Cc: Dave Gerlach, Tony Lindgren, linux-arm-kernel, linux-omap,
	Paul Walmsley, Vaibhav Bedia, Suman Anna, Ohad Ben-Cohen

+ Ohad

Santosh Shilimkar <santosh.shilimkar@ti.com> writes:

> On Tuesday 13 August 2013 10:29 AM, Kevin Hilman wrote:
>> Dave Gerlach <d-gerlach@ti.com> writes:
>> 
>>> On 08/12/2013 02:17 PM, Kevin Hilman wrote:
>>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>>
>>>>> On 08/09/2013 12:11 AM, Tony Lindgren wrote:
>>>>>> * Dave Gerlach <d-gerlach@ti.com> [130808 09:23]:
>>>>>>> On 08/08/2013 08:44 AM, Santosh Shilimkar wrote:
>>>>>>>> Lets address the above better. I don't see a need of 8 functions
>>>>>>>> exported doing one or 2 register writes.
>>>>>>>>
>>>>>>>> Look M3 based handling is going to be there on future SOCs
>>>>>>>> as well and this kind of handling of IPC is very short cited.
>>>>>>>>
>>>>>>>
>>>>>>> The idea here was to move all control module register accesses into
>>>>>>> one file in planning of implementing a driver for the control module
>>>>>>> itself in the future.
>>>>>>>
>>>>>>>> Probably we should have a separate driver for M3 in linux which
>>>>>>>> can have all this local code instead of all these exports.
>>>>>>>
>>>>>>> The wkup_m3 code has been moved to a small driver found in patch 8
>>>>>>> of this series, would it better to move this code there rather than
>>>>>>> with the rest of the control module code?
>>>>>>
>>>>>> Please make everything you can into regular device drivers.
>>>>>>
>>>>>> We still have some dependencies to mach-omap2 code for PRCM
>>>>>> for example, but we're trying to get all that to live in
>>>>>> drivers.
>>>>>>
>>>>>> So for new pieces, let's not add further dependencies to
>>>>>> complicate moving things to drivers.
>>>>>>
>>>>>> Regards,
>>>>>>
>>>>>> Tony
>>>>>>
>>>>>
>>>>> Ok I will go ahead and pull the control module code that handles IPC
>>>>> into the wkup_m3 driver.
>>>>
>>>> Any control module register access still needs to stay in control.c.
>>>>
>>>>> The wkup_m3.c file is still present in mach-omap2 as the right
>>>>> location for it wasn't decided in the last RFC. Any thoughts on a good
>>>>> location for it?
>>>>
>>>> I raised this also in earlier reviews, but don't remember the if it was
>>>> answered...
>>>>
>>>> Why can't we handle the wkup_m3 using remoteproc/rpmsg instead of
>>>> creating another little driver that duplicates communication with the
>>>> M3.  Note also that the firmware load part would also be provided by
>>>> remoteproc/rpmsg.
>>>
>>> Looping Suman Anna who handled the IPC patches this patch set is based
>>> on top of...
>>>
>>> For the wkup_m3, the mailbox isn't used in a traditional manner. It's
>>> only used with a dummy write to trigger an interrupt from the A8 to
>>> the M3 and then communication happens in IPC registers within the
>>> control module. No messages are actually sent through the mailbox in
>>> either direction so that's why it was done this way rather than bring
>>> in full support for the mailbox.
>> 
>> I don't believe remoteproc/rpmsg forces you to use the mailbox for
>> communication, and can use other IPC mechanisms.  This still sounds
>> cleaner than reinventing remoteproc/rpmsg because of slight variations.
>> 
>> The linux way is to use and extend what is already there, and if it's
>> extended to the breaking point, then make a case for why something new
>> is needed.
>> 
> While I agree to re-use frameworks, am strongly against use of IPC for
> the power management which is time sensitive. 

Maybe I'm misunderstanding what you mean by IPC, but I'm not sure how
you can be against IPC here.  Communication with M3 requires it.

The only question is what framework to use: create a new wkup_m3 driver
which creates yet another set of IPC APIs as well as a seprate firmware
load path?  Or reuse remoteproc/rpmsg which provides both.

> Imagine a scenario where
> ACPI is asked to go through remoteproc/ipc for talking to firmware.
> If it takes 10 to 15 uS just to send a command to firmware to change
> some control, that just tells something is not right and thats what
> IPC will do.

Sounds like what you're saying is that remoteproc/rpmsg will be too slow
for this?  Is there any evidence of that?  Even if it is slow, it sounds
like a perfect opportuntity to enhance it.

Also, if speed is that much of a concern concern here, I wonder why
there's a 500msec timeout in in the communication between MPU and M3 in
the current code.

> ARM world is also moving towards that by standardizing some of these
> through (read PSCI) and thats the way to go in general. 

Agreed, but I'm not sure (yet) about enforcing PSCI on legacy platforms
that don't support it natively.  Are you saying that the AM33xx firmware
should be converted to be PSCI compliant?  Admittedly, I haven't read
the PSCI spec closely, but I'm wondering if the current role splitting
between MPU and M3 fits well with PSCI. 

> Specifically for this series, I am also against having tons of exports
> and all of that should be extracted properly but remoteproc is not
> going to be the way. Firmware download has to happen much earlier(ROM
> path) so thats not the requirement where we could have used the
> remoteproc firmware download feature.

At least for AM33xx, I don't see any requirement that firmware download
happens early (or at all.)  PM will simply be disabled until firmware is
available (and running.)

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-13 16:19                     ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-13 16:19 UTC (permalink / raw)
  To: linux-arm-kernel

+ Ohad

Santosh Shilimkar <santosh.shilimkar@ti.com> writes:

> On Tuesday 13 August 2013 10:29 AM, Kevin Hilman wrote:
>> Dave Gerlach <d-gerlach@ti.com> writes:
>> 
>>> On 08/12/2013 02:17 PM, Kevin Hilman wrote:
>>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>>
>>>>> On 08/09/2013 12:11 AM, Tony Lindgren wrote:
>>>>>> * Dave Gerlach <d-gerlach@ti.com> [130808 09:23]:
>>>>>>> On 08/08/2013 08:44 AM, Santosh Shilimkar wrote:
>>>>>>>> Lets address the above better. I don't see a need of 8 functions
>>>>>>>> exported doing one or 2 register writes.
>>>>>>>>
>>>>>>>> Look M3 based handling is going to be there on future SOCs
>>>>>>>> as well and this kind of handling of IPC is very short cited.
>>>>>>>>
>>>>>>>
>>>>>>> The idea here was to move all control module register accesses into
>>>>>>> one file in planning of implementing a driver for the control module
>>>>>>> itself in the future.
>>>>>>>
>>>>>>>> Probably we should have a separate driver for M3 in linux which
>>>>>>>> can have all this local code instead of all these exports.
>>>>>>>
>>>>>>> The wkup_m3 code has been moved to a small driver found in patch 8
>>>>>>> of this series, would it better to move this code there rather than
>>>>>>> with the rest of the control module code?
>>>>>>
>>>>>> Please make everything you can into regular device drivers.
>>>>>>
>>>>>> We still have some dependencies to mach-omap2 code for PRCM
>>>>>> for example, but we're trying to get all that to live in
>>>>>> drivers.
>>>>>>
>>>>>> So for new pieces, let's not add further dependencies to
>>>>>> complicate moving things to drivers.
>>>>>>
>>>>>> Regards,
>>>>>>
>>>>>> Tony
>>>>>>
>>>>>
>>>>> Ok I will go ahead and pull the control module code that handles IPC
>>>>> into the wkup_m3 driver.
>>>>
>>>> Any control module register access still needs to stay in control.c.
>>>>
>>>>> The wkup_m3.c file is still present in mach-omap2 as the right
>>>>> location for it wasn't decided in the last RFC. Any thoughts on a good
>>>>> location for it?
>>>>
>>>> I raised this also in earlier reviews, but don't remember the if it was
>>>> answered...
>>>>
>>>> Why can't we handle the wkup_m3 using remoteproc/rpmsg instead of
>>>> creating another little driver that duplicates communication with the
>>>> M3.  Note also that the firmware load part would also be provided by
>>>> remoteproc/rpmsg.
>>>
>>> Looping Suman Anna who handled the IPC patches this patch set is based
>>> on top of...
>>>
>>> For the wkup_m3, the mailbox isn't used in a traditional manner. It's
>>> only used with a dummy write to trigger an interrupt from the A8 to
>>> the M3 and then communication happens in IPC registers within the
>>> control module. No messages are actually sent through the mailbox in
>>> either direction so that's why it was done this way rather than bring
>>> in full support for the mailbox.
>> 
>> I don't believe remoteproc/rpmsg forces you to use the mailbox for
>> communication, and can use other IPC mechanisms.  This still sounds
>> cleaner than reinventing remoteproc/rpmsg because of slight variations.
>> 
>> The linux way is to use and extend what is already there, and if it's
>> extended to the breaking point, then make a case for why something new
>> is needed.
>> 
> While I agree to re-use frameworks, am strongly against use of IPC for
> the power management which is time sensitive. 

Maybe I'm misunderstanding what you mean by IPC, but I'm not sure how
you can be against IPC here.  Communication with M3 requires it.

The only question is what framework to use: create a new wkup_m3 driver
which creates yet another set of IPC APIs as well as a seprate firmware
load path?  Or reuse remoteproc/rpmsg which provides both.

> Imagine a scenario where
> ACPI is asked to go through remoteproc/ipc for talking to firmware.
> If it takes 10 to 15 uS just to send a command to firmware to change
> some control, that just tells something is not right and thats what
> IPC will do.

Sounds like what you're saying is that remoteproc/rpmsg will be too slow
for this?  Is there any evidence of that?  Even if it is slow, it sounds
like a perfect opportuntity to enhance it.

Also, if speed is that much of a concern concern here, I wonder why
there's a 500msec timeout in in the communication between MPU and M3 in
the current code.

> ARM world is also moving towards that by standardizing some of these
> through (read PSCI) and thats the way to go in general. 

Agreed, but I'm not sure (yet) about enforcing PSCI on legacy platforms
that don't support it natively.  Are you saying that the AM33xx firmware
should be converted to be PSCI compliant?  Admittedly, I haven't read
the PSCI spec closely, but I'm wondering if the current role splitting
between MPU and M3 fits well with PSCI. 

> Specifically for this series, I am also against having tons of exports
> and all of that should be extracted properly but remoteproc is not
> going to be the way. Firmware download has to happen much earlier(ROM
> path) so thats not the requirement where we could have used the
> remoteproc firmware download feature.

At least for AM33xx, I don't see any requirement that firmware download
happens early (or at all.)  PM will simply be disabled until firmware is
available (and running.)

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-13 16:19                     ` Kevin Hilman
@ 2013-08-13 18:18                       ` Santosh Shilimkar
  -1 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-13 18:18 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Dave Gerlach, Tony Lindgren, linux-arm-kernel, linux-omap,
	Paul Walmsley, Vaibhav Bedia, Suman Anna, Ohad Ben-Cohen

On Tuesday 13 August 2013 12:19 PM, Kevin Hilman wrote:
> + Ohad
> 
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> 
>> On Tuesday 13 August 2013 10:29 AM, Kevin Hilman wrote:
>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>
>>>> On 08/12/2013 02:17 PM, Kevin Hilman wrote:
>>>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>>>
>>>>>> On 08/09/2013 12:11 AM, Tony Lindgren wrote:
>>>>>>> * Dave Gerlach <d-gerlach@ti.com> [130808 09:23]:
>>>>>>>> On 08/08/2013 08:44 AM, Santosh Shilimkar wrote:
>>>>>>>>> Lets address the above better. I don't see a need of 8 functions
>>>>>>>>> exported doing one or 2 register writes.
>>>>>>>>>
>>>>>>>>> Look M3 based handling is going to be there on future SOCs
>>>>>>>>> as well and this kind of handling of IPC is very short cited.
>>>>>>>>>
>>>>>>>>
>>>>>>>> The idea here was to move all control module register accesses into
>>>>>>>> one file in planning of implementing a driver for the control module
>>>>>>>> itself in the future.
>>>>>>>>
>>>>>>>>> Probably we should have a separate driver for M3 in linux which
>>>>>>>>> can have all this local code instead of all these exports.
>>>>>>>>
>>>>>>>> The wkup_m3 code has been moved to a small driver found in patch 8
>>>>>>>> of this series, would it better to move this code there rather than
>>>>>>>> with the rest of the control module code?
>>>>>>>
>>>>>>> Please make everything you can into regular device drivers.
>>>>>>>
>>>>>>> We still have some dependencies to mach-omap2 code for PRCM
>>>>>>> for example, but we're trying to get all that to live in
>>>>>>> drivers.
>>>>>>>
>>>>>>> So for new pieces, let's not add further dependencies to
>>>>>>> complicate moving things to drivers.
>>>>>>>
>>>>>>> Regards,
>>>>>>>
>>>>>>> Tony
>>>>>>>
>>>>>>
>>>>>> Ok I will go ahead and pull the control module code that handles IPC
>>>>>> into the wkup_m3 driver.
>>>>>
>>>>> Any control module register access still needs to stay in control.c.
>>>>>
>>>>>> The wkup_m3.c file is still present in mach-omap2 as the right
>>>>>> location for it wasn't decided in the last RFC. Any thoughts on a good
>>>>>> location for it?
>>>>>
>>>>> I raised this also in earlier reviews, but don't remember the if it was
>>>>> answered...
>>>>>
>>>>> Why can't we handle the wkup_m3 using remoteproc/rpmsg instead of
>>>>> creating another little driver that duplicates communication with the
>>>>> M3.  Note also that the firmware load part would also be provided by
>>>>> remoteproc/rpmsg.
>>>>
>>>> Looping Suman Anna who handled the IPC patches this patch set is based
>>>> on top of...
>>>>
>>>> For the wkup_m3, the mailbox isn't used in a traditional manner. It's
>>>> only used with a dummy write to trigger an interrupt from the A8 to
>>>> the M3 and then communication happens in IPC registers within the
>>>> control module. No messages are actually sent through the mailbox in
>>>> either direction so that's why it was done this way rather than bring
>>>> in full support for the mailbox.
>>>
>>> I don't believe remoteproc/rpmsg forces you to use the mailbox for
>>> communication, and can use other IPC mechanisms.  This still sounds
>>> cleaner than reinventing remoteproc/rpmsg because of slight variations.
>>>
>>> The linux way is to use and extend what is already there, and if it's
>>> extended to the breaking point, then make a case for why something new
>>> is needed.
>>>
>> While I agree to re-use frameworks, am strongly against use of IPC for
>> the power management which is time sensitive. 
> 
> Maybe I'm misunderstanding what you mean by IPC, but I'm not sure how
> you can be against IPC here.  Communication with M3 requires it.
>
> The only question is what framework to use: create a new wkup_m3 driver
> which creates yet another set of IPC APIs as well as a seprate firmware
> load path?  Or reuse remoteproc/rpmsg which provides both.
>
I mean Linux IPC layers. 
 
>> Imagine a scenario where
>> ACPI is asked to go through remoteproc/ipc for talking to firmware.
>> If it takes 10 to 15 uS just to send a command to firmware to change
>> some control, that just tells something is not right and thats what
>> IPC will do.
> 
> Sounds like what you're saying is that remoteproc/rpmsg will be too slow
> for this?  Is there any evidence of that?  Even if it is slow, it sounds
> like a perfect opportuntity to enhance it.
>
Well 10's uS is fine for the pure IPC kind of messaging. The numbers were
measured on Linux OMAP IPC stack for different purpose.
 
> Also, if speed is that much of a concern concern here, I wonder why
> there's a 500msec timeout in in the communication between MPU and M3 in
> the current code.
> 
>> ARM world is also moving towards that by standardizing some of these
>> through (read PSCI) and thats the way to go in general. 
> 
> Agreed, but I'm not sure (yet) about enforcing PSCI on legacy platforms
> that don't support it natively.  Are you saying that the AM33xx firmware
> should be converted to be PSCI compliant?  Admittedly, I haven't read
> the PSCI spec closely, but I'm wondering if the current role splitting
> between MPU and M3 fits well with PSCI. 
>
I didn't mean for the AM3XXX specifically because its current job is rather
very limited. i.e suspend. My concern is that IPC is not viewed as
an option for power management controllers like M3 which can abstract
all the hardware gory details and export a simpled interface for OS
in form of PSCI/ACPI. 

>> Specifically for this series, I am also against having tons of exports
>> and all of that should be extracted properly but remoteproc is not
>> going to be the way. Firmware download has to happen much earlier(ROM
>> path) so thats not the requirement where we could have used the
>> remoteproc firmware download feature.
> 
> At least for AM33xx, I don't see any requirement that firmware download
> happens early (or at all.)  PM will simply be disabled until firmware is
> available (and running.)
> 
Thats because its role is pretty much limited. The point was mainly from
general PM firmware download strategy and not specifically for this
one device.

I just wanted to be sure that we will do all of this for AM3XXX and expect
the future SOCs to follow that model where M3 would have more prominent
role and more and more hardware sequencing for HLOS.

Regards,
Santosh


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-13 18:18                       ` Santosh Shilimkar
  0 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-13 18:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 13 August 2013 12:19 PM, Kevin Hilman wrote:
> + Ohad
> 
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
> 
>> On Tuesday 13 August 2013 10:29 AM, Kevin Hilman wrote:
>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>
>>>> On 08/12/2013 02:17 PM, Kevin Hilman wrote:
>>>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>>>
>>>>>> On 08/09/2013 12:11 AM, Tony Lindgren wrote:
>>>>>>> * Dave Gerlach <d-gerlach@ti.com> [130808 09:23]:
>>>>>>>> On 08/08/2013 08:44 AM, Santosh Shilimkar wrote:
>>>>>>>>> Lets address the above better. I don't see a need of 8 functions
>>>>>>>>> exported doing one or 2 register writes.
>>>>>>>>>
>>>>>>>>> Look M3 based handling is going to be there on future SOCs
>>>>>>>>> as well and this kind of handling of IPC is very short cited.
>>>>>>>>>
>>>>>>>>
>>>>>>>> The idea here was to move all control module register accesses into
>>>>>>>> one file in planning of implementing a driver for the control module
>>>>>>>> itself in the future.
>>>>>>>>
>>>>>>>>> Probably we should have a separate driver for M3 in linux which
>>>>>>>>> can have all this local code instead of all these exports.
>>>>>>>>
>>>>>>>> The wkup_m3 code has been moved to a small driver found in patch 8
>>>>>>>> of this series, would it better to move this code there rather than
>>>>>>>> with the rest of the control module code?
>>>>>>>
>>>>>>> Please make everything you can into regular device drivers.
>>>>>>>
>>>>>>> We still have some dependencies to mach-omap2 code for PRCM
>>>>>>> for example, but we're trying to get all that to live in
>>>>>>> drivers.
>>>>>>>
>>>>>>> So for new pieces, let's not add further dependencies to
>>>>>>> complicate moving things to drivers.
>>>>>>>
>>>>>>> Regards,
>>>>>>>
>>>>>>> Tony
>>>>>>>
>>>>>>
>>>>>> Ok I will go ahead and pull the control module code that handles IPC
>>>>>> into the wkup_m3 driver.
>>>>>
>>>>> Any control module register access still needs to stay in control.c.
>>>>>
>>>>>> The wkup_m3.c file is still present in mach-omap2 as the right
>>>>>> location for it wasn't decided in the last RFC. Any thoughts on a good
>>>>>> location for it?
>>>>>
>>>>> I raised this also in earlier reviews, but don't remember the if it was
>>>>> answered...
>>>>>
>>>>> Why can't we handle the wkup_m3 using remoteproc/rpmsg instead of
>>>>> creating another little driver that duplicates communication with the
>>>>> M3.  Note also that the firmware load part would also be provided by
>>>>> remoteproc/rpmsg.
>>>>
>>>> Looping Suman Anna who handled the IPC patches this patch set is based
>>>> on top of...
>>>>
>>>> For the wkup_m3, the mailbox isn't used in a traditional manner. It's
>>>> only used with a dummy write to trigger an interrupt from the A8 to
>>>> the M3 and then communication happens in IPC registers within the
>>>> control module. No messages are actually sent through the mailbox in
>>>> either direction so that's why it was done this way rather than bring
>>>> in full support for the mailbox.
>>>
>>> I don't believe remoteproc/rpmsg forces you to use the mailbox for
>>> communication, and can use other IPC mechanisms.  This still sounds
>>> cleaner than reinventing remoteproc/rpmsg because of slight variations.
>>>
>>> The linux way is to use and extend what is already there, and if it's
>>> extended to the breaking point, then make a case for why something new
>>> is needed.
>>>
>> While I agree to re-use frameworks, am strongly against use of IPC for
>> the power management which is time sensitive. 
> 
> Maybe I'm misunderstanding what you mean by IPC, but I'm not sure how
> you can be against IPC here.  Communication with M3 requires it.
>
> The only question is what framework to use: create a new wkup_m3 driver
> which creates yet another set of IPC APIs as well as a seprate firmware
> load path?  Or reuse remoteproc/rpmsg which provides both.
>
I mean Linux IPC layers. 
 
>> Imagine a scenario where
>> ACPI is asked to go through remoteproc/ipc for talking to firmware.
>> If it takes 10 to 15 uS just to send a command to firmware to change
>> some control, that just tells something is not right and thats what
>> IPC will do.
> 
> Sounds like what you're saying is that remoteproc/rpmsg will be too slow
> for this?  Is there any evidence of that?  Even if it is slow, it sounds
> like a perfect opportuntity to enhance it.
>
Well 10's uS is fine for the pure IPC kind of messaging. The numbers were
measured on Linux OMAP IPC stack for different purpose.
 
> Also, if speed is that much of a concern concern here, I wonder why
> there's a 500msec timeout in in the communication between MPU and M3 in
> the current code.
> 
>> ARM world is also moving towards that by standardizing some of these
>> through (read PSCI) and thats the way to go in general. 
> 
> Agreed, but I'm not sure (yet) about enforcing PSCI on legacy platforms
> that don't support it natively.  Are you saying that the AM33xx firmware
> should be converted to be PSCI compliant?  Admittedly, I haven't read
> the PSCI spec closely, but I'm wondering if the current role splitting
> between MPU and M3 fits well with PSCI. 
>
I didn't mean for the AM3XXX specifically because its current job is rather
very limited. i.e suspend. My concern is that IPC is not viewed as
an option for power management controllers like M3 which can abstract
all the hardware gory details and export a simpled interface for OS
in form of PSCI/ACPI. 

>> Specifically for this series, I am also against having tons of exports
>> and all of that should be extracted properly but remoteproc is not
>> going to be the way. Firmware download has to happen much earlier(ROM
>> path) so thats not the requirement where we could have used the
>> remoteproc firmware download feature.
> 
> At least for AM33xx, I don't see any requirement that firmware download
> happens early (or at all.)  PM will simply be disabled until firmware is
> available (and running.)
> 
Thats because its role is pretty much limited. The point was mainly from
general PM firmware download strategy and not specifically for this
one device.

I just wanted to be sure that we will do all of this for AM3XXX and expect
the future SOCs to follow that model where M3 would have more prominent
role and more and more hardware sequencing for HLOS.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-13 18:18                       ` Santosh Shilimkar
@ 2013-08-13 18:30                         ` Russ Dill
  -1 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-13 18:30 UTC (permalink / raw)
  To: Santosh Shilimkar
  Cc: Kevin Hilman, Ohad Ben-Cohen, Paul Walmsley, Suman Anna,
	Dave Gerlach, Tony Lindgren, Vaibhav Bedia, linux-omap,
	linux-arm-kernel

>>> ARM world is also moving towards that by standardizing some of these
>>> through (read PSCI) and thats the way to go in general.
>>
>> Agreed, but I'm not sure (yet) about enforcing PSCI on legacy platforms
>> that don't support it natively.  Are you saying that the AM33xx firmware
>> should be converted to be PSCI compliant?  Admittedly, I haven't read
>> the PSCI spec closely, but I'm wondering if the current role splitting
>> between MPU and M3 fits well with PSCI.
>>
> I didn't mean for the AM3XXX specifically because its current job is rather
> very limited. i.e suspend. My concern is that IPC is not viewed as
> an option for power management controllers like M3 which can abstract
> all the hardware gory details and export a simpled interface for OS
> in form of PSCI/ACPI.

The IPC between the M3 and the A8 on the am335x is just a pair of
notification mechanisms (one from the A8, mailbox, and one from the
M3, sev) and a set of 8 32 bit registers. The 8 32 bit registers are
just a scratchpad and have no access rules or functionality beyond
being a scratchpad. How complicated do we want to make this?

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-13 18:30                         ` Russ Dill
  0 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-13 18:30 UTC (permalink / raw)
  To: linux-arm-kernel

>>> ARM world is also moving towards that by standardizing some of these
>>> through (read PSCI) and thats the way to go in general.
>>
>> Agreed, but I'm not sure (yet) about enforcing PSCI on legacy platforms
>> that don't support it natively.  Are you saying that the AM33xx firmware
>> should be converted to be PSCI compliant?  Admittedly, I haven't read
>> the PSCI spec closely, but I'm wondering if the current role splitting
>> between MPU and M3 fits well with PSCI.
>>
> I didn't mean for the AM3XXX specifically because its current job is rather
> very limited. i.e suspend. My concern is that IPC is not viewed as
> an option for power management controllers like M3 which can abstract
> all the hardware gory details and export a simpled interface for OS
> in form of PSCI/ACPI.

The IPC between the M3 and the A8 on the am335x is just a pair of
notification mechanisms (one from the A8, mailbox, and one from the
M3, sev) and a set of 8 32 bit registers. The 8 32 bit registers are
just a scratchpad and have no access rules or functionality beyond
being a scratchpad. How complicated do we want to make this?

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-13 18:30                         ` Russ Dill
@ 2013-08-13 18:40                           ` Santosh Shilimkar
  -1 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-13 18:40 UTC (permalink / raw)
  To: Russ Dill
  Cc: Ohad Ben-Cohen, Paul Walmsley, Kevin Hilman, Dave Gerlach,
	Tony Lindgren, Vaibhav Bedia, linux-omap, Suman Anna,
	linux-arm-kernel

On Tuesday 13 August 2013 02:30 PM, Russ Dill wrote:
>>>> ARM world is also moving towards that by standardizing some of these
>>>> through (read PSCI) and thats the way to go in general.
>>>
>>> Agreed, but I'm not sure (yet) about enforcing PSCI on legacy platforms
>>> that don't support it natively.  Are you saying that the AM33xx firmware
>>> should be converted to be PSCI compliant?  Admittedly, I haven't read
>>> the PSCI spec closely, but I'm wondering if the current role splitting
>>> between MPU and M3 fits well with PSCI.
>>>
>> I didn't mean for the AM3XXX specifically because its current job is rather
>> very limited. i.e suspend. My concern is that IPC is not viewed as
>> an option for power management controllers like M3 which can abstract
>> all the hardware gory details and export a simpled interface for OS
>> in form of PSCI/ACPI.
> 
> The IPC between the M3 and the A8 on the am335x is just a pair of
> notification mechanisms (one from the A8, mailbox, and one from the
> M3, sev) and a set of 8 32 bit registers. The 8 32 bit registers are
> just a scratchpad and have no access rules or functionality beyond
> being a scratchpad. How complicated do we want to make this?
> 
Exactly what I mean as well.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-13 18:40                           ` Santosh Shilimkar
  0 siblings, 0 replies; 212+ messages in thread
From: Santosh Shilimkar @ 2013-08-13 18:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 13 August 2013 02:30 PM, Russ Dill wrote:
>>>> ARM world is also moving towards that by standardizing some of these
>>>> through (read PSCI) and thats the way to go in general.
>>>
>>> Agreed, but I'm not sure (yet) about enforcing PSCI on legacy platforms
>>> that don't support it natively.  Are you saying that the AM33xx firmware
>>> should be converted to be PSCI compliant?  Admittedly, I haven't read
>>> the PSCI spec closely, but I'm wondering if the current role splitting
>>> between MPU and M3 fits well with PSCI.
>>>
>> I didn't mean for the AM3XXX specifically because its current job is rather
>> very limited. i.e suspend. My concern is that IPC is not viewed as
>> an option for power management controllers like M3 which can abstract
>> all the hardware gory details and export a simpled interface for OS
>> in form of PSCI/ACPI.
> 
> The IPC between the M3 and the A8 on the am335x is just a pair of
> notification mechanisms (one from the A8, mailbox, and one from the
> M3, sev) and a set of 8 32 bit registers. The 8 32 bit registers are
> just a scratchpad and have no access rules or functionality beyond
> being a scratchpad. How complicated do we want to make this?
> 
Exactly what I mean as well.

Regards,
Santosh

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-13 18:30                         ` Russ Dill
@ 2013-08-13 19:11                           ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-13 19:11 UTC (permalink / raw)
  To: Russ Dill
  Cc: Santosh Shilimkar, Ohad Ben-Cohen, Paul Walmsley, Suman Anna,
	Dave Gerlach, Tony Lindgren, Vaibhav Bedia, linux-omap,
	linux-arm-kernel

Russ Dill <russ.dill@gmail.com> writes:

>>>> ARM world is also moving towards that by standardizing some of these
>>>> through (read PSCI) and thats the way to go in general.
>>>
>>> Agreed, but I'm not sure (yet) about enforcing PSCI on legacy platforms
>>> that don't support it natively.  Are you saying that the AM33xx firmware
>>> should be converted to be PSCI compliant?  Admittedly, I haven't read
>>> the PSCI spec closely, but I'm wondering if the current role splitting
>>> between MPU and M3 fits well with PSCI.
>>>
>> I didn't mean for the AM3XXX specifically because its current job is rather
>> very limited. i.e suspend. My concern is that IPC is not viewed as
>> an option for power management controllers like M3 which can abstract
>> all the hardware gory details and export a simpled interface for OS
>> in form of PSCI/ACPI.
>
> The IPC between the M3 and the A8 on the am335x is just a pair of
> notification mechanisms (one from the A8, mailbox, and one from the
> M3, sev) and a set of 8 32 bit registers. The 8 32 bit registers are
> just a scratchpad and have no access rules or functionality beyond
> being a scratchpad. How complicated do we want to make this?

The OMAP IPC between the MPU and DSP (read: any other remote processor)
is just a mailbox and some shared memory.  No complicated, and works
with remoteproc/rpmsg.

What's more complicated? reusing existing frameworks or re-inventing
them?  Don't forget that "simple" drivers rarely stay that way.

Also, this is not a hard stance on my part.  I just need to be
convinced.  

The fact is that there are existing frameworks for doing what is being
proposed here.  Either use the existing frameworks, or make a technical
argument based on why those frameworks are not a good fit (ideally,
after having tried to use those frameworks.)

Once again, I'm pretty sure I mentioned this in earlier reviews of this
series.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-13 19:11                           ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-13 19:11 UTC (permalink / raw)
  To: linux-arm-kernel

Russ Dill <russ.dill@gmail.com> writes:

>>>> ARM world is also moving towards that by standardizing some of these
>>>> through (read PSCI) and thats the way to go in general.
>>>
>>> Agreed, but I'm not sure (yet) about enforcing PSCI on legacy platforms
>>> that don't support it natively.  Are you saying that the AM33xx firmware
>>> should be converted to be PSCI compliant?  Admittedly, I haven't read
>>> the PSCI spec closely, but I'm wondering if the current role splitting
>>> between MPU and M3 fits well with PSCI.
>>>
>> I didn't mean for the AM3XXX specifically because its current job is rather
>> very limited. i.e suspend. My concern is that IPC is not viewed as
>> an option for power management controllers like M3 which can abstract
>> all the hardware gory details and export a simpled interface for OS
>> in form of PSCI/ACPI.
>
> The IPC between the M3 and the A8 on the am335x is just a pair of
> notification mechanisms (one from the A8, mailbox, and one from the
> M3, sev) and a set of 8 32 bit registers. The 8 32 bit registers are
> just a scratchpad and have no access rules or functionality beyond
> being a scratchpad. How complicated do we want to make this?

The OMAP IPC between the MPU and DSP (read: any other remote processor)
is just a mailbox and some shared memory.  No complicated, and works
with remoteproc/rpmsg.

What's more complicated? reusing existing frameworks or re-inventing
them?  Don't forget that "simple" drivers rarely stay that way.

Also, this is not a hard stance on my part.  I just need to be
convinced.  

The fact is that there are existing frameworks for doing what is being
proposed here.  Either use the existing frameworks, or make a technical
argument based on why those frameworks are not a good fit (ideally,
after having tried to use those frameworks.)

Once again, I'm pretty sure I mentioned this in earlier reviews of this
series.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-13 19:11                           ` Kevin Hilman
@ 2013-08-14 17:27                             ` Suman Anna
  -1 siblings, 0 replies; 212+ messages in thread
From: Suman Anna @ 2013-08-14 17:27 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Russ Dill, Santosh Shilimkar, Ohad Ben-Cohen, Paul Walmsley,
	Dave Gerlach, Tony Lindgren, Vaibhav Bedia, linux-omap,
	linux-arm-kernel

Kevin, Santosh, Dave, Russ,

On 08/13/2013 02:11 PM, Kevin Hilman wrote:
> Russ Dill <russ.dill@gmail.com> writes:
> 
>>>>> ARM world is also moving towards that by standardizing some of these
>>>>> through (read PSCI) and thats the way to go in general.
>>>>
>>>> Agreed, but I'm not sure (yet) about enforcing PSCI on legacy platforms
>>>> that don't support it natively.  Are you saying that the AM33xx firmware
>>>> should be converted to be PSCI compliant?  Admittedly, I haven't read
>>>> the PSCI spec closely, but I'm wondering if the current role splitting
>>>> between MPU and M3 fits well with PSCI.
>>>>
>>> I didn't mean for the AM3XXX specifically because its current job is rather
>>> very limited. i.e suspend. My concern is that IPC is not viewed as
>>> an option for power management controllers like M3 which can abstract
>>> all the hardware gory details and export a simpled interface for OS
>>> in form of PSCI/ACPI.
>>
>> The IPC between the M3 and the A8 on the am335x is just a pair of
>> notification mechanisms (one from the A8, mailbox, and one from the
>> M3, sev) and a set of 8 32 bit registers. The 8 32 bit registers are
>> just a scratchpad and have no access rules or functionality beyond
>> being a scratchpad. How complicated do we want to make this?
> 
> The OMAP IPC between the MPU and DSP (read: any other remote processor)
> is just a mailbox and some shared memory.  No complicated, and works
> with remoteproc/rpmsg.

I had to catch up on all the threads before I responded, but here are my
notes regarding using remoteproc/rpmsg infrastructure for WkupM3. It
definitely brings in lot more complexity than what's present today. The
WkupM3 in AM335x does not have the same feature set as the Cortex-M3s
used within the IPU in OMAP4+ SoCs. It does not have an MMU and
peripheral accesses seems to be limited to just those in L4_Wkup domain.

A lot actually depends on whether the WkupM3 can use DDR. I am not sure
if there are any restrictions on WkupM3 from where it could run the code
or access data from. From what I can gather from the TRM (there's no big
separate chapter on WkupM3), it has just 16K UMEM and a 8K DMEM, and its
not much. The current firmware is loaded directly into the WkupM3's
internal UMem space and a check is being performed to make sure the
firmware is less than  16K, so that it can fit into UMem.

The remoteproc infrastructure is currently tied closely with the
virtio/rpmsg framework, and the boot requires that there are virtio
devices present in the resource table from the firmware image. The rpmsg
shared memory buffers are currently kinda fixed (512 buffers of 512
bytes each) and requires 3 pages just for the vring structures for this
many buffers. So, if there are restrictions on DDR access, then this
pretty much rules out remoteproc/rpmsg infrastructure.

If the DDR access is ok, then there are other challenges that needs to
be met. The current firmware definitely requires the addition of the
resource table and the lower level code for handling the virtio_ring
transport for receiving messages. It would also need its own remoteproc
driver for handling the firmware binary format and the signalling
required to trigger the rpmsg buffer processing. The firmware binary
format needs to be adapted to something that this driver would
understand. It definitely doesn't look like ELF currently, so something
on the lines of ste_modem_rproc needs to be done. Also, the
remoteproc/rpmsg infrastructure can support multiple vring transport
channels between the processor, and depending on how many are supported,
we either need to exchange the vq_id (like OMAP remoteproc), or process
the known virtqueues always (like DA8xx remoteproc). The former requires
that a message payload is used, and mandates the usage of the IPC data
registers in the control module given that WkupM3 on AM335 cannot access
any mailbox registers. Any usage of IPC data registers depends on where
we do it. If all the accesses were to be done within
mach-omap2/control.c, then there is no easy way for using this API from
drivers/remoteproc, until we have the control module driver. I do feel
that this needs to be done within the wkup_m3 driver currently. This
would be no different to the crossbar driver example on DRA7, which also
has to deal with registers in Control module. The IPC data registers do
not have any associated interrupts by itself, so just making this a
standalone driver is also not possible. Also, the dependencies with
using the omap_device API for dealing with the hard reset lines needs to
be dealt with.

The current communication uses the IPC data registers, and sometimes
uses them as plain status registers. There's certain registers used for
sharing status, version etc which are shared by both the processors.
Using rpmsg would require communicating every single message, and if
there were to be some shared variables to be used simultaneously, then
this has to be exchanged through a new remoteproc resource type.

One additional aspect is that the current remoteproc core does not have
the necessary runtime pm support, but in general the approach would be
to treat the remoteprocs as true slave devices. I would imagine the
driver core to put the remoteprocs into reset state, after asking them
to save their context during suspend.

regards
Suman


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-14 17:27                             ` Suman Anna
  0 siblings, 0 replies; 212+ messages in thread
From: Suman Anna @ 2013-08-14 17:27 UTC (permalink / raw)
  To: linux-arm-kernel

Kevin, Santosh, Dave, Russ,

On 08/13/2013 02:11 PM, Kevin Hilman wrote:
> Russ Dill <russ.dill@gmail.com> writes:
> 
>>>>> ARM world is also moving towards that by standardizing some of these
>>>>> through (read PSCI) and thats the way to go in general.
>>>>
>>>> Agreed, but I'm not sure (yet) about enforcing PSCI on legacy platforms
>>>> that don't support it natively.  Are you saying that the AM33xx firmware
>>>> should be converted to be PSCI compliant?  Admittedly, I haven't read
>>>> the PSCI spec closely, but I'm wondering if the current role splitting
>>>> between MPU and M3 fits well with PSCI.
>>>>
>>> I didn't mean for the AM3XXX specifically because its current job is rather
>>> very limited. i.e suspend. My concern is that IPC is not viewed as
>>> an option for power management controllers like M3 which can abstract
>>> all the hardware gory details and export a simpled interface for OS
>>> in form of PSCI/ACPI.
>>
>> The IPC between the M3 and the A8 on the am335x is just a pair of
>> notification mechanisms (one from the A8, mailbox, and one from the
>> M3, sev) and a set of 8 32 bit registers. The 8 32 bit registers are
>> just a scratchpad and have no access rules or functionality beyond
>> being a scratchpad. How complicated do we want to make this?
> 
> The OMAP IPC between the MPU and DSP (read: any other remote processor)
> is just a mailbox and some shared memory.  No complicated, and works
> with remoteproc/rpmsg.

I had to catch up on all the threads before I responded, but here are my
notes regarding using remoteproc/rpmsg infrastructure for WkupM3. It
definitely brings in lot more complexity than what's present today. The
WkupM3 in AM335x does not have the same feature set as the Cortex-M3s
used within the IPU in OMAP4+ SoCs. It does not have an MMU and
peripheral accesses seems to be limited to just those in L4_Wkup domain.

A lot actually depends on whether the WkupM3 can use DDR. I am not sure
if there are any restrictions on WkupM3 from where it could run the code
or access data from. From what I can gather from the TRM (there's no big
separate chapter on WkupM3), it has just 16K UMEM and a 8K DMEM, and its
not much. The current firmware is loaded directly into the WkupM3's
internal UMem space and a check is being performed to make sure the
firmware is less than  16K, so that it can fit into UMem.

The remoteproc infrastructure is currently tied closely with the
virtio/rpmsg framework, and the boot requires that there are virtio
devices present in the resource table from the firmware image. The rpmsg
shared memory buffers are currently kinda fixed (512 buffers of 512
bytes each) and requires 3 pages just for the vring structures for this
many buffers. So, if there are restrictions on DDR access, then this
pretty much rules out remoteproc/rpmsg infrastructure.

If the DDR access is ok, then there are other challenges that needs to
be met. The current firmware definitely requires the addition of the
resource table and the lower level code for handling the virtio_ring
transport for receiving messages. It would also need its own remoteproc
driver for handling the firmware binary format and the signalling
required to trigger the rpmsg buffer processing. The firmware binary
format needs to be adapted to something that this driver would
understand. It definitely doesn't look like ELF currently, so something
on the lines of ste_modem_rproc needs to be done. Also, the
remoteproc/rpmsg infrastructure can support multiple vring transport
channels between the processor, and depending on how many are supported,
we either need to exchange the vq_id (like OMAP remoteproc), or process
the known virtqueues always (like DA8xx remoteproc). The former requires
that a message payload is used, and mandates the usage of the IPC data
registers in the control module given that WkupM3 on AM335 cannot access
any mailbox registers. Any usage of IPC data registers depends on where
we do it. If all the accesses were to be done within
mach-omap2/control.c, then there is no easy way for using this API from
drivers/remoteproc, until we have the control module driver. I do feel
that this needs to be done within the wkup_m3 driver currently. This
would be no different to the crossbar driver example on DRA7, which also
has to deal with registers in Control module. The IPC data registers do
not have any associated interrupts by itself, so just making this a
standalone driver is also not possible. Also, the dependencies with
using the omap_device API for dealing with the hard reset lines needs to
be dealt with.

The current communication uses the IPC data registers, and sometimes
uses them as plain status registers. There's certain registers used for
sharing status, version etc which are shared by both the processors.
Using rpmsg would require communicating every single message, and if
there were to be some shared variables to be used simultaneously, then
this has to be exchanged through a new remoteproc resource type.

One additional aspect is that the current remoteproc core does not have
the necessary runtime pm support, but in general the approach would be
to treat the remoteprocs as true slave devices. I would imagine the
driver core to put the remoteprocs into reset state, after asking them
to save their context during suspend.

regards
Suman

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-14 17:27                             ` Suman Anna
@ 2013-08-14 19:16                               ` Russ Dill
  -1 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-14 19:16 UTC (permalink / raw)
  To: Suman Anna
  Cc: Kevin Hilman, Santosh Shilimkar, Ohad Ben-Cohen, Paul Walmsley,
	Dave Gerlach, Tony Lindgren, Vaibhav Bedia, linux-omap,
	linux-arm-kernel

On Wed, Aug 14, 2013 at 10:27 AM, Suman Anna <s-anna@ti.com> wrote:
> Kevin, Santosh, Dave, Russ,
>
> On 08/13/2013 02:11 PM, Kevin Hilman wrote:
>> Russ Dill <russ.dill@gmail.com> writes:
>>
>>>>>> ARM world is also moving towards that by standardizing some of these
>>>>>> through (read PSCI) and thats the way to go in general.
>>>>>
>>>>> Agreed, but I'm not sure (yet) about enforcing PSCI on legacy platforms
>>>>> that don't support it natively.  Are you saying that the AM33xx firmware
>>>>> should be converted to be PSCI compliant?  Admittedly, I haven't read
>>>>> the PSCI spec closely, but I'm wondering if the current role splitting
>>>>> between MPU and M3 fits well with PSCI.
>>>>>
>>>> I didn't mean for the AM3XXX specifically because its current job is rather
>>>> very limited. i.e suspend. My concern is that IPC is not viewed as
>>>> an option for power management controllers like M3 which can abstract
>>>> all the hardware gory details and export a simpled interface for OS
>>>> in form of PSCI/ACPI.
>>>
>>> The IPC between the M3 and the A8 on the am335x is just a pair of
>>> notification mechanisms (one from the A8, mailbox, and one from the
>>> M3, sev) and a set of 8 32 bit registers. The 8 32 bit registers are
>>> just a scratchpad and have no access rules or functionality beyond
>>> being a scratchpad. How complicated do we want to make this?
>>
>> The OMAP IPC between the MPU and DSP (read: any other remote processor)
>> is just a mailbox and some shared memory.  No complicated, and works
>> with remoteproc/rpmsg.
>
> I had to catch up on all the threads before I responded, but here are my
> notes regarding using remoteproc/rpmsg infrastructure for WkupM3. It
> definitely brings in lot more complexity than what's present today. The
> WkupM3 in AM335x does not have the same feature set as the Cortex-M3s
> used within the IPU in OMAP4+ SoCs. It does not have an MMU and
> peripheral accesses seems to be limited to just those in L4_Wkup domain.
>
> A lot actually depends on whether the WkupM3 can use DDR. I am not sure
> if there are any restrictions on WkupM3 from where it could run the code
> or access data from. From what I can gather from the TRM (there's no big
> separate chapter on WkupM3), it has just 16K UMEM and a 8K DMEM, and its
> not much. The current firmware is loaded directly into the WkupM3's
> internal UMem space and a check is being performed to make sure the
> firmware is less than  16K, so that it can fit into UMem.

Even if the WkupM3 could access DMEM, it would defeat the whole
purpose of using it, as it lives to do things like enable VTP, but the
EMIF clocks into bypass, turn off the power domain the EMIF is
contained in, etc.

> The remoteproc infrastructure is currently tied closely with the
> virtio/rpmsg framework, and the boot requires that there are virtio
> devices present in the resource table from the firmware image. The rpmsg
> shared memory buffers are currently kinda fixed (512 buffers of 512
> bytes each) and requires 3 pages just for the vring structures for this
> many buffers. So, if there are restrictions on DDR access, then this
> pretty much rules out remoteproc/rpmsg infrastructure.
>
> If the DDR access is ok, then there are other challenges that needs to
> be met. The current firmware definitely requires the addition of the
> resource table and the lower level code for handling the virtio_ring
> transport for receiving messages. It would also need its own remoteproc
> driver for handling the firmware binary format and the signalling
> required to trigger the rpmsg buffer processing. The firmware binary
> format needs to be adapted to something that this driver would
> understand. It definitely doesn't look like ELF currently, so something
> on the lines of ste_modem_rproc needs to be done. Also, the
> remoteproc/rpmsg infrastructure can support multiple vring transport
> channels between the processor, and depending on how many are supported,
> we either need to exchange the vq_id (like OMAP remoteproc), or process
> the known virtqueues always (like DA8xx remoteproc). The former requires
> that a message payload is used, and mandates the usage of the IPC data
> registers in the control module given that WkupM3 on AM335 cannot access
> any mailbox registers. Any usage of IPC data registers depends on where
> we do it. If all the accesses were to be done within
> mach-omap2/control.c, then there is no easy way for using this API from
> drivers/remoteproc, until we have the control module driver. I do feel
> that this needs to be done within the wkup_m3 driver currently. This
> would be no different to the crossbar driver example on DRA7, which also
> has to deal with registers in Control module. The IPC data registers do
> not have any associated interrupts by itself, so just making this a
> standalone driver is also not possible. Also, the dependencies with
> using the omap_device API for dealing with the hard reset lines needs to
> be dealt with.
>
> The current communication uses the IPC data registers, and sometimes
> uses them as plain status registers. There's certain registers used for
> sharing status, version etc which are shared by both the processors.
> Using rpmsg would require communicating every single message, and if
> there were to be some shared variables to be used simultaneously, then
> this has to be exchanged through a new remoteproc resource type.
>
> One additional aspect is that the current remoteproc core does not have
> the necessary runtime pm support, but in general the approach would be
> to treat the remoteprocs as true slave devices. I would imagine the
> driver core to put the remoteprocs into reset state, after asking them
> to save their context during suspend.
>
> regards
> Suman
>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-14 19:16                               ` Russ Dill
  0 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-14 19:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 14, 2013 at 10:27 AM, Suman Anna <s-anna@ti.com> wrote:
> Kevin, Santosh, Dave, Russ,
>
> On 08/13/2013 02:11 PM, Kevin Hilman wrote:
>> Russ Dill <russ.dill@gmail.com> writes:
>>
>>>>>> ARM world is also moving towards that by standardizing some of these
>>>>>> through (read PSCI) and thats the way to go in general.
>>>>>
>>>>> Agreed, but I'm not sure (yet) about enforcing PSCI on legacy platforms
>>>>> that don't support it natively.  Are you saying that the AM33xx firmware
>>>>> should be converted to be PSCI compliant?  Admittedly, I haven't read
>>>>> the PSCI spec closely, but I'm wondering if the current role splitting
>>>>> between MPU and M3 fits well with PSCI.
>>>>>
>>>> I didn't mean for the AM3XXX specifically because its current job is rather
>>>> very limited. i.e suspend. My concern is that IPC is not viewed as
>>>> an option for power management controllers like M3 which can abstract
>>>> all the hardware gory details and export a simpled interface for OS
>>>> in form of PSCI/ACPI.
>>>
>>> The IPC between the M3 and the A8 on the am335x is just a pair of
>>> notification mechanisms (one from the A8, mailbox, and one from the
>>> M3, sev) and a set of 8 32 bit registers. The 8 32 bit registers are
>>> just a scratchpad and have no access rules or functionality beyond
>>> being a scratchpad. How complicated do we want to make this?
>>
>> The OMAP IPC between the MPU and DSP (read: any other remote processor)
>> is just a mailbox and some shared memory.  No complicated, and works
>> with remoteproc/rpmsg.
>
> I had to catch up on all the threads before I responded, but here are my
> notes regarding using remoteproc/rpmsg infrastructure for WkupM3. It
> definitely brings in lot more complexity than what's present today. The
> WkupM3 in AM335x does not have the same feature set as the Cortex-M3s
> used within the IPU in OMAP4+ SoCs. It does not have an MMU and
> peripheral accesses seems to be limited to just those in L4_Wkup domain.
>
> A lot actually depends on whether the WkupM3 can use DDR. I am not sure
> if there are any restrictions on WkupM3 from where it could run the code
> or access data from. From what I can gather from the TRM (there's no big
> separate chapter on WkupM3), it has just 16K UMEM and a 8K DMEM, and its
> not much. The current firmware is loaded directly into the WkupM3's
> internal UMem space and a check is being performed to make sure the
> firmware is less than  16K, so that it can fit into UMem.

Even if the WkupM3 could access DMEM, it would defeat the whole
purpose of using it, as it lives to do things like enable VTP, but the
EMIF clocks into bypass, turn off the power domain the EMIF is
contained in, etc.

> The remoteproc infrastructure is currently tied closely with the
> virtio/rpmsg framework, and the boot requires that there are virtio
> devices present in the resource table from the firmware image. The rpmsg
> shared memory buffers are currently kinda fixed (512 buffers of 512
> bytes each) and requires 3 pages just for the vring structures for this
> many buffers. So, if there are restrictions on DDR access, then this
> pretty much rules out remoteproc/rpmsg infrastructure.
>
> If the DDR access is ok, then there are other challenges that needs to
> be met. The current firmware definitely requires the addition of the
> resource table and the lower level code for handling the virtio_ring
> transport for receiving messages. It would also need its own remoteproc
> driver for handling the firmware binary format and the signalling
> required to trigger the rpmsg buffer processing. The firmware binary
> format needs to be adapted to something that this driver would
> understand. It definitely doesn't look like ELF currently, so something
> on the lines of ste_modem_rproc needs to be done. Also, the
> remoteproc/rpmsg infrastructure can support multiple vring transport
> channels between the processor, and depending on how many are supported,
> we either need to exchange the vq_id (like OMAP remoteproc), or process
> the known virtqueues always (like DA8xx remoteproc). The former requires
> that a message payload is used, and mandates the usage of the IPC data
> registers in the control module given that WkupM3 on AM335 cannot access
> any mailbox registers. Any usage of IPC data registers depends on where
> we do it. If all the accesses were to be done within
> mach-omap2/control.c, then there is no easy way for using this API from
> drivers/remoteproc, until we have the control module driver. I do feel
> that this needs to be done within the wkup_m3 driver currently. This
> would be no different to the crossbar driver example on DRA7, which also
> has to deal with registers in Control module. The IPC data registers do
> not have any associated interrupts by itself, so just making this a
> standalone driver is also not possible. Also, the dependencies with
> using the omap_device API for dealing with the hard reset lines needs to
> be dealt with.
>
> The current communication uses the IPC data registers, and sometimes
> uses them as plain status registers. There's certain registers used for
> sharing status, version etc which are shared by both the processors.
> Using rpmsg would require communicating every single message, and if
> there were to be some shared variables to be used simultaneously, then
> this has to be exchanged through a new remoteproc resource type.
>
> One additional aspect is that the current remoteproc core does not have
> the necessary runtime pm support, but in general the approach would be
> to treat the remoteprocs as true slave devices. I would imagine the
> driver core to put the remoteprocs into reset state, after asking them
> to save their context during suspend.
>
> regards
> Suman
>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-08-06 17:49 ` Dave Gerlach
@ 2013-08-19  9:23   ` Gururaja Hebbar
  -1 siblings, 0 replies; 212+ messages in thread
From: Gururaja Hebbar @ 2013-08-19  9:23 UTC (permalink / raw)
  To: Dave Gerlach; +Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman

On 8/6/2013 11:19 PM, Dave Gerlach wrote:
> Hi,
> 
> This is the third version of the patch series for adding basic suspend-resume
> support for AM33XX, previously submitted by Vaibhav Bedia. This patchset 
> is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
> that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are 
> required for the pm code to properly suspend and resume.
> 
> The PM code uses the firmware interface and expects the userspace to load 
> the WKUP_M3 binary before the suspend-resume functionality is made available.
> The binary file (and the source-code for WKUP_M3) can be obtained from the 
> 'next2' branch at [4]. The WKUP_M3 binary can either be loaded post bootup 
> via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be 
> included in the kernel image as part of the build process.
> 
> Suspend to mem is tested on am335x-bone and am335x-evm.
> 
> More details on AM335x suspend-resume are provided within the commit logs
> for each patch.

can you share the working repo which has all these patches applied?

Thanks & Regards
Gururaja

> 
> Changes in v3:
> - Moved wkup_m3 code into separate driver
> - Split up ti_emif header move
> - Addressed clean-up comments
> - Removed mailbox patches
> - v2-v3 Discussion:
> http://marc.info/?l=linux-arm-kernel&m=135698501821090&w=4
> 
> Changes in v2:
> - Broke patches up to isolate assembly code and build hookup.
> - Moved control module code to separate module
> - v1->v2 Discussion:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2012-November/129508.html
> 
> Regards,
> Dave
> 
> [1] http://marc.info/?l=linux-arm-kernel&m=137303736714638&w=4
> [2] http://marc.info/?l=linux-omap&m=137303723114610&w=4
> [3] http://marc.info/?l=linux-omap&m=137401384611934&w=4
> [4] http://arago-project.org/git/projects/?p=am33x-cm3.git;a=shortlog;h=refs/heads/next2
> 
> 
> Dave Gerlach (1):
>   memory: emif: Move EMIF register defines to include/linux/
> 
> Vaibhav Bedia (8):
>   ARM: OMAP2+: AM33XX: control: Add some control module registers and
>     APIs
>   ARM: OMAP: DTB: Update IRQ data for WKUP_M3
>   ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
>   ARM: OMAP2+: AM33XX: Add assembly code for PM operations
>   ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device
>   ARM: OMAP: omap_device: Add APIs to enable and idle hwmods
>   ARM: OMAP2+: AM33XX: Basic suspend resume support
>   ARM: OMAP2+: AM33XX: Hookup AM33XX PM code into OMAP builds
> 
>  arch/arm/boot/dts/am33xx.dtsi       |    1 +
>  arch/arm/mach-omap2/Kconfig         |    7 +-
>  arch/arm/mach-omap2/Makefile        |    2 +
>  arch/arm/mach-omap2/board-generic.c |    3 +-
>  arch/arm/mach-omap2/common.c        |   28 ++
>  arch/arm/mach-omap2/common.h        |   14 +
>  arch/arm/mach-omap2/control.c       |   57 ++++
>  arch/arm/mach-omap2/control.h       |   54 ++++
>  arch/arm/mach-omap2/io.c            |    6 +
>  arch/arm/mach-omap2/omap_device.c   |    8 +
>  arch/arm/mach-omap2/omap_device.h   |    2 +
>  arch/arm/mach-omap2/pm.c            |    3 +-
>  arch/arm/mach-omap2/pm.h            |    5 +
>  arch/arm/mach-omap2/pm33xx.c        |  474 +++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/pm33xx.h        |   77 +++++
>  arch/arm/mach-omap2/sleep33xx.S     |  350 ++++++++++++++++++++++
>  arch/arm/mach-omap2/sram.c          |   10 +-
>  arch/arm/mach-omap2/sram.h          |    2 +
>  arch/arm/mach-omap2/timer.c         |   32 ++
>  arch/arm/mach-omap2/wkup_m3.c       |  183 ++++++++++++
>  drivers/memory/emif.h               |  543 +---------------------------------
>  include/linux/ti_emif.h             |  558 +++++++++++++++++++++++++++++++++++
>  22 files changed, 1872 insertions(+), 547 deletions(-)
>  create mode 100644 arch/arm/mach-omap2/pm33xx.c
>  create mode 100644 arch/arm/mach-omap2/pm33xx.h
>  create mode 100644 arch/arm/mach-omap2/sleep33xx.S
>  create mode 100644 arch/arm/mach-omap2/wkup_m3.c
>  create mode 100644 include/linux/ti_emif.h
> 


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-08-19  9:23   ` Gururaja Hebbar
  0 siblings, 0 replies; 212+ messages in thread
From: Gururaja Hebbar @ 2013-08-19  9:23 UTC (permalink / raw)
  To: linux-arm-kernel

On 8/6/2013 11:19 PM, Dave Gerlach wrote:
> Hi,
> 
> This is the third version of the patch series for adding basic suspend-resume
> support for AM33XX, previously submitted by Vaibhav Bedia. This patchset 
> is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
> that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are 
> required for the pm code to properly suspend and resume.
> 
> The PM code uses the firmware interface and expects the userspace to load 
> the WKUP_M3 binary before the suspend-resume functionality is made available.
> The binary file (and the source-code for WKUP_M3) can be obtained from the 
> 'next2' branch at [4]. The WKUP_M3 binary can either be loaded post bootup 
> via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be 
> included in the kernel image as part of the build process.
> 
> Suspend to mem is tested on am335x-bone and am335x-evm.
> 
> More details on AM335x suspend-resume are provided within the commit logs
> for each patch.

can you share the working repo which has all these patches applied?

Thanks & Regards
Gururaja

> 
> Changes in v3:
> - Moved wkup_m3 code into separate driver
> - Split up ti_emif header move
> - Addressed clean-up comments
> - Removed mailbox patches
> - v2-v3 Discussion:
> http://marc.info/?l=linux-arm-kernel&m=135698501821090&w=4
> 
> Changes in v2:
> - Broke patches up to isolate assembly code and build hookup.
> - Moved control module code to separate module
> - v1->v2 Discussion:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2012-November/129508.html
> 
> Regards,
> Dave
> 
> [1] http://marc.info/?l=linux-arm-kernel&m=137303736714638&w=4
> [2] http://marc.info/?l=linux-omap&m=137303723114610&w=4
> [3] http://marc.info/?l=linux-omap&m=137401384611934&w=4
> [4] http://arago-project.org/git/projects/?p=am33x-cm3.git;a=shortlog;h=refs/heads/next2
> 
> 
> Dave Gerlach (1):
>   memory: emif: Move EMIF register defines to include/linux/
> 
> Vaibhav Bedia (8):
>   ARM: OMAP2+: AM33XX: control: Add some control module registers and
>     APIs
>   ARM: OMAP: DTB: Update IRQ data for WKUP_M3
>   ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
>   ARM: OMAP2+: AM33XX: Add assembly code for PM operations
>   ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device
>   ARM: OMAP: omap_device: Add APIs to enable and idle hwmods
>   ARM: OMAP2+: AM33XX: Basic suspend resume support
>   ARM: OMAP2+: AM33XX: Hookup AM33XX PM code into OMAP builds
> 
>  arch/arm/boot/dts/am33xx.dtsi       |    1 +
>  arch/arm/mach-omap2/Kconfig         |    7 +-
>  arch/arm/mach-omap2/Makefile        |    2 +
>  arch/arm/mach-omap2/board-generic.c |    3 +-
>  arch/arm/mach-omap2/common.c        |   28 ++
>  arch/arm/mach-omap2/common.h        |   14 +
>  arch/arm/mach-omap2/control.c       |   57 ++++
>  arch/arm/mach-omap2/control.h       |   54 ++++
>  arch/arm/mach-omap2/io.c            |    6 +
>  arch/arm/mach-omap2/omap_device.c   |    8 +
>  arch/arm/mach-omap2/omap_device.h   |    2 +
>  arch/arm/mach-omap2/pm.c            |    3 +-
>  arch/arm/mach-omap2/pm.h            |    5 +
>  arch/arm/mach-omap2/pm33xx.c        |  474 +++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/pm33xx.h        |   77 +++++
>  arch/arm/mach-omap2/sleep33xx.S     |  350 ++++++++++++++++++++++
>  arch/arm/mach-omap2/sram.c          |   10 +-
>  arch/arm/mach-omap2/sram.h          |    2 +
>  arch/arm/mach-omap2/timer.c         |   32 ++
>  arch/arm/mach-omap2/wkup_m3.c       |  183 ++++++++++++
>  drivers/memory/emif.h               |  543 +---------------------------------
>  include/linux/ti_emif.h             |  558 +++++++++++++++++++++++++++++++++++
>  22 files changed, 1872 insertions(+), 547 deletions(-)
>  create mode 100644 arch/arm/mach-omap2/pm33xx.c
>  create mode 100644 arch/arm/mach-omap2/pm33xx.h
>  create mode 100644 arch/arm/mach-omap2/sleep33xx.S
>  create mode 100644 arch/arm/mach-omap2/wkup_m3.c
>  create mode 100644 include/linux/ti_emif.h
> 

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 5/9] ARM: OMAP2+: AM33XX: Add assembly code for PM operations
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-19 12:54     ` Gururaja Hebbar
  -1 siblings, 0 replies; 212+ messages in thread
From: Gururaja Hebbar @ 2013-08-19 12:54 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman,
	Vaibhav Bedia, Santosh Shilimkar

Hi,

On 8/6/2013 11:19 PM, Dave Gerlach wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
> 
> In preparation for suspend-resume support for AM33XX, add
> the assembly file with the code which is copied to internal
> memory (OCMC RAM) during bootup and runs from there.
> 
> As part of the low power entry (DeepSleep0 mode in AM33XX TRM),
> the code running from OCMC RAM does the following
> 1. Stores the EMIF configuration
> 2. Puts external memory in self-refresh
> 3. Disables EMIF clock
> 4. Executes WFI after writing to MPU_CLKCTRL register.
> 

...snip...
...snip...


> +	ldr	r1, [r0, #EMIF_DDR_PHY_CTRL_1]
> +	str	r1, emif_rd_lat_val
> +
> +	/* Put SDRAM in self-refresh */
> +	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +	orr	r1, r1, #0xa0
> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
> +	str	r1, [r0, #4]

This seems to be a bug which I had pointed out to VB earlier.

r0 ---> base of emif module

r0 + 4 ---> EMIF4_0_SDRAM_STATUS   ===> which is read only register


Above 2 lines should be as below

+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]


It works even with the bug because the Shadow register is updated and
that some how seems to take precedence.


Thanks & regards
Gururaja


> +
> +	ldr	r1, dram_sync_word	@ a dummy access to DDR as per spec
> +	ldr	r2, [r1, #0]


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 5/9] ARM: OMAP2+: AM33XX: Add assembly code for PM operations
@ 2013-08-19 12:54     ` Gururaja Hebbar
  0 siblings, 0 replies; 212+ messages in thread
From: Gururaja Hebbar @ 2013-08-19 12:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 8/6/2013 11:19 PM, Dave Gerlach wrote:
> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
> 
> In preparation for suspend-resume support for AM33XX, add
> the assembly file with the code which is copied to internal
> memory (OCMC RAM) during bootup and runs from there.
> 
> As part of the low power entry (DeepSleep0 mode in AM33XX TRM),
> the code running from OCMC RAM does the following
> 1. Stores the EMIF configuration
> 2. Puts external memory in self-refresh
> 3. Disables EMIF clock
> 4. Executes WFI after writing to MPU_CLKCTRL register.
> 

...snip...
...snip...


> +	ldr	r1, [r0, #EMIF_DDR_PHY_CTRL_1]
> +	str	r1, emif_rd_lat_val
> +
> +	/* Put SDRAM in self-refresh */
> +	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +	orr	r1, r1, #0xa0
> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
> +	str	r1, [r0, #4]

This seems to be a bug which I had pointed out to VB earlier.

r0 ---> base of emif module

r0 + 4 ---> EMIF4_0_SDRAM_STATUS   ===> which is read only register


Above 2 lines should be as below

+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]


It works even with the bug because the Shadow register is updated and
that some how seems to take precedence.


Thanks & regards
Gururaja


> +
> +	ldr	r1, dram_sync_word	@ a dummy access to DDR as per spec
> +	ldr	r2, [r1, #0]

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-08-19  9:23   ` Gururaja Hebbar
@ 2013-08-19 17:47     ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-19 17:47 UTC (permalink / raw)
  To: Gururaja Hebbar; +Cc: Kevin Hilman, Paul Walmsley, linux-omap, linux-arm-kernel

On 08/19/2013 04:23 AM, Gururaja Hebbar wrote:
> On 8/6/2013 11:19 PM, Dave Gerlach wrote:
>> Hi,
>>
>> This is the third version of the patch series for adding basic suspend-resume
>> support for AM33XX, previously submitted by Vaibhav Bedia. This patchset
>> is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
>> that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are
>> required for the pm code to properly suspend and resume.
>>
>> The PM code uses the firmware interface and expects the userspace to load
>> the WKUP_M3 binary before the suspend-resume functionality is made available.
>> The binary file (and the source-code for WKUP_M3) can be obtained from the
>> 'next2' branch at [4]. The WKUP_M3 binary can either be loaded post bootup
>> via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be
>> included in the kernel image as part of the build process.
>>
>> Suspend to mem is tested on am335x-bone and am335x-evm.
>>
>> More details on AM335x suspend-resume are provided within the commit logs
>> for each patch.
>
> can you share the working repo which has all these patches applied?
>
> Thanks & Regards
> Gururaja
>

The working repo for this version of the patch series can be found here:

git://github.com/dgerlach/linux-pm.git am335x-3.11rc4-suspend-resume

Regards,
Dave

>>
>> Changes in v3:
>> - Moved wkup_m3 code into separate driver
>> - Split up ti_emif header move
>> - Addressed clean-up comments
>> - Removed mailbox patches
>> - v2-v3 Discussion:
>> http://marc.info/?l=linux-arm-kernel&m=135698501821090&w=4
>>
>> Changes in v2:
>> - Broke patches up to isolate assembly code and build hookup.
>> - Moved control module code to separate module
>> - v1->v2 Discussion:
>> http://lists.infradead.org/pipermail/linux-arm-kernel/2012-November/129508.html
>>
>> Regards,
>> Dave
>>
>> [1] http://marc.info/?l=linux-arm-kernel&m=137303736714638&w=4
>> [2] http://marc.info/?l=linux-omap&m=137303723114610&w=4
>> [3] http://marc.info/?l=linux-omap&m=137401384611934&w=4
>> [4] http://arago-project.org/git/projects/?p=am33x-cm3.git;a=shortlog;h=refs/heads/next2
>>
>>
>> Dave Gerlach (1):
>>    memory: emif: Move EMIF register defines to include/linux/
>>
>> Vaibhav Bedia (8):
>>    ARM: OMAP2+: AM33XX: control: Add some control module registers and
>>      APIs
>>    ARM: OMAP: DTB: Update IRQ data for WKUP_M3
>>    ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
>>    ARM: OMAP2+: AM33XX: Add assembly code for PM operations
>>    ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device
>>    ARM: OMAP: omap_device: Add APIs to enable and idle hwmods
>>    ARM: OMAP2+: AM33XX: Basic suspend resume support
>>    ARM: OMAP2+: AM33XX: Hookup AM33XX PM code into OMAP builds
>>
>>   arch/arm/boot/dts/am33xx.dtsi       |    1 +
>>   arch/arm/mach-omap2/Kconfig         |    7 +-
>>   arch/arm/mach-omap2/Makefile        |    2 +
>>   arch/arm/mach-omap2/board-generic.c |    3 +-
>>   arch/arm/mach-omap2/common.c        |   28 ++
>>   arch/arm/mach-omap2/common.h        |   14 +
>>   arch/arm/mach-omap2/control.c       |   57 ++++
>>   arch/arm/mach-omap2/control.h       |   54 ++++
>>   arch/arm/mach-omap2/io.c            |    6 +
>>   arch/arm/mach-omap2/omap_device.c   |    8 +
>>   arch/arm/mach-omap2/omap_device.h   |    2 +
>>   arch/arm/mach-omap2/pm.c            |    3 +-
>>   arch/arm/mach-omap2/pm.h            |    5 +
>>   arch/arm/mach-omap2/pm33xx.c        |  474 +++++++++++++++++++++++++++++
>>   arch/arm/mach-omap2/pm33xx.h        |   77 +++++
>>   arch/arm/mach-omap2/sleep33xx.S     |  350 ++++++++++++++++++++++
>>   arch/arm/mach-omap2/sram.c          |   10 +-
>>   arch/arm/mach-omap2/sram.h          |    2 +
>>   arch/arm/mach-omap2/timer.c         |   32 ++
>>   arch/arm/mach-omap2/wkup_m3.c       |  183 ++++++++++++
>>   drivers/memory/emif.h               |  543 +---------------------------------
>>   include/linux/ti_emif.h             |  558 +++++++++++++++++++++++++++++++++++
>>   22 files changed, 1872 insertions(+), 547 deletions(-)
>>   create mode 100644 arch/arm/mach-omap2/pm33xx.c
>>   create mode 100644 arch/arm/mach-omap2/pm33xx.h
>>   create mode 100644 arch/arm/mach-omap2/sleep33xx.S
>>   create mode 100644 arch/arm/mach-omap2/wkup_m3.c
>>   create mode 100644 include/linux/ti_emif.h
>>
>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-08-19 17:47     ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-19 17:47 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/19/2013 04:23 AM, Gururaja Hebbar wrote:
> On 8/6/2013 11:19 PM, Dave Gerlach wrote:
>> Hi,
>>
>> This is the third version of the patch series for adding basic suspend-resume
>> support for AM33XX, previously submitted by Vaibhav Bedia. This patchset
>> is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
>> that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are
>> required for the pm code to properly suspend and resume.
>>
>> The PM code uses the firmware interface and expects the userspace to load
>> the WKUP_M3 binary before the suspend-resume functionality is made available.
>> The binary file (and the source-code for WKUP_M3) can be obtained from the
>> 'next2' branch at [4]. The WKUP_M3 binary can either be loaded post bootup
>> via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be
>> included in the kernel image as part of the build process.
>>
>> Suspend to mem is tested on am335x-bone and am335x-evm.
>>
>> More details on AM335x suspend-resume are provided within the commit logs
>> for each patch.
>
> can you share the working repo which has all these patches applied?
>
> Thanks & Regards
> Gururaja
>

The working repo for this version of the patch series can be found here:

git://github.com/dgerlach/linux-pm.git am335x-3.11rc4-suspend-resume

Regards,
Dave

>>
>> Changes in v3:
>> - Moved wkup_m3 code into separate driver
>> - Split up ti_emif header move
>> - Addressed clean-up comments
>> - Removed mailbox patches
>> - v2-v3 Discussion:
>> http://marc.info/?l=linux-arm-kernel&m=135698501821090&w=4
>>
>> Changes in v2:
>> - Broke patches up to isolate assembly code and build hookup.
>> - Moved control module code to separate module
>> - v1->v2 Discussion:
>> http://lists.infradead.org/pipermail/linux-arm-kernel/2012-November/129508.html
>>
>> Regards,
>> Dave
>>
>> [1] http://marc.info/?l=linux-arm-kernel&m=137303736714638&w=4
>> [2] http://marc.info/?l=linux-omap&m=137303723114610&w=4
>> [3] http://marc.info/?l=linux-omap&m=137401384611934&w=4
>> [4] http://arago-project.org/git/projects/?p=am33x-cm3.git;a=shortlog;h=refs/heads/next2
>>
>>
>> Dave Gerlach (1):
>>    memory: emif: Move EMIF register defines to include/linux/
>>
>> Vaibhav Bedia (8):
>>    ARM: OMAP2+: AM33XX: control: Add some control module registers and
>>      APIs
>>    ARM: OMAP: DTB: Update IRQ data for WKUP_M3
>>    ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec
>>    ARM: OMAP2+: AM33XX: Add assembly code for PM operations
>>    ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device
>>    ARM: OMAP: omap_device: Add APIs to enable and idle hwmods
>>    ARM: OMAP2+: AM33XX: Basic suspend resume support
>>    ARM: OMAP2+: AM33XX: Hookup AM33XX PM code into OMAP builds
>>
>>   arch/arm/boot/dts/am33xx.dtsi       |    1 +
>>   arch/arm/mach-omap2/Kconfig         |    7 +-
>>   arch/arm/mach-omap2/Makefile        |    2 +
>>   arch/arm/mach-omap2/board-generic.c |    3 +-
>>   arch/arm/mach-omap2/common.c        |   28 ++
>>   arch/arm/mach-omap2/common.h        |   14 +
>>   arch/arm/mach-omap2/control.c       |   57 ++++
>>   arch/arm/mach-omap2/control.h       |   54 ++++
>>   arch/arm/mach-omap2/io.c            |    6 +
>>   arch/arm/mach-omap2/omap_device.c   |    8 +
>>   arch/arm/mach-omap2/omap_device.h   |    2 +
>>   arch/arm/mach-omap2/pm.c            |    3 +-
>>   arch/arm/mach-omap2/pm.h            |    5 +
>>   arch/arm/mach-omap2/pm33xx.c        |  474 +++++++++++++++++++++++++++++
>>   arch/arm/mach-omap2/pm33xx.h        |   77 +++++
>>   arch/arm/mach-omap2/sleep33xx.S     |  350 ++++++++++++++++++++++
>>   arch/arm/mach-omap2/sram.c          |   10 +-
>>   arch/arm/mach-omap2/sram.h          |    2 +
>>   arch/arm/mach-omap2/timer.c         |   32 ++
>>   arch/arm/mach-omap2/wkup_m3.c       |  183 ++++++++++++
>>   drivers/memory/emif.h               |  543 +---------------------------------
>>   include/linux/ti_emif.h             |  558 +++++++++++++++++++++++++++++++++++
>>   22 files changed, 1872 insertions(+), 547 deletions(-)
>>   create mode 100644 arch/arm/mach-omap2/pm33xx.c
>>   create mode 100644 arch/arm/mach-omap2/pm33xx.h
>>   create mode 100644 arch/arm/mach-omap2/sleep33xx.S
>>   create mode 100644 arch/arm/mach-omap2/wkup_m3.c
>>   create mode 100644 include/linux/ti_emif.h
>>
>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 5/9] ARM: OMAP2+: AM33XX: Add assembly code for PM operations
  2013-08-19 12:54     ` Gururaja Hebbar
@ 2013-08-19 17:51       ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-19 17:51 UTC (permalink / raw)
  To: Gururaja Hebbar
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Kevin Hilman,
	Vaibhav Bedia, Santosh Shilimkar

On 08/19/2013 07:54 AM, Gururaja Hebbar wrote:
> Hi,
>
> On 8/6/2013 11:19 PM, Dave Gerlach wrote:
>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>
>> In preparation for suspend-resume support for AM33XX, add
>> the assembly file with the code which is copied to internal
>> memory (OCMC RAM) during bootup and runs from there.
>>
>> As part of the low power entry (DeepSleep0 mode in AM33XX TRM),
>> the code running from OCMC RAM does the following
>> 1. Stores the EMIF configuration
>> 2. Puts external memory in self-refresh
>> 3. Disables EMIF clock
>> 4. Executes WFI after writing to MPU_CLKCTRL register.
>>
>
> ...snip...
> ...snip...
>
>
>> +	ldr	r1, [r0, #EMIF_DDR_PHY_CTRL_1]
>> +	str	r1, emif_rd_lat_val
>> +
>> +	/* Put SDRAM in self-refresh */
>> +	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
>> +	orr	r1, r1, #0xa0
>> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
>> +	str	r1, [r0, #4]
>
> This seems to be a bug which I had pointed out to VB earlier.
>
> r0 ---> base of emif module
>
> r0 + 4 ---> EMIF4_0_SDRAM_STATUS   ===> which is read only register
>
>
> Above 2 lines should be as below
>
> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
>
>
> It works even with the bug because the Shadow register is updated and
> that some how seems to take precedence.
>
>
> Thanks & regards
> Gururaja
>

Thanks for pointing this out, I have fixed it for next version.

Regards,
Dave

>
>> +
>> +	ldr	r1, dram_sync_word	@ a dummy access to DDR as per spec
>> +	ldr	r2, [r1, #0]
>


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 5/9] ARM: OMAP2+: AM33XX: Add assembly code for PM operations
@ 2013-08-19 17:51       ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-19 17:51 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/19/2013 07:54 AM, Gururaja Hebbar wrote:
> Hi,
>
> On 8/6/2013 11:19 PM, Dave Gerlach wrote:
>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>
>> In preparation for suspend-resume support for AM33XX, add
>> the assembly file with the code which is copied to internal
>> memory (OCMC RAM) during bootup and runs from there.
>>
>> As part of the low power entry (DeepSleep0 mode in AM33XX TRM),
>> the code running from OCMC RAM does the following
>> 1. Stores the EMIF configuration
>> 2. Puts external memory in self-refresh
>> 3. Disables EMIF clock
>> 4. Executes WFI after writing to MPU_CLKCTRL register.
>>
>
> ...snip...
> ...snip...
>
>
>> +	ldr	r1, [r0, #EMIF_DDR_PHY_CTRL_1]
>> +	str	r1, emif_rd_lat_val
>> +
>> +	/* Put SDRAM in self-refresh */
>> +	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
>> +	orr	r1, r1, #0xa0
>> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
>> +	str	r1, [r0, #4]
>
> This seems to be a bug which I had pointed out to VB earlier.
>
> r0 ---> base of emif module
>
> r0 + 4 ---> EMIF4_0_SDRAM_STATUS   ===> which is read only register
>
>
> Above 2 lines should be as below
>
> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
> +	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
>
>
> It works even with the bug because the Shadow register is updated and
> that some how seems to take precedence.
>
>
> Thanks & regards
> Gururaja
>

Thanks for pointing this out, I have fixed it for next version.

Regards,
Dave

>
>> +
>> +	ldr	r1, dram_sync_word	@ a dummy access to DDR as per spec
>> +	ldr	r2, [r1, #0]
>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-08 21:14             ` Kevin Hilman
@ 2013-08-20 22:48               ` Paul Walmsley
  -1 siblings, 0 replies; 212+ messages in thread
From: Paul Walmsley @ 2013-08-20 22:48 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: Kevin Hilman, Santosh Shilimkar, Nishanth Menon, Russ Dill,
	linux-arm-kernel, linux-omap, Vaibhav Bedia, Tony Lingren,
	Benoit Cousson


Hi folks,

catching up on this thread.

On 08/06/2013 12:49 PM, Dave Gerlach wrote:

> +
> +static int am33xx_pm_suspend(void)
> +{
> +     int i, j, ret = 0;
> +
> +     int status = 0;
> +     struct platform_device *pdev;
> +     struct omap_device *od;
> +
> +     /*
> +      * By default the following IPs do not have MSTANDBY asserted
> +      * which is necessary for PER domain transition. If the drivers
> +      * are not compiled into the kernel HWMOD code will not change the
> +      * state of the IPs if the IP was not never enabled. To ensure
> +      * that there no issues with or without the drivers being compiled
> +      * in the kernel, we forcefully put these IPs to idle.
> +      */
> +     for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++) {
> +             pdev = to_platform_device(am33xx_mod[i].dev);
> +             od = to_omap_device(pdev);
> +             if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
> +                     omap_device_enable_hwmods(od);
> +                     omap_device_idle_hwmods(od);
> +             }
> +     }

Does this have to be done for every suspend entry, or can it just be done 
once during kernel initialization?

If the latter, shouldn't this be done by hwmod during the initial reset 
and idle of all of these devices, based on a flag?  For example, we had 
this flag for OMAP3630:

 * HWMOD_FORCE_MSTANDBY: Always keep MIDLEMODE bits cleared so that device
 *     is kept in force-standby mode. Failing to do so causes PM problems
 *     with musb on OMAP3630 at least. Note that musb has a dedicated 
register
 *     to control MSTANDBY signal when MIDLEMODE is set to force-standby.


- Paul

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-20 22:48               ` Paul Walmsley
  0 siblings, 0 replies; 212+ messages in thread
From: Paul Walmsley @ 2013-08-20 22:48 UTC (permalink / raw)
  To: linux-arm-kernel


Hi folks,

catching up on this thread.

On 08/06/2013 12:49 PM, Dave Gerlach wrote:

> +
> +static int am33xx_pm_suspend(void)
> +{
> +     int i, j, ret = 0;
> +
> +     int status = 0;
> +     struct platform_device *pdev;
> +     struct omap_device *od;
> +
> +     /*
> +      * By default the following IPs do not have MSTANDBY asserted
> +      * which is necessary for PER domain transition. If the drivers
> +      * are not compiled into the kernel HWMOD code will not change the
> +      * state of the IPs if the IP was not never enabled. To ensure
> +      * that there no issues with or without the drivers being compiled
> +      * in the kernel, we forcefully put these IPs to idle.
> +      */
> +     for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++) {
> +             pdev = to_platform_device(am33xx_mod[i].dev);
> +             od = to_omap_device(pdev);
> +             if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
> +                     omap_device_enable_hwmods(od);
> +                     omap_device_idle_hwmods(od);
> +             }
> +     }

Does this have to be done for every suspend entry, or can it just be done 
once during kernel initialization?

If the latter, shouldn't this be done by hwmod during the initial reset 
and idle of all of these devices, based on a flag?  For example, we had 
this flag for OMAP3630:

 * HWMOD_FORCE_MSTANDBY: Always keep MIDLEMODE bits cleared so that device
 *     is kept in force-standby mode. Failing to do so causes PM problems
 *     with musb on OMAP3630 at least. Note that musb has a dedicated 
register
 *     to control MSTANDBY signal when MIDLEMODE is set to force-standby.


- Paul

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-14 17:27                             ` Suman Anna
@ 2013-08-20 23:39                               ` Paul Walmsley
  -1 siblings, 0 replies; 212+ messages in thread
From: Paul Walmsley @ 2013-08-20 23:39 UTC (permalink / raw)
  To: Suman Anna
  Cc: Kevin Hilman, Russ Dill, Santosh Shilimkar, Ohad Ben-Cohen,
	Dave Gerlach, Tony Lindgren, Vaibhav Bedia, linux-omap,
	linux-arm-kernel

Hi

a few comments

On Wed, 14 Aug 2013, Suman Anna wrote:

> The remoteproc infrastructure is currently tied closely with the
> virtio/rpmsg framework, and the boot requires that there are virtio
> devices present in the resource table from the firmware image.

Using static channels is something that can be added to the existing code, 
if you don't want to use dynamic channels.

> The rpmsg shared memory buffers are currently kinda fixed (512 buffers 
> of 512 bytes each) and requires 3 pages just for the vring structures 
> for this many buffers. So, if there are restrictions on DDR access, then 
> this pretty much rules out remoteproc/rpmsg infrastructure.

It should be possible to patch that code to vary the size and count of the 
memory buffers, based on the remote processor.  So no direct DDR access 
should be required - for that reason, anyway.

> If the DDR access is ok, then there are other challenges that needs to
> be met. The current firmware definitely requires the addition of the
> resource table and the lower level code for handling the virtio_ring
> transport for receiving messages. It would also need its own remoteproc
> driver for handling the firmware binary format 

Hmm, could you explain this further?  Are you just referring to the 
process of parsing out the dynamic channel data during initialization?

> and the signalling required to trigger the rpmsg buffer processing. The 
> firmware binary format needs to be adapted to something that this driver 
> would understand.  It definitely doesn't look like ELF currently, so 
> something on the lines of ste_modem_rproc needs to be done.

Or just use ELF or static channels.

> Also, the remoteproc/rpmsg infrastructure can support multiple vring 
> transport channels between the processor, and depending on how many are 
> supported, we either need to exchange the vq_id (like OMAP remoteproc), 
> or process the known virtqueues always (like DA8xx remoteproc). The 
> former requires that a message payload is used, and mandates the usage 
> of the IPC data registers in the control module given that WkupM3 on 
> AM335 cannot access any mailbox registers. Any usage of IPC data 
> registers depends on where we do it. If all the accesses were to be done 
> within mach-omap2/control.c, then there is no easy way for using this 
> API from drivers/remoteproc, until we have the control module driver.

Yep, real SCM drivers have been needed for some time now, for pretty much 
all of the OMAP SoCs.  It should be pretty easy to prototype for your 
purposes, though.

> The current communication uses the IPC data registers, and sometimes
> uses them as plain status registers. There's certain registers used for
> sharing status, version etc which are shared by both the processors.
> Using rpmsg would require communicating every single message, and if
> there were to be some shared variables to be used simultaneously, then
> this has to be exchanged through a new remoteproc resource type.

I don't quite understand this last part - "shared variables to be used 
simultaneously".  How does the existing code synchronize them?

> One additional aspect is that the current remoteproc core does not have
> the necessary runtime pm support, but in general the approach would be
> to treat the remoteprocs as true slave devices. I would imagine the
> driver core to put the remoteprocs into reset state, after asking them
> to save their context during suspend.

Why is runtime PM support needed in the remoteproc core?  Wouldn't that 
only be needed in the remote processor's device driver?


- Paul

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-20 23:39                               ` Paul Walmsley
  0 siblings, 0 replies; 212+ messages in thread
From: Paul Walmsley @ 2013-08-20 23:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hi

a few comments

On Wed, 14 Aug 2013, Suman Anna wrote:

> The remoteproc infrastructure is currently tied closely with the
> virtio/rpmsg framework, and the boot requires that there are virtio
> devices present in the resource table from the firmware image.

Using static channels is something that can be added to the existing code, 
if you don't want to use dynamic channels.

> The rpmsg shared memory buffers are currently kinda fixed (512 buffers 
> of 512 bytes each) and requires 3 pages just for the vring structures 
> for this many buffers. So, if there are restrictions on DDR access, then 
> this pretty much rules out remoteproc/rpmsg infrastructure.

It should be possible to patch that code to vary the size and count of the 
memory buffers, based on the remote processor.  So no direct DDR access 
should be required - for that reason, anyway.

> If the DDR access is ok, then there are other challenges that needs to
> be met. The current firmware definitely requires the addition of the
> resource table and the lower level code for handling the virtio_ring
> transport for receiving messages. It would also need its own remoteproc
> driver for handling the firmware binary format 

Hmm, could you explain this further?  Are you just referring to the 
process of parsing out the dynamic channel data during initialization?

> and the signalling required to trigger the rpmsg buffer processing. The 
> firmware binary format needs to be adapted to something that this driver 
> would understand.  It definitely doesn't look like ELF currently, so 
> something on the lines of ste_modem_rproc needs to be done.

Or just use ELF or static channels.

> Also, the remoteproc/rpmsg infrastructure can support multiple vring 
> transport channels between the processor, and depending on how many are 
> supported, we either need to exchange the vq_id (like OMAP remoteproc), 
> or process the known virtqueues always (like DA8xx remoteproc). The 
> former requires that a message payload is used, and mandates the usage 
> of the IPC data registers in the control module given that WkupM3 on 
> AM335 cannot access any mailbox registers. Any usage of IPC data 
> registers depends on where we do it. If all the accesses were to be done 
> within mach-omap2/control.c, then there is no easy way for using this 
> API from drivers/remoteproc, until we have the control module driver.

Yep, real SCM drivers have been needed for some time now, for pretty much 
all of the OMAP SoCs.  It should be pretty easy to prototype for your 
purposes, though.

> The current communication uses the IPC data registers, and sometimes
> uses them as plain status registers. There's certain registers used for
> sharing status, version etc which are shared by both the processors.
> Using rpmsg would require communicating every single message, and if
> there were to be some shared variables to be used simultaneously, then
> this has to be exchanged through a new remoteproc resource type.

I don't quite understand this last part - "shared variables to be used 
simultaneously".  How does the existing code synchronize them?

> One additional aspect is that the current remoteproc core does not have
> the necessary runtime pm support, but in general the approach would be
> to treat the remoteprocs as true slave devices. I would imagine the
> driver core to put the remoteprocs into reset state, after asking them
> to save their context during suspend.

Why is runtime PM support needed in the remoteproc core?  Wouldn't that 
only be needed in the remote processor's device driver?


- Paul

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
  2013-08-20 23:39                               ` Paul Walmsley
@ 2013-08-21 17:32                                 ` Suman Anna
  -1 siblings, 0 replies; 212+ messages in thread
From: Suman Anna @ 2013-08-21 17:32 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: Kevin Hilman, Russ Dill, Santosh Shilimkar, Ohad Ben-Cohen,
	Dave Gerlach, Tony Lindgren, Vaibhav Bedia, linux-omap,
	linux-arm-kernel

Paul,

On 08/20/2013 06:39 PM, Paul Walmsley wrote:
> Hi
> 
> a few comments
> 
> On Wed, 14 Aug 2013, Suman Anna wrote:
> 
>> The remoteproc infrastructure is currently tied closely with the
>> virtio/rpmsg framework, and the boot requires that there are virtio
>> devices present in the resource table from the firmware image.
> 
> Using static channels is something that can be added to the existing code, 
> if you don't want to use dynamic channels.

The resource table is used for both indicating the remoteproc resources
as well as allowing the driver to publish the data back so that the
remote processor can configure itself. The virtio devices do have other
configuration fields and this allows the driver to update the status
fields which the remote processor can read. This functionality is
definitely lost if we use static virtio devices.

Also, the remoteproc boot is a two-step process currently. It reads the
virtio device information from the resource table and creates the virtio
devices. The virtio device probe then triggers the remoteproc boot,
which processes the firmware segments and handles the actual processor
boot. The memory for firmware segments are allocated through CMA and the
allocated addresses are published through the resource table to the
remote processor-side. The core definitely needs to be patched up to
support loading internal memory segments.

> 
>> The rpmsg shared memory buffers are currently kinda fixed (512 buffers 
>> of 512 bytes each) and requires 3 pages just for the vring structures 
>> for this many buffers. So, if there are restrictions on DDR access, then 
>> this pretty much rules out remoteproc/rpmsg infrastructure.
> 
> It should be possible to patch that code to vary the size and count of the 
> memory buffers, based on the remote processor.  So no direct DDR access 
> should be required - for that reason, anyway.

Yep, I agree that this needs to be programmable. Support needs to be
added to both the remoteproc and rpmsg cores to deal with internal
memory for the vrings and vring buffers. Currently, it is all allocated
dynamically through CMA. That said, the WkupM3 really has a very small
memory regions, 16K of UMEM and 8K of DMEM. Everything has to fit within
that including the vrings and vring buffers. I have to check if there
are alignment restrictions imposed by the virtio code on the vrings and
if that overshoots the available internal memory.

> 
>> If the DDR access is ok, then there are other challenges that needs to
>> be met. The current firmware definitely requires the addition of the
>> resource table and the lower level code for handling the virtio_ring
>> transport for receiving messages. It would also need its own remoteproc
>> driver for handling the firmware binary format 
> 
> Hmm, could you explain this further?  Are you just referring to the 
> process of parsing out the dynamic channel data during initialization?

Yes, for parsing out where the resource table is. The remoteproc core
provides the necessary hooks for finding the resource table and loading
the firmware segments. If the firmware file is gonna remain a binary
blob, then these hooks need to be implemented for that binary format. No
issues if it were an ELF file, since we expect the resource table to be
present in a special section.

> 
>> and the signalling required to trigger the rpmsg buffer processing. The 
>> firmware binary format needs to be adapted to something that this driver 
>> would understand.  It definitely doesn't look like ELF currently, so 
>> something on the lines of ste_modem_rproc needs to be done.
> 
> Or just use ELF or static channels.

I have taken a look at the firmware tree, and the binary is generated
from an ELF file, so the format is not an issue as long as the memory
footprint is satisfied. static channels is more of an issue as pointed
above.

> 
>> Also, the remoteproc/rpmsg infrastructure can support multiple vring 
>> transport channels between the processor, and depending on how many are 
>> supported, we either need to exchange the vq_id (like OMAP remoteproc), 
>> or process the known virtqueues always (like DA8xx remoteproc). The 
>> former requires that a message payload is used, and mandates the usage 
>> of the IPC data registers in the control module given that WkupM3 on 
>> AM335 cannot access any mailbox registers. Any usage of IPC data 
>> registers depends on where we do it. If all the accesses were to be done 
>> within mach-omap2/control.c, then there is no easy way for using this 
>> API from drivers/remoteproc, until we have the control module driver.
> 
> Yep, real SCM drivers have been needed for some time now, for pretty much 
> all of the OMAP SoCs.  It should be pretty easy to prototype for your 
> purposes, though.
> 
>> The current communication uses the IPC data registers, and sometimes
>> uses them as plain status registers. There's certain registers used for
>> sharing status, version etc which are shared by both the processors.
>> Using rpmsg would require communicating every single message, and if
>> there were to be some shared variables to be used simultaneously, then
>> this has to be exchanged through a new remoteproc resource type.
> 
> I don't quite understand this last part - "shared variables to be used 
> simultaneously".  How does the existing code synchronize them?

The IPC data registers are just like regular registers, values written
in them stay that way until changed. The current PM code uses some of
these registers as fixed status variables, while some of them are
changed based on the state machine, and an interrupt is sent to process
that PM command. The message payload is well within these 8 registers
for the needs of PM.

> 
>> One additional aspect is that the current remoteproc core does not have
>> the necessary runtime pm support, but in general the approach would be
>> to treat the remoteprocs as true slave devices. I would imagine the
>> driver core to put the remoteprocs into reset state, after asking them
>> to save their context during suspend.
> 
> Why is runtime PM support needed in the remoteproc core?  Wouldn't that 
> only be needed in the remote processor's device driver?

The actual low-level operations would be in the remote processor's
device driver, but since the core maintains the overall device
management including loading and state machine, doing it in the core
would be nice as it provides a common base logic (can be implemented
through device type and ops)  instead of replicating it in every device
driver.

regards
Suman

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
@ 2013-08-21 17:32                                 ` Suman Anna
  0 siblings, 0 replies; 212+ messages in thread
From: Suman Anna @ 2013-08-21 17:32 UTC (permalink / raw)
  To: linux-arm-kernel

Paul,

On 08/20/2013 06:39 PM, Paul Walmsley wrote:
> Hi
> 
> a few comments
> 
> On Wed, 14 Aug 2013, Suman Anna wrote:
> 
>> The remoteproc infrastructure is currently tied closely with the
>> virtio/rpmsg framework, and the boot requires that there are virtio
>> devices present in the resource table from the firmware image.
> 
> Using static channels is something that can be added to the existing code, 
> if you don't want to use dynamic channels.

The resource table is used for both indicating the remoteproc resources
as well as allowing the driver to publish the data back so that the
remote processor can configure itself. The virtio devices do have other
configuration fields and this allows the driver to update the status
fields which the remote processor can read. This functionality is
definitely lost if we use static virtio devices.

Also, the remoteproc boot is a two-step process currently. It reads the
virtio device information from the resource table and creates the virtio
devices. The virtio device probe then triggers the remoteproc boot,
which processes the firmware segments and handles the actual processor
boot. The memory for firmware segments are allocated through CMA and the
allocated addresses are published through the resource table to the
remote processor-side. The core definitely needs to be patched up to
support loading internal memory segments.

> 
>> The rpmsg shared memory buffers are currently kinda fixed (512 buffers 
>> of 512 bytes each) and requires 3 pages just for the vring structures 
>> for this many buffers. So, if there are restrictions on DDR access, then 
>> this pretty much rules out remoteproc/rpmsg infrastructure.
> 
> It should be possible to patch that code to vary the size and count of the 
> memory buffers, based on the remote processor.  So no direct DDR access 
> should be required - for that reason, anyway.

Yep, I agree that this needs to be programmable. Support needs to be
added to both the remoteproc and rpmsg cores to deal with internal
memory for the vrings and vring buffers. Currently, it is all allocated
dynamically through CMA. That said, the WkupM3 really has a very small
memory regions, 16K of UMEM and 8K of DMEM. Everything has to fit within
that including the vrings and vring buffers. I have to check if there
are alignment restrictions imposed by the virtio code on the vrings and
if that overshoots the available internal memory.

> 
>> If the DDR access is ok, then there are other challenges that needs to
>> be met. The current firmware definitely requires the addition of the
>> resource table and the lower level code for handling the virtio_ring
>> transport for receiving messages. It would also need its own remoteproc
>> driver for handling the firmware binary format 
> 
> Hmm, could you explain this further?  Are you just referring to the 
> process of parsing out the dynamic channel data during initialization?

Yes, for parsing out where the resource table is. The remoteproc core
provides the necessary hooks for finding the resource table and loading
the firmware segments. If the firmware file is gonna remain a binary
blob, then these hooks need to be implemented for that binary format. No
issues if it were an ELF file, since we expect the resource table to be
present in a special section.

> 
>> and the signalling required to trigger the rpmsg buffer processing. The 
>> firmware binary format needs to be adapted to something that this driver 
>> would understand.  It definitely doesn't look like ELF currently, so 
>> something on the lines of ste_modem_rproc needs to be done.
> 
> Or just use ELF or static channels.

I have taken a look at the firmware tree, and the binary is generated
from an ELF file, so the format is not an issue as long as the memory
footprint is satisfied. static channels is more of an issue as pointed
above.

> 
>> Also, the remoteproc/rpmsg infrastructure can support multiple vring 
>> transport channels between the processor, and depending on how many are 
>> supported, we either need to exchange the vq_id (like OMAP remoteproc), 
>> or process the known virtqueues always (like DA8xx remoteproc). The 
>> former requires that a message payload is used, and mandates the usage 
>> of the IPC data registers in the control module given that WkupM3 on 
>> AM335 cannot access any mailbox registers. Any usage of IPC data 
>> registers depends on where we do it. If all the accesses were to be done 
>> within mach-omap2/control.c, then there is no easy way for using this 
>> API from drivers/remoteproc, until we have the control module driver.
> 
> Yep, real SCM drivers have been needed for some time now, for pretty much 
> all of the OMAP SoCs.  It should be pretty easy to prototype for your 
> purposes, though.
> 
>> The current communication uses the IPC data registers, and sometimes
>> uses them as plain status registers. There's certain registers used for
>> sharing status, version etc which are shared by both the processors.
>> Using rpmsg would require communicating every single message, and if
>> there were to be some shared variables to be used simultaneously, then
>> this has to be exchanged through a new remoteproc resource type.
> 
> I don't quite understand this last part - "shared variables to be used 
> simultaneously".  How does the existing code synchronize them?

The IPC data registers are just like regular registers, values written
in them stay that way until changed. The current PM code uses some of
these registers as fixed status variables, while some of them are
changed based on the state machine, and an interrupt is sent to process
that PM command. The message payload is well within these 8 registers
for the needs of PM.

> 
>> One additional aspect is that the current remoteproc core does not have
>> the necessary runtime pm support, but in general the approach would be
>> to treat the remoteprocs as true slave devices. I would imagine the
>> driver core to put the remoteprocs into reset state, after asking them
>> to save their context during suspend.
> 
> Why is runtime PM support needed in the remoteproc core?  Wouldn't that 
> only be needed in the remote processor's device driver?

The actual low-level operations would be in the remote processor's
device driver, but since the core maintains the overall device
management including loading and state machine, doing it in the core
would be nice as it provides a common base logic (can be implemented
through device type and ops)  instead of replicating it in every device
driver.

regards
Suman

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-20 22:48               ` Paul Walmsley
@ 2013-08-23 14:56                 ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-23 14:56 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: Kevin Hilman, Santosh Shilimkar, Nishanth Menon, Russ Dill,
	linux-arm-kernel, linux-omap, Vaibhav Bedia, Tony Lingren,
	Benoit Cousson

On 08/20/2013 05:48 PM, Paul Walmsley wrote:
>
> Hi folks,
>
> catching up on this thread.
>
> On 08/06/2013 12:49 PM, Dave Gerlach wrote:
>
>> +
>> +static int am33xx_pm_suspend(void)
>> +{
>> +     int i, j, ret = 0;
>> +
>> +     int status = 0;
>> +     struct platform_device *pdev;
>> +     struct omap_device *od;
>> +
>> +     /*
>> +      * By default the following IPs do not have MSTANDBY asserted
>> +      * which is necessary for PER domain transition. If the drivers
>> +      * are not compiled into the kernel HWMOD code will not change the
>> +      * state of the IPs if the IP was not never enabled. To ensure
>> +      * that there no issues with or without the drivers being compiled
>> +      * in the kernel, we forcefully put these IPs to idle.
>> +      */
>> +     for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++) {
>> +             pdev = to_platform_device(am33xx_mod[i].dev);
>> +             od = to_omap_device(pdev);
>> +             if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
>> +                     omap_device_enable_hwmods(od);
>> +                     omap_device_idle_hwmods(od);
>> +             }
>> +     }
>
> Does this have to be done for every suspend entry, or can it just be done
> once during kernel initialization?
>
> If the latter, shouldn't this be done by hwmod during the initial reset
> and idle of all of these devices, based on a flag?  For example, we had
> this flag for OMAP3630:
>
>   * HWMOD_FORCE_MSTANDBY: Always keep MIDLEMODE bits cleared so that device
>   *     is kept in force-standby mode. Failing to do so causes PM problems
>   *     with musb on OMAP3630 at least. Note that musb has a dedicated
> register
>   *     to control MSTANDBY signal when MIDLEMODE is set to force-standby.
>

Hi,
Unfortunately this does have to be done at some point after every 
suspend/resume cycle because while the IPs are idled during initial 
reset, after a suspend cycle the context loss when no driver is bound 
causes MSTANDBY to be unasserted again which as mentioned breaks the PER 
power domain transition during the next suspend attempt.

The current plan for this is somewhat similar to what you mentioned, all 
of the troublesome modules will be flagged in hwmod and when the hwmods 
are loaded they are tracked if no driver gets bound and then idled post 
resume by a pm_notifier.

Regards,
Dave

>
> - Paul
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-23 14:56                 ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-23 14:56 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/20/2013 05:48 PM, Paul Walmsley wrote:
>
> Hi folks,
>
> catching up on this thread.
>
> On 08/06/2013 12:49 PM, Dave Gerlach wrote:
>
>> +
>> +static int am33xx_pm_suspend(void)
>> +{
>> +     int i, j, ret = 0;
>> +
>> +     int status = 0;
>> +     struct platform_device *pdev;
>> +     struct omap_device *od;
>> +
>> +     /*
>> +      * By default the following IPs do not have MSTANDBY asserted
>> +      * which is necessary for PER domain transition. If the drivers
>> +      * are not compiled into the kernel HWMOD code will not change the
>> +      * state of the IPs if the IP was not never enabled. To ensure
>> +      * that there no issues with or without the drivers being compiled
>> +      * in the kernel, we forcefully put these IPs to idle.
>> +      */
>> +     for (i = 0; i < ARRAY_SIZE(am33xx_mod); i++) {
>> +             pdev = to_platform_device(am33xx_mod[i].dev);
>> +             od = to_omap_device(pdev);
>> +             if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
>> +                     omap_device_enable_hwmods(od);
>> +                     omap_device_idle_hwmods(od);
>> +             }
>> +     }
>
> Does this have to be done for every suspend entry, or can it just be done
> once during kernel initialization?
>
> If the latter, shouldn't this be done by hwmod during the initial reset
> and idle of all of these devices, based on a flag?  For example, we had
> this flag for OMAP3630:
>
>   * HWMOD_FORCE_MSTANDBY: Always keep MIDLEMODE bits cleared so that device
>   *     is kept in force-standby mode. Failing to do so causes PM problems
>   *     with musb on OMAP3630 at least. Note that musb has a dedicated
> register
>   *     to control MSTANDBY signal when MIDLEMODE is set to force-standby.
>

Hi,
Unfortunately this does have to be done at some point after every 
suspend/resume cycle because while the IPs are idled during initial 
reset, after a suspend cycle the context loss when no driver is bound 
causes MSTANDBY to be unasserted again which as mentioned breaks the PER 
power domain transition during the next suspend attempt.

The current plan for this is somewhat similar to what you mentioned, all 
of the troublesome modules will be flagged in hwmod and when the hwmods 
are loaded they are tracked if no driver gets bound and then idled post 
resume by a pm_notifier.

Regards,
Dave

>
> - Paul
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-08-19 17:47     ` Dave Gerlach
@ 2013-08-27 20:23       ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-27 20:23 UTC (permalink / raw)
  To: Dave Gerlach; +Cc: Gururaja Hebbar, linux-arm-kernel, linux-omap, Paul Walmsley

Hi Dave,

Dave Gerlach <d-gerlach@ti.com> writes:

> On 08/19/2013 04:23 AM, Gururaja Hebbar wrote:
>> On 8/6/2013 11:19 PM, Dave Gerlach wrote:
>>> Hi,
>>>
>>> This is the third version of the patch series for adding basic suspend-resume
>>> support for AM33XX, previously submitted by Vaibhav Bedia. This patchset
>>> is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
>>> that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are
>>> required for the pm code to properly suspend and resume.
>>>
>>> The PM code uses the firmware interface and expects the userspace to load
>>> the WKUP_M3 binary before the suspend-resume functionality is made available.
>>> The binary file (and the source-code for WKUP_M3) can be obtained from the
>>> 'next2' branch at [4]. The WKUP_M3 binary can either be loaded post bootup
>>> via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be
>>> included in the kernel image as part of the build process.
>>>
>>> Suspend to mem is tested on am335x-bone and am335x-evm.
>>>
>>> More details on AM335x suspend-resume are provided within the commit logs
>>> for each patch.
>>
>> can you share the working repo which has all these patches applied?
>>
>> Thanks & Regards
>> Gururaja
>>
>
> The working repo for this version of the patch series can be found here:
>
> git://github.com/dgerlach/linux-pm.git am335x-3.11rc4-suspend-resume

I tried this branch on my beaglebone black, and it's not fully resuming.
Suspend seems to be working (power draw goes from ~1W to ~130mW) and
pressing a key on the UART seems to be waking up the SoC (power draw
goes to ~600mW) but I don't ever get the console back.

Is there a specific version of the firmware I should be using?

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-08-27 20:23       ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-27 20:23 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Dave,

Dave Gerlach <d-gerlach@ti.com> writes:

> On 08/19/2013 04:23 AM, Gururaja Hebbar wrote:
>> On 8/6/2013 11:19 PM, Dave Gerlach wrote:
>>> Hi,
>>>
>>> This is the third version of the patch series for adding basic suspend-resume
>>> support for AM33XX, previously submitted by Vaibhav Bedia. This patchset
>>> is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
>>> that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are
>>> required for the pm code to properly suspend and resume.
>>>
>>> The PM code uses the firmware interface and expects the userspace to load
>>> the WKUP_M3 binary before the suspend-resume functionality is made available.
>>> The binary file (and the source-code for WKUP_M3) can be obtained from the
>>> 'next2' branch at [4]. The WKUP_M3 binary can either be loaded post bootup
>>> via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be
>>> included in the kernel image as part of the build process.
>>>
>>> Suspend to mem is tested on am335x-bone and am335x-evm.
>>>
>>> More details on AM335x suspend-resume are provided within the commit logs
>>> for each patch.
>>
>> can you share the working repo which has all these patches applied?
>>
>> Thanks & Regards
>> Gururaja
>>
>
> The working repo for this version of the patch series can be found here:
>
> git://github.com/dgerlach/linux-pm.git am335x-3.11rc4-suspend-resume

I tried this branch on my beaglebone black, and it's not fully resuming.
Suspend seems to be working (power draw goes from ~1W to ~130mW) and
pressing a key on the UART seems to be waking up the SoC (power draw
goes to ~600mW) but I don't ever get the console back.

Is there a specific version of the firmware I should be using?

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-06 17:49   ` Dave Gerlach
@ 2013-08-27 21:45     ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-27 21:45 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Vaibhav Bedia,
	Tony Lingren, Santosh Shilimkar, Benoit Cousson

Dave Gerlach <d-gerlach@ti.com> writes:

> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> AM335x supports various low power modes as documented
> in section 8.1.4.3 of the AM335x TRM which is available
> @ http://www.ti.com/litv/pdf/spruh73f
>
> DeepSleep0 mode offers the lowest power mode with limited
> wakeup sources without a system reboot and is mapped as
> the suspend state in the kernel. In this state, MPU and
> PER domains are turned off with the internal RAM held in
> retention to facilitate resume process. As part of the boot
> process, the assembly code is copied over to OCMCRAM using
> the OMAP SRAM code.
>
> AM335x has a Cortex-M3 (WKUP_M3) which assists the MPU
> in DeepSleep0 entry and exit. WKUP_M3 takes care of the
> clockdomain and powerdomain transitions based on the
> intended low power state. MPU needs to load the appropriate
> WKUP_M3 binary onto the WKUP_M3 memory space before it can
> leverage any of the PM features like DeepSleep.
>
> The IPC mechanism between MPU and WKUP_M3 uses a mailbox
> sub-module and 8 IPC registers in the Control module. MPU
> uses the assigned Mailbox for issuing an interrupt to
> WKUP_M3 which then goes and checks the IPC registers for
> the payload. WKUP_M3 has the ability to trigger on interrupt

s/trigger on interrupt/trigger an interrupt/  ??

> to MPU by executing the "sev" instruction.
>
> In the current implementation when the suspend process
> is initiated MPU interrupts the WKUP_M3 to let it know about
> the intent of entering DeepSleep0 and waits for an ACK. When
> the ACK is received MPU continues with its suspend process
> to suspend all the drivers and then jumps to assembly in
> OCMC RAM. The assembly code puts the PLLs in bypass, puts the
> external RAM in self-refresh mode and then finally execute the
> WFI instruction. Execution of the WFI instruction triggers another
> interrupt to the WKUP_M3 which then continues wiht the power down
> sequence wherein the clockdomain and powerdomain transition takes
> place. As part of the sleep sequence, WKUP_M3 unmasks the interrupt
> lines for the wakeup sources. WFI execution on WKUP_M3 causes the
> hardware to disable the main oscillator of the SoC.
>
> When a wakeup event occurs, WKUP_M3 starts the power-up
> sequence by switching on the power domains and finally
> enabling the clock to MPU. Since the MPU gets powered down
> as part of the sleep sequence in the resume path ROM code
> starts executing. The ROM code detects a wakeup from sleep
> and then jumps to the resume location in OCMC which was
> populated in one of the IPC registers as part of the suspend
> sequence.
>
> The low level code in OCMC relocks the PLLs, enables access
> to external RAM and then jumps to the cpu_resume code of
> the kernel to finish the resume process.

[...]

>  arch/arm/mach-omap2/pm33xx.c  |  474 +++++++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/pm33xx.h  |   77 +++++++
>  arch/arm/mach-omap2/wkup_m3.c |  183 ++++++++++++++++


Looking closer at this code as I'm trying to fully get my head around
all the IPC, I have some more comments.

I think the split between pm33xx.c and the M3 driver is still confusing
here.  For example, am33xx_ping_wkup_m3(),
am33xx_m3_state_machine_reset() and the guts of am33xx_pm_begin() all
belong inside the M3 driver, along with all the wakeup_src stuff, which
is info coming from the M3.

IOW, the communication with M3 should be abstracted from pm33xx by the
M3 driver (or possibly an eventual remoteproc/rpmsg implementation) with
a well defined API.  In this implementation, the interface is pretty
fuzzy and mixed between pm33xx.c and wkup_m3.c.

Kevin

P.S. I'd also suggest renaming wakeup_src to something else since
it's close to wakeup_source which has a rather different meaning in the
kernel (c.f. linux/pm_wakeup.h)

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-27 21:45     ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-27 21:45 UTC (permalink / raw)
  To: linux-arm-kernel

Dave Gerlach <d-gerlach@ti.com> writes:

> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>
> AM335x supports various low power modes as documented
> in section 8.1.4.3 of the AM335x TRM which is available
> @ http://www.ti.com/litv/pdf/spruh73f
>
> DeepSleep0 mode offers the lowest power mode with limited
> wakeup sources without a system reboot and is mapped as
> the suspend state in the kernel. In this state, MPU and
> PER domains are turned off with the internal RAM held in
> retention to facilitate resume process. As part of the boot
> process, the assembly code is copied over to OCMCRAM using
> the OMAP SRAM code.
>
> AM335x has a Cortex-M3 (WKUP_M3) which assists the MPU
> in DeepSleep0 entry and exit. WKUP_M3 takes care of the
> clockdomain and powerdomain transitions based on the
> intended low power state. MPU needs to load the appropriate
> WKUP_M3 binary onto the WKUP_M3 memory space before it can
> leverage any of the PM features like DeepSleep.
>
> The IPC mechanism between MPU and WKUP_M3 uses a mailbox
> sub-module and 8 IPC registers in the Control module. MPU
> uses the assigned Mailbox for issuing an interrupt to
> WKUP_M3 which then goes and checks the IPC registers for
> the payload. WKUP_M3 has the ability to trigger on interrupt

s/trigger on interrupt/trigger an interrupt/  ??

> to MPU by executing the "sev" instruction.
>
> In the current implementation when the suspend process
> is initiated MPU interrupts the WKUP_M3 to let it know about
> the intent of entering DeepSleep0 and waits for an ACK. When
> the ACK is received MPU continues with its suspend process
> to suspend all the drivers and then jumps to assembly in
> OCMC RAM. The assembly code puts the PLLs in bypass, puts the
> external RAM in self-refresh mode and then finally execute the
> WFI instruction. Execution of the WFI instruction triggers another
> interrupt to the WKUP_M3 which then continues wiht the power down
> sequence wherein the clockdomain and powerdomain transition takes
> place. As part of the sleep sequence, WKUP_M3 unmasks the interrupt
> lines for the wakeup sources. WFI execution on WKUP_M3 causes the
> hardware to disable the main oscillator of the SoC.
>
> When a wakeup event occurs, WKUP_M3 starts the power-up
> sequence by switching on the power domains and finally
> enabling the clock to MPU. Since the MPU gets powered down
> as part of the sleep sequence in the resume path ROM code
> starts executing. The ROM code detects a wakeup from sleep
> and then jumps to the resume location in OCMC which was
> populated in one of the IPC registers as part of the suspend
> sequence.
>
> The low level code in OCMC relocks the PLLs, enables access
> to external RAM and then jumps to the cpu_resume code of
> the kernel to finish the resume process.

[...]

>  arch/arm/mach-omap2/pm33xx.c  |  474 +++++++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/pm33xx.h  |   77 +++++++
>  arch/arm/mach-omap2/wkup_m3.c |  183 ++++++++++++++++


Looking closer at this code as I'm trying to fully get my head around
all the IPC, I have some more comments.

I think the split between pm33xx.c and the M3 driver is still confusing
here.  For example, am33xx_ping_wkup_m3(),
am33xx_m3_state_machine_reset() and the guts of am33xx_pm_begin() all
belong inside the M3 driver, along with all the wakeup_src stuff, which
is info coming from the M3.

IOW, the communication with M3 should be abstracted from pm33xx by the
M3 driver (or possibly an eventual remoteproc/rpmsg implementation) with
a well defined API.  In this implementation, the interface is pretty
fuzzy and mixed between pm33xx.c and wkup_m3.c.

Kevin

P.S. I'd also suggest renaming wakeup_src to something else since
it's close to wakeup_source which has a rather different meaning in the
kernel (c.f. linux/pm_wakeup.h)

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-08-27 20:23       ` Kevin Hilman
@ 2013-08-29 21:30         ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-29 21:30 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Gururaja Hebbar, linux-arm-kernel, linux-omap, Paul Walmsley

On 08/27/2013 03:23 PM, Kevin Hilman wrote:
> Hi Dave,
>
> Dave Gerlach <d-gerlach@ti.com> writes:
>
>> On 08/19/2013 04:23 AM, Gururaja Hebbar wrote:
>>> On 8/6/2013 11:19 PM, Dave Gerlach wrote:
>>>> Hi,
>>>>
>>>> This is the third version of the patch series for adding basic suspend-resume
>>>> support for AM33XX, previously submitted by Vaibhav Bedia. This patchset
>>>> is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
>>>> that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are
>>>> required for the pm code to properly suspend and resume.
>>>>
>>>> The PM code uses the firmware interface and expects the userspace to load
>>>> the WKUP_M3 binary before the suspend-resume functionality is made available.
>>>> The binary file (and the source-code for WKUP_M3) can be obtained from the
>>>> 'next2' branch at [4]. The WKUP_M3 binary can either be loaded post bootup
>>>> via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be
>>>> included in the kernel image as part of the build process.
>>>>
>>>> Suspend to mem is tested on am335x-bone and am335x-evm.
>>>>
>>>> More details on AM335x suspend-resume are provided within the commit logs
>>>> for each patch.
>>>
>>> can you share the working repo which has all these patches applied?
>>>
>>> Thanks & Regards
>>> Gururaja
>>>
>>
>> The working repo for this version of the patch series can be found here:
>>
>> git://github.com/dgerlach/linux-pm.git am335x-3.11rc4-suspend-resume
>
> I tried this branch on my beaglebone black, and it's not fully resuming.
> Suspend seems to be working (power draw goes from ~1W to ~130mW) and
> pressing a key on the UART seems to be waking up the SoC (power draw
> goes to ~600mW) but I don't ever get the console back.
>
> Is there a specific version of the firmware I should be using?
>
> Kevin
>

Kevin, I agree there does seem to be some issues with Beaglebone black. 
I can confirm it works on BeagleBone White and the large am335 EVM, I am 
working on pinpointing the issue on beaglebone black, seems that support 
isn't quite there yet.

Regards,
Dave


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-08-29 21:30         ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-29 21:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/27/2013 03:23 PM, Kevin Hilman wrote:
> Hi Dave,
>
> Dave Gerlach <d-gerlach@ti.com> writes:
>
>> On 08/19/2013 04:23 AM, Gururaja Hebbar wrote:
>>> On 8/6/2013 11:19 PM, Dave Gerlach wrote:
>>>> Hi,
>>>>
>>>> This is the third version of the patch series for adding basic suspend-resume
>>>> support for AM33XX, previously submitted by Vaibhav Bedia. This patchset
>>>> is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
>>>> that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are
>>>> required for the pm code to properly suspend and resume.
>>>>
>>>> The PM code uses the firmware interface and expects the userspace to load
>>>> the WKUP_M3 binary before the suspend-resume functionality is made available.
>>>> The binary file (and the source-code for WKUP_M3) can be obtained from the
>>>> 'next2' branch at [4]. The WKUP_M3 binary can either be loaded post bootup
>>>> via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be
>>>> included in the kernel image as part of the build process.
>>>>
>>>> Suspend to mem is tested on am335x-bone and am335x-evm.
>>>>
>>>> More details on AM335x suspend-resume are provided within the commit logs
>>>> for each patch.
>>>
>>> can you share the working repo which has all these patches applied?
>>>
>>> Thanks & Regards
>>> Gururaja
>>>
>>
>> The working repo for this version of the patch series can be found here:
>>
>> git://github.com/dgerlach/linux-pm.git am335x-3.11rc4-suspend-resume
>
> I tried this branch on my beaglebone black, and it's not fully resuming.
> Suspend seems to be working (power draw goes from ~1W to ~130mW) and
> pressing a key on the UART seems to be waking up the SoC (power draw
> goes to ~600mW) but I don't ever get the console back.
>
> Is there a specific version of the firmware I should be using?
>
> Kevin
>

Kevin, I agree there does seem to be some issues with Beaglebone black. 
I can confirm it works on BeagleBone White and the large am335 EVM, I am 
working on pinpointing the issue on beaglebone black, seems that support 
isn't quite there yet.

Regards,
Dave

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-27 21:45     ` Kevin Hilman
@ 2013-08-29 21:41       ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-29 21:41 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Vaibhav Bedia,
	Tony Lingren, Santosh Shilimkar, Benoit Cousson

On 08/27/2013 04:45 PM, Kevin Hilman wrote:
> Dave Gerlach <d-gerlach@ti.com> writes:
>
>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>
>> AM335x supports various low power modes as documented
>> in section 8.1.4.3 of the AM335x TRM which is available
>> @ http://www.ti.com/litv/pdf/spruh73f
>>
>> DeepSleep0 mode offers the lowest power mode with limited
>> wakeup sources without a system reboot and is mapped as
>> the suspend state in the kernel. In this state, MPU and
>> PER domains are turned off with the internal RAM held in
>> retention to facilitate resume process. As part of the boot
>> process, the assembly code is copied over to OCMCRAM using
>> the OMAP SRAM code.
>>
>> AM335x has a Cortex-M3 (WKUP_M3) which assists the MPU
>> in DeepSleep0 entry and exit. WKUP_M3 takes care of the
>> clockdomain and powerdomain transitions based on the
>> intended low power state. MPU needs to load the appropriate
>> WKUP_M3 binary onto the WKUP_M3 memory space before it can
>> leverage any of the PM features like DeepSleep.
>>
>> The IPC mechanism between MPU and WKUP_M3 uses a mailbox
>> sub-module and 8 IPC registers in the Control module. MPU
>> uses the assigned Mailbox for issuing an interrupt to
>> WKUP_M3 which then goes and checks the IPC registers for
>> the payload. WKUP_M3 has the ability to trigger on interrupt
>
> s/trigger on interrupt/trigger an interrupt/  ??

Oops I will fix that.

>
>> to MPU by executing the "sev" instruction.
>>
>> In the current implementation when the suspend process
>> is initiated MPU interrupts the WKUP_M3 to let it know about
>> the intent of entering DeepSleep0 and waits for an ACK. When
>> the ACK is received MPU continues with its suspend process
>> to suspend all the drivers and then jumps to assembly in
>> OCMC RAM. The assembly code puts the PLLs in bypass, puts the
>> external RAM in self-refresh mode and then finally execute the
>> WFI instruction. Execution of the WFI instruction triggers another
>> interrupt to the WKUP_M3 which then continues wiht the power down
>> sequence wherein the clockdomain and powerdomain transition takes
>> place. As part of the sleep sequence, WKUP_M3 unmasks the interrupt
>> lines for the wakeup sources. WFI execution on WKUP_M3 causes the
>> hardware to disable the main oscillator of the SoC.
>>
>> When a wakeup event occurs, WKUP_M3 starts the power-up
>> sequence by switching on the power domains and finally
>> enabling the clock to MPU. Since the MPU gets powered down
>> as part of the sleep sequence in the resume path ROM code
>> starts executing. The ROM code detects a wakeup from sleep
>> and then jumps to the resume location in OCMC which was
>> populated in one of the IPC registers as part of the suspend
>> sequence.
>>
>> The low level code in OCMC relocks the PLLs, enables access
>> to external RAM and then jumps to the cpu_resume code of
>> the kernel to finish the resume process.
>
> [...]
>
>>   arch/arm/mach-omap2/pm33xx.c  |  474 +++++++++++++++++++++++++++++++++++++++++
>>   arch/arm/mach-omap2/pm33xx.h  |   77 +++++++
>>   arch/arm/mach-omap2/wkup_m3.c |  183 ++++++++++++++++
>
>
> Looking closer at this code as I'm trying to fully get my head around
> all the IPC, I have some more comments.
>
> I think the split between pm33xx.c and the M3 driver is still confusing
> here.  For example, am33xx_ping_wkup_m3(),
> am33xx_m3_state_machine_reset() and the guts of am33xx_pm_begin() all
> belong inside the M3 driver, along with all the wakeup_src stuff, which
> is info coming from the M3.
>
> IOW, the communication with M3 should be abstracted from pm33xx by the
> M3 driver (or possibly an eventual remoteproc/rpmsg implementation) with
> a well defined API.  In this implementation, the interface is pretty
> fuzzy and mixed between pm33xx.c and wkup_m3.c.

I have since moved much more of the m3 functionality, including the ping 
and wakeup src code, into the wkup_m3 driver to make the split more 
clear but I haven't yet moved the state machine portion into the wkup_m3 
driver. I feel that this is the portion of the IPC that could 
potentially be the most variant between different SoC implementations so 
leaving this in the pm code should allow for more flexibility.

>
> Kevin
>
> P.S. I'd also suggest renaming wakeup_src to something else since
> it's close to wakeup_source which has a rather different meaning in the
> kernel (c.f. linux/pm_wakeup.h)
>

I will rename this to tie it into the M3 code.

Regards,
Dave


^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-29 21:41       ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-29 21:41 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/27/2013 04:45 PM, Kevin Hilman wrote:
> Dave Gerlach <d-gerlach@ti.com> writes:
>
>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>
>> AM335x supports various low power modes as documented
>> in section 8.1.4.3 of the AM335x TRM which is available
>> @ http://www.ti.com/litv/pdf/spruh73f
>>
>> DeepSleep0 mode offers the lowest power mode with limited
>> wakeup sources without a system reboot and is mapped as
>> the suspend state in the kernel. In this state, MPU and
>> PER domains are turned off with the internal RAM held in
>> retention to facilitate resume process. As part of the boot
>> process, the assembly code is copied over to OCMCRAM using
>> the OMAP SRAM code.
>>
>> AM335x has a Cortex-M3 (WKUP_M3) which assists the MPU
>> in DeepSleep0 entry and exit. WKUP_M3 takes care of the
>> clockdomain and powerdomain transitions based on the
>> intended low power state. MPU needs to load the appropriate
>> WKUP_M3 binary onto the WKUP_M3 memory space before it can
>> leverage any of the PM features like DeepSleep.
>>
>> The IPC mechanism between MPU and WKUP_M3 uses a mailbox
>> sub-module and 8 IPC registers in the Control module. MPU
>> uses the assigned Mailbox for issuing an interrupt to
>> WKUP_M3 which then goes and checks the IPC registers for
>> the payload. WKUP_M3 has the ability to trigger on interrupt
>
> s/trigger on interrupt/trigger an interrupt/  ??

Oops I will fix that.

>
>> to MPU by executing the "sev" instruction.
>>
>> In the current implementation when the suspend process
>> is initiated MPU interrupts the WKUP_M3 to let it know about
>> the intent of entering DeepSleep0 and waits for an ACK. When
>> the ACK is received MPU continues with its suspend process
>> to suspend all the drivers and then jumps to assembly in
>> OCMC RAM. The assembly code puts the PLLs in bypass, puts the
>> external RAM in self-refresh mode and then finally execute the
>> WFI instruction. Execution of the WFI instruction triggers another
>> interrupt to the WKUP_M3 which then continues wiht the power down
>> sequence wherein the clockdomain and powerdomain transition takes
>> place. As part of the sleep sequence, WKUP_M3 unmasks the interrupt
>> lines for the wakeup sources. WFI execution on WKUP_M3 causes the
>> hardware to disable the main oscillator of the SoC.
>>
>> When a wakeup event occurs, WKUP_M3 starts the power-up
>> sequence by switching on the power domains and finally
>> enabling the clock to MPU. Since the MPU gets powered down
>> as part of the sleep sequence in the resume path ROM code
>> starts executing. The ROM code detects a wakeup from sleep
>> and then jumps to the resume location in OCMC which was
>> populated in one of the IPC registers as part of the suspend
>> sequence.
>>
>> The low level code in OCMC relocks the PLLs, enables access
>> to external RAM and then jumps to the cpu_resume code of
>> the kernel to finish the resume process.
>
> [...]
>
>>   arch/arm/mach-omap2/pm33xx.c  |  474 +++++++++++++++++++++++++++++++++++++++++
>>   arch/arm/mach-omap2/pm33xx.h  |   77 +++++++
>>   arch/arm/mach-omap2/wkup_m3.c |  183 ++++++++++++++++
>
>
> Looking closer at this code as I'm trying to fully get my head around
> all the IPC, I have some more comments.
>
> I think the split between pm33xx.c and the M3 driver is still confusing
> here.  For example, am33xx_ping_wkup_m3(),
> am33xx_m3_state_machine_reset() and the guts of am33xx_pm_begin() all
> belong inside the M3 driver, along with all the wakeup_src stuff, which
> is info coming from the M3.
>
> IOW, the communication with M3 should be abstracted from pm33xx by the
> M3 driver (or possibly an eventual remoteproc/rpmsg implementation) with
> a well defined API.  In this implementation, the interface is pretty
> fuzzy and mixed between pm33xx.c and wkup_m3.c.

I have since moved much more of the m3 functionality, including the ping 
and wakeup src code, into the wkup_m3 driver to make the split more 
clear but I haven't yet moved the state machine portion into the wkup_m3 
driver. I feel that this is the portion of the IPC that could 
potentially be the most variant between different SoC implementations so 
leaving this in the pm code should allow for more flexibility.

>
> Kevin
>
> P.S. I'd also suggest renaming wakeup_src to something else since
> it's close to wakeup_source which has a rather different meaning in the
> kernel (c.f. linux/pm_wakeup.h)
>

I will rename this to tie it into the M3 code.

Regards,
Dave

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-08-29 21:30         ` Dave Gerlach
@ 2013-08-29 21:52           ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-29 21:52 UTC (permalink / raw)
  To: Dave Gerlach; +Cc: Gururaja Hebbar, linux-arm-kernel, linux-omap, Paul Walmsley

Dave Gerlach <d-gerlach@ti.com> writes:

> On 08/27/2013 03:23 PM, Kevin Hilman wrote:
>> Hi Dave,
>>
>> Dave Gerlach <d-gerlach@ti.com> writes:
>>
>>> On 08/19/2013 04:23 AM, Gururaja Hebbar wrote:
>>>> On 8/6/2013 11:19 PM, Dave Gerlach wrote:
>>>>> Hi,
>>>>>
>>>>> This is the third version of the patch series for adding basic suspend-resume
>>>>> support for AM33XX, previously submitted by Vaibhav Bedia. This patchset
>>>>> is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
>>>>> that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are
>>>>> required for the pm code to properly suspend and resume.
>>>>>
>>>>> The PM code uses the firmware interface and expects the userspace to load
>>>>> the WKUP_M3 binary before the suspend-resume functionality is made available.
>>>>> The binary file (and the source-code for WKUP_M3) can be obtained from the
>>>>> 'next2' branch at [4]. The WKUP_M3 binary can either be loaded post bootup
>>>>> via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be
>>>>> included in the kernel image as part of the build process.
>>>>>
>>>>> Suspend to mem is tested on am335x-bone and am335x-evm.
>>>>>
>>>>> More details on AM335x suspend-resume are provided within the commit logs
>>>>> for each patch.
>>>>
>>>> can you share the working repo which has all these patches applied?
>>>>
>>>> Thanks & Regards
>>>> Gururaja
>>>>
>>>
>>> The working repo for this version of the patch series can be found here:
>>>
>>> git://github.com/dgerlach/linux-pm.git am335x-3.11rc4-suspend-resume
>>
>> I tried this branch on my beaglebone black, and it's not fully resuming.
>> Suspend seems to be working (power draw goes from ~1W to ~130mW) and
>> pressing a key on the UART seems to be waking up the SoC (power draw
>> goes to ~600mW) but I don't ever get the console back.
>>
>> Is there a specific version of the firmware I should be using?
>>
>> Kevin
>>
>
> Kevin, I agree there does seem to be some issues with Beaglebone
> black. I can confirm it works on BeagleBone White and the large am335
> EVM, I am working on pinpointing the issue on beaglebone black, seems
> that support isn't quite there yet.

OK, I didn't realize that.  I'll give it a try on my BB white.

Is there a specific version/branch of the firmware I should be using?

Thanks,

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-08-29 21:52           ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-29 21:52 UTC (permalink / raw)
  To: linux-arm-kernel

Dave Gerlach <d-gerlach@ti.com> writes:

> On 08/27/2013 03:23 PM, Kevin Hilman wrote:
>> Hi Dave,
>>
>> Dave Gerlach <d-gerlach@ti.com> writes:
>>
>>> On 08/19/2013 04:23 AM, Gururaja Hebbar wrote:
>>>> On 8/6/2013 11:19 PM, Dave Gerlach wrote:
>>>>> Hi,
>>>>>
>>>>> This is the third version of the patch series for adding basic suspend-resume
>>>>> support for AM33XX, previously submitted by Vaibhav Bedia. This patchset
>>>>> is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
>>>>> that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are
>>>>> required for the pm code to properly suspend and resume.
>>>>>
>>>>> The PM code uses the firmware interface and expects the userspace to load
>>>>> the WKUP_M3 binary before the suspend-resume functionality is made available.
>>>>> The binary file (and the source-code for WKUP_M3) can be obtained from the
>>>>> 'next2' branch at [4]. The WKUP_M3 binary can either be loaded post bootup
>>>>> via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be
>>>>> included in the kernel image as part of the build process.
>>>>>
>>>>> Suspend to mem is tested on am335x-bone and am335x-evm.
>>>>>
>>>>> More details on AM335x suspend-resume are provided within the commit logs
>>>>> for each patch.
>>>>
>>>> can you share the working repo which has all these patches applied?
>>>>
>>>> Thanks & Regards
>>>> Gururaja
>>>>
>>>
>>> The working repo for this version of the patch series can be found here:
>>>
>>> git://github.com/dgerlach/linux-pm.git am335x-3.11rc4-suspend-resume
>>
>> I tried this branch on my beaglebone black, and it's not fully resuming.
>> Suspend seems to be working (power draw goes from ~1W to ~130mW) and
>> pressing a key on the UART seems to be waking up the SoC (power draw
>> goes to ~600mW) but I don't ever get the console back.
>>
>> Is there a specific version of the firmware I should be using?
>>
>> Kevin
>>
>
> Kevin, I agree there does seem to be some issues with Beaglebone
> black. I can confirm it works on BeagleBone White and the large am335
> EVM, I am working on pinpointing the issue on beaglebone black, seems
> that support isn't quite there yet.

OK, I didn't realize that.  I'll give it a try on my BB white.

Is there a specific version/branch of the firmware I should be using?

Thanks,

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-29 21:41       ` Dave Gerlach
@ 2013-08-29 22:02         ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-29 22:02 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-arm-kernel, linux-omap, Paul Walmsley, Vaibhav Bedia,
	Tony Lingren, Santosh Shilimkar, Benoit Cousson

Dave Gerlach <d-gerlach@ti.com> writes:

> On 08/27/2013 04:45 PM, Kevin Hilman wrote:
>> Dave Gerlach <d-gerlach@ti.com> writes:
>>
>>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>>
>>> AM335x supports various low power modes as documented
>>> in section 8.1.4.3 of the AM335x TRM which is available
>>> @ http://www.ti.com/litv/pdf/spruh73f
>>>
>>> DeepSleep0 mode offers the lowest power mode with limited
>>> wakeup sources without a system reboot and is mapped as
>>> the suspend state in the kernel. In this state, MPU and
>>> PER domains are turned off with the internal RAM held in
>>> retention to facilitate resume process. As part of the boot
>>> process, the assembly code is copied over to OCMCRAM using
>>> the OMAP SRAM code.
>>>
>>> AM335x has a Cortex-M3 (WKUP_M3) which assists the MPU
>>> in DeepSleep0 entry and exit. WKUP_M3 takes care of the
>>> clockdomain and powerdomain transitions based on the
>>> intended low power state. MPU needs to load the appropriate
>>> WKUP_M3 binary onto the WKUP_M3 memory space before it can
>>> leverage any of the PM features like DeepSleep.
>>>
>>> The IPC mechanism between MPU and WKUP_M3 uses a mailbox
>>> sub-module and 8 IPC registers in the Control module. MPU
>>> uses the assigned Mailbox for issuing an interrupt to
>>> WKUP_M3 which then goes and checks the IPC registers for
>>> the payload. WKUP_M3 has the ability to trigger on interrupt
>>
>> s/trigger on interrupt/trigger an interrupt/  ??
>
> Oops I will fix that.
>
>>
>>> to MPU by executing the "sev" instruction.
>>>
>>> In the current implementation when the suspend process
>>> is initiated MPU interrupts the WKUP_M3 to let it know about
>>> the intent of entering DeepSleep0 and waits for an ACK. When
>>> the ACK is received MPU continues with its suspend process
>>> to suspend all the drivers and then jumps to assembly in
>>> OCMC RAM. The assembly code puts the PLLs in bypass, puts the
>>> external RAM in self-refresh mode and then finally execute the
>>> WFI instruction. Execution of the WFI instruction triggers another
>>> interrupt to the WKUP_M3 which then continues wiht the power down
>>> sequence wherein the clockdomain and powerdomain transition takes
>>> place. As part of the sleep sequence, WKUP_M3 unmasks the interrupt
>>> lines for the wakeup sources. WFI execution on WKUP_M3 causes the
>>> hardware to disable the main oscillator of the SoC.
>>>
>>> When a wakeup event occurs, WKUP_M3 starts the power-up
>>> sequence by switching on the power domains and finally
>>> enabling the clock to MPU. Since the MPU gets powered down
>>> as part of the sleep sequence in the resume path ROM code
>>> starts executing. The ROM code detects a wakeup from sleep
>>> and then jumps to the resume location in OCMC which was
>>> populated in one of the IPC registers as part of the suspend
>>> sequence.
>>>
>>> The low level code in OCMC relocks the PLLs, enables access
>>> to external RAM and then jumps to the cpu_resume code of
>>> the kernel to finish the resume process.
>>
>> [...]
>>
>>>   arch/arm/mach-omap2/pm33xx.c  |  474 +++++++++++++++++++++++++++++++++++++++++
>>>   arch/arm/mach-omap2/pm33xx.h  |   77 +++++++
>>>   arch/arm/mach-omap2/wkup_m3.c |  183 ++++++++++++++++
>>
>>
>> Looking closer at this code as I'm trying to fully get my head around
>> all the IPC, I have some more comments.
>>
>> I think the split between pm33xx.c and the M3 driver is still confusing
>> here.  For example, am33xx_ping_wkup_m3(),
>> am33xx_m3_state_machine_reset() and the guts of am33xx_pm_begin() all
>> belong inside the M3 driver, along with all the wakeup_src stuff, which
>> is info coming from the M3.
>>
>> IOW, the communication with M3 should be abstracted from pm33xx by the
>> M3 driver (or possibly an eventual remoteproc/rpmsg implementation) with
>> a well defined API.  In this implementation, the interface is pretty
>> fuzzy and mixed between pm33xx.c and wkup_m3.c.
>
> I have since moved much more of the m3 functionality, including the
> ping and wakeup src code, into the wkup_m3 driver to make the split
> more clear but I haven't yet moved the state machine portion into the
> wkup_m3 driver. I feel that this is the portion of the IPC that could
> potentially be the most variant between different SoC implementations
> so leaving this in the pm code should allow for more flexibility.

I still think this belogs in the M3 driver, because AFAICT, it's
specific to the M3 firmware, not to the SoC.

>>
>> Kevin
>>
>> P.S. I'd also suggest renaming wakeup_src to something else since
>> it's close to wakeup_source which has a rather different meaning in the
>> kernel (c.f. linux/pm_wakeup.h)
>>
>
> I will rename this to tie it into the M3 code.

Great, thanks.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-29 22:02         ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-29 22:02 UTC (permalink / raw)
  To: linux-arm-kernel

Dave Gerlach <d-gerlach@ti.com> writes:

> On 08/27/2013 04:45 PM, Kevin Hilman wrote:
>> Dave Gerlach <d-gerlach@ti.com> writes:
>>
>>> From: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>>
>>> AM335x supports various low power modes as documented
>>> in section 8.1.4.3 of the AM335x TRM which is available
>>> @ http://www.ti.com/litv/pdf/spruh73f
>>>
>>> DeepSleep0 mode offers the lowest power mode with limited
>>> wakeup sources without a system reboot and is mapped as
>>> the suspend state in the kernel. In this state, MPU and
>>> PER domains are turned off with the internal RAM held in
>>> retention to facilitate resume process. As part of the boot
>>> process, the assembly code is copied over to OCMCRAM using
>>> the OMAP SRAM code.
>>>
>>> AM335x has a Cortex-M3 (WKUP_M3) which assists the MPU
>>> in DeepSleep0 entry and exit. WKUP_M3 takes care of the
>>> clockdomain and powerdomain transitions based on the
>>> intended low power state. MPU needs to load the appropriate
>>> WKUP_M3 binary onto the WKUP_M3 memory space before it can
>>> leverage any of the PM features like DeepSleep.
>>>
>>> The IPC mechanism between MPU and WKUP_M3 uses a mailbox
>>> sub-module and 8 IPC registers in the Control module. MPU
>>> uses the assigned Mailbox for issuing an interrupt to
>>> WKUP_M3 which then goes and checks the IPC registers for
>>> the payload. WKUP_M3 has the ability to trigger on interrupt
>>
>> s/trigger on interrupt/trigger an interrupt/  ??
>
> Oops I will fix that.
>
>>
>>> to MPU by executing the "sev" instruction.
>>>
>>> In the current implementation when the suspend process
>>> is initiated MPU interrupts the WKUP_M3 to let it know about
>>> the intent of entering DeepSleep0 and waits for an ACK. When
>>> the ACK is received MPU continues with its suspend process
>>> to suspend all the drivers and then jumps to assembly in
>>> OCMC RAM. The assembly code puts the PLLs in bypass, puts the
>>> external RAM in self-refresh mode and then finally execute the
>>> WFI instruction. Execution of the WFI instruction triggers another
>>> interrupt to the WKUP_M3 which then continues wiht the power down
>>> sequence wherein the clockdomain and powerdomain transition takes
>>> place. As part of the sleep sequence, WKUP_M3 unmasks the interrupt
>>> lines for the wakeup sources. WFI execution on WKUP_M3 causes the
>>> hardware to disable the main oscillator of the SoC.
>>>
>>> When a wakeup event occurs, WKUP_M3 starts the power-up
>>> sequence by switching on the power domains and finally
>>> enabling the clock to MPU. Since the MPU gets powered down
>>> as part of the sleep sequence in the resume path ROM code
>>> starts executing. The ROM code detects a wakeup from sleep
>>> and then jumps to the resume location in OCMC which was
>>> populated in one of the IPC registers as part of the suspend
>>> sequence.
>>>
>>> The low level code in OCMC relocks the PLLs, enables access
>>> to external RAM and then jumps to the cpu_resume code of
>>> the kernel to finish the resume process.
>>
>> [...]
>>
>>>   arch/arm/mach-omap2/pm33xx.c  |  474 +++++++++++++++++++++++++++++++++++++++++
>>>   arch/arm/mach-omap2/pm33xx.h  |   77 +++++++
>>>   arch/arm/mach-omap2/wkup_m3.c |  183 ++++++++++++++++
>>
>>
>> Looking closer at this code as I'm trying to fully get my head around
>> all the IPC, I have some more comments.
>>
>> I think the split between pm33xx.c and the M3 driver is still confusing
>> here.  For example, am33xx_ping_wkup_m3(),
>> am33xx_m3_state_machine_reset() and the guts of am33xx_pm_begin() all
>> belong inside the M3 driver, along with all the wakeup_src stuff, which
>> is info coming from the M3.
>>
>> IOW, the communication with M3 should be abstracted from pm33xx by the
>> M3 driver (or possibly an eventual remoteproc/rpmsg implementation) with
>> a well defined API.  In this implementation, the interface is pretty
>> fuzzy and mixed between pm33xx.c and wkup_m3.c.
>
> I have since moved much more of the m3 functionality, including the
> ping and wakeup src code, into the wkup_m3 driver to make the split
> more clear but I haven't yet moved the state machine portion into the
> wkup_m3 driver. I feel that this is the portion of the IPC that could
> potentially be the most variant between different SoC implementations
> so leaving this in the pm code should allow for more flexibility.

I still think this belogs in the M3 driver, because AFAICT, it's
specific to the M3 firmware, not to the SoC.

>>
>> Kevin
>>
>> P.S. I'd also suggest renaming wakeup_src to something else since
>> it's close to wakeup_source which has a rather different meaning in the
>> kernel (c.f. linux/pm_wakeup.h)
>>
>
> I will rename this to tie it into the M3 code.

Great, thanks.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-08-29 21:30         ` Dave Gerlach
@ 2013-08-29 22:20           ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-29 22:20 UTC (permalink / raw)
  To: Dave Gerlach; +Cc: Gururaja Hebbar, linux-arm-kernel, linux-omap, Paul Walmsley

Dave Gerlach <d-gerlach@ti.com> writes:

[...]

>>>
>>> The working repo for this version of the patch series can be found here:
>>>
>>> git://github.com/dgerlach/linux-pm.git am335x-3.11rc4-suspend-resume
>>
>> I tried this branch on my beaglebone black, and it's not fully resuming.
>> Suspend seems to be working (power draw goes from ~1W to ~130mW) and
>> pressing a key on the UART seems to be waking up the SoC (power draw
>> goes to ~600mW) but I don't ever get the console back.
>>
>> Is there a specific version of the firmware I should be using?
>>
>> Kevin
>>
>
> Kevin, I agree there does seem to be some issues with Beaglebone
> black. I can confirm it works on BeagleBone White and the large am335
> EVM, I am working on pinpointing the issue on beaglebone black, seems
> that support isn't quite there yet.

OK, I tried the above branch on my BB white, using prebuilt firmware
from the next3 branch of the am33x-cm3 repo and it's suspending/resuming
fine.  Thanks for the pointer.

FYI, measuring at the 5V supply, it goes from ~1.6W at idle down to
~700mW in suspend.  The black goes from ~1W down to an impressive 130mW
but of course, it doesn't wake up so maybe it's not that impressive. ;)

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-08-29 22:20           ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-29 22:20 UTC (permalink / raw)
  To: linux-arm-kernel

Dave Gerlach <d-gerlach@ti.com> writes:

[...]

>>>
>>> The working repo for this version of the patch series can be found here:
>>>
>>> git://github.com/dgerlach/linux-pm.git am335x-3.11rc4-suspend-resume
>>
>> I tried this branch on my beaglebone black, and it's not fully resuming.
>> Suspend seems to be working (power draw goes from ~1W to ~130mW) and
>> pressing a key on the UART seems to be waking up the SoC (power draw
>> goes to ~600mW) but I don't ever get the console back.
>>
>> Is there a specific version of the firmware I should be using?
>>
>> Kevin
>>
>
> Kevin, I agree there does seem to be some issues with Beaglebone
> black. I can confirm it works on BeagleBone White and the large am335
> EVM, I am working on pinpointing the issue on beaglebone black, seems
> that support isn't quite there yet.

OK, I tried the above branch on my BB white, using prebuilt firmware
from the next3 branch of the am33x-cm3 repo and it's suspending/resuming
fine.  Thanks for the pointer.

FYI, measuring at the 5V supply, it goes from ~1.6W at idle down to
~700mW in suspend.  The black goes from ~1W down to an impressive 130mW
but of course, it doesn't wake up so maybe it's not that impressive. ;)

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-08-29 21:52           ` Kevin Hilman
@ 2013-08-29 22:20             ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-29 22:20 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Gururaja Hebbar, linux-arm-kernel, linux-omap, Paul Walmsley

On 08/29/2013 04:52 PM, Kevin Hilman wrote:
> Dave Gerlach <d-gerlach@ti.com> writes:
>
>> On 08/27/2013 03:23 PM, Kevin Hilman wrote:
>>> Hi Dave,
>>>
>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>
>>>> On 08/19/2013 04:23 AM, Gururaja Hebbar wrote:
>>>>> On 8/6/2013 11:19 PM, Dave Gerlach wrote:
>>>>>> Hi,
>>>>>>
>>>>>> This is the third version of the patch series for adding basic suspend-resume
>>>>>> support for AM33XX, previously submitted by Vaibhav Bedia. This patchset
>>>>>> is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
>>>>>> that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are
>>>>>> required for the pm code to properly suspend and resume.
>>>>>>
>>>>>> The PM code uses the firmware interface and expects the userspace to load
>>>>>> the WKUP_M3 binary before the suspend-resume functionality is made available.
>>>>>> The binary file (and the source-code for WKUP_M3) can be obtained from the
>>>>>> 'next2' branch at [4]. The WKUP_M3 binary can either be loaded post bootup
>>>>>> via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be
>>>>>> included in the kernel image as part of the build process.
>>>>>>
>>>>>> Suspend to mem is tested on am335x-bone and am335x-evm.
>>>>>>
>>>>>> More details on AM335x suspend-resume are provided within the commit logs
>>>>>> for each patch.
>>>>>
>>>>> can you share the working repo which has all these patches applied?
>>>>>
>>>>> Thanks & Regards
>>>>> Gururaja
>>>>>
>>>>
>>>> The working repo for this version of the patch series can be found here:
>>>>
>>>> git://github.com/dgerlach/linux-pm.git am335x-3.11rc4-suspend-resume
>>>
>>> I tried this branch on my beaglebone black, and it's not fully resuming.
>>> Suspend seems to be working (power draw goes from ~1W to ~130mW) and
>>> pressing a key on the UART seems to be waking up the SoC (power draw
>>> goes to ~600mW) but I don't ever get the console back.
>>>
>>> Is there a specific version of the firmware I should be using?
>>>
>>> Kevin
>>>
>>
>> Kevin, I agree there does seem to be some issues with Beaglebone
>> black. I can confirm it works on BeagleBone White and the large am335
>> EVM, I am working on pinpointing the issue on beaglebone black, seems
>> that support isn't quite there yet.
>
> OK, I didn't realize that.  I'll give it a try on my BB white.
>
> Is there a specific version/branch of the firmware I should be using?
>
> Thanks,
>
> Kevin
>

Kevin,

The next2 branch, which you can find here [1], is what this revision of 
the series was developed against and is tested and works.

Regards,
Dave

[1] 
http://arago-project.org/git/projects/?p=am33x-cm3.git;a=shortlog;h=refs/heads/next2

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-08-29 22:20             ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-08-29 22:20 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/29/2013 04:52 PM, Kevin Hilman wrote:
> Dave Gerlach <d-gerlach@ti.com> writes:
>
>> On 08/27/2013 03:23 PM, Kevin Hilman wrote:
>>> Hi Dave,
>>>
>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>
>>>> On 08/19/2013 04:23 AM, Gururaja Hebbar wrote:
>>>>> On 8/6/2013 11:19 PM, Dave Gerlach wrote:
>>>>>> Hi,
>>>>>>
>>>>>> This is the third version of the patch series for adding basic suspend-resume
>>>>>> support for AM33XX, previously submitted by Vaibhav Bedia. This patchset
>>>>>> is based on 3.11-rc4 and depends on a forthcoming patchset from Suman Anna
>>>>>> that adds mailbox support for the wkup_m3. The patches at [1], [2], and [3] are
>>>>>> required for the pm code to properly suspend and resume.
>>>>>>
>>>>>> The PM code uses the firmware interface and expects the userspace to load
>>>>>> the WKUP_M3 binary before the suspend-resume functionality is made available.
>>>>>> The binary file (and the source-code for WKUP_M3) can be obtained from the
>>>>>> 'next2' branch at [4]. The WKUP_M3 binary can either be loaded post bootup
>>>>>> via the sysfs entry './sys/devices/ocp.2/wkup_m3.4/firmware' or it can be
>>>>>> included in the kernel image as part of the build process.
>>>>>>
>>>>>> Suspend to mem is tested on am335x-bone and am335x-evm.
>>>>>>
>>>>>> More details on AM335x suspend-resume are provided within the commit logs
>>>>>> for each patch.
>>>>>
>>>>> can you share the working repo which has all these patches applied?
>>>>>
>>>>> Thanks & Regards
>>>>> Gururaja
>>>>>
>>>>
>>>> The working repo for this version of the patch series can be found here:
>>>>
>>>> git://github.com/dgerlach/linux-pm.git am335x-3.11rc4-suspend-resume
>>>
>>> I tried this branch on my beaglebone black, and it's not fully resuming.
>>> Suspend seems to be working (power draw goes from ~1W to ~130mW) and
>>> pressing a key on the UART seems to be waking up the SoC (power draw
>>> goes to ~600mW) but I don't ever get the console back.
>>>
>>> Is there a specific version of the firmware I should be using?
>>>
>>> Kevin
>>>
>>
>> Kevin, I agree there does seem to be some issues with Beaglebone
>> black. I can confirm it works on BeagleBone White and the large am335
>> EVM, I am working on pinpointing the issue on beaglebone black, seems
>> that support isn't quite there yet.
>
> OK, I didn't realize that.  I'll give it a try on my BB white.
>
> Is there a specific version/branch of the firmware I should be using?
>
> Thanks,
>
> Kevin
>

Kevin,

The next2 branch, which you can find here [1], is what this revision of 
the series was developed against and is tested and works.

Regards,
Dave

[1] 
http://arago-project.org/git/projects/?p=am33x-cm3.git;a=shortlog;h=refs/heads/next2

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-08-29 22:20           ` Kevin Hilman
@ 2013-08-29 22:43             ` Russ Dill
  -1 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-29 22:43 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Dave Gerlach, Paul Walmsley, linux-omap, Linux ARM Kernel List,
	Gururaja Hebbar

On Thu, Aug 29, 2013 at 3:20 PM, Kevin Hilman <khilman@linaro.org> wrote:
> Dave Gerlach <d-gerlach@ti.com> writes:
>
> [...]
>
>>>>
>>>> The working repo for this version of the patch series can be found here:
>>>>
>>>> git://github.com/dgerlach/linux-pm.git am335x-3.11rc4-suspend-resume
>>>
>>> I tried this branch on my beaglebone black, and it's not fully resuming.
>>> Suspend seems to be working (power draw goes from ~1W to ~130mW) and
>>> pressing a key on the UART seems to be waking up the SoC (power draw
>>> goes to ~600mW) but I don't ever get the console back.
>>>
>>> Is there a specific version of the firmware I should be using?
>>>
>>> Kevin
>>>
>>
>> Kevin, I agree there does seem to be some issues with Beaglebone
>> black. I can confirm it works on BeagleBone White and the large am335
>> EVM, I am working on pinpointing the issue on beaglebone black, seems
>> that support isn't quite there yet.
>
> OK, I tried the above branch on my BB white, using prebuilt firmware
> from the next3 branch of the am33x-cm3 repo and it's suspending/resuming
> fine.  Thanks for the pointer.
>
> FYI, measuring at the 5V supply, it goes from ~1.6W at idle down to
> ~700mW in suspend.  The black goes from ~1W down to an impressive 130mW
> but of course, it doesn't wake up so maybe it's not that impressive. ;)

Just a reminder, the next3 firmware is built to be compatible with
older kernel revisions whereas the next2 firmware is not. In order for
that compatibility to work, the CMD_ID_DS0 that mainline uses should
change from 0x3 to 0x4

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-08-29 22:43             ` Russ Dill
  0 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-08-29 22:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 29, 2013 at 3:20 PM, Kevin Hilman <khilman@linaro.org> wrote:
> Dave Gerlach <d-gerlach@ti.com> writes:
>
> [...]
>
>>>>
>>>> The working repo for this version of the patch series can be found here:
>>>>
>>>> git://github.com/dgerlach/linux-pm.git am335x-3.11rc4-suspend-resume
>>>
>>> I tried this branch on my beaglebone black, and it's not fully resuming.
>>> Suspend seems to be working (power draw goes from ~1W to ~130mW) and
>>> pressing a key on the UART seems to be waking up the SoC (power draw
>>> goes to ~600mW) but I don't ever get the console back.
>>>
>>> Is there a specific version of the firmware I should be using?
>>>
>>> Kevin
>>>
>>
>> Kevin, I agree there does seem to be some issues with Beaglebone
>> black. I can confirm it works on BeagleBone White and the large am335
>> EVM, I am working on pinpointing the issue on beaglebone black, seems
>> that support isn't quite there yet.
>
> OK, I tried the above branch on my BB white, using prebuilt firmware
> from the next3 branch of the am33x-cm3 repo and it's suspending/resuming
> fine.  Thanks for the pointer.
>
> FYI, measuring at the 5V supply, it goes from ~1.6W at idle down to
> ~700mW in suspend.  The black goes from ~1W down to an impressive 130mW
> but of course, it doesn't wake up so maybe it's not that impressive. ;)

Just a reminder, the next3 firmware is built to be compatible with
older kernel revisions whereas the next2 firmware is not. In order for
that compatibility to work, the CMD_ID_DS0 that mainline uses should
change from 0x3 to 0x4

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-08-29 22:43             ` Russ Dill
@ 2013-08-29 23:02               ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-29 23:02 UTC (permalink / raw)
  To: Russ Dill
  Cc: Dave Gerlach, Paul Walmsley, linux-omap, Linux ARM Kernel List,
	Gururaja Hebbar

On Thu, Aug 29, 2013 at 3:43 PM, Russ Dill <Russ.Dill@ti.com> wrote:
> On Thu, Aug 29, 2013 at 3:20 PM, Kevin Hilman <khilman@linaro.org> wrote:
>> Dave Gerlach <d-gerlach@ti.com> writes:
>>
>> [...]
>>
>>>>>
>>>>> The working repo for this version of the patch series can be found here:
>>>>>
>>>>> git://github.com/dgerlach/linux-pm.git am335x-3.11rc4-suspend-resume
>>>>
>>>> I tried this branch on my beaglebone black, and it's not fully resuming.
>>>> Suspend seems to be working (power draw goes from ~1W to ~130mW) and
>>>> pressing a key on the UART seems to be waking up the SoC (power draw
>>>> goes to ~600mW) but I don't ever get the console back.
>>>>
>>>> Is there a specific version of the firmware I should be using?
>>>>
>>>> Kevin
>>>>
>>>
>>> Kevin, I agree there does seem to be some issues with Beaglebone
>>> black. I can confirm it works on BeagleBone White and the large am335
>>> EVM, I am working on pinpointing the issue on beaglebone black, seems
>>> that support isn't quite there yet.
>>
>> OK, I tried the above branch on my BB white, using prebuilt firmware
>> from the next3 branch of the am33x-cm3 repo and it's suspending/resuming
>> fine.  Thanks for the pointer.
>>
>> FYI, measuring at the 5V supply, it goes from ~1.6W at idle down to
>> ~700mW in suspend.  The black goes from ~1W down to an impressive 130mW
>> but of course, it doesn't wake up so maybe it's not that impressive. ;)
>
> Just a reminder, the next3 firmware is built to be compatible with
> older kernel revisions whereas the next2 firmware is not. In order for
> that compatibility to work, the CMD_ID_DS0 that mainline uses should
> change from 0x3 to 0x4

Thanks, i switched to the next2 firmware since I'm only using current kernels.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-08-29 23:02               ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-29 23:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 29, 2013 at 3:43 PM, Russ Dill <Russ.Dill@ti.com> wrote:
> On Thu, Aug 29, 2013 at 3:20 PM, Kevin Hilman <khilman@linaro.org> wrote:
>> Dave Gerlach <d-gerlach@ti.com> writes:
>>
>> [...]
>>
>>>>>
>>>>> The working repo for this version of the patch series can be found here:
>>>>>
>>>>> git://github.com/dgerlach/linux-pm.git am335x-3.11rc4-suspend-resume
>>>>
>>>> I tried this branch on my beaglebone black, and it's not fully resuming.
>>>> Suspend seems to be working (power draw goes from ~1W to ~130mW) and
>>>> pressing a key on the UART seems to be waking up the SoC (power draw
>>>> goes to ~600mW) but I don't ever get the console back.
>>>>
>>>> Is there a specific version of the firmware I should be using?
>>>>
>>>> Kevin
>>>>
>>>
>>> Kevin, I agree there does seem to be some issues with Beaglebone
>>> black. I can confirm it works on BeagleBone White and the large am335
>>> EVM, I am working on pinpointing the issue on beaglebone black, seems
>>> that support isn't quite there yet.
>>
>> OK, I tried the above branch on my BB white, using prebuilt firmware
>> from the next3 branch of the am33x-cm3 repo and it's suspending/resuming
>> fine.  Thanks for the pointer.
>>
>> FYI, measuring at the 5V supply, it goes from ~1.6W at idle down to
>> ~700mW in suspend.  The black goes from ~1W down to an impressive 130mW
>> but of course, it doesn't wake up so maybe it's not that impressive. ;)
>
> Just a reminder, the next3 firmware is built to be compatible with
> older kernel revisions whereas the next2 firmware is not. In order for
> that compatibility to work, the CMD_ID_DS0 that mainline uses should
> change from 0x3 to 0x4

Thanks, i switched to the next2 firmware since I'm only using current kernels.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-08 23:04                 ` Kevin Hilman
@ 2013-08-30 17:29                   ` Vaibhav Bedia
  -1 siblings, 0 replies; 212+ messages in thread
From: Vaibhav Bedia @ 2013-08-30 17:29 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Nishanth Menon, Paul Walmsley, Dave Gerlach, Russ Dill,
	Vaibhav Bedia, Tony Lingren, Santosh Shilimkar, Benoit Cousson,
	linux-omap, Linux ARM Kernel List

(picking up an old thread, again)

On Thu, Aug 8, 2013 at 7:04 PM, Kevin Hilman <khilman@linaro.org> wrote:
>
> I disagree here.  I'm a firmware minimalist, and hiding bugs like this
> in the firmware is wrong when Linux is otherwise managing these devices.
> It also imposes criteria on the firmware of future SoCs that doesn't
> belong there either.  IMO, the only stuff the firmware should do is what
> Linux *cannot* do.
>
> Remember, this only needs to happen when there isn't a driver for these
> devices.  Should we communicate to the firmware that the OS has no
> driver, so please enable the hack?  I think not.
>

Agreed on not hiding the bugs in the firmware. Moreover, M3 can't access
the IPs in PER domain which is where the bad modules are, so the h/w
doesn't support such hackery (+1 for the h/w after all the -1's that it gets ;)

[...]

>>> That being said, IMO, the kernel (specifically omap_device) should
>>> handle this, and it should be rather easy to do in the omap_device layer
>>> and keep the SoC suspend/resume core code simple and ignorant of these
>>> "quirks."
>>>
>>> AFAICT, there's no reason these quirks need to be dealt with immediatly
>>> on suspend.  A slight delay should be fine, as long as it's before the
>>> next suspend/idle attempt, right?
>>>
>>> Given that, what we need to do (and by we, I mean you) is to flag all
>>> broken IP blocks, and let omap_device handle them in a suspend/resume
>>> notifier (c.f. register_pm_notifier() and PM_POST_SUSPEND.)
>>
>> yes - that is the alternate that comes to mind.
>
> In the earlier reviews of this series (many months ago now), I
> complained about the presence of this device specific handling in the
> core MPU PM code.  I'm somewhat troubled by the fact that nobody explored
> alternatives that so easily come to mind.
>

My bad. I was thinking along those lines [1] but after the suggestion on
using the driver bound status i just went with that suggestion in the dumbest
possible manner.

Regards,
Vaibhav

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2012-November/129676.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-30 17:29                   ` Vaibhav Bedia
  0 siblings, 0 replies; 212+ messages in thread
From: Vaibhav Bedia @ 2013-08-30 17:29 UTC (permalink / raw)
  To: linux-arm-kernel

(picking up an old thread, again)

On Thu, Aug 8, 2013 at 7:04 PM, Kevin Hilman <khilman@linaro.org> wrote:
>
> I disagree here.  I'm a firmware minimalist, and hiding bugs like this
> in the firmware is wrong when Linux is otherwise managing these devices.
> It also imposes criteria on the firmware of future SoCs that doesn't
> belong there either.  IMO, the only stuff the firmware should do is what
> Linux *cannot* do.
>
> Remember, this only needs to happen when there isn't a driver for these
> devices.  Should we communicate to the firmware that the OS has no
> driver, so please enable the hack?  I think not.
>

Agreed on not hiding the bugs in the firmware. Moreover, M3 can't access
the IPs in PER domain which is where the bad modules are, so the h/w
doesn't support such hackery (+1 for the h/w after all the -1's that it gets ;)

[...]

>>> That being said, IMO, the kernel (specifically omap_device) should
>>> handle this, and it should be rather easy to do in the omap_device layer
>>> and keep the SoC suspend/resume core code simple and ignorant of these
>>> "quirks."
>>>
>>> AFAICT, there's no reason these quirks need to be dealt with immediatly
>>> on suspend.  A slight delay should be fine, as long as it's before the
>>> next suspend/idle attempt, right?
>>>
>>> Given that, what we need to do (and by we, I mean you) is to flag all
>>> broken IP blocks, and let omap_device handle them in a suspend/resume
>>> notifier (c.f. register_pm_notifier() and PM_POST_SUSPEND.)
>>
>> yes - that is the alternate that comes to mind.
>
> In the earlier reviews of this series (many months ago now), I
> complained about the presence of this device specific handling in the
> core MPU PM code.  I'm somewhat troubled by the fact that nobody explored
> alternatives that so easily come to mind.
>

My bad. I was thinking along those lines [1] but after the suggestion on
using the driver bound status i just went with that suggestion in the dumbest
possible manner.

Regards,
Vaibhav

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2012-November/129676.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-27 21:45     ` Kevin Hilman
@ 2013-08-30 17:39       ` Vaibhav Bedia
  -1 siblings, 0 replies; 212+ messages in thread
From: Vaibhav Bedia @ 2013-08-30 17:39 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Dave Gerlach, Paul Walmsley, Tony Lingren, Vaibhav Bedia,
	Santosh Shilimkar, Benoit Cousson, linux-omap,
	Linux ARM Kernel List

On Tue, Aug 27, 2013 at 5:45 PM, Kevin Hilman <khilman@linaro.org> wrote:
[...]
>
> Looking closer at this code as I'm trying to fully get my head around
> all the IPC, I have some more comments.
>
> I think the split between pm33xx.c and the M3 driver is still confusing
> here.  For example, am33xx_ping_wkup_m3(),
> am33xx_m3_state_machine_reset() and the guts of am33xx_pm_begin() all
> belong inside the M3 driver, along with all the wakeup_src stuff, which
> is info coming from the M3.
>
> IOW, the communication with M3 should be abstracted from pm33xx by the
> M3 driver (or possibly an eventual remoteproc/rpmsg implementation) with
> a well defined API.  In this implementation, the interface is pretty
> fuzzy and mixed between pm33xx.c and wkup_m3.c.
>
>

The reason for the current split was to have the M3 driver just do the minimal
that's needed to talk to get M3 and MPU talking. What made me do it this way
was to attempt to address a previous comment on keeping options open for folks
to use M3 for things other than PM stuff. The IPC stuff is how
implementors of the
firmware (anything other than the PM one that TI provides) want it to be.

The top level idea was to have the users of the firmware (PM in this case)
decide what functionality they want when talking to M3. They are also free to
decide the register bitfield layout and other IPC details.

This was also a feeble attempt to keep things extensible for AM437x where
in addition to the broken mailbox usage there's now a control module bit
to trigger the interrupt to M3 (what's worse? pick one that you hate more ;)
The AM437x PM routines could then just register different callbacks that
are triggered when the M3 interrupts the MPU.

Hope this clears up some of the confusion.

Regards,
Vaibhav

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-30 17:39       ` Vaibhav Bedia
  0 siblings, 0 replies; 212+ messages in thread
From: Vaibhav Bedia @ 2013-08-30 17:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 27, 2013 at 5:45 PM, Kevin Hilman <khilman@linaro.org> wrote:
[...]
>
> Looking closer at this code as I'm trying to fully get my head around
> all the IPC, I have some more comments.
>
> I think the split between pm33xx.c and the M3 driver is still confusing
> here.  For example, am33xx_ping_wkup_m3(),
> am33xx_m3_state_machine_reset() and the guts of am33xx_pm_begin() all
> belong inside the M3 driver, along with all the wakeup_src stuff, which
> is info coming from the M3.
>
> IOW, the communication with M3 should be abstracted from pm33xx by the
> M3 driver (or possibly an eventual remoteproc/rpmsg implementation) with
> a well defined API.  In this implementation, the interface is pretty
> fuzzy and mixed between pm33xx.c and wkup_m3.c.
>
>

The reason for the current split was to have the M3 driver just do the minimal
that's needed to talk to get M3 and MPU talking. What made me do it this way
was to attempt to address a previous comment on keeping options open for folks
to use M3 for things other than PM stuff. The IPC stuff is how
implementors of the
firmware (anything other than the PM one that TI provides) want it to be.

The top level idea was to have the users of the firmware (PM in this case)
decide what functionality they want when talking to M3. They are also free to
decide the register bitfield layout and other IPC details.

This was also a feeble attempt to keep things extensible for AM437x where
in addition to the broken mailbox usage there's now a control module bit
to trigger the interrupt to M3 (what's worse? pick one that you hate more ;)
The AM437x PM routines could then just register different callbacks that
are triggered when the M3 interrupts the MPU.

Hope this clears up some of the confusion.

Regards,
Vaibhav

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
  2013-08-30 17:39       ` Vaibhav Bedia
@ 2013-08-30 21:18         ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-30 21:18 UTC (permalink / raw)
  To: Vaibhav Bedia
  Cc: Dave Gerlach, Paul Walmsley, Tony Lingren, Vaibhav Bedia,
	Santosh Shilimkar, Benoit Cousson, linux-omap,
	Linux ARM Kernel List

Vaibhav Bedia <vaibhav.bedia@gmail.com> writes:

> On Tue, Aug 27, 2013 at 5:45 PM, Kevin Hilman <khilman@linaro.org> wrote:
> [...]
>>
>> Looking closer at this code as I'm trying to fully get my head around
>> all the IPC, I have some more comments.
>>
>> I think the split between pm33xx.c and the M3 driver is still confusing
>> here.  For example, am33xx_ping_wkup_m3(),
>> am33xx_m3_state_machine_reset() and the guts of am33xx_pm_begin() all
>> belong inside the M3 driver, along with all the wakeup_src stuff, which
>> is info coming from the M3.
>>
>> IOW, the communication with M3 should be abstracted from pm33xx by the
>> M3 driver (or possibly an eventual remoteproc/rpmsg implementation) with
>> a well defined API.  In this implementation, the interface is pretty
>> fuzzy and mixed between pm33xx.c and wkup_m3.c.
>>
>>
>
> The reason for the current split was to have the M3 driver just do the minimal
> that's needed to talk to get M3 and MPU talking. What made me do it this way
> was to attempt to address a previous comment on keeping options open for folks
> to use M3 for things other than PM stuff. The IPC stuff is how
> implementors of the
> firmware (anything other than the PM one that TI provides) want it to be.

IMO, there should actually be 3 levels. the SoC PM implementation
(pm33xx.c), the M3 driver where the protocol, state-machine, etc. are
handled, and the messaging layer.  In the current proposal, the last 2
are combined, but I'd really like to see a generalized messaging layer
that everyone else using an M3 coprocessor might use as well.  As
mentioned already, I think that should be rpmsg, but that still needs
some exploration.

> The top level idea was to have the users of the firmware (PM in this case)
> decide what functionality they want when talking to M3. They are also free to
> decide the register bitfield layout and other IPC details.
>
> This was also a feeble attempt to keep things extensible for AM437x where
> in addition to the broken mailbox usage there's now a control module bit
> to trigger the interrupt to M3 (what's worse? pick one that you hate more ;)

Sounds like AM43xx is better.  If you have a control module bit to
trigger an interrupt, why do you need the mailbox at all?

> The AM437x PM routines could then just register different callbacks that
> are triggered when the M3 interrupts the MPU.
>
> Hope this clears up some of the confusion.

Thanks,

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support
@ 2013-08-30 21:18         ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-08-30 21:18 UTC (permalink / raw)
  To: linux-arm-kernel

Vaibhav Bedia <vaibhav.bedia@gmail.com> writes:

> On Tue, Aug 27, 2013 at 5:45 PM, Kevin Hilman <khilman@linaro.org> wrote:
> [...]
>>
>> Looking closer at this code as I'm trying to fully get my head around
>> all the IPC, I have some more comments.
>>
>> I think the split between pm33xx.c and the M3 driver is still confusing
>> here.  For example, am33xx_ping_wkup_m3(),
>> am33xx_m3_state_machine_reset() and the guts of am33xx_pm_begin() all
>> belong inside the M3 driver, along with all the wakeup_src stuff, which
>> is info coming from the M3.
>>
>> IOW, the communication with M3 should be abstracted from pm33xx by the
>> M3 driver (or possibly an eventual remoteproc/rpmsg implementation) with
>> a well defined API.  In this implementation, the interface is pretty
>> fuzzy and mixed between pm33xx.c and wkup_m3.c.
>>
>>
>
> The reason for the current split was to have the M3 driver just do the minimal
> that's needed to talk to get M3 and MPU talking. What made me do it this way
> was to attempt to address a previous comment on keeping options open for folks
> to use M3 for things other than PM stuff. The IPC stuff is how
> implementors of the
> firmware (anything other than the PM one that TI provides) want it to be.

IMO, there should actually be 3 levels. the SoC PM implementation
(pm33xx.c), the M3 driver where the protocol, state-machine, etc. are
handled, and the messaging layer.  In the current proposal, the last 2
are combined, but I'd really like to see a generalized messaging layer
that everyone else using an M3 coprocessor might use as well.  As
mentioned already, I think that should be rpmsg, but that still needs
some exploration.

> The top level idea was to have the users of the firmware (PM in this case)
> decide what functionality they want when talking to M3. They are also free to
> decide the register bitfield layout and other IPC details.
>
> This was also a feeble attempt to keep things extensible for AM437x where
> in addition to the broken mailbox usage there's now a control module bit
> to trigger the interrupt to M3 (what's worse? pick one that you hate more ;)

Sounds like AM43xx is better.  If you have a control module bit to
trigger an interrupt, why do you need the mailbox at all?

> The AM437x PM routines could then just register different callbacks that
> are triggered when the M3 interrupts the MPU.
>
> Hope this clears up some of the confusion.

Thanks,

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-08-29 23:02               ` Kevin Hilman
@ 2013-09-03 17:24                 ` Dave Gerlach
  -1 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-09-03 17:24 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Paul Walmsley, linux-omap, Russ Dill, Linux ARM Kernel List,
	Gururaja Hebbar

On 08/29/2013 06:02 PM, Kevin Hilman wrote:
> On Thu, Aug 29, 2013 at 3:43 PM, Russ Dill <Russ.Dill@ti.com> wrote:
>> On Thu, Aug 29, 2013 at 3:20 PM, Kevin Hilman <khilman@linaro.org> wrote:
>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>
>>> [...]
>>>
>>>>>>
>>>>>> The working repo for this version of the patch series can be found here:
>>>>>>
>>>>>> git://github.com/dgerlach/linux-pm.git am335x-3.11rc4-suspend-resume
>>>>>
>>>>> I tried this branch on my beaglebone black, and it's not fully resuming.
>>>>> Suspend seems to be working (power draw goes from ~1W to ~130mW) and
>>>>> pressing a key on the UART seems to be waking up the SoC (power draw
>>>>> goes to ~600mW) but I don't ever get the console back.
>>>>>
>>>>> Is there a specific version of the firmware I should be using?
>>>>>
>>>>> Kevin
>>>>>
>>>>
>>>> Kevin, I agree there does seem to be some issues with Beaglebone
>>>> black. I can confirm it works on BeagleBone White and the large am335
>>>> EVM, I am working on pinpointing the issue on beaglebone black, seems
>>>> that support isn't quite there yet.
>>>
>>> OK, I tried the above branch on my BB white, using prebuilt firmware
>>> from the next3 branch of the am33x-cm3 repo and it's suspending/resuming
>>> fine.  Thanks for the pointer.
>>>
>>> FYI, measuring at the 5V supply, it goes from ~1.6W at idle down to
>>> ~700mW in suspend.  The black goes from ~1W down to an impressive 130mW
>>> but of course, it doesn't wake up so maybe it's not that impressive. ;)
>>
>> Just a reminder, the next3 firmware is built to be compatible with
>> older kernel revisions whereas the next2 firmware is not. In order for
>> that compatibility to work, the CMD_ID_DS0 that mainline uses should
>> change from 0x3 to 0x4
>
> Thanks, i switched to the next2 firmware since I'm only using current kernels.
>
> Kevin
>

Kevin,
Thanks for taking the time to try this out, it does seem there are a few 
kinks with BeagleBone Black but we'll get those worked out.

Regards,
Dave

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-09-03 17:24                 ` Dave Gerlach
  0 siblings, 0 replies; 212+ messages in thread
From: Dave Gerlach @ 2013-09-03 17:24 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/29/2013 06:02 PM, Kevin Hilman wrote:
> On Thu, Aug 29, 2013 at 3:43 PM, Russ Dill <Russ.Dill@ti.com> wrote:
>> On Thu, Aug 29, 2013 at 3:20 PM, Kevin Hilman <khilman@linaro.org> wrote:
>>> Dave Gerlach <d-gerlach@ti.com> writes:
>>>
>>> [...]
>>>
>>>>>>
>>>>>> The working repo for this version of the patch series can be found here:
>>>>>>
>>>>>> git://github.com/dgerlach/linux-pm.git am335x-3.11rc4-suspend-resume
>>>>>
>>>>> I tried this branch on my beaglebone black, and it's not fully resuming.
>>>>> Suspend seems to be working (power draw goes from ~1W to ~130mW) and
>>>>> pressing a key on the UART seems to be waking up the SoC (power draw
>>>>> goes to ~600mW) but I don't ever get the console back.
>>>>>
>>>>> Is there a specific version of the firmware I should be using?
>>>>>
>>>>> Kevin
>>>>>
>>>>
>>>> Kevin, I agree there does seem to be some issues with Beaglebone
>>>> black. I can confirm it works on BeagleBone White and the large am335
>>>> EVM, I am working on pinpointing the issue on beaglebone black, seems
>>>> that support isn't quite there yet.
>>>
>>> OK, I tried the above branch on my BB white, using prebuilt firmware
>>> from the next3 branch of the am33x-cm3 repo and it's suspending/resuming
>>> fine.  Thanks for the pointer.
>>>
>>> FYI, measuring at the 5V supply, it goes from ~1.6W at idle down to
>>> ~700mW in suspend.  The black goes from ~1W down to an impressive 130mW
>>> but of course, it doesn't wake up so maybe it's not that impressive. ;)
>>
>> Just a reminder, the next3 firmware is built to be compatible with
>> older kernel revisions whereas the next2 firmware is not. In order for
>> that compatibility to work, the CMD_ID_DS0 that mainline uses should
>> change from 0x3 to 0x4
>
> Thanks, i switched to the next2 firmware since I'm only using current kernels.
>
> Kevin
>

Kevin,
Thanks for taking the time to try this out, it does seem there are a few 
kinks with BeagleBone Black but we'll get those worked out.

Regards,
Dave

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-09-03 17:24                 ` Dave Gerlach
@ 2013-09-04 15:01                   ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-09-04 15:01 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: Russ Dill, Paul Walmsley, linux-omap, Linux ARM Kernel List,
	Gururaja Hebbar

Hi Dave,

> Thanks for taking the time to try this out, it does seem there are a few
> kinks with BeagleBone Black but we'll get those worked out.

I also just noticed that wake from RTC isn't working, but wake from
serial console does.  Does RTC wake work for you?  (I use rtcwake -m
mem -s4)

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-09-04 15:01                   ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-09-04 15:01 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Dave,

> Thanks for taking the time to try this out, it does seem there are a few
> kinks with BeagleBone Black but we'll get those worked out.

I also just noticed that wake from RTC isn't working, but wake from
serial console does.  Does RTC wake work for you?  (I use rtcwake -m
mem -s4)

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-09-04 15:01                   ` Kevin Hilman
@ 2013-09-04 15:12                     ` Russ Dill
  -1 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-09-04 15:12 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Dave Gerlach, Paul Walmsley, linux-omap, Linux ARM Kernel List,
	Gururaja Hebbar

On Wed, Sep 4, 2013 at 8:01 AM, Kevin Hilman <khilman@linaro.org> wrote:
> Hi Dave,
>
>> Thanks for taking the time to try this out, it does seem there are a few
>> kinks with BeagleBone Black but we'll get those worked out.
>
> I also just noticed that wake from RTC isn't working, but wake from
> serial console does.  Does RTC wake work for you?  (I use rtcwake -m
> mem -s4)
>
> Kevin

On Beaglebone white or black? For PG 1.0 (Beaglebone white) there is
the following errata:

"RTC: 32.768-kHZ Clock is Gating Off"

Details The RTC has a clock gating issue that stops the internal
32.768-kHz clock when the VDD_CORE voltage domain drops below the
recommended operating range or the PWRONRSTn input terminal is held
low. This issue has the following side effects:

- The RTC counters stop incrementing when the 32.768-kHz clock is
gated. This causes the RTC to lose time while the clock is gated.

- A wakeup event applied to the EXT_WAKEUP input terminal is masked if
the EXT_WAKEUP_DB_EN bit in the RTC PMIC register (0x98) is set to 1
which enables the de-bounce function for the EXT_WAKEUP input. This
occurs because the 32.768-kHz clock is being used to clock the
de-bounce circuit.

> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-09-04 15:12                     ` Russ Dill
  0 siblings, 0 replies; 212+ messages in thread
From: Russ Dill @ 2013-09-04 15:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Sep 4, 2013 at 8:01 AM, Kevin Hilman <khilman@linaro.org> wrote:
> Hi Dave,
>
>> Thanks for taking the time to try this out, it does seem there are a few
>> kinks with BeagleBone Black but we'll get those worked out.
>
> I also just noticed that wake from RTC isn't working, but wake from
> serial console does.  Does RTC wake work for you?  (I use rtcwake -m
> mem -s4)
>
> Kevin

On Beaglebone white or black? For PG 1.0 (Beaglebone white) there is
the following errata:

"RTC: 32.768-kHZ Clock is Gating Off"

Details The RTC has a clock gating issue that stops the internal
32.768-kHz clock when the VDD_CORE voltage domain drops below the
recommended operating range or the PWRONRSTn input terminal is held
low. This issue has the following side effects:

- The RTC counters stop incrementing when the 32.768-kHz clock is
gated. This causes the RTC to lose time while the clock is gated.

- A wakeup event applied to the EXT_WAKEUP input terminal is masked if
the EXT_WAKEUP_DB_EN bit in the RTC PMIC register (0x98) is set to 1
which enables the de-bounce function for the EXT_WAKEUP input. This
occurs because the 32.768-kHz clock is being used to clock the
de-bounce circuit.

> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 212+ messages in thread

* Re: [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
  2013-09-04 15:12                     ` Russ Dill
@ 2013-09-04 15:18                       ` Kevin Hilman
  -1 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-09-04 15:18 UTC (permalink / raw)
  To: Russ Dill
  Cc: Dave Gerlach, Paul Walmsley, linux-omap, Linux ARM Kernel List,
	Gururaja Hebbar

On Wed, Sep 4, 2013 at 8:12 AM, Russ Dill <Russ.Dill@ti.com> wrote:
> On Wed, Sep 4, 2013 at 8:01 AM, Kevin Hilman <khilman@linaro.org> wrote:
>> Hi Dave,
>>
>>> Thanks for taking the time to try this out, it does seem there are a few
>>> kinks with BeagleBone Black but we'll get those worked out.
>>
>> I also just noticed that wake from RTC isn't working, but wake from
>> serial console does.  Does RTC wake work for you?  (I use rtcwake -m
>> mem -s4)
>>
>> Kevin
>
> On Beaglebone white or black?

White.

> For PG 1.0 (Beaglebone white) there is
> the following errata:
>
> "RTC: 32.768-kHZ Clock is Gating Off"
>
> Details The RTC has a clock gating issue that stops the internal
> 32.768-kHz clock when the VDD_CORE voltage domain drops below the
> recommended operating range or the PWRONRSTn input terminal is held
> low. This issue has the following side effects:
>
> - The RTC counters stop incrementing when the 32.768-kHz clock is
> gated. This causes the RTC to lose time while the clock is gated.
>
> - A wakeup event applied to the EXT_WAKEUP input terminal is masked if
> the EXT_WAKEUP_DB_EN bit in the RTC PMIC register (0x98) is set to 1
> which enables the de-bounce function for the EXT_WAKEUP input. This
> occurs because the 32.768-kHz clock is being used to clock the
> de-bounce circuit.

I'm not using your VDD_CORE scaling series (or maybe the firmware is
scaling VDD_CORE?)

Anyways, thanks for the info on the errata, that must be what's causing it.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

* [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support
@ 2013-09-04 15:18                       ` Kevin Hilman
  0 siblings, 0 replies; 212+ messages in thread
From: Kevin Hilman @ 2013-09-04 15:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Sep 4, 2013 at 8:12 AM, Russ Dill <Russ.Dill@ti.com> wrote:
> On Wed, Sep 4, 2013 at 8:01 AM, Kevin Hilman <khilman@linaro.org> wrote:
>> Hi Dave,
>>
>>> Thanks for taking the time to try this out, it does seem there are a few
>>> kinks with BeagleBone Black but we'll get those worked out.
>>
>> I also just noticed that wake from RTC isn't working, but wake from
>> serial console does.  Does RTC wake work for you?  (I use rtcwake -m
>> mem -s4)
>>
>> Kevin
>
> On Beaglebone white or black?

White.

> For PG 1.0 (Beaglebone white) there is
> the following errata:
>
> "RTC: 32.768-kHZ Clock is Gating Off"
>
> Details The RTC has a clock gating issue that stops the internal
> 32.768-kHz clock when the VDD_CORE voltage domain drops below the
> recommended operating range or the PWRONRSTn input terminal is held
> low. This issue has the following side effects:
>
> - The RTC counters stop incrementing when the 32.768-kHz clock is
> gated. This causes the RTC to lose time while the clock is gated.
>
> - A wakeup event applied to the EXT_WAKEUP input terminal is masked if
> the EXT_WAKEUP_DB_EN bit in the RTC PMIC register (0x98) is set to 1
> which enables the de-bounce function for the EXT_WAKEUP input. This
> occurs because the 32.768-kHz clock is being used to clock the
> de-bounce circuit.

I'm not using your VDD_CORE scaling series (or maybe the firmware is
scaling VDD_CORE?)

Anyways, thanks for the info on the errata, that must be what's causing it.

Kevin

^ permalink raw reply	[flat|nested] 212+ messages in thread

end of thread, other threads:[~2013-09-04 15:18 UTC | newest]

Thread overview: 212+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-06 17:49 [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support Dave Gerlach
2013-08-06 17:49 ` Dave Gerlach
2013-08-06 17:49 ` [PATCHv3 1/9] memory: emif: Move EMIF register defines to include/linux/ Dave Gerlach
2013-08-06 17:49   ` Dave Gerlach
2013-08-08  0:48   ` Russ Dill
2013-08-08  0:48     ` Russ Dill
2013-08-08 13:35   ` Santosh Shilimkar
2013-08-08 13:35     ` Santosh Shilimkar
2013-08-12 19:32     ` Greg Kroah-Hartman
2013-08-12 19:32       ` Greg Kroah-Hartman
2013-08-12 19:33       ` Santosh Shilimkar
2013-08-12 19:33         ` Santosh Shilimkar
2013-08-06 17:49 ` [PATCHv3 2/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs Dave Gerlach
2013-08-06 17:49   ` Dave Gerlach
2013-08-08  0:52   ` Russ Dill
2013-08-08  0:52     ` Russ Dill
2013-08-08 13:44   ` Santosh Shilimkar
2013-08-08 13:44     ` Santosh Shilimkar
2013-08-08 16:16     ` Dave Gerlach
2013-08-08 16:16       ` Dave Gerlach
2013-08-09  5:11       ` Tony Lindgren
2013-08-09  5:11         ` Tony Lindgren
2013-08-09 20:55         ` Dave Gerlach
2013-08-09 20:55           ` Dave Gerlach
2013-08-12  7:54           ` Tony Lindgren
2013-08-12  7:54             ` Tony Lindgren
2013-08-12 19:17           ` Kevin Hilman
2013-08-12 19:17             ` Kevin Hilman
2013-08-12 21:40             ` Dave Gerlach
2013-08-12 21:40               ` Dave Gerlach
2013-08-13 14:29               ` Kevin Hilman
2013-08-13 14:29                 ` Kevin Hilman
2013-08-13 15:08                 ` Santosh Shilimkar
2013-08-13 15:08                   ` Santosh Shilimkar
2013-08-13 16:19                   ` Kevin Hilman
2013-08-13 16:19                     ` Kevin Hilman
2013-08-13 18:18                     ` Santosh Shilimkar
2013-08-13 18:18                       ` Santosh Shilimkar
2013-08-13 18:30                       ` Russ Dill
2013-08-13 18:30                         ` Russ Dill
2013-08-13 18:40                         ` Santosh Shilimkar
2013-08-13 18:40                           ` Santosh Shilimkar
2013-08-13 19:11                         ` Kevin Hilman
2013-08-13 19:11                           ` Kevin Hilman
2013-08-14 17:27                           ` Suman Anna
2013-08-14 17:27                             ` Suman Anna
2013-08-14 19:16                             ` Russ Dill
2013-08-14 19:16                               ` Russ Dill
2013-08-20 23:39                             ` Paul Walmsley
2013-08-20 23:39                               ` Paul Walmsley
2013-08-21 17:32                               ` Suman Anna
2013-08-21 17:32                                 ` Suman Anna
2013-08-06 17:49 ` [PATCHv3 3/9] ARM: OMAP: DTB: Update IRQ data for WKUP_M3 Dave Gerlach
2013-08-06 17:49   ` Dave Gerlach
2013-08-08  0:53   ` Russ Dill
2013-08-08  0:53     ` Russ Dill
2013-08-08 13:46   ` Santosh Shilimkar
2013-08-08 13:46     ` Santosh Shilimkar
2013-08-06 17:49 ` [PATCHv3 4/9] ARM: OMAP2+: AM33XX: Reserve memory to comply with EMIF spec Dave Gerlach
2013-08-06 17:49   ` Dave Gerlach
2013-08-08  2:30   ` Russ Dill
2013-08-08  2:30     ` Russ Dill
2013-08-08 14:19   ` Santosh Shilimkar
2013-08-08 14:19     ` Santosh Shilimkar
2013-08-08 18:16   ` Kevin Hilman
2013-08-08 18:16     ` Kevin Hilman
2013-08-08 19:31     ` Santosh Shilimkar
2013-08-08 19:31       ` Santosh Shilimkar
2013-08-08 20:05       ` Kevin Hilman
2013-08-08 20:05         ` Kevin Hilman
2013-08-08 20:11         ` Santosh Shilimkar
2013-08-08 20:11           ` Santosh Shilimkar
2013-08-09 15:11           ` Kevin Hilman
2013-08-09 15:11             ` Kevin Hilman
2013-08-09 16:25             ` Dave Gerlach
2013-08-09 16:25               ` Dave Gerlach
2013-08-06 17:49 ` [PATCHv3 5/9] ARM: OMAP2+: AM33XX: Add assembly code for PM operations Dave Gerlach
2013-08-06 17:49   ` Dave Gerlach
2013-08-08  7:02   ` Russ Dill
2013-08-08  7:02     ` Russ Dill
2013-08-08 14:50   ` Santosh Shilimkar
2013-08-08 14:50     ` Santosh Shilimkar
2013-08-08 15:16     ` Russ Dill
2013-08-08 15:16       ` Russ Dill
2013-08-08 15:22       ` Santosh Shilimkar
2013-08-08 15:22         ` Santosh Shilimkar
2013-08-08 16:03         ` Russ Dill
2013-08-08 16:03           ` Russ Dill
2013-08-19 12:54   ` Gururaja Hebbar
2013-08-19 12:54     ` Gururaja Hebbar
2013-08-19 17:51     ` Dave Gerlach
2013-08-19 17:51       ` Dave Gerlach
2013-08-06 17:49 ` [PATCHv3 6/9] ARM: OMAP2+: timer: Add suspend-resume callbacks for clkevent device Dave Gerlach
2013-08-06 17:49   ` Dave Gerlach
2013-08-08  7:03   ` Russ Dill
2013-08-08  7:03     ` Russ Dill
2013-08-08 14:23   ` Santosh Shilimkar
2013-08-08 14:23     ` Santosh Shilimkar
2013-08-08 16:09     ` Dave Gerlach
2013-08-08 16:09       ` Dave Gerlach
2013-08-08 18:25   ` Kevin Hilman
2013-08-08 18:25     ` Kevin Hilman
2013-08-08 19:49     ` Dave Gerlach
2013-08-08 19:49       ` Dave Gerlach
2013-08-06 17:49 ` [PATCHv3 7/9] ARM: OMAP: omap_device: Add APIs to enable and idle hwmods Dave Gerlach
2013-08-06 17:49   ` Dave Gerlach
2013-08-08  7:05   ` Russ Dill
2013-08-08  7:05     ` Russ Dill
2013-08-08 14:26   ` Santosh Shilimkar
2013-08-08 14:26     ` Santosh Shilimkar
2013-08-06 17:49 ` [PATCHv3 8/9] ARM: OMAP2+: AM33XX: Basic suspend resume support Dave Gerlach
2013-08-06 17:49   ` Dave Gerlach
2013-08-07 16:22   ` Nishanth Menon
2013-08-07 16:22     ` Nishanth Menon
2013-08-07 18:12     ` Dave Gerlach
2013-08-07 18:12       ` Dave Gerlach
2013-08-07 19:16       ` Nishanth Menon
2013-08-07 19:16         ` Nishanth Menon
2013-08-08  8:45   ` Russ Dill
2013-08-08  8:45     ` Russ Dill
2013-08-08 12:26     ` Nishanth Menon
2013-08-08 12:26       ` Nishanth Menon
2013-08-08 15:03       ` Santosh Shilimkar
2013-08-08 15:03         ` Santosh Shilimkar
2013-08-08 16:06         ` Dave Gerlach
2013-08-08 16:06           ` Dave Gerlach
2013-08-08 16:22           ` Nishanth Menon
2013-08-08 16:22             ` Nishanth Menon
2013-08-08 21:14           ` Kevin Hilman
2013-08-08 21:14             ` Kevin Hilman
2013-08-08 21:32             ` Nishanth Menon
2013-08-08 21:32               ` Nishanth Menon
2013-08-08 23:04               ` Kevin Hilman
2013-08-08 23:04                 ` Kevin Hilman
2013-08-09 15:11                 ` Nishanth Menon
2013-08-09 15:11                   ` Nishanth Menon
2013-08-09 16:12                   ` Kevin Hilman
2013-08-09 16:12                     ` Kevin Hilman
2013-08-09 16:36                     ` Nishanth Menon
2013-08-09 16:36                       ` Nishanth Menon
2013-08-09 20:34                       ` Kevin Hilman
2013-08-09 20:34                         ` Kevin Hilman
2013-08-09 21:35                         ` Nishanth Menon
2013-08-09 21:35                           ` Nishanth Menon
2013-08-09 22:28                         ` Russ Dill
2013-08-09 22:28                           ` Russ Dill
2013-08-12 16:09                           ` Kevin Hilman
2013-08-12 16:09                             ` Kevin Hilman
2013-08-30 17:29                 ` Vaibhav Bedia
2013-08-30 17:29                   ` Vaibhav Bedia
2013-08-20 22:48             ` Paul Walmsley
2013-08-20 22:48               ` Paul Walmsley
2013-08-23 14:56               ` Dave Gerlach
2013-08-23 14:56                 ` Dave Gerlach
2013-08-13  7:43   ` Russ Dill
2013-08-13  7:43     ` Russ Dill
2013-08-13 14:59     ` Kevin Hilman
2013-08-13 14:59       ` Kevin Hilman
2013-08-27 21:45   ` Kevin Hilman
2013-08-27 21:45     ` Kevin Hilman
2013-08-29 21:41     ` Dave Gerlach
2013-08-29 21:41       ` Dave Gerlach
2013-08-29 22:02       ` Kevin Hilman
2013-08-29 22:02         ` Kevin Hilman
2013-08-30 17:39     ` Vaibhav Bedia
2013-08-30 17:39       ` Vaibhav Bedia
2013-08-30 21:18       ` Kevin Hilman
2013-08-30 21:18         ` Kevin Hilman
2013-08-06 17:49 ` [PATCHv3 9/9] ARM: OMAP2+: AM33XX: Hookup AM33XX PM code into OMAP builds Dave Gerlach
2013-08-06 17:49   ` Dave Gerlach
2013-08-08  8:47   ` Russ Dill
2013-08-08  8:47     ` Russ Dill
2013-08-08 14:53   ` Santosh Shilimkar
2013-08-08 14:53     ` Santosh Shilimkar
2013-08-08 13:31 ` [PATCHv3 0/9] ARM: OMAP2+: AM33XX: Add suspend-resume support Santosh Shilimkar
2013-08-08 13:31   ` Santosh Shilimkar
2013-08-11 11:53 ` Daniel Mack
2013-08-11 11:53   ` Daniel Mack
2013-08-12 18:59   ` Dave Gerlach
2013-08-12 18:59     ` Dave Gerlach
2013-08-13 12:39     ` Daniel Mack
2013-08-13 12:39       ` Daniel Mack
2013-08-13 15:33       ` Dave Gerlach
2013-08-13 15:33         ` Dave Gerlach
2013-08-13 15:51         ` Daniel Mack
2013-08-13 15:51           ` Daniel Mack
2013-08-19  9:23 ` Gururaja Hebbar
2013-08-19  9:23   ` Gururaja Hebbar
2013-08-19 17:47   ` Dave Gerlach
2013-08-19 17:47     ` Dave Gerlach
2013-08-27 20:23     ` Kevin Hilman
2013-08-27 20:23       ` Kevin Hilman
2013-08-29 21:30       ` Dave Gerlach
2013-08-29 21:30         ` Dave Gerlach
2013-08-29 21:52         ` Kevin Hilman
2013-08-29 21:52           ` Kevin Hilman
2013-08-29 22:20           ` Dave Gerlach
2013-08-29 22:20             ` Dave Gerlach
2013-08-29 22:20         ` Kevin Hilman
2013-08-29 22:20           ` Kevin Hilman
2013-08-29 22:43           ` Russ Dill
2013-08-29 22:43             ` Russ Dill
2013-08-29 23:02             ` Kevin Hilman
2013-08-29 23:02               ` Kevin Hilman
2013-09-03 17:24               ` Dave Gerlach
2013-09-03 17:24                 ` Dave Gerlach
2013-09-04 15:01                 ` Kevin Hilman
2013-09-04 15:01                   ` Kevin Hilman
2013-09-04 15:12                   ` Russ Dill
2013-09-04 15:12                     ` Russ Dill
2013-09-04 15:18                     ` Kevin Hilman
2013-09-04 15:18                       ` Kevin Hilman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.