All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/7] tegra20-emc: Identify memory chip by LPDDR configuration
@ 2021-10-05 23:00 Dmitry Osipenko
  2021-10-05 23:00 ` [PATCH v4 1/7] dt-bindings: Relocate DDR bindings Dmitry Osipenko
                   ` (6 more replies)
  0 siblings, 7 replies; 17+ messages in thread
From: Dmitry Osipenko @ 2021-10-05 23:00 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Krzysztof Kozlowski, Rob Herring
  Cc: devicetree, linux-kernel, linux-tegra

Support memory chip identification by LPDDR2 configuration, which is
needed by ASUS Transformer TF101 tablet device that doesn't store RAMCODE
in Tegra's NVMEM.

Changelog:

v4: - Moved DDR bindings directory to memory-controllers/, like it
      was suggested by Krzysztof Kozlowski.

    - Converted existing LPDDR2 binding to schema and utilized it,
      like it was requested by Krzysztof Kozlowski.

    - Added Elpida B8132B2PB-6D-F compatible.

    - Made code changes that were requested by Krzysztof Kozlowski.

v3: - Corrected sub-node name in tegra20-emc.yaml.

v2: - Added separate binding for standard LPDDR2 properties, like it
      was suggested by Krzysztof Kozlowski.

    - Switched Tegra binding to use new lpddr2-configuration sub-node
      that contains the standard properties.

    - Extended commit message of the "emc: Document new LPDDR2 sub-node"
      patch, telling how the properties are supposed to be used, which
      was requested by Krzysztof Kozlowski.

    - Added new common helpers for parsing LPDDR2 properties and made
      tegra20-emc driver to use these helpers.

Dmitry Osipenko (7):
  dt-bindings: Relocate DDR bindings
  dt-bindings: memory: lpddr2: Convert to schema
  dt-bindings: memory: lpddr2: Add revision-id properties
  dt-bindings: memory: lpddr2: Document Elpida B8132B2PB-6D-F
  dt-bindings: memory: tegra20: emc: Document new LPDDR2 sub-node
  memory: Add LPDDR2 configuration helpers
  memory: tegra20-emc: Support matching timings by LPDDR2 configuration

 .../devicetree/bindings/ddr/lpddr2.txt        | 102 ---------
 .../memory-controllers/ddr/jedec,lpddr2.yaml  | 208 ++++++++++++++++++
 .../ddr/lpddr2-timings.txt                    |   0
 .../ddr/lpddr3-timings.txt                    |   0
 .../{ => memory-controllers}/ddr/lpddr3.txt   |   0
 .../nvidia,tegra20-emc.yaml                   |  23 +-
 drivers/memory/jedec_ddr.h                    |  46 ++++
 drivers/memory/jedec_ddr_data.c               |  41 ++++
 drivers/memory/of_memory.c                    |  88 ++++++++
 drivers/memory/of_memory.h                    |   9 +
 drivers/memory/tegra/Kconfig                  |   1 +
 drivers/memory/tegra/tegra20-emc.c            | 199 +++++++++++++++--
 12 files changed, 599 insertions(+), 118 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/ddr/lpddr2.txt
 create mode 100644 Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
 rename Documentation/devicetree/bindings/{ => memory-controllers}/ddr/lpddr2-timings.txt (100%)
 rename Documentation/devicetree/bindings/{ => memory-controllers}/ddr/lpddr3-timings.txt (100%)
 rename Documentation/devicetree/bindings/{ => memory-controllers}/ddr/lpddr3.txt (100%)

-- 
2.32.0


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

* [PATCH v4 1/7] dt-bindings: Relocate DDR bindings
  2021-10-05 23:00 [PATCH v4 0/7] tegra20-emc: Identify memory chip by LPDDR configuration Dmitry Osipenko
@ 2021-10-05 23:00 ` Dmitry Osipenko
  2021-10-05 23:00 ` [PATCH v4 2/7] dt-bindings: memory: lpddr2: Convert to schema Dmitry Osipenko
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 17+ messages in thread
From: Dmitry Osipenko @ 2021-10-05 23:00 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Krzysztof Kozlowski, Rob Herring
  Cc: devicetree, linux-kernel, linux-tegra

Move DDR bindings to memory-controllers directory to make them more
discoverable.

Suggested-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../bindings/{ => memory-controllers}/ddr/lpddr2-timings.txt      | 0
 .../devicetree/bindings/{ => memory-controllers}/ddr/lpddr2.txt   | 0
 .../bindings/{ => memory-controllers}/ddr/lpddr3-timings.txt      | 0
 .../devicetree/bindings/{ => memory-controllers}/ddr/lpddr3.txt   | 0
 4 files changed, 0 insertions(+), 0 deletions(-)
 rename Documentation/devicetree/bindings/{ => memory-controllers}/ddr/lpddr2-timings.txt (100%)
 rename Documentation/devicetree/bindings/{ => memory-controllers}/ddr/lpddr2.txt (100%)
 rename Documentation/devicetree/bindings/{ => memory-controllers}/ddr/lpddr3-timings.txt (100%)
 rename Documentation/devicetree/bindings/{ => memory-controllers}/ddr/lpddr3.txt (100%)

diff --git a/Documentation/devicetree/bindings/ddr/lpddr2-timings.txt b/Documentation/devicetree/bindings/memory-controllers/ddr/lpddr2-timings.txt
similarity index 100%
rename from Documentation/devicetree/bindings/ddr/lpddr2-timings.txt
rename to Documentation/devicetree/bindings/memory-controllers/ddr/lpddr2-timings.txt
diff --git a/Documentation/devicetree/bindings/ddr/lpddr2.txt b/Documentation/devicetree/bindings/memory-controllers/ddr/lpddr2.txt
similarity index 100%
rename from Documentation/devicetree/bindings/ddr/lpddr2.txt
rename to Documentation/devicetree/bindings/memory-controllers/ddr/lpddr2.txt
diff --git a/Documentation/devicetree/bindings/ddr/lpddr3-timings.txt b/Documentation/devicetree/bindings/memory-controllers/ddr/lpddr3-timings.txt
similarity index 100%
rename from Documentation/devicetree/bindings/ddr/lpddr3-timings.txt
rename to Documentation/devicetree/bindings/memory-controllers/ddr/lpddr3-timings.txt
diff --git a/Documentation/devicetree/bindings/ddr/lpddr3.txt b/Documentation/devicetree/bindings/memory-controllers/ddr/lpddr3.txt
similarity index 100%
rename from Documentation/devicetree/bindings/ddr/lpddr3.txt
rename to Documentation/devicetree/bindings/memory-controllers/ddr/lpddr3.txt
-- 
2.32.0


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

* [PATCH v4 2/7] dt-bindings: memory: lpddr2: Convert to schema
  2021-10-05 23:00 [PATCH v4 0/7] tegra20-emc: Identify memory chip by LPDDR configuration Dmitry Osipenko
  2021-10-05 23:00 ` [PATCH v4 1/7] dt-bindings: Relocate DDR bindings Dmitry Osipenko
@ 2021-10-05 23:00 ` Dmitry Osipenko
  2021-10-06 10:57   ` Krzysztof Kozlowski
  2021-10-05 23:00 ` [PATCH v4 3/7] dt-bindings: memory: lpddr2: Add revision-id properties Dmitry Osipenko
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: Dmitry Osipenko @ 2021-10-05 23:00 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Krzysztof Kozlowski, Rob Herring
  Cc: devicetree, linux-kernel, linux-tegra

Convert LPDDR2 binding to schema. I removed obsolete ti,jedec-lpddr2-*
compatibles since they were never used by device-trees and by the code.

Suggested-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../memory-controllers/ddr/jedec,lpddr2.yaml  | 195 ++++++++++++++++++
 .../memory-controllers/ddr/lpddr2.txt         | 102 ---------
 2 files changed, 195 insertions(+), 102 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
 delete mode 100644 Documentation/devicetree/bindings/memory-controllers/ddr/lpddr2.txt

diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
new file mode 100644
index 000000000000..d99ccad54938
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
@@ -0,0 +1,195 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/ddr/jedec,lpddr2.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: LPDDR2 SDRAM compliant to JEDEC JESD209-2
+
+maintainers:
+  - Krzysztof Kozlowski <krzk@kernel.org>
+
+properties:
+  compatible:
+    oneOf:
+      - items:
+          - enum:
+              - Elpida,ECB240ABACN
+          - enum:
+              - jedec,lpddr2-s4
+      - items:
+          - enum:
+              - jedec,lpddr2-s2
+      - items:
+          - enum:
+              - jedec,lpddr2-nvm
+
+  density:
+    description: |
+      Density in megabits of SDRAM chip. Obtained from device datasheet.
+    enum:
+      - 64
+      - 128
+      - 256
+      - 512
+      - 1024
+      - 2048
+      - 4096
+      - 8192
+      - 16384
+      - 32768
+
+  io-width:
+    description: |
+      IO bus width in bits of SDRAM chip. Obtained from device datasheet.
+    enum:
+      - 32
+      - 16
+      - 8
+
+  tRRD-min-tck:
+    maximum: 16
+    description: |
+      Active bank a to active bank b in terms of number of clock cycles.
+      Obtained from device datasheet.
+
+  tWTR-min-tck:
+    maximum: 16
+    description: |
+      Internal WRITE-to-READ command delay in terms of number of clock cycles.
+      Obtained from device datasheet.
+
+  tXP-min-tck:
+    maximum: 16
+    description: |
+      Exit power-down to next valid command delay in terms of number of clock
+      cycles. Obtained from device datasheet.
+
+  tRTP-min-tck:
+    maximum: 16
+    description: |
+      Internal READ to PRECHARGE command delay in terms of number of clock
+      cycles. Obtained from device datasheet.
+
+  tCKE-min-tck:
+    maximum: 16
+    description: |
+      CKE minimum pulse width (HIGH and LOW pulse width) in terms of number
+      of clock cycles. Obtained from device datasheet.
+
+  tRPab-min-tck:
+    maximum: 16
+    description: |
+      Row precharge time (all banks) in terms of number of clock cycles.
+      Obtained from device datasheet.
+
+  tRCD-min-tck:
+    maximum: 16
+    description: |
+      RAS-to-CAS delay in terms of number of clock cycles. Obtained from
+      device datasheet.
+
+  tWR-min-tck:
+    maximum: 16
+    description: |
+      WRITE recovery time in terms of number of clock cycles. Obtained from
+      device datasheet.
+
+  tRASmin-min-tck:
+    maximum: 16
+    description: |
+      Row active time in terms of number of clock cycles. Obtained from device
+      datasheet.
+
+  tCKESR-min-tck:
+    maximum: 16
+    description: |
+      CKE minimum pulse width during SELF REFRESH (low pulse width during
+      SELF REFRESH) in terms of number of clock cycles. Obtained from device
+      datasheet.
+
+  tFAW-min-tck:
+    maximum: 16
+    description: |
+      Four-bank activate window in terms of number of clock cycles. Obtained
+      from device datasheet.
+
+patternProperties:
+  "^lpddr2-timings":
+    type: object
+    description: |
+      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/memory-controllers/ddr/lpddr2-timings.txt for more information
+      on "lpddr2-timings".
+
+required:
+  - compatible
+  - density
+  - io-width
+
+additionalProperties: false
+
+examples:
+  - |
+    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-timings0 {
+            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-timings1 {
+            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>;
+        };
+    };
diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/lpddr2.txt b/Documentation/devicetree/bindings/memory-controllers/ddr/lpddr2.txt
deleted file mode 100644
index ddd40121e6f6..000000000000
--- a/Documentation/devicetree/bindings/memory-controllers/ddr/lpddr2.txt
+++ /dev/null
@@ -1,102 +0,0 @@
-* 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/ddr/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@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@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>;
-	};
-
-}
-- 
2.32.0


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

* [PATCH v4 3/7] dt-bindings: memory: lpddr2: Add revision-id properties
  2021-10-05 23:00 [PATCH v4 0/7] tegra20-emc: Identify memory chip by LPDDR configuration Dmitry Osipenko
  2021-10-05 23:00 ` [PATCH v4 1/7] dt-bindings: Relocate DDR bindings Dmitry Osipenko
  2021-10-05 23:00 ` [PATCH v4 2/7] dt-bindings: memory: lpddr2: Convert to schema Dmitry Osipenko
@ 2021-10-05 23:00 ` Dmitry Osipenko
  2021-10-06 10:59   ` Krzysztof Kozlowski
  2021-10-05 23:00 ` [PATCH v4 4/7] dt-bindings: memory: lpddr2: Document Elpida B8132B2PB-6D-F Dmitry Osipenko
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: Dmitry Osipenko @ 2021-10-05 23:00 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Krzysztof Kozlowski, Rob Herring
  Cc: devicetree, linux-kernel, linux-tegra

Add optional revision-id standard LPDDR2 properties which will help to
identify memory chip.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../memory-controllers/ddr/jedec,lpddr2.yaml         | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
index d99ccad54938..01efb43c3425 100644
--- a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
@@ -24,6 +24,16 @@ properties:
           - enum:
               - jedec,lpddr2-nvm
 
+  revision-id1:
+    maximum: 255
+    description: |
+      Revision 1 value of SDRAM chip. Obtained from device datasheet.
+
+  revision-id2:
+    maximum: 255
+    description: |
+      Revision 2 value of SDRAM chip. Obtained from device datasheet.
+
   density:
     description: |
       Density in megabits of SDRAM chip. Obtained from device datasheet.
@@ -138,6 +148,8 @@ examples:
         compatible = "Elpida,ECB240ABACN", "jedec,lpddr2-s4";
         density = <2048>;
         io-width = <32>;
+        revision-id1 = <1>;
+        revision-id2 = <0>;
 
         tRPab-min-tck = <3>;
         tRCD-min-tck = <3>;
-- 
2.32.0


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

* [PATCH v4 4/7] dt-bindings: memory: lpddr2: Document Elpida B8132B2PB-6D-F
  2021-10-05 23:00 [PATCH v4 0/7] tegra20-emc: Identify memory chip by LPDDR configuration Dmitry Osipenko
                   ` (2 preceding siblings ...)
  2021-10-05 23:00 ` [PATCH v4 3/7] dt-bindings: memory: lpddr2: Add revision-id properties Dmitry Osipenko
@ 2021-10-05 23:00 ` Dmitry Osipenko
  2021-10-05 23:00 ` [PATCH v4 5/7] dt-bindings: memory: tegra20: emc: Document new LPDDR2 sub-node Dmitry Osipenko
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 17+ messages in thread
From: Dmitry Osipenko @ 2021-10-05 23:00 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Krzysztof Kozlowski, Rob Herring
  Cc: devicetree, linux-kernel, linux-tegra

Elpida B8132B2PB-6D-F memory chip is used by ASUS Transformer TF101
tablet, add compatible for it. We need to specify this compatible it
for a device-tree node containing corresponding memory timings in order
to allow software to match the timings with the detected hardware.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
index 01efb43c3425..464d8406be3c 100644
--- a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
@@ -15,6 +15,7 @@ properties:
       - items:
           - enum:
               - Elpida,ECB240ABACN
+              - elpida,B8132B2PB-6D-F
           - enum:
               - jedec,lpddr2-s4
       - items:
-- 
2.32.0


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

* [PATCH v4 5/7] dt-bindings: memory: tegra20: emc: Document new LPDDR2 sub-node
  2021-10-05 23:00 [PATCH v4 0/7] tegra20-emc: Identify memory chip by LPDDR configuration Dmitry Osipenko
                   ` (3 preceding siblings ...)
  2021-10-05 23:00 ` [PATCH v4 4/7] dt-bindings: memory: lpddr2: Document Elpida B8132B2PB-6D-F Dmitry Osipenko
@ 2021-10-05 23:00 ` Dmitry Osipenko
  2021-10-05 23:00 ` [PATCH v4 6/7] memory: Add LPDDR2 configuration helpers Dmitry Osipenko
  2021-10-05 23:00 ` [PATCH v4 7/7] memory: tegra20-emc: Support matching timings by LPDDR2 configuration Dmitry Osipenko
  6 siblings, 0 replies; 17+ messages in thread
From: Dmitry Osipenko @ 2021-10-05 23:00 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Krzysztof Kozlowski, Rob Herring
  Cc: devicetree, linux-kernel, linux-tegra

Some Tegra20 boards don't have RAM code stored in NVMEM, which is used for
the memory chip identification and the identity information should be read
out from LPDDR2 chip in this case. Document new sub-node containing generic
LPDDR2 properties that will be used for the memory chip identification if
RAM code isn't available. The identification is done by reading out memory
configuration values from generic LPDDR2 mode registers of SDRAM chip and
comparing them with the values of device-tree 'lpddr2' sub-node.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../nvidia,tegra20-emc.yaml                   | 23 +++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.yaml b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.yaml
index cac6842dc8f1..2fa44951cfde 100644
--- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.yaml
@@ -164,12 +164,20 @@ patternProperties:
       "#size-cells":
         const: 0
 
+      lpddr2:
+        $ref: "ddr/jedec,lpddr2.yaml#"
+        type: object
+
     patternProperties:
       "^emc-table@[0-9]+$":
         $ref: "#/$defs/emc-table"
 
-    required:
-      - nvidia,ram-code
+    oneOf:
+      - required:
+          - nvidia,ram-code
+
+      - required:
+          - lpddr2
 
     additionalProperties: false
 
@@ -227,4 +235,15 @@ examples:
                         0x00000000 0x00000000 0x00000000 0x00000000>;
             };
         };
+
+        emc-tables@1 {
+            reg = <1>;
+
+            lpddr2 {
+                compatible = "elpida,B8132B2PB-6D-F", "jedec,lpddr2-s4";
+                revision-id1 = <1>;
+                density = <2048>;
+                io-width = <16>;
+            };
+        };
     };
-- 
2.32.0


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

* [PATCH v4 6/7] memory: Add LPDDR2 configuration helpers
  2021-10-05 23:00 [PATCH v4 0/7] tegra20-emc: Identify memory chip by LPDDR configuration Dmitry Osipenko
                   ` (4 preceding siblings ...)
  2021-10-05 23:00 ` [PATCH v4 5/7] dt-bindings: memory: tegra20: emc: Document new LPDDR2 sub-node Dmitry Osipenko
@ 2021-10-05 23:00 ` Dmitry Osipenko
  2021-10-05 23:00 ` [PATCH v4 7/7] memory: tegra20-emc: Support matching timings by LPDDR2 configuration Dmitry Osipenko
  6 siblings, 0 replies; 17+ messages in thread
From: Dmitry Osipenko @ 2021-10-05 23:00 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Krzysztof Kozlowski, Rob Herring
  Cc: devicetree, linux-kernel, linux-tegra

Add common helpers for reading and parsing standard LPDDR2 configuration
properties.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/memory/jedec_ddr.h      | 46 +++++++++++++++++
 drivers/memory/jedec_ddr_data.c | 41 +++++++++++++++
 drivers/memory/of_memory.c      | 88 +++++++++++++++++++++++++++++++++
 drivers/memory/of_memory.h      |  9 ++++
 4 files changed, 184 insertions(+)

diff --git a/drivers/memory/jedec_ddr.h b/drivers/memory/jedec_ddr.h
index e59ccbd982d0..6bc617ee2e5c 100644
--- a/drivers/memory/jedec_ddr.h
+++ b/drivers/memory/jedec_ddr.h
@@ -112,6 +112,26 @@
 #define NUM_DDR_ADDR_TABLE_ENTRIES			11
 #define NUM_DDR_TIMING_TABLE_ENTRIES			4
 
+#define LPDDR2_MANID_SAMSUNG		1
+#define LPDDR2_MANID_QIMONDA		2
+#define LPDDR2_MANID_ELPIDA		3
+#define LPDDR2_MANID_ETRON		4
+#define LPDDR2_MANID_NANYA		5
+#define LPDDR2_MANID_HYNIX		6
+#define LPDDR2_MANID_MOSEL		7
+#define LPDDR2_MANID_WINBOND		8
+#define LPDDR2_MANID_ESMT		9
+#define LPDDR2_MANID_SPANSION		11
+#define LPDDR2_MANID_SST		12
+#define LPDDR2_MANID_ZMOS		13
+#define LPDDR2_MANID_INTEL		14
+#define LPDDR2_MANID_NUMONYX		254
+#define LPDDR2_MANID_MICRON		255
+
+#define LPDDR2_TYPE_S4			0
+#define LPDDR2_TYPE_S2			1
+#define LPDDR2_TYPE_NVM			2
+
 /* Structure for DDR addressing info from the JEDEC spec */
 struct lpddr2_addressing {
 	u32 num_banks;
@@ -170,6 +190,32 @@ extern const struct lpddr2_timings
 	lpddr2_jedec_timings[NUM_DDR_TIMING_TABLE_ENTRIES];
 extern const struct lpddr2_min_tck lpddr2_jedec_min_tck;
 
+/* Structure of MR8 */
+union lpddr2_basic_config4 {
+	u32 value;
+
+	struct {
+		unsigned int arch_type : 2;
+		unsigned int density : 4;
+		unsigned int io_width : 2;
+	} __packed;
+};
+
+/*
+ * Structure for information about LPDDR2 chip. All parameters are matching
+ * raw values of mode register bitfields or negative if info unavailable.
+ */
+struct lpddr2_info {
+	int arch_type;
+	int density;
+	int io_width;
+	int manufacturer_id;
+	int revision_id1;
+	int revision_id2;
+};
+
+const char *lpddr2_jedec_manufacturer(unsigned int manufacturer_id);
+
 /*
  * Structure for timings for LPDDR3 based on LPDDR2 plus additional fields.
  * All parameters are in pico seconds(ps) excluding max_freq, min_freq which
diff --git a/drivers/memory/jedec_ddr_data.c b/drivers/memory/jedec_ddr_data.c
index ed601d813175..2cca4fa188f9 100644
--- a/drivers/memory/jedec_ddr_data.c
+++ b/drivers/memory/jedec_ddr_data.c
@@ -131,3 +131,44 @@ const struct lpddr2_min_tck lpddr2_jedec_min_tck = {
 	.tFAW		= 8
 };
 EXPORT_SYMBOL_GPL(lpddr2_jedec_min_tck);
+
+const char *lpddr2_jedec_manufacturer(unsigned int manufacturer_id)
+{
+	switch (manufacturer_id) {
+	case LPDDR2_MANID_SAMSUNG:
+		return "Samsung";
+	case LPDDR2_MANID_QIMONDA:
+		return "Qimonda";
+	case LPDDR2_MANID_ELPIDA:
+		return "Elpida";
+	case LPDDR2_MANID_ETRON:
+		return "Etron";
+	case LPDDR2_MANID_NANYA:
+		return "Nanya";
+	case LPDDR2_MANID_HYNIX:
+		return "Hynix";
+	case LPDDR2_MANID_MOSEL:
+		return "Mosel";
+	case LPDDR2_MANID_WINBOND:
+		return "Winbond";
+	case LPDDR2_MANID_ESMT:
+		return "ESMT";
+	case LPDDR2_MANID_SPANSION:
+		return "Spansion";
+	case LPDDR2_MANID_SST:
+		return "SST";
+	case LPDDR2_MANID_ZMOS:
+		return "ZMOS";
+	case LPDDR2_MANID_INTEL:
+		return "Intel";
+	case LPDDR2_MANID_NUMONYX:
+		return "Numonyx";
+	case LPDDR2_MANID_MICRON:
+		return "Micron";
+	default:
+		break;
+	}
+
+	return "invalid";
+}
+EXPORT_SYMBOL_GPL(lpddr2_jedec_manufacturer);
diff --git a/drivers/memory/of_memory.c b/drivers/memory/of_memory.c
index d9f5437d3bce..60ecd52680a8 100644
--- a/drivers/memory/of_memory.c
+++ b/drivers/memory/of_memory.c
@@ -298,3 +298,91 @@ const struct lpddr3_timings
 	return NULL;
 }
 EXPORT_SYMBOL(of_lpddr3_get_ddr_timings);
+
+/**
+ * of_lpddr2_get_info() - extracts information about the lpddr2 chip.
+ * @np: Pointer to device tree node containing lpddr2 info
+ * @dev: Device requesting info
+ *
+ * Populates lpddr2_info structure by extracting data from device
+ * tree node. Returns pointer to populated structure. If error
+ * happened while populating, returns NULL. If property is missing
+ * in a device-tree, then the corresponding value is set to -ENOENT.
+ */
+const struct lpddr2_info
+*of_lpddr2_get_info(struct device_node *np, struct device *dev)
+{
+	struct lpddr2_info *ret_info, info = {};
+	struct property *prop;
+	const char *cp;
+	int err;
+
+	err = of_property_read_u32(np, "revision-id1", &info.revision_id1);
+	if (err)
+		info.revision_id1 = -ENOENT;
+
+	err = of_property_read_u32(np, "revision-id2", &info.revision_id2);
+	if (err)
+		info.revision_id2 = -ENOENT;
+
+	err = of_property_read_u32(np, "io-width", &info.io_width);
+	if (err)
+		return NULL;
+
+	info.io_width = 32 / info.io_width - 1;
+
+	err = of_property_read_u32(np, "density", &info.density);
+	if (err)
+		return NULL;
+
+	info.density = ffs(info.density) - 7;
+
+	if (of_device_is_compatible(np, "jedec,lpddr2-s4"))
+		info.arch_type = LPDDR2_TYPE_S4;
+	else if (of_device_is_compatible(np, "jedec,lpddr2-s2"))
+		info.arch_type = LPDDR2_TYPE_S2;
+	else if (of_device_is_compatible(np, "jedec,lpddr2-nvm"))
+		info.arch_type = LPDDR2_TYPE_NVM;
+	else
+		return NULL;
+
+	prop = of_find_property(np, "compatible", NULL);
+	for (cp = of_prop_next_string(prop, NULL); cp;
+	     cp = of_prop_next_string(prop, cp)) {
+
+#define OF_LPDDR2_COMPAT(compat, ID) \
+		/* legacy Elpida compatible starts with a capital letter */ \
+		if (!strncasecmp(cp, compat ",", strlen(compat ","))) { \
+			info.manufacturer_id = LPDDR2_MANID_##ID; \
+			break; \
+		}
+
+		OF_LPDDR2_COMPAT("samsung", SAMSUNG)
+		OF_LPDDR2_COMPAT("qimonda", QIMONDA)
+		OF_LPDDR2_COMPAT("etron", ETRON)
+		OF_LPDDR2_COMPAT("nanya", NANYA)
+		OF_LPDDR2_COMPAT("hynix", HYNIX)
+		OF_LPDDR2_COMPAT("mosel", MOSEL)
+		OF_LPDDR2_COMPAT("winbond", WINBOND)
+		OF_LPDDR2_COMPAT("esmt", ESMT)
+		OF_LPDDR2_COMPAT("spansion", SPANSION)
+		OF_LPDDR2_COMPAT("sst", SST)
+		OF_LPDDR2_COMPAT("zmos", ZMOS)
+		OF_LPDDR2_COMPAT("intel", INTEL)
+		OF_LPDDR2_COMPAT("numonyx", NUMONYX)
+		OF_LPDDR2_COMPAT("micron", MICRON)
+		OF_LPDDR2_COMPAT("elpida", ELPIDA)
+
+#undef OF_LPDDR2_COMPAT
+	}
+
+	if (!info.manufacturer_id)
+		info.manufacturer_id = -ENOENT;
+
+	ret_info = devm_kzalloc(dev, sizeof(*ret_info), GFP_KERNEL);
+	if (ret_info)
+		*ret_info = info;
+
+	return ret_info;
+}
+EXPORT_SYMBOL(of_lpddr2_get_info);
diff --git a/drivers/memory/of_memory.h b/drivers/memory/of_memory.h
index 4a99b232ab0a..1c4e47fede8a 100644
--- a/drivers/memory/of_memory.h
+++ b/drivers/memory/of_memory.h
@@ -20,6 +20,9 @@ const struct lpddr3_min_tck *of_lpddr3_get_min_tck(struct device_node *np,
 const struct lpddr3_timings *
 of_lpddr3_get_ddr_timings(struct device_node *np_ddr,
 			  struct device *dev, u32 device_type, u32 *nr_frequencies);
+
+const struct lpddr2_info *of_lpddr2_get_info(struct device_node *np,
+					     struct device *dev);
 #else
 static inline const struct lpddr2_min_tck
 	*of_get_min_tck(struct device_node *np, struct device *dev)
@@ -46,6 +49,12 @@ static inline const struct lpddr3_timings
 {
 	return NULL;
 }
+
+static inline const struct lpddr2_info
+	*of_lpddr2_get_info(struct device_node *np, struct device *dev)
+{
+	return NULL;
+}
 #endif /* CONFIG_OF && CONFIG_DDR */
 
 #endif /* __LINUX_MEMORY_OF_REG_ */
-- 
2.32.0


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

* [PATCH v4 7/7] memory: tegra20-emc: Support matching timings by LPDDR2 configuration
  2021-10-05 23:00 [PATCH v4 0/7] tegra20-emc: Identify memory chip by LPDDR configuration Dmitry Osipenko
                   ` (5 preceding siblings ...)
  2021-10-05 23:00 ` [PATCH v4 6/7] memory: Add LPDDR2 configuration helpers Dmitry Osipenko
@ 2021-10-05 23:00 ` Dmitry Osipenko
  6 siblings, 0 replies; 17+ messages in thread
From: Dmitry Osipenko @ 2021-10-05 23:00 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Krzysztof Kozlowski, Rob Herring
  Cc: devicetree, linux-kernel, linux-tegra

ASUS Transformer TF101 doesn't provide RAM code and in this case memory
timings should be selected based on identity information read out from
SDRAM chip. Support matching timings by LPDDR2 configuration.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/memory/tegra/Kconfig       |   1 +
 drivers/memory/tegra/tegra20-emc.c | 199 +++++++++++++++++++++++++++--
 2 files changed, 186 insertions(+), 14 deletions(-)

diff --git a/drivers/memory/tegra/Kconfig b/drivers/memory/tegra/Kconfig
index f9bae36c03a3..7951764b4efe 100644
--- a/drivers/memory/tegra/Kconfig
+++ b/drivers/memory/tegra/Kconfig
@@ -16,6 +16,7 @@ config TEGRA20_EMC
 	depends on ARCH_TEGRA_2x_SOC || COMPILE_TEST
 	select DEVFREQ_GOV_SIMPLE_ONDEMAND
 	select PM_DEVFREQ
+	select DDR
 	help
 	  This driver is for the External Memory Controller (EMC) found on
 	  Tegra20 chips. The EMC controls the external DRAM on the board.
diff --git a/drivers/memory/tegra/tegra20-emc.c b/drivers/memory/tegra/tegra20-emc.c
index c3462dbc8c22..77c5cd52d1a2 100644
--- a/drivers/memory/tegra/tegra20-emc.c
+++ b/drivers/memory/tegra/tegra20-emc.c
@@ -5,6 +5,7 @@
  * Author: Dmitry Osipenko <digetx@gmail.com>
  */
 
+#include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/clk/tegra.h>
 #include <linux/debugfs.h>
@@ -27,11 +28,15 @@
 #include <soc/tegra/common.h>
 #include <soc/tegra/fuse.h>
 
+#include "../jedec_ddr.h"
+#include "../of_memory.h"
+
 #include "mc.h"
 
 #define EMC_INTSTATUS				0x000
 #define EMC_INTMASK				0x004
 #define EMC_DBG					0x008
+#define EMC_ADR_CFG_0				0x010
 #define EMC_TIMING_CONTROL			0x028
 #define EMC_RC					0x02c
 #define EMC_RFC					0x030
@@ -68,6 +73,7 @@
 #define EMC_QUSE_EXTRA				0x0ac
 #define EMC_ODT_WRITE				0x0b0
 #define EMC_ODT_READ				0x0b4
+#define EMC_MRR					0x0ec
 #define EMC_FBIO_CFG5				0x104
 #define EMC_FBIO_CFG6				0x114
 #define EMC_STAT_CONTROL			0x160
@@ -94,6 +100,7 @@
 
 #define EMC_REFRESH_OVERFLOW_INT		BIT(3)
 #define EMC_CLKCHANGE_COMPLETE_INT		BIT(4)
+#define EMC_MRR_DIVLD_INT			BIT(5)
 
 #define EMC_DBG_READ_MUX_ASSEMBLY		BIT(0)
 #define EMC_DBG_WRITE_MUX_ACTIVE		BIT(1)
@@ -102,11 +109,25 @@
 #define EMC_DBG_CFG_PRIORITY			BIT(24)
 
 #define EMC_FBIO_CFG5_DRAM_WIDTH_X16		BIT(4)
+#define EMC_FBIO_CFG5_DRAM_TYPE			GENMASK(1, 0)
+
+#define EMC_MRR_DEV_SELECTN			GENMASK(31, 30)
+#define EMC_MRR_MRR_MA				GENMASK(23, 16)
+#define EMC_MRR_MRR_DATA			GENMASK(15, 0)
+
+#define EMC_ADR_CFG_0_EMEM_NUMDEV		GENMASK(25, 24)
 
 #define EMC_PWR_GATHER_CLEAR			(1 << 8)
 #define EMC_PWR_GATHER_DISABLE			(2 << 8)
 #define EMC_PWR_GATHER_ENABLE			(3 << 8)
 
+enum emc_dram_type {
+	DRAM_TYPE_RESERVED,
+	DRAM_TYPE_DDR1,
+	DRAM_TYPE_LPDDR2,
+	DRAM_TYPE_DDR2,
+};
+
 static const u16 emc_timing_registers[] = {
 	EMC_RC,
 	EMC_RFC,
@@ -201,6 +222,14 @@ struct tegra_emc {
 	struct mutex rate_lock;
 
 	struct devfreq_simple_ondemand_data ondemand_data;
+
+	/* memory chip identity information */
+	union lpddr2_basic_config4 basic_conf4;
+	unsigned int manufacturer_id;
+	unsigned int revision_id1;
+	unsigned int revision_id2;
+
+	bool mrr_error;
 };
 
 static irqreturn_t tegra_emc_isr(int irq, void *data)
@@ -397,15 +426,19 @@ static int tegra_emc_load_timings_from_dt(struct tegra_emc *emc,
 	if (!emc->timings)
 		return -ENOMEM;
 
-	emc->num_timings = child_count;
 	timing = emc->timings;
 
 	for_each_child_of_node(node, child) {
+		if (of_node_name_eq(child, "lpddr2"))
+			continue;
+
 		err = load_one_timing_from_dt(emc, timing++, child);
 		if (err) {
 			of_node_put(child);
 			return err;
 		}
+
+		emc->num_timings++;
 	}
 
 	sort(emc->timings, emc->num_timings, sizeof(*timing), cmp_timings,
@@ -422,12 +455,18 @@ static int tegra_emc_load_timings_from_dt(struct tegra_emc *emc,
 }
 
 static struct device_node *
-tegra_emc_find_node_by_ram_code(struct device *dev)
+tegra_emc_find_node_by_ram_code(struct tegra_emc *emc)
 {
+	struct device *dev = emc->dev;
 	struct device_node *np;
 	u32 value, ram_code;
 	int err;
 
+	if (emc->mrr_error) {
+		dev_warn(dev, "memory timings skipped due to MRR error\n");
+		return NULL;
+	}
+
 	if (of_get_child_count(dev->of_node) == 0) {
 		dev_info_once(dev, "device-tree doesn't have memory timings\n");
 		return NULL;
@@ -442,8 +481,49 @@ tegra_emc_find_node_by_ram_code(struct device *dev)
 	     np = of_find_node_by_name(np, "emc-tables")) {
 		err = of_property_read_u32(np, "nvidia,ram-code", &value);
 		if (err || value != ram_code) {
-			of_node_put(np);
-			continue;
+			struct device_node *lpddr2_np;
+			bool cfg_mismatches = false;
+
+			lpddr2_np = of_find_node_by_name(np, "lpddr2");
+			if (lpddr2_np) {
+				const struct lpddr2_info *info;
+
+				info = of_lpddr2_get_info(lpddr2_np, dev);
+				if (info) {
+					if (info->manufacturer_id >= 0 &&
+					    info->manufacturer_id != emc->manufacturer_id)
+						cfg_mismatches = true;
+
+					if (info->revision_id1 >= 0 &&
+					    info->revision_id1 != emc->revision_id1)
+						cfg_mismatches = true;
+
+					if (info->revision_id2 >= 0 &&
+					    info->revision_id2 != emc->revision_id2)
+						cfg_mismatches = true;
+
+					if (info->density != emc->basic_conf4.density)
+						cfg_mismatches = true;
+
+					if (info->io_width != emc->basic_conf4.io_width)
+						cfg_mismatches = true;
+
+					if (info->arch_type != emc->basic_conf4.arch_type)
+						cfg_mismatches = true;
+				} else {
+					dev_err(dev, "failed to parse %pOF\n", lpddr2_np);
+					cfg_mismatches = true;
+				}
+
+				of_node_put(lpddr2_np);
+			} else {
+				cfg_mismatches = true;
+			}
+
+			if (cfg_mismatches) {
+				of_node_put(np);
+				continue;
+			}
 		}
 
 		return np;
@@ -455,10 +535,72 @@ tegra_emc_find_node_by_ram_code(struct device *dev)
 	return NULL;
 }
 
+static int emc_read_lpddr_mode_register(struct tegra_emc *emc,
+					unsigned int emem_dev,
+					unsigned int register_addr,
+					unsigned int *register_data)
+{
+	u32 memory_dev = emem_dev + 1;
+	u32 val, mr_mask = 0xff;
+	int err;
+
+	/* clear data-valid interrupt status */
+	writel_relaxed(EMC_MRR_DIVLD_INT, emc->regs + EMC_INTSTATUS);
+
+	/* issue mode register read request */
+	val  = FIELD_PREP(EMC_MRR_DEV_SELECTN, memory_dev);
+	val |= FIELD_PREP(EMC_MRR_MRR_MA, register_addr);
+
+	writel_relaxed(val, emc->regs + EMC_MRR);
+
+	/* wait for the LPDDR2 data-valid interrupt */
+	err = readl_relaxed_poll_timeout_atomic(emc->regs + EMC_INTSTATUS, val,
+						val & EMC_MRR_DIVLD_INT,
+						1, 100);
+	if (err) {
+		dev_err(emc->dev, "mode register %u read failed: %d\n",
+			register_addr, err);
+		emc->mrr_error = true;
+		return err;
+	}
+
+	/* read out mode register data */
+	val = readl_relaxed(emc->regs + EMC_MRR);
+	*register_data = FIELD_GET(EMC_MRR_MRR_DATA, val) & mr_mask;
+
+	return 0;
+}
+
+static void emc_read_lpddr_sdram_info(struct tegra_emc *emc,
+				      unsigned int emem_dev,
+				      bool print_out)
+{
+	/* these registers are standard for all LPDDR JEDEC memory chips */
+	emc_read_lpddr_mode_register(emc, emem_dev, 5, &emc->manufacturer_id);
+	emc_read_lpddr_mode_register(emc, emem_dev, 6, &emc->revision_id1);
+	emc_read_lpddr_mode_register(emc, emem_dev, 7, &emc->revision_id2);
+	emc_read_lpddr_mode_register(emc, emem_dev, 8, &emc->basic_conf4.value);
+
+	if (!print_out)
+		return;
+
+	dev_info(emc->dev, "SDRAM[dev%u]: manufacturer: 0x%x (%s) rev1: 0x%x rev2: 0x%x prefetch: S%u density: %uMbit iowidth: %ubit\n",
+		 emem_dev, emc->manufacturer_id,
+		 lpddr2_jedec_manufacturer(emc->manufacturer_id),
+		 emc->revision_id1, emc->revision_id2,
+		 4 >> emc->basic_conf4.arch_type,
+		 64 << emc->basic_conf4.density,
+		 32 >> emc->basic_conf4.io_width);
+}
+
 static int emc_setup_hw(struct tegra_emc *emc)
 {
+	u32 emc_cfg, emc_dbg, emc_fbio, emc_adr_cfg;
 	u32 intmask = EMC_REFRESH_OVERFLOW_INT;
-	u32 emc_cfg, emc_dbg, emc_fbio;
+	static bool print_sdram_info_once;
+	enum emc_dram_type dram_type;
+	const char *dram_type_str;
+	unsigned int emem_numdev;
 
 	emc_cfg = readl_relaxed(emc->regs + EMC_CFG_2);
 
@@ -496,7 +638,36 @@ static int emc_setup_hw(struct tegra_emc *emc)
 	else
 		emc->dram_bus_width = 32;
 
-	dev_info_once(emc->dev, "%ubit DRAM bus\n", emc->dram_bus_width);
+	dram_type = FIELD_GET(EMC_FBIO_CFG5_DRAM_TYPE, emc_fbio);
+
+	switch (dram_type) {
+	case DRAM_TYPE_RESERVED:
+		dram_type_str = "INVALID";
+		break;
+	case DRAM_TYPE_DDR1:
+		dram_type_str = "DDR1";
+		break;
+	case DRAM_TYPE_LPDDR2:
+		dram_type_str = "LPDDR2";
+		break;
+	case DRAM_TYPE_DDR2:
+		dram_type_str = "DDR2";
+		break;
+	}
+
+	emc_adr_cfg = readl_relaxed(emc->regs + EMC_ADR_CFG_0);
+	emem_numdev = FIELD_GET(EMC_ADR_CFG_0_EMEM_NUMDEV, emc_adr_cfg) + 1;
+
+	dev_info_once(emc->dev, "%ubit DRAM bus, %u %s %s attached\n",
+		      emc->dram_bus_width, emem_numdev, dram_type_str,
+		      emem_numdev == 2 ? "devices" : "device");
+
+	if (dram_type == DRAM_TYPE_LPDDR2) {
+		while (emem_numdev--)
+			emc_read_lpddr_sdram_info(emc, emem_numdev,
+						  !print_sdram_info_once);
+		print_sdram_info_once = true;
+	}
 
 	return 0;
 }
@@ -1049,14 +1220,6 @@ static int tegra_emc_probe(struct platform_device *pdev)
 	emc->clk_nb.notifier_call = tegra_emc_clk_change_notify;
 	emc->dev = &pdev->dev;
 
-	np = tegra_emc_find_node_by_ram_code(&pdev->dev);
-	if (np) {
-		err = tegra_emc_load_timings_from_dt(emc, np);
-		of_node_put(np);
-		if (err)
-			return err;
-	}
-
 	emc->regs = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(emc->regs))
 		return PTR_ERR(emc->regs);
@@ -1065,6 +1228,14 @@ static int tegra_emc_probe(struct platform_device *pdev)
 	if (err)
 		return err;
 
+	np = tegra_emc_find_node_by_ram_code(emc);
+	if (np) {
+		err = tegra_emc_load_timings_from_dt(emc, np);
+		of_node_put(np);
+		if (err)
+			return err;
+	}
+
 	err = devm_request_irq(&pdev->dev, irq, tegra_emc_isr, 0,
 			       dev_name(&pdev->dev), emc);
 	if (err) {
-- 
2.32.0


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

* Re: [PATCH v4 2/7] dt-bindings: memory: lpddr2: Convert to schema
  2021-10-05 23:00 ` [PATCH v4 2/7] dt-bindings: memory: lpddr2: Convert to schema Dmitry Osipenko
@ 2021-10-06 10:57   ` Krzysztof Kozlowski
  2021-10-06 15:41     ` Dmitry Osipenko
  0 siblings, 1 reply; 17+ messages in thread
From: Krzysztof Kozlowski @ 2021-10-06 10:57 UTC (permalink / raw)
  To: Dmitry Osipenko, Thierry Reding, Jonathan Hunter, Rob Herring
  Cc: devicetree, linux-kernel, linux-tegra

On 06/10/2021 01:00, Dmitry Osipenko wrote:
> Convert LPDDR2 binding to schema. I removed obsolete ti,jedec-lpddr2-*
> compatibles since they were never used by device-trees and by the code.
> 
> Suggested-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  .../memory-controllers/ddr/jedec,lpddr2.yaml  | 195 ++++++++++++++++++
>  .../memory-controllers/ddr/lpddr2.txt         | 102 ---------
>  2 files changed, 195 insertions(+), 102 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
>  delete mode 100644 Documentation/devicetree/bindings/memory-controllers/ddr/lpddr2.txt
> 
> diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
> new file mode 100644
> index 000000000000..d99ccad54938
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
> @@ -0,0 +1,195 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/memory-controllers/ddr/jedec,lpddr2.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: LPDDR2 SDRAM compliant to JEDEC JESD209-2
> +
> +maintainers:
> +  - Krzysztof Kozlowski <krzk@kernel.org>

My Canonical address please, so:
Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>

> +
> +properties:
> +  compatible:
> +    oneOf:
> +      - items:
> +          - enum:
> +              - Elpida,ECB240ABACN
> +          - enum:
> +              - jedec,lpddr2-s4
> +      - items:
> +          - enum:
> +              - jedec,lpddr2-s2
> +      - items:
> +          - enum:
> +              - jedec,lpddr2-nvm
> +
> +  density:
> +    description: |
> +      Density in megabits of SDRAM chip. Obtained from device datasheet.

You need here a type/ref, so uint32.

> +    enum:
> +      - 64
> +      - 128
> +      - 256
> +      - 512
> +      - 1024
> +      - 2048
> +      - 4096
> +      - 8192
> +      - 16384
> +      - 32768
> +
> +  io-width:
> +    description: |
> +      IO bus width in bits of SDRAM chip. Obtained from device datasheet.

You need here a type/ref, so uint32.

> +    enum:
> +      - 32
> +      - 16
> +      - 8
> +
> +  tRRD-min-tck:
> +    maximum: 16

Here and further type is needed.


> +    description: |
> +      Active bank a to active bank b in terms of number of clock cycles.
> +      Obtained from device datasheet.
> +
> +  tWTR-min-tck:
> +    maximum: 16
> +    description: |
> +      Internal WRITE-to-READ command delay in terms of number of clock cycles.
> +      Obtained from device datasheet.
> +

Best regards,
Krzysztof

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

* Re: [PATCH v4 3/7] dt-bindings: memory: lpddr2: Add revision-id properties
  2021-10-05 23:00 ` [PATCH v4 3/7] dt-bindings: memory: lpddr2: Add revision-id properties Dmitry Osipenko
@ 2021-10-06 10:59   ` Krzysztof Kozlowski
  2021-10-06 15:47     ` Dmitry Osipenko
  0 siblings, 1 reply; 17+ messages in thread
From: Krzysztof Kozlowski @ 2021-10-06 10:59 UTC (permalink / raw)
  To: Dmitry Osipenko, Thierry Reding, Jonathan Hunter, Rob Herring
  Cc: devicetree, linux-kernel, linux-tegra

On 06/10/2021 01:00, Dmitry Osipenko wrote:
> Add optional revision-id standard LPDDR2 properties which will help to
> identify memory chip.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  .../memory-controllers/ddr/jedec,lpddr2.yaml         | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
> index d99ccad54938..01efb43c3425 100644
> --- a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
> +++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
> @@ -24,6 +24,16 @@ properties:
>            - enum:
>                - jedec,lpddr2-nvm
>  
> +  revision-id1:
> +    maximum: 255
> +    description: |
> +      Revision 1 value of SDRAM chip. Obtained from device datasheet.
> +

Also type/ref for uint32 needed.


Best regards,
Krzysztof

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

* Re: [PATCH v4 2/7] dt-bindings: memory: lpddr2: Convert to schema
  2021-10-06 10:57   ` Krzysztof Kozlowski
@ 2021-10-06 15:41     ` Dmitry Osipenko
  2021-10-06 15:44       ` Dmitry Osipenko
  2021-10-06 17:21       ` Krzysztof Kozlowski
  0 siblings, 2 replies; 17+ messages in thread
From: Dmitry Osipenko @ 2021-10-06 15:41 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Rob Herring
  Cc: devicetree, linux-kernel, linux-tegra

06.10.2021 13:57, Krzysztof Kozlowski пишет:
>> +  density:
>> +    description: |
>> +      Density in megabits of SDRAM chip. Obtained from device datasheet.
> You need here a type/ref, so uint32.
> 

The type is uint32 by default. I can add it, but it's not really necessary.

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

* Re: [PATCH v4 2/7] dt-bindings: memory: lpddr2: Convert to schema
  2021-10-06 15:41     ` Dmitry Osipenko
@ 2021-10-06 15:44       ` Dmitry Osipenko
  2021-10-06 17:23         ` Krzysztof Kozlowski
  2021-10-06 17:21       ` Krzysztof Kozlowski
  1 sibling, 1 reply; 17+ messages in thread
From: Dmitry Osipenko @ 2021-10-06 15:44 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Rob Herring
  Cc: devicetree, linux-kernel, linux-tegra

06.10.2021 18:41, Dmitry Osipenko пишет:
> 06.10.2021 13:57, Krzysztof Kozlowski пишет:
>>> +  density:
>>> +    description: |
>>> +      Density in megabits of SDRAM chip. Obtained from device datasheet.
>> You need here a type/ref, so uint32.
>>
> 
> The type is uint32 by default. I can add it, but it's not really necessary.
> 

You may grep bindings for 'enum: [' to see that nobody is specifying the
type.

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

* Re: [PATCH v4 3/7] dt-bindings: memory: lpddr2: Add revision-id properties
  2021-10-06 10:59   ` Krzysztof Kozlowski
@ 2021-10-06 15:47     ` Dmitry Osipenko
  2021-10-06 16:11       ` Dmitry Osipenko
  0 siblings, 1 reply; 17+ messages in thread
From: Dmitry Osipenko @ 2021-10-06 15:47 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Rob Herring
  Cc: devicetree, linux-kernel, linux-tegra

06.10.2021 13:59, Krzysztof Kozlowski пишет:
> On 06/10/2021 01:00, Dmitry Osipenko wrote:
>> Add optional revision-id standard LPDDR2 properties which will help to
>> identify memory chip.
>>
>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>> ---
>>  .../memory-controllers/ddr/jedec,lpddr2.yaml         | 12 ++++++++++++
>>  1 file changed, 12 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
>> index d99ccad54938..01efb43c3425 100644
>> --- a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
>> +++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
>> @@ -24,6 +24,16 @@ properties:
>>            - enum:
>>                - jedec,lpddr2-nvm
>>  
>> +  revision-id1:
>> +    maximum: 255
>> +    description: |
>> +      Revision 1 value of SDRAM chip. Obtained from device datasheet.
>> +
> 
> Also type/ref for uint32 needed.

Also unnecessary :) It's uint32 by default, inferred from the 'maximum'.

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

* Re: [PATCH v4 3/7] dt-bindings: memory: lpddr2: Add revision-id properties
  2021-10-06 15:47     ` Dmitry Osipenko
@ 2021-10-06 16:11       ` Dmitry Osipenko
  0 siblings, 0 replies; 17+ messages in thread
From: Dmitry Osipenko @ 2021-10-06 16:11 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Rob Herring
  Cc: devicetree, linux-kernel, linux-tegra

06.10.2021 18:47, Dmitry Osipenko пишет:
> 06.10.2021 13:59, Krzysztof Kozlowski пишет:
>> On 06/10/2021 01:00, Dmitry Osipenko wrote:
>>> Add optional revision-id standard LPDDR2 properties which will help to
>>> identify memory chip.
>>>
>>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>>> ---
>>>  .../memory-controllers/ddr/jedec,lpddr2.yaml         | 12 ++++++++++++
>>>  1 file changed, 12 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
>>> index d99ccad54938..01efb43c3425 100644
>>> --- a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
>>> +++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
>>> @@ -24,6 +24,16 @@ properties:
>>>            - enum:
>>>                - jedec,lpddr2-nvm
>>>  
>>> +  revision-id1:
>>> +    maximum: 255
>>> +    description: |
>>> +      Revision 1 value of SDRAM chip. Obtained from device datasheet.
>>> +
>>
>> Also type/ref for uint32 needed.
> 
> Also unnecessary :) It's uint32 by default, inferred from the 'maximum'.
> 

Please grep for 'maximum: ' to see that other bindings don't specify the
type.

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

* Re: [PATCH v4 2/7] dt-bindings: memory: lpddr2: Convert to schema
  2021-10-06 15:41     ` Dmitry Osipenko
  2021-10-06 15:44       ` Dmitry Osipenko
@ 2021-10-06 17:21       ` Krzysztof Kozlowski
  1 sibling, 0 replies; 17+ messages in thread
From: Krzysztof Kozlowski @ 2021-10-06 17:21 UTC (permalink / raw)
  To: Dmitry Osipenko, Thierry Reding, Jonathan Hunter, Rob Herring
  Cc: devicetree, linux-kernel, linux-tegra

On 06/10/2021 17:41, Dmitry Osipenko wrote:
> 06.10.2021 13:57, Krzysztof Kozlowski пишет:
>>> +  density:
>>> +    description: |
>>> +      Density in megabits of SDRAM chip. Obtained from device datasheet.
>> You need here a type/ref, so uint32.
>>
> 
> The type is uint32 by default. I can add it, but it's not really necessary.

Hmmm, maybe I missed some background here. Who sets uint32 as default?
The schema does not define "density" so this is more like a vendor-type
property which required therefore a type.

Also Rob's pointed this to my patch here around "op_mode":
https://lore.kernel.org/linux-samsung-soc/cdcd4eda-a7a9-2aa2-1316-e7184ff30bf3@canonical.com/T/#m17adea693a9cbcca75b0ba6f9d878f5fd1bf5d14

Best regards,
Krzysztof

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

* Re: [PATCH v4 2/7] dt-bindings: memory: lpddr2: Convert to schema
  2021-10-06 15:44       ` Dmitry Osipenko
