ddr_bandwidth: support multi-ports config for one channel [1/1]
authortao zeng <tao.zeng@amlogic.com>
Thu, 29 Nov 2018 01:55:14 +0000 (09:55 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Mon, 17 Dec 2018 06:50:12 +0000 (22:50 -0800)
PD#172256

Problem:
ddr bandwidth prot config can only set 1 port for 1 channel. But
dmc controller support measure many ports on 1 channel.

Solution:
Using bit mask to support multi-ports config for one channel.

Verify:
P212

Change-Id: Iad79e6ebd6aeb74b0e31b3f1bee08de4fd557cc1
Signed-off-by: tao zeng <tao.zeng@amlogic.com>
drivers/amlogic/ddr_tool/ddr_band_op_g12.c
drivers/amlogic/ddr_tool/ddr_band_op_gx.c
drivers/amlogic/ddr_tool/ddr_band_op_gxl.c
drivers/amlogic/ddr_tool/ddr_bandwidth.c
include/linux/amlogic/aml_ddr_bandwidth.h
include/linux/amlogic/ddr_port.h

index ec0f50f..b49770d 100644 (file)
@@ -40,12 +40,18 @@ static void g12_dmc_port_config(struct ddr_bandwidth *db, int channel, int port)
                                        DMC_MON_G12_CTRL6, DMC_MON_G12_CTRL8};
        int subport = -1;
 
+       /* clear all port mask */
+       if (port < 0) {
+               writel(0, db->ddr_reg + rp[channel]);
+               writel(0, db->ddr_reg + rs[channel]);
+               return;
+       }
+
        if (port >= PORT_MAJOR)
                subport = port - PORT_MAJOR;
 
        if (subport < 0) {
                val = readl(db->ddr_reg + rp[channel]);
-               val &= ~(0xffffff << 0);
                val |=  (1 << port);
                writel(val, db->ddr_reg + rp[channel]);
                val = 0xffff;
@@ -54,7 +60,6 @@ static void g12_dmc_port_config(struct ddr_bandwidth *db, int channel, int port)
                val = (0x1 << 23);      /* select device */
                writel(val, db->ddr_reg + rp[channel]);
                val = readl(db->ddr_reg + rs[channel]);
-               val &= ~(0xffff);
                val |= (1 << subport);
                writel(val, db->ddr_reg + rs[channel]);
        }
@@ -124,7 +129,7 @@ static void g12_dmc_bandwidth_init(struct ddr_bandwidth *db)
        g12_dmc_bandwidth_enable(db);
 
        for (i = 0; i < db->channels; i++)
-               g12_dmc_port_config(db, i, db->port[i]);
+               g12_dmc_port_config(db, i, -1);
 }
 
 static int g12_handle_irq(struct ddr_bandwidth *db, struct ddr_grant *dg)
index 387dd55..88b9f6e 100644 (file)
@@ -37,6 +37,12 @@ static void gx_dmc_port_config(struct ddr_bandwidth *db, int channel, int port)
        unsigned int val;
        int subport = -1;
 
+       /* set to a unused port to clear bandwidth */
+       if (port < 0) {
+               writel(0x8016ffff, db->ddr_reg + DMC_MON_CTRL2);
+               return;
+       }
+
        if (port >= PORT_MAJOR)
                subport = port - PORT_MAJOR;
 
@@ -89,7 +95,7 @@ static void gx_dmc_bandwidth_init(struct ddr_bandwidth *db)
        writel(db->clock_count, db->ddr_reg + DMC_MON_CTRL3);
        gx_dmc_bandwidth_enable(db);
 
-       gx_dmc_port_config(db, 0, db->port[0]);
+       gx_dmc_port_config(db, 0, -1);
 }
 
 static int gx_handle_irq(struct ddr_bandwidth *db, struct ddr_grant *dg)
index c03b7b5..b92a59a 100644 (file)
@@ -44,9 +44,14 @@ static void gxl_dmc_port_config(struct ddr_bandwidth *db, int channel, int port)
        if (port >= PORT_MAJOR)
                subport = port - PORT_MAJOR;
 
+       /* clear all port mask */
+       if (port < 0) {
+               writel(0, db->ddr_reg + port_reg[channel]);
+               return;
+       }
+
        val = readl(db->ddr_reg + port_reg[channel]);
        if (port < 16) {
-               val &= ~(0xffff << 16);
                val |= ((1 << (16 + port)) | 0xffff);
        } else if (subport > 0) {
                val &= ~(0xffffffff);
@@ -94,7 +99,7 @@ static void gxl_dmc_bandwidth_init(struct ddr_bandwidth *db)
        gxl_dmc_bandwidth_enable(db);
 
        for (i = 0; i < db->channels; i++)
-               gxl_dmc_port_config(db, i, db->port[i]);
+               gxl_dmc_port_config(db, i, -1);
 }
 
 
index e73ee4a..9412335 100644 (file)
@@ -133,15 +133,34 @@ static char *find_port_name(int id)
        return NULL;
 }
 
