summaryrefslogtreecommitdiff
path: root/drivers/bus
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-10-20 00:10:27 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-10-20 00:10:27 -0300
commitd0b2f91bede3bd5e3d24dd6803e56eee959c1797 (patch)
tree7fee4ab0509879c373c4f2cbd5b8a5be5b4041ee /drivers/bus
parente914f8eb445e8f74b00303c19c2ffceaedd16a05 (diff)
Linux-libre 4.8.2-gnupck-4.8.2-gnu
Diffstat (limited to 'drivers/bus')
-rw-r--r--drivers/bus/Kconfig13
-rw-r--r--drivers/bus/Makefile1
-rw-r--r--drivers/bus/arm-cci.c55
-rw-r--r--drivers/bus/arm-ccn.c142
-rw-r--r--drivers/bus/imx-weim.c5
-rw-r--r--drivers/bus/mvebu-mbus.c10
-rw-r--r--drivers/bus/tegra-aconnect.c112
-rw-r--r--drivers/bus/uniphier-system-bus.c3
-rw-r--r--drivers/bus/vexpress-config.c1
9 files changed, 244 insertions, 98 deletions
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index c5a7de9bc..3b205e212 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -132,6 +132,19 @@ config SUNXI_RSB
with various RSB based devices, such as AXP223, AXP8XX PMICs,
and AC100/AC200 ICs.
+# TODO: This uses pm_clk_*() symbols that aren't exported in v4.7 and hence
+# the driver will fail to build as a module. However there are patches to
+# address that queued for v4.8, so this can be turned into a tristate symbol
+# after v4.8-rc1.
+config TEGRA_ACONNECT
+ bool "Tegra ACONNECT Bus Driver"
+ depends on ARCH_TEGRA_210_SOC
+ depends on OF && PM
+ select PM_CLK
+ help
+ Driver for the Tegra ACONNECT bus which is used to interface with
+ the devices inside the Audio Processing Engine (APE) for Tegra210.
+
config UNIPHIER_SYSTEM_BUS
tristate "UniPhier System Bus driver"
depends on ARCH_UNIPHIER && OF
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index ccff007ee..ac84cc434 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -17,5 +17,6 @@ obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o
obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
+obj-$(CONFIG_TEGRA_ACONNECT) += tegra-aconnect.o
obj-$(CONFIG_UNIPHIER_SYSTEM_BUS) += uniphier-system-bus.o
obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o
diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index a49b28378..ffa7c9dcb 100644
--- a/drivers/bus/arm-cci.c
+++ b/drivers/bus/arm-cci.c
@@ -144,12 +144,15 @@ struct cci_pmu {
int num_cntrs;
atomic_t active_events;
struct mutex reserve_mutex;
- struct notifier_block cpu_nb;
+ struct list_head entry;
cpumask_t cpus;
};
#define to_cci_pmu(c) (container_of(c, struct cci_pmu, pmu))
+static DEFINE_MUTEX(cci_pmu_mutex);
+static LIST_HEAD(cci_pmu_list);
+
enum cci_models {
#ifdef CONFIG_ARM_CCI400_PMU
CCI400_R0,
@@ -548,7 +551,7 @@ static struct attribute *cci5xx_pmu_event_attrs[] = {
CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_wrq, 0xB),
CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_cd_hs, 0xC),
CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_rq_stall_addr_hazard, 0xD),
- CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snopp_rq_stall_tt_full, 0xE),
+ CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_rq_stall_tt_full, 0xE),
CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_rq_tzmp1_prot, 0xF),
NULL
};
@@ -1503,31 +1506,26 @@ static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev)
return perf_pmu_register(&cci_pmu->pmu, name, -1);
}
-static int cci_pmu_cpu_notifier(struct notifier_block *self,
- unsigned long action, void *hcpu)
+static int cci_pmu_offline_cpu(unsigned int cpu)
{
- struct cci_pmu *cci_pmu = container_of(self,
- struct cci_pmu, cpu_nb);
- unsigned int cpu = (long)hcpu;
+ struct cci_pmu *cci_pmu;
unsigned int target;
- switch (action & ~CPU_TASKS_FROZEN) {
- case CPU_DOWN_PREPARE:
+ mutex_lock(&cci_pmu_mutex);
+ list_for_each_entry(cci_pmu, &cci_pmu_list, entry) {
if (!cpumask_test_and_clear_cpu(cpu, &cci_pmu->cpus))
- break;
+ continue;
target = cpumask_any_but(cpu_online_mask, cpu);
- if (target >= nr_cpu_ids) // UP, last CPU
- break;
+ if (target >= nr_cpu_ids)
+ continue;
/*
* TODO: migrate context once core races on event->ctx have
* been fixed.
*/
cpumask_set_cpu(target, &cci_pmu->cpus);
- default:
- break;
}
-
- return NOTIFY_OK;
+ mutex_unlock(&cci_pmu_mutex);
+ return 0;
}
static struct cci_pmu_model cci_pmu_models[] = {
@@ -1766,24 +1764,13 @@ static int cci_pmu_probe(struct platform_device *pdev)
atomic_set(&cci_pmu->active_events, 0);
cpumask_set_cpu(smp_processor_id(), &cci_pmu->cpus);
- cci_pmu->cpu_nb = (struct notifier_block) {
- .notifier_call = cci_pmu_cpu_notifier,
- /*
- * to migrate uncore events, our notifier should be executed
- * before perf core's notifier.
- */
- .priority = CPU_PRI_PERF + 1,
- };
-
- ret = register_cpu_notifier(&cci_pmu->cpu_nb);
+ ret = cci_pmu_init(cci_pmu, pdev);
if (ret)
return ret;
- ret = cci_pmu_init(cci_pmu, pdev);
- if (ret) {
- unregister_cpu_notifier(&cci_pmu->cpu_nb);
- return ret;
- }
+ mutex_lock(&cci_pmu_mutex);
+ list_add(&cci_pmu->entry, &cci_pmu_list);
+ mutex_unlock(&cci_pmu_mutex);
pr_info("ARM %s PMU driver probed", cci_pmu->model->name);
return 0;
@@ -1817,6 +1804,12 @@ static int __init cci_platform_init(void)
{
int ret;
+ ret = cpuhp_setup_state_nocalls(CPUHP_AP_PERF_ARM_CCI_ONLINE,
+ "AP_PERF_ARM_CCI_ONLINE", NULL,
+ cci_pmu_offline_cpu);
+ if (ret)
+ return ret;
+
ret = platform_driver_register(&cci_pmu_driver);
if (ret)
return ret;
diff --git a/drivers/bus/arm-ccn.c b/drivers/bus/arm-ccn.c
index d88372b79..884c0305e 100644
--- a/drivers/bus/arm-ccn.c
+++ b/drivers/bus/arm-ccn.c
@@ -167,7 +167,7 @@ struct arm_ccn_dt {
struct hrtimer hrtimer;
cpumask_t cpu;
- struct notifier_block cpu_nb;
+ struct list_head entry;
struct pmu pmu;
};
@@ -190,6 +190,8 @@ struct arm_ccn {
int mn_id;
};
+static DEFINE_MUTEX(arm_ccn_mutex);
+static LIST_HEAD(arm_ccn_list);
static int arm_ccn_node_to_xp(int node)
{
@@ -211,6 +213,7 @@ static int arm_ccn_node_to_xp_port(int node)
#define CCN_CONFIG_TYPE(_config) (((_config) >> 8) & 0xff)
#define CCN_CONFIG_EVENT(_config) (((_config) >> 16) & 0xff)
#define CCN_CONFIG_PORT(_config) (((_config) >> 24) & 0x3)
+#define CCN_CONFIG_BUS(_config) (((_config) >> 24) & 0x3)
#define CCN_CONFIG_VC(_config) (((_config) >> 26) & 0x7)
#define CCN_CONFIG_DIR(_config) (((_config) >> 29) & 0x1)
#define CCN_CONFIG_MASK(_config) (((_config) >> 30) & 0xf)
@@ -240,6 +243,7 @@ static CCN_FORMAT_ATTR(xp, "config:0-7");
static CCN_FORMAT_ATTR(type, "config:8-15");
static CCN_FORMAT_ATTR(event, "config:16-23");
static CCN_FORMAT_ATTR(port, "config:24-25");
+static CCN_FORMAT_ATTR(bus, "config:24-25");
static CCN_FORMAT_ATTR(vc, "config:26-28");
static CCN_FORMAT_ATTR(dir, "config:29-29");
static CCN_FORMAT_ATTR(mask, "config:30-33");
@@ -252,6 +256,7 @@ static struct attribute *arm_ccn_pmu_format_attrs[] = {
&arm_ccn_pmu_format_attr_type.attr.attr,
&arm_ccn_pmu_format_attr_event.attr.attr,
&arm_ccn_pmu_format_attr_port.attr.attr,
+ &arm_ccn_pmu_format_attr_bus.attr.attr,
&arm_ccn_pmu_format_attr_vc.attr.attr,
&arm_ccn_pmu_format_attr_dir.attr.attr,
&arm_ccn_pmu_format_attr_mask.attr.attr,
@@ -349,10 +354,14 @@ static ssize_t arm_ccn_pmu_event_show(struct device *dev,
break;
case CCN_TYPE_XP:
res += snprintf(buf + res, PAGE_SIZE - res,
- ",xp=?,port=?,vc=?,dir=?");
+ ",xp=?,vc=?");
if (event->event == CCN_EVENT_WATCHPOINT)
res += snprintf(buf + res, PAGE_SIZE - res,
- ",cmp_l=?,cmp_h=?,mask=?");
+ ",port=?,dir=?,cmp_l=?,cmp_h=?,mask=?");
+ else
+ res += snprintf(buf + res, PAGE_SIZE - res,
+ ",bus=?");
+
break;
case CCN_TYPE_MN:
res += snprintf(buf + res, PAGE_SIZE - res, ",node=%d", ccn->mn_id);
@@ -736,9 +745,10 @@ static int arm_ccn_pmu_event_init(struct perf_event *event)
if (has_branch_stack(event) || event->attr.exclude_user ||
event->attr.exclude_kernel || event->attr.exclude_hv ||
- event->attr.exclude_idle) {
+ event->attr.exclude_idle || event->attr.exclude_host ||
+ event->attr.exclude_guest) {
dev_warn(ccn->dev, "Can't exclude execution levels!\n");
- return -EOPNOTSUPP;
+ return -EINVAL;
}
if (event->cpu < 0) {
@@ -930,38 +940,17 @@ static void arm_ccn_pmu_event_start(struct perf_event *event, int flags)
arm_ccn_pmu_read_counter(ccn, hw->idx));
hw->state = 0;
- /*
- * Pin the timer, so that the overflows are handled by the chosen
- * event->cpu (this is the same one as presented in "cpumask"
- * attribute).
- */
- if (!ccn->irq)
- hrtimer_start(&ccn->dt.hrtimer, arm_ccn_pmu_timer_period(),
- HRTIMER_MODE_REL_PINNED);
-
/* Set the DT bus input, engaging the counter */
arm_ccn_pmu_xp_dt_config(event, 1);
}
static void arm_ccn_pmu_event_stop(struct perf_event *event, int flags)
{
- struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
struct hw_perf_event *hw = &event->hw;
- u64 timeout;
/* Disable counting, setting the DT bus to pass-through mode */
arm_ccn_pmu_xp_dt_config(event, 0);
- if (!ccn->irq)
- hrtimer_cancel(&ccn->dt.hrtimer);
-
- /* Let the DT bus drain */
- timeout = arm_ccn_pmu_read_counter(ccn, CCN_IDX_PMU_CYCLE_COUNTER) +
- ccn->num_xps;
- while (arm_ccn_pmu_read_counter(ccn, CCN_IDX_PMU_CYCLE_COUNTER) <
- timeout)
- cpu_relax();
-
if (flags & PERF_EF_UPDATE)
arm_ccn_pmu_event_update(event);
@@ -1027,7 +1016,7 @@ static void arm_ccn_pmu_xp_event_config(struct perf_event *event)
hw->event_base = CCN_XP_DT_CONFIG__DT_CFG__XP_PMU_EVENT(hw->config_base);
id = (CCN_CONFIG_VC(event->attr.config) << 4) |
- (CCN_CONFIG_PORT(event->attr.config) << 3) |
+ (CCN_CONFIG_BUS(event->attr.config) << 3) |
(CCN_CONFIG_EVENT(event->attr.config) << 0);
val = readl(source->base + CCN_XP_PMU_EVENT_SEL);
@@ -1112,15 +1101,31 @@ static void arm_ccn_pmu_event_config(struct perf_event *event)
spin_unlock(&ccn->dt.config_lock);
}
+static int arm_ccn_pmu_active_counters(struct arm_ccn *ccn)
+{
+ return bitmap_weight(ccn->dt.pmu_counters_mask,
+ CCN_NUM_PMU_EVENT_COUNTERS + 1);
+}
+
static int arm_ccn_pmu_event_add(struct perf_event *event, int flags)
{
int err;
struct hw_perf_event *hw = &event->hw;
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
err = arm_ccn_pmu_event_alloc(event);
if (err)
return err;
+ /*
+ * Pin the timer, so that the overflows are handled by the chosen
+ * event->cpu (this is the same one as presented in "cpumask"
+ * attribute).
+ */
+ if (!ccn->irq && arm_ccn_pmu_active_counters(ccn) == 1)
+ hrtimer_start(&ccn->dt.hrtimer, arm_ccn_pmu_timer_period(),
+ HRTIMER_MODE_REL_PINNED);
+
arm_ccn_pmu_event_config(event);
hw->state = PERF_HES_STOPPED;
@@ -1133,9 +1138,14 @@ static int arm_ccn_pmu_event_add(struct perf_event *event, int flags)
static void arm_ccn_pmu_event_del(struct perf_event *event, int flags)
{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+
arm_ccn_pmu_event_stop(event, PERF_EF_UPDATE);
arm_ccn_pmu_event_release(event);
+
+ if (!ccn->irq && arm_ccn_pmu_active_counters(ccn) == 0)
+ hrtimer_cancel(&ccn->dt.hrtimer);
}
static void arm_ccn_pmu_event_read(struct perf_event *event)
@@ -1143,6 +1153,24 @@ static void arm_ccn_pmu_event_read(struct perf_event *event)
arm_ccn_pmu_event_update(event);
}
+static void arm_ccn_pmu_enable(struct pmu *pmu)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(pmu);
+
+ u32 val = readl(ccn->dt.base + CCN_DT_PMCR);
+ val |= CCN_DT_PMCR__PMU_EN;
+ writel(val, ccn->dt.base + CCN_DT_PMCR);
+}
+
+static void arm_ccn_pmu_disable(struct pmu *pmu)
+{
+ struct arm_ccn *ccn = pmu_to_arm_ccn(pmu);
+
+ u32 val = readl(ccn->dt.base + CCN_DT_PMCR);
+ val &= ~CCN_DT_PMCR__PMU_EN;
+ writel(val, ccn->dt.base + CCN_DT_PMCR);
+}
+
static irqreturn_t arm_ccn_pmu_overflow_handler(struct arm_ccn_dt *dt)
{
u32 pmovsr = readl(dt->base + CCN_DT_PMOVSR);
@@ -1186,30 +1214,27 @@ static enum hrtimer_restart arm_ccn_pmu_timer_handler(struct hrtimer *hrtimer)
}
-static int arm_ccn_pmu_cpu_notifier(struct notifier_block *nb,
- unsigned long action, void *hcpu)
+static int arm_ccn_pmu_offline_cpu(unsigned int cpu)
{
- struct arm_ccn_dt *dt = container_of(nb, struct arm_ccn_dt, cpu_nb);
- struct arm_ccn *ccn = container_of(dt, struct arm_ccn, dt);
- unsigned int cpu = (long)hcpu; /* for (long) see kernel/cpu.c */
+ struct arm_ccn_dt *dt;
unsigned int target;
- switch (action & ~CPU_TASKS_FROZEN) {
- case CPU_DOWN_PREPARE:
+ mutex_lock(&arm_ccn_mutex);
+ list_for_each_entry(dt, &arm_ccn_list, entry) {
+ struct arm_ccn *ccn = container_of(dt, struct arm_ccn, dt);
+
if (!cpumask_test_and_clear_cpu(cpu, &dt->cpu))
- break;
+ continue;
target = cpumask_any_but(cpu_online_mask, cpu);
if (target >= nr_cpu_ids)
- break;
+ continue;
perf_pmu_migrate_context(&dt->pmu, cpu, target);
cpumask_set_cpu(target, &dt->cpu);
if (ccn->irq)
WARN_ON(irq_set_affinity_hint(ccn->irq, &dt->cpu) != 0);
- default:
- break;
}
-
- return NOTIFY_OK;
+ mutex_unlock(&arm_ccn_mutex);
+ return 0;
}
@@ -1268,6 +1293,8 @@ static int arm_ccn_pmu_init(struct arm_ccn *ccn)
.start = arm_ccn_pmu_event_start,
.stop = arm_ccn_pmu_event_stop,
.read = arm_ccn_pmu_event_read,
+ .pmu_enable = arm_ccn_pmu_enable,
+ .pmu_disable = arm_ccn_pmu_disable,
};
/* No overflow interrupt? Have to use a timer instead. */
@@ -1281,16 +1308,6 @@ static int arm_ccn_pmu_init(struct arm_ccn *ccn)
/* Pick one CPU which we will use to collect data from CCN... */
cpumask_set_cpu(smp_processor_id(), &ccn->dt.cpu);
- /*
- * ... and change the selection when it goes offline. Priority is
- * picked to have a chance to migrate events before perf is notified.
- */
- ccn->dt.cpu_nb.notifier_call = arm_ccn_pmu_cpu_notifier;
- ccn->dt.cpu_nb.priority = CPU_PRI_PERF + 1,
- err = register_cpu_notifier(&ccn->dt.cpu_nb);
- if (err)
- goto error_cpu_notifier;
-
/* Also make sure that the overflow interrupt is handled by this CPU */
if (ccn->irq) {
err = irq_set_affinity_hint(ccn->irq, &ccn->dt.cpu);
@@ -1304,12 +1321,13 @@ static int arm_ccn_pmu_init(struct arm_ccn *ccn)
if (err)
goto error_pmu_register;
+ mutex_lock(&arm_ccn_mutex);
+ list_add(&ccn->dt.entry, &arm_ccn_list);
+ mutex_unlock(&arm_ccn_mutex);
return 0;
error_pmu_register:
error_set_affinity:
- unregister_cpu_notifier(&ccn->dt.cpu_nb);
-error_cpu_notifier:
ida_simple_remove(&arm_ccn_pmu_ida, ccn->dt.id);
for (i = 0; i < ccn->num_xps; i++)
writel(0, ccn->xp[i].base + CCN_XP_DT_CONTROL);
@@ -1321,9 +1339,12 @@ static void arm_ccn_pmu_cleanup(struct arm_ccn *ccn)
{
int i;
+ mutex_lock(&arm_ccn_mutex);
+ list_del(&ccn->dt.entry);
+ mutex_unlock(&arm_ccn_mutex);
+
if (ccn->irq)
irq_set_affinity_hint(ccn->irq, NULL);
- unregister_cpu_notifier(&ccn->dt.cpu_nb);
for (i = 0; i < ccn->num_xps; i++)
writel(0, ccn->xp[i].base + CCN_XP_DT_CONTROL);
writel(0, ccn->dt.base + CCN_DT_PMCR);
@@ -1331,7 +1352,6 @@ static void arm_ccn_pmu_cleanup(struct arm_ccn *ccn)
ida_simple_remove(&arm_ccn_pmu_ida, ccn->dt.id);
}
-
static int arm_ccn_for_each_valid_region(struct arm_ccn *ccn,
int (*callback)(struct arm_ccn *ccn, int region,
void __iomem *base, u32 type, u32 id))
@@ -1496,8 +1516,9 @@ static int arm_ccn_probe(struct platform_device *pdev)
/* Can set 'disable' bits, so can acknowledge interrupts */
writel(CCN_MN_ERRINT_STATUS__PMU_EVENTS__ENABLE,
ccn->base + CCN_MN_ERRINT_STATUS);
- err = devm_request_irq(ccn->dev, irq, arm_ccn_irq_handler, 0,
- dev_name(ccn->dev), ccn);
+ err = devm_request_irq(ccn->dev, irq, arm_ccn_irq_handler,
+ IRQF_NOBALANCING | IRQF_NO_THREAD,
+ dev_name(ccn->dev), ccn);
if (err)
return err;
@@ -1550,7 +1571,13 @@ static struct platform_driver arm_ccn_driver = {
static int __init arm_ccn_init(void)
{
- int i;
+ int i, ret;
+
+ ret = cpuhp_setup_state_nocalls(CPUHP_AP_PERF_ARM_CCN_ONLINE,
+ "AP_PERF_ARM_CCN_ONLINE", NULL,
+ arm_ccn_pmu_offline_cpu);
+ if (ret)
+ return ret;
for (i = 0; i < ARRAY_SIZE(arm_ccn_pmu_events); i++)
arm_ccn_pmu_events_attrs[i] = &arm_ccn_pmu_events[i].attr.attr;
@@ -1560,6 +1587,7 @@ static int __init arm_ccn_init(void)
static void __exit arm_ccn_exit(void)
{
+ cpuhp_remove_state_nocalls(CPUHP_AP_PERF_ARM_CCN_ONLINE);
platform_driver_unregister(&arm_ccn_driver);
}
diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c
index 1827fc4d1..4bd361d64 100644
--- a/drivers/bus/imx-weim.c
+++ b/drivers/bus/imx-weim.c
@@ -163,9 +163,8 @@ static int __init weim_parse_dt(struct platform_device *pdev,
}
if (have_child)
- ret = of_platform_populate(pdev->dev.of_node,
- of_default_bus_match_table,
- NULL, &pdev->dev);
+ ret = of_platform_default_populate(pdev->dev.of_node,
+ NULL, &pdev->dev);
if (ret)
dev_err(&pdev->dev, "%s fail to create devices.\n",
pdev->dev.of_node->full_name);
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c
index ce54a0160..c7f396903 100644
--- a/drivers/bus/mvebu-mbus.c
+++ b/drivers/bus/mvebu-mbus.c
@@ -117,7 +117,7 @@ struct mvebu_mbus_soc_data {
unsigned int (*win_remap_offset)(const int win);
void (*setup_cpu_target)(struct mvebu_mbus_state *s);
int (*save_cpu_target)(struct mvebu_mbus_state *s,
- u32 *store_addr);
+ u32 __iomem *store_addr);
int (*show_cpu_target)(struct mvebu_mbus_state *s,
struct seq_file *seq, void *v);
};
@@ -728,7 +728,7 @@ mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus)
static int
mvebu_mbus_default_save_cpu_target(struct mvebu_mbus_state *mbus,
- u32 *store_addr)
+ u32 __iomem *store_addr)
{
int i;
@@ -780,7 +780,7 @@ mvebu_mbus_dove_setup_cpu_target(struct mvebu_mbus_state *mbus)
static int
mvebu_mbus_dove_save_cpu_target(struct mvebu_mbus_state *mbus,
- u32 *store_addr)
+ u32 __iomem *store_addr)
{
int i;
@@ -796,7 +796,7 @@ mvebu_mbus_dove_save_cpu_target(struct mvebu_mbus_state *mbus,
return 4;
}
-int mvebu_mbus_save_cpu_target(u32 *store_addr)
+int mvebu_mbus_save_cpu_target(u32 __iomem *store_addr)
{
return mbus_state.soc->save_cpu_target(&mbus_state, store_addr);
}
@@ -1089,7 +1089,7 @@ static void mvebu_mbus_resume(void)
}
}
-struct syscore_ops mvebu_mbus_syscore_ops = {
+static struct syscore_ops mvebu_mbus_syscore_ops = {
.suspend = mvebu_mbus_suspend,
.resume = mvebu_mbus_resume,
};
diff --git a/drivers/bus/tegra-aconnect.c b/drivers/bus/tegra-aconnect.c
new file mode 100644
index 000000000..7e4104b74
--- /dev/null
+++ b/drivers/bus/tegra-aconnect.c
@@ -0,0 +1,112 @@
+/*
+ * Tegra ACONNECT Bus Driver
+ *
+ * Copyright (C) 2016, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_runtime.h>
+
+static int tegra_aconnect_add_clock(struct device *dev, char *name)
+{
+ struct clk *clk;
+ int ret;
+
+ clk = clk_get(dev, name);
+ if (IS_ERR(clk)) {
+ dev_err(dev, "%s clock not found\n", name);
+ return PTR_ERR(clk);
+ }
+
+ ret = pm_clk_add_clk(dev, clk);
+ if (ret)
+ clk_put(clk);
+
+ return ret;
+}
+
+static int tegra_aconnect_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ if (!pdev->dev.of_node)
+ return -EINVAL;
+
+ ret = pm_clk_create(&pdev->dev);
+ if (ret)
+ return ret;
+
+ ret = tegra_aconnect_add_clock(&pdev->dev, "ape");
+ if (ret)
+ goto clk_destroy;
+
+ ret = tegra_aconnect_add_clock(&pdev->dev, "apb2ape");
+ if (ret)
+ goto clk_destroy;
+
+ pm_runtime_enable(&pdev->dev);
+
+ of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+
+ dev_info(&pdev->dev, "Tegra ACONNECT bus registered\n");
+
+ return 0;
+
+clk_destroy:
+ pm_clk_destroy(&pdev->dev);
+
+ return ret;
+}
+
+static int tegra_aconnect_remove(struct platform_device *pdev)
+{
+ pm_runtime_disable(&pdev->dev);
+
+ pm_clk_destroy(&pdev->dev);
+
+ return 0;
+}
+
+static int tegra_aconnect_runtime_resume(struct device *dev)
+{
+ return pm_clk_resume(dev);
+}
+
+static int tegra_aconnect_runtime_suspend(struct device *dev)
+{
+ return pm_clk_suspend(dev);
+}
+
+static const struct dev_pm_ops tegra_aconnect_pm_ops = {
+ SET_RUNTIME_PM_OPS(tegra_aconnect_runtime_suspend,
+ tegra_aconnect_runtime_resume, NULL)
+};
+
+static const struct of_device_id tegra_aconnect_of_match[] = {
+ { .compatible = "nvidia,tegra210-aconnect", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, tegra_aconnect_of_match);
+
+static struct platform_driver tegra_aconnect_driver = {
+ .probe = tegra_aconnect_probe,
+ .remove = tegra_aconnect_remove,
+ .driver = {
+ .name = "tegra-aconnect",
+ .of_match_table = tegra_aconnect_of_match,
+ .pm = &tegra_aconnect_pm_ops,
+ },
+};
+module_platform_driver(tegra_aconnect_driver);
+
+MODULE_DESCRIPTION("NVIDIA Tegra ACONNECT Bus Driver");
+MODULE_AUTHOR("Jon Hunter <jonathanh@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/bus/uniphier-system-bus.c b/drivers/bus/uniphier-system-bus.c
index 350b7309c..1e6e0269e 100644
--- a/drivers/bus/uniphier-system-bus.c
+++ b/drivers/bus/uniphier-system-bus.c
@@ -257,8 +257,7 @@ static int uniphier_system_bus_probe(struct platform_device *pdev)
uniphier_system_bus_set_reg(priv);
/* Now, the bus is configured. Populate platform_devices below it */
- return of_platform_populate(dev->of_node, of_default_bus_match_table,
- NULL, dev);
+ return of_platform_default_populate(dev->of_node, NULL, dev);
}
static const struct of_device_id uniphier_system_bus_match[] = {
diff --git a/drivers/bus/vexpress-config.c b/drivers/bus/vexpress-config.c
index c3cb76b36..9efdf1de4 100644
--- a/drivers/bus/vexpress-config.c
+++ b/drivers/bus/vexpress-config.c
@@ -178,6 +178,7 @@ static int vexpress_config_populate(struct device_node *node)
parent = class_find_device(vexpress_config_class, NULL, bridge,
vexpress_config_node_match);
+ of_node_put(bridge);
if (WARN_ON(!parent))
return -ENODEV;