blob: 6171c92f80e73ab87388161327eee5610a1a4f62 [file] [log] [blame]
Brian Swetland03e00cd2009-07-01 17:58:37 -07001/* arch/arm/mach-msm/smd_debug.c
2 *
3 * Copyright (C) 2007 Google, Inc.
Eric Holmbergc7e8daf2011-12-28 11:49:21 -07004 * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
Brian Swetland03e00cd2009-07-01 17:58:37 -07005 * Author: Brian Swetland <swetland@google.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/debugfs.h>
19#include <linux/list.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070020#include <linux/ctype.h>
Eric Holmbergc7e8daf2011-12-28 11:49:21 -070021#include <linux/jiffies.h>
Brian Swetland03e00cd2009-07-01 17:58:37 -070022
23#include <mach/msm_iomap.h>
24
25#include "smd_private.h"
26
27#if defined(CONFIG_DEBUG_FS)
28
29static char *chstate(unsigned n)
30{
31 switch (n) {
32 case SMD_SS_CLOSED:
33 return "CLOSED";
34 case SMD_SS_OPENING:
35 return "OPENING";
36 case SMD_SS_OPENED:
37 return "OPENED";
38 case SMD_SS_FLUSHING:
39 return "FLUSHING";
40 case SMD_SS_CLOSING:
41 return "CLOSING";
42 case SMD_SS_RESET:
43 return "RESET";
44 case SMD_SS_RESET_OPENING:
45 return "ROPENING";
46 default:
47 return "UNKNOWN";
48 }
49}
50
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070051static int debug_f3(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -070052{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070053 char *x;
54 int size;
55 int i = 0, j = 0;
56 unsigned cols = 0;
57 char str[4*sizeof(unsigned)+1] = {0};
Brian Swetland03e00cd2009-07-01 17:58:37 -070058
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070059 i += scnprintf(buf + i, max - i,
60 "Printing to log\n");
61
62 x = smem_get_entry(SMEM_ERR_F3_TRACE_LOG, &size);
63 if (x != 0) {
64 pr_info("smem: F3 TRACE LOG\n");
65 while (size > 0) {
66 if (size >= sizeof(unsigned)) {
67 pr_info("%08x", *((unsigned *) x));
68 for (j = 0; j < sizeof(unsigned); ++j)
69 if (isprint(*(x+j)))
70 str[cols*sizeof(unsigned) + j]
71 = *(x+j);
72 else
73 str[cols*sizeof(unsigned) + j]
74 = '-';
75 x += sizeof(unsigned);
76 size -= sizeof(unsigned);
77 } else {
78 while (size-- > 0)
79 pr_info("%02x", (unsigned) *x++);
80 break;
81 }
82 if (cols == 3) {
83 cols = 0;
84 str[4*sizeof(unsigned)] = 0;
85 pr_info(" %s\n", str);
86 str[0] = 0;
87 } else {
88 cols++;
89 pr_info(" ");
90 }
91 }
92 pr_info("\n");
93 }
94
95 return max;
96}
97
98static int debug_diag(char *buf, int max)
99{
100 int i = 0;
101
102 i += scnprintf(buf + i, max - i,
103 "Printing to log\n");
104 smd_diag();
105
106 return i;
107}
108
109static int debug_modem_err_f3(char *buf, int max)
110{
111 char *x;
112 int size;
113 int i = 0, j = 0;
114 unsigned cols = 0;
115 char str[4*sizeof(unsigned)+1] = {0};
116
117 x = smem_get_entry(SMEM_ERR_F3_TRACE_LOG, &size);
118 if (x != 0) {
119 pr_info("smem: F3 TRACE LOG\n");
120 while (size > 0 && max - i) {
121 if (size >= sizeof(unsigned)) {
122 i += scnprintf(buf + i, max - i, "%08x",
123 *((unsigned *) x));
124 for (j = 0; j < sizeof(unsigned); ++j)
125 if (isprint(*(x+j)))
126 str[cols*sizeof(unsigned) + j]
127 = *(x+j);
128 else
129 str[cols*sizeof(unsigned) + j]
130 = '-';
131 x += sizeof(unsigned);
132 size -= sizeof(unsigned);
133 } else {
134 while (size-- > 0 && max - i)
135 i += scnprintf(buf + i, max - i,
136 "%02x",
137 (unsigned) *x++);
138 break;
139 }
140 if (cols == 3) {
141 cols = 0;
142 str[4*sizeof(unsigned)] = 0;
143 i += scnprintf(buf + i, max - i, " %s\n",
144 str);
145 str[0] = 0;
146 } else {
147 cols++;
148 i += scnprintf(buf + i, max - i, " ");
149 }
150 }
151 i += scnprintf(buf + i, max - i, "\n");
152 }
153
154 return i;
155}
156
157static int debug_modem_err(char *buf, int max)
158{
159 char *x;
160 int size;
161 int i = 0;
162
163 x = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG);
164 if (x != 0) {
165 x[SZ_DIAG_ERR_MSG - 1] = 0;
166 i += scnprintf(buf + i, max - i,
167 "smem: DIAG '%s'\n", x);
168 }
169
170 x = smem_get_entry(SMEM_ERR_CRASH_LOG, &size);
171 if (x != 0) {
172 x[size - 1] = 0;
173 i += scnprintf(buf + i, max - i,
174 "smem: CRASH LOG\n'%s'\n", x);
175 }
176 i += scnprintf(buf + i, max - i, "\n");
177
178 return i;
179}
180
181static int debug_read_diag_msg(char *buf, int max)
182{
183 char *msg;
184 int i = 0;
185
186 msg = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG);
187
188 if (msg) {
189 msg[SZ_DIAG_ERR_MSG - 1] = 0;
190 i += scnprintf(buf + i, max - i, "diag: '%s'\n", msg);
191 }
192 return i;
193}
194
195static int dump_ch(char *buf, int max, int n,
196 struct smd_half_channel *s,
197 struct smd_half_channel *r,
198 unsigned size)
199{
Brian Swetland03e00cd2009-07-01 17:58:37 -0700200 return scnprintf(
201 buf, max,
202 "ch%02d:"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700203 " %8s(%04d/%04d) %c%c%c%c%c%c%c%c <->"
204 " %8s(%04d/%04d) %c%c%c%c%c%c%c%c : %5x\n", n,
Brian Swetland03e00cd2009-07-01 17:58:37 -0700205 chstate(s->state), s->tail, s->head,
206 s->fDSR ? 'D' : 'd',
207 s->fCTS ? 'C' : 'c',
208 s->fCD ? 'C' : 'c',
209 s->fRI ? 'I' : 'i',
210 s->fHEAD ? 'W' : 'w',
211 s->fTAIL ? 'R' : 'r',
212 s->fSTATE ? 'S' : 's',
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700213 s->fBLOCKREADINTR ? 'B' : 'b',
Brian Swetland03e00cd2009-07-01 17:58:37 -0700214 chstate(r->state), r->tail, r->head,
215 r->fDSR ? 'D' : 'd',
216 r->fCTS ? 'R' : 'r',
217 r->fCD ? 'C' : 'c',
218 r->fRI ? 'I' : 'i',
219 r->fHEAD ? 'W' : 'w',
220 r->fTAIL ? 'R' : 'r',
Brian Swetland37521a32009-07-01 18:30:47 -0700221 r->fSTATE ? 'S' : 's',
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700222 r->fBLOCKREADINTR ? 'B' : 'b',
223 size
Brian Swetland03e00cd2009-07-01 17:58:37 -0700224 );
225}
226
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700227static int debug_read_smsm_state(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700228{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700229 uint32_t *smsm;
230 int n, i = 0;
231
232 smsm = smem_find(ID_SHARED_STATE,
233 SMSM_NUM_ENTRIES * sizeof(uint32_t));
234
235 if (smsm)
236 for (n = 0; n < SMSM_NUM_ENTRIES; n++)
237 i += scnprintf(buf + i, max - i, "entry %d: 0x%08x\n",
238 n, smsm[n]);
239
240 return i;
241}
242
243struct SMSM_CB_DATA {
244 int cb_count;
245 void *data;
246 uint32_t old_state;
247 uint32_t new_state;
248};
249static struct SMSM_CB_DATA smsm_cb_data;
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700250static struct completion smsm_cb_completion;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700251
252static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
253{
254 smsm_cb_data.cb_count++;
255 smsm_cb_data.old_state = old_state;
256 smsm_cb_data.new_state = new_state;
257 smsm_cb_data.data = data;
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700258 complete_all(&smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700259}
260
261#define UT_EQ_INT(a, b) \
262 if ((a) != (b)) { \
263 i += scnprintf(buf + i, max - i, \
264 "%s:%d " #a "(%d) != " #b "(%d)\n", \
265 __func__, __LINE__, \
266 a, b); \
267 break; \
268 } \
269 do {} while (0)
270
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700271#define UT_GT_INT(a, b) \
272 if ((a) <= (b)) { \
273 i += scnprintf(buf + i, max - i, \
274 "%s:%d " #a "(%d) > " #b "(%d)\n", \
275 __func__, __LINE__, \
276 a, b); \
277 break; \
278 } \
279 do {} while (0)
280
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700281#define SMSM_CB_TEST_INIT() \
282 do { \
283 smsm_cb_data.cb_count = 0; \
284 smsm_cb_data.old_state = 0; \
285 smsm_cb_data.new_state = 0; \
286 smsm_cb_data.data = 0; \
287 } while (0)
288
289
290static int debug_test_smsm(char *buf, int max)
291{
Brian Swetland03e00cd2009-07-01 17:58:37 -0700292 int i = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700293 int test_num = 0;
294 int ret;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700295
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700296 /* Test case 1 - Register new callback for notification */
297 do {
298 test_num++;
299 SMSM_CB_TEST_INIT();
300 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_SMDINIT,
301 smsm_state_cb, (void *)0x1234);
302 UT_EQ_INT(ret, 0);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700303
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700304 /* de-assert SMSM_SMD_INIT to trigger state update */
305 UT_EQ_INT(smsm_cb_data.cb_count, 0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700306 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700307 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700308 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
309 msecs_to_jiffies(20)), 0);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700310
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700311 UT_EQ_INT(smsm_cb_data.cb_count, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700312 UT_EQ_INT(smsm_cb_data.old_state & SMSM_SMDINIT, SMSM_SMDINIT);
313 UT_EQ_INT(smsm_cb_data.new_state & SMSM_SMDINIT, 0x0);
314 UT_EQ_INT((int)smsm_cb_data.data, 0x1234);
315
316 /* re-assert SMSM_SMD_INIT to trigger state update */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700317 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700318 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700319 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
320 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700321 UT_EQ_INT(smsm_cb_data.cb_count, 2);
322 UT_EQ_INT(smsm_cb_data.old_state & SMSM_SMDINIT, 0x0);
323 UT_EQ_INT(smsm_cb_data.new_state & SMSM_SMDINIT, SMSM_SMDINIT);
324
325 /* deregister callback */
326 ret = smsm_state_cb_deregister(SMSM_APPS_STATE, SMSM_SMDINIT,
327 smsm_state_cb, (void *)0x1234);
328 UT_EQ_INT(ret, 2);
329
330 /* make sure state change doesn't cause any more callbacks */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700331 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700332 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
333 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700334 UT_EQ_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
335 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700336 UT_EQ_INT(smsm_cb_data.cb_count, 2);
337
338 i += scnprintf(buf + i, max - i, "Test %d - PASS\n", test_num);
339 } while (0);
340
341 /* Test case 2 - Update already registered callback */
342 do {
343 test_num++;
344 SMSM_CB_TEST_INIT();
345 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_SMDINIT,
346 smsm_state_cb, (void *)0x1234);
347 UT_EQ_INT(ret, 0);
348 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_INIT,
349 smsm_state_cb, (void *)0x1234);
350 UT_EQ_INT(ret, 1);
351
352 /* verify both callback bits work */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700353 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700354 UT_EQ_INT(smsm_cb_data.cb_count, 0);
355 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700356 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
357 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700358 UT_EQ_INT(smsm_cb_data.cb_count, 1);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700359 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700360 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700361 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
362 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700363 UT_EQ_INT(smsm_cb_data.cb_count, 2);
364
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700365 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700366 smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700367 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
368 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700369 UT_EQ_INT(smsm_cb_data.cb_count, 3);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700370 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700371 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700372 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
373 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700374 UT_EQ_INT(smsm_cb_data.cb_count, 4);
375
376 /* deregister 1st callback */
377 ret = smsm_state_cb_deregister(SMSM_APPS_STATE, SMSM_SMDINIT,
378 smsm_state_cb, (void *)0x1234);
379 UT_EQ_INT(ret, 1);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700380 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700381 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
382 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700383 UT_EQ_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
384 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700385 UT_EQ_INT(smsm_cb_data.cb_count, 4);
386
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700387 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700388 smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700389 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
390 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700391 UT_EQ_INT(smsm_cb_data.cb_count, 5);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700392 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700393 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700394 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
395 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700396 UT_EQ_INT(smsm_cb_data.cb_count, 6);
397
398 /* deregister 2nd callback */
399 ret = smsm_state_cb_deregister(SMSM_APPS_STATE, SMSM_INIT,
400 smsm_state_cb, (void *)0x1234);
401 UT_EQ_INT(ret, 2);
402
403 /* make sure state change doesn't cause any more callbacks */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700404 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700405 smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
406 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700407 UT_EQ_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
408 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700409 UT_EQ_INT(smsm_cb_data.cb_count, 6);
410
411 i += scnprintf(buf + i, max - i, "Test %d - PASS\n", test_num);
412 } while (0);
413
414 /* Test case 3 - Two callback registrations with different data */
415 do {
416 test_num++;
417 SMSM_CB_TEST_INIT();
418 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_SMDINIT,
419 smsm_state_cb, (void *)0x1234);
420 UT_EQ_INT(ret, 0);
421 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_INIT,
422 smsm_state_cb, (void *)0x3456);
423 UT_EQ_INT(ret, 0);
424
425 /* verify both callbacks work */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700426 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700427 UT_EQ_INT(smsm_cb_data.cb_count, 0);
428 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700429 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
430 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700431 UT_EQ_INT(smsm_cb_data.cb_count, 1);
432 UT_EQ_INT((int)smsm_cb_data.data, 0x1234);
433
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700434 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700435 smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700436 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
437 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700438 UT_EQ_INT(smsm_cb_data.cb_count, 2);
439 UT_EQ_INT((int)smsm_cb_data.data, 0x3456);
440
441 /* cleanup and unregister
442 * degregister in reverse to verify data field is
443 * being used
444 */
445 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
446 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
447 ret = smsm_state_cb_deregister(SMSM_APPS_STATE,
448 SMSM_INIT,
449 smsm_state_cb, (void *)0x3456);
450 UT_EQ_INT(ret, 2);
451 ret = smsm_state_cb_deregister(SMSM_APPS_STATE,
452 SMSM_SMDINIT,
453 smsm_state_cb, (void *)0x1234);
454 UT_EQ_INT(ret, 2);
455
456 i += scnprintf(buf + i, max - i, "Test %d - PASS\n", test_num);
457 } while (0);
458
Brian Swetland03e00cd2009-07-01 17:58:37 -0700459 return i;
460}
461
462static int debug_read_mem(char *buf, int max)
463{
464 unsigned n;
465 struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
466 struct smem_heap_entry *toc = shared->heap_toc;
467 int i = 0;
468
469 i += scnprintf(buf + i, max - i,
470 "heap: init=%d free=%d remain=%d\n",
471 shared->heap_info.initialized,
472 shared->heap_info.free_offset,
473 shared->heap_info.heap_remaining);
474
475 for (n = 0; n < SMEM_NUM_ITEMS; n++) {
476 if (toc[n].allocated == 0)
477 continue;
478 i += scnprintf(buf + i, max - i,
479 "%04d: offset %08x size %08x\n",
480 n, toc[n].offset, toc[n].size);
481 }
482 return i;
483}
484
Eric Holmberg27134822011-12-15 16:07:50 -0700485#if (!defined(CONFIG_MSM_SMD_PKG4) && !defined(CONFIG_MSM_SMD_PKG3))
486static int debug_read_ch(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700487{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700488 void *shared;
489 int n, i = 0;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700490
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700491 for (n = 0; n < SMD_CHANNELS; n++) {
492 shared = smem_find(ID_SMD_CHANNELS + n,
493 2 * (sizeof(struct smd_half_channel) +
494 SMD_BUF_SIZE));
495
496 if (shared == 0)
497 continue;
498 i += dump_ch(buf + i, max - i, n, shared,
499 (shared + sizeof(struct smd_half_channel) +
500 SMD_BUF_SIZE), SMD_BUF_SIZE);
501 }
Brian Swetland03e00cd2009-07-01 17:58:37 -0700502
503 return i;
504}
Eric Holmberg27134822011-12-15 16:07:50 -0700505#else
506static int debug_read_ch(char *buf, int max)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700507{
508 void *shared, *buffer;
509 unsigned buffer_sz;
510 int n, i = 0;
511
512 for (n = 0; n < SMD_CHANNELS; n++) {
513 shared = smem_find(ID_SMD_CHANNELS + n,
514 2 * sizeof(struct smd_half_channel));
515
516 if (shared == 0)
517 continue;
518
519 buffer = smem_get_entry(SMEM_SMD_FIFO_BASE_ID + n, &buffer_sz);
520
521 if (buffer == 0)
522 continue;
523
524 i += dump_ch(buf + i, max - i, n, shared,
525 (shared + sizeof(struct smd_half_channel)),
526 buffer_sz / 2);
527 }
528
529 return i;
530}
Eric Holmberg27134822011-12-15 16:07:50 -0700531#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700532
533static int debug_read_smem_version(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700534{
535 struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700536 uint32_t n, version, i = 0;
537
538 for (n = 0; n < 32; n++) {
539 version = shared->version[n];
540 i += scnprintf(buf + i, max - i,
541 "entry %d: smem = %d proc_comm = %d\n", n,
542 version >> 16,
543 version & 0xffff);
544 }
545
546 return i;
547}
548
549/* NNV: revist, it may not be smd version */
550static int debug_read_smd_version(char *buf, int max)
551{
552 uint32_t *smd_ver;
553 uint32_t n, version, i = 0;
554
555 smd_ver = smem_alloc(SMEM_VERSION_SMD, 32 * sizeof(uint32_t));
556
557 if (smd_ver)
558 for (n = 0; n < 32; n++) {
559 version = smd_ver[n];
560 i += scnprintf(buf + i, max - i,
561 "entry %d: %d.%d\n", n,
562 version >> 16,
563 version & 0xffff);
564 }
565
566 return i;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700567}
568
569static int debug_read_build_id(char *buf, int max)
570{
571 unsigned size;
572 void *data;
573
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700574 data = smem_get_entry(SMEM_HW_SW_BUILD_ID, &size);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700575 if (!data)
576 return 0;
577
578 if (size >= max)
579 size = max;
580 memcpy(buf, data, size);
581
582 return size;
583}
584
585static int debug_read_alloc_tbl(char *buf, int max)
586{
587 struct smd_alloc_elm *shared;
588 int n, i = 0;
589
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700590 shared = smem_find(ID_CH_ALLOC_TBL, sizeof(struct smd_alloc_elm[64]));
591
592 if (!shared)
593 return 0;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700594
595 for (n = 0; n < 64; n++) {
Brian Swetland03e00cd2009-07-01 17:58:37 -0700596 i += scnprintf(buf + i, max - i,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700597 "name=%s cid=%d ch type=%d "
598 "xfer type=%d ref_count=%d\n",
599 shared[n].name,
600 shared[n].cid,
601 SMD_CHANNEL_TYPE(shared[n].type),
602 SMD_XFER_TYPE(shared[n].type),
603 shared[n].ref_count);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700604 }
605
606 return i;
607}
608
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700609static int debug_read_intr_mask(char *buf, int max)
610{
611 uint32_t *smsm;
612 int m, n, i = 0;
613
614 smsm = smem_alloc(SMEM_SMSM_CPU_INTR_MASK,
615 SMSM_NUM_ENTRIES * SMSM_NUM_HOSTS * sizeof(uint32_t));
616
617 if (smsm)
618 for (m = 0; m < SMSM_NUM_ENTRIES; m++) {
619 i += scnprintf(buf + i, max - i, "entry %d:", m);
620 for (n = 0; n < SMSM_NUM_HOSTS; n++)
621 i += scnprintf(buf + i, max - i,
622 " host %d: 0x%08x",
623 n, smsm[m * SMSM_NUM_HOSTS + n]);
624 i += scnprintf(buf + i, max - i, "\n");
625 }
626
627 return i;
628}
629
630static int debug_read_intr_mux(char *buf, int max)
631{
632 uint32_t *smsm;
633 int n, i = 0;
634
635 smsm = smem_alloc(SMEM_SMD_SMSM_INTR_MUX,
636 SMSM_NUM_INTR_MUX * sizeof(uint32_t));
637
638 if (smsm)
639 for (n = 0; n < SMSM_NUM_INTR_MUX; n++)
640 i += scnprintf(buf + i, max - i, "entry %d: %d\n",
641 n, smsm[n]);
642
643 return i;
644}
645
Brian Swetland03e00cd2009-07-01 17:58:37 -0700646#define DEBUG_BUFMAX 4096
647static char debug_buffer[DEBUG_BUFMAX];
648
649static ssize_t debug_read(struct file *file, char __user *buf,
650 size_t count, loff_t *ppos)
651{
652 int (*fill)(char *buf, int max) = file->private_data;
653 int bsize = fill(debug_buffer, DEBUG_BUFMAX);
654 return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize);
655}
656
657static int debug_open(struct inode *inode, struct file *file)
658{
659 file->private_data = inode->i_private;
660 return 0;
661}
662
663static const struct file_operations debug_ops = {
664 .read = debug_read,
665 .open = debug_open,
666};
667
668static void debug_create(const char *name, mode_t mode,
669 struct dentry *dent,
670 int (*fill)(char *buf, int max))
671{
672 debugfs_create_file(name, mode, dent, fill, &debug_ops);
673}
674
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700675static int __init smd_debugfs_init(void)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700676{
677 struct dentry *dent;
678
679 dent = debugfs_create_dir("smd", 0);
680 if (IS_ERR(dent))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700681 return PTR_ERR(dent);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700682
683 debug_create("ch", 0444, dent, debug_read_ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700684 debug_create("diag", 0444, dent, debug_read_diag_msg);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700685 debug_create("mem", 0444, dent, debug_read_mem);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700686 debug_create("version", 0444, dent, debug_read_smd_version);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700687 debug_create("tbl", 0444, dent, debug_read_alloc_tbl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700688 debug_create("modem_err", 0444, dent, debug_modem_err);
689 debug_create("modem_err_f3", 0444, dent, debug_modem_err_f3);
690 debug_create("print_diag", 0444, dent, debug_diag);
691 debug_create("print_f3", 0444, dent, debug_f3);
692
693 /* NNV: this is google only stuff */
Brian Swetland03e00cd2009-07-01 17:58:37 -0700694 debug_create("build", 0444, dent, debug_read_build_id);
Daniel Walker869a2a02010-04-23 11:04:14 -0700695
696 return 0;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700697}
698
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700699static int __init smsm_debugfs_init(void)
700{
701 struct dentry *dent;
702
703 dent = debugfs_create_dir("smsm", 0);
704 if (IS_ERR(dent))
705 return PTR_ERR(dent);
706
707 debug_create("state", 0444, dent, debug_read_smsm_state);
708 debug_create("intr_mask", 0444, dent, debug_read_intr_mask);
709 debug_create("intr_mux", 0444, dent, debug_read_intr_mux);
710 debug_create("version", 0444, dent, debug_read_smem_version);
711 debug_create("smsm_test", 0444, dent, debug_test_smsm);
712
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700713 init_completion(&smsm_cb_completion);
714
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700715 return 0;
716}
717
Brian Swetland03e00cd2009-07-01 17:58:37 -0700718late_initcall(smd_debugfs_init);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700719late_initcall(smsm_debugfs_init);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700720#endif
721
722
723#define MAX_NUM_SLEEP_CLIENTS 64
724#define MAX_SLEEP_NAME_LEN 8
725
726#define NUM_GPIO_INT_REGISTERS 6
727#define GPIO_SMEM_NUM_GROUPS 2
728#define GPIO_SMEM_MAX_PC_INTERRUPTS 8
729
730struct tramp_gpio_save {
731 unsigned int enable;
732 unsigned int detect;
733 unsigned int polarity;
734};
735
736struct tramp_gpio_smem {
737 uint16_t num_fired[GPIO_SMEM_NUM_GROUPS];
738 uint16_t fired[GPIO_SMEM_NUM_GROUPS][GPIO_SMEM_MAX_PC_INTERRUPTS];
739 uint32_t enabled[NUM_GPIO_INT_REGISTERS];
740 uint32_t detection[NUM_GPIO_INT_REGISTERS];
741 uint32_t polarity[NUM_GPIO_INT_REGISTERS];
742};
743
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700744/*
745 * Print debug information on shared memory sleep variables
746 */
747void smsm_print_sleep_info(uint32_t sleep_delay, uint32_t sleep_limit,
748 uint32_t irq_mask, uint32_t wakeup_reason, uint32_t pending_irqs)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700749{
750 unsigned long flags;
751 uint32_t *ptr;
752 struct tramp_gpio_smem *gpio;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700753
754 spin_lock_irqsave(&smem_lock, flags);
755
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700756 pr_info("SMEM_SMSM_SLEEP_DELAY: %x\n", sleep_delay);
757 pr_info("SMEM_SMSM_LIMIT_SLEEP: %x\n", sleep_limit);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700758
759 ptr = smem_alloc(SMEM_SLEEP_POWER_COLLAPSE_DISABLED, sizeof(*ptr));
760 if (ptr)
761 pr_info("SMEM_SLEEP_POWER_COLLAPSE_DISABLED: %x\n", *ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700762 else
763 pr_info("SMEM_SLEEP_POWER_COLLAPSE_DISABLED: missing\n");
Brian Swetland03e00cd2009-07-01 17:58:37 -0700764
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700765 pr_info("SMEM_SMSM_INT_INFO %x %x %x\n",
766 irq_mask, pending_irqs, wakeup_reason);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700767
768 gpio = smem_alloc(SMEM_GPIO_INT, sizeof(*gpio));
769 if (gpio) {
770 int i;
771 for (i = 0; i < NUM_GPIO_INT_REGISTERS; i++)
772 pr_info("SMEM_GPIO_INT: %d: e %x d %x p %x\n",
773 i, gpio->enabled[i], gpio->detection[i],
774 gpio->polarity[i]);
775
776 for (i = 0; i < GPIO_SMEM_NUM_GROUPS; i++)
777 pr_info("SMEM_GPIO_INT: %d: f %d: %d %d...\n",
778 i, gpio->num_fired[i], gpio->fired[i][0],
779 gpio->fired[i][1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700780 } else
781 pr_info("SMEM_GPIO_INT: missing\n");
782
Brian Swetland03e00cd2009-07-01 17:58:37 -0700783 spin_unlock_irqrestore(&smem_lock, flags);
784}