From 7cd1197dac80540965c883bddc1107c2fe6e2436 Mon Sep 17 00:00:00 2001 From: tao zeng Date: Thu, 29 Nov 2018 09:55:14 +0800 Subject: [PATCH] ddr_bandwidth: support multi-ports config for one channel [1/1] 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 --- drivers/amlogic/ddr_tool/ddr_band_op_g12.c | 11 +++++-- drivers/amlogic/ddr_tool/ddr_band_op_gx.c | 8 ++++- drivers/amlogic/ddr_tool/ddr_band_op_gxl.c | 9 ++++-- drivers/amlogic/ddr_tool/ddr_bandwidth.c | 51 ++++++++++++++++++++++-------- include/linux/amlogic/aml_ddr_bandwidth.h | 10 +++--- include/linux/amlogic/ddr_port.h | 2 +- 6 files changed, 66 insertions(+), 25 deletions(-) diff --git a/drivers/amlogic/ddr_tool/ddr_band_op_g12.c b/drivers/amlogic/ddr_tool/ddr_band_op_g12.c index ec0f50f..b49770d 100644 --- a/drivers/amlogic/ddr_tool/ddr_band_op_g12.c +++ b/drivers/amlogic/ddr_tool/ddr_band_op_g12.c @@ -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) diff --git a/drivers/amlogic/ddr_tool/ddr_band_op_gx.c b/drivers/amlogic/ddr_tool/ddr_band_op_gx.c index 387dd55..88b9f6e 100644 --- a/drivers/amlogic/ddr_tool/ddr_band_op_gx.c +++ b/drivers/amlogic/ddr_tool/ddr_band_op_gx.c @@ -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) diff --git a/drivers/amlogic/ddr_tool/ddr_band_op_gxl.c b/drivers/amlogic/ddr_tool/ddr_band_op_gxl.c index c03b7b5..b92a59a 100644 --- a/drivers/amlogic/ddr_tool/ddr_band_op_gxl.c +++ b/drivers/amlogic/ddr_tool/ddr_band_op_gxl.c @@ -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); } diff --git a/drivers/amlogic/ddr_tool/ddr_bandwidth.c b/drivers/amlogic/ddr_tool/ddr_bandwidth.c index d15b0eb..513ed83 100644 --- a/drivers/amlogic/ddr_tool/ddr_bandwidth.c +++ b/drivers/amlogic/ddr_tool/ddr_bandwidth.c @@ -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 __ref 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__); diff --git a/include/linux/amlogic/aml_ddr_bandwidth.h b/include/linux/amlogic/aml_ddr_bandwidth.h index 1235d1e..bde095b 100644 --- a/include/linux/amlogic/aml_ddr_bandwidth.h +++ b/include/linux/amlogic/aml_ddr_bandwidth.h @@ -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 diff --git a/include/linux/amlogic/ddr_port.h b/include/linux/amlogic/ddr_port.h index a50755f..4f0b5c4 100644 --- a/include/linux/amlogic/ddr_port.h +++ b/include/linux/amlogic/ddr_port.h @@ -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 -- 2.7.4