linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/4] dt: device tree support for TI EMIF driver for 3.6
@ 2012-06-29 13:43 Santosh Shilimkar
  2012-06-29 13:43 ` [PATCH v4 1/4] dt: device tree bindings for LPDDR2 memories Santosh Shilimkar
                   ` (3 more replies)
  0 siblings, 4 replies; 17+ messages in thread
From: Santosh Shilimkar @ 2012-06-29 13:43 UTC (permalink / raw)
  To: linux-arm-kernel

Tony,

Here is the EMIF driver DT support which was kept on hold for the driver
to get merged. The series has been already reviewed on the list.

v4:
Fixed the DT config flag and rebased against 3.5-rc4

v3:
Rebased against the 3.5-rc2

This series adds device tree support for TI EMIF SDRAM controller
driver. For this, a binding has been added for representing AC timing
parameters and other details of LPDDR2 memories.

It is available at:

git://github.com/SantoshShilimkar/linux.git for_3.6/emif_dt


Aneesh V (4):
  dt: device tree bindings for LPDDR2 memories
  dt: emif: device tree bindings for TI's EMIF sdram controller
  arm: dts: EMIF and LPDDR2 device tree data for OMAP4 boards
  memory: emif: add device tree support to emif driver

 .../devicetree/bindings/lpddr2/lpddr2-timings.txt  |   52 ++++
 .../devicetree/bindings/lpddr2/lpddr2.txt          |  102 +++++++
 .../bindings/memory-controllers/ti/emif.txt        |   55 ++++
 arch/arm/boot/dts/elpida_ecb240abacn.dtsi          |   67 +++++
 arch/arm/boot/dts/omap4-panda.dts                  |   13 +
 arch/arm/boot/dts/omap4-sdp.dts                    |   13 +
 arch/arm/boot/dts/omap4.dtsi                       |   18 ++
 drivers/memory/emif.c                              |  291 +++++++++++++++++++-
 8 files changed, 610 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt
 create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2.txt
 create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti/emif.txt
 create mode 100644 arch/arm/boot/dts/elpida_ecb240abacn.dtsi

-- 
1.7.9.5

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

* [PATCH v4 1/4] dt: device tree bindings for LPDDR2 memories
  2012-06-29 13:43 [PATCH v4 0/4] dt: device tree support for TI EMIF driver for 3.6 Santosh Shilimkar
@ 2012-06-29 13:43 ` Santosh Shilimkar
  2012-06-29 13:43 ` [PATCH v4 2/4] dt: emif: device tree bindings for TI's EMIF sdram controller Santosh Shilimkar
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 17+ messages in thread
From: Santosh Shilimkar @ 2012-06-29 13:43 UTC (permalink / raw)
  To: linux-arm-kernel

From: Aneesh V <aneesh@ti.com>

device tree bindings for LPDDR2 SDRAM memories compliant
to JESD209-2 standard.

The 'lpddr2' binding in-turn uses another binding 'lpddr2-timings'
for specifying the AC timing parameters of the memory device at
different speed-bins.

Reviewed-by: Benoit Cousson <b-cousson@ti.com>
Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
[santosh.shilimkar at ti.com: Rebased against 3.5-rc]
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
 .../devicetree/bindings/lpddr2/lpddr2-timings.txt  |   52 ++++++++++
 .../devicetree/bindings/lpddr2/lpddr2.txt          |  102 ++++++++++++++++++++
 2 files changed, 154 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt
 create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2.txt

diff --git a/Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt b/Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt
new file mode 100644
index 0000000..9ceb19e
--- /dev/null
+++ b/Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt
@@ -0,0 +1,52 @@
+* AC timing parameters of LPDDR2(JESD209-2) memories for a given speed-bin
+
+Required properties:
+- compatible : Should be "jedec,lpddr2-timings"
+- min-freq : minimum DDR clock frequency for the speed-bin. Type is <u32>
+- max-freq : maximum DDR clock frequency for the speed-bin. Type is <u32>
+
+Optional properties:
+
+The following properties represent AC timing parameters from the memory
+data-sheet of the device for a given speed-bin. All these properties are
+of type <u32> and the default unit is ps (pico seconds). Parameters with
+a different unit have a suffix indicating the unit such as 'tRAS-max-ns'
+- tRCD
+- tWR
+- tRAS-min
+- tRRD
+- tWTR
+- tXP
+- tRTP
+- tDQSCK-max
+- tFAW
+- tZQCS
+- tZQinit
+- tRPab
+- tZQCL
+- tCKESR
+- tRAS-max-ns
+- tDQSCK-max-derated
+
+Example:
+
+timings_elpida_ECB240ABACN_400mhz: lpddr2-timings at 0 {
+	compatible	= "jedec,lpddr2-timings";
+	min-freq	= <10000000>;
+	max-freq	= <400000000>;
+	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>;
+};
diff --git a/Documentation/devicetree/bindings/lpddr2/lpddr2.txt b/Documentation/devicetree/bindings/lpddr2/lpddr2.txt
new file mode 100644
index 0000000..58354a0
--- /dev/null
+++ b/Documentation/devicetree/bindings/lpddr2/lpddr2.txt
@@ -0,0 +1,102 @@
+* LPDDR2 SDRAM memories compliant to JEDEC JESD209-2
+
+Required properties:
+- compatible : Should be one of - "jedec,lpddr2-nvm", "jedec,lpddr2-s2",
+  "jedec,lpddr2-s4"
+
+  "ti,jedec-lpddr2-s2" should be listed if the memory part is LPDDR2-S2 type
+
+  "ti,jedec-lpddr2-s4" should be listed if the memory part is LPDDR2-S4 type
+
+  "ti,jedec-lpddr2-nvm" should be listed if the memory part is LPDDR2-NVM type
+
+- density  : <u32> representing density in Mb (Mega bits)
+
+- io-width : <u32> representing bus width. Possible values are 8, 16, and 32
+
+Optional properties:
+
+The following optional properties represent the minimum value of some AC
+timing parameters of the DDR device in terms of number of clock cycles.
+These values shall be obtained from the device data-sheet.
+- tRRD-min-tck
+- tWTR-min-tck
+- tXP-min-tck
+- tRTP-min-tck
+- tCKE-min-tck
+- tRPab-min-tck
+- tRCD-min-tck
+- tWR-min-tck
+- tRASmin-min-tck
+- tCKESR-min-tck
+- tFAW-min-tck
+
+Child nodes:
+- The lpddr2 node may have one or more child nodes of type "lpddr2-timings".
+  "lpddr2-timings" provides AC timing parameters of the device for
+  a given speed-bin. The user may provide the timings for as many
+  speed-bins as is required. Please see Documentation/devicetree/
+  bindings/lpddr2/lpddr2-timings.txt for more information on "lpddr2-timings"
+
+Example:
+
+elpida_ECB240ABACN : lpddr2 {
+	compatible	= "Elpida,ECB240ABACN","jedec,lpddr2-s4";
+	density		= <2048>;
+	io-width	= <32>;
+
+	tRPab-min-tck	= <3>;
+	tRCD-min-tck	= <3>;
+	tWR-min-tck	= <3>;
+	tRASmin-min-tck	= <3>;
+	tRRD-min-tck	= <2>;
+	tWTR-min-tck	= <2>;
+	tXP-min-tck	= <2>;
+	tRTP-min-tck	= <2>;
+	tCKE-min-tck	= <3>;
+	tCKESR-min-tck	= <3>;
+	tFAW-min-tck	= <8>;
+
+	timings_elpida_ECB240ABACN_400mhz: lpddr2-timings at 0 {
+		compatible	= "jedec,lpddr2-timings";
+		min-freq	= <10000000>;
+		max-freq	= <400000000>;
+		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>;
+	};
+
+	timings_elpida_ECB240ABACN_200mhz: lpddr2-timings at 1 {
+		compatible	= "jedec,lpddr2-timings";
+		min-freq	= <10000000>;
+		max-freq	= <200000000>;
+		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>;
+	};
+
+}
-- 
1.7.9.5

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

* [PATCH v4 2/4] dt: emif: device tree bindings for TI's EMIF sdram controller
  2012-06-29 13:43 [PATCH v4 0/4] dt: device tree support for TI EMIF driver for 3.6 Santosh Shilimkar
  2012-06-29 13:43 ` [PATCH v4 1/4] dt: device tree bindings for LPDDR2 memories Santosh Shilimkar
@ 2012-06-29 13:43 ` Santosh Shilimkar
  2012-06-29 13:43 ` [PATCH v4 3/4] arm: dts: EMIF and LPDDR2 device tree data for OMAP4 boards Santosh Shilimkar
  2012-06-29 13:43 ` [PATCH v4 4/4] memory: emif: add device tree support to emif driver Santosh Shilimkar
  3 siblings, 0 replies; 17+ messages in thread
From: Santosh Shilimkar @ 2012-06-29 13:43 UTC (permalink / raw)
  To: linux-arm-kernel

From: Aneesh V <aneesh@ti.com>

EMIF - External Memory Interface - is an SDRAM controller used in
TI SoCs. EMIF supports, based on the IP revision, one or more of
DDR2/DDR3/LPDDR2 protocols. This binding describes a given instance
of the EMIF IP and memory parts attached to it.

Reviewed-by: Benoit Cousson <b-cousson@ti.com>
Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
[santosh.shilimkar at ti.com: Rebased against 3.5-rc]
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
 .../bindings/memory-controllers/ti/emif.txt        |   55 ++++++++++++++++++++
 1 file changed, 55 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti/emif.txt

diff --git a/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt
new file mode 100644
index 0000000..938f8e1
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt
@@ -0,0 +1,55 @@
+* EMIF family of TI SDRAM controllers
+
+EMIF - External Memory Interface - is an SDRAM controller used in
+TI SoCs. EMIF supports, based on the IP revision, one or more of
+DDR2/DDR3/LPDDR2 protocols. This binding describes a given instance
+of the EMIF IP and memory parts attached to it.
+
+Required properties:
+- compatible	: Should be of the form "ti,emif-<ip-rev>" where <ip-rev>
+  is the IP revision of the specific EMIF instance.
+
+- phy-type	: <u32> indicating the DDR phy type. Following are the
+  allowed values
+  <1>	: Attila PHY
+  <2>	: Intelli PHY
+
+- device-handle	: phandle to a "lpddr2" node representing the memory part
+
+- ti,hwmods	: For TI hwmods processing and omap device creation
+  the value shall be "emif<n>" where <n> is the number of the EMIF
+  instance with base 1.
+
+Optional properties:
+- cs1-used		: Have this property if CS1 of this EMIF
+  instance has a memory part attached to it. If there is a memory
+  part attached to CS1, it should be the same type as the one on CS0,
+  so there is no need to give the details of this memory part.
+
+- cal-resistor-per-cs	: Have this property if the board has one
+  calibration resistor per chip-select.
+
+- hw-caps-read-idle-ctrl: Have this property if the controller
+  supports read idle window programming
+
+- hw-caps-dll-calib-ctrl: Have this property if the controller
+  supports dll calibration control
+
+- hw-caps-ll-interface	: Have this property if the controller
+  has a low latency interface and corresponding interrupt events
+
+- hw-caps-temp-alert	: Have this property if the controller
+  has capability for generating SDRAM temperature alerts
+
+Example:
+
+emif1: emif at 0x4c000000 {
+	compatible	= "ti,emif-4d";
+	ti,hwmods	= "emif2";
+	phy-type	= <1>;
+	device-handle	= <&elpida_ECB240ABACN>;
+	cs1-used;
+	hw-caps-read-idle-ctrl;
+	hw-caps-ll-interface;
+	hw-caps-temp-alert;
+};
-- 
1.7.9.5

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

* [PATCH v4 3/4] arm: dts: EMIF and LPDDR2 device tree data for OMAP4 boards
  2012-06-29 13:43 [PATCH v4 0/4] dt: device tree support for TI EMIF driver for 3.6 Santosh Shilimkar
  2012-06-29 13:43 ` [PATCH v4 1/4] dt: device tree bindings for LPDDR2 memories Santosh Shilimkar
  2012-06-29 13:43 ` [PATCH v4 2/4] dt: emif: device tree bindings for TI's EMIF sdram controller Santosh Shilimkar
@ 2012-06-29 13:43 ` Santosh Shilimkar
  2012-06-29 13:43 ` [PATCH v4 4/4] memory: emif: add device tree support to emif driver Santosh Shilimkar
  3 siblings, 0 replies; 17+ messages in thread
From: Santosh Shilimkar @ 2012-06-29 13:43 UTC (permalink / raw)
  To: linux-arm-kernel

From: Aneesh V <aneesh@ti.com>

Device tree data for the EMIF sdram controllers in OMAP4
and LPDDR2 memory devices attached to OMAP4 boards.

Reviewed-by: Benoit Cousson <b-cousson@ti.com>
Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
[santosh.shilimkar at ti.com: Rebased against 3.5-rc]
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
 arch/arm/boot/dts/elpida_ecb240abacn.dtsi |   67 +++++++++++++++++++++++++++++
 arch/arm/boot/dts/omap4-panda.dts         |   13 ++++++
 arch/arm/boot/dts/omap4-sdp.dts           |   13 ++++++
 arch/arm/boot/dts/omap4.dtsi              |   18 ++++++++
 4 files changed, 111 insertions(+)
 create mode 100644 arch/arm/boot/dts/elpida_ecb240abacn.dtsi

diff --git a/arch/arm/boot/dts/elpida_ecb240abacn.dtsi b/arch/arm/boot/dts/elpida_ecb240abacn.dtsi
new file mode 100644
index 0000000..f97f70f
--- /dev/null
+++ b/arch/arm/boot/dts/elpida_ecb240abacn.dtsi
@@ -0,0 +1,67 @@
+/*
+ * Common devices used in different OMAP boards
+ */
+
+/ {
+	elpida_ECB240ABACN: lpddr2 {
+		compatible	= "Elpida,ECB240ABACN","jedec,lpddr2-s4";
+		density		= <2048>;
+		io-width	= <32>;
+
+		tRPab-min-tck	= <3>;
+		tRCD-min-tck	= <3>;
+		tWR-min-tck	= <3>;
+		tRASmin-min-tck	= <3>;
+		tRRD-min-tck	= <2>;
+		tWTR-min-tck	= <2>;
+		tXP-min-tck	= <2>;
+		tRTP-min-tck	= <2>;
+		tCKE-min-tck	= <3>;
+		tCKESR-min-tck	= <3>;
+		tFAW-min-tck	= <8>;
+
+		timings_elpida_ECB240ABACN_400mhz: lpddr2-timings at 0 {
+			compatible	= "jedec,lpddr2-timings";
+			min-freq	= <10000000>;
+			max-freq	= <400000000>;
+			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>;
+		};
+
+		timings_elpida_ECB240ABACN_200mhz: lpddr2-timings at 1 {
+			compatible	= "jedec,lpddr2-timings";
+			min-freq	= <10000000>;
+			max-freq	= <200000000>;
+			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>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts
index 1efe0c5..08a0b21 100644
--- a/arch/arm/boot/dts/omap4-panda.dts
+++ b/arch/arm/boot/dts/omap4-panda.dts
@@ -8,6 +8,7 @@
 /dts-v1/;
 
 /include/ "omap4.dtsi"
+/include/ "elpida_ecb240abacn.dtsi"
 
 / {
 	model = "TI OMAP4 PandaBoard";
@@ -32,6 +33,18 @@
 			linux,default-trigger = "mmc0";
 		};
 	};
+
+	ocp {
+		emif1: emif at 0x4c000000 {
+			cs1-used;
+			device-handle = <&elpida_ECB240ABACN>;
+		};
+
+		emif2: emif at 0x4d000000 {
+			cs1-used;
+			device-handle = <&elpida_ECB240ABACN>;
+		};
+	};
 };
 
 &i2c1 {
diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts
index d08c4d1..562f03e 100644
--- a/arch/arm/boot/dts/omap4-sdp.dts
+++ b/arch/arm/boot/dts/omap4-sdp.dts
@@ -8,6 +8,7 @@
 /dts-v1/;
 
 /include/ "omap4.dtsi"
+/include/ "elpida_ecb240abacn.dtsi"
 
 / {
 	model = "TI OMAP4 SDP board";
@@ -70,6 +71,18 @@
 			gpios = <&gpio5 11 0>; /* 139 */
 		};
 	};
+
+	ocp {
+		emif1: emif at 0x4c000000 {
+			cs1-used;
+			device-handle = <&elpida_ECB240ABACN>;
+		};
+
+		emif2: emif at 0x4d000000 {
+			cs1-used;
+			device-handle = <&elpida_ECB240ABACN>;
+		};
+	};
 };
 
 &i2c1 {
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 359c497..08813c4 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -272,5 +272,23 @@
 			ti,hwmods = "mmc5";
 			ti,needs-special-reset;
 		};
+
+		emif1: emif at 0x4c000000 {
+			compatible	= "ti,emif-4d";
+			ti,hwmods	= "emif1";
+			phy-type	= <1>;
+			hw-caps-read-idle-ctrl;
+			hw-caps-ll-interface;
+			hw-caps-temp-alert;
+		};
+
+		emif2: emif at 0x4d000000 {
+			compatible	= "ti,emif-4d";
+			ti,hwmods	= "emif2";
+			phy-type	= <1>;
+			hw-caps-read-idle-ctrl;
+			hw-caps-ll-interface;
+			hw-caps-temp-alert;
+		};
 	};
 };
-- 
1.7.9.5

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

* [PATCH v4 4/4] memory: emif: add device tree support to emif driver
  2012-06-29 13:43 [PATCH v4 0/4] dt: device tree support for TI EMIF driver for 3.6 Santosh Shilimkar
                   ` (2 preceding siblings ...)
  2012-06-29 13:43 ` [PATCH v4 3/4] arm: dts: EMIF and LPDDR2 device tree data for OMAP4 boards Santosh Shilimkar
@ 2012-06-29 13:43 ` Santosh Shilimkar
  2012-06-30  4:08   ` Shilimkar, Santosh
  3 siblings, 1 reply; 17+ messages in thread
From: Santosh Shilimkar @ 2012-06-29 13:43 UTC (permalink / raw)
  To: linux-arm-kernel

From: Aneesh V <aneesh@ti.com>

Device tree support for the EMIF driver.

Reviewed-by: Benoit Cousson <b-cousson@ti.com>
Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
[santosh.shilimkar at ti.com: Rebased against 3.5-rc]
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
 drivers/memory/emif.c |  291 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 290 insertions(+), 1 deletion(-)

diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
index 33a4396..101997b 100644
--- a/drivers/memory/emif.c
+++ b/drivers/memory/emif.c
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/module.h>
@@ -49,6 +50,7 @@
  *				frequency in effect at the moment)
  * @plat_data:			Pointer to saved platform data.
  * @debugfs_root:		dentry to the root folder for EMIF in debugfs
