blob: 764102d60ef28cb1f513c1a35fb0986746644975 [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
Eric Holmberg7ad623a2012-03-01 14:41:10 -070098static int debug_int_stats(char *buf, int max)
99{
100 int i = 0;
101 int subsys;
102 struct interrupt_stat *stats = interrupt_stats;
103 const char *subsys_name;
104
105 i += scnprintf(buf + i, max - i,
106 " Subsystem | In | Out (Hardcoded) |"
107 " Out (Configured) |\n");
108
109 for (subsys = 0; subsys < NUM_SMD_SUBSYSTEMS; ++subsys) {
110 subsys_name = smd_pid_to_subsystem(subsys);
111 if (subsys_name) {
112 i += scnprintf(buf + i, max - i,
113 "%-10s %4s | %9u | %9u | %9u |\n",
114 smd_pid_to_subsystem(subsys), "smd",
115 stats->smd_in_count,
116 stats->smd_out_hardcode_count,
117 stats->smd_out_config_count);
118
119 i += scnprintf(buf + i, max - i,
120 "%-10s %4s | %9u | %9u | %9u |\n",
121 smd_pid_to_subsystem(subsys), "smsm",
122 stats->smsm_in_count,
123 stats->smsm_out_hardcode_count,
124 stats->smsm_out_config_count);
125 }
126 ++stats;
127 }
128
129 return i;
130}
131
132static int debug_int_stats_reset(char *buf, int max)
133{
134 int i = 0;
135 int subsys;
136 struct interrupt_stat *stats = interrupt_stats;
137
138 i += scnprintf(buf + i, max - i, "Resetting interrupt stats.\n");
139
140 for (subsys = 0; subsys < NUM_SMD_SUBSYSTEMS; ++subsys) {
141 stats->smd_in_count = 0;
142 stats->smd_out_hardcode_count = 0;
143 stats->smd_out_config_count = 0;
144 stats->smsm_in_count = 0;
145 stats->smsm_out_hardcode_count = 0;
146 stats->smsm_out_config_count = 0;
147 ++stats;
148 }
149
150 return i;
151}
152
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700153static int debug_diag(char *buf, int max)
154{
155 int i = 0;
156
157 i += scnprintf(buf + i, max - i,
158 "Printing to log\n");
159 smd_diag();
160
161 return i;
162}
163
164static int debug_modem_err_f3(char *buf, int max)
165{
166 char *x;
167 int size;
168 int i = 0, j = 0;
169 unsigned cols = 0;
170 char str[4*sizeof(unsigned)+1] = {0};
171
172 x = smem_get_entry(SMEM_ERR_F3_TRACE_LOG, &size);
173 if (x != 0) {
174 pr_info("smem: F3 TRACE LOG\n");
175 while (size > 0 && max - i) {
176 if (size >= sizeof(unsigned)) {
177 i += scnprintf(buf + i, max - i, "%08x",
178 *((unsigned *) x));
179 for (j = 0; j < sizeof(unsigned); ++j)
180 if (isprint(*(x+j)))
181 str[cols*sizeof(unsigned) + j]
182 = *(x+j);
183 else
184 str[cols*sizeof(unsigned) + j]
185 = '-';
186 x += sizeof(unsigned);
187 size -= sizeof(unsigned);
188 } else {
189 while (size-- > 0 && max - i)
190 i += scnprintf(buf + i, max - i,
191 "%02x",
192 (unsigned) *x++);
193 break;
194 }
195 if (cols == 3) {
196 cols = 0;
197 str[4*sizeof(unsigned)] = 0;
198 i += scnprintf(buf + i, max - i, " %s\n",
199 str);
200 str[0] = 0;
201 } else {
202 cols++;
203 i += scnprintf(buf + i, max - i, " ");
204 }
205 }
206 i += scnprintf(buf + i, max - i, "\n");
207 }
208
209 return i;
210}
211
212static int debug_modem_err(char *buf, int max)
213{
214 char *x;
215 int size;
216 int i = 0;
217
218 x = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG);
219 if (x != 0) {
220 x[SZ_DIAG_ERR_MSG - 1] = 0;
221 i += scnprintf(buf + i, max - i,
222 "smem: DIAG '%s'\n", x);
223 }
224
225 x = smem_get_entry(SMEM_ERR_CRASH_LOG, &size);
226 if (x != 0) {
227 x[size - 1] = 0;
228 i += scnprintf(buf + i, max - i,
229 "smem: CRASH LOG\n'%s'\n", x);
230 }
231 i += scnprintf(buf + i, max - i, "\n");
232
233 return i;
234}
235
236static int debug_read_diag_msg(char *buf, int max)
237{
238 char *msg;
239 int i = 0;
240
241 msg = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG);
242
243 if (msg) {
244 msg[SZ_DIAG_ERR_MSG - 1] = 0;
245 i += scnprintf(buf + i, max - i, "diag: '%s'\n", msg);
246 }
247 return i;
248}
249
250static int dump_ch(char *buf, int max, int n,
251 struct smd_half_channel *s,
252 struct smd_half_channel *r,
253 unsigned size)
254{
Brian Swetland03e00cd2009-07-01 17:58:37 -0700255 return scnprintf(
256 buf, max,
257 "ch%02d:"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700258 " %8s(%04d/%04d) %c%c%c%c%c%c%c%c <->"
259 " %8s(%04d/%04d) %c%c%c%c%c%c%c%c : %5x\n", n,
Brian Swetland03e00cd2009-07-01 17:58:37 -0700260 chstate(s->state), s->tail, s->head,
261 s->fDSR ? 'D' : 'd',
262 s->fCTS ? 'C' : 'c',
263 s->fCD ? 'C' : 'c',
264 s->fRI ? 'I' : 'i',
265 s->fHEAD ? 'W' : 'w',
266 s->fTAIL ? 'R' : 'r',
267 s->fSTATE ? 'S' : 's',
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700268 s->fBLOCKREADINTR ? 'B' : 'b',
Brian Swetland03e00cd2009-07-01 17:58:37 -0700269 chstate(r->state), r->tail, r->head,
270 r->fDSR ? 'D' : 'd',
271 r->fCTS ? 'R' : 'r',
272 r->fCD ? 'C' : 'c',
273 r->fRI ? 'I' : 'i',
274 r->fHEAD ? 'W' : 'w',
275 r->fTAIL ? 'R' : 'r',
Brian Swetland37521a32009-07-01 18:30:47 -0700276 r->fSTATE ? 'S' : 's',
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700277 r->fBLOCKREADINTR ? 'B' : 'b',
278 size
Brian Swetland03e00cd2009-07-01 17:58:37 -0700279 );
280}
281
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700282static int debug_read_smsm_state(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700283{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700284 uint32_t *smsm;
285 int n, i = 0;
286
287 smsm = smem_find(ID_SHARED_STATE,
288 SMSM_NUM_ENTRIES * sizeof(uint32_t));
289
290 if (smsm)
291 for (n = 0; n < SMSM_NUM_ENTRIES; n++)
292 i += scnprintf(buf + i, max - i, "entry %d: 0x%08x\n",
293 n, smsm[n]);
294
295 return i;
296}
297
298struct SMSM_CB_DATA {
299 int cb_count;
300 void *data;
301 uint32_t old_state;
302 uint32_t new_state;
303};
304static struct SMSM_CB_DATA smsm_cb_data;
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700305static struct completion smsm_cb_completion;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700306
307static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
308{
309 smsm_cb_data.cb_count++;
310 smsm_cb_data.old_state = old_state;
311 smsm_cb_data.new_state = new_state;
312 smsm_cb_data.data = data;
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700313 complete_all(&smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700314}
315
316#define UT_EQ_INT(a, b) \
317 if ((a) != (b)) { \
318 i += scnprintf(buf + i, max - i, \
319 "%s:%d " #a "(%d) != " #b "(%d)\n", \
320 __func__, __LINE__, \
321 a, b); \
322 break; \
323 } \
324 do {} while (0)
325
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700326#define UT_GT_INT(a, b) \
327 if ((a) <= (b)) { \
328 i += scnprintf(buf + i, max - i, \
329 "%s:%d " #a "(%d) > " #b "(%d)\n", \
330 __func__, __LINE__, \
331 a, b); \
332 break; \
333 } \
334 do {} while (0)
335
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700336#define SMSM_CB_TEST_INIT() \
337 do { \
338 smsm_cb_data.cb_count = 0; \
339 smsm_cb_data.old_state = 0; \
340 smsm_cb_data.new_state = 0; \
341 smsm_cb_data.data = 0; \
342 } while (0)
343
344
345static int debug_test_smsm(char *buf, int max)
346{
Brian Swetland03e00cd2009-07-01 17:58:37 -0700347 int i = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700348 int test_num = 0;
349 int ret;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700350
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700351 /* Test case 1 - Register new callback for notification */
352 do {
353 test_num++;
354 SMSM_CB_TEST_INIT();
355 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_SMDINIT,
356 smsm_state_cb, (void *)0x1234);
357 UT_EQ_INT(ret, 0);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700358
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700359 /* de-assert SMSM_SMD_INIT to trigger state update */
360 UT_EQ_INT(smsm_cb_data.cb_count, 0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700361 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700362 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700363 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
364 msecs_to_jiffies(20)), 0);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700365
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700366 UT_EQ_INT(smsm_cb_data.cb_count, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700367 UT_EQ_INT(smsm_cb_data.old_state & SMSM_SMDINIT, SMSM_SMDINIT);
368 UT_EQ_INT(smsm_cb_data.new_state & SMSM_SMDINIT, 0x0);
369 UT_EQ_INT((int)smsm_cb_data.data, 0x1234);
370
371 /* re-assert SMSM_SMD_INIT to trigger state update */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700372 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700373 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700374 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
375 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700376 UT_EQ_INT(smsm_cb_data.cb_count, 2);
377 UT_EQ_INT(smsm_cb_data.old_state & SMSM_SMDINIT, 0x0);
378 UT_EQ_INT(smsm_cb_data.new_state & SMSM_SMDINIT, SMSM_SMDINIT);
379
380 /* deregister callback */
381 ret = smsm_state_cb_deregister(SMSM_APPS_STATE, SMSM_SMDINIT,
382 smsm_state_cb, (void *)0x1234);
383 UT_EQ_INT(ret, 2);
384
385 /* make sure state change doesn't cause any more callbacks */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700386 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700387 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
388 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700389 UT_EQ_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, 2);
392
393 i += scnprintf(buf + i, max - i, "Test %d - PASS\n", test_num);
394 } while (0);
395
396 /* Test case 2 - Update already registered callback */
397 do {
398 test_num++;
399 SMSM_CB_TEST_INIT();
400 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_SMDINIT,
401 smsm_state_cb, (void *)0x1234);
402 UT_EQ_INT(ret, 0);
403 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_INIT,
404 smsm_state_cb, (void *)0x1234);
405 UT_EQ_INT(ret, 1);
406
407 /* verify both callback bits work */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700408 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700409 UT_EQ_INT(smsm_cb_data.cb_count, 0);
410 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700411 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
412 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700413 UT_EQ_INT(smsm_cb_data.cb_count, 1);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700414 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700415 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700416 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
417 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700418 UT_EQ_INT(smsm_cb_data.cb_count, 2);
419
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700420 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700421 smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700422 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
423 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700424 UT_EQ_INT(smsm_cb_data.cb_count, 3);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700425 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700426 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700427 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
428 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700429 UT_EQ_INT(smsm_cb_data.cb_count, 4);
430
431 /* deregister 1st callback */
432 ret = smsm_state_cb_deregister(SMSM_APPS_STATE, SMSM_SMDINIT,
433 smsm_state_cb, (void *)0x1234);
434 UT_EQ_INT(ret, 1);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700435 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700436 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
437 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700438 UT_EQ_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
439 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700440 UT_EQ_INT(smsm_cb_data.cb_count, 4);
441
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700442 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700443 smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700444 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
445 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700446 UT_EQ_INT(smsm_cb_data.cb_count, 5);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700447 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700448 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700449 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
450 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700451 UT_EQ_INT(smsm_cb_data.cb_count, 6);
452
453 /* deregister 2nd callback */
454 ret = smsm_state_cb_deregister(SMSM_APPS_STATE, SMSM_INIT,
455 smsm_state_cb, (void *)0x1234);
456 UT_EQ_INT(ret, 2);
457
458 /* make sure state change doesn't cause any more callbacks */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700459 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700460 smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
461 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700462 UT_EQ_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
463 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700464 UT_EQ_INT(smsm_cb_data.cb_count, 6);
465
466 i += scnprintf(buf + i, max - i, "Test %d - PASS\n", test_num);
467 } while (0);
468
469 /* Test case 3 - Two callback registrations with different data */
470 do {
471 test_num++;
472 SMSM_CB_TEST_INIT();
473 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_SMDINIT,
474 smsm_state_cb, (void *)0x1234);
475 UT_EQ_INT(ret, 0);
476 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_INIT,
477 smsm_state_cb, (void *)0x3456);
478 UT_EQ_INT(ret, 0);
479
480 /* verify both callbacks work */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700481 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700482 UT_EQ_INT(smsm_cb_data.cb_count, 0);
483 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700484 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
485 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700486 UT_EQ_INT(smsm_cb_data.cb_count, 1);
487 UT_EQ_INT((int)smsm_cb_data.data, 0x1234);
488
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700489 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700490 smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700491 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
492 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700493 UT_EQ_INT(smsm_cb_data.cb_count, 2);
494 UT_EQ_INT((int)smsm_cb_data.data, 0x3456);
495
496 /* cleanup and unregister
497 * degregister in reverse to verify data field is
498 * being used
499 */
500 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
501 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
502 ret = smsm_state_cb_deregister(SMSM_APPS_STATE,
503 SMSM_INIT,
504 smsm_state_cb, (void *)0x3456);
505 UT_EQ_INT(ret, 2);
506 ret = smsm_state_cb_deregister(SMSM_APPS_STATE,
507 SMSM_SMDINIT,
508 smsm_state_cb, (void *)0x1234);
509 UT_EQ_INT(ret, 2);
510
511 i += scnprintf(buf + i, max - i, "Test %d - PASS\n", test_num);
512 } while (0);
513
Brian Swetland03e00cd2009-07-01 17:58:37 -0700514 return i;
515}
516
517static int debug_read_mem(char *buf, int max)
518{
519 unsigned n;
520 struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
521 struct smem_heap_entry *toc = shared->heap_toc;
522 int i = 0;
523
524 i += scnprintf(buf + i, max - i,
525 "heap: init=%d free=%d remain=%d\n",
526 shared->heap_info.initialized,
527 shared->heap_info.free_offset,
528 shared->heap_info.heap_remaining);
529
530 for (n = 0; n < SMEM_NUM_ITEMS; n++) {
531 if (toc[n].allocated == 0)
532 continue;
533 i += scnprintf(buf + i, max - i,
534 "%04d: offset %08x size %08x\n",
535 n, toc[n].offset, toc[n].size);
536 }
537 return i;
538}
539
Eric Holmberg27134822011-12-15 16:07:50 -0700540#if (!defined(CONFIG_MSM_SMD_PKG4) && !defined(CONFIG_MSM_SMD_PKG3))
541static int debug_read_ch(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700542{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700543 void *shared;
544 int n, i = 0;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700545
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700546 for (n = 0; n < SMD_CHANNELS; n++) {
547 shared = smem_find(ID_SMD_CHANNELS + n,
548 2 * (sizeof(struct smd_half_channel) +
549 SMD_BUF_SIZE));
550
551 if (shared == 0)
552 continue;
553 i += dump_ch(buf + i, max - i, n, shared,
554 (shared + sizeof(struct smd_half_channel) +
555 SMD_BUF_SIZE), SMD_BUF_SIZE);
556 }
Brian Swetland03e00cd2009-07-01 17:58:37 -0700557
558 return i;
559}
Eric Holmberg27134822011-12-15 16:07:50 -0700560#else
561static int debug_read_ch(char *buf, int max)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700562{
563 void *shared, *buffer;
564 unsigned buffer_sz;
565 int n, i = 0;
566
567 for (n = 0; n < SMD_CHANNELS; n++) {
568 shared = smem_find(ID_SMD_CHANNELS + n,
569 2 * sizeof(struct smd_half_channel));
570
571 if (shared == 0)
572 continue;
573
574 buffer = smem_get_entry(SMEM_SMD_FIFO_BASE_ID + n, &buffer_sz);
575
576 if (buffer == 0)
577 continue;
578
579 i += dump_ch(buf + i, max - i, n, shared,
580 (shared + sizeof(struct smd_half_channel)),
581 buffer_sz / 2);
582 }
583
584 return i;
585}
Eric Holmberg27134822011-12-15 16:07:50 -0700586#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700587
588static int debug_read_smem_version(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700589{
590 struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700591 uint32_t n, version, i = 0;
592
593 for (n = 0; n < 32; n++) {
594 version = shared->version[n];
595 i += scnprintf(buf + i, max - i,
596 "entry %d: smem = %d proc_comm = %d\n", n,
597 version >> 16,
598 version & 0xffff);
599 }
600
601 return i;
602}
603
604/* NNV: revist, it may not be smd version */
605static int debug_read_smd_version(char *buf, int max)
606{
607 uint32_t *smd_ver;
608 uint32_t n, version, i = 0;
609
610 smd_ver = smem_alloc(SMEM_VERSION_SMD, 32 * sizeof(uint32_t));
611
612 if (smd_ver)
613 for (n = 0; n < 32; n++) {
614 version = smd_ver[n];
615 i += scnprintf(buf + i, max - i,
616 "entry %d: %d.%d\n", n,
617 version >> 16,
618 version & 0xffff);
619 }
620
621 return i;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700622}
623
624static int debug_read_build_id(char *buf, int max)
625{
626 unsigned size;
627 void *data;
628
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700629 data = smem_get_entry(SMEM_HW_SW_BUILD_ID, &size);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700630 if (!data)
631 return 0;
632
633 if (size >= max)
634 size = max;
635 memcpy(buf, data, size);
636
637 return size;
638}
639
640static int debug_read_alloc_tbl(char *buf, int max)
641{
642 struct smd_alloc_elm *shared;
643 int n, i = 0;
644
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700645 shared = smem_find(ID_CH_ALLOC_TBL, sizeof(struct smd_alloc_elm[64]));
646
647 if (!shared)
648 return 0;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700649
650 for (n = 0; n < 64; n++) {
Brian Swetland03e00cd2009-07-01 17:58:37 -0700651 i += scnprintf(buf + i, max - i,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700652 "name=%s cid=%d ch type=%d "
653 "xfer type=%d ref_count=%d\n",
654 shared[n].name,
655 shared[n].cid,
656 SMD_CHANNEL_TYPE(shared[n].type),
657 SMD_XFER_TYPE(shared[n].type),
658 shared[n].ref_count);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700659 }
660
661 return i;
662}
663
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700664static int debug_read_intr_mask(char *buf, int max)
665{
666 uint32_t *smsm;
667 int m, n, i = 0;
668
669 smsm = smem_alloc(SMEM_SMSM_CPU_INTR_MASK,
670 SMSM_NUM_ENTRIES * SMSM_NUM_HOSTS * sizeof(uint32_t));
671
672 if (smsm)
673 for (m = 0; m < SMSM_NUM_ENTRIES; m++) {
674 i += scnprintf(buf + i, max - i, "entry %d:", m);
675 for (n = 0; n < SMSM_NUM_HOSTS; n++)
676 i += scnprintf(buf + i, max - i,
677 " host %d: 0x%08x",
678 n, smsm[m * SMSM_NUM_HOSTS + n]);
679 i += scnprintf(buf + i, max - i, "\n");
680 }
681
682 return i;
683}
684
685static int debug_read_intr_mux(char *buf, int max)
686{
687 uint32_t *smsm;
688 int n, i = 0;
689
690 smsm = smem_alloc(SMEM_SMD_SMSM_INTR_MUX,
691 SMSM_NUM_INTR_MUX * sizeof(uint32_t));
692
693 if (smsm)
694 for (n = 0; n < SMSM_NUM_INTR_MUX; n++)
695 i += scnprintf(buf + i, max - i, "entry %d: %d\n",
696 n, smsm[n]);
697
698 return i;
699}
700
Brian Swetland03e00cd2009-07-01 17:58:37 -0700701#define DEBUG_BUFMAX 4096
702static char debug_buffer[DEBUG_BUFMAX];
703
704static ssize_t debug_read(struct file *file, char __user *buf,
705 size_t count, loff_t *ppos)
706{
707 int (*fill)(char *buf, int max) = file->private_data;
Eric Holmbergf9a75f52011-12-28 19:04:18 -0700708 int bsize;
709
710 if (*ppos != 0)
711 return 0;
712
713 bsize = fill(debug_buffer, DEBUG_BUFMAX);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700714 return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize);
715}
716
717static int debug_open(struct inode *inode, struct file *file)
718{
719 file->private_data = inode->i_private;
720 return 0;
721}
722
723static const struct file_operations debug_ops = {
724 .read = debug_read,
725 .open = debug_open,
726};
727
728static void debug_create(const char *name, mode_t mode,
729 struct dentry *dent,
730 int (*fill)(char *buf, int max))
731{
732 debugfs_create_file(name, mode, dent, fill, &debug_ops);
733}
734
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700735static int __init smd_debugfs_init(void)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700736{
737 struct dentry *dent;
738
739 dent = debugfs_create_dir("smd", 0);
740 if (IS_ERR(dent))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700741 return PTR_ERR(dent);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700742
743 debug_create("ch", 0444, dent, debug_read_ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700744 debug_create("diag", 0444, dent, debug_read_diag_msg);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700745 debug_create("mem", 0444, dent, debug_read_mem);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700746 debug_create("version", 0444, dent, debug_read_smd_version);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700747 debug_create("tbl", 0444, dent, debug_read_alloc_tbl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700748 debug_create("modem_err", 0444, dent, debug_modem_err);
749 debug_create("modem_err_f3", 0444, dent, debug_modem_err_f3);
750 debug_create("print_diag", 0444, dent, debug_diag);
751 debug_create("print_f3", 0444, dent, debug_f3);
Eric Holmberg7ad623a2012-03-01 14:41:10 -0700752 debug_create("int_stats", 0444, dent, debug_int_stats);
753 debug_create("int_stats_reset", 0444, dent, debug_int_stats_reset);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700754
755 /* NNV: this is google only stuff */
Brian Swetland03e00cd2009-07-01 17:58:37 -0700756 debug_create("build", 0444, dent, debug_read_build_id);
Daniel Walker869a2a02010-04-23 11:04:14 -0700757
758 return 0;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700759}
760
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700761static int __init smsm_debugfs_init(void)
762{
763 struct dentry *dent;
764
765 dent = debugfs_create_dir("smsm", 0);
766 if (IS_ERR(dent))
767 return PTR_ERR(dent);
768
769 debug_create("state", 0444, dent, debug_read_smsm_state);
770 debug_create("intr_mask", 0444, dent, debug_read_intr_mask);
771 debug_create("intr_mux", 0444, dent, debug_read_intr_mux);
772 debug_create("version", 0444, dent, debug_read_smem_version);
773 debug_create("smsm_test", 0444, dent, debug_test_smsm);
774
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700775 init_completion(&smsm_cb_completion);
776
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700777 return 0;
778}
779
Brian Swetland03e00cd2009-07-01 17:58:37 -0700780late_initcall(smd_debugfs_init);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700781late_initcall(smsm_debugfs_init);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700782#endif
783
784
785#define MAX_NUM_SLEEP_CLIENTS 64
786#define MAX_SLEEP_NAME_LEN 8
787
788#define NUM_GPIO_INT_REGISTERS 6
789#define GPIO_SMEM_NUM_GROUPS 2
790#define GPIO_SMEM_MAX_PC_INTERRUPTS 8
791
792struct tramp_gpio_save {
793 unsigned int enable;
794 unsigned int detect;
795 unsigned int polarity;
796};
797
798struct tramp_gpio_smem {
799 uint16_t num_fired[GPIO_SMEM_NUM_GROUPS];
800 uint16_t fired[GPIO_SMEM_NUM_GROUPS][GPIO_SMEM_MAX_PC_INTERRUPTS];
801 uint32_t enabled[NUM_GPIO_INT_REGISTERS];
802 uint32_t detection[NUM_GPIO_INT_REGISTERS];
803 uint32_t polarity[NUM_GPIO_INT_REGISTERS];
804};
805
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700806/*
807 * Print debug information on shared memory sleep variables
808 */
809void smsm_print_sleep_info(uint32_t sleep_delay, uint32_t sleep_limit,
810 uint32_t irq_mask, uint32_t wakeup_reason, uint32_t pending_irqs)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700811{
812 unsigned long flags;
813 uint32_t *ptr;
814 struct tramp_gpio_smem *gpio;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700815
816 spin_lock_irqsave(&smem_lock, flags);
817
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700818 pr_info("SMEM_SMSM_SLEEP_DELAY: %x\n", sleep_delay);
819 pr_info("SMEM_SMSM_LIMIT_SLEEP: %x\n", sleep_limit);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700820
821 ptr = smem_alloc(SMEM_SLEEP_POWER_COLLAPSE_DISABLED, sizeof(*ptr));
822 if (ptr)
823 pr_info("SMEM_SLEEP_POWER_COLLAPSE_DISABLED: %x\n", *ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700824 else
825 pr_info("SMEM_SLEEP_POWER_COLLAPSE_DISABLED: missing\n");
Brian Swetland03e00cd2009-07-01 17:58:37 -0700826
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700827 pr_info("SMEM_SMSM_INT_INFO %x %x %x\n",
828 irq_mask, pending_irqs, wakeup_reason);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700829
830 gpio = smem_alloc(SMEM_GPIO_INT, sizeof(*gpio));
831 if (gpio) {
832 int i;
833 for (i = 0; i < NUM_GPIO_INT_REGISTERS; i++)
834 pr_info("SMEM_GPIO_INT: %d: e %x d %x p %x\n",
835 i, gpio->enabled[i], gpio->detection[i],
836 gpio->polarity[i]);
837
838 for (i = 0; i < GPIO_SMEM_NUM_GROUPS; i++)
839 pr_info("SMEM_GPIO_INT: %d: f %d: %d %d...\n",
840 i, gpio->num_fired[i], gpio->fired[i][0],
841 gpio->fired[i][1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700842 } else
843 pr_info("SMEM_GPIO_INT: missing\n");
844
Brian Swetland03e00cd2009-07-01 17:58:37 -0700845 spin_unlock_irqrestore(&smem_lock, flags);
846}