+static int format_port(char *buf, u64 port_mask)
+{
+       u64 t;
+       int i, size = 0;
+       char *name;
+
+       for (i = 0; i < sizeof(u64) * 8; i++) {
+               t = 1ULL << i;
+               if (port_mask & t) {
+                       name = find_port_name(i);
+                       if (!name)
+                               continue;
+                       size += sprintf(buf + size, "      %s\n", name);
+               }
+       }
+       return size;
+}
+
 static ssize_t ddr_channel_show(struct class *cla,
        struct class_attribute *attr, char *buf)
 {
        int size = 0, i;
 
-       for (i = 0; i < aml_db->channels; i++)
-               size += sprintf(buf + size, "ch %d:%3d, %s\n",
-                               i, aml_db->port[i],
-                               find_port_name(aml_db->port[i]));
+       for (i = 0; i < aml_db->channels; i++) {
+               size += sprintf(buf + size, "ch %d:%16llx: ports:\n",
+                               i, aml_db->port[i]);
+               size += format_port(buf + size, aml_db->port[i]);
+       }
 
        return size;
 }
@@ -156,8 +175,8 @@ static ssize_t ddr_channel_store(struct class *cla,
                return count;
        }
 
-       if (ch >= MAX_CHANNEL ||
-           (ch && aml_db->cpu_type < MESON_CPU_MAJOR_ID_GXTVBB) ||
+       if (ch >= MAX_CHANNEL || ch < 0 ||
+           aml_db->cpu_type < MESON_CPU_MAJOR_ID_GXTVBB ||
            port > MAX_PORTS) {
                pr_info("invalid channel %d or port %d\n", ch, port);
                return count;
@@ -165,7 +184,10 @@ static ssize_t ddr_channel_store(struct class *cla,
 
        if (aml_db->ops && aml_db->ops->config_port) {
                aml_db->ops->config_port(aml_db, ch, port);
-               aml_db->port[ch] = port;
+               if (port < 0) /* clear port set */
+                       aml_db->port[ch] = 0;
+               else
+                       aml_db->port[ch] |= 1ULL << port;
        }
 
        return count;
@@ -226,11 +248,11 @@ static ssize_t mode_store(struct class *cla,
 
        if (val == MODE_AUTODETECT && aml_db->ops && aml_db->ops->config_port) {
                if (aml_db->mali_port[0] >= 0) {
-                       aml_db->port[0] = aml_db->mali_port[0];
+                       aml_db->port[0] = (1ULL << aml_db->mali_port[0]);
                        aml_db->ops->config_port(aml_db, 0, aml_db->port[0]);
                }
                if (aml_db->mali_port[1] >= 0) {
-                       aml_db->port[1] = aml_db->mali_port[1];
+                       aml_db->port[1] = (1ULL << aml_db->mali_port[1]);
                        aml_db->ops->config_port(aml_db, 1, aml_db->port[1]);
                }
        }
@@ -282,8 +304,8 @@ static ssize_t clock_count_store(struct class *cla,
 static ssize_t bandwidth_show(struct class *cla,
        struct class_attribute *attr, char *buf)
 {
-       size_t s = 0, i;
-       int percent, rem;
+       size_t s = 0;
+       int percent, rem, i;
 #define BANDWIDTH_PREFIX "Total bandwidth: %8d KB/s, usage: %2d.%02d%%\n"
 
        if (aml_db->mode != MODE_ENABLE)
@@ -295,8 +317,8 @@ static ssize_t bandwidth_show(struct class *cla,
                        aml_db->total_bandwidth, percent, rem);
 
        for (i = 0; i < aml_db->channels; i++) {
-               s += sprintf(buf + s, "port%d: %8d KB/s\n",
-                               aml_db->port[i], aml_db->bandwidth[i]);
+               s += sprintf(buf + s, "ch:%d port bit:%16llx: %8d KB/s\n",
+                            i, aml_db->port[i], aml_db->bandwidth[i]);
        }
        return s;
 }
@@ -592,6 +614,9 @@ static int __init ddr_bandwidth_probe(struct platform_device *pdev)
                goto inval;
        }
 
+       if (!aml_db->ops->config_port)
+               goto inval;
+
        r = class_register(&aml_ddr_class);
        if (r)
                pr_info("%s, class regist failed\n", __func__);
index 1235d1e..bde095b 100644 (file)
@@ -130,25 +130,25 @@ struct ddr_bandwidth_ops {
 };
 
 struct ddr_bandwidth {
-       void __iomem *ddr_reg;
-       void __iomem *pll_reg;
-       struct class *class;
        unsigned short cpu_type;
        unsigned short real_ports;
        char busy;
        char mode;
        int mali_port[2];
        unsigned int threshold;
-       struct work_struct work_bandwidth;
        unsigned int irq_num;
        unsigned int clock_count;
        unsigned int channels;
-       unsigned int port[MAX_CHANNEL];
        unsigned int bandwidth[MAX_CHANNEL];
        unsigned int total_usage;
        unsigned int total_bandwidth;
+       u64          port[MAX_CHANNEL];
+       void __iomem *ddr_reg;
+       void __iomem *pll_reg;
+       struct class *class;
        struct ddr_port_desc *port_desc;
        struct ddr_bandwidth_ops *ops;
+       struct work_struct work_bandwidth;
 };
 
 #ifdef CONFIG_AMLOGIC_DDR_BANDWIDTH
index a50755f..4f0b5c4 100644 (file)
@@ -18,7 +18,7 @@
 #ifndef __DDR_PORT_DESC_H__
 #define __DDR_PORT_DESC_H__
 
-#define MAX_PORTS                      256
+#define MAX_PORTS                      63
 #define MAX_NAME                       15
 #define PORT_MAJOR                     32