All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-03-16 21:51 ` Aneesh V
  0 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-03-16 21:51 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-arm-kernel, linux-omap, Aneesh V, Greg KH

Add a driver for the EMIF SDRAM controller used in TI SoCs

EMIF is an SDRAM controller that supports, based on its revision,
one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
for LPDDR2.

The driver supports the following features:
- Calculates the DDR AC timing parameters to be set in EMIF
  registers using data from the device data-sheets and based
  on the DDR frequency. If data from data-sheets is not available
  default timing values from the JEDEC spec are used. These
  will be safe, but not necessarily optimal
- API for changing timings during DVFS or at boot-up
- Temperature alert configuration and handling of temperature
  alerts, if any for LPDDR2 devices
  * temperature alert is based on periodic polling of MR4 mode
    register in DDR devices automatically performed by hardware
  * timings are de-rated and brought back to nominal when
    temperature raises and falls respectively
- Cache of calculated register values to avoid re-calculating
  them

The driver will need some minor updates when it is eventually
integrated with Dynamic Voltage and Frequency Scaling (DVFS).
This can not be done now as DVFS support is not available in
the mainline yet.

Discussions with Santosh Shilimkar <santosh.shilimkar@ti.com>
were immensely helpful in shaping up the interfaces. Vibhore Vardhan
<vvardhan@gmail.com> did the initial code snippet for thermal
handling.

Testing: 
- The driver is tested on OMAP4430 SDP.
- The driver in a slightly adapted form is also tested on OMAP5.
- Since mainline kernel doesn't have DVFS support yet,
  testing was done using a test module.
- Temperature alert handling was tested with simulated interrupts
  and faked temperature values as testing all cases in real-life
  scenarios is difficult.
- Tested the driver as a module

Cc: Greg KH <greg@kroah.com>

v4:
- Converted instances of EXPORT_SYMBOL to EXPORT_SYMBOL_GPL
- Removed un-necessary "#ifndef __ASSEMBLY__'
- Minor formatting fix

v2:
- Fixed a bug found in the implementation of errata i728
  workaround
- Fixed the value of frequency printed in debugfs
- Dropped the hwmod patch as Paul has already posted a
  a hwmod series [1] that adds hwmod for EMIF
- Converted instances of __init to __init_or_module

[1] http://thread.gmane.org/gmane.linux.ports.arm.omap/72855

Aneesh V (7):
  misc: ddr: add LPDDR2 data from JESD209-2
  misc: emif: add register definitions for EMIF
  misc: emif: add basic infrastructure for EMIF driver
  misc: emif: handle frequency and voltage change events
  misc: emif: add interrupt and temperature handling
  misc: emif: add one-time settings
  misc: emif: add debugfs entries for emif

 Documentation/misc-devices/ti-emif.txt  |   58 ++
 drivers/misc/Kconfig                    |   12 +
 drivers/misc/Makefile                   |    1 +
 drivers/misc/emif.c                     | 1670 +++++++++++++++++++++++++++++++
 drivers/misc/emif.h                     |  589 +++++++++++
 include/linux/platform_data/emif_plat.h |  128 +++
 include/misc/jedec_ddr.h                |  175 ++++
 lib/Kconfig                             |    8 +
 lib/Makefile                            |    2 +
 lib/jedec_ddr_data.c                    |  135 +++
 10 files changed, 2778 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/misc-devices/ti-emif.txt
 create mode 100644 drivers/misc/emif.c
 create mode 100644 drivers/misc/emif.h
 create mode 100644 include/linux/platform_data/emif_plat.h
 create mode 100644 include/misc/jedec_ddr.h
 create mode 100644 lib/jedec_ddr_data.c


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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-03-16 21:51 ` Aneesh V
  0 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-03-16 21:51 UTC (permalink / raw)
  To: linux-arm-kernel

Add a driver for the EMIF SDRAM controller used in TI SoCs

EMIF is an SDRAM controller that supports, based on its revision,
one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
for LPDDR2.

The driver supports the following features:
- Calculates the DDR AC timing parameters to be set in EMIF
  registers using data from the device data-sheets and based
  on the DDR frequency. If data from data-sheets is not available
  default timing values from the JEDEC spec are used. These
  will be safe, but not necessarily optimal
- API for changing timings during DVFS or at boot-up
- Temperature alert configuration and handling of temperature
  alerts, if any for LPDDR2 devices
  * temperature alert is based on periodic polling of MR4 mode
    register in DDR devices automatically performed by hardware
  * timings are de-rated and brought back to nominal when
    temperature raises and falls respectively
- Cache of calculated register values to avoid re-calculating
  them

The driver will need some minor updates when it is eventually
integrated with Dynamic Voltage and Frequency Scaling (DVFS).
This can not be done now as DVFS support is not available in
the mainline yet.

Discussions with Santosh Shilimkar <santosh.shilimkar@ti.com>
were immensely helpful in shaping up the interfaces. Vibhore Vardhan
<vvardhan@gmail.com> did the initial code snippet for thermal
handling.

Testing: 
- The driver is tested on OMAP4430 SDP.
- The driver in a slightly adapted form is also tested on OMAP5.
- Since mainline kernel doesn't have DVFS support yet,
  testing was done using a test module.
- Temperature alert handling was tested with simulated interrupts
  and faked temperature values as testing all cases in real-life
  scenarios is difficult.
- Tested the driver as a module

Cc: Greg KH <greg@kroah.com>

v4:
- Converted instances of EXPORT_SYMBOL to EXPORT_SYMBOL_GPL
- Removed un-necessary "#ifndef __ASSEMBLY__'
- Minor formatting fix

v2:
- Fixed a bug found in the implementation of errata i728
  workaround
- Fixed the value of frequency printed in debugfs
- Dropped the hwmod patch as Paul has already posted a
  a hwmod series [1] that adds hwmod for EMIF
- Converted instances of __init to __init_or_module

[1] http://thread.gmane.org/gmane.linux.ports.arm.omap/72855

Aneesh V (7):
  misc: ddr: add LPDDR2 data from JESD209-2
  misc: emif: add register definitions for EMIF
  misc: emif: add basic infrastructure for EMIF driver
  misc: emif: handle frequency and voltage change events
  misc: emif: add interrupt and temperature handling
  misc: emif: add one-time settings
  misc: emif: add debugfs entries for emif

 Documentation/misc-devices/ti-emif.txt  |   58 ++
 drivers/misc/Kconfig                    |   12 +
 drivers/misc/Makefile                   |    1 +
 drivers/misc/emif.c                     | 1670 +++++++++++++++++++++++++++++++
 drivers/misc/emif.h                     |  589 +++++++++++
 include/linux/platform_data/emif_plat.h |  128 +++
 include/misc/jedec_ddr.h                |  175 ++++
 lib/Kconfig                             |    8 +
 lib/Makefile                            |    2 +
 lib/jedec_ddr_data.c                    |  135 +++
 10 files changed, 2778 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/misc-devices/ti-emif.txt
 create mode 100644 drivers/misc/emif.c
 create mode 100644 drivers/misc/emif.h
 create mode 100644 include/linux/platform_data/emif_plat.h
 create mode 100644 include/misc/jedec_ddr.h
 create mode 100644 lib/jedec_ddr_data.c

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

* [PATCH v4 1/7] misc: ddr: add LPDDR2 data from JESD209-2
  2012-03-16 21:51 ` Aneesh V
@ 2012-03-16 21:51   ` Aneesh V
  -1 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-03-16 21:51 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-arm-kernel, linux-omap, Aneesh V, Greg KH

add LPDDR2 data from the JEDEC spec JESD209-2. The data
includes:

1. Addressing information for LPDDR2 memories of different
   densities and types(S2/S4)
2. AC timing data.

This data will useful for memory controller device drivers.
Right now this is used by the TI EMIF SDRAM controller
driver.

Cc: Greg KH <greg@kroah.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
---

v4:
- Removed 'ifndef __ASSEMBLY__' from jedec_ddr.h
- Updated commit log to be more specific on where
  this patch is used currently
- Converted EXPORT_SYMBOL to EXPORT_SYMBOL_GPL
- Removed un-necessary newline

v1:
- Moved to /lib from /drivers/misc
- Corrected Copyright year
---
 include/misc/jedec_ddr.h |  175 ++++++++++++++++++++++++++++++++++++++++++++++
 lib/Kconfig              |    8 ++
 lib/Makefile             |    2 +
 lib/jedec_ddr_data.c     |  135 +++++++++++++++++++++++++++++++++++
 4 files changed, 320 insertions(+), 0 deletions(-)
 create mode 100644 include/misc/jedec_ddr.h
 create mode 100644 lib/jedec_ddr_data.c

diff --git a/include/misc/jedec_ddr.h b/include/misc/jedec_ddr.h
new file mode 100644
index 0000000..ddad0f8
--- /dev/null
+++ b/include/misc/jedec_ddr.h
@@ -0,0 +1,175 @@
+/*
+ * Definitions for DDR memories based on JEDEC specs
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Aneesh V <aneesh@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 __LINUX_JEDEC_DDR_H
+#define __LINUX_JEDEC_DDR_H
+
+#include <linux/types.h>
+
+/* DDR Densities */
+#define DDR_DENSITY_64Mb	1
+#define DDR_DENSITY_128Mb	2
+#define DDR_DENSITY_256Mb	3
+#define DDR_DENSITY_512Mb	4
+#define DDR_DENSITY_1Gb		5
+#define DDR_DENSITY_2Gb		6
+#define DDR_DENSITY_4Gb		7
+#define DDR_DENSITY_8Gb		8
+#define DDR_DENSITY_16Gb	9
+#define DDR_DENSITY_32Gb	10
+
+/* DDR type */
+#define DDR_TYPE_DDR2		1
+#define DDR_TYPE_DDR3		2
+#define DDR_TYPE_LPDDR2_S4	3
+#define DDR_TYPE_LPDDR2_S2	4
+#define DDR_TYPE_LPDDR2_NVM	5
+
+/* DDR IO width */
+#define DDR_IO_WIDTH_4		1
+#define DDR_IO_WIDTH_8		2
+#define DDR_IO_WIDTH_16		3
+#define DDR_IO_WIDTH_32		4
+
+/* Number of Row bits */
+#define R9			9
+#define R10			10
+#define R11			11
+#define R12			12
+#define R13			13
+#define R14			14
+#define R15			15
+#define R16			16
+
+/* Number of Column bits */
+#define C7			7
+#define C8			8
+#define C9			9
+#define C10			10
+#define C11			11
+#define C12			12
+
+/* Number of Banks */
+#define B1			0
+#define B2			1
+#define B4			2
+#define B8			3
+
+/* Refresh rate in nano-seconds */
+#define T_REFI_15_6		15600
+#define T_REFI_7_8		7800
+#define T_REFI_3_9		3900
+
+/* tRFC values */
+#define T_RFC_90		90000
+#define T_RFC_110		110000
+#define T_RFC_130		130000
+#define T_RFC_160		160000
+#define T_RFC_210		210000
+#define T_RFC_300		300000
+#define T_RFC_350		350000
+
+/* Mode register numbers */
+#define DDR_MR0			0
+#define DDR_MR1			1
+#define DDR_MR2			2
+#define DDR_MR3			3
+#define DDR_MR4			4
+#define DDR_MR5			5
+#define DDR_MR6			6
+#define DDR_MR7			7
+#define DDR_MR8			8
+#define DDR_MR9			9
+#define DDR_MR10		10
+#define DDR_MR11		11
+#define DDR_MR16		16
+#define DDR_MR17		17
+#define DDR_MR18		18
+
+/*
+ * LPDDR2 related defines
+ */
+
+/* MR4 register fields */
+#define MR4_SDRAM_REF_RATE_SHIFT			0
+#define MR4_SDRAM_REF_RATE_MASK				7
+#define MR4_TUF_SHIFT					7
+#define MR4_TUF_MASK					(1 << 7)
+
+/* MR4 SDRAM Refresh Rate field values */
+#define SDRAM_TEMP_NOMINAL				0x3
+#define SDRAM_TEMP_RESERVED_4				0x4
+#define SDRAM_TEMP_HIGH_DERATE_REFRESH			0x5
+#define SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS	0x6
+#define SDRAM_TEMP_VERY_HIGH_SHUTDOWN			0x7
+
+#define NUM_DDR_ADDR_TABLE_ENTRIES			11
+#define NUM_DDR_TIMING_TABLE_ENTRIES			4
+
+/* Structure for DDR addressing info from the JEDEC spec */
+struct lpddr2_addressing {
+	u32 num_banks;
+	u32 tREFI_ns;
+	u32 tRFCab_ps;
+};
+
+/*
+ * Structure for timings from the LPDDR2 datasheet
+ * All parameters are in pico seconds(ps) unless explicitly indicated
+ * with a suffix like tRAS_max_ns below
+ */
+struct lpddr2_timings {
+	u32 max_freq;
+	u32 min_freq;
+	u32 tRPab;
+	u32 tRCD;
+	u32 tWR;
+	u32 tRAS_min;
+	u32 tRRD;
+	u32 tWTR;
+	u32 tXP;
+	u32 tRTP;
+	u32 tCKESR;
+	u32 tDQSCK_max;
+	u32 tDQSCK_max_derated;
+	u32 tFAW;
+	u32 tZQCS;
+	u32 tZQCL;
+	u32 tZQinit;
+	u32 tRAS_max_ns;
+};
+
+/*
+ * Min value for some parameters in terms of number of tCK cycles(nCK)
+ * Please set to zero parameters that are not valid for a given memory
+ * type
+ */
+struct lpddr2_min_tck {
+	u32 tRPab;
+	u32 tRCD;
+	u32 tWR;
+	u32 tRASmin;
+	u32 tRRD;
+	u32 tWTR;
+	u32 tXP;
+	u32 tRTP;
+	u32 tCKE;
+	u32 tCKESR;
+	u32 tFAW;
+};
+
+extern const struct lpddr2_addressing
+	lpddr2_jedec_addressing_table[NUM_DDR_ADDR_TABLE_ENTRIES];
+extern const struct lpddr2_timings
+	lpddr2_jedec_timings[NUM_DDR_TIMING_TABLE_ENTRIES];
+extern const struct lpddr2_min_tck lpddr2_jedec_min_tck;
+
+#endif /* __LINUX_JEDEC_DDR_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index 028aba9..c5d4f1f 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -291,6 +291,14 @@ config CORDIC
 	  This option provides an implementation of the CORDIC algorithm;
 	  calculations are in fixed point. Module will be called cordic.
 
+config DDR
+	bool "JEDEC DDR data"
+	help
+	  Data from JEDEC specs for DDR SDRAM memories,
+	  particularly the AC timing parameters and addressing
+	  information. This data is useful for drivers handling
+	  DDR SDRAM controllers.
+
 config MPILIB
 	tristate
 	select CLZ_TAB
diff --git a/lib/Makefile b/lib/Makefile
index 18515f0..74290c9 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -123,6 +123,8 @@ obj-$(CONFIG_SIGNATURE) += digsig.o
 
 obj-$(CONFIG_CLZ_TAB) += clz_tab.o
 
+obj-$(CONFIG_DDR) += jedec_ddr_data.o
+
 hostprogs-y	:= gen_crc32table
 clean-files	:= crc32table.h
 
diff --git a/lib/jedec_ddr_data.c b/lib/jedec_ddr_data.c
new file mode 100644
index 0000000..498c78f
--- /dev/null
+++ b/lib/jedec_ddr_data.c
@@ -0,0 +1,135 @@
+/*
+ * DDR addressing details and AC timing parameters from JEDEC specs
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Aneesh V <aneesh@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <misc/jedec_ddr.h>
+#include <linux/module.h>
+
+/* LPDDR2 addressing details from JESD209-2 section 2.4 */
+const struct lpddr2_addressing
+	lpddr2_jedec_addressing_table[NUM_DDR_ADDR_TABLE_ENTRIES] = {
+	{B4, T_REFI_15_6, T_RFC_90}, /* 64M */
+	{B4, T_REFI_15_6, T_RFC_90}, /* 128M */
+	{B4, T_REFI_7_8,  T_RFC_90}, /* 256M */
+	{B4, T_REFI_7_8,  T_RFC_90}, /* 512M */
+	{B8, T_REFI_7_8, T_RFC_130}, /* 1GS4 */
+	{B8, T_REFI_3_9, T_RFC_130}, /* 2GS4 */
+	{B8, T_REFI_3_9, T_RFC_130}, /* 4G */
+	{B8, T_REFI_3_9, T_RFC_210}, /* 8G */
+	{B4, T_REFI_7_8, T_RFC_130}, /* 1GS2 */
+	{B4, T_REFI_3_9, T_RFC_130}, /* 2GS2 */
+};
+EXPORT_SYMBOL_GPL(lpddr2_jedec_addressing_table);
+
+/* LPDDR2 AC timing parameters from JESD209-2 section 12 */
+const struct lpddr2_timings
+	lpddr2_jedec_timings[NUM_DDR_TIMING_TABLE_ENTRIES] = {
+	/* Speed bin 400(200 MHz) */
+	[0] = {
+		.max_freq	= 200000000,
+		.min_freq	= 10000000,
+		.tRPab		= 21000,
+		.tRCD		= 18000,
+		.tWR		= 15000,
+		.tRAS_min	= 42000,
+		.tRRD		= 10000,
+		.tWTR		= 10000,
+		.tXP		= 7500,
+		.tRTP		= 7500,
+		.tCKESR		= 15000,
+		.tDQSCK_max	= 5500,
+		.tFAW		= 50000,
+		.tZQCS		= 90000,
+		.tZQCL		= 360000,
+		.tZQinit	= 1000000,
+		.tRAS_max_ns	= 70000,
+		.tDQSCK_max_derated = 6000,
+	},
+	/* Speed bin 533(266 MHz) */
+	[1] = {
+		.max_freq	= 266666666,
+		.min_freq	= 10000000,
+		.tRPab		= 21000,
+		.tRCD		= 18000,
+		.tWR		= 15000,
+		.tRAS_min	= 42000,
+		.tRRD		= 10000,
+		.tWTR		= 7500,
+		.tXP		= 7500,
+		.tRTP		= 7500,
+		.tCKESR		= 15000,
+		.tDQSCK_max	= 5500,
+		.tFAW		= 50000,
+		.tZQCS		= 90000,
+		.tZQCL		= 360000,
+		.tZQinit	= 1000000,
+		.tRAS_max_ns	= 70000,
+		.tDQSCK_max_derated = 6000,
+	},
+	/* Speed bin 800(400 MHz) */
+	[2] = {
+		.max_freq	= 400000000,
+		.min_freq	= 10000000,
+		.tRPab		= 21000,
+		.tRCD		= 18000,
+		.tWR		= 15000,
+		.tRAS_min	= 42000,
+		.tRRD		= 10000,
+		.tWTR		= 7500,
+		.tXP		= 7500,
+		.tRTP		= 7500,
+		.tCKESR		= 15000,
+		.tDQSCK_max	= 5500,
+		.tFAW		= 50000,
+		.tZQCS		= 90000,
+		.tZQCL		= 360000,
+		.tZQinit	= 1000000,
+		.tRAS_max_ns	= 70000,
+		.tDQSCK_max_derated = 6000,
+	},
+	/* Speed bin 1066(533 MHz) */
+	[3] = {
+		.max_freq	= 533333333,
+		.min_freq	= 10000000,
+		.tRPab		= 21000,
+		.tRCD		= 18000,
+		.tWR		= 15000,
+		.tRAS_min	= 42000,
+		.tRRD		= 10000,
+		.tWTR		= 7500,
+		.tXP		= 7500,
+		.tRTP		= 7500,
+		.tCKESR		= 15000,
+		.tDQSCK_max	= 5500,
+		.tFAW		= 50000,
+		.tZQCS		= 90000,
+		.tZQCL		= 360000,
+		.tZQinit	= 1000000,
+		.tRAS_max_ns	= 70000,
+		.tDQSCK_max_derated = 5620,
+	},
+};
+EXPORT_SYMBOL_GPL(lpddr2_jedec_timings);
+
+const struct lpddr2_min_tck lpddr2_jedec_min_tck = {
+	.tRPab		= 3,
+	.tRCD		= 3,
+	.tWR		= 3,
+	.tRASmin	= 3,
+	.tRRD		= 2,
+	.tWTR		= 2,
+	.tXP		= 2,
+	.tRTP		= 2,
+	.tCKE		= 3,
+	.tCKESR		= 3,
+	.tFAW		= 8
+};
+EXPORT_SYMBOL_GPL(lpddr2_jedec_min_tck);
-- 
1.7.1


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

* [PATCH v4 1/7] misc: ddr: add LPDDR2 data from JESD209-2
@ 2012-03-16 21:51   ` Aneesh V
  0 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-03-16 21:51 UTC (permalink / raw)
  To: linux-arm-kernel

add LPDDR2 data from the JEDEC spec JESD209-2. The data
includes:

1. Addressing information for LPDDR2 memories of different
   densities and types(S2/S4)
2. AC timing data.

This data will useful for memory controller device drivers.
Right now this is used by the TI EMIF SDRAM controller
driver.

Cc: Greg KH <greg@kroah.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
---

v4:
- Removed 'ifndef __ASSEMBLY__' from jedec_ddr.h
- Updated commit log to be more specific on where
  this patch is used currently
- Converted EXPORT_SYMBOL to EXPORT_SYMBOL_GPL
- Removed un-necessary newline

v1:
- Moved to /lib from /drivers/misc
- Corrected Copyright year
---
 include/misc/jedec_ddr.h |  175 ++++++++++++++++++++++++++++++++++++++++++++++
 lib/Kconfig              |    8 ++
 lib/Makefile             |    2 +
 lib/jedec_ddr_data.c     |  135 +++++++++++++++++++++++++++++++++++
 4 files changed, 320 insertions(+), 0 deletions(-)
 create mode 100644 include/misc/jedec_ddr.h
 create mode 100644 lib/jedec_ddr_data.c

diff --git a/include/misc/jedec_ddr.h b/include/misc/jedec_ddr.h
new file mode 100644
index 0000000..ddad0f8
--- /dev/null
+++ b/include/misc/jedec_ddr.h
@@ -0,0 +1,175 @@
+/*
+ * Definitions for DDR memories based on JEDEC specs
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Aneesh V <aneesh@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 __LINUX_JEDEC_DDR_H
+#define __LINUX_JEDEC_DDR_H
+
+#include <linux/types.h>
+
+/* DDR Densities */
+#define DDR_DENSITY_64Mb	1
+#define DDR_DENSITY_128Mb	2
+#define DDR_DENSITY_256Mb	3
+#define DDR_DENSITY_512Mb	4
+#define DDR_DENSITY_1Gb		5
+#define DDR_DENSITY_2Gb		6
+#define DDR_DENSITY_4Gb		7
+#define DDR_DENSITY_8Gb		8
+#define DDR_DENSITY_16Gb	9
+#define DDR_DENSITY_32Gb	10
+
+/* DDR type */
+#define DDR_TYPE_DDR2		1
+#define DDR_TYPE_DDR3		2
+#define DDR_TYPE_LPDDR2_S4	3
+#define DDR_TYPE_LPDDR2_S2	4
+#define DDR_TYPE_LPDDR2_NVM	5
+
+/* DDR IO width */
+#define DDR_IO_WIDTH_4		1
+#define DDR_IO_WIDTH_8		2
+#define DDR_IO_WIDTH_16		3
+#define DDR_IO_WIDTH_32		4
+
+/* Number of Row bits */
+#define R9			9
+#define R10			10
+#define R11			11
+#define R12			12
+#define R13			13
+#define R14			14
+#define R15			15
+#define R16			16
+
+/* Number of Column bits */
+#define C7			7
+#define C8			8
+#define C9			9
+#define C10			10
+#define C11			11
+#define C12			12
+
+/* Number of Banks */
+#define B1			0
+#define B2			1
+#define B4			2
+#define B8			3
+
+/* Refresh rate in nano-seconds */
+#define T_REFI_15_6		15600
+#define T_REFI_7_8		7800
+#define T_REFI_3_9		3900
+
+/* tRFC values */
+#define T_RFC_90		90000
+#define T_RFC_110		110000
+#define T_RFC_130		130000
+#define T_RFC_160		160000
+#define T_RFC_210		210000
+#define T_RFC_300		300000
+#define T_RFC_350		350000
+
+/* Mode register numbers */
+#define DDR_MR0			0
+#define DDR_MR1			1
+#define DDR_MR2			2
+#define DDR_MR3			3
+#define DDR_MR4			4
+#define DDR_MR5			5
+#define DDR_MR6			6
+#define DDR_MR7			7
+#define DDR_MR8			8
+#define DDR_MR9			9
+#define DDR_MR10		10
+#define DDR_MR11		11
+#define DDR_MR16		16
+#define DDR_MR17		17
+#define DDR_MR18		18
+
+/*
+ * LPDDR2 related defines
+ */
+
+/* MR4 register fields */
+#define MR4_SDRAM_REF_RATE_SHIFT			0
+#define MR4_SDRAM_REF_RATE_MASK				7
+#define MR4_TUF_SHIFT					7
+#define MR4_TUF_MASK					(1 << 7)
+
+/* MR4 SDRAM Refresh Rate field values */
+#define SDRAM_TEMP_NOMINAL				0x3
+#define SDRAM_TEMP_RESERVED_4				0x4
+#define SDRAM_TEMP_HIGH_DERATE_REFRESH			0x5
+#define SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS	0x6
+#define SDRAM_TEMP_VERY_HIGH_SHUTDOWN			0x7
+
+#define NUM_DDR_ADDR_TABLE_ENTRIES			11
+#define NUM_DDR_TIMING_TABLE_ENTRIES			4
+
+/* Structure for DDR addressing info from the JEDEC spec */
+struct lpddr2_addressing {
+	u32 num_banks;
+	u32 tREFI_ns;
+	u32 tRFCab_ps;
+};
+
+/*
+ * Structure for timings from the LPDDR2 datasheet
+ * All parameters are in pico seconds(ps) unless explicitly indicated
+ * with a suffix like tRAS_max_ns below
+ */
+struct lpddr2_timings {
+	u32 max_freq;
+	u32 min_freq;
+	u32 tRPab;
+	u32 tRCD;
+	u32 tWR;
+	u32 tRAS_min;
+	u32 tRRD;
+	u32 tWTR;
+	u32 tXP;
+	u32 tRTP;
+	u32 tCKESR;
+	u32 tDQSCK_max;
+	u32 tDQSCK_max_derated;
+	u32 tFAW;
+	u32 tZQCS;
+	u32 tZQCL;
+	u32 tZQinit;
+	u32 tRAS_max_ns;
+};
+
+/*
+ * Min value for some parameters in terms of number of tCK cycles(nCK)
+ * Please set to zero parameters that are not valid for a given memory
+ * type
+ */
+struct lpddr2_min_tck {
+	u32 tRPab;
+	u32 tRCD;
+	u32 tWR;
+	u32 tRASmin;
+	u32 tRRD;
+	u32 tWTR;
+	u32 tXP;
+	u32 tRTP;
+	u32 tCKE;
+	u32 tCKESR;
+	u32 tFAW;
+};
+
+extern const struct lpddr2_addressing
+	lpddr2_jedec_addressing_table[NUM_DDR_ADDR_TABLE_ENTRIES];
+extern const struct lpddr2_timings
+	lpddr2_jedec_timings[NUM_DDR_TIMING_TABLE_ENTRIES];
+extern const struct lpddr2_min_tck lpddr2_jedec_min_tck;
+
+#endif /* __LINUX_JEDEC_DDR_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index 028aba9..c5d4f1f 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -291,6 +291,14 @@ config CORDIC
 	  This option provides an implementation of the CORDIC algorithm;
 	  calculations are in fixed point. Module will be called cordic.
 
+config DDR
+	bool "JEDEC DDR data"
+	help
+	  Data from JEDEC specs for DDR SDRAM memories,
+	  particularly the AC timing parameters and addressing
+	  information. This data is useful for drivers handling
+	  DDR SDRAM controllers.
+
 config MPILIB
 	tristate
 	select CLZ_TAB
diff --git a/lib/Makefile b/lib/Makefile
index 18515f0..74290c9 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -123,6 +123,8 @@ obj-$(CONFIG_SIGNATURE) += digsig.o
 
 obj-$(CONFIG_CLZ_TAB) += clz_tab.o
 
+obj-$(CONFIG_DDR) += jedec_ddr_data.o
+
 hostprogs-y	:= gen_crc32table
 clean-files	:= crc32table.h
 
diff --git a/lib/jedec_ddr_data.c b/lib/jedec_ddr_data.c
new file mode 100644
index 0000000..498c78f
--- /dev/null
+++ b/lib/jedec_ddr_data.c
@@ -0,0 +1,135 @@
+/*
+ * DDR addressing details and AC timing parameters from JEDEC specs
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Aneesh V <aneesh@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <misc/jedec_ddr.h>
+#include <linux/module.h>
+
+/* LPDDR2 addressing details from JESD209-2 section 2.4 */
+const struct lpddr2_addressing
+	lpddr2_jedec_addressing_table[NUM_DDR_ADDR_TABLE_ENTRIES] = {
+	{B4, T_REFI_15_6, T_RFC_90}, /* 64M */
+	{B4, T_REFI_15_6, T_RFC_90}, /* 128M */
+	{B4, T_REFI_7_8,  T_RFC_90}, /* 256M */
+	{B4, T_REFI_7_8,  T_RFC_90}, /* 512M */
+	{B8, T_REFI_7_8, T_RFC_130}, /* 1GS4 */
+	{B8, T_REFI_3_9, T_RFC_130}, /* 2GS4 */
+	{B8, T_REFI_3_9, T_RFC_130}, /* 4G */
+	{B8, T_REFI_3_9, T_RFC_210}, /* 8G */
+	{B4, T_REFI_7_8, T_RFC_130}, /* 1GS2 */
+	{B4, T_REFI_3_9, T_RFC_130}, /* 2GS2 */
+};
+EXPORT_SYMBOL_GPL(lpddr2_jedec_addressing_table);
+
+/* LPDDR2 AC timing parameters from JESD209-2 section 12 */
+const struct lpddr2_timings
+	lpddr2_jedec_timings[NUM_DDR_TIMING_TABLE_ENTRIES] = {
+	/* Speed bin 400(200 MHz) */
+	[0] = {
+		.max_freq	= 200000000,
+		.min_freq	= 10000000,
+		.tRPab		= 21000,
+		.tRCD		= 18000,
+		.tWR		= 15000,
+		.tRAS_min	= 42000,
+		.tRRD		= 10000,
+		.tWTR		= 10000,
+		.tXP		= 7500,
+		.tRTP		= 7500,
+		.tCKESR		= 15000,
+		.tDQSCK_max	= 5500,
+		.tFAW		= 50000,
+		.tZQCS		= 90000,
+		.tZQCL		= 360000,
+		.tZQinit	= 1000000,
+		.tRAS_max_ns	= 70000,
+		.tDQSCK_max_derated = 6000,
+	},
+	/* Speed bin 533(266 MHz) */
+	[1] = {
+		.max_freq	= 266666666,
+		.min_freq	= 10000000,
+		.tRPab		= 21000,
+		.tRCD		= 18000,
+		.tWR		= 15000,
+		.tRAS_min	= 42000,
+		.tRRD		= 10000,
+		.tWTR		= 7500,
+		.tXP		= 7500,
+		.tRTP		= 7500,
+		.tCKESR		= 15000,
+		.tDQSCK_max	= 5500,
+		.tFAW		= 50000,
+		.tZQCS		= 90000,
+		.tZQCL		= 360000,
+		.tZQinit	= 1000000,
+		.tRAS_max_ns	= 70000,
+		.tDQSCK_max_derated = 6000,
+	},
+	/* Speed bin 800(400 MHz) */
+	[2] = {
+		.max_freq	= 400000000,
+		.min_freq	= 10000000,
+		.tRPab		= 21000,
+		.tRCD		= 18000,
+		.tWR		= 15000,
+		.tRAS_min	= 42000,
+		.tRRD		= 10000,
+		.tWTR		= 7500,
+		.tXP		= 7500,
+		.tRTP		= 7500,
+		.tCKESR		= 15000,
+		.tDQSCK_max	= 5500,
+		.tFAW		= 50000,
+		.tZQCS		= 90000,
+		.tZQCL		= 360000,
+		.tZQinit	= 1000000,
+		.tRAS_max_ns	= 70000,
+		.tDQSCK_max_derated = 6000,
+	},
+	/* Speed bin 1066(533 MHz) */
+	[3] = {
+		.max_freq	= 533333333,
+		.min_freq	= 10000000,
+		.tRPab		= 21000,
+		.tRCD		= 18000,
+		.tWR		= 15000,
+		.tRAS_min	= 42000,
+		.tRRD		= 10000,
+		.tWTR		= 7500,
+		.tXP		= 7500,
+		.tRTP		= 7500,
+		.tCKESR		= 15000,
+		.tDQSCK_max	= 5500,
+		.tFAW		= 50000,
+		.tZQCS		= 90000,
+		.tZQCL		= 360000,
+		.tZQinit	= 1000000,
+		.tRAS_max_ns	= 70000,
+		.tDQSCK_max_derated = 5620,
+	},
+};
+EXPORT_SYMBOL_GPL(lpddr2_jedec_timings);
+
+const struct lpddr2_min_tck lpddr2_jedec_min_tck = {
+	.tRPab		= 3,
+	.tRCD		= 3,
+	.tWR		= 3,
+	.tRASmin	= 3,
+	.tRRD		= 2,
+	.tWTR		= 2,
+	.tXP		= 2,
+	.tRTP		= 2,
+	.tCKE		= 3,
+	.tCKESR		= 3,
+	.tFAW		= 8
+};
+EXPORT_SYMBOL_GPL(lpddr2_jedec_min_tck);
-- 
1.7.1

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

* [PATCH v4 2/7] misc: emif: add register definitions for EMIF
  2012-03-16 21:51 ` Aneesh V
@ 2012-03-16 21:51   ` Aneesh V
  -1 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-03-16 21:51 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-arm-kernel, linux-omap, Aneesh V, Greg KH

Add register offsets and bit field definitions
for EMIF module in TI SoCs

Cc: Greg KH <greg@kroah.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
---
v1:
- Improved commit log
- Corrected copyright year
- Changed file name in order to add other defines
  needed by the driver in the same file in subsequent
  patches
---
 drivers/misc/emif.h |  454 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 454 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/emif.h

diff --git a/drivers/misc/emif.h b/drivers/misc/emif.h
new file mode 100644
index 0000000..44b97df
--- /dev/null
+++ b/drivers/misc/emif.h
@@ -0,0 +1,454 @@
+/*
+ * 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 __EMIF_H
+#define __EMIF_H
+
+/* 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
-- 
1.7.1


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

* [PATCH v4 2/7] misc: emif: add register definitions for EMIF
@ 2012-03-16 21:51   ` Aneesh V
  0 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-03-16 21:51 UTC (permalink / raw)
  To: linux-arm-kernel

Add register offsets and bit field definitions
for EMIF module in TI SoCs

Cc: Greg KH <greg@kroah.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
---
v1:
- Improved commit log
- Corrected copyright year
- Changed file name in order to add other defines
  needed by the driver in the same file in subsequent
  patches
---
 drivers/misc/emif.h |  454 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 454 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/emif.h

