RE: [RFC 3/7] OMAP: Introduce voltage domain pointer and device specific set rate and get rate in device opp structures.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




>>-----Original Message-----
>>From: Kevin Hilman [mailto:khilman@xxxxxxxxxxxxxxxxxxx]
>>Sent: Wednesday, August 04, 2010 6:03 AM
>>To: Gopinath, Thara
>>Cc: linux-omap@xxxxxxxxxxxxxxx; paul@xxxxxxxxx; Cousson, Benoit; Sripathy, Vishwanath; Sawant, Anand;
>>Basak, Partha
>>Subject: Re: [RFC 3/7] OMAP: Introduce voltage domain pointer and device specific set rate and get
>>rate in device opp structures.
>>
>>Thara Gopinath <thara@xxxxxx> writes:
>>
>>> This patch extends the device opp structure to contain
>>> info about the voltage domain to which the device belongs to
>>> and to contain pointers to scale the operating rate of the
>>> device. This patch also adds an API in the opp layer that
>>> can be used by the voltage layer to get a list of all the
>>> scalable devices belonging to a particular voltage domain.
>>> This API is to be typically called only once by the voltage
>>> layer per voltage domain instance and the device list should
>>> be stored. This approach makes it easy during dvfs to scale
>>> all the devices associated with a voltage domain and then
>>> scale the voltage domain.
>>>
>>> Signed-off-by: Thara Gopinath <thara@xxxxxx>
>>> ---
>>>  arch/arm/plat-omap/include/plat/opp.h |   37 +++++++++++++++++++++++++-
>>>  arch/arm/plat-omap/opp.c              |   47 +++++++++++++++++++++++++-------
>>>  2 files changed, 72 insertions(+), 12 deletions(-)
>>>
>>> diff --git a/arch/arm/plat-omap/include/plat/opp.h b/arch/arm/plat-omap/include/plat/opp.h
>>> index 893731f..15e1e70 100644
>>> --- a/arch/arm/plat-omap/include/plat/opp.h
>>> +++ b/arch/arm/plat-omap/include/plat/opp.h
>>> @@ -16,6 +16,7 @@
>>>
>>>  #include <linux/err.h>
>>>  #include <linux/cpufreq.h>
>>> +#include <linux/clk.h>
>>>
>>>  #include <plat/common.h>
>>>
>>> @@ -38,21 +39,45 @@
>>>   */
>>>  struct omap_opp_def {
>>>  	char *hwmod_name;
>>> +	char *vdd_name;
>>>
>>>  	unsigned long freq;
>>>  	unsigned long u_volt;
>>>
>>> +	int (*set_rate)(struct device *dev, unsigned long rate);
>>> +	unsigned long (*get_rate) (struct device *dev);
>>> +
>>>  	bool enabled;
>>>  };
>>>
>>> +struct device_opp {
>>> +	struct list_head node;
>>> +	char *vdd_name;
>>> +
>>> +	struct omap_hwmod *oh;
>>> +	struct device *dev;
>>> +	struct omap_volt_domain *volt_domain;
>>> +
>>> +	struct list_head opp_list;
>>> +	u32 opp_count;
>>> +	u32 enabled_opp_count;
>>> +
>>> +	int (*set_rate)(struct device *dev, unsigned long rate);
>>> +	unsigned long (*get_rate) (struct device *dev);
>>> +};
>>
>>I don't like moving the definition of this struct out.  This exposes the
>>implmentation details of the OPP layer that are subject to change.
>>
>>A quick glance shows you need to access the volt_domain field and the
>>new function pointers.
>>
>>The voltage domain should be part of the hwmod as suggested by Benoit,
>>and an API created to get the voltage domain from the hwmod.
>>
>>For the get/set rate functions, maybe new OPP layer API should be
>>created access those functions.  opp_[get|set]_rate()?

Yes I could do this.

