aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-msm/proc_comm.c
diff options
context:
space:
mode:
authorBrian Swetland <swetland@google.com>2008-09-09 12:36:50 -0400
committerBrian Swetland <swetland@google.com>2008-10-22 05:39:32 -0400
commitb8a16e1fdfe9caed734df0e157ad74ae2b13e3bd (patch)
treebce53911b0eb587d067dcbda6ea47b9cc0b0536f /arch/arm/mach-msm/proc_comm.c
parent1637de0c9b4dbac0f185e94b2b8cd2c2db78700d (diff)
[ARM] msm: add proc_comm support, necessary for clock and power control
The proc_comm protocol is the lowest level protocol available for communicating with the modem core. It provides access to clock and power control, among other things, and is safe for use from atomic contexts, unlike the higher level SMD and RPC transports. Signed-off-by: Brian Swetland <swetland@google.com>
Diffstat (limited to 'arch/arm/mach-msm/proc_comm.c')
-rw-r--r--arch/arm/mach-msm/proc_comm.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/arch/arm/mach-msm/proc_comm.c b/arch/arm/mach-msm/proc_comm.c
new file mode 100644
index 000000000000..915ee704ed3c
--- /dev/null
+++ b/arch/arm/mach-msm/proc_comm.c
@@ -0,0 +1,110 @@
1/* arch/arm/mach-msm/proc_comm.c
2 *
3 * Copyright (C) 2007-2008 Google, Inc.
4 * Author: Brian Swetland <swetland@google.com>
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/delay.h>
18#include <linux/errno.h>
19#include <linux/io.h>
20#include <linux/spinlock.h>
21#include <mach/msm_iomap.h>
22#include <mach/system.h>
23
24#include "proc_comm.h"
25
26#define MSM_A2M_INT(n) (MSM_CSR_BASE + 0x400 + (n) * 4)
27
28static inline void notify_other_proc_comm(void)
29{
30 writel(1, MSM_A2M_INT(6));
31}
32
33#define APP_COMMAND 0x00
34#define APP_STATUS 0x04
35#define APP_DATA1 0x08
36#define APP_DATA2 0x0C
37
38#define MDM_COMMAND 0x10
39#define MDM_STATUS 0x14
40#define MDM_DATA1 0x18
41#define MDM_DATA2 0x1C
42
43static DEFINE_SPINLOCK(proc_comm_lock);
44
45/* The higher level SMD support will install this to
46 * provide a way to check for and handle modem restart.
47 */
48int (*msm_check_for_modem_crash)(void);
49
50/* Poll for a state change, checking for possible
51 * modem crashes along the way (so we don't wait
52 * forever while the ARM9 is blowing up).
53 *
54 * Return an error in the event of a modem crash and
55 * restart so the msm_proc_comm() routine can restart
56 * the operation from the beginning.
57 */
58static int proc_comm_wait_for(void __iomem *addr, unsigned value)
59{
60 for (;;) {
61 if (readl(addr) == value)
62 return 0;
63
64 if (msm_check_for_modem_crash)
65 if (msm_check_for_modem_crash())
66 return -EAGAIN;
67 }
68}
69
70int msm_proc_comm(unsigned cmd, unsigned *data1, unsigned *data2)
71{
72 void __iomem *base = MSM_SHARED_RAM_BASE;
73 unsigned long flags;
74 int ret;
75
76 spin_lock_irqsave(&proc_comm_lock, flags);
77
78 for (;;) {
79 if (proc_comm_wait_for(base + MDM_STATUS, PCOM_READY))
80 continue;
81
82 writel(cmd, base + APP_COMMAND);
83 writel(data1 ? *data1 : 0, base + APP_DATA1);
84 writel(data2 ? *data2 : 0, base + APP_DATA2);
85
86 notify_other_proc_comm();
87
88 if (proc_comm_wait_for(base + APP_COMMAND, PCOM_CMD_DONE))
89 continue;
90
91 if (readl(base + APP_STATUS) != PCOM_CMD_FAIL) {
92 if (data1)
93 *data1 = readl(base + APP_DATA1);
94 if (data2)
95 *data2 = readl(base + APP_DATA2);
96 ret = 0;
97 } else {
98 ret = -EIO;
99 }
100 break;
101 }
102
103 writel(PCOM_CMD_IDLE, base + APP_COMMAND);
104
105 spin_unlock_irqrestore(&proc_comm_lock, flags);
106
107 return ret;
108}
109
110