@ 2021-10-06 17:23         ` Krzysztof Kozlowski
  2021-10-06 17:31           ` Dmitry Osipenko
  0 siblings, 1 reply; 17+ messages in thread
From: Krzysztof Kozlowski @ 2021-10-06 17:23 UTC (permalink / raw)
  To: Dmitry Osipenko, Thierry Reding, Jonathan Hunter, Rob Herring
  Cc: devicetree, linux-kernel, linux-tegra

On 06/10/2021 17:44, Dmitry Osipenko wrote:
> 06.10.2021 18:41, Dmitry Osipenko пишет:
>> 06.10.2021 13:57, Krzysztof Kozlowski пишет:
>>>> +  density:
>>>> +    description: |
>>>> +      Density in megabits of SDRAM chip. Obtained from device datasheet.
>>> You need here a type/ref, so uint32.
>>>
>>
>> The type is uint32 by default. I can add it, but it's not really necessary.
>>
> 
> You may grep bindings for 'enum: [' to see that nobody is specifying the
> type.
> 

Just because everyone makes a mistake, is not a proof it should be done
like that. Please see example schema and vendor,int-property.

AFAIR, only properties defined by schema (directly or by unit suffix,
e.g. microvolt) do not need types.

Best regards,
Krzysztof

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

* Re: [PATCH v4 2/7] dt-bindings: memory: lpddr2: Convert to schema
  2021-10-06 17:23         ` Krzysztof Kozlowski
@ 2021-10-06 17:31           ` Dmitry Osipenko
  0 siblings, 0 replies; 17+ messages in thread
From: Dmitry Osipenko @ 2021-10-06 17:31 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Thierry Reding, Jonathan Hunter, Rob Herring
  Cc: devicetree, linux-kernel, linux-tegra

06.10.2021 20:23, Krzysztof Kozlowski пишет:
> On 06/10/2021 17:44, Dmitry Osipenko wrote:
>> 06.10.2021 18:41, Dmitry Osipenko пишет:
>>> 06.10.2021 13:57, Krzysztof Kozlowski пишет:
>>>>> +  density:
>>>>> +    description: |
>>>>> +      Density in megabits of SDRAM chip. Obtained from device datasheet.
>>>> You need here a type/ref, so uint32.
>>>>
>>>
>>> The type is uint32 by default. I can add it, but it's not really necessary.
>>>
>>
>> You may grep bindings for 'enum: [' to see that nobody is specifying the
>> type.
>>
> 
> Just because everyone makes a mistake, is not a proof it should be done
> like that. Please see example schema and vendor,int-property.
> 
> AFAIR, only properties defined by schema (directly or by unit suffix,
> e.g. microvolt) do not need types.

I'm not DT expert, but dt_binding_check says that binding is valid, even
with W=1. Meanwhile negative values are wrong. All integers are u32 by
default for DTB.

Alright, I'll just add the type since it won't hurt anyways.

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

end of thread, other threads:[~2021-10-06 17:32 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-05 23:00 [PATCH v4 0/7] tegra20-emc: Identify memory chip by LPDDR configuration Dmitry Osipenko
2021-10-05 23:00 ` [PATCH v4 1/7] dt-bindings: Relocate DDR bindings Dmitry Osipenko
2021-10-05 23:00 ` [PATCH v4 2/7] dt-bindings: memory: lpddr2: Convert to schema Dmitry Osipenko
2021-10-06 10:57   ` Krzysztof Kozlowski
2021-10-06 15:41     ` Dmitry Osipenko
2021-10-06 15:44       ` Dmitry Osipenko
2021-10-06 17:23         ` Krzysztof Kozlowski
2021-10-06 17:31           ` Dmitry Osipenko
2021-10-06 17:21       ` Krzysztof Kozlowski
2021-10-05 23:00 ` [PATCH v4 3/7] dt-bindings: memory: lpddr2: Add revision-id properties Dmitry Osipenko
2021-10-06 10:59   ` Krzysztof Kozlowski
2021-10-06 15:47     ` Dmitry Osipenko
2021-10-06 16:11       ` Dmitry Osipenko
2021-10-05 23:00 ` [PATCH v4 4/7] dt-bindings: memory: lpddr2: Document Elpida B8132B2PB-6D-F Dmitry Osipenko
2021-10-05 23:00 ` [PATCH v4 5/7] dt-bindings: memory: tegra20: emc: Document new LPDDR2 sub-node Dmitry Osipenko
2021-10-05 23:00 ` [PATCH v4 6/7] memory: Add LPDDR2 configuration helpers Dmitry Osipenko
2021-10-05 23:00 ` [PATCH v4 7/7] memory: tegra20-emc: Support matching timings by LPDDR2 configuration Dmitry Osipenko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.