From 7fef54d3e4e2c6a60dc3dc5c7030d533fd3577ca Mon Sep 17 00:00:00 2001 From: Rama Aparna Mallavarapu Date: Tue, 23 Apr 2019 11:51:53 +0530 Subject: [PATCH] devfreq: detect ddr type and add frequency table accordingly Some targets support different DDR types. Detect the DDR type and populate the frequency table accordingly. OPP framework supports opp-supported-hw bit map which allows the selected frequencies to be added to the opp table based on the hardware version check. Implement the same in the bandwidth monitor device so that the right frequencies would be added to the opp table. This patch also adds checks for the latency based device to detect the DDR type at runtime and add the corresponding frequency map. Change-Id: Ice5a0b14da67b3f2f07e98bc7349220da7d4efdb Signed-off-by: Santosh Mardi Signed-off-by: Rama Aparna Mallavarapu --- drivers/devfreq/arm-memlat-mon.c | 23 +++++++++++++++++++++++ drivers/devfreq/devfreq_devbw.c | 15 +++++++++++++++ drivers/devfreq/governor_memlat.c | 23 ++++++++++++++++++----- drivers/devfreq/governor_memlat.h | 1 + 4 files changed, 57 insertions(+), 5 deletions(-) diff --git a/drivers/devfreq/arm-memlat-mon.c b/drivers/devfreq/arm-memlat-mon.c index 4bec02c4b2c9..7eb3ad45e4ce 100644 --- a/drivers/devfreq/arm-memlat-mon.c +++ b/drivers/devfreq/arm-memlat-mon.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "governor.h" #include "governor_memlat.h" #include @@ -252,6 +253,26 @@ static int get_mask_from_dev_handle(struct platform_device *pdev, return ret; } +static struct device_node *parse_child_nodes(struct device *dev) +{ + struct device_node *of_child; + int ddr_type_of = -1; + int ddr_type = of_fdt_get_ddrtype(); + int ret; + + for_each_child_of_node(dev->of_node, of_child) { + ret = of_property_read_u32(of_child, "qcom,ddr-type", + &ddr_type_of); + if (!ret && (ddr_type == ddr_type_of)) { + dev_dbg(dev, + "ddr-type = %d, is matching DT entry\n", + ddr_type_of); + return of_child; + } + } + return NULL; +} + static int arm_memlat_mon_driver_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -297,6 +318,8 @@ static int arm_memlat_mon_driver_probe(struct platform_device *pdev) hw->start_hwmon = &start_hwmon; hw->stop_hwmon = &stop_hwmon; hw->get_cnt = &get_cnt; + if (of_get_child_count(dev->of_node)) + hw->get_child_of_node = &parse_child_nodes; spec = of_device_get_match_data(dev); if (spec && spec->is_compute) { diff --git a/drivers/devfreq/devfreq_devbw.c b/drivers/devfreq/devfreq_devbw.c index 22c3a13f979f..af8440bc0ba8 100644 --- a/drivers/devfreq/devfreq_devbw.c +++ b/drivers/devfreq/devfreq_devbw.c @@ -17,7 +17,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -101,6 +103,8 @@ int devfreq_add_devbw(struct device *dev) u32 ports[MAX_PATHS * 2]; const char *gov_name; int ret, len, i, num_paths; + struct opp_table *opp_table; + u32 version; d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL); if (!d) @@ -147,6 +151,15 @@ int devfreq_add_devbw(struct device *dev) p->target = devbw_target; p->get_dev_status = devbw_get_dev_status; + if (of_device_is_compatible(dev->of_node, "qcom,devbw-ddr")) { + version = (1 << of_fdt_get_ddrtype()); + opp_table = dev_pm_opp_set_supported_hw(dev, &version, 1); + if (IS_ERR(opp_table)) { + dev_err(dev, "Failed to set supported hardware\n"); + return PTR_ERR(opp_table); + } + } + ret = dev_pm_opp_of_add_table(dev); if (ret) dev_err(dev, "Couldn't parse OPP table:%d\n", ret); @@ -203,6 +216,8 @@ static int devfreq_devbw_remove(struct platform_device *pdev) } static const struct of_device_id devbw_match_table[] = { + { .compatible = "qcom,devbw-llcc" }, + { .compatible = "qcom,devbw-ddr" }, { .compatible = "qcom,devbw" }, {} }; diff --git a/drivers/devfreq/governor_memlat.c b/drivers/devfreq/governor_memlat.c index c279ec824031..ba14cb3fc330 100644 --- a/drivers/devfreq/governor_memlat.c +++ b/drivers/devfreq/governor_memlat.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include "governor.h" @@ -419,14 +420,18 @@ static struct devfreq_governor devfreq_gov_compute = { #define NUM_COLS 2 static struct core_dev_map *init_core_dev_map(struct device *dev, - char *prop_name) + struct device_node *of_node, + char *prop_name) { int len, nf, i, j; u32 data; struct core_dev_map *tbl; int ret; - if (!of_find_property(dev->of_node, prop_name, &len)) + if (!of_node) + of_node = dev->of_node; + + if (!of_find_property(of_node, prop_name, &len)) return NULL; len /= sizeof(data); @@ -440,13 +445,13 @@ static struct core_dev_map *init_core_dev_map(struct device *dev, return NULL; for (i = 0, j = 0; i < nf; i++, j += 2) { - ret = of_property_read_u32_index(dev->of_node, prop_name, j, + ret = of_property_read_u32_index(of_node, prop_name, j, &data); if (ret) return NULL; tbl[i].core_mhz = data / 1000; - ret = of_property_read_u32_index(dev->of_node, prop_name, j + 1, + ret = of_property_read_u32_index(of_node, prop_name, j + 1, &data); if (ret) return NULL; @@ -463,6 +468,7 @@ static struct memlat_node *register_common(struct device *dev, struct memlat_hwmon *hw) { struct memlat_node *node; + struct device_node *of_child; if (!hw->dev && !hw->of_node) return ERR_PTR(-EINVAL); @@ -474,7 +480,14 @@ static struct memlat_node *register_common(struct device *dev, node->ratio_ceil = 10; node->hw = hw; - hw->freq_map = init_core_dev_map(dev, "qcom,core-dev-table"); + if (hw->get_child_of_node) { + of_child = hw->get_child_of_node(dev); + hw->freq_map = init_core_dev_map(dev, of_child, + "qcom,core-dev-table"); + } else { + hw->freq_map = init_core_dev_map(dev, NULL, + "qcom,core-dev-table"); + } if (!hw->freq_map) { dev_err(dev, "Couldn't find the core-dev freq table!\n"); return ERR_PTR(-EINVAL); diff --git a/drivers/devfreq/governor_memlat.h b/drivers/devfreq/governor_memlat.h index c3c71a32c9fe..f09625ef2645 100644 --- a/drivers/devfreq/governor_memlat.h +++ b/drivers/devfreq/governor_memlat.h @@ -54,6 +54,7 @@ struct memlat_hwmon { int (*start_hwmon)(struct memlat_hwmon *hw); void (*stop_hwmon)(struct memlat_hwmon *hw); unsigned long (*get_cnt)(struct memlat_hwmon *hw); + struct device_node *(*get_child_of_node)(struct device *dev); struct device *dev; struct device_node *of_node;