Commit fa6a599e authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branch 'pm-devfreq'

* pm-devfreq: (26 commits)
  PM / devfreq: tegra30: Tune up MCCPU boost-down coefficient
  PM / devfreq: tegra30: Support variable polling interval
  PM / devfreq: Add new interrupt_driven flag for governors
  PM / devfreq: tegra30: Use kHz units for dependency threshold
  PM / devfreq: tegra30: Disable consecutive interrupts when appropriate
  PM / devfreq: tegra30: Don't enable already enabled consecutive interrupts
  PM / devfreq: tegra30: Include appropriate header
  PM / devfreq: tegra30: Constify structs
  PM / devfreq: tegra30: Don't enable consecutive-down interrupt on startup
  PM / devfreq: tegra30: Reset boosting on startup
  PM / devfreq: tegra30: Move clk-notifier's registration to governor's start
  PM / devfreq: tegra30: Use CPUFreq notifier
  PM / devfreq: tegra30: Use kHz units uniformly in the code
  PM / devfreq: tegra30: Fix integer overflow on CPU's freq max out
  PM / devfreq: tegra30: Drop write-barrier
  PM / devfreq: tegra30: Handle possible round-rate error
  PM / devfreq: tegra30: Keep interrupt disabled while governor is stopped
  PM / devfreq: tegra30: Change irq type to unsigned int
  PM / devfreq: exynos-ppmu: remove useless assignment
  PM / devfreq: Lock devfreq in trans_stat_show
  ...
parents c48b90f8 2b328421
...@@ -10,14 +10,23 @@ The Exynos PPMU driver uses the devfreq-event class to provide event data ...@@ -10,14 +10,23 @@ The Exynos PPMU driver uses the devfreq-event class to provide event data
to various devfreq devices. The devfreq devices would use the event data when to various devfreq devices. The devfreq devices would use the event data when
derterming the current state of each IP. derterming the current state of each IP.
Required properties: Required properties for PPMU device:
- compatible: Should be "samsung,exynos-ppmu" or "samsung,exynos-ppmu-v2. - compatible: Should be "samsung,exynos-ppmu" or "samsung,exynos-ppmu-v2.
- reg: physical base address of each PPMU and length of memory mapped region. - reg: physical base address of each PPMU and length of memory mapped region.
Optional properties: Optional properties for PPMU device:
- clock-names : the name of clock used by the PPMU, "ppmu" - clock-names : the name of clock used by the PPMU, "ppmu"
- clocks : phandles for clock specified in "clock-names" property - clocks : phandles for clock specified in "clock-names" property
Required properties for 'events' child node of PPMU device:
- event-name : the unique event name among PPMU device
Optional properties for 'events' child node of PPMU device:
- event-data-type : Define the type of data which shell be counted
by the counter. You can check include/dt-bindings/pmu/exynos_ppmu.h for
all possible type, i.e. count read requests, count write data in bytes,
etc. This field is optional and when it is missing, the driver code
will use default data type.
Example1 : PPMUv1 nodes in exynos3250.dtsi are listed below. Example1 : PPMUv1 nodes in exynos3250.dtsi are listed below.
ppmu_dmc0: ppmu_dmc0@106a0000 { ppmu_dmc0: ppmu_dmc0@106a0000 {
...@@ -145,3 +154,16 @@ Example3 : PPMUv2 nodes in exynos5433.dtsi are listed below. ...@@ -145,3 +154,16 @@ Example3 : PPMUv2 nodes in exynos5433.dtsi are listed below.
reg = <0x104d0000 0x2000>; reg = <0x104d0000 0x2000>;
status = "disabled"; status = "disabled";
}; };
Example4 : 'event-data-type' in exynos4412-ppmu-common.dtsi are listed below.
&ppmu_dmc0 {
status = "okay";
events {
ppmu_dmc0_3: ppmu-event3-dmc0 {
event-name = "ppmu-event3-dmc0";
event-data-type = <(PPMU_RO_DATA_CNT |
PPMU_WO_DATA_CNT)>;
};
};
};
...@@ -50,8 +50,6 @@ Required properties only for passive bus device: ...@@ -50,8 +50,6 @@ Required properties only for passive bus device:
Optional properties only for parent bus device: Optional properties only for parent bus device:
- exynos,saturation-ratio: the percentage value which is used to calibrate - exynos,saturation-ratio: the percentage value which is used to calibrate
the performance count against total cycle count. the performance count against total cycle count.
- exynos,voltage-tolerance: the percentage value for bus voltage tolerance
which is used to calculate the max voltage.
Detailed correlation between sub-blocks and power line according to Exynos SoC: Detailed correlation between sub-blocks and power line according to Exynos SoC:
- In case of Exynos3250, there are two power line as following: - In case of Exynos3250, there are two power line as following:
......
...@@ -3532,7 +3532,7 @@ BUS FREQUENCY DRIVER FOR SAMSUNG EXYNOS ...@@ -3532,7 +3532,7 @@ BUS FREQUENCY DRIVER FOR SAMSUNG EXYNOS
M: Chanwoo Choi <cw00.choi@samsung.com> M: Chanwoo Choi <cw00.choi@samsung.com>
L: linux-pm@vger.kernel.org L: linux-pm@vger.kernel.org
L: linux-samsung-soc@vger.kernel.org L: linux-samsung-soc@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git
S: Maintained S: Maintained
F: drivers/devfreq/exynos-bus.c F: drivers/devfreq/exynos-bus.c
F: Documentation/devicetree/bindings/devfreq/exynos-bus.txt F: Documentation/devicetree/bindings/devfreq/exynos-bus.txt
...@@ -4760,9 +4760,9 @@ F: include/linux/devcoredump.h ...@@ -4760,9 +4760,9 @@ F: include/linux/devcoredump.h
DEVICE FREQUENCY (DEVFREQ) DEVICE FREQUENCY (DEVFREQ)
M: MyungJoo Ham <myungjoo.ham@samsung.com> M: MyungJoo Ham <myungjoo.ham@samsung.com>
M: Kyungmin Park <kyungmin.park@samsung.com> M: Kyungmin Park <kyungmin.park@samsung.com>
R: Chanwoo Choi <cw00.choi@samsung.com> M: Chanwoo Choi <cw00.choi@samsung.com>
L: linux-pm@vger.kernel.org L: linux-pm@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git
S: Maintained S: Maintained
F: drivers/devfreq/ F: drivers/devfreq/
F: include/linux/devfreq.h F: include/linux/devfreq.h
...@@ -4772,10 +4772,11 @@ F: include/trace/events/devfreq.h ...@@ -4772,10 +4772,11 @@ F: include/trace/events/devfreq.h
DEVICE FREQUENCY EVENT (DEVFREQ-EVENT) DEVICE FREQUENCY EVENT (DEVFREQ-EVENT)
M: Chanwoo Choi <cw00.choi@samsung.com> M: Chanwoo Choi <cw00.choi@samsung.com>
L: linux-pm@vger.kernel.org L: linux-pm@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git
S: Supported S: Supported
F: drivers/devfreq/event/ F: drivers/devfreq/event/
F: drivers/devfreq/devfreq-event.c F: drivers/devfreq/devfreq-event.c
F: include/dt-bindings/pmu/exynos_ppmu.h
F: include/linux/devfreq-event.h F: include/linux/devfreq-event.h
F: Documentation/devicetree/bindings/devfreq/event/ F: Documentation/devicetree/bindings/devfreq/event/
......
...@@ -160,6 +160,7 @@ int devfreq_update_status(struct devfreq *devfreq, unsigned long freq) ...@@ -160,6 +160,7 @@ 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;
lockdep_assert_held(&devfreq->lock);
cur_time = jiffies; cur_time = jiffies;
/* Immediately exit if previous_freq is not initialized yet. */ /* Immediately exit if previous_freq is not initialized yet. */
...@@ -409,6 +410,9 @@ static void devfreq_monitor(struct work_struct *work) ...@@ -409,6 +410,9 @@ static void devfreq_monitor(struct work_struct *work)
*/ */
void devfreq_monitor_start(struct devfreq *devfreq) void devfreq_monitor_start(struct devfreq *devfreq)
{ {
if (devfreq->governor->interrupt_driven)
return;
INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor); INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor);
if (devfreq->profile->polling_ms) if (devfreq->profile->polling_ms)
queue_delayed_work(devfreq_wq, &devfreq->work, queue_delayed_work(devfreq_wq, &devfreq->work,
...@@ -426,6 +430,9 @@ EXPORT_SYMBOL(devfreq_monitor_start); ...@@ -426,6 +430,9 @@ EXPORT_SYMBOL(devfreq_monitor_start);
*/ */
void devfreq_monitor_stop(struct devfreq *devfreq) void devfreq_monitor_stop(struct devfreq *devfreq)
{ {
if (devfreq->governor->interrupt_driven)
return;
cancel_delayed_work_sync(&devfreq->work); cancel_delayed_work_sync(&devfreq->work);
} }
EXPORT_SYMBOL(devfreq_monitor_stop); EXPORT_SYMBOL(devfreq_monitor_stop);
...@@ -453,6 +460,10 @@ void devfreq_monitor_suspend(struct devfreq *devfreq) ...@@ -453,6 +460,10 @@ void devfreq_monitor_suspend(struct devfreq *devfreq)
devfreq_update_status(devfreq, devfreq->previous_freq); devfreq_update_status(devfreq, devfreq->previous_freq);
devfreq->stop_polling = true; devfreq->stop_polling = true;
mutex_unlock(&devfreq->lock); mutex_unlock(&devfreq->lock);
if (devfreq->governor->interrupt_driven)
return;
cancel_delayed_work_sync(&devfreq->work); cancel_delayed_work_sync(&devfreq->work);
} }
EXPORT_SYMBOL(devfreq_monitor_suspend); EXPORT_SYMBOL(devfreq_monitor_suspend);
...@@ -473,11 +484,15 @@ void devfreq_monitor_resume(struct devfreq *devfreq) ...@@ -473,11 +484,15 @@ void devfreq_monitor_resume(struct devfreq *devfreq)
if (!devfreq->stop_polling) if (!devfreq->stop_polling)
goto out; goto out;
if (devfreq->governor->interrupt_driven)
goto out_update;
if (!delayed_work_pending(&devfreq->work) && if (!delayed_work_pending(&devfreq->work) &&
devfreq->profile->polling_ms) devfreq->profile->polling_ms)
queue_delayed_work(devfreq_wq, &devfreq->work, queue_delayed_work(devfreq_wq, &devfreq->work,
msecs_to_jiffies(devfreq->profile->polling_ms)); msecs_to_jiffies(devfreq->profile->polling_ms));
out_update:
devfreq->last_stat_updated = jiffies; devfreq->last_stat_updated = jiffies;
devfreq->stop_polling = false; devfreq->stop_polling = false;
...@@ -509,6 +524,9 @@ void devfreq_interval_update(struct devfreq *devfreq, unsigned int *delay) ...@@ -509,6 +524,9 @@ void devfreq_interval_update(struct devfreq *devfreq, unsigned int *delay)
if (devfreq->stop_polling) if (devfreq->stop_polling)
goto out; goto out;
if (devfreq->governor->interrupt_driven)
goto out;
/* if new delay is zero, stop polling */ /* if new delay is zero, stop polling */
if (!new_delay) { if (!new_delay) {
mutex_unlock(&devfreq->lock); mutex_unlock(&devfreq->lock);
...@@ -625,7 +643,7 @@ struct devfreq *devfreq_add_device(struct device *dev, ...@@ -625,7 +643,7 @@ 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.\n", dev_err(dev, "%s: devfreq device already exists!\n",
__func__); __func__);
err = -EINVAL; err = -EINVAL;
goto err_out; goto err_out;
...@@ -1195,7 +1213,7 @@ static ssize_t available_governors_show(struct device *d, ...@@ -1195,7 +1213,7 @@ static ssize_t available_governors_show(struct device *d,
* The devfreq with immutable governor (e.g., passive) shows * The devfreq with immutable governor (e.g., passive) shows
* only own governor. * only own governor.
*/ */
if (df->governor->immutable) { if (df->governor && df->governor->immutable) {
count = scnprintf(&buf[count], DEVFREQ_NAME_LEN, count = scnprintf(&buf[count], DEVFREQ_NAME_LEN,
"%s ", df->governor_name); "%s ", df->governor_name);
/* /*
...@@ -1397,12 +1415,17 @@ static ssize_t trans_stat_show(struct device *dev, ...@@ -1397,12 +1415,17 @@ static ssize_t trans_stat_show(struct device *dev,
int i, j; int i, j;
unsigned int max_state = devfreq->profile->max_state; unsigned int max_state = devfreq->profile->max_state;
if (!devfreq->stop_polling &&
devfreq_update_status(devfreq, devfreq->previous_freq))
return 0;
if (max_state == 0) if (max_state == 0)
return sprintf(buf, "Not Supported.\n"); return sprintf(buf, "Not Supported.\n");
mutex_lock(&devfreq->lock);
if (!devfreq->stop_polling &&
devfreq_update_status(devfreq, devfreq->previous_freq)) {
mutex_unlock(&devfreq->lock);
return 0;
}
mutex_unlock(&devfreq->lock);
len = sprintf(buf, " From : To\n"); len = sprintf(buf, " From : To\n");
len += sprintf(buf + len, " :"); len += sprintf(buf + len, " :");
for (i = 0; i < max_state; i++) for (i = 0; i < max_state; i++)
......
...@@ -673,7 +673,6 @@ static int exynos_ppmu_probe(struct platform_device *pdev) ...@@ -673,7 +673,6 @@ static int exynos_ppmu_probe(struct platform_device *pdev)
for (i = 0; i < info->num_events; i++) { for (i = 0; i < info->num_events; i++) {
edev[i] = devm_devfreq_event_add_edev(&pdev->dev, &desc[i]); edev[i] = devm_devfreq_event_add_edev(&pdev->dev, &desc[i]);
if (IS_ERR(edev[i])) { if (IS_ERR(edev[i])) {
ret = PTR_ERR(edev[i]);
dev_err(&pdev->dev, dev_err(&pdev->dev,
"failed to add devfreq-event device\n"); "failed to add devfreq-event device\n");
return PTR_ERR(edev[i]); return PTR_ERR(edev[i]);
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
* @name: Governor's name * @name: Governor's name
* @immutable: Immutable flag for governor. If the value is 1, * @immutable: Immutable flag for governor. If the value is 1,
* this govenror is never changeable to other governor. * this govenror is never changeable to other governor.
* @interrupt_driven: Devfreq core won't schedule polling work for this
* governor if value is set to 1.
* @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
...@@ -49,6 +51,7 @@ struct devfreq_governor { ...@@ -49,6 +51,7 @@ struct devfreq_governor {
const char name[DEVFREQ_NAME_LEN]; const char name[DEVFREQ_NAME_LEN];
const unsigned int immutable; const unsigned int immutable;
const unsigned int interrupt_driven;
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);
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Samsung Exynos PPMU event types for counting in regs
*
* Copyright (c) 2019, Samsung Electronics
* Author: Lukasz Luba <l.luba@partner.samsung.com>
*/
#ifndef __DT_BINDINGS_PMU_EXYNOS_PPMU_H
#define __DT_BINDINGS_PMU_EXYNOS_PPMU_H
#define PPMU_RO_BUSY_CYCLE_CNT 0x0
#define PPMU_WO_BUSY_CYCLE_CNT 0x1
#define PPMU_RW_BUSY_CYCLE_CNT 0x2
#define PPMU_RO_REQUEST_CNT 0x3
#define PPMU_WO_REQUEST_CNT 0x4
#define PPMU_RO_DATA_CNT 0x5
#define PPMU_WO_DATA_CNT 0x6
#define PPMU_RO_LATENCY 0x12
#define PPMU_WO_LATENCY 0x16
#define PPMU_V2_RO_DATA_CNT 0x4
#define PPMU_V2_WO_DATA_CNT 0x5
#define PPMU_V2_EVT3_RW_DATA_CNT 0x22
#endif
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