>>
>>
>>>  /*
>>>   * Initialization wrapper used to define an OPP.
>>>   * To point at the end of a terminator of a list of OPPs,
>>>   * use OMAP_OPP_DEF(0, 0, 0)
>>>   */
>>> -#define OMAP_OPP_DEF(_hwmod_name, _enabled, _freq, _uv)	\
>>> +#define OMAP_OPP_DEF(_hwmod_name, _vdd_name, _set_rate, _get_rate, \
>>> +			_enabled, _freq, _uv)	\
>>>  {						\
>>>  	.hwmod_name	= _hwmod_name,		\
>>> +	.vdd_name	= _vdd_name,		\
>>> +	.set_rate	= _set_rate,		\
>>> +	.get_rate	= _get_rate,		\
>>>  	.enabled	= _enabled,		\
>>>  	.freq		= _freq,		\
>>>  	.u_volt		= _uv,			\
>>> @@ -77,6 +102,8 @@ struct omap_opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq);
>>>
>>>  struct omap_opp *opp_find_voltage(struct device *dev, unsigned long volt);
>>>
>>> +struct device_opp *opp_find_dev_opp(struct device *dev);
>>> +
>>>  int opp_add(const struct omap_opp_def *opp_def);
>>>
>>>  int opp_enable(struct omap_opp *opp);
>>> @@ -89,6 +116,9 @@ u8 __deprecated opp_get_opp_id(struct omap_opp *opp);
>>>
>>>  void opp_init_cpufreq_table(struct device *dev,
>>>  			    struct cpufreq_frequency_table **table);
>>> +
>>> +struct device **opp_init_voltage_params(struct omap_volt_domain *volt_domain,
>>> +		int *dev_count);
>>>  #else
>>>  static inline unsigned long opp_get_voltage(const struct omap_opp *opp)
>>>  {
>>> @@ -124,6 +154,11 @@ static inline struct omap_opp *opp_find_freq_ceil(struct omap_opp *oppl,
>>>  	return ERR_PTR(-EINVAL);
>>>  }
>>>
>>> +static inline struct device_opp *opp_find_dev_opp(struct device *dev)
>>> +{
>>> +	return ERR_PTR(-EINVAL);
>>> +}
>>> +
>>>  static inline struct omap_opp *opp_add(struct omap_opp *oppl,
>>>  				       const struct omap_opp_def *opp_def)
>>>  {
>>> diff --git a/arch/arm/plat-omap/opp.c b/arch/arm/plat-omap/opp.c
>>> index 070ff5b..9bc53e8 100644
>>> --- a/arch/arm/plat-omap/opp.c
>>> +++ b/arch/arm/plat-omap/opp.c
>>> @@ -22,6 +22,7 @@
>>>  #include <plat/opp_twl_tps.h>
>>>  #include <plat/opp.h>
>>>  #include <plat/omap_device.h>
>>> +#include <plat/voltage.h>
>>>
>>>  /**
>>>   * struct omap_opp - OMAP OPP description structure
>>> @@ -43,17 +44,6 @@ struct omap_opp {
>>>  	struct device_opp *dev_opp;  /* containing device_opp struct */
>>>  };
>>>
>>> -struct device_opp {
>>> -	struct list_head node;
>>> -
>>> -	struct omap_hwmod *oh;
>>> -	struct device *dev;
>>> -
>>> -	struct list_head opp_list;
>>> -	u32 opp_count;
>>> -	u32 enabled_opp_count;
>>> -};
>>> -
>>>  static LIST_HEAD(dev_opp_list);
>>>
>>>  /**
>>> @@ -330,6 +320,11 @@ struct omap_opp *opp_find_voltage(struct device *dev, unsigned long volt)
>>>  	return opp;
>>>  }
>>>
>>> +struct device_opp *opp_find_dev_opp(struct device *dev)
>>> +{
>>> +	return find_device_opp(dev);
>>> +}
>>> +
>>>  /* wrapper to reuse converting opp_def to opp struct */
>>>  static void omap_opp_populate(struct omap_opp *opp,
>>>  			      const struct omap_opp_def *opp_def)
>>> @@ -385,6 +380,11 @@ int opp_add(const struct omap_opp_def *opp_def)
>>>
>>>  		dev_opp->oh = oh;
>>>  		dev_opp->dev = &oh->od->pdev.dev;
>>> +		dev_opp->vdd_name = kzalloc(strlen(opp_def->vdd_name) + 1,
>>> +				GFP_KERNEL);
>>> +		strcpy(dev_opp->vdd_name, opp_def->vdd_name);
>>
>>Since this is user-defined data/string, should probably have a max
>>strlen and use strncpy.

I did not get this. What is the problem with the strlen here ?

Regards
Thara

>>
>>Kevin
>>
>>> +		dev_opp->set_rate = opp_def->set_rate;
>>> +		dev_opp->get_rate = opp_def->get_rate;
>>>  		INIT_LIST_HEAD(&dev_opp->opp_list);
>>>
>>>  		list_add(&dev_opp->node, &dev_opp_list);
>>> @@ -511,3 +511,28 @@ void opp_init_cpufreq_table(struct device *dev,
>>>
>>>  	*table = &freq_table[0];
>>>  }
>>> +
>>> +struct device **opp_init_voltage_params(struct omap_volt_domain *volt_domain,
>>> +		int *dev_count)
>>> +{
>>> +	struct device_opp *dev_opp;
>>> +	struct device **dev_list;
>>> +	int count = 0, i = 0;
>>> +
>>> +	list_for_each_entry(dev_opp, &dev_opp_list, node) {
>>> +		if (!strcmp(dev_opp->vdd_name, volt_domain->name)) {
>>> +			dev_opp->volt_domain = volt_domain;
>>> +			count++;
>>> +		}
>>> +	}
>>> +
>>> +	dev_list = kzalloc(sizeof(struct device *) * count, GFP_KERNEL);
>>> +
>>> +	list_for_each_entry(dev_opp, &dev_opp_list, node) {
>>> +		if (dev_opp->volt_domain == volt_domain)
>>> +			dev_list[i++] = dev_opp->dev;
>>> +	}
>>> +
>>> +	*dev_count = count;
>>> +	return dev_list;
>>> +}
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux