blob: cc82a017ba0c953f3fd8f9d88a438f9798819b21 [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,
Arun Kumar Neelakantamac7c02d2012-10-16 22:17:55 +0530106 " Subsystem | Interrupt ID | In | Out (Hardcoded) |"
Eric Holmberg7ad623a2012-03-01 14:41:10 -0700107 " 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,
Arun Kumar Neelakantamac7c02d2012-10-16 22:17:55 +0530113 "%-10s %4s | %9d | %9u | %9u | %9u |\n",
Eric Holmberg7ad623a2012-03-01 14:41:10 -0700114 smd_pid_to_subsystem(subsys), "smd",
Arun Kumar Neelakantamac7c02d2012-10-16 22:17:55 +0530115 stats->smd_interrupt_id,
Eric Holmberg7ad623a2012-03-01 14:41:10 -0700116 stats->smd_in_count,
117 stats->smd_out_hardcode_count,
118 stats->smd_out_config_count);
119
120 i += scnprintf(buf + i, max - i,
Arun Kumar Neelakantamac7c02d2012-10-16 22:17:55 +0530121 "%-10s %4s | %9d | %9u | %9u | %9u |\n",
Eric Holmberg7ad623a2012-03-01 14:41:10 -0700122 smd_pid_to_subsystem(subsys), "smsm",
Arun Kumar Neelakantamac7c02d2012-10-16 22:17:55 +0530123 stats->smsm_interrupt_id,
Eric Holmberg7ad623a2012-03-01 14:41:10 -0700124 stats->smsm_in_count,
125 stats->smsm_out_hardcode_count,
126 stats->smsm_out_config_count);
127 }
128 ++stats;
129 }
130
131 return i;
132}
133
134static int debug_int_stats_reset(char *buf, int max)
135{
136 int i = 0;
137 int subsys;
138 struct interrupt_stat *stats = interrupt_stats;
139
140 i += scnprintf(buf + i, max - i, "Resetting interrupt stats.\n");
141
142 for (subsys = 0; subsys < NUM_SMD_SUBSYSTEMS; ++subsys) {
143 stats->smd_in_count = 0;
144 stats->smd_out_hardcode_count = 0;
145 stats->smd_out_config_count = 0;
146 stats->smsm_in_count = 0;
147 stats->smsm_out_hardcode_count = 0;
148 stats->smsm_out_config_count = 0;
149 ++stats;
150 }
151
152 return i;
153}
154
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700155static int debug_diag(char *buf, int max)
156{
157 int i = 0;
158
159 i += scnprintf(buf + i, max - i,
160 "Printing to log\n");
161 smd_diag();
162
163 return i;
164}
165
166static int debug_modem_err_f3(char *buf, int max)
167{
168 char *x;
169 int size;
170 int i = 0, j = 0;
171 unsigned cols = 0;
172 char str[4*sizeof(unsigned)+1] = {0};
173
174 x = smem_get_entry(SMEM_ERR_F3_TRACE_LOG, &size);
175 if (x != 0) {
176 pr_info("smem: F3 TRACE LOG\n");
177 while (size > 0 && max - i) {
178 if (size >= sizeof(unsigned)) {
179 i += scnprintf(buf + i, max - i, "%08x",
180 *((unsigned *) x));
181 for (j = 0; j < sizeof(unsigned); ++j)
182 if (isprint(*(x+j)))
183 str[cols*sizeof(unsigned) + j]
184 = *(x+j);
185 else
186 str[cols*sizeof(unsigned) + j]
187 = '-';
188 x += sizeof(unsigned);
189 size -= sizeof(unsigned);
190 } else {
191 while (size-- > 0 && max - i)
192 i += scnprintf(buf + i, max - i,
193 "%02x",
194 (unsigned) *x++);
195 break;
196 }
197 if (cols == 3) {
198 cols = 0;
199 str[4*sizeof(unsigned)] = 0;
200 i += scnprintf(buf + i, max - i, " %s\n",
201 str);
202 str[0] = 0;
203 } else {
204 cols++;
205 i += scnprintf(buf + i, max - i, " ");
206 }
207 }
208 i += scnprintf(buf + i, max - i, "\n");
209 }
210
211 return i;
212}
213
214static int debug_modem_err(char *buf, int max)
215{
216 char *x;
217 int size;
218 int i = 0;
219
220 x = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG);
221 if (x != 0) {
222 x[SZ_DIAG_ERR_MSG - 1] = 0;
223 i += scnprintf(buf + i, max - i,
224 "smem: DIAG '%s'\n", x);
225 }
226
227 x = smem_get_entry(SMEM_ERR_CRASH_LOG, &size);
228 if (x != 0) {
229 x[size - 1] = 0;
230 i += scnprintf(buf + i, max - i,
231 "smem: CRASH LOG\n'%s'\n", x);
232 }
233 i += scnprintf(buf + i, max - i, "\n");
234
235 return i;
236}
237
238static int debug_read_diag_msg(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700239{
240 char *msg;
241 int i = 0;
242
243 msg = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG);
244
Brian Swetland03e00cd2009-07-01 17:58:37 -0700245 if (msg) {
246 msg[SZ_DIAG_ERR_MSG - 1] = 0;
247 i += scnprintf(buf + i, max - i, "diag: '%s'\n", msg);
248 }
249 return i;
250}
251
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700252static int dump_ch(char *buf, int max, int n,
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600253 void *half_ch_s,
254 void *half_ch_r,
255 struct smd_half_channel_access *half_ch_funcs,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700256 unsigned size)
257{
Brian Swetland03e00cd2009-07-01 17:58:37 -0700258 return scnprintf(
259 buf, max,
260 "ch%02d:"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700261 " %8s(%04d/%04d) %c%c%c%c%c%c%c%c <->"
262 " %8s(%04d/%04d) %c%c%c%c%c%c%c%c : %5x\n", n,
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600263 chstate(half_ch_funcs->get_state(half_ch_s)),
264 half_ch_funcs->get_tail(half_ch_s),
265 half_ch_funcs->get_head(half_ch_s),
266 half_ch_funcs->get_fDSR(half_ch_s) ? 'D' : 'd',
267 half_ch_funcs->get_fCTS(half_ch_s) ? 'C' : 'c',
268 half_ch_funcs->get_fCD(half_ch_s) ? 'C' : 'c',
269 half_ch_funcs->get_fRI(half_ch_s) ? 'I' : 'i',
270 half_ch_funcs->get_fHEAD(half_ch_s) ? 'W' : 'w',
271 half_ch_funcs->get_fTAIL(half_ch_s) ? 'R' : 'r',
272 half_ch_funcs->get_fSTATE(half_ch_s) ? 'S' : 's',
273 half_ch_funcs->get_fBLOCKREADINTR(half_ch_s) ? 'B' : 'b',
274 chstate(half_ch_funcs->get_state(half_ch_r)),
275 half_ch_funcs->get_tail(half_ch_r),
276 half_ch_funcs->get_head(half_ch_r),
277 half_ch_funcs->get_fDSR(half_ch_r) ? 'D' : 'd',
278 half_ch_funcs->get_fCTS(half_ch_r) ? 'C' : 'c',
279 half_ch_funcs->get_fCD(half_ch_r) ? 'C' : 'c',
280 half_ch_funcs->get_fRI(half_ch_r) ? 'I' : 'i',
281 half_ch_funcs->get_fHEAD(half_ch_r) ? 'W' : 'w',
282 half_ch_funcs->get_fTAIL(half_ch_r) ? 'R' : 'r',
283 half_ch_funcs->get_fSTATE(half_ch_r) ? 'S' : 's',
284 half_ch_funcs->get_fBLOCKREADINTR(half_ch_r) ? 'B' : 'b',
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700285 size
Brian Swetland03e00cd2009-07-01 17:58:37 -0700286 );
287}
288
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700289static int debug_read_smsm_state(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700290{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700291 uint32_t *smsm;
292 int n, i = 0;
293
294 smsm = smem_find(ID_SHARED_STATE,
295 SMSM_NUM_ENTRIES * sizeof(uint32_t));
296
297 if (smsm)
298 for (n = 0; n < SMSM_NUM_ENTRIES; n++)
299 i += scnprintf(buf + i, max - i, "entry %d: 0x%08x\n",
300 n, smsm[n]);
301
302 return i;
303}
304
305struct SMSM_CB_DATA {
306 int cb_count;
307 void *data;
308 uint32_t old_state;
309 uint32_t new_state;
310};
311static struct SMSM_CB_DATA smsm_cb_data;
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700312static struct completion smsm_cb_completion;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700313
314static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
315{
316 smsm_cb_data.cb_count++;
317 smsm_cb_data.old_state = old_state;
318 smsm_cb_data.new_state = new_state;
319 smsm_cb_data.data = data;
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700320 complete_all(&smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700321}
322
323#define UT_EQ_INT(a, b) \
324 if ((a) != (b)) { \
325 i += scnprintf(buf + i, max - i, \
326 "%s:%d " #a "(%d) != " #b "(%d)\n", \
327 __func__, __LINE__, \
328 a, b); \
329 break; \
330 } \
331 do {} while (0)
332
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700333#define UT_GT_INT(a, b) \
334 if ((a) <= (b)) { \
335 i += scnprintf(buf + i, max - i, \
336 "%s:%d " #a "(%d) > " #b "(%d)\n", \
337 __func__, __LINE__, \
338 a, b); \
339 break; \
340 } \
341 do {} while (0)
342
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700343#define SMSM_CB_TEST_INIT() \
344 do { \
345 smsm_cb_data.cb_count = 0; \
346 smsm_cb_data.old_state = 0; \
347 smsm_cb_data.new_state = 0; \
348 smsm_cb_data.data = 0; \
349 } while (0)
350
351
352static int debug_test_smsm(char *buf, int max)
353{
Brian Swetland03e00cd2009-07-01 17:58:37 -0700354 int i = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700355 int test_num = 0;
356 int ret;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700357
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700358 /* Test case 1 - Register new callback for notification */
359 do {
360 test_num++;
361 SMSM_CB_TEST_INIT();
362 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_SMDINIT,
363 smsm_state_cb, (void *)0x1234);
364 UT_EQ_INT(ret, 0);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700365
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700366 /* de-assert SMSM_SMD_INIT to trigger state update */
367 UT_EQ_INT(smsm_cb_data.cb_count, 0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700368 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700369 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700370 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
371 msecs_to_jiffies(20)), 0);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700372
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700373 UT_EQ_INT(smsm_cb_data.cb_count, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700374 UT_EQ_INT(smsm_cb_data.old_state & SMSM_SMDINIT, SMSM_SMDINIT);
375 UT_EQ_INT(smsm_cb_data.new_state & SMSM_SMDINIT, 0x0);
376 UT_EQ_INT((int)smsm_cb_data.data, 0x1234);
377
378 /* re-assert SMSM_SMD_INIT to trigger state update */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700379 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700380 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700381 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
382 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700383 UT_EQ_INT(smsm_cb_data.cb_count, 2);
384 UT_EQ_INT(smsm_cb_data.old_state & SMSM_SMDINIT, 0x0);
385 UT_EQ_INT(smsm_cb_data.new_state & SMSM_SMDINIT, SMSM_SMDINIT);
386
387 /* deregister callback */
388 ret = smsm_state_cb_deregister(SMSM_APPS_STATE, SMSM_SMDINIT,
389 smsm_state_cb, (void *)0x1234);
390 UT_EQ_INT(ret, 2);
391
392 /* make sure state change doesn't cause any more callbacks */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700393 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700394 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
395 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700396 UT_EQ_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
397 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700398 UT_EQ_INT(smsm_cb_data.cb_count, 2);
399
400 i += scnprintf(buf + i, max - i, "Test %d - PASS\n", test_num);
401 } while (0);
402
403 /* Test case 2 - Update already registered callback */
404 do {
405 test_num++;
406 SMSM_CB_TEST_INIT();
407 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_SMDINIT,
408 smsm_state_cb, (void *)0x1234);
409 UT_EQ_INT(ret, 0);
410 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_INIT,
411 smsm_state_cb, (void *)0x1234);
412 UT_EQ_INT(ret, 1);
413
414 /* verify both callback bits work */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700415 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700416 UT_EQ_INT(smsm_cb_data.cb_count, 0);
417 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700418 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
419 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700420 UT_EQ_INT(smsm_cb_data.cb_count, 1);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700421 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700422 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700423 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
424 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700425 UT_EQ_INT(smsm_cb_data.cb_count, 2);
426
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700427 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700428 smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 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, 3);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700432 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700433 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700434 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
435 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700436 UT_EQ_INT(smsm_cb_data.cb_count, 4);
437
438 /* deregister 1st callback */
439 ret = smsm_state_cb_deregister(SMSM_APPS_STATE, SMSM_SMDINIT,
440 smsm_state_cb, (void *)0x1234);
441 UT_EQ_INT(ret, 1);
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_SMDINIT, 0x0);
444 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700445 UT_EQ_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
446 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700447 UT_EQ_INT(smsm_cb_data.cb_count, 4);
448
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700449 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700450 smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700451 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
452 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700453 UT_EQ_INT(smsm_cb_data.cb_count, 5);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700454 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700455 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700456 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
457 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700458 UT_EQ_INT(smsm_cb_data.cb_count, 6);
459
460 /* deregister 2nd callback */
461 ret = smsm_state_cb_deregister(SMSM_APPS_STATE, SMSM_INIT,
462 smsm_state_cb, (void *)0x1234);
463 UT_EQ_INT(ret, 2);
464
465 /* make sure state change doesn't cause any more callbacks */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700466 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700467 smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
468 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700469 UT_EQ_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
470 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700471 UT_EQ_INT(smsm_cb_data.cb_count, 6);
472
473 i += scnprintf(buf + i, max - i, "Test %d - PASS\n", test_num);
474 } while (0);
475
476 /* Test case 3 - Two callback registrations with different data */
477 do {
478 test_num++;
479 SMSM_CB_TEST_INIT();
480 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_SMDINIT,
481 smsm_state_cb, (void *)0x1234);
482 UT_EQ_INT(ret, 0);
483 ret = smsm_state_cb_register(SMSM_APPS_STATE, SMSM_INIT,
484 smsm_state_cb, (void *)0x3456);
485 UT_EQ_INT(ret, 0);
486
487 /* verify both callbacks work */
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700488 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700489 UT_EQ_INT(smsm_cb_data.cb_count, 0);
490 smsm_change_state(SMSM_APPS_STATE, SMSM_SMDINIT, 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, 1);
494 UT_EQ_INT((int)smsm_cb_data.data, 0x1234);
495
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700496 INIT_COMPLETION(smsm_cb_completion);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700497 smsm_change_state(SMSM_APPS_STATE, SMSM_INIT, 0x0);
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700498 UT_GT_INT((int)wait_for_completion_timeout(&smsm_cb_completion,
499 msecs_to_jiffies(20)), 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700500 UT_EQ_INT(smsm_cb_data.cb_count, 2);
501 UT_EQ_INT((int)smsm_cb_data.data, 0x3456);
502
503 /* cleanup and unregister
504 * degregister in reverse to verify data field is
505 * being used
506 */
507 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_SMDINIT);
508 smsm_change_state(SMSM_APPS_STATE, 0x0, SMSM_INIT);
509 ret = smsm_state_cb_deregister(SMSM_APPS_STATE,
510 SMSM_INIT,
511 smsm_state_cb, (void *)0x3456);
512 UT_EQ_INT(ret, 2);
513 ret = smsm_state_cb_deregister(SMSM_APPS_STATE,
514 SMSM_SMDINIT,
515 smsm_state_cb, (void *)0x1234);
516 UT_EQ_INT(ret, 2);
517
518 i += scnprintf(buf + i, max - i, "Test %d - PASS\n", test_num);
519 } while (0);
520
Brian Swetland03e00cd2009-07-01 17:58:37 -0700521 return i;
522}
523
524static int debug_read_mem(char *buf, int max)
525{
526 unsigned n;
527 struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
528 struct smem_heap_entry *toc = shared->heap_toc;
529 int i = 0;
530
531 i += scnprintf(buf + i, max - i,
532 "heap: init=%d free=%d remain=%d\n",
533 shared->heap_info.initialized,
534 shared->heap_info.free_offset,
535 shared->heap_info.heap_remaining);
536
537 for (n = 0; n < SMEM_NUM_ITEMS; n++) {
538 if (toc[n].allocated == 0)
539 continue;
540 i += scnprintf(buf + i, max - i,
541 "%04d: offset %08x size %08x\n",
542 n, toc[n].offset, toc[n].size);
543 }
544 return i;
545}
546
Eric Holmberg27134822011-12-15 16:07:50 -0700547#if (!defined(CONFIG_MSM_SMD_PKG4) && !defined(CONFIG_MSM_SMD_PKG3))
Brian Swetland03e00cd2009-07-01 17:58:37 -0700548static int debug_read_ch(char *buf, int max)
549{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700550 void *shared;
551 int n, i = 0;
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600552 struct smd_alloc_elm *ch_tbl;
553 unsigned ch_type;
554 unsigned shared_size;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700555
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600556 ch_tbl = smem_find(ID_CH_ALLOC_TBL, sizeof(*ch_tbl) * 64);
557 if (!ch_tbl)
558 goto fail;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700559
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700560 for (n = 0; n < SMD_CHANNELS; n++) {
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600561 ch_type = SMD_CHANNEL_TYPE(ch_tbl[n].type);
562 if (is_word_access_ch(ch_type))
563 shared_size =
564 sizeof(struct smd_half_channel_word_access);
565 else
566 shared_size = sizeof(struct smd_half_channel);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700567 shared = smem_find(ID_SMD_CHANNELS + n,
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600568 2 * shared_size + SMD_BUF_SIZE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700569
570 if (shared == 0)
571 continue;
572 i += dump_ch(buf + i, max - i, n, shared,
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600573 (shared + shared_size +
574 SMD_BUF_SIZE), get_half_ch_funcs(ch_type),
575 SMD_BUF_SIZE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700576 }
Brian Swetland03e00cd2009-07-01 17:58:37 -0700577
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600578fail:
Brian Swetland03e00cd2009-07-01 17:58:37 -0700579 return i;
580}
Eric Holmberg27134822011-12-15 16:07:50 -0700581#else
582static int debug_read_ch(char *buf, int max)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700583{
584 void *shared, *buffer;
585 unsigned buffer_sz;
586 int n, i = 0;
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600587 struct smd_alloc_elm *ch_tbl;
588 unsigned ch_type;
589 unsigned shared_size;
590
591 ch_tbl = smem_find(ID_CH_ALLOC_TBL, sizeof(*ch_tbl) * 64);
592 if (!ch_tbl)
593 goto fail;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700594
595 for (n = 0; n < SMD_CHANNELS; n++) {
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600596 ch_type = SMD_CHANNEL_TYPE(ch_tbl[n].type);
597 if (is_word_access_ch(ch_type))
598 shared_size =
599 sizeof(struct smd_half_channel_word_access);
600 else
601 shared_size = sizeof(struct smd_half_channel);
602
603 shared = smem_find(ID_SMD_CHANNELS + n, 2 * shared_size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700604
605 if (shared == 0)
606 continue;
607
608 buffer = smem_get_entry(SMEM_SMD_FIFO_BASE_ID + n, &buffer_sz);
609
610 if (buffer == 0)
611 continue;
612
613 i += dump_ch(buf + i, max - i, n, shared,
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600614 (shared + shared_size),
615 get_half_ch_funcs(ch_type),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700616 buffer_sz / 2);
617 }
618
Jeff Hugo918b2dc2012-03-21 13:42:09 -0600619fail:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700620 return i;
621}
Eric Holmberg27134822011-12-15 16:07:50 -0700622#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700623
624static int debug_read_smem_version(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700625{
626 struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700627 uint32_t n, version, i = 0;
628
629 for (n = 0; n < 32; n++) {
630 version = shared->version[n];
631 i += scnprintf(buf + i, max - i,
632 "entry %d: smem = %d proc_comm = %d\n", n,
633 version >> 16,
634 version & 0xffff);
635 }
Brian Swetland03e00cd2009-07-01 17:58:37 -0700636
637 return i;
638}
639
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700640/* NNV: revist, it may not be smd version */
641static int debug_read_smd_version(char *buf, int max)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700642{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700643 uint32_t *smd_ver;
644 uint32_t n, version, i = 0;
645
646 smd_ver = smem_alloc(SMEM_VERSION_SMD, 32 * sizeof(uint32_t));
647
648 if (smd_ver)
649 for (n = 0; n < 32; n++) {
650 version = smd_ver[n];
651 i += scnprintf(buf + i, max - i,
652 "entry %d: %d.%d\n", n,
653 version >> 16,
654 version & 0xffff);
655 }
656
657 return i;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700658}
659
660static int debug_read_build_id(char *buf, int max)
661{
662 unsigned size;
663 void *data;
664
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700665 data = smem_get_entry(SMEM_HW_SW_BUILD_ID, &size);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700666 if (!data)
667 return 0;
668
669 if (size >= max)
670 size = max;
671 memcpy(buf, data, size);
672
673 return size;
674}
675
676static int debug_read_alloc_tbl(char *buf, int max)
677{
678 struct smd_alloc_elm *shared;
679 int n, i = 0;
680
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700681 shared = smem_find(ID_CH_ALLOC_TBL, sizeof(struct smd_alloc_elm[64]));
682
683 if (!shared)
684 return 0;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700685
686 for (n = 0; n < 64; n++) {
Brian Swetland03e00cd2009-07-01 17:58:37 -0700687 i += scnprintf(buf + i, max - i,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700688 "name=%s cid=%d ch type=%d "
689 "xfer type=%d ref_count=%d\n",
690 shared[n].name,
691 shared[n].cid,
692 SMD_CHANNEL_TYPE(shared[n].type),
693 SMD_XFER_TYPE(shared[n].type),
694 shared[n].ref_count);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700695 }
696
697 return i;
698}
699
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700700static int debug_read_intr_mask(char *buf, int max)
701{
702 uint32_t *smsm;
703 int m, n, i = 0;
704
705 smsm = smem_alloc(SMEM_SMSM_CPU_INTR_MASK,
706 SMSM_NUM_ENTRIES * SMSM_NUM_HOSTS * sizeof(uint32_t));
707
708 if (smsm)
709 for (m = 0; m < SMSM_NUM_ENTRIES; m++) {
710 i += scnprintf(buf + i, max - i, "entry %d:", m);
711 for (n = 0; n < SMSM_NUM_HOSTS; n++)
712 i += scnprintf(buf + i, max - i,
713 " host %d: 0x%08x",
714 n, smsm[m * SMSM_NUM_HOSTS + n]);
715 i += scnprintf(buf + i, max - i, "\n");
716 }
717
718 return i;
719}
720
721static int debug_read_intr_mux(char *buf, int max)
722{
723 uint32_t *smsm;
724 int n, i = 0;
725
726 smsm = smem_alloc(SMEM_SMD_SMSM_INTR_MUX,
727 SMSM_NUM_INTR_MUX * sizeof(uint32_t));
728
729 if (smsm)
730 for (n = 0; n < SMSM_NUM_INTR_MUX; n++)
731 i += scnprintf(buf + i, max - i, "entry %d: %d\n",
732 n, smsm[n]);
733
734 return i;
735}
736
Brian Swetland03e00cd2009-07-01 17:58:37 -0700737#define DEBUG_BUFMAX 4096
738static char debug_buffer[DEBUG_BUFMAX];
739
740static ssize_t debug_read(struct file *file, char __user *buf,
741 size_t count, loff_t *ppos)
742{
743 int (*fill)(char *buf, int max) = file->private_data;
Eric Holmbergf9a75f52011-12-28 19:04:18 -0700744 int bsize;
745
746 if (*ppos != 0)
747 return 0;
748
749 bsize = fill(debug_buffer, DEBUG_BUFMAX);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700750 return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize);
751}
752
Brian Swetland03e00cd2009-07-01 17:58:37 -0700753static const struct file_operations debug_ops = {
754 .read = debug_read,
Stephen Boyd234e3402012-04-05 14:25:11 -0700755 .open = simple_open,
Brian Swetland03e00cd2009-07-01 17:58:37 -0700756};
757
Al Virof4ae40a2011-07-24 04:33:43 -0400758static void debug_create(const char *name, umode_t mode,
Brian Swetland03e00cd2009-07-01 17:58:37 -0700759 struct dentry *dent,
760 int (*fill)(char *buf, int max))
761{
762 debugfs_create_file(name, mode, dent, fill, &debug_ops);
763}
764
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700765static int __init smd_debugfs_init(void)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700766{
767 struct dentry *dent;
768
769 dent = debugfs_create_dir("smd", 0);
770 if (IS_ERR(dent))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700771 return PTR_ERR(dent);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700772
773 debug_create("ch", 0444, dent, debug_read_ch);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700774 debug_create("diag", 0444, dent, debug_read_diag_msg);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700775 debug_create("mem", 0444, dent, debug_read_mem);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700776 debug_create("version", 0444, dent, debug_read_smd_version);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700777 debug_create("tbl", 0444, dent, debug_read_alloc_tbl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700778 debug_create("modem_err", 0444, dent, debug_modem_err);
779 debug_create("modem_err_f3", 0444, dent, debug_modem_err_f3);
780 debug_create("print_diag", 0444, dent, debug_diag);
781 debug_create("print_f3", 0444, dent, debug_f3);
Eric Holmberg7ad623a2012-03-01 14:41:10 -0700782 debug_create("int_stats", 0444, dent, debug_int_stats);
783 debug_create("int_stats_reset", 0444, dent, debug_int_stats_reset);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700784
785 /* NNV: this is google only stuff */
Brian Swetland03e00cd2009-07-01 17:58:37 -0700786 debug_create("build", 0444, dent, debug_read_build_id);
Daniel Walker869a2a02010-04-23 11:04:14 -0700787
788 return 0;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700789}
790
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700791static int __init smsm_debugfs_init(void)
792{
793 struct dentry *dent;
794
795 dent = debugfs_create_dir("smsm", 0);
796 if (IS_ERR(dent))
797 return PTR_ERR(dent);
798
799 debug_create("state", 0444, dent, debug_read_smsm_state);
800 debug_create("intr_mask", 0444, dent, debug_read_intr_mask);
801 debug_create("intr_mux", 0444, dent, debug_read_intr_mux);
802 debug_create("version", 0444, dent, debug_read_smem_version);
803 debug_create("smsm_test", 0444, dent, debug_test_smsm);
804
Eric Holmbergc7e8daf2011-12-28 11:49:21 -0700805 init_completion(&smsm_cb_completion);
806
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700807 return 0;
808}
809
Brian Swetland03e00cd2009-07-01 17:58:37 -0700810late_initcall(smd_debugfs_init);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700811late_initcall(smsm_debugfs_init);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700812#endif
813
814
815#define MAX_NUM_SLEEP_CLIENTS 64
816#define MAX_SLEEP_NAME_LEN 8
817
818#define NUM_GPIO_INT_REGISTERS 6
819#define GPIO_SMEM_NUM_GROUPS 2
820#define GPIO_SMEM_MAX_PC_INTERRUPTS 8
821
822struct tramp_gpio_save {
823 unsigned int enable;
824 unsigned int detect;
825 unsigned int polarity;
826};
827
828struct tramp_gpio_smem {
829 uint16_t num_fired[GPIO_SMEM_NUM_GROUPS];
830 uint16_t fired[GPIO_SMEM_NUM_GROUPS][GPIO_SMEM_MAX_PC_INTERRUPTS];
831 uint32_t enabled[NUM_GPIO_INT_REGISTERS];
832 uint32_t detection[NUM_GPIO_INT_REGISTERS];
833 uint32_t polarity[NUM_GPIO_INT_REGISTERS];
834};
835
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700836/*
837 * Print debug information on shared memory sleep variables
838 */
839void smsm_print_sleep_info(uint32_t sleep_delay, uint32_t sleep_limit,
840 uint32_t irq_mask, uint32_t wakeup_reason, uint32_t pending_irqs)
Brian Swetland03e00cd2009-07-01 17:58:37 -0700841{
842 unsigned long flags;
843 uint32_t *ptr;
844 struct tramp_gpio_smem *gpio;
Brian Swetland03e00cd2009-07-01 17:58:37 -0700845
846 spin_lock_irqsave(&smem_lock, flags);
847
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700848 pr_info("SMEM_SMSM_SLEEP_DELAY: %x\n", sleep_delay);
849 pr_info("SMEM_SMSM_LIMIT_SLEEP: %x\n", sleep_limit);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700850
851 ptr = smem_alloc(SMEM_SLEEP_POWER_COLLAPSE_DISABLED, sizeof(*ptr));
852 if (ptr)
853 pr_info("SMEM_SLEEP_POWER_COLLAPSE_DISABLED: %x\n", *ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700854 else
855 pr_info("SMEM_SLEEP_POWER_COLLAPSE_DISABLED: missing\n");
Brian Swetland03e00cd2009-07-01 17:58:37 -0700856
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700857 pr_info("SMEM_SMSM_INT_INFO %x %x %x\n",
858 irq_mask, pending_irqs, wakeup_reason);
Brian Swetland03e00cd2009-07-01 17:58:37 -0700859
860 gpio = smem_alloc(SMEM_GPIO_INT, sizeof(*gpio));
861 if (gpio) {
862 int i;
863 for (i = 0; i < NUM_GPIO_INT_REGISTERS; i++)
864 pr_info("SMEM_GPIO_INT: %d: e %x d %x p %x\n",
865 i, gpio->enabled[i], gpio->detection[i],
866 gpio->polarity[i]);
867
868 for (i = 0; i < GPIO_SMEM_NUM_GROUPS; i++)
869 pr_info("SMEM_GPIO_INT: %d: f %d: %d %d...\n",
870 i, gpio->num_fired[i], gpio->fired[i][0],
871 gpio->fired[i][1]);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700872 } else
873 pr_info("SMEM_GPIO_INT: missing\n");
874
Brian Swetland03e00cd2009-07-01 17:58:37 -0700875 spin_unlock_irqrestore(&smem_lock, flags);
876}