linux/drivers/opp/of.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Generic OPP OF helpers
 *
 * Copyright (C) 2009-2010 Texas Instruments Incorporated.
 *	Nishanth Menon
 *	Romit Dasgupta
 *	Kevin Hilman
 */

#define pr_fmt(fmt)

#include <linux/cpu.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/pm_domain.h>
#include <linux/slab.h>
#include <linux/export.h>
#include <linux/energy_model.h>

#include "opp.h"

/* OPP tables with uninitialized required OPPs, protected by opp_table_lock */
static LIST_HEAD(lazy_opp_tables);

/*
 * Returns opp descriptor node for a device node, caller must
 * do of_node_put().
 */
static struct device_node *_opp_of_get_opp_desc_node(struct device_node *np,
						     int index)
{}

/* Returns opp descriptor node for a device, caller must do of_node_put() */
struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev)
{}
EXPORT_SYMBOL_GPL();

struct opp_table *_managed_opp(struct device *dev, int index)
{}

/* The caller must call dev_pm_opp_put() after the OPP is used */
static struct dev_pm_opp *_find_opp_of_np(struct opp_table *opp_table,
					  struct device_node *opp_np)
{}

static struct device_node *of_parse_required_opp(struct device_node *np,
						 int index)
{}

/* The caller must call dev_pm_opp_put_opp_table() after the table is used */
static struct opp_table *_find_table_of_opp_np(struct device_node *opp_np)
{}

/* Free resources previously acquired by _opp_table_alloc_required_tables() */
static void _opp_table_free_required_tables(struct opp_table *opp_table)
{}

/*
 * Populate all devices and opp tables which are part of "required-opps" list.
 * Checking only the first OPP node should be enough.
 */
static void _opp_table_alloc_required_tables(struct opp_table *opp_table,
					     struct device *dev,
					     struct device_node *opp_np)
{}

void _of_init_opp_table(struct opp_table *opp_table, struct device *dev,
			int index)
{}

void _of_clear_opp_table(struct opp_table *opp_table)
{}

/*
 * Release all resources previously acquired with a call to
 * _of_opp_alloc_required_opps().
 */
static void _of_opp_free_required_opps(struct opp_table *opp_table,
				       struct dev_pm_opp *opp)
{}

void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp)
{}

static int _link_required_opps(struct dev_pm_opp *opp, struct opp_table *opp_table,
			       struct opp_table *required_table, int index)
{}

/* Populate all required OPPs which are part of "required-opps" list */
static int _of_opp_alloc_required_opps(struct opp_table *opp_table,
				       struct dev_pm_opp *opp)
{}

/* Link required OPPs for an individual OPP */
static int lazy_link_required_opps(struct opp_table *opp_table,
				   struct opp_table *new_table, int index)
{}

/* Link required OPPs for all OPPs of the newly added OPP table */
static void lazy_link_required_opp_table(struct opp_table *new_table)
{}

static int _bandwidth_supported(struct device *dev, struct opp_table *opp_table)
{}

int dev_pm_opp_of_find_icc_paths(struct device *dev,
				 struct opp_table *opp_table)
{}
EXPORT_SYMBOL_GPL();

static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table,
			      struct device_node *np)
{}

static u32 *_parse_named_prop(struct dev_pm_opp *opp, struct device *dev,
			      struct opp_table *opp_table,
			      const char *prop_type, bool *triplet)
{}

static u32 *opp_parse_microvolt(struct dev_pm_opp *opp, struct device *dev,
				struct opp_table *opp_table, bool *triplet)
{}

static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
			      struct opp_table *opp_table)
{}

/**
 * dev_pm_opp_of_remove_table() - Free OPP table entries created from static DT
 *				  entries
 * @dev:	device pointer used to lookup OPP table.
 *
 * Free OPPs created using static entries present in DT.
 */
void dev_pm_opp_of_remove_table(struct device *dev)
{}
EXPORT_SYMBOL_GPL();

static int _read_rate(struct dev_pm_opp *new_opp, struct opp_table *opp_table,
		      struct device_node *np)
{}

static int _read_bw(struct dev_pm_opp *new_opp, struct opp_table *opp_table,
		    struct device_node *np, bool peak)
{}

static int _read_opp_key(struct dev_pm_opp *new_opp,
			 struct opp_table *opp_table, struct device_node *np)
{}

