soc: actions: owl-sps: Factor out owl_sps_set_pg() for power-gating

Allow the SMP code to reuse PM domain code for CPU2/CPU3 wakeup.

Signed-off-by: Andreas Färber <afaerber@suse.de>
diff --git a/drivers/soc/actions/Kconfig b/drivers/soc/actions/Kconfig
index bdf827d..9d68b5a 100644
--- a/drivers/soc/actions/Kconfig
+++ b/drivers/soc/actions/Kconfig
@@ -1,8 +1,12 @@
 if ARCH_ACTIONS || COMPILE_TEST
 
+config OWL_PM_DOMAINS_HELPER
+	bool
+
 config OWL_PM_DOMAINS
 	bool "Actions Semi SPS power domains"
 	depends on PM
+	select OWL_PM_DOMAINS_HELPER
 	select PM_GENERIC_DOMAINS
 	help
 	  Say 'y' here to enable support for Smart Power System (SPS)
diff --git a/drivers/soc/actions/Makefile b/drivers/soc/actions/Makefile
index 720c34e..1e101b0 100644
--- a/drivers/soc/actions/Makefile
+++ b/drivers/soc/actions/Makefile
@@ -1 +1,2 @@
+obj-$(CONFIG_OWL_PM_DOMAINS_HELPER) += owl-sps-helper.o
 obj-$(CONFIG_OWL_PM_DOMAINS) += owl-sps.o
diff --git a/drivers/soc/actions/owl-sps-helper.c b/drivers/soc/actions/owl-sps-helper.c
new file mode 100644
index 0000000..9d7a2c2
--- /dev/null
+++ b/drivers/soc/actions/owl-sps-helper.c
@@ -0,0 +1,51 @@
+/*
+ * Actions Semi Owl Smart Power System (SPS) shared helpers
+ *
+ * Copyright 2012 Actions Semi Inc.
+ * Author: Actions Semi, Inc.
+ *
+ * Copyright (c) 2017 Andreas Färber
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#define OWL_SPS_PG_CTL	0x0
+
+int owl_sps_set_pg(void __iomem *base, u32 pwr_mask, u32 ack_mask, bool enable)
+{
+	u32 val;
+	bool ack;
+	int timeout;
+
+	val = readl(base + OWL_SPS_PG_CTL);
+	ack = val & ack_mask;
+	if (ack == enable)
+		return 0;
+
+	if (enable)
+		val |= pwr_mask;
+	else
+		val &= ~pwr_mask;
+
+	writel(val, base + OWL_SPS_PG_CTL);
+
+	for (timeout = 5000; timeout > 0; timeout -= 50) {
+		val = readl(base + OWL_SPS_PG_CTL);
+		if ((val & ack_mask) == (enable ? ack_mask : 0))
+			break;
+		udelay(50);
+	}
+	if (timeout <= 0)
+		return -ETIMEDOUT;
+
+	udelay(10);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(owl_sps_set_pg);
diff --git a/drivers/soc/actions/owl-sps.c b/drivers/soc/actions/owl-sps.c
index 8abb72f..875225bfa 100644
--- a/drivers/soc/actions/owl-sps.c
+++ b/drivers/soc/actions/owl-sps.c
@@ -12,15 +12,12 @@
  * option) any later version.
  */
 
-#include <linux/delay.h>
-#include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/pm_domain.h>
+#include <linux/soc/actions/owl-sps.h>
 #include <dt-bindings/power/owl-s500-powergate.h>
 
-#define OWL_SPS_PG_CTL	0x0
-
 struct owl_sps_domain_info {
 	const char *name;
 	int pwr_bit;
@@ -51,37 +48,12 @@
 
 static int owl_sps_set_power(struct owl_sps_domain *pd, bool enable)
 {
-	u32 val, pwr_mask, ack_mask;
-	int timeout;
-	bool ack;
+	u32 pwr_mask, ack_mask;
 
 	ack_mask = BIT(pd->info->ack_bit);
 	pwr_mask = BIT(pd->info->pwr_bit);
-	val = readl(pd->sps->base + OWL_SPS_PG_CTL);
-	ack = val & ack_mask;
 
-	if (ack == enable)
-		return 0;
-
-	if (enable)
-		val |= pwr_mask;
-	else
-		val &= ~pwr_mask;
-
-	writel(val, pd->sps->base + OWL_SPS_PG_CTL);
-
-	for (timeout = 5000; timeout > 0; timeout -= 50) {
-		val = readl(pd->sps->base + OWL_SPS_PG_CTL);
-		if ((val & ack_mask) == (enable ? ack_mask : 0))
-			break;
-		udelay(50);
-	}
-	if (timeout <= 0)
-		return -ETIMEDOUT;
-
-	udelay(10);
-
-	return 0;
+	return owl_sps_set_pg(pd->sps->base, pwr_mask, ack_mask, enable);
 }
 
 static int owl_sps_power_on(struct generic_pm_domain *domain)
diff --git a/include/linux/soc/actions/owl-sps.h b/include/linux/soc/actions/owl-sps.h
new file mode 100644
index 0000000..33d0dbe
--- /dev/null
+++ b/include/linux/soc/actions/owl-sps.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2017 Andreas Färber
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#ifndef SOC_ACTIONS_OWL_SPS_H
+#define SOC_ACTIONS_OWL_SPS_H
+
+int owl_sps_set_pg(void __iomem *base, u32 pwr_mask, u32 ack_mask, bool enable);
+
+#endif