Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f34edeef authored by Santosh Mardi's avatar Santosh Mardi
Browse files

devfreq: detect ddr type and add frequency table accordingly



Trinket target support LPDDR3 and LPDDR4 HW supporting different
frequency levels, update devfreq drivers to detect the DDR type
and add frequency tables accordingly.

Change-Id: I5286466274a3e96739b1feecdaccc9bea773d2b8
Signed-off-by: default avatarSantosh Mardi <gsantosh@codeaurora.org>
parent 4f1b5e51
Loading
Loading
Loading
Loading
+24 −1
Original line number Original line Diff line number Diff line
/*
/*
 * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * it under the terms of the GNU General Public License version 2 and
@@ -28,6 +28,7 @@
#include <linux/irq.h>
#include <linux/irq.h>
#include <linux/cpu_pm.h>
#include <linux/cpu_pm.h>
#include <linux/cpu.h>
#include <linux/cpu.h>
#include <linux/of_fdt.h>
#include "governor.h"
#include "governor.h"
#include "governor_memlat.h"
#include "governor_memlat.h"
#include <linux/perf_event.h>
#include <linux/perf_event.h>
@@ -260,6 +261,26 @@ static int get_mask_from_dev_handle(struct platform_device *pdev,
	return ret;
	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)
static int arm_memlat_mon_driver_probe(struct platform_device *pdev)
{
{
	struct device *dev = &pdev->dev;
	struct device *dev = &pdev->dev;
@@ -305,6 +326,8 @@ static int arm_memlat_mon_driver_probe(struct platform_device *pdev)
	hw->start_hwmon = &start_hwmon;
	hw->start_hwmon = &start_hwmon;
	hw->stop_hwmon = &stop_hwmon;
	hw->stop_hwmon = &stop_hwmon;
	hw->get_cnt = &get_cnt;
	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);
	spec = of_device_get_match_data(dev);
	if (spec && spec->is_compute) {
	if (spec && spec->is_compute) {
+63 −2
Original line number Original line Diff line number Diff line
/*
/*
 * Copyright (c) 2013-2014, 2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2014, 2018-2019, The Linux Foundation. All rights reserved.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * it under the terms of the GNU General Public License version 2 and
@@ -25,7 +25,9 @@
#include <linux/mutex.h>
#include <linux/mutex.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/devfreq.h>
#include <linux/devfreq.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <trace/events/power.h>
#include <trace/events/power.h>
#include <linux/msm-bus.h>
#include <linux/msm-bus.h>
#include <linux/msm-bus-board.h>
#include <linux/msm-bus-board.h>
@@ -99,6 +101,62 @@ static int devbw_get_dev_status(struct device *dev,
	return 0;
	return 0;
}
}


#define PROP_OPERATING_POINTS_V2 "operating-points-v2"

static int add_opp_prop_from_child(struct device *dev,
				struct device_node *of_child)
{
	struct property *prop;
	int len = 0, ret = 0;
	void *value;
	const void *p_val;

	p_val = of_get_property(of_child, PROP_OPERATING_POINTS_V2, &len);
	value = devm_kzalloc(dev, len, GFP_KERNEL);
	if (!value)
		return -ENOMEM;
	memcpy(value, p_val, len);
	prop = devm_kzalloc(dev, sizeof(*prop), GFP_KERNEL);
	if (!prop) {
		devm_kfree(dev, value);
		return -ENOMEM;
	}
	prop->name = "operating-points-v2";
	prop->value = value;
	prop->length = len;
	ret = of_add_property(dev->of_node, prop);
	if (ret) {
		devm_kfree(dev, value);
		devm_kfree(dev, prop);
		dev_err(dev, "failed to add property: %d\n", ret);
	}

	return ret;
}

static int parse_child_nodes_for_opp(struct device *dev)
{
	struct device_node *of_child;
	int ddr_type_of = -1;
	int ddr_type = of_fdt_get_ddrtype();
	int ret = -EINVAL;

	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);
			ret = add_opp_prop_from_child(dev, of_child);
			if (ret)
				return ret;
			return dev_pm_opp_of_add_table(dev);
		}
		ret = -ENODEV;
	}
	return ret;
}

#define PROP_PORTS "qcom,src-dst-ports"
#define PROP_PORTS "qcom,src-dst-ports"
#define PROP_ACTIVE "qcom,active-only"
#define PROP_ACTIVE "qcom,active-only"


@@ -154,8 +212,11 @@ int devfreq_add_devbw(struct device *dev)
	p->polling_ms = 50;
	p->polling_ms = 50;
	p->target = devbw_target;
	p->target = devbw_target;
	p->get_dev_status = devbw_get_dev_status;
	p->get_dev_status = devbw_get_dev_status;

	if (of_get_child_count(dev->of_node))
		ret = parse_child_nodes_for_opp(dev);
	else
		ret = dev_pm_opp_of_add_table(dev);
		ret = dev_pm_opp_of_add_table(dev);

	if (ret)
	if (ret)
		dev_err(dev, "Couldn't parse OPP table:%d\n", ret);
		dev_err(dev, "Couldn't parse OPP table:%d\n", ret);


+18 −5
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@
#include <linux/mutex.h>
#include <linux/mutex.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of.h>
#include <linux/devfreq.h>
#include <linux/devfreq.h>
#include "governor.h"
#include "governor.h"
@@ -427,6 +428,7 @@ static struct devfreq_governor devfreq_gov_compute = {


#define NUM_COLS	2
#define NUM_COLS	2
static struct core_dev_map *init_core_dev_map(struct device *dev,
static struct core_dev_map *init_core_dev_map(struct device *dev,
					struct device_node *of_node,
					char *prop_name)
					char *prop_name)
{
{
	int len, nf, i, j;
	int len, nf, i, j;
@@ -434,7 +436,10 @@ static struct core_dev_map *init_core_dev_map(struct device *dev,
	struct core_dev_map *tbl;
	struct core_dev_map *tbl;
	int ret;
	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;
		return NULL;
	len /= sizeof(data);
	len /= sizeof(data);


@@ -448,13 +453,13 @@ static struct core_dev_map *init_core_dev_map(struct device *dev,
		return NULL;
		return NULL;


	for (i = 0, j = 0; i < nf; i++, j += 2) {
	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);
				&data);
		if (ret)
		if (ret)
			return NULL;
			return NULL;
		tbl[i].core_mhz = data / 1000;
		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);
				&data);
		if (ret)
		if (ret)
			return NULL;
			return NULL;
@@ -471,6 +476,7 @@ static struct memlat_node *register_common(struct device *dev,
					   struct memlat_hwmon *hw)
					   struct memlat_hwmon *hw)
{
{
	struct memlat_node *node;
	struct memlat_node *node;
	struct device_node *of_child;


	if (!hw->dev && !hw->of_node)
	if (!hw->dev && !hw->of_node)
		return ERR_PTR(-EINVAL);
		return ERR_PTR(-EINVAL);
@@ -482,7 +488,14 @@ static struct memlat_node *register_common(struct device *dev,
	node->ratio_ceil = 10;
	node->ratio_ceil = 10;
	node->hw = hw;
	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) {
	if (!hw->freq_map) {
		dev_err(dev, "Couldn't find the core-dev freq table!\n");
		dev_err(dev, "Couldn't find the core-dev freq table!\n");
		return ERR_PTR(-EINVAL);
		return ERR_PTR(-EINVAL);
+2 −1
Original line number Original line Diff line number Diff line
/*
/*
 * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2017, 2019, The Linux Foundation. All rights reserved.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * it under the terms of the GNU General Public License version 2 and
@@ -62,6 +62,7 @@ struct memlat_hwmon {
	int (*start_hwmon)(struct memlat_hwmon *hw);
	int (*start_hwmon)(struct memlat_hwmon *hw);
	void (*stop_hwmon)(struct memlat_hwmon *hw);
	void (*stop_hwmon)(struct memlat_hwmon *hw);
	unsigned long (*get_cnt)(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 *dev;
	struct device_node *of_node;
	struct device_node *of_node;