diff --git a/drivers/misc/emif.h b/drivers/misc/emif.h
new file mode 100644
index 0000000..44b97df
--- /dev/null
+++ b/drivers/misc/emif.h
@@ -0,0 +1,454 @@
+/*
+ * 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 __EMIF_H
+#define __EMIF_H
+
+/* 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
-- 
1.7.1

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

* [PATCH v4 3/7] misc: emif: add basic infrastructure for EMIF driver
  2012-03-16 21:51 ` Aneesh V
@ 2012-03-16 21:51   ` Aneesh V
  -1 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-03-16 21:51 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-arm-kernel, linux-omap, Aneesh V, Greg KH

EMIF is an SDRAM controller used in various Texas Instruments
SoCs. EMIF supports, based on its revision, one or more of
LPDDR2/DDR2/DDR3 protocols.

Add the basic infrastructure for EMIF driver that includes
driver registration, probe, parsing of platform data etc.

Cc: Greg KH <greg@kroah.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
---
v2:
- replaced __init with __init_or_module

v1:
- Removed emif_cleanup() function and instead used
  devm_* variant of APIs for resource allocations
- Split include/linux/emif.h into two parts. The first
  part now becomes include/linux/platform_data/emif_plat.h
  and the other part is now merged in drivers/misc/emif.h
- Made error messages more verbose
- Corrected copyright year
- Fixed other coding style comments
- Minor adjustments to patch organization. Moved
  some definitions to a subsequent patch that uses
  them
- Added a list a of devices. This is needed for errata
  i728 workaround and for the new locking scheme
- Added documentation for driver
---
 Documentation/misc-devices/ti-emif.txt  |   58 ++++++
 drivers/misc/Kconfig                    |   12 ++
 drivers/misc/Makefile                   |    1 +
 drivers/misc/emif.c                     |  289 +++++++++++++++++++++++++++++++
 drivers/misc/emif.h                     |    7 +
 include/linux/platform_data/emif_plat.h |  128 ++++++++++++++
 6 files changed, 495 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/misc-devices/ti-emif.txt
 create mode 100644 drivers/misc/emif.c
 create mode 100644 include/linux/platform_data/emif_plat.h

diff --git a/Documentation/misc-devices/ti-emif.txt b/Documentation/misc-devices/ti-emif.txt
new file mode 100644
index 0000000..a9238c1
--- /dev/null
+++ b/Documentation/misc-devices/ti-emif.txt
@@ -0,0 +1,58 @@
+TI EMIF SDRAM Controller Driver:
+
+Author
+========
+Aneesh V <aneesh@ti.com>
+
+Location
+============
+driver/misc/emif.c
+
+Supported SoCs:
+===================
+TI OMAP44xx
+TI OMAP54xx
+
+Menuconfig option:
+==========================
+Device Drivers
+	Misc devices
+		Texas Instruments EMIF driver
+
+Description
+===========
+This driver is for the EMIF module available in Texas Instruments
+SoCs. EMIF is an SDRAM controller that, based on its revision,
+supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols.
+This driver takes care of only LPDDR2 memories presently. The
+functions of the driver includes re-configuring AC timing
+parameters and other settings during frequency, voltage and
+temperature changes
+
+Platform Data (see include/linux/platform_data/emif_plat.h):
+=====================================================================
+DDR device details and other board dependent and SoC dependent
+information can be passed through platform data (struct emif_platform_data)
+- DDR device details: 'struct ddr_device_info'
+- Device AC timings: 'struct lpddr2_timings' and 'struct lpddr2_min_tck'
+- Custom configurations: customizable policy options through
+  'struct emif_custom_configs'
+- IP revision
+- PHY type
+
+Interface to the external world:
+================================
+EMIF driver registers notifiers for voltage and frequency changes
+affecting EMIF and takes appropriate actions when these are invoked.
+- freq_pre_notify_handling()
+- freq_post_notify_handling()
+- volt_notify_handling()
+
+Debugfs
+========
+The driver creates two debugfs entries per device.
+- regcache_dump : dump of register values calculated and saved for all
+  frequencies used so far.
+- mr4 : last polled value of MR4 register in the LPDDR2 device. MR4
+  indicates the current temperature level of the device.
+
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index c779509..847a936 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -441,6 +441,18 @@ config VMWARE_BALLOON
 	  To compile this driver as a module, choose M here: the
 	  module will be called vmw_balloon.
 
+config TI_EMIF
+	tristate "Texas Instruments EMIF driver"
+	select DDR
+	help
+	  This driver is for the EMIF module available in Texas Instruments
+	  SoCs. EMIF is an SDRAM controller that, based on its revision,
+	  supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols.
+	  This driver takes care of only LPDDR2 memories presently. The
+	  functions of the driver includes re-configuring AC timing
+	  parameters and other settings during frequency, voltage and
+	  temperature changes
+
 config ARM_CHARLCD
 	bool "ARM Ltd. Character LCD Driver"
 	depends on PLAT_VERSATILE
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 3e1d801..75ab920 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_TI_DAC7512)	+= ti_dac7512.o
 obj-$(CONFIG_C2PORT)		+= c2port/
 obj-$(CONFIG_IWMC3200TOP)      += iwmc3200top/
 obj-$(CONFIG_HMC6352)		+= hmc6352.o
+obj-$(CONFIG_TI_EMIF)		+= emif.o
 obj-y				+= eeprom/
 obj-y				+= cb710/
 obj-$(CONFIG_SPEAR13XX_PCIE_GADGET)	+= spear13xx_pcie_gadget.o
diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c
new file mode 100644
index 0000000..f864640
--- /dev/null
+++ b/drivers/misc/emif.c
@@ -0,0 +1,289 @@
+/*
+ * EMIF driver
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Aneesh V <aneesh@ti.com>
+ * Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/platform_data/emif_plat.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <misc/jedec_ddr.h>
+#include "emif.h"
+
+/**
+ * struct emif_data - Per device static data for driver's use
+ * @duplicate:			Whether the DDR devices attached to this EMIF
+ *				instance are exactly same as that on EMIF1. In
+ *				this case we can save some memory and processing
+ * @temperature_level:		Maximum temperature of LPDDR2 devices attached
+ *				to this EMIF - read from MR4 register. If there
+ *				are two devices attached to this EMIF, this
+ *				value is the maximum of the two temperature
+ *				levels.
+ * @node:			node in the device list
+ * @base:			base address of memory-mapped IO registers.
+ * @dev:			device pointer.
+ * @plat_data:			Pointer to saved platform data.
+ */
+struct emif_data {
+	u8				duplicate;
+	u8				temperature_level;
+	struct list_head		node;
+	void __iomem			*base;
+	struct device			*dev;
+	struct emif_platform_data	*plat_data;
+};
+
+static struct emif_data *emif1;
+static LIST_HEAD(device_list);
+
+static void get_default_timings(struct emif_data *emif)
+{
+	struct emif_platform_data *pd = emif->plat_data;
+
+	pd->timings		= lpddr2_jedec_timings;
+	pd->timings_arr_size	= ARRAY_SIZE(lpddr2_jedec_timings);
+
+	dev_warn(emif->dev, "%s: using default timings\n", __func__);
+}
+
+static int is_dev_data_valid(u32 type, u32 density, u32 io_width, u32 phy_type,
+		u32 ip_rev, struct device *dev)
+{
+	int valid;
+
+	valid = (type == DDR_TYPE_LPDDR2_S4 ||
+			type == DDR_TYPE_LPDDR2_S2)
+		&& (density >= DDR_DENSITY_64Mb
+			&& density <= DDR_DENSITY_8Gb)
+		&& (io_width >= DDR_IO_WIDTH_8
+			&& io_width <= DDR_IO_WIDTH_32);
+
+	/* Combinations of EMIF and PHY revisions that we support today */
+	switch (ip_rev) {
+	case EMIF_4D:
+		valid = valid && (phy_type == EMIF_PHY_TYPE_ATTILAPHY);
+		break;
+	case EMIF_4D5:
+		valid = valid && (phy_type == EMIF_PHY_TYPE_INTELLIPHY);
+		break;
+	default:
+		valid = 0;
+	}
+
+	if (!valid)
+		dev_err(dev, "%s: invalid DDR details\n", __func__);
+	return valid;
+}
+
+static int is_custom_config_valid(struct emif_custom_configs *cust_cfgs,
+		struct device *dev)
+{
+	int valid = 1;
+
+	if ((cust_cfgs->mask & EMIF_CUSTOM_CONFIG_LPMODE) &&
+		(cust_cfgs->lpmode != EMIF_LP_MODE_DISABLE))
+		valid = cust_cfgs->lpmode_freq_threshold &&
+			cust_cfgs->lpmode_timeout_performance &&
+			cust_cfgs->lpmode_timeout_power;
+
+	if (cust_cfgs->mask & EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL)
+		valid = valid && cust_cfgs->temp_alert_poll_interval_ms;
+
+	if (!valid)
+		dev_warn(dev, "%s: invalid custom configs\n", __func__);
+
+	return valid;
+}
+
+static struct emif_data *__init_or_module get_device_details(
+		struct platform_device *pdev)
+{
+	u32				size;
+	struct emif_data		*emif = NULL;
+	struct ddr_device_info		*dev_info;
+	struct emif_custom_configs	*cust_cfgs;
+	struct emif_platform_data	*pd;
+	struct device			*dev;
+	void				*temp;
+
+	pd = pdev->dev.platform_data;
+	dev = &pdev->dev;
+
+	if (!(pd && pd->device_info && is_dev_data_valid(pd->device_info->type,
+			pd->device_info->density, pd->device_info->io_width,
+			pd->phy_type, pd->ip_rev, dev))) {
+		dev_err(dev, "%s: invalid device data\n", __func__);
+		goto error;
+	}
+
+	emif	= devm_kzalloc(dev, sizeof(*emif), GFP_KERNEL);
+	temp	= devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+	dev_info = devm_kzalloc(dev, sizeof(*dev_info), GFP_KERNEL);
+
+	if (!emif || !pd || !dev_info) {
+		dev_err(dev, "%s:%d: allocation error\n", __func__, __LINE__);
+		goto error;
+	}
+
+	memcpy(temp, pd, sizeof(*pd));
+	pd = temp;
+	memcpy(dev_info, pd->device_info, sizeof(*dev_info));
+
+	pd->device_info		= dev_info;
+	emif->plat_data		= pd;
+	emif->dev		= dev;
+	emif->temperature_level	= SDRAM_TEMP_NOMINAL;
+
+	/*
+	 * For EMIF instances other than EMIF1 see if the devices connected
+	 * are exactly same as on EMIF1(which is typically the case). If so,
+	 * mark it as a duplicate of EMIF1 and skip copying timings data.
+	 * This will save some memory and some computation later.
+	 */
+	emif->duplicate = emif1 && (memcmp(dev_info,
+		emif1->plat_data->device_info,
+		sizeof(struct ddr_device_info)) == 0);
+
+	if (emif->duplicate) {
+		pd->timings = NULL;
+		pd->min_tck = NULL;
+		goto out;
+	} else if (emif1) {
+		dev_warn(emif->dev, "%s: Non-symmetric DDR geometry\n",
+			__func__);
+	}
+
+	/*
+	 * Copy custom configs - ignore allocation error, if any, as
+	 * custom_configs is not very critical
+	 */
+	cust_cfgs = pd->custom_configs;
+	if (cust_cfgs && is_custom_config_valid(cust_cfgs, dev)) {
+		temp = devm_kzalloc(dev, sizeof(*cust_cfgs), GFP_KERNEL);
+		if (temp)
+			memcpy(temp, cust_cfgs, sizeof(*cust_cfgs));
+		else
+			dev_warn(dev, "%s:%d: allocation error\n", __func__,
+				__LINE__);
+		pd->custom_configs = temp;
+	}
+
+	/*
+	 * Copy timings and min-tck values from platform data. If it is not
+	 * available or if memory allocation fails, use JEDEC defaults
+	 */
+	size = sizeof(struct lpddr2_timings) * pd->timings_arr_size;
+	if (pd->timings) {
+		temp = devm_kzalloc(dev, size, GFP_KERNEL);
+		if (temp) {
+			memcpy(temp, pd->timings, sizeof(*pd->timings));
+			pd->timings = temp;
+		} else {
+			dev_warn(dev, "%s:%d: allocation error\n", __func__,
+				__LINE__);
+			get_default_timings(emif);
+		}
+	} else {
+		get_default_timings(emif);
+	}
+
+	if (pd->min_tck) {
+		temp = devm_kzalloc(dev, sizeof(*pd->min_tck), GFP_KERNEL);
+		if (temp) {
+			memcpy(temp, pd->min_tck, sizeof(*pd->min_tck));
+			pd->min_tck = temp;
+		} else {
+			dev_warn(dev, "%s:%d: allocation error\n", __func__,
+				__LINE__);
+			pd->min_tck = &lpddr2_jedec_min_tck;
+		}
+	} else {
+		pd->min_tck = &lpddr2_jedec_min_tck;
+	}
+
+out:
+	return emif;
+
+error:
+	return NULL;
+}
+
+static int __init_or_module emif_probe(struct platform_device *pdev)
+{
+	struct emif_data	*emif;
+	struct resource		*res;
+
+	emif = get_device_details(pdev);
+	if (!emif) {
+		pr_err("%s: error getting device data\n", __func__);
+		goto error;
+	}
+
+	if (!emif1)
+		emif1 = emif;
+
+	list_add(&emif->node, &device_list);
+
+	/* Save pointers to each other in emif and device structures */
+	emif->dev = &pdev->dev;
+	platform_set_drvdata(pdev, emif);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(emif->dev, "%s: error getting memory resource\n",
+			__func__);
+		goto error;
+	}
+
+	emif->base = devm_request_and_ioremap(emif->dev, res);
+	if (!emif->base) {
+		dev_err(emif->dev, "%s: devm_request_and_ioremap() failed\n",
+			__func__);
+		goto error;
+	}
+
+	dev_info(&pdev->dev, "%s: device configured with addr = %p\n",
+		__func__, emif->base);
+
+	return 0;
+error:
+	return -ENODEV;
+}
+
+static struct platform_driver emif_driver = {
+	.driver = {
+		.name = "emif",
+	},
+};
+
+static int __init_or_module emif_register(void)
+{
+	return platform_driver_probe(&emif_driver, emif_probe);
+}
+
+static void __exit emif_unregister(void)
+{
+	platform_driver_unregister(&emif_driver);
+}
+
+module_init(emif_register);
+module_exit(emif_unregister);
+MODULE_DESCRIPTION("TI EMIF SDRAM Controller Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:emif");
+MODULE_AUTHOR("Texas Instruments Inc");
diff --git a/drivers/misc/emif.h b/drivers/misc/emif.h
index 44b97df..692b2a8 100644
--- a/drivers/misc/emif.h
+++ b/drivers/misc/emif.h
@@ -12,6 +12,13 @@
 #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
+
 /* Registers offset */
 #define EMIF_MODULE_ID_AND_REVISION			0x0000
 #define EMIF_STATUS					0x0004
diff --git a/include/linux/platform_data/emif_plat.h b/include/linux/platform_data/emif_plat.h
new file mode 100644
index 0000000..03378ca
--- /dev/null
+++ b/include/linux/platform_data/emif_plat.h
@@ -0,0 +1,128 @@
+/*
+ * Definitions for TI EMIF device platform data
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Aneesh V <aneesh@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 __EMIF_PLAT_H
+#define __EMIF_PLAT_H
+
+/* Low power modes - EMIF_PWR_MGMT_CTRL */
+#define EMIF_LP_MODE_DISABLE				0
+#define EMIF_LP_MODE_CLOCK_STOP				1
+#define EMIF_LP_MODE_SELF_REFRESH			2
+#define EMIF_LP_MODE_PWR_DN				4
+
+/* Hardware capabilities */
+#define	EMIF_HW_CAPS_LL_INTERFACE			0x00000001
+
+/*
+ * EMIF IP Revisions
+ *	EMIF4D  - Used in OMAP4
+ *	EMIF4D5 - Used in OMAP5
+ */
+#define	EMIF_4D						1
+#define	EMIF_4D5					2
+
+/*
+ * PHY types
+ *	ATTILAPHY  - Used in OMAP4
+ *	INTELLIPHY - Used in OMAP5
+ */
+#define	EMIF_PHY_TYPE_ATTILAPHY				1
+#define	EMIF_PHY_TYPE_INTELLIPHY			2
+
+/* Custom config requests */
+#define EMIF_CUSTOM_CONFIG_LPMODE			0x00000001
+#define EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL	0x00000002
+
+#ifndef __ASSEMBLY__
+/**
+ * struct ddr_device_info - All information about the DDR device except AC
+ *		timing parameters
+ * @type:	Device type (LPDDR2-S4, LPDDR2-S2 etc)
+ * @density:	Device density
+ * @io_width:	Bus width
+ * @cs1_used:	Whether there is a DDR device attached to the second
+ *		chip-select(CS1) of this EMIF instance
+ * @cal_resistors_per_cs: Whether there is one calibration resistor per
+ *		chip-select or whether it's a single one for both
+ * @manufacturer: Manufacturer name string
+ */
+struct ddr_device_info {
+	u32	type;
+	u32	density;
+	u32	io_width;
+	u32	cs1_used;
+	u32	cal_resistors_per_cs;
+	char	manufacturer[10];
+};
+
+/**
+ * struct emif_custom_configs - Custom configuration parameters/policies
+ *		passed from the platform layer
+ * @mask:	Mask to indicate which configs are requested
+ * @lpmode:	LPMODE to be used in PWR_MGMT_CTRL register
+ * @lpmode_timeout_performance: Timeout before LPMODE entry when higher
+ *		performance is desired at the cost of power (typically
+ *		at higher OPPs)
+ * @lpmode_timeout_power: Timeout before LPMODE entry when better power
+ *		savings is desired and performance is not important
+ *		(typically at lower loads indicated by lower OPPs)
+ * @lpmode_freq_threshold: The DDR frequency threshold to identify between
+ *		the above two cases:
+ *		timeout = (freq >= lpmode_freq_threshold) ?
+ *			lpmode_timeout_performance :
+ *			lpmode_timeout_power;
+ * @temp_alert_poll_interval_ms: LPDDR2 MR4 polling interval at nominal
+ *		temperature(in milliseconds). When temperature is high
+ *		polling is done 4 times as frequently.
+ */
+struct emif_custom_configs {
+	u32 mask;
+	u32 lpmode;
+	u32 lpmode_timeout_performance;
+	u32 lpmode_timeout_power;
+	u32 lpmode_freq_threshold;
+	u32 temp_alert_poll_interval_ms;
+};
+
+/**
+ * struct emif_platform_data - Platform data passed on EMIF platform
+ *				device creation. Used by the driver.
+ * @hw_caps:		Hw capabilities of the EMIF IP in the respective SoC
+ * @device_info:	Device info structure containing information such
+ *			as type, bus width, density etc
+ * @timings:		Timings information from device datasheet passed
+ *			as an array of 'struct lpddr2_timings'. Can be NULL
+ *			if if default timings are ok
+ * @timings_arr_size:	Size of the timings array. Depends on the number
+ *			of different frequencies for which timings data
+ *			is provided
+ * @min_tck:		Minimum value of some timing parameters in terms
+ *			of number of cycles. Can be NULL if default values
+ *			are ok
+ * @custom_configs:	Custom configurations requested by SoC or board
+ *			code and the data for them. Can be NULL if default
+ *			configurations done by the driver are ok. See
+ *			documentation for 'struct emif_custom_configs' for
+ *			more details
+ */
+struct emif_platform_data {
+	u32 hw_caps;
+	struct ddr_device_info *device_info;
+	const struct lpddr2_timings *timings;
+	u32 timings_arr_size;
+	const struct lpddr2_min_tck *min_tck;
+	struct emif_custom_configs *custom_configs;
+	u32 ip_rev;
+	u32 phy_type;
+};
+#endif /* __ASSEMBLY__ */
+
+#endif /* __LINUX_EMIF_H */
-- 
1.7.1


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

* [PATCH v4 3/7] misc: emif: add basic infrastructure for EMIF driver
@ 2012-03-16 21:51   ` Aneesh V
  0 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-03-16 21:51 UTC (permalink / raw)
  To: linux-arm-kernel

EMIF is an SDRAM controller used in various Texas Instruments
SoCs. EMIF supports, based on its revision, one or more of
LPDDR2/DDR2/DDR3 protocols.

Add the basic infrastructure for EMIF driver that includes
driver registration, probe, parsing of platform data etc.

Cc: Greg KH <greg@kroah.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
---
v2:
- replaced __init with __init_or_module

v1:
- Removed emif_cleanup() function and instead used
  devm_* variant of APIs for resource allocations
- Split include/linux/emif.h into two parts. The first
  part now becomes include/linux/platform_data/emif_plat.h
  and the other part is now merged in drivers/misc/emif.h
- Made error messages more verbose
- Corrected copyright year
- Fixed other coding style comments
- Minor adjustments to patch organization. Moved
  some definitions to a subsequent patch that uses
  them
- Added a list a of devices. This is needed for errata
  i728 workaround and for the new locking scheme
- Added documentation for driver
---
 Documentation/misc-devices/ti-emif.txt  |   58 ++++++
 drivers/misc/Kconfig                    |   12 ++
 drivers/misc/Makefile                   |    1 +
 drivers/misc/emif.c                     |  289 +++++++++++++++++++++++++++++++
 drivers/misc/emif.h                     |    7 +
 include/linux/platform_data/emif_plat.h |  128 ++++++++++++++
 6 files changed, 495 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/misc-devices/ti-emif.txt
 create mode 100644 drivers/misc/emif.c
 create mode 100644 include/linux/platform_data/emif_plat.h

diff --git a/Documentation/misc-devices/ti-emif.txt b/Documentation/misc-devices/ti-emif.txt
new file mode 100644
index 0000000..a9238c1
--- /dev/null
+++ b/Documentation/misc-devices/ti-emif.txt
@@ -0,0 +1,58 @@
+TI EMIF SDRAM Controller Driver:
+
+Author
+========
+Aneesh V <aneesh@ti.com>
+
+Location
+============
+driver/misc/emif.c
+
+Supported SoCs:
+===================
+TI OMAP44xx
+TI OMAP54xx
+
+Menuconfig option:
+==========================
+Device Drivers
+	Misc devices
+		Texas Instruments EMIF driver
+
+Description
+===========
+This driver is for the EMIF module available in Texas Instruments
+SoCs. EMIF is an SDRAM controller that, based on its revision,
+supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols.
+This driver takes care of only LPDDR2 memories presently. The
+functions of the driver includes re-configuring AC timing
+parameters and other settings during frequency, voltage and
+temperature changes
+
+Platform Data (see include/linux/platform_data/emif_plat.h):
+=====================================================================
+DDR device details and other board dependent and SoC dependent
+information can be passed through platform data (struct emif_platform_data)
+- DDR device details: 'struct ddr_device_info'
+- Device AC timings: 'struct lpddr2_timings' and 'struct lpddr2_min_tck'
+- Custom configurations: customizable policy options through
+  'struct emif_custom_configs'
+- IP revision
+- PHY type
+
+Interface to the external world:
+================================
+EMIF driver registers notifiers for voltage and frequency changes
+affecting EMIF and takes appropriate actions when these are invoked.
+- freq_pre_notify_handling()
+- freq_post_notify_handling()
+- volt_notify_handling()
+
+Debugfs
+========
+The driver creates two debugfs entries per device.
+- regcache_dump : dump of register values calculated and saved for all
+  frequencies used so far.
+- mr4 : last polled value of MR4 register in the LPDDR2 device. MR4
+  indicates the current temperature level of the device.
+
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index c779509..847a936 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -441,6 +441,18 @@ config VMWARE_BALLOON
 	  To compile this driver as a module, choose M here: the
 	  module will be called vmw_balloon.
 
+config TI_EMIF
+	tristate "Texas Instruments EMIF driver"
+	select DDR
+	help
+	  This driver is for the EMIF module available in Texas Instruments
+	  SoCs. EMIF is an SDRAM controller that, based on its revision,
+	  supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols.
+	  This driver takes care of only LPDDR2 memories presently. The
+	  functions of the driver includes re-configuring AC timing
+	  parameters and other settings during frequency, voltage and
+	  temperature changes
+
 config ARM_CHARLCD
 	bool "ARM Ltd. Character LCD Driver"
 	depends on PLAT_VERSATILE
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 3e1d801..75ab920 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_TI_DAC7512)	+= ti_dac7512.o
 obj-$(CONFIG_C2PORT)		+= c2port/
 obj-$(CONFIG_IWMC3200TOP)      += iwmc3200top/
 obj-$(CONFIG_HMC6352)		+= hmc6352.o
+obj-$(CONFIG_TI_EMIF)		+= emif.o
 obj-y				+= eeprom/
 obj-y				+= cb710/
 obj-$(CONFIG_SPEAR13XX_PCIE_GADGET)	+= spear13xx_pcie_gadget.o
diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c
new file mode 100644
index 0000000..f864640
--- /dev/null
+++ b/drivers/misc/emif.c
@@ -0,0 +1,289 @@
+/*
+ * EMIF driver
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Aneesh V <aneesh@ti.com>
+ * Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/platform_data/emif_plat.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <misc/jedec_ddr.h>
+#include "emif.h"
+
+/**
+ * struct emif_data - Per device static data for driver's use
+ * @duplicate:			Whether the DDR devices attached to this EMIF
+ *				instance are exactly same as that on EMIF1. In
+ *				this case we can save some memory and processing
+ * @temperature_level:		Maximum temperature of LPDDR2 devices attached
+ *				to this EMIF - read from MR4 register. If there
+ *				are two devices attached to this EMIF, this
+ *				value is the maximum of the two temperature
+ *				levels.
+ * @node:			node in the device list
+ * @base:			base address of memory-mapped IO registers.
+ * @dev:			device pointer.
+ * @plat_data:			Pointer to saved platform data.
+ */
+struct emif_data {
+	u8				duplicate;
+	u8				temperature_level;
+	struct list_head		node;
+	void __iomem			*base;
+	struct device			*dev;
+	struct emif_platform_data	*plat_data;
+};
+
+static struct emif_data *emif1;
+static LIST_HEAD(device_list);
+
+static void get_default_timings(struct emif_data *emif)
+{
+	struct emif_platform_data *pd = emif->plat_data;
+
+	pd->timings		= lpddr2_jedec_timings;
+	pd->timings_arr_size	= ARRAY_SIZE(lpddr2_jedec_timings);
+
+	dev_warn(emif->dev, "%s: using default timings\n", __func__);
+}
+
+static int is_dev_data_valid(u32 type, u32 density, u32 io_width, u32 phy_type,
+		u32 ip_rev, struct device *dev)
+{
+	int valid;
+
+	valid = (type == DDR_TYPE_LPDDR2_S4 ||
+			type == DDR_TYPE_LPDDR2_S2)
+		&& (density >= DDR_DENSITY_64Mb
+			&& density <= DDR_DENSITY_8Gb)
+		&& (io_width >= DDR_IO_WIDTH_8
+			&& io_width <= DDR_IO_WIDTH_32);
+
+	/* Combinations of EMIF and PHY revisions that we support today */
+	switch (ip_rev) {
+	case EMIF_4D:
+		valid = valid && (phy_type == EMIF_PHY_TYPE_ATTILAPHY);
+		break;
+	case EMIF_4D5:
+		valid = valid && (phy_type == EMIF_PHY_TYPE_INTELLIPHY);
+		break;
+	default:
+		valid = 0;
+	}
+
+	if (!valid)
+		dev_err(dev, "%s: invalid DDR details\n", __func__);
+	return valid;
+}
+
+static int is_custom_config_valid(struct emif_custom_configs *cust_cfgs,
+		struct device *dev)
+{
+	int valid = 1;
+
+	if ((cust_cfgs->mask & EMIF_CUSTOM_CONFIG_LPMODE) &&
+		(cust_cfgs->lpmode != EMIF_LP_MODE_DISABLE))
+		valid = cust_cfgs->lpmode_freq_threshold &&
+			cust_cfgs->lpmode_timeout_performance &&
+			cust_cfgs->lpmode_timeout_power;
+
+	if (cust_cfgs->mask & EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL)
+		valid = valid && cust_cfgs->temp_alert_poll_interval_ms;
+
+	if (!valid)
+		dev_warn(dev, "%s: invalid custom configs\n", __func__);
+
+	return valid;
+}
+
+static struct emif_data *__init_or_module get_device_details(
+		struct platform_device *pdev)
+{
+	u32				size;
+	struct emif_data		*emif = NULL;
+	struct ddr_device_info		*dev_info;
+	struct emif_custom_configs	*cust_cfgs;
+	struct emif_platform_data	*pd;
+	struct device			*dev;
+	void				*temp;
+
+	pd = pdev->dev.platform_data;
+	dev = &pdev->dev;
+
+	if (!(pd && pd->device_info && is_dev_data_valid(pd->device_info->type,
+			pd->device_info->density, pd->device_info->io_width,
+			pd->phy_type, pd->ip_rev, dev))) {
+		dev_err(dev, "%s: invalid device data\n", __func__);
+		goto error;
+	}
+
+	emif	= devm_kzalloc(dev, sizeof(*emif), GFP_KERNEL);
+	temp	= devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+	dev_info = devm_kzalloc(dev, sizeof(*dev_info), GFP_KERNEL);
+
+	if (!emif || !pd || !dev_info) {
+		dev_err(dev, "%s:%d: allocation error\n", __func__, __LINE__);
+		goto error;
+	}
+
+	memcpy(temp, pd, sizeof(*pd));
+	pd = temp;
+	memcpy(dev_info, pd->device_info, sizeof(*dev_info));
+
+	pd->device_info		= dev_info;
+	emif->plat_data		= pd;
+	emif->dev		= dev;
+	emif->temperature_level	= SDRAM_TEMP_NOMINAL;
+
+	/*
+	 * For EMIF instances other than EMIF1 see if the devices connected
+	 * are exactly same as on EMIF1(which is typically the case). If so,
+	 * mark it as a duplicate of EMIF1 and skip copying timings data.
+	 * This will save some memory and some computation later.
+	 */
+	emif->duplicate = emif1 && (memcmp(dev_info,
+		emif1->plat_data->device_info,
+		sizeof(struct ddr_device_info)) == 0);
+
+	if (emif->duplicate) {
+		pd->timings = NULL;
+		pd->min_tck = NULL;
+		goto out;
+	} else if (emif1) {
+		dev_warn(emif->dev, "%s: Non-symmetric DDR geometry\n",
+			__func__);
+	}
+
+	/*
+	 * Copy custom configs - ignore allocation error, if any, as
+	 * custom_configs is not very critical
+	 */
+	cust_cfgs = pd->custom_configs;
+	if (cust_cfgs && is_custom_config_valid(cust_cfgs, dev)) {
+		temp = devm_kzalloc(dev, sizeof(*cust_cfgs), GFP_KERNEL);
+		if (temp)
+			memcpy(temp, cust_cfgs, sizeof(*cust_cfgs));
+		else
+			dev_warn(dev, "%s:%d: allocation error\n", __func__,
+				__LINE__);
+		pd->custom_configs = temp;
+	}
+
+	/*
+	 * Copy timings and min-tck values from platform data. If it is not
+	 * available or if memory allocation fails, use JEDEC defaults
+	 */
+	size = sizeof(struct lpddr2_timings) * pd->timings_arr_size;
+	if (pd->timings) {
+		temp = devm_kzalloc(dev, size, GFP_KERNEL);
+		if (temp) {
+			memcpy(temp, pd->timings, sizeof(*pd->timings));
+			pd->timings = temp;
+		} else {
+			dev_warn(dev, "%s:%d: allocation error\n", __func__,
+				__LINE__);
+			get_default_timings(emif);
+		}
+	} else {
+		get_default_timings(emif);
+	}
+
+	if (pd->min_tck) {
+		temp = devm_kzalloc(dev, sizeof(*pd->min_tck), GFP_KERNEL);
+		if (temp) {
+			memcpy(temp, pd->min_tck, sizeof(*pd->min_tck));
+			pd->min_tck = temp;
+		} else {
+			dev_warn(dev, "%s:%d: allocation error\n", __func__,
+				__LINE__);
+			pd->min_tck = &lpddr2_jedec_min_tck;
+		}
+	} else {
+		pd->min_tck = &lpddr2_jedec_min_tck;
+	}
+
+out:
+	return emif;
+
+error:
+	return NULL;
+}
+
+static int __init_or_module emif_probe(struct platform_device *pdev)
+{
+	struct emif_data	*emif;
+	struct resource		*res;
+
+	emif = get_device_details(pdev);
+	if (!emif) {
+		pr_err("%s: error getting device data\n", __func__);
+		goto error;
+	}
+
+	if (!emif1)
+		emif1 = emif;
+
+	list_add(&emif->node, &device_list);
+
+	/* Save pointers to each other in emif and device structures */
+	emif->dev = &pdev->dev;
+	platform_set_drvdata(pdev, emif);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(emif->dev, "%s: error getting memory resource\n",
+			__func__);
+		goto error;
+	}
+
+	emif->base = devm_request_and_ioremap(emif->dev, res);
+	if (!emif->base) {
+		dev_err(emif->dev, "%s: devm_request_and_ioremap() failed\n",
+			__func__);
+		goto error;
+	}
+
+	dev_info(&pdev->dev, "%s: device configured with addr = %p\n",
+		__func__, emif->base);
+
+	return 0;
+error:
+	return -ENODEV;
+}
+
+static struct platform_driver emif_driver = {
+	.driver = {
+		.name = "emif",
+	},
+};
+
+static int __init_or_module emif_register(void)
+{
+	return platform_driver_probe(&emif_driver, emif_probe);
+}
+
+static void __exit emif_unregister(void)
+{
+	platform_driver_unregister(&emif_driver);
+}
+
+module_init(emif_register);
+module_exit(emif_unregister);
+MODULE_DESCRIPTION("TI EMIF SDRAM Controller Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:emif");
+MODULE_AUTHOR("Texas Instruments Inc");
diff --git a/drivers/misc/emif.h b/drivers/misc/emif.h
index 44b97df..692b2a8 100644
--- a/drivers/misc/emif.h
+++ b/drivers/misc/emif.h
@@ -12,6 +12,13 @@
 #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
+
 /* Registers offset */
 #define EMIF_MODULE_ID_AND_REVISION			0x0000
 #define EMIF_STATUS					0x0004
diff --git a/include/linux/platform_data/emif_plat.h b/include/linux/platform_data/emif_plat.h
new file mode 100644
index 0000000..03378ca
--- /dev/null
+++ b/include/linux/platform_data/emif_plat.h
@@ -0,0 +1,128 @@
+/*
+ * Definitions for TI EMIF device platform data
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Aneesh V <aneesh@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 __EMIF_PLAT_H
+#define __EMIF_PLAT_H
+
+/* Low power modes - EMIF_PWR_MGMT_CTRL */
+#define EMIF_LP_MODE_DISABLE				0
+#define EMIF_LP_MODE_CLOCK_STOP				1
+#define EMIF_LP_MODE_SELF_REFRESH			2
+#define EMIF_LP_MODE_PWR_DN				4
+
+/* Hardware capabilities */
+#define	EMIF_HW_CAPS_LL_INTERFACE			0x00000001
+
+/*
+ * EMIF IP Revisions
+ *	EMIF4D  - Used in OMAP4
+ *	EMIF4D5 - Used in OMAP5
+ */
+#define	EMIF_4D						1
+#define	EMIF_4D5					2
+
+/*
+ * PHY types
+ *	ATTILAPHY  - Used in OMAP4
+ *	INTELLIPHY - Used in OMAP5
+ */
+#define	EMIF_PHY_TYPE_ATTILAPHY				1
+#define	EMIF_PHY_TYPE_INTELLIPHY			2
+
+/* Custom config requests */
+#define EMIF_CUSTOM_CONFIG_LPMODE			0x00000001
+#define EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL	0x00000002
+
+#ifndef __ASSEMBLY__
+/**
+ * struct ddr_device_info - All information about the DDR device except AC
+ *		timing parameters
+ * @type:	Device type (LPDDR2-S4, LPDDR2-S2 etc)
+ * @density:	Device density
+ * @io_width:	Bus width
+ * @cs1_used:	Whether there is a DDR device attached to the second
+ *		chip-select(CS1) of this EMIF instance
+ * @cal_resistors_per_cs: Whether there is one calibration resistor per
+ *		chip-select or whether it's a single one for both
+ * @manufacturer: Manufacturer name string
+ */
+struct ddr_device_info {
+	u32	type;
+	u32	density;
+	u32	io_width;
+	u32	cs1_used;
+	u32	cal_resistors_per_cs;
+	char	manufacturer[10];
+};
+
+/**
+ * struct emif_custom_configs - Custom configuration parameters/policies
+ *		passed from the platform layer
+ * @mask:	Mask to indicate which configs are requested
+ * @lpmode:	LPMODE to be used in PWR_MGMT_CTRL register
+ * @lpmode_timeout_performance: Timeout before LPMODE entry when higher
+ *		performance is desired at the cost of power (typically
+ *		at higher OPPs)
+ * @lpmode_timeout_power: Timeout before LPMODE entry when better power
+ *		savings is desired and performance is not important
+ *		(typically at lower loads indicated by lower OPPs)
+ * @lpmode_freq_threshold: The DDR frequency threshold to identify between
+ *		the above two cases:
+ *		timeout = (freq >= lpmode_freq_threshold) ?
+ *			lpmode_timeout_performance :
+ *			lpmode_timeout_power;
+ * @temp_alert_poll_interval_ms: LPDDR2 MR4 polling interval at nominal
+ *		temperature(in milliseconds). When temperature is high
+ *		polling is done 4 times as frequently.
+ */
+struct emif_custom_configs {
+	u32 mask;
+	u32 lpmode;
+	u32 lpmode_timeout_performance;
+	u32 lpmode_timeout_power;
+	u32 lpmode_freq_threshold;
+	u32 temp_alert_poll_interval_ms;
+};
+
+/**
+ * struct emif_platform_data - Platform data passed on EMIF platform
+ *				device creation. Used by the driver.
+ * @hw_caps:		Hw capabilities of the EMIF IP in the respective SoC
+ * @device_info:	Device info structure containing information such
+ *			as type, bus width, density etc
+ * @timings:		Timings information from device datasheet passed
+ *			as an array of 'struct lpddr2_timings'. Can be NULL
+ *			if if default timings are ok
+ * @timings_arr_size:	Size of the timings array. Depends on the number
+ *			of different frequencies for which timings data
+ *			is provided
+ * @min_tck:		Minimum value of some timing parameters in terms
+ *			of number of cycles. Can be NULL if default values
+ *			are ok
+ * @custom_configs:	Custom configurations requested by SoC or board
+ *			code and the data for them. Can be NULL if default
+ *			configurations done by the driver are ok. See
+ *			documentation for 'struct emif_custom_configs' for
+ *			more details
+ */
+struct emif_platform_data {
+	u32 hw_caps;
+	struct ddr_device_info *device_info;
+	const struct lpddr2_timings *timings;
+	u32 timings_arr_size;
+	const struct lpddr2_min_tck *min_tck;
+	struct emif_custom_configs *custom_configs;
+	u32 ip_rev;
+	u32 phy_type;
+};
+#endif /* __ASSEMBLY__ */
+
+#endif /* __LINUX_EMIF_H */
-- 
1.7.1

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

* [PATCH v4 4/7] misc: emif: handle frequency and voltage change events
  2012-03-16 21:51 ` Aneesh V
