msm: pil-q6v5: Move bus port halting into pil-q6v5 library
Other drivers that use the pil-q6v5 library will also need bus port
halting functions. Generalize the LPASS-specific code for doing this
and move it into pil-q6v5.c.
Signed-off-by: Matt Wagantall <mattw@codeaurora.org>
Change-Id: I4d6e5798dfc7692d17abcec05ac3bc818e3634ec
diff --git a/arch/arm/mach-msm/pil-q6v5.c b/arch/arm/mach-msm/pil-q6v5.c
index 3b9d542..6a96990 100644
--- a/arch/arm/mach-msm/pil-q6v5.c
+++ b/arch/arm/mach-msm/pil-q6v5.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
#include <linux/elf.h>
#include <linux/err.h>
#include <linux/of.h>
@@ -25,11 +26,18 @@
#include "peripheral-loader.h"
#include "pil-q6v5.h"
-/* Register Offsets */
+/* QDSP6SS Register Offsets */
#define QDSP6SS_RESET 0x014
#define QDSP6SS_GFMUX_CTL 0x020
#define QDSP6SS_PWR_CTL 0x030
+/* AXI Halt Register Offsets */
+#define AXI_HALTREQ 0x0
+#define AXI_HALTACK 0x4
+#define AXI_IDLE 0x8
+
+#define HALT_ACK_TIMEOUT_US 100000
+
/* QDSP6SS_RESET */
#define Q6SS_CORE_ARES BIT(1)
#define Q6SS_ETM_ISDB_ARES BIT(3)
@@ -68,6 +76,27 @@
}
EXPORT_SYMBOL(pil_q6v5_remove_proxy_votes);
+void pil_q6v5_halt_axi_port(struct pil_desc *pil, void __iomem *halt_base)
+{
+ int ret;
+ u32 status;
+
+ /* Assert halt request */
+ writel_relaxed(1, halt_base + AXI_HALTREQ);
+
+ /* Wait for halt */
+ ret = readl_poll_timeout(halt_base + AXI_HALTACK,
+ status, status != 0, 50, HALT_ACK_TIMEOUT_US);
+ if (ret)
+ dev_warn(pil->dev, "Port %p halt timeout\n", halt_base);
+ else if (!readl_relaxed(halt_base + AXI_IDLE))
+ dev_warn(pil->dev, "Port %p halt failed\n", halt_base);
+
+ /* Clear halt request (port will remain halted until reset) */
+ writel_relaxed(0, halt_base + AXI_HALTREQ);
+}
+EXPORT_SYMBOL(pil_q6v5_halt_axi_port);
+
int pil_q6v5_init_image(struct pil_desc *pil, const u8 *metadata,
size_t size)
{
@@ -210,6 +239,11 @@
resource_size(res));
if (!drv->reg_base)
return ERR_PTR(-ENOMEM);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ drv->axi_halt_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!drv->axi_halt_base)
+ return ERR_PTR(-ENOMEM);
desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
if (!desc)