linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs
@ 2019-11-18 20:02 Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 01/29] dt-bindings: memory: tegra20: mc: Document new interconnect property Dmitry Osipenko
                   ` (29 more replies)
  0 siblings, 30 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Hello,

This series brings initial support for memory interconnect to Tegra20,
Terga30 and Tegra124 SoCs. The interconnect provides are quite generic
and should be suitable for all Tegra SoCs, but currently upstream kernel
has EMC/MC drivers only for those three generations of Tegra SoCs.

For the start only display controllers are getting interconnect API
support, others could be supported later on. The display controllers
have the biggest demand for interconnect API right now because dynamic
memory frequency scaling can't be done safely without taking into account
bandwidth requirement from the displays.

Dmitry Osipenko (29):
  dt-bindings: memory: tegra20: mc: Document new interconnect property
  dt-bindings: memory: tegra20: emc: Document new interconnect property
  dt-bindings: memory: tegra30: mc: Document new interconnect property
  dt-bindings: memory: tegra30: emc: Document new interconnect property
  dt-bindings: memory: tegra124: mc: Document new interconnect property
  dt-bindings: memory: tegra124: emc: Document new interconnect property
  dt-bindings: host1x: Document new interconnect properties
  dt-bindings: interconnect: tegra: Add initial IDs
  ARM: tegra: Add interconnect properties to Tegra20 device-tree
  ARM: tegra: Add interconnect properties to Tegra30 device-tree
  ARM: tegra: Add interconnect properties to Tegra124 device-tree
  interconnect: Add memory interconnection providers for NVIDIA Tegra
    SoCs
  memory: tegra: Register as interconnect provider
  memory: tegra: Add interconnect nodes for Terga20 display controllers
  memory: tegra: Add interconnect nodes for Terga30 display controllers
  memory: tegra: Add interconnect nodes for Terga124 display controllers
  memory: tegra20-emc: Use devm_platform_ioremap_resource
  memory: tegra20-emc: Continue probing if timings/IRQ are missing in
    device-tree
  memory: tegra20-emc: Register as interconnect provider
  memory: tegra30-emc: Continue probing if timings are missing in
    device-tree
  memory: tegra30-emc: Register as interconnect provider
  memory: tegra124-emc: Use devm_platform_ioremap_resource
  memory: tegra124-emc: Register as interconnect provider
  drm/tegra: dc: Use devm_platform_ioremap_resource
  drm/tegra: dc: Release PM and RGB output when client's registration
    fails
  drm/tegra: dc: Support memory bandwidth management
  ARM: tegra: Enable interconnect API in tegra_defconfig
  ARM: multi_v7_defconfig: Enable NVIDIA Tegra interconnect providers
  MAINTAINERS: Add maintainers for NVIDIA Tegra interconnect drivers

 .../display/tegra/nvidia,tegra20-host1x.txt   |  67 +++++
 .../nvidia,tegra124-emc.txt                   |   3 +
 .../nvidia,tegra124-mc.yaml                   |   5 +
 .../memory-controllers/nvidia,tegra20-emc.txt |   4 +
 .../memory-controllers/nvidia,tegra20-mc.txt  |   4 +
 .../nvidia,tegra30-emc.yaml                   |   6 +
 .../memory-controllers/nvidia,tegra30-mc.yaml |   5 +
 MAINTAINERS                                   |   9 +
 arch/arm/boot/dts/tegra124.dtsi               |  10 +
 arch/arm/boot/dts/tegra20.dtsi                |  11 +-
 arch/arm/boot/dts/tegra30.dtsi                |  12 +-
 arch/arm/configs/multi_v7_defconfig           |   2 +
 arch/arm/configs/tegra_defconfig              |   2 +
 drivers/gpu/drm/tegra/dc.c                    | 252 +++++++++++++++++-
 drivers/gpu/drm/tegra/dc.h                    |   8 +
 drivers/gpu/drm/tegra/drm.c                   |  18 ++
 drivers/gpu/drm/tegra/plane.c                 |   1 +
 drivers/gpu/drm/tegra/plane.h                 |   4 +-
 drivers/interconnect/Kconfig                  |   1 +
 drivers/interconnect/Makefile                 |   1 +
 drivers/interconnect/tegra/Kconfig            |   6 +
 drivers/interconnect/tegra/Makefile           |   4 +
 drivers/interconnect/tegra/tegra-icc-emc.c    | 138 ++++++++++
 drivers/interconnect/tegra/tegra-icc-mc.c     | 130 +++++++++
 drivers/memory/tegra/mc.c                     |   4 +
 drivers/memory/tegra/tegra124-emc.c           |  28 +-
 drivers/memory/tegra/tegra124.c               |  16 ++
 drivers/memory/tegra/tegra20-emc.c            |  91 ++++---
 drivers/memory/tegra/tegra20.c                |  14 +
 drivers/memory/tegra/tegra30-emc.c            |  34 ++-
 drivers/memory/tegra/tegra30.c                |  14 +
 include/dt-bindings/interconnect/tegra-icc.h  |  11 +
 include/soc/tegra/mc.h                        |  26 ++
 33 files changed, 883 insertions(+), 58 deletions(-)
 create mode 100644 drivers/interconnect/tegra/Kconfig
 create mode 100644 drivers/interconnect/tegra/Makefile
 create mode 100644 drivers/interconnect/tegra/tegra-icc-emc.c
 create mode 100644 drivers/interconnect/tegra/tegra-icc-mc.c
 create mode 100644 include/dt-bindings/interconnect/tegra-icc.h

-- 
2.23.0


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

* [PATCH v1 01/29] dt-bindings: memory: tegra20: mc: Document new interconnect property
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 02/29] dt-bindings: memory: tegra20: emc: " Dmitry Osipenko
                   ` (28 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Memory controller is interconnected with memory clients and with the
external memory controller. Document new interconnect property which
designates memory controller as interconnect provider.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../bindings/memory-controllers/nvidia,tegra20-mc.txt         | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-mc.txt b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-mc.txt
index e55328237df4..b0765d5cb124 100644
--- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-mc.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-mc.txt
@@ -16,6 +16,9 @@ Required properties:
   IOMMU specifier needed to encode an address. GART supports only a single
   address space that is shared by all devices, therefore no additional
   information needed for the address encoding.
+- #interconnect-cells : Should be 1. This cell represents memory client
+  interconnect. The assignments may be found in header file
+  <dt-bindings/interconnect/tegra-icc.h>.
 
 Example:
 	mc: memory-controller@7000f000 {
@@ -27,6 +30,7 @@ Example:
 		interrupts = <GIC_SPI 77 0x04>;
 		#reset-cells = <1>;
 		#iommu-cells = <0>;
+		#interconnect-cells = <1>;
 	};
 
 	video-codec@6001a000 {
-- 
2.23.0


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

* [PATCH v1 02/29] dt-bindings: memory: tegra20: emc: Document new interconnect property
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 01/29] dt-bindings: memory: tegra20: mc: Document new interconnect property Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-19  6:21   ` Thierry Reding
  2019-11-18 20:02 ` [PATCH v1 03/29] dt-bindings: memory: tegra30: mc: " Dmitry Osipenko
                   ` (27 subsequent siblings)
  29 siblings, 1 reply; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

External memory controller is interconnected with memory controller and
with external memory. Document new interconnect property which designates
external memory controller as interconnect provider.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../bindings/memory-controllers/nvidia,tegra20-emc.txt        | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.txt b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.txt
index add95367640b..7566d883f921 100644
--- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.txt
@@ -12,6 +12,9 @@ Properties:
   irrespective of ram-code configuration.
 - interrupts : Should contain EMC General interrupt.
 - clocks : Should contain EMC clock.
+- #interconnect-cells : Should be 1. This cell represents external memory
+  interconnect. The assignments may be found in header file
+  <dt-bindings/interconnect/tegra-icc.h>.
 
 Child device nodes describe the memory settings for different configurations and clock rates.
 
@@ -20,6 +23,7 @@ Example:
 	memory-controller@7000f400 {
 		#address-cells = < 1 >;
 		#size-cells = < 0 >;
+		#interconnect-cells = < 1 >;
 		compatible = "nvidia,tegra20-emc";
 		reg = <0x7000f4000 0x200>;
 		interrupts = <0 78 0x04>;
-- 
2.23.0


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

* [PATCH v1 03/29] dt-bindings: memory: tegra30: mc: Document new interconnect property
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 01/29] dt-bindings: memory: tegra20: mc: Document new interconnect property Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 02/29] dt-bindings: memory: tegra20: emc: " Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 04/29] dt-bindings: memory: tegra30: emc: " Dmitry Osipenko
                   ` (26 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Memory controller is interconnected with memory clients and with the
external memory controller. Document new interconnect property which
designates memory controller as interconnect provider.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../bindings/memory-controllers/nvidia,tegra30-mc.yaml       | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-mc.yaml b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-mc.yaml
index 84fd57bcf0dc..5436e6d420bc 100644
--- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-mc.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-mc.yaml
@@ -57,6 +57,9 @@ properties:
   "#iommu-cells":
     const: 1
 
+  "#interconnect-cells":
+    const: 1
+
 patternProperties:
   "^emc-timings-[0-9]+$":
     type: object
@@ -120,6 +123,7 @@ required:
   - clock-names
   - "#reset-cells"
   - "#iommu-cells"
+  - "#interconnect-cells"
 
 additionalProperties: false
 
@@ -135,6 +139,7 @@ examples:
 
         #iommu-cells = <1>;
         #reset-cells = <1>;
+        #interconnect-cells = <1>;
 
         emc-timings-1 {
             nvidia,ram-code = <1>;
-- 
2.23.0


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

* [PATCH v1 04/29] dt-bindings: memory: tegra30: emc: Document new interconnect property
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (2 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 03/29] dt-bindings: memory: tegra30: mc: " Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 05/29] dt-bindings: memory: tegra124: mc: " Dmitry Osipenko
                   ` (25 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

External memory controller is interconnected with memory controller and
with external memory. Document new interconnect property which designates
external memory controller as interconnect provider.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../bindings/memory-controllers/nvidia,tegra30-emc.yaml     | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-emc.yaml b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-emc.yaml
index 7fe0ca14e324..ecdffbe691ce 100644
--- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-emc.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-emc.yaml
@@ -31,6 +31,9 @@ properties:
   interrupts:
     maxItems: 1
 
+  "#interconnect-cells":
+    const: 1
+
   nvidia,memory-controller:
     $ref: /schemas/types.yaml#/definitions/phandle
     description:
@@ -214,6 +217,7 @@ required:
   - interrupts
   - clocks
   - nvidia,memory-controller
+  - "#interconnect-cells"
 
 additionalProperties: false
 
@@ -227,6 +231,8 @@ examples:
 
         nvidia,memory-controller = <&mc>;
 
+        #interconnect-cells = <1>;
+
         emc-timings-1 {
             nvidia,ram-code = <1>;
 
-- 
2.23.0


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

* [PATCH v1 05/29] dt-bindings: memory: tegra124: mc: Document new interconnect property
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (3 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 04/29] dt-bindings: memory: tegra30: emc: " Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 06/29] dt-bindings: memory: tegra124: emc: " Dmitry Osipenko
                   ` (24 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Memory controller is interconnected with memory clients and with the
external memory controller. Document new interconnect property which
designates memory controller as interconnect provider.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../bindings/memory-controllers/nvidia,tegra124-mc.yaml      | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-mc.yaml b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-mc.yaml
index 30d9fb193d7f..b3aa3e6b7006 100644
--- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-mc.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-mc.yaml
@@ -40,6 +40,9 @@ properties:
   "#iommu-cells":
     const: 1
 
+  "#interconnect-cells":
+    const: 1
+
 patternProperties:
   "^emc-timings-[0-9]+$":
     type: object
@@ -104,6 +107,7 @@ required:
   - clock-names
   - "#reset-cells"
   - "#iommu-cells"
+  - "#interconnect-cells"
 
 additionalProperties: false
 
@@ -119,6 +123,7 @@ examples:
 
         #iommu-cells = <1>;
         #reset-cells = <1>;
+        #interconnect-cells = <1>;
 
         emc-timings-3 {
             nvidia,ram-code = <3>;
-- 
2.23.0


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

* [PATCH v1 06/29] dt-bindings: memory: tegra124: emc: Document new interconnect property
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (4 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 05/29] dt-bindings: memory: tegra124: mc: " Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 07/29] dt-bindings: host1x: Document new interconnect properties Dmitry Osipenko
                   ` (23 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

External memory controller is interconnected with memory controller and
with external memory. Document new interconnect property which designates
external memory controller as interconnect provider.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../bindings/memory-controllers/nvidia,tegra124-emc.txt        | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-emc.txt b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-emc.txt
index ba0bc3f12419..ff48b46604e6 100644
--- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-emc.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-emc.txt
@@ -5,6 +5,7 @@ Required properties :
 - compatible : Should be "nvidia,tegra124-emc".
 - reg : physical base address and length of the controller's registers.
 - nvidia,memory-controller : phandle of the MC driver.
+- #interconnect-cells : Should be 1.
 
 The node should contain a "emc-timings" subnode for each supported RAM type
 (see field RAM_CODE in register PMC_STRAPPING_OPT_A), with its unit address
@@ -195,6 +196,8 @@ Example SoC include file:
 		reg = <0x0 0x7001b000 0x0 0x1000>;
 
 		nvidia,memory-controller = <&mc>;
+
+		#interconnect-cells = <1>;
 	};
 };
 
-- 
2.23.0


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

* [PATCH v1 07/29] dt-bindings: host1x: Document new interconnect properties
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (5 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 06/29] dt-bindings: memory: tegra124: emc: " Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 08/29] dt-bindings: interconnect: tegra: Add initial IDs Dmitry Osipenko
                   ` (22 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Host1x clients are interconnected with memory controller through Graphics
HOST bus, these clients will issue memory bandwidth requests to the memory
controller that will adapt arbitration configuration in order to satisfy
clients and then propagate the aggregated bandwidth request to external
memory controller. The new interconnect properties are optional, thus
backwards compatibility is preserved with older device-trees.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 .../display/tegra/nvidia,tegra20-host1x.txt   | 67 +++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
index 9999255ac5b6..2a1fc1a194d2 100644
--- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
+++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.txt
@@ -20,6 +20,11 @@ Required properties:
 - reset-names: Must include the following entries:
   - host1x
 
+Each host1x client module having to perform DMA through the Memory Controller
+should have the interconnect endpoints set to the Memory Client and External
+Memory respectively, interconnect name must be set to "dma-mem".
+The interconnect property is optional.
+
 The host1x top-level node defines a number of children, each representing one
 of the following host1x client modules:
 
@@ -36,6 +41,11 @@ of the following host1x client modules:
   - reset-names: Must include the following entries:
     - mpe
 
+  Optional properties:
+  - interconnects: Must contain entry for the memory interconnect.
+  - interconnect-names: Must include the following entries:
+    - dma-mem
+
 - vi: video input
 
   Required properties:
@@ -49,6 +59,11 @@ of the following host1x client modules:
   - reset-names: Must include the following entries:
     - vi
 
+  Optional properties:
+  - interconnects: Must contain entry for the memory interconnect.
+  - interconnect-names: Must include the following entries:
+    - dma-mem
+
 - epp: encoder pre-processor
 
   Required properties:
@@ -62,6 +77,11 @@ of the following host1x client modules:
   - reset-names: Must include the following entries:
     - epp
 
+  Optional properties:
+  - interconnects: Must contain entry for the memory interconnect.
+  - interconnect-names: Must include the following entries:
+    - dma-mem
+
 - isp: image signal processor
 
   Required properties:
@@ -75,6 +95,11 @@ of the following host1x client modules:
   - reset-names: Must include the following entries:
     - isp
 
+  Optional properties:
+  - interconnects: Must contain entry for the memory interconnect.
+  - interconnect-names: Must include the following entries:
+    - dma-mem
+
 - gr2d: 2D graphics engine
 
   Required properties:
@@ -88,6 +113,11 @@ of the following host1x client modules:
   - reset-names: Must include the following entries:
     - 2d
 
+  Optional properties:
+  - interconnects: Must contain entry for the memory interconnect.
+  - interconnect-names: Must include the following entries:
+    - dma-mem
+
 - gr3d: 3D graphics engine
 
   Required properties:
@@ -106,6 +136,11 @@ of the following host1x client modules:
     - 3d
     - 3d2 (Only required on SoCs with two 3D clocks)
 
+  Optional properties:
+  - interconnects: Must contain entry for the memory interconnect.
+  - interconnect-names: Must include the following entries:
+    - dma-mem
+
 - dc: display controller
 
   Required properties:
@@ -133,6 +168,9 @@ of the following host1x client modules:
   - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
   - nvidia,edid: supplies a binary EDID blob
   - nvidia,panel: phandle of a display panel
+  - interconnects: Must contain entry for the memory interconnect.
+  - interconnect-names: Must include the following entries:
+    - dma-mem
 
 - hdmi: High Definition Multimedia Interface
 
@@ -281,6 +319,11 @@ of the following host1x client modules:
   - reset-names: Must include the following entries:
     - vic
 
+  Optional properties:
+  - interconnects: Must contain entry for the memory interconnect.
+  - interconnect-names: Must include the following entries:
+    - dma-mem
+
 Example:
 
 / {
@@ -307,6 +350,9 @@ Example:
 			clocks = <&tegra_car TEGRA20_CLK_MPE>;
 			resets = <&tegra_car 60>;
 			reset-names = "mpe";
+
+			interconnects = <&mc TEGRA_ICC_MC_MPE &emc TEGRA_ICC_EMEM>;
+			interconnect-names = "dma-mem";
 		};
 
 		vi {
@@ -316,6 +362,9 @@ Example:
 			clocks = <&tegra_car TEGRA20_CLK_VI>;
 			resets = <&tegra_car 100>;
 			reset-names = "vi";
+
+			interconnects = <&mc TEGRA_ICC_MC_VI &emc TEGRA_ICC_EMEM>;
+			interconnect-names = "dma-mem";
 		};
 
 		epp {
@@ -325,6 +374,9 @@ Example:
 			clocks = <&tegra_car TEGRA20_CLK_EPP>;
 			resets = <&tegra_car 19>;
 			reset-names = "epp";
+
+			interconnects = <&mc TEGRA_ICC_MC_EPP &emc TEGRA_ICC_EMEM>;
+			interconnect-names = "dma-mem";
 		};
 
 		isp {
@@ -334,6 +386,9 @@ Example:
 			clocks = <&tegra_car TEGRA20_CLK_ISP>;
 			resets = <&tegra_car 23>;
 			reset-names = "isp";
+
+			interconnects = <&mc TEGRA_ICC_MC_ISP &emc TEGRA_ICC_EMEM>;
+			interconnect-names = "dma-mem";
 		};
 
 		gr2d {
@@ -343,6 +398,9 @@ Example:
 			clocks = <&tegra_car TEGRA20_CLK_GR2D>;
 			resets = <&tegra_car 21>;
 			reset-names = "2d";
+
+			interconnects = <&mc TEGRA_ICC_MC_2D &emc TEGRA_ICC_EMEM>;
+			interconnect-names = "dma-mem";
 		};
 
 		gr3d {
@@ -351,6 +409,9 @@ Example:
 			clocks = <&tegra_car TEGRA20_CLK_GR3D>;
 			resets = <&tegra_car 24>;
 			reset-names = "3d";
+
+			interconnects = <&mc TEGRA_ICC_MC_3D &emc TEGRA_ICC_EMEM>;
+			interconnect-names = "dma-mem";
 		};
 
 		dc@54200000 {
@@ -363,6 +424,9 @@ Example:
 			resets = <&tegra_car 27>;
 			reset-names = "dc";
 
+			interconnects = <&mc TEGRA_ICC_MC_DC &emc TEGRA_ICC_EMEM>;
+			interconnect-names = "dma-mem";
+
 			rgb {
 				status = "disabled";
 			};
@@ -378,6 +442,9 @@ Example:
 			resets = <&tegra_car 26>;
 			reset-names = "dc";
 
+			interconnects = <&mc TEGRA_ICC_MC_DCB &emc TEGRA_ICC_EMEM>;
+			interconnect-names = "dma-mem";
+
 			rgb {
 				status = "disabled";
 			};
-- 
2.23.0


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

* [PATCH v1 08/29] dt-bindings: interconnect: tegra: Add initial IDs
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (6 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 07/29] dt-bindings: host1x: Document new interconnect properties Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-19  6:25   ` Thierry Reding
  2019-11-18 20:02 ` [PATCH v1 09/29] ARM: tegra: Add interconnect properties to Tegra20 device-tree Dmitry Osipenko
                   ` (21 subsequent siblings)
  29 siblings, 1 reply; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Define interconnect IDs for memory controller (MC), external memory
controller (EMC), external memory (EMEM) and memory clients of display
controllers (DC).

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 include/dt-bindings/interconnect/tegra-icc.h | 11 +++++++++++
 1 file changed, 11 insertions(+)
 create mode 100644 include/dt-bindings/interconnect/tegra-icc.h

diff --git a/include/dt-bindings/interconnect/tegra-icc.h b/include/dt-bindings/interconnect/tegra-icc.h
new file mode 100644
index 000000000000..e6b6a819434a
--- /dev/null
+++ b/include/dt-bindings/interconnect/tegra-icc.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef DT_BINDINGS_ICC_TEGRA_H
+#define DT_BINDINGS_ICC_TEGRA_H
+
+#define TEGRA_ICC_EMC			0
+#define TEGRA_ICC_EMEM			1
+#define TEGRA_ICC_MC			2
+#define TEGRA_ICC_MC_DC			3
+#define TEGRA_ICC_MC_DCB		4
+
+#endif
-- 
2.23.0


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

* [PATCH v1 09/29] ARM: tegra: Add interconnect properties to Tegra20 device-tree
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (7 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 08/29] dt-bindings: interconnect: tegra: Add initial IDs Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 10/29] ARM: tegra: Add interconnect properties to Tegra30 device-tree Dmitry Osipenko
                   ` (20 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Add interconnect properties to the memory controller, external memory
controller and the display controller nodes to describe interconnection
of these nodes.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/boot/dts/tegra20.dtsi | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 9c58e7fcf5c0..2aa10a34516b 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -3,6 +3,7 @@
 #include <dt-bindings/gpio/tegra-gpio.h>
 #include <dt-bindings/memory/tegra20-mc.h>
 #include <dt-bindings/pinctrl/pinctrl-tegra.h>
+#include <dt-bindings/interconnect/tegra-icc.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
 / {
@@ -108,6 +109,9 @@
 
 			nvidia,head = <0>;
 
+			interconnects = <&mc TEGRA_ICC_MC_DC &emc TEGRA_ICC_EMEM>;
+			interconnect-names = "dma-mem";
+
 			rgb {
 				status = "disabled";
 			};
@@ -125,6 +129,9 @@
 
 			nvidia,head = <1>;
 
+			interconnects = <&mc TEGRA_ICC_MC_DCB &emc TEGRA_ICC_EMEM>;
+			interconnect-names = "dma-mem";
+
 			rgb {
 				status = "disabled";
 			};
@@ -624,15 +631,17 @@
 		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
 		#reset-cells = <1>;
 		#iommu-cells = <0>;
+		#interconnect-cells = <1>;
 	};
 
-	memory-controller@7000f400 {
+	emc: memory-controller@7000f400 {
 		compatible = "nvidia,tegra20-emc";
 		reg = <0x7000f400 0x200>;
 		interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&tegra_car TEGRA20_CLK_EMC>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		#interconnect-cells = <1>;
 	};
 
 	fuse@7000f800 {
-- 
2.23.0


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

* [PATCH v1 10/29] ARM: tegra: Add interconnect properties to Tegra30 device-tree
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (8 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 09/29] ARM: tegra: Add interconnect properties to Tegra20 device-tree Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 11/29] ARM: tegra: Add interconnect properties to Tegra124 device-tree Dmitry Osipenko
                   ` (19 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Add interconnect properties to the memory controller, external memory
controller and the display controller nodes to describe interconnection
of these nodes.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/boot/dts/tegra30.dtsi | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index 55ae050042ce..69a239f1a823 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -3,6 +3,7 @@
 #include <dt-bindings/gpio/tegra-gpio.h>
 #include <dt-bindings/memory/tegra30-mc.h>
 #include <dt-bindings/pinctrl/pinctrl-tegra.h>
+#include <dt-bindings/interconnect/tegra-icc.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
 / {
@@ -207,6 +208,9 @@
 
 			nvidia,head = <0>;
 
+			interconnects = <&mc TEGRA_ICC_MC_DC &emc TEGRA_ICC_EMEM>;
+			interconnect-names = "dma-mem";
+
 			rgb {
 				status = "disabled";
 			};
@@ -226,6 +230,9 @@
 
 			nvidia,head = <1>;
 
+			interconnects = <&mc TEGRA_ICC_MC_DCB &emc TEGRA_ICC_EMEM>;
+			interconnect-names = "dma-mem";
+
 			rgb {
 				status = "disabled";
 			};
@@ -731,15 +738,18 @@
 
 		#iommu-cells = <1>;
 		#reset-cells = <1>;
+		#interconnect-cells = <1>;
 	};
 
-	memory-controller@7000f400 {
+	emc: memory-controller@7000f400 {
 		compatible = "nvidia,tegra30-emc";
 		reg = <0x7000f400 0x400>;
 		interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&tegra_car TEGRA30_CLK_EMC>;
 
 		nvidia,memory-controller = <&mc>;
+
+		#interconnect-cells = <1>;
 	};
 
 	fuse@7000f800 {
-- 
2.23.0


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

* [PATCH v1 11/29] ARM: tegra: Add interconnect properties to Tegra124 device-tree
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (9 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 10/29] ARM: tegra: Add interconnect properties to Tegra30 device-tree Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-19  6:27   ` Thierry Reding
  2019-11-18 20:02 ` [PATCH v1 12/29] interconnect: Add memory interconnection providers for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (18 subsequent siblings)
  29 siblings, 1 reply; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Add interconnect properties to the memory controller, external memory
controller and the display controller nodes to describe interconnection
of these nodes.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/boot/dts/tegra124.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index 413bfb981de8..5069af3011cc 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -3,6 +3,7 @@
 #include <dt-bindings/gpio/tegra-gpio.h>
 #include <dt-bindings/memory/tegra124-mc.h>
 #include <dt-bindings/pinctrl/pinctrl-tegra.h>
+#include <dt-bindings/interconnect/tegra-icc.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/reset/tegra124-car.h>
 #include <dt-bindings/thermal/tegra124-soctherm.h>
@@ -111,6 +112,9 @@
 			iommus = <&mc TEGRA_SWGROUP_DC>;
 
 			nvidia,head = <0>;
+
+			interconnects = <&mc TEGRA_ICC_MC_DC &emc TEGRA_ICC_EMEM>;
+			interconnect-names = "dma-mem";
 		};
 
 		dc@54240000 {
@@ -126,6 +130,9 @@
 			iommus = <&mc TEGRA_SWGROUP_DCB>;
 
 			nvidia,head = <1>;
+
+			interconnects = <&mc TEGRA_ICC_MC_DCB &emc TEGRA_ICC_EMEM>;
+			interconnect-names = "dma-mem";
 		};
 
 		hdmi: hdmi@54280000 {
@@ -620,6 +627,7 @@
 		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
 
 		#iommu-cells = <1>;
+		#interconnect-cells = <1>;
 	};
 
 	emc: emc@7001b000 {
@@ -627,6 +635,8 @@
 		reg = <0x0 0x7001b000 0x0 0x1000>;
 
 		nvidia,memory-controller = <&mc>;
+
+		#interconnect-cells = <1>;
 	};
 
 	sata@70020000 {
-- 
2.23.0


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

* [PATCH v1 12/29] interconnect: Add memory interconnection providers for NVIDIA Tegra SoCs
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (10 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 11/29] ARM: tegra: Add interconnect properties to Tegra124 device-tree Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-19  6:30   ` Thierry Reding
  2019-11-19  6:31   ` Thierry Reding
  2019-11-18 20:02 ` [PATCH v1 13/29] memory: tegra: Register as interconnect provider Dmitry Osipenko
                   ` (17 subsequent siblings)
  29 siblings, 2 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

All NVIDIA Tegra SoCs have identical topology in regards to memory
interconnection between memory clients and memory controllers.
The memory controller (MC) and external memory controller (EMC) are
providing memory clients with required memory bandwidth. The memory
controller performs arbitration between memory clients, while the
external memory controller transfers data from/to DRAM and pipes that
data from/to memory controller. Memory controller interconnect provider
aggregates bandwidth requests from memory clients and sends the aggregated
request to EMC provider that scales DRAM frequency in order to satisfy the
bandwidth requirement. Memory controller provider could adjust hardware
configuration for a more optimal arbitration depending on bandwidth
requirements from memory clients, but this is unimplemented for now.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/interconnect/Kconfig               |   1 +
 drivers/interconnect/Makefile              |   1 +
 drivers/interconnect/tegra/Kconfig         |   6 +
 drivers/interconnect/tegra/Makefile        |   4 +
 drivers/interconnect/tegra/tegra-icc-emc.c | 138 +++++++++++++++++++++
 drivers/interconnect/tegra/tegra-icc-mc.c  | 130 +++++++++++++++++++
 include/soc/tegra/mc.h                     |  26 ++++
 7 files changed, 306 insertions(+)
 create mode 100644 drivers/interconnect/tegra/Kconfig
 create mode 100644 drivers/interconnect/tegra/Makefile
 create mode 100644 drivers/interconnect/tegra/tegra-icc-emc.c
 create mode 100644 drivers/interconnect/tegra/tegra-icc-mc.c

diff --git a/drivers/interconnect/Kconfig b/drivers/interconnect/Kconfig
index bfa4ca3ab7a9..b11ca09665bb 100644
--- a/drivers/interconnect/Kconfig
+++ b/drivers/interconnect/Kconfig
@@ -12,5 +12,6 @@ menuconfig INTERCONNECT
 if INTERCONNECT
 
 source "drivers/interconnect/qcom/Kconfig"
+source "drivers/interconnect/tegra/Kconfig"
 
 endif
diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile
index 28f2ab0824d5..a37d419e262c 100644
--- a/drivers/interconnect/Makefile
+++ b/drivers/interconnect/Makefile
@@ -4,3 +4,4 @@ icc-core-objs				:= core.o
 
 obj-$(CONFIG_INTERCONNECT)		+= icc-core.o
 obj-$(CONFIG_INTERCONNECT_QCOM)		+= qcom/
+obj-$(CONFIG_INTERCONNECT_TEGRA)	+= tegra/
diff --git a/drivers/interconnect/tegra/Kconfig b/drivers/interconnect/tegra/Kconfig
new file mode 100644
index 000000000000..b724781da71e
--- /dev/null
+++ b/drivers/interconnect/tegra/Kconfig
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config INTERCONNECT_TEGRA
+	bool "NVIDIA Tegra interconnect drivers"
+	depends on ARCH_TEGRA || COMPILE_TEST
+	help
+	  Say Y here to enable support for NVIDIA Tegra interconnect drivers.
diff --git a/drivers/interconnect/tegra/Makefile b/drivers/interconnect/tegra/Makefile
new file mode 100644
index 000000000000..74ff2e53dbdc
--- /dev/null
+++ b/drivers/interconnect/tegra/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_INTERCONNECT_TEGRA) += tegra-icc-mc.o
+obj-$(CONFIG_INTERCONNECT_TEGRA) += tegra-icc-emc.o
diff --git a/drivers/interconnect/tegra/tegra-icc-emc.c b/drivers/interconnect/tegra/tegra-icc-emc.c
new file mode 100644
index 000000000000..b594ce811153
--- /dev/null
+++ b/drivers/interconnect/tegra/tegra-icc-emc.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Author: Dmitry Osipenko <digetx@gmail.com>
+ * Copyright (C) 2019 GRATE-DRIVER project
+ */
+
+#include <dt-bindings/interconnect/tegra-icc.h>
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/interconnect-provider.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+
+#include <soc/tegra/mc.h>
+
+struct tegra_emc_provider {
+	struct icc_provider provider;
+	struct clk *clk;
+	unsigned int dram_data_bus_width_bytes;
+};
+
+static inline struct tegra_emc_provider *
+to_tegra_emc_provider(struct icc_provider *provider)
+{
+	return container_of(provider, struct tegra_emc_provider, provider);
+}
+
+static struct icc_node *
+tegra_emc_of_icc_xlate_onecell(struct of_phandle_args *spec, void *data)
+{
+	struct icc_provider *provider = data;
+	struct icc_node *node;
+
+	list_for_each_entry(node, &provider->nodes, node_list) {
+		if (node->id == spec->args[0])
+			return node;
+	}
+
+	return ERR_PTR(-EINVAL);
+}
+
+static int tegra_emc_icc_set(struct icc_node *src, struct icc_node *dst)
+{
+	struct tegra_emc_provider *emc = to_tegra_emc_provider(dst->provider);
+	unsigned long long rate = icc_units_to_bps(dst->avg_bw);
+	unsigned int ddr = 2;
+	int err;
+
+	do_div(rate, ddr * emc->dram_data_bus_width_bytes);
+	rate = min_t(u64, rate, U32_MAX);
+
+	err = clk_set_min_rate(emc->clk, rate);
+	if (err)
+		return err;
+
+	err = clk_set_rate(emc->clk, rate);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int tegra_emc_icc_aggregate(struct icc_node *node,
+				   u32 tag, u32 avg_bw, u32 peak_bw,
+				   u32 *agg_avg, u32 *agg_peak)
+{
+	*agg_avg = min((u64)avg_bw + (*agg_avg), (u64)U32_MAX);
+	*agg_peak = max(*agg_peak, peak_bw);
+
+	return 0;
+}
+
+int tegra_icc_emc_setup_interconnect(struct device *emc_dev,
+				     unsigned int dram_data_bus_width_bytes)
+{
+	struct tegra_emc_provider *emc;
+	struct icc_node *node, *tmp;
+	int err;
+
+	emc = devm_kzalloc(emc_dev, sizeof(*emc), GFP_KERNEL);
+	if (!emc)
+		return -ENOMEM;
+
+	emc->clk = devm_clk_get(emc_dev, "emc");
+	err = PTR_ERR_OR_ZERO(emc->clk);
+	if (err)
+		return err;
+
+	emc->dram_data_bus_width_bytes = dram_data_bus_width_bytes;
+
+	emc->provider.dev = emc_dev;
+	emc->provider.set = tegra_emc_icc_set;
+	emc->provider.data = &emc->provider;
+	emc->provider.xlate = tegra_emc_of_icc_xlate_onecell;
+	emc->provider.aggregate = tegra_emc_icc_aggregate;
+
+	err = icc_provider_add(&emc->provider);
+	if (err)
+		return err;
+
+	/* create External Memory Controller node */
+	node = icc_node_create(TEGRA_ICC_EMC);
+	err = PTR_ERR_OR_ZERO(node);
+	if (err)
+		goto del_provider;
+
+	node->name = "EMC";
+	icc_node_add(node, &emc->provider);
+
+	/* link External Memory Controller with External Memory */
+	err = icc_link_create(node, TEGRA_ICC_EMEM);
+	if (err)
+		goto destroy_nodes;
+
+	/* create External Memory node */
+	node = icc_node_create(TEGRA_ICC_EMEM);
+	err = PTR_ERR_OR_ZERO(node);
+	if (err)
+		goto destroy_nodes;
+
+	node->name = "EMEM";
+	icc_node_add(node, &emc->provider);
+
+	return 0;
+
+destroy_nodes:
+	list_for_each_entry_safe(node, tmp, &emc->provider.nodes, node_list) {
+		icc_node_del(node);
+		icc_node_destroy(node->id);
+	}
+
+del_provider:
+	icc_provider_del(&emc->provider);
+
+	return err;
+}
diff --git a/drivers/interconnect/tegra/tegra-icc-mc.c b/drivers/interconnect/tegra/tegra-icc-mc.c
new file mode 100644
index 000000000000..f1ff8f98def3
--- /dev/null
+++ b/drivers/interconnect/tegra/tegra-icc-mc.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Author: Dmitry Osipenko <digetx@gmail.com>
+ * Copyright (C) 2019 GRATE-DRIVER project
+ */
+
+#include <dt-bindings/interconnect/tegra-icc.h>
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/interconnect-provider.h>
+#include <linux/of.h>
+
+#include <soc/tegra/mc.h>
+
+static struct icc_node *
+tegra_mc_of_icc_xlate_onecell(struct of_phandle_args *spec, void *data)
+{
+	struct icc_provider *provider = data;
+	struct icc_node *node;
+
+	list_for_each_entry(node, &provider->nodes, node_list) {
+		if (node->id == spec->args[0])
+			return node;
+	}
+
+	return ERR_PTR(-EINVAL);
+}
+
+static int tegra_mc_icc_set(struct icc_node *src, struct icc_node *dst)
+{
+	return 0;
+}
+
+static int tegra_mc_icc_aggregate(struct icc_node *node,
+				  u32 tag, u32 avg_bw, u32 peak_bw,
+				  u32 *agg_avg, u32 *agg_peak)
+{
+	*agg_avg = min((u64)avg_bw + (*agg_avg), (u64)U32_MAX);
+	*agg_peak = max(*agg_peak, peak_bw);
+
+	return 0;
+}
+
+/*
+ * Memory Controller (MC) has few Memory Clients that are issuing memory
+ * bandwidth allocation requests to the MC interconnect provider. The MC
+ * provider aggregates the requests and then sends the aggregated request
+ * up to the External Memory Controller (EMC) interconnect provider which
+ * re-configures hardware interface to External Memory (EMEM) in accordance
+ * to the required bandwidth.
+ *
+ * Memory interconnect topology:
+ *
+ *               +----+
+ *   +-----+     |    |
+ *   | GPU +---->+    |
+ *   +-----+     |    |
+ *               |    |     +-----+     +------+
+ *    ...        | MC +---->+ EMC +---->+ EMEM |
+ *               |    |     +-----+     +------+
+ *  +------+     |    |
+ *  | DISP +---->+    |
+ *  +------+     |    |
+ *               +----+
+ */
+int tegra_icc_mc_setup_interconnect(struct tegra_mc *mc)
+{
+	struct icc_provider *provider;
+	struct icc_node *node, *tmp;
+	unsigned int i;
+	int err;
+
+	provider = devm_kzalloc(mc->dev, sizeof(*provider), GFP_KERNEL);
+	if (!provider)
+		return -ENOMEM;
+
+	provider->dev = mc->dev;
+	provider->set = tegra_mc_icc_set;
+	provider->data = provider;
+	provider->xlate = tegra_mc_of_icc_xlate_onecell;
+	provider->aggregate = tegra_mc_icc_aggregate;
+
+	err = icc_provider_add(provider);
+	if (err)
+		return err;
+
+	/* create Memory Controller node */
+	node = icc_node_create(TEGRA_ICC_MC);
+	err = PTR_ERR_OR_ZERO(node);
+	if (err)
+		goto del_provider;
+
+	node->name = "MC";
+	icc_node_add(node, provider);
+
+	/* link Memory Controller with External Memory Controller */
+	err = icc_link_create(node, TEGRA_ICC_EMC);
+	if (err)
+		goto destroy_nodes;
+
+	for (i = 0; i < mc->soc->num_icc_nodes; i++) {
+		/* create MC client node */
+		node = icc_node_create(mc->soc->icc_nodes[i].id);
+		err = PTR_ERR_OR_ZERO(node);
+		if (err)
+			goto destroy_nodes;
+
+		node->name = mc->soc->icc_nodes[i].name;
+		icc_node_add(node, provider);
+
+		/* link Memory Client with Memory Controller */
+		err = icc_link_create(node, TEGRA_ICC_MC);
+		if (err)
+			goto destroy_nodes;
+	}
+
+	return 0;
+
+destroy_nodes:
+	list_for_each_entry_safe(node, tmp, &provider->nodes, node_list) {
+		icc_node_del(node);
+		icc_node_destroy(node->id);
+	}
+
+del_provider:
+	icc_provider_del(provider);
+
+	return err;
+}
diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h
index 1238e35653d1..593954324259 100644
--- a/include/soc/tegra/mc.h
+++ b/include/soc/tegra/mc.h
@@ -141,6 +141,11 @@ struct tegra_mc_reset_ops {
 			    const struct tegra_mc_reset *rst);
 };
 
+struct tegra_mc_icc_node {
+	const char *name;
+	unsigned int id;
+};
+
 struct tegra_mc_soc {
 	const struct tegra_mc_client *clients;
 	unsigned int num_clients;
@@ -160,6 +165,9 @@ struct tegra_mc_soc {
 	const struct tegra_mc_reset_ops *reset_ops;
 	const struct tegra_mc_reset *resets;
 	unsigned int num_resets;
+
+	const struct tegra_mc_icc_node *icc_nodes;
+	unsigned int num_icc_nodes;
 };
 
 struct tegra_mc {
@@ -184,4 +192,22 @@ struct tegra_mc {
 int tegra_mc_write_emem_configuration(struct tegra_mc *mc, unsigned long rate);
 unsigned int tegra_mc_get_emem_device_count(struct tegra_mc *mc);
 
+#ifdef CONFIG_INTERCONNECT_TEGRA
+int tegra_icc_mc_setup_interconnect(struct tegra_mc *mc);
+int tegra_icc_emc_setup_interconnect(struct device *emc_dev,
+				     unsigned int dram_data_bus_width_bytes);
+#else
+static inline int tegra_icc_mc_setup_interconnect(struct tegra_mc *mc);
+{
+	return 0;
+}
+
+static inline int
+tegra_icc_emc_setup_interconnect(struct device *emc_dev,
+				 unsigned int dram_data_bus_width_bytes)
+{
+	return 0;
+}
+#endif
+
 #endif /* __SOC_TEGRA_MC_H__ */
-- 
2.23.0


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

* [PATCH v1 13/29] memory: tegra: Register as interconnect provider
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (11 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 12/29] interconnect: Add memory interconnection providers for NVIDIA Tegra SoCs Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 14/29] memory: tegra: Add interconnect nodes for Terga20 display controllers Dmitry Osipenko
                   ` (16 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Memory controller now provides memory clients with memory bandwidth using
interconnect API.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/memory/tegra/mc.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
index ec8403557ed4..a4f7cc0bf9e7 100644
--- a/drivers/memory/tegra/mc.c
+++ b/drivers/memory/tegra/mc.c
@@ -699,6 +699,10 @@ static int tegra_mc_probe(struct platform_device *pdev)
 		}
 	}
 
+	err = tegra_icc_mc_setup_interconnect(mc);
+	if (err)
+		dev_err(&pdev->dev, "failed to initialize ICC: %d\n", err);
+
 	return 0;
 }
 
-- 
2.23.0


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

* [PATCH v1 14/29] memory: tegra: Add interconnect nodes for Terga20 display controllers
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (12 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 13/29] memory: tegra: Register as interconnect provider Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-19  6:34   ` Thierry Reding
  2019-11-18 20:02 ` [PATCH v1 15/29] memory: tegra: Add interconnect nodes for Terga30 " Dmitry Osipenko
                   ` (15 subsequent siblings)
  29 siblings, 1 reply; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Add initial interconnect nodes that allow display controller driver
to perform memory bandwidth requests using interconnect API.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/memory/tegra/tegra20.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c
index a8098bff91d9..dfcd9fdb7ce7 100644
--- a/drivers/memory/tegra/tegra20.c
+++ b/drivers/memory/tegra/tegra20.c
@@ -3,6 +3,7 @@
  * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
  */
 
+#include <dt-bindings/interconnect/tegra-icc.h>
 #include <dt-bindings/memory/tegra20-mc.h>
 
 #include "mc.h"
@@ -280,6 +281,17 @@ static const struct tegra_mc_reset_ops tegra20_mc_reset_ops = {
 	.reset_status = tegra20_mc_reset_status,
 };
 
+#define TEGRA20_MC_ICC(_name)				\
+	{						\
+		.name = #_name,				\
+		.id = TEGRA_ICC_MC_##_name,		\
+	}
+
+static const struct tegra_mc_icc_node tegra20_mc_icc_nodes[] = {
+	TEGRA20_MC_ICC(DC),
+	TEGRA20_MC_ICC(DCB),
+};
+
 const struct tegra_mc_soc tegra20_mc_soc = {
 	.clients = tegra20_mc_clients,
 	.num_clients = ARRAY_SIZE(tegra20_mc_clients),
@@ -290,4 +302,6 @@ const struct tegra_mc_soc tegra20_mc_soc = {
 	.reset_ops = &tegra20_mc_reset_ops,
 	.resets = tegra20_mc_resets,
 	.num_resets = ARRAY_SIZE(tegra20_mc_resets),
+	.icc_nodes = tegra20_mc_icc_nodes,
+	.num_icc_nodes = ARRAY_SIZE(tegra20_mc_icc_nodes),
 };
-- 
2.23.0


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

* [PATCH v1 15/29] memory: tegra: Add interconnect nodes for Terga30 display controllers
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (13 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 14/29] memory: tegra: Add interconnect nodes for Terga20 display controllers Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 16/29] memory: tegra: Add interconnect nodes for Terga124 " Dmitry Osipenko
                   ` (14 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Add initial interconnect nodes that allow display controller driver
to perform memory bandwidth requests using interconnect API.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/memory/tegra/tegra30.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c
index fcdd812eed80..df0d550b07f8 100644
--- a/drivers/memory/tegra/tegra30.c
+++ b/drivers/memory/tegra/tegra30.c
@@ -6,6 +6,7 @@
 #include <linux/of.h>
 #include <linux/mm.h>
 
+#include <dt-bindings/interconnect/tegra-icc.h>
 #include <dt-bindings/memory/tegra30-mc.h>
 
 #include "mc.h"
@@ -1011,6 +1012,17 @@ static const struct tegra_mc_reset tegra30_mc_resets[] = {
 	TEGRA30_MC_RESET(VI,       0x200, 0x204, 17),
 };
 
+#define TEGRA30_MC_ICC(_name)				\
+	{						\
+		.name = #_name,				\
+		.id = TEGRA_ICC_MC_##_name,		\
+	}
+
+static const struct tegra_mc_icc_node tegra30_mc_icc_nodes[] = {
+	TEGRA30_MC_ICC(DC),
+	TEGRA30_MC_ICC(DCB),
+};
+
 const struct tegra_mc_soc tegra30_mc_soc = {
 	.clients = tegra30_mc_clients,
 	.num_clients = ARRAY_SIZE(tegra30_mc_clients),
@@ -1025,4 +1037,6 @@ const struct tegra_mc_soc tegra30_mc_soc = {
 	.reset_ops = &tegra_mc_reset_ops_common,
 	.resets = tegra30_mc_resets,
 	.num_resets = ARRAY_SIZE(tegra30_mc_resets),
+	.icc_nodes = tegra30_mc_icc_nodes,
+	.num_icc_nodes = ARRAY_SIZE(tegra30_mc_icc_nodes),
 };
-- 
2.23.0


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

* [PATCH v1 16/29] memory: tegra: Add interconnect nodes for Terga124 display controllers
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (14 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 15/29] memory: tegra: Add interconnect nodes for Terga30 " Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 17/29] memory: tegra20-emc: Use devm_platform_ioremap_resource Dmitry Osipenko
                   ` (13 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Add initial interconnect nodes that allow display controller driver
to perform memory bandwidth requests using interconnect API.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/memory/tegra/tegra124.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c
index 493b5dc3a4b3..dae6b366281f 100644
--- a/drivers/memory/tegra/tegra124.c
+++ b/drivers/memory/tegra/tegra124.c
@@ -6,6 +6,7 @@
 #include <linux/of.h>
 #include <linux/mm.h>
 
+#include <dt-bindings/interconnect/tegra-icc.h>
 #include <dt-bindings/memory/tegra124-mc.h>
 
 #include "mc.h"
@@ -1028,6 +1029,17 @@ static const unsigned long tegra124_mc_emem_regs[] = {
 	MC_EMEM_ARB_RING1_THROTTLE
 };
 
+#define TEGRA124_MC_ICC(_name)				\
+	{						\
+		.name = #_name,				\
+		.id = TEGRA_ICC_MC_##_name,		\
+	}
+
+static const struct tegra_mc_icc_node tegra124_mc_icc_nodes[] = {
+	TEGRA124_MC_ICC(DC),
+	TEGRA124_MC_ICC(DCB),
+};
+
 static const struct tegra_smmu_soc tegra124_smmu_soc = {
 	.clients = tegra124_mc_clients,
 	.num_clients = ARRAY_SIZE(tegra124_mc_clients),
@@ -1056,6 +1068,8 @@ const struct tegra_mc_soc tegra124_mc_soc = {
 	.reset_ops = &tegra_mc_reset_ops_common,
 	.resets = tegra124_mc_resets,
 	.num_resets = ARRAY_SIZE(tegra124_mc_resets),
+	.icc_nodes = tegra124_mc_icc_nodes,
+	.num_icc_nodes = ARRAY_SIZE(tegra124_mc_icc_nodes),
 };
 #endif /* CONFIG_ARCH_TEGRA_124_SOC */
 
@@ -1086,5 +1100,7 @@ const struct tegra_mc_soc tegra132_mc_soc = {
 	.reset_ops = &tegra_mc_reset_ops_common,
 	.resets = tegra124_mc_resets,
 	.num_resets = ARRAY_SIZE(tegra124_mc_resets),
+	.icc_nodes = tegra124_mc_icc_nodes,
+	.num_icc_nodes = ARRAY_SIZE(tegra124_mc_icc_nodes),
 };
 #endif /* CONFIG_ARCH_TEGRA_132_SOC */
-- 
2.23.0


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

* [PATCH v1 17/29] memory: tegra20-emc: Use devm_platform_ioremap_resource
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (15 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 16/29] memory: tegra: Add interconnect nodes for Terga124 " Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 18/29] memory: tegra20-emc: Continue probing if timings/IRQ are missing in device-tree Dmitry Osipenko
                   ` (12 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Utilize that relatively new helper which makes code a bit cleaner.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/memory/tegra/tegra20-emc.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/memory/tegra/tegra20-emc.c b/drivers/memory/tegra/tegra20-emc.c
index 1b23b1c34476..d2efd0c658c0 100644
--- a/drivers/memory/tegra/tegra20-emc.c
+++ b/drivers/memory/tegra/tegra20-emc.c
@@ -482,7 +482,6 @@ static int tegra_emc_probe(struct platform_device *pdev)
 {
 	struct device_node *np;
 	struct tegra_emc *emc;
-	struct resource *res;
 	int irq, err;
 
 	/* driver has nothing to do in a case of memory timing absence */
@@ -518,8 +517,7 @@ static int tegra_emc_probe(struct platform_device *pdev)
 	if (err)
 		return err;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	emc->regs = devm_ioremap_resource(&pdev->dev, res);
+	emc->regs = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(emc->regs))
 		return PTR_ERR(emc->regs);
 
-- 
2.23.0


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

* [PATCH v1 18/29] memory: tegra20-emc: Continue probing if timings/IRQ are missing in device-tree
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (16 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 17/29] memory: tegra20-emc: Use devm_platform_ioremap_resource Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 19/29] memory: tegra20-emc: Register as interconnect provider Dmitry Osipenko
                   ` (11 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

EMC driver will become mandatory after making it interconnect provider
because interconnect users like display controller driver will fail to
probe using newer device-trees that have interconnect properties. Thus
make driver to probe even if timings or IRQ are missing in device-tree,
the frequency scaling won't be available in this case because there will
be only one frequency available, the frequency that is left from
bootloader.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/memory/tegra/tegra20-emc.c | 61 +++++++++++++++---------------
 1 file changed, 31 insertions(+), 30 deletions(-)

diff --git a/drivers/memory/tegra/tegra20-emc.c b/drivers/memory/tegra/tegra20-emc.c
index d2efd0c658c0..28bd9fd4c3c9 100644
--- a/drivers/memory/tegra/tegra20-emc.c
+++ b/drivers/memory/tegra/tegra20-emc.c
@@ -381,6 +381,11 @@ tegra_emc_find_node_by_ram_code(struct device *dev)
 	u32 value, ram_code;
 	int err;
 
+	if (of_get_child_count(dev->of_node) == 0) {
+		dev_info(dev, "device-tree doesn't have memory timings\n");
+		return NULL;
+	}
+
 	if (!of_property_read_bool(dev->of_node, "nvidia,use-ram-code"))
 		return of_node_get(dev->of_node);
 
@@ -449,6 +454,9 @@ static long emc_round_rate(unsigned long rate,
 	struct tegra_emc *emc = arg;
 	unsigned int i;
 
+	if (!emc->num_timings)
+		return clk_get_rate(emc->clk);
+
 	min_rate = min(min_rate, emc->timings[emc->num_timings - 1].rate);
 
 	for (i = 0; i < emc->num_timings; i++) {
@@ -484,38 +492,21 @@ static int tegra_emc_probe(struct platform_device *pdev)
 	struct tegra_emc *emc;
 	int irq, err;
 
-	/* driver has nothing to do in a case of memory timing absence */
-	if (of_get_child_count(pdev->dev.of_node) == 0) {
-		dev_info(&pdev->dev,
-			 "EMC device tree node doesn't have memory timings\n");
-		return 0;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "interrupt not specified\n");
-		dev_err(&pdev->dev, "please update your device tree\n");
-		return irq;
-	}
-
-	np = tegra_emc_find_node_by_ram_code(&pdev->dev);
-	if (!np)
-		return -EINVAL;
-
 	emc = devm_kzalloc(&pdev->dev, sizeof(*emc), GFP_KERNEL);
-	if (!emc) {
-		of_node_put(np);
+	if (!emc)
 		return -ENOMEM;
-	}
 
 	init_completion(&emc->clk_handshake_complete);
 	emc->clk_nb.notifier_call = tegra_emc_clk_change_notify;
 	emc->dev = &pdev->dev;
 
-	err = tegra_emc_load_timings_from_dt(emc, np);
-	of_node_put(np);
-	if (err)
-		return err;
+	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))
@@ -525,11 +516,21 @@ static int tegra_emc_probe(struct platform_device *pdev)
 	if (err)
 		return err;
 
-	err = devm_request_irq(&pdev->dev, irq, tegra_emc_isr, 0,
-			       dev_name(&pdev->dev), emc);
-	if (err) {
-		dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", irq, err);
-		return err;
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "interrupt not specified\n");
+		dev_err(&pdev->dev, "please update your device tree\n");
+		dev_err(&pdev->dev, "frequency scaling disabled\n");
+
+		emc->num_timings = 0;
+	} else {
+		err = devm_request_irq(&pdev->dev, irq, tegra_emc_isr, 0,
+				       dev_name(&pdev->dev), emc);
+		if (err) {
+			dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n",
+				irq, err);
+			return err;
+		}
 	}
 
 	tegra20_clk_set_emc_round_callback(emc_round_rate, emc);
-- 
2.23.0


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

* [PATCH v1 19/29] memory: tegra20-emc: Register as interconnect provider
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (17 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 18/29] memory: tegra20-emc: Continue probing if timings/IRQ are missing in device-tree Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 20/29] memory: tegra30-emc: Continue probing if timings are missing in device-tree Dmitry Osipenko
                   ` (10 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

EMC now provides MC with memory bandwidth using interconnect API.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/memory/tegra/tegra20-emc.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/drivers/memory/tegra/tegra20-emc.c b/drivers/memory/tegra/tegra20-emc.c
index 28bd9fd4c3c9..61ce422e102a 100644
--- a/drivers/memory/tegra/tegra20-emc.c
+++ b/drivers/memory/tegra/tegra20-emc.c
@@ -19,6 +19,7 @@
 #include <linux/types.h>
 
 #include <soc/tegra/fuse.h>
+#include <soc/tegra/mc.h>
 
 #define EMC_INTSTATUS				0x000
 #define EMC_INTMASK				0x004
@@ -87,6 +88,8 @@
 #define EMC_DBG_READ_DQM_CTRL			BIT(9)
 #define EMC_DBG_CFG_PRIORITY			BIT(24)
 
+#define EMC_FBIO_CFG5_DRAM_WIDTH_X16		BIT(4)
+
 static const u16 emc_timing_registers[] = {
 	EMC_RC,
 	EMC_RFC,
@@ -486,10 +489,27 @@ static long emc_round_rate(unsigned long rate,
 	return timing->rate;
 }
 
+static unsigned int emc_dram_data_bus_width_bytes(struct tegra_emc *emc)
+{
+	unsigned int bus_width;
+	u32 emc_cfg;
+
+	emc_cfg = readl_relaxed(emc->regs + EMC_FBIO_CFG5);
+	if (emc_cfg & EMC_FBIO_CFG5_DRAM_WIDTH_X16)
+		bus_width = 16;
+	else
+		bus_width = 32;
+
+	dev_info(emc->dev, "DRAM data-bus width: %ubit\n", bus_width);
+
+	return bus_width / 8;
+}
+
 static int tegra_emc_probe(struct platform_device *pdev)
 {
 	struct device_node *np;
 	struct tegra_emc *emc;
+	unsigned int bus_width;
 	int irq, err;
 
 	emc = devm_kzalloc(&pdev->dev, sizeof(*emc), GFP_KERNEL);
@@ -549,6 +569,12 @@ static int tegra_emc_probe(struct platform_device *pdev)
 		goto unset_cb;
 	}
 
+	bus_width = emc_dram_data_bus_width_bytes(emc);
+
+	err = tegra_icc_emc_setup_interconnect(&pdev->dev, bus_width);
+	if (err)
+		dev_err(&pdev->dev, "failed to initialize ICC: %d\n", err);
+
 	return 0;
 
 unset_cb:
-- 
2.23.0


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

* [PATCH v1 20/29] memory: tegra30-emc: Continue probing if timings are missing in device-tree
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (18 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 19/29] memory: tegra20-emc: Register as interconnect provider Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 21/29] memory: tegra30-emc: Register as interconnect provider Dmitry Osipenko
                   ` (9 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

EMC driver will become mandatory after making it interconnect provider
because interconnect users like display controller driver will fail to
probe using newer device-trees that have interconnect properties. Thus
make driver to probe even if timings are missing in device-tree, the
frequency scaling won't be available in this case because there will be
only one frequency available, the frequency that is left from bootloader.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/memory/tegra/tegra30-emc.c | 29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/memory/tegra/tegra30-emc.c b/drivers/memory/tegra/tegra30-emc.c
index 0b6a5e451ea3..ee194e8ed521 100644
--- a/drivers/memory/tegra/tegra30-emc.c
+++ b/drivers/memory/tegra/tegra30-emc.c
@@ -985,6 +985,11 @@ static struct device_node *emc_find_node_by_ram_code(struct device *dev)
 	u32 value, ram_code;
 	int err;
 
+	if (of_get_child_count(dev->of_node) == 0) {
+		dev_info(dev, "device-tree doesn't have memory timings\n");
+		return NULL;
+	}
+
 	ram_code = tegra_read_ram_code();
 
 	for_each_child_of_node(dev->of_node, np) {
@@ -1054,6 +1059,9 @@ static long emc_round_rate(unsigned long rate,
 	struct tegra_emc *emc = arg;
 	unsigned int i;
 
+	if (!emc->num_timings)
+		return clk_get_rate(emc->clk);
+
 	min_rate = min(min_rate, emc->timings[emc->num_timings - 1].rate);
 
 	for (i = 0; i < emc->num_timings; i++) {
@@ -1090,12 +1098,6 @@ static int tegra_emc_probe(struct platform_device *pdev)
 	struct tegra_emc *emc;
 	int err;
 
-	if (of_get_child_count(pdev->dev.of_node) == 0) {
-		dev_info(&pdev->dev,
-			 "device-tree node doesn't have memory timings\n");
-		return -ENODEV;
-	}
-
 	np = of_parse_phandle(pdev->dev.of_node, "nvidia,memory-controller", 0);
 	if (!np) {
 		dev_err(&pdev->dev, "could not get memory controller node\n");
@@ -1107,10 +1109,6 @@ static int tegra_emc_probe(struct platform_device *pdev)
 	if (!mc)
 		return -ENOENT;
 
-	np = emc_find_node_by_ram_code(&pdev->dev);
-	if (!np)
-		return -EINVAL;
-
 	emc = devm_kzalloc(&pdev->dev, sizeof(*emc), GFP_KERNEL);
 	if (!emc) {
 		of_node_put(np);
@@ -1125,10 +1123,13 @@ static int tegra_emc_probe(struct platform_device *pdev)
 	emc->clk_nb.notifier_call = emc_clk_change_notify;
 	emc->dev = &pdev->dev;
 
-	err = emc_load_timings_from_dt(emc, np);
-	of_node_put(np);
-	if (err)
-		return err;
+	np = emc_find_node_by_ram_code(&pdev->dev);
+	if (np) {
+		err = 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))
-- 
2.23.0


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

* [PATCH v1 21/29] memory: tegra30-emc: Register as interconnect provider
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (19 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 20/29] memory: tegra30-emc: Continue probing if timings are missing in device-tree Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 22/29] memory: tegra124-emc: Use devm_platform_ioremap_resource Dmitry Osipenko
                   ` (8 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

EMC now provides MC with memory bandwidth using interconnect API.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/memory/tegra/tegra30-emc.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/memory/tegra/tegra30-emc.c b/drivers/memory/tegra/tegra30-emc.c
index ee194e8ed521..7316ab50511b 100644
--- a/drivers/memory/tegra/tegra30-emc.c
+++ b/drivers/memory/tegra/tegra30-emc.c
@@ -1171,6 +1171,11 @@ static int tegra_emc_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, emc);
 
+	/* Tegra30 has DRAM channel fixed at 32bit width */
+	err = tegra_icc_emc_setup_interconnect(&pdev->dev, 32 / 8);
+	if (err)
+		dev_err(&pdev->dev, "failed to initialize ICC: %d\n", err);
+
 	return 0;
 
 unset_cb:
-- 
2.23.0


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

* [PATCH v1 22/29] memory: tegra124-emc: Use devm_platform_ioremap_resource
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (20 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 21/29] memory: tegra30-emc: Register as interconnect provider Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 23/29] memory: tegra124-emc: Register as interconnect provider Dmitry Osipenko
                   ` (7 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Utilize that relatively new helper which makes code a bit cleaner.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/memory/tegra/tegra124-emc.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/memory/tegra/tegra124-emc.c b/drivers/memory/tegra/tegra124-emc.c
index 464f0ceaee63..2c73260654ba 100644
--- a/drivers/memory/tegra/tegra124-emc.c
+++ b/drivers/memory/tegra/tegra124-emc.c
@@ -1085,7 +1085,6 @@ static int tegra_emc_probe(struct platform_device *pdev)
 	struct platform_device *mc;
 	struct device_node *np;
 	struct tegra_emc *emc;
-	struct resource *res;
 	u32 ram_code;
 	int err;
 
@@ -1095,8 +1094,7 @@ static int tegra_emc_probe(struct platform_device *pdev)
 
 	emc->dev = &pdev->dev;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	emc->regs = devm_ioremap_resource(&pdev->dev, res);
+	emc->regs = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(emc->regs))
 		return PTR_ERR(emc->regs);
 
-- 
2.23.0


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

* [PATCH v1 23/29] memory: tegra124-emc: Register as interconnect provider
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (21 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 22/29] memory: tegra124-emc: Use devm_platform_ioremap_resource Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-19 16:57   ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 24/29] drm/tegra: dc: Use devm_platform_ioremap_resource Dmitry Osipenko
                   ` (6 subsequent siblings)
  29 siblings, 1 reply; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

EMC now provides MC with memory bandwidth using interconnect API.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/memory/tegra/tegra124-emc.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/memory/tegra/tegra124-emc.c b/drivers/memory/tegra/tegra124-emc.c
index 2c73260654ba..c9478dcbeece 100644
--- a/drivers/memory/tegra/tegra124-emc.c
+++ b/drivers/memory/tegra/tegra124-emc.c
@@ -25,6 +25,7 @@
 #define EMC_FBIO_CFG5				0x104
 #define	EMC_FBIO_CFG5_DRAM_TYPE_MASK		0x3
 #define	EMC_FBIO_CFG5_DRAM_TYPE_SHIFT		0
+#define EMC_FBIO_CFG5_DRAM_WIDTH_X64		BIT(4)
 
 #define EMC_INTSTATUS				0x0
 #define EMC_INTSTATUS_CLKCHANGE_COMPLETE	BIT(4)
@@ -1080,11 +1081,28 @@ static void emc_debugfs_init(struct device *dev, struct tegra_emc *emc)
 		dev_err(dev, "failed to create debugfs entry\n");
 }
 
+static unsigned int emc_dram_data_bus_width_bytes(struct tegra_emc *emc)
+{
+	unsigned int bus_width;
+	u32 emc_cfg;
+
+	emc_cfg = readl_relaxed(emc->regs + EMC_FBIO_CFG5);
+	if (emc_cfg & EMC_FBIO_CFG5_DRAM_WIDTH_X64)
+		bus_width = 64;
+	else
+		bus_width = 32;
+
+	dev_info(emc->dev, "DRAM data-bus width: %ubit\n", bus_width);
+
+	return bus_width / 8;
+}
+
 static int tegra_emc_probe(struct platform_device *pdev)
 {
 	struct platform_device *mc;
 	struct device_node *np;
 	struct tegra_emc *emc;
+	unsigned int bus_width;
 	u32 ram_code;
 	int err;
 
@@ -1146,6 +1164,12 @@ static int tegra_emc_probe(struct platform_device *pdev)
 	if (IS_ENABLED(CONFIG_DEBUG_FS))
 		emc_debugfs_init(&pdev->dev, emc);
 
+	bus_width = emc_dram_data_bus_width_bytes(emc);
+
+	err = tegra_icc_emc_setup_interconnect(&pdev->dev, bus_width);
+	if (err)
+		dev_err(&pdev->dev, "failed to initialize ICC: %d\n", err);
+
 	return 0;
 };
 
-- 
2.23.0


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

* [PATCH v1 24/29] drm/tegra: dc: Use devm_platform_ioremap_resource
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (22 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 23/29] memory: tegra124-emc: Register as interconnect provider Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 25/29] drm/tegra: dc: Release PM and RGB output when client's registration fails Dmitry Osipenko
                   ` (5 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Utilize that relatively new helper which makes code a bit cleaner.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/gpu/drm/tegra/dc.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 5b1f9ff97576..14834cba5455 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -2421,7 +2421,6 @@ static int tegra_dc_couple(struct tegra_dc *dc)
 
 static int tegra_dc_probe(struct platform_device *pdev)
 {
-	struct resource *regs;
 	struct tegra_dc *dc;
 	int err;
 
@@ -2478,8 +2477,7 @@ static int tegra_dc_probe(struct platform_device *pdev)
 		tegra_powergate_power_off(dc->powergate);
 	}
 
-	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	dc->regs = devm_ioremap_resource(&pdev->dev, regs);
+	dc->regs = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(dc->regs))
 		return PTR_ERR(dc->regs);
 
-- 
2.23.0


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

* [PATCH v1 25/29] drm/tegra: dc: Release PM and RGB output when client's registration fails
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (23 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 24/29] drm/tegra: dc: Use devm_platform_ioremap_resource Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 26/29] drm/tegra: dc: Support memory bandwidth management Dmitry Osipenko
                   ` (4 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Runtime PM and RGB output need to be released when host1x client
registration fails.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/gpu/drm/tegra/dc.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 14834cba5455..c2c61156cdcf 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -2504,10 +2504,16 @@ static int tegra_dc_probe(struct platform_device *pdev)
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
 			err);
-		return err;
+		goto disable_pm;
 	}
 
 	return 0;
+
+disable_pm:
+	pm_runtime_disable(&pdev->dev);
+	tegra_dc_rgb_remove(dc);
+
+	return err;
 }
 
 static int tegra_dc_remove(struct platform_device *pdev)
-- 
2.23.0


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

* [PATCH v1 26/29] drm/tegra: dc: Support memory bandwidth management
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (24 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 25/29] drm/tegra: dc: Release PM and RGB output when client's registration fails Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 27/29] ARM: tegra: Enable interconnect API in tegra_defconfig Dmitry Osipenko
                   ` (3 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Display controller (DC) performs isochronous memory transfers and thus
has a requirement for a minimum memory bandwidth that shall be fulfilled,
otherwise framebuffer data can't be fetched fast enough and this results
in a DC's data-FIFO underflow that follows by a visual corruption.

The External Memory Controller drivers provide facility for memory
bandwidth management via interconnect API. This patch wires up the
interconnect API support to the DC driver.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/gpu/drm/tegra/dc.c    | 240 +++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/tegra/dc.h    |   8 ++
 drivers/gpu/drm/tegra/drm.c   |  18 +++
 drivers/gpu/drm/tegra/plane.c |   1 +
 drivers/gpu/drm/tegra/plane.h |   4 +-
 5 files changed, 269 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index c2c61156cdcf..c60a0c00d95f 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -519,6 +519,122 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
 		tegra_plane_setup_blending(plane, window);
 }
 
+static unsigned long
+tegra_plane_memory_bandwidth(struct drm_plane_state *state,
+			     struct tegra_dc_window *window)
+{
+	struct tegra_plane_state *tegra_state;
+	struct drm_crtc_state *crtc_state;
+	const struct drm_format_info *fmt;
+	struct tegra_dc_window win;
+	unsigned int bpp_plane;
+	unsigned int bpp;
+	unsigned int mul;
+	unsigned int i;
+
+	if (!state->fb || !state->visible)
+		return 0;
+
+	crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc);
+	tegra_state = to_tegra_plane_state(state);
+
+	if (!window)
+		window = &win;
+
+	window->src.w = drm_rect_width(&state->src) >> 16;
+	window->src.h = drm_rect_height(&state->src) >> 16;
+	window->dst.w = drm_rect_width(&state->dst);
+	window->dst.h = drm_rect_height(&state->dst);
+	window->tiling = tegra_state->tiling;
+
+	fmt = state->fb->format;
+
+	/*
+	 * Note that real memory bandwidth vary depending on format and
+	 * memory layout, we are not taking that into account because small
+	 * estimation error isn't important since bandwidth is rounded up
+	 * anyway.
+	 */
+	for (i = 0, bpp = 0; i < fmt->num_planes; i++) {
+		bpp_plane = fmt->cpp[i] * 8;
+
+		/*
+		 * Sub-sampling is relevant for chroma planes only and vertical
+		 * readouts are not cached, hence only horizontal sub-sampling
+		 * matters.
+		 */
+		if (i > 0)
+			bpp_plane /= fmt->hsub;
+
+		bpp += bpp_plane;
+	}
+
+	/*
+	 * Horizontal downscale takes extra bandwidth which roughly depends
+	 * on the scaled width.
+	 */
+	if (window->src.w > window->dst.w)
+		mul = (window->src.w - window->dst.w) * bpp / 2048 + 1;
+	else
+		mul = 1;
+
+	/*
+	 * Ignore window if its width is small enough such that data-prefetch
+	 * FIFO will easily help to overcome temporal memory pressure. This is
+	 * a typical case for the cursor's plane.
+	 */
+	if (mul == 1 && window->src.w * bpp <= 2048)
+		return 0;
+
+	/* mode.clock in kHz, bandwidth in kbit/s */
+	return kbps_to_icc(crtc_state->mode.clock * bpp * mul);
+}
+
+static unsigned long
+tegra20_plane_memory_bandwidth(struct drm_plane_state *state)
+{
+	/* ~35% efficiency */
+	return tegra_plane_memory_bandwidth(state, NULL) * 29 / 10;
+}
+
+static unsigned long
+tegra30_plane_memory_bandwidth(struct drm_plane_state *state)
+{
+	struct tegra_dc_window window;
+	unsigned long bandwidth;
+
+	bandwidth = tegra_plane_memory_bandwidth(state, &window);
+
+	/* x2: memory overfetch for tiled framebuffer and DDR3 */
+	if (window.tiling.mode == TEGRA_BO_TILING_MODE_TILED)
+		bandwidth *= 2;
+
+	/* ~35% efficiency */
+	return bandwidth * 29 / 10;
+}
+
+static unsigned long
+tegra114_plane_memory_bandwidth(struct drm_plane_state *state)
+{
+	struct tegra_dc_window window;
+	unsigned long bandwidth;
+
+	bandwidth = tegra_plane_memory_bandwidth(state, &window);
+
+	/* x2: memory overfetch for tiled framebuffer and DDR3 */
+	if (window.tiling.mode == TEGRA_BO_TILING_MODE_TILED)
+		bandwidth *= 2;
+
+	return bandwidth;
+}
+
+static unsigned long
+tegra124_plane_memory_bandwidth(struct drm_plane_state *state)
+{
+	/* 64bit memory bus */
+	return tegra_plane_memory_bandwidth(state, NULL);
+}
+
 static const u32 tegra20_primary_formats[] = {
 	DRM_FORMAT_ARGB4444,
 	DRM_FORMAT_ARGB1555,
@@ -608,8 +724,10 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
 	int err;
 
 	/* no need for further checks if the plane is being disabled */
-	if (!state->crtc)
+	if (!state->crtc) {
+		plane_state->memory_bandwidth = 0;
 		return 0;
+	}
 
 	err = tegra_plane_format(state->fb->format->format,
 				 &plane_state->format,
@@ -662,6 +780,8 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
 	if (err < 0)
 		return err;
 
+	plane_state->memory_bandwidth = dc->soc->plane_memory_bandwidth(state);
+
 	return 0;
 }
 
@@ -1186,6 +1306,7 @@ tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
 	copy->pclk = state->pclk;
 	copy->div = state->div;
 	copy->planes = state->planes;
+	copy->memory_bandwidth = state->memory_bandwidth;
 
 	return &copy->base;
 }
@@ -1774,6 +1895,8 @@ static void tegra_crtc_atomic_disable(struct drm_crtc *crtc,
 	spin_unlock_irq(&crtc->dev->event_lock);
 
 	pm_runtime_put_sync(dc->dev);
+
+	icc_set_bw(dc->icc, 0, 0);
 }
 
 static void tegra_crtc_atomic_enable(struct drm_crtc *crtc,
@@ -1784,6 +1907,8 @@ static void tegra_crtc_atomic_enable(struct drm_crtc *crtc,
 	struct tegra_dc *dc = to_tegra_dc(crtc);
 	u32 value;
 
+	icc_set_bw(dc->icc, state->memory_bandwidth, state->memory_bandwidth);
+
 	pm_runtime_get_sync(dc->dev);
 
 	/* initialize display controller */
@@ -1893,6 +2018,9 @@ static void tegra_crtc_atomic_enable(struct drm_crtc *crtc,
 static void tegra_crtc_atomic_begin(struct drm_crtc *crtc,
 				    struct drm_crtc_state *old_crtc_state)
 {
+	struct tegra_dc_state *dc_old_state = to_dc_state(old_crtc_state);
+	struct tegra_dc_state *dc_state = to_dc_state(crtc->state);
+	struct tegra_dc *dc = to_tegra_dc(crtc);
 	unsigned long flags;
 
 	if (crtc->state->event) {
@@ -1907,6 +2035,25 @@ static void tegra_crtc_atomic_begin(struct drm_crtc *crtc,
 
 		crtc->state->event = NULL;
 	}
+
+	if (old_crtc_state && old_crtc_state->active) {
+		/*
+		 * Raise memory bandwidth before changes take effect if it
+		 * goes from low to high.
+		 */
+		if (dc_old_state->memory_bandwidth < dc_state->memory_bandwidth)
+			icc_set_bw(dc->icc,
+				   dc_state->memory_bandwidth,
+				   dc_state->memory_bandwidth);
+	} else {
+		/*
+		 * Raise memory bandwidth before changes take effect if
+		 * CRTC is turning on.
+		 */
+		icc_set_bw(dc->icc,
+			   dc_state->memory_bandwidth,
+			   dc_state->memory_bandwidth);
+	}
 }
 
 static void tegra_crtc_atomic_flush(struct drm_crtc *crtc,
@@ -1925,7 +2072,79 @@ static void tegra_crtc_atomic_flush(struct drm_crtc *crtc,
 	value = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
 }
 
+static bool
+tegra_plane_intersects_with_other_plane(struct drm_crtc_state *state,
+					const struct drm_plane_state *plane_state)
+{
+	const struct drm_plane_state *other_state;
+	struct drm_plane *plane;
+	struct drm_rect rect;
+
+	drm_atomic_crtc_state_for_each_plane_state(plane, other_state, state) {
+		rect = plane_state->dst;
+
+		if (other_state == plane_state)
+			continue;
+
+		if (!other_state->visible || !other_state->fb)
+			continue;
+
+		if (drm_rect_intersect(&rect, &other_state->dst))
+			return true;
+	}
+
+	return false;
+}
+
+static int tegra_crtc_atomic_check(struct drm_crtc *crtc,
+				   struct drm_crtc_state *state)
+{
+	struct tegra_dc_state *dc_state = to_dc_state(state);
+	const struct drm_plane_state *plane_state;
+	const struct tegra_plane_state *tegra;
+	unsigned long long bandwidth = 0;
+	struct drm_plane *plane;
+
+	/*
+	 * For overlapping planes pixel's data is fetched for each plane at
+	 * the same time, hence bandwidth is accumulated in this case.
+	 */
+	drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, state) {
+		tegra = to_tegra_plane_state(plane_state);
+
+		if (tegra_plane_intersects_with_other_plane(state, plane_state))
+			bandwidth += tegra->memory_bandwidth;
+		else
+			bandwidth = max(bandwidth, (u64)tegra->memory_bandwidth);
+	}
+
+	dc_state->memory_bandwidth = min(bandwidth, (u64)U32_MAX);
+
+	return 0;
+}
+
+void tegra_crtc_atomic_post_commit(struct drm_crtc *crtc,
+				   struct drm_crtc_state *old_crtc_state)
+{
+	struct tegra_dc_state *dc_old_state = to_dc_state(old_crtc_state);
+	struct tegra_dc_state *dc_state = to_dc_state(crtc->state);
+	struct tegra_dc *dc = to_tegra_dc(crtc);
+
+	if (!dc_old_state)
+		return;
+
+	/*
+	 * Drop memory bandwidth after changes take effect if it goes from
+	 * high to low.
+	 */
+	if (dc_old_state->memory_bandwidth > dc_state->memory_bandwidth)
+		icc_set_bw(dc->icc,
+			   dc_state->memory_bandwidth,
+			   dc_state->memory_bandwidth);
+}
+
 static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
+	.atomic_check = tegra_crtc_atomic_check,
 	.atomic_begin = tegra_crtc_atomic_begin,
 	.atomic_flush = tegra_crtc_atomic_flush,
 	.atomic_enable = tegra_crtc_atomic_enable,
@@ -2143,6 +2362,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
 	.modifiers = tegra20_modifiers,
 	.has_win_a_without_filters = true,
 	.has_win_c_without_vert_filter = true,
+	.plane_memory_bandwidth = tegra20_plane_memory_bandwidth,
 };
 
 static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
@@ -2162,6 +2382,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
 	.modifiers = tegra20_modifiers,
 	.has_win_a_without_filters = false,
 	.has_win_c_without_vert_filter = false,
+	.plane_memory_bandwidth = tegra30_plane_memory_bandwidth,
 };
 
 static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
@@ -2181,6 +2402,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
 	.modifiers = tegra20_modifiers,
 	.has_win_a_without_filters = false,
 	.has_win_c_without_vert_filter = false,
+	.plane_memory_bandwidth = tegra114_plane_memory_bandwidth,
 };
 
 static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
@@ -2200,6 +2422,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
 	.modifiers = tegra124_modifiers,
 	.has_win_a_without_filters = false,
 	.has_win_c_without_vert_filter = false,
+	.plane_memory_bandwidth = tegra124_plane_memory_bandwidth,
 };
 
 static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
@@ -2219,6 +2442,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
 	.modifiers = tegra124_modifiers,
 	.has_win_a_without_filters = false,
 	.has_win_c_without_vert_filter = false,
+	.plane_memory_bandwidth = tegra124_plane_memory_bandwidth,
 };
 
 static const struct tegra_windowgroup_soc tegra186_dc_wgrps[] = {
@@ -2267,6 +2491,7 @@ static const struct tegra_dc_soc_info tegra186_dc_soc_info = {
 	.has_nvdisplay = true,
 	.wgrps = tegra186_dc_wgrps,
 	.num_wgrps = ARRAY_SIZE(tegra186_dc_wgrps),
+	.plane_memory_bandwidth = tegra124_plane_memory_bandwidth,
 };
 
 static const struct tegra_windowgroup_soc tegra194_dc_wgrps[] = {
@@ -2315,6 +2540,7 @@ static const struct tegra_dc_soc_info tegra194_dc_soc_info = {
 	.has_nvdisplay = true,
 	.wgrps = tegra194_dc_wgrps,
 	.num_wgrps = ARRAY_SIZE(tegra194_dc_wgrps),
+	.plane_memory_bandwidth = tegra124_plane_memory_bandwidth,
 };
 
 static const struct of_device_id tegra_dc_of_match[] = {
@@ -2493,6 +2719,13 @@ static int tegra_dc_probe(struct platform_device *pdev)
 		return err;
 	}
 
+	dc->icc = of_icc_get(dc->dev, "dma-mem");
+	err = PTR_ERR_OR_ZERO(dc->icc);
+	if (err) {
+		dev_err(dc->dev, "failed to get interconnect: %d\n", err);
+		goto remove_rgb;
+	}
+
 	platform_set_drvdata(pdev, dc);
 	pm_runtime_enable(&pdev->dev);
 
@@ -2511,6 +2744,9 @@ static int tegra_dc_probe(struct platform_device *pdev)
 
 disable_pm:
 	pm_runtime_disable(&pdev->dev);
+	icc_put(dc->icc);
+
+remove_rgb:
 	tegra_dc_rgb_remove(dc);
 
 	return err;
@@ -2528,6 +2764,8 @@ static int tegra_dc_remove(struct platform_device *pdev)
 		return err;
 	}
 
+	icc_put(dc->icc);
+
 	err = tegra_dc_rgb_remove(dc);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to remove RGB output: %d\n", err);
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 3d8ddccd758f..629b379a8207 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -8,6 +8,7 @@
 #define TEGRA_DC_H 1
 
 #include <linux/host1x.h>
+#include <linux/interconnect.h>
 
 #include <drm/drm_crtc.h>
 
@@ -23,6 +24,8 @@ struct tegra_dc_state {
 	unsigned int div;
 
 	u32 planes;
+
+	unsigned long memory_bandwidth;
 };
 
 static inline struct tegra_dc_state *to_dc_state(struct drm_crtc_state *state)
@@ -66,6 +69,7 @@ struct tegra_dc_soc_info {
 	const u64 *modifiers;
 	bool has_win_a_without_filters;
 	bool has_win_c_without_vert_filter;
+	unsigned long (*plane_memory_bandwidth)(struct drm_plane_state *state);
 };
 
 struct tegra_dc {
@@ -90,6 +94,8 @@ struct tegra_dc {
 	struct drm_info_list *debugfs_files;
 
 	const struct tegra_dc_soc_info *soc;
+
+	struct icc_path *icc;
 };
 
 static inline struct tegra_dc *
@@ -150,6 +156,8 @@ int tegra_dc_state_setup_clock(struct tegra_dc *dc,
 			       struct drm_crtc_state *crtc_state,
 			       struct clk *clk, unsigned long pclk,
 			       unsigned int div);
+void tegra_crtc_atomic_post_commit(struct drm_crtc *crtc,
+				   struct drm_crtc_state *old_crtc_state);
 
 /* from rgb.c */
 int tegra_dc_rgb_probe(struct tegra_dc *dc);
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 56e5e7a5c108..ccce91ea7180 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -20,6 +20,7 @@
 #include <drm/drm_prime.h>
 #include <drm/drm_vblank.h>
 
+#include "dc.h"
 #include "drm.h"
 #include "gem.h"
 
@@ -59,6 +60,21 @@ static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = {
 	.atomic_commit = drm_atomic_helper_commit,
 };
 
+static void tegra_atomic_post_commit(struct drm_device *drm,
+				     struct drm_atomic_state *old_state)
+{
+	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
+	struct drm_crtc *crtc;
+	int i;
+
+	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
+		if (!new_crtc_state->active)
+			continue;
+
+		tegra_crtc_atomic_post_commit(crtc, old_crtc_state);
+	}
+}
+
 static void tegra_atomic_commit_tail(struct drm_atomic_state *old_state)
 {
 	struct drm_device *drm = old_state->dev;
@@ -75,6 +91,8 @@ static void tegra_atomic_commit_tail(struct drm_atomic_state *old_state)
 	} else {
 		drm_atomic_helper_commit_tail_rpm(old_state);
 	}
+
+	tegra_atomic_post_commit(drm, old_state);
 }
 
 static const struct drm_mode_config_helper_funcs
diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c
index 163b590be224..1f482e594dc9 100644
--- a/drivers/gpu/drm/tegra/plane.c
+++ b/drivers/gpu/drm/tegra/plane.c
@@ -61,6 +61,7 @@ tegra_plane_atomic_duplicate_state(struct drm_plane *plane)
 	copy->swap = state->swap;
 	copy->bottom_up = state->bottom_up;
 	copy->opaque = state->opaque;
+	copy->memory_bandwidth = state->memory_bandwidth;
 
 	for (i = 0; i < 2; i++)
 		copy->blending[i] = state->blending[i];
diff --git a/drivers/gpu/drm/tegra/plane.h b/drivers/gpu/drm/tegra/plane.h
index a158a915109a..5227c7a9ad8b 100644
--- a/drivers/gpu/drm/tegra/plane.h
+++ b/drivers/gpu/drm/tegra/plane.h
@@ -51,10 +51,12 @@ struct tegra_plane_state {
 	/* used for legacy blending support only */
 	struct tegra_plane_legacy_blending_state blending[2];
 	bool opaque;
+
+	unsigned long memory_bandwidth;
 };
 
 static inline struct tegra_plane_state *
-to_tegra_plane_state(struct drm_plane_state *state)
+to_tegra_plane_state(const struct drm_plane_state *state)
 {
 	if (state)
 		return container_of(state, struct tegra_plane_state, base);
-- 
2.23.0


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

* [PATCH v1 27/29] ARM: tegra: Enable interconnect API in tegra_defconfig
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (25 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 26/29] drm/tegra: dc: Support memory bandwidth management Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 28/29] ARM: multi_v7_defconfig: Enable NVIDIA Tegra interconnect providers Dmitry Osipenko
                   ` (2 subsequent siblings)
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Tegra now has interconnect providers that are used for memory bandwidth
allocation by display driver.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/configs/tegra_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index aa94369bdd0f..02e3a987f69f 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -268,6 +268,8 @@ CONFIG_AK8975=y
 CONFIG_PWM=y
 CONFIG_PWM_TEGRA=y
 CONFIG_PHY_TEGRA_XUSB=y
+CONFIG_INTERCONNECT=y
+CONFIG_INTERCONNECT_TEGRA=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
-- 
2.23.0


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

* [PATCH v1 28/29] ARM: multi_v7_defconfig: Enable NVIDIA Tegra interconnect providers
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (26 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 27/29] ARM: tegra: Enable interconnect API in tegra_defconfig Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-18 20:02 ` [PATCH v1 29/29] MAINTAINERS: Add maintainers for NVIDIA Tegra interconnect drivers Dmitry Osipenko
  2019-11-19  6:19 ` [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Thierry Reding
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Tegra now has interconnect providers that are used for memory bandwidth
allocation by display driver.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/configs/multi_v7_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 293f0cea076c..c131d7969aa3 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -1085,6 +1085,8 @@ CONFIG_FSI_MASTER_ASPEED=m
 CONFIG_FSI_SCOM=m
 CONFIG_FSI_SBEFIFO=m
 CONFIG_FSI_OCC=m
+CONFIG_INTERCONNECT=y
+CONFIG_INTERCONNECT_TEGRA=y
 CONFIG_EXT4_FS=y
 CONFIG_AUTOFS4_FS=y
 CONFIG_MSDOS_FS=y
-- 
2.23.0


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

* [PATCH v1 29/29] MAINTAINERS: Add maintainers for NVIDIA Tegra interconnect drivers
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (27 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 28/29] ARM: multi_v7_defconfig: Enable NVIDIA Tegra interconnect providers Dmitry Osipenko
@ 2019-11-18 20:02 ` Dmitry Osipenko
  2019-11-19  6:19 ` [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Thierry Reding
  29 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-18 20:02 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

Dmitry and Thierry will maintain NVIDIA Tegra interconnect drivers.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 MAINTAINERS | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 51bf69f520e8..fd82089edad6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8614,6 +8614,15 @@ F:	include/dt-bindings/interconnect/
 F:	include/linux/interconnect-provider.h
 F:	include/linux/interconnect.h
 
+INTERCONNECT DRIVERS FOR NVIDIA TEGRA
+R:	Dmitry Osipenko <digetx@gmail.com>
+S:	Thierry Reding <thierry.reding@gmail.com>
+L:	linux-pm@vger.kernel.org
+L:	linux-tegra@vger.kernel.org
+S:	Supported
+F:	drivers/interconnect/tegra/
+F:	include/dt-bindings/interconnect/tegra-icc.h
+
 INVENSENSE MPU-3050 GYROSCOPE DRIVER
 M:	Linus Walleij <linus.walleij@linaro.org>
 L:	linux-iio@vger.kernel.org
-- 
2.23.0


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

* Re: [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs
  2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
                   ` (28 preceding siblings ...)
  2019-11-18 20:02 ` [PATCH v1 29/29] MAINTAINERS: Add maintainers for NVIDIA Tegra interconnect drivers Dmitry Osipenko
@ 2019-11-19  6:19 ` Thierry Reding
  29 siblings, 0 replies; 46+ messages in thread
From: Thierry Reding @ 2019-11-19  6:19 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jonathan Hunter, Peter De Schrijver, Mikko Perttunen,
	Georgi Djakov, Rob Herring, linux-tegra, linux-pm, linux-kernel,
	dri-devel, devicetree

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

On Mon, Nov 18, 2019 at 11:02:18PM +0300, Dmitry Osipenko wrote:
> Hello,
> 

I like this, thanks for looking into this.

> This series brings initial support for memory interconnect to Tegra20,
> Terga30 and Tegra124 SoCs. The interconnect provides are quite generic
> and should be suitable for all Tegra SoCs, but currently upstream kernel
> has EMC/MC drivers only for those three generations of Tegra SoCs.

Tegra186 and Tegra194 should support this out of the box because the EMC
frequency can be scaled via the BPMP. Tegra210 support for EMC scaling
is in the works, so hopefully we'll be able to extend this in the near
future.

> For the start only display controllers are getting interconnect API
> support, others could be supported later on. The display controllers
> have the biggest demand for interconnect API right now because dynamic
> memory frequency scaling can't be done safely without taking into account
> bandwidth requirement from the displays.

Agreed, display controllers are where we most immediately notice when
there's not enough bandwidth. I think it's fair to start small and
extend interconnect consumers as we progress.

I've got a couple of comments regarding individual patches, but on the
whole this looks pretty nice.

Thierry

> Dmitry Osipenko (29):
>   dt-bindings: memory: tegra20: mc: Document new interconnect property
>   dt-bindings: memory: tegra20: emc: Document new interconnect property
>   dt-bindings: memory: tegra30: mc: Document new interconnect property
>   dt-bindings: memory: tegra30: emc: Document new interconnect property
>   dt-bindings: memory: tegra124: mc: Document new interconnect property
>   dt-bindings: memory: tegra124: emc: Document new interconnect property
>   dt-bindings: host1x: Document new interconnect properties
>   dt-bindings: interconnect: tegra: Add initial IDs
>   ARM: tegra: Add interconnect properties to Tegra20 device-tree
>   ARM: tegra: Add interconnect properties to Tegra30 device-tree
>   ARM: tegra: Add interconnect properties to Tegra124 device-tree
>   interconnect: Add memory interconnection providers for NVIDIA Tegra
>     SoCs
>   memory: tegra: Register as interconnect provider
>   memory: tegra: Add interconnect nodes for Terga20 display controllers
>   memory: tegra: Add interconnect nodes for Terga30 display controllers
>   memory: tegra: Add interconnect nodes for Terga124 display controllers
>   memory: tegra20-emc: Use devm_platform_ioremap_resource
>   memory: tegra20-emc: Continue probing if timings/IRQ are missing in
>     device-tree
>   memory: tegra20-emc: Register as interconnect provider
>   memory: tegra30-emc: Continue probing if timings are missing in
>     device-tree
>   memory: tegra30-emc: Register as interconnect provider
>   memory: tegra124-emc: Use devm_platform_ioremap_resource
>   memory: tegra124-emc: Register as interconnect provider
>   drm/tegra: dc: Use devm_platform_ioremap_resource
>   drm/tegra: dc: Release PM and RGB output when client's registration
>     fails
>   drm/tegra: dc: Support memory bandwidth management
>   ARM: tegra: Enable interconnect API in tegra_defconfig
>   ARM: multi_v7_defconfig: Enable NVIDIA Tegra interconnect providers
>   MAINTAINERS: Add maintainers for NVIDIA Tegra interconnect drivers
> 
>  .../display/tegra/nvidia,tegra20-host1x.txt   |  67 +++++
>  .../nvidia,tegra124-emc.txt                   |   3 +
>  .../nvidia,tegra124-mc.yaml                   |   5 +
>  .../memory-controllers/nvidia,tegra20-emc.txt |   4 +
>  .../memory-controllers/nvidia,tegra20-mc.txt  |   4 +
>  .../nvidia,tegra30-emc.yaml                   |   6 +
>  .../memory-controllers/nvidia,tegra30-mc.yaml |   5 +
>  MAINTAINERS                                   |   9 +
>  arch/arm/boot/dts/tegra124.dtsi               |  10 +
>  arch/arm/boot/dts/tegra20.dtsi                |  11 +-
>  arch/arm/boot/dts/tegra30.dtsi                |  12 +-
>  arch/arm/configs/multi_v7_defconfig           |   2 +
>  arch/arm/configs/tegra_defconfig              |   2 +
>  drivers/gpu/drm/tegra/dc.c                    | 252 +++++++++++++++++-
>  drivers/gpu/drm/tegra/dc.h                    |   8 +
>  drivers/gpu/drm/tegra/drm.c                   |  18 ++
>  drivers/gpu/drm/tegra/plane.c                 |   1 +
>  drivers/gpu/drm/tegra/plane.h                 |   4 +-
>  drivers/interconnect/Kconfig                  |   1 +
>  drivers/interconnect/Makefile                 |   1 +
>  drivers/interconnect/tegra/Kconfig            |   6 +
>  drivers/interconnect/tegra/Makefile           |   4 +
>  drivers/interconnect/tegra/tegra-icc-emc.c    | 138 ++++++++++
>  drivers/interconnect/tegra/tegra-icc-mc.c     | 130 +++++++++
>  drivers/memory/tegra/mc.c                     |   4 +
>  drivers/memory/tegra/tegra124-emc.c           |  28 +-
>  drivers/memory/tegra/tegra124.c               |  16 ++
>  drivers/memory/tegra/tegra20-emc.c            |  91 ++++---
>  drivers/memory/tegra/tegra20.c                |  14 +
>  drivers/memory/tegra/tegra30-emc.c            |  34 ++-
>  drivers/memory/tegra/tegra30.c                |  14 +
>  include/dt-bindings/interconnect/tegra-icc.h  |  11 +
>  include/soc/tegra/mc.h                        |  26 ++
>  33 files changed, 883 insertions(+), 58 deletions(-)
>  create mode 100644 drivers/interconnect/tegra/Kconfig
>  create mode 100644 drivers/interconnect/tegra/Makefile
>  create mode 100644 drivers/interconnect/tegra/tegra-icc-emc.c
>  create mode 100644 drivers/interconnect/tegra/tegra-icc-mc.c
>  create mode 100644 include/dt-bindings/interconnect/tegra-icc.h
> 
> -- 
> 2.23.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v1 02/29] dt-bindings: memory: tegra20: emc: Document new interconnect property
  2019-11-18 20:02 ` [PATCH v1 02/29] dt-bindings: memory: tegra20: emc: " Dmitry Osipenko
@ 2019-11-19  6:21   ` Thierry Reding
  2019-11-19 16:57     ` Dmitry Osipenko
  0 siblings, 1 reply; 46+ messages in thread
From: Thierry Reding @ 2019-11-19  6:21 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jonathan Hunter, Peter De Schrijver, Mikko Perttunen,
	Georgi Djakov, Rob Herring, linux-tegra, linux-pm, linux-kernel,
	dri-devel, devicetree

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

On Mon, Nov 18, 2019 at 11:02:20PM +0300, Dmitry Osipenko wrote:
> External memory controller is interconnected with memory controller and
> with external memory. Document new interconnect property which designates
> external memory controller as interconnect provider.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  .../bindings/memory-controllers/nvidia,tegra20-emc.txt        | 4 ++++
>  1 file changed, 4 insertions(+)

Do we really want to describe this particular connection? It's pretty
static and the only real connection here is the EMC frequency, so the
whole interconnect infrastructure seems a bit overkill.

Sounds to me like we could piggyback on top of the existing
nvidia,memory-controller property of the EMC to make the connection.

Thierry

> 
> diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.txt b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.txt
> index add95367640b..7566d883f921 100644
> --- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.txt
> +++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.txt
> @@ -12,6 +12,9 @@ Properties:
>    irrespective of ram-code configuration.
>  - interrupts : Should contain EMC General interrupt.
>  - clocks : Should contain EMC clock.
> +- #interconnect-cells : Should be 1. This cell represents external memory
> +  interconnect. The assignments may be found in header file
> +  <dt-bindings/interconnect/tegra-icc.h>.
>  
>  Child device nodes describe the memory settings for different configurations and clock rates.
>  
> @@ -20,6 +23,7 @@ Example:
>  	memory-controller@7000f400 {
>  		#address-cells = < 1 >;
>  		#size-cells = < 0 >;
> +		#interconnect-cells = < 1 >;
>  		compatible = "nvidia,tegra20-emc";
>  		reg = <0x7000f4000 0x200>;
>  		interrupts = <0 78 0x04>;
> -- 
> 2.23.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v1 08/29] dt-bindings: interconnect: tegra: Add initial IDs
  2019-11-18 20:02 ` [PATCH v1 08/29] dt-bindings: interconnect: tegra: Add initial IDs Dmitry Osipenko
@ 2019-11-19  6:25   ` Thierry Reding
  2019-11-19 16:56     ` Dmitry Osipenko
  0 siblings, 1 reply; 46+ messages in thread
From: Thierry Reding @ 2019-11-19  6:25 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jonathan Hunter, Peter De Schrijver, Mikko Perttunen,
	Georgi Djakov, Rob Herring, linux-tegra, linux-pm, linux-kernel,
	dri-devel, devicetree

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

On Mon, Nov 18, 2019 at 11:02:26PM +0300, Dmitry Osipenko wrote:
> Define interconnect IDs for memory controller (MC), external memory
> controller (EMC), external memory (EMEM) and memory clients of display
> controllers (DC).
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  include/dt-bindings/interconnect/tegra-icc.h | 11 +++++++++++
>  1 file changed, 11 insertions(+)
>  create mode 100644 include/dt-bindings/interconnect/tegra-icc.h

There was a bit of discussion regarding this for a recent patch that I
was working on, see:

	http://patchwork.ozlabs.org/project/linux-tegra/list/?series=140318

I'd rather not use an additional set of definitions for this. The memory
controller already has a set of native IDs for memory clients that I
think we can reuse for this.

I've only added these client IDs for Tegra194 because that's where we
need it to actually describe a specific hardware quirk, but I can come
up with the equivalent for older chips as well.

Thierry

> diff --git a/include/dt-bindings/interconnect/tegra-icc.h b/include/dt-bindings/interconnect/tegra-icc.h
> new file mode 100644
> index 000000000000..e6b6a819434a
> --- /dev/null
> +++ b/include/dt-bindings/interconnect/tegra-icc.h
> @@ -0,0 +1,11 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef DT_BINDINGS_ICC_TEGRA_H
> +#define DT_BINDINGS_ICC_TEGRA_H
> +
> +#define TEGRA_ICC_EMC			0
> +#define TEGRA_ICC_EMEM			1
> +#define TEGRA_ICC_MC			2
> +#define TEGRA_ICC_MC_DC			3
> +#define TEGRA_ICC_MC_DCB		4
> +
> +#endif
> -- 
> 2.23.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v1 11/29] ARM: tegra: Add interconnect properties to Tegra124 device-tree
  2019-11-18 20:02 ` [PATCH v1 11/29] ARM: tegra: Add interconnect properties to Tegra124 device-tree Dmitry Osipenko
@ 2019-11-19  6:27   ` Thierry Reding
  0 siblings, 0 replies; 46+ messages in thread
From: Thierry Reding @ 2019-11-19  6:27 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jonathan Hunter, Peter De Schrijver, Mikko Perttunen,
	Georgi Djakov, Rob Herring, linux-tegra, linux-pm, linux-kernel,
	dri-devel, devicetree

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

On Mon, Nov 18, 2019 at 11:02:29PM +0300, Dmitry Osipenko wrote:
> Add interconnect properties to the memory controller, external memory
> controller and the display controller nodes to describe interconnection
> of these nodes.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  arch/arm/boot/dts/tegra124.dtsi | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
> index 413bfb981de8..5069af3011cc 100644
> --- a/arch/arm/boot/dts/tegra124.dtsi
> +++ b/arch/arm/boot/dts/tegra124.dtsi
> @@ -3,6 +3,7 @@
>  #include <dt-bindings/gpio/tegra-gpio.h>
>  #include <dt-bindings/memory/tegra124-mc.h>
>  #include <dt-bindings/pinctrl/pinctrl-tegra.h>
> +#include <dt-bindings/interconnect/tegra-icc.h>
>  #include <dt-bindings/interrupt-controller/arm-gic.h>
>  #include <dt-bindings/reset/tegra124-car.h>
>  #include <dt-bindings/thermal/tegra124-soctherm.h>
> @@ -111,6 +112,9 @@
>  			iommus = <&mc TEGRA_SWGROUP_DC>;
>  
>  			nvidia,head = <0>;
> +
> +			interconnects = <&mc TEGRA_ICC_MC_DC &emc TEGRA_ICC_EMEM>;
> +			interconnect-names = "dma-mem";

I don't think this is quite correct. The display controller is not
connected to the EMC. Instead, requests go to the MC which then forwards
them to the EMC. So I think we really only need the one connection here.
There are some clients that are read/write and they may need extra
entries, but all connections from memory clients should be to the MC,
not the EMC.

Thierry

>  		};
>  
>  		dc@54240000 {
> @@ -126,6 +130,9 @@
>  			iommus = <&mc TEGRA_SWGROUP_DCB>;
>  
>  			nvidia,head = <1>;
> +
> +			interconnects = <&mc TEGRA_ICC_MC_DCB &emc TEGRA_ICC_EMEM>;
> +			interconnect-names = "dma-mem";
>  		};
>  
>  		hdmi: hdmi@54280000 {
> @@ -620,6 +627,7 @@
>  		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
>  
>  		#iommu-cells = <1>;
> +		#interconnect-cells = <1>;
>  	};
>  
>  	emc: emc@7001b000 {
> @@ -627,6 +635,8 @@
>  		reg = <0x0 0x7001b000 0x0 0x1000>;
>  
>  		nvidia,memory-controller = <&mc>;
> +
> +		#interconnect-cells = <1>;
>  	};
>  
>  	sata@70020000 {
> -- 
> 2.23.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v1 12/29] interconnect: Add memory interconnection providers for NVIDIA Tegra SoCs
  2019-11-18 20:02 ` [PATCH v1 12/29] interconnect: Add memory interconnection providers for NVIDIA Tegra SoCs Dmitry Osipenko
@ 2019-11-19  6:30   ` Thierry Reding
  2019-11-19 16:58     ` Dmitry Osipenko
  2019-11-19  6:31   ` Thierry Reding
  1 sibling, 1 reply; 46+ messages in thread
From: Thierry Reding @ 2019-11-19  6:30 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jonathan Hunter, Peter De Schrijver, Mikko Perttunen,
	Georgi Djakov, Rob Herring, linux-tegra, linux-pm, linux-kernel,
	dri-devel, devicetree

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

On Mon, Nov 18, 2019 at 11:02:30PM +0300, Dmitry Osipenko wrote:
> All NVIDIA Tegra SoCs have identical topology in regards to memory
> interconnection between memory clients and memory controllers.
> The memory controller (MC) and external memory controller (EMC) are
> providing memory clients with required memory bandwidth. The memory
> controller performs arbitration between memory clients, while the
> external memory controller transfers data from/to DRAM and pipes that
> data from/to memory controller. Memory controller interconnect provider
> aggregates bandwidth requests from memory clients and sends the aggregated
> request to EMC provider that scales DRAM frequency in order to satisfy the
> bandwidth requirement. Memory controller provider could adjust hardware
> configuration for a more optimal arbitration depending on bandwidth
> requirements from memory clients, but this is unimplemented for now.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  drivers/interconnect/Kconfig               |   1 +
>  drivers/interconnect/Makefile              |   1 +
>  drivers/interconnect/tegra/Kconfig         |   6 +
>  drivers/interconnect/tegra/Makefile        |   4 +
>  drivers/interconnect/tegra/tegra-icc-emc.c | 138 +++++++++++++++++++++
>  drivers/interconnect/tegra/tegra-icc-mc.c  | 130 +++++++++++++++++++
>  include/soc/tegra/mc.h                     |  26 ++++
>  7 files changed, 306 insertions(+)
>  create mode 100644 drivers/interconnect/tegra/Kconfig
>  create mode 100644 drivers/interconnect/tegra/Makefile
>  create mode 100644 drivers/interconnect/tegra/tegra-icc-emc.c
>  create mode 100644 drivers/interconnect/tegra/tegra-icc-mc.c

Why does this have to be separate from the memory controller driver in
drivers/memory/tegra? It seems like this requires a bunch of boilerplate
just so that this code can live in the drivers/interconnect directory.
If Georgi doesn't insist, I'd prefer if we carried this code directly in
the drivers/memory/tegra directory so that we don't have so many
indirections.

Also, and I already briefly mentioned this in another reply, I think we
don't need two providers here. The only one we're really interested in
is the memory-client to memory-controller paths. The MC to EMC path is
static.

Thierry

> diff --git a/drivers/interconnect/Kconfig b/drivers/interconnect/Kconfig
> index bfa4ca3ab7a9..b11ca09665bb 100644
> --- a/drivers/interconnect/Kconfig
> +++ b/drivers/interconnect/Kconfig
> @@ -12,5 +12,6 @@ menuconfig INTERCONNECT
>  if INTERCONNECT
>  
>  source "drivers/interconnect/qcom/Kconfig"
> +source "drivers/interconnect/tegra/Kconfig"
>  
>  endif
> diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile
> index 28f2ab0824d5..a37d419e262c 100644
> --- a/drivers/interconnect/Makefile
> +++ b/drivers/interconnect/Makefile
> @@ -4,3 +4,4 @@ icc-core-objs				:= core.o
>  
>  obj-$(CONFIG_INTERCONNECT)		+= icc-core.o
>  obj-$(CONFIG_INTERCONNECT_QCOM)		+= qcom/
> +obj-$(CONFIG_INTERCONNECT_TEGRA)	+= tegra/
> diff --git a/drivers/interconnect/tegra/Kconfig b/drivers/interconnect/tegra/Kconfig
> new file mode 100644
> index 000000000000..b724781da71e
> --- /dev/null
> +++ b/drivers/interconnect/tegra/Kconfig
> @@ -0,0 +1,6 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +config INTERCONNECT_TEGRA
> +	bool "NVIDIA Tegra interconnect drivers"
> +	depends on ARCH_TEGRA || COMPILE_TEST
> +	help
> +	  Say Y here to enable support for NVIDIA Tegra interconnect drivers.
> diff --git a/drivers/interconnect/tegra/Makefile b/drivers/interconnect/tegra/Makefile
> new file mode 100644
> index 000000000000..74ff2e53dbdc
> --- /dev/null
> +++ b/drivers/interconnect/tegra/Makefile
> @@ -0,0 +1,4 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +obj-$(CONFIG_INTERCONNECT_TEGRA) += tegra-icc-mc.o
> +obj-$(CONFIG_INTERCONNECT_TEGRA) += tegra-icc-emc.o
> diff --git a/drivers/interconnect/tegra/tegra-icc-emc.c b/drivers/interconnect/tegra/tegra-icc-emc.c
> new file mode 100644
> index 000000000000..b594ce811153
> --- /dev/null
> +++ b/drivers/interconnect/tegra/tegra-icc-emc.c
> @@ -0,0 +1,138 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Author: Dmitry Osipenko <digetx@gmail.com>
> + * Copyright (C) 2019 GRATE-DRIVER project
> + */
> +
> +#include <dt-bindings/interconnect/tegra-icc.h>
> +
> +#include <linux/clk.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/interconnect-provider.h>
> +#include <linux/kernel.h>
> +#include <linux/of.h>
> +
> +#include <soc/tegra/mc.h>
> +
> +struct tegra_emc_provider {
> +	struct icc_provider provider;
> +	struct clk *clk;
> +	unsigned int dram_data_bus_width_bytes;
> +};
> +
> +static inline struct tegra_emc_provider *
> +to_tegra_emc_provider(struct icc_provider *provider)
> +{
> +	return container_of(provider, struct tegra_emc_provider, provider);
> +}
> +
> +static struct icc_node *
> +tegra_emc_of_icc_xlate_onecell(struct of_phandle_args *spec, void *data)
> +{
> +	struct icc_provider *provider = data;
> +	struct icc_node *node;
> +
> +	list_for_each_entry(node, &provider->nodes, node_list) {
> +		if (node->id == spec->args[0])
> +			return node;
> +	}
> +
> +	return ERR_PTR(-EINVAL);
> +}
> +
> +static int tegra_emc_icc_set(struct icc_node *src, struct icc_node *dst)
> +{
> +	struct tegra_emc_provider *emc = to_tegra_emc_provider(dst->provider);
> +	unsigned long long rate = icc_units_to_bps(dst->avg_bw);
> +	unsigned int ddr = 2;
> +	int err;
> +
> +	do_div(rate, ddr * emc->dram_data_bus_width_bytes);
> +	rate = min_t(u64, rate, U32_MAX);
> +
> +	err = clk_set_min_rate(emc->clk, rate);
> +	if (err)
> +		return err;
> +
> +	err = clk_set_rate(emc->clk, rate);
> +	if (err)
> +		return err;
> +
> +	return 0;
> +}
> +
> +static int tegra_emc_icc_aggregate(struct icc_node *node,
> +				   u32 tag, u32 avg_bw, u32 peak_bw,
> +				   u32 *agg_avg, u32 *agg_peak)
> +{
> +	*agg_avg = min((u64)avg_bw + (*agg_avg), (u64)U32_MAX);
> +	*agg_peak = max(*agg_peak, peak_bw);
> +
> +	return 0;
> +}
> +
> +int tegra_icc_emc_setup_interconnect(struct device *emc_dev,
> +				     unsigned int dram_data_bus_width_bytes)
> +{
> +	struct tegra_emc_provider *emc;
> +	struct icc_node *node, *tmp;
> +	int err;
> +
> +	emc = devm_kzalloc(emc_dev, sizeof(*emc), GFP_KERNEL);
> +	if (!emc)
> +		return -ENOMEM;
> +
> +	emc->clk = devm_clk_get(emc_dev, "emc");
> +	err = PTR_ERR_OR_ZERO(emc->clk);
> +	if (err)
> +		return err;
> +
> +	emc->dram_data_bus_width_bytes = dram_data_bus_width_bytes;
> +
> +	emc->provider.dev = emc_dev;
> +	emc->provider.set = tegra_emc_icc_set;
> +	emc->provider.data = &emc->provider;
> +	emc->provider.xlate = tegra_emc_of_icc_xlate_onecell;
> +	emc->provider.aggregate = tegra_emc_icc_aggregate;
> +
> +	err = icc_provider_add(&emc->provider);
> +	if (err)
> +		return err;
> +
> +	/* create External Memory Controller node */
> +	node = icc_node_create(TEGRA_ICC_EMC);
> +	err = PTR_ERR_OR_ZERO(node);
> +	if (err)
> +		goto del_provider;
> +
> +	node->name = "EMC";
> +	icc_node_add(node, &emc->provider);
> +
> +	/* link External Memory Controller with External Memory */
> +	err = icc_link_create(node, TEGRA_ICC_EMEM);
> +	if (err)
> +		goto destroy_nodes;
> +
> +	/* create External Memory node */
> +	node = icc_node_create(TEGRA_ICC_EMEM);
> +	err = PTR_ERR_OR_ZERO(node);
> +	if (err)
> +		goto destroy_nodes;
> +
> +	node->name = "EMEM";
> +	icc_node_add(node, &emc->provider);
> +
> +	return 0;
> +
> +destroy_nodes:
> +	list_for_each_entry_safe(node, tmp, &emc->provider.nodes, node_list) {
> +		icc_node_del(node);
> +		icc_node_destroy(node->id);
> +	}
> +
> +del_provider:
> +	icc_provider_del(&emc->provider);
> +
> +	return err;
> +}
> diff --git a/drivers/interconnect/tegra/tegra-icc-mc.c b/drivers/interconnect/tegra/tegra-icc-mc.c
> new file mode 100644
> index 000000000000..f1ff8f98def3
> --- /dev/null
> +++ b/drivers/interconnect/tegra/tegra-icc-mc.c
> @@ -0,0 +1,130 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Author: Dmitry Osipenko <digetx@gmail.com>
> + * Copyright (C) 2019 GRATE-DRIVER project
> + */
> +
> +#include <dt-bindings/interconnect/tegra-icc.h>
> +
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/interconnect-provider.h>
> +#include <linux/of.h>
> +
> +#include <soc/tegra/mc.h>
> +
> +static struct icc_node *
> +tegra_mc_of_icc_xlate_onecell(struct of_phandle_args *spec, void *data)
> +{
> +	struct icc_provider *provider = data;
> +	struct icc_node *node;
> +
> +	list_for_each_entry(node, &provider->nodes, node_list) {
> +		if (node->id == spec->args[0])
> +			return node;
> +	}
> +
> +	return ERR_PTR(-EINVAL);
> +}
> +
> +static int tegra_mc_icc_set(struct icc_node *src, struct icc_node *dst)
> +{
> +	return 0;
> +}
> +
> +static int tegra_mc_icc_aggregate(struct icc_node *node,
> +				  u32 tag, u32 avg_bw, u32 peak_bw,
> +				  u32 *agg_avg, u32 *agg_peak)
> +{
> +	*agg_avg = min((u64)avg_bw + (*agg_avg), (u64)U32_MAX);
> +	*agg_peak = max(*agg_peak, peak_bw);
> +
> +	return 0;
> +}
> +
> +/*
> + * Memory Controller (MC) has few Memory Clients that are issuing memory
> + * bandwidth allocation requests to the MC interconnect provider. The MC
> + * provider aggregates the requests and then sends the aggregated request
> + * up to the External Memory Controller (EMC) interconnect provider which
> + * re-configures hardware interface to External Memory (EMEM) in accordance
> + * to the required bandwidth.
> + *
> + * Memory interconnect topology:
> + *
> + *               +----+
> + *   +-----+     |    |
> + *   | GPU +---->+    |
> + *   +-----+     |    |
> + *               |    |     +-----+     +------+
> + *    ...        | MC +---->+ EMC +---->+ EMEM |
> + *               |    |     +-----+     +------+
> + *  +------+     |    |
> + *  | DISP +---->+    |
> + *  +------+     |    |
> + *               +----+
> + */
> +int tegra_icc_mc_setup_interconnect(struct tegra_mc *mc)
> +{
> +	struct icc_provider *provider;
> +	struct icc_node *node, *tmp;
> +	unsigned int i;
> +	int err;
> +
> +	provider = devm_kzalloc(mc->dev, sizeof(*provider), GFP_KERNEL);
> +	if (!provider)
> +		return -ENOMEM;
> +
> +	provider->dev = mc->dev;
> +	provider->set = tegra_mc_icc_set;
> +	provider->data = provider;
> +	provider->xlate = tegra_mc_of_icc_xlate_onecell;
> +	provider->aggregate = tegra_mc_icc_aggregate;
> +
> +	err = icc_provider_add(provider);
> +	if (err)
> +		return err;
> +
> +	/* create Memory Controller node */
> +	node = icc_node_create(TEGRA_ICC_MC);
> +	err = PTR_ERR_OR_ZERO(node);
> +	if (err)
> +		goto del_provider;
> +
> +	node->name = "MC";
> +	icc_node_add(node, provider);
> +
> +	/* link Memory Controller with External Memory Controller */
> +	err = icc_link_create(node, TEGRA_ICC_EMC);
> +	if (err)
> +		goto destroy_nodes;
> +
> +	for (i = 0; i < mc->soc->num_icc_nodes; i++) {
> +		/* create MC client node */
> +		node = icc_node_create(mc->soc->icc_nodes[i].id);
> +		err = PTR_ERR_OR_ZERO(node);
> +		if (err)
> +			goto destroy_nodes;
> +
> +		node->name = mc->soc->icc_nodes[i].name;
> +		icc_node_add(node, provider);
> +
> +		/* link Memory Client with Memory Controller */
> +		err = icc_link_create(node, TEGRA_ICC_MC);
> +		if (err)
> +			goto destroy_nodes;
> +	}
> +
> +	return 0;
> +
> +destroy_nodes:
> +	list_for_each_entry_safe(node, tmp, &provider->nodes, node_list) {
> +		icc_node_del(node);
> +		icc_node_destroy(node->id);
> +	}
> +
> +del_provider:
> +	icc_provider_del(provider);
> +
> +	return err;
> +}
> diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h
> index 1238e35653d1..593954324259 100644
> --- a/include/soc/tegra/mc.h
> +++ b/include/soc/tegra/mc.h
> @@ -141,6 +141,11 @@ struct tegra_mc_reset_ops {
>  			    const struct tegra_mc_reset *rst);
>  };
>  
> +struct tegra_mc_icc_node {
> +	const char *name;
> +	unsigned int id;
> +};
> +
>  struct tegra_mc_soc {
>  	const struct tegra_mc_client *clients;
>  	unsigned int num_clients;
> @@ -160,6 +165,9 @@ struct tegra_mc_soc {
>  	const struct tegra_mc_reset_ops *reset_ops;
>  	const struct tegra_mc_reset *resets;
>  	unsigned int num_resets;
> +
> +	const struct tegra_mc_icc_node *icc_nodes;
> +	unsigned int num_icc_nodes;
>  };
>  
>  struct tegra_mc {
> @@ -184,4 +192,22 @@ struct tegra_mc {
>  int tegra_mc_write_emem_configuration(struct tegra_mc *mc, unsigned long rate);
>  unsigned int tegra_mc_get_emem_device_count(struct tegra_mc *mc);
>  
> +#ifdef CONFIG_INTERCONNECT_TEGRA
> +int tegra_icc_mc_setup_interconnect(struct tegra_mc *mc);
> +int tegra_icc_emc_setup_interconnect(struct device *emc_dev,
> +				     unsigned int dram_data_bus_width_bytes);
> +#else
> +static inline int tegra_icc_mc_setup_interconnect(struct tegra_mc *mc);
> +{
> +	return 0;
> +}
> +
> +static inline int
> +tegra_icc_emc_setup_interconnect(struct device *emc_dev,
> +				 unsigned int dram_data_bus_width_bytes)
> +{
> +	return 0;
> +}
> +#endif
> +
>  #endif /* __SOC_TEGRA_MC_H__ */
> -- 
> 2.23.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v1 12/29] interconnect: Add memory interconnection providers for NVIDIA Tegra SoCs
  2019-11-18 20:02 ` [PATCH v1 12/29] interconnect: Add memory interconnection providers for NVIDIA Tegra SoCs Dmitry Osipenko
  2019-11-19  6:30   ` Thierry Reding
@ 2019-11-19  6:31   ` Thierry Reding
  2019-11-19 16:59     ` Dmitry Osipenko
  1 sibling, 1 reply; 46+ messages in thread
From: Thierry Reding @ 2019-11-19  6:31 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jonathan Hunter, Peter De Schrijver, Mikko Perttunen,
	Georgi Djakov, Rob Herring, linux-tegra, linux-pm, linux-kernel,
	dri-devel, devicetree

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

On Mon, Nov 18, 2019 at 11:02:30PM +0300, Dmitry Osipenko wrote:
[...]
> diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h
> index 1238e35653d1..593954324259 100644
> --- a/include/soc/tegra/mc.h
> +++ b/include/soc/tegra/mc.h
> @@ -141,6 +141,11 @@ struct tegra_mc_reset_ops {
>  			    const struct tegra_mc_reset *rst);
>  };
>  
> +struct tegra_mc_icc_node {
> +	const char *name;
> +	unsigned int id;
> +};
> +
>  struct tegra_mc_soc {
>  	const struct tegra_mc_client *clients;
>  	unsigned int num_clients;
> @@ -160,6 +165,9 @@ struct tegra_mc_soc {
>  	const struct tegra_mc_reset_ops *reset_ops;
>  	const struct tegra_mc_reset *resets;
>  	unsigned int num_resets;
> +
> +	const struct tegra_mc_icc_node *icc_nodes;
> +	unsigned int num_icc_nodes;
>  };
>  
>  struct tegra_mc {
> @@ -184,4 +192,22 @@ struct tegra_mc {
>  int tegra_mc_write_emem_configuration(struct tegra_mc *mc, unsigned long rate);
>  unsigned int tegra_mc_get_emem_device_count(struct tegra_mc *mc);
>  
> +#ifdef CONFIG_INTERCONNECT_TEGRA
> +int tegra_icc_mc_setup_interconnect(struct tegra_mc *mc);
> +int tegra_icc_emc_setup_interconnect(struct device *emc_dev,
> +				     unsigned int dram_data_bus_width_bytes);
> +#else
> +static inline int tegra_icc_mc_setup_interconnect(struct tegra_mc *mc);
> +{
> +	return 0;
> +}
> +
> +static inline int
> +tegra_icc_emc_setup_interconnect(struct device *emc_dev,
> +				 unsigned int dram_data_bus_width_bytes)
> +{
> +	return 0;
> +}
> +#endif

Is there really any reason why we should make this support optional? It
seems to me like we would always want this enabled once it's tested and
known to work.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v1 14/29] memory: tegra: Add interconnect nodes for Terga20 display controllers
  2019-11-18 20:02 ` [PATCH v1 14/29] memory: tegra: Add interconnect nodes for Terga20 display controllers Dmitry Osipenko
@ 2019-11-19  6:34   ` Thierry Reding
  0 siblings, 0 replies; 46+ messages in thread
From: Thierry Reding @ 2019-11-19  6:34 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jonathan Hunter, Peter De Schrijver, Mikko Perttunen,
	Georgi Djakov, Rob Herring, linux-tegra, linux-pm, linux-kernel,
	dri-devel, devicetree

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

On Mon, Nov 18, 2019 at 11:02:32PM +0300, Dmitry Osipenko wrote:
> Add initial interconnect nodes that allow display controller driver
> to perform memory bandwidth requests using interconnect API.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  drivers/memory/tegra/tegra20.c | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c
> index a8098bff91d9..dfcd9fdb7ce7 100644
> --- a/drivers/memory/tegra/tegra20.c
> +++ b/drivers/memory/tegra/tegra20.c
> @@ -3,6 +3,7 @@
>   * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
>   */
>  
> +#include <dt-bindings/interconnect/tegra-icc.h>
>  #include <dt-bindings/memory/tegra20-mc.h>
>  
>  #include "mc.h"
> @@ -280,6 +281,17 @@ static const struct tegra_mc_reset_ops tegra20_mc_reset_ops = {
>  	.reset_status = tegra20_mc_reset_status,
>  };
>  
> +#define TEGRA20_MC_ICC(_name)				\
> +	{						\
> +		.name = #_name,				\
> +		.id = TEGRA_ICC_MC_##_name,		\
> +	}
> +
> +static const struct tegra_mc_icc_node tegra20_mc_icc_nodes[] = {
> +	TEGRA20_MC_ICC(DC),
> +	TEGRA20_MC_ICC(DCB),
> +};
> +
>  const struct tegra_mc_soc tegra20_mc_soc = {
>  	.clients = tegra20_mc_clients,
>  	.num_clients = ARRAY_SIZE(tegra20_mc_clients),
> @@ -290,4 +302,6 @@ const struct tegra_mc_soc tegra20_mc_soc = {
>  	.reset_ops = &tegra20_mc_reset_ops,
>  	.resets = tegra20_mc_resets,
>  	.num_resets = ARRAY_SIZE(tegra20_mc_resets),
> +	.icc_nodes = tegra20_mc_icc_nodes,
> +	.num_icc_nodes = ARRAY_SIZE(tegra20_mc_icc_nodes),
>  };

As I mentioned, we already have most (if not all) of the information
that we need for this in the various struct tegra_mc_client tables.
Those tables also contain some definitions for latency allowance
registers that we are eventually going to need to do more tweaking as
you suggested in your cover letter.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v1 08/29] dt-bindings: interconnect: tegra: Add initial IDs
  2019-11-19  6:25   ` Thierry Reding
@ 2019-11-19 16:56     ` Dmitry Osipenko
  2019-11-21 17:14       ` Dmitry Osipenko
  0 siblings, 1 reply; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-19 16:56 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Jonathan Hunter, Peter De Schrijver, Mikko Perttunen,
	Georgi Djakov, Rob Herring, linux-tegra, linux-pm, linux-kernel,
	dri-devel, devicetree

19.11.2019 09:25, Thierry Reding пишет:
> On Mon, Nov 18, 2019 at 11:02:26PM +0300, Dmitry Osipenko wrote:
>> Define interconnect IDs for memory controller (MC), external memory
>> controller (EMC), external memory (EMEM) and memory clients of display
>> controllers (DC).
>>
>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>> ---
>>  include/dt-bindings/interconnect/tegra-icc.h | 11 +++++++++++
>>  1 file changed, 11 insertions(+)
>>  create mode 100644 include/dt-bindings/interconnect/tegra-icc.h


Hello Thierry,

> There was a bit of discussion regarding this for a recent patch that I
> was working on, see:
> 
> 	http://patchwork.ozlabs.org/project/linux-tegra/list/?series=140318

Thank you very much for the link.

> I'd rather not use an additional set of definitions for this. The memory
> controller already has a set of native IDs for memory clients that I
> think we can reuse for this.

I missed that it's fine to have multiple ICC connections defined
per-path, at quick glance looks like indeed it should be fine to re-use
MC IDs.

> I've only added these client IDs for Tegra194 because that's where we
> need it to actually describe a specific hardware quirk, but I can come
> up with the equivalent for older chips as well.

Older Tegra SoCs have hardware units connected to MC through AHB bus,
like USB for example. These units do not have MC client IDs and there is
no MC ID defined for the AHB bus either, but probably it won't be a
problem to define IDs for them if will be necessary.

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

* Re: [PATCH v1 02/29] dt-bindings: memory: tegra20: emc: Document new interconnect property
  2019-11-19  6:21   ` Thierry Reding
@ 2019-11-19 16:57     ` Dmitry Osipenko
  0 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-19 16:57 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Jonathan Hunter, Peter De Schrijver, Mikko Perttunen,
	Georgi Djakov, Rob Herring, linux-tegra, linux-pm, linux-kernel,
	dri-devel, devicetree

19.11.2019 09:21, Thierry Reding пишет:
> On Mon, Nov 18, 2019 at 11:02:20PM +0300, Dmitry Osipenko wrote:
>> External memory controller is interconnected with memory controller and
>> with external memory. Document new interconnect property which designates
>> external memory controller as interconnect provider.
>>
>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>> ---
>>  .../bindings/memory-controllers/nvidia,tegra20-emc.txt        | 4 ++++
>>  1 file changed, 4 insertions(+)
> 
> Do we really want to describe this particular connection? It's pretty
> static and the only real connection here is the EMC frequency, so the
> whole interconnect infrastructure seems a bit overkill.
> 
> Sounds to me like we could piggyback on top of the existing
> nvidia,memory-controller property of the EMC to make the connection.

Ultimately each memory client talks to EMEM through MC and EMC, although
it should be okay to ignore the EMEM from a driver's / software perspective.

[snip]

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

* Re: [PATCH v1 23/29] memory: tegra124-emc: Register as interconnect provider
  2019-11-18 20:02 ` [PATCH v1 23/29] memory: tegra124-emc: Register as interconnect provider Dmitry Osipenko
@ 2019-11-19 16:57   ` Dmitry Osipenko
  0 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-19 16:57 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Peter De Schrijver,
	Mikko Perttunen, Georgi Djakov, Rob Herring
  Cc: linux-tegra, linux-pm, linux-kernel, dri-devel, devicetree

18.11.2019 23:02, Dmitry Osipenko пишет:
> EMC now provides MC with memory bandwidth using interconnect API.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  drivers/memory/tegra/tegra124-emc.c | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
> 
> diff --git a/drivers/memory/tegra/tegra124-emc.c b/drivers/memory/tegra/tegra124-emc.c
> index 2c73260654ba..c9478dcbeece 100644
> --- a/drivers/memory/tegra/tegra124-emc.c
> +++ b/drivers/memory/tegra/tegra124-emc.c
> @@ -25,6 +25,7 @@
>  #define EMC_FBIO_CFG5				0x104
>  #define	EMC_FBIO_CFG5_DRAM_TYPE_MASK		0x3
>  #define	EMC_FBIO_CFG5_DRAM_TYPE_SHIFT		0
> +#define EMC_FBIO_CFG5_DRAM_WIDTH_X64		BIT(4)
>  
>  #define EMC_INTSTATUS				0x0
>  #define EMC_INTSTATUS_CLKCHANGE_COMPLETE	BIT(4)
> @@ -1080,11 +1081,28 @@ static void emc_debugfs_init(struct device *dev, struct tegra_emc *emc)
>  		dev_err(dev, "failed to create debugfs entry\n");
>  }
>  
> +static unsigned int emc_dram_data_bus_width_bytes(struct tegra_emc *emc)
> +{
> +	unsigned int bus_width;
> +	u32 emc_cfg;
> +
> +	emc_cfg = readl_relaxed(emc->regs + EMC_FBIO_CFG5);
> +	if (emc_cfg & EMC_FBIO_CFG5_DRAM_WIDTH_X64)
> +		bus_width = 64;
> +	else
> +		bus_width = 32;

Looks like I got a bit confused while was looking at TRMs before, seems
this width is unrelated to the EMC channel at all. I'll try to revisit
this again.

> +	dev_info(emc->dev, "DRAM data-bus width: %ubit\n", bus_width);
> +
> +	return bus_width / 8;
> +}
> +
>  static int tegra_emc_probe(struct platform_device *pdev)
>  {
>  	struct platform_device *mc;
>  	struct device_node *np;
>  	struct tegra_emc *emc;
> +	unsigned int bus_width;
>  	u32 ram_code;
>  	int err;
>  
> @@ -1146,6 +1164,12 @@ static int tegra_emc_probe(struct platform_device *pdev)
>  	if (IS_ENABLED(CONFIG_DEBUG_FS))
>  		emc_debugfs_init(&pdev->dev, emc);
>  
> +	bus_width = emc_dram_data_bus_width_bytes(emc);
> +
> +	err = tegra_icc_emc_setup_interconnect(&pdev->dev, bus_width);
> +	if (err)
> +		dev_err(&pdev->dev, "failed to initialize ICC: %d\n", err);
> +
>  	return 0;
>  };
>  
> 


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

* Re: [PATCH v1 12/29] interconnect: Add memory interconnection providers for NVIDIA Tegra SoCs
  2019-11-19  6:30   ` Thierry Reding
@ 2019-11-19 16:58     ` Dmitry Osipenko
  2019-11-21 17:33       ` Dmitry Osipenko
  0 siblings, 1 reply; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-19 16:58 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Jonathan Hunter, Peter De Schrijver, Mikko Perttunen,
	Georgi Djakov, Rob Herring, linux-tegra, linux-pm, linux-kernel,
	dri-devel, devicetree

19.11.2019 09:30, Thierry Reding пишет:
> On Mon, Nov 18, 2019 at 11:02:30PM +0300, Dmitry Osipenko wrote:
>> All NVIDIA Tegra SoCs have identical topology in regards to memory
>> interconnection between memory clients and memory controllers.
>> The memory controller (MC) and external memory controller (EMC) are
>> providing memory clients with required memory bandwidth. The memory
>> controller performs arbitration between memory clients, while the
>> external memory controller transfers data from/to DRAM and pipes that
>> data from/to memory controller. Memory controller interconnect provider
>> aggregates bandwidth requests from memory clients and sends the aggregated
>> request to EMC provider that scales DRAM frequency in order to satisfy the
>> bandwidth requirement. Memory controller provider could adjust hardware
>> configuration for a more optimal arbitration depending on bandwidth
>> requirements from memory clients, but this is unimplemented for now.
>>
>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>> ---
>>  drivers/interconnect/Kconfig               |   1 +
>>  drivers/interconnect/Makefile              |   1 +
>>  drivers/interconnect/tegra/Kconfig         |   6 +
>>  drivers/interconnect/tegra/Makefile        |   4 +
>>  drivers/interconnect/tegra/tegra-icc-emc.c | 138 +++++++++++++++++++++
>>  drivers/interconnect/tegra/tegra-icc-mc.c  | 130 +++++++++++++++++++
>>  include/soc/tegra/mc.h                     |  26 ++++
>>  7 files changed, 306 insertions(+)
>>  create mode 100644 drivers/interconnect/tegra/Kconfig
>>  create mode 100644 drivers/interconnect/tegra/Makefile
>>  create mode 100644 drivers/interconnect/tegra/tegra-icc-emc.c
>>  create mode 100644 drivers/interconnect/tegra/tegra-icc-mc.c
> 
> Why does this have to be separate from the memory controller driver in
> drivers/memory/tegra? It seems like this requires a bunch of boilerplate
> just so that this code can live in the drivers/interconnect directory.

It fits with the IOMMU separation. To me that it's a bit nicer to have
the separation for the ICC as well, but having ICC within memory
controller driver also will be fine.

Indeed it looks like there is not much in the MC's provider code right
now, but maybe more stuff will be added later on.

> If Georgi doesn't insist, I'd prefer if we carried this code directly in
> the drivers/memory/tegra directory so that we don't have so many
> indirections.
> 
> Also, and I already briefly mentioned this in another reply, I think we
> don't need two providers here. The only one we're really interested in
> is the memory-client to memory-controller paths. The MC to EMC path is
> static.

Perhaps it is fine to drop EMC path, I'll revisit it.

[snip]

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

* Re: [PATCH v1 12/29] interconnect: Add memory interconnection providers for NVIDIA Tegra SoCs
  2019-11-19  6:31   ` Thierry Reding
@ 2019-11-19 16:59     ` Dmitry Osipenko
  0 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-19 16:59 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Jonathan Hunter, Peter De Schrijver, Mikko Perttunen,
	Georgi Djakov, Rob Herring, linux-tegra, linux-pm, linux-kernel,
	dri-devel, devicetree

19.11.2019 09:31, Thierry Reding пишет:
> On Mon, Nov 18, 2019 at 11:02:30PM +0300, Dmitry Osipenko wrote:
> [...]
>> diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h
>> index 1238e35653d1..593954324259 100644
>> --- a/include/soc/tegra/mc.h
>> +++ b/include/soc/tegra/mc.h
>> @@ -141,6 +141,11 @@ struct tegra_mc_reset_ops {
>>  			    const struct tegra_mc_reset *rst);
>>  };
>>  
>> +struct tegra_mc_icc_node {
>> +	const char *name;
>> +	unsigned int id;
>> +};
>> +
>>  struct tegra_mc_soc {
>>  	const struct tegra_mc_client *clients;
>>  	unsigned int num_clients;
>> @@ -160,6 +165,9 @@ struct tegra_mc_soc {
>>  	const struct tegra_mc_reset_ops *reset_ops;
>>  	const struct tegra_mc_reset *resets;
>>  	unsigned int num_resets;
>> +
>> +	const struct tegra_mc_icc_node *icc_nodes;
>> +	unsigned int num_icc_nodes;
>>  };
>>  
>>  struct tegra_mc {
>> @@ -184,4 +192,22 @@ struct tegra_mc {
>>  int tegra_mc_write_emem_configuration(struct tegra_mc *mc, unsigned long rate);
>>  unsigned int tegra_mc_get_emem_device_count(struct tegra_mc *mc);
>>  
>> +#ifdef CONFIG_INTERCONNECT_TEGRA
>> +int tegra_icc_mc_setup_interconnect(struct tegra_mc *mc);
>> +int tegra_icc_emc_setup_interconnect(struct device *emc_dev,
>> +				     unsigned int dram_data_bus_width_bytes);
>> +#else
>> +static inline int tegra_icc_mc_setup_interconnect(struct tegra_mc *mc);
>> +{
>> +	return 0;
>> +}
>> +
>> +static inline int
>> +tegra_icc_emc_setup_interconnect(struct device *emc_dev,
>> +				 unsigned int dram_data_bus_width_bytes)
>> +{
>> +	return 0;
>> +}
>> +#endif
> 
> Is there really any reason why we should make this support optional? It
> seems to me like we would always want this enabled once it's tested and
> known to work.

There is always some room for bugs, should be better to have an option
to disable ICC entirely (IMO).

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

* Re: [PATCH v1 08/29] dt-bindings: interconnect: tegra: Add initial IDs
  2019-11-19 16:56     ` Dmitry Osipenko
@ 2019-11-21 17:14       ` Dmitry Osipenko
  2019-11-25 11:32         ` Thierry Reding
  0 siblings, 1 reply; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-21 17:14 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Jonathan Hunter, Peter De Schrijver, Mikko Perttunen,
	Georgi Djakov, Rob Herring, linux-tegra, linux-pm, linux-kernel,
	dri-devel, devicetree

19.11.2019 19:56, Dmitry Osipenko пишет:
> 19.11.2019 09:25, Thierry Reding пишет:
>> On Mon, Nov 18, 2019 at 11:02:26PM +0300, Dmitry Osipenko wrote:
>>> Define interconnect IDs for memory controller (MC), external memory
>>> controller (EMC), external memory (EMEM) and memory clients of display
>>> controllers (DC).
>>>
>>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>>> ---
>>>  include/dt-bindings/interconnect/tegra-icc.h | 11 +++++++++++
>>>  1 file changed, 11 insertions(+)
>>>  create mode 100644 include/dt-bindings/interconnect/tegra-icc.h
> 
> 
> Hello Thierry,
> 
>> There was a bit of discussion regarding this for a recent patch that I
>> was working on, see:
>>
>> 	http://patchwork.ozlabs.org/project/linux-tegra/list/?series=140318
> 
> Thank you very much for the link.
> 
>> I'd rather not use an additional set of definitions for this. The memory
>> controller already has a set of native IDs for memory clients that I
>> think we can reuse for this.
> 
> I missed that it's fine to have multiple ICC connections defined
> per-path, at quick glance looks like indeed it should be fine to re-use
> MC IDs.

Well, it is not quite correct to have multiple connections per-path.

Please take look at interconnect's binding and core.c:

  1. there should be one src->dst connection per-path
  2. each connection should comprise of one source and one destination nodes

>> I've only added these client IDs for Tegra194 because that's where we
>> need it to actually describe a specific hardware quirk, but I can come
>> up with the equivalent for older chips as well.
> 
> Older Tegra SoCs have hardware units connected to MC through AHB bus,
> like USB for example. These units do not have MC client IDs and there is
> no MC ID defined for the AHB bus either, but probably it won't be a
> problem to define IDs for them if will be necessary.
> 

Since interconnect binding requires to define both source and
destination nodes for the path, then MC IDs are not enough in order to
define interconnect path because these IDs represent only the source
nodes. Destination node should be either EMC or EMEM.

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

* Re: [PATCH v1 12/29] interconnect: Add memory interconnection providers for NVIDIA Tegra SoCs
  2019-11-19 16:58     ` Dmitry Osipenko
@ 2019-11-21 17:33       ` Dmitry Osipenko
  0 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-21 17:33 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Jonathan Hunter, Peter De Schrijver, Mikko Perttunen,
	Georgi Djakov, Rob Herring, linux-tegra, linux-pm, linux-kernel,
	dri-devel, devicetree

19.11.2019 19:58, Dmitry Osipenko пишет:
> 19.11.2019 09:30, Thierry Reding пишет:
>> On Mon, Nov 18, 2019 at 11:02:30PM +0300, Dmitry Osipenko wrote:
>>> All NVIDIA Tegra SoCs have identical topology in regards to memory
>>> interconnection between memory clients and memory controllers.
>>> The memory controller (MC) and external memory controller (EMC) are
>>> providing memory clients with required memory bandwidth. The memory
>>> controller performs arbitration between memory clients, while the
>>> external memory controller transfers data from/to DRAM and pipes that
>>> data from/to memory controller. Memory controller interconnect provider
>>> aggregates bandwidth requests from memory clients and sends the aggregated
>>> request to EMC provider that scales DRAM frequency in order to satisfy the
>>> bandwidth requirement. Memory controller provider could adjust hardware
>>> configuration for a more optimal arbitration depending on bandwidth
>>> requirements from memory clients, but this is unimplemented for now.
>>>
>>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>>> ---
>>>  drivers/interconnect/Kconfig               |   1 +
>>>  drivers/interconnect/Makefile              |   1 +
>>>  drivers/interconnect/tegra/Kconfig         |   6 +
>>>  drivers/interconnect/tegra/Makefile        |   4 +
>>>  drivers/interconnect/tegra/tegra-icc-emc.c | 138 +++++++++++++++++++++
>>>  drivers/interconnect/tegra/tegra-icc-mc.c  | 130 +++++++++++++++++++
>>>  include/soc/tegra/mc.h                     |  26 ++++
>>>  7 files changed, 306 insertions(+)
>>>  create mode 100644 drivers/interconnect/tegra/Kconfig
>>>  create mode 100644 drivers/interconnect/tegra/Makefile
>>>  create mode 100644 drivers/interconnect/tegra/tegra-icc-emc.c
>>>  create mode 100644 drivers/interconnect/tegra/tegra-icc-mc.c
>>
>> Why does this have to be separate from the memory controller driver in
>> drivers/memory/tegra? It seems like this requires a bunch of boilerplate
>> just so that this code can live in the drivers/interconnect directory.
> 
> It fits with the IOMMU separation. To me that it's a bit nicer to have
> the separation for the ICC as well, but having ICC within memory
> controller driver also will be fine.
> 
> Indeed it looks like there is not much in the MC's provider code right
> now, but maybe more stuff will be added later on.
> 
>> If Georgi doesn't insist, I'd prefer if we carried this code directly in
>> the drivers/memory/tegra directory so that we don't have so many
>> indirections.
>>
>> Also, and I already briefly mentioned this in another reply, I think we
>> don't need two providers here. The only one we're really interested in
>> is the memory-client to memory-controller paths. The MC to EMC path is
>> static.
> 
> Perhaps it is fine to drop EMC path, I'll revisit it.
> 
> [snip]

One advantage of having both MC and EMC as ICC providers is that there
won't be a need to mess with a custom coupling of MC-EMC drivers
together because interconnect API naturally takes care of the coupling
for us by telling ICC users to defer until both providers are registered.

I'll take another look at this over the weekend, but for now my v1
variant looks appropriate in terms of a better hardware description and
implementation in the code.

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

* Re: [PATCH v1 08/29] dt-bindings: interconnect: tegra: Add initial IDs
  2019-11-21 17:14       ` Dmitry Osipenko
@ 2019-11-25 11:32         ` Thierry Reding
  2019-11-28 20:06           ` Dmitry Osipenko
  0 siblings, 1 reply; 46+ messages in thread
From: Thierry Reding @ 2019-11-25 11:32 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Jonathan Hunter, Peter De Schrijver, Mikko Perttunen,
	Georgi Djakov, Rob Herring, linux-tegra, linux-pm, linux-kernel,
	dri-devel, devicetree

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

On Thu, Nov 21, 2019 at 08:14:35PM +0300, Dmitry Osipenko wrote:
> 19.11.2019 19:56, Dmitry Osipenko пишет:
> > 19.11.2019 09:25, Thierry Reding пишет:
> >> On Mon, Nov 18, 2019 at 11:02:26PM +0300, Dmitry Osipenko wrote:
> >>> Define interconnect IDs for memory controller (MC), external memory
> >>> controller (EMC), external memory (EMEM) and memory clients of display
> >>> controllers (DC).
> >>>
> >>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> >>> ---
> >>>  include/dt-bindings/interconnect/tegra-icc.h | 11 +++++++++++
> >>>  1 file changed, 11 insertions(+)
> >>>  create mode 100644 include/dt-bindings/interconnect/tegra-icc.h
> > 
> > 
> > Hello Thierry,
> > 
> >> There was a bit of discussion regarding this for a recent patch that I
> >> was working on, see:
> >>
> >> 	http://patchwork.ozlabs.org/project/linux-tegra/list/?series=140318
> > 
> > Thank you very much for the link.
> > 
> >> I'd rather not use an additional set of definitions for this. The memory
> >> controller already has a set of native IDs for memory clients that I
> >> think we can reuse for this.
> > 
> > I missed that it's fine to have multiple ICC connections defined
> > per-path, at quick glance looks like indeed it should be fine to re-use
> > MC IDs.
> 
> Well, it is not quite correct to have multiple connections per-path.
> 
> Please take look at interconnect's binding and core.c:
> 
>   1. there should be one src->dst connection per-path
>   2. each connection should comprise of one source and one destination nodes
> 
> >> I've only added these client IDs for Tegra194 because that's where we
> >> need it to actually describe a specific hardware quirk, but I can come
> >> up with the equivalent for older chips as well.
> > 
> > Older Tegra SoCs have hardware units connected to MC through AHB bus,
> > like USB for example. These units do not have MC client IDs and there is
> > no MC ID defined for the AHB bus either, but probably it won't be a
> > problem to define IDs for them if will be necessary.
> > 
> 
> Since interconnect binding requires to define both source and
> destination nodes for the path, then MC IDs are not enough in order to
> define interconnect path because these IDs represent only the source
> nodes. Destination node should be either EMC or EMEM.

This doesn't really map well to Tegra. The source of the path is always
the device and the destination is always the memory controller. We also
can have multiple paths between a device and the memory controller. The
typical case is to have at least a read and a write path, but there are
a number of devices that have multiple read and/or multiple write paths
to the memory controller.

Or perhaps I'm looking at this the wrong way, and what we really ought
to describe is the paths with MC sitting in the middle. So it'd be
something like:

	MC ID --- source ---> MC --- destination ---> EMC

for write paths and:

	EMC --- source ---> MC --- destination ---> MC ID

for read paths. I have no idea what would be a good connection ID for
EMC, since I don't think MC really differentiates at that level. Perhaps
#interconnect-cells = <0> for EMC would be appropriate.

This would make the bindings look more like this, taking a random sample
from the above series:

	ethernet@2490000 {
		...
		interconnects = <&emc &mc TEGRA194_MEMORY_CLIENT_EQOSR>,
				<&mc TEGRA194_MEMORY_CLIENT_EQOSW &emc>;
		interconnect-names = "dma-mem", "dma-mem";
		...
	};

In words, the above would mean that for the ethernet device there is one
path (a read slave interface) where data flows from the EMC through the
MC to the device with memory client ID TEGRA194_MEMORY_CLIENT_EQOSR. The
second path (a write slave interface) describes data flowing from the
device (with memory client ID TEGRA194_MEMORY_CLIENT_EQOSW) through the
MC and towards the EMC.

Irrespective of the above, I think we definitely need to keep separate
IDs for read and write paths because each of them have separate controls
for arbitration and latency allowance. So each of those may need to be
separately configurable.

Does that make sense?

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v1 08/29] dt-bindings: interconnect: tegra: Add initial IDs
  2019-11-25 11:32         ` Thierry Reding
@ 2019-11-28 20:06           ` Dmitry Osipenko
  0 siblings, 0 replies; 46+ messages in thread
From: Dmitry Osipenko @ 2019-11-28 20:06 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Jonathan Hunter, Peter De Schrijver, Mikko Perttunen,
	Georgi Djakov, Rob Herring, linux-tegra, linux-pm, linux-kernel,
	dri-devel, devicetree

25.11.2019 14:32, Thierry Reding пишет:
> On Thu, Nov 21, 2019 at 08:14:35PM +0300, Dmitry Osipenko wrote:
>> 19.11.2019 19:56, Dmitry Osipenko пишет:
>>> 19.11.2019 09:25, Thierry Reding пишет:
>>>> On Mon, Nov 18, 2019 at 11:02:26PM +0300, Dmitry Osipenko wrote:
>>>>> Define interconnect IDs for memory controller (MC), external memory
>>>>> controller (EMC), external memory (EMEM) and memory clients of display
>>>>> controllers (DC).
>>>>>
>>>>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>>>>> ---
>>>>>  include/dt-bindings/interconnect/tegra-icc.h | 11 +++++++++++
>>>>>  1 file changed, 11 insertions(+)
>>>>>  create mode 100644 include/dt-bindings/interconnect/tegra-icc.h
>>>
>>>
>>> Hello Thierry,
>>>
>>>> There was a bit of discussion regarding this for a recent patch that I
>>>> was working on, see:
>>>>
>>>> 	http://patchwork.ozlabs.org/project/linux-tegra/list/?series=140318
>>>
>>> Thank you very much for the link.
>>>
>>>> I'd rather not use an additional set of definitions for this. The memory
>>>> controller already has a set of native IDs for memory clients that I
>>>> think we can reuse for this.
>>>
>>> I missed that it's fine to have multiple ICC connections defined
>>> per-path, at quick glance looks like indeed it should be fine to re-use
>>> MC IDs.
>>
>> Well, it is not quite correct to have multiple connections per-path.
>>
>> Please take look at interconnect's binding and core.c:
>>
>>   1. there should be one src->dst connection per-path
>>   2. each connection should comprise of one source and one destination nodes
>>
>>>> I've only added these client IDs for Tegra194 because that's where we
>>>> need it to actually describe a specific hardware quirk, but I can come
>>>> up with the equivalent for older chips as well.
>>>
>>> Older Tegra SoCs have hardware units connected to MC through AHB bus,
>>> like USB for example. These units do not have MC client IDs and there is
>>> no MC ID defined for the AHB bus either, but probably it won't be a
>>> problem to define IDs for them if will be necessary.
>>>
>>
>> Since interconnect binding requires to define both source and
>> destination nodes for the path, then MC IDs are not enough in order to
>> define interconnect path because these IDs represent only the source
>> nodes. Destination node should be either EMC or EMEM.
> 
> This doesn't really map well to Tegra. The source of the path is always
> the device and the destination is always the memory controller. We also
> can have multiple paths between a device and the memory controller. The
> typical case is to have at least a read and a write path, but there are
> a number of devices that have multiple read and/or multiple write paths
> to the memory controller.
> 
> Or perhaps I'm looking at this the wrong way, and what we really ought
> to describe is the paths with MC sitting in the middle. So it'd be
> something like:
> 
> 	MC ID --- source ---> MC --- destination ---> EMC

Yes, this should be correct.

> for write paths and:
> 
> 	EMC --- source ---> MC --- destination ---> MC ID

Both write and read paths have the same direction in terms of
interconnect API. The source node requests bandwidth from the
destination node, where source is memory client and destination is EMC/EMEM.

> for read paths. I have no idea what would be a good connection ID for
> EMC, since I don't think MC really differentiates at that level. Perhaps
> #interconnect-cells = <0> for EMC would be appropriate.

It should be fine to define ICC ID for EMC that doesn't overlap with the
memory client IDs, say #1000.

> This would make the bindings look more like this, taking a random sample
> from the above series:
> 
> 	ethernet@2490000 {
> 		...
> 		interconnects = <&emc &mc TEGRA194_MEMORY_CLIENT_EQOSR>,
> 				<&mc TEGRA194_MEMORY_CLIENT_EQOSW &emc>;
> 		interconnect-names = "dma-mem", "dma-mem";
> 		...
> 	};
> 
> In words, the above would mean that for the ethernet device there is one
> path (a read slave interface) where data flows from the EMC through the
> MC to the device with memory client ID TEGRA194_MEMORY_CLIENT_EQOSR. The
> second path (a write slave interface) describes data flowing from the
> device (with memory client ID TEGRA194_MEMORY_CLIENT_EQOSW) through the
> MC and towards the EMC.
> 
> Irrespective of the above, I think we definitely need to keep separate
> IDs for read and write paths because each of them have separate controls
> for arbitration and latency allowance. So each of those may need to be
> separately configurable.
> 
> Does that make sense?

I'll try to update this series to use ICC-path per display plane and see
how it goes.

In general, looks like should be fine to have ICC paths defined per
memory client.

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

end of thread, other threads:[~2019-11-28 20:06 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-18 20:02 [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 01/29] dt-bindings: memory: tegra20: mc: Document new interconnect property Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 02/29] dt-bindings: memory: tegra20: emc: " Dmitry Osipenko
2019-11-19  6:21   ` Thierry Reding
2019-11-19 16:57     ` Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 03/29] dt-bindings: memory: tegra30: mc: " Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 04/29] dt-bindings: memory: tegra30: emc: " Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 05/29] dt-bindings: memory: tegra124: mc: " Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 06/29] dt-bindings: memory: tegra124: emc: " Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 07/29] dt-bindings: host1x: Document new interconnect properties Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 08/29] dt-bindings: interconnect: tegra: Add initial IDs Dmitry Osipenko
2019-11-19  6:25   ` Thierry Reding
2019-11-19 16:56     ` Dmitry Osipenko
2019-11-21 17:14       ` Dmitry Osipenko
2019-11-25 11:32         ` Thierry Reding
2019-11-28 20:06           ` Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 09/29] ARM: tegra: Add interconnect properties to Tegra20 device-tree Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 10/29] ARM: tegra: Add interconnect properties to Tegra30 device-tree Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 11/29] ARM: tegra: Add interconnect properties to Tegra124 device-tree Dmitry Osipenko
2019-11-19  6:27   ` Thierry Reding
2019-11-18 20:02 ` [PATCH v1 12/29] interconnect: Add memory interconnection providers for NVIDIA Tegra SoCs Dmitry Osipenko
2019-11-19  6:30   ` Thierry Reding
2019-11-19 16:58     ` Dmitry Osipenko
2019-11-21 17:33       ` Dmitry Osipenko
2019-11-19  6:31   ` Thierry Reding
2019-11-19 16:59     ` Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 13/29] memory: tegra: Register as interconnect provider Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 14/29] memory: tegra: Add interconnect nodes for Terga20 display controllers Dmitry Osipenko
2019-11-19  6:34   ` Thierry Reding
2019-11-18 20:02 ` [PATCH v1 15/29] memory: tegra: Add interconnect nodes for Terga30 " Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 16/29] memory: tegra: Add interconnect nodes for Terga124 " Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 17/29] memory: tegra20-emc: Use devm_platform_ioremap_resource Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 18/29] memory: tegra20-emc: Continue probing if timings/IRQ are missing in device-tree Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 19/29] memory: tegra20-emc: Register as interconnect provider Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 20/29] memory: tegra30-emc: Continue probing if timings are missing in device-tree Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 21/29] memory: tegra30-emc: Register as interconnect provider Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 22/29] memory: tegra124-emc: Use devm_platform_ioremap_resource Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 23/29] memory: tegra124-emc: Register as interconnect provider Dmitry Osipenko
2019-11-19 16:57   ` Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 24/29] drm/tegra: dc: Use devm_platform_ioremap_resource Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 25/29] drm/tegra: dc: Release PM and RGB output when client's registration fails Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 26/29] drm/tegra: dc: Support memory bandwidth management Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 27/29] ARM: tegra: Enable interconnect API in tegra_defconfig Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 28/29] ARM: multi_v7_defconfig: Enable NVIDIA Tegra interconnect providers Dmitry Osipenko
2019-11-18 20:02 ` [PATCH v1 29/29] MAINTAINERS: Add maintainers for NVIDIA Tegra interconnect drivers Dmitry Osipenko
2019-11-19  6:19 ` [PATCH v1 00/29] Introduce memory interconnect for NVIDIA Tegra SoCs Thierry Reding

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).