@ 2012-03-16 21:51   ` Aneesh V
  -1 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-03-16 21:51 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-arm-kernel, linux-omap, Aneesh V, Greg KH

Change SDRAM timings and other settings as necessary
on voltage and frequency changes. We calculate these
register settings based on data from the device data
sheet and inputs such a frequency, voltage state(stable
or ramping), temperature level etc.

TODO: frequency and voltage change handling needs to
be integrated with clock framework and regulator
framework respectively. This is not done today
due to missing pieces in the kernel.

Cc: Greg KH <greg@kroah.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
---
v1:
- Added comment in commit log as well as code about
  missing integration part that needs to be done in
  future
- Removed some settings that were relevant only for
  DDR3
- Correction in temperature derated value of tim3
- Added errata i735 and i728  workarounds. As part of
  this we need to now maintain a list of all devices
  in the driver and iterate through them in some cases
- Improved synchronization. Added protection for newly
  identified cases of potential race conditions.
- Minor changes in patch organization. struct members
  needed by this patch now defined here.
---
 drivers/misc/emif.c |  894 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 drivers/misc/emif.h |  130 ++++++++-
 2 files changed, 1020 insertions(+), 4 deletions(-)

diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c
index f864640..1ca8165 100644
--- a/drivers/misc/emif.c
+++ b/drivers/misc/emif.c
@@ -21,6 +21,7 @@
 #include <linux/seq_file.h>
 #include <linux/module.h>
 #include <linux/list.h>
+#include <linux/spinlock.h>
 #include <misc/jedec_ddr.h>
 #include "emif.h"
 
@@ -37,20 +38,595 @@
  * @node:			node in the device list
  * @base:			base address of memory-mapped IO registers.
  * @dev:			device pointer.
+ * @addressing			table with addressing information from the spec
+ * @regs_cache:			An array of 'struct emif_regs' that stores
+ *				calculated register values for different
+ *				frequencies, to avoid re-calculating them on
+ *				each DVFS transition.
+ * @curr_regs:			The set of register values used in the last
+ *				frequency change (i.e. corresponding to the
+ *				frequency in effect at the moment)
  * @plat_data:			Pointer to saved platform data.
  */
 struct emif_data {
 	u8				duplicate;
 	u8				temperature_level;
+	u8				lpmode;
 	struct list_head		node;
+	unsigned long			irq_state;
 	void __iomem			*base;
 	struct device			*dev;
+	const struct lpddr2_addressing	*addressing;
+	struct emif_regs		*regs_cache[EMIF_MAX_NUM_FREQUENCIES];
+	struct emif_regs		*curr_regs;
 	struct emif_platform_data	*plat_data;
 };
 
 static struct emif_data *emif1;
+static spinlock_t	emif_lock;
+static unsigned long	irq_state;
+static u32		t_ck; /* DDR clock period in ps */
 static LIST_HEAD(device_list);
 
+/*
+ * Calculate the period of DDR clock from frequency value
+ */
+static void set_ddr_clk_period(u32 freq)
+{
+	/* Divide 10^12 by frequency to get period in ps */
+	t_ck = (u32)DIV_ROUND_UP_ULL(1000000000000ull, freq);
+}
+
+/*
+ * Get the CL from SDRAM_CONFIG register
+ */
+static u32 get_cl(struct emif_data *emif)
+{
+	u32		cl;
+	void __iomem	*base = emif->base;
+
+	cl = (readl(base + EMIF_SDRAM_CONFIG) & CL_MASK) >> CL_SHIFT;
+
+	return cl;
+}
+
+static void set_lpmode(struct emif_data *emif, u8 lpmode)
+{
+	u32 temp;
+	void __iomem *base = emif->base;
+
+	temp = readl(base + EMIF_POWER_MANAGEMENT_CONTROL);
+	temp &= ~LP_MODE_MASK;
+	temp |= (lpmode << LP_MODE_SHIFT);
+	writel(temp, base + EMIF_POWER_MANAGEMENT_CONTROL);
+}
+
+static void do_freq_update(void)
+{
+	struct emif_data *emif;
+
+	/*
+	 * Workaround for errata i728: Disable LPMODE during FREQ_UPDATE
+	 *
+	 * i728 DESCRIPTION:
+	 * The EMIF automatically puts the SDRAM into self-refresh mode
+	 * after the EMIF has not performed accesses during
+	 * EMIF_PWR_MGMT_CTRL[7:4] REG_SR_TIM number of DDR clock cycles
+	 * and the EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE bit field is set
+	 * to 0x2. If during a small window the following three events
+	 * occur:
+	 * - The SR_TIMING counter expires
+	 * - And frequency change is requested
+	 * - And OCP access is requested
+	 * Then it causes instable clock on the DDR interface.
+	 *
+	 * WORKAROUND
+	 * To avoid the occurrence of the three events, the workaround
+	 * is to disable the self-refresh when requesting a frequency
+	 * change. Before requesting a frequency change the software must
+	 * program EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x0. When the
+	 * frequency change has been done, the software can reprogram
+	 * EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x2
+	 */
+	list_for_each_entry(emif, &device_list, node) {
+		if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH)
+			set_lpmode(emif, EMIF_LP_MODE_DISABLE);
+	}
+
+	/*
+	 * TODO: Do FREQ_UPDATE here when an API
+	 * is available for this as part of the new
+	 * clock framework
+	 */
+
+	list_for_each_entry(emif, &device_list, node) {
+		if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH)
+			set_lpmode(emif, EMIF_LP_MODE_SELF_REFRESH);
+	}
+}
+
+/* Find addressing table entry based on the device's type and density */
+static const struct lpddr2_addressing *get_addressing_table(
+	const struct ddr_device_info *device_info)
+{
+	u32		index, type, density;
+
+	type = device_info->type;
+	density = device_info->density;
+
+	switch (type) {
+	case DDR_TYPE_LPDDR2_S4:
+		index = density - 1;
+		break;
+	case DDR_TYPE_LPDDR2_S2:
+		switch (density) {
+		case DDR_DENSITY_1Gb:
+		case DDR_DENSITY_2Gb:
+			index = density + 3;
+			break;
+		default:
+			index = density - 1;
+		}
+		break;
+	default:
+		return NULL;
+	}
+
+	return &lpddr2_jedec_addressing_table[index];
+}
+
+/*
+ * Find the the right timing table from the array of timing
+ * tables of the device using DDR clock frequency
+ */
+static const struct lpddr2_timings *get_timings_table(struct emif_data *emif,
+		u32 freq)
+{
+	u32				i, min, max, freq_nearest;
+	const struct lpddr2_timings	*timings = NULL;
+	const struct lpddr2_timings	*timings_arr = emif->plat_data->timings;
+	struct				device *dev = emif->dev;
+
+	/* Start with a very high frequency - 1GHz */
+	freq_nearest = 1000000000;
+
+	/*
+	 * Find the timings table such that:
+	 *  1. the frequency range covers the required frequency(safe) AND
+	 *  2. the max_freq is closest to the required frequency(optimal)
+	 */
+	for (i = 0; i < emif->plat_data->timings_arr_size; i++) {
+		max = timings_arr[i].max_freq;
+		min = timings_arr[i].min_freq;
+		if ((freq >= min) && (freq <= max) && (max < freq_nearest)) {
+			freq_nearest = max;
+			timings = &timings_arr[i];
+		}
+	}
+
+	if (!timings)
+		dev_err(dev, "%s: couldn't find timings for - %dHz\n",
+			__func__, freq);
+
+	dev_dbg(dev, "%s: timings table: freq %d, speed bin freq %d\n",
+		__func__, freq, freq_nearest);
+
+	return timings;
+}
+
+static u32 get_sdram_ref_ctrl_shdw(u32 freq,
+		const struct lpddr2_addressing *addressing)
+{
+	u32 ref_ctrl_shdw = 0, val = 0, freq_khz, t_refi;
+
+	/* Scale down frequency and t_refi to avoid overflow */
+	freq_khz = freq / 1000;
+	t_refi = addressing->tREFI_ns / 100;
+
+	/*
+	 * refresh rate to be set is 'tREFI(in us) * freq in MHz
+	 * division by 10000 to account for change in units
+	 */
+	val = t_refi * freq_khz / 10000;
+	ref_ctrl_shdw |= val << REFRESH_RATE_SHIFT;
+
+	return ref_ctrl_shdw;
+}
+
+static u32 get_sdram_tim_1_shdw(const struct lpddr2_timings *timings,
+		const struct lpddr2_min_tck *min_tck,
+		const struct lpddr2_addressing *addressing)
+{
+	u32 tim1 = 0, val = 0;
+
+	val = max(min_tck->tWTR, DIV_ROUND_UP(timings->tWTR, t_ck)) - 1;
+	tim1 |= val << T_WTR_SHIFT;
+
+	if (addressing->num_banks == B8)
+		val = DIV_ROUND_UP(timings->tFAW, t_ck*4);
+	else
+		val = max(min_tck->tRRD, DIV_ROUND_UP(timings->tRRD, t_ck));
+	tim1 |= (val - 1) << T_RRD_SHIFT;
+
+	val = DIV_ROUND_UP(timings->tRAS_min + timings->tRPab, t_ck) - 1;
+	tim1 |= val << T_RC_SHIFT;
+
+	val = max(min_tck->tRASmin, DIV_ROUND_UP(timings->tRAS_min, t_ck));
+	tim1 |= (val - 1) << T_RAS_SHIFT;
+
+	val = max(min_tck->tWR, DIV_ROUND_UP(timings->tWR, t_ck)) - 1;
+	tim1 |= val << T_WR_SHIFT;
+
+	val = max(min_tck->tRCD, DIV_ROUND_UP(timings->tRCD, t_ck)) - 1;
+	tim1 |= val << T_RCD_SHIFT;
+
+	val = max(min_tck->tRPab, DIV_ROUND_UP(timings->tRPab, t_ck)) - 1;
+	tim1 |= val << T_RP_SHIFT;
+
+	return tim1;
+}
+
+static u32 get_sdram_tim_1_shdw_derated(const struct lpddr2_timings *timings,
+		const struct lpddr2_min_tck *min_tck,
+		const struct lpddr2_addressing *addressing)
+{
+	u32 tim1 = 0, val = 0;
+
+	val = max(min_tck->tWTR, DIV_ROUND_UP(timings->tWTR, t_ck)) - 1;
+	tim1 = val << T_WTR_SHIFT;
+
+	/*
+	 * tFAW is approximately 4 times tRRD. So add 1875*4 = 7500ps
+	 * to tFAW for de-rating
+	 */
+	if (addressing->num_banks == B8) {
+		val = DIV_ROUND_UP(timings->tFAW + 7500, 4 * t_ck) - 1;
+	} else {
+		val = DIV_ROUND_UP(timings->tRRD + 1875, t_ck);
+		val = max(min_tck->tRRD, val) - 1;
+	}
+	tim1 |= val << T_RRD_SHIFT;
+
+	val = DIV_ROUND_UP(timings->tRAS_min + timings->tRPab + 1875, t_ck);
+	tim1 |= (val - 1) << T_RC_SHIFT;
+
+	val = DIV_ROUND_UP(timings->tRAS_min + 1875, t_ck);
+	val = max(min_tck->tRASmin, val) - 1;
+	tim1 |= val << T_RAS_SHIFT;
+
+	val = max(min_tck->tWR, DIV_ROUND_UP(timings->tWR, t_ck)) - 1;
+	tim1 |= val << T_WR_SHIFT;
+
+	val = max(min_tck->tRCD, DIV_ROUND_UP(timings->tRCD + 1875, t_ck));
+	tim1 |= (val - 1) << T_RCD_SHIFT;
+
+	val = max(min_tck->tRPab, DIV_ROUND_UP(timings->tRPab + 1875, t_ck));
+	tim1 |= (val - 1) << T_RP_SHIFT;
+
+	return tim1;
+}
+
+static u32 get_sdram_tim_2_shdw(const struct lpddr2_timings *timings,
+		const struct lpddr2_min_tck *min_tck,
+		const struct lpddr2_addressing *addressing,
+		u32 type)
+{
+	u32 tim2 = 0, val = 0;
+
+	val = min_tck->tCKE - 1;
+	tim2 |= val << T_CKE_SHIFT;
+
+	val = max(min_tck->tRTP, DIV_ROUND_UP(timings->tRTP, t_ck)) - 1;
+	tim2 |= val << T_RTP_SHIFT;
+
+	/* tXSNR = tRFCab_ps + 10 ns(tRFCab_ps for LPDDR2). */
+	val = DIV_ROUND_UP(addressing->tRFCab_ps + 10000, t_ck) - 1;
+	tim2 |= val << T_XSNR_SHIFT;
+
+	/* XSRD same as XSNR for LPDDR2 */
+	tim2 |= val << T_XSRD_SHIFT;
+
+	val = max(min_tck->tXP, DIV_ROUND_UP(timings->tXP, t_ck)) - 1;
+	tim2 |= val << T_XP_SHIFT;
+
+	return tim2;
+}
+
+static u32 get_sdram_tim_3_shdw(const struct lpddr2_timings *timings,
+		const struct lpddr2_min_tck *min_tck,
+		const struct lpddr2_addressing *addressing,
+		u32 type, u32 ip_rev, u32 derated)
+{
+	u32 tim3 = 0, val = 0, t_dqsck;
+
+	val = timings->tRAS_max_ns / addressing->tREFI_ns - 1;
+	val = val > 0xF ? 0xF : val;
+	tim3 |= val << T_RAS_MAX_SHIFT;
+
+	val = DIV_ROUND_UP(addressing->tRFCab_ps, t_ck) - 1;
+	tim3 |= val << T_RFC_SHIFT;
+
+	t_dqsck = (derated == EMIF_DERATED_TIMINGS) ?
+		timings->tDQSCK_max_derated : timings->tDQSCK_max;
+	if (ip_rev == EMIF_4D5)
+		val = DIV_ROUND_UP(t_dqsck + 1000, t_ck) - 1;
+	else
+		val = DIV_ROUND_UP(t_dqsck, t_ck) - 1;
+
+	tim3 |= val << T_TDQSCKMAX_SHIFT;
+
+	val = DIV_ROUND_UP(timings->tZQCS, t_ck) - 1;
+	tim3 |= val << ZQ_ZQCS_SHIFT;
+
+	val = DIV_ROUND_UP(timings->tCKESR, t_ck);
+	val = max(min_tck->tCKESR, val) - 1;
+	tim3 |= val << T_CKESR_SHIFT;
+
+	if (ip_rev == EMIF_4D5) {
+		tim3 |= (EMIF_T_CSTA - 1) << T_CSTA_SHIFT;
+
+		val = DIV_ROUND_UP(EMIF_T_PDLL_UL, 128) - 1;
+		tim3 |= val << T_PDLL_UL_SHIFT;
+	}
+
+	return tim3;
+}
+
+static u32 get_read_idle_ctrl_shdw(u8 volt_ramp)
+{
+	u32 idle = 0, val = 0;
+
+	/*
+	 * Maximum value in normal conditions and increased frequency
+	 * when voltage is ramping
+	 */
+	if (volt_ramp)
+		val = READ_IDLE_INTERVAL_DVFS / t_ck / 64 - 1;
+	else
+		val = 0x1FF;
+
+	/*
+	 * READ_IDLE_CTRL register in EMIF4D has same offset and fields
+	 * as DLL_CALIB_CTRL in EMIF4D5, so use the same shifts
+	 */
+	idle |= val << DLL_CALIB_INTERVAL_SHIFT;
+	idle |= EMIF_READ_IDLE_LEN_VAL << ACK_WAIT_SHIFT;
+
+	return idle;
+}
+
+static u32 get_dll_calib_ctrl_shdw(u8 volt_ramp)
+{
+	u32 calib = 0, val = 0;
+
+	if (volt_ramp == DDR_VOLTAGE_RAMPING)
+		val = DLL_CALIB_INTERVAL_DVFS / t_ck / 16 - 1;
+	else
+		val = 0; /* Disabled when voltage is stable */
+
+	calib |= val << DLL_CALIB_INTERVAL_SHIFT;
+	calib |= DLL_CALIB_ACK_WAIT_VAL << ACK_WAIT_SHIFT;
+
+	return calib;
+}
+
+static u32 get_ddr_phy_ctrl_1_attilaphy_4d(const struct lpddr2_timings *timings,
+	u32 freq, u8 RL)
+{
+	u32 phy = EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY, val = 0;
+
+	val = RL + DIV_ROUND_UP(timings->tDQSCK_max, t_ck) - 1;
+	phy |= val << READ_LATENCY_SHIFT_4D;
+
+	if (freq <= 100000000)
+		val = EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY;
+	else if (freq <= 200000000)
+		val = EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY;
+	else
+		val = EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY;
+
+	phy |= val << DLL_SLAVE_DLY_CTRL_SHIFT_4D;
+
+	return phy;
+}
+
+static u32 get_phy_ctrl_1_intelliphy_4d5(u32 freq, u8 cl)
+{
+	u32 phy = EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY, half_delay;
+
+	/*
+	 * DLL operates at 266 MHz. If DDR frequency is near 266 MHz,
+	 * half-delay is not needed else set half-delay
+	 */
+	if (freq >= 265000000 && freq < 267000000)
+		half_delay = 0;
+	else
+		half_delay = 1;
+
+	phy |= half_delay << DLL_HALF_DELAY_SHIFT_4D5;
+	phy |= ((cl + DIV_ROUND_UP(EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS,
+			t_ck) - 1) << READ_LATENCY_SHIFT_4D5);
+
+	return phy;
+}
+
+static u32 get_ext_phy_ctrl_2_intelliphy_4d5(void)
+{
+	u32 fifo_we_slave_ratio;
+
+	fifo_we_slave_ratio =  DIV_ROUND_CLOSEST(
+		EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256 , t_ck);
+
+	return fifo_we_slave_ratio | fifo_we_slave_ratio << 11 |
+		fifo_we_slave_ratio << 22;
+}
+
+static u32 get_ext_phy_ctrl_3_intelliphy_4d5(void)
+{
+	u32 fifo_we_slave_ratio;
+
+	fifo_we_slave_ratio =  DIV_ROUND_CLOSEST(
+		EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256 , t_ck);
+
+	return fifo_we_slave_ratio >> 10 | fifo_we_slave_ratio << 1 |
+		fifo_we_slave_ratio << 12 | fifo_we_slave_ratio << 23;
+}
+
+static u32 get_ext_phy_ctrl_4_intelliphy_4d5(void)
+{
+	u32 fifo_we_slave_ratio;
+
+	fifo_we_slave_ratio =  DIV_ROUND_CLOSEST(
+		EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256 , t_ck);
+
+	return fifo_we_slave_ratio >> 9 | fifo_we_slave_ratio << 2 |
+		fifo_we_slave_ratio << 13;
+}
+
+static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev)
+{
+	u32 pwr_mgmt_ctrl	= 0, timeout;
+	u32 lpmode		= EMIF_LP_MODE_SELF_REFRESH;
+	u32 timeout_perf	= EMIF_LP_MODE_TIMEOUT_PERFORMANCE;
+	u32 timeout_pwr		= EMIF_LP_MODE_TIMEOUT_POWER;
+	u32 freq_threshold	= EMIF_LP_MODE_FREQ_THRESHOLD;
+
+	struct emif_custom_configs *cust_cfgs = emif->plat_data->custom_configs;
+
+	if (cust_cfgs && (cust_cfgs->mask & EMIF_CUSTOM_CONFIG_LPMODE)) {
+		lpmode		= cust_cfgs->lpmode;
+		timeout_perf	= cust_cfgs->lpmode_timeout_performance;
+		timeout_pwr	= cust_cfgs->lpmode_timeout_power;
+		freq_threshold  = cust_cfgs->lpmode_freq_threshold;
+	}
+
+	/* Timeout based on DDR frequency */
+	timeout = freq >= freq_threshold ? timeout_perf : timeout_pwr;
+
+	/* The value to be set in register is "log2(timeout) - 3" */
+	if (timeout < 16) {
+		timeout = 0;
+	} else {
+		timeout = __fls(timeout) - 3;
+		if (timeout & (timeout - 1))
+			timeout++;
+	}
+
+	switch (lpmode) {
+	case EMIF_LP_MODE_CLOCK_STOP:
+		pwr_mgmt_ctrl = (timeout << CS_TIM_SHIFT) |
+					SR_TIM_MASK | PD_TIM_MASK;
+		break;
+	case EMIF_LP_MODE_SELF_REFRESH:
+		/* Workaround for errata i735 */
+		if (timeout < 6)
+			timeout = 6;
+
+		pwr_mgmt_ctrl = (timeout << SR_TIM_SHIFT) |
+					CS_TIM_MASK | PD_TIM_MASK;
+		break;
+	case EMIF_LP_MODE_PWR_DN:
+		pwr_mgmt_ctrl = (timeout << PD_TIM_SHIFT) |
+					CS_TIM_MASK | SR_TIM_MASK;
+		break;
+	case EMIF_LP_MODE_DISABLE:
+	default:
+		pwr_mgmt_ctrl = CS_TIM_MASK |
+					PD_TIM_MASK | SR_TIM_MASK;
+	}
+
+	/* No CS_TIM in EMIF_4D5 */
+	if (ip_rev == EMIF_4D5)
+		pwr_mgmt_ctrl &= ~CS_TIM_MASK;
+
+	pwr_mgmt_ctrl |= lpmode << LP_MODE_SHIFT;
+
+	return pwr_mgmt_ctrl;
+}
+
+/*
+ * Program EMIF shadow registers that are not dependent on temperature
+ * or voltage
+ */
+static void setup_registers(struct emif_data *emif, struct emif_regs *regs)
+{
+	void __iomem	*base = emif->base;
+
+	writel(regs->sdram_tim2_shdw, base + EMIF_SDRAM_TIMING_2_SHDW);
+	writel(regs->phy_ctrl_1_shdw, base + EMIF_DDR_PHY_CTRL_1_SHDW);
+
+	/* Settings specific for EMIF4D5 */
+	if (emif->plat_data->ip_rev != EMIF_4D5)
+		return;
+	writel(regs->ext_phy_ctrl_2_shdw, base + EMIF_EXT_PHY_CTRL_2_SHDW);
+	writel(regs->ext_phy_ctrl_3_shdw, base + EMIF_EXT_PHY_CTRL_3_SHDW);
+	writel(regs->ext_phy_ctrl_4_shdw, base + EMIF_EXT_PHY_CTRL_4_SHDW);
+}
+
+/*
+ * When voltage ramps dll calibration and forced read idle should
+ * happen more often
+ */
+static void setup_volt_sensitive_regs(struct emif_data *emif,
+		struct emif_regs *regs, u32 volt_state)
+{
+	u32		calib_ctrl;
+	void __iomem	*base = emif->base;
+
+	/*
+	 * EMIF_READ_IDLE_CTRL in EMIF4D refers to the same register as
+	 * EMIF_DLL_CALIB_CTRL in EMIF4D5 and dll_calib_ctrl_shadow_*
+	 * is an alias of the respective read_idle_ctrl_shdw_* (members of
+	 * a union). So, the below code takes care of both cases
+	 */
+	if (volt_state == DDR_VOLTAGE_RAMPING)
+		calib_ctrl = regs->dll_calib_ctrl_shdw_volt_ramp;
+	else
+		calib_ctrl = regs->dll_calib_ctrl_shdw_normal;
+
+	writel(calib_ctrl, base + EMIF_DLL_CALIB_CTRL_SHDW);
+}
+
+/*
+ * setup_temperature_sensitive_regs() - set the timings for temperature
+ * sensitive registers. This happens once at initialisation time based
+ * on the temperature at boot time and subsequently based on the temperature
+ * alert interrupt. Temperature alert can happen when the temperature
+ * increases or drops. So this function can have the effect of either
+ * derating the timings or going back to nominal values.
+ */
+static void setup_temperature_sensitive_regs(struct emif_data *emif,
+		struct emif_regs *regs)
+{
+	u32		tim1, tim3, ref_ctrl, type;
+	void __iomem	*base = emif->base;
+	u32		temperature;
+
+	type = emif->plat_data->device_info->type;
+
+	tim1 = regs->sdram_tim1_shdw;
+	tim3 = regs->sdram_tim3_shdw;
+	ref_ctrl = regs->ref_ctrl_shdw;
+
+	/* No de-rating for non-lpddr2 devices */
+	if (type != DDR_TYPE_LPDDR2_S2 && type != DDR_TYPE_LPDDR2_S4)
+		goto out;
+
+	temperature = emif->temperature_level;
+	if (temperature == SDRAM_TEMP_HIGH_DERATE_REFRESH) {
+		ref_ctrl = regs->ref_ctrl_shdw_derated;
+	} else if (temperature == SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS) {
+		tim1 = regs->sdram_tim1_shdw_derated;
+		tim3 = regs->sdram_tim3_shdw_derated;
+		ref_ctrl = regs->ref_ctrl_shdw_derated;
+	}
+
+out:
+	writel(tim1, base + EMIF_SDRAM_TIMING_1_SHDW);
+	writel(tim3, base + EMIF_SDRAM_TIMING_3_SHDW);
+	writel(ref_ctrl, base + EMIF_SDRAM_REFRESH_CTRL_SHDW);
+}
+
 static void get_default_timings(struct emif_data *emif)
 {
 	struct emif_platform_data *pd = emif->plat_data;
@@ -234,10 +810,8 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
 		goto error;
 	}
 
-	if (!emif1)
-		emif1 = emif;
-
 	list_add(&emif->node, &device_list);
+	emif->addressing = get_addressing_table(emif->plat_data->device_info);
 
 	/* Save pointers to each other in emif and device structures */
 	emif->dev = &pdev->dev;
@@ -257,6 +831,18 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
 		goto error;
 	}
 
+	/* One-time actions taken on probing the first device */
+	if (!emif1) {
+		emif1 = emif;
+		spin_lock_init(&emif_lock);
+
+		/*
+		 * TODO: register notifiers for frequency and voltage
+		 * change here once the respective frameworks are
+		 * available
+		 */
+	}
+
 	dev_info(&pdev->dev, "%s: device configured with addr = %p\n",
 		__func__, emif->base);
 
@@ -265,6 +851,308 @@ error:
 	return -ENODEV;
 }
 
+static int get_emif_reg_values(struct emif_data *emif, u32 freq,
+		struct emif_regs *regs)
+{
+	u32				cs1_used, ip_rev, phy_type;
+	u32				cl, type;
+	const struct lpddr2_timings	*timings;
+	const struct lpddr2_min_tck	*min_tck;
+	const struct ddr_device_info	*device_info;
+	const struct lpddr2_addressing	*addressing;
+	struct emif_data		*emif_for_calc;
+	struct device			*dev;
+	const struct emif_custom_configs *custom_configs;
+
+	dev = emif->dev;
+	/*
+	 * If the devices on this EMIF instance is duplicate of EMIF1,
+	 * use EMIF1 details for the calculation
+	 */
+	emif_for_calc	= emif->duplicate ? emif1 : emif;
+	timings		= get_timings_table(emif_for_calc, freq);
+	addressing	= emif_for_calc->addressing;
+	if (!timings || !addressing) {
+		dev_err(dev, "%s: not enough data available for %dHz",
+			__func__, freq);
+		return -1;
+	}
+
+	device_info	= emif_for_calc->plat_data->device_info;
+	type		= device_info->type;
+	cs1_used	= device_info->cs1_used;
+	ip_rev		= emif_for_calc->plat_data->ip_rev;
+	phy_type	= emif_for_calc->plat_data->phy_type;
+
+	min_tck		= emif_for_calc->plat_data->min_tck;
+	custom_configs	= emif_for_calc->plat_data->custom_configs;
+
+	set_ddr_clk_period(freq);
+
+	regs->ref_ctrl_shdw = get_sdram_ref_ctrl_shdw(freq, addressing);
+	regs->sdram_tim1_shdw = get_sdram_tim_1_shdw(timings, min_tck,
+			addressing);
+	regs->sdram_tim2_shdw = get_sdram_tim_2_shdw(timings, min_tck,
+			addressing, type);
+	regs->sdram_tim3_shdw = get_sdram_tim_3_shdw(timings, min_tck,
+		addressing, type, ip_rev, EMIF_NORMAL_TIMINGS);
+
+	cl = get_cl(emif);
+
+	if (phy_type == EMIF_PHY_TYPE_ATTILAPHY && ip_rev == EMIF_4D) {
+		regs->phy_ctrl_1_shdw = get_ddr_phy_ctrl_1_attilaphy_4d(
+			timings, freq, cl);
+	} else if (phy_type == EMIF_PHY_TYPE_INTELLIPHY && ip_rev == EMIF_4D5) {
+		regs->phy_ctrl_1_shdw = get_phy_ctrl_1_intelliphy_4d5(freq, cl);
+		regs->ext_phy_ctrl_2_shdw = get_ext_phy_ctrl_2_intelliphy_4d5();
+		regs->ext_phy_ctrl_3_shdw = get_ext_phy_ctrl_3_intelliphy_4d5();
+		regs->ext_phy_ctrl_4_shdw = get_ext_phy_ctrl_4_intelliphy_4d5();
+	} else {
+		return -1;
+	}
+
+	/* Only timeout values in pwr_mgmt_ctrl_shdw register */
+	regs->pwr_mgmt_ctrl_shdw =
+		get_pwr_mgmt_ctrl(freq, emif_for_calc, ip_rev) &
+		(CS_TIM_MASK | SR_TIM_MASK | PD_TIM_MASK);
+
+	if (ip_rev & EMIF_4D) {
+		regs->read_idle_ctrl_shdw_normal =
+			get_read_idle_ctrl_shdw(DDR_VOLTAGE_STABLE);
+
+		regs->read_idle_ctrl_shdw_volt_ramp =
+			get_read_idle_ctrl_shdw(DDR_VOLTAGE_RAMPING);
+	} else if (ip_rev & EMIF_4D5) {
+		regs->dll_calib_ctrl_shdw_normal =
+			get_dll_calib_ctrl_shdw(DDR_VOLTAGE_STABLE);
+
+		regs->dll_calib_ctrl_shdw_volt_ramp =
+			get_dll_calib_ctrl_shdw(DDR_VOLTAGE_RAMPING);
+	}
+
+	if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) {
+		regs->ref_ctrl_shdw_derated = get_sdram_ref_ctrl_shdw(freq / 4,
+			addressing);
+
+		regs->sdram_tim1_shdw_derated =
+			get_sdram_tim_1_shdw_derated(timings, min_tck,
+				addressing);
+
+		regs->sdram_tim3_shdw_derated = get_sdram_tim_3_shdw(timings,
+			min_tck, addressing, type, ip_rev,
+			EMIF_DERATED_TIMINGS);
+	}
+
+	regs->freq = freq;
+
+	return 0;
+}
+
+/*
+ * get_regs() - gets the cached emif_regs structure for a given EMIF instance
+ * given frequency(freq):
+ *
+ * As an optimisation, every EMIF instance other than EMIF1 shares the
+ * register cache with EMIF1 if the devices connected on this instance
+ * are same as that on EMIF1(indicated by the duplicate flag)
+ *
+ * If we do not have an entry corresponding to the frequency given, we
+ * allocate a new entry and calculate the values
+ *
+ * Upon finding the right reg dump, save it in curr_regs. It can be
+ * directly used for thermal de-rating and voltage ramping changes.
+ */
+static struct emif_regs *get_regs(struct emif_data *emif, u32 freq)
+{
+	int			i;
+	struct emif_regs	**regs_cache;
+	struct emif_regs	*regs = NULL;
+	struct device		*dev;
+
+	dev = emif->dev;
+	if (emif->curr_regs && emif->curr_regs->freq == freq) {
+		dev_dbg(dev, "%s: using curr_regs - %u Hz", __func__, freq);
+		return emif->curr_regs;
+	}
+
+	if (emif->duplicate)
+		regs_cache = emif1->regs_cache;
+	else
+		regs_cache = emif->regs_cache;
+
+	for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++) {
+		if (regs_cache[i]->freq == freq) {
+			regs = regs_cache[i];
+			dev_dbg(dev,
+				"%s: reg dump found in reg cache for %u Hz\n",
+				__func__, freq);
+			break;
+		}
+	}
+
+	/*
+	 * If we don't have an entry for this frequency in the cache create one
+	 * and calculate the values
+	 */
+	if (!regs) {
+		regs = devm_kzalloc(emif->dev, sizeof(*regs), GFP_ATOMIC);
+		if (!regs)
+			return NULL;
+
+		if (get_emif_reg_values(emif, freq, regs)) {
+			devm_kfree(emif->dev, regs);
+			return NULL;
+		}
+
+		/*
+		 * Now look for an un-used entry in the cache and save the
+		 * newly created struct. If there are no free entries
+		 * over-write the last entry
+		 */
+		for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++)
+			;
+
+		if (i >= EMIF_MAX_NUM_FREQUENCIES) {
+			dev_warn(dev, "%s: regs_cache full - reusing a slot!!\n",
+				__func__);
+			i = EMIF_MAX_NUM_FREQUENCIES - 1;
+			devm_kfree(emif->dev, regs_cache[i]);
+		}
+		regs_cache[i] = regs;
+	}
+
+	return regs;
+}
+
+static void do_volt_notify_handling(struct emif_data *emif, u32 volt_state)
+{
+	dev_dbg(emif->dev, "%s: voltage notification : %d", __func__,
+		volt_state);
+
+	if (!emif->curr_regs) {
+		dev_err(emif->dev,
+			"%s: volt-notify before registers are ready: %d\n",
+			__func__, volt_state);
+		return;
+	}
+
+	setup_volt_sensitive_regs(emif, emif->curr_regs, volt_state);
+}
+
+/*
+ * TODO: voltage notify handling should be hooked up to
+ * regulator framework as soon as the necessary support
+ * is available in mainline kernel. This function is un-used
+ * right now.
+ */
+static void __attribute__((unused)) volt_notify_handling(u32 volt_state)
+{
+	struct emif_data *emif;
+
+	spin_lock_irqsave(&emif_lock, irq_state);
+
+	list_for_each_entry(emif, &device_list, node)
+		do_volt_notify_handling(emif, volt_state);
+	do_freq_update();
+
+	spin_unlock_irqrestore(&emif_lock, irq_state);
+}
+
+static void do_freq_pre_notify_handling(struct emif_data *emif, u32 new_freq)
+{
+	struct emif_regs *regs;
+
+	regs = get_regs(emif, new_freq);
+	if (!regs)
+		return;
+
+	emif->curr_regs = regs;
+
+	/*
+	 * Update the shadow registers:
+	 * Temperature and voltage-ramp sensitive settings are also configured
+	 * in terms of DDR cycles. So, we need to update them too when there
+	 * is a freq change
+	 */
+	dev_dbg(emif->dev, "%s: setting up shadow registers for %uHz",
+		__func__, new_freq);
+	setup_registers(emif, regs);
+	setup_temperature_sensitive_regs(emif, regs);
+	setup_volt_sensitive_regs(emif, regs, DDR_VOLTAGE_STABLE);
+
+	/*
+	 * Part of workaround for errata i728. See do_freq_update()
+	 * for more details
+	 */
+	if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH)
+		set_lpmode(emif, EMIF_LP_MODE_DISABLE);
+}
+
+/*
+ * TODO: frequency notify handling should be hooked up to
+ * clock framework as soon as the necessary support is
+ * available in mainline kernel. This function is un-used
+ * right now.
+ */
+static void __attribute__((unused)) freq_pre_notify_handling(u32 new_freq)
+{
+	struct emif_data *emif;
+
+	/*
+	 * NOTE: we are taking the spin-lock here and releases it
+	 * only in post-notifier. This doesn't look good and
+	 * Sparse complains about it, but this seems to be
+	 * un-avoidable. We need to lock a sequence of events
+	 * that is split between EMIF and clock framework.
+	 *
+	 * 1. EMIF driver updates EMIF timings in shadow registers in the
+	 *    frequency pre-notify callback from clock framework
+	 * 2. clock framework sets up the registers for the new frequency
+	 * 3. clock framework initiates a hw-sequence that updates
+	 *    the frequency EMIF timings synchronously.
+	 *
+	 * All these 3 steps should be performed as an atomic operation
+	 * vis-a-vis similar sequence in the EMIF interrupt handler
+	 * for temperature events. Otherwise, there could be race
+	 * conditions that could result in incorrect EMIF timings for
+	 * a given frequency
+	 */
+	spin_lock_irqsave(&emif_lock, irq_state);
+
+	list_for_each_entry(emif, &device_list, node)
+		do_freq_pre_notify_handling(emif, new_freq);
+}
+
+static void do_freq_post_notify_handling(struct emif_data *emif)
+{
+	/*
+	 * Part of workaround for errata i728. See do_freq_update()
+	 * for more details
+	 */
+	if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH)
+		set_lpmode(emif, EMIF_LP_MODE_SELF_REFRESH);
+}
+
+/*
+ * TODO: frequency notify handling should be hooked up to
+ * clock framework as soon as the necessary support is
+ * available in mainline kernel. This function is un-used
+ * right now.
+ */
+static void __attribute__((unused)) freq_post_notify_handling(void)
+{
+	struct emif_data *emif;
+
+	list_for_each_entry(emif, &device_list, node)
+		do_freq_post_notify_handling(emif);
+
+	/*
+	 * Lock is done in pre-notify handler. See freq_pre_notify_handling()
+	 * for more details
+	 */
+	spin_unlock_irqrestore(&emif_lock, irq_state);
+}
+
 static struct platform_driver emif_driver = {
 	.driver = {
 		.name = "emif",
diff --git a/drivers/misc/emif.h b/drivers/misc/emif.h
index 692b2a8..bfe08ba 100644
--- a/drivers/misc/emif.h
+++ b/drivers/misc/emif.h
@@ -19,6 +19,103 @@
  */
 #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
@@ -458,4 +555,35 @@
 #define READ_LATENCY_SHDW_SHIFT				0
 #define READ_LATENCY_SHDW_MASK				(0x1f << 0)
 
-#endif
+#ifndef __ASSEMBLY__
+/*
+ * Structure containing shadow of important registers in EMIF
+ * The calculation function fills in this structure to be later used for
+ * initialisation and DVFS
+ */
+struct emif_regs {
+	u32 freq;
+	u32 ref_ctrl_shdw;
+	u32 ref_ctrl_shdw_derated;
+	u32 sdram_tim1_shdw;
+	u32 sdram_tim1_shdw_derated;
+	u32 sdram_tim2_shdw;
+	u32 sdram_tim3_shdw;
+	u32 sdram_tim3_shdw_derated;
+	u32 pwr_mgmt_ctrl_shdw;
+	union {
+		u32 read_idle_ctrl_shdw_normal;
+		u32 dll_calib_ctrl_shdw_normal;
+	};
+	union {
+		u32 read_idle_ctrl_shdw_volt_ramp;
+		u32 dll_calib_ctrl_shdw_volt_ramp;
+	};
+
+	u32 phy_ctrl_1_shdw;
+	u32 ext_phy_ctrl_2_shdw;
+	u32 ext_phy_ctrl_3_shdw;
+	u32 ext_phy_ctrl_4_shdw;
+};
+#endif /* __ASSEMBLY__ */
+#endif /* __EMIF_H */
-- 
1.7.1


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

* [PATCH v4 4/7] misc: emif: handle frequency and voltage change events
@ 2012-03-16 21:51   ` Aneesh V
  0 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-03-16 21:51 UTC (permalink / raw)
  To: linux-arm-kernel

Change SDRAM timings and other settings as necessary
on voltage and frequency changes. We calculate these
register settings based on data from the device data
sheet and inputs such a frequency, voltage state(stable
or ramping), temperature level etc.

TODO: frequency and voltage change handling needs to
be integrated with clock framework and regulator
framework respectively. This is not done today
due to missing pieces in the kernel.

Cc: Greg KH <greg@kroah.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
---
v1:
- Added comment in commit log as well as code about
  missing integration part that needs to be done in
  future
- Removed some settings that were relevant only for
  DDR3
- Correction in temperature derated value of tim3
- Added errata i735 and i728  workarounds. As part of
  this we need to now maintain a list of all devices
  in the driver and iterate through them in some cases
- Improved synchronization. Added protection for newly
  identified cases of potential race conditions.
- Minor changes in patch organization. struct members
  needed by this patch now defined here.
---
 drivers/misc/emif.c |  894 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 drivers/misc/emif.h |  130 ++++++++-
 2 files changed, 1020 insertions(+), 4 deletions(-)

diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c
index f864640..1ca8165 100644
--- a/drivers/misc/emif.c
+++ b/drivers/misc/emif.c
@@ -21,6 +21,7 @@
 #include <linux/seq_file.h>
 #include <linux/module.h>
 #include <linux/list.h>
+#include <linux/spinlock.h>
 #include <misc/jedec_ddr.h>
 #include "emif.h"
 
@@ -37,20 +38,595 @@
  * @node:			node in the device list
  * @base:			base address of memory-mapped IO registers.
  * @dev:			device pointer.
+ * @addressing			table with addressing information from the spec
+ * @regs_cache:			An array of 'struct emif_regs' that stores
+ *				calculated register values for different
+ *				frequencies, to avoid re-calculating them on
+ *				each DVFS transition.
+ * @curr_regs:			The set of register values used in the last
+ *				frequency change (i.e. corresponding to the
+ *				frequency in effect at the moment)
  * @plat_data:			Pointer to saved platform data.
  */
 struct emif_data {
 	u8				duplicate;
 	u8				temperature_level;
+	u8				lpmode;
 	struct list_head		node;
+	unsigned long			irq_state;
 	void __iomem			*base;
 	struct device			*dev;
+	const struct lpddr2_addressing	*addressing;
+	struct emif_regs		*regs_cache[EMIF_MAX_NUM_FREQUENCIES];
+	struct emif_regs		*curr_regs;
 	struct emif_platform_data	*plat_data;
 };
 
 static struct emif_data *emif1;
+static spinlock_t	emif_lock;
+static unsigned long	irq_state;
+static u32		t_ck; /* DDR clock period in ps */
 static LIST_HEAD(device_list);
 
+/*
+ * Calculate the period of DDR clock from frequency value
+ */
+static void set_ddr_clk_period(u32 freq)
+{
+	/* Divide 10^12 by frequency to get period in ps */
+	t_ck = (u32)DIV_ROUND_UP_ULL(1000000000000ull, freq);
+}
+
+/*
+ * Get the CL from SDRAM_CONFIG register
+ */
+static u32 get_cl(struct emif_data *emif)
+{
+	u32		cl;
+	void __iomem	*base = emif->base;
+
+	cl = (readl(base + EMIF_SDRAM_CONFIG) & CL_MASK) >> CL_SHIFT;
+
+	return cl;
+}
+
+static void set_lpmode(struct emif_data *emif, u8 lpmode)
+{
+	u32 temp;
+	void __iomem *base = emif->base;
+
+	temp = readl(base + EMIF_POWER_MANAGEMENT_CONTROL);
+	temp &= ~LP_MODE_MASK;
+	temp |= (lpmode << LP_MODE_SHIFT);
+	writel(temp, base + EMIF_POWER_MANAGEMENT_CONTROL);
+}
+
+static void do_freq_update(void)
+{
+	struct emif_data *emif;
+
+	/*
+	 * Workaround for errata i728: Disable LPMODE during FREQ_UPDATE
+	 *
+	 * i728 DESCRIPTION:
+	 * The EMIF automatically puts the SDRAM into self-refresh mode
+	 * after the EMIF has not performed accesses during
+	 * EMIF_PWR_MGMT_CTRL[7:4] REG_SR_TIM number of DDR clock cycles
+	 * and the EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE bit field is set
+	 * to 0x2. If during a small window the following three events
+	 * occur:
+	 * - The SR_TIMING counter expires
+	 * - And frequency change is requested
+	 * - And OCP access is requested
+	 * Then it causes instable clock on the DDR interface.
+	 *
+	 * WORKAROUND
+	 * To avoid the occurrence of the three events, the workaround
+	 * is to disable the self-refresh when requesting a frequency
+	 * change. Before requesting a frequency change the software must
+	 * program EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x0. When the
+	 * frequency change has been done, the software can reprogram
+	 * EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE to 0x2
+	 */
+	list_for_each_entry(emif, &device_list, node) {
+		if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH)
+			set_lpmode(emif, EMIF_LP_MODE_DISABLE);
+	}
+
+	/*
+	 * TODO: Do FREQ_UPDATE here when an API
+	 * is available for this as part of the new
+	 * clock framework
+	 */
+
+	list_for_each_entry(emif, &device_list, node) {
+		if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH)
+			set_lpmode(emif, EMIF_LP_MODE_SELF_REFRESH);
+	}
+}
+
+/* Find addressing table entry based on the device's type and density */
+static const struct lpddr2_addressing *get_addressing_table(
+	const struct ddr_device_info *device_info)
+{
+	u32		index, type, density;
+
+	type = device_info->type;
+	density = device_info->density;
+
+	switch (type) {
+	case DDR_TYPE_LPDDR2_S4:
+		index = density - 1;
+		break;
+	case DDR_TYPE_LPDDR2_S2:
+		switch (density) {
+		case DDR_DENSITY_1Gb:
+		case DDR_DENSITY_2Gb:
+			index = density + 3;
+			break;
+		default:
+			index = density - 1;
+		}
+		break;
+	default:
+		return NULL;
+	}
+
+	return &lpddr2_jedec_addressing_table[index];
+}
+
+/*
+ * Find the the right timing table from the array of timing
+ * tables of the device using DDR clock frequency
+ */
+static const struct lpddr2_timings *get_timings_table(struct emif_data *emif,
+		u32 freq)
+{
+	u32				i, min, max, freq_nearest;
+	const struct lpddr2_timings	*timings = NULL;
+	const struct lpddr2_timings	*timings_arr = emif->plat_data->timings;
+	struct				device *dev = emif->dev;
+
+	/* Start with a very high frequency - 1GHz */
+	freq_nearest = 1000000000;
+
+	/*
+	 * Find the timings table such that:
+	 *  1. the frequency range covers the required frequency(safe) AND
+	 *  2. the max_freq is closest to the required frequency(optimal)
+	 */
+	for (i = 0; i < emif->plat_data->timings_arr_size; i++) {
+		max = timings_arr[i].max_freq;
+		min = timings_arr[i].min_freq;
+		if ((freq >= min) && (freq <= max) && (max < freq_nearest)) {
+			freq_nearest = max;
+			timings = &timings_arr[i];
+		}
+	}
+
+	if (!timings)
+		dev_err(dev, "%s: couldn't find timings for - %dHz\n",
+			__func__, freq);
+
+	dev_dbg(dev, "%s: timings table: freq %d, speed bin freq %d\n",
+		__func__, freq, freq_nearest);
+
+	return timings;
+}
+
+static u32 get_sdram_ref_ctrl_shdw(u32 freq,
+		const struct lpddr2_addressing *addressing)
+{
+	u32 ref_ctrl_shdw = 0, val = 0, freq_khz, t_refi;
+
+	/* Scale down frequency and t_refi to avoid overflow */
+	freq_khz = freq / 1000;
+	t_refi = addressing->tREFI_ns / 100;
+
+	/*
+	 * refresh rate to be set is 'tREFI(in us) * freq in MHz
+	 * division by 10000 to account for change in units
+	 */
+	val = t_refi * freq_khz / 10000;
+	ref_ctrl_shdw |= val << REFRESH_RATE_SHIFT;
+
+	return ref_ctrl_shdw;
+}
+
+static u32 get_sdram_tim_1_shdw(const struct lpddr2_timings *timings,
+		const struct lpddr2_min_tck *min_tck,
+		const struct lpddr2_addressing *addressing)
+{
+	u32 tim1 = 0, val = 0;
+
+	val = max(min_tck->tWTR, DIV_ROUND_UP(timings->tWTR, t_ck)) - 1;
+	tim1 |= val << T_WTR_SHIFT;
+
+	if (addressing->num_banks == B8)
+		val = DIV_ROUND_UP(timings->tFAW, t_ck*4);
+	else
+		val = max(min_tck->tRRD, DIV_ROUND_UP(timings->tRRD, t_ck));
+	tim1 |= (val - 1) << T_RRD_SHIFT;
+
+	val = DIV_ROUND_UP(timings->tRAS_min + timings->tRPab, t_ck) - 1;
+	tim1 |= val << T_RC_SHIFT;
+
+	val = max(min_tck->tRASmin, DIV_ROUND_UP(timings->tRAS_min, t_ck));
+	tim1 |= (val - 1) << T_RAS_SHIFT;
+
+	val = max(min_tck->tWR, DIV_ROUND_UP(timings->tWR, t_ck)) - 1;
+	tim1 |= val << T_WR_SHIFT;
+
+	val = max(min_tck->tRCD, DIV_ROUND_UP(timings->tRCD, t_ck)) - 1;
+	tim1 |= val << T_RCD_SHIFT;
+
+	val = max(min_tck->tRPab, DIV_ROUND_UP(timings->tRPab, t_ck)) - 1;
+	tim1 |= val << T_RP_SHIFT;
+
+	return tim1;
+}
+
+static u32 get_sdram_tim_1_shdw_derated(const struct lpddr2_timings *timings,
+		const struct lpddr2_min_tck *min_tck,
+		const struct lpddr2_addressing *addressing)
+{
+	u32 tim1 = 0, val = 0;
+
+	val = max(min_tck->tWTR, DIV_ROUND_UP(timings->tWTR, t_ck)) - 1;
+	tim1 = val << T_WTR_SHIFT;
+
+	/*
+	 * tFAW is approximately 4 times tRRD. So add 1875*4 = 7500ps
+	 * to tFAW for de-rating
+	 */
+	if (addressing->num_banks == B8) {
+		val = DIV_ROUND_UP(timings->tFAW + 7500, 4 * t_ck) - 1;
+	} else {
+		val = DIV_ROUND_UP(timings->tRRD + 1875, t_ck);
+		val = max(min_tck->tRRD, val) - 1;
+	}
+	tim1 |= val << T_RRD_SHIFT;
+
+	val = DIV_ROUND_UP(timings->tRAS_min + timings->tRPab + 1875, t_ck);
+	tim1 |= (val - 1) << T_RC_SHIFT;
+
+	val = DIV_ROUND_UP(timings->tRAS_min + 1875, t_ck);
+	val = max(min_tck->tRASmin, val) - 1;
+	tim1 |= val << T_RAS_SHIFT;
+
+	val = max(min_tck->tWR, DIV_ROUND_UP(timings->tWR, t_ck)) - 1;
+	tim1 |= val << T_WR_SHIFT;
+
+	val = max(min_tck->tRCD, DIV_ROUND_UP(timings->tRCD + 1875, t_ck));
+	tim1 |= (val - 1) << T_RCD_SHIFT;
+
+	val = max(min_tck->tRPab, DIV_ROUND_UP(timings->tRPab + 1875, t_ck));
+	tim1 |= (val - 1) << T_RP_SHIFT;
+
+	return tim1;
+}
+
+static u32 get_sdram_tim_2_shdw(const struct lpddr2_timings *timings,
+		const struct lpddr2_min_tck *min_tck,
+		const struct lpddr2_addressing *addressing,
+		u32 type)
+{
+	u32 tim2 = 0, val = 0;
+
+	val = min_tck->tCKE - 1;
+	tim2 |= val << T_CKE_SHIFT;
+
+	val = max(min_tck->tRTP, DIV_ROUND_UP(timings->tRTP, t_ck)) - 1;
+	tim2 |= val << T_RTP_SHIFT;
+
+	/* tXSNR = tRFCab_ps + 10 ns(tRFCab_ps for LPDDR2). */
+	val = DIV_ROUND_UP(addressing->tRFCab_ps + 10000, t_ck) - 1;
+	tim2 |= val << T_XSNR_SHIFT;
+
+	/* XSRD same as XSNR for LPDDR2 */
+	tim2 |= val << T_XSRD_SHIFT;
+
+	val = max(min_tck->tXP, DIV_ROUND_UP(timings->tXP, t_ck)) - 1;
+	tim2 |= val << T_XP_SHIFT;
+
+	return tim2;
+}
+
+static u32 get_sdram_tim_3_shdw(const struct lpddr2_timings *timings,
+		const struct lpddr2_min_tck *min_tck,
+		const struct lpddr2_addressing *addressing,
+		u32 type, u32 ip_rev, u32 derated)
+{
+	u32 tim3 = 0, val = 0, t_dqsck;
+
+	val = timings->tRAS_max_ns / addressing->tREFI_ns - 1;
+	val = val > 0xF ? 0xF : val;
+	tim3 |= val << T_RAS_MAX_SHIFT;
+
+	val = DIV_ROUND_UP(addressing->tRFCab_ps, t_ck) - 1;
+	tim3 |= val << T_RFC_SHIFT;
+
+	t_dqsck = (derated == EMIF_DERATED_TIMINGS) ?
+		timings->tDQSCK_max_derated : timings->tDQSCK_max;
+	if (ip_rev == EMIF_4D5)
+		val = DIV_ROUND_UP(t_dqsck + 1000, t_ck) - 1;
+	else
+		val = DIV_ROUND_UP(t_dqsck, t_ck) - 1;
+
+	tim3 |= val << T_TDQSCKMAX_SHIFT;
+
+	val = DIV_ROUND_UP(timings->tZQCS, t_ck) - 1;
+	tim3 |= val << ZQ_ZQCS_SHIFT;
+
+	val = DIV_ROUND_UP(timings->tCKESR, t_ck);
+	val = max(min_tck->tCKESR, val) - 1;
+	tim3 |= val << T_CKESR_SHIFT;
+
+	if (ip_rev == EMIF_4D5) {
+		tim3 |= (EMIF_T_CSTA - 1) << T_CSTA_SHIFT;
+
+		val = DIV_ROUND_UP(EMIF_T_PDLL_UL, 128) - 1;
+		tim3 |= val << T_PDLL_UL_SHIFT;
+	}
+
+	return tim3;
+}
+
+static u32 get_read_idle_ctrl_shdw(u8 volt_ramp)
+{
+	u32 idle = 0, val = 0;
+
+	/*
+	 * Maximum value in normal conditions and increased frequency
+	 * when voltage is ramping
+	 */
+	if (volt_ramp)
+		val = READ_IDLE_INTERVAL_DVFS / t_ck / 64 - 1;
+	else
+		val = 0x1FF;
+
+	/*
+	 * READ_IDLE_CTRL register in EMIF4D has same offset and fields
+	 * as DLL_CALIB_CTRL in EMIF4D5, so use the same shifts
+	 */
+	idle |= val << DLL_CALIB_INTERVAL_SHIFT;
+	idle |= EMIF_READ_IDLE_LEN_VAL << ACK_WAIT_SHIFT;
+
+	return idle;
+}
+
+static u32 get_dll_calib_ctrl_shdw(u8 volt_ramp)
+{
+	u32 calib = 0, val = 0;
+
+	if (volt_ramp == DDR_VOLTAGE_RAMPING)
+		val = DLL_CALIB_INTERVAL_DVFS / t_ck / 16 - 1;
+	else
+		val = 0; /* Disabled when voltage is stable */
+
+	calib |= val << DLL_CALIB_INTERVAL_SHIFT;
+	calib |= DLL_CALIB_ACK_WAIT_VAL << ACK_WAIT_SHIFT;
+
+	return calib;
+}
+
+static u32 get_ddr_phy_ctrl_1_attilaphy_4d(const struct lpddr2_timings *timings,
+	u32 freq, u8 RL)
+{
+	u32 phy = EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY, val = 0;
+
+	val = RL + DIV_ROUND_UP(timings->tDQSCK_max, t_ck) - 1;
+	phy |= val << READ_LATENCY_SHIFT_4D;
+
+	if (freq <= 100000000)
+		val = EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY;
+	else if (freq <= 200000000)
+		val = EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY;
+	else
+		val = EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY;
+
+	phy |= val << DLL_SLAVE_DLY_CTRL_SHIFT_4D;
+
+	return phy;
+}
+
+static u32 get_phy_ctrl_1_intelliphy_4d5(u32 freq, u8 cl)
+{
+	u32 phy = EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY, half_delay;
+
+	/*
+	 * DLL operates@266 MHz. If DDR frequency is near 266 MHz,
+	 * half-delay is not needed else set half-delay
+	 */
+	if (freq >= 265000000 && freq < 267000000)
+		half_delay = 0;
+	else
+		half_delay = 1;
+
+	phy |= half_delay << DLL_HALF_DELAY_SHIFT_4D5;
+	phy |= ((cl + DIV_ROUND_UP(EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS,
+			t_ck) - 1) << READ_LATENCY_SHIFT_4D5);
+
+	return phy;
+}
+
+static u32 get_ext_phy_ctrl_2_intelliphy_4d5(void)
+{
+	u32 fifo_we_slave_ratio;
+
+	fifo_we_slave_ratio =  DIV_ROUND_CLOSEST(
+		EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256 , t_ck);
+
+	return fifo_we_slave_ratio | fifo_we_slave_ratio << 11 |
+		fifo_we_slave_ratio << 22;
+}
+
+static u32 get_ext_phy_ctrl_3_intelliphy_4d5(void)
+{
+	u32 fifo_we_slave_ratio;
+
+	fifo_we_slave_ratio =  DIV_ROUND_CLOSEST(
+		EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256 , t_ck);
+
+	return fifo_we_slave_ratio >> 10 | fifo_we_slave_ratio << 1 |
+		fifo_we_slave_ratio << 12 | fifo_we_slave_ratio << 23;
+}
+
+static u32 get_ext_phy_ctrl_4_intelliphy_4d5(void)
+{
+	u32 fifo_we_slave_ratio;
+
+	fifo_we_slave_ratio =  DIV_ROUND_CLOSEST(
+		EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS * 256 , t_ck);
+
+	return fifo_we_slave_ratio >> 9 | fifo_we_slave_ratio << 2 |
+		fifo_we_slave_ratio << 13;
+}
+
+static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev)
+{
+	u32 pwr_mgmt_ctrl	= 0, timeout;
+	u32 lpmode		= EMIF_LP_MODE_SELF_REFRESH;
+	u32 timeout_perf	= EMIF_LP_MODE_TIMEOUT_PERFORMANCE;
+	u32 timeout_pwr		= EMIF_LP_MODE_TIMEOUT_POWER;
+	u32 freq_threshold	= EMIF_LP_MODE_FREQ_THRESHOLD;
+
+	struct emif_custom_configs *cust_cfgs = emif->plat_data->custom_configs;
+
+	if (cust_cfgs && (cust_cfgs->mask & EMIF_CUSTOM_CONFIG_LPMODE)) {
+		lpmode		= cust_cfgs->lpmode;
+		timeout_perf	= cust_cfgs->lpmode_timeout_performance;
+		timeout_pwr	= cust_cfgs->lpmode_timeout_power;
+		freq_threshold  = cust_cfgs->lpmode_freq_threshold;
+	}
+
+	/* Timeout based on DDR frequency */
+	timeout = freq >= freq_threshold ? timeout_perf : timeout_pwr;
+
+	/* The value to be set in register is "log2(timeout) - 3" */
+	if (timeout < 16) {
+		timeout = 0;
+	} else {
+		timeout = __fls(timeout) - 3;
+		if (timeout & (timeout - 1))
+			timeout++;
+	}
+
+	switch (lpmode) {
+	case EMIF_LP_MODE_CLOCK_STOP:
+		pwr_mgmt_ctrl = (timeout << CS_TIM_SHIFT) |
+					SR_TIM_MASK | PD_TIM_MASK;
+		break;
+	case EMIF_LP_MODE_SELF_REFRESH:
+		/* Workaround for errata i735 */
+		if (timeout < 6)
+			timeout = 6;
+
+		pwr_mgmt_ctrl = (timeout << SR_TIM_SHIFT) |
+					CS_TIM_MASK | PD_TIM_MASK;
+		break;
+	case EMIF_LP_MODE_PWR_DN:
+		pwr_mgmt_ctrl = (timeout << PD_TIM_SHIFT) |
+					CS_TIM_MASK | SR_TIM_MASK;
+		break;
+	case EMIF_LP_MODE_DISABLE:
+	default:
+		pwr_mgmt_ctrl = CS_TIM_MASK |
+					PD_TIM_MASK | SR_TIM_MASK;
+	}
+
+	/* No CS_TIM in EMIF_4D5 */
+	if (ip_rev == EMIF_4D5)
+		pwr_mgmt_ctrl &= ~CS_TIM_MASK;
+
+	pwr_mgmt_ctrl |= lpmode << LP_MODE_SHIFT;
+
+	return pwr_mgmt_ctrl;
+}
+
+/*
+ * Program EMIF shadow registers that are not dependent on temperature
+ * or voltage
+ */
+static void setup_registers(struct emif_data *emif, struct emif_regs *regs)
+{
+	void __iomem	*base = emif->base;
+
+	writel(regs->sdram_tim2_shdw, base + EMIF_SDRAM_TIMING_2_SHDW);
+	writel(regs->phy_ctrl_1_shdw, base + EMIF_DDR_PHY_CTRL_1_SHDW);
+
+	/* Settings specific for EMIF4D5 */
+	if (emif->plat_data->ip_rev != EMIF_4D5)
+		return;
+	writel(regs->ext_phy_ctrl_2_shdw, base + EMIF_EXT_PHY_CTRL_2_SHDW);
+	writel(regs->ext_phy_ctrl_3_shdw, base + EMIF_EXT_PHY_CTRL_3_SHDW);
+	writel(regs->ext_phy_ctrl_4_shdw, base + EMIF_EXT_PHY_CTRL_4_SHDW);
+}
+
+/*
+ * When voltage ramps dll calibration and forced read idle should
+ * happen more often
+ */
+static void setup_volt_sensitive_regs(struct emif_data *emif,
+		struct emif_regs *regs, u32 volt_state)
+{
+	u32		calib_ctrl;
+	void __iomem	*base = emif->base;
+
+	/*
+	 * EMIF_READ_IDLE_CTRL in EMIF4D refers to the same register as
+	 * EMIF_DLL_CALIB_CTRL in EMIF4D5 and dll_calib_ctrl_shadow_*
+	 * is an alias of the respective read_idle_ctrl_shdw_* (members of
+	 * a union). So, the below code takes care of both cases
+	 */
+	if (volt_state == DDR_VOLTAGE_RAMPING)
+		calib_ctrl = regs->dll_calib_ctrl_shdw_volt_ramp;
+	else
+		calib_ctrl = regs->dll_calib_ctrl_shdw_normal;
+
+	writel(calib_ctrl, base + EMIF_DLL_CALIB_CTRL_SHDW);
+}
+
+/*
+ * setup_temperature_sensitive_regs() - set the timings for temperature
+ * sensitive registers. This happens once at initialisation time based
+ * on the temperature at boot time and subsequently based on the temperature
+ * alert interrupt. Temperature alert can happen when the temperature
+ * increases or drops. So this function can have the effect of either
+ * derating the timings or going back to nominal values.
+ */
+static void setup_temperature_sensitive_regs(struct emif_data *emif,
+		struct emif_regs *regs)
+{
+	u32		tim1, tim3, ref_ctrl, type;
+	void __iomem	*base = emif->base;
+	u32		temperature;
+
+	type = emif->plat_data->device_info->type;
+
+	tim1 = regs->sdram_tim1_shdw;
+	tim3 = regs->sdram_tim3_shdw;
+	ref_ctrl = regs->ref_ctrl_shdw;
+
+	/* No de-rating for non-lpddr2 devices */
+	if (type != DDR_TYPE_LPDDR2_S2 && type != DDR_TYPE_LPDDR2_S4)
+		goto out;
+
+	temperature = emif->temperature_level;
+	if (temperature == SDRAM_TEMP_HIGH_DERATE_REFRESH) {
+		ref_ctrl = regs->ref_ctrl_shdw_derated;
+	} else if (temperature == SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS) {
+		tim1 = regs->sdram_tim1_shdw_derated;
+		tim3 = regs->sdram_tim3_shdw_derated;
+		ref_ctrl = regs->ref_ctrl_shdw_derated;
+	}
+
+out:
+	writel(tim1, base + EMIF_SDRAM_TIMING_1_SHDW);
+	writel(tim3, base + EMIF_SDRAM_TIMING_3_SHDW);
+	writel(ref_ctrl, base + EMIF_SDRAM_REFRESH_CTRL_SHDW);
+}
+
 static void get_default_timings(struct emif_data *emif)
 {
 	struct emif_platform_data *pd = emif->plat_data;
@@ -234,10 +810,8 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
 		goto error;
 	}
 
-	if (!emif1)
-		emif1 = emif;
-
 	list_add(&emif->node, &device_list);
+	emif->addressing = get_addressing_table(emif->plat_data->device_info);
 
 	/* Save pointers to each other in emif and device structures */
 	emif->dev = &pdev->dev;
@@ -257,6 +831,18 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
 		goto error;
 	}
 
+	/* One-time actions taken on probing the first device */
+	if (!emif1) {
+		emif1 = emif;
+		spin_lock_init(&emif_lock);
+
+		/*
+		 * TODO: register notifiers for frequency and voltage
+		 * change here once the respective frameworks are
+		 * available
+		 */
+	}
+
 	dev_info(&pdev->dev, "%s: device configured with addr = %p\n",
 		__func__, emif->base);
 
@@ -265,6 +851,308 @@ error:
 	return -ENODEV;
 }
 
+static int get_emif_reg_values(struct emif_data *emif, u32 freq,
+		struct emif_regs *regs)
+{
+	u32				cs1_used, ip_rev, phy_type;
+	u32				cl, type;
+	const struct lpddr2_timings	*timings;
+	const struct lpddr2_min_tck	*min_tck;
+	const struct ddr_device_info	*device_info;
+	const struct lpddr2_addressing	*addressing;
+	struct emif_data		*emif_for_calc;
+	struct device			*dev;
+	const struct emif_custom_configs *custom_configs;
+
+	dev = emif->dev;
+	/*
+	 * If the devices on this EMIF instance is duplicate of EMIF1,
+	 * use EMIF1 details for the calculation
+	 */
+	emif_for_calc	= emif->duplicate ? emif1 : emif;
+	timings		= get_timings_table(emif_for_calc, freq);
+	addressing	= emif_for_calc->addressing;
+	if (!timings || !addressing) {
+		dev_err(dev, "%s: not enough data available for %dHz",
+			__func__, freq);
+		return -1;
+	}
+
+	device_info	= emif_for_calc->plat_data->device_info;
+	type		= device_info->type;
+	cs1_used	= device_info->cs1_used;
+	ip_rev		= emif_for_calc->plat_data->ip_rev;
+	phy_type	= emif_for_calc->plat_data->phy_type;
+
+	min_tck		= emif_for_calc->plat_data->min_tck;
+	custom_configs	= emif_for_calc->plat_data->custom_configs;
+
+	set_ddr_clk_period(freq);
+
+	regs->ref_ctrl_shdw = get_sdram_ref_ctrl_shdw(freq, addressing);
+	regs->sdram_tim1_shdw = get_sdram_tim_1_shdw(timings, min_tck,
+			addressing);
+	regs->sdram_tim2_shdw = get_sdram_tim_2_shdw(timings, min_tck,
+			addressing, type);
+	regs->sdram_tim3_shdw = get_sdram_tim_3_shdw(timings, min_tck,
+		addressing, type, ip_rev, EMIF_NORMAL_TIMINGS);
+
+	cl = get_cl(emif);
+
+	if (phy_type == EMIF_PHY_TYPE_ATTILAPHY && ip_rev == EMIF_4D) {
+		regs->phy_ctrl_1_shdw = get_ddr_phy_ctrl_1_attilaphy_4d(
+			timings, freq, cl);
+	} else if (phy_type == EMIF_PHY_TYPE_INTELLIPHY && ip_rev == EMIF_4D5) {
+		regs->phy_ctrl_1_shdw = get_phy_ctrl_1_intelliphy_4d5(freq, cl);
+		regs->ext_phy_ctrl_2_shdw = get_ext_phy_ctrl_2_intelliphy_4d5();
+		regs->ext_phy_ctrl_3_shdw = get_ext_phy_ctrl_3_intelliphy_4d5();
+		regs->ext_phy_ctrl_4_shdw = get_ext_phy_ctrl_4_intelliphy_4d5();
+	} else {
+		return -1;
+	}
+
+	/* Only timeout values in pwr_mgmt_ctrl_shdw register */
+	regs->pwr_mgmt_ctrl_shdw =
+		get_pwr_mgmt_ctrl(freq, emif_for_calc, ip_rev) &
+		(CS_TIM_MASK | SR_TIM_MASK | PD_TIM_MASK);
+
+	if (ip_rev & EMIF_4D) {
+		regs->read_idle_ctrl_shdw_normal =
+			get_read_idle_ctrl_shdw(DDR_VOLTAGE_STABLE);
+
+		regs->read_idle_ctrl_shdw_volt_ramp =
+			get_read_idle_ctrl_shdw(DDR_VOLTAGE_RAMPING);
+	} else if (ip_rev & EMIF_4D5) {
+		regs->dll_calib_ctrl_shdw_normal =
+			get_dll_calib_ctrl_shdw(DDR_VOLTAGE_STABLE);
+
+		regs->dll_calib_ctrl_shdw_volt_ramp =
+			get_dll_calib_ctrl_shdw(DDR_VOLTAGE_RAMPING);
+	}
+
+	if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) {
+		regs->ref_ctrl_shdw_derated = get_sdram_ref_ctrl_shdw(freq / 4,
+			addressing);
+
+		regs->sdram_tim1_shdw_derated =
+			get_sdram_tim_1_shdw_derated(timings, min_tck,
+				addressing);
+
+		regs->sdram_tim3_shdw_derated = get_sdram_tim_3_shdw(timings,
+			min_tck, addressing, type, ip_rev,
+			EMIF_DERATED_TIMINGS);
+	}
+
+	regs->freq = freq;
+
+	return 0;
+}
+
+/*
+ * get_regs() - gets the cached emif_regs structure for a given EMIF instance
+ * given frequency(freq):
+ *
+ * As an optimisation, every EMIF instance other than EMIF1 shares the
+ * register cache with EMIF1 if the devices connected on this instance
+ * are same as that on EMIF1(indicated by the duplicate flag)
+ *
+ * If we do not have an entry corresponding to the frequency given, we
+ * allocate a new entry and calculate the values
+ *
+ * Upon finding the right reg dump, save it in curr_regs. It can be
+ * directly used for thermal de-rating and voltage ramping changes.
+ */
+static struct emif_regs *get_regs(struct emif_data *emif, u32 freq)
+{
+	int			i;
+	struct emif_regs	**regs_cache;
+	struct emif_regs	*regs = NULL;
+	struct device		*dev;
+
+	dev = emif->dev;
+	if (emif->curr_regs && emif->curr_regs->freq == freq) {
+		dev_dbg(dev, "%s: using curr_regs - %u Hz", __func__, freq);
+		return emif->curr_regs;
+	}
+
+	if (emif->duplicate)
+		regs_cache = emif1->regs_cache;
+	else
+		regs_cache = emif->regs_cache;
+
+	for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++) {
+		if (regs_cache[i]->freq == freq) {
+			regs = regs_cache[i];
+			dev_dbg(dev,
+				"%s: reg dump found in reg cache for %u Hz\n",
+				__func__, freq);
+			break;
+		}
+	}
+
+	/*
+	 * If we don't have an entry for this frequency in the cache create one
+	 * and calculate the values
+	 */
+	if (!regs) {
+		regs = devm_kzalloc(emif->dev, sizeof(*regs), GFP_ATOMIC);
+		if (!regs)
+			return NULL;
+
+		if (get_emif_reg_values(emif, freq, regs)) {
+			devm_kfree(emif->dev, regs);
+			return NULL;
+		}
+
+		/*
+		 * Now look for an un-used entry in the cache and save the
+		 * newly created struct. If there are no free entries
+		 * over-write the last entry
+		 */
+		for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++)
+			;
+
+		if (i >= EMIF_MAX_NUM_FREQUENCIES) {
+			dev_warn(dev, "%s: regs_cache full - reusing a slot!!\n",
+				__func__);
+			i = EMIF_MAX_NUM_FREQUENCIES - 1;
+			devm_kfree(emif->dev, regs_cache[i]);
+		}
+		regs_cache[i] = regs;
+	}
+
+	return regs;
+}
+
+static void do_volt_notify_handling(struct emif_data *emif, u32 volt_state)
+{
+	dev_dbg(emif->dev, "%s: voltage notification : %d", __func__,
+		volt_state);
+
+	if (!emif->curr_regs) {
+		dev_err(emif->dev,
+			"%s: volt-notify before registers are ready: %d\n",
+			__func__, volt_state);
+		return;
+	}
+
+	setup_volt_sensitive_regs(emif, emif->curr_regs, volt_state);
+}
+
+/*
+ * TODO: voltage notify handling should be hooked up to
+ * regulator framework as soon as the necessary support
+ * is available in mainline kernel. This function is un-used
+ * right now.
+ */
+static void __attribute__((unused)) volt_notify_handling(u32 volt_state)
+{
+	struct emif_data *emif;
+
+	spin_lock_irqsave(&emif_lock, irq_state);
+
+	list_for_each_entry(emif, &device_list, node)
+		do_volt_notify_handling(emif, volt_state);
+	do_freq_update();
+
+	spin_unlock_irqrestore(&emif_lock, irq_state);
+}
+
+static void do_freq_pre_notify_handling(struct emif_data *emif, u32 new_freq)
+{
+	struct emif_regs *regs;
+
+	regs = get_regs(emif, new_freq);
+	if (!regs)
+		return;
+
+	emif->curr_regs = regs;
+
+	/*
+	 * Update the shadow registers:
+	 * Temperature and voltage-ramp sensitive settings are also configured
+	 * in terms of DDR cycles. So, we need to update them too when there
+	 * is a freq change
+	 */
+	dev_dbg(emif->dev, "%s: setting up shadow registers for %uHz",
+		__func__, new_freq);
+	setup_registers(emif, regs);
+	setup_temperature_sensitive_regs(emif, regs);
+	setup_volt_sensitive_regs(emif, regs, DDR_VOLTAGE_STABLE);
+
+	/*
+	 * Part of workaround for errata i728. See do_freq_update()
+	 * for more details
+	 */
+	if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH)
+		set_lpmode(emif, EMIF_LP_MODE_DISABLE);
+}
+
+/*
+ * TODO: frequency notify handling should be hooked up to
+ * clock framework as soon as the necessary support is
+ * available in mainline kernel. This function is un-used
+ * right now.
+ */
+static void __attribute__((unused)) freq_pre_notify_handling(u32 new_freq)
+{
+	struct emif_data *emif;
+
+	/*
+	 * NOTE: we are taking the spin-lock here and releases it
+	 * only in post-notifier. This doesn't look good and
+	 * Sparse complains about it, but this seems to be
+	 * un-avoidable. We need to lock a sequence of events
+	 * that is split between EMIF and clock framework.
+	 *
+	 * 1. EMIF driver updates EMIF timings in shadow registers in the
+	 *    frequency pre-notify callback from clock framework
+	 * 2. clock framework sets up the registers for the new frequency
+	 * 3. clock framework initiates a hw-sequence that updates
+	 *    the frequency EMIF timings synchronously.
+	 *
+	 * All these 3 steps should be performed as an atomic operation
+	 * vis-a-vis similar sequence in the EMIF interrupt handler
+	 * for temperature events. Otherwise, there could be race
+	 * conditions that could result in incorrect EMIF timings for
+	 * a given frequency
+	 */
+	spin_lock_irqsave(&emif_lock, irq_state);
+
+	list_for_each_entry(emif, &device_list, node)
+		do_freq_pre_notify_handling(emif, new_freq);
+}
+
+static void do_freq_post_notify_handling(struct emif_data *emif)
+{
+	/*
+	 * Part of workaround for errata i728. See do_freq_update()
+	 * for more details
+	 */
+	if (emif->lpmode == EMIF_LP_MODE_SELF_REFRESH)
+		set_lpmode(emif, EMIF_LP_MODE_SELF_REFRESH);
+}
+
+/*
+ * TODO: frequency notify handling should be hooked up to
+ * clock framework as soon as the necessary support is
+ * available in mainline kernel. This function is un-used
+ * right now.
+ */
+static void __attribute__((unused)) freq_post_notify_handling(void)
+{
+	struct emif_data *emif;
+
+	list_for_each_entry(emif, &device_list, node)
+		do_freq_post_notify_handling(emif);
+
+	/*
+	 * Lock is done in pre-notify handler. See freq_pre_notify_handling()
+	 * for more details
+	 */
+	spin_unlock_irqrestore(&emif_lock, irq_state);
+}
+
 static struct platform_driver emif_driver = {
 	.driver = {
 		.name = "emif",
diff --git a/drivers/misc/emif.h b/drivers/misc/emif.h
index 692b2a8..bfe08ba 100644
--- a/drivers/misc/emif.h
+++ b/drivers/misc/emif.h
@@ -19,6 +19,103 @@
  */
 #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
@@ -458,4 +555,35 @@
 #define READ_LATENCY_SHDW_SHIFT				0
 #define READ_LATENCY_SHDW_MASK				(0x1f << 0)
 
-#endif
+#ifndef __ASSEMBLY__
+/*
+ * Structure containing shadow of important registers in EMIF
+ * The calculation function fills in this structure to be later used for
+ * initialisation and DVFS
+ */
+struct emif_regs {
+	u32 freq;
+	u32 ref_ctrl_shdw;
+	u32 ref_ctrl_shdw_derated;
+	u32 sdram_tim1_shdw;
+	u32 sdram_tim1_shdw_derated;
+	u32 sdram_tim2_shdw;
+	u32 sdram_tim3_shdw;
+	u32 sdram_tim3_shdw_derated;
+	u32 pwr_mgmt_ctrl_shdw;
+	union {
+		u32 read_idle_ctrl_shdw_normal;
+		u32 dll_calib_ctrl_shdw_normal;
+	};
+	union {
+		u32 read_idle_ctrl_shdw_volt_ramp;
+		u32 dll_calib_ctrl_shdw_volt_ramp;
+	};
+
+	u32 phy_ctrl_1_shdw;
+	u32 ext_phy_ctrl_2_shdw;
+	u32 ext_phy_ctrl_3_shdw;
+	u32 ext_phy_ctrl_4_shdw;
+};
+#endif /* __ASSEMBLY__ */
+#endif /* __EMIF_H */
-- 
1.7.1

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

* [PATCH v4 5/7] misc: emif: add interrupt and temperature handling
  2012-03-16 21:51 ` Aneesh V
@ 2012-03-16 21:51   ` Aneesh V
  -1 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-03-16 21:51 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-arm-kernel, linux-omap, Aneesh V, Greg KH

Add an ISR for EMIF that:
	1. reports details of access errors
	2. takes action on thermal events

Also clear all interrupts on shut-down. Pending IRQs
may casue problems during warm-reset.

Temperature handling:
EMIF can be configured to poll the temperature level
of an LPDDR2 device from the MR4 mode register in the
device. EMIF generates an interrupt whenever it identifies
a temperature level change between two consecutive pollings.

Some of the timing parameters need to be de-rated at high
temperatures. The interrupt handler takes care of doing
this and also takes care of going back to nominal settings
when temperature falls back to nominal levels.

Cc: Greg KH <greg@kroah.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
---

v2:
- replaced __init with __init_or_module

v1:
- Improved commit log
- Improved synchronization with thread context
---
 drivers/misc/emif.c |  211 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 209 insertions(+), 2 deletions(-)

diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c
index 1ca8165..52048f4 100644
--- a/drivers/misc/emif.c
+++ b/drivers/misc/emif.c
@@ -545,6 +545,42 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev)
 }
 
 /*
+ * Get the temperature level of the EMIF instance:
+ * Reads the MR4 register of attached SDRAM parts to find out the temperature
+ * level. If there are two parts attached(one on each CS), then the temperature
+ * level for the EMIF instance is the higher of the two temperatures.
+ */
+static void get_temperature_level(struct emif_data *emif)
+{
+	u32		temp, temperature_level;
+	void __iomem	*base;
+
+	base = emif->base;
+
+	/* Read mode register 4 */
+	writel(DDR_MR4, base + EMIF_LPDDR2_MODE_REG_CONFIG);
+	temperature_level = readl(base + EMIF_LPDDR2_MODE_REG_DATA);
+	temperature_level = (temperature_level & MR4_SDRAM_REF_RATE_MASK) >>
+				MR4_SDRAM_REF_RATE_SHIFT;
+
+	if (emif->plat_data->device_info->cs1_used) {
+		writel(DDR_MR4 | CS_MASK, base + EMIF_LPDDR2_MODE_REG_CONFIG);
+		temp = readl(base + EMIF_LPDDR2_MODE_REG_DATA);
+		temp = (temp & MR4_SDRAM_REF_RATE_MASK)
+				>> MR4_SDRAM_REF_RATE_SHIFT;
+		temperature_level = max(temp, temperature_level);
+	}
+
+	/* treat everything less than nominal(3) in MR4 as nominal */
+	if (unlikely(temperature_level < SDRAM_TEMP_NOMINAL))
+		temperature_level = SDRAM_TEMP_NOMINAL;
+
+	/* if we get reserved value in MR4 persist with the existing value */
+	if (likely(temperature_level != SDRAM_TEMP_RESERVED_4))
+		emif->temperature_level = temperature_level;
+}
+
+/*
  * Program EMIF shadow registers that are not dependent on temperature
  * or voltage
  */
@@ -627,6 +663,158 @@ out:
 	writel(ref_ctrl, base + EMIF_SDRAM_REFRESH_CTRL_SHDW);
 }
 
+static irqreturn_t handle_temp_alert(void __iomem *base, struct emif_data *emif)
+{
+	u32		old_temp_level;
+	irqreturn_t	ret = IRQ_HANDLED;
+
+	spin_lock_irqsave(&emif_lock, irq_state);
+	old_temp_level = emif->temperature_level;
+	get_temperature_level(emif);
+
+	if (unlikely(emif->temperature_level == old_temp_level)) {
+		goto out;
+	} else if (!emif->curr_regs) {
+		dev_err(emif->dev, "temperature alert before registers are calculated, not de-rating timings\n");
+		goto out;
+	}
+
+	if (emif->temperature_level < old_temp_level ||
+		emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) {
+		/*
+		 * Temperature coming down - defer handling to thread OR
+		 * Temperature far too high - do kernel_power_off() from
+		 * thread context
+		 */
+		ret = IRQ_WAKE_THREAD;
+	} else {
+		/* Temperature is going up - handle immediately */
+		setup_temperature_sensitive_regs(emif, emif->curr_regs);
+		do_freq_update();
+	}
+
+out:
+	spin_unlock_irqrestore(&emif_lock, irq_state);
+	return ret;
+}
+
+static irqreturn_t emif_interrupt_handler(int irq, void *dev_id)
+{
+	u32			interrupts;
+	struct emif_data	*emif = dev_id;
+	void __iomem		*base = emif->base;
+	struct device		*dev = emif->dev;
+	irqreturn_t		ret = IRQ_HANDLED;
+
+	/* Save the status and clear it */
+	interrupts = readl(base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS);
+	writel(interrupts, base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS);
+
+	/*
+	 * Handle temperature alert
+	 * Temperature alert should be same for all ports
+	 * So, it's enough to process it only for one of the ports
+	 */
+	if (interrupts & TA_SYS_MASK)
+		ret = handle_temp_alert(base, emif);
+
+	if (interrupts & ERR_SYS_MASK)
+		dev_err(dev, "Access error from SYS port - %x\n", interrupts);
+
+	if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE) {
+		/* Save the status and clear it */
+		interrupts = readl(base + EMIF_LL_OCP_INTERRUPT_STATUS);
+		writel(interrupts, base + EMIF_LL_OCP_INTERRUPT_STATUS);
+
+		if (interrupts & ERR_LL_MASK)
+			dev_err(dev, "Access error from LL port - %x\n",
+				interrupts);
+	}
+
+	return ret;
+}
+
+static irqreturn_t emif_threaded_isr(int irq, void *dev_id)
+{
+	struct emif_data	*emif = dev_id;
+
+	if (emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) {
+		dev_emerg(emif->dev, "SDRAM temperature exceeds operating limit.. Needs shut down!!!\n");
+		kernel_power_off();
+		return IRQ_HANDLED;
+	}
+
+	spin_lock_irqsave(&emif_lock, irq_state);
+
+	if (emif->curr_regs) {
+		setup_temperature_sensitive_regs(emif, emif->curr_regs);
+		do_freq_update();
+	} else {
+		dev_err(emif->dev, "temperature alert before registers are calculated, not de-rating timings\n");
+	}
+
+	spin_unlock_irqrestore(&emif_lock, irq_state);
+
+	return IRQ_HANDLED;
+}
+
+static void clear_all_interrupts(struct emif_data *emif)
+{
+	void __iomem	*base = emif->base;
+
+	writel(readl(base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS),
+		base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS);
+	if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE)
+		writel(readl(base + EMIF_LL_OCP_INTERRUPT_STATUS),
+			base + EMIF_LL_OCP_INTERRUPT_STATUS);
+}
+
+static void disable_and_clear_all_interrupts(struct emif_data *emif)
+{
+	void __iomem		*base = emif->base;
+
+	/* Disable all interrupts */
+	writel(readl(base + EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET),
+		base + EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR);
+	if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE)
+		writel(readl(base + EMIF_LL_OCP_INTERRUPT_ENABLE_SET),
+			base + EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR);
+
+	/* Clear all interrupts */
+	clear_all_interrupts(emif);
+}
+
+static int __init_or_module setup_interrupts(struct emif_data *emif, u32 irq)
+{
+	u32		interrupts, type;
+	void __iomem	*base = emif->base;
+
+	type = emif->plat_data->device_info->type;
+
+	clear_all_interrupts(emif);
+
+	/* Enable interrupts for SYS interface */
+	interrupts = EN_ERR_SYS_MASK;
+	if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4)
+		interrupts |= EN_TA_SYS_MASK;
+	writel(interrupts, base + EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET);
+
+	/* Enable interrupts for LL interface */
+	if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE) {
+		/* TA need not be enabled for LL */
+		interrupts = EN_ERR_LL_MASK;
+		writel(interrupts, base + EMIF_LL_OCP_INTERRUPT_ENABLE_SET);
+	}
+
+	/* setup IRQ handlers */
+	return devm_request_threaded_irq(emif->dev, irq,
+				    emif_interrupt_handler,
+				    emif_threaded_isr,
+				    0, dev_name(emif->dev),
+				    emif);
+
+}
+
 static void get_default_timings(struct emif_data *emif)
 {
 	struct emif_platform_data *pd = emif->plat_data;
@@ -803,6 +991,7 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
 {
 	struct emif_data	*emif;
 	struct resource		*res;
+	int			irq;
 
 	emif = get_device_details(pdev);
 	if (!emif) {
@@ -831,6 +1020,16 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
 		goto error;
 	}
 
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(emif->dev, "%s: error getting IRQ resource - %d\n",
+			__func__, irq);
+		goto error;
+	}
+
+	disable_and_clear_all_interrupts(emif);
+	setup_interrupts(emif, irq);
+
 	/* One-time actions taken on probing the first device */
 	if (!emif1) {
 		emif1 = emif;
@@ -843,14 +1042,21 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
 		 */
 	}
 
-	dev_info(&pdev->dev, "%s: device configured with addr = %p\n",
-		__func__, emif->base);
+	dev_info(&pdev->dev, "%s: device configured with addr = %p and IRQ%d\n",
+		__func__, emif->base, irq);
 
 	return 0;
 error:
 	return -ENODEV;
 }
 
+static void emif_shutdown(struct platform_device *pdev)
+{
+	struct emif_data	*emif = platform_get_drvdata(pdev);
+
+	disable_and_clear_all_interrupts(emif);
+}
+
 static int get_emif_reg_values(struct emif_data *emif, u32 freq,
 		struct emif_regs *regs)
 {
@@ -1154,6 +1360,7 @@ static void __attribute__((unused)) freq_post_notify_handling(void)
 }
 
 static struct platform_driver emif_driver = {
+	.shutdown	= emif_shutdown,
 	.driver = {
 		.name = "emif",
 	},
-- 
1.7.1


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

* [PATCH v4 5/7] misc: emif: add interrupt and temperature handling
@ 2012-03-16 21:51   ` Aneesh V
  0 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-03-16 21:51 UTC (permalink / raw)
  To: linux-arm-kernel

Add an ISR for EMIF that:
	1. reports details of access errors
	2. takes action on thermal events

Also clear all interrupts on shut-down. Pending IRQs
may casue problems during warm-reset.

Temperature handling:
EMIF can be configured to poll the temperature level
of an LPDDR2 device from the MR4 mode register in the
device. EMIF generates an interrupt whenever it identifies
a temperature level change between two consecutive pollings.

Some of the timing parameters need to be de-rated at high
temperatures. The interrupt handler takes care of doing
this and also takes care of going back to nominal settings
when temperature falls back to nominal levels.

Cc: Greg KH <greg@kroah.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
---

v2:
- replaced __init with __init_or_module

v1:
- Improved commit log
- Improved synchronization with thread context
---
 drivers/misc/emif.c |  211 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 209 insertions(+), 2 deletions(-)

diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c
index 1ca8165..52048f4 100644
--- a/drivers/misc/emif.c
+++ b/drivers/misc/emif.c
@@ -545,6 +545,42 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev)
 }
 
 /*
+ * Get the temperature level of the EMIF instance:
+ * Reads the MR4 register of attached SDRAM parts to find out the temperature
+ * level. If there are two parts attached(one on each CS), then the temperature
+ * level for the EMIF instance is the higher of the two temperatures.
+ */
+static void get_temperature_level(struct emif_data *emif)
+{
+	u32		temp, temperature_level;
+	void __iomem	*base;
+
+	base = emif->base;
+
+	/* Read mode register 4 */
+	writel(DDR_MR4, base + EMIF_LPDDR2_MODE_REG_CONFIG);
+	temperature_level = readl(base + EMIF_LPDDR2_MODE_REG_DATA);
+	temperature_level = (temperature_level & MR4_SDRAM_REF_RATE_MASK) >>
+				MR4_SDRAM_REF_RATE_SHIFT;
+
+	if (emif->plat_data->device_info->cs1_used) {
+		writel(DDR_MR4 | CS_MASK, base + EMIF_LPDDR2_MODE_REG_CONFIG);
+		temp = readl(base + EMIF_LPDDR2_MODE_REG_DATA);
+		temp = (temp & MR4_SDRAM_REF_RATE_MASK)
+				>> MR4_SDRAM_REF_RATE_SHIFT;
+		temperature_level = max(temp, temperature_level);
+	}
+
+	/* treat everything less than nominal(3) in MR4 as nominal */
+	if (unlikely(temperature_level < SDRAM_TEMP_NOMINAL))
+		temperature_level = SDRAM_TEMP_NOMINAL;
+
+	/* if we get reserved value in MR4 persist with the existing value */
+	if (likely(temperature_level != SDRAM_TEMP_RESERVED_4))
+		emif->temperature_level = temperature_level;
+}
+
+/*
  * Program EMIF shadow registers that are not dependent on temperature
  * or voltage
  */
@@ -627,6 +663,158 @@ out:
 	writel(ref_ctrl, base + EMIF_SDRAM_REFRESH_CTRL_SHDW);
 }
 
+static irqreturn_t handle_temp_alert(void __iomem *base, struct emif_data *emif)
+{
+	u32		old_temp_level;
+	irqreturn_t	ret = IRQ_HANDLED;
+
+	spin_lock_irqsave(&emif_lock, irq_state);
+	old_temp_level = emif->temperature_level;
+	get_temperature_level(emif);
+
+	if (unlikely(emif->temperature_level == old_temp_level)) {
+		goto out;
+	} else if (!emif->curr_regs) {
+		dev_err(emif->dev, "temperature alert before registers are calculated, not de-rating timings\n");
+		goto out;
+	}
+
+	if (emif->temperature_level < old_temp_level ||
+		emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) {
+		/*
+		 * Temperature coming down - defer handling to thread OR
+		 * Temperature far too high - do kernel_power_off() from
+		 * thread context
+		 */
+		ret = IRQ_WAKE_THREAD;
+	} else {
+		/* Temperature is going up - handle immediately */
+		setup_temperature_sensitive_regs(emif, emif->curr_regs);
+		do_freq_update();
+	}
+
+out:
+	spin_unlock_irqrestore(&emif_lock, irq_state);
+	return ret;
+}
+
+static irqreturn_t emif_interrupt_handler(int irq, void *dev_id)
+{
+	u32			interrupts;
+	struct emif_data	*emif = dev_id;
+	void __iomem		*base = emif->base;
+	struct device		*dev = emif->dev;
+	irqreturn_t		ret = IRQ_HANDLED;
+
+	/* Save the status and clear it */
+	interrupts = readl(base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS);
+	writel(interrupts, base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS);
+
+	/*
+	 * Handle temperature alert
+	 * Temperature alert should be same for all ports
+	 * So, it's enough to process it only for one of the ports
+	 */
+	if (interrupts & TA_SYS_MASK)
+		ret = handle_temp_alert(base, emif);
+
+	if (interrupts & ERR_SYS_MASK)
+		dev_err(dev, "Access error from SYS port - %x\n", interrupts);
+
+	if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE) {
+		/* Save the status and clear it */
+		interrupts = readl(base + EMIF_LL_OCP_INTERRUPT_STATUS);
+		writel(interrupts, base + EMIF_LL_OCP_INTERRUPT_STATUS);
+
+		if (interrupts & ERR_LL_MASK)
+			dev_err(dev, "Access error from LL port - %x\n",
+				interrupts);
+	}
+
+	return ret;
+}
+
+static irqreturn_t emif_threaded_isr(int irq, void *dev_id)
+{
+	struct emif_data	*emif = dev_id;
+
+	if (emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) {
+		dev_emerg(emif->dev, "SDRAM temperature exceeds operating limit.. Needs shut down!!!\n");
+		kernel_power_off();
+		return IRQ_HANDLED;
+	}
+
+	spin_lock_irqsave(&emif_lock, irq_state);
+
+	if (emif->curr_regs) {
+		setup_temperature_sensitive_regs(emif, emif->curr_regs);
+		do_freq_update();
+	} else {
+		dev_err(emif->dev, "temperature alert before registers are calculated, not de-rating timings\n");
+	}
+
+	spin_unlock_irqrestore(&emif_lock, irq_state);
+
+	return IRQ_HANDLED;
+}
+
+static void clear_all_interrupts(struct emif_data *emif)
+{
+	void __iomem	*base = emif->base;
+
+	writel(readl(base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS),
+		base + EMIF_SYSTEM_OCP_INTERRUPT_STATUS);
+	if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE)
+		writel(readl(base + EMIF_LL_OCP_INTERRUPT_STATUS),
+			base + EMIF_LL_OCP_INTERRUPT_STATUS);
+}
+
+static void disable_and_clear_all_interrupts(struct emif_data *emif)
+{
+	void __iomem		*base = emif->base;
+
+	/* Disable all interrupts */
+	writel(readl(base + EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET),
+		base + EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR);
+	if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE)
+		writel(readl(base + EMIF_LL_OCP_INTERRUPT_ENABLE_SET),
+			base + EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR);
+
+	/* Clear all interrupts */
+	clear_all_interrupts(emif);
+}
+
+static int __init_or_module setup_interrupts(struct emif_data *emif, u32 irq)
+{
+	u32		interrupts, type;
+	void __iomem	*base = emif->base;
+
+	type = emif->plat_data->device_info->type;
+
+	clear_all_interrupts(emif);
+
+	/* Enable interrupts for SYS interface */
+	interrupts = EN_ERR_SYS_MASK;
+	if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4)
+		interrupts |= EN_TA_SYS_MASK;
+	writel(interrupts, base + EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET);
+
+	/* Enable interrupts for LL interface */
+	if (emif->plat_data->hw_caps & EMIF_HW_CAPS_LL_INTERFACE) {
+		/* TA need not be enabled for LL */
+		interrupts = EN_ERR_LL_MASK;
+		writel(interrupts, base + EMIF_LL_OCP_INTERRUPT_ENABLE_SET);
+	}
+
+	/* setup IRQ handlers */
+	return devm_request_threaded_irq(emif->dev, irq,
+				    emif_interrupt_handler,
+				    emif_threaded_isr,
+				    0, dev_name(emif->dev),
+				    emif);
+
+}
+
 static void get_default_timings(struct emif_data *emif)
 {
 	struct emif_platform_data *pd = emif->plat_data;
@@ -803,6 +991,7 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
 {
 	struct emif_data	*emif;
 	struct resource		*res;
+	int			irq;
 
 	emif = get_device_details(pdev);
 	if (!emif) {
@@ -831,6 +1020,16 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
 		goto error;
 	}
 
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(emif->dev, "%s: error getting IRQ resource - %d\n",
+			__func__, irq);
+		goto error;
+	}
+
+	disable_and_clear_all_interrupts(emif);
+	setup_interrupts(emif, irq);
+
 	/* One-time actions taken on probing the first device */
 	if (!emif1) {
 		emif1 = emif;
@@ -843,14 +1042,21 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
 		 */
 	}
 
-	dev_info(&pdev->dev, "%s: device configured with addr = %p\n",
-		__func__, emif->base);
+	dev_info(&pdev->dev, "%s: device configured with addr = %p and IRQ%d\n",
+		__func__, emif->base, irq);
 
 	return 0;
 error:
 	return -ENODEV;
 }
 
+static void emif_shutdown(struct platform_device *pdev)
+{
+	struct emif_data	*emif = platform_get_drvdata(pdev);
+
+	disable_and_clear_all_interrupts(emif);
+}
+
 static int get_emif_reg_values(struct emif_data *emif, u32 freq,
 		struct emif_regs *regs)
 {
@@ -1154,6 +1360,7 @@ static void __attribute__((unused)) freq_post_notify_handling(void)
 }
 
 static struct platform_driver emif_driver = {
+	.shutdown	= emif_shutdown,
 	.driver = {
 		.name = "emif",
 	},
-- 
1.7.1

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

* [PATCH v4 6/7] misc: emif: add one-time settings
  2012-03-16 21:51 ` Aneesh V
@ 2012-03-16 21:51   ` Aneesh V
  -1 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-03-16 21:51 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-arm-kernel, linux-omap, Aneesh V, Greg KH

Add settings that are not dependent on frequency
or any other transient parameters. This includes
- power managment control init
- impedence calibration control
- frequency independent phy configuration registers
- initialization of temperature polling

Cc: Greg KH <greg@kroah.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
---
v2:
- replaced __init with __init_or_module
- fixed bug in the implementation of i728 errata workaround

v1:
- Improved commit log
- Changes for errata i728 workaround
---
 drivers/misc/emif.c |  148 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 148 insertions(+), 0 deletions(-)

diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c
index 52048f4..270a0e4 100644
--- a/drivers/misc/emif.c
+++ b/drivers/misc/emif.c
@@ -78,6 +78,24 @@ static void set_ddr_clk_period(u32 freq)
 }
 
 /*
+ * Get bus width used by EMIF. Note that this may be different from the
+ * bus width of the DDR devices used. For instance two 16-bit DDR devices
+ * may be connected to a given CS of EMIF. In this case bus width as far
+ * as EMIF is concerned is 32, where as the DDR bus width is 16 bits.
+ */
+static u32 get_emif_bus_width(struct emif_data *emif)
+{
+	u32		width;
+	void __iomem	*base = emif->base;
+
+	width = (readl(base + EMIF_SDRAM_CONFIG) & NARROW_MODE_MASK)
+			>> NARROW_MODE_SHIFT;
+	width = width == 0 ? 32 : 16;
+
+	return width;
+}
+
+/*
  * Get the CL from SDRAM_CONFIG register
  */
 static u32 get_cl(struct emif_data *emif)
@@ -372,6 +390,70 @@ static u32 get_sdram_tim_3_shdw(const struct lpddr2_timings *timings,
 	return tim3;
 }
 
+static u32 get_zq_config_reg(const struct lpddr2_addressing *addressing,
+		bool cs1_used, bool cal_resistors_per_cs)
+{
+	u32 zq = 0, val = 0;
+
+	val = EMIF_ZQCS_INTERVAL_US * 1000 / addressing->tREFI_ns;
+	zq |= val << ZQ_REFINTERVAL_SHIFT;
+
+	val = DIV_ROUND_UP(T_ZQCL_DEFAULT_NS, T_ZQCS_DEFAULT_NS) - 1;
+	zq |= val << ZQ_ZQCL_MULT_SHIFT;
+
+	val = DIV_ROUND_UP(T_ZQINIT_DEFAULT_NS, T_ZQCL_DEFAULT_NS) - 1;
+	zq |= val << ZQ_ZQINIT_MULT_SHIFT;
+
+	zq |= ZQ_SFEXITEN_ENABLE << ZQ_SFEXITEN_SHIFT;
+
+	if (cal_resistors_per_cs)
+		zq |= ZQ_DUALCALEN_ENABLE << ZQ_DUALCALEN_SHIFT;
+	else
+		zq |= ZQ_DUALCALEN_DISABLE << ZQ_DUALCALEN_SHIFT;
+
+	zq |= ZQ_CS0EN_MASK; /* CS0 is used for sure */
+
+	val = cs1_used ? 1 : 0;
+	zq |= val << ZQ_CS1EN_SHIFT;
+
+	return zq;
+}
+
+static u32 get_temp_alert_config(const struct lpddr2_addressing *addressing,
+		const struct emif_custom_configs *custom_configs, bool cs1_used,
+		u32 sdram_io_width, u32 emif_bus_width)
+{
+	u32 alert = 0, interval, devcnt;
+
+	if (custom_configs && (custom_configs->mask &
+				EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL))
+		interval = custom_configs->temp_alert_poll_interval_ms;
+	else
+		interval = TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS;
+
+	interval *= 1000000;			/* Convert to ns */
+	interval /= addressing->tREFI_ns;	/* Convert to refresh cycles */
+	alert |= (interval << TA_REFINTERVAL_SHIFT);
+
+	/*
+	 * sdram_io_width is in 'log2(x) - 1' form. Convert emif_bus_width
+	 * also to this form and subtract to get TA_DEVCNT, which is
+	 * in log2(x) form.
+	 */
+	emif_bus_width = __fls(emif_bus_width) - 1;
+	devcnt = emif_bus_width - sdram_io_width;
+	alert |= devcnt << TA_DEVCNT_SHIFT;
+
+	/* DEVWDT is in 'log2(x) - 3' form */
+	alert |= (sdram_io_width - 2) << TA_DEVWDT_SHIFT;
+
+	alert |= 1 << TA_SFEXITEN_SHIFT;
+	alert |= 1 << TA_CS0EN_SHIFT;
+	alert |= (cs1_used ? 1 : 0) << TA_CS1EN_SHIFT;
+
+	return alert;
+}
+
 static u32 get_read_idle_ctrl_shdw(u8 volt_ramp)
 {
 	u32 idle = 0, val = 0;
@@ -815,6 +897,71 @@ static int __init_or_module setup_interrupts(struct emif_data *emif, u32 irq)
 
 }
 
+static void __init_or_module emif_onetime_settings(struct emif_data *emif)
+{
+	u32				pwr_mgmt_ctrl, zq, temp_alert_cfg;
+	void __iomem			*base = emif->base;
+	const struct lpddr2_addressing	*addressing;
+	const struct ddr_device_info	*device_info;
+
+	device_info = emif->plat_data->device_info;
+	addressing = get_addressing_table(device_info);
+
+	/*
+	 * Init power management settings
+	 * We don't know the frequency yet. Use a high frequency
+	 * value for a conservative timeout setting
+	 */
+	pwr_mgmt_ctrl = get_pwr_mgmt_ctrl(1000000000, emif,
+			emif->plat_data->ip_rev);
+	emif->lpmode = (pwr_mgmt_ctrl & LP_MODE_MASK) >> LP_MODE_SHIFT;
+	writel(pwr_mgmt_ctrl, base + EMIF_POWER_MANAGEMENT_CONTROL);
+
+	/* Init ZQ calibration settings */
+	zq = get_zq_config_reg(addressing, device_info->cs1_used,
+		device_info->cal_resistors_per_cs);
+	writel(zq, base + EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG);
+
+	/* Check temperature level temperature level*/
+	get_temperature_level(emif);
+	if (emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN)
+		dev_emerg(emif->dev, "SDRAM temperature exceeds operating limit.. Needs shut down!!!\n");
+
+	/* Init temperature polling */
+	temp_alert_cfg = get_temp_alert_config(addressing,
+		emif->plat_data->custom_configs, device_info->cs1_used,
+		device_info->io_width, get_emif_bus_width(emif));
+	writel(temp_alert_cfg, base + EMIF_TEMPERATURE_ALERT_CONFIG);
+
+	/*
+	 * Program external PHY control registers that are not frequency
+	 * dependent
+	 */
+	if (emif->plat_data->phy_type != EMIF_PHY_TYPE_INTELLIPHY)
+		return;
+	writel(EMIF_EXT_PHY_CTRL_1_VAL, base + EMIF_EXT_PHY_CTRL_1_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_5_VAL, base + EMIF_EXT_PHY_CTRL_5_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_6_VAL, base + EMIF_EXT_PHY_CTRL_6_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_7_VAL, base + EMIF_EXT_PHY_CTRL_7_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_8_VAL, base + EMIF_EXT_PHY_CTRL_8_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_9_VAL, base + EMIF_EXT_PHY_CTRL_9_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_10_VAL, base + EMIF_EXT_PHY_CTRL_10_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_11_VAL, base + EMIF_EXT_PHY_CTRL_11_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_12_VAL, base + EMIF_EXT_PHY_CTRL_12_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_13_VAL, base + EMIF_EXT_PHY_CTRL_13_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_14_VAL, base + EMIF_EXT_PHY_CTRL_14_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_15_VAL, base + EMIF_EXT_PHY_CTRL_15_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_16_VAL, base + EMIF_EXT_PHY_CTRL_16_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_17_VAL, base + EMIF_EXT_PHY_CTRL_17_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_18_VAL, base + EMIF_EXT_PHY_CTRL_18_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_19_VAL, base + EMIF_EXT_PHY_CTRL_19_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_20_VAL, base + EMIF_EXT_PHY_CTRL_20_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_21_VAL, base + EMIF_EXT_PHY_CTRL_21_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_22_VAL, base + EMIF_EXT_PHY_CTRL_22_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_23_VAL, base + EMIF_EXT_PHY_CTRL_23_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_24_VAL, base + EMIF_EXT_PHY_CTRL_24_SHDW);
+}
+
 static void get_default_timings(struct emif_data *emif)
 {
 	struct emif_platform_data *pd = emif->plat_data;
@@ -1027,6 +1174,7 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
 		goto error;
 	}
 
+	emif_onetime_settings(emif);
 	disable_and_clear_all_interrupts(emif);
 	setup_interrupts(emif, irq);
 
-- 
1.7.1


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

* [PATCH v4 6/7] misc: emif: add one-time settings
@ 2012-03-16 21:51   ` Aneesh V
  0 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-03-16 21:51 UTC (permalink / raw)
  To: linux-arm-kernel

Add settings that are not dependent on frequency
or any other transient parameters. This includes
- power managment control init
- impedence calibration control
- frequency independent phy configuration registers
- initialization of temperature polling

Cc: Greg KH <greg@kroah.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
---
v2:
- replaced __init with __init_or_module
- fixed bug in the implementation of i728 errata workaround

v1:
- Improved commit log
- Changes for errata i728 workaround
---
 drivers/misc/emif.c |  148 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 148 insertions(+), 0 deletions(-)

diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c
index 52048f4..270a0e4 100644
--- a/drivers/misc/emif.c
+++ b/drivers/misc/emif.c
@@ -78,6 +78,24 @@ static void set_ddr_clk_period(u32 freq)
 }
 
 /*
+ * Get bus width used by EMIF. Note that this may be different from the
+ * bus width of the DDR devices used. For instance two 16-bit DDR devices
+ * may be connected to a given CS of EMIF. In this case bus width as far
+ * as EMIF is concerned is 32, where as the DDR bus width is 16 bits.
+ */
+static u32 get_emif_bus_width(struct emif_data *emif)
+{
+	u32		width;
+	void __iomem	*base = emif->base;
+
+	width = (readl(base + EMIF_SDRAM_CONFIG) & NARROW_MODE_MASK)
+			>> NARROW_MODE_SHIFT;
+	width = width == 0 ? 32 : 16;
+
+	return width;
+}
+
+/*
  * Get the CL from SDRAM_CONFIG register
  */
 static u32 get_cl(struct emif_data *emif)
@@ -372,6 +390,70 @@ static u32 get_sdram_tim_3_shdw(const struct lpddr2_timings *timings,
 	return tim3;
 }
 
+static u32 get_zq_config_reg(const struct lpddr2_addressing *addressing,
+		bool cs1_used, bool cal_resistors_per_cs)
+{
+	u32 zq = 0, val = 0;
+
+	val = EMIF_ZQCS_INTERVAL_US * 1000 / addressing->tREFI_ns;
+	zq |= val << ZQ_REFINTERVAL_SHIFT;
+
+	val = DIV_ROUND_UP(T_ZQCL_DEFAULT_NS, T_ZQCS_DEFAULT_NS) - 1;
+	zq |= val << ZQ_ZQCL_MULT_SHIFT;
+
+	val = DIV_ROUND_UP(T_ZQINIT_DEFAULT_NS, T_ZQCL_DEFAULT_NS) - 1;
+	zq |= val << ZQ_ZQINIT_MULT_SHIFT;
+
+	zq |= ZQ_SFEXITEN_ENABLE << ZQ_SFEXITEN_SHIFT;
+
+	if (cal_resistors_per_cs)
+		zq |= ZQ_DUALCALEN_ENABLE << ZQ_DUALCALEN_SHIFT;
+	else
+		zq |= ZQ_DUALCALEN_DISABLE << ZQ_DUALCALEN_SHIFT;
+
+	zq |= ZQ_CS0EN_MASK; /* CS0 is used for sure */
+
+	val = cs1_used ? 1 : 0;
+	zq |= val << ZQ_CS1EN_SHIFT;
+
+	return zq;
+}
+
+static u32 get_temp_alert_config(const struct lpddr2_addressing *addressing,
+		const struct emif_custom_configs *custom_configs, bool cs1_used,
+		u32 sdram_io_width, u32 emif_bus_width)
+{
+	u32 alert = 0, interval, devcnt;
+
+	if (custom_configs && (custom_configs->mask &
+				EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL))
+		interval = custom_configs->temp_alert_poll_interval_ms;
+	else
+		interval = TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS;
+
+	interval *= 1000000;			/* Convert to ns */
+	interval /= addressing->tREFI_ns;	/* Convert to refresh cycles */
+	alert |= (interval << TA_REFINTERVAL_SHIFT);
+
+	/*
+	 * sdram_io_width is in 'log2(x) - 1' form. Convert emif_bus_width
+	 * also to this form and subtract to get TA_DEVCNT, which is
+	 * in log2(x) form.
+	 */
+	emif_bus_width = __fls(emif_bus_width) - 1;
+	devcnt = emif_bus_width - sdram_io_width;
+	alert |= devcnt << TA_DEVCNT_SHIFT;
+
+	/* DEVWDT is in 'log2(x) - 3' form */
+	alert |= (sdram_io_width - 2) << TA_DEVWDT_SHIFT;
+
+	alert |= 1 << TA_SFEXITEN_SHIFT;
+	alert |= 1 << TA_CS0EN_SHIFT;
+	alert |= (cs1_used ? 1 : 0) << TA_CS1EN_SHIFT;
+
+	return alert;
+}
+
 static u32 get_read_idle_ctrl_shdw(u8 volt_ramp)
 {
 	u32 idle = 0, val = 0;
@@ -815,6 +897,71 @@ static int __init_or_module setup_interrupts(struct emif_data *emif, u32 irq)
 
 }
 
+static void __init_or_module emif_onetime_settings(struct emif_data *emif)
+{
+	u32				pwr_mgmt_ctrl, zq, temp_alert_cfg;
+	void __iomem			*base = emif->base;
+	const struct lpddr2_addressing	*addressing;
+	const struct ddr_device_info	*device_info;
+
+	device_info = emif->plat_data->device_info;
+	addressing = get_addressing_table(device_info);
+
+	/*
+	 * Init power management settings
+	 * We don't know the frequency yet. Use a high frequency
+	 * value for a conservative timeout setting
+	 */
+	pwr_mgmt_ctrl = get_pwr_mgmt_ctrl(1000000000, emif,
+			emif->plat_data->ip_rev);
+	emif->lpmode = (pwr_mgmt_ctrl & LP_MODE_MASK) >> LP_MODE_SHIFT;
+	writel(pwr_mgmt_ctrl, base + EMIF_POWER_MANAGEMENT_CONTROL);
+
+	/* Init ZQ calibration settings */
+	zq = get_zq_config_reg(addressing, device_info->cs1_used,
+		device_info->cal_resistors_per_cs);
+	writel(zq, base + EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG);
+
+	/* Check temperature level temperature level*/
+	get_temperature_level(emif);
+	if (emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN)
+		dev_emerg(emif->dev, "SDRAM temperature exceeds operating limit.. Needs shut down!!!\n");
+
+	/* Init temperature polling */
+	temp_alert_cfg = get_temp_alert_config(addressing,
+		emif->plat_data->custom_configs, device_info->cs1_used,
+		device_info->io_width, get_emif_bus_width(emif));
+	writel(temp_alert_cfg, base + EMIF_TEMPERATURE_ALERT_CONFIG);
+
+	/*
+	 * Program external PHY control registers that are not frequency
+	 * dependent
+	 */
+	if (emif->plat_data->phy_type != EMIF_PHY_TYPE_INTELLIPHY)
+		return;
+	writel(EMIF_EXT_PHY_CTRL_1_VAL, base + EMIF_EXT_PHY_CTRL_1_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_5_VAL, base + EMIF_EXT_PHY_CTRL_5_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_6_VAL, base + EMIF_EXT_PHY_CTRL_6_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_7_VAL, base + EMIF_EXT_PHY_CTRL_7_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_8_VAL, base + EMIF_EXT_PHY_CTRL_8_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_9_VAL, base + EMIF_EXT_PHY_CTRL_9_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_10_VAL, base + EMIF_EXT_PHY_CTRL_10_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_11_VAL, base + EMIF_EXT_PHY_CTRL_11_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_12_VAL, base + EMIF_EXT_PHY_CTRL_12_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_13_VAL, base + EMIF_EXT_PHY_CTRL_13_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_14_VAL, base + EMIF_EXT_PHY_CTRL_14_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_15_VAL, base + EMIF_EXT_PHY_CTRL_15_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_16_VAL, base + EMIF_EXT_PHY_CTRL_16_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_17_VAL, base + EMIF_EXT_PHY_CTRL_17_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_18_VAL, base + EMIF_EXT_PHY_CTRL_18_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_19_VAL, base + EMIF_EXT_PHY_CTRL_19_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_20_VAL, base + EMIF_EXT_PHY_CTRL_20_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_21_VAL, base + EMIF_EXT_PHY_CTRL_21_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_22_VAL, base + EMIF_EXT_PHY_CTRL_22_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_23_VAL, base + EMIF_EXT_PHY_CTRL_23_SHDW);
+	writel(EMIF_EXT_PHY_CTRL_24_VAL, base + EMIF_EXT_PHY_CTRL_24_SHDW);
+}
+
 static void get_default_timings(struct emif_data *emif)
 {
 	struct emif_platform_data *pd = emif->plat_data;
@@ -1027,6 +1174,7 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
 		goto error;
 	}
 
+	emif_onetime_settings(emif);
 	disable_and_clear_all_interrupts(emif);
 	setup_interrupts(emif, irq);
 
-- 
1.7.1

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

* [PATCH v4 7/7] misc: emif: add debugfs entries for emif
  2012-03-16 21:51 ` Aneesh V
@ 2012-03-16 21:51   ` Aneesh V
  -1 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-03-16 21:51 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-arm-kernel, linux-omap, Aneesh V, Greg KH

Add debug entries for:
	1. calculated registers per frequency
	2. last polled value of MR4(temperature level
	   of LPDDR2 memory)

Cc: Greg KH <greg@kroah.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
---
v2:
- Corrected the frequency value shown in
  register cache dump
- replaced __init with __init_or_module
---
 drivers/misc/emif.c |  138 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 138 insertions(+), 0 deletions(-)

diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c
index 270a0e4..6d2f776 100644
--- a/drivers/misc/emif.c
+++ b/drivers/misc/emif.c
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/module.h>
 #include <linux/list.h>
@@ -47,6 +48,7 @@
  *				frequency change (i.e. corresponding to the
  *				frequency in effect at the moment)
  * @plat_data:			Pointer to saved platform data.
+ * @debugfs_root:		dentry to the root folder for EMIF in debugfs
  */
 struct emif_data {
 	u8				duplicate;
@@ -60,6 +62,7 @@ struct emif_data {
 	struct emif_regs		*regs_cache[EMIF_MAX_NUM_FREQUENCIES];
 	struct emif_regs		*curr_regs;
 	struct emif_platform_data	*plat_data;
+	struct dentry			*debugfs_root;
 };
 
 static struct emif_data *emif1;
@@ -68,6 +71,130 @@ static unsigned long	irq_state;
 static u32		t_ck; /* DDR clock period in ps */
 static LIST_HEAD(device_list);
 
+static void do_emif_regdump_show(struct seq_file *s, struct emif_data *emif,
+	struct emif_regs *regs)
+{
+	u32 type = emif->plat_data->device_info->type;
+	u32 ip_rev = emif->plat_data->ip_rev;
+
+	seq_printf(s, "EMIF register cache dump for %dMHz\n",
+		regs->freq/1000000);
+
+	seq_printf(s, "ref_ctrl_shdw\t: 0x%08x\n", regs->ref_ctrl_shdw);
+	seq_printf(s, "sdram_tim1_shdw\t: 0x%08x\n", regs->sdram_tim1_shdw);
+	seq_printf(s, "sdram_tim2_shdw\t: 0x%08x\n", regs->sdram_tim2_shdw);
+	seq_printf(s, "sdram_tim3_shdw\t: 0x%08x\n", regs->sdram_tim3_shdw);
+
+	if (ip_rev == EMIF_4D) {
+		seq_printf(s, "read_idle_ctrl_shdw_normal\t: 0x%08x\n",
+			regs->read_idle_ctrl_shdw_normal);
+		seq_printf(s, "read_idle_ctrl_shdw_volt_ramp\t: 0x%08x\n",
+			regs->read_idle_ctrl_shdw_volt_ramp);
+	} else if (ip_rev == EMIF_4D5) {
+		seq_printf(s, "dll_calib_ctrl_shdw_normal\t: 0x%08x\n",
+			regs->dll_calib_ctrl_shdw_normal);
+		seq_printf(s, "dll_calib_ctrl_shdw_volt_ramp\t: 0x%08x\n",
+			regs->dll_calib_ctrl_shdw_volt_ramp);
+	}
+
+	if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) {
+		seq_printf(s, "ref_ctrl_shdw_derated\t: 0x%08x\n",
+			regs->ref_ctrl_shdw_derated);
+		seq_printf(s, "sdram_tim1_shdw_derated\t: 0x%08x\n",
+			regs->sdram_tim1_shdw_derated);
+		seq_printf(s, "sdram_tim3_shdw_derated\t: 0x%08x\n",
+			regs->sdram_tim3_shdw_derated);
+	}
+}
+
+static int emif_regdump_show(struct seq_file *s, void *unused)
+{
+	struct emif_data	*emif	= s->private;
+	struct emif_regs	**regs_cache;
+	int			i;
+
+	if (emif->duplicate)
+		regs_cache = emif1->regs_cache;
+	else
+		regs_cache = emif->regs_cache;
+
+	for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++) {
+		do_emif_regdump_show(s, emif, regs_cache[i]);
+		seq_printf(s, "\n");
+	}
+
+	return 0;
+}
+
+static int emif_regdump_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, emif_regdump_show, inode->i_private);
+}
+
+static const struct file_operations emif_regdump_fops = {
+	.open			= emif_regdump_open,
+	.read			= seq_read,
+	.release		= single_release,
+};
+
+static int emif_mr4_show(struct seq_file *s, void *unused)
+{
+	struct emif_data *emif = s->private;
+
+	seq_printf(s, "MR4=%d\n", emif->temperature_level);
+	return 0;
+}
+
+static int emif_mr4_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, emif_mr4_show, inode->i_private);
+}
+
+static const struct file_operations emif_mr4_fops = {
+	.open			= emif_mr4_open,
+	.read			= seq_read,
+	.release		= single_release,
+};
+
+static int __init_or_module emif_debugfs_init(struct emif_data *emif)
+{
+	struct dentry	*dentry;
+	int		ret;
+
+	dentry = debugfs_create_dir(dev_name(emif->dev), NULL);
+	if (IS_ERR(dentry)) {
+		ret = PTR_ERR(dentry);
+		goto err0;
+	}
+	emif->debugfs_root = dentry;
+
+	dentry = debugfs_create_file("regcache_dump", S_IRUGO,
+			emif->debugfs_root, emif, &emif_regdump_fops);
+	if (IS_ERR(dentry)) {
+		ret = PTR_ERR(dentry);
+		goto err1;
+	}
+
+	dentry = debugfs_create_file("mr4", S_IRUGO,
+			emif->debugfs_root, emif, &emif_mr4_fops);
+	if (IS_ERR(dentry)) {
+		ret = PTR_ERR(dentry);
+		goto err1;
+	}
+
+	return 0;
+err1:
+	debugfs_remove_recursive(emif->debugfs_root);
+err0:
+	return ret;
+}
+
+static void __exit emif_debugfs_exit(struct emif_data *emif)
+{
+	debugfs_remove_recursive(emif->debugfs_root);
+	emif->debugfs_root = NULL;
+}
+
 /*
  * Calculate the period of DDR clock from frequency value
  */
@@ -1175,6 +1302,7 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
 	}
 
 	emif_onetime_settings(emif);
+	emif_debugfs_init(emif);
 	disable_and_clear_all_interrupts(emif);
 	setup_interrupts(emif, irq);
 
@@ -1198,6 +1326,15 @@ error:
 	return -ENODEV;
 }
 
