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 <gsantosh@codeaurora.org>
Signed-off-by: Rama Aparna Mallavarapu <aparnam@codeaurora.org>
This commit is contained in:
Rama Aparna Mallavarapu
2019-04-23 11:51:53 +05:30
parent cf8acfa8c9
commit 7fef54d3e4
4 changed files with 57 additions and 5 deletions

View File

@ -20,6 +20,7 @@
#include <linux/irq.h>
#include <linux/cpu_pm.h>
#include <linux/cpu.h>
#include <linux/of_fdt.h>
#include "governor.h"
#include "governor_memlat.h"
#include <linux/perf_event.h>
@ -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) {

View File

@ -17,7 +17,9 @@
#include <linux/mutex.h>
#include <linux/interrupt.h>
#include <linux/devfreq.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <trace/events/power.h>
#include <linux/msm-bus.h>
#include <linux/msm-bus-board.h>
@ -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" },
{}
};

View File

@ -18,6 +18,7 @@
#include <linux/mutex.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/devfreq.h>
#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);

View File

@ -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;