+ * @np_ddr:			Pointer to ddr device tree node
  */
 struct emif_data {
 	u8				duplicate;
@@ -63,6 +65,7 @@ struct emif_data {
 	struct emif_regs		*curr_regs;
 	struct emif_platform_data	*plat_data;
 	struct dentry			*debugfs_root;
+	struct device_node		*np_ddr;
 };
 
 static struct emif_data *emif1;
@@ -1148,6 +1151,278 @@ static int is_custom_config_valid(struct emif_custom_configs *cust_cfgs,
 	return valid;
 }
 
+#if defined(CONFIG_OF)
+static void __init_or_module of_get_custom_configs(struct device_node *np_emif,
+		struct emif_data *emif)
+{
+	struct emif_custom_configs	*cust_cfgs = NULL;
+	int				len;
+	const int			*lpmode, *poll_intvl;
+
+	lpmode = of_get_property(np_emif, "low-power-mode", &len);
+	poll_intvl = of_get_property(np_emif, "temp-alert-poll-interval", &len);
+
+	if (lpmode || poll_intvl)
+		cust_cfgs = devm_kzalloc(emif->dev, sizeof(*cust_cfgs),
+			GFP_KERNEL);
+
+	if (!cust_cfgs)
+		return;
+
+	if (lpmode) {
+		cust_cfgs->mask |= EMIF_CUSTOM_CONFIG_LPMODE;
+		cust_cfgs->lpmode = *lpmode;
+		of_property_read_u32(np_emif,
+				"low-power-mode-timeout-performance",
+				&cust_cfgs->lpmode_timeout_performance);
+		of_property_read_u32(np_emif,
+				"low-power-mode-timeout-power",
+				&cust_cfgs->lpmode_timeout_power);
+		of_property_read_u32(np_emif,
+				"low-power-mode-freq-threshold",
+				&cust_cfgs->lpmode_freq_threshold);
+	}
+
+	if (poll_intvl) {
+		cust_cfgs->mask |=
+				EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL;
+		cust_cfgs->temp_alert_poll_interval_ms = *poll_intvl;
+	}
+
+	if (!is_custom_config_valid(cust_cfgs, emif->dev)) {
+		devm_kfree(emif->dev, cust_cfgs);
+		return;
+	}
+
+	emif->plat_data->custom_configs = cust_cfgs;
+}
+
+static void __init_or_module of_get_min_tck(struct device_node *np,
+		struct emif_data *emif)
+{
+	int			ret = 0;
+	struct lpddr2_min_tck	*min;
+
+	min = devm_kzalloc(emif->dev, sizeof(*min), GFP_KERNEL);
+	if (!min)
+		goto default_min_tck;
+
+	ret |= of_property_read_u32(np, "tRPab-min-tck", &min->tRPab);
+	ret |= of_property_read_u32(np, "tRCD-min-tck", &min->tRCD);
+	ret |= of_property_read_u32(np, "tWR-min-tck", &min->tWR);
+	ret |= of_property_read_u32(np, "tRASmin-min-tck", &min->tRASmin);
+	ret |= of_property_read_u32(np, "tRRD-min-tck", &min->tRRD);
+	ret |= of_property_read_u32(np, "tWTR-min-tck", &min->tWTR);
+	ret |= of_property_read_u32(np, "tXP-min-tck", &min->tXP);
+	ret |= of_property_read_u32(np, "tRTP-min-tck", &min->tRTP);
+	ret |= of_property_read_u32(np, "tCKE-min-tck", &min->tCKE);
+	ret |= of_property_read_u32(np, "tCKESR-min-tck", &min->tCKESR);
+	ret |= of_property_read_u32(np, "tFAW-min-tck", &min->tFAW);
+
+	if (ret) {
+		devm_kfree(emif->dev, min);
+		goto default_min_tck;
+	}
+
+	emif->plat_data->min_tck = min;
+	return;
+
+default_min_tck:
+	dev_warn(emif->dev, "%s: using default min-tck values\n", __func__);
+	emif->plat_data->min_tck = &lpddr2_jedec_min_tck;
+}
+
+static int __init_or_module of_do_get_timings(struct device_node *np,
+		struct lpddr2_timings *tim)
+{
+	int ret;
+
+	ret = of_property_read_u32(np, "max-freq", &tim->max_freq);
+	ret |= of_property_read_u32(np, "min-freq", &tim->min_freq);
+	ret |= of_property_read_u32(np, "tRPab", &tim->tRPab);
+	ret |= of_property_read_u32(np, "tRCD", &tim->tRCD);
+	ret |= of_property_read_u32(np, "tWR", &tim->tWR);
+	ret |= of_property_read_u32(np, "tRAS-min", &tim->tRAS_min);
+	ret |= of_property_read_u32(np, "tRRD", &tim->tRRD);
+	ret |= of_property_read_u32(np, "tWTR", &tim->tWTR);
+	ret |= of_property_read_u32(np, "tXP", &tim->tXP);
+	ret |= of_property_read_u32(np, "tRTP", &tim->tRTP);
+	ret |= of_property_read_u32(np, "tCKESR", &tim->tCKESR);
+	ret |= of_property_read_u32(np, "tDQSCK-max", &tim->tDQSCK_max);
+	ret |= of_property_read_u32(np, "tFAW", &tim->tFAW);
+	ret |= of_property_read_u32(np, "tZQCS", &tim->tZQCS);
+	ret |= of_property_read_u32(np, "tZQCL", &tim->tZQCL);
+	ret |= of_property_read_u32(np, "tZQinit", &tim->tZQinit);
+	ret |= of_property_read_u32(np, "tRAS-max-ns", &tim->tRAS_max_ns);
+	ret |= of_property_read_u32(np, "tDQSCK-max-derated",
+		&tim->tDQSCK_max_derated);
+
+	return ret;
+}
+
+static void __init_or_module of_get_ddr_timings(struct device_node *np_ddr,
+		struct emif_data *emif)
+{
+	struct lpddr2_timings	*timings = NULL;
+	u32			arr_sz = 0, i = 0;
+	struct device_node	*np_tim;
+	char			*tim_compat;
+
+	switch (emif->plat_data->device_info->type) {
+	case DDR_TYPE_LPDDR2_S2:
+	case DDR_TYPE_LPDDR2_S4:
+		tim_compat = "jedec,lpddr2-timings";
+		break;
+	default:
+		dev_warn(emif->dev, "%s: un-supported memory type\n", __func__);
+	}
+
+	for_each_child_of_node(np_ddr, np_tim)
+		if (of_device_is_compatible(np_tim, tim_compat))
+			arr_sz++;
+
+	if (arr_sz)
+		timings = devm_kzalloc(emif->dev, sizeof(*timings) * arr_sz,
+			GFP_KERNEL);
+
+	if (!timings)
+		goto default_timings;
+
+	for_each_child_of_node(np_ddr, np_tim) {
+		if (of_device_is_compatible(np_tim, tim_compat)) {
+			if (of_do_get_timings(np_tim, &timings[i])) {
+				devm_kfree(emif->dev, timings);
+				goto default_timings;
+			}
+			i++;
+		}
+	}
+
+	emif->plat_data->timings = timings;
+	emif->plat_data->timings_arr_size = arr_sz;
+
+	return;
+
+default_timings:
+	get_default_timings(emif);
+
+	return;
+}
+
+static void __init_or_module of_get_ddr_info(struct device_node *np_emif,
+		struct device_node *np_ddr,
+		struct ddr_device_info *dev_info)
+{
+	u32 density = 0, io_width = 0;
+	int len;
+
+	if (of_find_property(np_emif, "cs1-used", &len))
+		dev_info->cs1_used = true;
+
+	if (of_find_property(np_emif, "cal-resistor-per-cs", &len))
+		dev_info->cal_resistors_per_cs = true;
+
+	if (of_device_is_compatible(np_ddr , "jedec,lpddr2-s4"))
+		dev_info->type = DDR_TYPE_LPDDR2_S4;
+	else if (of_device_is_compatible(np_ddr , "jedec,lpddr2-s2"))
+		dev_info->type = DDR_TYPE_LPDDR2_S2;
+
+	of_property_read_u32(np_ddr, "density", &density);
+	of_property_read_u32(np_ddr, "io-width", &io_width);
+
+	/* Convert from density in Mb to the density encoding in jedc_ddr.h */
+	if (density & (density - 1))
+		dev_info->density = 0;
+	else
+		dev_info->density = __fls(density) - 5;
+
+	/* Convert from io_width in bits to io_width encoding in jedc_ddr.h */
+	if (io_width & (io_width - 1))
+		dev_info->io_width = 0;
+	else
+		dev_info->io_width = __fls(io_width) - 1;
+}
+
+static struct emif_data * __init_or_module of_get_device_details(
+		struct device_node *np_emif, struct device *dev)
+{
+	struct emif_data		*emif = NULL;
+	struct ddr_device_info		*dev_info = NULL;
+	struct emif_platform_data	*pd = NULL;
+	struct device_node		*np_ddr;
+	int				len;
+
+	np_ddr = of_parse_phandle(np_emif, "device-handle", 0);
+	if (!np_ddr)
+		goto error;
+	emif	= devm_kzalloc(dev, sizeof(struct emif_data), GFP_KERNEL);
+	pd	= 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: of_get_device_details() failure!!\n",
+			__func__);
+		goto error;
+	}
+
+	emif->plat_data		= pd;
+	pd->device_info		= dev_info;
+	emif->dev		= dev;
+	emif->np_ddr		= np_ddr;
+	emif->temperature_level	= SDRAM_TEMP_NOMINAL;
+
+	if (of_device_is_compatible(np_emif, "ti,emif-4d"))
+		emif->plat_data->ip_rev = EMIF_4D;
+	else if (of_device_is_compatible(np_emif, "ti,emif-4d5"))
+		emif->plat_data->ip_rev = EMIF_4D5;
+
+	of_property_read_u32(np_emif, "phy-type", &pd->phy_type);
+
+	if (of_find_property(np_emif, "hw-caps-ll-interface", &len))
+		pd->hw_caps |= EMIF_HW_CAPS_LL_INTERFACE;
+
+	of_get_ddr_info(np_emif, np_ddr, dev_info);
+	if (!is_dev_data_valid(pd->device_info->type, pd->device_info->density,
+			pd->device_info->io_width, pd->phy_type, pd->ip_rev,
+			emif->dev)) {
+		dev_err(dev, "%s: invalid device data!!\n", __func__);
+		goto error;
+	}
+	/*
+	 * 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. This will save some memory and
+	 * computation.
+	 */
+	if (emif1 && emif1->np_ddr == np_ddr) {
+		emif->duplicate = true;
+		goto out;
+	} else if (emif1) {
+		dev_warn(emif->dev, "%s: Non-symmetric DDR geometry\n",
+			__func__);
+	}
+
+
+	of_get_custom_configs(np_emif, emif);
+	of_get_ddr_timings(np_ddr, emif);
+	of_get_min_tck(np_ddr, emif);
+	goto out;
+
+error:
+	return NULL;
+out:
+	return emif;
+}
+
+#else
+
+static struct emif_data * __init_or_module of_get_device_details(
+		struct device_node *np_emif, struct device *dev)
+{
+	return NULL;
+}
+#endif
+
 static struct emif_data *__init_or_module get_device_details(
 		struct platform_device *pdev)
 {
@@ -1267,7 +1542,11 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
 	struct resource		*res;
 	int			irq;
 
-	emif = get_device_details(pdev);
+	if (pdev->dev.of_node)
+		emif = of_get_device_details(pdev->dev.of_node, &pdev->dev);
+	else
+		emif = get_device_details(pdev);
+
 	if (!emif) {
 		pr_err("%s: error getting device data\n", __func__);
 		goto error;
@@ -1644,11 +1923,21 @@ static void __attribute__((unused)) freq_post_notify_handling(void)
 	spin_unlock_irqrestore(&emif_lock, irq_state);
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id emif_of_match[] = {
+		{ .compatible = "ti,emif-4d" },
+		{ .compatible = "ti,emif-4d5" },
+		{},
+};
+MODULE_DEVICE_TABLE(of, emif_of_match);
+#endif
+
 static struct platform_driver emif_driver = {
 	.remove		= __exit_p(emif_remove),
 	.shutdown	= emif_shutdown,
 	.driver = {
 		.name = "emif",
+		.of_match_table = of_match_ptr(emif_of_match),
 	},
 };
 
-- 
1.7.9.5

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

* [PATCH v4 4/4] memory: emif: add device tree support to emif driver
  2012-06-29 13:43 ` [PATCH v4 4/4] memory: emif: add device tree support to emif driver Santosh Shilimkar
@ 2012-06-30  4:08   ` Shilimkar, Santosh
  2012-06-30  4:23     ` Greg KH
  0 siblings, 1 reply; 17+ messages in thread
From: Shilimkar, Santosh @ 2012-06-30  4:08 UTC (permalink / raw)
  To: linux-arm-kernel

(+ Greg, By mistake the your name got dropped cc from list)

On Fri, Jun 29, 2012 at 7:13 PM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
> From: Aneesh V <aneesh@ti.com>
>
> Device tree support for the EMIF driver.
>
> Reviewed-by: Benoit Cousson <b-cousson@ti.com>
> Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
> Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
> Signed-off-by: Aneesh V <aneesh@ti.com>
> [santosh.shilimkar at ti.com: Rebased against 3.5-rc]
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> ---
> ?drivers/memory/emif.c | ?291 ++++++++++++++++++++++++++++++++++++++++++++++++-
> ?1 file changed, 290 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
> index 33a4396..101997b 100644
> --- a/drivers/memory/emif.c
> +++ b/drivers/memory/emif.c
> @@ -18,6 +18,7 @@
> ?#include <linux/platform_device.h>
> ?#include <linux/interrupt.h>
> ?#include <linux/slab.h>
> +#include <linux/of.h>
> ?#include <linux/debugfs.h>
> ?#include <linux/seq_file.h>
> ?#include <linux/module.h>
> @@ -49,6 +50,7 @@
> ?* ? ? ? ? ? ? ? ? ? ? ? ? ? ? frequency in effect at the moment)
> ?* @plat_data: ? ? ? ? ? ? ? ? Pointer to saved platform data.
> ?* @debugfs_root: ? ? ? ? ? ? ?dentry to the root folder for EMIF in debugfs
> + * @np_ddr: ? ? ? ? ? ? ? ? ? ?Pointer to ddr device tree node
> ?*/
> ?struct emif_data {
> ? ? ? ?u8 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?duplicate;
> @@ -63,6 +65,7 @@ struct emif_data {
> ? ? ? ?struct emif_regs ? ? ? ? ? ? ? ?*curr_regs;
> ? ? ? ?struct emif_platform_data ? ? ? *plat_data;
> ? ? ? ?struct dentry ? ? ? ? ? ? ? ? ? *debugfs_root;
> + ? ? ? struct device_node ? ? ? ? ? ? ?*np_ddr;
> ?};
>
> ?static struct emif_data *emif1;
> @@ -1148,6 +1151,278 @@ static int is_custom_config_valid(struct emif_custom_configs *cust_cfgs,
> ? ? ? ?return valid;
> ?}
>
> +#if defined(CONFIG_OF)
> +static void __init_or_module of_get_custom_configs(struct device_node *np_emif,
> + ? ? ? ? ? ? ? struct emif_data *emif)
> +{
> + ? ? ? struct emif_custom_configs ? ? ?*cust_cfgs = NULL;
> + ? ? ? int ? ? ? ? ? ? ? ? ? ? ? ? ? ? len;
> + ? ? ? const int ? ? ? ? ? ? ? ? ? ? ? *lpmode, *poll_intvl;
> +
> + ? ? ? lpmode = of_get_property(np_emif, "low-power-mode", &len);
> + ? ? ? poll_intvl = of_get_property(np_emif, "temp-alert-poll-interval", &len);
> +
> + ? ? ? if (lpmode || poll_intvl)
> + ? ? ? ? ? ? ? cust_cfgs = devm_kzalloc(emif->dev, sizeof(*cust_cfgs),
> + ? ? ? ? ? ? ? ? ? ? ? GFP_KERNEL);
> +
> + ? ? ? if (!cust_cfgs)
> + ? ? ? ? ? ? ? return;
> +
> + ? ? ? if (lpmode) {
> + ? ? ? ? ? ? ? cust_cfgs->mask |= EMIF_CUSTOM_CONFIG_LPMODE;
> + ? ? ? ? ? ? ? cust_cfgs->lpmode = *lpmode;
> + ? ? ? ? ? ? ? of_property_read_u32(np_emif,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "low-power-mode-timeout-performance",
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &cust_cfgs->lpmode_timeout_performance);
> + ? ? ? ? ? ? ? of_property_read_u32(np_emif,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "low-power-mode-timeout-power",
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &cust_cfgs->lpmode_timeout_power);
> + ? ? ? ? ? ? ? of_property_read_u32(np_emif,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "low-power-mode-freq-threshold",
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &cust_cfgs->lpmode_freq_threshold);
> + ? ? ? }
> +
> + ? ? ? if (poll_intvl) {
> + ? ? ? ? ? ? ? cust_cfgs->mask |=
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL;
> + ? ? ? ? ? ? ? cust_cfgs->temp_alert_poll_interval_ms = *poll_intvl;
> + ? ? ? }
> +
> + ? ? ? if (!is_custom_config_valid(cust_cfgs, emif->dev)) {
> + ? ? ? ? ? ? ? devm_kfree(emif->dev, cust_cfgs);
> + ? ? ? ? ? ? ? return;
> + ? ? ? }
> +
> + ? ? ? emif->plat_data->custom_configs = cust_cfgs;
> +}
> +
> +static void __init_or_module of_get_min_tck(struct device_node *np,
> + ? ? ? ? ? ? ? struct emif_data *emif)
> +{
> + ? ? ? int ? ? ? ? ? ? ? ? ? ? ret = 0;
> + ? ? ? struct lpddr2_min_tck ? *min;
> +
> + ? ? ? min = devm_kzalloc(emif->dev, sizeof(*min), GFP_KERNEL);
> + ? ? ? if (!min)
> + ? ? ? ? ? ? ? goto default_min_tck;
> +
> + ? ? ? ret |= of_property_read_u32(np, "tRPab-min-tck", &min->tRPab);
> + ? ? ? ret |= of_property_read_u32(np, "tRCD-min-tck", &min->tRCD);
> + ? ? ? ret |= of_property_read_u32(np, "tWR-min-tck", &min->tWR);
> + ? ? ? ret |= of_property_read_u32(np, "tRASmin-min-tck", &min->tRASmin);
> + ? ? ? ret |= of_property_read_u32(np, "tRRD-min-tck", &min->tRRD);
> + ? ? ? ret |= of_property_read_u32(np, "tWTR-min-tck", &min->tWTR);
> + ? ? ? ret |= of_property_read_u32(np, "tXP-min-tck", &min->tXP);
> + ? ? ? ret |= of_property_read_u32(np, "tRTP-min-tck", &min->tRTP);
> + ? ? ? ret |= of_property_read_u32(np, "tCKE-min-tck", &min->tCKE);
> + ? ? ? ret |= of_property_read_u32(np, "tCKESR-min-tck", &min->tCKESR);
> + ? ? ? ret |= of_property_read_u32(np, "tFAW-min-tck", &min->tFAW);
> +
> + ? ? ? if (ret) {
> + ? ? ? ? ? ? ? devm_kfree(emif->dev, min);
> + ? ? ? ? ? ? ? goto default_min_tck;
> + ? ? ? }
> +
> + ? ? ? emif->plat_data->min_tck = min;
> + ? ? ? return;
> +
> +default_min_tck:
> + ? ? ? dev_warn(emif->dev, "%s: using default min-tck values\n", __func__);
> + ? ? ? emif->plat_data->min_tck = &lpddr2_jedec_min_tck;
> +}
> +
> +static int __init_or_module of_do_get_timings(struct device_node *np,
> + ? ? ? ? ? ? ? struct lpddr2_timings *tim)
> +{
> + ? ? ? int ret;
> +
> + ? ? ? ret = of_property_read_u32(np, "max-freq", &tim->max_freq);
> + ? ? ? ret |= of_property_read_u32(np, "min-freq", &tim->min_freq);
> + ? ? ? ret |= of_property_read_u32(np, "tRPab", &tim->tRPab);
> + ? ? ? ret |= of_property_read_u32(np, "tRCD", &tim->tRCD);
> + ? ? ? ret |= of_property_read_u32(np, "tWR", &tim->tWR);
> + ? ? ? ret |= of_property_read_u32(np, "tRAS-min", &tim->tRAS_min);
> + ? ? ? ret |= of_property_read_u32(np, "tRRD", &tim->tRRD);
> + ? ? ? ret |= of_property_read_u32(np, "tWTR", &tim->tWTR);
> + ? ? ? ret |= of_property_read_u32(np, "tXP", &tim->tXP);
> + ? ? ? ret |= of_property_read_u32(np, "tRTP", &tim->tRTP);
> + ? ? ? ret |= of_property_read_u32(np, "tCKESR", &tim->tCKESR);
> + ? ? ? ret |= of_property_read_u32(np, "tDQSCK-max", &tim->tDQSCK_max);
> + ? ? ? ret |= of_property_read_u32(np, "tFAW", &tim->tFAW);
> + ? ? ? ret |= of_property_read_u32(np, "tZQCS", &tim->tZQCS);
> + ? ? ? ret |= of_property_read_u32(np, "tZQCL", &tim->tZQCL);
> + ? ? ? ret |= of_property_read_u32(np, "tZQinit", &tim->tZQinit);
> + ? ? ? ret |= of_property_read_u32(np, "tRAS-max-ns", &tim->tRAS_max_ns);
> + ? ? ? ret |= of_property_read_u32(np, "tDQSCK-max-derated",
> + ? ? ? ? ? ? ? &tim->tDQSCK_max_derated);
> +
> + ? ? ? return ret;
> +}
> +
> +static void __init_or_module of_get_ddr_timings(struct device_node *np_ddr,
> + ? ? ? ? ? ? ? struct emif_data *emif)
> +{
> + ? ? ? struct lpddr2_timings ? *timings = NULL;
> + ? ? ? u32 ? ? ? ? ? ? ? ? ? ? arr_sz = 0, i = 0;
> + ? ? ? struct device_node ? ? ?*np_tim;
> + ? ? ? char ? ? ? ? ? ? ? ? ? ?*tim_compat;
> +
> + ? ? ? switch (emif->plat_data->device_info->type) {
> + ? ? ? case DDR_TYPE_LPDDR2_S2:
> + ? ? ? case DDR_TYPE_LPDDR2_S4:
> + ? ? ? ? ? ? ? tim_compat = "jedec,lpddr2-timings";
> + ? ? ? ? ? ? ? break;
> + ? ? ? default:
> + ? ? ? ? ? ? ? dev_warn(emif->dev, "%s: un-supported memory type\n", __func__);
> + ? ? ? }
> +
> + ? ? ? for_each_child_of_node(np_ddr, np_tim)
> + ? ? ? ? ? ? ? if (of_device_is_compatible(np_tim, tim_compat))
> + ? ? ? ? ? ? ? ? ? ? ? arr_sz++;
> +
> + ? ? ? if (arr_sz)
> + ? ? ? ? ? ? ? timings = devm_kzalloc(emif->dev, sizeof(*timings) * arr_sz,
> + ? ? ? ? ? ? ? ? ? ? ? GFP_KERNEL);
> +
> + ? ? ? if (!timings)
> + ? ? ? ? ? ? ? goto default_timings;
> +
> + ? ? ? for_each_child_of_node(np_ddr, np_tim) {
> + ? ? ? ? ? ? ? if (of_device_is_compatible(np_tim, tim_compat)) {
> + ? ? ? ? ? ? ? ? ? ? ? if (of_do_get_timings(np_tim, &timings[i])) {
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? devm_kfree(emif->dev, timings);
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? goto default_timings;
> + ? ? ? ? ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? ? ? ? ? i++;
> + ? ? ? ? ? ? ? }
> + ? ? ? }
> +
> + ? ? ? emif->plat_data->timings = timings;
> + ? ? ? emif->plat_data->timings_arr_size = arr_sz;
> +
> + ? ? ? return;
> +
> +default_timings:
> + ? ? ? get_default_timings(emif);
> +
> + ? ? ? return;
> +}
> +
> +static void __init_or_module of_get_ddr_info(struct device_node *np_emif,
> + ? ? ? ? ? ? ? struct device_node *np_ddr,
> + ? ? ? ? ? ? ? struct ddr_device_info *dev_info)
> +{
> + ? ? ? u32 density = 0, io_width = 0;
> + ? ? ? int len;
> +
> + ? ? ? if (of_find_property(np_emif, "cs1-used", &len))
> + ? ? ? ? ? ? ? dev_info->cs1_used = true;
> +
> + ? ? ? if (of_find_property(np_emif, "cal-resistor-per-cs", &len))
> + ? ? ? ? ? ? ? dev_info->cal_resistors_per_cs = true;
> +
> + ? ? ? if (of_device_is_compatible(np_ddr , "jedec,lpddr2-s4"))
> + ? ? ? ? ? ? ? dev_info->type = DDR_TYPE_LPDDR2_S4;
> + ? ? ? else if (of_device_is_compatible(np_ddr , "jedec,lpddr2-s2"))
> + ? ? ? ? ? ? ? dev_info->type = DDR_TYPE_LPDDR2_S2;
> +
> + ? ? ? of_property_read_u32(np_ddr, "density", &density);
> + ? ? ? of_property_read_u32(np_ddr, "io-width", &io_width);
> +
> + ? ? ? /* Convert from density in Mb to the density encoding in jedc_ddr.h */
> + ? ? ? if (density & (density - 1))
> + ? ? ? ? ? ? ? dev_info->density = 0;
> + ? ? ? else
> + ? ? ? ? ? ? ? dev_info->density = __fls(density) - 5;
> +
> + ? ? ? /* Convert from io_width in bits to io_width encoding in jedc_ddr.h */
> + ? ? ? if (io_width & (io_width - 1))
> + ? ? ? ? ? ? ? dev_info->io_width = 0;
> + ? ? ? else
> + ? ? ? ? ? ? ? dev_info->io_width = __fls(io_width) - 1;
> +}
> +
> +static struct emif_data * __init_or_module of_get_device_details(
> + ? ? ? ? ? ? ? struct device_node *np_emif, struct device *dev)
> +{
> + ? ? ? struct emif_data ? ? ? ? ? ? ? ?*emif = NULL;
> + ? ? ? struct ddr_device_info ? ? ? ? ?*dev_info = NULL;
> + ? ? ? struct emif_platform_data ? ? ? *pd = NULL;
> + ? ? ? struct device_node ? ? ? ? ? ? ?*np_ddr;
> + ? ? ? int ? ? ? ? ? ? ? ? ? ? ? ? ? ? len;
> +
> + ? ? ? np_ddr = of_parse_phandle(np_emif, "device-handle", 0);
> + ? ? ? if (!np_ddr)
> + ? ? ? ? ? ? ? goto error;
> + ? ? ? emif ? ?= devm_kzalloc(dev, sizeof(struct emif_data), GFP_KERNEL);
> + ? ? ? pd ? ? ?= 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: of_get_device_details() failure!!\n",
> + ? ? ? ? ? ? ? ? ? ? ? __func__);
> + ? ? ? ? ? ? ? goto error;
> + ? ? ? }
> +
> + ? ? ? emif->plat_data ? ? ? ? = pd;
> + ? ? ? pd->device_info ? ? ? ? = dev_info;
> + ? ? ? emif->dev ? ? ? ? ? ? ? = dev;
> + ? ? ? emif->np_ddr ? ? ? ? ? ?= np_ddr;
> + ? ? ? emif->temperature_level = SDRAM_TEMP_NOMINAL;
> +
> + ? ? ? if (of_device_is_compatible(np_emif, "ti,emif-4d"))
> + ? ? ? ? ? ? ? emif->plat_data->ip_rev = EMIF_4D;
> + ? ? ? else if (of_device_is_compatible(np_emif, "ti,emif-4d5"))
> + ? ? ? ? ? ? ? emif->plat_data->ip_rev = EMIF_4D5;
> +
> + ? ? ? of_property_read_u32(np_emif, "phy-type", &pd->phy_type);
> +
> + ? ? ? if (of_find_property(np_emif, "hw-caps-ll-interface", &len))
> + ? ? ? ? ? ? ? pd->hw_caps |= EMIF_HW_CAPS_LL_INTERFACE;
> +
> + ? ? ? of_get_ddr_info(np_emif, np_ddr, dev_info);
> + ? ? ? if (!is_dev_data_valid(pd->device_info->type, pd->device_info->density,
> + ? ? ? ? ? ? ? ? ? ? ? pd->device_info->io_width, pd->phy_type, pd->ip_rev,
> + ? ? ? ? ? ? ? ? ? ? ? emif->dev)) {
> + ? ? ? ? ? ? ? dev_err(dev, "%s: invalid device data!!\n", __func__);
> + ? ? ? ? ? ? ? goto error;
> + ? ? ? }
> + ? ? ? /*
> + ? ? ? ?* 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. This will save some memory and
> + ? ? ? ?* computation.
> + ? ? ? ?*/
> + ? ? ? if (emif1 && emif1->np_ddr == np_ddr) {
> + ? ? ? ? ? ? ? emif->duplicate = true;
> + ? ? ? ? ? ? ? goto out;
> + ? ? ? } else if (emif1) {
> + ? ? ? ? ? ? ? dev_warn(emif->dev, "%s: Non-symmetric DDR geometry\n",
> + ? ? ? ? ? ? ? ? ? ? ? __func__);
> + ? ? ? }
> +
> +
> + ? ? ? of_get_custom_configs(np_emif, emif);
> + ? ? ? of_get_ddr_timings(np_ddr, emif);
> + ? ? ? of_get_min_tck(np_ddr, emif);
> + ? ? ? goto out;
> +
> +error:
> + ? ? ? return NULL;
> +out:
> + ? ? ? return emif;
> +}
> +
> +#else
> +
> +static struct emif_data * __init_or_module of_get_device_details(
> + ? ? ? ? ? ? ? struct device_node *np_emif, struct device *dev)
> +{
> + ? ? ? return NULL;
> +}
> +#endif
> +
> ?static struct emif_data *__init_or_module get_device_details(
> ? ? ? ? ? ? ? ?struct platform_device *pdev)
> ?{
> @@ -1267,7 +1542,11 @@ static int __init_or_module emif_probe(struct platform_device *pdev)
> ? ? ? ?struct resource ? ? ? ? *res;
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? irq;
>
> - ? ? ? emif = get_device_details(pdev);
> + ? ? ? if (pdev->dev.of_node)
> + ? ? ? ? ? ? ? emif = of_get_device_details(pdev->dev.of_node, &pdev->dev);
> + ? ? ? else
> + ? ? ? ? ? ? ? emif = get_device_details(pdev);
> +
> ? ? ? ?if (!emif) {
> ? ? ? ? ? ? ? ?pr_err("%s: error getting device data\n", __func__);
> ? ? ? ? ? ? ? ?goto error;
> @@ -1644,11 +1923,21 @@ static void __attribute__((unused)) freq_post_notify_handling(void)
> ? ? ? ?spin_unlock_irqrestore(&emif_lock, irq_state);
> ?}
>
> +#if defined(CONFIG_OF)
> +static const struct of_device_id emif_of_match[] = {
> + ? ? ? ? ? ? ? { .compatible = "ti,emif-4d" },
> + ? ? ? ? ? ? ? { .compatible = "ti,emif-4d5" },
> + ? ? ? ? ? ? ? {},
> +};
> +MODULE_DEVICE_TABLE(of, emif_of_match);
> +#endif
> +
> ?static struct platform_driver emif_driver = {
> ? ? ? ?.remove ? ? ? ? = __exit_p(emif_remove),
> ? ? ? ?.shutdown ? ? ? = emif_shutdown,
> ? ? ? ?.driver = {
> ? ? ? ? ? ? ? ?.name = "emif",
> + ? ? ? ? ? ? ? .of_match_table = of_match_ptr(emif_of_match),
> ? ? ? ?},
> ?};
>
> --
> 1.7.9.5
>

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

* [PATCH v4 4/4] memory: emif: add device tree support to emif driver
  2012-06-30  4:08   ` Shilimkar, Santosh
@ 2012-06-30  4:23     ` Greg KH
  2012-06-30  4:42       ` Shilimkar, Santosh
  0 siblings, 1 reply; 17+ messages in thread
From: Greg KH @ 2012-06-30  4:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Jun 30, 2012 at 09:38:41AM +0530, Shilimkar, Santosh wrote:
> (+ Greg, By mistake the your name got dropped cc from list)
> 
> On Fri, Jun 29, 2012 at 7:13 PM, Santosh Shilimkar
> <santosh.shilimkar@ti.com> wrote:
> > From: Aneesh V <aneesh@ti.com>
> >
> > Device tree support for the EMIF driver.
> >
> > Reviewed-by: Benoit Cousson <b-cousson@ti.com>
> > Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
> > Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
> > Signed-off-by: Aneesh V <aneesh@ti.com>
> > [santosh.shilimkar at ti.com: Rebased against 3.5-rc]
> > Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> > ---
> > ?drivers/memory/emif.c | ?291 ++++++++++++++++++++++++++++++++++++++++++++++++-
> > ?1 file changed, 290 insertions(+), 1 deletion(-)

Wouldn't this just be better off as a separate file that only gets build
if CONFIG_OF is set, as I'm sure that other systems are going to want
access to these "read the device tree values" functions, right?

thanks,

greg k-h

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

* [PATCH v4 4/4] memory: emif: add device tree support to emif driver
  2012-06-30  4:23     ` Greg KH
@ 2012-06-30  4:42       ` Shilimkar, Santosh
  2012-07-02 13:18         ` Shilimkar, Santosh
  0 siblings, 1 reply; 17+ messages in thread
From: Shilimkar, Santosh @ 2012-06-30  4:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Jun 30, 2012 at 9:53 AM, Greg KH <gregkh@linuxfoundation.org> wrote:
> On Sat, Jun 30, 2012 at 09:38:41AM +0530, Shilimkar, Santosh wrote:
>> (+ Greg, By mistake the your name got dropped cc from list)
>>
>> On Fri, Jun 29, 2012 at 7:13 PM, Santosh Shilimkar
>> <santosh.shilimkar@ti.com> wrote:
>> > From: Aneesh V <aneesh@ti.com>
>> >
>> > Device tree support for the EMIF driver.
>> >
>> > Reviewed-by: Benoit Cousson <b-cousson@ti.com>
>> > Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
>> > Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
>> > Signed-off-by: Aneesh V <aneesh@ti.com>
>> > [santosh.shilimkar at ti.com: Rebased against 3.5-rc]
>> > Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
>> > ---
>> > ?drivers/memory/emif.c | ?291 ++++++++++++++++++++++++++++++++++++++++++++++++-
>> > ?1 file changed, 290 insertions(+), 1 deletion(-)
>
> Wouldn't this just be better off as a separate file that only gets build
> if CONFIG_OF is set, as I'm sure that other systems are going to want
> access to these "read the device tree values" functions, right?
>
Probably yes. At least separate the LPDDR2 memory
generic parameter DT read code. There are parameters like phy
type which is specific to OMAP controllers so that still need to kept
inside EMIF driver. So there in driver, few lines of code will be there
under CONFIG_OF.

I can extract those functions which can be commonly used and put them
in another file under drivers/memory/

Is that fine with you ?

Regards
Santosh

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

* [PATCH v4 4/4] memory: emif: add device tree support to emif driver
  2012-06-30  4:42       ` Shilimkar, Santosh
@ 2012-07-02 13:18         ` Shilimkar, Santosh
  2012-07-09 13:32           ` Shilimkar, Santosh
  0 siblings, 1 reply; 17+ messages in thread
From: Shilimkar, Santosh @ 2012-07-02 13:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Jun 30, 2012 at 10:12 AM, Shilimkar, Santosh
<santosh.shilimkar@ti.com> wrote:
> On Sat, Jun 30, 2012 at 9:53 AM, Greg KH <gregkh@linuxfoundation.org> wrote:
>> On Sat, Jun 30, 2012 at 09:38:41AM +0530, Shilimkar, Santosh wrote:
>>> (+ Greg, By mistake the your name got dropped cc from list)
>>>
>>> On Fri, Jun 29, 2012 at 7:13 PM, Santosh Shilimkar
>>> <santosh.shilimkar@ti.com> wrote:
>>> > From: Aneesh V <aneesh@ti.com>
>>> >
>>> > Device tree support for the EMIF driver.
>>> >
>>> > Reviewed-by: Benoit Cousson <b-cousson@ti.com>
>>> > Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
>>> > Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
>>> > Signed-off-by: Aneesh V <aneesh@ti.com>
>>> > [santosh.shilimkar at ti.com: Rebased against 3.5-rc]
>>> > Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>> > ---
>>> >  drivers/memory/emif.c |  291 ++++++++++++++++++++++++++++++++++++++++++++++++-
>>> >  1 file changed, 290 insertions(+), 1 deletion(-)
>>
>> Wouldn't this just be better off as a separate file that only gets build
>> if CONFIG_OF is set, as I'm sure that other systems are going to want
>> access to these "read the device tree values" functions, right?
>>
> Probably yes. At least separate the LPDDR2 memory
> generic parameter DT read code. There are parameters like phy
> type which is specific to OMAP controllers so that still need to kept
> inside EMIF driver. So there in driver, few lines of code will be there
> under CONFIG_OF.
>
> I can extract those functions which can be commonly used and put them
> in another file under drivers/memory/
>
> Is that fine with you ?
>
To elaborate more, I have created below patch.
Let me know what do you think ?

------>>
>From 42abb2b29136efb9983abdd203fe1e6bce784715 Mon Sep 17 00:00:00 2001
From: Aneesh V <aneesh@ti.com>
Date: Mon, 30 Jan 2012 20:06:30 +0530
Subject: [PATCH] memory: emif: add device tree support to emif driver

Device tree support for the EMIF driver. LPDDR2 generic timings
extraction from device is managed using couple of helper
functions which can be used by other memory controller
drivers.

Reviewed-by: Benoit Cousson <b-cousson@ti.com>
Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
[santosh.shilimkar at ti.com: Rebased against 3.5-rc]
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
>From last version, the only change is to the lpddr2 dt timings generic
functions moved to separate file(of_memory.c)  and build it only for
CONFIG_OF.

 drivers/memory/Makefile    |    1 +
 drivers/memory/emif.c      |  182 +++++++++++++++++++++++++++++++++++++++++++-
 drivers/memory/of_memory.c |  153 +++++++++++++++++++++++++++++++++++++
 drivers/memory/of_memory.h |   36 +++++++++
 4 files changed, 371 insertions(+), 1 deletions(-)
 create mode 100644 drivers/memory/of_memory.c
 create mode 100644 drivers/memory/of_memory.h

diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 42b3ce9..cd8486b 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -2,6 +2,7 @@
 # Makefile for memory devices
 #

+obj-$(CONFIG_OF)		+= of_memory.o
 obj-$(CONFIG_TI_EMIF)		+= emif.o
 obj-$(CONFIG_TEGRA20_MC)	+= tegra20-mc.o
 obj-$(CONFIG_TEGRA30_MC)	+= tegra30-mc.o
diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
index 33a4396..06b4eb7 100644
--- a/drivers/memory/emif.c
+++ b/drivers/memory/emif.c
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/module.h>
@@ -25,6 +26,7 @@
 #include <linux/spinlock.h>
 #include <memory/jedec_ddr.h>
 #include "emif.h"
+#include "of_memory.h"

 /**
  * struct emif_data - Per device static data for driver's use
@@ -49,6 +51,7 @@
  *				frequency in effect at the moment)
  * @plat_data:			Pointer to saved platform data.
  * @debugfs_root:		dentry to the root folder for EMIF in debugfs
+ * @np_ddr:			Pointer to ddr device tree node
  */
 struct emif_data {
 	u8				duplicate;
@@ -63,6 +66,7 @@ struct emif_data {
 	struct emif_regs		*curr_regs;
 	struct emif_platform_data	*plat_data;
 	struct dentry			*debugfs_root;
+	struct device_node		*np_ddr;
 };

 static struct emif_data *emif1;
@@ -1148,6 +1152,168 @@ static int is_custom_config_valid(struct
emif_custom_configs *cust_cfgs,
 	return valid;
 }

+#if defined(CONFIG_OF)
+static void __init_or_module of_get_custom_configs(struct device_node *np_emif,
+		struct emif_data *emif)
+{
+	struct emif_custom_configs	*cust_cfgs = NULL;
+	int				len;
+	const int			*lpmode, *poll_intvl;
+
+	lpmode = of_get_property(np_emif, "low-power-mode", &len);
+	poll_intvl = of_get_property(np_emif, "temp-alert-poll-interval", &len);
+
+	if (lpmode || poll_intvl)
+		cust_cfgs = devm_kzalloc(emif->dev, sizeof(*cust_cfgs),
+			GFP_KERNEL);
+
+	if (!cust_cfgs)
+		return;
+
+	if (lpmode) {
+		cust_cfgs->mask |= EMIF_CUSTOM_CONFIG_LPMODE;
+		cust_cfgs->lpmode = *lpmode;
+		of_property_read_u32(np_emif,
+				"low-power-mode-timeout-performance",
+				&cust_cfgs->lpmode_timeout_performance);
+		of_property_read_u32(np_emif,
+				"low-power-mode-timeout-power",
+				&cust_cfgs->lpmode_timeout_power);
+		of_property_read_u32(np_emif,
+				"low-power-mode-freq-threshold",
+				&cust_cfgs->lpmode_freq_threshold);
+	}
+
+	if (poll_intvl) {
+		cust_cfgs->mask |=
+				EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL;
+		cust_cfgs->temp_alert_poll_interval_ms = *poll_intvl;
+	}
+
+	if (!is_custom_config_valid(cust_cfgs, emif->dev)) {
+		devm_kfree(emif->dev, cust_cfgs);
+		return;
+	}
+
+	emif->plat_data->custom_configs = cust_cfgs;
+}
+
+static void __init_or_module of_get_ddr_info(struct device_node *np_emif,
+		struct device_node *np_ddr,
+		struct ddr_device_info *dev_info)
+{
+	u32 density = 0, io_width = 0;
+	int len;
+
+	if (of_find_property(np_emif, "cs1-used", &len))
+		dev_info->cs1_used = true;
+
+	if (of_find_property(np_emif, "cal-resistor-per-cs", &len))
+		dev_info->cal_resistors_per_cs = true;
+
+	if (of_device_is_compatible(np_ddr , "jedec,lpddr2-s4"))
+		dev_info->type = DDR_TYPE_LPDDR2_S4;
+	else if (of_device_is_compatible(np_ddr , "jedec,lpddr2-s2"))
+		dev_info->type = DDR_TYPE_LPDDR2_S2;
+
+	of_property_read_u32(np_ddr, "density", &density);
+	of_property_read_u32(np_ddr, "io-width", &io_width);
+
+	/* Convert from density in Mb to the density encoding in jedc_ddr.h */
+	if (density & (density - 1))
+		dev_info->density = 0;
+	else
+		dev_info->density = __fls(density) - 5;
+
+	/* Convert from io_width in bits to io_width encoding in jedc_ddr.h */
+	if (io_width & (io_width - 1))
+		dev_info->io_width = 0;
+	else
+		dev_info->io_width = __fls(io_width) - 1;
+}
+
+static struct emif_data * __init_or_module of_get_device_details(
+		struct device_node *np_emif, struct device *dev)
+{
+	struct emif_data		*emif = NULL;
+	struct ddr_device_info		*dev_info = NULL;
+	struct emif_platform_data	*pd = NULL;
+	struct device_node		*np_ddr;
+	int				len;
+
+	np_ddr = of_parse_phandle(np_emif, "device-handle", 0);
+	if (!np_ddr)
+		goto error;
+	emif	= devm_kzalloc(dev, sizeof(struct emif_data), GFP_KERNEL);
+	pd	= 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: of_get_device_details() failure!!\n",
+			__func__);
+		goto error;
+	}
+
+	emif->plat_data		= pd;
+	pd->device_info		= dev_info;
+	emif->dev		= dev;
+	emif->np_ddr		= np_ddr;
+	emif->temperature_level	= SDRAM_TEMP_NOMINAL;
+
+	if (of_device_is_compatible(np_emif, "ti,emif-4d"))
+		emif->plat_data->ip_rev = EMIF_4D;
+	else if (of_device_is_compatible(np_emif, "ti,emif-4d5"))
+		emif->plat_data->ip_rev = EMIF_4D5;
+
+	of_property_read_u32(np_emif, "phy-type", &pd->phy_type);
+
+	if (of_find_property(np_emif, "hw-caps-ll-interface", &len))
+		pd->hw_caps |= EMIF_HW_CAPS_LL_INTERFACE;
+
+	of_get_ddr_info(np_emif, np_ddr, dev_info);
+	if (!is_dev_data_valid(pd->device_info->type, pd->device_info->density,
+			pd->device_info->io_width, pd->phy_type, pd->ip_rev,
+			emif->dev)) {
+		dev_err(dev, "%s: invalid device data!!\n", __func__);
+		goto error;
+	}
+	/*
+	 * 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. This will save some memory and
+	 * computation.
+	 */
+	if (emif1 && emif1->np_ddr == np_ddr) {
+		emif->duplicate = true;
+		goto out;
+	} else if (emif1) {
+		dev_warn(emif->dev, "%s: Non-symmetric DDR geometry\n",
+			__func__);
+	}
+
+	of_get_custom_configs(np_emif, emif);
+	emif->plat_data->timings = of_get_ddr_timings(np_ddr, emif->dev,
+					emif->plat_data->device_info->type,
+					&emif->plat_data->timings_arr_size);
+
+	emif->plat_data->min_tck = of_get_min_tck(np_ddr, emif->dev);
+	goto out;
+
+error:
+	return NULL;
+out:
+	return emif;
+}
+
+#else
+
+static struct emif_data * __init_or_module of_get_device_details(
+		struct device_node *np_emif, struct device *dev)
+{
+	return NULL;
+}
+#endif
+
 static struct emif_data *__init_or_module get_device_details(
 		struct platform_device *pdev)
 {
@@ -1267,7 +1433,11 @@ static int __init_or_module emif_probe(struct
platform_device *pdev)
 	struct resource		*res;
 	int			irq;

-	emif = get_device_details(pdev);
+	if (pdev->dev.of_node)
+		emif = of_get_device_details(pdev->dev.of_node, &pdev->dev);
+	else
+		emif = get_device_details(pdev);
+
 	if (!emif) {
 		pr_err("%s: error getting device data\n", __func__);
 		goto error;
@@ -1644,11 +1814,21 @@ static void __attribute__((unused))
freq_post_notify_handling(void)
 	spin_unlock_irqrestore(&emif_lock, irq_state);
 }

+#if defined(CONFIG_OF)
+static const struct of_device_id emif_of_match[] = {
+		{ .compatible = "ti,emif-4d" },
+		{ .compatible = "ti,emif-4d5" },
+		{},
+};
+MODULE_DEVICE_TABLE(of, emif_of_match);
+#endif
+
 static struct platform_driver emif_driver = {
 	.remove		= __exit_p(emif_remove),
 	.shutdown	= emif_shutdown,
 	.driver = {
 		.name = "emif",
+		.of_match_table = of_match_ptr(emif_of_match),
 	},
 };

diff --git a/drivers/memory/of_memory.c b/drivers/memory/of_memory.c
new file mode 100644
index 0000000..c16aacc
--- /dev/null
+++ b/drivers/memory/of_memory.c
@@ -0,0 +1,153 @@
+/*
+ * OpenFirmware helpers for memory drivers
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/of.h>
+#include <linux/gfp.h>
+#include <memory/jedec_ddr.h>
+#include <linux/export.h>
+
+/**
+ * of_get_min_tck() - extract min timing values for ddr
+ * @np: pointer to ddr device tree node
+ * @device: device requesting for min timing values
+ *
+ * Populates the lpddr2_min_tck structure by extracting data
+ * from device tree node. Returns a pointer to the populated
+ * structure. If any error in populating the structure, returns
+ * default min timings provided by JEDEC.
+ */
+const struct lpddr2_min_tck *of_get_min_tck(struct device_node *np,
+		struct device *dev)
+{
+	int			ret = 0;
+	struct lpddr2_min_tck	*min;
+
+	min = devm_kzalloc(dev, sizeof(*min), GFP_KERNEL);
+	if (!min)
+		goto default_min_tck;
+
+	ret |= of_property_read_u32(np, "tRPab-min-tck", &min->tRPab);
+	ret |= of_property_read_u32(np, "tRCD-min-tck", &min->tRCD);
+	ret |= of_property_read_u32(np, "tWR-min-tck", &min->tWR);
+	ret |= of_property_read_u32(np, "tRASmin-min-tck", &min->tRASmin);
+	ret |= of_property_read_u32(np, "tRRD-min-tck", &min->tRRD);
+	ret |= of_property_read_u32(np, "tWTR-min-tck", &min->tWTR);
+	ret |= of_property_read_u32(np, "tXP-min-tck", &min->tXP);
+	ret |= of_property_read_u32(np, "tRTP-min-tck", &min->tRTP);
+	ret |= of_property_read_u32(np, "tCKE-min-tck", &min->tCKE);
+	ret |= of_property_read_u32(np, "tCKESR-min-tck", &min->tCKESR);
+	ret |= of_property_read_u32(np, "tFAW-min-tck", &min->tFAW);
+
+	if (ret) {
+		devm_kfree(dev, min);
+		goto default_min_tck;
+	}
+
+	return min;
+
+default_min_tck:
+	dev_warn(dev, "%s: using default min-tck values\n", __func__);
+	return &lpddr2_jedec_min_tck;
+}
+EXPORT_SYMBOL(of_get_min_tck);
+
+static int of_do_get_timings(struct device_node *np,
+		struct lpddr2_timings *tim)
+{
+	int ret;
+
+	ret = of_property_read_u32(np, "max-freq", &tim->max_freq);
+	ret |= of_property_read_u32(np, "min-freq", &tim->min_freq);
+	ret |= of_property_read_u32(np, "tRPab", &tim->tRPab);
+	ret |= of_property_read_u32(np, "tRCD", &tim->tRCD);
+	ret |= of_property_read_u32(np, "tWR", &tim->tWR);
+	ret |= of_property_read_u32(np, "tRAS-min", &tim->tRAS_min);
+	ret |= of_property_read_u32(np, "tRRD", &tim->tRRD);
+	ret |= of_property_read_u32(np, "tWTR", &tim->tWTR);
+	ret |= of_property_read_u32(np, "tXP", &tim->tXP);
+	ret |= of_property_read_u32(np, "tRTP", &tim->tRTP);
+	ret |= of_property_read_u32(np, "tCKESR", &tim->tCKESR);
+	ret |= of_property_read_u32(np, "tDQSCK-max", &tim->tDQSCK_max);
+	ret |= of_property_read_u32(np, "tFAW", &tim->tFAW);
+	ret |= of_property_read_u32(np, "tZQCS", &tim->tZQCS);
+	ret |= of_property_read_u32(np, "tZQCL", &tim->tZQCL);
+	ret |= of_property_read_u32(np, "tZQinit", &tim->tZQinit);
+	ret |= of_property_read_u32(np, "tRAS-max-ns", &tim->tRAS_max_ns);
+	ret |= of_property_read_u32(np, "tDQSCK-max-derated",
+		&tim->tDQSCK_max_derated);
+
+	return ret;
+}
+
+/**
+ * of_get_ddr_timings() - extracts the ddr timings and updates no of
+ * frequencies available.
+ * @np_ddr: Pointer to ddr device tree node
+ * @dev: Device requesting for ddr timings
+ * @device_type: Type of ddr(LPDDR2 S2/S4)
+ * @nr_frequencies: No of frequencies available for ddr
+ * (updated by this function)
+ *
+ * Populates lpddr2_timings structure by extracting data from device
+ * tree node. Returns pointer to populated structure. If any error
+ * while populating, returns default timings provided by JEDEC.
+ */
+const struct lpddr2_timings *of_get_ddr_timings(struct device_node *np_ddr,
+		struct device *dev, u32 device_type, u32 *nr_frequencies)
+{
+	struct lpddr2_timings	*timings = NULL;
+	u32			arr_sz = 0, i = 0;
+	struct device_node	*np_tim;
+	char			*tim_compat;
+
+	switch (device_type) {
+	case DDR_TYPE_LPDDR2_S2:
+	case DDR_TYPE_LPDDR2_S4:
+		tim_compat = "jedec,lpddr2-timings";
+		break;
+	default:
+		dev_warn(dev, "%s: un-supported memory type\n", __func__);
+	}
+
+	for_each_child_of_node(np_ddr, np_tim)
+		if (of_device_is_compatible(np_tim, tim_compat))
+			arr_sz++;
+
+	if (arr_sz)
+		timings = devm_kzalloc(dev, sizeof(*timings) * arr_sz,
+			GFP_KERNEL);
+
+	if (!timings)
+		goto default_timings;
+
+	for_each_child_of_node(np_ddr, np_tim) {
+		if (of_device_is_compatible(np_tim, tim_compat)) {
+			if (of_do_get_timings(np_tim, &timings[i])) {
+				devm_kfree(dev, timings);
+				goto default_timings;
+			}
+			i++;
+		}
+	}
+
+	*nr_frequencies = arr_sz;
+
+	return timings;
+
+default_timings:
+	dev_warn(dev, "%s: using default timings\n", __func__);
+	*nr_frequencies = ARRAY_SIZE(lpddr2_jedec_timings);
+	return lpddr2_jedec_timings;
+}
+EXPORT_SYMBOL(of_get_ddr_timings);
diff --git a/drivers/memory/of_memory.h b/drivers/memory/of_memory.h
new file mode 100644
index 0000000..20b496e
--- /dev/null
+++ b/drivers/memory/of_memory.h
@@ -0,0 +1,36 @@
+/*
+ * OpenFirmware helpers for memory drivers
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __LINUX_MEMORY_OF_REG_H
+#define __LINUX_MEMORY_OF_REG_H
+
+#ifdef CONFIG_OF
+extern const struct lpddr2_min_tck *of_get_min_tck(struct device_node *np,
+		struct device *dev);
+extern const struct lpddr2_timings
+	*of_get_ddr_timings(struct device_node *np_ddr, struct device *dev,
+	u32 device_type, u32 *nr_frequencies);
+#else
+static inline const struct lpddr2_min_tck
+	*of_get_min_tck(struct device_node *np, struct device *dev)
+{
+	return NULL;
+}
+
+static inline const struct lpddr2_timings
+	*of_get_ddr_timings(struct device_node *np_ddr, struct device *dev,
+	u32 device_type, u32 *nr_frequencies)
+{
+	return NULL;
+}
+#endif /* CONFIG_OF */
+
+#endif /* __LINUX_MEMORY_OF_REG_ */
-- 
1.7.5.4

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

* [PATCH v4 4/4] memory: emif: add device tree support to emif driver
  2012-07-02 13:18         ` Shilimkar, Santosh
@ 2012-07-09 13:32           ` Shilimkar, Santosh
  2012-07-17 16:36             ` Greg KH
  0 siblings, 1 reply; 17+ messages in thread
From: Shilimkar, Santosh @ 2012-07-09 13:32 UTC (permalink / raw)
  To: linux-arm-kernel

Greg,

On Mon, Jul 2, 2012 at 6:48 PM, Shilimkar, Santosh
<santosh.shilimkar@ti.com> wrote:
> On Sat, Jun 30, 2012 at 10:12 AM, Shilimkar, Santosh
> <santosh.shilimkar@ti.com> wrote:
>> On Sat, Jun 30, 2012 at 9:53 AM, Greg KH <gregkh@linuxfoundation.org> wrote:
>>> On Sat, Jun 30, 2012 at 09:38:41AM +0530, Shilimkar, Santosh wrote:
>>>> (+ Greg, By mistake the your name got dropped cc from list)
>>>>
>>>> On Fri, Jun 29, 2012 at 7:13 PM, Santosh Shilimkar
>>>> <santosh.shilimkar@ti.com> wrote:
>>>> > From: Aneesh V <aneesh@ti.com>
>>>> >
>>>> > Device tree support for the EMIF driver.
>>>> >
>>>> > Reviewed-by: Benoit Cousson <b-cousson@ti.com>
>>>> > Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
>>>> > Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
>>>> > Signed-off-by: Aneesh V <aneesh@ti.com>
>>>> > [santosh.shilimkar at ti.com: Rebased against 3.5-rc]
>>>> > Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>> > ---
>>>> >  drivers/memory/emif.c |  291 ++++++++++++++++++++++++++++++++++++++++++++++++-
>>>> >  1 file changed, 290 insertions(+), 1 deletion(-)
>>>
>>> Wouldn't this just be better off as a separate file that only gets build
>>> if CONFIG_OF is set, as I'm sure that other systems are going to want
>>> access to these "read the device tree values" functions, right?
>>>
>> Probably yes. At least separate the LPDDR2 memory
>> generic parameter DT read code. There are parameters like phy
>> type which is specific to OMAP controllers so that still need to kept
>> inside EMIF driver. So there in driver, few lines of code will be there
>> under CONFIG_OF.
>>
>> I can extract those functions which can be commonly used and put them
>> in another file under drivers/memory/
>>
>> Is that fine with you ?
>>
> To elaborate more, I have created below patch.
> Let me know what do you think ?
>
Any comments ??

> ------>>
> From 42abb2b29136efb9983abdd203fe1e6bce784715 Mon Sep 17 00:00:00 2001
> From: Aneesh V <aneesh@ti.com>
> Date: Mon, 30 Jan 2012 20:06:30 +0530
> Subject: [PATCH] memory: emif: add device tree support to emif driver
>
> Device tree support for the EMIF driver. LPDDR2 generic timings
> extraction from device is managed using couple of helper
> functions which can be used by other memory controller
> drivers.
>
> Reviewed-by: Benoit Cousson <b-cousson@ti.com>
> Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
> Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
> Signed-off-by: Aneesh V <aneesh@ti.com>
> [santosh.shilimkar at ti.com: Rebased against 3.5-rc]
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> ---
> From last version, the only change is to the lpddr2 dt timings generic
> functions moved to separate file(of_memory.c)  and build it only for
> CONFIG_OF.
>
>  drivers/memory/Makefile    |    1 +
>  drivers/memory/emif.c      |  182 +++++++++++++++++++++++++++++++++++++++++++-
>  drivers/memory/of_memory.c |  153 +++++++++++++++++++++++++++++++++++++
>  drivers/memory/of_memory.h |   36 +++++++++
>  4 files changed, 371 insertions(+), 1 deletions(-)
>  create mode 100644 drivers/memory/of_memory.c
>  create mode 100644 drivers/memory/of_memory.h
>
> diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
> index 42b3ce9..cd8486b 100644
> --- a/drivers/memory/Makefile
> +++ b/drivers/memory/Makefile
> @@ -2,6 +2,7 @@
>  # Makefile for memory devices
>  #
>
> +obj-$(CONFIG_OF)               += of_memory.o
>  obj-$(CONFIG_TI_EMIF)          += emif.o
>  obj-$(CONFIG_TEGRA20_MC)       += tegra20-mc.o
>  obj-$(CONFIG_TEGRA30_MC)       += tegra30-mc.o
> diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
> index 33a4396..06b4eb7 100644
> --- a/drivers/memory/emif.c
> +++ b/drivers/memory/emif.c
> @@ -18,6 +18,7 @@
>  #include <linux/platform_device.h>
>  #include <linux/interrupt.h>
>  #include <linux/slab.h>
> +#include <linux/of.h>
>  #include <linux/debugfs.h>
>  #include <linux/seq_file.h>
>  #include <linux/module.h>
> @@ -25,6 +26,7 @@
>  #include <linux/spinlock.h>
>  #include <memory/jedec_ddr.h>
>  #include "emif.h"
> +#include "of_memory.h"
>
>  /**
>   * struct emif_data - Per device static data for driver's use
> @@ -49,6 +51,7 @@
>   *                             frequency in effect at the moment)
>   * @plat_data:                 Pointer to saved platform data.
>   * @debugfs_root:              dentry to the root folder for EMIF in debugfs
> + * @np_ddr:                    Pointer to ddr device tree node
>   */
>  struct emif_data {
>         u8                              duplicate;
> @@ -63,6 +66,7 @@ struct emif_data {
>         struct emif_regs                *curr_regs;
>         struct emif_platform_data       *plat_data;
>         struct dentry                   *debugfs_root;
> +       struct device_node              *np_ddr;
>  };
>
>  static struct emif_data *emif1;
> @@ -1148,6 +1152,168 @@ static int is_custom_config_valid(struct
> emif_custom_configs *cust_cfgs,
>         return valid;
>  }
>
> +#if defined(CONFIG_OF)
> +static void __init_or_module of_get_custom_configs(struct device_node *np_emif,
> +               struct emif_data *emif)
> +{
> +       struct emif_custom_configs      *cust_cfgs = NULL;
> +       int                             len;
> +       const int                       *lpmode, *poll_intvl;
> +
> +       lpmode = of_get_property(np_emif, "low-power-mode", &len);
> +       poll_intvl = of_get_property(np_emif, "temp-alert-poll-interval", &len);
> +
> +       if (lpmode || poll_intvl)
> +               cust_cfgs = devm_kzalloc(emif->dev, sizeof(*cust_cfgs),
> +                       GFP_KERNEL);
> +
> +       if (!cust_cfgs)
> +               return;
> +
> +       if (lpmode) {
> +               cust_cfgs->mask |= EMIF_CUSTOM_CONFIG_LPMODE;
> +               cust_cfgs->lpmode = *lpmode;
> +               of_property_read_u32(np_emif,
> +                               "low-power-mode-timeout-performance",
> +                               &cust_cfgs->lpmode_timeout_performance);
> +               of_property_read_u32(np_emif,
> +                               "low-power-mode-timeout-power",
> +                               &cust_cfgs->lpmode_timeout_power);
> +               of_property_read_u32(np_emif,
> +                               "low-power-mode-freq-threshold",
> +                               &cust_cfgs->lpmode_freq_threshold);
> +       }
> +
> +       if (poll_intvl) {
> +               cust_cfgs->mask |=
> +                               EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL;
> +               cust_cfgs->temp_alert_poll_interval_ms = *poll_intvl;
> +       }
> +
> +       if (!is_custom_config_valid(cust_cfgs, emif->dev)) {
> +               devm_kfree(emif->dev, cust_cfgs);
> +               return;
> +       }
> +
> +       emif->plat_data->custom_configs = cust_cfgs;
> +}
> +
> +static void __init_or_module of_get_ddr_info(struct device_node *np_emif,
> +               struct device_node *np_ddr,
> +               struct ddr_device_info *dev_info)
> +{
> +       u32 density = 0, io_width = 0;
> +       int len;
> +
> +       if (of_find_property(np_emif, "cs1-used", &len))
> +               dev_info->cs1_used = true;
> +
> +       if (of_find_property(np_emif, "cal-resistor-per-cs", &len))
> +               dev_info->cal_resistors_per_cs = true;
> +
> +       if (of_device_is_compatible(np_ddr , "jedec,lpddr2-s4"))
> +               dev_info->type = DDR_TYPE_LPDDR2_S4;
> +       else if (of_device_is_compatible(np_ddr , "jedec,lpddr2-s2"))
> +               dev_info->type = DDR_TYPE_LPDDR2_S2;
> +
> +       of_property_read_u32(np_ddr, "density", &density);
> +       of_property_read_u32(np_ddr, "io-width", &io_width);
> +
> +       /* Convert from density in Mb to the density encoding in jedc_ddr.h */
> +       if (density & (density - 1))
> +               dev_info->density = 0;
> +       else
> +               dev_info->density = __fls(density) - 5;
> +
> +       /* Convert from io_width in bits to io_width encoding in jedc_ddr.h */
> +       if (io_width & (io_width - 1))
> +               dev_info->io_width = 0;
> +       else
> +               dev_info->io_width = __fls(io_width) - 1;
> +}
> +
> +static struct emif_data * __init_or_module of_get_device_details(
> +               struct device_node *np_emif, struct device *dev)
> +{
> +       struct emif_data                *emif = NULL;
> +       struct ddr_device_info          *dev_info = NULL;
> +       struct emif_platform_data       *pd = NULL;
> +       struct device_node              *np_ddr;
> +       int                             len;
> +
> +       np_ddr = of_parse_phandle(np_emif, "device-handle", 0);
> +       if (!np_ddr)
> +               goto error;
> +       emif    = devm_kzalloc(dev, sizeof(struct emif_data), GFP_KERNEL);
> +       pd      = 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: of_get_device_details() failure!!\n",
> +                       __func__);
> +               goto error;
> +       }
> +
> +       emif->plat_data         = pd;
> +       pd->device_info         = dev_info;
> +       emif->dev               = dev;
> +       emif->np_ddr            = np_ddr;
> +       emif->temperature_level = SDRAM_TEMP_NOMINAL;
> +
> +       if (of_device_is_compatible(np_emif, "ti,emif-4d"))
> +               emif->plat_data->ip_rev = EMIF_4D;
> +       else if (of_device_is_compatible(np_emif, "ti,emif-4d5"))
> +               emif->plat_data->ip_rev = EMIF_4D5;
> +
> +       of_property_read_u32(np_emif, "phy-type", &pd->phy_type);
> +
> +       if (of_find_property(np_emif, "hw-caps-ll-interface", &len))
> +               pd->hw_caps |= EMIF_HW_CAPS_LL_INTERFACE;
> +
> +       of_get_ddr_info(np_emif, np_ddr, dev_info);
> +       if (!is_dev_data_valid(pd->device_info->type, pd->device_info->density,
> +                       pd->device_info->io_width, pd->phy_type, pd->ip_rev,
> +                       emif->dev)) {
> +               dev_err(dev, "%s: invalid device data!!\n", __func__);
> +               goto error;
> +       }
> +       /*
> +        * 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. This will save some memory and
> +        * computation.
> +        */
> +       if (emif1 && emif1->np_ddr == np_ddr) {
> +               emif->duplicate = true;
> +               goto out;
> +       } else if (emif1) {
> +               dev_warn(emif->dev, "%s: Non-symmetric DDR geometry\n",
> +                       __func__);
> +       }
> +
> +       of_get_custom_configs(np_emif, emif);
> +       emif->plat_data->timings = of_get_ddr_timings(np_ddr, emif->dev,
> +                                       emif->plat_data->device_info->type,
> +                                       &emif->plat_data->timings_arr_size);
> +
> +       emif->plat_data->min_tck = of_get_min_tck(np_ddr, emif->dev);
> +       goto out;
> +
> +error:
> +       return NULL;
> +out:
> +       return emif;
> +}
> +
> +#else
> +
> +static struct emif_data * __init_or_module of_get_device_details(
> +               struct device_node *np_emif, struct device *dev)
> +{
> +       return NULL;
> +}
> +#endif
> +
>  static struct emif_data *__init_or_module get_device_details(
>                 struct platform_device *pdev)
>  {
> @@ -1267,7 +1433,11 @@ static int __init_or_module emif_probe(struct
> platform_device *pdev)
>         struct resource         *res;
>         int                     irq;
>
> -       emif = get_device_details(pdev);
> +       if (pdev->dev.of_node)
> +               emif = of_get_device_details(pdev->dev.of_node, &pdev->dev);
> +       else
> +               emif = get_device_details(pdev);
> +
>         if (!emif) {
>                 pr_err("%s: error getting device data\n", __func__);
>                 goto error;
> @@ -1644,11 +1814,21 @@ static void __attribute__((unused))
> freq_post_notify_handling(void)
>         spin_unlock_irqrestore(&emif_lock, irq_state);
>  }
>
> +#if defined(CONFIG_OF)
> +static const struct of_device_id emif_of_match[] = {
> +               { .compatible = "ti,emif-4d" },
> +               { .compatible = "ti,emif-4d5" },
> +               {},
> +};
> +MODULE_DEVICE_TABLE(of, emif_of_match);
> +#endif
> +
>  static struct platform_driver emif_driver = {
>         .remove         = __exit_p(emif_remove),
>         .shutdown       = emif_shutdown,
>         .driver = {
>                 .name = "emif",
> +               .of_match_table = of_match_ptr(emif_of_match),
>         },
>  };
>
> diff --git a/drivers/memory/of_memory.c b/drivers/memory/of_memory.c
> new file mode 100644
> index 0000000..c16aacc
> --- /dev/null
> +++ b/drivers/memory/of_memory.c
> @@ -0,0 +1,153 @@
> +/*
> + * OpenFirmware helpers for memory drivers
> + *
> + * Copyright (C) 2012 Texas Instruments, Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/platform_device.h>
> +#include <linux/list.h>
> +#include <linux/of.h>
> +#include <linux/gfp.h>
> +#include <memory/jedec_ddr.h>
> +#include <linux/export.h>
> +
> +/**
> + * of_get_min_tck() - extract min timing values for ddr
> + * @np: pointer to ddr device tree node
> + * @device: device requesting for min timing values
> + *
> + * Populates the lpddr2_min_tck structure by extracting data
> + * from device tree node. Returns a pointer to the populated
> + * structure. If any error in populating the structure, returns
> + * default min timings provided by JEDEC.
> + */
> +const struct lpddr2_min_tck *of_get_min_tck(struct device_node *np,
> +               struct device *dev)
> +{
> +       int                     ret = 0;
> +       struct lpddr2_min_tck   *min;
> +
> +       min = devm_kzalloc(dev, sizeof(*min), GFP_KERNEL);
> +       if (!min)
> +               goto default_min_tck;
> +
> +       ret |= of_property_read_u32(np, "tRPab-min-tck", &min->tRPab);
> +       ret |= of_property_read_u32(np, "tRCD-min-tck", &min->tRCD);
> +       ret |= of_property_read_u32(np, "tWR-min-tck", &min->tWR);
> +       ret |= of_property_read_u32(np, "tRASmin-min-tck", &min->tRASmin);
> +       ret |= of_property_read_u32(np, "tRRD-min-tck", &min->tRRD);
> +       ret |= of_property_read_u32(np, "tWTR-min-tck", &min->tWTR);
> +       ret |= of_property_read_u32(np, "tXP-min-tck", &min->tXP);
> +       ret |= of_property_read_u32(np, "tRTP-min-tck", &min->tRTP);
> +       ret |= of_property_read_u32(np, "tCKE-min-tck", &min->tCKE);
> +       ret |= of_property_read_u32(np, "tCKESR-min-tck", &min->tCKESR);
> +       ret |= of_property_read_u32(np, "tFAW-min-tck", &min->tFAW);
> +
> +       if (ret) {
> +               devm_kfree(dev, min);
> +               goto default_min_tck;
> +       }
> +
> +       return min;
> +
> +default_min_tck:
> +       dev_warn(dev, "%s: using default min-tck values\n", __func__);
> +       return &lpddr2_jedec_min_tck;
> +}
> +EXPORT_SYMBOL(of_get_min_tck);
> +
> +static int of_do_get_timings(struct device_node *np,
> +               struct lpddr2_timings *tim)
> +{
> +       int ret;
> +
> +       ret = of_property_read_u32(np, "max-freq", &tim->max_freq);
> +       ret |= of_property_read_u32(np, "min-freq", &tim->min_freq);
> +       ret |= of_property_read_u32(np, "tRPab", &tim->tRPab);
> +       ret |= of_property_read_u32(np, "tRCD", &tim->tRCD);
> +       ret |= of_property_read_u32(np, "tWR", &tim->tWR);
> +       ret |= of_property_read_u32(np, "tRAS-min", &tim->tRAS_min);
> +       ret |= of_property_read_u32(np, "tRRD", &tim->tRRD);
> +       ret |= of_property_read_u32(np, "tWTR", &tim->tWTR);
> +       ret |= of_property_read_u32(np, "tXP", &tim->tXP);
> +       ret |= of_property_read_u32(np, "tRTP", &tim->tRTP);
> +       ret |= of_property_read_u32(np, "tCKESR", &tim->tCKESR);
> +       ret |= of_property_read_u32(np, "tDQSCK-max", &tim->tDQSCK_max);
> +       ret |= of_property_read_u32(np, "tFAW", &tim->tFAW);
> +       ret |= of_property_read_u32(np, "tZQCS", &tim->tZQCS);
> +       ret |= of_property_read_u32(np, "tZQCL", &tim->tZQCL);
> +       ret |= of_property_read_u32(np, "tZQinit", &tim->tZQinit);
> +       ret |= of_property_read_u32(np, "tRAS-max-ns", &tim->tRAS_max_ns);
> +       ret |= of_property_read_u32(np, "tDQSCK-max-derated",
> +               &tim->tDQSCK_max_derated);
> +
> +       return ret;
> +}
> +
> +/**
> + * of_get_ddr_timings() - extracts the ddr timings and updates no of
> + * frequencies available.
> + * @np_ddr: Pointer to ddr device tree node
> + * @dev: Device requesting for ddr timings
> + * @device_type: Type of ddr(LPDDR2 S2/S4)
> + * @nr_frequencies: No of frequencies available for ddr
> + * (updated by this function)
> + *
> + * Populates lpddr2_timings structure by extracting data from device
> + * tree node. Returns pointer to populated structure. If any error
> + * while populating, returns default timings provided by JEDEC.
> + */
> +const struct lpddr2_timings *of_get_ddr_timings(struct device_node *np_ddr,
> +               struct device *dev, u32 device_type, u32 *nr_frequencies)
> +{
> +       struct lpddr2_timings   *timings = NULL;
> +       u32                     arr_sz = 0, i = 0;
> +       struct device_node      *np_tim;
> +       char                    *tim_compat;
> +
> +       switch (device_type) {
> +       case DDR_TYPE_LPDDR2_S2:
> +       case DDR_TYPE_LPDDR2_S4:
> +               tim_compat = "jedec,lpddr2-timings";
> +               break;
> +       default:
> +               dev_warn(dev, "%s: un-supported memory type\n", __func__);
> +       }
> +
> +       for_each_child_of_node(np_ddr, np_tim)
> +               if (of_device_is_compatible(np_tim, tim_compat))
> +                       arr_sz++;
> +
> +       if (arr_sz)
> +               timings = devm_kzalloc(dev, sizeof(*timings) * arr_sz,
> +                       GFP_KERNEL);
> +
> +       if (!timings)
> +               goto default_timings;
> +
> +       for_each_child_of_node(np_ddr, np_tim) {
> +               if (of_device_is_compatible(np_tim, tim_compat)) {
> +                       if (of_do_get_timings(np_tim, &timings[i])) {
> +                               devm_kfree(dev, timings);
> +                               goto default_timings;
> +                       }
> +                       i++;
> +               }
> +       }
> +
> +       *nr_frequencies = arr_sz;
> +
> +       return timings;
> +
> +default_timings:
> +       dev_warn(dev, "%s: using default timings\n", __func__);
> +       *nr_frequencies = ARRAY_SIZE(lpddr2_jedec_timings);
> +       return lpddr2_jedec_timings;
> +}
> +EXPORT_SYMBOL(of_get_ddr_timings);
> diff --git a/drivers/memory/of_memory.h b/drivers/memory/of_memory.h
> new file mode 100644
> index 0000000..20b496e
> --- /dev/null
> +++ b/drivers/memory/of_memory.h
> @@ -0,0 +1,36 @@
> +/*
> + * OpenFirmware helpers for memory drivers
> + *
> + * Copyright (C) 2012 Texas Instruments, Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef __LINUX_MEMORY_OF_REG_H
> +#define __LINUX_MEMORY_OF_REG_H
> +
> +#ifdef CONFIG_OF
> +extern const struct lpddr2_min_tck *of_get_min_tck(struct device_node *np,
> +               struct device *dev);
> +extern const struct lpddr2_timings
> +       *of_get_ddr_timings(struct device_node *np_ddr, struct device *dev,
> +       u32 device_type, u32 *nr_frequencies);
> +#else
> +static inline const struct lpddr2_min_tck
> +       *of_get_min_tck(struct device_node *np, struct device *dev)
> +{
> +       return NULL;
> +}
> +
> +static inline const struct lpddr2_timings
> +       *of_get_ddr_timings(struct device_node *np_ddr, struct device *dev,
> +       u32 device_type, u32 *nr_frequencies)
> +{
> +       return NULL;
> +}
> +#endif /* CONFIG_OF */
> +
> +#endif /* __LINUX_MEMORY_OF_REG_ */
> --
> 1.7.5.4

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

* [PATCH v4 4/4] memory: emif: add device tree support to emif driver
  2012-07-09 13:32           ` Shilimkar, Santosh
@ 2012-07-17 16:36             ` Greg KH
  2012-07-17 17:07               ` Shilimkar, Santosh
  0 siblings, 1 reply; 17+ messages in thread
From: Greg KH @ 2012-07-17 16:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 09, 2012 at 07:02:36PM +0530, Shilimkar, Santosh wrote:
> Greg,
> 
> On Mon, Jul 2, 2012 at 6:48 PM, Shilimkar, Santosh
> <santosh.shilimkar@ti.com> wrote:
> > On Sat, Jun 30, 2012 at 10:12 AM, Shilimkar, Santosh
> > <santosh.shilimkar@ti.com> wrote:
> >> On Sat, Jun 30, 2012 at 9:53 AM, Greg KH <gregkh@linuxfoundation.org> wrote:
> >>> On Sat, Jun 30, 2012 at 09:38:41AM +0530, Shilimkar, Santosh wrote:
> >>>> (+ Greg, By mistake the your name got dropped cc from list)
> >>>>
> >>>> On Fri, Jun 29, 2012 at 7:13 PM, Santosh Shilimkar
> >>>> <santosh.shilimkar@ti.com> wrote:
> >>>> > From: Aneesh V <aneesh@ti.com>
> >>>> >
> >>>> > Device tree support for the EMIF driver.
> >>>> >
> >>>> > Reviewed-by: Benoit Cousson <b-cousson@ti.com>
> >>>> > Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
> >>>> > Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
> >>>> > Signed-off-by: Aneesh V <aneesh@ti.com>
> >>>> > [santosh.shilimkar at ti.com: Rebased against 3.5-rc]
> >>>> > Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> >>>> > ---
> >>>> >  drivers/memory/emif.c |  291 ++++++++++++++++++++++++++++++++++++++++++++++++-
> >>>> >  1 file changed, 290 insertions(+), 1 deletion(-)
> >>>
> >>> Wouldn't this just be better off as a separate file that only gets build
> >>> if CONFIG_OF is set, as I'm sure that other systems are going to want
> >>> access to these "read the device tree values" functions, right?
> >>>
> >> Probably yes. At least separate the LPDDR2 memory
> >> generic parameter DT read code. There are parameters like phy
> >> type which is specific to OMAP controllers so that still need to kept
> >> inside EMIF driver. So there in driver, few lines of code will be there
> >> under CONFIG_OF.
> >>
> >> I can extract those functions which can be commonly used and put them
> >> in another file under drivers/memory/
> >>
> >> Is that fine with you ?
> >>
> > To elaborate more, I have created below patch.
> > Let me know what do you think ?
> >
> Any comments ??

Becides the obvious one of sending a line-wrapped patch that can not be
applied?  :)

greg k-h

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

* [PATCH v4 4/4] memory: emif: add device tree support to emif driver
  2012-07-17 16:36             ` Greg KH
@ 2012-07-17 17:07               ` Shilimkar, Santosh
  2012-07-17 17:58                 ` Greg KH
  0 siblings, 1 reply; 17+ messages in thread
From: Shilimkar, Santosh @ 2012-07-17 17:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 17, 2012 at 10:06 PM, Greg KH <gregkh@linuxfoundation.org> wrote:
> On Mon, Jul 09, 2012 at 07:02:36PM +0530, Shilimkar, Santosh wrote:
>> Greg,
>>

[...]

>> > To elaborate more, I have created below patch.
>> > Let me know what do you think ?
>> >
>> Any comments ??
>
> Becides the obvious one of sending a line-wrapped patch that can not be
> applied?  :)
>
My bad. Sorry about that.
Sending it again and also attaching it in case mailer screws it up.

-->>
>From 74688a87fd490909e9122bf757c0096480e9fc11 Mon Sep 17 00:00:00 2001
From: Aneesh V <aneesh@ti.com>
Date: Mon, 30 Jan 2012 20:06:30 +0530
Subject: [PATCH 4/4] memory: emif: add device tree support to emif driver

Device tree support for the EMIF driver. LPDDR2 generic timings
extraction from device is managed using couple of helper
functions which can be used by other memory controller
drivers.

Reviewed-by: Benoit Cousson <b-cousson@ti.com>
Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
Signed-off-by: Aneesh V <aneesh@ti.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/memory/Makefile    |    1 +
 drivers/memory/emif.c      |  182 +++++++++++++++++++++++++++++++++++++++++++-
 drivers/memory/of_memory.c |  153 +++++++++++++++++++++++++++++++++++++
 drivers/memory/of_memory.h |   36 +++++++++
 4 files changed, 371 insertions(+), 1 deletion(-)
 create mode 100644 drivers/memory/of_memory.c
 create mode 100644 drivers/memory/of_memory.h

diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 42b3ce9..cd8486b 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -2,6 +2,7 @@
 # Makefile for memory devices
 #

+obj-$(CONFIG_OF)		+= of_memory.o
 obj-$(CONFIG_TI_EMIF)		+= emif.o
 obj-$(CONFIG_TEGRA20_MC)	+= tegra20-mc.o
 obj-$(CONFIG_TEGRA30_MC)	+= tegra30-mc.o
diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
index 33a4396..06b4eb7 100644
--- a/drivers/memory/emif.c
+++ b/drivers/memory/emif.c
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/module.h>
@@ -25,6 +26,7 @@
 #include <linux/spinlock.h>
 #include <memory/jedec_ddr.h>
 #include "emif.h"
+#include "of_memory.h"

 /**
  * struct emif_data - Per device static data for driver's use
@@ -49,6 +51,7 @@
  *				frequency in effect at the moment)
  * @plat_data:			Pointer to saved platform data.
  * @debugfs_root:		dentry to the root folder for EMIF in debugfs
+ * @np_ddr:			Pointer to ddr device tree node
  */
 struct emif_data {
 	u8				duplicate;
@@ -63,6 +66,7 @@ struct emif_data {
 	struct emif_regs		*curr_regs;
 	struct emif_platform_data	*plat_data;
 	struct dentry			*debugfs_root;
+	struct device_node		*np_ddr;
 };

 static struct emif_data *emif1;
@@ -1148,6 +1152,168 @@ static int is_custom_config_valid(struct
emif_custom_configs *cust_cfgs,
 	return valid;
 }

+#if defined(CONFIG_OF)
+static void __init_or_module of_get_custom_configs(struct device_node *np_emif,
+		struct emif_data *emif)
+{
+	struct emif_custom_configs	*cust_cfgs = NULL;
+	int				len;
+	const int			*lpmode, *poll_intvl;
+
+	lpmode = of_get_property(np_emif, "low-power-mode", &len);
+	poll_intvl = of_get_property(np_emif, "temp-alert-poll-interval", &len);
+
+	if (lpmode || poll_intvl)
+		cust_cfgs = devm_kzalloc(emif->dev, sizeof(*cust_cfgs),
+			GFP_KERNEL);
+
+	if (!cust_cfgs)
+		return;
+
+	if (lpmode) {
+		cust_cfgs->mask |= EMIF_CUSTOM_CONFIG_LPMODE;
+		cust_cfgs->lpmode = *lpmode;
+		of_property_read_u32(np_emif,
+				"low-power-mode-timeout-performance",
+				&cust_cfgs->lpmode_timeout_performance);
+		of_property_read_u32(np_emif,
+				"low-power-mode-timeout-power",
+				&cust_cfgs->lpmode_timeout_power);
+		of_property_read_u32(np_emif,
+				"low-power-mode-freq-threshold",
+				&cust_cfgs->lpmode_freq_threshold);
+	}
+
+	if (poll_intvl) {
+		cust_cfgs->mask |=
+				EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL;
+		cust_cfgs->temp_alert_poll_interval_ms = *poll_intvl;
+	}
+
+	if (!is_custom_config_valid(cust_cfgs, emif->dev)) {
+		devm_kfree(emif->dev, cust_cfgs);
+		return;
+	}
+
+	emif->plat_data->custom_configs = cust_cfgs;
+}
+
+static void __init_or_module of_get_ddr_info(struct device_node *np_emif,
+		struct device_node *np_ddr,
+		struct ddr_device_info *dev_info)
+{
+	u32 density = 0, io_width = 0;
+	int len;
+
+	if (of_find_property(np_emif, "cs1-used", &len))
+		dev_info->cs1_used = true;
+
+	if (of_find_property(np_emif, "cal-resistor-per-cs", &len))
+		dev_info->cal_resistors_per_cs = true;
+
+	if (of_device_is_compatible(np_ddr , "jedec,lpddr2-s4"))
+		dev_info->type = DDR_TYPE_LPDDR2_S4;
+	else if (of_device_is_compatible(np_ddr , "jedec,lpddr2-s2"))
+		dev_info->type = DDR_TYPE_LPDDR2_S2;
+
+	of_property_read_u32(np_ddr, "density", &density);
+	of_property_read_u32(np_ddr, "io-width", &io_width);
+
+	/* Convert from density in Mb to the density encoding in jedc_ddr.h */
+	if (density & (density - 1))
+		dev_info->density = 0;
+	else
+		dev_info->density = __fls(density) - 5;
+
+	/* Convert from io_width in bits to io_width encoding in jedc_ddr.h */
+	if (io_width & (io_width - 1))
+		dev_info->io_width = 0;
+	else
+		dev_info->io_width = __fls(io_width) - 1;
+}
+
+static struct emif_data * __init_or_module of_get_device_details(
+		struct device_node *np_emif, struct device *dev)
+{
+	struct emif_data		*emif = NULL;
+	struct ddr_device_info		*dev_info = NULL;
+	struct emif_platform_data	*pd = NULL;
+	struct device_node		*np_ddr;
+	int				len;
+
+	np_ddr = of_parse_phandle(np_emif, "device-handle", 0);
+	if (!np_ddr)
+		goto error;
+	emif	= devm_kzalloc(dev, sizeof(struct emif_data), GFP_KERNEL);
+	pd	= 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: of_get_device_details() failure!!\n",
+			__func__);
+		goto error;
+	}
+
+	emif->plat_data		= pd;
+	pd->device_info		= dev_info;
+	emif->dev		= dev;
+	emif->np_ddr		= np_ddr;
+	emif->temperature_level	= SDRAM_TEMP_NOMINAL;
+
+	if (of_device_is_compatible(np_emif, "ti,emif-4d"))
+		emif->plat_data->ip_rev = EMIF_4D;
+	else if (of_device_is_compatible(np_emif, "ti,emif-4d5"))
+		emif->plat_data->ip_rev = EMIF_4D5;
+
+	of_property_read_u32(np_emif, "phy-type", &pd->phy_type);
+
+	if (of_find_property(np_emif, "hw-caps-ll-interface", &len))
+		pd->hw_caps |= EMIF_HW_CAPS_LL_INTERFACE;
+
+	of_get_ddr_info(np_emif, np_ddr, dev_info);
+	if (!is_dev_data_valid(pd->device_info->type, pd->device_info->density,
+			pd->device_info->io_width, pd->phy_type, pd->ip_rev,
+			emif->dev)) {
+		dev_err(dev, "%s: invalid device data!!\n", __func__);
+		goto error;
+	}
+	/*
+	 * 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. This will save some memory and
+	 * computation.
+	 */
+	if (emif1 && emif1->np_ddr == np_ddr) {
+		emif->duplicate = true;
+		goto out;
+	} else if (emif1) {
+		dev_warn(emif->dev, "%s: Non-symmetric DDR geometry\n",
+			__func__);
+	}
+
+	of_get_custom_configs(np_emif, emif);
+	emif->plat_data->timings = of_get_ddr_timings(np_ddr, emif->dev,
+					emif->plat_data->device_info->type,
+					&emif->plat_data->timings_arr_size);
+
+	emif->plat_data->min_tck = of_get_min_tck(np_ddr, emif->dev);
+	goto out;
+
+error:
+	return NULL;
+out:
+	return emif;
+}
+
+#else
+
+static struct emif_data * __init_or_module of_get_device_details(
+		struct device_node *np_emif, struct device *dev)
+{
+	return NULL;
+}
+#endif
+
 static struct emif_data *__init_or_module get_device_details(
 		struct platform_device *pdev)
 {
@@ -1267,7 +1433,11 @@ static int __init_or_module emif_probe(struct
platform_device *pdev)
 	struct resource		*res;
 	int			irq;

-	emif = get_device_details(pdev);
+	if (pdev->dev.of_node)
+		emif = of_get_device_details(pdev->dev.of_node, &pdev->dev);
+	else
+		emif = get_device_details(pdev);
+
 	if (!emif) {
 		pr_err("%s: error getting device data\n", __func__);
 		goto error;
@@ -1644,11 +1814,21 @@ static void __attribute__((unused))
freq_post_notify_handling(void)
 	spin_unlock_irqrestore(&emif_lock, irq_state);
 }

+#if defined(CONFIG_OF)
+static const struct of_device_id emif_of_match[] = {
+		{ .compatible = "ti,emif-4d" },
+		{ .compatible = "ti,emif-4d5" },
+		{},
+};
+MODULE_DEVICE_TABLE(of, emif_of_match);
+#endif
+
 static struct platform_driver emif_driver = {
 	.remove		= __exit_p(emif_remove),
 	.shutdown	= emif_shutdown,
 	.driver = {
 		.name = "emif",
+		.of_match_table = of_match_ptr(emif_of_match),
 	},
 };

diff --git a/drivers/memory/of_memory.c b/drivers/memory/of_memory.c
new file mode 100644
index 0000000..6007435
--- /dev/null
+++ b/drivers/memory/of_memory.c
@@ -0,0 +1,153 @@
+/*
+ * OpenFirmware helpers for memory drivers
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/of.h>
+#include <linux/gfp.h>
+#include <memory/jedec_ddr.h>
+#include <linux/export.h>
+
+/**
+ * of_get_min_tck() - extract min timing values for ddr
+ * @np: pointer to ddr device tree node
+ * @device: device requesting for min timing values
+ *
+ * Populates the lpddr2_min_tck structure by extracting data
+ * from device tree node. Returns a pointer to the populated
+ * structure. If any error in populating the structure, returns
+ * default min timings provided by JEDEC.
+ */
+const struct lpddr2_min_tck *of_get_min_tck(struct device_node *np,
+		struct device *dev)
+{
+	int			ret = 0;
+	struct lpddr2_min_tck	*min;
+
+	min = devm_kzalloc(dev, sizeof(*min), GFP_KERNEL);
+	if (!min)
+		goto default_min_tck;
+
+	ret |= of_property_read_u32(np, "tRPab-min-tck", &min->tRPab);
+	ret |= of_property_read_u32(np, "tRCD-min-tck", &min->tRCD);
+	ret |= of_property_read_u32(np, "tWR-min-tck", &min->tWR);
+	ret |= of_property_read_u32(np, "tRASmin-min-tck", &min->tRASmin);
+	ret |= of_property_read_u32(np, "tRRD-min-tck", &min->tRRD);
+	ret |= of_property_read_u32(np, "tWTR-min-tck", &min->tWTR);
+	ret |= of_property_read_u32(np, "tXP-min-tck", &min->tXP);
+	ret |= of_property_read_u32(np, "tRTP-min-tck", &min->tRTP);
+	ret |= of_property_read_u32(np, "tCKE-min-tck", &min->tCKE);
+	ret |= of_property_read_u32(np, "tCKESR-min-tck", &min->tCKESR);
+	ret |= of_property_read_u32(np, "tFAW-min-tck", &min->tFAW);
+
+	if (ret) {
+		devm_kfree(dev, min);
+		goto default_min_tck;
+	}
+
+	return min;
+
+default_min_tck:
+	dev_warn(dev, "%s: using default min-tck values\n", __func__);
+	return &lpddr2_jedec_min_tck;
+}
+EXPORT_SYMBOL(of_get_min_tck);
+
+static int of_do_get_timings(struct device_node *np,
+		struct lpddr2_timings *tim)
+{
+	int ret;
+
+	ret = of_property_read_u32(np, "max-freq", &tim->max_freq);
+	ret |= of_property_read_u32(np, "min-freq", &tim->min_freq);
+	ret |= of_property_read_u32(np, "tRPab", &tim->tRPab);
+	ret |= of_property_read_u32(np, "tRCD", &tim->tRCD);
+	ret |= of_property_read_u32(np, "tWR", &tim->tWR);
+	ret |= of_property_read_u32(np, "tRAS-min", &tim->tRAS_min);
+	ret |= of_property_read_u32(np, "tRRD", &tim->tRRD);
+	ret |= of_property_read_u32(np, "tWTR", &tim->tWTR);
+	ret |= of_property_read_u32(np, "tXP", &tim->tXP);
+	ret |= of_property_read_u32(np, "tRTP", &tim->tRTP);
+	ret |= of_property_read_u32(np, "tCKESR", &tim->tCKESR);
+	ret |= of_property_read_u32(np, "tDQSCK-max", &tim->tDQSCK_max);
+	ret |= of_property_read_u32(np, "tFAW", &tim->tFAW);
+	ret |= of_property_read_u32(np, "tZQCS", &tim->tZQCS);
+	ret |= of_property_read_u32(np, "tZQCL", &tim->tZQCL);
+	ret |= of_property_read_u32(np, "tZQinit", &tim->tZQinit);
+	ret |= of_property_read_u32(np, "tRAS-max-ns", &tim->tRAS_max_ns);
+	ret |= of_property_read_u32(np, "tDQSCK-max-derated",
+		&tim->tDQSCK_max_derated);
+
+	return ret;
+}
+
+/**
+ * of_get_ddr_timings() - extracts the ddr timings and updates no of
+ * frequencies available.
+ * @np_ddr: Pointer to ddr device tree node
+ * @dev: Device requesting for ddr timings
+ * @device_type: Type of ddr(LPDDR2 S2/S4)
+ * @nr_frequencies: No of frequencies available for ddr
+ * (updated by this function)
+ *
+ * Populates lpddr2_timings structure by extracting data from device
+ * tree node. Returns pointer to populated structure. If any error
+ * while populating, returns default timings provided by JEDEC.
+ */
+const struct lpddr2_timings *of_get_ddr_timings(struct device_node *np_ddr,
+		struct device *dev, u32 device_type, u32 *nr_frequencies)
+{
+	struct lpddr2_timings	*timings = NULL;
+	u32			arr_sz = 0, i = 0;
+	struct device_node	*np_tim;
+	char			*tim_compat;
+
+	switch (device_type) {
+	case DDR_TYPE_LPDDR2_S2:
+	case DDR_TYPE_LPDDR2_S4:
+		tim_compat = "jedec,lpddr2-timings";
+		break;
+	default:
+		dev_warn(dev, "%s: un-supported memory type\n", __func__);
+	}
+
+	for_each_child_of_node(np_ddr, np_tim)
+		if (of_device_is_compatible(np_tim, tim_compat))
+			arr_sz++;
+
+	if (arr_sz)
+		timings = devm_kzalloc(dev, sizeof(*timings) * arr_sz,
+			GFP_KERNEL);
+
+	if (!timings)
+		goto default_timings;
+
+	for_each_child_of_node(np_ddr, np_tim) {
+		if (of_device_is_compatible(np_tim, tim_compat)) {
+			if (of_do_get_timings(np_tim, &timings[i])) {
+				devm_kfree(dev, timings);
+				goto default_timings;
+			}
+			i++;
+		}
+	}
+
+	*nr_frequencies = arr_sz;
+
+	return timings;
+
+default_timings:
+	dev_warn(dev, "%s: using default timings\n", __func__);
+	*nr_frequencies = ARRAY_SIZE(lpddr2_jedec_timings);
+	return lpddr2_jedec_timings;
+}
+EXPORT_SYMBOL(of_get_ddr_timings);
diff --git a/drivers/memory/of_memory.h b/drivers/memory/of_memory.h
new file mode 100644
index 0000000..20b496e
--- /dev/null
+++ b/drivers/memory/of_memory.h
@@ -0,0 +1,36 @@
+/*
+ * OpenFirmware helpers for memory drivers
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __LINUX_MEMORY_OF_REG_H
+#define __LINUX_MEMORY_OF_REG_H
+
+#ifdef CONFIG_OF
+extern const struct lpddr2_min_tck *of_get_min_tck(struct device_node *np,
+		struct device *dev);
+extern const struct lpddr2_timings
+	*of_get_ddr_timings(struct device_node *np_ddr, struct device *dev,
+	u32 device_type, u32 *nr_frequencies);
+#else
+static inline const struct lpddr2_min_tck
+	*of_get_min_tck(struct device_node *np, struct device *dev)
+{
+	return NULL;
+}
+
+static inline const struct lpddr2_timings
+	*of_get_ddr_timings(struct device_node *np_ddr, struct device *dev,
+	u32 device_type, u32 *nr_frequencies)
+{
+	return NULL;
+}
+#endif /* CONFIG_OF */
+
+#endif /* __LINUX_MEMORY_OF_REG_ */
-- 
1.7.9.5
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0004-memory-emif-add-device-tree-support-to-emif-driver.patch
Type: application/octet-stream
Size: 14866 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120717/f58bbc92/attachment-0001.obj>

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

* [PATCH v4 4/4] memory: emif: add device tree support to emif driver
  2012-07-17 17:07               ` Shilimkar, Santosh
@ 2012-07-17 17:58                 ` Greg KH
  2012-07-18  6:44                   ` Shilimkar, Santosh
  0 siblings, 1 reply; 17+ messages in thread
From: Greg KH @ 2012-07-17 17:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 17, 2012 at 10:37:45PM +0530, Shilimkar, Santosh wrote:
> On Tue, Jul 17, 2012 at 10:06 PM, Greg KH <gregkh@linuxfoundation.org> wrote:
> > On Mon, Jul 09, 2012 at 07:02:36PM +0530, Shilimkar, Santosh wrote:
> >> Greg,
> >>
> 
> [...]
> 
> >> > To elaborate more, I have created below patch.
> >> > Let me know what do you think ?
> >> >
> >> Any comments ??
> >
> > Becides the obvious one of sending a line-wrapped patch that can not be
> > applied?  :)
> >
> My bad. Sorry about that.
> Sending it again and also attaching it in case mailer screws it up.
> 
> -->>
> >From 74688a87fd490909e9122bf757c0096480e9fc11 Mon Sep 17 00:00:00 2001
> From: Aneesh V <aneesh@ti.com>
> Date: Mon, 30 Jan 2012 20:06:30 +0530
> Subject: [PATCH 4/4] memory: emif: add device tree support to emif driver
> 
> Device tree support for the EMIF driver. LPDDR2 generic timings
> extraction from device is managed using couple of helper
> functions which can be used by other memory controller
> drivers.
> 
> Reviewed-by: Benoit Cousson <b-cousson@ti.com>
> Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
> Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
> Signed-off-by: Aneesh V <aneesh@ti.com>
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> ---
>  drivers/memory/Makefile    |    1 +
>  drivers/memory/emif.c      |  182 +++++++++++++++++++++++++++++++++++++++++++-
>  drivers/memory/of_memory.c |  153 +++++++++++++++++++++++++++++++++++++
>  drivers/memory/of_memory.h |   36 +++++++++
>  4 files changed, 371 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/memory/of_memory.c
>  create mode 100644 drivers/memory/of_memory.h
> 
> diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
> index 42b3ce9..cd8486b 100644
> --- a/drivers/memory/Makefile
> +++ b/drivers/memory/Makefile
> @@ -2,6 +2,7 @@
>  # Makefile for memory devices
>  #
> 
> +obj-$(CONFIG_OF)		+= of_memory.o
>  obj-$(CONFIG_TI_EMIF)		+= emif.o
>  obj-$(CONFIG_TEGRA20_MC)	+= tegra20-mc.o
>  obj-$(CONFIG_TEGRA30_MC)	+= tegra30-mc.o
> diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
> index 33a4396..06b4eb7 100644
> --- a/drivers/memory/emif.c
> +++ b/drivers/memory/emif.c
> @@ -18,6 +18,7 @@
>  #include <linux/platform_device.h>
>  #include <linux/interrupt.h>
>  #include <linux/slab.h>
> +#include <linux/of.h>
>  #include <linux/debugfs.h>
>  #include <linux/seq_file.h>
>  #include <linux/module.h>
> @@ -25,6 +26,7 @@
>  #include <linux/spinlock.h>
>  #include <memory/jedec_ddr.h>
>  #include "emif.h"
> +#include "of_memory.h"
> 
>  /**
>   * struct emif_data - Per device static data for driver's use
> @@ -49,6 +51,7 @@
>   *				frequency in effect at the moment)
>   * @plat_data:			Pointer to saved platform data.
>   * @debugfs_root:		dentry to the root folder for EMIF in debugfs
> + * @np_ddr:			Pointer to ddr device tree node
>   */
>  struct emif_data {
>  	u8				duplicate;
> @@ -63,6 +66,7 @@ struct emif_data {
>  	struct emif_regs		*curr_regs;
>  	struct emif_platform_data	*plat_data;
>  	struct dentry			*debugfs_root;
> +	struct device_node		*np_ddr;
>  };
> 
>  static struct emif_data *emif1;
> @@ -1148,6 +1152,168 @@ static int is_custom_config_valid(struct
> emif_custom_configs *cust_cfgs,
>  	return valid;
>  }
> 
> +#if defined(CONFIG_OF)
> +static void __init_or_module of_get_custom_configs(struct device_node *np_emif,
> +		struct emif_data *emif)

Why can't all of this code be in the of_memory.c file?


> +static struct emif_data * __init_or_module of_get_device_details(
> +		struct device_node *np_emif, struct device *dev)

of_get_memory_device_details()?

> +{
> +	struct emif_data		*emif = NULL;
> +	struct ddr_device_info		*dev_info = NULL;
> +	struct emif_platform_data	*pd = NULL;
> +	struct device_node		*np_ddr;
> +	int				len;
> +
> +	np_ddr = of_parse_phandle(np_emif, "device-handle", 0);
> +	if (!np_ddr)
> +		goto error;
> +	emif	= devm_kzalloc(dev, sizeof(struct emif_data), GFP_KERNEL);
> +	pd	= 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: of_get_device_details() failure!!\n",
> +			__func__);

Look at what that error message just printed out.  Redundancy is nice,
but come on, that's not ok :)

thanks,

greg k-h

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

* [PATCH v4 4/4] memory: emif: add device tree support to emif driver
  2012-07-17 17:58                 ` Greg KH
@ 2012-07-18  6:44                   ` Shilimkar, Santosh
  2012-08-13  5:27                     ` Shilimkar, Santosh
  0 siblings, 1 reply; 17+ messages in thread
From: Shilimkar, Santosh @ 2012-07-18  6:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 17, 2012 at 11:28 PM, Greg KH <gregkh@linuxfoundation.org> wrote:
> On Tue, Jul 17, 2012 at 10:37:45PM +0530, Shilimkar, Santosh wrote:
>> On Tue, Jul 17, 2012 at 10:06 PM, Greg KH <gregkh@linuxfoundation.org> wrote:
>> > On Mon, Jul 09, 2012 at 07:02:36PM +0530, Shilimkar, Santosh wrote:
>> >> Greg,
>> >>

[..]

>> >From 74688a87fd490909e9122bf757c0096480e9fc11 Mon Sep 17 00:00:00 2001
>> From: Aneesh V <aneesh@ti.com>
>> Date: Mon, 30 Jan 2012 20:06:30 +0530
>> Subject: [PATCH 4/4] memory: emif: add device tree support to emif driver
>>
>> Device tree support for the EMIF driver. LPDDR2 generic timings
>> extraction from device is managed using couple of helper
>> functions which can be used by other memory controller
>> drivers.
>>
>> Reviewed-by: Benoit Cousson <b-cousson@ti.com>
>> Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
>> Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
>> Signed-off-by: Aneesh V <aneesh@ti.com>
>> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
>> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>> ---
>>  drivers/memory/Makefile    |    1 +
>>  drivers/memory/emif.c      |  182 +++++++++++++++++++++++++++++++++++++++++++-
>>  drivers/memory/of_memory.c |  153 +++++++++++++++++++++++++++++++++++++
>>  drivers/memory/of_memory.h |   36 +++++++++
>>  4 files changed, 371 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/memory/of_memory.c
>>  create mode 100644 drivers/memory/of_memory.h
>>
>> diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
>> index 42b3ce9..cd8486b 100644
>> --- a/drivers/memory/Makefile
>> +++ b/drivers/memory/Makefile
>> @@ -2,6 +2,7 @@
>>  # Makefile for memory devices
>>  #
>>
>> +obj-$(CONFIG_OF)             += of_memory.o
>>  obj-$(CONFIG_TI_EMIF)                += emif.o
>>  obj-$(CONFIG_TEGRA20_MC)     += tegra20-mc.o
>>  obj-$(CONFIG_TEGRA30_MC)     += tegra30-mc.o
>> diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
>> index 33a4396..06b4eb7 100644
>> --- a/drivers/memory/emif.c
>> +++ b/drivers/memory/emif.c
>> @@ -18,6 +18,7 @@
>>  #include <linux/platform_device.h>
>>  #include <linux/interrupt.h>
>>  #include <linux/slab.h>
>> +#include <linux/of.h>
>>  #include <linux/debugfs.h>
>>  #include <linux/seq_file.h>
>>  #include <linux/module.h>
>> @@ -25,6 +26,7 @@
>>  #include <linux/spinlock.h>
>>  #include <memory/jedec_ddr.h>
>>  #include "emif.h"
>> +#include "of_memory.h"
>>
>>  /**
>>   * struct emif_data - Per device static data for driver's use
>> @@ -49,6 +51,7 @@
>>   *                           frequency in effect at the moment)
>>   * @plat_data:                       Pointer to saved platform data.
>>   * @debugfs_root:            dentry to the root folder for EMIF in debugfs
>> + * @np_ddr:                  Pointer to ddr device tree node
>>   */
>>  struct emif_data {
>>       u8                              duplicate;
>> @@ -63,6 +66,7 @@ struct emif_data {
>>       struct emif_regs                *curr_regs;
>>       struct emif_platform_data       *plat_data;
>>       struct dentry                   *debugfs_root;
>> +     struct device_node              *np_ddr;
>>  };
>>
>>  static struct emif_data *emif1;
>> @@ -1148,6 +1152,168 @@ static int is_custom_config_valid(struct
>> emif_custom_configs *cust_cfgs,
>>       return valid;
>>  }
>>
>> +#if defined(CONFIG_OF)
>> +static void __init_or_module of_get_custom_configs(struct device_node *np_emif,
>> +             struct emif_data *emif)
>
> Why can't all of this code be in the of_memory.c file?
>
Primarily because the parameters are very much specific to EMIF
memory controller and won't be of much use for other memory controllers.

Currently the information extracted from DT with these function is like:
- EMIF controller IP version : EMIF_4D or EMIF_4D5
- Which analog phy is integrated : EMIF_ATTILAPHY or EMIF_ATTILAPHY
- IP hardware interface: EMIF Low latency port or sys port interface.
- EMIF connections - Whether EMIF1 only, EMIF2 only or EMIF1 & EMIF2
- Memory connections to EMIF - Same type and size memories or asymmetric
- Chip select usage per controller: Whether CS0, CS1, CS0 & CS1
- ZQ calibration - Per chip select or enable EMIF dual calibration feature.
- Enable/disable EMIF Low power mode and temperature alerts.
- EMIF low power mode configuration:
      - Clock stop, self refresh, Deep power down.
      - Low power time out values for performance and power mode.
      - DDR frequency threshold to switch between power and
performance settings.
- EMIF temperature polling cycle configuration.

As you can see these are very specific to the EMIF memory controller and hence
I didn't move them to of_memory.c

>> +static struct emif_data * __init_or_module of_get_device_details(
>> +             struct device_node *np_emif, struct device *dev)
>
> of_get_memory_device_details()?
>
Right. Will rename it as you suggested.

>> +{
>> +     struct emif_data                *emif = NULL;
>> +     struct ddr_device_info          *dev_info = NULL;
>> +     struct emif_platform_data       *pd = NULL;
>> +     struct device_node              *np_ddr;
>> +     int                             len;
>> +
>> +     np_ddr = of_parse_phandle(np_emif, "device-handle", 0);
>> +     if (!np_ddr)
>> +             goto error;
>> +     emif    = devm_kzalloc(dev, sizeof(struct emif_data), GFP_KERNEL);
>> +     pd      = 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: of_get_device_details() failure!!\n",
>> +                     __func__);
>
> Look at what that error message just printed out.  Redundancy is nice,
> but come on, that's not ok :)
>
Agree. The error message should have been some thing like
"Out of memory". Will fix this in next version.

Regards
Santosh

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

* [PATCH v4 4/4] memory: emif: add device tree support to emif driver
  2012-07-18  6:44                   ` Shilimkar, Santosh
@ 2012-08-13  5:27                     ` Shilimkar, Santosh
  2012-08-16 18:45                       ` Greg KH
  0 siblings, 1 reply; 17+ messages in thread
From: Shilimkar, Santosh @ 2012-08-13  5:27 UTC (permalink / raw)
  To: linux-arm-kernel

Greg,

On Wed, Jul 18, 2012 at 12:14 PM, Shilimkar, Santosh
<santosh.shilimkar@ti.com> wrote:
> On Tue, Jul 17, 2012 at 11:28 PM, Greg KH <gregkh@linuxfoundation.org> wrote:
>> On Tue, Jul 17, 2012 at 10:37:45PM +0530, Shilimkar, Santosh wrote:
>>> On Tue, Jul 17, 2012 at 10:06 PM, Greg KH <gregkh@linuxfoundation.org> wrote:
>>> > On Mon, Jul 09, 2012 at 07:02:36PM +0530, Shilimkar, Santosh wrote:
>>> >> Greg,
>>> >>
>
> [..]
>
>>> >From 74688a87fd490909e9122bf757c0096480e9fc11 Mon Sep 17 00:00:00 2001
>>> From: Aneesh V <aneesh@ti.com>
>>> Date: Mon, 30 Jan 2012 20:06:30 +0530
>>> Subject: [PATCH 4/4] memory: emif: add device tree support to emif driver
>>>
>>> Device tree support for the EMIF driver. LPDDR2 generic timings
>>> extraction from device is managed using couple of helper
>>> functions which can be used by other memory controller
>>> drivers.
>>>
>>> Reviewed-by: Benoit Cousson <b-cousson@ti.com>
>>> Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
>>> Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
>>> Signed-off-by: Aneesh V <aneesh@ti.com>
>>> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>>> ---
>>>  drivers/memory/Makefile    |    1 +
>>>  drivers/memory/emif.c      |  182 +++++++++++++++++++++++++++++++++++++++++++-
>>>  drivers/memory/of_memory.c |  153 +++++++++++++++++++++++++++++++++++++
>>>  drivers/memory/of_memory.h |   36 +++++++++
>>>  4 files changed, 371 insertions(+), 1 deletion(-)
>>>  create mode 100644 drivers/memory/of_memory.c
>>>  create mode 100644 drivers/memory/of_memory.h
>>>
>>> diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
>>> index 42b3ce9..cd8486b 100644
>>> --- a/drivers/memory/Makefile
>>> +++ b/drivers/memory/Makefile
>>> @@ -2,6 +2,7 @@
>>>  # Makefile for memory devices
>>>  #
>>>
>>> +obj-$(CONFIG_OF)             += of_memory.o
>>>  obj-$(CONFIG_TI_EMIF)                += emif.o
>>>  obj-$(CONFIG_TEGRA20_MC)     += tegra20-mc.o
>>>  obj-$(CONFIG_TEGRA30_MC)     += tegra30-mc.o
>>> diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
>>> index 33a4396..06b4eb7 100644
>>> --- a/drivers/memory/emif.c
>>> +++ b/drivers/memory/emif.c
>>> @@ -18,6 +18,7 @@
>>>  #include <linux/platform_device.h>
>>>  #include <linux/interrupt.h>
>>>  #include <linux/slab.h>
>>> +#include <linux/of.h>
>>>  #include <linux/debugfs.h>
>>>  #include <linux/seq_file.h>
>>>  #include <linux/module.h>
>>> @@ -25,6 +26,7 @@
>>>  #include <linux/spinlock.h>
>>>  #include <memory/jedec_ddr.h>
>>>  #include "emif.h"
>>> +#include "of_memory.h"
>>>
>>>  /**
>>>   * struct emif_data - Per device static data for driver's use
>>> @@ -49,6 +51,7 @@
>>>   *                           frequency in effect at the moment)
>>>   * @plat_data:                       Pointer to saved platform data.
>>>   * @debugfs_root:            dentry to the root folder for EMIF in debugfs
>>> + * @np_ddr:                  Pointer to ddr device tree node
>>>   */
>>>  struct emif_data {
>>>       u8                              duplicate;
>>> @@ -63,6 +66,7 @@ struct emif_data {
>>>       struct emif_regs                *curr_regs;
>>>       struct emif_platform_data       *plat_data;
>>>       struct dentry                   *debugfs_root;
>>> +     struct device_node              *np_ddr;
>>>  };
>>>
>>>  static struct emif_data *emif1;
>>> @@ -1148,6 +1152,168 @@ static int is_custom_config_valid(struct
>>> emif_custom_configs *cust_cfgs,
>>>       return valid;
>>>  }
>>>
>>> +#if defined(CONFIG_OF)
>>> +static void __init_or_module of_get_custom_configs(struct device_node *np_emif,
>>> +             struct emif_data *emif)
>>
>> Why can't all of this code be in the of_memory.c file?
>>
> Primarily because the parameters are very much specific to EMIF
> memory controller and won't be of much use for other memory controllers.
>
> Currently the information extracted from DT with these function is like:
> - EMIF controller IP version : EMIF_4D or EMIF_4D5
> - Which analog phy is integrated : EMIF_ATTILAPHY or EMIF_ATTILAPHY
> - IP hardware interface: EMIF Low latency port or sys port interface.
> - EMIF connections - Whether EMIF1 only, EMIF2 only or EMIF1 & EMIF2
> - Memory connections to EMIF - Same type and size memories or asymmetric
> - Chip select usage per controller: Whether CS0, CS1, CS0 & CS1
> - ZQ calibration - Per chip select or enable EMIF dual calibration feature.
> - Enable/disable EMIF Low power mode and temperature alerts.
> - EMIF low power mode configuration:
>       - Clock stop, self refresh, Deep power down.
>       - Low power time out values for performance and power mode.
>       - DDR frequency threshold to switch between power and
> performance settings.
> - EMIF temperature polling cycle configuration.
>
> As you can see these are very specific to the EMIF memory controller and hence
> I didn't move them to of_memory.c
>
Do you have any more comment on this patch? If not, I can go ahead and
post the refreshed version of the patch.

Regards
Santosh

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

* [PATCH v4 4/4] memory: emif: add device tree support to emif driver
  2012-08-13  5:27                     ` Shilimkar, Santosh
@ 2012-08-16 18:45                       ` Greg KH
  2012-08-17  8:50                         ` Shilimkar, Santosh
  0 siblings, 1 reply; 17+ messages in thread
From: Greg KH @ 2012-08-16 18:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 13, 2012 at 10:57:06AM +0530, Shilimkar, Santosh wrote:
> Greg,
> 
> On Wed, Jul 18, 2012 at 12:14 PM, Shilimkar, Santosh
> <santosh.shilimkar@ti.com> wrote:
> > On Tue, Jul 17, 2012 at 11:28 PM, Greg KH <gregkh@linuxfoundation.org> wrote:
> >> On Tue, Jul 17, 2012 at 10:37:45PM +0530, Shilimkar, Santosh wrote:
> >>> On Tue, Jul 17, 2012 at 10:06 PM, Greg KH <gregkh@linuxfoundation.org> wrote:
> >>> > On Mon, Jul 09, 2012 at 07:02:36PM +0530, Shilimkar, Santosh wrote:
> >>> >> Greg,
> >>> >>
> >
> > [..]
> >
> >>> >From 74688a87fd490909e9122bf757c0096480e9fc11 Mon Sep 17 00:00:00 2001
> >>> From: Aneesh V <aneesh@ti.com>
> >>> Date: Mon, 30 Jan 2012 20:06:30 +0530
> >>> Subject: [PATCH 4/4] memory: emif: add device tree support to emif driver
> >>>
> >>> Device tree support for the EMIF driver. LPDDR2 generic timings
> >>> extraction from device is managed using couple of helper
> >>> functions which can be used by other memory controller
> >>> drivers.
> >>>
> >>> Reviewed-by: Benoit Cousson <b-cousson@ti.com>
> >>> Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
> >>> Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
> >>> Signed-off-by: Aneesh V <aneesh@ti.com>
> >>> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> >>> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> >>> ---
> >>>  drivers/memory/Makefile    |    1 +
> >>>  drivers/memory/emif.c      |  182 +++++++++++++++++++++++++++++++++++++++++++-
> >>>  drivers/memory/of_memory.c |  153 +++++++++++++++++++++++++++++++++++++
> >>>  drivers/memory/of_memory.h |   36 +++++++++
> >>>  4 files changed, 371 insertions(+), 1 deletion(-)
> >>>  create mode 100644 drivers/memory/of_memory.c
> >>>  create mode 100644 drivers/memory/of_memory.h
> >>>
> >>> diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
> >>> index 42b3ce9..cd8486b 100644
> >>> --- a/drivers/memory/Makefile
> >>> +++ b/drivers/memory/Makefile
> >>> @@ -2,6 +2,7 @@
> >>>  # Makefile for memory devices
> >>>  #
> >>>
> >>> +obj-$(CONFIG_OF)             += of_memory.o
> >>>  obj-$(CONFIG_TI_EMIF)                += emif.o
> >>>  obj-$(CONFIG_TEGRA20_MC)     += tegra20-mc.o
> >>>  obj-$(CONFIG_TEGRA30_MC)     += tegra30-mc.o
> >>> diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
> >>> index 33a4396..06b4eb7 100644
> >>> --- a/drivers/memory/emif.c
> >>> +++ b/drivers/memory/emif.c
> >>> @@ -18,6 +18,7 @@
> >>>  #include <linux/platform_device.h>
> >>>  #include <linux/interrupt.h>
> >>>  #include <linux/slab.h>
> >>> +#include <linux/of.h>
> >>>  #include <linux/debugfs.h>
> >>>  #include <linux/seq_file.h>
> >>>  #include <linux/module.h>
> >>> @@ -25,6 +26,7 @@
> >>>  #include <linux/spinlock.h>
> >>>  #include <memory/jedec_ddr.h>
> >>>  #include "emif.h"
> >>> +#include "of_memory.h"
> >>>
> >>>  /**
> >>>   * struct emif_data - Per device static data for driver's use
> >>> @@ -49,6 +51,7 @@
> >>>   *                           frequency in effect at the moment)
> >>>   * @plat_data:                       Pointer to saved platform data.
> >>>   * @debugfs_root:            dentry to the root folder for EMIF in debugfs
> >>> + * @np_ddr:                  Pointer to ddr device tree node
> >>>   */
> >>>  struct emif_data {
> >>>       u8                              duplicate;
> >>> @@ -63,6 +66,7 @@ struct emif_data {
> >>>       struct emif_regs                *curr_regs;
> >>>       struct emif_platform_data       *plat_data;
> >>>       struct dentry                   *debugfs_root;
> >>> +     struct device_node              *np_ddr;
> >>>  };
> >>>
> >>>  static struct emif_data *emif1;
> >>> @@ -1148,6 +1152,168 @@ static int is_custom_config_valid(struct
> >>> emif_custom_configs *cust_cfgs,
> >>>       return valid;
> >>>  }
> >>>
> >>> +#if defined(CONFIG_OF)
> >>> +static void __init_or_module of_get_custom_configs(struct device_node *np_emif,
> >>> +             struct emif_data *emif)
> >>
> >> Why can't all of this code be in the of_memory.c file?
> >>
> > Primarily because the parameters are very much specific to EMIF
> > memory controller and won't be of much use for other memory controllers.
> >
> > Currently the information extracted from DT with these function is like:
> > - EMIF controller IP version : EMIF_4D or EMIF_4D5
> > - Which analog phy is integrated : EMIF_ATTILAPHY or EMIF_ATTILAPHY
> > - IP hardware interface: EMIF Low latency port or sys port interface.
> > - EMIF connections - Whether EMIF1 only, EMIF2 only or EMIF1 & EMIF2
> > - Memory connections to EMIF - Same type and size memories or asymmetric
> > - Chip select usage per controller: Whether CS0, CS1, CS0 & CS1
> > - ZQ calibration - Per chip select or enable EMIF dual calibration feature.
> > - Enable/disable EMIF Low power mode and temperature alerts.
> > - EMIF low power mode configuration:
> >       - Clock stop, self refresh, Deep power down.
> >       - Low power time out values for performance and power mode.
> >       - DDR frequency threshold to switch between power and
> > performance settings.
> > - EMIF temperature polling cycle configuration.
> >
> > As you can see these are very specific to the EMIF memory controller and hence
> > I didn't move them to of_memory.c
> >
> Do you have any more comment on this patch? If not, I can go ahead and
> post the refreshed version of the patch.

Please always do, I have no idea what this patch even contained anymore,
it was a few hundred patches ago that I've reviewed and I have no
recollection of it...

thanks,

greg k-h

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

* [PATCH v4 4/4] memory: emif: add device tree support to emif driver
  2012-08-16 18:45                       ` Greg KH
@ 2012-08-17  8:50                         ` Shilimkar, Santosh
  0 siblings, 0 replies; 17+ messages in thread
From: Shilimkar, Santosh @ 2012-08-17  8:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Aug 17, 2012 at 12:15 AM, Greg KH <gregkh@linuxfoundation.org> wrote:
> On Mon, Aug 13, 2012 at 10:57:06AM +0530, Shilimkar, Santosh wrote:
>> Greg,
>>
>> On Wed, Jul 18, 2012 at 12:14 PM, Shilimkar, Santosh
>> <santosh.shilimkar@ti.com> wrote:
>> > On Tue, Jul 17, 2012 at 11:28 PM, Greg KH <gregkh@linuxfoundation.org> wrote:
>> >> On Tue, Jul 17, 2012 at 10:37:45PM +0530, Shilimkar, Santosh wrote:
>> >>> On Tue, Jul 17, 2012 at 10:06 PM, Greg KH <gregkh@linuxfoundation.org> wrote:
>> >>> > On Mon, Jul 09, 2012 at 07:02:36PM +0530, Shilimkar, Santosh wrote:
>> >>> >> Greg,
>> >>> >>
>> >
>> > [..]
>> >
>> >>> >From 74688a87fd490909e9122bf757c0096480e9fc11 Mon Sep 17 00:00:00 2001
>> >>> From: Aneesh V <aneesh@ti.com>
>> >>> Date: Mon, 30 Jan 2012 20:06:30 +0530
>> >>> Subject: [PATCH 4/4] memory: emif: add device tree support to emif driver
>> >>>
>> >>> Device tree support for the EMIF driver. LPDDR2 generic timings
>> >>> extraction from device is managed using couple of helper
>> >>> functions which can be used by other memory controller
>> >>> drivers.
>> >>>
>> >>> Reviewed-by: Benoit Cousson <b-cousson@ti.com>
>> >>> Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
>> >>> Tested-by: Lokesh Vutla <lokeshvutla@ti.com>
>> >>> Signed-off-by: Aneesh V <aneesh@ti.com>
>> >>> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
>> >>> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>> >>> ---
>> >>>  drivers/memory/Makefile    |    1 +
>> >>>  drivers/memory/emif.c      |  182 +++++++++++++++++++++++++++++++++++++++++++-
>> >>>  drivers/memory/of_memory.c |  153 +++++++++++++++++++++++++++++++++++++
>> >>>  drivers/memory/of_memory.h |   36 +++++++++
>> >>>  4 files changed, 371 insertions(+), 1 deletion(-)
>> >>>  create mode 100644 drivers/memory/of_memory.c
>> >>>  create mode 100644 drivers/memory/of_memory.h
>> >>>
>> >>> diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
>> >>> index 42b3ce9..cd8486b 100644
>> >>> --- a/drivers/memory/Makefile
>> >>> +++ b/drivers/memory/Makefile
>> >>> @@ -2,6 +2,7 @@
>> >>>  # Makefile for memory devices
>> >>>  #
>> >>>
>> >>> +obj-$(CONFIG_OF)             += of_memory.o
>> >>>  obj-$(CONFIG_TI_EMIF)                += emif.o
>> >>>  obj-$(CONFIG_TEGRA20_MC)     += tegra20-mc.o
>> >>>  obj-$(CONFIG_TEGRA30_MC)     += tegra30-mc.o
>> >>> diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
>> >>> index 33a4396..06b4eb7 100644
>> >>> --- a/drivers/memory/emif.c
>> >>> +++ b/drivers/memory/emif.c
>> >>> @@ -18,6 +18,7 @@
>> >>>  #include <linux/platform_device.h>
>> >>>  #include <linux/interrupt.h>
>> >>>  #include <linux/slab.h>
>> >>> +#include <linux/of.h>
>> >>>  #include <linux/debugfs.h>
>> >>>  #include <linux/seq_file.h>
>> >>>  #include <linux/module.h>
>> >>> @@ -25,6 +26,7 @@
>> >>>  #include <linux/spinlock.h>
>> >>>  #include <memory/jedec_ddr.h>
>> >>>  #include "emif.h"
>> >>> +#include "of_memory.h"
>> >>>
>> >>>  /**
>> >>>   * struct emif_data - Per device static data for driver's use
>> >>> @@ -49,6 +51,7 @@
>> >>>   *                           frequency in effect at the moment)
>> >>>   * @plat_data:                       Pointer to saved platform data.
>> >>>   * @debugfs_root:            dentry to the root folder for EMIF in debugfs
>> >>> + * @np_ddr:                  Pointer to ddr device tree node
>> >>>   */
>> >>>  struct emif_data {
>> >>>       u8                              duplicate;
>> >>> @@ -63,6 +66,7 @@ struct emif_data {
>> >>>       struct emif_regs                *curr_regs;
>> >>>       struct emif_platform_data       *plat_data;
>> >>>       struct dentry                   *debugfs_root;
>> >>> +     struct device_node              *np_ddr;
>> >>>  };
>> >>>
>> >>>  static struct emif_data *emif1;
>> >>> @@ -1148,6 +1152,168 @@ static int is_custom_config_valid(struct
>> >>> emif_custom_configs *cust_cfgs,
>> >>>       return valid;
>> >>>  }
>> >>>
>> >>> +#if defined(CONFIG_OF)
>> >>> +static void __init_or_module of_get_custom_configs(struct device_node *np_emif,
>> >>> +             struct emif_data *emif)
>> >>
>> >> Why can't all of this code be in the of_memory.c file?
>> >>
>> > Primarily because the parameters are very much specific to EMIF
>> > memory controller and won't be of much use for other memory controllers.
>> >
>> > Currently the information extracted from DT with these function is like:
>> > - EMIF controller IP version : EMIF_4D or EMIF_4D5
>> > - Which analog phy is integrated : EMIF_ATTILAPHY or EMIF_ATTILAPHY
>> > - IP hardware interface: EMIF Low latency port or sys port interface.
>> > - EMIF connections - Whether EMIF1 only, EMIF2 only or EMIF1 & EMIF2
>> > - Memory connections to EMIF - Same type and size memories or asymmetric
>> > - Chip select usage per controller: Whether CS0, CS1, CS0 & CS1
>> > - ZQ calibration - Per chip select or enable EMIF dual calibration feature.
>> > - Enable/disable EMIF Low power mode and temperature alerts.
>> > - EMIF low power mode configuration:
>> >       - Clock stop, self refresh, Deep power down.
>> >       - Low power time out values for performance and power mode.
>> >       - DDR frequency threshold to switch between power and
>> > performance settings.
>> > - EMIF temperature polling cycle configuration.
>> >
>> > As you can see these are very specific to the EMIF memory controller and hence
>> > I didn't move them to of_memory.c
>> >
>> Do you have any more comment on this patch? If not, I can go ahead and
>> post the refreshed version of the patch.
>
> Please always do, I have no idea what this patch even contained anymore,
> it was a few hundred patches ago that I've reviewed and I have no
> recollection of it...
>
Done. Posted the refresh version [1]. Thanks for review.

Regards
Santosh

[1] https://patchwork.kernel.org/patch/1337871/

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

end of thread, other threads:[~2012-08-17  8:50 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-29 13:43 [PATCH v4 0/4] dt: device tree support for TI EMIF driver for 3.6 Santosh Shilimkar
2012-06-29 13:43 ` [PATCH v4 1/4] dt: device tree bindings for LPDDR2 memories Santosh Shilimkar
2012-06-29 13:43 ` [PATCH v4 2/4] dt: emif: device tree bindings for TI's EMIF sdram controller Santosh Shilimkar
2012-06-29 13:43 ` [PATCH v4 3/4] arm: dts: EMIF and LPDDR2 device tree data for OMAP4 boards Santosh Shilimkar
2012-06-29 13:43 ` [PATCH v4 4/4] memory: emif: add device tree support to emif driver Santosh Shilimkar
2012-06-30  4:08   ` Shilimkar, Santosh
2012-06-30  4:23     ` Greg KH
2012-06-30  4:42       ` Shilimkar, Santosh
2012-07-02 13:18         ` Shilimkar, Santosh
2012-07-09 13:32           ` Shilimkar, Santosh
2012-07-17 16:36             ` Greg KH
2012-07-17 17:07               ` Shilimkar, Santosh
2012-07-17 17:58                 ` Greg KH
2012-07-18  6:44                   ` Shilimkar, Santosh
2012-08-13  5:27                     ` Shilimkar, Santosh
2012-08-16 18:45                       ` Greg KH
2012-08-17  8:50                         ` Shilimkar, Santosh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).