summaryrefslogtreecommitdiff
path: root/arch/arm/mach-msm/proc_comm.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-msm/proc_comm.c')
-rw-r--r--arch/arm/mach-msm/proc_comm.c93
1 files changed, 60 insertions, 33 deletions
diff --git a/arch/arm/mach-msm/proc_comm.c b/arch/arm/mach-msm/proc_comm.c
index 915ee704ed3c..937e59b46dfe 100644
--- a/arch/arm/mach-msm/proc_comm.c
+++ b/arch/arm/mach-msm/proc_comm.c
@@ -1,6 +1,7 @@
/* arch/arm/mach-msm/proc_comm.c
*
* Copyright (C) 2007-2008 Google, Inc.
+ * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
* Author: Brian Swetland <swetland@google.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -18,16 +19,21 @@
#include <linux/errno.h>
#include <linux/io.h>
#include <linux/spinlock.h>
+#include <linux/module.h>
#include <mach/msm_iomap.h>
#include <mach/system.h>
#include "proc_comm.h"
-#define MSM_A2M_INT(n) (MSM_CSR_BASE + 0x400 + (n) * 4)
+#if defined(CONFIG_ARCH_MSM7X30)
+#define MSM_TRIG_A2M_INT(n) (writel(1 << n, MSM_GCC_BASE + 0x8))
+#else
+#define MSM_TRIG_A2M_INT(n) (writel(1, MSM_CSR_BASE + 0x400 + (n) * 4))
+#endif
static inline void notify_other_proc_comm(void)
{
- writel(1, MSM_A2M_INT(6));
+ MSM_TRIG_A2M_INT(6);
}
#define APP_COMMAND 0x00
@@ -43,68 +49,89 @@ static inline void notify_other_proc_comm(void)
static DEFINE_SPINLOCK(proc_comm_lock);
/* The higher level SMD support will install this to
- * provide a way to check for and handle modem restart.
+ * provide a way to check for and handle modem restart?
*/
int (*msm_check_for_modem_crash)(void);
/* Poll for a state change, checking for possible
* modem crashes along the way (so we don't wait
- * forever while the ARM9 is blowing up).
+ * forever while the ARM9 is blowing up.
*
* Return an error in the event of a modem crash and
* restart so the msm_proc_comm() routine can restart
* the operation from the beginning.
*/
-static int proc_comm_wait_for(void __iomem *addr, unsigned value)
+static int proc_comm_wait_for(unsigned addr, unsigned value)
{
- for (;;) {
+ while (1) {
if (readl(addr) == value)
return 0;
if (msm_check_for_modem_crash)
if (msm_check_for_modem_crash())
return -EAGAIN;
+
+ udelay(5);
}
}
+void msm_proc_comm_reset_modem_now(void)
+{
+ unsigned base = (unsigned)MSM_SHARED_RAM_BASE;
+ unsigned long flags;
+
+ spin_lock_irqsave(&proc_comm_lock, flags);
+
+again:
+ if (proc_comm_wait_for(base + MDM_STATUS, PCOM_READY))
+ goto again;
+
+ writel(PCOM_RESET_MODEM, base + APP_COMMAND);
+ writel(0, base + APP_DATA1);
+ writel(0, base + APP_DATA2);
+
+ spin_unlock_irqrestore(&proc_comm_lock, flags);
+
+ notify_other_proc_comm();
+
+ return;
+}
+EXPORT_SYMBOL(msm_proc_comm_reset_modem_now);
+
int msm_proc_comm(unsigned cmd, unsigned *data1, unsigned *data2)
{
- void __iomem *base = MSM_SHARED_RAM_BASE;
+ unsigned base = (unsigned)MSM_SHARED_RAM_BASE;
unsigned long flags;
int ret;
spin_lock_irqsave(&proc_comm_lock, flags);
- for (;;) {
- if (proc_comm_wait_for(base + MDM_STATUS, PCOM_READY))
- continue;
-
- writel(cmd, base + APP_COMMAND);
- writel(data1 ? *data1 : 0, base + APP_DATA1);
- writel(data2 ? *data2 : 0, base + APP_DATA2);
-
- notify_other_proc_comm();
-
- if (proc_comm_wait_for(base + APP_COMMAND, PCOM_CMD_DONE))
- continue;
-
- if (readl(base + APP_STATUS) != PCOM_CMD_FAIL) {
- if (data1)
- *data1 = readl(base + APP_DATA1);
- if (data2)
- *data2 = readl(base + APP_DATA2);
- ret = 0;
- } else {
- ret = -EIO;
- }
- break;
+again:
+ if (proc_comm_wait_for(base + MDM_STATUS, PCOM_READY))
+ goto again;
+
+ writel(cmd, base + APP_COMMAND);
+ writel(data1 ? *data1 : 0, base + APP_DATA1);
+ writel(data2 ? *data2 : 0, base + APP_DATA2);
+
+ notify_other_proc_comm();
+
+ if (proc_comm_wait_for(base + APP_COMMAND, PCOM_CMD_DONE))
+ goto again;
+
+ if (readl(base + APP_STATUS) == PCOM_CMD_SUCCESS) {
+ if (data1)
+ *data1 = readl(base + APP_DATA1);
+ if (data2)
+ *data2 = readl(base + APP_DATA2);
+ ret = 0;
+ } else {
+ ret = -EIO;
}
writel(PCOM_CMD_IDLE, base + APP_COMMAND);
spin_unlock_irqrestore(&proc_comm_lock, flags);
-
return ret;
}
-
-
+EXPORT_SYMBOL(msm_proc_comm);