Commit 2b328421 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files
Pull devfreq updates for v5.5 from Chanwoo Choi:

"1. Update devfreq core

 - Check NULL governor in available_governors_show sysfs in order to prevent
   showing wrong governor information.

 - Fix race condition between devfreq_update_status() and trans_stat_show()

 - Add new 'interrupt-driven' flag for devfreq goveroris. Each devfreq driver can
   add their own interrupt-driven governor (NIVIDIA Tegra30 ACTMON governor). It
   needs to use the following sysfs interface to get the new polling interval in
   order to change the NVIDIA Tegra30 hardware's polling interval.

   : /sys/class/devfreq/devfreqX/polling_interval

   So, if 'interrupt-driven' flag of devfreq governor is 1, the devfreq governor
   is able to use the 'polling_interval' sysfs interface to get the new polling
   interval value. But, the devfreq core doesn't schedule out the polling work
   for this governor like NVIDIA Tegra30 ACTMON governor.

 2. Update devfreq drivers

 - For exynos-bus.c, remove unused property from dt-binding documentation

 - For tegra30-devfreq.c, update the internal behavior like fixing the overflow
   integer issue and clean-up code.

 3. Update devfreq-event driver

 - For exynos-ppmu.c, add exynos_ppmu.h dt-binding file for 'event-data-type' filed.
   and update dt-binging documentation. Also,  Fix minor coding style."

* tag 'devfreq-next-for-5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux: (25 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 c389ec67 fee22854
Loading
Loading
Loading
Loading
+24 −2
Original line number Diff line number Diff line
@@ -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
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.
- 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"
- 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.

		ppmu_dmc0: ppmu_dmc0@106a0000 {
@@ -145,3 +154,16 @@ Example3 : PPMUv2 nodes in exynos5433.dtsi are listed below.
			reg = <0x104d0000 0x2000>;
			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)>;
			};
		};
	};
+0 −2
Original line number Diff line number Diff line
@@ -50,8 +50,6 @@ Required properties only for passive bus device:
Optional properties only for parent bus device:
- exynos,saturation-ratio: the percentage value which is used to calibrate
			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:
- In case of Exynos3250, there are two power line as following:
+1 −0
Original line number Diff line number Diff line
@@ -4778,6 +4778,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git
S:	Supported
F:	drivers/devfreq/event/
F:	drivers/devfreq/devfreq-event.c
F:	include/dt-bindings/pmu/exynos_ppmu.h
F:	include/linux/devfreq-event.h
F:	Documentation/devicetree/bindings/devfreq/event/
+28 −5
Original line number Diff line number Diff line
@@ -160,6 +160,7 @@ int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
	int lev, prev_lev, ret = 0;
	unsigned long cur_time;

	lockdep_assert_held(&devfreq->lock);
	cur_time = jiffies;

	/* Immediately exit if previous_freq is not initialized yet. */
@@ -409,6 +410,9 @@ static void devfreq_monitor(struct work_struct *work)
 */
void devfreq_monitor_start(struct devfreq *devfreq)
{
	if (devfreq->governor->interrupt_driven)
		return;

	INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor);
	if (devfreq->profile->polling_ms)
		queue_delayed_work(devfreq_wq, &devfreq->work,
@@ -426,6 +430,9 @@ EXPORT_SYMBOL(devfreq_monitor_start);
 */
void devfreq_monitor_stop(struct devfreq *devfreq)
{
	if (devfreq->governor->interrupt_driven)
		return;

	cancel_delayed_work_sync(&devfreq->work);
}
EXPORT_SYMBOL(devfreq_monitor_stop);
@@ -453,6 +460,10 @@ void devfreq_monitor_suspend(struct devfreq *devfreq)
	devfreq_update_status(devfreq, devfreq->previous_freq);
	devfreq->stop_polling = true;
	mutex_unlock(&devfreq->lock);

	if (devfreq->governor->interrupt_driven)
		return;

	cancel_delayed_work_sync(&devfreq->work);
}
EXPORT_SYMBOL(devfreq_monitor_suspend);
@@ -473,11 +484,15 @@ void devfreq_monitor_resume(struct devfreq *devfreq)
	if (!devfreq->stop_polling)
		goto out;

	if (devfreq->governor->interrupt_driven)
		goto out_update;

	if (!delayed_work_pending(&devfreq->work) &&
			devfreq->profile->polling_ms)
		queue_delayed_work(devfreq_wq, &devfreq->work,
			msecs_to_jiffies(devfreq->profile->polling_ms));

out_update:
	devfreq->last_stat_updated = jiffies;
	devfreq->stop_polling = false;

@@ -509,6 +524,9 @@ void devfreq_interval_update(struct devfreq *devfreq, unsigned int *delay)
	if (devfreq->stop_polling)
		goto out;

	if (devfreq->governor->interrupt_driven)
		goto out;

	/* if new delay is zero, stop polling */
	if (!new_delay) {
		mutex_unlock(&devfreq->lock);
@@ -625,7 +643,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
	devfreq = find_device_devfreq(dev);
	mutex_unlock(&devfreq_list_lock);
	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__);
		err = -EINVAL;
		goto err_out;
@@ -1195,7 +1213,7 @@ static ssize_t available_governors_show(struct device *d,
	 * The devfreq with immutable governor (e.g., passive) shows
	 * only own governor.
	 */
	if (df->governor->immutable) {
	if (df->governor && df->governor->immutable) {
		count = scnprintf(&buf[count], DEVFREQ_NAME_LEN,
				  "%s ", df->governor_name);
	/*
@@ -1397,12 +1415,17 @@ static ssize_t trans_stat_show(struct device *dev,
	int i, j;
	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)
		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 + len, "           :");
	for (i = 0; i < max_state; i++)
+0 −1
Original line number Diff line number Diff line
@@ -673,7 +673,6 @@ static int exynos_ppmu_probe(struct platform_device *pdev)
	for (i = 0; i < info->num_events; i++) {
		edev[i] = devm_devfreq_event_add_edev(&pdev->dev, &desc[i]);
		if (IS_ERR(edev[i])) {
			ret = PTR_ERR(edev[i]);
			dev_err(&pdev->dev,
				"failed to add devfreq-event device\n");
			return PTR_ERR(edev[i]);
Loading