/**
 * _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
 * @opp_table:	OPP table
 * @dev:	device for which we do this operation
 * @np:		device node
 *
 * This function adds an opp definition to the opp table and returns status. The
 * opp can be controlled using dev_pm_opp_enable/disable functions and may be
 * removed by dev_pm_opp_remove.
 *
 * Return:
 * Valid OPP pointer:
 *		On success
 * NULL:
 *		Duplicate OPPs (both freq and volt are same) and opp->available
 *		OR if the OPP is not supported by hardware.
 * ERR_PTR(-EEXIST):
 *		Freq are same and volt are different OR
 *		Duplicate OPPs (both freq and volt are same) and !opp->available
 * ERR_PTR(-ENOMEM):
 *		Memory allocation failure
 * ERR_PTR(-EINVAL):
 *		Failed parsing the OPP node
 */
static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
		struct device *dev, struct device_node *np)
{}

/* Initializes OPP tables based on new bindings */
static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
{}

/* Initializes OPP tables based on old-deprecated bindings */
static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table)
{}

static int _of_add_table_indexed(struct device *dev, int index)
{}

static void devm_pm_opp_of_table_release(void *data)
{}

static int _devm_of_add_table_indexed(struct device *dev, int index)
{}

/**
 * devm_pm_opp_of_add_table() - Initialize opp table from device tree
 * @dev:	device pointer used to lookup OPP table.
 *
 * Register the initial OPP table with the OPP library for given device.
 *
 * The opp_table structure will be freed after the device is destroyed.
 *
 * Return:
 * 0		On success OR
 *		Duplicate OPPs (both freq and volt are same) and opp->available
 * -EEXIST	Freq are same and volt are different OR
 *		Duplicate OPPs (both freq and volt are same) and !opp->available
 * -ENOMEM	Memory allocation failure
 * -ENODEV	when 'operating-points' property is not found or is invalid data
 *		in device node.
 * -ENODATA	when empty 'operating-points' property is found
 * -EINVAL	when invalid entries are found in opp-v2 table
 */
int devm_pm_opp_of_add_table(struct device *dev)
{}
EXPORT_SYMBOL_GPL();

/**
 * dev_pm_opp_of_add_table() - Initialize opp table from device tree
 * @dev:	device pointer used to lookup OPP table.
 *
 * Register the initial OPP table with the OPP library for given device.
 *
 * Return:
 * 0		On success OR
 *		Duplicate OPPs (both freq and volt are same) and opp->available
 * -EEXIST	Freq are same and volt are different OR
 *		Duplicate OPPs (both freq and volt are same) and !opp->available
 * -ENOMEM	Memory allocation failure
 * -ENODEV	when 'operating-points' property is not found or is invalid data
 *		in device node.
 * -ENODATA	when empty 'operating-points' property is found
 * -EINVAL	when invalid entries are found in opp-v2 table
 */
int dev_pm_opp_of_add_table(struct device *dev)
{}
EXPORT_SYMBOL_GPL();

/**
 * dev_pm_opp_of_add_table_indexed() - Initialize indexed opp table from device tree
 * @dev:	device pointer used to lookup OPP table.
 * @index:	Index number.
 *
 * Register the initial OPP table with the OPP library for given device only
 * using the "operating-points-v2" property.
 *
 * Return: Refer to dev_pm_opp_of_add_table() for return values.
 */
int dev_pm_opp_of_add_table_indexed(struct device *dev, int index)
{}
EXPORT_SYMBOL_GPL();

/**
 * devm_pm_opp_of_add_table_indexed() - Initialize indexed opp table from device tree
 * @dev:	device pointer used to lookup OPP table.
 * @index:	Index number.
 *
 * This is a resource-managed variant of dev_pm_opp_of_add_table_indexed().
 */
int devm_pm_opp_of_add_table_indexed(struct device *dev, int index)
{}
EXPORT_SYMBOL_GPL();

/* CPU device specific helpers */

/**
 * dev_pm_opp_of_cpumask_remove_table() - Removes OPP table for @cpumask
 * @cpumask:	cpumask for which OPP table needs to be removed
 *
 * This removes the OPP tables for CPUs present in the @cpumask.
 * This should be used only to remove static entries created from DT.
 */
void dev_pm_opp_of_cpumask_remove_table(const struct cpumask *cpumask)
{}
EXPORT_SYMBOL_GPL();

/**
 * dev_pm_opp_of_cpumask_add_table() - Adds OPP table for @cpumask
 * @cpumask:	cpumask for which OPP table needs to be added.
 *
 * This adds the OPP tables for CPUs present in the @cpumask.
 */
