Re: [PATCH v5 27/36] memory: tegra-mc: Register as interconnect provider

2020-09-10 Thread Georgi Djakov
On 8/14/20 03:06, Dmitry Osipenko wrote:
> Now memory controller is a memory interconnection provider. This allows us
> to use interconnect API in order to change memory configuration.
> 
> Signed-off-by: Dmitry Osipenko 

Thanks Dmitry! Looks good to me.

Acked-by: Georgi Djakov 
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v5 27/36] memory: tegra-mc: Register as interconnect provider

2020-09-10 Thread Dmitry Osipenko
09.09.2020 11:31, Georgi Djakov пишет:
> On 8/14/20 03:06, Dmitry Osipenko wrote:
>> Now memory controller is a memory interconnection provider. This allows us
>> to use interconnect API in order to change memory configuration.
>>
>> Signed-off-by: Dmitry Osipenko 
> 
> Thanks Dmitry! Looks good to me.
> 
> Acked-by: Georgi Djakov 
> 

Thanks you!
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v5 27/36] memory: tegra-mc: Register as interconnect provider

2020-08-17 Thread Dmitry Osipenko
Now memory controller is a memory interconnection provider. This allows us
to use interconnect API in order to change memory configuration.

Signed-off-by: Dmitry Osipenko 
---
 drivers/memory/tegra/Kconfig |   1 +
 drivers/memory/tegra/mc.c| 118 +++
 drivers/memory/tegra/mc.h|   8 +++
 include/soc/tegra/mc.h   |   3 +
 4 files changed, 130 insertions(+)

diff --git a/drivers/memory/tegra/Kconfig b/drivers/memory/tegra/Kconfig
index 5bf75b316a2f..7055fdef2c32 100644
--- a/drivers/memory/tegra/Kconfig
+++ b/drivers/memory/tegra/Kconfig
@@ -3,6 +3,7 @@ config TEGRA_MC
bool "NVIDIA Tegra Memory Controller support"
default y
depends on ARCH_TEGRA
+   select INTERCONNECT
help
  This driver supports the Memory Controller (MC) hardware found on
  NVIDIA Tegra SoCs.
diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
index 772aa021b5f6..46759ddaa3c9 100644
--- a/drivers/memory/tegra/mc.c
+++ b/drivers/memory/tegra/mc.c
@@ -594,6 +594,122 @@ static __maybe_unused irqreturn_t tegra20_mc_irq(int irq, 
void *data)
return IRQ_HANDLED;
 }
 
+static int tegra_mc_icc_set(struct icc_node *src, struct icc_node *dst)
+{
+   /*
+* The plan is to populate this function with a latency allowness
+* programming sometime later, for now this a dummy callback.
+*/
+   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. Each MC interconnect node represents an
+ * individual Memory Client.
+ *
+ * Memory interconnect topology:
+ *
+ *   ++
+ * ++||
+ * | TEXSRD +--->+|
+ * ++||
+ *   ||+-++--+
+ *...| MC +--->+ EMC +--->+ EMEM |
+ *   ||+-++--+
+ * ++||
+ * | DISP.. +--->+|
+ * ++||
+ *   ++
+ */
+static int tegra_mc_interconnect_setup(struct tegra_mc *mc)
+{
+   struct icc_onecell_data *data;
+   struct icc_node *node;
+   unsigned int num_nodes;
+   unsigned int i;
+   int err;
+
+   /* older device-trees don't have interconnect properties */
+   if (!of_find_property(mc->dev->of_node, "#interconnect-cells", NULL))
+   return 0;
+
+   num_nodes = mc->soc->num_clients;
+
+   data = devm_kzalloc(mc->dev, struct_size(data, nodes, num_nodes),
+   GFP_KERNEL);
+   if (!data)
+   return -ENOMEM;
+
+   mc->provider.dev = mc->dev;
+   mc->provider.set = tegra_mc_icc_set;
+   mc->provider.data = data;
+   mc->provider.xlate = of_icc_xlate_onecell;
+   mc->provider.aggregate = tegra_mc_icc_aggregate;
+
+   err = icc_provider_add(>provider);
+   if (err)
+   goto err_msg;
+
+   /* create Memory Controller node */
+   node = icc_node_create(TEGRA_ICC_MC);
+   err = PTR_ERR_OR_ZERO(node);
+   if (err)
+   goto del_provider;
+
+   node->name = "Memory Controller";
+   icc_node_add(node, >provider);
+
+   /* link Memory Controller to External Memory Controller */
+   err = icc_link_create(node, TEGRA_ICC_EMC);
+   if (err)
+   goto remove_nodes;
+
+   for (i = 0; i < num_nodes; i++) {
+   /* create MC client node */
+   node = icc_node_create(mc->soc->clients[i].id);
+   err = PTR_ERR_OR_ZERO(node);
+   if (err)
+   goto remove_nodes;
+
+   node->name = mc->soc->clients[i].name;
+   icc_node_add(node, >provider);
+
+   /* link Memory Client to Memory Controller */
+   err = icc_link_create(node, TEGRA_ICC_MC);
+   if (err)
+   goto remove_nodes;
+
+   data->nodes[i] = node;
+   }
+   data->num_nodes = num_nodes;
+
+   return 0;
+
+remove_nodes:
+   icc_nodes_remove(>provider);
+del_provider:
+   icc_provider_del(>provider);
+err_msg:
+   dev_err(mc->dev, "failed to initialize ICC: %d\n", err);
+
+   return err;
+}
+
 static int tegra_mc_probe(struct platform_device *pdev)
 {
struct resource *res;
@@ -702,6 +818,8 @@ static int tegra_mc_probe(struct