Commit 41ef3d1d authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branch 'pm-devfreq'

* pm-devfreq:
  PM / devfreq: Modify the device name as devfreq(X) for sysfs
  PM / devfreq: Simplify the sysfs name of devfreq-event device
  PM / devfreq: Remove unnecessary separate _remove_devfreq()
  PM / devfreq: Fix wrong trans_stat of passive devfreq device
  PM / devfreq: Fix available_governor sysfs
  PM / devfreq: exynos-ppmu: Show the registred device for ppmu device
  PM / devfreq: Fix the wrong description for userspace governor
  PM / devfreq: Fix the checkpatch warnings
  PM / devfreq: exynos-bus: Print the real clock rate of bus
  PM / devfreq: exynos-ppmu: Use the regmap interface to handle the registers
  PM / devfreq: exynos-bus: Add the detailed correlation for Exynos5433
  PM / devfreq: Don't delete sysfs group twice
parents ad7eec42 23b017a6
What: /sys/class/devfreq-event/event(x)/
Date: January 2017
Contact: Chanwoo Choi <cw00.choi@samsung.com>
Description:
Provide a place in sysfs for the devfreq-event objects.
This allows accessing various devfreq-event specific variables.
The name of devfreq-event object denoted as 'event(x)' which
includes the unique number of 'x' for each devfreq-event object.
What: /sys/class/devfreq-event/event(x)/name
Date: January 2017
Contact: Chanwoo Choi <cw00.choi@samsung.com>
Description:
The /sys/class/devfreq-event/event(x)/name attribute contains
the name of the devfreq-event object. This attribute is
read-only.
What: /sys/class/devfreq-event/event(x)/enable_count
Date: January 2017
Contact: Chanwoo Choi <cw00.choi@samsung.com>
Description:
The /sys/class/devfreq-event/event(x)/enable_count attribute
contains the reference count to enable the devfreq-event
object. If the device is enabled, the value of attribute is
greater than zero.
...@@ -123,6 +123,20 @@ Detailed correlation between sub-blocks and power line according to Exynos SoC: ...@@ -123,6 +123,20 @@ Detailed correlation between sub-blocks and power line according to Exynos SoC:
|--- FSYS |--- FSYS
|--- FSYS2 |--- FSYS2
- In case of Exynos5433, there is VDD_INT power line as following:
VDD_INT |--- G2D (parent device)
|--- MSCL
|--- GSCL
|--- JPEG
|--- MFC
|--- HEVC
|--- BUS0
|--- BUS1
|--- BUS2
|--- PERIS (Fixed clock rate)
|--- PERIC (Fixed clock rate)
|--- FSYS (Fixed clock rate)
Example1: Example1:
Show the AXI buses of Exynos3250 SoC. Exynos3250 divides the buses to Show the AXI buses of Exynos3250 SoC. Exynos3250 divides the buses to
power line (regulator). The MIF (Memory Interface) AXI bus is used to power line (regulator). The MIF (Memory Interface) AXI bus is used to
......
...@@ -306,7 +306,7 @@ struct devfreq_event_dev *devfreq_event_add_edev(struct device *dev, ...@@ -306,7 +306,7 @@ struct devfreq_event_dev *devfreq_event_add_edev(struct device *dev,
struct devfreq_event_desc *desc) struct devfreq_event_desc *desc)
{ {
struct devfreq_event_dev *edev; struct devfreq_event_dev *edev;
static atomic_t event_no = ATOMIC_INIT(0); static atomic_t event_no = ATOMIC_INIT(-1);
int ret; int ret;
if (!dev || !desc) if (!dev || !desc)
...@@ -329,7 +329,7 @@ struct devfreq_event_dev *devfreq_event_add_edev(struct device *dev, ...@@ -329,7 +329,7 @@ struct devfreq_event_dev *devfreq_event_add_edev(struct device *dev,
edev->dev.class = devfreq_event_class; edev->dev.class = devfreq_event_class;
edev->dev.release = devfreq_event_release_edev; edev->dev.release = devfreq_event_release_edev;
dev_set_name(&edev->dev, "event.%d", atomic_inc_return(&event_no) - 1); dev_set_name(&edev->dev, "event%d", atomic_inc_return(&event_no));
ret = device_register(&edev->dev); ret = device_register(&edev->dev);
if (ret < 0) { if (ret < 0) {
put_device(&edev->dev); put_device(&edev->dev);
......
...@@ -128,7 +128,7 @@ static void devfreq_set_freq_table(struct devfreq *devfreq) ...@@ -128,7 +128,7 @@ static void devfreq_set_freq_table(struct devfreq *devfreq)
* @devfreq: the devfreq instance * @devfreq: the devfreq instance
* @freq: the update target frequency * @freq: the update target frequency
*/ */
static int devfreq_update_status(struct devfreq *devfreq, unsigned long freq) int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
{ {
int lev, prev_lev, ret = 0; int lev, prev_lev, ret = 0;
unsigned long cur_time; unsigned long cur_time;
...@@ -164,6 +164,7 @@ static int devfreq_update_status(struct devfreq *devfreq, unsigned long freq) ...@@ -164,6 +164,7 @@ static int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
devfreq->last_stat_updated = cur_time; devfreq->last_stat_updated = cur_time;
return ret; return ret;
} }
EXPORT_SYMBOL(devfreq_update_status);
/** /**
* find_devfreq_governor() - find devfreq governor from name * find_devfreq_governor() - find devfreq governor from name
...@@ -472,11 +473,15 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type, ...@@ -472,11 +473,15 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
} }
/** /**
* _remove_devfreq() - Remove devfreq from the list and release its resources. * devfreq_dev_release() - Callback for struct device to release the device.
* @devfreq: the devfreq struct * @dev: the devfreq device
*
* Remove devfreq from the list and release its resources.
*/ */
static void _remove_devfreq(struct devfreq *devfreq) static void devfreq_dev_release(struct device *dev)
{ {
struct devfreq *devfreq = to_devfreq(dev);
mutex_lock(&devfreq_list_lock); mutex_lock(&devfreq_list_lock);
if (IS_ERR(find_device_devfreq(devfreq->dev.parent))) { if (IS_ERR(find_device_devfreq(devfreq->dev.parent))) {
mutex_unlock(&devfreq_list_lock); mutex_unlock(&devfreq_list_lock);
...@@ -497,19 +502,6 @@ static void _remove_devfreq(struct devfreq *devfreq) ...@@ -497,19 +502,6 @@ static void _remove_devfreq(struct devfreq *devfreq)
kfree(devfreq); kfree(devfreq);
} }
/**
* devfreq_dev_release() - Callback for struct device to release the device.
* @dev: the devfreq device
*
* This calls _remove_devfreq() if _remove_devfreq() is not called.
*/
static void devfreq_dev_release(struct device *dev)
{
struct devfreq *devfreq = to_devfreq(dev);
_remove_devfreq(devfreq);
}
/** /**
* devfreq_add_device() - Add devfreq feature to the device * devfreq_add_device() - Add devfreq feature to the device
* @dev: the device to add devfreq feature. * @dev: the device to add devfreq feature.
...@@ -525,6 +517,7 @@ struct devfreq *devfreq_add_device(struct device *dev, ...@@ -525,6 +517,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
{ {
struct devfreq *devfreq; struct devfreq *devfreq;
struct devfreq_governor *governor; struct devfreq_governor *governor;
static atomic_t devfreq_no = ATOMIC_INIT(-1);
int err = 0; int err = 0;
if (!dev || !profile || !governor_name) { if (!dev || !profile || !governor_name) {
...@@ -536,15 +529,14 @@ struct devfreq *devfreq_add_device(struct device *dev, ...@@ -536,15 +529,14 @@ struct devfreq *devfreq_add_device(struct device *dev,
devfreq = find_device_devfreq(dev); devfreq = find_device_devfreq(dev);
mutex_unlock(&devfreq_list_lock); mutex_unlock(&devfreq_list_lock);
if (!IS_ERR(devfreq)) { if (!IS_ERR(devfreq)) {
dev_err(dev, "%s: Unable to create devfreq for the device. It already has one.\n", __func__); dev_err(dev, "%s: Unable to create devfreq for the device.\n",
__func__);
err = -EINVAL; err = -EINVAL;
goto err_out; goto err_out;
} }
devfreq = kzalloc(sizeof(struct devfreq), GFP_KERNEL); devfreq = kzalloc(sizeof(struct devfreq), GFP_KERNEL);
if (!devfreq) { if (!devfreq) {
dev_err(dev, "%s: Unable to create devfreq for the device\n",
__func__);
err = -ENOMEM; err = -ENOMEM;
goto err_out; goto err_out;
} }
...@@ -567,18 +559,21 @@ struct devfreq *devfreq_add_device(struct device *dev, ...@@ -567,18 +559,21 @@ struct devfreq *devfreq_add_device(struct device *dev,
mutex_lock(&devfreq->lock); mutex_lock(&devfreq->lock);
} }
dev_set_name(&devfreq->dev, "%s", dev_name(dev)); dev_set_name(&devfreq->dev, "devfreq%d",
atomic_inc_return(&devfreq_no));
err = device_register(&devfreq->dev); err = device_register(&devfreq->dev);
if (err) { if (err) {
mutex_unlock(&devfreq->lock); mutex_unlock(&devfreq->lock);
goto err_out; goto err_out;
} }
devfreq->trans_table = devm_kzalloc(&devfreq->dev, sizeof(unsigned int) * devfreq->trans_table = devm_kzalloc(&devfreq->dev,
sizeof(unsigned int) *
devfreq->profile->max_state * devfreq->profile->max_state *
devfreq->profile->max_state, devfreq->profile->max_state,
GFP_KERNEL); GFP_KERNEL);
devfreq->time_in_state = devm_kzalloc(&devfreq->dev, sizeof(unsigned long) * devfreq->time_in_state = devm_kzalloc(&devfreq->dev,
sizeof(unsigned long) *
devfreq->profile->max_state, devfreq->profile->max_state,
GFP_KERNEL); GFP_KERNEL);
devfreq->last_stat_updated = jiffies; devfreq->last_stat_updated = jiffies;
...@@ -937,6 +932,9 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr, ...@@ -937,6 +932,9 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
if (df->governor == governor) { if (df->governor == governor) {
ret = 0; ret = 0;
goto out; goto out;
} else if (df->governor->immutable || governor->immutable) {
ret = -EINVAL;
goto out;
} }
if (df->governor) { if (df->governor) {
...@@ -966,13 +964,33 @@ static ssize_t available_governors_show(struct device *d, ...@@ -966,13 +964,33 @@ static ssize_t available_governors_show(struct device *d,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct devfreq_governor *tmp_governor; struct devfreq *df = to_devfreq(d);
ssize_t count = 0; ssize_t count = 0;
mutex_lock(&devfreq_list_lock); mutex_lock(&devfreq_list_lock);
list_for_each_entry(tmp_governor, &devfreq_governor_list, node)
/*
* The devfreq with immutable governor (e.g., passive) shows
* only own governor.
*/
if (df->governor->immutable) {
count = scnprintf(&buf[count], DEVFREQ_NAME_LEN,
"%s ", df->governor_name);
/*
* The devfreq device shows the registered governor except for
* immutable governors such as passive governor .
*/
} else {
struct devfreq_governor *governor;
list_for_each_entry(governor, &devfreq_governor_list, node) {
if (governor->immutable)
continue;
count += scnprintf(&buf[count], (PAGE_SIZE - count - 2), count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
"%s ", tmp_governor->name); "%s ", governor->name);
}
}
mutex_unlock(&devfreq_list_lock); mutex_unlock(&devfreq_list_lock);
/* Truncate the trailing space */ /* Truncate the trailing space */
......
This diff is collapsed.
...@@ -146,8 +146,8 @@ static int exynos_bus_target(struct device *dev, unsigned long *freq, u32 flags) ...@@ -146,8 +146,8 @@ static int exynos_bus_target(struct device *dev, unsigned long *freq, u32 flags)
} }
bus->curr_freq = new_freq; bus->curr_freq = new_freq;
dev_dbg(dev, "Set the frequency of bus (%lukHz -> %lukHz)\n", dev_dbg(dev, "Set the frequency of bus (%luHz -> %luHz, %luHz)\n",
old_freq/1000, new_freq/1000); old_freq, new_freq, clk_get_rate(bus->clk));
out: out:
mutex_unlock(&bus->lock); mutex_unlock(&bus->lock);
...@@ -239,8 +239,8 @@ static int exynos_bus_passive_target(struct device *dev, unsigned long *freq, ...@@ -239,8 +239,8 @@ static int exynos_bus_passive_target(struct device *dev, unsigned long *freq,
*freq = new_freq; *freq = new_freq;
bus->curr_freq = new_freq; bus->curr_freq = new_freq;
dev_dbg(dev, "Set the frequency of bus (%lukHz -> %lukHz)\n", dev_dbg(dev, "Set the frequency of bus (%luHz -> %luHz, %luHz)\n",
old_freq/1000, new_freq/1000); old_freq, new_freq, clk_get_rate(bus->clk));
out: out:
mutex_unlock(&bus->lock); mutex_unlock(&bus->lock);
......
...@@ -38,4 +38,6 @@ extern void devfreq_interval_update(struct devfreq *devfreq, ...@@ -38,4 +38,6 @@ extern void devfreq_interval_update(struct devfreq *devfreq,
extern int devfreq_add_governor(struct devfreq_governor *governor); extern int devfreq_add_governor(struct devfreq_governor *governor);
extern int devfreq_remove_governor(struct devfreq_governor *governor); extern int devfreq_remove_governor(struct devfreq_governor *governor);
extern int devfreq_update_status(struct devfreq *devfreq, unsigned long freq);
#endif /* _GOVERNOR_H */ #endif /* _GOVERNOR_H */
...@@ -112,6 +112,11 @@ static int update_devfreq_passive(struct devfreq *devfreq, unsigned long freq) ...@@ -112,6 +112,11 @@ static int update_devfreq_passive(struct devfreq *devfreq, unsigned long freq)
if (ret < 0) if (ret < 0)
goto out; goto out;
if (devfreq->profile->freq_table
&& (devfreq_update_status(devfreq, freq)))
dev_err(&devfreq->dev,
"Couldn't update frequency transition information.\n");
devfreq->previous_freq = freq; devfreq->previous_freq = freq;
out: out:
...@@ -179,6 +184,7 @@ static int devfreq_passive_event_handler(struct devfreq *devfreq, ...@@ -179,6 +184,7 @@ static int devfreq_passive_event_handler(struct devfreq *devfreq,
static struct devfreq_governor devfreq_passive = { static struct devfreq_governor devfreq_passive = {
.name = "passive", .name = "passive",
.immutable = 1,
.get_target_freq = devfreq_passive_get_target_freq, .get_target_freq = devfreq_passive_get_target_freq,
.event_handler = devfreq_passive_event_handler, .event_handler = devfreq_passive_event_handler,
}; };
......
/* /*
* linux/drivers/devfreq/governor_simpleondemand.c * linux/drivers/devfreq/governor_userspace.c
* *
* Copyright (C) 2011 Samsung Electronics * Copyright (C) 2011 Samsung Electronics
* MyungJoo Ham <myungjoo.ham@samsung.com> * MyungJoo Ham <myungjoo.ham@samsung.com>
...@@ -50,7 +50,6 @@ static ssize_t store_freq(struct device *dev, struct device_attribute *attr, ...@@ -50,7 +50,6 @@ static ssize_t store_freq(struct device *dev, struct device_attribute *attr,
unsigned long wanted; unsigned long wanted;
int err = 0; int err = 0;
mutex_lock(&devfreq->lock); mutex_lock(&devfreq->lock);
data = devfreq->data; data = devfreq->data;
...@@ -112,7 +111,13 @@ static int userspace_init(struct devfreq *devfreq) ...@@ -112,7 +111,13 @@ static int userspace_init(struct devfreq *devfreq)
static void userspace_exit(struct devfreq *devfreq) static void userspace_exit(struct devfreq *devfreq)
{ {
/*
* Remove the sysfs entry, unless this is being called after
* device_del(), which should have done this already via kobject_del().
*/
if (devfreq->dev.kobj.sd)
sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group); sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group);
kfree(devfreq->data); kfree(devfreq->data);
devfreq->data = NULL; devfreq->data = NULL;
} }
......
...@@ -104,6 +104,8 @@ struct devfreq_dev_profile { ...@@ -104,6 +104,8 @@ struct devfreq_dev_profile {
* struct devfreq_governor - Devfreq policy governor * struct devfreq_governor - Devfreq policy governor
* @node: list node - contains registered devfreq governors * @node: list node - contains registered devfreq governors
* @name: Governor's name * @name: Governor's name
* @immutable: Immutable flag for governor. If the value is 1,
* this govenror is never changeable to other governor.
* @get_target_freq: Returns desired operating frequency for the device. * @get_target_freq: Returns desired operating frequency for the device.
* Basically, get_target_freq will run * Basically, get_target_freq will run
* devfreq_dev_profile.get_dev_status() to get the * devfreq_dev_profile.get_dev_status() to get the
...@@ -121,6 +123,7 @@ struct devfreq_governor { ...@@ -121,6 +123,7 @@ struct devfreq_governor {
struct list_head node; struct list_head node;
const char name[DEVFREQ_NAME_LEN]; const char name[DEVFREQ_NAME_LEN];
const unsigned int immutable;
int (*get_target_freq)(struct devfreq *this, unsigned long *freq); int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
int (*event_handler)(struct devfreq *devfreq, int (*event_handler)(struct devfreq *devfreq,
unsigned int event, void *data); unsigned int event, void *data);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment