blob: d64bcf2d5b916bfd6185457b70f9bef5dde34196 [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;
Brian Swetland03e00cd2009-07-01 17:58:37 -070096}
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)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700237{
238 char *msg;
239 int i = 0;
240
241 msg = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG);
242
Brian Swetland03e00cd2009-07-01 17:58:37 -0700243 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
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700250static int dump_ch(char *buf, int max, int n,
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600251 void *half_ch_s,
252 void *half_ch_r,
253 struct smd_half_channel_access *half_ch_funcs,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700254 unsigned size)
255{
Brian Swetland03e00cd2009-07-01 17:58:37 -0700256 return scnprintf(
257 buf, max,
258 "ch%02d:"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700259 " %8s(%04d/%04d) %c%c%c%c%c%c%c%c <->"
260 " %8s(%04d/%04d) %c%c%c%c%c%c%c%c : %5x\n", n,
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600261 chstate(half_ch_funcs->get_state(half_ch_s)),
262 half_ch_funcs->get_tail(half_ch_s),
263 half_ch_funcs->get_head(half_ch_s),
264 half_ch_funcs->get_fDSR(half_ch_s) ? 'D' : 'd',
265 half_ch_funcs->get_fCTS(half_ch_s) ? 'C' : 'c',
266 half_ch_funcs->get_fCD(half_ch_s) ? 'C' : 'c',
267 half_ch_funcs->get_fRI(half_ch_s) ? 'I' : 'i',
268 half_ch_funcs->get_fHEAD(half_ch_s) ? 'W' : 'w',
269 half_ch_funcs->get_fTAIL(half_ch_s) ? 'R' : 'r',
270 half_ch_funcs->get_fSTATE(half_ch_s) ? 'S' : 's',
271 half_ch_funcs->get_fBLOCKREADINTR(half_ch_s) ? 'B' : 'b',
272 chstate(half_ch_funcs->get_state(half_ch_r)),
273 half_ch_funcs->get_tail(half_ch_r),
274 half_ch_funcs->get_head(half_ch_r),
275 half_ch_funcs->get_fDSR(half_ch_r) ? 'D' : 'd',
276 half_ch_funcs->get_fCTS(half_ch_r) ? 'C' : 'c',
277 half_ch_funcs->get_fCD(half_ch_r) ? 'C' : 'c',
278 half_ch_funcs->get_fRI(half_ch_r) ? 'I' : 'i',
279 half_ch_funcs->get_fHEAD(half_ch_r) ? 'W' : 'w',
280 half_ch_funcs->get_fTAIL(half_ch_r) ? 'R' : 'r',
281 half_ch_funcs->get_fSTATE(half_ch_r) ? 'S' : 's',
282 half_ch_funcs->get_fBLOCKREADINTR(half_ch_r) ? 'B' : 'b',
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700283 size
Brian Swetland03e00cd2009-07-01 17:58:37 -0700284 );
285}
286
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700287static int debug_read_smsm_state(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700288{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700289 uint32_t *smsm;
290 int n, i = 0;
291
292 smsm = smem_find(ID_SHARED_STATE,
293 SMSM_NUM_ENTRIES * sizeof(uint32_t));
294
295 if (smsm)
296 for (n = 0; n < SMSM_NUM_ENTRIES; n++)
297 i += scnprintf(buf + i, max - i, "entry %d: 0x%08x\n",
298 n, smsm[n]);
299
300 return i;
301}
302
303struct SMSM_CB_DATA {
304 int cb_count;
305 void *data;
306 uint32_t old_state;
307 uint32_t new_state;
308};
309static struct SMSM_CB_DATA smsm_cb_data;
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700310static struct completion smsm_cb_completion;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700311
312static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
313{
314 smsm_cb_data.cb_count++;
315 smsm_cb_data.old_state = old_state;
316 smsm_cb_data.new_state = new_state;
317 smsm_cb_data.data = data;
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700318 complete_all(&smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700319}
320
321#define UT_EQ_INT(a, b) \
322 if ((a) != (b)) { \
323 i += scnprintf(buf + i, max - i, \
324 "%s:%d " #a "(%d) != " #b "(%d)\n", \
325 __func__, __LINE__, \
326 a, b); \
327 break; \
328 } \
329 do {} while (0)
330
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700331#define UT_GT_INT(a, b) \
332 if ((a) <= (b)) { \
333 i += scnprintf(buf + i, max - i, \
334 "%s:%d " #a "(%d) > " #b "(%d)\n", \
335 __func__, __LINE__, \
336 a, b); \
337 break; \
338 } \
339 do {} while (0)
340
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700341#define SMSM_CB_TEST_INIT() \
342 do { \
343 smsm_cb_data.cb_count = 0; \
344 smsm_cb_data.old_state = 0; \
345 smsm_cb_data.new_state = 0; \
346 smsm_cb_data.data = 0; \
347 } while (0)
348
349
350static int debug_test_smsm(char *buf, int max)
351{
Brian Swetland03e00cd2009-07-01 17:58:37 -0700352 int i = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700353 int test_num = 0;
354 int ret;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700355
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700356 /* Test case 1 - Register new callback for notification */
357 do {
358 test_num++;
359 SMSM_CB_TEST_INIT();
360 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_SMDINIT,
361 smsm_state_cb, (void *)0x1234);
362 UT_EQ_INT(ret, 0);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700363
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700364 /* de-assert SMSM_SMD_INIT to trigger state update */
365 UT_EQ_INT(smsm_cb_data.cb_count, 0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700366 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700367 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700368 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
369 msecs_to_jiffies(20)), 0);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700370
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700371 UT_EQ_INT(smsm_cb_data.cb_count, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700372 UT_EQ_INT(smsm_cb_data.old_state & SMSM_SMDINIT, SMSM_SMDINIT);
373 UT_EQ_INT(smsm_cb_data.new_state & SMSM_SMDINIT, 0x0);
374 UT_EQ_INT((int)smsm_cb_data.data, 0x1234);
375
376 /* re-assert SMSM_SMD_INIT to trigger state update */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700377 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700378 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700379 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
380 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700381 UT_EQ_INT(smsm_cb_data.cb_count, 2);
382 UT_EQ_INT(smsm_cb_data.old_state & SMSM_SMDINIT, 0x0);
383 UT_EQ_INT(smsm_cb_data.new_state & SMSM_SMDINIT, SMSM_SMDINIT);
384
385 /* deregister callback */
386 ret = smsm_state_cb_deregister(SMSM_APPS_STATE, SMSM_SMDINIT,
387 smsm_state_cb, (void *)0x1234);
388 UT_EQ_INT(ret, 2);
389
390 /* make sure state change doesn't cause any more callbacks */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700391 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700392 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
393 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700394 UT_EQ_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, 2);
397
398 i += scnprintf(buf + i, max - i, "Test %d - PASS\n", test_num);
399 } while (0);
400
401 /* Test case 2 - Update already registered callback */
402 do {
403 test_num++;
404 SMSM_CB_TEST_INIT();
405 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_SMDINIT,
406 smsm_state_cb, (void *)0x1234);
407 UT_EQ_INT(ret, 0);
408 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_INIT,
409 smsm_state_cb, (void *)0x1234);
410 UT_EQ_INT(ret, 1);
411
412 /* verify both callback bits work */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700413 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700414 UT_EQ_INT(smsm_cb_data.cb_count, 0);
415 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
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, 1);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700419 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700420 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700421 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
422 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700423 UT_EQ_INT(smsm_cb_data.cb_count, 2);
424
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, SMSM_INIT, 0x0);
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, 3);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700430 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700431 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700432 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
433 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700434 UT_EQ_INT(smsm_cb_data.cb_count, 4);
435
436 /* deregister 1st callback */
437 ret = smsm_state_cb_deregister(SMSM_APPS_STATE, SMSM_SMDINIT,
438 smsm_state_cb, (void *)0x1234);
439 UT_EQ_INT(ret, 1);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700440 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700441 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
442 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700443 UT_EQ_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
444 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700445 UT_EQ_INT(smsm_cb_data.cb_count, 4);
446
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, SMSM_INIT, 0x0);
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, 5);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700452 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700453 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700454 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
455 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700456 UT_EQ_INT(smsm_cb_data.cb_count, 6);
457
458 /* deregister 2nd callback */
459 ret = smsm_state_cb_deregister(SMSM_APPS_STATE, SMSM_INIT,
460 smsm_state_cb, (void *)0x1234);
461 UT_EQ_INT(ret, 2);
462
463 /* make sure state change doesn't cause any more callbacks */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700464 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700465 smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
466 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700467 UT_EQ_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
468 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700469 UT_EQ_INT(smsm_cb_data.cb_count, 6);
470
471 i += scnprintf(buf + i, max - i, "Test %d - PASS\n", test_num);
472 } while (0);
473
474 /* Test case 3 - Two callback registrations with different data */
475 do {
476 test_num++;
477 SMSM_CB_TEST_INIT();
478 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_SMDINIT,
479 smsm_state_cb, (void *)0x1234);
480 UT_EQ_INT(ret, 0);
481 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_INIT,
482 smsm_state_cb, (void *)0x3456);
483 UT_EQ_INT(ret, 0);
484
485 /* verify both callbacks work */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700486 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700487 UT_EQ_INT(smsm_cb_data.cb_count, 0);
488 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700489 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
490 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700491 UT_EQ_INT(smsm_cb_data.cb_count, 1);
492 UT_EQ_INT((int)smsm_cb_data.data, 0x1234);
493
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700494 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700495 smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700496 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
497 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700498 UT_EQ_INT(smsm_cb_data.cb_count, 2);
499 UT_EQ_INT((int)smsm_cb_data.data, 0x3456);
500
501 /* cleanup and unregister
502 * degregister in reverse to verify data field is
503 * being used
504 */
505 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
506 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
507 ret = smsm_state_cb_deregister(SMSM_APPS_STATE,
508 SMSM_INIT,
509 smsm_state_cb, (void *)0x3456);
510 UT_EQ_INT(ret, 2);
511 ret = smsm_state_cb_deregister(SMSM_APPS_STATE,
512 SMSM_SMDINIT,
513 smsm_state_cb, (void *)0x1234);
514 UT_EQ_INT(ret, 2);
515
516 i += scnprintf(buf + i, max - i, "Test %d - PASS\n", test_num);
517 } while (0);
518
Brian Swetland03e00cd2009-07-01 17:58:37 -0700519 return i;
520}
521
522static int debug_read_mem(char *buf, int max)
523{
524 unsigned n;
525 struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
526 struct smem_heap_entry *toc = shared->heap_toc;
527 int i = 0;
528
529 i += scnprintf(buf + i, max - i,
530 "heap: init=%d free=%d remain=%d\n",
531 shared->heap_info.initialized,
532 shared->heap_info.free_offset,
533 shared->heap_info.heap_remaining);
534
535 for (n = 0; n < SMEM_NUM_ITEMS; n++) {
536 if (toc[n].allocated == 0)
537 continue;
538 i += scnprintf(buf + i, max - i,
539 "%04d: offset %08x size %08x\n",
540 n, toc[n].offset, toc[n].size);
541 }
542 return i;
543}
544
Eric Holmberg27134822011-12-15 16:07:50 -0700545#if (!defined(CONFIG_MSM_SMD_PKG4) && !defined(CONFIG_MSM_SMD_PKG3))
Brian Swetland03e00cd2009-07-01 17:58:37 -0700546static int debug_read_ch(char *buf, int max)
547{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700548 void *shared;
549 int n, i = 0;
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600550 struct smd_alloc_elm *ch_tbl;
551 unsigned ch_type;
552 unsigned shared_size;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700553
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600554 ch_tbl = smem_find(ID_CH_ALLOC_TBL, sizeof(*ch_tbl) * 64);
555 if (!ch_tbl)
556 goto fail;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700557
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700558 for (n = 0; n < SMD_CHANNELS; n++) {
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600559 ch_type = SMD_CHANNEL_TYPE(ch_tbl[n].type);
560 if (is_word_access_ch(ch_type))
561 shared_size =
562 sizeof(struct smd_half_channel_word_access);
563 else
564 shared_size = sizeof(struct smd_half_channel);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700565 shared = smem_find(ID_SMD_CHANNELS + n,
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600566 2 * shared_size + SMD_BUF_SIZE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700567
568 if (shared == 0)
569 continue;
570 i += dump_ch(buf + i, max - i, n, shared,
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600571 (shared + shared_size +
572 SMD_BUF_SIZE), get_half_ch_funcs(ch_type),
573 SMD_BUF_SIZE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700574 }
Brian Swetland03e00cd2009-07-01 17:58:37 -0700575
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600576fail:
Brian Swetland03e00cd2009-07-01 17:58:37 -0700577 return i;
578}
Eric Holmberg27134822011-12-15 16:07:50 -0700579#else
580static int debug_read_ch(char *buf, int max)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700581{
582 void *shared, *buffer;
583 unsigned buffer_sz;
584 int n, i = 0;
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600585 struct smd_alloc_elm *ch_tbl;
586 unsigned ch_type;
587 unsigned shared_size;
588
589 ch_tbl = smem_find(ID_CH_ALLOC_TBL, sizeof(*ch_tbl) * 64);
590 if (!ch_tbl)
591 goto fail;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700592
593 for (n = 0; n < SMD_CHANNELS; n++) {
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600594 ch_type = SMD_CHANNEL_TYPE(ch_tbl[n].type);
595 if (is_word_access_ch(ch_type))
596 shared_size =
597 sizeof(struct smd_half_channel_word_access);
598 else
599 shared_size = sizeof(struct smd_half_channel);
600
601 shared = smem_find(ID_SMD_CHANNELS + n, 2 * shared_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700602
603 if (shared == 0)
604 continue;
605
606 buffer = smem_get_entry(SMEM_SMD_FIFO_BASE_ID + n, &buffer_sz);
607
608 if (buffer == 0)
609 continue;
610
611 i += dump_ch(buf + i, max - i, n, shared,
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600612 (shared + shared_size),
613 get_half_ch_funcs(ch_type),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700614 buffer_sz / 2);
615 }
616
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600617fail:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700618 return i;
619}
Eric Holmberg27134822011-12-15 16:07:50 -0700620#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700621
622static int debug_read_smem_version(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700623{
624 struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700625 uint32_t n, version, i = 0;
626
627 for (n = 0; n < 32; n++) {
628 version = shared->version[n];
629 i += scnprintf(buf + i, max - i,
630 "entry %d: smem = %d proc_comm = %d\n", n,
631 version >> 16,
632 version & 0xffff);
633 }
Brian Swetland03e00cd2009-07-01 17:58:37 -0700634
635 return i;
636}
637
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700638/* NNV: revist, it may not be smd version */
639static int debug_read_smd_version(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700640{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700641 uint32_t *smd_ver;
642 uint32_t n, version, i = 0;
643
644 smd_ver = smem_alloc(SMEM_VERSION_SMD, 32 * sizeof(uint32_t));
645
646 if (smd_ver)
647 for (n = 0; n < 32; n++) {
648 version = smd_ver[n];
649 i += scnprintf(buf + i, max - i,
650 "entry %d: %d.%d\n", n,
651 version >> 16,
652 version & 0xffff);
653 }
654
655 return i;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700656}
657
658static int debug_read_build_id(char *buf, int max)
659{
660 unsigned size;
661 void *data;
662
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700663 data = smem_get_entry(SMEM_HW_SW_BUILD_ID, &size);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700664 if (!data)
665 return 0;
666
667 if (size >= max)
668 size = max;
669 memcpy(buf, data, size);
670
671 return size;
672}
673
674static int debug_read_alloc_tbl(char *buf, int max)
675{
676 struct smd_alloc_elm *shared;
677 int n, i = 0;
678
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700679 shared = smem_find(ID_CH_ALLOC_TBL, sizeof(struct smd_alloc_elm[64]));
680
681 if (!shared)
682 return 0;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700683
684 for (n = 0; n < 64; n++) {
Brian Swetland03e00cd2009-07-01 17:58:37 -0700685 i += scnprintf(buf + i, max - i,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700686 "name=%s cid=%d ch type=%d "
687 "xfer type=%d ref_count=%d\n",
688 shared[n].name,
689 shared[n].cid,
690 SMD_CHANNEL_TYPE(shared[n].type),
691 SMD_XFER_TYPE(shared[n].type),
692 shared[n].ref_count);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700693 }
694
695 return i;
696}
697
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700698static int debug_read_intr_mask(char *buf, int max)
699{
700 uint32_t *smsm;
701 int m, n, i = 0;
702
703 smsm = smem_alloc(SMEM_SMSM_CPU_INTR_MASK,
704 SMSM_NUM_ENTRIES * SMSM_NUM_HOSTS * sizeof(uint32_t));
705
706 if (smsm)
707 for (m = 0; m < SMSM_NUM_ENTRIES; m++) {
708 i += scnprintf(buf + i, max - i, "entry %d:", m);
709 for (n = 0; n < SMSM_NUM_HOSTS; n++)
710 i += scnprintf(buf + i, max - i,
711 " host %d: 0x%08x",
712 n, smsm[m * SMSM_NUM_HOSTS + n]);
713 i += scnprintf(buf + i, max - i, "\n");
714 }
715
716 return i;
717}
718
719static int debug_read_intr_mux(char *buf, int max)
720{
721 uint32_t *smsm;
722 int n, i = 0;
723
724 smsm = smem_alloc(SMEM_SMD_SMSM_INTR_MUX,
725 SMSM_NUM_INTR_MUX * sizeof(uint32_t));
726
727 if (smsm)
728 for (n = 0; n < SMSM_NUM_INTR_MUX; n++)
729 i += scnprintf(buf + i, max - i, "entry %d: %d\n",
730 n, smsm[n]);
731
732 return i;
733}
734
Brian Swetland03e00cd2009-07-01 17:58:37 -0700735#define DEBUG_BUFMAX 4096
736static char debug_buffer[DEBUG_BUFMAX];
737
738static ssize_t debug_read(struct file *file, char __user *buf,
739 size_t count, loff_t *ppos)
740{
741 int (*fill)(char *buf, int max) = file->private_data;
Eric Holmbergf9a75f52011-12-28 19:04:18 -0700742 int bsize;
743
744 if (*ppos != 0)
745 return 0;
746
747 bsize = fill(debug_buffer, DEBUG_BUFMAX);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700748 return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize);
749}
750
Brian Swetland03e00cd2009-07-01 17:58:37 -0700751static const struct file_operations debug_ops = {
752 .read = debug_read,
Stephen Boyd234e3402012-04-05 14:25:11 -0700753 .open = simple_open,
Brian Swetland03e00cd2009-07-01 17:58:37 -0700754};
755
Al Virof4ae40a2011-07-24 04:33:43 -0400756static void debug_create(const char *name, umode_t mode,
Brian Swetland03e00cd2009-07-01 17:58:37 -0700757 struct dentry *dent,
758 int (*fill)(char *buf, int max))
759{
760 debugfs_create_file(name, mode, dent, fill, &debug_ops);
761}
762
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700763static int __init smd_debugfs_init(void)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700764{
765 struct dentry *dent;
766
767 dent = debugfs_create_dir("smd", 0);
768 if (IS_ERR(dent))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700769 return PTR_ERR(dent);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700770
771 debug_create("ch", 0444, dent, debug_read_ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700772 debug_create("diag", 0444, dent, debug_read_diag_msg);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700773 debug_create("mem", 0444, dent, debug_read_mem);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700774 debug_create("version", 0444, dent, debug_read_smd_version);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700775 debug_create("tbl", 0444, dent, debug_read_alloc_tbl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700776 debug_create("modem_err", 0444, dent, debug_modem_err);
777 debug_create("modem_err_f3", 0444, dent, debug_modem_err_f3);
778 debug_create("print_diag", 0444, dent, debug_diag);
779 debug_create("print_f3", 0444, dent, debug_f3);
Eric Holmberg7ad623a2012-03-01 14:41:10 -0700780 debug_create("int_stats", 0444, dent, debug_int_stats);
781 debug_create("int_stats_reset", 0444, dent, debug_int_stats_reset);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700782
783 /* NNV: this is google only stuff */
Brian Swetland03e00cd2009-07-01 17:58:37 -0700784 debug_create("build", 0444, dent, debug_read_build_id);
Daniel Walker869a2a02010-04-23 11:04:14 -0700785
786 return 0;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700787}
788
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700789static int __init smsm_debugfs_init(void)
790{
791 struct dentry *dent;
792
793 dent = debugfs_create_dir("smsm", 0);
794 if (IS_ERR(dent))
795 return PTR_ERR(dent);
796
797 debug_create("state", 0444, dent, debug_read_smsm_state);
798 debug_create("intr_mask", 0444, dent, debug_read_intr_mask);
799 debug_create("intr_mux", 0444, dent, debug_read_intr_mux);
800 debug_create("version", 0444, dent, debug_read_smem_version);
801 debug_create("smsm_test", 0444, dent, debug_test_smsm);
802
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700803 init_completion(&smsm_cb_completion);
804
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700805 return 0;
806}
807
Brian Swetland03e00cd2009-07-01 17:58:37 -0700808late_initcall(smd_debugfs_init);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700809late_initcall(smsm_debugfs_init);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700810#endif
811
812
813#define MAX_NUM_SLEEP_CLIENTS 64
814#define MAX_SLEEP_NAME_LEN 8
815
816#define NUM_GPIO_INT_REGISTERS 6
817#define GPIO_SMEM_NUM_GROUPS 2
818#define GPIO_SMEM_MAX_PC_INTERRUPTS 8
819
820struct tramp_gpio_save {
821 unsigned int enable;
822 unsigned int detect;
823 unsigned int polarity;
824};
825
826struct tramp_gpio_smem {
827 uint16_t num_fired[GPIO_SMEM_NUM_GROUPS];
828 uint16_t fired[GPIO_SMEM_NUM_GROUPS][GPIO_SMEM_MAX_PC_INTERRUPTS];
829 uint32_t enabled[NUM_GPIO_INT_REGISTERS];
830 uint32_t detection[NUM_GPIO_INT_REGISTERS];
831 uint32_t polarity[NUM_GPIO_INT_REGISTERS];
832};
833
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700834/*
835 * Print debug information on shared memory sleep variables
836 */
837void smsm_print_sleep_info(uint32_t sleep_delay, uint32_t sleep_limit,
838 uint32_t irq_mask, uint32_t wakeup_reason, uint32_t pending_irqs)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700839{
840 unsigned long flags;
841 uint32_t *ptr;
842 struct tramp_gpio_smem *gpio;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700843
844 spin_lock_irqsave(&smem_lock, flags);
845
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700846 pr_info("SMEM_SMSM_SLEEP_DELAY: %x\n", sleep_delay);
847 pr_info("SMEM_SMSM_LIMIT_SLEEP: %x\n", sleep_limit);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700848
849 ptr = smem_alloc(SMEM_SLEEP_POWER_COLLAPSE_DISABLED, sizeof(*ptr));
850 if (ptr)
851 pr_info("SMEM_SLEEP_POWER_COLLAPSE_DISABLED: %x\n", *ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700852 else
853 pr_info("SMEM_SLEEP_POWER_COLLAPSE_DISABLED: missing\n");
Brian Swetland03e00cd2009-07-01 17:58:37 -0700854
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700855 pr_info("SMEM_SMSM_INT_INFO %x %x %x\n",
856 irq_mask, pending_irqs, wakeup_reason);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700857
858 gpio = smem_alloc(SMEM_GPIO_INT, sizeof(*gpio));
859 if (gpio) {
860 int i;
861 for (i = 0; i < NUM_GPIO_INT_REGISTERS; i++)
862 pr_info("SMEM_GPIO_INT: %d: e %x d %x p %x\n",
863 i, gpio->enabled[i], gpio->detection[i],
864 gpio->polarity[i]);
865
866 for (i = 0; i < GPIO_SMEM_NUM_GROUPS; i++)
867 pr_info("SMEM_GPIO_INT: %d: f %d: %d %d...\n",
868 i, gpio->num_fired[i], gpio->fired[i][0],
869 gpio->fired[i][1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700870 } else
871 pr_info("SMEM_GPIO_INT: missing\n");
872
Brian Swetland03e00cd2009-07-01 17:58:37 -0700873 spin_unlock_irqrestore(&smem_lock, flags);
874}