+static int __exit emif_remove(struct platform_device *pdev)
+{
+	struct emif_data *emif = platform_get_drvdata(pdev);
+
+	emif_debugfs_exit(emif);
+
+	return 0;
+}
+
 static void emif_shutdown(struct platform_device *pdev)
 {
 	struct emif_data	*emif = platform_get_drvdata(pdev);
@@ -1508,6 +1645,7 @@ static void __attribute__((unused)) freq_post_notify_handling(void)
 }
 
 static struct platform_driver emif_driver = {
+	.remove		= __exit_p(emif_remove),
 	.shutdown	= emif_shutdown,
 	.driver = {
 		.name = "emif",
-- 
1.7.1


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

* [PATCH v4 7/7] misc: emif: add debugfs entries for emif
@ 2012-03-16 21:51   ` Aneesh V
  0 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-03-16 21:51 UTC (permalink / raw)
  To: linux-arm-kernel

Add debug entries for:
	1. calculated registers per frequency
	2. last polled value of MR4(temperature level
	   of LPDDR2 memory)

Cc: Greg KH <greg@kroah.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
---
v2:
- Corrected the frequency value shown in
  register cache dump
- replaced __init with __init_or_module
---
 drivers/misc/emif.c |  138 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 138 insertions(+), 0 deletions(-)

diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c
index 270a0e4..6d2f776 100644
--- a/drivers/misc/emif.c
+++ b/drivers/misc/emif.c
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/module.h>
 #include <linux/list.h>
@@ -47,6 +48,7 @@
  *				frequency change (i.e. corresponding to the
  *				frequency in effect at the moment)
  * @plat_data:			Pointer to saved platform data.
+ * @debugfs_root:		dentry to the root folder for EMIF in debugfs
  */
 struct emif_data {
 	u8				duplicate;
@@ -60,6 +62,7 @@ struct emif_data {
 	struct emif_regs		*regs_cache[EMIF_MAX_NUM_FREQUENCIES];
 	struct emif_regs		*curr_regs;
 	struct emif_platform_data	*plat_data;
+	struct dentry			*debugfs_root;
 };
 
 static struct emif_data *emif1;
@@ -68,6 +71,130 @@ static unsigned long	irq_state;
 static u32		t_ck; /* DDR clock period in ps */
 static LIST_HEAD(device_list);
 
+static void do_emif_regdump_show(struct seq_file *s, struct emif_data *emif,
+	struct emif_regs *regs)
+{
+	u32 type = emif->plat_data->device_info->type;
+	u32 ip_rev = emif->plat_data->ip_rev;
+
+	seq_printf(s, "EMIF register cache dump for %dMHz\n",
+		regs->freq/1000000);
+
+	seq_printf(s, "ref_ctrl_shdw\t: 0x%08x\n", regs->ref_ctrl_shdw);
+	seq_printf(s, "sdram_tim1_shdw\t: 0x%08x\n", regs->sdram_tim1_shdw);
+	seq_printf(s, "sdram_tim2_shdw\t: 0x%08x\n", regs->sdram_tim2_shdw);
+	seq_printf(s, "sdram_tim3_shdw\t: 0x%08x\n", regs->sdram_tim3_shdw);
+
+	if (ip_rev == EMIF_4D) {
+		seq_printf(s, "read_idle_ctrl_shdw_normal\t: 0x%08x\n",
+			regs->read_idle_ctrl_shdw_normal);
+		seq_printf(s, "read_idle_ctrl_shdw_volt_ramp\t: 0x%08x\n",
+			regs->read_idle_ctrl_shdw_volt_ramp);
+	} else if (ip_rev == EMIF_4D5) {
+		seq_printf(s, "dll_calib_ctrl_shdw_normal\t: 0x%08x\n",
+			regs->dll_calib_ctrl_shdw_normal);
+		seq_printf(s, "dll_calib_ctrl_shdw_volt_ramp\t: 0x%08x\n",
+			regs->dll_calib_ctrl_shdw_volt_ramp);
+	}
+
+	if (type == DDR_TYPE_LPDDR2_S2 || type == DDR_TYPE_LPDDR2_S4) {
+		seq_printf(s, "ref_ctrl_shdw_derated\t: 0x%08x\n",
+			regs->ref_ctrl_shdw_derated);
+		seq_printf(s, "sdram_tim1_shdw_derated\t: 0x%08x\n",
+			regs->sdram_tim1_shdw_derated);
+		seq_printf(s, "sdram_tim3_shdw_derated\t: 0x%08x\n",
+			regs->sdram_tim3_shdw_derated);
+	}
+}
+
+static int emif_regdump_show(struct seq_file *s, void *unused)
+{
+	struct emif_data	*emif	= s->private;
+	struct emif_regs	**regs_cache;
+	int			i;
+
+	if (emif->duplicate)
+		regs_cache = emif1->regs_cache;
+	else
+		regs_cache = emif->regs_cache;
+
+	for (i = 0; i < EMIF_MAX_NUM_FREQUENCIES && regs_cache[i]; i++) {
+		do_emif_regdump_show(s, emif, regs_cache[i]);
+		seq_printf(s, "\n");
+	}
+
+	return 0;
+}
+
+static int emif_regdump_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, emif_regdump_show, inode->i_private);
+}
+
+static const struct file_operations emif_regdump_fops = {
+	.open			= emif_regdump_open,
+	.read			= seq_read,
+	.release		= single_release,
+};
+
+static int emif_mr4_show(struct seq_file *s, void *unused)
+{
+	struct emif_data *emif = s->private;
+
+	seq_printf(s, "MR4=%d\n", emif->temperature_level);
+	return 0;
+}
+
+static int emif_mr4_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, emif_mr4_show, inode->i_private);
+}
+
+static const struct file_operations emif_mr4_fops = {
+	.open			= emif_mr4_open,
+	.read			= seq_read,
+	.release		= single_release,
+};
+
+static int __init_or_module emif_debugfs_init(struct emif_data *emif)
+{
+	struct dentry	*dentry;
+	int		ret;
+
+	dentry = debugfs_create_dir(dev_name(emif->dev), NULL);
+	if (IS_ERR(dentry)) {
+		ret = PTR_ERR(dentry);
+		goto err0;
+	}
+	emif->debugfs_root = dentry;
+
+	dentry = debugfs_create_file("regcache_dump", S_IRUGO,
+			emif->debugfs_root, emif, &emif_regdump_fops);
+	if (IS_ERR(dentry)) {
+		ret = PTR_ERR(dentry);
+		goto err1;
+	}
+
+	dentry = debugfs_create_file("mr4", S_IRUGO,
+			emif->debugfs_root, emif, &emif_mr4_fops);
+	if (IS_ERR(dentry)) {
+		ret = PTR_ERR(dentry);
+		goto err1;
+	}
+
+	return 0;
+err1:
+	debugfs_remove_recursive(emif->debugfs_root);
+err0:
+	return ret;
+}
+
+static void __exit emif_debugfs_exit(struct emif_data *emif)
+{
+	debugfs_remove_recursive(emif->debugfs_root);
+	emif->debugfs_root = NULL;
+}
+
 /*
  * Calculate the period of DDR clock from frequency value
  */
@@ -1175,6 +1302,7 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
 	}
 
 	emif_onetime_settings(emif);
+	emif_debugfs_init(emif);
 	disable_and_clear_all_interrupts(emif);
 	setup_interrupts(emif, irq);
 
@@ -1198,6 +1326,15 @@ error:
 	return -ENODEV;
 }
 
+static int __exit emif_remove(struct platform_device *pdev)
+{
+	struct emif_data *emif = platform_get_drvdata(pdev);
+
+	emif_debugfs_exit(emif);
+
+	return 0;
+}
+
 static void emif_shutdown(struct platform_device *pdev)
 {
 	struct emif_data	*emif = platform_get_drvdata(pdev);
@@ -1508,6 +1645,7 @@ static void __attribute__((unused)) freq_post_notify_handling(void)
 }
 
 static struct platform_driver emif_driver = {
+	.remove		= __exit_p(emif_remove),
 	.shutdown	= emif_shutdown,
 	.driver = {
 		.name = "emif",
-- 
1.7.1

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-03-16 21:51 ` Aneesh V
  (?)
@ 2012-03-17  6:10   ` Kyungmin Park
  -1 siblings, 0 replies; 84+ messages in thread
From: Kyungmin Park @ 2012-03-17  6:10 UTC (permalink / raw)
  To: Aneesh V
  Cc: linux-kernel, Greg KH, linux-omap, linux-arm-kernel,
	함명주

Hi,

On 3/17/12, Aneesh V <aneesh@ti.com> wrote:
> Add a driver for the EMIF SDRAM controller used in TI SoCs
>
> EMIF is an SDRAM controller that supports, based on its revision,
> one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
> for LPDDR2.
>
> The driver supports the following features:
> - Calculates the DDR AC timing parameters to be set in EMIF
>   registers using data from the device data-sheets and based
>   on the DDR frequency. If data from data-sheets is not available
>   default timing values from the JEDEC spec are used. These
>   will be safe, but not necessarily optimal
> - API for changing timings during DVFS or at boot-up
> - Temperature alert configuration and handling of temperature
>   alerts, if any for LPDDR2 devices
>   * temperature alert is based on periodic polling of MR4 mode
>     register in DDR devices automatically performed by hardware
>   * timings are de-rated and brought back to nominal when
>     temperature raises and falls respectively
> - Cache of calculated register values to avoid re-calculating
>   them
>
> The driver will need some minor updates when it is eventually
> integrated with Dynamic Voltage and Frequency Scaling (DVFS).
> This can not be done now as DVFS support is not available in
> the mainline yet.
Do you see the devfreq? it's designed for non-cpu device frequency.
It's role is similar with cpufreq.

Now samsung exynos uses devfreq for DRAM bus frequency.

Thank you,
Kyungmin Park
>
> Discussions with Santosh Shilimkar <santosh.shilimkar@ti.com>
> were immensely helpful in shaping up the interfaces. Vibhore Vardhan
> <vvardhan@gmail.com> did the initial code snippet for thermal
> handling.
>
> Testing:
> - The driver is tested on OMAP4430 SDP.
> - The driver in a slightly adapted form is also tested on OMAP5.
> - Since mainline kernel doesn't have DVFS support yet,
>   testing was done using a test module.
> - Temperature alert handling was tested with simulated interrupts
>   and faked temperature values as testing all cases in real-life
>   scenarios is difficult.
> - Tested the driver as a module
>
> Cc: Greg KH <greg@kroah.com>
>
> v4:
> - Converted instances of EXPORT_SYMBOL to EXPORT_SYMBOL_GPL
> - Removed un-necessary "#ifndef __ASSEMBLY__'
> - Minor formatting fix
>
> v2:
> - Fixed a bug found in the implementation of errata i728
>   workaround
> - Fixed the value of frequency printed in debugfs
> - Dropped the hwmod patch as Paul has already posted a
>   a hwmod series [1] that adds hwmod for EMIF
> - Converted instances of __init to __init_or_module
>
> [1] http://thread.gmane.org/gmane.linux.ports.arm.omap/72855
>
> Aneesh V (7):
>   misc: ddr: add LPDDR2 data from JESD209-2
>   misc: emif: add register definitions for EMIF
>   misc: emif: add basic infrastructure for EMIF driver
>   misc: emif: handle frequency and voltage change events
>   misc: emif: add interrupt and temperature handling
>   misc: emif: add one-time settings
>   misc: emif: add debugfs entries for emif
>
>  Documentation/misc-devices/ti-emif.txt  |   58 ++
>  drivers/misc/Kconfig                    |   12 +
>  drivers/misc/Makefile                   |    1 +
>  drivers/misc/emif.c                     | 1670
> +++++++++++++++++++++++++++++++
>  drivers/misc/emif.h                     |  589 +++++++++++
>  include/linux/platform_data/emif_plat.h |  128 +++
>  include/misc/jedec_ddr.h                |  175 ++++
>  lib/Kconfig                             |    8 +
>  lib/Makefile                            |    2 +
>  lib/jedec_ddr_data.c                    |  135 +++
>  10 files changed, 2778 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/misc-devices/ti-emif.txt
>  create mode 100644 drivers/misc/emif.c
>  create mode 100644 drivers/misc/emif.h
>  create mode 100644 include/linux/platform_data/emif_plat.h
>  create mode 100644 include/misc/jedec_ddr.h
>  create mode 100644 lib/jedec_ddr_data.c
>
>
> _______________________________________________
> 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] 84+ messages in thread

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-03-17  6:10   ` Kyungmin Park
  0 siblings, 0 replies; 84+ messages in thread
From: Kyungmin Park @ 2012-03-17  6:10 UTC (permalink / raw)
  To: Aneesh V
  Cc: Greg KH, 함명주,
	linux-omap, linux-kernel, linux-arm-kernel

Hi,

On 3/17/12, Aneesh V <aneesh@ti.com> wrote:
> Add a driver for the EMIF SDRAM controller used in TI SoCs
>
> EMIF is an SDRAM controller that supports, based on its revision,
> one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
> for LPDDR2.
>
> The driver supports the following features:
> - Calculates the DDR AC timing parameters to be set in EMIF
>   registers using data from the device data-sheets and based
>   on the DDR frequency. If data from data-sheets is not available
>   default timing values from the JEDEC spec are used. These
>   will be safe, but not necessarily optimal
> - API for changing timings during DVFS or at boot-up
> - Temperature alert configuration and handling of temperature
>   alerts, if any for LPDDR2 devices
>   * temperature alert is based on periodic polling of MR4 mode
>     register in DDR devices automatically performed by hardware
>   * timings are de-rated and brought back to nominal when
>     temperature raises and falls respectively
> - Cache of calculated register values to avoid re-calculating
>   them
>
> The driver will need some minor updates when it is eventually
> integrated with Dynamic Voltage and Frequency Scaling (DVFS).
> This can not be done now as DVFS support is not available in
> the mainline yet.
Do you see the devfreq? it's designed for non-cpu device frequency.
It's role is similar with cpufreq.

Now samsung exynos uses devfreq for DRAM bus frequency.

Thank you,
Kyungmin Park
>
> Discussions with Santosh Shilimkar <santosh.shilimkar@ti.com>
> were immensely helpful in shaping up the interfaces. Vibhore Vardhan
> <vvardhan@gmail.com> did the initial code snippet for thermal
> handling.
>
> Testing:
> - The driver is tested on OMAP4430 SDP.
> - The driver in a slightly adapted form is also tested on OMAP5.
> - Since mainline kernel doesn't have DVFS support yet,
>   testing was done using a test module.
> - Temperature alert handling was tested with simulated interrupts
>   and faked temperature values as testing all cases in real-life
>   scenarios is difficult.
> - Tested the driver as a module
>
> Cc: Greg KH <greg@kroah.com>
>
> v4:
> - Converted instances of EXPORT_SYMBOL to EXPORT_SYMBOL_GPL
> - Removed un-necessary "#ifndef __ASSEMBLY__'
> - Minor formatting fix
>
> v2:
> - Fixed a bug found in the implementation of errata i728
>   workaround
> - Fixed the value of frequency printed in debugfs
> - Dropped the hwmod patch as Paul has already posted a
>   a hwmod series [1] that adds hwmod for EMIF
> - Converted instances of __init to __init_or_module
>
> [1] http://thread.gmane.org/gmane.linux.ports.arm.omap/72855
>
> Aneesh V (7):
>   misc: ddr: add LPDDR2 data from JESD209-2
>   misc: emif: add register definitions for EMIF
>   misc: emif: add basic infrastructure for EMIF driver
>   misc: emif: handle frequency and voltage change events
>   misc: emif: add interrupt and temperature handling
>   misc: emif: add one-time settings
>   misc: emif: add debugfs entries for emif
>
>  Documentation/misc-devices/ti-emif.txt  |   58 ++
>  drivers/misc/Kconfig                    |   12 +
>  drivers/misc/Makefile                   |    1 +
>  drivers/misc/emif.c                     | 1670
> +++++++++++++++++++++++++++++++
>  drivers/misc/emif.h                     |  589 +++++++++++
>  include/linux/platform_data/emif_plat.h |  128 +++
>  include/misc/jedec_ddr.h                |  175 ++++
>  lib/Kconfig                             |    8 +
>  lib/Makefile                            |    2 +
>  lib/jedec_ddr_data.c                    |  135 +++
>  10 files changed, 2778 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/misc-devices/ti-emif.txt
>  create mode 100644 drivers/misc/emif.c
>  create mode 100644 drivers/misc/emif.h
>  create mode 100644 include/linux/platform_data/emif_plat.h
>  create mode 100644 include/misc/jedec_ddr.h
>  create mode 100644 lib/jedec_ddr_data.c
>
>
> _______________________________________________
> 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] 84+ messages in thread

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-03-17  6:10   ` Kyungmin Park
  0 siblings, 0 replies; 84+ messages in thread
From: Kyungmin Park @ 2012-03-17  6:10 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 3/17/12, Aneesh V <aneesh@ti.com> wrote:
> Add a driver for the EMIF SDRAM controller used in TI SoCs
>
> EMIF is an SDRAM controller that supports, based on its revision,
> one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
> for LPDDR2.
>
> The driver supports the following features:
> - Calculates the DDR AC timing parameters to be set in EMIF
>   registers using data from the device data-sheets and based
>   on the DDR frequency. If data from data-sheets is not available
>   default timing values from the JEDEC spec are used. These
>   will be safe, but not necessarily optimal
> - API for changing timings during DVFS or at boot-up
> - Temperature alert configuration and handling of temperature
>   alerts, if any for LPDDR2 devices
>   * temperature alert is based on periodic polling of MR4 mode
>     register in DDR devices automatically performed by hardware
>   * timings are de-rated and brought back to nominal when
>     temperature raises and falls respectively
> - Cache of calculated register values to avoid re-calculating
>   them
>
> The driver will need some minor updates when it is eventually
> integrated with Dynamic Voltage and Frequency Scaling (DVFS).
> This can not be done now as DVFS support is not available in
> the mainline yet.
Do you see the devfreq? it's designed for non-cpu device frequency.
It's role is similar with cpufreq.

Now samsung exynos uses devfreq for DRAM bus frequency.

Thank you,
Kyungmin Park
>
> Discussions with Santosh Shilimkar <santosh.shilimkar@ti.com>
> were immensely helpful in shaping up the interfaces. Vibhore Vardhan
> <vvardhan@gmail.com> did the initial code snippet for thermal
> handling.
>
> Testing:
> - The driver is tested on OMAP4430 SDP.
> - The driver in a slightly adapted form is also tested on OMAP5.
> - Since mainline kernel doesn't have DVFS support yet,
>   testing was done using a test module.
> - Temperature alert handling was tested with simulated interrupts
>   and faked temperature values as testing all cases in real-life
>   scenarios is difficult.
> - Tested the driver as a module
>
> Cc: Greg KH <greg@kroah.com>
>
> v4:
> - Converted instances of EXPORT_SYMBOL to EXPORT_SYMBOL_GPL
> - Removed un-necessary "#ifndef __ASSEMBLY__'
> - Minor formatting fix
>
> v2:
> - Fixed a bug found in the implementation of errata i728
>   workaround
> - Fixed the value of frequency printed in debugfs
> - Dropped the hwmod patch as Paul has already posted a
>   a hwmod series [1] that adds hwmod for EMIF
> - Converted instances of __init to __init_or_module
>
> [1] http://thread.gmane.org/gmane.linux.ports.arm.omap/72855
>
> Aneesh V (7):
>   misc: ddr: add LPDDR2 data from JESD209-2
>   misc: emif: add register definitions for EMIF
>   misc: emif: add basic infrastructure for EMIF driver
>   misc: emif: handle frequency and voltage change events
>   misc: emif: add interrupt and temperature handling
>   misc: emif: add one-time settings
>   misc: emif: add debugfs entries for emif
>
>  Documentation/misc-devices/ti-emif.txt  |   58 ++
>  drivers/misc/Kconfig                    |   12 +
>  drivers/misc/Makefile                   |    1 +
>  drivers/misc/emif.c                     | 1670
> +++++++++++++++++++++++++++++++
>  drivers/misc/emif.h                     |  589 +++++++++++
>  include/linux/platform_data/emif_plat.h |  128 +++
>  include/misc/jedec_ddr.h                |  175 ++++
>  lib/Kconfig                             |    8 +
>  lib/Makefile                            |    2 +
>  lib/jedec_ddr_data.c                    |  135 +++
>  10 files changed, 2778 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/misc-devices/ti-emif.txt
>  create mode 100644 drivers/misc/emif.c
>  create mode 100644 drivers/misc/emif.h
>  create mode 100644 include/linux/platform_data/emif_plat.h
>  create mode 100644 include/misc/jedec_ddr.h
>  create mode 100644 lib/jedec_ddr_data.c
>
>
> _______________________________________________
> 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] 84+ messages in thread

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-03-16 21:51 ` Aneesh V
@ 2012-04-12  2:44   ` Paul Walmsley
  -1 siblings, 0 replies; 84+ messages in thread
From: Paul Walmsley @ 2012-04-12  2:44 UTC (permalink / raw)
  To: Aneesh V, Greg KH
  Cc: linux-kernel, linux-arm-kernel, linux-omap, mgreer, msalter

Cc Mark Greer, Mark Salter

Hi Greg, Aneesh,

On Sat, 17 Mar 2012, Aneesh V wrote:

> Add a driver for the EMIF SDRAM controller used in TI SoCs
> 
> EMIF is an SDRAM controller that supports, based on its revision,
> one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
> for LPDDR2.

Just checking to see what the current state of this series is.  Greg, are 
you considering this for merging, or are there remaining issues?  Aneesh, 
do you have any remaining issues to resolve with this set?

This is useful not only for OMAP4 and AM3517/3505, but also will probably 
be useful for the C6x chips that Mark Salter is working on.


- Paul

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12  2:44   ` Paul Walmsley
  0 siblings, 0 replies; 84+ messages in thread
From: Paul Walmsley @ 2012-04-12  2:44 UTC (permalink / raw)
  To: linux-arm-kernel

Cc Mark Greer, Mark Salter

Hi Greg, Aneesh,

On Sat, 17 Mar 2012, Aneesh V wrote:

> Add a driver for the EMIF SDRAM controller used in TI SoCs
> 
> EMIF is an SDRAM controller that supports, based on its revision,
> one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
> for LPDDR2.

Just checking to see what the current state of this series is.  Greg, are 
you considering this for merging, or are there remaining issues?  Aneesh, 
do you have any remaining issues to resolve with this set?

This is useful not only for OMAP4 and AM3517/3505, but also will probably 
be useful for the C6x chips that Mark Salter is working on.


- Paul

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-12  2:44   ` Paul Walmsley
  (?)
@ 2012-04-12  2:57     ` Aneesh V
  -1 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-04-12  2:57 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: Greg KH, linux-kernel, linux-arm-kernel, linux-omap, mgreer,
	msalter, santosh.shilimkar

Hi Paul,

On 04/11/2012 07:44 PM, Paul Walmsley wrote:
> Cc Mark Greer, Mark Salter
>
> Hi Greg, Aneesh,
>
> On Sat, 17 Mar 2012, Aneesh V wrote:
>
>> Add a driver for the EMIF SDRAM controller used in TI SoCs
>>
>> EMIF is an SDRAM controller that supports, based on its revision,
>> one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
>> for LPDDR2.
>
> Just checking to see what the current state of this series is.  Greg, are
> you considering this for merging, or are there remaining issues?  Aneesh,
> do you have any remaining issues to resolve with this set?

No. I don't have anything remaining. It's just that I was on vacation
for a while and couldn't find time for this after that. If Greg is fine
with this, I can rebase it and send one final version with
Reviewed-By's from Santosh and Benoit.

thanks,
Aneesh

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12  2:57     ` Aneesh V
  0 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-04-12  2:57 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: Greg KH, linux-kernel, linux-arm-kernel, linux-omap, mgreer,
	msalter, santosh.shilimkar

Hi Paul,

On 04/11/2012 07:44 PM, Paul Walmsley wrote:
> Cc Mark Greer, Mark Salter
>
> Hi Greg, Aneesh,
>
> On Sat, 17 Mar 2012, Aneesh V wrote:
>
>> Add a driver for the EMIF SDRAM controller used in TI SoCs
>>
>> EMIF is an SDRAM controller that supports, based on its revision,
>> one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
>> for LPDDR2.
>
> Just checking to see what the current state of this series is.  Greg, are
> you considering this for merging, or are there remaining issues?  Aneesh,
> do you have any remaining issues to resolve with this set?

No. I don't have anything remaining. It's just that I was on vacation
for a while and couldn't find time for this after that. If Greg is fine
with this, I can rebase it and send one final version with
Reviewed-By's from Santosh and Benoit.

thanks,
Aneesh

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12  2:57     ` Aneesh V
  0 siblings, 0 replies; 84+ messages in thread
From: Aneesh V @ 2012-04-12  2:57 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Paul,

On 04/11/2012 07:44 PM, Paul Walmsley wrote:
> Cc Mark Greer, Mark Salter
>
> Hi Greg, Aneesh,
>
> On Sat, 17 Mar 2012, Aneesh V wrote:
>
>> Add a driver for the EMIF SDRAM controller used in TI SoCs
>>
>> EMIF is an SDRAM controller that supports, based on its revision,
>> one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
>> for LPDDR2.
>
> Just checking to see what the current state of this series is.  Greg, are
> you considering this for merging, or are there remaining issues?  Aneesh,
> do you have any remaining issues to resolve with this set?

No. I don't have anything remaining. It's just that I was on vacation
for a while and couldn't find time for this after that. If Greg is fine
with this, I can rebase it and send one final version with
Reviewed-By's from Santosh and Benoit.

thanks,
Aneesh

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-12  2:44   ` Paul Walmsley
@ 2012-04-12  3:00     ` Greg KH
  -1 siblings, 0 replies; 84+ messages in thread
From: Greg KH @ 2012-04-12  3:00 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: Aneesh V, linux-kernel, linux-arm-kernel, linux-omap, mgreer, msalter

On Wed, Apr 11, 2012 at 08:44:39PM -0600, Paul Walmsley wrote:
> Cc Mark Greer, Mark Salter
> 
> Hi Greg, Aneesh,
> 
> On Sat, 17 Mar 2012, Aneesh V wrote:
> 
> > Add a driver for the EMIF SDRAM controller used in TI SoCs
> > 
> > EMIF is an SDRAM controller that supports, based on its revision,
> > one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
> > for LPDDR2.
> 
> Just checking to see what the current state of this series is.  Greg, are 
> you considering this for merging, or are there remaining issues?  Aneesh, 
> do you have any remaining issues to resolve with this set?

What about the review comment about devfreq?

> This is useful not only for OMAP4 and AM3517/3505, but also will probably 
> be useful for the C6x chips that Mark Salter is working on.

It's still in my "to-review" queue, that I'm slowly making my way
through.  So it's not lost, but I would like to get the devfreq
interface question cleared up first.

thanks,

greg k-h

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12  3:00     ` Greg KH
  0 siblings, 0 replies; 84+ messages in thread
From: Greg KH @ 2012-04-12  3:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Apr 11, 2012 at 08:44:39PM -0600, Paul Walmsley wrote:
> Cc Mark Greer, Mark Salter
> 
> Hi Greg, Aneesh,
> 
> On Sat, 17 Mar 2012, Aneesh V wrote:
> 
> > Add a driver for the EMIF SDRAM controller used in TI SoCs
> > 
> > EMIF is an SDRAM controller that supports, based on its revision,
> > one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
> > for LPDDR2.
> 
> Just checking to see what the current state of this series is.  Greg, are 
> you considering this for merging, or are there remaining issues?  Aneesh, 
> do you have any remaining issues to resolve with this set?

What about the review comment about devfreq?

> This is useful not only for OMAP4 and AM3517/3505, but also will probably 
> be useful for the C6x chips that Mark Salter is working on.

It's still in my "to-review" queue, that I'm slowly making my way
through.  So it's not lost, but I would like to get the devfreq
interface question cleared up first.

thanks,

greg k-h

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-12  3:00     ` Greg KH
@ 2012-04-12  3:12       ` Paul Walmsley
  -1 siblings, 0 replies; 84+ messages in thread
From: Paul Walmsley @ 2012-04-12  3:12 UTC (permalink / raw)
  To: Aneesh V
  Cc: Greg KH, linux-kernel, linux-arm-kernel, linux-omap, mgreer, msalter

thanks for the response Greg,

Hi Aneesh,

On Wed, 11 Apr 2012, Greg KH wrote:

> On Wed, Apr 11, 2012 at 08:44:39PM -0600, Paul Walmsley wrote:
> > On Sat, 17 Mar 2012, Aneesh V wrote:
> > 
> > > Add a driver for the EMIF SDRAM controller used in TI SoCs
> > > 
> > > EMIF is an SDRAM controller that supports, based on its revision,
> > > one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
> > > for LPDDR2.
> > 
> > Just checking to see what the current state of this series is.  Greg, are 
> > you considering this for merging, or are there remaining issues?  Aneesh, 
> > do you have any remaining issues to resolve with this set?
> 
> What about the review comment about devfreq?
> 
> > This is useful not only for OMAP4 and AM3517/3505, but also will probably 
> > be useful for the C6x chips that Mark Salter is working on.
> 
> It's still in my "to-review" queue, that I'm slowly making my way
> through.  So it's not lost, but I would like to get the devfreq
> interface question cleared up first.

Aneesh, care to address the devfreq comments? 

I haven't looked at the series closely, so unfortunately I'm not presently 
in a position to comment.


- Paul

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12  3:12       ` Paul Walmsley
  0 siblings, 0 replies; 84+ messages in thread
From: Paul Walmsley @ 2012-04-12  3:12 UTC (permalink / raw)
  To: linux-arm-kernel

thanks for the response Greg,

Hi Aneesh,

On Wed, 11 Apr 2012, Greg KH wrote:

> On Wed, Apr 11, 2012 at 08:44:39PM -0600, Paul Walmsley wrote:
> > On Sat, 17 Mar 2012, Aneesh V wrote:
> > 
> > > Add a driver for the EMIF SDRAM controller used in TI SoCs
> > > 
> > > EMIF is an SDRAM controller that supports, based on its revision,
> > > one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
> > > for LPDDR2.
> > 
> > Just checking to see what the current state of this series is.  Greg, are 
> > you considering this for merging, or are there remaining issues?  Aneesh, 
> > do you have any remaining issues to resolve with this set?
> 
> What about the review comment about devfreq?
> 
> > This is useful not only for OMAP4 and AM3517/3505, but also will probably 
> > be useful for the C6x chips that Mark Salter is working on.
> 
> It's still in my "to-review" queue, that I'm slowly making my way
> through.  So it's not lost, but I would like to get the devfreq
> interface question cleared up first.

Aneesh, care to address the devfreq comments? 

I haven't looked at the series closely, so unfortunately I'm not presently 
in a position to comment.


- Paul

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-12  3:00     ` Greg KH
@ 2012-04-12  6:47       ` Santosh Shilimkar
  -1 siblings, 0 replies; 84+ messages in thread
From: Santosh Shilimkar @ 2012-04-12  6:47 UTC (permalink / raw)
  To: Greg KH
  Cc: Paul Walmsley, Aneesh V, linux-kernel, linux-arm-kernel,
	linux-omap, mgreer, msalter

On Thursday 12 April 2012 08:30 AM, Greg KH wrote:
> On Wed, Apr 11, 2012 at 08:44:39PM -0600, Paul Walmsley wrote:
>> Cc Mark Greer, Mark Salter
>>
>> Hi Greg, Aneesh,
>>
>> On Sat, 17 Mar 2012, Aneesh V wrote:
>>
>>> Add a driver for the EMIF SDRAM controller used in TI SoCs
>>>
>>> EMIF is an SDRAM controller that supports, based on its revision,
>>> one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
>>> for LPDDR2.
>>
>> Just checking to see what the current state of this series is.  Greg, are 
>> you considering this for merging, or are there remaining issues?  Aneesh, 
>> do you have any remaining issues to resolve with this set?
> 
> What about the review comment about devfreq?
>
Devfreq is not suitable for this driver. I already replied on this
thread [1]

Acting on frequency change is just one function of the controller
driver and that too need not bed to attached with devfreq. The driver
has features like temperature handling as per JDEC specs, active power
managements modes, system wide suspend power management like self
refresh and also configuration which can help memory hotplug for
power savings and initialising the DDR timings to avoid boot-loader
defaults.The controller IP works in conjunction with PRCM (OMAP Power
IP) block to achieve some of this functionality.

I was hoping that we will have some thing like drivers/memory/*
but since it doesn't exist, we used drivers/misc.

Regards
Santosh
[1] https://lkml.org/lkml/2012/3/19/178

>> This is useful not only for OMAP4 and AM3517/3505, but also will probably 
>> be useful for the C6x chips that Mark Salter is working on.
> 
> It's still in my "to-review" queue, that I'm slowly making my way
> through.  So it's not lost, but I would like to get the devfreq
> interface question cleared up first.
> 
Let us know if you need more clarification on devfreq part.
Thanks for looking into it.

Regards
Santosh

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12  6:47       ` Santosh Shilimkar
  0 siblings, 0 replies; 84+ messages in thread
From: Santosh Shilimkar @ 2012-04-12  6:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 12 April 2012 08:30 AM, Greg KH wrote:
> On Wed, Apr 11, 2012 at 08:44:39PM -0600, Paul Walmsley wrote:
>> Cc Mark Greer, Mark Salter
>>
>> Hi Greg, Aneesh,
>>
>> On Sat, 17 Mar 2012, Aneesh V wrote:
>>
>>> Add a driver for the EMIF SDRAM controller used in TI SoCs
>>>
>>> EMIF is an SDRAM controller that supports, based on its revision,
>>> one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
>>> for LPDDR2.
>>
>> Just checking to see what the current state of this series is.  Greg, are 
>> you considering this for merging, or are there remaining issues?  Aneesh, 
>> do you have any remaining issues to resolve with this set?
> 
> What about the review comment about devfreq?
>
Devfreq is not suitable for this driver. I already replied on this
thread [1]

Acting on frequency change is just one function of the controller
driver and that too need not bed to attached with devfreq. The driver
has features like temperature handling as per JDEC specs, active power
managements modes, system wide suspend power management like self
refresh and also configuration which can help memory hotplug for
power savings and initialising the DDR timings to avoid boot-loader
defaults.The controller IP works in conjunction with PRCM (OMAP Power
IP) block to achieve some of this functionality.

I was hoping that we will have some thing like drivers/memory/*
but since it doesn't exist, we used drivers/misc.

Regards
Santosh
[1] https://lkml.org/lkml/2012/3/19/178

>> This is useful not only for OMAP4 and AM3517/3505, but also will probably 
>> be useful for the C6x chips that Mark Salter is working on.
> 
> It's still in my "to-review" queue, that I'm slowly making my way
> through.  So it's not lost, but I would like to get the devfreq
> interface question cleared up first.
> 
Let us know if you need more clarification on devfreq part.
Thanks for looking into it.

Regards
Santosh

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-12  6:47       ` Santosh Shilimkar
@ 2012-04-12 13:10         ` Greg KH
  -1 siblings, 0 replies; 84+ messages in thread
From: Greg KH @ 2012-04-12 13:10 UTC (permalink / raw)
  To: Santosh Shilimkar
  Cc: Paul Walmsley, Aneesh V, linux-kernel, linux-arm-kernel,
	linux-omap, mgreer, msalter

On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
> I was hoping that we will have some thing like drivers/memory/*
> but since it doesn't exist, we used drivers/misc.

Why not create it?  I have no objection to that, it makes it more
obvious as to what this really is.

greg k-h

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 13:10         ` Greg KH
  0 siblings, 0 replies; 84+ messages in thread
From: Greg KH @ 2012-04-12 13:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
> I was hoping that we will have some thing like drivers/memory/*
> but since it doesn't exist, we used drivers/misc.

Why not create it?  I have no objection to that, it makes it more
obvious as to what this really is.

greg k-h

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

* RE: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-12 13:10         ` Greg KH
  (?)
@ 2012-04-12 13:34           ` Mohammed, Afzal
  -1 siblings, 0 replies; 84+ messages in thread
From: Mohammed, Afzal @ 2012-04-12 13:34 UTC (permalink / raw)
  To: Greg KH, Shilimkar, Santosh
  Cc: Paul Walmsley, V, Aneesh, linux-kernel, linux-arm-kernel,
	linux-omap, mgreer, msalter

Hi Greg,

On Thu, Apr 12, 2012 at 18:40:45, Greg KH wrote:
> On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
> > I was hoping that we will have some thing like drivers/memory/*
> > but since it doesn't exist, we used drivers/misc.
> 
> Why not create it?  I have no objection to that, it makes it more
> obvious as to what this really is.

There is another memory controller used in a few TI SoCs,
namely GPMC [1], do you prefer having it too there.

As of now it is not a driver, platform code handles GPMC, a patch
series for converting it into a driver (but still residing in
platform folder) was sent a few days back [2,3].


Regards
Afzal

[1]
GPMC (General Purpose Memory Controller) in brief:
GPMC is an unified memory controller dedicated to interfacing external
memory devices like
 Asynchronous SRAM like memories and application specific integrated circuit devices.
 Asynchronous, synchronous, and page mode burst NOR flash devices NAND flash
 Pseudo-SRAM devices

GPMC has to be configured as required by timings of the connected
peripheral. It needs to be configured only initially. Once it is
configured it can be used to handle different protocols like NAND,
NOR. Various kinds of devices like ethernet, uart, usb, fpga etc
can work using GPMC interface. GPMC has a seperate additional
functionality of NAND handling

[2] https://lkml.org/lkml/2012/4/5/210
[3] https://lkml.org/lkml/2012/4/5/212



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

* RE: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 13:34           ` Mohammed, Afzal
  0 siblings, 0 replies; 84+ messages in thread
From: Mohammed, Afzal @ 2012-04-12 13:34 UTC (permalink / raw)
  To: Greg KH, Shilimkar, Santosh
  Cc: Paul Walmsley, V, Aneesh, linux-kernel, linux-arm-kernel,
	linux-omap, mgreer, msalter

Hi Greg,

On Thu, Apr 12, 2012 at 18:40:45, Greg KH wrote:
> On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
> > I was hoping that we will have some thing like drivers/memory/*
> > but since it doesn't exist, we used drivers/misc.
> 
> Why not create it?  I have no objection to that, it makes it more
> obvious as to what this really is.

There is another memory controller used in a few TI SoCs,
namely GPMC [1], do you prefer having it too there.

As of now it is not a driver, platform code handles GPMC, a patch
series for converting it into a driver (but still residing in
platform folder) was sent a few days back [2,3].


Regards
Afzal

[1]
GPMC (General Purpose Memory Controller) in brief:
GPMC is an unified memory controller dedicated to interfacing external
memory devices like
 Asynchronous SRAM like memories and application specific integrated circuit devices.
 Asynchronous, synchronous, and page mode burst NOR flash devices NAND flash
 Pseudo-SRAM devices

GPMC has to be configured as required by timings of the connected
peripheral. It needs to be configured only initially. Once it is
configured it can be used to handle different protocols like NAND,
NOR. Various kinds of devices like ethernet, uart, usb, fpga etc
can work using GPMC interface. GPMC has a seperate additional
functionality of NAND handling

[2] https://lkml.org/lkml/2012/4/5/210
[3] https://lkml.org/lkml/2012/4/5/212

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 13:34           ` Mohammed, Afzal
  0 siblings, 0 replies; 84+ messages in thread
From: Mohammed, Afzal @ 2012-04-12 13:34 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Greg,

On Thu, Apr 12, 2012 at 18:40:45, Greg KH wrote:
> On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
> > I was hoping that we will have some thing like drivers/memory/*
> > but since it doesn't exist, we used drivers/misc.
> 
> Why not create it?  I have no objection to that, it makes it more
> obvious as to what this really is.

There is another memory controller used in a few TI SoCs,
namely GPMC [1], do you prefer having it too there.

As of now it is not a driver, platform code handles GPMC, a patch
series for converting it into a driver (but still residing in
platform folder) was sent a few days back [2,3].


Regards
Afzal

[1]
GPMC (General Purpose Memory Controller) in brief:
GPMC is an unified memory controller dedicated to interfacing external
memory devices like
 Asynchronous SRAM like memories and application specific integrated circuit devices.
 Asynchronous, synchronous, and page mode burst NOR flash devices NAND flash
 Pseudo-SRAM devices

GPMC has to be configured as required by timings of the connected
peripheral. It needs to be configured only initially. Once it is
configured it can be used to handle different protocols like NAND,
NOR. Various kinds of devices like ethernet, uart, usb, fpga etc
can work using GPMC interface. GPMC has a seperate additional
functionality of NAND handling

[2] https://lkml.org/lkml/2012/4/5/210
[3] https://lkml.org/lkml/2012/4/5/212

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-12 13:34           ` Mohammed, Afzal
  (?)
@ 2012-04-12 14:10             ` Greg KH
  -1 siblings, 0 replies; 84+ messages in thread
From: Greg KH @ 2012-04-12 14:10 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: Shilimkar, Santosh, Paul Walmsley, V, Aneesh, linux-kernel,
	linux-arm-kernel, linux-omap, mgreer, msalter

On Thu, Apr 12, 2012 at 01:34:15PM +0000, Mohammed, Afzal wrote:
> Hi Greg,
> 
> On Thu, Apr 12, 2012 at 18:40:45, Greg KH wrote:
> > On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
> > > I was hoping that we will have some thing like drivers/memory/*
> > > but since it doesn't exist, we used drivers/misc.
> > 
> > Why not create it?  I have no objection to that, it makes it more
> > obvious as to what this really is.
> 
> There is another memory controller used in a few TI SoCs,
> namely GPMC [1], do you prefer having it too there.

Sure, why not?

> As of now it is not a driver, platform code handles GPMC, a patch
> series for converting it into a driver (but still residing in
> platform folder) was sent a few days back [2,3].

People are moving things out of the platform folder, so drivers/memory
makes sense.

thanks,

greg k-h

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 14:10             ` Greg KH
  0 siblings, 0 replies; 84+ messages in thread
From: Greg KH @ 2012-04-12 14:10 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: Shilimkar, Santosh, Paul Walmsley, V, Aneesh, linux-kernel,
	linux-arm-kernel, linux-omap, mgreer, msalter

On Thu, Apr 12, 2012 at 01:34:15PM +0000, Mohammed, Afzal wrote:
> Hi Greg,
> 
> On Thu, Apr 12, 2012 at 18:40:45, Greg KH wrote:
> > On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
> > > I was hoping that we will have some thing like drivers/memory/*
> > > but since it doesn't exist, we used drivers/misc.
> > 
> > Why not create it?  I have no objection to that, it makes it more
> > obvious as to what this really is.
> 
> There is another memory controller used in a few TI SoCs,
> namely GPMC [1], do you prefer having it too there.

Sure, why not?

> As of now it is not a driver, platform code handles GPMC, a patch
> series for converting it into a driver (but still residing in
> platform folder) was sent a few days back [2,3].

People are moving things out of the platform folder, so drivers/memory
makes sense.

thanks,

greg k-h

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 14:10             ` Greg KH
  0 siblings, 0 replies; 84+ messages in thread
From: Greg KH @ 2012-04-12 14:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 12, 2012 at 01:34:15PM +0000, Mohammed, Afzal wrote:
> Hi Greg,
> 
> On Thu, Apr 12, 2012 at 18:40:45, Greg KH wrote:
> > On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
> > > I was hoping that we will have some thing like drivers/memory/*
> > > but since it doesn't exist, we used drivers/misc.
> > 
> > Why not create it?  I have no objection to that, it makes it more
> > obvious as to what this really is.
> 
> There is another memory controller used in a few TI SoCs,
> namely GPMC [1], do you prefer having it too there.

Sure, why not?

> As of now it is not a driver, platform code handles GPMC, a patch
> series for converting it into a driver (but still residing in
> platform folder) was sent a few days back [2,3].

People are moving things out of the platform folder, so drivers/memory
makes sense.

thanks,

greg k-h

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-12 13:10         ` Greg KH
@ 2012-04-12 14:14           ` Shilimkar, Santosh
  -1 siblings, 0 replies; 84+ messages in thread
From: Shilimkar, Santosh @ 2012-04-12 14:14 UTC (permalink / raw)
  To: Greg KH
  Cc: Paul Walmsley, Aneesh V, linux-kernel, linux-arm-kernel,
	linux-omap, mgreer, msalter

On Thu, Apr 12, 2012 at 6:40 PM, Greg KH <greg@kroah.com> wrote:
> On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
>> I was hoping that we will have some thing like drivers/memory/*
>> but since it doesn't exist, we used drivers/misc.
>
> Why not create it?  I have no objection to that, it makes it more
> obvious as to what this really is.
>
Looks like I should have this question earlier.
EMIF driver is perfect candidate for drivers/memory/

Thanks Greg for suggestion. We will go ahead and
create drivers/memory and have EMIF drivers there.

Regards
Santosh

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 14:14           ` Shilimkar, Santosh
  0 siblings, 0 replies; 84+ messages in thread
From: Shilimkar, Santosh @ 2012-04-12 14:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 12, 2012 at 6:40 PM, Greg KH <greg@kroah.com> wrote:
> On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
>> I was hoping that we will have some thing like drivers/memory/*
>> but since it doesn't exist, we used drivers/misc.
>
> Why not create it? ?I have no objection to that, it makes it more
> obvious as to what this really is.
>
Looks like I should have this question earlier.
EMIF driver is perfect candidate for drivers/memory/

Thanks Greg for suggestion. We will go ahead and
create drivers/memory and have EMIF drivers there.

Regards
Santosh

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

* RE: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-12 14:10             ` Greg KH
  (?)
@ 2012-04-12 14:15               ` Mohammed, Afzal
  -1 siblings, 0 replies; 84+ messages in thread
From: Mohammed, Afzal @ 2012-04-12 14:15 UTC (permalink / raw)
  To: Greg KH
  Cc: Shilimkar, Santosh, Paul Walmsley, V, Aneesh, linux-kernel,
	linux-arm-kernel, linux-omap, mgreer, msalter

Hi Greg,

On Thu, Apr 12, 2012 at 19:40:50, Greg KH wrote:
> > There is another memory controller used in a few TI SoCs,
> > namely GPMC [1], do you prefer having it too there.
> 
> Sure, why not?

Thanks a lot, we were struggling to find a suitable location for the driver.

Regards
Afzal 

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

* RE: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 14:15               ` Mohammed, Afzal
  0 siblings, 0 replies; 84+ messages in thread
From: Mohammed, Afzal @ 2012-04-12 14:15 UTC (permalink / raw)
  To: Greg KH
  Cc: Shilimkar, Santosh, Paul Walmsley, V, Aneesh, linux-kernel,
	linux-arm-kernel, linux-omap, mgreer, msalter

Hi Greg,

On Thu, Apr 12, 2012 at 19:40:50, Greg KH wrote:
> > There is another memory controller used in a few TI SoCs,
> > namely GPMC [1], do you prefer having it too there.
> 
> Sure, why not?

Thanks a lot, we were struggling to find a suitable location for the driver.

Regards
Afzal 

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 14:15               ` Mohammed, Afzal
  0 siblings, 0 replies; 84+ messages in thread
From: Mohammed, Afzal @ 2012-04-12 14:15 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Greg,

On Thu, Apr 12, 2012 at 19:40:50, Greg KH wrote:
> > There is another memory controller used in a few TI SoCs,
> > namely GPMC [1], do you prefer having it too there.
> 
> Sure, why not?

Thanks a lot, we were struggling to find a suitable location for the driver.

Regards
Afzal 

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-12 13:34           ` Mohammed, Afzal
  (?)
@ 2012-04-12 14:21             ` Kevin Hilman
  -1 siblings, 0 replies; 84+ messages in thread
From: Kevin Hilman @ 2012-04-12 14:21 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: Greg KH, Shilimkar, Santosh, Paul Walmsley, V, Aneesh,
	linux-kernel, linux-arm-kernel, linux-omap, mgreer, msalter

"Mohammed, Afzal" <afzal@ti.com> writes:

> Hi Greg,
>
> On Thu, Apr 12, 2012 at 18:40:45, Greg KH wrote:
>> On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
>> > I was hoping that we will have some thing like drivers/memory/*
>> > but since it doesn't exist, we used drivers/misc.
>> 
>> Why not create it?  I have no objection to that, it makes it more
>> obvious as to what this really is.
>
> There is another memory controller used in a few TI SoCs,
> namely GPMC [1], do you prefer having it too there.
>
> As of now it is not a driver, platform code handles GPMC, a patch
> series for converting it into a driver (but still residing in
> platform folder) was sent a few days back [2,3].

IMO, wherever EMIF ends up, GPMC should as well.

Kevin


> [1]
> GPMC (General Purpose Memory Controller) in brief:
> GPMC is an unified memory controller dedicated to interfacing external
> memory devices like
>  Asynchronous SRAM like memories and application specific integrated circuit devices.
>  Asynchronous, synchronous, and page mode burst NOR flash devices NAND flash
>  Pseudo-SRAM devices
>
> GPMC has to be configured as required by timings of the connected
> peripheral. It needs to be configured only initially. Once it is
> configured it can be used to handle different protocols like NAND,
> NOR. Various kinds of devices like ethernet, uart, usb, fpga etc
> can work using GPMC interface. GPMC has a seperate additional
> functionality of NAND handling
>
> [2] https://lkml.org/lkml/2012/4/5/210
> [3] https://lkml.org/lkml/2012/4/5/212
>
>
> --
> 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] 84+ messages in thread

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 14:21             ` Kevin Hilman
  0 siblings, 0 replies; 84+ messages in thread
From: Kevin Hilman @ 2012-04-12 14:21 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: Greg KH, Shilimkar, Santosh, Paul Walmsley, V, Aneesh,
	linux-kernel, linux-arm-kernel, linux-omap, mgreer, msalter

"Mohammed, Afzal" <afzal@ti.com> writes:

> Hi Greg,
>
> On Thu, Apr 12, 2012 at 18:40:45, Greg KH wrote:
>> On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
>> > I was hoping that we will have some thing like drivers/memory/*
>> > but since it doesn't exist, we used drivers/misc.
>> 
>> Why not create it?  I have no objection to that, it makes it more
>> obvious as to what this really is.
>
> There is another memory controller used in a few TI SoCs,
> namely GPMC [1], do you prefer having it too there.
>
> As of now it is not a driver, platform code handles GPMC, a patch
> series for converting it into a driver (but still residing in
> platform folder) was sent a few days back [2,3].

IMO, wherever EMIF ends up, GPMC should as well.

Kevin


> [1]
> GPMC (General Purpose Memory Controller) in brief:
> GPMC is an unified memory controller dedicated to interfacing external
> memory devices like
>  Asynchronous SRAM like memories and application specific integrated circuit devices.
>  Asynchronous, synchronous, and page mode burst NOR flash devices NAND flash
>  Pseudo-SRAM devices
>
> GPMC has to be configured as required by timings of the connected
> peripheral. It needs to be configured only initially. Once it is
> configured it can be used to handle different protocols like NAND,
> NOR. Various kinds of devices like ethernet, uart, usb, fpga etc
> can work using GPMC interface. GPMC has a seperate additional
> functionality of NAND handling
>
> [2] https://lkml.org/lkml/2012/4/5/210
> [3] https://lkml.org/lkml/2012/4/5/212
>
>
> --
> 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] 84+ messages in thread

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 14:21             ` Kevin Hilman
  0 siblings, 0 replies; 84+ messages in thread
From: Kevin Hilman @ 2012-04-12 14:21 UTC (permalink / raw)
  To: linux-arm-kernel

"Mohammed, Afzal" <afzal@ti.com> writes:

> Hi Greg,
>
> On Thu, Apr 12, 2012 at 18:40:45, Greg KH wrote:
>> On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
>> > I was hoping that we will have some thing like drivers/memory/*
>> > but since it doesn't exist, we used drivers/misc.
>> 
>> Why not create it?  I have no objection to that, it makes it more
>> obvious as to what this really is.
>
> There is another memory controller used in a few TI SoCs,
> namely GPMC [1], do you prefer having it too there.
>
> As of now it is not a driver, platform code handles GPMC, a patch
> series for converting it into a driver (but still residing in
> platform folder) was sent a few days back [2,3].

IMO, wherever EMIF ends up, GPMC should as well.

Kevin


> [1]
> GPMC (General Purpose Memory Controller) in brief:
> GPMC is an unified memory controller dedicated to interfacing external
> memory devices like
>  Asynchronous SRAM like memories and application specific integrated circuit devices.
>  Asynchronous, synchronous, and page mode burst NOR flash devices NAND flash
>  Pseudo-SRAM devices
>
> GPMC has to be configured as required by timings of the connected
> peripheral. It needs to be configured only initially. Once it is
> configured it can be used to handle different protocols like NAND,
> NOR. Various kinds of devices like ethernet, uart, usb, fpga etc
> can work using GPMC interface. GPMC has a seperate additional
> functionality of NAND handling
>
> [2] https://lkml.org/lkml/2012/4/5/210
> [3] https://lkml.org/lkml/2012/4/5/212
>
>
> --
> 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] 84+ messages in thread

* RE: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-12 13:34           ` Mohammed, Afzal
  (?)
@ 2012-04-12 17:00             ` Paul Walmsley
  -1 siblings, 0 replies; 84+ messages in thread
From: Paul Walmsley @ 2012-04-12 17:00 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: Greg KH, Shilimkar, Santosh, V, Aneesh, linux-kernel,
	linux-arm-kernel, linux-omap, mgreer, msalter

Hi

On Thu, 12 Apr 2012, Mohammed, Afzal wrote:

> On Thu, Apr 12, 2012 at 18:40:45, Greg KH wrote:
> > On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
> > > I was hoping that we will have some thing like drivers/memory/*
> > > but since it doesn't exist, we used drivers/misc.
> > 
> > Why not create it?  I have no objection to that, it makes it more
> > obvious as to what this really is.
> 
> There is another memory controller used in a few TI SoCs,
> namely GPMC [1], do you prefer having it too there.
> 
> As of now it is not a driver, platform code handles GPMC, a patch
> series for converting it into a driver (but still residing in
> platform folder) was sent a few days back [2,3].

Probably the GPMC driver should go into a slightly different place than 
SDRC/EMIF.  

GPMC is actually a general-purpose parallel bus driver.  It's used to 
interface Ethernet controllers, UARTs, FPGAs, NAND/NOR flash, SRAM, etc.  
It cannot be used to control DRAM, at least not without a separate DRAM 
controller chip.

SDRC/EMIF are both DRAM controllers.  That's all they do.  They can't be 
used to control anything else.  They implement DRAM refresh, etc.

So perhaps something like drivers/memory/dram/ for the SDRAM controllers, 
and maybe drivers/memory/ for the GPMC?


- Paul

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

* RE: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 17:00             ` Paul Walmsley
  0 siblings, 0 replies; 84+ messages in thread
From: Paul Walmsley @ 2012-04-12 17:00 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: Greg KH, Shilimkar, Santosh, V, Aneesh, linux-kernel,
	linux-arm-kernel, linux-omap, mgreer, msalter

Hi

On Thu, 12 Apr 2012, Mohammed, Afzal wrote:

> On Thu, Apr 12, 2012 at 18:40:45, Greg KH wrote:
> > On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
> > > I was hoping that we will have some thing like drivers/memory/*
> > > but since it doesn't exist, we used drivers/misc.
> > 
> > Why not create it?  I have no objection to that, it makes it more
> > obvious as to what this really is.
> 
> There is another memory controller used in a few TI SoCs,
> namely GPMC [1], do you prefer having it too there.
> 
> As of now it is not a driver, platform code handles GPMC, a patch
> series for converting it into a driver (but still residing in
> platform folder) was sent a few days back [2,3].

Probably the GPMC driver should go into a slightly different place than 
SDRC/EMIF.  

GPMC is actually a general-purpose parallel bus driver.  It's used to 
interface Ethernet controllers, UARTs, FPGAs, NAND/NOR flash, SRAM, etc.  
It cannot be used to control DRAM, at least not without a separate DRAM 
controller chip.

SDRC/EMIF are both DRAM controllers.  That's all they do.  They can't be 
used to control anything else.  They implement DRAM refresh, etc.

So perhaps something like drivers/memory/dram/ for the SDRAM controllers, 
and maybe drivers/memory/ for the GPMC?


- Paul

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 17:00             ` Paul Walmsley
  0 siblings, 0 replies; 84+ messages in thread
From: Paul Walmsley @ 2012-04-12 17:00 UTC (permalink / raw)
  To: linux-arm-kernel

Hi

On Thu, 12 Apr 2012, Mohammed, Afzal wrote:

> On Thu, Apr 12, 2012 at 18:40:45, Greg KH wrote:
> > On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
> > > I was hoping that we will have some thing like drivers/memory/*
> > > but since it doesn't exist, we used drivers/misc.
> > 
> > Why not create it?  I have no objection to that, it makes it more
> > obvious as to what this really is.
> 
> There is another memory controller used in a few TI SoCs,
> namely GPMC [1], do you prefer having it too there.
> 
> As of now it is not a driver, platform code handles GPMC, a patch
> series for converting it into a driver (but still residing in
> platform folder) was sent a few days back [2,3].

Probably the GPMC driver should go into a slightly different place than 
SDRC/EMIF.  

GPMC is actually a general-purpose parallel bus driver.  It's used to 
interface Ethernet controllers, UARTs, FPGAs, NAND/NOR flash, SRAM, etc.  
It cannot be used to control DRAM, at least not without a separate DRAM 
controller chip.

SDRC/EMIF are both DRAM controllers.  That's all they do.  They can't be 
used to control anything else.  They implement DRAM refresh, etc.

So perhaps something like drivers/memory/dram/ for the SDRAM controllers, 
and maybe drivers/memory/ for the GPMC?


- Paul

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-12 17:00             ` Paul Walmsley
  (?)
@ 2012-04-12 18:50               ` Cousson, Benoit
  -1 siblings, 0 replies; 84+ messages in thread
From: Cousson, Benoit @ 2012-04-12 18:50 UTC (permalink / raw)
  To: Paul Walmsley, Balbi, Felipe
  Cc: Mohammed, Afzal, Greg KH, Shilimkar, Santosh, V, Aneesh,
	linux-kernel, linux-arm-kernel, linux-omap, mgreer, msalter

+ Felipe,

Hi Paul,

On 4/12/2012 7:00 PM, Paul Walmsley wrote:
> Hi
>
> On Thu, 12 Apr 2012, Mohammed, Afzal wrote:
>
>> On Thu, Apr 12, 2012 at 18:40:45, Greg KH wrote:
>>> On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
>>>> I was hoping that we will have some thing like drivers/memory/*
>>>> but since it doesn't exist, we used drivers/misc.
>>>
>>> Why not create it?  I have no objection to that, it makes it more
>>> obvious as to what this really is.
>>
>> There is another memory controller used in a few TI SoCs,
>> namely GPMC [1], do you prefer having it too there.
>>
>> As of now it is not a driver, platform code handles GPMC, a patch
>> series for converting it into a driver (but still residing in
>> platform folder) was sent a few days back [2,3].
>
> Probably the GPMC driver should go into a slightly different place than
> SDRC/EMIF.
>
> GPMC is actually a general-purpose parallel bus driver.  It's used to
> interface Ethernet controllers, UARTs, FPGAs, NAND/NOR flash, SRAM, etc.
> It cannot be used to control DRAM, at least not without a separate DRAM
> controller chip.
>
> SDRC/EMIF are both DRAM controllers.  That's all they do.  They can't be
> used to control anything else.  They implement DRAM refresh, etc.

The LPDDR2 spec does consider as well NVM (Non Volatile Memory), so I 
think we should stick to driver/memory for EMIF.

> So perhaps something like drivers/memory/dram/ for the SDRAM controllers,
> and maybe drivers/memory/ for the GPMC?

In fact Felipe was considering something else for that kind of general 
purpose bus driver like GMPC, C2C and LLI...

... But I do not remember the name :-)

Regards,
Benoit

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 18:50               ` Cousson, Benoit
  0 siblings, 0 replies; 84+ messages in thread
From: Cousson, Benoit @ 2012-04-12 18:50 UTC (permalink / raw)
  To: Paul Walmsley, Balbi, Felipe
  Cc: Mohammed, Afzal, Greg KH, Shilimkar, Santosh, V, Aneesh,
	linux-kernel, linux-arm-kernel, linux-omap, mgreer, msalter

+ Felipe,

Hi Paul,

On 4/12/2012 7:00 PM, Paul Walmsley wrote:
> Hi
>
> On Thu, 12 Apr 2012, Mohammed, Afzal wrote:
>
>> On Thu, Apr 12, 2012 at 18:40:45, Greg KH wrote:
>>> On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
>>>> I was hoping that we will have some thing like drivers/memory/*
>>>> but since it doesn't exist, we used drivers/misc.
>>>
>>> Why not create it?  I have no objection to that, it makes it more
>>> obvious as to what this really is.
>>
>> There is another memory controller used in a few TI SoCs,
>> namely GPMC [1], do you prefer having it too there.
>>
>> As of now it is not a driver, platform code handles GPMC, a patch
>> series for converting it into a driver (but still residing in
>> platform folder) was sent a few days back [2,3].
>
> Probably the GPMC driver should go into a slightly different place than
> SDRC/EMIF.
>
> GPMC is actually a general-purpose parallel bus driver.  It's used to
> interface Ethernet controllers, UARTs, FPGAs, NAND/NOR flash, SRAM, etc.
> It cannot be used to control DRAM, at least not without a separate DRAM
> controller chip.
>
> SDRC/EMIF are both DRAM controllers.  That's all they do.  They can't be
> used to control anything else.  They implement DRAM refresh, etc.

The LPDDR2 spec does consider as well NVM (Non Volatile Memory), so I 
think we should stick to driver/memory for EMIF.

> So perhaps something like drivers/memory/dram/ for the SDRAM controllers,
> and maybe drivers/memory/ for the GPMC?

In fact Felipe was considering something else for that kind of general 
purpose bus driver like GMPC, C2C and LLI...

... But I do not remember the name :-)

Regards,
Benoit

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 18:50               ` Cousson, Benoit
  0 siblings, 0 replies; 84+ messages in thread
From: Cousson, Benoit @ 2012-04-12 18:50 UTC (permalink / raw)
  To: linux-arm-kernel

+ Felipe,

Hi Paul,

On 4/12/2012 7:00 PM, Paul Walmsley wrote:
> Hi
>
> On Thu, 12 Apr 2012, Mohammed, Afzal wrote:
>
>> On Thu, Apr 12, 2012 at 18:40:45, Greg KH wrote:
>>> On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
>>>> I was hoping that we will have some thing like drivers/memory/*
>>>> but since it doesn't exist, we used drivers/misc.
>>>
>>> Why not create it?  I have no objection to that, it makes it more
>>> obvious as to what this really is.
>>
>> There is another memory controller used in a few TI SoCs,
>> namely GPMC [1], do you prefer having it too there.
>>
>> As of now it is not a driver, platform code handles GPMC, a patch
>> series for converting it into a driver (but still residing in
>> platform folder) was sent a few days back [2,3].
>
> Probably the GPMC driver should go into a slightly different place than
> SDRC/EMIF.
>
> GPMC is actually a general-purpose parallel bus driver.  It's used to
> interface Ethernet controllers, UARTs, FPGAs, NAND/NOR flash, SRAM, etc.
> It cannot be used to control DRAM, at least not without a separate DRAM
> controller chip.
>
> SDRC/EMIF are both DRAM controllers.  That's all they do.  They can't be
> used to control anything else.  They implement DRAM refresh, etc.

The LPDDR2 spec does consider as well NVM (Non Volatile Memory), so I 
think we should stick to driver/memory for EMIF.

> So perhaps something like drivers/memory/dram/ for the SDRAM controllers,
> and maybe drivers/memory/ for the GPMC?

In fact Felipe was considering something else for that kind of general 
purpose bus driver like GMPC, C2C and LLI...

... But I do not remember the name :-)

Regards,
Benoit

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-12 18:50               ` Cousson, Benoit
  (?)
@ 2012-04-12 19:15                 ` Paul Walmsley
  -1 siblings, 0 replies; 84+ messages in thread
From: Paul Walmsley @ 2012-04-12 19:15 UTC (permalink / raw)
  To: Cousson, Benoit
  Cc: Balbi, Felipe, Mohammed, Afzal, Greg KH, Shilimkar, Santosh, V,
	Aneesh, linux-kernel, linux-arm-kernel, linux-omap, mgreer,
	msalter

[-- Attachment #1: Type: TEXT/PLAIN, Size: 709 bytes --]

Hi Benoît,

On Thu, 12 Apr 2012, Cousson, Benoit wrote:

> The LPDDR2 spec does consider as well NVM (Non Volatile Memory), so I think we
> should stick to driver/memory for EMIF.

Hmm good point!

> > So perhaps something like drivers/memory/dram/ for the SDRAM controllers,
> > and maybe drivers/memory/ for the GPMC?
> 
> In fact Felipe was considering something else for that kind of general purpose
> bus driver like GMPC, C2C and LLI...
> 
> ... But I do not remember the name :-)

It would be nice if we could separate IP blocks that can drive an Ethernet 
controller or modem chip from the DRAM controllers; they are quite 
different beasts from a common API standpoint.


- Paul

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 19:15                 ` Paul Walmsley
  0 siblings, 0 replies; 84+ messages in thread
From: Paul Walmsley @ 2012-04-12 19:15 UTC (permalink / raw)
  To: Cousson, Benoit
  Cc: Balbi, Felipe, Mohammed, Afzal, Greg KH, Shilimkar, Santosh, V,
	Aneesh, linux-kernel, linux-arm-kernel, linux-omap, mgreer,
	msalter

[-- Attachment #1: Type: TEXT/PLAIN, Size: 709 bytes --]

Hi Benoît,

On Thu, 12 Apr 2012, Cousson, Benoit wrote:

> The LPDDR2 spec does consider as well NVM (Non Volatile Memory), so I think we
> should stick to driver/memory for EMIF.

Hmm good point!

> > So perhaps something like drivers/memory/dram/ for the SDRAM controllers,
> > and maybe drivers/memory/ for the GPMC?
> 
> In fact Felipe was considering something else for that kind of general purpose
> bus driver like GMPC, C2C and LLI...
> 
> ... But I do not remember the name :-)

It would be nice if we could separate IP blocks that can drive an Ethernet 
controller or modem chip from the DRAM controllers; they are quite 
different beasts from a common API standpoint.


- Paul

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 19:15                 ` Paul Walmsley
  0 siblings, 0 replies; 84+ messages in thread
From: Paul Walmsley @ 2012-04-12 19:15 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Beno?t,

On Thu, 12 Apr 2012, Cousson, Benoit wrote:

> The LPDDR2 spec does consider as well NVM (Non Volatile Memory), so I think we
> should stick to driver/memory for EMIF.

Hmm good point!

> > So perhaps something like drivers/memory/dram/ for the SDRAM controllers,
> > and maybe drivers/memory/ for the GPMC?
> 
> In fact Felipe was considering something else for that kind of general purpose
> bus driver like GMPC, C2C and LLI...
> 
> ... But I do not remember the name :-)

It would be nice if we could separate IP blocks that can drive an Ethernet 
controller or modem chip from the DRAM controllers; they are quite 
different beasts from a common API standpoint.


- Paul

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-12 19:15                 ` Paul Walmsley
  (?)
@ 2012-04-12 19:24                   ` Cousson, Benoit
  -1 siblings, 0 replies; 84+ messages in thread
From: Cousson, Benoit @ 2012-04-12 19:24 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: Balbi, Felipe, Mohammed, Afzal, Greg KH, Shilimkar, Santosh, V,
	Aneesh, linux-kernel, linux-arm-kernel, linux-omap, mgreer,
	msalter

On 4/12/2012 9:15 PM, Paul Walmsley wrote:
> Hi Benoît,
>
> On Thu, 12 Apr 2012, Cousson, Benoit wrote:
>
>> The LPDDR2 spec does consider as well NVM (Non Volatile Memory), so I think we
>> should stick to driver/memory for EMIF.
>
> Hmm good point!
>
>>> So perhaps something like drivers/memory/dram/ for the SDRAM controllers,
>>> and maybe drivers/memory/ for the GPMC?
>>
>> In fact Felipe was considering something else for that kind of general purpose
>> bus driver like GMPC, C2C and LLI...
>>
>> ... But I do not remember the name :-)
>
> It would be nice if we could separate IP blocks that can drive an Ethernet
> controller or modem chip from the DRAM controllers; they are quite
> different beasts from a common API standpoint.

Yep, fully agree. In fact Felipe's suggestion was something like 
drivers/ocd for off-chip devices, but maybe something like drivers/gpbus 
will highlight a little bit more the bus controller aspect of such driver.

Regards,
Benoit

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 19:24                   ` Cousson, Benoit
  0 siblings, 0 replies; 84+ messages in thread
From: Cousson, Benoit @ 2012-04-12 19:24 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: Balbi, Felipe, Mohammed, Afzal, Greg KH, Shilimkar, Santosh, V,
	Aneesh, linux-kernel, linux-arm-kernel, linux-omap, mgreer,
	msalter

On 4/12/2012 9:15 PM, Paul Walmsley wrote:
> Hi Benoît,
>
> On Thu, 12 Apr 2012, Cousson, Benoit wrote:
>
>> The LPDDR2 spec does consider as well NVM (Non Volatile Memory), so I think we
>> should stick to driver/memory for EMIF.
>
> Hmm good point!
>
>>> So perhaps something like drivers/memory/dram/ for the SDRAM controllers,
>>> and maybe drivers/memory/ for the GPMC?
>>
>> In fact Felipe was considering something else for that kind of general purpose
>> bus driver like GMPC, C2C and LLI...
>>
>> ... But I do not remember the name :-)
>
> It would be nice if we could separate IP blocks that can drive an Ethernet
> controller or modem chip from the DRAM controllers; they are quite
> different beasts from a common API standpoint.

Yep, fully agree. In fact Felipe's suggestion was something like 
drivers/ocd for off-chip devices, but maybe something like drivers/gpbus 
will highlight a little bit more the bus controller aspect of such driver.

Regards,
Benoit

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 19:24                   ` Cousson, Benoit
  0 siblings, 0 replies; 84+ messages in thread
From: Cousson, Benoit @ 2012-04-12 19:24 UTC (permalink / raw)
  To: linux-arm-kernel

On 4/12/2012 9:15 PM, Paul Walmsley wrote:
> Hi Beno?t,
>
> On Thu, 12 Apr 2012, Cousson, Benoit wrote:
>
>> The LPDDR2 spec does consider as well NVM (Non Volatile Memory), so I think we
>> should stick to driver/memory for EMIF.
>
> Hmm good point!
>
>>> So perhaps something like drivers/memory/dram/ for the SDRAM controllers,
>>> and maybe drivers/memory/ for the GPMC?
>>
>> In fact Felipe was considering something else for that kind of general purpose
>> bus driver like GMPC, C2C and LLI...
>>
>> ... But I do not remember the name :-)
>
> It would be nice if we could separate IP blocks that can drive an Ethernet
> controller or modem chip from the DRAM controllers; they are quite
> different beasts from a common API standpoint.

Yep, fully agree. In fact Felipe's suggestion was something like 
drivers/ocd for off-chip devices, but maybe something like drivers/gpbus 
will highlight a little bit more the bus controller aspect of such driver.

Regards,
Benoit

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-12  3:00     ` Greg KH
@ 2012-04-12 19:58       ` V, Aneesh
  -1 siblings, 0 replies; 84+ messages in thread
From: V, Aneesh @ 2012-04-12 19:58 UTC (permalink / raw)
  To: Greg KH
  Cc: Paul Walmsley, linux-kernel, linux-arm-kernel, linux-omap,
	mgreer, msalter

Hi Greg,

On Wed, Apr 11, 2012 at 8:00 PM, Greg KH <greg@kroah.com> wrote:
> On Wed, Apr 11, 2012 at 08:44:39PM -0600, Paul Walmsley wrote:
>> Cc Mark Greer, Mark Salter
>>
>> Hi Greg, Aneesh,
>>
>> On Sat, 17 Mar 2012, Aneesh V wrote:
>>
>> > Add a driver for the EMIF SDRAM controller used in TI SoCs
>> >
>> > EMIF is an SDRAM controller that supports, based on its revision,
>> > one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
>> > for LPDDR2.
>>
>> Just checking to see what the current state of this series is.  Greg, are
>> you considering this for merging, or are there remaining issues?  Aneesh,
>> do you have any remaining issues to resolve with this set?
>
> What about the review comment about devfreq?

I see that Santosh has already commented on this.
My views are similar, that frequency update is only one of the
many functions of the driver.

>
>> This is useful not only for OMAP4 and AM3517/3505, but also will probably
>> be useful for the C6x chips that Mark Salter is working on.
>
> It's still in my "to-review" queue, that I'm slowly making my way
> through.  So it's not lost, but I would like to get the devfreq
> interface question cleared up first.

Thanks. I will wait for your review then. Once I have your comments
I will re-work and submit in the new directory structure proposed.

thanks,
Aneesh

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-12 19:58       ` V, Aneesh
  0 siblings, 0 replies; 84+ messages in thread
From: V, Aneesh @ 2012-04-12 19:58 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Greg,

On Wed, Apr 11, 2012 at 8:00 PM, Greg KH <greg@kroah.com> wrote:
> On Wed, Apr 11, 2012 at 08:44:39PM -0600, Paul Walmsley wrote:
>> Cc Mark Greer, Mark Salter
>>
>> Hi Greg, Aneesh,
>>
>> On Sat, 17 Mar 2012, Aneesh V wrote:
>>
>> > Add a driver for the EMIF SDRAM controller used in TI SoCs
>> >
>> > EMIF is an SDRAM controller that supports, based on its revision,
>> > one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
>> > for LPDDR2.
>>
>> Just checking to see what the current state of this series is. ?Greg, are
>> you considering this for merging, or are there remaining issues? ?Aneesh,
>> do you have any remaining issues to resolve with this set?
>
> What about the review comment about devfreq?

I see that Santosh has already commented on this.
My views are similar, that frequency update is only one of the
many functions of the driver.

>
>> This is useful not only for OMAP4 and AM3517/3505, but also will probably
>> be useful for the C6x chips that Mark Salter is working on.
>
> It's still in my "to-review" queue, that I'm slowly making my way
> through. ?So it's not lost, but I would like to get the devfreq
> interface question cleared up first.

Thanks. I will wait for your review then. Once I have your comments
I will re-work and submit in the new directory structure proposed.

thanks,
Aneesh

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-12 18:50               ` Cousson, Benoit
  (?)
@ 2012-04-13  9:07                 ` Felipe Balbi
  -1 siblings, 0 replies; 84+ messages in thread
From: Felipe Balbi @ 2012-04-13  9:07 UTC (permalink / raw)
  To: Cousson, Benoit
  Cc: Paul Walmsley, Balbi, Felipe, Mohammed, Afzal, Greg KH,
	Shilimkar, Santosh, V, Aneesh, linux-kernel, linux-arm-kernel,
	linux-omap, mgreer, msalter

[-- Attachment #1: Type: text/plain, Size: 2207 bytes --]

On Thu, Apr 12, 2012 at 08:50:55PM +0200, Cousson, Benoit wrote:
> + Felipe,
> 
> Hi Paul,
> 
> On 4/12/2012 7:00 PM, Paul Walmsley wrote:
> >Hi
> >
> >On Thu, 12 Apr 2012, Mohammed, Afzal wrote:
> >
> >>On Thu, Apr 12, 2012 at 18:40:45, Greg KH wrote:
> >>>On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
> >>>>I was hoping that we will have some thing like drivers/memory/*
> >>>>but since it doesn't exist, we used drivers/misc.
> >>>
> >>>Why not create it?  I have no objection to that, it makes it more
> >>>obvious as to what this really is.
> >>
> >>There is another memory controller used in a few TI SoCs,
> >>namely GPMC [1], do you prefer having it too there.
> >>
> >>As of now it is not a driver, platform code handles GPMC, a patch
> >>series for converting it into a driver (but still residing in
> >>platform folder) was sent a few days back [2,3].
> >
> >Probably the GPMC driver should go into a slightly different place than
> >SDRC/EMIF.
> >
> >GPMC is actually a general-purpose parallel bus driver.  It's used to
> >interface Ethernet controllers, UARTs, FPGAs, NAND/NOR flash, SRAM, etc.
> >It cannot be used to control DRAM, at least not without a separate DRAM
> >controller chip.
> >
> >SDRC/EMIF are both DRAM controllers.  That's all they do.  They can't be
> >used to control anything else.  They implement DRAM refresh, etc.
> 
> The LPDDR2 spec does consider as well NVM (Non Volatile Memory), so I
> think we should stick to driver/memory for EMIF.
> 
> >So perhaps something like drivers/memory/dram/ for the SDRAM controllers,
> >and maybe drivers/memory/ for the GPMC?
> 
> In fact Felipe was considering something else for that kind of
> general purpose bus driver like GMPC, C2C and LLI...
> 
> ... But I do not remember the name :-)

the name matters very little :-) But the idea was to avoid writing yet
another bus driver and just use the platform_bus instead. We would do
all the channel/port setup before hand and far-end device driver
wouldn't have to know if it's integrated into the SoC or plugged though
LLI/C2C/GPMC.

From the driver's perspective it would look the same.

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-13  9:07                 ` Felipe Balbi
  0 siblings, 0 replies; 84+ messages in thread
From: Felipe Balbi @ 2012-04-13  9:07 UTC (permalink / raw)
  To: Cousson, Benoit
  Cc: Paul Walmsley, Balbi, Felipe, Mohammed, Afzal, Greg KH,
	Shilimkar, Santosh, V, Aneesh, linux-kernel, linux-arm-kernel,
	linux-omap, mgreer, msalter

[-- Attachment #1: Type: text/plain, Size: 2207 bytes --]

On Thu, Apr 12, 2012 at 08:50:55PM +0200, Cousson, Benoit wrote:
> + Felipe,
> 
> Hi Paul,
> 
> On 4/12/2012 7:00 PM, Paul Walmsley wrote:
> >Hi
> >
> >On Thu, 12 Apr 2012, Mohammed, Afzal wrote:
> >
> >>On Thu, Apr 12, 2012 at 18:40:45, Greg KH wrote:
> >>>On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
> >>>>I was hoping that we will have some thing like drivers/memory/*
> >>>>but since it doesn't exist, we used drivers/misc.
> >>>
> >>>Why not create it?  I have no objection to that, it makes it more
> >>>obvious as to what this really is.
> >>
> >>There is another memory controller used in a few TI SoCs,
> >>namely GPMC [1], do you prefer having it too there.
> >>
> >>As of now it is not a driver, platform code handles GPMC, a patch
> >>series for converting it into a driver (but still residing in
> >>platform folder) was sent a few days back [2,3].
> >
> >Probably the GPMC driver should go into a slightly different place than
> >SDRC/EMIF.
> >
> >GPMC is actually a general-purpose parallel bus driver.  It's used to
> >interface Ethernet controllers, UARTs, FPGAs, NAND/NOR flash, SRAM, etc.
> >It cannot be used to control DRAM, at least not without a separate DRAM
> >controller chip.
> >
> >SDRC/EMIF are both DRAM controllers.  That's all they do.  They can't be
> >used to control anything else.  They implement DRAM refresh, etc.
> 
> The LPDDR2 spec does consider as well NVM (Non Volatile Memory), so I
> think we should stick to driver/memory for EMIF.
> 
> >So perhaps something like drivers/memory/dram/ for the SDRAM controllers,
> >and maybe drivers/memory/ for the GPMC?
> 
> In fact Felipe was considering something else for that kind of
> general purpose bus driver like GMPC, C2C and LLI...
> 
> ... But I do not remember the name :-)

the name matters very little :-) But the idea was to avoid writing yet
another bus driver and just use the platform_bus instead. We would do
all the channel/port setup before hand and far-end device driver
wouldn't have to know if it's integrated into the SoC or plugged though
LLI/C2C/GPMC.

From the driver's perspective it would look the same.

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-13  9:07                 ` Felipe Balbi
  0 siblings, 0 replies; 84+ messages in thread
From: Felipe Balbi @ 2012-04-13  9:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 12, 2012 at 08:50:55PM +0200, Cousson, Benoit wrote:
> + Felipe,
> 
> Hi Paul,
> 
> On 4/12/2012 7:00 PM, Paul Walmsley wrote:
> >Hi
> >
> >On Thu, 12 Apr 2012, Mohammed, Afzal wrote:
> >
> >>On Thu, Apr 12, 2012 at 18:40:45, Greg KH wrote:
> >>>On Thu, Apr 12, 2012 at 12:17:49PM +0530, Santosh Shilimkar wrote:
> >>>>I was hoping that we will have some thing like drivers/memory/*
> >>>>but since it doesn't exist, we used drivers/misc.
> >>>
> >>>Why not create it?  I have no objection to that, it makes it more
> >>>obvious as to what this really is.
> >>
> >>There is another memory controller used in a few TI SoCs,
> >>namely GPMC [1], do you prefer having it too there.
> >>
> >>As of now it is not a driver, platform code handles GPMC, a patch
> >>series for converting it into a driver (but still residing in
> >>platform folder) was sent a few days back [2,3].
> >
> >Probably the GPMC driver should go into a slightly different place than
> >SDRC/EMIF.
> >
> >GPMC is actually a general-purpose parallel bus driver.  It's used to
> >interface Ethernet controllers, UARTs, FPGAs, NAND/NOR flash, SRAM, etc.
> >It cannot be used to control DRAM, at least not without a separate DRAM
> >controller chip.
> >
> >SDRC/EMIF are both DRAM controllers.  That's all they do.  They can't be
> >used to control anything else.  They implement DRAM refresh, etc.
> 
> The LPDDR2 spec does consider as well NVM (Non Volatile Memory), so I
> think we should stick to driver/memory for EMIF.
> 
> >So perhaps something like drivers/memory/dram/ for the SDRAM controllers,
> >and maybe drivers/memory/ for the GPMC?
> 
> In fact Felipe was considering something else for that kind of
> general purpose bus driver like GMPC, C2C and LLI...
> 
> ... But I do not remember the name :-)

the name matters very little :-) But the idea was to avoid writing yet
another bus driver and just use the platform_bus instead. We would do
all the channel/port setup before hand and far-end device driver
wouldn't have to know if it's integrated into the SoC or plugged though
LLI/C2C/GPMC.

>From the driver's perspective it would look the same.

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120413/f54b34a4/attachment.sig>

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-12  2:44   ` Paul Walmsley
@ 2012-04-13 14:15     ` Mark Salter
  -1 siblings, 0 replies; 84+ messages in thread
From: Mark Salter @ 2012-04-13 14:15 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: Aneesh V, Greg KH, linux-kernel, linux-arm-kernel, linux-omap, mgreer

On Wed, 2012-04-11 at 20:44 -0600, Paul Walmsley wrote:
> This is useful not only for OMAP4 and AM3517/3505, but also will probably 
> be useful for the C6x chips that Mark Salter is working on.

I have been keeping an occasional eye on these patches but I don't see
any usefulness for the currently supported C6X chips. The current set
of supported chips use a completely different DDR controller. There is
an EMIF controller on some which provides a parallel bus for connecting
to external devices (NOR flash, etc) but it looks completely different
from the OMAP EMIF. I think the TI DaVinci chips have EMIF (and other IO
blocks) similar to C6X which could use common drivers.

--Mark



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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-13 14:15     ` Mark Salter
  0 siblings, 0 replies; 84+ messages in thread
From: Mark Salter @ 2012-04-13 14:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 2012-04-11 at 20:44 -0600, Paul Walmsley wrote:
> This is useful not only for OMAP4 and AM3517/3505, but also will probably 
> be useful for the C6x chips that Mark Salter is working on.

I have been keeping an occasional eye on these patches but I don't see
any usefulness for the currently supported C6X chips. The current set
of supported chips use a completely different DDR controller. There is
an EMIF controller on some which provides a parallel bus for connecting
to external devices (NOR flash, etc) but it looks completely different
from the OMAP EMIF. I think the TI DaVinci chips have EMIF (and other IO
blocks) similar to C6X which could use common drivers.

--Mark

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

* RE: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-12 19:58       ` V, Aneesh
  (?)
@ 2012-04-23 10:56         ` Mohammed, Afzal
  -1 siblings, 0 replies; 84+ messages in thread
From: Mohammed, Afzal @ 2012-04-23 10:56 UTC (permalink / raw)
  To: V, Aneesh, Greg KH
  Cc: Paul Walmsley, linux-kernel, mgreer, msalter, linux-omap,
	linux-arm-kernel, Hunter, Jon

Hi Aneesh,

On Fri, Apr 13, 2012 at 01:28:55, V, Aneesh wrote:

> Thanks. I will wait for your review then. Once I have your comments
> I will re-work and submit in the new directory structure proposed.

Do you have a plan on submitting EMIF driver in the new proposed
(drivers/memory) directory. Or shall I submit GPMC driver by creating
the new "memory" directory.

Regards
Afzal

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

* RE: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-23 10:56         ` Mohammed, Afzal
  0 siblings, 0 replies; 84+ messages in thread
From: Mohammed, Afzal @ 2012-04-23 10:56 UTC (permalink / raw)
  To: V, Aneesh, Greg KH
  Cc: Paul Walmsley, linux-kernel, mgreer, msalter, linux-omap,
	linux-arm-kernel, Hunter, Jon

Hi Aneesh,

On Fri, Apr 13, 2012 at 01:28:55, V, Aneesh wrote:

> Thanks. I will wait for your review then. Once I have your comments
> I will re-work and submit in the new directory structure proposed.

Do you have a plan on submitting EMIF driver in the new proposed
(drivers/memory) directory. Or shall I submit GPMC driver by creating
the new "memory" directory.

Regards
Afzal

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-23 10:56         ` Mohammed, Afzal
  0 siblings, 0 replies; 84+ messages in thread
From: Mohammed, Afzal @ 2012-04-23 10:56 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Aneesh,

On Fri, Apr 13, 2012 at 01:28:55, V, Aneesh wrote:

> Thanks. I will wait for your review then. Once I have your comments
> I will re-work and submit in the new directory structure proposed.

Do you have a plan on submitting EMIF driver in the new proposed
(drivers/memory) directory. Or shall I submit GPMC driver by creating
the new "memory" directory.

Regards
Afzal

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-23 10:56         ` Mohammed, Afzal
  (?)
@ 2012-04-23 11:04           ` Shilimkar, Santosh
  -1 siblings, 0 replies; 84+ messages in thread
From: Shilimkar, Santosh @ 2012-04-23 11:04 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: V, Aneesh, Greg KH, Paul Walmsley, linux-kernel, mgreer, msalter,
	linux-omap, linux-arm-kernel, Hunter, Jon

Afzal,

On Mon, Apr 23, 2012 at 4:26 PM, Mohammed, Afzal <afzal@ti.com> wrote:
> Hi Aneesh,
>
> On Fri, Apr 13, 2012 at 01:28:55, V, Aneesh wrote:
>
>> Thanks. I will wait for your review then. Once I have your comments
>> I will re-work and submit in the new directory structure proposed.
>
> Do you have a plan on submitting EMIF driver in the new proposed
> (drivers/memory) directory. Or shall I submit GPMC driver by creating
> the new "memory" directory.
>
 Greg mentioned that he plans to do a review of EMIF driver. We were waiting
for his comments before sending the updated series.

Please go ahead in creating directory.

Regards
Santosh

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-23 11:04           ` Shilimkar, Santosh
  0 siblings, 0 replies; 84+ messages in thread
From: Shilimkar, Santosh @ 2012-04-23 11:04 UTC (permalink / raw)
  To: Mohammed, Afzal
  Cc: V, Aneesh, Greg KH, Paul Walmsley, linux-kernel, mgreer, msalter,
	linux-omap, linux-arm-kernel, Hunter, Jon

Afzal,

On Mon, Apr 23, 2012 at 4:26 PM, Mohammed, Afzal <afzal@ti.com> wrote:
> Hi Aneesh,
>
> On Fri, Apr 13, 2012 at 01:28:55, V, Aneesh wrote:
>
>> Thanks. I will wait for your review then. Once I have your comments
>> I will re-work and submit in the new directory structure proposed.
>
> Do you have a plan on submitting EMIF driver in the new proposed
> (drivers/memory) directory. Or shall I submit GPMC driver by creating
> the new "memory" directory.
>
 Greg mentioned that he plans to do a review of EMIF driver. We were waiting
for his comments before sending the updated series.

Please go ahead in creating directory.

Regards
Santosh

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-23 11:04           ` Shilimkar, Santosh
  0 siblings, 0 replies; 84+ messages in thread
From: Shilimkar, Santosh @ 2012-04-23 11:04 UTC (permalink / raw)
  To: linux-arm-kernel

Afzal,

On Mon, Apr 23, 2012 at 4:26 PM, Mohammed, Afzal <afzal@ti.com> wrote:
> Hi Aneesh,
>
> On Fri, Apr 13, 2012 at 01:28:55, V, Aneesh wrote:
>
>> Thanks. I will wait for your review then. Once I have your comments
>> I will re-work and submit in the new directory structure proposed.
>
> Do you have a plan on submitting EMIF driver in the new proposed
> (drivers/memory) directory. Or shall I submit GPMC driver by creating
> the new "memory" directory.
>
 Greg mentioned that he plans to do a review of EMIF driver. We were waiting
for his comments before sending the updated series.

Please go ahead in creating directory.

Regards
Santosh

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

* RE: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-23 11:04           ` Shilimkar, Santosh
  (?)
@ 2012-04-23 11:09             ` Mohammed, Afzal
  -1 siblings, 0 replies; 84+ messages in thread
From: Mohammed, Afzal @ 2012-04-23 11:09 UTC (permalink / raw)
  To: Shilimkar, Santosh
  Cc: V, Aneesh, Greg KH, Paul Walmsley, linux-kernel, mgreer, msalter,
	linux-omap, linux-arm-kernel, Hunter, Jon

Hi Santosh,

On Mon, Apr 23, 2012 at 16:34:46, Shilimkar, Santosh wrote:
> Please go ahead in creating directory.

Thanks for the quick reply.

Regards
Afzal

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

* RE: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-23 11:09             ` Mohammed, Afzal
  0 siblings, 0 replies; 84+ messages in thread
From: Mohammed, Afzal @ 2012-04-23 11:09 UTC (permalink / raw)
  To: Shilimkar, Santosh
  Cc: V, Aneesh, Greg KH, Paul Walmsley, linux-kernel, mgreer, msalter,
	linux-omap, linux-arm-kernel, Hunter, Jon

Hi Santosh,

On Mon, Apr 23, 2012 at 16:34:46, Shilimkar, Santosh wrote:
> Please go ahead in creating directory.

Thanks for the quick reply.

Regards
Afzal

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-23 11:09             ` Mohammed, Afzal
  0 siblings, 0 replies; 84+ messages in thread
From: Mohammed, Afzal @ 2012-04-23 11:09 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Santosh,

On Mon, Apr 23, 2012 at 16:34:46, Shilimkar, Santosh wrote:
> Please go ahead in creating directory.

Thanks for the quick reply.

Regards
Afzal

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-23 11:04           ` Shilimkar, Santosh
  (?)
@ 2012-04-23 14:27             ` Greg KH
  -1 siblings, 0 replies; 84+ messages in thread
From: Greg KH @ 2012-04-23 14:27 UTC (permalink / raw)
  To: Shilimkar, Santosh
  Cc: Mohammed, Afzal, V, Aneesh, Paul Walmsley, linux-kernel, mgreer,
	msalter, linux-omap, linux-arm-kernel, Hunter, Jon

On Mon, Apr 23, 2012 at 04:34:46PM +0530, Shilimkar, Santosh wrote:
> Afzal,
> 
> On Mon, Apr 23, 2012 at 4:26 PM, Mohammed, Afzal <afzal@ti.com> wrote:
> > Hi Aneesh,
> >
> > On Fri, Apr 13, 2012 at 01:28:55, V, Aneesh wrote:
> >
> >> Thanks. I will wait for your review then. Once I have your comments
> >> I will re-work and submit in the new directory structure proposed.
> >
> > Do you have a plan on submitting EMIF driver in the new proposed
> > (drivers/memory) directory. Or shall I submit GPMC driver by creating
> > the new "memory" directory.
> >
>  Greg mentioned that he plans to do a review of EMIF driver. We were waiting
> for his comments before sending the updated series.

No, don't wait for me, please resend, I was waiting for you :)

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-23 14:27             ` Greg KH
  0 siblings, 0 replies; 84+ messages in thread
From: Greg KH @ 2012-04-23 14:27 UTC (permalink / raw)
  To: Shilimkar, Santosh
  Cc: Mohammed, Afzal, V, Aneesh, Paul Walmsley, linux-kernel, mgreer,
	msalter, linux-omap, linux-arm-kernel, Hunter, Jon

On Mon, Apr 23, 2012 at 04:34:46PM +0530, Shilimkar, Santosh wrote:
> Afzal,
> 
> On Mon, Apr 23, 2012 at 4:26 PM, Mohammed, Afzal <afzal@ti.com> wrote:
> > Hi Aneesh,
> >
> > On Fri, Apr 13, 2012 at 01:28:55, V, Aneesh wrote:
> >
> >> Thanks. I will wait for your review then. Once I have your comments
> >> I will re-work and submit in the new directory structure proposed.
> >
> > Do you have a plan on submitting EMIF driver in the new proposed
> > (drivers/memory) directory. Or shall I submit GPMC driver by creating
> > the new "memory" directory.
> >
>  Greg mentioned that he plans to do a review of EMIF driver. We were waiting
> for his comments before sending the updated series.

No, don't wait for me, please resend, I was waiting for you :)

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-23 14:27             ` Greg KH
  0 siblings, 0 replies; 84+ messages in thread
From: Greg KH @ 2012-04-23 14:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 23, 2012 at 04:34:46PM +0530, Shilimkar, Santosh wrote:
> Afzal,
> 
> On Mon, Apr 23, 2012 at 4:26 PM, Mohammed, Afzal <afzal@ti.com> wrote:
> > Hi Aneesh,
> >
> > On Fri, Apr 13, 2012 at 01:28:55, V, Aneesh wrote:
> >
> >> Thanks. I will wait for your review then. Once I have your comments
> >> I will re-work and submit in the new directory structure proposed.
> >
> > Do you have a plan on submitting EMIF driver in the new proposed
> > (drivers/memory) directory. Or shall I submit GPMC driver by creating
> > the new "memory" directory.
> >
>  Greg mentioned that he plans to do a review of EMIF driver. We were waiting
> for his comments before sending the updated series.

No, don't wait for me, please resend, I was waiting for you :)

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-23 14:27             ` Greg KH
  (?)
@ 2012-04-23 14:44               ` Shilimkar, Santosh
  -1 siblings, 0 replies; 84+ messages in thread
From: Shilimkar, Santosh @ 2012-04-23 14:44 UTC (permalink / raw)
  To: Greg KH
  Cc: Mohammed, Afzal, V, Aneesh, Paul Walmsley, linux-kernel, mgreer,
	msalter, linux-omap, linux-arm-kernel, Hunter, Jon

On Mon, Apr 23, 2012 at 7:57 PM, Greg KH <greg@kroah.com> wrote:
> On Mon, Apr 23, 2012 at 04:34:46PM +0530, Shilimkar, Santosh wrote:
>> Afzal,
>>
>> On Mon, Apr 23, 2012 at 4:26 PM, Mohammed, Afzal <afzal@ti.com> wrote:
>> > Hi Aneesh,
>> >
>> > On Fri, Apr 13, 2012 at 01:28:55, V, Aneesh wrote:
>> >
>> >> Thanks. I will wait for your review then. Once I have your comments
>> >> I will re-work and submit in the new directory structure proposed.
>> >
>> > Do you have a plan on submitting EMIF driver in the new proposed
>> > (drivers/memory) directory. Or shall I submit GPMC driver by creating
>> > the new "memory" directory.
>> >
>>  Greg mentioned that he plans to do a review of EMIF driver. We were waiting
>> for his comments before sending the updated series.
>
> No, don't wait for me, please resend, I was waiting for you :)

Thanks Greg !!
Will start working on updating the patch set and post it on list.

Regards
Santosh

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-23 14:44               ` Shilimkar, Santosh
  0 siblings, 0 replies; 84+ messages in thread
From: Shilimkar, Santosh @ 2012-04-23 14:44 UTC (permalink / raw)
  To: Greg KH
  Cc: Mohammed, Afzal, V, Aneesh, Paul Walmsley, linux-kernel, mgreer,
	msalter, linux-omap, linux-arm-kernel, Hunter, Jon

On Mon, Apr 23, 2012 at 7:57 PM, Greg KH <greg@kroah.com> wrote:
> On Mon, Apr 23, 2012 at 04:34:46PM +0530, Shilimkar, Santosh wrote:
>> Afzal,
>>
>> On Mon, Apr 23, 2012 at 4:26 PM, Mohammed, Afzal <afzal@ti.com> wrote:
>> > Hi Aneesh,
>> >
>> > On Fri, Apr 13, 2012 at 01:28:55, V, Aneesh wrote:
>> >
>> >> Thanks. I will wait for your review then. Once I have your comments
>> >> I will re-work and submit in the new directory structure proposed.
>> >
>> > Do you have a plan on submitting EMIF driver in the new proposed
>> > (drivers/memory) directory. Or shall I submit GPMC driver by creating
>> > the new "memory" directory.
>> >
>>  Greg mentioned that he plans to do a review of EMIF driver. We were waiting
>> for his comments before sending the updated series.
>
> No, don't wait for me, please resend, I was waiting for you :)

Thanks Greg !!
Will start working on updating the patch set and post it on list.

Regards
Santosh

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-23 14:44               ` Shilimkar, Santosh
  0 siblings, 0 replies; 84+ messages in thread
From: Shilimkar, Santosh @ 2012-04-23 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 23, 2012 at 7:57 PM, Greg KH <greg@kroah.com> wrote:
> On Mon, Apr 23, 2012 at 04:34:46PM +0530, Shilimkar, Santosh wrote:
>> Afzal,
>>
>> On Mon, Apr 23, 2012 at 4:26 PM, Mohammed, Afzal <afzal@ti.com> wrote:
>> > Hi Aneesh,
>> >
>> > On Fri, Apr 13, 2012 at 01:28:55, V, Aneesh wrote:
>> >
>> >> Thanks. I will wait for your review then. Once I have your comments
>> >> I will re-work and submit in the new directory structure proposed.
>> >
>> > Do you have a plan on submitting EMIF driver in the new proposed
>> > (drivers/memory) directory. Or shall I submit GPMC driver by creating
>> > the new "memory" directory.
>> >
>> ?Greg mentioned that he plans to do a review of EMIF driver. We were waiting
>> for his comments before sending the updated series.
>
> No, don't wait for me, please resend, I was waiting for you :)

Thanks Greg !!
Will start working on updating the patch set and post it on list.

Regards
Santosh

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-04-23 14:44               ` Shilimkar, Santosh
  (?)
@ 2012-04-27 13:16                 ` Santosh Shilimkar
  -1 siblings, 0 replies; 84+ messages in thread
From: Santosh Shilimkar @ 2012-04-27 13:16 UTC (permalink / raw)
  To: Greg KH
  Cc: Mohammed, Afzal, V, Aneesh, Paul Walmsley, linux-kernel, mgreer,
	msalter, linux-omap, linux-arm-kernel, Hunter, Jon

Greg,

On Monday 23 April 2012 08:14 PM, Shilimkar, Santosh wrote:
> On Mon, Apr 23, 2012 at 7:57 PM, Greg KH <greg@kroah.com> wrote:
>> On Mon, Apr 23, 2012 at 04:34:46PM +0530, Shilimkar, Santosh wrote:
>>> Afzal,
>>>
>>> On Mon, Apr 23, 2012 at 4:26 PM, Mohammed, Afzal <afzal@ti.com> wrote:
>>>> Hi Aneesh,
>>>>
>>>> On Fri, Apr 13, 2012 at 01:28:55, V, Aneesh wrote:
>>>>
>>>>> Thanks. I will wait for your review then. Once I have your comments
>>>>> I will re-work and submit in the new directory structure proposed.
>>>>
>>>> Do you have a plan on submitting EMIF driver in the new proposed
>>>> (drivers/memory) directory. Or shall I submit GPMC driver by creating
>>>> the new "memory" directory.
>>>>
>>>  Greg mentioned that he plans to do a review of EMIF driver. We were waiting
>>> for his comments before sending the updated series.
>>
>> No, don't wait for me, please resend, I was waiting for you :)
> 
> Thanks Greg !!
> Will start working on updating the patch set and post it on list.
> 
Have posted the updated version [1] as per discussion on
this thread.

Regards
Santosh

[1] http://www.spinics.net/lists/arm-kernel/msg171869.html

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

* Re: [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-27 13:16                 ` Santosh Shilimkar
  0 siblings, 0 replies; 84+ messages in thread
From: Santosh Shilimkar @ 2012-04-27 13:16 UTC (permalink / raw)
  To: Greg KH
  Cc: Mohammed, Afzal, V, Aneesh, Paul Walmsley, linux-kernel, mgreer,
	msalter, linux-omap, linux-arm-kernel, Hunter, Jon

Greg,

On Monday 23 April 2012 08:14 PM, Shilimkar, Santosh wrote:
> On Mon, Apr 23, 2012 at 7:57 PM, Greg KH <greg@kroah.com> wrote:
>> On Mon, Apr 23, 2012 at 04:34:46PM +0530, Shilimkar, Santosh wrote:
>>> Afzal,
>>>
>>> On Mon, Apr 23, 2012 at 4:26 PM, Mohammed, Afzal <afzal@ti.com> wrote:
>>>> Hi Aneesh,
>>>>
>>>> On Fri, Apr 13, 2012 at 01:28:55, V, Aneesh wrote:
>>>>
>>>>> Thanks. I will wait for your review then. Once I have your comments
>>>>> I will re-work and submit in the new directory structure proposed.
>>>>
>>>> Do you have a plan on submitting EMIF driver in the new proposed
>>>> (drivers/memory) directory. Or shall I submit GPMC driver by creating
>>>> the new "memory" directory.
>>>>
>>>  Greg mentioned that he plans to do a review of EMIF driver. We were waiting
>>> for his comments before sending the updated series.
>>
>> No, don't wait for me, please resend, I was waiting for you :)
> 
> Thanks Greg !!
> Will start working on updating the patch set and post it on list.
> 
Have posted the updated version [1] as per discussion on
this thread.

Regards
Santosh

[1] http://www.spinics.net/lists/arm-kernel/msg171869.html

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
@ 2012-04-27 13:16                 ` Santosh Shilimkar
  0 siblings, 0 replies; 84+ messages in thread
From: Santosh Shilimkar @ 2012-04-27 13:16 UTC (permalink / raw)
  To: linux-arm-kernel

Greg,

On Monday 23 April 2012 08:14 PM, Shilimkar, Santosh wrote:
> On Mon, Apr 23, 2012 at 7:57 PM, Greg KH <greg@kroah.com> wrote:
>> On Mon, Apr 23, 2012 at 04:34:46PM +0530, Shilimkar, Santosh wrote:
>>> Afzal,
>>>
>>> On Mon, Apr 23, 2012 at 4:26 PM, Mohammed, Afzal <afzal@ti.com> wrote:
>>>> Hi Aneesh,
>>>>
>>>> On Fri, Apr 13, 2012 at 01:28:55, V, Aneesh wrote:
>>>>
>>>>> Thanks. I will wait for your review then. Once I have your comments
>>>>> I will re-work and submit in the new directory structure proposed.
>>>>
>>>> Do you have a plan on submitting EMIF driver in the new proposed
>>>> (drivers/memory) directory. Or shall I submit GPMC driver by creating
>>>> the new "memory" directory.
>>>>
>>>  Greg mentioned that he plans to do a review of EMIF driver. We were waiting
>>> for his comments before sending the updated series.
>>
>> No, don't wait for me, please resend, I was waiting for you :)
> 
> Thanks Greg !!
> Will start working on updating the patch set and post it on list.
> 
Have posted the updated version [1] as per discussion on
this thread.

Regards
Santosh

[1] http://www.spinics.net/lists/arm-kernel/msg171869.html

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

* [PATCH v4 0/7] Add TI EMIF SDRAM controller driver
  2012-03-19  1:08 함명주
@ 2012-03-19  7:07 ` Shilimkar, Santosh
  0 siblings, 0 replies; 84+ messages in thread
From: Shilimkar, Santosh @ 2012-03-19  7:07 UTC (permalink / raw)
  To: linux-arm-kernel

2012/3/19 ??? <myungjoo.ham@samsung.com>:
>
> Kyungmin Park<kmpark@infradead.org> 2012-03-17 15:10 (GMT+09:00)
>> Hi,
>> On 3/17/12, Aneesh V wrote:
>> > Add a driver for the EMIF SDRAM controller used in TI SoCs
>> >
>> > EMIF is an SDRAM controller that supports, based on its revision,
>> > one or more of LPDDR2/DDR2/DDR3 protocols.This driver adds support
>> > for LPDDR2.
>> >
>> > The driver supports the following features:
>> > - Calculates the DDR AC timing parameters to be set in EMIF
>> >   registers using data from the device data-sheets and based
>> >   on the DDR frequency. If data from data-sheets is not available
>> >   default timing values from the JEDEC spec are used. These
>> >   will be safe, but not necessarily optimal
>> > - API for changing timings during DVFS or at boot-up
>
> This means that you alreeady have callbacks to create a devfreq device driver that supports DVFS on the device. This doesn't need to be a misc device driver then.
>
Nope. The callbacks mentioned above are mainly coming from the clock
framework. Ofcourse the clock node trigger
with voltage ramps would be triggered by some upper laver
governor/framework like CPUFreq/DEVFREQ but as
such this is not necessary. This is an indepdent driver and just like
CPUFREQ notifies it's users for the frequency
change, this driver will be notified to take any action on pre and
post notification. Note that, the driver will
be notified by regulator framework for the voltage ramp up/down cases
too with notifiers.

>> > - Temperature alert configuration and handling of temperature
>> >   alerts, if any for LPDDR2 devices
>> >   * temperature alert is based on periodic polling of MR4 mode
>> >     register in DDR devices automatically performed by hardware
>> >   * timings are de-rated and brought back to nominal when
>> >     temperature raises and falls respectively
>
> This can be a feature overriding "max_freq" inside the Omap EMIF devfreq device driver though it maybe (or not.. I just don't sure) be better to use thermal framework as well.
>
That's absolute abuse and there is no need to link the temperature
handling with DVFS. Reducing frequency can be one
of the cooling techniques but that's not related to the temperature
alert handling. Temperature handling in the EMIF
driver is strictly as per the JDEC specs and that is to de-rate the
timings when temperature threshold is crossed.

The idea is drivers should be independent of all the global policy
governors. Hope this is clear to
you.

Regards
Santosh

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

end of thread, other threads:[~2012-04-27 13:16 UTC | newest]

Thread overview: 84+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-03-16 21:51 [PATCH v4 0/7] Add TI EMIF SDRAM controller driver Aneesh V
2012-03-16 21:51 ` Aneesh V
2012-03-16 21:51 ` [PATCH v4 1/7] misc: ddr: add LPDDR2 data from JESD209-2 Aneesh V
2012-03-16 21:51   ` Aneesh V
2012-03-16 21:51 ` [PATCH v4 2/7] misc: emif: add register definitions for EMIF Aneesh V
2012-03-16 21:51   ` Aneesh V
2012-03-16 21:51 ` [PATCH v4 3/7] misc: emif: add basic infrastructure for EMIF driver Aneesh V
2012-03-16 21:51   ` Aneesh V
2012-03-16 21:51 ` [PATCH v4 4/7] misc: emif: handle frequency and voltage change events Aneesh V
2012-03-16 21:51   ` Aneesh V
2012-03-16 21:51 ` [PATCH v4 5/7] misc: emif: add interrupt and temperature handling Aneesh V
2012-03-16 21:51   ` Aneesh V
2012-03-16 21:51 ` [PATCH v4 6/7] misc: emif: add one-time settings Aneesh V
2012-03-16 21:51   ` Aneesh V
2012-03-16 21:51 ` [PATCH v4 7/7] misc: emif: add debugfs entries for emif Aneesh V
2012-03-16 21:51   ` Aneesh V
2012-03-17  6:10 ` [PATCH v4 0/7] Add TI EMIF SDRAM controller driver Kyungmin Park
2012-03-17  6:10   ` Kyungmin Park
2012-03-17  6:10   ` Kyungmin Park
2012-04-12  2:44 ` Paul Walmsley
2012-04-12  2:44   ` Paul Walmsley
2012-04-12  2:57   ` Aneesh V
2012-04-12  2:57     ` Aneesh V
2012-04-12  2:57     ` Aneesh V
2012-04-12  3:00   ` Greg KH
2012-04-12  3:00     ` Greg KH
2012-04-12  3:12     ` Paul Walmsley
2012-04-12  3:12       ` Paul Walmsley
2012-04-12  6:47     ` Santosh Shilimkar
2012-04-12  6:47       ` Santosh Shilimkar
2012-04-12 13:10       ` Greg KH
2012-04-12 13:10         ` Greg KH
2012-04-12 13:34         ` Mohammed, Afzal
2012-04-12 13:34           ` Mohammed, Afzal
2012-04-12 13:34           ` Mohammed, Afzal
2012-04-12 14:10           ` Greg KH
2012-04-12 14:10             ` Greg KH
2012-04-12 14:10             ` Greg KH
2012-04-12 14:15             ` Mohammed, Afzal
2012-04-12 14:15               ` Mohammed, Afzal
2012-04-12 14:15               ` Mohammed, Afzal
2012-04-12 14:21           ` Kevin Hilman
2012-04-12 14:21             ` Kevin Hilman
2012-04-12 14:21             ` Kevin Hilman
2012-04-12 17:00           ` Paul Walmsley
2012-04-12 17:00             ` Paul Walmsley
2012-04-12 17:00             ` Paul Walmsley
2012-04-12 18:50             ` Cousson, Benoit
2012-04-12 18:50               ` Cousson, Benoit
2012-04-12 18:50               ` Cousson, Benoit
2012-04-12 19:15               ` Paul Walmsley
2012-04-12 19:15                 ` Paul Walmsley
2012-04-12 19:15                 ` Paul Walmsley
2012-04-12 19:24                 ` Cousson, Benoit
2012-04-12 19:24                   ` Cousson, Benoit
2012-04-12 19:24                   ` Cousson, Benoit
2012-04-13  9:07               ` Felipe Balbi
2012-04-13  9:07                 ` Felipe Balbi
2012-04-13  9:07                 ` Felipe Balbi
2012-04-12 14:14         ` Shilimkar, Santosh
2012-04-12 14:14           ` Shilimkar, Santosh
2012-04-12 19:58     ` V, Aneesh
2012-04-12 19:58       ` V, Aneesh
2012-04-23 10:56       ` Mohammed, Afzal
2012-04-23 10:56         ` Mohammed, Afzal
2012-04-23 10:56         ` Mohammed, Afzal
2012-04-23 11:04         ` Shilimkar, Santosh
2012-04-23 11:04           ` Shilimkar, Santosh
2012-04-23 11:04           ` Shilimkar, Santosh
2012-04-23 11:09           ` Mohammed, Afzal
2012-04-23 11:09             ` Mohammed, Afzal
2012-04-23 11:09             ` Mohammed, Afzal
2012-04-23 14:27           ` Greg KH
2012-04-23 14:27             ` Greg KH
2012-04-23 14:27             ` Greg KH
2012-04-23 14:44             ` Shilimkar, Santosh
2012-04-23 14:44               ` Shilimkar, Santosh
2012-04-23 14:44               ` Shilimkar, Santosh
2012-04-27 13:16               ` Santosh Shilimkar
2012-04-27 13:16                 ` Santosh Shilimkar
2012-04-27 13:16                 ` Santosh Shilimkar
2012-04-13 14:15   ` Mark Salter
2012-04-13 14:15     ` Mark Salter
2012-03-19  1:08 함명주
2012-03-19  7:07 ` Shilimkar, Santosh

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.