* [RFC PATCH 0/5] devfreq: Add devfreq-event class to provide raw data for devfreq device
@ 2014-09-05 4:30 Chanwoo Choi
2014-09-05 4:30 ` [RFC PATCH 1/5] devfreq: Add new devfreq_event class to provide basic data for devfreq governor Chanwoo Choi
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Chanwoo Choi @ 2014-09-05 4:30 UTC (permalink / raw)
To: myungjoo.ham, linux-pm
Cc: kyungmin.park, rafael.j.wysocki, a.kesavan, kgene.kim,
tomasz.figa, b.zolnierkie, nm, linux-kernel, linux-samsung-soc,
linux-arm-kernel, Chanwoo Choi
This patchset add new devfreq_event class to provide raw data to determine
current utilization of device which is used for devfreq governor.
But, This patchset is just initial version and must need more implementaion
and updates.
Although this patchset has not enough feature to support devfreq-event class,
I send this RFC patchset to share current implementation. Please feel free to
give comment and advice.
[Description of devfreq-event class]
This patchset add new devfreq_event class for devfreq_event device which provide
raw data (e.g., memory bus utilization/GPU utilization). This raw data from
devfreq_event data would be used for the governor of devfreq subsystem.
- devfreq_event device : Provide raw data for governor of existing devfreq device
- devfreq device : Monitor device state and change frequency/voltage of device
using the raw data from devfreq_event device
The devfreq subsystem support generic DVFS(Dynamic Voltage/Frequency Scaling)
for Non-CPU Devices. The devfreq device would dertermine current device state
using various governor (e.g., ondemand, performance, powersave). After completed
determination of system state, devfreq device would change the frequency/voltage
of devfreq device according to the result of governor.
But, devfreq governor must need basic data which indicates current device state.
Existing devfreq subsystem only consider devfreq device which check current system
state and determine proper system state using basic data. There is no subsystem
for device providing basic data to devfreq device.
The devfreq subsystem must need devfreq_event device(data-provider device) for
existing devfreq device. So, this patch add new devfreq_event class for
devfreq_event device which read various basic data(e.g, memory bus utilization,
GPU utilization) and provide measured data to existing devfreq device through
standard APIs of devfreq_event class.
The following description explains the feature of two kind of devfreq class:
- devfreq class (existing)
: devfreq consumer device use raw data from devfreq_event device for
determining proper current system state and change voltage/frequency
dynamically using various governors.
- devfreq_event class (new)
: Provide measured raw data to devfreq device for governor
[For example]
If board dts includes PPMU_DMC0/DMC1/CPU event node,
would show following sysfs entry. Also devfreq driver(e.g., exynos4_bus.c)
can get the instance of devfreq-event device by using provided API and then
get raw data which reflect the current utilization of device.
-sh-3.2# pwd
/sys/class/devfreq_event
-sh-3.2# ls -al
total 0
drwxr-xr-x 2 root root 0 Jan 1 21:06 .
drwxr-xr-x 45 root root 0 Jan 1 21:06 ..
lrwxrwxrwx 1 root root 0 Jan 1 21:06 event.0 -> ../../devices/soc/106a0000.ppmu_dmc0/devfreq_event/event.0
lrwxrwxrwx 1 root root 0 Jan 1 21:06 event.1 -> ../../devices/soc/106b0000.ppmu_dmc1/devfreq_event/event.1
lrwxrwxrwx 1 root root 0 Jan 1 21:06 event.2 -> ../../devices/soc/106c0000.ppmu_cpu/devfreq_event/event.2
Chanwoo Choi (5):
devfreq: Add new devfreq_event class to provide basic data for devfreq governor
devfreq: event: Add exynos-ppmu devfreq evnet driver
ARM: dts: Add PPMU dt node for Exynos3250
ARM: dts: Add PPMU dt node for Exynos4 SoC
ARM: dts: Add dt node fo PPMU_CPU/DMC0/DMC1 for exynos4412-trats2
arch/arm/boot/dts/exynos3250.dtsi | 66 +++++
arch/arm/boot/dts/exynos4.dtsi | 96 ++++++++
arch/arm/boot/dts/exynos4210.dtsi | 8 +
arch/arm/boot/dts/exynos4412-trats2.dts | 29 +++
drivers/devfreq/Kconfig | 12 +
drivers/devfreq/Makefile | 5 +-
drivers/devfreq/devfreq-event.c | 251 +++++++++++++++++++
drivers/devfreq/event/Makefile | 2 +
drivers/devfreq/event/exynos-ppmu.c | 410 ++++++++++++++++++++++++++++++++
include/linux/devfreq.h | 97 ++++++++
10 files changed, 975 insertions(+), 1 deletion(-)
create mode 100644 drivers/devfreq/devfreq-event.c
create mode 100644 drivers/devfreq/event/Makefile
create mode 100644 drivers/devfreq/event/exynos-ppmu.c
--
1.8.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [RFC PATCH 1/5] devfreq: Add new devfreq_event class to provide basic data for devfreq governor
2014-09-05 4:30 [RFC PATCH 0/5] devfreq: Add devfreq-event class to provide raw data for devfreq device Chanwoo Choi
@ 2014-09-05 4:30 ` Chanwoo Choi
2014-09-05 4:30 ` [RFC PATCH 2/5] devfreq: event: Add exynos-ppmu devfreq evnet driver Chanwoo Choi
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Chanwoo Choi @ 2014-09-05 4:30 UTC (permalink / raw)
To: myungjoo.ham, linux-pm
Cc: kyungmin.park, rafael.j.wysocki, a.kesavan, kgene.kim,
tomasz.figa, b.zolnierkie, nm, linux-kernel, linux-samsung-soc,
linux-arm-kernel, Chanwoo Choi
This patch add new devfreq_event class for devfreq_event device which provide
raw data (e.g., memory bus utilization/GPU utilization). This raw data from
devfreq_event data would be used for the governor of devfreq subsystem.
- devfreq_event device : Provide raw data for governor of existing devfreq device
- devfreq device : Monitor device state and change frequency/voltage of device
using the raw data from devfreq_event device
The devfreq subsystem support generic DVFS(Dynamic Voltage/Frequency Scaling)
for Non-CPU Devices. The devfreq device would dertermine current device state
using various governor (e.g., ondemand, performance, powersave). After completed
determination of system state, devfreq device would change the frequency/voltage
of devfreq device according to the result of governor.
But, devfreq governor must need basic data which indicates current device state.
Existing devfreq subsystem only consider devfreq device which check current system
state and determine proper system state using basic data. There is no subsystem
for device providing basic data to devfreq device.
The devfreq subsystem must need devfreq_event device(data-provider device) for
existing devfreq device. So, this patch add new devfreq_event class for
devfreq_event device which read various basic data(e.g, memory bus utilization,
GPU utilization) and provide measured data to existing devfreq device through
standard APIs of devfreq_event class.
The following description explains the feature of two kind of devfreq class:
- devfreq class (existing)
: devfreq consumer device use raw data from devfreq_event device for
determining proper current system state and change voltage/frequency
dynamically using various governors.
- devfreq_event class (new)
: Provide measured raw data to devfreq device for governor
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/devfreq/Kconfig | 2 +
drivers/devfreq/Makefile | 5 +-
drivers/devfreq/devfreq-event.c | 251 ++++++++++++++++++++++++++++++++++++++++
drivers/devfreq/event/Makefile | 1 +
include/linux/devfreq.h | 97 ++++++++++++++++
5 files changed, 355 insertions(+), 1 deletion(-)
create mode 100644 drivers/devfreq/devfreq-event.c
create mode 100644 drivers/devfreq/event/Makefile
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index 3dced0a..ef839e7 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -88,4 +88,6 @@ config ARM_EXYNOS5_BUS_DEVFREQ
It reads PPMU counters of memory controllers and adjusts the
operating frequencies and voltages with OPP support.
+comment "DEVFREQ Event Drivers"
+
endif # PM_DEVFREQ
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
index 16138c9..a1ffabe 100644
--- a/drivers/devfreq/Makefile
+++ b/drivers/devfreq/Makefile
@@ -1,4 +1,4 @@
-obj-$(CONFIG_PM_DEVFREQ) += devfreq.o
+obj-$(CONFIG_PM_DEVFREQ) += devfreq.o devfreq-event.o
obj-$(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) += governor_simpleondemand.o
obj-$(CONFIG_DEVFREQ_GOV_PERFORMANCE) += governor_performance.o
obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o
@@ -7,3 +7,6 @@ obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o
# DEVFREQ Drivers
obj-$(CONFIG_ARM_EXYNOS4_BUS_DEVFREQ) += exynos/
obj-$(CONFIG_ARM_EXYNOS5_BUS_DEVFREQ) += exynos/
+
+# DEVFREQ Event Drivers
+obj-$(CONFIG_PM_DEVFREQ) += event/
diff --git a/drivers/devfreq/devfreq-event.c b/drivers/devfreq/devfreq-event.c
new file mode 100644
index 0000000..1629197
--- /dev/null
+++ b/drivers/devfreq/devfreq-event.c
@@ -0,0 +1,251 @@
+/*
+ * devfreq-event: Generic DEVFREQ Event class driver
+ *
+ * Copyright (C) 2014 Samsung Electronics
+ * Chanwoo Choi <cw00.choi@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This driver is based on drivers/devfreq/devfreq.c
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/pm_opp.h>
+#include <linux/devfreq.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/printk.h>
+#include <linux/hrtimer.h>
+#include <linux/of.h>
+#include "governor.h"
+
+static struct class *devfreq_event_class;
+
+/* The list of all devfreq event list */
+static LIST_HEAD(devfreq_event_list);
+static DEFINE_MUTEX(devfreq_event_list_lock);
+
+#define to_devfreq_event(DEV) container_of(DEV, struct devfreq_event_dev, dev)
+
+struct devfreq_event_dev *devfreq_add_event_device(struct device *dev,
+ struct devfreq_event_desc *desc)
+{
+ struct devfreq_event_dev *edev;
+ static atomic_t event_no = ATOMIC_INIT(0);
+ int ret;
+
+ if (!dev || !desc)
+ return ERR_PTR(-EINVAL);
+
+ if (!desc->name || !desc->ops || !desc->dev)
+ return ERR_PTR(-EINVAL);
+
+ edev = kzalloc(sizeof(struct devfreq_event_dev), GFP_KERNEL);
+ if (!edev)
+ return ERR_PTR(-ENOMEM);
+
+ mutex_lock(&devfreq_event_list_lock);
+
+ mutex_init(&edev->mutex);
+ edev->desc = desc;
+ edev->driver_data = desc->driver_data;
+ edev->owner = desc->owner;
+
+ edev->dev.parent = dev;
+ edev->dev.class = devfreq_event_class;
+
+ dev_set_name(&edev->dev, "event.%d",
+ atomic_inc_return(&event_no) - 1);
+ ret = device_register(&edev->dev);
+ if (ret != 0) {
+ put_device(&edev->dev);
+ goto err;
+ }
+ dev_set_drvdata(&edev->dev, edev);
+
+ /* Add devfreq event device to devfreq_event_list */
+ INIT_LIST_HEAD(&edev->node);
+ list_add(&edev->node, &devfreq_event_list);
+
+ mutex_unlock(&devfreq_event_list_lock);
+
+ return edev;
+err:
+ kfree(edev);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(devfreq_add_event_device);
+
+struct devfreq_event_dev *devfreq_get_edev(const char *edev_name)
+{
+ struct devfreq_event_dev *edev;
+
+ mutex_lock(&devfreq_event_list_lock);
+ list_for_each_entry(edev, &devfreq_event_list, node) {
+ if (!strcmp(edev->desc->name, edev_name))
+ goto out;
+ }
+ edev = NULL;
+out:
+ mutex_unlock(&devfreq_event_list_lock);
+
+ return edev;
+}
+EXPORT_SYMBOL_GPL(devfreq_get_edev);
+
+struct devfreq_event_dev *devfreq_get_edev_by_phandle(struct device *dev,
+ int index)
+{
+ struct device_node *node;
+ struct devfreq_event_dev *edev;
+
+ if (!dev->of_node) {
+ dev_err(dev, "device does not have a device node entry\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ node = of_parse_phandle(dev->of_node, "devfreq-events", index);
+ if (!node) {
+ dev_err(dev, "failed to get phandle in %s node\n",
+ dev->of_node->full_name);
+ return ERR_PTR(-ENODEV);
+ }
+
+ edev = devfreq_get_edev(node->name);
+ if (!edev) {
+ dev_err(dev, "unable to get devfreq-event device : %s\n",
+ node->name);
+ return ERR_PTR(-ENODEV);
+ }
+
+ return edev;
+}
+EXPORT_SYMBOL_GPL(devfreq_get_edev_by_phandle);
+
+int devfreq_put_edev(struct devfreq_event_dev *edev)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(devfreq_put_edev);
+
+int devfreq_enable_edev(struct devfreq_event_dev *edev)
+{
+ if (!edev || !edev->desc)
+ return -EINVAL;
+
+ if (edev->desc->ops && edev->desc->ops->enable)
+ return edev->desc->ops->enable(edev);
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(devfreq_enable_edev);
+
+int devfreq_disable_edev(struct devfreq_event_dev *edev)
+{
+ if (!edev || !edev->desc)
+ return -EINVAL;
+
+ if (edev->desc->ops && edev->desc->ops->disable)
+ return edev->desc->ops->disable(edev);
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(devfreq_disable_edev);
+
+int devfreq_set_event_edev(struct devfreq_event_dev *edev)
+{
+ if (!edev || !edev->desc)
+ return -EINVAL;
+
+ if (edev->desc->ops && edev->desc->ops->set_event)
+ return edev->desc->ops->set_event(edev);
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(devfreq_set_event_edev);
+
+int devfreq_get_event_edev(struct devfreq_event_dev *edev)
+{
+ if (!edev || !edev->desc)
+ return -EINVAL;
+
+ if (edev->desc->ops && edev->desc->ops->get_event)
+ return edev->desc->ops->get_event(edev);
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(devfreq_get_event_edev);
+
+int devfreq_reset_edev(struct devfreq_event_dev *edev)
+{
+ if (!edev || !edev->desc)
+ return -EINVAL;
+
+ if (edev->desc->ops && edev->desc->ops->reset)
+ return edev->desc->ops->reset(edev);
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(devfreq_reset_edev);
+
+void *edev_get_drvdata(struct devfreq_event_dev *edev)
+{
+ return edev->driver_data;
+}
+EXPORT_SYMBOL_GPL(edev_get_drvdata);
+
+/*
+ * Device Attribues for devfreq event class
+ */
+static ssize_t name_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct devfreq_event_dev *edev = to_devfreq_event(dev);
+
+ if (!edev || !edev->desc)
+ return -EINVAL;
+
+ return sprintf(buf, "%s\n", edev->desc->name);
+}
+static DEVICE_ATTR_RO(name);
+
+static struct attribute *devfreq_event_attrs[] = {
+ &dev_attr_name.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(devfreq_event);
+
+static int __init devfreq_event_init(void)
+{
+ devfreq_event_class = class_create(THIS_MODULE, "devfreq_event");
+ if (IS_ERR(devfreq_event_class)) {
+ pr_err("%s: couldn't create class\n", __FILE__);
+ return PTR_ERR(devfreq_event_class);
+ }
+
+ devfreq_event_class->dev_groups = devfreq_event_groups;
+
+ return 0;
+}
+subsys_initcall(devfreq_event_init);
+
+static void __exit devfreq_event_exit(void)
+{
+ class_destroy(devfreq_event_class);
+}
+module_exit(devfreq_event_exit);
+
+MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
+MODULE_DESCRIPTION("devfreq-event class support");
+MODULE_LICENSE("GPL");
diff --git a/drivers/devfreq/event/Makefile b/drivers/devfreq/event/Makefile
new file mode 100644
index 0000000..dc56005
--- /dev/null
+++ b/drivers/devfreq/event/Makefile
@@ -0,0 +1 @@
+# Exynos DEVFREQ Event Drivers
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index f1863dc..a87989b 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -175,6 +175,36 @@ struct devfreq {
unsigned long last_stat_updated;
};
+struct devfreq_event_dev {
+ const struct devfreq_event_desc *desc;
+
+ struct list_head node;
+ struct device dev;
+ struct module *owner;
+ struct mutex mutex;
+
+ void *driver_data;
+};
+
+struct devfreq_event_ops {
+ int (*enable)(struct devfreq_event_dev *edev);
+ int (*disable)(struct devfreq_event_dev *edev);
+ int (*set_event)(struct devfreq_event_dev *edev);
+ int (*get_event)(struct devfreq_event_dev *edev);
+ int (*reset)(struct devfreq_event_dev *edev);
+};
+
+struct devfreq_event_desc {
+ const char *name;
+ unsigned int id;
+
+ struct devfreq_event_ops *ops;
+ struct device *dev;
+ struct module *owner;
+
+ void *driver_data;
+};
+
#if defined(CONFIG_PM_DEVFREQ)
extern struct devfreq *devfreq_add_device(struct device *dev,
struct devfreq_dev_profile *profile,
@@ -204,6 +234,20 @@ extern int devm_devfreq_register_opp_notifier(struct device *dev,
extern void devm_devfreq_unregister_opp_notifier(struct device *dev,
struct devfreq *devfreq);
+/* Functions for devfreq event device */
+extern struct devfreq_event_dev *devfreq_add_event_device(struct device *dev,
+ struct devfreq_event_desc *desc);
+extern struct devfreq_event_dev *devfreq_get_edev(const char *name);
+extern struct devfreq_event_dev *devfreq_get_edev_by_phandle(struct device *dev,
+ int index);
+extern int devfreq_put_edev(struct devfreq_event_dev *edev);
+extern int devfreq_enable_edev(struct devfreq_event_dev *edev);
+extern int devfreq_disable_edev(struct devfreq_event_dev *edev);
+extern int devfreq_set_event_edev(struct devfreq_event_dev *edev);
+extern int devfreq_get_event_edev(struct devfreq_event_dev *edev);
+extern int devfreq_reset_edev(struct devfreq_event_dev *edev);
+extern void *edev_get_drvdata(struct devfreq_event_dev *edev);
+
#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
/**
* struct devfreq_simple_ondemand_data - void *data fed to struct devfreq
@@ -233,6 +277,13 @@ static inline struct devfreq *devfreq_add_device(struct device *dev,
return ERR_PTR(-ENOSYS);
}
+static inline struct devfreq_event_dev *devfreq_add_event_device(
+ struct device *dev,
+ struct devfreq_event_desc *desc);
+{
+ return ERR_PTR(-ENODEV);
+}
+
static inline int devfreq_remove_device(struct devfreq *devfreq)
{
return 0;
@@ -289,6 +340,52 @@ static inline void devm_devfreq_unregister_opp_notifier(struct device *dev,
struct devfreq *devfreq)
{
}
+
+static inline void *edev_get_drvdata(struct devfreq_event_dev *edev);
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline struct devfreq_event_dev *devfreq_get_edev(const char *name)
+{
+ return ERR_PTR(-ENODEV);
+}
+
+struct devfreq_event_dev *devfreq_get_edev_by_phandle(struct device *dev,
+ int index)
+{
+ return ERR_PTR(-ENODEV);
+}
+
+static inline int devfreq_put_edev(struct devfreq_event_dev *edev)
+{
+ return -EINVAL;
+}
+
+static inline int devfreq_enable_edev(struct devfreq_event_dev *edev)
+{
+ return -EINVAL;
+}
+
+static inline int devfreq_disable_edev(struct devfreq_event_dev *edev)
+{
+ return -EINVAL;
+}
+
+static inline int devfreq_set_event_edev(struct devfreq_event_dev *edev)
+{
+ return -EINVAL;
+}
+
+static inline int devfreq_get_event_edev(struct devfreq_event_dev *edev)
+{
+ return -EINVAL;
+}
+
+static inline int devfreq_reset_edev(struct devfreq_event_dev *edev)
+{
+ return -EINVAL;
+}
#endif /* CONFIG_PM_DEVFREQ */
#endif /* __LINUX_DEVFREQ_H__ */
--
1.8.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [RFC PATCH 2/5] devfreq: event: Add exynos-ppmu devfreq evnet driver
2014-09-05 4:30 [RFC PATCH 0/5] devfreq: Add devfreq-event class to provide raw data for devfreq device Chanwoo Choi
2014-09-05 4:30 ` [RFC PATCH 1/5] devfreq: Add new devfreq_event class to provide basic data for devfreq governor Chanwoo Choi
@ 2014-09-05 4:30 ` Chanwoo Choi
2014-09-12 8:41 ` Paul Bolle
2014-09-05 4:30 ` [RFC PATCH 3/5] ARM: dts: Add PPMU dt node for Exynos3250 Chanwoo Choi
` (2 subsequent siblings)
4 siblings, 1 reply; 8+ messages in thread
From: Chanwoo Choi @ 2014-09-05 4:30 UTC (permalink / raw)
To: myungjoo.ham, linux-pm
Cc: kyungmin.park, rafael.j.wysocki, a.kesavan, kgene.kim,
tomasz.figa, b.zolnierkie, nm, linux-kernel, linux-samsung-soc,
linux-arm-kernel, Chanwoo Choi
This patch add exynos-ppmu devfreq event driver to provider raw data about
the utilization of each IP in Exynos SoC series.
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/devfreq/Kconfig | 10 +
drivers/devfreq/event/Makefile | 1 +
drivers/devfreq/event/exynos-ppmu.c | 410 ++++++++++++++++++++++++++++++++++++
3 files changed, 421 insertions(+)
create mode 100644 drivers/devfreq/event/exynos-ppmu.c
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index ef839e7..4fbbcea 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -90,4 +90,14 @@ config ARM_EXYNOS5_BUS_DEVFREQ
comment "DEVFREQ Event Drivers"
+config DEVFREQ_EVENT_EXYNOS_PPMU
+ bool "EXYNOS PPMU (Performance Profiling Monitoring Unit) DEVFREQ event Driver"
+ depends on ARCH_EXYNOS
+ select ARCH_HAS_OPP
+ select PM_OPP
+ help
+ This add the DEVFREQ event driver for Exynos SoC. It provides PPMU
+ (Performance Profiling Monitoring Unit) counters to estimate the
+ utilization of each module.
+
endif # PM_DEVFREQ
diff --git a/drivers/devfreq/event/Makefile b/drivers/devfreq/event/Makefile
index dc56005..be146ea 100644
--- a/drivers/devfreq/event/Makefile
+++ b/drivers/devfreq/event/Makefile
@@ -1 +1,2 @@
# Exynos DEVFREQ Event Drivers
+obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_PPMU) += exynos-ppmu.o
diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c
new file mode 100644
index 0000000..54fd492
--- /dev/null
+++ b/drivers/devfreq/event/exynos-ppmu.c
@@ -0,0 +1,410 @@
+/*
+ * exynos_ppmu.c - EXYNOS PPMU (Performance Profiling Monitoring Units) support
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Author : Chanwoo Choi <cw00.choi@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This driver is based on drivers/devfreq/exynos/exynos_ppmu.c
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/suspend.h>
+#include <linux/devfreq.h>
+
+#define PPMU_ENABLE BIT(0)
+#define PPMU_DISABLE 0x0
+#define PPMU_CYCLE_RESET BIT(1)
+#define PPMU_COUNTER_RESET BIT(2)
+
+#define PPMU_ENABLE_COUNT0 BIT(0)
+#define PPMU_ENABLE_COUNT1 BIT(1)
+#define PPMU_ENABLE_COUNT2 BIT(2)
+#define PPMU_ENABLE_COUNT3 BIT(3)
+#define PPMU_ENABLE_CYCLE BIT(31)
+
+#define PPMU_CNTENS 0x10
+#define PPMU_FLAG 0x50
+#define PPMU_CCNT_OVERFLOW BIT(31)
+#define PPMU_CCNT 0x100
+
+#define PPMU_PMCNT0 0x110
+#define PPMU_PMCNT_OFFSET 0x10
+#define PMCNT_OFFSET(x) (PPMU_PMCNT0 + (PPMU_PMCNT_OFFSET * x))
+
+#define PPMU_BEVT0SEL 0x1000
+#define PPMU_BEVTSEL_OFFSET 0x100
+#define PPMU_BEVTSEL(x) (PPMU_BEVT0SEL + (x * PPMU_BEVTSEL_OFFSET))
+
+#define RD_DATA_COUNT 0x5
+#define WR_DATA_COUNT 0x6
+#define RDWR_DATA_COUNT 0x7
+
+enum exynos_ppmu_type {
+ TYPE_PPMU_EXYNOS4210,
+};
+
+enum ppmu_counter {
+ PPMU_PMNCNT0,
+ PPMU_PMNCNT1,
+ PPMU_PMNCNT2,
+ PPMU_PMNCNT3,
+ PPMU_PMNCNT_MAX,
+};
+
+/* Platform data */
+struct exynos_ppmu_data {
+ struct devfreq *devfreq;
+ struct devfreq_event_dev **edev;
+ struct devfreq_event_desc *events;
+ unsigned int num_events;
+
+ struct device *dev;
+ struct clk *clk_ppmu;
+ struct mutex lock;
+
+ enum exynos_ppmu_type type;
+
+ struct __exynos_ppmu {
+ void __iomem *hw_base;
+ unsigned int ccnt;
+ unsigned int event[PPMU_PMNCNT_MAX];
+ unsigned int count[PPMU_PMNCNT_MAX];
+ unsigned long long ns;
+ ktime_t reset_time;
+ bool ccnt_overflow;
+ bool count_overflow[PPMU_PMNCNT_MAX];
+ } ppmu;
+};
+
+static int exynos_ppmu_enable(struct devfreq_event_dev *edev)
+{
+ struct exynos_ppmu_data *exynos_ppmu = edev_get_drvdata(edev);
+
+ __raw_writel(PPMU_ENABLE, exynos_ppmu->ppmu.hw_base);
+
+ return 0;
+}
+
+static int exynos_ppmu_disable(struct devfreq_event_dev *edev)
+{
+ struct exynos_ppmu_data *exynos_ppmu = edev_get_drvdata(edev);
+
+ __raw_writel(PPMU_DISABLE, exynos_ppmu->ppmu.hw_base);
+
+ return 0;
+}
+
+static int exynos_ppmu_set_event(struct devfreq_event_dev *edev)
+{
+ struct exynos_ppmu_data *exynos_ppmu = edev_get_drvdata(edev);
+ void __iomem *ppmu_base = exynos_ppmu->ppmu.hw_base;
+ int id = edev->desc->id;
+
+ __raw_writel(RDWR_DATA_COUNT, ppmu_base + PPMU_BEVTSEL(id));
+
+ return 0;
+}
+
+static int exynos_ppmu_get_event(struct devfreq_event_dev *edev)
+{
+ struct exynos_ppmu_data *exynos_ppmu = edev_get_drvdata(edev);
+ void __iomem *ppmu_base = exynos_ppmu->ppmu.hw_base;
+ int id = edev->desc->id;
+ int count, total_count;
+
+ total_count = __raw_readl(ppmu_base + PPMU_CCNT);
+
+ if (id == PPMU_PMNCNT3)
+ count = ((__raw_readl(ppmu_base + PMCNT_OFFSET(id)) << 8) |
+ __raw_readl(ppmu_base + PMCNT_OFFSET(id + 1)));
+ else
+ count = __raw_readl(ppmu_base + PMCNT_OFFSET(id));
+
+ count = (count * 100) / total_count;
+
+ return count;
+}
+
+static int exynos_ppmu_reset(struct devfreq_event_dev *edev)
+{
+ struct exynos_ppmu_data *exynos_ppmu = edev_get_drvdata(edev);
+ void __iomem *ppmu_base = exynos_ppmu->ppmu.hw_base;
+
+ __raw_writel(PPMU_CYCLE_RESET | PPMU_COUNTER_RESET, ppmu_base);
+ __raw_writel(PPMU_ENABLE_CYCLE |
+ PPMU_ENABLE_COUNT0 |
+ PPMU_ENABLE_COUNT1 |
+ PPMU_ENABLE_COUNT2 |
+ PPMU_ENABLE_COUNT3,
+ ppmu_base + PPMU_CNTENS);
+
+ return 0;
+}
+
+static struct devfreq_event_ops exynos_ppmu_ops = {
+ .enable = exynos_ppmu_enable,
+ .disable = exynos_ppmu_disable,
+ .set_event = exynos_ppmu_set_event,
+ .get_event = exynos_ppmu_get_event,
+ .reset = exynos_ppmu_reset,
+};
+
+static struct of_device_id exynos_ppmu_id_match[] = {
+ {
+ .compatible = "samsung,exynos4210-ppmu",
+ .data = (void *)TYPE_PPMU_EXYNOS4210,
+ },
+};
+
+struct __exynos_ppmu_events {
+ char *name;
+ int id;
+} ppmu_events[] = {
+ { "ppmu-dmc0-pmcnt0", PPMU_PMNCNT0 },
+ { "ppmu-dmc0-pmcnt1", PPMU_PMNCNT1 },
+ { "ppmu-dmc0-pmcnt2", PPMU_PMNCNT2 },
+ { "ppmu-dmc0-pmcnt3", PPMU_PMNCNT3 },
+
+ { "ppmu-dmc1-pmcnt0", PPMU_PMNCNT0 },
+ { "ppmu-dmc1-pmcnt1", PPMU_PMNCNT1 },
+ { "ppmu-dmc1-pmcnt2", PPMU_PMNCNT2 },
+ { "ppmu-dmc1-pmcnt3", PPMU_PMNCNT3 },
+
+ { "ppmu-cpu-pmcnt0", PPMU_PMNCNT0 },
+ { "ppmu-cpu-pmcnt1", PPMU_PMNCNT1 },
+ { "ppmu-cpu-pmcnt2", PPMU_PMNCNT2 },
+ { "ppmu-cpu-pmcnt3", PPMU_PMNCNT3 },
+
+ { "ppmu-rightbus-pmcnt0", PPMU_PMNCNT0 },
+ { "ppmu-rightbus-pmcnt1", PPMU_PMNCNT1 },
+ { "ppmu-rightbus-pmcnt2", PPMU_PMNCNT2 },
+ { "ppmu-rightbus-pmcnt3", PPMU_PMNCNT3 },
+
+ { "ppmu-leftbus-pmcnt0", PPMU_PMNCNT0 },
+ { "ppmu-leftbus-pmcnt1", PPMU_PMNCNT1 },
+ { "ppmu-leftbus-pmcnt2", PPMU_PMNCNT2 },
+ { "ppmu-leftbus-pmcnt3", PPMU_PMNCNT3 },
+
+ { "ppmu-camif-pmcnt0", PPMU_PMNCNT0 },
+ { "ppmu-camif-pmcnt1", PPMU_PMNCNT1 },
+ { "ppmu-camif-pmcnt2", PPMU_PMNCNT2 },
+ { "ppmu-camif-pmcnt3", PPMU_PMNCNT3 },
+
+ { "ppmu-lcd0-pmcnt0", PPMU_PMNCNT0 },
+ { "ppmu-lcd0-pmcnt1", PPMU_PMNCNT1 },
+ { "ppmu-lcd0-pmcnt2", PPMU_PMNCNT2 },
+ { "ppmu-lcd0-pmcnt3", PPMU_PMNCNT3 },
+
+ { "ppmu-g3d-pmcnt0", PPMU_PMNCNT0 },
+ { "ppmu-g3d-pmcnt1", PPMU_PMNCNT1 },
+ { "ppmu-g3d-pmcnt2", PPMU_PMNCNT2 },
+ { "ppmu-g3d-pmcnt3", PPMU_PMNCNT3 },
+
+ { "ppmu-mfc-pmcnt0", PPMU_PMNCNT0 },
+ { "ppmu-mfc-pmcnt1", PPMU_PMNCNT1 },
+ { "ppmu-mfc-pmcnt2", PPMU_PMNCNT2 },
+ { "ppmu-mfc-pmcnt3", PPMU_PMNCNT3 },
+
+ { "ppmu-fsys-pmcnt0", PPMU_PMNCNT0 },
+ { "ppmu-fsys-pmcnt1", PPMU_PMNCNT1 },
+ { "ppmu-fsys-pmcnt2", PPMU_PMNCNT2 },
+ { "ppmu-fsys-pmcnt3", PPMU_PMNCNT3 },
+ { /* sentinel */ },
+};
+
+static int of_get_devfreq_events(struct device_node *np,
+ struct exynos_ppmu_data *exynos_ppmu)
+{
+ struct devfreq_event_desc *events;
+ struct device *dev = exynos_ppmu->dev;
+ struct device_node *events_np, *node;
+ int i, j, count;
+
+ events_np = of_find_node_by_name(np, "events");
+ if (!events_np) {
+ dev_err(dev, "Failed to find ppmus sub-node\n");
+ return -EINVAL;
+ }
+
+ count = of_get_child_count(events_np);
+ events = devm_kzalloc(dev, sizeof(struct devfreq_event_desc) * count,
+ GFP_KERNEL);
+ if (!events)
+ return -ENOMEM;
+ exynos_ppmu->num_events = count;
+
+ j = 0;
+ for_each_child_of_node(events_np, node) {
+ for (i = 0; i < ARRAY_SIZE(ppmu_events); i++) {
+ if (!of_node_cmp(node->name, ppmu_events[i].name))
+ break;
+ }
+
+ if (i == ARRAY_SIZE(ppmu_events)) {
+ dev_warn(dev,
+ "don't know how to configure events : %s\n",
+ node->name);
+ continue;
+ }
+ events[j].id = ppmu_events[i].id;
+ events[j].ops = &exynos_ppmu_ops;
+ events[j].owner = THIS_MODULE;
+ events[j].dev = dev;
+ events[j].driver_data = exynos_ppmu;
+ of_property_read_string(node, "event-name", &events[j].name);
+ j++;
+ }
+ exynos_ppmu->events = events;
+
+ return 0;
+}
+
+static int exynos_ppmu_parse_dt(struct exynos_ppmu_data *exynos_ppmu)
+{
+ struct device *dev = exynos_ppmu->dev;
+ struct device_node *np = dev->of_node;
+ int ret = 0;
+
+ if (!np) {
+ dev_err(dev, "Failed to find devicetree node\n");
+ return -EINVAL;
+ }
+
+ /* Maps the memory mapped IO to control PPMU register */
+ exynos_ppmu->ppmu.hw_base = of_iomap(np, 0);
+ if (IS_ERR_OR_NULL(exynos_ppmu->ppmu.hw_base)) {
+ dev_err(dev, "Failed to map memory region\n");
+ ret = -EINVAL;
+ goto err_iomap;
+ }
+
+ /* FIXME: Get the clock of ppmu and enable this clock */
+ exynos_ppmu->clk_ppmu = devm_clk_get(dev, "ppmu");
+ if (IS_ERR(exynos_ppmu->clk_ppmu))
+ dev_warn(dev, "Failed to get PPMU clock\n");
+
+ ret = of_get_devfreq_events(np, exynos_ppmu);
+ if (ret < 0) {
+ dev_err(dev, "Failed to parse exynos ppmu dt node\n");
+ goto err_clock;
+ }
+
+ return 0;
+
+err_clock:
+ clk_disable_unprepare(exynos_ppmu->clk_ppmu);
+err_iomap:
+ iounmap(exynos_ppmu->ppmu.hw_base);
+
+ return ret;
+}
+
+static int exynos_ppmu_get_driver_data(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const struct of_device_id *match;
+
+ match = of_match_node(exynos_ppmu_id_match, dev->of_node);
+ if (!match)
+ return -ENODEV;
+
+ return (int) match->data;
+}
+
+static int exynos_ppmu_probe(struct platform_device *pdev)
+{
+ struct exynos_ppmu_data *exynos_ppmu;
+ struct devfreq_event_dev **edev;
+ struct devfreq_event_desc *events;
+ int i, ret = 0, size;
+
+ /* Allocate the memory of exynos_ppmu_data and initialize it */
+ exynos_ppmu = devm_kzalloc(&pdev->dev, sizeof(struct exynos_ppmu_data),
+ GFP_KERNEL);
+ if (!exynos_ppmu)
+ return -ENOMEM;
+
+ mutex_init(&exynos_ppmu->lock);
+ exynos_ppmu->type = exynos_ppmu_get_driver_data(pdev);
+ exynos_ppmu->dev = &pdev->dev;
+
+ /* Parse dt data to get resource */
+ ret = exynos_ppmu_parse_dt(exynos_ppmu);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to parse DT node for resource\n");
+ return ret;
+ }
+ events = exynos_ppmu->events;
+
+ size = sizeof(struct devfreq_event_dev *) * exynos_ppmu->num_events;
+ exynos_ppmu->edev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+ if (!exynos_ppmu->edev) {
+ dev_err(&pdev->dev,
+ "Failed to allocate memory devfreq_event_dev list\n");
+ return -ENOMEM;
+ }
+ edev = exynos_ppmu->edev;
+ platform_set_drvdata(pdev, exynos_ppmu);
+
+ for (i = 0; i < exynos_ppmu->num_events; i++) {
+ edev[i] = devfreq_add_event_device(&pdev->dev, &events[i]);
+ if (IS_ERR(edev)) {
+ ret = PTR_ERR(edev);
+ dev_err(&pdev->dev, "Failed to add devfreq evt dev\n");
+ goto err;
+ }
+ }
+
+ return 0;
+err:
+ clk_disable_unprepare(exynos_ppmu->clk_ppmu);
+ iounmap(exynos_ppmu->ppmu.hw_base);
+
+ return ret;
+}
+
+static int exynos_ppmu_remove(struct platform_device *pdev)
+{
+ struct exynos_ppmu_data *exynos_ppmu = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(exynos_ppmu->clk_ppmu);
+ iounmap(exynos_ppmu->ppmu.hw_base);
+
+ /* Remove devfreq instance */
+ devfreq_remove_device(exynos_ppmu->devfreq);
+
+ return 0;
+}
+
+static const struct platform_device_id exynos_ppmu_id[] = {
+ { "exynos4210-ppmu", TYPE_PPMU_EXYNOS4210 },
+ { },
+};
+
+static struct platform_driver exynos_ppmu_driver = {
+ .probe = exynos_ppmu_probe,
+ .remove = exynos_ppmu_remove,
+ .id_table = exynos_ppmu_id,
+ .driver = {
+ .name = "exynos-ppmu",
+ .owner = THIS_MODULE,
+ .of_match_table = exynos_ppmu_id_match,
+ },
+};
+
+module_platform_driver(exynos_ppmu_driver);
+
+MODULE_DESCRIPTION("EXYNOS PPMU(Performance Profiling Monitoring Unit) driver");
+MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:exynos-ppmu");
--
1.8.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [RFC PATCH 3/5] ARM: dts: Add PPMU dt node for Exynos3250
2014-09-05 4:30 [RFC PATCH 0/5] devfreq: Add devfreq-event class to provide raw data for devfreq device Chanwoo Choi
2014-09-05 4:30 ` [RFC PATCH 1/5] devfreq: Add new devfreq_event class to provide basic data for devfreq governor Chanwoo Choi
2014-09-05 4:30 ` [RFC PATCH 2/5] devfreq: event: Add exynos-ppmu devfreq evnet driver Chanwoo Choi
@ 2014-09-05 4:30 ` Chanwoo Choi
2014-09-05 4:30 ` [RFC PATCH 4/5] ARM: dts: Add PPMU dt node for Exynos4 SoC Chanwoo Choi
2014-09-05 4:30 ` [RFC PATCH 5/5] ARM: dts: Add dt node fo PPMU_CPU/DMC0/DMC1 for exynos4412-trats2 Chanwoo Choi
4 siblings, 0 replies; 8+ messages in thread
From: Chanwoo Choi @ 2014-09-05 4:30 UTC (permalink / raw)
To: myungjoo.ham, linux-pm
Cc: kyungmin.park, rafael.j.wysocki, a.kesavan, kgene.kim,
tomasz.figa, b.zolnierkie, nm, linux-kernel, linux-samsung-soc,
linux-arm-kernel, Chanwoo Choi
This patch add PPMU (Performance Profiling Monitoring Units) dt node
to estimate the utilization of each IP in Exynos SoC throught DEVFREQ Event
subsystem.
This patch adds following PPMU dt nodes:
- PPMU_DMC0 0x106a0000
- PPMU_DMC1 0x106b0000
- PPMU_RIGHTBUS 0x112A0000
- PPMU_LEFTBUS 0x116A0000
- PPMU_CAMIF 0x11AC0000
- PPMU_LCD0 0x11E40000
- PPMU_3D 0x13220000
- PPMU_MFC_L 0x13660000
- PPMU_CPU 0x106c0000
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/boot/dts/exynos3250.dtsi | 66 +++++++++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi
index 1d52de6..20a4c59 100644
--- a/arch/arm/boot/dts/exynos3250.dtsi
+++ b/arch/arm/boot/dts/exynos3250.dtsi
@@ -465,6 +465,72 @@
compatible = "arm,cortex-a7-pmu";
interrupts = <0 18 0>, <0 19 0>;
};
+
+ ppmu_dmc0: ppmu_dmc0@106a0000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x106a0000 0x2000>;
+ status = "disabled";
+ };
+
+ ppmu_dmc1: ppmu_dmc1@106b0000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x106b0000 0x2000>;
+ status = "disabled";
+ };
+
+ ppmu_cpu: ppmu_cpu@106c0000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x106c0000 0x2000>;
+ status = "disabled";
+ };
+
+ ppmu_rightbus: ppmu_rightbus@112a0000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x112a0000 0x2000>;
+ clocks = <&cmu CLK_PPMURIGHT>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
+
+ ppmu_leftbus: ppmu_leftbus0@116a0000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x116a0000 0x2000>;
+ clocks = <&cmu CLK_PPMULEFT>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
+
+ ppmu_camif: ppmu_camif@11ac0000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x11ac0000 0x2000>;
+ clocks = <&cmu CLK_PPMUCAMIF>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
+
+ ppmu_lcd0: ppmu_lcd0@11e40000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x11e40000 0x2000>;
+ clocks = <&cmu CLK_PPMULCD0>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
+
+ ppmu_g3d: ppmu_g3d@13220000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x13220000 0x2000>;
+ clocks = <&cmu CLK_PPMUG3D>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
+
+ ppmu_mfc_l: ppmu_mfc_l@13660000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x13660000 0x2000>;
+ clocks = <&cmu CLK_PPMUMFC_L>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
};
};
--
1.8.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [RFC PATCH 4/5] ARM: dts: Add PPMU dt node for Exynos4 SoC
2014-09-05 4:30 [RFC PATCH 0/5] devfreq: Add devfreq-event class to provide raw data for devfreq device Chanwoo Choi
` (2 preceding siblings ...)
2014-09-05 4:30 ` [RFC PATCH 3/5] ARM: dts: Add PPMU dt node for Exynos3250 Chanwoo Choi
@ 2014-09-05 4:30 ` Chanwoo Choi
2014-09-05 4:30 ` [RFC PATCH 5/5] ARM: dts: Add dt node fo PPMU_CPU/DMC0/DMC1 for exynos4412-trats2 Chanwoo Choi
4 siblings, 0 replies; 8+ messages in thread
From: Chanwoo Choi @ 2014-09-05 4:30 UTC (permalink / raw)
To: myungjoo.ham, linux-pm
Cc: kyungmin.park, rafael.j.wysocki, a.kesavan, kgene.kim,
tomasz.figa, b.zolnierkie, nm, linux-kernel, linux-samsung-soc,
linux-arm-kernel, Chanwoo Choi
This patch add PPMU (Performance Profiling Monitoring Unit) dt node for Exynos4
(Exynos4210/4212/4412) SoC. PPMU dt node is used to monitor the utilization of
each IP.
The Exynos4210/Exynos4212/Exynos4412 SoC includes following PPMUs:
- PPMU_DMC0 0x106A_0000
- PPMU_DMC1 0x106B_0000
- PPMU_CPU 0x106C_0000
- PPMU_ACP 0x10AE_0000
- PPMU_RIGHT_BUS 0x112A_0000
- PPMU_LEFT_BUS 0x116A_0000
- PPMU_LCD0 0x11E4_0000
- PPMU_CAMIF 0x11AC_0000
- PPMU_IMAGE 0x12AA_0000
- PPMU_TV 0x12E4_0000
- PPMU_3D 0x1322_0000
- PPMU_MFC_L 0x1366_0000
- PPMU_MFC_R 0x1367_0000
Additionally, the Exynos4210 SoC includes following PPMUs:
- PPMU_LCD1 0x1224_0000
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/boot/dts/exynos4.dtsi | 96 +++++++++++++++++++++++++++++++++++++++
arch/arm/boot/dts/exynos4210.dtsi | 8 ++++
2 files changed, 104 insertions(+)
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index e0278ec..c58d3f3 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -645,4 +645,100 @@
samsung,sysreg = <&sys_reg>;
status = "disabled";
};
+
+ ppmu_dmc0: ppmu_dmc0@106a0000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x106a0000 0x2000>;
+ clocks = <&clock CLK_PPMUDMC0>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
+
+ ppmu_dmc1: ppmu_dmc1@106b0000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x106b0000 0x2000>;
+ clocks = <&clock CLK_PPMUDMC1>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
+
+ ppmu_cpu: ppmu_cpu@106c0000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x106c0000 0x2000>;
+ clocks = <&clock CLK_PPMUCPU>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
+
+ ppmu_rightbus: ppmu_rightbus@112a0000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x112a0000 0x2000>;
+ clocks = <&clock CLK_PPMURIGHT>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
+
+ ppmu_leftbus: ppmu_leftbus0@116a0000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x116a0000 0x2000>;
+ clocks = <&clock CLK_PPMULEFT>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
+
+ ppmu_camif: ppmu_camif@11ac0000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x11ac0000 0x2000>;
+ clocks = <&clock CLK_PPMUCAMIF>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
+
+ ppmu_lcd0: ppmu_lcd0@11e40000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x11e40000 0x2000>;
+ clocks = <&clock CLK_PPMULCD0>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
+
+ ppmu_image: ppmu_image@12aa0000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x12aa0000 0x2000>;
+ clocks = <&clock CLK_PPMUIMAGE>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
+
+ ppmu_tv: ppmu_tv@12e40000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x12e40000 0x2000>;
+ clocks = <&clock CLK_PPMUTV>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
+
+ ppmu_g3d: ppmu_g3d@13220000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x13220000 0x2000>;
+ clocks = <&clock CLK_PPMUG3D>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
+
+ ppmu_mfc_l: ppmu_mfc_l@13660000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x13660000 0x2000>;
+ clocks = <&clock CLK_PPMUMFC_L>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
+
+ ppmu_mfc_r: ppmu_mfc_r@13670000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x13670000 0x2000>;
+ clocks = <&clock CLK_PPMUMFC_R>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
};
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index 807bb5b..1b854e6 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -175,4 +175,12 @@
samsung,lcd-wb;
};
};
+
+ ppmu_lcd1: ppmu_lcd1@12240000 {
+ compatible = "samsung,exynos4210-ppmu";
+ reg = <0x12240000 0x2000>;
+ clocks = <&clock CLK_PPMULCD1>;
+ clock-names = "ppmu";
+ status = "disabled";
+ };
};
--
1.8.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [RFC PATCH 5/5] ARM: dts: Add dt node fo PPMU_CPU/DMC0/DMC1 for exynos4412-trats2
2014-09-05 4:30 [RFC PATCH 0/5] devfreq: Add devfreq-event class to provide raw data for devfreq device Chanwoo Choi
` (3 preceding siblings ...)
2014-09-05 4:30 ` [RFC PATCH 4/5] ARM: dts: Add PPMU dt node for Exynos4 SoC Chanwoo Choi
@ 2014-09-05 4:30 ` Chanwoo Choi
4 siblings, 0 replies; 8+ messages in thread
From: Chanwoo Choi @ 2014-09-05 4:30 UTC (permalink / raw)
To: myungjoo.ham, linux-pm
Cc: kyungmin.park, rafael.j.wysocki, a.kesavan, kgene.kim,
tomasz.figa, b.zolnierkie, nm, linux-kernel, linux-samsung-soc,
linux-arm-kernel, Chanwoo Choi
This patch add dt node for PPMU_CPU/DMC0/DMC1 for exynos4412-trats2 board.
Each PPMU dt node includes one event of 'PPMU Count 3'
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/boot/dts/exynos4412-trats2.dts | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts
index 11967f4..00dcb91 100644
--- a/arch/arm/boot/dts/exynos4412-trats2.dts
+++ b/arch/arm/boot/dts/exynos4412-trats2.dts
@@ -770,6 +770,35 @@
status = "okay";
};
+ ppmu_cpu: ppmu_cpu@106c0000 {
+ status = "okay";
+
+ events {
+ ppmu_cpu_3: ppmu-cpu-pmcnt3 {
+ event-name = "ppmu-cpu-pmcnt3";
+ };
+ };
+ };
+
+ ppmu_dmc0: ppmu_dmc0@106a0000 {
+ status = "okay";
+
+ events {
+ ppmu_dmc0_3: ppmu-dmc0-pmcnt3 {
+ event-name = "ppmu-dmc0-pmcnt3";
+ };
+ };
+ };
+
+ ppmu_dmc1: ppmu_dmc1@106b0000 {
+ status = "okay";
+
+ events {
+ ppmu_dmc1_3: ppmu-dmc1-pmcnt3 {
+ event-name = "ppmu-dmc1-pmcnt3";
+ };
+ };
+
thermistor-ap@0 {
compatible = "ntc,ncp15wb473";
pullup-uv = <1800000>; /* VCC_1.8V_AP */
--
1.8.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [RFC PATCH 2/5] devfreq: event: Add exynos-ppmu devfreq evnet driver
2014-09-05 4:30 ` [RFC PATCH 2/5] devfreq: event: Add exynos-ppmu devfreq evnet driver Chanwoo Choi
@ 2014-09-12 8:41 ` Paul Bolle
2014-09-23 2:11 ` Chanwoo Choi
0 siblings, 1 reply; 8+ messages in thread
From: Paul Bolle @ 2014-09-12 8:41 UTC (permalink / raw)
To: Chanwoo Choi
Cc: myungjoo.ham, linux-pm, kyungmin.park, rafael.j.wysocki,
a.kesavan, kgene.kim, tomasz.figa, b.zolnierkie, nm, linux-kernel,
linux-samsung-soc, linux-arm-kernel
On Fri, 2014-09-05 at 13:30 +0900, Chanwoo Choi wrote:
> This patch add exynos-ppmu devfreq event driver to provider raw data about
> the utilization of each IP in Exynos SoC series.
>
> Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
> Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
> drivers/devfreq/Kconfig | 10 +
> drivers/devfreq/event/Makefile | 1 +
> drivers/devfreq/event/exynos-ppmu.c | 410 ++++++++++++++++++++++++++++++++++++
> 3 files changed, 421 insertions(+)
> create mode 100644 drivers/devfreq/event/exynos-ppmu.c
>
> diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
> index ef839e7..4fbbcea 100644
> --- a/drivers/devfreq/Kconfig
> +++ b/drivers/devfreq/Kconfig
> @@ -90,4 +90,14 @@ config ARM_EXYNOS5_BUS_DEVFREQ
>
> comment "DEVFREQ Event Drivers"
>
> +config DEVFREQ_EVENT_EXYNOS_PPMU
> + bool "EXYNOS PPMU (Performance Profiling Monitoring Unit) DEVFREQ event Driver"
> + depends on ARCH_EXYNOS
> + select ARCH_HAS_OPP
This select statement can be dropped: see commit 78c5e0bb145d ("PM /
OPP: Remove ARCH_HAS_OPP").
By the way: there's a typo in the commit summary ("evnet").
> + select PM_OPP
> + help
> + This add the DEVFREQ event driver for Exynos SoC. It provides PPMU
> + (Performance Profiling Monitoring Unit) counters to estimate the
> + utilization of each module.
> +
> endif # PM_DEVFREQ
Paul Bolle
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC PATCH 2/5] devfreq: event: Add exynos-ppmu devfreq evnet driver
2014-09-12 8:41 ` Paul Bolle
@ 2014-09-23 2:11 ` Chanwoo Choi
0 siblings, 0 replies; 8+ messages in thread
From: Chanwoo Choi @ 2014-09-23 2:11 UTC (permalink / raw)
To: Paul Bolle
Cc: myungjoo.ham, linux-pm, kyungmin.park, rafael.j.wysocki,
a.kesavan, kgene.kim, tomasz.figa, b.zolnierkie, nm, linux-kernel,
linux-samsung-soc, linux-arm-kernel
Hi Paul,
On 09/12/2014 05:41 PM, Paul Bolle wrote:
> On Fri, 2014-09-05 at 13:30 +0900, Chanwoo Choi wrote:
>> This patch add exynos-ppmu devfreq event driver to provider raw data about
>> the utilization of each IP in Exynos SoC series.
>>
>> Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
>> Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
>> ---
>> drivers/devfreq/Kconfig | 10 +
>> drivers/devfreq/event/Makefile | 1 +
>> drivers/devfreq/event/exynos-ppmu.c | 410 ++++++++++++++++++++++++++++++++++++
>> 3 files changed, 421 insertions(+)
>> create mode 100644 drivers/devfreq/event/exynos-ppmu.c
>>
>> diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
>> index ef839e7..4fbbcea 100644
>> --- a/drivers/devfreq/Kconfig
>> +++ b/drivers/devfreq/Kconfig
>> @@ -90,4 +90,14 @@ config ARM_EXYNOS5_BUS_DEVFREQ
>>
>> comment "DEVFREQ Event Drivers"
>>
>> +config DEVFREQ_EVENT_EXYNOS_PPMU
>> + bool "EXYNOS PPMU (Performance Profiling Monitoring Unit) DEVFREQ event Driver"
>> + depends on ARCH_EXYNOS
>> + select ARCH_HAS_OPP
>
> This select statement can be dropped: see commit 78c5e0bb145d ("PM /
> OPP: Remove ARCH_HAS_OPP").
I'll drop it.
>
> By the way: there's a typo in the commit summary ("evnet").
My mistake, I'll fix typo.
Thanks for your review.
Chanwoo Choi
>
>> + select PM_OPP
>> + help
>> + This add the DEVFREQ event driver for Exynos SoC. It provides PPMU
>> + (Performance Profiling Monitoring Unit) counters to estimate the
>> + utilization of each module.
>> +
>> endif # PM_DEVFREQ
>
>
> Paul Bolle
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2014-09-23 2:11 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-09-05 4:30 [RFC PATCH 0/5] devfreq: Add devfreq-event class to provide raw data for devfreq device Chanwoo Choi
2014-09-05 4:30 ` [RFC PATCH 1/5] devfreq: Add new devfreq_event class to provide basic data for devfreq governor Chanwoo Choi
2014-09-05 4:30 ` [RFC PATCH 2/5] devfreq: event: Add exynos-ppmu devfreq evnet driver Chanwoo Choi
2014-09-12 8:41 ` Paul Bolle
2014-09-23 2:11 ` Chanwoo Choi
2014-09-05 4:30 ` [RFC PATCH 3/5] ARM: dts: Add PPMU dt node for Exynos3250 Chanwoo Choi
2014-09-05 4:30 ` [RFC PATCH 4/5] ARM: dts: Add PPMU dt node for Exynos4 SoC Chanwoo Choi
2014-09-05 4:30 ` [RFC PATCH 5/5] ARM: dts: Add dt node fo PPMU_CPU/DMC0/DMC1 for exynos4412-trats2 Chanwoo Choi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox