Skip to content

Commit

Permalink
Merge tag 'pullreq201908' of ssh://gitolite.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/mzx/devfreq

Pull devfreq changes for v5.4 from MyungJoo Ham:

"This series include:

- Tegra driver fixes
- new Tegra devices
- Rockchip fixes
- Exynos-bus fixes
- Event: add "event type"
- Passive: notifier updates"

* tag 'pullreq201908' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq: (27 commits)
  PM / devfreq: passive: Use non-devm notifiers
  PM / devfreq: exynos-bus: Convert to use dev_pm_opp_set_rate()
  PM / devfreq: exynos-bus: Correct clock enable sequence
  PM / devfreq: Correct devm_devfreq_remove_device() documentation
  PM / devfreq: events: extend events by type of counted data
  PM / devfreq: exynos-events: change matching code during probe
  PM / devfreq: tegra20: add COMMON_CLK dependency
  PM / devfreq: events: add Exynos PPMU new events
  PM / devfreq: Fix kernel oops on governor module load
  PM / devfreq: rk3399_dmc: Fix spelling typo
  PM / devfreq: Fix spelling typo
  PM / devfreq: Introduce driver for NVIDIA Tegra20
  PM / devfreq: tegra: Rename tegra-devfreq.c to tegra30-devfreq.c
  PM / devfreq: tegra: Enable COMPILE_TEST for the driver
  PM / devfreq: tegra: Support Tegra30
  PM / devfreq: tegra: Reconfigure hardware on governor's restart
  PM / devfreq: tegra: Move governor registration to driver's probe
  PM / devfreq: tegra: Mark ACTMON's governor as immutable
  PM / devfreq: tegra: Avoid inconsistency of current frequency value
  PM / devfreq: tegra: Clean up driver's probe / remove
  ...
  • Loading branch information
rafaeljw committed Aug 26, 2019
2 parents a55aa89 + 0ef7c7c commit 47e6a8d
Show file tree
Hide file tree
Showing 10 changed files with 500 additions and 332 deletions.
19 changes: 16 additions & 3 deletions drivers/devfreq/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,28 @@ config ARM_EXYNOS_BUS_DEVFREQ
This does not yet operate with optimal voltages.

config ARM_TEGRA_DEVFREQ
tristate "Tegra DEVFREQ Driver"
depends on ARCH_TEGRA_124_SOC
select DEVFREQ_GOV_SIMPLE_ONDEMAND
tristate "NVIDIA Tegra30/114/124/210 DEVFREQ Driver"
depends on ARCH_TEGRA_3x_SOC || ARCH_TEGRA_114_SOC || \
ARCH_TEGRA_132_SOC || ARCH_TEGRA_124_SOC || \
ARCH_TEGRA_210_SOC || \
COMPILE_TEST
select PM_OPP
help
This adds the DEVFREQ driver for the Tegra family of SoCs.
It reads ACTMON counters of memory controllers and adjusts the
operating frequencies and voltages with OPP support.

config ARM_TEGRA20_DEVFREQ
tristate "NVIDIA Tegra20 DEVFREQ Driver"
depends on (TEGRA_MC && TEGRA20_EMC) || COMPILE_TEST
depends on COMMON_CLK
select DEVFREQ_GOV_SIMPLE_ONDEMAND
select PM_OPP
help
This adds the DEVFREQ driver for the Tegra20 family of SoCs.
It reads Memory Controller counters and adjusts the operating
frequencies and voltages with OPP support.

config ARM_RK3399_DMC_DEVFREQ
tristate "ARM RK3399 DMC DEVFREQ Driver"
depends on ARCH_ROCKCHIP
Expand Down
3 changes: 2 additions & 1 deletion drivers/devfreq/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o
# DEVFREQ Drivers
obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o
obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o
obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra-devfreq.o
obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o
obj-$(CONFIG_ARM_TEGRA20_DEVFREQ) += tegra20-devfreq.o

# DEVFREQ Event Drivers
obj-$(CONFIG_PM_DEVFREQ_EVENT) += event/
12 changes: 6 additions & 6 deletions drivers/devfreq/devfreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ static struct devfreq_governor *try_then_request_governor(const char *name)
/* Restore previous state before return */
mutex_lock(&devfreq_list_lock);
if (err)
return ERR_PTR(err);
return (err < 0) ? ERR_PTR(err) : ERR_PTR(-EINVAL);

governor = find_devfreq_governor(name);
}
Expand Down Expand Up @@ -402,7 +402,7 @@ static void devfreq_monitor(struct work_struct *work)
* devfreq_monitor_start() - Start load monitoring of devfreq instance
* @devfreq: the devfreq instance.
*
* Helper function for starting devfreq device load monitoing. By
* Helper function for starting devfreq device load monitoring. By
* default delayed work based monitoring is supported. Function
* to be called from governor in response to DEVFREQ_GOV_START
* event when device is added to devfreq framework.
Expand All @@ -420,7 +420,7 @@ EXPORT_SYMBOL(devfreq_monitor_start);
* devfreq_monitor_stop() - Stop load monitoring of a devfreq instance
* @devfreq: the devfreq instance.
*
* Helper function to stop devfreq device load monitoing. Function
* Helper function to stop devfreq device load monitoring. Function
* to be called from governor in response to DEVFREQ_GOV_STOP
* event when device is removed from devfreq framework.
*/
Expand All @@ -434,7 +434,7 @@ EXPORT_SYMBOL(devfreq_monitor_stop);
* devfreq_monitor_suspend() - Suspend load monitoring of a devfreq instance
* @devfreq: the devfreq instance.
*
* Helper function to suspend devfreq device load monitoing. Function
* Helper function to suspend devfreq device load monitoring. Function
* to be called from governor in response to DEVFREQ_GOV_SUSPEND
* event or when polling interval is set to zero.
*
Expand All @@ -461,7 +461,7 @@ EXPORT_SYMBOL(devfreq_monitor_suspend);
* devfreq_monitor_resume() - Resume load monitoring of a devfreq instance
* @devfreq: the devfreq instance.
*
* Helper function to resume devfreq device load monitoing. Function
* Helper function to resume devfreq device load monitoring. Function
* to be called from governor in response to DEVFREQ_GOV_RESUME
* event or when polling interval is set to non-zero.
*/
Expand Down Expand Up @@ -867,7 +867,7 @@ EXPORT_SYMBOL_GPL(devfreq_get_devfreq_by_phandle);

/**
* devm_devfreq_remove_device() - Resource-managed devfreq_remove_device()
* @dev: the device to add devfreq feature.
* @dev: the device from which to remove devfreq feature.
* @devfreq: the devfreq instance to be removed
*/
void devm_devfreq_remove_device(struct device *dev, struct devfreq *devfreq)
Expand Down
104 changes: 72 additions & 32 deletions drivers/devfreq/event/exynos-ppmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,19 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/suspend.h>
#include <linux/devfreq-event.h>

#include "exynos-ppmu.h"

enum exynos_ppmu_type {
EXYNOS_TYPE_PPMU,
EXYNOS_TYPE_PPMU_V2,
};

struct exynos_ppmu_data {
struct clk *clk;
};
Expand All @@ -33,6 +39,7 @@ struct exynos_ppmu {
struct regmap *regmap;

struct exynos_ppmu_data ppmu;
enum exynos_ppmu_type ppmu_type;
};

#define PPMU_EVENT(name) \
Expand Down Expand Up @@ -86,6 +93,12 @@ static struct __exynos_ppmu_events {
PPMU_EVENT(d1-cpu),
PPMU_EVENT(d1-general),
PPMU_EVENT(d1-rt),

/* For Exynos5422 SoC */
PPMU_EVENT(dmc0_0),
PPMU_EVENT(dmc0_1),
PPMU_EVENT(dmc1_0),
PPMU_EVENT(dmc1_1),
};

static int exynos_ppmu_find_ppmu_id(struct devfreq_event_dev *edev)
Expand Down Expand Up @@ -151,9 +164,9 @@ static int exynos_ppmu_set_event(struct devfreq_event_dev *edev)
if (ret < 0)
return ret;

/* Set the event of Read/Write data count */
/* Set the event of proper data type monitoring */
ret = regmap_write(info->regmap, PPMU_BEVTxSEL(id),
PPMU_RO_DATA_CNT | PPMU_WO_DATA_CNT);
edev->desc->event_type);
if (ret < 0)
return ret;

Expand Down Expand Up @@ -365,23 +378,11 @@ static int exynos_ppmu_v2_set_event(struct devfreq_event_dev *edev)
if (ret < 0)
return ret;

/* Set the event of Read/Write data count */
switch (id) {
case PPMU_PMNCNT0:
case PPMU_PMNCNT1:
case PPMU_PMNCNT2:
ret = regmap_write(info->regmap, PPMU_V2_CH_EVx_TYPE(id),
PPMU_V2_RO_DATA_CNT | PPMU_V2_WO_DATA_CNT);
if (ret < 0)
return ret;
break;
case PPMU_PMNCNT3:
ret = regmap_write(info->regmap, PPMU_V2_CH_EVx_TYPE(id),
PPMU_V2_EVT3_RW_DATA_CNT);
if (ret < 0)
return ret;
break;
}
/* Set the event of proper data type monitoring */
ret = regmap_write(info->regmap, PPMU_V2_CH_EVx_TYPE(id),
edev->desc->event_type);
if (ret < 0)
return ret;

/* Reset cycle counter/performance counter and enable PPMU */
ret = regmap_read(info->regmap, PPMU_V2_PMNC, &pmnc);
Expand Down Expand Up @@ -480,46 +481,44 @@ static const struct devfreq_event_ops exynos_ppmu_v2_ops = {
static const struct of_device_id exynos_ppmu_id_match[] = {
{
.compatible = "samsung,exynos-ppmu",
.data = (void *)&exynos_ppmu_ops,
.data = (void *)EXYNOS_TYPE_PPMU,
}, {
.compatible = "samsung,exynos-ppmu-v2",
.data = (void *)&exynos_ppmu_v2_ops,
.data = (void *)EXYNOS_TYPE_PPMU_V2,
},
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, exynos_ppmu_id_match);

static struct devfreq_event_ops *exynos_bus_get_ops(struct device_node *np)
{
const struct of_device_id *match;

match = of_match_node(exynos_ppmu_id_match, np);
return (struct devfreq_event_ops *)match->data;
}

static int of_get_devfreq_events(struct device_node *np,
struct exynos_ppmu *info)
{
struct devfreq_event_desc *desc;
struct devfreq_event_ops *event_ops;
struct device *dev = info->dev;
struct device_node *events_np, *node;
int i, j, count;
const struct of_device_id *of_id;
int ret;

events_np = of_get_child_by_name(np, "events");
if (!events_np) {
dev_err(dev,
"failed to get child node of devfreq-event devices\n");
return -EINVAL;
}
event_ops = exynos_bus_get_ops(np);

count = of_get_child_count(events_np);
desc = devm_kcalloc(dev, count, sizeof(*desc), GFP_KERNEL);
if (!desc)
return -ENOMEM;
info->num_events = count;

of_id = of_match_device(exynos_ppmu_id_match, dev);
if (of_id)
info->ppmu_type = (enum exynos_ppmu_type)of_id->data;
else
return -EINVAL;

j = 0;
for_each_child_of_node(events_np, node) {
for (i = 0; i < ARRAY_SIZE(ppmu_events); i++) {
Expand All @@ -537,10 +536,51 @@ static int of_get_devfreq_events(struct device_node *np,
continue;
}

desc[j].ops = event_ops;
switch (info->ppmu_type) {
case EXYNOS_TYPE_PPMU:
desc[j].ops = &exynos_ppmu_ops;
break;
case EXYNOS_TYPE_PPMU_V2:
desc[j].ops = &exynos_ppmu_v2_ops;
break;
}

desc[j].driver_data = info;

of_property_read_string(node, "event-name", &desc[j].name);
ret = of_property_read_u32(node, "event-data-type",
&desc[j].event_type);
if (ret) {
/* Set the event of proper data type counting.
* Check if the data type has been defined in DT,
* use default if not.
*/
if (info->ppmu_type == EXYNOS_TYPE_PPMU_V2) {
struct devfreq_event_dev edev;
int id;
/* Not all registers take the same value for
* read+write data count.
*/
edev.desc = &desc[j];
id = exynos_ppmu_find_ppmu_id(&edev);

switch (id) {
case PPMU_PMNCNT0:
case PPMU_PMNCNT1:
case PPMU_PMNCNT2:
desc[j].event_type = PPMU_V2_RO_DATA_CNT
| PPMU_V2_WO_DATA_CNT;
break;
case PPMU_PMNCNT3:
desc[j].event_type =
PPMU_V2_EVT3_RW_DATA_CNT;
break;
}
} else {
desc[j].event_type = PPMU_RO_DATA_CNT |
PPMU_WO_DATA_CNT;
}
}

j++;
}
Expand Down
Loading

0 comments on commit 47e6a8d

Please sign in to comment.