int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask)
{}
EXPORT_SYMBOL_GPL();

/*
 * Works only for OPP v2 bindings.
 *
 * Returns -ENOENT if operating-points-v2 bindings aren't supported.
 */
/**
 * dev_pm_opp_of_get_sharing_cpus() - Get cpumask of CPUs sharing OPPs with
 *				      @cpu_dev using operating-points-v2
 *				      bindings.
 *
 * @cpu_dev:	CPU device for which we do this operation
 * @cpumask:	cpumask to update with information of sharing CPUs
 *
 * This updates the @cpumask with CPUs that are sharing OPPs with @cpu_dev.
 *
 * Returns -ENOENT if operating-points-v2 isn't present for @cpu_dev.
 */
int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev,
				   struct cpumask *cpumask)
{}
EXPORT_SYMBOL_GPL();

/**
 * of_get_required_opp_performance_state() - Search for required OPP and return its performance state.
 * @np: Node that contains the "required-opps" property.
 * @index: Index of the phandle to parse.
 *
 * Returns the performance state of the OPP pointed out by the "required-opps"
 * property at @index in @np.
 *
 * Return: Zero or positive performance state on success, otherwise negative
 * value on errors.
 */
int of_get_required_opp_performance_state(struct device_node *np, int index)
{}
EXPORT_SYMBOL_GPL();

/**
 * dev_pm_opp_of_has_required_opp - Find out if a required-opps exists.
 * @dev: The device to investigate.
 *
 * Returns true if the device's node has a "operating-points-v2" property and if
 * the corresponding node for the opp-table describes opp nodes that uses the
 * "required-opps" property.
 *
 * Return: True if a required-opps is present, else false.
 */
bool dev_pm_opp_of_has_required_opp(struct device *dev)
{}

/**
 * dev_pm_opp_get_of_node() - Gets the DT node corresponding to an opp
 * @opp:	opp for which DT node has to be returned for
 *
 * Return: DT node corresponding to the opp, else 0 on success.
 *
 * The caller needs to put the node with of_node_put() after using it.
 */
struct device_node *dev_pm_opp_get_of_node(struct dev_pm_opp *opp)
{}
EXPORT_SYMBOL_GPL();

/*
 * Callback function provided to the Energy Model framework upon registration.
 * It provides the power used by @dev at @kHz if it is the frequency of an
 * existing OPP, or at the frequency of the first OPP above @kHz otherwise
 * (see dev_pm_opp_find_freq_ceil()). This function updates @kHz to the ceiled
 * frequency and @uW to the associated power.
 *
 * Returns 0 on success or a proper -EINVAL value in case of error.
 */
static int __maybe_unused
_get_dt_power(struct device *dev, unsigned long *uW, unsigned long *kHz)
{}

/**
 * dev_pm_opp_calc_power() - Calculate power value for device with EM
 * @dev		: Device for which an Energy Model has to be registered
 * @uW		: New power value that is calculated
 * @kHz		: Frequency for which the new power is calculated
 *
 * This computes the power estimated by @dev at @kHz if it is the frequency
 * of an existing OPP, or at the frequency of the first OPP above @kHz otherwise
 * (see dev_pm_opp_find_freq_ceil()). This function updates @kHz to the ceiled
 * frequency and @uW to the associated power. The power is estimated as
 * P = C * V^2 * f with C being the device's capacitance and V and f
 * respectively the voltage and frequency of the OPP.
 * It is also used as a callback function provided to the Energy Model
 * framework upon registration.
 *
 * Returns -EINVAL if the power calculation failed because of missing
 * parameters, 0 otherwise.
 */
int dev_pm_opp_calc_power(struct device *dev, unsigned long *uW,
			  unsigned long *kHz)
{}
EXPORT_SYMBOL_GPL();

static bool _of_has_opp_microwatt_property(struct device *dev)
{}

/**
 * dev_pm_opp_of_register_em() - Attempt to register an Energy Model
 * @dev		: Device for which an Energy Model has to be registered
 * @cpus	: CPUs for which an Energy Model has to be registered. For
 *		other type of devices it should be set to NULL.
 *
 * This checks whether the "dynamic-power-coefficient" devicetree property has
 * been specified, and tries to register an Energy Model with it if it has.
 * Having this property means the voltages are known for OPPs and the EM
 * might be calculated.
 */
int dev_pm_opp_of_register_em(struct device *dev, struct cpumask *cpus)
{}
EXPORT_SYMBOL_GPL();