Commit 4c277e2f authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'pm-opp'

* pm-opp:
  opp: Don't parse icc paths unnecessarily
  opp: Remove bandwidth votes when target_freq is zero
  opp: core: add regulators enable and disable
  opp: Reorder the code for !target_freq case
  opp: Expose bandwidth information via debugfs
  cpufreq: dt: Add support for interconnect bandwidth scaling
  opp: Update the bandwidth on OPP frequency changes
  opp: Add sanity checks in _read_opp_key()
  opp: Add support for parsing interconnect bandwidth
  interconnect: Remove unused module exit code from core
  interconnect: Disallow interconnect core to be built as a module
  interconnect: Add of_icc_get_by_index() helper function
  OPP: Add helpers for reading the binding properties
  dt-bindings: opp: Introduce opp-peak-kBps and opp-avg-kBps bindings
parents afd8d7c7 4573e9ef
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -83,9 +83,14 @@ properties.

Required properties:
- opp-hz: Frequency in Hz, expressed as a 64-bit big-endian integer. This is a
  required property for all device nodes but devices like power domains. The
  power domain nodes must have another (implementation dependent) property which
  uniquely identifies the OPP nodes.
  required property for all device nodes, unless another "required" property to
  uniquely identify the OPP nodes exists. Devices like power domains must have
  another (implementation dependent) property.

- opp-peak-kBps: Peak bandwidth in kilobytes per second, expressed as an array
  of 32-bit big-endian integers. Each element of the array represents the
  peak bandwidth value of each interconnect path. The number of elements should
  match the number of interconnect paths.

Optional properties:
- opp-microvolt: voltage in micro Volts.
@@ -132,6 +137,12 @@ Optional properties:
- opp-level: A value representing the performance level of the device,
  expressed as a 32-bit integer.

- opp-avg-kBps: Average bandwidth in kilobytes per second, expressed as an array
  of 32-bit big-endian integers. Each element of the array represents the
  average bandwidth value of each interconnect path. The number of elements
  should match the number of interconnect paths. This property is only
  meaningful in OPP tables where opp-peak-kBps is present.

- clock-latency-ns: Specifies the maximum possible transition latency (in
  nanoseconds) for switching to this OPP from any other OPP.

+4 −0
Original line number Diff line number Diff line
@@ -41,3 +41,7 @@ Temperature
Pressure
----------------------------------------
-kpascal	: kilopascal

Throughput
----------------------------------------
-kBps		: kilobytes per second
+4 −0
Original line number Diff line number Diff line
@@ -121,6 +121,10 @@ static int resources_available(void)

	clk_put(cpu_clk);

	ret = dev_pm_opp_of_find_icc_paths(cpu_dev, NULL);
	if (ret)
		return ret;

	name = find_supply_name(cpu_dev);
	/* Platform doesn't require regulator */
	if (!name)
+1 −1
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0-only
menuconfig INTERCONNECT
	tristate "On-Chip Interconnect management support"
	bool "On-Chip Interconnect management support"
	help
	  Support for management of the on-chip interconnects.

+73 −24
Original line number Diff line number Diff line
@@ -351,9 +351,9 @@ static struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec)
}

/**
 * of_icc_get() - get a path handle from a DT node based on name
 * of_icc_get_by_index() - get a path handle from a DT node based on index
 * @dev: device pointer for the consumer device
 * @name: interconnect path name
 * @idx: interconnect path index
 *
 * This function will search for a path between two endpoints and return an
 * icc_path handle on success. Use icc_put() to release constraints when they
@@ -365,13 +365,12 @@ static struct icc_node *of_icc_get_from_provider(struct of_phandle_args *spec)
 * Return: icc_path pointer on success or ERR_PTR() on error. NULL is returned
 * when the API is disabled or the "interconnects" DT property is missing.
 */
struct icc_path *of_icc_get(struct device *dev, const char *name)
struct icc_path *of_icc_get_by_index(struct device *dev, int idx)
{
	struct icc_path *path = ERR_PTR(-EPROBE_DEFER);
	struct icc_path *path;
	struct icc_node *src_node, *dst_node;
	struct device_node *np = NULL;
	struct device_node *np;
	struct of_phandle_args src_args, dst_args;
	int idx = 0;
	int ret;

	if (!dev || !dev->of_node)
@@ -391,12 +390,6 @@ struct icc_path *of_icc_get(struct device *dev, const char *name)
	 * lets support only global ids and extend this in the future if needed
	 * without breaking DT compatibility.
	 */
	if (name) {
		idx = of_property_match_string(np, "interconnect-names", name);
		if (idx < 0)
			return ERR_PTR(idx);
	}

	ret = of_parse_phandle_with_args(np, "interconnects",
					 "#interconnect-cells", idx * 2,
					 &src_args);
@@ -439,12 +432,8 @@ struct icc_path *of_icc_get(struct device *dev, const char *name)
		return path;
	}

	if (name)
		path->name = kstrdup_const(name, GFP_KERNEL);
	else
	path->name = kasprintf(GFP_KERNEL, "%s-%s",
			       src_node->name, dst_node->name);

	if (!path->name) {
		kfree(path);
		return ERR_PTR(-ENOMEM);
@@ -452,6 +441,53 @@ struct icc_path *of_icc_get(struct device *dev, const char *name)

	return path;
}
EXPORT_SYMBOL_GPL(of_icc_get_by_index);

/**
 * of_icc_get() - get a path handle from a DT node based on name
 * @dev: device pointer for the consumer device
 * @name: interconnect path name
 *
 * This function will search for a path between two endpoints and return an
 * icc_path handle on success. Use icc_put() to release constraints when they
 * are not needed anymore.
 * If the interconnect API is disabled, NULL is returned and the consumer
 * drivers will still build. Drivers are free to handle this specifically,
 * but they don't have to.
 *
 * Return: icc_path pointer on success or ERR_PTR() on error. NULL is returned
 * when the API is disabled or the "interconnects" DT property is missing.
 */
struct icc_path *of_icc_get(struct device *dev, const char *name)
{
	struct device_node *np;
	int idx = 0;

	if (!dev || !dev->of_node)
		return ERR_PTR(-ENODEV);

	np = dev->of_node;

	/*
	 * When the consumer DT node do not have "interconnects" property
	 * return a NULL path to skip setting constraints.
	 */
	if (!of_find_property(np, "interconnects", NULL))
		return NULL;

	/*
	 * We use a combination of phandle and specifier for endpoint. For now
	 * lets support only global ids and extend this in the future if needed
	 * without breaking DT compatibility.
	 */
	if (name) {
		idx = of_property_match_string(np, "interconnect-names", name);
		if (idx < 0)
			return ERR_PTR(idx);
	}

	return of_icc_get_by_index(dev, idx);
}
EXPORT_SYMBOL_GPL(of_icc_get);

/**
@@ -478,6 +514,24 @@ void icc_set_tag(struct icc_path *path, u32 tag)
}
EXPORT_SYMBOL_GPL(icc_set_tag);

/**
 * icc_get_name() - Get name of the icc path
 * @path: reference to the path returned by icc_get()
 *
 * This function is used by an interconnect consumer to get the name of the icc
 * path.
 *
 * Returns a valid pointer on success, or NULL otherwise.
 */
const char *icc_get_name(struct icc_path *path)
{
	if (!path)
		return NULL;

	return path->name;
}
EXPORT_SYMBOL_GPL(icc_get_name);

/**
 * icc_set_bw() - set bandwidth constraints on an interconnect path
 * @path: reference to the path returned by icc_get()
@@ -908,12 +962,7 @@ static int __init icc_init(void)
	return 0;
}

static void __exit icc_exit(void)
{
	debugfs_remove_recursive(icc_debugfs_dir);
}
module_init(icc_init);
module_exit(icc_exit);
device_initcall(icc_init);

MODULE_AUTHOR("Georgi Djakov <georgi.djakov@linaro.org>");
MODULE_DESCRIPTION("Interconnect Driver Core");
Loading